| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2012 Google Inc. | 2 * Copyright 2012 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "SkRRect.h" | 8 #include "SkRRect.h" |
| 9 #include "SkMatrix.h" | 9 #include "SkMatrix.h" |
| 10 | 10 |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 121 * We need all combinations of predicates to be true to have a "safe" radius va
lue. | 121 * We need all combinations of predicates to be true to have a "safe" radius va
lue. |
| 122 */ | 122 */ |
| 123 static SkScalar clamp_radius_check_predicates(SkScalar rad, SkScalar min, SkScal
ar max) { | 123 static SkScalar clamp_radius_check_predicates(SkScalar rad, SkScalar min, SkScal
ar max) { |
| 124 SkASSERT(min < max); | 124 SkASSERT(min < max); |
| 125 if (rad > max - min || min + rad > max || max - rad < min) { | 125 if (rad > max - min || min + rad > max || max - rad < min) { |
| 126 rad = SkScalarDecULP(rad); | 126 rad = SkScalarDecULP(rad); |
| 127 } | 127 } |
| 128 return rad; | 128 return rad; |
| 129 } | 129 } |
| 130 | 130 |
| 131 // These parameters intentionally double. Apropos crbug.com/463920, if one of th
e |
| 132 // radii is huge while the other is small, single precision math can completely |
| 133 // miss the fact that a scale is required. |
| 134 static double compute_min_scale(double rad1, double rad2, double limit, double c
urMin) { |
| 135 if ((rad1 + rad2) > limit) { |
| 136 return SkTMin(curMin, limit / (rad1 + rad2)); |
| 137 } |
| 138 return curMin; |
| 139 } |
| 140 |
| 131 void SkRRect::setRectRadii(const SkRect& rect, const SkVector radii[4]) { | 141 void SkRRect::setRectRadii(const SkRect& rect, const SkVector radii[4]) { |
| 132 if (rect.isEmpty() || !rect.isFinite()) { | 142 if (rect.isEmpty() || !rect.isFinite()) { |
| 133 this->setEmpty(); | 143 this->setEmpty(); |
| 134 return; | 144 return; |
| 135 } | 145 } |
| 136 | 146 |
| 137 if (!SkScalarsAreFinite(&radii[0].fX, 8)) { | 147 if (!SkScalarsAreFinite(&radii[0].fX, 8)) { |
| 138 this->setRect(rect); // devolve into a simple rect | 148 this->setRect(rect); // devolve into a simple rect |
| 139 return; | 149 return; |
| 140 } | 150 } |
| (...skipping 25 matching lines...) Expand all Loading... |
| 166 // Proportionally scale down all radii to fit. Find the minimum ratio | 176 // Proportionally scale down all radii to fit. Find the minimum ratio |
| 167 // of a side and the radii on that side (for all four sides) and use | 177 // of a side and the radii on that side (for all four sides) and use |
| 168 // that to scale down _all_ the radii. This algorithm is from the | 178 // that to scale down _all_ the radii. This algorithm is from the |
| 169 // W3 spec (http://www.w3.org/TR/css3-background/) section 5.5 - Overlapping | 179 // W3 spec (http://www.w3.org/TR/css3-background/) section 5.5 - Overlapping |
| 170 // Curves: | 180 // Curves: |
| 171 // "Let f = min(Li/Si), where i is one of { top, right, bottom, left }, | 181 // "Let f = min(Li/Si), where i is one of { top, right, bottom, left }, |
| 172 // Si is the sum of the two corresponding radii of the corners on side i, | 182 // Si is the sum of the two corresponding radii of the corners on side i, |
| 173 // and Ltop = Lbottom = the width of the box, | 183 // and Ltop = Lbottom = the width of the box, |
| 174 // and Lleft = Lright = the height of the box. | 184 // and Lleft = Lright = the height of the box. |
| 175 // If f < 1, then all corner radii are reduced by multiplying them by f." | 185 // If f < 1, then all corner radii are reduced by multiplying them by f." |
| 176 SkScalar scale = SK_Scalar1; | 186 double scale = 1.0; |
| 177 | 187 |
| 178 if (fRadii[0].fX + fRadii[1].fX > rect.width()) { | 188 scale = compute_min_scale(fRadii[0].fX, fRadii[1].fX, rect.width(), scale); |
| 179 scale = SkMinScalar(scale, | 189 scale = compute_min_scale(fRadii[1].fY, fRadii[2].fY, rect.height(), scale); |
| 180 SkScalarDiv(rect.width(), fRadii[0].fX + fRadii[1].f
X)); | 190 scale = compute_min_scale(fRadii[2].fX, fRadii[3].fX, rect.width(), scale); |
| 181 } | 191 scale = compute_min_scale(fRadii[3].fY, fRadii[0].fY, rect.height(), scale); |
| 182 if (fRadii[1].fY + fRadii[2].fY > rect.height()) { | |
| 183 scale = SkMinScalar(scale, | |
| 184 SkScalarDiv(rect.height(), fRadii[1].fY + fRadii[2].
fY)); | |
| 185 } | |
| 186 if (fRadii[2].fX + fRadii[3].fX > rect.width()) { | |
| 187 scale = SkMinScalar(scale, | |
| 188 SkScalarDiv(rect.width(), fRadii[2].fX + fRadii[3].f
X)); | |
| 189 } | |
| 190 if (fRadii[3].fY + fRadii[0].fY > rect.height()) { | |
| 191 scale = SkMinScalar(scale, | |
| 192 SkScalarDiv(rect.height(), fRadii[3].fY + fRadii[0].
fY)); | |
| 193 } | |
| 194 | 192 |
| 195 if (scale < SK_Scalar1) { | 193 if (scale < 1.0) { |
| 196 for (int i = 0; i < 4; ++i) { | 194 for (int i = 0; i < 4; ++i) { |
| 197 fRadii[i].fX *= scale; | 195 fRadii[i].fX *= scale; |
| 198 fRadii[i].fY *= scale; | 196 fRadii[i].fY *= scale; |
| 199 } | 197 } |
| 200 } | 198 } |
| 201 | 199 |
| 202 // skbug.com/3239 -- its possible that we can hit the following inconsistenc
y: | 200 // skbug.com/3239 -- its possible that we can hit the following inconsistenc
y: |
| 203 // rad == bounds.bottom - bounds.top | 201 // rad == bounds.bottom - bounds.top |
| 204 // bounds.bottom - radius < bounds.top | 202 // bounds.bottom - radius < bounds.top |
| 205 // YIKES | 203 // YIKES |
| (...skipping 384 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 590 } | 588 } |
| 591 | 589 |
| 592 for (int i = 0; i < 4; ++i) { | 590 for (int i = 0; i < 4; ++i) { |
| 593 validate_radius_check_predicates(fRadii[i].fX, fRect.fLeft, fRect.fRight
); | 591 validate_radius_check_predicates(fRadii[i].fX, fRect.fLeft, fRect.fRight
); |
| 594 validate_radius_check_predicates(fRadii[i].fY, fRect.fTop, fRect.fBottom
); | 592 validate_radius_check_predicates(fRadii[i].fY, fRect.fTop, fRect.fBottom
); |
| 595 } | 593 } |
| 596 } | 594 } |
| 597 #endif // SK_DEBUG | 595 #endif // SK_DEBUG |
| 598 | 596 |
| 599 /////////////////////////////////////////////////////////////////////////////// | 597 /////////////////////////////////////////////////////////////////////////////// |
| OLD | NEW |