Index: Source/core/animation/AnimationTimeline.cpp |
diff --git a/Source/core/animation/AnimationTimeline.cpp b/Source/core/animation/AnimationTimeline.cpp |
index 52cf0e856a4be00086c2cd083c1c759652e43235..69fd74065ca14baed243c0ef32bd8746314a81fd 100644 |
--- a/Source/core/animation/AnimationTimeline.cpp |
+++ b/Source/core/animation/AnimationTimeline.cpp |
@@ -63,9 +63,8 @@ PassRefPtrWillBeRawPtr<AnimationTimeline> AnimationTimeline::create(Document* do |
AnimationTimeline::AnimationTimeline(Document* document, PassOwnPtrWillBeRawPtr<PlatformTiming> timing) |
: m_document(document) |
- , m_zeroTime(0) |
- , m_documentCurrentTimeSnapshot(0) |
- , m_zeroTimeOffset(0) |
+ , m_zeroTime(0) // 0 is used by unit tests which cannot initialize from the loader |
+ , m_zeroTimeInitialized(false) |
, m_playbackRate(1) |
, m_lastCurrentTimeInternal(0) |
{ |
@@ -182,10 +181,11 @@ void AnimationTimeline::AnimationTimelineTiming::trace(Visitor* visitor) |
double AnimationTimeline::zeroTime() |
{ |
- if (!m_zeroTime && m_document && m_document->loader()) { |
+ if (!m_zeroTimeInitialized && m_document && m_document->loader()) { |
m_zeroTime = m_document->loader()->timing()->referenceMonotonicTime(); |
+ m_zeroTimeInitialized = true; |
} |
- return m_zeroTime + m_zeroTimeOffset; |
+ return m_zeroTime; |
} |
double AnimationTimeline::currentTime(bool& isNull) |
@@ -199,9 +199,9 @@ double AnimationTimeline::currentTimeInternal(bool& isNull) |
isNull = true; |
return std::numeric_limits<double>::quiet_NaN(); |
} |
- // New currentTime = currentTime when the playback rate was last changed + time delta since then * playback rate |
- double delta = document()->animationClock().currentTime() - m_documentCurrentTimeSnapshot; |
- double result = m_documentCurrentTimeSnapshot - zeroTime() + delta * playbackRate(); |
+ double result = m_playbackRate == 0 |
+ ? zeroTime() |
+ : (document()->animationClock().currentTime() - zeroTime()) * m_playbackRate; |
isNull = std::isnan(result); |
return result; |
} |
@@ -224,7 +224,18 @@ void AnimationTimeline::setCurrentTime(double currentTime) |
void AnimationTimeline::setCurrentTimeInternal(double currentTime) |
{ |
- m_zeroTimeOffset = document()->animationClock().currentTime() - m_zeroTime - currentTime; |
+ m_zeroTime = m_playbackRate == 0 |
+ ? currentTime |
+ : (document()->animationClock().currentTime() - currentTime) / m_playbackRate; |
+ m_zeroTimeInitialized = true; |
+ |
+ for (const auto& player : m_players) { |
+ // The Player needs a timing update to pick up a new time. |
+ player->setOutdated(); |
+ // Any corresponding compositor animation will need to be restarted. Marking the |
+ // source changed forces this. |
+ player->setCompositorPending(true); |
+ } |
} |
double AnimationTimeline::effectiveTime() |
@@ -264,13 +275,16 @@ void AnimationTimeline::setOutdatedAnimationPlayer(AnimationPlayer* player) |
void AnimationTimeline::setPlaybackRate(double playbackRate) |
{ |
- // FIXME: floating point error difference between current time before and after the playback rate changes |
- if (!m_documentCurrentTimeSnapshot) |
- m_documentCurrentTimeSnapshot = m_zeroTime; |
- m_zeroTimeOffset += (document()->animationClock().currentTime() - m_documentCurrentTimeSnapshot) * (1 - m_playbackRate); |
- m_documentCurrentTimeSnapshot = document()->animationClock().currentTime(); |
+ double currentTime = currentTimeInternal(); |
m_playbackRate = playbackRate; |
+ m_zeroTime = playbackRate == 0 |
+ ? currentTime |
+ : document()->animationClock().currentTime() - currentTime / playbackRate; |
+ m_zeroTimeInitialized = true; |
+ |
for (const auto& player : m_players) { |
+ // Corresponding compositor animation may need to be restarted to pick up |
+ // the new playback rate. Marking the source changed forces this. |
player->setCompositorPending(true); |
} |
} |