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