allow move/zero-line/close to draw caps
authorcaryclark <caryclark@google.com>
Mon, 22 Feb 2016 20:44:54 +0000 (12:44 -0800)
committerCommit bot <commit-bot@chromium.org>
Mon, 22 Feb 2016 20:44:54 +0000 (12:44 -0800)
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

include/core/SkPath.h
src/core/SkPath.cpp
src/core/SkStroke.cpp

index e1bc5e4..8df7633 100644 (file)
@@ -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).
      */
index 06bbeef..320448a 100644 (file)
@@ -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);
index 5a43075..370cbdc 100644 (file)
@@ -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;