aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar caryclark <caryclark@google.com>2016-02-22 12:44:54 -0800
committerGravatar Commit bot <commit-bot@chromium.org>2016-02-22 12:44:54 -0800
commitd49a86ade0bab1fc3048d6ba5d8536abf25ed77c (patch)
treecc29859cac808f77090602d1555905e0ddd26b85
parente5257bd384a764d0dc1fea3a198ebc9d0101a760 (diff)
allow move/zero-line/close to draw caps
-rw-r--r--include/core/SkPath.h4
-rw-r--r--src/core/SkPath.cpp15
-rw-r--r--src/core/SkStroke.cpp21
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;