
Ding, dong... BUG=154451 Review URL: https://chromiumcodereview.appspot.com/11410021 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@167071 0039d316-1c4b-4281-b951-d872f2087c98
145 lines
3.7 KiB
C++
145 lines
3.7 KiB
C++
// Copyright 2012 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 "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 {
|
|
|
|
// 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 {
|
|
|
|
TimingFunction::TimingFunction()
|
|
{
|
|
}
|
|
|
|
TimingFunction::~TimingFunction()
|
|
{
|
|
}
|
|
|
|
double TimingFunction::duration() const
|
|
{
|
|
return 1.0;
|
|
}
|
|
|
|
scoped_ptr<CubicBezierTimingFunction> CubicBezierTimingFunction::create(double x1, double y1, double x2, double y2)
|
|
{
|
|
return make_scoped_ptr(new CubicBezierTimingFunction(x1, y1, x2, y2));
|
|
}
|
|
|
|
CubicBezierTimingFunction::CubicBezierTimingFunction(double x1, double y1, double x2, double y2)
|
|
: m_x1(SkDoubleToScalar(x1))
|
|
, m_y1(SkDoubleToScalar(y1))
|
|
, m_x2(SkDoubleToScalar(x2))
|
|
, m_y2(SkDoubleToScalar(y2))
|
|
{
|
|
}
|
|
|
|
CubicBezierTimingFunction::~CubicBezierTimingFunction()
|
|
{
|
|
}
|
|
|
|
float CubicBezierTimingFunction::getValue(double x) const
|
|
{
|
|
SkScalar value = SkUnitCubicInterp(m_x1, m_y1, m_x2, m_y2, x);
|
|
return SkScalarToFloat(value);
|
|
}
|
|
|
|
scoped_ptr<AnimationCurve> CubicBezierTimingFunction::clone() const
|
|
{
|
|
return make_scoped_ptr(new CubicBezierTimingFunction(*this)).PassAs<AnimationCurve>();
|
|
}
|
|
|
|
// These numbers come from http://www.w3.org/TR/css3-transitions/#transition-timing-function_tag.
|
|
scoped_ptr<TimingFunction> EaseTimingFunction::create()
|
|
{
|
|
return CubicBezierTimingFunction::create(0.25, 0.1, 0.25, 1).PassAs<TimingFunction>();
|
|
}
|
|
|
|
scoped_ptr<TimingFunction> EaseInTimingFunction::create()
|
|
{
|
|
return CubicBezierTimingFunction::create(0.42, 0, 1.0, 1).PassAs<TimingFunction>();
|
|
}
|
|
|
|
scoped_ptr<TimingFunction> EaseOutTimingFunction::create()
|
|
{
|
|
return CubicBezierTimingFunction::create(0, 0, 0.58, 1).PassAs<TimingFunction>();
|
|
}
|
|
|
|
scoped_ptr<TimingFunction> EaseInOutTimingFunction::create()
|
|
{
|
|
return CubicBezierTimingFunction::create(0.42, 0, 0.58, 1).PassAs<TimingFunction>();
|
|
}
|
|
|
|
} // namespace cc
|