Handle direction control in compositor Animations

This patch is the blink side. The chromium side is handled on issue #180153010

It doesn't revert functions anymore in blink. Instead, it sets the direction parameter to WebAnimation, which will in turn pass it to the compositor.

BUG=348071

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

git-svn-id: svn://svn.chromium.org/blink/trunk@181945 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent 5c649087
<html>
<style>
div {
position: relative;
height: 100px;
width: 100px;
background: blue;
-webkit-transform: translateZ(0);
-webkit-animation-duration: 2s;
-webkit-animation-timing-function: linear;
-webkit-animation-fill-mode: both;
-webkit-animation-iteration-count: 2;
}
.test0 {
-webkit-animation-direction: normal;
}
.test1 {
-webkit-animation-direction: reverse;
}
.test2 {
-webkit-animation-direction: alternate;
}
.test3 {
-webkit-animation-direction: reverse;
}
.anim-left {
-webkit-animation-name: anim-left;
z-index: 100;
}
.anim-transform {
-webkit-animation-name: anim-transform;
z-index: 200;
}
@-webkit-keyframes anim-left {
0% {
left: 0px;
}
100% {
left: 300px;
}
}
@-webkit-keyframes anim-transform {
0% {
-webkit-transform: translateX(0px);
}
100% {
-webkit-transform: translateX(300px);
}
}
</style>
<body>
<p>
Each section below has two boxes, the top runs on the main thread, the bottom
on the compositor. The animations should be identical but start at different
times.
</p><p>
This test is successful if the boxes are mostly in sync (there might be a small
offset between them).
</p>
<hr>
Direction normal
<br>
<div class='test0 anim-left'></div>
<div class='test0 anim-transform'></div>
Direction reverse
<br>
<div class='test1 anim-left'></div>
<div class='test1 anim-transform'></div>
Direction alternate
<br>
<div class='test2 anim-left'></div>
<div class='test2 anim-transform'></div>
Direction alternate-reverse
<br>
<div class='test3 anim-left'></div>
<div class='test3 anim-transform'></div>
</body>
</html>
...@@ -59,71 +59,17 @@ namespace blink { ...@@ -59,71 +59,17 @@ namespace blink {
namespace { namespace {
void getKeyframeValuesForProperty(const KeyframeEffectModelBase* effect, CSSPropertyID id, double scale, bool reverse, PropertySpecificKeyframeVector& values) void getKeyframeValuesForProperty(const KeyframeEffectModelBase* effect, CSSPropertyID id, double scale, PropertySpecificKeyframeVector& values)
{ {
ASSERT(values.isEmpty()); ASSERT(values.isEmpty());
const PropertySpecificKeyframeVector& group = effect->getPropertySpecificKeyframes(id); const PropertySpecificKeyframeVector& group = effect->getPropertySpecificKeyframes(id);
if (reverse) { for (size_t i = 0; i < group.size(); ++i) {
for (size_t i = group.size(); i--;) { double offset = group[i]->offset() * scale;
double offset = (1 - group[i]->offset()) * scale; values.append(group[i]->cloneWithOffset(offset));
values.append(group[i]->cloneWithOffset(offset));
}
} else {
for (size_t i = 0; i < group.size(); ++i) {
double offset = group[i]->offset() * scale;
values.append(group[i]->cloneWithOffset(offset));
}
}
}
}
// -----------------------------------------------------------------------
// TimingFunctionReverser methods
// -----------------------------------------------------------------------
PassRefPtr<TimingFunction> CompositorAnimationsTimingFunctionReverser::reverse(const LinearTimingFunction& timefunc)
{
return const_cast<LinearTimingFunction*>(&timefunc);
}
PassRefPtr<TimingFunction> CompositorAnimationsTimingFunctionReverser::reverse(const CubicBezierTimingFunction& timefunc)
{
switch (timefunc.subType()) {
case CubicBezierTimingFunction::EaseIn:
return CubicBezierTimingFunction::preset(CubicBezierTimingFunction::EaseOut);
case CubicBezierTimingFunction::EaseOut:
return CubicBezierTimingFunction::preset(CubicBezierTimingFunction::EaseIn);
case CubicBezierTimingFunction::EaseInOut:
return const_cast<CubicBezierTimingFunction*>(&timefunc);
case CubicBezierTimingFunction::Ease: // Ease is not symmetrical
case CubicBezierTimingFunction::Custom:
return CubicBezierTimingFunction::create(1 - timefunc.x2(), 1 - timefunc.y2(), 1 - timefunc.x1(), 1 - timefunc.y1());
default:
ASSERT_NOT_REACHED();
return PassRefPtr<TimingFunction>();
} }
} }
PassRefPtr<TimingFunction> CompositorAnimationsTimingFunctionReverser::reverse(const TimingFunction& timefunc)
{
switch (timefunc.type()) {
case TimingFunction::LinearFunction: {
const LinearTimingFunction& linear = toLinearTimingFunction(timefunc);
return reverse(linear);
}
case TimingFunction::CubicBezierFunction: {
const CubicBezierTimingFunction& cubic = toCubicBezierTimingFunction(timefunc);
return reverse(cubic);
}
// Steps function can not be reversed.
case TimingFunction::StepsFunction:
default:
ASSERT_NOT_REACHED();
return PassRefPtr<TimingFunction>();
}
} }
bool CompositorAnimations::getAnimatedBoundingBox(FloatBox& box, const AnimationEffect& effect, double minValue, double maxValue) const bool CompositorAnimations::getAnimatedBoundingBox(FloatBox& box, const AnimationEffect& effect, double minValue, double maxValue) const
...@@ -340,10 +286,7 @@ bool CompositorAnimationsImpl::convertTimingForCompositor(const Timing& timing, ...@@ -340,10 +286,7 @@ bool CompositorAnimationsImpl::convertTimingForCompositor(const Timing& timing,
if (scaledStartDelay > 0 && scaledStartDelay > out.scaledDuration * timing.iterationCount) if (scaledStartDelay > 0 && scaledStartDelay > out.scaledDuration * timing.iterationCount)
return false; return false;
out.reverse = (timing.direction == Timing::PlaybackDirectionReverse out.direction = timing.direction;
|| timing.direction == Timing::PlaybackDirectionAlternateReverse);
out.alternate = (timing.direction == Timing::PlaybackDirectionAlternate
|| timing.direction == Timing::PlaybackDirectionAlternateReverse);
if (!std::isfinite(timing.iterationCount)) { if (!std::isfinite(timing.iterationCount)) {
out.adjustedIterationCount = -1; out.adjustedIterationCount = -1;
...@@ -415,26 +358,15 @@ void addKeyframeWithTimingFunction(PlatformAnimationCurveType& curve, const Plat ...@@ -415,26 +358,15 @@ void addKeyframeWithTimingFunction(PlatformAnimationCurveType& curve, const Plat
} // namespace anoymous } // namespace anoymous
void CompositorAnimationsImpl::addKeyframesToCurve(WebCompositorAnimationCurve& curve, const PropertySpecificKeyframeVector& keyframes, const Timing& timing, bool reverse) void CompositorAnimationsImpl::addKeyframesToCurve(WebCompositorAnimationCurve& curve, const PropertySpecificKeyframeVector& keyframes, const Timing& timing)
{ {
for (size_t i = 0; i < keyframes.size(); i++) { for (size_t i = 0; i < keyframes.size(); i++) {
RefPtr<TimingFunction> reversedTimingFunction;
const TimingFunction* keyframeTimingFunction = 0; const TimingFunction* keyframeTimingFunction = 0;
if (i < keyframes.size() - 1) { // Ignore timing function of last frame. if (i < keyframes.size() - 1) { // Ignore timing function of last frame.
if (keyframes.size() == 2 && keyframes[0]->easing().type() == TimingFunction::LinearFunction) { if (keyframes.size() == 2 && keyframes[0]->easing().type() == TimingFunction::LinearFunction) {
if (reverse) { keyframeTimingFunction = timing.timingFunction.get();
reversedTimingFunction = CompositorAnimationsTimingFunctionReverser::reverse(*timing.timingFunction.get());
keyframeTimingFunction = reversedTimingFunction.get();
} else {
keyframeTimingFunction = timing.timingFunction.get();
}
} else { } else {
if (reverse) { keyframeTimingFunction = &keyframes[i]->easing();
reversedTimingFunction = CompositorAnimationsTimingFunctionReverser::reverse(keyframes[i + 1]->easing());
keyframeTimingFunction = reversedTimingFunction.get();
} else {
keyframeTimingFunction = &keyframes[i]->easing();
}
} }
} }
...@@ -486,7 +418,7 @@ void CompositorAnimationsImpl::getAnimationOnCompositor(const Timing& timing, do ...@@ -486,7 +418,7 @@ void CompositorAnimationsImpl::getAnimationOnCompositor(const Timing& timing, do
for (PropertySet::iterator it = properties.begin(); it != properties.end(); ++it) { for (PropertySet::iterator it = properties.begin(); it != properties.end(); ++it) {
PropertySpecificKeyframeVector values; PropertySpecificKeyframeVector values;
getKeyframeValuesForProperty(&effect, *it, compositorTiming.scaledDuration, compositorTiming.reverse, values); getKeyframeValuesForProperty(&effect, *it, compositorTiming.scaledDuration, values);
WebCompositorAnimation::TargetProperty targetProperty; WebCompositorAnimation::TargetProperty targetProperty;
OwnPtr<WebCompositorAnimationCurve> curve; OwnPtr<WebCompositorAnimationCurve> curve;
...@@ -495,21 +427,21 @@ void CompositorAnimationsImpl::getAnimationOnCompositor(const Timing& timing, do ...@@ -495,21 +427,21 @@ void CompositorAnimationsImpl::getAnimationOnCompositor(const Timing& timing, do
targetProperty = WebCompositorAnimation::TargetPropertyOpacity; targetProperty = WebCompositorAnimation::TargetPropertyOpacity;
WebFloatAnimationCurve* floatCurve = Platform::current()->compositorSupport()->createFloatAnimationCurve(); WebFloatAnimationCurve* floatCurve = Platform::current()->compositorSupport()->createFloatAnimationCurve();
addKeyframesToCurve(*floatCurve, values, timing, compositorTiming.reverse); addKeyframesToCurve(*floatCurve, values, timing);
curve = adoptPtr(floatCurve); curve = adoptPtr(floatCurve);
break; break;
} }
case CSSPropertyWebkitFilter: { case CSSPropertyWebkitFilter: {
targetProperty = WebCompositorAnimation::TargetPropertyFilter; targetProperty = WebCompositorAnimation::TargetPropertyFilter;
WebFilterAnimationCurve* filterCurve = Platform::current()->compositorSupport()->createFilterAnimationCurve(); WebFilterAnimationCurve* filterCurve = Platform::current()->compositorSupport()->createFilterAnimationCurve();
addKeyframesToCurve(*filterCurve, values, timing, compositorTiming.reverse); addKeyframesToCurve(*filterCurve, values, timing);
curve = adoptPtr(filterCurve); curve = adoptPtr(filterCurve);
break; break;
} }
case CSSPropertyTransform: { case CSSPropertyTransform: {
targetProperty = WebCompositorAnimation::TargetPropertyTransform; targetProperty = WebCompositorAnimation::TargetPropertyTransform;
WebTransformAnimationCurve* transformCurve = Platform::current()->compositorSupport()->createTransformAnimationCurve(); WebTransformAnimationCurve* transformCurve = Platform::current()->compositorSupport()->createTransformAnimationCurve();
addKeyframesToCurve(*transformCurve, values, timing, compositorTiming.reverse); addKeyframesToCurve(*transformCurve, values, timing);
curve = adoptPtr(transformCurve); curve = adoptPtr(transformCurve);
break; break;
} }
...@@ -526,7 +458,23 @@ void CompositorAnimationsImpl::getAnimationOnCompositor(const Timing& timing, do ...@@ -526,7 +458,23 @@ void CompositorAnimationsImpl::getAnimationOnCompositor(const Timing& timing, do
animation->setIterations(compositorTiming.adjustedIterationCount); animation->setIterations(compositorTiming.adjustedIterationCount);
animation->setTimeOffset(compositorTiming.scaledTimeOffset); animation->setTimeOffset(compositorTiming.scaledTimeOffset);
animation->setAlternatesDirection(compositorTiming.alternate);
switch (compositorTiming.direction) {
case Timing::PlaybackDirectionNormal:
animation->setDirection(blink::WebCompositorAnimation::DirectionNormal);
break;
case Timing::PlaybackDirectionReverse:
animation->setDirection(blink::WebCompositorAnimation::DirectionReverse);
break;
case Timing::PlaybackDirectionAlternate:
animation->setDirection(blink::WebCompositorAnimation::DirectionAlternate);
break;
case Timing::PlaybackDirectionAlternateReverse:
animation->setDirection(blink::WebCompositorAnimation::DirectionAlternateReverse);
break;
default:
ASSERT_NOT_REACHED();
}
animations.append(animation.release()); animations.append(animation.release());
} }
......
...@@ -41,18 +41,6 @@ namespace blink { ...@@ -41,18 +41,6 @@ namespace blink {
class Element; class Element;
class FloatBox; class FloatBox;
// Given an input timing function between keyframe at 0 and keyframe at 1.0, we
// need a timing function such that the behavior with the keyframes swapped is
// equivalent to reversing time with the input timing function and keyframes.
// This means flipping the timing function about x=0.5 and about y=0.5.
// FIXME: Remove once the Compositor natively understands reversing time.
class CompositorAnimationsTimingFunctionReverser {
public:
static PassRefPtr<TimingFunction> reverse(const LinearTimingFunction& timefunc);
static PassRefPtr<TimingFunction> reverse(const CubicBezierTimingFunction& timefunc);
static PassRefPtr<TimingFunction> reverse(const TimingFunction& timefunc);
};
class CompositorAnimations { class CompositorAnimations {
public: public:
static CompositorAnimations* instance() { return instance(0); } static CompositorAnimations* instance() { return instance(0); }
......
...@@ -41,8 +41,7 @@ class WebCompositorAnimationCurve; ...@@ -41,8 +41,7 @@ class WebCompositorAnimationCurve;
class CompositorAnimationsImpl { class CompositorAnimationsImpl {
private: private:
struct CompositorTiming { struct CompositorTiming {
bool reverse; Timing::PlaybackDirection direction;
bool alternate;
double scaledDuration; double scaledDuration;
double scaledTimeOffset; double scaledTimeOffset;
double adjustedIterationCount; double adjustedIterationCount;
...@@ -52,7 +51,7 @@ private: ...@@ -52,7 +51,7 @@ private:
static void getAnimationOnCompositor(const Timing&, double startTime, double timeOffset, const KeyframeEffectModelBase&, Vector<OwnPtr<WebCompositorAnimation> >& animations); static void getAnimationOnCompositor(const Timing&, double startTime, double timeOffset, const KeyframeEffectModelBase&, Vector<OwnPtr<WebCompositorAnimation> >& animations);
static void addKeyframesToCurve(WebCompositorAnimationCurve&, const AnimatableValuePropertySpecificKeyframeVector&, const Timing&, bool reverse); static void addKeyframesToCurve(WebCompositorAnimationCurve&, const AnimatableValuePropertySpecificKeyframeVector&, const Timing&);
friend class CompositorAnimations; friend class CompositorAnimations;
friend class AnimationCompositorAnimationsTest; friend class AnimationCompositorAnimationsTest;
......
...@@ -392,20 +392,21 @@ TEST_F(AnimationCompositorAnimationsTest, ConvertTimingForCompositorPlaybackRate ...@@ -392,20 +392,21 @@ TEST_F(AnimationCompositorAnimationsTest, ConvertTimingForCompositorPlaybackRate
TEST_F(AnimationCompositorAnimationsTest, ConvertTimingForCompositorDirection) TEST_F(AnimationCompositorAnimationsTest, ConvertTimingForCompositorDirection)
{ {
m_timing.direction = Timing::PlaybackDirectionNormal;
EXPECT_TRUE(convertTimingForCompositor(m_timing, m_compositorTiming));
EXPECT_EQ(m_compositorTiming.direction, Timing::PlaybackDirectionNormal);
m_timing.direction = Timing::PlaybackDirectionAlternate; m_timing.direction = Timing::PlaybackDirectionAlternate;
EXPECT_TRUE(convertTimingForCompositor(m_timing, m_compositorTiming)); EXPECT_TRUE(convertTimingForCompositor(m_timing, m_compositorTiming));
EXPECT_TRUE(m_compositorTiming.alternate); EXPECT_EQ(m_compositorTiming.direction, Timing::PlaybackDirectionAlternate);
EXPECT_FALSE(m_compositorTiming.reverse);
m_timing.direction = Timing::PlaybackDirectionAlternateReverse; m_timing.direction = Timing::PlaybackDirectionAlternateReverse;
EXPECT_TRUE(convertTimingForCompositor(m_timing, m_compositorTiming)); EXPECT_TRUE(convertTimingForCompositor(m_timing, m_compositorTiming));
EXPECT_TRUE(m_compositorTiming.alternate); EXPECT_EQ(m_compositorTiming.direction, Timing::PlaybackDirectionAlternateReverse);
EXPECT_TRUE(m_compositorTiming.reverse);
m_timing.direction = Timing::PlaybackDirectionReverse; m_timing.direction = Timing::PlaybackDirectionReverse;
EXPECT_TRUE(convertTimingForCompositor(m_timing, m_compositorTiming)); EXPECT_TRUE(convertTimingForCompositor(m_timing, m_compositorTiming));
EXPECT_FALSE(m_compositorTiming.alternate); EXPECT_EQ(m_compositorTiming.direction, Timing::PlaybackDirectionReverse);
EXPECT_TRUE(m_compositorTiming.reverse);
} }
TEST_F(AnimationCompositorAnimationsTest, ConvertTimingForCompositorDirectionIterationsAndStartDelay) TEST_F(AnimationCompositorAnimationsTest, ConvertTimingForCompositorDirectionIterationsAndStartDelay)
...@@ -417,8 +418,7 @@ TEST_F(AnimationCompositorAnimationsTest, ConvertTimingForCompositorDirectionIte ...@@ -417,8 +418,7 @@ TEST_F(AnimationCompositorAnimationsTest, ConvertTimingForCompositorDirectionIte
EXPECT_TRUE(convertTimingForCompositor(m_timing, m_compositorTiming)); EXPECT_TRUE(convertTimingForCompositor(m_timing, m_compositorTiming));
EXPECT_DOUBLE_EQ(6.0, m_compositorTiming.scaledTimeOffset); EXPECT_DOUBLE_EQ(6.0, m_compositorTiming.scaledTimeOffset);
EXPECT_EQ(4, m_compositorTiming.adjustedIterationCount); EXPECT_EQ(4, m_compositorTiming.adjustedIterationCount);
EXPECT_TRUE(m_compositorTiming.alternate); EXPECT_EQ(m_compositorTiming.direction, Timing::PlaybackDirectionAlternate);
EXPECT_FALSE(m_compositorTiming.reverse);
m_timing.direction = Timing::PlaybackDirectionAlternate; m_timing.direction = Timing::PlaybackDirectionAlternate;
m_timing.iterationCount = 4.0; m_timing.iterationCount = 4.0;
...@@ -427,8 +427,7 @@ TEST_F(AnimationCompositorAnimationsTest, ConvertTimingForCompositorDirectionIte ...@@ -427,8 +427,7 @@ TEST_F(AnimationCompositorAnimationsTest, ConvertTimingForCompositorDirectionIte
EXPECT_TRUE(convertTimingForCompositor(m_timing, m_compositorTiming)); EXPECT_TRUE(convertTimingForCompositor(m_timing, m_compositorTiming));
EXPECT_DOUBLE_EQ(11.0, m_compositorTiming.scaledTimeOffset); EXPECT_DOUBLE_EQ(11.0, m_compositorTiming.scaledTimeOffset);
EXPECT_EQ(4, m_compositorTiming.adjustedIterationCount); EXPECT_EQ(4, m_compositorTiming.adjustedIterationCount);
EXPECT_TRUE(m_compositorTiming.alternate); EXPECT_EQ(m_compositorTiming.direction, Timing::PlaybackDirectionAlternate);
EXPECT_FALSE(m_compositorTiming.reverse);
m_timing.direction = Timing::PlaybackDirectionAlternateReverse; m_timing.direction = Timing::PlaybackDirectionAlternateReverse;
m_timing.iterationCount = 4.0; m_timing.iterationCount = 4.0;
...@@ -437,8 +436,7 @@ TEST_F(AnimationCompositorAnimationsTest, ConvertTimingForCompositorDirectionIte ...@@ -437,8 +436,7 @@ TEST_F(AnimationCompositorAnimationsTest, ConvertTimingForCompositorDirectionIte
EXPECT_TRUE(convertTimingForCompositor(m_timing, m_compositorTiming)); EXPECT_TRUE(convertTimingForCompositor(m_timing, m_compositorTiming));
EXPECT_DOUBLE_EQ(6.0, m_compositorTiming.scaledTimeOffset); EXPECT_DOUBLE_EQ(6.0, m_compositorTiming.scaledTimeOffset);
EXPECT_EQ(4, m_compositorTiming.adjustedIterationCount); EXPECT_EQ(4, m_compositorTiming.adjustedIterationCount);
EXPECT_TRUE(m_compositorTiming.alternate); EXPECT_EQ(m_compositorTiming.direction, Timing::PlaybackDirectionAlternateReverse);
EXPECT_TRUE(m_compositorTiming.reverse);
m_timing.direction = Timing::PlaybackDirectionAlternateReverse; m_timing.direction = Timing::PlaybackDirectionAlternateReverse;
m_timing.iterationCount = 4.0; m_timing.iterationCount = 4.0;
...@@ -447,8 +445,7 @@ TEST_F(AnimationCompositorAnimationsTest, ConvertTimingForCompositorDirectionIte ...@@ -447,8 +445,7 @@ TEST_F(AnimationCompositorAnimationsTest, ConvertTimingForCompositorDirectionIte
EXPECT_TRUE(convertTimingForCompositor(m_timing, m_compositorTiming)); EXPECT_TRUE(convertTimingForCompositor(m_timing, m_compositorTiming));
EXPECT_DOUBLE_EQ(11.0, m_compositorTiming.scaledTimeOffset); EXPECT_DOUBLE_EQ(11.0, m_compositorTiming.scaledTimeOffset);
EXPECT_EQ(4, m_compositorTiming.adjustedIterationCount); EXPECT_EQ(4, m_compositorTiming.adjustedIterationCount);
EXPECT_TRUE(m_compositorTiming.alternate); EXPECT_EQ(m_compositorTiming.direction, Timing::PlaybackDirectionAlternateReverse);
EXPECT_TRUE(m_compositorTiming.reverse);
} }
TEST_F(AnimationCompositorAnimationsTest, isCandidateForAnimationOnCompositorTimingTimingFunctionPassThru) TEST_F(AnimationCompositorAnimationsTest, isCandidateForAnimationOnCompositorTimingTimingFunctionPassThru)
...@@ -613,7 +610,7 @@ TEST_F(AnimationCompositorAnimationsTest, createSimpleOpacityAnimation) ...@@ -613,7 +610,7 @@ TEST_F(AnimationCompositorAnimationsTest, createSimpleOpacityAnimation)
usesMockAnimation += EXPECT_CALL(*mockAnimationPtr, setIterations(1)); usesMockAnimation += EXPECT_CALL(*mockAnimationPtr, setIterations(1));
usesMockAnimation += EXPECT_CALL(*mockAnimationPtr, setTimeOffset(0.0)); usesMockAnimation += EXPECT_CALL(*mockAnimationPtr, setTimeOffset(0.0));
usesMockAnimation += EXPECT_CALL(*mockAnimationPtr, setAlternatesDirection(false)); usesMockAnimation += EXPECT_CALL(*mockAnimationPtr, setDirection(blink::WebCompositorAnimation::DirectionNormal));
EXPECT_CALL(*mockAnimationPtr, delete_()) EXPECT_CALL(*mockAnimationPtr, delete_())
.Times(1) .Times(1)
...@@ -660,7 +657,7 @@ TEST_F(AnimationCompositorAnimationsTest, createSimpleOpacityAnimationDuration) ...@@ -660,7 +657,7 @@ TEST_F(AnimationCompositorAnimationsTest, createSimpleOpacityAnimationDuration)
usesMockAnimation += EXPECT_CALL(*mockAnimationPtr, setIterations(1)); usesMockAnimation += EXPECT_CALL(*mockAnimationPtr, setIterations(1));
usesMockAnimation += EXPECT_CALL(*mockAnimationPtr, setTimeOffset(0.0)); usesMockAnimation += EXPECT_CALL(*mockAnimationPtr, setTimeOffset(0.0));
usesMockAnimation += EXPECT_CALL(*mockAnimationPtr, setAlternatesDirection(false)); usesMockAnimation += EXPECT_CALL(*mockAnimationPtr, setDirection(blink::WebCompositorAnimation::DirectionNormal));
EXPECT_CALL(*mockAnimationPtr, delete_()) EXPECT_CALL(*mockAnimationPtr, delete_())
.Times(1) .Times(1)
...@@ -713,7 +710,7 @@ TEST_F(AnimationCompositorAnimationsTest, createMultipleKeyframeOpacityAnimation ...@@ -713,7 +710,7 @@ TEST_F(AnimationCompositorAnimationsTest, createMultipleKeyframeOpacityAnimation
usesMockAnimation += EXPECT_CALL(*mockAnimationPtr, setIterations(5)); usesMockAnimation += EXPECT_CALL(*mockAnimationPtr, setIterations(5));
usesMockAnimation += EXPECT_CALL(*mockAnimationPtr, setTimeOffset(0.0)); usesMockAnimation += EXPECT_CALL(*mockAnimationPtr, setTimeOffset(0.0));
usesMockAnimation += EXPECT_CALL(*mockAnimationPtr, setAlternatesDirection(true)); usesMockAnimation += EXPECT_CALL(*mockAnimationPtr, setDirection(blink::WebCompositorAnimation::DirectionAlternate));
EXPECT_CALL(*mockAnimationPtr, delete_()) EXPECT_CALL(*mockAnimationPtr, delete_())
.Times(1) .Times(1)
...@@ -762,7 +759,7 @@ TEST_F(AnimationCompositorAnimationsTest, createSimpleOpacityAnimationStartDelay ...@@ -762,7 +759,7 @@ TEST_F(AnimationCompositorAnimationsTest, createSimpleOpacityAnimationStartDelay
usesMockAnimation += EXPECT_CALL(*mockAnimationPtr, setIterations(5)); usesMockAnimation += EXPECT_CALL(*mockAnimationPtr, setIterations(5));
usesMockAnimation += EXPECT_CALL(*mockAnimationPtr, setTimeOffset(-3.25)); usesMockAnimation += EXPECT_CALL(*mockAnimationPtr, setTimeOffset(-3.25));
usesMockAnimation += EXPECT_CALL(*mockAnimationPtr, setAlternatesDirection(false)); usesMockAnimation += EXPECT_CALL(*mockAnimationPtr, setDirection(blink::WebCompositorAnimation::DirectionNormal));
EXPECT_CALL(*mockAnimationPtr, delete_()) EXPECT_CALL(*mockAnimationPtr, delete_())
.Times(1) .Times(1)
...@@ -821,7 +818,7 @@ TEST_F(AnimationCompositorAnimationsTest, createMultipleKeyframeOpacityAnimation ...@@ -821,7 +818,7 @@ TEST_F(AnimationCompositorAnimationsTest, createMultipleKeyframeOpacityAnimation
usesMockAnimation += EXPECT_CALL(*mockAnimationPtr, setIterations(10)); usesMockAnimation += EXPECT_CALL(*mockAnimationPtr, setIterations(10));
usesMockAnimation += EXPECT_CALL(*mockAnimationPtr, setTimeOffset(0.0)); usesMockAnimation += EXPECT_CALL(*mockAnimationPtr, setTimeOffset(0.0));
usesMockAnimation += EXPECT_CALL(*mockAnimationPtr, setAlternatesDirection(true)); usesMockAnimation += EXPECT_CALL(*mockAnimationPtr, setDirection(blink::WebCompositorAnimation::DirectionAlternate));
EXPECT_CALL(*mockAnimationPtr, delete_()) EXPECT_CALL(*mockAnimationPtr, delete_())
.Times(1) .Times(1)
...@@ -867,10 +864,10 @@ TEST_F(AnimationCompositorAnimationsTest, createReversedOpacityAnimation) ...@@ -867,10 +864,10 @@ TEST_F(AnimationCompositorAnimationsTest, createReversedOpacityAnimation)
EXPECT_CALL(mockCompositor, createFloatAnimationCurve()) EXPECT_CALL(mockCompositor, createFloatAnimationCurve())
.WillOnce(Return(mockCurvePtr)); .WillOnce(Return(mockCurvePtr));
usesMockCurve += EXPECT_CALL(*mockCurvePtr, add(WebFloatKeyframe(0.0, 5.0), 1.0, 0.0, 1.0, 1.0)); usesMockCurve += EXPECT_CALL(*mockCurvePtr, add(blink::WebFloatKeyframe(0.0, 2.0), blink::WebCompositorAnimationCurve::TimingFunctionTypeEaseIn));
usesMockCurve += EXPECT_CALL(*mockCurvePtr, add(WebFloatKeyframe(0.5, 20.0), WebCompositorAnimationCurve::TimingFunctionTypeLinear)); usesMockCurve += EXPECT_CALL(*mockCurvePtr, add(blink::WebFloatKeyframe(0.25, -1.0), blink::WebCompositorAnimationCurve::TimingFunctionTypeLinear));
usesMockCurve += EXPECT_CALL(*mockCurvePtr, add(WebFloatKeyframe(0.75, -1.0), WebCompositorAnimationCurve::TimingFunctionTypeEaseOut)); usesMockCurve += EXPECT_CALL(*mockCurvePtr, add(blink::WebFloatKeyframe(0.5, 20.0), 0.0, 0.0, 0.0, 1.0));
usesMockCurve += EXPECT_CALL(*mockCurvePtr, add(WebFloatKeyframe(1.0, 2.0))); usesMockCurve += EXPECT_CALL(*mockCurvePtr, add(blink::WebFloatKeyframe(1.0, 5.0)));
// Create the animation // Create the animation
WebCompositorAnimationMock* mockAnimationPtr = new WebCompositorAnimationMock(WebCompositorAnimation::TargetPropertyOpacity); WebCompositorAnimationMock* mockAnimationPtr = new WebCompositorAnimationMock(WebCompositorAnimation::TargetPropertyOpacity);
...@@ -881,7 +878,7 @@ TEST_F(AnimationCompositorAnimationsTest, createReversedOpacityAnimation) ...@@ -881,7 +878,7 @@ TEST_F(AnimationCompositorAnimationsTest, createReversedOpacityAnimation)
usesMockAnimation += EXPECT_CALL(*mockAnimationPtr, setIterations(10)); usesMockAnimation += EXPECT_CALL(*mockAnimationPtr, setIterations(10));
usesMockAnimation += EXPECT_CALL(*mockAnimationPtr, setTimeOffset(0.0)); usesMockAnimation += EXPECT_CALL(*mockAnimationPtr, setTimeOffset(0.0));
usesMockAnimation += EXPECT_CALL(*mockAnimationPtr, setAlternatesDirection(true)); usesMockAnimation += EXPECT_CALL(*mockAnimationPtr, setDirection(blink::WebCompositorAnimation::DirectionAlternateReverse));
EXPECT_CALL(*mockAnimationPtr, delete_()) EXPECT_CALL(*mockAnimationPtr, delete_())
.Times(1) .Times(1)
...@@ -919,8 +916,8 @@ TEST_F(AnimationCompositorAnimationsTest, createReversedOpacityAnimationNegative ...@@ -919,8 +916,8 @@ TEST_F(AnimationCompositorAnimationsTest, createReversedOpacityAnimationNegative
EXPECT_CALL(mockCompositor, createFloatAnimationCurve()) EXPECT_CALL(mockCompositor, createFloatAnimationCurve())
.WillOnce(Return(mockCurvePtr)); .WillOnce(Return(mockCurvePtr));
usesMockCurve += EXPECT_CALL(*mockCurvePtr, add(WebFloatKeyframe(0.0, 5.0), WebCompositorAnimationCurve::TimingFunctionTypeLinear)); usesMockCurve += EXPECT_CALL(*mockCurvePtr, add(blink::WebFloatKeyframe(0.0, 2.0), blink::WebCompositorAnimationCurve::TimingFunctionTypeLinear));
usesMockCurve += EXPECT_CALL(*mockCurvePtr, add(WebFloatKeyframe(1.5, 2.0))); usesMockCurve += EXPECT_CALL(*mockCurvePtr, add(blink::WebFloatKeyframe(1.5, 5.0)));
// Create animation // Create animation
WebCompositorAnimationMock* mockAnimationPtr = new WebCompositorAnimationMock(WebCompositorAnimation::TargetPropertyOpacity); WebCompositorAnimationMock* mockAnimationPtr = new WebCompositorAnimationMock(WebCompositorAnimation::TargetPropertyOpacity);
...@@ -931,7 +928,7 @@ TEST_F(AnimationCompositorAnimationsTest, createReversedOpacityAnimationNegative ...@@ -931,7 +928,7 @@ TEST_F(AnimationCompositorAnimationsTest, createReversedOpacityAnimationNegative
usesMockAnimation += EXPECT_CALL(*mockAnimationPtr, setIterations(5)); usesMockAnimation += EXPECT_CALL(*mockAnimationPtr, setIterations(5));
usesMockAnimation += EXPECT_CALL(*mockAnimationPtr, setTimeOffset(3.0)); usesMockAnimation += EXPECT_CALL(*mockAnimationPtr, setTimeOffset(3.0));
usesMockAnimation += EXPECT_CALL(*mockAnimationPtr, setAlternatesDirection(true)); usesMockAnimation += EXPECT_CALL(*mockAnimationPtr, setDirection(blink::WebCompositorAnimation::DirectionAlternateReverse));
EXPECT_CALL(*mockAnimationPtr, delete_()) EXPECT_CALL(*mockAnimationPtr, delete_())
.Times(1) .Times(1)
......
...@@ -85,8 +85,8 @@ public: ...@@ -85,8 +85,8 @@ public:
MOCK_CONST_METHOD0(timeOffset, double()); MOCK_CONST_METHOD0(timeOffset, double());
MOCK_METHOD1(setTimeOffset, void(double)); MOCK_METHOD1(setTimeOffset, void(double));
MOCK_CONST_METHOD0(alternatesDirection, bool()); MOCK_CONST_METHOD0(direction, Direction());
MOCK_METHOD1(setAlternatesDirection, void(bool)); MOCK_METHOD1(setDirection, void(Direction));
MOCK_METHOD0(delete_, void()); MOCK_METHOD0(delete_, void());
~WebCompositorAnimationMock() { delete_(); } ~WebCompositorAnimationMock() { delete_(); }
......
/*
* Copyright (c) 2013, Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "core/animation/CompositorAnimations.h"
#include "wtf/PassRefPtr.h"
#include "wtf/RefPtr.h"
#include <gmock/gmock.h>
#include <gtest/gtest.h>
// FIXME: Remove once https://codereview.chromium.org/50603011/ lands.
#define EXPECT_REFV_EQ(a, b) EXPECT_EQ(*(a.get()), *(b.get()))
#define EXPECT_REFV_NE(a, b) EXPECT_NE(*(a.get()), *(b.get()))
namespace {
using namespace blink;
class AnimationCompositorAnimationsTimingFunctionReverserTest : public ::testing::Test {
protected:
public:
PassRefPtr<TimingFunction> reverse(const RefPtr<TimingFunction>& timefunc)
{
return CompositorAnimationsTimingFunctionReverser::reverse(*timefunc);
}
};
TEST_F(AnimationCompositorAnimationsTimingFunctionReverserTest, LinearReverse)
{
RefPtr<TimingFunction> linearTiming = LinearTimingFunction::shared();
EXPECT_REFV_EQ(linearTiming, reverse(linearTiming));
}
TEST_F(AnimationCompositorAnimationsTimingFunctionReverserTest, CubicReverse)
{
RefPtr<TimingFunction> cubicEaseInTiming = CubicBezierTimingFunction::preset(CubicBezierTimingFunction::EaseIn);
RefPtr<TimingFunction> cubicEaseOutTiming = CubicBezierTimingFunction::preset(CubicBezierTimingFunction::EaseOut);
RefPtr<TimingFunction> cubicEaseInOutTiming = CubicBezierTimingFunction::preset(CubicBezierTimingFunction::EaseInOut);
EXPECT_REFV_EQ(cubicEaseOutTiming, reverse(cubicEaseInTiming));
EXPECT_REFV_EQ(cubicEaseInTiming, reverse(cubicEaseOutTiming));
EXPECT_REFV_EQ(cubicEaseInOutTiming, reverse(cubicEaseInOutTiming));
RefPtr<TimingFunction> cubicCustomTiming = CubicBezierTimingFunction::create(0.17, 0.67, 1, -1.73);
// Due to floating point, 1.0-(-1.73) != 2.73
RefPtr<TimingFunction> cubicCustomTimingReversed = CubicBezierTimingFunction::create(0, 1.0 - (-1.73), 1.0 - 0.17, 1.0 - 0.67);
EXPECT_REFV_EQ(cubicCustomTimingReversed, reverse(cubicCustomTiming));
RefPtr<TimingFunction> cubicEaseTiming = CubicBezierTimingFunction::preset(CubicBezierTimingFunction::Ease);
RefPtr<TimingFunction> cubicEaseTimingReversed = CubicBezierTimingFunction::create(1.0 - 0.25, 0.0, 1.0 - 0.25, 1.0 - 0.1);
EXPECT_REFV_EQ(cubicEaseTimingReversed, reverse(cubicEaseTiming));
}
} // namespace
...@@ -3446,7 +3446,6 @@ ...@@ -3446,7 +3446,6 @@
'animation/AnimationTranslationUtilTest.cpp', 'animation/AnimationTranslationUtilTest.cpp',
'animation/CompositorAnimationsTest.cpp', 'animation/CompositorAnimationsTest.cpp',
'animation/CompositorAnimationsTestHelper.h', 'animation/CompositorAnimationsTestHelper.h',
'animation/CompositorAnimationsTimingFunctionReverserTest.cpp',
'animation/EffectInputTest.cpp', 'animation/EffectInputTest.cpp',
'animation/InterpolableValueTest.cpp', 'animation/InterpolableValueTest.cpp',
'animation/InterpolationEffectTest.cpp', 'animation/InterpolationEffectTest.cpp',
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#define WebCompositorAnimation_h #define WebCompositorAnimation_h
#define WEB_ANIMATION_SUPPORTS_FRACTIONAL_ITERATIONS 1 #define WEB_ANIMATION_SUPPORTS_FRACTIONAL_ITERATIONS 1
#define WEB_ANIMATION_SUPPORTS_FULL_DIRECTION 1
namespace blink { namespace blink {
...@@ -19,6 +20,13 @@ public: ...@@ -19,6 +20,13 @@ public:
TargetPropertyScrollOffset TargetPropertyScrollOffset
}; };
enum Direction {
DirectionNormal = 0,
DirectionReverse,
DirectionAlternate,
DirectionAlternateReverse
};
virtual ~WebCompositorAnimation() { } virtual ~WebCompositorAnimation() { }
// An id is effectively the animation's name, and it is not unique. // An id is effectively the animation's name, and it is not unique.
...@@ -38,9 +46,8 @@ public: ...@@ -38,9 +46,8 @@ public:
virtual double timeOffset() const = 0; virtual double timeOffset() const = 0;
virtual void setTimeOffset(double monotonicTime) = 0; virtual void setTimeOffset(double monotonicTime) = 0;
// If alternatesDirection is true, on odd numbered iterations we reverse the curve. virtual Direction direction() const = 0;
virtual bool alternatesDirection() const = 0; virtual void setDirection(Direction) = 0;
virtual void setAlternatesDirection(bool) = 0;
}; };
} // namespace blink } // namespace blink
......
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