Home | History | Annotate | Download | only in animation
      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/memory/scoped_vector.h"
      8 #include "cc/animation/transform_operations.h"
      9 #include "cc/test/geometry_test_utils.h"
     10 #include "testing/gtest/include/gtest/gtest.h"
     11 #include "ui/gfx/vector3d_f.h"
     12 
     13 namespace cc {
     14 namespace {
     15 
     16 TEST(TransformOperationTest, TransformTypesAreUnique) {
     17   ScopedVector<TransformOperations> transforms;
     18 
     19   TransformOperations* to_add = new TransformOperations();
     20   to_add->AppendTranslate(1, 0, 0);
     21   transforms.push_back(to_add);
     22 
     23   to_add = new TransformOperations();
     24   to_add->AppendRotate(0, 0, 1, 2);
     25   transforms.push_back(to_add);
     26 
     27   to_add = new TransformOperations();
     28   to_add->AppendScale(2, 2, 2);
     29   transforms.push_back(to_add);
     30 
     31   to_add = new TransformOperations();
     32   to_add->AppendSkew(1, 0);
     33   transforms.push_back(to_add);
     34 
     35   to_add = new TransformOperations();
     36   to_add->AppendPerspective(800);
     37   transforms.push_back(to_add);
     38 
     39   for (size_t i = 0; i < transforms.size(); ++i) {
     40     for (size_t j = 0; j < transforms.size(); ++j) {
     41       bool matches_type = transforms[i]->MatchesTypes(*transforms[j]);
     42       EXPECT_TRUE((i == j && matches_type) || !matches_type);
     43     }
     44   }
     45 }
     46 
     47 TEST(TransformOperationTest, MatchTypesSameLength) {
     48   TransformOperations translates;
     49   translates.AppendTranslate(1, 0, 0);
     50   translates.AppendTranslate(1, 0, 0);
     51   translates.AppendTranslate(1, 0, 0);
     52 
     53   TransformOperations skews;
     54   skews.AppendSkew(0, 2);
     55   skews.AppendSkew(0, 2);
     56   skews.AppendSkew(0, 2);
     57 
     58   TransformOperations translates2;
     59   translates2.AppendTranslate(0, 2, 0);
     60   translates2.AppendTranslate(0, 2, 0);
     61   translates2.AppendTranslate(0, 2, 0);
     62 
     63   TransformOperations translates3 = translates2;
     64 
     65   EXPECT_FALSE(translates.MatchesTypes(skews));
     66   EXPECT_TRUE(translates.MatchesTypes(translates2));
     67   EXPECT_TRUE(translates.MatchesTypes(translates3));
     68 }
     69 
     70 TEST(TransformOperationTest, MatchTypesDifferentLength) {
     71   TransformOperations translates;
     72   translates.AppendTranslate(1, 0, 0);
     73   translates.AppendTranslate(1, 0, 0);
     74   translates.AppendTranslate(1, 0, 0);
     75 
     76   TransformOperations skews;
     77   skews.AppendSkew(2, 0);
     78   skews.AppendSkew(2, 0);
     79 
     80   TransformOperations translates2;
     81   translates2.AppendTranslate(0, 2, 0);
     82   translates2.AppendTranslate(0, 2, 0);
     83 
     84   EXPECT_FALSE(translates.MatchesTypes(skews));
     85   EXPECT_FALSE(translates.MatchesTypes(translates2));
     86 }
     87 
     88 void GetIdentityOperations(ScopedVector<TransformOperations>* operations) {
     89   TransformOperations* to_add = new TransformOperations();
     90   operations->push_back(to_add);
     91 
     92   to_add = new TransformOperations();
     93   to_add->AppendTranslate(0, 0, 0);
     94   operations->push_back(to_add);
     95 
     96   to_add = new TransformOperations();
     97   to_add->AppendTranslate(0, 0, 0);
     98   to_add->AppendTranslate(0, 0, 0);
     99   operations->push_back(to_add);
    100 
    101   to_add = new TransformOperations();
    102   to_add->AppendScale(1, 1, 1);
    103   operations->push_back(to_add);
    104 
    105   to_add = new TransformOperations();
    106   to_add->AppendScale(1, 1, 1);
    107   to_add->AppendScale(1, 1, 1);
    108   operations->push_back(to_add);
    109 
    110   to_add = new TransformOperations();
    111   to_add->AppendSkew(0, 0);
    112   operations->push_back(to_add);
    113 
    114   to_add = new TransformOperations();
    115   to_add->AppendSkew(0, 0);
    116   to_add->AppendSkew(0, 0);
    117   operations->push_back(to_add);
    118 
    119   to_add = new TransformOperations();
    120   to_add->AppendRotate(0, 0, 1, 0);
    121   operations->push_back(to_add);
    122 
    123   to_add = new TransformOperations();
    124   to_add->AppendRotate(0, 0, 1, 0);
    125   to_add->AppendRotate(0, 0, 1, 0);
    126   operations->push_back(to_add);
    127 
    128   to_add = new TransformOperations();
    129   to_add->AppendMatrix(gfx::Transform());
    130   operations->push_back(to_add);
    131 
    132   to_add = new TransformOperations();
    133   to_add->AppendMatrix(gfx::Transform());
    134   to_add->AppendMatrix(gfx::Transform());
    135   operations->push_back(to_add);
    136 }
    137 
    138 TEST(TransformOperationTest, IdentityAlwaysMatches) {
    139   ScopedVector<TransformOperations> operations;
    140   GetIdentityOperations(&operations);
    141 
    142   for (size_t i = 0; i < operations.size(); ++i) {
    143     for (size_t j = 0; j < operations.size(); ++j)
    144       EXPECT_TRUE(operations[i]->MatchesTypes(*operations[j]));
    145   }
    146 }
    147 
    148 TEST(TransformOperationTest, ApplyTranslate) {
    149   double x = 1;
    150   double y = 2;
    151   double z = 3;
    152   TransformOperations operations;
    153   operations.AppendTranslate(x, y, z);
    154   gfx::Transform expected;
    155   expected.Translate3d(x, y, z);
    156   EXPECT_TRANSFORMATION_MATRIX_EQ(expected, operations.Apply());
    157 }
    158 
    159 TEST(TransformOperationTest, ApplyRotate) {
    160   double x = 1;
    161   double y = 2;
    162   double z = 3;
    163   double degrees = 80;
    164   TransformOperations operations;
    165   operations.AppendRotate(x, y, z, degrees);
    166   gfx::Transform expected;
    167   expected.RotateAbout(gfx::Vector3dF(x, y, z), degrees);
    168   EXPECT_TRANSFORMATION_MATRIX_EQ(expected, operations.Apply());
    169 }
    170 
    171 TEST(TransformOperationTest, ApplyScale) {
    172   double x = 1;
    173   double y = 2;
    174   double z = 3;
    175   TransformOperations operations;
    176   operations.AppendScale(x, y, z);
    177   gfx::Transform expected;
    178   expected.Scale3d(x, y, z);
    179   EXPECT_TRANSFORMATION_MATRIX_EQ(expected, operations.Apply());
    180 }
    181 
    182 TEST(TransformOperationTest, ApplySkew) {
    183   double x = 1;
    184   double y = 2;
    185   TransformOperations operations;
    186   operations.AppendSkew(x, y);
    187   gfx::Transform expected;
    188   expected.SkewX(x);
    189   expected.SkewY(y);
    190   EXPECT_TRANSFORMATION_MATRIX_EQ(expected, operations.Apply());
    191 }
    192 
    193 TEST(TransformOperationTest, ApplyPerspective) {
    194   double depth = 800;
    195   TransformOperations operations;
    196   operations.AppendPerspective(depth);
    197   gfx::Transform expected;
    198   expected.ApplyPerspectiveDepth(depth);
    199   EXPECT_TRANSFORMATION_MATRIX_EQ(expected, operations.Apply());
    200 }
    201 
    202 TEST(TransformOperationTest, ApplyMatrix) {
    203   double dx = 1;
    204   double dy = 2;
    205   double dz = 3;
    206   gfx::Transform expected_matrix;
    207   expected_matrix.Translate3d(dx, dy, dz);
    208   TransformOperations matrix_transform;
    209   matrix_transform.AppendMatrix(expected_matrix);
    210   EXPECT_TRANSFORMATION_MATRIX_EQ(expected_matrix, matrix_transform.Apply());
    211 }
    212 
    213 TEST(TransformOperationTest, ApplyOrder) {
    214   double sx = 2;
    215   double sy = 4;
    216   double sz = 8;
    217 
    218   double dx = 1;
    219   double dy = 2;
    220   double dz = 3;
    221 
    222   TransformOperations operations;
    223   operations.AppendScale(sx, sy, sz);
    224   operations.AppendTranslate(dx, dy, dz);
    225 
    226   gfx::Transform expected_scale_matrix;
    227   expected_scale_matrix.Scale3d(sx, sy, sz);
    228 
    229   gfx::Transform expected_translate_matrix;
    230   expected_translate_matrix.Translate3d(dx, dy, dz);
    231 
    232   gfx::Transform expected_combined_matrix = expected_scale_matrix;
    233   expected_combined_matrix.PreconcatTransform(expected_translate_matrix);
    234 
    235   EXPECT_TRANSFORMATION_MATRIX_EQ(expected_combined_matrix, operations.Apply());
    236 }
    237 
    238 TEST(TransformOperationTest, BlendOrder) {
    239   double sx1 = 2;
    240   double sy1 = 4;
    241   double sz1 = 8;
    242 
    243   double dx1 = 1;
    244   double dy1 = 2;
    245   double dz1 = 3;
    246 
    247   double sx2 = 4;
    248   double sy2 = 8;
    249   double sz2 = 16;
    250 
    251   double dx2 = 10;
    252   double dy2 = 20;
    253   double dz2 = 30;
    254 
    255   TransformOperations operations_from;
    256   operations_from.AppendScale(sx1, sy1, sz1);
    257   operations_from.AppendTranslate(dx1, dy1, dz1);
    258 
    259   TransformOperations operations_to;
    260   operations_to.AppendScale(sx2, sy2, sz2);
    261   operations_to.AppendTranslate(dx2, dy2, dz2);
    262 
    263   gfx::Transform scale_from;
    264   scale_from.Scale3d(sx1, sy1, sz1);
    265   gfx::Transform translate_from;
    266   translate_from.Translate3d(dx1, dy1, dz1);
    267 
    268   gfx::Transform scale_to;
    269   scale_to.Scale3d(sx2, sy2, sz2);
    270   gfx::Transform translate_to;
    271   translate_to.Translate3d(dx2, dy2, dz2);
    272 
    273   double progress = 0.25;
    274 
    275   gfx::Transform blended_scale = scale_to;
    276   blended_scale.Blend(scale_from, progress);
    277 
    278   gfx::Transform blended_translate = translate_to;
    279   blended_translate.Blend(translate_from, progress);
    280 
    281   gfx::Transform expected = blended_scale;
    282   expected.PreconcatTransform(blended_translate);
    283 
    284   EXPECT_TRANSFORMATION_MATRIX_EQ(
    285       expected, operations_to.Blend(operations_from, progress));
    286 }
    287 
    288 static void CheckProgress(double progress,
    289               const gfx::Transform& from_matrix,
    290               const gfx::Transform& to_matrix,
    291               const TransformOperations& from_transform,
    292               const TransformOperations& to_transform) {
    293   gfx::Transform expected_matrix = to_matrix;
    294   expected_matrix.Blend(from_matrix, progress);
    295   EXPECT_TRANSFORMATION_MATRIX_EQ(
    296       expected_matrix, to_transform.Blend(from_transform, progress));
    297 }
    298 
    299 TEST(TransformOperationTest, BlendProgress) {
    300   double sx = 2;
    301   double sy = 4;
    302   double sz = 8;
    303   TransformOperations operations_from;
    304   operations_from.AppendScale(sx, sy, sz);
    305 
    306   gfx::Transform matrix_from;
    307   matrix_from.Scale3d(sx, sy, sz);
    308 
    309   sx = 4;
    310   sy = 8;
    311   sz = 16;
    312   TransformOperations operations_to;
    313   operations_to.AppendScale(sx, sy, sz);
    314 
    315   gfx::Transform matrix_to;
    316   matrix_to.Scale3d(sx, sy, sz);
    317 
    318   CheckProgress(-1, matrix_from, matrix_to, operations_from, operations_to);
    319   CheckProgress(0, matrix_from, matrix_to, operations_from, operations_to);
    320   CheckProgress(0.25, matrix_from, matrix_to, operations_from, operations_to);
    321   CheckProgress(0.5, matrix_from, matrix_to, operations_from, operations_to);
    322   CheckProgress(1, matrix_from, matrix_to, operations_from, operations_to);
    323   CheckProgress(2, matrix_from, matrix_to, operations_from, operations_to);
    324 }
    325 
    326 TEST(TransformOperationTest, BlendWhenTypesDoNotMatch) {
    327   double sx1 = 2;
    328   double sy1 = 4;
    329   double sz1 = 8;
    330 
    331   double dx1 = 1;
    332   double dy1 = 2;
    333   double dz1 = 3;
    334 
    335   double sx2 = 4;
    336   double sy2 = 8;
    337   double sz2 = 16;
    338 
    339   double dx2 = 10;
    340   double dy2 = 20;
    341   double dz2 = 30;
    342 
    343   TransformOperations operations_from;
    344   operations_from.AppendScale(sx1, sy1, sz1);
    345   operations_from.AppendTranslate(dx1, dy1, dz1);
    346 
    347   TransformOperations operations_to;
    348   operations_to.AppendTranslate(dx2, dy2, dz2);
    349   operations_to.AppendScale(sx2, sy2, sz2);
    350 
    351   gfx::Transform from;
    352   from.Scale3d(sx1, sy1, sz1);
    353   from.Translate3d(dx1, dy1, dz1);
    354 
    355   gfx::Transform to;
    356   to.Translate3d(dx2, dy2, dz2);
    357   to.Scale3d(sx2, sy2, sz2);
    358 
    359   double progress = 0.25;
    360 
    361   gfx::Transform expected = to;
    362   expected.Blend(from, progress);
    363 
    364   EXPECT_TRANSFORMATION_MATRIX_EQ(
    365       expected, operations_to.Blend(operations_from, progress));
    366 }
    367 
    368 TEST(TransformOperationTest, LargeRotationsWithSameAxis) {
    369   TransformOperations operations_from;
    370   operations_from.AppendRotate(0, 0, 1, 0);
    371 
    372   TransformOperations operations_to;
    373   operations_to.AppendRotate(0, 0, 2, 360);
    374 
    375   double progress = 0.5;
    376 
    377   gfx::Transform expected;
    378   expected.RotateAbout(gfx::Vector3dF(0, 0, 1), 180);
    379 
    380   EXPECT_TRANSFORMATION_MATRIX_EQ(
    381       expected, operations_to.Blend(operations_from, progress));
    382 }
    383 
    384 TEST(TransformOperationTest, LargeRotationsWithSameAxisInDifferentDirection) {
    385   TransformOperations operations_from;
    386   operations_from.AppendRotate(0, 0, 1, 180);
    387 
    388   TransformOperations operations_to;
    389   operations_to.AppendRotate(0, 0, -1, 180);
    390 
    391   double progress = 0.5;
    392 
    393   gfx::Transform expected;
    394 
    395   EXPECT_TRANSFORMATION_MATRIX_EQ(
    396       expected, operations_to.Blend(operations_from, progress));
    397 }
    398 
    399 TEST(TransformOperationTest, LargeRotationsWithDifferentAxes) {
    400   TransformOperations operations_from;
    401   operations_from.AppendRotate(0, 0, 1, 175);
    402 
    403   TransformOperations operations_to;
    404   operations_to.AppendRotate(0, 1, 0, 175);
    405 
    406   double progress = 0.5;
    407   gfx::Transform matrix_from;
    408   matrix_from.RotateAbout(gfx::Vector3dF(0, 0, 1), 175);
    409 
    410   gfx::Transform matrix_to;
    411   matrix_to.RotateAbout(gfx::Vector3dF(0, 1, 0), 175);
    412 
    413   gfx::Transform expected = matrix_to;
    414   expected.Blend(matrix_from, progress);
    415 
    416   EXPECT_TRANSFORMATION_MATRIX_EQ(
    417       expected, operations_to.Blend(operations_from, progress));
    418 }
    419 
    420 TEST(TransformOperationTest, BlendRotationFromIdentity) {
    421   ScopedVector<TransformOperations> identity_operations;
    422   GetIdentityOperations(&identity_operations);
    423 
    424   for (size_t i = 0; i < identity_operations.size(); ++i) {
    425     TransformOperations operations;
    426     operations.AppendRotate(0, 0, 1, 360);
    427 
    428     double progress = 0.5;
    429 
    430     gfx::Transform expected;
    431     expected.RotateAbout(gfx::Vector3dF(0, 0, 1), 180);
    432 
    433     EXPECT_TRANSFORMATION_MATRIX_EQ(
    434         expected, operations.Blend(*identity_operations[i], progress));
    435 
    436     progress = -0.5;
    437 
    438     expected.MakeIdentity();
    439     expected.RotateAbout(gfx::Vector3dF(0, 0, 1), -180);
    440 
    441     EXPECT_TRANSFORMATION_MATRIX_EQ(
    442         expected, operations.Blend(*identity_operations[i], progress));
    443 
    444     progress = 1.5;
    445 
    446     expected.MakeIdentity();
    447     expected.RotateAbout(gfx::Vector3dF(0, 0, 1), 540);
    448 
    449     EXPECT_TRANSFORMATION_MATRIX_EQ(
    450         expected, operations.Blend(*identity_operations[i], progress));
    451   }
    452 }
    453 
    454 TEST(TransformOperationTest, BlendTranslationFromIdentity) {
    455   ScopedVector<TransformOperations> identity_operations;
    456   GetIdentityOperations(&identity_operations);
    457 
    458   for (size_t i = 0; i < identity_operations.size(); ++i) {
    459     TransformOperations operations;
    460     operations.AppendTranslate(2, 2, 2);
    461 
    462     double progress = 0.5;
    463 
    464     gfx::Transform expected;
    465     expected.Translate3d(1, 1, 1);
    466 
    467     EXPECT_TRANSFORMATION_MATRIX_EQ(
    468         expected, operations.Blend(*identity_operations[i], progress));
    469 
    470     progress = -0.5;
    471 
    472     expected.MakeIdentity();
    473     expected.Translate3d(-1, -1, -1);
    474 
    475     EXPECT_TRANSFORMATION_MATRIX_EQ(
    476         expected, operations.Blend(*identity_operations[i], progress));
    477 
    478     progress = 1.5;
    479 
    480     expected.MakeIdentity();
    481     expected.Translate3d(3, 3, 3);
    482 
    483     EXPECT_TRANSFORMATION_MATRIX_EQ(
    484         expected, operations.Blend(*identity_operations[i], progress));
    485   }
    486 }
    487 
    488 TEST(TransformOperationTest, BlendScaleFromIdentity) {
    489   ScopedVector<TransformOperations> identity_operations;
    490   GetIdentityOperations(&identity_operations);
    491 
    492   for (size_t i = 0; i < identity_operations.size(); ++i) {
    493     TransformOperations operations;
    494     operations.AppendScale(3, 3, 3);
    495 
    496     double progress = 0.5;
    497 
    498     gfx::Transform expected;
    499     expected.Scale3d(2, 2, 2);
    500 
    501     EXPECT_TRANSFORMATION_MATRIX_EQ(
    502         expected, operations.Blend(*identity_operations[i], progress));
    503 
    504     progress = -0.5;
    505 
    506     expected.MakeIdentity();
    507     expected.Scale3d(0, 0, 0);
    508 
    509     EXPECT_TRANSFORMATION_MATRIX_EQ(
    510         expected, operations.Blend(*identity_operations[i], progress));
    511 
    512     progress = 1.5;
    513 
    514     expected.MakeIdentity();
    515     expected.Scale3d(4, 4, 4);
    516 
    517     EXPECT_TRANSFORMATION_MATRIX_EQ(
    518         expected, operations.Blend(*identity_operations[i], progress));
    519   }
    520 }
    521 
    522 TEST(TransformOperationTest, BlendSkewFromIdentity) {
    523   ScopedVector<TransformOperations> identity_operations;
    524   GetIdentityOperations(&identity_operations);
    525 
    526   for (size_t i = 0; i < identity_operations.size(); ++i) {
    527     TransformOperations operations;
    528     operations.AppendSkew(2, 2);
    529 
    530     double progress = 0.5;
    531 
    532     gfx::Transform expected;
    533     expected.SkewX(1);
    534     expected.SkewY(1);
    535 
    536     EXPECT_TRANSFORMATION_MATRIX_EQ(
    537         expected, operations.Blend(*identity_operations[i], progress));
    538 
    539     progress = -0.5;
    540 
    541     expected.MakeIdentity();
    542     expected.SkewX(-1);
    543     expected.SkewY(-1);
    544 
    545     EXPECT_TRANSFORMATION_MATRIX_EQ(
    546         expected, operations.Blend(*identity_operations[i], progress));
    547 
    548     progress = 1.5;
    549 
    550     expected.MakeIdentity();
    551     expected.SkewX(3);
    552     expected.SkewY(3);
    553 
    554     EXPECT_TRANSFORMATION_MATRIX_EQ(
    555         expected, operations.Blend(*identity_operations[i], progress));
    556   }
    557 }
    558 
    559 TEST(TransformOperationTest, BlendPerspectiveFromIdentity) {
    560   ScopedVector<TransformOperations> identity_operations;
    561   GetIdentityOperations(&identity_operations);
    562 
    563   for (size_t i = 0; i < identity_operations.size(); ++i) {
    564     TransformOperations operations;
    565     operations.AppendPerspective(1000);
    566 
    567     double progress = 0.5;
    568 
    569     gfx::Transform expected;
    570     expected.ApplyPerspectiveDepth(
    571         500 + 0.5 * std::numeric_limits<double>::max());
    572 
    573     EXPECT_TRANSFORMATION_MATRIX_EQ(
    574         expected, operations.Blend(*identity_operations[i], progress));
    575   }
    576 }
    577 
    578 TEST(TransformOperationTest, BlendRotationToIdentity) {
    579   ScopedVector<TransformOperations> identity_operations;
    580   GetIdentityOperations(&identity_operations);
    581 
    582   for (size_t i = 0; i < identity_operations.size(); ++i) {
    583     TransformOperations operations;
    584     operations.AppendRotate(0, 0, 1, 360);
    585 
    586     double progress = 0.5;
    587 
    588     gfx::Transform expected;
    589     expected.RotateAbout(gfx::Vector3dF(0, 0, 1), 180);
    590 
    591     EXPECT_TRANSFORMATION_MATRIX_EQ(
    592         expected, identity_operations[i]->Blend(operations, progress));
    593   }
    594 }
    595 
    596 TEST(TransformOperationTest, BlendTranslationToIdentity) {
    597   ScopedVector<TransformOperations> identity_operations;
    598   GetIdentityOperations(&identity_operations);
    599 
    600   for (size_t i = 0; i < identity_operations.size(); ++i) {
    601     TransformOperations operations;
    602     operations.AppendTranslate(2, 2, 2);
    603 
    604     double progress = 0.5;
    605 
    606     gfx::Transform expected;
    607     expected.Translate3d(1, 1, 1);
    608 
    609     EXPECT_TRANSFORMATION_MATRIX_EQ(
    610         expected, identity_operations[i]->Blend(operations, progress));
    611   }
    612 }
    613 
    614 TEST(TransformOperationTest, BlendScaleToIdentity) {
    615   ScopedVector<TransformOperations> identity_operations;
    616   GetIdentityOperations(&identity_operations);
    617 
    618   for (size_t i = 0; i < identity_operations.size(); ++i) {
    619     TransformOperations operations;
    620     operations.AppendScale(3, 3, 3);
    621 
    622     double progress = 0.5;
    623 
    624     gfx::Transform expected;
    625     expected.Scale3d(2, 2, 2);
    626 
    627     EXPECT_TRANSFORMATION_MATRIX_EQ(
    628         expected, identity_operations[i]->Blend(operations, progress));
    629   }
    630 }
    631 
    632 TEST(TransformOperationTest, BlendSkewToIdentity) {
    633   ScopedVector<TransformOperations> identity_operations;
    634   GetIdentityOperations(&identity_operations);
    635 
    636   for (size_t i = 0; i < identity_operations.size(); ++i) {
    637     TransformOperations operations;
    638     operations.AppendSkew(2, 2);
    639 
    640     double progress = 0.5;
    641 
    642     gfx::Transform expected;
    643     expected.SkewX(1);
    644     expected.SkewY(1);
    645 
    646     EXPECT_TRANSFORMATION_MATRIX_EQ(
    647         expected, identity_operations[i]->Blend(operations, progress));
    648   }
    649 }
    650 
    651 TEST(TransformOperationTest, BlendPerspectiveToIdentity) {
    652   ScopedVector<TransformOperations> identity_operations;
    653   GetIdentityOperations(&identity_operations);
    654 
    655   for (size_t i = 0; i < identity_operations.size(); ++i) {
    656     TransformOperations operations;
    657     operations.AppendPerspective(1000);
    658 
    659     double progress = 0.5;
    660 
    661     gfx::Transform expected;
    662     expected.ApplyPerspectiveDepth(
    663         500 + 0.5 * std::numeric_limits<double>::max());
    664 
    665     EXPECT_TRANSFORMATION_MATRIX_EQ(
    666         expected, identity_operations[i]->Blend(operations, progress));
    667   }
    668 }
    669 
    670 TEST(TransformOperationTest, ExtrapolatePerspectiveBlending) {
    671   TransformOperations operations1;
    672   operations1.AppendPerspective(1000);
    673 
    674   TransformOperations operations2;
    675   operations2.AppendPerspective(500);
    676 
    677   gfx::Transform expected;
    678   expected.ApplyPerspectiveDepth(250);
    679 
    680   EXPECT_TRANSFORMATION_MATRIX_EQ(
    681       expected, operations1.Blend(operations2, -0.5));
    682 
    683   expected.MakeIdentity();
    684   expected.ApplyPerspectiveDepth(1250);
    685 
    686   EXPECT_TRANSFORMATION_MATRIX_EQ(
    687       expected, operations1.Blend(operations2, 1.5));
    688 }
    689 
    690 TEST(TransformOperationTest, ExtrapolateMatrixBlending) {
    691   gfx::Transform transform1;
    692   transform1.Translate3d(1, 1, 1);
    693   TransformOperations operations1;
    694   operations1.AppendMatrix(transform1);
    695 
    696   gfx::Transform transform2;
    697   transform2.Translate3d(3, 3, 3);
    698   TransformOperations operations2;
    699   operations2.AppendMatrix(transform2);
    700 
    701   gfx::Transform expected;
    702   EXPECT_TRANSFORMATION_MATRIX_EQ(
    703       expected, operations1.Blend(operations2, 1.5));
    704 
    705   expected.Translate3d(4, 4, 4);
    706   EXPECT_TRANSFORMATION_MATRIX_EQ(
    707       expected, operations1.Blend(operations2, -0.5));
    708 }
    709 
    710 }  // namespace
    711 }  // namespace cc
    712