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; |