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