aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/GrShape.cpp
diff options
context:
space:
mode:
authorGravatar Brian Salomon <bsalomon@google.com>2017-12-21 11:56:42 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-12-21 22:45:15 +0000
commit72f78c37010eb2bf20be4884d4f376d122830dfd (patch)
tree3ff52aa1e3f3bc8776e85f9c64f4c371772b336b /src/gpu/GrShape.cpp
parent6925fc0429424cae67a887e6faa27f168995612a (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.cpp103
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;
+}