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