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 <memory>
8 
9 #include "base/compiler_specific.h"
10 #include "base/strings/stringprintf.h"
11 #include "base/time/time.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 #include "ui/compositor/layer_animation_delegate.h"
14 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
15 #include "ui/compositor/test/test_layer_animation_delegate.h"
16 #include "ui/compositor/test/test_utils.h"
17 #include "ui/gfx/geometry/rect.h"
18 #include "ui/gfx/transform.h"
19 
20 namespace ui {
21 
22 namespace {
23 
24 // Verify that the TargetValue(TestLayerAnimationDelegate*) constructor
25 // correctly assigns values. See www.crbug.com/483134.
TEST(TargetValueTest,VerifyLayerAnimationDelegateConstructor)26 TEST(TargetValueTest, VerifyLayerAnimationDelegateConstructor) {
27   const gfx::Rect kBounds(1, 2, 3, 5);
28   const gfx::Transform kTransform(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f);
29   const float kOpacity = 1.235f;
30   const bool kVisibility = false;
31   const float kBrightness = 2.358f;
32   const float kGrayscale = 2.5813f;
33   const SkColor kColor = SK_ColorCYAN;
34   const gfx::Rect kClipRect(2, 3, 4, 5);
35   const gfx::RoundedCornersF kRoundedCorners(2.0f, 3.0f, 4.0f, 5.0f);
36 
37   TestLayerAnimationDelegate delegate;
38   delegate.SetBoundsFromAnimation(kBounds,
39                                   PropertyChangeReason::NOT_FROM_ANIMATION);
40   delegate.SetTransformFromAnimation(kTransform,
41                                      PropertyChangeReason::NOT_FROM_ANIMATION);
42   delegate.SetOpacityFromAnimation(kOpacity,
43                                    PropertyChangeReason::NOT_FROM_ANIMATION);
44   delegate.SetVisibilityFromAnimation(kVisibility,
45                                       PropertyChangeReason::NOT_FROM_ANIMATION);
46   delegate.SetBrightnessFromAnimation(kBrightness,
47                                       PropertyChangeReason::NOT_FROM_ANIMATION);
48   delegate.SetGrayscaleFromAnimation(kGrayscale,
49                                      PropertyChangeReason::NOT_FROM_ANIMATION);
50   delegate.SetColorFromAnimation(kColor,
51                                  PropertyChangeReason::NOT_FROM_ANIMATION);
52   delegate.SetClipRectFromAnimation(kClipRect,
53                                     PropertyChangeReason::NOT_FROM_ANIMATION);
54   delegate.SetRoundedCornersFromAnimation(
55       kRoundedCorners, PropertyChangeReason::NOT_FROM_ANIMATION);
56 
57   LayerAnimationElement::TargetValue target_value(&delegate);
58 
59   EXPECT_EQ(kBounds, target_value.bounds);
60   EXPECT_EQ(kTransform, target_value.transform);
61   EXPECT_FLOAT_EQ(kOpacity, target_value.opacity);
62   EXPECT_EQ(kVisibility, target_value.visibility);
63   EXPECT_FLOAT_EQ(kBrightness, target_value.brightness);
64   EXPECT_FLOAT_EQ(kGrayscale, target_value.grayscale);
65   EXPECT_EQ(SK_ColorCYAN, target_value.color);
66   EXPECT_EQ(kClipRect, target_value.clip_rect);
67   EXPECT_EQ(kRoundedCorners, target_value.rounded_corners);
68 }
69 
70 // Check that the transformation element progresses the delegate as expected and
71 // that the element can be reused after it completes.
TEST(LayerAnimationElementTest,TransformElement)72 TEST(LayerAnimationElementTest, TransformElement) {
73   TestLayerAnimationDelegate delegate;
74   gfx::Transform start_transform, target_transform;
75   start_transform.Rotate(-30.0);
76   target_transform.Rotate(30.0);
77   base::TimeTicks start_time;
78   base::TimeTicks effective_start_time;
79   base::TimeDelta delta = base::TimeDelta::FromSeconds(1);
80 
81   std::unique_ptr<LayerAnimationElement> element =
82       LayerAnimationElement::CreateTransformElement(target_transform, delta);
83   element->set_animation_group_id(1);
84 
85   for (int i = 0; i < 2; ++i) {
86     start_time = effective_start_time + delta;
87     element->set_requested_start_time(start_time);
88     delegate.SetTransformFromAnimation(
89         start_transform, PropertyChangeReason::NOT_FROM_ANIMATION);
90     element->Start(&delegate, 1);
91     element->Progress(start_time, &delegate);
92     CheckApproximatelyEqual(start_transform,
93                             delegate.GetTransformForAnimation());
94     delegate.ExpectLastPropertyChangeReason(
95         PropertyChangeReason::FROM_ANIMATION);
96     effective_start_time = start_time + delta;
97     element->set_effective_start_time(effective_start_time);
98     element->Progress(effective_start_time, &delegate);
99     EXPECT_FLOAT_EQ(0.0, element->last_progressed_fraction());
100     element->Progress(effective_start_time + delta/2, &delegate);
101     EXPECT_FLOAT_EQ(0.5, element->last_progressed_fraction());
102 
103     base::TimeDelta element_duration;
104     EXPECT_TRUE(element->IsFinished(effective_start_time + delta,
105                                     &element_duration));
106     EXPECT_EQ(2 * delta, element_duration);
107 
108     element->Progress(effective_start_time + delta, &delegate);
109     EXPECT_FLOAT_EQ(1.0, element->last_progressed_fraction());
110     CheckApproximatelyEqual(target_transform,
111                             delegate.GetTransformForAnimation());
112     delegate.ExpectLastPropertyChangeReason(
113         PropertyChangeReason::FROM_ANIMATION);
114   }
115 
116   LayerAnimationElement::TargetValue target_value(&delegate);
117   element->GetTargetValue(&target_value);
118   CheckApproximatelyEqual(target_transform, target_value.transform);
119 }
120 
121 // Check that the bounds element progresses the delegate as expected and
122 // that the element can be reused after it completes.
TEST(LayerAnimationElementTest,BoundsElement)123 TEST(LayerAnimationElementTest, BoundsElement) {
124   TestLayerAnimationDelegate delegate;
125   gfx::Rect start, target, middle;
126   start = target = middle = gfx::Rect(0, 0, 50, 50);
127   start.set_x(-90);
128   target.set_x(90);
129   base::TimeTicks start_time;
130   base::TimeDelta delta = base::TimeDelta::FromSeconds(1);
131 
132   std::unique_ptr<LayerAnimationElement> element =
133       LayerAnimationElement::CreateBoundsElement(target, delta);
134 
135   for (int i = 0; i < 2; ++i) {
136     start_time += delta;
137     element->set_requested_start_time(start_time);
138     delegate.SetBoundsFromAnimation(start,
139                                     PropertyChangeReason::NOT_FROM_ANIMATION);
140     element->Start(&delegate, 1);
141     element->Progress(start_time, &delegate);
142     CheckApproximatelyEqual(start, delegate.GetBoundsForAnimation());
143     delegate.ExpectLastPropertyChangeReason(
144         PropertyChangeReason::FROM_ANIMATION);
145     element->Progress(start_time + delta/2, &delegate);
146     CheckApproximatelyEqual(middle, delegate.GetBoundsForAnimation());
147     delegate.ExpectLastPropertyChangeReason(
148         PropertyChangeReason::FROM_ANIMATION);
149 
150     base::TimeDelta element_duration;
151     EXPECT_TRUE(element->IsFinished(start_time + delta, &element_duration));
152     EXPECT_EQ(delta, element_duration);
153 
154     element->Progress(start_time + delta, &delegate);
155     CheckApproximatelyEqual(target, delegate.GetBoundsForAnimation());
156     delegate.ExpectLastPropertyChangeReason(
157         PropertyChangeReason::FROM_ANIMATION);
158   }
159 
160   LayerAnimationElement::TargetValue target_value(&delegate);
161   element->GetTargetValue(&target_value);
162   CheckApproximatelyEqual(target, target_value.bounds);
163 }
164 
165 // Check that the opacity element progresses the delegate as expected and
166 // that the element can be reused after it completes.
TEST(LayerAnimationElementTest,OpacityElement)167 TEST(LayerAnimationElementTest, OpacityElement) {
168   TestLayerAnimationDelegate delegate;
169   float start = 0.0;
170   float middle = 0.5;
171   float target = 1.0;
172   base::TimeTicks start_time;
173   base::TimeTicks effective_start_time;
174   base::TimeDelta delta = base::TimeDelta::FromSeconds(1);
175   std::unique_ptr<LayerAnimationElement> element =
176       LayerAnimationElement::CreateOpacityElement(target, delta);
177 
178   for (int i = 0; i < 2; ++i) {
179     start_time = effective_start_time + delta;
180     element->set_requested_start_time(start_time);
181     delegate.SetOpacityFromAnimation(start,
182                                      PropertyChangeReason::NOT_FROM_ANIMATION);
183     element->Start(&delegate, 1);
184     element->Progress(start_time, &delegate);
185     EXPECT_FLOAT_EQ(start, element->last_progressed_fraction());
186     effective_start_time = start_time + delta;
187     element->set_effective_start_time(effective_start_time);
188     element->Progress(effective_start_time, &delegate);
189     EXPECT_FLOAT_EQ(start, element->last_progressed_fraction());
190     element->Progress(effective_start_time + delta/2, &delegate);
191     EXPECT_FLOAT_EQ(middle, element->last_progressed_fraction());
192 
193     base::TimeDelta element_duration;
194     EXPECT_TRUE(element->IsFinished(effective_start_time + delta,
195                                     &element_duration));
196     EXPECT_EQ(2 * delta, element_duration);
197 
198     element->Progress(effective_start_time + delta, &delegate);
199     EXPECT_FLOAT_EQ(target, element->last_progressed_fraction());
200     EXPECT_FLOAT_EQ(target, delegate.GetOpacityForAnimation());
201     delegate.ExpectLastPropertyChangeReason(
202         PropertyChangeReason::FROM_ANIMATION);
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   std::unique_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(
225         start, PropertyChangeReason::NOT_FROM_ANIMATION);
226     element->Start(&delegate, 1);
227     element->Progress(start_time, &delegate);
228     EXPECT_TRUE(delegate.GetVisibilityForAnimation());
229     delegate.ExpectLastPropertyChangeReason(
230         PropertyChangeReason::FROM_ANIMATION);
231     element->Progress(start_time + delta/2, &delegate);
232     EXPECT_TRUE(delegate.GetVisibilityForAnimation());
233     delegate.ExpectLastPropertyChangeReason(
234         PropertyChangeReason::FROM_ANIMATION);
235 
236     base::TimeDelta element_duration;
237     EXPECT_TRUE(element->IsFinished(start_time + delta, &element_duration));
238     EXPECT_EQ(delta, element_duration);
239 
240     element->Progress(start_time + delta, &delegate);
241     EXPECT_FALSE(delegate.GetVisibilityForAnimation());
242     delegate.ExpectLastPropertyChangeReason(
243         PropertyChangeReason::FROM_ANIMATION);
244   }
245 
246   LayerAnimationElement::TargetValue target_value(&delegate);
247   element->GetTargetValue(&target_value);
248   EXPECT_FALSE(target_value.visibility);
249 }
250 
251 // Check that the Brightness element progresses the delegate as expected and
252 // that the element can be reused after it completes.
TEST(LayerAnimationElementTest,BrightnessElement)253 TEST(LayerAnimationElementTest, BrightnessElement) {
254   TestLayerAnimationDelegate delegate;
255   float start = 0.0;
256   float middle = 0.5;
257   float target = 1.0;
258   base::TimeTicks start_time;
259   base::TimeDelta delta = base::TimeDelta::FromSeconds(1);
260   std::unique_ptr<LayerAnimationElement> element =
261       LayerAnimationElement::CreateBrightnessElement(target, delta);
262 
263   for (int i = 0; i < 2; ++i) {
264     start_time += delta;
265     element->set_requested_start_time(start_time);
266     delegate.SetBrightnessFromAnimation(
267         start, PropertyChangeReason::NOT_FROM_ANIMATION);
268     element->Start(&delegate, 1);
269     element->Progress(start_time, &delegate);
270     EXPECT_FLOAT_EQ(start, delegate.GetBrightnessForAnimation());
271     delegate.ExpectLastPropertyChangeReason(
272         PropertyChangeReason::FROM_ANIMATION);
273     element->Progress(start_time + delta/2, &delegate);
274     EXPECT_FLOAT_EQ(middle, delegate.GetBrightnessForAnimation());
275     delegate.ExpectLastPropertyChangeReason(
276         PropertyChangeReason::FROM_ANIMATION);
277 
278     base::TimeDelta element_duration;
279     EXPECT_TRUE(element->IsFinished(start_time + delta, &element_duration));
280     EXPECT_EQ(delta, element_duration);
281 
282     element->Progress(start_time + delta, &delegate);
283     EXPECT_FLOAT_EQ(target, delegate.GetBrightnessForAnimation());
284     delegate.ExpectLastPropertyChangeReason(
285         PropertyChangeReason::FROM_ANIMATION);
286   }
287 
288   LayerAnimationElement::TargetValue target_value(&delegate);
289   element->GetTargetValue(&target_value);
290   EXPECT_FLOAT_EQ(target, target_value.brightness);
291 }
292 
293 // Check that the Grayscale element progresses the delegate as expected and
294 // that the element can be reused after it completes.
TEST(LayerAnimationElementTest,GrayscaleElement)295 TEST(LayerAnimationElementTest, GrayscaleElement) {
296   TestLayerAnimationDelegate delegate;
297   float start = 0.0;
298   float middle = 0.5;
299   float target = 1.0;
300   base::TimeTicks start_time;
301   base::TimeDelta delta = base::TimeDelta::FromSeconds(1);
302   std::unique_ptr<LayerAnimationElement> element =
303       LayerAnimationElement::CreateGrayscaleElement(target, delta);
304 
305   for (int i = 0; i < 2; ++i) {
306     start_time += delta;
307     element->set_requested_start_time(start_time);
308     delegate.SetGrayscaleFromAnimation(
309         start, PropertyChangeReason::NOT_FROM_ANIMATION);
310     element->Start(&delegate, 1);
311     element->Progress(start_time, &delegate);
312     EXPECT_FLOAT_EQ(start, delegate.GetGrayscaleForAnimation());
313     delegate.ExpectLastPropertyChangeReason(
314         PropertyChangeReason::FROM_ANIMATION);
315     element->Progress(start_time + delta/2, &delegate);
316     EXPECT_FLOAT_EQ(middle, delegate.GetGrayscaleForAnimation());
317     delegate.ExpectLastPropertyChangeReason(
318         PropertyChangeReason::FROM_ANIMATION);
319 
320     base::TimeDelta element_duration;
321     EXPECT_TRUE(element->IsFinished(start_time + delta, &element_duration));
322     EXPECT_EQ(delta, element_duration);
323 
324     element->Progress(start_time + delta, &delegate);
325     EXPECT_FLOAT_EQ(target, delegate.GetGrayscaleForAnimation());
326     delegate.ExpectLastPropertyChangeReason(
327         PropertyChangeReason::FROM_ANIMATION);
328   }
329 
330   LayerAnimationElement::TargetValue target_value(&delegate);
331   element->GetTargetValue(&target_value);
332   EXPECT_FLOAT_EQ(target, target_value.grayscale);
333 }
334 
335 // Check that the pause element progresses the delegate as expected and
336 // that the element can be reused after it completes.
TEST(LayerAnimationElementTest,PauseElement)337 TEST(LayerAnimationElementTest, PauseElement) {
338   LayerAnimationElement::AnimatableProperties properties =
339       LayerAnimationElement::TRANSFORM | LayerAnimationElement::BOUNDS |
340       LayerAnimationElement::OPACITY | LayerAnimationElement::BRIGHTNESS |
341       LayerAnimationElement::GRAYSCALE;
342 
343   base::TimeTicks start_time;
344   base::TimeDelta delta = base::TimeDelta::FromSeconds(1);
345 
346   std::unique_ptr<LayerAnimationElement> element =
347       LayerAnimationElement::CreatePauseElement(properties, delta);
348 
349   TestLayerAnimationDelegate delegate;
350   TestLayerAnimationDelegate copy = delegate;
351 
352   start_time += delta;
353   element->set_requested_start_time(start_time);
354   element->Start(&delegate, 1);
355 
356   // Pause should last for |delta|.
357   base::TimeDelta element_duration;
358   EXPECT_TRUE(element->IsFinished(start_time + delta, &element_duration));
359   EXPECT_EQ(delta, element_duration);
360 
361   element->Progress(start_time + delta, &delegate);
362 
363   // Nothing should have changed.
364   CheckApproximatelyEqual(delegate.GetBoundsForAnimation(),
365                           copy.GetBoundsForAnimation());
366   CheckApproximatelyEqual(delegate.GetTransformForAnimation(),
367                           copy.GetTransformForAnimation());
368   EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(),
369                   copy.GetOpacityForAnimation());
370   EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(),
371                   copy.GetBrightnessForAnimation());
372   EXPECT_FLOAT_EQ(delegate.GetGrayscaleForAnimation(),
373                   copy.GetGrayscaleForAnimation());
374 }
375 
376 // Check that the ClipRect element progresses the delegate as expected and
377 // that the element can be reused after it completes.
TEST(LayerAnimationElementTest,ClipRectElement)378 TEST(LayerAnimationElementTest, ClipRectElement) {
379   TestLayerAnimationDelegate delegate;
380   gfx::Rect start, target, middle;
381   start = target = middle = gfx::Rect(0, 0, 50, 50);
382 
383   start.set_x(-10);
384   target.set_x(10);
385 
386   start.set_y(-20);
387   target.set_y(20);
388 
389   start.set_width(70);
390   target.set_width(30);
391   base::TimeTicks start_time;
392   base::TimeDelta delta = base::TimeDelta::FromSeconds(1);
393 
394   std::unique_ptr<LayerAnimationElement> element =
395       LayerAnimationElement::CreateClipRectElement(target, delta);
396 
397   for (int i = 0; i < 2; ++i) {
398     start_time += delta;
399     element->set_requested_start_time(start_time);
400     delegate.SetClipRectFromAnimation(start,
401                                       PropertyChangeReason::NOT_FROM_ANIMATION);
402     element->Start(&delegate, 1);
403     element->Progress(start_time, &delegate);
404     CheckApproximatelyEqual(start, delegate.GetClipRectForAnimation());
405     delegate.ExpectLastPropertyChangeReason(
406         PropertyChangeReason::FROM_ANIMATION);
407     element->Progress(start_time + delta / 2, &delegate);
408     CheckApproximatelyEqual(middle, delegate.GetClipRectForAnimation());
409     delegate.ExpectLastPropertyChangeReason(
410         PropertyChangeReason::FROM_ANIMATION);
411 
412     base::TimeDelta element_duration;
413     EXPECT_TRUE(element->IsFinished(start_time + delta, &element_duration));
414     EXPECT_EQ(delta, element_duration);
415 
416     element->Progress(start_time + delta, &delegate);
417     CheckApproximatelyEqual(target, delegate.GetClipRectForAnimation());
418     delegate.ExpectLastPropertyChangeReason(
419         PropertyChangeReason::FROM_ANIMATION);
420   }
421 
422   LayerAnimationElement::TargetValue target_value(&delegate);
423   element->GetTargetValue(&target_value);
424   CheckApproximatelyEqual(target, target_value.clip_rect);
425 }
426 
427 // Check that the RoundedCorners element progresses the delegate as expected and
428 // that the element can be reused after it completes.
TEST(LayerAnimationElementTest,RoundedCornersElement)429 TEST(LayerAnimationElementTest, RoundedCornersElement) {
430   TestLayerAnimationDelegate delegate;
431   gfx::RoundedCornersF start(1.0f, 2.0f, 3.0f, 4.0f);
432   gfx::RoundedCornersF target(11.0f, 12.0f, 13.0f, 14.0f);
433   gfx::RoundedCornersF middle(6.0f, 7.0f, 8.0f, 9.0f);
434 
435   base::TimeTicks start_time;
436   base::TimeDelta delta = base::TimeDelta::FromSeconds(1);
437 
438   std::unique_ptr<LayerAnimationElement> element =
439       LayerAnimationElement::CreateRoundedCornersElement(target, delta);
440 
441   for (int i = 0; i < 2; ++i) {
442     start_time += delta;
443     element->set_requested_start_time(start_time);
444     delegate.SetRoundedCornersFromAnimation(
445         start, PropertyChangeReason::NOT_FROM_ANIMATION);
446     element->Start(&delegate, 1);
447     element->Progress(start_time, &delegate);
448     CheckApproximatelyEqual(start, delegate.GetRoundedCornersForAnimation());
449     delegate.ExpectLastPropertyChangeReason(
450         PropertyChangeReason::FROM_ANIMATION);
451     element->Progress(start_time + delta / 2, &delegate);
452     CheckApproximatelyEqual(middle, delegate.GetRoundedCornersForAnimation());
453     delegate.ExpectLastPropertyChangeReason(
454         PropertyChangeReason::FROM_ANIMATION);
455 
456     base::TimeDelta element_duration;
457     EXPECT_TRUE(element->IsFinished(start_time + delta, &element_duration));
458     EXPECT_EQ(delta, element_duration);
459 
460     element->Progress(start_time + delta, &delegate);
461     CheckApproximatelyEqual(target, delegate.GetRoundedCornersForAnimation());
462     delegate.ExpectLastPropertyChangeReason(
463         PropertyChangeReason::FROM_ANIMATION);
464   }
465 
466   LayerAnimationElement::TargetValue target_value(&delegate);
467   element->GetTargetValue(&target_value);
468   CheckApproximatelyEqual(target, target_value.rounded_corners);
469 }
470 
471 // Check that a threaded opacity element updates the delegate as expected when
472 // aborted.
TEST(LayerAnimationElementTest,AbortOpacityElement)473 TEST(LayerAnimationElementTest, AbortOpacityElement) {
474   TestLayerAnimationDelegate delegate;
475   float start = 0.0;
476   float target = 1.0;
477   base::TimeTicks start_time;
478   base::TimeTicks effective_start_time;
479   base::TimeDelta delta = base::TimeDelta::FromSeconds(1);
480   std::unique_ptr<LayerAnimationElement> element =
481       LayerAnimationElement::CreateOpacityElement(target, delta);
482 
483   // Choose a non-linear Tween type.
484   gfx::Tween::Type tween_type = gfx::Tween::EASE_IN;
485   element->set_tween_type(tween_type);
486 
487   delegate.SetOpacityFromAnimation(start,
488                                    PropertyChangeReason::NOT_FROM_ANIMATION);
489   delegate.ExpectLastPropertyChangeReason(
490       PropertyChangeReason::NOT_FROM_ANIMATION);
491 
492   // Aborting the element before it has started should not update the delegate.
493   element->Abort(&delegate);
494   EXPECT_FLOAT_EQ(start, delegate.GetOpacityForAnimation());
495   delegate.ExpectLastPropertyChangeReasonIsUnset();
496 
497   start_time += delta;
498   element->set_requested_start_time(start_time);
499   element->Start(&delegate, 1);
500   element->Progress(start_time, &delegate);
501   effective_start_time = start_time + delta;
502   element->set_effective_start_time(effective_start_time);
503   element->Progress(effective_start_time, &delegate);
504   element->Progress(effective_start_time + delta/2, &delegate);
505 
506   // Since the element has started, it should update the delegate when
507   // aborted.
508   element->Abort(&delegate);
509   EXPECT_FLOAT_EQ(gfx::Tween::CalculateValue(tween_type, 0.5),
510                   delegate.GetOpacityForAnimation());
511   delegate.ExpectLastPropertyChangeReason(PropertyChangeReason::FROM_ANIMATION);
512 }
513 
514 // Check that a threaded transform element updates the delegate as expected when
515 // aborted.
TEST(LayerAnimationElementTest,AbortTransformElement)516 TEST(LayerAnimationElementTest, AbortTransformElement) {
517   TestLayerAnimationDelegate delegate;
518   gfx::Transform start_transform, target_transform;
519   start_transform.Rotate(-30.0);
520   target_transform.Rotate(30.0);
521   base::TimeTicks start_time;
522   base::TimeTicks effective_start_time;
523   base::TimeDelta delta = base::TimeDelta::FromSeconds(1);
524   std::unique_ptr<LayerAnimationElement> element =
525       LayerAnimationElement::CreateTransformElement(target_transform, delta);
526 
527   // Choose a non-linear Tween type.
528   gfx::Tween::Type tween_type = gfx::Tween::EASE_IN;
529   element->set_tween_type(tween_type);
530 
531   delegate.SetTransformFromAnimation(start_transform,
532                                      PropertyChangeReason::NOT_FROM_ANIMATION);
533   delegate.ExpectLastPropertyChangeReason(
534       PropertyChangeReason::NOT_FROM_ANIMATION);
535 
536   // Aborting the element before it has started should not update the delegate.
537   element->Abort(&delegate);
538   CheckApproximatelyEqual(start_transform, delegate.GetTransformForAnimation());
539   delegate.ExpectLastPropertyChangeReasonIsUnset();
540 
541   start_time += delta;
542   element->set_requested_start_time(start_time);
543   element->Start(&delegate, 1);
544   element->Progress(start_time, &delegate);
545   effective_start_time = start_time + delta;
546   element->set_effective_start_time(effective_start_time);
547   element->Progress(effective_start_time, &delegate);
548   element->Progress(effective_start_time + delta/2, &delegate);
549 
550   // Since the element has started, it should update the delegate when
551   // aborted.
552   element->Abort(&delegate);
553   target_transform.Blend(start_transform,
554                          gfx::Tween::CalculateValue(tween_type, 0.5));
555   CheckApproximatelyEqual(target_transform,
556                           delegate.GetTransformForAnimation());
557   delegate.ExpectLastPropertyChangeReason(PropertyChangeReason::FROM_ANIMATION);
558 }
559 
560 // Check that an opacity element is not threaded if the start and target values
561 // are the same.
TEST(LayerAnimationElementTest,OpacityElementIsThreaded)562 TEST(LayerAnimationElementTest, OpacityElementIsThreaded) {
563   TestLayerAnimationDelegate delegate;
564   float start = 0.0;
565   float target = 1.0;
566   delegate.SetOpacityFromAnimation(start,
567                                    PropertyChangeReason::NOT_FROM_ANIMATION);
568   base::TimeDelta delta = base::TimeDelta::FromSeconds(1);
569   std::unique_ptr<LayerAnimationElement> element =
570       LayerAnimationElement::CreateOpacityElement(target, delta);
571   EXPECT_TRUE(element->IsThreaded(&delegate));
572   element->ProgressToEnd(&delegate);
573   EXPECT_FLOAT_EQ(target, delegate.GetOpacityForAnimation());
574   delegate.ExpectLastPropertyChangeReason(PropertyChangeReason::FROM_ANIMATION);
575 
576   start = 1.0;
577   delegate.SetOpacityFromAnimation(start,
578                                    PropertyChangeReason::NOT_FROM_ANIMATION);
579   element = LayerAnimationElement::CreateOpacityElement(target, delta);
580   EXPECT_FALSE(element->IsThreaded(&delegate));
581   element->ProgressToEnd(&delegate);
582   EXPECT_FLOAT_EQ(target, delegate.GetOpacityForAnimation());
583   delegate.ExpectLastPropertyChangeReason(PropertyChangeReason::FROM_ANIMATION);
584 }
585 
TEST(LayerAnimationElementTest,ToString)586 TEST(LayerAnimationElementTest, ToString) {
587   float target = 1.0;
588   base::TimeDelta delta = base::TimeDelta::FromSeconds(1);
589   std::unique_ptr<LayerAnimationElement> element =
590       LayerAnimationElement::CreateOpacityElement(target, delta);
591   element->set_animation_group_id(42);
592   // TODO(wkorman): Test varying last_progressed_fraction.
593   EXPECT_EQ(
594       base::StringPrintf("LayerAnimationElement{name=ThreadedOpacityTransition,"
595                          " id=%d, group=42, "
596                          "last_progressed_fraction=0.00}",
597                          element->keyframe_model_id()),
598       element->ToString());
599 }
600 
601 } // namespace
602 
603 } // namespace ui
604