filter/source/svg/presentation_engine.js | 649 ++++++++++++++++++++++++------- sd/source/core/CustomAnimationEffect.cxx | 13 sd/xml/effects.xml | 12 3 files changed, 524 insertions(+), 150 deletions(-)
New commits: commit 248f71c2486c8b651827f960b82b8294f9f79913 Author: Marco Cecchetti <[email protected]> Date: Mon Jul 9 00:59:05 2012 +0200 Added support for interactive animation sequence to the JavaScript engine. Now it is possible to start an effect by clicking on a given shape. diff --git a/filter/source/svg/presentation_engine.js b/filter/source/svg/presentation_engine.js index a5a3a3f..cccbcd0 100644 --- a/filter/source/svg/presentation_engine.js +++ b/filter/source/svg/presentation_engine.js @@ -222,7 +222,7 @@ function getDefaultCharCodeDictionary() } -function slideOnMouseDown( aEvt ) +function slideOnMouseUp( aEvt ) { if (!aEvt) aEvt = window.event; @@ -236,8 +236,12 @@ function slideOnMouseDown( aEvt ) if( 0 != nOffset ) dispatchEffects( nOffset ); + return true; // the click has been handled } +document.handleClick = slideOnMouseUp; + + /** Event handler for mouse wheel events in slide mode. * based on http://adomas.org/javascript-mouse-wheel/ * @@ -309,7 +313,7 @@ function mouseHandlerDispatch( aEvt, anAction ) } //Set mouse event handler. -document.onmousedown = function( aEvt ) { return mouseHandlerDispatch( aEvt, MOUSE_DOWN ); }; +document.onmouseup = function( aEvt ) { return mouseHandlerDispatch( aEvt, MOUSE_UP ); }; //document.onmousemove = function( aEvt ) { return mouseHandlerDispatch( aEvt, MOUSE_MOVE ); }; /** Function to supply the default mouse handler dictionary. @@ -324,13 +328,17 @@ function getDefaultMouseHandlerDictionary() mouseHandlerDict[INDEX_MODE] = new Object(); // slide mode - mouseHandlerDict[SLIDE_MODE][MOUSE_DOWN] - = function( aEvt ) { return slideOnMouseDown( aEvt ); }; + mouseHandlerDict[SLIDE_MODE][MOUSE_UP] + //= function( aEvt ) { return slideOnMouseDown( aEvt ); }; + = function( aEvt ) { return ( aSlideShow.aEventMultiplexer ) ? + aSlideShow.aEventMultiplexer.notifyMouseClick( aEvt ) + : slideOnMouseUp( aEvt ); }; + mouseHandlerDict[SLIDE_MODE][MOUSE_WHEEL] = function( aEvt ) { return slideOnMouseWheel( aEvt ); }; // index mode - mouseHandlerDict[INDEX_MODE][MOUSE_DOWN] + mouseHandlerDict[INDEX_MODE][MOUSE_UP] = function( aEvt ) { return toggleSlideIndex(); }; // mouseHandlerDict[INDEX_MODE][MOUSE_MOVE] // = function( aEvt ) { return theSlideIndexPage.updateSelection( aEvt ); }; @@ -1433,7 +1441,7 @@ var NAVDBG = new DebugPrinter(); NAVDBG.off(); var ANIMDBG = new DebugPrinter(); -ANIMDBG.on(); +ANIMDBG.off(); var aRegisterEventDebugPrinter = new DebugPrinter(); aRegisterEventDebugPrinter.off(); @@ -5047,11 +5055,11 @@ NodeContext.prototype.makeSourceEventElement = function( sId, aEventBaseElem ) return null; } - if( !this.aAnimationNodeMap[ sId ] ) + if( !this.aSourceEventElementMap[ sId ] ) { - this.aAnimationNodeMap[ sId ] = new SourceEventElement( aEventBaseElem, this.aContext.aEventMultiplexer ); + this.aSourceEventElementMap[ sId ] = new SourceEventElement( sId, aEventBaseElem, this.aContext.aEventMultiplexer ); } - return this.aAnimationNodeMap[ sId ]; + return this.aSourceEventElementMap[ sId ]; }; @@ -5323,7 +5331,7 @@ BaseNode.prototype.resolve = function() { this.aActivationEvent = makeDelay( bind( this, this.activate ), this.getBegin().getOffset() + this.nStartDelay ); } - registerEvent( this.getBegin(), this.aActivationEvent, this.aNodeContext ); + registerEvent( this.getId(), this.getBegin(), this.aActivationEvent, this.aNodeContext ); return true; } @@ -9378,6 +9386,7 @@ function SlideAnimations( aSlideShowContext ) this.aAnimatedElementMap = new Object(); this.aSourceEventElementMap = new Object(); this.aNextEffectEventArray = new NextEffectEventArray(); + this.aInteractiveAnimationSequenceMap = new Object(); this.aEventMultiplexer = new EventMultiplexer( aSlideShowContext.aTimerEventQueue ); this.aRootNode = null; this.bElementsParsed = false; @@ -9385,6 +9394,11 @@ function SlideAnimations( aSlideShowContext ) this.aContext.aAnimationNodeMap = this.aAnimationNodeMap; this.aContext.aAnimatedElementMap = this.aAnimatedElementMap; this.aContext.aSourceEventElementMap = this.aSourceEventElementMap; + + // We set up a low priority for the invocation of document.handleClick + // in order to make clicks on shapes, that start interactive animation + // sequence (on click), have an higher priority. + this.aEventMultiplexer.registerMouseClickHandler( document, 100 ); } @@ -9433,7 +9447,12 @@ SlideAnimations.prototype.start = function() if( !this.bElementsParsed ) return false; - aSlideShow.setSlideEvents( this.aNextEffectEventArray, this.aEventMultiplexer ); + this.chargeSourceEvents(); + this.chargeInterAnimEvents(); + + aSlideShow.setSlideEvents( this.aNextEffectEventArray, + this.aInteractiveAnimationSequenceMap, + this.aEventMultiplexer ); if( this.aContext.bFirstRun == undefined ) this.aContext.bFirstRun = true; @@ -9489,7 +9508,21 @@ SlideAnimations.prototype.clearNextEffectEvents = function() this.aContext.bFirstRun = undefined; }; +SlideAnimations.prototype.chargeSourceEvents = function() +{ + for( var id in this.aSourceEventElementMap ) + { + this.aSourceEventElementMap[id].charge(); + } +}; +SlideAnimations.prototype.chargeInterAnimEvents = function() +{ + for( var id in this.aInteractiveAnimationSequenceMap ) + { + this.aInteractiveAnimationSequenceMap[id].chargeEvents(); + } +}; /********************************************************************************************** * Event classes and helper functions @@ -9578,7 +9611,7 @@ function makeDelay( aFunctor, nTimeout ) // ------------------------------------------------------------------------------------------ // -function registerEvent( aTiming, aEvent, aNodeContext ) +function registerEvent( nNodeId, aTiming, aEvent, aNodeContext ) { var aSlideShowContext = aNodeContext.aContext; var eTimingType = aTiming.getType(); @@ -9603,6 +9636,14 @@ function registerEvent( aTiming, aEvent, aNodeContext ) log( 'registerEvent: next effect event array not initialized' ); return; } + var aInteractiveAnimationSequenceMap = + aSlideShowContext.aInteractiveAnimationSequenceMap; + if( !aInteractiveAnimationSequenceMap ) + { + log( 'registerEvent: interactive animation sequence map not initialized' ); + return; + } + switch( eTimingType ) { case EVENT_TIMING: @@ -9618,6 +9659,12 @@ function registerEvent( aTiming, aEvent, aNodeContext ) } var aSourceEventElement = aNodeContext.makeSourceEventElement( sEventBaseElemId, aEventBaseElem ); + if( !aInteractiveAnimationSequenceMap[ nNodeId ] ) + { + var aInteractiveAnimationSequence = new InteractiveAnimationSequence( nNodeId ); + aInteractiveAnimationSequenceMap[ nNodeId ] = aInteractiveAnimationSequence; + } + var bEventRegistered = false; switch( eEventType ) { @@ -9629,7 +9676,12 @@ function registerEvent( aTiming, aEvent, aNodeContext ) log( 'generateEvent: not handled event type: ' + eEventType ); } if( bEventRegistered ) - aSourceEventElement.addEventListener( eEventType ); + { + var aStartEvent = aInteractiveAnimationSequenceMap[ nNodeId ].getStartEvent(); + var aEndEvent = aInteractiveAnimationSequenceMap[ nNodeId ].getEndEvent(); + aEventMultiplexer.registerEvent( eEventType, aSourceEventElement.getId(), aStartEvent ); + aEventMultiplexer.registerEvent( EVENT_TRIGGER_END_EVENT, nNodeId, aEndEvent ); + } } else // no base event element present { @@ -9680,82 +9732,173 @@ registerEvent.DBG = function( aTiming, nTime ) // ------------------------------------------------------------------------------------------ // -function SourceEventElement( aElement, aEventMultiplexer ) +function SourceEventElement( sId, aElement, aEventMultiplexer ) { - this.nId = getUniqueId(); + this.sId = sId; this.aElement = aElement; this.aEventMultiplexer = aEventMultiplexer; - this.aEventListenerStateArray = new Array(); -} + this.aEventMultiplexer.registerMouseClickHandler( this, 1000 ); + + this.bClickHandled = false; + this.bIsPointerOver = false; + this.aElement.addEventListener( 'mouseover', bind2( SourceEventElement.prototype.onMouseEnter, this), false ); + this.aElement.addEventListener( 'mouseout', bind2( SourceEventElement.prototype.onMouseLeave, this), false ); +} SourceEventElement.prototype.getId = function() { - return this.nId; + return this.sId; }; -SourceEventElement.prototype.isEqualTo = function( aSourceEventElement ) +SourceEventElement.prototype.onMouseEnter = function() { - return ( this.getId() == aSourceEventElement.getId() ); + this.bIsPointerOver = true; }; -SourceEventElement.prototype.onClick = function() +SourceEventElement.prototype.onMouseLeave = function() { - this.aEventMultiplexer.notifyClickEvent( this ); + this.bIsPointerOver = false; }; -SourceEventElement.prototype.isEventListenerRegistered = function( eEventType ) +SourceEventElement.prototype.charge = function() { - return this.aEventListenerStateArray[ eEventType ]; + this.bClickHandled = false; }; -SourceEventElement.prototype.addEventListener = function( eEventType ) +SourceEventElement.prototype.handleClick = function( aMouseEvent ) { - if( !this.aElement ) - return false; + if( !this.bIsPointerOver ) return false; - this.aEventListenerStateArray[ eEventType ] = true; - switch( eEventType ) - { - case EVENT_TRIGGER_ON_CLICK: - this.aElement.addEventListener( 'click', this.onClick, false ); - break; - default: - log( 'SourceEventElement.addEventListener: not handled event type: ' + eEventType ); - return false; - } + if( this.bClickHandled ) + return true; + + this.aEventMultiplexer.notifyEvent( EVENT_TRIGGER_ON_CLICK, this.getId() ); + aSlideShow.update(); + this.bClickHandled = true; return true; }; -SourceEventElement.prototype.removeEventListener = function( eEventType ) + + +// ------------------------------------------------------------------------------------------ // +function InteractiveAnimationSequence( nId ) { - if( !this.aElement ) - return false; + this.nId = nId; + this.bIsRunning = false; + this.aStartEvent = null; + this.aEndEvent = null; +} - this.aEventListenerStateArray[ eEventType ] = false; - switch( eEventType ) +InteractiveAnimationSequence.prototype.getId = function() +{ + return this.nId; +}; + +InteractiveAnimationSequence.prototype.getStartEvent = function() +{ + if( !this.aStartEvent ) { - case EVENT_TRIGGER_ON_CLICK: - this.aElement.removeEventListener( 'click', this.onClick, false ); - break; - default: - log( 'SourceEventElement.removeEventListener: not handled event type: ' + eEventType ); - return false; + this.aStartEvent = + makeEvent( bind2( InteractiveAnimationSequence.prototype.start, this ) ); } - return true; + return this.aStartEvent; }; +InteractiveAnimationSequence.prototype.getEndEvent = function() +{ + if( !this.aEndEvent ) + { + this.aEndEvent = + makeEvent( bind2( InteractiveAnimationSequence.prototype.end, this ) ); + } + return this.aEndEvent; +}; + +InteractiveAnimationSequence.prototype.chargeEvents = function() +{ + if( this.aStartEvent ) this.aStartEvent.charge(); + if( this.aEndEvent ) this.aEndEvent.charge(); +}; + +InteractiveAnimationSequence.prototype.isRunning = function() +{ + return this.bIsRunning; +}; + +InteractiveAnimationSequence.prototype.start = function() +{ + aSlideShow.notifyInteractiveAnimationSequenceStart( this.getId() ); + this.bIsRunning = true; +}; + +InteractiveAnimationSequence.prototype.end = function() +{ + aSlideShow.notifyInteractiveAnimationSequenceEnd( this.getId() ); + this.bIsRunning = false; +}; + +// ------------------------------------------------------------------------------------------ // +/** class PriorityEntry + * It provides an entry type for priority queues. + * Higher is the value of nPriority higher is the priority of the created entry. + * + * @param aValue + * The object to be prioritized. + * @param nPriority + * An integral number representing the object priority. + * + */ +function PriorityEntry( aValue, nPriority ) +{ + this.aValue = aValue; + this.nPriority = nPriority; +} + +/** EventEntry.compare + * Compare priority of two entries. + * + * @param aLhsEntry + * An instance of type PriorityEntry. + * @param aRhsEntry + * An instance of type PriorityEntry. + * @return {Boolean} + * True if the first entry has higher priority of the second entry, + * false otherwise. + */ +PriorityEntry.compare = function( aLhsEntry, aRhsEntry ) +{ + return ( aLhsEntry.nPriority < aRhsEntry.nPriority ); +}; // ------------------------------------------------------------------------------------------ // function EventMultiplexer( aTimerEventQueue ) { this.aTimerEventQueue = aTimerEventQueue; this.aEventMap = new Object(); + this.aMouseClickHandlerSet = new PriorityQueue( PriorityEntry.compare ); this.aSkipEffectEvent = null; this.aRewindCurrentEffectEvent = null; this.aRewindLastEffectEvent = null; } +EventMultiplexer.prototype.registerMouseClickHandler = function( aHandler, nPriority ) +{ + var aHandlerEntry = new PriorityEntry( aHandler, nPriority ); + this.aMouseClickHandlerSet.push( aHandlerEntry ); +}; + +EventMultiplexer.prototype.notifyMouseClick = function( aMouseEvent ) +{ + var aMouseClickHandlerSet = this.aMouseClickHandlerSet; + var nSize = aMouseClickHandlerSet.size(); + for( var i = 0; i < nSize; ++i ) + { + var aHandlerEntry = aMouseClickHandlerSet.aSequence[i]; + if( aHandlerEntry.aValue.handleClick( aMouseEvent ) ) + break; + } +}; EventMultiplexer.prototype.registerEvent = function( eEventType, aNotifierId, aEvent ) { @@ -11284,12 +11427,17 @@ function SlideShow() this.aTimerEventQueue = new TimerEventQueue( this.aTimer ); this.aActivityQueue = new ActivityQueue( this.aTimer ); this.aNextEffectEventArray = null; + this.aInteractiveAnimationSequenceMap = null; this.aEventMultiplexer = null; - this.aContext = new SlideShowContext( this.aTimerEventQueue, this.aEventMultiplexer, - this.aNextEffectEventArray, this.aActivityQueue ); + this.aContext = new SlideShowContext( this.aTimerEventQueue, + this.aEventMultiplexer, + this.aNextEffectEventArray, + this.aInteractiveAnimationSequenceMap, + this.aActivityQueue ); this.nCurrentEffect = 0; this.eDirection = FORWARD; + this.nTotalInteracAnimSeqRunning = 0; this.bIsIdle = true; this.bIsEnabled = true; this.bIsRewinding = false; @@ -11299,19 +11447,27 @@ function SlideShow() } -SlideShow.prototype.setSlideEvents = function( aNextEffectEventArray, aEventMultiplexer ) +SlideShow.prototype.setSlideEvents = function( aNextEffectEventArray, + aInteractiveAnimationSequenceMap, + aEventMultiplexer ) { if( !aNextEffectEventArray ) log( 'SlideShow.setSlideEvents: aNextEffectEventArray is not valid' ); + if( !aInteractiveAnimationSequenceMap ) + log( 'SlideShow.setSlideEvents:aInteractiveAnimationSequenceMap is not valid' ); + if( !aEventMultiplexer ) log( 'SlideShow.setSlideEvents: aEventMultiplexer is not valid' ); this.aContext.aNextEffectEventArray = aNextEffectEventArray; this.aNextEffectEventArray = aNextEffectEventArray; + this.aContext.aInteractiveAnimationSequenceMap = aInteractiveAnimationSequenceMap; + this.aInteractiveAnimationSequenceMap = aInteractiveAnimationSequenceMap; this.aContext.aEventMultiplexer = aEventMultiplexer; this.aEventMultiplexer = aEventMultiplexer; this.nCurrentEffect = 0; + this.nTotalInteracAnimSeqRunning = 0; }; SlideShow.prototype.createSlideTransition = function( aSlideTransitionHandler, aLeavingSlide, aEnteringSlide, aTransitionEndEvent ) @@ -11361,6 +11517,11 @@ SlideShow.prototype.isRunning = function() return !this.bIsIdle; }; +SlideShow.prototype.isInterAnimSeqRunning = function() +{ + return ( this.nTotalInteracAnimSeqRunning > 0 ); +}; + SlideShow.prototype.isEnabled = function() { return this.bIsEnabled; @@ -11393,11 +11554,27 @@ SlideShow.prototype.notifyTransitionEnd = function( nSlideIndex ) } }; +SlideShow.prototype.notifyInteractiveAnimationSequenceStart = function( nNodeId ) +{ + ++this.nTotalInteracAnimSeqRunning; +}; + +SlideShow.prototype.notifyInteractiveAnimationSequenceEnd = function( nNodeId ) +{ + assert( this.nTotalInteracAnimSeqRunning > 0, + 'SlideShow.notifyInteractiveAnimationSequenceStart: ' + + 'the total number of running interactive application is zero' ); + --this.nTotalInteracAnimSeqRunning; +}; + SlideShow.prototype.nextEffect = function() { if( !this.isEnabled() ) return false; + if( this.isInterAnimSeqRunning() ) + return true; + if( this.isRunning() ) { this.skipCurrentEffect(); @@ -11443,6 +11620,9 @@ SlideShow.prototype.skipEffect = function() if( this.bIsSkipping || this.bIsRewinding ) return true; + if( this.isInterAnimSeqRunning() ) + return true; + if( this.isRunning() ) { this.skipCurrentEffect(); @@ -11478,6 +11658,9 @@ SlideShow.prototype.skipAllEffects = function() if( this.bIsSkippingAll ) return true; + if( this.isInterAnimSeqRunning() ) + return true; + this.bIsSkippingAll = true; if( this.isRunning() ) { @@ -11513,6 +11696,9 @@ SlideShow.prototype.rewindEffect = function() if( this.bIsSkipping || this.bIsRewinding ) return; + if( this.isInterAnimSeqRunning() ) + return true; + if( this.nCurrentEffect == 0 ) { this.rewindToPreviousSlide(); @@ -11717,11 +11903,12 @@ var aSlideShow = null; // ------------------------------------------------------------------------------------------ // -function SlideShowContext( aTimerEventQueue, aEventMultiplexer, aNextEffectEventArray, aActivityQueue) +function SlideShowContext( aTimerEventQueue, aEventMultiplexer, aNextEffectEventArray, aInteractiveAnimationSequenceMap, aActivityQueue) { this.aTimerEventQueue = aTimerEventQueue; this.aEventMultiplexer = aEventMultiplexer; this.aNextEffectEventArray = aNextEffectEventArray; + this.aInteractiveAnimationSequenceMap = aInteractiveAnimationSequenceMap; this.aActivityQueue = aActivityQueue; this.bIsSkipping = false; } commit 247be8bada5dfb1fe3acb7625a1b230d55b592d3 Author: Marco Cecchetti <[email protected]> Date: Thu Jul 5 19:17:26 2012 +0200 Bug fix: now the JavaScript engine parse the âcounter-clockwiseâ value correctly. Previously it expected âcounterclockwiseâ. diff --git a/filter/source/svg/presentation_engine.js b/filter/source/svg/presentation_engine.js index 984eaef..a5a3a3f 100644 --- a/filter/source/svg/presentation_engine.js +++ b/filter/source/svg/presentation_engine.js @@ -4117,9 +4117,9 @@ aColorSpaceOutMap = [ 'rgb', 'hsl' ]; var CLOCKWISE = 0; var COUNTERCLOCKWISE = 1; -aClockDirectionInMap = { 'clockwise': CLOCKWISE, 'counterclockwise': COUNTERCLOCKWISE }; +aClockDirectionInMap = { 'clockwise': CLOCKWISE, 'counter-clockwise': COUNTERCLOCKWISE }; -aClockDirectionOutMap = [ 'clockwise', 'counterclockwise' ]; +aClockDirectionOutMap = [ 'clockwise', 'counter-clockwise' ]; // Attribute Value Types commit 48265b1ce5b9003c754397415d30425df88e3581 Author: Marco Cecchetti <[email protected]> Date: Thu Jul 5 18:50:39 2012 +0200 Bug fix: now the darken and lighten effects work in the right way. Edited the effects.xml and changed effect direction to counterclockwise. diff --git a/sd/xml/effects.xml b/sd/xml/effects.xml index be341ef..b555a32 100644 --- a/sd/xml/effects.xml +++ b/sd/xml/effects.xml @@ -1172,9 +1172,9 @@ <anim:par smil:begin="indefinite" smil:fill="hold"> <anim:par smil:begin="0" smil:fill="hold"> <anim:par smil:begin="0" smil:fill="hold" pres:node-type="on-click" pres:preset-class="emphasis" pres:preset-id="ooo-emphasis-darken"> - <anim:animateColor smil:dur="0.5" smil:fill="hold" smil:attributeName="color" smil:by="hsl(0,-12%,-25%)" anim:color-interpolation="hsl" anim:color-interpolation-direction="clockwise"/> - <anim:animateColor smil:dur="0.5" smil:fill="hold" smil:attributeName="fill-color" smil:by="hsl(0,-12%,-25%)" anim:color-interpolation="hsl" anim:color-interpolation-direction="clockwise"/> - <anim:animateColor smil:dur="0.5" smil:fill="hold" smil:attributeName="stroke-color" smil:by="hsl(0,-12%,-25%)" anim:color-interpolation="hsl" anim:color-interpolation-direction="clockwise"/> + <anim:animateColor smil:dur="0.5" smil:fill="hold" smil:attributeName="color" smil:by="hsl(0,-12%,-25%)" anim:color-interpolation="hsl" anim:color-interpolation-direction="counterclockwise"/> + <anim:animateColor smil:dur="0.5" smil:fill="hold" smil:attributeName="fill-color" smil:by="hsl(0,-12%,-25%)" anim:color-interpolation="hsl" anim:color-interpolation-direction="counterclockwise"/> + <anim:animateColor smil:dur="0.5" smil:fill="hold" smil:attributeName="stroke-color" smil:by="hsl(0,-12%,-25%)" anim:color-interpolation="hsl" anim:color-interpolation-direction="counterclockwise"/> <anim:set smil:dur="0.5" smil:fill="hold" smil:attributeName="fill" smil:to="solid"/> </anim:par> </anim:par> @@ -1200,9 +1200,9 @@ <anim:par smil:begin="indefinite" smil:fill="hold"> <anim:par smil:begin="0" smil:fill="hold"> <anim:par smil:begin="0" smil:fill="hold" pres:node-type="on-click" pres:preset-class="emphasis" pres:preset-id="ooo-emphasis-lighten"> - <anim:animateColor smil:dur="0.5" smil:fill="hold" smil:attributeName="color" smil:by="hsl(0,12%,25%)" anim:color-interpolation="hsl" anim:color-interpolation-direction="clockwise"/> - <anim:animateColor smil:dur="0.5" smil:fill="hold" smil:attributeName="fill-color" smil:by="hsl(0,12%,25%)" anim:color-interpolation="hsl" anim:color-interpolation-direction="clockwise"/> - <anim:animateColor smil:dur="0.5" smil:fill="hold" smil:attributeName="stroke-color" smil:by="hsl(0,12%,25%)" anim:color-interpolation="hsl" anim:color-interpolation-direction="clockwise"/> + <anim:animateColor smil:dur="0.5" smil:fill="hold" smil:attributeName="color" smil:by="hsl(0,12%,25%)" anim:color-interpolation="hsl" anim:color-interpolation-direction="counterclockwise"/> + <anim:animateColor smil:dur="0.5" smil:fill="hold" smil:attributeName="fill-color" smil:by="hsl(0,12%,25%)" anim:color-interpolation="hsl" anim:color-interpolation-direction="counterclockwise"/> + <anim:animateColor smil:dur="0.5" smil:fill="hold" smil:attributeName="stroke-color" smil:by="hsl(0,12%,25%)" anim:color-interpolation="hsl" anim:color-interpolation-direction="counterclockwise"/> <anim:set smil:dur="0.5" smil:fill="hold" smil:attributeName="fill" smil:to="solid"/> </anim:par> </anim:par> commit 978e9607e63c227e2f7fe865af94485a7042531a Author: Marco Cecchetti <[email protected]> Date: Thu Jul 5 16:35:02 2012 +0200 Bug fix: now repeated animations and begin=âafter effect â works properly together. Modified the CustomAnimationEffect class in order to take into account the repeatCount attribute value when computing the node effect absolute duration. diff --git a/sd/source/core/CustomAnimationEffect.cxx b/sd/source/core/CustomAnimationEffect.cxx index 16756a5..625376f 100644 --- a/sd/source/core/CustomAnimationEffect.cxx +++ b/sd/source/core/CustomAnimationEffect.cxx @@ -281,6 +281,10 @@ void CustomAnimationEffect::setNode( const ::com::sun::star::uno::Reference< ::c } mfAbsoluteDuration = mfDuration; + double fRepeatCount = 1.0; + if( (mxNode->getRepeatCount()) >>= fRepeatCount ) + mfAbsoluteDuration *= fRepeatCount; + checkForText(); } @@ -755,7 +759,9 @@ void CustomAnimationEffect::setDuration( double fDuration ) { double fScale = fDuration / mfDuration; mfDuration = fDuration; - mfAbsoluteDuration = mfDuration; + double fRepeatCount = 1.0; + getRepeatCount() >>= fRepeatCount; + mfAbsoluteDuration = mfDuration * fRepeatCount; // calculate effect duration and get target shape Reference< XEnumerationAccess > xEnumerationAccess( mxNode, UNO_QUERY ); @@ -954,7 +960,12 @@ sal_Int16 CustomAnimationEffect::getFill() const void CustomAnimationEffect::setRepeatCount( const Any& rRepeatCount ) { if( mxNode.is() ) + { mxNode->setRepeatCount( rRepeatCount ); + double fRepeatCount = 1.0; + rRepeatCount >>= fRepeatCount; + mfAbsoluteDuration = mfDuration * fRepeatCount; + } } // -------------------------------------------------------------------- commit 2e91423ace0a4b0051b3b1beb9e1e461378437a4 Author: Marco Cecchetti <[email protected]> Date: Thu Jul 5 10:19:47 2012 +0200 Bug fix: now a clip-based transition works correctly when mode=âoutâ and reverse method involves flipping. diff --git a/filter/source/svg/presentation_engine.js b/filter/source/svg/presentation_engine.js index f042263..984eaef 100644 --- a/filter/source/svg/presentation_engine.js +++ b/filter/source/svg/presentation_engine.js @@ -7933,8 +7933,10 @@ ClippingFunctor.prototype.perform = function( nT, nWidth, nHeight ) { var aClipPoly = this.aParametricPolyPolygon.perform( this.bForwardParameterSweep ? nT : (1 - nT) ); - if( this.bFlip ) - aClipPoly.changeOrientation(); + // Note: even if the reverse method involves flipping we don't need to + // change the clip-poly orientation because we utilize the 'nonzero' + // clip-rule. + // See: http://www.w3.org/TR/SVG11/painting.html#FillRuleProperty if( this.bSubtractPolygon ) { commit ef43a2a37ce48ae3d41957034b94c6d0463d16df Author: Marco Cecchetti <[email protected]> Date: Wed Jul 4 18:50:46 2012 +0200 Provided support for rewinding to the previous slide and for skipping / rewinding all effects. The following method of the SlideShow class has been implemented: skipAllEffects, rewindToPreviousSlide, rewindAllEffects. Commented out the calls to the initAnimatedElement methods for ValueListActivity and FromToByActivity class as it is the source of a bug. diff --git a/filter/source/svg/presentation_engine.js b/filter/source/svg/presentation_engine.js index 2e66561..f042263 100644 --- a/filter/source/svg/presentation_engine.js +++ b/filter/source/svg/presentation_engine.js @@ -150,13 +150,13 @@ function getDefaultKeyCodeDictionary() keyCodeDict[SLIDE_MODE][RIGHT_KEY] = function() { return dispatchEffects(1); }; keyCodeDict[SLIDE_MODE][UP_KEY] - = function() { return skipEffects(-1); }; + = function() { return aSlideShow.rewindEffect(); }; keyCodeDict[SLIDE_MODE][DOWN_KEY] = function() { return skipEffects(1); }; keyCodeDict[SLIDE_MODE][PAGE_UP_KEY] - = function() { return switchSlide( -1, true ); }; + = function() { return aSlideShow.rewindAllEffects(); }; keyCodeDict[SLIDE_MODE][PAGE_DOWN_KEY] - = function() { return switchSlide( 1, true ); }; + = function() { return skipAllEffects(); }; keyCodeDict[SLIDE_MODE][HOME_KEY] = function() { return aSlideShow.displaySlide( 0, true ); }; keyCodeDict[SLIDE_MODE][END_KEY] @@ -1433,7 +1433,7 @@ var NAVDBG = new DebugPrinter(); NAVDBG.off(); var ANIMDBG = new DebugPrinter(); -ANIMDBG.off(); +ANIMDBG.on(); var aRegisterEventDebugPrinter = new DebugPrinter(); aRegisterEventDebugPrinter.off(); @@ -2985,6 +2985,15 @@ function dispatchEffects(dir) } } +function skipAllEffects() +{ + var bRet = aSlideShow.skipAllEffects(); + if( !bRet ) + { + switchSlide( 1, true ); + } +} + function skipEffects(dir) { if( dir == 1 ) @@ -2993,12 +3002,12 @@ function skipEffects(dir) if( !bRet ) { - switchSlide( 1, false ); + switchSlide( 1, true ); } } else { - switchSlide( dir, false ); + switchSlide( dir, true ); } } @@ -10725,7 +10734,7 @@ function FromToByActivityTemplate( BaseType ) // template parameter this.nIteration = 0; this.bCumulative = bAccumulate; - this.initAnimatedElement(); + //this.initAnimatedElement(); } extend( FromToByActivity, BaseType ); @@ -10931,7 +10940,7 @@ function ValueListActivityTemplate( BaseType ) // template parameter this.bCumulative = bAccumulate; this.aLastValue = this.aValueList[ this.aValueList.length - 1 ]; - this.initAnimatedElement(); + //this.initAnimatedElement(); } extend( ValueListActivity, BaseType ); @@ -10943,7 +10952,7 @@ function ValueListActivityTemplate( BaseType ) // template parameter ANIMDBG.print( 'createValueListActivity: value[' + i + '] = ' + this.aValueList[i] ); } - this.initAnimatedElement(); + //this.initAnimatedElement(); }; ValueListActivity.prototype.initAnimatedElement = function() @@ -11283,6 +11292,7 @@ function SlideShow() this.bIsEnabled = true; this.bIsRewinding = false; this.bIsSkipping = false; + this.bIsSkippingAll = false; this.bNoSlideTransition = false; } @@ -11422,30 +11432,6 @@ SlideShow.prototype.skipCurrentEffect = function() this.bIsSkipping = false; }; -/** rewindEffect - * Rewind the current playing effect or the last played one. - * - */ -SlideShow.prototype.rewindEffect = function() -{ - if( this.bIsSkipping || this.bIsRewinding ) - return true; - - this.bIsRewinding = true; - if( this.isRunning() ) - { - this.aEventMultiplexer.notifyRewindCurrentEffectEvent(); - } - else - { - this.aEventMultiplexer.notifyRewindLastEffectEvent(); - } - if( this.nCurrentEffect > 0 ) - --this.nCurrentEffect; - this.update(); - this.bIsRewinding = false; -}; - /** skipEffect * Skip the next effect to be played. * @@ -11478,6 +11464,105 @@ SlideShow.prototype.skipEffect = function() return true; }; +/** skipAllEffects + * Skip all left effects on the current slide. + * + * @return {Boolean} + * True if it already skipping or when it has ended skipping, + * false if the next slide needs to be displayed. + */ +SlideShow.prototype.skipAllEffects = function() +{ + if( this.bIsSkippingAll ) + return true; + + this.bIsSkippingAll = true; + if( this.isRunning() ) + { + this.skipCurrentEffect(); + } + else if( !this.aNextEffectEventArray + || ( this.nCurrentEffect >= this.aNextEffectEventArray.size() ) ) + { + this.bIsSkippingAll = false; + return false; + } + + // Pay attention here: a new next effect event is appended to + // aNextEffectEventArray only after the related animation node has been + // resolved, that is only after the animation node related to the previous + // effect has notified to be deactivated to the main sequence time container. + // So you should avoid any optimization here because the size of + // aNextEffectEventArray will going on increasing after every skip action. + while( this.nCurrentEffect < this.aNextEffectEventArray.size() ) + { + this.skipEffect(); + } + this.bIsSkippingAll = false; + return true; +}; + +/** rewindEffect + * Rewind the current playing effect or the last played one. + * + */ +SlideShow.prototype.rewindEffect = function() +{ + if( this.bIsSkipping || this.bIsRewinding ) + return; + + if( this.nCurrentEffect == 0 ) + { + this.rewindToPreviousSlide(); + return; + } + + this.bIsRewinding = true; + if( this.isRunning() ) + { + this.aEventMultiplexer.notifyRewindCurrentEffectEvent(); + } + else + { + this.aEventMultiplexer.notifyRewindLastEffectEvent(); + } + if( this.nCurrentEffect > 0 ) + --this.nCurrentEffect; + this.update(); + this.bIsRewinding = false; +}; + +/** rewindToPreviousSlide + * Displays the previous slide with all effects played. + * + */ +SlideShow.prototype.rewindToPreviousSlide = function() +{ + if( this.isRunning() ) + return; + var nNewSlide = nCurSlide - 1; + this.displaySlide( nNewSlide, true ); + this.skipAllEffects(); +}; + +/** rewindAllEffects + * Rewind all effects already played on the current slide. + * + */ +SlideShow.prototype.rewindAllEffects = function() +{ + if( this.nCurrentEffect == 0 ) + { + this.rewindToPreviousSlide(); + return; + } + + while( this.nCurrentEffect > 0 ) + { + this.rewindEffect(); + } +}; + SlideShow.prototype.displaySlide = function( nNewSlide, bSkipSlideTransition ) { var aMetaDoc = theMetaDoc; commit ecca9699d12a6a24265779668507e9f6d930694c Author: Marco Cecchetti <[email protected]> Date: Tue Jul 3 19:22:34 2012 +0200 Performed some clean up and added documentation comments. diff --git a/filter/source/svg/presentation_engine.js b/filter/source/svg/presentation_engine.js index 9b62dd7..2e66561 100644 --- a/filter/source/svg/presentation_engine.js +++ b/filter/source/svg/presentation_engine.js @@ -6281,6 +6281,7 @@ BaseContainerNode.prototype.removeEffect = function() var nChildrenCount = this.aChildrenArray.length; if( nChildrenCount == 0 ) return; + // We remove effect in reverse order. for( var i = nChildrenCount - 1; i >= 0; --i ) { if( ( this.aChildrenArray[i].getState() & ( FROZEN_NODE | ENDED_NODE ) ) == 0 ) @@ -6465,11 +6466,24 @@ SequentialTimeContainer.prototype.notifyDeactivating = function( aNotifier ) } }; +/** skipEffect + * Skip the current playing shape effect. + * Requires: the current node is the main sequence root node. + * + * @param aChildNode + * An animation node representing the root node of the shape effect being + * played. + */ SequentialTimeContainer.prototype.skipEffect = function( aChildNode ) { if( this.isChildNode( aChildNode ) ) { + // First off we end all queued activities. this.getContext().aActivityQueue.endAll(); + // We signal that we are going to skip all subsequent animations by + // setting the bIsSkipping flag to 'true', then all queued events are + // fired immediately. In such a way the correct order of the various + // events that belong to the animation time-line is preserved. this.getContext().bIsSkipping = true; this.getContext().aTimerEventQueue.forceEmpty(); this.getContext().bIsSkipping = false; @@ -6478,63 +6492,122 @@ SequentialTimeContainer.prototype.skipEffect = function( aChildNode ) } else { - log( 'SequentialTimeContainer.skipEffect: unknown child: ' + aChildNode.getId() ); + log( 'SequentialTimeContainer.skipEffect: unknown child: ' + + aChildNode.getId() ); } }; +/** rewindCurrentEffect + * Rewind a playing shape effect. + * Requires: the current node is the main sequence root node. + * + * @param aChildNode + * An animation node representing the root node of the shape effect being + * played + */ SequentialTimeContainer.prototype.rewindCurrentEffect = function( aChildNode ) { if( this.isChildNode( aChildNode ) ) { - assert( !this.bIsRewinding, 'SequentialTimeContainer.rewindCurrentEffect: is already rewinding.' ); + assert( !this.bIsRewinding, + 'SequentialTimeContainer.rewindCurrentEffect: is already rewinding.' ); + // We signal we are rewinding so the notifyDeactivating method returns + // immediately without increment the finished children counter and + // resolve the next child. this.bIsRewinding = true; + // First off we end all queued activities. this.getContext().aActivityQueue.endAll(); + // We signal that we are going to skip all subsequent animations by + // setting the bIsSkipping flag to 'true', then all queued events are + // fired immediately. In such a way the correct order of the various + // events that belong to the animation time-line is preserved. this.getContext().bIsSkipping = true; this.getContext().aTimerEventQueue.forceEmpty(); this.getContext().bIsSkipping = false; + // We end all new activities appended to the activity queue by + // the fired events. this.getContext().aActivityQueue.endAll(); + // Now we perform a final 'end' and restore the animated shape to + // the state it was before the current effect was applied. aChildNode.end(); aChildNode.removeEffect(); + // Finally we place the child node to the 'unresolved' state and + // resolve it again. aChildNode.init(); this.resolveChild( aChildNode ); this.bIsRewinding = false; } else { - log( 'SequentialTimeContainer.rewindCurrentEffect: unknown child: ' + aChildNode.getId() ); + log( 'SequentialTimeContainer.rewindCurrentEffect: unknown child: ' + + aChildNode.getId() ); } }; +/** rewindLastEffect + * Rewind the last ended effect. + * Requires: the current node is the main sequence root node. + * + * @param aChildNode + * An animation node representing the root node of the next shape effect + * to be played. + */ SequentialTimeContainer.prototype.rewindLastEffect = function( aChildNode ) { if( this.isChildNode( aChildNode ) ) { - assert( !this.bIsRewinding, 'SequentialTimeContainer.rewindLastEffect: is already rewinding.' ); + assert( !this.bIsRewinding, + 'SequentialTimeContainer.rewindLastEffect: is already rewinding.' ); + // We signal we are rewinding so the notifyDeactivating method returns + // immediately without increment the finished children counter and + // resolve the next child. this.bIsRewinding = true; + // We end the current effect and remove any change it applies on the + // animated shape. this.getContext().aTimerEventQueue.forceEmpty(); this.getContext().aActivityQueue.clear(); - aChildNode.end(); aChildNode.removeEffect(); + + // As we rewind the previous effect we need to decrease the finished + // children counter. --this.nFinishedChildren; var aPreviousChildNode = this.aChildrenArray[ this.nFinishedChildren ]; + // No need to invoke the end method for the previous child as it is + // already in the ENDED state. + aPreviousChildNode.removeEffect(); + // We place the child node to the 'unresolved' state. aPreviousChildNode.init(); - // We need to re-initialize it too, because it is in state ENDED now, - // and cannot be resolved again later. + // We need to re-initialize the old current child too, because it is + // in ENDED state now, On the contrary it cannot be resolved again later. aChildNode.init(); this.resolveChild( aPreviousChildNode ); this.bIsRewinding = false; } else { - log( 'SequentialTimeContainer.rewindLastEffect: unknown child: ' + aChildNode.getId() ); + log( 'SequentialTimeContainer.rewindLastEffect: unknown child: ' + + aChildNode.getId() ); } }; +/** resolveChild + * Resolve the passed child. + * In case this node is a main sequence root node events for skipping and + * rewinding the effect related to the passed child node are created and + * registered. + * + * @param aChildNode + * An animation node representing the root node of the next shape effect + * to be played. + * @return + * It returns true if the passed child has been resolved successfully, + * false otherwise. + */ SequentialTimeContainer.prototype.resolveChild = function( aChildNode ) { var bResolved = aChildNode.resolve(); @@ -6551,7 +6624,7 @@ SequentialTimeContainer.prototype.resolveChild = function( aChildNode ) this.aRewindCurrentEffectEvent.dispose(); this.aRewindCurrentEffectEvent = makeEvent( bind2( SequentialTimeContainer.prototype.rewindCurrentEffect, this, aChildNode ) ); - this.aContext.aEventMultiplexer.registerRewindEffectEvent( this.aRewindCurrentEffectEvent ); + this.aContext.aEventMultiplexer.registerRewindCurrentEffectEvent( this.aRewindCurrentEffectEvent ); if( this.aRewindLastEffectEvent ) this.aRewindLastEffectEvent.dispose(); @@ -8529,11 +8602,6 @@ AnimatedElement.prototype.getId = function() return this.aActiveElement.getAttribute( 'id' ); }; -AnimatedElement.prototype.isUpdated = function() -{ - return this.bIsUpdated; -}; - AnimatedElement.prototype.getAdditiveMode = function() { return this.eAdditiveMode; @@ -8571,8 +8639,7 @@ AnimatedElement.prototype.notifySlideStart = function() AnimatedElement.prototype.notifyAnimationStart = function() { - this.DBG( '.notifyAnimationStart invoked' ); - this.bIsUpdated = false; + // empty body }; AnimatedElement.prototype.notifyAnimationEnd = function() @@ -8582,28 +8649,16 @@ AnimatedElement.prototype.notifyAnimationEnd = function() AnimatedElement.prototype.notifyNextEffectStart = function( nEffectIndex ) { -// 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; + // empty body }; +/** saveState + * Save the state of the managed animated element and append it to aStateSet + * using the passed animation node id as key. + * + * @param nAnimationNodeId + * A non negative integer representing the unique id of an animation node. + */ AnimatedElement.prototype.saveState = function( nAnimationNodeId ) { ANIMDBG.print( 'AnimatedElement(' + this.getId() + ').saveState(' + nAnimationNodeId +')' ); @@ -8620,6 +8675,16 @@ AnimatedElement.prototype.saveState = function( nAnimationNodeId ) }; +/** restoreState + * Restore the state of the managed animated element to the state with key + * the passed animation node id. + * + * @param nAnimationNodeId + * A non negative integer representing the unique id of an animation node. + * + * @return + * True if the restoring operation is successful, false otherwise. + */ AnimatedElement.prototype.restoreState = function( nAnimationNodeId ) { if( !this.aStateSet[ nAnimationNodeId ] ) @@ -9676,7 +9741,7 @@ function EventMultiplexer( aTimerEventQueue ) this.aTimerEventQueue = aTimerEventQueue; this.aEventMap = new Object(); this.aSkipEffectEvent = null; - this.aRewindEffectEvent = null; + this.aRewindCurrentEffectEvent = null; this.aRewindLastEffectEvent = null; } @@ -9727,17 +9792,17 @@ EventMultiplexer.prototype.notifySkipEffectEvent = function() } }; -EventMultiplexer.prototype.registerRewindEffectEvent = function( aEvent ) +EventMultiplexer.prototype.registerRewindCurrentEffectEvent = function( aEvent ) { - this.aRewindEffectEvent = aEvent; + this.aRewindCurrentEffectEvent = aEvent; }; -EventMultiplexer.prototype.notifyRewindEffectEvent = function() +EventMultiplexer.prototype.notifyRewindCurrentEffectEvent = function() { - if( this.aRewindEffectEvent ) + if( this.aRewindCurrentEffectEvent ) { - this.aTimerEventQueue.addEvent( this.aRewindEffectEvent ); - this.aRewindEffectEvent = null; + this.aTimerEventQueue.addEvent( this.aRewindCurrentEffectEvent ); + this.aRewindCurrentEffectEvent = null; } }; @@ -11342,6 +11407,10 @@ SlideShow.prototype.nextEffect = function() return true; }; +/** skipCurrentEffect + * Skip the current playing effect. + * + */ SlideShow.prototype.skipCurrentEffect = function() { if( this.bIsSkipping || this.bIsRewinding ) @@ -11353,6 +11422,10 @@ SlideShow.prototype.skipCurrentEffect = function() this.bIsSkipping = false; }; +/** rewindEffect + * Rewind the current playing effect or the last played one. + * + */ SlideShow.prototype.rewindEffect = function() { if( this.bIsSkipping || this.bIsRewinding ) @@ -11361,17 +11434,22 @@ SlideShow.prototype.rewindEffect = function() this.bIsRewinding = true; if( this.isRunning() ) { - this.aEventMultiplexer.notifyRewindEffectEvent(); + this.aEventMultiplexer.notifyRewindCurrentEffectEvent(); } else { this.aEventMultiplexer.notifyRewindLastEffectEvent(); } - --this.nCurrentEffect; + if( this.nCurrentEffect > 0 ) + --this.nCurrentEffect; this.update(); this.bIsRewinding = false; }; +/** skipEffect + * Skip the next effect to be played. + * + */ SlideShow.prototype.skipEffect = function() { if( this.bIsSkipping || this.bIsRewinding ) @@ -11400,16 +11478,6 @@ SlideShow.prototype.skipEffect = function() return true; }; -//SlideShow.prototype.previousEffect = function() -//{ -// if( this.nCurrentEffect <= 0 ) -// return false; -// this.eDirection = BACKWARD; -// this.aNextEffectEventArray.at( this.nCurrentEffect ).fire(); -// --this.nCurrentEffect; -// return true; -//}; - SlideShow.prototype.displaySlide = function( nNewSlide, bSkipSlideTransition ) { var aMetaDoc = theMetaDoc; commit 12a52aaeecd60df958f75323ae9ca7684486e1ed Author: Marco Cecchetti <[email protected]> Date: Tue Jul 3 15:39:32 2012 +0200 Changed the rewindCurrentEffect method. The change was needed because rewinding a playing shape transition effect based on a clip-path doesnât work properly on Firefox and Internet Explorer. diff --git a/filter/source/svg/presentation_engine.js b/filter/source/svg/presentation_engine.js index d705658..9b62dd7 100644 --- a/filter/source/svg/presentation_engine.js +++ b/filter/source/svg/presentation_engine.js @@ -6489,8 +6489,11 @@ SequentialTimeContainer.prototype.rewindCurrentEffect = function( aChildNode ) assert( !this.bIsRewinding, 'SequentialTimeContainer.rewindCurrentEffect: is already rewinding.' ); this.bIsRewinding = true; + this.getContext().aActivityQueue.endAll(); + this.getContext().bIsSkipping = true; this.getContext().aTimerEventQueue.forceEmpty(); - this.getContext().aActivityQueue.clear(); + this.getContext().bIsSkipping = false; + this.getContext().aActivityQueue.endAll(); aChildNode.end(); aChildNode.removeEffect(); commit d501d66a69340869227f2051b912614b04799d2c Author: Marco Cecchetti <[email protected]> Date: Mon Jul 2 23:36:35 2012 +0200 Skipping a single effect works in JavaScript even if the effect is rewinded (fill=remove). Added a bIsSkipping flag to the SlideShowContext class and modified the activate_st method of the AnimationBaseNode class. Now when we are skipping the managed activity is not appended to the activity class but the end method is executed immediately. In such a way the correct order of the various events that belong to the animation time-line is preserved. diff --git a/filter/source/svg/presentation_engine.js b/filter/source/svg/presentation_engine.js index c71cad6..d705658 100644 --- a/filter/source/svg/presentation_engine.js +++ b/filter/source/svg/presentation_engine.js @@ -5745,7 +5745,14 @@ AnimationBaseNode.prototype.activate_st = function() { this.saveStateOfAnimatedElement(); this.aActivity.setTargets( this.getAnimatedElement() ); - this.getContext().aActivityQueue.addActivity( this.aActivity ); + if( this.getContext().bIsSkipping ) + { + this.aActivity.end(); + } + else + { + this.getContext().aActivityQueue.addActivity( this.aActivity ); + } } else { @@ -5821,8 +5828,7 @@ AnimationBaseNode.prototype.saveStateOfAnimatedElement = function() AnimationBaseNode.prototype.removeEffect = function() { - log( 'AnimationBaseNode.removeEffect invoked' ); - this.getAnimatedElement().setTo( this.getId() ); + this.getAnimatedElement().restoreState( this.getId() ); }; AnimationBaseNode.prototype.getTargetElement = function() @@ -6175,7 +6181,7 @@ BaseContainerNode.prototype.deactivate_st = function( eDestState ) // end all children that are not ENDED: this.forEachChildNode( mem_fn( 'end' ), ~ENDED_NODE ); if( this.getFillMode() == FILL_MODE_REMOVE ) - this.forEachChildNode( mem_fn( 'removeEffect' ), ENDED_NODE ); + this.removeEffect(); } }; @@ -6277,8 +6283,14 @@ BaseContainerNode.prototype.removeEffect = function() return; for( var i = nChildrenCount - 1; i >= 0; --i ) { - if( ( this.aChildrenArray[i].getState() & FROZEN_NODE | ENDED_NODE ) == 0 ) + if( ( this.aChildrenArray[i].getState() & ( FROZEN_NODE | ENDED_NODE ) ) == 0 ) + { + log( 'BaseContainerNode.removeEffect: child(id:' + + this.aChildrenArray[i].getId() + ') is neither frozen nor ended;' + + ' state: ' + + aTransitionModeOutMap[ this.aChildrenArray[i].getState() ] ); continue; + } this.aChildrenArray[i].removeEffect(); } }; @@ -6458,7 +6470,9 @@ SequentialTimeContainer.prototype.skipEffect = function( aChildNode ) if( this.isChildNode( aChildNode ) ) { this.getContext().aActivityQueue.endAll(); + this.getContext().bIsSkipping = true; this.getContext().aTimerEventQueue.forceEmpty(); + this.getContext().bIsSkipping = false; var aEvent = makeEvent( bind2( aChildNode.deactivate, aChildNode ) ); this.getContext().aTimerEventQueue.addEvent( aEvent ); } @@ -8589,6 +8603,7 @@ AnimatedElement.prototype.notifyNextEffectStart = function( nEffectIndex ) AnimatedElement.prototype.saveState = function( nAnimationNodeId ) { + ANIMDBG.print( 'AnimatedElement(' + this.getId() + ').saveState(' + nAnimationNodeId +')' ); if( !this.aStateSet[ nAnimationNodeId ] ) { this.aStateSet[ nAnimationNodeId ] = new Object(); @@ -8602,15 +8617,17 @@ AnimatedElement.prototype.saveState = function( nAnimationNodeId ) }; -AnimatedElement.prototype.setTo = function( nAnimationNodeId ) +AnimatedElement.prototype.restoreState = function( nAnimationNodeId ) { if( !this.aStateSet[ nAnimationNodeId ] ) { - log( 'AnimatedElement(' + this.getId() + ').setTo: state ' + log( 'AnimatedElement(' + this.getId() + ').restoreState: state ' +nAnimationNodeId + ' is not valid' ); return false; } + ANIMDBG.print( 'AnimatedElement(' + this.getId() + ').restoreState(' + nAnimationNodeId +')' ); + var aState = this.aStateSet[ nAnimationNodeId ]; var bRet = this.setToElement( aState.aElement ); if( bRet ) @@ -11196,8 +11213,8 @@ function SlideShow() this.eDirection = FORWARD; this.bIsIdle = true; this.bIsEnabled = true; - this.bIsSkipping = false; this.bIsRewinding = false; + this.bIsSkipping = false; this.bNoSlideTransition = false; } @@ -11548,6 +11565,7 @@ function SlideShowContext( aTimerEventQueue, aEventMultiplexer, aNextEffectEvent this.aEventMultiplexer = aEventMultiplexer; this.aNextEffectEventArray = aNextEffectEventArray; this.aActivityQueue = aActivityQueue; + this.bIsSkipping = false; }
_______________________________________________ Libreoffice-commits mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
