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 // must be first 32 #include <canvas/debug.hxx> 33 #include <tools/diagnose_ex.h> 34 #include <canvas/verbosetrace.hxx> 35 36 #include <com/sun/star/animations/AnimationCalcMode.hpp> 37 #include <comphelper/sequence.hxx> 38 39 #include "activitiesfactory.hxx" 40 #include "smilfunctionparser.hxx" 41 #include "accumulation.hxx" 42 #include "activityparameters.hxx" 43 #include "interpolation.hxx" 44 #include "tools.hxx" 45 #include "simplecontinuousactivitybase.hxx" 46 #include "discreteactivitybase.hxx" 47 #include "continuousactivitybase.hxx" 48 #include "continuouskeytimeactivitybase.hxx" 49 50 #include <boost/bind.hpp> 51 #include <boost/optional.hpp> 52 53 #include <cmath> // for modf 54 #include <vector> 55 #include <algorithm> 56 57 using namespace com::sun::star; 58 59 namespace slideshow { 60 namespace internal { 61 62 namespace { 63 64 /** Traits template, to take formula application only for ValueType = double 65 */ 66 template<typename ValueType> struct FormulaTraits 67 { 68 static ValueType getPresentationValue( 69 const ValueType& rVal, const ExpressionNodeSharedPtr& ) 70 { 71 return rVal; 72 } 73 }; 74 75 /// Specialization for ValueType = double 76 template<> struct FormulaTraits<double> 77 { 78 static double getPresentationValue( 79 double const& rVal, ExpressionNodeSharedPtr const& rFormula ) 80 { 81 return rFormula ? (*rFormula)(rVal) : rVal; 82 } 83 }; 84 85 // Various ActivityBase specializations for different animator types 86 // ================================================================= 87 88 /** FromToBy handler 89 90 Provides the Activity specializations for FromToBy 91 animations (e.g. those without a values list). 92 93 This template makes heavy use of SFINAE, only one of 94 the perform*() methods will compile for each of the 95 base classes. 96 97 Note that we omit the virtual keyword on the perform() 98 overrides on purpose; those that actually do override 99 baseclass virtual methods inherit the property, and 100 the others won't increase our vtable. What's more, 101 having all perform() method in the vtable actually 102 creates POIs for them, which breaks the whole SFINAE 103 concept (IOW, this template won't compile any longer). 104 105 @tpl BaseType 106 Base class to use for this activity. Only 107 ContinuousActivityBase and DiscreteActivityBase are 108 supported here. 109 110 @tpl AnimationType 111 Type of the Animation to call. 112 */ 113 template<class BaseType, typename AnimationType> 114 class FromToByActivity : public BaseType 115 { 116 public: 117 typedef typename AnimationType::ValueType ValueType; 118 typedef boost::optional<ValueType> OptionalValueType; 119 120 private: 121 // some compilers don't inline whose definition they haven't 122 // seen before the call site... 123 ValueType getPresentationValue( const ValueType& rVal ) const 124 { 125 return FormulaTraits<ValueType>::getPresentationValue( rVal, mpFormula); 126 } 127 128 public: 129 /** Create FromToByActivity. 130 131 @param rFrom 132 From this value, the animation starts 133 134 @param rTo 135 With this value, the animation ends 136 137 @param rBy 138 With this value, the animation increments the start value 139 140 @param rParms 141 Standard Activity parameter struct 142 143 @param rAnim 144 Shared ptr to AnimationType 145 146 @param rInterpolator 147 Interpolator object to be used for lerping between 148 start and end value (need to be passed, since it 149 might contain state, e.g. interpolation direction 150 for HSL color space). 151 152 @param bCumulative 153 Whether repeated animations should cumulate the 154 value, or start fresh each time. 155 */ 156 FromToByActivity( 157 const OptionalValueType& rFrom, 158 const OptionalValueType& rTo, 159 const OptionalValueType& rBy, 160 const ActivityParameters& rParms, 161 const ::boost::shared_ptr< AnimationType >& rAnim, 162 const Interpolator< ValueType >& rInterpolator, 163 bool bCumulative ) 164 : BaseType( rParms ), 165 maFrom( rFrom ), 166 maTo( rTo ), 167 maBy( rBy ), 168 mpFormula( rParms.mpFormula ), 169 maStartValue(), 170 maEndValue(), 171 mpAnim( rAnim ), 172 maInterpolator( rInterpolator ), 173 mbDynamicStartValue( false ), 174 mbCumulative( bCumulative ) 175 { 176 ENSURE_OR_THROW( mpAnim, "Invalid animation object" ); 177 178 ENSURE_OR_THROW( 179 rTo || rBy, 180 "From and one of To or By, or To or By alone must be valid" ); 181 } 182 183 virtual void startAnimation() 184 { 185 if (this->isDisposed() || !mpAnim) 186 return; 187 BaseType::startAnimation(); 188 189 // start animation 190 mpAnim->start( BaseType::getShape(), 191 BaseType::getShapeAttributeLayer() ); 192 193 // setup start and end value. Determine animation 194 // start value only when animation actually 195 // started up (this order is part of the Animation 196 // interface contract) 197 const ValueType aAnimationStartValue( mpAnim->getUnderlyingValue() ); 198 199 // first of all, determine general type of 200 // animation, by inspecting which of the FromToBy values 201 // are actually valid. 202 // See http://www.w3.org/TR/smil20/animation.html#AnimationNS-FromToBy 203 // for a definition 204 if( maFrom ) 205 { 206 // From-to or From-by animation. According to 207 // SMIL spec, the To value takes precedence 208 // over the By value, if both are specified 209 if( maTo ) 210 { 211 // From-To animation 212 maStartValue = *maFrom; 213 maEndValue = *maTo; 214 } 215 else if( maBy ) 216 { 217 // From-By animation 218 maStartValue = *maFrom; 219 maEndValue = maStartValue + *maBy; 220 } 221 } 222 else 223 { 224 // By or To animation. According to SMIL spec, 225 // the To value takes precedence over the By 226 // value, if both are specified 227 if( maTo ) 228 { 229 // To animation 230 231 // According to the SMIL spec 232 // (http://www.w3.org/TR/smil20/animation.html#animationNS-ToAnimation), 233 // the to animation interpolates between 234 // the _running_ underlying value and the to value (as the end value) 235 mbDynamicStartValue = true; 236 maEndValue = *maTo; 237 } 238 else if( maBy ) 239 { 240 // By animation 241 maStartValue = aAnimationStartValue; 242 maEndValue = maStartValue + *maBy; 243 } 244 } 245 } 246 247 virtual void endAnimation() 248 { 249 // end animation 250 if (mpAnim) 251 mpAnim->end(); 252 } 253 254 /// perform override for ContinuousActivityBase 255 void perform( double nModifiedTime, sal_uInt32 nRepeatCount ) const 256 { 257 if (this->isDisposed() || !mpAnim) 258 return; 259 (*mpAnim)( 260 getPresentationValue( 261 accumulate( maEndValue, 262 mbCumulative * nRepeatCount, // means: mbCumulative ? nRepeatCount : 0, 263 maInterpolator( (mbDynamicStartValue 264 ? mpAnim->getUnderlyingValue() 265 : maStartValue), 266 maEndValue, 267 nModifiedTime ) ) ) ); 268 } 269 270 using BaseType::perform; 271 272 /// perform override for DiscreteActivityBase base 273 void perform( sal_uInt32 nFrame, sal_uInt32 nRepeatCount ) const 274 { 275 if (this->isDisposed() || !mpAnim) 276 return; 277 (*mpAnim)( 278 getPresentationValue( 279 accumulate( maEndValue, mbCumulative ? nRepeatCount : 0, 280 lerp( maInterpolator, 281 (mbDynamicStartValue 282 ? mpAnim->getUnderlyingValue() 283 : maStartValue), 284 maEndValue, 285 nFrame, 286 BaseType::getNumberOfKeyTimes() ) ) ) ); 287 } 288 289 using BaseType::isAutoReverse; 290 291 virtual void performEnd() 292 { 293 // xxx todo: good guess 294 if (mpAnim) 295 { 296 if (isAutoReverse()) 297 (*mpAnim)( getPresentationValue( maStartValue ) ); 298 else 299 (*mpAnim)( getPresentationValue( maEndValue ) ); 300 } 301 } 302 303 /// Disposable: 304 virtual void dispose() 305 { 306 mpAnim.reset(); 307 BaseType::dispose(); 308 } 309 310 private: 311 const OptionalValueType maFrom; 312 const OptionalValueType maTo; 313 const OptionalValueType maBy; 314 315 ExpressionNodeSharedPtr mpFormula; 316 317 ValueType maStartValue; 318 ValueType maEndValue; 319 320 ::boost::shared_ptr< AnimationType > mpAnim; 321 Interpolator< ValueType > maInterpolator; 322 bool mbDynamicStartValue; 323 bool mbCumulative; 324 }; 325 326 327 /** Generate Activity corresponding to given FromToBy values 328 329 @tpl BaseType 330 BaseType to use for deriving the Activity from 331 332 @tpl AnimationType 333 Subtype of the Animation object (e.g. NumberAnimation) 334 */ 335 template<class BaseType, typename AnimationType> 336 AnimationActivitySharedPtr createFromToByActivity( 337 const uno::Any& rFromAny, 338 const uno::Any& rToAny, 339 const uno::Any& rByAny, 340 const ActivityParameters& rParms, 341 const ::boost::shared_ptr< AnimationType >& rAnim, 342 const Interpolator< typename AnimationType::ValueType >& rInterpolator, 343 bool bCumulative, 344 const ShapeSharedPtr& rShape, 345 const ::basegfx::B2DVector& rSlideBounds ) 346 { 347 typedef typename AnimationType::ValueType ValueType; 348 typedef boost::optional<ValueType> OptionalValueType; 349 350 OptionalValueType aFrom; 351 OptionalValueType aTo; 352 OptionalValueType aBy; 353 354 ValueType aTmpValue; 355 356 if( rFromAny.hasValue() ) 357 { 358 ENSURE_OR_THROW( 359 extractValue( aTmpValue, rFromAny, rShape, rSlideBounds ), 360 "createFromToByActivity(): Could not extract from value" ); 361 aFrom.reset(aTmpValue); 362 } 363 if( rToAny.hasValue() ) 364 { 365 ENSURE_OR_THROW( 366 extractValue( aTmpValue, rToAny, rShape, rSlideBounds ), 367 "createFromToByActivity(): Could not extract to value" ); 368 aTo.reset(aTmpValue); 369 } 370 if( rByAny.hasValue() ) 371 { 372 ENSURE_OR_THROW( 373 extractValue( aTmpValue, rByAny, rShape, rSlideBounds ), 374 "createFromToByActivity(): Could not extract by value" ); 375 aBy.reset(aTmpValue); 376 } 377 378 return AnimationActivitySharedPtr( 379 new FromToByActivity<BaseType, AnimationType>( 380 aFrom, 381 aTo, 382 aBy, 383 rParms, 384 rAnim, 385 rInterpolator, 386 bCumulative ) ); 387 } 388 389 /* The following table shows which animator combines with 390 which Activity type: 391 392 NumberAnimator: all 393 PairAnimation: all 394 ColorAnimation: all 395 StringAnimation: DiscreteActivityBase 396 BoolAnimation: DiscreteActivityBase 397 */ 398 399 /** Values handler 400 401 Provides the Activity specializations for value lists 402 animations. 403 404 This template makes heavy use of SFINAE, only one of 405 the perform*() methods will compile for each of the 406 base classes. 407 408 Note that we omit the virtual keyword on the perform() 409 overrides on purpose; those that actually do override 410 baseclass virtual methods inherit the property, and 411 the others won't increase our vtable. What's more, 412 having all perform() method in the vtable actually 413 creates POIs for them, which breaks the whole SFINAE 414 concept (IOW, this template won't compile any longer). 415 416 @tpl BaseType 417 Base class to use for this activity. Only 418 ContinuousKeyTimeActivityBase and DiscreteActivityBase 419 are supported here. For values animation without key 420 times, the client must emulate key times by providing 421 a vector of equally spaced values between 0 and 1, 422 with the same number of entries as the values vector. 423 424 @tpl AnimationType 425 Type of the Animation to call. 426 */ 427 template<class BaseType, typename AnimationType> 428 class ValuesActivity : public BaseType 429 { 430 public: 431 typedef typename AnimationType::ValueType ValueType; 432 typedef std::vector<ValueType> ValueVectorType; 433 434 private: 435 // some compilers don't inline methods whose definition they haven't 436 // seen before the call site... 437 ValueType getPresentationValue( const ValueType& rVal ) const 438 { 439 return FormulaTraits<ValueType>::getPresentationValue( 440 rVal, mpFormula ); 441 } 442 443 public: 444 /** Create ValuesActivity. 445 446 @param rValues 447 Value vector to cycle animation through 448 449 @param rParms 450 Standard Activity parameter struct 451 452 @param rAnim 453 Shared ptr to AnimationType 454 455 @param rInterpolator 456 Interpolator object to be used for lerping between 457 start and end value (need to be passed, since it 458 might contain state, e.g. interpolation direction 459 for HSL color space). 460 461 @param bCumulative 462 Whether repeated animations should cumulate the 463 value, or start afresh each time. 464 */ 465 ValuesActivity( 466 const ValueVectorType& rValues, 467 const ActivityParameters& rParms, 468 const boost::shared_ptr<AnimationType>& rAnim, 469 const Interpolator< ValueType >& rInterpolator, 470 bool bCumulative ) 471 : BaseType( rParms ), 472 maValues( rValues ), 473 mpFormula( rParms.mpFormula ), 474 mpAnim( rAnim ), 475 maInterpolator( rInterpolator ), 476 mbCumulative( bCumulative ) 477 { 478 ENSURE_OR_THROW( mpAnim, "Invalid animation object" ); 479 ENSURE_OR_THROW( !rValues.empty(), "Empty value vector" ); 480 } 481 482 virtual void startAnimation() 483 { 484 if (this->isDisposed() || !mpAnim) 485 return; 486 BaseType::startAnimation(); 487 488 // start animation 489 mpAnim->start( BaseType::getShape(), 490 BaseType::getShapeAttributeLayer() ); 491 } 492 493 virtual void endAnimation() 494 { 495 // end animation 496 if (mpAnim) 497 mpAnim->end(); 498 } 499 500 /// perform override for ContinuousKeyTimeActivityBase base 501 void perform( sal_uInt32 nIndex, 502 double nFractionalIndex, 503 sal_uInt32 nRepeatCount ) const 504 { 505 if (this->isDisposed() || !mpAnim) 506 return; 507 ENSURE_OR_THROW( nIndex+1 < maValues.size(), 508 "ValuesActivity::perform(): index out of range" ); 509 510 // interpolate between nIndex and nIndex+1 values 511 (*mpAnim)( 512 getPresentationValue( 513 accumulate( maValues.back(), 514 mbCumulative ? nRepeatCount : 0, 515 maInterpolator( maValues[ nIndex ], 516 maValues[ nIndex+1 ], 517 nFractionalIndex ) ) ) ); 518 } 519 520 using BaseType::perform; 521 522 /// perform override for DiscreteActivityBase base 523 void perform( sal_uInt32 nFrame, sal_uInt32 nRepeatCount ) const 524 { 525 if (this->isDisposed() || !mpAnim) 526 return; 527 ENSURE_OR_THROW( nFrame < maValues.size(), 528 "ValuesActivity::perform(): index out of range" ); 529 530 // this is discrete, thus no lerp here. 531 (*mpAnim)( 532 getPresentationValue( 533 accumulate( maValues.back(), 534 mbCumulative ? nRepeatCount : 0, 535 maValues[ nFrame ] ) ) ); 536 } 537 538 virtual void performEnd() 539 { 540 // xxx todo: good guess 541 if (mpAnim) 542 (*mpAnim)( getPresentationValue( maValues.back() ) ); 543 } 544 545 /// Disposable: 546 virtual void dispose() 547 { 548 mpAnim.reset(); 549 BaseType::dispose(); 550 } 551 552 private: 553 ValueVectorType maValues; 554 555 ExpressionNodeSharedPtr mpFormula; 556 557 boost::shared_ptr<AnimationType> mpAnim; 558 Interpolator< ValueType > maInterpolator; 559 bool mbCumulative; 560 }; 561 562 /** Generate Activity corresponding to given Value vector 563 564 @tpl BaseType 565 BaseType to use for deriving the Activity from 566 567 @tpl AnimationType 568 Subtype of the Animation object (e.g. NumberAnimation) 569 */ 570 template<class BaseType, typename AnimationType> 571 AnimationActivitySharedPtr createValueListActivity( 572 const uno::Sequence<uno::Any>& rValues, 573 const ActivityParameters& rParms, 574 const boost::shared_ptr<AnimationType>& rAnim, 575 const Interpolator<typename AnimationType::ValueType>& rInterpolator, 576 bool bCumulative, 577 const ShapeSharedPtr& rShape, 578 const ::basegfx::B2DVector& rSlideBounds ) 579 { 580 typedef typename AnimationType::ValueType ValueType; 581 typedef std::vector<ValueType> ValueVectorType; 582 583 ValueVectorType aValueVector; 584 aValueVector.reserve( rValues.getLength() ); 585 586 for( ::std::size_t i=0, nLen=rValues.getLength(); i<nLen; ++i ) 587 { 588 ValueType aValue; 589 ENSURE_OR_THROW( 590 extractValue( aValue, rValues[i], rShape, rSlideBounds ), 591 "createValueListActivity(): Could not extract values" ); 592 aValueVector.push_back( aValue ); 593 } 594 595 return AnimationActivitySharedPtr( 596 new ValuesActivity<BaseType, AnimationType>( 597 aValueVector, 598 rParms, 599 rAnim, 600 rInterpolator, 601 bCumulative ) ); 602 } 603 604 /** Generate Activity for given XAnimate, corresponding to given Value vector 605 606 @tpl AnimationType 607 Subtype of the Animation object (e.g. NumberAnimation) 608 609 @param rParms 610 Common activity parameters 611 612 @param xNode 613 XAnimate node, to retrieve animation values from 614 615 @param rAnim 616 Actual animation to operate with (gets called with the 617 time-dependent values) 618 619 @param rInterpolator 620 Interpolator object to be used for lerping between 621 start and end values (need to be passed, since it 622 might contain state, e.g. interpolation direction 623 for HSL color space). 624 */ 625 template<typename AnimationType> 626 AnimationActivitySharedPtr createActivity( 627 const ActivitiesFactory::CommonParameters& rParms, 628 const uno::Reference< animations::XAnimate >& xNode, 629 const ::boost::shared_ptr< AnimationType >& rAnim, 630 const Interpolator< typename AnimationType::ValueType >& rInterpolator 631 = Interpolator< typename AnimationType::ValueType >() ) 632 { 633 // setup common parameters 634 // ======================= 635 636 ActivityParameters aActivityParms( rParms.mpEndEvent, 637 rParms.mrEventQueue, 638 rParms.mrActivitiesQueue, 639 rParms.mnMinDuration, 640 rParms.maRepeats, 641 rParms.mnAcceleration, 642 rParms.mnDeceleration, 643 rParms.mnMinNumberOfFrames, 644 rParms.mbAutoReverse ); 645 646 // is a formula given? 647 const ::rtl::OUString& rFormulaString( xNode->getFormula() ); 648 if( rFormulaString.getLength() ) 649 { 650 // yep, parse and pass to ActivityParameters 651 try 652 { 653 aActivityParms.mpFormula = 654 SmilFunctionParser::parseSmilFunction( 655 rFormulaString, 656 calcRelativeShapeBounds( 657 rParms.maSlideBounds, 658 rParms.mpShape->getBounds() ) ); 659 } 660 catch( ParseError& ) 661 { 662 // parse error, thus no formula 663 OSL_ENSURE( false, 664 "createActivity(): Error parsing formula string" ); 665 } 666 } 667 668 // are key times given? 669 const uno::Sequence< double >& aKeyTimes( xNode->getKeyTimes() ); 670 if( aKeyTimes.hasElements() ) 671 { 672 // yes, convert them from Sequence< double > 673 aActivityParms.maDiscreteTimes.resize( aKeyTimes.getLength() ); 674 comphelper::sequenceToArray( 675 &aActivityParms.maDiscreteTimes[0], 676 aKeyTimes ); // saves us some temporary vectors 677 } 678 679 // values sequence given? 680 const sal_Int32 nValueLen( xNode->getValues().getLength() ); 681 if( nValueLen ) 682 { 683 // Value list activity 684 // =================== 685 686 // fake keytimes, if necessary 687 if( !aKeyTimes.hasElements() ) 688 { 689 // create a dummy vector of key times, 690 // with aValues.getLength equally spaced entries. 691 for( sal_Int32 i=0; i<nValueLen; ++i ) 692 aActivityParms.maDiscreteTimes.push_back( double(i)/nValueLen ); 693 } 694 695 // determine type of animation needed here: 696 // Value list activities are possible with 697 // ContinuousKeyTimeActivityBase and DiscreteActivityBase 698 // specializations 699 const sal_Int16 nCalcMode( xNode->getCalcMode() ); 700 701 switch( nCalcMode ) 702 { 703 case animations::AnimationCalcMode::DISCRETE: 704 { 705 // since DiscreteActivityBase suspends itself 706 // between the frames, create a WakeupEvent for it. 707 aActivityParms.mpWakeupEvent.reset( 708 new WakeupEvent( 709 rParms.mrEventQueue.getTimer(), 710 rParms.mrActivitiesQueue ) ); 711 712 AnimationActivitySharedPtr pActivity( 713 createValueListActivity< DiscreteActivityBase >( 714 xNode->getValues(), 715 aActivityParms, 716 rAnim, 717 rInterpolator, 718 xNode->getAccumulate(), 719 rParms.mpShape, 720 rParms.maSlideBounds ) ); 721 722 // WakeupEvent and DiscreteActivityBase need circular 723 // references to the corresponding other object. 724 aActivityParms.mpWakeupEvent->setActivity( pActivity ); 725 726 return pActivity; 727 } 728 729 default: 730 OSL_ENSURE( false, "createActivity(): unexpected case" ); 731 // FALLTHROUGH intended 732 case animations::AnimationCalcMode::PACED: 733 // FALLTHROUGH intended 734 case animations::AnimationCalcMode::SPLINE: 735 // FALLTHROUGH intended 736 case animations::AnimationCalcMode::LINEAR: 737 return createValueListActivity< ContinuousKeyTimeActivityBase >( 738 xNode->getValues(), 739 aActivityParms, 740 rAnim, 741 rInterpolator, 742 xNode->getAccumulate(), 743 rParms.mpShape, 744 rParms.maSlideBounds ); 745 } 746 } 747 else 748 { 749 // FromToBy activity 750 // ================= 751 752 // determine type of animation needed here: 753 // FromToBy activities are possible with 754 // ContinuousActivityBase and DiscreteActivityBase 755 // specializations 756 const sal_Int16 nCalcMode( xNode->getCalcMode() ); 757 758 switch( nCalcMode ) 759 { 760 case animations::AnimationCalcMode::DISCRETE: 761 { 762 // fake keytimes, if necessary 763 if( !aKeyTimes.hasElements() ) 764 { 765 // create a dummy vector of 2 key times 766 const ::std::size_t nLen( 2 ); 767 for( ::std::size_t i=0; i<nLen; ++i ) 768 aActivityParms.maDiscreteTimes.push_back( double(i)/nLen ); 769 } 770 771 // since DiscreteActivityBase suspends itself 772 // between the frames, create a WakeupEvent for it. 773 aActivityParms.mpWakeupEvent.reset( 774 new WakeupEvent( 775 rParms.mrEventQueue.getTimer(), 776 rParms.mrActivitiesQueue ) ); 777 778 AnimationActivitySharedPtr pActivity( 779 createFromToByActivity< DiscreteActivityBase >( 780 xNode->getFrom(), 781 xNode->getTo(), 782 xNode->getBy(), 783 aActivityParms, 784 rAnim, 785 rInterpolator, 786 xNode->getAccumulate(), 787 rParms.mpShape, 788 rParms.maSlideBounds ) ); 789 790 // WakeupEvent and DiscreteActivityBase need circular 791 // references to the corresponding other object. 792 aActivityParms.mpWakeupEvent->setActivity( pActivity ); 793 794 return pActivity; 795 } 796 797 default: 798 OSL_ENSURE( false, "createActivity(): unexpected case" ); 799 // FALLTHROUGH intended 800 case animations::AnimationCalcMode::PACED: 801 // FALLTHROUGH intended 802 case animations::AnimationCalcMode::SPLINE: 803 // FALLTHROUGH intended 804 case animations::AnimationCalcMode::LINEAR: 805 return createFromToByActivity< ContinuousActivityBase >( 806 xNode->getFrom(), 807 xNode->getTo(), 808 xNode->getBy(), 809 aActivityParms, 810 rAnim, 811 rInterpolator, 812 xNode->getAccumulate(), 813 rParms.mpShape, 814 rParms.maSlideBounds ); 815 } 816 } 817 } 818 819 /** Simple activity for ActivitiesFactory::createSimpleActivity 820 821 @tpl Direction 822 Determines direction of value generator. A 1 yields a 823 forward direction, starting with 0.0 and ending with 824 1.0. A 0 yields a backward direction, starting with 825 1.0 and ending with 0.0 826 */ 827 template<int Direction> 828 class SimpleActivity : public ContinuousActivityBase 829 { 830 public: 831 /** Create SimpleActivity. 832 833 @param rParms 834 Standard Activity parameter struct 835 */ 836 SimpleActivity( const ActivityParameters& rParms, 837 const NumberAnimationSharedPtr& rAnim ) : 838 ContinuousActivityBase( rParms ), 839 mpAnim( rAnim ) 840 { 841 ENSURE_OR_THROW( mpAnim, "Invalid animation object" ); 842 } 843 844 virtual void startAnimation() 845 { 846 if (this->isDisposed() || !mpAnim) 847 return; 848 ContinuousActivityBase::startAnimation(); 849 850 // start animation 851 mpAnim->start( getShape(), 852 getShapeAttributeLayer() ); 853 } 854 855 virtual void endAnimation() 856 { 857 // end animation 858 if (mpAnim) 859 mpAnim->end(); 860 } 861 862 using SimpleContinuousActivityBase::perform; 863 864 /// perform override for ContinuousActivityBase 865 virtual void perform( double nModifiedTime, sal_uInt32 ) const 866 { 867 if (this->isDisposed() || !mpAnim) 868 return; 869 // no cumulation, simple [0,1] range 870 (*mpAnim)( 1.0 - Direction + nModifiedTime*(2.0*Direction - 1.0) ); 871 } 872 873 virtual void performEnd() 874 { 875 // xxx todo: review 876 if (mpAnim) 877 (*mpAnim)( 1.0*Direction ); 878 } 879 880 /// Disposable: 881 virtual void dispose() 882 { 883 mpAnim.reset(); 884 ContinuousActivityBase::dispose(); 885 } 886 887 private: 888 NumberAnimationSharedPtr mpAnim; 889 }; 890 891 } // anon namespace 892 893 894 AnimationActivitySharedPtr ActivitiesFactory::createAnimateActivity( 895 const CommonParameters& rParms, 896 const NumberAnimationSharedPtr& rAnim, 897 const uno::Reference< animations::XAnimate >& xNode ) 898 { 899 // forward to appropriate template instantiation 900 return createActivity( rParms, xNode, rAnim ); 901 } 902 903 AnimationActivitySharedPtr ActivitiesFactory::createAnimateActivity( 904 const CommonParameters& rParms, 905 const EnumAnimationSharedPtr& rAnim, 906 const uno::Reference< animations::XAnimate >& xNode ) 907 { 908 // forward to appropriate template instantiation 909 return createActivity( rParms, xNode, rAnim ); 910 } 911 912 AnimationActivitySharedPtr ActivitiesFactory::createAnimateActivity( 913 const CommonParameters& rParms, 914 const ColorAnimationSharedPtr& rAnim, 915 const uno::Reference< animations::XAnimate >& xNode ) 916 { 917 // forward to appropriate template instantiation 918 return createActivity( rParms, xNode, rAnim ); 919 } 920 921 AnimationActivitySharedPtr ActivitiesFactory::createAnimateActivity( 922 const CommonParameters& rParms, 923 const HSLColorAnimationSharedPtr& rAnim, 924 const uno::Reference< animations::XAnimateColor >& xNode ) 925 { 926 // forward to appropriate template instantiation 927 return createActivity( rParms, 928 uno::Reference< animations::XAnimate >( 929 xNode, uno::UNO_QUERY_THROW ), 930 rAnim, 931 // Direction==true means clockwise in SMIL API 932 Interpolator< HSLColor >( !xNode->getDirection() ) ); 933 } 934 935 AnimationActivitySharedPtr ActivitiesFactory::createAnimateActivity( 936 const CommonParameters& rParms, 937 const PairAnimationSharedPtr& rAnim, 938 const uno::Reference< animations::XAnimate >& xNode ) 939 { 940 // forward to appropriate template instantiation 941 return createActivity( rParms, xNode, rAnim ); 942 } 943 944 AnimationActivitySharedPtr ActivitiesFactory::createAnimateActivity( 945 const CommonParameters& rParms, 946 const StringAnimationSharedPtr& rAnim, 947 const uno::Reference< animations::XAnimate >& xNode ) 948 { 949 // forward to appropriate template instantiation 950 return createActivity( rParms, xNode, rAnim ); 951 } 952 953 AnimationActivitySharedPtr ActivitiesFactory::createAnimateActivity( 954 const CommonParameters& rParms, 955 const BoolAnimationSharedPtr& rAnim, 956 const uno::Reference< animations::XAnimate >& xNode ) 957 { 958 // forward to appropriate template instantiation 959 return createActivity( rParms, xNode, rAnim ); 960 } 961 962 AnimationActivitySharedPtr ActivitiesFactory::createSimpleActivity( 963 const CommonParameters& rParms, 964 const NumberAnimationSharedPtr& rAnim, 965 bool bDirectionForward ) 966 { 967 ActivityParameters aActivityParms( rParms.mpEndEvent, 968 rParms.mrEventQueue, 969 rParms.mrActivitiesQueue, 970 rParms.mnMinDuration, 971 rParms.maRepeats, 972 rParms.mnAcceleration, 973 rParms.mnDeceleration, 974 rParms.mnMinNumberOfFrames, 975 rParms.mbAutoReverse ); 976 977 if( bDirectionForward ) 978 return AnimationActivitySharedPtr( 979 new SimpleActivity<1>( aActivityParms, rAnim ) ); 980 else 981 return AnimationActivitySharedPtr( 982 new SimpleActivity<0>( aActivityParms, rAnim ) ); 983 } 984 985 } // namespace internal 986 } // namespace presentation 987 988