Gtk-WARNING gtktreestore.c:1047: Invalid column number 1 added to iter
[LibreOffice.git] / slideshow / source / engine / slide / slideimpl.cxx
blob97bce331aed2efe2f64e1f9abb677356f823368d
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 <osl/diagnose.hxx>
22 #include <canvas/canvastools.hxx>
23 #include <comphelper/diagnose_ex.hxx>
24 #include <cppcanvas/basegfxfactory.hxx>
25 #include <cppcanvas/vclfactory.hxx>
27 #include <basegfx/matrix/b2dhommatrix.hxx>
28 #include <basegfx/matrix/b2dhommatrixtools.hxx>
29 #include <basegfx/point/b2dpoint.hxx>
31 #include <com/sun/star/awt/SystemPointer.hpp>
32 #include <com/sun/star/drawing/XMasterPageTarget.hpp>
33 #include <com/sun/star/frame/XModel.hpp>
34 #include <com/sun/star/beans/XPropertySet.hpp>
35 #include <com/sun/star/presentation/ParagraphTarget.hpp>
36 #include <com/sun/star/presentation/EffectNodeType.hpp>
38 #include <slide.hxx>
39 #include <slideshowcontext.hxx>
40 #include "slideanimations.hxx"
41 #include <doctreenode.hxx>
42 #include <screenupdater.hxx>
43 #include <cursormanager.hxx>
44 #include <shapeimporter.hxx>
45 #include <slideshowexceptions.hxx>
46 #include <eventqueue.hxx>
47 #include <activitiesqueue.hxx>
48 #include "layermanager.hxx"
49 #include "shapemanagerimpl.hxx"
50 #include <usereventqueue.hxx>
51 #include "userpaintoverlay.hxx"
52 #include "targetpropertiescreator.hxx"
53 #include <tools.hxx>
54 #include <tools/helpers.hxx>
55 #include <tools/json_writer.hxx>
56 #include <box2dtools.hxx>
57 #include <utility>
58 #include <vcl/graphicfilter.hxx>
59 #include <vcl/virdev.hxx>
60 #include <svx/svdograf.hxx>
62 using namespace ::com::sun::star;
65 namespace slideshow::internal
68 namespace
70 class SlideImpl : public Slide,
71 public CursorManager,
72 public ViewEventHandler,
73 public ::osl::DebugBase<SlideImpl>
75 public:
76 SlideImpl( const uno::Reference<drawing::XDrawPage>& xDrawPage,
77 uno::Reference<drawing::XDrawPagesSupplier> xDrawPages,
78 uno::Reference<animations::XAnimationNode> xRootNode,
79 EventQueue& rEventQueue,
80 EventMultiplexer& rEventMultiplexer,
81 ScreenUpdater& rScreenUpdater,
82 ActivitiesQueue& rActivitiesQueue,
83 UserEventQueue& rUserEventQueue,
84 CursorManager& rCursorManager,
85 MediaFileManager& rMediaFileManager,
86 const UnoViewContainer& rViewContainer,
87 const uno::Reference<uno::XComponentContext>& xContext,
88 const ShapeEventListenerMap& rShapeListenerMap,
89 const ShapeCursorMap& rShapeCursorMap,
90 PolyPolygonVector&& rPolyPolygonVector,
91 RGBColor const& rUserPaintColor,
92 double dUserPaintStrokeWidth,
93 bool bUserPaintEnabled,
94 bool bIntrinsicAnimationsAllowed,
95 bool bDisableAnimationZOrder);
97 virtual ~SlideImpl() override;
100 // Slide interface
103 virtual void prefetch() override;
104 virtual void show( bool ) override;
105 virtual void hide() override;
107 virtual basegfx::B2ISize getSlideSize() const override;
108 virtual uno::Reference<drawing::XDrawPage > getXDrawPage() const override;
109 virtual uno::Reference<animations::XAnimationNode> getXAnimationNode() const override;
110 virtual PolyPolygonVector getPolygons() override;
111 virtual void drawPolygons() const override;
112 virtual bool isPaintOverlayActive() const override;
113 virtual void enablePaintOverlay() override;
114 virtual void update_settings( bool bUserPaintEnabled, RGBColor const& aUserPaintColor, double dUserPaintStrokeWidth ) override;
117 // TODO(F2): Rework SlideBitmap to no longer be based on XBitmap,
118 // but on canvas-independent basegfx bitmaps
119 virtual SlideBitmapSharedPtr getCurrentSlideBitmap( const UnoViewSharedPtr& rView ) const override;
121 private:
122 // ViewEventHandler
123 virtual void viewAdded( const UnoViewSharedPtr& rView ) override;
124 virtual void viewRemoved( const UnoViewSharedPtr& rView ) override;
125 virtual void viewChanged( const UnoViewSharedPtr& rView ) override;
126 virtual void viewsChanged() override;
128 // CursorManager
129 virtual bool requestCursor( sal_Int16 nCursorShape ) override;
130 virtual void resetCursor() override;
132 void activatePaintOverlay();
133 void deactivatePaintOverlay();
135 /** Query whether the slide has animations at all
137 If the slide doesn't have animations, show() displays
138 only static content. If an event is registered with
139 registerSlideEndEvent(), this event will be
140 immediately activated at the end of the show() method.
142 @return true, if this slide has animations, false
143 otherwise
145 bool isAnimated();
147 /// Set all Shapes to their initial attributes for slideshow
148 bool applyInitialShapeAttributes( const css::uno::Reference< css::animations::XAnimationNode >& xRootAnimationNode );
150 /// Set shapes to attributes corresponding to initial or final state of slide
151 void applyShapeAttributes(
152 const css::uno::Reference< css::animations::XAnimationNode >& xRootAnimationNode,
153 bool bInitial) const;
155 /// Renders current slide content to bitmap
156 SlideBitmapSharedPtr createCurrentSlideBitmap(
157 const UnoViewSharedPtr& rView,
158 ::basegfx::B2ISize const & rSlideSize ) const;
160 /// Prefetch all shapes (not the animations)
161 bool loadShapes();
163 /// Retrieve slide size from XDrawPage
164 basegfx::B2ISize getSlideSizeImpl() const;
166 /// Prefetch show, but don't call applyInitialShapeAttributes()
167 bool implPrefetchShow();
169 /// Add Polygons to the member maPolygons
170 void addPolygons(const PolyPolygonVector& rPolygons);
172 // Types
173 // =====
175 enum SlideAnimationState
177 CONSTRUCTING_STATE=0,
178 INITIAL_STATE=1,
179 SHOWING_STATE=2,
180 FINAL_STATE=3,
181 SlideAnimationState_NUM_ENTRIES=4
184 typedef std::vector< SlideBitmapSharedPtr > VectorOfSlideBitmaps;
185 /** Vector of slide bitmaps.
187 Since the bitmap content is sensitive to animation
188 effects, we have an inner vector containing a distinct
189 bitmap for each of the SlideAnimationStates.
191 typedef ::std::vector< std::pair< UnoViewSharedPtr,
192 VectorOfSlideBitmaps > > VectorOfVectorOfSlideBitmaps;
195 // Member variables
196 // ================
198 /// The page model object
199 uno::Reference< drawing::XDrawPage > mxDrawPage;
200 uno::Reference< drawing::XDrawPagesSupplier > mxDrawPagesSupplier;
201 uno::Reference< animations::XAnimationNode > mxRootNode;
203 LayerManagerSharedPtr mpLayerManager;
204 std::shared_ptr<ShapeManagerImpl> mpShapeManager;
205 std::shared_ptr<SubsettableShapeManager> mpSubsettableShapeManager;
206 box2d::utils::Box2DWorldSharedPtr mpBox2DWorld;
208 /// Contains common objects needed throughout the slideshow
209 SlideShowContext maContext;
211 /// parent cursor manager
212 CursorManager& mrCursorManager;
214 /// Handles the animation and event generation for us
215 SlideAnimations maAnimations;
216 PolyPolygonVector maPolygons;
218 RGBColor maUserPaintColor;
219 double mdUserPaintStrokeWidth;
220 UserPaintOverlaySharedPtr mpPaintOverlay;
222 /// Bitmaps with slide content at various states
223 mutable VectorOfVectorOfSlideBitmaps maSlideBitmaps;
225 SlideAnimationState meAnimationState;
227 const basegfx::B2ISize maSlideSize;
229 sal_Int16 mnCurrentCursor;
231 /// True, when intrinsic shape animations are allowed
232 bool mbIntrinsicAnimationsAllowed;
234 /// True, when user paint overlay is enabled
235 bool mbUserPaintOverlayEnabled;
237 /// True, if initial load of all page shapes succeeded
238 bool mbShapesLoaded;
240 /// True, if initial load of all animation info succeeded
241 bool mbShowLoaded;
243 /** True, if this slide is not static.
245 If this slide has animated content, this variable will
246 be true, and false otherwise.
248 bool mbHaveAnimations;
250 /** True, if this slide has a main animation sequence.
252 If this slide has animation content, which in turn has
253 a main animation sequence (which must be fully run
254 before EventMultiplexer::notifySlideAnimationsEnd() is
255 called), this member is true.
257 bool mbMainSequenceFound;
259 /// When true, show() was called. Slide hidden otherwise.
260 bool mbActive;
262 /// When true, enablePaintOverlay was called and mbUserPaintOverlay = true
263 bool mbPaintOverlayActive;
265 /// When true, final state attributes are already applied to shapes
266 bool mbFinalStateApplied;
270 void slideRenderer( SlideImpl const * pSlide, const UnoViewSharedPtr& rView )
272 // fully clear view content to background color
273 rView->clearAll();
275 SlideBitmapSharedPtr pBitmap( pSlide->getCurrentSlideBitmap( rView ) );
276 ::cppcanvas::CanvasSharedPtr pCanvas( rView->getCanvas() );
278 const ::basegfx::B2DHomMatrix aViewTransform( rView->getTransformation() );
279 const ::basegfx::B2DPoint aOutPosPixel( aViewTransform * ::basegfx::B2DPoint() );
281 // setup a canvas with device coordinate space, the slide
282 // bitmap already has the correct dimension.
283 ::cppcanvas::CanvasSharedPtr pDevicePixelCanvas( pCanvas->clone() );
284 pDevicePixelCanvas->setTransformation( ::basegfx::B2DHomMatrix() );
286 // render at given output position
287 pBitmap->move( aOutPosPixel );
289 // clear clip (might have been changed, e.g. from comb
290 // transition)
291 pBitmap->clip( ::basegfx::B2DPolyPolygon() );
292 pBitmap->draw( pDevicePixelCanvas );
296 SlideImpl::SlideImpl( const uno::Reference< drawing::XDrawPage >& xDrawPage,
297 uno::Reference<drawing::XDrawPagesSupplier> xDrawPages,
298 uno::Reference< animations::XAnimationNode > xRootNode,
299 EventQueue& rEventQueue,
300 EventMultiplexer& rEventMultiplexer,
301 ScreenUpdater& rScreenUpdater,
302 ActivitiesQueue& rActivitiesQueue,
303 UserEventQueue& rUserEventQueue,
304 CursorManager& rCursorManager,
305 MediaFileManager& rMediaFileManager,
306 const UnoViewContainer& rViewContainer,
307 const uno::Reference< uno::XComponentContext >& xComponentContext,
308 const ShapeEventListenerMap& rShapeListenerMap,
309 const ShapeCursorMap& rShapeCursorMap,
310 PolyPolygonVector&& rPolyPolygonVector,
311 RGBColor const& aUserPaintColor,
312 double dUserPaintStrokeWidth,
313 bool bUserPaintEnabled,
314 bool bIntrinsicAnimationsAllowed,
315 bool bDisableAnimationZOrder) :
316 mxDrawPage( xDrawPage ),
317 mxDrawPagesSupplier(std::move( xDrawPages )),
318 mxRootNode(std::move( xRootNode )),
319 mpLayerManager( std::make_shared<LayerManager>(
320 rViewContainer,
321 bDisableAnimationZOrder) ),
322 mpShapeManager( std::make_shared<ShapeManagerImpl>(
323 rEventMultiplexer,
324 mpLayerManager,
325 rCursorManager,
326 rShapeListenerMap,
327 rShapeCursorMap,
328 xDrawPage)),
329 mpSubsettableShapeManager( mpShapeManager ),
330 mpBox2DWorld( std::make_shared<box2d::utils::box2DWorld>(
331 basegfx::B2DVector(getSlideSizeImpl().getWidth(), getSlideSizeImpl().getHeight()) ) ),
332 maContext( mpSubsettableShapeManager,
333 rEventQueue,
334 rEventMultiplexer,
335 rScreenUpdater,
336 rActivitiesQueue,
337 rUserEventQueue,
338 *this,
339 rMediaFileManager,
340 rViewContainer,
341 xComponentContext,
342 mpBox2DWorld ),
343 mrCursorManager( rCursorManager ),
344 maAnimations( maContext,
345 basegfx::B2DVector(getSlideSizeImpl().getWidth(), getSlideSizeImpl().getHeight()) ),
346 maPolygons(std::move(rPolyPolygonVector)),
347 maUserPaintColor(aUserPaintColor),
348 mdUserPaintStrokeWidth(dUserPaintStrokeWidth),
349 mpPaintOverlay(),
350 maSlideBitmaps(),
351 meAnimationState( CONSTRUCTING_STATE ),
352 maSlideSize(getSlideSizeImpl()),
353 mnCurrentCursor( awt::SystemPointer::ARROW ),
354 mbIntrinsicAnimationsAllowed( bIntrinsicAnimationsAllowed ),
355 mbUserPaintOverlayEnabled(bUserPaintEnabled),
356 mbShapesLoaded( false ),
357 mbShowLoaded( false ),
358 mbHaveAnimations( false ),
359 mbMainSequenceFound( false ),
360 mbActive( false ),
361 mbPaintOverlayActive( false ),
362 mbFinalStateApplied( false )
364 if (uno::Reference<frame::XModel> xModel{ mxDrawPagesSupplier, uno::UNO_QUERY })
366 OUString presentationURL = xModel->getURL();
367 auto fileDirectoryEndIdx = presentationURL.lastIndexOf("/");
368 if (presentationURL.startsWith("file:///") && fileDirectoryEndIdx != -1)
369 maContext.maFallbackDir = OUString::Concat(presentationURL.subView(0, fileDirectoryEndIdx + 1));
372 // clone already existing views for slide bitmaps
373 for( const auto& rView : rViewContainer )
374 viewAdded( rView );
376 // register screen update (LayerManager needs to signal pending
377 // updates)
378 maContext.mrScreenUpdater.addViewUpdate(mpShapeManager);
381 void SlideImpl::update_settings( bool bUserPaintEnabled, RGBColor const& aUserPaintColor, double dUserPaintStrokeWidth )
383 maUserPaintColor = aUserPaintColor;
384 mdUserPaintStrokeWidth = dUserPaintStrokeWidth;
385 mbUserPaintOverlayEnabled = bUserPaintEnabled;
388 SlideImpl::~SlideImpl()
390 if( mpShapeManager )
392 maContext.mrScreenUpdater.removeViewUpdate(mpShapeManager);
393 mpShapeManager->dispose();
395 // TODO(Q3): Make sure LayerManager (and thus Shapes) dies
396 // first, because SlideShowContext has SubsettableShapeManager
397 // as reference member.
398 mpLayerManager.reset();
402 void SlideImpl::prefetch()
404 if( !mxRootNode.is() )
405 return;
407 // Try to prefetch all graphics from the page. This will be done
408 // in threads to be more efficient than loading them on-demand one by one.
409 std::vector<Graphic*> graphics;
410 for (sal_Int32 i = 0; i < mxDrawPage->getCount(); i++)
412 css::uno::Reference<css::drawing::XShape> xShape(mxDrawPage->getByIndex(i), css::uno::UNO_QUERY_THROW);
413 SdrObject* pObj = SdrObject::getSdrObjectFromXShape(xShape);
414 if (!pObj)
415 continue;
416 if( SdrGrafObj* grafObj = dynamic_cast<SdrGrafObj*>(pObj))
417 if( !grafObj->GetGraphic().isAvailable())
418 graphics.push_back( const_cast<Graphic*>(&grafObj->GetGraphic()));
420 if(graphics.size() > 1) // threading does not help with loading just one
421 GraphicFilter::GetGraphicFilter().MakeGraphicsAvailableThreaded( graphics );
423 applyInitialShapeAttributes(mxRootNode);
426 void SlideImpl::show( bool bSlideBackgroundPainted )
428 if( mbActive )
429 return; // already active
431 if( !mpShapeManager || !mpLayerManager )
432 return; // disposed
434 // set initial shape attributes (e.g. hide shapes that have
435 // 'appear' effect set)
436 if( !applyInitialShapeAttributes(mxRootNode) )
437 return;
439 // activate and take over view - clears view, if necessary
440 mbActive = true;
441 requestCursor( mnCurrentCursor );
443 // enable shape management & event broadcasting for shapes of this
444 // slide. Also enables LayerManager to record updates. Currently,
445 // never let LayerManager render initial slide content, use
446 // buffered slide bitmaps instead.
447 mpShapeManager->activate();
450 // render slide to screen, if requested
451 if( !bSlideBackgroundPainted )
453 for( const auto& rContext : maContext.mrViewContainer )
454 slideRenderer( this, rContext );
456 maContext.mrScreenUpdater.notifyUpdate();
460 // fire up animations
461 const bool bIsAnimated( isAnimated() );
462 if( bIsAnimated )
463 maAnimations.start(); // feeds initial events into queue
465 // NOTE: this looks slightly weird, but is indeed correct:
466 // as isAnimated() might return false, _although_ there is
467 // a main sequence (because the animation nodes don't
468 // contain any executable effects), we gotta check both
469 // conditions here.
470 if( !bIsAnimated || !mbMainSequenceFound )
472 // manually trigger a slide animation end event (we don't have
473 // animations at all, or we don't have a main animation
474 // sequence, but if we had, it'd end now). Note that having
475 // animations alone does not matter here, as only main
476 // sequence animations prevents showing the next slide on
477 // nextEvent().
478 maContext.mrEventMultiplexer.notifySlideAnimationsEnd();
481 // enable shape-intrinsic animations (drawing layer animations or
482 // GIF animations)
483 if( mbIntrinsicAnimationsAllowed )
484 mpSubsettableShapeManager->notifyIntrinsicAnimationsEnabled();
486 // enable paint overlay, if maUserPaintColor is valid
487 activatePaintOverlay();
490 // from now on, animations might be showing
491 meAnimationState = SHOWING_STATE;
494 void SlideImpl::hide()
496 if( !mbActive || !mpShapeManager )
497 return; // already hidden/disposed
500 // from now on, all animations are stopped
501 meAnimationState = FINAL_STATE;
504 // disable user paint overlay under all circumstances,
505 // this slide now ceases to be active.
506 deactivatePaintOverlay();
509 // switch off all shape-intrinsic animations.
510 mpSubsettableShapeManager->notifyIntrinsicAnimationsDisabled();
512 // force-end all SMIL animations, too
513 maAnimations.end();
516 // disable shape management & event broadcasting for shapes of this
517 // slide. Also disables LayerManager.
518 mpShapeManager->deactivate();
520 // vanish from view
521 resetCursor();
522 mbActive = false;
525 basegfx::B2ISize SlideImpl::getSlideSize() const
527 return maSlideSize;
530 uno::Reference<drawing::XDrawPage > SlideImpl::getXDrawPage() const
532 return mxDrawPage;
535 uno::Reference<animations::XAnimationNode> SlideImpl::getXAnimationNode() const
537 return mxRootNode;
540 PolyPolygonVector SlideImpl::getPolygons()
542 if(mbPaintOverlayActive)
543 maPolygons = mpPaintOverlay->getPolygons();
544 return maPolygons;
547 SlideBitmapSharedPtr SlideImpl::getCurrentSlideBitmap( const UnoViewSharedPtr& rView ) const
549 // search corresponding entry in maSlideBitmaps (which
550 // contains the views as the key)
551 VectorOfVectorOfSlideBitmaps::iterator aIter;
552 const VectorOfVectorOfSlideBitmaps::iterator aEnd( maSlideBitmaps.end() );
553 if( (aIter=std::find_if( maSlideBitmaps.begin(),
554 aEnd,
555 [&rView]
556 ( const VectorOfVectorOfSlideBitmaps::value_type& cp )
557 { return rView == cp.first; } ) ) == aEnd )
559 // corresponding view not found - maybe view was not
560 // added to Slide?
561 ENSURE_OR_THROW( false,
562 "SlideImpl::getInitialSlideBitmap(): view does not "
563 "match any of the added ones" );
566 // ensure that the show is loaded
567 if( !mbShowLoaded )
569 // only prefetch and init shapes when not done already
570 // (otherwise, at least applyInitialShapeAttributes() will be
571 // called twice for initial slide rendering). Furthermore,
572 // applyInitialShapeAttributes() _always_ performs
573 // initializations, which would be highly unwanted during a
574 // running show. OTOH, a slide whose mbShowLoaded is false is
575 // guaranteed not be running a show.
577 // set initial shape attributes (e.g. hide 'appear' effect
578 // shapes)
579 if( !const_cast<SlideImpl*>(this)->applyInitialShapeAttributes( mxRootNode ) )
580 ENSURE_OR_THROW(false,
581 "SlideImpl::getCurrentSlideBitmap(): Cannot "
582 "apply initial attributes");
585 SlideBitmapSharedPtr& rBitmap( aIter->second.at( meAnimationState ));
586 auto aSize = getSlideSizePixel(basegfx::B2DVector(getSlideSize().getWidth(), getSlideSize().getHeight()), rView);
587 const basegfx::B2ISize rSlideSize(aSize.getX(), aSize.getY());
589 // is the bitmap valid (actually existent, and of correct
590 // size)?
591 if( !rBitmap || rBitmap->getSize() != rSlideSize )
593 // no bitmap there yet, or wrong size - create one
594 rBitmap = createCurrentSlideBitmap(rView, rSlideSize);
597 return rBitmap;
601 // private methods
604 void SlideImpl::viewAdded( const UnoViewSharedPtr& rView )
606 maSlideBitmaps.emplace_back( rView,
607 VectorOfSlideBitmaps(SlideAnimationState_NUM_ENTRIES) );
609 if( mpLayerManager )
610 mpLayerManager->viewAdded( rView );
613 void SlideImpl::viewRemoved( const UnoViewSharedPtr& rView )
615 if( mpLayerManager )
616 mpLayerManager->viewRemoved( rView );
618 std::erase_if(maSlideBitmaps,
619 [&rView]
620 ( const VectorOfVectorOfSlideBitmaps::value_type& cp )
621 { return rView == cp.first; } );
624 void SlideImpl::viewChanged( const UnoViewSharedPtr& rView )
626 // nothing to do for the Slide - getCurrentSlideBitmap() lazily
627 // handles bitmap resizes
628 if( mbActive && mpLayerManager )
629 mpLayerManager->viewChanged(rView);
632 void SlideImpl::viewsChanged()
634 // nothing to do for the Slide - getCurrentSlideBitmap() lazily
635 // handles bitmap resizes
636 if( mbActive && mpLayerManager )
637 mpLayerManager->viewsChanged();
640 bool SlideImpl::requestCursor( sal_Int16 nCursorShape )
642 mnCurrentCursor = nCursorShape;
643 return mrCursorManager.requestCursor(mnCurrentCursor);
646 void SlideImpl::resetCursor()
648 mnCurrentCursor = awt::SystemPointer::ARROW;
649 mrCursorManager.resetCursor();
652 bool SlideImpl::isAnimated()
654 // prefetch, but don't apply initial shape attributes
655 if( !implPrefetchShow() )
656 return false;
658 return mbHaveAnimations && maAnimations.isAnimated();
661 SlideBitmapSharedPtr SlideImpl::createCurrentSlideBitmap( const UnoViewSharedPtr& rView,
662 const ::basegfx::B2ISize& rBmpSize ) const
664 ENSURE_OR_THROW( rView && rView->getCanvas(),
665 "SlideImpl::createCurrentSlideBitmap(): Invalid view" );
666 ENSURE_OR_THROW( mpLayerManager,
667 "SlideImpl::createCurrentSlideBitmap(): Invalid layer manager" );
668 ENSURE_OR_THROW( mbShowLoaded,
669 "SlideImpl::createCurrentSlideBitmap(): No show loaded" );
671 // tdf#96083 ensure end state settings are applied to shapes once when bitmap gets re-rendered
672 // in that state
673 if(!mbFinalStateApplied && FINAL_STATE == meAnimationState && mxRootNode.is())
675 const_cast< SlideImpl* >(this)->mbFinalStateApplied = true;
676 applyShapeAttributes(mxRootNode, false);
679 ::cppcanvas::CanvasSharedPtr pCanvas( rView->getCanvas() );
681 // create a bitmap of appropriate size
682 ::cppcanvas::BitmapSharedPtr pBitmap(
683 ::cppcanvas::BaseGfxFactory::createBitmap(
684 pCanvas,
685 rBmpSize ) );
687 ENSURE_OR_THROW( pBitmap,
688 "SlideImpl::createCurrentSlideBitmap(): Cannot create page bitmap" );
690 ::cppcanvas::BitmapCanvasSharedPtr pBitmapCanvas( pBitmap->getBitmapCanvas() );
692 ENSURE_OR_THROW( pBitmapCanvas,
693 "SlideImpl::createCurrentSlideBitmap(): Cannot create page bitmap canvas" );
695 // apply linear part of destination canvas transformation (linear means in this context:
696 // transformation without any translational components)
697 ::basegfx::B2DHomMatrix aLinearTransform( rView->getTransformation() );
698 aLinearTransform.set( 0, 2, 0.0 );
699 aLinearTransform.set( 1, 2, 0.0 );
700 pBitmapCanvas->setTransformation( aLinearTransform );
702 // output all shapes to bitmap
703 initSlideBackground( pBitmapCanvas, rBmpSize );
704 mpLayerManager->renderTo( pBitmapCanvas );
706 return std::make_shared<SlideBitmap>( pBitmap );
709 class MainSequenceSearcher
711 public:
712 MainSequenceSearcher()
714 maSearchKey.Name = "node-type";
715 maSearchKey.Value <<= presentation::EffectNodeType::MAIN_SEQUENCE;
718 void operator()( const uno::Reference< animations::XAnimationNode >& xChildNode )
720 uno::Sequence< beans::NamedValue > aUserData( xChildNode->getUserData() );
722 if( findNamedValue( aUserData, maSearchKey ) )
724 maMainSequence = xChildNode;
728 const uno::Reference< animations::XAnimationNode >& getMainSequence() const
730 return maMainSequence;
733 private:
734 beans::NamedValue maSearchKey;
735 uno::Reference< animations::XAnimationNode > maMainSequence;
738 bool SlideImpl::implPrefetchShow()
740 if( mbShowLoaded )
741 return true;
743 ENSURE_OR_RETURN_FALSE( mxDrawPage.is(),
744 "SlideImpl::implPrefetchShow(): Invalid draw page" );
745 ENSURE_OR_RETURN_FALSE( mpLayerManager,
746 "SlideImpl::implPrefetchShow(): Invalid layer manager" );
748 // fetch desired page content
749 // ==========================
751 if( !loadShapes() )
752 return false;
754 // New animations framework: import the shape effect info
755 // ======================================================
759 if( mxRootNode.is() )
761 if( !maAnimations.importAnimations( mxRootNode ) )
763 OSL_FAIL( "SlideImpl::implPrefetchShow(): have animation nodes, "
764 "but import animations failed." );
766 // could not import animation framework,
767 // _although_ some animation nodes are there -
768 // this is an error (not finding animations at
769 // all is okay - might be a static slide)
770 return false;
773 // now check whether we've got a main sequence (if
774 // not, we must manually call
775 // EventMultiplexer::notifySlideAnimationsEnd()
776 // above, as e.g. interactive sequences alone
777 // don't block nextEvent() from issuing the next
778 // slide)
779 MainSequenceSearcher aSearcher;
780 if( for_each_childNode( mxRootNode, aSearcher ) )
781 mbMainSequenceFound = aSearcher.getMainSequence().is();
783 // import successfully done
784 mbHaveAnimations = true;
787 catch( uno::RuntimeException& )
789 throw;
791 catch( uno::Exception& )
793 TOOLS_WARN_EXCEPTION( "slideshow", "" );
794 // TODO(E2): Error handling. For now, bail out
797 mbShowLoaded = true;
799 return true;
802 void SlideImpl::enablePaintOverlay()
804 if( !mbUserPaintOverlayEnabled || !mbPaintOverlayActive )
806 mbUserPaintOverlayEnabled = true;
807 activatePaintOverlay();
811 void SlideImpl::activatePaintOverlay()
813 if( mbUserPaintOverlayEnabled || !maPolygons.empty() )
815 mpPaintOverlay = UserPaintOverlay::create( maUserPaintColor,
816 mdUserPaintStrokeWidth,
817 maContext,
818 std::vector(maPolygons),
819 mbUserPaintOverlayEnabled );
820 mbPaintOverlayActive = true;
824 void SlideImpl::drawPolygons() const
826 if( mpPaintOverlay )
827 mpPaintOverlay->drawPolygons();
830 void SlideImpl::addPolygons(const PolyPolygonVector& rPolygons)
832 maPolygons.insert(maPolygons.end(), rPolygons.begin(), rPolygons.end());
835 bool SlideImpl::isPaintOverlayActive() const
837 return mbPaintOverlayActive;
840 void SlideImpl::deactivatePaintOverlay()
842 if(mbPaintOverlayActive)
843 maPolygons = mpPaintOverlay->getPolygons();
845 mpPaintOverlay.reset();
846 mbPaintOverlayActive = false;
849 void SlideImpl::applyShapeAttributes(
850 const css::uno::Reference< css::animations::XAnimationNode >& xRootAnimationNode,
851 bool bInitial) const
853 const uno::Sequence< animations::TargetProperties > aProps(
854 TargetPropertiesCreator::createTargetProperties( xRootAnimationNode, bInitial ) );
856 // apply extracted values to our shapes
857 for( const auto& rProp : aProps )
859 sal_Int16 nParaIndex( -1 );
860 uno::Reference< drawing::XShape > xShape( rProp.Target,
861 uno::UNO_QUERY );
863 if( !xShape.is() )
865 // not a shape target. Maybe a ParagraphTarget?
866 presentation::ParagraphTarget aParaTarget;
868 if( rProp.Target >>= aParaTarget )
870 // yep, ParagraphTarget found - extract shape
871 // and index
872 xShape = aParaTarget.Shape;
873 nParaIndex = aParaTarget.Paragraph;
877 if( xShape.is() )
879 ShapeSharedPtr pShape( mpLayerManager->lookupShape( xShape ) );
881 if( !pShape )
883 OSL_FAIL( "SlideImpl::applyInitialShapeAttributes(): no shape found for given target" );
884 continue;
887 AttributableShapeSharedPtr pAttrShape(
888 ::std::dynamic_pointer_cast< AttributableShape >( pShape ) );
890 if( !pAttrShape )
892 OSL_FAIL( "SlideImpl::applyInitialShapeAttributes(): shape found does not "
893 "implement AttributableShape interface" );
894 continue;
897 if( nParaIndex != -1 )
899 // our target is a paragraph subset, thus look
900 // this up first.
901 const DocTreeNodeSupplier& rNodeSupplier( pAttrShape->getTreeNodeSupplier() );
903 if( rNodeSupplier.getNumberOfTreeNodes(
904 DocTreeNode::NodeType::LogicalParagraph ) <= nParaIndex )
906 OSL_FAIL( "SlideImpl::applyInitialShapeAttributes(): shape found does not "
907 "provide a subset for requested paragraph index" );
908 continue;
911 pAttrShape = pAttrShape->getSubset(
912 rNodeSupplier.getTreeNode(
913 nParaIndex,
914 DocTreeNode::NodeType::LogicalParagraph ) );
916 if( !pAttrShape )
918 OSL_FAIL( "SlideImpl::applyInitialShapeAttributes(): shape found does not "
919 "provide a subset for requested paragraph index" );
920 continue;
924 const uno::Sequence< beans::NamedValue >& rShapeProps( rProp.Properties );
925 for( const auto& rShapeProp : rShapeProps )
927 bool bVisible=false;
928 if( rShapeProp.Name.equalsIgnoreAsciiCase("visibility") &&
929 extractValue( bVisible,
930 rShapeProp.Value,
931 pShape,
932 basegfx::B2DVector(getSlideSize().getWidth(), getSlideSize().getHeight()) ))
934 pAttrShape->setVisibility( bVisible );
936 else
938 OSL_FAIL( "SlideImpl::applyInitialShapeAttributes(): Unexpected "
939 "(and unimplemented) property encountered" );
946 bool SlideImpl::applyInitialShapeAttributes(
947 const uno::Reference< animations::XAnimationNode >& xRootAnimationNode )
949 if( !implPrefetchShow() )
950 return false;
952 if( !xRootAnimationNode.is() )
954 meAnimationState = INITIAL_STATE;
956 return true; // no animations - no attributes to apply -
957 // succeeded
960 applyShapeAttributes(xRootAnimationNode, true);
962 meAnimationState = INITIAL_STATE;
964 return true;
967 bool SlideImpl::loadShapes()
969 if( mbShapesLoaded )
970 return true;
972 ENSURE_OR_RETURN_FALSE( mxDrawPage.is(),
973 "SlideImpl::loadShapes(): Invalid draw page" );
974 ENSURE_OR_RETURN_FALSE( mpLayerManager,
975 "SlideImpl::loadShapes(): Invalid layer manager" );
977 // fetch desired page content
978 // ==========================
980 // also take master page content
981 uno::Reference< drawing::XDrawPage > xMasterPage;
982 uno::Reference< drawing::XShapes > xMasterPageShapes;
983 sal_Int32 nCurrCount(0);
985 uno::Reference< drawing::XMasterPageTarget > xMasterPageTarget( mxDrawPage,
986 uno::UNO_QUERY );
987 if( xMasterPageTarget.is() )
989 xMasterPage = xMasterPageTarget->getMasterPage();
990 xMasterPageShapes = xMasterPage;
992 if( xMasterPage.is() && xMasterPageShapes.is() )
994 // TODO(P2): maybe cache master pages here (or treat the
995 // masterpage as a single metafile. At least currently,
996 // masterpages do not contain animation effects)
999 // load the masterpage shapes
1001 ShapeImporter aMPShapesFunctor( xMasterPage,
1002 mxDrawPage,
1003 mxDrawPagesSupplier,
1004 maContext,
1005 0, /* shape num starts at 0 */
1006 true );
1008 mpLayerManager->addShape(
1009 aMPShapesFunctor.importBackgroundShape() );
1011 while( !aMPShapesFunctor.isImportDone() )
1013 ShapeSharedPtr const pShape(
1014 aMPShapesFunctor.importShape() );
1015 if( pShape )
1017 pShape->setIsForeground(false);
1018 mpLayerManager->addShape( pShape );
1021 addPolygons(aMPShapesFunctor.getPolygons());
1023 nCurrCount = static_cast<sal_Int32>(aMPShapesFunctor.getImportedShapesCount());
1025 catch( uno::RuntimeException& )
1027 throw;
1029 catch( ShapeLoadFailedException& )
1031 // TODO(E2): Error handling. For now, bail out
1032 TOOLS_WARN_EXCEPTION( "slideshow", "SlideImpl::loadShapes(): caught ShapeLoadFailedException" );
1033 return false;
1036 catch( uno::Exception& )
1038 TOOLS_WARN_EXCEPTION( "slideshow", "" );
1039 return false;
1046 // load the normal page shapes
1049 ShapeImporter aShapesFunctor( mxDrawPage,
1050 mxDrawPage,
1051 mxDrawPagesSupplier,
1052 maContext,
1053 nCurrCount,
1054 false );
1056 while( !aShapesFunctor.isImportDone() )
1058 ShapeSharedPtr const pShape(
1059 aShapesFunctor.importShape() );
1060 if( pShape )
1061 mpLayerManager->addShape( pShape );
1063 addPolygons(aShapesFunctor.getPolygons());
1065 catch( uno::RuntimeException& )
1067 throw;
1069 catch( ShapeLoadFailedException& )
1071 // TODO(E2): Error handling. For now, bail out
1072 TOOLS_WARN_EXCEPTION( "slideshow", "SlideImpl::loadShapes(): caught ShapeLoadFailedException" );
1073 return false;
1075 catch( uno::Exception& )
1077 TOOLS_WARN_EXCEPTION( "slideshow", "" );
1078 return false;
1081 mbShapesLoaded = true;
1083 return true;
1086 basegfx::B2ISize SlideImpl::getSlideSizeImpl() const
1088 uno::Reference< beans::XPropertySet > xPropSet(
1089 mxDrawPage, uno::UNO_QUERY_THROW );
1091 sal_Int32 nDocWidth = 0;
1092 sal_Int32 nDocHeight = 0;
1093 xPropSet->getPropertyValue(u"Width"_ustr) >>= nDocWidth;
1094 xPropSet->getPropertyValue(u"Height"_ustr) >>= nDocHeight;
1096 return basegfx::B2ISize( nDocWidth, nDocHeight );
1099 } // anonymous namespace
1102 SlideSharedPtr createSlide( const uno::Reference< drawing::XDrawPage >& xDrawPage,
1103 const uno::Reference<drawing::XDrawPagesSupplier>& xDrawPages,
1104 const uno::Reference< animations::XAnimationNode >& xRootNode,
1105 EventQueue& rEventQueue,
1106 EventMultiplexer& rEventMultiplexer,
1107 ScreenUpdater& rScreenUpdater,
1108 ActivitiesQueue& rActivitiesQueue,
1109 UserEventQueue& rUserEventQueue,
1110 CursorManager& rCursorManager,
1111 MediaFileManager& rMediaFileManager,
1112 const UnoViewContainer& rViewContainer,
1113 const uno::Reference< uno::XComponentContext >& xComponentContext,
1114 const ShapeEventListenerMap& rShapeListenerMap,
1115 const ShapeCursorMap& rShapeCursorMap,
1116 PolyPolygonVector&& rPolyPolygonVector,
1117 RGBColor const& rUserPaintColor,
1118 double dUserPaintStrokeWidth,
1119 bool bUserPaintEnabled,
1120 bool bIntrinsicAnimationsAllowed,
1121 bool bDisableAnimationZOrder )
1123 auto pRet = std::make_shared<SlideImpl>( xDrawPage, xDrawPages, xRootNode, rEventQueue,
1124 rEventMultiplexer, rScreenUpdater,
1125 rActivitiesQueue, rUserEventQueue,
1126 rCursorManager, rMediaFileManager, rViewContainer,
1127 xComponentContext, rShapeListenerMap,
1128 rShapeCursorMap, std::move(rPolyPolygonVector), rUserPaintColor,
1129 dUserPaintStrokeWidth, bUserPaintEnabled,
1130 bIntrinsicAnimationsAllowed,
1131 bDisableAnimationZOrder );
1133 rEventMultiplexer.addViewHandler( pRet );
1135 return pRet;
1138 } // namespace slideshow
1140 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */