• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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