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