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 <comphelper/diagnose_ex.hxx>
22 #include <basegfx/range/b1drange.hxx>
23 #include <basegfx/matrix/b2dhommatrix.hxx>
24 #include <cppcanvas/canvas.hxx>
30 #include "layermanager.hxx"
32 using namespace ::com::sun::star
;
36 // add operator!= for weak_ptr
37 bool notEqual( slideshow::internal::LayerWeakPtr
const& rLHS
,
38 slideshow::internal::LayerWeakPtr
const& rRHS
)
40 return rLHS
.lock().get() != rRHS
.lock().get();
44 namespace slideshow::internal
46 template<typename LayerFunc
,
47 typename ShapeFunc
> void LayerManager::manageViews(
51 LayerSharedPtr pCurrLayer
;
52 ViewLayerSharedPtr pCurrViewLayer
;
53 for( const auto& rShape
: maAllShapes
)
55 LayerSharedPtr pLayer
= rShape
.second
.lock();
56 if( pLayer
&& pLayer
!= pCurrLayer
)
59 pCurrViewLayer
= layerFunc(pCurrLayer
);
63 shapeFunc(rShape
.first
,pCurrViewLayer
);
67 LayerManager::LayerManager( const UnoViewContainer
& rViews
,
68 bool bDisableAnimationZOrder
) :
75 mbLayerAssociationDirty(false),
77 mbDisableAnimationZOrder(bDisableAnimationZOrder
)
79 // prevent frequent resizes (won't have more than 4 layers
80 // for 99.9% of the cases)
83 // create initial background layer
84 maLayers
.push_back( Layer::createBackgroundLayer() );
87 for( const auto& rView
: mrViews
)
91 void LayerManager::activate()
94 maUpdateShapes
.clear(); // update gets forced via area, or
95 // has happened outside already
97 // clear all possibly pending update areas - content
99 for( const auto& pLayer
: maLayers
)
100 pLayer
->clearUpdateRanges();
102 updateShapeLayers( true/*bSlideBackgroundPainted*/ );
105 void LayerManager::deactivate()
107 // TODO(F3): This is mostly a hack. Problem is, there's
108 // currently no smart way of telling shapes "remove your
109 // sprites". Others, like MediaShapes, listen to
110 // start/stop animation events, which is too much overhead
111 // for all shapes, though.
113 const bool bMoreThanOneLayer(maLayers
.size() > 1);
114 if (mnActiveSprites
|| bMoreThanOneLayer
)
116 // clear all viewlayers, dump everything but the
117 // background layer - this will also remove all shape
119 for (auto& rShape
: maAllShapes
)
120 rShape
.first
->clearAllViewLayers();
122 for (auto& rShape
: maAllShapes
)
123 rShape
.second
.reset();
125 if (bMoreThanOneLayer
)
126 maLayers
.erase(maLayers
.begin() + 1, maLayers
.end());
128 mbLayerAssociationDirty
= true;
133 // only background layer left
134 OSL_ASSERT( maLayers
.size() == 1 && maLayers
.front()->isBackgroundLayer() );
137 void LayerManager::viewAdded( const UnoViewSharedPtr
& rView
)
139 // view must be member of mrViews container
140 OSL_ASSERT( std::find(mrViews
.begin(),
142 rView
) != mrViews
.end() );
148 // add View to all registered shapes
150 [&rView
]( const LayerSharedPtr
& pLayer
)
151 { return pLayer
->addView( rView
); },
152 []( const ShapeSharedPtr
& pShape
, const ViewLayerSharedPtr
& pLayer
)
153 { return pShape
->addViewLayer( pLayer
, true ); } );
155 // in case we haven't reached all layers from the
156 // maAllShapes, issue addView again for good measure
157 for( const auto& pLayer
: maLayers
)
158 pLayer
->addView( rView
);
161 void LayerManager::viewRemoved( const UnoViewSharedPtr
& rView
)
163 // view must not be member of mrViews container anymore
164 OSL_ASSERT( std::find(mrViews
.begin(),
166 rView
) == mrViews
.end() );
168 // remove View from all registered shapes
170 [&rView
]( const LayerSharedPtr
& pLayer
)
171 { return pLayer
->removeView( rView
); },
172 []( const ShapeSharedPtr
& pShape
, const ViewLayerSharedPtr
& pLayer
)
173 { return pShape
->removeViewLayer( pLayer
); } );
175 // in case we haven't reached all layers from the
176 // maAllShapes, issue removeView again for good measure
177 for( const auto& pLayer
: maLayers
)
178 pLayer
->removeView( rView
);
181 void LayerManager::viewChanged( const UnoViewSharedPtr
& rView
)
183 // view must be member of mrViews container
184 OSL_ASSERT( std::find(mrViews
.begin(),
186 rView
) != mrViews
.end() );
188 // TODO(P2): selectively update only changed view
192 void LayerManager::viewsChanged()
198 for( const auto& pView
: mrViews
)
201 // TODO(F3): resize and repaint all layers
204 for( const auto& rShape
: maAllShapes
)
205 rShape
.first
->render();
208 void LayerManager::addShape( const ShapeSharedPtr
& rShape
)
210 OSL_ASSERT( !maLayers
.empty() ); // always at least background layer
211 ENSURE_OR_THROW( rShape
, "LayerManager::addShape(): invalid Shape" );
213 // add shape to XShape hash map
214 if( !maXShapeHash
.emplace(rShape
->getXShape(),
217 // entry already present, nothing to do
221 // add shape to appropriate layer
222 implAddShape( rShape
);
225 void LayerManager::putShape2BackgroundLayer( LayerShapeMap::value_type
& rShapeEntry
)
227 LayerSharedPtr
& rBgLayer( maLayers
.front() );
228 rBgLayer
->setShapeViews(rShapeEntry
.first
);
229 rShapeEntry
.second
= rBgLayer
;
232 void LayerManager::implAddShape( const ShapeSharedPtr
& rShape
)
234 OSL_ASSERT( !maLayers
.empty() ); // always at least background layer
235 ENSURE_OR_THROW( rShape
, "LayerManager::implAddShape(): invalid Shape" );
237 LayerShapeMap::value_type
aValue (rShape
, LayerWeakPtr());
239 OSL_ASSERT( maAllShapes
.find(rShape
) == maAllShapes
.end() ); // shape must not be added already
240 mbLayerAssociationDirty
= true;
242 if( mbDisableAnimationZOrder
)
243 putShape2BackgroundLayer(
244 *maAllShapes
.insert(aValue
).first
);
246 maAllShapes
.insert(aValue
);
248 // update shape, it's just added and not yet painted
249 if( rShape
->isVisible() )
250 notifyShapeUpdate( rShape
);
253 bool LayerManager::removeShape( const ShapeSharedPtr
& rShape
)
255 // remove shape from XShape hash map
256 if( maXShapeHash
.erase( rShape
->getXShape() ) == 0 )
257 return false; // shape not in map
259 OSL_ASSERT( maAllShapes
.find(rShape
) != maAllShapes
.end() );
261 implRemoveShape( rShape
);
266 void LayerManager::implRemoveShape( const ShapeSharedPtr
& rShape
)
268 OSL_ASSERT( !maLayers
.empty() ); // always at least background layer
269 ENSURE_OR_THROW( rShape
, "LayerManager::implRemoveShape(): invalid Shape" );
271 const LayerShapeMap::iterator
aShapeEntry( maAllShapes
.find(rShape
) );
273 if( aShapeEntry
== maAllShapes
.end() )
276 const bool bShapeUpdateNotified
= maUpdateShapes
.erase( rShape
) != 0;
278 // Enter shape area to the update area, but only if shape
279 // is visible and not in sprite mode (otherwise, updating
280 // the area doesn't do actual harm, but costs time)
281 // Actually, also add it if it was listed in
282 // maUpdateShapes (might have just gone invisible).
283 if( bShapeUpdateNotified
||
284 (rShape
->isVisible() &&
285 !rShape
->isBackgroundDetached()) )
287 LayerSharedPtr pLayer
= aShapeEntry
->second
.lock();
290 // store area early, once the shape is removed from
291 // the layers, it no longer has any view references
292 pLayer
->addUpdateRange( rShape
->getUpdateArea() );
296 rShape
->clearAllViewLayers();
297 maAllShapes
.erase( aShapeEntry
);
299 mbLayerAssociationDirty
= true;
302 ShapeSharedPtr
LayerManager::lookupShape( const uno::Reference
< drawing::XShape
>& xShape
) const
304 ENSURE_OR_THROW( xShape
.is(), "LayerManager::lookupShape(): invalid Shape" );
306 const XShapeToShapeMap::const_iterator
aIter( maXShapeHash
.find( xShape
));
307 if( aIter
== maXShapeHash
.end() )
308 return ShapeSharedPtr(); // not found
310 // found, return data part of entry pair.
311 return aIter
->second
;
314 AttributableShapeSharedPtr
LayerManager::getSubsetShape( const AttributableShapeSharedPtr
& rOrigShape
,
315 const DocTreeNode
& rTreeNode
)
317 OSL_ASSERT( !maLayers
.empty() ); // always at least background layer
319 AttributableShapeSharedPtr pSubset
;
321 // shape already added?
322 if( rOrigShape
->createSubset( pSubset
,
325 OSL_ENSURE( pSubset
, "LayerManager::getSubsetShape(): failed to create subset" );
327 // don't add to shape hash, we're dupes to the
328 // original XShape anyway - all subset shapes return
329 // the same XShape as the original one.
331 // add shape to corresponding layer
332 implAddShape( pSubset
);
334 // update original shape, it now shows less content
335 // (the subset is removed from its displayed
336 // output). Subset shape is updated within
338 if( rOrigShape
->isVisible() )
339 notifyShapeUpdate( rOrigShape
);
345 const XShapeToShapeMap
& LayerManager::getXShapeToShapeMap() const
350 void LayerManager::revokeSubset( const AttributableShapeSharedPtr
& rOrigShape
,
351 const AttributableShapeSharedPtr
& rSubsetShape
)
353 OSL_ASSERT( !maLayers
.empty() ); // always at least background layer
355 if( rOrigShape
->revokeSubset( rSubsetShape
) )
357 OSL_ASSERT( maAllShapes
.find(rSubsetShape
) != maAllShapes
.end() );
359 implRemoveShape( rSubsetShape
);
361 // update original shape, it now shows more content
362 // (the subset is added back to its displayed output)
363 if( rOrigShape
->isVisible() )
364 notifyShapeUpdate( rOrigShape
);
368 void LayerManager::enterAnimationMode( const AnimatableShapeSharedPtr
& rShape
)
370 OSL_ASSERT( !maLayers
.empty() ); // always at least background layer
371 ENSURE_OR_THROW( rShape
, "LayerManager::enterAnimationMode(): invalid Shape" );
373 const bool bPrevAnimState( rShape
->isBackgroundDetached() );
375 rShape
->enterAnimationMode();
377 // if this call _really_ enabled the animation mode at
378 // rShape, insert it to our enter animation queue, to
379 // perform the necessary layer reorg lazily on
380 // LayerManager::update()/render().
381 if( bPrevAnimState
!= rShape
->isBackgroundDetached() )
384 mbLayerAssociationDirty
= true;
386 // area needs update (shape is removed from normal
387 // slide, and now rendered as an autonomous
388 // sprite). store in update set
389 if( rShape
->isVisible() )
390 addUpdateArea( rShape
);
393 // TODO(P1): this can lead to potential wasted effort, if
394 // a shape gets toggled animated/unanimated a few times
395 // between two frames, returning to the original state.
398 void LayerManager::leaveAnimationMode( const AnimatableShapeSharedPtr
& rShape
)
400 ENSURE_OR_THROW( !maLayers
.empty(), "LayerManager::leaveAnimationMode(): no layers" );
401 ENSURE_OR_THROW( rShape
, "LayerManager::leaveAnimationMode(): invalid Shape" );
403 const bool bPrevAnimState( rShape
->isBackgroundDetached() );
405 rShape
->leaveAnimationMode();
407 // if this call _really_ ended the animation mode at
408 // rShape, insert it to our leave animation queue, to
409 // perform the necessary layer reorg lazily on
410 // LayerManager::update()/render().
411 if( bPrevAnimState
!= rShape
->isBackgroundDetached() )
414 mbLayerAssociationDirty
= true;
416 // shape needs update, no previous rendering, fast
418 if( rShape
->isVisible() )
419 notifyShapeUpdate( rShape
);
422 // TODO(P1): this can lead to potential wasted effort, if
423 // a shape gets toggled animated/unanimated a few times
424 // between two frames, returning to the original state.
427 void LayerManager::notifyShapeUpdate( const ShapeSharedPtr
& rShape
)
429 if( !mbActive
|| mrViews
.empty() )
432 // hidden sprite-shape needs render() call still, to hide sprite
433 if( rShape
->isVisible() || rShape
->isBackgroundDetached() )
434 maUpdateShapes
.insert( rShape
);
436 addUpdateArea( rShape
);
439 bool LayerManager::isUpdatePending() const
444 if( mbLayerAssociationDirty
|| !maUpdateShapes
.empty() )
447 return std::any_of( maLayers
.begin(),
449 std::mem_fn(&Layer::isUpdatePending
) );
452 bool LayerManager::updateSprites()
456 // send update() calls to every shape in the
457 // maUpdateShapes set, which is _animated_ (i.e. a
459 for( const auto& pShape
: maUpdateShapes
)
461 if( pShape
->isBackgroundDetached() )
463 // can update shape directly, without
464 // affecting layer content (shape is
465 // currently displayed in a sprite)
466 if( !pShape
->update() )
467 bRet
= false; // delay error exit
471 // TODO(P2): addUpdateArea() involves log(n)
472 // search for shape layer. Have a frequent
473 // shape/layer association cache, or ptr back to
474 // layer at the shape?
476 // cannot update shape directly, it's not
477 // animated and update() calls will prolly
478 // overwrite other page content.
479 addUpdateArea( pShape
);
483 maUpdateShapes
.clear();
488 bool LayerManager::update()
495 // going to render - better flush any pending layer reorg
497 updateShapeLayers(false);
500 bRet
= updateSprites();
502 // any non-sprite update areas left?
503 if( std::none_of( maLayers
.begin(),
505 std::mem_fn( &Layer::isUpdatePending
) ) )
506 return bRet
; // nope, done.
508 // update each shape on each layer, that has
510 bool bIsCurrLayerUpdating(false);
511 Layer::EndUpdater aEndUpdater
;
512 LayerSharedPtr pCurrLayer
;
513 for( const auto& rShape
: maAllShapes
)
515 LayerSharedPtr pLayer
= rShape
.second
.lock();
516 if( pLayer
!= pCurrLayer
)
519 bIsCurrLayerUpdating
= pCurrLayer
->isUpdatePending();
521 if( bIsCurrLayerUpdating
)
522 aEndUpdater
= pCurrLayer
->beginUpdate();
525 if( bIsCurrLayerUpdating
&&
526 !rShape
.first
->isBackgroundDetached() &&
527 pCurrLayer
->isInsideUpdateArea(rShape
.first
) )
529 if( !rShape
.first
->render() )
539 /** Little wrapper around a Canvas, to render one-shot
542 class DummyLayer
: public ViewLayer
545 explicit DummyLayer( ::cppcanvas::CanvasSharedPtr xCanvas
) :
546 mpCanvas(std::move( xCanvas
))
550 virtual bool isOnView(ViewSharedPtr
const& /*rView*/) const override
552 return true; // visible on all views
555 virtual ::cppcanvas::CanvasSharedPtr
getCanvas() const override
560 virtual void clear() const override
565 virtual void clearAll() const override
570 virtual ::cppcanvas::CustomSpriteSharedPtr
createSprite( const ::basegfx::B2DSize
& /*rSpriteSizePixel*/,
571 double /*nSpritePrio*/ ) const override
573 ENSURE_OR_THROW( false,
574 "DummyLayer::createSprite(): This method is not supposed to be called!" );
575 return ::cppcanvas::CustomSpriteSharedPtr();
578 virtual void setPriority( const basegfx::B1DRange
& /*rRange*/ ) override
580 OSL_FAIL( "BitmapView::setPriority(): This method is not supposed to be called!" );
583 virtual css::geometry::IntegerSize2D
getTranslationOffset() const override
585 return geometry::IntegerSize2D(0,0);
588 virtual ::basegfx::B2DHomMatrix
getTransformation() const override
590 return mpCanvas
->getTransformation();
593 virtual ::basegfx::B2DHomMatrix
getSpriteTransformation() const override
595 OSL_FAIL( "BitmapView::getSpriteTransformation(): This method is not supposed to be called!" );
596 return ::basegfx::B2DHomMatrix();
599 virtual void setClip( const ::basegfx::B2DPolyPolygon
& /*rClip*/ ) override
601 OSL_FAIL( "BitmapView::setClip(): This method is not supposed to be called!" );
604 virtual bool resize( const ::basegfx::B2DRange
& /*rArea*/ ) override
606 OSL_FAIL( "BitmapView::resize(): This method is not supposed to be called!" );
611 ::cppcanvas::CanvasSharedPtr mpCanvas
;
615 bool LayerManager::renderTo( const ::cppcanvas::CanvasSharedPtr
& rTargetCanvas
) const
618 ViewLayerSharedPtr pTmpLayer
= std::make_shared
<DummyLayer
>( rTargetCanvas
);
620 for( const auto& rShape
: maAllShapes
)
624 // forward to all shape's addViewLayer method (which
625 // we request to render the Shape on the new
626 // ViewLayer. Since we add the shapes in the
627 // maShapeSet order (which is also the render order),
628 // this is equivalent to a subsequent render() call)
629 rShape
.first
->addViewLayer( pTmpLayer
,
632 // and remove again, this is only temporary
633 rShape
.first
->removeViewLayer( pTmpLayer
);
635 catch( uno::Exception
& )
637 // TODO(E1): Might be superfluous. Nowadays,
638 // addViewLayer swallows all errors, anyway.
639 TOOLS_WARN_EXCEPTION( "slideshow", "" );
640 // at least one shape could not be rendered
648 void LayerManager::addUpdateArea( ShapeSharedPtr
const& rShape
)
650 OSL_ASSERT( !maLayers
.empty() ); // always at least background layer
651 ENSURE_OR_THROW( rShape
, "LayerManager::addUpdateArea(): invalid Shape" );
653 const LayerShapeMap::const_iterator
aShapeEntry( maAllShapes
.find(rShape
) );
655 if( aShapeEntry
== maAllShapes
.end() )
658 LayerSharedPtr pLayer
= aShapeEntry
->second
.lock();
660 pLayer
->addUpdateRange( rShape
->getUpdateArea() );
663 void LayerManager::commitLayerChanges( std::size_t nCurrLayerIndex
,
664 LayerShapeMap::const_iterator aFirstLayerShape
,
665 const LayerShapeMap::const_iterator
& aEndLayerShapes
)
667 const bool bLayerExists( maLayers
.size() > nCurrLayerIndex
);
671 const LayerSharedPtr
& rLayer( maLayers
.at(nCurrLayerIndex
) );
672 const bool bLayerResized( rLayer
->commitBounds() );
673 rLayer
->setPriority( basegfx::B1DRange(nCurrLayerIndex
,
674 nCurrLayerIndex
+1) );
679 // need to re-render whole layer - start from
681 rLayer
->clearContent();
683 // render and remove from update set
684 while( aFirstLayerShape
!= aEndLayerShapes
)
686 maUpdateShapes
.erase(aFirstLayerShape
->first
);
687 aFirstLayerShape
->first
->render();
692 LayerSharedPtr
LayerManager::createForegroundLayer() const
694 OSL_ASSERT( mbActive
);
696 LayerSharedPtr
pLayer( Layer::createLayer() );
698 // create ViewLayers for all registered views, and add to
699 // newly created layer.
700 for( const auto& rView
: mrViews
)
701 pLayer
->addView( rView
);
706 void LayerManager::updateShapeLayers( bool bBackgroundLayerPainted
)
708 OSL_ASSERT( !maLayers
.empty() ); // always at least background layer
709 OSL_ASSERT( mbActive
);
711 // do we need to process shapes?
712 if( !mbLayerAssociationDirty
)
715 if( mbDisableAnimationZOrder
)
717 // layer setup happened elsewhere, is only bg layer
719 mbLayerAssociationDirty
= false;
723 // scan through maAllShapes, and determine shape animation
724 // discontinuities: when a shape that has
725 // isBackgroundDetached() return false follows a shape
726 // with isBackgroundDetached() true, the former and all
727 // following ones must be moved into an own layer.
729 // to avoid tons of temporaries, create weak_ptr to Layers
731 std::vector
< LayerWeakPtr
> aWeakLayers(maLayers
.begin(),maLayers
.end());
733 std::size_t nCurrLayerIndex(0);
734 bool bIsBackgroundLayer(true);
735 bool bLastWasBackgroundDetached(false); // last shape sprite state
736 LayerShapeMap::iterator
aCurrShapeEntry( maAllShapes
.begin() );
737 LayerShapeMap::iterator
aCurrLayerFirstShapeEntry( maAllShapes
.begin() );
738 const LayerShapeMap::iterator
aEndShapeEntry ( maAllShapes
.end() );
739 while( aCurrShapeEntry
!= aEndShapeEntry
)
741 const ShapeSharedPtr
pCurrShape( aCurrShapeEntry
->first
);
742 const bool bThisIsBackgroundDetached(
743 pCurrShape
->isBackgroundDetached() );
745 if( bLastWasBackgroundDetached
&&
746 !bThisIsBackgroundDetached
)
748 // discontinuity found - current shape needs to
749 // get into a new layer
752 // commit changes to previous layer
753 commitLayerChanges(nCurrLayerIndex
,
754 aCurrLayerFirstShapeEntry
,
756 aCurrLayerFirstShapeEntry
=aCurrShapeEntry
;
758 bIsBackgroundLayer
= false;
760 if( aWeakLayers
.size() <= nCurrLayerIndex
||
761 notEqual(aWeakLayers
.at(nCurrLayerIndex
), aCurrShapeEntry
->second
) )
763 // no more layers left, or shape was not
764 // member of this layer - create a new one
765 maLayers
.insert( maLayers
.begin()+nCurrLayerIndex
,
766 createForegroundLayer() );
767 aWeakLayers
.insert( aWeakLayers
.begin()+nCurrLayerIndex
,
768 maLayers
[nCurrLayerIndex
] );
772 OSL_ASSERT( maLayers
.size() == aWeakLayers
.size() );
774 // note: using indices here, since vector::insert
775 // above invalidates iterators
776 LayerSharedPtr
& rCurrLayer( maLayers
.at(nCurrLayerIndex
) );
777 LayerWeakPtr
& rCurrWeakLayer( aWeakLayers
.at(nCurrLayerIndex
) );
778 if( notEqual(rCurrWeakLayer
, aCurrShapeEntry
->second
) )
780 // mismatch: shape is not contained in current
781 // layer - move shape to that layer, then.
782 maLayers
.at(nCurrLayerIndex
)->setShapeViews(
785 // layer got new shape(s), need full repaint, if
787 if( !bThisIsBackgroundDetached
&& pCurrShape
->isVisible() )
789 LayerSharedPtr
pOldLayer( aCurrShapeEntry
->second
.lock() );
792 // old layer still valid? then we need to
793 // repaint former shape area
794 pOldLayer
->addUpdateRange(
795 pCurrShape
->getUpdateArea() );
798 // render on new layer (only if not
799 // explicitly disabled)
800 if( !(bBackgroundLayerPainted
&& bIsBackgroundLayer
) )
801 maUpdateShapes
.insert( pCurrShape
);
804 aCurrShapeEntry
->second
= rCurrWeakLayer
;
807 // update layerbounds regardless of the fact that the
808 // shape might be contained in said layer
809 // already. updateBounds() is dumb and needs to
810 // collect all shape bounds.
811 // of course, no need to expand layer bounds for
812 // shapes that reside in sprites themselves.
813 if( !bThisIsBackgroundDetached
&& !bIsBackgroundLayer
)
814 rCurrLayer
->updateBounds( pCurrShape
);
816 bLastWasBackgroundDetached
= bThisIsBackgroundDetached
;
820 // commit very last layer data
821 commitLayerChanges(nCurrLayerIndex
,
822 aCurrLayerFirstShapeEntry
,
825 // any layers left? Bin them!
826 if( maLayers
.size() > nCurrLayerIndex
+1 )
827 maLayers
.erase(maLayers
.begin()+nCurrLayerIndex
+1,
830 mbLayerAssociationDirty
= false;
834 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */