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