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
AnimationTimeline::AnimationTimeline(Document* document, PassOwnPtrWillBeRawPtr<PlatformTiming> timing)
: m_document(document)
, m_zeroTime(0)
, m_currentTimeSnapshot(0)
, m_rawCurrentTimeSnapshot(0)
, m_playbackRate(1)
{
if (!timing)
m_timing = adoptPtrWillBeNoop(new AnimationTimelineTiming(this));
......@@ -184,7 +187,8 @@ double AnimationTimeline::currentTimeInternal(bool& isNull)
isNull = true;
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);
return result;
}
......@@ -230,6 +234,19 @@ void AnimationTimeline::setOutdatedAnimationPlayer(AnimationPlayer* player)
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)
void AnimationTimeline::detachFromDocument()
{
......
......@@ -91,6 +91,9 @@ public:
void setOutdatedAnimationPlayer(AnimationPlayer*);
bool hasOutdatedAnimationPlayer() const;
void setPlaybackRate(double);
double playbackRate() const;
Document* document() { return m_document.get(); }
#if !ENABLE(OILPAN)
void detachFromDocument();
......@@ -110,6 +113,10 @@ private:
WillBeHeapHashSet<RefPtrWillBeMember<AnimationPlayer>> m_playersNeedingUpdate;
WillBeHeapHashSet<RawPtrWillBeWeakMember<AnimationPlayer>> m_players;
double m_currentTimeSnapshot;
double m_rawCurrentTimeSnapshot;
double m_playbackRate;
friend class SMILTimeContainer;
static const double s_minimumDelay;
......
......@@ -186,6 +186,92 @@ TEST_F(AnimationAnimationTimelineTest, ZeroTime)
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)
{
float seekTime = 1;
......
......@@ -36,6 +36,7 @@
#include "bindings/core/v8/ScriptRegexp.h"
#include "core/HTMLNames.h"
#include "core/UserAgentStyleSheets.h"
#include "core/animation/AnimationTimeline.h"
#include "core/css/StyleSheetContents.h"
#include "core/css/resolver/StyleResolver.h"
#include "core/css/resolver/ViewportStyleResolver.h"
......@@ -1475,6 +1476,14 @@ void InspectorPageAgent::setShowViewportSizeOnResize(ErrorString*, bool show, co
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()
{
m_editedResourceContent.clear();
......
......@@ -123,6 +123,7 @@ public:
virtual void startScreencast(ErrorString*, const String* format, const int* quality, const int* maxWidth, const int* maxHeight) override;
virtual void stopScreencast(ErrorString*) override;
virtual void setShowViewportSizeOnResize(ErrorString*, bool show, const bool* showGrid) override;
virtual void setAnimationsPlaybackRate(ErrorString*, double playbackRate) override;
// InspectorInstrumentation API
void didClearDocumentOfWindowObject(LocalFrame*);
......
......@@ -583,6 +583,14 @@
"description": "Shows / hides color picker",
"hidden": true,
"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": [
......
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