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