Chromium Code Reviews| Index: ui/gfx/compositor/layer_animation_unittest.cc |
| diff --git a/ui/gfx/compositor/layer_animation_unittest.cc b/ui/gfx/compositor/layer_animation_unittest.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..3af8f7d6c3ae2dc9b2d0dcd82c4824b26a51143d |
| --- /dev/null |
| +++ b/ui/gfx/compositor/layer_animation_unittest.cc |
| @@ -0,0 +1,859 @@ |
| +// Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "base/basictypes.h" |
| +#include "base/compiler_specific.h" |
| +#include "base/memory/scoped_ptr.h" |
| +#include "base/time.h" |
| +#include "testing/gtest/include/gtest/gtest.h" |
| +#include "ui/gfx/rect.h" |
| +#include "ui/gfx/transform.h" |
| +#include "ui/gfx/compositor/layer_animation_delegate.h" |
| +#include "ui/gfx/compositor/layer_animation_element.h" |
| +#include "ui/gfx/compositor/layer_animation_sequence.h" |
| +#include "ui/gfx/compositor/layer_animator.h" |
| + |
| +namespace ui { |
| + |
| +namespace { |
| + |
| +void CheckApproximatelyEqual(const Transform& lhs, |
| + const Transform& rhs) { |
| + for (int i = 0; i < 4; ++i) { |
| + for (int j = 0; j < 4; ++j) { |
| + EXPECT_FLOAT_EQ(lhs.matrix().get(i, j), rhs.matrix().get(i, j)); |
| + } |
| + } |
| +} |
| + |
| +void CheckApproximatelyEqual(const gfx::Rect& lhs, |
| + const gfx::Rect& rhs) { |
| + EXPECT_FLOAT_EQ(lhs.x(), rhs.x()); |
| + EXPECT_FLOAT_EQ(lhs.y(), rhs.y()); |
| + EXPECT_FLOAT_EQ(lhs.width(), rhs.width()); |
| + EXPECT_FLOAT_EQ(lhs.height(), rhs.height()); |
| +} |
| + |
| +class DummyLayerAnimationDelegate : public LayerAnimationDelegate { |
| + public: |
| + DummyLayerAnimationDelegate() : opacity_(1.0f) { |
| + } |
| + |
| + virtual void SetBoundsFromAnimation(const gfx::Rect& bounds) OVERRIDE { |
| + bounds_ = bounds; |
| + } |
| + virtual void SetTransformFromAnimation(const Transform& transform) OVERRIDE { |
| + transform_ = transform; |
| + } |
| + virtual void SetOpacityFromAnimation(float opacity) OVERRIDE { |
| + opacity_ = opacity; |
| + } |
| + virtual void ScheduleDrawForAnimation() OVERRIDE { |
| + } |
| + virtual const gfx::Rect& GetBoundsForAnimation() const OVERRIDE { |
| + return bounds_; |
| + } |
| + virtual const Transform& GetTransformForAnimation() const OVERRIDE { |
| + return transform_; |
| + } |
| + virtual const float GetOpacityForAnimation() const OVERRIDE { |
| + return opacity_; |
| + } |
| + |
| + private: |
| + gfx::Rect bounds_; |
| + Transform transform_; |
| + float opacity_; |
| +}; |
| + |
| +TEST(LayerAnimationElementTest, TransformElement) { |
|
sky
2011/10/19 00:06:33
It's better form to create _unittest for each of t
|
| + DummyLayerAnimationDelegate delegate; |
| + Transform start_transform, target_transform, middle_transform; |
| + start_transform.SetRotate(-90); |
| + target_transform.SetRotate(90); |
| + base::TimeDelta delta = base::TimeDelta::FromSeconds(1); |
| + |
| + scoped_ptr<LayerAnimationElement> element( |
| + LayerAnimationElement::CreateTransformElement(target_transform, delta)); |
| + |
| + for (int i = 0; i < 2; ++i) { |
| + delegate.SetTransformFromAnimation(start_transform); |
| + element->Progress(0.0, &delegate); |
| + CheckApproximatelyEqual(start_transform, |
| + delegate.GetTransformForAnimation()); |
| + element->Progress(0.5, &delegate); |
| + CheckApproximatelyEqual(middle_transform, |
| + delegate.GetTransformForAnimation()); |
| + element->Progress(1.0, &delegate); |
| + CheckApproximatelyEqual(target_transform, |
| + delegate.GetTransformForAnimation()); |
| + } |
| + |
| + EXPECT_EQ(delta, element->Duration()); |
| +} |
| + |
| +TEST(LayerAnimationElementTest, BoundsElement) { |
|
sky
2011/10/19 00:06:33
Add descriptions for each of your tests.
|
| + DummyLayerAnimationDelegate delegate; |
| + gfx::Rect start, target, middle; |
| + start = target = middle = gfx::Rect(0, 0, 50, 50); |
| + start.set_x(-90); |
| + target.set_x(90); |
| + base::TimeDelta delta = base::TimeDelta::FromSeconds(1); |
| + |
| + scoped_ptr<LayerAnimationElement> element( |
| + LayerAnimationElement::CreateBoundsElement(target, delta)); |
| + |
| + for (int i = 0; i < 2; ++i) { |
| + delegate.SetBoundsFromAnimation(start); |
| + element->Progress(0.0, &delegate); |
| + CheckApproximatelyEqual(start, delegate.GetBoundsForAnimation()); |
| + element->Progress(0.5, &delegate); |
| + CheckApproximatelyEqual(middle, delegate.GetBoundsForAnimation()); |
| + element->Progress(1.0, &delegate); |
| + CheckApproximatelyEqual(target, delegate.GetBoundsForAnimation()); |
| + } |
| + |
| + EXPECT_EQ(delta, element->Duration()); |
| +} |
| + |
| +TEST(LayerAnimationElementTest, OpacityElement) { |
| + DummyLayerAnimationDelegate delegate; |
| + float start = 0.0; |
| + float middle = 0.5; |
| + float target = 1.0; |
| + base::TimeDelta delta = base::TimeDelta::FromSeconds(1); |
| + scoped_ptr<LayerAnimationElement> element( |
| + LayerAnimationElement::CreateOpacityElement(target, delta)); |
| + |
| + for (int i = 0; i < 2; ++i) { |
| + delegate.SetOpacityFromAnimation(start); |
| + element->Progress(0.0, &delegate); |
| + EXPECT_FLOAT_EQ(start, delegate.GetOpacityForAnimation()); |
| + element->Progress(0.5, &delegate); |
| + EXPECT_FLOAT_EQ(middle, delegate.GetOpacityForAnimation()); |
| + element->Progress(1.0, &delegate); |
| + EXPECT_FLOAT_EQ(target, delegate.GetOpacityForAnimation()); |
| + } |
| + |
| + EXPECT_EQ(delta, element->Duration()); |
| +} |
| + |
| +TEST(LayerAnimationElementTest, PauseElement) { |
| + LayerAnimationElement::AnimatableProperties properties; |
| + properties.insert(LayerAnimationElement::TRANSFORM); |
| + properties.insert(LayerAnimationElement::BOUNDS); |
| + properties.insert(LayerAnimationElement::OPACITY); |
| + base::TimeDelta delta = base::TimeDelta::FromSeconds(1); |
| + |
| + scoped_ptr<LayerAnimationElement> element( |
| + LayerAnimationElement::CreatePauseElement(properties, delta)); |
| + |
| + DummyLayerAnimationDelegate delegate; |
| + DummyLayerAnimationDelegate copy = delegate; |
| + |
| + element->Progress(1.0, &delegate); |
| + |
| + // Nothing should have changed. |
| + CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), |
| + copy.GetBoundsForAnimation()); |
| + CheckApproximatelyEqual(delegate.GetTransformForAnimation(), |
| + copy.GetTransformForAnimation()); |
| + EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), |
| + copy.GetOpacityForAnimation()); |
| + |
| + // Pause should last for |delta|. |
| + EXPECT_EQ(delta, element->Duration()); |
| +} |
| + |
| +TEST(LayerAnimationSequenceTest, NoElement) { |
| + LayerAnimationSequence sequence; |
| + EXPECT_EQ(sequence.duration(), base::TimeDelta()); |
| + EXPECT_TRUE(sequence.properties().size() == 0); |
| + LayerAnimationElement::AnimatableProperties properties; |
| + EXPECT_FALSE(sequence.HasCommonProperty(properties)); |
| +} |
| + |
| +TEST(LayerAnimationSequenceTest, SingleElement) { |
| + LayerAnimationSequence sequence; |
| + DummyLayerAnimationDelegate delegate; |
| + float start = 0.0; |
| + float middle = 0.5; |
| + float target = 1.0; |
| + base::TimeDelta delta = base::TimeDelta::FromSeconds(1); |
| + sequence.AddElement( |
| + LayerAnimationElement::CreateOpacityElement(target, delta)); |
| + |
| + for (int i = 0; i < 2; ++i) { |
| + delegate.SetOpacityFromAnimation(start); |
| + sequence.Progress(base::TimeDelta::FromMilliseconds(0), &delegate); |
| + EXPECT_FLOAT_EQ(start, delegate.GetOpacityForAnimation()); |
| + sequence.Progress(base::TimeDelta::FromMilliseconds(500), &delegate); |
| + EXPECT_FLOAT_EQ(middle, delegate.GetOpacityForAnimation()); |
| + sequence.Progress(base::TimeDelta::FromMilliseconds(1000), &delegate); |
| + EXPECT_FLOAT_EQ(target, delegate.GetOpacityForAnimation()); |
| + } |
| + |
| + EXPECT_TRUE(sequence.properties().size() == 1); |
| + EXPECT_TRUE(sequence.properties().find(LayerAnimationElement::OPACITY) != |
| + sequence.properties().end()); |
| + EXPECT_EQ(delta, sequence.duration()); |
| +} |
| + |
| +TEST(LayerAnimationSequenceTest, MultipleElement) { |
| + LayerAnimationSequence sequence; |
| + DummyLayerAnimationDelegate delegate; |
| + float start_opacity = 0.0; |
| + float middle_opacity = 0.5; |
| + float target_opacity = 1.0; |
| + base::TimeDelta delta = base::TimeDelta::FromSeconds(1); |
| + sequence.AddElement( |
| + LayerAnimationElement::CreateOpacityElement(target_opacity, delta)); |
| + |
| + // Pause bounds for a second. |
| + LayerAnimationElement::AnimatableProperties properties; |
| + properties.insert(LayerAnimationElement::BOUNDS); |
| + |
| + sequence.AddElement( |
| + LayerAnimationElement::CreatePauseElement(properties, delta)); |
| + |
| + Transform start_transform, target_transform, middle_transform; |
| + start_transform.SetRotate(-90); |
| + target_transform.SetRotate(90); |
| + |
| + sequence.AddElement( |
| + LayerAnimationElement::CreateTransformElement(target_transform, delta)); |
| + |
| + for (int i = 0; i < 2; ++i) { |
| + delegate.SetOpacityFromAnimation(start_opacity); |
| + delegate.SetTransformFromAnimation(start_transform); |
| + |
| + sequence.Progress(base::TimeDelta::FromMilliseconds(0), &delegate); |
| + EXPECT_FLOAT_EQ(start_opacity, delegate.GetOpacityForAnimation()); |
| + sequence.Progress(base::TimeDelta::FromMilliseconds(500), &delegate); |
| + EXPECT_FLOAT_EQ(middle_opacity, delegate.GetOpacityForAnimation()); |
| + sequence.Progress(base::TimeDelta::FromMilliseconds(1000), &delegate); |
| + EXPECT_FLOAT_EQ(target_opacity, delegate.GetOpacityForAnimation()); |
| + DummyLayerAnimationDelegate copy = delegate; |
| + |
| + // In the middle of the pause -- nothing should have changed. |
| + sequence.Progress(base::TimeDelta::FromMilliseconds(1500), &delegate); |
| + CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), |
| + copy.GetBoundsForAnimation()); |
| + CheckApproximatelyEqual(delegate.GetTransformForAnimation(), |
| + copy.GetTransformForAnimation()); |
| + EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), |
| + copy.GetOpacityForAnimation()); |
| + |
| + |
| + sequence.Progress(base::TimeDelta::FromMilliseconds(2000), &delegate); |
| + CheckApproximatelyEqual(start_transform, |
| + delegate.GetTransformForAnimation()); |
| + sequence.Progress(base::TimeDelta::FromMilliseconds(2500), &delegate); |
| + CheckApproximatelyEqual(middle_transform, |
| + delegate.GetTransformForAnimation()); |
| + sequence.Progress(base::TimeDelta::FromMilliseconds(3000), &delegate); |
| + CheckApproximatelyEqual(target_transform, |
| + delegate.GetTransformForAnimation()); |
| + } |
| + |
| + EXPECT_TRUE(sequence.properties().size() == 3); |
| + EXPECT_TRUE(sequence.properties().find(LayerAnimationElement::OPACITY) != |
| + sequence.properties().end()); |
| + EXPECT_TRUE(sequence.properties().find(LayerAnimationElement::TRANSFORM) != |
| + sequence.properties().end()); |
| + EXPECT_TRUE(sequence.properties().find(LayerAnimationElement::BOUNDS) != |
| + sequence.properties().end()); |
| + EXPECT_EQ(delta + delta + delta, sequence.duration()); |
| +} |
| + |
| +TEST(LayerAnimatorTest, ImplicitAnimation) { |
| + scoped_ptr<LayerAnimator> animator( |
| + LayerAnimator::CreateImplicitAnimator()); |
| + animator->SetAnimationForTest(NULL); |
| + DummyLayerAnimationDelegate delegate; |
| + animator->SetDelegate(&delegate); |
| + base::TimeTicks now = base::TimeTicks::Now(); |
| + animator->SetOpacity(0.5); |
| + EXPECT_TRUE(animator->IsAnimating()); |
| + animator->Step(now + base::TimeDelta::FromSeconds(1)); |
| + EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), 0.5); |
| +} |
| + |
| +TEST(LayerAnimatorTest, NoImplicitAnimation) { |
| + scoped_ptr<LayerAnimator> animator( |
| + LayerAnimator::CreateDefaultAnimator()); |
| + animator->SetAnimationForTest(NULL); |
| + DummyLayerAnimationDelegate delegate; |
| + animator->SetDelegate(&delegate); |
| + base::TimeTicks now = base::TimeTicks::Now(); |
| + animator->SetOpacity(0.5); |
| + EXPECT_FALSE(animator->IsAnimating()); |
| + EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), 0.5); |
| +} |
| + |
| +TEST(LayerAnimatorTest, StopAnimatingProperty) { |
| + scoped_ptr<LayerAnimator> animator( |
| + LayerAnimator::CreateImplicitAnimator()); |
| + animator->SetAnimationForTest(NULL); |
| + DummyLayerAnimationDelegate delegate; |
| + animator->SetDelegate(&delegate); |
| + base::TimeTicks now = base::TimeTicks::Now(); |
| + double target_opacity(0.5); |
| + gfx::Rect target_bounds(0, 0, 50, 50); |
| + animator->SetOpacity(target_opacity); |
| + animator->SetBounds(target_bounds); |
| + animator->StopAnimatingProperty(LayerAnimationElement::OPACITY); |
| + EXPECT_TRUE(animator->IsAnimating()); |
| + EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), 0.5); |
| + animator->StopAnimatingProperty(LayerAnimationElement::BOUNDS); |
| + EXPECT_FALSE(animator->IsAnimating()); |
| + CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), target_bounds); |
| +} |
| + |
| +TEST(LayerAnimatorTest, StopAnimating) { |
| + scoped_ptr<LayerAnimator> animator( |
| + LayerAnimator::CreateImplicitAnimator()); |
| + animator->SetAnimationForTest(NULL); |
| + DummyLayerAnimationDelegate delegate; |
| + animator->SetDelegate(&delegate); |
| + base::TimeTicks now = base::TimeTicks::Now(); |
| + double target_opacity(0.5); |
| + gfx::Rect target_bounds(0, 0, 50, 50); |
| + animator->SetOpacity(target_opacity); |
| + animator->SetBounds(target_bounds); |
| + EXPECT_TRUE(animator->IsAnimating()); |
| + animator->StopAnimating(); |
| + EXPECT_FALSE(animator->IsAnimating()); |
| + EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), 0.5); |
| + CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), target_bounds); |
| +} |
| + |
| +// schedule animation (that can run immediately) |
| +TEST(LayerAnimatorTest, ScheduleAnimationThatCanRunImmediately) { |
| + scoped_ptr<LayerAnimator> animator(LayerAnimator::CreateDefaultAnimator()); |
| + animator->SetAnimationForTest(NULL); |
| + DummyLayerAnimationDelegate delegate; |
| + animator->SetDelegate(&delegate); |
| + |
| + double start_opacity(0.0); |
| + double middle_opacity(0.5); |
| + double target_opacity(1.0); |
| + |
| + base::TimeDelta delta = base::TimeDelta::FromSeconds(1); |
| + |
| + delegate.SetOpacityFromAnimation(start_opacity); |
| + |
| + animator->ScheduleAnimation( |
| + new LayerAnimationSequence( |
| + LayerAnimationElement::CreateOpacityElement(target_opacity, delta))); |
| + |
| + EXPECT_TRUE(animator->IsAnimating()); |
| + EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity); |
| + |
| + base::TimeTicks start_time = animator->get_last_step_time_for_test(); |
| + |
| + animator->Step(start_time + base::TimeDelta::FromMilliseconds(500)); |
| + |
| + EXPECT_TRUE(animator->IsAnimating()); |
| + EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), middle_opacity); |
| + |
| + animator->Step(start_time + base::TimeDelta::FromMilliseconds(1000)); |
| + |
| + EXPECT_FALSE(animator->IsAnimating()); |
| + EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), target_opacity); |
| +} |
| + |
| +// schedule two animations on separate properties |
| +TEST(LayerAnimatorTest, ScheduleTwoAnimationsThatCanRunImmediately) { |
| + scoped_ptr<LayerAnimator> animator(LayerAnimator::CreateDefaultAnimator()); |
| + animator->SetAnimationForTest(NULL); |
| + DummyLayerAnimationDelegate delegate; |
| + animator->SetDelegate(&delegate); |
| + |
| + double start_opacity(0.0); |
| + double middle_opacity(0.5); |
| + double target_opacity(1.0); |
| + |
| + gfx::Rect start_bounds, target_bounds, middle_bounds; |
| + start_bounds = target_bounds = middle_bounds = gfx::Rect(0, 0, 50, 50); |
| + start_bounds.set_x(-90); |
| + target_bounds.set_x(90); |
| + |
| + base::TimeDelta delta = base::TimeDelta::FromSeconds(1); |
| + |
| + delegate.SetOpacityFromAnimation(start_opacity); |
| + delegate.SetBoundsFromAnimation(start_bounds); |
| + |
| + animator->ScheduleAnimation( |
| + new LayerAnimationSequence( |
| + LayerAnimationElement::CreateOpacityElement(target_opacity, delta))); |
| + |
| + animator->ScheduleAnimation( |
| + new LayerAnimationSequence( |
| + LayerAnimationElement::CreateBoundsElement(target_bounds, delta))); |
| + |
| + EXPECT_TRUE(animator->IsAnimating()); |
| + EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity); |
| + CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), start_bounds); |
| + |
| + base::TimeTicks start_time = animator->get_last_step_time_for_test(); |
| + |
| + animator->Step(start_time + base::TimeDelta::FromMilliseconds(500)); |
| + |
| + EXPECT_TRUE(animator->IsAnimating()); |
| + EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), middle_opacity); |
| + CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), middle_bounds); |
| + |
| + animator->Step(start_time + base::TimeDelta::FromMilliseconds(1000)); |
| + |
| + EXPECT_FALSE(animator->IsAnimating()); |
| + EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), target_opacity); |
| + CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), target_bounds); |
| +} |
| + |
| +// schedule two animations on the same property |
| +TEST(LayerAnimatorTest, ScheduleTwoAnimationsOnSameProperty) { |
| + scoped_ptr<LayerAnimator> animator(LayerAnimator::CreateDefaultAnimator()); |
| + animator->SetAnimationForTest(NULL); |
| + DummyLayerAnimationDelegate delegate; |
| + animator->SetDelegate(&delegate); |
| + |
| + double start_opacity(0.0); |
| + double middle_opacity(0.5); |
| + double target_opacity(1.0); |
| + |
| + base::TimeDelta delta = base::TimeDelta::FromSeconds(1); |
| + |
| + delegate.SetOpacityFromAnimation(start_opacity); |
| + |
| + animator->ScheduleAnimation( |
| + new LayerAnimationSequence( |
| + LayerAnimationElement::CreateOpacityElement(target_opacity, delta))); |
| + |
| + animator->ScheduleAnimation( |
| + new LayerAnimationSequence( |
| + LayerAnimationElement::CreateOpacityElement(start_opacity, delta))); |
| + |
| + EXPECT_TRUE(animator->IsAnimating()); |
| + EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity); |
| + |
| + base::TimeTicks start_time = animator->get_last_step_time_for_test(); |
| + |
| + animator->Step(start_time + base::TimeDelta::FromMilliseconds(500)); |
| + |
| + EXPECT_TRUE(animator->IsAnimating()); |
| + EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), middle_opacity); |
| + |
| + animator->Step(start_time + base::TimeDelta::FromMilliseconds(1000)); |
| + |
| + EXPECT_TRUE(animator->IsAnimating()); |
| + EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), target_opacity); |
| + |
| + animator->Step(start_time + base::TimeDelta::FromMilliseconds(1500)); |
| + |
| + EXPECT_TRUE(animator->IsAnimating()); |
| + EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), middle_opacity); |
| + |
| + animator->Step(start_time + base::TimeDelta::FromMilliseconds(2000)); |
| + |
| + EXPECT_FALSE(animator->IsAnimating()); |
| + EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity); |
| +} |
| + |
| +// schedule {o}, {o,b}, {b} and ensure that {b} doesn't run right away. |
| +TEST(LayerAnimatorTest, ScheduleBlockedAnimation) { |
| + scoped_ptr<LayerAnimator> animator(LayerAnimator::CreateDefaultAnimator()); |
| + animator->SetAnimationForTest(NULL); |
| + DummyLayerAnimationDelegate delegate; |
| + animator->SetDelegate(&delegate); |
| + |
| + double start_opacity(0.0); |
| + double middle_opacity(0.5); |
| + double target_opacity(1.0); |
| + |
| + gfx::Rect start_bounds, target_bounds, middle_bounds; |
| + start_bounds = target_bounds = middle_bounds = gfx::Rect(0, 0, 50, 50); |
| + start_bounds.set_x(-90); |
| + target_bounds.set_x(90); |
| + |
| + base::TimeDelta delta = base::TimeDelta::FromSeconds(1); |
| + |
| + delegate.SetOpacityFromAnimation(start_opacity); |
| + delegate.SetBoundsFromAnimation(start_bounds); |
| + |
| + animator->ScheduleAnimation( |
| + new LayerAnimationSequence( |
| + LayerAnimationElement::CreateOpacityElement(target_opacity, delta))); |
| + |
| + scoped_ptr<LayerAnimationSequence> bounds_and_opacity( |
| + new LayerAnimationSequence( |
| + LayerAnimationElement::CreateOpacityElement(start_opacity, delta))); |
| + |
| + bounds_and_opacity->AddElement( |
| + LayerAnimationElement::CreateBoundsElement(target_bounds, delta)); |
| + |
| + animator->ScheduleAnimation(bounds_and_opacity.release()); |
| + |
| + animator->ScheduleAnimation( |
| + new LayerAnimationSequence( |
| + LayerAnimationElement::CreateBoundsElement(start_bounds, delta))); |
| + |
| + EXPECT_TRUE(animator->IsAnimating()); |
| + EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity); |
| + CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), start_bounds); |
| + |
| + base::TimeTicks start_time = animator->get_last_step_time_for_test(); |
| + |
| + animator->Step(start_time + base::TimeDelta::FromMilliseconds(500)); |
| + |
| + EXPECT_TRUE(animator->IsAnimating()); |
| + EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), middle_opacity); |
| + CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), start_bounds); |
| + |
| + animator->Step(start_time + base::TimeDelta::FromMilliseconds(1000)); |
| + |
| + EXPECT_TRUE(animator->IsAnimating()); |
| + EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), target_opacity); |
| + CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), start_bounds); |
| + |
| + animator->Step(start_time + base::TimeDelta::FromMilliseconds(2000)); |
| + |
| + EXPECT_TRUE(animator->IsAnimating()); |
| + EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity); |
| + CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), start_bounds); |
| + |
| + animator->Step(start_time + base::TimeDelta::FromMilliseconds(3000)); |
| + |
| + EXPECT_TRUE(animator->IsAnimating()); |
| + EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity); |
| + CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), target_bounds); |
| + |
| + animator->Step(start_time + base::TimeDelta::FromMilliseconds(4000)); |
| + |
| + EXPECT_FALSE(animator->IsAnimating()); |
| + EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity); |
| + CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), start_bounds); |
| +} |
| + |
| +// schedule {o} and then schedule {o} and {b} together |
| +TEST(LayerAnimatorTest, ScheduleTogether) { |
| + scoped_ptr<LayerAnimator> animator(LayerAnimator::CreateDefaultAnimator()); |
| + animator->SetAnimationForTest(NULL); |
| + DummyLayerAnimationDelegate delegate; |
| + animator->SetDelegate(&delegate); |
| + |
| + double start_opacity(0.0); |
| + double target_opacity(1.0); |
| + |
| + gfx::Rect start_bounds, target_bounds, middle_bounds; |
| + start_bounds = target_bounds = gfx::Rect(0, 0, 50, 50); |
| + start_bounds.set_x(-90); |
| + target_bounds.set_x(90); |
| + |
| + base::TimeDelta delta = base::TimeDelta::FromSeconds(1); |
| + |
| + delegate.SetOpacityFromAnimation(start_opacity); |
| + delegate.SetBoundsFromAnimation(start_bounds); |
| + |
| + animator->ScheduleAnimation( |
| + new LayerAnimationSequence( |
| + LayerAnimationElement::CreateOpacityElement(target_opacity, delta))); |
| + |
| + std::vector<LayerAnimationSequence*> sequences; |
| + sequences.push_back(new LayerAnimationSequence( |
| + LayerAnimationElement::CreateOpacityElement(start_opacity, delta))); |
| + sequences.push_back(new LayerAnimationSequence( |
| + LayerAnimationElement::CreateBoundsElement(target_bounds, delta))); |
| + |
| + animator->ScheduleTogether(sequences); |
| + |
| + EXPECT_TRUE(animator->IsAnimating()); |
| + EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity); |
| + CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), start_bounds); |
| + |
| + base::TimeTicks start_time = animator->get_last_step_time_for_test(); |
| + |
| + animator->Step(start_time + base::TimeDelta::FromMilliseconds(1000)); |
| + |
| + EXPECT_TRUE(animator->IsAnimating()); |
| + EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), target_opacity); |
| + CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), start_bounds); |
| + |
| + animator->Step(start_time + base::TimeDelta::FromMilliseconds(2000)); |
| + |
| + EXPECT_FALSE(animator->IsAnimating()); |
| + EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity); |
| + CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), target_bounds); |
| +} |
| + |
| +// start animation (that can run immediately) |
| +TEST(LayerAnimatorTest, StartAnimationThatCanRunImmediately) { |
| + scoped_ptr<LayerAnimator> animator(LayerAnimator::CreateDefaultAnimator()); |
| + animator->SetAnimationForTest(NULL); |
| + DummyLayerAnimationDelegate delegate; |
| + animator->SetDelegate(&delegate); |
| + |
| + double start_opacity(0.0); |
| + double middle_opacity(0.5); |
| + double target_opacity(1.0); |
| + |
| + base::TimeDelta delta = base::TimeDelta::FromSeconds(1); |
| + |
| + delegate.SetOpacityFromAnimation(start_opacity); |
| + |
| + animator->StartAnimation( |
| + new LayerAnimationSequence( |
| + LayerAnimationElement::CreateOpacityElement(target_opacity, delta))); |
| + |
| + EXPECT_TRUE(animator->IsAnimating()); |
| + EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity); |
| + |
| + base::TimeTicks start_time = animator->get_last_step_time_for_test(); |
| + |
| + animator->Step(start_time + base::TimeDelta::FromMilliseconds(500)); |
| + |
| + EXPECT_TRUE(animator->IsAnimating()); |
| + EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), middle_opacity); |
| + |
| + animator->Step(start_time + base::TimeDelta::FromMilliseconds(1000)); |
| + |
| + EXPECT_FALSE(animator->IsAnimating()); |
| + EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), target_opacity); |
| +} |
| + |
| +// preempt by immediately setting new target |
| +TEST(LayerAnimatorTest, PreemptBySettingNewTarget) { |
| + scoped_ptr<LayerAnimator> animator(LayerAnimator::CreateDefaultAnimator()); |
| + animator->SetAnimationForTest(NULL); |
| + DummyLayerAnimationDelegate delegate; |
| + animator->SetDelegate(&delegate); |
| + |
| + double start_opacity(0.0); |
| + double target_opacity(1.0); |
| + |
| + base::TimeDelta delta = base::TimeDelta::FromSeconds(1); |
| + |
| + delegate.SetOpacityFromAnimation(start_opacity); |
| + |
| + animator->set_preemption_strategy(LayerAnimator::IMMEDIATELY_SET_NEW_TARGET); |
| + |
| + animator->StartAnimation( |
| + new LayerAnimationSequence( |
| + LayerAnimationElement::CreateOpacityElement(target_opacity, delta))); |
| + |
| + animator->StartAnimation( |
| + new LayerAnimationSequence( |
| + LayerAnimationElement::CreateOpacityElement(start_opacity, delta))); |
| + |
| + EXPECT_FALSE(animator->IsAnimating()); |
| + EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity); |
| +} |
| + |
| +// preempt by animating to new target |
| +TEST(LayerAnimatorTest, PreemptByImmediatelyAnimatingToNewTarget) { |
| + scoped_ptr<LayerAnimator> animator(LayerAnimator::CreateDefaultAnimator()); |
| + animator->SetAnimationForTest(NULL); |
| + DummyLayerAnimationDelegate delegate; |
| + animator->SetDelegate(&delegate); |
| + |
| + double start_opacity(0.0); |
| + double middle_opacity(0.5); |
| + double target_opacity(1.0); |
| + |
| + base::TimeDelta delta = base::TimeDelta::FromSeconds(1); |
| + |
| + delegate.SetOpacityFromAnimation(start_opacity); |
| + |
| + animator->set_preemption_strategy( |
| + LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); |
| + |
| + animator->StartAnimation( |
| + new LayerAnimationSequence( |
| + LayerAnimationElement::CreateOpacityElement(target_opacity, delta))); |
| + |
| + base::TimeTicks start_time = animator->get_last_step_time_for_test(); |
| + |
| + animator->Step(start_time + base::TimeDelta::FromMilliseconds(500)); |
| + |
| + animator->StartAnimation( |
| + new LayerAnimationSequence( |
| + LayerAnimationElement::CreateOpacityElement(start_opacity, delta))); |
| + |
| + EXPECT_TRUE(animator->IsAnimating()); |
| + EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), middle_opacity); |
| + |
| + animator->StartAnimation( |
| + new LayerAnimationSequence( |
| + LayerAnimationElement::CreateOpacityElement(start_opacity, delta))); |
| + |
| + EXPECT_TRUE(animator->IsAnimating()); |
| + |
| + animator->Step(start_time + base::TimeDelta::FromMilliseconds(1000)); |
| + |
| + EXPECT_TRUE(animator->IsAnimating()); |
| + EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), |
| + 0.5 * (start_opacity + middle_opacity)); |
| + |
| + animator->Step(start_time + base::TimeDelta::FromMilliseconds(1500)); |
| + |
| + EXPECT_FALSE(animator->IsAnimating()); |
| + EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity); |
| +} |
| + |
| +// preempt by enqueuing the new animation |
| +TEST(LayerAnimatorTest, PreemptEnqueueNewAnimation) { |
| + scoped_ptr<LayerAnimator> animator(LayerAnimator::CreateDefaultAnimator()); |
| + animator->SetAnimationForTest(NULL); |
| + DummyLayerAnimationDelegate delegate; |
| + animator->SetDelegate(&delegate); |
| + |
| + double start_opacity(0.0); |
| + double middle_opacity(0.5); |
| + double target_opacity(1.0); |
| + |
| + base::TimeDelta delta = base::TimeDelta::FromSeconds(1); |
| + |
| + delegate.SetOpacityFromAnimation(start_opacity); |
| + |
| + animator->set_preemption_strategy(LayerAnimator::ENQUEUE_NEW_ANIMATION); |
| + |
| + animator->StartAnimation( |
| + new LayerAnimationSequence( |
| + LayerAnimationElement::CreateOpacityElement(target_opacity, delta))); |
| + |
| + base::TimeTicks start_time = animator->get_last_step_time_for_test(); |
| + |
| + animator->Step(start_time + base::TimeDelta::FromMilliseconds(500)); |
| + |
| + animator->StartAnimation( |
| + new LayerAnimationSequence( |
| + LayerAnimationElement::CreateOpacityElement(start_opacity, delta))); |
| + |
| + EXPECT_TRUE(animator->IsAnimating()); |
| + EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), middle_opacity); |
| + |
| + EXPECT_TRUE(animator->IsAnimating()); |
| + |
| + animator->Step(start_time + base::TimeDelta::FromMilliseconds(1000)); |
| + |
| + EXPECT_TRUE(animator->IsAnimating()); |
| + EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), target_opacity); |
| + |
| + animator->Step(start_time + base::TimeDelta::FromMilliseconds(1500)); |
| + |
| + EXPECT_TRUE(animator->IsAnimating()); |
| + EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), middle_opacity); |
| + |
| + animator->Step(start_time + base::TimeDelta::FromMilliseconds(2000)); |
| + |
| + EXPECT_FALSE(animator->IsAnimating()); |
| + EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity); |
| +} |
| + |
| +// Start an animation when there are sequences waiting in the queue. In this |
| +// case, all pending and running animations should be finished, and the new |
| +// animation started. |
| +TEST(LayerAnimatorTest, PreemptyByReplacingQueuedAnimations) { |
| + scoped_ptr<LayerAnimator> animator(LayerAnimator::CreateDefaultAnimator()); |
| + animator->SetAnimationForTest(NULL); |
| + DummyLayerAnimationDelegate delegate; |
| + animator->SetDelegate(&delegate); |
| + |
| + double start_opacity(0.0); |
| + double middle_opacity(0.5); |
| + double target_opacity(1.0); |
| + |
| + base::TimeDelta delta = base::TimeDelta::FromSeconds(1); |
| + |
| + delegate.SetOpacityFromAnimation(start_opacity); |
| + |
| + animator->set_preemption_strategy(LayerAnimator::REPLACE_QUEUED_ANIMATIONS); |
| + |
| + animator->StartAnimation( |
| + new LayerAnimationSequence( |
| + LayerAnimationElement::CreateOpacityElement(target_opacity, delta))); |
| + |
| + base::TimeTicks start_time = animator->get_last_step_time_for_test(); |
| + |
| + animator->Step(start_time + base::TimeDelta::FromMilliseconds(500)); |
| + |
| + animator->StartAnimation( |
| + new LayerAnimationSequence( |
| + LayerAnimationElement::CreateOpacityElement(middle_opacity, delta))); |
| + |
| + // Queue should now have two animations. Starting a third should replace the |
| + // second. |
| + animator->StartAnimation( |
| + new LayerAnimationSequence( |
| + LayerAnimationElement::CreateOpacityElement(start_opacity, delta))); |
| + |
| + EXPECT_TRUE(animator->IsAnimating()); |
| + EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), middle_opacity); |
| + |
| + animator->Step(start_time + base::TimeDelta::FromMilliseconds(1000)); |
| + |
| + EXPECT_TRUE(animator->IsAnimating()); |
| + EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), target_opacity); |
| + |
| + animator->Step(start_time + base::TimeDelta::FromMilliseconds(1500)); |
| + |
| + EXPECT_TRUE(animator->IsAnimating()); |
| + EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), middle_opacity); |
| + |
| + animator->Step(start_time + base::TimeDelta::FromMilliseconds(2000)); |
| + |
| + EXPECT_FALSE(animator->IsAnimating()); |
| + EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity); |
| +} |
| + |
| +// cyclic sequence |
| +TEST(LayerAnimatorTest, CyclicSequences) { |
| + scoped_ptr<LayerAnimator> animator(LayerAnimator::CreateDefaultAnimator()); |
| + animator->SetAnimationForTest(NULL); |
| + DummyLayerAnimationDelegate delegate; |
| + animator->SetDelegate(&delegate); |
| + |
| + double start_opacity(0.0); |
| + double target_opacity(1.0); |
| + |
| + base::TimeDelta delta = base::TimeDelta::FromSeconds(1); |
| + |
| + delegate.SetOpacityFromAnimation(start_opacity); |
| + |
| + scoped_ptr<LayerAnimationSequence> sequence( |
| + new LayerAnimationSequence( |
| + LayerAnimationElement::CreateOpacityElement(target_opacity, delta))); |
| + |
| + sequence->AddElement( |
| + LayerAnimationElement::CreateOpacityElement(start_opacity, delta)); |
| + |
| + sequence->set_is_cyclic(true); |
| + |
| + animator->StartAnimation(sequence.release()); |
| + |
| + base::TimeTicks start_time = animator->get_last_step_time_for_test(); |
| + |
| + animator->Step(start_time + base::TimeDelta::FromMilliseconds(1000)); |
| + |
| + EXPECT_TRUE(animator->IsAnimating()); |
| + EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), target_opacity); |
| + |
| + animator->Step(start_time + base::TimeDelta::FromMilliseconds(2000)); |
| + |
| + EXPECT_TRUE(animator->IsAnimating()); |
| + EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity); |
| + |
| + animator->Step(start_time + base::TimeDelta::FromMilliseconds(3000)); |
| + |
| + EXPECT_TRUE(animator->IsAnimating()); |
| + EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), target_opacity); |
| + |
| + animator->StopAnimatingProperty(LayerAnimationElement::OPACITY); |
| + |
| + EXPECT_FALSE(animator->IsAnimating()); |
| +} |
| + |
| +} // namespace |
| + |
| +} // namespace ui |