1 // Copyright (c) 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 "ui/compositor/layer_animation_element.h"
6
7 #include "base/basictypes.h"
8 #include "base/compiler_specific.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/time/time.h"
11 #include "testing/gtest/include/gtest/gtest.h"
12 #include "ui/compositor/layer_animation_delegate.h"
13 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
14 #include "ui/compositor/test/test_layer_animation_delegate.h"
15 #include "ui/compositor/test/test_utils.h"
16 #include "ui/gfx/rect.h"
17 #include "ui/gfx/transform.h"
18
19 namespace ui {
20
21 namespace {
22
23 // Check that the transformation element progresses the delegate as expected and
24 // that the element can be reused after it completes.
TEST(LayerAnimationElementTest,TransformElement)25 TEST(LayerAnimationElementTest, TransformElement) {
26 TestLayerAnimationDelegate delegate;
27 gfx::Transform start_transform, target_transform;
28 start_transform.Rotate(-30.0);
29 target_transform.Rotate(30.0);
30 base::TimeTicks start_time;
31 base::TimeTicks effective_start_time;
32 base::TimeDelta delta = base::TimeDelta::FromSeconds(1);
33
34 scoped_ptr<LayerAnimationElement> element(
35 LayerAnimationElement::CreateTransformElement(target_transform, delta));
36 element->set_animation_group_id(1);
37
38 for (int i = 0; i < 2; ++i) {
39 start_time = effective_start_time + delta;
40 element->set_requested_start_time(start_time);
41 delegate.SetTransformFromAnimation(start_transform);
42 element->Start(&delegate, 1);
43 element->Progress(start_time, &delegate);
44 CheckApproximatelyEqual(start_transform,
45 delegate.GetTransformForAnimation());
46 effective_start_time = start_time + delta;
47 element->set_effective_start_time(effective_start_time);
48 element->Progress(effective_start_time, &delegate);
49 EXPECT_FLOAT_EQ(0.0, element->last_progressed_fraction());
50 element->Progress(effective_start_time + delta/2, &delegate);
51 EXPECT_FLOAT_EQ(0.5, element->last_progressed_fraction());
52
53 base::TimeDelta element_duration;
54 EXPECT_TRUE(element->IsFinished(effective_start_time + delta,
55 &element_duration));
56 EXPECT_EQ(2 * delta, element_duration);
57
58 element->Progress(effective_start_time + delta, &delegate);
59 EXPECT_FLOAT_EQ(1.0, element->last_progressed_fraction());
60 CheckApproximatelyEqual(target_transform,
61 delegate.GetTransformForAnimation());
62 }
63
64 LayerAnimationElement::TargetValue target_value(&delegate);
65 element->GetTargetValue(&target_value);
66 CheckApproximatelyEqual(target_transform, target_value.transform);
67 }
68
69 // Ensures that duration is copied correctly.
TEST(LayerAnimationElementTest,InverseElementDurationNoScale)70 TEST(LayerAnimationElementTest, InverseElementDurationNoScale) {
71 gfx::Transform transform;
72 base::TimeDelta delta;
73
74 scoped_ptr<LayerAnimationElement> base_element(
75 LayerAnimationElement::CreateTransformElement(transform, delta));
76
77 scoped_ptr<LayerAnimationElement> inverse_element(
78 LayerAnimationElement::CreateInverseTransformElement(transform,
79 base_element.get()));
80 EXPECT_EQ(base_element->duration(), inverse_element->duration());
81 }
82
83 // Ensures that duration is copied correctly and not double scaled.
TEST(LayerAnimationElementTest,InverseElementDurationScaled)84 TEST(LayerAnimationElementTest, InverseElementDurationScaled) {
85 gfx::Transform transform;
86 base::TimeDelta delta;
87
88 ScopedAnimationDurationScaleMode faster_duration(
89 ScopedAnimationDurationScaleMode::FAST_DURATION);
90 scoped_ptr<LayerAnimationElement> base_element(
91 LayerAnimationElement::CreateTransformElement(transform, delta));
92
93 scoped_ptr<LayerAnimationElement> inverse_element(
94 LayerAnimationElement::CreateInverseTransformElement(transform,
95 base_element.get()));
96 EXPECT_EQ(base_element->duration(), inverse_element->duration());
97 }
98
99 // Ensures that the GetTargetTransform() method works as intended.
TEST(LayerAnimationElementTest,InverseElementTargetCalculation)100 TEST(LayerAnimationElementTest, InverseElementTargetCalculation) {
101 base::TimeTicks start_time;
102 base::TimeDelta delta = base::TimeDelta::FromSeconds(1);
103 start_time += delta;
104
105 gfx::Transform identity, transform;
106
107 transform.Scale3d(2.0, 2.0, 2.0);
108
109 scoped_ptr<LayerAnimationElement> base_element(
110 LayerAnimationElement::CreateTransformElement(transform, delta));
111 scoped_ptr<LayerAnimationElement> inverse_element(
112 LayerAnimationElement::CreateInverseTransformElement(identity,
113 base_element.get()));
114
115 base_element->set_requested_start_time(start_time);
116 inverse_element->set_requested_start_time(start_time);
117
118 TestLayerAnimationDelegate delegate;
119 delegate.SetTransformFromAnimation(transform);
120
121 base_element->Start(&delegate, 1);
122 inverse_element->Start(&delegate, 1);
123 LayerAnimationElement::TargetValue target;
124 inverse_element->GetTargetValue(&target);
125
126 EXPECT_TRUE(target.transform.IsIdentity())
127 << "Target should be identity such that the initial 2x scale from the start"
128 << " carries over at end when parent is doubled.";
129 }
130
131 // Check that the bounds element progresses the delegate as expected and
132 // that the element can be reused after it completes.
TEST(LayerAnimationElementTest,BoundsElement)133 TEST(LayerAnimationElementTest, BoundsElement) {
134 TestLayerAnimationDelegate delegate;
135 gfx::Rect start, target, middle;
136 start = target = middle = gfx::Rect(0, 0, 50, 50);
137 start.set_x(-90);
138 target.set_x(90);
139 base::TimeTicks start_time;
140 base::TimeDelta delta = base::TimeDelta::FromSeconds(1);
141
142 scoped_ptr<LayerAnimationElement> element(
143 LayerAnimationElement::CreateBoundsElement(target, delta));
144
145 for (int i = 0; i < 2; ++i) {
146 start_time += delta;
147 element->set_requested_start_time(start_time);
148 delegate.SetBoundsFromAnimation(start);
149 element->Start(&delegate, 1);
150 element->Progress(start_time, &delegate);
151 CheckApproximatelyEqual(start, delegate.GetBoundsForAnimation());
152 element->Progress(start_time + delta/2, &delegate);
153 CheckApproximatelyEqual(middle, delegate.GetBoundsForAnimation());
154
155 base::TimeDelta element_duration;
156 EXPECT_TRUE(element->IsFinished(start_time + delta, &element_duration));
157 EXPECT_EQ(delta, element_duration);
158
159 element->Progress(start_time + delta, &delegate);
160 CheckApproximatelyEqual(target, delegate.GetBoundsForAnimation());
161 }
162
163 LayerAnimationElement::TargetValue target_value(&delegate);
164 element->GetTargetValue(&target_value);
165 CheckApproximatelyEqual(target, target_value.bounds);
166 }
167
168 // Check that the opacity element progresses the delegate as expected and
169 // that the element can be reused after it completes.
TEST(LayerAnimationElementTest,OpacityElement)170 TEST(LayerAnimationElementTest, OpacityElement) {
171 TestLayerAnimationDelegate delegate;
172 float start = 0.0;
173 float middle = 0.5;
174 float target = 1.0;
175 base::TimeTicks start_time;
176 base::TimeTicks effective_start_time;
177 base::TimeDelta delta = base::TimeDelta::FromSeconds(1);
178 scoped_ptr<LayerAnimationElement> element(
179 LayerAnimationElement::CreateOpacityElement(target, delta));
180
181 for (int i = 0; i < 2; ++i) {
182 start_time = effective_start_time + delta;
183 element->set_requested_start_time(start_time);
184 delegate.SetOpacityFromAnimation(start);
185 element->Start(&delegate, 1);
186 element->Progress(start_time, &delegate);
187 EXPECT_FLOAT_EQ(start, element->last_progressed_fraction());
188 effective_start_time = start_time + delta;
189 element->set_effective_start_time(effective_start_time);
190 element->Progress(effective_start_time, &delegate);
191 EXPECT_FLOAT_EQ(start, element->last_progressed_fraction());
192 element->Progress(effective_start_time + delta/2, &delegate);
193 EXPECT_FLOAT_EQ(middle, element->last_progressed_fraction());
194
195 base::TimeDelta element_duration;
196 EXPECT_TRUE(element->IsFinished(effective_start_time + delta,
197 &element_duration));
198 EXPECT_EQ(2 * delta, element_duration);
199
200 element->Progress(effective_start_time + delta, &delegate);
201 EXPECT_FLOAT_EQ(target, element->last_progressed_fraction());
202 EXPECT_FLOAT_EQ(target, delegate.GetOpacityForAnimation());
203 }
204
205 LayerAnimationElement::TargetValue target_value(&delegate);
206 element->GetTargetValue(&target_value);
207 EXPECT_FLOAT_EQ(target, target_value.opacity);
208 }
209
210 // Check that the visibility element progresses the delegate as expected and
211 // that the element can be reused after it completes.
TEST(LayerAnimationElementTest,VisibilityElement)212 TEST(LayerAnimationElementTest, VisibilityElement) {
213 TestLayerAnimationDelegate delegate;
214 bool start = true;
215 bool target = false;
216 base::TimeTicks start_time;
217 base::TimeDelta delta = base::TimeDelta::FromSeconds(1);
218 scoped_ptr<LayerAnimationElement> element(
219 LayerAnimationElement::CreateVisibilityElement(target, delta));
220
221 for (int i = 0; i < 2; ++i) {
222 start_time += delta;
223 element->set_requested_start_time(start_time);
224 delegate.SetVisibilityFromAnimation(start);
225 element->Start(&delegate, 1);
226 element->Progress(start_time, &delegate);
227 EXPECT_TRUE(delegate.GetVisibilityForAnimation());
228 element->Progress(start_time + delta/2, &delegate);
229 EXPECT_TRUE(delegate.GetVisibilityForAnimation());
230
231 base::TimeDelta element_duration;
232 EXPECT_TRUE(element->IsFinished(start_time + delta, &element_duration));
233 EXPECT_EQ(delta, element_duration);
234
235 element->Progress(start_time + delta, &delegate);
236 EXPECT_FALSE(delegate.GetVisibilityForAnimation());
237 }
238
239 LayerAnimationElement::TargetValue target_value(&delegate);
240 element->GetTargetValue(&target_value);
241 EXPECT_FALSE(target_value.visibility);
242 }
243
244 // Check that the Brightness element progresses the delegate as expected and
245 // that the element can be reused after it completes.
TEST(LayerAnimationElementTest,BrightnessElement)246 TEST(LayerAnimationElementTest, BrightnessElement) {
247 TestLayerAnimationDelegate delegate;
248 float start = 0.0;
249 float middle = 0.5;
250 float target = 1.0;
251 base::TimeTicks start_time;
252 base::TimeDelta delta = base::TimeDelta::FromSeconds(1);
253 scoped_ptr<LayerAnimationElement> element(
254 LayerAnimationElement::CreateBrightnessElement(target, delta));
255
256 for (int i = 0; i < 2; ++i) {
257 start_time += delta;
258 element->set_requested_start_time(start_time);
259 delegate.SetBrightnessFromAnimation(start);
260 element->Start(&delegate, 1);
261 element->Progress(start_time, &delegate);
262 EXPECT_FLOAT_EQ(start, delegate.GetBrightnessForAnimation());
263 element->Progress(start_time + delta/2, &delegate);
264 EXPECT_FLOAT_EQ(middle, delegate.GetBrightnessForAnimation());
265
266 base::TimeDelta element_duration;
267 EXPECT_TRUE(element->IsFinished(start_time + delta, &element_duration));
268 EXPECT_EQ(delta, element_duration);
269
270 element->Progress(start_time + delta, &delegate);
271 EXPECT_FLOAT_EQ(target, delegate.GetBrightnessForAnimation());
272 }
273
274 LayerAnimationElement::TargetValue target_value(&delegate);
275 element->GetTargetValue(&target_value);
276 EXPECT_FLOAT_EQ(target, target_value.brightness);
277 }
278
279 // Check that the Grayscale element progresses the delegate as expected and
280 // that the element can be reused after it completes.
TEST(LayerAnimationElementTest,GrayscaleElement)281 TEST(LayerAnimationElementTest, GrayscaleElement) {
282 TestLayerAnimationDelegate delegate;
283 float start = 0.0;
284 float middle = 0.5;
285 float target = 1.0;
286 base::TimeTicks start_time;
287 base::TimeDelta delta = base::TimeDelta::FromSeconds(1);
288 scoped_ptr<LayerAnimationElement> element(
289 LayerAnimationElement::CreateGrayscaleElement(target, delta));
290
291 for (int i = 0; i < 2; ++i) {
292 start_time += delta;
293 element->set_requested_start_time(start_time);
294 delegate.SetGrayscaleFromAnimation(start);
295 element->Start(&delegate, 1);
296 element->Progress(start_time, &delegate);
297 EXPECT_FLOAT_EQ(start, delegate.GetGrayscaleForAnimation());
298 element->Progress(start_time + delta/2, &delegate);
299 EXPECT_FLOAT_EQ(middle, delegate.GetGrayscaleForAnimation());
300
301 base::TimeDelta element_duration;
302 EXPECT_TRUE(element->IsFinished(start_time + delta, &element_duration));
303 EXPECT_EQ(delta, element_duration);
304
305 element->Progress(start_time + delta, &delegate);
306 EXPECT_FLOAT_EQ(target, delegate.GetGrayscaleForAnimation());
307 }
308
309 LayerAnimationElement::TargetValue target_value(&delegate);
310 element->GetTargetValue(&target_value);
311 EXPECT_FLOAT_EQ(target, target_value.grayscale);
312 }
313
314 // Check that the pause element progresses the delegate as expected and
315 // that the element can be reused after it completes.
TEST(LayerAnimationElementTest,PauseElement)316 TEST(LayerAnimationElementTest, PauseElement) {
317 LayerAnimationElement::AnimatableProperties properties =
318 LayerAnimationElement::TRANSFORM | LayerAnimationElement::BOUNDS |
319 LayerAnimationElement::OPACITY | LayerAnimationElement::BRIGHTNESS |
320 LayerAnimationElement::GRAYSCALE;
321
322 base::TimeTicks start_time;
323 base::TimeDelta delta = base::TimeDelta::FromSeconds(1);
324
325 scoped_ptr<LayerAnimationElement> element(
326 LayerAnimationElement::CreatePauseElement(properties, delta));
327
328 TestLayerAnimationDelegate delegate;
329 TestLayerAnimationDelegate copy = delegate;
330
331 start_time += delta;
332 element->set_requested_start_time(start_time);
333 element->Start(&delegate, 1);
334
335 // Pause should last for |delta|.
336 base::TimeDelta element_duration;
337 EXPECT_TRUE(element->IsFinished(start_time + delta, &element_duration));
338 EXPECT_EQ(delta, element_duration);
339
340 element->Progress(start_time + delta, &delegate);
341
342 // Nothing should have changed.
343 CheckApproximatelyEqual(delegate.GetBoundsForAnimation(),
344 copy.GetBoundsForAnimation());
345 CheckApproximatelyEqual(delegate.GetTransformForAnimation(),
346 copy.GetTransformForAnimation());
347 EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(),
348 copy.GetOpacityForAnimation());
349 EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(),
350 copy.GetBrightnessForAnimation());
351 EXPECT_FLOAT_EQ(delegate.GetGrayscaleForAnimation(),
352 copy.GetGrayscaleForAnimation());
353 }
354
355 // Check that a threaded opacity element updates the delegate as expected when
356 // aborted.
TEST(LayerAnimationElementTest,AbortOpacityElement)357 TEST(LayerAnimationElementTest, AbortOpacityElement) {
358 TestLayerAnimationDelegate delegate;
359 float start = 0.0;
360 float target = 1.0;
361 base::TimeTicks start_time;
362 base::TimeTicks effective_start_time;
363 base::TimeDelta delta = base::TimeDelta::FromSeconds(1);
364 scoped_ptr<LayerAnimationElement> element(
365 LayerAnimationElement::CreateOpacityElement(target, delta));
366
367 // Choose a non-linear Tween type.
368 gfx::Tween::Type tween_type = gfx::Tween::EASE_IN;
369 element->set_tween_type(tween_type);
370
371 delegate.SetOpacityFromAnimation(start);
372
373 // Aborting the element before it has started should not update the delegate.
374 element->Abort(&delegate);
375 EXPECT_FLOAT_EQ(start, delegate.GetOpacityForAnimation());
376
377 start_time += delta;
378 element->set_requested_start_time(start_time);
379 element->Start(&delegate, 1);
380 element->Progress(start_time, &delegate);
381 effective_start_time = start_time + delta;
382 element->set_effective_start_time(effective_start_time);
383 element->Progress(effective_start_time, &delegate);
384 element->Progress(effective_start_time + delta/2, &delegate);
385
386 // Since the element has started, it should update the delegate when
387 // aborted.
388 element->Abort(&delegate);
389 EXPECT_FLOAT_EQ(gfx::Tween::CalculateValue(tween_type, 0.5),
390 delegate.GetOpacityForAnimation());
391 }
392
393 // Check that a threaded transform element updates the delegate as expected when
394 // aborted.
TEST(LayerAnimationElementTest,AbortTransformElement)395 TEST(LayerAnimationElementTest, AbortTransformElement) {
396 TestLayerAnimationDelegate delegate;
397 gfx::Transform start_transform, target_transform;
398 start_transform.Rotate(-30.0);
399 target_transform.Rotate(30.0);
400 base::TimeTicks start_time;
401 base::TimeTicks effective_start_time;
402 base::TimeDelta delta = base::TimeDelta::FromSeconds(1);
403 scoped_ptr<LayerAnimationElement> element(
404 LayerAnimationElement::CreateTransformElement(target_transform, delta));
405
406 // Choose a non-linear Tween type.
407 gfx::Tween::Type tween_type = gfx::Tween::EASE_IN;
408 element->set_tween_type(tween_type);
409
410 delegate.SetTransformFromAnimation(start_transform);
411
412 // Aborting the element before it has started should not update the delegate.
413 element->Abort(&delegate);
414 CheckApproximatelyEqual(start_transform, delegate.GetTransformForAnimation());
415
416 start_time += delta;
417 element->set_requested_start_time(start_time);
418 element->Start(&delegate, 1);
419 element->Progress(start_time, &delegate);
420 effective_start_time = start_time + delta;
421 element->set_effective_start_time(effective_start_time);
422 element->Progress(effective_start_time, &delegate);
423 element->Progress(effective_start_time + delta/2, &delegate);
424
425 // Since the element has started, it should update the delegate when
426 // aborted.
427 element->Abort(&delegate);
428 target_transform.Blend(start_transform,
429 gfx::Tween::CalculateValue(tween_type, 0.5));
430 CheckApproximatelyEqual(target_transform,
431 delegate.GetTransformForAnimation());
432 }
433
434 } // namespace
435
436 } // namespace ui
437