| #include "Test.h" | 
 | #include "SkMatrix.h" | 
 |  | 
 | static bool nearly_equal_scalar(SkScalar a, SkScalar b) { | 
 | #ifdef SK_SCALAR_IS_FLOAT | 
 |     const float tolerance = 0.000005f; | 
 | #else | 
 |     const int32_t tolerance = 8; | 
 | #endif | 
 |  | 
 |     return SkScalarAbs(a - b) <= tolerance; | 
 | } | 
 |  | 
 | static bool nearly_equal(const SkMatrix& a, const SkMatrix& b) { | 
 |     for (int i = 0; i < 9; i++) { | 
 |         if (!nearly_equal_scalar(a[i], b[i])) { | 
 |             printf("not equal %g %g\n", (float)a[i], (float)b[i]); | 
 |             return false; | 
 |         } | 
 |     } | 
 |     return true; | 
 | } | 
 |  | 
 | static bool is_identity(const SkMatrix& m) { | 
 |     SkMatrix identity; | 
 |     identity.reset(); | 
 |     return nearly_equal(m, identity); | 
 | } | 
 |  | 
 | static void test_flatten(skiatest::Reporter* reporter, const SkMatrix& m) { | 
 |     // add 100 in case we have a bug, I don't want to kill my stack in the test | 
 |     char buffer[SkMatrix::kMaxFlattenSize + 100]; | 
 |     uint32_t size1 = m.flatten(NULL); | 
 |     uint32_t size2 = m.flatten(buffer); | 
 |     REPORTER_ASSERT(reporter, size1 == size2); | 
 |     REPORTER_ASSERT(reporter, size1 <= SkMatrix::kMaxFlattenSize); | 
 |      | 
 |     SkMatrix m2; | 
 |     uint32_t size3 = m2.unflatten(buffer); | 
 |     REPORTER_ASSERT(reporter, size1 == size2); | 
 |     REPORTER_ASSERT(reporter, m == m2); | 
 |      | 
 |     char buffer2[SkMatrix::kMaxFlattenSize + 100]; | 
 |     size3 = m2.flatten(buffer2); | 
 |     REPORTER_ASSERT(reporter, size1 == size2); | 
 |     REPORTER_ASSERT(reporter, memcmp(buffer, buffer2, size1) == 0); | 
 | } | 
 |  | 
 | void TestMatrix(skiatest::Reporter* reporter) { | 
 |     SkMatrix    mat, inverse, iden1, iden2; | 
 |  | 
 |     mat.reset(); | 
 |     mat.setTranslate(SK_Scalar1, SK_Scalar1); | 
 |     mat.invert(&inverse); | 
 |     iden1.setConcat(mat, inverse); | 
 |     REPORTER_ASSERT(reporter, is_identity(iden1)); | 
 |  | 
 |     mat.setScale(SkIntToScalar(2), SkIntToScalar(2)); | 
 |     mat.invert(&inverse); | 
 |     iden1.setConcat(mat, inverse); | 
 |     REPORTER_ASSERT(reporter, is_identity(iden1)); | 
 |     test_flatten(reporter, mat); | 
 |  | 
 |     mat.setScale(SK_Scalar1/2, SK_Scalar1/2); | 
 |     mat.invert(&inverse); | 
 |     iden1.setConcat(mat, inverse); | 
 |     REPORTER_ASSERT(reporter, is_identity(iden1)); | 
 |     test_flatten(reporter, mat); | 
 |  | 
 |     mat.setScale(SkIntToScalar(3), SkIntToScalar(5), SkIntToScalar(20), 0); | 
 |     mat.postRotate(SkIntToScalar(25)); | 
 |     REPORTER_ASSERT(reporter, mat.invert(NULL)); | 
 |     mat.invert(&inverse); | 
 |     iden1.setConcat(mat, inverse); | 
 |     REPORTER_ASSERT(reporter, is_identity(iden1)); | 
 |     iden2.setConcat(inverse, mat); | 
 |     REPORTER_ASSERT(reporter, is_identity(iden2)); | 
 |     test_flatten(reporter, mat); | 
 |     test_flatten(reporter, iden2); | 
 |  | 
 |     // rectStaysRect test | 
 |     { | 
 |         static const struct { | 
 |             SkScalar    m00, m01, m10, m11; | 
 |             bool        mStaysRect; | 
 |         } | 
 |         gRectStaysRectSamples[] = { | 
 |             {          0,          0,          0,           0, false }, | 
 |             {          0,          0,          0,  SK_Scalar1, false }, | 
 |             {          0,          0, SK_Scalar1,           0, false }, | 
 |             {          0,          0, SK_Scalar1,  SK_Scalar1, false }, | 
 |             {          0, SK_Scalar1,          0,           0, false }, | 
 |             {          0, SK_Scalar1,          0,  SK_Scalar1, false }, | 
 |             {          0, SK_Scalar1, SK_Scalar1,           0, true }, | 
 |             {          0, SK_Scalar1, SK_Scalar1,  SK_Scalar1, false }, | 
 |             { SK_Scalar1,          0,          0,           0, false }, | 
 |             { SK_Scalar1,          0,          0,  SK_Scalar1, true }, | 
 |             { SK_Scalar1,          0, SK_Scalar1,           0, false }, | 
 |             { SK_Scalar1,          0, SK_Scalar1,  SK_Scalar1, false }, | 
 |             { SK_Scalar1, SK_Scalar1,          0,           0, false }, | 
 |             { SK_Scalar1, SK_Scalar1,          0,  SK_Scalar1, false }, | 
 |             { SK_Scalar1, SK_Scalar1, SK_Scalar1,           0, false }, | 
 |             { SK_Scalar1, SK_Scalar1, SK_Scalar1,  SK_Scalar1, false } | 
 |         }; | 
 |  | 
 |         for (size_t i = 0; i < SK_ARRAY_COUNT(gRectStaysRectSamples); i++) { | 
 |             SkMatrix    m; | 
 |  | 
 |             m.reset(); | 
 |             m.set(SkMatrix::kMScaleX, gRectStaysRectSamples[i].m00); | 
 |             m.set(SkMatrix::kMSkewX,  gRectStaysRectSamples[i].m01); | 
 |             m.set(SkMatrix::kMSkewY,  gRectStaysRectSamples[i].m10); | 
 |             m.set(SkMatrix::kMScaleY, gRectStaysRectSamples[i].m11); | 
 |             REPORTER_ASSERT(reporter, | 
 |                     m.rectStaysRect() == gRectStaysRectSamples[i].mStaysRect); | 
 |         } | 
 |     } | 
 | } | 
 |  | 
 | #include "TestClassDef.h" | 
 | DEFINE_TESTCLASS("Matrix", MatrixTestClass, TestMatrix) |