Supply CSS transition easing when creating keyframes for CSS transitions

Linear easing was being supplied instead of the timing function specified by the user.

Example for testing: http://jsbin.com/sihif/1/quiet

Cubic bezier keyframe easings were being calculated without knowledge of the iteration duration. This led to inconsistency in the accuracy being requested.

We now always use the iteration duration when choosing the accuracy for timing function evaluation.

Without this, the transitions layout tests opacity-transform-transitions-inside-iframe.html and
cubic-bezier-overflow-length.html would have needed rebaselining.

BUG=352919

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

git-svn-id: svn://svn.chromium.org/blink/trunk@169897 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent f95a9b26
...@@ -127,7 +127,7 @@ void Animation::applyEffects(bool previouslyInEffect) ...@@ -127,7 +127,7 @@ void Animation::applyEffects(bool previouslyInEffect)
double iteration = currentIteration(); double iteration = currentIteration();
ASSERT(iteration >= 0); ASSERT(iteration >= 0);
// FIXME: Handle iteration values which overflow int. // FIXME: Handle iteration values which overflow int.
m_activeInterpolations = m_effect->sample(static_cast<int>(iteration), timeFraction()); m_activeInterpolations = m_effect->sample(static_cast<int>(iteration), timeFraction(), duration());
if (player()) if (player())
m_target->setNeedsAnimationStyleRecalc(); m_target->setNeedsAnimationStyleRecalc();
} }
......
...@@ -49,7 +49,7 @@ public: ...@@ -49,7 +49,7 @@ public:
}; };
virtual ~AnimationEffect() { } virtual ~AnimationEffect() { }
virtual PassOwnPtr<Vector<RefPtr<Interpolation> > > sample(int iteration, double fraction) const = 0; virtual PassOwnPtr<Vector<RefPtr<Interpolation> > > sample(int iteration, double fraction, double iterationDuration) const = 0;
virtual bool affects(CSSPropertyID) { return false; }; virtual bool affects(CSSPropertyID) { return false; };
virtual bool isKeyframeEffectModel() const { return false; } virtual bool isKeyframeEffectModel() const { return false; }
......
...@@ -55,7 +55,7 @@ PassOwnPtr<Vector<RefPtr<Interpolation> > > InertAnimation::sample() ...@@ -55,7 +55,7 @@ PassOwnPtr<Vector<RefPtr<Interpolation> > > InertAnimation::sample()
double iteration = currentIteration(); double iteration = currentIteration();
ASSERT(iteration >= 0); ASSERT(iteration >= 0);
// FIXME: Handle iteration values which overflow int. // FIXME: Handle iteration values which overflow int.
return m_effect->sample(static_cast<int>(iteration), timeFraction()); return m_effect->sample(static_cast<int>(iteration), timeFraction(), duration());
} }
......
...@@ -7,11 +7,7 @@ ...@@ -7,11 +7,7 @@
namespace WebCore { namespace WebCore {
namespace { PassOwnPtr<Vector<RefPtr<Interpolation> > > InterpolationEffect::getActiveInterpolations(double fraction, double iterationDuration) const
const double accuracyForKeyframeEasing = 0.0000001;
}
PassOwnPtr<Vector<RefPtr<Interpolation> > > InterpolationEffect::getActiveInterpolations(double fraction) const
{ {
Vector<RefPtr<Interpolation> >* result = new Vector<RefPtr<Interpolation> >(); Vector<RefPtr<Interpolation> >* result = new Vector<RefPtr<Interpolation> >();
...@@ -22,7 +18,7 @@ PassOwnPtr<Vector<RefPtr<Interpolation> > > InterpolationEffect::getActiveInterp ...@@ -22,7 +18,7 @@ PassOwnPtr<Vector<RefPtr<Interpolation> > > InterpolationEffect::getActiveInterp
RefPtr<Interpolation> interpolation = record->m_interpolation; RefPtr<Interpolation> interpolation = record->m_interpolation;
double localFraction = (fraction - record->m_start) / (record->m_end - record->m_start); double localFraction = (fraction - record->m_start) / (record->m_end - record->m_start);
if (record->m_easing) if (record->m_easing)
localFraction = record->m_easing->evaluate(localFraction, accuracyForKeyframeEasing); localFraction = record->m_easing->evaluate(localFraction, accuracyForDuration(iterationDuration));
interpolation->interpolate(0, localFraction); interpolation->interpolate(0, localFraction);
result->append(interpolation); result->append(interpolation);
} }
......
...@@ -17,7 +17,7 @@ class InterpolationEffect : public RefCounted<InterpolationEffect> { ...@@ -17,7 +17,7 @@ class InterpolationEffect : public RefCounted<InterpolationEffect> {
public: public:
static PassRefPtr<InterpolationEffect> create() { return adoptRef(new InterpolationEffect()); } static PassRefPtr<InterpolationEffect> create() { return adoptRef(new InterpolationEffect()); }
PassOwnPtr<Vector<RefPtr<Interpolation> > > getActiveInterpolations(double fraction) const; PassOwnPtr<Vector<RefPtr<Interpolation> > > getActiveInterpolations(double fraction, double iterationDuration) const;
void addInterpolation(PassRefPtr<Interpolation> interpolation, PassRefPtr<TimingFunction> easing, double start, double end, double applyFrom, double applyTo) void addInterpolation(PassRefPtr<Interpolation> interpolation, PassRefPtr<TimingFunction> easing, double start, double end, double applyFrom, double applyTo)
{ {
......
...@@ -7,6 +7,12 @@ ...@@ -7,6 +7,12 @@
#include <gtest/gtest.h> #include <gtest/gtest.h>
namespace {
const double duration = 1.0;
} // namespace
namespace WebCore { namespace WebCore {
class AnimationInterpolationEffectTest : public ::testing::Test { class AnimationInterpolationEffectTest : public ::testing::Test {
...@@ -28,22 +34,22 @@ TEST_F(AnimationInterpolationEffectTest, SingleInterpolation) ...@@ -28,22 +34,22 @@ TEST_F(AnimationInterpolationEffectTest, SingleInterpolation)
interpolationEffect->addInterpolation(Interpolation::create(InterpolableNumber::create(0), InterpolableNumber::create(10)), interpolationEffect->addInterpolation(Interpolation::create(InterpolableNumber::create(0), InterpolableNumber::create(10)),
RefPtr<TimingFunction>(), 0, 1, -1, 2); RefPtr<TimingFunction>(), 0, 1, -1, 2);
OwnPtr<Vector<RefPtr<Interpolation> > > activeInterpolations = interpolationEffect->getActiveInterpolations(-2); OwnPtr<Vector<RefPtr<Interpolation> > > activeInterpolations = interpolationEffect->getActiveInterpolations(-2, duration);
EXPECT_EQ(0ul, activeInterpolations->size()); EXPECT_EQ(0ul, activeInterpolations->size());
activeInterpolations = interpolationEffect->getActiveInterpolations(-0.5); activeInterpolations = interpolationEffect->getActiveInterpolations(-0.5, duration);
EXPECT_EQ(1ul, activeInterpolations->size()); EXPECT_EQ(1ul, activeInterpolations->size());
EXPECT_EQ(-5, getInterpolableNumber(activeInterpolations->at(0))); EXPECT_EQ(-5, getInterpolableNumber(activeInterpolations->at(0)));
activeInterpolations = interpolationEffect->getActiveInterpolations(0.5); activeInterpolations = interpolationEffect->getActiveInterpolations(0.5, duration);
EXPECT_EQ(1ul, activeInterpolations->size()); EXPECT_EQ(1ul, activeInterpolations->size());
EXPECT_FLOAT_EQ(5, getInterpolableNumber(activeInterpolations->at(0))); EXPECT_FLOAT_EQ(5, getInterpolableNumber(activeInterpolations->at(0)));
activeInterpolations = interpolationEffect->getActiveInterpolations(1.5); activeInterpolations = interpolationEffect->getActiveInterpolations(1.5, duration);
EXPECT_EQ(1ul, activeInterpolations->size()); EXPECT_EQ(1ul, activeInterpolations->size());
EXPECT_FLOAT_EQ(15, getInterpolableNumber(activeInterpolations->at(0))); EXPECT_FLOAT_EQ(15, getInterpolableNumber(activeInterpolations->at(0)));
activeInterpolations = interpolationEffect->getActiveInterpolations(3); activeInterpolations = interpolationEffect->getActiveInterpolations(3, duration);
EXPECT_EQ(0ul, activeInterpolations->size()); EXPECT_EQ(0ul, activeInterpolations->size());
} }
...@@ -57,28 +63,33 @@ TEST_F(AnimationInterpolationEffectTest, MultipleInterpolations) ...@@ -57,28 +63,33 @@ TEST_F(AnimationInterpolationEffectTest, MultipleInterpolations)
interpolationEffect->addInterpolation(Interpolation::create(InterpolableNumber::create(1), InterpolableNumber::create(6)), interpolationEffect->addInterpolation(Interpolation::create(InterpolableNumber::create(1), InterpolableNumber::create(6)),
CubicBezierTimingFunction::preset(CubicBezierTimingFunction::Ease), 0.5, 1.5, 0.5, 1.5); CubicBezierTimingFunction::preset(CubicBezierTimingFunction::Ease), 0.5, 1.5, 0.5, 1.5);
OwnPtr<Vector<RefPtr<Interpolation> > > activeInterpolations = interpolationEffect->getActiveInterpolations(-0.5); OwnPtr<Vector<RefPtr<Interpolation> > > activeInterpolations = interpolationEffect->getActiveInterpolations(-0.5, duration);
EXPECT_EQ(0ul, activeInterpolations->size()); EXPECT_EQ(0ul, activeInterpolations->size());
activeInterpolations = interpolationEffect->getActiveInterpolations(0); activeInterpolations = interpolationEffect->getActiveInterpolations(0, duration);
EXPECT_EQ(1ul, activeInterpolations->size()); EXPECT_EQ(1ul, activeInterpolations->size());
EXPECT_FLOAT_EQ(0, getInterpolableNumber(activeInterpolations->at(0))); EXPECT_FLOAT_EQ(0, getInterpolableNumber(activeInterpolations->at(0)));
activeInterpolations = interpolationEffect->getActiveInterpolations(0.5); activeInterpolations = interpolationEffect->getActiveInterpolations(0.5, duration);
EXPECT_EQ(2ul, activeInterpolations->size()); EXPECT_EQ(2ul, activeInterpolations->size());
EXPECT_FLOAT_EQ(0.5f, getInterpolableNumber(activeInterpolations->at(0))); EXPECT_FLOAT_EQ(0.5f, getInterpolableNumber(activeInterpolations->at(0)));
EXPECT_FLOAT_EQ(1, getInterpolableNumber(activeInterpolations->at(1))); EXPECT_FLOAT_EQ(1, getInterpolableNumber(activeInterpolations->at(1)));
activeInterpolations = interpolationEffect->getActiveInterpolations(1); activeInterpolations = interpolationEffect->getActiveInterpolations(1, duration);
EXPECT_EQ(2ul, activeInterpolations->size());
EXPECT_FLOAT_EQ(10, getInterpolableNumber(activeInterpolations->at(0)));
EXPECT_FLOAT_EQ(5.0282884f, getInterpolableNumber(activeInterpolations->at(1)));
activeInterpolations = interpolationEffect->getActiveInterpolations(1, duration * 1000);
EXPECT_EQ(2ul, activeInterpolations->size()); EXPECT_EQ(2ul, activeInterpolations->size());
EXPECT_FLOAT_EQ(10, getInterpolableNumber(activeInterpolations->at(0))); EXPECT_FLOAT_EQ(10, getInterpolableNumber(activeInterpolations->at(0)));
EXPECT_FLOAT_EQ(5.0120168f, getInterpolableNumber(activeInterpolations->at(1))); EXPECT_FLOAT_EQ(5.0120168f, getInterpolableNumber(activeInterpolations->at(1)));
activeInterpolations = interpolationEffect->getActiveInterpolations(1.5); activeInterpolations = interpolationEffect->getActiveInterpolations(1.5, duration);
EXPECT_EQ(1ul, activeInterpolations->size()); EXPECT_EQ(1ul, activeInterpolations->size());
EXPECT_FLOAT_EQ(12.5f, getInterpolableNumber(activeInterpolations->at(0))); EXPECT_FLOAT_EQ(12.5f, getInterpolableNumber(activeInterpolations->at(0)));
activeInterpolations = interpolationEffect->getActiveInterpolations(2); activeInterpolations = interpolationEffect->getActiveInterpolations(2, duration);
EXPECT_EQ(1ul, activeInterpolations->size()); EXPECT_EQ(1ul, activeInterpolations->size());
EXPECT_FLOAT_EQ(15, getInterpolableNumber(activeInterpolations->at(0))); EXPECT_FLOAT_EQ(15, getInterpolableNumber(activeInterpolations->at(0)));
} }
......
...@@ -117,14 +117,14 @@ PropertySet KeyframeEffectModel::properties() const ...@@ -117,14 +117,14 @@ PropertySet KeyframeEffectModel::properties() const
return result; return result;
} }
PassOwnPtr<Vector<RefPtr<Interpolation> > > KeyframeEffectModel::sample(int iteration, double fraction) const PassOwnPtr<Vector<RefPtr<Interpolation> > > KeyframeEffectModel::sample(int iteration, double fraction, double iterationDuration) const
{ {
ASSERT(iteration >= 0); ASSERT(iteration >= 0);
ASSERT(!isNull(fraction)); ASSERT(!isNull(fraction));
ensureKeyframeGroups(); ensureKeyframeGroups();
ensureInterpolationEffect(); ensureInterpolationEffect();
return m_interpolationEffect->getActiveInterpolations(fraction); return m_interpolationEffect->getActiveInterpolations(fraction, iterationDuration);
} }
KeyframeEffectModel::KeyframeVector KeyframeEffectModel::normalizedKeyframes(const KeyframeVector& keyframes) KeyframeEffectModel::KeyframeVector KeyframeEffectModel::normalizedKeyframes(const KeyframeVector& keyframes)
......
...@@ -103,7 +103,7 @@ public: ...@@ -103,7 +103,7 @@ public:
} }
// AnimationEffect implementation. // AnimationEffect implementation.
virtual PassOwnPtr<Vector<RefPtr<Interpolation> > > sample(int iteration, double fraction) const OVERRIDE; virtual PassOwnPtr<Vector<RefPtr<Interpolation> > > sample(int iteration, double fraction, double iterationDuration) const OVERRIDE;
// FIXME: Implement setFrames() // FIXME: Implement setFrames()
const KeyframeVector& getFrames() const { return m_keyframes; } const KeyframeVector& getFrames() const { return m_keyframes; }
......
...@@ -545,11 +545,19 @@ void CSSAnimations::calculateTransitionUpdateForProperty(CSSPropertyID id, const ...@@ -545,11 +545,19 @@ void CSSAnimations::calculateTransitionUpdateForProperty(CSSPropertyID id, const
if (AnimatableValue::usesDefaultInterpolation(to.get(), from.get())) if (AnimatableValue::usesDefaultInterpolation(to.get(), from.get()))
return; return;
Timing timing;
bool isPaused;
RefPtr<TimingFunction> timingFunction = timingFromAnimationData(anim, timing, isPaused);
ASSERT(!isPaused);
// Note that the backwards part is required for delay to work.
timing.fillMode = Timing::FillModeBoth;
KeyframeEffectModel::KeyframeVector keyframes; KeyframeEffectModel::KeyframeVector keyframes;
RefPtrWillBeRawPtr<Keyframe> startKeyframe = Keyframe::create(); RefPtrWillBeRawPtr<Keyframe> startKeyframe = Keyframe::create();
startKeyframe->setPropertyValue(id, from.get()); startKeyframe->setPropertyValue(id, from.get());
startKeyframe->setOffset(0); startKeyframe->setOffset(0);
startKeyframe->setEasing(timingFunction);
keyframes.append(startKeyframe); keyframes.append(startKeyframe);
RefPtrWillBeRawPtr<Keyframe> endKeyframe = Keyframe::create(); RefPtrWillBeRawPtr<Keyframe> endKeyframe = Keyframe::create();
...@@ -559,14 +567,6 @@ void CSSAnimations::calculateTransitionUpdateForProperty(CSSPropertyID id, const ...@@ -559,14 +567,6 @@ void CSSAnimations::calculateTransitionUpdateForProperty(CSSPropertyID id, const
RefPtrWillBeRawPtr<KeyframeEffectModel> effect = KeyframeEffectModel::create(keyframes); RefPtrWillBeRawPtr<KeyframeEffectModel> effect = KeyframeEffectModel::create(keyframes);
Timing timing;
bool isPaused;
RefPtr<TimingFunction> timingFunction = timingFromAnimationData(anim, timing, isPaused);
ASSERT(!isPaused);
timing.timingFunction = timingFunction;
// Note that the backwards part is required for delay to work.
timing.fillMode = Timing::FillModeBoth;
update->startTransition(id, from.get(), to.get(), InertAnimation::create(effect, timing, isPaused)); update->startTransition(id, from.get(), to.get(), InertAnimation::create(effect, timing, isPaused));
ASSERT(!element->activeAnimations() || !element->activeAnimations()->isAnimationStyleChange()); ASSERT(!element->activeAnimations() || !element->activeAnimations()->isAnimationStyleChange());
} }
......
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