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_sequence.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/layer_animation_element.h" 14 #include "ui/compositor/test/test_layer_animation_delegate.h" 15 #include "ui/compositor/test/test_layer_animation_observer.h" 16 #include "ui/compositor/test/test_utils.h" 17 #include "ui/gfx/rect.h" 18 #include "ui/gfx/transform.h" 19 20 namespace ui { 21 22 namespace { 23 24 // Check that the sequence behaves sanely when it contains no elements. 25 TEST(LayerAnimationSequenceTest, NoElement) { 26 LayerAnimationSequence sequence; 27 base::TimeTicks start_time; 28 start_time += base::TimeDelta::FromSeconds(1); 29 sequence.set_start_time(start_time); 30 EXPECT_TRUE(sequence.IsFinished(start_time)); 31 EXPECT_EQ(static_cast<LayerAnimationElement::AnimatableProperties>( 32 LayerAnimationElement::UNKNOWN), 33 sequence.properties()); 34 EXPECT_FALSE(sequence.HasConflictingProperty(LayerAnimationElement::UNKNOWN)); 35 } 36 37 // Check that the sequences progresses the delegate as expected when it contains 38 // a single non-threaded element. 39 TEST(LayerAnimationSequenceTest, SingleElement) { 40 LayerAnimationSequence sequence; 41 TestLayerAnimationDelegate delegate; 42 float start = 0.0f; 43 float middle = 0.5f; 44 float target = 1.0f; 45 base::TimeTicks start_time; 46 base::TimeDelta delta = base::TimeDelta::FromSeconds(1); 47 sequence.AddElement( 48 LayerAnimationElement::CreateBrightnessElement(target, delta)); 49 50 for (int i = 0; i < 2; ++i) { 51 start_time += delta; 52 sequence.set_start_time(start_time); 53 delegate.SetBrightnessFromAnimation(start); 54 sequence.Start(&delegate); 55 sequence.Progress(start_time, &delegate); 56 EXPECT_FLOAT_EQ(start, delegate.GetBrightnessForAnimation()); 57 sequence.Progress(start_time + base::TimeDelta::FromMilliseconds(500), 58 &delegate); 59 EXPECT_FLOAT_EQ(middle, delegate.GetBrightnessForAnimation()); 60 EXPECT_TRUE(sequence.IsFinished(start_time + delta)); 61 sequence.Progress(start_time + base::TimeDelta::FromMilliseconds(1000), 62 &delegate); 63 EXPECT_FLOAT_EQ(target, delegate.GetBrightnessForAnimation()); 64 } 65 66 EXPECT_EQ(static_cast<LayerAnimationElement::AnimatableProperties>( 67 LayerAnimationElement::BRIGHTNESS), 68 sequence.properties()); 69 } 70 71 // Check that the sequences progresses the delegate as expected when it contains 72 // a single threaded element. 73 TEST(LayerAnimationSequenceTest, SingleThreadedElement) { 74 LayerAnimationSequence sequence; 75 TestLayerAnimationDelegate delegate; 76 float start = 0.0f; 77 float middle = 0.5f; 78 float target = 1.0f; 79 base::TimeTicks start_time; 80 base::TimeTicks effective_start; 81 base::TimeDelta delta = base::TimeDelta::FromSeconds(1); 82 sequence.AddElement( 83 LayerAnimationElement::CreateOpacityElement(target, delta)); 84 85 for (int i = 0; i < 2; ++i) { 86 int starting_group_id = 1; 87 sequence.set_animation_group_id(starting_group_id); 88 start_time = effective_start + delta; 89 sequence.set_start_time(start_time); 90 delegate.SetOpacityFromAnimation(start); 91 sequence.Start(&delegate); 92 sequence.Progress(start_time, &delegate); 93 EXPECT_FLOAT_EQ(start, sequence.last_progressed_fraction()); 94 effective_start = start_time + delta; 95 sequence.OnThreadedAnimationStarted( 96 cc::AnimationEvent(cc::AnimationEvent::Started, 97 0, 98 sequence.animation_group_id(), 99 cc::Animation::Opacity, 100 effective_start)); 101 sequence.Progress(effective_start + delta/2, &delegate); 102 EXPECT_FLOAT_EQ(middle, sequence.last_progressed_fraction()); 103 EXPECT_TRUE(sequence.IsFinished(effective_start + delta)); 104 sequence.Progress(effective_start + delta, &delegate); 105 EXPECT_FLOAT_EQ(target, sequence.last_progressed_fraction()); 106 EXPECT_FLOAT_EQ(target, delegate.GetOpacityForAnimation()); 107 } 108 109 EXPECT_EQ(static_cast<LayerAnimationElement::AnimatableProperties>( 110 LayerAnimationElement::OPACITY), 111 sequence.properties()); 112 } 113 114 // Check that the sequences progresses the delegate as expected when it contains 115 // multiple elements. Note, see the layer animator tests for cyclic sequences. 116 TEST(LayerAnimationSequenceTest, MultipleElement) { 117 LayerAnimationSequence sequence; 118 TestLayerAnimationDelegate delegate; 119 float start_opacity = 0.0f; 120 float target_opacity = 1.0f; 121 base::TimeTicks start_time; 122 base::TimeTicks opacity_effective_start; 123 base::TimeTicks transform_effective_start; 124 base::TimeDelta delta = base::TimeDelta::FromSeconds(1); 125 sequence.AddElement( 126 LayerAnimationElement::CreateOpacityElement(target_opacity, delta)); 127 128 // Pause bounds for a second. 129 sequence.AddElement(LayerAnimationElement::CreatePauseElement( 130 LayerAnimationElement::BOUNDS, delta)); 131 132 gfx::Transform start_transform, target_transform, middle_transform; 133 start_transform.Rotate(-30.0); 134 target_transform.Rotate(30.0); 135 136 sequence.AddElement( 137 LayerAnimationElement::CreateTransformElement(target_transform, delta)); 138 139 for (int i = 0; i < 2; ++i) { 140 int starting_group_id = 1; 141 sequence.set_animation_group_id(starting_group_id); 142 start_time = opacity_effective_start + 4 * delta; 143 sequence.set_start_time(start_time); 144 delegate.SetOpacityFromAnimation(start_opacity); 145 delegate.SetTransformFromAnimation(start_transform); 146 147 sequence.Start(&delegate); 148 sequence.Progress(start_time, &delegate); 149 EXPECT_FLOAT_EQ(0.0, sequence.last_progressed_fraction()); 150 opacity_effective_start = start_time + delta; 151 EXPECT_EQ(starting_group_id, sequence.animation_group_id()); 152 sequence.OnThreadedAnimationStarted( 153 cc::AnimationEvent(cc::AnimationEvent::Started, 154 0, 155 sequence.animation_group_id(), 156 cc::Animation::Opacity, 157 opacity_effective_start)); 158 sequence.Progress(opacity_effective_start + delta/2, &delegate); 159 EXPECT_FLOAT_EQ(0.5, sequence.last_progressed_fraction()); 160 sequence.Progress(opacity_effective_start + delta, &delegate); 161 EXPECT_FLOAT_EQ(target_opacity, delegate.GetOpacityForAnimation()); 162 163 // Now at the start of the pause. 164 EXPECT_FLOAT_EQ(0.0, sequence.last_progressed_fraction()); 165 TestLayerAnimationDelegate copy = delegate; 166 167 // In the middle of the pause -- nothing should have changed. 168 sequence.Progress(opacity_effective_start + delta + delta/2, 169 &delegate); 170 CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), 171 copy.GetBoundsForAnimation()); 172 CheckApproximatelyEqual(delegate.GetTransformForAnimation(), 173 copy.GetTransformForAnimation()); 174 EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), 175 copy.GetOpacityForAnimation()); 176 177 sequence.Progress(opacity_effective_start + 2 * delta, &delegate); 178 CheckApproximatelyEqual(start_transform, 179 delegate.GetTransformForAnimation()); 180 EXPECT_FLOAT_EQ(0.0, sequence.last_progressed_fraction()); 181 transform_effective_start = opacity_effective_start + 3 * delta; 182 EXPECT_NE(starting_group_id, sequence.animation_group_id()); 183 sequence.OnThreadedAnimationStarted( 184 cc::AnimationEvent(cc::AnimationEvent::Started, 185 0, 186 sequence.animation_group_id(), 187 cc::Animation::Transform, 188 transform_effective_start)); 189 sequence.Progress(transform_effective_start + delta/2, &delegate); 190 EXPECT_FLOAT_EQ(0.5, sequence.last_progressed_fraction()); 191 EXPECT_TRUE(sequence.IsFinished(transform_effective_start + delta)); 192 sequence.Progress(transform_effective_start + delta, &delegate); 193 CheckApproximatelyEqual(target_transform, 194 delegate.GetTransformForAnimation()); 195 } 196 197 EXPECT_EQ( 198 static_cast<LayerAnimationElement::AnimatableProperties>( 199 LayerAnimationElement::OPACITY | LayerAnimationElement::TRANSFORM | 200 LayerAnimationElement::BOUNDS), 201 sequence.properties()); 202 } 203 204 // Check that a sequence can still be aborted if it has cycled many times. 205 TEST(LayerAnimationSequenceTest, AbortingCyclicSequence) { 206 LayerAnimationSequence sequence; 207 TestLayerAnimationDelegate delegate; 208 float start_brightness = 0.0f; 209 float target_brightness = 1.0f; 210 base::TimeTicks start_time; 211 base::TimeDelta delta = base::TimeDelta::FromSeconds(1); 212 sequence.AddElement( 213 LayerAnimationElement::CreateBrightnessElement(target_brightness, delta)); 214 215 sequence.AddElement( 216 LayerAnimationElement::CreateBrightnessElement(start_brightness, delta)); 217 218 sequence.set_is_cyclic(true); 219 220 delegate.SetBrightnessFromAnimation(start_brightness); 221 222 start_time += delta; 223 sequence.set_start_time(start_time); 224 sequence.Start(&delegate); 225 sequence.Progress(start_time + base::TimeDelta::FromMilliseconds(101000), 226 &delegate); 227 EXPECT_FLOAT_EQ(target_brightness, delegate.GetBrightnessForAnimation()); 228 sequence.Abort(&delegate); 229 230 // Should be able to reuse the sequence after aborting. 231 delegate.SetBrightnessFromAnimation(start_brightness); 232 start_time += base::TimeDelta::FromMilliseconds(101000); 233 sequence.set_start_time(start_time); 234 sequence.Progress(start_time + base::TimeDelta::FromMilliseconds(100000), 235 &delegate); 236 EXPECT_FLOAT_EQ(start_brightness, delegate.GetBrightnessForAnimation()); 237 } 238 239 // Check that a sequence can be 'fast-forwarded' to the end and the target set. 240 // Also check that this has no effect if the sequence is cyclic. 241 TEST(LayerAnimationSequenceTest, SetTarget) { 242 LayerAnimationSequence sequence; 243 TestLayerAnimationDelegate delegate; 244 float start_opacity = 0.0f; 245 float target_opacity = 1.0f; 246 base::TimeDelta delta = base::TimeDelta::FromSeconds(1); 247 sequence.AddElement( 248 LayerAnimationElement::CreateOpacityElement(target_opacity, delta)); 249 250 LayerAnimationElement::TargetValue target_value(&delegate); 251 target_value.opacity = start_opacity; 252 sequence.GetTargetValue(&target_value); 253 EXPECT_FLOAT_EQ(target_opacity, target_value.opacity); 254 255 sequence.set_is_cyclic(true); 256 target_value.opacity = start_opacity; 257 sequence.GetTargetValue(&target_value); 258 EXPECT_FLOAT_EQ(start_opacity, target_value.opacity); 259 } 260 261 TEST(LayerAnimationSequenceTest, AddObserver) { 262 base::TimeTicks start_time; 263 base::TimeDelta delta = base::TimeDelta::FromSeconds(1); 264 LayerAnimationSequence sequence; 265 sequence.AddElement( 266 LayerAnimationElement::CreateBrightnessElement(1.0f, delta)); 267 for (int i = 0; i < 2; ++i) { 268 start_time += delta; 269 sequence.set_start_time(start_time); 270 TestLayerAnimationObserver observer; 271 TestLayerAnimationDelegate delegate; 272 sequence.AddObserver(&observer); 273 EXPECT_TRUE(!observer.last_ended_sequence()); 274 sequence.Progress(start_time + delta, &delegate); 275 EXPECT_EQ(observer.last_ended_sequence(), &sequence); 276 sequence.RemoveObserver(&observer); 277 } 278 } 279 280 } // namespace 281 282 } // namespace ui 283