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