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