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.
5 #include "ui/compositor/layer_animation_element.h"
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/geometry/rect.h"
17 #include "ui/gfx/transform.h"
23 // Verify that the TargetValue(TestLayerAnimationDelegate*) constructor
24 // correctly assigns values. See www.crbug.com/483134.
25 TEST(TargetValueTest
, VerifyLayerAnimationDelegateConstructor
) {
26 const gfx::Rect
kBounds(1, 2, 3, 5);
27 const gfx::Transform
kTransform(1.0f
, 2.0f
, 3.0f
, 4.0f
, 5.0f
, 6.0f
);
28 const float kOpacity
= 1.235f
;
29 const bool kVisibility
= false;
30 const float kBrightness
= 2.358f
;
31 const float kGrayscale
= 2.5813f
;
32 const SkColor kColor
= SK_ColorCYAN
;
34 TestLayerAnimationDelegate delegate
;
35 delegate
.SetBoundsFromAnimation(kBounds
);
36 delegate
.SetTransformFromAnimation(kTransform
);
37 delegate
.SetOpacityFromAnimation(kOpacity
);
38 delegate
.SetVisibilityFromAnimation(kVisibility
);
39 delegate
.SetBrightnessFromAnimation(kBrightness
);
40 delegate
.SetGrayscaleFromAnimation(kGrayscale
);
41 delegate
.SetColorFromAnimation(kColor
);
43 LayerAnimationElement::TargetValue
target_value(&delegate
);
45 EXPECT_EQ(kBounds
, target_value
.bounds
);
46 EXPECT_EQ(kTransform
, target_value
.transform
);
47 EXPECT_FLOAT_EQ(kOpacity
, target_value
.opacity
);
48 EXPECT_EQ(kVisibility
, target_value
.visibility
);
49 EXPECT_FLOAT_EQ(kBrightness
, target_value
.brightness
);
50 EXPECT_FLOAT_EQ(kGrayscale
, target_value
.grayscale
);
51 EXPECT_EQ(SK_ColorCYAN
, target_value
.color
);
54 // Check that the transformation element progresses the delegate as expected and
55 // that the element can be reused after it completes.
56 TEST(LayerAnimationElementTest
, TransformElement
) {
57 TestLayerAnimationDelegate delegate
;
58 gfx::Transform start_transform
, target_transform
;
59 start_transform
.Rotate(-30.0);
60 target_transform
.Rotate(30.0);
61 base::TimeTicks start_time
;
62 base::TimeTicks effective_start_time
;
63 base::TimeDelta delta
= base::TimeDelta::FromSeconds(1);
65 scoped_ptr
<LayerAnimationElement
> element(
66 LayerAnimationElement::CreateTransformElement(target_transform
, delta
));
67 element
->set_animation_group_id(1);
69 for (int i
= 0; i
< 2; ++i
) {
70 start_time
= effective_start_time
+ delta
;
71 element
->set_requested_start_time(start_time
);
72 delegate
.SetTransformFromAnimation(start_transform
);
73 element
->Start(&delegate
, 1);
74 element
->Progress(start_time
, &delegate
);
75 CheckApproximatelyEqual(start_transform
,
76 delegate
.GetTransformForAnimation());
77 effective_start_time
= start_time
+ delta
;
78 element
->set_effective_start_time(effective_start_time
);
79 element
->Progress(effective_start_time
, &delegate
);
80 EXPECT_FLOAT_EQ(0.0, element
->last_progressed_fraction());
81 element
->Progress(effective_start_time
+ delta
/2, &delegate
);
82 EXPECT_FLOAT_EQ(0.5, element
->last_progressed_fraction());
84 base::TimeDelta element_duration
;
85 EXPECT_TRUE(element
->IsFinished(effective_start_time
+ delta
,
87 EXPECT_EQ(2 * delta
, element_duration
);
89 element
->Progress(effective_start_time
+ delta
, &delegate
);
90 EXPECT_FLOAT_EQ(1.0, element
->last_progressed_fraction());
91 CheckApproximatelyEqual(target_transform
,
92 delegate
.GetTransformForAnimation());
95 LayerAnimationElement::TargetValue
target_value(&delegate
);
96 element
->GetTargetValue(&target_value
);
97 CheckApproximatelyEqual(target_transform
, target_value
.transform
);
100 // Ensures that duration is copied correctly.
101 TEST(LayerAnimationElementTest
, InverseElementDurationNoScale
) {
102 gfx::Transform transform
;
103 base::TimeDelta delta
;
105 scoped_ptr
<LayerAnimationElement
> base_element(
106 LayerAnimationElement::CreateTransformElement(transform
, delta
));
108 scoped_ptr
<LayerAnimationElement
> inverse_element(
109 LayerAnimationElement::CreateInverseTransformElement(transform
,
110 base_element
.get()));
111 EXPECT_EQ(base_element
->duration(), inverse_element
->duration());
114 // Ensures that duration is copied correctly and not double scaled.
115 TEST(LayerAnimationElementTest
, InverseElementDurationScaled
) {
116 gfx::Transform transform
;
117 base::TimeDelta delta
;
119 ScopedAnimationDurationScaleMode
faster_duration(
120 ScopedAnimationDurationScaleMode::FAST_DURATION
);
121 scoped_ptr
<LayerAnimationElement
> base_element(
122 LayerAnimationElement::CreateTransformElement(transform
, delta
));
124 scoped_ptr
<LayerAnimationElement
> inverse_element(
125 LayerAnimationElement::CreateInverseTransformElement(transform
,
126 base_element
.get()));
127 EXPECT_EQ(base_element
->duration(), inverse_element
->duration());
130 // Ensures that the GetTargetTransform() method works as intended.
131 TEST(LayerAnimationElementTest
, InverseElementTargetCalculation
) {
132 base::TimeTicks start_time
;
133 base::TimeDelta delta
= base::TimeDelta::FromSeconds(1);
136 gfx::Transform identity
, transform
;
138 transform
.Scale3d(2.0, 2.0, 2.0);
140 scoped_ptr
<LayerAnimationElement
> base_element(
141 LayerAnimationElement::CreateTransformElement(transform
, delta
));
142 scoped_ptr
<LayerAnimationElement
> inverse_element(
143 LayerAnimationElement::CreateInverseTransformElement(identity
,
144 base_element
.get()));
146 base_element
->set_requested_start_time(start_time
);
147 inverse_element
->set_requested_start_time(start_time
);
149 TestLayerAnimationDelegate delegate
;
150 delegate
.SetTransformFromAnimation(transform
);
152 base_element
->Start(&delegate
, 1);
153 inverse_element
->Start(&delegate
, 1);
154 LayerAnimationElement::TargetValue target
;
155 inverse_element
->GetTargetValue(&target
);
157 EXPECT_TRUE(target
.transform
.IsIdentity())
158 << "Target should be identity such that the initial 2x scale from the start"
159 << " carries over at end when parent is doubled.";
162 // Check that the bounds element progresses the delegate as expected and
163 // that the element can be reused after it completes.
164 TEST(LayerAnimationElementTest
, BoundsElement
) {
165 TestLayerAnimationDelegate delegate
;
166 gfx::Rect start
, target
, middle
;
167 start
= target
= middle
= gfx::Rect(0, 0, 50, 50);
170 base::TimeTicks start_time
;
171 base::TimeDelta delta
= base::TimeDelta::FromSeconds(1);
173 scoped_ptr
<LayerAnimationElement
> element(
174 LayerAnimationElement::CreateBoundsElement(target
, delta
));
176 for (int i
= 0; i
< 2; ++i
) {
178 element
->set_requested_start_time(start_time
);
179 delegate
.SetBoundsFromAnimation(start
);
180 element
->Start(&delegate
, 1);
181 element
->Progress(start_time
, &delegate
);
182 CheckApproximatelyEqual(start
, delegate
.GetBoundsForAnimation());
183 element
->Progress(start_time
+ delta
/2, &delegate
);
184 CheckApproximatelyEqual(middle
, delegate
.GetBoundsForAnimation());
186 base::TimeDelta element_duration
;
187 EXPECT_TRUE(element
->IsFinished(start_time
+ delta
, &element_duration
));
188 EXPECT_EQ(delta
, element_duration
);
190 element
->Progress(start_time
+ delta
, &delegate
);
191 CheckApproximatelyEqual(target
, delegate
.GetBoundsForAnimation());
194 LayerAnimationElement::TargetValue
target_value(&delegate
);
195 element
->GetTargetValue(&target_value
);
196 CheckApproximatelyEqual(target
, target_value
.bounds
);
199 // Check that the opacity element progresses the delegate as expected and
200 // that the element can be reused after it completes.
201 TEST(LayerAnimationElementTest
, OpacityElement
) {
202 TestLayerAnimationDelegate delegate
;
206 base::TimeTicks start_time
;
207 base::TimeTicks effective_start_time
;
208 base::TimeDelta delta
= base::TimeDelta::FromSeconds(1);
209 scoped_ptr
<LayerAnimationElement
> element(
210 LayerAnimationElement::CreateOpacityElement(target
, delta
));
212 for (int i
= 0; i
< 2; ++i
) {
213 start_time
= effective_start_time
+ delta
;
214 element
->set_requested_start_time(start_time
);
215 delegate
.SetOpacityFromAnimation(start
);
216 element
->Start(&delegate
, 1);
217 element
->Progress(start_time
, &delegate
);
218 EXPECT_FLOAT_EQ(start
, element
->last_progressed_fraction());
219 effective_start_time
= start_time
+ delta
;
220 element
->set_effective_start_time(effective_start_time
);
221 element
->Progress(effective_start_time
, &delegate
);
222 EXPECT_FLOAT_EQ(start
, element
->last_progressed_fraction());
223 element
->Progress(effective_start_time
+ delta
/2, &delegate
);
224 EXPECT_FLOAT_EQ(middle
, element
->last_progressed_fraction());
226 base::TimeDelta element_duration
;
227 EXPECT_TRUE(element
->IsFinished(effective_start_time
+ delta
,
229 EXPECT_EQ(2 * delta
, element_duration
);
231 element
->Progress(effective_start_time
+ delta
, &delegate
);
232 EXPECT_FLOAT_EQ(target
, element
->last_progressed_fraction());
233 EXPECT_FLOAT_EQ(target
, delegate
.GetOpacityForAnimation());
236 LayerAnimationElement::TargetValue
target_value(&delegate
);
237 element
->GetTargetValue(&target_value
);
238 EXPECT_FLOAT_EQ(target
, target_value
.opacity
);
241 // Check that the visibility element progresses the delegate as expected and
242 // that the element can be reused after it completes.
243 TEST(LayerAnimationElementTest
, VisibilityElement
) {
244 TestLayerAnimationDelegate delegate
;
247 base::TimeTicks start_time
;
248 base::TimeDelta delta
= base::TimeDelta::FromSeconds(1);
249 scoped_ptr
<LayerAnimationElement
> element(
250 LayerAnimationElement::CreateVisibilityElement(target
, delta
));
252 for (int i
= 0; i
< 2; ++i
) {
254 element
->set_requested_start_time(start_time
);
255 delegate
.SetVisibilityFromAnimation(start
);
256 element
->Start(&delegate
, 1);
257 element
->Progress(start_time
, &delegate
);
258 EXPECT_TRUE(delegate
.GetVisibilityForAnimation());
259 element
->Progress(start_time
+ delta
/2, &delegate
);
260 EXPECT_TRUE(delegate
.GetVisibilityForAnimation());
262 base::TimeDelta element_duration
;
263 EXPECT_TRUE(element
->IsFinished(start_time
+ delta
, &element_duration
));
264 EXPECT_EQ(delta
, element_duration
);
266 element
->Progress(start_time
+ delta
, &delegate
);
267 EXPECT_FALSE(delegate
.GetVisibilityForAnimation());
270 LayerAnimationElement::TargetValue
target_value(&delegate
);
271 element
->GetTargetValue(&target_value
);
272 EXPECT_FALSE(target_value
.visibility
);
275 // Check that the Brightness element progresses the delegate as expected and
276 // that the element can be reused after it completes.
277 TEST(LayerAnimationElementTest
, BrightnessElement
) {
278 TestLayerAnimationDelegate delegate
;
282 base::TimeTicks start_time
;
283 base::TimeDelta delta
= base::TimeDelta::FromSeconds(1);
284 scoped_ptr
<LayerAnimationElement
> element(
285 LayerAnimationElement::CreateBrightnessElement(target
, delta
));
287 for (int i
= 0; i
< 2; ++i
) {
289 element
->set_requested_start_time(start_time
);
290 delegate
.SetBrightnessFromAnimation(start
);
291 element
->Start(&delegate
, 1);
292 element
->Progress(start_time
, &delegate
);
293 EXPECT_FLOAT_EQ(start
, delegate
.GetBrightnessForAnimation());
294 element
->Progress(start_time
+ delta
/2, &delegate
);
295 EXPECT_FLOAT_EQ(middle
, delegate
.GetBrightnessForAnimation());
297 base::TimeDelta element_duration
;
298 EXPECT_TRUE(element
->IsFinished(start_time
+ delta
, &element_duration
));
299 EXPECT_EQ(delta
, element_duration
);
301 element
->Progress(start_time
+ delta
, &delegate
);
302 EXPECT_FLOAT_EQ(target
, delegate
.GetBrightnessForAnimation());
305 LayerAnimationElement::TargetValue
target_value(&delegate
);
306 element
->GetTargetValue(&target_value
);
307 EXPECT_FLOAT_EQ(target
, target_value
.brightness
);
310 // Check that the Grayscale element progresses the delegate as expected and
311 // that the element can be reused after it completes.
312 TEST(LayerAnimationElementTest
, GrayscaleElement
) {
313 TestLayerAnimationDelegate delegate
;
317 base::TimeTicks start_time
;
318 base::TimeDelta delta
= base::TimeDelta::FromSeconds(1);
319 scoped_ptr
<LayerAnimationElement
> element(
320 LayerAnimationElement::CreateGrayscaleElement(target
, delta
));
322 for (int i
= 0; i
< 2; ++i
) {
324 element
->set_requested_start_time(start_time
);
325 delegate
.SetGrayscaleFromAnimation(start
);
326 element
->Start(&delegate
, 1);
327 element
->Progress(start_time
, &delegate
);
328 EXPECT_FLOAT_EQ(start
, delegate
.GetGrayscaleForAnimation());
329 element
->Progress(start_time
+ delta
/2, &delegate
);
330 EXPECT_FLOAT_EQ(middle
, delegate
.GetGrayscaleForAnimation());
332 base::TimeDelta element_duration
;
333 EXPECT_TRUE(element
->IsFinished(start_time
+ delta
, &element_duration
));
334 EXPECT_EQ(delta
, element_duration
);
336 element
->Progress(start_time
+ delta
, &delegate
);
337 EXPECT_FLOAT_EQ(target
, delegate
.GetGrayscaleForAnimation());
340 LayerAnimationElement::TargetValue
target_value(&delegate
);
341 element
->GetTargetValue(&target_value
);
342 EXPECT_FLOAT_EQ(target
, target_value
.grayscale
);
345 // Check that the pause element progresses the delegate as expected and
346 // that the element can be reused after it completes.
347 TEST(LayerAnimationElementTest
, PauseElement
) {
348 LayerAnimationElement::AnimatableProperties properties
=
349 LayerAnimationElement::TRANSFORM
| LayerAnimationElement::BOUNDS
|
350 LayerAnimationElement::OPACITY
| LayerAnimationElement::BRIGHTNESS
|
351 LayerAnimationElement::GRAYSCALE
;
353 base::TimeTicks start_time
;
354 base::TimeDelta delta
= base::TimeDelta::FromSeconds(1);
356 scoped_ptr
<LayerAnimationElement
> element(
357 LayerAnimationElement::CreatePauseElement(properties
, delta
));
359 TestLayerAnimationDelegate delegate
;
360 TestLayerAnimationDelegate copy
= delegate
;
363 element
->set_requested_start_time(start_time
);
364 element
->Start(&delegate
, 1);
366 // Pause should last for |delta|.
367 base::TimeDelta element_duration
;
368 EXPECT_TRUE(element
->IsFinished(start_time
+ delta
, &element_duration
));
369 EXPECT_EQ(delta
, element_duration
);
371 element
->Progress(start_time
+ delta
, &delegate
);
373 // Nothing should have changed.
374 CheckApproximatelyEqual(delegate
.GetBoundsForAnimation(),
375 copy
.GetBoundsForAnimation());
376 CheckApproximatelyEqual(delegate
.GetTransformForAnimation(),
377 copy
.GetTransformForAnimation());
378 EXPECT_FLOAT_EQ(delegate
.GetOpacityForAnimation(),
379 copy
.GetOpacityForAnimation());
380 EXPECT_FLOAT_EQ(delegate
.GetBrightnessForAnimation(),
381 copy
.GetBrightnessForAnimation());
382 EXPECT_FLOAT_EQ(delegate
.GetGrayscaleForAnimation(),
383 copy
.GetGrayscaleForAnimation());
386 // Check that a threaded opacity element updates the delegate as expected when
388 TEST(LayerAnimationElementTest
, AbortOpacityElement
) {
389 TestLayerAnimationDelegate delegate
;
392 base::TimeTicks start_time
;
393 base::TimeTicks effective_start_time
;
394 base::TimeDelta delta
= base::TimeDelta::FromSeconds(1);
395 scoped_ptr
<LayerAnimationElement
> element(
396 LayerAnimationElement::CreateOpacityElement(target
, delta
));
398 // Choose a non-linear Tween type.
399 gfx::Tween::Type tween_type
= gfx::Tween::EASE_IN
;
400 element
->set_tween_type(tween_type
);
402 delegate
.SetOpacityFromAnimation(start
);
404 // Aborting the element before it has started should not update the delegate.
405 element
->Abort(&delegate
);
406 EXPECT_FLOAT_EQ(start
, delegate
.GetOpacityForAnimation());
409 element
->set_requested_start_time(start_time
);
410 element
->Start(&delegate
, 1);
411 element
->Progress(start_time
, &delegate
);
412 effective_start_time
= start_time
+ delta
;
413 element
->set_effective_start_time(effective_start_time
);
414 element
->Progress(effective_start_time
, &delegate
);
415 element
->Progress(effective_start_time
+ delta
/2, &delegate
);
417 // Since the element has started, it should update the delegate when
419 element
->Abort(&delegate
);
420 EXPECT_FLOAT_EQ(gfx::Tween::CalculateValue(tween_type
, 0.5),
421 delegate
.GetOpacityForAnimation());
424 // Check that a threaded transform element updates the delegate as expected when
426 TEST(LayerAnimationElementTest
, AbortTransformElement
) {
427 TestLayerAnimationDelegate delegate
;
428 gfx::Transform start_transform
, target_transform
;
429 start_transform
.Rotate(-30.0);
430 target_transform
.Rotate(30.0);
431 base::TimeTicks start_time
;
432 base::TimeTicks effective_start_time
;
433 base::TimeDelta delta
= base::TimeDelta::FromSeconds(1);
434 scoped_ptr
<LayerAnimationElement
> element(
435 LayerAnimationElement::CreateTransformElement(target_transform
, delta
));
437 // Choose a non-linear Tween type.
438 gfx::Tween::Type tween_type
= gfx::Tween::EASE_IN
;
439 element
->set_tween_type(tween_type
);
441 delegate
.SetTransformFromAnimation(start_transform
);
443 // Aborting the element before it has started should not update the delegate.
444 element
->Abort(&delegate
);
445 CheckApproximatelyEqual(start_transform
, delegate
.GetTransformForAnimation());
448 element
->set_requested_start_time(start_time
);
449 element
->Start(&delegate
, 1);
450 element
->Progress(start_time
, &delegate
);
451 effective_start_time
= start_time
+ delta
;
452 element
->set_effective_start_time(effective_start_time
);
453 element
->Progress(effective_start_time
, &delegate
);
454 element
->Progress(effective_start_time
+ delta
/2, &delegate
);
456 // Since the element has started, it should update the delegate when
458 element
->Abort(&delegate
);
459 target_transform
.Blend(start_transform
,
460 gfx::Tween::CalculateValue(tween_type
, 0.5));
461 CheckApproximatelyEqual(target_transform
,
462 delegate
.GetTransformForAnimation());