| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_slideshow.hxx" |
| |
| // must be first |
| #include <canvas/debug.hxx> |
| #include <tools/diagnose_ex.h> |
| #include <canvas/verbosetrace.hxx> |
| |
| #include <com/sun/star/animations/AnimationCalcMode.hpp> |
| #include <comphelper/sequence.hxx> |
| |
| #include "activitiesfactory.hxx" |
| #include "smilfunctionparser.hxx" |
| #include "accumulation.hxx" |
| #include "activityparameters.hxx" |
| #include "interpolation.hxx" |
| #include "tools.hxx" |
| #include "simplecontinuousactivitybase.hxx" |
| #include "discreteactivitybase.hxx" |
| #include "continuousactivitybase.hxx" |
| #include "continuouskeytimeactivitybase.hxx" |
| |
| #include <boost/bind.hpp> |
| #include <boost/optional.hpp> |
| |
| #include <cmath> // for modf |
| #include <vector> |
| #include <algorithm> |
| |
| using namespace com::sun::star; |
| |
| namespace slideshow { |
| namespace internal { |
| |
| namespace { |
| |
| /** Traits template, to take formula application only for ValueType = double |
| */ |
| template<typename ValueType> struct FormulaTraits |
| { |
| static ValueType getPresentationValue( |
| const ValueType& rVal, const ExpressionNodeSharedPtr& ) |
| { |
| return rVal; |
| } |
| }; |
| |
| /// Specialization for ValueType = double |
| template<> struct FormulaTraits<double> |
| { |
| static double getPresentationValue( |
| double const& rVal, ExpressionNodeSharedPtr const& rFormula ) |
| { |
| return rFormula ? (*rFormula)(rVal) : rVal; |
| } |
| }; |
| |
| // Various ActivityBase specializations for different animator types |
| // ================================================================= |
| |
| /** FromToBy handler |
| |
| Provides the Activity specializations for FromToBy |
| animations (e.g. those without a values list). |
| |
| This template makes heavy use of SFINAE, only one of |
| the perform*() methods will compile for each of the |
| base classes. |
| |
| Note that we omit the virtual keyword on the perform() |
| overrides on purpose; those that actually do override |
| baseclass virtual methods inherit the property, and |
| the others won't increase our vtable. What's more, |
| having all perform() method in the vtable actually |
| creates POIs for them, which breaks the whole SFINAE |
| concept (IOW, this template won't compile any longer). |
| |
| @tpl BaseType |
| Base class to use for this activity. Only |
| ContinuousActivityBase and DiscreteActivityBase are |
| supported here. |
| |
| @tpl AnimationType |
| Type of the Animation to call. |
| */ |
| template<class BaseType, typename AnimationType> |
| class FromToByActivity : public BaseType |
| { |
| public: |
| typedef typename AnimationType::ValueType ValueType; |
| typedef boost::optional<ValueType> OptionalValueType; |
| |
| private: |
| // some compilers don't inline whose definition they haven't |
| // seen before the call site... |
| ValueType getPresentationValue( const ValueType& rVal ) const |
| { |
| return FormulaTraits<ValueType>::getPresentationValue( rVal, mpFormula); |
| } |
| |
| public: |
| /** Create FromToByActivity. |
| |
| @param rFrom |
| From this value, the animation starts |
| |
| @param rTo |
| With this value, the animation ends |
| |
| @param rBy |
| With this value, the animation increments the start value |
| |
| @param rParms |
| Standard Activity parameter struct |
| |
| @param rAnim |
| Shared ptr to AnimationType |
| |
| @param rInterpolator |
| Interpolator object to be used for lerping between |
| start and end value (need to be passed, since it |
| might contain state, e.g. interpolation direction |
| for HSL color space). |
| |
| @param bCumulative |
| Whether repeated animations should cumulate the |
| value, or start fresh each time. |
| */ |
| 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 ) |
| : BaseType( rParms ), |
| maFrom( rFrom ), |
| maTo( rTo ), |
| maBy( rBy ), |
| mpFormula( rParms.mpFormula ), |
| maStartValue(), |
| maEndValue(), |
| mpAnim( rAnim ), |
| maInterpolator( rInterpolator ), |
| mbCumulative( bCumulative ) |
| { |
| ENSURE_OR_THROW( mpAnim, "Invalid animation object" ); |
| |
| ENSURE_OR_THROW( |
| rTo || rBy, |
| "From and one of To or By, or To or By alone must be valid" ); |
| } |
| |
| virtual void startAnimation() |
| { |
| if (this->isDisposed() || !mpAnim) |
| return; |
| BaseType::startAnimation(); |
| |
| // start animation |
| mpAnim->start( BaseType::getShape(), |
| BaseType::getShapeAttributeLayer() ); |
| |
| // setup start and end value. Determine animation |
| // start value only when animation actually |
| // started up (this order is part of the Animation |
| // interface contract) |
| const ValueType aAnimationStartValue( mpAnim->getUnderlyingValue() ); |
| |
| // first of all, determine general type of |
| // animation, by inspecting which of the FromToBy values |
| // are actually valid. |
| // See http://www.w3.org/TR/smil20/animation.html#AnimationNS-FromToBy |
| // for a definition |
| if( maFrom ) |
| { |
| // From-to or From-by animation. According to |
| // SMIL spec, the To value takes precedence |
| // over the By value, if both are specified |
| if( maTo ) |
| { |
| // From-To animation |
| maStartValue = *maFrom; |
| maEndValue = *maTo; |
| } |
| else if( maBy ) |
| { |
| // From-By animation |
| maStartValue = *maFrom; |
| maEndValue = maStartValue + *maBy; |
| } |
| } |
| else |
| { |
| // By or To animation. According to SMIL spec, |
| // the To value takes precedence over the By |
| // value, if both are specified |
| if( maTo ) |
| { |
| // To animation |
| maStartValue = aAnimationStartValue; |
| maEndValue = *maTo; |
| } |
| else if( maBy ) |
| { |
| // By animation |
| maStartValue = aAnimationStartValue; |
| maEndValue = maStartValue + *maBy; |
| } |
| } |
| } |
| |
| virtual void endAnimation() |
| { |
| // end animation |
| if (mpAnim) |
| mpAnim->end(); |
| } |
| |
| /// perform override for ContinuousActivityBase |
| void perform( double nModifiedTime, sal_uInt32 nRepeatCount ) const |
| { |
| if (this->isDisposed() || !mpAnim) |
| return; |
| (*mpAnim)( |
| getPresentationValue( |
| accumulate( maEndValue, |
| mbCumulative * nRepeatCount, // means: mbCumulative ? nRepeatCount : 0, |
| maInterpolator( maStartValue, |
| maEndValue, |
| nModifiedTime ) ) ) ); |
| } |
| |
| using BaseType::perform; |
| |
| /// perform override for DiscreteActivityBase base |
| void perform( sal_uInt32 nFrame, sal_uInt32 nRepeatCount ) const |
| { |
| if (this->isDisposed() || !mpAnim) |
| return; |
| (*mpAnim)( |
| getPresentationValue( |
| accumulate( maEndValue, mbCumulative ? nRepeatCount : 0, |
| lerp( maInterpolator, |
| maStartValue, |
| maEndValue, |
| nFrame, |
| BaseType::getNumberOfKeyTimes() ) ) ) ); |
| } |
| |
| using BaseType::isAutoReverse; |
| |
| virtual void performEnd() |
| { |
| // xxx todo: good guess |
| if (mpAnim) |
| { |
| if (isAutoReverse()) |
| (*mpAnim)( getPresentationValue( maStartValue ) ); |
| else |
| (*mpAnim)( getPresentationValue( maEndValue ) ); |
| } |
| } |
| |
| /// Disposable: |
| virtual void dispose() |
| { |
| mpAnim.reset(); |
| BaseType::dispose(); |
| } |
| |
| private: |
| const OptionalValueType maFrom; |
| const OptionalValueType maTo; |
| const OptionalValueType maBy; |
| |
| ExpressionNodeSharedPtr mpFormula; |
| |
| ValueType maStartValue; |
| ValueType maEndValue; |
| |
| ::boost::shared_ptr< AnimationType > mpAnim; |
| Interpolator< ValueType > maInterpolator; |
| bool mbCumulative; |
| }; |
| |
| |
| /** Generate Activity corresponding to given FromToBy values |
| |
| @tpl BaseType |
| BaseType to use for deriving the Activity from |
| |
| @tpl AnimationType |
| Subtype of the Animation object (e.g. NumberAnimation) |
| */ |
| template<class BaseType, typename AnimationType> |
| AnimationActivitySharedPtr 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 ) |
| { |
| typedef typename AnimationType::ValueType ValueType; |
| typedef boost::optional<ValueType> OptionalValueType; |
| |
| OptionalValueType aFrom; |
| OptionalValueType aTo; |
| OptionalValueType aBy; |
| |
| ValueType aTmpValue; |
| |
| if( rFromAny.hasValue() ) |
| { |
| ENSURE_OR_THROW( |
| extractValue( aTmpValue, rFromAny, rShape, rSlideBounds ), |
| "createFromToByActivity(): Could not extract from value" ); |
| aFrom.reset(aTmpValue); |
| } |
| if( rToAny.hasValue() ) |
| { |
| ENSURE_OR_THROW( |
| extractValue( aTmpValue, rToAny, rShape, rSlideBounds ), |
| "createFromToByActivity(): Could not extract to value" ); |
| aTo.reset(aTmpValue); |
| } |
| if( rByAny.hasValue() ) |
| { |
| ENSURE_OR_THROW( |
| extractValue( aTmpValue, rByAny, rShape, rSlideBounds ), |
| "createFromToByActivity(): Could not extract by value" ); |
| aBy.reset(aTmpValue); |
| } |
| |
| return AnimationActivitySharedPtr( |
| new FromToByActivity<BaseType, AnimationType>( |
| aFrom, |
| aTo, |
| aBy, |
| rParms, |
| rAnim, |
| rInterpolator, |
| bCumulative ) ); |
| } |
| |
| /* The following table shows which animator combines with |
| which Activity type: |
| |
| NumberAnimator: all |
| PairAnimation: all |
| ColorAnimation: all |
| StringAnimation: DiscreteActivityBase |
| BoolAnimation: DiscreteActivityBase |
| */ |
| |
| /** Values handler |
| |
| Provides the Activity specializations for value lists |
| animations. |
| |
| This template makes heavy use of SFINAE, only one of |
| the perform*() methods will compile for each of the |
| base classes. |
| |
| Note that we omit the virtual keyword on the perform() |
| overrides on purpose; those that actually do override |
| baseclass virtual methods inherit the property, and |
| the others won't increase our vtable. What's more, |
| having all perform() method in the vtable actually |
| creates POIs for them, which breaks the whole SFINAE |
| concept (IOW, this template won't compile any longer). |
| |
| @tpl BaseType |
| Base class to use for this activity. Only |
| ContinuousKeyTimeActivityBase and DiscreteActivityBase |
| are supported here. For values animation without key |
| times, the client must emulate key times by providing |
| a vector of equally spaced values between 0 and 1, |
| with the same number of entries as the values vector. |
| |
| @tpl AnimationType |
| Type of the Animation to call. |
| */ |
| template<class BaseType, typename AnimationType> |
| class ValuesActivity : public BaseType |
| { |
| public: |
| typedef typename AnimationType::ValueType ValueType; |
| typedef std::vector<ValueType> ValueVectorType; |
| |
| private: |
| // some compilers don't inline methods whose definition they haven't |
| // seen before the call site... |
| ValueType getPresentationValue( const ValueType& rVal ) const |
| { |
| return FormulaTraits<ValueType>::getPresentationValue( |
| rVal, mpFormula ); |
| } |
| |
| public: |
| /** Create ValuesActivity. |
| |
| @param rValues |
| Value vector to cycle animation through |
| |
| @param rParms |
| Standard Activity parameter struct |
| |
| @param rAnim |
| Shared ptr to AnimationType |
| |
| @param rInterpolator |
| Interpolator object to be used for lerping between |
| start and end value (need to be passed, since it |
| might contain state, e.g. interpolation direction |
| for HSL color space). |
| |
| @param bCumulative |
| Whether repeated animations should cumulate the |
| value, or start afresh each time. |
| */ |
| ValuesActivity( |
| const ValueVectorType& rValues, |
| const ActivityParameters& rParms, |
| const boost::shared_ptr<AnimationType>& rAnim, |
| const Interpolator< ValueType >& rInterpolator, |
| bool bCumulative ) |
| : BaseType( rParms ), |
| maValues( rValues ), |
| mpFormula( rParms.mpFormula ), |
| mpAnim( rAnim ), |
| maInterpolator( rInterpolator ), |
| mbCumulative( bCumulative ) |
| { |
| ENSURE_OR_THROW( mpAnim, "Invalid animation object" ); |
| ENSURE_OR_THROW( !rValues.empty(), "Empty value vector" ); |
| } |
| |
| virtual void startAnimation() |
| { |
| if (this->isDisposed() || !mpAnim) |
| return; |
| BaseType::startAnimation(); |
| |
| // start animation |
| mpAnim->start( BaseType::getShape(), |
| BaseType::getShapeAttributeLayer() ); |
| } |
| |
| virtual void endAnimation() |
| { |
| // end animation |
| if (mpAnim) |
| mpAnim->end(); |
| } |
| |
| /// perform override for ContinuousKeyTimeActivityBase base |
| void perform( sal_uInt32 nIndex, |
| double nFractionalIndex, |
| sal_uInt32 nRepeatCount ) const |
| { |
| if (this->isDisposed() || !mpAnim) |
| return; |
| ENSURE_OR_THROW( nIndex+1 < maValues.size(), |
| "ValuesActivity::perform(): index out of range" ); |
| |
| // interpolate between nIndex and nIndex+1 values |
| (*mpAnim)( |
| getPresentationValue( |
| accumulate<ValueType>( maValues.back(), |
| mbCumulative ? nRepeatCount : 0, |
| maInterpolator( maValues[ nIndex ], |
| maValues[ nIndex+1 ], |
| nFractionalIndex ) ) ) ); |
| } |
| |
| using BaseType::perform; |
| |
| /// perform override for DiscreteActivityBase base |
| void perform( sal_uInt32 nFrame, sal_uInt32 nRepeatCount ) const |
| { |
| if (this->isDisposed() || !mpAnim) |
| return; |
| ENSURE_OR_THROW( nFrame < maValues.size(), |
| "ValuesActivity::perform(): index out of range" ); |
| |
| // this is discrete, thus no lerp here. |
| (*mpAnim)( |
| getPresentationValue( |
| accumulate<ValueType>( maValues.back(), |
| mbCumulative ? nRepeatCount : 0, |
| maValues[ nFrame ] ) ) ); |
| } |
| |
| virtual void performEnd() |
| { |
| // xxx todo: good guess |
| if (mpAnim) |
| (*mpAnim)( getPresentationValue( maValues.back() ) ); |
| } |
| |
| /// Disposable: |
| virtual void dispose() |
| { |
| mpAnim.reset(); |
| BaseType::dispose(); |
| } |
| |
| private: |
| ValueVectorType maValues; |
| |
| ExpressionNodeSharedPtr mpFormula; |
| |
| boost::shared_ptr<AnimationType> mpAnim; |
| Interpolator< ValueType > maInterpolator; |
| bool mbCumulative; |
| }; |
| |
| /** Generate Activity corresponding to given Value vector |
| |
| @tpl BaseType |
| BaseType to use for deriving the Activity from |
| |
| @tpl AnimationType |
| Subtype of the Animation object (e.g. NumberAnimation) |
| */ |
| template<class BaseType, typename AnimationType> |
| AnimationActivitySharedPtr 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 ) |
| { |
| typedef typename AnimationType::ValueType ValueType; |
| typedef std::vector<ValueType> ValueVectorType; |
| |
| ValueVectorType aValueVector; |
| aValueVector.reserve( rValues.getLength() ); |
| |
| for( ::std::size_t i=0, nLen=rValues.getLength(); i<nLen; ++i ) |
| { |
| ValueType aValue; |
| ENSURE_OR_THROW( |
| extractValue( aValue, rValues[i], rShape, rSlideBounds ), |
| "createValueListActivity(): Could not extract values" ); |
| aValueVector.push_back( aValue ); |
| } |
| |
| return AnimationActivitySharedPtr( |
| new ValuesActivity<BaseType, AnimationType>( |
| aValueVector, |
| rParms, |
| rAnim, |
| rInterpolator, |
| bCumulative ) ); |
| } |
| |
| /** Generate Activity for given XAnimate, corresponding to given Value vector |
| |
| @tpl AnimationType |
| Subtype of the Animation object (e.g. NumberAnimation) |
| |
| @param rParms |
| Common activity parameters |
| |
| @param xNode |
| XAnimate node, to retrieve animation values from |
| |
| @param rAnim |
| Actual animation to operate with (gets called with the |
| time-dependent values) |
| |
| @param rInterpolator |
| Interpolator object to be used for lerping between |
| start and end values (need to be passed, since it |
| might contain state, e.g. interpolation direction |
| for HSL color space). |
| */ |
| template<typename AnimationType> |
| AnimationActivitySharedPtr 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 >() ) |
| { |
| // setup common parameters |
| // ======================= |
| |
| ActivityParameters aActivityParms( rParms.mpEndEvent, |
| rParms.mrEventQueue, |
| rParms.mrActivitiesQueue, |
| rParms.mnMinDuration, |
| rParms.maRepeats, |
| rParms.mnAcceleration, |
| rParms.mnDeceleration, |
| rParms.mnMinNumberOfFrames, |
| rParms.mbAutoReverse ); |
| |
| // is a formula given? |
| const ::rtl::OUString& rFormulaString( xNode->getFormula() ); |
| if( rFormulaString.getLength() ) |
| { |
| // yep, parse and pass to ActivityParameters |
| try |
| { |
| aActivityParms.mpFormula = |
| SmilFunctionParser::parseSmilFunction( |
| rFormulaString, |
| calcRelativeShapeBounds( |
| rParms.maSlideBounds, |
| rParms.mpShape->getBounds() ) ); |
| } |
| catch( ParseError& ) |
| { |
| // parse error, thus no formula |
| OSL_ENSURE( false, |
| "createActivity(): Error parsing formula string" ); |
| } |
| } |
| |
| // are key times given? |
| const uno::Sequence< double >& aKeyTimes( xNode->getKeyTimes() ); |
| if( aKeyTimes.hasElements() ) |
| { |
| // yes, convert them from Sequence< double > |
| aActivityParms.maDiscreteTimes.resize( aKeyTimes.getLength() ); |
| comphelper::sequenceToArray( |
| &aActivityParms.maDiscreteTimes[0], |
| aKeyTimes ); // saves us some temporary vectors |
| } |
| |
| // values sequence given? |
| const sal_Int32 nValueLen( xNode->getValues().getLength() ); |
| if( nValueLen ) |
| { |
| // Value list activity |
| // =================== |
| |
| // fake keytimes, if necessary |
| if( !aKeyTimes.hasElements() ) |
| { |
| // create a dummy vector of key times, |
| // with aValues.getLength equally spaced entries. |
| for( sal_Int32 i=0; i<nValueLen; ++i ) |
| aActivityParms.maDiscreteTimes.push_back( double(i)/nValueLen ); |
| } |
| |
| // determine type of animation needed here: |
| // Value list activities are possible with |
| // ContinuousKeyTimeActivityBase and DiscreteActivityBase |
| // specializations |
| const sal_Int16 nCalcMode( xNode->getCalcMode() ); |
| |
| switch( nCalcMode ) |
| { |
| case animations::AnimationCalcMode::DISCRETE: |
| { |
| // since DiscreteActivityBase suspends itself |
| // between the frames, create a WakeupEvent for it. |
| aActivityParms.mpWakeupEvent.reset( |
| new WakeupEvent( |
| rParms.mrEventQueue.getTimer(), |
| rParms.mrActivitiesQueue ) ); |
| |
| AnimationActivitySharedPtr pActivity( |
| createValueListActivity< DiscreteActivityBase >( |
| xNode->getValues(), |
| aActivityParms, |
| rAnim, |
| rInterpolator, |
| xNode->getAccumulate(), |
| rParms.mpShape, |
| rParms.maSlideBounds ) ); |
| |
| // WakeupEvent and DiscreteActivityBase need circular |
| // references to the corresponding other object. |
| aActivityParms.mpWakeupEvent->setActivity( pActivity ); |
| |
| return pActivity; |
| } |
| |
| default: |
| OSL_ENSURE( false, "createActivity(): unexpected case" ); |
| // FALLTHROUGH intended |
| case animations::AnimationCalcMode::PACED: |
| // FALLTHROUGH intended |
| case animations::AnimationCalcMode::SPLINE: |
| // FALLTHROUGH intended |
| case animations::AnimationCalcMode::LINEAR: |
| return createValueListActivity< ContinuousKeyTimeActivityBase >( |
| xNode->getValues(), |
| aActivityParms, |
| rAnim, |
| rInterpolator, |
| xNode->getAccumulate(), |
| rParms.mpShape, |
| rParms.maSlideBounds ); |
| } |
| } |
| else |
| { |
| // FromToBy activity |
| // ================= |
| |
| // determine type of animation needed here: |
| // FromToBy activities are possible with |
| // ContinuousActivityBase and DiscreteActivityBase |
| // specializations |
| const sal_Int16 nCalcMode( xNode->getCalcMode() ); |
| |
| switch( nCalcMode ) |
| { |
| case animations::AnimationCalcMode::DISCRETE: |
| { |
| // fake keytimes, if necessary |
| if( !aKeyTimes.hasElements() ) |
| { |
| // create a dummy vector of 2 key times |
| const ::std::size_t nLen( 2 ); |
| for( ::std::size_t i=0; i<nLen; ++i ) |
| aActivityParms.maDiscreteTimes.push_back( double(i)/nLen ); |
| } |
| |
| // since DiscreteActivityBase suspends itself |
| // between the frames, create a WakeupEvent for it. |
| aActivityParms.mpWakeupEvent.reset( |
| new WakeupEvent( |
| rParms.mrEventQueue.getTimer(), |
| rParms.mrActivitiesQueue ) ); |
| |
| AnimationActivitySharedPtr pActivity( |
| createFromToByActivity< DiscreteActivityBase >( |
| xNode->getFrom(), |
| xNode->getTo(), |
| xNode->getBy(), |
| aActivityParms, |
| rAnim, |
| rInterpolator, |
| xNode->getAccumulate(), |
| rParms.mpShape, |
| rParms.maSlideBounds ) ); |
| |
| // WakeupEvent and DiscreteActivityBase need circular |
| // references to the corresponding other object. |
| aActivityParms.mpWakeupEvent->setActivity( pActivity ); |
| |
| return pActivity; |
| } |
| |
| default: |
| OSL_ENSURE( false, "createActivity(): unexpected case" ); |
| // FALLTHROUGH intended |
| case animations::AnimationCalcMode::PACED: |
| // FALLTHROUGH intended |
| case animations::AnimationCalcMode::SPLINE: |
| // FALLTHROUGH intended |
| case animations::AnimationCalcMode::LINEAR: |
| return createFromToByActivity< ContinuousActivityBase >( |
| xNode->getFrom(), |
| xNode->getTo(), |
| xNode->getBy(), |
| aActivityParms, |
| rAnim, |
| rInterpolator, |
| xNode->getAccumulate(), |
| rParms.mpShape, |
| rParms.maSlideBounds ); |
| } |
| } |
| } |
| |
| /** Simple activity for ActivitiesFactory::createSimpleActivity |
| |
| @tpl Direction |
| Determines direction of value generator. A 1 yields a |
| forward direction, starting with 0.0 and ending with |
| 1.0. A 0 yields a backward direction, starting with |
| 1.0 and ending with 0.0 |
| */ |
| template<int Direction> |
| class SimpleActivity : public ContinuousActivityBase |
| { |
| public: |
| /** Create SimpleActivity. |
| |
| @param rParms |
| Standard Activity parameter struct |
| */ |
| SimpleActivity( const ActivityParameters& rParms, |
| const NumberAnimationSharedPtr& rAnim ) : |
| ContinuousActivityBase( rParms ), |
| mpAnim( rAnim ) |
| { |
| ENSURE_OR_THROW( mpAnim, "Invalid animation object" ); |
| } |
| |
| virtual void startAnimation() |
| { |
| if (this->isDisposed() || !mpAnim) |
| return; |
| ContinuousActivityBase::startAnimation(); |
| |
| // start animation |
| mpAnim->start( getShape(), |
| getShapeAttributeLayer() ); |
| } |
| |
| virtual void endAnimation() |
| { |
| // end animation |
| if (mpAnim) |
| mpAnim->end(); |
| } |
| |
| using SimpleContinuousActivityBase::perform; |
| |
| /// perform override for ContinuousActivityBase |
| virtual void perform( double nModifiedTime, sal_uInt32 ) const |
| { |
| if (this->isDisposed() || !mpAnim) |
| return; |
| // no cumulation, simple [0,1] range |
| (*mpAnim)( 1.0 - Direction + nModifiedTime*(2.0*Direction - 1.0) ); |
| } |
| |
| virtual void performEnd() |
| { |
| // xxx todo: review |
| if (mpAnim) |
| (*mpAnim)( 1.0*Direction ); |
| } |
| |
| /// Disposable: |
| virtual void dispose() |
| { |
| mpAnim.reset(); |
| ContinuousActivityBase::dispose(); |
| } |
| |
| private: |
| NumberAnimationSharedPtr mpAnim; |
| }; |
| |
| } // anon namespace |
| |
| |
| AnimationActivitySharedPtr ActivitiesFactory::createAnimateActivity( |
| const CommonParameters& rParms, |
| const NumberAnimationSharedPtr& rAnim, |
| const uno::Reference< animations::XAnimate >& xNode ) |
| { |
| // forward to appropriate template instantiation |
| return createActivity( rParms, xNode, rAnim ); |
| } |
| |
| AnimationActivitySharedPtr ActivitiesFactory::createAnimateActivity( |
| const CommonParameters& rParms, |
| const EnumAnimationSharedPtr& rAnim, |
| const uno::Reference< animations::XAnimate >& xNode ) |
| { |
| // forward to appropriate template instantiation |
| return createActivity( rParms, xNode, rAnim ); |
| } |
| |
| AnimationActivitySharedPtr ActivitiesFactory::createAnimateActivity( |
| const CommonParameters& rParms, |
| const ColorAnimationSharedPtr& rAnim, |
| const uno::Reference< animations::XAnimate >& xNode ) |
| { |
| // forward to appropriate template instantiation |
| return createActivity( rParms, xNode, rAnim ); |
| } |
| |
| AnimationActivitySharedPtr ActivitiesFactory::createAnimateActivity( |
| const CommonParameters& rParms, |
| const HSLColorAnimationSharedPtr& rAnim, |
| const uno::Reference< animations::XAnimateColor >& xNode ) |
| { |
| // forward to appropriate template instantiation |
| return createActivity( rParms, |
| uno::Reference< animations::XAnimate >( |
| xNode, uno::UNO_QUERY_THROW ), |
| rAnim, |
| // Direction==true means clockwise in SMIL API |
| Interpolator< HSLColor >( !xNode->getDirection() ) ); |
| } |
| |
| AnimationActivitySharedPtr ActivitiesFactory::createAnimateActivity( |
| const CommonParameters& rParms, |
| const PairAnimationSharedPtr& rAnim, |
| const uno::Reference< animations::XAnimate >& xNode ) |
| { |
| // forward to appropriate template instantiation |
| return createActivity( rParms, xNode, rAnim ); |
| } |
| |
| AnimationActivitySharedPtr ActivitiesFactory::createAnimateActivity( |
| const CommonParameters& rParms, |
| const StringAnimationSharedPtr& rAnim, |
| const uno::Reference< animations::XAnimate >& xNode ) |
| { |
| // forward to appropriate template instantiation |
| return createActivity( rParms, xNode, rAnim ); |
| } |
| |
| AnimationActivitySharedPtr ActivitiesFactory::createAnimateActivity( |
| const CommonParameters& rParms, |
| const BoolAnimationSharedPtr& rAnim, |
| const uno::Reference< animations::XAnimate >& xNode ) |
| { |
| // forward to appropriate template instantiation |
| return createActivity( rParms, xNode, rAnim ); |
| } |
| |
| AnimationActivitySharedPtr ActivitiesFactory::createSimpleActivity( |
| const CommonParameters& rParms, |
| const NumberAnimationSharedPtr& rAnim, |
| bool bDirectionForward ) |
| { |
| ActivityParameters aActivityParms( rParms.mpEndEvent, |
| rParms.mrEventQueue, |
| rParms.mrActivitiesQueue, |
| rParms.mnMinDuration, |
| rParms.maRepeats, |
| rParms.mnAcceleration, |
| rParms.mnDeceleration, |
| rParms.mnMinNumberOfFrames, |
| rParms.mbAutoReverse ); |
| |
| if( bDirectionForward ) |
| return AnimationActivitySharedPtr( |
| new SimpleActivity<1>( aActivityParms, rAnim ) ); |
| else |
| return AnimationActivitySharedPtr( |
| new SimpleActivity<0>( aActivityParms, rAnim ) ); |
| } |
| |
| } // namespace internal |
| } // namespace presentation |
| |