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