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