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
3// found in the LICENSE file.
4
5#include "cc/animation/keyframed_animation_curve.h"
6
7#include "cc/animation/transform_operations.h"
8#include "testing/gmock/include/gmock/gmock.h"
9#include "testing/gtest/include/gtest/gtest.h"
10
11namespace cc {
12namespace {
13
14void ExpectTranslateX(double translate_x, const gfx::Transform& transform) {
15  EXPECT_FLOAT_EQ(translate_x, transform.matrix().getDouble(0, 3));
16}
17
18void ExpectBrightness(double brightness, const FilterOperations& filter) {
19  EXPECT_EQ(1u, filter.size());
20  EXPECT_EQ(FilterOperation::BRIGHTNESS, filter.at(0).type());
21  EXPECT_FLOAT_EQ(brightness, filter.at(0).amount());
22}
23
24// Tests that a float animation with one keyframe works as expected.
25TEST(KeyframedAnimationCurveTest, OneFloatKeyframe) {
26  scoped_ptr<KeyframedFloatAnimationCurve> curve(
27      KeyframedFloatAnimationCurve::Create());
28  curve->AddKeyframe(
29      FloatKeyframe::Create(0.0, 2.f, scoped_ptr<TimingFunction>()));
30  EXPECT_FLOAT_EQ(2.f, curve->GetValue(-1.f));
31  EXPECT_FLOAT_EQ(2.f, curve->GetValue(0.f));
32  EXPECT_FLOAT_EQ(2.f, curve->GetValue(0.5f));
33  EXPECT_FLOAT_EQ(2.f, curve->GetValue(1.f));
34  EXPECT_FLOAT_EQ(2.f, curve->GetValue(2.f));
35}
36
37// Tests that a float animation with two keyframes works as expected.
38TEST(KeyframedAnimationCurveTest, TwoFloatKeyframe) {
39  scoped_ptr<KeyframedFloatAnimationCurve> curve(
40      KeyframedFloatAnimationCurve::Create());
41  curve->AddKeyframe(
42      FloatKeyframe::Create(0.0, 2.f, scoped_ptr<TimingFunction>()));
43  curve->AddKeyframe(
44      FloatKeyframe::Create(1.0, 4.f, scoped_ptr<TimingFunction>()));
45  EXPECT_FLOAT_EQ(2.f, curve->GetValue(-1.f));
46  EXPECT_FLOAT_EQ(2.f, curve->GetValue(0.f));
47  EXPECT_FLOAT_EQ(3.f, curve->GetValue(0.5f));
48  EXPECT_FLOAT_EQ(4.f, curve->GetValue(1.f));
49  EXPECT_FLOAT_EQ(4.f, curve->GetValue(2.f));
50}
51
52// Tests that a float animation with three keyframes works as expected.
53TEST(KeyframedAnimationCurveTest, ThreeFloatKeyframe) {
54  scoped_ptr<KeyframedFloatAnimationCurve> curve(
55      KeyframedFloatAnimationCurve::Create());
56  curve->AddKeyframe(
57      FloatKeyframe::Create(0.0, 2.f, scoped_ptr<TimingFunction>()));
58  curve->AddKeyframe(
59      FloatKeyframe::Create(1.0, 4.f, scoped_ptr<TimingFunction>()));
60  curve->AddKeyframe(
61      FloatKeyframe::Create(2.0, 8.f, scoped_ptr<TimingFunction>()));
62  EXPECT_FLOAT_EQ(2.f, curve->GetValue(-1.f));
63  EXPECT_FLOAT_EQ(2.f, curve->GetValue(0.f));
64  EXPECT_FLOAT_EQ(3.f, curve->GetValue(0.5f));
65  EXPECT_FLOAT_EQ(4.f, curve->GetValue(1.f));
66  EXPECT_FLOAT_EQ(6.f, curve->GetValue(1.5f));
67  EXPECT_FLOAT_EQ(8.f, curve->GetValue(2.f));
68  EXPECT_FLOAT_EQ(8.f, curve->GetValue(3.f));
69}
70
71// Tests that a float animation with multiple keys at a given time works sanely.
72TEST(KeyframedAnimationCurveTest, RepeatedFloatKeyTimes) {
73  scoped_ptr<KeyframedFloatAnimationCurve> curve(
74      KeyframedFloatAnimationCurve::Create());
75  curve->AddKeyframe(
76      FloatKeyframe::Create(0.0, 4.f, scoped_ptr<TimingFunction>()));
77  curve->AddKeyframe(
78      FloatKeyframe::Create(1.0, 4.f, scoped_ptr<TimingFunction>()));
79  curve->AddKeyframe(
80      FloatKeyframe::Create(1.0, 6.f, scoped_ptr<TimingFunction>()));
81  curve->AddKeyframe(
82      FloatKeyframe::Create(2.0, 6.f, scoped_ptr<TimingFunction>()));
83
84  EXPECT_FLOAT_EQ(4.f, curve->GetValue(-1.f));
85  EXPECT_FLOAT_EQ(4.f, curve->GetValue(0.f));
86  EXPECT_FLOAT_EQ(4.f, curve->GetValue(0.5f));
87
88  // There is a discontinuity at 1. Any value between 4 and 6 is valid.
89  float value = curve->GetValue(1.f);
90  EXPECT_TRUE(value >= 4 && value <= 6);
91
92  EXPECT_FLOAT_EQ(6.f, curve->GetValue(1.5f));
93  EXPECT_FLOAT_EQ(6.f, curve->GetValue(2.f));
94  EXPECT_FLOAT_EQ(6.f, curve->GetValue(3.f));
95}
96
97// Tests that a transform animation with one keyframe works as expected.
98TEST(KeyframedAnimationCurveTest, OneTransformKeyframe) {
99  scoped_ptr<KeyframedTransformAnimationCurve> curve(
100      KeyframedTransformAnimationCurve::Create());
101  TransformOperations operations;
102  operations.AppendTranslate(2.f, 0.f, 0.f);
103  curve->AddKeyframe(
104      TransformKeyframe::Create(0.f, operations, scoped_ptr<TimingFunction>()));
105
106  ExpectTranslateX(2.f, curve->GetValue(-1.f));
107  ExpectTranslateX(2.f, curve->GetValue(0.f));
108  ExpectTranslateX(2.f, curve->GetValue(0.5f));
109  ExpectTranslateX(2.f, curve->GetValue(1.f));
110  ExpectTranslateX(2.f, curve->GetValue(2.f));
111}
112
113// Tests that a transform animation with two keyframes works as expected.
114TEST(KeyframedAnimationCurveTest, TwoTransformKeyframe) {
115  scoped_ptr<KeyframedTransformAnimationCurve> curve(
116      KeyframedTransformAnimationCurve::Create());
117  TransformOperations operations1;
118  operations1.AppendTranslate(2.f, 0.f, 0.f);
119  TransformOperations operations2;
120  operations2.AppendTranslate(4.f, 0.f, 0.f);
121
122  curve->AddKeyframe(TransformKeyframe::Create(
123      0.f, operations1, scoped_ptr<TimingFunction>()));
124  curve->AddKeyframe(TransformKeyframe::Create(
125      1.f, operations2, scoped_ptr<TimingFunction>()));
126  ExpectTranslateX(2.f, curve->GetValue(-1.f));
127  ExpectTranslateX(2.f, curve->GetValue(0.f));
128  ExpectTranslateX(3.f, curve->GetValue(0.5f));
129  ExpectTranslateX(4.f, curve->GetValue(1.f));
130  ExpectTranslateX(4.f, curve->GetValue(2.f));
131}
132
133// Tests that a transform animation with three keyframes works as expected.
134TEST(KeyframedAnimationCurveTest, ThreeTransformKeyframe) {
135  scoped_ptr<KeyframedTransformAnimationCurve> curve(
136      KeyframedTransformAnimationCurve::Create());
137  TransformOperations operations1;
138  operations1.AppendTranslate(2.f, 0.f, 0.f);
139  TransformOperations operations2;
140  operations2.AppendTranslate(4.f, 0.f, 0.f);
141  TransformOperations operations3;
142  operations3.AppendTranslate(8.f, 0.f, 0.f);
143  curve->AddKeyframe(TransformKeyframe::Create(
144      0.f, operations1, scoped_ptr<TimingFunction>()));
145  curve->AddKeyframe(TransformKeyframe::Create(
146      1.f, operations2, scoped_ptr<TimingFunction>()));
147  curve->AddKeyframe(TransformKeyframe::Create(
148      2.f, operations3, scoped_ptr<TimingFunction>()));
149  ExpectTranslateX(2.f, curve->GetValue(-1.f));
150  ExpectTranslateX(2.f, curve->GetValue(0.f));
151  ExpectTranslateX(3.f, curve->GetValue(0.5f));
152  ExpectTranslateX(4.f, curve->GetValue(1.f));
153  ExpectTranslateX(6.f, curve->GetValue(1.5f));
154  ExpectTranslateX(8.f, curve->GetValue(2.f));
155  ExpectTranslateX(8.f, curve->GetValue(3.f));
156}
157
158// Tests that a transform animation with multiple keys at a given time works
159// sanely.
160TEST(KeyframedAnimationCurveTest, RepeatedTransformKeyTimes) {
161  scoped_ptr<KeyframedTransformAnimationCurve> curve(
162      KeyframedTransformAnimationCurve::Create());
163  // A step function.
164  TransformOperations operations1;
165  operations1.AppendTranslate(4.f, 0.f, 0.f);
166  TransformOperations operations2;
167  operations2.AppendTranslate(4.f, 0.f, 0.f);
168  TransformOperations operations3;
169  operations3.AppendTranslate(6.f, 0.f, 0.f);
170  TransformOperations operations4;
171  operations4.AppendTranslate(6.f, 0.f, 0.f);
172  curve->AddKeyframe(TransformKeyframe::Create(
173      0.f, operations1, scoped_ptr<TimingFunction>()));
174  curve->AddKeyframe(TransformKeyframe::Create(
175      1.f, operations2, scoped_ptr<TimingFunction>()));
176  curve->AddKeyframe(TransformKeyframe::Create(
177      1.f, operations3, scoped_ptr<TimingFunction>()));
178  curve->AddKeyframe(TransformKeyframe::Create(
179      2.f, operations4, scoped_ptr<TimingFunction>()));
180
181  ExpectTranslateX(4.f, curve->GetValue(-1.f));
182  ExpectTranslateX(4.f, curve->GetValue(0.f));
183  ExpectTranslateX(4.f, curve->GetValue(0.5f));
184
185  // There is a discontinuity at 1. Any value between 4 and 6 is valid.
186  gfx::Transform value = curve->GetValue(1.f);
187  EXPECT_GE(value.matrix().getDouble(0.f, 3.f), 4);
188  EXPECT_LE(value.matrix().getDouble(0.f, 3.f), 6);
189
190  ExpectTranslateX(6.f, curve->GetValue(1.5f));
191  ExpectTranslateX(6.f, curve->GetValue(2.f));
192  ExpectTranslateX(6.f, curve->GetValue(3.f));
193}
194
195// Tests that a filter animation with one keyframe works as expected.
196TEST(KeyframedAnimationCurveTest, OneFilterKeyframe) {
197  scoped_ptr<KeyframedFilterAnimationCurve> curve(
198      KeyframedFilterAnimationCurve::Create());
199  FilterOperations operations;
200  operations.Append(FilterOperation::CreateBrightnessFilter(2.f));
201  curve->AddKeyframe(
202      FilterKeyframe::Create(0.f, operations, scoped_ptr<TimingFunction>()));
203
204  ExpectBrightness(2.f, curve->GetValue(-1.f));
205  ExpectBrightness(2.f, curve->GetValue(0.f));
206  ExpectBrightness(2.f, curve->GetValue(0.5f));
207  ExpectBrightness(2.f, curve->GetValue(1.f));
208  ExpectBrightness(2.f, curve->GetValue(2.f));
209}
210
211// Tests that a filter animation with two keyframes works as expected.
212TEST(KeyframedAnimationCurveTest, TwoFilterKeyframe) {
213  scoped_ptr<KeyframedFilterAnimationCurve> curve(
214      KeyframedFilterAnimationCurve::Create());
215  FilterOperations operations1;
216  operations1.Append(FilterOperation::CreateBrightnessFilter(2.f));
217  FilterOperations operations2;
218  operations2.Append(FilterOperation::CreateBrightnessFilter(4.f));
219
220  curve->AddKeyframe(FilterKeyframe::Create(
221      0.f, operations1, scoped_ptr<TimingFunction>()));
222  curve->AddKeyframe(FilterKeyframe::Create(
223      1.f, operations2, scoped_ptr<TimingFunction>()));
224  ExpectBrightness(2.f, curve->GetValue(-1.f));
225  ExpectBrightness(2.f, curve->GetValue(0.f));
226  ExpectBrightness(3.f, curve->GetValue(0.5f));
227  ExpectBrightness(4.f, curve->GetValue(1.f));
228  ExpectBrightness(4.f, curve->GetValue(2.f));
229}
230
231// Tests that a filter animation with three keyframes works as expected.
232TEST(KeyframedAnimationCurveTest, ThreeFilterKeyframe) {
233  scoped_ptr<KeyframedFilterAnimationCurve> curve(
234      KeyframedFilterAnimationCurve::Create());
235  FilterOperations operations1;
236  operations1.Append(FilterOperation::CreateBrightnessFilter(2.f));
237  FilterOperations operations2;
238  operations2.Append(FilterOperation::CreateBrightnessFilter(4.f));
239  FilterOperations operations3;
240  operations3.Append(FilterOperation::CreateBrightnessFilter(8.f));
241  curve->AddKeyframe(FilterKeyframe::Create(
242      0.f, operations1, scoped_ptr<TimingFunction>()));
243  curve->AddKeyframe(FilterKeyframe::Create(
244      1.f, operations2, scoped_ptr<TimingFunction>()));
245  curve->AddKeyframe(FilterKeyframe::Create(
246      2.f, operations3, scoped_ptr<TimingFunction>()));
247  ExpectBrightness(2.f, curve->GetValue(-1.f));
248  ExpectBrightness(2.f, curve->GetValue(0.f));
249  ExpectBrightness(3.f, curve->GetValue(0.5f));
250  ExpectBrightness(4.f, curve->GetValue(1.f));
251  ExpectBrightness(6.f, curve->GetValue(1.5f));
252  ExpectBrightness(8.f, curve->GetValue(2.f));
253  ExpectBrightness(8.f, curve->GetValue(3.f));
254}
255
256// Tests that a filter animation with multiple keys at a given time works
257// sanely.
258TEST(KeyframedAnimationCurveTest, RepeatedFilterKeyTimes) {
259  scoped_ptr<KeyframedFilterAnimationCurve> curve(
260      KeyframedFilterAnimationCurve::Create());
261  // A step function.
262  FilterOperations operations1;
263  operations1.Append(FilterOperation::CreateBrightnessFilter(4.f));
264  FilterOperations operations2;
265  operations2.Append(FilterOperation::CreateBrightnessFilter(4.f));
266  FilterOperations operations3;
267  operations3.Append(FilterOperation::CreateBrightnessFilter(6.f));
268  FilterOperations operations4;
269  operations4.Append(FilterOperation::CreateBrightnessFilter(6.f));
270  curve->AddKeyframe(FilterKeyframe::Create(
271      0.f, operations1, scoped_ptr<TimingFunction>()));
272  curve->AddKeyframe(FilterKeyframe::Create(
273      1.f, operations2, scoped_ptr<TimingFunction>()));
274  curve->AddKeyframe(FilterKeyframe::Create(
275      1.f, operations3, scoped_ptr<TimingFunction>()));
276  curve->AddKeyframe(FilterKeyframe::Create(
277      2.f, operations4, scoped_ptr<TimingFunction>()));
278
279  ExpectBrightness(4.f, curve->GetValue(-1.f));
280  ExpectBrightness(4.f, curve->GetValue(0.f));
281  ExpectBrightness(4.f, curve->GetValue(0.5f));
282
283  // There is a discontinuity at 1. Any value between 4 and 6 is valid.
284  FilterOperations value = curve->GetValue(1.f);
285  EXPECT_EQ(1u, value.size());
286  EXPECT_EQ(FilterOperation::BRIGHTNESS, value.at(0).type());
287  EXPECT_GE(value.at(0).amount(), 4);
288  EXPECT_LE(value.at(0).amount(), 6);
289
290  ExpectBrightness(6.f, curve->GetValue(1.5f));
291  ExpectBrightness(6.f, curve->GetValue(2.f));
292  ExpectBrightness(6.f, curve->GetValue(3.f));
293}
294
295// Tests that the keyframes may be added out of order.
296TEST(KeyframedAnimationCurveTest, UnsortedKeyframes) {
297  scoped_ptr<KeyframedFloatAnimationCurve> curve(
298      KeyframedFloatAnimationCurve::Create());
299  curve->AddKeyframe(
300      FloatKeyframe::Create(2.0, 8.f, scoped_ptr<TimingFunction>()));
301  curve->AddKeyframe(
302      FloatKeyframe::Create(0.0, 2.f, scoped_ptr<TimingFunction>()));
303  curve->AddKeyframe(
304      FloatKeyframe::Create(1.0, 4.f, scoped_ptr<TimingFunction>()));
305  EXPECT_FLOAT_EQ(2.f, curve->GetValue(-1.f));
306  EXPECT_FLOAT_EQ(2.f, curve->GetValue(0.f));
307  EXPECT_FLOAT_EQ(3.f, curve->GetValue(0.5f));
308  EXPECT_FLOAT_EQ(4.f, curve->GetValue(1.f));
309  EXPECT_FLOAT_EQ(6.f, curve->GetValue(1.5f));
310  EXPECT_FLOAT_EQ(8.f, curve->GetValue(2.f));
311  EXPECT_FLOAT_EQ(8.f, curve->GetValue(3.f));
312}
313
314// Tests that a cubic bezier timing function works as expected.
315TEST(KeyframedAnimationCurveTest, CubicBezierTimingFunction) {
316  scoped_ptr<KeyframedFloatAnimationCurve> curve(
317      KeyframedFloatAnimationCurve::Create());
318  curve->AddKeyframe(FloatKeyframe::Create(
319      0.0,
320      0.f,
321      CubicBezierTimingFunction::Create(0.25f, 0.f, 0.75f, 1.f)
322          .PassAs<TimingFunction>()));
323  curve->AddKeyframe(
324      FloatKeyframe::Create(1.0, 1.f, scoped_ptr<TimingFunction>()));
325
326  EXPECT_FLOAT_EQ(0.f, curve->GetValue(0.f));
327  EXPECT_LT(0.f, curve->GetValue(0.25f));
328  EXPECT_GT(0.25f, curve->GetValue(0.25f));
329  EXPECT_NEAR(curve->GetValue(0.5f), 0.5f, 0.00015f);
330  EXPECT_LT(0.75f, curve->GetValue(0.75f));
331  EXPECT_GT(1.f, curve->GetValue(0.75f));
332  EXPECT_FLOAT_EQ(1.f, curve->GetValue(1.f));
333}
334
335}  // namespace
336}  // namespace cc
337