Home | History | Annotate | Download | only in compositor
      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.
     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.
     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.
     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.
    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.
    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.
    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.
    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.
    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.
    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.
    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.
    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.
    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