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 10*25ea7f45SAndrew Rist * 11*25ea7f45SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12*25ea7f45SAndrew Rist * 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. 19*25ea7f45SAndrew Rist * 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 <canvas/verbosetrace.hxx> 29cdf0e10cSrcweir #include <canvas/canvastools.hxx> 30cdf0e10cSrcweir #include <tools/diagnose_ex.h> 31cdf0e10cSrcweir 32cdf0e10cSrcweir #include <comphelper/scopeguard.hxx> 33cdf0e10cSrcweir 34cdf0e10cSrcweir #include <basegfx/range/b2drectangle.hxx> 35cdf0e10cSrcweir #include <basegfx/tools/canvastools.hxx> 36cdf0e10cSrcweir 37cdf0e10cSrcweir #include <boost/cast.hpp> 38cdf0e10cSrcweir 39cdf0e10cSrcweir #include "dx_spritecanvashelper.hxx" 40cdf0e10cSrcweir #include "dx_canvascustomsprite.hxx" 41cdf0e10cSrcweir 42cdf0e10cSrcweir #if defined(DX_DEBUG_IMAGES) 43cdf0e10cSrcweir # if OSL_DEBUG_LEVEL > 0 44cdf0e10cSrcweir # include <imdebug.h> 45cdf0e10cSrcweir # undef min 46cdf0e10cSrcweir # undef max 47cdf0e10cSrcweir # endif 48cdf0e10cSrcweir #endif 49cdf0e10cSrcweir 50cdf0e10cSrcweir using namespace ::com::sun::star; 51cdf0e10cSrcweir 52cdf0e10cSrcweir namespace dxcanvas 53cdf0e10cSrcweir { 54cdf0e10cSrcweir namespace 55cdf0e10cSrcweir { 56cdf0e10cSrcweir void repaintBackground( const ::basegfx::B2DRange& rUpdateArea, 57cdf0e10cSrcweir const ::basegfx::B2IRange& rOutputArea, 58cdf0e10cSrcweir const DXSurfaceBitmapSharedPtr& rBackBuffer ) 59cdf0e10cSrcweir { 60cdf0e10cSrcweir // TODO(E1): Use numeric_cast to catch overflow here 61cdf0e10cSrcweir ::basegfx::B2IRange aActualArea( 0, 0, 62cdf0e10cSrcweir static_cast<sal_Int32>(rOutputArea.getWidth()), 63cdf0e10cSrcweir static_cast<sal_Int32>(rOutputArea.getHeight()) ); 64cdf0e10cSrcweir aActualArea.intersect( fround( rUpdateArea ) ); 65cdf0e10cSrcweir 66cdf0e10cSrcweir // repaint the given area of the screen with background content 67cdf0e10cSrcweir rBackBuffer->draw(aActualArea); 68cdf0e10cSrcweir } 69cdf0e10cSrcweir 70cdf0e10cSrcweir void spriteRedraw( const ::canvas::Sprite::Reference& rSprite ) 71cdf0e10cSrcweir { 72cdf0e10cSrcweir // downcast to derived dxcanvas::Sprite interface, which 73cdf0e10cSrcweir // provides the actual redraw methods. 74cdf0e10cSrcweir ::boost::polymorphic_downcast< Sprite* >( 75cdf0e10cSrcweir rSprite.get() )->redraw(); 76cdf0e10cSrcweir } 77cdf0e10cSrcweir 78cdf0e10cSrcweir void spriteRedrawStub( const ::canvas::Sprite::Reference& rSprite ) 79cdf0e10cSrcweir { 80cdf0e10cSrcweir if( rSprite.is() ) 81cdf0e10cSrcweir { 82cdf0e10cSrcweir // downcast to derived dxcanvas::Sprite interface, which 83cdf0e10cSrcweir // provides the actual redraw methods. 84cdf0e10cSrcweir ::boost::polymorphic_downcast< Sprite* >( 85cdf0e10cSrcweir rSprite.get() )->redraw(); 86cdf0e10cSrcweir } 87cdf0e10cSrcweir } 88cdf0e10cSrcweir 89cdf0e10cSrcweir void spriteRedrawStub2( const ::canvas::SpriteRedrawManager::AreaComponent& rComponent ) 90cdf0e10cSrcweir { 91cdf0e10cSrcweir if( rComponent.second.getSprite().is() ) 92cdf0e10cSrcweir { 93cdf0e10cSrcweir // downcast to derived dxcanvas::Sprite interface, which 94cdf0e10cSrcweir // provides the actual redraw methods. 95cdf0e10cSrcweir ::boost::polymorphic_downcast< Sprite* >( 96cdf0e10cSrcweir rComponent.second.getSprite().get() )->redraw(); 97cdf0e10cSrcweir } 98cdf0e10cSrcweir } 99cdf0e10cSrcweir } 100cdf0e10cSrcweir 101cdf0e10cSrcweir SpriteCanvasHelper::SpriteCanvasHelper() : 102cdf0e10cSrcweir mpSpriteSurface( NULL ), 103cdf0e10cSrcweir mpRedrawManager( NULL ), 104cdf0e10cSrcweir mpRenderModule(), 105cdf0e10cSrcweir mpSurfaceProxy(), 106cdf0e10cSrcweir mpBackBuffer(), 107cdf0e10cSrcweir maUpdateRect(), 108cdf0e10cSrcweir maScrapRect(), 109cdf0e10cSrcweir mbShowSpriteBounds( false ) 110cdf0e10cSrcweir { 111cdf0e10cSrcweir #if defined(VERBOSE) && defined(DBG_UTIL) 112cdf0e10cSrcweir // inverse default for verbose debug mode 113cdf0e10cSrcweir mbShowSpriteBounds = true; 114cdf0e10cSrcweir #endif 115cdf0e10cSrcweir } 116cdf0e10cSrcweir 117cdf0e10cSrcweir void SpriteCanvasHelper::init( SpriteCanvas& rParent, 118cdf0e10cSrcweir ::canvas::SpriteRedrawManager& rManager, 119cdf0e10cSrcweir const IDXRenderModuleSharedPtr& rRenderModule, 120cdf0e10cSrcweir const ::canvas::ISurfaceProxyManagerSharedPtr& rSurfaceProxy, 121cdf0e10cSrcweir const DXSurfaceBitmapSharedPtr& rBackBuffer, 122cdf0e10cSrcweir const ::basegfx::B2ISize& rOutputOffset ) 123cdf0e10cSrcweir { 124cdf0e10cSrcweir // init base 125cdf0e10cSrcweir setDevice( rParent ); 126cdf0e10cSrcweir setTarget( rBackBuffer, rOutputOffset ); 127cdf0e10cSrcweir 128cdf0e10cSrcweir mpSpriteSurface = &rParent; 129cdf0e10cSrcweir mpRedrawManager = &rManager; 130cdf0e10cSrcweir mpRenderModule = rRenderModule; 131cdf0e10cSrcweir mpSurfaceProxy = rSurfaceProxy; 132cdf0e10cSrcweir mpBackBuffer = rBackBuffer; 133cdf0e10cSrcweir } 134cdf0e10cSrcweir 135cdf0e10cSrcweir void SpriteCanvasHelper::disposing() 136cdf0e10cSrcweir { 137cdf0e10cSrcweir if(mpRenderModule) 138cdf0e10cSrcweir mpRenderModule->disposing(); 139cdf0e10cSrcweir 140cdf0e10cSrcweir mpBackBuffer.reset(); 141cdf0e10cSrcweir mpRenderModule.reset(); 142cdf0e10cSrcweir mpRedrawManager = NULL; 143cdf0e10cSrcweir mpSpriteSurface = NULL; 144cdf0e10cSrcweir 145cdf0e10cSrcweir // forward to base 146cdf0e10cSrcweir CanvasHelper::disposing(); 147cdf0e10cSrcweir } 148cdf0e10cSrcweir 149cdf0e10cSrcweir uno::Reference< rendering::XAnimatedSprite > SpriteCanvasHelper::createSpriteFromAnimation( 150cdf0e10cSrcweir const uno::Reference< rendering::XAnimation >& /*animation*/ ) 151cdf0e10cSrcweir { 152cdf0e10cSrcweir return uno::Reference< rendering::XAnimatedSprite >(); 153cdf0e10cSrcweir } 154cdf0e10cSrcweir 155cdf0e10cSrcweir uno::Reference< rendering::XAnimatedSprite > SpriteCanvasHelper::createSpriteFromBitmaps( 156cdf0e10cSrcweir const uno::Sequence< uno::Reference< rendering::XBitmap > >& /*animationBitmaps*/, 157cdf0e10cSrcweir sal_Int8 /*interpolationMode*/ ) 158cdf0e10cSrcweir { 159cdf0e10cSrcweir return uno::Reference< rendering::XAnimatedSprite >(); 160cdf0e10cSrcweir } 161cdf0e10cSrcweir 162cdf0e10cSrcweir uno::Reference< rendering::XCustomSprite > SpriteCanvasHelper::createCustomSprite( const geometry::RealSize2D& spriteSize ) 163cdf0e10cSrcweir { 164cdf0e10cSrcweir if( !mpRedrawManager ) 165cdf0e10cSrcweir return uno::Reference< rendering::XCustomSprite >(); // we're disposed 166cdf0e10cSrcweir 167cdf0e10cSrcweir return uno::Reference< rendering::XCustomSprite >( 168cdf0e10cSrcweir new CanvasCustomSprite( spriteSize, 169cdf0e10cSrcweir mpSpriteSurface, 170cdf0e10cSrcweir mpRenderModule, 171cdf0e10cSrcweir mpSurfaceProxy, 172cdf0e10cSrcweir mbShowSpriteBounds ) ); 173cdf0e10cSrcweir } 174cdf0e10cSrcweir 175cdf0e10cSrcweir uno::Reference< rendering::XSprite > SpriteCanvasHelper::createClonedSprite( const uno::Reference< rendering::XSprite >& /*original*/ ) 176cdf0e10cSrcweir { 177cdf0e10cSrcweir return uno::Reference< rendering::XSprite >(); 178cdf0e10cSrcweir } 179cdf0e10cSrcweir 180cdf0e10cSrcweir sal_Bool SpriteCanvasHelper::updateScreen( const ::basegfx::B2IRectangle& rCurrArea, 181cdf0e10cSrcweir sal_Bool bUpdateAll, 182cdf0e10cSrcweir bool& io_bSurfaceDirty ) 183cdf0e10cSrcweir { 184cdf0e10cSrcweir if( !mpRedrawManager || 185cdf0e10cSrcweir !mpRenderModule || 186cdf0e10cSrcweir !mpBackBuffer ) 187cdf0e10cSrcweir { 188cdf0e10cSrcweir return sal_False; // disposed, or otherwise dysfunctional 189cdf0e10cSrcweir } 190cdf0e10cSrcweir 191cdf0e10cSrcweir #if defined(DX_DEBUG_IMAGES) 192cdf0e10cSrcweir # if OSL_DEBUG_LEVEL > 0 193cdf0e10cSrcweir mpBackBuffer->imageDebugger(); 194cdf0e10cSrcweir # endif 195cdf0e10cSrcweir #endif 196cdf0e10cSrcweir 197cdf0e10cSrcweir // store current output area (need to tunnel that to the 198cdf0e10cSrcweir // background, scroll, opaque and general sprite repaint 199cdf0e10cSrcweir // routines) 200cdf0e10cSrcweir maScrapRect = rCurrArea; 201cdf0e10cSrcweir 202cdf0e10cSrcweir // clear area that needs to be blitted to screen beforehand 203cdf0e10cSrcweir maUpdateRect.reset(); 204cdf0e10cSrcweir 205cdf0e10cSrcweir // TODO(P1): Might be worthwile to track areas of background 206cdf0e10cSrcweir // changes, too. 207cdf0e10cSrcweir 208cdf0e10cSrcweir // TODO(P2): Might be worthwhile to use page-flipping only if 209cdf0e10cSrcweir // a certain percentage of screen area has changed - and 210cdf0e10cSrcweir // compose directly to the front buffer otherwise. 211cdf0e10cSrcweir if( !bUpdateAll && !io_bSurfaceDirty ) 212cdf0e10cSrcweir { 213cdf0e10cSrcweir // background has not changed, so we're free to optimize 214cdf0e10cSrcweir // repaint to areas where a sprite has changed 215cdf0e10cSrcweir 216cdf0e10cSrcweir // process each independent area of overlapping sprites 217cdf0e10cSrcweir // separately. 218cdf0e10cSrcweir mpRedrawManager->forEachSpriteArea( *this ); 219cdf0e10cSrcweir 220cdf0e10cSrcweir // flip primary surface to screen 221cdf0e10cSrcweir // ============================== 222cdf0e10cSrcweir 223cdf0e10cSrcweir // perform buffer flipping 224cdf0e10cSrcweir mpRenderModule->flip( maUpdateRect, 225cdf0e10cSrcweir rCurrArea ); 226cdf0e10cSrcweir } 227cdf0e10cSrcweir else 228cdf0e10cSrcweir { 229cdf0e10cSrcweir // limit update to parent window area (ignored for fullscreen) 230cdf0e10cSrcweir // TODO(E1): Use numeric_cast to catch overflow here 231cdf0e10cSrcweir const ::basegfx::B2IRectangle aUpdateArea( 0,0, 232cdf0e10cSrcweir static_cast<sal_Int32>(rCurrArea.getWidth()), 233cdf0e10cSrcweir static_cast<sal_Int32>(rCurrArea.getHeight()) ); 234cdf0e10cSrcweir 235cdf0e10cSrcweir // background has changed, or called requested full 236cdf0e10cSrcweir // update, or we're performing double buffering via page 237cdf0e10cSrcweir // flipping, so we currently have no choice but repaint 238cdf0e10cSrcweir // everything 239cdf0e10cSrcweir 240cdf0e10cSrcweir // repaint the whole screen with background content 241cdf0e10cSrcweir mpBackBuffer->draw(aUpdateArea); 242cdf0e10cSrcweir 243cdf0e10cSrcweir // redraw sprites 244cdf0e10cSrcweir mpRedrawManager->forEachSprite(::std::ptr_fun( &spriteRedraw ) ); 245cdf0e10cSrcweir 246cdf0e10cSrcweir // flip primary surface to screen 247cdf0e10cSrcweir // ============================== 248cdf0e10cSrcweir 249cdf0e10cSrcweir // perform buffer flipping 250cdf0e10cSrcweir mpRenderModule->flip( aUpdateArea, 251cdf0e10cSrcweir rCurrArea ); 252cdf0e10cSrcweir } 253cdf0e10cSrcweir 254cdf0e10cSrcweir // change record vector must be cleared, for the next turn of 255cdf0e10cSrcweir // rendering and sprite changing 256cdf0e10cSrcweir mpRedrawManager->clearChangeRecords(); 257cdf0e10cSrcweir 258cdf0e10cSrcweir io_bSurfaceDirty = false; 259cdf0e10cSrcweir 260cdf0e10cSrcweir return sal_True; 261cdf0e10cSrcweir } 262cdf0e10cSrcweir 263cdf0e10cSrcweir void SpriteCanvasHelper::backgroundPaint( const ::basegfx::B2DRange& rUpdateRect ) 264cdf0e10cSrcweir { 265cdf0e10cSrcweir ENSURE_OR_THROW( mpRenderModule && 266cdf0e10cSrcweir mpBackBuffer, 267cdf0e10cSrcweir "SpriteCanvasHelper::backgroundPaint(): NULL device pointer " ); 268cdf0e10cSrcweir 269cdf0e10cSrcweir repaintBackground( rUpdateRect, 270cdf0e10cSrcweir maScrapRect, 271cdf0e10cSrcweir mpBackBuffer ); 272cdf0e10cSrcweir } 273cdf0e10cSrcweir 274cdf0e10cSrcweir void SpriteCanvasHelper::scrollUpdate( const ::basegfx::B2DRange& /*rMoveStart*/, 275cdf0e10cSrcweir const ::basegfx::B2DRange& rMoveEnd, 276cdf0e10cSrcweir const ::canvas::SpriteRedrawManager::UpdateArea& rUpdateArea ) 277cdf0e10cSrcweir { 278cdf0e10cSrcweir ENSURE_OR_THROW( mpRenderModule && 279cdf0e10cSrcweir mpBackBuffer, 280cdf0e10cSrcweir "SpriteCanvasHelper::scrollUpdate(): NULL device pointer " ); 281cdf0e10cSrcweir 282cdf0e10cSrcweir // round rectangles to integer pixel. Note: have to be 283cdf0e10cSrcweir // extremely careful here, to avoid off-by-one errors for 284cdf0e10cSrcweir // the destination area: otherwise, the next scroll update 285cdf0e10cSrcweir // would copy pixel that are not supposed to be part of 286cdf0e10cSrcweir // the sprite. 287cdf0e10cSrcweir const ::basegfx::B2IRange& rDestRect( 288cdf0e10cSrcweir ::canvas::tools::spritePixelAreaFromB2DRange( rMoveEnd ) ); 289cdf0e10cSrcweir 290cdf0e10cSrcweir // not much sense in really implementing scrollUpdate here, 291cdf0e10cSrcweir // since outputting a sprite only partially would result in 292cdf0e10cSrcweir // expensive clipping. Furthermore, we cannot currently render 293cdf0e10cSrcweir // 3D directly to the front buffer, thus, would have to blit 294cdf0e10cSrcweir // the full sprite area, anyway. But at least optimized in the 295cdf0e10cSrcweir // sense that unnecessary background paints behind the sprites 296cdf0e10cSrcweir // are avoided. 297cdf0e10cSrcweir ::std::for_each( rUpdateArea.maComponentList.begin(), 298cdf0e10cSrcweir rUpdateArea.maComponentList.end(), 299cdf0e10cSrcweir ::std::ptr_fun( &spriteRedrawStub2 ) ); 300cdf0e10cSrcweir 301cdf0e10cSrcweir // repaint uncovered areas from backbuffer - take the 302cdf0e10cSrcweir // _rounded_ rectangles from above, to have the update 303cdf0e10cSrcweir // consistent with the scroll above. 304cdf0e10cSrcweir ::std::vector< ::basegfx::B2DRange > aUncoveredAreas; 305cdf0e10cSrcweir ::basegfx::computeSetDifference( aUncoveredAreas, 306cdf0e10cSrcweir rUpdateArea.maTotalBounds, 307cdf0e10cSrcweir ::basegfx::B2DRange( rDestRect ) ); 308cdf0e10cSrcweir ::std::for_each( aUncoveredAreas.begin(), 309cdf0e10cSrcweir aUncoveredAreas.end(), 310cdf0e10cSrcweir ::boost::bind( &repaintBackground, 311cdf0e10cSrcweir _1, 312cdf0e10cSrcweir ::boost::cref(maScrapRect), 313cdf0e10cSrcweir ::boost::cref(mpBackBuffer) ) ); 314cdf0e10cSrcweir 315cdf0e10cSrcweir // TODO(E1): Use numeric_cast to catch overflow here 316cdf0e10cSrcweir ::basegfx::B2IRange aActualArea( 0, 0, 317cdf0e10cSrcweir static_cast<sal_Int32>(maScrapRect.getWidth()), 318cdf0e10cSrcweir static_cast<sal_Int32>(maScrapRect.getHeight()) ); 319cdf0e10cSrcweir aActualArea.intersect( fround( rUpdateArea.maTotalBounds ) ); 320cdf0e10cSrcweir 321cdf0e10cSrcweir // add given update area to the 'blit to foreground' rect 322cdf0e10cSrcweir maUpdateRect.expand( aActualArea ); 323cdf0e10cSrcweir } 324cdf0e10cSrcweir 325cdf0e10cSrcweir void SpriteCanvasHelper::opaqueUpdate( const ::basegfx::B2DRange& rTotalArea, 326cdf0e10cSrcweir const ::std::vector< ::canvas::Sprite::Reference >& rSortedUpdateSprites ) 327cdf0e10cSrcweir { 328cdf0e10cSrcweir ENSURE_OR_THROW( mpRenderModule && 329cdf0e10cSrcweir mpBackBuffer, 330cdf0e10cSrcweir "SpriteCanvasHelper::opaqueUpdate(): NULL device pointer " ); 331cdf0e10cSrcweir 332cdf0e10cSrcweir // TODO(P2): optimize this by truly rendering to the front 333cdf0e10cSrcweir // buffer. Currently, we've the 3D device only for the back 334cdf0e10cSrcweir // buffer. 335cdf0e10cSrcweir ::std::for_each( rSortedUpdateSprites.begin(), 336cdf0e10cSrcweir rSortedUpdateSprites.end(), 337cdf0e10cSrcweir ::std::ptr_fun( &spriteRedrawStub ) ); 338cdf0e10cSrcweir 339cdf0e10cSrcweir // TODO(E1): Use numeric_cast to catch overflow here 340cdf0e10cSrcweir ::basegfx::B2IRange aActualArea( 0, 0, 341cdf0e10cSrcweir static_cast<sal_Int32>(maScrapRect.getWidth()), 342cdf0e10cSrcweir static_cast<sal_Int32>(maScrapRect.getHeight()) ); 343cdf0e10cSrcweir aActualArea.intersect( fround( rTotalArea ) ); 344cdf0e10cSrcweir 345cdf0e10cSrcweir // add given update area to the 'blit to foreground' rect 346cdf0e10cSrcweir maUpdateRect.expand( aActualArea ); 347cdf0e10cSrcweir } 348cdf0e10cSrcweir 349cdf0e10cSrcweir void SpriteCanvasHelper::genericUpdate( const ::basegfx::B2DRange& rTotalArea, 350cdf0e10cSrcweir const ::std::vector< ::canvas::Sprite::Reference >& rSortedUpdateSprites ) 351cdf0e10cSrcweir { 352cdf0e10cSrcweir ENSURE_OR_THROW( mpRenderModule && 353cdf0e10cSrcweir mpBackBuffer, 354cdf0e10cSrcweir "SpriteCanvasHelper::genericUpdate(): NULL device pointer " ); 355cdf0e10cSrcweir 356cdf0e10cSrcweir // paint background 357cdf0e10cSrcweir // ================ 358cdf0e10cSrcweir 359cdf0e10cSrcweir // TODO(E1): Use numeric_cast to catch overflow here 360cdf0e10cSrcweir ::basegfx::B2IRange aActualArea( 0, 0, 361cdf0e10cSrcweir static_cast<sal_Int32>(maScrapRect.getWidth()), 362cdf0e10cSrcweir static_cast<sal_Int32>(maScrapRect.getHeight()) ); 363cdf0e10cSrcweir aActualArea.intersect( fround( rTotalArea ) ); 364cdf0e10cSrcweir 365cdf0e10cSrcweir // repaint the given area of the screen with background content 366cdf0e10cSrcweir mpBackBuffer->draw(aActualArea); 367cdf0e10cSrcweir 368cdf0e10cSrcweir // paint sprite 369cdf0e10cSrcweir // ============ 370cdf0e10cSrcweir 371cdf0e10cSrcweir ::std::for_each( rSortedUpdateSprites.begin(), 372cdf0e10cSrcweir rSortedUpdateSprites.end(), 373cdf0e10cSrcweir ::std::ptr_fun( &spriteRedrawStub ) ); 374cdf0e10cSrcweir 375cdf0e10cSrcweir // add given update area to the 'blit to foreground' rect 376cdf0e10cSrcweir maUpdateRect.expand( aActualArea ); 377cdf0e10cSrcweir } 378cdf0e10cSrcweir } 379