From a2318576d6510dc63513ce335ed0027666bd55bf Mon Sep 17 00:00:00 2001 From: Brian Osman Date: Mon, 10 Jul 2017 15:09:26 -0400 Subject: Correctly stroke zero length segments in multi-contour paths Bug: skia: Change-Id: I959287780ef94a258a6746132f3acb9f90e6c6cc Reviewed-on: https://skia-review.googlesource.com/21863 Reviewed-by: Cary Clark Commit-Queue: Brian Osman --- src/core/SkPath.cpp | 6 +++--- src/core/SkStroke.cpp | 12 +++++++----- 2 files changed, 10 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/core/SkPath.cpp b/src/core/SkPath.cpp index f4c8e8b7c4..2be3251401 100644 --- a/src/core/SkPath.cpp +++ b/src/core/SkPath.cpp @@ -1192,12 +1192,12 @@ bool SkPath::hasOnlyMoveTos() const { return true; } -bool SkPath::isZeroLength() const { - int count = fPathRef->countPoints(); +bool SkPath::isZeroLengthSincePoint(int startPtIndex) const { + int count = fPathRef->countPoints() - startPtIndex; if (count < 2) { return true; } - const SkPoint* pts = fPathRef.get()->points(); + const SkPoint* pts = fPathRef.get()->points() + startPtIndex; const SkPoint& first = *pts; for (int index = 1; index < count; ++index) { if (first != pts[index]) { diff --git a/src/core/SkStroke.cpp b/src/core/SkStroke.cpp index e384df1ef7..61bd730e67 100644 --- a/src/core/SkStroke.cpp +++ b/src/core/SkStroke.cpp @@ -136,14 +136,14 @@ public: void done(SkPath* dst, bool isLine) { this->finishContour(false, isLine); - fOuter.addPath(fExtra); dst->swap(fOuter); } SkScalar getResScale() const { return fResScale; } - bool isZeroLength() const { - return fInner.isZeroLength() && fOuter.isZeroLength(); + bool isCurrentContourEmpty() const { + return fInner.isZeroLengthSincePoint(0) && + fOuter.isZeroLengthSincePoint(fFirstOuterPtIndexInContour); } private: @@ -156,6 +156,7 @@ private: SkVector fFirstNormal, fPrevNormal, fFirstUnitNormal, fPrevUnitNormal; SkPoint fFirstPt, fPrevPt; // on original path SkPoint fFirstOuterPt; + int fFirstOuterPtIndexInContour; int fSegmentCount; bool fPrevIsLine; bool fCanIgnoreCenter; @@ -164,7 +165,6 @@ private: SkStrokerPriv::JoinProc fJoiner; SkPath fInner, fOuter; // outer is our working answer, inner is temp - SkPath fExtra; // added as extra complete contours enum StrokeType { kOuter_StrokeType = 1, // use sign-opposite values later to flip perpendicular axis @@ -325,6 +325,7 @@ void SkPathStroker::finishContour(bool close, bool currIsLine) { // reallocating its internal storage. fInner.rewind(); fSegmentCount = -1; + fFirstOuterPtIndexInContour = fOuter.countPoints(); } /////////////////////////////////////////////////////////////////////////////// @@ -352,6 +353,7 @@ SkPathStroker::SkPathStroker(const SkPath& src, fCapper = SkStrokerPriv::CapFactory(cap); fJoiner = SkStrokerPriv::JoinFactory(join); fSegmentCount = -1; + fFirstOuterPtIndexInContour = 0; fPrevIsLine = false; // Need some estimate of how large our final result (fOuter) @@ -1431,7 +1433,7 @@ void SkStroke::strokePath(const SkPath& src, SkPath* dst) const { /* 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()) { + if (stroker.isCurrentContourEmpty()) { ZERO_LENGTH: lastSegment = SkPath::kLine_Verb; break; -- cgit v1.2.3