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 {
getPresentationValueslideshow::internal::__anon9f54c5e60111::FormulaTraits64 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 {
getPresentationValueslideshow::internal::__anon9f54c5e60111::FormulaTraits74 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...
getPresentationValue(const ValueType & rVal) const119 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 */
FromToByActivity(const OptionalValueType & rFrom,const OptionalValueType & rTo,const OptionalValueType & rBy,const ActivityParameters & rParms,const::boost::shared_ptr<AnimationType> & rAnim,const Interpolator<ValueType> & rInterpolator,bool bCumulative)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
startAnimation()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
endAnimation()237 virtual void endAnimation()
238 {
239 // end animation
240 if (mpAnim)
241 mpAnim->end();
242 }
243
244 /// perform override for ContinuousActivityBase
perform(double nModifiedTime,sal_uInt32 nRepeatCount) const245 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
perform(sal_uInt32 nFrame,sal_uInt32 nRepeatCount) const261 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
performEnd()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:
dispose()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>
createFromToByActivity(const uno::Any & rFromAny,const uno::Any & rToAny,const uno::Any & rByAny,const ActivityParameters & rParms,const::boost::shared_ptr<AnimationType> & rAnim,const Interpolator<typename AnimationType::ValueType> & rInterpolator,bool bCumulative,const ShapeSharedPtr & rShape,const::basegfx::B2DVector & rSlideBounds)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...
getPresentationValue(const ValueType & rVal) const422 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 */
ValuesActivity(const ValueVectorType & rValues,const ActivityParameters & rParms,const boost::shared_ptr<AnimationType> & rAnim,const Interpolator<ValueType> & rInterpolator,bool bCumulative)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
startAnimation()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
endAnimation()478 virtual void endAnimation()
479 {
480 // end animation
481 if (mpAnim)
482 mpAnim->end();
483 }
484
485 /// perform override for ContinuousKeyTimeActivityBase base
perform(sal_uInt32 nIndex,double nFractionalIndex,sal_uInt32 nRepeatCount) const486 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<ValueType>( 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
perform(sal_uInt32 nFrame,sal_uInt32 nRepeatCount) const508 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<ValueType>( maValues.back(),
519 mbCumulative ? nRepeatCount : 0,
520 maValues[ nFrame ] ) ) );
521 }
522
performEnd()523 virtual void performEnd()
524 {
525 // xxx todo: good guess
526 if (mpAnim)
527 (*mpAnim)( getPresentationValue( maValues.back() ) );
528 }
529
530 /// Disposable:
dispose()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>
createValueListActivity(const uno::Sequence<uno::Any> & rValues,const ActivityParameters & rParms,const boost::shared_ptr<AnimationType> & rAnim,const Interpolator<typename AnimationType::ValueType> & rInterpolator,bool bCumulative,const ShapeSharedPtr & rShape,const::basegfx::B2DVector & rSlideBounds)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>
createActivity(const ActivitiesFactory::CommonParameters & rParms,const uno::Reference<animations::XAnimate> & xNode,const::boost::shared_ptr<AnimationType> & rAnim,const Interpolator<typename AnimationType::ValueType> & rInterpolator=Interpolator<typename AnimationType::ValueType> ())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 */
SimpleActivity(const ActivityParameters & rParms,const NumberAnimationSharedPtr & rAnim)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
startAnimation()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
endAnimation()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
perform(double nModifiedTime,sal_uInt32) const850 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
performEnd()858 virtual void performEnd()
859 {
860 // xxx todo: review
861 if (mpAnim)
862 (*mpAnim)( 1.0*Direction );
863 }
864
865 /// Disposable:
dispose()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
createAnimateActivity(const CommonParameters & rParms,const NumberAnimationSharedPtr & rAnim,const uno::Reference<animations::XAnimate> & xNode)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
createAnimateActivity(const CommonParameters & rParms,const EnumAnimationSharedPtr & rAnim,const uno::Reference<animations::XAnimate> & xNode)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
createAnimateActivity(const CommonParameters & rParms,const ColorAnimationSharedPtr & rAnim,const uno::Reference<animations::XAnimate> & xNode)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
createAnimateActivity(const CommonParameters & rParms,const HSLColorAnimationSharedPtr & rAnim,const uno::Reference<animations::XAnimateColor> & xNode)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
createAnimateActivity(const CommonParameters & rParms,const PairAnimationSharedPtr & rAnim,const uno::Reference<animations::XAnimate> & xNode)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
createAnimateActivity(const CommonParameters & rParms,const StringAnimationSharedPtr & rAnim,const uno::Reference<animations::XAnimate> & xNode)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
createAnimateActivity(const CommonParameters & rParms,const BoolAnimationSharedPtr & rAnim,const uno::Reference<animations::XAnimate> & xNode)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
createSimpleActivity(const CommonParameters & rParms,const NumberAnimationSharedPtr & rAnim,bool bDirectionForward)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