Commit fd51a7c0 authored by shans@chromium.org's avatar shans@chromium.org

Web Animations: Add Interpolation class.

This patch introduces the Interpolation class, which represents
a primitive animation between two values (expressed as InterpolableValues).

This is part of an effort to refactor the animations pipeline in order
to make it generic on animation value type (see linked master bug).

This code is not yet used anywhere. It will be used in future patches.

BUG=346495

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

git-svn-id: svn://svn.chromium.org/blink/trunk@168629 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent 0a712811
...@@ -22,10 +22,7 @@ public: ...@@ -22,10 +22,7 @@ public:
private: private:
virtual PassOwnPtr<InterpolableValue> interpolate(const InterpolableValue &to, const double progress) const = 0; virtual PassOwnPtr<InterpolableValue> interpolate(const InterpolableValue &to, const double progress) const = 0;
// TODO: Replace this with Interpolation when committing Interpolation friend class Interpolation;
// patch. Refactor InterpolableValueTest to test via Interpolation
// interface.
friend class AnimationInterpolableValueTest;
// Keep interpolate private, but allow calls within the hierarchy without // Keep interpolate private, but allow calls within the hierarchy without
// knowledge of type. // knowledge of type.
...@@ -99,6 +96,7 @@ public: ...@@ -99,6 +96,7 @@ public:
ASSERT(position < m_size); ASSERT(position < m_size);
return m_values.get()[position].get(); return m_values.get()[position].get();
} }
size_t length() const { return m_size; }
virtual PassOwnPtr<InterpolableValue> clone() const OVERRIDE FINAL { return create(*this); } virtual PassOwnPtr<InterpolableValue> clone() const OVERRIDE FINAL { return create(*this); }
private: private:
......
...@@ -5,27 +5,38 @@ ...@@ -5,27 +5,38 @@
#include "config.h" #include "config.h"
#include "core/animation/InterpolableValue.h" #include "core/animation/InterpolableValue.h"
#include "core/animation/Interpolation.h"
#include <gtest/gtest.h> #include <gtest/gtest.h>
namespace WebCore { namespace WebCore {
class AnimationInterpolableValueTest : public ::testing::Test { class AnimationInterpolableValueTest : public ::testing::Test {
protected: protected:
InterpolableValue* interpolationValue(Interpolation& interpolation)
{
return interpolation.getCachedValueForTesting();
}
double interpolateNumbers(double a, double b, double progress) double interpolateNumbers(double a, double b, double progress)
{ {
OwnPtr<InterpolableValue> aVal = static_pointer_cast<InterpolableValue>(InterpolableNumber::create(a)); RefPtr<Interpolation> i = Interpolation::create(InterpolableNumber::create(a), InterpolableNumber::create(b));
return toInterpolableNumber(aVal->interpolate(*InterpolableNumber::create(b).get(), progress).get())->value(); i->interpolate(progress);
return toInterpolableNumber(interpolationValue(*i.get()))->value();
} }
double interpolateBools(bool a, bool b, double progress) bool interpolateBools(bool a, bool b, double progress)
{ {
OwnPtr<InterpolableValue> aVal = static_pointer_cast<InterpolableValue>(InterpolableBool::create(a)); RefPtr<Interpolation> i = Interpolation::create(InterpolableBool::create(a), InterpolableBool::create(b));
return toInterpolableBool(aVal->interpolate(*InterpolableBool::create(b).get(), progress).get())->value(); i->interpolate(progress);
return toInterpolableBool(interpolationValue(*i.get()))->value();
} }
PassOwnPtr<InterpolableValue> interpolateLists(PassOwnPtr<InterpolableList> listA, PassOwnPtr<InterpolableList> listB, double progress) PassRefPtr<Interpolation> interpolateLists(PassOwnPtr<InterpolableList> listA, PassOwnPtr<InterpolableList> listB, double progress)
{ {
return static_pointer_cast<InterpolableValue>(listA)->interpolate(*listB.get(), progress); RefPtr<Interpolation> i = Interpolation::create(listA, listB);
i->interpolate(progress);
return i;
} }
}; };
...@@ -61,8 +72,8 @@ TEST_F(AnimationInterpolableValueTest, SimpleList) ...@@ -61,8 +72,8 @@ TEST_F(AnimationInterpolableValueTest, SimpleList)
listB->set(1, InterpolableNumber::create(-200)); listB->set(1, InterpolableNumber::create(-200));
listB->set(2, InterpolableNumber::create(300)); listB->set(2, InterpolableNumber::create(300));
OwnPtr<InterpolableValue> result = interpolateLists(listA.release(), listB.release(), 0.3); RefPtr<Interpolation> i = interpolateLists(listA.release(), listB.release(), 0.3);
InterpolableList* outList = toInterpolableList(result.get()); InterpolableList* outList = toInterpolableList(interpolationValue(*i.get()));
EXPECT_FLOAT_EQ(30, toInterpolableNumber(outList->get(0))->value()); EXPECT_FLOAT_EQ(30, toInterpolableNumber(outList->get(0))->value());
EXPECT_FLOAT_EQ(-30.6f, toInterpolableNumber(outList->get(1))->value()); EXPECT_FLOAT_EQ(-30.6f, toInterpolableNumber(outList->get(1))->value());
EXPECT_FLOAT_EQ(104.35f, toInterpolableNumber(outList->get(2))->value()); EXPECT_FLOAT_EQ(104.35f, toInterpolableNumber(outList->get(2))->value());
...@@ -84,8 +95,8 @@ TEST_F(AnimationInterpolableValueTest, NestedList) ...@@ -84,8 +95,8 @@ TEST_F(AnimationInterpolableValueTest, NestedList)
listB->set(1, subListB.release()); listB->set(1, subListB.release());
listB->set(2, InterpolableBool::create(true)); listB->set(2, InterpolableBool::create(true));
OwnPtr<InterpolableValue> result = interpolateLists(listA.release(), listB.release(), 0.5); RefPtr<Interpolation> i = interpolateLists(listA.release(), listB.release(), 0.5);
InterpolableList* outList = toInterpolableList(result.get()); InterpolableList* outList = toInterpolableList(interpolationValue(*i.get()));
EXPECT_FLOAT_EQ(50, toInterpolableNumber(outList->get(0))->value()); EXPECT_FLOAT_EQ(50, toInterpolableNumber(outList->get(0))->value());
EXPECT_FLOAT_EQ(75, toInterpolableNumber(toInterpolableList(outList->get(1))->get(0))->value()); EXPECT_FLOAT_EQ(75, toInterpolableNumber(toInterpolableList(outList->get(1))->get(0))->value());
EXPECT_TRUE(toInterpolableBool(outList->get(2))->value()); EXPECT_TRUE(toInterpolableBool(outList->get(2))->value());
......
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "config.h"
#include "core/animation/Interpolation.h"
namespace WebCore {
namespace {
bool typesMatch(const InterpolableValue* start, const InterpolableValue* end)
{
if (start->isNumber())
return end->isNumber();
if (start->isBool())
return end->isBool();
if (!(start->isList() && end->isList()))
return false;
const InterpolableList* startList = toInterpolableList(start);
const InterpolableList* endList = toInterpolableList(end);
if (startList->length() != endList->length())
return false;
for (size_t i = 0; i < startList->length(); ++i) {
if (!typesMatch(startList->get(i), endList->get(i)))
return false;
}
return true;
}
}
Interpolation::Interpolation(PassOwnPtr<InterpolableValue> start, PassOwnPtr<InterpolableValue> end)
: m_start(start)
, m_end(end)
, m_cachedFraction(0)
, m_cachedValue(m_start->clone())
{
RELEASE_ASSERT(typesMatch(m_start.get(), m_end.get()));
}
void Interpolation::interpolate(double fraction) const
{
if (m_cachedFraction != fraction) {
m_cachedValue = m_start->interpolate(*m_end, fraction);
m_cachedFraction = fraction;
}
}
}
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef Interpolation_h
#define Interpolation_h
#include "core/animation/InterpolableValue.h"
#include "core/css/resolver/StyleResolverState.h"
#include "wtf/RefCounted.h"
namespace WebCore {
class Interpolation : public RefCounted<Interpolation> {
public:
static PassRefPtr<Interpolation> create(PassOwnPtr<InterpolableValue> start, PassOwnPtr<InterpolableValue> end)
{
return adoptRef(new Interpolation(start, end));
}
void interpolate(double fraction) const;
protected:
const OwnPtr<InterpolableValue> m_start;
const OwnPtr<InterpolableValue> m_end;
mutable double m_cachedFraction;
mutable OwnPtr<InterpolableValue> m_cachedValue;
Interpolation(PassOwnPtr<InterpolableValue> start, PassOwnPtr<InterpolableValue> end);
private:
InterpolableValue* getCachedValueForTesting() const { return m_cachedValue.get(); }
friend class AnimationInterpolableValueTest;
};
class StyleInterpolation : public Interpolation {
public:
// 1) convert m_cachedValue into an X
// 2) shove X into StyleResolverState
// X can be:
// (1) a CSSValue (and applied via StyleBuilder::applyProperty)
// (2) an AnimatableValue (and applied via // AnimatedStyleBuilder::applyProperty)
// (3) a custom value that is inserted directly into the StyleResolverState.
virtual void apply(StyleResolverState&) = 0;
protected:
CSSPropertyID m_id;
StyleInterpolation(PassOwnPtr<InterpolableValue> start, PassOwnPtr<InterpolableValue> end, CSSPropertyID id)
: Interpolation(start, end)
, m_id(id)
{ }
};
}
#endif
...@@ -595,6 +595,8 @@ ...@@ -595,6 +595,8 @@
'animation/EffectInput.h', 'animation/EffectInput.h',
'animation/InertAnimation.cpp', 'animation/InertAnimation.cpp',
'animation/InertAnimation.h', 'animation/InertAnimation.h',
'animation/Interpolation.cpp',
'animation/Interpolation.h',
'animation/InterpolableValue.cpp', 'animation/InterpolableValue.cpp',
'animation/InterpolableValue.h', 'animation/InterpolableValue.h',
'animation/KeyframeEffectModel.cpp', 'animation/KeyframeEffectModel.cpp',
......
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