• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2011 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "SkMatrix44.h"
9 #include "Test.h"
10 
nearly_equal_double(double a,double b)11 static bool nearly_equal_double(double a, double b) {
12     const double tolerance = 1e-7;
13     double diff = a - b;
14     if (diff < 0)
15         diff = -diff;
16     return diff <= tolerance;
17 }
18 
nearly_equal_mscalar(SkMScalar a,SkMScalar b)19 static bool nearly_equal_mscalar(SkMScalar a, SkMScalar b) {
20     const SkMScalar tolerance = SK_MScalar1 / 200000;
21 
22     return SkTAbs<SkMScalar>(a - b) <= tolerance;
23 }
24 
nearly_equal_scalar(SkScalar a,SkScalar b)25 static bool nearly_equal_scalar(SkScalar a, SkScalar b) {
26     const SkScalar tolerance = SK_Scalar1 / 200000;
27     return SkScalarAbs(a - b) <= tolerance;
28 }
29 
assert16(skiatest::Reporter * reporter,const T data[],T m0,T m1,T m2,T m3,T m4,T m5,T m6,T m7,T m8,T m9,T m10,T m11,T m12,T m13,T m14,T m15)30 template <typename T> void assert16(skiatest::Reporter* reporter, const T data[],
31                                     T m0,  T m1,  T m2,  T m3,
32                                     T m4,  T m5,  T m6,  T m7,
33                                     T m8,  T m9,  T m10, T m11,
34                                     T m12, T m13, T m14, T m15) {
35     REPORTER_ASSERT(reporter, data[0] == m0);
36     REPORTER_ASSERT(reporter, data[1] == m1);
37     REPORTER_ASSERT(reporter, data[2] == m2);
38     REPORTER_ASSERT(reporter, data[3] == m3);
39 
40     REPORTER_ASSERT(reporter, data[4] == m4);
41     REPORTER_ASSERT(reporter, data[5] == m5);
42     REPORTER_ASSERT(reporter, data[6] == m6);
43     REPORTER_ASSERT(reporter, data[7] == m7);
44 
45     REPORTER_ASSERT(reporter, data[8] == m8);
46     REPORTER_ASSERT(reporter, data[9] == m9);
47     REPORTER_ASSERT(reporter, data[10] == m10);
48     REPORTER_ASSERT(reporter, data[11] == m11);
49 
50     REPORTER_ASSERT(reporter, data[12] == m12);
51     REPORTER_ASSERT(reporter, data[13] == m13);
52     REPORTER_ASSERT(reporter, data[14] == m14);
53     REPORTER_ASSERT(reporter, data[15] == m15);
54 }
55 
nearly_equal(const SkMatrix44 & a,const SkMatrix44 & b)56 static bool nearly_equal(const SkMatrix44& a, const SkMatrix44& b) {
57     for (int i = 0; i < 4; ++i) {
58         for (int j = 0; j < 4; ++j) {
59             if (!nearly_equal_mscalar(a.get(i, j), b.get(i, j))) {
60                 SkDebugf("not equal %g %g\n", a.get(i, j), b.get(i, j));
61                 return false;
62             }
63         }
64     }
65     return true;
66 }
67 
is_identity(const SkMatrix44 & m)68 static bool is_identity(const SkMatrix44& m) {
69     SkMatrix44 identity(SkMatrix44::kIdentity_Constructor);
70     return nearly_equal(m, identity);
71 }
72 
73 ///////////////////////////////////////////////////////////////////////////////
bits_isonly(int value,int mask)74 static bool bits_isonly(int value, int mask) {
75     return 0 == (value & ~mask);
76 }
77 
test_constructor(skiatest::Reporter * reporter)78 static void test_constructor(skiatest::Reporter* reporter) {
79     // Allocate a matrix on the heap
80     SkMatrix44* placeholderMatrix = new SkMatrix44(SkMatrix44::kUninitialized_Constructor);
81     SkAutoTDelete<SkMatrix44> deleteMe(placeholderMatrix);
82 
83     for (int row = 0; row < 4; ++row) {
84         for (int col = 0; col < 4; ++col) {
85             placeholderMatrix->setDouble(row, col, row * col);
86         }
87     }
88 
89     // Use placement-new syntax to trigger the constructor on top of the heap
90     // address we already initialized. This allows us to check that the
91     // constructor did avoid initializing the matrix contents.
92     SkMatrix44* testMatrix = new(placeholderMatrix) SkMatrix44(SkMatrix44::kUninitialized_Constructor);
93     REPORTER_ASSERT(reporter, testMatrix == placeholderMatrix);
94     REPORTER_ASSERT(reporter, !testMatrix->isIdentity());
95     for (int row = 0; row < 4; ++row) {
96         for (int col = 0; col < 4; ++col) {
97             REPORTER_ASSERT(reporter, nearly_equal_double(row * col, testMatrix->getDouble(row, col)));
98         }
99     }
100 
101     // Verify that kIdentity_Constructor really does initialize to an identity matrix.
102     testMatrix = 0;
103     testMatrix = new(placeholderMatrix) SkMatrix44(SkMatrix44::kIdentity_Constructor);
104     REPORTER_ASSERT(reporter, testMatrix == placeholderMatrix);
105     REPORTER_ASSERT(reporter, testMatrix->isIdentity());
106     REPORTER_ASSERT(reporter, *testMatrix == SkMatrix44::I());
107 }
108 
test_translate(skiatest::Reporter * reporter)109 static void test_translate(skiatest::Reporter* reporter) {
110     SkMatrix44 mat(SkMatrix44::kUninitialized_Constructor);
111     SkMatrix44 inverse(SkMatrix44::kUninitialized_Constructor);
112 
113     mat.setTranslate(0, 0, 0);
114     REPORTER_ASSERT(reporter, bits_isonly(mat.getType(), SkMatrix44::kIdentity_Mask));
115     mat.setTranslate(1, 2, 3);
116     REPORTER_ASSERT(reporter, bits_isonly(mat.getType(), SkMatrix44::kTranslate_Mask));
117     REPORTER_ASSERT(reporter, mat.invert(&inverse));
118     REPORTER_ASSERT(reporter, bits_isonly(inverse.getType(), SkMatrix44::kTranslate_Mask));
119 
120     SkMatrix44 a(SkMatrix44::kUninitialized_Constructor);
121     SkMatrix44 b(SkMatrix44::kUninitialized_Constructor);
122     SkMatrix44 c(SkMatrix44::kUninitialized_Constructor);
123     a.set3x3(1, 2, 3, 4, 5, 6, 7, 8, 9);
124     b.setTranslate(10, 11, 12);
125 
126     c.setConcat(a, b);
127     mat = a;
128     mat.preTranslate(10, 11, 12);
129     REPORTER_ASSERT(reporter, mat == c);
130 
131     c.setConcat(b, a);
132     mat = a;
133     mat.postTranslate(10, 11, 12);
134     REPORTER_ASSERT(reporter, mat == c);
135 }
136 
test_scale(skiatest::Reporter * reporter)137 static void test_scale(skiatest::Reporter* reporter) {
138     SkMatrix44 mat(SkMatrix44::kUninitialized_Constructor);
139     SkMatrix44 inverse(SkMatrix44::kUninitialized_Constructor);
140 
141     mat.setScale(1, 1, 1);
142     REPORTER_ASSERT(reporter, bits_isonly(mat.getType(), SkMatrix44::kIdentity_Mask));
143     mat.setScale(1, 2, 3);
144     REPORTER_ASSERT(reporter, bits_isonly(mat.getType(), SkMatrix44::kScale_Mask));
145     REPORTER_ASSERT(reporter, mat.invert(&inverse));
146     REPORTER_ASSERT(reporter, bits_isonly(inverse.getType(), SkMatrix44::kScale_Mask));
147 
148     SkMatrix44 a(SkMatrix44::kUninitialized_Constructor);
149     SkMatrix44 b(SkMatrix44::kUninitialized_Constructor);
150     SkMatrix44 c(SkMatrix44::kUninitialized_Constructor);
151     a.set3x3(1, 2, 3, 4, 5, 6, 7, 8, 9);
152     b.setScale(10, 11, 12);
153 
154     c.setConcat(a, b);
155     mat = a;
156     mat.preScale(10, 11, 12);
157     REPORTER_ASSERT(reporter, mat == c);
158 
159     c.setConcat(b, a);
160     mat = a;
161     mat.postScale(10, 11, 12);
162     REPORTER_ASSERT(reporter, mat == c);
163 }
164 
make_i(SkMatrix44 * mat)165 static void make_i(SkMatrix44* mat) { mat->setIdentity(); }
make_t(SkMatrix44 * mat)166 static void make_t(SkMatrix44* mat) { mat->setTranslate(1, 2, 3); }
make_s(SkMatrix44 * mat)167 static void make_s(SkMatrix44* mat) { mat->setScale(1, 2, 3); }
make_st(SkMatrix44 * mat)168 static void make_st(SkMatrix44* mat) {
169     mat->setScale(1, 2, 3);
170     mat->postTranslate(1, 2, 3);
171 }
make_a(SkMatrix44 * mat)172 static void make_a(SkMatrix44* mat) {
173     mat->setRotateDegreesAbout(1, 2, 3, 45);
174 }
make_p(SkMatrix44 * mat)175 static void make_p(SkMatrix44* mat) {
176     SkMScalar data[] = {
177         1, 2, 3, 4, 5, 6, 7, 8,
178         1, 2, 3, 4, 5, 6, 7, 8,
179     };
180     mat->setRowMajor(data);
181 }
182 
183 typedef void (*Make44Proc)(SkMatrix44*);
184 
185 static const Make44Proc gMakeProcs[] = {
186     make_i, make_t, make_s, make_st, make_a, make_p
187 };
188 
test_map2(skiatest::Reporter * reporter,const SkMatrix44 & mat)189 static void test_map2(skiatest::Reporter* reporter, const SkMatrix44& mat) {
190     SkMScalar src2[] = { 1, 2 };
191     SkMScalar src4[] = { src2[0], src2[1], 0, 1 };
192     SkMScalar dstA[4], dstB[4];
193 
194     for (int i = 0; i < 4; ++i) {
195         dstA[i] = 123456789;
196         dstB[i] = 987654321;
197     }
198 
199     mat.map2(src2, 1, dstA);
200     mat.mapMScalars(src4, dstB);
201 
202     for (int i = 0; i < 4; ++i) {
203         REPORTER_ASSERT(reporter, dstA[i] == dstB[i]);
204     }
205 }
206 
test_map2(skiatest::Reporter * reporter)207 static void test_map2(skiatest::Reporter* reporter) {
208     SkMatrix44 mat(SkMatrix44::kUninitialized_Constructor);
209 
210     for (size_t i = 0; i < SK_ARRAY_COUNT(gMakeProcs); ++i) {
211         gMakeProcs[i](&mat);
212         test_map2(reporter, mat);
213     }
214 }
215 
test_gettype(skiatest::Reporter * reporter)216 static void test_gettype(skiatest::Reporter* reporter) {
217     SkMatrix44 matrix(SkMatrix44::kIdentity_Constructor);
218 
219     REPORTER_ASSERT(reporter, matrix.isIdentity());
220     REPORTER_ASSERT(reporter, SkMatrix44::kIdentity_Mask == matrix.getType());
221 
222     int expectedMask;
223 
224     matrix.set(1, 1, 0);
225     expectedMask = SkMatrix44::kScale_Mask;
226     REPORTER_ASSERT(reporter, matrix.getType() == expectedMask);
227 
228     matrix.set(0, 3, 1);    // translate-x
229     expectedMask |= SkMatrix44::kTranslate_Mask;
230     REPORTER_ASSERT(reporter, matrix.getType() == expectedMask);
231 
232     matrix.set(2, 0, 1);
233     expectedMask |= SkMatrix44::kAffine_Mask;
234     REPORTER_ASSERT(reporter, matrix.getType() == expectedMask);
235 
236     matrix.set(3, 2, 1);
237     REPORTER_ASSERT(reporter, matrix.getType() & SkMatrix44::kPerspective_Mask);
238 
239     // ensure that negative zero is treated as zero
240     SkMScalar dx = 0;
241     SkMScalar dy = 0;
242     SkMScalar dz = 0;
243     matrix.setTranslate(-dx, -dy, -dz);
244     REPORTER_ASSERT(reporter, matrix.isIdentity());
245     matrix.preTranslate(-dx, -dy, -dz);
246     REPORTER_ASSERT(reporter, matrix.isIdentity());
247     matrix.postTranslate(-dx, -dy, -dz);
248     REPORTER_ASSERT(reporter, matrix.isIdentity());
249 }
250 
test_common_angles(skiatest::Reporter * reporter)251 static void test_common_angles(skiatest::Reporter* reporter) {
252     SkMatrix44 rot(SkMatrix44::kUninitialized_Constructor);
253     // Test precision of rotation in common cases
254     int common_angles[] = { 0, 90, -90, 180, -180, 270, -270, 360, -360 };
255     for (int i = 0; i < 9; ++i) {
256         rot.setRotateDegreesAbout(0, 0, -1, SkIntToScalar(common_angles[i]));
257 
258         SkMatrix rot3x3 = rot;
259         REPORTER_ASSERT(reporter, rot3x3.rectStaysRect());
260     }
261 }
262 
test_concat(skiatest::Reporter * reporter)263 static void test_concat(skiatest::Reporter* reporter) {
264     int i;
265     SkMatrix44 a(SkMatrix44::kUninitialized_Constructor);
266     SkMatrix44 b(SkMatrix44::kUninitialized_Constructor);
267     SkMatrix44 c(SkMatrix44::kUninitialized_Constructor);
268     SkMatrix44 d(SkMatrix44::kUninitialized_Constructor);
269 
270     a.setTranslate(10, 10, 10);
271     b.setScale(2, 2, 2);
272 
273     SkScalar src[8] = {
274         0, 0, 0, 1,
275         1, 1, 1, 1
276     };
277     SkScalar dst[8];
278 
279     c.setConcat(a, b);
280 
281     d = a;
282     d.preConcat(b);
283     REPORTER_ASSERT(reporter, d == c);
284 
285     c.mapScalars(src, dst); c.mapScalars(src + 4, dst + 4);
286     for (i = 0; i < 3; ++i) {
287         REPORTER_ASSERT(reporter, 10 == dst[i]);
288         REPORTER_ASSERT(reporter, 12 == dst[i + 4]);
289     }
290 
291     c.setConcat(b, a);
292 
293     d = a;
294     d.postConcat(b);
295     REPORTER_ASSERT(reporter, d == c);
296 
297     c.mapScalars(src, dst); c.mapScalars(src + 4, dst + 4);
298     for (i = 0; i < 3; ++i) {
299         REPORTER_ASSERT(reporter, 20 == dst[i]);
300         REPORTER_ASSERT(reporter, 22 == dst[i + 4]);
301     }
302 }
303 
test_determinant(skiatest::Reporter * reporter)304 static void test_determinant(skiatest::Reporter* reporter) {
305     SkMatrix44 a(SkMatrix44::kIdentity_Constructor);
306     REPORTER_ASSERT(reporter, nearly_equal_double(1, a.determinant()));
307     a.set(1, 1, 2);
308     REPORTER_ASSERT(reporter, nearly_equal_double(2, a.determinant()));
309     SkMatrix44 b(SkMatrix44::kUninitialized_Constructor);
310     REPORTER_ASSERT(reporter, a.invert(&b));
311     REPORTER_ASSERT(reporter, nearly_equal_double(0.5, b.determinant()));
312     SkMatrix44 c = b = a;
313     c.set(0, 1, 4);
314     b.set(1, 0, 4);
315     REPORTER_ASSERT(reporter,
316                     nearly_equal_double(a.determinant(),
317                                         b.determinant()));
318     SkMatrix44 d = a;
319     d.set(0, 0, 8);
320     REPORTER_ASSERT(reporter, nearly_equal_double(16, d.determinant()));
321 
322     SkMatrix44 e = a;
323     e.postConcat(d);
324     REPORTER_ASSERT(reporter, nearly_equal_double(32, e.determinant()));
325     e.set(0, 0, 0);
326     REPORTER_ASSERT(reporter, nearly_equal_double(0, e.determinant()));
327 }
328 
test_invert(skiatest::Reporter * reporter)329 static void test_invert(skiatest::Reporter* reporter) {
330     SkMatrix44 inverse(SkMatrix44::kUninitialized_Constructor);
331     double inverseData[16];
332 
333     SkMatrix44 identity(SkMatrix44::kIdentity_Constructor);
334     identity.invert(&inverse);
335     inverse.asRowMajord(inverseData);
336     assert16<double>(reporter, inverseData,
337                      1, 0, 0, 0,
338                      0, 1, 0, 0,
339                      0, 0, 1, 0,
340                      0, 0, 0, 1);
341 
342     SkMatrix44 translation(SkMatrix44::kUninitialized_Constructor);
343     translation.setTranslate(2, 3, 4);
344     translation.invert(&inverse);
345     inverse.asRowMajord(inverseData);
346     assert16<double>(reporter, inverseData,
347                      1, 0, 0, -2,
348                      0, 1, 0, -3,
349                      0, 0, 1, -4,
350                      0, 0, 0, 1);
351 
352     SkMatrix44 scale(SkMatrix44::kUninitialized_Constructor);
353     scale.setScale(2, 4, 8);
354     scale.invert(&inverse);
355     inverse.asRowMajord(inverseData);
356     assert16<double>(reporter, inverseData,
357                      0.5, 0,    0,     0,
358                      0,   0.25, 0,     0,
359                      0,   0,    0.125, 0,
360                      0,   0,    0,     1);
361 
362     SkMatrix44 scaleTranslation(SkMatrix44::kUninitialized_Constructor);
363     scaleTranslation.setScale(10, 100, 1000);
364     scaleTranslation.preTranslate(2, 3, 4);
365     scaleTranslation.invert(&inverse);
366     inverse.asRowMajord(inverseData);
367     assert16<double>(reporter, inverseData,
368                      0.1,  0,    0,   -2,
369                      0,   0.01,  0,   -3,
370                      0,    0,  0.001, -4,
371                      0,    0,    0,   1);
372 
373     SkMatrix44 rotation(SkMatrix44::kUninitialized_Constructor);
374     rotation.setRotateDegreesAbout(0, 0, 1, 90);
375     rotation.invert(&inverse);
376     SkMatrix44 expected(SkMatrix44::kUninitialized_Constructor);
377     double expectedInverseRotation[16] =
378             {0,  1, 0, 0,
379              -1, 0, 0, 0,
380              0,  0, 1, 0,
381              0,  0, 0, 1};
382     expected.setRowMajord(expectedInverseRotation);
383     REPORTER_ASSERT(reporter, nearly_equal(expected, inverse));
384 
385     SkMatrix44 affine(SkMatrix44::kUninitialized_Constructor);
386     affine.setRotateDegreesAbout(0, 0, 1, 90);
387     affine.preScale(10, 20, 100);
388     affine.preTranslate(2, 3, 4);
389     affine.invert(&inverse);
390     double expectedInverseAffine[16] =
391             {0,    0.1,  0,   -2,
392              -0.05, 0,   0,   -3,
393              0,     0,  0.01, -4,
394              0,     0,   0,   1};
395     expected.setRowMajord(expectedInverseAffine);
396     REPORTER_ASSERT(reporter, nearly_equal(expected, inverse));
397 
398     SkMatrix44 perspective(SkMatrix44::kIdentity_Constructor);
399     perspective.setDouble(3, 2, 1.0);
400     perspective.invert(&inverse);
401     double expectedInversePerspective[16] =
402             {1, 0,  0, 0,
403              0, 1,  0, 0,
404              0, 0,  1, 0,
405              0, 0, -1, 1};
406     expected.setRowMajord(expectedInversePerspective);
407     REPORTER_ASSERT(reporter, nearly_equal(expected, inverse));
408 
409     SkMatrix44 affineAndPerspective(SkMatrix44::kIdentity_Constructor);
410     affineAndPerspective.setDouble(3, 2, 1.0);
411     affineAndPerspective.preScale(10, 20, 100);
412     affineAndPerspective.preTranslate(2, 3, 4);
413     affineAndPerspective.invert(&inverse);
414     double expectedInverseAffineAndPerspective[16] =
415             {0.1, 0,    2,   -2,
416              0,  0.05,  3,   -3,
417              0,   0,   4.01, -4,
418              0,   0,   -1,    1};
419     expected.setRowMajord(expectedInverseAffineAndPerspective);
420     REPORTER_ASSERT(reporter, nearly_equal(expected, inverse));
421 }
422 
test_transpose(skiatest::Reporter * reporter)423 static void test_transpose(skiatest::Reporter* reporter) {
424     SkMatrix44 a(SkMatrix44::kUninitialized_Constructor);
425     SkMatrix44 b(SkMatrix44::kUninitialized_Constructor);
426 
427     int i = 0;
428     for (int row = 0; row < 4; ++row) {
429         for (int col = 0; col < 4; ++col) {
430             a.setDouble(row, col, i);
431             b.setDouble(col, row, i++);
432         }
433     }
434 
435     a.transpose();
436     REPORTER_ASSERT(reporter, nearly_equal(a, b));
437 }
438 
test_get_set_double(skiatest::Reporter * reporter)439 static void test_get_set_double(skiatest::Reporter* reporter) {
440     SkMatrix44 a(SkMatrix44::kUninitialized_Constructor);
441     for (int row = 0; row < 4; ++row) {
442         for (int col = 0; col < 4; ++col) {
443             a.setDouble(row, col, 3.141592653589793);
444             REPORTER_ASSERT(reporter,
445                             nearly_equal_double(3.141592653589793,
446                                                 a.getDouble(row, col)));
447             a.setDouble(row, col, 0);
448             REPORTER_ASSERT(reporter,
449                             nearly_equal_double(0, a.getDouble(row, col)));
450         }
451     }
452 }
453 
test_set_row_col_major(skiatest::Reporter * reporter)454 static void test_set_row_col_major(skiatest::Reporter* reporter) {
455     SkMatrix44 a(SkMatrix44::kUninitialized_Constructor);
456     SkMatrix44 b(SkMatrix44::kUninitialized_Constructor);
457 
458     for (int row = 0; row < 4; ++row) {
459         for (int col = 0; col < 4; ++col) {
460             a.setDouble(row, col, row * 4 + col);
461         }
462     }
463 
464     double bufferd[16];
465     float bufferf[16];
466     a.asColMajord(bufferd);
467     b.setColMajord(bufferd);
468     REPORTER_ASSERT(reporter, nearly_equal(a, b));
469     b.setRowMajord(bufferd);
470     b.transpose();
471     REPORTER_ASSERT(reporter, nearly_equal(a, b));
472     a.asColMajorf(bufferf);
473     b.setColMajorf(bufferf);
474     REPORTER_ASSERT(reporter, nearly_equal(a, b));
475     b.setRowMajorf(bufferf);
476     b.transpose();
477     REPORTER_ASSERT(reporter, nearly_equal(a, b));
478 }
479 
test_3x3_conversion(skiatest::Reporter * reporter)480 static void test_3x3_conversion(skiatest::Reporter* reporter) {
481     SkMScalar values4x4[16] = { 1, 2, 3, 4,
482                                 5, 6, 7, 8,
483                                 9, 10, 11, 12,
484                                 13, 14, 15, 16 };
485     SkScalar values3x3[9] = { 1, 2, 4,
486                               5, 6, 8,
487                               13, 14, 16 };
488     SkMScalar values4x4flattened[16] = { 1, 2, 0, 4,
489                                          5, 6, 0, 8,
490                                          0, 0, 1, 0,
491                                          13, 14, 0, 16 };
492     SkMatrix44 a44(SkMatrix44::kUninitialized_Constructor);
493     a44.setRowMajor(values4x4);
494 
495     SkMatrix a33 = a44;
496     SkMatrix expected33;
497     for (int i = 0; i < 9; i++) expected33[i] = values3x3[i];
498     REPORTER_ASSERT(reporter, expected33 == a33);
499 
500     SkMatrix44 a44flattened = a33;
501     SkMatrix44 expected44flattened(SkMatrix44::kUninitialized_Constructor);
502     expected44flattened.setRowMajor(values4x4flattened);
503     REPORTER_ASSERT(reporter, nearly_equal(a44flattened, expected44flattened));
504 
505     // Test that a point with a Z value of 0 is transformed the same way.
506     SkScalar vec4[4] = { 2, 4, 0, 8 };
507     SkScalar vec3[3] = { 2, 4, 8 };
508 
509     SkScalar vec4transformed[4];
510     SkScalar vec3transformed[3];
511     SkScalar vec4transformed2[4];
512     a44.mapScalars(vec4, vec4transformed);
513     a33.mapHomogeneousPoints(vec3transformed, vec3, 1);
514     a44flattened.mapScalars(vec4, vec4transformed2);
515     REPORTER_ASSERT(reporter, nearly_equal_scalar(vec4transformed[0], vec3transformed[0]));
516     REPORTER_ASSERT(reporter, nearly_equal_scalar(vec4transformed[1], vec3transformed[1]));
517     REPORTER_ASSERT(reporter, nearly_equal_scalar(vec4transformed[3], vec3transformed[2]));
518     REPORTER_ASSERT(reporter, nearly_equal_scalar(vec4transformed[0], vec4transformed2[0]));
519     REPORTER_ASSERT(reporter, nearly_equal_scalar(vec4transformed[1], vec4transformed2[1]));
520     REPORTER_ASSERT(reporter, !nearly_equal_scalar(vec4transformed[2], vec4transformed2[2]));
521     REPORTER_ASSERT(reporter, nearly_equal_scalar(vec4transformed[3], vec4transformed2[3]));
522 }
523 
DEF_TEST(Matrix44,reporter)524 DEF_TEST(Matrix44, reporter) {
525     SkMatrix44 mat(SkMatrix44::kUninitialized_Constructor);
526     SkMatrix44 inverse(SkMatrix44::kUninitialized_Constructor);
527     SkMatrix44 iden1(SkMatrix44::kUninitialized_Constructor);
528     SkMatrix44 iden2(SkMatrix44::kUninitialized_Constructor);
529     SkMatrix44 rot(SkMatrix44::kUninitialized_Constructor);
530 
531     mat.setTranslate(1, 1, 1);
532     mat.invert(&inverse);
533     iden1.setConcat(mat, inverse);
534     REPORTER_ASSERT(reporter, is_identity(iden1));
535 
536     mat.setScale(2, 2, 2);
537     mat.invert(&inverse);
538     iden1.setConcat(mat, inverse);
539     REPORTER_ASSERT(reporter, is_identity(iden1));
540 
541     mat.setScale(SK_MScalar1/2, SK_MScalar1/2, SK_MScalar1/2);
542     mat.invert(&inverse);
543     iden1.setConcat(mat, inverse);
544     REPORTER_ASSERT(reporter, is_identity(iden1));
545 
546     mat.setScale(3, 3, 3);
547     rot.setRotateDegreesAbout(0, 0, -1, 90);
548     mat.postConcat(rot);
549     REPORTER_ASSERT(reporter, mat.invert(NULL));
550     mat.invert(&inverse);
551     iden1.setConcat(mat, inverse);
552     REPORTER_ASSERT(reporter, is_identity(iden1));
553     iden2.setConcat(inverse, mat);
554     REPORTER_ASSERT(reporter, is_identity(iden2));
555 
556     // test tiny-valued matrix inverse
557     mat.reset();
558     mat.setScale(1.0e-12, 1.0e-12, 1.0e-12);
559     rot.setRotateDegreesAbout(0, 0, -1, 90);
560     mat.postConcat(rot);
561     mat.postTranslate(1.0e-12, 1.0e-12, 1.0e-12);
562     REPORTER_ASSERT(reporter, mat.invert(NULL));
563     mat.invert(&inverse);
564     iden1.setConcat(mat, inverse);
565     REPORTER_ASSERT(reporter, is_identity(iden1));
566 
567     // test mixed-valued matrix inverse
568     mat.reset();
569     mat.setScale(1.0e-10, 3.0, 1.0e+10);
570     rot.setRotateDegreesAbout(0, 0, -1, 90);
571     mat.postConcat(rot);
572     mat.postTranslate(1.0e+10, 3.0, 1.0e-10);
573     REPORTER_ASSERT(reporter, mat.invert(NULL));
574     mat.invert(&inverse);
575     iden1.setConcat(mat, inverse);
576     REPORTER_ASSERT(reporter, is_identity(iden1));
577 
578     // test degenerate matrix
579     mat.reset();
580     mat.set3x3(1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0);
581     REPORTER_ASSERT(reporter, !mat.invert(NULL));
582 
583     // test rol/col Major getters
584     {
585         mat.setTranslate(2, 3, 4);
586         float dataf[16];
587         double datad[16];
588 
589         mat.asColMajorf(dataf);
590         assert16<float>(reporter, dataf,
591                  1, 0, 0, 0,
592                  0, 1, 0, 0,
593                  0, 0, 1, 0,
594                  2, 3, 4, 1);
595         mat.asColMajord(datad);
596         assert16<double>(reporter, datad, 1, 0, 0, 0,
597                         0, 1, 0, 0,
598                         0, 0, 1, 0,
599                         2, 3, 4, 1);
600         mat.asRowMajorf(dataf);
601         assert16<float>(reporter, dataf, 1, 0, 0, 2,
602                         0, 1, 0, 3,
603                         0, 0, 1, 4,
604                         0, 0, 0, 1);
605         mat.asRowMajord(datad);
606         assert16<double>(reporter, datad, 1, 0, 0, 2,
607                         0, 1, 0, 3,
608                         0, 0, 1, 4,
609                         0, 0, 0, 1);
610     }
611 
612     test_concat(reporter);
613 
614     if (false) { // avoid bit rot, suppress warning (working on making this pass)
615         test_common_angles(reporter);
616     }
617 
618     test_constructor(reporter);
619     test_gettype(reporter);
620     test_determinant(reporter);
621     test_invert(reporter);
622     test_transpose(reporter);
623     test_get_set_double(reporter);
624     test_set_row_col_major(reporter);
625     test_translate(reporter);
626     test_scale(reporter);
627     test_map2(reporter);
628     test_3x3_conversion(reporter);
629 }
630