Index: tests/MatrixTest.cpp |
diff --git a/tests/MatrixTest.cpp b/tests/MatrixTest.cpp |
index 2f16d656619bf0c881ad9a85f71285cb30196996..16801d1a76c5caf4d2670a4e738fd7c16187c476 100644 |
--- a/tests/MatrixTest.cpp |
+++ b/tests/MatrixTest.cpp |
@@ -592,6 +592,141 @@ static void test_matrix_decomposition(skiatest::Reporter* reporter) { |
REPORTER_ASSERT(reporter, !SkDecomposeUpper2x2(mat, &rotation0, &scaleX, &scaleY, &rotation1)); |
} |
+// For test_matrix_homogeneous, below. |
+static bool scalar_array_nearly_equal_relative(const SkScalar a[], const SkScalar b[], int count) { |
+ for (int i = 0; i < count; ++i) { |
+ if (!scalar_nearly_equal_relative(a[i], b[i])) { |
+ return false; |
+ } |
+ } |
+ return true; |
+} |
+ |
+// For test_matrix_homogeneous, below. |
+// Maps a single triple in src using m and compares results to those in dst |
+static bool naive_homogeneous_mapping(const SkMatrix& m, const SkScalar src[3], |
+ const SkScalar dst[3]) { |
+ SkScalar res[3]; |
+ res[0] = src[0] * m[0] + src[1] * m[1] + src[2] * m[2]; |
+ res[1] = src[0] * m[3] + src[1] * m[4] + src[2] * m[5]; |
+ res[2] = src[0] * m[6] + src[1] * m[7] + src[2] * m[8]; |
+ return scalar_array_nearly_equal_relative(res, dst, 3); |
+} |
+ |
+static void test_matrix_homogeneous(skiatest::Reporter* reporter) { |
+ SkMatrix mat; |
+ |
+ const float kRotation0 = 15.5f; |
+ const float kRotation1 = -50.f; |
+ const float kScale0 = 5000.f; |
+ |
+ const int kTripleCount = 1000; |
+ const int kMatrixCount = 1000; |
+ SkRandom rand; |
+ |
+ SkScalar randTriples[3*kTripleCount]; |
+ for (int i = 0; i < 3*kTripleCount; ++i) { |
+ randTriples[i] = rand.nextRangeF(-3000.f, 3000.f); |
+ } |
+ |
+ SkMatrix mats[kMatrixCount]; |
+ for (int i = 0; i < kMatrixCount; ++i) { |
+ for (int j = 0; j < 9; ++j) { |
+ mats[i].set(j, rand.nextRangeF(-3000.f, 3000.f)); |
+ } |
+ } |
+ |
+ // identity |
+ { |
+ mat.reset(); |
+ SkScalar dst[3*kTripleCount]; |
+ mat.mapHomogeneousPoints(dst, randTriples, kTripleCount); |
+ REPORTER_ASSERT(reporter, scalar_array_nearly_equal_relative(randTriples, dst, kTripleCount*3)); |
+ } |
+ |
+ // zero matrix |
+ { |
+ mat.setAll(0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f); |
+ SkScalar dst[3*kTripleCount]; |
+ mat.mapHomogeneousPoints(dst, randTriples, kTripleCount); |
+ SkScalar zeros[3] = {0.f, 0.f, 0.f}; |
+ for (int i = 0; i < kTripleCount; ++i) { |
+ REPORTER_ASSERT(reporter, scalar_array_nearly_equal_relative(&dst[i*3], zeros, 3)); |
+ } |
+ } |
+ |
+ // zero point |
+ { |
+ SkScalar zeros[3] = {0.f, 0.f, 0.f}; |
+ for (int i = 0; i < kMatrixCount; ++i) { |
+ SkScalar dst[3]; |
+ mats[i].mapHomogeneousPoints(dst, zeros, 1); |
+ REPORTER_ASSERT(reporter, scalar_array_nearly_equal_relative(dst, zeros, 3)); |
+ } |
+ } |
+ |
+ // doesn't crash with null dst, src, count == 0 |
+ { |
+ mats[0].mapHomogeneousPoints(NULL, NULL, 0); |
+ } |
+ |
+ // uniform scale of point |
+ { |
+ mat.setScale(kScale0, kScale0); |
+ SkScalar dst[3]; |
+ SkScalar src[3] = {randTriples[0], randTriples[1], 1.f}; |
+ SkPoint pnt; |
+ pnt.set(src[0], src[1]); |
+ mat.mapHomogeneousPoints(dst, src, 1); |
+ mat.mapPoints(&pnt, &pnt, 1); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(dst[0], pnt.fX)); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(dst[1], pnt.fY)); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(dst[2], SK_Scalar1)); |
+ } |
+ |
+ // rotation of point |
+ { |
+ mat.setRotate(kRotation0); |
+ SkScalar dst[3]; |
+ SkScalar src[3] = {randTriples[0], randTriples[1], 1.f}; |
+ SkPoint pnt; |
+ pnt.set(src[0], src[1]); |
+ mat.mapHomogeneousPoints(dst, src, 1); |
+ mat.mapPoints(&pnt, &pnt, 1); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(dst[0], pnt.fX)); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(dst[1], pnt.fY)); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(dst[2], SK_Scalar1)); |
+ } |
+ |
+ // rotation, scale, rotation of point |
+ { |
+ mat.setRotate(kRotation1); |
+ mat.postScale(kScale0, kScale0); |
+ mat.postRotate(kRotation0); |
+ SkScalar dst[3]; |
+ SkScalar src[3] = {randTriples[0], randTriples[1], 1.f}; |
+ SkPoint pnt; |
+ pnt.set(src[0], src[1]); |
+ mat.mapHomogeneousPoints(dst, src, 1); |
+ mat.mapPoints(&pnt, &pnt, 1); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(dst[0], pnt.fX)); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(dst[1], pnt.fY)); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(dst[2], SK_Scalar1)); |
+ } |
+ |
+ // compare with naive approach |
+ { |
+ for (int i = 0; i < kMatrixCount; ++i) { |
+ for (int j = 0; j < kTripleCount; ++j) { |
+ SkScalar dst[3]; |
+ mats[i].mapHomogeneousPoints(dst, &randTriples[j*3], 1); |
+ REPORTER_ASSERT(reporter, naive_homogeneous_mapping(mats[i], &randTriples[j*3], dst)); |
+ } |
+ } |
+ } |
+ |
+} |
+ |
static void TestMatrix(skiatest::Reporter* reporter) { |
SkMatrix mat, inverse, iden1, iden2; |
@@ -713,6 +848,7 @@ static void TestMatrix(skiatest::Reporter* reporter) { |
test_matrix_is_similarity(reporter); |
test_matrix_recttorect(reporter); |
test_matrix_decomposition(reporter); |
+ test_matrix_homogeneous(reporter); |
} |
#include "TestClassDef.h" |