| #include "Test.h" |
| #include "SkMatrix.h" |
| |
| static bool nearly_equal_scalar(SkScalar a, SkScalar b) { |
| // Note that we get more compounded error for multiple operations when |
| // SK_SCALAR_IS_FIXED. |
| #ifdef SK_SCALAR_IS_FLOAT |
| const SkScalar tolerance = SK_Scalar1 / 200000; |
| #else |
| const SkScalar tolerance = SK_Scalar1 / 1024; |
| #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); |
| } |
| } |
| |
| mat.reset(); |
| mat.set(SkMatrix::kMScaleX, SkIntToScalar(1)); |
| mat.set(SkMatrix::kMSkewX, SkIntToScalar(2)); |
| mat.set(SkMatrix::kMTransX, SkIntToScalar(3)); |
| mat.set(SkMatrix::kMSkewY, SkIntToScalar(4)); |
| mat.set(SkMatrix::kMScaleY, SkIntToScalar(5)); |
| mat.set(SkMatrix::kMTransY, SkIntToScalar(6)); |
| SkScalar affine[6]; |
| REPORTER_ASSERT(reporter, mat.asAffine(affine)); |
| |
| #define affineEqual(e) affine[SkMatrix::kA##e] == mat.get(SkMatrix::kM##e) |
| REPORTER_ASSERT(reporter, affineEqual(ScaleX)); |
| REPORTER_ASSERT(reporter, affineEqual(SkewY)); |
| REPORTER_ASSERT(reporter, affineEqual(SkewX)); |
| REPORTER_ASSERT(reporter, affineEqual(ScaleY)); |
| REPORTER_ASSERT(reporter, affineEqual(TransX)); |
| REPORTER_ASSERT(reporter, affineEqual(TransY)); |
| #undef affineEqual |
| |
| mat.set(SkMatrix::kMPersp1, SkIntToScalar(1)); |
| REPORTER_ASSERT(reporter, !mat.asAffine(affine)); |
| } |
| |
| #include "TestClassDef.h" |
| DEFINE_TESTCLASS("Matrix", MatrixTestClass, TestMatrix) |