[gpu] Remove getMaxStretch for perspective, use mapRadius for perspective path subdiv tol, add test
Review URL: http://codereview.appspot.com/4975063/
git-svn-id: http://skia.googlecode.com/svn/trunk@2246 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/tests/MatrixTest.cpp b/tests/MatrixTest.cpp
index df24a5a..4638fe1 100644
--- a/tests/MatrixTest.cpp
+++ b/tests/MatrixTest.cpp
@@ -7,6 +7,7 @@
*/
#include "Test.h"
#include "SkMatrix.h"
+#include "SkRandom.h"
static bool nearly_equal_scalar(SkScalar a, SkScalar b) {
// Note that we get more compounded error for multiple operations when
@@ -55,6 +56,94 @@
REPORTER_ASSERT(reporter, memcmp(buffer, buffer2, size1) == 0);
}
+void test_matrix_max_stretch(skiatest::Reporter* reporter) {
+ SkMatrix identity;
+ identity.reset();
+ REPORTER_ASSERT(reporter, SK_Scalar1 == identity.getMaxStretch());
+
+ SkMatrix scale;
+ scale.setScale(SK_Scalar1 * 2, SK_Scalar1 * 4);
+ REPORTER_ASSERT(reporter, SK_Scalar1 * 4 == scale.getMaxStretch());
+
+ SkMatrix rot90Scale;
+ rot90Scale.setRotate(90 * SK_Scalar1);
+ rot90Scale.postScale(SK_Scalar1 / 4, SK_Scalar1 / 2);
+ REPORTER_ASSERT(reporter, SK_Scalar1 / 2 == rot90Scale.getMaxStretch());
+
+ SkMatrix rotate;
+ rotate.setRotate(128 * SK_Scalar1);
+ REPORTER_ASSERT(reporter, SkScalarAbs(SK_Scalar1 - rotate.getMaxStretch()) <= SK_ScalarNearlyZero);
+
+ SkMatrix translate;
+ translate.setTranslate(10 * SK_Scalar1, -5 * SK_Scalar1);
+ REPORTER_ASSERT(reporter, SK_Scalar1 == translate.getMaxStretch());
+
+ SkMatrix perspX;
+ perspX.reset();
+ perspX.setPerspX(SK_Scalar1 / 1000);
+ REPORTER_ASSERT(reporter, -SK_Scalar1 == perspX.getMaxStretch());
+
+ SkMatrix perspY;
+ perspY.reset();
+ perspY.setPerspX(-SK_Scalar1 / 500);
+ REPORTER_ASSERT(reporter, -SK_Scalar1 == perspY.getMaxStretch());
+
+ SkMatrix baseMats[] = {scale, rot90Scale, rotate,
+ translate, perspX, perspY};
+ SkMatrix mats[2*SK_ARRAY_COUNT(baseMats)];
+ for (int i = 0; i < SK_ARRAY_COUNT(baseMats); ++i) {
+ mats[i] = baseMats[i];
+ bool invertable = mats[i].invert(&mats[i + SK_ARRAY_COUNT(baseMats)]);
+ REPORTER_ASSERT(reporter, invertable);
+ }
+ SkRandom rand;
+ for (int m = 0; m < 1000; ++m) {
+ SkMatrix mat;
+ mat.reset();
+ for (int i = 0; i < 4; ++i) {
+ int x = rand.nextU() % SK_ARRAY_COUNT(mats);
+ mat.postConcat(mats[x]);
+ }
+ SkScalar stretch = mat.getMaxStretch();
+
+ if ((stretch < 0) != mat.hasPerspective()) {
+ stretch = mat.getMaxStretch();
+ }
+
+ REPORTER_ASSERT(reporter, (stretch < 0) == mat.hasPerspective());
+
+ if (mat.hasPerspective()) {
+ m -= 1; // try another non-persp matrix
+ continue;
+ }
+
+ // test a bunch of vectors. None should be scaled by more than stretch
+ // (modulo some error) and we should find a vector that is scaled by
+ // almost stretch.
+ static const SkScalar gStretchTol = (105 * SK_Scalar1) / 100;
+ static const SkScalar gMaxStretchTol = (97 * SK_Scalar1) / 100;
+ SkScalar max = 0;
+ SkVector vectors[1000];
+ for (int i = 0; i < SK_ARRAY_COUNT(vectors); ++i) {
+ vectors[i].fX = rand.nextSScalar1();
+ vectors[i].fY = rand.nextSScalar1();
+ if (!vectors[i].normalize()) {
+ i -= 1;
+ continue;
+ }
+ }
+ mat.mapVectors(vectors, SK_ARRAY_COUNT(vectors));
+ for (int i = 0; i < SK_ARRAY_COUNT(vectors); ++i) {
+ SkScalar d = vectors[i].length();
+ REPORTER_ASSERT(reporter, SkScalarDiv(d, stretch) < gStretchTol);
+ if (max < d) {
+ max = d;
+ }
+ }
+ REPORTER_ASSERT(reporter, SkScalarDiv(max, stretch) >= gMaxStretchTol);
+ }
+}
+
void TestMatrix(skiatest::Reporter* reporter) {
SkMatrix mat, inverse, iden1, iden2;
@@ -146,6 +235,8 @@
mat.set(SkMatrix::kMPersp1, SkIntToScalar(1));
REPORTER_ASSERT(reporter, !mat.asAffine(affine));
+
+ test_matrix_max_stretch(reporter);
}
#include "TestClassDef.h"