1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <canvas/debug.hxx>
22 #include <tools/diagnose_ex.h>
23 #include <basegfx/range/b1drange.hxx>
24 #include <basegfx/matrix/b2dhommatrix.hxx>
26 #include <comphelper/anytostring.hxx>
27 #include <cppuhelper/exc_hlp.hxx>
29 #include <boost/bind.hpp>
32 #include <o3tl/compat_functional.hxx>
34 #include "layermanager.hxx"
36 using namespace ::com::sun::star
;
40 // add operator!= for weak_ptr
41 inline bool operator!=( slideshow::internal::LayerWeakPtr
const& rLHS
,
42 slideshow::internal::LayerWeakPtr
const& rRHS
)
44 return (rLHS
<rRHS
) || (rRHS
<rLHS
);
52 template<typename LayerFunc
,
53 typename ShapeFunc
> void LayerManager::manageViews(
57 LayerSharedPtr pCurrLayer
;
58 ViewLayerSharedPtr pCurrViewLayer
;
59 LayerShapeMap::const_iterator
aIter( maAllShapes
.begin() );
60 const LayerShapeMap::const_iterator
aEnd ( maAllShapes
.end() );
61 while( aIter
!= aEnd
)
63 LayerSharedPtr pLayer
= aIter
->second
.lock();
64 if( pLayer
&& pLayer
!= pCurrLayer
)
67 pCurrViewLayer
= layerFunc(pCurrLayer
);
71 shapeFunc(aIter
->first
,pCurrViewLayer
);
77 LayerManager::LayerManager( const UnoViewContainer
& rViews
,
78 const ::basegfx::B2DRange
& rPageBounds
,
79 bool bDisableAnimationZOrder
) :
85 maPageBounds( rPageBounds
),
87 mbLayerAssociationDirty(false),
89 mbDisableAnimationZOrder(bDisableAnimationZOrder
)
91 // prevent frequent resizes (won't have more than 4 layers
92 // for 99.9% of the cases)
95 // create initial background layer
97 Layer::createBackgroundLayer(
101 std::for_each( mrViews
.begin(),
103 ::boost::bind(&LayerManager::viewAdded
,
108 void LayerManager::activate( bool bSlideBackgoundPainted
)
111 maUpdateShapes
.clear(); // update gets forced via area, or
112 // has happened outside already
114 if( !bSlideBackgoundPainted
)
116 std::for_each(mrViews
.begin(),
118 boost::mem_fn(&View::clearAll
));
120 // force update of whole slide area
121 std::for_each( maLayers
.begin(),
123 boost::bind( &Layer::addUpdateRange
,
125 boost::cref(maPageBounds
) ));
129 // clear all possibly pending update areas - content
131 std::for_each( maLayers
.begin(),
133 boost::mem_fn( &Layer::clearUpdateRanges
));
136 updateShapeLayers( bSlideBackgoundPainted
);
139 void LayerManager::deactivate()
141 // TODO(F3): This is mostly a hack. Problem is, there's
142 // currently no smart way of telling shapes "remove your
143 // sprites". Others, like MediaShapes, listen to
144 // start/stop animation events, which is too much overhead
145 // for all shapes, though.
147 const bool bMoreThanOneLayer(maLayers
.size() > 1);
148 if( mnActiveSprites
|| bMoreThanOneLayer
)
150 // clear all viewlayers, dump everything but the
151 // background layer - this will also remove all shape
153 std::for_each(maAllShapes
.begin(),
155 boost::bind( &Shape::clearAllViewLayers
,
156 boost::bind( o3tl::select1st
<LayerShapeMap::value_type
>(),
159 for (LayerShapeMap::iterator
160 iShape (maAllShapes
.begin()),
161 iEnd (maAllShapes
.end());
165 iShape
->second
.reset();
168 if( bMoreThanOneLayer
)
169 maLayers
.erase(maLayers
.begin()+1,
172 mbLayerAssociationDirty
= true;
177 // only background layer left
178 OSL_ASSERT( maLayers
.size() == 1 && maLayers
.front()->isBackgroundLayer() );
181 void LayerManager::viewAdded( const UnoViewSharedPtr
& rView
)
183 // view must be member of mrViews container
184 OSL_ASSERT( std::find(mrViews
.begin(),
186 rView
) != mrViews
.end() );
192 // add View to all registered shapes
194 boost::bind(&Layer::addView
,
197 // repaint on view add
198 boost::bind(&Shape::addViewLayer
,
203 // in case we haven't reached all layers from the
204 // maAllShapes, issue addView again for good measure
205 std::for_each( maLayers
.begin(),
207 boost::bind( &Layer::addView
,
209 boost::cref(rView
) ));
212 void LayerManager::viewRemoved( const UnoViewSharedPtr
& rView
)
214 // view must not be member of mrViews container anymore
215 OSL_ASSERT( std::find(mrViews
.begin(),
217 rView
) == mrViews
.end() );
219 // remove View from all registered shapes
221 boost::bind(&Layer::removeView
,
224 boost::bind(&Shape::removeViewLayer
,
228 // in case we haven't reached all layers from the
229 // maAllShapes, issue removeView again for good measure
230 std::for_each( maLayers
.begin(),
232 boost::bind( &Layer::removeView
,
234 boost::cref(rView
) ));
237 void LayerManager::viewChanged( const UnoViewSharedPtr
& rView
)
241 // view must be member of mrViews container
242 OSL_ASSERT( std::find(mrViews
.begin(),
244 rView
) != mrViews
.end() );
246 // TODO(P2): selectively update only changed view
250 void LayerManager::viewsChanged()
256 ::std::for_each( mrViews
.begin(),
258 ::boost::mem_fn(&View::clearAll
) );
260 // TODO(F3): resize and repaint all layers
263 std::for_each( maAllShapes
.begin(),
265 boost::bind(&Shape::render
,
266 boost::bind( ::o3tl::select1st
<LayerShapeMap::value_type
>(), _1
)) );
269 void LayerManager::addShape( const ShapeSharedPtr
& rShape
)
271 OSL_ASSERT( !maLayers
.empty() ); // always at least background layer
272 ENSURE_OR_THROW( rShape
, "LayerManager::addShape(): invalid Shape" );
274 // add shape to XShape hash map
275 if( !maXShapeHash
.insert(
276 XShapeHash::value_type( rShape
->getXShape(),
279 // entry already present, nothing to do
283 // add shape to appropriate layer
284 implAddShape( rShape
);
287 void LayerManager::putShape2BackgroundLayer( LayerShapeMap::value_type
& rShapeEntry
)
289 LayerSharedPtr
& rBgLayer( maLayers
.front() );
290 rBgLayer
->setShapeViews(rShapeEntry
.first
);
291 rShapeEntry
.second
= rBgLayer
;
294 void LayerManager::implAddShape( const ShapeSharedPtr
& rShape
)
296 OSL_ASSERT( !maLayers
.empty() ); // always at least background layer
297 ENSURE_OR_THROW( rShape
, "LayerManager::implAddShape(): invalid Shape" );
299 LayerShapeMap::value_type
aValue (rShape
, LayerWeakPtr());
301 OSL_ASSERT( maAllShapes
.find(rShape
) == maAllShapes
.end() ); // shape must not be added already
302 mbLayerAssociationDirty
= true;
304 if( mbDisableAnimationZOrder
)
305 putShape2BackgroundLayer(
306 *maAllShapes
.insert(aValue
).first
);
308 maAllShapes
.insert(aValue
);
310 // update shape, it's just added and not yet painted
311 if( rShape
->isVisible() )
312 notifyShapeUpdate( rShape
);
315 void LayerManager::implRemoveShape( const ShapeSharedPtr
& rShape
)
317 OSL_ASSERT( !maLayers
.empty() ); // always at least background layer
318 ENSURE_OR_THROW( rShape
, "LayerManager::implRemoveShape(): invalid Shape" );
320 const LayerShapeMap::iterator
aShapeEntry( maAllShapes
.find(rShape
) );
322 if( aShapeEntry
== maAllShapes
.end() )
325 const bool bShapeUpdateNotified
= maUpdateShapes
.erase( rShape
) != 0;
327 // Enter shape area to the update area, but only if shape
328 // is visible and not in sprite mode (otherwise, updating
329 // the area doesn't do actual harm, but costs time)
330 // Actually, also add it if it was listed in
331 // maUpdateShapes (might have just gone invisible).
332 if( bShapeUpdateNotified
||
333 (rShape
->isVisible() &&
334 !rShape
->isBackgroundDetached()) )
336 LayerSharedPtr pLayer
= aShapeEntry
->second
.lock();
339 // store area early, once the shape is removed from
340 // the layers, it no longer has any view references
341 pLayer
->addUpdateRange( rShape
->getUpdateArea() );
345 rShape
->clearAllViewLayers();
346 maAllShapes
.erase( aShapeEntry
);
348 mbLayerAssociationDirty
= true;
351 ShapeSharedPtr
LayerManager::lookupShape( const uno::Reference
< drawing::XShape
>& xShape
) const
353 ENSURE_OR_THROW( xShape
.is(), "LayerManager::lookupShape(): invalid Shape" );
355 const XShapeHash::const_iterator
aIter( maXShapeHash
.find( xShape
));
356 if( aIter
== maXShapeHash
.end() )
357 return ShapeSharedPtr(); // not found
359 // found, return data part of entry pair.
360 return aIter
->second
;
363 AttributableShapeSharedPtr
LayerManager::getSubsetShape( const AttributableShapeSharedPtr
& rOrigShape
,
364 const DocTreeNode
& rTreeNode
)
366 OSL_ASSERT( !maLayers
.empty() ); // always at least background layer
368 AttributableShapeSharedPtr pSubset
;
370 // shape already added?
371 if( rOrigShape
->createSubset( pSubset
,
374 OSL_ENSURE( pSubset
, "LayerManager::getSubsetShape(): failed to create subset" );
376 // don't add to shape hash, we're dupes to the
377 // original XShape anyway - all subset shapes return
378 // the same XShape as the original one.
380 // add shape to corresponding layer
381 implAddShape( pSubset
);
383 // update original shape, it now shows less content
384 // (the subset is removed from its displayed
385 // output). Subset shape is updated within
387 if( rOrigShape
->isVisible() )
388 notifyShapeUpdate( rOrigShape
);
394 void LayerManager::revokeSubset( const AttributableShapeSharedPtr
& rOrigShape
,
395 const AttributableShapeSharedPtr
& rSubsetShape
)
397 OSL_ASSERT( !maLayers
.empty() ); // always at least background layer
399 if( rOrigShape
->revokeSubset( rSubsetShape
) )
401 OSL_ASSERT( maAllShapes
.find(rSubsetShape
) != maAllShapes
.end() );
403 implRemoveShape( rSubsetShape
);
405 // update original shape, it now shows more content
406 // (the subset is added back to its displayed output)
407 if( rOrigShape
->isVisible() )
408 notifyShapeUpdate( rOrigShape
);
412 void LayerManager::enterAnimationMode( const AnimatableShapeSharedPtr
& rShape
)
414 OSL_ASSERT( !maLayers
.empty() ); // always at least background layer
415 ENSURE_OR_THROW( rShape
, "LayerManager::enterAnimationMode(): invalid Shape" );
417 const bool bPrevAnimState( rShape
->isBackgroundDetached() );
419 rShape
->enterAnimationMode();
421 // if this call _really_ enabled the animation mode at
422 // rShape, insert it to our enter animation queue, to
423 // perform the necessary layer reorg lazily on
424 // LayerManager::update()/render().
425 if( bPrevAnimState
!= rShape
->isBackgroundDetached() )
428 mbLayerAssociationDirty
= true;
430 // area needs update (shape is removed from normal
431 // slide, and now rendered as an autonomous
432 // sprite). store in update set
433 if( rShape
->isVisible() )
434 addUpdateArea( rShape
);
437 // TODO(P1): this can lead to potential wasted effort, if
438 // a shape gets toggled animated/unanimated a few times
439 // between two frames, returning to the original state.
442 void LayerManager::leaveAnimationMode( const AnimatableShapeSharedPtr
& rShape
)
444 ENSURE_OR_THROW( !maLayers
.empty(), "LayerManager::leaveAnimationMode(): no layers" );
445 ENSURE_OR_THROW( rShape
, "LayerManager::leaveAnimationMode(): invalid Shape" );
447 const bool bPrevAnimState( rShape
->isBackgroundDetached() );
449 rShape
->leaveAnimationMode();
451 // if this call _really_ ended the animation mode at
452 // rShape, insert it to our leave animation queue, to
453 // perform the necessary layer reorg lazily on
454 // LayerManager::update()/render().
455 if( bPrevAnimState
!= rShape
->isBackgroundDetached() )
458 mbLayerAssociationDirty
= true;
460 // shape needs update, no previous rendering, fast
462 if( rShape
->isVisible() )
463 notifyShapeUpdate( rShape
);
466 // TODO(P1): this can lead to potential wasted effort, if
467 // a shape gets toggled animated/unanimated a few times
468 // between two frames, returning to the original state.
471 void LayerManager::notifyShapeUpdate( const ShapeSharedPtr
& rShape
)
473 if( !mbActive
|| mrViews
.empty() )
476 // hidden sprite-shape needs render() call still, to hide sprite
477 if( rShape
->isVisible() || rShape
->isBackgroundDetached() )
478 maUpdateShapes
.insert( rShape
);
480 addUpdateArea( rShape
);
483 bool LayerManager::isUpdatePending() const
488 if( mbLayerAssociationDirty
|| !maUpdateShapes
.empty() )
491 return std::any_of( maLayers
.begin(),
493 boost::mem_fn(&Layer::isUpdatePending
) );
496 bool LayerManager::updateSprites()
500 // send update() calls to every shape in the
501 // maUpdateShapes set, which is _animated_ (i.e. a
503 const ShapeUpdateSet::const_iterator aEnd
=maUpdateShapes
.end();
504 ShapeUpdateSet::const_iterator aCurrShape
=maUpdateShapes
.begin();
505 while( aCurrShape
!= aEnd
)
507 if( (*aCurrShape
)->isBackgroundDetached() )
509 // can update shape directly, without
510 // affecting layer content (shape is
511 // currently displayed in a sprite)
512 if( !(*aCurrShape
)->update() )
513 bRet
= false; // delay error exit
517 // TODO(P2): addUpdateArea() involves log(n)
518 // search for shape layer. Have a frequent
519 // shape/layer association cache, or ptr back to
520 // layer at the shape?
522 // cannot update shape directly, it's not
523 // animated and update() calls will prolly
524 // overwrite other page content.
525 addUpdateArea( *aCurrShape
);
531 maUpdateShapes
.clear();
536 bool LayerManager::update()
543 // going to render - better flush any pending layer reorg
545 updateShapeLayers(false);
548 bRet
= updateSprites();
550 // any non-sprite update areas left?
551 if( std::none_of( maLayers
.begin(),
553 boost::mem_fn( &Layer::isUpdatePending
) ) )
554 return bRet
; // nope, done.
556 // update each shape on each layer, that has
558 bool bIsCurrLayerUpdating(false);
559 Layer::EndUpdater aEndUpdater
;
560 LayerSharedPtr pCurrLayer
;
561 LayerShapeMap::const_iterator
aIter( maAllShapes
.begin() );
562 const LayerShapeMap::const_iterator
aEnd ( maAllShapes
.end() );
563 while( aIter
!= aEnd
)
565 LayerSharedPtr pLayer
= aIter
->second
.lock();
566 if( pLayer
!= pCurrLayer
)
569 bIsCurrLayerUpdating
= pCurrLayer
->isUpdatePending();
571 if( bIsCurrLayerUpdating
)
572 aEndUpdater
= pCurrLayer
->beginUpdate();
575 if( bIsCurrLayerUpdating
&&
576 !aIter
->first
->isBackgroundDetached() &&
577 pCurrLayer
->isInsideUpdateArea(aIter
->first
) )
579 if( !aIter
->first
->render() )
591 /** Little wrapper around a Canvas, to render one-shot
594 class DummyLayer
: public ViewLayer
597 explicit DummyLayer( const ::cppcanvas::CanvasSharedPtr
& rCanvas
) :
602 virtual bool isOnView(boost::shared_ptr
<View
> const& /*rView*/) const SAL_OVERRIDE
604 return true; // visible on all views
607 virtual ::cppcanvas::CanvasSharedPtr
getCanvas() const SAL_OVERRIDE
612 virtual void clear() const SAL_OVERRIDE
617 virtual void clearAll() const SAL_OVERRIDE
622 virtual ::cppcanvas::CustomSpriteSharedPtr
createSprite( const ::basegfx::B2DSize
& /*rSpriteSizePixel*/,
623 double /*nSpritePrio*/ ) const SAL_OVERRIDE
625 ENSURE_OR_THROW( false,
626 "DummyLayer::createSprite(): This method is not supposed to be called!" );
627 return ::cppcanvas::CustomSpriteSharedPtr();
630 virtual void setPriority( const basegfx::B1DRange
& /*rRange*/ ) SAL_OVERRIDE
632 OSL_FAIL( "BitmapView::setPriority(): This method is not supposed to be called!" );
635 virtual ::com::sun::star::geometry::IntegerSize2D
getTranslationOffset() const SAL_OVERRIDE
637 return geometry::IntegerSize2D(0,0);
640 virtual ::basegfx::B2DHomMatrix
getTransformation() const SAL_OVERRIDE
642 return mpCanvas
->getTransformation();
645 virtual ::basegfx::B2DHomMatrix
getSpriteTransformation() const SAL_OVERRIDE
647 OSL_FAIL( "BitmapView::getSpriteTransformation(): This method is not supposed to be called!" );
648 return ::basegfx::B2DHomMatrix();
651 virtual void setClip( const ::basegfx::B2DPolyPolygon
& /*rClip*/ ) SAL_OVERRIDE
653 OSL_FAIL( "BitmapView::setClip(): This method is not supposed to be called!" );
656 virtual bool resize( const ::basegfx::B2DRange
& /*rArea*/ ) SAL_OVERRIDE
658 OSL_FAIL( "BitmapView::resize(): This method is not supposed to be called!" );
663 ::cppcanvas::CanvasSharedPtr mpCanvas
;
667 bool LayerManager::renderTo( const ::cppcanvas::CanvasSharedPtr
& rTargetCanvas
) const
670 ViewLayerSharedPtr
pTmpLayer( new DummyLayer( rTargetCanvas
) );
672 LayerShapeMap::const_iterator
aIter( maAllShapes
.begin() );
673 const LayerShapeMap::const_iterator
aEnd ( maAllShapes
.end() );
674 while( aIter
!= aEnd
)
678 // forward to all shape's addViewLayer method (which
679 // we request to render the Shape on the new
680 // ViewLayer. Since we add the shapes in the
681 // maShapeSet order (which is also the render order),
682 // this is equivalent to a subsequent render() call)
683 aIter
->first
->addViewLayer( pTmpLayer
,
686 // and remove again, this is only temporary
687 aIter
->first
->removeViewLayer( pTmpLayer
);
689 catch( uno::Exception
& )
691 // TODO(E1): Might be superfluous. Nowadays,
692 // addViewLayer swallows all errors, anyway.
693 OSL_FAIL( OUStringToOString(
694 comphelper::anyToString( cppu::getCaughtException() ),
695 RTL_TEXTENCODING_UTF8
).getStr() );
697 // at least one shape could not be rendered
707 void LayerManager::addUpdateArea( ShapeSharedPtr
const& rShape
)
709 OSL_ASSERT( !maLayers
.empty() ); // always at least background layer
710 ENSURE_OR_THROW( rShape
, "LayerManager::addUpdateArea(): invalid Shape" );
712 const LayerShapeMap::const_iterator
aShapeEntry( maAllShapes
.find(rShape
) );
714 if( aShapeEntry
== maAllShapes
.end() )
717 LayerSharedPtr pLayer
= aShapeEntry
->second
.lock();
719 pLayer
->addUpdateRange( rShape
->getUpdateArea() );
722 void LayerManager::commitLayerChanges( std::size_t nCurrLayerIndex
,
723 LayerShapeMap::const_iterator aFirstLayerShape
,
724 LayerShapeMap::const_iterator aEndLayerShapes
)
726 const bool bLayerExists( maLayers
.size() > nCurrLayerIndex
);
729 const LayerSharedPtr
& rLayer( maLayers
.at(nCurrLayerIndex
) );
730 const bool bLayerResized( rLayer
->commitBounds() );
731 rLayer
->setPriority( basegfx::B1DRange(nCurrLayerIndex
,
732 nCurrLayerIndex
+1) );
736 // need to re-render whole layer - start from
738 rLayer
->clearContent();
740 // render and remove from update set
741 while( aFirstLayerShape
!= aEndLayerShapes
)
743 maUpdateShapes
.erase(aFirstLayerShape
->first
);
744 aFirstLayerShape
->first
->render();
751 LayerSharedPtr
LayerManager::createForegroundLayer() const
753 OSL_ASSERT( mbActive
);
755 LayerSharedPtr
pLayer( Layer::createLayer(
758 // create ViewLayers for all registered views, and add to
759 // newly created layer.
760 ::std::for_each( mrViews
.begin(),
762 boost::bind( &Layer::addView
,
769 void LayerManager::updateShapeLayers( bool bBackgroundLayerPainted
)
771 OSL_ASSERT( !maLayers
.empty() ); // always at least background layer
772 OSL_ASSERT( mbActive
);
774 // do we need to process shapes?
775 if( !mbLayerAssociationDirty
)
778 if( mbDisableAnimationZOrder
)
780 // layer setup happened elsewhere, is only bg layer
782 mbLayerAssociationDirty
= false;
786 // scan through maAllShapes, and determine shape animation
787 // discontinuities: when a shape that has
788 // isBackgroundDetached() return false follows a shape
789 // with isBackgroundDetached() true, the former and all
790 // following ones must be moved into an own layer.
792 // to avoid tons of temporaries, create weak_ptr to Layers
794 std::vector
< LayerWeakPtr
> aWeakLayers(maLayers
.size());
795 std::copy(maLayers
.begin(),maLayers
.end(),aWeakLayers
.begin());
797 std::size_t nCurrLayerIndex(0);
798 bool bIsBackgroundLayer(true);
799 bool bLastWasBackgroundDetached(false); // last shape sprite state
800 LayerShapeMap::iterator
aCurrShapeEntry( maAllShapes
.begin() );
801 LayerShapeMap::iterator
aCurrLayerFirstShapeEntry( maAllShapes
.begin() );
802 const LayerShapeMap::iterator
aEndShapeEntry ( maAllShapes
.end() );
803 ShapeUpdateSet aUpdatedShapes
; // shapes that need update
804 while( aCurrShapeEntry
!= aEndShapeEntry
)
806 const ShapeSharedPtr
pCurrShape( aCurrShapeEntry
->first
);
807 const bool bThisIsBackgroundDetached(
808 pCurrShape
->isBackgroundDetached() );
810 if( bLastWasBackgroundDetached
&&
811 !bThisIsBackgroundDetached
)
813 // discontinuity found - current shape needs to
814 // get into a new layer
817 // commit changes to previous layer
818 commitLayerChanges(nCurrLayerIndex
,
819 aCurrLayerFirstShapeEntry
,
821 aCurrLayerFirstShapeEntry
=aCurrShapeEntry
;
823 bIsBackgroundLayer
= false;
825 if( aWeakLayers
.size() <= nCurrLayerIndex
||
826 aWeakLayers
.at(nCurrLayerIndex
) != aCurrShapeEntry
->second
)
828 // no more layers left, or shape was not
829 // member of this layer - create a new one
830 maLayers
.insert( maLayers
.begin()+nCurrLayerIndex
,
831 createForegroundLayer() );
832 aWeakLayers
.insert( aWeakLayers
.begin()+nCurrLayerIndex
,
833 maLayers
[nCurrLayerIndex
] );
837 OSL_ASSERT( maLayers
.size() == aWeakLayers
.size() );
839 // note: using indices here, since vector::insert
840 // above invalidates iterators
841 LayerSharedPtr
& rCurrLayer( maLayers
.at(nCurrLayerIndex
) );
842 LayerWeakPtr
& rCurrWeakLayer( aWeakLayers
.at(nCurrLayerIndex
) );
843 if( rCurrWeakLayer
!= aCurrShapeEntry
->second
)
845 // mismatch: shape is not contained in current
846 // layer - move shape to that layer, then.
847 maLayers
.at(nCurrLayerIndex
)->setShapeViews(
850 // layer got new shape(s), need full repaint, if
852 if( !bThisIsBackgroundDetached
&& pCurrShape
->isVisible() )
854 LayerSharedPtr
pOldLayer( aCurrShapeEntry
->second
.lock() );
857 // old layer still valid? then we need to
858 // repaint former shape area
859 pOldLayer
->addUpdateRange(
860 pCurrShape
->getUpdateArea() );
863 // render on new layer (only if not
864 // explicitly disabled)
865 if( !(bBackgroundLayerPainted
&& bIsBackgroundLayer
) )
866 maUpdateShapes
.insert( pCurrShape
);
869 aCurrShapeEntry
->second
= rCurrWeakLayer
;
872 // update layerbounds regardless of the fact that the
873 // shape might be contained in said layer
874 // already. updateBounds() is dumb and needs to
875 // collect all shape bounds.
876 // of course, no need to expand layer bounds for
877 // shapes that reside in sprites themselves.
878 if( !bThisIsBackgroundDetached
&& !bIsBackgroundLayer
)
879 rCurrLayer
->updateBounds( pCurrShape
);
881 bLastWasBackgroundDetached
= bThisIsBackgroundDetached
;
885 // commit very last layer data
886 commitLayerChanges(nCurrLayerIndex
,
887 aCurrLayerFirstShapeEntry
,
890 // any layers left? Bin them!
891 if( maLayers
.size() > nCurrLayerIndex
+1 )
892 maLayers
.erase(maLayers
.begin()+nCurrLayerIndex
+1,
895 mbLayerAssociationDirty
= false;
900 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */