diff options
author | scroggo@google.com <scroggo@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-11-05 15:54:42 +0000 |
---|---|---|
committer | scroggo@google.com <scroggo@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-11-05 15:54:42 +0000 |
commit | 20e3cd2c9fbc049eae8bcedc591c2cc8d4bed656 (patch) | |
tree | 12b4d1d2461bdca4dc3284a7c27e8d7a02bad022 /src | |
parent | a93f4e770f22f913197bef82dc19078e12bee76b (diff) |
Add SkRRect::transform.
Much like SkPath::transform, it transforms an SkRRect based on an
SkMatrix. Unlike SkPath::transform, it will fail for matrices that
contain perspective or skewing.
Required by a future change (https://codereview.chromium.org/48623006)
to speed up drawing large blurry rounded rectangles by using ninepatches.
TODO: This could easily support 90 degree rotations, if desired.
BUG=https://b.corp.google.com/issue?id=11174385
R=reed@google.com, robertphillips@google.com
Review URL: https://codereview.chromium.org/52703003
git-svn-id: http://skia.googlecode.com/svn/trunk@12132 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src')
-rw-r--r-- | src/core/SkRRect.cpp | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/src/core/SkRRect.cpp b/src/core/SkRRect.cpp index bcbf37ec59..e5296d4e3a 100644 --- a/src/core/SkRRect.cpp +++ b/src/core/SkRRect.cpp @@ -6,6 +6,7 @@ */ #include "SkRRect.h" +#include "SkMatrix.h" /////////////////////////////////////////////////////////////////////////////// @@ -233,6 +234,85 @@ void SkRRect::computeType() const { fType = kComplex_Type; } +static bool matrix_only_scale_and_translate(const SkMatrix& matrix) { + const SkMatrix::TypeMask m = (SkMatrix::TypeMask) (SkMatrix::kAffine_Mask + | SkMatrix::kPerspective_Mask); + return (matrix.getType() & m) == 0; +} + +bool SkRRect::transform(const SkMatrix& matrix, SkRRect* dst) const { + if (NULL == dst) { + return false; + } + + // Assert that the caller is not trying to do this in place, which + // would violate const-ness. Do not return false though, so that + // if they know what they're doing and want to violate it they can. + SkASSERT(dst != this); + + if (matrix.isIdentity()) { + *dst = *this; + return true; + } + + // If transform supported 90 degree rotations (which it could), we could + // use SkMatrix::rectStaysRect() to check for a valid transformation. + if (!matrix_only_scale_and_translate(matrix)) { + return false; + } + + SkRect newRect; + if (!matrix.mapRect(&newRect, fRect)) { + return false; + } + + // At this point, this is guaranteed to succeed, so we can modify dst. + dst->fRect = newRect; + + // Now scale each corner + SkScalar xScale = matrix.getScaleX(); + const bool flipX = xScale < 0; + if (flipX) { + xScale = -xScale; + } + SkScalar yScale = matrix.getScaleY(); + const bool flipY = yScale < 0; + if (flipY) { + yScale = -yScale; + } + + // Scale the radii without respecting the flip. + for (int i = 0; i < 4; ++i) { + dst->fRadii[i].fX = SkScalarMul(fRadii[i].fX, xScale); + dst->fRadii[i].fY = SkScalarMul(fRadii[i].fY, yScale); + } + + // Now swap as necessary. + if (flipX) { + if (flipY) { + // Swap with opposite corners + SkTSwap(dst->fRadii[kUpperLeft_Corner], dst->fRadii[kLowerRight_Corner]); + SkTSwap(dst->fRadii[kUpperRight_Corner], dst->fRadii[kLowerLeft_Corner]); + } else { + // Only swap in x + SkTSwap(dst->fRadii[kUpperRight_Corner], dst->fRadii[kUpperLeft_Corner]); + SkTSwap(dst->fRadii[kLowerRight_Corner], dst->fRadii[kLowerLeft_Corner]); + } + } else if (flipY) { + // Only swap in y + SkTSwap(dst->fRadii[kUpperLeft_Corner], dst->fRadii[kLowerLeft_Corner]); + 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; +} + /////////////////////////////////////////////////////////////////////////////// void SkRRect::inset(SkScalar dx, SkScalar dy, SkRRect* dst) const { |