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