Index: ui/gfx/compositor/layer_animator_unittest.cc |
diff --git a/ui/gfx/compositor/layer_animator_unittest.cc b/ui/gfx/compositor/layer_animator_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..6eccb529460751ea8ebd18d2d044066ab74d0e4b |
--- /dev/null |
+++ b/ui/gfx/compositor/layer_animator_unittest.cc |
@@ -0,0 +1,648 @@ |
+// 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 "ui/gfx/compositor/layer_animator.h" |
+ |
+#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/test_utils.h" |
+#include "ui/gfx/compositor/test_layer_animation_delegate.h" |
+ |
+namespace ui { |
+ |
+namespace { |
+ |
+// Checks that setting a property on an implicit animator causes an animation to |
+// happen. |
+TEST(LayerAnimatorTest, ImplicitAnimation) { |
+ scoped_ptr<LayerAnimator> animator(LayerAnimator::CreateImplicitAnimator()); |
+ AnimationContainerElement* element = animator.get(); |
+ animator->set_disable_timer_for_test(true); |
+ TestLayerAnimationDelegate delegate; |
+ animator->SetDelegate(&delegate); |
+ base::TimeTicks now = base::TimeTicks::Now(); |
+ animator->SetOpacity(0.5); |
+ EXPECT_TRUE(animator->is_animating()); |
+ element->Step(now + base::TimeDelta::FromSeconds(1)); |
+ EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), 0.5); |
+} |
+ |
+// Checks that if the animator is a default animator, that implicit animations |
+// are not started. |
+TEST(LayerAnimatorTest, NoImplicitAnimation) { |
+ scoped_ptr<LayerAnimator> animator(LayerAnimator::CreateDefaultAnimator()); |
+ animator->set_disable_timer_for_test(true); |
+ TestLayerAnimationDelegate delegate; |
+ animator->SetDelegate(&delegate); |
+ base::TimeTicks now = base::TimeTicks::Now(); |
+ animator->SetOpacity(0.5); |
+ EXPECT_FALSE(animator->is_animating()); |
+ EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), 0.5); |
+} |
+ |
+// Checks that StopAnimatingProperty stops animation for that property, and also |
+// skips the stopped animation to the end. |
+TEST(LayerAnimatorTest, StopAnimatingProperty) { |
+ scoped_ptr<LayerAnimator> animator(LayerAnimator::CreateImplicitAnimator()); |
+ animator->set_disable_timer_for_test(true); |
+ TestLayerAnimationDelegate 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->is_animating()); |
+ EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), 0.5); |
+ animator->StopAnimatingProperty(LayerAnimationElement::BOUNDS); |
+ EXPECT_FALSE(animator->is_animating()); |
+ CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), target_bounds); |
+} |
+ |
+// Checks that multiple running animation for separate properties can be stopped |
+// simultaneously and that all animations are advanced to their target values. |
+TEST(LayerAnimatorTest, StopAnimating) { |
+ scoped_ptr<LayerAnimator> animator(LayerAnimator::CreateImplicitAnimator()); |
+ animator->set_disable_timer_for_test(true); |
+ TestLayerAnimationDelegate 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->is_animating()); |
+ animator->StopAnimating(); |
+ EXPECT_FALSE(animator->is_animating()); |
+ EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), 0.5); |
+ CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), target_bounds); |
+} |
+ |
+// Schedule an animation that can run immediately. This is the trivial case and |
+// should result in the animation being started immediately. |
+TEST(LayerAnimatorTest, ScheduleAnimationThatCanRunImmediately) { |
+ scoped_ptr<LayerAnimator> animator(LayerAnimator::CreateDefaultAnimator()); |
+ AnimationContainerElement* element = animator.get(); |
+ animator->set_disable_timer_for_test(true); |
+ TestLayerAnimationDelegate 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->is_animating()); |
+ EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity); |
+ |
+ base::TimeTicks start_time = animator->get_last_step_time_for_test(); |
+ |
+ element->Step(start_time + base::TimeDelta::FromMilliseconds(500)); |
+ |
+ EXPECT_TRUE(animator->is_animating()); |
+ EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), middle_opacity); |
+ |
+ element->Step(start_time + base::TimeDelta::FromMilliseconds(1000)); |
+ |
+ EXPECT_FALSE(animator->is_animating()); |
+ EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), target_opacity); |
+} |
+ |
+// Schedule two animations on separate properties. Both animations should |
+// start immediately and should progress in lock step. |
+TEST(LayerAnimatorTest, ScheduleTwoAnimationsThatCanRunImmediately) { |
+ scoped_ptr<LayerAnimator> animator(LayerAnimator::CreateDefaultAnimator()); |
+ AnimationContainerElement* element = animator.get(); |
+ animator->set_disable_timer_for_test(true); |
+ TestLayerAnimationDelegate 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->is_animating()); |
+ EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity); |
+ CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), start_bounds); |
+ |
+ base::TimeTicks start_time = animator->get_last_step_time_for_test(); |
+ |
+ element->Step(start_time + base::TimeDelta::FromMilliseconds(500)); |
+ |
+ EXPECT_TRUE(animator->is_animating()); |
+ EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), middle_opacity); |
+ CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), middle_bounds); |
+ |
+ element->Step(start_time + base::TimeDelta::FromMilliseconds(1000)); |
+ |
+ EXPECT_FALSE(animator->is_animating()); |
+ EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), target_opacity); |
+ CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), target_bounds); |
+} |
+ |
+// Schedule two animations on the same property. In this case, the two |
+// animations should run one after another. |
+TEST(LayerAnimatorTest, ScheduleTwoAnimationsOnSameProperty) { |
+ scoped_ptr<LayerAnimator> animator(LayerAnimator::CreateDefaultAnimator()); |
+ AnimationContainerElement* element = animator.get(); |
+ animator->set_disable_timer_for_test(true); |
+ TestLayerAnimationDelegate 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->is_animating()); |
+ EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity); |
+ |
+ base::TimeTicks start_time = animator->get_last_step_time_for_test(); |
+ |
+ element->Step(start_time + base::TimeDelta::FromMilliseconds(500)); |
+ |
+ EXPECT_TRUE(animator->is_animating()); |
+ EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), middle_opacity); |
+ |
+ element->Step(start_time + base::TimeDelta::FromMilliseconds(1000)); |
+ |
+ EXPECT_TRUE(animator->is_animating()); |
+ EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), target_opacity); |
+ |
+ element->Step(start_time + base::TimeDelta::FromMilliseconds(1500)); |
+ |
+ EXPECT_TRUE(animator->is_animating()); |
+ EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), middle_opacity); |
+ |
+ element->Step(start_time + base::TimeDelta::FromMilliseconds(2000)); |
+ |
+ EXPECT_FALSE(animator->is_animating()); |
+ EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity); |
+} |
+ |
+// Schedule [{o}, {o,b}, {b}] and ensure that {b} doesn't run right away. That |
+// is, ensure that all animations targetting a particular property are run in |
+// order. |
+TEST(LayerAnimatorTest, ScheduleBlockedAnimation) { |
+ scoped_ptr<LayerAnimator> animator(LayerAnimator::CreateDefaultAnimator()); |
+ AnimationContainerElement* element = animator.get(); |
+ animator->set_disable_timer_for_test(true); |
+ TestLayerAnimationDelegate 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->is_animating()); |
+ EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity); |
+ CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), start_bounds); |
+ |
+ base::TimeTicks start_time = animator->get_last_step_time_for_test(); |
+ |
+ element->Step(start_time + base::TimeDelta::FromMilliseconds(500)); |
+ |
+ EXPECT_TRUE(animator->is_animating()); |
+ EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), middle_opacity); |
+ CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), start_bounds); |
+ |
+ element->Step(start_time + base::TimeDelta::FromMilliseconds(1000)); |
+ |
+ EXPECT_TRUE(animator->is_animating()); |
+ EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), target_opacity); |
+ CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), start_bounds); |
+ |
+ element->Step(start_time + base::TimeDelta::FromMilliseconds(2000)); |
+ |
+ EXPECT_TRUE(animator->is_animating()); |
+ EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity); |
+ CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), start_bounds); |
+ |
+ element->Step(start_time + base::TimeDelta::FromMilliseconds(3000)); |
+ |
+ EXPECT_TRUE(animator->is_animating()); |
+ EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity); |
+ CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), target_bounds); |
+ |
+ element->Step(start_time + base::TimeDelta::FromMilliseconds(4000)); |
+ |
+ EXPECT_FALSE(animator->is_animating()); |
+ EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity); |
+ CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), start_bounds); |
+} |
+ |
+// Schedule {o} and then schedule {o} and {b} together. In this case, since |
+// ScheduleTogether is being used, the bounds animation should not start until |
+// the second opacity animation starts. |
+TEST(LayerAnimatorTest, ScheduleTogether) { |
+ scoped_ptr<LayerAnimator> animator(LayerAnimator::CreateDefaultAnimator()); |
+ AnimationContainerElement* element = animator.get(); |
+ animator->set_disable_timer_for_test(true); |
+ TestLayerAnimationDelegate 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->is_animating()); |
+ EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity); |
+ CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), start_bounds); |
+ |
+ base::TimeTicks start_time = animator->get_last_step_time_for_test(); |
+ |
+ element->Step(start_time + base::TimeDelta::FromMilliseconds(1000)); |
+ |
+ EXPECT_TRUE(animator->is_animating()); |
+ EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), target_opacity); |
+ CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), start_bounds); |
+ |
+ element->Step(start_time + base::TimeDelta::FromMilliseconds(2000)); |
+ |
+ EXPECT_FALSE(animator->is_animating()); |
+ EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity); |
+ CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), target_bounds); |
+} |
+ |
+// Start animation (that can run immediately). This is the trivial case (see |
+// the trival case for ScheduleAnimation). |
+TEST(LayerAnimatorTest, StartAnimationThatCanRunImmediately) { |
+ scoped_ptr<LayerAnimator> animator(LayerAnimator::CreateDefaultAnimator()); |
+ AnimationContainerElement* element = animator.get(); |
+ animator->set_disable_timer_for_test(true); |
+ TestLayerAnimationDelegate 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->is_animating()); |
+ EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity); |
+ |
+ base::TimeTicks start_time = animator->get_last_step_time_for_test(); |
+ |
+ element->Step(start_time + base::TimeDelta::FromMilliseconds(500)); |
+ |
+ EXPECT_TRUE(animator->is_animating()); |
+ EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), middle_opacity); |
+ |
+ element->Step(start_time + base::TimeDelta::FromMilliseconds(1000)); |
+ |
+ EXPECT_FALSE(animator->is_animating()); |
+ EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), target_opacity); |
+} |
+ |
+// Preempt by immediately setting new target. |
+TEST(LayerAnimatorTest, PreemptBySettingNewTarget) { |
+ scoped_ptr<LayerAnimator> animator(LayerAnimator::CreateDefaultAnimator()); |
+ animator->set_disable_timer_for_test(true); |
+ TestLayerAnimationDelegate 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->is_animating()); |
+ EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity); |
+} |
+ |
+// Preempt by animating to new target. |
+TEST(LayerAnimatorTest, PreemptByImmediatelyAnimatingToNewTarget) { |
+ scoped_ptr<LayerAnimator> animator(LayerAnimator::CreateDefaultAnimator()); |
+ AnimationContainerElement* element = animator.get(); |
+ animator->set_disable_timer_for_test(true); |
+ TestLayerAnimationDelegate 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(); |
+ |
+ element->Step(start_time + base::TimeDelta::FromMilliseconds(500)); |
+ |
+ animator->StartAnimation( |
+ new LayerAnimationSequence( |
+ LayerAnimationElement::CreateOpacityElement(start_opacity, delta))); |
+ |
+ EXPECT_TRUE(animator->is_animating()); |
+ EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), middle_opacity); |
+ |
+ animator->StartAnimation( |
+ new LayerAnimationSequence( |
+ LayerAnimationElement::CreateOpacityElement(start_opacity, delta))); |
+ |
+ EXPECT_TRUE(animator->is_animating()); |
+ |
+ element->Step(start_time + base::TimeDelta::FromMilliseconds(1000)); |
+ |
+ EXPECT_TRUE(animator->is_animating()); |
+ EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), |
+ 0.5 * (start_opacity + middle_opacity)); |
+ |
+ element->Step(start_time + base::TimeDelta::FromMilliseconds(1500)); |
+ |
+ EXPECT_FALSE(animator->is_animating()); |
+ EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity); |
+} |
+ |
+// Preempt by enqueuing the new animation. |
+TEST(LayerAnimatorTest, PreemptEnqueueNewAnimation) { |
+ scoped_ptr<LayerAnimator> animator(LayerAnimator::CreateDefaultAnimator()); |
+ AnimationContainerElement* element = animator.get(); |
+ animator->set_disable_timer_for_test(true); |
+ TestLayerAnimationDelegate 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(); |
+ |
+ element->Step(start_time + base::TimeDelta::FromMilliseconds(500)); |
+ |
+ animator->StartAnimation( |
+ new LayerAnimationSequence( |
+ LayerAnimationElement::CreateOpacityElement(start_opacity, delta))); |
+ |
+ EXPECT_TRUE(animator->is_animating()); |
+ EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), middle_opacity); |
+ |
+ EXPECT_TRUE(animator->is_animating()); |
+ |
+ element->Step(start_time + base::TimeDelta::FromMilliseconds(1000)); |
+ |
+ EXPECT_TRUE(animator->is_animating()); |
+ EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), target_opacity); |
+ |
+ element->Step(start_time + base::TimeDelta::FromMilliseconds(1500)); |
+ |
+ EXPECT_TRUE(animator->is_animating()); |
+ EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), middle_opacity); |
+ |
+ element->Step(start_time + base::TimeDelta::FromMilliseconds(2000)); |
+ |
+ EXPECT_FALSE(animator->is_animating()); |
+ 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()); |
+ AnimationContainerElement* element = animator.get(); |
+ animator->set_disable_timer_for_test(true); |
+ TestLayerAnimationDelegate 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(); |
+ |
+ element->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->is_animating()); |
+ EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), middle_opacity); |
+ |
+ element->Step(start_time + base::TimeDelta::FromMilliseconds(1000)); |
+ |
+ EXPECT_TRUE(animator->is_animating()); |
+ EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), target_opacity); |
+ |
+ element->Step(start_time + base::TimeDelta::FromMilliseconds(1500)); |
+ |
+ EXPECT_TRUE(animator->is_animating()); |
+ EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), middle_opacity); |
+ |
+ element->Step(start_time + base::TimeDelta::FromMilliseconds(2000)); |
+ |
+ EXPECT_FALSE(animator->is_animating()); |
+ EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity); |
+} |
+ |
+// Test that cyclic sequences continue to animate. |
+TEST(LayerAnimatorTest, CyclicSequences) { |
+ scoped_ptr<LayerAnimator> animator(LayerAnimator::CreateDefaultAnimator()); |
+ AnimationContainerElement* element = animator.get(); |
+ animator->set_disable_timer_for_test(true); |
+ TestLayerAnimationDelegate 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(); |
+ |
+ element->Step(start_time + base::TimeDelta::FromMilliseconds(1000)); |
+ |
+ EXPECT_TRUE(animator->is_animating()); |
+ EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), target_opacity); |
+ |
+ element->Step(start_time + base::TimeDelta::FromMilliseconds(2000)); |
+ |
+ EXPECT_TRUE(animator->is_animating()); |
+ EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity); |
+ |
+ element->Step(start_time + base::TimeDelta::FromMilliseconds(3000)); |
+ |
+ EXPECT_TRUE(animator->is_animating()); |
+ EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), target_opacity); |
+ |
+ // Skip ahead by a lot. |
+ element->Step(start_time + base::TimeDelta::FromMilliseconds(1000000000000)); |
+ |
+ EXPECT_TRUE(animator->is_animating()); |
+ EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity); |
+ |
+ // Skip ahead by a lot. |
+ element->Step(start_time + base::TimeDelta::FromMilliseconds(1000000001000)); |
+ |
+ EXPECT_TRUE(animator->is_animating()); |
+ EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), target_opacity); |
+ |
+ animator->StopAnimatingProperty(LayerAnimationElement::OPACITY); |
+ |
+ EXPECT_FALSE(animator->is_animating()); |
+} |
+ |
+} // namespace |
+ |
+} // namespace ui |