Bump version to 6.0-36
[LibreOffice.git] / slideshow / source / engine / slide / slideimpl.cxx
blobc81dfff0d10a1f9b4de485369286b7f1870b6e30
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 <tools/diagnose_ex.h>
23 #include <canvas/canvastools.hxx>
24 #include <cppcanvas/basegfxfactory.hxx>
26 #include <basegfx/matrix/b2dhommatrix.hxx>
27 #include <basegfx/point/b2dpoint.hxx>
28 #include <basegfx/polygon/b2dpolygon.hxx>
29 #include <basegfx/polygon/b2dpolygontools.hxx>
30 #include <basegfx/numeric/ftools.hxx>
32 #include <com/sun/star/awt/SystemPointer.hpp>
33 #include <com/sun/star/container/XIndexAccess.hpp>
34 #include <com/sun/star/drawing/XMasterPageTarget.hpp>
35 #include <com/sun/star/beans/XPropertySet.hpp>
36 #include <com/sun/star/container/XEnumerationAccess.hpp>
37 #include <com/sun/star/awt/Rectangle.hpp>
38 #include <com/sun/star/presentation/ParagraphTarget.hpp>
39 #include <com/sun/star/presentation/EffectNodeType.hpp>
40 #include <com/sun/star/drawing/TextAnimationKind.hpp>
42 #include <cppuhelper/exc_hlp.hxx>
43 #include <comphelper/anytostring.hxx>
45 #include <slide.hxx>
46 #include <slideshowcontext.hxx>
47 #include "slideanimations.hxx"
48 #include <doctreenode.hxx>
49 #include <screenupdater.hxx>
50 #include <cursormanager.hxx>
51 #include <shapeimporter.hxx>
52 #include <slideshowexceptions.hxx>
53 #include <eventqueue.hxx>
54 #include <activitiesqueue.hxx>
55 #include "layermanager.hxx"
56 #include "shapemanagerimpl.hxx"
57 #include <usereventqueue.hxx>
58 #include "userpaintoverlay.hxx"
59 #include <event.hxx>
60 #include "targetpropertiescreator.hxx"
61 #include <tools.hxx>
63 #include <iterator>
64 #include <functional>
65 #include <iostream>
67 using namespace ::com::sun::star;
70 namespace slideshow
72 namespace internal
74 namespace
77 class SlideImpl : public Slide,
78 public CursorManager,
79 public ViewEventHandler,
80 public ::osl::DebugBase<SlideImpl>
82 public:
83 SlideImpl( const uno::Reference<drawing::XDrawPage>& xDrawPage,
84 const uno::Reference<drawing::XDrawPagesSupplier>& xDrawPages,
85 const uno::Reference<animations::XAnimationNode>& xRootNode,
86 EventQueue& rEventQueue,
87 EventMultiplexer& rEventMultiplexer,
88 ScreenUpdater& rScreenUpdater,
89 ActivitiesQueue& rActivitiesQueue,
90 UserEventQueue& rUserEventQueue,
91 CursorManager& rCursorManager,
92 const UnoViewContainer& rViewContainer,
93 const uno::Reference<uno::XComponentContext>& xContext,
94 const ShapeEventListenerMap& rShapeListenerMap,
95 const ShapeCursorMap& rShapeCursorMap,
96 const PolyPolygonVector& rPolyPolygonVector,
97 RGBColor const& rUserPaintColor,
98 double dUserPaintStrokeWidth,
99 bool bUserPaintEnabled,
100 bool bIntrinsicAnimationsAllowed,
101 bool bDisableAnimationZOrder );
103 virtual ~SlideImpl() override;
106 // Slide interface
109 virtual void prefetch() override;
110 virtual void show( bool ) override;
111 virtual void hide() override;
113 virtual basegfx::B2ISize getSlideSize() const override;
114 virtual uno::Reference<drawing::XDrawPage > getXDrawPage() const override;
115 virtual uno::Reference<animations::XAnimationNode> getXAnimationNode() const override;
116 virtual PolyPolygonVector getPolygons() override;
117 virtual void drawPolygons() const override;
118 virtual bool isPaintOverlayActive() const override;
119 virtual void enablePaintOverlay() override;
120 virtual void disablePaintOverlay() override;
121 virtual void update_settings( bool bUserPaintEnabled, RGBColor const& aUserPaintColor, double dUserPaintStrokeWidth ) override;
124 // TODO(F2): Rework SlideBitmap to no longer be based on XBitmap,
125 // but on canvas-independent basegfx bitmaps
126 virtual SlideBitmapSharedPtr getCurrentSlideBitmap( const UnoViewSharedPtr& rView ) const override;
129 private:
130 // ViewEventHandler
131 virtual void viewAdded( const UnoViewSharedPtr& rView ) override;
132 virtual void viewRemoved( const UnoViewSharedPtr& rView ) override;
133 virtual void viewChanged( const UnoViewSharedPtr& rView ) override;
134 virtual void viewsChanged() override;
136 // CursorManager
137 virtual bool requestCursor( sal_Int16 nCursorShape ) override;
138 virtual void resetCursor() override;
140 void activatePaintOverlay();
141 void deactivatePaintOverlay();
143 /** Query whether the slide has animations at all
145 If the slide doesn't have animations, show() displays
146 only static content. If an event is registered with
147 registerSlideEndEvent(), this event will be
148 immediately activated at the end of the show() method.
150 @return true, if this slide has animations, false
151 otherwise
153 bool isAnimated();
155 /// Set all Shapes to their initial attributes for slideshow
156 bool applyInitialShapeAttributes( const css::uno::Reference< css::animations::XAnimationNode >& xRootAnimationNode );
158 /// Set shapes to attributes corresponding to initial or final state of slide
159 void applyShapeAttributes(
160 const css::uno::Reference< css::animations::XAnimationNode >& xRootAnimationNode,
161 bool bInitial) const;
163 /// Renders current slide content to bitmap
164 SlideBitmapSharedPtr createCurrentSlideBitmap(
165 const UnoViewSharedPtr& rView,
166 ::basegfx::B2ISize const & rSlideSize ) const;
168 /// Prefetch all shapes (not the animations)
169 bool loadShapes();
171 /// Retrieve slide size from XDrawPage
172 basegfx::B2ISize getSlideSizeImpl() const;
174 /// Prefetch show, but don't call applyInitialShapeAttributes()
175 bool implPrefetchShow();
177 /// Add Polygons to the member maPolygons
178 void addPolygons(const PolyPolygonVector& rPolygons);
180 // Types
181 // =====
183 enum SlideAnimationState
185 CONSTRUCTING_STATE=0,
186 INITIAL_STATE=1,
187 SHOWING_STATE=2,
188 FINAL_STATE=3,
189 SlideAnimationState_NUM_ENTRIES=4
192 typedef std::vector< SlideBitmapSharedPtr > VectorOfSlideBitmaps;
193 /** Vector of slide bitmaps.
195 Since the bitmap content is sensitive to animation
196 effects, we have an inner vector containing a distinct
197 bitmap for each of the SlideAnimationStates.
199 typedef ::std::vector< std::pair< UnoViewSharedPtr,
200 VectorOfSlideBitmaps > > VectorOfVectorOfSlideBitmaps;
203 // Member variables
204 // ================
206 /// The page model object
207 uno::Reference< drawing::XDrawPage > mxDrawPage;
208 uno::Reference< drawing::XDrawPagesSupplier > mxDrawPagesSupplier;
209 uno::Reference< animations::XAnimationNode > mxRootNode;
211 LayerManagerSharedPtr mpLayerManager;
212 std::shared_ptr<ShapeManagerImpl> mpShapeManager;
213 std::shared_ptr<SubsettableShapeManager> mpSubsettableShapeManager;
215 /// Contains common objects needed throughout the slideshow
216 SlideShowContext maContext;
218 /// parent cursor manager
219 CursorManager& mrCursorManager;
221 /// Handles the animation and event generation for us
222 SlideAnimations maAnimations;
223 PolyPolygonVector maPolygons;
225 RGBColor maUserPaintColor;
226 double mdUserPaintStrokeWidth;
227 UserPaintOverlaySharedPtr mpPaintOverlay;
229 /// Bitmaps with slide content at various states
230 mutable VectorOfVectorOfSlideBitmaps maSlideBitmaps;
232 SlideAnimationState meAnimationState;
234 const basegfx::B2ISize maSlideSize;
236 sal_Int16 mnCurrentCursor;
238 /// True, when intrinsic shape animations are allowed
239 bool mbIntrinsicAnimationsAllowed;
241 /// True, when user paint overlay is enabled
242 bool mbUserPaintOverlayEnabled;
244 /// True, if initial load of all page shapes succeeded
245 bool mbShapesLoaded;
247 /// True, if initial load of all animation info succeeded
248 bool mbShowLoaded;
250 /** True, if this slide is not static.
252 If this slide has animated content, this variable will
253 be true, and false otherwise.
255 bool mbHaveAnimations;
257 /** True, if this slide has a main animation sequence.
259 If this slide has animation content, which in turn has
260 a main animation sequence (which must be fully run
261 before EventMultiplexer::notifySlideAnimationsEnd() is
262 called), this member is true.
264 bool mbMainSequenceFound;
266 /// When true, show() was called. Slide hidden otherwise.
267 bool mbActive;
269 /// When true, enablePaintOverlay was called and mbUserPaintOverlay = true
270 bool mbPaintOverlayActive;
272 /// When true, final state attributes are already applied to shapes
273 bool mbFinalStateApplied;
277 void slideRenderer( SlideImpl const * pSlide, const UnoViewSharedPtr& rView )
279 // fully clear view content to background color
280 rView->clearAll();
282 SlideBitmapSharedPtr pBitmap( pSlide->getCurrentSlideBitmap( rView ) );
283 ::cppcanvas::CanvasSharedPtr pCanvas( rView->getCanvas() );
285 const ::basegfx::B2DHomMatrix aViewTransform( rView->getTransformation() );
286 const ::basegfx::B2DPoint aOutPosPixel( aViewTransform * ::basegfx::B2DPoint() );
288 // setup a canvas with device coordinate space, the slide
289 // bitmap already has the correct dimension.
290 ::cppcanvas::CanvasSharedPtr pDevicePixelCanvas( pCanvas->clone() );
291 pDevicePixelCanvas->setTransformation( ::basegfx::B2DHomMatrix() );
293 // render at given output position
294 pBitmap->move( aOutPosPixel );
296 // clear clip (might have been changed, e.g. from comb
297 // transition)
298 pBitmap->clip( ::basegfx::B2DPolyPolygon() );
299 pBitmap->draw( pDevicePixelCanvas );
303 SlideImpl::SlideImpl( const uno::Reference< drawing::XDrawPage >& xDrawPage,
304 const uno::Reference<drawing::XDrawPagesSupplier>& xDrawPages,
305 const uno::Reference< animations::XAnimationNode >& xRootNode,
306 EventQueue& rEventQueue,
307 EventMultiplexer& rEventMultiplexer,
308 ScreenUpdater& rScreenUpdater,
309 ActivitiesQueue& rActivitiesQueue,
310 UserEventQueue& rUserEventQueue,
311 CursorManager& rCursorManager,
312 const UnoViewContainer& rViewContainer,
313 const uno::Reference< uno::XComponentContext >& xComponentContext,
314 const ShapeEventListenerMap& rShapeListenerMap,
315 const ShapeCursorMap& rShapeCursorMap,
316 const PolyPolygonVector& rPolyPolygonVector,
317 RGBColor const& aUserPaintColor,
318 double dUserPaintStrokeWidth,
319 bool bUserPaintEnabled,
320 bool bIntrinsicAnimationsAllowed,
321 bool bDisableAnimationZOrder ) :
322 mxDrawPage( xDrawPage ),
323 mxDrawPagesSupplier( xDrawPages ),
324 mxRootNode( xRootNode ),
325 mpLayerManager( new LayerManager(
326 rViewContainer,
327 bDisableAnimationZOrder) ),
328 mpShapeManager( new ShapeManagerImpl(
329 rEventMultiplexer,
330 mpLayerManager,
331 rCursorManager,
332 rShapeListenerMap,
333 rShapeCursorMap)),
334 mpSubsettableShapeManager( mpShapeManager ),
335 maContext( mpSubsettableShapeManager,
336 rEventQueue,
337 rEventMultiplexer,
338 rScreenUpdater,
339 rActivitiesQueue,
340 rUserEventQueue,
341 *this,
342 rViewContainer,
343 xComponentContext ),
344 mrCursorManager( rCursorManager ),
345 maAnimations( maContext,
346 basegfx::B2DSize( getSlideSizeImpl() ) ),
347 maPolygons(rPolyPolygonVector),
348 maUserPaintColor(aUserPaintColor),
349 mdUserPaintStrokeWidth(dUserPaintStrokeWidth),
350 mpPaintOverlay(),
351 maSlideBitmaps(),
352 meAnimationState( CONSTRUCTING_STATE ),
353 maSlideSize(getSlideSizeImpl()),
354 mnCurrentCursor( awt::SystemPointer::ARROW ),
355 mbIntrinsicAnimationsAllowed( bIntrinsicAnimationsAllowed ),
356 mbUserPaintOverlayEnabled(bUserPaintEnabled),
357 mbShapesLoaded( false ),
358 mbShowLoaded( false ),
359 mbHaveAnimations( false ),
360 mbMainSequenceFound( false ),
361 mbActive( false ),
362 mbPaintOverlayActive( false ),
363 mbFinalStateApplied( false )
365 // clone already existing views for slide bitmaps
366 for( const auto& rView : rViewContainer )
367 viewAdded( rView );
369 // register screen update (LayerManager needs to signal pending
370 // updates)
371 maContext.mrScreenUpdater.addViewUpdate(mpShapeManager);
374 void SlideImpl::update_settings( bool bUserPaintEnabled, RGBColor const& aUserPaintColor, double dUserPaintStrokeWidth )
376 maUserPaintColor = aUserPaintColor;
377 mdUserPaintStrokeWidth = dUserPaintStrokeWidth;
378 mbUserPaintOverlayEnabled = bUserPaintEnabled;
381 SlideImpl::~SlideImpl()
383 if( mpShapeManager )
385 maContext.mrScreenUpdater.removeViewUpdate(mpShapeManager);
386 mpShapeManager->dispose();
388 // TODO(Q3): Make sure LayerManager (and thus Shapes) dies
389 // first, because SlideShowContext has SubsettableShapeManager
390 // as reference member.
391 mpLayerManager.reset();
395 void SlideImpl::prefetch()
397 if( !mxRootNode.is() )
398 return;
400 applyInitialShapeAttributes(mxRootNode);
403 void SlideImpl::show( bool bSlideBackgoundPainted )
405 if( mbActive )
406 return; // already active
408 if( !mpShapeManager || !mpLayerManager )
409 return; // disposed
411 // set initial shape attributes (e.g. hide shapes that have
412 // 'appear' effect set)
413 if( !applyInitialShapeAttributes(mxRootNode) )
414 return;
416 // activate and take over view - clears view, if necessary
417 mbActive = true;
418 requestCursor( mnCurrentCursor );
420 // enable shape management & event broadcasting for shapes of this
421 // slide. Also enables LayerManager to record updates. Currently,
422 // never let LayerManager render initial slide content, use
423 // buffered slide bitmaps instead.
424 mpShapeManager->activate();
427 // render slide to screen, if requested
428 if( !bSlideBackgoundPainted )
430 for( const auto& rContext : maContext.mrViewContainer )
431 slideRenderer( this, rContext );
433 maContext.mrScreenUpdater.notifyUpdate();
437 // fire up animations
438 const bool bIsAnimated( isAnimated() );
439 if( bIsAnimated )
440 maAnimations.start(); // feeds initial events into queue
442 // NOTE: this looks slightly weird, but is indeed correct:
443 // as isAnimated() might return false, _although_ there is
444 // a main sequence (because the animation nodes don't
445 // contain any executable effects), we gotta check both
446 // conditions here.
447 if( !bIsAnimated || !mbMainSequenceFound )
449 // manually trigger a slide animation end event (we don't have
450 // animations at all, or we don't have a main animation
451 // sequence, but if we had, it'd end now). Note that having
452 // animations alone does not matter here, as only main
453 // sequence animations prevents showing the next slide on
454 // nextEvent().
455 maContext.mrEventMultiplexer.notifySlideAnimationsEnd();
458 // enable shape-intrinsic animations (drawing layer animations or
459 // GIF animations)
460 if( mbIntrinsicAnimationsAllowed )
461 mpSubsettableShapeManager->notifyIntrinsicAnimationsEnabled();
463 // enable paint overlay, if maUserPaintColor is valid
464 activatePaintOverlay();
467 // from now on, animations might be showing
468 meAnimationState = SHOWING_STATE;
471 void SlideImpl::hide()
473 if( !mbActive || !mpShapeManager )
474 return; // already hidden/disposed
477 // from now on, all animations are stopped
478 meAnimationState = FINAL_STATE;
481 // disable user paint overlay under all circumstances,
482 // this slide now ceases to be active.
483 deactivatePaintOverlay();
486 // switch off all shape-intrinsic animations.
487 mpSubsettableShapeManager->notifyIntrinsicAnimationsDisabled();
489 // force-end all SMIL animations, too
490 maAnimations.end();
493 // disable shape management & event broadcasting for shapes of this
494 // slide. Also disables LayerManager.
495 mpShapeManager->deactivate();
497 // vanish from view
498 resetCursor();
499 mbActive = false;
502 basegfx::B2ISize SlideImpl::getSlideSize() const
504 return maSlideSize;
507 uno::Reference<drawing::XDrawPage > SlideImpl::getXDrawPage() const
509 return mxDrawPage;
512 uno::Reference<animations::XAnimationNode> SlideImpl::getXAnimationNode() const
514 return mxRootNode;
517 PolyPolygonVector SlideImpl::getPolygons()
519 if(mbPaintOverlayActive)
520 maPolygons = mpPaintOverlay->getPolygons();
521 return maPolygons;
524 SlideBitmapSharedPtr SlideImpl::getCurrentSlideBitmap( const UnoViewSharedPtr& rView ) const
526 // search corresponding entry in maSlideBitmaps (which
527 // contains the views as the key)
528 VectorOfVectorOfSlideBitmaps::iterator aIter;
529 const VectorOfVectorOfSlideBitmaps::iterator aEnd( maSlideBitmaps.end() );
530 if( (aIter=std::find_if( maSlideBitmaps.begin(),
531 aEnd,
532 [&rView]
533 ( const VectorOfVectorOfSlideBitmaps::value_type& cp )
534 { return rView == cp.first; } ) ) == aEnd )
536 // corresponding view not found - maybe view was not
537 // added to Slide?
538 ENSURE_OR_THROW( false,
539 "SlideImpl::getInitialSlideBitmap(): view does not "
540 "match any of the added ones" );
543 // ensure that the show is loaded
544 if( !mbShowLoaded )
546 // only prefetch and init shapes when not done already
547 // (otherwise, at least applyInitialShapeAttributes() will be
548 // called twice for initial slide rendering). Furthermore,
549 // applyInitialShapeAttributes() _always_ performs
550 // initializations, which would be highly unwanted during a
551 // running show. OTOH, a slide whose mbShowLoaded is false is
552 // guaranteed not be running a show.
554 // set initial shape attributes (e.g. hide 'appear' effect
555 // shapes)
556 if( !const_cast<SlideImpl*>(this)->applyInitialShapeAttributes( mxRootNode ) )
557 ENSURE_OR_THROW(false,
558 "SlideImpl::getCurrentSlideBitmap(): Cannot "
559 "apply initial attributes");
562 SlideBitmapSharedPtr& rBitmap( aIter->second.at( meAnimationState ));
563 const ::basegfx::B2ISize& rSlideSize(
564 getSlideSizePixel( ::basegfx::B2DSize( getSlideSize() ),
565 rView ));
567 // is the bitmap valid (actually existent, and of correct
568 // size)?
569 if( !rBitmap || rBitmap->getSize() != rSlideSize )
571 // no bitmap there yet, or wrong size - create one
572 rBitmap = createCurrentSlideBitmap(rView, rSlideSize);
575 return rBitmap;
579 // private methods
582 void SlideImpl::viewAdded( const UnoViewSharedPtr& rView )
584 maSlideBitmaps.emplace_back( rView,
585 VectorOfSlideBitmaps(SlideAnimationState_NUM_ENTRIES) );
587 if( mpLayerManager )
588 mpLayerManager->viewAdded( rView );
591 void SlideImpl::viewRemoved( const UnoViewSharedPtr& rView )
593 if( mpLayerManager )
594 mpLayerManager->viewRemoved( rView );
596 const VectorOfVectorOfSlideBitmaps::iterator aEnd( maSlideBitmaps.end() );
597 maSlideBitmaps.erase(
598 std::remove_if( maSlideBitmaps.begin(),
599 aEnd,
600 [&rView]
601 ( const VectorOfVectorOfSlideBitmaps::value_type& cp )
602 { return rView == cp.first; } ),
603 aEnd );
606 void SlideImpl::viewChanged( const UnoViewSharedPtr& rView )
608 // nothing to do for the Slide - getCurrentSlideBitmap() lazily
609 // handles bitmap resizes
610 if( mbActive && mpLayerManager )
611 mpLayerManager->viewChanged(rView);
614 void SlideImpl::viewsChanged()
616 // nothing to do for the Slide - getCurrentSlideBitmap() lazily
617 // handles bitmap resizes
618 if( mbActive && mpLayerManager )
619 mpLayerManager->viewsChanged();
622 bool SlideImpl::requestCursor( sal_Int16 nCursorShape )
624 mnCurrentCursor = nCursorShape;
625 return mrCursorManager.requestCursor(mnCurrentCursor);
628 void SlideImpl::resetCursor()
630 mnCurrentCursor = awt::SystemPointer::ARROW;
631 mrCursorManager.resetCursor();
634 bool SlideImpl::isAnimated()
636 // prefetch, but don't apply initial shape attributes
637 if( !implPrefetchShow() )
638 return false;
640 return mbHaveAnimations && maAnimations.isAnimated();
643 SlideBitmapSharedPtr SlideImpl::createCurrentSlideBitmap( const UnoViewSharedPtr& rView,
644 const ::basegfx::B2ISize& rBmpSize ) const
646 ENSURE_OR_THROW( rView && rView->getCanvas(),
647 "SlideImpl::createCurrentSlideBitmap(): Invalid view" );
648 ENSURE_OR_THROW( mpLayerManager,
649 "SlideImpl::createCurrentSlideBitmap(): Invalid layer manager" );
650 ENSURE_OR_THROW( mbShowLoaded,
651 "SlideImpl::createCurrentSlideBitmap(): No show loaded" );
653 // tdf#96083 ensure end state settings are applied to shapes once when bitmap gets re-rendered
654 // in that state
655 if(!mbFinalStateApplied && FINAL_STATE == meAnimationState && mxRootNode.is())
657 const_cast< SlideImpl* >(this)->mbFinalStateApplied = true;
658 applyShapeAttributes(mxRootNode, false);
661 ::cppcanvas::CanvasSharedPtr pCanvas( rView->getCanvas() );
663 // create a bitmap of appropriate size
664 ::cppcanvas::BitmapSharedPtr pBitmap(
665 ::cppcanvas::BaseGfxFactory::createBitmap(
666 pCanvas,
667 rBmpSize ) );
669 ENSURE_OR_THROW( pBitmap,
670 "SlideImpl::createCurrentSlideBitmap(): Cannot create page bitmap" );
672 ::cppcanvas::BitmapCanvasSharedPtr pBitmapCanvas( pBitmap->getBitmapCanvas() );
674 ENSURE_OR_THROW( pBitmapCanvas,
675 "SlideImpl::createCurrentSlideBitmap(): Cannot create page bitmap canvas" );
677 // apply linear part of destination canvas transformation (linear means in this context:
678 // transformation without any translational components)
679 ::basegfx::B2DHomMatrix aLinearTransform( rView->getTransformation() );
680 aLinearTransform.set( 0, 2, 0.0 );
681 aLinearTransform.set( 1, 2, 0.0 );
682 pBitmapCanvas->setTransformation( aLinearTransform );
684 // output all shapes to bitmap
685 initSlideBackground( pBitmapCanvas, rBmpSize );
686 mpLayerManager->renderTo( pBitmapCanvas );
688 return std::make_shared<SlideBitmap>( pBitmap );
691 namespace
693 class MainSequenceSearcher
695 public:
696 MainSequenceSearcher()
698 maSearchKey.Name = "node-type";
699 maSearchKey.Value <<= presentation::EffectNodeType::MAIN_SEQUENCE;
702 void operator()( const uno::Reference< animations::XAnimationNode >& xChildNode )
704 uno::Sequence< beans::NamedValue > aUserData( xChildNode->getUserData() );
706 if( findNamedValue( aUserData, maSearchKey ) )
708 maMainSequence = xChildNode;
712 const uno::Reference< animations::XAnimationNode >& getMainSequence() const
714 return maMainSequence;
717 private:
718 beans::NamedValue maSearchKey;
719 uno::Reference< animations::XAnimationNode > maMainSequence;
723 bool SlideImpl::implPrefetchShow()
725 if( mbShowLoaded )
726 return true;
728 ENSURE_OR_RETURN_FALSE( mxDrawPage.is(),
729 "SlideImpl::implPrefetchShow(): Invalid draw page" );
730 ENSURE_OR_RETURN_FALSE( mpLayerManager,
731 "SlideImpl::implPrefetchShow(): Invalid layer manager" );
733 // fetch desired page content
734 // ==========================
736 if( !loadShapes() )
737 return false;
739 // New animations framework: import the shape effect info
740 // ======================================================
744 if( mxRootNode.is() )
746 if( !maAnimations.importAnimations( mxRootNode ) )
748 OSL_FAIL( "SlideImpl::implPrefetchShow(): have animation nodes, "
749 "but import animations failed." );
751 // could not import animation framework,
752 // _although_ some animation nodes are there -
753 // this is an error (not finding animations at
754 // all is okay - might be a static slide)
755 return false;
758 // now check whether we've got a main sequence (if
759 // not, we must manually call
760 // EventMultiplexer::notifySlideAnimationsEnd()
761 // above, as e.g. interactive sequences alone
762 // don't block nextEvent() from issuing the next
763 // slide)
764 MainSequenceSearcher aSearcher;
765 if( for_each_childNode( mxRootNode, aSearcher ) )
766 mbMainSequenceFound = aSearcher.getMainSequence().is();
768 // import successfully done
769 mbHaveAnimations = true;
772 catch( uno::RuntimeException& )
774 throw;
776 catch( uno::Exception& )
778 SAL_WARN( "slideshow", comphelper::anyToString(cppu::getCaughtException()) );
779 // TODO(E2): Error handling. For now, bail out
782 mbShowLoaded = true;
784 return true;
787 void SlideImpl::enablePaintOverlay()
789 if( !mbUserPaintOverlayEnabled || !mbPaintOverlayActive )
791 mbUserPaintOverlayEnabled = true;
792 activatePaintOverlay();
796 void SlideImpl::disablePaintOverlay()
800 void SlideImpl::activatePaintOverlay()
802 if( mbUserPaintOverlayEnabled || !maPolygons.empty() )
804 mpPaintOverlay = UserPaintOverlay::create( maUserPaintColor,
805 mdUserPaintStrokeWidth,
806 maContext,
807 maPolygons,
808 mbUserPaintOverlayEnabled );
809 mbPaintOverlayActive = true;
813 void SlideImpl::drawPolygons() const
815 if( mpPaintOverlay )
816 mpPaintOverlay->drawPolygons();
819 void SlideImpl::addPolygons(const PolyPolygonVector& rPolygons)
821 if(!rPolygons.empty())
823 for( PolyPolygonVector::const_iterator aIter = rPolygons.begin(),
824 aEnd = rPolygons.end();
825 aIter!=aEnd;
826 ++aIter )
828 maPolygons.push_back(*aIter);
833 bool SlideImpl::isPaintOverlayActive() const
835 return mbPaintOverlayActive;
838 void SlideImpl::deactivatePaintOverlay()
840 if(mbPaintOverlayActive)
841 maPolygons = mpPaintOverlay->getPolygons();
843 mpPaintOverlay.reset();
844 mbPaintOverlayActive = false;
847 void SlideImpl::applyShapeAttributes(
848 const css::uno::Reference< css::animations::XAnimationNode >& xRootAnimationNode,
849 bool bInitial) const
851 uno::Sequence< animations::TargetProperties > aProps(
852 TargetPropertiesCreator::createTargetProperties( xRootAnimationNode, bInitial ) );
854 // apply extracted values to our shapes
855 const ::std::size_t nSize( aProps.getLength() );
856 for( ::std::size_t i=0; i<nSize; ++i )
858 sal_Int16 nParaIndex( -1 );
859 uno::Reference< drawing::XShape > xShape( aProps[i].Target,
860 uno::UNO_QUERY );
862 if( !xShape.is() )
864 // not a shape target. Maybe a ParagraphTarget?
865 presentation::ParagraphTarget aParaTarget;
867 if( aProps[i].Target >>= aParaTarget )
869 // yep, ParagraphTarget found - extract shape
870 // and index
871 xShape = aParaTarget.Shape;
872 nParaIndex = aParaTarget.Paragraph;
876 if( xShape.is() )
878 ShapeSharedPtr pShape( mpLayerManager->lookupShape( xShape ) );
880 if( !pShape )
882 OSL_FAIL( "SlideImpl::applyInitialShapeAttributes(): no shape found for given target" );
883 continue;
886 AttributableShapeSharedPtr pAttrShape(
887 ::std::dynamic_pointer_cast< AttributableShape >( pShape ) );
889 if( !pAttrShape )
891 OSL_FAIL( "SlideImpl::applyInitialShapeAttributes(): shape found does not "
892 "implement AttributableShape interface" );
893 continue;
896 if( nParaIndex != -1 )
898 // our target is a paragraph subset, thus look
899 // this up first.
900 const DocTreeNodeSupplier& rNodeSupplier( pAttrShape->getTreeNodeSupplier() );
902 if( rNodeSupplier.getNumberOfTreeNodes(
903 DocTreeNode::NodeType::LogicalParagraph ) <= nParaIndex )
905 OSL_FAIL( "SlideImpl::applyInitialShapeAttributes(): shape found does not "
906 "provide a subset for requested paragraph index" );
907 continue;
910 pAttrShape = pAttrShape->getSubset(
911 rNodeSupplier.getTreeNode(
912 nParaIndex,
913 DocTreeNode::NodeType::LogicalParagraph ) );
915 if( !pAttrShape )
917 OSL_FAIL( "SlideImpl::applyInitialShapeAttributes(): shape found does not "
918 "provide a subset for requested paragraph index" );
919 continue;
923 const uno::Sequence< beans::NamedValue >& rShapeProps( aProps[i].Properties );
924 const ::std::size_t nShapePropSize( rShapeProps.getLength() );
925 for( ::std::size_t j=0; j<nShapePropSize; ++j )
927 bool bVisible=false;
928 if( rShapeProps[j].Name.equalsIgnoreAsciiCase("visibility") &&
929 extractValue( bVisible,
930 rShapeProps[j].Value,
931 pShape,
932 ::basegfx::B2DSize( getSlideSize() ) ))
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.set( xMasterPage,
991 uno::UNO_QUERY );
993 if( xMasterPage.is() && xMasterPageShapes.is() )
995 // TODO(P2): maybe cache master pages here (or treat the
996 // masterpage as a single metafile. At least currently,
997 // masterpages do not contain animation effects)
1000 // load the masterpage shapes
1002 ShapeImporter aMPShapesFunctor( xMasterPage,
1003 mxDrawPage,
1004 mxDrawPagesSupplier,
1005 maContext,
1006 0, /* shape num starts at 0 */
1007 true );
1009 mpLayerManager->addShape(
1010 aMPShapesFunctor.importBackgroundShape() );
1012 while( !aMPShapesFunctor.isImportDone() )
1014 ShapeSharedPtr const& rShape(
1015 aMPShapesFunctor.importShape() );
1016 if( rShape )
1017 mpLayerManager->addShape( rShape );
1019 addPolygons(aMPShapesFunctor.getPolygons());
1021 nCurrCount = static_cast<sal_Int32>(aMPShapesFunctor.getImportedShapesCount());
1023 catch( uno::RuntimeException& )
1025 throw;
1027 catch( ShapeLoadFailedException& )
1029 // TODO(E2): Error handling. For now, bail out
1030 OSL_FAIL( "SlideImpl::loadShapes(): caught ShapeLoadFailedException" );
1031 return false;
1034 catch( uno::Exception& )
1036 SAL_WARN( "slideshow", comphelper::anyToString( cppu::getCaughtException() ) );
1037 return false;
1044 // load the normal page shapes
1047 ShapeImporter aShapesFunctor( mxDrawPage,
1048 mxDrawPage,
1049 mxDrawPagesSupplier,
1050 maContext,
1051 nCurrCount,
1052 false );
1054 while( !aShapesFunctor.isImportDone() )
1056 ShapeSharedPtr const& rShape(
1057 aShapesFunctor.importShape() );
1058 if( rShape )
1059 mpLayerManager->addShape( rShape );
1061 addPolygons(aShapesFunctor.getPolygons());
1063 catch( uno::RuntimeException& )
1065 throw;
1067 catch( ShapeLoadFailedException& )
1069 // TODO(E2): Error handling. For now, bail out
1070 OSL_FAIL( "SlideImpl::loadShapes(): caught ShapeLoadFailedException" );
1071 return false;
1073 catch( uno::Exception& )
1075 SAL_WARN( "slideshow", comphelper::anyToString( cppu::getCaughtException() ) );
1076 return false;
1079 mbShapesLoaded = true;
1081 return true;
1084 basegfx::B2ISize SlideImpl::getSlideSizeImpl() const
1086 uno::Reference< beans::XPropertySet > xPropSet(
1087 mxDrawPage, uno::UNO_QUERY_THROW );
1089 sal_Int32 nDocWidth = 0;
1090 sal_Int32 nDocHeight = 0;
1091 xPropSet->getPropertyValue("Width") >>= nDocWidth;
1092 xPropSet->getPropertyValue("Height") >>= nDocHeight;
1094 return basegfx::B2ISize( nDocWidth, nDocHeight );
1097 } // namespace
1100 SlideSharedPtr createSlide( const uno::Reference< drawing::XDrawPage >& xDrawPage,
1101 const uno::Reference<drawing::XDrawPagesSupplier>& xDrawPages,
1102 const uno::Reference< animations::XAnimationNode >& xRootNode,
1103 EventQueue& rEventQueue,
1104 EventMultiplexer& rEventMultiplexer,
1105 ScreenUpdater& rScreenUpdater,
1106 ActivitiesQueue& rActivitiesQueue,
1107 UserEventQueue& rUserEventQueue,
1108 CursorManager& rCursorManager,
1109 const UnoViewContainer& rViewContainer,
1110 const uno::Reference< uno::XComponentContext >& xComponentContext,
1111 const ShapeEventListenerMap& rShapeListenerMap,
1112 const ShapeCursorMap& rShapeCursorMap,
1113 const PolyPolygonVector& rPolyPolygonVector,
1114 RGBColor const& rUserPaintColor,
1115 double dUserPaintStrokeWidth,
1116 bool bUserPaintEnabled,
1117 bool bIntrinsicAnimationsAllowed,
1118 bool bDisableAnimationZOrder )
1120 std::shared_ptr<SlideImpl> pRet( new SlideImpl( xDrawPage, xDrawPages, xRootNode, rEventQueue,
1121 rEventMultiplexer, rScreenUpdater,
1122 rActivitiesQueue, rUserEventQueue,
1123 rCursorManager, rViewContainer,
1124 xComponentContext, rShapeListenerMap,
1125 rShapeCursorMap, rPolyPolygonVector, rUserPaintColor,
1126 dUserPaintStrokeWidth, bUserPaintEnabled,
1127 bIntrinsicAnimationsAllowed,
1128 bDisableAnimationZOrder ));
1130 rEventMultiplexer.addViewHandler( pRet );
1132 return pRet;
1135 } // namespace internal
1136 } // namespace slideshow
1138 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */