Home | History | Annotate | Download | only in tests
      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 }
    660