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