OLD | NEW |
1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "config.h" | 5 #include "config.h" |
6 | 6 |
7 #include "cc/timing_function.h" | 7 #include "cc/timing_function.h" |
| 8 #include "third_party/skia/include/core/SkMath.h" |
8 | 9 |
| 10 // TODO(danakj) These methods come from SkInterpolator.cpp. When such a method |
| 11 // is available in the public Skia API, we should switch to using that. |
| 12 // http://crbug.com/159735 |
9 namespace { | 13 namespace { |
10 const double epsilon = 1e-6; | 14 |
11 } // namespace | 15 // Dot14 has 14 bits for decimal places, and the remainder for whole numbers. |
| 16 typedef int Dot14; |
| 17 #define DOT14_ONE (1 << 14) |
| 18 #define DOT14_HALF (1 << 13) |
| 19 |
| 20 #define Dot14ToFloat(x) ((x) / 16384.f) |
| 21 |
| 22 static inline Dot14 Dot14Mul(Dot14 a, Dot14 b) |
| 23 { |
| 24 return (a * b + DOT14_HALF) >> 14; |
| 25 } |
| 26 |
| 27 static inline Dot14 EvalCubic(Dot14 t, Dot14 A, Dot14 B, Dot14 C) |
| 28 { |
| 29 return Dot14Mul(Dot14Mul(Dot14Mul(C, t) + B, t) + A, t); |
| 30 } |
| 31 |
| 32 static inline Dot14 PinAndConvert(SkScalar x) |
| 33 { |
| 34 if (x <= 0) |
| 35 return 0; |
| 36 if (x >= SK_Scalar1) |
| 37 return DOT14_ONE; |
| 38 return SkScalarToFixed(x) >> 2; |
| 39 } |
| 40 |
| 41 SkScalar SkUnitCubicInterp(SkScalar bx, SkScalar by, SkScalar cx, SkScalar cy, S
kScalar value) |
| 42 { |
| 43 Dot14 x = PinAndConvert(value); |
| 44 |
| 45 if (x == 0) return 0; |
| 46 if (x == DOT14_ONE) return SK_Scalar1; |
| 47 |
| 48 Dot14 b = PinAndConvert(bx); |
| 49 Dot14 c = PinAndConvert(cx); |
| 50 |
| 51 // Now compute our coefficients from the control points. |
| 52 // t -> 3b |
| 53 // t^2 -> 3c - 6b |
| 54 // t^3 -> 3b - 3c + 1 |
| 55 Dot14 A = 3 * b; |
| 56 Dot14 B = 3 * (c - 2 * b); |
| 57 Dot14 C = 3 * (b - c) + DOT14_ONE; |
| 58 |
| 59 // Now search for a t value given x. |
| 60 Dot14 t = DOT14_HALF; |
| 61 Dot14 dt = DOT14_HALF; |
| 62 for (int i = 0; i < 13; i++) { |
| 63 dt >>= 1; |
| 64 Dot14 guess = EvalCubic(t, A, B, C); |
| 65 if (x < guess) |
| 66 t -= dt; |
| 67 else |
| 68 t += dt; |
| 69 } |
| 70 |
| 71 // Now we have t, so compute the coefficient for Y and evaluate. |
| 72 b = PinAndConvert(by); |
| 73 c = PinAndConvert(cy); |
| 74 A = 3 * b; |
| 75 B = 3 * (c - 2 * b); |
| 76 C = 3 * (b - c) + DOT14_ONE; |
| 77 return SkFixedToScalar(EvalCubic(t, A, B, C) << 2); |
| 78 } |
| 79 |
| 80 } // anonymous namespace |
12 | 81 |
13 namespace cc { | 82 namespace cc { |
14 | 83 |
15 TimingFunction::TimingFunction() | 84 TimingFunction::TimingFunction() |
16 { | 85 { |
17 } | 86 } |
18 | 87 |
19 TimingFunction::~TimingFunction() | 88 TimingFunction::~TimingFunction() |
20 { | 89 { |
21 } | 90 } |
22 | 91 |
23 double TimingFunction::duration() const | 92 double TimingFunction::duration() const |
24 { | 93 { |
25 return 1.0; | 94 return 1.0; |
26 } | 95 } |
27 | 96 |
28 scoped_ptr<CubicBezierTimingFunction> CubicBezierTimingFunction::create(double x
1, double y1, double x2, double y2) | 97 scoped_ptr<CubicBezierTimingFunction> CubicBezierTimingFunction::create(double x
1, double y1, double x2, double y2) |
29 { | 98 { |
30 return make_scoped_ptr(new CubicBezierTimingFunction(x1, y1, x2, y2)); | 99 return make_scoped_ptr(new CubicBezierTimingFunction(x1, y1, x2, y2)); |
31 } | 100 } |
32 | 101 |
33 CubicBezierTimingFunction::CubicBezierTimingFunction(double x1, double y1, doubl
e x2, double y2) | 102 CubicBezierTimingFunction::CubicBezierTimingFunction(double x1, double y1, doubl
e x2, double y2) |
34 : m_curve(x1, y1, x2, y2) | 103 : m_x1(SkDoubleToScalar(x1)) |
| 104 , m_y1(SkDoubleToScalar(y1)) |
| 105 , m_x2(SkDoubleToScalar(x2)) |
| 106 , m_y2(SkDoubleToScalar(y2)) |
35 { | 107 { |
36 } | 108 } |
37 | 109 |
38 CubicBezierTimingFunction::~CubicBezierTimingFunction() | 110 CubicBezierTimingFunction::~CubicBezierTimingFunction() |
39 { | 111 { |
40 } | 112 } |
41 | 113 |
42 float CubicBezierTimingFunction::getValue(double x) const | 114 float CubicBezierTimingFunction::getValue(double x) const |
43 { | 115 { |
44 UnitBezier temp(m_curve); | 116 SkScalar value = SkUnitCubicInterp(m_x1, m_y1, m_x2, m_y2, x); |
45 return static_cast<float>(temp.solve(x, epsilon)); | 117 return SkScalarToFloat(value); |
46 } | 118 } |
47 | 119 |
48 scoped_ptr<AnimationCurve> CubicBezierTimingFunction::clone() const | 120 scoped_ptr<AnimationCurve> CubicBezierTimingFunction::clone() const |
49 { | 121 { |
50 return make_scoped_ptr(new CubicBezierTimingFunction(*this)).PassAs<Animatio
nCurve>(); | 122 return make_scoped_ptr(new CubicBezierTimingFunction(*this)).PassAs<Animatio
nCurve>(); |
51 } | 123 } |
52 | 124 |
53 // These numbers come from http://www.w3.org/TR/css3-transitions/#transition-tim
ing-function_tag. | 125 // These numbers come from http://www.w3.org/TR/css3-transitions/#transition-tim
ing-function_tag. |
54 scoped_ptr<TimingFunction> EaseTimingFunction::create() | 126 scoped_ptr<TimingFunction> EaseTimingFunction::create() |
55 { | 127 { |
56 return CubicBezierTimingFunction::create(0.25, 0.1, 0.25, 1).PassAs<TimingFu
nction>(); | 128 return CubicBezierTimingFunction::create(0.25, 0.1, 0.25, 1).PassAs<TimingFu
nction>(); |
57 } | 129 } |
58 | 130 |
59 scoped_ptr<TimingFunction> EaseInTimingFunction::create() | 131 scoped_ptr<TimingFunction> EaseInTimingFunction::create() |
60 { | 132 { |
61 return CubicBezierTimingFunction::create(0.42, 0, 1.0, 1).PassAs<TimingFunct
ion>(); | 133 return CubicBezierTimingFunction::create(0.42, 0, 1.0, 1).PassAs<TimingFunct
ion>(); |
62 } | 134 } |
63 | 135 |
64 scoped_ptr<TimingFunction> EaseOutTimingFunction::create() | 136 scoped_ptr<TimingFunction> EaseOutTimingFunction::create() |
65 { | 137 { |
66 return CubicBezierTimingFunction::create(0, 0, 0.58, 1).PassAs<TimingFunctio
n>(); | 138 return CubicBezierTimingFunction::create(0, 0, 0.58, 1).PassAs<TimingFunctio
n>(); |
67 } | 139 } |
68 | 140 |
69 scoped_ptr<TimingFunction> EaseInOutTimingFunction::create() | 141 scoped_ptr<TimingFunction> EaseInOutTimingFunction::create() |
70 { | 142 { |
71 return CubicBezierTimingFunction::create(0.42, 0, 0.58, 1).PassAs<TimingFunc
tion>(); | 143 return CubicBezierTimingFunction::create(0.42, 0, 0.58, 1).PassAs<TimingFunc
tion>(); |
72 } | 144 } |
73 | 145 |
74 } // namespace cc | 146 } // namespace cc |
OLD | NEW |