Fix build break
[chromium-blink-merge.git] / ui / gfx / transform_unittest.cc
bloba4985fb8410af23e269a391a62b88b031070c4af
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 // MSVC++ requires this to be set before any other includes to get M_PI.
6 #define _USE_MATH_DEFINES
8 #include "ui/gfx/transform.h"
10 #include <cmath>
11 #include <ostream>
12 #include <limits>
14 #include "base/basictypes.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16 #include "ui/gfx/point.h"
17 #include "ui/gfx/point3_f.h"
18 #include "ui/gfx/transform_util.h"
19 #include "ui/gfx/vector3d_f.h"
21 namespace gfx {
23 namespace {
25 #define EXPECT_ROW1_EQ(a, b, c, d, transform) \
26 EXPECT_FLOAT_EQ((a), (transform).matrix().get(0, 0)); \
27 EXPECT_FLOAT_EQ((b), (transform).matrix().get(0, 1)); \
28 EXPECT_FLOAT_EQ((c), (transform).matrix().get(0, 2)); \
29 EXPECT_FLOAT_EQ((d), (transform).matrix().get(0, 3));
31 #define EXPECT_ROW2_EQ(a, b, c, d, transform) \
32 EXPECT_FLOAT_EQ((a), (transform).matrix().get(1, 0)); \
33 EXPECT_FLOAT_EQ((b), (transform).matrix().get(1, 1)); \
34 EXPECT_FLOAT_EQ((c), (transform).matrix().get(1, 2)); \
35 EXPECT_FLOAT_EQ((d), (transform).matrix().get(1, 3));
37 #define EXPECT_ROW3_EQ(a, b, c, d, transform) \
38 EXPECT_FLOAT_EQ((a), (transform).matrix().get(2, 0)); \
39 EXPECT_FLOAT_EQ((b), (transform).matrix().get(2, 1)); \
40 EXPECT_FLOAT_EQ((c), (transform).matrix().get(2, 2)); \
41 EXPECT_FLOAT_EQ((d), (transform).matrix().get(2, 3));
43 #define EXPECT_ROW4_EQ(a, b, c, d, transform) \
44 EXPECT_FLOAT_EQ((a), (transform).matrix().get(3, 0)); \
45 EXPECT_FLOAT_EQ((b), (transform).matrix().get(3, 1)); \
46 EXPECT_FLOAT_EQ((c), (transform).matrix().get(3, 2)); \
47 EXPECT_FLOAT_EQ((d), (transform).matrix().get(3, 3)); \
49 // Checking float values for equality close to zero is not robust using
50 // EXPECT_FLOAT_EQ (see gtest documentation). So, to verify rotation matrices,
51 // we must use a looser absolute error threshold in some places.
52 #define EXPECT_ROW1_NEAR(a, b, c, d, transform, errorThreshold) \
53 EXPECT_NEAR((a), (transform).matrix().get(0, 0), (errorThreshold)); \
54 EXPECT_NEAR((b), (transform).matrix().get(0, 1), (errorThreshold)); \
55 EXPECT_NEAR((c), (transform).matrix().get(0, 2), (errorThreshold)); \
56 EXPECT_NEAR((d), (transform).matrix().get(0, 3), (errorThreshold));
58 #define EXPECT_ROW2_NEAR(a, b, c, d, transform, errorThreshold) \
59 EXPECT_NEAR((a), (transform).matrix().get(1, 0), (errorThreshold)); \
60 EXPECT_NEAR((b), (transform).matrix().get(1, 1), (errorThreshold)); \
61 EXPECT_NEAR((c), (transform).matrix().get(1, 2), (errorThreshold)); \
62 EXPECT_NEAR((d), (transform).matrix().get(1, 3), (errorThreshold));
64 #define EXPECT_ROW3_NEAR(a, b, c, d, transform, errorThreshold) \
65 EXPECT_NEAR((a), (transform).matrix().get(2, 0), (errorThreshold)); \
66 EXPECT_NEAR((b), (transform).matrix().get(2, 1), (errorThreshold)); \
67 EXPECT_NEAR((c), (transform).matrix().get(2, 2), (errorThreshold)); \
68 EXPECT_NEAR((d), (transform).matrix().get(2, 3), (errorThreshold));
70 bool PointsAreNearlyEqual(const Point3F& lhs,
71 const Point3F& rhs) {
72 float epsilon = 0.0001f;
73 return lhs.SquaredDistanceTo(rhs) < epsilon;
76 bool MatricesAreNearlyEqual(const Transform& lhs,
77 const Transform& rhs) {
78 float epsilon = 0.0001f;
79 for (int row = 0; row < 4; ++row) {
80 for (int col = 0; col < 4; ++col) {
81 if (std::abs(lhs.matrix().get(row, col) -
82 rhs.matrix().get(row, col)) > epsilon)
83 return false;
86 return true;
89 void InitializeTestMatrix(Transform* transform) {
90 SkMatrix44& matrix = transform->matrix();
91 matrix.setDouble(0, 0, 10.0);
92 matrix.setDouble(1, 0, 11.0);
93 matrix.setDouble(2, 0, 12.0);
94 matrix.setDouble(3, 0, 13.0);
95 matrix.setDouble(0, 1, 14.0);
96 matrix.setDouble(1, 1, 15.0);
97 matrix.setDouble(2, 1, 16.0);
98 matrix.setDouble(3, 1, 17.0);
99 matrix.setDouble(0, 2, 18.0);
100 matrix.setDouble(1, 2, 19.0);
101 matrix.setDouble(2, 2, 20.0);
102 matrix.setDouble(3, 2, 21.0);
103 matrix.setDouble(0, 3, 22.0);
104 matrix.setDouble(1, 3, 23.0);
105 matrix.setDouble(2, 3, 24.0);
106 matrix.setDouble(3, 3, 25.0);
108 // Sanity check
109 EXPECT_ROW1_EQ(10.0f, 14.0f, 18.0f, 22.0f, (*transform));
110 EXPECT_ROW2_EQ(11.0f, 15.0f, 19.0f, 23.0f, (*transform));
111 EXPECT_ROW3_EQ(12.0f, 16.0f, 20.0f, 24.0f, (*transform));
112 EXPECT_ROW4_EQ(13.0f, 17.0f, 21.0f, 25.0f, (*transform));
115 void InitializeTestMatrix2(Transform* transform) {
116 SkMatrix44& matrix = transform->matrix();
117 matrix.setDouble(0, 0, 30.0);
118 matrix.setDouble(1, 0, 31.0);
119 matrix.setDouble(2, 0, 32.0);
120 matrix.setDouble(3, 0, 33.0);
121 matrix.setDouble(0, 1, 34.0);
122 matrix.setDouble(1, 1, 35.0);
123 matrix.setDouble(2, 1, 36.0);
124 matrix.setDouble(3, 1, 37.0);
125 matrix.setDouble(0, 2, 38.0);
126 matrix.setDouble(1, 2, 39.0);
127 matrix.setDouble(2, 2, 40.0);
128 matrix.setDouble(3, 2, 41.0);
129 matrix.setDouble(0, 3, 42.0);
130 matrix.setDouble(1, 3, 43.0);
131 matrix.setDouble(2, 3, 44.0);
132 matrix.setDouble(3, 3, 45.0);
134 // Sanity check
135 EXPECT_ROW1_EQ(30.0f, 34.0f, 38.0f, 42.0f, (*transform));
136 EXPECT_ROW2_EQ(31.0f, 35.0f, 39.0f, 43.0f, (*transform));
137 EXPECT_ROW3_EQ(32.0f, 36.0f, 40.0f, 44.0f, (*transform));
138 EXPECT_ROW4_EQ(33.0f, 37.0f, 41.0f, 45.0f, (*transform));
141 #ifdef SK_MSCALAR_IS_DOUBLE
142 #define ERROR_THRESHOLD 1e-14
143 #else
144 #define ERROR_THRESHOLD 1e-7
145 #endif
146 #define LOOSE_ERROR_THRESHOLD 1e-7
148 TEST(XFormTest, Equality) {
149 Transform lhs, rhs, interpolated;
150 rhs.matrix().set3x3(1, 2, 3,
151 4, 5, 6,
152 7, 8, 9);
153 interpolated = lhs;
154 for (int i = 0; i <= 100; ++i) {
155 for (int row = 0; row < 4; ++row) {
156 for (int col = 0; col < 4; ++col) {
157 float a = lhs.matrix().get(row, col);
158 float b = rhs.matrix().get(row, col);
159 float t = i / 100.0f;
160 interpolated.matrix().set(row, col, a + (b - a) * t);
163 if (i == 100) {
164 EXPECT_TRUE(rhs == interpolated);
165 } else {
166 EXPECT_TRUE(rhs != interpolated);
169 lhs = Transform();
170 rhs = Transform();
171 for (int i = 1; i < 100; ++i) {
172 lhs.MakeIdentity();
173 rhs.MakeIdentity();
174 lhs.Translate(i, i);
175 rhs.Translate(-i, -i);
176 EXPECT_TRUE(lhs != rhs);
177 rhs.Translate(2*i, 2*i);
178 EXPECT_TRUE(lhs == rhs);
182 TEST(XFormTest, ConcatTranslate) {
183 static const struct TestCase {
184 int x1;
185 int y1;
186 float tx;
187 float ty;
188 int x2;
189 int y2;
190 } test_cases[] = {
191 { 0, 0, 10.0f, 20.0f, 10, 20 },
192 { 0, 0, -10.0f, -20.0f, 0, 0 },
193 { 0, 0, -10.0f, -20.0f, -10, -20 },
194 { 0, 0,
195 std::numeric_limits<float>::quiet_NaN(),
196 std::numeric_limits<float>::quiet_NaN(),
197 10, 20 },
200 Transform xform;
201 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
202 const TestCase& value = test_cases[i];
203 Transform translation;
204 translation.Translate(value.tx, value.ty);
205 xform = translation * xform;
206 Point3F p1(value.x1, value.y1, 0);
207 Point3F p2(value.x2, value.y2, 0);
208 xform.TransformPoint(p1);
209 if (value.tx == value.tx &&
210 value.ty == value.ty) {
211 EXPECT_TRUE(PointsAreNearlyEqual(p1, p2));
216 TEST(XFormTest, ConcatScale) {
217 static const struct TestCase {
218 int before;
219 float scale;
220 int after;
221 } test_cases[] = {
222 { 1, 10.0f, 10 },
223 { 1, .1f, 1 },
224 { 1, 100.0f, 100 },
225 { 1, -1.0f, -100 },
226 { 1, std::numeric_limits<float>::quiet_NaN(), 1 }
229 Transform xform;
230 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
231 const TestCase& value = test_cases[i];
232 Transform scale;
233 scale.Scale(value.scale, value.scale);
234 xform = scale * xform;
235 Point3F p1(value.before, value.before, 0);
236 Point3F p2(value.after, value.after, 0);
237 xform.TransformPoint(p1);
238 if (value.scale == value.scale) {
239 EXPECT_TRUE(PointsAreNearlyEqual(p1, p2));
244 TEST(XFormTest, ConcatRotate) {
245 static const struct TestCase {
246 int x1;
247 int y1;
248 float degrees;
249 int x2;
250 int y2;
251 } test_cases[] = {
252 { 1, 0, 90.0f, 0, 1 },
253 { 1, 0, -90.0f, 1, 0 },
254 { 1, 0, 90.0f, 0, 1 },
255 { 1, 0, 360.0f, 0, 1 },
256 { 1, 0, 0.0f, 0, 1 },
257 { 1, 0, std::numeric_limits<float>::quiet_NaN(), 1, 0 }
260 Transform xform;
261 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
262 const TestCase& value = test_cases[i];
263 Transform rotation;
264 rotation.Rotate(value.degrees);
265 xform = rotation * xform;
266 Point3F p1(value.x1, value.y1, 0);
267 Point3F p2(value.x2, value.y2, 0);
268 xform.TransformPoint(p1);
269 if (value.degrees == value.degrees) {
270 EXPECT_TRUE(PointsAreNearlyEqual(p1, p2));
275 TEST(XFormTest, SetTranslate) {
276 static const struct TestCase {
277 int x1; int y1;
278 float tx; float ty;
279 int x2; int y2;
280 } test_cases[] = {
281 { 0, 0, 10.0f, 20.0f, 10, 20 },
282 { 10, 20, 10.0f, 20.0f, 20, 40 },
283 { 10, 20, 0.0f, 0.0f, 10, 20 },
284 { 0, 0,
285 std::numeric_limits<float>::quiet_NaN(),
286 std::numeric_limits<float>::quiet_NaN(),
287 0, 0 }
290 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
291 const TestCase& value = test_cases[i];
292 for (int k = 0; k < 3; ++k) {
293 Point3F p0, p1, p2;
294 Transform xform;
295 switch (k) {
296 case 0:
297 p1.SetPoint(value.x1, 0, 0);
298 p2.SetPoint(value.x2, 0, 0);
299 xform.Translate(value.tx, 0.0);
300 break;
301 case 1:
302 p1.SetPoint(0, value.y1, 0);
303 p2.SetPoint(0, value.y2, 0);
304 xform.Translate(0.0, value.ty);
305 break;
306 case 2:
307 p1.SetPoint(value.x1, value.y1, 0);
308 p2.SetPoint(value.x2, value.y2, 0);
309 xform.Translate(value.tx, value.ty);
310 break;
312 p0 = p1;
313 xform.TransformPoint(p1);
314 if (value.tx == value.tx &&
315 value.ty == value.ty) {
316 EXPECT_TRUE(PointsAreNearlyEqual(p1, p2));
317 xform.TransformPointReverse(p1);
318 EXPECT_TRUE(PointsAreNearlyEqual(p1, p0));
324 TEST(XFormTest, SetScale) {
325 static const struct TestCase {
326 int before;
327 float s;
328 int after;
329 } test_cases[] = {
330 { 1, 10.0f, 10 },
331 { 1, 1.0f, 1 },
332 { 1, 0.0f, 0 },
333 { 0, 10.0f, 0 },
334 { 1, std::numeric_limits<float>::quiet_NaN(), 0 },
337 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
338 const TestCase& value = test_cases[i];
339 for (int k = 0; k < 3; ++k) {
340 Point3F p0, p1, p2;
341 Transform xform;
342 switch (k) {
343 case 0:
344 p1.SetPoint(value.before, 0, 0);
345 p2.SetPoint(value.after, 0, 0);
346 xform.Scale(value.s, 1.0);
347 break;
348 case 1:
349 p1.SetPoint(0, value.before, 0);
350 p2.SetPoint(0, value.after, 0);
351 xform.Scale(1.0, value.s);
352 break;
353 case 2:
354 p1.SetPoint(value.before, value.before, 0);
355 p2.SetPoint(value.after, value.after, 0);
356 xform.Scale(value.s, value.s);
357 break;
359 p0 = p1;
360 xform.TransformPoint(p1);
361 if (value.s == value.s) {
362 EXPECT_TRUE(PointsAreNearlyEqual(p1, p2));
363 if (value.s != 0.0f) {
364 xform.TransformPointReverse(p1);
365 EXPECT_TRUE(PointsAreNearlyEqual(p1, p0));
372 TEST(XFormTest, SetRotate) {
373 static const struct SetRotateCase {
374 int x;
375 int y;
376 float degree;
377 int xprime;
378 int yprime;
379 } set_rotate_cases[] = {
380 { 100, 0, 90.0f, 0, 100 },
381 { 0, 0, 90.0f, 0, 0 },
382 { 0, 100, 90.0f, -100, 0 },
383 { 0, 1, -90.0f, 1, 0 },
384 { 100, 0, 0.0f, 100, 0 },
385 { 0, 0, 0.0f, 0, 0 },
386 { 0, 0, std::numeric_limits<float>::quiet_NaN(), 0, 0 },
387 { 100, 0, 360.0f, 100, 0 }
390 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(set_rotate_cases); ++i) {
391 const SetRotateCase& value = set_rotate_cases[i];
392 Point3F p0;
393 Point3F p1(value.x, value.y, 0);
394 Point3F p2(value.xprime, value.yprime, 0);
395 p0 = p1;
396 Transform xform;
397 xform.Rotate(value.degree);
398 // just want to make sure that we don't crash in the case of NaN.
399 if (value.degree == value.degree) {
400 xform.TransformPoint(p1);
401 EXPECT_TRUE(PointsAreNearlyEqual(p1, p2));
402 xform.TransformPointReverse(p1);
403 EXPECT_TRUE(PointsAreNearlyEqual(p1, p0));
408 // 2D tests
409 TEST(XFormTest, ConcatTranslate2D) {
410 static const struct TestCase {
411 int x1;
412 int y1;
413 float tx;
414 float ty;
415 int x2;
416 int y2;
417 } test_cases[] = {
418 { 0, 0, 10.0f, 20.0f, 10, 20},
419 { 0, 0, -10.0f, -20.0f, 0, 0},
420 { 0, 0, -10.0f, -20.0f, -10, -20},
421 { 0, 0,
422 std::numeric_limits<float>::quiet_NaN(),
423 std::numeric_limits<float>::quiet_NaN(),
424 10, 20},
427 Transform xform;
428 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
429 const TestCase& value = test_cases[i];
430 Transform translation;
431 translation.Translate(value.tx, value.ty);
432 xform = translation * xform;
433 Point p1(value.x1, value.y1);
434 Point p2(value.x2, value.y2);
435 xform.TransformPoint(p1);
436 if (value.tx == value.tx &&
437 value.ty == value.ty) {
438 EXPECT_EQ(p1.x(), p2.x());
439 EXPECT_EQ(p1.y(), p2.y());
444 TEST(XFormTest, ConcatScale2D) {
445 static const struct TestCase {
446 int before;
447 float scale;
448 int after;
449 } test_cases[] = {
450 { 1, 10.0f, 10},
451 { 1, .1f, 1},
452 { 1, 100.0f, 100},
453 { 1, -1.0f, -100},
454 { 1, std::numeric_limits<float>::quiet_NaN(), 1}
457 Transform xform;
458 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
459 const TestCase& value = test_cases[i];
460 Transform scale;
461 scale.Scale(value.scale, value.scale);
462 xform = scale * xform;
463 Point p1(value.before, value.before);
464 Point p2(value.after, value.after);
465 xform.TransformPoint(p1);
466 if (value.scale == value.scale) {
467 EXPECT_EQ(p1.x(), p2.x());
468 EXPECT_EQ(p1.y(), p2.y());
473 TEST(XFormTest, ConcatRotate2D) {
474 static const struct TestCase {
475 int x1;
476 int y1;
477 float degrees;
478 int x2;
479 int y2;
480 } test_cases[] = {
481 { 1, 0, 90.0f, 0, 1},
482 { 1, 0, -90.0f, 1, 0},
483 { 1, 0, 90.0f, 0, 1},
484 { 1, 0, 360.0f, 0, 1},
485 { 1, 0, 0.0f, 0, 1},
486 { 1, 0, std::numeric_limits<float>::quiet_NaN(), 1, 0}
489 Transform xform;
490 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
491 const TestCase& value = test_cases[i];
492 Transform rotation;
493 rotation.Rotate(value.degrees);
494 xform = rotation * xform;
495 Point p1(value.x1, value.y1);
496 Point p2(value.x2, value.y2);
497 xform.TransformPoint(p1);
498 if (value.degrees == value.degrees) {
499 EXPECT_EQ(p1.x(), p2.x());
500 EXPECT_EQ(p1.y(), p2.y());
505 TEST(XFormTest, SetTranslate2D) {
506 static const struct TestCase {
507 int x1; int y1;
508 float tx; float ty;
509 int x2; int y2;
510 } test_cases[] = {
511 { 0, 0, 10.0f, 20.0f, 10, 20},
512 { 10, 20, 10.0f, 20.0f, 20, 40},
513 { 10, 20, 0.0f, 0.0f, 10, 20},
514 { 0, 0,
515 std::numeric_limits<float>::quiet_NaN(),
516 std::numeric_limits<float>::quiet_NaN(),
517 0, 0}
520 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
521 const TestCase& value = test_cases[i];
522 for (int j = -1; j < 2; ++j) {
523 for (int k = 0; k < 3; ++k) {
524 float epsilon = 0.0001f;
525 Point p0, p1, p2;
526 Transform xform;
527 switch (k) {
528 case 0:
529 p1.SetPoint(value.x1, 0);
530 p2.SetPoint(value.x2, 0);
531 xform.Translate(value.tx + j * epsilon, 0.0);
532 break;
533 case 1:
534 p1.SetPoint(0, value.y1);
535 p2.SetPoint(0, value.y2);
536 xform.Translate(0.0, value.ty + j * epsilon);
537 break;
538 case 2:
539 p1.SetPoint(value.x1, value.y1);
540 p2.SetPoint(value.x2, value.y2);
541 xform.Translate(value.tx + j * epsilon,
542 value.ty + j * epsilon);
543 break;
545 p0 = p1;
546 xform.TransformPoint(p1);
547 if (value.tx == value.tx &&
548 value.ty == value.ty) {
549 EXPECT_EQ(p1.x(), p2.x());
550 EXPECT_EQ(p1.y(), p2.y());
551 xform.TransformPointReverse(p1);
552 EXPECT_EQ(p1.x(), p0.x());
553 EXPECT_EQ(p1.y(), p0.y());
560 TEST(XFormTest, SetScale2D) {
561 static const struct TestCase {
562 int before;
563 float s;
564 int after;
565 } test_cases[] = {
566 { 1, 10.0f, 10},
567 { 1, 1.0f, 1},
568 { 1, 0.0f, 0},
569 { 0, 10.0f, 0},
570 { 1, std::numeric_limits<float>::quiet_NaN(), 0},
573 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
574 const TestCase& value = test_cases[i];
575 for (int j = -1; j < 2; ++j) {
576 for (int k = 0; k < 3; ++k) {
577 float epsilon = 0.0001f;
578 Point p0, p1, p2;
579 Transform xform;
580 switch (k) {
581 case 0:
582 p1.SetPoint(value.before, 0);
583 p2.SetPoint(value.after, 0);
584 xform.Scale(value.s + j * epsilon, 1.0);
585 break;
586 case 1:
587 p1.SetPoint(0, value.before);
588 p2.SetPoint(0, value.after);
589 xform.Scale(1.0, value.s + j * epsilon);
590 break;
591 case 2:
592 p1.SetPoint(value.before,
593 value.before);
594 p2.SetPoint(value.after,
595 value.after);
596 xform.Scale(value.s + j * epsilon,
597 value.s + j * epsilon);
598 break;
600 p0 = p1;
601 xform.TransformPoint(p1);
602 if (value.s == value.s) {
603 EXPECT_EQ(p1.x(), p2.x());
604 EXPECT_EQ(p1.y(), p2.y());
605 if (value.s != 0.0f) {
606 xform.TransformPointReverse(p1);
607 EXPECT_EQ(p1.x(), p0.x());
608 EXPECT_EQ(p1.y(), p0.y());
616 TEST(XFormTest, SetRotate2D) {
617 static const struct SetRotateCase {
618 int x;
619 int y;
620 float degree;
621 int xprime;
622 int yprime;
623 } set_rotate_cases[] = {
624 { 100, 0, 90.0f, 0, 100},
625 { 0, 0, 90.0f, 0, 0},
626 { 0, 100, 90.0f, -100, 0},
627 { 0, 1, -90.0f, 1, 0},
628 { 100, 0, 0.0f, 100, 0},
629 { 0, 0, 0.0f, 0, 0},
630 { 0, 0, std::numeric_limits<float>::quiet_NaN(), 0, 0},
631 { 100, 0, 360.0f, 100, 0}
634 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(set_rotate_cases); ++i) {
635 const SetRotateCase& value = set_rotate_cases[i];
636 for (int j = 1; j >= -1; --j) {
637 float epsilon = 0.1f;
638 Point pt(value.x, value.y);
639 Transform xform;
640 // should be invariant to small floating point errors.
641 xform.Rotate(value.degree + j * epsilon);
642 // just want to make sure that we don't crash in the case of NaN.
643 if (value.degree == value.degree) {
644 xform.TransformPoint(pt);
645 EXPECT_EQ(value.xprime, pt.x());
646 EXPECT_EQ(value.yprime, pt.y());
647 xform.TransformPointReverse(pt);
648 EXPECT_EQ(pt.x(), value.x);
649 EXPECT_EQ(pt.y(), value.y);
655 TEST(XFormTest, BlendTranslate) {
656 Transform from;
657 for (int i = 0; i < 10; ++i) {
658 Transform to;
659 to.Translate3d(1, 1, 1);
660 double t = i / 9.0;
661 EXPECT_TRUE(to.Blend(from, t));
662 EXPECT_FLOAT_EQ(t, to.matrix().get(0, 3));
663 EXPECT_FLOAT_EQ(t, to.matrix().get(1, 3));
664 EXPECT_FLOAT_EQ(t, to.matrix().get(2, 3));
668 TEST(XFormTest, BlendRotate) {
669 Vector3dF axes[] = {
670 Vector3dF(1, 0, 0),
671 Vector3dF(0, 1, 0),
672 Vector3dF(0, 0, 1),
673 Vector3dF(1, 1, 1)
675 Transform from;
676 for (size_t index = 0; index < ARRAYSIZE_UNSAFE(axes); ++index) {
677 for (int i = 0; i < 10; ++i) {
678 Transform to;
679 to.RotateAbout(axes[index], 90);
680 double t = i / 9.0;
681 EXPECT_TRUE(to.Blend(from, t));
683 Transform expected;
684 expected.RotateAbout(axes[index], 90 * t);
686 EXPECT_TRUE(MatricesAreNearlyEqual(expected, to));
691 TEST(XFormTest, CannotBlend180DegreeRotation) {
692 Vector3dF axes[] = {
693 Vector3dF(1, 0, 0),
694 Vector3dF(0, 1, 0),
695 Vector3dF(0, 0, 1),
696 Vector3dF(1, 1, 1)
698 Transform from;
699 for (size_t index = 0; index < ARRAYSIZE_UNSAFE(axes); ++index) {
700 Transform to;
701 to.RotateAbout(axes[index], 180);
702 EXPECT_FALSE(to.Blend(from, 0.5));
706 TEST(XFormTest, BlendScale) {
707 Transform from;
708 for (int i = 0; i < 10; ++i) {
709 Transform to;
710 to.Scale3d(5, 4, 3);
711 double t = i / 9.0;
712 EXPECT_TRUE(to.Blend(from, t));
713 EXPECT_FLOAT_EQ(t * 4 + 1, to.matrix().get(0, 0));
714 EXPECT_FLOAT_EQ(t * 3 + 1, to.matrix().get(1, 1));
715 EXPECT_FLOAT_EQ(t * 2 + 1, to.matrix().get(2, 2));
719 TEST(XFormTest, BlendSkew) {
720 Transform from;
721 for (int i = 0; i < 2; ++i) {
722 Transform to;
723 to.SkewX(20);
724 to.SkewY(10);
725 double t = i;
726 Transform expected;
727 expected.SkewX(t * 20);
728 expected.SkewY(t * 10);
729 EXPECT_TRUE(to.Blend(from, t));
730 EXPECT_TRUE(MatricesAreNearlyEqual(expected, to));
734 TEST(XFormTest, BlendPerspective) {
735 Transform from;
736 from.ApplyPerspectiveDepth(200);
737 for (int i = 0; i < 2; ++i) {
738 Transform to;
739 to.ApplyPerspectiveDepth(800);
740 double t = i;
741 Transform expected;
742 expected.ApplyPerspectiveDepth(t * 600 + 200);
743 EXPECT_TRUE(to.Blend(from, t));
744 EXPECT_TRUE(MatricesAreNearlyEqual(expected, to));
748 TEST(XFormTest, BlendIdentity) {
749 Transform from;
750 Transform to;
751 EXPECT_TRUE(to.Blend(from, 0.5));
752 EXPECT_EQ(to, from);
755 TEST(XFormTest, CannotBlendSingularMatrix) {
756 Transform from;
757 Transform to;
758 to.matrix().set(1, 1, SkDoubleToMScalar(0));
759 EXPECT_FALSE(to.Blend(from, 0.5));
762 TEST(XFormTest, VerifyBlendForTranslation) {
763 Transform from;
764 from.Translate3d(100.0, 200.0, 100.0);
766 Transform to;
768 to.Translate3d(200.0, 100.0, 300.0);
769 to.Blend(from, 0.0);
770 EXPECT_EQ(from, to);
772 to = Transform();
773 to.Translate3d(200.0, 100.0, 300.0);
774 to.Blend(from, 0.25);
775 EXPECT_ROW1_EQ(1.0f, 0.0f, 0.0f, 125.0f, to);
776 EXPECT_ROW2_EQ(0.0f, 1.0f, 0.0f, 175.0f, to);
777 EXPECT_ROW3_EQ(0.0f, 0.0f, 1.0f, 150.0f, to);
778 EXPECT_ROW4_EQ(0.0f, 0.0f, 0.0f, 1.0f, to);
780 to = Transform();
781 to.Translate3d(200.0, 100.0, 300.0);
782 to.Blend(from, 0.5);
783 EXPECT_ROW1_EQ(1.0f, 0.0f, 0.0f, 150.0f, to);
784 EXPECT_ROW2_EQ(0.0f, 1.0f, 0.0f, 150.0f, to);
785 EXPECT_ROW3_EQ(0.0f, 0.0f, 1.0f, 200.0f, to);
786 EXPECT_ROW4_EQ(0.0f, 0.0f, 0.0f, 1.0f, to);
788 to = Transform();
789 to.Translate3d(200.0, 100.0, 300.0);
790 to.Blend(from, 1.0);
791 EXPECT_ROW1_EQ(1.0f, 0.0f, 0.0f, 200.0f, to);
792 EXPECT_ROW2_EQ(0.0f, 1.0f, 0.0f, 100.0f, to);
793 EXPECT_ROW3_EQ(0.0f, 0.0f, 1.0f, 300.0f, to);
794 EXPECT_ROW4_EQ(0.0f, 0.0f, 0.0f, 1.0f, to);
797 TEST(XFormTest, VerifyBlendForScale) {
798 Transform from;
799 from.Scale3d(100.0, 200.0, 100.0);
801 Transform to;
803 to.Scale3d(200.0, 100.0, 300.0);
804 to.Blend(from, 0.0);
805 EXPECT_EQ(from, to);
807 to = Transform();
808 to.Scale3d(200.0, 100.0, 300.0);
809 to.Blend(from, 0.25);
810 EXPECT_ROW1_EQ(125.0f, 0.0f, 0.0f, 0.0f, to);
811 EXPECT_ROW2_EQ(0.0f, 175.0f, 0.0f, 0.0f, to);
812 EXPECT_ROW3_EQ(0.0f, 0.0f, 150.0f, 0.0f, to);
813 EXPECT_ROW4_EQ(0.0f, 0.0f, 0.0f, 1.0f, to);
815 to = Transform();
816 to.Scale3d(200.0, 100.0, 300.0);
817 to.Blend(from, 0.5);
818 EXPECT_ROW1_EQ(150.0f, 0.0f, 0.0f, 0.0f, to);
819 EXPECT_ROW2_EQ(0.0f, 150.0f, 0.0f, 0.0f, to);
820 EXPECT_ROW3_EQ(0.0f, 0.0f, 200.0f, 0.0f, to);
821 EXPECT_ROW4_EQ(0.0f, 0.0f, 0.0f, 1.0f, to);
823 to = Transform();
824 to.Scale3d(200.0, 100.0, 300.0);
825 to.Blend(from, 1.0);
826 EXPECT_ROW1_EQ(200.0f, 0.0f, 0.0f, 0.0f, to);
827 EXPECT_ROW2_EQ(0.0f, 100.0f, 0.0f, 0.0f, to);
828 EXPECT_ROW3_EQ(0.0f, 0.0f, 300.0f, 0.0f, to);
829 EXPECT_ROW4_EQ(0.0f, 0.0f, 0.0f, 1.0f, to);
832 TEST(XFormTest, VerifyBlendForSkewX) {
833 Transform from;
834 from.SkewX(0.0);
836 Transform to;
838 to.SkewX(45.0);
839 to.Blend(from, 0.0);
840 EXPECT_EQ(from, to);
842 to = Transform();
843 to.SkewX(45.0);
844 to.Blend(from, 0.5);
845 EXPECT_ROW1_EQ(1.0f, 0.5f, 0.0f, 0.0f, to);
846 EXPECT_ROW2_EQ(0.0f, 1.0f, 0.0f, 0.0f, to);
847 EXPECT_ROW3_EQ(0.0f, 0.0f, 1.0f, 0.0f, to);
848 EXPECT_ROW4_EQ(0.0f, 0.0f, 0.0f, 1.0f, to);
850 to = Transform();
851 to.SkewX(45.0);
852 to.Blend(from, 0.25);
853 EXPECT_ROW1_EQ(1.0f, 0.25f, 0.0f, 0.0f, to);
854 EXPECT_ROW2_EQ(0.0f, 1.0f, 0.0f, 0.0f, to);
855 EXPECT_ROW3_EQ(0.0f, 0.0f, 1.0f, 0.0f, to);
856 EXPECT_ROW4_EQ(0.0f, 0.0f, 0.0f, 1.0f, to);
858 to = Transform();
859 to.SkewX(45.0);
860 to.Blend(from, 1.0);
861 EXPECT_ROW1_EQ(1.0f, 1.0f, 0.0f, 0.0f, to);
862 EXPECT_ROW2_EQ(0.0f, 1.0f, 0.0f, 0.0f, to);
863 EXPECT_ROW3_EQ(0.0f, 0.0f, 1.0f, 0.0f, to);
864 EXPECT_ROW4_EQ(0.0f, 0.0f, 0.0f, 1.0f, to);
867 TEST(XFormTest, VerifyBlendForSkewY) {
868 // NOTE CAREFULLY: Decomposition of skew and rotation terms of the matrix
869 // is inherently underconstrained, and so it does not always compute the
870 // originally intended skew parameters. The current implementation uses QR
871 // decomposition, which decomposes the shear into a rotation + non-uniform
872 // scale.
874 // It is unlikely that the decomposition implementation will need to change
875 // very often, so to get any test coverage, the compromise is to verify the
876 // exact matrix that the.Blend() operation produces.
878 // This problem also potentially exists for skewX, but the current QR
879 // decomposition implementation just happens to decompose those test
880 // matrices intuitively.
882 // Unfortunately, this case suffers from uncomfortably large precision
883 // error.
885 Transform from;
886 from.SkewY(0.0);
888 Transform to;
890 to.SkewY(45.0);
891 to.Blend(from, 0.0);
892 EXPECT_EQ(from, to);
894 to = Transform();
895 to.SkewY(45.0);
896 to.Blend(from, 0.25);
897 EXPECT_ROW1_NEAR(1.0823489449280947471976333,
898 0.0464370719145053845178239,
899 0.0,
900 0.0,
902 LOOSE_ERROR_THRESHOLD);
903 EXPECT_ROW2_NEAR(0.2152925909665224513123150,
904 0.9541702441750861130032035,
905 0.0,
906 0.0,
908 LOOSE_ERROR_THRESHOLD);
909 EXPECT_ROW3_EQ(0.0f, 0.0f, 1.0f, 0.0f, to);
910 EXPECT_ROW4_EQ(0.0f, 0.0f, 0.0f, 1.0f, to);
912 to = Transform();
913 to.SkewY(45.0);
914 to.Blend(from, 0.5);
915 EXPECT_ROW1_NEAR(1.1152212925809066312865525,
916 0.0676495144007326631996335,
917 0.0,
918 0.0,
920 LOOSE_ERROR_THRESHOLD);
921 EXPECT_ROW2_NEAR(0.4619397844342648662419037,
922 0.9519009045724774464858342,
923 0.0,
924 0.0,
926 LOOSE_ERROR_THRESHOLD);
927 EXPECT_ROW3_EQ(0.0f, 0.0f, 1.0f, 0.0f, to);
928 EXPECT_ROW4_EQ(0.0f, 0.0f, 0.0f, 1.0f, to);
930 to = Transform();
931 to.SkewY(45.0);
932 to.Blend(from, 1.0);
933 EXPECT_ROW1_NEAR(1.0, 0.0, 0.0, 0.0, to, LOOSE_ERROR_THRESHOLD);
934 EXPECT_ROW2_NEAR(1.0, 1.0, 0.0, 0.0, to, LOOSE_ERROR_THRESHOLD);
935 EXPECT_ROW3_EQ(0.0f, 0.0f, 1.0f, 0.0f, to);
936 EXPECT_ROW4_EQ(0.0f, 0.0f, 0.0f, 1.0f, to);
939 TEST(XFormTest, VerifyBlendForRotationAboutX) {
940 // Even though.Blending uses quaternions, axis-aligned rotations should.
941 // Blend the same with quaternions or Euler angles. So we can test
942 // rotation.Blending by comparing against manually specified matrices from
943 // Euler angles.
945 Transform from;
946 from.RotateAbout(Vector3dF(1.0, 0.0, 0.0), 0.0);
948 Transform to;
950 to.RotateAbout(Vector3dF(1.0, 0.0, 0.0), 90.0);
951 to.Blend(from, 0.0);
952 EXPECT_EQ(from, to);
954 double expectedRotationAngle = 22.5 * M_PI / 180.0;
955 to = Transform();
956 to.RotateAbout(Vector3dF(1.0, 0.0, 0.0), 90.0);
957 to.Blend(from, 0.25);
958 EXPECT_ROW1_NEAR(1.0, 0.0, 0.0, 0.0, to, ERROR_THRESHOLD);
959 EXPECT_ROW2_NEAR(0.0,
960 std::cos(expectedRotationAngle),
961 -std::sin(expectedRotationAngle),
962 0.0,
964 ERROR_THRESHOLD);
965 EXPECT_ROW3_NEAR(0.0,
966 std::sin(expectedRotationAngle),
967 std::cos(expectedRotationAngle),
968 0.0,
970 ERROR_THRESHOLD);
971 EXPECT_ROW4_EQ(0.0f, 0.0f, 0.0f, 1.0f, to);
973 expectedRotationAngle = 45.0 * M_PI / 180.0;
974 to = Transform();
975 to.RotateAbout(Vector3dF(1.0, 0.0, 0.0), 90.0);
976 to.Blend(from, 0.5);
977 EXPECT_ROW1_NEAR(1.0, 0.0, 0.0, 0.0, to, ERROR_THRESHOLD);
978 EXPECT_ROW2_NEAR(0.0,
979 std::cos(expectedRotationAngle),
980 -std::sin(expectedRotationAngle),
981 0.0,
983 ERROR_THRESHOLD);
984 EXPECT_ROW3_NEAR(0.0,
985 std::sin(expectedRotationAngle),
986 std::cos(expectedRotationAngle),
987 0.0,
989 ERROR_THRESHOLD);
990 EXPECT_ROW4_EQ(0.0f, 0.0f, 0.0f, 1.0f, to);
992 to = Transform();
993 to.RotateAbout(Vector3dF(1.0, 0.0, 0.0), 90.0);
994 to.Blend(from, 1.0);
995 EXPECT_ROW1_NEAR(1.0, 0.0, 0.0, 0.0, to, ERROR_THRESHOLD);
996 EXPECT_ROW2_NEAR(0.0, 0.0, -1.0, 0.0, to, ERROR_THRESHOLD);
997 EXPECT_ROW3_NEAR(0.0, 1.0, 0.0, 0.0, to, ERROR_THRESHOLD);
998 EXPECT_ROW4_EQ(0.0f, 0.0f, 0.0f, 1.0f, to);
1001 TEST(XFormTest, VerifyBlendForRotationAboutY) {
1002 Transform from;
1003 from.RotateAbout(Vector3dF(0.0, 1.0, 0.0), 0.0);
1005 Transform to;
1007 to.RotateAbout(Vector3dF(0.0, 1.0, 0.0), 90.0);
1008 to.Blend(from, 0.0);
1009 EXPECT_EQ(from, to);
1011 double expectedRotationAngle = 22.5 * M_PI / 180.0;
1012 to = Transform();
1013 to.RotateAbout(Vector3dF(0.0, 1.0, 0.0), 90.0);
1014 to.Blend(from, 0.25);
1015 EXPECT_ROW1_NEAR(std::cos(expectedRotationAngle),
1016 0.0,
1017 std::sin(expectedRotationAngle),
1018 0.0,
1020 ERROR_THRESHOLD);
1021 EXPECT_ROW2_NEAR(0.0, 1.0, 0.0, 0.0, to, ERROR_THRESHOLD);
1022 EXPECT_ROW3_NEAR(-std::sin(expectedRotationAngle),
1023 0.0,
1024 std::cos(expectedRotationAngle),
1025 0.0,
1027 ERROR_THRESHOLD);
1028 EXPECT_ROW4_EQ(0.0f, 0.0f, 0.0f, 1.0f, to);
1030 expectedRotationAngle = 45.0 * M_PI / 180.0;
1031 to = Transform();
1032 to.RotateAbout(Vector3dF(0.0, 1.0, 0.0), 90.0);
1033 to.Blend(from, 0.5);
1034 EXPECT_ROW1_NEAR(std::cos(expectedRotationAngle),
1035 0.0,
1036 std::sin(expectedRotationAngle),
1037 0.0,
1039 ERROR_THRESHOLD);
1040 EXPECT_ROW2_NEAR(0.0, 1.0, 0.0, 0.0, to, ERROR_THRESHOLD);
1041 EXPECT_ROW3_NEAR(-std::sin(expectedRotationAngle),
1042 0.0,
1043 std::cos(expectedRotationAngle),
1044 0.0,
1046 ERROR_THRESHOLD);
1047 EXPECT_ROW4_EQ(0.0f, 0.0f, 0.0f, 1.0f, to);
1049 to = Transform();
1050 to.RotateAbout(Vector3dF(0.0, 1.0, 0.0), 90.0);
1051 to.Blend(from, 1.0);
1052 EXPECT_ROW1_NEAR(0.0, 0.0, 1.0, 0.0, to, ERROR_THRESHOLD);
1053 EXPECT_ROW2_NEAR(0.0, 1.0, 0.0, 0.0, to, ERROR_THRESHOLD);
1054 EXPECT_ROW3_NEAR(-1.0, 0.0, 0.0, 0.0, to, ERROR_THRESHOLD);
1055 EXPECT_ROW4_EQ(0.0f, 0.0f, 0.0f, 1.0f, to);
1058 TEST(XFormTest, VerifyBlendForRotationAboutZ) {
1059 Transform from;
1060 from.RotateAbout(Vector3dF(0.0, 0.0, 1.0), 0.0);
1062 Transform to;
1064 to.RotateAbout(Vector3dF(0.0, 0.0, 1.0), 90.0);
1065 to.Blend(from, 0.0);
1066 EXPECT_EQ(from, to);
1068 double expectedRotationAngle = 22.5 * M_PI / 180.0;
1069 to = Transform();
1070 to.RotateAbout(Vector3dF(0.0, 0.0, 1.0), 90.0);
1071 to.Blend(from, 0.25);
1072 EXPECT_ROW1_NEAR(std::cos(expectedRotationAngle),
1073 -std::sin(expectedRotationAngle),
1074 0.0,
1075 0.0,
1077 ERROR_THRESHOLD);
1078 EXPECT_ROW2_NEAR(std::sin(expectedRotationAngle),
1079 std::cos(expectedRotationAngle),
1080 0.0,
1081 0.0,
1083 ERROR_THRESHOLD);
1084 EXPECT_ROW3_NEAR(0.0, 0.0, 1.0, 0.0, to, ERROR_THRESHOLD);
1085 EXPECT_ROW4_EQ(0.0f, 0.0f, 0.0f, 1.0f, to);
1087 expectedRotationAngle = 45.0 * M_PI / 180.0;
1088 to = Transform();
1089 to.RotateAbout(Vector3dF(0.0, 0.0, 1.0), 90.0);
1090 to.Blend(from, 0.5);
1091 EXPECT_ROW1_NEAR(std::cos(expectedRotationAngle),
1092 -std::sin(expectedRotationAngle),
1093 0.0,
1094 0.0,
1096 ERROR_THRESHOLD);
1097 EXPECT_ROW2_NEAR(std::sin(expectedRotationAngle),
1098 std::cos(expectedRotationAngle),
1099 0.0,
1100 0.0,
1102 ERROR_THRESHOLD);
1103 EXPECT_ROW3_NEAR(0.0, 0.0, 1.0, 0.0, to, ERROR_THRESHOLD);
1104 EXPECT_ROW4_EQ(0.0f, 0.0f, 0.0f, 1.0f, to);
1106 to = Transform();
1107 to.RotateAbout(Vector3dF(0.0, 0.0, 1.0), 90.0);
1108 to.Blend(from, 1.0);
1109 EXPECT_ROW1_NEAR(0.0, -1.0, 0.0, 0.0, to, ERROR_THRESHOLD);
1110 EXPECT_ROW2_NEAR(1.0, 0.0, 0.0, 0.0, to, ERROR_THRESHOLD);
1111 EXPECT_ROW3_NEAR(0.0, 0.0, 1.0, 0.0, to, ERROR_THRESHOLD);
1112 EXPECT_ROW4_EQ(0.0f, 0.0f, 0.0f, 1.0f, to);
1115 TEST(XFormTest, VerifyBlendForCompositeTransform) {
1116 // Verify that the.Blending was done with a decomposition in correct order
1117 // by blending a composite transform. Using matrix x vector notation
1118 // (Ax = b, where x is column vector), the ordering should be:
1119 // perspective * translation * rotation * skew * scale
1121 // It is not as important (or meaningful) to check intermediate
1122 // interpolations; order of operations will be tested well enough by the
1123 // end cases that are easier to specify.
1125 Transform from;
1126 Transform to;
1128 Transform expectedEndOfAnimation;
1129 expectedEndOfAnimation.ApplyPerspectiveDepth(1.0);
1130 expectedEndOfAnimation.Translate3d(10.0, 20.0, 30.0);
1131 expectedEndOfAnimation.RotateAbout(Vector3dF(0.0, 0.0, 1.0), 25.0);
1132 expectedEndOfAnimation.SkewY(45.0);
1133 expectedEndOfAnimation.Scale3d(6.0, 7.0, 8.0);
1135 to = expectedEndOfAnimation;
1136 to.Blend(from, 0.0);
1137 EXPECT_EQ(from, to);
1139 to = expectedEndOfAnimation;
1140 // We short circuit if blend is >= 1, so to check the numerics, we will
1141 // check that we get close to what we expect when we're nearly done
1142 // interpolating.
1143 to.Blend(from, .99999);
1145 // Recomposing the matrix results in a normalized matrix, so to verify we
1146 // need to normalize the expectedEndOfAnimation before comparing elements.
1147 // Normalizing means dividing everything by expectedEndOfAnimation.m44().
1148 Transform normalizedExpectedEndOfAnimation = expectedEndOfAnimation;
1149 Transform normalizationMatrix;
1150 normalizationMatrix.matrix().set(
1151 0.0,
1152 0.0,
1153 SkDoubleToMScalar(1 / expectedEndOfAnimation.matrix().get(3.0, 3.0)));
1154 normalizationMatrix.matrix().set(
1155 1.0,
1156 1.0,
1157 SkDoubleToMScalar(1 / expectedEndOfAnimation.matrix().get(3.0, 3.0)));
1158 normalizationMatrix.matrix().set(
1159 2.0,
1160 2.0,
1161 SkDoubleToMScalar(1 / expectedEndOfAnimation.matrix().get(3.0, 3.0)));
1162 normalizationMatrix.matrix().set(
1163 3.0,
1164 3.0,
1165 SkDoubleToMScalar(1 / expectedEndOfAnimation.matrix().get(3.0, 3.0)));
1166 normalizedExpectedEndOfAnimation.PreconcatTransform(normalizationMatrix);
1168 EXPECT_TRUE(MatricesAreNearlyEqual(normalizedExpectedEndOfAnimation, to));
1171 TEST(XFormTest, DecomposedTransformCtor) {
1172 DecomposedTransform decomp;
1173 for (int i = 0; i < 3; ++i) {
1174 EXPECT_EQ(0.0, decomp.translate[i]);
1175 EXPECT_EQ(1.0, decomp.scale[i]);
1176 EXPECT_EQ(0.0, decomp.skew[i]);
1177 EXPECT_EQ(0.0, decomp.quaternion[i]);
1178 EXPECT_EQ(0.0, decomp.perspective[i]);
1180 EXPECT_EQ(1.0, decomp.quaternion[3]);
1181 EXPECT_EQ(1.0, decomp.perspective[3]);
1182 Transform identity;
1183 Transform composed = ComposeTransform(decomp);
1184 EXPECT_TRUE(MatricesAreNearlyEqual(identity, composed));
1187 TEST(XFormTest, FactorTRS) {
1188 for (int degrees = 0; degrees < 180; ++degrees) {
1189 // build a transformation matrix.
1190 gfx::Transform transform;
1191 transform.Translate(degrees * 2, -degrees * 3);
1192 transform.Rotate(degrees);
1193 transform.Scale(degrees + 1, 2 * degrees + 1);
1195 // factor the matrix
1196 DecomposedTransform decomp;
1197 bool success = DecomposeTransform(&decomp, transform);
1198 EXPECT_TRUE(success);
1199 EXPECT_FLOAT_EQ(decomp.translate[0], degrees * 2);
1200 EXPECT_FLOAT_EQ(decomp.translate[1], -degrees * 3);
1201 double rotation = std::acos(decomp.quaternion[3]) * 360.0 / M_PI;
1202 while (rotation < 0.0)
1203 rotation += 360.0;
1204 while (rotation > 360.0)
1205 rotation -= 360.0;
1206 EXPECT_FLOAT_EQ(rotation, degrees);
1207 EXPECT_FLOAT_EQ(decomp.scale[0], degrees + 1);
1208 EXPECT_FLOAT_EQ(decomp.scale[1], 2 * degrees + 1);
1212 TEST(XFormTest, IntegerTranslation) {
1213 gfx::Transform transform;
1214 EXPECT_TRUE(transform.IsIdentityOrIntegerTranslation());
1216 transform.Translate3d(1, 2, 3);
1217 EXPECT_TRUE(transform.IsIdentityOrIntegerTranslation());
1219 transform.MakeIdentity();
1220 transform.Translate3d(-1, -2, -3);
1221 EXPECT_TRUE(transform.IsIdentityOrIntegerTranslation());
1223 transform.MakeIdentity();
1224 transform.Translate3d(4.5, 0, 0);
1225 EXPECT_FALSE(transform.IsIdentityOrIntegerTranslation());
1227 transform.MakeIdentity();
1228 transform.Translate3d(0, -6.7, 0);
1229 EXPECT_FALSE(transform.IsIdentityOrIntegerTranslation());
1231 transform.MakeIdentity();
1232 transform.Translate3d(0, 0, 8.9);
1233 EXPECT_FALSE(transform.IsIdentityOrIntegerTranslation());
1236 TEST(XFormTest, verifyMatrixInversion) {
1238 // Invert a translation
1239 gfx::Transform translation;
1240 translation.Translate3d(2.0, 3.0, 4.0);
1241 EXPECT_TRUE(translation.IsInvertible());
1243 gfx::Transform inverse_translation;
1244 bool is_invertible = translation.GetInverse(&inverse_translation);
1245 EXPECT_TRUE(is_invertible);
1246 EXPECT_ROW1_EQ(1.0f, 0.0f, 0.0f, -2.0f, inverse_translation);
1247 EXPECT_ROW2_EQ(0.0f, 1.0f, 0.0f, -3.0f, inverse_translation);
1248 EXPECT_ROW3_EQ(0.0f, 0.0f, 1.0f, -4.0f, inverse_translation);
1249 EXPECT_ROW4_EQ(0.0f, 0.0f, 0.0f, 1.0f, inverse_translation);
1253 // Invert a non-uniform scale
1254 gfx::Transform scale;
1255 scale.Scale3d(4.0, 10.0, 100.0);
1256 EXPECT_TRUE(scale.IsInvertible());
1258 gfx::Transform inverse_scale;
1259 bool is_invertible = scale.GetInverse(&inverse_scale);
1260 EXPECT_TRUE(is_invertible);
1261 EXPECT_ROW1_EQ(0.25f, 0.0f, 0.0f, 0.0f, inverse_scale);
1262 EXPECT_ROW2_EQ(0.0f, 0.1f, 0.0f, 0.0f, inverse_scale);
1263 EXPECT_ROW3_EQ(0.0f, 0.0f, 0.01f, 0.0f, inverse_scale);
1264 EXPECT_ROW4_EQ(0.0f, 0.0f, 0.0f, 1.0f, inverse_scale);
1268 // Try to invert a matrix that is not invertible.
1269 // The inverse() function should reset the output matrix to identity.
1270 gfx::Transform uninvertible;
1271 uninvertible.matrix().setDouble(0, 0, 0.0);
1272 uninvertible.matrix().setDouble(1, 1, 0.0);
1273 uninvertible.matrix().setDouble(2, 2, 0.0);
1274 uninvertible.matrix().setDouble(3, 3, 0.0);
1275 EXPECT_FALSE(uninvertible.IsInvertible());
1277 gfx::Transform inverse_of_uninvertible;
1279 // Add a scale just to more easily ensure that inverse_of_uninvertible is
1280 // reset to identity.
1281 inverse_of_uninvertible.Scale3d(4.0, 10.0, 100.0);
1283 bool is_invertible = uninvertible.GetInverse(&inverse_of_uninvertible);
1284 EXPECT_FALSE(is_invertible);
1285 EXPECT_TRUE(inverse_of_uninvertible.IsIdentity());
1286 EXPECT_ROW1_EQ(1.0f, 0.0f, 0.0f, 0.0f, inverse_of_uninvertible);
1287 EXPECT_ROW2_EQ(0.0f, 1.0f, 0.0f, 0.0f, inverse_of_uninvertible);
1288 EXPECT_ROW3_EQ(0.0f, 0.0f, 1.0f, 0.0f, inverse_of_uninvertible);
1289 EXPECT_ROW4_EQ(0.0f, 0.0f, 0.0f, 1.0f, inverse_of_uninvertible);
1293 TEST(XFormTest, verifyBackfaceVisibilityBasicCases) {
1294 Transform transform;
1296 transform.MakeIdentity();
1297 EXPECT_FALSE(transform.IsBackFaceVisible());
1299 transform.MakeIdentity();
1300 transform.RotateAboutYAxis(80.0);
1301 EXPECT_FALSE(transform.IsBackFaceVisible());
1303 transform.MakeIdentity();
1304 transform.RotateAboutYAxis(100.0);
1305 EXPECT_TRUE(transform.IsBackFaceVisible());
1307 // Edge case, 90 degree rotation should return false.
1308 transform.MakeIdentity();
1309 transform.RotateAboutYAxis(90.0);
1310 EXPECT_FALSE(transform.IsBackFaceVisible());
1313 TEST(XFormTest, verifyBackfaceVisibilityForPerspective) {
1314 Transform layer_space_to_projection_plane;
1316 // This tests if IsBackFaceVisible works properly under perspective
1317 // transforms. Specifically, layers that may have their back face visible in
1318 // orthographic projection, may not actually have back face visible under
1319 // perspective projection.
1321 // Case 1: Layer is rotated by slightly more than 90 degrees, at the center
1322 // of the prespective projection. In this case, the layer's back-side
1323 // is visible to the camera.
1324 layer_space_to_projection_plane.MakeIdentity();
1325 layer_space_to_projection_plane.ApplyPerspectiveDepth(1.0);
1326 layer_space_to_projection_plane.Translate3d(0.0, 0.0, 0.0);
1327 layer_space_to_projection_plane.RotateAboutYAxis(100.0);
1328 EXPECT_TRUE(layer_space_to_projection_plane.IsBackFaceVisible());
1330 // Case 2: Layer is rotated by slightly more than 90 degrees, but shifted off
1331 // to the side of the camera. Because of the wide field-of-view, the
1332 // layer's front side is still visible.
1334 // |<-- front side of layer is visible to camera
1335 // \ | /
1336 // \ | /
1337 // \| /
1338 // | /
1339 // |\ /<-- camera field of view
1340 // | \ /
1341 // back side of layer -->| \ /
1342 // \./ <-- camera origin
1344 layer_space_to_projection_plane.MakeIdentity();
1345 layer_space_to_projection_plane.ApplyPerspectiveDepth(1.0);
1346 layer_space_to_projection_plane.Translate3d(-10.0, 0.0, 0.0);
1347 layer_space_to_projection_plane.RotateAboutYAxis(100.0);
1348 EXPECT_FALSE(layer_space_to_projection_plane.IsBackFaceVisible());
1350 // Case 3: Additionally rotating the layer by 180 degrees should of course
1351 // show the opposite result of case 2.
1352 layer_space_to_projection_plane.RotateAboutYAxis(180.0);
1353 EXPECT_TRUE(layer_space_to_projection_plane.IsBackFaceVisible());
1356 TEST(XFormTest, verifyDefaultConstructorCreatesIdentityMatrix) {
1357 Transform A;
1358 EXPECT_ROW1_EQ(1.0f, 0.0f, 0.0f, 0.0f, A);
1359 EXPECT_ROW2_EQ(0.0f, 1.0f, 0.0f, 0.0f, A);
1360 EXPECT_ROW3_EQ(0.0f, 0.0f, 1.0f, 0.0f, A);
1361 EXPECT_ROW4_EQ(0.0f, 0.0f, 0.0f, 1.0f, A);
1362 EXPECT_TRUE(A.IsIdentity());
1365 TEST(XFormTest, verifyCopyConstructor) {
1366 Transform A;
1367 InitializeTestMatrix(&A);
1369 // Copy constructor should produce exact same elements as matrix A.
1370 Transform B(A);
1371 EXPECT_ROW1_EQ(10.0f, 14.0f, 18.0f, 22.0f, B);
1372 EXPECT_ROW2_EQ(11.0f, 15.0f, 19.0f, 23.0f, B);
1373 EXPECT_ROW3_EQ(12.0f, 16.0f, 20.0f, 24.0f, B);
1374 EXPECT_ROW4_EQ(13.0f, 17.0f, 21.0f, 25.0f, B);
1377 TEST(XFormTest, verifyConstructorFor16Elements) {
1378 Transform transform(1.0, 2.0, 3.0, 4.0,
1379 5.0, 6.0, 7.0, 8.0,
1380 9.0, 10.0, 11.0, 12.0,
1381 13.0, 14.0, 15.0, 16.0);
1383 EXPECT_ROW1_EQ(1.0f, 2.0f, 3.0f, 4.0f, transform);
1384 EXPECT_ROW2_EQ(5.0f, 6.0f, 7.0f, 8.0f, transform);
1385 EXPECT_ROW3_EQ(9.0f, 10.0f, 11.0f, 12.0f, transform);
1386 EXPECT_ROW4_EQ(13.0f, 14.0f, 15.0f, 16.0f, transform);
1389 TEST(XFormTest, verifyConstructorFor2dElements) {
1390 Transform transform(1.0, 2.0, 3.0, 4.0, 5.0, 6.0);
1392 EXPECT_ROW1_EQ(1.0f, 2.0f, 0.0f, 5.0f, transform);
1393 EXPECT_ROW2_EQ(3.0f, 4.0f, 0.0f, 6.0f, transform);
1394 EXPECT_ROW3_EQ(0.0f, 0.0f, 1.0f, 0.0f, transform);
1395 EXPECT_ROW4_EQ(0.0f, 0.0f, 0.0f, 1.0f, transform);
1399 TEST(XFormTest, verifyAssignmentOperator) {
1400 Transform A;
1401 InitializeTestMatrix(&A);
1402 Transform B;
1403 InitializeTestMatrix2(&B);
1404 Transform C;
1405 InitializeTestMatrix2(&C);
1406 C = B = A;
1408 // Both B and C should now have been re-assigned to the value of A.
1409 EXPECT_ROW1_EQ(10.0f, 14.0f, 18.0f, 22.0f, B);
1410 EXPECT_ROW2_EQ(11.0f, 15.0f, 19.0f, 23.0f, B);
1411 EXPECT_ROW3_EQ(12.0f, 16.0f, 20.0f, 24.0f, B);
1412 EXPECT_ROW4_EQ(13.0f, 17.0f, 21.0f, 25.0f, B);
1414 EXPECT_ROW1_EQ(10.0f, 14.0f, 18.0f, 22.0f, C);
1415 EXPECT_ROW2_EQ(11.0f, 15.0f, 19.0f, 23.0f, C);
1416 EXPECT_ROW3_EQ(12.0f, 16.0f, 20.0f, 24.0f, C);
1417 EXPECT_ROW4_EQ(13.0f, 17.0f, 21.0f, 25.0f, C);
1420 TEST(XFormTest, verifyEqualsBooleanOperator) {
1421 Transform A;
1422 InitializeTestMatrix(&A);
1424 Transform B;
1425 InitializeTestMatrix(&B);
1426 EXPECT_TRUE(A == B);
1428 // Modifying multiple elements should cause equals operator to return false.
1429 Transform C;
1430 InitializeTestMatrix2(&C);
1431 EXPECT_FALSE(A == C);
1433 // Modifying any one individual element should cause equals operator to
1434 // return false.
1435 Transform D;
1436 D = A;
1437 D.matrix().setDouble(0, 0, 0.0);
1438 EXPECT_FALSE(A == D);
1440 D = A;
1441 D.matrix().setDouble(1, 0, 0.0);
1442 EXPECT_FALSE(A == D);
1444 D = A;
1445 D.matrix().setDouble(2, 0, 0.0);
1446 EXPECT_FALSE(A == D);
1448 D = A;
1449 D.matrix().setDouble(3, 0, 0.0);
1450 EXPECT_FALSE(A == D);
1452 D = A;
1453 D.matrix().setDouble(0, 1, 0.0);
1454 EXPECT_FALSE(A == D);
1456 D = A;
1457 D.matrix().setDouble(1, 1, 0.0);
1458 EXPECT_FALSE(A == D);
1460 D = A;
1461 D.matrix().setDouble(2, 1, 0.0);
1462 EXPECT_FALSE(A == D);
1464 D = A;
1465 D.matrix().setDouble(3, 1, 0.0);
1466 EXPECT_FALSE(A == D);
1468 D = A;
1469 D.matrix().setDouble(0, 2, 0.0);
1470 EXPECT_FALSE(A == D);
1472 D = A;
1473 D.matrix().setDouble(1, 2, 0.0);
1474 EXPECT_FALSE(A == D);
1476 D = A;
1477 D.matrix().setDouble(2, 2, 0.0);
1478 EXPECT_FALSE(A == D);
1480 D = A;
1481 D.matrix().setDouble(3, 2, 0.0);
1482 EXPECT_FALSE(A == D);
1484 D = A;
1485 D.matrix().setDouble(0, 3, 0.0);
1486 EXPECT_FALSE(A == D);
1488 D = A;
1489 D.matrix().setDouble(1, 3, 0.0);
1490 EXPECT_FALSE(A == D);
1492 D = A;
1493 D.matrix().setDouble(2, 3, 0.0);
1494 EXPECT_FALSE(A == D);
1496 D = A;
1497 D.matrix().setDouble(3, 3, 0.0);
1498 EXPECT_FALSE(A == D);
1501 TEST(XFormTest, verifyMultiplyOperator) {
1502 Transform A;
1503 InitializeTestMatrix(&A);
1505 Transform B;
1506 InitializeTestMatrix2(&B);
1508 Transform C = A * B;
1509 EXPECT_ROW1_EQ(2036.0f, 2292.0f, 2548.0f, 2804.0f, C);
1510 EXPECT_ROW2_EQ(2162.0f, 2434.0f, 2706.0f, 2978.0f, C);
1511 EXPECT_ROW3_EQ(2288.0f, 2576.0f, 2864.0f, 3152.0f, C);
1512 EXPECT_ROW4_EQ(2414.0f, 2718.0f, 3022.0f, 3326.0f, C);
1514 // Just an additional sanity check; matrix multiplication is not commutative.
1515 EXPECT_FALSE(A * B == B * A);
1518 TEST(XFormTest, verifyMultiplyAndAssignOperator) {
1519 Transform A;
1520 InitializeTestMatrix(&A);
1522 Transform B;
1523 InitializeTestMatrix2(&B);
1525 A *= B;
1526 EXPECT_ROW1_EQ(2036.0f, 2292.0f, 2548.0f, 2804.0f, A);
1527 EXPECT_ROW2_EQ(2162.0f, 2434.0f, 2706.0f, 2978.0f, A);
1528 EXPECT_ROW3_EQ(2288.0f, 2576.0f, 2864.0f, 3152.0f, A);
1529 EXPECT_ROW4_EQ(2414.0f, 2718.0f, 3022.0f, 3326.0f, A);
1531 // Just an additional sanity check; matrix multiplication is not commutative.
1532 Transform C = A;
1533 C *= B;
1534 Transform D = B;
1535 D *= A;
1536 EXPECT_FALSE(C == D);
1539 TEST(XFormTest, verifyMatrixMultiplication) {
1540 Transform A;
1541 InitializeTestMatrix(&A);
1543 Transform B;
1544 InitializeTestMatrix2(&B);
1546 A.PreconcatTransform(B);
1547 EXPECT_ROW1_EQ(2036.0f, 2292.0f, 2548.0f, 2804.0f, A);
1548 EXPECT_ROW2_EQ(2162.0f, 2434.0f, 2706.0f, 2978.0f, A);
1549 EXPECT_ROW3_EQ(2288.0f, 2576.0f, 2864.0f, 3152.0f, A);
1550 EXPECT_ROW4_EQ(2414.0f, 2718.0f, 3022.0f, 3326.0f, A);
1553 TEST(XFormTest, verifyMakeIdentiy) {
1554 Transform A;
1555 InitializeTestMatrix(&A);
1556 A.MakeIdentity();
1557 EXPECT_ROW1_EQ(1.0f, 0.0f, 0.0f, 0.0f, A);
1558 EXPECT_ROW2_EQ(0.0f, 1.0f, 0.0f, 0.0f, A);
1559 EXPECT_ROW3_EQ(0.0f, 0.0f, 1.0f, 0.0f, A);
1560 EXPECT_ROW4_EQ(0.0f, 0.0f, 0.0f, 1.0f, A);
1561 EXPECT_TRUE(A.IsIdentity());
1564 TEST(XFormTest, verifyTranslate) {
1565 Transform A;
1566 A.Translate(2.0, 3.0);
1567 EXPECT_ROW1_EQ(1.0f, 0.0f, 0.0f, 2.0f, A);
1568 EXPECT_ROW2_EQ(0.0f, 1.0f, 0.0f, 3.0f, A);
1569 EXPECT_ROW3_EQ(0.0f, 0.0f, 1.0f, 0.0f, A);
1570 EXPECT_ROW4_EQ(0.0f, 0.0f, 0.0f, 1.0f, A);
1572 // Verify that Translate() post-multiplies the existing matrix.
1573 A.MakeIdentity();
1574 A.Scale(5.0, 5.0);
1575 A.Translate(2.0, 3.0);
1576 EXPECT_ROW1_EQ(5.0f, 0.0f, 0.0f, 10.0f, A);
1577 EXPECT_ROW2_EQ(0.0f, 5.0f, 0.0f, 15.0f, A);
1578 EXPECT_ROW3_EQ(0.0f, 0.0f, 1.0f, 0.0f, A);
1579 EXPECT_ROW4_EQ(0.0f, 0.0f, 0.0f, 1.0f, A);
1582 TEST(XFormTest, verifyTranslate3d) {
1583 Transform A;
1584 A.Translate3d(2.0, 3.0, 4.0);
1585 EXPECT_ROW1_EQ(1.0f, 0.0f, 0.0f, 2.0f, A);
1586 EXPECT_ROW2_EQ(0.0f, 1.0f, 0.0f, 3.0f, A);
1587 EXPECT_ROW3_EQ(0.0f, 0.0f, 1.0f, 4.0f, A);
1588 EXPECT_ROW4_EQ(0.0f, 0.0f, 0.0f, 1.0f, A);
1590 // Verify that Translate3d() post-multiplies the existing matrix.
1591 A.MakeIdentity();
1592 A.Scale3d(6.0, 7.0, 8.0);
1593 A.Translate3d(2.0, 3.0, 4.0);
1594 EXPECT_ROW1_EQ(6.0f, 0.0f, 0.0f, 12.0f, A);
1595 EXPECT_ROW2_EQ(0.0f, 7.0f, 0.0f, 21.0f, A);
1596 EXPECT_ROW3_EQ(0.0f, 0.0f, 8.0f, 32.0f, A);
1597 EXPECT_ROW4_EQ(0.0f, 0.0f, 0.0f, 1.0f, A);
1600 TEST(XFormTest, verifyScale) {
1601 Transform A;
1602 A.Scale(6.0, 7.0);
1603 EXPECT_ROW1_EQ(6.0f, 0.0f, 0.0f, 0.0f, A);
1604 EXPECT_ROW2_EQ(0.0f, 7.0f, 0.0f, 0.0f, A);
1605 EXPECT_ROW3_EQ(0.0f, 0.0f, 1.0f, 0.0f, A);
1606 EXPECT_ROW4_EQ(0.0f, 0.0f, 0.0f, 1.0f, A);
1608 // Verify that Scale() post-multiplies the existing matrix.
1609 A.MakeIdentity();
1610 A.Translate3d(2.0, 3.0, 4.0);
1611 A.Scale(6.0, 7.0);
1612 EXPECT_ROW1_EQ(6.0f, 0.0f, 0.0f, 2.0f, A);
1613 EXPECT_ROW2_EQ(0.0f, 7.0f, 0.0f, 3.0f, A);
1614 EXPECT_ROW3_EQ(0.0f, 0.0f, 1.0f, 4.0f, A);
1615 EXPECT_ROW4_EQ(0.0f, 0.0f, 0.0f, 1.0f, A);
1618 TEST(XFormTest, verifyScale3d) {
1619 Transform A;
1620 A.Scale3d(6.0, 7.0, 8.0);
1621 EXPECT_ROW1_EQ(6.0f, 0.0f, 0.0f, 0.0f, A);
1622 EXPECT_ROW2_EQ(0.0f, 7.0f, 0.0f, 0.0f, A);
1623 EXPECT_ROW3_EQ(0.0f, 0.0f, 8.0f, 0.0f, A);
1624 EXPECT_ROW4_EQ(0.0f, 0.0f, 0.0f, 1.0f, A);
1626 // Verify that scale3d() post-multiplies the existing matrix.
1627 A.MakeIdentity();
1628 A.Translate3d(2.0, 3.0, 4.0);
1629 A.Scale3d(6.0, 7.0, 8.0);
1630 EXPECT_ROW1_EQ(6.0f, 0.0f, 0.0f, 2.0f, A);
1631 EXPECT_ROW2_EQ(0.0f, 7.0f, 0.0f, 3.0f, A);
1632 EXPECT_ROW3_EQ(0.0f, 0.0f, 8.0f, 4.0f, A);
1633 EXPECT_ROW4_EQ(0.0f, 0.0f, 0.0f, 1.0f, A);
1636 TEST(XFormTest, verifyRotate) {
1637 Transform A;
1638 A.Rotate(90.0);
1639 EXPECT_ROW1_NEAR(0.0, -1.0, 0.0, 0.0, A, ERROR_THRESHOLD);
1640 EXPECT_ROW2_NEAR(1.0, 0.0, 0.0, 0.0, A, ERROR_THRESHOLD);
1641 EXPECT_ROW3_EQ(0.0f, 0.0f, 1.0f, 0.0f, A);
1642 EXPECT_ROW4_EQ(0.0f, 0.0f, 0.0f, 1.0f, A);
1644 // Verify that Rotate() post-multiplies the existing matrix.
1645 A.MakeIdentity();
1646 A.Scale3d(6.0, 7.0, 8.0);
1647 A.Rotate(90.0);
1648 EXPECT_ROW1_NEAR(0.0, -6.0, 0.0, 0.0, A, ERROR_THRESHOLD);
1649 EXPECT_ROW2_NEAR(7.0, 0.0, 0.0, 0.0, A, ERROR_THRESHOLD);
1650 EXPECT_ROW3_EQ(0.0f, 0.0f, 8.0f, 0.0f, A);
1651 EXPECT_ROW4_EQ(0.0f, 0.0f, 0.0f, 1.0f, A);
1654 TEST(XFormTest, verifyRotateAboutXAxis) {
1655 Transform A;
1656 double sin45 = 0.5 * sqrt(2.0);
1657 double cos45 = sin45;
1659 A.MakeIdentity();
1660 A.RotateAboutXAxis(90.0);
1661 EXPECT_ROW1_EQ(1.0f, 0.0f, 0.0f, 0.0f, A);
1662 EXPECT_ROW2_NEAR(0.0, 0.0, -1.0, 0.0, A, ERROR_THRESHOLD);
1663 EXPECT_ROW3_NEAR(0.0, 1.0, 0.0, 0.0, A, ERROR_THRESHOLD);
1664 EXPECT_ROW4_EQ(0.0f, 0.0f, 0.0f, 1.0f, A);
1666 A.MakeIdentity();
1667 A.RotateAboutXAxis(45.0);
1668 EXPECT_ROW1_EQ(1.0f, 0.0f, 0.0f, 0.0f, A);
1669 EXPECT_ROW2_NEAR(0.0, cos45, -sin45, 0.0, A, ERROR_THRESHOLD);
1670 EXPECT_ROW3_NEAR(0.0, sin45, cos45, 0.0, A, ERROR_THRESHOLD);
1671 EXPECT_ROW4_EQ(0.0f, 0.0f, 0.0f, 1.0f, A);
1673 // Verify that RotateAboutXAxis(angle) post-multiplies the existing matrix.
1674 A.MakeIdentity();
1675 A.Scale3d(6.0, 7.0, 8.0);
1676 A.RotateAboutXAxis(90.0);
1677 EXPECT_ROW1_NEAR(6.0, 0.0, 0.0, 0.0, A, ERROR_THRESHOLD);
1678 EXPECT_ROW2_NEAR(0.0, 0.0, -7.0, 0.0, A, ERROR_THRESHOLD);
1679 EXPECT_ROW3_NEAR(0.0, 8.0, 0.0, 0.0, A, ERROR_THRESHOLD);
1680 EXPECT_ROW4_EQ(0.0f, 0.0f, 0.0f, 1.0f, A);
1683 TEST(XFormTest, verifyRotateAboutYAxis) {
1684 Transform A;
1685 double sin45 = 0.5 * sqrt(2.0);
1686 double cos45 = sin45;
1688 // Note carefully, the expected pattern is inverted compared to rotating
1689 // about x axis or z axis.
1690 A.MakeIdentity();
1691 A.RotateAboutYAxis(90.0);
1692 EXPECT_ROW1_NEAR(0.0, 0.0, 1.0, 0.0, A, ERROR_THRESHOLD);
1693 EXPECT_ROW2_EQ(0.0f, 1.0f, 0.0f, 0.0f, A);
1694 EXPECT_ROW3_NEAR(-1.0, 0.0, 0.0, 0.0, A, ERROR_THRESHOLD);
1695 EXPECT_ROW4_EQ(0.0f, 0.0f, 0.0f, 1.0f, A);
1697 A.MakeIdentity();
1698 A.RotateAboutYAxis(45.0);
1699 EXPECT_ROW1_NEAR(cos45, 0.0, sin45, 0.0, A, ERROR_THRESHOLD);
1700 EXPECT_ROW2_EQ(0.0f, 1.0f, 0.0f, 0.0f, A);
1701 EXPECT_ROW3_NEAR(-sin45, 0.0, cos45, 0.0, A, ERROR_THRESHOLD);
1702 EXPECT_ROW4_EQ(0.0f, 0.0f, 0.0f, 1.0f, A);
1704 // Verify that RotateAboutYAxis(angle) post-multiplies the existing matrix.
1705 A.MakeIdentity();
1706 A.Scale3d(6.0, 7.0, 8.0);
1707 A.RotateAboutYAxis(90.0);
1708 EXPECT_ROW1_NEAR(0.0, 0.0, 6.0, 0.0, A, ERROR_THRESHOLD);
1709 EXPECT_ROW2_NEAR(0.0, 7.0, 0.0, 0.0, A, ERROR_THRESHOLD);
1710 EXPECT_ROW3_NEAR(-8.0, 0.0, 0.0, 0.0, A, ERROR_THRESHOLD);
1711 EXPECT_ROW4_EQ(0.0f, 0.0f, 0.0f, 1.0f, A);
1714 TEST(XFormTest, verifyRotateAboutZAxis) {
1715 Transform A;
1716 double sin45 = 0.5 * sqrt(2.0);
1717 double cos45 = sin45;
1719 A.MakeIdentity();
1720 A.RotateAboutZAxis(90.0);
1721 EXPECT_ROW1_NEAR(0.0, -1.0, 0.0, 0.0, A, ERROR_THRESHOLD);
1722 EXPECT_ROW2_NEAR(1.0, 0.0, 0.0, 0.0, A, ERROR_THRESHOLD);
1723 EXPECT_ROW3_EQ(0.0f, 0.0f, 1.0f, 0.0f, A);
1724 EXPECT_ROW4_EQ(0.0f, 0.0f, 0.0f, 1.0f, A);
1726 A.MakeIdentity();
1727 A.RotateAboutZAxis(45.0);
1728 EXPECT_ROW1_NEAR(cos45, -sin45, 0.0, 0.0, A, ERROR_THRESHOLD);
1729 EXPECT_ROW2_NEAR(sin45, cos45, 0.0, 0.0, A, ERROR_THRESHOLD);
1730 EXPECT_ROW3_EQ(0.0f, 0.0f, 1.0f, 0.0f, A);
1731 EXPECT_ROW4_EQ(0.0f, 0.0f, 0.0f, 1.0f, A);
1733 // Verify that RotateAboutZAxis(angle) post-multiplies the existing matrix.
1734 A.MakeIdentity();
1735 A.Scale3d(6.0, 7.0, 8.0);
1736 A.RotateAboutZAxis(90.0);
1737 EXPECT_ROW1_NEAR(0.0, -6.0, 0.0, 0.0, A, ERROR_THRESHOLD);
1738 EXPECT_ROW2_NEAR(7.0, 0.0, 0.0, 0.0, A, ERROR_THRESHOLD);
1739 EXPECT_ROW3_EQ(0.0f, 0.0f, 8.0f, 0.0f, A);
1740 EXPECT_ROW4_EQ(0.0f, 0.0f, 0.0f, 1.0f, A);
1743 TEST(XFormTest, verifyRotateAboutForAlignedAxes) {
1744 Transform A;
1746 // Check rotation about z-axis
1747 A.MakeIdentity();
1748 A.RotateAbout(Vector3dF(0.0, 0.0, 1.0), 90.0);
1749 EXPECT_ROW1_NEAR(0.0, -1.0, 0.0, 0.0, A, ERROR_THRESHOLD);
1750 EXPECT_ROW2_NEAR(1.0, 0.0, 0.0, 0.0, A, ERROR_THRESHOLD);
1751 EXPECT_ROW3_EQ(0.0f, 0.0f, 1.0f, 0.0f, A);
1752 EXPECT_ROW4_EQ(0.0f, 0.0f, 0.0f, 1.0f, A);
1754 // Check rotation about x-axis
1755 A.MakeIdentity();
1756 A.RotateAbout(Vector3dF(1.0, 0.0, 0.0), 90.0);
1757 EXPECT_ROW1_EQ(1.0f, 0.0f, 0.0f, 0.0f, A);
1758 EXPECT_ROW2_NEAR(0.0, 0.0, -1.0, 0.0, A, ERROR_THRESHOLD);
1759 EXPECT_ROW3_NEAR(0.0, 1.0, 0.0, 0.0, A, ERROR_THRESHOLD);
1760 EXPECT_ROW4_EQ(0.0f, 0.0f, 0.0f, 1.0f, A);
1762 // Check rotation about y-axis. Note carefully, the expected pattern is
1763 // inverted compared to rotating about x axis or z axis.
1764 A.MakeIdentity();
1765 A.RotateAbout(Vector3dF(0.0, 1.0, 0.0), 90.0);
1766 EXPECT_ROW1_NEAR(0.0, 0.0, 1.0, 0.0, A, ERROR_THRESHOLD);
1767 EXPECT_ROW2_EQ(0.0f, 1.0f, 0.0f, 0.0f, A);
1768 EXPECT_ROW3_NEAR(-1.0, 0.0, 0.0, 0.0, A, ERROR_THRESHOLD);
1769 EXPECT_ROW4_EQ(0.0f, 0.0f, 0.0f, 1.0f, A);
1771 // Verify that rotate3d(axis, angle) post-multiplies the existing matrix.
1772 A.MakeIdentity();
1773 A.Scale3d(6.0, 7.0, 8.0);
1774 A.RotateAboutZAxis(90.0);
1775 EXPECT_ROW1_NEAR(0.0, -6.0, 0.0, 0.0, A, ERROR_THRESHOLD);
1776 EXPECT_ROW2_NEAR(7.0, 0.0, 0.0, 0.0, A, ERROR_THRESHOLD);
1777 EXPECT_ROW3_EQ(0.0f, 0.0f, 8.0f, 0.0f, A);
1778 EXPECT_ROW4_EQ(0.0f, 0.0f, 0.0f, 1.0f, A);
1781 TEST(XFormTest, verifyRotateAboutForArbitraryAxis) {
1782 // Check rotation about an arbitrary non-axis-aligned vector.
1783 Transform A;
1784 A.RotateAbout(Vector3dF(1.0, 1.0, 1.0), 90.0);
1785 EXPECT_ROW1_NEAR(0.3333333333333334258519187,
1786 -0.2440169358562924717404030,
1787 0.9106836025229592124219380,
1788 0.0, A, ERROR_THRESHOLD);
1789 EXPECT_ROW2_NEAR(0.9106836025229592124219380,
1790 0.3333333333333334258519187,
1791 -0.2440169358562924717404030,
1792 0.0, A, ERROR_THRESHOLD);
1793 EXPECT_ROW3_NEAR(-0.2440169358562924717404030,
1794 0.9106836025229592124219380,
1795 0.3333333333333334258519187,
1796 0.0, A, ERROR_THRESHOLD);
1797 EXPECT_ROW4_EQ(0.0f, 0.0f, 0.0f, 1.0f, A);
1800 TEST(XFormTest, verifyRotateAboutForDegenerateAxis) {
1801 // Check rotation about a degenerate zero vector.
1802 // It is expected to skip applying the rotation.
1803 Transform A;
1805 A.RotateAbout(Vector3dF(0.0, 0.0, 0.0), 45.0);
1806 // Verify that A remains unchanged.
1807 EXPECT_TRUE(A.IsIdentity());
1809 InitializeTestMatrix(&A);
1810 A.RotateAbout(Vector3dF(0.0, 0.0, 0.0), 35.0);
1812 // Verify that A remains unchanged.
1813 EXPECT_ROW1_EQ(10.0f, 14.0f, 18.0f, 22.0f, A);
1814 EXPECT_ROW2_EQ(11.0f, 15.0f, 19.0f, 23.0f, A);
1815 EXPECT_ROW3_EQ(12.0f, 16.0f, 20.0f, 24.0f, A);
1816 EXPECT_ROW4_EQ(13.0f, 17.0f, 21.0f, 25.0f, A);
1819 TEST(XFormTest, verifySkewX) {
1820 Transform A;
1821 A.SkewX(45.0);
1822 EXPECT_ROW1_EQ(1.0f, 1.0f, 0.0f, 0.0f, A);
1823 EXPECT_ROW2_EQ(0.0f, 1.0f, 0.0f, 0.0f, A);
1824 EXPECT_ROW3_EQ(0.0f, 0.0f, 1.0f, 0.0f, A);
1825 EXPECT_ROW4_EQ(0.0f, 0.0f, 0.0f, 1.0f, A);
1827 // Verify that skewX() post-multiplies the existing matrix. Row 1, column 2,
1828 // would incorrectly have value "7" if the matrix is pre-multiplied instead
1829 // of post-multiplied.
1830 A.MakeIdentity();
1831 A.Scale3d(6.0, 7.0, 8.0);
1832 A.SkewX(45.0);
1833 EXPECT_ROW1_EQ(6.0f, 6.0f, 0.0f, 0.0f, A);
1834 EXPECT_ROW2_EQ(0.0f, 7.0f, 0.0f, 0.0f, A);
1835 EXPECT_ROW3_EQ(0.0f, 0.0f, 8.0f, 0.0f, A);
1836 EXPECT_ROW4_EQ(0.0f, 0.0f, 0.0f, 1.0f, A);
1839 TEST(XFormTest, verifySkewY) {
1840 Transform A;
1841 A.SkewY(45.0);
1842 EXPECT_ROW1_EQ(1.0f, 0.0f, 0.0f, 0.0f, A);
1843 EXPECT_ROW2_EQ(1.0f, 1.0f, 0.0f, 0.0f, A);
1844 EXPECT_ROW3_EQ(0.0f, 0.0f, 1.0f, 0.0f, A);
1845 EXPECT_ROW4_EQ(0.0f, 0.0f, 0.0f, 1.0f, A);
1847 // Verify that skewY() post-multiplies the existing matrix. Row 2, column 1 ,
1848 // would incorrectly have value "6" if the matrix is pre-multiplied instead
1849 // of post-multiplied.
1850 A.MakeIdentity();
1851 A.Scale3d(6.0, 7.0, 8.0);
1852 A.SkewY(45.0);
1853 EXPECT_ROW1_EQ(6.0f, 0.0f, 0.0f, 0.0f, A);
1854 EXPECT_ROW2_EQ(7.0f, 7.0f, 0.0f, 0.0f, A);
1855 EXPECT_ROW3_EQ(0.0f, 0.0f, 8.0f, 0.0f, A);
1856 EXPECT_ROW4_EQ(0.0f, 0.0f, 0.0f, 1.0f, A);
1859 TEST(XFormTest, verifyPerspectiveDepth) {
1860 Transform A;
1861 A.ApplyPerspectiveDepth(1.0);
1862 EXPECT_ROW1_EQ(1.0f, 0.0f, 0.0f, 0.0f, A);
1863 EXPECT_ROW2_EQ(0.0f, 1.0f, 0.0f, 0.0f, A);
1864 EXPECT_ROW3_EQ(0.0f, 0.0f, 1.0f, 0.0f, A);
1865 EXPECT_ROW4_EQ(0.0f, 0.0f, -1.0f, 1.0f, A);
1867 // Verify that PerspectiveDepth() post-multiplies the existing matrix.
1868 A.MakeIdentity();
1869 A.Translate3d(2.0, 3.0, 4.0);
1870 A.ApplyPerspectiveDepth(1.0);
1871 EXPECT_ROW1_EQ(1.0f, 0.0f, -2.0f, 2.0f, A);
1872 EXPECT_ROW2_EQ(0.0f, 1.0f, -3.0f, 3.0f, A);
1873 EXPECT_ROW3_EQ(0.0f, 0.0f, -3.0f, 4.0f, A);
1874 EXPECT_ROW4_EQ(0.0f, 0.0f, -1.0f, 1.0f, A);
1877 TEST(XFormTest, verifyHasPerspective) {
1878 Transform A;
1879 A.ApplyPerspectiveDepth(1.0);
1880 EXPECT_TRUE(A.HasPerspective());
1882 A.MakeIdentity();
1883 A.ApplyPerspectiveDepth(0.0);
1884 EXPECT_FALSE(A.HasPerspective());
1886 A.MakeIdentity();
1887 A.matrix().setDouble(3, 0, -1.0);
1888 EXPECT_TRUE(A.HasPerspective());
1890 A.MakeIdentity();
1891 A.matrix().setDouble(3, 1, -1.0);
1892 EXPECT_TRUE(A.HasPerspective());
1894 A.MakeIdentity();
1895 A.matrix().setDouble(3, 2, -0.3);
1896 EXPECT_TRUE(A.HasPerspective());
1898 A.MakeIdentity();
1899 A.matrix().setDouble(3, 3, 0.5);
1900 EXPECT_TRUE(A.HasPerspective());
1902 A.MakeIdentity();
1903 A.matrix().setDouble(3, 3, 0.0);
1904 EXPECT_TRUE(A.HasPerspective());
1907 TEST(XFormTest, verifyIsInvertible) {
1908 Transform A;
1910 // Translations, rotations, scales, skews and arbitrary combinations of them
1911 // are invertible.
1912 A.MakeIdentity();
1913 EXPECT_TRUE(A.IsInvertible());
1915 A.MakeIdentity();
1916 A.Translate3d(2.0, 3.0, 4.0);
1917 EXPECT_TRUE(A.IsInvertible());
1919 A.MakeIdentity();
1920 A.Scale3d(6.0, 7.0, 8.0);
1921 EXPECT_TRUE(A.IsInvertible());
1923 A.MakeIdentity();
1924 A.RotateAboutXAxis(10.0);
1925 A.RotateAboutYAxis(20.0);
1926 A.RotateAboutZAxis(30.0);
1927 EXPECT_TRUE(A.IsInvertible());
1929 A.MakeIdentity();
1930 A.SkewX(45.0);
1931 EXPECT_TRUE(A.IsInvertible());
1933 // A perspective matrix (projection plane at z=0) is invertible. The
1934 // intuitive explanation is that perspective is eqivalent to a skew of the
1935 // w-axis; skews are invertible.
1936 A.MakeIdentity();
1937 A.ApplyPerspectiveDepth(1.0);
1938 EXPECT_TRUE(A.IsInvertible());
1940 // A "pure" perspective matrix derived by similar triangles, with m44() set
1941 // to zero (i.e. camera positioned at the origin), is not invertible.
1942 A.MakeIdentity();
1943 A.ApplyPerspectiveDepth(1.0);
1944 A.matrix().setDouble(3, 3, 0.0);
1945 EXPECT_FALSE(A.IsInvertible());
1947 // Adding more to a non-invertible matrix will not make it invertible in the
1948 // general case.
1949 A.MakeIdentity();
1950 A.ApplyPerspectiveDepth(1.0);
1951 A.matrix().setDouble(3, 3, 0.0);
1952 A.Scale3d(6.0, 7.0, 8.0);
1953 A.RotateAboutXAxis(10.0);
1954 A.RotateAboutYAxis(20.0);
1955 A.RotateAboutZAxis(30.0);
1956 A.Translate3d(6.0, 7.0, 8.0);
1957 EXPECT_FALSE(A.IsInvertible());
1959 // A degenerate matrix of all zeros is not invertible.
1960 A.MakeIdentity();
1961 A.matrix().setDouble(0, 0, 0.0);
1962 A.matrix().setDouble(1, 1, 0.0);
1963 A.matrix().setDouble(2, 2, 0.0);
1964 A.matrix().setDouble(3, 3, 0.0);
1965 EXPECT_FALSE(A.IsInvertible());
1968 TEST(XFormTest, verifyIsIdentity) {
1969 Transform A;
1971 InitializeTestMatrix(&A);
1972 EXPECT_FALSE(A.IsIdentity());
1974 A.MakeIdentity();
1975 EXPECT_TRUE(A.IsIdentity());
1977 // Modifying any one individual element should cause the matrix to no longer
1978 // be identity.
1979 A.MakeIdentity();
1980 A.matrix().setDouble(0, 0, 2.0);
1981 EXPECT_FALSE(A.IsIdentity());
1983 A.MakeIdentity();
1984 A.matrix().setDouble(1, 0, 2.0);
1985 EXPECT_FALSE(A.IsIdentity());
1987 A.MakeIdentity();
1988 A.matrix().setDouble(2, 0, 2.0);
1989 EXPECT_FALSE(A.IsIdentity());
1991 A.MakeIdentity();
1992 A.matrix().setDouble(3, 0, 2.0);
1993 EXPECT_FALSE(A.IsIdentity());
1995 A.MakeIdentity();
1996 A.matrix().setDouble(0, 1, 2.0);
1997 EXPECT_FALSE(A.IsIdentity());
1999 A.MakeIdentity();
2000 A.matrix().setDouble(1, 1, 2.0);
2001 EXPECT_FALSE(A.IsIdentity());
2003 A.MakeIdentity();
2004 A.matrix().setDouble(2, 1, 2.0);
2005 EXPECT_FALSE(A.IsIdentity());
2007 A.MakeIdentity();
2008 A.matrix().setDouble(3, 1, 2.0);
2009 EXPECT_FALSE(A.IsIdentity());
2011 A.MakeIdentity();
2012 A.matrix().setDouble(0, 2, 2.0);
2013 EXPECT_FALSE(A.IsIdentity());
2015 A.MakeIdentity();
2016 A.matrix().setDouble(1, 2, 2.0);
2017 EXPECT_FALSE(A.IsIdentity());
2019 A.MakeIdentity();
2020 A.matrix().setDouble(2, 2, 2.0);
2021 EXPECT_FALSE(A.IsIdentity());
2023 A.MakeIdentity();
2024 A.matrix().setDouble(3, 2, 2.0);
2025 EXPECT_FALSE(A.IsIdentity());
2027 A.MakeIdentity();
2028 A.matrix().setDouble(0, 3, 2.0);
2029 EXPECT_FALSE(A.IsIdentity());
2031 A.MakeIdentity();
2032 A.matrix().setDouble(1, 3, 2.0);
2033 EXPECT_FALSE(A.IsIdentity());
2035 A.MakeIdentity();
2036 A.matrix().setDouble(2, 3, 2.0);
2037 EXPECT_FALSE(A.IsIdentity());
2039 A.MakeIdentity();
2040 A.matrix().setDouble(3, 3, 2.0);
2041 EXPECT_FALSE(A.IsIdentity());
2044 TEST(XFormTest, verifyIsIdentityOrTranslation) {
2045 Transform A;
2047 InitializeTestMatrix(&A);
2048 EXPECT_FALSE(A.IsIdentityOrTranslation());
2050 A.MakeIdentity();
2051 EXPECT_TRUE(A.IsIdentityOrTranslation());
2053 // Modifying any non-translation components should cause
2054 // IsIdentityOrTranslation() to return false. NOTE: (0, 3), (1, 3), and
2055 // (2, 3) are the translation components, so modifying them should still
2056 // return true.
2057 A.MakeIdentity();
2058 A.matrix().setDouble(0, 0, 2.0);
2059 EXPECT_FALSE(A.IsIdentityOrTranslation());
2061 A.MakeIdentity();
2062 A.matrix().setDouble(1, 0, 2.0);
2063 EXPECT_FALSE(A.IsIdentityOrTranslation());
2065 A.MakeIdentity();
2066 A.matrix().setDouble(2, 0, 2.0);
2067 EXPECT_FALSE(A.IsIdentityOrTranslation());
2069 A.MakeIdentity();
2070 A.matrix().setDouble(3, 0, 2.0);
2071 EXPECT_FALSE(A.IsIdentityOrTranslation());
2073 A.MakeIdentity();
2074 A.matrix().setDouble(0, 1, 2.0);
2075 EXPECT_FALSE(A.IsIdentityOrTranslation());
2077 A.MakeIdentity();
2078 A.matrix().setDouble(1, 1, 2.0);
2079 EXPECT_FALSE(A.IsIdentityOrTranslation());
2081 A.MakeIdentity();
2082 A.matrix().setDouble(2, 1, 2.0);
2083 EXPECT_FALSE(A.IsIdentityOrTranslation());
2085 A.MakeIdentity();
2086 A.matrix().setDouble(3, 1, 2.0);
2087 EXPECT_FALSE(A.IsIdentityOrTranslation());
2089 A.MakeIdentity();
2090 A.matrix().setDouble(0, 2, 2.0);
2091 EXPECT_FALSE(A.IsIdentityOrTranslation());
2093 A.MakeIdentity();
2094 A.matrix().setDouble(1, 2, 2.0);
2095 EXPECT_FALSE(A.IsIdentityOrTranslation());
2097 A.MakeIdentity();
2098 A.matrix().setDouble(2, 2, 2.0);
2099 EXPECT_FALSE(A.IsIdentityOrTranslation());
2101 A.MakeIdentity();
2102 A.matrix().setDouble(3, 2, 2.0);
2103 EXPECT_FALSE(A.IsIdentityOrTranslation());
2105 // Note carefully - expecting true here.
2106 A.MakeIdentity();
2107 A.matrix().setDouble(0, 3, 2.0);
2108 EXPECT_TRUE(A.IsIdentityOrTranslation());
2110 // Note carefully - expecting true here.
2111 A.MakeIdentity();
2112 A.matrix().setDouble(1, 3, 2.0);
2113 EXPECT_TRUE(A.IsIdentityOrTranslation());
2115 // Note carefully - expecting true here.
2116 A.MakeIdentity();
2117 A.matrix().setDouble(2, 3, 2.0);
2118 EXPECT_TRUE(A.IsIdentityOrTranslation());
2120 A.MakeIdentity();
2121 A.matrix().setDouble(3, 3, 2.0);
2122 EXPECT_FALSE(A.IsIdentityOrTranslation());
2125 TEST(XFormTest, verifyIsScaleOrTranslation) {
2126 Transform A;
2128 InitializeTestMatrix(&A);
2129 EXPECT_FALSE(A.IsScaleOrTranslation());
2131 A.MakeIdentity();
2132 EXPECT_TRUE(A.IsScaleOrTranslation());
2134 // Modifying any non-scale or non-translation components should cause
2135 // IsScaleOrTranslation() to return false. (0, 0), (1, 1), (2, 2), (0, 3),
2136 // (1, 3), and (2, 3) are the scale and translation components, so
2137 // modifying them should still return true.
2139 // Note carefully - expecting true here.
2140 A.MakeIdentity();
2141 A.matrix().setDouble(0, 0, 2.0);
2142 EXPECT_TRUE(A.IsScaleOrTranslation());
2144 A.MakeIdentity();
2145 A.matrix().setDouble(1, 0, 2.0);
2146 EXPECT_FALSE(A.IsScaleOrTranslation());
2148 A.MakeIdentity();
2149 A.matrix().setDouble(2, 0, 2.0);
2150 EXPECT_FALSE(A.IsScaleOrTranslation());
2152 A.MakeIdentity();
2153 A.matrix().setDouble(3, 0, 2.0);
2154 EXPECT_FALSE(A.IsScaleOrTranslation());
2156 A.MakeIdentity();
2157 A.matrix().setDouble(0, 1, 2.0);
2158 EXPECT_FALSE(A.IsScaleOrTranslation());
2160 // Note carefully - expecting true here.
2161 A.MakeIdentity();
2162 A.matrix().setDouble(1, 1, 2.0);
2163 EXPECT_TRUE(A.IsScaleOrTranslation());
2165 A.MakeIdentity();
2166 A.matrix().setDouble(2, 1, 2.0);
2167 EXPECT_FALSE(A.IsScaleOrTranslation());
2169 A.MakeIdentity();
2170 A.matrix().setDouble(3, 1, 2.0);
2171 EXPECT_FALSE(A.IsScaleOrTranslation());
2173 A.MakeIdentity();
2174 A.matrix().setDouble(0, 2, 2.0);
2175 EXPECT_FALSE(A.IsScaleOrTranslation());
2177 A.MakeIdentity();
2178 A.matrix().setDouble(1, 2, 2.0);
2179 EXPECT_FALSE(A.IsScaleOrTranslation());
2181 // Note carefully - expecting true here.
2182 A.MakeIdentity();
2183 A.matrix().setDouble(2, 2, 2.0);
2184 EXPECT_TRUE(A.IsScaleOrTranslation());
2186 A.MakeIdentity();
2187 A.matrix().setDouble(3, 2, 2.0);
2188 EXPECT_FALSE(A.IsScaleOrTranslation());
2190 // Note carefully - expecting true here.
2191 A.MakeIdentity();
2192 A.matrix().setDouble(0, 3, 2.0);
2193 EXPECT_TRUE(A.IsScaleOrTranslation());
2195 // Note carefully - expecting true here.
2196 A.MakeIdentity();
2197 A.matrix().setDouble(1, 3, 2.0);
2198 EXPECT_TRUE(A.IsScaleOrTranslation());
2200 // Note carefully - expecting true here.
2201 A.MakeIdentity();
2202 A.matrix().setDouble(2, 3, 2.0);
2203 EXPECT_TRUE(A.IsScaleOrTranslation());
2205 A.MakeIdentity();
2206 A.matrix().setDouble(3, 3, 2.0);
2207 EXPECT_FALSE(A.IsScaleOrTranslation());
2210 TEST(XFormTest, verifyFlattenTo2d) {
2211 Transform A;
2212 InitializeTestMatrix(&A);
2214 A.FlattenTo2d();
2215 EXPECT_ROW1_EQ(10.0f, 14.0f, 0.0f, 22.0f, A);
2216 EXPECT_ROW2_EQ(11.0f, 15.0f, 0.0f, 23.0f, A);
2217 EXPECT_ROW3_EQ(0.0f, 0.0f, 1.0f, 0.0f, A);
2218 EXPECT_ROW4_EQ(13.0f, 17.0f, 0.0f, 25.0f, A);
2221 } // namespace
2223 } // namespace gfx