Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / tests / Matrix44Test.cpp
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
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
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
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
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
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
68 static bool is_identity(const SkMatrix44& m) {
69     SkMatrix44 identity(SkMatrix44::kIdentity_Constructor);
70     return nearly_equal(m, identity);
71 }
72
73 ///////////////////////////////////////////////////////////////////////////////
74 static bool bits_isonly(int value, int mask) {
75     return 0 == (value & ~mask);
76 }
77
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
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
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
165 static void make_i(SkMatrix44* mat) { mat->setIdentity(); }
166 static void make_t(SkMatrix44* mat) { mat->setTranslate(1, 2, 3); }
167 static void make_s(SkMatrix44* mat) { mat->setScale(1, 2, 3); }
168 static void make_st(SkMatrix44* mat) {
169     mat->setScale(1, 2, 3);
170     mat->postTranslate(1, 2, 3);
171 }
172 static void make_a(SkMatrix44* mat) {
173     mat->setRotateDegreesAbout(1, 2, 3, 45);
174 }
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
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
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
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
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
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
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
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
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
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
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
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
524 static void test_has_perspective(skiatest::Reporter* reporter) {
525     SkMatrix44 transform(SkMatrix44::kIdentity_Constructor);
526
527     transform.set(3, 2, -0.1);
528     REPORTER_ASSERT(reporter, transform.hasPerspective());
529
530     transform.reset();
531     REPORTER_ASSERT(reporter, !transform.hasPerspective());
532
533     transform.set(3, 0, -1.0);
534     REPORTER_ASSERT(reporter, transform.hasPerspective());
535
536     transform.reset();
537     transform.set(3, 1, -1.0);
538     REPORTER_ASSERT(reporter, transform.hasPerspective());
539
540     transform.reset();
541     transform.set(3, 2, -0.3);
542     REPORTER_ASSERT(reporter, transform.hasPerspective());
543
544     transform.reset();
545     transform.set(3, 3, 0.5);
546     REPORTER_ASSERT(reporter, transform.hasPerspective());
547  
548     transform.reset();
549     transform.set(3, 3, 0.0);
550     REPORTER_ASSERT(reporter, transform.hasPerspective());
551 }
552
553 DEF_TEST(Matrix44, reporter) {
554     SkMatrix44 mat(SkMatrix44::kUninitialized_Constructor);
555     SkMatrix44 inverse(SkMatrix44::kUninitialized_Constructor);
556     SkMatrix44 iden1(SkMatrix44::kUninitialized_Constructor);
557     SkMatrix44 iden2(SkMatrix44::kUninitialized_Constructor);
558     SkMatrix44 rot(SkMatrix44::kUninitialized_Constructor);
559
560     mat.setTranslate(1, 1, 1);
561     mat.invert(&inverse);
562     iden1.setConcat(mat, inverse);
563     REPORTER_ASSERT(reporter, is_identity(iden1));
564
565     mat.setScale(2, 2, 2);
566     mat.invert(&inverse);
567     iden1.setConcat(mat, inverse);
568     REPORTER_ASSERT(reporter, is_identity(iden1));
569
570     mat.setScale(SK_MScalar1/2, SK_MScalar1/2, SK_MScalar1/2);
571     mat.invert(&inverse);
572     iden1.setConcat(mat, inverse);
573     REPORTER_ASSERT(reporter, is_identity(iden1));
574
575     mat.setScale(3, 3, 3);
576     rot.setRotateDegreesAbout(0, 0, -1, 90);
577     mat.postConcat(rot);
578     REPORTER_ASSERT(reporter, mat.invert(NULL));
579     mat.invert(&inverse);
580     iden1.setConcat(mat, inverse);
581     REPORTER_ASSERT(reporter, is_identity(iden1));
582     iden2.setConcat(inverse, mat);
583     REPORTER_ASSERT(reporter, is_identity(iden2));
584
585     // test tiny-valued matrix inverse
586     mat.reset();
587     mat.setScale(1.0e-12, 1.0e-12, 1.0e-12);
588     rot.setRotateDegreesAbout(0, 0, -1, 90);
589     mat.postConcat(rot);
590     mat.postTranslate(1.0e-12, 1.0e-12, 1.0e-12);
591     REPORTER_ASSERT(reporter, mat.invert(NULL));
592     mat.invert(&inverse);
593     iden1.setConcat(mat, inverse);
594     REPORTER_ASSERT(reporter, is_identity(iden1));
595
596     // test mixed-valued matrix inverse
597     mat.reset();
598     mat.setScale(1.0e-10, 3.0, 1.0e+10);
599     rot.setRotateDegreesAbout(0, 0, -1, 90);
600     mat.postConcat(rot);
601     mat.postTranslate(1.0e+10, 3.0, 1.0e-10);
602     REPORTER_ASSERT(reporter, mat.invert(NULL));
603     mat.invert(&inverse);
604     iden1.setConcat(mat, inverse);
605     REPORTER_ASSERT(reporter, is_identity(iden1));
606
607     // test degenerate matrix
608     mat.reset();
609     mat.set3x3(1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0);
610     REPORTER_ASSERT(reporter, !mat.invert(NULL));
611
612     // test rol/col Major getters
613     {
614         mat.setTranslate(2, 3, 4);
615         float dataf[16];
616         double datad[16];
617
618         mat.asColMajorf(dataf);
619         assert16<float>(reporter, dataf,
620                  1, 0, 0, 0,
621                  0, 1, 0, 0,
622                  0, 0, 1, 0,
623                  2, 3, 4, 1);
624         mat.asColMajord(datad);
625         assert16<double>(reporter, datad, 1, 0, 0, 0,
626                         0, 1, 0, 0,
627                         0, 0, 1, 0,
628                         2, 3, 4, 1);
629         mat.asRowMajorf(dataf);
630         assert16<float>(reporter, dataf, 1, 0, 0, 2,
631                         0, 1, 0, 3,
632                         0, 0, 1, 4,
633                         0, 0, 0, 1);
634         mat.asRowMajord(datad);
635         assert16<double>(reporter, datad, 1, 0, 0, 2,
636                         0, 1, 0, 3,
637                         0, 0, 1, 4,
638                         0, 0, 0, 1);
639     }
640
641     test_concat(reporter);
642
643     if (false) { // avoid bit rot, suppress warning (working on making this pass)
644         test_common_angles(reporter);
645     }
646
647     test_constructor(reporter);
648     test_gettype(reporter);
649     test_determinant(reporter);
650     test_invert(reporter);
651     test_transpose(reporter);
652     test_get_set_double(reporter);
653     test_set_row_col_major(reporter);
654     test_translate(reporter);
655     test_scale(reporter);
656     test_map2(reporter);
657     test_3x3_conversion(reporter);
658     test_has_perspective(reporter);
659 }