From bf2f0c913774c90e4c9a65119d0219187bb4498c Mon Sep 17 00:00:00 2001 From: Mark Hung Date: Thu, 21 Mar 2019 22:56:41 +0800 Subject: tdf#73092 remove remaining shape of the repeating animation. It is neccessary to set a drawshape to invisible (i.e. remove the effect ) before the drawshape rewind, otherwise it remains at the original place. The timenode container will ask its child to remove the effect after all the child finished, before it start to repeat or it deactivate. Change-Id: Iaef1a8269b61afa0c37b03655e2ea169f1d3c453 Reviewed-on: https://gerrit.libreoffice.org/69543 Tested-by: Jenkins Reviewed-by: Mark Hung --- .../source/engine/animationnodes/animationbasenode.cxx | 17 ++++++++++++++++- .../source/engine/animationnodes/animationbasenode.hxx | 2 ++ .../source/engine/animationnodes/basecontainernode.cxx | 8 ++++++++ slideshow/source/inc/animationnode.hxx | 7 +++++++ slideshow/source/inc/basenode.hxx | 7 ++++--- 5 files changed, 37 insertions(+), 4 deletions(-) (limited to 'slideshow/source') diff --git a/slideshow/source/engine/animationnodes/animationbasenode.cxx b/slideshow/source/engine/animationnodes/animationbasenode.cxx index 107ac68650a6..ed4d157c526f 100644 --- a/slideshow/source/engine/animationnodes/animationbasenode.cxx +++ b/slideshow/source/engine/animationnodes/animationbasenode.cxx @@ -24,6 +24,7 @@ #include #include #include +#include #include #include "nodetools.hxx" @@ -52,6 +53,7 @@ AnimationBaseNode::AnimationBaseNode( mpShape(), mpShapeSubset(), mpSubsetManager(rContext.maContext.mpSubsettableShapeManager), + mbPreservedVisibility(true), mbIsIndependentSubset( rContext.mbIsIndependentSubset ) { // extract native node targets @@ -234,8 +236,11 @@ bool AnimationBaseNode::resolve_st() void AnimationBaseNode::activate_st() { + AttributableShapeSharedPtr const pShape(getShape()); + mbPreservedVisibility = pShape->isVisible(); + // create new attribute layer - maAttributeLayerHolder.createAttributeLayer( getShape() ); + maAttributeLayerHolder.createAttributeLayer(pShape); ENSURE_OR_THROW( maAttributeLayerHolder.get(), "Could not generate shape attribute layer" ); @@ -354,6 +359,16 @@ void AnimationBaseNode::deactivate_st( NodeState eDestState ) } } +void AnimationBaseNode::removeEffect() +{ + if (!isDependentSubsettedShape()) { + AttributableShapeSharedPtr const pShape(getShape()); + pShape->setVisibility(!mbPreservedVisibility); + getContext().mpSubsettableShapeManager->notifyShapeUpdate( pShape ); + pShape->setVisibility(mbPreservedVisibility); + } +} + bool AnimationBaseNode::hasPendingAnimation() const { // TODO(F1): This might not always be true. Are there 'inactive' diff --git a/slideshow/source/engine/animationnodes/animationbasenode.hxx b/slideshow/source/engine/animationnodes/animationbasenode.hxx index 55ec060ac4ad..7751642517aa 100644 --- a/slideshow/source/engine/animationnodes/animationbasenode.hxx +++ b/slideshow/source/engine/animationnodes/animationbasenode.hxx @@ -46,6 +46,7 @@ public: #if defined(DBG_UTIL) virtual void showState() const override; #endif + virtual void removeEffect() override; protected: virtual void dispose() override; @@ -87,6 +88,7 @@ private: /// When valid, this is a subsetted target shape ShapeSubsetSharedPtr mpShapeSubset; SubsettableShapeManagerSharedPtr const mpSubsetManager; + bool mbPreservedVisibility; bool mbIsIndependentSubset; }; diff --git a/slideshow/source/engine/animationnodes/basecontainernode.cxx b/slideshow/source/engine/animationnodes/basecontainernode.cxx index e8e5dfbd7f88..02668ae7fd28 100644 --- a/slideshow/source/engine/animationnodes/basecontainernode.cxx +++ b/slideshow/source/engine/animationnodes/basecontainernode.cxx @@ -20,6 +20,7 @@ #include #include +#include #include #include #include "nodetools.hxx" @@ -161,6 +162,11 @@ bool BaseContainerNode::notifyDeactivatedChild( } if(mnLeftIterations >= 1.0 || mbRestart) { + // SMIL spec said that "Accumulate" controls whether or not the animation + // is cumulative, but XTimeContainer do not have this attribute, so always + // remove the effect before next repeat. + forEachChildNode(std::mem_fn(&AnimationNode::removeEffect), -1); + if (mnLeftIterations >= 1.0) bFinished = false; @@ -172,6 +178,8 @@ bool BaseContainerNode::notifyDeactivatedChild( } else if (isDurationIndefinite()) { + if (getFillMode() == animations::AnimationFill::REMOVE) + forEachChildNode(std::mem_fn(&AnimationNode::removeEffect), -1); deactivate(); } } diff --git a/slideshow/source/inc/animationnode.hxx b/slideshow/source/inc/animationnode.hxx index 3eb5a7295668..34eca1da91ed 100644 --- a/slideshow/source/inc/animationnode.hxx +++ b/slideshow/source/inc/animationnode.hxx @@ -136,6 +136,13 @@ public: virtual void notifyDeactivating( const AnimationNodeSharedPtr& rNotifier ) = 0; + /** Called by the container to remove the animation effect + to make the painted shape correct if it restart because + of repeat or rewind ( fill mode is AnimationFill::REMOVE ) + to start state. + */ + virtual void removeEffect() = 0; + /** Query node whether it has an animation pending. @return true, if this node (or at least one of its children) diff --git a/slideshow/source/inc/basenode.hxx b/slideshow/source/inc/basenode.hxx index bbfc2f78a03c..bc4eb9420b83 100644 --- a/slideshow/source/inc/basenode.hxx +++ b/slideshow/source/inc/basenode.hxx @@ -123,6 +123,10 @@ public: bool isMainSequenceRootNode() const { return mbIsMainSequenceRootNode; } + /// Get the node's fill mode + sal_Int16 getFillMode(); + + virtual void removeEffect() override {} protected: void scheduleDeactivationEvent( EventSharedPtr const& pEvent = EventSharedPtr() ); @@ -163,9 +167,6 @@ private: */ sal_Int16 getRestartDefaultMode() const; - /// Get the node's fill mode - sal_Int16 getFillMode(); - /** Get the default fill mode. If this node's default mode is AnimationFill::DEFAULT, -- cgit