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