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 <marklh9@gmail.com>
diff --git a/slideshow/source/engine/animationnodes/animationbasenode.cxx b/slideshow/source/engine/animationnodes/animationbasenode.cxx
index 107ac68..ed4d157 100644
--- a/slideshow/source/engine/animationnodes/animationbasenode.cxx
+++ b/slideshow/source/engine/animationnodes/animationbasenode.cxx
@@ -24,6 +24,7 @@
#include <com/sun/star/presentation/ParagraphTarget.hpp>
#include <com/sun/star/animations/Timing.hpp>
#include <com/sun/star/animations/AnimationAdditiveMode.hpp>
#include <com/sun/star/animations/AnimationFill.hpp>
#include <com/sun/star/presentation/ShapeAnimationSubType.hpp>
#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 55ec060..7751642 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 e8e5dfb..02668ae 100644
--- a/slideshow/source/engine/animationnodes/basecontainernode.cxx
+++ b/slideshow/source/engine/animationnodes/basecontainernode.cxx
@@ -20,6 +20,7 @@
#include <basecontainernode.hxx>
#include <com/sun/star/animations/AnimationRestart.hpp>
#include <com/sun/star/animations/AnimationFill.hpp>
#include <eventqueue.hxx>
#include <tools.hxx>
#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 3eb5a729..34eca1d 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 bbfc2f7..bc4eb94 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,