android: Update app-specific/MIME type icons
[LibreOffice.git] / slideshow / source / engine / slide / slideimpl.cxx
blobbf07e18acf60b533681832359312d97f7280ac41
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 <comphelper/diagnose_ex.hxx>
23 #include <cppcanvas/basegfxfactory.hxx>
25 #include <basegfx/matrix/b2dhommatrix.hxx>
26 #include <basegfx/point/b2dpoint.hxx>
28 #include <com/sun/star/awt/SystemPointer.hpp>
29 #include <com/sun/star/drawing/XMasterPageTarget.hpp>
30 #include <com/sun/star/beans/XPropertySet.hpp>
31 #include <com/sun/star/presentation/ParagraphTarget.hpp>
32 #include <com/sun/star/presentation/EffectNodeType.hpp>
34 #include <slide.hxx>
35 #include <slideshowcontext.hxx>
36 #include "slideanimations.hxx"
37 #include <doctreenode.hxx>
38 #include <screenupdater.hxx>
39 #include <cursormanager.hxx>
40 #include <shapeimporter.hxx>
41 #include <slideshowexceptions.hxx>
42 #include <eventqueue.hxx>
43 #include <activitiesqueue.hxx>
44 #include "layermanager.hxx"
45 #include "shapemanagerimpl.hxx"
46 #include <usereventqueue.hxx>
47 #include "userpaintoverlay.hxx"
48 #include "targetpropertiescreator.hxx"
49 #include <tools.hxx>
50 #include <box2dtools.hxx>
51 #include <utility>
52 #include <vcl/graphicfilter.hxx>
53 #include <svx/svdograf.hxx>
55 using namespace ::com::sun::star;
58 namespace slideshow::internal
60 namespace
63 class SlideImpl : public Slide,
64 public CursorManager,
65 public ViewEventHandler,
66 public ::osl::DebugBase<SlideImpl>
68 public:
69 SlideImpl( const uno::Reference<drawing::XDrawPage>& xDrawPage,
70 uno::Reference<drawing::XDrawPagesSupplier> xDrawPages,
71 uno::Reference<animations::XAnimationNode> xRootNode,
72 EventQueue& rEventQueue,
73 EventMultiplexer& rEventMultiplexer,
74 ScreenUpdater& rScreenUpdater,
75 ActivitiesQueue& rActivitiesQueue,
76 UserEventQueue& rUserEventQueue,
77 CursorManager& rCursorManager,
78 MediaFileManager& rMediaFileManager,
79 const UnoViewContainer& rViewContainer,
80 const uno::Reference<uno::XComponentContext>& xContext,
81 const ShapeEventListenerMap& rShapeListenerMap,
82 const ShapeCursorMap& rShapeCursorMap,
83 PolyPolygonVector&& rPolyPolygonVector,
84 RGBColor const& rUserPaintColor,
85 double dUserPaintStrokeWidth,
86 bool bUserPaintEnabled,
87 bool bIntrinsicAnimationsAllowed,
88 bool bDisableAnimationZOrder );
90 virtual ~SlideImpl() override;
93 // Slide interface
96 virtual void prefetch() override;
97 virtual void show( bool ) override;
98 virtual void hide() override;
100 virtual basegfx::B2ISize getSlideSize() const override;
101 virtual uno::Reference<drawing::XDrawPage > getXDrawPage() const override;
102 virtual uno::Reference<animations::XAnimationNode> getXAnimationNode() const override;
103 virtual PolyPolygonVector getPolygons() override;
104 virtual void drawPolygons() const override;
105 virtual bool isPaintOverlayActive() const override;
106 virtual void enablePaintOverlay() override;
107 virtual void update_settings( bool bUserPaintEnabled, RGBColor const& aUserPaintColor, double dUserPaintStrokeWidth ) override;
110 // TODO(F2): Rework SlideBitmap to no longer be based on XBitmap,
111 // but on canvas-independent basegfx bitmaps
112 virtual SlideBitmapSharedPtr getCurrentSlideBitmap( const UnoViewSharedPtr& rView ) const override;
115 private:
116 // ViewEventHandler
117 virtual void viewAdded( const UnoViewSharedPtr& rView ) override;
118 virtual void viewRemoved( const UnoViewSharedPtr& rView ) override;
119 virtual void viewChanged( const UnoViewSharedPtr& rView ) override;
120 virtual void viewsChanged() override;
122 // CursorManager
123 virtual bool requestCursor( sal_Int16 nCursorShape ) override;
124 virtual void resetCursor() override;
126 void activatePaintOverlay();
127 void deactivatePaintOverlay();
129 /** Query whether the slide has animations at all
131 If the slide doesn't have animations, show() displays
132 only static content. If an event is registered with
133 registerSlideEndEvent(), this event will be
134 immediately activated at the end of the show() method.
136 @return true, if this slide has animations, false
137 otherwise
139 bool isAnimated();
141 /// Set all Shapes to their initial attributes for slideshow
142 bool applyInitialShapeAttributes( const css::uno::Reference< css::animations::XAnimationNode >& xRootAnimationNode );
144 /// Set shapes to attributes corresponding to initial or final state of slide
145 void applyShapeAttributes(
146 const css::uno::Reference< css::animations::XAnimationNode >& xRootAnimationNode,
147 bool bInitial) const;
149 /// Renders current slide content to bitmap
150 SlideBitmapSharedPtr createCurrentSlideBitmap(
151 const UnoViewSharedPtr& rView,
152 ::basegfx::B2ISize const & rSlideSize ) const;
154 /// Prefetch all shapes (not the animations)
155 bool loadShapes();
157 /// Retrieve slide size from XDrawPage
158 basegfx::B2ISize getSlideSizeImpl() const;
160 /// Prefetch show, but don't call applyInitialShapeAttributes()
161 bool implPrefetchShow();
163 /// Add Polygons to the member maPolygons
164 void addPolygons(const PolyPolygonVector& rPolygons);
166 // Types
167 // =====
169 enum SlideAnimationState
171 CONSTRUCTING_STATE=0,
172 INITIAL_STATE=1,
173 SHOWING_STATE=2,
174 FINAL_STATE=3,
175 SlideAnimationState_NUM_ENTRIES=4
178 typedef std::vector< SlideBitmapSharedPtr > VectorOfSlideBitmaps;
179 /** Vector of slide bitmaps.
181 Since the bitmap content is sensitive to animation
182 effects, we have an inner vector containing a distinct
183 bitmap for each of the SlideAnimationStates.
185 typedef ::std::vector< std::pair< UnoViewSharedPtr,
186 VectorOfSlideBitmaps > > VectorOfVectorOfSlideBitmaps;
189 // Member variables
190 // ================
192 /// The page model object
193 uno::Reference< drawing::XDrawPage > mxDrawPage;
194 uno::Reference< drawing::XDrawPagesSupplier > mxDrawPagesSupplier;
195 uno::Reference< animations::XAnimationNode > mxRootNode;
197 LayerManagerSharedPtr mpLayerManager;
198 std::shared_ptr<ShapeManagerImpl> mpShapeManager;
199 std::shared_ptr<SubsettableShapeManager> mpSubsettableShapeManager;
200 box2d::utils::Box2DWorldSharedPtr mpBox2DWorld;
202 /// Contains common objects needed throughout the slideshow
203 SlideShowContext maContext;
205 /// parent cursor manager
206 CursorManager& mrCursorManager;
208 /// Handles the animation and event generation for us
209 SlideAnimations maAnimations;
210 PolyPolygonVector maPolygons;
212 RGBColor maUserPaintColor;
213 double mdUserPaintStrokeWidth;
214 UserPaintOverlaySharedPtr mpPaintOverlay;
216 /// Bitmaps with slide content at various states
217 mutable VectorOfVectorOfSlideBitmaps maSlideBitmaps;
219 SlideAnimationState meAnimationState;
221 const basegfx::B2ISize maSlideSize;
223 sal_Int16 mnCurrentCursor;
225 /// True, when intrinsic shape animations are allowed
226 bool mbIntrinsicAnimationsAllowed;
228 /// True, when user paint overlay is enabled
229 bool mbUserPaintOverlayEnabled;
231 /// True, if initial load of all page shapes succeeded
232 bool mbShapesLoaded;
234 /// True, if initial load of all animation info succeeded
235 bool mbShowLoaded;
237 /** True, if this slide is not static.
239 If this slide has animated content, this variable will
240 be true, and false otherwise.
242 bool mbHaveAnimations;
244 /** True, if this slide has a main animation sequence.
246 If this slide has animation content, which in turn has
247 a main animation sequence (which must be fully run
248 before EventMultiplexer::notifySlideAnimationsEnd() is
249 called), this member is true.
251 bool mbMainSequenceFound;
253 /// When true, show() was called. Slide hidden otherwise.
254 bool mbActive;
256 /// When true, enablePaintOverlay was called and mbUserPaintOverlay = true
257 bool mbPaintOverlayActive;
259 /// When true, final state attributes are already applied to shapes
260 bool mbFinalStateApplied;
264 void slideRenderer( SlideImpl const * pSlide, const UnoViewSharedPtr& rView )
266 // fully clear view content to background color
267 rView->clearAll();
269 SlideBitmapSharedPtr pBitmap( pSlide->getCurrentSlideBitmap( rView ) );
270 ::cppcanvas::CanvasSharedPtr pCanvas( rView->getCanvas() );
272 const ::basegfx::B2DHomMatrix aViewTransform( rView->getTransformation() );
273 const ::basegfx::B2DPoint aOutPosPixel( aViewTransform * ::basegfx::B2DPoint() );
275 // setup a canvas with device coordinate space, the slide
276 // bitmap already has the correct dimension.
277 ::cppcanvas::CanvasSharedPtr pDevicePixelCanvas( pCanvas->clone() );
278 pDevicePixelCanvas->setTransformation( ::basegfx::B2DHomMatrix() );
280 // render at given output position
281 pBitmap->move( aOutPosPixel );
283 // clear clip (might have been changed, e.g. from comb
284 // transition)
285 pBitmap->clip( ::basegfx::B2DPolyPolygon() );
286 pBitmap->draw( pDevicePixelCanvas );
290 SlideImpl::SlideImpl( const uno::Reference< drawing::XDrawPage >& xDrawPage,
291 uno::Reference<drawing::XDrawPagesSupplier> xDrawPages,
292 uno::Reference< animations::XAnimationNode > xRootNode,
293 EventQueue& rEventQueue,
294 EventMultiplexer& rEventMultiplexer,
295 ScreenUpdater& rScreenUpdater,
296 ActivitiesQueue& rActivitiesQueue,
297 UserEventQueue& rUserEventQueue,
298 CursorManager& rCursorManager,
299 MediaFileManager& rMediaFileManager,
300 const UnoViewContainer& rViewContainer,
301 const uno::Reference< uno::XComponentContext >& xComponentContext,
302 const ShapeEventListenerMap& rShapeListenerMap,
303 const ShapeCursorMap& rShapeCursorMap,
304 PolyPolygonVector&& rPolyPolygonVector,
305 RGBColor const& aUserPaintColor,
306 double dUserPaintStrokeWidth,
307 bool bUserPaintEnabled,
308 bool bIntrinsicAnimationsAllowed,
309 bool bDisableAnimationZOrder ) :
310 mxDrawPage( xDrawPage ),
311 mxDrawPagesSupplier(std::move( xDrawPages )),
312 mxRootNode(std::move( xRootNode )),
313 mpLayerManager( std::make_shared<LayerManager>(
314 rViewContainer,
315 bDisableAnimationZOrder) ),
316 mpShapeManager( std::make_shared<ShapeManagerImpl>(
317 rEventMultiplexer,
318 mpLayerManager,
319 rCursorManager,
320 rShapeListenerMap,
321 rShapeCursorMap,
322 xDrawPage)),
323 mpSubsettableShapeManager( mpShapeManager ),
324 mpBox2DWorld( std::make_shared<box2d::utils::box2DWorld>(
325 basegfx::B2DVector( getSlideSizeImpl() ) ) ),
326 maContext( mpSubsettableShapeManager,
327 rEventQueue,
328 rEventMultiplexer,
329 rScreenUpdater,
330 rActivitiesQueue,
331 rUserEventQueue,
332 *this,
333 rMediaFileManager,
334 rViewContainer,
335 xComponentContext,
336 mpBox2DWorld ),
337 mrCursorManager( rCursorManager ),
338 maAnimations( maContext,
339 basegfx::B2DVector( getSlideSizeImpl() ) ),
340 maPolygons(std::move(rPolyPolygonVector)),
341 maUserPaintColor(aUserPaintColor),
342 mdUserPaintStrokeWidth(dUserPaintStrokeWidth),
343 mpPaintOverlay(),
344 maSlideBitmaps(),
345 meAnimationState( CONSTRUCTING_STATE ),
346 maSlideSize(getSlideSizeImpl()),
347 mnCurrentCursor( awt::SystemPointer::ARROW ),
348 mbIntrinsicAnimationsAllowed( bIntrinsicAnimationsAllowed ),
349 mbUserPaintOverlayEnabled(bUserPaintEnabled),
350 mbShapesLoaded( false ),
351 mbShowLoaded( false ),
352 mbHaveAnimations( false ),
353 mbMainSequenceFound( false ),
354 mbActive( false ),
355 mbPaintOverlayActive( false ),
356 mbFinalStateApplied( false )
358 // clone already existing views for slide bitmaps
359 for( const auto& rView : rViewContainer )
360 viewAdded( rView );
362 // register screen update (LayerManager needs to signal pending
363 // updates)
364 maContext.mrScreenUpdater.addViewUpdate(mpShapeManager);
367 void SlideImpl::update_settings( bool bUserPaintEnabled, RGBColor const& aUserPaintColor, double dUserPaintStrokeWidth )
369 maUserPaintColor = aUserPaintColor;
370 mdUserPaintStrokeWidth = dUserPaintStrokeWidth;
371 mbUserPaintOverlayEnabled = bUserPaintEnabled;
374 SlideImpl::~SlideImpl()
376 if( mpShapeManager )
378 maContext.mrScreenUpdater.removeViewUpdate(mpShapeManager);
379 mpShapeManager->dispose();
381 // TODO(Q3): Make sure LayerManager (and thus Shapes) dies
382 // first, because SlideShowContext has SubsettableShapeManager
383 // as reference member.
384 mpLayerManager.reset();
388 void SlideImpl::prefetch()
390 if( !mxRootNode.is() )
391 return;
393 // Try to prefetch all graphics from the page. This will be done
394 // in threads to be more efficient than loading them on-demand one by one.
395 std::vector<Graphic*> graphics;
396 for (sal_Int32 i = 0; i < mxDrawPage->getCount(); i++)
398 com::sun::star::uno::Reference<com::sun::star::drawing::XShape> xShape(mxDrawPage->getByIndex(i), com::sun::star::uno::UNO_QUERY_THROW);
399 SdrObject* pObj = SdrObject::getSdrObjectFromXShape(xShape);
400 if (!pObj)
401 continue;
402 if( SdrGrafObj* grafObj = dynamic_cast<SdrGrafObj*>(pObj))
403 if( !grafObj->GetGraphic().isAvailable())
404 graphics.push_back( const_cast<Graphic*>(&grafObj->GetGraphic()));
406 if(graphics.size() > 1) // threading does not help with loading just one
407 GraphicFilter::GetGraphicFilter().MakeGraphicsAvailableThreaded( graphics );
409 applyInitialShapeAttributes(mxRootNode);
412 void SlideImpl::show( bool bSlideBackgroundPainted )
414 if( mbActive )
415 return; // already active
417 if( !mpShapeManager || !mpLayerManager )
418 return; // disposed
420 // set initial shape attributes (e.g. hide shapes that have
421 // 'appear' effect set)
422 if( !applyInitialShapeAttributes(mxRootNode) )
423 return;
425 // activate and take over view - clears view, if necessary
426 mbActive = true;
427 requestCursor( mnCurrentCursor );
429 // enable shape management & event broadcasting for shapes of this
430 // slide. Also enables LayerManager to record updates. Currently,
431 // never let LayerManager render initial slide content, use
432 // buffered slide bitmaps instead.
433 mpShapeManager->activate();
436 // render slide to screen, if requested
437 if( !bSlideBackgroundPainted )
439 for( const auto& rContext : maContext.mrViewContainer )
440 slideRenderer( this, rContext );
442 maContext.mrScreenUpdater.notifyUpdate();
446 // fire up animations
447 const bool bIsAnimated( isAnimated() );
448 if( bIsAnimated )
449 maAnimations.start(); // feeds initial events into queue
451 // NOTE: this looks slightly weird, but is indeed correct:
452 // as isAnimated() might return false, _although_ there is
453 // a main sequence (because the animation nodes don't
454 // contain any executable effects), we gotta check both
455 // conditions here.
456 if( !bIsAnimated || !mbMainSequenceFound )
458 // manually trigger a slide animation end event (we don't have
459 // animations at all, or we don't have a main animation
460 // sequence, but if we had, it'd end now). Note that having
461 // animations alone does not matter here, as only main
462 // sequence animations prevents showing the next slide on
463 // nextEvent().
464 maContext.mrEventMultiplexer.notifySlideAnimationsEnd();
467 // enable shape-intrinsic animations (drawing layer animations or
468 // GIF animations)
469 if( mbIntrinsicAnimationsAllowed )
470 mpSubsettableShapeManager->notifyIntrinsicAnimationsEnabled();
472 // enable paint overlay, if maUserPaintColor is valid
473 activatePaintOverlay();
476 // from now on, animations might be showing
477 meAnimationState = SHOWING_STATE;
480 void SlideImpl::hide()
482 if( !mbActive || !mpShapeManager )
483 return; // already hidden/disposed
486 // from now on, all animations are stopped
487 meAnimationState = FINAL_STATE;
490 // disable user paint overlay under all circumstances,
491 // this slide now ceases to be active.
492 deactivatePaintOverlay();
495 // switch off all shape-intrinsic animations.
496 mpSubsettableShapeManager->notifyIntrinsicAnimationsDisabled();
498 // force-end all SMIL animations, too
499 maAnimations.end();
502 // disable shape management & event broadcasting for shapes of this
503 // slide. Also disables LayerManager.
504 mpShapeManager->deactivate();
506 // vanish from view
507 resetCursor();
508 mbActive = false;
511 basegfx::B2ISize SlideImpl::getSlideSize() const
513 return maSlideSize;
516 uno::Reference<drawing::XDrawPage > SlideImpl::getXDrawPage() const
518 return mxDrawPage;
521 uno::Reference<animations::XAnimationNode> SlideImpl::getXAnimationNode() const
523 return mxRootNode;
526 PolyPolygonVector SlideImpl::getPolygons()
528 if(mbPaintOverlayActive)
529 maPolygons = mpPaintOverlay->getPolygons();
530 return maPolygons;
533 SlideBitmapSharedPtr SlideImpl::getCurrentSlideBitmap( const UnoViewSharedPtr& rView ) const
535 // search corresponding entry in maSlideBitmaps (which
536 // contains the views as the key)
537 VectorOfVectorOfSlideBitmaps::iterator aIter;
538 const VectorOfVectorOfSlideBitmaps::iterator aEnd( maSlideBitmaps.end() );
539 if( (aIter=std::find_if( maSlideBitmaps.begin(),
540 aEnd,
541 [&rView]
542 ( const VectorOfVectorOfSlideBitmaps::value_type& cp )
543 { return rView == cp.first; } ) ) == aEnd )
545 // corresponding view not found - maybe view was not
546 // added to Slide?
547 ENSURE_OR_THROW( false,
548 "SlideImpl::getInitialSlideBitmap(): view does not "
549 "match any of the added ones" );
552 // ensure that the show is loaded
553 if( !mbShowLoaded )
555 // only prefetch and init shapes when not done already
556 // (otherwise, at least applyInitialShapeAttributes() will be
557 // called twice for initial slide rendering). Furthermore,
558 // applyInitialShapeAttributes() _always_ performs
559 // initializations, which would be highly unwanted during a
560 // running show. OTOH, a slide whose mbShowLoaded is false is
561 // guaranteed not be running a show.
563 // set initial shape attributes (e.g. hide 'appear' effect
564 // shapes)
565 if( !const_cast<SlideImpl*>(this)->applyInitialShapeAttributes( mxRootNode ) )
566 ENSURE_OR_THROW(false,
567 "SlideImpl::getCurrentSlideBitmap(): Cannot "
568 "apply initial attributes");
571 SlideBitmapSharedPtr& rBitmap( aIter->second.at( meAnimationState ));
572 const ::basegfx::B2ISize& rSlideSize(
573 getSlideSizePixel( ::basegfx::B2DVector( getSlideSize() ),
574 rView ));
576 // is the bitmap valid (actually existent, and of correct
577 // size)?
578 if( !rBitmap || rBitmap->getSize() != rSlideSize )
580 // no bitmap there yet, or wrong size - create one
581 rBitmap = createCurrentSlideBitmap(rView, rSlideSize);
584 return rBitmap;
588 // private methods
591 void SlideImpl::viewAdded( const UnoViewSharedPtr& rView )
593 maSlideBitmaps.emplace_back( rView,
594 VectorOfSlideBitmaps(SlideAnimationState_NUM_ENTRIES) );
596 if( mpLayerManager )
597 mpLayerManager->viewAdded( rView );
600 void SlideImpl::viewRemoved( const UnoViewSharedPtr& rView )
602 if( mpLayerManager )
603 mpLayerManager->viewRemoved( rView );
605 const VectorOfVectorOfSlideBitmaps::iterator aEnd( maSlideBitmaps.end() );
606 maSlideBitmaps.erase(
607 std::remove_if( maSlideBitmaps.begin(),
608 aEnd,
609 [&rView]
610 ( const VectorOfVectorOfSlideBitmaps::value_type& cp )
611 { return rView == cp.first; } ),
612 aEnd );
615 void SlideImpl::viewChanged( const UnoViewSharedPtr& rView )
617 // nothing to do for the Slide - getCurrentSlideBitmap() lazily
618 // handles bitmap resizes
619 if( mbActive && mpLayerManager )
620 mpLayerManager->viewChanged(rView);
623 void SlideImpl::viewsChanged()
625 // nothing to do for the Slide - getCurrentSlideBitmap() lazily
626 // handles bitmap resizes
627 if( mbActive && mpLayerManager )
628 mpLayerManager->viewsChanged();
631 bool SlideImpl::requestCursor( sal_Int16 nCursorShape )
633 mnCurrentCursor = nCursorShape;
634 return mrCursorManager.requestCursor(mnCurrentCursor);
637 void SlideImpl::resetCursor()
639 mnCurrentCursor = awt::SystemPointer::ARROW;
640 mrCursorManager.resetCursor();
643 bool SlideImpl::isAnimated()
645 // prefetch, but don't apply initial shape attributes
646 if( !implPrefetchShow() )
647 return false;
649 return mbHaveAnimations && maAnimations.isAnimated();
652 SlideBitmapSharedPtr SlideImpl::createCurrentSlideBitmap( const UnoViewSharedPtr& rView,
653 const ::basegfx::B2ISize& rBmpSize ) const
655 ENSURE_OR_THROW( rView && rView->getCanvas(),
656 "SlideImpl::createCurrentSlideBitmap(): Invalid view" );
657 ENSURE_OR_THROW( mpLayerManager,
658 "SlideImpl::createCurrentSlideBitmap(): Invalid layer manager" );
659 ENSURE_OR_THROW( mbShowLoaded,
660 "SlideImpl::createCurrentSlideBitmap(): No show loaded" );
662 // tdf#96083 ensure end state settings are applied to shapes once when bitmap gets re-rendered
663 // in that state
664 if(!mbFinalStateApplied && FINAL_STATE == meAnimationState && mxRootNode.is())
666 const_cast< SlideImpl* >(this)->mbFinalStateApplied = true;
667 applyShapeAttributes(mxRootNode, false);
670 ::cppcanvas::CanvasSharedPtr pCanvas( rView->getCanvas() );
672 // create a bitmap of appropriate size
673 ::cppcanvas::BitmapSharedPtr pBitmap(
674 ::cppcanvas::BaseGfxFactory::createBitmap(
675 pCanvas,
676 rBmpSize ) );
678 ENSURE_OR_THROW( pBitmap,
679 "SlideImpl::createCurrentSlideBitmap(): Cannot create page bitmap" );
681 ::cppcanvas::BitmapCanvasSharedPtr pBitmapCanvas( pBitmap->getBitmapCanvas() );
683 ENSURE_OR_THROW( pBitmapCanvas,
684 "SlideImpl::createCurrentSlideBitmap(): Cannot create page bitmap canvas" );
686 // apply linear part of destination canvas transformation (linear means in this context:
687 // transformation without any translational components)
688 ::basegfx::B2DHomMatrix aLinearTransform( rView->getTransformation() );
689 aLinearTransform.set( 0, 2, 0.0 );
690 aLinearTransform.set( 1, 2, 0.0 );
691 pBitmapCanvas->setTransformation( aLinearTransform );
693 // output all shapes to bitmap
694 initSlideBackground( pBitmapCanvas, rBmpSize );
695 mpLayerManager->renderTo( pBitmapCanvas );
697 return std::make_shared<SlideBitmap>( pBitmap );
700 class MainSequenceSearcher
702 public:
703 MainSequenceSearcher()
705 maSearchKey.Name = "node-type";
706 maSearchKey.Value <<= presentation::EffectNodeType::MAIN_SEQUENCE;
709 void operator()( const uno::Reference< animations::XAnimationNode >& xChildNode )
711 uno::Sequence< beans::NamedValue > aUserData( xChildNode->getUserData() );
713 if( findNamedValue( aUserData, maSearchKey ) )
715 maMainSequence = xChildNode;
719 const uno::Reference< animations::XAnimationNode >& getMainSequence() const
721 return maMainSequence;
724 private:
725 beans::NamedValue maSearchKey;
726 uno::Reference< animations::XAnimationNode > maMainSequence;
729 bool SlideImpl::implPrefetchShow()
731 if( mbShowLoaded )
732 return true;
734 ENSURE_OR_RETURN_FALSE( mxDrawPage.is(),
735 "SlideImpl::implPrefetchShow(): Invalid draw page" );
736 ENSURE_OR_RETURN_FALSE( mpLayerManager,
737 "SlideImpl::implPrefetchShow(): Invalid layer manager" );
739 // fetch desired page content
740 // ==========================
742 if( !loadShapes() )
743 return false;
745 // New animations framework: import the shape effect info
746 // ======================================================
750 if( mxRootNode.is() )
752 if( !maAnimations.importAnimations( mxRootNode ) )
754 OSL_FAIL( "SlideImpl::implPrefetchShow(): have animation nodes, "
755 "but import animations failed." );
757 // could not import animation framework,
758 // _although_ some animation nodes are there -
759 // this is an error (not finding animations at
760 // all is okay - might be a static slide)
761 return false;
764 // now check whether we've got a main sequence (if
765 // not, we must manually call
766 // EventMultiplexer::notifySlideAnimationsEnd()
767 // above, as e.g. interactive sequences alone
768 // don't block nextEvent() from issuing the next
769 // slide)
770 MainSequenceSearcher aSearcher;
771 if( for_each_childNode( mxRootNode, aSearcher ) )
772 mbMainSequenceFound = aSearcher.getMainSequence().is();
774 // import successfully done
775 mbHaveAnimations = true;
778 catch( uno::RuntimeException& )
780 throw;
782 catch( uno::Exception& )
784 TOOLS_WARN_EXCEPTION( "slideshow", "" );
785 // TODO(E2): Error handling. For now, bail out
788 mbShowLoaded = true;
790 return true;
793 void SlideImpl::enablePaintOverlay()
795 if( !mbUserPaintOverlayEnabled || !mbPaintOverlayActive )
797 mbUserPaintOverlayEnabled = true;
798 activatePaintOverlay();
802 void SlideImpl::activatePaintOverlay()
804 if( mbUserPaintOverlayEnabled || !maPolygons.empty() )
806 mpPaintOverlay = UserPaintOverlay::create( maUserPaintColor,
807 mdUserPaintStrokeWidth,
808 maContext,
809 std::vector(maPolygons),
810 mbUserPaintOverlayEnabled );
811 mbPaintOverlayActive = true;
815 void SlideImpl::drawPolygons() const
817 if( mpPaintOverlay )
818 mpPaintOverlay->drawPolygons();
821 void SlideImpl::addPolygons(const PolyPolygonVector& rPolygons)
823 maPolygons.insert(maPolygons.end(), rPolygons.begin(), rPolygons.end());
826 bool SlideImpl::isPaintOverlayActive() const
828 return mbPaintOverlayActive;
831 void SlideImpl::deactivatePaintOverlay()
833 if(mbPaintOverlayActive)
834 maPolygons = mpPaintOverlay->getPolygons();
836 mpPaintOverlay.reset();
837 mbPaintOverlayActive = false;
840 void SlideImpl::applyShapeAttributes(
841 const css::uno::Reference< css::animations::XAnimationNode >& xRootAnimationNode,
842 bool bInitial) const
844 const uno::Sequence< animations::TargetProperties > aProps(
845 TargetPropertiesCreator::createTargetProperties( xRootAnimationNode, bInitial ) );
847 // apply extracted values to our shapes
848 for( const auto& rProp : aProps )
850 sal_Int16 nParaIndex( -1 );
851 uno::Reference< drawing::XShape > xShape( rProp.Target,
852 uno::UNO_QUERY );
854 if( !xShape.is() )
856 // not a shape target. Maybe a ParagraphTarget?
857 presentation::ParagraphTarget aParaTarget;
859 if( rProp.Target >>= aParaTarget )
861 // yep, ParagraphTarget found - extract shape
862 // and index
863 xShape = aParaTarget.Shape;
864 nParaIndex = aParaTarget.Paragraph;
868 if( xShape.is() )
870 ShapeSharedPtr pShape( mpLayerManager->lookupShape( xShape ) );
872 if( !pShape )
874 OSL_FAIL( "SlideImpl::applyInitialShapeAttributes(): no shape found for given target" );
875 continue;
878 AttributableShapeSharedPtr pAttrShape(
879 ::std::dynamic_pointer_cast< AttributableShape >( pShape ) );
881 if( !pAttrShape )
883 OSL_FAIL( "SlideImpl::applyInitialShapeAttributes(): shape found does not "
884 "implement AttributableShape interface" );
885 continue;
888 if( nParaIndex != -1 )
890 // our target is a paragraph subset, thus look
891 // this up first.
892 const DocTreeNodeSupplier& rNodeSupplier( pAttrShape->getTreeNodeSupplier() );
894 if( rNodeSupplier.getNumberOfTreeNodes(
895 DocTreeNode::NodeType::LogicalParagraph ) <= nParaIndex )
897 OSL_FAIL( "SlideImpl::applyInitialShapeAttributes(): shape found does not "
898 "provide a subset for requested paragraph index" );
899 continue;
902 pAttrShape = pAttrShape->getSubset(
903 rNodeSupplier.getTreeNode(
904 nParaIndex,
905 DocTreeNode::NodeType::LogicalParagraph ) );
907 if( !pAttrShape )
909 OSL_FAIL( "SlideImpl::applyInitialShapeAttributes(): shape found does not "
910 "provide a subset for requested paragraph index" );
911 continue;
915 const uno::Sequence< beans::NamedValue >& rShapeProps( rProp.Properties );
916 for( const auto& rShapeProp : rShapeProps )
918 bool bVisible=false;
919 if( rShapeProp.Name.equalsIgnoreAsciiCase("visibility") &&
920 extractValue( bVisible,
921 rShapeProp.Value,
922 pShape,
923 basegfx::B2DVector(getSlideSize()) ))
925 pAttrShape->setVisibility( bVisible );
927 else
929 OSL_FAIL( "SlideImpl::applyInitialShapeAttributes(): Unexpected "
930 "(and unimplemented) property encountered" );
937 bool SlideImpl::applyInitialShapeAttributes(
938 const uno::Reference< animations::XAnimationNode >& xRootAnimationNode )
940 if( !implPrefetchShow() )
941 return false;
943 if( !xRootAnimationNode.is() )
945 meAnimationState = INITIAL_STATE;
947 return true; // no animations - no attributes to apply -
948 // succeeded
951 applyShapeAttributes(xRootAnimationNode, true);
953 meAnimationState = INITIAL_STATE;
955 return true;
958 bool SlideImpl::loadShapes()
960 if( mbShapesLoaded )
961 return true;
963 ENSURE_OR_RETURN_FALSE( mxDrawPage.is(),
964 "SlideImpl::loadShapes(): Invalid draw page" );
965 ENSURE_OR_RETURN_FALSE( mpLayerManager,
966 "SlideImpl::loadShapes(): Invalid layer manager" );
968 // fetch desired page content
969 // ==========================
971 // also take master page content
972 uno::Reference< drawing::XDrawPage > xMasterPage;
973 uno::Reference< drawing::XShapes > xMasterPageShapes;
974 sal_Int32 nCurrCount(0);
976 uno::Reference< drawing::XMasterPageTarget > xMasterPageTarget( mxDrawPage,
977 uno::UNO_QUERY );
978 if( xMasterPageTarget.is() )
980 xMasterPage = xMasterPageTarget->getMasterPage();
981 xMasterPageShapes = xMasterPage;
983 if( xMasterPage.is() && xMasterPageShapes.is() )
985 // TODO(P2): maybe cache master pages here (or treat the
986 // masterpage as a single metafile. At least currently,
987 // masterpages do not contain animation effects)
990 // load the masterpage shapes
992 ShapeImporter aMPShapesFunctor( xMasterPage,
993 mxDrawPage,
994 mxDrawPagesSupplier,
995 maContext,
996 0, /* shape num starts at 0 */
997 true );
999 mpLayerManager->addShape(
1000 aMPShapesFunctor.importBackgroundShape() );
1002 while( !aMPShapesFunctor.isImportDone() )
1004 ShapeSharedPtr const& rShape(
1005 aMPShapesFunctor.importShape() );
1006 if( rShape )
1008 rShape->setIsForeground(false);
1009 mpLayerManager->addShape( rShape );
1012 addPolygons(aMPShapesFunctor.getPolygons());
1014 nCurrCount = static_cast<sal_Int32>(aMPShapesFunctor.getImportedShapesCount());
1016 catch( uno::RuntimeException& )
1018 throw;
1020 catch( ShapeLoadFailedException& )
1022 // TODO(E2): Error handling. For now, bail out
1023 TOOLS_WARN_EXCEPTION( "slideshow", "SlideImpl::loadShapes(): caught ShapeLoadFailedException" );
1024 return false;
1027 catch( uno::Exception& )
1029 TOOLS_WARN_EXCEPTION( "slideshow", "" );
1030 return false;
1037 // load the normal page shapes
1040 ShapeImporter aShapesFunctor( mxDrawPage,
1041 mxDrawPage,
1042 mxDrawPagesSupplier,
1043 maContext,
1044 nCurrCount,
1045 false );
1047 while( !aShapesFunctor.isImportDone() )
1049 ShapeSharedPtr const& rShape(
1050 aShapesFunctor.importShape() );
1051 if( rShape )
1052 mpLayerManager->addShape( rShape );
1054 addPolygons(aShapesFunctor.getPolygons());
1056 catch( uno::RuntimeException& )
1058 throw;
1060 catch( ShapeLoadFailedException& )
1062 // TODO(E2): Error handling. For now, bail out
1063 TOOLS_WARN_EXCEPTION( "slideshow", "SlideImpl::loadShapes(): caught ShapeLoadFailedException" );
1064 return false;
1066 catch( uno::Exception& )
1068 TOOLS_WARN_EXCEPTION( "slideshow", "" );
1069 return false;
1072 mbShapesLoaded = true;
1074 return true;
1077 basegfx::B2ISize SlideImpl::getSlideSizeImpl() const
1079 uno::Reference< beans::XPropertySet > xPropSet(
1080 mxDrawPage, uno::UNO_QUERY_THROW );
1082 sal_Int32 nDocWidth = 0;
1083 sal_Int32 nDocHeight = 0;
1084 xPropSet->getPropertyValue("Width") >>= nDocWidth;
1085 xPropSet->getPropertyValue("Height") >>= nDocHeight;
1087 return basegfx::B2ISize( nDocWidth, nDocHeight );
1090 } // namespace
1093 SlideSharedPtr createSlide( const uno::Reference< drawing::XDrawPage >& xDrawPage,
1094 const uno::Reference<drawing::XDrawPagesSupplier>& xDrawPages,
1095 const uno::Reference< animations::XAnimationNode >& xRootNode,
1096 EventQueue& rEventQueue,
1097 EventMultiplexer& rEventMultiplexer,
1098 ScreenUpdater& rScreenUpdater,
1099 ActivitiesQueue& rActivitiesQueue,
1100 UserEventQueue& rUserEventQueue,
1101 CursorManager& rCursorManager,
1102 MediaFileManager& rMediaFileManager,
1103 const UnoViewContainer& rViewContainer,
1104 const uno::Reference< uno::XComponentContext >& xComponentContext,
1105 const ShapeEventListenerMap& rShapeListenerMap,
1106 const ShapeCursorMap& rShapeCursorMap,
1107 PolyPolygonVector&& rPolyPolygonVector,
1108 RGBColor const& rUserPaintColor,
1109 double dUserPaintStrokeWidth,
1110 bool bUserPaintEnabled,
1111 bool bIntrinsicAnimationsAllowed,
1112 bool bDisableAnimationZOrder )
1114 auto pRet = std::make_shared<SlideImpl>( xDrawPage, xDrawPages, xRootNode, rEventQueue,
1115 rEventMultiplexer, rScreenUpdater,
1116 rActivitiesQueue, rUserEventQueue,
1117 rCursorManager, rMediaFileManager, rViewContainer,
1118 xComponentContext, rShapeListenerMap,
1119 rShapeCursorMap, std::move(rPolyPolygonVector), rUserPaintColor,
1120 dUserPaintStrokeWidth, bUserPaintEnabled,
1121 bIntrinsicAnimationsAllowed,
1122 bDisableAnimationZOrder );
1124 rEventMultiplexer.addViewHandler( pRet );
1126 return pRet;
1129 } // namespace slideshow
1131 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */