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