All instances of addresses as void* are changed to uintptr_t in
[chromium-blink-merge.git] / cc / animation / transform_operations_unittest.cc
blob572ab47ec7af73a05af0425d51bf068cadcb17ba
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.
5 #include <limits>
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/geometry/box_f.h"
14 #include "ui/gfx/geometry/rect_conversions.h"
15 #include "ui/gfx/geometry/vector3d_f.h"
17 namespace cc {
18 namespace {
20 TEST(TransformOperationTest, TransformTypesAreUnique) {
21 ScopedVector<TransformOperations> transforms;
23 TransformOperations* to_add = new TransformOperations();
24 to_add->AppendTranslate(1, 0, 0);
25 transforms.push_back(to_add);
27 to_add = new TransformOperations();
28 to_add->AppendRotate(0, 0, 1, 2);
29 transforms.push_back(to_add);
31 to_add = new TransformOperations();
32 to_add->AppendScale(2, 2, 2);
33 transforms.push_back(to_add);
35 to_add = new TransformOperations();
36 to_add->AppendSkew(1, 0);
37 transforms.push_back(to_add);
39 to_add = new TransformOperations();
40 to_add->AppendPerspective(800);
41 transforms.push_back(to_add);
43 for (size_t i = 0; i < transforms.size(); ++i) {
44 for (size_t j = 0; j < transforms.size(); ++j) {
45 bool matches_type = transforms[i]->MatchesTypes(*transforms[j]);
46 EXPECT_TRUE((i == j && matches_type) || !matches_type);
51 TEST(TransformOperationTest, MatchTypesSameLength) {
52 TransformOperations translates;
53 translates.AppendTranslate(1, 0, 0);
54 translates.AppendTranslate(1, 0, 0);
55 translates.AppendTranslate(1, 0, 0);
57 TransformOperations skews;
58 skews.AppendSkew(0, 2);
59 skews.AppendSkew(0, 2);
60 skews.AppendSkew(0, 2);
62 TransformOperations translates2;
63 translates2.AppendTranslate(0, 2, 0);
64 translates2.AppendTranslate(0, 2, 0);
65 translates2.AppendTranslate(0, 2, 0);
67 TransformOperations translates3 = translates2;
69 EXPECT_FALSE(translates.MatchesTypes(skews));
70 EXPECT_TRUE(translates.MatchesTypes(translates2));
71 EXPECT_TRUE(translates.MatchesTypes(translates3));
74 TEST(TransformOperationTest, MatchTypesDifferentLength) {
75 TransformOperations translates;
76 translates.AppendTranslate(1, 0, 0);
77 translates.AppendTranslate(1, 0, 0);
78 translates.AppendTranslate(1, 0, 0);
80 TransformOperations skews;
81 skews.AppendSkew(2, 0);
82 skews.AppendSkew(2, 0);
84 TransformOperations translates2;
85 translates2.AppendTranslate(0, 2, 0);
86 translates2.AppendTranslate(0, 2, 0);
88 EXPECT_FALSE(translates.MatchesTypes(skews));
89 EXPECT_FALSE(translates.MatchesTypes(translates2));
92 void GetIdentityOperations(ScopedVector<TransformOperations>* operations) {
93 TransformOperations* to_add = new TransformOperations();
94 operations->push_back(to_add);
96 to_add = new TransformOperations();
97 to_add->AppendTranslate(0, 0, 0);
98 operations->push_back(to_add);
100 to_add = new TransformOperations();
101 to_add->AppendTranslate(0, 0, 0);
102 to_add->AppendTranslate(0, 0, 0);
103 operations->push_back(to_add);
105 to_add = new TransformOperations();
106 to_add->AppendScale(1, 1, 1);
107 operations->push_back(to_add);
109 to_add = new TransformOperations();
110 to_add->AppendScale(1, 1, 1);
111 to_add->AppendScale(1, 1, 1);
112 operations->push_back(to_add);
114 to_add = new TransformOperations();
115 to_add->AppendSkew(0, 0);
116 operations->push_back(to_add);
118 to_add = new TransformOperations();
119 to_add->AppendSkew(0, 0);
120 to_add->AppendSkew(0, 0);
121 operations->push_back(to_add);
123 to_add = new TransformOperations();
124 to_add->AppendRotate(0, 0, 1, 0);
125 operations->push_back(to_add);
127 to_add = new TransformOperations();
128 to_add->AppendRotate(0, 0, 1, 0);
129 to_add->AppendRotate(0, 0, 1, 0);
130 operations->push_back(to_add);
132 to_add = new TransformOperations();
133 to_add->AppendMatrix(gfx::Transform());
134 operations->push_back(to_add);
136 to_add = new TransformOperations();
137 to_add->AppendMatrix(gfx::Transform());
138 to_add->AppendMatrix(gfx::Transform());
139 operations->push_back(to_add);
142 TEST(TransformOperationTest, MatchTypesOrder) {
143 TransformOperations mix_order_identity;
144 mix_order_identity.AppendTranslate(0, 0, 0);
145 mix_order_identity.AppendScale(1, 1, 1);
146 mix_order_identity.AppendTranslate(0, 0, 0);
148 TransformOperations mix_order_one;
149 mix_order_one.AppendTranslate(0, 1, 0);
150 mix_order_one.AppendScale(2, 1, 3);
151 mix_order_one.AppendTranslate(1, 0, 0);
153 TransformOperations mix_order_two;
154 mix_order_two.AppendTranslate(0, 1, 0);
155 mix_order_two.AppendTranslate(1, 0, 0);
156 mix_order_two.AppendScale(2, 1, 3);
158 EXPECT_TRUE(mix_order_identity.MatchesTypes(mix_order_one));
159 EXPECT_FALSE(mix_order_identity.MatchesTypes(mix_order_two));
160 EXPECT_FALSE(mix_order_one.MatchesTypes(mix_order_two));
163 TEST(TransformOperationTest, NoneAlwaysMatches) {
164 ScopedVector<TransformOperations> operations;
165 GetIdentityOperations(&operations);
167 TransformOperations none_operation;
168 for (size_t i = 0; i < operations.size(); ++i)
169 EXPECT_TRUE(operations[i]->MatchesTypes(none_operation));
172 TEST(TransformOperationTest, ApplyTranslate) {
173 SkMScalar x = 1;
174 SkMScalar y = 2;
175 SkMScalar z = 3;
176 TransformOperations operations;
177 operations.AppendTranslate(x, y, z);
178 gfx::Transform expected;
179 expected.Translate3d(x, y, z);
180 EXPECT_TRANSFORMATION_MATRIX_EQ(expected, operations.Apply());
183 TEST(TransformOperationTest, ApplyRotate) {
184 SkMScalar x = 1;
185 SkMScalar y = 2;
186 SkMScalar z = 3;
187 SkMScalar degrees = 80;
188 TransformOperations operations;
189 operations.AppendRotate(x, y, z, degrees);
190 gfx::Transform expected;
191 expected.RotateAbout(gfx::Vector3dF(x, y, z), degrees);
192 EXPECT_TRANSFORMATION_MATRIX_EQ(expected, operations.Apply());
195 TEST(TransformOperationTest, ApplyScale) {
196 SkMScalar x = 1;
197 SkMScalar y = 2;
198 SkMScalar z = 3;
199 TransformOperations operations;
200 operations.AppendScale(x, y, z);
201 gfx::Transform expected;
202 expected.Scale3d(x, y, z);
203 EXPECT_TRANSFORMATION_MATRIX_EQ(expected, operations.Apply());
206 TEST(TransformOperationTest, ApplySkew) {
207 SkMScalar x = 1;
208 SkMScalar y = 2;
209 TransformOperations operations;
210 operations.AppendSkew(x, y);
211 gfx::Transform expected;
212 expected.Skew(x, y);
213 EXPECT_TRANSFORMATION_MATRIX_EQ(expected, operations.Apply());
216 TEST(TransformOperationTest, ApplyPerspective) {
217 SkMScalar depth = 800;
218 TransformOperations operations;
219 operations.AppendPerspective(depth);
220 gfx::Transform expected;
221 expected.ApplyPerspectiveDepth(depth);
222 EXPECT_TRANSFORMATION_MATRIX_EQ(expected, operations.Apply());
225 TEST(TransformOperationTest, ApplyMatrix) {
226 SkMScalar dx = 1;
227 SkMScalar dy = 2;
228 SkMScalar dz = 3;
229 gfx::Transform expected_matrix;
230 expected_matrix.Translate3d(dx, dy, dz);
231 TransformOperations matrix_transform;
232 matrix_transform.AppendMatrix(expected_matrix);
233 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_matrix, matrix_transform.Apply());
236 TEST(TransformOperationTest, ApplyOrder) {
237 SkMScalar sx = 2;
238 SkMScalar sy = 4;
239 SkMScalar sz = 8;
241 SkMScalar dx = 1;
242 SkMScalar dy = 2;
243 SkMScalar dz = 3;
245 TransformOperations operations;
246 operations.AppendScale(sx, sy, sz);
247 operations.AppendTranslate(dx, dy, dz);
249 gfx::Transform expected_scale_matrix;
250 expected_scale_matrix.Scale3d(sx, sy, sz);
252 gfx::Transform expected_translate_matrix;
253 expected_translate_matrix.Translate3d(dx, dy, dz);
255 gfx::Transform expected_combined_matrix = expected_scale_matrix;
256 expected_combined_matrix.PreconcatTransform(expected_translate_matrix);
258 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_combined_matrix, operations.Apply());
261 TEST(TransformOperationTest, BlendOrder) {
262 SkMScalar sx1 = 2;
263 SkMScalar sy1 = 4;
264 SkMScalar sz1 = 8;
266 SkMScalar dx1 = 1;
267 SkMScalar dy1 = 2;
268 SkMScalar dz1 = 3;
270 SkMScalar sx2 = 4;
271 SkMScalar sy2 = 8;
272 SkMScalar sz2 = 16;
274 SkMScalar dx2 = 10;
275 SkMScalar dy2 = 20;
276 SkMScalar dz2 = 30;
278 TransformOperations operations_from;
279 operations_from.AppendScale(sx1, sy1, sz1);
280 operations_from.AppendTranslate(dx1, dy1, dz1);
282 TransformOperations operations_to;
283 operations_to.AppendScale(sx2, sy2, sz2);
284 operations_to.AppendTranslate(dx2, dy2, dz2);
286 gfx::Transform scale_from;
287 scale_from.Scale3d(sx1, sy1, sz1);
288 gfx::Transform translate_from;
289 translate_from.Translate3d(dx1, dy1, dz1);
291 gfx::Transform scale_to;
292 scale_to.Scale3d(sx2, sy2, sz2);
293 gfx::Transform translate_to;
294 translate_to.Translate3d(dx2, dy2, dz2);
296 SkMScalar progress = 0.25f;
298 gfx::Transform blended_scale = scale_to;
299 blended_scale.Blend(scale_from, progress);
301 gfx::Transform blended_translate = translate_to;
302 blended_translate.Blend(translate_from, progress);
304 gfx::Transform expected = blended_scale;
305 expected.PreconcatTransform(blended_translate);
307 EXPECT_TRANSFORMATION_MATRIX_EQ(
308 expected, operations_to.Blend(operations_from, progress));
311 static void CheckProgress(SkMScalar progress,
312 const gfx::Transform& from_matrix,
313 const gfx::Transform& to_matrix,
314 const TransformOperations& from_transform,
315 const TransformOperations& to_transform) {
316 gfx::Transform expected_matrix = to_matrix;
317 expected_matrix.Blend(from_matrix, progress);
318 EXPECT_TRANSFORMATION_MATRIX_EQ(
319 expected_matrix, to_transform.Blend(from_transform, progress));
322 TEST(TransformOperationTest, BlendProgress) {
323 SkMScalar sx = 2;
324 SkMScalar sy = 4;
325 SkMScalar sz = 8;
326 TransformOperations operations_from;
327 operations_from.AppendScale(sx, sy, sz);
329 gfx::Transform matrix_from;
330 matrix_from.Scale3d(sx, sy, sz);
332 sx = 4;
333 sy = 8;
334 sz = 16;
335 TransformOperations operations_to;
336 operations_to.AppendScale(sx, sy, sz);
338 gfx::Transform matrix_to;
339 matrix_to.Scale3d(sx, sy, sz);
341 CheckProgress(-1, matrix_from, matrix_to, operations_from, operations_to);
342 CheckProgress(0, matrix_from, matrix_to, operations_from, operations_to);
343 CheckProgress(0.25f, matrix_from, matrix_to, operations_from, operations_to);
344 CheckProgress(0.5f, matrix_from, matrix_to, operations_from, operations_to);
345 CheckProgress(1, matrix_from, matrix_to, operations_from, operations_to);
346 CheckProgress(2, matrix_from, matrix_to, operations_from, operations_to);
349 TEST(TransformOperationTest, BlendWhenTypesDoNotMatch) {
350 SkMScalar sx1 = 2;
351 SkMScalar sy1 = 4;
352 SkMScalar sz1 = 8;
354 SkMScalar dx1 = 1;
355 SkMScalar dy1 = 2;
356 SkMScalar dz1 = 3;
358 SkMScalar sx2 = 4;
359 SkMScalar sy2 = 8;
360 SkMScalar sz2 = 16;
362 SkMScalar dx2 = 10;
363 SkMScalar dy2 = 20;
364 SkMScalar dz2 = 30;
366 TransformOperations operations_from;
367 operations_from.AppendScale(sx1, sy1, sz1);
368 operations_from.AppendTranslate(dx1, dy1, dz1);
370 TransformOperations operations_to;
371 operations_to.AppendTranslate(dx2, dy2, dz2);
372 operations_to.AppendScale(sx2, sy2, sz2);
374 gfx::Transform from;
375 from.Scale3d(sx1, sy1, sz1);
376 from.Translate3d(dx1, dy1, dz1);
378 gfx::Transform to;
379 to.Translate3d(dx2, dy2, dz2);
380 to.Scale3d(sx2, sy2, sz2);
382 SkMScalar progress = 0.25f;
384 gfx::Transform expected = to;
385 expected.Blend(from, progress);
387 EXPECT_TRANSFORMATION_MATRIX_EQ(
388 expected, operations_to.Blend(operations_from, progress));
391 TEST(TransformOperationTest, LargeRotationsWithSameAxis) {
392 TransformOperations operations_from;
393 operations_from.AppendRotate(0, 0, 1, 0);
395 TransformOperations operations_to;
396 operations_to.AppendRotate(0, 0, 2, 360);
398 SkMScalar progress = 0.5f;
400 gfx::Transform expected;
401 expected.RotateAbout(gfx::Vector3dF(0, 0, 1), 180);
403 EXPECT_TRANSFORMATION_MATRIX_EQ(
404 expected, operations_to.Blend(operations_from, progress));
407 TEST(TransformOperationTest, LargeRotationsWithSameAxisInDifferentDirection) {
408 TransformOperations operations_from;
409 operations_from.AppendRotate(0, 0, 1, 180);
411 TransformOperations operations_to;
412 operations_to.AppendRotate(0, 0, -1, 180);
414 SkMScalar progress = 0.5f;
416 gfx::Transform expected;
418 EXPECT_TRANSFORMATION_MATRIX_EQ(
419 expected, operations_to.Blend(operations_from, progress));
422 TEST(TransformOperationTest, LargeRotationsWithDifferentAxes) {
423 TransformOperations operations_from;
424 operations_from.AppendRotate(0, 0, 1, 175);
426 TransformOperations operations_to;
427 operations_to.AppendRotate(0, 1, 0, 175);
429 SkMScalar progress = 0.5f;
430 gfx::Transform matrix_from;
431 matrix_from.RotateAbout(gfx::Vector3dF(0, 0, 1), 175);
433 gfx::Transform matrix_to;
434 matrix_to.RotateAbout(gfx::Vector3dF(0, 1, 0), 175);
436 gfx::Transform expected = matrix_to;
437 expected.Blend(matrix_from, progress);
439 EXPECT_TRANSFORMATION_MATRIX_EQ(
440 expected, operations_to.Blend(operations_from, progress));
443 TEST(TransformOperationTest, RotationFromZeroDegDifferentAxes) {
444 TransformOperations operations_from;
445 operations_from.AppendRotate(0, 0, 1, 0);
447 TransformOperations operations_to;
448 operations_to.AppendRotate(0, 1, 0, 450);
450 SkMScalar progress = 0.5f;
451 gfx::Transform expected;
452 expected.RotateAbout(gfx::Vector3dF(0, 1, 0), 225);
453 EXPECT_TRANSFORMATION_MATRIX_EQ(
454 expected, operations_to.Blend(operations_from, progress));
457 TEST(TransformOperationTest, RotationFromZeroDegSameAxes) {
458 TransformOperations operations_from;
459 operations_from.AppendRotate(0, 0, 1, 0);
461 TransformOperations operations_to;
462 operations_to.AppendRotate(0, 0, 1, 450);
464 SkMScalar progress = 0.5f;
465 gfx::Transform expected;
466 expected.RotateAbout(gfx::Vector3dF(0, 0, 1), 225);
467 EXPECT_TRANSFORMATION_MATRIX_EQ(
468 expected, operations_to.Blend(operations_from, progress));
471 TEST(TransformOperationTest, RotationToZeroDegDifferentAxes) {
472 TransformOperations operations_from;
473 operations_from.AppendRotate(0, 1, 0, 450);
475 TransformOperations operations_to;
476 operations_to.AppendRotate(0, 0, 1, 0);
478 SkMScalar progress = 0.5f;
479 gfx::Transform expected;
480 expected.RotateAbout(gfx::Vector3dF(0, 1, 0), 225);
481 EXPECT_TRANSFORMATION_MATRIX_EQ(
482 expected, operations_to.Blend(operations_from, progress));
485 TEST(TransformOperationTest, RotationToZeroDegSameAxes) {
486 TransformOperations operations_from;
487 operations_from.AppendRotate(0, 0, 1, 450);
489 TransformOperations operations_to;
490 operations_to.AppendRotate(0, 0, 1, 0);
492 SkMScalar progress = 0.5f;
493 gfx::Transform expected;
494 expected.RotateAbout(gfx::Vector3dF(0, 0, 1), 225);
495 EXPECT_TRANSFORMATION_MATRIX_EQ(
496 expected, operations_to.Blend(operations_from, progress));
499 TEST(TransformOperationTest, BlendRotationFromIdentity) {
500 ScopedVector<TransformOperations> identity_operations;
501 GetIdentityOperations(&identity_operations);
503 for (size_t i = 0; i < identity_operations.size(); ++i) {
504 TransformOperations operations;
505 operations.AppendRotate(0, 0, 1, 90);
507 SkMScalar progress = 0.5f;
509 gfx::Transform expected;
510 expected.RotateAbout(gfx::Vector3dF(0, 0, 1), 45);
512 EXPECT_TRANSFORMATION_MATRIX_EQ(
513 expected, operations.Blend(*identity_operations[i], progress));
515 progress = -0.5f;
517 expected.MakeIdentity();
518 expected.RotateAbout(gfx::Vector3dF(0, 0, 1), -45);
520 EXPECT_TRANSFORMATION_MATRIX_EQ(
521 expected, operations.Blend(*identity_operations[i], progress));
523 progress = 1.5f;
525 expected.MakeIdentity();
526 expected.RotateAbout(gfx::Vector3dF(0, 0, 1), 135);
528 EXPECT_TRANSFORMATION_MATRIX_EQ(
529 expected, operations.Blend(*identity_operations[i], progress));
533 TEST(TransformOperationTest, BlendTranslationFromIdentity) {
534 ScopedVector<TransformOperations> identity_operations;
535 GetIdentityOperations(&identity_operations);
537 for (size_t i = 0; i < identity_operations.size(); ++i) {
538 TransformOperations operations;
539 operations.AppendTranslate(2, 2, 2);
541 SkMScalar progress = 0.5f;
543 gfx::Transform expected;
544 expected.Translate3d(1, 1, 1);
546 EXPECT_TRANSFORMATION_MATRIX_EQ(
547 expected, operations.Blend(*identity_operations[i], progress));
549 progress = -0.5f;
551 expected.MakeIdentity();
552 expected.Translate3d(-1, -1, -1);
554 EXPECT_TRANSFORMATION_MATRIX_EQ(
555 expected, operations.Blend(*identity_operations[i], progress));
557 progress = 1.5f;
559 expected.MakeIdentity();
560 expected.Translate3d(3, 3, 3);
562 EXPECT_TRANSFORMATION_MATRIX_EQ(
563 expected, operations.Blend(*identity_operations[i], progress));
567 TEST(TransformOperationTest, BlendScaleFromIdentity) {
568 ScopedVector<TransformOperations> identity_operations;
569 GetIdentityOperations(&identity_operations);
571 for (size_t i = 0; i < identity_operations.size(); ++i) {
572 TransformOperations operations;
573 operations.AppendScale(3, 3, 3);
575 SkMScalar progress = 0.5f;
577 gfx::Transform expected;
578 expected.Scale3d(2, 2, 2);
580 EXPECT_TRANSFORMATION_MATRIX_EQ(
581 expected, operations.Blend(*identity_operations[i], progress));
583 progress = -0.5f;
585 expected.MakeIdentity();
586 expected.Scale3d(0, 0, 0);
588 EXPECT_TRANSFORMATION_MATRIX_EQ(
589 expected, operations.Blend(*identity_operations[i], progress));
591 progress = 1.5f;
593 expected.MakeIdentity();
594 expected.Scale3d(4, 4, 4);
596 EXPECT_TRANSFORMATION_MATRIX_EQ(
597 expected, operations.Blend(*identity_operations[i], progress));
601 TEST(TransformOperationTest, BlendSkewFromEmpty) {
602 TransformOperations empty_operation;
604 TransformOperations operations;
605 operations.AppendSkew(2, 2);
607 SkMScalar progress = 0.5f;
609 gfx::Transform expected;
610 expected.Skew(1, 1);
612 EXPECT_TRANSFORMATION_MATRIX_EQ(expected,
613 operations.Blend(empty_operation, progress));
615 progress = -0.5f;
617 expected.MakeIdentity();
618 expected.Skew(-1, -1);
620 EXPECT_TRANSFORMATION_MATRIX_EQ(expected,
621 operations.Blend(empty_operation, progress));
623 progress = 1.5f;
625 expected.MakeIdentity();
626 expected.Skew(3, 3);
628 EXPECT_TRANSFORMATION_MATRIX_EQ(expected,
629 operations.Blend(empty_operation, progress));
632 TEST(TransformOperationTest, BlendPerspectiveFromIdentity) {
633 ScopedVector<TransformOperations> identity_operations;
634 GetIdentityOperations(&identity_operations);
636 for (size_t i = 0; i < identity_operations.size(); ++i) {
637 TransformOperations operations;
638 operations.AppendPerspective(1000);
640 SkMScalar progress = 0.5f;
642 gfx::Transform expected;
643 expected.ApplyPerspectiveDepth(2000);
645 EXPECT_TRANSFORMATION_MATRIX_EQ(
646 expected, operations.Blend(*identity_operations[i], progress));
650 TEST(TransformOperationTest, BlendRotationToIdentity) {
651 ScopedVector<TransformOperations> identity_operations;
652 GetIdentityOperations(&identity_operations);
654 for (size_t i = 0; i < identity_operations.size(); ++i) {
655 TransformOperations operations;
656 operations.AppendRotate(0, 0, 1, 90);
658 SkMScalar progress = 0.5f;
660 gfx::Transform expected;
661 expected.RotateAbout(gfx::Vector3dF(0, 0, 1), 45);
663 EXPECT_TRANSFORMATION_MATRIX_EQ(
664 expected, identity_operations[i]->Blend(operations, progress));
668 TEST(TransformOperationTest, BlendTranslationToIdentity) {
669 ScopedVector<TransformOperations> identity_operations;
670 GetIdentityOperations(&identity_operations);
672 for (size_t i = 0; i < identity_operations.size(); ++i) {
673 TransformOperations operations;
674 operations.AppendTranslate(2, 2, 2);
676 SkMScalar progress = 0.5f;
678 gfx::Transform expected;
679 expected.Translate3d(1, 1, 1);
681 EXPECT_TRANSFORMATION_MATRIX_EQ(
682 expected, identity_operations[i]->Blend(operations, progress));
686 TEST(TransformOperationTest, BlendScaleToIdentity) {
687 ScopedVector<TransformOperations> identity_operations;
688 GetIdentityOperations(&identity_operations);
690 for (size_t i = 0; i < identity_operations.size(); ++i) {
691 TransformOperations operations;
692 operations.AppendScale(3, 3, 3);
694 SkMScalar progress = 0.5f;
696 gfx::Transform expected;
697 expected.Scale3d(2, 2, 2);
699 EXPECT_TRANSFORMATION_MATRIX_EQ(
700 expected, identity_operations[i]->Blend(operations, progress));
704 TEST(TransformOperationTest, BlendSkewToEmpty) {
705 TransformOperations empty_operation;
707 TransformOperations operations;
708 operations.AppendSkew(2, 2);
710 SkMScalar progress = 0.5f;
712 gfx::Transform expected;
713 expected.Skew(1, 1);
715 EXPECT_TRANSFORMATION_MATRIX_EQ(expected,
716 empty_operation.Blend(operations, progress));
719 TEST(TransformOperationTest, BlendPerspectiveToIdentity) {
720 ScopedVector<TransformOperations> identity_operations;
721 GetIdentityOperations(&identity_operations);
723 for (size_t i = 0; i < identity_operations.size(); ++i) {
724 TransformOperations operations;
725 operations.AppendPerspective(1000);
727 SkMScalar progress = 0.5f;
729 gfx::Transform expected;
730 expected.ApplyPerspectiveDepth(2000);
732 EXPECT_TRANSFORMATION_MATRIX_EQ(
733 expected, identity_operations[i]->Blend(operations, progress));
737 TEST(TransformOperationTest, ExtrapolatePerspectiveBlending) {
738 TransformOperations operations1;
739 operations1.AppendPerspective(1000);
741 TransformOperations operations2;
742 operations2.AppendPerspective(500);
744 gfx::Transform expected;
745 expected.ApplyPerspectiveDepth(400);
747 EXPECT_TRANSFORMATION_MATRIX_EQ(
748 expected, operations1.Blend(operations2, -0.5));
750 expected.MakeIdentity();
751 expected.ApplyPerspectiveDepth(2000);
753 EXPECT_TRANSFORMATION_MATRIX_EQ(
754 expected, operations1.Blend(operations2, 1.5));
757 TEST(TransformOperationTest, ExtrapolateMatrixBlending) {
758 gfx::Transform transform1;
759 transform1.Translate3d(1, 1, 1);
760 TransformOperations operations1;
761 operations1.AppendMatrix(transform1);
763 gfx::Transform transform2;
764 transform2.Translate3d(3, 3, 3);
765 TransformOperations operations2;
766 operations2.AppendMatrix(transform2);
768 gfx::Transform expected;
769 EXPECT_TRANSFORMATION_MATRIX_EQ(
770 expected, operations1.Blend(operations2, 1.5));
772 expected.Translate3d(4, 4, 4);
773 EXPECT_TRANSFORMATION_MATRIX_EQ(
774 expected, operations1.Blend(operations2, -0.5));
777 TEST(TransformOperationTest, BlendedBoundsWhenTypesDoNotMatch) {
778 TransformOperations operations_from;
779 operations_from.AppendScale(2.0, 4.0, 8.0);
780 operations_from.AppendTranslate(1.0, 2.0, 3.0);
782 TransformOperations operations_to;
783 operations_to.AppendTranslate(10.0, 20.0, 30.0);
784 operations_to.AppendScale(4.0, 8.0, 16.0);
786 gfx::BoxF box(1.f, 1.f, 1.f);
787 gfx::BoxF bounds;
789 SkMScalar min_progress = 0.f;
790 SkMScalar max_progress = 1.f;
792 EXPECT_FALSE(operations_to.BlendedBoundsForBox(
793 box, operations_from, min_progress, max_progress, &bounds));
796 TEST(TransformOperationTest, BlendedBoundsForIdentity) {
797 TransformOperations operations_from;
798 operations_from.AppendIdentity();
799 TransformOperations operations_to;
800 operations_to.AppendIdentity();
802 gfx::BoxF box(1.f, 2.f, 3.f);
803 gfx::BoxF bounds;
805 SkMScalar min_progress = 0.f;
806 SkMScalar max_progress = 1.f;
808 EXPECT_TRUE(operations_to.BlendedBoundsForBox(
809 box, operations_from, min_progress, max_progress, &bounds));
810 EXPECT_EQ(box.ToString(), bounds.ToString());
813 TEST(TransformOperationTest, BlendedBoundsForTranslate) {
814 TransformOperations operations_from;
815 operations_from.AppendTranslate(3.0, -4.0, 2.0);
816 TransformOperations operations_to;
817 operations_to.AppendTranslate(7.0, 4.0, -2.0);
819 gfx::BoxF box(1.f, 2.f, 3.f, 4.f, 4.f, 4.f);
820 gfx::BoxF bounds;
822 SkMScalar min_progress = -0.5f;
823 SkMScalar max_progress = 1.5f;
824 EXPECT_TRUE(operations_to.BlendedBoundsForBox(
825 box, operations_from, min_progress, max_progress, &bounds));
826 EXPECT_EQ(gfx::BoxF(2.f, -6.f, -1.f, 12.f, 20.f, 12.f).ToString(),
827 bounds.ToString());
829 min_progress = 0.f;
830 max_progress = 1.f;
831 EXPECT_TRUE(operations_to.BlendedBoundsForBox(
832 box, operations_from, min_progress, max_progress, &bounds));
833 EXPECT_EQ(gfx::BoxF(4.f, -2.f, 1.f, 8.f, 12.f, 8.f).ToString(),
834 bounds.ToString());
836 TransformOperations identity;
837 EXPECT_TRUE(operations_to.BlendedBoundsForBox(
838 box, identity, min_progress, max_progress, &bounds));
839 EXPECT_EQ(gfx::BoxF(1.f, 2.f, 1.f, 11.f, 8.f, 6.f).ToString(),
840 bounds.ToString());
842 EXPECT_TRUE(identity.BlendedBoundsForBox(
843 box, operations_from, min_progress, max_progress, &bounds));
844 EXPECT_EQ(gfx::BoxF(1.f, -2.f, 3.f, 7.f, 8.f, 6.f).ToString(),
845 bounds.ToString());
848 TEST(TransformOperationTest, BlendedBoundsForScale) {
849 TransformOperations operations_from;
850 operations_from.AppendScale(3.0, 0.5, 2.0);
851 TransformOperations operations_to;
852 operations_to.AppendScale(7.0, 4.0, -2.0);
854 gfx::BoxF box(1.f, 2.f, 3.f, 4.f, 4.f, 4.f);
855 gfx::BoxF bounds;
857 SkMScalar min_progress = -0.5f;
858 SkMScalar max_progress = 1.5f;
859 EXPECT_TRUE(operations_to.BlendedBoundsForBox(
860 box, operations_from, min_progress, max_progress, &bounds));
861 EXPECT_EQ(gfx::BoxF(1.f, -7.5f, -28.f, 44.f, 42.f, 56.f).ToString(),
862 bounds.ToString());
864 min_progress = 0.f;
865 max_progress = 1.f;
866 EXPECT_TRUE(operations_to.BlendedBoundsForBox(
867 box, operations_from, min_progress, max_progress, &bounds));
868 EXPECT_EQ(gfx::BoxF(3.f, 1.f, -14.f, 32.f, 23.f, 28.f).ToString(),
869 bounds.ToString());
871 TransformOperations identity;
872 EXPECT_TRUE(operations_to.BlendedBoundsForBox(
873 box, identity, min_progress, max_progress, &bounds));
874 EXPECT_EQ(gfx::BoxF(1.f, 2.f, -14.f, 34.f, 22.f, 21.f).ToString(),
875 bounds.ToString());
877 EXPECT_TRUE(identity.BlendedBoundsForBox(
878 box, operations_from, min_progress, max_progress, &bounds));
879 EXPECT_EQ(gfx::BoxF(1.f, 1.f, 3.f, 14.f, 5.f, 11.f).ToString(),
880 bounds.ToString());
883 TEST(TransformOperationTest, BlendedBoundsWithZeroScale) {
884 TransformOperations zero_scale;
885 zero_scale.AppendScale(0.0, 0.0, 0.0);
886 TransformOperations non_zero_scale;
887 non_zero_scale.AppendScale(2.0, -4.0, 5.0);
889 gfx::BoxF box(1.f, 2.f, 3.f, 4.f, 4.f, 4.f);
890 gfx::BoxF bounds;
892 SkMScalar min_progress = 0.f;
893 SkMScalar max_progress = 1.f;
894 EXPECT_TRUE(zero_scale.BlendedBoundsForBox(
895 box, non_zero_scale, min_progress, max_progress, &bounds));
896 EXPECT_EQ(gfx::BoxF(0.f, -24.f, 0.f, 10.f, 24.f, 35.f).ToString(),
897 bounds.ToString());
899 EXPECT_TRUE(non_zero_scale.BlendedBoundsForBox(
900 box, zero_scale, min_progress, max_progress, &bounds));
901 EXPECT_EQ(gfx::BoxF(0.f, -24.f, 0.f, 10.f, 24.f, 35.f).ToString(),
902 bounds.ToString());
904 EXPECT_TRUE(zero_scale.BlendedBoundsForBox(
905 box, zero_scale, min_progress, max_progress, &bounds));
906 EXPECT_EQ(gfx::BoxF().ToString(), bounds.ToString());
909 TEST(TransformOperationTest, BlendedBoundsForRotationTrivial) {
910 TransformOperations operations_from;
911 operations_from.AppendRotate(0.f, 0.f, 1.f, 0.f);
912 TransformOperations operations_to;
913 operations_to.AppendRotate(0.f, 0.f, 1.f, 360.f);
915 float sqrt_2 = sqrt(2.f);
916 gfx::BoxF box(
917 -sqrt_2, -sqrt_2, 0.f, sqrt_2, sqrt_2, 0.f);
918 gfx::BoxF bounds;
920 // Since we're rotating 360 degrees, any box with dimensions between 0 and
921 // 2 * sqrt(2) should give the same result.
922 float sizes[] = { 0.f, 0.1f, sqrt_2, 2.f * sqrt_2 };
923 for (size_t i = 0; i < arraysize(sizes); ++i) {
924 box.set_size(sizes[i], sizes[i], 0.f);
925 SkMScalar min_progress = 0.f;
926 SkMScalar max_progress = 1.f;
927 EXPECT_TRUE(operations_to.BlendedBoundsForBox(
928 box, operations_from, min_progress, max_progress, &bounds));
929 EXPECT_EQ(gfx::BoxF(-2.f, -2.f, 0.f, 4.f, 4.f, 0.f).ToString(),
930 bounds.ToString());
934 TEST(TransformOperationTest, BlendedBoundsForRotationAllExtrema) {
935 // If the normal is out of the plane, we can have up to 6 extrema (a min/max
936 // in each dimension) between the endpoints of the arc. This test ensures that
937 // we consider all 6.
938 TransformOperations operations_from;
939 operations_from.AppendRotate(1.f, 1.f, 1.f, 30.f);
940 TransformOperations operations_to;
941 operations_to.AppendRotate(1.f, 1.f, 1.f, 390.f);
943 gfx::BoxF box(1.f, 0.f, 0.f, 0.f, 0.f, 0.f);
944 gfx::BoxF bounds;
946 float min = -1.f / 3.f;
947 float max = 1.f;
948 float size = max - min;
949 EXPECT_TRUE(operations_to.BlendedBoundsForBox(
950 box, operations_from, 0.f, 1.f, &bounds));
951 EXPECT_EQ(gfx::BoxF(min, min, min, size, size, size).ToString(),
952 bounds.ToString());
955 TEST(TransformOperationTest, BlendedBoundsForRotationDifferentAxes) {
956 // We can handle rotations about a single axis. If the axes are different,
957 // we revert to matrix interpolation for which inflated bounds cannot be
958 // computed.
959 TransformOperations operations_from;
960 operations_from.AppendRotate(1.f, 1.f, 1.f, 30.f);
961 TransformOperations operations_to_same;
962 operations_to_same.AppendRotate(1.f, 1.f, 1.f, 390.f);
963 TransformOperations operations_to_opposite;
964 operations_to_opposite.AppendRotate(-1.f, -1.f, -1.f, 390.f);
965 TransformOperations operations_to_different;
966 operations_to_different.AppendRotate(1.f, 3.f, 1.f, 390.f);
968 gfx::BoxF box(1.f, 0.f, 0.f, 0.f, 0.f, 0.f);
969 gfx::BoxF bounds;
971 EXPECT_TRUE(operations_to_same.BlendedBoundsForBox(
972 box, operations_from, 0.f, 1.f, &bounds));
973 EXPECT_TRUE(operations_to_opposite.BlendedBoundsForBox(
974 box, operations_from, 0.f, 1.f, &bounds));
975 EXPECT_FALSE(operations_to_different.BlendedBoundsForBox(
976 box, operations_from, 0.f, 1.f, &bounds));
979 TEST(TransformOperationTest, BlendedBoundsForRotationPointOnAxis) {
980 // Checks that if the point to rotate is sitting on the axis of rotation, that
981 // it does not get affected.
982 TransformOperations operations_from;
983 operations_from.AppendRotate(1.f, 1.f, 1.f, 30.f);
984 TransformOperations operations_to;
985 operations_to.AppendRotate(1.f, 1.f, 1.f, 390.f);
987 gfx::BoxF box(1.f, 1.f, 1.f, 0.f, 0.f, 0.f);
988 gfx::BoxF bounds;
990 EXPECT_TRUE(operations_to.BlendedBoundsForBox(
991 box, operations_from, 0.f, 1.f, &bounds));
992 EXPECT_EQ(box.ToString(), bounds.ToString());
995 TEST(TransformOperationTest, BlendedBoundsForRotationProblematicAxes) {
996 // Zeros in the components of the axis of rotation turned out to be tricky to
997 // deal with in practice. This function tests some potentially problematic
998 // axes to ensure sane behavior.
1000 // Some common values used in the expected boxes.
1001 float dim1 = 0.292893f;
1002 float dim2 = sqrt(2.f);
1003 float dim3 = 2.f * dim2;
1005 struct {
1006 float x;
1007 float y;
1008 float z;
1009 gfx::BoxF expected;
1010 } tests[] = {{0.f, 0.f, 0.f, gfx::BoxF(1.f, 1.f, 1.f, 0.f, 0.f, 0.f)},
1011 {1.f, 0.f, 0.f, gfx::BoxF(1.f, -dim2, -dim2, 0.f, dim3, dim3)},
1012 {0.f, 1.f, 0.f, gfx::BoxF(-dim2, 1.f, -dim2, dim3, 0.f, dim3)},
1013 {0.f, 0.f, 1.f, gfx::BoxF(-dim2, -dim2, 1.f, dim3, dim3, 0.f)},
1014 {1.f, 1.f, 0.f, gfx::BoxF(dim1, dim1, -1.f, dim2, dim2, 2.f)},
1015 {0.f, 1.f, 1.f, gfx::BoxF(-1.f, dim1, dim1, 2.f, dim2, dim2)},
1016 {1.f, 0.f, 1.f, gfx::BoxF(dim1, -1.f, dim1, dim2, 2.f, dim2)}};
1018 for (size_t i = 0; i < arraysize(tests); ++i) {
1019 float x = tests[i].x;
1020 float y = tests[i].y;
1021 float z = tests[i].z;
1022 TransformOperations operations_from;
1023 operations_from.AppendRotate(x, y, z, 0.f);
1024 TransformOperations operations_to;
1025 operations_to.AppendRotate(x, y, z, 360.f);
1026 gfx::BoxF box(1.f, 1.f, 1.f, 0.f, 0.f, 0.f);
1027 gfx::BoxF bounds;
1029 EXPECT_TRUE(operations_to.BlendedBoundsForBox(
1030 box, operations_from, 0.f, 1.f, &bounds));
1031 EXPECT_EQ(tests[i].expected.ToString(), bounds.ToString());
1035 static void ExpectBoxesApproximatelyEqual(const gfx::BoxF& lhs,
1036 const gfx::BoxF& rhs,
1037 float tolerance) {
1038 EXPECT_NEAR(lhs.x(), rhs.x(), tolerance);
1039 EXPECT_NEAR(lhs.y(), rhs.y(), tolerance);
1040 EXPECT_NEAR(lhs.z(), rhs.z(), tolerance);
1041 EXPECT_NEAR(lhs.width(), rhs.width(), tolerance);
1042 EXPECT_NEAR(lhs.height(), rhs.height(), tolerance);
1043 EXPECT_NEAR(lhs.depth(), rhs.depth(), tolerance);
1046 static void EmpiricallyTestBounds(const TransformOperations& from,
1047 const TransformOperations& to,
1048 SkMScalar min_progress,
1049 SkMScalar max_progress,
1050 bool test_containment_only) {
1051 gfx::BoxF box(200.f, 500.f, 100.f, 100.f, 300.f, 200.f);
1052 gfx::BoxF bounds;
1053 EXPECT_TRUE(
1054 to.BlendedBoundsForBox(box, from, min_progress, max_progress, &bounds));
1056 bool first_time = true;
1057 gfx::BoxF empirical_bounds;
1058 static const size_t kNumSteps = 10;
1059 for (size_t step = 0; step < kNumSteps; ++step) {
1060 float t = step / (kNumSteps - 1.f);
1061 t = gfx::Tween::FloatValueBetween(t, min_progress, max_progress);
1062 gfx::Transform partial_transform = to.Blend(from, t);
1063 gfx::BoxF transformed = box;
1064 partial_transform.TransformBox(&transformed);
1066 if (first_time) {
1067 empirical_bounds = transformed;
1068 first_time = false;
1069 } else {
1070 empirical_bounds.Union(transformed);
1074 if (test_containment_only) {
1075 gfx::BoxF unified_bounds = bounds;
1076 unified_bounds.Union(empirical_bounds);
1077 // Convert to the screen space rects these boxes represent.
1078 gfx::Rect bounds_rect = ToEnclosingRect(
1079 gfx::RectF(bounds.x(), bounds.y(), bounds.width(), bounds.height()));
1080 gfx::Rect unified_bounds_rect =
1081 ToEnclosingRect(gfx::RectF(unified_bounds.x(),
1082 unified_bounds.y(),
1083 unified_bounds.width(),
1084 unified_bounds.height()));
1085 EXPECT_EQ(bounds_rect.ToString(), unified_bounds_rect.ToString());
1086 } else {
1087 // Our empirical estimate will be a little rough since we're only doing
1088 // 100 samples.
1089 static const float kTolerance = 1e-2f;
1090 ExpectBoxesApproximatelyEqual(empirical_bounds, bounds, kTolerance);
1094 static void EmpiricallyTestBoundsEquality(const TransformOperations& from,
1095 const TransformOperations& to,
1096 SkMScalar min_progress,
1097 SkMScalar max_progress) {
1098 EmpiricallyTestBounds(from, to, min_progress, max_progress, false);
1101 static void EmpiricallyTestBoundsContainment(const TransformOperations& from,
1102 const TransformOperations& to,
1103 SkMScalar min_progress,
1104 SkMScalar max_progress) {
1105 EmpiricallyTestBounds(from, to, min_progress, max_progress, true);
1108 TEST(TransformOperationTest, BlendedBoundsForRotationEmpiricalTests) {
1109 // Sets up various axis angle combinations, computes the bounding box and
1110 // empirically tests that the transformed bounds are indeed contained by the
1111 // computed bounding box.
1113 struct {
1114 float x;
1115 float y;
1116 float z;
1117 } axes[] = {{1.f, 1.f, 1.f},
1118 {-1.f, -1.f, -1.f},
1119 {-1.f, 2.f, 3.f},
1120 {1.f, -2.f, 3.f},
1121 {1.f, 2.f, -3.f},
1122 {0.f, 0.f, 0.f},
1123 {1.f, 0.f, 0.f},
1124 {0.f, 1.f, 0.f},
1125 {0.f, 0.f, 1.f},
1126 {1.f, 1.f, 0.f},
1127 {0.f, 1.f, 1.f},
1128 {1.f, 0.f, 1.f},
1129 {-1.f, 0.f, 0.f},
1130 {0.f, -1.f, 0.f},
1131 {0.f, 0.f, -1.f},
1132 {-1.f, -1.f, 0.f},
1133 {0.f, -1.f, -1.f},
1134 {-1.f, 0.f, -1.f}};
1136 struct {
1137 float theta_from;
1138 float theta_to;
1139 } angles[] = {{5.f, 10.f},
1140 {10.f, 5.f},
1141 {0.f, 360.f},
1142 {20.f, 180.f},
1143 {-20.f, -180.f},
1144 {180.f, -220.f},
1145 {220.f, 320.f}};
1147 // We can go beyond the range [0, 1] (the bezier might slide out of this range
1148 // at either end), but since the first and last knots are at (0, 0) and (1, 1)
1149 // we will never go within it, so these tests are sufficient.
1150 struct {
1151 float min_progress;
1152 float max_progress;
1153 } progress[] = {
1154 {0.f, 1.f}, {-.25f, 1.25f},
1157 for (size_t i = 0; i < arraysize(axes); ++i) {
1158 for (size_t j = 0; j < arraysize(angles); ++j) {
1159 for (size_t k = 0; k < arraysize(progress); ++k) {
1160 float x = axes[i].x;
1161 float y = axes[i].y;
1162 float z = axes[i].z;
1163 TransformOperations operations_from;
1164 operations_from.AppendRotate(x, y, z, angles[j].theta_from);
1165 TransformOperations operations_to;
1166 operations_to.AppendRotate(x, y, z, angles[j].theta_to);
1167 EmpiricallyTestBoundsContainment(operations_from,
1168 operations_to,
1169 progress[k].min_progress,
1170 progress[k].max_progress);
1176 TEST(TransformOperationTest, PerspectiveMatrixAndTransformBlendingEquivalency) {
1177 TransformOperations from_operations;
1178 from_operations.AppendPerspective(200);
1180 TransformOperations to_operations;
1181 to_operations.AppendPerspective(1000);
1183 gfx::Transform from_transform;
1184 from_transform.ApplyPerspectiveDepth(200);
1186 gfx::Transform to_transform;
1187 to_transform.ApplyPerspectiveDepth(1000);
1189 static const int steps = 20;
1190 for (int i = 0; i < steps; ++i) {
1191 double progress = static_cast<double>(i) / (steps - 1);
1193 gfx::Transform blended_matrix = to_transform;
1194 EXPECT_TRUE(blended_matrix.Blend(from_transform, progress));
1196 gfx::Transform blended_transform =
1197 to_operations.Blend(from_operations, progress);
1199 EXPECT_TRANSFORMATION_MATRIX_EQ(blended_matrix, blended_transform);
1203 TEST(TransformOperationTest, BlendedBoundsForPerspective) {
1204 struct {
1205 float from_depth;
1206 float to_depth;
1207 } perspective_depths[] = {
1208 {600.f, 400.f},
1209 {800.f, 1000.f},
1210 {800.f, std::numeric_limits<float>::infinity()},
1213 struct {
1214 float min_progress;
1215 float max_progress;
1216 } progress[] = {
1217 {0.f, 1.f}, {-0.1f, 1.1f},
1220 for (size_t i = 0; i < arraysize(perspective_depths); ++i) {
1221 for (size_t j = 0; j < arraysize(progress); ++j) {
1222 TransformOperations operations_from;
1223 operations_from.AppendPerspective(perspective_depths[i].from_depth);
1224 TransformOperations operations_to;
1225 operations_to.AppendPerspective(perspective_depths[i].to_depth);
1226 EmpiricallyTestBoundsEquality(operations_from,
1227 operations_to,
1228 progress[j].min_progress,
1229 progress[j].max_progress);
1234 TEST(TransformOperationTest, BlendedBoundsForSkew) {
1235 struct {
1236 float from_x;
1237 float from_y;
1238 float to_x;
1239 float to_y;
1240 } skews[] = {
1241 {1.f, 0.5f, 0.5f, 1.f}, {2.f, 1.f, 0.5f, 0.5f},
1244 struct {
1245 float min_progress;
1246 float max_progress;
1247 } progress[] = {
1248 {0.f, 1.f}, {-0.1f, 1.1f},
1251 for (size_t i = 0; i < arraysize(skews); ++i) {
1252 for (size_t j = 0; j < arraysize(progress); ++j) {
1253 TransformOperations operations_from;
1254 operations_from.AppendSkew(skews[i].from_x, skews[i].from_y);
1255 TransformOperations operations_to;
1256 operations_to.AppendSkew(skews[i].to_x, skews[i].to_y);
1257 EmpiricallyTestBoundsEquality(operations_from,
1258 operations_to,
1259 progress[j].min_progress,
1260 progress[j].max_progress);
1265 TEST(TransformOperationTest, NonCommutativeRotations) {
1266 TransformOperations operations_from;
1267 operations_from.AppendRotate(1.0, 0.0, 0.0, 0.0);
1268 operations_from.AppendRotate(0.0, 1.0, 0.0, 0.0);
1269 TransformOperations operations_to;
1270 operations_to.AppendRotate(1.0, 0.0, 0.0, 45.0);
1271 operations_to.AppendRotate(0.0, 1.0, 0.0, 135.0);
1273 gfx::BoxF box(0, 0, 0, 1, 1, 1);
1274 gfx::BoxF bounds;
1276 SkMScalar min_progress = 0.0f;
1277 SkMScalar max_progress = 1.0f;
1278 EXPECT_TRUE(operations_to.BlendedBoundsForBox(
1279 box, operations_from, min_progress, max_progress, &bounds));
1280 gfx::Transform blended_transform =
1281 operations_to.Blend(operations_from, max_progress);
1282 gfx::Point3F blended_point(0.9f, 0.9f, 0.0f);
1283 blended_transform.TransformPoint(&blended_point);
1284 gfx::BoxF expanded_bounds = bounds;
1285 expanded_bounds.ExpandTo(blended_point);
1286 EXPECT_EQ(bounds.ToString(), expanded_bounds.ToString());
1289 TEST(TransformOperationTest, BlendedBoundsForSequence) {
1290 TransformOperations operations_from;
1291 operations_from.AppendTranslate(1.0, -5.0, 1.0);
1292 operations_from.AppendScale(-1.0, 2.0, 3.0);
1293 operations_from.AppendTranslate(2.0, 4.0, -1.0);
1294 TransformOperations operations_to;
1295 operations_to.AppendTranslate(13.0, -1.0, 5.0);
1296 operations_to.AppendScale(-3.0, -2.0, 5.0);
1297 operations_to.AppendTranslate(6.0, -2.0, 3.0);
1299 gfx::BoxF box(1.f, 2.f, 3.f, 4.f, 4.f, 4.f);
1300 gfx::BoxF bounds;
1302 SkMScalar min_progress = -0.5f;
1303 SkMScalar max_progress = 1.5f;
1304 EXPECT_TRUE(operations_to.BlendedBoundsForBox(
1305 box, operations_from, min_progress, max_progress, &bounds));
1306 EXPECT_EQ(gfx::BoxF(-57.f, -59.f, -1.f, 76.f, 112.f, 80.f).ToString(),
1307 bounds.ToString());
1309 min_progress = 0.f;
1310 max_progress = 1.f;
1311 EXPECT_TRUE(operations_to.BlendedBoundsForBox(
1312 box, operations_from, min_progress, max_progress, &bounds));
1313 EXPECT_EQ(gfx::BoxF(-32.f, -25.f, 7.f, 42.f, 44.f, 48.f).ToString(),
1314 bounds.ToString());
1316 TransformOperations identity;
1317 EXPECT_TRUE(operations_to.BlendedBoundsForBox(
1318 box, identity, min_progress, max_progress, &bounds));
1319 EXPECT_EQ(gfx::BoxF(-33.f, -13.f, 3.f, 57.f, 19.f, 52.f).ToString(),
1320 bounds.ToString());
1322 EXPECT_TRUE(identity.BlendedBoundsForBox(
1323 box, operations_from, min_progress, max_progress, &bounds));
1324 EXPECT_EQ(gfx::BoxF(-7.f, -3.f, 2.f, 15.f, 23.f, 20.f).ToString(),
1325 bounds.ToString());
1328 TEST(TransformOperationTest, AffectsScaleWithSingleOperation) {
1329 TransformOperations empty_operations;
1330 EXPECT_FALSE(empty_operations.AffectsScale());
1332 TransformOperations identity;
1333 identity.AppendIdentity();
1334 EXPECT_FALSE(identity.AffectsScale());
1336 TransformOperations translate;
1337 translate.AppendTranslate(1.f, 2.f, 3.f);
1338 EXPECT_FALSE(translate.AffectsScale());
1340 TransformOperations rotate;
1341 rotate.AppendRotate(1.f, 2.f, 3.f, 4.f);
1342 EXPECT_FALSE(rotate.AffectsScale());
1344 TransformOperations scale;
1345 scale.AppendScale(1.f, 2.f, 3.f);
1346 EXPECT_TRUE(scale.AffectsScale());
1348 TransformOperations skew;
1349 skew.AppendSkew(1.f, 2.f);
1350 EXPECT_FALSE(skew.AffectsScale());
1352 TransformOperations perspective;
1353 perspective.AppendPerspective(1.f);
1354 EXPECT_FALSE(perspective.AffectsScale());
1356 TransformOperations identity_matrix;
1357 identity_matrix.AppendMatrix(gfx::Transform());
1358 EXPECT_FALSE(identity_matrix.AffectsScale());
1360 TransformOperations translation_matrix;
1361 gfx::Transform translation_transform;
1362 translation_transform.Translate3d(1.f, 2.f, 3.f);
1363 translation_matrix.AppendMatrix(translation_transform);
1364 EXPECT_FALSE(translation_matrix.AffectsScale());
1366 TransformOperations scaling_matrix;
1367 gfx::Transform scaling_transform;
1368 scaling_transform.Scale(2.f, 2.f);
1369 scaling_matrix.AppendMatrix(scaling_transform);
1370 EXPECT_TRUE(scaling_matrix.AffectsScale());
1373 TEST(TransformOperationTest, AffectsScaleWithMultipleOperations) {
1374 TransformOperations operations1;
1375 operations1.AppendSkew(1.f, 2.f);
1376 operations1.AppendTranslate(1.f, 2.f, 3.f);
1377 operations1.AppendIdentity();
1378 EXPECT_FALSE(operations1.AffectsScale());
1380 TransformOperations operations2;
1381 operations2.AppendPerspective(2.f);
1382 operations2.AppendScale(1.f, 2.f, 3.f);
1383 operations2.AppendTranslate(3.f, 2.f, 1.f);
1384 EXPECT_TRUE(operations2.AffectsScale());
1387 TEST(TransformOperationTest, IsTranslationWithSingleOperation) {
1388 TransformOperations empty_operations;
1389 EXPECT_TRUE(empty_operations.IsTranslation());
1391 TransformOperations identity;
1392 identity.AppendIdentity();
1393 EXPECT_TRUE(identity.IsTranslation());
1395 TransformOperations translate;
1396 translate.AppendTranslate(1.f, 2.f, 3.f);
1397 EXPECT_TRUE(translate.IsTranslation());
1399 TransformOperations rotate;
1400 rotate.AppendRotate(1.f, 2.f, 3.f, 4.f);
1401 EXPECT_FALSE(rotate.IsTranslation());
1403 TransformOperations scale;
1404 scale.AppendScale(1.f, 2.f, 3.f);
1405 EXPECT_FALSE(scale.IsTranslation());
1407 TransformOperations skew;
1408 skew.AppendSkew(1.f, 2.f);
1409 EXPECT_FALSE(skew.IsTranslation());
1411 TransformOperations perspective;
1412 perspective.AppendPerspective(1.f);
1413 EXPECT_FALSE(perspective.IsTranslation());
1415 TransformOperations identity_matrix;
1416 identity_matrix.AppendMatrix(gfx::Transform());
1417 EXPECT_TRUE(identity_matrix.IsTranslation());
1419 TransformOperations translation_matrix;
1420 gfx::Transform translation_transform;
1421 translation_transform.Translate3d(1.f, 2.f, 3.f);
1422 translation_matrix.AppendMatrix(translation_transform);
1423 EXPECT_TRUE(translation_matrix.IsTranslation());
1425 TransformOperations scaling_matrix;
1426 gfx::Transform scaling_transform;
1427 scaling_transform.Scale(2.f, 2.f);
1428 scaling_matrix.AppendMatrix(scaling_transform);
1429 EXPECT_FALSE(scaling_matrix.IsTranslation());
1432 TEST(TransformOperationTest, IsTranslationWithMultipleOperations) {
1433 TransformOperations operations1;
1434 operations1.AppendSkew(1.f, 2.f);
1435 operations1.AppendTranslate(1.f, 2.f, 3.f);
1436 operations1.AppendIdentity();
1437 EXPECT_FALSE(operations1.IsTranslation());
1439 TransformOperations operations2;
1440 operations2.AppendIdentity();
1441 operations2.AppendTranslate(3.f, 2.f, 1.f);
1442 gfx::Transform translation_transform;
1443 translation_transform.Translate3d(1.f, 2.f, 3.f);
1444 operations2.AppendMatrix(translation_transform);
1445 EXPECT_TRUE(operations2.IsTranslation());
1448 TEST(TransformOperationTest, ScaleComponent) {
1449 gfx::Vector3dF scale;
1451 // Scale.
1452 TransformOperations operations1;
1453 operations1.AppendScale(-3.f, 2.f, 5.f);
1454 EXPECT_TRUE(operations1.ScaleComponent(&scale));
1455 EXPECT_EQ(gfx::Vector3dF(-3.f, 2.f, 5.f), scale);
1457 // Translate + Scale.
1458 TransformOperations operations5;
1459 operations5.AppendTranslate(1.f, 2.f, 3.f);
1460 operations5.AppendScale(2.f, 5.f, 4.f);
1461 EXPECT_TRUE(operations5.ScaleComponent(&scale));
1462 EXPECT_EQ(gfx::Vector3dF(2.f, 5.f, 4.f), scale);
1464 // Translate + Scale + Matrix with translate.
1465 gfx::Transform translation_transform;
1466 translation_transform.Translate3d(1.f, 2.f, 3.f);
1467 operations5.AppendMatrix(translation_transform);
1468 EXPECT_TRUE(operations5.ScaleComponent(&scale));
1469 EXPECT_EQ(gfx::Vector3dF(2.f, 5.f, 4.f), scale);
1472 TEST(TransformOperationTest, ScaleComponentCannotBeComputed) {
1473 gfx::Vector3dF scale;
1475 // Scale can.
1476 TransformOperations operations1;
1477 operations1.AppendScale(2.f, 2.f, 2.f);
1478 EXPECT_TRUE(operations1.ScaleComponent(&scale));
1479 EXPECT_EQ(gfx::Vector3dF(2.f, 2.f, 2.f), scale);
1481 // Translate can.
1482 TransformOperations operations2;
1483 operations2.AppendTranslate(1.f, 2.f, 3.f);
1484 EXPECT_TRUE(operations2.ScaleComponent(&scale));
1485 EXPECT_EQ(gfx::Vector3dF(1.f, 1.f, 1.f), scale);
1487 // Scale + translate can.
1488 TransformOperations operations3;
1489 operations3.AppendScale(2.f, 3.f, 2.f);
1490 operations3.AppendTranslate(1.f, 2.f, 3.f);
1491 EXPECT_TRUE(operations3.ScaleComponent(&scale));
1492 EXPECT_EQ(gfx::Vector3dF(2.f, 3.f, 2.f), scale);
1494 // Two Scales can't.
1495 TransformOperations operations4;
1496 operations4.AppendScale(2.f, 3.f, 2.f);
1497 operations4.AppendScale(3.f, 2.f, 3.f);
1498 EXPECT_FALSE(operations4.ScaleComponent(&scale));
1500 // Matrix can't.
1501 TransformOperations operations5;
1502 operations5.AppendScale(2.f, 2.f, 2.f);
1503 gfx::Transform scaling_transform;
1504 scaling_transform.Scale(2.f, 2.f);
1505 operations5.AppendMatrix(scaling_transform);
1506 EXPECT_FALSE(operations5.ScaleComponent(&scale));
1508 // Scale + Rotate can't.
1509 TransformOperations operations7;
1510 operations7.AppendScale(2.f, 2.f, 2.f);
1511 operations7.AppendRotate(1.f, 2.f, 3.f, 4.f);
1512 EXPECT_FALSE(operations7.ScaleComponent(&scale));
1514 // Scale + Skew can't.
1515 TransformOperations operations9;
1516 operations9.AppendScale(2.f, 2.f, 2.f);
1517 operations9.AppendSkew(1.f, 2.f);
1518 EXPECT_FALSE(operations9.ScaleComponent(&scale));
1520 // Scale + Perspective can't.
1521 TransformOperations operations11;
1522 operations11.AppendScale(2.f, 2.f, 2.f);
1523 operations11.AppendPerspective(1.f);
1524 EXPECT_FALSE(operations11.ScaleComponent(&scale));
1527 } // namespace
1528 } // namespace cc