LibreOffice Module slideshow (master) 1
slideimpl.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20
21#include <osl/diagnose.hxx>
24
27
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>
33
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>
42#include <eventqueue.hxx>
43#include <activitiesqueue.hxx>
44#include "layermanager.hxx"
45#include "shapemanagerimpl.hxx"
46#include <usereventqueue.hxx>
47#include "userpaintoverlay.hxx"
49#include <tools.hxx>
50#include <box2dtools.hxx>
51#include <utility>
52#include <vcl/graphicfilter.hxx>
53#include <svx/svdograf.hxx>
54
55using namespace ::com::sun::star;
56
57
58namespace slideshow::internal
59{
60namespace
61{
62
63class SlideImpl : public Slide,
64 public CursorManager,
65 public ViewEventHandler,
66 public ::osl::DebugBase<SlideImpl>
67{
68public:
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 );
89
90 virtual ~SlideImpl() override;
91
92
93 // Slide interface
94
95
96 virtual void prefetch() override;
97 virtual void show( bool ) override;
98 virtual void hide() override;
99
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;
108
109
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;
113
114
115private:
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;
121
122 // CursorManager
123 virtual bool requestCursor( sal_Int16 nCursorShape ) override;
124 virtual void resetCursor() override;
125
126 void activatePaintOverlay();
127 void deactivatePaintOverlay();
128
139 bool isAnimated();
140
142 bool applyInitialShapeAttributes( const css::uno::Reference< css::animations::XAnimationNode >& xRootAnimationNode );
143
145 void applyShapeAttributes(
146 const css::uno::Reference< css::animations::XAnimationNode >& xRootAnimationNode,
147 bool bInitial) const;
148
150 SlideBitmapSharedPtr createCurrentSlideBitmap(
151 const UnoViewSharedPtr& rView,
152 ::basegfx::B2ISize const & rSlideSize ) const;
153
155 bool loadShapes();
156
158 basegfx::B2ISize getSlideSizeImpl() const;
159
161 bool implPrefetchShow();
162
164 void addPolygons(const PolyPolygonVector& rPolygons);
165
166 // Types
167 // =====
168
169 enum SlideAnimationState
170 {
171 CONSTRUCTING_STATE=0,
172 INITIAL_STATE=1,
173 SHOWING_STATE=2,
174 FINAL_STATE=3,
175 SlideAnimationState_NUM_ENTRIES=4
176 };
177
178 typedef std::vector< SlideBitmapSharedPtr > VectorOfSlideBitmaps;
185 typedef ::std::vector< std::pair< UnoViewSharedPtr,
186 VectorOfSlideBitmaps > > VectorOfVectorOfSlideBitmaps;
187
188
189 // Member variables
190 // ================
191
193 uno::Reference< drawing::XDrawPage > mxDrawPage;
194 uno::Reference< drawing::XDrawPagesSupplier > mxDrawPagesSupplier;
195 uno::Reference< animations::XAnimationNode > mxRootNode;
196
198 std::shared_ptr<ShapeManagerImpl> mpShapeManager;
199 std::shared_ptr<SubsettableShapeManager> mpSubsettableShapeManager;
201
203 SlideShowContext maContext;
204
206 CursorManager& mrCursorManager;
207
209 SlideAnimations maAnimations;
211
215
217 mutable VectorOfVectorOfSlideBitmaps maSlideBitmaps;
218
219 SlideAnimationState meAnimationState;
220
222
224
227
230
233
236
243
252
255
258
261};
262
263
264void slideRenderer( SlideImpl const * pSlide, const UnoViewSharedPtr& rView )
265{
266 // fully clear view content to background color
267 rView->clearAll();
268
269 SlideBitmapSharedPtr pBitmap( pSlide->getCurrentSlideBitmap( rView ) );
270 ::cppcanvas::CanvasSharedPtr pCanvas( rView->getCanvas() );
271
272 const ::basegfx::B2DHomMatrix aViewTransform( rView->getTransformation() );
273 const ::basegfx::B2DPoint aOutPosPixel( aViewTransform * ::basegfx::B2DPoint() );
274
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() );
279
280 // render at given output position
281 pBitmap->move( aOutPosPixel );
282
283 // clear clip (might have been changed, e.g. from comb
284 // transition)
285 pBitmap->clip( ::basegfx::B2DPolyPolygon() );
286 pBitmap->draw( pDevicePixelCanvas );
287}
288
289
290SlideImpl::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,
319 rCursorManager,
320 rShapeListenerMap,
321 rShapeCursorMap,
322 xDrawPage)),
324 mpBox2DWorld( std::make_shared<box2d::utils::box2DWorld>(
325 basegfx::B2DVector(getSlideSizeImpl().getWidth(), getSlideSizeImpl().getHeight()) ) ),
327 rEventQueue,
328 rEventMultiplexer,
329 rScreenUpdater,
330 rActivitiesQueue,
331 rUserEventQueue,
332 *this,
333 rMediaFileManager,
334 rViewContainer,
335 xComponentContext,
336 mpBox2DWorld ),
337 mrCursorManager( rCursorManager ),
339 basegfx::B2DVector(getSlideSizeImpl().getWidth(), getSlideSizeImpl().getHeight()) ),
340 maPolygons(std::move(rPolyPolygonVector)),
341 maUserPaintColor(aUserPaintColor),
342 mdUserPaintStrokeWidth(dUserPaintStrokeWidth),
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 )
357{
358 // clone already existing views for slide bitmaps
359 for( const auto& rView : rViewContainer )
360 viewAdded( rView );
361
362 // register screen update (LayerManager needs to signal pending
363 // updates)
364 maContext.mrScreenUpdater.addViewUpdate(mpShapeManager);
365}
366
367void SlideImpl::update_settings( bool bUserPaintEnabled, RGBColor const& aUserPaintColor, double dUserPaintStrokeWidth )
368{
369 maUserPaintColor = aUserPaintColor;
370 mdUserPaintStrokeWidth = dUserPaintStrokeWidth;
371 mbUserPaintOverlayEnabled = bUserPaintEnabled;
372}
373
374SlideImpl::~SlideImpl()
375{
376 if( mpShapeManager )
377 {
378 maContext.mrScreenUpdater.removeViewUpdate(mpShapeManager);
379 mpShapeManager->dispose();
380
381 // TODO(Q3): Make sure LayerManager (and thus Shapes) dies
382 // first, because SlideShowContext has SubsettableShapeManager
383 // as reference member.
384 mpLayerManager.reset();
385 }
386}
387
388void SlideImpl::prefetch()
389{
390 if( !mxRootNode.is() )
391 return;
392
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++)
397 {
398 com::sun::star::uno::Reference<com::sun::star::drawing::XShape> xShape(mxDrawPage->getByIndex(i), com::sun::star::uno::UNO_QUERY_THROW);
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()));
405 }
406 if(graphics.size() > 1) // threading does not help with loading just one
408
409 applyInitialShapeAttributes(mxRootNode);
410}
411
412void SlideImpl::show( bool bSlideBackgroundPainted )
413{
414 if( mbActive )
415 return; // already active
416
418 return; // disposed
419
420 // set initial shape attributes (e.g. hide shapes that have
421 // 'appear' effect set)
422 if( !applyInitialShapeAttributes(mxRootNode) )
423 return;
424
425 // activate and take over view - clears view, if necessary
426 mbActive = true;
427 requestCursor( mnCurrentCursor );
428
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();
434
435
436 // render slide to screen, if requested
437 if( !bSlideBackgroundPainted )
438 {
439 for( const auto& rContext : maContext.mrViewContainer )
440 slideRenderer( this, rContext );
441
442 maContext.mrScreenUpdater.notifyUpdate();
443 }
444
445
446 // fire up animations
447 const bool bIsAnimated( isAnimated() );
448 if( bIsAnimated )
449 maAnimations.start(); // feeds initial events into queue
450
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 )
457 {
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();
465 }
466
467 // enable shape-intrinsic animations (drawing layer animations or
468 // GIF animations)
470 mpSubsettableShapeManager->notifyIntrinsicAnimationsEnabled();
471
472 // enable paint overlay, if maUserPaintColor is valid
473 activatePaintOverlay();
474
475
476 // from now on, animations might be showing
477 meAnimationState = SHOWING_STATE;
478}
479
480void SlideImpl::hide()
481{
482 if( !mbActive || !mpShapeManager )
483 return; // already hidden/disposed
484
485
486 // from now on, all animations are stopped
487 meAnimationState = FINAL_STATE;
488
489
490 // disable user paint overlay under all circumstances,
491 // this slide now ceases to be active.
492 deactivatePaintOverlay();
493
494
495 // switch off all shape-intrinsic animations.
496 mpSubsettableShapeManager->notifyIntrinsicAnimationsDisabled();
497
498 // force-end all SMIL animations, too
499 maAnimations.end();
500
501
502 // disable shape management & event broadcasting for shapes of this
503 // slide. Also disables LayerManager.
504 mpShapeManager->deactivate();
505
506 // vanish from view
507 resetCursor();
508 mbActive = false;
509}
510
511basegfx::B2ISize SlideImpl::getSlideSize() const
512{
513 return maSlideSize;
514}
515
516uno::Reference<drawing::XDrawPage > SlideImpl::getXDrawPage() const
517{
518 return mxDrawPage;
519}
520
521uno::Reference<animations::XAnimationNode> SlideImpl::getXAnimationNode() const
522{
523 return mxRootNode;
524}
525
526PolyPolygonVector SlideImpl::getPolygons()
527{
529 maPolygons = mpPaintOverlay->getPolygons();
530 return maPolygons;
531}
532
533SlideBitmapSharedPtr SlideImpl::getCurrentSlideBitmap( const UnoViewSharedPtr& rView ) const
534{
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 )
544 {
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" );
550 }
551
552 // ensure that the show is loaded
553 if( !mbShowLoaded )
554 {
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.
562
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");
569 }
570
571 SlideBitmapSharedPtr& rBitmap( aIter->second.at( meAnimationState ));
572 auto aSize = getSlideSizePixel(basegfx::B2DVector(getSlideSize().getWidth(), getSlideSize().getHeight()), rView);
573 const basegfx::B2ISize rSlideSize(aSize.getX(), aSize.getY());
574
575 // is the bitmap valid (actually existent, and of correct
576 // size)?
577 if( !rBitmap || rBitmap->getSize() != rSlideSize )
578 {
579 // no bitmap there yet, or wrong size - create one
580 rBitmap = createCurrentSlideBitmap(rView, rSlideSize);
581 }
582
583 return rBitmap;
584}
585
586
587// private methods
588
589
590void SlideImpl::viewAdded( const UnoViewSharedPtr& rView )
591{
592 maSlideBitmaps.emplace_back( rView,
593 VectorOfSlideBitmaps(SlideAnimationState_NUM_ENTRIES) );
594
595 if( mpLayerManager )
596 mpLayerManager->viewAdded( rView );
597}
598
599void SlideImpl::viewRemoved( const UnoViewSharedPtr& rView )
600{
601 if( mpLayerManager )
602 mpLayerManager->viewRemoved( rView );
603
604 const VectorOfVectorOfSlideBitmaps::iterator aEnd( maSlideBitmaps.end() );
605 maSlideBitmaps.erase(
606 std::remove_if( maSlideBitmaps.begin(),
607 aEnd,
608 [&rView]
609 ( const VectorOfVectorOfSlideBitmaps::value_type& cp )
610 { return rView == cp.first; } ),
611 aEnd );
612}
613
614void SlideImpl::viewChanged( const UnoViewSharedPtr& rView )
615{
616 // nothing to do for the Slide - getCurrentSlideBitmap() lazily
617 // handles bitmap resizes
618 if( mbActive && mpLayerManager )
619 mpLayerManager->viewChanged(rView);
620}
621
622void SlideImpl::viewsChanged()
623{
624 // nothing to do for the Slide - getCurrentSlideBitmap() lazily
625 // handles bitmap resizes
626 if( mbActive && mpLayerManager )
627 mpLayerManager->viewsChanged();
628}
629
630bool SlideImpl::requestCursor( sal_Int16 nCursorShape )
631{
632 mnCurrentCursor = nCursorShape;
633 return mrCursorManager.requestCursor(mnCurrentCursor);
634}
635
636void SlideImpl::resetCursor()
637{
638 mnCurrentCursor = awt::SystemPointer::ARROW;
639 mrCursorManager.resetCursor();
640}
641
642bool SlideImpl::isAnimated()
643{
644 // prefetch, but don't apply initial shape attributes
645 if( !implPrefetchShow() )
646 return false;
647
648 return mbHaveAnimations && maAnimations.isAnimated();
649}
650
651SlideBitmapSharedPtr SlideImpl::createCurrentSlideBitmap( const UnoViewSharedPtr& rView,
652 const ::basegfx::B2ISize& rBmpSize ) const
653{
654 ENSURE_OR_THROW( rView && rView->getCanvas(),
655 "SlideImpl::createCurrentSlideBitmap(): Invalid view" );
657 "SlideImpl::createCurrentSlideBitmap(): Invalid layer manager" );
659 "SlideImpl::createCurrentSlideBitmap(): No show loaded" );
660
661 // tdf#96083 ensure end state settings are applied to shapes once when bitmap gets re-rendered
662 // in that state
663 if(!mbFinalStateApplied && FINAL_STATE == meAnimationState && mxRootNode.is())
664 {
665 const_cast< SlideImpl* >(this)->mbFinalStateApplied = true;
666 applyShapeAttributes(mxRootNode, false);
667 }
668
669 ::cppcanvas::CanvasSharedPtr pCanvas( rView->getCanvas() );
670
671 // create a bitmap of appropriate size
674 pCanvas,
675 rBmpSize ) );
676
677 ENSURE_OR_THROW( pBitmap,
678 "SlideImpl::createCurrentSlideBitmap(): Cannot create page bitmap" );
679
680 ::cppcanvas::BitmapCanvasSharedPtr pBitmapCanvas( pBitmap->getBitmapCanvas() );
681
682 ENSURE_OR_THROW( pBitmapCanvas,
683 "SlideImpl::createCurrentSlideBitmap(): Cannot create page bitmap canvas" );
684
685 // apply linear part of destination canvas transformation (linear means in this context:
686 // transformation without any translational components)
687 ::basegfx::B2DHomMatrix aLinearTransform( rView->getTransformation() );
688 aLinearTransform.set( 0, 2, 0.0 );
689 aLinearTransform.set( 1, 2, 0.0 );
690 pBitmapCanvas->setTransformation( aLinearTransform );
691
692 // output all shapes to bitmap
693 initSlideBackground( pBitmapCanvas, rBmpSize );
694 mpLayerManager->renderTo( pBitmapCanvas );
695
696 return std::make_shared<SlideBitmap>( pBitmap );
697}
698
699class MainSequenceSearcher
700{
701public:
702 MainSequenceSearcher()
703 {
704 maSearchKey.Name = "node-type";
705 maSearchKey.Value <<= presentation::EffectNodeType::MAIN_SEQUENCE;
706 }
707
708 void operator()( const uno::Reference< animations::XAnimationNode >& xChildNode )
709 {
710 uno::Sequence< beans::NamedValue > aUserData( xChildNode->getUserData() );
711
712 if( findNamedValue( aUserData, maSearchKey ) )
713 {
714 maMainSequence = xChildNode;
715 }
716 }
717
718 const uno::Reference< animations::XAnimationNode >& getMainSequence() const
719 {
720 return maMainSequence;
721 }
722
723private:
724 beans::NamedValue maSearchKey;
725 uno::Reference< animations::XAnimationNode > maMainSequence;
726};
727
728bool SlideImpl::implPrefetchShow()
729{
730 if( mbShowLoaded )
731 return true;
732
734 "SlideImpl::implPrefetchShow(): Invalid draw page" );
736 "SlideImpl::implPrefetchShow(): Invalid layer manager" );
737
738 // fetch desired page content
739 // ==========================
740
741 if( !loadShapes() )
742 return false;
743
744 // New animations framework: import the shape effect info
745 // ======================================================
746
747 try
748 {
749 if( mxRootNode.is() )
750 {
751 if( !maAnimations.importAnimations( mxRootNode ) )
752 {
753 OSL_FAIL( "SlideImpl::implPrefetchShow(): have animation nodes, "
754 "but import animations failed." );
755
756 // could not import animation framework,
757 // _although_ some animation nodes are there -
758 // this is an error (not finding animations at
759 // all is okay - might be a static slide)
760 return false;
761 }
762
763 // now check whether we've got a main sequence (if
764 // not, we must manually call
765 // EventMultiplexer::notifySlideAnimationsEnd()
766 // above, as e.g. interactive sequences alone
767 // don't block nextEvent() from issuing the next
768 // slide)
769 MainSequenceSearcher aSearcher;
770 if( for_each_childNode( mxRootNode, aSearcher ) )
771 mbMainSequenceFound = aSearcher.getMainSequence().is();
772
773 // import successfully done
774 mbHaveAnimations = true;
775 }
776 }
777 catch( uno::RuntimeException& )
778 {
779 throw;
780 }
781 catch( uno::Exception& )
782 {
783 TOOLS_WARN_EXCEPTION( "slideshow", "" );
784 // TODO(E2): Error handling. For now, bail out
785 }
786
787 mbShowLoaded = true;
788
789 return true;
790}
791
792void SlideImpl::enablePaintOverlay()
793{
795 {
797 activatePaintOverlay();
798 }
799}
800
801void SlideImpl::activatePaintOverlay()
802{
803 if( mbUserPaintOverlayEnabled || !maPolygons.empty() )
804 {
805 mpPaintOverlay = UserPaintOverlay::create( maUserPaintColor,
807 maContext,
808 std::vector(maPolygons),
811 }
812}
813
814void SlideImpl::drawPolygons() const
815{
816 if( mpPaintOverlay )
817 mpPaintOverlay->drawPolygons();
818}
819
820void SlideImpl::addPolygons(const PolyPolygonVector& rPolygons)
821{
822 maPolygons.insert(maPolygons.end(), rPolygons.begin(), rPolygons.end());
823}
824
825bool SlideImpl::isPaintOverlayActive() const
826{
828}
829
830void SlideImpl::deactivatePaintOverlay()
831{
833 maPolygons = mpPaintOverlay->getPolygons();
834
835 mpPaintOverlay.reset();
836 mbPaintOverlayActive = false;
837}
838
839void SlideImpl::applyShapeAttributes(
840 const css::uno::Reference< css::animations::XAnimationNode >& xRootAnimationNode,
841 bool bInitial) const
842{
843 const uno::Sequence< animations::TargetProperties > aProps(
844 TargetPropertiesCreator::createTargetProperties( xRootAnimationNode, bInitial ) );
845
846 // apply extracted values to our shapes
847 for( const auto& rProp : aProps )
848 {
849 sal_Int16 nParaIndex( -1 );
850 uno::Reference< drawing::XShape > xShape( rProp.Target,
851 uno::UNO_QUERY );
852
853 if( !xShape.is() )
854 {
855 // not a shape target. Maybe a ParagraphTarget?
856 presentation::ParagraphTarget aParaTarget;
857
858 if( rProp.Target >>= aParaTarget )
859 {
860 // yep, ParagraphTarget found - extract shape
861 // and index
862 xShape = aParaTarget.Shape;
863 nParaIndex = aParaTarget.Paragraph;
864 }
865 }
866
867 if( xShape.is() )
868 {
869 ShapeSharedPtr pShape( mpLayerManager->lookupShape( xShape ) );
870
871 if( !pShape )
872 {
873 OSL_FAIL( "SlideImpl::applyInitialShapeAttributes(): no shape found for given target" );
874 continue;
875 }
876
878 ::std::dynamic_pointer_cast< AttributableShape >( pShape ) );
879
880 if( !pAttrShape )
881 {
882 OSL_FAIL( "SlideImpl::applyInitialShapeAttributes(): shape found does not "
883 "implement AttributableShape interface" );
884 continue;
885 }
886
887 if( nParaIndex != -1 )
888 {
889 // our target is a paragraph subset, thus look
890 // this up first.
891 const DocTreeNodeSupplier& rNodeSupplier( pAttrShape->getTreeNodeSupplier() );
892
893 if( rNodeSupplier.getNumberOfTreeNodes(
894 DocTreeNode::NodeType::LogicalParagraph ) <= nParaIndex )
895 {
896 OSL_FAIL( "SlideImpl::applyInitialShapeAttributes(): shape found does not "
897 "provide a subset for requested paragraph index" );
898 continue;
899 }
900
901 pAttrShape = pAttrShape->getSubset(
902 rNodeSupplier.getTreeNode(
903 nParaIndex,
904 DocTreeNode::NodeType::LogicalParagraph ) );
905
906 if( !pAttrShape )
907 {
908 OSL_FAIL( "SlideImpl::applyInitialShapeAttributes(): shape found does not "
909 "provide a subset for requested paragraph index" );
910 continue;
911 }
912 }
913
914 const uno::Sequence< beans::NamedValue >& rShapeProps( rProp.Properties );
915 for( const auto& rShapeProp : rShapeProps )
916 {
917 bool bVisible=false;
918 if( rShapeProp.Name.equalsIgnoreAsciiCase("visibility") &&
919 extractValue( bVisible,
920 rShapeProp.Value,
921 pShape,
922 basegfx::B2DVector(getSlideSize().getWidth(), getSlideSize().getHeight()) ))
923 {
924 pAttrShape->setVisibility( bVisible );
925 }
926 else
927 {
928 OSL_FAIL( "SlideImpl::applyInitialShapeAttributes(): Unexpected "
929 "(and unimplemented) property encountered" );
930 }
931 }
932 }
933 }
934}
935
936bool SlideImpl::applyInitialShapeAttributes(
937 const uno::Reference< animations::XAnimationNode >& xRootAnimationNode )
938{
939 if( !implPrefetchShow() )
940 return false;
941
942 if( !xRootAnimationNode.is() )
943 {
944 meAnimationState = INITIAL_STATE;
945
946 return true; // no animations - no attributes to apply -
947 // succeeded
948 }
949
950 applyShapeAttributes(xRootAnimationNode, true);
951
952 meAnimationState = INITIAL_STATE;
953
954 return true;
955}
956
957bool SlideImpl::loadShapes()
958{
959 if( mbShapesLoaded )
960 return true;
961
963 "SlideImpl::loadShapes(): Invalid draw page" );
965 "SlideImpl::loadShapes(): Invalid layer manager" );
966
967 // fetch desired page content
968 // ==========================
969
970 // also take master page content
971 uno::Reference< drawing::XDrawPage > xMasterPage;
972 uno::Reference< drawing::XShapes > xMasterPageShapes;
973 sal_Int32 nCurrCount(0);
974
975 uno::Reference< drawing::XMasterPageTarget > xMasterPageTarget( mxDrawPage,
976 uno::UNO_QUERY );
977 if( xMasterPageTarget.is() )
978 {
979 xMasterPage = xMasterPageTarget->getMasterPage();
980 xMasterPageShapes = xMasterPage;
981
982 if( xMasterPage.is() && xMasterPageShapes.is() )
983 {
984 // TODO(P2): maybe cache master pages here (or treat the
985 // masterpage as a single metafile. At least currently,
986 // masterpages do not contain animation effects)
987 try
988 {
989 // load the masterpage shapes
990
991 ShapeImporter aMPShapesFunctor( xMasterPage,
994 maContext,
995 0, /* shape num starts at 0 */
996 true );
997
998 mpLayerManager->addShape(
999 aMPShapesFunctor.importBackgroundShape() );
1000
1001 while( !aMPShapesFunctor.isImportDone() )
1002 {
1003 ShapeSharedPtr const& rShape(
1004 aMPShapesFunctor.importShape() );
1005 if( rShape )
1006 {
1007 rShape->setIsForeground(false);
1008 mpLayerManager->addShape( rShape );
1009 }
1010 }
1011 addPolygons(aMPShapesFunctor.getPolygons());
1012
1013 nCurrCount = static_cast<sal_Int32>(aMPShapesFunctor.getImportedShapesCount());
1014 }
1015 catch( uno::RuntimeException& )
1016 {
1017 throw;
1018 }
1019 catch( ShapeLoadFailedException& )
1020 {
1021 // TODO(E2): Error handling. For now, bail out
1022 TOOLS_WARN_EXCEPTION( "slideshow", "SlideImpl::loadShapes(): caught ShapeLoadFailedException" );
1023 return false;
1024
1025 }
1026 catch( uno::Exception& )
1027 {
1028 TOOLS_WARN_EXCEPTION( "slideshow", "" );
1029 return false;
1030 }
1031 }
1032 }
1033
1034 try
1035 {
1036 // load the normal page shapes
1037
1038
1039 ShapeImporter aShapesFunctor( mxDrawPage,
1040 mxDrawPage,
1042 maContext,
1043 nCurrCount,
1044 false );
1045
1046 while( !aShapesFunctor.isImportDone() )
1047 {
1048 ShapeSharedPtr const& rShape(
1049 aShapesFunctor.importShape() );
1050 if( rShape )
1051 mpLayerManager->addShape( rShape );
1052 }
1053 addPolygons(aShapesFunctor.getPolygons());
1054 }
1055 catch( uno::RuntimeException& )
1056 {
1057 throw;
1058 }
1059 catch( ShapeLoadFailedException& )
1060 {
1061 // TODO(E2): Error handling. For now, bail out
1062 TOOLS_WARN_EXCEPTION( "slideshow", "SlideImpl::loadShapes(): caught ShapeLoadFailedException" );
1063 return false;
1064 }
1065 catch( uno::Exception& )
1066 {
1067 TOOLS_WARN_EXCEPTION( "slideshow", "" );
1068 return false;
1069 }
1070
1071 mbShapesLoaded = true;
1072
1073 return true;
1074}
1075
1076basegfx::B2ISize SlideImpl::getSlideSizeImpl() const
1077{
1078 uno::Reference< beans::XPropertySet > xPropSet(
1079 mxDrawPage, uno::UNO_QUERY_THROW );
1080
1081 sal_Int32 nDocWidth = 0;
1082 sal_Int32 nDocHeight = 0;
1083 xPropSet->getPropertyValue("Width") >>= nDocWidth;
1084 xPropSet->getPropertyValue("Height") >>= nDocHeight;
1085
1086 return basegfx::B2ISize( nDocWidth, nDocHeight );
1087}
1088
1089} // namespace
1090
1091
1095 EventQueue& rEventQueue,
1096 EventMultiplexer& rEventMultiplexer,
1097 ScreenUpdater& rScreenUpdater,
1098 ActivitiesQueue& rActivitiesQueue,
1099 UserEventQueue& rUserEventQueue,
1100 CursorManager& rCursorManager,
1101 MediaFileManager& rMediaFileManager,
1102 const UnoViewContainer& rViewContainer,
1103 const uno::Reference< uno::XComponentContext >& xComponentContext,
1104 const ShapeEventListenerMap& rShapeListenerMap,
1105 const ShapeCursorMap& rShapeCursorMap,
1106 PolyPolygonVector&& rPolyPolygonVector,
1107 RGBColor const& rUserPaintColor,
1108 double dUserPaintStrokeWidth,
1109 bool bUserPaintEnabled,
1110 bool bIntrinsicAnimationsAllowed,
1111 bool bDisableAnimationZOrder )
1112{
1113 auto pRet = std::make_shared<SlideImpl>( xDrawPage, xDrawPages, xRootNode, rEventQueue,
1114 rEventMultiplexer, rScreenUpdater,
1115 rActivitiesQueue, rUserEventQueue,
1116 rCursorManager, rMediaFileManager, rViewContainer,
1117 xComponentContext, rShapeListenerMap,
1118 rShapeCursorMap, std::move(rPolyPolygonVector), rUserPaintColor,
1119 dUserPaintStrokeWidth, bUserPaintEnabled,
1120 bIntrinsicAnimationsAllowed,
1121 bDisableAnimationZOrder );
1122
1123 rEventMultiplexer.addViewHandler( pRet );
1124
1125 return pRet;
1126}
1127
1128} // namespace slideshow
1129
1130/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void MakeGraphicsAvailableThreaded(std::vector< Graphic * > &rGraphics)
static GraphicFilter & GetGraphicFilter()
static SdrObject * getSdrObjectFromXShape(const css::uno::Reference< css::uno::XInterface > &xInt)
static BitmapSharedPtr createBitmap(const CanvasSharedPtr &, const ::basegfx::B2ISize &rSize)
This class handles the XSprite updates needed for animations, such as moves, scales etc.
This class multiplexes user-activated and slide-show global events.
void addViewHandler(const ViewEventHandlerWeakPtr &rHandler)
Register an event handler that will be called when views are changed.
This class handles events in a presentation.
Definition: eventqueue.hxx:41
RGB color space class.
Definition: rgbcolor.hxx:35
This class schedules user-activated events.
#define TOOLS_WARN_EXCEPTION(area, stream)
#define ENSURE_OR_RETURN_FALSE(c, m)
#define ENSURE_OR_THROW(c, m)
ARROW
::std::shared_ptr< box2DWorld > Box2DWorldSharedPtr
std::shared_ptr< BitmapCanvas > BitmapCanvasSharedPtr
std::shared_ptr< ::cppcanvas::Bitmap > BitmapSharedPtr
std::shared_ptr< Canvas > CanvasSharedPtr
int i
std::shared_ptr< T > make_shared(Args &&... args)
Slide
ReturnType extractValue(Type nBitField, sal_uInt8 nStartBit, sal_uInt8 nBitCount)
uno::Sequence< animations::TargetProperties > createTargetProperties(const uno::Reference< animations::XAnimationNode > &rootNode, bool bInitial)
Generate shape property list - set bInitial to true for initial slide state.
::std::shared_ptr< class UserPaintOverlay > UserPaintOverlaySharedPtr
::std::vector< ::cppcanvas::PolyPolygonSharedPtr > PolyPolygonVector
::std::shared_ptr< SlideBitmap > SlideBitmapSharedPtr
Definition: slidebitmap.hxx:76
::std::shared_ptr< LayerManager > LayerManagerSharedPtr
basegfx::B2IVector getSlideSizePixel(const basegfx::B2DVector &rSlideSize, const UnoViewSharedPtr &pView)
Definition: tools.cxx:758
::std::map< css::uno::Reference< css::drawing::XShape >, sal_Int16 > ShapeCursorMap
Maps XShape to mouse cursor.
Definition: shapemaps.hxx:43
bool findNamedValue(uno::Sequence< beans::NamedValue > const &rSequence, const beans::NamedValue &rSearchKey)
Definition: tools.cxx:433
::std::map< css::uno::Reference< css::drawing::XShape >, std::shared_ptr< ::comphelper::OInterfaceContainerHelper3< css::presentation::XShapeEventListener > > > ShapeEventListenerMap
Maps XShape to shape listener.
Definition: shapemaps.hxx:39
SlideSharedPtr createSlide(const uno::Reference< drawing::XDrawPage > &xDrawPage, const uno::Reference< drawing::XDrawPagesSupplier > &xDrawPages, const uno::Reference< animations::XAnimationNode > &xRootNode, EventQueue &rEventQueue, EventMultiplexer &rEventMultiplexer, ScreenUpdater &rScreenUpdater, ActivitiesQueue &rActivitiesQueue, UserEventQueue &rUserEventQueue, CursorManager &rCursorManager, MediaFileManager &rMediaFileManager, const UnoViewContainer &rViewContainer, const uno::Reference< uno::XComponentContext > &xComponentContext, const ShapeEventListenerMap &rShapeListenerMap, const ShapeCursorMap &rShapeCursorMap, PolyPolygonVector &&rPolyPolygonVector, RGBColor const &rUserPaintColor, double dUserPaintStrokeWidth, bool bUserPaintEnabled, bool bIntrinsicAnimationsAllowed, bool bDisableAnimationZOrder)
Definition: slideimpl.cxx:1092
::std::shared_ptr< Slide > SlideSharedPtr
Definition: slide.hxx:148
::std::shared_ptr< AttributableShape > AttributableShapeSharedPtr
void initSlideBackground(const ::cppcanvas::CanvasSharedPtr &rCanvas, const ::basegfx::B2ISize &rSize)
Definition: tools.cxx:674
::std::shared_ptr< Shape > ShapeSharedPtr
std::shared_ptr< UnoView > UnoViewSharedPtr
bool for_each_childNode(const css::uno::Reference< css::animations::XAnimationNode > &xNode, Functor &rFunctor)
Apply given functor to every animation node child.
Definition: tools.hxx:365
CursorManager & mrCursorManager
parent cursor manager
Definition: slideimpl.cxx:206
sal_Int16 mnCurrentCursor
Definition: slideimpl.cxx:223
uno::Reference< animations::XAnimationNode > mxRootNode
Definition: slideimpl.cxx:195
uno::Reference< drawing::XDrawPage > mxDrawPage
The page model object.
Definition: slideimpl.cxx:193
std::shared_ptr< SubsettableShapeManager > mpSubsettableShapeManager
Definition: slideimpl.cxx:199
box2d::utils::Box2DWorldSharedPtr mpBox2DWorld
Definition: slideimpl.cxx:200
RGBColor maUserPaintColor
Definition: slideimpl.cxx:212
const basegfx::B2ISize maSlideSize
Definition: slideimpl.cxx:221
LayerManagerSharedPtr mpLayerManager
Definition: slideimpl.cxx:197
std::shared_ptr< ShapeManagerImpl > mpShapeManager
Definition: slideimpl.cxx:198
SlideAnimationState meAnimationState
Definition: slideimpl.cxx:219
bool mbHaveAnimations
True, if this slide is not static.
Definition: slideimpl.cxx:242
bool mbFinalStateApplied
When true, final state attributes are already applied to shapes.
Definition: slideimpl.cxx:260
VectorOfVectorOfSlideBitmaps maSlideBitmaps
Bitmaps with slide content at various states.
Definition: slideimpl.cxx:217
bool mbUserPaintOverlayEnabled
True, when user paint overlay is enabled.
Definition: slideimpl.cxx:229
UserPaintOverlaySharedPtr mpPaintOverlay
Definition: slideimpl.cxx:214
bool mbMainSequenceFound
True, if this slide has a main animation sequence.
Definition: slideimpl.cxx:251
bool mbPaintOverlayActive
When true, enablePaintOverlay was called and mbUserPaintOverlay = true.
Definition: slideimpl.cxx:257
bool mbIntrinsicAnimationsAllowed
True, when intrinsic shape animations are allowed.
Definition: slideimpl.cxx:226
bool mbShowLoaded
True, if initial load of all animation info succeeded.
Definition: slideimpl.cxx:235
bool mbShapesLoaded
True, if initial load of all page shapes succeeded.
Definition: slideimpl.cxx:232
bool mbActive
When true, show() was called. Slide hidden otherwise.
Definition: slideimpl.cxx:254
PolyPolygonVector maPolygons
Definition: slideimpl.cxx:210
double mdUserPaintStrokeWidth
Definition: slideimpl.cxx:213
uno::Reference< animations::XAnimationNode > maMainSequence
Definition: slideimpl.cxx:725
uno::Reference< drawing::XDrawPagesSupplier > mxDrawPagesSupplier
Definition: slideimpl.cxx:194
beans::NamedValue maSearchKey
Definition: slideimpl.cxx:724
SlideAnimations maAnimations
Handles the animation and event generation for us.
Definition: slideimpl.cxx:209
SlideShowContext maContext
Contains common objects needed throughout the slideshow.
Definition: slideimpl.cxx:203
bool bVisible