diff options
author | Brian Salomon <bsalomon@google.com> | 2017-12-21 11:56:42 -0500 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-12-21 22:45:15 +0000 |
commit | 72f78c37010eb2bf20be4884d4f376d122830dfd (patch) | |
tree | 3ff52aa1e3f3bc8776e85f9c64f4c371772b336b /src/gpu/GrShape.cpp | |
parent | 6925fc0429424cae67a887e6faa27f168995612a (diff) |
Make GrShape recognize horizontal/vertical dashed lines with 0 off intervals as rrects.
Change-Id: Ic29b41911e0185d36093d5352f4494709e8124ba
Reviewed-on: https://skia-review.googlesource.com/88428
Commit-Queue: Brian Salomon <bsalomon@google.com>
Reviewed-by: Greg Daniel <egdaniel@google.com>
Diffstat (limited to 'src/gpu/GrShape.cpp')
-rw-r--r-- | src/gpu/GrShape.cpp | 103 |
1 files changed, 56 insertions, 47 deletions
diff --git a/src/gpu/GrShape.cpp b/src/gpu/GrShape.cpp index 4c9338409c..b9bc00d1aa 100644 --- a/src/gpu/GrShape.cpp +++ b/src/gpu/GrShape.cpp @@ -579,6 +579,13 @@ void GrShape::attemptToSimplifyLine() { SkASSERT(Type::kLine == fType); SkASSERT(!fInheritedKey.count()); if (fStyle.isDashed()) { + bool allOffsZero = true; + for (int i = 1; i < fStyle.dashIntervalCnt() && allOffsZero; i += 2) { + allOffsZero = !fStyle.dashIntervals()[i]; + } + if (allOffsZero && this->attemptToSimplifyStrokedLineToRRect()) { + return; + } // Dashing ignores inverseness. fLineData.fInverted = false; return; @@ -595,57 +602,59 @@ void GrShape::attemptToSimplifyLine() { this->changeType(fLineData.fInverted ? Type::kInvertedEmpty : Type::kEmpty); return; } - SkPoint* pts = fLineData.fPts; - if (fStyle.strokeRec().getStyle() == SkStrokeRec::kStroke_Style) { - // If it is horizontal or vertical we will turn it into a filled rrect. - SkRect rect; - rect.fLeft = SkTMin(pts[0].fX, pts[1].fX); - rect.fRight = SkTMax(pts[0].fX, pts[1].fX); - rect.fTop = SkTMin(pts[0].fY, pts[1].fY); - rect.fBottom = SkTMax(pts[0].fY, pts[1].fY); - bool eqX = rect.fLeft == rect.fRight; - bool eqY = rect.fTop == rect.fBottom; - if (eqX || eqY) { - SkScalar r = fStyle.strokeRec().getWidth() / 2; - bool inverted = fLineData.fInverted; - this->changeType(Type::kRRect); - switch (fStyle.strokeRec().getCap()) { - case SkPaint::kButt_Cap: - if (eqX && eqY) { - this->changeType(Type::kEmpty); - return; - } - if (eqX) { - rect.outset(r, 0); - } else { - rect.outset(0, r); - } - fRRectData.fRRect = SkRRect::MakeRect(rect); - break; - case SkPaint::kSquare_Cap: - rect.outset(r, r); - fRRectData.fRRect = SkRRect::MakeRect(rect); - break; - case SkPaint::kRound_Cap: - rect.outset(r, r); - fRRectData.fRRect = SkRRect::MakeRectXY(rect, r, r); - break; - } - fRRectData.fInverted = inverted; - fRRectData.fDir = kDefaultRRectDir; - fRRectData.fStart = kDefaultRRectStart; - if (fRRectData.fRRect.isEmpty()) { - // This can happen when r is very small relative to the rect edges. - this->changeType(inverted ? Type::kInvertedEmpty : Type::kEmpty); - return; - } - fStyle = GrStyle::SimpleFill(); - return; - } + if (fStyle.strokeRec().getStyle() == SkStrokeRec::kStroke_Style && + this->attemptToSimplifyStrokedLineToRRect()) { + return; } // Only path effects could care about the order of the points. Otherwise canonicalize // the point order. + SkPoint* pts = fLineData.fPts; if (pts[1].fY < pts[0].fY || (pts[1].fY == pts[0].fY && pts[1].fX < pts[0].fX)) { SkTSwap(pts[0], pts[1]); } } + +bool GrShape::attemptToSimplifyStrokedLineToRRect() { + SkASSERT(Type::kLine == fType); + SkASSERT(fStyle.strokeRec().getStyle() == SkStrokeRec::kStroke_Style); + + SkRect rect; + SkVector outset; + // If we allowed a rotation angle for rrects we could capture all cases here. + if (fLineData.fPts[0].fY == fLineData.fPts[1].fY) { + rect.fLeft = SkTMin(fLineData.fPts[0].fX, fLineData.fPts[1].fX); + rect.fRight = SkTMax(fLineData.fPts[0].fX, fLineData.fPts[1].fX); + rect.fTop = rect.fBottom = fLineData.fPts[0].fY; + outset.fY = fStyle.strokeRec().getWidth() / 2.f; + outset.fX = SkPaint::kButt_Cap == fStyle.strokeRec().getCap() ? 0.f : outset.fY; + } else if (fLineData.fPts[0].fX == fLineData.fPts[1].fX) { + rect.fTop = SkTMin(fLineData.fPts[0].fY, fLineData.fPts[1].fY); + rect.fBottom = SkTMax(fLineData.fPts[0].fY, fLineData.fPts[1].fY); + rect.fLeft = rect.fRight = fLineData.fPts[0].fX; + outset.fX = fStyle.strokeRec().getWidth() / 2.f; + outset.fY = SkPaint::kButt_Cap == fStyle.strokeRec().getCap() ? 0.f : outset.fX; + } else { + return false; + } + rect.outset(outset.fX, outset.fY); + if (rect.isEmpty()) { + this->changeType(Type::kEmpty); + fStyle = GrStyle::SimpleFill(); + return true; + } + SkRRect rrect; + if (fStyle.strokeRec().getCap() == SkPaint::kRound_Cap) { + SkASSERT(outset.fX == outset.fY); + rrect = SkRRect::MakeRectXY(rect, outset.fX, outset.fY); + } else { + rrect = SkRRect::MakeRect(rect); + } + bool inverted = fLineData.fInverted && !fStyle.hasPathEffect(); + this->changeType(Type::kRRect); + fRRectData.fRRect = rrect; + fRRectData.fInverted = inverted; + fRRectData.fDir = kDefaultRRectDir; + fRRectData.fStart = kDefaultRRectStart; + fStyle = GrStyle::SimpleFill(); + return true; +} |