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 #include "precompiled_slideshow.hxx"
28*cdf0e10cSrcweir 
29*cdf0e10cSrcweir #include <canvas/debug.hxx>
30*cdf0e10cSrcweir #include <tools/diagnose_ex.h>
31*cdf0e10cSrcweir #include <canvas/canvastools.hxx>
32*cdf0e10cSrcweir 
33*cdf0e10cSrcweir #include "eventqueue.hxx"
34*cdf0e10cSrcweir #include "eventmultiplexer.hxx"
35*cdf0e10cSrcweir #include "slideview.hxx"
36*cdf0e10cSrcweir #include "delayevent.hxx"
37*cdf0e10cSrcweir #include "unoview.hxx"
38*cdf0e10cSrcweir 
39*cdf0e10cSrcweir #include <rtl/instance.hxx>
40*cdf0e10cSrcweir #include <cppuhelper/basemutex.hxx>
41*cdf0e10cSrcweir #include <cppuhelper/compbase2.hxx>
42*cdf0e10cSrcweir #include <cppuhelper/implementationentry.hxx>
43*cdf0e10cSrcweir #include <cppuhelper/interfacecontainer.h>
44*cdf0e10cSrcweir #include <comphelper/make_shared_from_uno.hxx>
45*cdf0e10cSrcweir 
46*cdf0e10cSrcweir #include <cppcanvas/spritecanvas.hxx>
47*cdf0e10cSrcweir #include <cppcanvas/customsprite.hxx>
48*cdf0e10cSrcweir #include <cppcanvas/vclfactory.hxx>
49*cdf0e10cSrcweir #include <cppcanvas/basegfxfactory.hxx>
50*cdf0e10cSrcweir 
51*cdf0e10cSrcweir #include <tools/debug.hxx>
52*cdf0e10cSrcweir 
53*cdf0e10cSrcweir #include <basegfx/range/b1drange.hxx>
54*cdf0e10cSrcweir #include <basegfx/range/b2drange.hxx>
55*cdf0e10cSrcweir #include <basegfx/range/b2irange.hxx>
56*cdf0e10cSrcweir #include <basegfx/point/b2dpoint.hxx>
57*cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygon.hxx>
58*cdf0e10cSrcweir #include <basegfx/matrix/b2dhommatrix.hxx>
59*cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygontools.hxx>
60*cdf0e10cSrcweir #include <basegfx/polygon/b2dpolypolygontools.hxx>
61*cdf0e10cSrcweir #include <basegfx/tools/canvastools.hxx>
62*cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygonclipper.hxx>
63*cdf0e10cSrcweir #include <basegfx/polygon/b2dpolypolygoncutter.hxx>
64*cdf0e10cSrcweir 
65*cdf0e10cSrcweir #include <com/sun/star/presentation/XSlideShow.hpp>
66*cdf0e10cSrcweir 
67*cdf0e10cSrcweir #include <boost/noncopyable.hpp>
68*cdf0e10cSrcweir #include <boost/bind.hpp>
69*cdf0e10cSrcweir #include <boost/weak_ptr.hpp>
70*cdf0e10cSrcweir 
71*cdf0e10cSrcweir #include <vector>
72*cdf0e10cSrcweir #include <iterator>
73*cdf0e10cSrcweir #include <algorithm>
74*cdf0e10cSrcweir 
75*cdf0e10cSrcweir using namespace com::sun::star;
76*cdf0e10cSrcweir 
77*cdf0e10cSrcweir namespace slideshow {
78*cdf0e10cSrcweir namespace internal {
79*cdf0e10cSrcweir 
80*cdf0e10cSrcweir namespace {
81*cdf0e10cSrcweir 
82*cdf0e10cSrcweir struct StaticUnitRectPoly : public rtl::StaticWithInit<basegfx::B2DPolygon, StaticUnitRectPoly>
83*cdf0e10cSrcweir {
84*cdf0e10cSrcweir     basegfx::B2DPolygon operator()()
85*cdf0e10cSrcweir     {
86*cdf0e10cSrcweir         return basegfx::tools::createUnitPolygon();
87*cdf0e10cSrcweir     }
88*cdf0e10cSrcweir };
89*cdf0e10cSrcweir 
90*cdf0e10cSrcweir /** Sprite entry, to store sprite plus priority
91*cdf0e10cSrcweir 
92*cdf0e10cSrcweir     The operator<() defines a strict weak ordering of sprites, sort
93*cdf0e10cSrcweir     key is the sprite priority.
94*cdf0e10cSrcweir  */
95*cdf0e10cSrcweir struct SpriteEntry
96*cdf0e10cSrcweir {
97*cdf0e10cSrcweir     SpriteEntry( const cppcanvas::CustomSpriteSharedPtr& rSprite,
98*cdf0e10cSrcweir                  double                                  nPrio ) :
99*cdf0e10cSrcweir         mpSprite( rSprite ),
100*cdf0e10cSrcweir         mnPriority( nPrio )
101*cdf0e10cSrcweir     {
102*cdf0e10cSrcweir     }
103*cdf0e10cSrcweir 
104*cdf0e10cSrcweir     bool operator<(const SpriteEntry& rRHS) const
105*cdf0e10cSrcweir     {
106*cdf0e10cSrcweir         return mnPriority < rRHS.mnPriority;
107*cdf0e10cSrcweir     }
108*cdf0e10cSrcweir 
109*cdf0e10cSrcweir     boost::weak_ptr< cppcanvas::CustomSprite > mpSprite;
110*cdf0e10cSrcweir     double                                     mnPriority;
111*cdf0e10cSrcweir };
112*cdf0e10cSrcweir 
113*cdf0e10cSrcweir typedef std::vector< SpriteEntry > SpriteVector;
114*cdf0e10cSrcweir 
115*cdf0e10cSrcweir 
116*cdf0e10cSrcweir /** Create a clip polygon for slide views
117*cdf0e10cSrcweir 
118*cdf0e10cSrcweir     @param rClip
119*cdf0e10cSrcweir     Clip to set (can be empty)
120*cdf0e10cSrcweir 
121*cdf0e10cSrcweir     @param rCanvas
122*cdf0e10cSrcweir     Canvas to create the clip polygon for
123*cdf0e10cSrcweir 
124*cdf0e10cSrcweir     @param rUserSize
125*cdf0e10cSrcweir     The size of the view. Note that the returned clip will
126*cdf0e10cSrcweir     <em>always</em> clip to at least the rect defined herein.
127*cdf0e10cSrcweir 
128*cdf0e10cSrcweir     @return the view clip polygon, in view coordinates, which is
129*cdf0e10cSrcweir     guaranteed to at least clip to the view size.
130*cdf0e10cSrcweir  */
131*cdf0e10cSrcweir basegfx::B2DPolyPolygon createClipPolygon( const basegfx::B2DPolyPolygon&    rClip,
132*cdf0e10cSrcweir                                            const cppcanvas::CanvasSharedPtr& /*rCanvas*/,
133*cdf0e10cSrcweir                                            const basegfx::B2DSize&           rUserSize )
134*cdf0e10cSrcweir {
135*cdf0e10cSrcweir     // setup canvas clipping
136*cdf0e10cSrcweir     // =====================
137*cdf0e10cSrcweir 
138*cdf0e10cSrcweir     // AW: Simplified
139*cdf0e10cSrcweir 	const basegfx::B2DRange aClipRange(0, 0, rUserSize.getX(), rUserSize.getY());
140*cdf0e10cSrcweir 
141*cdf0e10cSrcweir     if(rClip.count())
142*cdf0e10cSrcweir     {
143*cdf0e10cSrcweir     	return basegfx::tools::clipPolyPolygonOnRange(rClip, aClipRange, true, false);
144*cdf0e10cSrcweir     }
145*cdf0e10cSrcweir     else
146*cdf0e10cSrcweir     {
147*cdf0e10cSrcweir         return basegfx::B2DPolyPolygon(basegfx::tools::createPolygonFromRect(aClipRange));
148*cdf0e10cSrcweir     }
149*cdf0e10cSrcweir }
150*cdf0e10cSrcweir 
151*cdf0e10cSrcweir /** Prepare given clip polygon to be stored as the current clip
152*cdf0e10cSrcweir 
153*cdf0e10cSrcweir     Note that this is separate from createClipPolygon(), to allow
154*cdf0e10cSrcweir     SlideView implementations to store this intermediate result
155*cdf0e10cSrcweir     (createClipPolygon() has to be called every time the view size
156*cdf0e10cSrcweir     changes)
157*cdf0e10cSrcweir  */
158*cdf0e10cSrcweir basegfx::B2DPolyPolygon prepareClip( const basegfx::B2DPolyPolygon& rClip )
159*cdf0e10cSrcweir {
160*cdf0e10cSrcweir     basegfx::B2DPolyPolygon aClip( rClip );
161*cdf0e10cSrcweir 
162*cdf0e10cSrcweir     // TODO(P2): unnecessary, once XCanvas is correctly handling this
163*cdf0e10cSrcweir     // AW: Should be no longer necessary; tools are now bezier-safe
164*cdf0e10cSrcweir     if( aClip.areControlPointsUsed() )
165*cdf0e10cSrcweir         aClip = basegfx::tools::adaptiveSubdivideByAngle( aClip );
166*cdf0e10cSrcweir 
167*cdf0e10cSrcweir     // normalize polygon, preparation for clipping
168*cdf0e10cSrcweir     // in updateCanvas()
169*cdf0e10cSrcweir     aClip = basegfx::tools::correctOrientations(aClip);
170*cdf0e10cSrcweir     aClip = basegfx::tools::solveCrossovers(aClip);
171*cdf0e10cSrcweir     aClip = basegfx::tools::stripNeutralPolygons(aClip);
172*cdf0e10cSrcweir     aClip = basegfx::tools::stripDispensablePolygons(aClip, false);
173*cdf0e10cSrcweir 
174*cdf0e10cSrcweir     return aClip;
175*cdf0e10cSrcweir }
176*cdf0e10cSrcweir 
177*cdf0e10cSrcweir 
178*cdf0e10cSrcweir void clearRect( ::cppcanvas::CanvasSharedPtr const& pCanvas,
179*cdf0e10cSrcweir                 basegfx::B2IRange const&            rArea )
180*cdf0e10cSrcweir {
181*cdf0e10cSrcweir     // convert clip polygon to device coordinate system
182*cdf0e10cSrcweir     ::basegfx::B2DPolyPolygon const* pClipPoly( pCanvas->getClip() );
183*cdf0e10cSrcweir     if( pClipPoly )
184*cdf0e10cSrcweir     {
185*cdf0e10cSrcweir         ::basegfx::B2DPolyPolygon aClipPoly( *pClipPoly );
186*cdf0e10cSrcweir         aClipPoly.transform( pCanvas->getTransformation() );
187*cdf0e10cSrcweir         pCanvas->setClip( aClipPoly );
188*cdf0e10cSrcweir     }
189*cdf0e10cSrcweir 
190*cdf0e10cSrcweir     // set transformation to identitiy (->device pixel)
191*cdf0e10cSrcweir     pCanvas->setTransformation( ::basegfx::B2DHomMatrix() );
192*cdf0e10cSrcweir 
193*cdf0e10cSrcweir     // #i42440# Fill the _full_ background in
194*cdf0e10cSrcweir     // black. Since we had to extend the bitmap by one
195*cdf0e10cSrcweir     // pixel, and the bitmap is initialized white,
196*cdf0e10cSrcweir     // depending on the slide content a one pixel wide
197*cdf0e10cSrcweir     // line will show to the bottom and the right.
198*cdf0e10cSrcweir     const ::basegfx::B2DPolygon aPoly(
199*cdf0e10cSrcweir         ::basegfx::tools::createPolygonFromRect(
200*cdf0e10cSrcweir             basegfx::B2DRange(rArea)));
201*cdf0e10cSrcweir 
202*cdf0e10cSrcweir     ::cppcanvas::PolyPolygonSharedPtr pPolyPoly(
203*cdf0e10cSrcweir         ::cppcanvas::BaseGfxFactory::getInstance().createPolyPolygon( pCanvas,
204*cdf0e10cSrcweir                                                                       aPoly ) );
205*cdf0e10cSrcweir 
206*cdf0e10cSrcweir     if( pPolyPoly )
207*cdf0e10cSrcweir     {
208*cdf0e10cSrcweir         pPolyPoly->setCompositeOp( cppcanvas::CanvasGraphic::SOURCE );
209*cdf0e10cSrcweir         pPolyPoly->setRGBAFillColor( 0x00000000U );
210*cdf0e10cSrcweir         pPolyPoly->draw();
211*cdf0e10cSrcweir     }
212*cdf0e10cSrcweir 
213*cdf0e10cSrcweir #if defined(VERBOSE) && defined(DBG_UTIL)
214*cdf0e10cSrcweir     ::cppcanvas::CanvasSharedPtr pCliplessCanvas( pCanvas->clone() );
215*cdf0e10cSrcweir     pCliplessCanvas->setClip();
216*cdf0e10cSrcweir 
217*cdf0e10cSrcweir     if( pCanvas->getClip() )
218*cdf0e10cSrcweir     {
219*cdf0e10cSrcweir         ::cppcanvas::PolyPolygonSharedPtr pPolyPoly2(
220*cdf0e10cSrcweir             ::cppcanvas::BaseGfxFactory::getInstance().createPolyPolygon( pCliplessCanvas,
221*cdf0e10cSrcweir                                                                           *(pCanvas->getClip()) ));
222*cdf0e10cSrcweir         if( pPolyPoly2 )
223*cdf0e10cSrcweir         {
224*cdf0e10cSrcweir             pPolyPoly2->setRGBALineColor( 0x008000FFU );
225*cdf0e10cSrcweir             pPolyPoly2->draw();
226*cdf0e10cSrcweir         }
227*cdf0e10cSrcweir     }
228*cdf0e10cSrcweir #endif
229*cdf0e10cSrcweir }
230*cdf0e10cSrcweir 
231*cdf0e10cSrcweir /** Get bounds in pixel
232*cdf0e10cSrcweir 
233*cdf0e10cSrcweir     @param rLayerBounds
234*cdf0e10cSrcweir     Bound rect, in user space coordinates
235*cdf0e10cSrcweir 
236*cdf0e10cSrcweir     @param rTransformation
237*cdf0e10cSrcweir     User space to device pixel transformation
238*cdf0e10cSrcweir 
239*cdf0e10cSrcweir     @return the layer bounds in pixel, extended by one pixel to the
240*cdf0e10cSrcweir     right and bottom
241*cdf0e10cSrcweir  */
242*cdf0e10cSrcweir basegfx::B2IRange getLayerBoundsPixel( basegfx::B2DRange const&     rLayerBounds,
243*cdf0e10cSrcweir                                        basegfx::B2DHomMatrix const& rTransformation )
244*cdf0e10cSrcweir {
245*cdf0e10cSrcweir     ::basegfx::B2DRange aTmpRect;
246*cdf0e10cSrcweir     ::canvas::tools::calcTransformedRectBounds( aTmpRect,
247*cdf0e10cSrcweir                                                 rLayerBounds,
248*cdf0e10cSrcweir                                                 rTransformation );
249*cdf0e10cSrcweir 
250*cdf0e10cSrcweir     if( aTmpRect.isEmpty() )
251*cdf0e10cSrcweir         return ::basegfx::B2IRange();
252*cdf0e10cSrcweir 
253*cdf0e10cSrcweir     // #i42440# Returned layer size is one pixel too small, as
254*cdf0e10cSrcweir     // rendering happens one pixel to the right and below the
255*cdf0e10cSrcweir     // actual bound rect.
256*cdf0e10cSrcweir     return ::basegfx::B2IRange( ::basegfx::fround(aTmpRect.getMinX()),
257*cdf0e10cSrcweir                                 ::basegfx::fround(aTmpRect.getMinY()),
258*cdf0e10cSrcweir                                 ::basegfx::fround(aTmpRect.getMaxX()) + 1,
259*cdf0e10cSrcweir                                 ::basegfx::fround(aTmpRect.getMaxY()) + 1 );
260*cdf0e10cSrcweir }
261*cdf0e10cSrcweir 
262*cdf0e10cSrcweir 
263*cdf0e10cSrcweir // ----------------------------------------------------------------
264*cdf0e10cSrcweir 
265*cdf0e10cSrcweir /** Container class for sprites issued by a ViewLayer
266*cdf0e10cSrcweir 
267*cdf0e10cSrcweir     This class handles the sprite prioritization issues, that are
268*cdf0e10cSrcweir     needed for layer sprites (e.g. the need to re-prioritize sprites
269*cdf0e10cSrcweir     when the layer changes prio).
270*cdf0e10cSrcweir  */
271*cdf0e10cSrcweir class LayerSpriteContainer
272*cdf0e10cSrcweir {
273*cdf0e10cSrcweir     /** Max fill level of maSprites, before we try to prune it from
274*cdf0e10cSrcweir         deceased sprites
275*cdf0e10cSrcweir     */
276*cdf0e10cSrcweir     enum{ SPRITE_ULLAGE=256 };
277*cdf0e10cSrcweir 
278*cdf0e10cSrcweir     /** All sprites that have been issued by this container (pruned
279*cdf0e10cSrcweir         from time to time, for invalid references). This vector is
280*cdf0e10cSrcweir         kept sorted with increasing sprite priority.
281*cdf0e10cSrcweir     */
282*cdf0e10cSrcweir     SpriteVector       maSprites;
283*cdf0e10cSrcweir 
284*cdf0e10cSrcweir     /// Priority of this layer, relative to other view layers
285*cdf0e10cSrcweir     basegfx::B1DRange  maLayerPrioRange;
286*cdf0e10cSrcweir 
287*cdf0e10cSrcweir     double getSpritePriority( std::size_t nSpriteNum ) const
288*cdf0e10cSrcweir     {
289*cdf0e10cSrcweir         // divide the available layer range equally between all
290*cdf0e10cSrcweir         // sprites, assign upper bound of individual sprite range as
291*cdf0e10cSrcweir         // sprite prio (the layer itself gets assigned the lower bound
292*cdf0e10cSrcweir         // of sprite 0's individual range):
293*cdf0e10cSrcweir         //
294*cdf0e10cSrcweir         // | layer 0                    | layer 1                    | ...
295*cdf0e10cSrcweir         // |    sprite 0 |    sprite 1  |    sprite 0 |    sprite 1  | ...
296*cdf0e10cSrcweir         return maLayerPrioRange.getMinimum() + maLayerPrioRange.getRange()*(nSpriteNum+1)/(maSprites.size()+1);
297*cdf0e10cSrcweir     }
298*cdf0e10cSrcweir 
299*cdf0e10cSrcweir     /** Rescan sprite vector, and remove deceased sprites (and reset
300*cdf0e10cSrcweir         sprite prio)
301*cdf0e10cSrcweir 
302*cdf0e10cSrcweir         @param aBegin
303*cdf0e10cSrcweir         Iterator to the first entry to rescan
304*cdf0e10cSrcweir      */
305*cdf0e10cSrcweir     void updateSprites()
306*cdf0e10cSrcweir     {
307*cdf0e10cSrcweir         SpriteVector aValidSprites;
308*cdf0e10cSrcweir 
309*cdf0e10cSrcweir         // check all sprites for validity and set new priority
310*cdf0e10cSrcweir         SpriteVector::iterator       aCurrSprite( maSprites.begin() );
311*cdf0e10cSrcweir         const SpriteVector::iterator aEnd( maSprites.end() );
312*cdf0e10cSrcweir         while( aCurrSprite != aEnd )
313*cdf0e10cSrcweir         {
314*cdf0e10cSrcweir             cppcanvas::CustomSpriteSharedPtr pCurrSprite( aCurrSprite->mpSprite.lock() );
315*cdf0e10cSrcweir 
316*cdf0e10cSrcweir             if( pCurrSprite )
317*cdf0e10cSrcweir             {
318*cdf0e10cSrcweir                 // only copy still valid sprites over to the refreshed
319*cdf0e10cSrcweir                 // sprite vector.
320*cdf0e10cSrcweir                 aValidSprites.push_back( *aCurrSprite );
321*cdf0e10cSrcweir 
322*cdf0e10cSrcweir                 pCurrSprite->setPriority(
323*cdf0e10cSrcweir                     getSpritePriority( aValidSprites.size()-1 ));
324*cdf0e10cSrcweir             }
325*cdf0e10cSrcweir 
326*cdf0e10cSrcweir             ++aCurrSprite;
327*cdf0e10cSrcweir         }
328*cdf0e10cSrcweir 
329*cdf0e10cSrcweir         // replace sprite list with pruned one
330*cdf0e10cSrcweir         maSprites.swap( aValidSprites );
331*cdf0e10cSrcweir     }
332*cdf0e10cSrcweir 
333*cdf0e10cSrcweir public:
334*cdf0e10cSrcweir     LayerSpriteContainer() :
335*cdf0e10cSrcweir         maSprites(),
336*cdf0e10cSrcweir         maLayerPrioRange()
337*cdf0e10cSrcweir     {
338*cdf0e10cSrcweir     }
339*cdf0e10cSrcweir 
340*cdf0e10cSrcweir     basegfx::B1DRange getLayerPriority() const
341*cdf0e10cSrcweir     {
342*cdf0e10cSrcweir         return maLayerPrioRange;
343*cdf0e10cSrcweir     }
344*cdf0e10cSrcweir 
345*cdf0e10cSrcweir     void setLayerPriority( const basegfx::B1DRange& rRange )
346*cdf0e10cSrcweir     {
347*cdf0e10cSrcweir         if( rRange != maLayerPrioRange )
348*cdf0e10cSrcweir         {
349*cdf0e10cSrcweir             maLayerPrioRange = rRange;
350*cdf0e10cSrcweir 
351*cdf0e10cSrcweir             // prune and recalc sprite prios
352*cdf0e10cSrcweir             updateSprites();
353*cdf0e10cSrcweir         }
354*cdf0e10cSrcweir     }
355*cdf0e10cSrcweir 
356*cdf0e10cSrcweir     void addSprite( const cppcanvas::CustomSpriteSharedPtr& pSprite,
357*cdf0e10cSrcweir                     double                                  nPriority )
358*cdf0e10cSrcweir     {
359*cdf0e10cSrcweir         if( !pSprite )
360*cdf0e10cSrcweir             return;
361*cdf0e10cSrcweir 
362*cdf0e10cSrcweir         SpriteEntry aEntry( pSprite,nPriority );
363*cdf0e10cSrcweir 
364*cdf0e10cSrcweir         // insert new sprite, such that vector stays sorted
365*cdf0e10cSrcweir         SpriteVector::iterator aInsertPos(
366*cdf0e10cSrcweir             maSprites.insert(
367*cdf0e10cSrcweir                 std::lower_bound( maSprites.begin(),
368*cdf0e10cSrcweir                                   maSprites.end(),
369*cdf0e10cSrcweir                                   aEntry ),
370*cdf0e10cSrcweir                 aEntry ));
371*cdf0e10cSrcweir 
372*cdf0e10cSrcweir         const std::size_t nNumSprites( maSprites.size() );
373*cdf0e10cSrcweir         if( nNumSprites > SPRITE_ULLAGE ||
374*cdf0e10cSrcweir             maSprites.end() - aInsertPos > 1 )
375*cdf0e10cSrcweir         {
376*cdf0e10cSrcweir             // updateSprites() also updates all sprite prios
377*cdf0e10cSrcweir             updateSprites();
378*cdf0e10cSrcweir         }
379*cdf0e10cSrcweir         else
380*cdf0e10cSrcweir         {
381*cdf0e10cSrcweir             // added sprite to the end, and not too many sprites in
382*cdf0e10cSrcweir             // vector - perform optimized update (only need to set
383*cdf0e10cSrcweir             // prio). This basically caters for the common case of
384*cdf0e10cSrcweir             // iterated character animations, which generate lots of
385*cdf0e10cSrcweir             // sprites, all added to the end.
386*cdf0e10cSrcweir             pSprite->setPriority(
387*cdf0e10cSrcweir                 getSpritePriority( nNumSprites-1 ));
388*cdf0e10cSrcweir         }
389*cdf0e10cSrcweir     }
390*cdf0e10cSrcweir 
391*cdf0e10cSrcweir     void clear()
392*cdf0e10cSrcweir     {
393*cdf0e10cSrcweir         maSprites.clear();
394*cdf0e10cSrcweir     }
395*cdf0e10cSrcweir };
396*cdf0e10cSrcweir 
397*cdf0e10cSrcweir 
398*cdf0e10cSrcweir // ----------------------------------------------------------------
399*cdf0e10cSrcweir 
400*cdf0e10cSrcweir 
401*cdf0e10cSrcweir /** This class provides layers for a slide view
402*cdf0e10cSrcweir 
403*cdf0e10cSrcweir     Layers are used to render animations with the correct z order -
404*cdf0e10cSrcweir     because sprites are always in front of the static canvas
405*cdf0e10cSrcweir     background, shapes that must appear <em<before</em> an animation
406*cdf0e10cSrcweir     must also be displayed as a sprite.
407*cdf0e10cSrcweir 
408*cdf0e10cSrcweir     Each layer has a priority assigned to it (valid range [0,1]), which
409*cdf0e10cSrcweir     also affects all sprites created for this specific layer - i.e. if
410*cdf0e10cSrcweir     the layer priority changes, the sprites change z order together
411*cdf0e10cSrcweir     with their parent.
412*cdf0e10cSrcweir  */
413*cdf0e10cSrcweir class SlideViewLayer : public ViewLayer,
414*cdf0e10cSrcweir                        private boost::noncopyable
415*cdf0e10cSrcweir {
416*cdf0e10cSrcweir     /// Smart container for all sprites issued by this layer
417*cdf0e10cSrcweir     mutable LayerSpriteContainer             maSpriteContainer;
418*cdf0e10cSrcweir 
419*cdf0e10cSrcweir     /// Bounds of this layer in user space coordinates
420*cdf0e10cSrcweir     basegfx::B2DRange                        maLayerBounds;
421*cdf0e10cSrcweir 
422*cdf0e10cSrcweir     /// Bounds of this layer in device pixel
423*cdf0e10cSrcweir     mutable basegfx::B2IRange                maLayerBoundsPixel;
424*cdf0e10cSrcweir 
425*cdf0e10cSrcweir     /// Current clip polygon in user coordinates
426*cdf0e10cSrcweir     basegfx::B2DPolyPolygon                  maClip;
427*cdf0e10cSrcweir 
428*cdf0e10cSrcweir     /// Current size of the view in user coordinates
429*cdf0e10cSrcweir     basegfx::B2DSize                         maUserSize;
430*cdf0e10cSrcweir 
431*cdf0e10cSrcweir     /// Current overall view transformation
432*cdf0e10cSrcweir     basegfx::B2DHomMatrix                    maTransformation;
433*cdf0e10cSrcweir 
434*cdf0e10cSrcweir     /// 'parent' canvas, this viewlayer is associated with
435*cdf0e10cSrcweir     const cppcanvas::SpriteCanvasSharedPtr   mpSpriteCanvas;
436*cdf0e10cSrcweir 
437*cdf0e10cSrcweir     /** output surface (necessarily a sprite, won't otherwise be able
438*cdf0e10cSrcweir         to display anything <em>before</em> other sprites)
439*cdf0e10cSrcweir     */
440*cdf0e10cSrcweir     mutable cppcanvas::CustomSpriteSharedPtr mpSprite;
441*cdf0e10cSrcweir 
442*cdf0e10cSrcweir     /// actual output canvas retrieved from a sprite
443*cdf0e10cSrcweir     mutable cppcanvas::CanvasSharedPtr       mpOutputCanvas;
444*cdf0e10cSrcweir 
445*cdf0e10cSrcweir     /// ptr back to owning view. needed for isOnView() method
446*cdf0e10cSrcweir     View const* const                        mpParentView;
447*cdf0e10cSrcweir 
448*cdf0e10cSrcweir public:
449*cdf0e10cSrcweir     /** Create a new layer
450*cdf0e10cSrcweir 
451*cdf0e10cSrcweir         @param pCanvas
452*cdf0e10cSrcweir         Sprite canvas to create the layer on
453*cdf0e10cSrcweir 
454*cdf0e10cSrcweir         @param rTransform
455*cdf0e10cSrcweir         Initial overall canvas transformation
456*cdf0e10cSrcweir 
457*cdf0e10cSrcweir         @param rLayerBounds
458*cdf0e10cSrcweir         Initial layer bounds, in view coordinate system
459*cdf0e10cSrcweir      */
460*cdf0e10cSrcweir     SlideViewLayer( const cppcanvas::SpriteCanvasSharedPtr& pCanvas,
461*cdf0e10cSrcweir                     const basegfx::B2DHomMatrix&            rTransform,
462*cdf0e10cSrcweir                     const basegfx::B2DRange&                rLayerBounds,
463*cdf0e10cSrcweir                     const basegfx::B2DSize&                 rUserSize,
464*cdf0e10cSrcweir                     View const* const                       pParentView) :
465*cdf0e10cSrcweir         maSpriteContainer(),
466*cdf0e10cSrcweir         maLayerBounds(rLayerBounds),
467*cdf0e10cSrcweir         maLayerBoundsPixel(),
468*cdf0e10cSrcweir         maClip(),
469*cdf0e10cSrcweir         maUserSize(rUserSize),
470*cdf0e10cSrcweir         maTransformation(rTransform),
471*cdf0e10cSrcweir         mpSpriteCanvas(pCanvas),
472*cdf0e10cSrcweir         mpSprite(),
473*cdf0e10cSrcweir         mpOutputCanvas(),
474*cdf0e10cSrcweir         mpParentView(pParentView)
475*cdf0e10cSrcweir     {
476*cdf0e10cSrcweir     }
477*cdf0e10cSrcweir 
478*cdf0e10cSrcweir     void updateView( const basegfx::B2DHomMatrix& rMatrix,
479*cdf0e10cSrcweir                      const basegfx::B2DSize&      rUserSize )
480*cdf0e10cSrcweir     {
481*cdf0e10cSrcweir         maTransformation = rMatrix;
482*cdf0e10cSrcweir         maUserSize = rUserSize;
483*cdf0e10cSrcweir 
484*cdf0e10cSrcweir         // limit layer bounds to visible screen
485*cdf0e10cSrcweir         maLayerBounds.intersect( basegfx::B2DRange(0.0,
486*cdf0e10cSrcweir                                                    0.0,
487*cdf0e10cSrcweir                                                    maUserSize.getX(),
488*cdf0e10cSrcweir                                                    maUserSize.getY()) );
489*cdf0e10cSrcweir 
490*cdf0e10cSrcweir         basegfx::B2IRange const& rNewLayerPixel(
491*cdf0e10cSrcweir             getLayerBoundsPixel(maLayerBounds,
492*cdf0e10cSrcweir                                 maTransformation) );
493*cdf0e10cSrcweir         if( rNewLayerPixel != maLayerBoundsPixel )
494*cdf0e10cSrcweir         {
495*cdf0e10cSrcweir             // re-gen sprite with new size
496*cdf0e10cSrcweir             mpOutputCanvas.reset();
497*cdf0e10cSrcweir             mpSprite.reset();
498*cdf0e10cSrcweir         }
499*cdf0e10cSrcweir     }
500*cdf0e10cSrcweir 
501*cdf0e10cSrcweir private:
502*cdf0e10cSrcweir     // ViewLayer interface
503*cdf0e10cSrcweir     // ----------------------------------------------
504*cdf0e10cSrcweir 
505*cdf0e10cSrcweir     virtual cppcanvas::CustomSpriteSharedPtr createSprite(
506*cdf0e10cSrcweir         const ::basegfx::B2DSize& rSpriteSizePixel,
507*cdf0e10cSrcweir         double                    nPriority ) const
508*cdf0e10cSrcweir     {
509*cdf0e10cSrcweir         cppcanvas::CustomSpriteSharedPtr pSprite(
510*cdf0e10cSrcweir             mpSpriteCanvas->createCustomSprite( rSpriteSizePixel ) );
511*cdf0e10cSrcweir 
512*cdf0e10cSrcweir         maSpriteContainer.addSprite( pSprite,
513*cdf0e10cSrcweir                                      nPriority );
514*cdf0e10cSrcweir 
515*cdf0e10cSrcweir         return pSprite;
516*cdf0e10cSrcweir     }
517*cdf0e10cSrcweir 
518*cdf0e10cSrcweir     virtual void setPriority( const basegfx::B1DRange& rRange )
519*cdf0e10cSrcweir     {
520*cdf0e10cSrcweir         OSL_ENSURE( !rRange.isEmpty() &&
521*cdf0e10cSrcweir                     rRange.getMinimum() >= 1.0,
522*cdf0e10cSrcweir                     "SlideViewLayer::setPriority(): prio MUST be larger than 1.0 (because "
523*cdf0e10cSrcweir                     "the background layer already lies there)" );
524*cdf0e10cSrcweir 
525*cdf0e10cSrcweir         maSpriteContainer.setLayerPriority( rRange );
526*cdf0e10cSrcweir 
527*cdf0e10cSrcweir         if( mpSprite )
528*cdf0e10cSrcweir             mpSprite->setPriority( rRange.getMinimum() );
529*cdf0e10cSrcweir     }
530*cdf0e10cSrcweir 
531*cdf0e10cSrcweir     virtual basegfx::B2DHomMatrix getTransformation() const
532*cdf0e10cSrcweir     {
533*cdf0e10cSrcweir         // Offset given transformation by left, top border of given
534*cdf0e10cSrcweir         // range (after transformation through given transformation)
535*cdf0e10cSrcweir         basegfx::B2DRectangle aTmpRect;
536*cdf0e10cSrcweir         canvas::tools::calcTransformedRectBounds( aTmpRect,
537*cdf0e10cSrcweir                                                   maLayerBounds,
538*cdf0e10cSrcweir                                                   maTransformation );
539*cdf0e10cSrcweir 
540*cdf0e10cSrcweir         basegfx::B2DHomMatrix aMatrix( maTransformation );
541*cdf0e10cSrcweir 
542*cdf0e10cSrcweir         // Add translation according to the origin of aTmpRect.  Ignore the
543*cdf0e10cSrcweir         // translation when aTmpRect was not properly initialized.
544*cdf0e10cSrcweir         if ( ! aTmpRect.isEmpty())
545*cdf0e10cSrcweir         {
546*cdf0e10cSrcweir             aMatrix.translate( -basegfx::fround(aTmpRect.getMinX()),
547*cdf0e10cSrcweir                                -basegfx::fround(aTmpRect.getMinY()) );
548*cdf0e10cSrcweir         }
549*cdf0e10cSrcweir 
550*cdf0e10cSrcweir         return aMatrix;
551*cdf0e10cSrcweir     }
552*cdf0e10cSrcweir 
553*cdf0e10cSrcweir     virtual basegfx::B2DHomMatrix getSpriteTransformation() const
554*cdf0e10cSrcweir     {
555*cdf0e10cSrcweir         return maTransformation;
556*cdf0e10cSrcweir     }
557*cdf0e10cSrcweir 
558*cdf0e10cSrcweir     virtual void clear() const
559*cdf0e10cSrcweir     {
560*cdf0e10cSrcweir         // keep layer clip
561*cdf0e10cSrcweir         clearRect(getCanvas()->clone(),
562*cdf0e10cSrcweir                   maLayerBoundsPixel);
563*cdf0e10cSrcweir     }
564*cdf0e10cSrcweir 
565*cdf0e10cSrcweir     virtual void clearAll() const
566*cdf0e10cSrcweir     {
567*cdf0e10cSrcweir         ::cppcanvas::CanvasSharedPtr pCanvas( getCanvas()->clone() );
568*cdf0e10cSrcweir 
569*cdf0e10cSrcweir         // clear layer clip, to clear whole area
570*cdf0e10cSrcweir         pCanvas->setClip();
571*cdf0e10cSrcweir 
572*cdf0e10cSrcweir         clearRect(pCanvas,
573*cdf0e10cSrcweir                   maLayerBoundsPixel);
574*cdf0e10cSrcweir     }
575*cdf0e10cSrcweir 
576*cdf0e10cSrcweir     virtual bool isOnView(boost::shared_ptr<View> const& rView) const
577*cdf0e10cSrcweir     {
578*cdf0e10cSrcweir         return rView.get() == mpParentView;
579*cdf0e10cSrcweir     }
580*cdf0e10cSrcweir 
581*cdf0e10cSrcweir     virtual cppcanvas::CanvasSharedPtr getCanvas() const
582*cdf0e10cSrcweir     {
583*cdf0e10cSrcweir         if( !mpOutputCanvas )
584*cdf0e10cSrcweir         {
585*cdf0e10cSrcweir             if( !mpSprite )
586*cdf0e10cSrcweir             {
587*cdf0e10cSrcweir                 maLayerBoundsPixel = getLayerBoundsPixel(maLayerBounds,
588*cdf0e10cSrcweir                                                          maTransformation);
589*cdf0e10cSrcweir 
590*cdf0e10cSrcweir                 // HACK: ensure at least 1x1 pixel size. clients might
591*cdf0e10cSrcweir                 // need an actual canvas (e.g. for bound rect
592*cdf0e10cSrcweir                 // calculations) without rendering anything. Better
593*cdf0e10cSrcweir                 // solution: introduce something like a reference
594*cdf0e10cSrcweir                 // canvas for ViewLayers, which is always available.
595*cdf0e10cSrcweir                 if( maLayerBoundsPixel.isEmpty() )
596*cdf0e10cSrcweir                     maLayerBoundsPixel = basegfx::B2IRange(0,0,1,1);
597*cdf0e10cSrcweir 
598*cdf0e10cSrcweir                 const basegfx::B2I64Tuple& rSpriteSize(maLayerBoundsPixel.getRange());
599*cdf0e10cSrcweir                 mpSprite = mpSpriteCanvas->createCustomSprite(
600*cdf0e10cSrcweir                     basegfx::B2DVector(sal::static_int_cast<sal_Int32>(rSpriteSize.getX()),
601*cdf0e10cSrcweir                                        sal::static_int_cast<sal_Int32>(rSpriteSize.getY())) );
602*cdf0e10cSrcweir 
603*cdf0e10cSrcweir                 mpSprite->setPriority(
604*cdf0e10cSrcweir                     maSpriteContainer.getLayerPriority().getMinimum() );
605*cdf0e10cSrcweir 
606*cdf0e10cSrcweir #if defined(VERBOSE) && defined(DBG_UTIL)
607*cdf0e10cSrcweir                 mpSprite->movePixel(
608*cdf0e10cSrcweir                     basegfx::B2DPoint(maLayerBoundsPixel.getMinimum()) +
609*cdf0e10cSrcweir                     basegfx::B2DPoint(10,10) );
610*cdf0e10cSrcweir 
611*cdf0e10cSrcweir                 mpSprite->setAlpha(0.5);
612*cdf0e10cSrcweir #else
613*cdf0e10cSrcweir                 mpSprite->movePixel(
614*cdf0e10cSrcweir                     basegfx::B2DPoint(maLayerBoundsPixel.getMinimum()) );
615*cdf0e10cSrcweir 
616*cdf0e10cSrcweir                 mpSprite->setAlpha(1.0);
617*cdf0e10cSrcweir #endif
618*cdf0e10cSrcweir                 mpSprite->show();
619*cdf0e10cSrcweir             }
620*cdf0e10cSrcweir 
621*cdf0e10cSrcweir             ENSURE_OR_THROW( mpSprite,
622*cdf0e10cSrcweir                               "SlideViewLayer::getCanvas(): no layer sprite" );
623*cdf0e10cSrcweir 
624*cdf0e10cSrcweir             mpOutputCanvas = mpSprite->getContentCanvas();
625*cdf0e10cSrcweir 
626*cdf0e10cSrcweir             ENSURE_OR_THROW( mpOutputCanvas,
627*cdf0e10cSrcweir                               "SlideViewLayer::getCanvas(): sprite doesn't yield a canvas" );
628*cdf0e10cSrcweir 
629*cdf0e10cSrcweir             // new canvas retrieved - setup transformation and clip
630*cdf0e10cSrcweir             mpOutputCanvas->setTransformation( getTransformation() );
631*cdf0e10cSrcweir             mpOutputCanvas->setClip(
632*cdf0e10cSrcweir                 createClipPolygon( maClip,
633*cdf0e10cSrcweir                                    mpOutputCanvas,
634*cdf0e10cSrcweir                                    maUserSize ));
635*cdf0e10cSrcweir         }
636*cdf0e10cSrcweir 
637*cdf0e10cSrcweir         return mpOutputCanvas;
638*cdf0e10cSrcweir     }
639*cdf0e10cSrcweir 
640*cdf0e10cSrcweir     virtual void setClip( const basegfx::B2DPolyPolygon& rClip )
641*cdf0e10cSrcweir     {
642*cdf0e10cSrcweir         basegfx::B2DPolyPolygon aNewClip = prepareClip( rClip );
643*cdf0e10cSrcweir 
644*cdf0e10cSrcweir         if( aNewClip != maClip )
645*cdf0e10cSrcweir         {
646*cdf0e10cSrcweir             maClip = aNewClip;
647*cdf0e10cSrcweir 
648*cdf0e10cSrcweir             if(mpOutputCanvas )
649*cdf0e10cSrcweir                 mpOutputCanvas->setClip(
650*cdf0e10cSrcweir                     createClipPolygon( maClip,
651*cdf0e10cSrcweir                                        mpOutputCanvas,
652*cdf0e10cSrcweir                                        maUserSize ));
653*cdf0e10cSrcweir         }
654*cdf0e10cSrcweir     }
655*cdf0e10cSrcweir 
656*cdf0e10cSrcweir     virtual bool resize( const ::basegfx::B2DRange& rArea )
657*cdf0e10cSrcweir     {
658*cdf0e10cSrcweir         const bool bRet( maLayerBounds != rArea );
659*cdf0e10cSrcweir         maLayerBounds = rArea;
660*cdf0e10cSrcweir         updateView( maTransformation,
661*cdf0e10cSrcweir                     maUserSize );
662*cdf0e10cSrcweir 
663*cdf0e10cSrcweir         return bRet;
664*cdf0e10cSrcweir     }
665*cdf0e10cSrcweir };
666*cdf0e10cSrcweir 
667*cdf0e10cSrcweir 
668*cdf0e10cSrcweir // ---------------------------------------------------------
669*cdf0e10cSrcweir 
670*cdf0e10cSrcweir typedef cppu::WeakComponentImplHelper2<
671*cdf0e10cSrcweir     ::com::sun::star::util::XModifyListener,
672*cdf0e10cSrcweir       ::com::sun::star::awt::XPaintListener> SlideViewBase;
673*cdf0e10cSrcweir 
674*cdf0e10cSrcweir /** SlideView class
675*cdf0e10cSrcweir 
676*cdf0e10cSrcweir     This class implements the View interface, encapsulating
677*cdf0e10cSrcweir     <em>one</em> view a slideshow is displayed on.
678*cdf0e10cSrcweir  */
679*cdf0e10cSrcweir class SlideView : private cppu::BaseMutex,
680*cdf0e10cSrcweir                   public SlideViewBase,
681*cdf0e10cSrcweir                   public UnoView
682*cdf0e10cSrcweir {
683*cdf0e10cSrcweir public:
684*cdf0e10cSrcweir     SlideView( const uno::Reference<presentation::XSlideShowView>& xView,
685*cdf0e10cSrcweir                EventQueue&                                         rEventQueue,
686*cdf0e10cSrcweir                EventMultiplexer&                                   rEventMultiplexer );
687*cdf0e10cSrcweir     void updateCanvas();
688*cdf0e10cSrcweir 
689*cdf0e10cSrcweir private:
690*cdf0e10cSrcweir     // View:
691*cdf0e10cSrcweir     virtual ViewLayerSharedPtr createViewLayer( const basegfx::B2DRange& rLayerBounds ) const;
692*cdf0e10cSrcweir     virtual bool updateScreen() const;
693*cdf0e10cSrcweir     virtual bool paintScreen() const;
694*cdf0e10cSrcweir     virtual void setViewSize( const ::basegfx::B2DSize& );
695*cdf0e10cSrcweir     virtual void setCursorShape( sal_Int16 nPointerShape );
696*cdf0e10cSrcweir 
697*cdf0e10cSrcweir     // ViewLayer interface
698*cdf0e10cSrcweir     virtual bool isOnView(boost::shared_ptr<View> const& rView) const;
699*cdf0e10cSrcweir     virtual void clear() const;
700*cdf0e10cSrcweir     virtual void clearAll() const;
701*cdf0e10cSrcweir     virtual cppcanvas::CanvasSharedPtr getCanvas() const;
702*cdf0e10cSrcweir     virtual cppcanvas::CustomSpriteSharedPtr createSprite( const ::basegfx::B2DSize& rSpriteSizePixel,
703*cdf0e10cSrcweir                                                            double                    nPriority ) const;
704*cdf0e10cSrcweir     virtual void setPriority( const basegfx::B1DRange& rRange );
705*cdf0e10cSrcweir     virtual ::basegfx::B2DHomMatrix getTransformation() const;
706*cdf0e10cSrcweir     virtual basegfx::B2DHomMatrix getSpriteTransformation() const;
707*cdf0e10cSrcweir     virtual void setClip( const ::basegfx::B2DPolyPolygon& rClip );
708*cdf0e10cSrcweir     virtual bool resize( const ::basegfx::B2DRange& rArea );
709*cdf0e10cSrcweir 
710*cdf0e10cSrcweir     // UnoView:
711*cdf0e10cSrcweir     virtual void _dispose();
712*cdf0e10cSrcweir     virtual uno::Reference<presentation::XSlideShowView> getUnoView()const;
713*cdf0e10cSrcweir     virtual void setIsSoundEnabled (const bool bValue);
714*cdf0e10cSrcweir     virtual bool isSoundEnabled (void) const;
715*cdf0e10cSrcweir 
716*cdf0e10cSrcweir     // XEventListener:
717*cdf0e10cSrcweir     virtual void SAL_CALL disposing( lang::EventObject const& evt )
718*cdf0e10cSrcweir         throw (uno::RuntimeException);
719*cdf0e10cSrcweir     // XModifyListener:
720*cdf0e10cSrcweir     virtual void SAL_CALL modified( const lang::EventObject& aEvent )
721*cdf0e10cSrcweir         throw (uno::RuntimeException);
722*cdf0e10cSrcweir     // XPaintListener:
723*cdf0e10cSrcweir     virtual void SAL_CALL windowPaint( const awt::PaintEvent& e )
724*cdf0e10cSrcweir         throw (uno::RuntimeException);
725*cdf0e10cSrcweir 
726*cdf0e10cSrcweir     // WeakComponentImplHelperBase:
727*cdf0e10cSrcweir     virtual void SAL_CALL disposing();
728*cdf0e10cSrcweir 
729*cdf0e10cSrcweir     void updateClip();
730*cdf0e10cSrcweir 
731*cdf0e10cSrcweir private:
732*cdf0e10cSrcweir     typedef std::vector< boost::weak_ptr<SlideViewLayer> > ViewLayerVector;
733*cdf0e10cSrcweir 
734*cdf0e10cSrcweir     /// Prune viewlayers from deceased ones, optionally update them
735*cdf0e10cSrcweir     void pruneLayers( bool bWithViewLayerUpdate=false ) const;
736*cdf0e10cSrcweir 
737*cdf0e10cSrcweir     /** Max fill level of maViewLayers, before we try to prune it from
738*cdf0e10cSrcweir         deceased layers
739*cdf0e10cSrcweir     */
740*cdf0e10cSrcweir     enum{ LAYER_ULLAGE=8 };
741*cdf0e10cSrcweir 
742*cdf0e10cSrcweir     uno::Reference<presentation::XSlideShowView>              mxView;
743*cdf0e10cSrcweir     cppcanvas::SpriteCanvasSharedPtr                          mpCanvas;
744*cdf0e10cSrcweir 
745*cdf0e10cSrcweir     EventMultiplexer&                                         mrEventMultiplexer;
746*cdf0e10cSrcweir     EventQueue&                                               mrEventQueue;
747*cdf0e10cSrcweir 
748*cdf0e10cSrcweir     mutable LayerSpriteContainer                              maSprites;
749*cdf0e10cSrcweir     mutable ViewLayerVector                                   maViewLayers;
750*cdf0e10cSrcweir 
751*cdf0e10cSrcweir     basegfx::B2DPolyPolygon                                   maClip;
752*cdf0e10cSrcweir 
753*cdf0e10cSrcweir     basegfx::B2DHomMatrix                                     maViewTransform;
754*cdf0e10cSrcweir     basegfx::B2DSize                                          maUserSize;
755*cdf0e10cSrcweir     bool mbIsSoundEnabled;
756*cdf0e10cSrcweir };
757*cdf0e10cSrcweir 
758*cdf0e10cSrcweir 
759*cdf0e10cSrcweir SlideView::SlideView( const uno::Reference<presentation::XSlideShowView>& xView,
760*cdf0e10cSrcweir                       EventQueue&                                         rEventQueue,
761*cdf0e10cSrcweir                       EventMultiplexer&                                   rEventMultiplexer ) :
762*cdf0e10cSrcweir     SlideViewBase( m_aMutex ),
763*cdf0e10cSrcweir     mxView( xView ),
764*cdf0e10cSrcweir     mpCanvas(),
765*cdf0e10cSrcweir     mrEventMultiplexer( rEventMultiplexer ),
766*cdf0e10cSrcweir     mrEventQueue( rEventQueue ),
767*cdf0e10cSrcweir     maSprites(),
768*cdf0e10cSrcweir     maViewLayers(),
769*cdf0e10cSrcweir     maClip(),
770*cdf0e10cSrcweir     maViewTransform(),
771*cdf0e10cSrcweir     maUserSize( 1.0, 1.0 ), // default size: one-by-one rectangle
772*cdf0e10cSrcweir     mbIsSoundEnabled(true)
773*cdf0e10cSrcweir {
774*cdf0e10cSrcweir     // take care not constructing any UNO references to this _inside_
775*cdf0e10cSrcweir     // ctor, shift that code to createSlideView()!
776*cdf0e10cSrcweir     ENSURE_OR_THROW( mxView.is(),
777*cdf0e10cSrcweir                       "SlideView::SlideView(): Invalid view" );
778*cdf0e10cSrcweir 
779*cdf0e10cSrcweir     mpCanvas = cppcanvas::VCLFactory::getInstance().createSpriteCanvas(
780*cdf0e10cSrcweir         xView->getCanvas() );
781*cdf0e10cSrcweir     ENSURE_OR_THROW( mpCanvas,
782*cdf0e10cSrcweir                       "Could not create cppcanvas" );
783*cdf0e10cSrcweir 
784*cdf0e10cSrcweir     geometry::AffineMatrix2D aViewTransform(
785*cdf0e10cSrcweir         xView->getTransformation() );
786*cdf0e10cSrcweir 
787*cdf0e10cSrcweir     if( basegfx::fTools::equalZero(
788*cdf0e10cSrcweir             basegfx::B2DVector(aViewTransform.m00,
789*cdf0e10cSrcweir                                aViewTransform.m10).getLength()) ||
790*cdf0e10cSrcweir         basegfx::fTools::equalZero(
791*cdf0e10cSrcweir             basegfx::B2DVector(aViewTransform.m01,
792*cdf0e10cSrcweir                                aViewTransform.m11).getLength()) )
793*cdf0e10cSrcweir     {
794*cdf0e10cSrcweir         OSL_ENSURE( false,
795*cdf0e10cSrcweir                     "SlideView::SlideView(): Singular matrix!" );
796*cdf0e10cSrcweir 
797*cdf0e10cSrcweir         canvas::tools::setIdentityAffineMatrix2D(aViewTransform);
798*cdf0e10cSrcweir     }
799*cdf0e10cSrcweir 
800*cdf0e10cSrcweir     basegfx::unotools::homMatrixFromAffineMatrix(
801*cdf0e10cSrcweir         maViewTransform, aViewTransform );
802*cdf0e10cSrcweir 
803*cdf0e10cSrcweir     // once and forever: set fixed prio to this 'layer' (we're always
804*cdf0e10cSrcweir     // the background layer)
805*cdf0e10cSrcweir     maSprites.setLayerPriority( basegfx::B1DRange(0.0,1.0) );
806*cdf0e10cSrcweir }
807*cdf0e10cSrcweir 
808*cdf0e10cSrcweir void SlideView::disposing()
809*cdf0e10cSrcweir {
810*cdf0e10cSrcweir     osl::MutexGuard aGuard( m_aMutex );
811*cdf0e10cSrcweir 
812*cdf0e10cSrcweir     maViewLayers.clear();
813*cdf0e10cSrcweir     maSprites.clear();
814*cdf0e10cSrcweir     mpCanvas.reset();
815*cdf0e10cSrcweir 
816*cdf0e10cSrcweir     // additionally, also de-register from XSlideShowView
817*cdf0e10cSrcweir     if (mxView.is())
818*cdf0e10cSrcweir     {
819*cdf0e10cSrcweir         mxView->removeTransformationChangedListener( this );
820*cdf0e10cSrcweir         mxView->removePaintListener( this );
821*cdf0e10cSrcweir         mxView.clear();
822*cdf0e10cSrcweir     }
823*cdf0e10cSrcweir }
824*cdf0e10cSrcweir 
825*cdf0e10cSrcweir ViewLayerSharedPtr SlideView::createViewLayer( const basegfx::B2DRange& rLayerBounds ) const
826*cdf0e10cSrcweir {
827*cdf0e10cSrcweir     osl::MutexGuard aGuard( m_aMutex );
828*cdf0e10cSrcweir 
829*cdf0e10cSrcweir     ENSURE_OR_THROW( mpCanvas,
830*cdf0e10cSrcweir                       "SlideView::createViewLayer(): Disposed" );
831*cdf0e10cSrcweir 
832*cdf0e10cSrcweir     const std::size_t nNumLayers( maViewLayers.size() );
833*cdf0e10cSrcweir 
834*cdf0e10cSrcweir     // avoid filling up layer vector with lots of deceased layer weak
835*cdf0e10cSrcweir     // ptrs
836*cdf0e10cSrcweir     if( nNumLayers > LAYER_ULLAGE )
837*cdf0e10cSrcweir         pruneLayers();
838*cdf0e10cSrcweir 
839*cdf0e10cSrcweir     boost::shared_ptr<SlideViewLayer> pViewLayer( new SlideViewLayer(mpCanvas,
840*cdf0e10cSrcweir                                                                      getTransformation(),
841*cdf0e10cSrcweir                                                                      rLayerBounds,
842*cdf0e10cSrcweir                                                                      maUserSize,
843*cdf0e10cSrcweir                                                                      this) );
844*cdf0e10cSrcweir     maViewLayers.push_back( pViewLayer );
845*cdf0e10cSrcweir 
846*cdf0e10cSrcweir     return pViewLayer;
847*cdf0e10cSrcweir }
848*cdf0e10cSrcweir 
849*cdf0e10cSrcweir bool SlideView::updateScreen() const
850*cdf0e10cSrcweir {
851*cdf0e10cSrcweir     osl::MutexGuard aGuard( m_aMutex );
852*cdf0e10cSrcweir 
853*cdf0e10cSrcweir     ENSURE_OR_RETURN_FALSE( mpCanvas.get(),
854*cdf0e10cSrcweir                        "SlideView::updateScreen(): Disposed" );
855*cdf0e10cSrcweir 
856*cdf0e10cSrcweir     return mpCanvas->updateScreen( false );
857*cdf0e10cSrcweir }
858*cdf0e10cSrcweir 
859*cdf0e10cSrcweir bool SlideView::paintScreen() const
860*cdf0e10cSrcweir {
861*cdf0e10cSrcweir     osl::MutexGuard aGuard( m_aMutex );
862*cdf0e10cSrcweir 
863*cdf0e10cSrcweir     ENSURE_OR_RETURN_FALSE( mpCanvas.get(),
864*cdf0e10cSrcweir                        "SlideView::paintScreen(): Disposed" );
865*cdf0e10cSrcweir 
866*cdf0e10cSrcweir     return mpCanvas->updateScreen( true );
867*cdf0e10cSrcweir }
868*cdf0e10cSrcweir 
869*cdf0e10cSrcweir void SlideView::clear() const
870*cdf0e10cSrcweir {
871*cdf0e10cSrcweir     osl::MutexGuard aGuard( m_aMutex );
872*cdf0e10cSrcweir 
873*cdf0e10cSrcweir     OSL_ENSURE( mxView.is() && mpCanvas,
874*cdf0e10cSrcweir                 "SlideView::clear(): Disposed" );
875*cdf0e10cSrcweir     if( !mxView.is() || !mpCanvas )
876*cdf0e10cSrcweir         return;
877*cdf0e10cSrcweir 
878*cdf0e10cSrcweir     // keep layer clip
879*cdf0e10cSrcweir     clearRect(getCanvas()->clone(),
880*cdf0e10cSrcweir               getLayerBoundsPixel(
881*cdf0e10cSrcweir                   basegfx::B2DRange(0,0,
882*cdf0e10cSrcweir                                     maUserSize.getX(),
883*cdf0e10cSrcweir                                     maUserSize.getY()),
884*cdf0e10cSrcweir                   getTransformation()));
885*cdf0e10cSrcweir }
886*cdf0e10cSrcweir 
887*cdf0e10cSrcweir void SlideView::clearAll() const
888*cdf0e10cSrcweir {
889*cdf0e10cSrcweir     osl::MutexGuard aGuard( m_aMutex );
890*cdf0e10cSrcweir 
891*cdf0e10cSrcweir     OSL_ENSURE( mxView.is() && mpCanvas,
892*cdf0e10cSrcweir                 "SlideView::clear(): Disposed" );
893*cdf0e10cSrcweir     if( !mxView.is() || !mpCanvas )
894*cdf0e10cSrcweir         return;
895*cdf0e10cSrcweir 
896*cdf0e10cSrcweir     // clear whole view
897*cdf0e10cSrcweir     mxView->clear();
898*cdf0e10cSrcweir }
899*cdf0e10cSrcweir 
900*cdf0e10cSrcweir void SlideView::setViewSize( const basegfx::B2DSize& rSize )
901*cdf0e10cSrcweir {
902*cdf0e10cSrcweir     osl::MutexGuard aGuard( m_aMutex );
903*cdf0e10cSrcweir 
904*cdf0e10cSrcweir     maUserSize = rSize;
905*cdf0e10cSrcweir     updateCanvas();
906*cdf0e10cSrcweir }
907*cdf0e10cSrcweir 
908*cdf0e10cSrcweir void SlideView::setCursorShape( sal_Int16 nPointerShape )
909*cdf0e10cSrcweir {
910*cdf0e10cSrcweir     osl::MutexGuard const guard( m_aMutex );
911*cdf0e10cSrcweir 
912*cdf0e10cSrcweir     if (mxView.is())
913*cdf0e10cSrcweir         mxView->setMouseCursor( nPointerShape );
914*cdf0e10cSrcweir }
915*cdf0e10cSrcweir 
916*cdf0e10cSrcweir bool SlideView::isOnView(boost::shared_ptr<View> const& rView) const
917*cdf0e10cSrcweir {
918*cdf0e10cSrcweir     return rView.get() == this;
919*cdf0e10cSrcweir }
920*cdf0e10cSrcweir 
921*cdf0e10cSrcweir cppcanvas::CanvasSharedPtr SlideView::getCanvas() const
922*cdf0e10cSrcweir {
923*cdf0e10cSrcweir     osl::MutexGuard aGuard( m_aMutex );
924*cdf0e10cSrcweir 
925*cdf0e10cSrcweir     ENSURE_OR_THROW( mpCanvas,
926*cdf0e10cSrcweir                       "SlideView::getCanvas(): Disposed" );
927*cdf0e10cSrcweir 
928*cdf0e10cSrcweir     return mpCanvas;
929*cdf0e10cSrcweir }
930*cdf0e10cSrcweir 
931*cdf0e10cSrcweir cppcanvas::CustomSpriteSharedPtr SlideView::createSprite(
932*cdf0e10cSrcweir     const basegfx::B2DSize& rSpriteSizePixel,
933*cdf0e10cSrcweir     double                  nPriority ) const
934*cdf0e10cSrcweir {
935*cdf0e10cSrcweir     osl::MutexGuard aGuard( m_aMutex );
936*cdf0e10cSrcweir 
937*cdf0e10cSrcweir     ENSURE_OR_THROW( mpCanvas, "SlideView::createSprite(): Disposed" );
938*cdf0e10cSrcweir 
939*cdf0e10cSrcweir     cppcanvas::CustomSpriteSharedPtr pSprite(
940*cdf0e10cSrcweir         mpCanvas->createCustomSprite( rSpriteSizePixel ) );
941*cdf0e10cSrcweir 
942*cdf0e10cSrcweir     maSprites.addSprite( pSprite,
943*cdf0e10cSrcweir                          nPriority );
944*cdf0e10cSrcweir 
945*cdf0e10cSrcweir     return pSprite;
946*cdf0e10cSrcweir }
947*cdf0e10cSrcweir 
948*cdf0e10cSrcweir void SlideView::setPriority( const basegfx::B1DRange& /*rRange*/ )
949*cdf0e10cSrcweir {
950*cdf0e10cSrcweir     osl::MutexGuard aGuard( m_aMutex );
951*cdf0e10cSrcweir 
952*cdf0e10cSrcweir     OSL_ENSURE( false,
953*cdf0e10cSrcweir                 "SlideView::setPriority() is a NOOP for slide view - "
954*cdf0e10cSrcweir                 "content will always be shown in the background" );
955*cdf0e10cSrcweir }
956*cdf0e10cSrcweir 
957*cdf0e10cSrcweir basegfx::B2DHomMatrix SlideView::getTransformation() const
958*cdf0e10cSrcweir {
959*cdf0e10cSrcweir     osl::MutexGuard aGuard( m_aMutex );
960*cdf0e10cSrcweir 
961*cdf0e10cSrcweir     basegfx::B2DHomMatrix aMatrix;
962*cdf0e10cSrcweir     aMatrix.scale( 1.0/maUserSize.getX(), 1.0/maUserSize.getY() );
963*cdf0e10cSrcweir 
964*cdf0e10cSrcweir     return maViewTransform * aMatrix;
965*cdf0e10cSrcweir }
966*cdf0e10cSrcweir 
967*cdf0e10cSrcweir basegfx::B2DHomMatrix SlideView::getSpriteTransformation() const
968*cdf0e10cSrcweir {
969*cdf0e10cSrcweir     return getTransformation();
970*cdf0e10cSrcweir }
971*cdf0e10cSrcweir 
972*cdf0e10cSrcweir void SlideView::setClip( const basegfx::B2DPolyPolygon& rClip )
973*cdf0e10cSrcweir {
974*cdf0e10cSrcweir     osl::MutexGuard aGuard( m_aMutex );
975*cdf0e10cSrcweir 
976*cdf0e10cSrcweir     basegfx::B2DPolyPolygon aNewClip = prepareClip( rClip );
977*cdf0e10cSrcweir 
978*cdf0e10cSrcweir     if( aNewClip != maClip )
979*cdf0e10cSrcweir     {
980*cdf0e10cSrcweir         maClip = aNewClip;
981*cdf0e10cSrcweir 
982*cdf0e10cSrcweir         updateClip();
983*cdf0e10cSrcweir     }
984*cdf0e10cSrcweir }
985*cdf0e10cSrcweir 
986*cdf0e10cSrcweir bool SlideView::resize( const ::basegfx::B2DRange& /*rArea*/ )
987*cdf0e10cSrcweir {
988*cdf0e10cSrcweir     osl::MutexGuard aGuard( m_aMutex );
989*cdf0e10cSrcweir 
990*cdf0e10cSrcweir     OSL_ENSURE( false,
991*cdf0e10cSrcweir                 "SlideView::resize(): ignored for the View, can't change size "
992*cdf0e10cSrcweir                 "effectively, anyway" );
993*cdf0e10cSrcweir 
994*cdf0e10cSrcweir     return false;
995*cdf0e10cSrcweir }
996*cdf0e10cSrcweir 
997*cdf0e10cSrcweir uno::Reference<presentation::XSlideShowView> SlideView::getUnoView() const
998*cdf0e10cSrcweir {
999*cdf0e10cSrcweir     osl::MutexGuard aGuard( m_aMutex );
1000*cdf0e10cSrcweir     return mxView;
1001*cdf0e10cSrcweir }
1002*cdf0e10cSrcweir 
1003*cdf0e10cSrcweir void SlideView::setIsSoundEnabled (const bool bValue)
1004*cdf0e10cSrcweir {
1005*cdf0e10cSrcweir     mbIsSoundEnabled = bValue;
1006*cdf0e10cSrcweir }
1007*cdf0e10cSrcweir 
1008*cdf0e10cSrcweir bool SlideView::isSoundEnabled (void) const
1009*cdf0e10cSrcweir {
1010*cdf0e10cSrcweir     return mbIsSoundEnabled;
1011*cdf0e10cSrcweir }
1012*cdf0e10cSrcweir 
1013*cdf0e10cSrcweir void SlideView::_dispose()
1014*cdf0e10cSrcweir {
1015*cdf0e10cSrcweir     dispose();
1016*cdf0e10cSrcweir }
1017*cdf0e10cSrcweir 
1018*cdf0e10cSrcweir // XEventListener
1019*cdf0e10cSrcweir void SlideView::disposing( lang::EventObject const& evt )
1020*cdf0e10cSrcweir     throw (uno::RuntimeException)
1021*cdf0e10cSrcweir {
1022*cdf0e10cSrcweir     (void)evt;
1023*cdf0e10cSrcweir 
1024*cdf0e10cSrcweir     // no deregistration necessary anymore, XView has left:
1025*cdf0e10cSrcweir     osl::MutexGuard const guard( m_aMutex );
1026*cdf0e10cSrcweir 
1027*cdf0e10cSrcweir     if (mxView.is())
1028*cdf0e10cSrcweir     {
1029*cdf0e10cSrcweir         OSL_ASSERT( evt.Source == mxView );
1030*cdf0e10cSrcweir         mxView.clear();
1031*cdf0e10cSrcweir     }
1032*cdf0e10cSrcweir 
1033*cdf0e10cSrcweir     dispose();
1034*cdf0e10cSrcweir }
1035*cdf0e10cSrcweir 
1036*cdf0e10cSrcweir // XModifyListener
1037*cdf0e10cSrcweir void SlideView::modified( const lang::EventObject& /*aEvent*/ )
1038*cdf0e10cSrcweir     throw (uno::RuntimeException)
1039*cdf0e10cSrcweir {
1040*cdf0e10cSrcweir     osl::MutexGuard const guard( m_aMutex );
1041*cdf0e10cSrcweir 
1042*cdf0e10cSrcweir     OSL_ENSURE( mxView.is(), "SlideView::modified(): "
1043*cdf0e10cSrcweir                 "Disposed, but event received from XSlideShowView?!");
1044*cdf0e10cSrcweir 
1045*cdf0e10cSrcweir     if( !mxView.is() )
1046*cdf0e10cSrcweir         return;
1047*cdf0e10cSrcweir 
1048*cdf0e10cSrcweir     geometry::AffineMatrix2D aViewTransform(
1049*cdf0e10cSrcweir         mxView->getTransformation() );
1050*cdf0e10cSrcweir 
1051*cdf0e10cSrcweir     if( basegfx::fTools::equalZero(
1052*cdf0e10cSrcweir             basegfx::B2DVector(aViewTransform.m00,
1053*cdf0e10cSrcweir                                aViewTransform.m10).getLength()) ||
1054*cdf0e10cSrcweir         basegfx::fTools::equalZero(
1055*cdf0e10cSrcweir             basegfx::B2DVector(aViewTransform.m01,
1056*cdf0e10cSrcweir                                aViewTransform.m11).getLength()) )
1057*cdf0e10cSrcweir     {
1058*cdf0e10cSrcweir         OSL_ENSURE( false,
1059*cdf0e10cSrcweir                     "SlideView::modified(): Singular matrix!" );
1060*cdf0e10cSrcweir 
1061*cdf0e10cSrcweir         canvas::tools::setIdentityAffineMatrix2D(aViewTransform);
1062*cdf0e10cSrcweir     }
1063*cdf0e10cSrcweir 
1064*cdf0e10cSrcweir     // view transformation really changed?
1065*cdf0e10cSrcweir     basegfx::B2DHomMatrix aNewTransform;
1066*cdf0e10cSrcweir     basegfx::unotools::homMatrixFromAffineMatrix(
1067*cdf0e10cSrcweir         aNewTransform,
1068*cdf0e10cSrcweir         aViewTransform );
1069*cdf0e10cSrcweir 
1070*cdf0e10cSrcweir     if( aNewTransform == maViewTransform )
1071*cdf0e10cSrcweir         return; // No change, nothing to do
1072*cdf0e10cSrcweir 
1073*cdf0e10cSrcweir     maViewTransform = aNewTransform;
1074*cdf0e10cSrcweir 
1075*cdf0e10cSrcweir     updateCanvas();
1076*cdf0e10cSrcweir 
1077*cdf0e10cSrcweir     // notify view change. Don't call EventMultiplexer directly, this
1078*cdf0e10cSrcweir     // might not be the main thread!
1079*cdf0e10cSrcweir     mrEventQueue.addEvent(
1080*cdf0e10cSrcweir         makeEvent( boost::bind( (bool (EventMultiplexer::*)(
1081*cdf0e10cSrcweir                                      const uno::Reference<presentation::XSlideShowView>&))
1082*cdf0e10cSrcweir                                 &EventMultiplexer::notifyViewChanged,
1083*cdf0e10cSrcweir                                 boost::ref(mrEventMultiplexer), mxView ),
1084*cdf0e10cSrcweir                    "EventMultiplexer::notifyViewChanged"));
1085*cdf0e10cSrcweir }
1086*cdf0e10cSrcweir 
1087*cdf0e10cSrcweir // XPaintListener
1088*cdf0e10cSrcweir void SlideView::windowPaint( const awt::PaintEvent& /*e*/ )
1089*cdf0e10cSrcweir     throw (uno::RuntimeException)
1090*cdf0e10cSrcweir {
1091*cdf0e10cSrcweir     osl::MutexGuard aGuard( m_aMutex );
1092*cdf0e10cSrcweir 
1093*cdf0e10cSrcweir     OSL_ENSURE( mxView.is() && mpCanvas, "Disposed, but event received?!" );
1094*cdf0e10cSrcweir 
1095*cdf0e10cSrcweir     // notify view clobbering. Don't call EventMultiplexer directly,
1096*cdf0e10cSrcweir     // this might not be the main thread!
1097*cdf0e10cSrcweir     mrEventQueue.addEvent(
1098*cdf0e10cSrcweir         makeEvent( boost::bind( &EventMultiplexer::notifyViewClobbered,
1099*cdf0e10cSrcweir                                 boost::ref(mrEventMultiplexer), mxView ),
1100*cdf0e10cSrcweir                    "EventMultiplexer::notifyViewClobbered") );
1101*cdf0e10cSrcweir }
1102*cdf0e10cSrcweir 
1103*cdf0e10cSrcweir void SlideView::updateCanvas()
1104*cdf0e10cSrcweir {
1105*cdf0e10cSrcweir     OSL_ENSURE( mpCanvas,
1106*cdf0e10cSrcweir                 "SlideView::updateCanvasTransform(): Disposed" );
1107*cdf0e10cSrcweir 
1108*cdf0e10cSrcweir     if( !mpCanvas || !mxView.is())
1109*cdf0e10cSrcweir         return;
1110*cdf0e10cSrcweir 
1111*cdf0e10cSrcweir     mpCanvas->clear(); // this is unnecessary, strictly speaking. but
1112*cdf0e10cSrcweir                        // it makes the SlideView behave exactly like a
1113*cdf0e10cSrcweir                        // sprite-based SlideViewLayer, because those
1114*cdf0e10cSrcweir                        // are created from scratch after a resize
1115*cdf0e10cSrcweir     clearAll();
1116*cdf0e10cSrcweir     mpCanvas->setTransformation( getTransformation() );
1117*cdf0e10cSrcweir     mpCanvas->setClip(
1118*cdf0e10cSrcweir         createClipPolygon( maClip,
1119*cdf0e10cSrcweir                            mpCanvas,
1120*cdf0e10cSrcweir                            maUserSize ));
1121*cdf0e10cSrcweir 
1122*cdf0e10cSrcweir     // forward update to viewlayers
1123*cdf0e10cSrcweir     pruneLayers( true );
1124*cdf0e10cSrcweir }
1125*cdf0e10cSrcweir 
1126*cdf0e10cSrcweir void SlideView::updateClip()
1127*cdf0e10cSrcweir {
1128*cdf0e10cSrcweir     OSL_ENSURE( mpCanvas,
1129*cdf0e10cSrcweir                 "SlideView::updateClip(): Disposed" );
1130*cdf0e10cSrcweir 
1131*cdf0e10cSrcweir     if( !mpCanvas )
1132*cdf0e10cSrcweir         return;
1133*cdf0e10cSrcweir 
1134*cdf0e10cSrcweir     mpCanvas->setClip(
1135*cdf0e10cSrcweir         createClipPolygon( maClip,
1136*cdf0e10cSrcweir                            mpCanvas,
1137*cdf0e10cSrcweir                            maUserSize ));
1138*cdf0e10cSrcweir 
1139*cdf0e10cSrcweir     pruneLayers( false );
1140*cdf0e10cSrcweir }
1141*cdf0e10cSrcweir 
1142*cdf0e10cSrcweir void SlideView::pruneLayers( bool bWithViewLayerUpdate ) const
1143*cdf0e10cSrcweir {
1144*cdf0e10cSrcweir     ViewLayerVector aValidLayers;
1145*cdf0e10cSrcweir 
1146*cdf0e10cSrcweir     const basegfx::B2DHomMatrix& rCurrTransform(
1147*cdf0e10cSrcweir         getTransformation() );
1148*cdf0e10cSrcweir 
1149*cdf0e10cSrcweir     // check all layers for validity, and retain only the live ones
1150*cdf0e10cSrcweir     ViewLayerVector::const_iterator       aCurr( maViewLayers.begin() );
1151*cdf0e10cSrcweir     const ViewLayerVector::const_iterator aEnd( maViewLayers.end() );
1152*cdf0e10cSrcweir     while( aCurr != aEnd )
1153*cdf0e10cSrcweir     {
1154*cdf0e10cSrcweir         boost::shared_ptr< SlideViewLayer > pCurrLayer( aCurr->lock() );
1155*cdf0e10cSrcweir 
1156*cdf0e10cSrcweir         if( pCurrLayer )
1157*cdf0e10cSrcweir         {
1158*cdf0e10cSrcweir             aValidLayers.push_back( pCurrLayer );
1159*cdf0e10cSrcweir 
1160*cdf0e10cSrcweir             if( bWithViewLayerUpdate )
1161*cdf0e10cSrcweir                 pCurrLayer->updateView( rCurrTransform,
1162*cdf0e10cSrcweir                                         maUserSize );
1163*cdf0e10cSrcweir         }
1164*cdf0e10cSrcweir 
1165*cdf0e10cSrcweir         ++aCurr;
1166*cdf0e10cSrcweir     }
1167*cdf0e10cSrcweir 
1168*cdf0e10cSrcweir     // replace layer list with pruned one
1169*cdf0e10cSrcweir     maViewLayers.swap( aValidLayers );
1170*cdf0e10cSrcweir }
1171*cdf0e10cSrcweir 
1172*cdf0e10cSrcweir } // anonymous namespace
1173*cdf0e10cSrcweir 
1174*cdf0e10cSrcweir UnoViewSharedPtr createSlideView( uno::Reference< presentation::XSlideShowView> const& xView,
1175*cdf0e10cSrcweir                                   EventQueue&                                          rEventQueue,
1176*cdf0e10cSrcweir                                   EventMultiplexer&                                    rEventMultiplexer )
1177*cdf0e10cSrcweir {
1178*cdf0e10cSrcweir     boost::shared_ptr<SlideView> const that(
1179*cdf0e10cSrcweir         comphelper::make_shared_from_UNO(
1180*cdf0e10cSrcweir             new SlideView(xView,
1181*cdf0e10cSrcweir                           rEventQueue,
1182*cdf0e10cSrcweir                           rEventMultiplexer)));
1183*cdf0e10cSrcweir 
1184*cdf0e10cSrcweir     // register listeners with XSlideShowView
1185*cdf0e10cSrcweir     xView->addTransformationChangedListener( that.get() );
1186*cdf0e10cSrcweir     xView->addPaintListener( that.get() );
1187*cdf0e10cSrcweir 
1188*cdf0e10cSrcweir     // set new transformation
1189*cdf0e10cSrcweir     that->updateCanvas();
1190*cdf0e10cSrcweir 
1191*cdf0e10cSrcweir     return that;
1192*cdf0e10cSrcweir }
1193*cdf0e10cSrcweir 
1194*cdf0e10cSrcweir } // namespace internal
1195*cdf0e10cSrcweir } // namespace slideshow
1196*cdf0e10cSrcweir 
1197