| Index: cc/timing_function.cc
|
| diff --git a/cc/timing_function.cc b/cc/timing_function.cc
|
| index 6588d36d9649c51aa57bce41f1832389a638ced5..7aef57ebb9cab0d00c2385f54bb1600ec1666eb8 100644
|
| --- a/cc/timing_function.cc
|
| +++ b/cc/timing_function.cc
|
| @@ -5,10 +5,79 @@
|
| #include "config.h"
|
|
|
| #include "cc/timing_function.h"
|
| +#include "third_party/skia/include/core/SkMath.h"
|
|
|
| +// TODO(danakj) These methods come from SkInterpolator.cpp. When such a method
|
| +// is available in the public Skia API, we should switch to using that.
|
| +// http://crbug.com/159735
|
| namespace {
|
| -const double epsilon = 1e-6;
|
| -} // namespace
|
| +
|
| +// Dot14 has 14 bits for decimal places, and the remainder for whole numbers.
|
| +typedef int Dot14;
|
| +#define DOT14_ONE (1 << 14)
|
| +#define DOT14_HALF (1 << 13)
|
| +
|
| +#define Dot14ToFloat(x) ((x) / 16384.f)
|
| +
|
| +static inline Dot14 Dot14Mul(Dot14 a, Dot14 b)
|
| +{
|
| + return (a * b + DOT14_HALF) >> 14;
|
| +}
|
| +
|
| +static inline Dot14 EvalCubic(Dot14 t, Dot14 A, Dot14 B, Dot14 C)
|
| +{
|
| + return Dot14Mul(Dot14Mul(Dot14Mul(C, t) + B, t) + A, t);
|
| +}
|
| +
|
| +static inline Dot14 PinAndConvert(SkScalar x)
|
| +{
|
| + if (x <= 0)
|
| + return 0;
|
| + if (x >= SK_Scalar1)
|
| + return DOT14_ONE;
|
| + return SkScalarToFixed(x) >> 2;
|
| +}
|
| +
|
| +SkScalar SkUnitCubicInterp(SkScalar bx, SkScalar by, SkScalar cx, SkScalar cy, SkScalar value)
|
| +{
|
| + Dot14 x = PinAndConvert(value);
|
| +
|
| + if (x == 0) return 0;
|
| + if (x == DOT14_ONE) return SK_Scalar1;
|
| +
|
| + Dot14 b = PinAndConvert(bx);
|
| + Dot14 c = PinAndConvert(cx);
|
| +
|
| + // Now compute our coefficients from the control points.
|
| + // t -> 3b
|
| + // t^2 -> 3c - 6b
|
| + // t^3 -> 3b - 3c + 1
|
| + Dot14 A = 3 * b;
|
| + Dot14 B = 3 * (c - 2 * b);
|
| + Dot14 C = 3 * (b - c) + DOT14_ONE;
|
| +
|
| + // Now search for a t value given x.
|
| + Dot14 t = DOT14_HALF;
|
| + Dot14 dt = DOT14_HALF;
|
| + for (int i = 0; i < 13; i++) {
|
| + dt >>= 1;
|
| + Dot14 guess = EvalCubic(t, A, B, C);
|
| + if (x < guess)
|
| + t -= dt;
|
| + else
|
| + t += dt;
|
| + }
|
| +
|
| + // Now we have t, so compute the coefficient for Y and evaluate.
|
| + b = PinAndConvert(by);
|
| + c = PinAndConvert(cy);
|
| + A = 3 * b;
|
| + B = 3 * (c - 2 * b);
|
| + C = 3 * (b - c) + DOT14_ONE;
|
| + return SkFixedToScalar(EvalCubic(t, A, B, C) << 2);
|
| +}
|
| +
|
| +} // anonymous namespace
|
|
|
| namespace cc {
|
|
|
| @@ -31,7 +100,10 @@ scoped_ptr<CubicBezierTimingFunction> CubicBezierTimingFunction::create(double x
|
| }
|
|
|
| CubicBezierTimingFunction::CubicBezierTimingFunction(double x1, double y1, double x2, double y2)
|
| - : m_curve(x1, y1, x2, y2)
|
| + : m_x1(SkDoubleToScalar(x1))
|
| + , m_y1(SkDoubleToScalar(y1))
|
| + , m_x2(SkDoubleToScalar(x2))
|
| + , m_y2(SkDoubleToScalar(y2))
|
| {
|
| }
|
|
|
| @@ -41,8 +113,8 @@ CubicBezierTimingFunction::~CubicBezierTimingFunction()
|
|
|
| float CubicBezierTimingFunction::getValue(double x) const
|
| {
|
| - UnitBezier temp(m_curve);
|
| - return static_cast<float>(temp.solve(x, epsilon));
|
| + SkScalar value = SkUnitCubicInterp(m_x1, m_y1, m_x2, m_y2, x);
|
| + return SkScalarToFloat(value);
|
| }
|
|
|
| scoped_ptr<AnimationCurve> CubicBezierTimingFunction::clone() const
|
|
|