transform_operations_unittest.cc revision 4e180b6a0b4720a9b8e9e959a882386f690f08ff
1// Copyright 2013 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 <limits> 6 7#include "base/basictypes.h" 8#include "base/memory/scoped_vector.h" 9#include "cc/animation/transform_operations.h" 10#include "cc/test/geometry_test_utils.h" 11#include "testing/gtest/include/gtest/gtest.h" 12#include "ui/gfx/animation/tween.h" 13#include "ui/gfx/box_f.h" 14#include "ui/gfx/vector3d_f.h" 15 16namespace cc { 17namespace { 18 19TEST(TransformOperationTest, TransformTypesAreUnique) { 20 ScopedVector<TransformOperations> transforms; 21 22 TransformOperations* to_add = new TransformOperations(); 23 to_add->AppendTranslate(1, 0, 0); 24 transforms.push_back(to_add); 25 26 to_add = new TransformOperations(); 27 to_add->AppendRotate(0, 0, 1, 2); 28 transforms.push_back(to_add); 29 30 to_add = new TransformOperations(); 31 to_add->AppendScale(2, 2, 2); 32 transforms.push_back(to_add); 33 34 to_add = new TransformOperations(); 35 to_add->AppendSkew(1, 0); 36 transforms.push_back(to_add); 37 38 to_add = new TransformOperations(); 39 to_add->AppendPerspective(800); 40 transforms.push_back(to_add); 41 42 for (size_t i = 0; i < transforms.size(); ++i) { 43 for (size_t j = 0; j < transforms.size(); ++j) { 44 bool matches_type = transforms[i]->MatchesTypes(*transforms[j]); 45 EXPECT_TRUE((i == j && matches_type) || !matches_type); 46 } 47 } 48} 49 50TEST(TransformOperationTest, MatchTypesSameLength) { 51 TransformOperations translates; 52 translates.AppendTranslate(1, 0, 0); 53 translates.AppendTranslate(1, 0, 0); 54 translates.AppendTranslate(1, 0, 0); 55 56 TransformOperations skews; 57 skews.AppendSkew(0, 2); 58 skews.AppendSkew(0, 2); 59 skews.AppendSkew(0, 2); 60 61 TransformOperations translates2; 62 translates2.AppendTranslate(0, 2, 0); 63 translates2.AppendTranslate(0, 2, 0); 64 translates2.AppendTranslate(0, 2, 0); 65 66 TransformOperations translates3 = translates2; 67 68 EXPECT_FALSE(translates.MatchesTypes(skews)); 69 EXPECT_TRUE(translates.MatchesTypes(translates2)); 70 EXPECT_TRUE(translates.MatchesTypes(translates3)); 71} 72 73TEST(TransformOperationTest, MatchTypesDifferentLength) { 74 TransformOperations translates; 75 translates.AppendTranslate(1, 0, 0); 76 translates.AppendTranslate(1, 0, 0); 77 translates.AppendTranslate(1, 0, 0); 78 79 TransformOperations skews; 80 skews.AppendSkew(2, 0); 81 skews.AppendSkew(2, 0); 82 83 TransformOperations translates2; 84 translates2.AppendTranslate(0, 2, 0); 85 translates2.AppendTranslate(0, 2, 0); 86 87 EXPECT_FALSE(translates.MatchesTypes(skews)); 88 EXPECT_FALSE(translates.MatchesTypes(translates2)); 89} 90 91void GetIdentityOperations(ScopedVector<TransformOperations>* operations) { 92 TransformOperations* to_add = new TransformOperations(); 93 operations->push_back(to_add); 94 95 to_add = new TransformOperations(); 96 to_add->AppendTranslate(0, 0, 0); 97 operations->push_back(to_add); 98 99 to_add = new TransformOperations(); 100 to_add->AppendTranslate(0, 0, 0); 101 to_add->AppendTranslate(0, 0, 0); 102 operations->push_back(to_add); 103 104 to_add = new TransformOperations(); 105 to_add->AppendScale(1, 1, 1); 106 operations->push_back(to_add); 107 108 to_add = new TransformOperations(); 109 to_add->AppendScale(1, 1, 1); 110 to_add->AppendScale(1, 1, 1); 111 operations->push_back(to_add); 112 113 to_add = new TransformOperations(); 114 to_add->AppendSkew(0, 0); 115 operations->push_back(to_add); 116 117 to_add = new TransformOperations(); 118 to_add->AppendSkew(0, 0); 119 to_add->AppendSkew(0, 0); 120 operations->push_back(to_add); 121 122 to_add = new TransformOperations(); 123 to_add->AppendRotate(0, 0, 1, 0); 124 operations->push_back(to_add); 125 126 to_add = new TransformOperations(); 127 to_add->AppendRotate(0, 0, 1, 0); 128 to_add->AppendRotate(0, 0, 1, 0); 129 operations->push_back(to_add); 130 131 to_add = new TransformOperations(); 132 to_add->AppendMatrix(gfx::Transform()); 133 operations->push_back(to_add); 134 135 to_add = new TransformOperations(); 136 to_add->AppendMatrix(gfx::Transform()); 137 to_add->AppendMatrix(gfx::Transform()); 138 operations->push_back(to_add); 139} 140 141TEST(TransformOperationTest, IdentityAlwaysMatches) { 142 ScopedVector<TransformOperations> operations; 143 GetIdentityOperations(&operations); 144 145 for (size_t i = 0; i < operations.size(); ++i) { 146 for (size_t j = 0; j < operations.size(); ++j) 147 EXPECT_TRUE(operations[i]->MatchesTypes(*operations[j])); 148 } 149} 150 151TEST(TransformOperationTest, ApplyTranslate) { 152 SkMScalar x = 1; 153 SkMScalar y = 2; 154 SkMScalar z = 3; 155 TransformOperations operations; 156 operations.AppendTranslate(x, y, z); 157 gfx::Transform expected; 158 expected.Translate3d(x, y, z); 159 EXPECT_TRANSFORMATION_MATRIX_EQ(expected, operations.Apply()); 160} 161 162TEST(TransformOperationTest, ApplyRotate) { 163 SkMScalar x = 1; 164 SkMScalar y = 2; 165 SkMScalar z = 3; 166 SkMScalar degrees = 80; 167 TransformOperations operations; 168 operations.AppendRotate(x, y, z, degrees); 169 gfx::Transform expected; 170 expected.RotateAbout(gfx::Vector3dF(x, y, z), degrees); 171 EXPECT_TRANSFORMATION_MATRIX_EQ(expected, operations.Apply()); 172} 173 174TEST(TransformOperationTest, ApplyScale) { 175 SkMScalar x = 1; 176 SkMScalar y = 2; 177 SkMScalar z = 3; 178 TransformOperations operations; 179 operations.AppendScale(x, y, z); 180 gfx::Transform expected; 181 expected.Scale3d(x, y, z); 182 EXPECT_TRANSFORMATION_MATRIX_EQ(expected, operations.Apply()); 183} 184 185TEST(TransformOperationTest, ApplySkew) { 186 SkMScalar x = 1; 187 SkMScalar y = 2; 188 TransformOperations operations; 189 operations.AppendSkew(x, y); 190 gfx::Transform expected; 191 expected.SkewX(x); 192 expected.SkewY(y); 193 EXPECT_TRANSFORMATION_MATRIX_EQ(expected, operations.Apply()); 194} 195 196TEST(TransformOperationTest, ApplyPerspective) { 197 SkMScalar depth = 800; 198 TransformOperations operations; 199 operations.AppendPerspective(depth); 200 gfx::Transform expected; 201 expected.ApplyPerspectiveDepth(depth); 202 EXPECT_TRANSFORMATION_MATRIX_EQ(expected, operations.Apply()); 203} 204 205TEST(TransformOperationTest, ApplyMatrix) { 206 SkMScalar dx = 1; 207 SkMScalar dy = 2; 208 SkMScalar dz = 3; 209 gfx::Transform expected_matrix; 210 expected_matrix.Translate3d(dx, dy, dz); 211 TransformOperations matrix_transform; 212 matrix_transform.AppendMatrix(expected_matrix); 213 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_matrix, matrix_transform.Apply()); 214} 215 216TEST(TransformOperationTest, ApplyOrder) { 217 SkMScalar sx = 2; 218 SkMScalar sy = 4; 219 SkMScalar sz = 8; 220 221 SkMScalar dx = 1; 222 SkMScalar dy = 2; 223 SkMScalar dz = 3; 224 225 TransformOperations operations; 226 operations.AppendScale(sx, sy, sz); 227 operations.AppendTranslate(dx, dy, dz); 228 229 gfx::Transform expected_scale_matrix; 230 expected_scale_matrix.Scale3d(sx, sy, sz); 231 232 gfx::Transform expected_translate_matrix; 233 expected_translate_matrix.Translate3d(dx, dy, dz); 234 235 gfx::Transform expected_combined_matrix = expected_scale_matrix; 236 expected_combined_matrix.PreconcatTransform(expected_translate_matrix); 237 238 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_combined_matrix, operations.Apply()); 239} 240 241TEST(TransformOperationTest, BlendOrder) { 242 SkMScalar sx1 = 2; 243 SkMScalar sy1 = 4; 244 SkMScalar sz1 = 8; 245 246 SkMScalar dx1 = 1; 247 SkMScalar dy1 = 2; 248 SkMScalar dz1 = 3; 249 250 SkMScalar sx2 = 4; 251 SkMScalar sy2 = 8; 252 SkMScalar sz2 = 16; 253 254 SkMScalar dx2 = 10; 255 SkMScalar dy2 = 20; 256 SkMScalar dz2 = 30; 257 258 TransformOperations operations_from; 259 operations_from.AppendScale(sx1, sy1, sz1); 260 operations_from.AppendTranslate(dx1, dy1, dz1); 261 262 TransformOperations operations_to; 263 operations_to.AppendScale(sx2, sy2, sz2); 264 operations_to.AppendTranslate(dx2, dy2, dz2); 265 266 gfx::Transform scale_from; 267 scale_from.Scale3d(sx1, sy1, sz1); 268 gfx::Transform translate_from; 269 translate_from.Translate3d(dx1, dy1, dz1); 270 271 gfx::Transform scale_to; 272 scale_to.Scale3d(sx2, sy2, sz2); 273 gfx::Transform translate_to; 274 translate_to.Translate3d(dx2, dy2, dz2); 275 276 SkMScalar progress = 0.25f; 277 278 gfx::Transform blended_scale = scale_to; 279 blended_scale.Blend(scale_from, progress); 280 281 gfx::Transform blended_translate = translate_to; 282 blended_translate.Blend(translate_from, progress); 283 284 gfx::Transform expected = blended_scale; 285 expected.PreconcatTransform(blended_translate); 286 287 EXPECT_TRANSFORMATION_MATRIX_EQ( 288 expected, operations_to.Blend(operations_from, progress)); 289} 290 291static void CheckProgress(SkMScalar progress, 292 const gfx::Transform& from_matrix, 293 const gfx::Transform& to_matrix, 294 const TransformOperations& from_transform, 295 const TransformOperations& to_transform) { 296 gfx::Transform expected_matrix = to_matrix; 297 expected_matrix.Blend(from_matrix, progress); 298 EXPECT_TRANSFORMATION_MATRIX_EQ( 299 expected_matrix, to_transform.Blend(from_transform, progress)); 300} 301 302TEST(TransformOperationTest, BlendProgress) { 303 SkMScalar sx = 2; 304 SkMScalar sy = 4; 305 SkMScalar sz = 8; 306 TransformOperations operations_from; 307 operations_from.AppendScale(sx, sy, sz); 308 309 gfx::Transform matrix_from; 310 matrix_from.Scale3d(sx, sy, sz); 311 312 sx = 4; 313 sy = 8; 314 sz = 16; 315 TransformOperations operations_to; 316 operations_to.AppendScale(sx, sy, sz); 317 318 gfx::Transform matrix_to; 319 matrix_to.Scale3d(sx, sy, sz); 320 321 CheckProgress(-1, matrix_from, matrix_to, operations_from, operations_to); 322 CheckProgress(0, matrix_from, matrix_to, operations_from, operations_to); 323 CheckProgress(0.25f, matrix_from, matrix_to, operations_from, operations_to); 324 CheckProgress(0.5f, matrix_from, matrix_to, operations_from, operations_to); 325 CheckProgress(1, matrix_from, matrix_to, operations_from, operations_to); 326 CheckProgress(2, matrix_from, matrix_to, operations_from, operations_to); 327} 328 329TEST(TransformOperationTest, BlendWhenTypesDoNotMatch) { 330 SkMScalar sx1 = 2; 331 SkMScalar sy1 = 4; 332 SkMScalar sz1 = 8; 333 334 SkMScalar dx1 = 1; 335 SkMScalar dy1 = 2; 336 SkMScalar dz1 = 3; 337 338 SkMScalar sx2 = 4; 339 SkMScalar sy2 = 8; 340 SkMScalar sz2 = 16; 341 342 SkMScalar dx2 = 10; 343 SkMScalar dy2 = 20; 344 SkMScalar dz2 = 30; 345 346 TransformOperations operations_from; 347 operations_from.AppendScale(sx1, sy1, sz1); 348 operations_from.AppendTranslate(dx1, dy1, dz1); 349 350 TransformOperations operations_to; 351 operations_to.AppendTranslate(dx2, dy2, dz2); 352 operations_to.AppendScale(sx2, sy2, sz2); 353 354 gfx::Transform from; 355 from.Scale3d(sx1, sy1, sz1); 356 from.Translate3d(dx1, dy1, dz1); 357 358 gfx::Transform to; 359 to.Translate3d(dx2, dy2, dz2); 360 to.Scale3d(sx2, sy2, sz2); 361 362 SkMScalar progress = 0.25f; 363 364 gfx::Transform expected = to; 365 expected.Blend(from, progress); 366 367 EXPECT_TRANSFORMATION_MATRIX_EQ( 368 expected, operations_to.Blend(operations_from, progress)); 369} 370 371TEST(TransformOperationTest, LargeRotationsWithSameAxis) { 372 TransformOperations operations_from; 373 operations_from.AppendRotate(0, 0, 1, 0); 374 375 TransformOperations operations_to; 376 operations_to.AppendRotate(0, 0, 2, 360); 377 378 SkMScalar progress = 0.5f; 379 380 gfx::Transform expected; 381 expected.RotateAbout(gfx::Vector3dF(0, 0, 1), 180); 382 383 EXPECT_TRANSFORMATION_MATRIX_EQ( 384 expected, operations_to.Blend(operations_from, progress)); 385} 386 387TEST(TransformOperationTest, LargeRotationsWithSameAxisInDifferentDirection) { 388 TransformOperations operations_from; 389 operations_from.AppendRotate(0, 0, 1, 180); 390 391 TransformOperations operations_to; 392 operations_to.AppendRotate(0, 0, -1, 180); 393 394 SkMScalar progress = 0.5f; 395 396 gfx::Transform expected; 397 398 EXPECT_TRANSFORMATION_MATRIX_EQ( 399 expected, operations_to.Blend(operations_from, progress)); 400} 401 402TEST(TransformOperationTest, LargeRotationsWithDifferentAxes) { 403 TransformOperations operations_from; 404 operations_from.AppendRotate(0, 0, 1, 175); 405 406 TransformOperations operations_to; 407 operations_to.AppendRotate(0, 1, 0, 175); 408 409 SkMScalar progress = 0.5f; 410 gfx::Transform matrix_from; 411 matrix_from.RotateAbout(gfx::Vector3dF(0, 0, 1), 175); 412 413 gfx::Transform matrix_to; 414 matrix_to.RotateAbout(gfx::Vector3dF(0, 1, 0), 175); 415 416 gfx::Transform expected = matrix_to; 417 expected.Blend(matrix_from, progress); 418 419 EXPECT_TRANSFORMATION_MATRIX_EQ( 420 expected, operations_to.Blend(operations_from, progress)); 421} 422 423TEST(TransformOperationTest, BlendRotationFromIdentity) { 424 ScopedVector<TransformOperations> identity_operations; 425 GetIdentityOperations(&identity_operations); 426 427 for (size_t i = 0; i < identity_operations.size(); ++i) { 428 TransformOperations operations; 429 operations.AppendRotate(0, 0, 1, 360); 430 431 SkMScalar progress = 0.5f; 432 433 gfx::Transform expected; 434 expected.RotateAbout(gfx::Vector3dF(0, 0, 1), 180); 435 436 EXPECT_TRANSFORMATION_MATRIX_EQ( 437 expected, operations.Blend(*identity_operations[i], progress)); 438 439 progress = -0.5f; 440 441 expected.MakeIdentity(); 442 expected.RotateAbout(gfx::Vector3dF(0, 0, 1), -180); 443 444 EXPECT_TRANSFORMATION_MATRIX_EQ( 445 expected, operations.Blend(*identity_operations[i], progress)); 446 447 progress = 1.5f; 448 449 expected.MakeIdentity(); 450 expected.RotateAbout(gfx::Vector3dF(0, 0, 1), 540); 451 452 EXPECT_TRANSFORMATION_MATRIX_EQ( 453 expected, operations.Blend(*identity_operations[i], progress)); 454 } 455} 456 457TEST(TransformOperationTest, BlendTranslationFromIdentity) { 458 ScopedVector<TransformOperations> identity_operations; 459 GetIdentityOperations(&identity_operations); 460 461 for (size_t i = 0; i < identity_operations.size(); ++i) { 462 TransformOperations operations; 463 operations.AppendTranslate(2, 2, 2); 464 465 SkMScalar progress = 0.5f; 466 467 gfx::Transform expected; 468 expected.Translate3d(1, 1, 1); 469 470 EXPECT_TRANSFORMATION_MATRIX_EQ( 471 expected, operations.Blend(*identity_operations[i], progress)); 472 473 progress = -0.5f; 474 475 expected.MakeIdentity(); 476 expected.Translate3d(-1, -1, -1); 477 478 EXPECT_TRANSFORMATION_MATRIX_EQ( 479 expected, operations.Blend(*identity_operations[i], progress)); 480 481 progress = 1.5f; 482 483 expected.MakeIdentity(); 484 expected.Translate3d(3, 3, 3); 485 486 EXPECT_TRANSFORMATION_MATRIX_EQ( 487 expected, operations.Blend(*identity_operations[i], progress)); 488 } 489} 490 491TEST(TransformOperationTest, BlendScaleFromIdentity) { 492 ScopedVector<TransformOperations> identity_operations; 493 GetIdentityOperations(&identity_operations); 494 495 for (size_t i = 0; i < identity_operations.size(); ++i) { 496 TransformOperations operations; 497 operations.AppendScale(3, 3, 3); 498 499 SkMScalar progress = 0.5f; 500 501 gfx::Transform expected; 502 expected.Scale3d(2, 2, 2); 503 504 EXPECT_TRANSFORMATION_MATRIX_EQ( 505 expected, operations.Blend(*identity_operations[i], progress)); 506 507 progress = -0.5f; 508 509 expected.MakeIdentity(); 510 expected.Scale3d(0, 0, 0); 511 512 EXPECT_TRANSFORMATION_MATRIX_EQ( 513 expected, operations.Blend(*identity_operations[i], progress)); 514 515 progress = 1.5f; 516 517 expected.MakeIdentity(); 518 expected.Scale3d(4, 4, 4); 519 520 EXPECT_TRANSFORMATION_MATRIX_EQ( 521 expected, operations.Blend(*identity_operations[i], progress)); 522 } 523} 524 525TEST(TransformOperationTest, BlendSkewFromIdentity) { 526 ScopedVector<TransformOperations> identity_operations; 527 GetIdentityOperations(&identity_operations); 528 529 for (size_t i = 0; i < identity_operations.size(); ++i) { 530 TransformOperations operations; 531 operations.AppendSkew(2, 2); 532 533 SkMScalar progress = 0.5f; 534 535 gfx::Transform expected; 536 expected.SkewX(1); 537 expected.SkewY(1); 538 539 EXPECT_TRANSFORMATION_MATRIX_EQ( 540 expected, operations.Blend(*identity_operations[i], progress)); 541 542 progress = -0.5f; 543 544 expected.MakeIdentity(); 545 expected.SkewX(-1); 546 expected.SkewY(-1); 547 548 EXPECT_TRANSFORMATION_MATRIX_EQ( 549 expected, operations.Blend(*identity_operations[i], progress)); 550 551 progress = 1.5f; 552 553 expected.MakeIdentity(); 554 expected.SkewX(3); 555 expected.SkewY(3); 556 557 EXPECT_TRANSFORMATION_MATRIX_EQ( 558 expected, operations.Blend(*identity_operations[i], progress)); 559 } 560} 561 562TEST(TransformOperationTest, BlendPerspectiveFromIdentity) { 563 ScopedVector<TransformOperations> identity_operations; 564 GetIdentityOperations(&identity_operations); 565 566 for (size_t i = 0; i < identity_operations.size(); ++i) { 567 TransformOperations operations; 568 operations.AppendPerspective(1000); 569 570 SkMScalar progress = 0.5f; 571 572 gfx::Transform expected; 573 expected.ApplyPerspectiveDepth(500 + 574 0.5 * std::numeric_limits<SkMScalar>::max()); 575 576 EXPECT_TRANSFORMATION_MATRIX_EQ( 577 expected, operations.Blend(*identity_operations[i], progress)); 578 } 579} 580 581TEST(TransformOperationTest, BlendRotationToIdentity) { 582 ScopedVector<TransformOperations> identity_operations; 583 GetIdentityOperations(&identity_operations); 584 585 for (size_t i = 0; i < identity_operations.size(); ++i) { 586 TransformOperations operations; 587 operations.AppendRotate(0, 0, 1, 360); 588 589 SkMScalar progress = 0.5f; 590 591 gfx::Transform expected; 592 expected.RotateAbout(gfx::Vector3dF(0, 0, 1), 180); 593 594 EXPECT_TRANSFORMATION_MATRIX_EQ( 595 expected, identity_operations[i]->Blend(operations, progress)); 596 } 597} 598 599TEST(TransformOperationTest, BlendTranslationToIdentity) { 600 ScopedVector<TransformOperations> identity_operations; 601 GetIdentityOperations(&identity_operations); 602 603 for (size_t i = 0; i < identity_operations.size(); ++i) { 604 TransformOperations operations; 605 operations.AppendTranslate(2, 2, 2); 606 607 SkMScalar progress = 0.5f; 608 609 gfx::Transform expected; 610 expected.Translate3d(1, 1, 1); 611 612 EXPECT_TRANSFORMATION_MATRIX_EQ( 613 expected, identity_operations[i]->Blend(operations, progress)); 614 } 615} 616 617TEST(TransformOperationTest, BlendScaleToIdentity) { 618 ScopedVector<TransformOperations> identity_operations; 619 GetIdentityOperations(&identity_operations); 620 621 for (size_t i = 0; i < identity_operations.size(); ++i) { 622 TransformOperations operations; 623 operations.AppendScale(3, 3, 3); 624 625 SkMScalar progress = 0.5f; 626 627 gfx::Transform expected; 628 expected.Scale3d(2, 2, 2); 629 630 EXPECT_TRANSFORMATION_MATRIX_EQ( 631 expected, identity_operations[i]->Blend(operations, progress)); 632 } 633} 634 635TEST(TransformOperationTest, BlendSkewToIdentity) { 636 ScopedVector<TransformOperations> identity_operations; 637 GetIdentityOperations(&identity_operations); 638 639 for (size_t i = 0; i < identity_operations.size(); ++i) { 640 TransformOperations operations; 641 operations.AppendSkew(2, 2); 642 643 SkMScalar progress = 0.5f; 644 645 gfx::Transform expected; 646 expected.SkewX(1); 647 expected.SkewY(1); 648 649 EXPECT_TRANSFORMATION_MATRIX_EQ( 650 expected, identity_operations[i]->Blend(operations, progress)); 651 } 652} 653 654TEST(TransformOperationTest, BlendPerspectiveToIdentity) { 655 ScopedVector<TransformOperations> identity_operations; 656 GetIdentityOperations(&identity_operations); 657 658 for (size_t i = 0; i < identity_operations.size(); ++i) { 659 TransformOperations operations; 660 operations.AppendPerspective(1000); 661 662 SkMScalar progress = 0.5f; 663 664 gfx::Transform expected; 665 expected.ApplyPerspectiveDepth(500 + 666 0.5 * std::numeric_limits<SkMScalar>::max()); 667 668 EXPECT_TRANSFORMATION_MATRIX_EQ( 669 expected, identity_operations[i]->Blend(operations, progress)); 670 } 671} 672 673TEST(TransformOperationTest, ExtrapolatePerspectiveBlending) { 674 TransformOperations operations1; 675 operations1.AppendPerspective(1000); 676 677 TransformOperations operations2; 678 operations2.AppendPerspective(500); 679 680 gfx::Transform expected; 681 expected.ApplyPerspectiveDepth(250); 682 683 EXPECT_TRANSFORMATION_MATRIX_EQ( 684 expected, operations1.Blend(operations2, -0.5)); 685 686 expected.MakeIdentity(); 687 expected.ApplyPerspectiveDepth(1250); 688 689 EXPECT_TRANSFORMATION_MATRIX_EQ( 690 expected, operations1.Blend(operations2, 1.5)); 691} 692 693TEST(TransformOperationTest, ExtrapolateMatrixBlending) { 694 gfx::Transform transform1; 695 transform1.Translate3d(1, 1, 1); 696 TransformOperations operations1; 697 operations1.AppendMatrix(transform1); 698 699 gfx::Transform transform2; 700 transform2.Translate3d(3, 3, 3); 701 TransformOperations operations2; 702 operations2.AppendMatrix(transform2); 703 704 gfx::Transform expected; 705 EXPECT_TRANSFORMATION_MATRIX_EQ( 706 expected, operations1.Blend(operations2, 1.5)); 707 708 expected.Translate3d(4, 4, 4); 709 EXPECT_TRANSFORMATION_MATRIX_EQ( 710 expected, operations1.Blend(operations2, -0.5)); 711} 712 713TEST(TransformOperationTest, BlendedBoundsWhenTypesDoNotMatch) { 714 TransformOperations operations_from; 715 operations_from.AppendScale(2.0, 4.0, 8.0); 716 operations_from.AppendTranslate(1.0, 2.0, 3.0); 717 718 TransformOperations operations_to; 719 operations_to.AppendTranslate(10.0, 20.0, 30.0); 720 operations_to.AppendScale(4.0, 8.0, 16.0); 721 722 gfx::BoxF box(1.f, 1.f, 1.f); 723 gfx::BoxF bounds; 724 725 SkMScalar min_progress = 0.f; 726 SkMScalar max_progress = 1.f; 727 728 EXPECT_FALSE(operations_to.BlendedBoundsForBox( 729 box, operations_from, min_progress, max_progress, &bounds)); 730} 731 732TEST(TransformOperationTest, BlendedBoundsForIdentity) { 733 TransformOperations operations_from; 734 operations_from.AppendIdentity(); 735 TransformOperations operations_to; 736 operations_to.AppendIdentity(); 737 738 gfx::BoxF box(1.f, 2.f, 3.f); 739 gfx::BoxF bounds; 740 741 SkMScalar min_progress = 0.f; 742 SkMScalar max_progress = 1.f; 743 744 EXPECT_TRUE(operations_to.BlendedBoundsForBox( 745 box, operations_from, min_progress, max_progress, &bounds)); 746 EXPECT_EQ(box.ToString(), bounds.ToString()); 747} 748 749TEST(TransformOperationTest, BlendedBoundsForTranslate) { 750 TransformOperations operations_from; 751 operations_from.AppendTranslate(3.0, -4.0, 2.0); 752 TransformOperations operations_to; 753 operations_to.AppendTranslate(7.0, 4.0, -2.0); 754 755 gfx::BoxF box(1.f, 2.f, 3.f, 4.f, 4.f, 4.f); 756 gfx::BoxF bounds; 757 758 SkMScalar min_progress = -0.5f; 759 SkMScalar max_progress = 1.5f; 760 EXPECT_TRUE(operations_to.BlendedBoundsForBox( 761 box, operations_from, min_progress, max_progress, &bounds)); 762 EXPECT_EQ(gfx::BoxF(2.f, -6.f, -1.f, 12.f, 20.f, 12.f).ToString(), 763 bounds.ToString()); 764 765 min_progress = 0.f; 766 max_progress = 1.f; 767 EXPECT_TRUE(operations_to.BlendedBoundsForBox( 768 box, operations_from, min_progress, max_progress, &bounds)); 769 EXPECT_EQ(gfx::BoxF(4.f, -2.f, 1.f, 8.f, 12.f, 8.f).ToString(), 770 bounds.ToString()); 771 772 TransformOperations identity; 773 EXPECT_TRUE(operations_to.BlendedBoundsForBox( 774 box, identity, min_progress, max_progress, &bounds)); 775 EXPECT_EQ(gfx::BoxF(1.f, 2.f, 1.f, 11.f, 8.f, 6.f).ToString(), 776 bounds.ToString()); 777 778 EXPECT_TRUE(identity.BlendedBoundsForBox( 779 box, operations_from, min_progress, max_progress, &bounds)); 780 EXPECT_EQ(gfx::BoxF(1.f, -2.f, 3.f, 7.f, 8.f, 6.f).ToString(), 781 bounds.ToString()); 782} 783 784TEST(TransformOperationTest, BlendedBoundsForScale) { 785 TransformOperations operations_from; 786 operations_from.AppendScale(3.0, 0.5, 2.0); 787 TransformOperations operations_to; 788 operations_to.AppendScale(7.0, 4.0, -2.0); 789 790 gfx::BoxF box(1.f, 2.f, 3.f, 4.f, 4.f, 4.f); 791 gfx::BoxF bounds; 792 793 SkMScalar min_progress = -0.5f; 794 SkMScalar max_progress = 1.5f; 795 EXPECT_TRUE(operations_to.BlendedBoundsForBox( 796 box, operations_from, min_progress, max_progress, &bounds)); 797 EXPECT_EQ(gfx::BoxF(1.f, -7.5f, -28.f, 44.f, 42.f, 56.f).ToString(), 798 bounds.ToString()); 799 800 min_progress = 0.f; 801 max_progress = 1.f; 802 EXPECT_TRUE(operations_to.BlendedBoundsForBox( 803 box, operations_from, min_progress, max_progress, &bounds)); 804 EXPECT_EQ(gfx::BoxF(3.f, 1.f, -14.f, 32.f, 23.f, 28.f).ToString(), 805 bounds.ToString()); 806 807 TransformOperations identity; 808 EXPECT_TRUE(operations_to.BlendedBoundsForBox( 809 box, identity, min_progress, max_progress, &bounds)); 810 EXPECT_EQ(gfx::BoxF(1.f, 2.f, -14.f, 34.f, 22.f, 21.f).ToString(), 811 bounds.ToString()); 812 813 EXPECT_TRUE(identity.BlendedBoundsForBox( 814 box, operations_from, min_progress, max_progress, &bounds)); 815 EXPECT_EQ(gfx::BoxF(1.f, 1.f, 3.f, 14.f, 5.f, 11.f).ToString(), 816 bounds.ToString()); 817} 818 819TEST(TransformOperationTest, BlendedBoundsWithZeroScale) { 820 TransformOperations zero_scale; 821 zero_scale.AppendScale(0.0, 0.0, 0.0); 822 TransformOperations non_zero_scale; 823 non_zero_scale.AppendScale(2.0, -4.0, 5.0); 824 825 gfx::BoxF box(1.f, 2.f, 3.f, 4.f, 4.f, 4.f); 826 gfx::BoxF bounds; 827 828 SkMScalar min_progress = 0.f; 829 SkMScalar max_progress = 1.f; 830 EXPECT_TRUE(zero_scale.BlendedBoundsForBox( 831 box, non_zero_scale, min_progress, max_progress, &bounds)); 832 EXPECT_EQ(gfx::BoxF(0.f, -24.f, 0.f, 10.f, 24.f, 35.f).ToString(), 833 bounds.ToString()); 834 835 EXPECT_TRUE(non_zero_scale.BlendedBoundsForBox( 836 box, zero_scale, min_progress, max_progress, &bounds)); 837 EXPECT_EQ(gfx::BoxF(0.f, -24.f, 0.f, 10.f, 24.f, 35.f).ToString(), 838 bounds.ToString()); 839 840 EXPECT_TRUE(zero_scale.BlendedBoundsForBox( 841 box, zero_scale, min_progress, max_progress, &bounds)); 842 EXPECT_EQ(gfx::BoxF().ToString(), bounds.ToString()); 843} 844 845TEST(TransformOperationTest, BlendedBoundsForRotationTrivial) { 846 TransformOperations operations_from; 847 operations_from.AppendRotate(0.f, 0.f, 1.f, 0.f); 848 TransformOperations operations_to; 849 operations_to.AppendRotate(0.f, 0.f, 1.f, 360.f); 850 851 float sqrt_2 = sqrt(2.f); 852 gfx::BoxF box( 853 -sqrt_2, -sqrt_2, 0.f, sqrt_2, sqrt_2, 0.f); 854 gfx::BoxF bounds; 855 856 // Since we're rotating 360 degrees, any box with dimensions between 0 and 857 // 2 * sqrt(2) should give the same result. 858 float sizes[] = { 0.f, 0.1f, sqrt_2, 2.f * sqrt_2 }; 859 for (size_t i = 0; i < arraysize(sizes); ++i) { 860 box.set_size(sizes[i], sizes[i], 0.f); 861 SkMScalar min_progress = 0.f; 862 SkMScalar max_progress = 1.f; 863 EXPECT_TRUE(operations_to.BlendedBoundsForBox( 864 box, operations_from, min_progress, max_progress, &bounds)); 865 EXPECT_EQ(gfx::BoxF(-2.f, -2.f, 0.f, 4.f, 4.f, 0.f).ToString(), 866 bounds.ToString()); 867 } 868} 869 870TEST(TransformOperationTest, BlendedBoundsForRotationAllExtrema) { 871 // If the normal is out of the plane, we can have up to 6 extrema (a min/max 872 // in each dimension) between the endpoints of the arc. This test ensures that 873 // we consider all 6. 874 TransformOperations operations_from; 875 operations_from.AppendRotate(1.f, 1.f, 1.f, 30.f); 876 TransformOperations operations_to; 877 operations_to.AppendRotate(1.f, 1.f, 1.f, 390.f); 878 879 gfx::BoxF box(1.f, 0.f, 0.f, 0.f, 0.f, 0.f); 880 gfx::BoxF bounds; 881 882 float min = -1.f / 3.f; 883 float max = 1.f; 884 float size = max - min; 885 EXPECT_TRUE(operations_to.BlendedBoundsForBox( 886 box, operations_from, 0.f, 1.f, &bounds)); 887 EXPECT_EQ(gfx::BoxF(min, min, min, size, size, size).ToString(), 888 bounds.ToString()); 889} 890 891TEST(TransformOperationTest, BlendedBoundsForRotationPointOnAxis) { 892 // Checks that if the point to rotate is sitting on the axis of rotation, that 893 // it does not get affected. 894 TransformOperations operations_from; 895 operations_from.AppendRotate(1.f, 1.f, 1.f, 30.f); 896 TransformOperations operations_to; 897 operations_to.AppendRotate(1.f, 1.f, 1.f, 390.f); 898 899 gfx::BoxF box(1.f, 1.f, 1.f, 0.f, 0.f, 0.f); 900 gfx::BoxF bounds; 901 902 EXPECT_TRUE(operations_to.BlendedBoundsForBox( 903 box, operations_from, 0.f, 1.f, &bounds)); 904 EXPECT_EQ(box.ToString(), bounds.ToString()); 905} 906 907// This would have been best as anonymous structs, but |arraysize| does not get 908// along with anonymous structs (and using ARRAYSIZE_UNSAFE seemed like a worse 909// option). 910struct ProblematicAxisTest { 911 float x; 912 float y; 913 float z; 914 gfx::BoxF expected; 915}; 916 917TEST(TransformOperationTest, BlendedBoundsForRotationProblematicAxes) { 918 // Zeros in the components of the axis of rotation turned out to be tricky to 919 // deal with in practice. This function tests some potentially problematic 920 // axes to ensure sane behavior. 921 922 // Some common values used in the expected boxes. 923 float dim1 = 0.292893f; 924 float dim2 = sqrt(2.f); 925 float dim3 = 2.f * dim2; 926 927 ProblematicAxisTest tests[] = { 928 { 0.f, 0.f, 0.f, gfx::BoxF(1.f, 1.f, 1.f, 0.f, 0.f, 0.f) }, 929 { 1.f, 0.f, 0.f, gfx::BoxF(1.f, -dim2, -dim2, 0.f, dim3, dim3) }, 930 { 0.f, 1.f, 0.f, gfx::BoxF(-dim2, 1.f, -dim2, dim3, 0.f, dim3) }, 931 { 0.f, 0.f, 1.f, gfx::BoxF(-dim2, -dim2, 1.f, dim3, dim3, 0.f) }, 932 { 1.f, 1.f, 0.f, gfx::BoxF(dim1, dim1, -1.f, dim2, dim2, 2.f) }, 933 { 0.f, 1.f, 1.f, gfx::BoxF(-1.f, dim1, dim1, 2.f, dim2, dim2) }, 934 { 1.f, 0.f, 1.f, gfx::BoxF(dim1, -1.f, dim1, dim2, 2.f, dim2) } 935 }; 936 937 for (size_t i = 0; i < arraysize(tests); ++i) { 938 float x = tests[i].x; 939 float y = tests[i].y; 940 float z = tests[i].z; 941 TransformOperations operations_from; 942 operations_from.AppendRotate(x, y, z, 0.f); 943 TransformOperations operations_to; 944 operations_to.AppendRotate(x, y, z, 360.f); 945 gfx::BoxF box(1.f, 1.f, 1.f, 0.f, 0.f, 0.f); 946 gfx::BoxF bounds; 947 948 EXPECT_TRUE(operations_to.BlendedBoundsForBox( 949 box, operations_from, 0.f, 1.f, &bounds)); 950 EXPECT_EQ(tests[i].expected.ToString(), bounds.ToString()); 951 } 952} 953 954// These would have been best as anonymous structs, but |arraysize| does not get 955// along with anonymous structs (and using ARRAYSIZE_UNSAFE seemed like a worse 956// option). 957struct TestAxis { 958 float x; 959 float y; 960 float z; 961}; 962 963struct TestAngles { 964 float theta_from; 965 float theta_to; 966}; 967 968struct TestProgress { 969 float min_progress; 970 float max_progress; 971}; 972 973TEST(TransformOperationsTest, BlendedBoundsForRotationEmpiricalTests) { 974 // Sets up various axis angle combinations, computes the bounding box and 975 // empirically tests that the transformed bounds are indeed contained by the 976 // computed bounding box. 977 978 TestAxis axes[] = { 979 { 1.f, 1.f, 1.f }, 980 { -1.f, -1.f, -1.f }, 981 { -1.f, 2.f, 3.f }, 982 { 1.f, -2.f, 3.f }, 983 { 1.f, 2.f, -3.f }, 984 { 0.f, 0.f, 0.f }, 985 { 1.f, 0.f, 0.f }, 986 { 0.f, 1.f, 0.f }, 987 { 0.f, 0.f, 1.f }, 988 { 1.f, 1.f, 0.f }, 989 { 0.f, 1.f, 1.f }, 990 { 1.f, 0.f, 1.f }, 991 { -1.f, 0.f, 0.f }, 992 { 0.f, -1.f, 0.f }, 993 { 0.f, 0.f, -1.f }, 994 { -1.f, -1.f, 0.f }, 995 { 0.f, -1.f, -1.f }, 996 { -1.f, 0.f, -1.f } 997 }; 998 999 TestAngles angles[] = { 1000 { 5.f, 10.f }, 1001 { 10.f, 5.f }, 1002 { 0.f, 360.f }, 1003 { 20.f, 180.f }, 1004 { -20.f, -180.f }, 1005 { 180.f, -220.f }, 1006 { 220.f, 320.f } 1007 }; 1008 1009 // We can go beyond the range [0, 1] (the bezier might slide out of this range 1010 // at either end), but since the first and last knots are at (0, 0) and (1, 1) 1011 // we will never go within it, so these tests are sufficient. 1012 TestProgress progress[] = { 1013 { 0.f, 1.f }, 1014 { -.25f, 1.25f }, 1015 }; 1016 1017 size_t num_steps = 150; 1018 for (size_t i = 0; i < arraysize(axes); ++i) { 1019 for (size_t j = 0; j < arraysize(angles); ++j) { 1020 for (size_t k = 0; k < arraysize(progress); ++k) { 1021 float x = axes[i].x; 1022 float y = axes[i].y; 1023 float z = axes[i].z; 1024 TransformOperations operations_from; 1025 operations_from.AppendRotate(x, y, z, angles[j].theta_from); 1026 TransformOperations operations_to; 1027 operations_to.AppendRotate(x, y, z, angles[j].theta_to); 1028 1029 gfx::BoxF box(2.f, 5.f, 6.f, 1.f, 3.f, 2.f); 1030 gfx::BoxF bounds; 1031 1032 EXPECT_TRUE(operations_to.BlendedBoundsForBox(box, 1033 operations_from, 1034 progress[k].min_progress, 1035 progress[k].max_progress, 1036 &bounds)); 1037 bool first_point = true; 1038 gfx::BoxF empirical_bounds; 1039 for (size_t step = 0; step < num_steps; ++step) { 1040 float t = step / (num_steps - 1.f); 1041 t = gfx::Tween::FloatValueBetween( 1042 t, progress[k].min_progress, progress[k].max_progress); 1043 gfx::Transform partial_rotation = 1044 operations_to.Blend(operations_from, t); 1045 1046 for (int corner = 0; corner < 8; ++corner) { 1047 gfx::Point3F point = box.origin(); 1048 point += gfx::Vector3dF(corner & 1 ? box.width() : 0.f, 1049 corner & 2 ? box.height() : 0.f, 1050 corner & 4 ? box.depth() : 0.f); 1051 partial_rotation.TransformPoint(&point); 1052 if (first_point) { 1053 empirical_bounds.set_origin(point); 1054 first_point = false; 1055 } else { 1056 empirical_bounds.ExpandTo(point); 1057 } 1058 } 1059 } 1060 1061 // Our empirical estimate will be a little rough since we're only doing 1062 // 100 samples. 1063 static const float kTolerance = 1e-2f; 1064 EXPECT_NEAR(empirical_bounds.x(), bounds.x(), kTolerance); 1065 EXPECT_NEAR(empirical_bounds.y(), bounds.y(), kTolerance); 1066 EXPECT_NEAR(empirical_bounds.z(), bounds.z(), kTolerance); 1067 EXPECT_NEAR(empirical_bounds.width(), bounds.width(), kTolerance); 1068 EXPECT_NEAR(empirical_bounds.height(), bounds.height(), kTolerance); 1069 EXPECT_NEAR(empirical_bounds.depth(), bounds.depth(), kTolerance); 1070 } 1071 } 1072 } 1073} 1074 1075TEST(TransformOperationTest, BlendedBoundsForSequence) { 1076 TransformOperations operations_from; 1077 operations_from.AppendTranslate(2.0, 4.0, -1.0); 1078 operations_from.AppendScale(-1.0, 2.0, 3.0); 1079 operations_from.AppendTranslate(1.0, -5.0, 1.0); 1080 TransformOperations operations_to; 1081 operations_to.AppendTranslate(6.0, -2.0, 3.0); 1082 operations_to.AppendScale(-3.0, -2.0, 5.0); 1083 operations_to.AppendTranslate(13.0, -1.0, 5.0); 1084 1085 gfx::BoxF box(1.f, 2.f, 3.f, 4.f, 4.f, 4.f); 1086 gfx::BoxF bounds; 1087 1088 SkMScalar min_progress = -0.5f; 1089 SkMScalar max_progress = 1.5f; 1090 EXPECT_TRUE(operations_to.BlendedBoundsForBox( 1091 box, operations_from, min_progress, max_progress, &bounds)); 1092 EXPECT_EQ(gfx::BoxF(-57.f, -59.f, -1.f, 76.f, 112.f, 80.f).ToString(), 1093 bounds.ToString()); 1094 1095 min_progress = 0.f; 1096 max_progress = 1.f; 1097 EXPECT_TRUE(operations_to.BlendedBoundsForBox( 1098 box, operations_from, min_progress, max_progress, &bounds)); 1099 EXPECT_EQ(gfx::BoxF(-32.f, -25.f, 7.f, 42.f, 44.f, 48.f).ToString(), 1100 bounds.ToString()); 1101 1102 TransformOperations identity; 1103 EXPECT_TRUE(operations_to.BlendedBoundsForBox( 1104 box, identity, min_progress, max_progress, &bounds)); 1105 EXPECT_EQ(gfx::BoxF(-33.f, -13.f, 3.f, 57.f, 19.f, 52.f).ToString(), 1106 bounds.ToString()); 1107 1108 EXPECT_TRUE(identity.BlendedBoundsForBox( 1109 box, operations_from, min_progress, max_progress, &bounds)); 1110 EXPECT_EQ(gfx::BoxF(-7.f, -3.f, 2.f, 15.f, 23.f, 20.f).ToString(), 1111 bounds.ToString()); 1112} 1113 1114} // namespace 1115} // namespace cc 1116