diff options
author | robertphillips <robertphillips@google.com> | 2015-03-13 09:53:01 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-03-13 09:53:01 -0700 |
commit | 2a679ae8f5b80a337f67783dbc0a447a9f4312c7 (patch) | |
tree | 2ba8d9530da2b474fc01dee3d5c5c627db08d959 /src | |
parent | c1b11f1db69bea8d64ebf656ae92ea9ec6dbb40f (diff) |
Fix bug with very large round rects with large radii
BUG=463920
Review URL: https://codereview.chromium.org/998903003
Diffstat (limited to 'src')
-rw-r--r-- | src/core/SkRRect.cpp | 34 |
1 files changed, 16 insertions, 18 deletions
diff --git a/src/core/SkRRect.cpp b/src/core/SkRRect.cpp index d8b4a20d88..e54256009a 100644 --- a/src/core/SkRRect.cpp +++ b/src/core/SkRRect.cpp @@ -128,6 +128,16 @@ static SkScalar clamp_radius_check_predicates(SkScalar rad, SkScalar min, SkScal return rad; } +// These parameters intentionally double. Apropos crbug.com/463920, if one of the +// radii is huge while the other is small, single precision math can completely +// miss the fact that a scale is required. +static double compute_min_scale(double rad1, double rad2, double limit, double curMin) { + if ((rad1 + rad2) > limit) { + return SkTMin(curMin, limit / (rad1 + rad2)); + } + return curMin; +} + void SkRRect::setRectRadii(const SkRect& rect, const SkVector radii[4]) { if (rect.isEmpty() || !rect.isFinite()) { this->setEmpty(); @@ -173,26 +183,14 @@ void SkRRect::setRectRadii(const SkRect& rect, const SkVector radii[4]) { // and Ltop = Lbottom = the width of the box, // and Lleft = Lright = the height of the box. // If f < 1, then all corner radii are reduced by multiplying them by f." - SkScalar scale = SK_Scalar1; + double scale = 1.0; - if (fRadii[0].fX + fRadii[1].fX > rect.width()) { - scale = SkMinScalar(scale, - SkScalarDiv(rect.width(), fRadii[0].fX + fRadii[1].fX)); - } - if (fRadii[1].fY + fRadii[2].fY > rect.height()) { - scale = SkMinScalar(scale, - SkScalarDiv(rect.height(), fRadii[1].fY + fRadii[2].fY)); - } - if (fRadii[2].fX + fRadii[3].fX > rect.width()) { - scale = SkMinScalar(scale, - SkScalarDiv(rect.width(), fRadii[2].fX + fRadii[3].fX)); - } - if (fRadii[3].fY + fRadii[0].fY > rect.height()) { - scale = SkMinScalar(scale, - SkScalarDiv(rect.height(), fRadii[3].fY + fRadii[0].fY)); - } + scale = compute_min_scale(fRadii[0].fX, fRadii[1].fX, rect.width(), scale); + scale = compute_min_scale(fRadii[1].fY, fRadii[2].fY, rect.height(), scale); + scale = compute_min_scale(fRadii[2].fX, fRadii[3].fX, rect.width(), scale); + scale = compute_min_scale(fRadii[3].fY, fRadii[0].fY, rect.height(), scale); - if (scale < SK_Scalar1) { + if (scale < 1.0) { for (int i = 0; i < 4; ++i) { fRadii[i].fX *= scale; fRadii[i].fY *= scale; |