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