Index: tests/RoundRectTest.cpp |
diff --git a/tests/RoundRectTest.cpp b/tests/RoundRectTest.cpp |
index 93f5e7d20fdca268efd320352b24f10b8024afac..e2965d53685e5daacd268ee9387e72c69c2cd32d 100644 |
--- a/tests/RoundRectTest.cpp |
+++ b/tests/RoundRectTest.cpp |
@@ -6,10 +6,11 @@ |
*/ |
#include "Test.h" |
+#include "SkMatrix.h" |
#include "SkRRect.h" |
-static const SkScalar kWidth = 100.0f; |
-static const SkScalar kHeight = 100.0f; |
+static const SkScalar kWidth = SkFloatToScalar(100.0f); |
+static const SkScalar kHeight = SkFloatToScalar(100.0f); |
static void test_inset(skiatest::Reporter* reporter) { |
SkRRect rr, rr2; |
@@ -451,6 +452,206 @@ static void test_round_rect_contains_rect(skiatest::Reporter* reporter) { |
} |
} |
+// Called for a matrix that should cause SkRRect::transform to fail. |
+static void assert_transform_failure(skiatest::Reporter* reporter, const SkRRect& orig, |
+ const SkMatrix& matrix) { |
+ // The test depends on the fact that the original is not empty. |
+ SkASSERT(!orig.isEmpty()); |
+ SkRRect dst; |
+ dst.setEmpty(); |
+ |
+ const SkRRect copyOfDst = dst; |
+ const SkRRect copyOfOrig = orig; |
+ bool success = orig.transform(matrix, &dst); |
+ // This transform should fail. |
+ REPORTER_ASSERT(reporter, !success); |
+ // Since the transform failed, dst should be unchanged. |
+ REPORTER_ASSERT(reporter, copyOfDst == dst); |
+ // original should not be modified. |
+ REPORTER_ASSERT(reporter, copyOfOrig == orig); |
+ REPORTER_ASSERT(reporter, orig != dst); |
+} |
+ |
+#define GET_RADII \ |
+ const SkVector& origUL = orig.radii(SkRRect::kUpperLeft_Corner); \ |
+ const SkVector& origUR = orig.radii(SkRRect::kUpperRight_Corner); \ |
+ const SkVector& origLR = orig.radii(SkRRect::kLowerRight_Corner); \ |
+ const SkVector& origLL = orig.radii(SkRRect::kLowerLeft_Corner); \ |
+ const SkVector& dstUL = dst.radii(SkRRect::kUpperLeft_Corner); \ |
+ const SkVector& dstUR = dst.radii(SkRRect::kUpperRight_Corner); \ |
+ const SkVector& dstLR = dst.radii(SkRRect::kLowerRight_Corner); \ |
+ const SkVector& dstLL = dst.radii(SkRRect::kLowerLeft_Corner) |
+ |
+// Called to test various transforms on a single SkRRect. |
+static void test_transform_helper(skiatest::Reporter* reporter, const SkRRect& orig) { |
+ SkRRect dst; |
+ dst.setEmpty(); |
+ |
+ // The identity matrix will duplicate the rrect. |
+ bool success = orig.transform(SkMatrix::I(), &dst); |
+ REPORTER_ASSERT(reporter, success); |
+ REPORTER_ASSERT(reporter, orig == dst); |
+ |
+ // Skew and Perspective make transform fail. |
+ SkMatrix matrix; |
+ matrix.reset(); |
+ matrix.setSkewX(SkIntToScalar(2)); |
+ assert_transform_failure(reporter, orig, matrix); |
+ |
+ matrix.reset(); |
+ matrix.setSkewY(SkIntToScalar(3)); |
+ assert_transform_failure(reporter, orig, matrix); |
+ |
+ matrix.reset(); |
+ matrix.setPerspX(SkScalarToPersp(SkIntToScalar(4))); |
+ assert_transform_failure(reporter, orig, matrix); |
+ |
+ matrix.reset(); |
+ matrix.setPerspY(SkScalarToPersp(SkIntToScalar(5))); |
+ assert_transform_failure(reporter, orig, matrix); |
+ |
+ // Rotation fails. |
+ matrix.reset(); |
+ matrix.setRotate(SkIntToScalar(90)); |
+ assert_transform_failure(reporter, orig, matrix); |
+ matrix.setRotate(SkIntToScalar(37)); |
+ assert_transform_failure(reporter, orig, matrix); |
+ |
+ // Translate will keep the rect moved, but otherwise the same. |
+ matrix.reset(); |
+ SkScalar translateX = SkIntToScalar(32); |
+ SkScalar translateY = SkIntToScalar(15); |
+ matrix.setTranslateX(translateX); |
+ matrix.setTranslateY(translateY); |
+ dst.setEmpty(); |
+ success = orig.transform(matrix, &dst); |
+ REPORTER_ASSERT(reporter, success); |
+ for (int i = 0; i < 4; ++i) { |
+ REPORTER_ASSERT(reporter, |
+ orig.radii((SkRRect::Corner) i) == dst.radii((SkRRect::Corner) i)); |
+ } |
+ REPORTER_ASSERT(reporter, orig.rect().width() == dst.rect().width()); |
+ REPORTER_ASSERT(reporter, orig.rect().height() == dst.rect().height()); |
+ REPORTER_ASSERT(reporter, dst.rect().left() == orig.rect().left() + translateX); |
+ REPORTER_ASSERT(reporter, dst.rect().top() == orig.rect().top() + translateY); |
+ |
+ // Keeping the translation, but adding skew will make transform fail. |
+ matrix.setSkewY(SkIntToScalar(7)); |
+ assert_transform_failure(reporter, orig, matrix); |
+ |
+ // Scaling in -x will flip the round rect horizontally. |
+ matrix.reset(); |
+ matrix.setScaleX(SkIntToScalar(-1)); |
+ dst.setEmpty(); |
+ success = orig.transform(matrix, &dst); |
+ REPORTER_ASSERT(reporter, success); |
+ { |
+ GET_RADII; |
+ // Radii have swapped in x. |
+ REPORTER_ASSERT(reporter, origUL == dstUR); |
+ REPORTER_ASSERT(reporter, origUR == dstUL); |
+ REPORTER_ASSERT(reporter, origLR == dstLL); |
+ REPORTER_ASSERT(reporter, origLL == dstLR); |
+ } |
+ // Width and height remain the same. |
+ REPORTER_ASSERT(reporter, orig.rect().width() == dst.rect().width()); |
+ REPORTER_ASSERT(reporter, orig.rect().height() == dst.rect().height()); |
+ // Right and left have swapped (sort of) |
+ REPORTER_ASSERT(reporter, orig.rect().right() == -dst.rect().left()); |
+ // Top has stayed the same. |
+ REPORTER_ASSERT(reporter, orig.rect().top() == dst.rect().top()); |
+ |
+ // Keeping the scale, but adding a persp will make transform fail. |
+ matrix.setPerspX(SkScalarToPersp(SkIntToScalar(7))); |
+ assert_transform_failure(reporter, orig, matrix); |
+ |
+ // Scaling in -y will flip the round rect vertically. |
+ matrix.reset(); |
+ matrix.setScaleY(SkIntToScalar(-1)); |
+ dst.setEmpty(); |
+ success = orig.transform(matrix, &dst); |
+ REPORTER_ASSERT(reporter, success); |
+ { |
+ GET_RADII; |
+ // Radii have swapped in y. |
+ REPORTER_ASSERT(reporter, origUL == dstLL); |
+ REPORTER_ASSERT(reporter, origUR == dstLR); |
+ REPORTER_ASSERT(reporter, origLR == dstUR); |
+ REPORTER_ASSERT(reporter, origLL == dstUL); |
+ } |
+ // Width and height remain the same. |
+ REPORTER_ASSERT(reporter, orig.rect().width() == dst.rect().width()); |
+ REPORTER_ASSERT(reporter, orig.rect().height() == dst.rect().height()); |
+ // Top and bottom have swapped (sort of) |
+ REPORTER_ASSERT(reporter, orig.rect().top() == -dst.rect().bottom()); |
+ // Left has stayed the same. |
+ REPORTER_ASSERT(reporter, orig.rect().left() == dst.rect().left()); |
+ |
+ // Scaling in -x and -y will swap in both directions. |
+ matrix.reset(); |
+ matrix.setScaleY(SkIntToScalar(-1)); |
+ matrix.setScaleX(SkIntToScalar(-1)); |
+ dst.setEmpty(); |
+ success = orig.transform(matrix, &dst); |
+ REPORTER_ASSERT(reporter, success); |
+ { |
+ GET_RADII; |
+ REPORTER_ASSERT(reporter, origUL == dstLR); |
+ REPORTER_ASSERT(reporter, origUR == dstLL); |
+ REPORTER_ASSERT(reporter, origLR == dstUL); |
+ REPORTER_ASSERT(reporter, origLL == dstUR); |
+ } |
+ // Width and height remain the same. |
+ REPORTER_ASSERT(reporter, orig.rect().width() == dst.rect().width()); |
+ REPORTER_ASSERT(reporter, orig.rect().height() == dst.rect().height()); |
+ REPORTER_ASSERT(reporter, orig.rect().top() == -dst.rect().bottom()); |
+ REPORTER_ASSERT(reporter, orig.rect().right() == -dst.rect().left()); |
+ |
+ // Scale in both directions. |
+ SkScalar xScale = SkIntToScalar(3); |
+ SkScalar yScale = SkFloatToScalar(3.2f); |
+ matrix.reset(); |
+ matrix.setScaleX(xScale); |
+ matrix.setScaleY(yScale); |
+ dst.setEmpty(); |
+ success = orig.transform(matrix, &dst); |
+ REPORTER_ASSERT(reporter, success); |
+ // Radii are scaled. |
+ for (int i = 0; i < 4; ++i) { |
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(dst.radii((SkRRect::Corner) i).fX, |
+ SkScalarMul(orig.radii((SkRRect::Corner) i).fX, xScale))); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(dst.radii((SkRRect::Corner) i).fY, |
+ SkScalarMul(orig.radii((SkRRect::Corner) i).fY, yScale))); |
+ } |
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(dst.rect().width(), |
+ SkScalarMul(orig.rect().width(), xScale))); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(dst.rect().height(), |
+ SkScalarMul(orig.rect().height(), yScale))); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(dst.rect().left(), |
+ SkScalarMul(orig.rect().left(), xScale))); |
+ REPORTER_ASSERT(reporter, SkScalarNearlyEqual(dst.rect().top(), |
+ SkScalarMul(orig.rect().top(), yScale))); |
+} |
+ |
+static void test_round_rect_transform(skiatest::Reporter* reporter) { |
+ SkRRect rrect; |
+ { |
+ SkRect r = { 0, 0, kWidth, kHeight }; |
+ rrect.setRectXY(r, SkIntToScalar(4), SkIntToScalar(7)); |
+ test_transform_helper(reporter, rrect); |
+ } |
+ { |
+ SkRect r = { SkIntToScalar(5), SkIntToScalar(15), |
+ SkIntToScalar(27), SkIntToScalar(34) }; |
+ SkVector radii[4] = { { 0, SkIntToScalar(1) }, |
+ { SkIntToScalar(2), SkIntToScalar(3) }, |
+ { SkIntToScalar(4), SkIntToScalar(5) }, |
+ { SkIntToScalar(6), SkIntToScalar(7) } }; |
+ rrect.setRectRadii(r, radii); |
+ test_transform_helper(reporter, rrect); |
+ } |
+} |
+ |
static void TestRoundRect(skiatest::Reporter* reporter) { |
test_round_rect_basic(reporter); |
test_round_rect_rects(reporter); |
@@ -459,6 +660,7 @@ static void TestRoundRect(skiatest::Reporter* reporter) { |
test_round_rect_iffy_parameters(reporter); |
test_inset(reporter); |
test_round_rect_contains_rect(reporter); |
+ test_round_rect_transform(reporter); |
} |
#include "TestClassDef.h" |