Commit 1e7db55c authored by samli@chromium.org's avatar samli@chromium.org

Animations: Allow document animation timelines to have a playback rate

This change allows for animation timelines to have a playback rate
specified which can then be used to pause or slow down all animations
on a timeline. An inspector protocol method is also added to allow the
animation timeline playback rate to be set on all document animation
timelines associated with a page.

BUG=432368

Review URL: https://codereview.chromium.org/717003002

git-svn-id: svn://svn.chromium.org/blink/trunk@185262 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent eae4bf9e
...@@ -63,6 +63,9 @@ PassRefPtrWillBeRawPtr<AnimationTimeline> AnimationTimeline::create(Document* do ...@@ -63,6 +63,9 @@ PassRefPtrWillBeRawPtr<AnimationTimeline> AnimationTimeline::create(Document* do
AnimationTimeline::AnimationTimeline(Document* document, PassOwnPtrWillBeRawPtr<PlatformTiming> timing) AnimationTimeline::AnimationTimeline(Document* document, PassOwnPtrWillBeRawPtr<PlatformTiming> timing)
: m_document(document) : m_document(document)
, m_zeroTime(0) , m_zeroTime(0)
, m_currentTimeSnapshot(0)
, m_rawCurrentTimeSnapshot(0)
, m_playbackRate(1)
{ {
if (!timing) if (!timing)
m_timing = adoptPtrWillBeNoop(new AnimationTimelineTiming(this)); m_timing = adoptPtrWillBeNoop(new AnimationTimelineTiming(this));
...@@ -184,7 +187,8 @@ double AnimationTimeline::currentTimeInternal(bool& isNull) ...@@ -184,7 +187,8 @@ double AnimationTimeline::currentTimeInternal(bool& isNull)
isNull = true; isNull = true;
return std::numeric_limits<double>::quiet_NaN(); return std::numeric_limits<double>::quiet_NaN();
} }
double result = m_document->animationClock().currentTime() - zeroTime(); // New currentTime = currentTime when the playback rate was last changed + time delta since then * playback rate
double result = m_currentTimeSnapshot + (m_document->animationClock().currentTime() - m_rawCurrentTimeSnapshot - zeroTime()) * playbackRate();
isNull = std::isnan(result); isNull = std::isnan(result);
return result; return result;
} }
...@@ -230,6 +234,19 @@ void AnimationTimeline::setOutdatedAnimationPlayer(AnimationPlayer* player) ...@@ -230,6 +234,19 @@ void AnimationTimeline::setOutdatedAnimationPlayer(AnimationPlayer* player)
m_timing->serviceOnNextFrame(); m_timing->serviceOnNextFrame();
} }
void AnimationTimeline::setPlaybackRate(double playbackRate)
{
// FIXME: need to invalidate compositor animations
m_currentTimeSnapshot = currentTimeInternal();
m_rawCurrentTimeSnapshot = m_document->animationClock().currentTime() - zeroTime();
m_playbackRate = playbackRate;
}
double AnimationTimeline::playbackRate() const
{
return m_playbackRate;
}
#if !ENABLE(OILPAN) #if !ENABLE(OILPAN)
void AnimationTimeline::detachFromDocument() void AnimationTimeline::detachFromDocument()
{ {
......
...@@ -91,6 +91,9 @@ public: ...@@ -91,6 +91,9 @@ public:
void setOutdatedAnimationPlayer(AnimationPlayer*); void setOutdatedAnimationPlayer(AnimationPlayer*);
bool hasOutdatedAnimationPlayer() const; bool hasOutdatedAnimationPlayer() const;
void setPlaybackRate(double);
double playbackRate() const;
Document* document() { return m_document.get(); } Document* document() { return m_document.get(); }
#if !ENABLE(OILPAN) #if !ENABLE(OILPAN)
void detachFromDocument(); void detachFromDocument();
...@@ -110,6 +113,10 @@ private: ...@@ -110,6 +113,10 @@ private:
WillBeHeapHashSet<RefPtrWillBeMember<AnimationPlayer>> m_playersNeedingUpdate; WillBeHeapHashSet<RefPtrWillBeMember<AnimationPlayer>> m_playersNeedingUpdate;
WillBeHeapHashSet<RawPtrWillBeWeakMember<AnimationPlayer>> m_players; WillBeHeapHashSet<RawPtrWillBeWeakMember<AnimationPlayer>> m_players;
double m_currentTimeSnapshot;
double m_rawCurrentTimeSnapshot;
double m_playbackRate;
friend class SMILTimeContainer; friend class SMILTimeContainer;
static const double s_minimumDelay; static const double s_minimumDelay;
......
...@@ -186,6 +186,92 @@ TEST_F(AnimationAnimationTimelineTest, ZeroTime) ...@@ -186,6 +186,92 @@ TEST_F(AnimationAnimationTimelineTest, ZeroTime)
EXPECT_FALSE(isNull); EXPECT_FALSE(isNull);
} }
TEST_F(AnimationAnimationTimelineTest, PlaybackRateForInspectorNormal)
{
timeline = AnimationTimeline::create(document.get());
bool isNull;
document->animationClock().updateTime(100);
timeline->setPlaybackRate(1.0);
EXPECT_EQ(100, timeline->currentTimeInternal());
EXPECT_EQ(100, timeline->currentTimeInternal(isNull));
EXPECT_FALSE(isNull);
document->animationClock().updateTime(200);
EXPECT_EQ(200, timeline->currentTimeInternal());
EXPECT_EQ(200, timeline->currentTimeInternal(isNull));
EXPECT_FALSE(isNull);
}
TEST_F(AnimationAnimationTimelineTest, PlaybackRateForInspectorPause)
{
timeline = AnimationTimeline::create(document.get());
bool isNull;
document->animationClock().updateTime(100);
EXPECT_EQ(100, timeline->currentTimeInternal());
EXPECT_EQ(100, timeline->currentTimeInternal(isNull));
EXPECT_FALSE(isNull);
timeline->setPlaybackRate(0.0);
document->animationClock().updateTime(200);
EXPECT_EQ(100, timeline->currentTimeInternal());
EXPECT_EQ(100, timeline->currentTimeInternal(isNull));
timeline->setPlaybackRate(1.0);
document->animationClock().updateTime(400);
EXPECT_EQ(300, timeline->currentTimeInternal());
EXPECT_EQ(300, timeline->currentTimeInternal(isNull));
EXPECT_FALSE(isNull);
}
TEST_F(AnimationAnimationTimelineTest, PlaybackRateForInspectorSlow)
{
timeline = AnimationTimeline::create(document.get());
bool isNull;
document->animationClock().updateTime(100);
EXPECT_EQ(100, timeline->currentTimeInternal());
EXPECT_EQ(100, timeline->currentTimeInternal(isNull));
EXPECT_FALSE(isNull);
timeline->setPlaybackRate(0.5);
document->animationClock().updateTime(300);
EXPECT_EQ(200, timeline->currentTimeInternal());
EXPECT_EQ(200, timeline->currentTimeInternal(isNull));
timeline->setPlaybackRate(1.0);
document->animationClock().updateTime(400);
EXPECT_EQ(300, timeline->currentTimeInternal());
EXPECT_EQ(300, timeline->currentTimeInternal(isNull));
EXPECT_FALSE(isNull);
}
TEST_F(AnimationAnimationTimelineTest, PlaybackRateForInspectorFast)
{
timeline = AnimationTimeline::create(document.get());
bool isNull;
document->animationClock().updateTime(100);
EXPECT_EQ(100, timeline->currentTimeInternal());
EXPECT_EQ(100, timeline->currentTimeInternal(isNull));
EXPECT_FALSE(isNull);
timeline->setPlaybackRate(2);
document->animationClock().updateTime(300);
EXPECT_EQ(500, timeline->currentTimeInternal());
EXPECT_EQ(500, timeline->currentTimeInternal(isNull));
timeline->setPlaybackRate(1.0);
document->animationClock().updateTime(400);
EXPECT_EQ(600, timeline->currentTimeInternal());
EXPECT_EQ(600, timeline->currentTimeInternal(isNull));
EXPECT_FALSE(isNull);
}
TEST_F(AnimationAnimationTimelineTest, PauseForTesting) TEST_F(AnimationAnimationTimelineTest, PauseForTesting)
{ {
float seekTime = 1; float seekTime = 1;
......
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include "bindings/core/v8/ScriptRegexp.h" #include "bindings/core/v8/ScriptRegexp.h"
#include "core/HTMLNames.h" #include "core/HTMLNames.h"
#include "core/UserAgentStyleSheets.h" #include "core/UserAgentStyleSheets.h"
#include "core/animation/AnimationTimeline.h"
#include "core/css/StyleSheetContents.h" #include "core/css/StyleSheetContents.h"
#include "core/css/resolver/StyleResolver.h" #include "core/css/resolver/StyleResolver.h"
#include "core/css/resolver/ViewportStyleResolver.h" #include "core/css/resolver/ViewportStyleResolver.h"
...@@ -1475,6 +1476,14 @@ void InspectorPageAgent::setShowViewportSizeOnResize(ErrorString*, bool show, co ...@@ -1475,6 +1476,14 @@ void InspectorPageAgent::setShowViewportSizeOnResize(ErrorString*, bool show, co
m_state->setBoolean(PageAgentState::showGridOnResize, asBool(showGrid)); m_state->setBoolean(PageAgentState::showGridOnResize, asBool(showGrid));
} }
void InspectorPageAgent::setAnimationsPlaybackRate(ErrorString*, double playbackRate)
{
for (Frame* frame = m_page->mainFrame(); frame; frame = frame->tree().traverseNext()) {
if (frame->isLocalFrame())
toLocalFrame(frame)->document()->timeline().setPlaybackRate(playbackRate);
}
}
void InspectorPageAgent::clearEditedResourcesContent() void InspectorPageAgent::clearEditedResourcesContent()
{ {
m_editedResourceContent.clear(); m_editedResourceContent.clear();
......
...@@ -123,6 +123,7 @@ public: ...@@ -123,6 +123,7 @@ public:
virtual void startScreencast(ErrorString*, const String* format, const int* quality, const int* maxWidth, const int* maxHeight) override; virtual void startScreencast(ErrorString*, const String* format, const int* quality, const int* maxWidth, const int* maxHeight) override;
virtual void stopScreencast(ErrorString*) override; virtual void stopScreencast(ErrorString*) override;
virtual void setShowViewportSizeOnResize(ErrorString*, bool show, const bool* showGrid) override; virtual void setShowViewportSizeOnResize(ErrorString*, bool show, const bool* showGrid) override;
virtual void setAnimationsPlaybackRate(ErrorString*, double playbackRate) override;
// InspectorInstrumentation API // InspectorInstrumentation API
void didClearDocumentOfWindowObject(LocalFrame*); void didClearDocumentOfWindowObject(LocalFrame*);
......
...@@ -583,6 +583,14 @@ ...@@ -583,6 +583,14 @@
"description": "Shows / hides color picker", "description": "Shows / hides color picker",
"hidden": true, "hidden": true,
"handlers": ["browser"] "handlers": ["browser"]
},
{
"name": "setAnimationsPlaybackRate",
"parameters": [
{ "name": "playbackRate", "type": "number", "description": "Playback rate for animations on page" }
],
"description": "Sets the playback rate of the document timeline.",
"hidden": true
} }
], ],
"events": [ "events": [
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment