layer_animation_element_unittest.cc revision d0247b1b59f9c528cb6df88b4f2b9afaf80d181e
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
19namespace ui {
20
21namespace {
22
23// Check that the transformation element progresses the delegate as expected and
24// that the element can be reused after it completes.
25TEST(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.
70TEST(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.
84TEST(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.
100TEST(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.
133TEST(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.
170TEST(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.
212TEST(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.
246TEST(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.
281TEST(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.
316TEST(LayerAnimationElementTest, PauseElement) {
317  LayerAnimationElement::AnimatableProperties properties;
318  properties.insert(LayerAnimationElement::TRANSFORM);
319  properties.insert(LayerAnimationElement::BOUNDS);
320  properties.insert(LayerAnimationElement::OPACITY);
321  properties.insert(LayerAnimationElement::BRIGHTNESS);
322  properties.insert(LayerAnimationElement::GRAYSCALE);
323  base::TimeTicks start_time;
324  base::TimeDelta delta = base::TimeDelta::FromSeconds(1);
325
326  scoped_ptr<LayerAnimationElement> element(
327      LayerAnimationElement::CreatePauseElement(properties, delta));
328
329  TestLayerAnimationDelegate delegate;
330  TestLayerAnimationDelegate copy = delegate;
331
332  start_time += delta;
333  element->set_requested_start_time(start_time);
334  element->Start(&delegate, 1);
335
336  // Pause should last for |delta|.
337  base::TimeDelta element_duration;
338  EXPECT_TRUE(element->IsFinished(start_time + delta, &element_duration));
339  EXPECT_EQ(delta, element_duration);
340
341  element->Progress(start_time + delta, &delegate);
342
343  // Nothing should have changed.
344  CheckApproximatelyEqual(delegate.GetBoundsForAnimation(),
345                          copy.GetBoundsForAnimation());
346  CheckApproximatelyEqual(delegate.GetTransformForAnimation(),
347                          copy.GetTransformForAnimation());
348  EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(),
349                  copy.GetOpacityForAnimation());
350  EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(),
351                  copy.GetBrightnessForAnimation());
352  EXPECT_FLOAT_EQ(delegate.GetGrayscaleForAnimation(),
353                  copy.GetGrayscaleForAnimation());
354}
355
356// Check that a threaded opacity element updates the delegate as expected when
357// aborted.
358TEST(LayerAnimationElementTest, AbortOpacityElement) {
359  TestLayerAnimationDelegate delegate;
360  float start = 0.0;
361  float target = 1.0;
362  base::TimeTicks start_time;
363  base::TimeTicks effective_start_time;
364  base::TimeDelta delta = base::TimeDelta::FromSeconds(1);
365  scoped_ptr<LayerAnimationElement> element(
366      LayerAnimationElement::CreateOpacityElement(target, delta));
367
368  // Choose a non-linear Tween type.
369  gfx::Tween::Type tween_type = gfx::Tween::EASE_IN;
370  element->set_tween_type(tween_type);
371
372  delegate.SetOpacityFromAnimation(start);
373
374  // Aborting the element before it has started should not update the delegate.
375  element->Abort(&delegate);
376  EXPECT_FLOAT_EQ(start, delegate.GetOpacityForAnimation());
377
378  start_time += delta;
379  element->set_requested_start_time(start_time);
380  element->Start(&delegate, 1);
381  element->Progress(start_time, &delegate);
382  effective_start_time = start_time + delta;
383  element->set_effective_start_time(effective_start_time);
384  element->Progress(effective_start_time, &delegate);
385  element->Progress(effective_start_time + delta/2, &delegate);
386
387  // Since the element has started, it should update the delegate when
388  // aborted.
389  element->Abort(&delegate);
390  EXPECT_FLOAT_EQ(gfx::Tween::CalculateValue(tween_type, 0.5),
391                  delegate.GetOpacityForAnimation());
392}
393
394// Check that a threaded transform element updates the delegate as expected when
395// aborted.
396TEST(LayerAnimationElementTest, AbortTransformElement) {
397  TestLayerAnimationDelegate delegate;
398  gfx::Transform start_transform, target_transform;
399  start_transform.Rotate(-30.0);
400  target_transform.Rotate(30.0);
401  base::TimeTicks start_time;
402  base::TimeTicks effective_start_time;
403  base::TimeDelta delta = base::TimeDelta::FromSeconds(1);
404  scoped_ptr<LayerAnimationElement> element(
405      LayerAnimationElement::CreateTransformElement(target_transform, delta));
406
407  // Choose a non-linear Tween type.
408  gfx::Tween::Type tween_type = gfx::Tween::EASE_IN;
409  element->set_tween_type(tween_type);
410
411  delegate.SetTransformFromAnimation(start_transform);
412
413  // Aborting the element before it has started should not update the delegate.
414  element->Abort(&delegate);
415  CheckApproximatelyEqual(start_transform, delegate.GetTransformForAnimation());
416
417  start_time += delta;
418  element->set_requested_start_time(start_time);
419  element->Start(&delegate, 1);
420  element->Progress(start_time, &delegate);
421  effective_start_time = start_time + delta;
422  element->set_effective_start_time(effective_start_time);
423  element->Progress(effective_start_time, &delegate);
424  element->Progress(effective_start_time + delta/2, &delegate);
425
426  // Since the element has started, it should update the delegate when
427  // aborted.
428  element->Abort(&delegate);
429  target_transform.Blend(start_transform,
430                         gfx::Tween::CalculateValue(tween_type, 0.5));
431  CheckApproximatelyEqual(target_transform,
432                          delegate.GetTransformForAnimation());
433}
434
435} // namespace
436
437} // namespace ui
438