1*25ea7f45SAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 3*25ea7f45SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 4*25ea7f45SAndrew Rist * or more contributor license agreements. See the NOTICE file 5*25ea7f45SAndrew Rist * distributed with this work for additional information 6*25ea7f45SAndrew Rist * regarding copyright ownership. The ASF licenses this file 7*25ea7f45SAndrew Rist * to you under the Apache License, Version 2.0 (the 8*25ea7f45SAndrew Rist * "License"); you may not use this file except in compliance 9*25ea7f45SAndrew Rist * with the License. You may obtain a copy of the License at 10cdf0e10cSrcweir * 11*25ea7f45SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12cdf0e10cSrcweir * 13*25ea7f45SAndrew Rist * Unless required by applicable law or agreed to in writing, 14*25ea7f45SAndrew Rist * software distributed under the License is distributed on an 15*25ea7f45SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*25ea7f45SAndrew Rist * KIND, either express or implied. See the License for the 17*25ea7f45SAndrew Rist * specific language governing permissions and limitations 18*25ea7f45SAndrew Rist * under the License. 19cdf0e10cSrcweir * 20*25ea7f45SAndrew Rist *************************************************************/ 21*25ea7f45SAndrew Rist 22*25ea7f45SAndrew 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 { 59cdf0e10cSrcweir SpriteHelper::SpriteHelper() : 60cdf0e10cSrcweir mpBackBuffer(), 61cdf0e10cSrcweir mpBackBufferMask(), 62cdf0e10cSrcweir maContent(), 63cdf0e10cSrcweir mbShowSpriteBounds(false) 64cdf0e10cSrcweir { 65cdf0e10cSrcweir } 66cdf0e10cSrcweir 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 83cdf0e10cSrcweir void SpriteHelper::disposing() 84cdf0e10cSrcweir { 85cdf0e10cSrcweir mpBackBuffer.reset(); 86cdf0e10cSrcweir mpBackBufferMask.reset(); 87cdf0e10cSrcweir 88cdf0e10cSrcweir // forward to parent 89cdf0e10cSrcweir CanvasCustomSpriteHelper::disposing(); 90cdf0e10cSrcweir } 91cdf0e10cSrcweir 92cdf0e10cSrcweir 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 162cdf0e10cSrcweir #ifndef QUARTZ 163cdf0e10cSrcweir if( aMask.GetBitCount() != 1 ) 164cdf0e10cSrcweir { 165cdf0e10cSrcweir OSL_ENSURE(false, 166cdf0e10cSrcweir "CanvasCustomSprite::redraw(): Mask bitmap is not " 167cdf0e10cSrcweir "monochrome (performance!)"); 168cdf0e10cSrcweir aMask.MakeMono(255); 169cdf0e10cSrcweir } 170cdf0e10cSrcweir #endif 171cdf0e10cSrcweir 172cdf0e10cSrcweir // Note: since we retrieved aBmp and aMask 173cdf0e10cSrcweir // directly from an OutDev, it's already a 174cdf0e10cSrcweir // 'display bitmap' on windows. 175cdf0e10cSrcweir maContent = BitmapEx( aBmp, aMask ); 176cdf0e10cSrcweir } 177cdf0e10cSrcweir } 178cdf0e10cSrcweir 179cdf0e10cSrcweir ::basegfx::B2DHomMatrix aTransform( getTransformation() ); 180cdf0e10cSrcweir 181cdf0e10cSrcweir // check whether matrix is "easy" to handle - pure 182cdf0e10cSrcweir // translations or scales are handled by OutputDevice 183cdf0e10cSrcweir // alone 184cdf0e10cSrcweir const bool bIdentityTransform( aTransform.isIdentity() ); 185cdf0e10cSrcweir 186cdf0e10cSrcweir // make transformation absolute (put sprite to final 187cdf0e10cSrcweir // output position). Need to happen here, as we also have 188cdf0e10cSrcweir // to translate the clip polygon 189cdf0e10cSrcweir aTransform.translate( aOutPos.X(), 190cdf0e10cSrcweir aOutPos.Y() ); 191cdf0e10cSrcweir 192cdf0e10cSrcweir if( !bIdentityTransform ) 193cdf0e10cSrcweir { 194cdf0e10cSrcweir if( !::basegfx::fTools::equalZero( aTransform.get(0,1) ) || 195cdf0e10cSrcweir !::basegfx::fTools::equalZero( aTransform.get(1,0) ) ) 196cdf0e10cSrcweir { 197cdf0e10cSrcweir // "complex" transformation, employ affine 198cdf0e10cSrcweir // transformator 199cdf0e10cSrcweir 200cdf0e10cSrcweir // modify output position, to account for the fact 201cdf0e10cSrcweir // that transformBitmap() always normalizes its output 202cdf0e10cSrcweir // bitmap into the smallest enclosing box. 203cdf0e10cSrcweir ::basegfx::B2DRectangle aDestRect; 204cdf0e10cSrcweir ::canvas::tools::calcTransformedRectBounds( aDestRect, 205cdf0e10cSrcweir ::basegfx::B2DRectangle(0, 206cdf0e10cSrcweir 0, 207cdf0e10cSrcweir rOrigOutputSize.getX(), 208cdf0e10cSrcweir rOrigOutputSize.getY()), 209cdf0e10cSrcweir aTransform ); 210cdf0e10cSrcweir 211cdf0e10cSrcweir aOutPos.X() = ::basegfx::fround( aDestRect.getMinX() ); 212cdf0e10cSrcweir aOutPos.Y() = ::basegfx::fround( aDestRect.getMinY() ); 213cdf0e10cSrcweir 214cdf0e10cSrcweir // TODO(P3): Use optimized bitmap transformation here. 215cdf0e10cSrcweir 216cdf0e10cSrcweir // actually re-create the bitmap ONLY if necessary 217cdf0e10cSrcweir if( bNeedBitmapUpdate ) 218cdf0e10cSrcweir maContent = tools::transformBitmap( *maContent, 219cdf0e10cSrcweir aTransform, 220cdf0e10cSrcweir uno::Sequence<double>(), 221cdf0e10cSrcweir tools::MODULATE_NONE ); 222cdf0e10cSrcweir 223cdf0e10cSrcweir aOutputSize = maContent->GetSizePixel(); 224cdf0e10cSrcweir } 225cdf0e10cSrcweir else 226cdf0e10cSrcweir { 227cdf0e10cSrcweir // relatively 'simplistic' transformation - 228cdf0e10cSrcweir // retrieve scale and translational offset 229cdf0e10cSrcweir aOutputSize.setWidth ( 230cdf0e10cSrcweir ::basegfx::fround( rOrigOutputSize.getX() * aTransform.get(0,0) ) ); 231cdf0e10cSrcweir aOutputSize.setHeight( 232cdf0e10cSrcweir ::basegfx::fround( rOrigOutputSize.getY() * aTransform.get(1,1) ) ); 233cdf0e10cSrcweir 234cdf0e10cSrcweir aOutPos.X() = ::basegfx::fround( aTransform.get(0,2) ); 235cdf0e10cSrcweir aOutPos.Y() = ::basegfx::fround( aTransform.get(1,2) ); 236cdf0e10cSrcweir } 237cdf0e10cSrcweir } 238cdf0e10cSrcweir 239cdf0e10cSrcweir // transformBitmap() might return empty bitmaps, for tiny 240cdf0e10cSrcweir // scales. 241cdf0e10cSrcweir if( !!(*maContent) ) 242cdf0e10cSrcweir { 243cdf0e10cSrcweir // when true, fast path for slide transition has 244cdf0e10cSrcweir // already redrawn the sprite. 245cdf0e10cSrcweir bool bSpriteRedrawn( false ); 246cdf0e10cSrcweir 247cdf0e10cSrcweir rTargetSurface.Push( PUSH_CLIPREGION ); 248cdf0e10cSrcweir 249cdf0e10cSrcweir // apply clip (if any) 250cdf0e10cSrcweir if( getClip().is() ) 251cdf0e10cSrcweir { 252cdf0e10cSrcweir ::basegfx::B2DPolyPolygon aClipPoly( 253cdf0e10cSrcweir ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D( 254cdf0e10cSrcweir getClip() )); 255cdf0e10cSrcweir 256cdf0e10cSrcweir if( aClipPoly.count() ) 257cdf0e10cSrcweir { 258cdf0e10cSrcweir // aTransform already contains the 259cdf0e10cSrcweir // translational component, moving the clip to 260cdf0e10cSrcweir // the final sprite output position. 261cdf0e10cSrcweir aClipPoly.transform( aTransform ); 262cdf0e10cSrcweir 263cdf0e10cSrcweir #if ! defined WNT && ! defined QUARTZ 264cdf0e10cSrcweir // non-Windows only - bAtLeastOnePolygon is 265cdf0e10cSrcweir // only used in non-WNT code below 266cdf0e10cSrcweir 267cdf0e10cSrcweir // check whether maybe the clip consists 268cdf0e10cSrcweir // solely out of rectangular polygons. If this 269cdf0e10cSrcweir // is the case, enforce using the triangle 270cdf0e10cSrcweir // clip region setup - non-optimized X11 271cdf0e10cSrcweir // drivers tend to perform abyssmally on 272cdf0e10cSrcweir // XPolygonRegion, which is used internally, 273cdf0e10cSrcweir // when filling complex polypolygons. 274cdf0e10cSrcweir bool bAtLeastOnePolygon( false ); 275cdf0e10cSrcweir const sal_Int32 nPolygons( aClipPoly.count() ); 276cdf0e10cSrcweir 277cdf0e10cSrcweir for( sal_Int32 i=0; i<nPolygons; ++i ) 278cdf0e10cSrcweir { 279cdf0e10cSrcweir if( !::basegfx::tools::isRectangle( 280cdf0e10cSrcweir aClipPoly.getB2DPolygon(i)) ) 281cdf0e10cSrcweir { 282cdf0e10cSrcweir bAtLeastOnePolygon = true; 283cdf0e10cSrcweir break; 284cdf0e10cSrcweir } 285cdf0e10cSrcweir } 286cdf0e10cSrcweir #endif 287cdf0e10cSrcweir 288cdf0e10cSrcweir if( mbShowSpriteBounds ) 289cdf0e10cSrcweir { 290cdf0e10cSrcweir // Paint green sprite clip area 291cdf0e10cSrcweir rTargetSurface.SetLineColor( Color( 0,255,0 ) ); 292cdf0e10cSrcweir rTargetSurface.SetFillColor(); 293cdf0e10cSrcweir 294cdf0e10cSrcweir rTargetSurface.DrawPolyPolygon(PolyPolygon(aClipPoly)); // #i76339# 295cdf0e10cSrcweir } 296cdf0e10cSrcweir 297cdf0e10cSrcweir #if ! defined WNT && ! defined QUARTZ 298cdf0e10cSrcweir // as a matter of fact, this fast path only 299cdf0e10cSrcweir // performs well for X11 - under Windows, the 300cdf0e10cSrcweir // clip via SetTriangleClipRegion is faster. 301cdf0e10cSrcweir if( bAtLeastOnePolygon && 302cdf0e10cSrcweir bBufferedUpdate && 303cdf0e10cSrcweir ::rtl::math::approxEqual(fAlpha, 1.0) && 304cdf0e10cSrcweir !maContent->IsTransparent() ) 305cdf0e10cSrcweir { 306cdf0e10cSrcweir // fast path for slide transitions 307cdf0e10cSrcweir // (buffered, no alpha, no mask (because 308cdf0e10cSrcweir // full slide is contained in the sprite)) 309cdf0e10cSrcweir 310cdf0e10cSrcweir // XOR bitmap onto backbuffer, clear area 311cdf0e10cSrcweir // that should be _visible_ with black, 312cdf0e10cSrcweir // XOR bitmap again on top of that - 313cdf0e10cSrcweir // result: XOR cancels out where no black 314cdf0e10cSrcweir // has been rendered, and yields the 315cdf0e10cSrcweir // original bitmap, where black is 316cdf0e10cSrcweir // underneath. 317cdf0e10cSrcweir rTargetSurface.Push( PUSH_RASTEROP ); 318cdf0e10cSrcweir rTargetSurface.SetRasterOp( ROP_XOR ); 319cdf0e10cSrcweir rTargetSurface.DrawBitmap( aOutPos, 320cdf0e10cSrcweir aOutputSize, 321cdf0e10cSrcweir maContent->GetBitmap() ); 322cdf0e10cSrcweir 323cdf0e10cSrcweir rTargetSurface.SetLineColor(); 324cdf0e10cSrcweir rTargetSurface.SetFillColor( COL_BLACK ); 325cdf0e10cSrcweir rTargetSurface.SetRasterOp( ROP_0 ); 326cdf0e10cSrcweir rTargetSurface.DrawPolyPolygon(PolyPolygon(aClipPoly)); // #i76339# 327cdf0e10cSrcweir 328cdf0e10cSrcweir rTargetSurface.SetRasterOp( ROP_XOR ); 329cdf0e10cSrcweir rTargetSurface.DrawBitmap( aOutPos, 330cdf0e10cSrcweir aOutputSize, 331cdf0e10cSrcweir maContent->GetBitmap() ); 332cdf0e10cSrcweir 333cdf0e10cSrcweir rTargetSurface.Pop(); 334cdf0e10cSrcweir 335cdf0e10cSrcweir bSpriteRedrawn = true; 336cdf0e10cSrcweir } 337cdf0e10cSrcweir else 338cdf0e10cSrcweir #endif 339cdf0e10cSrcweir { 340cdf0e10cSrcweir Region aClipRegion( aClipPoly ); 341cdf0e10cSrcweir rTargetSurface.SetClipRegion( aClipRegion ); 342cdf0e10cSrcweir } 343cdf0e10cSrcweir } 344cdf0e10cSrcweir } 345cdf0e10cSrcweir 346cdf0e10cSrcweir if( !bSpriteRedrawn ) 347cdf0e10cSrcweir { 348cdf0e10cSrcweir if( ::rtl::math::approxEqual(fAlpha, 1.0) ) 349cdf0e10cSrcweir { 350cdf0e10cSrcweir // no alpha modulation -> just copy to output 351cdf0e10cSrcweir if( maContent->IsTransparent() ) 352cdf0e10cSrcweir rTargetSurface.DrawBitmapEx( aOutPos, aOutputSize, *maContent ); 353cdf0e10cSrcweir else 354cdf0e10cSrcweir rTargetSurface.DrawBitmap( aOutPos, aOutputSize, maContent->GetBitmap() ); 355cdf0e10cSrcweir } 356cdf0e10cSrcweir else 357cdf0e10cSrcweir { 358cdf0e10cSrcweir // TODO(P3): Switch to OutputDevice::DrawTransparent() 359cdf0e10cSrcweir // here 360cdf0e10cSrcweir 361cdf0e10cSrcweir // draw semi-transparent 362cdf0e10cSrcweir sal_uInt8 nColor( static_cast<sal_uInt8>( ::basegfx::fround( 255.0*(1.0 - fAlpha) + .5) ) ); 363cdf0e10cSrcweir AlphaMask aAlpha( maContent->GetSizePixel(), 364cdf0e10cSrcweir &nColor ); 365cdf0e10cSrcweir 366cdf0e10cSrcweir // mask out fully transparent areas 367cdf0e10cSrcweir if( maContent->IsTransparent() ) 368cdf0e10cSrcweir aAlpha.Replace( maContent->GetMask(), 255 ); 369cdf0e10cSrcweir 370cdf0e10cSrcweir // alpha-blend to output 371cdf0e10cSrcweir rTargetSurface.DrawBitmapEx( aOutPos, aOutputSize, 372cdf0e10cSrcweir BitmapEx( maContent->GetBitmap(), 373cdf0e10cSrcweir aAlpha ) ); 374cdf0e10cSrcweir } 375cdf0e10cSrcweir } 376cdf0e10cSrcweir 377cdf0e10cSrcweir rTargetSurface.Pop(); 378cdf0e10cSrcweir 379cdf0e10cSrcweir if( mbShowSpriteBounds ) 380cdf0e10cSrcweir { 381cdf0e10cSrcweir ::PolyPolygon aMarkerPoly( 382cdf0e10cSrcweir ::canvas::tools::getBoundMarksPolyPolygon( 383cdf0e10cSrcweir ::basegfx::B2DRectangle(aOutPos.X(), 384cdf0e10cSrcweir aOutPos.Y(), 385cdf0e10cSrcweir aOutPos.X() + aOutputSize.Width()-1, 386cdf0e10cSrcweir aOutPos.Y() + aOutputSize.Height()-1) ) ); 387cdf0e10cSrcweir 388cdf0e10cSrcweir // Paint little red sprite area markers 389cdf0e10cSrcweir rTargetSurface.SetLineColor( COL_RED ); 390cdf0e10cSrcweir rTargetSurface.SetFillColor(); 391cdf0e10cSrcweir 392cdf0e10cSrcweir for( int i=0; i<aMarkerPoly.Count(); ++i ) 393cdf0e10cSrcweir { 394cdf0e10cSrcweir rTargetSurface.DrawPolyLine( aMarkerPoly.GetObject((sal_uInt16)i) ); 395cdf0e10cSrcweir } 396cdf0e10cSrcweir 397cdf0e10cSrcweir // paint sprite prio 398cdf0e10cSrcweir Font aVCLFont; 399cdf0e10cSrcweir aVCLFont.SetHeight( std::min(long(20),aOutputSize.Height()) ); 400cdf0e10cSrcweir aVCLFont.SetColor( COL_RED ); 401cdf0e10cSrcweir 402cdf0e10cSrcweir rTargetSurface.SetTextAlign(ALIGN_TOP); 403cdf0e10cSrcweir rTargetSurface.SetTextColor( COL_RED ); 404cdf0e10cSrcweir rTargetSurface.SetFont( aVCLFont ); 405cdf0e10cSrcweir 406cdf0e10cSrcweir ::rtl::OUString text( ::rtl::math::doubleToUString( getPriority(), 407cdf0e10cSrcweir rtl_math_StringFormat_F, 408cdf0e10cSrcweir 2,'.',NULL,' ') ); 409cdf0e10cSrcweir 410cdf0e10cSrcweir rTargetSurface.DrawText( aOutPos+Point(2,2), text ); 411cdf0e10cSrcweir 412cdf0e10cSrcweir #if defined(VERBOSE) && OSL_DEBUG_LEVEL > 0 413cdf0e10cSrcweir OSL_TRACE( "SpriteHelper::redraw(): sprite %X has prio %f\n", 414cdf0e10cSrcweir this, getPriority() ); 415cdf0e10cSrcweir #endif 416cdf0e10cSrcweir } 417cdf0e10cSrcweir } 418cdf0e10cSrcweir } 419cdf0e10cSrcweir } 420cdf0e10cSrcweir 421cdf0e10cSrcweir ::basegfx::B2DPolyPolygon SpriteHelper::polyPolygonFromXPolyPolygon2D( uno::Reference< rendering::XPolyPolygon2D >& xPoly ) const 422cdf0e10cSrcweir { 423cdf0e10cSrcweir return ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D( xPoly ); 424cdf0e10cSrcweir } 425cdf0e10cSrcweir 426cdf0e10cSrcweir } 427