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