LibreOffice Module slideshow (master) 1
layermanager.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20
24#include <cppcanvas/canvas.hxx>
25
26#include <functional>
27#include <algorithm>
28#include <utility>
29
30#include "layermanager.hxx"
31
32using namespace ::com::sun::star;
33
34namespace
35{
36 // add operator!= for weak_ptr
37 bool notEqual( slideshow::internal::LayerWeakPtr const& rLHS,
39 {
40 return rLHS.lock().get() != rRHS.lock().get();
41 }
42}
43
44namespace slideshow::internal
45{
46 template<typename LayerFunc,
47 typename ShapeFunc> void LayerManager::manageViews(
48 LayerFunc layerFunc,
49 ShapeFunc shapeFunc )
50 {
51 LayerSharedPtr pCurrLayer;
52 ViewLayerSharedPtr pCurrViewLayer;
53 for( const auto& rShape : maAllShapes )
54 {
55 LayerSharedPtr pLayer = rShape.second.lock();
56 if( pLayer && pLayer != pCurrLayer )
57 {
58 pCurrLayer = pLayer;
59 pCurrViewLayer = layerFunc(pCurrLayer);
60 }
61
62 if( pCurrViewLayer )
63 shapeFunc(rShape.first,pCurrViewLayer);
64 }
65 }
66
68 bool bDisableAnimationZOrder ) :
69 mrViews(rViews),
70 maLayers(),
71 maXShapeHash( 101 ),
72 maAllShapes(),
73 maUpdateShapes(),
74 mnActiveSprites(0),
75 mbLayerAssociationDirty(false),
76 mbActive(false),
77 mbDisableAnimationZOrder(bDisableAnimationZOrder)
78 {
79 // prevent frequent resizes (won't have more than 4 layers
80 // for 99.9% of the cases)
81 maLayers.reserve(4);
82
83 // create initial background layer
85
86 // init views
87 for( const auto& rView : mrViews )
88 viewAdded( rView );
89 }
90
92 {
93 mbActive = true;
94 maUpdateShapes.clear(); // update gets forced via area, or
95 // has happened outside already
96
97 // clear all possibly pending update areas - content
98 // is there, already
99 for( const auto& pLayer : maLayers )
100 pLayer->clearUpdateRanges();
101
102 updateShapeLayers( true/*bSlideBackgroundPainted*/ );
103 }
104
106 {
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.
112
113 const bool bMoreThanOneLayer(maLayers.size() > 1);
114 if (mnActiveSprites || bMoreThanOneLayer)
115 {
116 // clear all viewlayers, dump everything but the
117 // background layer - this will also remove all shape
118 // sprites
119 for (auto& rShape : maAllShapes)
120 rShape.first->clearAllViewLayers();
121
122 for (auto& rShape : maAllShapes)
123 rShape.second.reset();
124
125 if (bMoreThanOneLayer)
126 maLayers.erase(maLayers.begin() + 1, maLayers.end());
127
129 }
130
131 mbActive = false;
132
133 // only background layer left
134 OSL_ASSERT( maLayers.size() == 1 && maLayers.front()->isBackgroundLayer() );
135 }
136
138 {
139 // view must be member of mrViews container
140 OSL_ASSERT( std::find(mrViews.begin(),
141 mrViews.end(),
142 rView) != mrViews.end() );
143
144 // init view content
145 if( mbActive )
146 rView->clearAll();
147
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 ); } );
154
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 );
159 }
160
162 {
163 // view must not be member of mrViews container anymore
164 OSL_ASSERT( std::find(mrViews.begin(),
165 mrViews.end(),
166 rView) == mrViews.end() );
167
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 ); } );
174
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 );
179 }
180
182 {
183 // view must be member of mrViews container
184 OSL_ASSERT( std::find(mrViews.begin(),
185 mrViews.end(),
186 rView) != mrViews.end() );
187
188 // TODO(P2): selectively update only changed view
189 viewsChanged();
190 }
191
193 {
194 if( !mbActive )
195 return;
196
197 // clear view area
198 for( const auto& pView : mrViews )
199 pView->clearAll();
200
201 // TODO(F3): resize and repaint all layers
202
203 // render all shapes
204 for( const auto& rShape : maAllShapes )
205 rShape.first->render();
206 }
207
209 {
210 OSL_ASSERT( !maLayers.empty() ); // always at least background layer
211 ENSURE_OR_THROW( rShape, "LayerManager::addShape(): invalid Shape" );
212
213 // add shape to XShape hash map
214 if( !maXShapeHash.emplace(rShape->getXShape(),
215 rShape).second )
216 {
217 // entry already present, nothing to do
218 return;
219 }
220
221 // add shape to appropriate layer
222 implAddShape( rShape );
223 }
224
225 void LayerManager::putShape2BackgroundLayer( LayerShapeMap::value_type& rShapeEntry )
226 {
227 LayerSharedPtr& rBgLayer( maLayers.front() );
228 rBgLayer->setShapeViews(rShapeEntry.first);
229 rShapeEntry.second = rBgLayer;
230 }
231
233 {
234 OSL_ASSERT( !maLayers.empty() ); // always at least background layer
235 ENSURE_OR_THROW( rShape, "LayerManager::implAddShape(): invalid Shape" );
236
237 LayerShapeMap::value_type aValue (rShape, LayerWeakPtr());
238
239 OSL_ASSERT( maAllShapes.find(rShape) == maAllShapes.end() ); // shape must not be added already
241
244 *maAllShapes.insert(aValue).first );
245 else
246 maAllShapes.insert(aValue);
247
248 // update shape, it's just added and not yet painted
249 if( rShape->isVisible() )
250 notifyShapeUpdate( rShape );
251 }
252
254 {
255 // remove shape from XShape hash map
256 if( maXShapeHash.erase( rShape->getXShape() ) == 0 )
257 return false; // shape not in map
258
259 OSL_ASSERT( maAllShapes.find(rShape) != maAllShapes.end() );
260
261 implRemoveShape( rShape );
262
263 return true;
264 }
265
267 {
268 OSL_ASSERT( !maLayers.empty() ); // always at least background layer
269 ENSURE_OR_THROW( rShape, "LayerManager::implRemoveShape(): invalid Shape" );
270
271 const LayerShapeMap::iterator aShapeEntry( maAllShapes.find(rShape) );
272
273 if( aShapeEntry == maAllShapes.end() )
274 return;
275
276 const bool bShapeUpdateNotified = maUpdateShapes.erase( rShape ) != 0;
277
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()) )
286 {
287 LayerSharedPtr pLayer = aShapeEntry->second.lock();
288 if( pLayer )
289 {
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() );
293 }
294 }
295
296 rShape->clearAllViewLayers();
297 maAllShapes.erase( aShapeEntry );
298
300 }
301
303 {
304 ENSURE_OR_THROW( xShape.is(), "LayerManager::lookupShape(): invalid Shape" );
305
306 const XShapeToShapeMap::const_iterator aIter( maXShapeHash.find( xShape ));
307 if( aIter == maXShapeHash.end() )
308 return ShapeSharedPtr(); // not found
309
310 // found, return data part of entry pair.
311 return aIter->second;
312 }
313
315 const DocTreeNode& rTreeNode )
316 {
317 OSL_ASSERT( !maLayers.empty() ); // always at least background layer
318
320
321 // shape already added?
322 if( rOrigShape->createSubset( pSubset,
323 rTreeNode ) )
324 {
325 OSL_ENSURE( pSubset, "LayerManager::getSubsetShape(): failed to create subset" );
326
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.
330
331 // add shape to corresponding layer
332 implAddShape( pSubset );
333
334 // update original shape, it now shows less content
335 // (the subset is removed from its displayed
336 // output). Subset shape is updated within
337 // implAddShape().
338 if( rOrigShape->isVisible() )
339 notifyShapeUpdate( rOrigShape );
340 }
341
342 return pSubset;
343 }
344
346 {
347 return maXShapeHash;
348 }
349
351 const AttributableShapeSharedPtr& rSubsetShape )
352 {
353 OSL_ASSERT( !maLayers.empty() ); // always at least background layer
354
355 if( rOrigShape->revokeSubset( rSubsetShape ) )
356 {
357 OSL_ASSERT( maAllShapes.find(rSubsetShape) != maAllShapes.end() );
358
359 implRemoveShape( rSubsetShape );
360
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 );
365 }
366 }
367
369 {
370 OSL_ASSERT( !maLayers.empty() ); // always at least background layer
371 ENSURE_OR_THROW( rShape, "LayerManager::enterAnimationMode(): invalid Shape" );
372
373 const bool bPrevAnimState( rShape->isBackgroundDetached() );
374
375 rShape->enterAnimationMode();
376
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() )
382 {
385
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 );
391 }
392
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.
396 }
397
399 {
400 ENSURE_OR_THROW( !maLayers.empty(), "LayerManager::leaveAnimationMode(): no layers" );
401 ENSURE_OR_THROW( rShape, "LayerManager::leaveAnimationMode(): invalid Shape" );
402
403 const bool bPrevAnimState( rShape->isBackgroundDetached() );
404
405 rShape->leaveAnimationMode();
406
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() )
412 {
415
416 // shape needs update, no previous rendering, fast
417 // update possible.
418 if( rShape->isVisible() )
419 notifyShapeUpdate( rShape );
420 }
421
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.
425 }
426
428 {
429 if( !mbActive || mrViews.empty() )
430 return;
431
432 // hidden sprite-shape needs render() call still, to hide sprite
433 if( rShape->isVisible() || rShape->isBackgroundDetached() )
434 maUpdateShapes.insert( rShape );
435 else
436 addUpdateArea( rShape );
437 }
438
440 {
441 if( !mbActive )
442 return false;
443
445 return true;
446
447 return std::any_of( maLayers.begin(),
448 maLayers.end(),
449 std::mem_fn(&Layer::isUpdatePending) );
450 }
451
453 {
454 bool bRet(true);
455
456 // send update() calls to every shape in the
457 // maUpdateShapes set, which is _animated_ (i.e. a
458 // sprite).
459 for( const auto& pShape : maUpdateShapes )
460 {
461 if( pShape->isBackgroundDetached() )
462 {
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
468 }
469 else
470 {
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?
475
476 // cannot update shape directly, it's not
477 // animated and update() calls will prolly
478 // overwrite other page content.
479 addUpdateArea( pShape );
480 }
481 }
482
483 maUpdateShapes.clear();
484
485 return bRet;
486 }
487
489 {
490 bool bRet = true;
491
492 if( !mbActive )
493 return bRet;
494
495 // going to render - better flush any pending layer reorg
496 // now
497 updateShapeLayers(false);
498
499 // all sprites
500 bRet = updateSprites();
501
502 // any non-sprite update areas left?
503 if( std::none_of( maLayers.begin(),
504 maLayers.end(),
505 std::mem_fn( &Layer::isUpdatePending ) ) )
506 return bRet; // nope, done.
507
508 // update each shape on each layer, that has
509 // isUpdatePending()
510 bool bIsCurrLayerUpdating(false);
511 Layer::EndUpdater aEndUpdater;
512 LayerSharedPtr pCurrLayer;
513 for( const auto& rShape : maAllShapes )
514 {
515 LayerSharedPtr pLayer = rShape.second.lock();
516 if( pLayer != pCurrLayer )
517 {
518 pCurrLayer = pLayer;
519 bIsCurrLayerUpdating = pCurrLayer->isUpdatePending();
520
521 if( bIsCurrLayerUpdating )
522 aEndUpdater = pCurrLayer->beginUpdate();
523 }
524
525 if( bIsCurrLayerUpdating &&
526 !rShape.first->isBackgroundDetached() &&
527 pCurrLayer->isInsideUpdateArea(rShape.first) )
528 {
529 if( !rShape.first->render() )
530 bRet = false;
531 }
532 }
533
534 return bRet;
535 }
536
537 namespace
538 {
542 class DummyLayer : public ViewLayer
543 {
544 public:
545 explicit DummyLayer( ::cppcanvas::CanvasSharedPtr xCanvas ) :
546 mpCanvas(std::move( xCanvas ))
547 {
548 }
549
550 virtual bool isOnView(ViewSharedPtr const& /*rView*/) const override
551 {
552 return true; // visible on all views
553 }
554
555 virtual ::cppcanvas::CanvasSharedPtr getCanvas() const override
556 {
557 return mpCanvas;
558 }
559
560 virtual void clear() const override
561 {
562 // NOOP
563 }
564
565 virtual void clearAll() const override
566 {
567 // NOOP
568 }
569
570 virtual ::cppcanvas::CustomSpriteSharedPtr createSprite( const ::basegfx::B2DSize& /*rSpriteSizePixel*/,
571 double /*nSpritePrio*/ ) const override
572 {
573 ENSURE_OR_THROW( false,
574 "DummyLayer::createSprite(): This method is not supposed to be called!" );
575 return ::cppcanvas::CustomSpriteSharedPtr();
576 }
577
578 virtual void setPriority( const basegfx::B1DRange& /*rRange*/ ) override
579 {
580 OSL_FAIL( "BitmapView::setPriority(): This method is not supposed to be called!" );
581 }
582
583 virtual css::geometry::IntegerSize2D getTranslationOffset() const override
584 {
585 return geometry::IntegerSize2D(0,0);
586 }
587
588 virtual ::basegfx::B2DHomMatrix getTransformation() const override
589 {
590 return mpCanvas->getTransformation();
591 }
592
593 virtual ::basegfx::B2DHomMatrix getSpriteTransformation() const override
594 {
595 OSL_FAIL( "BitmapView::getSpriteTransformation(): This method is not supposed to be called!" );
596 return ::basegfx::B2DHomMatrix();
597 }
598
599 virtual void setClip( const ::basegfx::B2DPolyPolygon& /*rClip*/ ) override
600 {
601 OSL_FAIL( "BitmapView::setClip(): This method is not supposed to be called!" );
602 }
603
604 virtual bool resize( const ::basegfx::B2DRange& /*rArea*/ ) override
605 {
606 OSL_FAIL( "BitmapView::resize(): This method is not supposed to be called!" );
607 return false;
608 }
609
610 private:
612 };
613 }
614
615 bool LayerManager::renderTo( const ::cppcanvas::CanvasSharedPtr& rTargetCanvas ) const
616 {
617 bool bRet( true );
618 ViewLayerSharedPtr pTmpLayer = std::make_shared<DummyLayer>( rTargetCanvas );
619
620 for( const auto& rShape : maAllShapes )
621 {
622 try
623 {
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,
630 true );
631
632 // and remove again, this is only temporary
633 rShape.first->removeViewLayer( pTmpLayer );
634 }
635 catch( uno::Exception& )
636 {
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
641 bRet = false;
642 }
643 }
644
645 return bRet;
646 }
647
649 {
650 OSL_ASSERT( !maLayers.empty() ); // always at least background layer
651 ENSURE_OR_THROW( rShape, "LayerManager::addUpdateArea(): invalid Shape" );
652
653 const LayerShapeMap::const_iterator aShapeEntry( maAllShapes.find(rShape) );
654
655 if( aShapeEntry == maAllShapes.end() )
656 return;
657
658 LayerSharedPtr pLayer = aShapeEntry->second.lock();
659 if( pLayer )
660 pLayer->addUpdateRange( rShape->getUpdateArea() );
661 }
662
663 void LayerManager::commitLayerChanges( std::size_t nCurrLayerIndex,
664 LayerShapeMap::const_iterator aFirstLayerShape,
665 const LayerShapeMap::const_iterator& aEndLayerShapes )
666 {
667 const bool bLayerExists( maLayers.size() > nCurrLayerIndex );
668 if( !bLayerExists )
669 return;
670
671 const LayerSharedPtr& rLayer( maLayers.at(nCurrLayerIndex) );
672 const bool bLayerResized( rLayer->commitBounds() );
673 rLayer->setPriority( basegfx::B1DRange(nCurrLayerIndex,
674 nCurrLayerIndex+1) );
675
676 if( !bLayerResized )
677 return;
678
679 // need to re-render whole layer - start from
680 // clean state
681 rLayer->clearContent();
682
683 // render and remove from update set
684 while( aFirstLayerShape != aEndLayerShapes )
685 {
686 maUpdateShapes.erase(aFirstLayerShape->first);
687 aFirstLayerShape->first->render();
688 ++aFirstLayerShape;
689 }
690 }
691
693 {
694 OSL_ASSERT( mbActive );
695
697
698 // create ViewLayers for all registered views, and add to
699 // newly created layer.
700 for( const auto& rView : mrViews )
701 pLayer->addView( rView );
702
703 return pLayer;
704 }
705
706 void LayerManager::updateShapeLayers( bool bBackgroundLayerPainted )
707 {
708 OSL_ASSERT( !maLayers.empty() ); // always at least background layer
709 OSL_ASSERT( mbActive );
710
711 // do we need to process shapes?
713 return;
714
716 {
717 // layer setup happened elsewhere, is only bg layer
718 // anyway.
720 return;
721 }
722
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.
728
729 // to avoid tons of temporaries, create weak_ptr to Layers
730 // beforehand
731 std::vector< LayerWeakPtr > aWeakLayers(maLayers.begin(),maLayers.end());
732
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 )
740 {
741 const ShapeSharedPtr pCurrShape( aCurrShapeEntry->first );
742 const bool bThisIsBackgroundDetached(
743 pCurrShape->isBackgroundDetached() );
744
745 if( bLastWasBackgroundDetached &&
746 !bThisIsBackgroundDetached )
747 {
748 // discontinuity found - current shape needs to
749 // get into a new layer
750
751
752 // commit changes to previous layer
753 commitLayerChanges(nCurrLayerIndex,
754 aCurrLayerFirstShapeEntry,
755 aCurrShapeEntry);
756 aCurrLayerFirstShapeEntry=aCurrShapeEntry;
757 ++nCurrLayerIndex;
758 bIsBackgroundLayer = false;
759
760 if( aWeakLayers.size() <= nCurrLayerIndex ||
761 notEqual(aWeakLayers.at(nCurrLayerIndex), aCurrShapeEntry->second) )
762 {
763 // no more layers left, or shape was not
764 // member of this layer - create a new one
765 maLayers.insert( maLayers.begin()+nCurrLayerIndex,
767 aWeakLayers.insert( aWeakLayers.begin()+nCurrLayerIndex,
768 maLayers[nCurrLayerIndex] );
769 }
770 }
771
772 OSL_ASSERT( maLayers.size() == aWeakLayers.size() );
773
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) )
779 {
780 // mismatch: shape is not contained in current
781 // layer - move shape to that layer, then.
782 maLayers.at(nCurrLayerIndex)->setShapeViews(
783 pCurrShape );
784
785 // layer got new shape(s), need full repaint, if
786 // non-sprite shape
787 if( !bThisIsBackgroundDetached && pCurrShape->isVisible() )
788 {
789 LayerSharedPtr pOldLayer( aCurrShapeEntry->second.lock() );
790 if( pOldLayer )
791 {
792 // old layer still valid? then we need to
793 // repaint former shape area
794 pOldLayer->addUpdateRange(
795 pCurrShape->getUpdateArea() );
796 }
797
798 // render on new layer (only if not
799 // explicitly disabled)
800 if( !(bBackgroundLayerPainted && bIsBackgroundLayer) )
801 maUpdateShapes.insert( pCurrShape );
802 }
803
804 aCurrShapeEntry->second = rCurrWeakLayer;
805 }
806
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 );
815
816 bLastWasBackgroundDetached = bThisIsBackgroundDetached;
817 ++aCurrShapeEntry;
818 }
819
820 // commit very last layer data
821 commitLayerChanges(nCurrLayerIndex,
822 aCurrLayerFirstShapeEntry,
823 aCurrShapeEntry);
824
825 // any layers left? Bin them!
826 if( maLayers.size() > nCurrLayerIndex+1 )
827 maLayers.erase(maLayers.begin()+nCurrLayerIndex+1,
828 maLayers.end());
829
831 }
832}
833
834/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
This class represents kind of a DOM tree node for shape text.
Definition: doctreenode.hxx:45
void implRemoveShape(const ShapeSharedPtr &rShape)
Common stuff when removing a shape.
bool mbDisableAnimationZOrder
When true, all sprite animations run in the foreground.
void viewAdded(const UnoViewSharedPtr &rView)
Notify new view added to UnoViewContainer.
bool renderTo(const ::cppcanvas::CanvasSharedPtr &rTargetCanvas) const
Render the content to given canvas.
void updateShapeLayers(bool bBackgroundLayerPainted)
Commits any pending layer reorg, due to shapes either entering or leaving animation mode.
void deactivate()
Deactivate the LayerManager.
void commitLayerChanges(std::size_t nCurrLayerIndex, LayerShapeMap::const_iterator aFirstLayerShape, const LayerShapeMap::const_iterator &aEndLayerShapes)
Push changes from updateShapeLayerAssociations() to current layer.
const UnoViewContainer & mrViews
Registered views.
ShapeSharedPtr lookupShape(const css::uno::Reference< css::drawing::XShape > &xShape) const
Lookup a Shape from an XShape model object.
LayerShapeMap maAllShapes
Set of shapes this LayerManager own.
AttributableShapeSharedPtr getSubsetShape(const AttributableShapeSharedPtr &rOrigShape, const DocTreeNode &rTreeNode)
Query a subset of the given original shape.
void notifyShapeUpdate(const ShapeSharedPtr &rShape)
Notify that a shape needs an update.
void revokeSubset(const AttributableShapeSharedPtr &rOrigShape, const AttributableShapeSharedPtr &rSubsetShape)
Revoke a previously queried subset shape.
void manageViews(LayerFunc layerFunc, ShapeFunc shapeFunc)
Add or remove views.
void activate()
Activate the LayerManager.
void leaveAnimationMode(const AnimatableShapeSharedPtr &rShape)
Notify the LayerManager that the given Shape is no longer animated.
void addUpdateArea(ShapeSharedPtr const &rShape)
Adds shape area to containing layer's damage area.
void implAddShape(const ShapeSharedPtr &rShape)
Common stuff when adding a shape.
void enterAnimationMode(const AnimatableShapeSharedPtr &rShape)
Notify the LayerManager that the given Shape starts an animation now.
bool mbLayerAssociationDirty
sal_True, if shapes might need to move to different layer
LayerSharedPtr createForegroundLayer() const
::std::vector< LayerSharedPtr > maLayers
All layers of this object. Vector owns the layers.
const XShapeToShapeMap & getXShapeToShapeMap() const
Get a map that maps all Shapes with their XShape reference as the key.
bool update()
Update the content.
LayerManager(const UnoViewContainer &rViews, bool bDisableAnimationZOrder)
Create a new layer manager for the given page bounds.
bool isUpdatePending() const
Check whether any update operations are pending.
void addShape(const ShapeSharedPtr &rShape)
Add the shape to this object.
void viewRemoved(const UnoViewSharedPtr &rView)
Notify view removed from UnoViewContainer.
void putShape2BackgroundLayer(LayerShapeMap::value_type &rShapeEntry)
Init Shape layers with background layer.
XShapeToShapeMap maXShapeHash
Contains all shapes with their XShape reference as the key.
bool mbActive
sal_False when deactivated
::std::set< ShapeSharedPtr > maUpdateShapes
Set of shapes that have requested an update.
sal_Int32 mnActiveSprites
Number of shape sprites currently active on this LayerManager.
void viewChanged(const UnoViewSharedPtr &rView)
bool removeShape(const ShapeSharedPtr &rShape)
Remove shape from this object.
bool isUpdatePending() const
Whether any update ranges have been added.
Definition: layer.hxx:150
static LayerSharedPtr createBackgroundLayer()
Create background layer.
Definition: layer.cxx:261
std::shared_ptr< LayerEndUpdate > EndUpdater
Definition: layer.hxx:64
static LayerSharedPtr createLayer()
Create non-background layer.
Definition: layer.cxx:266
#define TOOLS_WARN_EXCEPTION(area, stream)
#define ENSURE_OR_THROW(c, m)
::cppcanvas::CanvasSharedPtr mpCanvas
std::shared_ptr< Canvas > CanvasSharedPtr
::std::shared_ptr< AnimatableShape > AnimatableShapeSharedPtr
std::shared_ptr< View > ViewSharedPtr
Definition: view.hxx:80
std::shared_ptr< ViewLayer > ViewLayerSharedPtr
Definition: viewlayer.hxx:168
::std::weak_ptr< Layer > LayerWeakPtr
Definition: layer.hxx:38
::std::shared_ptr< Layer > LayerSharedPtr
Definition: layer.hxx:36
::std::shared_ptr< AttributableShape > AttributableShapeSharedPtr
std::unordered_map< css::uno::Reference< css::drawing::XShape >, ShapeSharedPtr, hash< css::uno::Reference< css::drawing::XShape > > > XShapeToShapeMap
A hash map which maps the XShape to the corresponding Shape object.
::std::shared_ptr< Shape > ShapeSharedPtr
std::shared_ptr< UnoView > UnoViewSharedPtr
::basegfx::B2DHomMatrix getSpriteTransformation(const ::basegfx::B2DVector &rPixelSize, const ::basegfx::B2DVector &rOrigSize, const ShapeAttributeLayerSharedPtr &pAttr)
Definition: tools.cxx:474
bool mbActive
When true, show() was called. Slide hidden otherwise.
Definition: slideimpl.cxx:254