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 <canvas/debug.hxx> 32 #include <tools/diagnose_ex.h> 33 34 #include <basegfx/matrix/b2dhommatrix.hxx> 35 #include <basegfx/tools/canvastools.hxx> 36 #include <basegfx/polygon/b2dpolygontools.hxx> 37 #include <basegfx/polygon/b2dpolypolygontools.hxx> 38 39 #include <cppcanvas/basegfxfactory.hxx> 40 41 #include <comphelper/optional.hxx> 42 #include <comphelper/make_shared_from_uno.hxx> 43 44 #include <com/sun/star/rendering/XIntegerBitmap.hpp> 45 #include <com/sun/star/rendering/IntegerBitmapLayout.hpp> 46 #include <com/sun/star/animations/TransitionType.hpp> 47 #include <com/sun/star/animations/TransitionSubType.hpp> 48 #include <com/sun/star/lang/XMultiServiceFactory.hpp> 49 50 #include "slidechangebase.hxx" 51 #include "transitionfactory.hxx" 52 #include "transitiontools.hxx" 53 #include "parametricpolypolygonfactory.hxx" 54 #include "animationfactory.hxx" 55 #include "clippingfunctor.hxx" 56 #include "combtransition.hxx" 57 #include "tools.hxx" 58 59 #include <boost/bind.hpp> 60 61 62 /*************************************************** 63 *** *** 64 *** Slide Transition Effects *** 65 *** *** 66 ***************************************************/ 67 68 using namespace com::sun::star; 69 70 namespace slideshow { 71 namespace internal { 72 73 namespace { 74 75 // helper methods 76 // ============================================= 77 78 void fillPage( const ::cppcanvas::CanvasSharedPtr& rDestinationCanvas, 79 const ::basegfx::B2DSize& rPageSizePixel, 80 const RGBColor& rFillColor ) 81 { 82 // need to render without any transformation (we 83 // assume rPageSizePixel to represent device units) 84 const ::cppcanvas::CanvasSharedPtr pDevicePixelCanvas( 85 rDestinationCanvas->clone() ); 86 pDevicePixelCanvas->setTransformation( ::basegfx::B2DHomMatrix() ); 87 88 // TODO(F2): Properly respect clip here. 89 // Might have to be transformed, too. 90 const ::basegfx::B2DHomMatrix aViewTransform( 91 rDestinationCanvas->getTransformation() ); 92 const ::basegfx::B2DPoint aOutputPosPixel( 93 aViewTransform * ::basegfx::B2DPoint() ); 94 95 fillRect( pDevicePixelCanvas, 96 ::basegfx::B2DRectangle( 97 aOutputPosPixel.getX(), 98 aOutputPosPixel.getY(), 99 aOutputPosPixel.getX() + rPageSizePixel.getX(), 100 aOutputPosPixel.getY() + rPageSizePixel.getY() ), 101 rFillColor.getIntegerColor() ); 102 } 103 104 class PluginSlideChange: public SlideChangeBase 105 { 106 struct TransitionViewPair { 107 uno::Reference<presentation::XTransition> mxTransition; 108 UnoViewSharedPtr mpView; 109 110 TransitionViewPair( uno::Reference<presentation::XTransition> xTransition, const UnoViewSharedPtr pView ) 111 { 112 mxTransition = xTransition; 113 mpView = pView; 114 } 115 116 ~TransitionViewPair() 117 { 118 mxTransition.clear(); 119 mpView.reset();; 120 } 121 122 void update( double t ) 123 { 124 mxTransition->update( t ); 125 } 126 }; 127 128 public: 129 /** Create a new SlideChanger, for the given leaving and 130 entering slide bitmaps, which uses super secret OpenGL 131 stuff. 132 */ 133 PluginSlideChange( sal_Int16 nTransitionType, 134 sal_Int16 nTransitionSubType, 135 boost::optional<SlideSharedPtr> const& leavingSlide_, 136 const SlideSharedPtr& pEnteringSlide, 137 const UnoViewContainer& rViewContainer, 138 ScreenUpdater& rScreenUpdater, 139 const uno::Reference< 140 presentation::XTransitionFactory>& xFactory, 141 const SoundPlayerSharedPtr& pSoundPlayer, 142 EventMultiplexer& rEventMultiplexer) : 143 SlideChangeBase( leavingSlide_, 144 pEnteringSlide, 145 pSoundPlayer, 146 rViewContainer, 147 rScreenUpdater, 148 rEventMultiplexer ), 149 maTransitions(), 150 mbSuccess( false ), 151 mnTransitionType( nTransitionType ), 152 mnTransitionSubType( nTransitionSubType ), 153 mxFactory( xFactory ) 154 { 155 // create one transition per view 156 UnoViewVector::const_iterator aCurrView (rViewContainer.begin()); 157 const UnoViewVector::const_iterator aEnd(rViewContainer.end()); 158 while( aCurrView != aEnd ) 159 { 160 if(! addTransition( *aCurrView ) ) 161 return; 162 163 ENSURE_OR_THROW(maTransitions.back() && maTransitions.back()->mxTransition.is(), 164 "Failed to create plugin transition"); 165 ++aCurrView; 166 } 167 mbSuccess = true; 168 } 169 170 ~PluginSlideChange() 171 { 172 mxFactory.clear(); 173 174 ::std::vector< TransitionViewPair* >::const_iterator aCurrView (maTransitions.begin()); 175 ::std::vector< TransitionViewPair* >::const_iterator aEnd(maTransitions.end()); 176 while( aCurrView != aEnd ) 177 { 178 delete (*aCurrView); 179 ++aCurrView; 180 } 181 maTransitions.clear(); 182 } 183 184 bool addTransition( const UnoViewSharedPtr& rView ) 185 { 186 uno::Reference<presentation::XTransition> rTransition = mxFactory->createTransition( 187 mnTransitionType, 188 mnTransitionSubType, 189 rView->getUnoView(), 190 getLeavingBitmap(ViewEntry(rView))->getXBitmap(), 191 getEnteringBitmap(ViewEntry(rView))->getXBitmap() ); 192 193 if( rTransition.is() ) 194 maTransitions.push_back( new TransitionViewPair( rTransition, rView ) ); 195 else 196 return false; 197 198 return true; 199 } 200 201 virtual bool operator()( double t ) 202 { 203 std::for_each(maTransitions.begin(), 204 maTransitions.end(), 205 boost::bind( &TransitionViewPair::update, 206 _1, t) ); 207 return true; 208 } 209 210 bool Success() 211 { 212 return mbSuccess; 213 } 214 215 // ViewEventHandler 216 virtual void viewAdded( const UnoViewSharedPtr& rView ) 217 { 218 OSL_TRACE("PluginSlideChange viewAdded"); 219 SlideChangeBase::viewAdded( rView ); 220 221 ::std::vector< TransitionViewPair* >::const_iterator aCurrView (maTransitions.begin()); 222 ::std::vector< TransitionViewPair* >::const_iterator aEnd(maTransitions.end()); 223 bool bKnown = false; 224 while( aCurrView != aEnd ) 225 { 226 if( (*aCurrView)->mpView == rView ) { 227 bKnown = true; 228 break; 229 } 230 ++aCurrView; 231 } 232 233 if( !bKnown ) { 234 OSL_TRACE("need to be added"); 235 236 addTransition( rView ); 237 } 238 } 239 240 virtual void viewRemoved( const UnoViewSharedPtr& rView ) 241 { 242 OSL_TRACE("PluginSlideChange viewRemoved"); 243 SlideChangeBase::viewRemoved( rView ); 244 245 ::std::vector< TransitionViewPair* >::iterator aCurrView (maTransitions.begin()); 246 ::std::vector< TransitionViewPair* >::const_iterator aEnd(maTransitions.end()); 247 while( aCurrView != aEnd ) 248 { 249 if( (*aCurrView)->mpView == rView ) { 250 OSL_TRACE( "view removed" ); 251 delete (*aCurrView); 252 maTransitions.erase( aCurrView ); 253 break; 254 } 255 ++aCurrView; 256 } 257 } 258 259 virtual void viewChanged( const UnoViewSharedPtr& rView ) 260 { 261 OSL_TRACE("PluginSlideChange viewChanged"); 262 SlideChangeBase::viewChanged( rView ); 263 264 ::std::vector< TransitionViewPair* >::const_iterator aCurrView (maTransitions.begin()); 265 ::std::vector< TransitionViewPair* >::const_iterator aEnd(maTransitions.end()); 266 while( aCurrView != aEnd ) 267 { 268 if( (*aCurrView)->mpView == rView ) { 269 OSL_TRACE( "view changed" ); 270 (*aCurrView)->mxTransition->viewChanged( rView->getUnoView(), 271 getLeavingBitmap(ViewEntry(rView))->getXBitmap(), 272 getEnteringBitmap(ViewEntry(rView))->getXBitmap() ); 273 } else 274 OSL_TRACE( "view did not changed" ); 275 276 ++aCurrView; 277 } 278 } 279 280 virtual void viewsChanged() 281 { 282 OSL_TRACE("PluginSlideChange viewsChanged"); 283 SlideChangeBase::viewsChanged(); 284 285 ::std::vector< TransitionViewPair* >::const_iterator aCurrView (maTransitions.begin()); 286 ::std::vector< TransitionViewPair* >::const_iterator aEnd(maTransitions.end()); 287 while( aCurrView != aEnd ) 288 { 289 OSL_TRACE( "view changed" ); 290 (*aCurrView)->mxTransition->viewChanged( (*aCurrView)->mpView->getUnoView(), 291 getLeavingBitmap(ViewEntry((*aCurrView)->mpView))->getXBitmap(), 292 getEnteringBitmap(ViewEntry((*aCurrView)->mpView))->getXBitmap() ); 293 ++aCurrView; 294 } 295 } 296 297 private: 298 // One transition object per view 299 std::vector< TransitionViewPair* > maTransitions; 300 301 // bool 302 bool mbSuccess; 303 304 sal_Int16 mnTransitionType; 305 sal_Int16 mnTransitionSubType; 306 307 uno::Reference<presentation::XTransitionFactory> mxFactory; 308 }; 309 310 class ClippedSlideChange : public SlideChangeBase 311 { 312 public: 313 /** Create a new SlideChanger, for the given leaving and 314 entering slide bitmaps, which applies the given clip 315 polygon. 316 */ 317 ClippedSlideChange( 318 const SlideSharedPtr& pEnteringSlide, 319 const ParametricPolyPolygonSharedPtr& rPolygon, 320 const TransitionInfo& rTransitionInfo, 321 const UnoViewContainer& rViewContainer, 322 ScreenUpdater& rScreenUpdater, 323 EventMultiplexer& rEventMultiplexer, 324 bool bDirectionForward, 325 const SoundPlayerSharedPtr& pSoundPlayer ) : 326 SlideChangeBase( 327 // leaving bitmap is empty, we're leveraging the fact that the 328 // old slide is still displayed in the background: 329 boost::optional<SlideSharedPtr>(), 330 pEnteringSlide, 331 pSoundPlayer, 332 rViewContainer, 333 rScreenUpdater, 334 rEventMultiplexer ), 335 maClippingFunctor( rPolygon, 336 rTransitionInfo, 337 bDirectionForward, 338 true ) 339 {} 340 341 virtual void performIn( 342 const ::cppcanvas::CustomSpriteSharedPtr& rSprite, 343 const ViewEntry& rViewEntry, 344 const ::cppcanvas::CanvasSharedPtr& rDestinationCanvas, 345 double t ); 346 347 virtual void performOut( 348 const ::cppcanvas::CustomSpriteSharedPtr& rSprite, 349 const ViewEntry& rViewEntry, 350 const ::cppcanvas::CanvasSharedPtr& rDestinationCanvas, 351 double t ); 352 353 private: 354 ClippingFunctor maClippingFunctor; 355 }; 356 357 void ClippedSlideChange::performIn( 358 const ::cppcanvas::CustomSpriteSharedPtr& rSprite, 359 const ViewEntry& rViewEntry, 360 const ::cppcanvas::CanvasSharedPtr& /*rDestinationCanvas*/, 361 double t ) 362 { 363 // #i46602# Better work in device coordinate space here, 364 // otherwise, we too easily suffer from roundoffs. Apart from 365 // that, getEnteringSizePixel() _guarantees_ to cover the whole 366 // slide bitmap. There's a catch, though: this removes any effect 367 // of the view transformation (e.g. rotation) from the transition. 368 rSprite->setClipPixel( 369 maClippingFunctor( t, 370 getEnteringSlideSizePixel(rViewEntry.mpView) ) ); 371 } 372 373 void ClippedSlideChange::performOut( 374 const ::cppcanvas::CustomSpriteSharedPtr& /*rSprite*/, 375 const ViewEntry& /*rViewEntry*/, 376 const ::cppcanvas::CanvasSharedPtr& /*rDestinationCanvas*/, 377 double /*t*/ ) 378 { 379 // not needed here 380 } 381 382 383 class FadingSlideChange : public SlideChangeBase 384 { 385 public: 386 /** Create a new SlideChanger, for the given leaving and 387 entering slides, which applies a fade effect. 388 */ 389 FadingSlideChange( 390 boost::optional<SlideSharedPtr> const & leavingSlide, 391 const SlideSharedPtr& pEnteringSlide, 392 boost::optional<RGBColor> const& rFadeColor, 393 const SoundPlayerSharedPtr& pSoundPlayer, 394 const UnoViewContainer& rViewContainer, 395 ScreenUpdater& rScreenUpdater, 396 EventMultiplexer& rEventMultiplexer ) 397 : SlideChangeBase( leavingSlide, 398 pEnteringSlide, 399 pSoundPlayer, 400 rViewContainer, 401 rScreenUpdater, 402 rEventMultiplexer ), 403 maFadeColor( rFadeColor ), 404 mbFirstTurn( true ) 405 {} 406 407 virtual void performIn( 408 const ::cppcanvas::CustomSpriteSharedPtr& rSprite, 409 const ViewEntry& rViewEntry, 410 const ::cppcanvas::CanvasSharedPtr& rDestinationCanvas, 411 double t ); 412 413 virtual void performOut( 414 const ::cppcanvas::CustomSpriteSharedPtr& rSprite, 415 const ViewEntry& rViewEntry, 416 const ::cppcanvas::CanvasSharedPtr& rDestinationCanvas, 417 double t ); 418 419 private: 420 const boost::optional< RGBColor > maFadeColor; 421 bool mbFirstTurn; 422 }; 423 424 void FadingSlideChange::performIn( 425 const ::cppcanvas::CustomSpriteSharedPtr& rSprite, 426 const ViewEntry& /*rViewEntry*/, 427 const ::cppcanvas::CanvasSharedPtr& /*rDestinationCanvas*/, 428 double t ) 429 { 430 ENSURE_OR_THROW( 431 rSprite, 432 "FadingSlideChange::performIn(): Invalid sprite" ); 433 434 if( maFadeColor ) 435 // After half of the active time, fade in new slide 436 rSprite->setAlpha( t > 0.5 ? 2.0*(t-0.5) : 0.0 ); 437 else 438 // Fade in new slide over full active time 439 rSprite->setAlpha( t ); 440 } 441 442 void FadingSlideChange::performOut( 443 const ::cppcanvas::CustomSpriteSharedPtr& rSprite, 444 const ViewEntry& rViewEntry, 445 const ::cppcanvas::CanvasSharedPtr& rDestinationCanvas, 446 double t ) 447 { 448 ENSURE_OR_THROW( 449 rSprite, 450 "FadingSlideChange::performOut(): Invalid sprite" ); 451 ENSURE_OR_THROW( 452 rDestinationCanvas, 453 "FadingSlideChange::performOut(): Invalid dest canvas" ); 454 455 // only needed for color fades 456 if( maFadeColor ) 457 { 458 if( mbFirstTurn ) 459 { 460 mbFirstTurn = false; 461 462 // clear page to given fade color. 'Leaving' slide is 463 // painted atop of that, but slowly fading out. 464 fillPage( rDestinationCanvas, 465 getEnteringSlideSizePixel( rViewEntry.mpView ), 466 *maFadeColor ); 467 } 468 469 // Until half of the active time, fade out old 470 // slide. After half of the active time, old slide 471 // will be invisible. 472 rSprite->setAlpha( t > 0.5 ? 0.0 : 2.0*(0.5-t) ); 473 } 474 } 475 476 class MovingSlideChange : public SlideChangeBase 477 { 478 /// Direction vector for leaving slide, 479 const ::basegfx::B2DVector maLeavingDirection; 480 481 /// Direction vector for entering slide, 482 const ::basegfx::B2DVector maEnteringDirection; 483 484 bool mbFirstPerformCall; 485 486 public: 487 /** Create a new SlideChanger, for the given entering slide 488 bitmaps, which performes a moving slide change effect 489 490 @param rLeavingDirection 491 Direction vector. The move is performed along this 492 direction vector, starting at a position where the leaving 493 slide is fully visible, and ending at a position where the 494 leaving slide is just not visible. The vector must have 495 unit length. 496 497 @param rEnteringDirection 498 Direction vector. The move is performed along this 499 direction vector, starting at a position where the 500 entering slide is just not visible, and ending at the 501 final slide position. The vector must have unit length. 502 */ 503 MovingSlideChange( 504 const boost::optional<SlideSharedPtr>& leavingSlide, 505 const SlideSharedPtr& pEnteringSlide, 506 const SoundPlayerSharedPtr& pSoundPlayer, 507 const UnoViewContainer& rViewContainer, 508 ScreenUpdater& rScreenUpdater, 509 EventMultiplexer& rEventMultiplexer, 510 const ::basegfx::B2DVector& rLeavingDirection, 511 const ::basegfx::B2DVector& rEnteringDirection ) 512 : SlideChangeBase( 513 leavingSlide, pEnteringSlide, pSoundPlayer, 514 rViewContainer, rScreenUpdater, rEventMultiplexer, 515 // Optimization: when leaving bitmap is given, 516 // but it does not move, don't create sprites for it, 517 // we simply paint it once at startup: 518 !rLeavingDirection.equalZero() /* bCreateLeavingSprites */, 519 !rEnteringDirection.equalZero() /* bCreateEnteringSprites */ ), 520 // TODO(F1): calc correct length of direction 521 // vector. Directions not strictly horizontal or vertical 522 // must travel a longer distance. 523 maLeavingDirection( rLeavingDirection ), 524 // TODO(F1): calc correct length of direction 525 // vector. Directions not strictly horizontal or vertical 526 // must travel a longer distance. 527 maEnteringDirection( rEnteringDirection ), 528 mbFirstPerformCall( true ) 529 {} 530 531 virtual void performIn( 532 const ::cppcanvas::CustomSpriteSharedPtr& rSprite, 533 const ViewEntry& rViewEntry, 534 const ::cppcanvas::CanvasSharedPtr& rDestinationCanvas, 535 double t ); 536 537 virtual void performOut( 538 const ::cppcanvas::CustomSpriteSharedPtr& rSprite, 539 const ViewEntry& rViewEntry, 540 const ::cppcanvas::CanvasSharedPtr& rDestinationCanvas, 541 double t ); 542 }; 543 544 void MovingSlideChange::performIn( 545 const ::cppcanvas::CustomSpriteSharedPtr& rSprite, 546 const ViewEntry& rViewEntry, 547 const ::cppcanvas::CanvasSharedPtr& rDestinationCanvas, 548 double t ) 549 { 550 // intro sprite moves: 551 552 ENSURE_OR_THROW( 553 rSprite, 554 "MovingSlideChange::performIn(): Invalid sprite" ); 555 ENSURE_OR_THROW( 556 rDestinationCanvas, 557 "MovingSlideChange::performIn(): Invalid dest canvas" ); 558 559 if (mbFirstPerformCall && maLeavingDirection.equalZero()) 560 { 561 mbFirstPerformCall = false; 562 renderBitmap( getLeavingBitmap(rViewEntry), rDestinationCanvas ); 563 } 564 565 // TODO(F1): This does not account for non-translational 566 // transformations! If the canvas is rotated, we still 567 // move the sprite unrotated (which might or might not 568 // produce the intended effect). 569 const basegfx::B2DHomMatrix aViewTransform( 570 rDestinationCanvas->getTransformation() ); 571 const basegfx::B2DPoint aPageOrigin( 572 aViewTransform * basegfx::B2DPoint() ); 573 574 // move sprite 575 rSprite->movePixel( 576 aPageOrigin + 577 ((t - 1.0) * 578 ::basegfx::B2DSize( getEnteringSlideSizePixel(rViewEntry.mpView) ) * 579 maEnteringDirection) ); 580 } 581 582 void MovingSlideChange::performOut( 583 const ::cppcanvas::CustomSpriteSharedPtr& rSprite, 584 const ViewEntry& rViewEntry, 585 const ::cppcanvas::CanvasSharedPtr& rDestinationCanvas, 586 double t ) 587 { 588 // outro sprite moves: 589 590 ENSURE_OR_THROW( 591 rSprite, 592 "MovingSlideChange::performOut(): Invalid sprite" ); 593 ENSURE_OR_THROW( 594 rDestinationCanvas, 595 "MovingSlideChange::performOut(): Invalid dest canvas" ); 596 597 if (mbFirstPerformCall && maEnteringDirection.equalZero()) 598 { 599 mbFirstPerformCall = false; 600 renderBitmap( getEnteringBitmap(rViewEntry), rDestinationCanvas ); 601 } 602 603 // TODO(F1): This does not account for non-translational 604 // transformations! If the canvas is rotated, we still 605 // move the sprite unrotated (which might or might not 606 // produce the intended effect). 607 const basegfx::B2DHomMatrix aViewTransform( 608 rDestinationCanvas->getTransformation() ); 609 const basegfx::B2DPoint aPageOrigin( 610 aViewTransform * basegfx::B2DPoint() ); 611 612 // move sprite 613 rSprite->movePixel( 614 aPageOrigin + (t * 615 ::basegfx::B2DSize( getEnteringSlideSizePixel(rViewEntry.mpView) ) * 616 maLeavingDirection) ); 617 } 618 619 620 NumberAnimationSharedPtr createPushWipeTransition( 621 boost::optional<SlideSharedPtr> const & leavingSlide_, 622 const SlideSharedPtr& pEnteringSlide, 623 const UnoViewContainer& rViewContainer, 624 ScreenUpdater& rScreenUpdater, 625 EventMultiplexer& rEventMultiplexer, 626 sal_Int16 /*nTransitionType*/, 627 sal_Int16 nTransitionSubType, 628 bool /*bTransitionDirection*/, 629 const SoundPlayerSharedPtr& pSoundPlayer ) 630 { 631 boost::optional<SlideSharedPtr> leavingSlide; // no bitmap 632 if (leavingSlide_ && (*leavingSlide_).get() != 0) 633 { 634 // opt: only page, if we've an 635 // actual slide to move out here. We 636 // _don't_ need a fake black background 637 // bitmap, neither for push nor for comb 638 // wipes. 639 leavingSlide = leavingSlide_; 640 } 641 642 // setup direction vector 643 bool bComb( false ); 644 ::basegfx::B2DVector aDirection; 645 switch( nTransitionSubType ) 646 { 647 default: 648 OSL_ENSURE( 649 false, 650 "createPushWipeTransition(): Unexpected transition " 651 "subtype for animations::TransitionType::PUSHWIPE " 652 "transitions" ); 653 return NumberAnimationSharedPtr(); 654 655 case animations::TransitionSubType::FROMTOP: 656 aDirection = ::basegfx::B2DVector( 0.0, 1.0 ); 657 break; 658 659 case animations::TransitionSubType::FROMBOTTOM: 660 aDirection = ::basegfx::B2DVector( 0.0, -1.0 ); 661 break; 662 663 case animations::TransitionSubType::FROMLEFT: 664 aDirection = ::basegfx::B2DVector( 1.0, 0.0 ); 665 break; 666 667 case animations::TransitionSubType::FROMRIGHT: 668 aDirection = ::basegfx::B2DVector( -1.0, 0.0 ); 669 break; 670 671 case animations::TransitionSubType::FROMBOTTOMRIGHT: 672 aDirection = ::basegfx::B2DVector( -1.0, -1.0 ); 673 break; 674 675 case animations::TransitionSubType::FROMBOTTOMLEFT: 676 aDirection = ::basegfx::B2DVector( 1.0, -1.0 ); 677 break; 678 679 case animations::TransitionSubType::FROMTOPRIGHT: 680 aDirection = ::basegfx::B2DVector( -1.0, 1.0 ); 681 break; 682 683 case animations::TransitionSubType::FROMTOPLEFT: 684 aDirection = ::basegfx::B2DVector( 1.0, 1.0 ); 685 break; 686 687 case animations::TransitionSubType::COMBHORIZONTAL: 688 aDirection = ::basegfx::B2DVector( 1.0, 0.0 ); 689 bComb = true; 690 break; 691 692 case animations::TransitionSubType::COMBVERTICAL: 693 aDirection = ::basegfx::B2DVector( 0.0, 1.0 ); 694 bComb = true; 695 break; 696 } 697 698 if( bComb ) 699 { 700 return NumberAnimationSharedPtr( 701 new CombTransition( leavingSlide, 702 pEnteringSlide, 703 pSoundPlayer, 704 rViewContainer, 705 rScreenUpdater, 706 rEventMultiplexer, 707 aDirection, 708 24 /* comb with 12 stripes */ )); 709 } 710 else 711 { 712 return NumberAnimationSharedPtr( 713 new MovingSlideChange( leavingSlide, 714 pEnteringSlide, 715 pSoundPlayer, 716 rViewContainer, 717 rScreenUpdater, 718 rEventMultiplexer, 719 aDirection, 720 aDirection )); 721 } 722 } 723 724 NumberAnimationSharedPtr createSlideWipeTransition( 725 boost::optional<SlideSharedPtr> const & leavingSlide, 726 const SlideSharedPtr& pEnteringSlide, 727 const UnoViewContainer& rViewContainer, 728 ScreenUpdater& rScreenUpdater, 729 EventMultiplexer& rEventMultiplexer, 730 sal_Int16 /*nTransitionType*/, 731 sal_Int16 nTransitionSubType, 732 bool bTransitionDirection, 733 const SoundPlayerSharedPtr& pSoundPlayer ) 734 { 735 // setup 'in' direction vector 736 ::basegfx::B2DVector aInDirection; 737 switch( nTransitionSubType ) 738 { 739 default: 740 OSL_ENSURE( 741 false, 742 "createSlideWipeTransition(): Unexpected transition " 743 "subtype for animations::TransitionType::SLIDEWIPE " 744 "transitions" ); 745 return NumberAnimationSharedPtr(); 746 747 case animations::TransitionSubType::FROMTOP: 748 aInDirection = ::basegfx::B2DVector( 0.0, 1.0 ); 749 break; 750 751 case animations::TransitionSubType::FROMRIGHT: 752 aInDirection = ::basegfx::B2DVector( -1.0, 0.0 ); 753 break; 754 755 case animations::TransitionSubType::FROMLEFT: 756 aInDirection = ::basegfx::B2DVector( 1.0, 0.0 ); 757 break; 758 759 case animations::TransitionSubType::FROMBOTTOM: 760 aInDirection = ::basegfx::B2DVector( 0.0, -1.0 ); 761 break; 762 763 case animations::TransitionSubType::FROMBOTTOMRIGHT: 764 aInDirection = ::basegfx::B2DVector( -1.0, -1.0 ); 765 break; 766 767 case animations::TransitionSubType::FROMBOTTOMLEFT: 768 aInDirection = ::basegfx::B2DVector( 1.0, -1.0 ); 769 break; 770 771 case animations::TransitionSubType::FROMTOPRIGHT: 772 aInDirection = ::basegfx::B2DVector( -1.0, 1.0 ); 773 break; 774 775 case animations::TransitionSubType::FROMTOPLEFT: 776 aInDirection = ::basegfx::B2DVector( 1.0, 1.0 ); 777 break; 778 } 779 780 if( bTransitionDirection ) 781 { 782 // normal, 'forward' slide wipe effect. Since the old 783 // content is still on screen (and does not move), we omit 784 // the 'leaving' slide. 785 // ======================================================= 786 787 return NumberAnimationSharedPtr( 788 new MovingSlideChange( 789 boost::optional<SlideSharedPtr>() /* no slide */, 790 pEnteringSlide, 791 pSoundPlayer, 792 rViewContainer, 793 rScreenUpdater, 794 rEventMultiplexer, 795 basegfx::B2DVector(), 796 aInDirection )); 797 } 798 else 799 { 800 // 'reversed' slide wipe effect. Reverse for slide wipes 801 // means, that the new slide is in the back, statically, 802 // and the old one is moving off in the foreground. 803 // ======================================================= 804 805 return NumberAnimationSharedPtr( 806 new MovingSlideChange( leavingSlide, 807 pEnteringSlide, 808 pSoundPlayer, 809 rViewContainer, 810 rScreenUpdater, 811 rEventMultiplexer, 812 aInDirection, 813 basegfx::B2DVector() )); 814 } 815 } 816 817 NumberAnimationSharedPtr createPluginTransition( 818 sal_Int16 nTransitionType, 819 sal_Int16 nTransitionSubType, 820 boost::optional<SlideSharedPtr> const& pLeavingSlide, 821 const SlideSharedPtr& pEnteringSlide, 822 const UnoViewContainer& rViewContainer, 823 ScreenUpdater& rScreenUpdater, 824 const uno::Reference< 825 presentation::XTransitionFactory>& xFactory, 826 const SoundPlayerSharedPtr& pSoundPlayer, 827 EventMultiplexer& rEventMultiplexer) 828 { 829 PluginSlideChange* pTransition = 830 new PluginSlideChange( 831 nTransitionType, 832 nTransitionSubType, 833 pLeavingSlide, 834 pEnteringSlide, 835 rViewContainer, 836 rScreenUpdater, 837 xFactory, 838 pSoundPlayer, 839 rEventMultiplexer ); 840 841 if( pTransition->Success() ) 842 return NumberAnimationSharedPtr( pTransition ); 843 else { 844 delete pTransition; 845 return NumberAnimationSharedPtr(); 846 } 847 } 848 849 } // anon namespace 850 851 852 NumberAnimationSharedPtr TransitionFactory::createSlideTransition( 853 const SlideSharedPtr& pLeavingSlide, 854 const SlideSharedPtr& pEnteringSlide, 855 const UnoViewContainer& rViewContainer, 856 ScreenUpdater& rScreenUpdater, 857 EventMultiplexer& rEventMultiplexer, 858 const uno::Reference<presentation::XTransitionFactory>& xOptionalFactory, 859 sal_Int16 nTransitionType, 860 sal_Int16 nTransitionSubType, 861 bool bTransitionDirection, 862 const RGBColor& rTransitionFadeColor, 863 const SoundPlayerSharedPtr& pSoundPlayer ) 864 { 865 // xxx todo: change to TransitionType::NONE, TransitionSubType::NONE: 866 if (nTransitionType == 0 && nTransitionSubType == 0) { 867 // just play sound, no slide transition: 868 if (pSoundPlayer) { 869 pSoundPlayer->startPlayback(); 870 // xxx todo: for now, presentation.cxx takes care about the slide 871 // #i50492# transition sound object, so just release it here 872 } 873 return NumberAnimationSharedPtr(); 874 } 875 876 ENSURE_OR_THROW( 877 pEnteringSlide, 878 "TransitionFactory::createSlideTransition(): Invalid entering slide" ); 879 880 if( xOptionalFactory.is() && 881 xOptionalFactory->hasTransition(nTransitionType, nTransitionSubType) ) 882 { 883 // #i82460# - optional plugin factory claims this transition. delegate. 884 NumberAnimationSharedPtr pTransition( 885 createPluginTransition( 886 nTransitionType, 887 nTransitionSubType, 888 comphelper::make_optional(pLeavingSlide), 889 pEnteringSlide, 890 rViewContainer, 891 rScreenUpdater, 892 xOptionalFactory, 893 pSoundPlayer, 894 rEventMultiplexer )); 895 896 if( pTransition.get() ) 897 return pTransition; 898 } 899 900 const TransitionInfo* pTransitionInfo( 901 getTransitionInfo( nTransitionType, nTransitionSubType ) ); 902 903 if( pTransitionInfo != NULL ) 904 { 905 switch( pTransitionInfo->meTransitionClass ) 906 { 907 default: 908 case TransitionInfo::TRANSITION_INVALID: 909 OSL_TRACE( 910 "TransitionFactory::createSlideTransition(): " 911 "Invalid type/subtype (%d/%d) combination encountered.", 912 nTransitionType, 913 nTransitionSubType ); 914 return NumberAnimationSharedPtr(); 915 916 917 case TransitionInfo::TRANSITION_CLIP_POLYPOLYGON: 918 { 919 // generate parametric poly-polygon 920 ParametricPolyPolygonSharedPtr pPoly( 921 ParametricPolyPolygonFactory::createClipPolyPolygon( 922 nTransitionType, nTransitionSubType ) ); 923 924 // create a clip transition from that 925 return NumberAnimationSharedPtr( 926 new ClippedSlideChange( pEnteringSlide, 927 pPoly, 928 *pTransitionInfo, 929 rViewContainer, 930 rScreenUpdater, 931 rEventMultiplexer, 932 bTransitionDirection, 933 pSoundPlayer )); 934 } 935 936 case TransitionInfo::TRANSITION_SPECIAL: 937 { 938 switch( nTransitionType ) 939 { 940 default: 941 OSL_ENSURE( 942 false, 943 "TransitionFactory::createSlideTransition(): " 944 "Unexpected transition type for " 945 "TRANSITION_SPECIAL transitions" ); 946 return NumberAnimationSharedPtr(); 947 948 case animations::TransitionType::RANDOM: 949 { 950 // select randomly one of the effects from the 951 // TransitionFactoryTable 952 953 const TransitionInfo* pRandomTransitionInfo( 954 getRandomTransitionInfo() ); 955 956 ENSURE_OR_THROW( 957 pRandomTransitionInfo != NULL, 958 "TransitionFactory::createSlideTransition(): " 959 "Got invalid random transition info" ); 960 961 ENSURE_OR_THROW( 962 pRandomTransitionInfo->mnTransitionType != 963 animations::TransitionType::RANDOM, 964 "TransitionFactory::createSlideTransition(): " 965 "Got random again for random input!" ); 966 967 // and recurse 968 return createSlideTransition( 969 pLeavingSlide, 970 pEnteringSlide, 971 rViewContainer, 972 rScreenUpdater, 973 rEventMultiplexer, 974 xOptionalFactory, 975 pRandomTransitionInfo->mnTransitionType, 976 pRandomTransitionInfo->mnTransitionSubType, 977 bTransitionDirection, 978 rTransitionFadeColor, 979 pSoundPlayer ); 980 } 981 982 case animations::TransitionType::PUSHWIPE: 983 { 984 return createPushWipeTransition( 985 comphelper::make_optional(pLeavingSlide), 986 pEnteringSlide, 987 rViewContainer, 988 rScreenUpdater, 989 rEventMultiplexer, 990 nTransitionType, 991 nTransitionSubType, 992 bTransitionDirection, 993 pSoundPlayer ); 994 } 995 996 case animations::TransitionType::SLIDEWIPE: 997 { 998 return createSlideWipeTransition( 999 comphelper::make_optional(pLeavingSlide), 1000 pEnteringSlide, 1001 rViewContainer, 1002 rScreenUpdater, 1003 rEventMultiplexer, 1004 nTransitionType, 1005 nTransitionSubType, 1006 bTransitionDirection, 1007 pSoundPlayer ); 1008 } 1009 1010 case animations::TransitionType::FADE: 1011 { 1012 // black page: 1013 boost::optional<SlideSharedPtr> leavingSlide; 1014 1015 switch( nTransitionSubType ) 1016 { 1017 case animations::TransitionSubType::CROSSFADE: 1018 // crossfade needs no further setup, 1019 // just blend new slide over existing 1020 // background. 1021 break; 1022 1023 // TODO(F1): Implement toColor/fromColor fades 1024 case animations::TransitionSubType::FADETOCOLOR: 1025 // FALLTHROUGH intended 1026 case animations::TransitionSubType::FADEFROMCOLOR: 1027 // FALLTHROUGH intended 1028 case animations::TransitionSubType::FADEOVERCOLOR: 1029 if (pLeavingSlide) { 1030 // only generate, if fade 1031 // effect really needs it. 1032 leavingSlide.reset( pLeavingSlide ); 1033 } 1034 break; 1035 1036 default: 1037 ENSURE_OR_THROW( false, 1038 "SlideTransitionFactory::createSlideTransition(): Unknown FADE subtype" ); 1039 } 1040 1041 return NumberAnimationSharedPtr( 1042 new FadingSlideChange( 1043 leavingSlide, 1044 pEnteringSlide, 1045 comphelper::make_optional( 1046 rTransitionFadeColor), 1047 pSoundPlayer, 1048 rViewContainer, 1049 rScreenUpdater, 1050 rEventMultiplexer )); 1051 } 1052 } 1053 } 1054 break; 1055 } 1056 } 1057 1058 // No animation generated, maybe no table entry for given 1059 // transition? 1060 OSL_TRACE( 1061 "TransitionFactory::createSlideTransition(): " 1062 "Unknown type/subtype (%d/%d) combination encountered", 1063 nTransitionType, 1064 nTransitionSubType ); 1065 OSL_ENSURE( 1066 false, 1067 "TransitionFactory::createSlideTransition(): " 1068 "Unknown type/subtype combination encountered" ); 1069 1070 return NumberAnimationSharedPtr(); 1071 } 1072 1073 } // namespace internal 1074 } // namespace presentation 1075