1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: image.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_canvas.hxx"
34 #include <canvas/debug.hxx>
35 #include <tools/diagnose_ex.h>
37 #include <canvas/canvastools.hxx>
38 #include <canvas/parametricpolypolygon.hxx>
40 #include <com/sun/star/rendering/RepaintResult.hpp>
41 #include <com/sun/star/rendering/XIntegerReadOnlyBitmap.hpp>
43 #include <vcl/canvastools.hxx>
44 #include <vcl/bitmapex.hxx>
45 #include <vcl/bmpacc.hxx>
47 #include <basegfx/range/b2drange.hxx>
48 #include <basegfx/point/b2dpoint.hxx>
49 #include <basegfx/matrix/b2dhommatrix.hxx>
50 #include <basegfx/polygon/b2dpolygon.hxx>
51 #include <basegfx/polygon/b2dpolypolygon.hxx>
52 #include <basegfx/polygon/b2dpolygoncutandtouch.hxx>
53 #include <basegfx/polygon/b2dpolygontriangulator.hxx>
54 #include <basegfx/polygon/b2dpolypolygontools.hxx>
55 #include <basegfx/polygon/b2dpolygontools.hxx>
56 #include <basegfx/polygon/b2dpolygonclipper.hxx>
57 #include <basegfx/tools/canvastools.hxx>
58 #include <basegfx/polygon/b2dpolypolygoncutter.hxx>
59 #include <basegfx/polygon/b2dpolygonclipper.hxx>
63 #define CANVAS_IMAGE_CXX
64 #include "image_sysprereq.h"
66 //////////////////////////////////////////////////////////////////////////////////
67 // platform-dependend includes [wrapped into their own namepsaces]
68 //////////////////////////////////////////////////////////////////////////////////
72 # pragma warning(push,1)
81 #define WIN32_LEAN_AND_MEAN
105 using namespace ::com::sun::star
;
107 namespace canvas
{ namespace
109 //////////////////////////////////////////////////////////////////////////////////
110 // TransAffineFromAffineMatrix
111 //////////////////////////////////////////////////////////////////////////////////
113 ::agg::trans_affine
transAffineFromAffineMatrix( const geometry::AffineMatrix2D
& m
)
115 return agg::trans_affine(m
.m00
,
123 //////////////////////////////////////////////////////////////////////////////////
124 // TransAffineFromB2DHomMatrix
125 //////////////////////////////////////////////////////////////////////////////////
127 ::agg::trans_affine
transAffineFromB2DHomMatrix( const ::basegfx::B2DHomMatrix
& m
)
129 return agg::trans_affine(m
.get(0,0),
137 //////////////////////////////////////////////////////////////////////////////////
139 //////////////////////////////////////////////////////////////////////////////////
160 explicit ARGB( sal_uInt32 _color
) :
176 ARGB( sal_uInt32 default_color
,
177 const ::com::sun::star::uno::Sequence
< double >& sequence
) :
180 if(sequence
.getLength() > 2)
182 Color
.r
= static_cast<sal_uInt8
>(255.0f
*sequence
[0]);
183 Color
.g
= static_cast<sal_uInt8
>(255.0f
*sequence
[1]);
184 Color
.b
= static_cast<sal_uInt8
>(255.0f
*sequence
[2]);
185 if(sequence
.getLength() > 3)
186 Color
.a
= static_cast<sal_uInt8
>(255.0f
*sequence
[3]);
190 ARGB( const ARGB
& rhs
) :
195 ARGB
&operator=( const ARGB
&rhs
)
202 //////////////////////////////////////////////////////////////////////////////////
204 //////////////////////////////////////////////////////////////////////////////////
206 /// Calc common output state from XCanvas parameters
207 void setupState( ::basegfx::B2DHomMatrix
& o_rViewTransform
,
208 ::basegfx::B2DHomMatrix
& o_rRenderTransform
,
209 ::std::auto_ptr
< ::basegfx::B2DPolyPolygon
>& o_rViewClip
,
210 ::std::auto_ptr
< ::basegfx::B2DPolyPolygon
>& o_rRenderClip
,
211 ARGB
& o_rRenderColor
,
212 const rendering::ViewState
& viewState
,
213 const rendering::RenderState
& renderState
)
215 ::basegfx::unotools::homMatrixFromAffineMatrix(o_rRenderTransform
,
216 renderState
.AffineTransform
);
217 ::basegfx::unotools::homMatrixFromAffineMatrix(o_rViewTransform
,
218 viewState
.AffineTransform
);
220 o_rRenderColor
= ARGB(0xFFFFFFFF,
221 renderState
.DeviceColor
);
223 // TODO(F3): handle compositing modes
225 if( viewState
.Clip
.is() )
227 ::basegfx::B2DPolyPolygon
aViewClip(
228 ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D( viewState
.Clip
));
230 if(aViewClip
.areControlPointsUsed())
231 aViewClip
= ::basegfx::tools::adaptiveSubdivideByAngle(aViewClip
);
233 o_rViewClip
.reset( new ::basegfx::B2DPolyPolygon( aViewClip
) );
236 if( renderState
.Clip
.is() )
238 ::basegfx::B2DPolyPolygon
aRenderClip(
239 ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D( viewState
.Clip
) );
241 if(aRenderClip
.areControlPointsUsed())
242 aRenderClip
= ::basegfx::tools::adaptiveSubdivideByAngle(aRenderClip
);
244 o_rRenderClip
.reset( new ::basegfx::B2DPolyPolygon( aRenderClip
) );
248 //////////////////////////////////////////////////////////////////////////////////
249 // clipAndTransformPolygon
250 //////////////////////////////////////////////////////////////////////////////////
252 /** Clip and transform given polygon
257 @param bIsFilledPolyPolygon
258 When true, the polygon is clipped as if it was to be rendered
259 with fill, when false, the polygon is clipped as if it was to
260 be rendered with stroking.
262 void clipAndTransformPolygon( ::basegfx::B2DPolyPolygon
& io_rClippee
,
263 bool bIsFilledPolyPolygon
,
264 const ::basegfx::B2DHomMatrix
& rViewTransform
,
265 const ::basegfx::B2DHomMatrix
& rRenderTransform
,
266 const ::basegfx::B2DPolyPolygon
* pViewClip
,
267 const ::basegfx::B2DPolyPolygon
* pRenderClip
)
269 ::basegfx::B2DPolyPolygon
aPolyPolygon(io_rClippee
);
272 // clip contour against renderclip
276 aPolyPolygon
= basegfx::tools::clipPolyPolygonOnPolyPolygon(
277 aPolyPolygon
, *pRenderClip
, true, !bIsFilledPolyPolygon
);
280 if( !aPolyPolygon
.count() )
283 // transform result into view space
284 aPolyPolygon
.transform(rRenderTransform
);
286 // clip contour against viewclip
290 aPolyPolygon
= basegfx::tools::clipPolyPolygonOnPolyPolygon(
291 aPolyPolygon
, *pViewClip
, true, !bIsFilledPolyPolygon
);
294 if(!(aPolyPolygon
.count()))
297 // transform result into device space
298 aPolyPolygon
.transform(rViewTransform
);
300 io_rClippee
= aPolyPolygon
;
303 //////////////////////////////////////////////////////////////////////////////////
305 //////////////////////////////////////////////////////////////////////////////////
307 void setupPolyPolygon( ::basegfx::B2DPolyPolygon
& io_rClippee
,
308 bool bIsFilledPolyPolygon
,
309 ARGB
& o_rRenderColor
,
310 const rendering::ViewState
& viewState
,
311 const rendering::RenderState
& renderState
)
313 ::basegfx::B2DHomMatrix aViewTransform
;
314 ::basegfx::B2DHomMatrix aRenderTransform
;
315 ::std::auto_ptr
< ::basegfx::B2DPolyPolygon
> pViewClip
;
316 ::std::auto_ptr
< ::basegfx::B2DPolyPolygon
> pRenderClip
;
318 setupState( aViewTransform
,
326 clipAndTransformPolygon( io_rClippee
,
327 bIsFilledPolyPolygon
,
334 //////////////////////////////////////////////////////////////////////////////////
336 //////////////////////////////////////////////////////////////////////////////////
338 // Raw ABGR [AABBGGRR] 32bit continous
343 sal_uInt8
* mpBitmapData
;
346 //////////////////////////////////////////////////////////////////////////////////
348 //////////////////////////////////////////////////////////////////////////////////
350 void vclBitmapEx2Raw( const ::BitmapEx
& rBmpEx
, RawABGRBitmap
& rBmpData
)
352 Bitmap
aBitmap( rBmpEx
.GetBitmap() );
354 ScopedBitmapReadAccess
pReadAccess( aBitmap
.AcquireReadAccess(),
357 const sal_Int32
nWidth( rBmpData
.mnWidth
);
358 const sal_Int32
nHeight( rBmpData
.mnHeight
);
360 ENSURE_OR_THROW( pReadAccess
.get() != NULL
,
361 "vclBitmapEx2Raw(): "
362 "Unable to acquire read acces to bitmap" );
364 if( rBmpEx
.IsTransparent())
366 if( rBmpEx
.IsAlpha() )
369 Bitmap
aAlpha( rBmpEx
.GetAlpha().GetBitmap() );
371 ScopedBitmapReadAccess
pAlphaReadAccess( aAlpha
.AcquireReadAccess(),
374 // By convention, the access buffer always has
375 // one of the following formats:
377 // BMP_FORMAT_1BIT_MSB_PAL
378 // BMP_FORMAT_4BIT_MSN_PAL
379 // BMP_FORMAT_8BIT_PAL
380 // BMP_FORMAT_16BIT_TC_LSB_MASK
381 // BMP_FORMAT_24BIT_TC_BGR
382 // BMP_FORMAT_32BIT_TC_MASK
384 // and is always BMP_FORMAT_BOTTOM_UP
387 // WinSalBitmap::AcquireBuffer() sets up the
390 ENSURE_OR_THROW( pAlphaReadAccess
.get() != NULL
,
391 "vclBitmapEx2Raw(): "
392 "Unable to acquire read acces to alpha" );
394 ENSURE_OR_THROW( pAlphaReadAccess
->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL
||
395 pAlphaReadAccess
->GetScanlineFormat() == BMP_FORMAT_8BIT_TC_MASK
,
396 "vclBitmapEx2Raw(): "
397 "Unsupported alpha scanline format" );
400 sal_uInt8
* pCurrOutput( rBmpData
.mpBitmapData
);
403 for( y
=0; y
<nHeight
; ++y
)
405 switch( pReadAccess
->GetScanlineFormat() )
407 case BMP_FORMAT_8BIT_PAL
:
409 Scanline pScan
= pReadAccess
->GetScanline( y
);
410 Scanline pAScan
= pAlphaReadAccess
->GetScanline( y
);
412 for( x
=0; x
<nWidth
; ++x
)
414 aCol
= pReadAccess
->GetPaletteColor( *pScan
++ );
416 *pCurrOutput
++ = aCol
.GetBlue();
417 *pCurrOutput
++ = aCol
.GetGreen();
418 *pCurrOutput
++ = aCol
.GetRed();
420 // out notion of alpha is
421 // different from the rest
423 *pCurrOutput
++ = 255 - (BYTE
)*pAScan
++;
428 case BMP_FORMAT_24BIT_TC_BGR
:
430 Scanline pScan
= pReadAccess
->GetScanline( y
);
431 Scanline pAScan
= pAlphaReadAccess
->GetScanline( y
);
433 for( x
=0; x
<nWidth
; ++x
)
436 *pCurrOutput
++ = *pScan
++;
437 *pCurrOutput
++ = *pScan
++;
438 *pCurrOutput
++ = *pScan
++;
440 // out notion of alpha is
441 // different from the rest
443 *pCurrOutput
++ = 255 - (BYTE
)*pAScan
++;
448 // TODO(P2): Might be advantageous
449 // to hand-formulate the following
451 case BMP_FORMAT_1BIT_MSB_PAL
:
452 // FALLTHROUGH intended
453 case BMP_FORMAT_4BIT_MSN_PAL
:
454 // FALLTHROUGH intended
455 case BMP_FORMAT_16BIT_TC_LSB_MASK
:
456 // FALLTHROUGH intended
457 case BMP_FORMAT_32BIT_TC_MASK
:
459 Scanline pAScan
= pAlphaReadAccess
->GetScanline( y
);
461 // using fallback for those
463 for( x
=0; x
<nWidth
; ++x
)
465 // yes. x and y are swapped on Get/SetPixel
466 aCol
= pReadAccess
->GetColor(y
,x
);
468 *pCurrOutput
++ = aCol
.GetBlue();
469 *pCurrOutput
++ = aCol
.GetGreen();
470 *pCurrOutput
++ = aCol
.GetRed();
472 // out notion of alpha is
473 // different from the rest
475 *pCurrOutput
++ = 255 - (BYTE
)*pAScan
++;
480 case BMP_FORMAT_1BIT_LSB_PAL
:
481 // FALLTHROUGH intended
482 case BMP_FORMAT_4BIT_LSN_PAL
:
483 // FALLTHROUGH intended
484 case BMP_FORMAT_8BIT_TC_MASK
:
485 // FALLTHROUGH intended
486 case BMP_FORMAT_24BIT_TC_RGB
:
487 // FALLTHROUGH intended
488 case BMP_FORMAT_24BIT_TC_MASK
:
489 // FALLTHROUGH intended
490 case BMP_FORMAT_16BIT_TC_MSB_MASK
:
491 // FALLTHROUGH intended
492 case BMP_FORMAT_32BIT_TC_ABGR
:
493 // FALLTHROUGH intended
494 case BMP_FORMAT_32BIT_TC_ARGB
:
495 // FALLTHROUGH intended
496 case BMP_FORMAT_32BIT_TC_BGRA
:
497 // FALLTHROUGH intended
498 case BMP_FORMAT_32BIT_TC_RGBA
:
499 // FALLTHROUGH intended
501 ENSURE_OR_THROW( false,
502 "vclBitmapEx2Raw(): "
503 "Unexpected scanline format - has "
504 "WinSalBitmap::AcquireBuffer() changed?" );
511 Bitmap
aMask( rBmpEx
.GetMask() );
513 ScopedBitmapReadAccess
pMaskReadAccess( aMask
.AcquireReadAccess(),
516 // By convention, the access buffer always has
517 // one of the following formats:
519 // BMP_FORMAT_1BIT_MSB_PAL
520 // BMP_FORMAT_4BIT_MSN_PAL
521 // BMP_FORMAT_8BIT_PAL
522 // BMP_FORMAT_16BIT_TC_LSB_MASK
523 // BMP_FORMAT_24BIT_TC_BGR
524 // BMP_FORMAT_32BIT_TC_MASK
526 // and is always BMP_FORMAT_BOTTOM_UP
529 // WinSalBitmap::AcquireBuffer() sets up the
532 ENSURE_OR_THROW( pMaskReadAccess
.get() != NULL
,
533 "vclBitmapEx2Raw(): "
534 "Unable to acquire read acces to mask" );
536 ENSURE_OR_THROW( pMaskReadAccess
->GetScanlineFormat() == BMP_FORMAT_1BIT_MSB_PAL
,
537 "vclBitmapEx2Raw(): "
538 "Unsupported mask scanline format" );
542 const int nMask( 1L );
543 const int nInitialBit(7);
544 sal_uInt32
*pBuffer
= reinterpret_cast<sal_uInt32
*>(rBmpData
.mpBitmapData
);
547 // mapping table, to get from mask index color to
548 // alpha value (which depends on the mask's palette)
549 sal_uInt8 aColorMap
[2];
551 const BitmapColor
& rCol0( pMaskReadAccess
->GetPaletteColor( 0 ) );
552 const BitmapColor
& rCol1( pMaskReadAccess
->GetPaletteColor( 1 ) );
554 // shortcut for true luminance calculation
555 // (assumes that palette is grey-level). Note the
556 // swapped the indices here, to account for the
557 // fact that VCL's notion of alpha is inverted to
558 // the rest of the world's.
559 aColorMap
[0] = rCol1
.GetRed();
560 aColorMap
[1] = rCol0
.GetRed();
562 for( y
=0; y
<nHeight
; ++y
)
564 switch( pReadAccess
->GetScanlineFormat() )
566 case BMP_FORMAT_8BIT_PAL
:
568 Scanline pScan
= pReadAccess
->GetScanline( y
);
569 Scanline pMScan
= pMaskReadAccess
->GetScanline( y
);
571 for( x
=0, nCurrBit
=nInitialBit
; x
<nWidth
; ++x
)
573 aCol
= pReadAccess
->GetPaletteColor( *pScan
++ );
576 unsigned int color
= aCol
.GetRed();
577 color
|= aCol
.GetGreen()<<8;
578 color
|= aCol
.GetBlue()<<16;
579 color
|= aColorMap
[ (pMScan
[ (x
& ~7L) >> 3L ] >> nCurrBit
) & nMask
]<<24;
581 nCurrBit
= ((nCurrBit
- 1) % 8L) & 7L;
586 case BMP_FORMAT_24BIT_TC_BGR
:
588 Scanline pScan
= pReadAccess
->GetScanline( y
);
589 Scanline pMScan
= pMaskReadAccess
->GetScanline( y
);
591 for( x
=0, nCurrBit
=nInitialBit
; x
<nWidth
; ++x
)
594 unsigned int color
= (*pScan
++)<<16;
595 color
|= (*pScan
++)<<8;
597 color
|= (aColorMap
[ (pMScan
[ (x
& ~7L) >> 3L ] >> nCurrBit
) & nMask
])<<24;
599 nCurrBit
= ((nCurrBit
- 1) % 8L) & 7L;
604 // TODO(P2): Might be advantageous
605 // to hand-formulate the following
607 case BMP_FORMAT_1BIT_MSB_PAL
:
608 // FALLTHROUGH intended
609 case BMP_FORMAT_4BIT_MSN_PAL
:
610 // FALLTHROUGH intended
611 case BMP_FORMAT_16BIT_TC_LSB_MASK
:
612 // FALLTHROUGH intended
613 case BMP_FORMAT_32BIT_TC_MASK
:
615 Scanline pMScan
= pMaskReadAccess
->GetScanline( y
);
617 // using fallback for those
619 for( x
=0, nCurrBit
=nInitialBit
; x
<nWidth
; ++x
)
621 // yes. x and y are swapped on Get/SetPixel
622 aCol
= pReadAccess
->GetColor(y
,x
);
625 unsigned int color
= aCol
.GetBlue()<<16;
626 color
|= aCol
.GetGreen()<<8;
627 color
|= aCol
.GetRed();
628 color
|= (aColorMap
[ (pMScan
[ (x
& ~7L) >> 3L ] >> nCurrBit
) & nMask
])<<24;
630 nCurrBit
= ((nCurrBit
- 1) % 8L) & 7L;
635 case BMP_FORMAT_1BIT_LSB_PAL
:
636 // FALLTHROUGH intended
637 case BMP_FORMAT_4BIT_LSN_PAL
:
638 // FALLTHROUGH intended
639 case BMP_FORMAT_8BIT_TC_MASK
:
640 // FALLTHROUGH intended
641 case BMP_FORMAT_24BIT_TC_RGB
:
642 // FALLTHROUGH intended
643 case BMP_FORMAT_24BIT_TC_MASK
:
644 // FALLTHROUGH intended
645 case BMP_FORMAT_16BIT_TC_MSB_MASK
:
646 // FALLTHROUGH intended
647 case BMP_FORMAT_32BIT_TC_ABGR
:
648 // FALLTHROUGH intended
649 case BMP_FORMAT_32BIT_TC_ARGB
:
650 // FALLTHROUGH intended
651 case BMP_FORMAT_32BIT_TC_BGRA
:
652 // FALLTHROUGH intended
653 case BMP_FORMAT_32BIT_TC_RGBA
:
654 // FALLTHROUGH intended
656 ENSURE_OR_THROW( false,
657 "vclBitmapEx2Raw(): "
658 "Unexpected scanline format - has "
659 "WinSalBitmap::AcquireBuffer() changed?" );
667 ULONG nFormat
= pReadAccess
->GetScanlineFormat();
668 BYTE
*pBuffer
= reinterpret_cast<BYTE
*>(rBmpData
.mpBitmapData
);
672 case BMP_FORMAT_24BIT_TC_BGR
:
675 sal_Int32 height
= pReadAccess
->Height();
676 for(sal_Int32 y
=0; y
<height
; ++y
)
678 BYTE
*pScanline
=pReadAccess
->GetScanline(y
);
679 sal_Int32 width
= pReadAccess
->Width();
680 for(sal_Int32 x
=0; x
<width
; ++x
)
683 BYTE
b(*pScanline
++);
684 BYTE
g(*pScanline
++);
685 BYTE
r(*pScanline
++);
694 case BMP_FORMAT_24BIT_TC_RGB
:
697 sal_Int32 height
= pReadAccess
->Height();
698 for(sal_Int32 y
=0; y
<height
; ++y
)
700 BYTE
*pScanline
=pReadAccess
->GetScanline(y
);
701 sal_Int32 width
= pReadAccess
->Width();
702 for(sal_Int32 x
=0; x
<width
; ++x
)
705 BYTE
r(*pScanline
++);
706 BYTE
g(*pScanline
++);
707 BYTE
b(*pScanline
++);
716 case BMP_FORMAT_1BIT_MSB_PAL
:
717 case BMP_FORMAT_1BIT_LSB_PAL
:
718 case BMP_FORMAT_4BIT_MSN_PAL
:
719 case BMP_FORMAT_4BIT_LSN_PAL
:
720 case BMP_FORMAT_8BIT_PAL
:
723 sal_Int32 height
= pReadAccess
->Height();
724 for(sal_Int32 y
=0; y
<height
; ++y
)
726 BYTE
*pScanline
=pReadAccess
->GetScanline(y
);
727 sal_Int32 width
= pReadAccess
->Width();
728 for(sal_Int32 x
=0; x
<width
; ++x
)
730 BitmapColor
aCol(pReadAccess
->GetPaletteColor(*pScanline
++));
732 *pBuffer
++ = aCol
.GetRed();
733 *pBuffer
++ = aCol
.GetGreen();
734 *pBuffer
++ = aCol
.GetBlue();
743 //////////////////////////////////////////////////////////////////////////////////
744 // color_generator_linear
745 //////////////////////////////////////////////////////////////////////////////////
747 template<typename T
> struct color_generator_linear
749 typedef typename
T::value_type value_type
;
751 color_generator_linear( const T
&c1
,
753 unsigned int aSteps
) : maSteps(aSteps
),
759 unsigned size() const { return maSteps
; }
760 const T
operator [] (unsigned v
) const
762 const double w
= double(v
)/maSteps
;
763 return T( static_cast<value_type
>(maColor1
.r
+(maColor2
.r
-maColor1
.r
)*w
),
764 static_cast<value_type
>(maColor1
.g
+(maColor2
.g
-maColor1
.g
)*w
),
765 static_cast<value_type
>(maColor1
.b
+(maColor2
.b
-maColor1
.b
)*w
),
766 static_cast<value_type
>(maColor1
.a
+(maColor2
.a
-maColor1
.a
)*w
));
769 unsigned int maSteps
;
774 //////////////////////////////////////////////////////////////////////////////////
775 // color_generator_axial
776 //////////////////////////////////////////////////////////////////////////////////
778 template<typename T
> struct color_generator_axial
780 typedef typename
T::value_type value_type
;
782 color_generator_axial( const T
&c1
,
784 unsigned int aSteps
) : maSteps(aSteps
),
790 unsigned size() const { return maSteps
; }
791 const T
operator [] (unsigned v
) const
793 const double aHalfSteps
= maSteps
/2.0;
794 const double w
= (v
>= aHalfSteps
) ?
795 1.0-((double(v
)-aHalfSteps
)/aHalfSteps
) :
796 (double(v
)*2.0)/maSteps
;
797 return T( static_cast<value_type
>(maColor1
.r
+(maColor2
.r
-maColor1
.r
)*w
),
798 static_cast<value_type
>(maColor1
.g
+(maColor2
.g
-maColor1
.g
)*w
),
799 static_cast<value_type
>(maColor1
.b
+(maColor2
.b
-maColor1
.b
)*w
),
800 static_cast<value_type
>(maColor1
.a
+(maColor2
.a
-maColor1
.a
)*w
));
803 unsigned int maSteps
;
808 //////////////////////////////////////////////////////////////////////////////////
809 // color_generator_adaptor
810 //////////////////////////////////////////////////////////////////////////////////
812 template<typename T
> struct color_generator_adaptor
814 color_generator_adaptor( const T
&c1
,
816 unsigned int aSteps
) : linear_generator(c1
,c2
,aSteps
),
817 axial_generator(c1
,c2
,aSteps
),
819 void set_linear( bool bLinear
) { mbLinear
=bLinear
; }
820 unsigned size() const { return mbLinear
? linear_generator
.size() : axial_generator
.size(); }
821 const T
operator [] (unsigned v
) const
824 linear_generator
.operator [] (v
) :
825 axial_generator
.operator [] (v
);
828 color_generator_linear
<T
> linear_generator
;
829 color_generator_axial
<T
> axial_generator
;
833 //////////////////////////////////////////////////////////////////////////////////
834 // gradient_polymorphic_wrapper_base
835 //////////////////////////////////////////////////////////////////////////////////
837 struct gradient_polymorphic_wrapper_base
839 virtual int calculate(int x
, int y
, int) const = 0;
842 //////////////////////////////////////////////////////////////////////////////////
843 // gradient_polymorphic_wrapper
844 //////////////////////////////////////////////////////////////////////////////////
846 template<class GradientF
> struct gradient_polymorphic_wrapper
:
847 public gradient_polymorphic_wrapper_base
849 virtual int calculate(int x
, int y
, int d
) const
851 return m_gradient
.calculate(x
, y
, d
);
853 GradientF m_gradient
;
856 //////////////////////////////////////////////////////////////////////////////////
858 //////////////////////////////////////////////////////////////////////////////////
867 inline int calculate(int x
, int y
, int d
) const
871 int clamp_x
= height
>width
? 0 : (width
-height
);
872 int clamp_y
= height
>width
? (height
-width
) : 0;
873 int value_x
= (ax
-clamp_x
)*d
/(width
-clamp_x
);
874 int value_y
= (ay
-clamp_y
)*d
/(height
-clamp_y
);
879 return value_x
> value_y
? value_x
: value_y
;
883 sal_uInt32
getBytesPerPixel( IColorBuffer::Format eFormat
)
888 OSL_ENSURE(false, "Unexpected pixel format");
889 // FALLTHROUGH intended
890 case IColorBuffer::FMT_R8G8B8
:
892 case IColorBuffer::FMT_A8R8G8B8
:
898 //////////////////////////////////////////////////////////////////////////////////
899 // Image::drawLinePolyPolygon
900 //////////////////////////////////////////////////////////////////////////////////
902 template<class pixel_format
>
903 void Image::drawLinePolyPolygonImpl( const ::basegfx::B2DPolyPolygon
& rPolyPolygon
,
905 const rendering::ViewState
& viewState
,
906 const rendering::RenderState
& renderState
)
908 ::basegfx::B2DPolyPolygon
aPolyPolygon( rPolyPolygon
);
911 setupPolyPolygon( aPolyPolygon
, false, aRenderColor
, viewState
, renderState
);
913 if( !aPolyPolygon
.count() )
916 // Class template pixel_formats_rgb24 has full knowledge about this
917 // particular pixel format in memory. The only template parameter
918 // can be order_rgb24 or order_bgr24 that determines the order of color channels.
919 //typedef agg::pixfmt_rgba32 pixel_format;
920 pixel_format
pixf(maRenderingBuffer
);
922 // There are two basic renderers with almost the same functionality:
923 // renderer_base and renderer_mclip. The first one is used most often
924 // and it performs low level clipping.
925 // This simply adds clipping to the graphics buffer, the clip rect
926 // will be initialized to the area of the framebuffer.
927 typedef agg::renderer_base
<pixel_format
> renderer_base
;
928 agg::renderer_base
<pixel_format
> renb(pixf
);
930 // To draw Anti-Aliased primitives one shoud *rasterize* them first.
931 // The primary rasterization technique in AGG is scanline based.
932 // That is, a polygon is converted into a number of horizontal
933 // scanlines and then the scanlines are being rendered one by one.
934 // To transfer information from a rasterizer to the scanline renderer
935 // there scanline containers are used. A scanline consists of a
936 // number of horizontal, non-intersecting spans. All spans must be ordered by X.
937 // --> *packed* scanline container
940 typedef agg::renderer_outline_aa
<renderer_base
> renderer_type
;
941 typedef agg::rasterizer_outline_aa
<renderer_type
> rasterizer_type
;
942 agg::line_profile_aa profile
;
943 profile
.width(fStrokeWidth
);
944 renderer_type
ren(renb
, profile
);
945 rasterizer_type
ras(ren
);
947 const agg::rgba8
fillcolor(aRenderColor
.Color
.r
,
948 aRenderColor
.Color
.g
,
949 aRenderColor
.Color
.b
,
950 aRenderColor
.Color
.a
);
951 ren
.color(fillcolor
);
953 agg::path_storage path
;
954 agg::conv_curve
<agg::path_storage
> curve(path
);
956 for(sal_uInt32 nPolygon
=0; nPolygon
<aPolyPolygon
.count(); ++nPolygon
)
958 const basegfx::B2DPolygon
aPolygon(aPolyPolygon
.getB2DPolygon(nPolygon
));
959 const sal_uInt32
nPointCount(aPolygon
.count());
963 if(aPolygon
.areControlPointsUsed())
965 // prepare edge-based loop
966 basegfx::B2DPoint
aCurrentPoint(aPolygon
.getB2DPoint(0));
967 const sal_uInt32
nEdgeCount(aPolygon
.isClosed() ? nPointCount
- 1 : nPointCount
);
970 path
.move_to(aCurrentPoint
.getX(), aCurrentPoint
.getY());
972 for(sal_uInt32
a(0); a
< nEdgeCount
; a
++)
975 const sal_uInt32
nNextIndex((a
+ 1) % nPointCount
);
976 const basegfx::B2DPoint
aNextPoint(aPolygon
.getB2DPoint(nNextIndex
));
978 // get control points
979 const basegfx::B2DPoint
aControlNext(aPolygon
.getNextControlPoint(a
));
980 const basegfx::B2DPoint
aControlPrev(aPolygon
.getPrevControlPoint(nNextIndex
));
982 // specify first cp, second cp, next vertex
984 aControlNext
.getX(), aControlNext
.getY(),
985 aControlPrev
.getX(), aControlPrev
.getY(),
986 aNextPoint
.getX(), aNextPoint
.getY());
989 aCurrentPoint
= aNextPoint
;
994 const basegfx::B2DPoint
aStartPoint(aPolygon
.getB2DPoint(0));
995 ras
.move_to_d(aStartPoint
.getX(), aStartPoint
.getY());
997 for(sal_uInt32
a(1); a
< nPointCount
; a
++)
999 const basegfx::B2DPoint
aVertexPoint(aPolygon
.getB2DPoint(a
));
1000 ras
.line_to_d(aVertexPoint
.getX(), aVertexPoint
.getY());
1003 ras
.render(aPolygon
.isClosed());
1008 ras
.add_path(curve
);
1012 //////////////////////////////////////////////////////////////////////////////////
1013 // Image::drawLinePolyPolygon
1014 //////////////////////////////////////////////////////////////////////////////////
1016 void Image::drawLinePolyPolygon( const ::basegfx::B2DPolyPolygon
& rPoly
,
1017 double fStrokeWidth
,
1018 const rendering::ViewState
& viewState
,
1019 const rendering::RenderState
& renderState
)
1021 switch(maDesc
.eFormat
)
1024 drawLinePolyPolygonImpl
<agg::pixfmt_rgb24
>(rPoly
,fStrokeWidth
,viewState
,renderState
);
1027 drawLinePolyPolygonImpl
<agg::pixfmt_rgba32
>(rPoly
,fStrokeWidth
,viewState
,renderState
);
1030 OSL_ENSURE(false, "Unexpected pixel format");
1035 //////////////////////////////////////////////////////////////////////////////////
1036 // Image::implDrawBitmap
1037 //////////////////////////////////////////////////////////////////////////////////
1039 /** internal utility function to draw one image into another one.
1040 the source image will be drawn with respect to the given
1041 transform and clip settings.
1043 ImageCachedPrimitiveSharedPtr
Image::implDrawBitmap(
1044 const Image
& rBitmap
,
1045 const rendering::ViewState
& viewState
,
1046 const rendering::RenderState
& renderState
)
1048 ::basegfx::B2DPolyPolygon
aPoly(
1049 ::basegfx::tools::createPolygonFromRect(
1050 ::basegfx::B2DRange(0.0, 0.0,
1051 rBitmap
.maDesc
.nWidth
,
1052 rBitmap
.maDesc
.nHeight
) ) );
1055 setupPolyPolygon( aPoly
, true, aFillColor
, viewState
, renderState
);
1057 if( !aPoly
.count() )
1058 return ImageCachedPrimitiveSharedPtr();
1060 ::basegfx::B2DHomMatrix aViewTransform
;
1061 ::basegfx::B2DHomMatrix aRenderTransform
;
1062 ::basegfx::B2DHomMatrix aTextureTransform
;
1064 ::basegfx::unotools::homMatrixFromAffineMatrix(aRenderTransform
,
1065 renderState
.AffineTransform
);
1066 ::basegfx::unotools::homMatrixFromAffineMatrix(aViewTransform
,
1067 viewState
.AffineTransform
);
1068 aTextureTransform
*= aRenderTransform
;
1070 // TODO(F2): Fill in texture
1071 rendering::Texture aTexture
;
1073 return fillTexturedPolyPolygon( rBitmap
,
1080 //////////////////////////////////////////////////////////////////////////////////
1081 // cachedPrimitiveFTPP [cachedPrimitive for [F]ill[T]extured[P]oly[P]olygon]
1082 //////////////////////////////////////////////////////////////////////////////////
1084 #if AGG_VERSION >= 2400
1085 template<class pixel_format_dst
,class span_gen_type
>
1087 template<class pixel_format
,class span_gen_type
>
1089 class cachedPrimitiveFTPP
: public ImageCachedPrimitive
1093 cachedPrimitiveFTPP( const ::basegfx::B2DHomMatrix
&rTransform
,
1094 const ::basegfx::B2DHomMatrix
&rViewTransform
,
1095 agg::rendering_buffer
&dst
,
1096 const agg::rendering_buffer
& src
) :
1097 aTransform(rTransform
),
1099 filter(filter_kernel
),
1100 #if AGG_VERSION >= 2400
1101 pixs(const_cast<agg::rendering_buffer
&>(src
)),
1103 sg(source
,inter
,filter
),
1108 sg(sa
,src
,inter
,filter
),
1114 ::basegfx::B2DHomMatrix
aFinalTransform(aTransform
);
1115 aFinalTransform
*= rViewTransform
;
1116 tm
= transAffineFromB2DHomMatrix(aFinalTransform
);
1120 virtual void setImage( const ::boost::shared_ptr
< class Image
>& rTargetImage
)
1122 pImage
=rTargetImage
;
1125 virtual sal_Int8
redraw( const ::com::sun::star::rendering::ViewState
& aState
) const
1127 ::basegfx::B2DHomMatrix aViewTransform
;
1128 ::basegfx::unotools::homMatrixFromAffineMatrix(aViewTransform
,aState
.AffineTransform
);
1129 ::basegfx::B2DHomMatrix
aFinalTransform(aTransform
);
1130 aFinalTransform
*= aViewTransform
;
1131 tm
= transAffineFromB2DHomMatrix(aFinalTransform
);
1134 return ::com::sun::star::rendering::RepaintResult::REDRAWN
;
1137 inline void redraw() const { agg::render_scanlines(ras
, sl
, ren
); }
1139 mutable agg::rasterizer_scanline_aa
<> ras
;
1143 typedef agg::span_interpolator_linear
<> interpolator_type
;
1144 #if AGG_VERSION >= 2400
1145 typedef agg::renderer_base
<pixel_format_dst
> renderer_base
;
1146 typedef agg::span_allocator
< typename
span_gen_type::color_type
> span_alloc_type
;
1147 typedef agg::renderer_scanline_aa
<renderer_base
, span_alloc_type
, span_gen_type
> renderer_type
;
1148 typedef typename
span_gen_type::source_type source_type
;
1149 typedef typename
span_gen_type::source_type::pixfmt_type pixel_format_src
;
1151 typedef agg::renderer_base
<pixel_format
> renderer_base
;
1152 typedef agg::renderer_scanline_aa
<renderer_base
, span_gen_type
> renderer_type
;
1155 ::basegfx::B2DHomMatrix aTransform
;
1156 interpolator_type inter
;
1157 agg::image_filter_bilinear filter_kernel
;
1158 agg::image_filter_lut filter
;
1159 #if AGG_VERSION >= 2400
1161 pixel_format_src pixs
;
1164 agg::span_allocator
< typename
span_gen_type::color_type
> sa
;
1167 #if AGG_VERSION >= 2400
1168 pixel_format_dst pixd
;
1173 mutable renderer_type ren
;
1174 mutable agg::scanline_p8 sl
;
1175 mutable agg::trans_affine tm
;
1176 ImageSharedPtr pImage
;
1179 //////////////////////////////////////////////////////////////////////////////////
1180 // Image::fillTexturedPolyPolygon
1181 //////////////////////////////////////////////////////////////////////////////////
1183 template<class pixel_format
,class span_gen_type
>
1184 ImageCachedPrimitiveSharedPtr
Image::fillTexturedPolyPolygonImpl(
1185 const Image
& rTexture
,
1186 const ::basegfx::B2DPolyPolygon
& rPolyPolygon
,
1187 const ::basegfx::B2DHomMatrix
& rOverallTransform
,
1188 const ::basegfx::B2DHomMatrix
& rViewTransform
,
1189 const rendering::Texture
& )
1191 // calculate final overall transform.
1192 ::basegfx::B2DHomMatrix
aOverallTransform(rOverallTransform
);
1193 aOverallTransform
*= rViewTransform
;
1195 // instead of always using the full-blown solution we
1196 // first check to see if this is a simple rectangular
1197 // 1-to-1 copy from source to destination image.
1198 ::basegfx::B2DTuple
aTranslate(aOverallTransform
.get(0,2),aOverallTransform
.get(1,2));
1199 ::basegfx::B2DTuple
aSize(rTexture
.maDesc
.nWidth
,rTexture
.maDesc
.nHeight
);
1200 ::basegfx::B2DRange
aRange(aTranslate
,aTranslate
+aSize
);
1201 ::basegfx::B2DPolyPolygon
aPolyPolygon(rPolyPolygon
);
1202 aPolyPolygon
.transform(aOverallTransform
);
1203 if(::basegfx::tools::isPolyPolygonEqualRectangle(aPolyPolygon
,aRange
))
1205 // yes, we can take the shortcut.
1206 // but we need to clip the destination rectangle
1207 // against the boundary of the destination image.
1208 sal_Int32
dwSrcX(0);
1209 sal_Int32
dwSrcY(0);
1210 sal_Int32
dwDstX(static_cast<sal_Int32
>(aTranslate
.getX()));
1211 sal_Int32
dwDstY(static_cast<sal_Int32
>(aTranslate
.getY()));
1212 sal_Int32
dwWidth(rTexture
.maDesc
.nWidth
);
1213 sal_Int32
dwHeight(rTexture
.maDesc
.nHeight
);
1215 // prevent fast copy if destination position is not an
1216 // integer coordinate. otherwise we would most probably
1217 // introduce visual glitches while combining this with
1218 // high-accuracy rendering stuff.
1219 if( ::basegfx::fTools::equalZero(aTranslate
.getX()-dwDstX
) &&
1220 ::basegfx::fTools::equalZero(aTranslate
.getY()-dwDstY
))
1222 // clip against destination boundary. shrink size if
1223 // necessary, modify destination position if we need to.
1224 if(dwDstX
< 0) { dwWidth
-=dwDstX
; dwSrcX
=-dwDstX
; dwDstX
=0; }
1225 if(dwDstY
< 0) { dwHeight
-=dwDstY
; dwSrcY
=-dwDstY
; dwDstY
=0; }
1226 const sal_Int32
dwRight(dwDstX
+dwWidth
);
1227 const sal_Int32
dwBottom(dwDstY
+dwHeight
);
1228 if(dwRight
> dwWidth
)
1229 dwWidth
-= dwRight
-dwWidth
;
1230 if(dwBottom
> dwHeight
)
1231 dwHeight
-= dwBottom
-dwHeight
;
1233 // calculate source buffer
1234 const Description
&srcDesc
= rTexture
.maDesc
;
1235 const sal_uInt32
dwSrcBytesPerPixel(getBytesPerPixel(srcDesc
.eFormat
));
1236 const sal_uInt32
dwSrcPitch(srcDesc
.nWidth
*dwSrcBytesPerPixel
+srcDesc
.nStride
);
1237 sal_uInt8
*pSrcBuffer
= rTexture
.maDesc
.pBuffer
+(dwSrcPitch
*dwSrcX
)+(dwSrcBytesPerPixel
*dwSrcY
);
1239 // calculate destination buffer
1240 const Description
&dstDesc
= maDesc
;
1241 const sal_uInt32
dwDstBytesPerPixel(getBytesPerPixel(dstDesc
.eFormat
));
1242 const sal_uInt32
dwDstPitch(dstDesc
.nWidth
*dwDstBytesPerPixel
+dstDesc
.nStride
);
1243 sal_uInt8
*pDstBuffer
= maDesc
.pBuffer
+(dwDstPitch
*dwDstY
)+(dwDstBytesPerPixel
*dwDstX
);
1245 // if source and destination format match, we can simply
1246 // copy whole scanlines.
1247 if(srcDesc
.eFormat
== dstDesc
.eFormat
)
1249 const sal_Size
dwNumBytesPerScanline(dwSrcBytesPerPixel
*dwWidth
);
1250 for(sal_Int32 y
=0; y
<dwHeight
; ++y
)
1252 rtl_copyMemory(pDstBuffer
,pSrcBuffer
,dwNumBytesPerScanline
);
1253 pSrcBuffer
+= dwSrcPitch
;
1254 pDstBuffer
+= dwDstPitch
;
1259 // otherwise [formats do not match], we need to copy
1260 // each pixel one by one and convert from source to destination format.
1261 if(srcDesc
.eFormat
== FMT_A8R8G8B8
&& dstDesc
.eFormat
== FMT_R8G8B8
)
1263 for(sal_Int32 y
=0; y
<dwHeight
; ++y
)
1265 sal_uInt8
*pSrc
=pSrcBuffer
;
1266 sal_uInt8
*pDst
=pDstBuffer
;
1267 for(sal_Int32 x
=0; x
<dwWidth
; ++x
)
1272 BYTE
Alpha(*pSrc
++);
1273 BYTE
OneMinusAlpha(0xFF-Alpha
);
1274 *pDst
=(((r
*Alpha
)+((*pDst
)*OneMinusAlpha
))/0xFF);
1276 *pDst
=(((g
*Alpha
)+((*pDst
)*OneMinusAlpha
))/0xFF);
1278 *pDst
=(((b
*Alpha
)+((*pDst
)*OneMinusAlpha
))/0xFF);
1281 pSrcBuffer
+= dwSrcPitch
;
1282 pDstBuffer
+= dwDstPitch
;
1285 else if(srcDesc
.eFormat
== FMT_R8G8B8
&& dstDesc
.eFormat
== FMT_A8R8G8B8
)
1287 for(sal_Int32 y
=0; y
<dwHeight
; ++y
)
1289 sal_uInt8
*pSrc
=pSrcBuffer
;
1290 sal_uInt8
*pDst
=pDstBuffer
;
1291 for(sal_Int32 x
=0; x
<dwWidth
; ++x
)
1301 pSrcBuffer
+= dwSrcPitch
;
1302 pDstBuffer
+= dwDstPitch
;
1307 return ImageCachedPrimitiveSharedPtr();
1311 typedef cachedPrimitiveFTPP
<pixel_format
,span_gen_type
> cachedPrimitive_t
;
1312 cachedPrimitive_t
*pPrimitive
= new cachedPrimitive_t( rOverallTransform
,
1315 rTexture
.maRenderingBuffer
);
1317 agg::path_storage path
;
1318 agg::conv_curve
<agg::path_storage
> curve(path
);
1320 for(sal_uInt32
nPolygon(0); nPolygon
< rPolyPolygon
.count(); nPolygon
++)
1322 const basegfx::B2DPolygon
aPolygon(rPolyPolygon
.getB2DPolygon(nPolygon
));
1323 const sal_uInt32
nPointCount(aPolygon
.count());
1327 if(aPolygon
.areControlPointsUsed())
1329 // prepare edge-based loop
1330 basegfx::B2DPoint
aCurrentPoint(aPolygon
.getB2DPoint(0));
1331 const sal_uInt32
nEdgeCount(aPolygon
.isClosed() ? nPointCount
- 1 : nPointCount
);
1334 path
.move_to(aCurrentPoint
.getX(), aCurrentPoint
.getY());
1336 for(sal_uInt32
a(0); a
< nEdgeCount
; a
++)
1338 // access next point
1339 const sal_uInt32
nNextIndex((a
+ 1) % nPointCount
);
1340 const basegfx::B2DPoint
aNextPoint(aPolygon
.getB2DPoint(nNextIndex
));
1342 // get control points
1343 const basegfx::B2DPoint
aControlNext(aPolygon
.getNextControlPoint(a
));
1344 const basegfx::B2DPoint
aControlPrev(aPolygon
.getPrevControlPoint(nNextIndex
));
1346 // specify first cp, second cp, next vertex
1348 aControlNext
.getX(), aControlNext
.getY(),
1349 aControlPrev
.getX(), aControlPrev
.getY(),
1350 aNextPoint
.getX(), aNextPoint
.getY());
1352 // prepare next step
1353 aCurrentPoint
= aNextPoint
;
1358 const basegfx::B2DPoint
aPoint(aPolygon
.getB2DPoint(0));
1359 pPrimitive
->ras
.move_to_d(aPoint
.getX(), aPoint
.getY());
1361 for(sal_uInt32
a(1); a
< nPointCount
; a
++)
1363 const basegfx::B2DPoint
aVertexPoint(aPolygon
.getB2DPoint(a
));
1364 pPrimitive
->ras
.line_to_d(aVertexPoint
.getX(), aVertexPoint
.getY());
1367 if(aPolygon
.isClosed())
1369 pPrimitive
->ras
.close_polygon();
1375 pPrimitive
->ras
.add_path(curve
);
1376 pPrimitive
->redraw();
1378 return ImageCachedPrimitiveSharedPtr(pPrimitive
);
1381 //////////////////////////////////////////////////////////////////////////////////
1382 // Image::fillTexturedPolyPolygon
1383 //////////////////////////////////////////////////////////////////////////////////
1385 ImageCachedPrimitiveSharedPtr
Image::fillTexturedPolyPolygon(
1386 const Image
& rTexture
,
1387 const ::basegfx::B2DPolyPolygon
& rPolyPolygon
,
1388 const ::basegfx::B2DHomMatrix
& rOverallTransform
,
1389 const ::basegfx::B2DHomMatrix
& rViewTransform
,
1390 const rendering::Texture
& texture
)
1392 typedef agg::wrap_mode_repeat wrap_x_type
;
1393 typedef agg::wrap_mode_repeat wrap_y_type
;
1394 typedef agg::pixfmt_rgb24 pixfmt_rgb24
;
1395 typedef agg::pixfmt_rgba32 pixfmt_rgba32
;
1396 #if AGG_VERSION >= 2400
1397 typedef agg::image_accessor_wrap
< pixfmt_rgba32
, wrap_x_type
, wrap_y_type
> img_source_type_rgba
;
1398 typedef agg::image_accessor_wrap
< pixfmt_rgb24
, wrap_x_type
, wrap_y_type
> img_source_type_rgb
;
1400 typedef agg::span_image_resample_rgba_affine
< img_source_type_rgba
> span_gen_type_rgba
;
1401 typedef agg::span_image_resample_rgb_affine
< img_source_type_rgb
> span_gen_type_rgb
;
1403 typedef agg::span_pattern_resample_rgba_affine
< pixfmt_rgba32::color_type
,
1404 pixfmt_rgba32::order_type
,
1406 wrap_y_type
> span_gen_type_rgba
;
1407 typedef agg::span_pattern_resample_rgb_affine
< pixfmt_rgb24::color_type
,
1408 pixfmt_rgb24::order_type
,
1410 wrap_y_type
> span_gen_type_rgb
;
1413 const Format nDest
= maDesc
.eFormat
;
1414 const Format nSource
= rTexture
.maDesc
.eFormat
;
1416 if(nDest
== FMT_R8G8B8
&& nSource
== FMT_R8G8B8
)
1418 return fillTexturedPolyPolygonImpl
< agg::pixfmt_rgb24
,
1419 span_gen_type_rgb
>(
1426 else if(nDest
== FMT_R8G8B8
&& nSource
== FMT_A8R8G8B8
)
1428 return fillTexturedPolyPolygonImpl
< agg::pixfmt_rgb24
,
1429 span_gen_type_rgba
>(
1436 else if(nDest
== FMT_A8R8G8B8
&& nSource
== FMT_R8G8B8
)
1438 return fillTexturedPolyPolygonImpl
< agg::pixfmt_rgba32
,
1439 span_gen_type_rgb
>(
1446 else if(nDest
== FMT_A8R8G8B8
&& nSource
== FMT_A8R8G8B8
)
1448 return fillTexturedPolyPolygonImpl
< agg::pixfmt_rgba32
,
1449 span_gen_type_rgba
>(
1458 OSL_ENSURE(false, "Unexpected pixel format");
1461 return ImageCachedPrimitiveSharedPtr();
1464 //////////////////////////////////////////////////////////////////////////////////
1465 // Image::fillGradient
1466 //////////////////////////////////////////////////////////////////////////////////
1468 template<class pixel_format
>
1469 void Image::fillGradientImpl( const ParametricPolyPolygon::Values
& rValues
,
1470 const uno::Sequence
< double >& rUnoColor1
,
1471 const uno::Sequence
< double >& rUnoColor2
,
1472 const ::basegfx::B2DPolyPolygon
& rPolyPolygon
,
1473 const ::basegfx::B2DHomMatrix
& rOverallTransform
,
1474 const rendering::Texture
& )
1476 const ARGB
aColor1(0xFFFFFFFF,
1478 const ARGB
aColor2(0xFFFFFFFF,
1481 // first of all we need to provide the framebuffer we want to render to.
1482 // the properties of the framebuffer are
1483 // 1) memory & layout [width, height, stride]
1487 // Class template pixel_formats_rgb24 has full knowledge about this
1488 // particular pixel format in memory. The only template parameter
1489 // can be order_rgb24 or order_bgr24 that determines the order of color channels.
1490 pixel_format
pixf(maRenderingBuffer
);
1492 // There are two basic renderers with almost the same functionality:
1493 // renderer_base and renderer_mclip. The first one is used most often
1494 // and it performs low level clipping.
1495 // This simply adds clipping to the graphics buffer, the clip rect
1496 // will be initialized to the area of the framebuffer.
1497 typedef agg::renderer_base
<pixel_format
> renderer_base
;
1498 renderer_base
rb(pixf
);
1500 // bounding rectangle of untransformed polypolygon
1501 const ::basegfx::B2DRange
& rBounds(::basegfx::tools::getRange(rPolyPolygon
));
1503 // the color generator produces a specific color from
1504 // some given interpolation value.
1505 // number of steps for color interpolation
1506 typedef typename
pixel_format::color_type color_type
;
1507 color_type
color1(agg::rgba8(aColor1
.Color
.r
,
1511 color_type
color2(agg::rgba8(aColor2
.Color
.r
,
1515 typedef color_generator_adaptor
<color_type
> color_generator_type
;
1516 unsigned int dwNumSteps
= static_cast<unsigned int>(rBounds
.getWidth());
1517 color_generator_type
colors(color1
,color2
,dwNumSteps
);
1518 colors
.set_linear(rValues
.meType
!= ParametricPolyPolygon::GRADIENT_AXIAL
);
1521 gradient_polymorphic_wrapper
<agg::gradient_x
> gf_x
;
1522 gradient_polymorphic_wrapper
<agg::gradient_radial
> gf_radial
;
1523 gradient_polymorphic_wrapper
<gradient_rect
> gf_rectangular
;
1524 gf_rectangular
.m_gradient
.width
= static_cast<int>(rBounds
.getWidth())<<4;
1525 gf_rectangular
.m_gradient
.height
= static_cast<int>(rBounds
.getHeight())<<4;
1526 const gradient_polymorphic_wrapper_base
*gf
[] = { &gf_x
, // GRADIENT_LINEAR
1527 &gf_x
, // GRADIENT_AXIAL
1528 &gf_radial
, // GRADIENT_ELLIPTICAL
1529 &gf_rectangular
// GRADIENT_RECTANGULAR
1532 // how do texture coordinates change when the pixel coordinate change?
1533 typedef agg::span_interpolator_linear
<> interpolator_type
;
1534 agg::trans_affine tm
;
1535 tm
*= agg::trans_affine_scaling(1.0f
/rBounds
.getWidth(),
1536 1.0f
/rBounds
.getHeight());
1537 if(rValues
.meType
== ParametricPolyPolygon::GRADIENT_ELLIPTICAL
||
1538 rValues
.meType
== ParametricPolyPolygon::GRADIENT_RECTANGULAR
)
1540 //tm *= trans_affine_scaling(mnAspectRatio,+1.0f);
1541 //const double fAspect = aBounds.getWidth()/aBounds.getHeight();
1542 //tm *= trans_affine_scaling(+0.5f,+0.5f*(1.0f/fAspect));
1543 //tm *= trans_affine_translation(+0.5f,+0.5f);
1544 tm
*= agg::trans_affine_scaling(+0.5f
,+0.5f
);
1545 tm
*= agg::trans_affine_translation(+0.5f
,+0.5f
);
1547 tm
*= transAffineFromB2DHomMatrix(rOverallTransform
);
1549 interpolator_type
inter(tm
);
1551 // spanline allocators reserve memory for the color values
1552 // filled up by the spanline generators.
1553 typedef agg::span_allocator
<color_type
> gradient_span_alloc
;
1554 gradient_span_alloc span_alloc
;
1556 // scanline generators create the actual color values for
1557 // some specific coordinate range of a scanline.
1558 typedef agg::span_gradient
<color_type
,
1560 gradient_polymorphic_wrapper_base
,
1561 color_generator_type
> gradient_span_gen
;
1562 #if AGG_VERSION >= 2400
1563 gradient_span_gen
span_gen(inter
,
1564 *gf
[rValues
.meType
],
1569 gradient_span_gen
span_gen(span_alloc
,
1571 *gf
[rValues
.meType
],
1577 // To draw Anti-Aliased primitives one shoud *rasterize* them first.
1578 // The primary rasterization technique in AGG is scanline based.
1579 // That is, a polygon is converted into a number of horizontal
1580 // scanlines and then the scanlines are being rendered one by one.
1581 // To transfer information from a rasterizer to the scanline renderer
1582 // there scanline containers are used. A scanline consists of a
1583 // number of horizontal, non-intersecting spans. All spans must be ordered by X.
1584 // --> packed scanline container
1585 agg::scanline_p8 sl
;
1587 // antialiased scanline renderer with pattern filling capability
1588 // [in contrast to solid renderers, that is]
1589 // the instance of this particular renderer combines the
1590 // renderbuffer [i.e. destination] and the spanline generator [i.e. source]
1591 #if AGG_VERSION >= 2400
1592 typedef agg::renderer_scanline_aa
<renderer_base
, gradient_span_alloc
, gradient_span_gen
> renderer_gradient
;
1593 renderer_gradient
r1(rb
, span_alloc
, span_gen
);
1595 typedef agg::renderer_scanline_aa
<renderer_base
, gradient_span_gen
> renderer_gradient
;
1596 renderer_gradient
r1(rb
, span_gen
);
1599 // instantiate the rasterizer and feed the incoming polypolygon.
1600 agg::rasterizer_scanline_aa
<> ras
;
1601 agg::path_storage path
;
1602 agg::conv_curve
<agg::path_storage
> curve(path
);
1604 for(sal_uInt32
nPolygon(0); nPolygon
< rPolyPolygon
.count(); nPolygon
++)
1606 const basegfx::B2DPolygon
aPolygon(rPolyPolygon
.getB2DPolygon(nPolygon
));
1607 const sal_uInt32
nPointCount(aPolygon
.count());
1611 if(aPolygon
.areControlPointsUsed())
1613 // prepare edge-based loop
1614 basegfx::B2DPoint
aCurrentPoint(aPolygon
.getB2DPoint(0));
1615 const sal_uInt32
nEdgeCount(aPolygon
.isClosed() ? nPointCount
- 1 : nPointCount
);
1618 path
.move_to(aCurrentPoint
.getX(), aCurrentPoint
.getY());
1620 for(sal_uInt32
a(0); a
< nEdgeCount
; a
++)
1622 // access next point
1623 const sal_uInt32
nNextIndex((a
+ 1) % nPointCount
);
1624 const basegfx::B2DPoint
aNextPoint(aPolygon
.getB2DPoint(nNextIndex
));
1626 // get control points
1627 const basegfx::B2DPoint
aControlNext(aPolygon
.getNextControlPoint(a
));
1628 const basegfx::B2DPoint
aControlPrev(aPolygon
.getPrevControlPoint(nNextIndex
));
1630 // specify first cp, second cp, next vertex
1632 aControlNext
.getX(), aControlNext
.getY(),
1633 aControlPrev
.getX(), aControlPrev
.getY(),
1634 aNextPoint
.getX(), aNextPoint
.getY());
1636 // prepare next step
1637 aCurrentPoint
= aNextPoint
;
1642 const basegfx::B2DPoint
aPoint(aPolygon
.getB2DPoint(0));
1643 ras
.move_to_d(aPoint
.getX(), aPoint
.getY());
1645 for(sal_uInt32
a(1); a
< nPointCount
; a
++)
1647 const basegfx::B2DPoint
aVertexPoint(aPolygon
.getB2DPoint(a
));
1648 ras
.line_to_d(aVertexPoint
.getX(), aVertexPoint
.getY());
1651 if(aPolygon
.isClosed())
1653 ras
.close_polygon();
1659 // everything is up and running, go...
1660 ras
.add_path(curve
);
1661 render_scanlines(ras
,sl
,r1
);
1664 //////////////////////////////////////////////////////////////////////////////////
1665 // Image::fillGradient
1666 //////////////////////////////////////////////////////////////////////////////////
1668 void Image::fillGradient( const ParametricPolyPolygon::Values
& rValues
,
1669 const uno::Sequence
< double >& rUnoColor1
,
1670 const uno::Sequence
< double >& rUnoColor2
,
1671 const ::basegfx::B2DPolyPolygon
& rPolyPolygon
,
1672 const ::basegfx::B2DHomMatrix
& rOverallTransform
,
1673 const rendering::Texture
& texture
)
1675 switch(maDesc
.eFormat
)
1678 fillGradientImpl
<agg::pixfmt_rgb24
>(rValues
,rUnoColor1
,rUnoColor2
,rPolyPolygon
,rOverallTransform
,texture
);
1681 fillGradientImpl
<agg::pixfmt_rgba32
>(rValues
,rUnoColor1
,rUnoColor2
,rPolyPolygon
,rOverallTransform
,texture
);
1684 OSL_ENSURE(false, "Unexpected pixel format");
1689 //////////////////////////////////////////////////////////////////////////////////
1690 // Image::fromVCLBitmap
1691 //////////////////////////////////////////////////////////////////////////////////
1693 bool Image::fromVCLBitmap( ::BitmapEx
& rBmpEx
)
1695 const ::Size
aBmpSize( rBmpEx
.GetSizePixel() );
1696 Image::Description desc
;
1697 desc
.eFormat
= rBmpEx
.IsTransparent() ? FMT_A8R8G8B8
: FMT_R8G8B8
;
1698 desc
.nWidth
= aBmpSize
.Width();
1699 desc
.nHeight
= aBmpSize
.Height();
1701 const sal_uInt32
nPitch(desc
.nWidth
*getBytesPerPixel(desc
.eFormat
)+desc
.nStride
);
1702 desc
.pBuffer
= new sal_uInt8
[nPitch
*desc
.nHeight
];
1704 mbBufferHasUserOwnership
= false;
1705 maRenderingBuffer
.attach(static_cast<agg::int8u
*>(desc
.pBuffer
),
1709 RawABGRBitmap aBmpData
;
1710 aBmpData
.mnWidth
= aBmpSize
.Width();
1711 aBmpData
.mnHeight
= aBmpSize
.Height();
1712 aBmpData
.mpBitmapData
= static_cast<sal_uInt8
*>(desc
.pBuffer
);
1713 vclBitmapEx2Raw(rBmpEx
,aBmpData
);
1718 //////////////////////////////////////////////////////////////////////////////////
1720 //////////////////////////////////////////////////////////////////////////////////
1722 Image::Image( const Description
& rDesc
) :
1724 maRenderingBuffer(),
1725 mbBufferHasUserOwnership( rDesc
.pBuffer
!= NULL
)
1727 #if defined(PROFILER)
1728 for(int i
=0; i
<TIMER_MAX
; ++i
)
1729 maElapsedTime
[i
]=0.0;
1732 // allocate own buffer memory, if not provided
1733 sal_uInt8
* pBuffer
= maDesc
.pBuffer
;
1734 const sal_uInt32
nWidth(maDesc
.nWidth
);
1735 const sal_uInt32
nHeight(maDesc
.nHeight
);
1736 const sal_uInt32
nStride(maDesc
.nStride
);
1737 const sal_uInt32
nPitch(nWidth
*getBytesPerPixel(maDesc
.eFormat
)
1741 pBuffer
= new sal_uInt8
[nPitch
*nHeight
];
1743 maDesc
.pBuffer
= pBuffer
;
1745 // attach graphics buffer
1746 maRenderingBuffer
.attach(
1747 static_cast<agg::int8u
*>(pBuffer
),
1753 //////////////////////////////////////////////////////////////////////////////////
1755 //////////////////////////////////////////////////////////////////////////////////
1757 Image::Image( const uno::Reference
< rendering::XBitmap
>& xBitmap
) :
1759 maRenderingBuffer(),
1760 mbBufferHasUserOwnership( false )
1762 #if defined(PROFILER)
1763 for(int i
=0; i
<TIMER_MAX
; ++i
)
1764 maElapsedTime
[i
]=0.0;
1767 // TODO(F1): Add support for floating point bitmap formats
1768 uno::Reference
<rendering::XIntegerReadOnlyBitmap
> xIntBmp(xBitmap
,
1769 uno::UNO_QUERY_THROW
);
1770 ::BitmapEx aBmpEx
= ::vcl::unotools::bitmapExFromXBitmap(xIntBmp
);
1772 fromVCLBitmap(aBmpEx
);
1774 // TODO(F2): Fallback to XIntegerBitmap interface for import
1776 "Image::Image(): Cannot retrieve bitmap data!" );
1779 //////////////////////////////////////////////////////////////////////////////////
1781 //////////////////////////////////////////////////////////////////////////////////
1785 #if defined(PROFILER)
1787 double aAccumulatedTime(0.0);
1788 for(int i
=0; i
<TIMER_MAX
; ++i
)
1789 aAccumulatedTime
+= maElapsedTime
[i
];
1791 OSL_TRACE("Image %d - %d %d %d %d %d\n",(int)(aAccumulatedTime
*1000.0),
1792 (int)(maElapsedTime
[TIMER_FILLTEXTUREDPOLYPOLYGON
]*1000.0),
1793 (int)(maElapsedTime
[TIMER_FILLB2DPOLYPOLYGON
]*1000.0),
1794 (int)(maElapsedTime
[TIMER_DRAWPOLYPOLYGON
]*1000.0),
1795 (int)(maElapsedTime
[TIMER_FILLPOLYPOLYGON
]*1000.0),
1796 (int)(maElapsedTime
[TIMER_DRAWBITMAP
]*1000.0));
1800 if( !mbBufferHasUserOwnership
)
1801 delete [] maDesc
.pBuffer
;
1804 //////////////////////////////////////////////////////////////////////////////////
1806 //////////////////////////////////////////////////////////////////////////////////
1808 template<class pixel_format
>
1809 void Image::clearImpl( sal_uInt8 a
,
1814 pixel_format
pixf(maRenderingBuffer
);
1815 agg::renderer_base
<pixel_format
> renb(pixf
);
1817 renb
.clear(agg::rgba8(r
,g
,b
,a
));
1820 //////////////////////////////////////////////////////////////////////////////////
1822 //////////////////////////////////////////////////////////////////////////////////
1824 void Image::clear( sal_uInt8 a
,
1829 switch(maDesc
.eFormat
)
1832 return clearImpl
<agg::pixfmt_rgb24
>(a
,r
,g
,b
);
1834 return clearImpl
<agg::pixfmt_rgba32
>(a
,r
,g
,b
);
1836 OSL_ENSURE(false, "Unexpected pixel format");
1841 //////////////////////////////////////////////////////////////////////////////////
1842 // Image::fillB2DPolyPolygon
1843 //////////////////////////////////////////////////////////////////////////////////
1845 void Image::fillB2DPolyPolygon(
1846 const ::basegfx::B2DPolyPolygon
& rPolyPolygon
,
1847 const rendering::ViewState
& viewState
,
1848 const rendering::RenderState
& renderState
)
1850 #if defined(PROFILER)
1851 ScopeTimer
aTimer(TIMER_FILLB2DPOLYPOLYGON
,this);
1854 switch(maDesc
.eFormat
)
1857 fillPolyPolygonImpl
<agg::pixfmt_rgb24
>(rPolyPolygon
,viewState
,renderState
);
1860 fillPolyPolygonImpl
<agg::pixfmt_rgba32
>(rPolyPolygon
,viewState
,renderState
);
1863 OSL_ENSURE(false, "Unexpected pixel format");
1868 //////////////////////////////////////////////////////////////////////////////////
1870 //////////////////////////////////////////////////////////////////////////////////
1872 sal_uInt8
* Image::lock() const
1874 return maDesc
.pBuffer
;
1877 //////////////////////////////////////////////////////////////////////////////////
1879 //////////////////////////////////////////////////////////////////////////////////
1881 void Image::unlock() const
1885 //////////////////////////////////////////////////////////////////////////////////
1887 //////////////////////////////////////////////////////////////////////////////////
1889 sal_uInt32
Image::getWidth() const
1891 return maDesc
.nWidth
;
1894 //////////////////////////////////////////////////////////////////////////////////
1896 //////////////////////////////////////////////////////////////////////////////////
1898 sal_uInt32
Image::getHeight() const
1900 return maDesc
.nHeight
;
1903 //////////////////////////////////////////////////////////////////////////////////
1905 //////////////////////////////////////////////////////////////////////////////////
1907 sal_uInt32
Image::getStride() const
1909 return maDesc
.nWidth
*getBytesPerPixel(maDesc
.eFormat
)+maDesc
.nStride
;
1912 //////////////////////////////////////////////////////////////////////////////////
1914 //////////////////////////////////////////////////////////////////////////////////
1916 IColorBuffer::Format
Image::getFormat() const
1918 return maDesc
.eFormat
;
1921 //////////////////////////////////////////////////////////////////////////////////
1923 //////////////////////////////////////////////////////////////////////////////////
1925 void Image::drawPoint( const geometry::RealPoint2D
& /*aPoint*/,
1926 const rendering::ViewState
& /*viewState*/,
1927 const rendering::RenderState
& /*renderState*/ )
1930 "Image::drawPoint(): NYI" );
1933 //////////////////////////////////////////////////////////////////////////////////
1935 //////////////////////////////////////////////////////////////////////////////////
1937 void Image::drawLine( const geometry::RealPoint2D
& aStartPoint
,
1938 const geometry::RealPoint2D
& aEndPoint
,
1939 const rendering::ViewState
& viewState
,
1940 const rendering::RenderState
& renderState
)
1942 ::basegfx::B2DPolygon aLinePoly
;
1944 ::basegfx::unotools::b2DPointFromRealPoint2D( aStartPoint
) );
1946 ::basegfx::unotools::b2DPointFromRealPoint2D( aEndPoint
) );
1948 drawLinePolyPolygon( ::basegfx::B2DPolyPolygon( aLinePoly
),
1954 //////////////////////////////////////////////////////////////////////////////////
1955 // Image::drawBezier
1956 //////////////////////////////////////////////////////////////////////////////////
1958 void Image::drawBezier( const geometry::RealBezierSegment2D
& aBezierSegment
,
1959 const geometry::RealPoint2D
& aEndPoint
,
1960 const rendering::ViewState
& viewState
,
1961 const rendering::RenderState
& renderState
)
1963 basegfx::B2DPolygon aBezierPoly
;
1965 aBezierPoly
.append(basegfx::B2DPoint(aBezierSegment
.Px
, aBezierSegment
.Py
));
1966 aBezierPoly
.appendBezierSegment(
1967 basegfx::B2DPoint(aBezierSegment
.C1x
, aBezierSegment
.C1y
),
1968 basegfx::B2DPoint(aBezierSegment
.C2x
, aBezierSegment
.C2y
),
1969 basegfx::unotools::b2DPointFromRealPoint2D(aEndPoint
));
1971 drawLinePolyPolygon( ::basegfx::B2DPolyPolygon( aBezierPoly
),
1977 //////////////////////////////////////////////////////////////////////////////////
1978 // Image::drawPolyPolygon
1979 //////////////////////////////////////////////////////////////////////////////////
1981 ImageCachedPrimitiveSharedPtr
Image::drawPolyPolygon(
1982 const uno::Reference
< rendering::XPolyPolygon2D
>& xPolyPolygon
,
1983 const rendering::ViewState
& viewState
,
1984 const rendering::RenderState
& renderState
)
1986 #if defined(PROFILER)
1987 ScopeTimer
aTimer(TIMER_DRAWPOLYPOLYGON
,this);
1990 if( !xPolyPolygon
.is() )
1991 return ImageCachedPrimitiveSharedPtr();
1993 drawLinePolyPolygon( ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D( xPolyPolygon
),
1998 // TODO(F2): Implement sensible ImageCachedPrimitive
1999 return ImageCachedPrimitiveSharedPtr();
2002 //////////////////////////////////////////////////////////////////////////////////
2003 // Image::strokePolyPolygon
2004 //////////////////////////////////////////////////////////////////////////////////
2006 ImageCachedPrimitiveSharedPtr
Image::strokePolyPolygon(
2007 const uno::Reference
< rendering::XPolyPolygon2D
>& xPolyPolygon
,
2008 const rendering::ViewState
& viewState
,
2009 const rendering::RenderState
& renderState
,
2010 const rendering::StrokeAttributes
& strokeAttributes
)
2012 if( !xPolyPolygon
.is() )
2013 return ImageCachedPrimitiveSharedPtr();
2015 drawLinePolyPolygon( ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D( xPolyPolygon
),
2016 strokeAttributes
.StrokeWidth
,
2020 // TODO(F2): Implement sensible ImageCachedPrimitive
2021 return ImageCachedPrimitiveSharedPtr();
2024 //////////////////////////////////////////////////////////////////////////////////
2025 // Image::strokeTexturedPolyPolygon
2026 //////////////////////////////////////////////////////////////////////////////////
2028 ImageCachedPrimitiveSharedPtr
Image::strokeTexturedPolyPolygon(
2029 const uno::Reference
< rendering::XPolyPolygon2D
>& /*xPolyPolygon*/,
2030 const rendering::ViewState
& /*viewState*/,
2031 const rendering::RenderState
& /*renderState*/,
2032 const uno::Sequence
< rendering::Texture
>& /*textures*/,
2033 const ::std::vector
< ::boost::shared_ptr
<Image
> >& /*textureAnnotations*/,
2034 const rendering::StrokeAttributes
& /*strokeAttributes*/ )
2037 "Image::strokeTexturedPolyPolygon(): NYI" );
2039 // TODO(F2): Implement sensible ImageCachedPrimitive
2040 return ImageCachedPrimitiveSharedPtr();
2043 //////////////////////////////////////////////////////////////////////////////////
2044 // Image::strokeTextureMappedPolyPolygon
2045 //////////////////////////////////////////////////////////////////////////////////
2047 ImageCachedPrimitiveSharedPtr
Image::strokeTextureMappedPolyPolygon(
2048 const uno::Reference
< rendering::XPolyPolygon2D
>& /*xPolyPolygon*/,
2049 const rendering::ViewState
& /*viewState*/,
2050 const rendering::RenderState
& /*renderState*/,
2051 const uno::Sequence
< rendering::Texture
>& /*textures*/,
2052 const ::std::vector
< ::boost::shared_ptr
<Image
> >& /*textureAnnotations*/,
2053 const uno::Reference
< geometry::XMapping2D
>& /*xMapping*/,
2054 const rendering::StrokeAttributes
& /*strokeAttributes*/ )
2057 "Image::strokeTextureMappedPolyPolygon(): NYI" );
2059 // TODO(F2): Implement sensible ImageCachedPrimitive
2060 return ImageCachedPrimitiveSharedPtr();
2063 //////////////////////////////////////////////////////////////////////////////////
2064 // Image::fillPolyPolygon
2065 //////////////////////////////////////////////////////////////////////////////////
2067 template<class pixel_format
>
2068 ImageCachedPrimitiveSharedPtr
Image::fillPolyPolygonImpl(
2069 const ::basegfx::B2DPolyPolygon
& rPolyPolygon
,
2070 const rendering::ViewState
& viewState
,
2071 const rendering::RenderState
& renderState
)
2073 #if defined(PROFILER)
2074 ScopeTimer
aTimer(TIMER_FILLPOLYPOLYGON
,this);
2079 ::basegfx::B2DPolyPolygon
aPolyPolygon(rPolyPolygon
);
2080 setupPolyPolygon( aPolyPolygon
, true, aFillColor
, viewState
, renderState
);
2082 if( !aPolyPolygon
.count() )
2083 return ImageCachedPrimitiveSharedPtr();
2085 pixel_format
pixf(maRenderingBuffer
);
2086 agg::renderer_base
<pixel_format
> renb(pixf
);
2088 // Scanline renderer for solid filling.
2089 agg::renderer_scanline_aa_solid
<agg::renderer_base
<pixel_format
> > ren(renb
);
2091 // Rasterizer & scanline
2092 agg::rasterizer_scanline_aa
<> ras
;
2093 agg::scanline_p8 sl
;
2095 agg::path_storage path
;
2096 agg::conv_curve
<agg::path_storage
> curve(path
);
2098 for(sal_uInt32
nPolygon(0); nPolygon
< aPolyPolygon
.count(); nPolygon
++)
2100 const basegfx::B2DPolygon
aPolygon(aPolyPolygon
.getB2DPolygon(nPolygon
));
2101 const sal_uInt32
nPointCount(aPolygon
.count());
2105 if(aPolygon
.areControlPointsUsed())
2107 // prepare edge-based loop
2108 basegfx::B2DPoint
aCurrentPoint(aPolygon
.getB2DPoint(0));
2109 const sal_uInt32
nEdgeCount(aPolygon
.isClosed() ? nPointCount
- 1 : nPointCount
);
2112 path
.move_to(aCurrentPoint
.getX(), aCurrentPoint
.getY());
2114 for(sal_uInt32
a(0); a
< nEdgeCount
; a
++)
2116 // access next point
2117 const sal_uInt32
nNextIndex((a
+ 1) % nPointCount
);
2118 const basegfx::B2DPoint
aNextPoint(aPolygon
.getB2DPoint(nNextIndex
));
2120 // get control points
2121 const basegfx::B2DPoint
aControlNext(aPolygon
.getNextControlPoint(a
));
2122 const basegfx::B2DPoint
aControlPrev(aPolygon
.getPrevControlPoint(nNextIndex
));
2124 // specify first cp, second cp, next vertex
2126 aControlNext
.getX(), aControlNext
.getY(),
2127 aControlPrev
.getX(), aControlPrev
.getY(),
2128 aNextPoint
.getX(), aNextPoint
.getY());
2130 // prepare next step
2131 aCurrentPoint
= aNextPoint
;
2136 const basegfx::B2DPoint
aPoint(aPolygon
.getB2DPoint(0));
2137 ras
.move_to_d(aPoint
.getX(), aPoint
.getY());
2139 for(sal_uInt32
a(1); a
< nPointCount
; a
++)
2141 const basegfx::B2DPoint
aVertexPoint(aPolygon
.getB2DPoint(a
));
2142 ras
.line_to_d(aVertexPoint
.getX(), aVertexPoint
.getY());
2145 if(aPolygon
.isClosed())
2147 ras
.close_polygon();
2153 ras
.add_path(curve
);
2154 agg::rgba8
fillcolor(aFillColor
.Color
.r
,aFillColor
.Color
.g
,aFillColor
.Color
.b
,aFillColor
.Color
.a
);
2155 ren
.color(fillcolor
);
2156 agg::render_scanlines(ras
, sl
, ren
);
2158 // TODO(F2): Implement sensible ImageCachedPrimitive
2159 return ImageCachedPrimitiveSharedPtr();
2162 //////////////////////////////////////////////////////////////////////////////////
2163 // Image::fillPolyPolygon
2164 //////////////////////////////////////////////////////////////////////////////////
2166 ImageCachedPrimitiveSharedPtr
Image::fillPolyPolygon(
2167 const uno::Reference
< rendering::XPolyPolygon2D
>& xPolyPolygon
,
2168 const rendering::ViewState
& viewState
,
2169 const rendering::RenderState
& renderState
)
2171 if( !xPolyPolygon
.is() )
2172 return ImageCachedPrimitiveSharedPtr();
2174 ::basegfx::B2DPolyPolygon
aPoly(
2175 ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D( xPolyPolygon
) );
2177 switch(maDesc
.eFormat
)
2180 return fillPolyPolygonImpl
<agg::pixfmt_rgb24
>(aPoly
,viewState
,renderState
);
2182 return fillPolyPolygonImpl
<agg::pixfmt_rgba32
>(aPoly
,viewState
,renderState
);
2184 OSL_ENSURE(false, "Unexpected pixel format");
2188 return ImageCachedPrimitiveSharedPtr();
2191 //////////////////////////////////////////////////////////////////////////////////
2192 // Image::fillTexturedPolyPolygon
2193 //////////////////////////////////////////////////////////////////////////////////
2195 ImageCachedPrimitiveSharedPtr
Image::fillTexturedPolyPolygon(
2196 const uno::Reference
< rendering::XPolyPolygon2D
>& xPolyPolygon
,
2197 const rendering::ViewState
& viewState
,
2198 const rendering::RenderState
& renderState
,
2199 const uno::Sequence
< rendering::Texture
>& textures
,
2200 const ::std::vector
< ::boost::shared_ptr
<Image
> >& textureAnnotations
)
2202 #if defined(PROFILER)
2203 ScopeTimer
aTimer(TIMER_FILLTEXTUREDPOLYPOLYGON
,this);
2206 if( !xPolyPolygon
.is() )
2207 return ImageCachedPrimitiveSharedPtr();
2209 ::basegfx::B2DPolyPolygon
aPoly(
2210 ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D( xPolyPolygon
) );
2213 setupPolyPolygon( aPoly
, true, aFillColor
, viewState
, renderState
);
2215 if( !aPoly
.count() )
2216 return ImageCachedPrimitiveSharedPtr();
2218 ::basegfx::B2DHomMatrix aViewTransform
;
2219 ::basegfx::B2DHomMatrix aRenderTransform
;
2220 ::basegfx::B2DHomMatrix aTextureTransform
;
2222 ::basegfx::unotools::homMatrixFromAffineMatrix(aTextureTransform
,
2223 textures
[0].AffineTransform
);
2224 ::basegfx::unotools::homMatrixFromAffineMatrix(aRenderTransform
,
2225 renderState
.AffineTransform
);
2226 ::basegfx::unotools::homMatrixFromAffineMatrix(aViewTransform
,
2227 viewState
.AffineTransform
);
2228 aTextureTransform
*= aRenderTransform
;
2230 // TODO(F1): Multi-texturing
2231 if( textures
[0].Gradient
.is() )
2233 aTextureTransform
*= aViewTransform
;
2235 // try to cast XParametricPolyPolygon2D reference to
2236 // our implementation class.
2237 ::canvas::ParametricPolyPolygon
* pGradient
=
2238 dynamic_cast< ::canvas::ParametricPolyPolygon
* >( textures
[0].Gradient
.get() );
2242 const ParametricPolyPolygon::Values
& rValues(
2243 pGradient
->getValues() );
2245 // TODO: use all the colors and place them on given positions/stops
2246 // TODO(E1): Return value
2247 // TODO(F1): FillRule
2248 fillGradient( rValues
,
2249 rValues
.maColors
[0],
2250 rValues
.maColors
[rValues
.maColors
.getLength () - 1],
2256 else if( textures
[0].Bitmap
.is() )
2258 ImageSharedPtr pTexture
;
2260 if( textureAnnotations
[0].get() != NULL
)
2261 pTexture
= textureAnnotations
[0];
2263 pTexture
.reset( new Image( textures
[0].Bitmap
) );
2265 const sal_uInt32
nWidth(pTexture
->maDesc
.nWidth
);
2266 const sal_uInt32
nHeight(pTexture
->maDesc
.nHeight
);
2268 // scale texture into one-by-one unit rect.
2269 aTextureTransform
.scale(1.0f
/nWidth
,
2272 // TODO(E1): Return value
2273 // TODO(F1): FillRule
2274 return fillTexturedPolyPolygon( *pTexture
,
2281 // TODO(F2): Implement sensible ImageCachedPrimitive
2282 return ImageCachedPrimitiveSharedPtr();
2285 //////////////////////////////////////////////////////////////////////////////////
2286 // Image::fillTextureMappedPolyPolygon
2287 //////////////////////////////////////////////////////////////////////////////////
2289 ImageCachedPrimitiveSharedPtr
Image::fillTextureMappedPolyPolygon(
2290 const uno::Reference
< rendering::XPolyPolygon2D
>& /*xPolyPolygon*/,
2291 const rendering::ViewState
& /*viewState*/,
2292 const rendering::RenderState
& /*renderState*/,
2293 const uno::Sequence
< rendering::Texture
>& /*textures*/,
2294 const ::std::vector
< ::boost::shared_ptr
<Image
> >& /*textureAnnotations*/,
2295 const uno::Reference
< geometry::XMapping2D
>& /*xMapping*/ )
2298 "Image::fillTextureMappedPolyPolygon(): NYI" );
2300 // TODO(F2): Implement sensible ImageCachedPrimitive
2301 return ImageCachedPrimitiveSharedPtr();
2304 //////////////////////////////////////////////////////////////////////////////////
2305 // Image::drawBitmap
2306 //////////////////////////////////////////////////////////////////////////////////
2308 ImageCachedPrimitiveSharedPtr
Image::drawBitmap(
2309 const uno::Reference
< rendering::XBitmap
>& xBitmap
,
2310 const rendering::ViewState
& viewState
,
2311 const rendering::RenderState
& renderState
)
2313 #if defined(PROFILER)
2314 ScopeTimer
aTimer(TIMER_DRAWBITMAP
,this);
2317 // TODO(P3): Implement bitmap caching
2319 return ImageCachedPrimitiveSharedPtr();
2321 XBitmapAccessor accessor( xBitmap );
2322 if(accessor.isValid())
2324 Image aImage( accessor.getDesc() );
2326 implDrawBitmap( aImage,
2330 // TODO(F2): Implement sensible ImageCachedPrimitive
2331 return ImageCachedPrimitiveSharedPtr();
2334 Image
aImage( xBitmap
);
2336 return implDrawBitmap( aImage
,viewState
,renderState
);
2339 //////////////////////////////////////////////////////////////////////////////////
2340 // Image::drawBitmap
2341 //////////////////////////////////////////////////////////////////////////////////
2343 ImageCachedPrimitiveSharedPtr
Image::drawBitmap(
2344 const ImageSharedPtr
& rImage
,
2345 const rendering::ViewState
& viewState
,
2346 const rendering::RenderState
& renderState
)
2348 #if defined(PROFILER)
2349 ScopeTimer
aTimer(TIMER_DRAWBITMAP
,this);
2352 // TODO(P3): Implement bitmap caching
2354 return ImageCachedPrimitiveSharedPtr();
2356 return implDrawBitmap( *rImage
,
2361 //////////////////////////////////////////////////////////////////////////////////
2362 // Image::drawBitmapModulated
2363 //////////////////////////////////////////////////////////////////////////////////
2365 ImageCachedPrimitiveSharedPtr
Image::drawBitmapModulated(
2366 const uno::Reference
< rendering::XBitmap
>& xBitmap
,
2367 const rendering::ViewState
& viewState
,
2368 const rendering::RenderState
& renderState
)
2370 // TODO(P3): Implement bitmap caching
2372 return ImageCachedPrimitiveSharedPtr();
2374 Image
aImage( xBitmap
);
2376 // TODO(F2): Distinguish modulated and unmodulated bitmap output
2377 return implDrawBitmap( aImage
,viewState
,renderState
);
2380 //////////////////////////////////////////////////////////////////////////////////
2381 // Image::drawBitmapModulated
2382 //////////////////////////////////////////////////////////////////////////////////
2384 ImageCachedPrimitiveSharedPtr
Image::drawBitmapModulated(
2385 const ImageSharedPtr
& rImage
,
2386 const rendering::ViewState
& viewState
,
2387 const rendering::RenderState
& renderState
)
2389 // TODO(P3): Implement bitmap caching
2391 return ImageCachedPrimitiveSharedPtr();
2393 // TODO(F2): Distinguish modulated and unmodulated bitmap output
2394 return implDrawBitmap( *rImage
,viewState
,renderState
);