1#include "Test.h" 2#include "SkMatrix.h" 3 4static bool nearly_equal_scalar(SkScalar a, SkScalar b) { 5 // Note that we get more compounded error for multiple operations when 6 // SK_SCALAR_IS_FIXED. 7#ifdef SK_SCALAR_IS_FLOAT 8 const SkScalar tolerance = SK_Scalar1 / 200000; 9#else 10 const SkScalar tolerance = SK_Scalar1 / 1024; 11#endif 12 13 return SkScalarAbs(a - b) <= tolerance; 14} 15 16static bool nearly_equal(const SkMatrix& a, const SkMatrix& b) { 17 for (int i = 0; i < 9; i++) { 18 if (!nearly_equal_scalar(a[i], b[i])) { 19 printf("not equal %g %g\n", (float)a[i], (float)b[i]); 20 return false; 21 } 22 } 23 return true; 24} 25 26static bool is_identity(const SkMatrix& m) { 27 SkMatrix identity; 28 identity.reset(); 29 return nearly_equal(m, identity); 30} 31 32static void test_flatten(skiatest::Reporter* reporter, const SkMatrix& m) { 33 // add 100 in case we have a bug, I don't want to kill my stack in the test 34 char buffer[SkMatrix::kMaxFlattenSize + 100]; 35 uint32_t size1 = m.flatten(NULL); 36 uint32_t size2 = m.flatten(buffer); 37 REPORTER_ASSERT(reporter, size1 == size2); 38 REPORTER_ASSERT(reporter, size1 <= SkMatrix::kMaxFlattenSize); 39 40 SkMatrix m2; 41 uint32_t size3 = m2.unflatten(buffer); 42 REPORTER_ASSERT(reporter, size1 == size2); 43 REPORTER_ASSERT(reporter, m == m2); 44 45 char buffer2[SkMatrix::kMaxFlattenSize + 100]; 46 size3 = m2.flatten(buffer2); 47 REPORTER_ASSERT(reporter, size1 == size2); 48 REPORTER_ASSERT(reporter, memcmp(buffer, buffer2, size1) == 0); 49} 50 51void TestMatrix(skiatest::Reporter* reporter) { 52 SkMatrix mat, inverse, iden1, iden2; 53 54 mat.reset(); 55 mat.setTranslate(SK_Scalar1, SK_Scalar1); 56 mat.invert(&inverse); 57 iden1.setConcat(mat, inverse); 58 REPORTER_ASSERT(reporter, is_identity(iden1)); 59 60 mat.setScale(SkIntToScalar(2), SkIntToScalar(2)); 61 mat.invert(&inverse); 62 iden1.setConcat(mat, inverse); 63 REPORTER_ASSERT(reporter, is_identity(iden1)); 64 test_flatten(reporter, mat); 65 66 mat.setScale(SK_Scalar1/2, SK_Scalar1/2); 67 mat.invert(&inverse); 68 iden1.setConcat(mat, inverse); 69 REPORTER_ASSERT(reporter, is_identity(iden1)); 70 test_flatten(reporter, mat); 71 72 mat.setScale(SkIntToScalar(3), SkIntToScalar(5), SkIntToScalar(20), 0); 73 mat.postRotate(SkIntToScalar(25)); 74 REPORTER_ASSERT(reporter, mat.invert(NULL)); 75 mat.invert(&inverse); 76 iden1.setConcat(mat, inverse); 77 REPORTER_ASSERT(reporter, is_identity(iden1)); 78 iden2.setConcat(inverse, mat); 79 REPORTER_ASSERT(reporter, is_identity(iden2)); 80 test_flatten(reporter, mat); 81 test_flatten(reporter, iden2); 82 83 // rectStaysRect test 84 { 85 static const struct { 86 SkScalar m00, m01, m10, m11; 87 bool mStaysRect; 88 } 89 gRectStaysRectSamples[] = { 90 { 0, 0, 0, 0, false }, 91 { 0, 0, 0, SK_Scalar1, false }, 92 { 0, 0, SK_Scalar1, 0, false }, 93 { 0, 0, SK_Scalar1, SK_Scalar1, false }, 94 { 0, SK_Scalar1, 0, 0, false }, 95 { 0, SK_Scalar1, 0, SK_Scalar1, false }, 96 { 0, SK_Scalar1, SK_Scalar1, 0, true }, 97 { 0, SK_Scalar1, SK_Scalar1, SK_Scalar1, false }, 98 { SK_Scalar1, 0, 0, 0, false }, 99 { SK_Scalar1, 0, 0, SK_Scalar1, true }, 100 { SK_Scalar1, 0, SK_Scalar1, 0, false }, 101 { SK_Scalar1, 0, SK_Scalar1, SK_Scalar1, false }, 102 { SK_Scalar1, SK_Scalar1, 0, 0, false }, 103 { SK_Scalar1, SK_Scalar1, 0, SK_Scalar1, false }, 104 { SK_Scalar1, SK_Scalar1, SK_Scalar1, 0, false }, 105 { SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_Scalar1, false } 106 }; 107 108 for (size_t i = 0; i < SK_ARRAY_COUNT(gRectStaysRectSamples); i++) { 109 SkMatrix m; 110 111 m.reset(); 112 m.set(SkMatrix::kMScaleX, gRectStaysRectSamples[i].m00); 113 m.set(SkMatrix::kMSkewX, gRectStaysRectSamples[i].m01); 114 m.set(SkMatrix::kMSkewY, gRectStaysRectSamples[i].m10); 115 m.set(SkMatrix::kMScaleY, gRectStaysRectSamples[i].m11); 116 REPORTER_ASSERT(reporter, 117 m.rectStaysRect() == gRectStaysRectSamples[i].mStaysRect); 118 } 119 } 120} 121 122#include "TestClassDef.h" 123DEFINE_TESTCLASS("Matrix", MatrixTestClass, TestMatrix) 124