diff options
Diffstat (limited to 'src/core/SkRRect.cpp')
-rw-r--r-- | src/core/SkRRect.cpp | 75 |
1 files changed, 74 insertions, 1 deletions
diff --git a/src/core/SkRRect.cpp b/src/core/SkRRect.cpp index 915ed75327..082646c2a7 100644 --- a/src/core/SkRRect.cpp +++ b/src/core/SkRRect.cpp @@ -43,6 +43,61 @@ void SkRRect::setRectXY(const SkRect& rect, SkScalar xRad, SkScalar yRad) { SkDEBUGCODE(this->validate();) } +void SkRRect::setNinePatch(const SkRect& rect, SkScalar leftRad, SkScalar topRad, + SkScalar rightRad, SkScalar bottomRad) { + if (rect.isEmpty()) { + this->setEmpty(); + return; + } + + leftRad = SkMaxScalar(leftRad, 0); + topRad = SkMaxScalar(topRad, 0); + rightRad = SkMaxScalar(rightRad, 0); + bottomRad = SkMaxScalar(bottomRad, 0); + + SkScalar scale = SK_Scalar1; + if (leftRad + rightRad > rect.width()) { + scale = SkScalarDiv(rect.width(), leftRad + rightRad); + } + if (topRad + bottomRad > rect.height()) { + scale = SkMinScalar(scale, SkScalarDiv(rect.width(), leftRad + rightRad)); + } + + if (scale < SK_Scalar1) { + leftRad = SkScalarMul(leftRad, scale); + topRad = SkScalarMul(topRad, scale); + rightRad = SkScalarMul(rightRad, scale); + bottomRad = SkScalarMul(bottomRad, scale); + } + + if (leftRad == rightRad && topRad == bottomRad) { + if (leftRad >= SkScalarHalf(rect.width()) && topRad >= SkScalarHalf(rect.height())) { + fType = kOval_Type; + } else if (0 == leftRad || 0 == topRad) { + // If the left and (by equality check above) right radii are zero then it is a rect. + // Same goes for top/bottom. + fType = kRect_Type; + leftRad = 0; + topRad = 0; + rightRad = 0; + bottomRad = 0; + } else { + fType = kSimple_Type; + } + } else { + fType = kNinePatch_Type; + } + + fRect = rect; + fRadii[kUpperLeft_Corner].set(leftRad, topRad); + fRadii[kUpperRight_Corner].set(rightRad, topRad); + fRadii[kLowerRight_Corner].set(rightRad, bottomRad); + fRadii[kLowerLeft_Corner].set(leftRad, bottomRad); + + SkDEBUGCODE(this->validate();) +} + + void SkRRect::setRectRadii(const SkRect& rect, const SkVector radii[4]) { if (rect.isEmpty()) { this->setEmpty(); @@ -200,6 +255,13 @@ bool SkRRect::contains(const SkRect& rect) const { this->checkCornerContainment(rect.fLeft, rect.fBottom); } +static bool radii_are_nine_patch(const SkVector radii[4]) { + return radii[SkRRect::kUpperLeft_Corner].fX == radii[SkRRect::kLowerLeft_Corner].fX && + radii[SkRRect::kUpperLeft_Corner].fY == radii[SkRRect::kUpperRight_Corner].fY && + radii[SkRRect::kUpperRight_Corner].fX == radii[SkRRect::kLowerRight_Corner].fX && + radii[SkRRect::kLowerLeft_Corner].fY == radii[SkRRect::kLowerRight_Corner].fY; +} + // There is a simplified version of this method in setRectXY void SkRRect::computeType() const { SkDEBUGCODE(this->validate();) @@ -238,7 +300,11 @@ void SkRRect::computeType() const { return; } - fType = kComplex_Type; + if (radii_are_nine_patch(fRadii)) { + fType = kNinePatch_Type; + } else { + fType = kComplex_Type; + } } static bool matrix_only_scale_and_translate(const SkMatrix& matrix) { @@ -391,6 +457,7 @@ void SkRRect::validate() const { allCornersSquare = false; } } + bool patchesOfNine = radii_are_nine_patch(fRadii); switch (fType) { case kEmpty_Type: @@ -417,9 +484,15 @@ void SkRRect::validate() const { SkASSERT(!fRect.isEmpty()); SkASSERT(!allRadiiZero && allRadiiSame && !allCornersSquare); break; + case kNinePatch_Type: + SkASSERT(!fRect.isEmpty()); + SkASSERT(!allRadiiZero && !allRadiiSame && !allCornersSquare); + SkASSERT(patchesOfNine); + break; case kComplex_Type: SkASSERT(!fRect.isEmpty()); SkASSERT(!allRadiiZero && !allRadiiSame && !allCornersSquare); + SkASSERT(!patchesOfNine); break; case kUnknown_Type: // no limits on this |