Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(817)

Side by Side Diff: webkit/compositor_bindings/web_transformation_matrix_unittest.cc

Issue 12629006: Prepare for removing WebTransformationMatrix from animation APIs (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright 2012 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 #define _USE_MATH_DEFINES
6 #include <math.h>
7
8 #include "testing/gtest/include/gtest/gtest.h"
9 #include "third_party/WebKit/Source/Platform/chromium/public/WebTransformationMa trix.h"
10
11 #define EXPECT_ROW1_EQ(a, b, c, d, matrix) \
12 EXPECT_FLOAT_EQ((a), (matrix).m11()); \
13 EXPECT_FLOAT_EQ((b), (matrix).m21()); \
14 EXPECT_FLOAT_EQ((c), (matrix).m31()); \
15 EXPECT_FLOAT_EQ((d), (matrix).m41());
16
17 #define EXPECT_ROW2_EQ(a, b, c, d, matrix) \
18 EXPECT_FLOAT_EQ((a), (matrix).m12()); \
19 EXPECT_FLOAT_EQ((b), (matrix).m22()); \
20 EXPECT_FLOAT_EQ((c), (matrix).m32()); \
21 EXPECT_FLOAT_EQ((d), (matrix).m42());
22
23 #define EXPECT_ROW3_EQ(a, b, c, d, matrix) \
24 EXPECT_FLOAT_EQ((a), (matrix).m13()); \
25 EXPECT_FLOAT_EQ((b), (matrix).m23()); \
26 EXPECT_FLOAT_EQ((c), (matrix).m33()); \
27 EXPECT_FLOAT_EQ((d), (matrix).m43());
28
29 #define EXPECT_ROW4_EQ(a, b, c, d, matrix) \
30 EXPECT_FLOAT_EQ((a), (matrix).m14()); \
31 EXPECT_FLOAT_EQ((b), (matrix).m24()); \
32 EXPECT_FLOAT_EQ((c), (matrix).m34()); \
33 EXPECT_FLOAT_EQ((d), (matrix).m44());
34
35 #define EXPECT_WEB_TRANSFORMATION_MATRIX_EQ(expected, actual) \
36 EXPECT_FLOAT_EQ((expected).m11(), (actual).m11()); \
37 EXPECT_FLOAT_EQ((expected).m12(), (actual).m12()); \
38 EXPECT_FLOAT_EQ((expected).m13(), (actual).m13()); \
39 EXPECT_FLOAT_EQ((expected).m14(), (actual).m14()); \
40 EXPECT_FLOAT_EQ((expected).m21(), (actual).m21()); \
41 EXPECT_FLOAT_EQ((expected).m22(), (actual).m22()); \
42 EXPECT_FLOAT_EQ((expected).m23(), (actual).m23()); \
43 EXPECT_FLOAT_EQ((expected).m24(), (actual).m24()); \
44 EXPECT_FLOAT_EQ((expected).m31(), (actual).m31()); \
45 EXPECT_FLOAT_EQ((expected).m32(), (actual).m32()); \
46 EXPECT_FLOAT_EQ((expected).m33(), (actual).m33()); \
47 EXPECT_FLOAT_EQ((expected).m34(), (actual).m34()); \
48 EXPECT_FLOAT_EQ((expected).m41(), (actual).m41()); \
49 EXPECT_FLOAT_EQ((expected).m42(), (actual).m42()); \
50 EXPECT_FLOAT_EQ((expected).m43(), (actual).m43()); \
51 EXPECT_FLOAT_EQ((expected).m44(), (actual).m44());
52
53 // Checking float values for equality close to zero is not robust using EXPECT_F LOAT_EQ
54 // (see gtest documentation). So, to verify rotation matrices, we must use a loo ser
55 // absolute error threshold in some places.
56 #define EXPECT_ROW1_NEAR(a, b, c, d, matrix, error_threshold) \
57 EXPECT_NEAR((a), (matrix).m11(), (error_threshold)); \
58 EXPECT_NEAR((b), (matrix).m21(), (error_threshold)); \
59 EXPECT_NEAR((c), (matrix).m31(), (error_threshold)); \
60 EXPECT_NEAR((d), (matrix).m41(), (error_threshold));
61
62 #define EXPECT_ROW2_NEAR(a, b, c, d, matrix, error_threshold) \
63 EXPECT_NEAR((a), (matrix).m12(), (error_threshold)); \
64 EXPECT_NEAR((b), (matrix).m22(), (error_threshold)); \
65 EXPECT_NEAR((c), (matrix).m32(), (error_threshold)); \
66 EXPECT_NEAR((d), (matrix).m42(), (error_threshold));
67
68 #define EXPECT_ROW3_NEAR(a, b, c, d, matrix, error_threshold) \
69 EXPECT_NEAR((a), (matrix).m13(), (error_threshold)); \
70 EXPECT_NEAR((b), (matrix).m23(), (error_threshold)); \
71 EXPECT_NEAR((c), (matrix).m33(), (error_threshold)); \
72 EXPECT_NEAR((d), (matrix).m43(), (error_threshold));
73
74 #define ERROR_THRESHOLD 1e-14
75 #define LOOSE_ERROR_THRESHOLD 1e-7
76
77 using namespace WebKit;
78
79 namespace {
80
81 static void initializeTestMatrix(WebTransformationMatrix& transform) {
82 transform.setM11(10);
83 transform.setM12(11);
84 transform.setM13(12);
85 transform.setM14(13);
86 transform.setM21(14);
87 transform.setM22(15);
88 transform.setM23(16);
89 transform.setM24(17);
90 transform.setM31(18);
91 transform.setM32(19);
92 transform.setM33(20);
93 transform.setM34(21);
94 transform.setM41(22);
95 transform.setM42(23);
96 transform.setM43(24);
97 transform.setM44(25);
98
99 // Sanity check
100 EXPECT_ROW1_EQ(10, 14, 18, 22, transform);
101 EXPECT_ROW2_EQ(11, 15, 19, 23, transform);
102 EXPECT_ROW3_EQ(12, 16, 20, 24, transform);
103 EXPECT_ROW4_EQ(13, 17, 21, 25, transform);
104 }
105
106 static void initializeTestMatrix2(WebTransformationMatrix& transform) {
107 transform.setM11(30);
108 transform.setM12(31);
109 transform.setM13(32);
110 transform.setM14(33);
111 transform.setM21(34);
112 transform.setM22(35);
113 transform.setM23(36);
114 transform.setM24(37);
115 transform.setM31(38);
116 transform.setM32(39);
117 transform.setM33(40);
118 transform.setM34(41);
119 transform.setM41(42);
120 transform.setM42(43);
121 transform.setM43(44);
122 transform.setM44(45);
123
124 // Sanity check
125 EXPECT_ROW1_EQ(30, 34, 38, 42, transform);
126 EXPECT_ROW2_EQ(31, 35, 39, 43, transform);
127 EXPECT_ROW3_EQ(32, 36, 40, 44, transform);
128 EXPECT_ROW4_EQ(33, 37, 41, 45, transform);
129 }
130
131 TEST(WebTransformationMatrixTest, DefaultConstructorCreatesIdentityMatrix) {
132 WebTransformationMatrix A;
133 EXPECT_ROW1_EQ(1, 0, 0, 0, A);
134 EXPECT_ROW2_EQ(0, 1, 0, 0, A);
135 EXPECT_ROW3_EQ(0, 0, 1, 0, A);
136 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
137 EXPECT_TRUE(A.isIdentity());
138 }
139
140 TEST(WebTransformationMatrixTest, ConstructorFor2dElements) {
141 WebTransformationMatrix A(1, 2, 3, 4, 5, 6);
142 EXPECT_ROW1_EQ(1, 3, 0, 5, A);
143 EXPECT_ROW2_EQ(2, 4, 0, 6, A);
144 EXPECT_ROW3_EQ(0, 0, 1, 0, A);
145 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
146 }
147
148 TEST(WebTransformationMatrixTest, ConstructorForAllElements) {
149 WebTransformationMatrix A(
150 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
151 EXPECT_ROW1_EQ(1, 5, 9, 13, A);
152 EXPECT_ROW2_EQ(2, 6, 10, 14, A);
153 EXPECT_ROW3_EQ(3, 7, 11, 15, A);
154 EXPECT_ROW4_EQ(4, 8, 12, 16, A);
155 }
156
157 TEST(WebTransformationMatrixTest, CopyConstructor) {
158 WebTransformationMatrix A;
159 initializeTestMatrix(A);
160
161 // Copy constructor should produce exact same elements as matrix A.
162 WebTransformationMatrix B(A);
163 EXPECT_ROW1_EQ(10, 14, 18, 22, B);
164 EXPECT_ROW2_EQ(11, 15, 19, 23, B);
165 EXPECT_ROW3_EQ(12, 16, 20, 24, B);
166 EXPECT_ROW4_EQ(13, 17, 21, 25, B);
167 }
168
169 TEST(WebTransformationMatrixTest, MatrixInversion) {
170 // Invert a translation
171 WebTransformationMatrix translation;
172 translation.translate3d(2, 3, 4);
173 EXPECT_TRUE(translation.isInvertible());
174
175 WebTransformationMatrix inverse_translation = translation.inverse();
176 EXPECT_ROW1_EQ(1, 0, 0, -2, inverse_translation);
177 EXPECT_ROW2_EQ(0, 1, 0, -3, inverse_translation);
178 EXPECT_ROW3_EQ(0, 0, 1, -4, inverse_translation);
179 EXPECT_ROW4_EQ(0, 0, 0, 1, inverse_translation);
180
181 // Note that inversion should not have changed the original matrix.
182 EXPECT_ROW1_EQ(1, 0, 0, 2, translation);
183 EXPECT_ROW2_EQ(0, 1, 0, 3, translation);
184 EXPECT_ROW3_EQ(0, 0, 1, 4, translation);
185 EXPECT_ROW4_EQ(0, 0, 0, 1, translation);
186
187 // Invert a non-uniform scale
188 WebTransformationMatrix scale;
189 scale.scale3d(4, 10, 100);
190 EXPECT_TRUE(scale.isInvertible());
191
192 WebTransformationMatrix inverse_scale = scale.inverse();
193 EXPECT_ROW1_EQ(0.25, 0, 0, 0, inverse_scale);
194 EXPECT_ROW2_EQ(0, .1f, 0, 0, inverse_scale);
195 EXPECT_ROW3_EQ(0, 0, .01f, 0, inverse_scale);
196 EXPECT_ROW4_EQ(0, 0, 0, 1, inverse_scale);
197
198 // Try to invert a matrix that is not invertible.
199 // The inverse() function should simply return an identity matrix.
200 WebTransformationMatrix not_invertible;
201 not_invertible.setM11(0);
202 not_invertible.setM22(0);
203 not_invertible.setM33(0);
204 not_invertible.setM44(0);
205 EXPECT_FALSE(not_invertible.isInvertible());
206
207 WebTransformationMatrix inverse_of_not_invertible;
208 initializeTestMatrix(
209 inverse_of_not_invertible); // initialize this to something non-identity, to make sure that assignment below actually took place.
210 inverse_of_not_invertible = not_invertible.inverse();
211 EXPECT_TRUE(inverse_of_not_invertible.isIdentity());
212 }
213
214 TEST(WebTransformationMatrixTest, To2DTransform) {
215 WebTransformationMatrix A;
216 initializeTestMatrix(A);
217
218 WebTransformationMatrix B = A.to2dTransform();
219
220 EXPECT_ROW1_EQ(10, 14, 0, 22, B);
221 EXPECT_ROW2_EQ(11, 15, 0, 23, B);
222 EXPECT_ROW3_EQ(0, 0, 1, 0, B);
223 EXPECT_ROW4_EQ(13, 17, 0, 25, B);
224
225 // Note that to2DTransform should not have changed the original matrix.
226 EXPECT_ROW1_EQ(10, 14, 18, 22, A);
227 EXPECT_ROW2_EQ(11, 15, 19, 23, A);
228 EXPECT_ROW3_EQ(12, 16, 20, 24, A);
229 EXPECT_ROW4_EQ(13, 17, 21, 25, A);
230 }
231
232 TEST(WebTransformationMatrixTest, AssignmentOperator) {
233 WebTransformationMatrix A;
234 initializeTestMatrix(A);
235 WebTransformationMatrix B;
236 initializeTestMatrix2(B);
237 WebTransformationMatrix C;
238 initializeTestMatrix2(C);
239 C = B = A;
240
241 // Both B and C should now have been re-assigned to the value of A.
242 EXPECT_ROW1_EQ(10, 14, 18, 22, B);
243 EXPECT_ROW2_EQ(11, 15, 19, 23, B);
244 EXPECT_ROW3_EQ(12, 16, 20, 24, B);
245 EXPECT_ROW4_EQ(13, 17, 21, 25, B);
246
247 EXPECT_ROW1_EQ(10, 14, 18, 22, C);
248 EXPECT_ROW2_EQ(11, 15, 19, 23, C);
249 EXPECT_ROW3_EQ(12, 16, 20, 24, C);
250 EXPECT_ROW4_EQ(13, 17, 21, 25, C);
251 }
252
253 TEST(WebTransformationMatrixTest, EqualsBooleanOperator) {
254 WebTransformationMatrix A;
255 initializeTestMatrix(A);
256
257 WebTransformationMatrix B;
258 initializeTestMatrix(B);
259 EXPECT_TRUE(A == B);
260
261 // Modifying multiple elements should cause equals operator to return false.
262 WebTransformationMatrix C;
263 initializeTestMatrix2(C);
264 EXPECT_FALSE(A == C);
265
266 // Modifying any one individual element should cause equals operator to return false.
267 WebTransformationMatrix D;
268 D = A;
269 D.setM11(0);
270 EXPECT_FALSE(A == D);
271
272 D = A;
273 D.setM12(0);
274 EXPECT_FALSE(A == D);
275
276 D = A;
277 D.setM13(0);
278 EXPECT_FALSE(A == D);
279
280 D = A;
281 D.setM14(0);
282 EXPECT_FALSE(A == D);
283
284 D = A;
285 D.setM21(0);
286 EXPECT_FALSE(A == D);
287
288 D = A;
289 D.setM22(0);
290 EXPECT_FALSE(A == D);
291
292 D = A;
293 D.setM23(0);
294 EXPECT_FALSE(A == D);
295
296 D = A;
297 D.setM24(0);
298 EXPECT_FALSE(A == D);
299
300 D = A;
301 D.setM31(0);
302 EXPECT_FALSE(A == D);
303
304 D = A;
305 D.setM32(0);
306 EXPECT_FALSE(A == D);
307
308 D = A;
309 D.setM33(0);
310 EXPECT_FALSE(A == D);
311
312 D = A;
313 D.setM34(0);
314 EXPECT_FALSE(A == D);
315
316 D = A;
317 D.setM41(0);
318 EXPECT_FALSE(A == D);
319
320 D = A;
321 D.setM42(0);
322 EXPECT_FALSE(A == D);
323
324 D = A;
325 D.setM43(0);
326 EXPECT_FALSE(A == D);
327
328 D = A;
329 D.setM44(0);
330 EXPECT_FALSE(A == D);
331 }
332
333 TEST(WebTransformationMatrixTest, MultiplyOperator) {
334 WebTransformationMatrix A;
335 initializeTestMatrix(A);
336
337 WebTransformationMatrix B;
338 initializeTestMatrix2(B);
339
340 WebTransformationMatrix C = A * B;
341 EXPECT_ROW1_EQ(2036, 2292, 2548, 2804, C);
342 EXPECT_ROW2_EQ(2162, 2434, 2706, 2978, C);
343 EXPECT_ROW3_EQ(2288, 2576, 2864, 3152, C);
344 EXPECT_ROW4_EQ(2414, 2718, 3022, 3326, C);
345
346 // Just an additional sanity check; matrix multiplication is not commutative.
347 EXPECT_FALSE(A * B == B * A);
348 }
349
350 TEST(WebTransformationMatrixTest, MatrixMultiplication) {
351 WebTransformationMatrix A;
352 initializeTestMatrix(A);
353
354 WebTransformationMatrix B;
355 initializeTestMatrix2(B);
356
357 A.multiply(B);
358 EXPECT_ROW1_EQ(2036, 2292, 2548, 2804, A);
359 EXPECT_ROW2_EQ(2162, 2434, 2706, 2978, A);
360 EXPECT_ROW3_EQ(2288, 2576, 2864, 3152, A);
361 EXPECT_ROW4_EQ(2414, 2718, 3022, 3326, A);
362 }
363
364 TEST(WebTransformationMatrixTest, MakeIdentiy) {
365 WebTransformationMatrix A;
366 initializeTestMatrix(A);
367 A.makeIdentity();
368 EXPECT_ROW1_EQ(1, 0, 0, 0, A);
369 EXPECT_ROW2_EQ(0, 1, 0, 0, A);
370 EXPECT_ROW3_EQ(0, 0, 1, 0, A);
371 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
372 EXPECT_TRUE(A.isIdentity());
373 }
374
375 TEST(WebTransformationMatrixTest, Translate) {
376 WebTransformationMatrix A;
377 A.translate(2, 3);
378 EXPECT_ROW1_EQ(1, 0, 0, 2, A);
379 EXPECT_ROW2_EQ(0, 1, 0, 3, A);
380 EXPECT_ROW3_EQ(0, 0, 1, 0, A);
381 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
382
383 // Verify that translate() post-multiplies the existing matrix.
384 A.makeIdentity();
385 A.scale(5);
386 A.translate(2, 3);
387 EXPECT_ROW1_EQ(5, 0, 0, 10, A);
388 EXPECT_ROW2_EQ(0, 5, 0, 15, A);
389 EXPECT_ROW3_EQ(0, 0, 1, 0, A);
390 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
391 }
392
393 TEST(WebTransformationMatrixTest, Translate3d) {
394 WebTransformationMatrix A;
395 A.translate3d(2, 3, 4);
396 EXPECT_ROW1_EQ(1, 0, 0, 2, A);
397 EXPECT_ROW2_EQ(0, 1, 0, 3, A);
398 EXPECT_ROW3_EQ(0, 0, 1, 4, A);
399 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
400
401 // Verify that translate3d() post-multiplies the existing matrix.
402 A.makeIdentity();
403 A.scale3d(6, 7, 8);
404 A.translate3d(2, 3, 4);
405 EXPECT_ROW1_EQ(6, 0, 0, 12, A);
406 EXPECT_ROW2_EQ(0, 7, 0, 21, A);
407 EXPECT_ROW3_EQ(0, 0, 8, 32, A);
408 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
409 }
410
411 TEST(WebTransformationMatrixTest, TranslateRight3d) {
412 WebTransformationMatrix A;
413 A.translateRight3d(2, 3, 4);
414 EXPECT_ROW1_EQ(1, 0, 0, 2, A);
415 EXPECT_ROW2_EQ(0, 1, 0, 3, A);
416 EXPECT_ROW3_EQ(0, 0, 1, 4, A);
417 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
418
419 // Note carefully, all other operations do post-multiply, this one is unique.
420 // Verify that translateRight3d() PRE-multiplies the existing matrix.
421 A.makeIdentity();
422 A.scale3d(6, 7, 8);
423 A.translateRight3d(2, 3, 4);
424 EXPECT_ROW1_EQ(6, 0, 0, 2, A);
425 EXPECT_ROW2_EQ(0, 7, 0, 3, A);
426 EXPECT_ROW3_EQ(0, 0, 8, 4, A);
427 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
428 }
429
430 TEST(WebTransformationMatrixTest, Scale) {
431 WebTransformationMatrix A;
432 A.scale(5);
433 EXPECT_ROW1_EQ(5, 0, 0, 0, A);
434 EXPECT_ROW2_EQ(0, 5, 0, 0, A);
435 EXPECT_ROW3_EQ(0, 0, 1, 0, A);
436 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
437
438 // Verify that scale() post-multiplies the existing matrix.
439 A.makeIdentity();
440 A.translate3d(2, 3, 4);
441 A.scale(5);
442 EXPECT_ROW1_EQ(5, 0, 0, 2, A);
443 EXPECT_ROW2_EQ(0, 5, 0, 3, A);
444 EXPECT_ROW3_EQ(0, 0, 1, 4, A);
445 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
446 }
447
448 TEST(WebTransformationMatrixTest, NonUniformScale) {
449 WebTransformationMatrix A;
450 A.scaleNonUniform(6, 7);
451 EXPECT_ROW1_EQ(6, 0, 0, 0, A);
452 EXPECT_ROW2_EQ(0, 7, 0, 0, A);
453 EXPECT_ROW3_EQ(0, 0, 1, 0, A);
454 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
455
456 // Verify that scaleNonUniform() post-multiplies the existing matrix.
457 A.makeIdentity();
458 A.translate3d(2, 3, 4);
459 A.scaleNonUniform(6, 7);
460 EXPECT_ROW1_EQ(6, 0, 0, 2, A);
461 EXPECT_ROW2_EQ(0, 7, 0, 3, A);
462 EXPECT_ROW3_EQ(0, 0, 1, 4, A);
463 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
464 }
465
466 TEST(WebTransformationMatrixTest, Scale3d) {
467 WebTransformationMatrix A;
468 A.scale3d(6, 7, 8);
469 EXPECT_ROW1_EQ(6, 0, 0, 0, A);
470 EXPECT_ROW2_EQ(0, 7, 0, 0, A);
471 EXPECT_ROW3_EQ(0, 0, 8, 0, A);
472 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
473
474 // Verify that scale3d() post-multiplies the existing matrix.
475 A.makeIdentity();
476 A.translate3d(2, 3, 4);
477 A.scale3d(6, 7, 8);
478 EXPECT_ROW1_EQ(6, 0, 0, 2, A);
479 EXPECT_ROW2_EQ(0, 7, 0, 3, A);
480 EXPECT_ROW3_EQ(0, 0, 8, 4, A);
481 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
482 }
483
484 TEST(WebTransformationMatrixTest, Rotate) {
485 WebTransformationMatrix A;
486 A.rotate(90);
487 EXPECT_ROW1_NEAR(0, -1, 0, 0, A, ERROR_THRESHOLD);
488 EXPECT_ROW2_NEAR(1, 0, 0, 0, A, ERROR_THRESHOLD);
489 EXPECT_ROW3_EQ(0, 0, 1, 0, A);
490 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
491
492 // Verify that rotate() post-multiplies the existing matrix.
493 A.makeIdentity();
494 A.scale3d(6, 7, 8);
495 A.rotate(90);
496 EXPECT_ROW1_NEAR(0, -6, 0, 0, A, ERROR_THRESHOLD);
497 EXPECT_ROW2_NEAR(7, 0, 0, 0, A, ERROR_THRESHOLD);
498 EXPECT_ROW3_EQ(0, 0, 8, 0, A);
499 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
500 }
501
502 TEST(WebTransformationMatrixTest, Rotate3d) {
503 WebTransformationMatrix A;
504
505 // Check rotation about z-axis
506 A.makeIdentity();
507 A.rotate3d(0, 0, 90);
508 EXPECT_ROW1_NEAR(0, -1, 0, 0, A, ERROR_THRESHOLD);
509 EXPECT_ROW2_NEAR(1, 0, 0, 0, A, ERROR_THRESHOLD);
510 EXPECT_ROW3_EQ(0, 0, 1, 0, A);
511 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
512
513 // Check rotation about x-axis
514 A.makeIdentity();
515 A.rotate3d(90, 0, 0);
516 EXPECT_ROW1_EQ(1, 0, 0, 0, A);
517 EXPECT_ROW2_NEAR(0, 0, -1, 0, A, ERROR_THRESHOLD);
518 EXPECT_ROW3_NEAR(0, 1, 0, 0, A, ERROR_THRESHOLD);
519 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
520
521 // Check rotation about y-axis.
522 // Note carefully, the expected pattern is inverted compared to rotating about x axis or z axis.
523 A.makeIdentity();
524 A.rotate3d(0, 90, 0);
525 EXPECT_ROW1_NEAR(0, 0, 1, 0, A, ERROR_THRESHOLD);
526 EXPECT_ROW2_EQ(0, 1, 0, 0, A);
527 EXPECT_ROW3_NEAR(-1, 0, 0, 0, A, ERROR_THRESHOLD);
528 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
529
530 // Verify that rotate3d(rx, ry, rz) post-multiplies the existing matrix.
531 A.makeIdentity();
532 A.scale3d(6, 7, 8);
533 A.rotate3d(0, 0, 90);
534 EXPECT_ROW1_NEAR(0, -6, 0, 0, A, ERROR_THRESHOLD);
535 EXPECT_ROW2_NEAR(7, 0, 0, 0, A, ERROR_THRESHOLD);
536 EXPECT_ROW3_EQ(0, 0, 8, 0, A);
537 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
538 }
539
540 TEST(WebTransformationMatrixTest, Rotate3dOrderOfCompositeRotations) {
541 // Rotate3d(degreesX, degreesY, degreesZ) is actually composite transform cons iting of
542 // three primitive rotations. This test verifies that the ordering of those th ree
543 // transforms is the intended ordering.
544 //
545 // The correct ordering for this test case should be:
546 // 1. rotate by 30 degrees about z-axis
547 // 2. rotate by 20 degrees about y-axis
548 // 3. rotate by 10 degrees about x-axis
549 //
550 // Note: there are 6 possible orderings of 3 transforms. For the specific tran sforms
551 // used in this test, all 6 combinations produce a unique matrix that is diffe rent
552 // from the other orderings. That way, this test verifies the exact ordering.
553
554 WebTransformationMatrix A;
555 A.makeIdentity();
556 A.rotate3d(10, 20, 30);
557
558 EXPECT_ROW1_NEAR(0.8137976813493738026394908,
559 -0.4409696105298823720630708,
560 0.3785223063697923939763257,
561 0,
562 A,
563 ERROR_THRESHOLD);
564 EXPECT_ROW2_NEAR(0.4698463103929541584413698,
565 0.8825641192593856043657752,
566 0.0180283112362972230968694,
567 0,
568 A,
569 ERROR_THRESHOLD);
570 EXPECT_ROW3_NEAR(-0.3420201433256686573969318,
571 0.1631759111665348205288950,
572 0.9254165783983233639631294,
573 0,
574 A,
575 ERROR_THRESHOLD);
576 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
577 }
578
579 TEST(WebTransformationMatrixTest, RotateAxisAngle3d) {
580 WebTransformationMatrix A;
581
582 // Check rotation about z-axis
583 A.makeIdentity();
584 A.rotate3d(0, 0, 1, 90);
585 EXPECT_ROW1_NEAR(0, -1, 0, 0, A, ERROR_THRESHOLD);
586 EXPECT_ROW2_NEAR(1, 0, 0, 0, A, ERROR_THRESHOLD);
587 EXPECT_ROW3_EQ(0, 0, 1, 0, A);
588 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
589
590 // Check rotation about x-axis
591 A.makeIdentity();
592 A.rotate3d(1, 0, 0, 90);
593 EXPECT_ROW1_EQ(1, 0, 0, 0, A);
594 EXPECT_ROW2_NEAR(0, 0, -1, 0, A, ERROR_THRESHOLD);
595 EXPECT_ROW3_NEAR(0, 1, 0, 0, A, ERROR_THRESHOLD);
596 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
597
598 // Check rotation about y-axis.
599 // Note carefully, the expected pattern is inverted compared to rotating about x axis or z axis.
600 A.makeIdentity();
601 A.rotate3d(0, 1, 0, 90);
602 EXPECT_ROW1_NEAR(0, 0, 1, 0, A, ERROR_THRESHOLD);
603 EXPECT_ROW2_EQ(0, 1, 0, 0, A);
604 EXPECT_ROW3_NEAR(-1, 0, 0, 0, A, ERROR_THRESHOLD);
605 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
606
607 // Verify that rotate3d(axis, angle) post-multiplies the existing matrix.
608 A.makeIdentity();
609 A.scale3d(6, 7, 8);
610 A.rotate3d(0, 0, 1, 90);
611 EXPECT_ROW1_NEAR(0, -6, 0, 0, A, ERROR_THRESHOLD);
612 EXPECT_ROW2_NEAR(7, 0, 0, 0, A, ERROR_THRESHOLD);
613 EXPECT_ROW3_EQ(0, 0, 8, 0, A);
614 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
615 }
616
617 TEST(WebTransformationMatrixTest, RotateAxisAngle3dForArbitraryAxis) {
618 // Check rotation about an arbitrary non-axis-aligned vector.
619 WebTransformationMatrix A;
620 A.rotate3d(1, 1, 1, 90);
621 EXPECT_ROW1_NEAR(0.3333333333333334258519187,
622 -0.2440169358562924717404030,
623 0.9106836025229592124219380,
624 0,
625 A,
626 ERROR_THRESHOLD);
627 EXPECT_ROW2_NEAR(0.9106836025229592124219380,
628 0.3333333333333334258519187,
629 -0.2440169358562924717404030,
630 0,
631 A,
632 ERROR_THRESHOLD);
633 EXPECT_ROW3_NEAR(-0.2440169358562924717404030,
634 0.9106836025229592124219380,
635 0.3333333333333334258519187,
636 0,
637 A,
638 ERROR_THRESHOLD);
639 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
640 }
641
642 TEST(WebTransformationMatrixTest, RotateAxisAngle3dForDegenerateAxis) {
643 // Check rotation about a degenerate zero vector.
644 // It is expected to skip applying the rotation.
645 WebTransformationMatrix A;
646
647 A.rotate3d(0, 0, 0, 45);
648 // Verify that A remains unchanged.
649 EXPECT_TRUE(A.isIdentity());
650
651 initializeTestMatrix(A);
652 A.rotate3d(0, 0, 0, 35);
653
654 // Verify that A remains unchanged.
655 EXPECT_ROW1_EQ(10, 14, 18, 22, A);
656 EXPECT_ROW2_EQ(11, 15, 19, 23, A);
657 EXPECT_ROW3_EQ(12, 16, 20, 24, A);
658 EXPECT_ROW4_EQ(13, 17, 21, 25, A);
659 }
660
661 TEST(WebTransformationMatrixTest, SkewX) {
662 WebTransformationMatrix A;
663 A.skewX(45);
664 EXPECT_ROW1_EQ(1, 1, 0, 0, A);
665 EXPECT_ROW2_EQ(0, 1, 0, 0, A);
666 EXPECT_ROW3_EQ(0, 0, 1, 0, A);
667 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
668
669 // Verify that skewX() post-multiplies the existing matrix.
670 // Row 1, column 2, would incorrectly have value "7" if the matrix is pre-mult iplied instead of post-multiplied.
671 A.makeIdentity();
672 A.scale3d(6, 7, 8);
673 A.skewX(45);
674 EXPECT_ROW1_EQ(6, 6, 0, 0, A);
675 EXPECT_ROW2_EQ(0, 7, 0, 0, A);
676 EXPECT_ROW3_EQ(0, 0, 8, 0, A);
677 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
678 }
679
680 TEST(WebTransformationMatrixTest, SkewY) {
681 WebTransformationMatrix A;
682 A.skewY(45);
683 EXPECT_ROW1_EQ(1, 0, 0, 0, A);
684 EXPECT_ROW2_EQ(1, 1, 0, 0, A);
685 EXPECT_ROW3_EQ(0, 0, 1, 0, A);
686 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
687
688 // Verify that skewY() post-multiplies the existing matrix.
689 // Row 2, column 1, would incorrectly have value "6" if the matrix is pre-mult iplied instead of post-multiplied.
690 A.makeIdentity();
691 A.scale3d(6, 7, 8);
692 A.skewY(45);
693 EXPECT_ROW1_EQ(6, 0, 0, 0, A);
694 EXPECT_ROW2_EQ(7, 7, 0, 0, A);
695 EXPECT_ROW3_EQ(0, 0, 8, 0, A);
696 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
697 }
698
699 TEST(WebTransformationMatrixTest, ApplyPerspective) {
700 WebTransformationMatrix A;
701 A.applyPerspective(1);
702 EXPECT_ROW1_EQ(1, 0, 0, 0, A);
703 EXPECT_ROW2_EQ(0, 1, 0, 0, A);
704 EXPECT_ROW3_EQ(0, 0, 1, 0, A);
705 EXPECT_ROW4_EQ(0, 0, -1, 1, A);
706
707 // Verify that applyPerspective() post-multiplies the existing matrix.
708 A.makeIdentity();
709 A.translate3d(2, 3, 4);
710 A.applyPerspective(1);
711 EXPECT_ROW1_EQ(1, 0, -2, 2, A);
712 EXPECT_ROW2_EQ(0, 1, -3, 3, A);
713 EXPECT_ROW3_EQ(0, 0, -3, 4, A);
714 EXPECT_ROW4_EQ(0, 0, -1, 1, A);
715 }
716
717 TEST(WebTransformationMatrixTest, HasPerspective) {
718 WebTransformationMatrix A;
719 A.applyPerspective(1);
720 EXPECT_TRUE(A.hasPerspective());
721
722 A.makeIdentity();
723 A.applyPerspective(0);
724 EXPECT_FALSE(A.hasPerspective());
725
726 A.makeIdentity();
727 A.setM34(-0.3);
728 EXPECT_TRUE(A.hasPerspective());
729
730 // FIXME: WebCore only checkes m34() for perspective, but that is probably
731 // wrong. https://bugs.webkit.org/show_bug.cgi?id=83088. For now, this test
732 // case expects the exact behavior as implemented by WebCore, but this should
733 // probably be changed so that if the entire bottom row is not exactly
734 // (0, 0, 0, 1), then hasPerspective should return true.
735
736 A.makeIdentity();
737 A.setM14(-1);
738 EXPECT_FALSE(A.hasPerspective());
739
740 A.makeIdentity();
741 A.setM24(-1);
742 EXPECT_FALSE(A.hasPerspective());
743
744 A.makeIdentity();
745 A.setM44(0.5);
746 EXPECT_FALSE(A.hasPerspective());
747 }
748
749 TEST(WebTransformationMatrixTest, IsInvertible) {
750 WebTransformationMatrix A;
751
752 // Translations, rotations, scales, skews and arbitrary combinations of them a re invertible.
753 A.makeIdentity();
754 EXPECT_TRUE(A.isInvertible());
755
756 A.makeIdentity();
757 A.translate3d(2, 3, 4);
758 EXPECT_TRUE(A.isInvertible());
759
760 A.makeIdentity();
761 A.scale3d(6, 7, 8);
762 EXPECT_TRUE(A.isInvertible());
763
764 A.makeIdentity();
765 A.rotate3d(10, 20, 30);
766 EXPECT_TRUE(A.isInvertible());
767
768 A.makeIdentity();
769 A.skewX(45);
770 EXPECT_TRUE(A.isInvertible());
771
772 // A perspective matrix (projection plane at z=0) is invertible. The intuitive
773 // explanation is that perspective is eqivalent to a skew of the w-axis; skews are
774 // invertible.
775 A.makeIdentity();
776 A.applyPerspective(1);
777 EXPECT_TRUE(A.isInvertible());
778
779 // A "pure" perspective matrix derived by similar triangles, with m44() set to zero
780 // (i.e. camera positioned at the origin), is not invertible.
781 A.makeIdentity();
782 A.applyPerspective(1);
783 A.setM44(0);
784 EXPECT_FALSE(A.isInvertible());
785
786 // Adding more to a non-invertible matrix will not make it invertible in the g eneral case.
787 A.makeIdentity();
788 A.applyPerspective(1);
789 A.setM44(0);
790 A.scale3d(6, 7, 8);
791 A.rotate3d(10, 20, 30);
792 A.translate3d(6, 7, 8);
793 EXPECT_FALSE(A.isInvertible());
794
795 // A degenerate matrix of all zeros is not invertible.
796 A.makeIdentity();
797 A.setM11(0);
798 A.setM22(0);
799 A.setM33(0);
800 A.setM44(0);
801 EXPECT_FALSE(A.isInvertible());
802 }
803
804 TEST(WebTransformationMatrixTest, IsIdentity) {
805 WebTransformationMatrix A;
806
807 initializeTestMatrix(A);
808 EXPECT_FALSE(A.isIdentity());
809
810 A.makeIdentity();
811 EXPECT_TRUE(A.isIdentity());
812
813 // Modifying any one individual element should cause the matrix to no longer b e identity.
814 A.makeIdentity();
815 A.setM11(2);
816 EXPECT_FALSE(A.isIdentity());
817
818 A.makeIdentity();
819 A.setM12(2);
820 EXPECT_FALSE(A.isIdentity());
821
822 A.makeIdentity();
823 A.setM13(2);
824 EXPECT_FALSE(A.isIdentity());
825
826 A.makeIdentity();
827 A.setM14(2);
828 EXPECT_FALSE(A.isIdentity());
829
830 A.makeIdentity();
831 A.setM21(2);
832 EXPECT_FALSE(A.isIdentity());
833
834 A.makeIdentity();
835 A.setM22(2);
836 EXPECT_FALSE(A.isIdentity());
837
838 A.makeIdentity();
839 A.setM23(2);
840 EXPECT_FALSE(A.isIdentity());
841
842 A.makeIdentity();
843 A.setM24(2);
844 EXPECT_FALSE(A.isIdentity());
845
846 A.makeIdentity();
847 A.setM31(2);
848 EXPECT_FALSE(A.isIdentity());
849
850 A.makeIdentity();
851 A.setM32(2);
852 EXPECT_FALSE(A.isIdentity());
853
854 A.makeIdentity();
855 A.setM33(2);
856 EXPECT_FALSE(A.isIdentity());
857
858 A.makeIdentity();
859 A.setM34(2);
860 EXPECT_FALSE(A.isIdentity());
861
862 A.makeIdentity();
863 A.setM41(2);
864 EXPECT_FALSE(A.isIdentity());
865
866 A.makeIdentity();
867 A.setM42(2);
868 EXPECT_FALSE(A.isIdentity());
869
870 A.makeIdentity();
871 A.setM43(2);
872 EXPECT_FALSE(A.isIdentity());
873
874 A.makeIdentity();
875 A.setM44(2);
876 EXPECT_FALSE(A.isIdentity());
877 }
878
879 TEST(WebTransformationMatrixTest, IsIdentityOrTranslation) {
880 WebTransformationMatrix A;
881
882 initializeTestMatrix(A);
883 EXPECT_FALSE(A.isIdentityOrTranslation());
884
885 A.makeIdentity();
886 EXPECT_TRUE(A.isIdentityOrTranslation());
887
888 // Modifying any non-translation components should cause isIdentityOrTranslati on() to
889 // return false. NOTE: m41(), m42(), and m43() are the translation components, so
890 // modifying them should still return true for isIdentityOrTranslation().
891 A.makeIdentity();
892 A.setM11(2);
893 EXPECT_FALSE(A.isIdentityOrTranslation());
894
895 A.makeIdentity();
896 A.setM12(2);
897 EXPECT_FALSE(A.isIdentityOrTranslation());
898
899 A.makeIdentity();
900 A.setM13(2);
901 EXPECT_FALSE(A.isIdentityOrTranslation());
902
903 A.makeIdentity();
904 A.setM14(2);
905 EXPECT_FALSE(A.isIdentityOrTranslation());
906
907 A.makeIdentity();
908 A.setM21(2);
909 EXPECT_FALSE(A.isIdentityOrTranslation());
910
911 A.makeIdentity();
912 A.setM22(2);
913 EXPECT_FALSE(A.isIdentityOrTranslation());
914
915 A.makeIdentity();
916 A.setM23(2);
917 EXPECT_FALSE(A.isIdentityOrTranslation());
918
919 A.makeIdentity();
920 A.setM24(2);
921 EXPECT_FALSE(A.isIdentityOrTranslation());
922
923 A.makeIdentity();
924 A.setM31(2);
925 EXPECT_FALSE(A.isIdentityOrTranslation());
926
927 A.makeIdentity();
928 A.setM32(2);
929 EXPECT_FALSE(A.isIdentityOrTranslation());
930
931 A.makeIdentity();
932 A.setM33(2);
933 EXPECT_FALSE(A.isIdentityOrTranslation());
934
935 A.makeIdentity();
936 A.setM34(2);
937 EXPECT_FALSE(A.isIdentityOrTranslation());
938
939 // Note carefully - expecting true here.
940 A.makeIdentity();
941 A.setM41(2);
942 EXPECT_TRUE(A.isIdentityOrTranslation());
943
944 // Note carefully - expecting true here.
945 A.makeIdentity();
946 A.setM42(2);
947 EXPECT_TRUE(A.isIdentityOrTranslation());
948
949 // Note carefully - expecting true here.
950 A.makeIdentity();
951 A.setM43(2);
952 EXPECT_TRUE(A.isIdentityOrTranslation());
953
954 A.makeIdentity();
955 A.setM44(2);
956 EXPECT_FALSE(A.isIdentityOrTranslation());
957 }
958
959 TEST(WebTransformationMatrixTest, IsIntegerTranslation) {
960 WebTransformationMatrix A;
961
962 A.makeIdentity();
963 A.translate(2, 3);
964 EXPECT_TRUE(A.isIntegerTranslation());
965
966 A.makeIdentity();
967 A.translate(2, 3);
968 EXPECT_TRUE(A.isIntegerTranslation());
969
970 A.makeIdentity();
971 A.translate(2.00001, 3);
972 EXPECT_FALSE(A.isIntegerTranslation());
973
974 A.makeIdentity();
975 A.translate(2, 2.99999);
976 EXPECT_FALSE(A.isIntegerTranslation());
977
978 // Stacking many integer translations should ideally not accumulate any precis ion error.
979 A.makeIdentity();
980 for (int i = 0; i < 100000; ++i)
981 A.translate(2, 3);
982 EXPECT_TRUE(A.isIntegerTranslation());
983 }
984
985 TEST(WebTransformationMatrixTest, BlendForTranslation) {
986 WebTransformationMatrix from;
987 from.translate3d(100, 200, 100);
988
989 WebTransformationMatrix to;
990
991 to.makeIdentity();
992 to.translate3d(200, 100, 300);
993 to.blend(from, 0);
994 EXPECT_WEB_TRANSFORMATION_MATRIX_EQ(from, to);
995
996 to.makeIdentity();
997 to.translate3d(200, 100, 300);
998 to.blend(from, 0.25);
999 EXPECT_ROW1_EQ(1, 0, 0, 125, to);
1000 EXPECT_ROW2_EQ(0, 1, 0, 175, to);
1001 EXPECT_ROW3_EQ(0, 0, 1, 150, to);
1002 EXPECT_ROW4_EQ(0, 0, 0, 1, to);
1003
1004 to.makeIdentity();
1005 to.translate3d(200, 100, 300);
1006 to.blend(from, 0.5);
1007 EXPECT_ROW1_EQ(1, 0, 0, 150, to);
1008 EXPECT_ROW2_EQ(0, 1, 0, 150, to);
1009 EXPECT_ROW3_EQ(0, 0, 1, 200, to);
1010 EXPECT_ROW4_EQ(0, 0, 0, 1, to);
1011
1012 to.makeIdentity();
1013 to.translate3d(200, 100, 300);
1014 to.blend(from, 1);
1015 EXPECT_ROW1_EQ(1, 0, 0, 200, to);
1016 EXPECT_ROW2_EQ(0, 1, 0, 100, to);
1017 EXPECT_ROW3_EQ(0, 0, 1, 300, to);
1018 EXPECT_ROW4_EQ(0, 0, 0, 1, to);
1019 }
1020
1021 TEST(WebTransformationMatrixTest, BlendForScale) {
1022 WebTransformationMatrix from;
1023 from.scale3d(100, 200, 100);
1024
1025 WebTransformationMatrix to;
1026
1027 to.makeIdentity();
1028 to.scale3d(200, 100, 300);
1029 to.blend(from, 0);
1030 EXPECT_WEB_TRANSFORMATION_MATRIX_EQ(from, to);
1031
1032 to.makeIdentity();
1033 to.scale3d(200, 100, 300);
1034 to.blend(from, 0.25);
1035 EXPECT_ROW1_EQ(125, 0, 0, 0, to);
1036 EXPECT_ROW2_EQ(0, 175, 0, 0, to);
1037 EXPECT_ROW3_EQ(0, 0, 150, 0, to);
1038 EXPECT_ROW4_EQ(0, 0, 0, 1, to);
1039
1040 to.makeIdentity();
1041 to.scale3d(200, 100, 300);
1042 to.blend(from, 0.5);
1043 EXPECT_ROW1_EQ(150, 0, 0, 0, to);
1044 EXPECT_ROW2_EQ(0, 150, 0, 0, to);
1045 EXPECT_ROW3_EQ(0, 0, 200, 0, to);
1046 EXPECT_ROW4_EQ(0, 0, 0, 1, to);
1047
1048 to.makeIdentity();
1049 to.scale3d(200, 100, 300);
1050 to.blend(from, 1);
1051 EXPECT_ROW1_EQ(200, 0, 0, 0, to);
1052 EXPECT_ROW2_EQ(0, 100, 0, 0, to);
1053 EXPECT_ROW3_EQ(0, 0, 300, 0, to);
1054 EXPECT_ROW4_EQ(0, 0, 0, 1, to);
1055 }
1056
1057 TEST(WebTransformationMatrixTest, BlendForSkewX) {
1058 WebTransformationMatrix from;
1059 from.skewX(0);
1060
1061 WebTransformationMatrix to;
1062
1063 to.makeIdentity();
1064 to.skewX(45);
1065 to.blend(from, 0);
1066 EXPECT_WEB_TRANSFORMATION_MATRIX_EQ(from, to);
1067
1068 to.makeIdentity();
1069 to.skewX(45);
1070 to.blend(from, 0.5);
1071 EXPECT_ROW1_EQ(1, 0.5, 0, 0, to);
1072 EXPECT_ROW2_EQ(0, 1, 0, 0, to);
1073 EXPECT_ROW3_EQ(0, 0, 1, 0, to);
1074 EXPECT_ROW4_EQ(0, 0, 0, 1, to);
1075
1076 to.makeIdentity();
1077 to.skewX(45);
1078 to.blend(from, 0.25);
1079 EXPECT_ROW1_EQ(1, 0.25, 0, 0, to);
1080 EXPECT_ROW2_EQ(0, 1, 0, 0, to);
1081 EXPECT_ROW3_EQ(0, 0, 1, 0, to);
1082 EXPECT_ROW4_EQ(0, 0, 0, 1, to);
1083
1084 to.makeIdentity();
1085 to.skewX(45);
1086 to.blend(from, 1);
1087 EXPECT_ROW1_EQ(1, 1, 0, 0, to);
1088 EXPECT_ROW2_EQ(0, 1, 0, 0, to);
1089 EXPECT_ROW3_EQ(0, 0, 1, 0, to);
1090 EXPECT_ROW4_EQ(0, 0, 0, 1, to);
1091 }
1092
1093 TEST(WebTransformationMatrixTest, BlendForSkewY) {
1094 // NOTE CAREFULLY: Decomposition of skew and rotation terms of the matrix is
1095 // inherently underconstrained, and so it does not always compute the original ly
1096 // intended skew parameters. The current implementation uses QR decomposition, which
1097 // decomposes the shear into a rotation + non-uniform scale.
1098 //
1099 // It is unlikely that the decomposition implementation will need to change ve ry
1100 // often, so to get any test coverage, the compromise is to verify the exact m atrix
1101 // that the blend() operation produces.
1102 //
1103 // This problem also potentially exists for skewX, but the current QR decompos ition
1104 // implementation just happens to decompose those test matrices intuitively.
1105
1106 WebTransformationMatrix from;
1107 from.skewY(0);
1108
1109 WebTransformationMatrix to;
1110
1111 to.makeIdentity();
1112 to.skewY(45);
1113 to.blend(from, 0);
1114 EXPECT_WEB_TRANSFORMATION_MATRIX_EQ(from, to);
1115
1116 to.makeIdentity();
1117 to.skewY(45);
1118 to.blend(from, 0.25);
1119 EXPECT_ROW1_NEAR(1.0823489449280947471976333,
1120 0.0464370719145053845178239,
1121 0,
1122 0,
1123 to,
1124 LOOSE_ERROR_THRESHOLD);
1125 EXPECT_ROW2_NEAR(0.2152925909665224513123150,
1126 0.9541702441750861130032035,
1127 0,
1128 0,
1129 to,
1130 LOOSE_ERROR_THRESHOLD);
1131 EXPECT_ROW3_EQ(0, 0, 1, 0, to);
1132 EXPECT_ROW4_EQ(0, 0, 0, 1, to);
1133
1134 to.makeIdentity();
1135 to.skewY(45);
1136 to.blend(from, 0.5);
1137 EXPECT_ROW1_NEAR(1.1152212925809066312865525,
1138 0.0676495144007326631996335,
1139 0,
1140 0,
1141 to,
1142 LOOSE_ERROR_THRESHOLD);
1143 EXPECT_ROW2_NEAR(0.4619397844342648662419037,
1144 0.9519009045724774464858342,
1145 0,
1146 0,
1147 to,
1148 LOOSE_ERROR_THRESHOLD);
1149 EXPECT_ROW3_EQ(0, 0, 1, 0, to);
1150 EXPECT_ROW4_EQ(0, 0, 0, 1, to);
1151
1152 // Unfortunately, this case suffers from uncomfortably large precision error.
1153 to.makeIdentity();
1154 to.skewY(45);
1155 to.blend(from, 1);
1156 EXPECT_ROW1_NEAR(1, 0, 0, 0, to, LOOSE_ERROR_THRESHOLD);
1157 EXPECT_ROW2_NEAR(1, 1, 0, 0, to, LOOSE_ERROR_THRESHOLD);
1158 EXPECT_ROW3_EQ(0, 0, 1, 0, to);
1159 EXPECT_ROW4_EQ(0, 0, 0, 1, to);
1160 }
1161
1162 TEST(WebTransformationMatrixTest, BlendForRotationAboutX) {
1163 // Even though blending uses quaternions, axis-aligned rotations should blend the same
1164 // with quaternions or Euler angles. So we can test rotation blending by compa ring
1165 // against manually specified matrices from Euler angles.
1166
1167 WebTransformationMatrix from;
1168 from.rotate3d(1, 0, 0, 0);
1169
1170 WebTransformationMatrix to;
1171
1172 to.makeIdentity();
1173 to.rotate3d(1, 0, 0, 90);
1174 to.blend(from, 0);
1175 EXPECT_WEB_TRANSFORMATION_MATRIX_EQ(from, to);
1176
1177 double expected_rotation_angle = 22.5 * M_PI / 180.0;
1178 to.makeIdentity();
1179 to.rotate3d(1, 0, 0, 90);
1180 to.blend(from, 0.25);
1181 EXPECT_ROW1_NEAR(1, 0, 0, 0, to, ERROR_THRESHOLD);
1182 EXPECT_ROW2_NEAR(0,
1183 cos(expected_rotation_angle),
1184 -sin(expected_rotation_angle),
1185 0,
1186 to,
1187 ERROR_THRESHOLD);
1188 EXPECT_ROW3_NEAR(0,
1189 sin(expected_rotation_angle),
1190 cos(expected_rotation_angle),
1191 0,
1192 to,
1193 ERROR_THRESHOLD);
1194 EXPECT_ROW4_EQ(0, 0, 0, 1, to);
1195
1196 expected_rotation_angle = 45 * M_PI / 180.0;
1197 to.makeIdentity();
1198 to.rotate3d(1, 0, 0, 90);
1199 to.blend(from, 0.5);
1200 EXPECT_ROW1_NEAR(1, 0, 0, 0, to, ERROR_THRESHOLD);
1201 EXPECT_ROW2_NEAR(0,
1202 cos(expected_rotation_angle),
1203 -sin(expected_rotation_angle),
1204 0,
1205 to,
1206 ERROR_THRESHOLD);
1207 EXPECT_ROW3_NEAR(0,
1208 sin(expected_rotation_angle),
1209 cos(expected_rotation_angle),
1210 0,
1211 to,
1212 ERROR_THRESHOLD);
1213 EXPECT_ROW4_EQ(0, 0, 0, 1, to);
1214
1215 to.makeIdentity();
1216 to.rotate3d(1, 0, 0, 90);
1217 to.blend(from, 1);
1218 EXPECT_ROW1_NEAR(1, 0, 0, 0, to, ERROR_THRESHOLD);
1219 EXPECT_ROW2_NEAR(0, 0, -1, 0, to, ERROR_THRESHOLD);
1220 EXPECT_ROW3_NEAR(0, 1, 0, 0, to, ERROR_THRESHOLD);
1221 EXPECT_ROW4_EQ(0, 0, 0, 1, to);
1222 }
1223
1224 TEST(WebTransformationMatrixTest, BlendForRotationAboutY) {
1225 WebTransformationMatrix from;
1226 from.rotate3d(0, 1, 0, 0);
1227
1228 WebTransformationMatrix to;
1229
1230 to.makeIdentity();
1231 to.rotate3d(0, 1, 0, 90);
1232 to.blend(from, 0);
1233 EXPECT_WEB_TRANSFORMATION_MATRIX_EQ(from, to);
1234
1235 double expected_rotation_angle = 22.5 * M_PI / 180.0;
1236 to.makeIdentity();
1237 to.rotate3d(0, 1, 0, 90);
1238 to.blend(from, 0.25);
1239 EXPECT_ROW1_NEAR(cos(expected_rotation_angle),
1240 0,
1241 sin(expected_rotation_angle),
1242 0,
1243 to,
1244 ERROR_THRESHOLD);
1245 EXPECT_ROW2_NEAR(0, 1, 0, 0, to, ERROR_THRESHOLD);
1246 EXPECT_ROW3_NEAR(-sin(expected_rotation_angle),
1247 0,
1248 cos(expected_rotation_angle),
1249 0,
1250 to,
1251 ERROR_THRESHOLD);
1252 EXPECT_ROW4_EQ(0, 0, 0, 1, to);
1253
1254 expected_rotation_angle = 45 * M_PI / 180.0;
1255 to.makeIdentity();
1256 to.rotate3d(0, 1, 0, 90);
1257 to.blend(from, 0.5);
1258 EXPECT_ROW1_NEAR(cos(expected_rotation_angle),
1259 0,
1260 sin(expected_rotation_angle),
1261 0,
1262 to,
1263 ERROR_THRESHOLD);
1264 EXPECT_ROW2_NEAR(0, 1, 0, 0, to, ERROR_THRESHOLD);
1265 EXPECT_ROW3_NEAR(-sin(expected_rotation_angle),
1266 0,
1267 cos(expected_rotation_angle),
1268 0,
1269 to,
1270 ERROR_THRESHOLD);
1271 EXPECT_ROW4_EQ(0, 0, 0, 1, to);
1272
1273 to.makeIdentity();
1274 to.rotate3d(0, 1, 0, 90);
1275 to.blend(from, 1);
1276 EXPECT_ROW1_NEAR(0, 0, 1, 0, to, ERROR_THRESHOLD);
1277 EXPECT_ROW2_NEAR(0, 1, 0, 0, to, ERROR_THRESHOLD);
1278 EXPECT_ROW3_NEAR(-1, 0, 0, 0, to, ERROR_THRESHOLD);
1279 EXPECT_ROW4_EQ(0, 0, 0, 1, to);
1280 }
1281
1282 TEST(WebTransformationMatrixTest, BlendForRotationAboutZ) {
1283 WebTransformationMatrix from;
1284 from.rotate3d(0, 0, 1, 0);
1285
1286 WebTransformationMatrix to;
1287
1288 to.makeIdentity();
1289 to.rotate3d(0, 0, 1, 90);
1290 to.blend(from, 0);
1291 EXPECT_WEB_TRANSFORMATION_MATRIX_EQ(from, to);
1292
1293 double expected_rotation_angle = 22.5 * M_PI / 180.0;
1294 to.makeIdentity();
1295 to.rotate3d(0, 0, 1, 90);
1296 to.blend(from, 0.25);
1297 EXPECT_ROW1_NEAR(cos(expected_rotation_angle),
1298 -sin(expected_rotation_angle),
1299 0,
1300 0,
1301 to,
1302 ERROR_THRESHOLD);
1303 EXPECT_ROW2_NEAR(sin(expected_rotation_angle),
1304 cos(expected_rotation_angle),
1305 0,
1306 0,
1307 to,
1308 ERROR_THRESHOLD);
1309 EXPECT_ROW3_NEAR(0, 0, 1, 0, to, ERROR_THRESHOLD);
1310 EXPECT_ROW4_EQ(0, 0, 0, 1, to);
1311
1312 expected_rotation_angle = 45 * M_PI / 180.0;
1313 to.makeIdentity();
1314 to.rotate3d(0, 0, 1, 90);
1315 to.blend(from, 0.5);
1316 EXPECT_ROW1_NEAR(cos(expected_rotation_angle),
1317 -sin(expected_rotation_angle),
1318 0,
1319 0,
1320 to,
1321 ERROR_THRESHOLD);
1322 EXPECT_ROW2_NEAR(sin(expected_rotation_angle),
1323 cos(expected_rotation_angle),
1324 0,
1325 0,
1326 to,
1327 ERROR_THRESHOLD);
1328 EXPECT_ROW3_NEAR(0, 0, 1, 0, to, ERROR_THRESHOLD);
1329 EXPECT_ROW4_EQ(0, 0, 0, 1, to);
1330
1331 to.makeIdentity();
1332 to.rotate3d(0, 0, 1, 90);
1333 to.blend(from, 1);
1334 EXPECT_ROW1_NEAR(0, -1, 0, 0, to, ERROR_THRESHOLD);
1335 EXPECT_ROW2_NEAR(1, 0, 0, 0, to, ERROR_THRESHOLD);
1336 EXPECT_ROW3_NEAR(0, 0, 1, 0, to, ERROR_THRESHOLD);
1337 EXPECT_ROW4_EQ(0, 0, 0, 1, to);
1338 }
1339
1340 TEST(WebTransformationMatrixTest, BlendForCompositeTransform) {
1341 // Verify that the blending was done with a decomposition in correct order by blending
1342 // a composite transform.
1343 // Using matrix x vector notation (Ax = b, where x is column vector), the orde ring should be:
1344 // perspective * translation * rotation * skew * scale
1345 //
1346 // It is not as important (or meaningful) to check intermediate interpolations ; order
1347 // of operations will be tested well enough by the end cases that are easier t o
1348 // specify.
1349
1350 WebTransformationMatrix from;
1351 WebTransformationMatrix to;
1352
1353 WebTransformationMatrix expected_end_of_animation;
1354 expected_end_of_animation.applyPerspective(1);
1355 expected_end_of_animation.translate3d(10, 20, 30);
1356 expected_end_of_animation.rotate3d(0, 0, 1, 25);
1357 expected_end_of_animation.skewY(45);
1358 expected_end_of_animation.scale3d(6, 7, 8);
1359
1360 to = expected_end_of_animation;
1361 to.blend(from, 0);
1362 EXPECT_WEB_TRANSFORMATION_MATRIX_EQ(from, to);
1363
1364 to = expected_end_of_animation;
1365 to.blend(from, 1);
1366
1367 // Recomposing the matrix results in a normalized matrix, so to verify we need to
1368 // normalize the expected_end_of_animation before comparing elements. Normaliz ing means
1369 // dividing everything by expected_end_of_animation.m44().
1370 WebTransformationMatrix normalized_expected_end_of_animation =
1371 expected_end_of_animation;
1372 WebTransformationMatrix normalization_matrix;
1373 normalization_matrix.setM11(1 / expected_end_of_animation.m44());
1374 normalization_matrix.setM22(1 / expected_end_of_animation.m44());
1375 normalization_matrix.setM33(1 / expected_end_of_animation.m44());
1376 normalization_matrix.setM44(1 / expected_end_of_animation.m44());
1377 normalized_expected_end_of_animation.multiply(normalization_matrix);
1378
1379 EXPECT_WEB_TRANSFORMATION_MATRIX_EQ(normalized_expected_end_of_animation, to);
1380 }
1381
1382 } // namespace
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698