Index: tests/MatrixTest.cpp |
diff --git a/tests/MatrixTest.cpp b/tests/MatrixTest.cpp |
index 5dface74d82d0e79f7389212ac650dba54035bbc..4977971627e377c15811d0a1c47bc7b660c94946 100644 |
--- a/tests/MatrixTest.cpp |
+++ b/tests/MatrixTest.cpp |
@@ -345,6 +345,190 @@ static void test_matrix_is_similarity(skiatest::Reporter* reporter) { |
REPORTER_ASSERT(reporter, mat.isSimilarity()); |
} |
+static void test_matrix_decomposition(skiatest::Reporter* reporter) { |
+ SkMatrix mat;//, rotate0, rotate1, uniformScale, anisoScale; |
+ SkScalar rotation0, scaleX, scaleY, rotation1; |
+ |
+ const float kRotation0 = 15.5f; |
+ const float kRotation1 = -50.f; |
+ const float kScale0 = 2000.f; |
+ const float kScale1 = 0.001f; |
+ |
+ // identity |
+ mat.reset(); |
+ REPORTER_ASSERT(reporter, mat.decomposeUpper2x2(&rotation0, &scaleX, &scaleY, &rotation1)); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyZero(rotation0)); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(scaleX, SK_Scalar1)); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(scaleY, SK_Scalar1)); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyZero(rotation1)); |
+ // make sure it doesn't crash if we pass in NULLs |
+ REPORTER_ASSERT(reporter, mat.decomposeUpper2x2(NULL, NULL, NULL, NULL)); |
+ |
+ // rotation only |
+ mat.setRotate(kRotation0); |
+ REPORTER_ASSERT(reporter, mat.decomposeUpper2x2(&rotation0, &scaleX, &scaleY, &rotation1)); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(rotation0, SkDegreesToRadians(kRotation0))); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(scaleX, SK_Scalar1)); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(scaleY, SK_Scalar1)); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyZero(rotation1)); |
+ |
+ // uniform scale only |
+ mat.setScale(kScale0, kScale0); |
+ REPORTER_ASSERT(reporter, mat.decomposeUpper2x2(&rotation0, &scaleX, &scaleY, &rotation1)); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyZero(rotation0)); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(scaleX, kScale0)); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(scaleY, kScale0)); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyZero(rotation1)); |
+ |
+ // anisotropic scale only |
+ mat.setScale(kScale0, kScale1); |
+ REPORTER_ASSERT(reporter, mat.decomposeUpper2x2(&rotation0, &scaleX, &scaleY, &rotation1)); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyZero(rotation0)); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(scaleX, kScale0)); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(scaleY, kScale1)); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyZero(rotation1)); |
+ |
+ // rotation then uniform scale |
+ mat.setRotate(kRotation1); |
+ mat.postScale(kScale0, kScale0); |
+ REPORTER_ASSERT(reporter, mat.decomposeUpper2x2(&rotation0, &scaleX, &scaleY, &rotation1)); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(rotation0, SkDegreesToRadians(kRotation1))); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(scaleX, kScale0)); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(scaleY, kScale0)); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyZero(rotation1)); |
+ |
+ // uniform scale then rotation |
+ mat.setScale(kScale0, kScale0); |
+ mat.postRotate(kRotation1); |
+ REPORTER_ASSERT(reporter, mat.decomposeUpper2x2(&rotation0, &scaleX, &scaleY, &rotation1)); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(rotation0, SkDegreesToRadians(kRotation1))); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(scaleX, kScale0)); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(scaleY, kScale0)); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyZero(rotation1)); |
+ |
+ // rotation then uniform scale+reflection |
+ mat.setRotate(kRotation0); |
+ mat.postScale(kScale1, -kScale1); |
+ REPORTER_ASSERT(reporter, mat.decomposeUpper2x2(&rotation0, &scaleX, &scaleY, &rotation1)); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(rotation0, SkDegreesToRadians(kRotation0))); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(scaleX, kScale1)); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(scaleY, -kScale1)); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyZero(rotation1)); |
+ |
+ // uniform scale+reflection, then rotate |
+ mat.setScale(kScale0, -kScale0); |
+ mat.postRotate(kRotation1); |
+ REPORTER_ASSERT(reporter, mat.decomposeUpper2x2(&rotation0, &scaleX, &scaleY, &rotation1)); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(rotation0, SkDegreesToRadians(-kRotation1))); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(scaleX, kScale0)); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(scaleY, -kScale0)); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyZero(rotation1)); |
+ |
+ // rotation then anisotropic scale |
+ mat.setRotate(kRotation1); |
+ mat.postScale(kScale1, kScale0); |
+ REPORTER_ASSERT(reporter, mat.decomposeUpper2x2(&rotation0, &scaleX, &scaleY, &rotation1)); |
+ // because of the shear/skew we won't get the same results, so we need to multiply it out |
+ SkMatrix mat2; |
+ mat2.setRotate(rotation0*(180.f/SK_ScalarPI)); |
+ mat2.postScale(scaleX, scaleY); |
+ mat2.postRotate(rotation1*(180.f/SK_ScalarPI)); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(mat[SkMatrix::kMScaleX], |
+ mat2[SkMatrix::kMScaleX])); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(mat[SkMatrix::kMSkewX], |
+ mat2[SkMatrix::kMSkewX])); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(mat[SkMatrix::kMSkewY], |
+ mat2[SkMatrix::kMSkewY])); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(mat[SkMatrix::kMScaleY], |
+ mat2[SkMatrix::kMScaleY])); |
+ |
+ // anisotropic scale then rotation |
+ mat.setScale(kScale0, kScale1); |
+ mat.postRotate(kRotation0); |
+ REPORTER_ASSERT(reporter, mat.decomposeUpper2x2(&rotation0, &scaleX, &scaleY, &rotation1)); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyZero(rotation0)); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(scaleX, kScale0)); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(scaleY, kScale1)); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(rotation1, SkDegreesToRadians(kRotation0))); |
+ |
+ // rotation, uniform scale, then different rotation |
+ mat.setRotate(kRotation1); |
+ mat.postScale(kScale0, kScale0); |
+ mat.postRotate(kRotation0); |
+ REPORTER_ASSERT(reporter, mat.decomposeUpper2x2(&rotation0, &scaleX, &scaleY, &rotation1)); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(rotation0, |
+ SkDegreesToRadians(kRotation0 + kRotation1))); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(scaleX, kScale0)); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(scaleY, kScale0)); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyZero(rotation1)); |
+ |
+ // rotation, anisotropic scale, then different rotation |
+ mat.setRotate(kRotation0); |
+ mat.postScale(kScale1, kScale0); |
+ mat.postRotate(kRotation1); |
+ REPORTER_ASSERT(reporter, mat.decomposeUpper2x2(&rotation0, &scaleX, &scaleY, &rotation1)); |
+ // because of the shear/skew we won't get the same results, so we need to multiply it out |
+ mat2.setRotate(rotation0*(180.f/SK_ScalarPI)); |
+ mat2.postScale(scaleX, scaleY); |
+ mat2.postRotate(rotation1*(180.f/SK_ScalarPI)); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(mat[SkMatrix::kMScaleX], |
+ mat2[SkMatrix::kMScaleX])); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(mat[SkMatrix::kMSkewX], |
+ mat2[SkMatrix::kMSkewX])); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(mat[SkMatrix::kMSkewY], |
+ mat2[SkMatrix::kMSkewY])); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(mat[SkMatrix::kMScaleY], |
+ mat2[SkMatrix::kMScaleY])); |
+ |
+ // translation shouldn't affect this |
+ mat.postTranslate(-1000.f, 1000.f); |
+ REPORTER_ASSERT(reporter, mat.decomposeUpper2x2(&rotation0, &scaleX, &scaleY, &rotation1)); |
+ // because of the shear/skew we won't get the same results, so we need to multiply it out |
+ mat2.setRotate(rotation0*(180.f/SK_ScalarPI)); |
+ mat2.postScale(scaleX, scaleY); |
+ mat2.postRotate(rotation1*(180.f/SK_ScalarPI)); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(mat[SkMatrix::kMScaleX], |
+ mat2[SkMatrix::kMScaleX])); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(mat[SkMatrix::kMSkewX], |
+ mat2[SkMatrix::kMSkewX])); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(mat[SkMatrix::kMSkewY], |
+ mat2[SkMatrix::kMSkewY])); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(mat[SkMatrix::kMScaleY], |
+ mat2[SkMatrix::kMScaleY])); |
+ |
+ // perspective shouldn't affect this |
+ mat[SkMatrix::kMPersp0] = 12.0; |
+ mat[SkMatrix::kMPersp1] = 4.0; |
+ mat[SkMatrix::kMPersp2] = 1872.0; |
+ REPORTER_ASSERT(reporter, mat.decomposeUpper2x2(&rotation0, &scaleX, &scaleY, &rotation1)); |
+ // because of the shear/skew we won't get the same results, so we need to multiply it out |
+ mat2.setRotate(rotation0*(180.f/SK_ScalarPI)); |
+ mat2.postScale(scaleX, scaleY); |
+ mat2.postRotate(rotation1*(180.f/SK_ScalarPI)); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(mat[SkMatrix::kMScaleX], |
+ mat2[SkMatrix::kMScaleX])); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(mat[SkMatrix::kMSkewX], |
+ mat2[SkMatrix::kMSkewX])); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(mat[SkMatrix::kMSkewY], |
+ mat2[SkMatrix::kMSkewY])); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(mat[SkMatrix::kMScaleY], |
+ mat2[SkMatrix::kMScaleY])); |
+ |
+ // degenerate matrices |
+ mat.reset(); |
+ mat[SkMatrix::kMScaleX] = 0.f; |
+ REPORTER_ASSERT(reporter, !mat.decomposeUpper2x2(&rotation0, &scaleX, &scaleY, &rotation1)); |
+ mat.reset(); |
+ mat[SkMatrix::kMScaleY] = 0.f; |
+ REPORTER_ASSERT(reporter, !mat.decomposeUpper2x2(&rotation0, &scaleX, &scaleY, &rotation1)); |
+ mat.reset(); |
+ mat[SkMatrix::kMScaleX] = 1.f; |
+ mat[SkMatrix::kMSkewX] = 2.f; |
+ mat[SkMatrix::kMSkewY] = 4.f; |
+ mat[SkMatrix::kMScaleY] = 8.f; // who do we appreciate? |
+ REPORTER_ASSERT(reporter, !mat.decomposeUpper2x2(&rotation0, &scaleX, &scaleY, &rotation1)); |
+} |
+ |
static void TestMatrix(skiatest::Reporter* reporter) { |
SkMatrix mat, inverse, iden1, iden2; |
@@ -465,6 +649,7 @@ static void TestMatrix(skiatest::Reporter* reporter) { |
test_matrix_max_stretch(reporter); |
test_matrix_is_similarity(reporter); |
test_matrix_recttorect(reporter); |
+ test_matrix_decomposition(reporter); |
} |
#include "TestClassDef.h" |