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