OLD | NEW |
| (Empty) |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include <limits> | |
6 | |
7 #include "base/basictypes.h" | |
8 #include "base/memory/scoped_vector.h" | |
9 #include "cc/animation/transform_operations.h" | |
10 #include "cc/test/geometry_test_utils.h" | |
11 #include "testing/gtest/include/gtest/gtest.h" | |
12 #include "ui/gfx/animation/tween.h" | |
13 #include "ui/gfx/geometry/box_f.h" | |
14 #include "ui/gfx/geometry/rect_conversions.h" | |
15 #include "ui/gfx/geometry/vector3d_f.h" | |
16 | |
17 namespace cc { | |
18 namespace { | |
19 | |
20 TEST(TransformOperationTest, TransformTypesAreUnique) { | |
21 ScopedVector<TransformOperations> transforms; | |
22 | |
23 TransformOperations* to_add = new TransformOperations(); | |
24 to_add->AppendTranslate(1, 0, 0); | |
25 transforms.push_back(to_add); | |
26 | |
27 to_add = new TransformOperations(); | |
28 to_add->AppendRotate(0, 0, 1, 2); | |
29 transforms.push_back(to_add); | |
30 | |
31 to_add = new TransformOperations(); | |
32 to_add->AppendScale(2, 2, 2); | |
33 transforms.push_back(to_add); | |
34 | |
35 to_add = new TransformOperations(); | |
36 to_add->AppendSkew(1, 0); | |
37 transforms.push_back(to_add); | |
38 | |
39 to_add = new TransformOperations(); | |
40 to_add->AppendPerspective(800); | |
41 transforms.push_back(to_add); | |
42 | |
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); | |
47 } | |
48 } | |
49 } | |
50 | |
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); | |
56 | |
57 TransformOperations skews; | |
58 skews.AppendSkew(0, 2); | |
59 skews.AppendSkew(0, 2); | |
60 skews.AppendSkew(0, 2); | |
61 | |
62 TransformOperations translates2; | |
63 translates2.AppendTranslate(0, 2, 0); | |
64 translates2.AppendTranslate(0, 2, 0); | |
65 translates2.AppendTranslate(0, 2, 0); | |
66 | |
67 TransformOperations translates3 = translates2; | |
68 | |
69 EXPECT_FALSE(translates.MatchesTypes(skews)); | |
70 EXPECT_TRUE(translates.MatchesTypes(translates2)); | |
71 EXPECT_TRUE(translates.MatchesTypes(translates3)); | |
72 } | |
73 | |
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); | |
79 | |
80 TransformOperations skews; | |
81 skews.AppendSkew(2, 0); | |
82 skews.AppendSkew(2, 0); | |
83 | |
84 TransformOperations translates2; | |
85 translates2.AppendTranslate(0, 2, 0); | |
86 translates2.AppendTranslate(0, 2, 0); | |
87 | |
88 EXPECT_FALSE(translates.MatchesTypes(skews)); | |
89 EXPECT_FALSE(translates.MatchesTypes(translates2)); | |
90 } | |
91 | |
92 void GetIdentityOperations(ScopedVector<TransformOperations>* operations) { | |
93 TransformOperations* to_add = new TransformOperations(); | |
94 operations->push_back(to_add); | |
95 | |
96 to_add = new TransformOperations(); | |
97 to_add->AppendTranslate(0, 0, 0); | |
98 operations->push_back(to_add); | |
99 | |
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); | |
104 | |
105 to_add = new TransformOperations(); | |
106 to_add->AppendScale(1, 1, 1); | |
107 operations->push_back(to_add); | |
108 | |
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); | |
113 | |
114 to_add = new TransformOperations(); | |
115 to_add->AppendSkew(0, 0); | |
116 operations->push_back(to_add); | |
117 | |
118 to_add = new TransformOperations(); | |
119 to_add->AppendSkew(0, 0); | |
120 to_add->AppendSkew(0, 0); | |
121 operations->push_back(to_add); | |
122 | |
123 to_add = new TransformOperations(); | |
124 to_add->AppendRotate(0, 0, 1, 0); | |
125 operations->push_back(to_add); | |
126 | |
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); | |
131 | |
132 to_add = new TransformOperations(); | |
133 to_add->AppendMatrix(gfx::Transform()); | |
134 operations->push_back(to_add); | |
135 | |
136 to_add = new TransformOperations(); | |
137 to_add->AppendMatrix(gfx::Transform()); | |
138 to_add->AppendMatrix(gfx::Transform()); | |
139 operations->push_back(to_add); | |
140 } | |
141 | |
142 TEST(TransformOperationTest, IdentityAlwaysMatches) { | |
143 ScopedVector<TransformOperations> operations; | |
144 GetIdentityOperations(&operations); | |
145 | |
146 for (size_t i = 0; i < operations.size(); ++i) { | |
147 for (size_t j = 0; j < operations.size(); ++j) | |
148 EXPECT_TRUE(operations[i]->MatchesTypes(*operations[j])); | |
149 } | |
150 } | |
151 | |
152 TEST(TransformOperationTest, ApplyTranslate) { | |
153 SkMScalar x = 1; | |
154 SkMScalar y = 2; | |
155 SkMScalar z = 3; | |
156 TransformOperations operations; | |
157 operations.AppendTranslate(x, y, z); | |
158 gfx::Transform expected; | |
159 expected.Translate3d(x, y, z); | |
160 EXPECT_TRANSFORMATION_MATRIX_EQ(expected, operations.Apply()); | |
161 } | |
162 | |
163 TEST(TransformOperationTest, ApplyRotate) { | |
164 SkMScalar x = 1; | |
165 SkMScalar y = 2; | |
166 SkMScalar z = 3; | |
167 SkMScalar degrees = 80; | |
168 TransformOperations operations; | |
169 operations.AppendRotate(x, y, z, degrees); | |
170 gfx::Transform expected; | |
171 expected.RotateAbout(gfx::Vector3dF(x, y, z), degrees); | |
172 EXPECT_TRANSFORMATION_MATRIX_EQ(expected, operations.Apply()); | |
173 } | |
174 | |
175 TEST(TransformOperationTest, ApplyScale) { | |
176 SkMScalar x = 1; | |
177 SkMScalar y = 2; | |
178 SkMScalar z = 3; | |
179 TransformOperations operations; | |
180 operations.AppendScale(x, y, z); | |
181 gfx::Transform expected; | |
182 expected.Scale3d(x, y, z); | |
183 EXPECT_TRANSFORMATION_MATRIX_EQ(expected, operations.Apply()); | |
184 } | |
185 | |
186 TEST(TransformOperationTest, ApplySkew) { | |
187 SkMScalar x = 1; | |
188 SkMScalar y = 2; | |
189 TransformOperations operations; | |
190 operations.AppendSkew(x, y); | |
191 gfx::Transform expected; | |
192 expected.SkewX(x); | |
193 expected.SkewY(y); | |
194 EXPECT_TRANSFORMATION_MATRIX_EQ(expected, operations.Apply()); | |
195 } | |
196 | |
197 TEST(TransformOperationTest, ApplyPerspective) { | |
198 SkMScalar depth = 800; | |
199 TransformOperations operations; | |
200 operations.AppendPerspective(depth); | |
201 gfx::Transform expected; | |
202 expected.ApplyPerspectiveDepth(depth); | |
203 EXPECT_TRANSFORMATION_MATRIX_EQ(expected, operations.Apply()); | |
204 } | |
205 | |
206 TEST(TransformOperationTest, ApplyMatrix) { | |
207 SkMScalar dx = 1; | |
208 SkMScalar dy = 2; | |
209 SkMScalar dz = 3; | |
210 gfx::Transform expected_matrix; | |
211 expected_matrix.Translate3d(dx, dy, dz); | |
212 TransformOperations matrix_transform; | |
213 matrix_transform.AppendMatrix(expected_matrix); | |
214 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_matrix, matrix_transform.Apply()); | |
215 } | |
216 | |
217 TEST(TransformOperationTest, ApplyOrder) { | |
218 SkMScalar sx = 2; | |
219 SkMScalar sy = 4; | |
220 SkMScalar sz = 8; | |
221 | |
222 SkMScalar dx = 1; | |
223 SkMScalar dy = 2; | |
224 SkMScalar dz = 3; | |
225 | |
226 TransformOperations operations; | |
227 operations.AppendScale(sx, sy, sz); | |
228 operations.AppendTranslate(dx, dy, dz); | |
229 | |
230 gfx::Transform expected_scale_matrix; | |
231 expected_scale_matrix.Scale3d(sx, sy, sz); | |
232 | |
233 gfx::Transform expected_translate_matrix; | |
234 expected_translate_matrix.Translate3d(dx, dy, dz); | |
235 | |
236 gfx::Transform expected_combined_matrix = expected_scale_matrix; | |
237 expected_combined_matrix.PreconcatTransform(expected_translate_matrix); | |
238 | |
239 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_combined_matrix, operations.Apply()); | |
240 } | |
241 | |
242 TEST(TransformOperationTest, BlendOrder) { | |
243 SkMScalar sx1 = 2; | |
244 SkMScalar sy1 = 4; | |
245 SkMScalar sz1 = 8; | |
246 | |
247 SkMScalar dx1 = 1; | |
248 SkMScalar dy1 = 2; | |
249 SkMScalar dz1 = 3; | |
250 | |
251 SkMScalar sx2 = 4; | |
252 SkMScalar sy2 = 8; | |
253 SkMScalar sz2 = 16; | |
254 | |
255 SkMScalar dx2 = 10; | |
256 SkMScalar dy2 = 20; | |
257 SkMScalar dz2 = 30; | |
258 | |
259 TransformOperations operations_from; | |
260 operations_from.AppendScale(sx1, sy1, sz1); | |
261 operations_from.AppendTranslate(dx1, dy1, dz1); | |
262 | |
263 TransformOperations operations_to; | |
264 operations_to.AppendScale(sx2, sy2, sz2); | |
265 operations_to.AppendTranslate(dx2, dy2, dz2); | |
266 | |
267 gfx::Transform scale_from; | |
268 scale_from.Scale3d(sx1, sy1, sz1); | |
269 gfx::Transform translate_from; | |
270 translate_from.Translate3d(dx1, dy1, dz1); | |
271 | |
272 gfx::Transform scale_to; | |
273 scale_to.Scale3d(sx2, sy2, sz2); | |
274 gfx::Transform translate_to; | |
275 translate_to.Translate3d(dx2, dy2, dz2); | |
276 | |
277 SkMScalar progress = 0.25f; | |
278 | |
279 gfx::Transform blended_scale = scale_to; | |
280 blended_scale.Blend(scale_from, progress); | |
281 | |
282 gfx::Transform blended_translate = translate_to; | |
283 blended_translate.Blend(translate_from, progress); | |
284 | |
285 gfx::Transform expected = blended_scale; | |
286 expected.PreconcatTransform(blended_translate); | |
287 | |
288 EXPECT_TRANSFORMATION_MATRIX_EQ( | |
289 expected, operations_to.Blend(operations_from, progress)); | |
290 } | |
291 | |
292 static void CheckProgress(SkMScalar progress, | |
293 const gfx::Transform& from_matrix, | |
294 const gfx::Transform& to_matrix, | |
295 const TransformOperations& from_transform, | |
296 const TransformOperations& to_transform) { | |
297 gfx::Transform expected_matrix = to_matrix; | |
298 expected_matrix.Blend(from_matrix, progress); | |
299 EXPECT_TRANSFORMATION_MATRIX_EQ( | |
300 expected_matrix, to_transform.Blend(from_transform, progress)); | |
301 } | |
302 | |
303 TEST(TransformOperationTest, BlendProgress) { | |
304 SkMScalar sx = 2; | |
305 SkMScalar sy = 4; | |
306 SkMScalar sz = 8; | |
307 TransformOperations operations_from; | |
308 operations_from.AppendScale(sx, sy, sz); | |
309 | |
310 gfx::Transform matrix_from; | |
311 matrix_from.Scale3d(sx, sy, sz); | |
312 | |
313 sx = 4; | |
314 sy = 8; | |
315 sz = 16; | |
316 TransformOperations operations_to; | |
317 operations_to.AppendScale(sx, sy, sz); | |
318 | |
319 gfx::Transform matrix_to; | |
320 matrix_to.Scale3d(sx, sy, sz); | |
321 | |
322 CheckProgress(-1, matrix_from, matrix_to, operations_from, operations_to); | |
323 CheckProgress(0, matrix_from, matrix_to, operations_from, operations_to); | |
324 CheckProgress(0.25f, matrix_from, matrix_to, operations_from, operations_to); | |
325 CheckProgress(0.5f, matrix_from, matrix_to, operations_from, operations_to); | |
326 CheckProgress(1, matrix_from, matrix_to, operations_from, operations_to); | |
327 CheckProgress(2, matrix_from, matrix_to, operations_from, operations_to); | |
328 } | |
329 | |
330 TEST(TransformOperationTest, BlendWhenTypesDoNotMatch) { | |
331 SkMScalar sx1 = 2; | |
332 SkMScalar sy1 = 4; | |
333 SkMScalar sz1 = 8; | |
334 | |
335 SkMScalar dx1 = 1; | |
336 SkMScalar dy1 = 2; | |
337 SkMScalar dz1 = 3; | |
338 | |
339 SkMScalar sx2 = 4; | |
340 SkMScalar sy2 = 8; | |
341 SkMScalar sz2 = 16; | |
342 | |
343 SkMScalar dx2 = 10; | |
344 SkMScalar dy2 = 20; | |
345 SkMScalar dz2 = 30; | |
346 | |
347 TransformOperations operations_from; | |
348 operations_from.AppendScale(sx1, sy1, sz1); | |
349 operations_from.AppendTranslate(dx1, dy1, dz1); | |
350 | |
351 TransformOperations operations_to; | |
352 operations_to.AppendTranslate(dx2, dy2, dz2); | |
353 operations_to.AppendScale(sx2, sy2, sz2); | |
354 | |
355 gfx::Transform from; | |
356 from.Scale3d(sx1, sy1, sz1); | |
357 from.Translate3d(dx1, dy1, dz1); | |
358 | |
359 gfx::Transform to; | |
360 to.Translate3d(dx2, dy2, dz2); | |
361 to.Scale3d(sx2, sy2, sz2); | |
362 | |
363 SkMScalar progress = 0.25f; | |
364 | |
365 gfx::Transform expected = to; | |
366 expected.Blend(from, progress); | |
367 | |
368 EXPECT_TRANSFORMATION_MATRIX_EQ( | |
369 expected, operations_to.Blend(operations_from, progress)); | |
370 } | |
371 | |
372 TEST(TransformOperationTest, LargeRotationsWithSameAxis) { | |
373 TransformOperations operations_from; | |
374 operations_from.AppendRotate(0, 0, 1, 0); | |
375 | |
376 TransformOperations operations_to; | |
377 operations_to.AppendRotate(0, 0, 2, 360); | |
378 | |
379 SkMScalar progress = 0.5f; | |
380 | |
381 gfx::Transform expected; | |
382 expected.RotateAbout(gfx::Vector3dF(0, 0, 1), 180); | |
383 | |
384 EXPECT_TRANSFORMATION_MATRIX_EQ( | |
385 expected, operations_to.Blend(operations_from, progress)); | |
386 } | |
387 | |
388 TEST(TransformOperationTest, LargeRotationsWithSameAxisInDifferentDirection) { | |
389 TransformOperations operations_from; | |
390 operations_from.AppendRotate(0, 0, 1, 180); | |
391 | |
392 TransformOperations operations_to; | |
393 operations_to.AppendRotate(0, 0, -1, 180); | |
394 | |
395 SkMScalar progress = 0.5f; | |
396 | |
397 gfx::Transform expected; | |
398 | |
399 EXPECT_TRANSFORMATION_MATRIX_EQ( | |
400 expected, operations_to.Blend(operations_from, progress)); | |
401 } | |
402 | |
403 TEST(TransformOperationTest, LargeRotationsWithDifferentAxes) { | |
404 TransformOperations operations_from; | |
405 operations_from.AppendRotate(0, 0, 1, 175); | |
406 | |
407 TransformOperations operations_to; | |
408 operations_to.AppendRotate(0, 1, 0, 175); | |
409 | |
410 SkMScalar progress = 0.5f; | |
411 gfx::Transform matrix_from; | |
412 matrix_from.RotateAbout(gfx::Vector3dF(0, 0, 1), 175); | |
413 | |
414 gfx::Transform matrix_to; | |
415 matrix_to.RotateAbout(gfx::Vector3dF(0, 1, 0), 175); | |
416 | |
417 gfx::Transform expected = matrix_to; | |
418 expected.Blend(matrix_from, progress); | |
419 | |
420 EXPECT_TRANSFORMATION_MATRIX_EQ( | |
421 expected, operations_to.Blend(operations_from, progress)); | |
422 } | |
423 | |
424 TEST(TransformOperationTest, BlendRotationFromIdentity) { | |
425 ScopedVector<TransformOperations> identity_operations; | |
426 GetIdentityOperations(&identity_operations); | |
427 | |
428 for (size_t i = 0; i < identity_operations.size(); ++i) { | |
429 TransformOperations operations; | |
430 operations.AppendRotate(0, 0, 1, 360); | |
431 | |
432 SkMScalar progress = 0.5f; | |
433 | |
434 gfx::Transform expected; | |
435 expected.RotateAbout(gfx::Vector3dF(0, 0, 1), 180); | |
436 | |
437 EXPECT_TRANSFORMATION_MATRIX_EQ( | |
438 expected, operations.Blend(*identity_operations[i], progress)); | |
439 | |
440 progress = -0.5f; | |
441 | |
442 expected.MakeIdentity(); | |
443 expected.RotateAbout(gfx::Vector3dF(0, 0, 1), -180); | |
444 | |
445 EXPECT_TRANSFORMATION_MATRIX_EQ( | |
446 expected, operations.Blend(*identity_operations[i], progress)); | |
447 | |
448 progress = 1.5f; | |
449 | |
450 expected.MakeIdentity(); | |
451 expected.RotateAbout(gfx::Vector3dF(0, 0, 1), 540); | |
452 | |
453 EXPECT_TRANSFORMATION_MATRIX_EQ( | |
454 expected, operations.Blend(*identity_operations[i], progress)); | |
455 } | |
456 } | |
457 | |
458 TEST(TransformOperationTest, BlendTranslationFromIdentity) { | |
459 ScopedVector<TransformOperations> identity_operations; | |
460 GetIdentityOperations(&identity_operations); | |
461 | |
462 for (size_t i = 0; i < identity_operations.size(); ++i) { | |
463 TransformOperations operations; | |
464 operations.AppendTranslate(2, 2, 2); | |
465 | |
466 SkMScalar progress = 0.5f; | |
467 | |
468 gfx::Transform expected; | |
469 expected.Translate3d(1, 1, 1); | |
470 | |
471 EXPECT_TRANSFORMATION_MATRIX_EQ( | |
472 expected, operations.Blend(*identity_operations[i], progress)); | |
473 | |
474 progress = -0.5f; | |
475 | |
476 expected.MakeIdentity(); | |
477 expected.Translate3d(-1, -1, -1); | |
478 | |
479 EXPECT_TRANSFORMATION_MATRIX_EQ( | |
480 expected, operations.Blend(*identity_operations[i], progress)); | |
481 | |
482 progress = 1.5f; | |
483 | |
484 expected.MakeIdentity(); | |
485 expected.Translate3d(3, 3, 3); | |
486 | |
487 EXPECT_TRANSFORMATION_MATRIX_EQ( | |
488 expected, operations.Blend(*identity_operations[i], progress)); | |
489 } | |
490 } | |
491 | |
492 TEST(TransformOperationTest, BlendScaleFromIdentity) { | |
493 ScopedVector<TransformOperations> identity_operations; | |
494 GetIdentityOperations(&identity_operations); | |
495 | |
496 for (size_t i = 0; i < identity_operations.size(); ++i) { | |
497 TransformOperations operations; | |
498 operations.AppendScale(3, 3, 3); | |
499 | |
500 SkMScalar progress = 0.5f; | |
501 | |
502 gfx::Transform expected; | |
503 expected.Scale3d(2, 2, 2); | |
504 | |
505 EXPECT_TRANSFORMATION_MATRIX_EQ( | |
506 expected, operations.Blend(*identity_operations[i], progress)); | |
507 | |
508 progress = -0.5f; | |
509 | |
510 expected.MakeIdentity(); | |
511 expected.Scale3d(0, 0, 0); | |
512 | |
513 EXPECT_TRANSFORMATION_MATRIX_EQ( | |
514 expected, operations.Blend(*identity_operations[i], progress)); | |
515 | |
516 progress = 1.5f; | |
517 | |
518 expected.MakeIdentity(); | |
519 expected.Scale3d(4, 4, 4); | |
520 | |
521 EXPECT_TRANSFORMATION_MATRIX_EQ( | |
522 expected, operations.Blend(*identity_operations[i], progress)); | |
523 } | |
524 } | |
525 | |
526 TEST(TransformOperationTest, BlendSkewFromIdentity) { | |
527 ScopedVector<TransformOperations> identity_operations; | |
528 GetIdentityOperations(&identity_operations); | |
529 | |
530 for (size_t i = 0; i < identity_operations.size(); ++i) { | |
531 TransformOperations operations; | |
532 operations.AppendSkew(2, 2); | |
533 | |
534 SkMScalar progress = 0.5f; | |
535 | |
536 gfx::Transform expected; | |
537 expected.SkewX(1); | |
538 expected.SkewY(1); | |
539 | |
540 EXPECT_TRANSFORMATION_MATRIX_EQ( | |
541 expected, operations.Blend(*identity_operations[i], progress)); | |
542 | |
543 progress = -0.5f; | |
544 | |
545 expected.MakeIdentity(); | |
546 expected.SkewX(-1); | |
547 expected.SkewY(-1); | |
548 | |
549 EXPECT_TRANSFORMATION_MATRIX_EQ( | |
550 expected, operations.Blend(*identity_operations[i], progress)); | |
551 | |
552 progress = 1.5f; | |
553 | |
554 expected.MakeIdentity(); | |
555 expected.SkewX(3); | |
556 expected.SkewY(3); | |
557 | |
558 EXPECT_TRANSFORMATION_MATRIX_EQ( | |
559 expected, operations.Blend(*identity_operations[i], progress)); | |
560 } | |
561 } | |
562 | |
563 TEST(TransformOperationTest, BlendPerspectiveFromIdentity) { | |
564 ScopedVector<TransformOperations> identity_operations; | |
565 GetIdentityOperations(&identity_operations); | |
566 | |
567 for (size_t i = 0; i < identity_operations.size(); ++i) { | |
568 TransformOperations operations; | |
569 operations.AppendPerspective(1000); | |
570 | |
571 SkMScalar progress = 0.5f; | |
572 | |
573 gfx::Transform expected; | |
574 expected.ApplyPerspectiveDepth(2000); | |
575 | |
576 EXPECT_TRANSFORMATION_MATRIX_EQ( | |
577 expected, operations.Blend(*identity_operations[i], progress)); | |
578 } | |
579 } | |
580 | |
581 TEST(TransformOperationTest, BlendRotationToIdentity) { | |
582 ScopedVector<TransformOperations> identity_operations; | |
583 GetIdentityOperations(&identity_operations); | |
584 | |
585 for (size_t i = 0; i < identity_operations.size(); ++i) { | |
586 TransformOperations operations; | |
587 operations.AppendRotate(0, 0, 1, 360); | |
588 | |
589 SkMScalar progress = 0.5f; | |
590 | |
591 gfx::Transform expected; | |
592 expected.RotateAbout(gfx::Vector3dF(0, 0, 1), 180); | |
593 | |
594 EXPECT_TRANSFORMATION_MATRIX_EQ( | |
595 expected, identity_operations[i]->Blend(operations, progress)); | |
596 } | |
597 } | |
598 | |
599 TEST(TransformOperationTest, BlendTranslationToIdentity) { | |
600 ScopedVector<TransformOperations> identity_operations; | |
601 GetIdentityOperations(&identity_operations); | |
602 | |
603 for (size_t i = 0; i < identity_operations.size(); ++i) { | |
604 TransformOperations operations; | |
605 operations.AppendTranslate(2, 2, 2); | |
606 | |
607 SkMScalar progress = 0.5f; | |
608 | |
609 gfx::Transform expected; | |
610 expected.Translate3d(1, 1, 1); | |
611 | |
612 EXPECT_TRANSFORMATION_MATRIX_EQ( | |
613 expected, identity_operations[i]->Blend(operations, progress)); | |
614 } | |
615 } | |
616 | |
617 TEST(TransformOperationTest, BlendScaleToIdentity) { | |
618 ScopedVector<TransformOperations> identity_operations; | |
619 GetIdentityOperations(&identity_operations); | |
620 | |
621 for (size_t i = 0; i < identity_operations.size(); ++i) { | |
622 TransformOperations operations; | |
623 operations.AppendScale(3, 3, 3); | |
624 | |
625 SkMScalar progress = 0.5f; | |
626 | |
627 gfx::Transform expected; | |
628 expected.Scale3d(2, 2, 2); | |
629 | |
630 EXPECT_TRANSFORMATION_MATRIX_EQ( | |
631 expected, identity_operations[i]->Blend(operations, progress)); | |
632 } | |
633 } | |
634 | |
635 TEST(TransformOperationTest, BlendSkewToIdentity) { | |
636 ScopedVector<TransformOperations> identity_operations; | |
637 GetIdentityOperations(&identity_operations); | |
638 | |
639 for (size_t i = 0; i < identity_operations.size(); ++i) { | |
640 TransformOperations operations; | |
641 operations.AppendSkew(2, 2); | |
642 | |
643 SkMScalar progress = 0.5f; | |
644 | |
645 gfx::Transform expected; | |
646 expected.SkewX(1); | |
647 expected.SkewY(1); | |
648 | |
649 EXPECT_TRANSFORMATION_MATRIX_EQ( | |
650 expected, identity_operations[i]->Blend(operations, progress)); | |
651 } | |
652 } | |
653 | |
654 TEST(TransformOperationTest, BlendPerspectiveToIdentity) { | |
655 ScopedVector<TransformOperations> identity_operations; | |
656 GetIdentityOperations(&identity_operations); | |
657 | |
658 for (size_t i = 0; i < identity_operations.size(); ++i) { | |
659 TransformOperations operations; | |
660 operations.AppendPerspective(1000); | |
661 | |
662 SkMScalar progress = 0.5f; | |
663 | |
664 gfx::Transform expected; | |
665 expected.ApplyPerspectiveDepth(2000); | |
666 | |
667 EXPECT_TRANSFORMATION_MATRIX_EQ( | |
668 expected, identity_operations[i]->Blend(operations, progress)); | |
669 } | |
670 } | |
671 | |
672 TEST(TransformOperationTest, ExtrapolatePerspectiveBlending) { | |
673 TransformOperations operations1; | |
674 operations1.AppendPerspective(1000); | |
675 | |
676 TransformOperations operations2; | |
677 operations2.AppendPerspective(500); | |
678 | |
679 gfx::Transform expected; | |
680 expected.ApplyPerspectiveDepth(400); | |
681 | |
682 EXPECT_TRANSFORMATION_MATRIX_EQ( | |
683 expected, operations1.Blend(operations2, -0.5)); | |
684 | |
685 expected.MakeIdentity(); | |
686 expected.ApplyPerspectiveDepth(2000); | |
687 | |
688 EXPECT_TRANSFORMATION_MATRIX_EQ( | |
689 expected, operations1.Blend(operations2, 1.5)); | |
690 } | |
691 | |
692 TEST(TransformOperationTest, ExtrapolateMatrixBlending) { | |
693 gfx::Transform transform1; | |
694 transform1.Translate3d(1, 1, 1); | |
695 TransformOperations operations1; | |
696 operations1.AppendMatrix(transform1); | |
697 | |
698 gfx::Transform transform2; | |
699 transform2.Translate3d(3, 3, 3); | |
700 TransformOperations operations2; | |
701 operations2.AppendMatrix(transform2); | |
702 | |
703 gfx::Transform expected; | |
704 EXPECT_TRANSFORMATION_MATRIX_EQ( | |
705 expected, operations1.Blend(operations2, 1.5)); | |
706 | |
707 expected.Translate3d(4, 4, 4); | |
708 EXPECT_TRANSFORMATION_MATRIX_EQ( | |
709 expected, operations1.Blend(operations2, -0.5)); | |
710 } | |
711 | |
712 TEST(TransformOperationTest, BlendedBoundsWhenTypesDoNotMatch) { | |
713 TransformOperations operations_from; | |
714 operations_from.AppendScale(2.0, 4.0, 8.0); | |
715 operations_from.AppendTranslate(1.0, 2.0, 3.0); | |
716 | |
717 TransformOperations operations_to; | |
718 operations_to.AppendTranslate(10.0, 20.0, 30.0); | |
719 operations_to.AppendScale(4.0, 8.0, 16.0); | |
720 | |
721 gfx::BoxF box(1.f, 1.f, 1.f); | |
722 gfx::BoxF bounds; | |
723 | |
724 SkMScalar min_progress = 0.f; | |
725 SkMScalar max_progress = 1.f; | |
726 | |
727 EXPECT_FALSE(operations_to.BlendedBoundsForBox( | |
728 box, operations_from, min_progress, max_progress, &bounds)); | |
729 } | |
730 | |
731 TEST(TransformOperationTest, BlendedBoundsForIdentity) { | |
732 TransformOperations operations_from; | |
733 operations_from.AppendIdentity(); | |
734 TransformOperations operations_to; | |
735 operations_to.AppendIdentity(); | |
736 | |
737 gfx::BoxF box(1.f, 2.f, 3.f); | |
738 gfx::BoxF bounds; | |
739 | |
740 SkMScalar min_progress = 0.f; | |
741 SkMScalar max_progress = 1.f; | |
742 | |
743 EXPECT_TRUE(operations_to.BlendedBoundsForBox( | |
744 box, operations_from, min_progress, max_progress, &bounds)); | |
745 EXPECT_EQ(box.ToString(), bounds.ToString()); | |
746 } | |
747 | |
748 TEST(TransformOperationTest, BlendedBoundsForTranslate) { | |
749 TransformOperations operations_from; | |
750 operations_from.AppendTranslate(3.0, -4.0, 2.0); | |
751 TransformOperations operations_to; | |
752 operations_to.AppendTranslate(7.0, 4.0, -2.0); | |
753 | |
754 gfx::BoxF box(1.f, 2.f, 3.f, 4.f, 4.f, 4.f); | |
755 gfx::BoxF bounds; | |
756 | |
757 SkMScalar min_progress = -0.5f; | |
758 SkMScalar max_progress = 1.5f; | |
759 EXPECT_TRUE(operations_to.BlendedBoundsForBox( | |
760 box, operations_from, min_progress, max_progress, &bounds)); | |
761 EXPECT_EQ(gfx::BoxF(2.f, -6.f, -1.f, 12.f, 20.f, 12.f).ToString(), | |
762 bounds.ToString()); | |
763 | |
764 min_progress = 0.f; | |
765 max_progress = 1.f; | |
766 EXPECT_TRUE(operations_to.BlendedBoundsForBox( | |
767 box, operations_from, min_progress, max_progress, &bounds)); | |
768 EXPECT_EQ(gfx::BoxF(4.f, -2.f, 1.f, 8.f, 12.f, 8.f).ToString(), | |
769 bounds.ToString()); | |
770 | |
771 TransformOperations identity; | |
772 EXPECT_TRUE(operations_to.BlendedBoundsForBox( | |
773 box, identity, min_progress, max_progress, &bounds)); | |
774 EXPECT_EQ(gfx::BoxF(1.f, 2.f, 1.f, 11.f, 8.f, 6.f).ToString(), | |
775 bounds.ToString()); | |
776 | |
777 EXPECT_TRUE(identity.BlendedBoundsForBox( | |
778 box, operations_from, min_progress, max_progress, &bounds)); | |
779 EXPECT_EQ(gfx::BoxF(1.f, -2.f, 3.f, 7.f, 8.f, 6.f).ToString(), | |
780 bounds.ToString()); | |
781 } | |
782 | |
783 TEST(TransformOperationTest, BlendedBoundsForScale) { | |
784 TransformOperations operations_from; | |
785 operations_from.AppendScale(3.0, 0.5, 2.0); | |
786 TransformOperations operations_to; | |
787 operations_to.AppendScale(7.0, 4.0, -2.0); | |
788 | |
789 gfx::BoxF box(1.f, 2.f, 3.f, 4.f, 4.f, 4.f); | |
790 gfx::BoxF bounds; | |
791 | |
792 SkMScalar min_progress = -0.5f; | |
793 SkMScalar max_progress = 1.5f; | |
794 EXPECT_TRUE(operations_to.BlendedBoundsForBox( | |
795 box, operations_from, min_progress, max_progress, &bounds)); | |
796 EXPECT_EQ(gfx::BoxF(1.f, -7.5f, -28.f, 44.f, 42.f, 56.f).ToString(), | |
797 bounds.ToString()); | |
798 | |
799 min_progress = 0.f; | |
800 max_progress = 1.f; | |
801 EXPECT_TRUE(operations_to.BlendedBoundsForBox( | |
802 box, operations_from, min_progress, max_progress, &bounds)); | |
803 EXPECT_EQ(gfx::BoxF(3.f, 1.f, -14.f, 32.f, 23.f, 28.f).ToString(), | |
804 bounds.ToString()); | |
805 | |
806 TransformOperations identity; | |
807 EXPECT_TRUE(operations_to.BlendedBoundsForBox( | |
808 box, identity, min_progress, max_progress, &bounds)); | |
809 EXPECT_EQ(gfx::BoxF(1.f, 2.f, -14.f, 34.f, 22.f, 21.f).ToString(), | |
810 bounds.ToString()); | |
811 | |
812 EXPECT_TRUE(identity.BlendedBoundsForBox( | |
813 box, operations_from, min_progress, max_progress, &bounds)); | |
814 EXPECT_EQ(gfx::BoxF(1.f, 1.f, 3.f, 14.f, 5.f, 11.f).ToString(), | |
815 bounds.ToString()); | |
816 } | |
817 | |
818 TEST(TransformOperationTest, BlendedBoundsWithZeroScale) { | |
819 TransformOperations zero_scale; | |
820 zero_scale.AppendScale(0.0, 0.0, 0.0); | |
821 TransformOperations non_zero_scale; | |
822 non_zero_scale.AppendScale(2.0, -4.0, 5.0); | |
823 | |
824 gfx::BoxF box(1.f, 2.f, 3.f, 4.f, 4.f, 4.f); | |
825 gfx::BoxF bounds; | |
826 | |
827 SkMScalar min_progress = 0.f; | |
828 SkMScalar max_progress = 1.f; | |
829 EXPECT_TRUE(zero_scale.BlendedBoundsForBox( | |
830 box, non_zero_scale, min_progress, max_progress, &bounds)); | |
831 EXPECT_EQ(gfx::BoxF(0.f, -24.f, 0.f, 10.f, 24.f, 35.f).ToString(), | |
832 bounds.ToString()); | |
833 | |
834 EXPECT_TRUE(non_zero_scale.BlendedBoundsForBox( | |
835 box, zero_scale, min_progress, max_progress, &bounds)); | |
836 EXPECT_EQ(gfx::BoxF(0.f, -24.f, 0.f, 10.f, 24.f, 35.f).ToString(), | |
837 bounds.ToString()); | |
838 | |
839 EXPECT_TRUE(zero_scale.BlendedBoundsForBox( | |
840 box, zero_scale, min_progress, max_progress, &bounds)); | |
841 EXPECT_EQ(gfx::BoxF().ToString(), bounds.ToString()); | |
842 } | |
843 | |
844 TEST(TransformOperationTest, BlendedBoundsForRotationTrivial) { | |
845 TransformOperations operations_from; | |
846 operations_from.AppendRotate(0.f, 0.f, 1.f, 0.f); | |
847 TransformOperations operations_to; | |
848 operations_to.AppendRotate(0.f, 0.f, 1.f, 360.f); | |
849 | |
850 float sqrt_2 = sqrt(2.f); | |
851 gfx::BoxF box( | |
852 -sqrt_2, -sqrt_2, 0.f, sqrt_2, sqrt_2, 0.f); | |
853 gfx::BoxF bounds; | |
854 | |
855 // Since we're rotating 360 degrees, any box with dimensions between 0 and | |
856 // 2 * sqrt(2) should give the same result. | |
857 float sizes[] = { 0.f, 0.1f, sqrt_2, 2.f * sqrt_2 }; | |
858 for (size_t i = 0; i < arraysize(sizes); ++i) { | |
859 box.set_size(sizes[i], sizes[i], 0.f); | |
860 SkMScalar min_progress = 0.f; | |
861 SkMScalar max_progress = 1.f; | |
862 EXPECT_TRUE(operations_to.BlendedBoundsForBox( | |
863 box, operations_from, min_progress, max_progress, &bounds)); | |
864 EXPECT_EQ(gfx::BoxF(-2.f, -2.f, 0.f, 4.f, 4.f, 0.f).ToString(), | |
865 bounds.ToString()); | |
866 } | |
867 } | |
868 | |
869 TEST(TransformOperationTest, BlendedBoundsForRotationAllExtrema) { | |
870 // If the normal is out of the plane, we can have up to 6 extrema (a min/max | |
871 // in each dimension) between the endpoints of the arc. This test ensures that | |
872 // we consider all 6. | |
873 TransformOperations operations_from; | |
874 operations_from.AppendRotate(1.f, 1.f, 1.f, 30.f); | |
875 TransformOperations operations_to; | |
876 operations_to.AppendRotate(1.f, 1.f, 1.f, 390.f); | |
877 | |
878 gfx::BoxF box(1.f, 0.f, 0.f, 0.f, 0.f, 0.f); | |
879 gfx::BoxF bounds; | |
880 | |
881 float min = -1.f / 3.f; | |
882 float max = 1.f; | |
883 float size = max - min; | |
884 EXPECT_TRUE(operations_to.BlendedBoundsForBox( | |
885 box, operations_from, 0.f, 1.f, &bounds)); | |
886 EXPECT_EQ(gfx::BoxF(min, min, min, size, size, size).ToString(), | |
887 bounds.ToString()); | |
888 } | |
889 | |
890 TEST(TransformOperationTest, BlendedBoundsForRotationDifferentAxes) { | |
891 // We can handle rotations about a single axis. If the axes are different, | |
892 // we revert to matrix interpolation for which inflated bounds cannot be | |
893 // computed. | |
894 TransformOperations operations_from; | |
895 operations_from.AppendRotate(1.f, 1.f, 1.f, 30.f); | |
896 TransformOperations operations_to_same; | |
897 operations_to_same.AppendRotate(1.f, 1.f, 1.f, 390.f); | |
898 TransformOperations operations_to_opposite; | |
899 operations_to_opposite.AppendRotate(-1.f, -1.f, -1.f, 390.f); | |
900 TransformOperations operations_to_different; | |
901 operations_to_different.AppendRotate(1.f, 3.f, 1.f, 390.f); | |
902 | |
903 gfx::BoxF box(1.f, 0.f, 0.f, 0.f, 0.f, 0.f); | |
904 gfx::BoxF bounds; | |
905 | |
906 EXPECT_TRUE(operations_to_same.BlendedBoundsForBox( | |
907 box, operations_from, 0.f, 1.f, &bounds)); | |
908 EXPECT_TRUE(operations_to_opposite.BlendedBoundsForBox( | |
909 box, operations_from, 0.f, 1.f, &bounds)); | |
910 EXPECT_FALSE(operations_to_different.BlendedBoundsForBox( | |
911 box, operations_from, 0.f, 1.f, &bounds)); | |
912 } | |
913 | |
914 TEST(TransformOperationTest, BlendedBoundsForRotationPointOnAxis) { | |
915 // Checks that if the point to rotate is sitting on the axis of rotation, that | |
916 // it does not get affected. | |
917 TransformOperations operations_from; | |
918 operations_from.AppendRotate(1.f, 1.f, 1.f, 30.f); | |
919 TransformOperations operations_to; | |
920 operations_to.AppendRotate(1.f, 1.f, 1.f, 390.f); | |
921 | |
922 gfx::BoxF box(1.f, 1.f, 1.f, 0.f, 0.f, 0.f); | |
923 gfx::BoxF bounds; | |
924 | |
925 EXPECT_TRUE(operations_to.BlendedBoundsForBox( | |
926 box, operations_from, 0.f, 1.f, &bounds)); | |
927 EXPECT_EQ(box.ToString(), bounds.ToString()); | |
928 } | |
929 | |
930 TEST(TransformOperationTest, BlendedBoundsForRotationProblematicAxes) { | |
931 // Zeros in the components of the axis of rotation turned out to be tricky to | |
932 // deal with in practice. This function tests some potentially problematic | |
933 // axes to ensure sane behavior. | |
934 | |
935 // Some common values used in the expected boxes. | |
936 float dim1 = 0.292893f; | |
937 float dim2 = sqrt(2.f); | |
938 float dim3 = 2.f * dim2; | |
939 | |
940 struct { | |
941 float x; | |
942 float y; | |
943 float z; | |
944 gfx::BoxF expected; | |
945 } tests[] = {{0.f, 0.f, 0.f, gfx::BoxF(1.f, 1.f, 1.f, 0.f, 0.f, 0.f)}, | |
946 {1.f, 0.f, 0.f, gfx::BoxF(1.f, -dim2, -dim2, 0.f, dim3, dim3)}, | |
947 {0.f, 1.f, 0.f, gfx::BoxF(-dim2, 1.f, -dim2, dim3, 0.f, dim3)}, | |
948 {0.f, 0.f, 1.f, gfx::BoxF(-dim2, -dim2, 1.f, dim3, dim3, 0.f)}, | |
949 {1.f, 1.f, 0.f, gfx::BoxF(dim1, dim1, -1.f, dim2, dim2, 2.f)}, | |
950 {0.f, 1.f, 1.f, gfx::BoxF(-1.f, dim1, dim1, 2.f, dim2, dim2)}, | |
951 {1.f, 0.f, 1.f, gfx::BoxF(dim1, -1.f, dim1, dim2, 2.f, dim2)}}; | |
952 | |
953 for (size_t i = 0; i < arraysize(tests); ++i) { | |
954 float x = tests[i].x; | |
955 float y = tests[i].y; | |
956 float z = tests[i].z; | |
957 TransformOperations operations_from; | |
958 operations_from.AppendRotate(x, y, z, 0.f); | |
959 TransformOperations operations_to; | |
960 operations_to.AppendRotate(x, y, z, 360.f); | |
961 gfx::BoxF box(1.f, 1.f, 1.f, 0.f, 0.f, 0.f); | |
962 gfx::BoxF bounds; | |
963 | |
964 EXPECT_TRUE(operations_to.BlendedBoundsForBox( | |
965 box, operations_from, 0.f, 1.f, &bounds)); | |
966 EXPECT_EQ(tests[i].expected.ToString(), bounds.ToString()); | |
967 } | |
968 } | |
969 | |
970 static void ExpectBoxesApproximatelyEqual(const gfx::BoxF& lhs, | |
971 const gfx::BoxF& rhs, | |
972 float tolerance) { | |
973 EXPECT_NEAR(lhs.x(), rhs.x(), tolerance); | |
974 EXPECT_NEAR(lhs.y(), rhs.y(), tolerance); | |
975 EXPECT_NEAR(lhs.z(), rhs.z(), tolerance); | |
976 EXPECT_NEAR(lhs.width(), rhs.width(), tolerance); | |
977 EXPECT_NEAR(lhs.height(), rhs.height(), tolerance); | |
978 EXPECT_NEAR(lhs.depth(), rhs.depth(), tolerance); | |
979 } | |
980 | |
981 static void EmpiricallyTestBounds(const TransformOperations& from, | |
982 const TransformOperations& to, | |
983 SkMScalar min_progress, | |
984 SkMScalar max_progress, | |
985 bool test_containment_only) { | |
986 gfx::BoxF box(200.f, 500.f, 100.f, 100.f, 300.f, 200.f); | |
987 gfx::BoxF bounds; | |
988 EXPECT_TRUE( | |
989 to.BlendedBoundsForBox(box, from, min_progress, max_progress, &bounds)); | |
990 | |
991 bool first_time = true; | |
992 gfx::BoxF empirical_bounds; | |
993 static const size_t kNumSteps = 10; | |
994 for (size_t step = 0; step < kNumSteps; ++step) { | |
995 float t = step / (kNumSteps - 1.f); | |
996 t = gfx::Tween::FloatValueBetween(t, min_progress, max_progress); | |
997 gfx::Transform partial_transform = to.Blend(from, t); | |
998 gfx::BoxF transformed = box; | |
999 partial_transform.TransformBox(&transformed); | |
1000 | |
1001 if (first_time) { | |
1002 empirical_bounds = transformed; | |
1003 first_time = false; | |
1004 } else { | |
1005 empirical_bounds.Union(transformed); | |
1006 } | |
1007 } | |
1008 | |
1009 if (test_containment_only) { | |
1010 gfx::BoxF unified_bounds = bounds; | |
1011 unified_bounds.Union(empirical_bounds); | |
1012 // Convert to the screen space rects these boxes represent. | |
1013 gfx::Rect bounds_rect = ToEnclosingRect( | |
1014 gfx::RectF(bounds.x(), bounds.y(), bounds.width(), bounds.height())); | |
1015 gfx::Rect unified_bounds_rect = | |
1016 ToEnclosingRect(gfx::RectF(unified_bounds.x(), | |
1017 unified_bounds.y(), | |
1018 unified_bounds.width(), | |
1019 unified_bounds.height())); | |
1020 EXPECT_EQ(bounds_rect.ToString(), unified_bounds_rect.ToString()); | |
1021 } else { | |
1022 // Our empirical estimate will be a little rough since we're only doing | |
1023 // 100 samples. | |
1024 static const float kTolerance = 1e-2f; | |
1025 ExpectBoxesApproximatelyEqual(empirical_bounds, bounds, kTolerance); | |
1026 } | |
1027 } | |
1028 | |
1029 static void EmpiricallyTestBoundsEquality(const TransformOperations& from, | |
1030 const TransformOperations& to, | |
1031 SkMScalar min_progress, | |
1032 SkMScalar max_progress) { | |
1033 EmpiricallyTestBounds(from, to, min_progress, max_progress, false); | |
1034 } | |
1035 | |
1036 static void EmpiricallyTestBoundsContainment(const TransformOperations& from, | |
1037 const TransformOperations& to, | |
1038 SkMScalar min_progress, | |
1039 SkMScalar max_progress) { | |
1040 EmpiricallyTestBounds(from, to, min_progress, max_progress, true); | |
1041 } | |
1042 | |
1043 TEST(TransformOperationTest, BlendedBoundsForRotationEmpiricalTests) { | |
1044 // Sets up various axis angle combinations, computes the bounding box and | |
1045 // empirically tests that the transformed bounds are indeed contained by the | |
1046 // computed bounding box. | |
1047 | |
1048 struct { | |
1049 float x; | |
1050 float y; | |
1051 float z; | |
1052 } axes[] = {{1.f, 1.f, 1.f}, | |
1053 {-1.f, -1.f, -1.f}, | |
1054 {-1.f, 2.f, 3.f}, | |
1055 {1.f, -2.f, 3.f}, | |
1056 {1.f, 2.f, -3.f}, | |
1057 {0.f, 0.f, 0.f}, | |
1058 {1.f, 0.f, 0.f}, | |
1059 {0.f, 1.f, 0.f}, | |
1060 {0.f, 0.f, 1.f}, | |
1061 {1.f, 1.f, 0.f}, | |
1062 {0.f, 1.f, 1.f}, | |
1063 {1.f, 0.f, 1.f}, | |
1064 {-1.f, 0.f, 0.f}, | |
1065 {0.f, -1.f, 0.f}, | |
1066 {0.f, 0.f, -1.f}, | |
1067 {-1.f, -1.f, 0.f}, | |
1068 {0.f, -1.f, -1.f}, | |
1069 {-1.f, 0.f, -1.f}}; | |
1070 | |
1071 struct { | |
1072 float theta_from; | |
1073 float theta_to; | |
1074 } angles[] = {{5.f, 10.f}, | |
1075 {10.f, 5.f}, | |
1076 {0.f, 360.f}, | |
1077 {20.f, 180.f}, | |
1078 {-20.f, -180.f}, | |
1079 {180.f, -220.f}, | |
1080 {220.f, 320.f}}; | |
1081 | |
1082 // We can go beyond the range [0, 1] (the bezier might slide out of this range | |
1083 // at either end), but since the first and last knots are at (0, 0) and (1, 1) | |
1084 // we will never go within it, so these tests are sufficient. | |
1085 struct { | |
1086 float min_progress; | |
1087 float max_progress; | |
1088 } progress[] = { | |
1089 {0.f, 1.f}, {-.25f, 1.25f}, | |
1090 }; | |
1091 | |
1092 for (size_t i = 0; i < arraysize(axes); ++i) { | |
1093 for (size_t j = 0; j < arraysize(angles); ++j) { | |
1094 for (size_t k = 0; k < arraysize(progress); ++k) { | |
1095 float x = axes[i].x; | |
1096 float y = axes[i].y; | |
1097 float z = axes[i].z; | |
1098 TransformOperations operations_from; | |
1099 operations_from.AppendRotate(x, y, z, angles[j].theta_from); | |
1100 TransformOperations operations_to; | |
1101 operations_to.AppendRotate(x, y, z, angles[j].theta_to); | |
1102 EmpiricallyTestBoundsContainment(operations_from, | |
1103 operations_to, | |
1104 progress[k].min_progress, | |
1105 progress[k].max_progress); | |
1106 } | |
1107 } | |
1108 } | |
1109 } | |
1110 | |
1111 TEST(TransformOperationTest, PerspectiveMatrixAndTransformBlendingEquivalency) { | |
1112 TransformOperations from_operations; | |
1113 from_operations.AppendPerspective(200); | |
1114 | |
1115 TransformOperations to_operations; | |
1116 to_operations.AppendPerspective(1000); | |
1117 | |
1118 gfx::Transform from_transform; | |
1119 from_transform.ApplyPerspectiveDepth(200); | |
1120 | |
1121 gfx::Transform to_transform; | |
1122 to_transform.ApplyPerspectiveDepth(1000); | |
1123 | |
1124 static const int steps = 20; | |
1125 for (int i = 0; i < steps; ++i) { | |
1126 double progress = static_cast<double>(i) / (steps - 1); | |
1127 | |
1128 gfx::Transform blended_matrix = to_transform; | |
1129 EXPECT_TRUE(blended_matrix.Blend(from_transform, progress)); | |
1130 | |
1131 gfx::Transform blended_transform = | |
1132 to_operations.Blend(from_operations, progress); | |
1133 | |
1134 EXPECT_TRANSFORMATION_MATRIX_EQ(blended_matrix, blended_transform); | |
1135 } | |
1136 } | |
1137 | |
1138 TEST(TransformOperationTest, BlendedBoundsForPerspective) { | |
1139 struct { | |
1140 float from_depth; | |
1141 float to_depth; | |
1142 } perspective_depths[] = { | |
1143 {600.f, 400.f}, | |
1144 {800.f, 1000.f}, | |
1145 {800.f, std::numeric_limits<float>::infinity()}, | |
1146 }; | |
1147 | |
1148 struct { | |
1149 float min_progress; | |
1150 float max_progress; | |
1151 } progress[] = { | |
1152 {0.f, 1.f}, {-0.1f, 1.1f}, | |
1153 }; | |
1154 | |
1155 for (size_t i = 0; i < arraysize(perspective_depths); ++i) { | |
1156 for (size_t j = 0; j < arraysize(progress); ++j) { | |
1157 TransformOperations operations_from; | |
1158 operations_from.AppendPerspective(perspective_depths[i].from_depth); | |
1159 TransformOperations operations_to; | |
1160 operations_to.AppendPerspective(perspective_depths[i].to_depth); | |
1161 EmpiricallyTestBoundsEquality(operations_from, | |
1162 operations_to, | |
1163 progress[j].min_progress, | |
1164 progress[j].max_progress); | |
1165 } | |
1166 } | |
1167 } | |
1168 | |
1169 TEST(TransformOperationTest, BlendedBoundsForSkew) { | |
1170 struct { | |
1171 float from_x; | |
1172 float from_y; | |
1173 float to_x; | |
1174 float to_y; | |
1175 } skews[] = { | |
1176 {1.f, 0.5f, 0.5f, 1.f}, {2.f, 1.f, 0.5f, 0.5f}, | |
1177 }; | |
1178 | |
1179 struct { | |
1180 float min_progress; | |
1181 float max_progress; | |
1182 } progress[] = { | |
1183 {0.f, 1.f}, {-0.1f, 1.1f}, | |
1184 }; | |
1185 | |
1186 for (size_t i = 0; i < arraysize(skews); ++i) { | |
1187 for (size_t j = 0; j < arraysize(progress); ++j) { | |
1188 TransformOperations operations_from; | |
1189 operations_from.AppendSkew(skews[i].from_x, skews[i].from_y); | |
1190 TransformOperations operations_to; | |
1191 operations_to.AppendSkew(skews[i].to_x, skews[i].to_y); | |
1192 EmpiricallyTestBoundsEquality(operations_from, | |
1193 operations_to, | |
1194 progress[j].min_progress, | |
1195 progress[j].max_progress); | |
1196 } | |
1197 } | |
1198 } | |
1199 | |
1200 TEST(TransformOperationTest, NonCommutativeRotations) { | |
1201 TransformOperations operations_from; | |
1202 operations_from.AppendRotate(1.0, 0.0, 0.0, 0.0); | |
1203 operations_from.AppendRotate(0.0, 1.0, 0.0, 0.0); | |
1204 TransformOperations operations_to; | |
1205 operations_to.AppendRotate(1.0, 0.0, 0.0, 45.0); | |
1206 operations_to.AppendRotate(0.0, 1.0, 0.0, 135.0); | |
1207 | |
1208 gfx::BoxF box(0, 0, 0, 1, 1, 1); | |
1209 gfx::BoxF bounds; | |
1210 | |
1211 SkMScalar min_progress = 0.0f; | |
1212 SkMScalar max_progress = 1.0f; | |
1213 EXPECT_TRUE(operations_to.BlendedBoundsForBox( | |
1214 box, operations_from, min_progress, max_progress, &bounds)); | |
1215 gfx::Transform blended_transform = | |
1216 operations_to.Blend(operations_from, max_progress); | |
1217 gfx::Point3F blended_point(0.9f, 0.9f, 0.0f); | |
1218 blended_transform.TransformPoint(&blended_point); | |
1219 gfx::BoxF expanded_bounds = bounds; | |
1220 expanded_bounds.ExpandTo(blended_point); | |
1221 EXPECT_EQ(bounds.ToString(), expanded_bounds.ToString()); | |
1222 } | |
1223 | |
1224 TEST(TransformOperationTest, BlendedBoundsForSequence) { | |
1225 TransformOperations operations_from; | |
1226 operations_from.AppendTranslate(1.0, -5.0, 1.0); | |
1227 operations_from.AppendScale(-1.0, 2.0, 3.0); | |
1228 operations_from.AppendTranslate(2.0, 4.0, -1.0); | |
1229 TransformOperations operations_to; | |
1230 operations_to.AppendTranslate(13.0, -1.0, 5.0); | |
1231 operations_to.AppendScale(-3.0, -2.0, 5.0); | |
1232 operations_to.AppendTranslate(6.0, -2.0, 3.0); | |
1233 | |
1234 gfx::BoxF box(1.f, 2.f, 3.f, 4.f, 4.f, 4.f); | |
1235 gfx::BoxF bounds; | |
1236 | |
1237 SkMScalar min_progress = -0.5f; | |
1238 SkMScalar max_progress = 1.5f; | |
1239 EXPECT_TRUE(operations_to.BlendedBoundsForBox( | |
1240 box, operations_from, min_progress, max_progress, &bounds)); | |
1241 EXPECT_EQ(gfx::BoxF(-57.f, -59.f, -1.f, 76.f, 112.f, 80.f).ToString(), | |
1242 bounds.ToString()); | |
1243 | |
1244 min_progress = 0.f; | |
1245 max_progress = 1.f; | |
1246 EXPECT_TRUE(operations_to.BlendedBoundsForBox( | |
1247 box, operations_from, min_progress, max_progress, &bounds)); | |
1248 EXPECT_EQ(gfx::BoxF(-32.f, -25.f, 7.f, 42.f, 44.f, 48.f).ToString(), | |
1249 bounds.ToString()); | |
1250 | |
1251 TransformOperations identity; | |
1252 EXPECT_TRUE(operations_to.BlendedBoundsForBox( | |
1253 box, identity, min_progress, max_progress, &bounds)); | |
1254 EXPECT_EQ(gfx::BoxF(-33.f, -13.f, 3.f, 57.f, 19.f, 52.f).ToString(), | |
1255 bounds.ToString()); | |
1256 | |
1257 EXPECT_TRUE(identity.BlendedBoundsForBox( | |
1258 box, operations_from, min_progress, max_progress, &bounds)); | |
1259 EXPECT_EQ(gfx::BoxF(-7.f, -3.f, 2.f, 15.f, 23.f, 20.f).ToString(), | |
1260 bounds.ToString()); | |
1261 } | |
1262 | |
1263 TEST(TransformOperationTest, AffectsScaleWithSingleOperation) { | |
1264 TransformOperations empty_operations; | |
1265 EXPECT_FALSE(empty_operations.AffectsScale()); | |
1266 | |
1267 TransformOperations identity; | |
1268 identity.AppendIdentity(); | |
1269 EXPECT_FALSE(identity.AffectsScale()); | |
1270 | |
1271 TransformOperations translate; | |
1272 translate.AppendTranslate(1.f, 2.f, 3.f); | |
1273 EXPECT_FALSE(translate.AffectsScale()); | |
1274 | |
1275 TransformOperations rotate; | |
1276 rotate.AppendRotate(1.f, 2.f, 3.f, 4.f); | |
1277 EXPECT_FALSE(rotate.AffectsScale()); | |
1278 | |
1279 TransformOperations scale; | |
1280 scale.AppendScale(1.f, 2.f, 3.f); | |
1281 EXPECT_TRUE(scale.AffectsScale()); | |
1282 | |
1283 TransformOperations skew; | |
1284 skew.AppendSkew(1.f, 2.f); | |
1285 EXPECT_FALSE(skew.AffectsScale()); | |
1286 | |
1287 TransformOperations perspective; | |
1288 perspective.AppendPerspective(1.f); | |
1289 EXPECT_FALSE(perspective.AffectsScale()); | |
1290 | |
1291 TransformOperations identity_matrix; | |
1292 identity_matrix.AppendMatrix(gfx::Transform()); | |
1293 EXPECT_FALSE(identity_matrix.AffectsScale()); | |
1294 | |
1295 TransformOperations translation_matrix; | |
1296 gfx::Transform translation_transform; | |
1297 translation_transform.Translate3d(1.f, 2.f, 3.f); | |
1298 translation_matrix.AppendMatrix(translation_transform); | |
1299 EXPECT_FALSE(translation_matrix.AffectsScale()); | |
1300 | |
1301 TransformOperations scaling_matrix; | |
1302 gfx::Transform scaling_transform; | |
1303 scaling_transform.Scale(2.f, 2.f); | |
1304 scaling_matrix.AppendMatrix(scaling_transform); | |
1305 EXPECT_TRUE(scaling_matrix.AffectsScale()); | |
1306 } | |
1307 | |
1308 TEST(TransformOperationTest, AffectsScaleWithMultipleOperations) { | |
1309 TransformOperations operations1; | |
1310 operations1.AppendSkew(1.f, 2.f); | |
1311 operations1.AppendTranslate(1.f, 2.f, 3.f); | |
1312 operations1.AppendIdentity(); | |
1313 EXPECT_FALSE(operations1.AffectsScale()); | |
1314 | |
1315 TransformOperations operations2; | |
1316 operations2.AppendPerspective(2.f); | |
1317 operations2.AppendScale(1.f, 2.f, 3.f); | |
1318 operations2.AppendTranslate(3.f, 2.f, 1.f); | |
1319 EXPECT_TRUE(operations2.AffectsScale()); | |
1320 } | |
1321 | |
1322 TEST(TransformOperationTest, IsTranslationWithSingleOperation) { | |
1323 TransformOperations empty_operations; | |
1324 EXPECT_TRUE(empty_operations.IsTranslation()); | |
1325 | |
1326 TransformOperations identity; | |
1327 identity.AppendIdentity(); | |
1328 EXPECT_TRUE(identity.IsTranslation()); | |
1329 | |
1330 TransformOperations translate; | |
1331 translate.AppendTranslate(1.f, 2.f, 3.f); | |
1332 EXPECT_TRUE(translate.IsTranslation()); | |
1333 | |
1334 TransformOperations rotate; | |
1335 rotate.AppendRotate(1.f, 2.f, 3.f, 4.f); | |
1336 EXPECT_FALSE(rotate.IsTranslation()); | |
1337 | |
1338 TransformOperations scale; | |
1339 scale.AppendScale(1.f, 2.f, 3.f); | |
1340 EXPECT_FALSE(scale.IsTranslation()); | |
1341 | |
1342 TransformOperations skew; | |
1343 skew.AppendSkew(1.f, 2.f); | |
1344 EXPECT_FALSE(skew.IsTranslation()); | |
1345 | |
1346 TransformOperations perspective; | |
1347 perspective.AppendPerspective(1.f); | |
1348 EXPECT_FALSE(perspective.IsTranslation()); | |
1349 | |
1350 TransformOperations identity_matrix; | |
1351 identity_matrix.AppendMatrix(gfx::Transform()); | |
1352 EXPECT_TRUE(identity_matrix.IsTranslation()); | |
1353 | |
1354 TransformOperations translation_matrix; | |
1355 gfx::Transform translation_transform; | |
1356 translation_transform.Translate3d(1.f, 2.f, 3.f); | |
1357 translation_matrix.AppendMatrix(translation_transform); | |
1358 EXPECT_TRUE(translation_matrix.IsTranslation()); | |
1359 | |
1360 TransformOperations scaling_matrix; | |
1361 gfx::Transform scaling_transform; | |
1362 scaling_transform.Scale(2.f, 2.f); | |
1363 scaling_matrix.AppendMatrix(scaling_transform); | |
1364 EXPECT_FALSE(scaling_matrix.IsTranslation()); | |
1365 } | |
1366 | |
1367 TEST(TransformOperationTest, IsTranslationWithMultipleOperations) { | |
1368 TransformOperations operations1; | |
1369 operations1.AppendSkew(1.f, 2.f); | |
1370 operations1.AppendTranslate(1.f, 2.f, 3.f); | |
1371 operations1.AppendIdentity(); | |
1372 EXPECT_FALSE(operations1.IsTranslation()); | |
1373 | |
1374 TransformOperations operations2; | |
1375 operations2.AppendIdentity(); | |
1376 operations2.AppendTranslate(3.f, 2.f, 1.f); | |
1377 gfx::Transform translation_transform; | |
1378 translation_transform.Translate3d(1.f, 2.f, 3.f); | |
1379 operations2.AppendMatrix(translation_transform); | |
1380 EXPECT_TRUE(operations2.IsTranslation()); | |
1381 } | |
1382 | |
1383 TEST(TransformOperationTest, ScaleComponent) { | |
1384 gfx::Vector3dF scale; | |
1385 | |
1386 // Scale. | |
1387 TransformOperations operations1; | |
1388 operations1.AppendScale(-3.f, 2.f, 5.f); | |
1389 EXPECT_TRUE(operations1.ScaleComponent(&scale)); | |
1390 EXPECT_EQ(gfx::Vector3dF(-3.f, 2.f, 5.f), scale); | |
1391 | |
1392 // Translate + Scale. | |
1393 TransformOperations operations5; | |
1394 operations5.AppendTranslate(1.f, 2.f, 3.f); | |
1395 operations5.AppendScale(2.f, 5.f, 4.f); | |
1396 EXPECT_TRUE(operations5.ScaleComponent(&scale)); | |
1397 EXPECT_EQ(gfx::Vector3dF(2.f, 5.f, 4.f), scale); | |
1398 | |
1399 // Translate + Scale + Matrix with translate. | |
1400 gfx::Transform translation_transform; | |
1401 translation_transform.Translate3d(1.f, 2.f, 3.f); | |
1402 operations5.AppendMatrix(translation_transform); | |
1403 EXPECT_TRUE(operations5.ScaleComponent(&scale)); | |
1404 EXPECT_EQ(gfx::Vector3dF(2.f, 5.f, 4.f), scale); | |
1405 } | |
1406 | |
1407 TEST(TransformOperationTest, ScaleComponentCannotBeComputed) { | |
1408 gfx::Vector3dF scale; | |
1409 | |
1410 // Scale can. | |
1411 TransformOperations operations1; | |
1412 operations1.AppendScale(2.f, 2.f, 2.f); | |
1413 EXPECT_TRUE(operations1.ScaleComponent(&scale)); | |
1414 EXPECT_EQ(gfx::Vector3dF(2.f, 2.f, 2.f), scale); | |
1415 | |
1416 // Translate can. | |
1417 TransformOperations operations2; | |
1418 operations2.AppendTranslate(1.f, 2.f, 3.f); | |
1419 EXPECT_TRUE(operations2.ScaleComponent(&scale)); | |
1420 EXPECT_EQ(gfx::Vector3dF(1.f, 1.f, 1.f), scale); | |
1421 | |
1422 // Scale + translate can. | |
1423 TransformOperations operations3; | |
1424 operations3.AppendScale(2.f, 3.f, 2.f); | |
1425 operations3.AppendTranslate(1.f, 2.f, 3.f); | |
1426 EXPECT_TRUE(operations3.ScaleComponent(&scale)); | |
1427 EXPECT_EQ(gfx::Vector3dF(2.f, 3.f, 2.f), scale); | |
1428 | |
1429 // Two Scales can't. | |
1430 TransformOperations operations4; | |
1431 operations4.AppendScale(2.f, 3.f, 2.f); | |
1432 operations4.AppendScale(3.f, 2.f, 3.f); | |
1433 EXPECT_FALSE(operations4.ScaleComponent(&scale)); | |
1434 | |
1435 // Matrix can't. | |
1436 TransformOperations operations5; | |
1437 operations5.AppendScale(2.f, 2.f, 2.f); | |
1438 gfx::Transform scaling_transform; | |
1439 scaling_transform.Scale(2.f, 2.f); | |
1440 operations5.AppendMatrix(scaling_transform); | |
1441 EXPECT_FALSE(operations5.ScaleComponent(&scale)); | |
1442 | |
1443 // Scale + Rotate can't. | |
1444 TransformOperations operations7; | |
1445 operations7.AppendScale(2.f, 2.f, 2.f); | |
1446 operations7.AppendRotate(1.f, 2.f, 3.f, 4.f); | |
1447 EXPECT_FALSE(operations7.ScaleComponent(&scale)); | |
1448 | |
1449 // Scale + Skew can't. | |
1450 TransformOperations operations9; | |
1451 operations9.AppendScale(2.f, 2.f, 2.f); | |
1452 operations9.AppendSkew(1.f, 2.f); | |
1453 EXPECT_FALSE(operations9.ScaleComponent(&scale)); | |
1454 | |
1455 // Scale + Perspective can't. | |
1456 TransformOperations operations11; | |
1457 operations11.AppendScale(2.f, 2.f, 2.f); | |
1458 operations11.AppendPerspective(1.f); | |
1459 EXPECT_FALSE(operations11.ScaleComponent(&scale)); | |
1460 } | |
1461 | |
1462 } // namespace | |
1463 } // namespace cc | |
OLD | NEW |