diff options
4 files changed, 155 insertions, 41 deletions
diff --git a/filter/source/svg/presentation_engine.js b/filter/source/svg/presentation_engine.js index 0c566c843a83..13a0a3b351ef 100644 --- a/filter/source/svg/presentation_engine.js +++ b/filter/source/svg/presentation_engine.js @@ -1439,7 +1439,7 @@ var aRegisterEventDebugPrinter = new DebugPrinter(); aRegisterEventDebugPrinter.off(); var aTimerEventQueueDebugPrinter = new DebugPrinter(); -aTimerEventQueueDebugPrinter.off(); +aTimerEventQueueDebugPrinter.on(); var aEventMultiplexerDebugPrinter = new DebugPrinter(); aEventMultiplexerDebugPrinter.off(); @@ -4522,7 +4522,7 @@ function createStateTransitionTable() aTable[FROZEN_NODE] = INVALID_NODE; // this state is unreachable here aTable[ENDED_NODE] = ENDED_NODE; // this state is a sink here (cannot restart) -// transition table for restart=NEVER, fill=FREEZE + // transition table for restart=NEVER, fill=FREEZE aTable = aSTT[RESTART_MODE_NEVER][FILL_MODE_FREEZE] = aSTT[RESTART_MODE_NEVER][FILL_MODE_HOLD] = @@ -5352,8 +5352,8 @@ BaseNode.prototype.resolve = function() BaseNode.prototype.activate = function() { -// log( 'restart mode: ' + aRestartModeOutMap[ this.getRestartMode() ] ); -// log( 'fill mode: ' + aFillModeOutMap[ this.getFillMode() ] ); + log( 'restart mode: ' + aRestartModeOutMap[ this.getRestartMode() ] ); + log( 'fill mode: ' + aFillModeOutMap[ this.getFillMode() ] ); if( ! this.checkValidNode() ) return false; @@ -5687,6 +5687,7 @@ function AnimationBaseNode( aAnimElem, aParentNode, aNodeContext ) this.bIsContainer = false; this.aTargetElement = null; this.aAnimatedElement = null; + this.nAnimatedElementOriginalState = 0; this.aActivity = null; this.nMinFrameCount = undefined; @@ -5734,7 +5735,7 @@ AnimationBaseNode.prototype.parseElement = function() if( this.aTargetElement ) { // set up target element initial visibility - if( true && aAnimElem.getAttribute( 'attributeName' ) === 'visibility' ) + if( aAnimElem.getAttribute( 'attributeName' ) === 'visibility' ) { if( aAnimElem.getAttribute( 'to' ) === 'visible' ) this.aTargetElement.setAttribute( 'visibility', 'hidden' ); @@ -5774,6 +5775,7 @@ AnimationBaseNode.prototype.activate_st = function() { if( this.aActivity ) { + this.nAnimatedElementOriginalState = this.getAnimatedElement().getCurrentState(); this.aActivity.setTargets( this.getAnimatedElement() ); this.getContext().aActivityQueue.addActivity( this.aActivity ); } @@ -5842,6 +5844,16 @@ AnimationBaseNode.prototype.hasPendingAnimation = function() return true; }; +AnimationBaseNode.prototype.saveStateOfAnimatedElement = function() +{ + this.getAnimatedElement().saveState(); +}; + +AnimationBaseNode.prototype.removeEffect = function() +{ + this.getAnimatedElement().setTo( this.nAnimatedElementOriginalState ); +}; + AnimationBaseNode.prototype.getTargetElement = function() { return this.aTargetElement; @@ -6096,6 +6108,7 @@ function BaseContainerNode( aAnimElem, aParentNode, aNodeContext ) this.aChildrenArray = new Array(); this.nFinishedChildren = 0; this.bDurationIndefinite = false; + this.nLeftIterations = 1; this.eImpressNodeType = undefined; this.ePresetClass = undefined; @@ -6157,6 +6170,13 @@ BaseContainerNode.prototype.appendChildNode = function( aAnimationNode ) BaseContainerNode.prototype.init_st = function() { + this.nLeftIterations = this.getRepeatCount(); + + return this.init_children(); +}; + +BaseContainerNode.prototype.init_children = function() +{ this.nFinishedChildren = 0; var nChildrenCount = this.aChildrenArray.length; var nInitChildren = 0; @@ -6170,6 +6190,7 @@ BaseContainerNode.prototype.init_st = function() return ( nChildrenCount == nInitChildren ); }; + BaseContainerNode.prototype.deactivate_st = function( eDestState ) { if( eDestState == FROZEN_NODE ) @@ -6245,12 +6266,49 @@ BaseContainerNode.prototype.notifyDeactivatedChild = function( aChildNode ) if( bFinished && this.isDurationIndefinite() ) { - this.deactivate(); + if( this.nLeftIterations >= 1.0 ) + { + this.nLeftIterations -= 1.0; + } + if( this.nLeftIterations >= 1.0 ) + { + bFinished = false; + var aRepetitionEvent = makeDelay( bind( this, this.repeat ), 0.0 ); + this.aContext.aTimerEventQueue.addEvent( aRepetitionEvent ); + } + else + { + this.deactivate(); + } } return bFinished; }; +BaseContainerNode.prototype.repeat = function() +{ + this.deactivate_st( ENDED_NODE ); + this.removeEffect(); + var bInitialized = this.init_children(); + if( bInitialized ) + this.activate_st(); + return bInitialized; +}; + +BaseContainerNode.prototype.removeEffect = function() +{ + this.forEachChildNode( mem_fn( 'removeEffect' ), FROZEN_NODE | ENDED_NODE ); +}; + +BaseContainerNode.prototype.saveStateOfAnimatedElement = function() +{ + var nChildrenCount = this.aChildrenArray.length; + for( var i = 0; i < nChildrenCount; ++i ) + { + this.aChildrenArray[i].saveStateOfAnimatedElement(); + } +} + BaseContainerNode.prototype.forEachChildNode = function( aFunction, eNodeStateMask ) { if( !eNodeStateMask ) @@ -6420,6 +6478,11 @@ SequentialTimeContainer.prototype.resolveChild = function( aChildNode ) if( bResolved && this.isMainSequenceRootNode() ) { + aChildNode.saveStateOfAnimatedElement(); + } + + if( bResolved && this.isMainSequenceRootNode() ) + { // skip/rewind events handling } return bResolved; @@ -8307,7 +8370,7 @@ function AnimatedElement( aElement ) this.aPreviousElement = null; this.aElementArray = new Array(); - this.nCurrentState = 0; + this.nCurrentState = -1; this.eAdditiveMode = ADDITIVE_MODE_REPLACE; this.bIsUpdated = true; @@ -8316,7 +8379,7 @@ function AnimatedElement( aElement ) this.aICTM = document.documentElement.createSVGMatrix(); this.setCTM(); - this.aElementArray[0] = this.aActiveElement.cloneNode( true ); + //this.aElementArray[0] = this.aActiveElement.cloneNode( true ); } AnimatedElement.prototype.initElement = function() @@ -8382,6 +8445,11 @@ AnimatedElement.prototype.getId = function() return this.aActiveElement.getAttribute( 'id' ); }; +AnimatedElement.prototype.getCurrentState = function() +{ + return this.nCurrentState; +}; + AnimatedElement.prototype.isUpdated = function() { return this.bIsUpdated; @@ -8432,26 +8500,35 @@ AnimatedElement.prototype.notifyAnimationEnd = function() AnimatedElement.prototype.notifyNextEffectStart = function( nEffectIndex ) { - assert( this.nCurrentState === nEffectIndex, - 'AnimatedElement(' + this.getId() + ').notifyNextEffectStart: assertion (current state == effect index) failed' ); +// assert( this.nCurrentState === nEffectIndex, +// 'AnimatedElement(' + this.getId() + ').notifyNextEffectStart: assertion (current state == effect index) failed' ); +// +// if( this.isUpdated() ) +// { +// if( !this.aElementArray[ nEffectIndex ] ) +// { +// this.aElementArray[ nEffectIndex ] = this.aElementArray[ this.nCurrentState ]; +// this.DBG( '.notifyNextEffectStart(' + nEffectIndex + '): new state set to previous one ' ); +// } +// } +// else +// { +// if( !this.aElementArray[ nEffectIndex ] ) +// { +// this.aElementArray[ nEffectIndex ] = this.aActiveElement.cloneNode( true ); +// this.DBG( '.notifyNextEffectStart(' + nEffectIndex + '): cloned active state ' ); +// } +// } +// ++this.nCurrentState; +}; - if( this.isUpdated() ) +AnimatedElement.prototype.saveState = function() +{ + ++this.nCurrentState; + if( !this.aElementArray[ this.nCurrentState ] ) { - if( !this.aElementArray[ nEffectIndex ] ) - { - this.aElementArray[ nEffectIndex ] = this.aElementArray[ this.nCurrentState ]; - this.DBG( '.notifyNextEffectStart(' + nEffectIndex + '): new state set to previous one ' ); - } + this.aElementArray[ this.nCurrentState ] = this.aActiveElement.cloneNode( true ); } - else - { - if( !this.aElementArray[ nEffectIndex ] ) - { - this.aElementArray[ nEffectIndex ] = this.aActiveElement.cloneNode( true ); - this.DBG( '.notifyNextEffectStart(' + nEffectIndex + '): cloned active state ' ); - } - } - ++this.nCurrentState; }; AnimatedElement.prototype.setToFirst = function() @@ -8464,12 +8541,19 @@ AnimatedElement.prototype.setToLast = function() this.setTo( this.aElementArray.length - 1 ); }; -AnimatedElement.prototype.setTo = function( nEffectIndex ) +AnimatedElement.prototype.setTo = function( nNewState ) { - var bRet = this.setToElement( this.aElementArray[ nEffectIndex ] ); + if( !this.aElementArray[ nNewState ] ) + { + log( 'AnimatedElement(' + this.getId() + ').setTo: state ' + + nNewState + ' is not valid' ); + return false; + } + + var bRet = this.setToElement( this.aElementArray[ nNewState ] ); if( bRet ) { - this.nCurrentState = nEffectIndex; + this.nCurrentState = nNewState; var aBBox = this.getBBox(); var aBaseBBox = this.getBaseBBox(); @@ -10613,7 +10697,7 @@ function FromToByActivityTemplate( BaseType ) // template parameter { if( this.aAnimation ) { - if( this.isAutoreverse() ) + if( this.isAutoReverse() ) this.aAnimation.perform( this.aStartValue ); else this.aAnimation.perform( this.aEndValue ); diff --git a/slideshow/source/engine/animationnodes/animationbasenode.cxx b/slideshow/source/engine/animationnodes/animationbasenode.cxx index ed6349522f22..719276dbca4b 100644 --- a/slideshow/source/engine/animationnodes/animationbasenode.cxx +++ b/slideshow/source/engine/animationnodes/animationbasenode.cxx @@ -422,16 +422,6 @@ AnimationBaseNode::fillCommonParameters() const else aRepeats.reset( nRepeats / nDuration ); } - // 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? diff --git a/slideshow/source/engine/animationnodes/basecontainernode.cxx b/slideshow/source/engine/animationnodes/basecontainernode.cxx index e9a53ac12bca..3ac076a19a18 100644 --- a/slideshow/source/engine/animationnodes/basecontainernode.cxx +++ b/slideshow/source/engine/animationnodes/basecontainernode.cxx @@ -32,10 +32,12 @@ #include <canvas/verbosetrace.hxx> #include "basecontainernode.hxx" +#include "eventqueue.hxx" #include "tools.hxx" #include "nodetools.hxx" #include "delayevent.hxx" +#include <boost/bind.hpp> #include <boost/mem_fn.hpp> #include <algorithm> @@ -65,7 +67,15 @@ void BaseContainerNode::dispose() bool BaseContainerNode::init_st() { + if( !(getXAnimationNode()->getRepeatCount() >>= mnLeftIterations) ) + mnLeftIterations = 1.0; + return init_children(); +} + +bool BaseContainerNode::init_children() +{ mnFinishedChildren = 0; + // initialize all children return (std::count_if( maChildren.begin(), maChildren.end(), @@ -75,6 +85,7 @@ bool BaseContainerNode::init_st() void BaseContainerNode::deactivate_st( NodeState eDestState ) { + mnLeftIterations = 0.0; if (eDestState == FROZEN) { // deactivate all children that are not FROZEN or ENDED: forEachChildNode( boost::mem_fn(&AnimationNode::deactivate), @@ -137,19 +148,44 @@ bool BaseContainerNode::notifyDeactivatedChild( std::size_t const nSize = maChildren.size(); OSL_ASSERT( mnFinishedChildren < nSize ); ++mnFinishedChildren; - bool const bFinished = (mnFinishedChildren >= nSize); + bool bFinished = (mnFinishedChildren >= nSize); // all children finished, and we've got indefinite duration? // think of ParallelTimeContainer::notifyDeactivating() // if duration given, we will be deactivated by some end event // @see fillCommonParameters() if (bFinished && isDurationIndefinite()) { - deactivate(); + if( mnLeftIterations >= 1.0 ) + { + mnLeftIterations -= 1.0; + } + if( mnLeftIterations >= 1.0 ) + { + bFinished = false; + EventSharedPtr aRepetitionEvent = + makeDelay( boost::bind( &BaseContainerNode::repeat, this ), + 0.0, + "BaseContainerNode::repeat"); + getContext().mrEventQueue.addEvent( aRepetitionEvent ); + } + else + { + deactivate(); + } } return bFinished; } +bool BaseContainerNode::repeat() +{ + deactivate_st( ENDED ); + sal_Bool bState = init_children(); + if( bState ) + activate_st(); + return bState; +} + #if OSL_DEBUG_LEVEL >= 2 && defined(DBG_UTIL) void BaseContainerNode::showState() const { diff --git a/slideshow/source/engine/animationnodes/basecontainernode.hxx b/slideshow/source/engine/animationnodes/basecontainernode.hxx index f4a0d78ac79a..4a9c6cd9057d 100644 --- a/slideshow/source/engine/animationnodes/basecontainernode.hxx +++ b/slideshow/source/engine/animationnodes/basecontainernode.hxx @@ -51,6 +51,7 @@ protected: private: virtual bool init_st(); + virtual bool init_children(); virtual void deactivate_st( NodeState eDestState ); virtual bool hasPendingAnimation() const; // force to be implemented by derived class: @@ -66,6 +67,8 @@ protected: /// @return true: if all children have been deactivated bool notifyDeactivatedChild( AnimationNodeSharedPtr const& pChildNode ); + bool repeat(); + template <typename FuncT> inline void forEachChildNode( FuncT const& func, int nodeStateMask = -1 ) const @@ -83,6 +86,7 @@ protected: typedef ::std::vector<AnimationNodeSharedPtr> VectorOfNodes; VectorOfNodes maChildren; ::std::size_t mnFinishedChildren; + double mnLeftIterations; private: const bool mbDurationIndefinite; |