1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_slideshow.hxx"
30 
31 #include <osl/diagnose.hxx>
32 #include <canvas/debug.hxx>
33 #include <tools/diagnose_ex.h>
34 #include <canvas/canvastools.hxx>
35 #include <cppcanvas/basegfxfactory.hxx>
36 
37 #include <basegfx/matrix/b2dhommatrix.hxx>
38 #include <basegfx/point/b2dpoint.hxx>
39 #include <basegfx/polygon/b2dpolygon.hxx>
40 #include <basegfx/polygon/b2dpolygontools.hxx>
41 #include <basegfx/numeric/ftools.hxx>
42 
43 #include <com/sun/star/awt/SystemPointer.hpp>
44 #include <com/sun/star/container/XIndexAccess.hpp>
45 #include <com/sun/star/drawing/XMasterPageTarget.hpp>
46 #include <com/sun/star/beans/XPropertySet.hpp>
47 #include <com/sun/star/container/XEnumerationAccess.hpp>
48 #include <com/sun/star/awt/Rectangle.hpp>
49 #include <com/sun/star/presentation/ParagraphTarget.hpp>
50 #include <com/sun/star/presentation/EffectNodeType.hpp>
51 #include <com/sun/star/animations/XAnimationNodeSupplier.hpp>
52 #include <com/sun/star/animations/XTargetPropertiesCreator.hpp>
53 #include <com/sun/star/drawing/TextAnimationKind.hpp>
54 
55 #include <animations/animationnodehelper.hxx>
56 
57 #include <cppuhelper/exc_hlp.hxx>
58 #include <comphelper/anytostring.hxx>
59 
60 #include "slide.hxx"
61 #include "slideshowcontext.hxx"
62 #include "slideanimations.hxx"
63 #include "doctreenode.hxx"
64 #include "screenupdater.hxx"
65 #include "cursormanager.hxx"
66 #include "shapeimporter.hxx"
67 #include "slideshowexceptions.hxx"
68 #include "eventqueue.hxx"
69 #include "activitiesqueue.hxx"
70 #include "layermanager.hxx"
71 #include "shapemanagerimpl.hxx"
72 #include "usereventqueue.hxx"
73 #include "userpaintoverlay.hxx"
74 #include "event.hxx"
75 #include "tools.hxx"
76 
77 #include <boost/bind.hpp>
78 #include <iterator>
79 #include <algorithm>
80 #include <functional>
81 #include <iostream>
82 
83 using namespace ::com::sun::star;
84 
85 // -----------------------------------------------------------------------------
86 
87 namespace slideshow
88 {
89 namespace internal
90 {
91 namespace
92 {
93 
94 class SlideImpl : public Slide,
95                   public CursorManager,
96                   public ViewEventHandler,
97                   public ::osl::DebugBase<SlideImpl>
98 {
99 public:
100     SlideImpl( const uno::Reference<drawing::XDrawPage>& 		 xDrawPage,
101                const uno::Reference<drawing::XDrawPagesSupplier>&	 xDrawPages,
102                const uno::Reference<animations::XAnimationNode>& xRootNode,
103                EventQueue&										 rEventQueue,
104                EventMultiplexer&								 rEventMultiplexer,
105                ScreenUpdater&                                    rScreenUpdater,
106                ActivitiesQueue&									 rActivitiesQueue,
107                UserEventQueue&									 rUserEventQueue,
108                CursorManager&                                    rCursorManager,
109                const UnoViewContainer&                           rViewContainer,
110                const uno::Reference<uno::XComponentContext>&     xContext,
111                const ShapeEventListenerMap&                      rShapeListenerMap,
112                const ShapeCursorMap&                             rShapeCursorMap,
113                const PolyPolygonVector&                          rPolyPolygonVector,
114                RGBColor const&                                   rUserPaintColor,
115                double                                            dUserPaintStrokeWidth,
116                bool                                              bUserPaintEnabled,
117                bool                                              bIntrinsicAnimationsAllowed,
118                bool                                              bDisableAnimationZOrder );
119 
120     ~SlideImpl();
121 
122 
123     // Disposable interface
124     // -------------------------------------------------------------------
125 
126     virtual void dispose();
127 
128 
129     // Slide interface
130     // -------------------------------------------------------------------
131 
132     virtual bool prefetch();
133     virtual bool show( bool );
134     virtual void hide();
135 
136     virtual basegfx::B2ISize getSlideSize() const;
137     virtual uno::Reference<drawing::XDrawPage > getXDrawPage() const;
138     virtual uno::Reference<animations::XAnimationNode> getXAnimationNode() const;
139     virtual PolyPolygonVector getPolygons();
140     virtual void drawPolygons() const;
141     virtual bool isPaintOverlayActive() const;
142     virtual void enablePaintOverlay();
143     virtual void disablePaintOverlay();
144 	virtual void update_settings( bool bUserPaintEnabled, RGBColor const& aUserPaintColor, double dUserPaintStrokeWidth );
145 
146 
147     // TODO(F2): Rework SlideBitmap to no longer be based on XBitmap,
148     // but on canvas-independent basegfx bitmaps
149     virtual SlideBitmapSharedPtr getCurrentSlideBitmap( const UnoViewSharedPtr& rView ) const;
150 
151 
152 private:
153     // ViewEventHandler
154     virtual void viewAdded( const UnoViewSharedPtr& rView );
155     virtual void viewRemoved( const UnoViewSharedPtr& rView );
156     virtual void viewChanged( const UnoViewSharedPtr& rView );
157     virtual void viewsChanged();
158 
159     // CursorManager
160     virtual bool requestCursor( sal_Int16 nCursorShape );
161     virtual void resetCursor();
162 
163 	void activatePaintOverlay();
164     void deactivatePaintOverlay();
165 
166     /** Query whether the slide has animations at all
167 
168         If the slide doesn't have animations, show() displays
169         only static content. If an event is registered with
170         registerSlideEndEvent(), this event will be
171         immediately activated at the end of the show() method.
172 
173         @return true, if this slide has animations, false
174         otherwise
175     */
176     bool isAnimated();
177 
178     /** Query whether this slide is currently showing.
179 
180         @return true, if this slide is currently showing.
181     */
182     bool isShowing() const;
183 
184     /// Set all Shapes to their initial attributes for slideshow
185     bool applyInitialShapeAttributes( const ::com::sun::star::uno::Reference<
186                                       ::com::sun::star::animations::XAnimationNode >& xRootAnimationNode );
187 
188     /// Renders current slide content to bitmap
189     SlideBitmapSharedPtr createCurrentSlideBitmap(
190         const UnoViewSharedPtr& rView,
191         ::basegfx::B2ISize const & rSlideSize ) const;
192 
193     /// Prefetch all shapes (not the animations)
194     bool loadShapes();
195 
196     /// Retrieve slide size from XDrawPage
197     basegfx::B2ISize getSlideSizeImpl() const;
198 
199     /// Prefetch show, but don't call applyInitialShapeAttributes()
200     bool implPrefetchShow();
201 
202     /// Query the rectangle covered by the slide
203     ::basegfx::B2DRectangle getSlideRect() const;
204 
205     /// Start GIF and other intrinsic shape animations
206     void endIntrinsicAnimations();
207 
208     /// End GIF and other intrinsic shape animations
209     void startIntrinsicAnimations();
210 
211     /// Add Polygons to the member maPolygons
212     void addPolygons(PolyPolygonVector aPolygons);
213 
214     // Types
215     // =====
216 
217     enum SlideAnimationState
218     {
219         CONSTRUCTING_STATE=0,
220         INITIAL_STATE=1,
221         SHOWING_STATE=2,
222         FINAL_STATE=3,
223         SlideAnimationState_NUM_ENTRIES=4
224     };
225 
226     typedef std::vector< SlideBitmapSharedPtr > VectorOfSlideBitmaps;
227     /** Vector of slide bitmaps.
228 
229         Since the bitmap content is sensitive to animation
230         effects, we have an inner vector containing a distinct
231         bitmap for each of the SlideAnimationStates.
232     */
233     typedef ::std::vector< std::pair< UnoViewSharedPtr,
234                                       VectorOfSlideBitmaps > > VectorOfVectorOfSlideBitmaps;
235 
236 
237     // Member variables
238     // ================
239 
240     /// The page model object
241     uno::Reference< drawing::XDrawPage >                mxDrawPage;
242     uno::Reference< drawing::XDrawPagesSupplier >       mxDrawPagesSupplier;
243     uno::Reference< animations::XAnimationNode >        mxRootNode;
244 
245     LayerManagerSharedPtr                               mpLayerManager;
246     boost::shared_ptr<ShapeManagerImpl>                 mpShapeManager;
247     boost::shared_ptr<SubsettableShapeManager>          mpSubsettableShapeManager;
248 
249     /// Contains common objects needed throughout the slideshow
250     SlideShowContext									maContext;
251 
252     /// parent cursor manager
253     CursorManager&                                      mrCursorManager;
254 
255     /// Handles the animation and event generation for us
256     SlideAnimations										maAnimations;
257     PolyPolygonVector                                   maPolygons;
258 
259     RGBColor                                            maUserPaintColor;
260     double                                              mdUserPaintStrokeWidth;
261     UserPaintOverlaySharedPtr							mpPaintOverlay;
262 
263     /// Bitmaps with slide content at various states
264     mutable VectorOfVectorOfSlideBitmaps                maSlideBitmaps;
265 
266     SlideAnimationState									meAnimationState;
267 
268     const basegfx::B2ISize                              maSlideSize;
269 
270     sal_Int16                                           mnCurrentCursor;
271 
272     /// True, when intrinsic shape animations are allowed
273     bool												mbIntrinsicAnimationsAllowed;
274 
275     /// True, when user paint overlay is enabled
276     bool                                                mbUserPaintOverlayEnabled;
277 
278     /// True, if initial load of all page shapes succeeded
279     bool												mbShapesLoaded;
280 
281     /// True, if initial load of all animation info succeeded
282     bool												mbShowLoaded;
283 
284     /** True, if this slide is not static.
285 
286         If this slide has animated content, this variable will
287         be true, and false otherwise.
288     */
289     bool												mbHaveAnimations;
290 
291     /** True, if this slide has a main animation sequence.
292 
293         If this slide has animation content, which in turn has
294         a main animation sequence (which must be fully run
295         before EventMultiplexer::notifySlideAnimationsEnd() is
296         called), this member is true.
297     */
298     bool												mbMainSequenceFound;
299 
300     /// When true, show() was called. Slide hidden oherwise.
301     bool                                                mbActive;
302 
303     ///When true, enablePaintOverlay was called and mbUserPaintOverlay = true
304     bool                                                mbPaintOverlayActive;
305 };
306 
307 
308 //////////////////////////////////////////////////////////////////////////////////
309 
310 
311 class SlideRenderer
312 {
313 public:
314     explicit SlideRenderer( SlideImpl& rSlide ) :
315         mrSlide( rSlide )
316     {
317     }
318 
319     void operator()( const UnoViewSharedPtr& rView )
320     {
321         // fully clear view content to background color
322         rView->clearAll();
323 
324         SlideBitmapSharedPtr 		 pBitmap( mrSlide.getCurrentSlideBitmap( rView ) );
325         ::cppcanvas::CanvasSharedPtr pCanvas( rView->getCanvas() );
326 
327         const ::basegfx::B2DHomMatrix 	aViewTransform( rView->getTransformation() );
328         const ::basegfx::B2DPoint 		aOutPosPixel( aViewTransform * ::basegfx::B2DPoint() );
329 
330         // setup a canvas with device coordinate space, the slide
331         // bitmap already has the correct dimension.
332         ::cppcanvas::CanvasSharedPtr pDevicePixelCanvas( pCanvas->clone() );
333         pDevicePixelCanvas->setTransformation( ::basegfx::B2DHomMatrix() );
334 
335         // render at given output position
336         pBitmap->move( aOutPosPixel );
337 
338         // clear clip (might have been changed, e.g. from comb
339         // transition)
340         pBitmap->clip( ::basegfx::B2DPolyPolygon() );
341         pBitmap->draw( pDevicePixelCanvas );
342     }
343 
344 private:
345     SlideImpl& mrSlide;
346 };
347 
348 
349 //////////////////////////////////////////////////////////////////////////////////
350 
351 
352 SlideImpl::SlideImpl( const uno::Reference< drawing::XDrawPage >&			xDrawPage,
353                       const uno::Reference<drawing::XDrawPagesSupplier>&    xDrawPages,
354                       const uno::Reference< animations::XAnimationNode >& 	xRootNode,
355                       EventQueue&											rEventQueue,
356                       EventMultiplexer&										rEventMultiplexer,
357                       ScreenUpdater&                                        rScreenUpdater,
358                       ActivitiesQueue&										rActivitiesQueue,
359                       UserEventQueue&										rUserEventQueue,
360                       CursorManager&                                        rCursorManager,
361                       const UnoViewContainer&                               rViewContainer,
362                       const uno::Reference< uno::XComponentContext >& 		xComponentContext,
363                       const ShapeEventListenerMap&                          rShapeListenerMap,
364                       const ShapeCursorMap&                                 rShapeCursorMap,
365                       const PolyPolygonVector&                              rPolyPolygonVector,
366                       RGBColor const&                                       aUserPaintColor,
367                       double                                                dUserPaintStrokeWidth,
368                       bool                                                  bUserPaintEnabled,
369                       bool                                                  bIntrinsicAnimationsAllowed,
370                       bool                                                  bDisableAnimationZOrder ) :
371     mxDrawPage( xDrawPage ),
372     mxDrawPagesSupplier( xDrawPages ),
373     mxRootNode( xRootNode ),
374     mpLayerManager( new LayerManager(
375                         rViewContainer,
376                         getSlideRect(),
377                         bDisableAnimationZOrder) ),
378     mpShapeManager( new ShapeManagerImpl(
379                         rEventMultiplexer,
380                         mpLayerManager,
381                         rCursorManager,
382                         rShapeListenerMap,
383                         rShapeCursorMap)),
384     mpSubsettableShapeManager( mpShapeManager ),
385     maContext( mpSubsettableShapeManager,
386                rEventQueue,
387                rEventMultiplexer,
388                rScreenUpdater,
389                rActivitiesQueue,
390                rUserEventQueue,
391                *this,
392                rViewContainer,
393                xComponentContext ),
394     mrCursorManager( rCursorManager ),
395     maAnimations( maContext,
396                   getSlideSizeImpl() ),
397     maPolygons(rPolyPolygonVector),
398     maUserPaintColor(aUserPaintColor),
399     mdUserPaintStrokeWidth(dUserPaintStrokeWidth),
400     mpPaintOverlay(),
401     maSlideBitmaps(),
402     meAnimationState( CONSTRUCTING_STATE ),
403     maSlideSize(getSlideSizeImpl()),
404     mnCurrentCursor( awt::SystemPointer::ARROW ),
405     mbIntrinsicAnimationsAllowed( bIntrinsicAnimationsAllowed ),
406     mbUserPaintOverlayEnabled(bUserPaintEnabled),
407     mbShapesLoaded( false ),
408     mbShowLoaded( false ),
409     mbHaveAnimations( false ),
410     mbMainSequenceFound( false ),
411     mbActive( false ),
412     mbPaintOverlayActive( false )
413 {
414     // clone already existing views for slide bitmaps
415     std::for_each( rViewContainer.begin(),
416                    rViewContainer.end(),
417                    boost::bind( &SlideImpl::viewAdded,
418                                 this,
419                                 _1 ));
420 
421     // register screen update (LayerManager needs to signal pending
422     // updates)
423     maContext.mrScreenUpdater.addViewUpdate(mpShapeManager);
424 }
425 
426 void SlideImpl::update_settings( bool bUserPaintEnabled, RGBColor const& aUserPaintColor, double dUserPaintStrokeWidth )
427 {
428 	maUserPaintColor = aUserPaintColor;
429     mdUserPaintStrokeWidth = dUserPaintStrokeWidth;
430 	mbUserPaintOverlayEnabled = bUserPaintEnabled;
431 }
432 
433 SlideImpl::~SlideImpl()
434 {
435     if( mpShapeManager )
436     {
437         maContext.mrScreenUpdater.removeViewUpdate(mpShapeManager);
438         mpShapeManager->dispose();
439 
440         // TODO(Q3): Make sure LayerManager (and thus Shapes) dies
441         // first, because SlideShowContext has SubsettableShapeManager
442         // as reference member.
443         mpLayerManager.reset();
444     }
445 }
446 
447 void SlideImpl::dispose()
448 {
449     maSlideBitmaps.clear();
450     mpPaintOverlay.reset();
451     maAnimations.dispose();
452     maContext.dispose();
453 
454     if( mpShapeManager )
455     {
456         maContext.mrScreenUpdater.removeViewUpdate(mpShapeManager);
457         mpShapeManager->dispose();
458     }
459 
460     // TODO(Q3): Make sure LayerManager (and thus Shapes) dies first,
461     // because SlideShowContext has SubsettableShapeManager as
462     // reference member.
463     mpLayerManager.reset();
464     mpSubsettableShapeManager.reset();
465     mpShapeManager.reset();
466     mxRootNode.clear();
467     mxDrawPage.clear();
468     mxDrawPagesSupplier.clear();
469 }
470 
471 bool SlideImpl::prefetch()
472 {
473     if( !mxRootNode.is() )
474         return false;
475 
476     return applyInitialShapeAttributes(mxRootNode);
477 }
478 
479 bool SlideImpl::show( bool bSlideBackgoundPainted )
480 {
481     // ---------------------------------------------------------------
482 
483     if( mbActive )
484         return true; // already active
485 
486     if( !mpShapeManager || !mpLayerManager )
487         return false; // disposed
488 
489     // ---------------------------------------------------------------
490 
491     // set initial shape attributes (e.g. hide shapes that have
492     // 'appear' effect set)
493     if( !applyInitialShapeAttributes(mxRootNode) )
494         return false;
495 
496     // ---------------------------------------------------------------
497 
498     // activate and take over view - clears view, if necessary
499     mbActive = true;
500     requestCursor( mnCurrentCursor );
501 
502     // enable shape management & event broadcasting for shapes of this
503     // slide. Also enables LayerManager to record updates. Currently,
504     // never let LayerManager render initial slide content, use
505     // buffered slide bitmaps instead.
506     mpShapeManager->activate( true );
507 
508     // ---------------------------------------------------------------
509 
510     // render slide to screen, if requested
511     if( !bSlideBackgoundPainted )
512     {
513         std::for_each(maContext.mrViewContainer.begin(),
514                       maContext.mrViewContainer.end(),
515                       boost::mem_fn(&View::clearAll));
516 
517         std::for_each( maContext.mrViewContainer.begin(),
518                        maContext.mrViewContainer.end(),
519                        SlideRenderer(*this) );
520         maContext.mrScreenUpdater.notifyUpdate();
521     }
522 
523     // ---------------------------------------------------------------
524 
525     // fire up animations
526     const bool bIsAnimated( isAnimated() );
527     if( bIsAnimated )
528         maAnimations.start(); // feeds initial events into queue
529 
530     // NOTE: this looks slightly weird, but is indeed correct:
531     // as isAnimated() might return false, _although_ there is
532     // a main sequence (because the animation nodes don't
533     // contain any executable effects), we gotta check both
534     // conditions here.
535     if( !bIsAnimated || !mbMainSequenceFound )
536     {
537         // manually trigger a slide animation end event (we don't have
538         // animations at all, or we don't have a main animation
539         // sequence, but if we had, it'd end now). Note that having
540         // animations alone does not matter here, as only main
541         // sequence animations prevents showing the next slide on
542         // nextEvent().
543         maContext.mrEventMultiplexer.notifySlideAnimationsEnd();
544     }
545 
546     // enable shape-intrinsic animations (drawing layer animations or
547     // GIF animations)
548     if( mbIntrinsicAnimationsAllowed )
549         startIntrinsicAnimations();
550 
551     // ---------------------------------------------------------------
552 
553     // enable paint overlay, if maUserPaintColor is valid
554     activatePaintOverlay();
555 
556     // ---------------------------------------------------------------
557 
558     // from now on, animations might be showing
559     meAnimationState = SHOWING_STATE;
560 
561     return true;
562 }
563 
564 void SlideImpl::hide()
565 {
566     if( !mbActive || !mpShapeManager )
567         return; // already hidden/disposed
568 
569     // ---------------------------------------------------------------
570 
571     // from now on, all animations are stopped
572     meAnimationState = FINAL_STATE;
573 
574     // ---------------------------------------------------------------
575 
576     // disable user paint overlay under all circumstances,
577     // this slide now ceases to be active.
578     deactivatePaintOverlay();
579 
580     // ---------------------------------------------------------------
581 
582     // switch off all shape-intrinsic animations.
583     endIntrinsicAnimations();
584 
585     // force-end all SMIL animations, too
586     maAnimations.end();
587 
588     // ---------------------------------------------------------------
589 
590     // disable shape management & event broadcasting for shapes of this
591     // slide. Also disables LayerManager.
592     mpShapeManager->deactivate();
593 
594     // vanish from view
595     resetCursor();
596     mbActive = false;
597 
598     // ---------------------------------------------------------------
599 }
600 
601 basegfx::B2ISize SlideImpl::getSlideSize() const
602 {
603     return maSlideSize;
604 }
605 
606 uno::Reference<drawing::XDrawPage > SlideImpl::getXDrawPage() const
607 {
608     return mxDrawPage;
609 }
610 
611 uno::Reference<animations::XAnimationNode> SlideImpl::getXAnimationNode() const
612 {
613     return mxRootNode;
614 }
615 
616 PolyPolygonVector SlideImpl::getPolygons()
617 {
618     if(mbPaintOverlayActive)
619         maPolygons = mpPaintOverlay->getPolygons();
620     return maPolygons;
621 }
622 
623 SlideBitmapSharedPtr SlideImpl::getCurrentSlideBitmap( const UnoViewSharedPtr& rView ) const
624 {
625     // search corresponding entry in maSlideBitmaps (which
626     // contains the views as the key)
627     VectorOfVectorOfSlideBitmaps::iterator       aIter;
628     const VectorOfVectorOfSlideBitmaps::iterator aEnd( maSlideBitmaps.end() );
629     if( (aIter=std::find_if( maSlideBitmaps.begin(),
630                              aEnd,
631                              boost::bind(
632                                  std::equal_to<UnoViewSharedPtr>(),
633                                  rView,
634                                  // select view:
635                                  boost::bind(
636                                      std::select1st<VectorOfVectorOfSlideBitmaps::value_type>(),
637                                      _1 )))) == aEnd )
638     {
639         // corresponding view not found - maybe view was not
640         // added to Slide?
641         ENSURE_OR_THROW( false,
642                           "SlideImpl::getInitialSlideBitmap(): view does not "
643                           "match any of the added ones" );
644     }
645 
646     // ensure that the show is loaded
647     if( !mbShowLoaded )
648     {
649         // only prefetch and init shapes when not done already
650         // (otherwise, at least applyInitialShapeAttributes() will be
651         // called twice for initial slide rendering). Furthermore,
652         // applyInitialShapeAttributes() _always_ performs
653         // initializations, which would be highly unwanted during a
654         // running show. OTOH, a slide whose mbShowLoaded is false is
655         // guaranteed not be running a show.
656 
657         // set initial shape attributes (e.g. hide 'appear' effect
658         // shapes)
659         if( !const_cast<SlideImpl*>(this)->applyInitialShapeAttributes( mxRootNode ) )
660             ENSURE_OR_THROW(false,
661                              "SlideImpl::getCurrentSlideBitmap(): Cannot "
662                              "apply initial attributes");
663     }
664 
665     SlideBitmapSharedPtr&     rBitmap( aIter->second.at( meAnimationState ));
666     const ::basegfx::B2ISize& rSlideSize(
667         getSlideSizePixel( getSlideSize(),
668                            rView ));
669 
670     // is the bitmap valid (actually existent, and of correct
671     // size)?
672     if( !rBitmap || rBitmap->getSize() != rSlideSize )
673     {
674         // no bitmap there yet, or wrong size - create one
675         rBitmap = createCurrentSlideBitmap(rView, rSlideSize);
676     }
677 
678     return rBitmap;
679 }
680 
681 
682 // private methods
683 //--------------------------------------------------------------------------------------------------------------
684 
685 
686 void SlideImpl::viewAdded( const UnoViewSharedPtr& rView )
687 {
688     maSlideBitmaps.push_back(
689         std::make_pair( rView,
690                         VectorOfSlideBitmaps(SlideAnimationState_NUM_ENTRIES) ));
691 
692     if( mpLayerManager )
693         mpLayerManager->viewAdded( rView );
694 }
695 
696 void SlideImpl::viewRemoved( const UnoViewSharedPtr& rView )
697 {
698     if( mpLayerManager )
699         mpLayerManager->viewRemoved( rView );
700 
701     const VectorOfVectorOfSlideBitmaps::iterator aEnd( maSlideBitmaps.end() );
702     maSlideBitmaps.erase(
703         std::remove_if( maSlideBitmaps.begin(),
704                         aEnd,
705                         boost::bind(
706                             std::equal_to<UnoViewSharedPtr>(),
707                             rView,
708                             // select view:
709                             boost::bind(
710                                 std::select1st<VectorOfVectorOfSlideBitmaps::value_type>(),
711                                 _1 ))),
712         aEnd );
713 }
714 
715 void SlideImpl::viewChanged( const UnoViewSharedPtr& rView )
716 {
717     // nothing to do for the Slide - getCurrentSlideBitmap() lazily
718     // handles bitmap resizes
719     if( mbActive && mpLayerManager )
720         mpLayerManager->viewChanged(rView);
721 }
722 
723 void SlideImpl::viewsChanged()
724 {
725     // nothing to do for the Slide - getCurrentSlideBitmap() lazily
726     // handles bitmap resizes
727     if( mbActive && mpLayerManager )
728         mpLayerManager->viewsChanged();
729 }
730 
731 bool SlideImpl::requestCursor( sal_Int16 nCursorShape )
732 {
733     mnCurrentCursor = nCursorShape;
734     return mrCursorManager.requestCursor(mnCurrentCursor);
735 }
736 
737 void SlideImpl::resetCursor()
738 {
739     mnCurrentCursor = awt::SystemPointer::ARROW;
740     mrCursorManager.resetCursor();
741 }
742 
743 bool SlideImpl::isShowing() const
744 {
745     return meAnimationState == SHOWING_STATE;
746 }
747 
748 bool SlideImpl::isAnimated()
749 {
750     // prefetch, but don't apply initial shape attributes
751     if( !implPrefetchShow() )
752         return false;
753 
754     return mbHaveAnimations && maAnimations.isAnimated();
755 }
756 
757 SlideBitmapSharedPtr SlideImpl::createCurrentSlideBitmap( const UnoViewSharedPtr&   rView,
758                                                           const ::basegfx::B2ISize& rBmpSize ) const
759 {
760     ENSURE_OR_THROW( rView && rView->getCanvas(),
761                       "SlideImpl::createCurrentSlideBitmap(): Invalid view" );
762     ENSURE_OR_THROW( mpLayerManager,
763                       "SlideImpl::createCurrentSlideBitmap(): Invalid layer manager" );
764     ENSURE_OR_THROW( mbShowLoaded,
765                       "SlideImpl::createCurrentSlideBitmap(): No show loaded" );
766 
767     ::cppcanvas::CanvasSharedPtr pCanvas( rView->getCanvas() );
768 
769     // create a bitmap of appropriate size
770     ::cppcanvas::BitmapSharedPtr pBitmap(
771         ::cppcanvas::BaseGfxFactory::getInstance().createBitmap(
772             pCanvas,
773             rBmpSize ) );
774 
775     ENSURE_OR_THROW( pBitmap,
776                       "SlideImpl::createCurrentSlideBitmap(): Cannot create page bitmap" );
777 
778     ::cppcanvas::BitmapCanvasSharedPtr pBitmapCanvas( pBitmap->getBitmapCanvas() );
779 
780     ENSURE_OR_THROW( pBitmapCanvas,
781                       "SlideImpl::createCurrentSlideBitmap(): Cannot create page bitmap canvas" );
782 
783     // apply linear part of destination canvas transformation (linear means in this context:
784     // transformation without any translational components)
785     ::basegfx::B2DHomMatrix aLinearTransform( rView->getTransformation() );
786     aLinearTransform.set( 0, 2, 0.0 );
787     aLinearTransform.set( 1, 2, 0.0 );
788     pBitmapCanvas->setTransformation( aLinearTransform );
789 
790     // output all shapes to bitmap
791     initSlideBackground( pBitmapCanvas, rBmpSize );
792     mpLayerManager->renderTo( pBitmapCanvas );
793 
794     return SlideBitmapSharedPtr( new SlideBitmap( pBitmap ) );
795 }
796 
797 namespace
798 {
799     class MainSequenceSearcher
800     {
801     public:
802         MainSequenceSearcher()
803         {
804             maSearchKey.Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "node-type" ) );
805             maSearchKey.Value <<= presentation::EffectNodeType::MAIN_SEQUENCE;
806         }
807 
808         void operator()( const uno::Reference< animations::XAnimationNode >& xChildNode )
809         {
810             uno::Sequence< beans::NamedValue > aUserData( xChildNode->getUserData() );
811 
812             if( findNamedValue( aUserData, maSearchKey ) )
813             {
814                 maMainSequence = xChildNode;
815             }
816         }
817 
818         uno::Reference< animations::XAnimationNode > getMainSequence() const
819         {
820             return maMainSequence;
821         }
822 
823     private:
824         beans::NamedValue 								maSearchKey;
825         uno::Reference< animations::XAnimationNode >	maMainSequence;
826     };
827 }
828 
829 bool SlideImpl::implPrefetchShow()
830 {
831     if( mbShowLoaded )
832         return true;
833 
834     ENSURE_OR_RETURN_FALSE( mxDrawPage.is(),
835                        "SlideImpl::implPrefetchShow(): Invalid draw page" );
836     ENSURE_OR_RETURN_FALSE( mpLayerManager,
837                        "SlideImpl::implPrefetchShow(): Invalid layer manager" );
838 
839     // fetch desired page content
840     // ==========================
841 
842     if( !loadShapes() )
843         return false;
844 
845     // New animations framework: import the shape effect info
846     // ======================================================
847 
848     try
849     {
850         if( mxRootNode.is() )
851         {
852             if( !maAnimations.importAnimations( mxRootNode ) )
853             {
854                 OSL_ENSURE( false,
855                             "SlideImpl::implPrefetchShow(): have animation nodes, "
856                             "but import animations failed." );
857 
858                 // could not import animation framework,
859                 // _although_ some animation nodes are there -
860                 // this is an error (not finding animations at
861                 // all is okay - might be a static slide)
862                 return false;
863             }
864 
865             // now check whether we've got a main sequence (if
866             // not, we must manually call
867             // EventMultiplexer::notifySlideAnimationsEnd()
868             // above, as e.g. interactive sequences alone
869             // don't block nextEvent() from issuing the next
870             // slide)
871             MainSequenceSearcher aSearcher;
872             if( ::anim::for_each_childNode( mxRootNode, aSearcher ) )
873                 mbMainSequenceFound = aSearcher.getMainSequence().is();
874 
875             // import successfully done
876             mbHaveAnimations = true;
877         }
878     }
879     catch( uno::RuntimeException& )
880     {
881         throw;
882     }
883     catch( uno::Exception& )
884     {
885         OSL_ENSURE(
886             false,
887             rtl::OUStringToOString(
888                 comphelper::anyToString(cppu::getCaughtException()),
889                 RTL_TEXTENCODING_UTF8 ) );
890         // TODO(E2): Error handling. For now, bail out
891     }
892 
893     mbShowLoaded = true;
894 
895     return true;
896 }
897 
898 void SlideImpl::enablePaintOverlay()
899 {
900 	if( !mbUserPaintOverlayEnabled || !mbPaintOverlayActive )
901 	{
902 		mbUserPaintOverlayEnabled = true;
903 		activatePaintOverlay();
904 	}
905 }
906 
907 void SlideImpl::disablePaintOverlay()
908 {
909 }
910 
911 void SlideImpl::activatePaintOverlay()
912 {
913     if( mbUserPaintOverlayEnabled || !maPolygons.empty() )
914     {
915         mpPaintOverlay = UserPaintOverlay::create( maUserPaintColor,
916                                                    mdUserPaintStrokeWidth,
917                                                    maContext,
918                                                    maPolygons,
919 												   mbUserPaintOverlayEnabled );
920         mbPaintOverlayActive = true;
921     }
922 }
923 
924 void SlideImpl::drawPolygons() const
925 {
926     if( mpPaintOverlay  )
927         mpPaintOverlay->drawPolygons();
928 }
929 
930 void SlideImpl::addPolygons(PolyPolygonVector aPolygons)
931 {
932     if(!aPolygons.empty())
933     {
934         for( PolyPolygonVector::iterator aIter=aPolygons.begin(),
935                  aEnd=aPolygons.end();
936              aIter!=aEnd;
937              ++aIter )
938         {
939             maPolygons.push_back(*aIter);
940         }
941     }
942 }
943 
944 bool SlideImpl::isPaintOverlayActive() const
945 {
946     return mbPaintOverlayActive;
947 }
948 
949 void SlideImpl::deactivatePaintOverlay()
950 {
951     if(mbPaintOverlayActive)
952         maPolygons = mpPaintOverlay->getPolygons();
953 
954     mpPaintOverlay.reset();
955     mbPaintOverlayActive = false;
956 }
957 
958 ::basegfx::B2DRectangle SlideImpl::getSlideRect() const
959 {
960     const basegfx::B2ISize slideSize( getSlideSizeImpl() );
961     return ::basegfx::B2DRectangle(0.0,0.0,
962                                    slideSize.getX(),
963                                    slideSize.getY());
964 }
965 
966 void SlideImpl::endIntrinsicAnimations()
967 {
968     mpSubsettableShapeManager->notifyIntrinsicAnimationsDisabled();
969 }
970 
971 void SlideImpl::startIntrinsicAnimations()
972 {
973     mpSubsettableShapeManager->notifyIntrinsicAnimationsEnabled();
974 }
975 
976 bool SlideImpl::applyInitialShapeAttributes(
977     const uno::Reference< animations::XAnimationNode >& xRootAnimationNode )
978 {
979     if( !implPrefetchShow() )
980         return false;
981 
982     if( !xRootAnimationNode.is() )
983     {
984         meAnimationState = INITIAL_STATE;
985 
986         return true; // no animations - no attributes to apply -
987                      // succeeded
988     }
989 
990     uno::Reference< animations::XTargetPropertiesCreator > xPropsCreator;
991 
992     try
993     {
994         ENSURE_OR_RETURN_FALSE( maContext.mxComponentContext.is(),
995                            "SlideImpl::applyInitialShapeAttributes(): Invalid component context" );
996 
997         uno::Reference<lang::XMultiComponentFactory> xFac(
998             maContext.mxComponentContext->getServiceManager() );
999 
1000         xPropsCreator.set(
1001             xFac->createInstanceWithContext(
1002                 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
1003                                      "com.sun.star.animations.TargetPropertiesCreator") ),
1004                 maContext.mxComponentContext ),
1005             uno::UNO_QUERY_THROW );
1006     }
1007     catch( uno::RuntimeException& )
1008     {
1009         throw;
1010     }
1011     catch( uno::Exception& )
1012     {
1013         OSL_ENSURE(
1014             false,
1015             rtl::OUStringToOString(
1016                 comphelper::anyToString(cppu::getCaughtException()),
1017                 RTL_TEXTENCODING_UTF8 ) );
1018 
1019         // could not determine initial shape attributes - this
1020         // is an error, as some effects might then be plainly
1021         // invisible
1022         ENSURE_OR_RETURN_FALSE( false,
1023                            "SlideImpl::applyInitialShapeAttributes(): "
1024                            "couldn't create TargetPropertiesCreator." );
1025     }
1026 
1027     uno::Sequence< animations::TargetProperties > aProps(
1028         xPropsCreator->createInitialTargetProperties( xRootAnimationNode ) );
1029 
1030     // apply extracted values to our shapes
1031     const ::std::size_t nSize( aProps.getLength() );
1032     for( ::std::size_t i=0; i<nSize; ++i )
1033     {
1034         sal_Int16 						  nParaIndex( -1 );
1035         uno::Reference< drawing::XShape > xShape( aProps[i].Target,
1036                                                   uno::UNO_QUERY );
1037 
1038         if( !xShape.is() )
1039         {
1040             // not a shape target. Maybe a ParagraphTarget?
1041             presentation::ParagraphTarget aParaTarget;
1042 
1043             if( (aProps[i].Target >>= aParaTarget) )
1044             {
1045                 // yep, ParagraphTarget found - extract shape
1046                 // and index
1047                 xShape = aParaTarget.Shape;
1048                 nParaIndex = aParaTarget.Paragraph;
1049             }
1050         }
1051 
1052         if( xShape.is() )
1053         {
1054             ShapeSharedPtr pShape( mpLayerManager->lookupShape( xShape ) );
1055 
1056             if( !pShape )
1057             {
1058                 OSL_ENSURE( false,
1059                             "SlideImpl::applyInitialShapeAttributes(): no shape found for given target" );
1060                 continue;
1061             }
1062 
1063             AttributableShapeSharedPtr pAttrShape(
1064                 ::boost::dynamic_pointer_cast< AttributableShape >( pShape ) );
1065 
1066             if( !pAttrShape )
1067             {
1068                 OSL_ENSURE( false,
1069                             "SlideImpl::applyInitialShapeAttributes(): shape found does not "
1070                             "implement AttributableShape interface" );
1071                 continue;
1072             }
1073 
1074             if( nParaIndex != -1 )
1075             {
1076                 // our target is a paragraph subset, thus look
1077                 // this up first.
1078                 const DocTreeNodeSupplier& rNodeSupplier( pAttrShape->getTreeNodeSupplier() );
1079 
1080                 pAttrShape = pAttrShape->getSubset(
1081                     rNodeSupplier.getTreeNode(
1082                         nParaIndex,
1083                         DocTreeNode::NODETYPE_LOGICAL_PARAGRAPH ) );
1084 
1085                 if( !pAttrShape )
1086                 {
1087                     OSL_ENSURE( false,
1088                                 "SlideImpl::applyInitialShapeAttributes(): shape found does not "
1089                                 "provide a subset for requested paragraph index" );
1090                     continue;
1091                 }
1092             }
1093 
1094             const uno::Sequence< beans::NamedValue >& rShapeProps( aProps[i].Properties );
1095             const ::std::size_t nShapePropSize( rShapeProps.getLength() );
1096             for( ::std::size_t j=0; j<nShapePropSize; ++j )
1097             {
1098                 bool bVisible=false;
1099                 if( rShapeProps[j].Name.equalsIgnoreAsciiCaseAscii("visibility") &&
1100                     extractValue( bVisible,
1101                                   rShapeProps[j].Value,
1102                                   pShape,
1103                                   getSlideSize() ))
1104                 {
1105                     pAttrShape->setVisibility( bVisible );
1106                 }
1107                 else
1108                 {
1109                     OSL_ENSURE( false,
1110                                 "SlideImpl::applyInitialShapeAttributes(): Unexpected "
1111                                 "(and unimplemented) property encountered" );
1112                 }
1113             }
1114         }
1115     }
1116 
1117     meAnimationState = INITIAL_STATE;
1118 
1119     return true;
1120 }
1121 
1122 bool SlideImpl::loadShapes()
1123 {
1124     if( mbShapesLoaded )
1125         return true;
1126 
1127     ENSURE_OR_RETURN_FALSE( mxDrawPage.is(),
1128                        "SlideImpl::loadShapes(): Invalid draw page" );
1129     ENSURE_OR_RETURN_FALSE( mpLayerManager,
1130                        "SlideImpl::loadShapes(): Invalid layer manager" );
1131 
1132     // fetch desired page content
1133     // ==========================
1134 
1135     // also take master page content
1136     uno::Reference< drawing::XDrawPage > xMasterPage;
1137     uno::Reference< drawing::XShapes >   xMasterPageShapes;
1138     sal_Int32                            nCurrCount(0);
1139 
1140     uno::Reference< drawing::XMasterPageTarget > xMasterPageTarget( mxDrawPage,
1141                                                                     uno::UNO_QUERY );
1142     if( xMasterPageTarget.is() )
1143     {
1144         xMasterPage = xMasterPageTarget->getMasterPage();
1145         xMasterPageShapes.set( xMasterPage,
1146                                uno::UNO_QUERY );
1147 
1148         if( xMasterPage.is() && xMasterPageShapes.is() )
1149         {
1150             // TODO(P2): maybe cache master pages here (or treat the
1151             // masterpage as a single metafile. At least currently,
1152             // masterpages do not contain animation effects)
1153             try
1154             {
1155                 // load the masterpage shapes
1156                 // -------------------------------------------------------------------------
1157                 ShapeImporter aMPShapesFunctor( xMasterPage,
1158                                                 mxDrawPage,
1159                                                 mxDrawPagesSupplier,
1160                                                 maContext,
1161                                                 0, /* shape num starts at 0 */
1162                                                 true );
1163 
1164                 mpLayerManager->addShape(
1165                     aMPShapesFunctor.importBackgroundShape() );
1166 
1167                 while( !aMPShapesFunctor.isImportDone() )
1168                 {
1169                     ShapeSharedPtr const& rShape(
1170                         aMPShapesFunctor.importShape() );
1171                     if( rShape )
1172                         mpLayerManager->addShape( rShape );
1173                 }
1174                 addPolygons(aMPShapesFunctor.getPolygons());
1175 
1176                 nCurrCount = xMasterPageShapes->getCount() + 1;
1177             }
1178             catch( uno::RuntimeException& )
1179             {
1180                 throw;
1181             }
1182             catch( ShapeLoadFailedException& )
1183             {
1184                 // TODO(E2): Error handling. For now, bail out
1185                 OSL_ENSURE( false,
1186                             "SlideImpl::loadShapes(): caught ShapeLoadFailedException" );
1187                 return false;
1188 
1189             }
1190             catch( uno::Exception& )
1191             {
1192                 OSL_ENSURE( false,
1193                             rtl::OUStringToOString(
1194                                 comphelper::anyToString( cppu::getCaughtException() ),
1195                                 RTL_TEXTENCODING_UTF8 ).getStr() );
1196 
1197                 return false;
1198             }
1199         }
1200     }
1201 
1202     try
1203     {
1204         // load the normal page shapes
1205         // -------------------------------------------------------------------------
1206 
1207         ShapeImporter aShapesFunctor( mxDrawPage,
1208                                       mxDrawPage,
1209                                       mxDrawPagesSupplier,
1210                                       maContext,
1211                                       nCurrCount,
1212                                       false );
1213 
1214         while( !aShapesFunctor.isImportDone() )
1215         {
1216             ShapeSharedPtr const& rShape(
1217                 aShapesFunctor.importShape() );
1218             if( rShape )
1219                 mpLayerManager->addShape( rShape );
1220         }
1221         addPolygons(aShapesFunctor.getPolygons());
1222     }
1223     catch( uno::RuntimeException& )
1224     {
1225         throw;
1226     }
1227     catch( ShapeLoadFailedException& )
1228     {
1229         // TODO(E2): Error handling. For now, bail out
1230         OSL_ENSURE( false,
1231                     "SlideImpl::loadShapes(): caught ShapeLoadFailedException" );
1232         return false;
1233     }
1234     catch( uno::Exception& )
1235     {
1236         OSL_ENSURE( false,
1237                     rtl::OUStringToOString(
1238                         comphelper::anyToString( cppu::getCaughtException() ),
1239                         RTL_TEXTENCODING_UTF8 ).getStr() );
1240 
1241         return false;
1242     }
1243 
1244     mbShapesLoaded = true;
1245 
1246     return true;
1247 }
1248 
1249 basegfx::B2ISize SlideImpl::getSlideSizeImpl() const
1250 {
1251     uno::Reference< beans::XPropertySet > xPropSet(
1252         mxDrawPage, uno::UNO_QUERY_THROW );
1253 
1254     sal_Int32 nDocWidth = 0;
1255     sal_Int32 nDocHeight = 0;
1256     xPropSet->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Width") ) ) >>= nDocWidth;
1257     xPropSet->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Height") ) ) >>= nDocHeight;
1258 
1259     return basegfx::B2ISize( nDocWidth, nDocHeight );
1260 }
1261 
1262 } // namespace
1263 
1264 
1265 SlideSharedPtr createSlide( const uno::Reference< drawing::XDrawPage >&			xDrawPage,
1266                             const uno::Reference<drawing::XDrawPagesSupplier>&  xDrawPages,
1267                             const uno::Reference< animations::XAnimationNode >& xRootNode,
1268                             EventQueue&											rEventQueue,
1269                             EventMultiplexer&									rEventMultiplexer,
1270                             ScreenUpdater&                                      rScreenUpdater,
1271                             ActivitiesQueue&									rActivitiesQueue,
1272                             UserEventQueue&										rUserEventQueue,
1273                             CursorManager&                                      rCursorManager,
1274                             const UnoViewContainer&                             rViewContainer,
1275                             const uno::Reference< uno::XComponentContext >& 	xComponentContext,
1276                             const ShapeEventListenerMap&                        rShapeListenerMap,
1277                             const ShapeCursorMap&                               rShapeCursorMap,
1278                             const PolyPolygonVector&                            rPolyPolygonVector,
1279                             RGBColor const&                                     rUserPaintColor,
1280                             double                                              dUserPaintStrokeWidth,
1281                             bool                                                bUserPaintEnabled,
1282                             bool                                                bIntrinsicAnimationsAllowed,
1283                             bool                                                bDisableAnimationZOrder )
1284 {
1285     boost::shared_ptr<SlideImpl> pRet( new SlideImpl( xDrawPage, xDrawPages, xRootNode, rEventQueue,
1286                                                       rEventMultiplexer, rScreenUpdater,
1287                                                       rActivitiesQueue, rUserEventQueue,
1288                                                       rCursorManager, rViewContainer,
1289                                                       xComponentContext, rShapeListenerMap,
1290                                                       rShapeCursorMap, rPolyPolygonVector, rUserPaintColor,
1291                                                       dUserPaintStrokeWidth, bUserPaintEnabled,
1292                                                       bIntrinsicAnimationsAllowed,
1293                                                       bDisableAnimationZOrder ));
1294 
1295     rEventMultiplexer.addViewHandler( pRet );
1296 
1297     return pRet;
1298 }
1299 
1300 } // namespace internal
1301 } // namespace slideshow
1302