| 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 |
| 11 /////////////////////////////////////////////////////////////////////////////// | 11 /////////////////////////////////////////////////////////////////////////////// |
| 12 | 12 |
| 13 void SkRRect::setRectXY(const SkRect& rect, SkScalar xRad, SkScalar yRad) { | 13 void SkRRect::setRectXY(const SkRect& rect, SkScalar xRad, SkScalar yRad) { |
| 14 if (rect.isEmpty()) { | 14 if (rect.isEmpty() || !rect.isFinite()) { |
| 15 this->setEmpty(); | 15 this->setEmpty(); |
| 16 return; | 16 return; |
| 17 } | 17 } |
| 18 | 18 |
| 19 if (!SkScalarsAreFinite(xRad, yRad)) { |
| 20 xRad = yRad = 0; // devolve into a simple rect |
| 21 } |
| 19 if (xRad <= 0 || yRad <= 0) { | 22 if (xRad <= 0 || yRad <= 0) { |
| 20 // all corners are square in this case | 23 // all corners are square in this case |
| 21 this->setRect(rect); | 24 this->setRect(rect); |
| 22 return; | 25 return; |
| 23 } | 26 } |
| 24 | 27 |
| 25 if (rect.width() < xRad+xRad || rect.height() < yRad+yRad) { | 28 if (rect.width() < xRad+xRad || rect.height() < yRad+yRad) { |
| 26 SkScalar scale = SkMinScalar(SkScalarDiv(rect.width(), xRad + xRad), | 29 SkScalar scale = SkMinScalar(SkScalarDiv(rect.width(), xRad + xRad), |
| 27 SkScalarDiv(rect.height(), yRad + yRad)); | 30 SkScalarDiv(rect.height(), yRad + yRad)); |
| 28 SkASSERT(scale < SK_Scalar1); | 31 SkASSERT(scale < SK_Scalar1); |
| 29 xRad = SkScalarMul(xRad, scale); | 32 xRad = SkScalarMul(xRad, scale); |
| 30 yRad = SkScalarMul(yRad, scale); | 33 yRad = SkScalarMul(yRad, scale); |
| 31 } | 34 } |
| 32 | 35 |
| 33 fRect = rect; | 36 fRect = rect; |
| 34 for (int i = 0; i < 4; ++i) { | 37 for (int i = 0; i < 4; ++i) { |
| 35 fRadii[i].set(xRad, yRad); | 38 fRadii[i].set(xRad, yRad); |
| 36 } | 39 } |
| 37 fType = kSimple_Type; | 40 fType = kSimple_Type; |
| 38 if (xRad >= SkScalarHalf(fRect.width()) && yRad >= SkScalarHalf(fRect.height
())) { | 41 if (xRad >= SkScalarHalf(fRect.width()) && yRad >= SkScalarHalf(fRect.height
())) { |
| 39 fType = kOval_Type; | 42 fType = kOval_Type; |
| 40 // TODO: assert that all the x&y radii are already W/2 & H/2 | 43 // TODO: assert that all the x&y radii are already W/2 & H/2 |
| 41 } | 44 } |
| 42 | 45 |
| 43 SkDEBUGCODE(this->validate();) | 46 SkDEBUGCODE(this->validate();) |
| 44 } | 47 } |
| 45 | 48 |
| 46 void SkRRect::setNinePatch(const SkRect& rect, SkScalar leftRad, SkScalar topRad
, | 49 void SkRRect::setNinePatch(const SkRect& rect, SkScalar leftRad, SkScalar topRad
, |
| 47 SkScalar rightRad, SkScalar bottomRad) { | 50 SkScalar rightRad, SkScalar bottomRad) { |
| 48 if (rect.isEmpty()) { | 51 if (rect.isEmpty() || !rect.isFinite()) { |
| 49 this->setEmpty(); | 52 this->setEmpty(); |
| 50 return; | 53 return; |
| 51 } | 54 } |
| 52 | 55 |
| 56 const SkScalar array[4] = { leftRad, topRad, rightRad, bottomRad }; |
| 57 if (!SkScalarsAreFinite(array, 4)) { |
| 58 this->setRect(rect); // devolve into a simple rect |
| 59 return; |
| 60 } |
| 61 |
| 53 leftRad = SkMaxScalar(leftRad, 0); | 62 leftRad = SkMaxScalar(leftRad, 0); |
| 54 topRad = SkMaxScalar(topRad, 0); | 63 topRad = SkMaxScalar(topRad, 0); |
| 55 rightRad = SkMaxScalar(rightRad, 0); | 64 rightRad = SkMaxScalar(rightRad, 0); |
| 56 bottomRad = SkMaxScalar(bottomRad, 0); | 65 bottomRad = SkMaxScalar(bottomRad, 0); |
| 57 | 66 |
| 58 SkScalar scale = SK_Scalar1; | 67 SkScalar scale = SK_Scalar1; |
| 59 if (leftRad + rightRad > rect.width()) { | 68 if (leftRad + rightRad > rect.width()) { |
| 60 scale = SkScalarDiv(rect.width(), leftRad + rightRad); | 69 scale = SkScalarDiv(rect.width(), leftRad + rightRad); |
| 61 } | 70 } |
| 62 if (topRad + bottomRad > rect.height()) { | 71 if (topRad + bottomRad > rect.height()) { |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 118 | 127 |
| 119 static SkScalar clamp_radius_sub(SkScalar rad, SkScalar min, SkScalar max) { | 128 static SkScalar clamp_radius_sub(SkScalar rad, SkScalar min, SkScalar max) { |
| 120 SkASSERT(rad <= max - min); | 129 SkASSERT(rad <= max - min); |
| 121 if (max - rad < min) { | 130 if (max - rad < min) { |
| 122 rad = SkScalarDecULP(rad); | 131 rad = SkScalarDecULP(rad); |
| 123 } | 132 } |
| 124 return rad; | 133 return rad; |
| 125 } | 134 } |
| 126 | 135 |
| 127 void SkRRect::setRectRadii(const SkRect& rect, const SkVector radii[4]) { | 136 void SkRRect::setRectRadii(const SkRect& rect, const SkVector radii[4]) { |
| 128 if (rect.isEmpty()) { | 137 if (rect.isEmpty() || !rect.isFinite()) { |
| 129 this->setEmpty(); | 138 this->setEmpty(); |
| 130 return; | 139 return; |
| 131 } | 140 } |
| 132 | 141 |
| 142 if (!SkScalarsAreFinite(&radii[0].fX, 8)) { |
| 143 this->setRect(rect); // devolve into a simple rect |
| 144 return; |
| 145 } |
| 146 |
| 133 fRect = rect; | 147 fRect = rect; |
| 134 memcpy(fRadii, radii, sizeof(fRadii)); | 148 memcpy(fRadii, radii, sizeof(fRadii)); |
| 135 | 149 |
| 136 bool allCornersSquare = true; | 150 bool allCornersSquare = true; |
| 137 | 151 |
| 138 // Clamp negative radii to zero | 152 // Clamp negative radii to zero |
| 139 for (int i = 0; i < 4; ++i) { | 153 for (int i = 0; i < 4; ++i) { |
| 140 if (fRadii[i].fX <= 0 || fRadii[i].fY <= 0) { | 154 if (fRadii[i].fX <= 0 || fRadii[i].fY <= 0) { |
| 141 // In this case we are being a little fast & loose. Since one of | 155 // In this case we are being a little fast & loose. Since one of |
| 142 // the radii is 0 the corner is square. However, the other radii | 156 // the radii is 0 the corner is square. However, the other radii |
| (...skipping 421 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 564 case kComplex_Type: | 578 case kComplex_Type: |
| 565 SkASSERT(!fRect.isEmpty()); | 579 SkASSERT(!fRect.isEmpty()); |
| 566 SkASSERT(!allRadiiZero && !allRadiiSame && !allCornersSquare); | 580 SkASSERT(!allRadiiZero && !allRadiiSame && !allCornersSquare); |
| 567 SkASSERT(!patchesOfNine); | 581 SkASSERT(!patchesOfNine); |
| 568 break; | 582 break; |
| 569 } | 583 } |
| 570 } | 584 } |
| 571 #endif // SK_DEBUG | 585 #endif // SK_DEBUG |
| 572 | 586 |
| 573 /////////////////////////////////////////////////////////////////////////////// | 587 /////////////////////////////////////////////////////////////////////////////// |
| OLD | NEW |