 Chromium Code Reviews
 Chromium Code Reviews Issue 802143002:
  AnimationPolicy setting is applied to SVG animation.  (Closed) 
  Base URL: https://chromium.googlesource.com/chromium/blink.git@master
    
  
    Issue 802143002:
  AnimationPolicy setting is applied to SVG animation.  (Closed) 
  Base URL: https://chromium.googlesource.com/chromium/blink.git@master| Index: Source/core/svg/animation/SMILTimeContainer.cpp | 
| diff --git a/Source/core/svg/animation/SMILTimeContainer.cpp b/Source/core/svg/animation/SMILTimeContainer.cpp | 
| index ea7c17eb12de3af5d027dd33b6048aa3c0bcc003..6d516d8aaeb0c221077ff9cc4ec155b4ff565a91 100644 | 
| --- a/Source/core/svg/animation/SMILTimeContainer.cpp | 
| +++ b/Source/core/svg/animation/SMILTimeContainer.cpp | 
| @@ -30,12 +30,14 @@ | 
| #include "core/animation/AnimationTimeline.h" | 
| #include "core/dom/ElementTraversal.h" | 
| #include "core/frame/FrameView.h" | 
| +#include "core/frame/Settings.h" | 
| #include "core/svg/SVGSVGElement.h" | 
| #include "core/svg/animation/SVGSMILElement.h" | 
| namespace blink { | 
| static const double initialFrameDelay = 0.025; | 
| +static const double animationPolicyOnceDuration = 3.000; | 
| #if !ENABLE(OILPAN) | 
| // Every entry-point that calls updateAnimations() should instantiate a | 
| @@ -57,7 +59,9 @@ SMILTimeContainer::SMILTimeContainer(SVGSVGElement& owner) | 
| , m_presetStartTime(0) | 
| , m_frameSchedulingState(Idle) | 
| , m_documentOrderIndexesDirty(false) | 
| + , m_animationState(NormalState) | 
| , m_wakeupTimer(this, &SMILTimeContainer::wakeupTimerFired) | 
| + , m_animationPolicyOnceTimer(this, &SMILTimeContainer::animationPolicyOnceTimerFired) | 
| , m_ownerSVGElement(owner) | 
| #if ENABLE(ASSERT) | 
| , m_preventScheduledAnimationsChanges(false) | 
| @@ -68,6 +72,7 @@ SMILTimeContainer::SMILTimeContainer(SVGSVGElement& owner) | 
| SMILTimeContainer::~SMILTimeContainer() | 
| { | 
| cancelAnimationFrame(); | 
| + cancelAnimationPolicyTimer(); | 
| ASSERT(!m_wakeupTimer.isActive()); | 
| #if ENABLE(ASSERT) | 
| ASSERT(!m_preventScheduledAnimationsChanges); | 
| @@ -152,17 +157,61 @@ SMILTime SMILTimeContainer::elapsed() const | 
| bool SMILTimeContainer::isPaused() const | 
| { | 
| + if (ImageAnimationPolicyNoAnimation == getAnimationPolicy()) | 
| 
fs
2014/12/22 16:23:14
I'd prefer if we could reuse existing state as muc
 
je_julie(Not used)
2014/12/24 03:50:51
Done.
 | 
| + return true; | 
| return m_pauseTime; | 
| } | 
| +bool SMILTimeContainer::isFrozen() const | 
| +{ | 
| + return m_animationState == FrozenState; | 
| +} | 
| + | 
| bool SMILTimeContainer::isStarted() const | 
| { | 
| return m_beginTime; | 
| } | 
| +ImageAnimationPolicy SMILTimeContainer::getAnimationPolicy() const | 
| +{ | 
| + Settings* settings = document().settings(); | 
| + if (!settings) | 
| + return ImageAnimationPolicyAllowed; | 
| + | 
| + ImageAnimationPolicy animationPolicy = settings->imageAnimationPolicy(); | 
| 
fs
2014/12/22 16:23:14
Nit: Return this directly.
 
je_julie(Not used)
2014/12/24 03:50:51
done.
 | 
| + return animationPolicy; | 
| +} | 
| + | 
| +void SMILTimeContainer::freezeTimeline() | 
| +{ | 
| + pause(true); | 
| 
fs
2014/12/22 16:23:14
Could we structure this do a state-transition befo
 
je_julie(Not used)
2014/12/24 03:50:51
I removed it with improved concept.
 | 
| +} | 
| + | 
| +void SMILTimeContainer::cancelAnimationPolicyTimer() | 
| +{ | 
| + if (m_animationPolicyOnceTimer.isActive()) | 
| + m_animationPolicyOnceTimer.stop(); | 
| +} | 
| + | 
| +void SMILTimeContainer::startAnimationPolicyTimer() | 
| +{ | 
| + m_animationState &= ~FrozenState; | 
| + m_animationPolicyOnceTimer.startOneShot(animationPolicyOnceDuration, FROM_HERE); | 
| +} | 
| + | 
| void SMILTimeContainer::begin() | 
| { | 
| RELEASE_ASSERT(!m_beginTime); | 
| + | 
| + ImageAnimationPolicy animationPolicy = getAnimationPolicy(); | 
| + if (animationPolicy == ImageAnimationPolicyNoAnimation) | 
| + return freezeTimeline(); | 
| 
fs
2014/12/22 16:23:15
This looks like a very complicated way to return d
 
je_julie(Not used)
2014/12/24 03:50:51
I removed it with improved concept.
 | 
| + | 
| + // Repeating behavior is not well-defined for SMIL/SVG animations | 
| + // We define "once" as "play for animationPolicyOnceDuration seconds" here instead. | 
| + if (animationPolicy == ImageAnimationPolicyAnimateOnce) | 
| + startAnimationPolicyTimer(); | 
| 
fs
2014/12/22 16:23:14
Shouldn't this interact with pause in some way? (S
 
je_julie(Not used)
2014/12/24 03:50:51
I updated code with paused condition.
 | 
| + | 
| double now = currentTime(); | 
| // If 'm_presetStartTime' is set, the timeline was modified via setElapsed() before the document began. | 
| @@ -192,9 +241,17 @@ void SMILTimeContainer::begin() | 
| } | 
| } | 
| -void SMILTimeContainer::pause() | 
| +void SMILTimeContainer::pause(bool freeze) | 
| { | 
| - ASSERT(!isPaused()); | 
| + if (ImageAnimationPolicyNoAnimation == getAnimationPolicy()) | 
| + return; | 
| + | 
| + ASSERT(!isPaused() || isFrozen()); | 
| + | 
| + if (freeze) | 
| + m_animationState |= FrozenState; | 
| + else | 
| + m_animationState |= PausedState; | 
| m_pauseTime = currentTime(); | 
| if (m_beginTime) { | 
| @@ -202,19 +259,45 @@ void SMILTimeContainer::pause() | 
| cancelAnimationFrame(); | 
| } | 
| m_resumeTime = 0; | 
| + | 
| + // Cancel the animation policy timer. | 
| + cancelAnimationPolicyTimer(); | 
| } | 
| void SMILTimeContainer::resume() | 
| { | 
| + if (ImageAnimationPolicyNoAnimation == getAnimationPolicy()) | 
| + return; | 
| + | 
| ASSERT(isPaused()); | 
| + | 
| + m_animationState &= ~PausedState; | 
| m_resumeTime = currentTime(); | 
| m_pauseTime = 0; | 
| scheduleWakeUp(0, SynchronizeAnimations); | 
| + | 
| + // Start the animation policy timer. | 
| + startAnimationPolicyTimer(); | 
| } | 
| void SMILTimeContainer::setElapsed(SMILTime time) | 
| { | 
| + // If imageAnimationPolicy is 'once' or 'none', | 
| + // none: setElapsed is not allowed. | 
| + // once: paused state - setElapsed. | 
| + // unpaused state - start animation policy timer and setElapsed. | 
| + ImageAnimationPolicy animationPolicy = getAnimationPolicy(); | 
| + if (animationPolicy == ImageAnimationPolicyNoAnimation) | 
| + return; | 
| + if (animationPolicy == ImageAnimationPolicyAnimateOnce) { | 
| + if (!(m_animationState & PausedState)) { | 
| + if (m_animationState & FrozenState) | 
| + resume(); | 
| + startAnimationPolicyTimer(); | 
| + } | 
| + } | 
| + | 
| // If the documment didn't begin yet, record a new start time, we'll seek to once its possible. | 
| if (!m_beginTime) { | 
| m_presetStartTime = time.value(); | 
| @@ -295,6 +378,11 @@ void SMILTimeContainer::wakeupTimerFired(Timer<SMILTimeContainer>*) | 
| } | 
| } | 
| +void SMILTimeContainer::animationPolicyOnceTimerFired(Timer<SMILTimeContainer>*) | 
| +{ | 
| + freezeTimeline(); | 
| +} | 
| + | 
| void SMILTimeContainer::updateDocumentOrderIndexes() | 
| { | 
| unsigned timingElementCount = 0; |