1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: layermanager.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_slideshow.hxx"
34 #include <canvas/debug.hxx>
35 #include <tools/diagnose_ex.h>
36 #include <basegfx/range/b1drange.hxx>
37 #include <basegfx/matrix/b2dhommatrix.hxx>
39 #include <comphelper/anytostring.hxx>
40 #include <cppuhelper/exc_hlp.hxx>
42 #include <boost/bind.hpp>
45 #include "layermanager.hxx"
47 using namespace ::com::sun::star
;
51 // add operator!= for weak_ptr
52 inline bool operator!=( slideshow::internal::LayerWeakPtr
const& rLHS
,
53 slideshow::internal::LayerWeakPtr
const& rRHS
)
55 return (rLHS
<rRHS
) || (rRHS
<rLHS
);
63 template<typename LayerFunc
,
64 typename ShapeFunc
> void LayerManager::manageViews(
68 LayerSharedPtr pCurrLayer
;
69 ViewLayerSharedPtr pCurrViewLayer
;
70 LayerShapeMap::const_iterator
aIter( maAllShapes
.begin() );
71 const LayerShapeMap::const_iterator
aEnd ( maAllShapes
.end() );
72 while( aIter
!= aEnd
)
74 LayerSharedPtr pLayer
= aIter
->second
.lock();
75 if( pLayer
&& pLayer
!= pCurrLayer
)
78 pCurrViewLayer
= layerFunc(pCurrLayer
);
82 shapeFunc(aIter
->first
,pCurrViewLayer
);
88 LayerManager::LayerManager( const UnoViewContainer
& rViews
,
89 const ::basegfx::B2DRange
& rPageBounds
,
90 bool bDisableAnimationZOrder
) :
96 maPageBounds( rPageBounds
),
98 mbLayerAssociationDirty(false),
100 mbDisableAnimationZOrder(bDisableAnimationZOrder
)
102 // prevent frequent resizes (won't have more than 4 layers
103 // for 99.9% of the cases)
106 // create initial background layer
108 Layer::createBackgroundLayer(
112 std::for_each( mrViews
.begin(),
114 ::boost::bind(&LayerManager::viewAdded
,
119 void LayerManager::activate( bool bSlideBackgoundPainted
)
122 maUpdateShapes
.clear(); // update gets forced via area, or
123 // has happend outside already
125 if( !bSlideBackgoundPainted
)
127 std::for_each(mrViews
.begin(),
129 boost::mem_fn(&View::clearAll
));
131 // force update of whole slide area
132 std::for_each( maLayers
.begin(),
134 boost::bind( &Layer::addUpdateRange
,
136 boost::cref(maPageBounds
) ));
140 // clear all possibly pending update areas - content
142 std::for_each( maLayers
.begin(),
144 boost::mem_fn( &Layer::clearUpdateRanges
));
147 updateShapeLayers( bSlideBackgoundPainted
);
150 void LayerManager::deactivate()
152 // TODO(F3): This is mostly a hack. Problem is, there's
153 // currently no smart way of telling shapes "remove your
154 // sprites". Others, like MediaShapes, listen to
155 // start/stop animation events, which is too much overhead
156 // for all shapes, though.
158 const bool bMoreThanOneLayer(maLayers
.size() > 1);
159 if( mnActiveSprites
|| bMoreThanOneLayer
)
161 // clear all viewlayers, dump everything but the
162 // background layer - this will also remove all shape
164 std::for_each(maAllShapes
.begin(),
166 boost::bind( &Shape::clearAllViewLayers
,
167 boost::bind( std::select1st
<LayerShapeMap::value_type
>(),
170 for (LayerShapeMap::iterator
171 iShape (maAllShapes
.begin()),
172 iEnd (maAllShapes
.end());
176 iShape
->second
.reset();
179 if( bMoreThanOneLayer
)
180 maLayers
.erase(maLayers
.begin()+1,
183 mbLayerAssociationDirty
= true;
188 // only background layer left
189 OSL_ASSERT( maLayers
.size() == 1 && maLayers
.front()->isBackgroundLayer() );
192 void LayerManager::viewAdded( const UnoViewSharedPtr
& rView
)
194 // view must be member of mrViews container
195 OSL_ASSERT( std::find(mrViews
.begin(),
197 rView
) != mrViews
.end() );
203 // add View to all registered shapes
205 boost::bind(&Layer::addView
,
208 // repaint on view add
209 boost::bind(&Shape::addViewLayer
,
214 // in case we haven't reached all layers from the
215 // maAllShapes, issue addView again for good measure
216 std::for_each( maLayers
.begin(),
218 boost::bind( &Layer::addView
,
220 boost::cref(rView
) ));
223 void LayerManager::viewRemoved( const UnoViewSharedPtr
& rView
)
225 // view must not be member of mrViews container anymore
226 OSL_ASSERT( std::find(mrViews
.begin(),
228 rView
) == mrViews
.end() );
230 // remove View from all registered shapes
232 boost::bind(&Layer::removeView
,
235 boost::bind(&Shape::removeViewLayer
,
239 // in case we haven't reached all layers from the
240 // maAllShapes, issue removeView again for good measure
241 std::for_each( maLayers
.begin(),
243 boost::bind( &Layer::removeView
,
245 boost::cref(rView
) ));
248 void LayerManager::viewChanged( const UnoViewSharedPtr
& rView
)
252 // view must be member of mrViews container
253 OSL_ASSERT( std::find(mrViews
.begin(),
255 rView
) != mrViews
.end() );
257 // TODO(P2): selectively update only changed view
261 void LayerManager::viewsChanged()
267 ::std::for_each( mrViews
.begin(),
269 ::boost::mem_fn(&View::clearAll
) );
271 // TODO(F3): resize and repaint all layers
274 std::for_each( maAllShapes
.begin(),
276 boost::bind(&Shape::render
,
277 boost::bind( ::std::select1st
<LayerShapeMap::value_type
>(), _1
)) );
280 void LayerManager::addShape( const ShapeSharedPtr
& rShape
)
282 OSL_ASSERT( !maLayers
.empty() ); // always at least background layer
283 ENSURE_OR_THROW( rShape
, "LayerManager::addShape(): invalid Shape" );
285 // add shape to XShape hash map
286 if( !maXShapeHash
.insert(
287 XShapeHash::value_type( rShape
->getXShape(),
290 // entry already present, nothing to do
294 // add shape to appropriate layer
295 implAddShape( rShape
);
298 void LayerManager::putShape2BackgroundLayer( LayerShapeMap::value_type
& rShapeEntry
)
300 LayerSharedPtr
& rBgLayer( maLayers
.front() );
301 rBgLayer
->setShapeViews(rShapeEntry
.first
);
302 rShapeEntry
.second
= rBgLayer
;
305 void LayerManager::implAddShape( const ShapeSharedPtr
& rShape
)
307 OSL_ASSERT( !maLayers
.empty() ); // always at least background layer
308 ENSURE_OR_THROW( rShape
, "LayerManager::implAddShape(): invalid Shape" );
310 LayerShapeMap::value_type
aValue (rShape
, LayerWeakPtr());
312 OSL_ASSERT( maAllShapes
.find(rShape
) == maAllShapes
.end() ); // shape must not be added already
313 mbLayerAssociationDirty
= true;
315 if( mbDisableAnimationZOrder
)
316 putShape2BackgroundLayer(
317 *maAllShapes
.insert(aValue
).first
);
319 maAllShapes
.insert(aValue
);
321 // update shape, it's just added and not yet painted
322 if( rShape
->isVisible() )
323 notifyShapeUpdate( rShape
);
326 bool LayerManager::removeShape( const ShapeSharedPtr
& rShape
)
328 // remove shape from XShape hash map
329 if( maXShapeHash
.erase( rShape
->getXShape() ) == 0 )
330 return false; // shape not in map
332 OSL_ASSERT( maAllShapes
.find(rShape
) != maAllShapes
.end() );
334 implRemoveShape( rShape
);
339 void LayerManager::implRemoveShape( const ShapeSharedPtr
& rShape
)
341 OSL_ASSERT( !maLayers
.empty() ); // always at least background layer
342 ENSURE_OR_THROW( rShape
, "LayerManager::implRemoveShape(): invalid Shape" );
344 const LayerShapeMap::iterator
aShapeEntry( maAllShapes
.find(rShape
) );
346 if( aShapeEntry
== maAllShapes
.end() )
349 const bool bShapeUpdateNotified
= maUpdateShapes
.erase( rShape
) != 0;
351 // Enter shape area to the update area, but only if shape
352 // is visible and not in sprite mode (otherwise, updating
353 // the area doesn't do actual harm, but costs time)
354 // Actually, also add it if it was listed in
355 // maUpdateShapes (might have just gone invisible).
356 if( bShapeUpdateNotified
||
357 (rShape
->isVisible() &&
358 !rShape
->isBackgroundDetached()) )
360 LayerSharedPtr pLayer
= aShapeEntry
->second
.lock();
363 // store area early, once the shape is removed from
364 // the layers, it no longer has any view references
365 pLayer
->addUpdateRange( rShape
->getUpdateArea() );
369 rShape
->clearAllViewLayers();
370 maAllShapes
.erase( aShapeEntry
);
372 mbLayerAssociationDirty
= true;
375 ShapeSharedPtr
LayerManager::lookupShape( const uno::Reference
< drawing::XShape
>& xShape
) const
377 ENSURE_OR_THROW( xShape
.is(), "LayerManager::lookupShape(): invalid Shape" );
379 const XShapeHash::const_iterator
aIter( maXShapeHash
.find( xShape
));
380 if( aIter
== maXShapeHash
.end() )
381 return ShapeSharedPtr(); // not found
383 // found, return data part of entry pair.
384 return aIter
->second
;
387 AttributableShapeSharedPtr
LayerManager::getSubsetShape( const AttributableShapeSharedPtr
& rOrigShape
,
388 const DocTreeNode
& rTreeNode
)
390 OSL_ASSERT( !maLayers
.empty() ); // always at least background layer
392 AttributableShapeSharedPtr pSubset
;
394 // shape already added?
395 if( rOrigShape
->createSubset( pSubset
,
398 OSL_ENSURE( pSubset
, "LayerManager::getSubsetShape(): failed to create subset" );
400 // don't add to shape hash, we're dupes to the
401 // original XShape anyway - all subset shapes return
402 // the same XShape as the original one.
404 // add shape to corresponding layer
405 implAddShape( pSubset
);
407 // update original shape, it now shows less content
408 // (the subset is removed from its displayed
409 // output). Subset shape is updated within
411 if( rOrigShape
->isVisible() )
412 notifyShapeUpdate( rOrigShape
);
418 void LayerManager::revokeSubset( const AttributableShapeSharedPtr
& rOrigShape
,
419 const AttributableShapeSharedPtr
& rSubsetShape
)
421 OSL_ASSERT( !maLayers
.empty() ); // always at least background layer
423 if( rOrigShape
->revokeSubset( rSubsetShape
) )
425 OSL_ASSERT( maAllShapes
.find(rSubsetShape
) != maAllShapes
.end() );
427 implRemoveShape( rSubsetShape
);
429 // update original shape, it now shows more content
430 // (the subset is added back to its displayed output)
431 if( rOrigShape
->isVisible() )
432 notifyShapeUpdate( rOrigShape
);
436 void LayerManager::enterAnimationMode( const AnimatableShapeSharedPtr
& rShape
)
438 OSL_ASSERT( !maLayers
.empty() ); // always at least background layer
439 ENSURE_OR_THROW( rShape
, "LayerManager::enterAnimationMode(): invalid Shape" );
441 const bool bPrevAnimState( rShape
->isBackgroundDetached() );
443 rShape
->enterAnimationMode();
445 // if this call _really_ enabled the animation mode at
446 // rShape, insert it to our enter animation queue, to
447 // perform the necessary layer reorg lazily on
448 // LayerManager::update()/render().
449 if( bPrevAnimState
!= rShape
->isBackgroundDetached() )
452 mbLayerAssociationDirty
= true;
454 // area needs update (shape is removed from normal
455 // slide, and now rendered as an autonomous
456 // sprite). store in update set
457 if( rShape
->isVisible() )
458 addUpdateArea( rShape
);
461 // TODO(P1): this can lead to potential wasted effort, if
462 // a shape gets toggled animated/unanimated a few times
463 // between two frames, returning to the original state.
466 void LayerManager::leaveAnimationMode( const AnimatableShapeSharedPtr
& rShape
)
468 ENSURE_OR_THROW( !maLayers
.empty(), "LayerManager::leaveAnimationMode(): no layers" );
469 ENSURE_OR_THROW( rShape
, "LayerManager::leaveAnimationMode(): invalid Shape" );
471 const bool bPrevAnimState( rShape
->isBackgroundDetached() );
473 rShape
->leaveAnimationMode();
475 // if this call _really_ ended the animation mode at
476 // rShape, insert it to our leave animation queue, to
477 // perform the necessary layer reorg lazily on
478 // LayerManager::update()/render().
479 if( bPrevAnimState
!= rShape
->isBackgroundDetached() )
482 mbLayerAssociationDirty
= true;
484 // shape needs update, no previous rendering, fast
486 if( rShape
->isVisible() )
487 notifyShapeUpdate( rShape
);
490 // TODO(P1): this can lead to potential wasted effort, if
491 // a shape gets toggled animated/unanimated a few times
492 // between two frames, returning to the original state.
495 void LayerManager::notifyShapeUpdate( const ShapeSharedPtr
& rShape
)
497 if( !mbActive
|| mrViews
.empty() )
500 // hidden sprite-shape needs render() call still, to hide sprite
501 if( rShape
->isVisible() || rShape
->isBackgroundDetached() )
502 maUpdateShapes
.insert( rShape
);
504 addUpdateArea( rShape
);
507 bool LayerManager::isUpdatePending() const
512 if( mbLayerAssociationDirty
|| !maUpdateShapes
.empty() )
515 const LayerVector::const_iterator
aEnd( maLayers
.end() );
516 if( std::find_if( maLayers
.begin(),
518 boost::mem_fn(&Layer::isUpdatePending
)) != aEnd
)
524 bool LayerManager::updateSprites()
528 // send update() calls to every shape in the
529 // maUpdateShapes set, which is _animated_ (i.e. a
531 const ShapeUpdateSet::const_iterator aEnd
=maUpdateShapes
.end();
532 ShapeUpdateSet::const_iterator aCurrShape
=maUpdateShapes
.begin();
533 while( aCurrShape
!= aEnd
)
535 if( (*aCurrShape
)->isBackgroundDetached() )
537 // can update shape directly, without
538 // affecting layer content (shape is
539 // currently displayed in a sprite)
540 if( !(*aCurrShape
)->update() )
541 bRet
= false; // delay error exit
545 // TODO(P2): addUpdateArea() involves log(n)
546 // search for shape layer. Have a frequent
547 // shape/layer association cache, or ptr back to
548 // layer at the shape?
550 // cannot update shape directly, it's not
551 // animated and update() calls will prolly
552 // overwrite other page content.
553 addUpdateArea( *aCurrShape
);
559 maUpdateShapes
.clear();
564 bool LayerManager::update()
571 // going to render - better flush any pending layer reorg
573 updateShapeLayers(false);
576 bRet
= updateSprites();
578 // any non-sprite update areas left?
579 if( std::find_if( maLayers
.begin(),
581 boost::mem_fn( &Layer::isUpdatePending
)) == maLayers
.end() )
582 return bRet
; // nope, done.
584 // update each shape on each layer, that has
586 bool bIsCurrLayerUpdating(false);
587 Layer::EndUpdater aEndUpdater
;
588 LayerSharedPtr pCurrLayer
;
589 LayerShapeMap::const_iterator
aIter( maAllShapes
.begin() );
590 const LayerShapeMap::const_iterator
aEnd ( maAllShapes
.end() );
591 while( aIter
!= aEnd
)
593 LayerSharedPtr pLayer
= aIter
->second
.lock();
594 if( pLayer
!= pCurrLayer
)
597 bIsCurrLayerUpdating
= pCurrLayer
->isUpdatePending();
599 if( bIsCurrLayerUpdating
)
600 aEndUpdater
= pCurrLayer
->beginUpdate();
603 if( bIsCurrLayerUpdating
&&
604 !aIter
->first
->isBackgroundDetached() &&
605 pCurrLayer
->isInsideUpdateArea(aIter
->first
) )
607 if( !aIter
->first
->render() )
619 /** Little wrapper around a Canvas, to render one-shot
622 class DummyLayer
: public ViewLayer
625 explicit DummyLayer( const ::cppcanvas::CanvasSharedPtr
& rCanvas
) :
630 virtual bool isOnView(boost::shared_ptr
<View
> const& /*rView*/) const
632 return true; // visible on all views
635 virtual ::cppcanvas::CanvasSharedPtr
getCanvas() const
640 virtual void clear() const
645 virtual void clearAll() const
650 virtual ::cppcanvas::CustomSpriteSharedPtr
createSprite( const ::basegfx::B2DSize
& /*rSpriteSizePixel*/,
651 double /*nSpritePrio*/ ) const
653 ENSURE_OR_THROW( false,
654 "DummyLayer::createSprite(): This method is not supposed to be called!" );
655 return ::cppcanvas::CustomSpriteSharedPtr();
658 virtual void setPriority( const basegfx::B1DRange
& /*rRange*/ )
661 "BitmapView::setPriority(): This method is not supposed to be called!" );
664 virtual ::basegfx::B2DHomMatrix
getTransformation() const
666 return mpCanvas
->getTransformation();
669 virtual ::basegfx::B2DHomMatrix
getSpriteTransformation() const
672 "BitmapView::getSpriteTransformation(): This method is not supposed to be called!" );
673 return ::basegfx::B2DHomMatrix();
676 virtual void setClip( const ::basegfx::B2DPolyPolygon
& /*rClip*/ )
679 "BitmapView::setClip(): This method is not supposed to be called!" );
682 virtual bool resize( const ::basegfx::B2DRange
& /*rArea*/ )
685 "BitmapView::resize(): This method is not supposed to be called!" );
690 ::cppcanvas::CanvasSharedPtr mpCanvas
;
694 bool LayerManager::renderTo( const ::cppcanvas::CanvasSharedPtr
& rTargetCanvas
) const
697 ViewLayerSharedPtr
pTmpLayer( new DummyLayer( rTargetCanvas
) );
699 LayerShapeMap::const_iterator
aIter( maAllShapes
.begin() );
700 const LayerShapeMap::const_iterator
aEnd ( maAllShapes
.end() );
701 while( aIter
!= aEnd
)
705 // forward to all shape's addViewLayer method (which
706 // we request to render the Shape on the new
707 // ViewLayer. Since we add the shapes in the
708 // maShapeSet order (which is also the render order),
709 // this is equivalent to a subsequent render() call)
710 aIter
->first
->addViewLayer( pTmpLayer
,
713 // and remove again, this is only temporary
714 aIter
->first
->removeViewLayer( pTmpLayer
);
716 catch( uno::Exception
& )
718 // TODO(E1): Might be superfluous. Nowadays,
719 // addViewLayer swallows all errors, anyway.
721 rtl::OUStringToOString(
722 comphelper::anyToString( cppu::getCaughtException() ),
723 RTL_TEXTENCODING_UTF8
).getStr() );
725 // at least one shape could not be rendered
735 void LayerManager::addUpdateArea( ShapeSharedPtr
const& rShape
)
737 OSL_ASSERT( !maLayers
.empty() ); // always at least background layer
738 ENSURE_OR_THROW( rShape
, "LayerManager::addUpdateArea(): invalid Shape" );
740 const LayerShapeMap::const_iterator
aShapeEntry( maAllShapes
.find(rShape
) );
742 if( aShapeEntry
== maAllShapes
.end() )
745 LayerSharedPtr pLayer
= aShapeEntry
->second
.lock();
747 pLayer
->addUpdateRange( rShape
->getUpdateArea() );
750 void LayerManager::commitLayerChanges( std::size_t nCurrLayerIndex
,
751 LayerShapeMap::const_iterator aFirstLayerShape
,
752 LayerShapeMap::const_iterator aEndLayerShapes
)
754 const bool bLayerExists( maLayers
.size() > nCurrLayerIndex
);
757 const LayerSharedPtr
& rLayer( maLayers
.at(nCurrLayerIndex
) );
758 const bool bLayerResized( rLayer
->commitBounds() );
759 rLayer
->setPriority( basegfx::B1DRange(nCurrLayerIndex
,
760 nCurrLayerIndex
+1) );
764 // need to re-render whole layer - start from
766 rLayer
->clearContent();
768 // render and remove from update set
769 while( aFirstLayerShape
!= aEndLayerShapes
)
771 maUpdateShapes
.erase(aFirstLayerShape
->first
);
772 aFirstLayerShape
->first
->render();
779 LayerSharedPtr
LayerManager::createForegroundLayer() const
781 OSL_ASSERT( mbActive
);
783 LayerSharedPtr
pLayer( Layer::createLayer(
786 // create ViewLayers for all registered views, and add to
787 // newly created layer.
788 ::std::for_each( mrViews
.begin(),
790 boost::bind( &Layer::addView
,
797 void LayerManager::updateShapeLayers( bool bBackgroundLayerPainted
)
799 OSL_ASSERT( !maLayers
.empty() ); // always at least background layer
800 OSL_ASSERT( mbActive
);
802 // do we need to process shapes?
803 if( !mbLayerAssociationDirty
)
806 if( mbDisableAnimationZOrder
)
808 // layer setup happened elsewhere, is only bg layer
810 mbLayerAssociationDirty
= false;
814 // scan through maAllShapes, and determine shape animation
815 // discontinuities: when a shape that has
816 // isBackgroundDetached() return false follows a shape
817 // with isBackgroundDetached() true, the former and all
818 // following ones must be moved into an own layer.
820 // to avoid tons of temporaries, create weak_ptr to Layers
822 std::vector
< LayerWeakPtr
> aWeakLayers(maLayers
.size());
823 std::copy(maLayers
.begin(),maLayers
.end(),aWeakLayers
.begin());
825 std::size_t nCurrLayerIndex(0);
826 bool bIsBackgroundLayer(true);
827 bool bLastWasBackgroundDetached(false); // last shape sprite state
828 LayerShapeMap::iterator
aCurrShapeEntry( maAllShapes
.begin() );
829 LayerShapeMap::iterator
aCurrLayerFirstShapeEntry( maAllShapes
.begin() );
830 const LayerShapeMap::iterator
aEndShapeEntry ( maAllShapes
.end() );
831 ShapeUpdateSet aUpdatedShapes
; // shapes that need update
832 while( aCurrShapeEntry
!= aEndShapeEntry
)
834 const ShapeSharedPtr
pCurrShape( aCurrShapeEntry
->first
);
835 const bool bThisIsBackgroundDetached(
836 pCurrShape
->isBackgroundDetached() );
838 if( bLastWasBackgroundDetached
== true &&
839 bThisIsBackgroundDetached
== false )
841 // discontinuity found - current shape needs to
842 // get into a new layer
843 // --------------------------------------------
845 // commit changes to previous layer
846 commitLayerChanges(nCurrLayerIndex
,
847 aCurrLayerFirstShapeEntry
,
849 aCurrLayerFirstShapeEntry
=aCurrShapeEntry
;
851 bIsBackgroundLayer
= false;
853 if( aWeakLayers
.size() <= nCurrLayerIndex
||
854 aWeakLayers
.at(nCurrLayerIndex
) != aCurrShapeEntry
->second
)
856 // no more layers left, or shape was not
857 // member of this layer - create a new one
858 maLayers
.insert( maLayers
.begin()+nCurrLayerIndex
,
859 createForegroundLayer() );
860 aWeakLayers
.insert( aWeakLayers
.begin()+nCurrLayerIndex
,
861 maLayers
[nCurrLayerIndex
] );
865 OSL_ASSERT( maLayers
.size() == aWeakLayers
.size() );
867 // note: using indices here, since vector::insert
868 // above invalidates iterators
869 LayerSharedPtr
& rCurrLayer( maLayers
.at(nCurrLayerIndex
) );
870 LayerWeakPtr
& rCurrWeakLayer( aWeakLayers
.at(nCurrLayerIndex
) );
871 if( rCurrWeakLayer
!= aCurrShapeEntry
->second
)
873 // mismatch: shape is not contained in current
874 // layer - move shape to that layer, then.
875 maLayers
.at(nCurrLayerIndex
)->setShapeViews(
878 // layer got new shape(s), need full repaint, if
880 if( !bThisIsBackgroundDetached
&& pCurrShape
->isVisible() )
882 LayerSharedPtr
pOldLayer( aCurrShapeEntry
->second
.lock() );
885 // old layer still valid? then we need to
886 // repaint former shape area
887 pOldLayer
->addUpdateRange(
888 pCurrShape
->getUpdateArea() );
891 // render on new layer (only if not
892 // explicitely disabled)
893 if( !(bBackgroundLayerPainted
&& bIsBackgroundLayer
) )
894 maUpdateShapes
.insert( pCurrShape
);
897 aCurrShapeEntry
->second
= rCurrWeakLayer
;
900 // update layerbounds regardless of the fact that the
901 // shape might be contained in said layer
902 // already. updateBounds() is dumb and needs to
903 // collect all shape bounds.
904 // of course, no need to expand layer bounds for
905 // shapes that reside in sprites themselves.
906 if( !bThisIsBackgroundDetached
&& !bIsBackgroundLayer
)
907 rCurrLayer
->updateBounds( pCurrShape
);
909 bLastWasBackgroundDetached
= bThisIsBackgroundDetached
;
913 // commit very last layer data
914 commitLayerChanges(nCurrLayerIndex
,
915 aCurrLayerFirstShapeEntry
,
918 // any layers left? Bin them!
919 if( maLayers
.size() > nCurrLayerIndex
+1 )
920 maLayers
.erase(maLayers
.begin()+nCurrLayerIndex
+1,
923 mbLayerAssociationDirty
= false;