1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <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>
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"
54 #include <tools/helpers.hxx>
55 #include <tools/json_writer.hxx>
56 #include <box2dtools.hxx>
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
70 class SlideImpl
: public Slide
,
72 public ViewEventHandler
,
73 public ::osl::DebugBase
<SlideImpl
>
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
;
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
;
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
;
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
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)
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
);
175 enum SlideAnimationState
177 CONSTRUCTING_STATE
=0,
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
;
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
240 /// True, if initial load of all animation info succeeded
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.
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
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
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
>(
321 bDisableAnimationZOrder
) ),
322 mpShapeManager( std::make_shared
<ShapeManagerImpl
>(
329 mpSubsettableShapeManager( mpShapeManager
),
330 mpBox2DWorld( std::make_shared
<box2d::utils::box2DWorld
>(
331 basegfx::B2DVector(getSlideSizeImpl().getWidth(), getSlideSizeImpl().getHeight()) ) ),
332 maContext( mpSubsettableShapeManager
,
343 mrCursorManager( rCursorManager
),
344 maAnimations( maContext
,
345 basegfx::B2DVector(getSlideSizeImpl().getWidth(), getSlideSizeImpl().getHeight()) ),
346 maPolygons(std::move(rPolyPolygonVector
)),
347 maUserPaintColor(aUserPaintColor
),
348 mdUserPaintStrokeWidth(dUserPaintStrokeWidth
),
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 ),
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
)
376 // register screen update (LayerManager needs to signal pending
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()
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() )
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
);
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
)
429 return; // already active
431 if( !mpShapeManager
|| !mpLayerManager
)
434 // set initial shape attributes (e.g. hide shapes that have
435 // 'appear' effect set)
436 if( !applyInitialShapeAttributes(mxRootNode
) )
439 // activate and take over view - clears view, if necessary
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() );
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
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
478 maContext
.mrEventMultiplexer
.notifySlideAnimationsEnd();
481 // enable shape-intrinsic animations (drawing layer animations or
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
516 // disable shape management & event broadcasting for shapes of this
517 // slide. Also disables LayerManager.
518 mpShapeManager
->deactivate();
525 basegfx::B2ISize
SlideImpl::getSlideSize() const
530 uno::Reference
<drawing::XDrawPage
> SlideImpl::getXDrawPage() const
535 uno::Reference
<animations::XAnimationNode
> SlideImpl::getXAnimationNode() const
540 PolyPolygonVector
SlideImpl::getPolygons()
542 if(mbPaintOverlayActive
)
543 maPolygons
= mpPaintOverlay
->getPolygons();
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(),
556 ( const VectorOfVectorOfSlideBitmaps::value_type
& cp
)
557 { return rView
== cp
.first
; } ) ) == aEnd
)
559 // corresponding view not found - maybe view was not
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
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
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
591 if( !rBitmap
|| rBitmap
->getSize() != rSlideSize
)
593 // no bitmap there yet, or wrong size - create one
594 rBitmap
= createCurrentSlideBitmap(rView
, rSlideSize
);
604 void SlideImpl::viewAdded( const UnoViewSharedPtr
& rView
)
606 maSlideBitmaps
.emplace_back( rView
,
607 VectorOfSlideBitmaps(SlideAnimationState_NUM_ENTRIES
) );
610 mpLayerManager
->viewAdded( rView
);
613 void SlideImpl::viewRemoved( const UnoViewSharedPtr
& rView
)
616 mpLayerManager
->viewRemoved( rView
);
618 std::erase_if(maSlideBitmaps
,
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() )
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
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(
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
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
;
734 beans::NamedValue maSearchKey
;
735 uno::Reference
< animations::XAnimationNode
> maMainSequence
;
738 bool SlideImpl::implPrefetchShow()
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 // ==========================
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)
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
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
& )
791 catch( uno::Exception
& )
793 TOOLS_WARN_EXCEPTION( "slideshow", "" );
794 // TODO(E2): Error handling. For now, bail out
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
,
818 std::vector(maPolygons
),
819 mbUserPaintOverlayEnabled
);
820 mbPaintOverlayActive
= true;
824 void SlideImpl::drawPolygons() const
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
,
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
,
865 // not a shape target. Maybe a ParagraphTarget?
866 presentation::ParagraphTarget aParaTarget
;
868 if( rProp
.Target
>>= aParaTarget
)
870 // yep, ParagraphTarget found - extract shape
872 xShape
= aParaTarget
.Shape
;
873 nParaIndex
= aParaTarget
.Paragraph
;
879 ShapeSharedPtr
pShape( mpLayerManager
->lookupShape( xShape
) );
883 OSL_FAIL( "SlideImpl::applyInitialShapeAttributes(): no shape found for given target" );
887 AttributableShapeSharedPtr
pAttrShape(
888 ::std::dynamic_pointer_cast
< AttributableShape
>( pShape
) );
892 OSL_FAIL( "SlideImpl::applyInitialShapeAttributes(): shape found does not "
893 "implement AttributableShape interface" );
897 if( nParaIndex
!= -1 )
899 // our target is a paragraph subset, thus look
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" );
911 pAttrShape
= pAttrShape
->getSubset(
912 rNodeSupplier
.getTreeNode(
914 DocTreeNode::NodeType::LogicalParagraph
) );
918 OSL_FAIL( "SlideImpl::applyInitialShapeAttributes(): shape found does not "
919 "provide a subset for requested paragraph index" );
924 const uno::Sequence
< beans::NamedValue
>& rShapeProps( rProp
.Properties
);
925 for( const auto& rShapeProp
: rShapeProps
)
928 if( rShapeProp
.Name
.equalsIgnoreAsciiCase("visibility") &&
929 extractValue( bVisible
,
932 basegfx::B2DVector(getSlideSize().getWidth(), getSlideSize().getHeight()) ))
934 pAttrShape
->setVisibility( bVisible
);
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() )
952 if( !xRootAnimationNode
.is() )
954 meAnimationState
= INITIAL_STATE
;
956 return true; // no animations - no attributes to apply -
960 applyShapeAttributes(xRootAnimationNode
, true);
962 meAnimationState
= INITIAL_STATE
;
967 bool SlideImpl::loadShapes()
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
,
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
,
1003 mxDrawPagesSupplier
,
1005 0, /* shape num starts at 0 */
1008 mpLayerManager
->addShape(
1009 aMPShapesFunctor
.importBackgroundShape() );
1011 while( !aMPShapesFunctor
.isImportDone() )
1013 ShapeSharedPtr
const pShape(
1014 aMPShapesFunctor
.importShape() );
1017 pShape
->setIsForeground(false);
1018 mpLayerManager
->addShape( pShape
);
1021 addPolygons(aMPShapesFunctor
.getPolygons());
1023 nCurrCount
= static_cast<sal_Int32
>(aMPShapesFunctor
.getImportedShapesCount());
1025 catch( uno::RuntimeException
& )
1029 catch( ShapeLoadFailedException
& )
1031 // TODO(E2): Error handling. For now, bail out
1032 TOOLS_WARN_EXCEPTION( "slideshow", "SlideImpl::loadShapes(): caught ShapeLoadFailedException" );
1036 catch( uno::Exception
& )
1038 TOOLS_WARN_EXCEPTION( "slideshow", "" );
1046 // load the normal page shapes
1049 ShapeImporter
aShapesFunctor( mxDrawPage
,
1051 mxDrawPagesSupplier
,
1056 while( !aShapesFunctor
.isImportDone() )
1058 ShapeSharedPtr
const pShape(
1059 aShapesFunctor
.importShape() );
1061 mpLayerManager
->addShape( pShape
);
1063 addPolygons(aShapesFunctor
.getPolygons());
1065 catch( uno::RuntimeException
& )
1069 catch( ShapeLoadFailedException
& )
1071 // TODO(E2): Error handling. For now, bail out
1072 TOOLS_WARN_EXCEPTION( "slideshow", "SlideImpl::loadShapes(): caught ShapeLoadFailedException" );
1075 catch( uno::Exception
& )
1077 TOOLS_WARN_EXCEPTION( "slideshow", "" );
1081 mbShapesLoaded
= 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
);
1138 } // namespace slideshow
1140 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */