xref: /AOO41X/main/slideshow/source/engine/slide/layermanager.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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_slideshow.hxx"
30*cdf0e10cSrcweir 
31*cdf0e10cSrcweir #include <canvas/debug.hxx>
32*cdf0e10cSrcweir #include <tools/diagnose_ex.h>
33*cdf0e10cSrcweir #include <basegfx/range/b1drange.hxx>
34*cdf0e10cSrcweir #include <basegfx/matrix/b2dhommatrix.hxx>
35*cdf0e10cSrcweir 
36*cdf0e10cSrcweir #include <comphelper/anytostring.hxx>
37*cdf0e10cSrcweir #include <cppuhelper/exc_hlp.hxx>
38*cdf0e10cSrcweir 
39*cdf0e10cSrcweir #include <boost/bind.hpp>
40*cdf0e10cSrcweir #include <algorithm>
41*cdf0e10cSrcweir 
42*cdf0e10cSrcweir #include "layermanager.hxx"
43*cdf0e10cSrcweir 
44*cdf0e10cSrcweir using namespace ::com::sun::star;
45*cdf0e10cSrcweir 
46*cdf0e10cSrcweir namespace boost
47*cdf0e10cSrcweir {
48*cdf0e10cSrcweir     // add operator!= for weak_ptr
49*cdf0e10cSrcweir     inline bool operator!=( slideshow::internal::LayerWeakPtr const& rLHS,
50*cdf0e10cSrcweir                             slideshow::internal::LayerWeakPtr const& rRHS )
51*cdf0e10cSrcweir     {
52*cdf0e10cSrcweir         return (rLHS<rRHS) || (rRHS<rLHS);
53*cdf0e10cSrcweir     }
54*cdf0e10cSrcweir }
55*cdf0e10cSrcweir 
56*cdf0e10cSrcweir namespace slideshow
57*cdf0e10cSrcweir {
58*cdf0e10cSrcweir     namespace internal
59*cdf0e10cSrcweir     {
60*cdf0e10cSrcweir         template<typename LayerFunc,
61*cdf0e10cSrcweir                  typename ShapeFunc> void LayerManager::manageViews(
62*cdf0e10cSrcweir                      LayerFunc layerFunc,
63*cdf0e10cSrcweir                      ShapeFunc shapeFunc )
64*cdf0e10cSrcweir         {
65*cdf0e10cSrcweir             LayerSharedPtr                      pCurrLayer;
66*cdf0e10cSrcweir             ViewLayerSharedPtr                  pCurrViewLayer;
67*cdf0e10cSrcweir             LayerShapeMap::const_iterator       aIter( maAllShapes.begin() );
68*cdf0e10cSrcweir             const LayerShapeMap::const_iterator aEnd ( maAllShapes.end() );
69*cdf0e10cSrcweir             while( aIter != aEnd )
70*cdf0e10cSrcweir             {
71*cdf0e10cSrcweir                 LayerSharedPtr pLayer = aIter->second.lock();
72*cdf0e10cSrcweir                 if( pLayer && pLayer != pCurrLayer )
73*cdf0e10cSrcweir                 {
74*cdf0e10cSrcweir                     pCurrLayer = pLayer;
75*cdf0e10cSrcweir                     pCurrViewLayer = layerFunc(pCurrLayer);
76*cdf0e10cSrcweir                 }
77*cdf0e10cSrcweir 
78*cdf0e10cSrcweir                 if( pCurrViewLayer )
79*cdf0e10cSrcweir                     shapeFunc(aIter->first,pCurrViewLayer);
80*cdf0e10cSrcweir 
81*cdf0e10cSrcweir                 ++aIter;
82*cdf0e10cSrcweir             }
83*cdf0e10cSrcweir         }
84*cdf0e10cSrcweir 
85*cdf0e10cSrcweir         LayerManager::LayerManager( const UnoViewContainer&    rViews,
86*cdf0e10cSrcweir                                     const ::basegfx::B2DRange& rPageBounds,
87*cdf0e10cSrcweir                                     bool                       bDisableAnimationZOrder ) :
88*cdf0e10cSrcweir             mrViews(rViews),
89*cdf0e10cSrcweir             maLayers(),
90*cdf0e10cSrcweir             maXShapeHash( 101 ),
91*cdf0e10cSrcweir             maAllShapes(),
92*cdf0e10cSrcweir             maUpdateShapes(),
93*cdf0e10cSrcweir             maPageBounds( rPageBounds ),
94*cdf0e10cSrcweir             mnActiveSprites(0),
95*cdf0e10cSrcweir             mbLayerAssociationDirty(false),
96*cdf0e10cSrcweir             mbActive(false),
97*cdf0e10cSrcweir             mbDisableAnimationZOrder(bDisableAnimationZOrder)
98*cdf0e10cSrcweir         {
99*cdf0e10cSrcweir             // prevent frequent resizes (won't have more than 4 layers
100*cdf0e10cSrcweir             // for 99.9% of the cases)
101*cdf0e10cSrcweir             maLayers.reserve(4);
102*cdf0e10cSrcweir 
103*cdf0e10cSrcweir             // create initial background layer
104*cdf0e10cSrcweir             maLayers.push_back(
105*cdf0e10cSrcweir                     Layer::createBackgroundLayer(
106*cdf0e10cSrcweir                         maPageBounds ));
107*cdf0e10cSrcweir 
108*cdf0e10cSrcweir             // init views
109*cdf0e10cSrcweir             std::for_each( mrViews.begin(),
110*cdf0e10cSrcweir                            mrViews.end(),
111*cdf0e10cSrcweir                            ::boost::bind(&LayerManager::viewAdded,
112*cdf0e10cSrcweir                                          this,
113*cdf0e10cSrcweir                                          _1) );
114*cdf0e10cSrcweir         }
115*cdf0e10cSrcweir 
116*cdf0e10cSrcweir         void LayerManager::activate( bool bSlideBackgoundPainted )
117*cdf0e10cSrcweir         {
118*cdf0e10cSrcweir             mbActive = true;
119*cdf0e10cSrcweir             maUpdateShapes.clear(); // update gets forced via area, or
120*cdf0e10cSrcweir                                     // has happend outside already
121*cdf0e10cSrcweir 
122*cdf0e10cSrcweir             if( !bSlideBackgoundPainted )
123*cdf0e10cSrcweir             {
124*cdf0e10cSrcweir                 std::for_each(mrViews.begin(),
125*cdf0e10cSrcweir                               mrViews.end(),
126*cdf0e10cSrcweir                               boost::mem_fn(&View::clearAll));
127*cdf0e10cSrcweir 
128*cdf0e10cSrcweir                 // force update of whole slide area
129*cdf0e10cSrcweir                 std::for_each( maLayers.begin(),
130*cdf0e10cSrcweir                                maLayers.end(),
131*cdf0e10cSrcweir                                boost::bind( &Layer::addUpdateRange,
132*cdf0e10cSrcweir                                             _1,
133*cdf0e10cSrcweir                                             boost::cref(maPageBounds) ));
134*cdf0e10cSrcweir             }
135*cdf0e10cSrcweir             else
136*cdf0e10cSrcweir             {
137*cdf0e10cSrcweir                 // clear all possibly pending update areas - content
138*cdf0e10cSrcweir                 // is there, already
139*cdf0e10cSrcweir                 std::for_each( maLayers.begin(),
140*cdf0e10cSrcweir                                maLayers.end(),
141*cdf0e10cSrcweir                                boost::mem_fn( &Layer::clearUpdateRanges ));
142*cdf0e10cSrcweir             }
143*cdf0e10cSrcweir 
144*cdf0e10cSrcweir             updateShapeLayers( bSlideBackgoundPainted );
145*cdf0e10cSrcweir         }
146*cdf0e10cSrcweir 
147*cdf0e10cSrcweir         void LayerManager::deactivate()
148*cdf0e10cSrcweir         {
149*cdf0e10cSrcweir             // TODO(F3): This is mostly a hack. Problem is, there's
150*cdf0e10cSrcweir             // currently no smart way of telling shapes "remove your
151*cdf0e10cSrcweir             // sprites". Others, like MediaShapes, listen to
152*cdf0e10cSrcweir             // start/stop animation events, which is too much overhead
153*cdf0e10cSrcweir             // for all shapes, though.
154*cdf0e10cSrcweir 
155*cdf0e10cSrcweir             const bool bMoreThanOneLayer(maLayers.size() > 1);
156*cdf0e10cSrcweir             if( mnActiveSprites || bMoreThanOneLayer )
157*cdf0e10cSrcweir             {
158*cdf0e10cSrcweir                 // clear all viewlayers, dump everything but the
159*cdf0e10cSrcweir                 // background layer - this will also remove all shape
160*cdf0e10cSrcweir                 // sprites
161*cdf0e10cSrcweir                 std::for_each(maAllShapes.begin(),
162*cdf0e10cSrcweir                               maAllShapes.end(),
163*cdf0e10cSrcweir                               boost::bind( &Shape::clearAllViewLayers,
164*cdf0e10cSrcweir                                            boost::bind( std::select1st<LayerShapeMap::value_type>(),
165*cdf0e10cSrcweir                                                         _1 )));
166*cdf0e10cSrcweir 
167*cdf0e10cSrcweir                 for (LayerShapeMap::iterator
168*cdf0e10cSrcweir                          iShape (maAllShapes.begin()),
169*cdf0e10cSrcweir                          iEnd (maAllShapes.end());
170*cdf0e10cSrcweir                      iShape!=iEnd;
171*cdf0e10cSrcweir                      ++iShape)
172*cdf0e10cSrcweir                 {
173*cdf0e10cSrcweir                     iShape->second.reset();
174*cdf0e10cSrcweir                 }
175*cdf0e10cSrcweir 
176*cdf0e10cSrcweir                 if( bMoreThanOneLayer )
177*cdf0e10cSrcweir                     maLayers.erase(maLayers.begin()+1,
178*cdf0e10cSrcweir                                    maLayers.end());
179*cdf0e10cSrcweir 
180*cdf0e10cSrcweir                 mbLayerAssociationDirty = true;
181*cdf0e10cSrcweir             }
182*cdf0e10cSrcweir 
183*cdf0e10cSrcweir             mbActive = false;
184*cdf0e10cSrcweir 
185*cdf0e10cSrcweir             // only background layer left
186*cdf0e10cSrcweir             OSL_ASSERT( maLayers.size() == 1 && maLayers.front()->isBackgroundLayer() );
187*cdf0e10cSrcweir         }
188*cdf0e10cSrcweir 
189*cdf0e10cSrcweir         void LayerManager::viewAdded( const UnoViewSharedPtr& rView )
190*cdf0e10cSrcweir         {
191*cdf0e10cSrcweir             // view must be member of mrViews container
192*cdf0e10cSrcweir             OSL_ASSERT( std::find(mrViews.begin(),
193*cdf0e10cSrcweir                                   mrViews.end(),
194*cdf0e10cSrcweir                                   rView) != mrViews.end() );
195*cdf0e10cSrcweir 
196*cdf0e10cSrcweir             // init view content
197*cdf0e10cSrcweir             if( mbActive )
198*cdf0e10cSrcweir                 rView->clearAll();
199*cdf0e10cSrcweir 
200*cdf0e10cSrcweir             // add View to all registered shapes
201*cdf0e10cSrcweir             manageViews(
202*cdf0e10cSrcweir                 boost::bind(&Layer::addView,
203*cdf0e10cSrcweir                             _1,
204*cdf0e10cSrcweir                             boost::cref(rView)),
205*cdf0e10cSrcweir                 // repaint on view add
206*cdf0e10cSrcweir                 boost::bind(&Shape::addViewLayer,
207*cdf0e10cSrcweir                             _1,
208*cdf0e10cSrcweir                             _2,
209*cdf0e10cSrcweir                             true) );
210*cdf0e10cSrcweir 
211*cdf0e10cSrcweir             // in case we haven't reached all layers from the
212*cdf0e10cSrcweir             // maAllShapes, issue addView again for good measure
213*cdf0e10cSrcweir             std::for_each( maLayers.begin(),
214*cdf0e10cSrcweir                            maLayers.end(),
215*cdf0e10cSrcweir                            boost::bind( &Layer::addView,
216*cdf0e10cSrcweir                                         _1,
217*cdf0e10cSrcweir                                         boost::cref(rView) ));
218*cdf0e10cSrcweir         }
219*cdf0e10cSrcweir 
220*cdf0e10cSrcweir         void LayerManager::viewRemoved( const UnoViewSharedPtr& rView )
221*cdf0e10cSrcweir         {
222*cdf0e10cSrcweir             // view must not be member of mrViews container anymore
223*cdf0e10cSrcweir             OSL_ASSERT( std::find(mrViews.begin(),
224*cdf0e10cSrcweir                                   mrViews.end(),
225*cdf0e10cSrcweir                                   rView) == mrViews.end() );
226*cdf0e10cSrcweir 
227*cdf0e10cSrcweir             // remove View from all registered shapes
228*cdf0e10cSrcweir             manageViews(
229*cdf0e10cSrcweir                 boost::bind(&Layer::removeView,
230*cdf0e10cSrcweir                             _1,
231*cdf0e10cSrcweir                             boost::cref(rView)),
232*cdf0e10cSrcweir                 boost::bind(&Shape::removeViewLayer,
233*cdf0e10cSrcweir                             _1,
234*cdf0e10cSrcweir                             _2) );
235*cdf0e10cSrcweir 
236*cdf0e10cSrcweir             // in case we haven't reached all layers from the
237*cdf0e10cSrcweir             // maAllShapes, issue removeView again for good measure
238*cdf0e10cSrcweir             std::for_each( maLayers.begin(),
239*cdf0e10cSrcweir                            maLayers.end(),
240*cdf0e10cSrcweir                            boost::bind( &Layer::removeView,
241*cdf0e10cSrcweir                                         _1,
242*cdf0e10cSrcweir                                         boost::cref(rView) ));
243*cdf0e10cSrcweir         }
244*cdf0e10cSrcweir 
245*cdf0e10cSrcweir         void LayerManager::viewChanged( const UnoViewSharedPtr& rView )
246*cdf0e10cSrcweir         {
247*cdf0e10cSrcweir             (void)rView;
248*cdf0e10cSrcweir 
249*cdf0e10cSrcweir             // view must be member of mrViews container
250*cdf0e10cSrcweir             OSL_ASSERT( std::find(mrViews.begin(),
251*cdf0e10cSrcweir                                   mrViews.end(),
252*cdf0e10cSrcweir                                   rView) != mrViews.end() );
253*cdf0e10cSrcweir 
254*cdf0e10cSrcweir             // TODO(P2): selectively update only changed view
255*cdf0e10cSrcweir             viewsChanged();
256*cdf0e10cSrcweir         }
257*cdf0e10cSrcweir 
258*cdf0e10cSrcweir         void LayerManager::viewsChanged()
259*cdf0e10cSrcweir         {
260*cdf0e10cSrcweir             if( !mbActive )
261*cdf0e10cSrcweir                 return;
262*cdf0e10cSrcweir 
263*cdf0e10cSrcweir             // clear view area
264*cdf0e10cSrcweir             ::std::for_each( mrViews.begin(),
265*cdf0e10cSrcweir                              mrViews.end(),
266*cdf0e10cSrcweir                              ::boost::mem_fn(&View::clearAll) );
267*cdf0e10cSrcweir 
268*cdf0e10cSrcweir             // TODO(F3): resize and repaint all layers
269*cdf0e10cSrcweir 
270*cdf0e10cSrcweir             // render all shapes
271*cdf0e10cSrcweir             std::for_each( maAllShapes.begin(),
272*cdf0e10cSrcweir                            maAllShapes.end(),
273*cdf0e10cSrcweir                            boost::bind(&Shape::render,
274*cdf0e10cSrcweir                                boost::bind( ::std::select1st<LayerShapeMap::value_type>(), _1)) );
275*cdf0e10cSrcweir         }
276*cdf0e10cSrcweir 
277*cdf0e10cSrcweir         void LayerManager::addShape( const ShapeSharedPtr& rShape )
278*cdf0e10cSrcweir         {
279*cdf0e10cSrcweir             OSL_ASSERT( !maLayers.empty() ); // always at least background layer
280*cdf0e10cSrcweir             ENSURE_OR_THROW( rShape, "LayerManager::addShape(): invalid Shape" );
281*cdf0e10cSrcweir 
282*cdf0e10cSrcweir             // add shape to XShape hash map
283*cdf0e10cSrcweir             if( !maXShapeHash.insert(
284*cdf0e10cSrcweir                     XShapeHash::value_type( rShape->getXShape(),
285*cdf0e10cSrcweir                                             rShape) ).second )
286*cdf0e10cSrcweir             {
287*cdf0e10cSrcweir                 // entry already present, nothing to do
288*cdf0e10cSrcweir                 return;
289*cdf0e10cSrcweir             }
290*cdf0e10cSrcweir 
291*cdf0e10cSrcweir             // add shape to appropriate layer
292*cdf0e10cSrcweir             implAddShape( rShape );
293*cdf0e10cSrcweir         }
294*cdf0e10cSrcweir 
295*cdf0e10cSrcweir         void LayerManager::putShape2BackgroundLayer( LayerShapeMap::value_type& rShapeEntry )
296*cdf0e10cSrcweir         {
297*cdf0e10cSrcweir             LayerSharedPtr& rBgLayer( maLayers.front() );
298*cdf0e10cSrcweir             rBgLayer->setShapeViews(rShapeEntry.first);
299*cdf0e10cSrcweir             rShapeEntry.second = rBgLayer;
300*cdf0e10cSrcweir         }
301*cdf0e10cSrcweir 
302*cdf0e10cSrcweir         void LayerManager::implAddShape( const ShapeSharedPtr& rShape )
303*cdf0e10cSrcweir         {
304*cdf0e10cSrcweir             OSL_ASSERT( !maLayers.empty() ); // always at least background layer
305*cdf0e10cSrcweir             ENSURE_OR_THROW( rShape, "LayerManager::implAddShape(): invalid Shape" );
306*cdf0e10cSrcweir 
307*cdf0e10cSrcweir             LayerShapeMap::value_type aValue (rShape, LayerWeakPtr());
308*cdf0e10cSrcweir 
309*cdf0e10cSrcweir             OSL_ASSERT( maAllShapes.find(rShape) == maAllShapes.end() ); // shape must not be added already
310*cdf0e10cSrcweir             mbLayerAssociationDirty = true;
311*cdf0e10cSrcweir 
312*cdf0e10cSrcweir             if( mbDisableAnimationZOrder )
313*cdf0e10cSrcweir                 putShape2BackgroundLayer(
314*cdf0e10cSrcweir                     *maAllShapes.insert(aValue).first );
315*cdf0e10cSrcweir             else
316*cdf0e10cSrcweir                 maAllShapes.insert(aValue);
317*cdf0e10cSrcweir 
318*cdf0e10cSrcweir             // update shape, it's just added and not yet painted
319*cdf0e10cSrcweir             if( rShape->isVisible() )
320*cdf0e10cSrcweir                 notifyShapeUpdate( rShape );
321*cdf0e10cSrcweir         }
322*cdf0e10cSrcweir 
323*cdf0e10cSrcweir         bool LayerManager::removeShape( const ShapeSharedPtr& rShape )
324*cdf0e10cSrcweir         {
325*cdf0e10cSrcweir             // remove shape from XShape hash map
326*cdf0e10cSrcweir             if( maXShapeHash.erase( rShape->getXShape() ) == 0 )
327*cdf0e10cSrcweir                 return false; // shape not in map
328*cdf0e10cSrcweir 
329*cdf0e10cSrcweir             OSL_ASSERT( maAllShapes.find(rShape) != maAllShapes.end() );
330*cdf0e10cSrcweir 
331*cdf0e10cSrcweir             implRemoveShape( rShape );
332*cdf0e10cSrcweir 
333*cdf0e10cSrcweir             return true;
334*cdf0e10cSrcweir         }
335*cdf0e10cSrcweir 
336*cdf0e10cSrcweir         void LayerManager::implRemoveShape( const ShapeSharedPtr& rShape )
337*cdf0e10cSrcweir         {
338*cdf0e10cSrcweir             OSL_ASSERT( !maLayers.empty() ); // always at least background layer
339*cdf0e10cSrcweir             ENSURE_OR_THROW( rShape, "LayerManager::implRemoveShape(): invalid Shape" );
340*cdf0e10cSrcweir 
341*cdf0e10cSrcweir             const LayerShapeMap::iterator aShapeEntry( maAllShapes.find(rShape) );
342*cdf0e10cSrcweir 
343*cdf0e10cSrcweir             if( aShapeEntry == maAllShapes.end() )
344*cdf0e10cSrcweir                 return;
345*cdf0e10cSrcweir 
346*cdf0e10cSrcweir             const bool bShapeUpdateNotified = maUpdateShapes.erase( rShape ) != 0;
347*cdf0e10cSrcweir 
348*cdf0e10cSrcweir             // Enter shape area to the update area, but only if shape
349*cdf0e10cSrcweir             // is visible and not in sprite mode (otherwise, updating
350*cdf0e10cSrcweir             // the area doesn't do actual harm, but costs time)
351*cdf0e10cSrcweir             // Actually, also add it if it was listed in
352*cdf0e10cSrcweir             // maUpdateShapes (might have just gone invisible).
353*cdf0e10cSrcweir             if( bShapeUpdateNotified ||
354*cdf0e10cSrcweir                 (rShape->isVisible() &&
355*cdf0e10cSrcweir                  !rShape->isBackgroundDetached()) )
356*cdf0e10cSrcweir             {
357*cdf0e10cSrcweir                 LayerSharedPtr pLayer = aShapeEntry->second.lock();
358*cdf0e10cSrcweir                 if( pLayer )
359*cdf0e10cSrcweir                 {
360*cdf0e10cSrcweir                     // store area early, once the shape is removed from
361*cdf0e10cSrcweir                     // the layers, it no longer has any view references
362*cdf0e10cSrcweir                     pLayer->addUpdateRange( rShape->getUpdateArea() );
363*cdf0e10cSrcweir                 }
364*cdf0e10cSrcweir             }
365*cdf0e10cSrcweir 
366*cdf0e10cSrcweir             rShape->clearAllViewLayers();
367*cdf0e10cSrcweir             maAllShapes.erase( aShapeEntry );
368*cdf0e10cSrcweir 
369*cdf0e10cSrcweir             mbLayerAssociationDirty = true;
370*cdf0e10cSrcweir         }
371*cdf0e10cSrcweir 
372*cdf0e10cSrcweir         ShapeSharedPtr LayerManager::lookupShape( const uno::Reference< drawing::XShape >& xShape ) const
373*cdf0e10cSrcweir         {
374*cdf0e10cSrcweir             ENSURE_OR_THROW( xShape.is(), "LayerManager::lookupShape(): invalid Shape" );
375*cdf0e10cSrcweir 
376*cdf0e10cSrcweir             const XShapeHash::const_iterator aIter( maXShapeHash.find( xShape ));
377*cdf0e10cSrcweir             if( aIter == maXShapeHash.end() )
378*cdf0e10cSrcweir                 return ShapeSharedPtr(); // not found
379*cdf0e10cSrcweir 
380*cdf0e10cSrcweir             // found, return data part of entry pair.
381*cdf0e10cSrcweir             return aIter->second;
382*cdf0e10cSrcweir         }
383*cdf0e10cSrcweir 
384*cdf0e10cSrcweir         AttributableShapeSharedPtr LayerManager::getSubsetShape( const AttributableShapeSharedPtr& 	rOrigShape,
385*cdf0e10cSrcweir                                                                  const DocTreeNode&					rTreeNode )
386*cdf0e10cSrcweir         {
387*cdf0e10cSrcweir             OSL_ASSERT( !maLayers.empty() ); // always at least background layer
388*cdf0e10cSrcweir 
389*cdf0e10cSrcweir             AttributableShapeSharedPtr pSubset;
390*cdf0e10cSrcweir 
391*cdf0e10cSrcweir             // shape already added?
392*cdf0e10cSrcweir             if( rOrigShape->createSubset( pSubset,
393*cdf0e10cSrcweir                                           rTreeNode ) )
394*cdf0e10cSrcweir             {
395*cdf0e10cSrcweir                 OSL_ENSURE( pSubset, "LayerManager::getSubsetShape(): failed to create subset" );
396*cdf0e10cSrcweir 
397*cdf0e10cSrcweir                 // don't add to shape hash, we're dupes to the
398*cdf0e10cSrcweir                 // original XShape anyway - all subset shapes return
399*cdf0e10cSrcweir                 // the same XShape as the original one.
400*cdf0e10cSrcweir 
401*cdf0e10cSrcweir                 // add shape to corresponding layer
402*cdf0e10cSrcweir                 implAddShape( pSubset );
403*cdf0e10cSrcweir 
404*cdf0e10cSrcweir                 // update original shape, it now shows less content
405*cdf0e10cSrcweir                 // (the subset is removed from its displayed
406*cdf0e10cSrcweir                 // output). Subset shape is updated within
407*cdf0e10cSrcweir                 // implAddShape().
408*cdf0e10cSrcweir                 if( rOrigShape->isVisible() )
409*cdf0e10cSrcweir                     notifyShapeUpdate( rOrigShape );
410*cdf0e10cSrcweir             }
411*cdf0e10cSrcweir 
412*cdf0e10cSrcweir             return pSubset;
413*cdf0e10cSrcweir         }
414*cdf0e10cSrcweir 
415*cdf0e10cSrcweir         void LayerManager::revokeSubset( const AttributableShapeSharedPtr& rOrigShape,
416*cdf0e10cSrcweir                                          const AttributableShapeSharedPtr& rSubsetShape )
417*cdf0e10cSrcweir         {
418*cdf0e10cSrcweir             OSL_ASSERT( !maLayers.empty() ); // always at least background layer
419*cdf0e10cSrcweir 
420*cdf0e10cSrcweir             if( rOrigShape->revokeSubset( rSubsetShape ) )
421*cdf0e10cSrcweir             {
422*cdf0e10cSrcweir                 OSL_ASSERT( maAllShapes.find(rSubsetShape) != maAllShapes.end() );
423*cdf0e10cSrcweir 
424*cdf0e10cSrcweir                 implRemoveShape( rSubsetShape );
425*cdf0e10cSrcweir 
426*cdf0e10cSrcweir                 // update original shape, it now shows more content
427*cdf0e10cSrcweir                 // (the subset is added back to its displayed output)
428*cdf0e10cSrcweir                 if( rOrigShape->isVisible() )
429*cdf0e10cSrcweir                     notifyShapeUpdate( rOrigShape );
430*cdf0e10cSrcweir             }
431*cdf0e10cSrcweir         }
432*cdf0e10cSrcweir 
433*cdf0e10cSrcweir         void LayerManager::enterAnimationMode( const AnimatableShapeSharedPtr& rShape )
434*cdf0e10cSrcweir         {
435*cdf0e10cSrcweir             OSL_ASSERT( !maLayers.empty() ); // always at least background layer
436*cdf0e10cSrcweir             ENSURE_OR_THROW( rShape, "LayerManager::enterAnimationMode(): invalid Shape" );
437*cdf0e10cSrcweir 
438*cdf0e10cSrcweir             const bool bPrevAnimState( rShape->isBackgroundDetached() );
439*cdf0e10cSrcweir 
440*cdf0e10cSrcweir             rShape->enterAnimationMode();
441*cdf0e10cSrcweir 
442*cdf0e10cSrcweir             // if this call _really_ enabled the animation mode at
443*cdf0e10cSrcweir             // rShape, insert it to our enter animation queue, to
444*cdf0e10cSrcweir             // perform the necessary layer reorg lazily on
445*cdf0e10cSrcweir             // LayerManager::update()/render().
446*cdf0e10cSrcweir             if( bPrevAnimState != rShape->isBackgroundDetached() )
447*cdf0e10cSrcweir             {
448*cdf0e10cSrcweir                 ++mnActiveSprites;
449*cdf0e10cSrcweir                 mbLayerAssociationDirty = true;
450*cdf0e10cSrcweir 
451*cdf0e10cSrcweir                 // area needs update (shape is removed from normal
452*cdf0e10cSrcweir                 // slide, and now rendered as an autonomous
453*cdf0e10cSrcweir                 // sprite). store in update set
454*cdf0e10cSrcweir                 if( rShape->isVisible() )
455*cdf0e10cSrcweir                     addUpdateArea( rShape );
456*cdf0e10cSrcweir             }
457*cdf0e10cSrcweir 
458*cdf0e10cSrcweir             // TODO(P1): this can lead to potential wasted effort, if
459*cdf0e10cSrcweir             // a shape gets toggled animated/unanimated a few times
460*cdf0e10cSrcweir             // between two frames, returning to the original state.
461*cdf0e10cSrcweir         }
462*cdf0e10cSrcweir 
463*cdf0e10cSrcweir         void LayerManager::leaveAnimationMode( const AnimatableShapeSharedPtr& rShape )
464*cdf0e10cSrcweir         {
465*cdf0e10cSrcweir             ENSURE_OR_THROW( !maLayers.empty(), "LayerManager::leaveAnimationMode(): no layers" );
466*cdf0e10cSrcweir             ENSURE_OR_THROW( rShape, "LayerManager::leaveAnimationMode(): invalid Shape" );
467*cdf0e10cSrcweir 
468*cdf0e10cSrcweir             const bool bPrevAnimState( rShape->isBackgroundDetached() );
469*cdf0e10cSrcweir 
470*cdf0e10cSrcweir             rShape->leaveAnimationMode();
471*cdf0e10cSrcweir 
472*cdf0e10cSrcweir             // if this call _really_ ended the animation mode at
473*cdf0e10cSrcweir             // rShape, insert it to our leave animation queue, to
474*cdf0e10cSrcweir             // perform the necessary layer reorg lazily on
475*cdf0e10cSrcweir             // LayerManager::update()/render().
476*cdf0e10cSrcweir             if( bPrevAnimState != rShape->isBackgroundDetached() )
477*cdf0e10cSrcweir             {
478*cdf0e10cSrcweir                 --mnActiveSprites;
479*cdf0e10cSrcweir                 mbLayerAssociationDirty = true;
480*cdf0e10cSrcweir 
481*cdf0e10cSrcweir                 // shape needs update, no previous rendering, fast
482*cdf0e10cSrcweir                 // update possible.
483*cdf0e10cSrcweir                 if( rShape->isVisible() )
484*cdf0e10cSrcweir                     notifyShapeUpdate( rShape );
485*cdf0e10cSrcweir             }
486*cdf0e10cSrcweir 
487*cdf0e10cSrcweir             // TODO(P1): this can lead to potential wasted effort, if
488*cdf0e10cSrcweir             // a shape gets toggled animated/unanimated a few times
489*cdf0e10cSrcweir             // between two frames, returning to the original state.
490*cdf0e10cSrcweir         }
491*cdf0e10cSrcweir 
492*cdf0e10cSrcweir         void LayerManager::notifyShapeUpdate( const ShapeSharedPtr& rShape )
493*cdf0e10cSrcweir         {
494*cdf0e10cSrcweir             if( !mbActive || mrViews.empty() )
495*cdf0e10cSrcweir                 return;
496*cdf0e10cSrcweir 
497*cdf0e10cSrcweir             // hidden sprite-shape needs render() call still, to hide sprite
498*cdf0e10cSrcweir             if( rShape->isVisible() || rShape->isBackgroundDetached() )
499*cdf0e10cSrcweir                 maUpdateShapes.insert( rShape );
500*cdf0e10cSrcweir             else
501*cdf0e10cSrcweir                 addUpdateArea( rShape );
502*cdf0e10cSrcweir         }
503*cdf0e10cSrcweir 
504*cdf0e10cSrcweir         bool LayerManager::isUpdatePending() const
505*cdf0e10cSrcweir         {
506*cdf0e10cSrcweir             if( !mbActive )
507*cdf0e10cSrcweir                 return false;
508*cdf0e10cSrcweir 
509*cdf0e10cSrcweir             if( mbLayerAssociationDirty || !maUpdateShapes.empty() )
510*cdf0e10cSrcweir                 return true;
511*cdf0e10cSrcweir 
512*cdf0e10cSrcweir             const LayerVector::const_iterator aEnd( maLayers.end() );
513*cdf0e10cSrcweir             if( std::find_if( maLayers.begin(),
514*cdf0e10cSrcweir                               aEnd,
515*cdf0e10cSrcweir                               boost::mem_fn(&Layer::isUpdatePending)) != aEnd )
516*cdf0e10cSrcweir                 return true;
517*cdf0e10cSrcweir 
518*cdf0e10cSrcweir             return false;
519*cdf0e10cSrcweir         }
520*cdf0e10cSrcweir 
521*cdf0e10cSrcweir         bool LayerManager::updateSprites()
522*cdf0e10cSrcweir         {
523*cdf0e10cSrcweir             bool bRet(true);
524*cdf0e10cSrcweir 
525*cdf0e10cSrcweir             // send update() calls to every shape in the
526*cdf0e10cSrcweir             // maUpdateShapes set, which is _animated_ (i.e. a
527*cdf0e10cSrcweir             // sprite).
528*cdf0e10cSrcweir             const ShapeUpdateSet::const_iterator aEnd=maUpdateShapes.end();
529*cdf0e10cSrcweir             ShapeUpdateSet::const_iterator 	     aCurrShape=maUpdateShapes.begin();
530*cdf0e10cSrcweir             while( aCurrShape != aEnd )
531*cdf0e10cSrcweir             {
532*cdf0e10cSrcweir                 if( (*aCurrShape)->isBackgroundDetached() )
533*cdf0e10cSrcweir                 {
534*cdf0e10cSrcweir                     // can update shape directly, without
535*cdf0e10cSrcweir                     // affecting layer content (shape is
536*cdf0e10cSrcweir                     // currently displayed in a sprite)
537*cdf0e10cSrcweir                     if( !(*aCurrShape)->update() )
538*cdf0e10cSrcweir                         bRet = false; // delay error exit
539*cdf0e10cSrcweir                 }
540*cdf0e10cSrcweir                 else
541*cdf0e10cSrcweir                 {
542*cdf0e10cSrcweir                     // TODO(P2): addUpdateArea() involves log(n)
543*cdf0e10cSrcweir                     // search for shape layer. Have a frequent
544*cdf0e10cSrcweir                     // shape/layer association cache, or ptr back to
545*cdf0e10cSrcweir                     // layer at the shape?
546*cdf0e10cSrcweir 
547*cdf0e10cSrcweir                     // cannot update shape directly, it's not
548*cdf0e10cSrcweir                     // animated and update() calls will prolly
549*cdf0e10cSrcweir                     // overwrite other page content.
550*cdf0e10cSrcweir                     addUpdateArea( *aCurrShape );
551*cdf0e10cSrcweir                 }
552*cdf0e10cSrcweir 
553*cdf0e10cSrcweir                 ++aCurrShape;
554*cdf0e10cSrcweir             }
555*cdf0e10cSrcweir 
556*cdf0e10cSrcweir             maUpdateShapes.clear();
557*cdf0e10cSrcweir 
558*cdf0e10cSrcweir             return bRet;
559*cdf0e10cSrcweir         }
560*cdf0e10cSrcweir 
561*cdf0e10cSrcweir         bool LayerManager::update()
562*cdf0e10cSrcweir         {
563*cdf0e10cSrcweir             bool bRet = true;
564*cdf0e10cSrcweir 
565*cdf0e10cSrcweir             if( !mbActive )
566*cdf0e10cSrcweir                 return bRet;
567*cdf0e10cSrcweir 
568*cdf0e10cSrcweir             // going to render - better flush any pending layer reorg
569*cdf0e10cSrcweir             // now
570*cdf0e10cSrcweir             updateShapeLayers(false);
571*cdf0e10cSrcweir 
572*cdf0e10cSrcweir             // all sprites
573*cdf0e10cSrcweir             bRet = updateSprites();
574*cdf0e10cSrcweir 
575*cdf0e10cSrcweir             // any non-sprite update areas left?
576*cdf0e10cSrcweir             if( std::find_if( maLayers.begin(),
577*cdf0e10cSrcweir                               maLayers.end(),
578*cdf0e10cSrcweir                               boost::mem_fn( &Layer::isUpdatePending )) == maLayers.end() )
579*cdf0e10cSrcweir                 return bRet; // nope, done.
580*cdf0e10cSrcweir 
581*cdf0e10cSrcweir             // update each shape on each layer, that has
582*cdf0e10cSrcweir             // isUpdatePending()
583*cdf0e10cSrcweir             bool                                bIsCurrLayerUpdating(false);
584*cdf0e10cSrcweir             Layer::EndUpdater                   aEndUpdater;
585*cdf0e10cSrcweir             LayerSharedPtr                      pCurrLayer;
586*cdf0e10cSrcweir             LayerShapeMap::const_iterator       aIter( maAllShapes.begin() );
587*cdf0e10cSrcweir             const LayerShapeMap::const_iterator aEnd ( maAllShapes.end() );
588*cdf0e10cSrcweir             while( aIter != aEnd )
589*cdf0e10cSrcweir             {
590*cdf0e10cSrcweir                 LayerSharedPtr pLayer = aIter->second.lock();
591*cdf0e10cSrcweir                 if( pLayer != pCurrLayer )
592*cdf0e10cSrcweir                 {
593*cdf0e10cSrcweir                     pCurrLayer = pLayer;
594*cdf0e10cSrcweir                     bIsCurrLayerUpdating = pCurrLayer->isUpdatePending();
595*cdf0e10cSrcweir 
596*cdf0e10cSrcweir                     if( bIsCurrLayerUpdating )
597*cdf0e10cSrcweir                         aEndUpdater = pCurrLayer->beginUpdate();
598*cdf0e10cSrcweir                 }
599*cdf0e10cSrcweir 
600*cdf0e10cSrcweir                 if( bIsCurrLayerUpdating &&
601*cdf0e10cSrcweir                     !aIter->first->isBackgroundDetached() &&
602*cdf0e10cSrcweir                     pCurrLayer->isInsideUpdateArea(aIter->first) )
603*cdf0e10cSrcweir                 {
604*cdf0e10cSrcweir                     if( !aIter->first->render() )
605*cdf0e10cSrcweir                         bRet = false;
606*cdf0e10cSrcweir                 }
607*cdf0e10cSrcweir 
608*cdf0e10cSrcweir                 ++aIter;
609*cdf0e10cSrcweir             }
610*cdf0e10cSrcweir 
611*cdf0e10cSrcweir             return bRet;
612*cdf0e10cSrcweir         }
613*cdf0e10cSrcweir 
614*cdf0e10cSrcweir         namespace
615*cdf0e10cSrcweir         {
616*cdf0e10cSrcweir             /** Little wrapper around a Canvas, to render one-shot
617*cdf0e10cSrcweir                 into a canvas
618*cdf0e10cSrcweir              */
619*cdf0e10cSrcweir             class DummyLayer : public ViewLayer
620*cdf0e10cSrcweir             {
621*cdf0e10cSrcweir             public:
622*cdf0e10cSrcweir                 explicit DummyLayer( const ::cppcanvas::CanvasSharedPtr& rCanvas ) :
623*cdf0e10cSrcweir                     mpCanvas( rCanvas )
624*cdf0e10cSrcweir                 {
625*cdf0e10cSrcweir                 }
626*cdf0e10cSrcweir 
627*cdf0e10cSrcweir                 virtual bool isOnView(boost::shared_ptr<View> const& /*rView*/) const
628*cdf0e10cSrcweir                 {
629*cdf0e10cSrcweir                     return true; // visible on all views
630*cdf0e10cSrcweir                 }
631*cdf0e10cSrcweir 
632*cdf0e10cSrcweir                 virtual ::cppcanvas::CanvasSharedPtr getCanvas() const
633*cdf0e10cSrcweir                 {
634*cdf0e10cSrcweir                     return mpCanvas;
635*cdf0e10cSrcweir                 }
636*cdf0e10cSrcweir 
637*cdf0e10cSrcweir                 virtual void clear() const
638*cdf0e10cSrcweir                 {
639*cdf0e10cSrcweir                     // NOOP
640*cdf0e10cSrcweir                 }
641*cdf0e10cSrcweir 
642*cdf0e10cSrcweir                 virtual void clearAll() const
643*cdf0e10cSrcweir                 {
644*cdf0e10cSrcweir                     // NOOP
645*cdf0e10cSrcweir                 }
646*cdf0e10cSrcweir 
647*cdf0e10cSrcweir                 virtual ::cppcanvas::CustomSpriteSharedPtr createSprite( const ::basegfx::B2DSize& /*rSpriteSizePixel*/,
648*cdf0e10cSrcweir                                                                          double                    /*nSpritePrio*/ ) const
649*cdf0e10cSrcweir                 {
650*cdf0e10cSrcweir                     ENSURE_OR_THROW( false,
651*cdf0e10cSrcweir                                       "DummyLayer::createSprite(): This method is not supposed to be called!" );
652*cdf0e10cSrcweir                     return ::cppcanvas::CustomSpriteSharedPtr();
653*cdf0e10cSrcweir                 }
654*cdf0e10cSrcweir 
655*cdf0e10cSrcweir                 virtual void setPriority( const basegfx::B1DRange& /*rRange*/ )
656*cdf0e10cSrcweir                 {
657*cdf0e10cSrcweir                     OSL_ENSURE( false,
658*cdf0e10cSrcweir                                 "BitmapView::setPriority(): This method is not supposed to be called!" );
659*cdf0e10cSrcweir                 }
660*cdf0e10cSrcweir 
661*cdf0e10cSrcweir                 virtual ::basegfx::B2DHomMatrix getTransformation() const
662*cdf0e10cSrcweir                 {
663*cdf0e10cSrcweir                     return mpCanvas->getTransformation();
664*cdf0e10cSrcweir                 }
665*cdf0e10cSrcweir 
666*cdf0e10cSrcweir                 virtual ::basegfx::B2DHomMatrix getSpriteTransformation() const
667*cdf0e10cSrcweir                 {
668*cdf0e10cSrcweir                     OSL_ENSURE( false,
669*cdf0e10cSrcweir                                 "BitmapView::getSpriteTransformation(): This method is not supposed to be called!" );
670*cdf0e10cSrcweir                     return ::basegfx::B2DHomMatrix();
671*cdf0e10cSrcweir                 }
672*cdf0e10cSrcweir 
673*cdf0e10cSrcweir                 virtual void setClip( const ::basegfx::B2DPolyPolygon& /*rClip*/ )
674*cdf0e10cSrcweir                 {
675*cdf0e10cSrcweir                     OSL_ENSURE( false,
676*cdf0e10cSrcweir                                 "BitmapView::setClip(): This method is not supposed to be called!" );
677*cdf0e10cSrcweir                 }
678*cdf0e10cSrcweir 
679*cdf0e10cSrcweir                 virtual bool resize( const ::basegfx::B2DRange& /*rArea*/ )
680*cdf0e10cSrcweir                 {
681*cdf0e10cSrcweir                     OSL_ENSURE( false,
682*cdf0e10cSrcweir                                 "BitmapView::resize(): This method is not supposed to be called!" );
683*cdf0e10cSrcweir                     return false;
684*cdf0e10cSrcweir                 }
685*cdf0e10cSrcweir 
686*cdf0e10cSrcweir             private:
687*cdf0e10cSrcweir                 ::cppcanvas::CanvasSharedPtr mpCanvas;
688*cdf0e10cSrcweir             };
689*cdf0e10cSrcweir         }
690*cdf0e10cSrcweir 
691*cdf0e10cSrcweir         bool LayerManager::renderTo( const ::cppcanvas::CanvasSharedPtr& rTargetCanvas ) const
692*cdf0e10cSrcweir         {
693*cdf0e10cSrcweir             bool bRet( true );
694*cdf0e10cSrcweir             ViewLayerSharedPtr pTmpLayer( new DummyLayer( rTargetCanvas ) );
695*cdf0e10cSrcweir 
696*cdf0e10cSrcweir             LayerShapeMap::const_iterator       aIter( maAllShapes.begin() );
697*cdf0e10cSrcweir             const LayerShapeMap::const_iterator aEnd ( maAllShapes.end() );
698*cdf0e10cSrcweir             while( aIter != aEnd )
699*cdf0e10cSrcweir             {
700*cdf0e10cSrcweir                 try
701*cdf0e10cSrcweir                 {
702*cdf0e10cSrcweir                     // forward to all shape's addViewLayer method (which
703*cdf0e10cSrcweir                     // we request to render the Shape on the new
704*cdf0e10cSrcweir                     // ViewLayer. Since we add the shapes in the
705*cdf0e10cSrcweir                     // maShapeSet order (which is also the render order),
706*cdf0e10cSrcweir                     // this is equivalent to a subsequent render() call)
707*cdf0e10cSrcweir                     aIter->first->addViewLayer( pTmpLayer,
708*cdf0e10cSrcweir                                                 true );
709*cdf0e10cSrcweir 
710*cdf0e10cSrcweir                     // and remove again, this is only temporary
711*cdf0e10cSrcweir                     aIter->first->removeViewLayer( pTmpLayer );
712*cdf0e10cSrcweir                 }
713*cdf0e10cSrcweir                 catch( uno::Exception& )
714*cdf0e10cSrcweir                 {
715*cdf0e10cSrcweir                     // TODO(E1): Might be superfluous. Nowadays,
716*cdf0e10cSrcweir                     // addViewLayer swallows all errors, anyway.
717*cdf0e10cSrcweir                     OSL_ENSURE( false,
718*cdf0e10cSrcweir                                 rtl::OUStringToOString(
719*cdf0e10cSrcweir                                     comphelper::anyToString( cppu::getCaughtException() ),
720*cdf0e10cSrcweir                                     RTL_TEXTENCODING_UTF8 ).getStr() );
721*cdf0e10cSrcweir 
722*cdf0e10cSrcweir                     // at least one shape could not be rendered
723*cdf0e10cSrcweir                     bRet = false;
724*cdf0e10cSrcweir                 }
725*cdf0e10cSrcweir 
726*cdf0e10cSrcweir                 ++aIter;
727*cdf0e10cSrcweir             }
728*cdf0e10cSrcweir 
729*cdf0e10cSrcweir             return bRet;
730*cdf0e10cSrcweir         }
731*cdf0e10cSrcweir 
732*cdf0e10cSrcweir         void LayerManager::addUpdateArea( ShapeSharedPtr const& rShape )
733*cdf0e10cSrcweir         {
734*cdf0e10cSrcweir             OSL_ASSERT( !maLayers.empty() ); // always at least background layer
735*cdf0e10cSrcweir             ENSURE_OR_THROW( rShape, "LayerManager::addUpdateArea(): invalid Shape" );
736*cdf0e10cSrcweir 
737*cdf0e10cSrcweir             const LayerShapeMap::const_iterator aShapeEntry( maAllShapes.find(rShape) );
738*cdf0e10cSrcweir 
739*cdf0e10cSrcweir             if( aShapeEntry == maAllShapes.end() )
740*cdf0e10cSrcweir                 return;
741*cdf0e10cSrcweir 
742*cdf0e10cSrcweir             LayerSharedPtr pLayer = aShapeEntry->second.lock();
743*cdf0e10cSrcweir             if( pLayer )
744*cdf0e10cSrcweir                 pLayer->addUpdateRange( rShape->getUpdateArea() );
745*cdf0e10cSrcweir         }
746*cdf0e10cSrcweir 
747*cdf0e10cSrcweir         void LayerManager::commitLayerChanges( std::size_t              nCurrLayerIndex,
748*cdf0e10cSrcweir                                                LayerShapeMap::const_iterator  aFirstLayerShape,
749*cdf0e10cSrcweir                                                LayerShapeMap::const_iterator  aEndLayerShapes )
750*cdf0e10cSrcweir         {
751*cdf0e10cSrcweir             const bool bLayerExists( maLayers.size() > nCurrLayerIndex );
752*cdf0e10cSrcweir             if( bLayerExists )
753*cdf0e10cSrcweir             {
754*cdf0e10cSrcweir                 const LayerSharedPtr& rLayer( maLayers.at(nCurrLayerIndex) );
755*cdf0e10cSrcweir                 const bool bLayerResized( rLayer->commitBounds() );
756*cdf0e10cSrcweir                 rLayer->setPriority( basegfx::B1DRange(nCurrLayerIndex,
757*cdf0e10cSrcweir                                                        nCurrLayerIndex+1) );
758*cdf0e10cSrcweir 
759*cdf0e10cSrcweir                 if( bLayerResized )
760*cdf0e10cSrcweir                 {
761*cdf0e10cSrcweir                     // need to re-render whole layer - start from
762*cdf0e10cSrcweir                     // clean state
763*cdf0e10cSrcweir                     rLayer->clearContent();
764*cdf0e10cSrcweir 
765*cdf0e10cSrcweir                     // render and remove from update set
766*cdf0e10cSrcweir                     while( aFirstLayerShape != aEndLayerShapes )
767*cdf0e10cSrcweir                     {
768*cdf0e10cSrcweir                         maUpdateShapes.erase(aFirstLayerShape->first);
769*cdf0e10cSrcweir                         aFirstLayerShape->first->render();
770*cdf0e10cSrcweir                         ++aFirstLayerShape;
771*cdf0e10cSrcweir                     }
772*cdf0e10cSrcweir                 }
773*cdf0e10cSrcweir             }
774*cdf0e10cSrcweir         }
775*cdf0e10cSrcweir 
776*cdf0e10cSrcweir         LayerSharedPtr LayerManager::createForegroundLayer() const
777*cdf0e10cSrcweir         {
778*cdf0e10cSrcweir             OSL_ASSERT( mbActive );
779*cdf0e10cSrcweir 
780*cdf0e10cSrcweir             LayerSharedPtr pLayer( Layer::createLayer(
781*cdf0e10cSrcweir                                        maPageBounds ));
782*cdf0e10cSrcweir 
783*cdf0e10cSrcweir             // create ViewLayers for all registered views, and add to
784*cdf0e10cSrcweir             // newly created layer.
785*cdf0e10cSrcweir             ::std::for_each( mrViews.begin(),
786*cdf0e10cSrcweir                              mrViews.end(),
787*cdf0e10cSrcweir                              boost::bind( &Layer::addView,
788*cdf0e10cSrcweir                                           boost::cref(pLayer),
789*cdf0e10cSrcweir                                           _1 ));
790*cdf0e10cSrcweir 
791*cdf0e10cSrcweir             return pLayer;
792*cdf0e10cSrcweir         }
793*cdf0e10cSrcweir 
794*cdf0e10cSrcweir         void LayerManager::updateShapeLayers( bool bBackgroundLayerPainted )
795*cdf0e10cSrcweir         {
796*cdf0e10cSrcweir             OSL_ASSERT( !maLayers.empty() ); // always at least background layer
797*cdf0e10cSrcweir             OSL_ASSERT( mbActive );
798*cdf0e10cSrcweir 
799*cdf0e10cSrcweir             // do we need to process shapes?
800*cdf0e10cSrcweir             if( !mbLayerAssociationDirty )
801*cdf0e10cSrcweir                 return;
802*cdf0e10cSrcweir 
803*cdf0e10cSrcweir             if( mbDisableAnimationZOrder )
804*cdf0e10cSrcweir             {
805*cdf0e10cSrcweir                 // layer setup happened elsewhere, is only bg layer
806*cdf0e10cSrcweir                 // anyway.
807*cdf0e10cSrcweir                 mbLayerAssociationDirty = false;
808*cdf0e10cSrcweir                 return;
809*cdf0e10cSrcweir             }
810*cdf0e10cSrcweir 
811*cdf0e10cSrcweir             // scan through maAllShapes, and determine shape animation
812*cdf0e10cSrcweir             // discontinuities: when a shape that has
813*cdf0e10cSrcweir             // isBackgroundDetached() return false follows a shape
814*cdf0e10cSrcweir             // with isBackgroundDetached() true, the former and all
815*cdf0e10cSrcweir             // following ones must be moved into an own layer.
816*cdf0e10cSrcweir 
817*cdf0e10cSrcweir             // to avoid tons of temporaries, create weak_ptr to Layers
818*cdf0e10cSrcweir             // beforehand
819*cdf0e10cSrcweir             std::vector< LayerWeakPtr > aWeakLayers(maLayers.size());
820*cdf0e10cSrcweir             std::copy(maLayers.begin(),maLayers.end(),aWeakLayers.begin());
821*cdf0e10cSrcweir 
822*cdf0e10cSrcweir             std::size_t                   nCurrLayerIndex(0);
823*cdf0e10cSrcweir             bool                          bIsBackgroundLayer(true);
824*cdf0e10cSrcweir             bool                          bLastWasBackgroundDetached(false); // last shape sprite state
825*cdf0e10cSrcweir             LayerShapeMap::iterator       aCurrShapeEntry( maAllShapes.begin() );
826*cdf0e10cSrcweir             LayerShapeMap::iterator       aCurrLayerFirstShapeEntry( maAllShapes.begin() );
827*cdf0e10cSrcweir             const LayerShapeMap::iterator aEndShapeEntry ( maAllShapes.end() );
828*cdf0e10cSrcweir             ShapeUpdateSet                aUpdatedShapes; // shapes that need update
829*cdf0e10cSrcweir             while( aCurrShapeEntry != aEndShapeEntry )
830*cdf0e10cSrcweir             {
831*cdf0e10cSrcweir                 const ShapeSharedPtr pCurrShape( aCurrShapeEntry->first );
832*cdf0e10cSrcweir                 const bool bThisIsBackgroundDetached(
833*cdf0e10cSrcweir                     pCurrShape->isBackgroundDetached() );
834*cdf0e10cSrcweir 
835*cdf0e10cSrcweir                 if( bLastWasBackgroundDetached == true &&
836*cdf0e10cSrcweir                     bThisIsBackgroundDetached == false )
837*cdf0e10cSrcweir                 {
838*cdf0e10cSrcweir                     // discontinuity found - current shape needs to
839*cdf0e10cSrcweir                     // get into a new layer
840*cdf0e10cSrcweir                     // --------------------------------------------
841*cdf0e10cSrcweir 
842*cdf0e10cSrcweir                     // commit changes to previous layer
843*cdf0e10cSrcweir                     commitLayerChanges(nCurrLayerIndex,
844*cdf0e10cSrcweir                                        aCurrLayerFirstShapeEntry,
845*cdf0e10cSrcweir                                        aCurrShapeEntry);
846*cdf0e10cSrcweir                     aCurrLayerFirstShapeEntry=aCurrShapeEntry;
847*cdf0e10cSrcweir                     ++nCurrLayerIndex;
848*cdf0e10cSrcweir                     bIsBackgroundLayer = false;
849*cdf0e10cSrcweir 
850*cdf0e10cSrcweir                     if( aWeakLayers.size() <= nCurrLayerIndex ||
851*cdf0e10cSrcweir                         aWeakLayers.at(nCurrLayerIndex) != aCurrShapeEntry->second )
852*cdf0e10cSrcweir                     {
853*cdf0e10cSrcweir                         // no more layers left, or shape was not
854*cdf0e10cSrcweir                         // member of this layer - create a new one
855*cdf0e10cSrcweir                         maLayers.insert( maLayers.begin()+nCurrLayerIndex,
856*cdf0e10cSrcweir                                          createForegroundLayer() );
857*cdf0e10cSrcweir                         aWeakLayers.insert( aWeakLayers.begin()+nCurrLayerIndex,
858*cdf0e10cSrcweir                                             maLayers[nCurrLayerIndex] );
859*cdf0e10cSrcweir                     }
860*cdf0e10cSrcweir                 }
861*cdf0e10cSrcweir 
862*cdf0e10cSrcweir                 OSL_ASSERT( maLayers.size() == aWeakLayers.size() );
863*cdf0e10cSrcweir 
864*cdf0e10cSrcweir                 // note: using indices here, since vector::insert
865*cdf0e10cSrcweir                 // above invalidates iterators
866*cdf0e10cSrcweir                 LayerSharedPtr& rCurrLayer( maLayers.at(nCurrLayerIndex) );
867*cdf0e10cSrcweir                 LayerWeakPtr& rCurrWeakLayer( aWeakLayers.at(nCurrLayerIndex) );
868*cdf0e10cSrcweir                 if( rCurrWeakLayer != aCurrShapeEntry->second )
869*cdf0e10cSrcweir                 {
870*cdf0e10cSrcweir                     // mismatch: shape is not contained in current
871*cdf0e10cSrcweir                     // layer - move shape to that layer, then.
872*cdf0e10cSrcweir                     maLayers.at(nCurrLayerIndex)->setShapeViews(
873*cdf0e10cSrcweir                         pCurrShape );
874*cdf0e10cSrcweir 
875*cdf0e10cSrcweir                     // layer got new shape(s), need full repaint, if
876*cdf0e10cSrcweir                     // non-sprite shape
877*cdf0e10cSrcweir                     if( !bThisIsBackgroundDetached && pCurrShape->isVisible() )
878*cdf0e10cSrcweir                     {
879*cdf0e10cSrcweir                         LayerSharedPtr pOldLayer( aCurrShapeEntry->second.lock() );
880*cdf0e10cSrcweir                         if( pOldLayer )
881*cdf0e10cSrcweir                         {
882*cdf0e10cSrcweir                             // old layer still valid? then we need to
883*cdf0e10cSrcweir                             // repaint former shape area
884*cdf0e10cSrcweir                             pOldLayer->addUpdateRange(
885*cdf0e10cSrcweir                                 pCurrShape->getUpdateArea() );
886*cdf0e10cSrcweir                         }
887*cdf0e10cSrcweir 
888*cdf0e10cSrcweir                         // render on new layer (only if not
889*cdf0e10cSrcweir                         // explicitely disabled)
890*cdf0e10cSrcweir                         if( !(bBackgroundLayerPainted && bIsBackgroundLayer) )
891*cdf0e10cSrcweir                             maUpdateShapes.insert( pCurrShape );
892*cdf0e10cSrcweir                     }
893*cdf0e10cSrcweir 
894*cdf0e10cSrcweir                     aCurrShapeEntry->second = rCurrWeakLayer;
895*cdf0e10cSrcweir                 }
896*cdf0e10cSrcweir 
897*cdf0e10cSrcweir                 // update layerbounds regardless of the fact that the
898*cdf0e10cSrcweir                 // shape might be contained in said layer
899*cdf0e10cSrcweir                 // already. updateBounds() is dumb and needs to
900*cdf0e10cSrcweir                 // collect all shape bounds.
901*cdf0e10cSrcweir                 // of course, no need to expand layer bounds for
902*cdf0e10cSrcweir                 // shapes that reside in sprites themselves.
903*cdf0e10cSrcweir                 if( !bThisIsBackgroundDetached && !bIsBackgroundLayer )
904*cdf0e10cSrcweir                     rCurrLayer->updateBounds( pCurrShape );
905*cdf0e10cSrcweir 
906*cdf0e10cSrcweir                 bLastWasBackgroundDetached = bThisIsBackgroundDetached;
907*cdf0e10cSrcweir                 ++aCurrShapeEntry;
908*cdf0e10cSrcweir             }
909*cdf0e10cSrcweir 
910*cdf0e10cSrcweir             // commit very last layer data
911*cdf0e10cSrcweir             commitLayerChanges(nCurrLayerIndex,
912*cdf0e10cSrcweir                                aCurrLayerFirstShapeEntry,
913*cdf0e10cSrcweir                                aCurrShapeEntry);
914*cdf0e10cSrcweir 
915*cdf0e10cSrcweir             // any layers left? Bin them!
916*cdf0e10cSrcweir             if( maLayers.size() > nCurrLayerIndex+1 )
917*cdf0e10cSrcweir                 maLayers.erase(maLayers.begin()+nCurrLayerIndex+1,
918*cdf0e10cSrcweir                                maLayers.end());
919*cdf0e10cSrcweir 
920*cdf0e10cSrcweir             mbLayerAssociationDirty = false;
921*cdf0e10cSrcweir         }
922*cdf0e10cSrcweir     }
923*cdf0e10cSrcweir }
924