aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar robertphillips <robertphillips@google.com>2014-06-27 08:59:26 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2014-06-27 08:59:26 -0700
commite5c1e3cd63e22bb06c24dd051f4d814f24786c08 (patch)
tree993b1d4b6479905fb4a745a0b1680e0a658de873
parenta8377402ee626bd0a6c61ef9f0c256f06eca5759 (diff)
Fix RRect tranform bug
When a RRect is an oval transforming the rectangle and the radii separately can result in a non-oval result (i.e., due to numerical issues some tiny straight edges may creep in). This CL remedies the situation by computing the new radii directly from the transformed rect. BUG=skia:2696 R=caryclark@google.com Author: robertphillips@google.com Review URL: https://codereview.chromium.org/354913004
-rw-r--r--src/core/SkRRect.cpp17
-rw-r--r--tests/RoundRectTest.cpp30
2 files changed, 43 insertions, 4 deletions
diff --git a/src/core/SkRRect.cpp b/src/core/SkRRect.cpp
index 9bb6725dea..10d3d7676b 100644
--- a/src/core/SkRRect.cpp
+++ b/src/core/SkRRect.cpp
@@ -342,6 +342,19 @@ bool SkRRect::transform(const SkMatrix& matrix, SkRRect* dst) const {
// At this point, this is guaranteed to succeed, so we can modify dst.
dst->fRect = newRect;
+ // Since the only transforms that were allowed are scale and translate, the type
+ // remains unchanged.
+ dst->fType = fType;
+
+ if (kOval_Type == fType) {
+ for (int i = 0; i < 4; ++i) {
+ dst->fRadii[i].fX = SkScalarHalf(newRect.width());
+ dst->fRadii[i].fY = SkScalarHalf(newRect.height());
+ }
+ SkDEBUGCODE(dst->validate();)
+ return true;
+ }
+
// Now scale each corner
SkScalar xScale = matrix.getScaleX();
const bool flipX = xScale < 0;
@@ -377,10 +390,6 @@ bool SkRRect::transform(const SkMatrix& matrix, SkRRect* dst) const {
SkTSwap(dst->fRadii[kUpperRight_Corner], dst->fRadii[kLowerRight_Corner]);
}
- // Since the only transforms that were allowed are scale and translate, the type
- // remains unchanged.
- dst->fType = fType;
-
SkDEBUGCODE(dst->validate();)
return true;
diff --git a/tests/RoundRectTest.cpp b/tests/RoundRectTest.cpp
index 0a528a6535..261ec67ca0 100644
--- a/tests/RoundRectTest.cpp
+++ b/tests/RoundRectTest.cpp
@@ -582,6 +582,35 @@ static void test_round_rect_transform(skiatest::Reporter* reporter) {
}
}
+// Test out the case where an oval already off in space is translated/scaled
+// further off into space - yielding numerical issues when the rect & radii
+// are transformed separatly
+// BUG=skia:2696
+static void test_issue_2696(skiatest::Reporter* reporter) {
+ SkRRect rrect;
+ SkRect r = { 28443.8594f, 53.1428604f, 28446.7148f, 56.0000038f };
+ rrect.setOval(r);
+
+ SkMatrix xform;
+ xform.setAll(2.44f, 0.0f, 485411.7f,
+ 0.0f, 2.44f, -438.7f,
+ 0.0f, 0.0f, 1.0f);
+ SkRRect dst;
+
+ bool success = rrect.transform(xform, &dst);
+ REPORTER_ASSERT(reporter, success);
+
+ SkScalar halfWidth = SkScalarHalf(dst.width());
+ SkScalar halfHeight = SkScalarHalf(dst.height());
+
+ for (int i = 0; i < 4; ++i) {
+ REPORTER_ASSERT(reporter,
+ SkScalarNearlyEqual(dst.radii((SkRRect::Corner)i).fX, halfWidth));
+ REPORTER_ASSERT(reporter,
+ SkScalarNearlyEqual(dst.radii((SkRRect::Corner)i).fY, halfHeight));
+ }
+}
+
DEF_TEST(RoundRect, reporter) {
test_round_rect_basic(reporter);
test_round_rect_rects(reporter);
@@ -591,4 +620,5 @@ DEF_TEST(RoundRect, reporter) {
test_inset(reporter);
test_round_rect_contains_rect(reporter);
test_round_rect_transform(reporter);
+ test_issue_2696(reporter);
}