filter/source/svg/presentation_engine.js | 95 +++++++++-- slideshow/source/engine/activities/activitiesfactory.cxx | 75 +++++++- slideshow/source/engine/animationnodes/animationbasenode.cxx | 14 + slideshow/source/engine/color.cxx | 25 ++ slideshow/source/inc/hslcolor.hxx | 2 slideshow/source/inc/rgbcolor.hxx | 2 6 files changed, 193 insertions(+), 20 deletions(-)
New commits: commit a42f479ae3a951656e0a29c46760d9df1615fff2 Author: Marco Cecchetti <mrcek...@gmail.com> Date: Wed Jun 13 19:50:38 2012 +0200 Now to animations and repeated to animations are handled by the C++ presentation engine as the SMIL spec describes. diff --git a/slideshow/source/engine/activities/activitiesfactory.cxx b/slideshow/source/engine/activities/activitiesfactory.cxx index f142456..a99a32a 100644 --- a/slideshow/source/engine/activities/activitiesfactory.cxx +++ b/slideshow/source/engine/activities/activitiesfactory.cxx @@ -167,6 +167,9 @@ public: mpFormula( rParms.mpFormula ), maStartValue(), maEndValue(), + maPreviousValue(), + maStartInterpolationValue(), + mnIteration( 0 ), mpAnim( rAnim ), maInterpolator( rInterpolator ), mbDynamicStartValue( false ), @@ -220,6 +223,9 @@ public: } else { + maStartValue = aAnimationStartValue; + maStartInterpolationValue = maStartValue; + // By or To animation. According to SMIL spec, // the To value takes precedence over the By // value, if both are specified @@ -232,6 +238,7 @@ public: // the to animation interpolates between // the _running_ underlying value and the to value (as the end value) mbDynamicStartValue = true; + maPreviousValue = maStartValue; maEndValue = *maTo; } else if( maBy ) @@ -255,15 +262,61 @@ public: { if (this->isDisposed() || !mpAnim) return; - (*mpAnim)( - getPresentationValue( - accumulate( maEndValue, - mbCumulative * nRepeatCount, // means: mbCumulative ? nRepeatCount : 0, - maInterpolator( (mbDynamicStartValue - ? mpAnim->getUnderlyingValue() - : maStartValue), - maEndValue, - nModifiedTime ) ) ) ); + + // According to SMIL 3.0 spec 'to' animation if no other (lower priority) + // animations are active or frozen then a simple interpolation is performed. + // That is, the start interpolation value is constant while the animation + // is running, and is equal to the underlying value retrieved when + // the animation start. + // However if another animation is manipulating the underlying value, + // the 'to' animation will initially add to the effect of the lower priority + // animation, and increasingly dominate it as it nears the end of the + // simple duration, eventually overriding it completely. + // That is, each time the underlying value is changed between two + // computations of the animation function the new underlying value is used + // as start value for the interpolation. + // See: + // http://www.w3.org/TR/SMIL3/smil-animation.html#animationNS-ToAnimation + // (Figure 6 - Effect of Additive to animation example) + // Moreover when a 'to' animation is repeated, at each new iteration + // the start interpolation value is reset to the underlying value + // of the animated property when the animation started, + // as it is shown in the example provided by the SMIL 3.0 spec. + // This is exactly as Firefox performs SVG 'to' animations. + if( mbDynamicStartValue ) + { + if( mnIteration != nRepeatCount ) + { + mnIteration = nRepeatCount; + maStartInterpolationValue = maStartValue; + } + else + { + ValueType aActualValue = mpAnim->getUnderlyingValue(); + if( aActualValue != maPreviousValue ) + maStartInterpolationValue = aActualValue; + } + } + + ValueType aValue = maInterpolator( maStartInterpolationValue, + maEndValue, nModifiedTime ); + + // According to the SMIL spec: + // Because 'to' animation is defined in terms of absolute values of + // the target attribute, cumulative animation is not defined. + if( mbCumulative && !mbDynamicStartValue ) + { + // aValue = this.aEndValue * nRepeatCount + aValue; + aValue = accumulate( maEndValue, nRepeatCount, aValue ); + } + + (*mpAnim)( getPresentationValue( aValue ) ); + + if( mbDynamicStartValue ) + { + maPreviousValue = mpAnim->getUnderlyingValue(); + } + } using BaseType::perform; @@ -316,6 +369,10 @@ private: ValueType maStartValue; ValueType maEndValue; + mutable ValueType maPreviousValue; + mutable ValueType maStartInterpolationValue; + mutable sal_uInt32 mnIteration; + ::boost::shared_ptr< AnimationType > mpAnim; Interpolator< ValueType > maInterpolator; bool mbDynamicStartValue; diff --git a/slideshow/source/engine/animationnodes/animationbasenode.cxx b/slideshow/source/engine/animationnodes/animationbasenode.cxx index df1bcc5..ed63495 100644 --- a/slideshow/source/engine/animationnodes/animationbasenode.cxx +++ b/slideshow/source/engine/animationnodes/animationbasenode.cxx @@ -33,6 +33,7 @@ #include <cppuhelper/exc_hlp.hxx> #include <comphelper/anytostring.hxx> #include <com/sun/star/presentation/ParagraphTarget.hpp> +#include <com/sun/star/animations/AnimationNodeType.hpp> #include <com/sun/star/animations/Timing.hpp> #include <com/sun/star/animations/AnimationAdditiveMode.hpp> #include <com/sun/star/presentation/ShapeAnimationSubType.hpp> @@ -421,7 +422,18 @@ AnimationBaseNode::fillCommonParameters() const else aRepeats.reset( nRepeats / nDuration ); } - else { + // This is a temporary workaround: + // as the repeatCount attribute is defined on the <par> parent node + // and activities are created only for animation node leaves, that + // actual performs a shape effect, we get the repeatCount value + // from the parent node. + else if( ( getXAnimationNode()->getType() != animations::AnimationNodeType::SET ) + && (getParentNode()->getXAnimationNode()->getRepeatCount() >>= nRepeats) ) + { + aRepeats.reset( nRepeats ); + } + else + { // no double value for both values - Timing::INDEFINITE? animations::Timing eTiming; diff --git a/slideshow/source/engine/color.cxx b/slideshow/source/engine/color.cxx index dc5092b..c9ce4f2 100644 --- a/slideshow/source/engine/color.cxx +++ b/slideshow/source/engine/color.cxx @@ -217,6 +217,19 @@ namespace slideshow return maHSLTriple.mnLuminance; } + + sal_Bool operator==( const HSLColor& rLHS, const HSLColor& rRHS ) + { + return ( rLHS.getHue() == rRHS.getHue() && + rLHS.getSaturation() == rRHS.getSaturation() && + rLHS.getLuminance() == rRHS.getLuminance() ); + } + + sal_Bool operator!=( const HSLColor& rLHS, const HSLColor& rRHS ) + { + return !( rLHS == rRHS ); + } + HSLColor operator+( const HSLColor& rLHS, const HSLColor& rRHS ) { return HSLColor( rLHS.getHue() + rRHS.getHue(), @@ -346,6 +359,18 @@ namespace slideshow 255 ); } + sal_Bool operator==( const RGBColor& rLHS, const RGBColor& rRHS ) + { + return ( rLHS.getRed() == rRHS.getRed() && + rLHS.getGreen() == rRHS.getGreen() && + rLHS.getBlue() == rRHS.getBlue() ); + } + + sal_Bool operator!=( const RGBColor& rLHS, const RGBColor& rRHS ) + { + return !( rLHS == rRHS ); + } + RGBColor operator+( const RGBColor& rLHS, const RGBColor& rRHS ) { return RGBColor( rLHS.getRed() + rRHS.getRed(), diff --git a/slideshow/source/inc/hslcolor.hxx b/slideshow/source/inc/hslcolor.hxx index 6659923..15500c7 100644 --- a/slideshow/source/inc/hslcolor.hxx +++ b/slideshow/source/inc/hslcolor.hxx @@ -88,6 +88,8 @@ namespace slideshow double mnMagicValue; }; + sal_Bool operator==( const HSLColor& rLHS, const HSLColor& rRHS ); + sal_Bool operator!=( const HSLColor& rLHS, const HSLColor& rRHS ); HSLColor operator+( const HSLColor& rLHS, const HSLColor& rRHS ); HSLColor operator*( const HSLColor& rLHS, const HSLColor& rRHS ); HSLColor operator*( double nFactor, const HSLColor& rRHS ); diff --git a/slideshow/source/inc/rgbcolor.hxx b/slideshow/source/inc/rgbcolor.hxx index fc161f7..844f324 100644 --- a/slideshow/source/inc/rgbcolor.hxx +++ b/slideshow/source/inc/rgbcolor.hxx @@ -84,6 +84,8 @@ namespace slideshow RGBTriple maRGBTriple; }; + sal_Bool operator==( const RGBColor& rLHS, const RGBColor& rRHS ); + sal_Bool operator!=( const RGBColor& rLHS, const RGBColor& rRHS ); RGBColor operator+( const RGBColor& rLHS, const RGBColor& rRHS ); RGBColor operator*( const RGBColor& rLHS, const RGBColor& rRHS ); RGBColor operator*( double nFactor, const RGBColor& rRHS ); commit 1c0b86543fd22a04d391bc96124024b7168128e7 Author: Marco Cecchetti <mrcek...@gmail.com> Date: Tue Jun 12 21:42:41 2012 +0200 Now to animations and repeated to animations are handled by the JavaScript engine as the SMIL spec describes. diff --git a/filter/source/svg/presentation_engine.js b/filter/source/svg/presentation_engine.js index 1ce3e16..13efb60 100644 --- a/filter/source/svg/presentation_engine.js +++ b/filter/source/svg/presentation_engine.js @@ -3375,6 +3375,13 @@ RGBColor.prototype.clone = function() return new RGBColor( this.nRed, this.nGreen, this.nBlue ); }; +RGBColor.prototype.equal = function( aRGBColor ) +{ + return ( this.nRed == aRGBColor.nRed ) && + ( this.nGreen == aRGBColor.nGreen ) && + ( this.nBlue == aRGBColor.nBlue ); +}; + RGBColor.prototype.add = function( aRGBColor ) { this.nRed += aRGBColor.nRed; @@ -3488,6 +3495,13 @@ HSLColor.prototype.clone = function() return new HSLColor( this.nHue, this.nSaturation, this.nLuminance ); }; +HSLColor.prototype.equal = function( aHSLColor ) +{ + return ( this.nHue == aHSLColor.nHue ) && + ( this.nSaturation += aHSLColor.nSaturation ) && + ( this.nLuminance += aHSLColor.nLuminance ); +}; + HSLColor.prototype.add = function( aHSLColor ) { this.nHue += aHSLColor.nHue; @@ -3990,11 +4004,11 @@ aPresetIdInMap = {}; // Restart Modes -RESTART_MODE_DEFAULT = 0; -RESTART_MODE_INHERIT = 0; -RESTART_MODE_ALWAYS = 1; -RESTART_MODE_WHEN_NOT_ACTIVE = 2; -RESTART_MODE_NEVER = 3; +var RESTART_MODE_DEFAULT = 0; +var RESTART_MODE_INHERIT = 0; +var RESTART_MODE_ALWAYS = 1; +var RESTART_MODE_WHEN_NOT_ACTIVE = 2; +var RESTART_MODE_NEVER = 3; aRestartModeInMap = { 'inherit' : RESTART_MODE_DEFAULT, @@ -4168,7 +4182,7 @@ BOXWIPE_TRANSITION = 2; FOURBOXWIPE_TRANSITION = 3; ELLIPSEWIPE_TRANSITION = 4; // 17 CLOCKWIPE_TRANSITION = 5; // 22 -PINWHEELWIPE_TRANSITION = 6 // 23 +PINWHEELWIPE_TRANSITION = 6; // 23 PUSHWIPE_TRANSITION = 7; // 35 SLIDEWIPE_TRANSITION = 8; // 36 FADE_TRANSITION = 9; // 37 @@ -9613,6 +9627,11 @@ var aOperatorSetMap = new Array(); // number operators aOperatorSetMap[ NUMBER_PROPERTY ] = new Object(); +aOperatorSetMap[ NUMBER_PROPERTY ].equal = function( a, b ) +{ + return ( a === b ); +}; + aOperatorSetMap[ NUMBER_PROPERTY ].add = function( a, b ) { return ( a + b ); @@ -9626,6 +9645,11 @@ aOperatorSetMap[ NUMBER_PROPERTY ].scale = function( k, v ) // color operators aOperatorSetMap[ COLOR_PROPERTY ] = new Object(); +aOperatorSetMap[ COLOR_PROPERTY ].equal = function( a, b ) +{ + return a.equal( b ); +}; + aOperatorSetMap[ COLOR_PROPERTY ].add = function( a, b ) { var c = a.clone(); @@ -10318,11 +10342,15 @@ function FromToByActivityTemplate( BaseType ) // template parameter this.aBy = aByValue; this.aStartValue = null; this.aEndValue = null; + this.aPreviousValue = null; + this.aStartInterpolationValue = null; this.aAnimation = aAnimation; this.aInterpolator = aInterpolator; + this.equal = aOperatorSet.equal; this.add = aOperatorSet.add; this.scale = aOperatorSet.scale; this.bDynamicStartValue = false; + this.nIteration = 0; this.bCumulative = bAccumulate; this.initAnimatedElement(); @@ -10378,6 +10406,9 @@ function FromToByActivityTemplate( BaseType ) // template parameter } else { + this.aStartValue = aAnimationStartValue; + this.aStartInterpolationValue = this.aStartValue; + // By or To animation. According to SMIL spec, // the To value takes precedence over the By // value, if both are specified @@ -10390,6 +10421,7 @@ function FromToByActivityTemplate( BaseType ) // template parameter // the to animation interpolates between // the _running_ underlying value and the to value (as the end value) this.bDynamicStartValue = true; + this.aPreviousValue = this.aStartValue; this.aEndValue = this.aTo; } else if( this.aBy ) @@ -10420,18 +10452,61 @@ function FromToByActivityTemplate( BaseType ) // template parameter return; } - var aValue = this.bDynamicStartValue ? this.aAnimation.getUnderlyingValue() - : this.aStartValue; - aValue = this.aInterpolator( aValue, this.aEndValue, nModifiedTime ); + // According to SMIL 3.0 spec 'to' animation if no other (lower priority) + // animations are active or frozen then a simple interpolation is performed. + // That is, the start interpolation value is constant while the animation + // is running, and is equal to the underlying value retrieved when + // the animation start. + // However if another animation is manipulating the underlying value, + // the 'to' animation will initially add to the effect of the lower priority + // animation, and increasingly dominate it as it nears the end of the + // simple duration, eventually overriding it completely. + // That is, each time the underlying value is changed between two + // computations of the animation function the new underlying value is used + // as start value for the interpolation. + // See: + // http://www.w3.org/TR/SMIL3/smil-animation.html#animationNS-ToAnimation + // (Figure 6 - Effect of Additive to animation example) + // Moreover when a 'to' animation is repeated, at each new iteration + // the start interpolation value is reset to the underlying value + // of the animated property when the animation started, + // as it is shown in the example provided by the SMIL 3.0 spec. + // This is exactly as Firefox performs SVG 'to' animations. + if( this.bDynamicStartValue ) + { + if( this.nIteration != nRepeatCount ) + { + this.nIteration = nRepeatCount; + this.aStartInterpolationValue = this.aStartValue; + } + else + { + var aActualValue = this.aAnimation.getUnderlyingValue(); + if( !this.equal( aActualValue, this.aPreviousValue ) ) + this.aStartInterpolationValue = aActualValue; + } + } - if( this.bCumulative ) + var aValue = this.aInterpolator( this.aStartInterpolationValue, + this.aEndValue, nModifiedTime ); + + // According to the SMIL spec: + // Because 'to' animation is defined in terms of absolute values of + // the target attribute, cumulative animation is not defined. + if( this.bCumulative && !this.bDynamicStartValue ) { // aValue = this.aEndValue * nRepeatCount + aValue; aValue = this.add( this.scale( nRepeatCount, this.aEndValue ), aValue ); } this.aAnimation.perform( aValue ); + + if( this.bDynamicStartValue ) + { + this.aPreviousValue = this.aAnimation.getUnderlyingValue(); + } + }; FromToByActivity.prototype.performEnd = function() _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits