1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_canvas.hxx"
31 #include <canvas/debug.hxx>
32 #include <tools/diagnose_ex.h>
34 #include <canvas/canvastools.hxx>
35 #include <canvas/parametricpolypolygon.hxx>
37 #include <com/sun/star/rendering/RepaintResult.hpp>
38 #include <com/sun/star/rendering/XIntegerReadOnlyBitmap.hpp>
40 #include <vcl/canvastools.hxx>
41 #include <vcl/bitmapex.hxx>
42 #include <vcl/bmpacc.hxx>
44 #include <basegfx/range/b2drange.hxx>
45 #include <basegfx/point/b2dpoint.hxx>
46 #include <basegfx/matrix/b2dhommatrix.hxx>
47 #include <basegfx/polygon/b2dpolygon.hxx>
48 #include <basegfx/polygon/b2dpolypolygon.hxx>
49 #include <basegfx/polygon/b2dpolygoncutandtouch.hxx>
50 #include <basegfx/polygon/b2dpolygontriangulator.hxx>
51 #include <basegfx/polygon/b2dpolypolygontools.hxx>
52 #include <basegfx/polygon/b2dpolygontools.hxx>
53 #include <basegfx/polygon/b2dpolygonclipper.hxx>
54 #include <basegfx/tools/canvastools.hxx>
55 #include <basegfx/polygon/b2dpolypolygoncutter.hxx>
56 #include <basegfx/polygon/b2dpolygonclipper.hxx>
60 #define CANVAS_IMAGE_CXX
61 #include "image_sysprereq.h"
63 //////////////////////////////////////////////////////////////////////////////////
64 // platform-dependend includes [wrapped into their own namepsaces]
65 //////////////////////////////////////////////////////////////////////////////////
69 # pragma warning(push,1)
78 #define WIN32_LEAN_AND_MEAN
102 using namespace ::com::sun::star
;
104 namespace canvas
{ namespace
106 //////////////////////////////////////////////////////////////////////////////////
107 // TransAffineFromAffineMatrix
108 //////////////////////////////////////////////////////////////////////////////////
110 ::agg::trans_affine
transAffineFromAffineMatrix( const geometry::AffineMatrix2D
& m
)
112 return agg::trans_affine(m
.m00
,
120 //////////////////////////////////////////////////////////////////////////////////
121 // TransAffineFromB2DHomMatrix
122 //////////////////////////////////////////////////////////////////////////////////
124 ::agg::trans_affine
transAffineFromB2DHomMatrix( const ::basegfx::B2DHomMatrix
& m
)
126 return agg::trans_affine(m
.get(0,0),
134 //////////////////////////////////////////////////////////////////////////////////
136 //////////////////////////////////////////////////////////////////////////////////
157 explicit ARGB( sal_uInt32 _color
) :
173 ARGB( sal_uInt32 default_color
,
174 const ::com::sun::star::uno::Sequence
< double >& sequence
) :
177 if(sequence
.getLength() > 2)
179 Color
.r
= static_cast<sal_uInt8
>(255.0f
*sequence
[0]);
180 Color
.g
= static_cast<sal_uInt8
>(255.0f
*sequence
[1]);
181 Color
.b
= static_cast<sal_uInt8
>(255.0f
*sequence
[2]);
182 if(sequence
.getLength() > 3)
183 Color
.a
= static_cast<sal_uInt8
>(255.0f
*sequence
[3]);
187 ARGB( const ARGB
& rhs
) :
192 ARGB
&operator=( const ARGB
&rhs
)
199 //////////////////////////////////////////////////////////////////////////////////
201 //////////////////////////////////////////////////////////////////////////////////
203 /// Calc common output state from XCanvas parameters
204 void setupState( ::basegfx::B2DHomMatrix
& o_rViewTransform
,
205 ::basegfx::B2DHomMatrix
& o_rRenderTransform
,
206 ::std::auto_ptr
< ::basegfx::B2DPolyPolygon
>& o_rViewClip
,
207 ::std::auto_ptr
< ::basegfx::B2DPolyPolygon
>& o_rRenderClip
,
208 ARGB
& o_rRenderColor
,
209 const rendering::ViewState
& viewState
,
210 const rendering::RenderState
& renderState
)
212 ::basegfx::unotools::homMatrixFromAffineMatrix(o_rRenderTransform
,
213 renderState
.AffineTransform
);
214 ::basegfx::unotools::homMatrixFromAffineMatrix(o_rViewTransform
,
215 viewState
.AffineTransform
);
217 o_rRenderColor
= ARGB(0xFFFFFFFF,
218 renderState
.DeviceColor
);
220 // TODO(F3): handle compositing modes
222 if( viewState
.Clip
.is() )
224 ::basegfx::B2DPolyPolygon
aViewClip(
225 ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D( viewState
.Clip
));
227 if(aViewClip
.areControlPointsUsed())
228 aViewClip
= ::basegfx::tools::adaptiveSubdivideByAngle(aViewClip
);
230 o_rViewClip
.reset( new ::basegfx::B2DPolyPolygon( aViewClip
) );
233 if( renderState
.Clip
.is() )
235 ::basegfx::B2DPolyPolygon
aRenderClip(
236 ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D( viewState
.Clip
) );
238 if(aRenderClip
.areControlPointsUsed())
239 aRenderClip
= ::basegfx::tools::adaptiveSubdivideByAngle(aRenderClip
);
241 o_rRenderClip
.reset( new ::basegfx::B2DPolyPolygon( aRenderClip
) );
245 //////////////////////////////////////////////////////////////////////////////////
246 // clipAndTransformPolygon
247 //////////////////////////////////////////////////////////////////////////////////
249 /** Clip and transform given polygon
254 @param bIsFilledPolyPolygon
255 When true, the polygon is clipped as if it was to be rendered
256 with fill, when false, the polygon is clipped as if it was to
257 be rendered with stroking.
259 void clipAndTransformPolygon( ::basegfx::B2DPolyPolygon
& io_rClippee
,
260 bool bIsFilledPolyPolygon
,
261 const ::basegfx::B2DHomMatrix
& rViewTransform
,
262 const ::basegfx::B2DHomMatrix
& rRenderTransform
,
263 const ::basegfx::B2DPolyPolygon
* pViewClip
,
264 const ::basegfx::B2DPolyPolygon
* pRenderClip
)
266 ::basegfx::B2DPolyPolygon
aPolyPolygon(io_rClippee
);
269 // clip contour against renderclip
273 aPolyPolygon
= basegfx::tools::clipPolyPolygonOnPolyPolygon(
274 aPolyPolygon
, *pRenderClip
, true, !bIsFilledPolyPolygon
);
277 if( !aPolyPolygon
.count() )
280 // transform result into view space
281 aPolyPolygon
.transform(rRenderTransform
);
283 // clip contour against viewclip
287 aPolyPolygon
= basegfx::tools::clipPolyPolygonOnPolyPolygon(
288 aPolyPolygon
, *pViewClip
, true, !bIsFilledPolyPolygon
);
291 if(!(aPolyPolygon
.count()))
294 // transform result into device space
295 aPolyPolygon
.transform(rViewTransform
);
297 io_rClippee
= aPolyPolygon
;
300 //////////////////////////////////////////////////////////////////////////////////
302 //////////////////////////////////////////////////////////////////////////////////
304 void setupPolyPolygon( ::basegfx::B2DPolyPolygon
& io_rClippee
,
305 bool bIsFilledPolyPolygon
,
306 ARGB
& o_rRenderColor
,
307 const rendering::ViewState
& viewState
,
308 const rendering::RenderState
& renderState
)
310 ::basegfx::B2DHomMatrix aViewTransform
;
311 ::basegfx::B2DHomMatrix aRenderTransform
;
312 ::std::auto_ptr
< ::basegfx::B2DPolyPolygon
> pViewClip
;
313 ::std::auto_ptr
< ::basegfx::B2DPolyPolygon
> pRenderClip
;
315 setupState( aViewTransform
,
323 clipAndTransformPolygon( io_rClippee
,
324 bIsFilledPolyPolygon
,
331 //////////////////////////////////////////////////////////////////////////////////
333 //////////////////////////////////////////////////////////////////////////////////
335 // Raw ABGR [AABBGGRR] 32bit continous
340 sal_uInt8
* mpBitmapData
;
343 //////////////////////////////////////////////////////////////////////////////////
345 //////////////////////////////////////////////////////////////////////////////////
347 void vclBitmapEx2Raw( const ::BitmapEx
& rBmpEx
, RawABGRBitmap
& rBmpData
)
349 Bitmap
aBitmap( rBmpEx
.GetBitmap() );
351 ScopedBitmapReadAccess
pReadAccess( aBitmap
.AcquireReadAccess(),
354 const sal_Int32
nWidth( rBmpData
.mnWidth
);
355 const sal_Int32
nHeight( rBmpData
.mnHeight
);
357 ENSURE_OR_THROW( pReadAccess
.get() != NULL
,
358 "vclBitmapEx2Raw(): "
359 "Unable to acquire read acces to bitmap" );
361 if( rBmpEx
.IsTransparent())
363 if( rBmpEx
.IsAlpha() )
366 Bitmap
aAlpha( rBmpEx
.GetAlpha().GetBitmap() );
368 ScopedBitmapReadAccess
pAlphaReadAccess( aAlpha
.AcquireReadAccess(),
371 // By convention, the access buffer always has
372 // one of the following formats:
374 // BMP_FORMAT_1BIT_MSB_PAL
375 // BMP_FORMAT_4BIT_MSN_PAL
376 // BMP_FORMAT_8BIT_PAL
377 // BMP_FORMAT_16BIT_TC_LSB_MASK
378 // BMP_FORMAT_24BIT_TC_BGR
379 // BMP_FORMAT_32BIT_TC_MASK
381 // and is always BMP_FORMAT_BOTTOM_UP
384 // WinSalBitmap::AcquireBuffer() sets up the
387 ENSURE_OR_THROW( pAlphaReadAccess
.get() != NULL
,
388 "vclBitmapEx2Raw(): "
389 "Unable to acquire read acces to alpha" );
391 ENSURE_OR_THROW( pAlphaReadAccess
->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL
||
392 pAlphaReadAccess
->GetScanlineFormat() == BMP_FORMAT_8BIT_TC_MASK
,
393 "vclBitmapEx2Raw(): "
394 "Unsupported alpha scanline format" );
397 sal_uInt8
* pCurrOutput( rBmpData
.mpBitmapData
);
400 for( y
=0; y
<nHeight
; ++y
)
402 switch( pReadAccess
->GetScanlineFormat() )
404 case BMP_FORMAT_8BIT_PAL
:
406 Scanline pScan
= pReadAccess
->GetScanline( y
);
407 Scanline pAScan
= pAlphaReadAccess
->GetScanline( y
);
409 for( x
=0; x
<nWidth
; ++x
)
411 aCol
= pReadAccess
->GetPaletteColor( *pScan
++ );
413 *pCurrOutput
++ = aCol
.GetBlue();
414 *pCurrOutput
++ = aCol
.GetGreen();
415 *pCurrOutput
++ = aCol
.GetRed();
417 // out notion of alpha is
418 // different from the rest
420 *pCurrOutput
++ = 255 - (sal_uInt8
)*pAScan
++;
425 case BMP_FORMAT_24BIT_TC_BGR
:
427 Scanline pScan
= pReadAccess
->GetScanline( y
);
428 Scanline pAScan
= pAlphaReadAccess
->GetScanline( y
);
430 for( x
=0; x
<nWidth
; ++x
)
433 *pCurrOutput
++ = *pScan
++;
434 *pCurrOutput
++ = *pScan
++;
435 *pCurrOutput
++ = *pScan
++;
437 // out notion of alpha is
438 // different from the rest
440 *pCurrOutput
++ = 255 - (sal_uInt8
)*pAScan
++;
445 // TODO(P2): Might be advantageous
446 // to hand-formulate the following
448 case BMP_FORMAT_1BIT_MSB_PAL
:
449 // FALLTHROUGH intended
450 case BMP_FORMAT_4BIT_MSN_PAL
:
451 // FALLTHROUGH intended
452 case BMP_FORMAT_16BIT_TC_LSB_MASK
:
453 // FALLTHROUGH intended
454 case BMP_FORMAT_32BIT_TC_MASK
:
456 Scanline pAScan
= pAlphaReadAccess
->GetScanline( y
);
458 // using fallback for those
460 for( x
=0; x
<nWidth
; ++x
)
462 // yes. x and y are swapped on Get/SetPixel
463 aCol
= pReadAccess
->GetColor(y
,x
);
465 *pCurrOutput
++ = aCol
.GetBlue();
466 *pCurrOutput
++ = aCol
.GetGreen();
467 *pCurrOutput
++ = aCol
.GetRed();
469 // out notion of alpha is
470 // different from the rest
472 *pCurrOutput
++ = 255 - (sal_uInt8
)*pAScan
++;
477 case BMP_FORMAT_1BIT_LSB_PAL
:
478 // FALLTHROUGH intended
479 case BMP_FORMAT_4BIT_LSN_PAL
:
480 // FALLTHROUGH intended
481 case BMP_FORMAT_8BIT_TC_MASK
:
482 // FALLTHROUGH intended
483 case BMP_FORMAT_24BIT_TC_RGB
:
484 // FALLTHROUGH intended
485 case BMP_FORMAT_24BIT_TC_MASK
:
486 // FALLTHROUGH intended
487 case BMP_FORMAT_16BIT_TC_MSB_MASK
:
488 // FALLTHROUGH intended
489 case BMP_FORMAT_32BIT_TC_ABGR
:
490 // FALLTHROUGH intended
491 case BMP_FORMAT_32BIT_TC_ARGB
:
492 // FALLTHROUGH intended
493 case BMP_FORMAT_32BIT_TC_BGRA
:
494 // FALLTHROUGH intended
495 case BMP_FORMAT_32BIT_TC_RGBA
:
496 // FALLTHROUGH intended
498 ENSURE_OR_THROW( false,
499 "vclBitmapEx2Raw(): "
500 "Unexpected scanline format - has "
501 "WinSalBitmap::AcquireBuffer() changed?" );
508 Bitmap
aMask( rBmpEx
.GetMask() );
510 ScopedBitmapReadAccess
pMaskReadAccess( aMask
.AcquireReadAccess(),
513 // By convention, the access buffer always has
514 // one of the following formats:
516 // BMP_FORMAT_1BIT_MSB_PAL
517 // BMP_FORMAT_4BIT_MSN_PAL
518 // BMP_FORMAT_8BIT_PAL
519 // BMP_FORMAT_16BIT_TC_LSB_MASK
520 // BMP_FORMAT_24BIT_TC_BGR
521 // BMP_FORMAT_32BIT_TC_MASK
523 // and is always BMP_FORMAT_BOTTOM_UP
526 // WinSalBitmap::AcquireBuffer() sets up the
529 ENSURE_OR_THROW( pMaskReadAccess
.get() != NULL
,
530 "vclBitmapEx2Raw(): "
531 "Unable to acquire read acces to mask" );
533 ENSURE_OR_THROW( pMaskReadAccess
->GetScanlineFormat() == BMP_FORMAT_1BIT_MSB_PAL
,
534 "vclBitmapEx2Raw(): "
535 "Unsupported mask scanline format" );
539 const int nMask( 1L );
540 const int nInitialBit(7);
541 sal_uInt32
*pBuffer
= reinterpret_cast<sal_uInt32
*>(rBmpData
.mpBitmapData
);
544 // mapping table, to get from mask index color to
545 // alpha value (which depends on the mask's palette)
546 sal_uInt8 aColorMap
[2];
548 const BitmapColor
& rCol0( pMaskReadAccess
->GetPaletteColor( 0 ) );
549 const BitmapColor
& rCol1( pMaskReadAccess
->GetPaletteColor( 1 ) );
551 // shortcut for true luminance calculation
552 // (assumes that palette is grey-level). Note the
553 // swapped the indices here, to account for the
554 // fact that VCL's notion of alpha is inverted to
555 // the rest of the world's.
556 aColorMap
[0] = rCol1
.GetRed();
557 aColorMap
[1] = rCol0
.GetRed();
559 for( y
=0; y
<nHeight
; ++y
)
561 switch( pReadAccess
->GetScanlineFormat() )
563 case BMP_FORMAT_8BIT_PAL
:
565 Scanline pScan
= pReadAccess
->GetScanline( y
);
566 Scanline pMScan
= pMaskReadAccess
->GetScanline( y
);
568 for( x
=0, nCurrBit
=nInitialBit
; x
<nWidth
; ++x
)
570 aCol
= pReadAccess
->GetPaletteColor( *pScan
++ );
573 unsigned int color
= aCol
.GetRed();
574 color
|= aCol
.GetGreen()<<8;
575 color
|= aCol
.GetBlue()<<16;
576 color
|= aColorMap
[ (pMScan
[ (x
& ~7L) >> 3L ] >> nCurrBit
) & nMask
]<<24;
578 nCurrBit
= ((nCurrBit
- 1) % 8L) & 7L;
583 case BMP_FORMAT_24BIT_TC_BGR
:
585 Scanline pScan
= pReadAccess
->GetScanline( y
);
586 Scanline pMScan
= pMaskReadAccess
->GetScanline( y
);
588 for( x
=0, nCurrBit
=nInitialBit
; x
<nWidth
; ++x
)
591 unsigned int color
= (*pScan
++)<<16;
592 color
|= (*pScan
++)<<8;
594 color
|= (aColorMap
[ (pMScan
[ (x
& ~7L) >> 3L ] >> nCurrBit
) & nMask
])<<24;
596 nCurrBit
= ((nCurrBit
- 1) % 8L) & 7L;
601 // TODO(P2): Might be advantageous
602 // to hand-formulate the following
604 case BMP_FORMAT_1BIT_MSB_PAL
:
605 // FALLTHROUGH intended
606 case BMP_FORMAT_4BIT_MSN_PAL
:
607 // FALLTHROUGH intended
608 case BMP_FORMAT_16BIT_TC_LSB_MASK
:
609 // FALLTHROUGH intended
610 case BMP_FORMAT_32BIT_TC_MASK
:
612 Scanline pMScan
= pMaskReadAccess
->GetScanline( y
);
614 // using fallback for those
616 for( x
=0, nCurrBit
=nInitialBit
; x
<nWidth
; ++x
)
618 // yes. x and y are swapped on Get/SetPixel
619 aCol
= pReadAccess
->GetColor(y
,x
);
622 unsigned int color
= aCol
.GetBlue()<<16;
623 color
|= aCol
.GetGreen()<<8;
624 color
|= aCol
.GetRed();
625 color
|= (aColorMap
[ (pMScan
[ (x
& ~7L) >> 3L ] >> nCurrBit
) & nMask
])<<24;
627 nCurrBit
= ((nCurrBit
- 1) % 8L) & 7L;
632 case BMP_FORMAT_1BIT_LSB_PAL
:
633 // FALLTHROUGH intended
634 case BMP_FORMAT_4BIT_LSN_PAL
:
635 // FALLTHROUGH intended
636 case BMP_FORMAT_8BIT_TC_MASK
:
637 // FALLTHROUGH intended
638 case BMP_FORMAT_24BIT_TC_RGB
:
639 // FALLTHROUGH intended
640 case BMP_FORMAT_24BIT_TC_MASK
:
641 // FALLTHROUGH intended
642 case BMP_FORMAT_16BIT_TC_MSB_MASK
:
643 // FALLTHROUGH intended
644 case BMP_FORMAT_32BIT_TC_ABGR
:
645 // FALLTHROUGH intended
646 case BMP_FORMAT_32BIT_TC_ARGB
:
647 // FALLTHROUGH intended
648 case BMP_FORMAT_32BIT_TC_BGRA
:
649 // FALLTHROUGH intended
650 case BMP_FORMAT_32BIT_TC_RGBA
:
651 // FALLTHROUGH intended
653 ENSURE_OR_THROW( false,
654 "vclBitmapEx2Raw(): "
655 "Unexpected scanline format - has "
656 "WinSalBitmap::AcquireBuffer() changed?" );
664 sal_uIntPtr nFormat
= pReadAccess
->GetScanlineFormat();
665 sal_uInt8
*pBuffer
= reinterpret_cast<sal_uInt8
*>(rBmpData
.mpBitmapData
);
669 case BMP_FORMAT_24BIT_TC_BGR
:
672 sal_Int32 height
= pReadAccess
->Height();
673 for(sal_Int32 y
=0; y
<height
; ++y
)
675 sal_uInt8
*pScanline
=pReadAccess
->GetScanline(y
);
676 sal_Int32 width
= pReadAccess
->Width();
677 for(sal_Int32 x
=0; x
<width
; ++x
)
680 sal_uInt8
b(*pScanline
++);
681 sal_uInt8
g(*pScanline
++);
682 sal_uInt8
r(*pScanline
++);
691 case BMP_FORMAT_24BIT_TC_RGB
:
694 sal_Int32 height
= pReadAccess
->Height();
695 for(sal_Int32 y
=0; y
<height
; ++y
)
697 sal_uInt8
*pScanline
=pReadAccess
->GetScanline(y
);
698 sal_Int32 width
= pReadAccess
->Width();
699 for(sal_Int32 x
=0; x
<width
; ++x
)
702 sal_uInt8
r(*pScanline
++);
703 sal_uInt8
g(*pScanline
++);
704 sal_uInt8
b(*pScanline
++);
713 case BMP_FORMAT_1BIT_MSB_PAL
:
714 case BMP_FORMAT_1BIT_LSB_PAL
:
715 case BMP_FORMAT_4BIT_MSN_PAL
:
716 case BMP_FORMAT_4BIT_LSN_PAL
:
717 case BMP_FORMAT_8BIT_PAL
:
720 sal_Int32 height
= pReadAccess
->Height();
721 for(sal_Int32 y
=0; y
<height
; ++y
)
723 sal_uInt8
*pScanline
=pReadAccess
->GetScanline(y
);
724 sal_Int32 width
= pReadAccess
->Width();
725 for(sal_Int32 x
=0; x
<width
; ++x
)
727 BitmapColor
aCol(pReadAccess
->GetPaletteColor(*pScanline
++));
729 *pBuffer
++ = aCol
.GetRed();
730 *pBuffer
++ = aCol
.GetGreen();
731 *pBuffer
++ = aCol
.GetBlue();
740 //////////////////////////////////////////////////////////////////////////////////
741 // color_generator_linear
742 //////////////////////////////////////////////////////////////////////////////////
744 template<typename T
> struct color_generator_linear
746 typedef typename
T::value_type value_type
;
748 color_generator_linear( const T
&c1
,
750 unsigned int aSteps
) : maSteps(aSteps
),
756 unsigned size() const { return maSteps
; }
757 const T
operator [] (unsigned v
) const
759 const double w
= double(v
)/maSteps
;
760 return T( static_cast<value_type
>(maColor1
.r
+(maColor2
.r
-maColor1
.r
)*w
),
761 static_cast<value_type
>(maColor1
.g
+(maColor2
.g
-maColor1
.g
)*w
),
762 static_cast<value_type
>(maColor1
.b
+(maColor2
.b
-maColor1
.b
)*w
),
763 static_cast<value_type
>(maColor1
.a
+(maColor2
.a
-maColor1
.a
)*w
));
766 unsigned int maSteps
;
771 //////////////////////////////////////////////////////////////////////////////////
772 // color_generator_axial
773 //////////////////////////////////////////////////////////////////////////////////
775 template<typename T
> struct color_generator_axial
777 typedef typename
T::value_type value_type
;
779 color_generator_axial( const T
&c1
,
781 unsigned int aSteps
) : maSteps(aSteps
),
787 unsigned size() const { return maSteps
; }
788 const T
operator [] (unsigned v
) const
790 const double aHalfSteps
= maSteps
/2.0;
791 const double w
= (v
>= aHalfSteps
) ?
792 1.0-((double(v
)-aHalfSteps
)/aHalfSteps
) :
793 (double(v
)*2.0)/maSteps
;
794 return T( static_cast<value_type
>(maColor1
.r
+(maColor2
.r
-maColor1
.r
)*w
),
795 static_cast<value_type
>(maColor1
.g
+(maColor2
.g
-maColor1
.g
)*w
),
796 static_cast<value_type
>(maColor1
.b
+(maColor2
.b
-maColor1
.b
)*w
),
797 static_cast<value_type
>(maColor1
.a
+(maColor2
.a
-maColor1
.a
)*w
));
800 unsigned int maSteps
;
805 //////////////////////////////////////////////////////////////////////////////////
806 // color_generator_adaptor
807 //////////////////////////////////////////////////////////////////////////////////
809 template<typename T
> struct color_generator_adaptor
811 color_generator_adaptor( const T
&c1
,
813 unsigned int aSteps
) : linear_generator(c1
,c2
,aSteps
),
814 axial_generator(c1
,c2
,aSteps
),
816 void set_linear( bool bLinear
) { mbLinear
=bLinear
; }
817 unsigned size() const { return mbLinear
? linear_generator
.size() : axial_generator
.size(); }
818 const T
operator [] (unsigned v
) const
821 linear_generator
.operator [] (v
) :
822 axial_generator
.operator [] (v
);
825 color_generator_linear
<T
> linear_generator
;
826 color_generator_axial
<T
> axial_generator
;
830 //////////////////////////////////////////////////////////////////////////////////
831 // gradient_polymorphic_wrapper_base
832 //////////////////////////////////////////////////////////////////////////////////
834 struct gradient_polymorphic_wrapper_base
836 virtual int calculate(int x
, int y
, int) const = 0;
839 //////////////////////////////////////////////////////////////////////////////////
840 // gradient_polymorphic_wrapper
841 //////////////////////////////////////////////////////////////////////////////////
843 template<class GradientF
> struct gradient_polymorphic_wrapper
:
844 public gradient_polymorphic_wrapper_base
846 virtual int calculate(int x
, int y
, int d
) const
848 return m_gradient
.calculate(x
, y
, d
);
850 GradientF m_gradient
;
853 //////////////////////////////////////////////////////////////////////////////////
855 //////////////////////////////////////////////////////////////////////////////////
864 inline int calculate(int x
, int y
, int d
) const
868 int clamp_x
= height
>width
? 0 : (width
-height
);
869 int clamp_y
= height
>width
? (height
-width
) : 0;
870 int value_x
= (ax
-clamp_x
)*d
/(width
-clamp_x
);
871 int value_y
= (ay
-clamp_y
)*d
/(height
-clamp_y
);
876 return value_x
> value_y
? value_x
: value_y
;
880 sal_uInt32
getBytesPerPixel( IColorBuffer::Format eFormat
)
885 OSL_ENSURE(false, "Unexpected pixel format");
886 // FALLTHROUGH intended
887 case IColorBuffer::FMT_R8G8B8
:
889 case IColorBuffer::FMT_A8R8G8B8
:
895 //////////////////////////////////////////////////////////////////////////////////
896 // Image::drawLinePolyPolygon
897 //////////////////////////////////////////////////////////////////////////////////
899 template<class pixel_format
>
900 void Image::drawLinePolyPolygonImpl( const ::basegfx::B2DPolyPolygon
& rPolyPolygon
,
902 const rendering::ViewState
& viewState
,
903 const rendering::RenderState
& renderState
)
905 ::basegfx::B2DPolyPolygon
aPolyPolygon( rPolyPolygon
);
908 setupPolyPolygon( aPolyPolygon
, false, aRenderColor
, viewState
, renderState
);
910 if( !aPolyPolygon
.count() )
913 // Class template pixel_formats_rgb24 has full knowledge about this
914 // particular pixel format in memory. The only template parameter
915 // can be order_rgb24 or order_bgr24 that determines the order of color channels.
916 //typedef agg::pixfmt_rgba32 pixel_format;
917 pixel_format
pixf(maRenderingBuffer
);
919 // There are two basic renderers with almost the same functionality:
920 // renderer_base and renderer_mclip. The first one is used most often
921 // and it performs low level clipping.
922 // This simply adds clipping to the graphics buffer, the clip rect
923 // will be initialized to the area of the framebuffer.
924 typedef agg::renderer_base
<pixel_format
> renderer_base
;
925 agg::renderer_base
<pixel_format
> renb(pixf
);
927 // To draw Anti-Aliased primitives one shoud *rasterize* them first.
928 // The primary rasterization technique in AGG is scanline based.
929 // That is, a polygon is converted into a number of horizontal
930 // scanlines and then the scanlines are being rendered one by one.
931 // To transfer information from a rasterizer to the scanline renderer
932 // there scanline containers are used. A scanline consists of a
933 // number of horizontal, non-intersecting spans. All spans must be ordered by X.
934 // --> *packed* scanline container
937 typedef agg::renderer_outline_aa
<renderer_base
> renderer_type
;
938 typedef agg::rasterizer_outline_aa
<renderer_type
> rasterizer_type
;
939 agg::line_profile_aa profile
;
940 profile
.width(fStrokeWidth
);
941 renderer_type
ren(renb
, profile
);
942 rasterizer_type
ras(ren
);
944 const agg::rgba8
fillcolor(aRenderColor
.Color
.r
,
945 aRenderColor
.Color
.g
,
946 aRenderColor
.Color
.b
,
947 aRenderColor
.Color
.a
);
948 ren
.color(fillcolor
);
950 agg::path_storage path
;
951 agg::conv_curve
<agg::path_storage
> curve(path
);
953 for(sal_uInt32 nPolygon
=0; nPolygon
<aPolyPolygon
.count(); ++nPolygon
)
955 const basegfx::B2DPolygon
aPolygon(aPolyPolygon
.getB2DPolygon(nPolygon
));
956 const sal_uInt32
nPointCount(aPolygon
.count());
960 if(aPolygon
.areControlPointsUsed())
962 // prepare edge-based loop
963 basegfx::B2DPoint
aCurrentPoint(aPolygon
.getB2DPoint(0));
964 const sal_uInt32
nEdgeCount(aPolygon
.isClosed() ? nPointCount
- 1 : nPointCount
);
967 path
.move_to(aCurrentPoint
.getX(), aCurrentPoint
.getY());
969 for(sal_uInt32
a(0); a
< nEdgeCount
; a
++)
972 const sal_uInt32
nNextIndex((a
+ 1) % nPointCount
);
973 const basegfx::B2DPoint
aNextPoint(aPolygon
.getB2DPoint(nNextIndex
));
975 // get control points
976 const basegfx::B2DPoint
aControlNext(aPolygon
.getNextControlPoint(a
));
977 const basegfx::B2DPoint
aControlPrev(aPolygon
.getPrevControlPoint(nNextIndex
));
979 // specify first cp, second cp, next vertex
981 aControlNext
.getX(), aControlNext
.getY(),
982 aControlPrev
.getX(), aControlPrev
.getY(),
983 aNextPoint
.getX(), aNextPoint
.getY());
986 aCurrentPoint
= aNextPoint
;
991 const basegfx::B2DPoint
aStartPoint(aPolygon
.getB2DPoint(0));
992 ras
.move_to_d(aStartPoint
.getX(), aStartPoint
.getY());
994 for(sal_uInt32
a(1); a
< nPointCount
; a
++)
996 const basegfx::B2DPoint
aVertexPoint(aPolygon
.getB2DPoint(a
));
997 ras
.line_to_d(aVertexPoint
.getX(), aVertexPoint
.getY());
1000 ras
.render(aPolygon
.isClosed());
1005 ras
.add_path(curve
);
1009 //////////////////////////////////////////////////////////////////////////////////
1010 // Image::drawLinePolyPolygon
1011 //////////////////////////////////////////////////////////////////////////////////
1013 void Image::drawLinePolyPolygon( const ::basegfx::B2DPolyPolygon
& rPoly
,
1014 double fStrokeWidth
,
1015 const rendering::ViewState
& viewState
,
1016 const rendering::RenderState
& renderState
)
1018 switch(maDesc
.eFormat
)
1021 drawLinePolyPolygonImpl
<agg::pixfmt_rgb24
>(rPoly
,fStrokeWidth
,viewState
,renderState
);
1024 drawLinePolyPolygonImpl
<agg::pixfmt_rgba32
>(rPoly
,fStrokeWidth
,viewState
,renderState
);
1027 OSL_ENSURE(false, "Unexpected pixel format");
1032 //////////////////////////////////////////////////////////////////////////////////
1033 // Image::implDrawBitmap
1034 //////////////////////////////////////////////////////////////////////////////////
1036 /** internal utility function to draw one image into another one.
1037 the source image will be drawn with respect to the given
1038 transform and clip settings.
1040 ImageCachedPrimitiveSharedPtr
Image::implDrawBitmap(
1041 const Image
& rBitmap
,
1042 const rendering::ViewState
& viewState
,
1043 const rendering::RenderState
& renderState
)
1045 ::basegfx::B2DPolyPolygon
aPoly(
1046 ::basegfx::tools::createPolygonFromRect(
1047 ::basegfx::B2DRange(0.0, 0.0,
1048 rBitmap
.maDesc
.nWidth
,
1049 rBitmap
.maDesc
.nHeight
) ) );
1052 setupPolyPolygon( aPoly
, true, aFillColor
, viewState
, renderState
);
1054 if( !aPoly
.count() )
1055 return ImageCachedPrimitiveSharedPtr();
1057 ::basegfx::B2DHomMatrix aViewTransform
;
1058 ::basegfx::B2DHomMatrix aRenderTransform
;
1059 ::basegfx::B2DHomMatrix aTextureTransform
;
1061 ::basegfx::unotools::homMatrixFromAffineMatrix(aRenderTransform
,
1062 renderState
.AffineTransform
);
1063 ::basegfx::unotools::homMatrixFromAffineMatrix(aViewTransform
,
1064 viewState
.AffineTransform
);
1065 aTextureTransform
*= aRenderTransform
;
1067 // TODO(F2): Fill in texture
1068 rendering::Texture aTexture
;
1070 return fillTexturedPolyPolygon( rBitmap
,
1077 //////////////////////////////////////////////////////////////////////////////////
1078 // cachedPrimitiveFTPP [cachedPrimitive for [F]ill[T]extured[P]oly[P]olygon]
1079 //////////////////////////////////////////////////////////////////////////////////
1081 #if AGG_VERSION >= 2400
1082 template<class pixel_format_dst
,class span_gen_type
>
1084 template<class pixel_format
,class span_gen_type
>
1086 class cachedPrimitiveFTPP
: public ImageCachedPrimitive
1090 cachedPrimitiveFTPP( const ::basegfx::B2DHomMatrix
&rTransform
,
1091 const ::basegfx::B2DHomMatrix
&rViewTransform
,
1092 agg::rendering_buffer
&dst
,
1093 const agg::rendering_buffer
& src
) :
1094 aTransform(rTransform
),
1096 filter(filter_kernel
),
1097 #if AGG_VERSION >= 2400
1098 pixs(const_cast<agg::rendering_buffer
&>(src
)),
1100 sg(source
,inter
,filter
),
1105 sg(sa
,src
,inter
,filter
),
1111 ::basegfx::B2DHomMatrix
aFinalTransform(aTransform
);
1112 aFinalTransform
*= rViewTransform
;
1113 tm
= transAffineFromB2DHomMatrix(aFinalTransform
);
1117 virtual void setImage( const ::boost::shared_ptr
< class Image
>& rTargetImage
)
1119 pImage
=rTargetImage
;
1122 virtual sal_Int8
redraw( const ::com::sun::star::rendering::ViewState
& aState
) const
1124 ::basegfx::B2DHomMatrix aViewTransform
;
1125 ::basegfx::unotools::homMatrixFromAffineMatrix(aViewTransform
,aState
.AffineTransform
);
1126 ::basegfx::B2DHomMatrix
aFinalTransform(aTransform
);
1127 aFinalTransform
*= aViewTransform
;
1128 tm
= transAffineFromB2DHomMatrix(aFinalTransform
);
1131 return ::com::sun::star::rendering::RepaintResult::REDRAWN
;
1134 inline void redraw() const { agg::render_scanlines(ras
, sl
, ren
); }
1136 mutable agg::rasterizer_scanline_aa
<> ras
;
1140 typedef agg::span_interpolator_linear
<> interpolator_type
;
1141 #if AGG_VERSION >= 2400
1142 typedef agg::renderer_base
<pixel_format_dst
> renderer_base
;
1143 typedef agg::span_allocator
< typename
span_gen_type::color_type
> span_alloc_type
;
1144 typedef agg::renderer_scanline_aa
<renderer_base
, span_alloc_type
, span_gen_type
> renderer_type
;
1145 typedef typename
span_gen_type::source_type source_type
;
1146 typedef typename
span_gen_type::source_type::pixfmt_type pixel_format_src
;
1148 typedef agg::renderer_base
<pixel_format
> renderer_base
;
1149 typedef agg::renderer_scanline_aa
<renderer_base
, span_gen_type
> renderer_type
;
1152 ::basegfx::B2DHomMatrix aTransform
;
1153 interpolator_type inter
;
1154 agg::image_filter_bilinear filter_kernel
;
1155 agg::image_filter_lut filter
;
1156 #if AGG_VERSION >= 2400
1158 pixel_format_src pixs
;
1161 agg::span_allocator
< typename
span_gen_type::color_type
> sa
;
1164 #if AGG_VERSION >= 2400
1165 pixel_format_dst pixd
;
1170 mutable renderer_type ren
;
1171 mutable agg::scanline_p8 sl
;
1172 mutable agg::trans_affine tm
;
1173 ImageSharedPtr pImage
;
1176 //////////////////////////////////////////////////////////////////////////////////
1177 // Image::fillTexturedPolyPolygon
1178 //////////////////////////////////////////////////////////////////////////////////
1180 template<class pixel_format
,class span_gen_type
>
1181 ImageCachedPrimitiveSharedPtr
Image::fillTexturedPolyPolygonImpl(
1182 const Image
& rTexture
,
1183 const ::basegfx::B2DPolyPolygon
& rPolyPolygon
,
1184 const ::basegfx::B2DHomMatrix
& rOverallTransform
,
1185 const ::basegfx::B2DHomMatrix
& rViewTransform
,
1186 const rendering::Texture
& )
1188 // calculate final overall transform.
1189 ::basegfx::B2DHomMatrix
aOverallTransform(rOverallTransform
);
1190 aOverallTransform
*= rViewTransform
;
1192 // instead of always using the full-blown solution we
1193 // first check to see if this is a simple rectangular
1194 // 1-to-1 copy from source to destination image.
1195 ::basegfx::B2DTuple
aTranslate(aOverallTransform
.get(0,2),aOverallTransform
.get(1,2));
1196 ::basegfx::B2DTuple
aSize(rTexture
.maDesc
.nWidth
,rTexture
.maDesc
.nHeight
);
1197 ::basegfx::B2DRange
aRange(aTranslate
,aTranslate
+aSize
);
1198 ::basegfx::B2DPolyPolygon
aPolyPolygon(rPolyPolygon
);
1199 aPolyPolygon
.transform(aOverallTransform
);
1200 if(::basegfx::tools::isPolyPolygonEqualRectangle(aPolyPolygon
,aRange
))
1202 // yes, we can take the shortcut.
1203 // but we need to clip the destination rectangle
1204 // against the boundary of the destination image.
1205 sal_Int32
dwSrcX(0);
1206 sal_Int32
dwSrcY(0);
1207 sal_Int32
dwDstX(static_cast<sal_Int32
>(aTranslate
.getX()));
1208 sal_Int32
dwDstY(static_cast<sal_Int32
>(aTranslate
.getY()));
1209 sal_Int32
dwWidth(rTexture
.maDesc
.nWidth
);
1210 sal_Int32
dwHeight(rTexture
.maDesc
.nHeight
);
1212 // prevent fast copy if destination position is not an
1213 // integer coordinate. otherwise we would most probably
1214 // introduce visual glitches while combining this with
1215 // high-accuracy rendering stuff.
1216 if( ::basegfx::fTools::equalZero(aTranslate
.getX()-dwDstX
) &&
1217 ::basegfx::fTools::equalZero(aTranslate
.getY()-dwDstY
))
1219 // clip against destination boundary. shrink size if
1220 // necessary, modify destination position if we need to.
1221 if(dwDstX
< 0) { dwWidth
-=dwDstX
; dwSrcX
=-dwDstX
; dwDstX
=0; }
1222 if(dwDstY
< 0) { dwHeight
-=dwDstY
; dwSrcY
=-dwDstY
; dwDstY
=0; }
1223 const sal_Int32
dwRight(dwDstX
+dwWidth
);
1224 const sal_Int32
dwBottom(dwDstY
+dwHeight
);
1225 if(dwRight
> dwWidth
)
1226 dwWidth
-= dwRight
-dwWidth
;
1227 if(dwBottom
> dwHeight
)
1228 dwHeight
-= dwBottom
-dwHeight
;
1230 // calculate source buffer
1231 const Description
&srcDesc
= rTexture
.maDesc
;
1232 const sal_uInt32
dwSrcBytesPerPixel(getBytesPerPixel(srcDesc
.eFormat
));
1233 const sal_uInt32
dwSrcPitch(srcDesc
.nWidth
*dwSrcBytesPerPixel
+srcDesc
.nStride
);
1234 sal_uInt8
*pSrcBuffer
= rTexture
.maDesc
.pBuffer
+(dwSrcPitch
*dwSrcX
)+(dwSrcBytesPerPixel
*dwSrcY
);
1236 // calculate destination buffer
1237 const Description
&dstDesc
= maDesc
;
1238 const sal_uInt32
dwDstBytesPerPixel(getBytesPerPixel(dstDesc
.eFormat
));
1239 const sal_uInt32
dwDstPitch(dstDesc
.nWidth
*dwDstBytesPerPixel
+dstDesc
.nStride
);
1240 sal_uInt8
*pDstBuffer
= maDesc
.pBuffer
+(dwDstPitch
*dwDstY
)+(dwDstBytesPerPixel
*dwDstX
);
1242 // if source and destination format match, we can simply
1243 // copy whole scanlines.
1244 if(srcDesc
.eFormat
== dstDesc
.eFormat
)
1246 const sal_Size
dwNumBytesPerScanline(dwSrcBytesPerPixel
*dwWidth
);
1247 for(sal_Int32 y
=0; y
<dwHeight
; ++y
)
1249 rtl_copyMemory(pDstBuffer
,pSrcBuffer
,dwNumBytesPerScanline
);
1250 pSrcBuffer
+= dwSrcPitch
;
1251 pDstBuffer
+= dwDstPitch
;
1256 // otherwise [formats do not match], we need to copy
1257 // each pixel one by one and convert from source to destination format.
1258 if(srcDesc
.eFormat
== FMT_A8R8G8B8
&& dstDesc
.eFormat
== FMT_R8G8B8
)
1260 for(sal_Int32 y
=0; y
<dwHeight
; ++y
)
1262 sal_uInt8
*pSrc
=pSrcBuffer
;
1263 sal_uInt8
*pDst
=pDstBuffer
;
1264 for(sal_Int32 x
=0; x
<dwWidth
; ++x
)
1266 sal_uInt8
r(*pSrc
++);
1267 sal_uInt8
g(*pSrc
++);
1268 sal_uInt8
b(*pSrc
++);
1269 sal_uInt8
Alpha(*pSrc
++);
1270 sal_uInt8
OneMinusAlpha(0xFF-Alpha
);
1271 *pDst
=(((r
*Alpha
)+((*pDst
)*OneMinusAlpha
))/0xFF);
1273 *pDst
=(((g
*Alpha
)+((*pDst
)*OneMinusAlpha
))/0xFF);
1275 *pDst
=(((b
*Alpha
)+((*pDst
)*OneMinusAlpha
))/0xFF);
1278 pSrcBuffer
+= dwSrcPitch
;
1279 pDstBuffer
+= dwDstPitch
;
1282 else if(srcDesc
.eFormat
== FMT_R8G8B8
&& dstDesc
.eFormat
== FMT_A8R8G8B8
)
1284 for(sal_Int32 y
=0; y
<dwHeight
; ++y
)
1286 sal_uInt8
*pSrc
=pSrcBuffer
;
1287 sal_uInt8
*pDst
=pDstBuffer
;
1288 for(sal_Int32 x
=0; x
<dwWidth
; ++x
)
1290 sal_uInt8
r(*pSrc
++);
1291 sal_uInt8
g(*pSrc
++);
1292 sal_uInt8
b(*pSrc
++);
1298 pSrcBuffer
+= dwSrcPitch
;
1299 pDstBuffer
+= dwDstPitch
;
1304 return ImageCachedPrimitiveSharedPtr();
1308 typedef cachedPrimitiveFTPP
<pixel_format
,span_gen_type
> cachedPrimitive_t
;
1309 cachedPrimitive_t
*pPrimitive
= new cachedPrimitive_t( rOverallTransform
,
1312 rTexture
.maRenderingBuffer
);
1314 agg::path_storage path
;
1315 agg::conv_curve
<agg::path_storage
> curve(path
);
1317 for(sal_uInt32
nPolygon(0); nPolygon
< rPolyPolygon
.count(); nPolygon
++)
1319 const basegfx::B2DPolygon
aPolygon(rPolyPolygon
.getB2DPolygon(nPolygon
));
1320 const sal_uInt32
nPointCount(aPolygon
.count());
1324 if(aPolygon
.areControlPointsUsed())
1326 // prepare edge-based loop
1327 basegfx::B2DPoint
aCurrentPoint(aPolygon
.getB2DPoint(0));
1328 const sal_uInt32
nEdgeCount(aPolygon
.isClosed() ? nPointCount
- 1 : nPointCount
);
1331 path
.move_to(aCurrentPoint
.getX(), aCurrentPoint
.getY());
1333 for(sal_uInt32
a(0); a
< nEdgeCount
; a
++)
1335 // access next point
1336 const sal_uInt32
nNextIndex((a
+ 1) % nPointCount
);
1337 const basegfx::B2DPoint
aNextPoint(aPolygon
.getB2DPoint(nNextIndex
));
1339 // get control points
1340 const basegfx::B2DPoint
aControlNext(aPolygon
.getNextControlPoint(a
));
1341 const basegfx::B2DPoint
aControlPrev(aPolygon
.getPrevControlPoint(nNextIndex
));
1343 // specify first cp, second cp, next vertex
1345 aControlNext
.getX(), aControlNext
.getY(),
1346 aControlPrev
.getX(), aControlPrev
.getY(),
1347 aNextPoint
.getX(), aNextPoint
.getY());
1349 // prepare next step
1350 aCurrentPoint
= aNextPoint
;
1355 const basegfx::B2DPoint
aPoint(aPolygon
.getB2DPoint(0));
1356 pPrimitive
->ras
.move_to_d(aPoint
.getX(), aPoint
.getY());
1358 for(sal_uInt32
a(1); a
< nPointCount
; a
++)
1360 const basegfx::B2DPoint
aVertexPoint(aPolygon
.getB2DPoint(a
));
1361 pPrimitive
->ras
.line_to_d(aVertexPoint
.getX(), aVertexPoint
.getY());
1364 if(aPolygon
.isClosed())
1366 pPrimitive
->ras
.close_polygon();
1372 pPrimitive
->ras
.add_path(curve
);
1373 pPrimitive
->redraw();
1375 return ImageCachedPrimitiveSharedPtr(pPrimitive
);
1378 //////////////////////////////////////////////////////////////////////////////////
1379 // Image::fillTexturedPolyPolygon
1380 //////////////////////////////////////////////////////////////////////////////////
1382 ImageCachedPrimitiveSharedPtr
Image::fillTexturedPolyPolygon(
1383 const Image
& rTexture
,
1384 const ::basegfx::B2DPolyPolygon
& rPolyPolygon
,
1385 const ::basegfx::B2DHomMatrix
& rOverallTransform
,
1386 const ::basegfx::B2DHomMatrix
& rViewTransform
,
1387 const rendering::Texture
& texture
)
1389 typedef agg::wrap_mode_repeat wrap_x_type
;
1390 typedef agg::wrap_mode_repeat wrap_y_type
;
1391 typedef agg::pixfmt_rgb24 pixfmt_rgb24
;
1392 typedef agg::pixfmt_rgba32 pixfmt_rgba32
;
1393 #if AGG_VERSION >= 2400
1394 typedef agg::image_accessor_wrap
< pixfmt_rgba32
, wrap_x_type
, wrap_y_type
> img_source_type_rgba
;
1395 typedef agg::image_accessor_wrap
< pixfmt_rgb24
, wrap_x_type
, wrap_y_type
> img_source_type_rgb
;
1397 typedef agg::span_image_resample_rgba_affine
< img_source_type_rgba
> span_gen_type_rgba
;
1398 typedef agg::span_image_resample_rgb_affine
< img_source_type_rgb
> span_gen_type_rgb
;
1400 typedef agg::span_pattern_resample_rgba_affine
< pixfmt_rgba32::color_type
,
1401 pixfmt_rgba32::order_type
,
1403 wrap_y_type
> span_gen_type_rgba
;
1404 typedef agg::span_pattern_resample_rgb_affine
< pixfmt_rgb24::color_type
,
1405 pixfmt_rgb24::order_type
,
1407 wrap_y_type
> span_gen_type_rgb
;
1410 const Format nDest
= maDesc
.eFormat
;
1411 const Format nSource
= rTexture
.maDesc
.eFormat
;
1413 if(nDest
== FMT_R8G8B8
&& nSource
== FMT_R8G8B8
)
1415 return fillTexturedPolyPolygonImpl
< agg::pixfmt_rgb24
,
1416 span_gen_type_rgb
>(
1423 else if(nDest
== FMT_R8G8B8
&& nSource
== FMT_A8R8G8B8
)
1425 return fillTexturedPolyPolygonImpl
< agg::pixfmt_rgb24
,
1426 span_gen_type_rgba
>(
1433 else if(nDest
== FMT_A8R8G8B8
&& nSource
== FMT_R8G8B8
)
1435 return fillTexturedPolyPolygonImpl
< agg::pixfmt_rgba32
,
1436 span_gen_type_rgb
>(
1443 else if(nDest
== FMT_A8R8G8B8
&& nSource
== FMT_A8R8G8B8
)
1445 return fillTexturedPolyPolygonImpl
< agg::pixfmt_rgba32
,
1446 span_gen_type_rgba
>(
1455 OSL_ENSURE(false, "Unexpected pixel format");
1458 return ImageCachedPrimitiveSharedPtr();
1461 //////////////////////////////////////////////////////////////////////////////////
1462 // Image::fillGradient
1463 //////////////////////////////////////////////////////////////////////////////////
1465 template<class pixel_format
>
1466 void Image::fillGradientImpl( const ParametricPolyPolygon::Values
& rValues
,
1467 const uno::Sequence
< double >& rUnoColor1
,
1468 const uno::Sequence
< double >& rUnoColor2
,
1469 const ::basegfx::B2DPolyPolygon
& rPolyPolygon
,
1470 const ::basegfx::B2DHomMatrix
& rOverallTransform
,
1471 const rendering::Texture
& )
1473 const ARGB
aColor1(0xFFFFFFFF,
1475 const ARGB
aColor2(0xFFFFFFFF,
1478 // first of all we need to provide the framebuffer we want to render to.
1479 // the properties of the framebuffer are
1480 // 1) memory & layout [width, height, stride]
1484 // Class template pixel_formats_rgb24 has full knowledge about this
1485 // particular pixel format in memory. The only template parameter
1486 // can be order_rgb24 or order_bgr24 that determines the order of color channels.
1487 pixel_format
pixf(maRenderingBuffer
);
1489 // There are two basic renderers with almost the same functionality:
1490 // renderer_base and renderer_mclip. The first one is used most often
1491 // and it performs low level clipping.
1492 // This simply adds clipping to the graphics buffer, the clip rect
1493 // will be initialized to the area of the framebuffer.
1494 typedef agg::renderer_base
<pixel_format
> renderer_base
;
1495 renderer_base
rb(pixf
);
1497 // bounding rectangle of untransformed polypolygon
1498 const ::basegfx::B2DRange
& rBounds(::basegfx::tools::getRange(rPolyPolygon
));
1500 // the color generator produces a specific color from
1501 // some given interpolation value.
1502 // number of steps for color interpolation
1503 typedef typename
pixel_format::color_type color_type
;
1504 color_type
color1(agg::rgba8(aColor1
.Color
.r
,
1508 color_type
color2(agg::rgba8(aColor2
.Color
.r
,
1512 typedef color_generator_adaptor
<color_type
> color_generator_type
;
1513 unsigned int dwNumSteps
= static_cast<unsigned int>(rBounds
.getWidth());
1514 color_generator_type
colors(color1
,color2
,dwNumSteps
);
1515 colors
.set_linear(true);
1518 gradient_polymorphic_wrapper
<agg::gradient_x
> gf_x
;
1519 gradient_polymorphic_wrapper
<agg::gradient_radial
> gf_radial
;
1520 gradient_polymorphic_wrapper
<gradient_rect
> gf_rectangular
;
1521 gf_rectangular
.m_gradient
.width
= static_cast<int>(rBounds
.getWidth())<<4;
1522 gf_rectangular
.m_gradient
.height
= static_cast<int>(rBounds
.getHeight())<<4;
1523 const gradient_polymorphic_wrapper_base
*gf
[] = { &gf_x
, // GRADIENT_LINEAR
1524 &gf_x
, // GRADIENT_AXIAL
1525 &gf_radial
, // GRADIENT_ELLIPTICAL
1526 &gf_rectangular
// GRADIENT_RECTANGULAR
1529 // how do texture coordinates change when the pixel coordinate change?
1530 typedef agg::span_interpolator_linear
<> interpolator_type
;
1531 agg::trans_affine tm
;
1532 tm
*= agg::trans_affine_scaling(1.0f
/rBounds
.getWidth(),
1533 1.0f
/rBounds
.getHeight());
1534 if(rValues
.meType
== ParametricPolyPolygon::GRADIENT_ELLIPTICAL
||
1535 rValues
.meType
== ParametricPolyPolygon::GRADIENT_RECTANGULAR
)
1537 //tm *= trans_affine_scaling(mnAspectRatio,+1.0f);
1538 //const double fAspect = aBounds.getWidth()/aBounds.getHeight();
1539 //tm *= trans_affine_scaling(+0.5f,+0.5f*(1.0f/fAspect));
1540 //tm *= trans_affine_translation(+0.5f,+0.5f);
1541 tm
*= agg::trans_affine_scaling(+0.5f
,+0.5f
);
1542 tm
*= agg::trans_affine_translation(+0.5f
,+0.5f
);
1544 tm
*= transAffineFromB2DHomMatrix(rOverallTransform
);
1546 interpolator_type
inter(tm
);
1548 // spanline allocators reserve memory for the color values
1549 // filled up by the spanline generators.
1550 typedef agg::span_allocator
<color_type
> gradient_span_alloc
;
1551 gradient_span_alloc span_alloc
;
1553 // scanline generators create the actual color values for
1554 // some specific coordinate range of a scanline.
1555 typedef agg::span_gradient
<color_type
,
1557 gradient_polymorphic_wrapper_base
,
1558 color_generator_type
> gradient_span_gen
;
1559 #if AGG_VERSION >= 2400
1560 gradient_span_gen
span_gen(inter
,
1561 *gf
[rValues
.meType
],
1566 gradient_span_gen
span_gen(span_alloc
,
1568 *gf
[rValues
.meType
],
1574 // To draw Anti-Aliased primitives one shoud *rasterize* them first.
1575 // The primary rasterization technique in AGG is scanline based.
1576 // That is, a polygon is converted into a number of horizontal
1577 // scanlines and then the scanlines are being rendered one by one.
1578 // To transfer information from a rasterizer to the scanline renderer
1579 // there scanline containers are used. A scanline consists of a
1580 // number of horizontal, non-intersecting spans. All spans must be ordered by X.
1581 // --> packed scanline container
1582 agg::scanline_p8 sl
;
1584 // antialiased scanline renderer with pattern filling capability
1585 // [in contrast to solid renderers, that is]
1586 // the instance of this particular renderer combines the
1587 // renderbuffer [i.e. destination] and the spanline generator [i.e. source]
1588 #if AGG_VERSION >= 2400
1589 typedef agg::renderer_scanline_aa
<renderer_base
, gradient_span_alloc
, gradient_span_gen
> renderer_gradient
;
1590 renderer_gradient
r1(rb
, span_alloc
, span_gen
);
1592 typedef agg::renderer_scanline_aa
<renderer_base
, gradient_span_gen
> renderer_gradient
;
1593 renderer_gradient
r1(rb
, span_gen
);
1596 // instantiate the rasterizer and feed the incoming polypolygon.
1597 agg::rasterizer_scanline_aa
<> ras
;
1598 agg::path_storage path
;
1599 agg::conv_curve
<agg::path_storage
> curve(path
);
1601 for(sal_uInt32
nPolygon(0); nPolygon
< rPolyPolygon
.count(); nPolygon
++)
1603 const basegfx::B2DPolygon
aPolygon(rPolyPolygon
.getB2DPolygon(nPolygon
));
1604 const sal_uInt32
nPointCount(aPolygon
.count());
1608 if(aPolygon
.areControlPointsUsed())
1610 // prepare edge-based loop
1611 basegfx::B2DPoint
aCurrentPoint(aPolygon
.getB2DPoint(0));
1612 const sal_uInt32
nEdgeCount(aPolygon
.isClosed() ? nPointCount
- 1 : nPointCount
);
1615 path
.move_to(aCurrentPoint
.getX(), aCurrentPoint
.getY());
1617 for(sal_uInt32
a(0); a
< nEdgeCount
; a
++)
1619 // access next point
1620 const sal_uInt32
nNextIndex((a
+ 1) % nPointCount
);
1621 const basegfx::B2DPoint
aNextPoint(aPolygon
.getB2DPoint(nNextIndex
));
1623 // get control points
1624 const basegfx::B2DPoint
aControlNext(aPolygon
.getNextControlPoint(a
));
1625 const basegfx::B2DPoint
aControlPrev(aPolygon
.getPrevControlPoint(nNextIndex
));
1627 // specify first cp, second cp, next vertex
1629 aControlNext
.getX(), aControlNext
.getY(),
1630 aControlPrev
.getX(), aControlPrev
.getY(),
1631 aNextPoint
.getX(), aNextPoint
.getY());
1633 // prepare next step
1634 aCurrentPoint
= aNextPoint
;
1639 const basegfx::B2DPoint
aPoint(aPolygon
.getB2DPoint(0));
1640 ras
.move_to_d(aPoint
.getX(), aPoint
.getY());
1642 for(sal_uInt32
a(1); a
< nPointCount
; a
++)
1644 const basegfx::B2DPoint
aVertexPoint(aPolygon
.getB2DPoint(a
));
1645 ras
.line_to_d(aVertexPoint
.getX(), aVertexPoint
.getY());
1648 if(aPolygon
.isClosed())
1650 ras
.close_polygon();
1656 // everything is up and running, go...
1657 ras
.add_path(curve
);
1658 render_scanlines(ras
,sl
,r1
);
1661 //////////////////////////////////////////////////////////////////////////////////
1662 // Image::fillGradient
1663 //////////////////////////////////////////////////////////////////////////////////
1665 void Image::fillGradient( const ParametricPolyPolygon::Values
& rValues
,
1666 const uno::Sequence
< double >& rUnoColor1
,
1667 const uno::Sequence
< double >& rUnoColor2
,
1668 const ::basegfx::B2DPolyPolygon
& rPolyPolygon
,
1669 const ::basegfx::B2DHomMatrix
& rOverallTransform
,
1670 const rendering::Texture
& texture
)
1672 switch(maDesc
.eFormat
)
1675 fillGradientImpl
<agg::pixfmt_rgb24
>(rValues
,rUnoColor1
,rUnoColor2
,rPolyPolygon
,rOverallTransform
,texture
);
1678 fillGradientImpl
<agg::pixfmt_rgba32
>(rValues
,rUnoColor1
,rUnoColor2
,rPolyPolygon
,rOverallTransform
,texture
);
1681 OSL_ENSURE(false, "Unexpected pixel format");
1686 //////////////////////////////////////////////////////////////////////////////////
1687 // Image::fromVCLBitmap
1688 //////////////////////////////////////////////////////////////////////////////////
1690 bool Image::fromVCLBitmap( ::BitmapEx
& rBmpEx
)
1692 const ::Size
aBmpSize( rBmpEx
.GetSizePixel() );
1693 Image::Description desc
;
1694 desc
.eFormat
= rBmpEx
.IsTransparent() ? FMT_A8R8G8B8
: FMT_R8G8B8
;
1695 desc
.nWidth
= aBmpSize
.Width();
1696 desc
.nHeight
= aBmpSize
.Height();
1698 const sal_uInt32
nPitch(desc
.nWidth
*getBytesPerPixel(desc
.eFormat
)+desc
.nStride
);
1699 desc
.pBuffer
= new sal_uInt8
[nPitch
*desc
.nHeight
];
1701 mbBufferHasUserOwnership
= false;
1702 maRenderingBuffer
.attach(static_cast<agg::int8u
*>(desc
.pBuffer
),
1706 RawABGRBitmap aBmpData
;
1707 aBmpData
.mnWidth
= aBmpSize
.Width();
1708 aBmpData
.mnHeight
= aBmpSize
.Height();
1709 aBmpData
.mpBitmapData
= static_cast<sal_uInt8
*>(desc
.pBuffer
);
1710 vclBitmapEx2Raw(rBmpEx
,aBmpData
);
1715 //////////////////////////////////////////////////////////////////////////////////
1717 //////////////////////////////////////////////////////////////////////////////////
1719 Image::Image( const Description
& rDesc
) :
1721 maRenderingBuffer(),
1722 mbBufferHasUserOwnership( rDesc
.pBuffer
!= NULL
)
1724 #if defined(PROFILER)
1725 for(int i
=0; i
<TIMER_MAX
; ++i
)
1726 maElapsedTime
[i
]=0.0;
1729 // allocate own buffer memory, if not provided
1730 sal_uInt8
* pBuffer
= maDesc
.pBuffer
;
1731 const sal_uInt32
nWidth(maDesc
.nWidth
);
1732 const sal_uInt32
nHeight(maDesc
.nHeight
);
1733 const sal_uInt32
nStride(maDesc
.nStride
);
1734 const sal_uInt32
nPitch(nWidth
*getBytesPerPixel(maDesc
.eFormat
)
1738 pBuffer
= new sal_uInt8
[nPitch
*nHeight
];
1740 maDesc
.pBuffer
= pBuffer
;
1742 // attach graphics buffer
1743 maRenderingBuffer
.attach(
1744 static_cast<agg::int8u
*>(pBuffer
),
1750 //////////////////////////////////////////////////////////////////////////////////
1752 //////////////////////////////////////////////////////////////////////////////////
1754 Image::Image( const uno::Reference
< rendering::XBitmap
>& xBitmap
) :
1756 maRenderingBuffer(),
1757 mbBufferHasUserOwnership( false )
1759 #if defined(PROFILER)
1760 for(int i
=0; i
<TIMER_MAX
; ++i
)
1761 maElapsedTime
[i
]=0.0;
1764 // TODO(F1): Add support for floating point bitmap formats
1765 uno::Reference
<rendering::XIntegerReadOnlyBitmap
> xIntBmp(xBitmap
,
1766 uno::UNO_QUERY_THROW
);
1767 ::BitmapEx aBmpEx
= ::vcl::unotools::bitmapExFromXBitmap(xIntBmp
);
1769 fromVCLBitmap(aBmpEx
);
1771 // TODO(F2): Fallback to XIntegerBitmap interface for import
1773 "Image::Image(): Cannot retrieve bitmap data!" );
1776 //////////////////////////////////////////////////////////////////////////////////
1778 //////////////////////////////////////////////////////////////////////////////////
1782 #if defined(PROFILER)
1784 double aAccumulatedTime(0.0);
1785 for(int i
=0; i
<TIMER_MAX
; ++i
)
1786 aAccumulatedTime
+= maElapsedTime
[i
];
1788 OSL_TRACE("Image %d - %d %d %d %d %d\n",(int)(aAccumulatedTime
*1000.0),
1789 (int)(maElapsedTime
[TIMER_FILLTEXTUREDPOLYPOLYGON
]*1000.0),
1790 (int)(maElapsedTime
[TIMER_FILLB2DPOLYPOLYGON
]*1000.0),
1791 (int)(maElapsedTime
[TIMER_DRAWPOLYPOLYGON
]*1000.0),
1792 (int)(maElapsedTime
[TIMER_FILLPOLYPOLYGON
]*1000.0),
1793 (int)(maElapsedTime
[TIMER_DRAWBITMAP
]*1000.0));
1797 if( !mbBufferHasUserOwnership
)
1798 delete [] maDesc
.pBuffer
;
1801 //////////////////////////////////////////////////////////////////////////////////
1803 //////////////////////////////////////////////////////////////////////////////////
1805 template<class pixel_format
>
1806 void Image::clearImpl( sal_uInt8 a
,
1811 pixel_format
pixf(maRenderingBuffer
);
1812 agg::renderer_base
<pixel_format
> renb(pixf
);
1814 renb
.clear(agg::rgba8(r
,g
,b
,a
));
1817 //////////////////////////////////////////////////////////////////////////////////
1819 //////////////////////////////////////////////////////////////////////////////////
1821 void Image::clear( sal_uInt8 a
,
1826 switch(maDesc
.eFormat
)
1829 return clearImpl
<agg::pixfmt_rgb24
>(a
,r
,g
,b
);
1831 return clearImpl
<agg::pixfmt_rgba32
>(a
,r
,g
,b
);
1833 OSL_ENSURE(false, "Unexpected pixel format");
1838 //////////////////////////////////////////////////////////////////////////////////
1839 // Image::fillB2DPolyPolygon
1840 //////////////////////////////////////////////////////////////////////////////////
1842 void Image::fillB2DPolyPolygon(
1843 const ::basegfx::B2DPolyPolygon
& rPolyPolygon
,
1844 const rendering::ViewState
& viewState
,
1845 const rendering::RenderState
& renderState
)
1847 #if defined(PROFILER)
1848 ScopeTimer
aTimer(TIMER_FILLB2DPOLYPOLYGON
,this);
1851 switch(maDesc
.eFormat
)
1854 fillPolyPolygonImpl
<agg::pixfmt_rgb24
>(rPolyPolygon
,viewState
,renderState
);
1857 fillPolyPolygonImpl
<agg::pixfmt_rgba32
>(rPolyPolygon
,viewState
,renderState
);
1860 OSL_ENSURE(false, "Unexpected pixel format");
1865 //////////////////////////////////////////////////////////////////////////////////
1867 //////////////////////////////////////////////////////////////////////////////////
1869 sal_uInt8
* Image::lock() const
1871 return maDesc
.pBuffer
;
1874 //////////////////////////////////////////////////////////////////////////////////
1876 //////////////////////////////////////////////////////////////////////////////////
1878 void Image::unlock() const
1882 //////////////////////////////////////////////////////////////////////////////////
1884 //////////////////////////////////////////////////////////////////////////////////
1886 sal_uInt32
Image::getWidth() const
1888 return maDesc
.nWidth
;
1891 //////////////////////////////////////////////////////////////////////////////////
1893 //////////////////////////////////////////////////////////////////////////////////
1895 sal_uInt32
Image::getHeight() const
1897 return maDesc
.nHeight
;
1900 //////////////////////////////////////////////////////////////////////////////////
1902 //////////////////////////////////////////////////////////////////////////////////
1904 sal_uInt32
Image::getStride() const
1906 return maDesc
.nWidth
*getBytesPerPixel(maDesc
.eFormat
)+maDesc
.nStride
;
1909 //////////////////////////////////////////////////////////////////////////////////
1911 //////////////////////////////////////////////////////////////////////////////////
1913 IColorBuffer::Format
Image::getFormat() const
1915 return maDesc
.eFormat
;
1918 //////////////////////////////////////////////////////////////////////////////////
1920 //////////////////////////////////////////////////////////////////////////////////
1922 void Image::drawPoint( const geometry::RealPoint2D
& /*aPoint*/,
1923 const rendering::ViewState
& /*viewState*/,
1924 const rendering::RenderState
& /*renderState*/ )
1927 "Image::drawPoint(): NYI" );
1930 //////////////////////////////////////////////////////////////////////////////////
1932 //////////////////////////////////////////////////////////////////////////////////
1934 void Image::drawLine( const geometry::RealPoint2D
& aStartPoint
,
1935 const geometry::RealPoint2D
& aEndPoint
,
1936 const rendering::ViewState
& viewState
,
1937 const rendering::RenderState
& renderState
)
1939 ::basegfx::B2DPolygon aLinePoly
;
1941 ::basegfx::unotools::b2DPointFromRealPoint2D( aStartPoint
) );
1943 ::basegfx::unotools::b2DPointFromRealPoint2D( aEndPoint
) );
1945 drawLinePolyPolygon( ::basegfx::B2DPolyPolygon( aLinePoly
),
1951 //////////////////////////////////////////////////////////////////////////////////
1952 // Image::drawBezier
1953 //////////////////////////////////////////////////////////////////////////////////
1955 void Image::drawBezier( const geometry::RealBezierSegment2D
& aBezierSegment
,
1956 const geometry::RealPoint2D
& aEndPoint
,
1957 const rendering::ViewState
& viewState
,
1958 const rendering::RenderState
& renderState
)
1960 basegfx::B2DPolygon aBezierPoly
;
1962 aBezierPoly
.append(basegfx::B2DPoint(aBezierSegment
.Px
, aBezierSegment
.Py
));
1963 aBezierPoly
.appendBezierSegment(
1964 basegfx::B2DPoint(aBezierSegment
.C1x
, aBezierSegment
.C1y
),
1965 basegfx::B2DPoint(aBezierSegment
.C2x
, aBezierSegment
.C2y
),
1966 basegfx::unotools::b2DPointFromRealPoint2D(aEndPoint
));
1968 drawLinePolyPolygon( ::basegfx::B2DPolyPolygon( aBezierPoly
),
1974 //////////////////////////////////////////////////////////////////////////////////
1975 // Image::drawPolyPolygon
1976 //////////////////////////////////////////////////////////////////////////////////
1978 ImageCachedPrimitiveSharedPtr
Image::drawPolyPolygon(
1979 const uno::Reference
< rendering::XPolyPolygon2D
>& xPolyPolygon
,
1980 const rendering::ViewState
& viewState
,
1981 const rendering::RenderState
& renderState
)
1983 #if defined(PROFILER)
1984 ScopeTimer
aTimer(TIMER_DRAWPOLYPOLYGON
,this);
1987 if( !xPolyPolygon
.is() )
1988 return ImageCachedPrimitiveSharedPtr();
1990 drawLinePolyPolygon( ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D( xPolyPolygon
),
1995 // TODO(F2): Implement sensible ImageCachedPrimitive
1996 return ImageCachedPrimitiveSharedPtr();
1999 //////////////////////////////////////////////////////////////////////////////////
2000 // Image::strokePolyPolygon
2001 //////////////////////////////////////////////////////////////////////////////////
2003 ImageCachedPrimitiveSharedPtr
Image::strokePolyPolygon(
2004 const uno::Reference
< rendering::XPolyPolygon2D
>& xPolyPolygon
,
2005 const rendering::ViewState
& viewState
,
2006 const rendering::RenderState
& renderState
,
2007 const rendering::StrokeAttributes
& strokeAttributes
)
2009 if( !xPolyPolygon
.is() )
2010 return ImageCachedPrimitiveSharedPtr();
2012 drawLinePolyPolygon( ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D( xPolyPolygon
),
2013 strokeAttributes
.StrokeWidth
,
2017 // TODO(F2): Implement sensible ImageCachedPrimitive
2018 return ImageCachedPrimitiveSharedPtr();
2021 //////////////////////////////////////////////////////////////////////////////////
2022 // Image::strokeTexturedPolyPolygon
2023 //////////////////////////////////////////////////////////////////////////////////
2025 ImageCachedPrimitiveSharedPtr
Image::strokeTexturedPolyPolygon(
2026 const uno::Reference
< rendering::XPolyPolygon2D
>& /*xPolyPolygon*/,
2027 const rendering::ViewState
& /*viewState*/,
2028 const rendering::RenderState
& /*renderState*/,
2029 const uno::Sequence
< rendering::Texture
>& /*textures*/,
2030 const ::std::vector
< ::boost::shared_ptr
<Image
> >& /*textureAnnotations*/,
2031 const rendering::StrokeAttributes
& /*strokeAttributes*/ )
2034 "Image::strokeTexturedPolyPolygon(): NYI" );
2036 // TODO(F2): Implement sensible ImageCachedPrimitive
2037 return ImageCachedPrimitiveSharedPtr();
2040 //////////////////////////////////////////////////////////////////////////////////
2041 // Image::strokeTextureMappedPolyPolygon
2042 //////////////////////////////////////////////////////////////////////////////////
2044 ImageCachedPrimitiveSharedPtr
Image::strokeTextureMappedPolyPolygon(
2045 const uno::Reference
< rendering::XPolyPolygon2D
>& /*xPolyPolygon*/,
2046 const rendering::ViewState
& /*viewState*/,
2047 const rendering::RenderState
& /*renderState*/,
2048 const uno::Sequence
< rendering::Texture
>& /*textures*/,
2049 const ::std::vector
< ::boost::shared_ptr
<Image
> >& /*textureAnnotations*/,
2050 const uno::Reference
< geometry::XMapping2D
>& /*xMapping*/,
2051 const rendering::StrokeAttributes
& /*strokeAttributes*/ )
2054 "Image::strokeTextureMappedPolyPolygon(): NYI" );
2056 // TODO(F2): Implement sensible ImageCachedPrimitive
2057 return ImageCachedPrimitiveSharedPtr();
2060 //////////////////////////////////////////////////////////////////////////////////
2061 // Image::fillPolyPolygon
2062 //////////////////////////////////////////////////////////////////////////////////
2064 template<class pixel_format
>
2065 ImageCachedPrimitiveSharedPtr
Image::fillPolyPolygonImpl(
2066 const ::basegfx::B2DPolyPolygon
& rPolyPolygon
,
2067 const rendering::ViewState
& viewState
,
2068 const rendering::RenderState
& renderState
)
2070 #if defined(PROFILER)
2071 ScopeTimer
aTimer(TIMER_FILLPOLYPOLYGON
,this);
2076 ::basegfx::B2DPolyPolygon
aPolyPolygon(rPolyPolygon
);
2077 setupPolyPolygon( aPolyPolygon
, true, aFillColor
, viewState
, renderState
);
2079 if( !aPolyPolygon
.count() )
2080 return ImageCachedPrimitiveSharedPtr();
2082 pixel_format
pixf(maRenderingBuffer
);
2083 agg::renderer_base
<pixel_format
> renb(pixf
);
2085 // Scanline renderer for solid filling.
2086 agg::renderer_scanline_aa_solid
<agg::renderer_base
<pixel_format
> > ren(renb
);
2088 // Rasterizer & scanline
2089 agg::rasterizer_scanline_aa
<> ras
;
2090 agg::scanline_p8 sl
;
2092 agg::path_storage path
;
2093 agg::conv_curve
<agg::path_storage
> curve(path
);
2095 for(sal_uInt32
nPolygon(0); nPolygon
< aPolyPolygon
.count(); nPolygon
++)
2097 const basegfx::B2DPolygon
aPolygon(aPolyPolygon
.getB2DPolygon(nPolygon
));
2098 const sal_uInt32
nPointCount(aPolygon
.count());
2102 if(aPolygon
.areControlPointsUsed())
2104 // prepare edge-based loop
2105 basegfx::B2DPoint
aCurrentPoint(aPolygon
.getB2DPoint(0));
2106 const sal_uInt32
nEdgeCount(aPolygon
.isClosed() ? nPointCount
- 1 : nPointCount
);
2109 path
.move_to(aCurrentPoint
.getX(), aCurrentPoint
.getY());
2111 for(sal_uInt32
a(0); a
< nEdgeCount
; a
++)
2113 // access next point
2114 const sal_uInt32
nNextIndex((a
+ 1) % nPointCount
);
2115 const basegfx::B2DPoint
aNextPoint(aPolygon
.getB2DPoint(nNextIndex
));
2117 // get control points
2118 const basegfx::B2DPoint
aControlNext(aPolygon
.getNextControlPoint(a
));
2119 const basegfx::B2DPoint
aControlPrev(aPolygon
.getPrevControlPoint(nNextIndex
));
2121 // specify first cp, second cp, next vertex
2123 aControlNext
.getX(), aControlNext
.getY(),
2124 aControlPrev
.getX(), aControlPrev
.getY(),
2125 aNextPoint
.getX(), aNextPoint
.getY());
2127 // prepare next step
2128 aCurrentPoint
= aNextPoint
;
2133 const basegfx::B2DPoint
aPoint(aPolygon
.getB2DPoint(0));
2134 ras
.move_to_d(aPoint
.getX(), aPoint
.getY());
2136 for(sal_uInt32
a(1); a
< nPointCount
; a
++)
2138 const basegfx::B2DPoint
aVertexPoint(aPolygon
.getB2DPoint(a
));
2139 ras
.line_to_d(aVertexPoint
.getX(), aVertexPoint
.getY());
2142 if(aPolygon
.isClosed())
2144 ras
.close_polygon();
2150 ras
.add_path(curve
);
2151 agg::rgba8
fillcolor(aFillColor
.Color
.r
,aFillColor
.Color
.g
,aFillColor
.Color
.b
,aFillColor
.Color
.a
);
2152 ren
.color(fillcolor
);
2153 agg::render_scanlines(ras
, sl
, ren
);
2155 // TODO(F2): Implement sensible ImageCachedPrimitive
2156 return ImageCachedPrimitiveSharedPtr();
2159 //////////////////////////////////////////////////////////////////////////////////
2160 // Image::fillPolyPolygon
2161 //////////////////////////////////////////////////////////////////////////////////
2163 ImageCachedPrimitiveSharedPtr
Image::fillPolyPolygon(
2164 const uno::Reference
< rendering::XPolyPolygon2D
>& xPolyPolygon
,
2165 const rendering::ViewState
& viewState
,
2166 const rendering::RenderState
& renderState
)
2168 if( !xPolyPolygon
.is() )
2169 return ImageCachedPrimitiveSharedPtr();
2171 ::basegfx::B2DPolyPolygon
aPoly(
2172 ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D( xPolyPolygon
) );
2174 switch(maDesc
.eFormat
)
2177 return fillPolyPolygonImpl
<agg::pixfmt_rgb24
>(aPoly
,viewState
,renderState
);
2179 return fillPolyPolygonImpl
<agg::pixfmt_rgba32
>(aPoly
,viewState
,renderState
);
2181 OSL_ENSURE(false, "Unexpected pixel format");
2185 return ImageCachedPrimitiveSharedPtr();
2188 //////////////////////////////////////////////////////////////////////////////////
2189 // Image::fillTexturedPolyPolygon
2190 //////////////////////////////////////////////////////////////////////////////////
2192 ImageCachedPrimitiveSharedPtr
Image::fillTexturedPolyPolygon(
2193 const uno::Reference
< rendering::XPolyPolygon2D
>& xPolyPolygon
,
2194 const rendering::ViewState
& viewState
,
2195 const rendering::RenderState
& renderState
,
2196 const uno::Sequence
< rendering::Texture
>& textures
,
2197 const ::std::vector
< ::boost::shared_ptr
<Image
> >& textureAnnotations
)
2199 #if defined(PROFILER)
2200 ScopeTimer
aTimer(TIMER_FILLTEXTUREDPOLYPOLYGON
,this);
2203 if( !xPolyPolygon
.is() )
2204 return ImageCachedPrimitiveSharedPtr();
2206 ::basegfx::B2DPolyPolygon
aPoly(
2207 ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D( xPolyPolygon
) );
2210 setupPolyPolygon( aPoly
, true, aFillColor
, viewState
, renderState
);
2212 if( !aPoly
.count() )
2213 return ImageCachedPrimitiveSharedPtr();
2215 ::basegfx::B2DHomMatrix aViewTransform
;
2216 ::basegfx::B2DHomMatrix aRenderTransform
;
2217 ::basegfx::B2DHomMatrix aTextureTransform
;
2219 ::basegfx::unotools::homMatrixFromAffineMatrix(aTextureTransform
,
2220 textures
[0].AffineTransform
);
2221 ::basegfx::unotools::homMatrixFromAffineMatrix(aRenderTransform
,
2222 renderState
.AffineTransform
);
2223 ::basegfx::unotools::homMatrixFromAffineMatrix(aViewTransform
,
2224 viewState
.AffineTransform
);
2225 aTextureTransform
*= aRenderTransform
;
2227 // TODO(F1): Multi-texturing
2228 if( textures
[0].Gradient
.is() )
2230 aTextureTransform
*= aViewTransform
;
2232 // try to cast XParametricPolyPolygon2D reference to
2233 // our implementation class.
2234 ::canvas::ParametricPolyPolygon
* pGradient
=
2235 dynamic_cast< ::canvas::ParametricPolyPolygon
* >( textures
[0].Gradient
.get() );
2239 const ParametricPolyPolygon::Values
& rValues(
2240 pGradient
->getValues() );
2242 // TODO: use all the colors and place them on given positions/stops
2243 // TODO(E1): Return value
2244 // TODO(F1): FillRule
2245 fillGradient( rValues
,
2246 rValues
.maColors
[0],
2247 rValues
.maColors
[rValues
.maColors
.getLength () - 1],
2253 else if( textures
[0].Bitmap
.is() )
2255 ImageSharedPtr pTexture
;
2257 if( textureAnnotations
[0].get() != NULL
)
2258 pTexture
= textureAnnotations
[0];
2260 pTexture
.reset( new Image( textures
[0].Bitmap
) );
2262 const sal_uInt32
nWidth(pTexture
->maDesc
.nWidth
);
2263 const sal_uInt32
nHeight(pTexture
->maDesc
.nHeight
);
2265 // scale texture into one-by-one unit rect.
2266 aTextureTransform
.scale(1.0f
/nWidth
,
2269 // TODO(E1): Return value
2270 // TODO(F1): FillRule
2271 return fillTexturedPolyPolygon( *pTexture
,
2278 // TODO(F2): Implement sensible ImageCachedPrimitive
2279 return ImageCachedPrimitiveSharedPtr();
2282 //////////////////////////////////////////////////////////////////////////////////
2283 // Image::fillTextureMappedPolyPolygon
2284 //////////////////////////////////////////////////////////////////////////////////
2286 ImageCachedPrimitiveSharedPtr
Image::fillTextureMappedPolyPolygon(
2287 const uno::Reference
< rendering::XPolyPolygon2D
>& /*xPolyPolygon*/,
2288 const rendering::ViewState
& /*viewState*/,
2289 const rendering::RenderState
& /*renderState*/,
2290 const uno::Sequence
< rendering::Texture
>& /*textures*/,
2291 const ::std::vector
< ::boost::shared_ptr
<Image
> >& /*textureAnnotations*/,
2292 const uno::Reference
< geometry::XMapping2D
>& /*xMapping*/ )
2295 "Image::fillTextureMappedPolyPolygon(): NYI" );
2297 // TODO(F2): Implement sensible ImageCachedPrimitive
2298 return ImageCachedPrimitiveSharedPtr();
2301 //////////////////////////////////////////////////////////////////////////////////
2302 // Image::drawBitmap
2303 //////////////////////////////////////////////////////////////////////////////////
2305 ImageCachedPrimitiveSharedPtr
Image::drawBitmap(
2306 const uno::Reference
< rendering::XBitmap
>& xBitmap
,
2307 const rendering::ViewState
& viewState
,
2308 const rendering::RenderState
& renderState
)
2310 #if defined(PROFILER)
2311 ScopeTimer
aTimer(TIMER_DRAWBITMAP
,this);
2314 // TODO(P3): Implement bitmap caching
2316 return ImageCachedPrimitiveSharedPtr();
2318 XBitmapAccessor accessor( xBitmap );
2319 if(accessor.isValid())
2321 Image aImage( accessor.getDesc() );
2323 implDrawBitmap( aImage,
2327 // TODO(F2): Implement sensible ImageCachedPrimitive
2328 return ImageCachedPrimitiveSharedPtr();
2331 Image
aImage( xBitmap
);
2333 return implDrawBitmap( aImage
,viewState
,renderState
);
2336 //////////////////////////////////////////////////////////////////////////////////
2337 // Image::drawBitmap
2338 //////////////////////////////////////////////////////////////////////////////////
2340 ImageCachedPrimitiveSharedPtr
Image::drawBitmap(
2341 const ImageSharedPtr
& rImage
,
2342 const rendering::ViewState
& viewState
,
2343 const rendering::RenderState
& renderState
)
2345 #if defined(PROFILER)
2346 ScopeTimer
aTimer(TIMER_DRAWBITMAP
,this);
2349 // TODO(P3): Implement bitmap caching
2351 return ImageCachedPrimitiveSharedPtr();
2353 return implDrawBitmap( *rImage
,
2358 //////////////////////////////////////////////////////////////////////////////////
2359 // Image::drawBitmapModulated
2360 //////////////////////////////////////////////////////////////////////////////////
2362 ImageCachedPrimitiveSharedPtr
Image::drawBitmapModulated(
2363 const uno::Reference
< rendering::XBitmap
>& xBitmap
,
2364 const rendering::ViewState
& viewState
,
2365 const rendering::RenderState
& renderState
)
2367 // TODO(P3): Implement bitmap caching
2369 return ImageCachedPrimitiveSharedPtr();
2371 Image
aImage( xBitmap
);
2373 // TODO(F2): Distinguish modulated and unmodulated bitmap output
2374 return implDrawBitmap( aImage
,viewState
,renderState
);
2377 //////////////////////////////////////////////////////////////////////////////////
2378 // Image::drawBitmapModulated
2379 //////////////////////////////////////////////////////////////////////////////////
2381 ImageCachedPrimitiveSharedPtr
Image::drawBitmapModulated(
2382 const ImageSharedPtr
& rImage
,
2383 const rendering::ViewState
& viewState
,
2384 const rendering::RenderState
& renderState
)
2386 // TODO(P3): Implement bitmap caching
2388 return ImageCachedPrimitiveSharedPtr();
2390 // TODO(F2): Distinguish modulated and unmodulated bitmap output
2391 return implDrawBitmap( *rImage
,viewState
,renderState
);