xref: /AOO41X/main/canvas/source/vcl/spritehelper.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1*cdf0e10cSrcweir /*************************************************************************
2*cdf0e10cSrcweir  *
3*cdf0e10cSrcweir  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*cdf0e10cSrcweir  *
5*cdf0e10cSrcweir  * Copyright 2000, 2010 Oracle and/or its affiliates.
6*cdf0e10cSrcweir  *
7*cdf0e10cSrcweir  * OpenOffice.org - a multi-platform office productivity suite
8*cdf0e10cSrcweir  *
9*cdf0e10cSrcweir  * This file is part of OpenOffice.org.
10*cdf0e10cSrcweir  *
11*cdf0e10cSrcweir  * OpenOffice.org is free software: you can redistribute it and/or modify
12*cdf0e10cSrcweir  * it under the terms of the GNU Lesser General Public License version 3
13*cdf0e10cSrcweir  * only, as published by the Free Software Foundation.
14*cdf0e10cSrcweir  *
15*cdf0e10cSrcweir  * OpenOffice.org is distributed in the hope that it will be useful,
16*cdf0e10cSrcweir  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*cdf0e10cSrcweir  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*cdf0e10cSrcweir  * GNU Lesser General Public License version 3 for more details
19*cdf0e10cSrcweir  * (a copy is included in the LICENSE file that accompanied this code).
20*cdf0e10cSrcweir  *
21*cdf0e10cSrcweir  * You should have received a copy of the GNU Lesser General Public License
22*cdf0e10cSrcweir  * version 3 along with OpenOffice.org.  If not, see
23*cdf0e10cSrcweir  * <http://www.openoffice.org/license.html>
24*cdf0e10cSrcweir  * for a copy of the LGPLv3 License.
25*cdf0e10cSrcweir  *
26*cdf0e10cSrcweir  ************************************************************************/
27*cdf0e10cSrcweir 
28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
29*cdf0e10cSrcweir #include "precompiled_canvas.hxx"
30*cdf0e10cSrcweir 
31*cdf0e10cSrcweir #include <canvas/debug.hxx>
32*cdf0e10cSrcweir #include <tools/diagnose_ex.h>
33*cdf0e10cSrcweir #include <canvas/verbosetrace.hxx>
34*cdf0e10cSrcweir 
35*cdf0e10cSrcweir #include <rtl/math.hxx>
36*cdf0e10cSrcweir 
37*cdf0e10cSrcweir #include <vcl/outdev.hxx>
38*cdf0e10cSrcweir #include <vcl/bitmap.hxx>
39*cdf0e10cSrcweir #include <vcl/alpha.hxx>
40*cdf0e10cSrcweir #include <vcl/bitmapex.hxx>
41*cdf0e10cSrcweir #include <vcl/canvastools.hxx>
42*cdf0e10cSrcweir 
43*cdf0e10cSrcweir #include <basegfx/matrix/b2dhommatrix.hxx>
44*cdf0e10cSrcweir #include <basegfx/point/b2dpoint.hxx>
45*cdf0e10cSrcweir #include <basegfx/tools/canvastools.hxx>
46*cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygon.hxx>
47*cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygontools.hxx>
48*cdf0e10cSrcweir #include <basegfx/polygon/b2dpolypolygontools.hxx>
49*cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygoncutandtouch.hxx>
50*cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygontriangulator.hxx>
51*cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygonclipper.hxx>
52*cdf0e10cSrcweir #include <basegfx/numeric/ftools.hxx>
53*cdf0e10cSrcweir 
54*cdf0e10cSrcweir #include <canvas/canvastools.hxx>
55*cdf0e10cSrcweir 
56*cdf0e10cSrcweir #include "spritehelper.hxx"
57*cdf0e10cSrcweir 
58*cdf0e10cSrcweir using namespace ::com::sun::star;
59*cdf0e10cSrcweir 
60*cdf0e10cSrcweir 
61*cdf0e10cSrcweir namespace vclcanvas
62*cdf0e10cSrcweir {
63*cdf0e10cSrcweir     SpriteHelper::SpriteHelper() :
64*cdf0e10cSrcweir         mpBackBuffer(),
65*cdf0e10cSrcweir         mpBackBufferMask(),
66*cdf0e10cSrcweir         maContent(),
67*cdf0e10cSrcweir         mbShowSpriteBounds(false)
68*cdf0e10cSrcweir     {
69*cdf0e10cSrcweir     }
70*cdf0e10cSrcweir 
71*cdf0e10cSrcweir     void SpriteHelper::init( const geometry::RealSize2D&               rSpriteSize,
72*cdf0e10cSrcweir                              const ::canvas::SpriteSurface::Reference& rOwningSpriteCanvas,
73*cdf0e10cSrcweir                              const BackBufferSharedPtr&                rBackBuffer,
74*cdf0e10cSrcweir                              const BackBufferSharedPtr&                rBackBufferMask,
75*cdf0e10cSrcweir                              bool                                      bShowSpriteBounds )
76*cdf0e10cSrcweir     {
77*cdf0e10cSrcweir         ENSURE_OR_THROW( rOwningSpriteCanvas.get() && rBackBuffer && rBackBufferMask,
78*cdf0e10cSrcweir                          "SpriteHelper::init(): Invalid sprite canvas or back buffer" );
79*cdf0e10cSrcweir 
80*cdf0e10cSrcweir         mpBackBuffer 		= rBackBuffer;
81*cdf0e10cSrcweir         mpBackBufferMask 	= rBackBufferMask;
82*cdf0e10cSrcweir         mbShowSpriteBounds 	= bShowSpriteBounds;
83*cdf0e10cSrcweir 
84*cdf0e10cSrcweir         init( rSpriteSize, rOwningSpriteCanvas );
85*cdf0e10cSrcweir     }
86*cdf0e10cSrcweir 
87*cdf0e10cSrcweir     void SpriteHelper::disposing()
88*cdf0e10cSrcweir     {
89*cdf0e10cSrcweir         mpBackBuffer.reset();
90*cdf0e10cSrcweir         mpBackBufferMask.reset();
91*cdf0e10cSrcweir 
92*cdf0e10cSrcweir         // forward to parent
93*cdf0e10cSrcweir         CanvasCustomSpriteHelper::disposing();
94*cdf0e10cSrcweir     }
95*cdf0e10cSrcweir 
96*cdf0e10cSrcweir     void SpriteHelper::redraw( OutputDevice&                rTargetSurface,
97*cdf0e10cSrcweir                                const ::basegfx::B2DPoint&	rPos,
98*cdf0e10cSrcweir                                bool& 						io_bSurfacesDirty,
99*cdf0e10cSrcweir                                bool                         bBufferedUpdate ) const
100*cdf0e10cSrcweir     {
101*cdf0e10cSrcweir         (void)bBufferedUpdate; // not used on every platform
102*cdf0e10cSrcweir 
103*cdf0e10cSrcweir         if( !mpBackBuffer ||
104*cdf0e10cSrcweir             !mpBackBufferMask )
105*cdf0e10cSrcweir         {
106*cdf0e10cSrcweir             return; // we're disposed
107*cdf0e10cSrcweir         }
108*cdf0e10cSrcweir 
109*cdf0e10cSrcweir         // log output pos in device pixel
110*cdf0e10cSrcweir         VERBOSE_TRACE( "SpriteHelper::redraw(): output pos is (%f, %f)",
111*cdf0e10cSrcweir                        rPos.getX(),
112*cdf0e10cSrcweir                        rPos.getY() );
113*cdf0e10cSrcweir 
114*cdf0e10cSrcweir         const double fAlpha( getAlpha() );
115*cdf0e10cSrcweir 
116*cdf0e10cSrcweir         if( isActive() &&
117*cdf0e10cSrcweir             !::basegfx::fTools::equalZero( fAlpha ) )
118*cdf0e10cSrcweir         {
119*cdf0e10cSrcweir             const Point					aEmptyPoint;
120*cdf0e10cSrcweir             const ::basegfx::B2DVector&	rOrigOutputSize( getSizePixel() );
121*cdf0e10cSrcweir 
122*cdf0e10cSrcweir             // might get changed below (e.g. adapted for
123*cdf0e10cSrcweir             // transformations). IMPORTANT: both position and size are
124*cdf0e10cSrcweir             // rounded to integer values. From now on, only those
125*cdf0e10cSrcweir             // rounded values are used, to keep clip and content in
126*cdf0e10cSrcweir             // sync.
127*cdf0e10cSrcweir             ::Size 	aOutputSize( ::vcl::unotools::sizeFromB2DSize( rOrigOutputSize ) );
128*cdf0e10cSrcweir             ::Point	aOutPos( ::vcl::unotools::pointFromB2DPoint( rPos ) );
129*cdf0e10cSrcweir 
130*cdf0e10cSrcweir 
131*cdf0e10cSrcweir             // TODO(F3): Support for alpha-VDev
132*cdf0e10cSrcweir 
133*cdf0e10cSrcweir             // Do we have to update our bitmaps (necessary if virdev
134*cdf0e10cSrcweir             // was painted to, or transformation changed)?
135*cdf0e10cSrcweir             const bool bNeedBitmapUpdate( io_bSurfacesDirty ||
136*cdf0e10cSrcweir                                           hasTransformChanged() ||
137*cdf0e10cSrcweir                                           maContent->IsEmpty() );
138*cdf0e10cSrcweir 
139*cdf0e10cSrcweir             // updating content of sprite cache - surface is no
140*cdf0e10cSrcweir             // longer dirty in relation to our cache
141*cdf0e10cSrcweir             io_bSurfacesDirty = false;
142*cdf0e10cSrcweir             transformUpdated();
143*cdf0e10cSrcweir 
144*cdf0e10cSrcweir             if( bNeedBitmapUpdate )
145*cdf0e10cSrcweir             {
146*cdf0e10cSrcweir                 Bitmap aBmp( mpBackBuffer->getOutDev().GetBitmap( aEmptyPoint,
147*cdf0e10cSrcweir                                                                   aOutputSize ) );
148*cdf0e10cSrcweir 
149*cdf0e10cSrcweir                 if( isContentFullyOpaque() )
150*cdf0e10cSrcweir                 {
151*cdf0e10cSrcweir                     // optimized case: content canvas is fully
152*cdf0e10cSrcweir                     // opaque. Note: since we retrieved aBmp directly
153*cdf0e10cSrcweir                     // from an OutDev, it's already a 'display bitmap'
154*cdf0e10cSrcweir                     // on windows.
155*cdf0e10cSrcweir                     maContent = BitmapEx( aBmp );
156*cdf0e10cSrcweir                 }
157*cdf0e10cSrcweir                 else
158*cdf0e10cSrcweir                 {
159*cdf0e10cSrcweir                     // sprite content might contain alpha, create
160*cdf0e10cSrcweir                     // BmpEx, then.
161*cdf0e10cSrcweir                     Bitmap aMask( mpBackBufferMask->getOutDev().GetBitmap( aEmptyPoint,
162*cdf0e10cSrcweir                                                                            aOutputSize ) );
163*cdf0e10cSrcweir 
164*cdf0e10cSrcweir 					// bitmasks are much faster than alphamasks on some platforms
165*cdf0e10cSrcweir 					// so convert to bitmask if useful
166*cdf0e10cSrcweir #ifndef QUARTZ
167*cdf0e10cSrcweir                     if( aMask.GetBitCount() != 1 )
168*cdf0e10cSrcweir                     {
169*cdf0e10cSrcweir                         OSL_ENSURE(false,
170*cdf0e10cSrcweir                                    "CanvasCustomSprite::redraw(): Mask bitmap is not "
171*cdf0e10cSrcweir                                    "monochrome (performance!)");
172*cdf0e10cSrcweir                         aMask.MakeMono(255);
173*cdf0e10cSrcweir                     }
174*cdf0e10cSrcweir #endif
175*cdf0e10cSrcweir 
176*cdf0e10cSrcweir                     // Note: since we retrieved aBmp and aMask
177*cdf0e10cSrcweir                     // directly from an OutDev, it's already a
178*cdf0e10cSrcweir                     // 'display bitmap' on windows.
179*cdf0e10cSrcweir                     maContent = BitmapEx( aBmp, aMask );
180*cdf0e10cSrcweir                 }
181*cdf0e10cSrcweir             }
182*cdf0e10cSrcweir 
183*cdf0e10cSrcweir             ::basegfx::B2DHomMatrix aTransform( getTransformation() );
184*cdf0e10cSrcweir 
185*cdf0e10cSrcweir             // check whether matrix is "easy" to handle - pure
186*cdf0e10cSrcweir             // translations or scales are handled by OutputDevice
187*cdf0e10cSrcweir             // alone
188*cdf0e10cSrcweir             const bool bIdentityTransform( aTransform.isIdentity() );
189*cdf0e10cSrcweir 
190*cdf0e10cSrcweir             // make transformation absolute (put sprite to final
191*cdf0e10cSrcweir             // output position). Need to happen here, as we also have
192*cdf0e10cSrcweir             // to translate the clip polygon
193*cdf0e10cSrcweir             aTransform.translate( aOutPos.X(),
194*cdf0e10cSrcweir                                   aOutPos.Y() );
195*cdf0e10cSrcweir 
196*cdf0e10cSrcweir             if( !bIdentityTransform )
197*cdf0e10cSrcweir             {
198*cdf0e10cSrcweir                 if( !::basegfx::fTools::equalZero( aTransform.get(0,1) ) ||
199*cdf0e10cSrcweir                     !::basegfx::fTools::equalZero( aTransform.get(1,0) ) )
200*cdf0e10cSrcweir                 {
201*cdf0e10cSrcweir                     // "complex" transformation, employ affine
202*cdf0e10cSrcweir                     // transformator
203*cdf0e10cSrcweir 
204*cdf0e10cSrcweir                     // modify output position, to account for the fact
205*cdf0e10cSrcweir                     // that transformBitmap() always normalizes its output
206*cdf0e10cSrcweir                     // bitmap into the smallest enclosing box.
207*cdf0e10cSrcweir                     ::basegfx::B2DRectangle	aDestRect;
208*cdf0e10cSrcweir                     ::canvas::tools::calcTransformedRectBounds( aDestRect,
209*cdf0e10cSrcweir                                                                 ::basegfx::B2DRectangle(0,
210*cdf0e10cSrcweir                                                                                         0,
211*cdf0e10cSrcweir                                                                                         rOrigOutputSize.getX(),
212*cdf0e10cSrcweir                                                                                         rOrigOutputSize.getY()),
213*cdf0e10cSrcweir                                                                 aTransform );
214*cdf0e10cSrcweir 
215*cdf0e10cSrcweir                     aOutPos.X() = ::basegfx::fround( aDestRect.getMinX() );
216*cdf0e10cSrcweir                     aOutPos.Y() = ::basegfx::fround( aDestRect.getMinY() );
217*cdf0e10cSrcweir 
218*cdf0e10cSrcweir                     // TODO(P3): Use optimized bitmap transformation here.
219*cdf0e10cSrcweir 
220*cdf0e10cSrcweir                     // actually re-create the bitmap ONLY if necessary
221*cdf0e10cSrcweir                     if( bNeedBitmapUpdate )
222*cdf0e10cSrcweir                         maContent = tools::transformBitmap( *maContent,
223*cdf0e10cSrcweir                                                             aTransform,
224*cdf0e10cSrcweir                                                             uno::Sequence<double>(),
225*cdf0e10cSrcweir                                                             tools::MODULATE_NONE );
226*cdf0e10cSrcweir 
227*cdf0e10cSrcweir                     aOutputSize = maContent->GetSizePixel();
228*cdf0e10cSrcweir                 }
229*cdf0e10cSrcweir                 else
230*cdf0e10cSrcweir                 {
231*cdf0e10cSrcweir                     // relatively 'simplistic' transformation -
232*cdf0e10cSrcweir                     // retrieve scale and translational offset
233*cdf0e10cSrcweir                     aOutputSize.setWidth (
234*cdf0e10cSrcweir                         ::basegfx::fround( rOrigOutputSize.getX() * aTransform.get(0,0) ) );
235*cdf0e10cSrcweir                     aOutputSize.setHeight(
236*cdf0e10cSrcweir                         ::basegfx::fround( rOrigOutputSize.getY() * aTransform.get(1,1) ) );
237*cdf0e10cSrcweir 
238*cdf0e10cSrcweir                     aOutPos.X() = ::basegfx::fround( aTransform.get(0,2) );
239*cdf0e10cSrcweir                     aOutPos.Y() = ::basegfx::fround( aTransform.get(1,2) );
240*cdf0e10cSrcweir                 }
241*cdf0e10cSrcweir             }
242*cdf0e10cSrcweir 
243*cdf0e10cSrcweir             // transformBitmap() might return empty bitmaps, for tiny
244*cdf0e10cSrcweir             // scales.
245*cdf0e10cSrcweir             if( !!(*maContent) )
246*cdf0e10cSrcweir             {
247*cdf0e10cSrcweir                 // when true, fast path for slide transition has
248*cdf0e10cSrcweir                 // already redrawn the sprite.
249*cdf0e10cSrcweir                 bool bSpriteRedrawn( false );
250*cdf0e10cSrcweir 
251*cdf0e10cSrcweir                 rTargetSurface.Push( PUSH_CLIPREGION );
252*cdf0e10cSrcweir 
253*cdf0e10cSrcweir                 // apply clip (if any)
254*cdf0e10cSrcweir                 if( getClip().is() )
255*cdf0e10cSrcweir                 {
256*cdf0e10cSrcweir                     ::basegfx::B2DPolyPolygon aClipPoly(
257*cdf0e10cSrcweir                         ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(
258*cdf0e10cSrcweir                             getClip() ));
259*cdf0e10cSrcweir 
260*cdf0e10cSrcweir                     if( aClipPoly.count() )
261*cdf0e10cSrcweir                     {
262*cdf0e10cSrcweir 						// aTransform already contains the
263*cdf0e10cSrcweir                         // translational component, moving the clip to
264*cdf0e10cSrcweir                         // the final sprite output position.
265*cdf0e10cSrcweir                         aClipPoly.transform( aTransform );
266*cdf0e10cSrcweir 
267*cdf0e10cSrcweir #if ! defined WNT && ! defined QUARTZ
268*cdf0e10cSrcweir                         // non-Windows only - bAtLeastOnePolygon is
269*cdf0e10cSrcweir                         // only used in non-WNT code below
270*cdf0e10cSrcweir 
271*cdf0e10cSrcweir                         // check whether maybe the clip consists
272*cdf0e10cSrcweir                         // solely out of rectangular polygons. If this
273*cdf0e10cSrcweir                         // is the case, enforce using the triangle
274*cdf0e10cSrcweir                         // clip region setup - non-optimized X11
275*cdf0e10cSrcweir                         // drivers tend to perform abyssmally on
276*cdf0e10cSrcweir                         // XPolygonRegion, which is used internally,
277*cdf0e10cSrcweir                         // when filling complex polypolygons.
278*cdf0e10cSrcweir                         bool bAtLeastOnePolygon( false );
279*cdf0e10cSrcweir                         const sal_Int32 nPolygons( aClipPoly.count() );
280*cdf0e10cSrcweir 
281*cdf0e10cSrcweir                         for( sal_Int32 i=0; i<nPolygons; ++i )
282*cdf0e10cSrcweir                         {
283*cdf0e10cSrcweir                             if( !::basegfx::tools::isRectangle(
284*cdf0e10cSrcweir                                     aClipPoly.getB2DPolygon(i)) )
285*cdf0e10cSrcweir                             {
286*cdf0e10cSrcweir                                 bAtLeastOnePolygon = true;
287*cdf0e10cSrcweir                                 break;
288*cdf0e10cSrcweir                             }
289*cdf0e10cSrcweir                         }
290*cdf0e10cSrcweir #endif
291*cdf0e10cSrcweir 
292*cdf0e10cSrcweir                         if( mbShowSpriteBounds )
293*cdf0e10cSrcweir                         {
294*cdf0e10cSrcweir                             // Paint green sprite clip area
295*cdf0e10cSrcweir                             rTargetSurface.SetLineColor( Color( 0,255,0 ) );
296*cdf0e10cSrcweir                             rTargetSurface.SetFillColor();
297*cdf0e10cSrcweir 
298*cdf0e10cSrcweir                             rTargetSurface.DrawPolyPolygon(PolyPolygon(aClipPoly)); // #i76339#
299*cdf0e10cSrcweir                         }
300*cdf0e10cSrcweir 
301*cdf0e10cSrcweir #if ! defined WNT && ! defined QUARTZ
302*cdf0e10cSrcweir                         // as a matter of fact, this fast path only
303*cdf0e10cSrcweir                         // performs well for X11 - under Windows, the
304*cdf0e10cSrcweir                         // clip via SetTriangleClipRegion is faster.
305*cdf0e10cSrcweir                         if( bAtLeastOnePolygon &&
306*cdf0e10cSrcweir                             bBufferedUpdate &&
307*cdf0e10cSrcweir                             ::rtl::math::approxEqual(fAlpha, 1.0) &&
308*cdf0e10cSrcweir                             !maContent->IsTransparent() )
309*cdf0e10cSrcweir                         {
310*cdf0e10cSrcweir                             // fast path for slide transitions
311*cdf0e10cSrcweir                             // (buffered, no alpha, no mask (because
312*cdf0e10cSrcweir                             // full slide is contained in the sprite))
313*cdf0e10cSrcweir 
314*cdf0e10cSrcweir                             // XOR bitmap onto backbuffer, clear area
315*cdf0e10cSrcweir                             // that should be _visible_ with black,
316*cdf0e10cSrcweir                             // XOR bitmap again on top of that -
317*cdf0e10cSrcweir                             // result: XOR cancels out where no black
318*cdf0e10cSrcweir                             // has been rendered, and yields the
319*cdf0e10cSrcweir                             // original bitmap, where black is
320*cdf0e10cSrcweir                             // underneath.
321*cdf0e10cSrcweir                             rTargetSurface.Push( PUSH_RASTEROP );
322*cdf0e10cSrcweir                             rTargetSurface.SetRasterOp( ROP_XOR );
323*cdf0e10cSrcweir                             rTargetSurface.DrawBitmap( aOutPos,
324*cdf0e10cSrcweir                                                        aOutputSize,
325*cdf0e10cSrcweir                                                        maContent->GetBitmap() );
326*cdf0e10cSrcweir 
327*cdf0e10cSrcweir                             rTargetSurface.SetLineColor();
328*cdf0e10cSrcweir                             rTargetSurface.SetFillColor( COL_BLACK );
329*cdf0e10cSrcweir                             rTargetSurface.SetRasterOp( ROP_0 );
330*cdf0e10cSrcweir                             rTargetSurface.DrawPolyPolygon(PolyPolygon(aClipPoly)); // #i76339#
331*cdf0e10cSrcweir 
332*cdf0e10cSrcweir                             rTargetSurface.SetRasterOp( ROP_XOR );
333*cdf0e10cSrcweir                             rTargetSurface.DrawBitmap( aOutPos,
334*cdf0e10cSrcweir                                                        aOutputSize,
335*cdf0e10cSrcweir                                                        maContent->GetBitmap() );
336*cdf0e10cSrcweir 
337*cdf0e10cSrcweir                             rTargetSurface.Pop();
338*cdf0e10cSrcweir 
339*cdf0e10cSrcweir                             bSpriteRedrawn = true;
340*cdf0e10cSrcweir                         }
341*cdf0e10cSrcweir                         else
342*cdf0e10cSrcweir #endif
343*cdf0e10cSrcweir                         {
344*cdf0e10cSrcweir                             Region aClipRegion( aClipPoly );
345*cdf0e10cSrcweir                             rTargetSurface.SetClipRegion( aClipRegion );
346*cdf0e10cSrcweir                         }
347*cdf0e10cSrcweir                     }
348*cdf0e10cSrcweir                 }
349*cdf0e10cSrcweir 
350*cdf0e10cSrcweir                 if( !bSpriteRedrawn )
351*cdf0e10cSrcweir                 {
352*cdf0e10cSrcweir                     if( ::rtl::math::approxEqual(fAlpha, 1.0) )
353*cdf0e10cSrcweir                     {
354*cdf0e10cSrcweir                         // no alpha modulation -> just copy to output
355*cdf0e10cSrcweir                         if( maContent->IsTransparent() )
356*cdf0e10cSrcweir                             rTargetSurface.DrawBitmapEx( aOutPos, aOutputSize, *maContent );
357*cdf0e10cSrcweir                         else
358*cdf0e10cSrcweir                             rTargetSurface.DrawBitmap( aOutPos, aOutputSize, maContent->GetBitmap() );
359*cdf0e10cSrcweir                     }
360*cdf0e10cSrcweir                     else
361*cdf0e10cSrcweir                     {
362*cdf0e10cSrcweir                         // TODO(P3): Switch to OutputDevice::DrawTransparent()
363*cdf0e10cSrcweir                         // here
364*cdf0e10cSrcweir 
365*cdf0e10cSrcweir                         // draw semi-transparent
366*cdf0e10cSrcweir                         sal_uInt8 nColor( static_cast<sal_uInt8>( ::basegfx::fround( 255.0*(1.0 - fAlpha) + .5) ) );
367*cdf0e10cSrcweir                         AlphaMask aAlpha( maContent->GetSizePixel(),
368*cdf0e10cSrcweir                                           &nColor );
369*cdf0e10cSrcweir 
370*cdf0e10cSrcweir                         // mask out fully transparent areas
371*cdf0e10cSrcweir                         if( maContent->IsTransparent() )
372*cdf0e10cSrcweir                             aAlpha.Replace( maContent->GetMask(), 255 );
373*cdf0e10cSrcweir 
374*cdf0e10cSrcweir                         // alpha-blend to output
375*cdf0e10cSrcweir                         rTargetSurface.DrawBitmapEx( aOutPos, aOutputSize,
376*cdf0e10cSrcweir                                                      BitmapEx( maContent->GetBitmap(),
377*cdf0e10cSrcweir                                                                aAlpha ) );
378*cdf0e10cSrcweir                     }
379*cdf0e10cSrcweir                 }
380*cdf0e10cSrcweir 
381*cdf0e10cSrcweir                 rTargetSurface.Pop();
382*cdf0e10cSrcweir 
383*cdf0e10cSrcweir                 if( mbShowSpriteBounds )
384*cdf0e10cSrcweir                 {
385*cdf0e10cSrcweir                     ::PolyPolygon aMarkerPoly(
386*cdf0e10cSrcweir                         ::canvas::tools::getBoundMarksPolyPolygon(
387*cdf0e10cSrcweir                             ::basegfx::B2DRectangle(aOutPos.X(),
388*cdf0e10cSrcweir                                                     aOutPos.Y(),
389*cdf0e10cSrcweir                                                     aOutPos.X() + aOutputSize.Width()-1,
390*cdf0e10cSrcweir                                                     aOutPos.Y() + aOutputSize.Height()-1) ) );
391*cdf0e10cSrcweir 
392*cdf0e10cSrcweir                     // Paint little red sprite area markers
393*cdf0e10cSrcweir                     rTargetSurface.SetLineColor( COL_RED );
394*cdf0e10cSrcweir                     rTargetSurface.SetFillColor();
395*cdf0e10cSrcweir 
396*cdf0e10cSrcweir                     for( int i=0; i<aMarkerPoly.Count(); ++i )
397*cdf0e10cSrcweir                     {
398*cdf0e10cSrcweir                         rTargetSurface.DrawPolyLine( aMarkerPoly.GetObject((sal_uInt16)i) );
399*cdf0e10cSrcweir                     }
400*cdf0e10cSrcweir 
401*cdf0e10cSrcweir                     // paint sprite prio
402*cdf0e10cSrcweir                     Font aVCLFont;
403*cdf0e10cSrcweir                     aVCLFont.SetHeight( std::min(long(20),aOutputSize.Height()) );
404*cdf0e10cSrcweir                     aVCLFont.SetColor( COL_RED );
405*cdf0e10cSrcweir 
406*cdf0e10cSrcweir                     rTargetSurface.SetTextAlign(ALIGN_TOP);
407*cdf0e10cSrcweir                     rTargetSurface.SetTextColor( COL_RED );
408*cdf0e10cSrcweir                     rTargetSurface.SetFont( aVCLFont );
409*cdf0e10cSrcweir 
410*cdf0e10cSrcweir                     ::rtl::OUString text( ::rtl::math::doubleToUString( getPriority(),
411*cdf0e10cSrcweir                                                                         rtl_math_StringFormat_F,
412*cdf0e10cSrcweir                                                                         2,'.',NULL,' ') );
413*cdf0e10cSrcweir 
414*cdf0e10cSrcweir                     rTargetSurface.DrawText( aOutPos+Point(2,2), text );
415*cdf0e10cSrcweir 
416*cdf0e10cSrcweir #if defined(VERBOSE) && OSL_DEBUG_LEVEL > 0
417*cdf0e10cSrcweir                     OSL_TRACE( "SpriteHelper::redraw(): sprite %X has prio %f\n",
418*cdf0e10cSrcweir                                this, getPriority() );
419*cdf0e10cSrcweir #endif
420*cdf0e10cSrcweir                 }
421*cdf0e10cSrcweir             }
422*cdf0e10cSrcweir         }
423*cdf0e10cSrcweir     }
424*cdf0e10cSrcweir 
425*cdf0e10cSrcweir     ::basegfx::B2DPolyPolygon SpriteHelper::polyPolygonFromXPolyPolygon2D( uno::Reference< rendering::XPolyPolygon2D >& xPoly ) const
426*cdf0e10cSrcweir     {
427*cdf0e10cSrcweir         return ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D( xPoly );
428*cdf0e10cSrcweir     }
429*cdf0e10cSrcweir 
430*cdf0e10cSrcweir }
431