LCOV - code coverage report
Current view: top level - slideshow/source/engine - slideshowimpl.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 65 719 9.0 %
Date: 2014-11-03 Functions: 13 62 21.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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 <canvas/debug.hxx>
      22             : #include <tools/diagnose_ex.h>
      23             : 
      24             : #include <cppuhelper/basemutex.hxx>
      25             : #include <cppuhelper/compbase1.hxx>
      26             : #include <cppuhelper/factory.hxx>
      27             : #include <cppuhelper/implementationentry.hxx>
      28             : #include <cppuhelper/compbase2.hxx>
      29             : #include <cppuhelper/interfacecontainer.h>
      30             : #include <cppuhelper/exc_hlp.hxx>
      31             : 
      32             : #include <comphelper/anytostring.hxx>
      33             : #include <comphelper/make_shared_from_uno.hxx>
      34             : #include <comphelper/scopeguard.hxx>
      35             : #include <comphelper/optional.hxx>
      36             : #include <comphelper/servicedecl.hxx>
      37             : #include <comphelper/namecontainer.hxx>
      38             : 
      39             : #include <cppcanvas/spritecanvas.hxx>
      40             : #include <cppcanvas/vclfactory.hxx>
      41             : #include <cppcanvas/basegfxfactory.hxx>
      42             : 
      43             : #include <tools/debug.hxx>
      44             : 
      45             : #include <basegfx/point/b2dpoint.hxx>
      46             : #include <basegfx/polygon/b2dpolygon.hxx>
      47             : #include <basegfx/matrix/b2dhommatrix.hxx>
      48             : #include <basegfx/polygon/b2dpolygontools.hxx>
      49             : #include <basegfx/polygon/b2dpolypolygontools.hxx>
      50             : #include <basegfx/tools/canvastools.hxx>
      51             : 
      52             : #include <vcl/font.hxx>
      53             : #include "rtl/ref.hxx"
      54             : 
      55             : #include <com/sun/star/beans/XPropertySet.hpp>
      56             : #include <com/sun/star/util/XModifyListener.hpp>
      57             : #include <com/sun/star/util/XUpdatable.hpp>
      58             : #include <com/sun/star/awt/XPaintListener.hpp>
      59             : #include <com/sun/star/awt/SystemPointer.hpp>
      60             : #include <com/sun/star/animations/TransitionType.hpp>
      61             : #include <com/sun/star/animations/TransitionSubType.hpp>
      62             : #include <com/sun/star/presentation/XSlideShow.hpp>
      63             : #include <com/sun/star/presentation/XSlideShowListener.hpp>
      64             : #include <com/sun/star/lang/XServiceInfo.hpp>
      65             : #include <com/sun/star/lang/XServiceName.hpp>
      66             : #include <com/sun/star/lang/XComponent.hpp>
      67             : #include <com/sun/star/lang/XMultiServiceFactory.hpp>
      68             : #include <com/sun/star/drawing/PointSequenceSequence.hpp>
      69             : #include <com/sun/star/drawing/PointSequence.hpp>
      70             : #include <com/sun/star/drawing/XLayer.hpp>
      71             : #include <com/sun/star/drawing/XLayerSupplier.hpp>
      72             : #include <com/sun/star/drawing/XLayerManager.hpp>
      73             : #include <com/sun/star/container/XNameAccess.hpp>
      74             : 
      75             : #include "com/sun/star/uno/Reference.hxx"
      76             : #include <com/sun/star/loader/CannotActivateFactoryException.hpp>
      77             : 
      78             : #include "unoviewcontainer.hxx"
      79             : #include "transitionfactory.hxx"
      80             : #include "eventmultiplexer.hxx"
      81             : #include "usereventqueue.hxx"
      82             : #include "eventqueue.hxx"
      83             : #include "cursormanager.hxx"
      84             : #include "slideshowcontext.hxx"
      85             : #include "activitiesqueue.hxx"
      86             : #include "activitiesfactory.hxx"
      87             : #include "interruptabledelayevent.hxx"
      88             : #include "slide.hxx"
      89             : #include "shapemaps.hxx"
      90             : #include "slideview.hxx"
      91             : #include "tools.hxx"
      92             : #include "unoview.hxx"
      93             : #include "slidebitmap.hxx"
      94             : #include "rehearsetimingsactivity.hxx"
      95             : #include "waitsymbol.hxx"
      96             : #include "effectrewinder.hxx"
      97             : #include "framerate.hxx"
      98             : #include "pointersymbol.hxx"
      99             : 
     100             : #include <boost/noncopyable.hpp>
     101             : #include <boost/bind.hpp>
     102             : 
     103             : #include <map>
     104             : #include <vector>
     105             : #include <iterator>
     106             : #include <string>
     107             : #include <algorithm>
     108             : #include <stdio.h>
     109             : #include <iostream>
     110             : 
     111             : using namespace com::sun::star;
     112             : using namespace ::slideshow::internal;
     113             : 
     114             : namespace {
     115             : 
     116             : /** During animations the update() method tells its caller to call it as
     117             :     soon as possible.  This gives us more time to render the next frame and
     118             :     still maintain a steady frame rate.  This class is responsible for
     119             :     synchronizing the display of new frames and thus keeping the frame rate
     120             :     steady.
     121             : */
     122           2 : class FrameSynchronization
     123             : {
     124             : public:
     125             :     /** Create new object with a predefined duration between two frames.
     126             :         @param nFrameDuration
     127             :             The preferred duration between the display of two frames in
     128             :             seconds.
     129             :     */
     130             :     FrameSynchronization (const double nFrameDuration);
     131             : 
     132             :     /** Set the current time as the time at which the current frame is
     133             :         displayed.  From this the target time of the next frame is derived.
     134             :     */
     135             :     void MarkCurrentFrame (void);
     136             : 
     137             :     /** When there is time left until the next frame is due then wait.
     138             :         Otherwise return without delay.
     139             :     */
     140             :     void Synchronize (void);
     141             : 
     142             :     /** Activate frame synchronization when an animation is active and
     143             :         frames are to be displayed in a steady rate.  While active
     144             :         Synchronize() will wait until the frame duration time has passed.
     145             :     */
     146             :     void Activate (void);
     147             : 
     148             :     /** Deactivate frame sychronization when no animation is active and the
     149             :         time between frames depends on user actions and other external
     150             :         sources.  While deactivated Synchronize() will return without delay.
     151             :     */
     152             :     void Deactivate (void);
     153             : 
     154             : private:
     155             :     /** The timer that is used for synchronization is independent from the
     156             :         one used by SlideShowImpl: it is not paused or modified by
     157             :         animations.
     158             :     */
     159             :     canvas::tools::ElapsedTime maTimer;
     160             :     /** Time between the display of frames.  Enforced only when mbIsActive
     161             :         is <TRUE/>.
     162             :     */
     163             :     const double mnFrameDuration;
     164             :     /** Time (of maTimer) when the next frame shall be displayed.
     165             :         Synchronize() will wait until this time.
     166             :     */
     167             :     double mnNextFrameTargetTime;
     168             :     /** Synchronize() will wait only when this flag is <TRUE/>.  Otherwise
     169             :         it returns immediately.
     170             :     */
     171             :     bool mbIsActive;
     172             : };
     173             : 
     174             : /******************************************************************************
     175             : 
     176             :    SlideShowImpl
     177             : 
     178             :    This class encapsulates the slideshow presentation viewer.
     179             : 
     180             :    With an instance of this class, it is possible to statically
     181             :    and dynamically show a presentation, as defined by the
     182             :    constructor-provided draw model (represented by a sequence
     183             :    of ::com::sun::star::drawing::XDrawPage objects).
     184             : 
     185             :    It is possible to show the presentation on multiple views
     186             :    simultaneously (e.g. for a multi-monitor setup). Since this
     187             :    class also relies on user interaction, the corresponding
     188             :    XSlideShowView interface provides means to register some UI
     189             :    event listeners (mostly borrowed from awt::XWindow interface).
     190             : 
     191             :    Since currently (mid 2004), OOo isn't very well suited to
     192             :    multi-threaded rendering, this class relies on <em>very
     193             :    frequent</em> external update() calls, which will render the
     194             :    next frame of animations. This works as follows: after the
     195             :    displaySlide() has been successfully called (which setup and
     196             :    starts an actual slide show), the update() method must be
     197             :    called until it returns false.
     198             :    Effectively, this puts the burden of providing
     199             :    concurrency to the clients of this class, which, as noted
     200             :    above, is currently unavoidable with the current state of
     201             :    affairs (I've actually tried threading here, but failed
     202             :    miserably when using the VCL canvas as the render backend -
     203             :    deadlocked).
     204             : 
     205             :  ******************************************************************************/
     206             : 
     207             : typedef cppu::WeakComponentImplHelper1<presentation::XSlideShow> SlideShowImplBase;
     208             : 
     209             : typedef ::std::vector< ::cppcanvas::PolyPolygonSharedPtr> PolyPolygonVector;
     210             : 
     211             : /// Maps XDrawPage for annotations persistence
     212             : typedef ::std::map< ::com::sun::star::uno::Reference<
     213             :                                     ::com::sun::star::drawing::XDrawPage>,
     214             :                                     PolyPolygonVector>  PolygonMap;
     215             : 
     216           2 : class SlideShowImpl : private cppu::BaseMutex,
     217             :                       public CursorManager,
     218             :                       public SlideShowImplBase
     219             : {
     220             : public:
     221             :     explicit SlideShowImpl(
     222             :         uno::Reference<uno::XComponentContext> const& xContext );
     223             : 
     224             :     /** Notify that the transition phase of the current slide
     225             :         has ended.
     226             : 
     227             :         The life of a slide has three phases: the transition
     228             :         phase, when the previous slide vanishes, and the
     229             :         current slide becomes visible, the shape animation
     230             :         phase, when shape effects are running, and the phase
     231             :         after the last shape animation has ended, but before
     232             :         the next slide transition starts.
     233             : 
     234             :         This method notifies the end of the first phase.
     235             : 
     236             :         @param bPaintSlide
     237             :         When true, Slide::show() is passed a true as well, denoting
     238             :         explicit paint of slide content. Pass false here, if e.g. a
     239             :         slide transition has already rendered the initial slide image.
     240             :     */
     241             :     void notifySlideTransitionEnded( bool bPaintSlide );
     242             : 
     243             :     /** Notify that the shape animation phase of the current slide
     244             :         has ended.
     245             : 
     246             :         The life of a slide has three phases: the transition
     247             :         phase, when the previous slide vanishes, and the
     248             :         current slide becomes visible, the shape animation
     249             :         phase, when shape effects are running, and the phase
     250             :         after the last shape animation has ended, but before
     251             :         the next slide transition starts.
     252             : 
     253             :         This method notifies the end of the second phase.
     254             :     */
     255             :     void notifySlideAnimationsEnded();
     256             : 
     257             :     /** Notify that the slide has ended.
     258             : 
     259             :         The life of a slide has three phases: the transition
     260             :         phase, when the previous slide vanishes, and the
     261             :         current slide becomes visible, the shape animation
     262             :         phase, when shape effects are running, and the phase
     263             :         after the last shape animation has ended, but before
     264             :         the next slide transition starts.
     265             : 
     266             :         This method notifies the end of the third phase.
     267             :     */
     268             :     void notifySlideEnded (const bool bReverse);
     269             : 
     270             :     /** Notification from eventmultiplexer that a hyperlink
     271             :         has been clicked.
     272             :     */
     273             :     bool notifyHyperLinkClicked( OUString const& hyperLink );
     274             : 
     275             :     /** Notification from eventmultiplexer that an animation event has occoured.
     276             :         This will be forewarded to all registered XSlideShowListener
     277             :      */
     278             :     bool handleAnimationEvent( const AnimationNodeSharedPtr& rNode );
     279             : 
     280             : private:
     281             :     // XSlideShow:
     282             :     virtual sal_Bool SAL_CALL nextEffect() throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
     283             :     virtual sal_Bool SAL_CALL previousEffect() throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
     284             :     virtual sal_Bool SAL_CALL startShapeActivity(
     285             :         uno::Reference<drawing::XShape> const& xShape )
     286             :         throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
     287             :     virtual sal_Bool SAL_CALL stopShapeActivity(
     288             :         uno::Reference<drawing::XShape> const& xShape )
     289             :         throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
     290             :     virtual sal_Bool SAL_CALL pause( sal_Bool bPauseShow )
     291             :         throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
     292             :     virtual uno::Reference<drawing::XDrawPage> SAL_CALL getCurrentSlide()
     293             :         throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
     294             :     virtual void SAL_CALL displaySlide(
     295             :         uno::Reference<drawing::XDrawPage> const& xSlide,
     296             :         uno::Reference<drawing::XDrawPagesSupplier> const& xDrawPages,
     297             :         uno::Reference<animations::XAnimationNode> const& xRootNode,
     298             :         uno::Sequence<beans::PropertyValue> const& rProperties )
     299             :         throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
     300             :     virtual void SAL_CALL registerUserPaintPolygons( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xDocFactory ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
     301             :     virtual sal_Bool SAL_CALL setProperty(
     302             :         beans::PropertyValue const& rProperty ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
     303             :     virtual sal_Bool SAL_CALL addView(
     304             :         uno::Reference<presentation::XSlideShowView> const& xView )
     305             :         throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
     306             :     virtual sal_Bool SAL_CALL removeView(
     307             :         uno::Reference<presentation::XSlideShowView> const& xView )
     308             :         throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
     309             :     virtual sal_Bool SAL_CALL update( double & nNextTimeout )
     310             :         throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
     311             :     virtual void SAL_CALL addSlideShowListener(
     312             :         uno::Reference<presentation::XSlideShowListener> const& xListener )
     313             :         throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
     314             :     virtual void SAL_CALL removeSlideShowListener(
     315             :         uno::Reference<presentation::XSlideShowListener> const& xListener )
     316             :         throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
     317             :     virtual void SAL_CALL addShapeEventListener(
     318             :         uno::Reference<presentation::XShapeEventListener> const& xListener,
     319             :         uno::Reference<drawing::XShape> const& xShape )
     320             :         throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
     321             :     virtual void SAL_CALL removeShapeEventListener(
     322             :         uno::Reference<presentation::XShapeEventListener> const& xListener,
     323             :         uno::Reference<drawing::XShape> const& xShape )
     324             :         throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
     325             :     virtual void SAL_CALL setShapeCursor(
     326             :         uno::Reference<drawing::XShape> const& xShape, sal_Int16 nPointerShape )
     327             :         throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
     328             : 
     329             :     // CursorManager
     330             : 
     331             : 
     332             :     virtual bool requestCursor( sal_Int16 nCursorShape ) SAL_OVERRIDE;
     333             :     virtual void resetCursor() SAL_OVERRIDE;
     334             : 
     335             :     /** This is somewhat similar to displaySlide when called for the current
     336             :         slide.  It has been simplified to take advantage of that no slide
     337             :         change takes place.  Furthermore it does not show the slide
     338             :         transition.
     339             :     */
     340             :     void redisplayCurrentSlide (void);
     341             : 
     342             : protected:
     343             :     // WeakComponentImplHelperBase
     344             :     virtual void SAL_CALL disposing() SAL_OVERRIDE;
     345             : 
     346           0 :     bool isDisposed() const
     347             :     {
     348           0 :         return (rBHelper.bDisposed || rBHelper.bInDispose);
     349             :     }
     350             : 
     351             : private:
     352             :     struct SeparateListenerImpl; friend struct SeparateListenerImpl;
     353             :     class PrefetchPropertiesFunc; friend class PrefetchPropertiesFunc;
     354             : 
     355             :     /// Stop currently running show.
     356             :     void stopShow();
     357             : 
     358             :     ///Find a polygons vector in maPolygons (map)
     359             :     PolygonMap::iterator findPolygons( uno::Reference<drawing::XDrawPage> const& xDrawPage);
     360             : 
     361             :     /// Creates a new slide.
     362             :     SlideSharedPtr makeSlide(
     363             :         uno::Reference<drawing::XDrawPage> const& xDrawPage,
     364             :         uno::Reference<drawing::XDrawPagesSupplier> const& xDrawPages,
     365             :         uno::Reference<animations::XAnimationNode> const& xRootNode );
     366             : 
     367             :     /// Checks whether the given slide/animation node matches mpPrefetchSlide
     368           0 :     static bool matches(
     369             :         SlideSharedPtr const& pSlide,
     370             :         uno::Reference<drawing::XDrawPage> const& xSlide,
     371             :         uno::Reference<animations::XAnimationNode> const& xNode )
     372             :     {
     373           0 :         if (pSlide)
     374           0 :             return (pSlide->getXDrawPage() == xSlide &&
     375           0 :                     pSlide->getXAnimationNode() == xNode);
     376             :         else
     377           0 :             return (!xSlide.is() && !xNode.is());
     378             :     }
     379             : 
     380             :     /// Resets the current slide transition sound object with a new one:
     381             :     SoundPlayerSharedPtr resetSlideTransitionSound(
     382             :         uno::Any const& url = uno::Any(), bool bLoopSound = false );
     383             : 
     384             :     /// stops the current slide transition sound
     385             :     void stopSlideTransitionSound();
     386             : 
     387             :     /** Prepare a slide transition
     388             : 
     389             :         This method registers all necessary events and
     390             :         activities for a slide transition.
     391             : 
     392             :         @return the slide change activity, or NULL for no transition effect
     393             :     */
     394             :     ActivitySharedPtr createSlideTransition(
     395             :         const uno::Reference< drawing::XDrawPage >&    xDrawPage,
     396             :         const SlideSharedPtr&                          rLeavingSlide,
     397             :         const SlideSharedPtr&                          rEnteringSlide,
     398             :         const EventSharedPtr&                          rTransitionEndEvent );
     399             : 
     400             :     /** Request/release the wait symbol.  The wait symbol is displayed when
     401             :         there are more requests then releases.  Locking the wait symbol
     402             :         helps to avoid intermediate repaints.
     403             : 
     404             :         Do not call this method directly.  Use WaitSymbolLock instead.
     405             :     */
     406             :     void requestWaitSymbol (void);
     407             :     void releaseWaitSymbol (void);
     408             : 
     409             :     class WaitSymbolLock {public:
     410           0 :         WaitSymbolLock(SlideShowImpl& rSlideShowImpl) : mrSlideShowImpl(rSlideShowImpl)
     411           0 :             { mrSlideShowImpl.requestWaitSymbol(); }
     412           0 :         ~WaitSymbolLock(void)
     413           0 :             { mrSlideShowImpl.releaseWaitSymbol(); }
     414             :     private: SlideShowImpl& mrSlideShowImpl;
     415             :     };
     416             : 
     417             :     /// Filter requested cursor shape against hard slideshow cursors (wait, etc.)
     418             :     sal_Int16 calcActiveCursor( sal_Int16 nCursorShape ) const;
     419             : 
     420             :     /** This method is called asynchronously to finish the rewinding of an
     421             :         effect to the previous slide that was initiated earlier.
     422             :     */
     423             :     void rewindEffectToPreviousSlide (void);
     424             : 
     425             :     /// all registered views
     426             :     UnoViewContainer                        maViewContainer;
     427             : 
     428             :     /// all registered slide show listeners
     429             :     cppu::OInterfaceContainerHelper         maListenerContainer;
     430             : 
     431             :     /// map of vectors, containing all registered listeners for a shape
     432             :     ShapeEventListenerMap                   maShapeEventListeners;
     433             :     /// map of sal_Int16 values, specifying the mouse cursor for every shape
     434             :     ShapeCursorMap                          maShapeCursors;
     435             : 
     436             :     //map of vector of Polygons, containing polygons drawn on each slide.
     437             :     PolygonMap                              maPolygons;
     438             : 
     439             :     boost::optional<RGBColor>               maUserPaintColor;
     440             : 
     441             :     double                                  maUserPaintStrokeWidth;
     442             : 
     443             :     //changed for the eraser project
     444             :     boost::optional<bool>           maEraseAllInk;
     445             :     boost::optional<bool>           maSwitchPenMode;
     446             :     boost::optional<bool>           maSwitchEraserMode;
     447             :     boost::optional<sal_Int32>          maEraseInk;
     448             :     //end changed
     449             : 
     450             :     boost::shared_ptr<canvas::tools::ElapsedTime> mpPresTimer;
     451             :     ScreenUpdater                           maScreenUpdater;
     452             :     EventQueue                              maEventQueue;
     453             :     EventMultiplexer                        maEventMultiplexer;
     454             :     ActivitiesQueue                         maActivitiesQueue;
     455             :     UserEventQueue                          maUserEventQueue;
     456             :     SubsettableShapeManagerSharedPtr        mpDummyPtr;
     457             : 
     458             :     boost::shared_ptr<SeparateListenerImpl> mpListener;
     459             : 
     460             :     boost::shared_ptr<RehearseTimingsActivity> mpRehearseTimingsActivity;
     461             :     boost::shared_ptr<WaitSymbol>           mpWaitSymbol;
     462             : 
     463             :     boost::shared_ptr<PointerSymbol>        mpPointerSymbol;
     464             : 
     465             :     /// the current slide transition sound object:
     466             :     SoundPlayerSharedPtr                    mpCurrentSlideTransitionSound;
     467             : 
     468             :     uno::Reference<uno::XComponentContext>  mxComponentContext;
     469             :     uno::Reference<
     470             :         presentation::XTransitionFactory>   mxOptionalTransitionFactory;
     471             : 
     472             :     /// the previously running slide
     473             :     SlideSharedPtr                          mpPreviousSlide;
     474             :     /// the currently running slide
     475             :     SlideSharedPtr                          mpCurrentSlide;
     476             :     /// the already prefetched slide: best candidate for upcoming slide
     477             :     SlideSharedPtr                          mpPrefetchSlide;
     478             :     /// slide to be prefetched: best candidate for upcoming slide
     479             :     uno::Reference<drawing::XDrawPage>      mxPrefetchSlide;
     480             :     ///  save the XDrawPagesSupplier to retieve polygons
     481             :     uno::Reference<drawing::XDrawPagesSupplier>  mxDrawPagesSupplier;
     482             :     /// slide animation to be prefetched:
     483             :     uno::Reference<animations::XAnimationNode> mxPrefetchAnimationNode;
     484             : 
     485             :     sal_Int16                               mnCurrentCursor;
     486             : 
     487             :     sal_Int32                               mnWaitSymbolRequestCount;
     488             :     bool                                    mbAutomaticAdvancementMode;
     489             :     bool                                    mbImageAnimationsAllowed;
     490             :     bool                                    mbNoSlideTransitions;
     491             :     bool                                    mbMouseVisible;
     492             :     bool                                    mbForceManualAdvance;
     493             :     bool                                    mbShowPaused;
     494             :     bool                                    mbSlideShowIdle;
     495             :     bool                                    mbDisableAnimationZOrder;
     496             : 
     497             :     EffectRewinder                          maEffectRewinder;
     498             :     FrameSynchronization                    maFrameSynchronization;
     499             : };
     500             : 
     501             : /** Separate event listener for animation, view and hyperlink events.
     502             : 
     503             :     This handler is registered for slide animation end, view and
     504             :     hyperlink events at the global EventMultiplexer, and forwards
     505             :     notifications to the SlideShowImpl
     506             : */
     507           4 : struct SlideShowImpl::SeparateListenerImpl : public EventHandler,
     508             :                                              public ViewRepaintHandler,
     509             :                                              public HyperlinkHandler,
     510             :                                              public AnimationEventHandler,
     511             :                                              private boost::noncopyable
     512             : {
     513             :     SlideShowImpl& mrShow;
     514             :     ScreenUpdater& mrScreenUpdater;
     515             :     EventQueue&    mrEventQueue;
     516             : 
     517           2 :     SeparateListenerImpl( SlideShowImpl& rShow,
     518             :                           ScreenUpdater& rScreenUpdater,
     519             :                           EventQueue&    rEventQueue ) :
     520             :         mrShow( rShow ),
     521             :         mrScreenUpdater( rScreenUpdater ),
     522           2 :         mrEventQueue( rEventQueue )
     523           2 :     {}
     524             : 
     525             :     // EventHandler
     526           0 :     virtual bool handleEvent() SAL_OVERRIDE
     527             :     {
     528             :         // DON't call notifySlideAnimationsEnded()
     529             :         // directly, but queue an event. handleEvent()
     530             :         // might be called from e.g.
     531             :         // showNext(), and notifySlideAnimationsEnded() must not be called
     532             :         // in recursion.  Note that the event is scheduled for the next
     533             :         // frame so that its expensive execution does not come in between
     534             :         // sprite hiding and shape redraw (at the end of the animation of a
     535             :         // shape), which would cause a flicker.
     536             :         mrEventQueue.addEventForNextRound(
     537           0 :             makeEvent(
     538             :                 boost::bind( &SlideShowImpl::notifySlideAnimationsEnded, boost::ref(mrShow) ),
     539           0 :                 "SlideShowImpl::notifySlideAnimationsEnded"));
     540           0 :         return true;
     541             :     }
     542             : 
     543             :     // ViewRepaintHandler
     544           0 :     virtual void viewClobbered( const UnoViewSharedPtr& rView ) SAL_OVERRIDE
     545             :     {
     546             :         // given view needs repaint, request update
     547           0 :         mrScreenUpdater.notifyUpdate(rView, true);
     548           0 :     }
     549             : 
     550             :     // HyperlinkHandler
     551           0 :     virtual bool handleHyperlink( OUString const& rLink ) SAL_OVERRIDE
     552             :     {
     553           0 :         return mrShow.notifyHyperLinkClicked(rLink);
     554             :     }
     555             : 
     556             :     // AnimationEventHandler
     557           0 :     virtual bool handleAnimationEvent( const AnimationNodeSharedPtr& rNode ) SAL_OVERRIDE
     558             :     {
     559           0 :         return mrShow.handleAnimationEvent(rNode);
     560             :     }
     561             : };
     562             : 
     563           2 : SlideShowImpl::SlideShowImpl(
     564             :     uno::Reference<uno::XComponentContext> const& xContext )
     565             :     : SlideShowImplBase(m_aMutex),
     566             :       maViewContainer(),
     567             :       maListenerContainer( m_aMutex ),
     568             :       maShapeEventListeners(),
     569             :       maShapeCursors(),
     570             :       maUserPaintColor(),
     571             :       maUserPaintStrokeWidth(4.0),
     572           2 :       mpPresTimer( new canvas::tools::ElapsedTime ),
     573             :       maScreenUpdater(maViewContainer),
     574             :       maEventQueue( mpPresTimer ),
     575             :       maEventMultiplexer( maEventQueue,
     576             :                           maViewContainer ),
     577             :       maActivitiesQueue( mpPresTimer ),
     578             :       maUserEventQueue( maEventMultiplexer,
     579             :                         maEventQueue,
     580             :                         *this ),
     581             :       mpDummyPtr(),
     582             :       mpListener(),
     583             :       mpRehearseTimingsActivity(),
     584             :       mpWaitSymbol(),
     585             :       mpPointerSymbol(),
     586             :       mpCurrentSlideTransitionSound(),
     587             :       mxComponentContext( xContext ),
     588             :       mxOptionalTransitionFactory(),
     589             :       mpCurrentSlide(),
     590             :       mpPrefetchSlide(),
     591             :       mxPrefetchSlide(),
     592             :       mxDrawPagesSupplier(),
     593             :       mxPrefetchAnimationNode(),
     594             :       mnCurrentCursor(awt::SystemPointer::ARROW),
     595             :       mnWaitSymbolRequestCount(0),
     596             :       mbAutomaticAdvancementMode(false),
     597             :       mbImageAnimationsAllowed( true ),
     598             :       mbNoSlideTransitions( false ),
     599             :       mbMouseVisible( true ),
     600             :       mbForceManualAdvance( false ),
     601             :       mbShowPaused( false ),
     602             :       mbSlideShowIdle( true ),
     603             :       mbDisableAnimationZOrder( false ),
     604             :       maEffectRewinder(maEventMultiplexer, maEventQueue, maUserEventQueue),
     605           4 :       maFrameSynchronization(1.0 / FrameRate::PreferredFramesPerSecond)
     606             : 
     607             : {
     608             :     // keep care not constructing any UNO references to this inside ctor,
     609             :     // shift that code to create()!
     610             : 
     611             :     uno::Reference<lang::XMultiComponentFactory> xFactory(
     612           2 :         mxComponentContext->getServiceManager() );
     613             : 
     614           2 :     if( xFactory.is() )
     615             :     {
     616             :         try
     617             :     {
     618             :             // #i82460# try to retrieve special transition factory
     619             :             mxOptionalTransitionFactory.set(
     620           2 :                 xFactory->createInstanceWithContext(
     621             :                     OUString("com.sun.star.presentation.TransitionFactory" ),
     622           2 :                     mxComponentContext ),
     623           2 :                 uno::UNO_QUERY );
     624             :         }
     625           0 :         catch (loader::CannotActivateFactoryException const&)
     626             :     {
     627             :     }
     628             :     }
     629             : 
     630             :     mpListener.reset( new SeparateListenerImpl(
     631             :                           *this,
     632             :                           maScreenUpdater,
     633           2 :                           maEventQueue ));
     634           2 :     maEventMultiplexer.addSlideAnimationsEndHandler( mpListener );
     635           2 :     maEventMultiplexer.addViewRepaintHandler( mpListener );
     636           2 :     maEventMultiplexer.addHyperlinkHandler( mpListener, 0.0 );
     637           2 :     maEventMultiplexer.addAnimationStartHandler( mpListener );
     638           2 :     maEventMultiplexer.addAnimationEndHandler( mpListener );
     639           2 : }
     640             : 
     641             : // we are about to be disposed (someone call dispose() on us)
     642           2 : void SlideShowImpl::disposing()
     643             : {
     644           2 :     osl::MutexGuard const guard( m_aMutex );
     645             : 
     646           2 :     maEffectRewinder.dispose();
     647             : 
     648             :     // stop slide transition sound, if any:
     649           2 :     stopSlideTransitionSound();
     650             : 
     651           2 :     mxComponentContext.clear();
     652             : 
     653           2 :     if( mpCurrentSlideTransitionSound )
     654             :     {
     655           0 :         mpCurrentSlideTransitionSound->dispose();
     656           0 :         mpCurrentSlideTransitionSound.reset();
     657             :     }
     658             : 
     659           2 :     mpWaitSymbol.reset();
     660           2 :     mpPointerSymbol.reset();
     661             : 
     662           2 :     if( mpRehearseTimingsActivity )
     663             :     {
     664           0 :         mpRehearseTimingsActivity->dispose();
     665           0 :         mpRehearseTimingsActivity.reset();
     666             :     }
     667             : 
     668           2 :     if( mpListener )
     669             :     {
     670           2 :         maEventMultiplexer.removeSlideAnimationsEndHandler(mpListener);
     671           2 :         maEventMultiplexer.removeViewRepaintHandler(mpListener);
     672           2 :         maEventMultiplexer.removeHyperlinkHandler(mpListener);
     673           2 :         maEventMultiplexer.removeAnimationStartHandler( mpListener );
     674           2 :         maEventMultiplexer.removeAnimationEndHandler( mpListener );
     675             : 
     676           2 :         mpListener.reset();
     677             :     }
     678             : 
     679           2 :     maUserEventQueue.clear();
     680           2 :     maActivitiesQueue.clear();
     681           2 :     maEventMultiplexer.clear();
     682           2 :     maEventQueue.clear();
     683           2 :     mpPresTimer.reset();
     684           2 :     maShapeCursors.clear();
     685           2 :     maShapeEventListeners.clear();
     686             : 
     687             :     // send all listeners a disposing() that we are going down:
     688             :     maListenerContainer.disposeAndClear(
     689           2 :         lang::EventObject( static_cast<cppu::OWeakObject *>(this) ) );
     690             : 
     691           2 :     maViewContainer.dispose();
     692             : 
     693             :     // release slides:
     694           2 :     mxPrefetchAnimationNode.clear();
     695           2 :     mxPrefetchSlide.clear();
     696           2 :     mpPrefetchSlide.reset();
     697           2 :     mpCurrentSlide.reset();
     698           2 :     mpPreviousSlide.reset();
     699           2 : }
     700             : 
     701             : /// stops the current slide transition sound
     702           2 : void SlideShowImpl::stopSlideTransitionSound()
     703             : {
     704           2 :     if (mpCurrentSlideTransitionSound)
     705             :     {
     706           0 :         mpCurrentSlideTransitionSound->stopPlayback();
     707           0 :         mpCurrentSlideTransitionSound->dispose();
     708           0 :         mpCurrentSlideTransitionSound.reset();
     709             :     }
     710           2 :  }
     711             : 
     712           0 : SoundPlayerSharedPtr SlideShowImpl::resetSlideTransitionSound( const uno::Any& rSound, bool bLoopSound )
     713             : {
     714           0 :     bool bStopSound = false;
     715           0 :     OUString url;
     716             : 
     717           0 :     if( !(rSound >>= bStopSound) )
     718           0 :         bStopSound = false;
     719           0 :     rSound >>= url;
     720             : 
     721           0 :     if( !bStopSound && url.isEmpty() )
     722           0 :         return SoundPlayerSharedPtr();
     723             : 
     724           0 :     stopSlideTransitionSound();
     725             : 
     726           0 :     if (!url.isEmpty())
     727             :     {
     728             :         try
     729             :         {
     730           0 :             mpCurrentSlideTransitionSound = SoundPlayer::create(
     731           0 :                 maEventMultiplexer, url, mxComponentContext );
     732           0 :             mpCurrentSlideTransitionSound->setPlaybackLoop( bLoopSound );
     733             :         }
     734           0 :         catch (lang::NoSupportException const&)
     735             :         {
     736             :             // catch possible exceptions from SoundPlayer, since
     737             :             // being not able to playback the sound is not a hard
     738             :             // error here (still, the slide transition should be
     739             :             // shown).
     740             :         }
     741             :     }
     742           0 :     return mpCurrentSlideTransitionSound;
     743             : }
     744             : 
     745           0 : ActivitySharedPtr SlideShowImpl::createSlideTransition(
     746             :     const uno::Reference< drawing::XDrawPage >& xDrawPage,
     747             :     const SlideSharedPtr&                       rLeavingSlide,
     748             :     const SlideSharedPtr&                       rEnteringSlide,
     749             :     const EventSharedPtr&                       rTransitionEndEvent)
     750             : {
     751           0 :     ENSURE_OR_THROW( !maViewContainer.empty(),
     752             :                       "createSlideTransition(): No views" );
     753           0 :     ENSURE_OR_THROW( rEnteringSlide,
     754             :                       "createSlideTransition(): No entering slide" );
     755             : 
     756             :     // return empty transition, if slide transitions
     757             :     // are disabled.
     758           0 :     if (mbNoSlideTransitions)
     759           0 :         return ActivitySharedPtr();
     760             : 
     761             :     // retrieve slide change parameters from XDrawPage
     762             :     uno::Reference< beans::XPropertySet > xPropSet( xDrawPage,
     763           0 :                                                     uno::UNO_QUERY );
     764             : 
     765           0 :     if( !xPropSet.is() )
     766             :     {
     767             :         OSL_TRACE( "createSlideTransition(): "
     768             :                    "Slide has no PropertySet - assuming no transition\n" );
     769           0 :         return ActivitySharedPtr();
     770             :     }
     771             : 
     772           0 :     sal_Int16 nTransitionType(0);
     773           0 :     if( !getPropertyValue( nTransitionType,
     774             :                            xPropSet,
     775           0 :                            "TransitionType") )
     776             :     {
     777             :         OSL_TRACE( "createSlideTransition(): "
     778             :                    "Could not extract slide transition type from XDrawPage - assuming no transition\n" );
     779           0 :         return ActivitySharedPtr();
     780             :     }
     781             : 
     782           0 :     sal_Int16 nTransitionSubType(0);
     783           0 :     if( !getPropertyValue( nTransitionSubType,
     784             :                            xPropSet,
     785           0 :                            "TransitionSubtype") )
     786             :     {
     787             :         OSL_TRACE( "createSlideTransition(): "
     788             :                    "Could not extract slide transition subtype from XDrawPage - assuming no transition\n" );
     789           0 :         return ActivitySharedPtr();
     790             :     }
     791             : 
     792           0 :     bool bTransitionDirection(false);
     793           0 :     if( !getPropertyValue( bTransitionDirection,
     794             :                            xPropSet,
     795           0 :                            "TransitionDirection") )
     796             :     {
     797             :         OSL_TRACE( "createSlideTransition(): "
     798             :                    "Could not extract slide transition direction from XDrawPage - assuming default direction\n" );
     799             :     }
     800             : 
     801           0 :     sal_Int32 aUnoColor(0);
     802           0 :     if( !getPropertyValue( aUnoColor,
     803             :                            xPropSet,
     804           0 :                            "TransitionFadeColor") )
     805             :     {
     806             :         OSL_TRACE( "createSlideTransition(): "
     807             :                    "Could not extract slide transition fade color from XDrawPage - assuming black\n" );
     808             :     }
     809             : 
     810           0 :     const RGBColor aTransitionFadeColor( unoColor2RGBColor( aUnoColor ));
     811             : 
     812           0 :     uno::Any aSound;
     813           0 :     bool bLoopSound = false;
     814             : 
     815           0 :     if( !getPropertyValue( aSound, xPropSet, "Sound") )
     816             :         OSL_TRACE( "createSlideTransition(): Could not determine transition sound effect URL from XDrawPage - using no sound" );
     817             : 
     818           0 :     if( !getPropertyValue( bLoopSound, xPropSet, "LoopSound" ) )
     819             :         OSL_TRACE( "createSlideTransition(): Could not get slide property 'LoopSound' - using no sound" );
     820             : 
     821             :     NumberAnimationSharedPtr pTransition(
     822             :         TransitionFactory::createSlideTransition(
     823             :             rLeavingSlide,
     824             :             rEnteringSlide,
     825             :             maViewContainer,
     826             :             maScreenUpdater,
     827             :             maEventMultiplexer,
     828             :             mxOptionalTransitionFactory,
     829             :             nTransitionType,
     830             :             nTransitionSubType,
     831             :             bTransitionDirection,
     832             :             aTransitionFadeColor,
     833           0 :             resetSlideTransitionSound( aSound, bLoopSound ) ));
     834             : 
     835           0 :     if( !pTransition )
     836           0 :         return ActivitySharedPtr(); // no transition effect has been
     837             :                                     // generated. Normally, that means
     838             :                                     // that simply no transition is
     839             :                                     // set on this slide.
     840             : 
     841           0 :     double nTransitionDuration(0.0);
     842           0 :     if( !getPropertyValue( nTransitionDuration,
     843             :                            xPropSet,
     844           0 :                            "TransitionDuration") )
     845             :     {
     846             :         OSL_TRACE( "createSlideTransition(): "
     847             :                    "Could not extract slide transition duration from XDrawPage - assuming no transition\n" );
     848           0 :         return ActivitySharedPtr();
     849             :     }
     850             : 
     851           0 :     sal_Int32 nMinFrames(5);
     852           0 :     if( !getPropertyValue( nMinFrames,
     853             :                            xPropSet,
     854           0 :                            "MinimalFrameNumber") )
     855             :     {
     856             :         OSL_TRACE( "createSlideTransition(): "
     857             :                    "No minimal number of frames given - assuming 5\n" );
     858             :     }
     859             : 
     860             :     // prefetch slide transition bitmaps, but postpone it after
     861             :     // displaySlide() has finished - sometimes, view size has not yet
     862             :     // reached final size
     863             :     maEventQueue.addEvent(
     864             :         makeEvent(
     865             :             boost::bind(
     866             :                 &::slideshow::internal::Animation::prefetch,
     867             :                 pTransition,
     868             :                 AnimatableShapeSharedPtr(),
     869             :                 ShapeAttributeLayerSharedPtr()),
     870           0 :             "Animation::prefetch"));
     871             : 
     872             :     return ActivitySharedPtr(
     873             :         ActivitiesFactory::createSimpleActivity(
     874             :             ActivitiesFactory::CommonParameters(
     875             :                 rTransitionEndEvent,
     876             :                 maEventQueue,
     877             :                 maActivitiesQueue,
     878             :                 nTransitionDuration,
     879             :                 nMinFrames,
     880             :                 false,
     881             :                 boost::optional<double>(1.0),
     882             :                 0.0,
     883             :                 0.0,
     884             :                 ShapeSharedPtr(),
     885           0 :                 basegfx::B2DSize( rEnteringSlide->getSlideSize() ) ),
     886             :             pTransition,
     887           0 :             true ));
     888             : }
     889             : 
     890           0 : PolygonMap::iterator SlideShowImpl::findPolygons( uno::Reference<drawing::XDrawPage> const& xDrawPage)
     891             : {
     892             :     // TODO(P2) : Optimze research in the map.
     893           0 :     bool bFound = false;
     894           0 :     PolygonMap::iterator aIter=maPolygons.begin();
     895             : 
     896           0 :     while(aIter!=maPolygons.end() && !bFound)
     897             :     {
     898           0 :         if(aIter->first == xDrawPage)
     899           0 :             bFound = true;
     900             :         else
     901           0 :             ++aIter;
     902             :     }
     903             : 
     904           0 :     return aIter;
     905             : }
     906             : 
     907           0 : SlideSharedPtr SlideShowImpl::makeSlide(
     908             :     uno::Reference<drawing::XDrawPage> const&          xDrawPage,
     909             :     uno::Reference<drawing::XDrawPagesSupplier> const& xDrawPages,
     910             :     uno::Reference<animations::XAnimationNode> const&  xRootNode )
     911             : {
     912           0 :     if( !xDrawPage.is() )
     913           0 :         return SlideSharedPtr();
     914             : 
     915             :     //Retrieve polygons for the current slide
     916           0 :     PolygonMap::iterator aIter;
     917           0 :     aIter = findPolygons(xDrawPage);
     918             : 
     919             :     const SlideSharedPtr pSlide( createSlide(xDrawPage,
     920             :                                              xDrawPages,
     921             :                                              xRootNode,
     922             :                                              maEventQueue,
     923             :                                              maEventMultiplexer,
     924             :                                              maScreenUpdater,
     925             :                                              maActivitiesQueue,
     926             :                                              maUserEventQueue,
     927             :                                              *this,
     928             :                                              maViewContainer,
     929             :                                              mxComponentContext,
     930             :                                              maShapeEventListeners,
     931             :                                              maShapeCursors,
     932           0 :                                              (aIter != maPolygons.end()) ? aIter->second :  PolyPolygonVector(),
     933           0 :                                              maUserPaintColor ? *maUserPaintColor : RGBColor(),
     934             :                                              maUserPaintStrokeWidth,
     935           0 :                                              !!maUserPaintColor,
     936             :                                              mbImageAnimationsAllowed,
     937           0 :                                              mbDisableAnimationZOrder) );
     938             : 
     939             :     // prefetch show content (reducing latency for slide
     940             :     // bitmap and effect start later on)
     941           0 :     pSlide->prefetch();
     942             : 
     943           0 :     return pSlide;
     944             : }
     945             : 
     946           0 : void SlideShowImpl::requestWaitSymbol (void)
     947             : {
     948           0 :     ++mnWaitSymbolRequestCount;
     949             :     OSL_ASSERT(mnWaitSymbolRequestCount>0);
     950             : 
     951           0 :     if (mnWaitSymbolRequestCount == 1)
     952             :     {
     953           0 :         if( !mpWaitSymbol )
     954             :         {
     955             :             // fall back to cursor
     956           0 :             requestCursor(calcActiveCursor(mnCurrentCursor));
     957             :         }
     958             :         else
     959           0 :             mpWaitSymbol->show();
     960             :     }
     961           0 : }
     962             : 
     963           0 : void SlideShowImpl::releaseWaitSymbol (void)
     964             : {
     965           0 :     --mnWaitSymbolRequestCount;
     966             :     OSL_ASSERT(mnWaitSymbolRequestCount>=0);
     967             : 
     968           0 :     if (mnWaitSymbolRequestCount == 0)
     969             :     {
     970           0 :         if( !mpWaitSymbol )
     971             :         {
     972             :             // fall back to cursor
     973           0 :             requestCursor(calcActiveCursor(mnCurrentCursor));
     974             :         }
     975             :         else
     976           0 :             mpWaitSymbol->hide();
     977             :     }
     978           0 : }
     979             : 
     980           0 : sal_Int16 SlideShowImpl::calcActiveCursor( sal_Int16 nCursorShape ) const
     981             : {
     982           0 :     if( mnWaitSymbolRequestCount>0 && !mpWaitSymbol ) // enforce wait cursor
     983           0 :         nCursorShape = awt::SystemPointer::WAIT;
     984           0 :     else if( !mbMouseVisible ) // enforce INVISIBLE
     985           0 :         nCursorShape = awt::SystemPointer::INVISIBLE;
     986           0 :     else if( maUserPaintColor &&
     987           0 :              nCursorShape == awt::SystemPointer::ARROW )
     988           0 :         nCursorShape = awt::SystemPointer::PEN;
     989             : 
     990           0 :     return nCursorShape;
     991             : }
     992             : 
     993           0 : void SlideShowImpl::stopShow()
     994             : {
     995             :     // Force-end running animation
     996             :     // ===========================
     997           0 :     if (mpCurrentSlide)
     998             :     {
     999           0 :         mpCurrentSlide->hide();
    1000             :         //Register polygons in the map
    1001           0 :         if(findPolygons(mpCurrentSlide->getXDrawPage()) != maPolygons.end())
    1002           0 :             maPolygons.erase(mpCurrentSlide->getXDrawPage());
    1003             : 
    1004           0 :         maPolygons.insert(make_pair(mpCurrentSlide->getXDrawPage(),mpCurrentSlide->getPolygons()));
    1005             :     }
    1006             : 
    1007             :     // clear all queues
    1008           0 :     maEventQueue.clear();
    1009           0 :     maActivitiesQueue.clear();
    1010             : 
    1011             :     // Attention: we MUST clear the user event queue here,
    1012             :     // this is because the current slide might have registered
    1013             :     // shape events (click or enter/leave), which might
    1014             :     // otherwise dangle forever in the queue (because of the
    1015             :     // shared ptr nature). If someone needs to change this:
    1016             :     // somehow unregister those shapes at the user event queue
    1017             :     // on notifySlideEnded().
    1018           0 :     maUserEventQueue.clear();
    1019             : 
    1020             :     // re-enable automatic effect advancement
    1021             :     // (maEventQueue.clear() above might have killed
    1022             :     // maEventMultiplexer's tick events)
    1023           0 :     if (mbAutomaticAdvancementMode)
    1024             :     {
    1025             :         // toggle automatic mode (enabling just again is
    1026             :         // ignored by EventMultiplexer)
    1027           0 :         maEventMultiplexer.setAutomaticMode( false );
    1028           0 :         maEventMultiplexer.setAutomaticMode( true );
    1029             :     }
    1030           0 : }
    1031             : 
    1032             : class SlideShowImpl::PrefetchPropertiesFunc
    1033             : {
    1034             : public:
    1035           0 :     PrefetchPropertiesFunc( SlideShowImpl * that_,
    1036             :         bool& rbSkipAllMainSequenceEffects,
    1037             :         bool& rbSkipSlideTransition)
    1038             :         : mpSlideShowImpl(that_),
    1039             :           mrbSkipAllMainSequenceEffects(rbSkipAllMainSequenceEffects),
    1040           0 :           mrbSkipSlideTransition(rbSkipSlideTransition)
    1041           0 :     {}
    1042             : 
    1043           0 :     void operator()( beans::PropertyValue const& rProperty ) const {
    1044           0 :         if (rProperty.Name == "Prefetch" )
    1045             :         {
    1046           0 :             uno::Sequence<uno::Any> seq;
    1047           0 :             if ((rProperty.Value >>= seq) && seq.getLength() == 2)
    1048             :             {
    1049           0 :                 seq[0] >>= mpSlideShowImpl->mxPrefetchSlide;
    1050           0 :                 seq[1] >>= mpSlideShowImpl->mxPrefetchAnimationNode;
    1051           0 :             }
    1052             :         }
    1053           0 :         else if ( rProperty.Name == "SkipAllMainSequenceEffects" )
    1054             :         {
    1055           0 :             rProperty.Value >>= mrbSkipAllMainSequenceEffects;
    1056             :         }
    1057           0 :         else if ( rProperty.Name == "SkipSlideTransition" )
    1058             :         {
    1059           0 :             rProperty.Value >>= mrbSkipSlideTransition;
    1060             :         }
    1061             :         else
    1062             :         {
    1063             :             OSL_FAIL( OUStringToOString(
    1064             :                             rProperty.Name, RTL_TEXTENCODING_UTF8 ).getStr() );
    1065             :         }
    1066           0 :     }
    1067             : private:
    1068             :     SlideShowImpl *const mpSlideShowImpl;
    1069             :     bool& mrbSkipAllMainSequenceEffects;
    1070             :     bool& mrbSkipSlideTransition;
    1071             : };
    1072             : 
    1073           0 : void SlideShowImpl::displaySlide(
    1074             :     uno::Reference<drawing::XDrawPage> const& xSlide,
    1075             :     uno::Reference<drawing::XDrawPagesSupplier> const& xDrawPages,
    1076             :     uno::Reference<animations::XAnimationNode> const& xRootNode,
    1077             :     uno::Sequence<beans::PropertyValue> const& rProperties )
    1078             :     throw (uno::RuntimeException, std::exception)
    1079             : {
    1080           0 :     osl::MutexGuard const guard( m_aMutex );
    1081             : 
    1082           0 :     if (isDisposed())
    1083           0 :         return;
    1084             : 
    1085           0 :     maEffectRewinder.setRootAnimationNode(xRootNode);
    1086             : 
    1087             :     // precondition: must only be called from the main thread!
    1088             :     DBG_TESTSOLARMUTEX();
    1089             : 
    1090           0 :     mxDrawPagesSupplier = xDrawPages;
    1091             : 
    1092           0 :     stopShow();  // MUST call that: results in
    1093             :     // maUserEventQueue.clear(). What's more,
    1094             :     // stopShow()'s currSlide->hide() call is
    1095             :     // now also required, notifySlideEnded()
    1096             :     // relies on that
    1097             :     // unconditionally. Otherwise, genuine
    1098             :     // shape animations (drawing layer and
    1099             :     // GIF) will not be stopped.
    1100             : 
    1101           0 :     bool bSkipAllMainSequenceEffects (false);
    1102           0 :     bool bSkipSlideTransition (false);
    1103             :     std::for_each( rProperties.getConstArray(),
    1104           0 :                    rProperties.getConstArray() + rProperties.getLength(),
    1105           0 :         PrefetchPropertiesFunc(this, bSkipAllMainSequenceEffects, bSkipSlideTransition) );
    1106             : 
    1107             :     OSL_ENSURE( !maViewContainer.empty(), "### no views!" );
    1108           0 :     if (maViewContainer.empty())
    1109           0 :         return;
    1110             : 
    1111             :     // this here might take some time
    1112             :     {
    1113           0 :         WaitSymbolLock aLock (*this);
    1114             : 
    1115           0 :         mpPreviousSlide = mpCurrentSlide;
    1116           0 :         mpCurrentSlide.reset();
    1117             : 
    1118           0 :         if (matches( mpPrefetchSlide, xSlide, xRootNode ))
    1119             :         {
    1120             :             // prefetched slide matches:
    1121           0 :             mpCurrentSlide = mpPrefetchSlide;
    1122             :         }
    1123             :         else
    1124           0 :             mpCurrentSlide = makeSlide( xSlide, xDrawPages, xRootNode );
    1125             : 
    1126             :         OSL_ASSERT( mpCurrentSlide );
    1127           0 :         if (mpCurrentSlide)
    1128             :         {
    1129           0 :             basegfx::B2DSize oldSlideSize;
    1130           0 :             if( mpPreviousSlide )
    1131           0 :                 oldSlideSize = basegfx::B2DSize( mpPreviousSlide->getSlideSize() );
    1132             : 
    1133           0 :             basegfx::B2DSize const slideSize( mpCurrentSlide->getSlideSize() );
    1134             : 
    1135             :             // push new transformation to all views, if size changed
    1136           0 :             if( !mpPreviousSlide || oldSlideSize != slideSize )
    1137             :             {
    1138             :                 std::for_each( maViewContainer.begin(),
    1139             :                                maViewContainer.end(),
    1140             :                                boost::bind( &View::setViewSize, _1,
    1141           0 :                                             boost::cref(slideSize) ));
    1142             : 
    1143             :                 // explicitly notify view change here,
    1144             :                 // because transformation might have changed:
    1145             :                 // optimization, this->notifyViewChange() would
    1146             :                 // repaint slide which is not necessary.
    1147           0 :                 maEventMultiplexer.notifyViewsChanged();
    1148             :             }
    1149             : 
    1150             :             // create slide transition, and add proper end event
    1151             :             // (which then starts the slide effects
    1152             :             // via CURRENT_SLIDE.show())
    1153             :             ActivitySharedPtr pSlideChangeActivity (
    1154             :                 createSlideTransition(
    1155           0 :                     mpCurrentSlide->getXDrawPage(),
    1156             :                     mpPreviousSlide,
    1157             :                     mpCurrentSlide,
    1158           0 :                     makeEvent(
    1159             :                         boost::bind(
    1160             :                             &SlideShowImpl::notifySlideTransitionEnded,
    1161             :                             this,
    1162             :                             false ),
    1163           0 :                         "SlideShowImpl::notifySlideTransitionEnded")));
    1164             : 
    1165           0 :             if (bSkipSlideTransition)
    1166             :             {
    1167             :                 // The transition activity was created for the side effects
    1168             :                 // (like sound transitions).  Because we want to skip the
    1169             :                 // acutual transition animation we do not need the activity
    1170             :                 // anymore.
    1171           0 :                 pSlideChangeActivity.reset();
    1172             :             }
    1173             : 
    1174           0 :             if (pSlideChangeActivity)
    1175             :             {
    1176             :                 // factory generated a slide transition - activate it!
    1177           0 :                 maActivitiesQueue.addActivity( pSlideChangeActivity );
    1178             :             }
    1179             :             else
    1180             :             {
    1181             :                 // no transition effect on this slide - schedule slide
    1182             :                 // effect start event right away.
    1183             :                 maEventQueue.addEvent(
    1184           0 :                     makeEvent(
    1185             :                         boost::bind(
    1186             :                             &SlideShowImpl::notifySlideTransitionEnded,
    1187             :                             this,
    1188             :                             true ),
    1189           0 :                         "SlideShowImpl::notifySlideTransitionEnded"));
    1190           0 :             }
    1191           0 :         }
    1192             :     } // finally
    1193             : 
    1194           0 :     maEventMultiplexer.notifySlideTransitionStarted();
    1195             :     maListenerContainer.forEach<presentation::XSlideShowListener>(
    1196           0 :         boost::mem_fn( &presentation::XSlideShowListener::slideTransitionStarted ) );
    1197             : 
    1198             :     // We are currently rewinding an effect.  This lead us from the next
    1199             :     // slide to this one.  To complete this we have to play back all main
    1200             :     // sequence effects on this slide.
    1201           0 :     if (bSkipAllMainSequenceEffects)
    1202           0 :         maEffectRewinder.skipAllMainSequenceEffects();
    1203             : }
    1204             : 
    1205           0 : void SlideShowImpl::redisplayCurrentSlide (void)
    1206             : {
    1207           0 :     osl::MutexGuard const guard( m_aMutex );
    1208             : 
    1209           0 :     if (isDisposed())
    1210           0 :         return;
    1211             : 
    1212             :     // precondition: must only be called from the main thread!
    1213             :     DBG_TESTSOLARMUTEX();
    1214           0 :     stopShow();
    1215             : 
    1216             :     OSL_ENSURE( !maViewContainer.empty(), "### no views!" );
    1217           0 :     if (maViewContainer.empty())
    1218           0 :         return;
    1219             : 
    1220             :     // No transition effect on this slide - schedule slide
    1221             :     // effect start event right away.
    1222             :     maEventQueue.addEvent(
    1223           0 :         makeEvent(
    1224             :             boost::bind(
    1225             :                 &SlideShowImpl::notifySlideTransitionEnded,
    1226             :                 this,
    1227             :                 true ),
    1228           0 :             "SlideShowImpl::notifySlideTransitionEnded"));
    1229             : 
    1230           0 :     maEventMultiplexer.notifySlideTransitionStarted();
    1231             :     maListenerContainer.forEach<presentation::XSlideShowListener>(
    1232           0 :         boost::mem_fn( &presentation::XSlideShowListener::slideTransitionStarted ) );
    1233             : }
    1234             : 
    1235           0 : sal_Bool SlideShowImpl::nextEffect() throw (uno::RuntimeException, std::exception)
    1236             : {
    1237           0 :     osl::MutexGuard const guard( m_aMutex );
    1238             : 
    1239           0 :     if (isDisposed())
    1240           0 :         return false;
    1241             : 
    1242             :     // precondition: must only be called from the main thread!
    1243             :     DBG_TESTSOLARMUTEX();
    1244             : 
    1245           0 :     if (mbShowPaused)
    1246           0 :         return true;
    1247             :     else
    1248           0 :         return maEventMultiplexer.notifyNextEffect();
    1249             : }
    1250             : 
    1251           0 : sal_Bool SlideShowImpl::previousEffect() throw (uno::RuntimeException, std::exception)
    1252             : {
    1253           0 :     osl::MutexGuard const guard( m_aMutex );
    1254             : 
    1255           0 :     if (isDisposed())
    1256           0 :         return false;
    1257             : 
    1258             :     // precondition: must only be called from the main thread!
    1259             :     DBG_TESTSOLARMUTEX();
    1260             : 
    1261           0 :     if (mbShowPaused)
    1262           0 :         return true;
    1263             :     else
    1264             :     {
    1265             :         return maEffectRewinder.rewind(
    1266             :             maScreenUpdater.createLock(false),
    1267             :             ::boost::bind<void>(::boost::mem_fn(&SlideShowImpl::redisplayCurrentSlide), this),
    1268           0 :             ::boost::bind<void>(::boost::mem_fn(&SlideShowImpl::rewindEffectToPreviousSlide), this));
    1269           0 :     }
    1270             : }
    1271             : 
    1272           0 : void SlideShowImpl::rewindEffectToPreviousSlide (void)
    1273             : {
    1274             :     // Show the wait symbol now and prevent it from showing temporary slide
    1275             :     // content while effects are played back.
    1276           0 :     WaitSymbolLock aLock (*this);
    1277             : 
    1278             :     // A previous call to EffectRewinder::Rewind could not rewind the current
    1279             :     // effect because there are no effects on the current slide or none has
    1280             :     // yet been displayed.  Go to the previous slide.
    1281           0 :     notifySlideEnded(true);
    1282             : 
    1283             :     // Process pending events once more in order to have the following
    1284             :     // screen update show the last effect.  Not sure whether this should be
    1285             :     // necessary.
    1286           0 :     maEventQueue.forceEmpty();
    1287             : 
    1288             :     // We have to call the screen updater before the wait symbol is turned
    1289             :     // off.  Otherwise the wait symbol would force the display of an
    1290             :     // intermediate state of the slide (before the effects are replayed.)
    1291           0 :     maScreenUpdater.commitUpdates();
    1292           0 : }
    1293             : 
    1294           0 : sal_Bool SlideShowImpl::startShapeActivity(
    1295             :     uno::Reference<drawing::XShape> const& /*xShape*/ )
    1296             :     throw (uno::RuntimeException, std::exception)
    1297             : {
    1298           0 :     osl::MutexGuard const guard( m_aMutex );
    1299             : 
    1300             :     // precondition: must only be called from the main thread!
    1301             :     DBG_TESTSOLARMUTEX();
    1302             : 
    1303             :     // TODO(F3): NYI
    1304             :     OSL_FAIL( "not yet implemented!" );
    1305           0 :     return false;
    1306             : }
    1307             : 
    1308           0 : sal_Bool SlideShowImpl::stopShapeActivity(
    1309             :     uno::Reference<drawing::XShape> const& /*xShape*/ )
    1310             :     throw (uno::RuntimeException, std::exception)
    1311             : {
    1312           0 :     osl::MutexGuard const guard( m_aMutex );
    1313             : 
    1314             :     // precondition: must only be called from the main thread!
    1315             :     DBG_TESTSOLARMUTEX();
    1316             : 
    1317             :     // TODO(F3): NYI
    1318             :     OSL_FAIL( "not yet implemented!" );
    1319           0 :     return false;
    1320             : }
    1321             : 
    1322           0 : sal_Bool SlideShowImpl::pause( sal_Bool bPauseShow )
    1323             :     throw (uno::RuntimeException, std::exception)
    1324             : {
    1325           0 :     osl::MutexGuard const guard( m_aMutex );
    1326             : 
    1327           0 :     if (isDisposed())
    1328           0 :         return false;
    1329             : 
    1330             :     // precondition: must only be called from the main thread!
    1331             :     DBG_TESTSOLARMUTEX();
    1332             : 
    1333           0 :     if (bPauseShow)
    1334           0 :         mpPresTimer->pauseTimer();
    1335             :     else
    1336           0 :         mpPresTimer->continueTimer();
    1337             : 
    1338           0 :     maEventMultiplexer.notifyPauseMode(bPauseShow);
    1339             : 
    1340           0 :     mbShowPaused = bPauseShow;
    1341           0 :     return true;
    1342             : }
    1343             : 
    1344           0 : uno::Reference<drawing::XDrawPage> SlideShowImpl::getCurrentSlide()
    1345             :     throw (uno::RuntimeException, std::exception)
    1346             : {
    1347           0 :     osl::MutexGuard const guard( m_aMutex );
    1348             : 
    1349           0 :     if (isDisposed())
    1350           0 :         return uno::Reference<drawing::XDrawPage>();
    1351             : 
    1352             :     // precondition: must only be called from the main thread!
    1353             :     DBG_TESTSOLARMUTEX();
    1354             : 
    1355           0 :     if (mpCurrentSlide)
    1356           0 :         return mpCurrentSlide->getXDrawPage();
    1357             :     else
    1358           0 :         return uno::Reference<drawing::XDrawPage>();
    1359             : }
    1360             : 
    1361           0 : sal_Bool SlideShowImpl::addView(
    1362             :     uno::Reference<presentation::XSlideShowView> const& xView )
    1363             :     throw (uno::RuntimeException, std::exception)
    1364             : {
    1365           0 :     osl::MutexGuard const guard( m_aMutex );
    1366             : 
    1367           0 :     if (isDisposed())
    1368           0 :         return false;
    1369             : 
    1370             :     // precondition: must only be called from the main thread!
    1371             :     DBG_TESTSOLARMUTEX();
    1372             : 
    1373             :     // first of all, check if view has a valid canvas
    1374           0 :     ENSURE_OR_RETURN_FALSE( xView.is(), "addView(): Invalid view" );
    1375           0 :     ENSURE_OR_RETURN_FALSE( xView->getCanvas().is(),
    1376             :                        "addView(): View does not provide a valid canvas" );
    1377             : 
    1378             :     UnoViewSharedPtr const pView( createSlideView(
    1379             :                                       xView,
    1380             :                                       maEventQueue,
    1381           0 :                                       maEventMultiplexer ));
    1382           0 :     if (!maViewContainer.addView( pView ))
    1383           0 :         return false; // view already added
    1384             : 
    1385             :     // initialize view content
    1386             :     // =======================
    1387             : 
    1388           0 :     if (mpCurrentSlide)
    1389             :     {
    1390             :         // set view transformation
    1391           0 :         const basegfx::B2ISize slideSize = mpCurrentSlide->getSlideSize();
    1392           0 :         pView->setViewSize( basegfx::B2DSize( slideSize.getX(),
    1393           0 :                                               slideSize.getY() ) );
    1394             :     }
    1395             : 
    1396             :     // clear view area (since its newly added,
    1397             :     // we need a clean slate)
    1398           0 :     pView->clearAll();
    1399             : 
    1400             :     // broadcast newly added view
    1401           0 :     maEventMultiplexer.notifyViewAdded( pView );
    1402             : 
    1403             :     // set current mouse ptr
    1404           0 :     pView->setCursorShape( calcActiveCursor(mnCurrentCursor) );
    1405             : 
    1406           0 :     return true;
    1407             : }
    1408             : 
    1409           0 : sal_Bool SlideShowImpl::removeView(
    1410             :     uno::Reference<presentation::XSlideShowView> const& xView )
    1411             :     throw (uno::RuntimeException, std::exception)
    1412             : {
    1413           0 :     osl::MutexGuard const guard( m_aMutex );
    1414             : 
    1415             :     // precondition: must only be called from the main thread!
    1416             :     DBG_TESTSOLARMUTEX();
    1417             : 
    1418           0 :     ENSURE_OR_RETURN_FALSE( xView.is(), "removeView(): Invalid view" );
    1419             : 
    1420           0 :     UnoViewSharedPtr const pView( maViewContainer.removeView( xView ) );
    1421           0 :     if( !pView )
    1422           0 :         return false; // view was not added in the first place
    1423             : 
    1424             :     // remove view from EventMultiplexer (mouse events etc.)
    1425           0 :     maEventMultiplexer.notifyViewRemoved( pView );
    1426             : 
    1427           0 :     pView->_dispose();
    1428             : 
    1429           0 :     return true;
    1430             : }
    1431             : 
    1432           0 : void SlideShowImpl::registerUserPaintPolygons( const uno::Reference< lang::XMultiServiceFactory >& xDocFactory ) throw (uno::RuntimeException, std::exception)
    1433             : {
    1434             :     //Retrieve Polygons if user ends presentation by context menu
    1435           0 :     if (mpCurrentSlide)
    1436             :     {
    1437           0 :         if(findPolygons(mpCurrentSlide->getXDrawPage()) != maPolygons.end())
    1438           0 :             maPolygons.erase(mpCurrentSlide->getXDrawPage());
    1439             : 
    1440           0 :         maPolygons.insert(make_pair(mpCurrentSlide->getXDrawPage(),mpCurrentSlide->getPolygons()));
    1441             :     }
    1442             : 
    1443             :     //Creating the layer for shapes
    1444             :     // query for the XLayerManager
    1445           0 :     uno::Reference< drawing::XLayerSupplier > xLayerSupplier(xDocFactory, uno::UNO_QUERY);
    1446           0 :     uno::Reference< container::XNameAccess > xNameAccess = xLayerSupplier->getLayerManager();
    1447             : 
    1448           0 :     uno::Reference< drawing::XLayerManager > xLayerManager(xNameAccess, uno::UNO_QUERY);
    1449             :     // create a layer and set its properties
    1450           0 :     uno::Reference< drawing::XLayer > xDrawnInSlideshow = xLayerManager->insertNewByIndex(xLayerManager->getCount());
    1451           0 :     uno::Reference< beans::XPropertySet > xLayerPropSet(xDrawnInSlideshow, uno::UNO_QUERY);
    1452             : 
    1453             :     //Layer Name which enables to catch annotations
    1454           0 :     OUString layerName = "DrawnInSlideshow";
    1455           0 :     uno::Any aPropLayer;
    1456             : 
    1457           0 :     aPropLayer <<= layerName;
    1458           0 :     xLayerPropSet->setPropertyValue("Name", aPropLayer);
    1459             : 
    1460           0 :     aPropLayer <<= true;
    1461           0 :     xLayerPropSet->setPropertyValue("IsVisible", aPropLayer);
    1462             : 
    1463           0 :     aPropLayer <<= false;
    1464           0 :     xLayerPropSet->setPropertyValue("IsLocked", aPropLayer);
    1465             : 
    1466           0 :     PolygonMap::iterator aIter=maPolygons.begin();
    1467             : 
    1468           0 :     PolyPolygonVector aPolygons;
    1469           0 :     ::cppcanvas::PolyPolygonSharedPtr pPolyPoly;
    1470           0 :     ::basegfx::B2DPolyPolygon b2DPolyPoly;
    1471             : 
    1472             :     //Register polygons for each slide
    1473           0 :     while(aIter!=maPolygons.end())
    1474             :     {
    1475           0 :         aPolygons = aIter->second;
    1476             :         //Get shapes for the slide
    1477           0 :         ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes > Shapes(aIter->first, ::com::sun::star::uno::UNO_QUERY);
    1478             :         //Retrieve polygons for one slide
    1479           0 :         for( PolyPolygonVector::iterator aIterPoly=aPolygons.begin(),
    1480           0 :                  aEnd=aPolygons.end();
    1481             :              aIterPoly!=aEnd; ++aIterPoly )
    1482             :         {
    1483           0 :             pPolyPoly = (*aIterPoly);
    1484           0 :             b2DPolyPoly = ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(pPolyPoly->getUNOPolyPolygon());
    1485             : 
    1486             :             //Normally there is only one polygon
    1487           0 :             for(sal_uInt32 i=0; i< b2DPolyPoly.count();i++)
    1488             :             {
    1489           0 :                 const ::basegfx::B2DPolygon& aPoly =  b2DPolyPoly.getB2DPolygon(i);
    1490           0 :                 sal_uInt32 nPoints = aPoly.count();
    1491             : 
    1492           0 :                 if( nPoints > 1)
    1493             :                 {
    1494             :                     //create the PolyLineShape
    1495           0 :                     uno::Reference< uno::XInterface > polyshape(xDocFactory->createInstance(
    1496           0 :                                                                     OUString("com.sun.star.drawing.PolyLineShape") ) );
    1497           0 :                     uno::Reference< drawing::XShape > rPolyShape(polyshape, uno::UNO_QUERY);
    1498             : 
    1499             :                     //Add the shape to the slide
    1500           0 :                     Shapes->add(rPolyShape);
    1501             : 
    1502             :                     //Retrieve shape properties
    1503           0 :                     uno::Reference< beans::XPropertySet > aXPropSet = uno::Reference< beans::XPropertySet >( rPolyShape, uno::UNO_QUERY );
    1504             :                     //Construct a sequence of points sequence
    1505           0 :                     drawing::PointSequenceSequence aRetval;
    1506             :                     //Create only one sequence for one polygon
    1507           0 :                     aRetval.realloc( 1 );
    1508             :                     // Retrieve the sequence of points from aRetval
    1509           0 :                     drawing::PointSequence* pOuterSequence = aRetval.getArray();
    1510             :                     // Create 2 points in this sequence
    1511           0 :                     pOuterSequence->realloc(nPoints);
    1512             :                     // Get these points which are in an array
    1513           0 :                     awt::Point* pInnerSequence = pOuterSequence->getArray();
    1514           0 :                     for( sal_uInt32 n = 0; n < nPoints; n++ )
    1515             :                     {
    1516             :                         //Create a point from the polygon
    1517             :                         *pInnerSequence++ = awt::Point(
    1518           0 :                             basegfx::fround(aPoly.getB2DPoint(n).getX()),
    1519           0 :                             basegfx::fround(aPoly.getB2DPoint(n).getY()));
    1520             :                     }
    1521             : 
    1522             :                     //Fill the properties
    1523             :                     //Give the built PointSequenceSequence.
    1524           0 :                     uno::Any aParam;
    1525           0 :                     aParam <<= aRetval;
    1526           0 :                     aXPropSet->setPropertyValue("PolyPolygon", aParam );
    1527             : 
    1528             :                     //LineStyle : SOLID by default
    1529           0 :                     uno::Any            aAny;
    1530             :                     drawing::LineStyle  eLS;
    1531           0 :                     eLS = drawing::LineStyle_SOLID;
    1532           0 :                     aAny <<= eLS;
    1533           0 :                     aXPropSet->setPropertyValue("LineStyle", aAny );
    1534             : 
    1535             :                     //LineColor
    1536             :                     sal_uInt32          nLineColor;
    1537           0 :                     nLineColor = pPolyPoly->getRGBALineColor();
    1538             :                     //Transform polygon color from RRGGBBAA to AARRGGBB
    1539           0 :                     aAny <<= RGBAColor2UnoColor(nLineColor);
    1540           0 :                     aXPropSet->setPropertyValue("LineColor", aAny );
    1541             : 
    1542             :                     //LineWidth
    1543             :                     double              fLineWidth;
    1544           0 :                     fLineWidth = pPolyPoly->getStrokeWidth();
    1545           0 :                     aAny <<= (sal_Int32)fLineWidth;
    1546           0 :                     aXPropSet->setPropertyValue("LineWidth", aAny );
    1547             : 
    1548             :                     // make polygons special
    1549           0 :                     xLayerManager->attachShapeToLayer(rPolyShape, xDrawnInSlideshow);
    1550             :                 }
    1551           0 :             }
    1552             :         }
    1553           0 :         ++aIter;
    1554           0 :     }
    1555           0 : }
    1556             : 
    1557           0 : sal_Bool SlideShowImpl::setProperty( beans::PropertyValue const& rProperty )
    1558             :     throw (uno::RuntimeException, std::exception)
    1559             : {
    1560           0 :     osl::MutexGuard const guard( m_aMutex );
    1561             : 
    1562           0 :     if (isDisposed())
    1563           0 :         return false;
    1564             : 
    1565             :     // precondition: must only be called from the main thread!
    1566             :     DBG_TESTSOLARMUTEX();
    1567             : 
    1568           0 :     if ( rProperty.Name == "AutomaticAdvancement" )
    1569             :     {
    1570           0 :         double nTimeout(0.0);
    1571           0 :         mbAutomaticAdvancementMode = (rProperty.Value >>= nTimeout);
    1572           0 :         if (mbAutomaticAdvancementMode)
    1573             :         {
    1574           0 :             maEventMultiplexer.setAutomaticTimeout( nTimeout );
    1575             :         }
    1576           0 :         maEventMultiplexer.setAutomaticMode( mbAutomaticAdvancementMode );
    1577           0 :         return true;
    1578             :     }
    1579             : 
    1580           0 :     if ( rProperty.Name == "UserPaintColor" )
    1581             :     {
    1582           0 :         sal_Int32 nColor(0);
    1583           0 :         if (rProperty.Value >>= nColor)
    1584             :         {
    1585             :             OSL_ENSURE( mbMouseVisible,
    1586             :                         "setProperty(): User paint overrides invisible mouse" );
    1587             : 
    1588             :             // enable user paint
    1589           0 :             maUserPaintColor.reset( unoColor2RGBColor( nColor ) );
    1590           0 :             if( mpCurrentSlide && !mpCurrentSlide->isPaintOverlayActive() )
    1591           0 :                 mpCurrentSlide->enablePaintOverlay();
    1592             : 
    1593           0 :             maEventMultiplexer.notifyUserPaintColor( *maUserPaintColor );
    1594             :         }
    1595             :         else
    1596             :         {
    1597             :             // disable user paint
    1598           0 :             maUserPaintColor.reset();
    1599           0 :             maEventMultiplexer.notifyUserPaintDisabled();
    1600           0 :             if( mpCurrentSlide )
    1601           0 :                 mpCurrentSlide->disablePaintOverlay();
    1602             :         }
    1603             : 
    1604           0 :         resetCursor();
    1605             : 
    1606           0 :         return true;
    1607             :     }
    1608             : 
    1609             :     //adding support for erasing features in UserPaintOverlay
    1610           0 :     if ( rProperty.Name == "EraseAllInk" )
    1611             :     {
    1612           0 :         bool nEraseAllInk(false);
    1613           0 :         if (rProperty.Value >>= nEraseAllInk)
    1614             :         {
    1615             :             OSL_ENSURE( mbMouseVisible,
    1616             :                         "setProperty(): User paint overrides invisible mouse" );
    1617             : 
    1618             :             // enable user paint
    1619           0 :             maEraseAllInk.reset( nEraseAllInk );
    1620           0 :             maEventMultiplexer.notifyEraseAllInk( *maEraseAllInk );
    1621             :         }
    1622             : 
    1623           0 :         return true;
    1624             :     }
    1625             : 
    1626           0 :     if ( rProperty.Name == "SwitchPenMode" )
    1627             :     {
    1628           0 :         bool nSwitchPenMode(false);
    1629           0 :         if (rProperty.Value >>= nSwitchPenMode)
    1630             :         {
    1631             :             OSL_ENSURE( mbMouseVisible,
    1632             :                         "setProperty(): User paint overrides invisible mouse" );
    1633             : 
    1634           0 :             if(nSwitchPenMode == true){
    1635             :             // Switch to Pen Mode
    1636           0 :             maSwitchPenMode.reset( nSwitchPenMode );
    1637           0 :             maEventMultiplexer.notifySwitchPenMode();
    1638             :             }
    1639             :         }
    1640           0 :         return true;
    1641             :     }
    1642             : 
    1643           0 :     if ( rProperty.Name == "SwitchEraserMode" )
    1644             :     {
    1645           0 :         bool nSwitchEraserMode(false);
    1646           0 :         if (rProperty.Value >>= nSwitchEraserMode)
    1647             :         {
    1648             :             OSL_ENSURE( mbMouseVisible,
    1649             :                         "setProperty(): User paint overrides invisible mouse" );
    1650           0 :             if(nSwitchEraserMode == true){
    1651             :             // switch to Eraser mode
    1652           0 :             maSwitchEraserMode.reset( nSwitchEraserMode );
    1653           0 :             maEventMultiplexer.notifySwitchEraserMode();
    1654             :             }
    1655             :         }
    1656             : 
    1657           0 :         return true;
    1658             :     }
    1659             : 
    1660           0 :     if ( rProperty.Name == "EraseInk" )
    1661             :     {
    1662           0 :         sal_Int32 nEraseInk(100);
    1663           0 :         if (rProperty.Value >>= nEraseInk)
    1664             :         {
    1665             :             OSL_ENSURE( mbMouseVisible,
    1666             :                         "setProperty(): User paint overrides invisible mouse" );
    1667             : 
    1668             :             // enable user paint
    1669           0 :             maEraseInk.reset( nEraseInk );
    1670           0 :             maEventMultiplexer.notifyEraseInkWidth( *maEraseInk );
    1671             :         }
    1672             : 
    1673           0 :         return true;
    1674             :     }
    1675             : 
    1676             :     // new Property for pen's width
    1677           0 :     if ( rProperty.Name == "UserPaintStrokeWidth" )
    1678             :     {
    1679           0 :         double nWidth(4.0);
    1680           0 :         if (rProperty.Value >>= nWidth)
    1681             :         {
    1682             :             OSL_ENSURE( mbMouseVisible,"setProperty(): User paint overrides invisible mouse" );
    1683             :             // enable user paint stroke width
    1684           0 :             maUserPaintStrokeWidth = nWidth;
    1685           0 :             maEventMultiplexer.notifyUserPaintStrokeWidth( maUserPaintStrokeWidth );
    1686             :         }
    1687             : 
    1688           0 :         return true;
    1689             :     }
    1690             : 
    1691           0 :     if ( rProperty.Name == "AdvanceOnClick" )
    1692             :     {
    1693           0 :         bool bAdvanceOnClick = false;
    1694           0 :         if (! (rProperty.Value >>= bAdvanceOnClick))
    1695           0 :             return false;
    1696           0 :         maUserEventQueue.setAdvanceOnClick( bAdvanceOnClick );
    1697           0 :         return true;
    1698             :     }
    1699             : 
    1700           0 :     if ( rProperty.Name == "DisableAnimationZOrder" )
    1701             :     {
    1702           0 :         bool bDisableAnimationZOrder = false;
    1703           0 :         if (! (rProperty.Value >>= bDisableAnimationZOrder))
    1704           0 :             return false;
    1705           0 :         mbDisableAnimationZOrder = bDisableAnimationZOrder;
    1706           0 :         return true;
    1707             :     }
    1708             : 
    1709           0 :     if ( rProperty.Name == "ImageAnimationsAllowed" )
    1710             :     {
    1711           0 :         if (! (rProperty.Value >>= mbImageAnimationsAllowed))
    1712           0 :             return false;
    1713             : 
    1714             :         // TODO(F3): Forward to slides!
    1715           0 :         return true;
    1716             :     }
    1717             : 
    1718           0 :     if ( rProperty.Name == "MouseVisible" )
    1719             :     {
    1720           0 :         if (! (rProperty.Value >>= mbMouseVisible))
    1721           0 :             return false;
    1722             : 
    1723           0 :         requestCursor(mnCurrentCursor);
    1724             : 
    1725           0 :         return true;
    1726             :     }
    1727             : 
    1728           0 :     if ( rProperty.Name == "ForceManualAdvance" )
    1729             :     {
    1730           0 :         return (rProperty.Value >>= mbForceManualAdvance);
    1731             :     }
    1732             : 
    1733           0 :     if ( rProperty.Name == "RehearseTimings" )
    1734             :     {
    1735           0 :         bool bRehearseTimings = false;
    1736           0 :         if (! (rProperty.Value >>= bRehearseTimings))
    1737           0 :             return false;
    1738             : 
    1739           0 :         if (bRehearseTimings)
    1740             :         {
    1741             :             // TODO(Q3): Move to slide
    1742           0 :             mpRehearseTimingsActivity = RehearseTimingsActivity::create(
    1743             :                 SlideShowContext(
    1744             :                     mpDummyPtr,
    1745             :                     maEventQueue,
    1746             :                     maEventMultiplexer,
    1747             :                     maScreenUpdater,
    1748             :                     maActivitiesQueue,
    1749             :                     maUserEventQueue,
    1750             :                     *this,
    1751             :                     maViewContainer,
    1752           0 :                     mxComponentContext) );
    1753             :         }
    1754           0 :         else if (mpRehearseTimingsActivity)
    1755             :         {
    1756             :             // removes timer from all views:
    1757           0 :             mpRehearseTimingsActivity->dispose();
    1758           0 :             mpRehearseTimingsActivity.reset();
    1759             :         }
    1760           0 :         return true;
    1761             :     }
    1762             : 
    1763           0 :     if ( rProperty.Name == "WaitSymbolBitmap" )
    1764             :     {
    1765           0 :         uno::Reference<rendering::XBitmap> xBitmap;
    1766           0 :         if (! (rProperty.Value >>= xBitmap))
    1767           0 :             return false;
    1768             : 
    1769           0 :         mpWaitSymbol = WaitSymbol::create( xBitmap,
    1770             :                                            maScreenUpdater,
    1771             :                                            maEventMultiplexer,
    1772           0 :                                            maViewContainer );
    1773             : 
    1774           0 :         return true;
    1775             :     }
    1776             : 
    1777           0 :     if ( rProperty.Name == "PointerSymbolBitmap" )
    1778             :     {
    1779           0 :         uno::Reference<rendering::XBitmap> xBitmap;
    1780           0 :         if (! (rProperty.Value >>= xBitmap))
    1781           0 :             return false;
    1782             : 
    1783           0 :         mpPointerSymbol = PointerSymbol::create( xBitmap,
    1784             :                                            maScreenUpdater,
    1785             :                                            maEventMultiplexer,
    1786           0 :                                            maViewContainer );
    1787             : 
    1788           0 :         return true;
    1789             :     }
    1790             : 
    1791           0 :     if ( rProperty.Name == "PointerVisible" )
    1792             :     {
    1793             :         bool visible;
    1794           0 :         if (!(rProperty.Value >>= visible))
    1795           0 :             return false;
    1796             : 
    1797           0 :         mpPointerSymbol->setVisible(visible);
    1798           0 :         return true;
    1799             :     }
    1800             : 
    1801           0 :     if ( rProperty.Name == "PointerPosition")
    1802             :     {
    1803           0 :         ::com::sun::star::geometry::RealPoint2D pos;
    1804           0 :         if (! (rProperty.Value >>= pos))
    1805           0 :             return false;
    1806             : 
    1807           0 :         mpPointerSymbol->viewsChanged(pos);
    1808           0 :         return true;
    1809             :     }
    1810             : 
    1811           0 :     if (rProperty.Name == "NoSlideTransitions" )
    1812             :     {
    1813           0 :         return (rProperty.Value >>= mbNoSlideTransitions);
    1814             :     }
    1815             : 
    1816           0 :     if ( rProperty.Name == "IsSoundEnabled" )
    1817             :     {
    1818           0 :         uno::Sequence<uno::Any> aValues;
    1819           0 :         uno::Reference<presentation::XSlideShowView> xView;
    1820           0 :         bool bValue (false);
    1821           0 :         if ((rProperty.Value >>= aValues)
    1822           0 :             && aValues.getLength()==2
    1823           0 :             && (aValues[0] >>= xView)
    1824           0 :             && (aValues[1] >>= bValue))
    1825             :         {
    1826             :             // Look up the view.
    1827           0 :             for (UnoViewVector::const_iterator
    1828           0 :                      iView (maViewContainer.begin()),
    1829           0 :                      iEnd (maViewContainer.end());
    1830             :                  iView!=iEnd;
    1831             :                  ++iView)
    1832             :             {
    1833           0 :                 if (*iView && (*iView)->getUnoView()==xView)
    1834             :                 {
    1835             :                     // Store the flag at the view so that media shapes have
    1836             :                     // access to it.
    1837           0 :                     (*iView)->setIsSoundEnabled(bValue);
    1838           0 :                     return true;
    1839             :                 }
    1840             :             }
    1841           0 :         }
    1842             :     }
    1843             : 
    1844           0 :     return false;
    1845             : }
    1846             : 
    1847           0 : void SlideShowImpl::addSlideShowListener(
    1848             :     uno::Reference<presentation::XSlideShowListener> const& xListener )
    1849             :     throw (uno::RuntimeException, std::exception)
    1850             : {
    1851           0 :     osl::MutexGuard const guard( m_aMutex );
    1852             : 
    1853           0 :     if (isDisposed())
    1854           0 :         return;
    1855             : 
    1856             :     // container syncs with passed mutex ref
    1857           0 :     maListenerContainer.addInterface(xListener);
    1858             : }
    1859             : 
    1860           0 : void SlideShowImpl::removeSlideShowListener(
    1861             :     uno::Reference<presentation::XSlideShowListener> const& xListener )
    1862             :     throw (uno::RuntimeException, std::exception)
    1863             : {
    1864           0 :     osl::MutexGuard const guard( m_aMutex );
    1865             : 
    1866             :     // container syncs with passed mutex ref
    1867           0 :     maListenerContainer.removeInterface(xListener);
    1868           0 : }
    1869             : 
    1870           0 : void SlideShowImpl::addShapeEventListener(
    1871             :     uno::Reference<presentation::XShapeEventListener> const& xListener,
    1872             :     uno::Reference<drawing::XShape> const& xShape )
    1873             :     throw (uno::RuntimeException, std::exception)
    1874             : {
    1875           0 :     osl::MutexGuard const guard( m_aMutex );
    1876             : 
    1877           0 :     if (isDisposed())
    1878           0 :         return;
    1879             : 
    1880             :     // precondition: must only be called from the main thread!
    1881             :     DBG_TESTSOLARMUTEX();
    1882             : 
    1883           0 :     ShapeEventListenerMap::iterator aIter;
    1884           0 :     if( (aIter=maShapeEventListeners.find( xShape )) ==
    1885           0 :         maShapeEventListeners.end() )
    1886             :     {
    1887             :         // no entry for this shape -> create one
    1888             :         aIter = maShapeEventListeners.insert(
    1889             :             ShapeEventListenerMap::value_type(
    1890             :                 xShape,
    1891             :                 boost::shared_ptr<cppu::OInterfaceContainerHelper>(
    1892           0 :                     new cppu::OInterfaceContainerHelper(m_aMutex)))).first;
    1893             :     }
    1894             : 
    1895             :     // add new listener to broadcaster
    1896           0 :     if( aIter->second.get() )
    1897           0 :         aIter->second->addInterface( xListener );
    1898             : 
    1899             :     maEventMultiplexer.notifyShapeListenerAdded(xListener,
    1900           0 :                                                 xShape);
    1901             : }
    1902             : 
    1903           0 : void SlideShowImpl::removeShapeEventListener(
    1904             :     uno::Reference<presentation::XShapeEventListener> const& xListener,
    1905             :     uno::Reference<drawing::XShape> const& xShape )
    1906             :     throw (uno::RuntimeException, std::exception)
    1907             : {
    1908           0 :     osl::MutexGuard const guard( m_aMutex );
    1909             : 
    1910             :     // precondition: must only be called from the main thread!
    1911             :     DBG_TESTSOLARMUTEX();
    1912             : 
    1913           0 :     ShapeEventListenerMap::iterator aIter;
    1914           0 :     if( (aIter = maShapeEventListeners.find( xShape )) !=
    1915           0 :         maShapeEventListeners.end() )
    1916             :     {
    1917             :         // entry for this shape found -> remove listener from
    1918             :         // helper object
    1919           0 :         ENSURE_OR_THROW(
    1920             :             aIter->second.get(),
    1921             :             "SlideShowImpl::removeShapeEventListener(): "
    1922             :             "listener map contains NULL broadcast helper" );
    1923             : 
    1924           0 :         aIter->second->removeInterface( xListener );
    1925             :     }
    1926             : 
    1927             :     maEventMultiplexer.notifyShapeListenerRemoved(xListener,
    1928           0 :                                                   xShape);
    1929           0 : }
    1930             : 
    1931           0 : void SlideShowImpl::setShapeCursor(
    1932             :     uno::Reference<drawing::XShape> const& xShape, sal_Int16 nPointerShape )
    1933             :     throw (uno::RuntimeException, std::exception)
    1934             : {
    1935           0 :     osl::MutexGuard const guard( m_aMutex );
    1936             : 
    1937           0 :     if (isDisposed())
    1938           0 :         return;
    1939             : 
    1940             :     // precondition: must only be called from the main thread!
    1941             :     DBG_TESTSOLARMUTEX();
    1942             : 
    1943           0 :     ShapeCursorMap::iterator aIter;
    1944           0 :     if( (aIter=maShapeCursors.find( xShape )) == maShapeCursors.end() )
    1945             :     {
    1946             :         // no entry for this shape -> create one
    1947           0 :         if( nPointerShape != awt::SystemPointer::ARROW )
    1948             :         {
    1949             :             // add new entry, unless shape shall display
    1950             :             // normal pointer arrow -> no need to handle that
    1951             :             // case
    1952             :             maShapeCursors.insert(
    1953             :                 ShapeCursorMap::value_type(xShape,
    1954           0 :                                            nPointerShape) );
    1955             :         }
    1956             :     }
    1957           0 :     else if( nPointerShape == awt::SystemPointer::ARROW )
    1958             :     {
    1959             :         // shape shall display normal cursor -> can disable
    1960             :         // the cursor and clear the entry
    1961           0 :         maShapeCursors.erase( xShape );
    1962             :     }
    1963             :     else
    1964             :     {
    1965             :         // existing entry found, update with new cursor ID
    1966           0 :         aIter->second = nPointerShape;
    1967             :     }
    1968             : 
    1969             :     maEventMultiplexer.notifyShapeCursorChange(xShape,
    1970           0 :                                                nPointerShape);
    1971             : }
    1972             : 
    1973           0 : bool SlideShowImpl::requestCursor( sal_Int16 nCursorShape )
    1974             : {
    1975           0 :     mnCurrentCursor = nCursorShape;
    1976             : 
    1977           0 :     const sal_Int16 nActualCursor = calcActiveCursor(mnCurrentCursor);
    1978             : 
    1979             :     // change all views to the requested cursor ID
    1980             :     std::for_each( maViewContainer.begin(),
    1981             :                    maViewContainer.end(),
    1982             :                    boost::bind( &View::setCursorShape,
    1983             :                                 _1,
    1984           0 :                                 nActualCursor ));
    1985             : 
    1986           0 :     return nActualCursor==nCursorShape;
    1987             : }
    1988             : 
    1989           0 : void SlideShowImpl::resetCursor()
    1990             : {
    1991           0 :     mnCurrentCursor = awt::SystemPointer::ARROW;
    1992             : 
    1993             :     // change all views to the default cursor ID
    1994             :     std::for_each( maViewContainer.begin(),
    1995             :                    maViewContainer.end(),
    1996             :                    boost::bind( &View::setCursorShape,
    1997             :                                 _1,
    1998           0 :                                 calcActiveCursor(mnCurrentCursor) ));
    1999           0 : }
    2000             : 
    2001           0 : sal_Bool SlideShowImpl::update( double & nNextTimeout )
    2002             :     throw (uno::RuntimeException, std::exception)
    2003             : {
    2004           0 :     osl::MutexGuard const guard( m_aMutex );
    2005             : 
    2006           0 :     if (isDisposed())
    2007           0 :         return false;
    2008             : 
    2009             :     // precondition: update() must only be called from the
    2010             :     // main thread!
    2011             :     DBG_TESTSOLARMUTEX();
    2012             : 
    2013           0 :     if( mbShowPaused )
    2014             :     {
    2015             :         // commit frame (might be repaints pending)
    2016           0 :         maScreenUpdater.commitUpdates();
    2017             : 
    2018           0 :         return false;
    2019             :     }
    2020             :     else
    2021             :     {
    2022             :         // TODO(F2): re-evaluate whether that timer lagging makes
    2023             :         // sense.
    2024             : 
    2025             :         // hold timer, while processing the queues:
    2026             :         // 1. when there is more than one active activity this ensures the
    2027             :         //    same time for all activities and events
    2028             :         // 2. processing of events may lead to creation of further events
    2029             :         //    that have zero delay.  While the timer is stopped these events
    2030             :         //    are processed in the same run.
    2031             :         {
    2032             :             //Get a shared-ptr that outlives the scope-guard which will
    2033             :             //ensure that the pointed-to-item exists in the case of a
    2034             :             //::dispose clearing mpPresTimer
    2035           0 :             boost::shared_ptr<canvas::tools::ElapsedTime> xTimer(mpPresTimer);
    2036             :             comphelper::ScopeGuard scopeGuard(
    2037             :                 boost::bind( &canvas::tools::ElapsedTime::releaseTimer,
    2038           0 :                              boost::cref(xTimer) ) );
    2039           0 :             xTimer->holdTimer();
    2040             : 
    2041             :             // process queues
    2042           0 :             maEventQueue.process();
    2043             : 
    2044             :             // #i118671# the call above may execute a macro bound to an object. In
    2045             :             // that case this macro may have destroyed this local sliseshow so that it
    2046             :             // is disposed (see bugdoc at task). In that case, detect this and exit
    2047             :             // gently from this slideshow. Do not forget to disable the scoped
    2048             :             // call to mpPresTimer, this will be deleted if we are disposed.
    2049           0 :             if (isDisposed())
    2050             :             {
    2051           0 :                 scopeGuard.dismiss();
    2052           0 :                 return false;
    2053             :             }
    2054             : 
    2055           0 :             maActivitiesQueue.process();
    2056             : 
    2057             :             // commit frame to screen
    2058           0 :             maFrameSynchronization.Synchronize();
    2059           0 :             maScreenUpdater.commitUpdates();
    2060             : 
    2061             :             // TODO(Q3): remove need to call dequeued() from
    2062             :             // activities. feels like a wart.
    2063             : 
    2064             :             // Rationale for ActivitiesQueue::processDequeued(): when
    2065             :             // an activity ends, it usually pushed the end state to
    2066             :             // the animated shape in question, and ends the animation
    2067             :             // (which, in turn, will usually disable shape sprite
    2068             :             // mode). Disabling shape sprite mode causes shape
    2069             :             // repaint, which, depending on slide content, takes
    2070             :             // considerably more time than sprite updates. Thus, the
    2071             :             // last animation step tends to look delayed. To
    2072             :             // camouflage this, reaching end position and disabling
    2073             :             // sprite mode is split into two (normal Activity::end(),
    2074             :             // and Activity::dequeued()). Now, the reason to call
    2075             :             // commitUpdates() twice here is caused by the unrelated
    2076             :             // fact that during wait cursor display/hide, the screen
    2077             :             // is updated, and shows hidden sprites, but, in case of
    2078             :             // leaving the second commitUpdates() call out and punting
    2079             :             // that to the next round, no updated static slide
    2080             :             // content. In short, the last shape animation of a slide
    2081             :             // tends to blink at its end.
    2082             : 
    2083             :             // process dequeued activities _after_ commit to screen
    2084           0 :             maActivitiesQueue.processDequeued();
    2085             : 
    2086             :             // commit frame to screen
    2087           0 :             maScreenUpdater.commitUpdates();
    2088             :         }
    2089             :         // Time held until here
    2090             : 
    2091           0 :         const bool bActivitiesLeft = (! maActivitiesQueue.isEmpty());
    2092           0 :         const bool bTimerEventsLeft = (! maEventQueue.isEmpty());
    2093           0 :         const bool bRet = (bActivitiesLeft || bTimerEventsLeft);
    2094             : 
    2095           0 :         if (bRet)
    2096             :         {
    2097             :             // calc nNextTimeout value:
    2098           0 :             if (bActivitiesLeft)
    2099             :             {
    2100             :                 // Activity queue is not empty.  Tell caller that we would
    2101             :                 // like to render another frame.
    2102             : 
    2103             :                 // Return a zero time-out to signal our caller to call us
    2104             :                 // back as soon as possible.  The actual timing, waiting the
    2105             :                 // appropriate amount of time between frames, is then done
    2106             :                 // by the maFrameSynchronization object.
    2107           0 :                 nNextTimeout = 0;
    2108           0 :                 maFrameSynchronization.Activate();
    2109             :             }
    2110             :             else
    2111             :             {
    2112             :                 // timer events left:
    2113             :                 // difference from current time (nota bene:
    2114             :                 // time no longer held here!) to the next event in
    2115             :                 // the event queue.
    2116             : 
    2117             :                 // #i61190# Retrieve next timeout only _after_
    2118             :                 // processing activity queue
    2119             : 
    2120             :                 // ensure positive value:
    2121           0 :                 nNextTimeout = std::max( 0.0, maEventQueue.nextTimeout() );
    2122             : 
    2123             :                 // There is no active animation so the frame rate does not
    2124             :                 // need to be synchronized.
    2125           0 :                 maFrameSynchronization.Deactivate();
    2126             :             }
    2127             : 
    2128           0 :             mbSlideShowIdle = false;
    2129             :         }
    2130             : 
    2131             : #if OSL_DEBUG_LEVEL >= 2 && defined(DBG_UTIL)
    2132             :         // when slideshow is idle, issue an XUpdatable::update() call
    2133             :         // exactly once after a previous animation sequence finished -
    2134             :         // this might trigger screen dumps on some canvas
    2135             :         // implementations
    2136             :         if( !mbSlideShowIdle &&
    2137             :             (!bRet ||
    2138             :              nNextTimeout > 1.0) )
    2139             :         {
    2140             :             UnoViewVector::const_iterator       aCurr(maViewContainer.begin());
    2141             :             const UnoViewVector::const_iterator aEnd(maViewContainer.end());
    2142             :             while( aCurr != aEnd )
    2143             :             {
    2144             :                 try
    2145             :                 {
    2146             :                     uno::Reference< presentation::XSlideShowView > xView( (*aCurr)->getUnoView(),
    2147             :                                                                           uno::UNO_QUERY_THROW );
    2148             :                     uno::Reference< util::XUpdatable >             xUpdatable( xView->getCanvas(),
    2149             :                                                                                uno::UNO_QUERY_THROW );
    2150             :                     xUpdatable->update();
    2151             :                 }
    2152             :                 catch( uno::RuntimeException& )
    2153             :                 {
    2154             :                     throw;
    2155             :                 }
    2156             :                 catch( uno::Exception& )
    2157             :                 {
    2158             :                     OSL_FAIL( OUStringToOString(
    2159             :                                     comphelper::anyToString( cppu::getCaughtException() ),
    2160             :                                     RTL_TEXTENCODING_UTF8 ).getStr() );
    2161             :                 }
    2162             : 
    2163             :                 ++aCurr;
    2164             :             }
    2165             : 
    2166             :             mbSlideShowIdle = true;
    2167             :         }
    2168             : #endif
    2169             : 
    2170           0 :         return bRet;
    2171           0 :     }
    2172             : }
    2173             : 
    2174           0 : void SlideShowImpl::notifySlideTransitionEnded( bool bPaintSlide )
    2175             : {
    2176           0 :     osl::MutexGuard const guard( m_aMutex );
    2177             : 
    2178             :     OSL_ENSURE( !isDisposed(), "### already disposed!" );
    2179             :     OSL_ENSURE( mpCurrentSlide,
    2180             :                 "notifySlideTransitionEnded(): Invalid current slide" );
    2181           0 :     if (mpCurrentSlide)
    2182             :     {
    2183           0 :         mpCurrentSlide->update_settings( !!maUserPaintColor, maUserPaintColor ? *maUserPaintColor : RGBColor(), maUserPaintStrokeWidth );
    2184             : 
    2185             :         // first init show, to give the animations
    2186             :         // the chance to register SlideStartEvents
    2187           0 :         const bool bBackgroundLayerRendered( !bPaintSlide );
    2188           0 :         mpCurrentSlide->show( bBackgroundLayerRendered );
    2189           0 :         maEventMultiplexer.notifySlideStartEvent();
    2190           0 :     }
    2191           0 : }
    2192             : 
    2193           0 : void queryAutomaticSlideTransition( uno::Reference<drawing::XDrawPage> const& xDrawPage,
    2194             :                                     double&                                   nAutomaticNextSlideTimeout,
    2195             :                                     bool&                                     bHasAutomaticNextSlide )
    2196             : {
    2197             :     // retrieve slide change parameters from XDrawPage
    2198             :     // ===============================================
    2199             : 
    2200             :     uno::Reference< beans::XPropertySet > xPropSet( xDrawPage,
    2201           0 :                                                     uno::UNO_QUERY );
    2202             : 
    2203           0 :     sal_Int32 nChange(0);
    2204           0 :     if( !xPropSet.is() ||
    2205             :         !getPropertyValue( nChange,
    2206             :                            xPropSet,
    2207             :                            OUString(
    2208           0 :                                "Change")) )
    2209             :     {
    2210             :         OSL_TRACE(
    2211             :             "queryAutomaticSlideTransition(): "
    2212             :             "Could not extract slide change mode from XDrawPage - assuming <none>\n" );
    2213             :     }
    2214             : 
    2215           0 :     bHasAutomaticNextSlide = nChange == 1;
    2216             : 
    2217           0 :     if( !xPropSet.is() ||
    2218             :         !getPropertyValue( nAutomaticNextSlideTimeout,
    2219             :                            xPropSet,
    2220             :                            OUString(
    2221           0 :                                "HighResDuration")) )
    2222             :     {
    2223             :         OSL_TRACE(
    2224             :             "queryAutomaticSlideTransition(): "
    2225             :             "Could not extract slide transition timeout from "
    2226             :             "XDrawPage - assuming 1 sec\n" );
    2227           0 :     }
    2228           0 : }
    2229             : 
    2230           0 : void SlideShowImpl::notifySlideAnimationsEnded()
    2231             : {
    2232           0 :     osl::MutexGuard const guard( m_aMutex );
    2233             : 
    2234             :     //Draw polygons above animations
    2235           0 :     mpCurrentSlide->drawPolygons();
    2236             : 
    2237             :     OSL_ENSURE( !isDisposed(), "### already disposed!" );
    2238             : 
    2239             :     // This struct will receive the (interruptable) event,
    2240             :     // that triggers the notifySlideEnded() method.
    2241           0 :     InterruptableEventPair aNotificationEvents;
    2242             : 
    2243           0 :     if( maEventMultiplexer.getAutomaticMode() )
    2244             :     {
    2245             :         OSL_ENSURE( ! mpRehearseTimingsActivity,
    2246             :                     "unexpected: RehearseTimings mode!" );
    2247             : 
    2248             :         // schedule a slide end event, with automatic mode's
    2249             :         // delay
    2250           0 :         aNotificationEvents = makeInterruptableDelay(
    2251           0 :             boost::bind<void>( boost::mem_fn(&SlideShowImpl::notifySlideEnded), this, false ),
    2252           0 :             maEventMultiplexer.getAutomaticTimeout() );
    2253             :     }
    2254             :     else
    2255             :     {
    2256             :         OSL_ENSURE( mpCurrentSlide,
    2257             :                     "notifySlideAnimationsEnded(): Invalid current slide!" );
    2258             : 
    2259           0 :         bool   bHasAutomaticNextSlide=false;
    2260           0 :         double nAutomaticNextSlideTimeout=0.0;
    2261           0 :         queryAutomaticSlideTransition(mpCurrentSlide->getXDrawPage(),
    2262             :                                       nAutomaticNextSlideTimeout,
    2263           0 :                                       bHasAutomaticNextSlide);
    2264             : 
    2265             :         // check whether slide transition should happen
    2266             :         // 'automatically'. If yes, simply schedule the
    2267             :         // specified timeout.
    2268             :         // NOTE: mbForceManualAdvance and mpRehearseTimingsActivity
    2269             :         // override any individual slide setting, to always
    2270             :         // step slides manually.
    2271           0 :         if( !mbForceManualAdvance &&
    2272           0 :             !mpRehearseTimingsActivity &&
    2273             :             bHasAutomaticNextSlide )
    2274             :         {
    2275           0 :             aNotificationEvents = makeInterruptableDelay(
    2276           0 :                 boost::bind<void>( boost::mem_fn(&SlideShowImpl::notifySlideEnded), this, false ),
    2277           0 :                 nAutomaticNextSlideTimeout);
    2278             : 
    2279             :             // TODO(F2): Provide a mechanism to let the user override
    2280             :             // this automatic timeout via next()
    2281             :         }
    2282             :         else
    2283             :         {
    2284           0 :             if (mpRehearseTimingsActivity)
    2285           0 :                 mpRehearseTimingsActivity->start();
    2286             : 
    2287             :             // generate click event. Thus, the user must
    2288             :             // trigger the actual end of a slide. No need to
    2289             :             // generate interruptable event here, there's no
    2290             :             // timeout involved.
    2291           0 :             aNotificationEvents.mpImmediateEvent =
    2292           0 :                 makeEvent( boost::bind<void>(
    2293             :                     boost::mem_fn(&SlideShowImpl::notifySlideEnded), this, false ),
    2294           0 :                     "SlideShowImpl::notifySlideEnded");
    2295             :         }
    2296             :     }
    2297             : 
    2298             :     // register events on the queues. To make automatic slide
    2299             :     // changes interruptable, register the interruption event
    2300             :     // as a nextEffectEvent target. Note that the timeout
    2301             :     // event is optional (e.g. manual slide changes don't
    2302             :     // generate a timeout)
    2303             :     maUserEventQueue.registerNextEffectEvent(
    2304           0 :         aNotificationEvents.mpImmediateEvent );
    2305             : 
    2306           0 :     if( aNotificationEvents.mpTimeoutEvent )
    2307           0 :         maEventQueue.addEvent( aNotificationEvents.mpTimeoutEvent );
    2308             : 
    2309             :     // current slide's main sequence is over. Now should be
    2310             :     // the time to prefetch the next slide (if any), and
    2311             :     // prepare the initial slide bitmap (speeds up slide
    2312             :     // change setup time a lot). Show the wait cursor, this
    2313             :     // indeed might take some seconds.
    2314             :     {
    2315           0 :         WaitSymbolLock aLock (*this);
    2316             : 
    2317           0 :         if (! matches( mpPrefetchSlide,
    2318           0 :                        mxPrefetchSlide, mxPrefetchAnimationNode ))
    2319             :         {
    2320           0 :             mpPrefetchSlide = makeSlide( mxPrefetchSlide, mxDrawPagesSupplier,
    2321           0 :                                          mxPrefetchAnimationNode );
    2322             :         }
    2323           0 :         if (mpPrefetchSlide)
    2324             :         {
    2325             :             // ignore return value, this is just to populate
    2326             :             // Slide's internal bitmap buffer, such that the time
    2327             :             // needed to generate the slide bitmap is not spent
    2328             :             // when the slide change is requested.
    2329           0 :             mpPrefetchSlide->getCurrentSlideBitmap( *maViewContainer.begin() );
    2330           0 :         }
    2331             :     } // finally
    2332             : 
    2333             :     maListenerContainer.forEach<presentation::XSlideShowListener>(
    2334           0 :         boost::mem_fn( &presentation::XSlideShowListener::slideAnimationsEnded ) );
    2335           0 : }
    2336             : 
    2337           0 : void SlideShowImpl::notifySlideEnded (const bool bReverse)
    2338             : {
    2339           0 :     osl::MutexGuard const guard( m_aMutex );
    2340             : 
    2341             :     OSL_ENSURE( !isDisposed(), "### already disposed!" );
    2342             : 
    2343           0 :     if (mpRehearseTimingsActivity && !bReverse)
    2344             :     {
    2345           0 :         const double time = mpRehearseTimingsActivity->stop();
    2346           0 :         if (mpRehearseTimingsActivity->hasBeenClicked())
    2347             :         {
    2348             :             // save time at current drawpage:
    2349             :             uno::Reference<beans::XPropertySet> xPropSet(
    2350           0 :                 mpCurrentSlide->getXDrawPage(), uno::UNO_QUERY );
    2351             :             OSL_ASSERT( xPropSet.is() );
    2352           0 :             if (xPropSet.is())
    2353             :             {
    2354           0 :                 xPropSet->setPropertyValue(
    2355             :                     "Change",
    2356           0 :                     uno::Any( static_cast<sal_Int32>(1) ) );
    2357           0 :                 xPropSet->setPropertyValue(
    2358             :                     "Duration",
    2359           0 :                     uno::Any( static_cast<sal_Int32>(time) ) );
    2360           0 :             }
    2361             :         }
    2362             :     }
    2363             : 
    2364           0 :     if (bReverse)
    2365           0 :         maEventMultiplexer.notifySlideEndEvent();
    2366             : 
    2367           0 :     stopShow();  // MUST call that: results in
    2368             :                  // maUserEventQueue.clear(). What's more,
    2369             :                  // stopShow()'s currSlide->hide() call is
    2370             :                  // now also required, notifySlideEnded()
    2371             :                  // relies on that
    2372             :                  // unconditionally. Otherwise, genuine
    2373             :                  // shape animations (drawing layer and
    2374             :                  // GIF) will not be stopped.
    2375             : 
    2376             :     maListenerContainer.forEach<presentation::XSlideShowListener>(
    2377             :         boost::bind<void>(
    2378             :             ::boost::mem_fn(&presentation::XSlideShowListener::slideEnded),
    2379             :             _1,
    2380           0 :             bReverse));
    2381           0 : }
    2382             : 
    2383           0 : bool SlideShowImpl::notifyHyperLinkClicked( OUString const& hyperLink )
    2384             : {
    2385           0 :     osl::MutexGuard const guard( m_aMutex );
    2386             : 
    2387             :     maListenerContainer.forEach<presentation::XSlideShowListener>(
    2388             :         boost::bind( &presentation::XSlideShowListener::hyperLinkClicked,
    2389             :                      _1,
    2390           0 :                      boost::cref(hyperLink) ));
    2391           0 :     return true;
    2392             : }
    2393             : 
    2394             : /** Notification from eventmultiplexer that an animation event has occoured.
    2395             :     This will be forewarded to all registered XSlideShoeListener
    2396             :  */
    2397           0 : bool SlideShowImpl::handleAnimationEvent( const AnimationNodeSharedPtr& rNode )
    2398             : {
    2399           0 :     osl::MutexGuard const guard( m_aMutex );
    2400             : 
    2401           0 :     uno::Reference<animations::XAnimationNode> xNode( rNode->getXAnimationNode() );
    2402             : 
    2403           0 :     switch( rNode->getState() )
    2404             :     {
    2405             :     case AnimationNode::ACTIVE:
    2406             :         maListenerContainer.forEach<presentation::XSlideShowListener>(
    2407             :             boost::bind( &animations::XAnimationListener::beginEvent,
    2408             :                          _1,
    2409           0 :                          boost::cref(xNode) ));
    2410           0 :         break;
    2411             : 
    2412             :     case AnimationNode::FROZEN:
    2413             :     case AnimationNode::ENDED:
    2414             :         maListenerContainer.forEach<presentation::XSlideShowListener>(
    2415             :             boost::bind( &animations::XAnimationListener::endEvent,
    2416             :                          _1,
    2417           0 :                          boost::cref(xNode) ));
    2418           0 :         if(mpCurrentSlide->isPaintOverlayActive())
    2419           0 :            mpCurrentSlide->drawPolygons();
    2420           0 :         break;
    2421             :     default:
    2422           0 :         break;
    2423             :     }
    2424             : 
    2425           0 :     return true;
    2426             : }
    2427             : 
    2428             : //===== FrameSynchronization ==================================================
    2429             : 
    2430           2 : FrameSynchronization::FrameSynchronization (const double nFrameDuration)
    2431             :     : maTimer(),
    2432             :       mnFrameDuration(nFrameDuration),
    2433             :       mnNextFrameTargetTime(0),
    2434           2 :       mbIsActive(false)
    2435             : {
    2436           2 :     MarkCurrentFrame();
    2437           2 : }
    2438             : 
    2439           2 : void FrameSynchronization::MarkCurrentFrame (void)
    2440             : {
    2441           2 :     mnNextFrameTargetTime = maTimer.getElapsedTime() + mnFrameDuration;
    2442           2 : }
    2443             : 
    2444           0 : void FrameSynchronization::Synchronize (void)
    2445             : {
    2446           0 :     if (mbIsActive)
    2447             :     {
    2448             :         // Do busy waiting for now.
    2449           0 :         while (maTimer.getElapsedTime() < mnNextFrameTargetTime)
    2450             :             ;
    2451             :     }
    2452             : 
    2453           0 :     MarkCurrentFrame();
    2454           0 : }
    2455             : 
    2456           0 : void FrameSynchronization::Activate (void)
    2457             : {
    2458           0 :     mbIsActive = true;
    2459           0 : }
    2460             : 
    2461           0 : void FrameSynchronization::Deactivate (void)
    2462             : {
    2463           0 :     mbIsActive = false;
    2464           0 : }
    2465             : 
    2466             : } // anon namespace
    2467             : 
    2468             : namespace sdecl = comphelper::service_decl;
    2469           4 : const sdecl::ServiceDecl slideShowDecl(
    2470             :      sdecl::class_<SlideShowImpl>(),
    2471             :     "com.sun.star.comp.presentation.SlideShow",
    2472           4 :     "com.sun.star.presentation.SlideShow" );
    2473             : 
    2474             : // The C shared lib entry points
    2475           8 : COMPHELPER_SERVICEDECL_EXPORTS1(slideshow, slideShowDecl)
    2476             : 
    2477             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10