diff options
author | Marco Cecchetti <marco.cecchetti@collabora.com> | 2022-05-23 12:22:19 +0200 |
---|---|---|
committer | Andras Timar <andras.timar@collabora.com> | 2022-05-25 11:44:48 +0200 |
commit | a6ed16394c4a95cf204f38c30cb025bc99f00027 (patch) | |
tree | 36e622d56941507bfd7e8523a2004ea114cf5138 /filter | |
parent | 84f0085d9b6f5628913cc7deb90c2d6b694c8447 (diff) |
svg filter: transform animations: support for scale and translate
Now the emphasis grow and shrink animation is supported.
Now the animation engine is able to handle array of values instead of
single value param when computing the next animation state.
Change-Id: Ic200103c6c26a63de8eecc37dcd36ba1a2f0d391
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/134870
Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com>
Reviewed-by: Andras Timar <andras.timar@collabora.com>
Diffstat (limited to 'filter')
-rw-r--r-- | filter/source/svg/presentation_engine.js | 231 |
1 files changed, 226 insertions, 5 deletions
diff --git a/filter/source/svg/presentation_engine.js b/filter/source/svg/presentation_engine.js index c98e93de7b7a..6473963f8e76 100644 --- a/filter/source/svg/presentation_engine.js +++ b/filter/source/svg/presentation_engine.js @@ -7033,6 +7033,8 @@ function matrixToString( aSVGMatrix ) // eslint-disable-next-line no-unused-vars function numberParser( sValue ) { + if( typeof sValue !== 'string' ) + return undefined; if( sValue === '.' ) return undefined; var reFloatNumber = /^[+-]?[0-9]*[.]?[0-9]*$/; @@ -7045,6 +7047,9 @@ function numberParser( sValue ) function booleanParser( sValue ) { + if( typeof sValue !== 'string' ) + return undefined; + sValue = sValue.toLowerCase(); if( sValue === 'true' ) return true; @@ -7056,6 +7061,9 @@ function booleanParser( sValue ) function colorParser( sValue ) { + if( typeof sValue !== 'string' ) + return undefined; + // The following 3 color functions are used in evaluating sValue string // so don't remove them. @@ -7989,6 +7997,7 @@ var ENUM_PROPERTY = 2; var COLOR_PROPERTY = 3; var STRING_PROPERTY = 4; var BOOL_PROPERTY = 5; +var TUPLE_NUMBER_PROPERTY = 6; var aValueTypeOutMap = [ 'unknown', 'number', 'enum', 'color', 'string', 'boolean' ]; @@ -8006,6 +8015,14 @@ var aAttributeMap = 'get': 'getOpacity', 'set': 'setOpacity' }, + 'scale': { 'type': TUPLE_NUMBER_PROPERTY, + 'get': 'getSize', + 'set': 'setSize' }, + + 'translate': { 'type': TUPLE_NUMBER_PROPERTY, + 'get': 'getPos', + 'set': 'setPos' }, + 'rotate': { 'type': NUMBER_PROPERTY, 'get': 'getRotationAngle', 'set': 'setRotationAngle' }, @@ -11615,10 +11632,21 @@ AnimationTransformNode.prototype.createActivity = function() var aActivityParamSet = this.fillActivityParams(); var aAnimation; - aAnimation = createPropertyAnimation( this.getAttributeName(), - this.getAnimatedElement(), - this.aNodeContext.aSlideWidth, - this.aNodeContext.aSlideHeight ); + if( this.getAttributeName() === 'scale' || this.getAttributeName() === 'translate' ) + { + aAnimation = createPairPropertyAnimation( this.getAttributeName(), + this.getAnimatedElement(), + this.aNodeContext.aSlideWidth, + this.aNodeContext.aSlideHeight ); + + } + else + { + aAnimation = createPropertyAnimation( this.getAttributeName(), + this.getAnimatedElement(), + this.aNodeContext.aSlideWidth, + this.aNodeContext.aSlideHeight ); + } var aInterpolator = null; // createActivity will compute it; return createActivity( aActivityParamSet, this, aAnimation, aInterpolator ); @@ -12049,6 +12077,41 @@ function createPropertyAnimation( sAttrName, aAnimatedElement, nWidth, nHeight ) +function createPairPropertyAnimation( sTransformType, aAnimatedElement, nWidth, nHeight ) +{ + var aFunctorSet = aAttributeMap[ sTransformType ]; + var sGetValueMethod = aFunctorSet.get; + var sSetValueMethod = aFunctorSet.set; + + var aDefaultValue = []; + var aSizeReference = []; + if( sTransformType === 'scale' ) + { + aDefaultValue[0] = aSizeReference[0] = aAnimatedElement.getBaseBBox().width; + aDefaultValue[1] = aSizeReference[1] = aAnimatedElement.getBaseBBox().height; + } + else if( sTransformType === 'translate' ) + { + aDefaultValue[0] = aAnimatedElement.getBaseCenterX(); + aDefaultValue[1] = aAnimatedElement.getBaseCenterY(); + aSizeReference[0] = nWidth; + aSizeReference[1] = nHeight; + } + else + { + log( 'createPairPropertyAnimation: transform type is not handled' ); + return null; + } + + return new TupleAnimation( bind( aAnimatedElement, aAnimatedElement[ sGetValueMethod ] ), + bind( aAnimatedElement, aAnimatedElement[ sSetValueMethod ] ), + aDefaultValue, + aSizeReference ); +} + + + + /** createShapeTransition * * @param aActivityParamSet @@ -12248,6 +12311,45 @@ GenericAnimation.prototype.getUnderlyingValue = function() +function TupleAnimation( aGetValueFunc, aSetValueFunc, aDefaultValue, aReferenceSize ) +{ + TupleAnimation.superclass.constructor.call( this, aGetValueFunc, aSetValueFunc ); + assert( aDefaultValue && aReferenceSize, + 'TupleAnimation constructor: default value functor and/or reference size are not valid' ); + + this.aDefaultValue = aDefaultValue; + this.aReferenceSize = aReferenceSize; +} +extend( TupleAnimation, GenericAnimation ); + +TupleAnimation.prototype.perform = function( aNormValue ) +{ + assert(aNormValue.length === this.aReferenceSize.length); + + var aValue = []; + for( var i = 0; i < aNormValue.length; ++i ) + { + aValue.push( aNormValue[i] * this.aReferenceSize[i] ); + } + + this.aSetValueFunc( aValue ); +}; + +TupleAnimation.prototype.getUnderlyingValue = function() +{ + var aValue = this.aGetValueFunc(); + assert(aValue.length === this.aReferenceSize.length); + + var aNormValue = []; + for( var i = 0; i < aValue.length; ++i ) + { + aNormValue.push( aValue[i] / this.aReferenceSize[i] ); + } + + return aNormValue; +}; + + function HSLAnimationWrapper( aColorAnimation ) { @@ -14565,6 +14667,11 @@ AnimatedElement.prototype.getY = function() return this.nCenterY; }; +AnimatedElement.prototype.getPos = function() +{ + return [this.getX(), this.getY()]; +}; + AnimatedElement.prototype.getWidth = function() { return this.nScaleFactorX * this.getBaseBBox().width; @@ -14575,6 +14682,11 @@ AnimatedElement.prototype.getHeight = function() return this.nScaleFactorY * this.getBaseBBox().height; }; +AnimatedElement.prototype.getSize = function() +{ + return [this.getWidth(), this.getHeight()]; +}; + AnimatedElement.prototype.updateTransformAttribute = function() { this.aTransformAttrList = this.aActiveElement.transform.baseVal; @@ -14604,12 +14716,27 @@ AnimatedElement.prototype.setY = function( nNewCenterY ) this.nCenterY = nNewCenterY; }; +AnimatedElement.prototype.setPos = function( aNewPos ) +{ + var nNewCenterX = aNewPos[0]; + var nNewCenterY = aNewPos[1]; + + if( nNewCenterX === this.nCenterX && nNewCenterY === this.nCenterY ) return; + + this.aTransformAttrList = this.aActiveElement.transform.baseVal; + this.aTransformAttr = this.aTransformAttrList.getItem( 0 ); + this.aTMatrix = this.aTransformAttr.matrix.translate( nNewCenterX - this.nCenterX, nNewCenterY - this.nCenterY ); + this.aTransformAttr.setMatrix( this.aTMatrix ); + this.nCenterX = nNewCenterX; + this.nCenterY = nNewCenterY; +}; + AnimatedElement.prototype.setWidth = function( nNewWidth ) { ANIMDBG.print( 'AnimatedElement.setWidth: nNewWidth = ' + nNewWidth ); if( nNewWidth < 0 ) { - log('AnimatedElement(' + this.getId() + ').setWidth: negative height!'); + log('AnimatedElement(' + this.getId() + ').setWidth: negative width!'); nNewWidth = 0; } @@ -14654,6 +14781,43 @@ AnimatedElement.prototype.setHeight = function( nNewHeight ) this.nScaleFactorY = nScaleFactorY; }; +AnimatedElement.prototype.setSize= function( aNewSize ) +{ + var nNewWidth = aNewSize[0]; + var nNewHeight = aNewSize[1]; + ANIMDBG.print( 'AnimatedElement.setSize: = [' + nNewWidth + ',' + nNewHeight + ']'); + if( nNewWidth < 0 ) + { + log('AnimatedElement(' + this.getId() + ').setSize: negative width!'); + nNewWidth = 0; + } + if( nNewHeight < 0 ) + { + log('AnimatedElement(' + this.getId() + ').setSize: negative height!'); + nNewHeight = 0; + } + + var nBaseWidth = this.getBaseBBox().width; + var nScaleFactorX = nNewWidth / nBaseWidth; + if( nScaleFactorX < 1e-5 ) nScaleFactorX = 1e-5; + + var nBaseHeight = this.getBaseBBox().height; + var nScaleFactorY = nNewHeight / nBaseHeight; + if( nScaleFactorY < 1e-5 ) nScaleFactorY = 1e-5; + + if( nScaleFactorX == this.nScaleFactorX && nScaleFactorY == this.nScaleFactorY ) return; + + this.aTMatrix = document.documentElement.createSVGMatrix() + .translate( this.nCenterX, this.nCenterY ) + .rotate(this.nRotationAngle) + .scaleNonUniform( nScaleFactorX, nScaleFactorY ) + .translate( -this.nBaseCenterX, -this.nBaseCenterY ); + this.updateTransformAttribute(); + + this.nScaleFactorX = nScaleFactorX; + this.nScaleFactorY = nScaleFactorY; +}; + AnimatedElement.prototype.getOpacity = function() { return this.aActiveElement.getAttribute( 'opacity' ); @@ -16387,6 +16551,17 @@ aInterpolatorHandler.aLerpFunctorMap[ CALC_MODE_LINEAR ][ COLOR_PROPERTY ][ COLO }; }; +aInterpolatorHandler.aLerpFunctorMap[ CALC_MODE_LINEAR ][ TUPLE_NUMBER_PROPERTY ] = + function ( aFrom, aTo, nT ) + { + var aRes = []; + for( var i = 0; i < aFrom.length; ++i ) + { + aRes.push( ( 1.0 - nT )* aFrom[i] + nT * aTo[i] ); + } + return aRes; + }; + @@ -16554,6 +16729,36 @@ aOperatorSetMap[ STRING_PROPERTY ] = aOperatorSetMap[ ENUM_PROPERTY ]; // bool operators aOperatorSetMap[ BOOL_PROPERTY ] = aOperatorSetMap[ ENUM_PROPERTY ]; +// tuple number operators +aOperatorSetMap[ TUPLE_NUMBER_PROPERTY ] = {}; + +aOperatorSetMap[ TUPLE_NUMBER_PROPERTY ].equal = function( a, b ) +{ + assert( a.length === b.length, 'Tuples length mismatch.' ); + return ( a.toString() === b.toString() ); +}; + +aOperatorSetMap[ TUPLE_NUMBER_PROPERTY ].add = function( a, b ) +{ + assert( a.length === b.length, 'Tuples length mismatch.' ); + var r = []; + for( var i = 0; i < a.length; ++i ) + { + r.push(a[i] + b[i]); + } + return r; +}; + +aOperatorSetMap[ TUPLE_NUMBER_PROPERTY ].scale = function( k, v ) +{ + var r = []; + for( var i = 0; i < v.length; ++i ) + { + r.push(k * v[i]); + } + return r; +}; + @@ -17963,6 +18168,22 @@ function extractAttributeValues( eValueType, aValueList, aValueSet, aBBox, nSlid aValueList.push( aValue ); } break; + case TUPLE_NUMBER_PROPERTY : + for( i = 0; i < aValueSet.length; ++i ) + { + if( typeof aValueSet[i] === 'string' ) + { + var aTuple = aValueSet[i].split(','); + aValue = []; + evalValuesAttribute(aValue, aTuple, aBBox, nSlideWidth, nSlideHeight); + aValueList.push(aValue); + } + else + { + aValueList.push( undefined ); + } + } + break; default: log( 'createValueListActivity: unexpected value type: ' + eValueType ); } |