diff options
author | caryclark <caryclark@google.com> | 2016-02-22 12:44:54 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-02-22 12:44:54 -0800 |
commit | d49a86ade0bab1fc3048d6ba5d8536abf25ed77c (patch) | |
tree | cc29859cac808f77090602d1555905e0ddd26b85 | |
parent | e5257bd384a764d0dc1fea3a198ebc9d0101a760 (diff) |
allow move/zero-line/close to draw caps
R=fmalita@chromium.org
BUG=skia:4784
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1720953002
Review URL: https://codereview.chromium.org/1720953002
-rw-r--r-- | include/core/SkPath.h | 4 | ||||
-rw-r--r-- | src/core/SkPath.cpp | 15 | ||||
-rw-r--r-- | src/core/SkStroke.cpp | 21 |
3 files changed, 36 insertions, 4 deletions
diff --git a/include/core/SkPath.h b/include/core/SkPath.h index e1bc5e4d85..8df7633d42 100644 --- a/include/core/SkPath.h +++ b/include/core/SkPath.h @@ -1143,6 +1143,10 @@ private: bool isRectContour(bool allowPartial, int* currVerb, const SkPoint** pts, bool* isClosed, Direction* direction) const; + // called by stroker to see if all points are equal and worthy of a cap + // equivalent to a short-circuit version of getBounds().isEmpty() + bool isZeroLength() const; + /** Returns if the path can return a bound at no cost (true) or will have to perform some computation (false). */ diff --git a/src/core/SkPath.cpp b/src/core/SkPath.cpp index 06bbeef096..320448a30e 100644 --- a/src/core/SkPath.cpp +++ b/src/core/SkPath.cpp @@ -1184,6 +1184,21 @@ bool SkPath::hasOnlyMoveTos() const { return true; } +bool SkPath::isZeroLength() const { + int count = fPathRef->countPoints(); + if (count < 2) { + return true; + } + const SkPoint* pts = fPathRef.get()->points(); + const SkPoint& first = *pts; + for (int index = 1; index < count; ++index) { + if (first != pts[index]) { + return false; + } + } + return true; +} + void SkPath::addRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry, Direction dir) { assert_known_direction(dir); diff --git a/src/core/SkStroke.cpp b/src/core/SkStroke.cpp index 5a43075284..370cbdc09b 100644 --- a/src/core/SkStroke.cpp +++ b/src/core/SkStroke.cpp @@ -140,6 +140,10 @@ public: SkScalar getResScale() const { return fResScale; } + bool isZeroLength() const { + return fInner.isZeroLength() && fOuter.isZeroLength(); + } + private: SkScalar fRadius; SkScalar fInvMiterLimit; @@ -1394,13 +1398,22 @@ void SkStroke::strokePath(const SkPath& src, SkPath* dst) const { lastSegment = SkPath::kCubic_Verb; break; case SkPath::kClose_Verb: - if (stroker.hasOnlyMoveTo() && SkPaint::kButt_Cap != this->getCap()) { + if (SkPaint::kButt_Cap != this->getCap()) { /* If the stroke consists of a moveTo followed by a close, treat it as if it were followed by a zero-length line. Lines without length can have square and round end caps. */ - stroker.lineTo(stroker.moveToPt()); - lastSegment = SkPath::kLine_Verb; - break; + if (stroker.hasOnlyMoveTo()) { + stroker.lineTo(stroker.moveToPt()); + goto ZERO_LENGTH; + } + /* If the stroke consists of a moveTo followed by one or more zero-length + verbs, then followed by a close, treat is as if it were followed by a + zero-length line. Lines without length can have square & round end caps. */ + if (stroker.isZeroLength()) { + ZERO_LENGTH: + lastSegment = SkPath::kLine_Verb; + break; + } } stroker.close(lastSegment == SkPath::kLine_Verb); break; |