#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); } } } #include "TestClassDef.h" DEFINE_TESTCLASS("Matrix", MatrixTestClass, TestMatrix)