return this from maker calls, so we can chain the calls

Bug: skia:
Change-Id: Id62eda9dab9399ce1183a959438db7dde59889d8
Reviewed-on: https://skia-review.googlesource.com/147113
Commit-Queue: Mike Reed <reed@google.com>
Reviewed-by: Kevin Lubick <kjlubick@google.com>
diff --git a/gm/concavepaths.cpp b/gm/concavepaths.cpp
index 4015236..adbc2c4 100644
--- a/gm/concavepaths.cpp
+++ b/gm/concavepaths.cpp
@@ -14,10 +14,10 @@
 void test_concave(SkCanvas* canvas, const SkPaint& paint) {
     SkPath path;
     canvas->translate(0, 0);
-    path.moveTo(SkIntToScalar(20), SkIntToScalar(20));
-    path.lineTo(SkIntToScalar(80), SkIntToScalar(20));
-    path.lineTo(SkIntToScalar(30), SkIntToScalar(30));
-    path.lineTo(SkIntToScalar(20), SkIntToScalar(80));
+    path.moveTo(SkIntToScalar(20), SkIntToScalar(20))
+        .lineTo(SkIntToScalar(80), SkIntToScalar(20))
+        .lineTo(SkIntToScalar(30), SkIntToScalar(30))
+        .lineTo(SkIntToScalar(20), SkIntToScalar(80));
     canvas->drawPath(path, paint);
 }
 
@@ -26,10 +26,10 @@
     SkPath path;
     canvas->save();
     canvas->translate(100, 0);
-    path.moveTo(SkIntToScalar(20), SkIntToScalar(20));
-    path.lineTo(SkIntToScalar(20), SkIntToScalar(80));
-    path.lineTo(SkIntToScalar(30), SkIntToScalar(30));
-    path.lineTo(SkIntToScalar(80), SkIntToScalar(20));
+    path.moveTo(SkIntToScalar(20), SkIntToScalar(20))
+        .lineTo(SkIntToScalar(20), SkIntToScalar(80))
+        .lineTo(SkIntToScalar(30), SkIntToScalar(30))
+        .lineTo(SkIntToScalar(80), SkIntToScalar(20));
     canvas->drawPath(path, paint);
     canvas->restore();
 }
@@ -39,10 +39,10 @@
     SkPath path;
     canvas->save();
     canvas->translate(200, 0);
-    path.moveTo(SkIntToScalar(20), SkIntToScalar(20));
-    path.lineTo(SkIntToScalar(80), SkIntToScalar(80));
-    path.lineTo(SkIntToScalar(80), SkIntToScalar(20));
-    path.lineTo(SkIntToScalar(20), SkIntToScalar(80));
+    path.moveTo(SkIntToScalar(20), SkIntToScalar(20))
+        .lineTo(SkIntToScalar(80), SkIntToScalar(80))
+        .lineTo(SkIntToScalar(80), SkIntToScalar(20))
+        .lineTo(SkIntToScalar(20), SkIntToScalar(80));
     canvas->drawPath(path, paint);
     canvas->restore();
 }
@@ -52,12 +52,12 @@
     SkPath path;
     canvas->save();
     canvas->translate(300, 0);
-    path.moveTo(SkIntToScalar(20), SkIntToScalar(20));
-    path.lineTo(SkIntToScalar(50), SkIntToScalar(40));
-    path.lineTo(SkIntToScalar(80), SkIntToScalar(20));
-    path.lineTo(SkIntToScalar(80), SkIntToScalar(80));
-    path.lineTo(SkIntToScalar(50), SkIntToScalar(60));
-    path.lineTo(SkIntToScalar(20), SkIntToScalar(80));
+    path.moveTo(SkIntToScalar(20), SkIntToScalar(20))
+        .lineTo(SkIntToScalar(50), SkIntToScalar(40))
+        .lineTo(SkIntToScalar(80), SkIntToScalar(20))
+        .lineTo(SkIntToScalar(80), SkIntToScalar(80))
+        .lineTo(SkIntToScalar(50), SkIntToScalar(60))
+        .lineTo(SkIntToScalar(20), SkIntToScalar(80));
     canvas->drawPath(path, paint);
     canvas->restore();
 }
@@ -69,12 +69,12 @@
     canvas->save();
     canvas->translate(400, 0);
     path.setIsVolatile(true);
-    path.moveTo(20, 20);
-    path.lineTo(50, 50);
-    path.lineTo(68, 20);
-    path.lineTo(68, 80);
-    path.lineTo(50, 50);
-    path.lineTo(20, 80);
+    path.moveTo(20, 20)
+        .lineTo(50, 50)
+        .lineTo(68, 20)
+        .lineTo(68, 80)
+        .lineTo(50, 50)
+        .lineTo(20, 80);
     canvas->drawPath(path, paint);
     canvas->restore();
 }
@@ -86,12 +86,12 @@
     canvas->save();
     canvas->translate(400, 100);
     path.setIsVolatile(true);
-    path.moveTo(80,     50);
-    path.lineTo(40,     80);
-    path.lineTo(60,     20);
-    path.lineTo(20,     20);
-    path.lineTo(39.99f, 80);
-    path.lineTo(80,     50);
+    path.moveTo(80,     50)
+        .lineTo(40,     80)
+        .lineTo(60,     20)
+        .lineTo(20,     20)
+        .lineTo(39.99f, 80)
+        .lineTo(80,     50);
     canvas->drawPath(path, paint);
     canvas->restore();
 }
@@ -101,12 +101,12 @@
     SkPath path;
     canvas->save();
     canvas->translate(0, 100);
-    path.moveTo(SkIntToScalar(20), SkIntToScalar(20));
-    path.lineTo(SkIntToScalar(80), SkIntToScalar(80));
-    path.lineTo(SkIntToScalar(70), SkIntToScalar(50));
-    path.lineTo(SkIntToScalar(80), SkIntToScalar(20));
-    path.lineTo(SkIntToScalar(20), SkIntToScalar(80));
-    path.lineTo(SkIntToScalar(0), SkIntToScalar(50));
+    path.moveTo(SkIntToScalar(20), SkIntToScalar(20))
+        .lineTo(SkIntToScalar(80), SkIntToScalar(80))
+        .lineTo(SkIntToScalar(70), SkIntToScalar(50))
+        .lineTo(SkIntToScalar(80), SkIntToScalar(20))
+        .lineTo(SkIntToScalar(20), SkIntToScalar(80))
+        .lineTo(SkIntToScalar(0), SkIntToScalar(50));
     canvas->drawPath(path, paint);
     canvas->restore();
 }
@@ -117,12 +117,12 @@
     SkPath path;
     canvas->save();
     canvas->translate(100, 100);
-    path.moveTo(SkIntToScalar(20), SkIntToScalar(20));
-    path.lineTo(SkIntToScalar(60), SkIntToScalar(50));
-    path.lineTo(SkIntToScalar(20), SkIntToScalar(80));
-    path.moveTo(SkIntToScalar(40), SkIntToScalar(20));
-    path.lineTo(SkIntToScalar(40), SkIntToScalar(80));
-    path.lineTo(SkIntToScalar(80), SkIntToScalar(50));
+    path.moveTo(SkIntToScalar(20), SkIntToScalar(20))
+        .lineTo(SkIntToScalar(60), SkIntToScalar(50))
+        .lineTo(SkIntToScalar(20), SkIntToScalar(80))
+        .moveTo(SkIntToScalar(40), SkIntToScalar(20))
+        .lineTo(SkIntToScalar(40), SkIntToScalar(80))
+        .lineTo(SkIntToScalar(80), SkIntToScalar(50));
     canvas->drawPath(path, paint);
     canvas->restore();
 }
@@ -132,30 +132,18 @@
     SkPath path;
     canvas->save();
     canvas->translate(200, 100);
-    path.moveTo(SkIntToScalar(20), SkIntToScalar(20));
-    path.lineTo(SkIntToScalar(80), SkIntToScalar(20));
-    path.lineTo(SkIntToScalar(80), SkIntToScalar(80));
-    path.lineTo(SkIntToScalar(20), SkIntToScalar(80));
-    path.moveTo(SkIntToScalar(30), SkIntToScalar(30));
-    path.lineTo(SkIntToScalar(30), SkIntToScalar(70));
-    path.lineTo(SkIntToScalar(70), SkIntToScalar(70));
-    path.lineTo(SkIntToScalar(70), SkIntToScalar(30));
+    path.addPoly({{20,20}, {80,20}, {80,80}, {20,80}}, false)
+        .addPoly({{30,30}, {30,70}, {70,70}, {70,30}}, false);
     canvas->drawPath(path, paint);
     canvas->restore();
 }
 
 // Star test (self-intersecting)
 void test_star(SkCanvas* canvas, const SkPaint& paint) {
-    SkPath path;
     canvas->save();
     canvas->translate(300, 100);
-    path.moveTo(30, 20);
-    path.lineTo(50, 80);
-    path.lineTo(70, 20);
-    path.lineTo(20, 57);
-    path.lineTo(80, 57);
-    path.close();
-    canvas->drawPath(path, paint);
+    canvas->drawPath(SkPath().addPoly({{30,20}, {50,80}, {70,20}, {20,57}, {80,57}}, false),
+                     paint);
     canvas->restore();
 }
 
diff --git a/include/core/SkPath.h b/include/core/SkPath.h
index d08ecfa..371097f 100644
--- a/include/core/SkPath.h
+++ b/include/core/SkPath.h
@@ -21,6 +21,7 @@
 #include "SkMatrix.h"
 #include "../private/SkPathRef.h"
 #include "../private/SkTo.h"
+#include <initializer_list>
 
 class SkAutoPathBoundsUpdate;
 class SkData;
@@ -301,7 +302,7 @@
         Removes verb array, SkPoint array, and weights, and sets FillType to kWinding_FillType.
         Internal storage associated with SkPath is released.
     */
-    void reset();
+    SkPath& reset();
 
     /** Sets SkPath to its initial state, preserving internal storage.
         Removes verb array, SkPoint array, and weights, and sets FillType to kWinding_FillType.
@@ -310,7 +311,7 @@
         Use rewind() instead of reset() if SkPath storage will be reused and performance
         is critical.
     */
-    void rewind();
+    SkPath& rewind();
 
     /** Returns if SkPath is empty.
         Empty SkPath may have FillType but has no SkPoint, SkPath::Verb, or conic weight.
@@ -548,15 +549,16 @@
 
         @param x  x-axis value of contour start
         @param y  y-axis value of contour start
+        @return this path
     */
-    void moveTo(SkScalar x, SkScalar y);
+    SkPath& moveTo(SkScalar x, SkScalar y);
 
     /** Adds beginning of contour at SkPoint p.
 
         @param p  contour start
     */
-    void moveTo(const SkPoint& p) {
-        this->moveTo(p.fX, p.fY);
+    SkPath& moveTo(const SkPoint& p) {
+        return this->moveTo(p.fX, p.fY);
     }
 
     /** Adds beginning of contour relative to last point.
@@ -567,7 +569,7 @@
         @param dx  offset from last point to contour start on x-axis
         @param dy  offset from last point to contour start on y-axis
     */
-    void rMoveTo(SkScalar dx, SkScalar dy);
+    SkPath& rMoveTo(SkScalar dx, SkScalar dy);
 
     /** Adds line from last point to (x, y). If SkPath is empty, or last SkPath::Verb is
         kClose_Verb, last point is set to (0, 0) before adding line.
@@ -578,7 +580,7 @@
         @param x  end of added line in x
         @param y  end of added line in y
     */
-    void lineTo(SkScalar x, SkScalar y);
+    SkPath& lineTo(SkScalar x, SkScalar y);
 
     /** Adds line from last point to SkPoint p. If SkPath is empty, or last SkPath::Verb is
         kClose_Verb, last point is set to (0, 0) before adding line.
@@ -588,8 +590,8 @@
 
         @param p  end SkPoint of added line
     */
-    void lineTo(const SkPoint& p) {
-        this->lineTo(p.fX, p.fY);
+    SkPath& lineTo(const SkPoint& p) {
+        return this->lineTo(p.fX, p.fY);
     }
 
     /** Adds line from last point to vector (dx, dy). If SkPath is empty, or last SkPath::Verb is
@@ -603,7 +605,7 @@
         @param dx  offset from last point to line end on x-axis
         @param dy  offset from last point to line end on y-axis
     */
-    void rLineTo(SkScalar dx, SkScalar dy);
+    SkPath& rLineTo(SkScalar dx, SkScalar dy);
 
     /** Adds quad from last point towards (x1, y1), to (x2, y2).
         If SkPath is empty, or last SkPath::Verb is kClose_Verb, last point is set to (0, 0)
@@ -618,7 +620,7 @@
         @param x2  end SkPoint of quad in x
         @param y2  end SkPoint of quad in y
     */
-    void quadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2);
+    SkPath& quadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2);
 
     /** Adds quad from last point towards SkPoint p1, to SkPoint p2.
         If SkPath is empty, or last SkPath::Verb is kClose_Verb, last point is set to (0, 0)
@@ -631,8 +633,8 @@
         @param p1  control SkPoint of added quad
         @param p2  end SkPoint of added quad
     */
-    void quadTo(const SkPoint& p1, const SkPoint& p2) {
-        this->quadTo(p1.fX, p1.fY, p2.fX, p2.fY);
+    SkPath& quadTo(const SkPoint& p1, const SkPoint& p2) {
+        return this->quadTo(p1.fX, p1.fY, p2.fX, p2.fY);
     }
 
     /** Adds quad from last point towards vector (dx1, dy1), to vector (dx2, dy2).
@@ -651,7 +653,7 @@
         @param dx2  offset from last point to quad end on x-axis
         @param dy2  offset from last point to quad end on y-axis
     */
-    void rQuadTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2);
+    SkPath& rQuadTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2);
 
     /** Adds conic from last point towards (x1, y1), to (x2, y2), weighted by w.
         If SkPath is empty, or last SkPath::Verb is kClose_Verb, last point is set to (0, 0)
@@ -674,8 +676,8 @@
         @param y2  end SkPoint of conic in y
         @param w   weight of added conic
     */
-    void conicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
-                 SkScalar w);
+    SkPath& conicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
+                    SkScalar w);
 
     /** Adds conic from last point towards SkPoint p1, to SkPoint p2, weighted by w.
         If SkPath is empty, or last SkPath::Verb is kClose_Verb, last point is set to (0, 0)
@@ -696,8 +698,8 @@
         @param p2  end SkPoint of added conic
         @param w   weight of added conic
     */
-    void conicTo(const SkPoint& p1, const SkPoint& p2, SkScalar w) {
-        this->conicTo(p1.fX, p1.fY, p2.fX, p2.fY, w);
+    SkPath& conicTo(const SkPoint& p1, const SkPoint& p2, SkScalar w) {
+        return this->conicTo(p1.fX, p1.fY, p2.fX, p2.fY, w);
     }
 
     /** Adds conic from last point towards vector (dx1, dy1), to vector (dx2, dy2),
@@ -724,8 +726,8 @@
         @param dy2  offset from last point to conic end on y-axis
         @param w    weight of added conic
     */
-    void rConicTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2,
-                  SkScalar w);
+    SkPath& rConicTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2,
+                     SkScalar w);
 
     /** Adds cubic from last point towards (x1, y1), then towards (x2, y2), ending at
         (x3, y3). If SkPath is empty, or last SkPath::Verb is kClose_Verb, last point is set to
@@ -742,8 +744,8 @@
         @param x3  end SkPoint of cubic in x
         @param y3  end SkPoint of cubic in y
     */
-    void cubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
-                 SkScalar x3, SkScalar y3);
+    SkPath& cubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
+                    SkScalar x3, SkScalar y3);
 
     /** Adds cubic from last point towards SkPoint p1, then towards SkPoint p2, ending at
         SkPoint p3. If SkPath is empty, or last SkPath::Verb is kClose_Verb, last point is set to
@@ -757,8 +759,8 @@
         @param p2  second control SkPoint of cubic
         @param p3  end SkPoint of cubic
     */
-    void cubicTo(const SkPoint& p1, const SkPoint& p2, const SkPoint& p3) {
-        this->cubicTo(p1.fX, p1.fY, p2.fX, p2.fY, p3.fX, p3.fY);
+    SkPath& cubicTo(const SkPoint& p1, const SkPoint& p2, const SkPoint& p3) {
+        return this->cubicTo(p1.fX, p1.fY, p2.fX, p2.fY, p3.fX, p3.fY);
     }
 
     /** Adds cubic from last point towards vector (dx1, dy1), then towards
@@ -780,8 +782,8 @@
         @param x3  offset from last point to cubic end on x-axis
         @param y3  offset from last point to cubic end on y-axis
     */
-    void rCubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
-                  SkScalar x3, SkScalar y3);
+    SkPath& rCubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
+                     SkScalar x3, SkScalar y3);
 
     /** Appends arc to SkPath. Arc added is part of ellipse
         bounded by oval, from startAngle through sweepAngle. Both startAngle and
@@ -797,7 +799,7 @@
         @param sweepAngle   sweep, in degrees. Positive is clockwise; treated modulo 360
         @param forceMoveTo  true to start a new contour with arc
     */
-    void arcTo(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle, bool forceMoveTo);
+    SkPath& arcTo(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle, bool forceMoveTo);
 
     /** Appends arc to SkPath, after appending line if needed. Arc is implemented by conic
         weighted to describe part of circle. Arc is contained by tangent from
@@ -810,7 +812,7 @@
         @param y2      y-axis value end of second tangent
         @param radius  distance from arc to circle center
     */
-    void arcTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar radius);
+    SkPath& arcTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar radius);
 
     /** Appends arc to SkPath, after appending line if needed. Arc is implemented by conic
         weighted to describe part of circle. Arc is contained by tangent from
@@ -830,8 +832,8 @@
         @param p2      end of second tangent
         @param radius  distance from arc to circle center
     */
-    void arcTo(const SkPoint p1, const SkPoint p2, SkScalar radius) {
-        this->arcTo(p1.fX, p1.fY, p2.fX, p2.fY, radius);
+    SkPath& arcTo(const SkPoint p1, const SkPoint p2, SkScalar radius) {
+        return this->arcTo(p1.fX, p1.fY, p2.fX, p2.fY, radius);
     }
 
     /** \enum SkPath::ArcSize
@@ -866,8 +868,8 @@
         @param x            end of arc
         @param y            end of arc
     */
-    void arcTo(SkScalar rx, SkScalar ry, SkScalar xAxisRotate, ArcSize largeArc,
-               Direction sweep, SkScalar x, SkScalar y);
+    SkPath& arcTo(SkScalar rx, SkScalar ry, SkScalar xAxisRotate, ArcSize largeArc,
+                  Direction sweep, SkScalar x, SkScalar y);
 
     /** Appends arc to SkPath. Arc is implemented by one or more conic weighted to describe part of oval
         with radii (r.fX, r.fY) rotated by xAxisRotate degrees. Arc curves from last SkPath SkPoint to
@@ -889,9 +891,9 @@
         @param sweep        chooses clockwise or counterclockwise arc
         @param xy           end of arc
     */
-    void arcTo(const SkPoint r, SkScalar xAxisRotate, ArcSize largeArc, Direction sweep,
+    SkPath& arcTo(const SkPoint r, SkScalar xAxisRotate, ArcSize largeArc, Direction sweep,
                const SkPoint xy) {
-        this->arcTo(r.fX, r.fY, xAxisRotate, largeArc, sweep, xy.fX, xy.fY);
+        return this->arcTo(r.fX, r.fY, xAxisRotate, largeArc, sweep, xy.fX, xy.fY);
     }
 
     /** Appends arc to SkPath, relative to last SkPath SkPoint. Arc is implemented by one or
@@ -919,8 +921,8 @@
         @param dx           x-axis offset end of arc from last SkPath SkPoint
         @param dy           y-axis offset end of arc from last SkPath SkPoint
     */
-    void rArcTo(SkScalar rx, SkScalar ry, SkScalar xAxisRotate, ArcSize largeArc,
-                Direction sweep, SkScalar dx, SkScalar dy);
+    SkPath& rArcTo(SkScalar rx, SkScalar ry, SkScalar xAxisRotate, ArcSize largeArc,
+                   Direction sweep, SkScalar dx, SkScalar dy);
 
     /** Appends kClose_Verb to SkPath. A closed contour connects the first and last SkPoint
         with line, forming a continuous loop. Open and closed contour draw the same
@@ -930,7 +932,7 @@
 
         close() has no effect if SkPath is empty or last SkPath SkPath::Verb is kClose_Verb.
     */
-    void close();
+    SkPath& close();
 
     /** Returns true if fill is inverted and SkPath with fill represents area outside
         of its geometric bounds.
@@ -1025,7 +1027,7 @@
         @param rect  SkRect to add as a closed contour
         @param dir   SkPath::Direction to wind added contour
     */
-    void addRect(const SkRect& rect, Direction dir = kCW_Direction);
+    SkPath& addRect(const SkRect& rect, Direction dir = kCW_Direction);
 
     /** Adds SkRect to SkPath, appending kMove_Verb, three kLine_Verb, and kClose_Verb.
         If dir is kCW_Direction, SkRect corners are added clockwise; if dir is
@@ -1036,7 +1038,7 @@
         @param dir    SkPath::Direction to wind added contour
         @param start  initial corner of SkRect to add
     */
-    void addRect(const SkRect& rect, Direction dir, unsigned start);
+    SkPath& addRect(const SkRect& rect, Direction dir, unsigned start);
 
     /** Adds SkRect (left, top, right, bottom) to SkPath,
         appending kMove_Verb, three kLine_Verb, and kClose_Verb,
@@ -1050,8 +1052,8 @@
         @param bottom  larger y-axis value of SkRect
         @param dir     SkPath::Direction to wind added contour
     */
-    void addRect(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom,
-                 Direction dir = kCW_Direction);
+    SkPath& addRect(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom,
+                    Direction dir = kCW_Direction);
 
     /** Adds oval to path, appending kMove_Verb, four kConic_Verb, and kClose_Verb.
         Oval is upright ellipse bounded by SkRect oval with radii equal to half oval width
@@ -1061,7 +1063,7 @@
         @param oval  bounds of ellipse added
         @param dir   SkPath::Direction to wind ellipse
     */
-    void addOval(const SkRect& oval, Direction dir = kCW_Direction);
+    SkPath& addOval(const SkRect& oval, Direction dir = kCW_Direction);
 
     /** Adds oval to SkPath, appending kMove_Verb, four kConic_Verb, and kClose_Verb.
         Oval is upright ellipse bounded by SkRect oval with radii equal to half oval width
@@ -1072,7 +1074,7 @@
         @param dir    SkPath::Direction to wind ellipse
         @param start  index of initial point of ellipse
     */
-    void addOval(const SkRect& oval, Direction dir, unsigned start);
+    SkPath& addOval(const SkRect& oval, Direction dir, unsigned start);
 
     /** Adds circle centered at (x, y) of size radius to SkPath, appending kMove_Verb,
         four kConic_Verb, and kClose_Verb. Circle begins at: (x + radius, y), continuing
@@ -1085,8 +1087,8 @@
         @param radius  distance from center to edge
         @param dir     SkPath::Direction to wind circle
     */
-    void addCircle(SkScalar x, SkScalar y, SkScalar radius,
-                   Direction dir = kCW_Direction);
+    SkPath& addCircle(SkScalar x, SkScalar y, SkScalar radius,
+                      Direction dir = kCW_Direction);
 
     /** Appends arc to SkPath, as the start of new contour. Arc added is part of ellipse
         bounded by oval, from startAngle through sweepAngle. Both startAngle and
@@ -1101,7 +1103,7 @@
         @param startAngle  starting angle of arc in degrees
         @param sweepAngle  sweep, in degrees. Positive is clockwise; treated modulo 360
     */
-    void addArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle);
+    SkPath& addArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle);
 
     /** Appends SkRRect to SkPath, creating a new closed contour. SkRRect has bounds
         equal to rect; each corner is 90 degrees of an ellipse with radii (rx, ry). If
@@ -1120,8 +1122,8 @@
         @param ry    y-axis radius of rounded corners on the SkRRect
         @param dir   SkPath::Direction to wind SkRRect
     */
-    void addRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry,
-                      Direction dir = kCW_Direction);
+    SkPath& addRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry,
+                         Direction dir = kCW_Direction);
 
     /** Appends SkRRect to SkPath, creating a new closed contour. SkRRect has bounds
         equal to rect; each corner is 90 degrees of an ellipse with radii from the
@@ -1131,8 +1133,8 @@
         @param radii  array of 8 SkScalar values, a radius pair for each corner
         @param dir    SkPath::Direction to wind SkRRect
     */
-    void addRoundRect(const SkRect& rect, const SkScalar radii[],
-                      Direction dir = kCW_Direction);
+    SkPath& addRoundRect(const SkRect& rect, const SkScalar radii[],
+                         Direction dir = kCW_Direction);
 
     /** Adds rrect to SkPath, creating a new closed contour. If
         dir is kCW_Direction, rrect starts at top-left of the lower-left corner and
@@ -1144,7 +1146,7 @@
         @param rrect  bounds and radii of rounded rectangle
         @param dir    SkPath::Direction to wind SkRRect
     */
-    void addRRect(const SkRRect& rrect, Direction dir = kCW_Direction);
+    SkPath& addRRect(const SkRRect& rrect, Direction dir = kCW_Direction);
 
     /** Adds rrect to SkPath, creating a new closed contour. If dir is kCW_Direction, rrect
         winds clockwise; if dir is kCCW_Direction, rrect winds counterclockwise.
@@ -1154,7 +1156,7 @@
         @param dir    SkPath::Direction to wind SkRRect
         @param start  index of initial point of SkRRect
     */
-    void addRRect(const SkRRect& rrect, Direction dir, unsigned start);
+    SkPath& addRRect(const SkRRect& rrect, Direction dir, unsigned start);
 
     /** Adds contour created from line array, adding (count - 1) line segments.
         Contour added starts at pts[0], then adds a line for every additional SkPoint
@@ -1168,7 +1170,11 @@
         @param count  length of SkPoint array
         @param close  true to add line connecting contour end and start
     */
-    void addPoly(const SkPoint pts[], int count, bool close);
+    SkPath& addPoly(const SkPoint pts[], int count, bool close);
+
+    SkPath& addPoly(const std::initializer_list<SkPoint>& list, bool close) {
+        return this->addPoly(list.begin(), SkToInt(list.size()), close);
+    }
 
     /** \enum SkPath::AddPathMode
         AddPathMode chooses how addPath() appends. Adding one SkPath to another can extend
@@ -1190,8 +1196,8 @@
         @param dy    offset added to src SkPoint array y-axis coordinates
         @param mode  kAppend_AddPathMode or kExtend_AddPathMode
     */
-    void addPath(const SkPath& src, SkScalar dx, SkScalar dy,
-                 AddPathMode mode = kAppend_AddPathMode);
+    SkPath& addPath(const SkPath& src, SkScalar dx, SkScalar dy,
+                    AddPathMode mode = kAppend_AddPathMode);
 
     /** Appends src to SkPath.
 
@@ -1202,10 +1208,10 @@
         @param src   SkPath verbs, SkPoint, and conic weights to add
         @param mode  kAppend_AddPathMode or kExtend_AddPathMode
     */
-    void addPath(const SkPath& src, AddPathMode mode = kAppend_AddPathMode) {
+    SkPath& addPath(const SkPath& src, AddPathMode mode = kAppend_AddPathMode) {
         SkMatrix m;
         m.reset();
-        this->addPath(src, m, mode);
+        return this->addPath(src, m, mode);
     }
 
     /** Appends src to SkPath, transformed by matrix. Transformed curves may have different
@@ -1219,14 +1225,15 @@
         @param matrix  transform applied to src
         @param mode    kAppend_AddPathMode or kExtend_AddPathMode
     */
-    void addPath(const SkPath& src, const SkMatrix& matrix, AddPathMode mode = kAppend_AddPathMode);
+    SkPath& addPath(const SkPath& src, const SkMatrix& matrix,
+                    AddPathMode mode = kAppend_AddPathMode);
 
     /** Appends src to SkPath, from back to front.
         Reversed src always appends a new contour to SkPath.
 
         @param src  SkPath verbs, SkPoint, and conic weights to add
     */
-    void reverseAddPath(const SkPath& src);
+    SkPath& reverseAddPath(const SkPath& src);
 
     /** Offsets SkPoint array by (dx, dy). Offset SkPath replaces dst.
         If dst is nullptr, SkPath is replaced by offset data.
@@ -1642,7 +1649,7 @@
         last point. If no moveTo() call has been made for this contour, the
         first point is automatically set to (0,0).
     */
-    void reversePathTo(const SkPath&);
+    SkPath& reversePathTo(const SkPath&);
 
     // called before we add points for lineTo, quadTo, cubicTo, checking to see
     // if we need to inject a leading moveTo first
diff --git a/src/core/SkPath.cpp b/src/core/SkPath.cpp
index 05d2ca8..d852cb6 100644
--- a/src/core/SkPath.cpp
+++ b/src/core/SkPath.cpp
@@ -364,18 +364,20 @@
     return genID;
 }
 
-void SkPath::reset() {
+SkPath& SkPath::reset() {
     SkDEBUGCODE(this->validate();)
 
     fPathRef.reset(SkPathRef::CreateEmpty());
     this->resetFields();
+    return *this;
 }
 
-void SkPath::rewind() {
+SkPath& SkPath::rewind() {
     SkDEBUGCODE(this->validate();)
 
     SkPathRef::Rewind(&fPathRef);
     this->resetFields();
+    return *this;
 }
 
 bool SkPath::isLastContourClosed() const {
@@ -746,7 +748,7 @@
     SkDEBUGCODE(this->validate();)
 }
 
-void SkPath::moveTo(SkScalar x, SkScalar y) {
+SkPath& SkPath::moveTo(SkScalar x, SkScalar y) {
     SkDEBUGCODE(this->validate();)
 
     SkPathRef::Editor ed(&fPathRef);
@@ -757,12 +759,13 @@
     ed.growForVerb(kMove_Verb)->set(x, y);
 
     DIRTY_AFTER_EDIT;
+    return *this;
 }
 
-void SkPath::rMoveTo(SkScalar x, SkScalar y) {
+SkPath& SkPath::rMoveTo(SkScalar x, SkScalar y) {
     SkPoint pt;
     this->getLastPt(&pt);
-    this->moveTo(pt.fX + x, pt.fY + y);
+    return this->moveTo(pt.fX + x, pt.fY + y);
 }
 
 void SkPath::injectMoveToIfNeeded() {
@@ -779,7 +782,7 @@
     }
 }
 
-void SkPath::lineTo(SkScalar x, SkScalar y) {
+SkPath& SkPath::lineTo(SkScalar x, SkScalar y) {
     SkDEBUGCODE(this->validate();)
 
     this->injectMoveToIfNeeded();
@@ -788,16 +791,17 @@
     ed.growForVerb(kLine_Verb)->set(x, y);
 
     DIRTY_AFTER_EDIT;
+    return *this;
 }
 
-void SkPath::rLineTo(SkScalar x, SkScalar y) {
+SkPath& SkPath::rLineTo(SkScalar x, SkScalar y) {
     this->injectMoveToIfNeeded();  // This can change the result of this->getLastPt().
     SkPoint pt;
     this->getLastPt(&pt);
-    this->lineTo(pt.fX + x, pt.fY + y);
+    return this->lineTo(pt.fX + x, pt.fY + y);
 }
 
-void SkPath::quadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2) {
+SkPath& SkPath::quadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2) {
     SkDEBUGCODE(this->validate();)
 
     this->injectMoveToIfNeeded();
@@ -808,17 +812,18 @@
     pts[1].set(x2, y2);
 
     DIRTY_AFTER_EDIT;
+    return *this;
 }
 
-void SkPath::rQuadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2) {
+SkPath& SkPath::rQuadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2) {
     this->injectMoveToIfNeeded();  // This can change the result of this->getLastPt().
     SkPoint pt;
     this->getLastPt(&pt);
-    this->quadTo(pt.fX + x1, pt.fY + y1, pt.fX + x2, pt.fY + y2);
+    return this->quadTo(pt.fX + x1, pt.fY + y1, pt.fX + x2, pt.fY + y2);
 }
 
-void SkPath::conicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
-                     SkScalar w) {
+SkPath& SkPath::conicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
+                        SkScalar w) {
     // check for <= 0 or NaN with this test
     if (!(w > 0)) {
         this->lineTo(x2, y2);
@@ -839,18 +844,19 @@
 
         DIRTY_AFTER_EDIT;
     }
+    return *this;
 }
 
-void SkPath::rConicTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2,
-                      SkScalar w) {
+SkPath& SkPath::rConicTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2,
+                         SkScalar w) {
     this->injectMoveToIfNeeded();  // This can change the result of this->getLastPt().
     SkPoint pt;
     this->getLastPt(&pt);
-    this->conicTo(pt.fX + dx1, pt.fY + dy1, pt.fX + dx2, pt.fY + dy2, w);
+    return this->conicTo(pt.fX + dx1, pt.fY + dy1, pt.fX + dx2, pt.fY + dy2, w);
 }
 
-void SkPath::cubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
-                     SkScalar x3, SkScalar y3) {
+SkPath& SkPath::cubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
+                        SkScalar x3, SkScalar y3) {
     SkDEBUGCODE(this->validate();)
 
     this->injectMoveToIfNeeded();
@@ -862,18 +868,19 @@
     pts[2].set(x3, y3);
 
     DIRTY_AFTER_EDIT;
+    return *this;
 }
 
-void SkPath::rCubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
-                      SkScalar x3, SkScalar y3) {
+SkPath& SkPath::rCubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
+                         SkScalar x3, SkScalar y3) {
     this->injectMoveToIfNeeded();  // This can change the result of this->getLastPt().
     SkPoint pt;
     this->getLastPt(&pt);
-    this->cubicTo(pt.fX + x1, pt.fY + y1, pt.fX + x2, pt.fY + y2,
-                  pt.fX + x3, pt.fY + y3);
+    return this->cubicTo(pt.fX + x1, pt.fY + y1, pt.fX + x2, pt.fY + y2,
+                         pt.fX + x3, pt.fY + y3);
 }
 
-void SkPath::close() {
+SkPath& SkPath::close() {
     SkDEBUGCODE(this->validate();)
 
     int count = fPathRef->countVerbs();
@@ -905,6 +912,7 @@
 #else
     fLastMoveToIndex ^= ~fLastMoveToIndex >> (8 * sizeof(fLastMoveToIndex) - 1);
 #endif
+    return *this;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -991,16 +999,16 @@
     SkASSERT(SkPath::kCW_Direction == dir || SkPath::kCCW_Direction == dir);
 }
 
-void SkPath::addRect(const SkRect& rect, Direction dir) {
-    this->addRect(rect, dir, 0);
+SkPath& SkPath::addRect(const SkRect& rect, Direction dir) {
+    return this->addRect(rect, dir, 0);
 }
 
-void SkPath::addRect(SkScalar left, SkScalar top, SkScalar right,
+SkPath& SkPath::addRect(SkScalar left, SkScalar top, SkScalar right,
                      SkScalar bottom, Direction dir) {
-    this->addRect(SkRect::MakeLTRB(left, top, right, bottom), dir, 0);
+    return this->addRect(SkRect::MakeLTRB(left, top, right, bottom), dir, 0);
 }
 
-void SkPath::addRect(const SkRect &rect, Direction dir, unsigned startIndex) {
+SkPath& SkPath::addRect(const SkRect &rect, Direction dir, unsigned startIndex) {
     assert_known_direction(dir);
     fFirstDirection = this->hasOnlyMoveTos() ?
         (SkPathPriv::FirstDirection)dir : SkPathPriv::kUnknown_FirstDirection;
@@ -1021,12 +1029,13 @@
     this->close();
 
     SkASSERT(this->countVerbs() == initialVerbCount + kVerbs);
+    return *this;
 }
 
-void SkPath::addPoly(const SkPoint pts[], int count, bool close) {
+SkPath& SkPath::addPoly(const SkPoint pts[], int count, bool close) {
     SkDEBUGCODE(this->validate();)
     if (count <= 0) {
-        return;
+        return *this;
     }
 
     fLastMoveToIndex = fPathRef->countPoints();
@@ -1047,6 +1056,7 @@
 
     DIRTY_AFTER_EDIT;
     SkDEBUGCODE(this->validate();)
+    return *this;
 }
 
 #include "SkGeometry.h"
@@ -1122,76 +1132,77 @@
     return count;
 }
 
-void SkPath::addRoundRect(const SkRect& rect, const SkScalar radii[],
+SkPath& SkPath::addRoundRect(const SkRect& rect, const SkScalar radii[],
                           Direction dir) {
     SkRRect rrect;
     rrect.setRectRadii(rect, (const SkVector*) radii);
-    this->addRRect(rrect, dir);
+    return this->addRRect(rrect, dir);
 }
 
-void SkPath::addRRect(const SkRRect& rrect, Direction dir) {
+SkPath& SkPath::addRRect(const SkRRect& rrect, Direction dir) {
     // legacy start indices: 6 (CW) and 7(CCW)
-    this->addRRect(rrect, dir, dir == kCW_Direction ? 6 : 7);
+    return this->addRRect(rrect, dir, dir == kCW_Direction ? 6 : 7);
 }
 
-void SkPath::addRRect(const SkRRect &rrect, Direction dir, unsigned startIndex) {
-        assert_known_direction(dir);
+SkPath& SkPath::addRRect(const SkRRect &rrect, Direction dir, unsigned startIndex) {
+    assert_known_direction(dir);
 
-        bool isRRect = hasOnlyMoveTos();
-        const SkRect& bounds = rrect.getBounds();
+    bool isRRect = hasOnlyMoveTos();
+    const SkRect& bounds = rrect.getBounds();
 
-        if (rrect.isRect() || rrect.isEmpty()) {
-            // degenerate(rect) => radii points are collapsing
-            this->addRect(bounds, dir, (startIndex + 1) / 2);
-        } else if (rrect.isOval()) {
-            // degenerate(oval) => line points are collapsing
-            this->addOval(bounds, dir, startIndex / 2);
-        } else {
-            fFirstDirection = this->hasOnlyMoveTos() ?
-                                (SkPathPriv::FirstDirection)dir : SkPathPriv::kUnknown_FirstDirection;
+    if (rrect.isRect() || rrect.isEmpty()) {
+        // degenerate(rect) => radii points are collapsing
+        this->addRect(bounds, dir, (startIndex + 1) / 2);
+    } else if (rrect.isOval()) {
+        // degenerate(oval) => line points are collapsing
+        this->addOval(bounds, dir, startIndex / 2);
+    } else {
+        fFirstDirection = this->hasOnlyMoveTos() ?
+                            (SkPathPriv::FirstDirection)dir : SkPathPriv::kUnknown_FirstDirection;
 
-            SkAutoPathBoundsUpdate apbu(this, bounds);
-            SkAutoDisableDirectionCheck addc(this);
+        SkAutoPathBoundsUpdate apbu(this, bounds);
+        SkAutoDisableDirectionCheck addc(this);
 
-            // we start with a conic on odd indices when moving CW vs. even indices when moving CCW
-            const bool startsWithConic = ((startIndex & 1) == (dir == kCW_Direction));
-            const SkScalar weight = SK_ScalarRoot2Over2;
+        // we start with a conic on odd indices when moving CW vs. even indices when moving CCW
+        const bool startsWithConic = ((startIndex & 1) == (dir == kCW_Direction));
+        const SkScalar weight = SK_ScalarRoot2Over2;
 
-            SkDEBUGCODE(int initialVerbCount = this->countVerbs());
-            const int kVerbs = startsWithConic
-                ? 9   // moveTo + 4x conicTo + 3x lineTo + close
-                : 10; // moveTo + 4x lineTo + 4x conicTo + close
-            this->incReserve(kVerbs);
+        SkDEBUGCODE(int initialVerbCount = this->countVerbs());
+        const int kVerbs = startsWithConic
+            ? 9   // moveTo + 4x conicTo + 3x lineTo + close
+            : 10; // moveTo + 4x lineTo + 4x conicTo + close
+        this->incReserve(kVerbs);
 
-            RRectPointIterator rrectIter(rrect, dir, startIndex);
-            // Corner iterator indices follow the collapsed radii model,
-            // adjusted such that the start pt is "behind" the radii start pt.
-            const unsigned rectStartIndex = startIndex / 2 + (dir == kCW_Direction ? 0 : 1);
-            RectPointIterator rectIter(bounds, dir, rectStartIndex);
+        RRectPointIterator rrectIter(rrect, dir, startIndex);
+        // Corner iterator indices follow the collapsed radii model,
+        // adjusted such that the start pt is "behind" the radii start pt.
+        const unsigned rectStartIndex = startIndex / 2 + (dir == kCW_Direction ? 0 : 1);
+        RectPointIterator rectIter(bounds, dir, rectStartIndex);
 
-            this->moveTo(rrectIter.current());
-            if (startsWithConic) {
-                for (unsigned i = 0; i < 3; ++i) {
-                    this->conicTo(rectIter.next(), rrectIter.next(), weight);
-                    this->lineTo(rrectIter.next());
-                }
+        this->moveTo(rrectIter.current());
+        if (startsWithConic) {
+            for (unsigned i = 0; i < 3; ++i) {
                 this->conicTo(rectIter.next(), rrectIter.next(), weight);
-                // final lineTo handled by close().
-            } else {
-                for (unsigned i = 0; i < 4; ++i) {
-                    this->lineTo(rrectIter.next());
-                    this->conicTo(rectIter.next(), rrectIter.next(), weight);
-                }
+                this->lineTo(rrectIter.next());
             }
-            this->close();
-
-            SkPathRef::Editor ed(&fPathRef);
-            ed.setIsRRect(isRRect, dir, startIndex % 8);
-
-            SkASSERT(this->countVerbs() == initialVerbCount + kVerbs);
+            this->conicTo(rectIter.next(), rrectIter.next(), weight);
+            // final lineTo handled by close().
+        } else {
+            for (unsigned i = 0; i < 4; ++i) {
+                this->lineTo(rrectIter.next());
+                this->conicTo(rectIter.next(), rrectIter.next(), weight);
+            }
         }
+        this->close();
 
-        SkDEBUGCODE(fPathRef->validate();)
+        SkPathRef::Editor ed(&fPathRef);
+        ed.setIsRRect(isRRect, dir, startIndex % 8);
+
+        SkASSERT(this->countVerbs() == initialVerbCount + kVerbs);
+    }
+
+    SkDEBUGCODE(fPathRef->validate();)
+    return *this;
 }
 
 bool SkPath::hasOnlyMoveTos() const {
@@ -1224,25 +1235,25 @@
     return true;
 }
 
-void SkPath::addRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry,
-                          Direction dir) {
+SkPath& SkPath::addRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry,
+                             Direction dir) {
     assert_known_direction(dir);
 
     if (rx < 0 || ry < 0) {
-        return;
+        return *this;
     }
 
     SkRRect rrect;
     rrect.setRectXY(rect, rx, ry);
-    this->addRRect(rrect, dir);
+    return this->addRRect(rrect, dir);
 }
 
-void SkPath::addOval(const SkRect& oval, Direction dir) {
+SkPath& SkPath::addOval(const SkRect& oval, Direction dir) {
     // legacy start index: 1
-    this->addOval(oval, dir, 1);
+    return this->addOval(oval, dir, 1);
 }
 
-void SkPath::addOval(const SkRect &oval, Direction dir, unsigned startPointIndex) {
+SkPath& SkPath::addOval(const SkRect &oval, Direction dir, unsigned startPointIndex) {
     assert_known_direction(dir);
 
     /* If addOval() is called after previous moveTo(),
@@ -1281,18 +1292,20 @@
     SkPathRef::Editor ed(&fPathRef);
 
     ed.setIsOval(isOval, kCCW_Direction == dir, startPointIndex % 4);
+    return *this;
 }
 
-void SkPath::addCircle(SkScalar x, SkScalar y, SkScalar r, Direction dir) {
+SkPath& SkPath::addCircle(SkScalar x, SkScalar y, SkScalar r, Direction dir) {
     if (r > 0) {
         this->addOval(SkRect::MakeLTRB(x - r, y - r, x + r, y + r), dir);
     }
+    return *this;
 }
 
-void SkPath::arcTo(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle,
-                   bool forceMoveTo) {
+SkPath& SkPath::arcTo(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle,
+                      bool forceMoveTo) {
     if (oval.width() < 0 || oval.height() < 0) {
-        return;
+        return *this;
     }
 
     if (fPathRef->countVerbs() == 0) {
@@ -1301,8 +1314,7 @@
 
     SkPoint lonePt;
     if (arc_is_lone_point(oval, startAngle, sweepAngle, &lonePt)) {
-        forceMoveTo ? this->moveTo(lonePt) : this->lineTo(lonePt);
-        return;
+        return forceMoveTo ? this->moveTo(lonePt) : this->lineTo(lonePt);
     }
 
     SkVector startV, stopV;
@@ -1340,7 +1352,7 @@
         singlePt.set(oval.centerX() + radiusX * sk_float_cos(endAngle),
             oval.centerY() + radiusY * sk_float_sin(endAngle));
         addPt(singlePt);
-        return;
+        return *this;
     }
 
     SkConic conics[SkConic::kMaxConicsForArc];
@@ -1355,6 +1367,7 @@
     } else {
         addPt(singlePt);
     }
+    return *this;
 }
 
 // This converts the SVG arc to conics.
@@ -1363,8 +1376,8 @@
 // See also SVG implementation notes:
 // http://www.w3.org/TR/SVG/implnote.html#ArcConversionEndpointToCenter
 // Note that arcSweep bool value is flipped from the original implementation.
-void SkPath::arcTo(SkScalar rx, SkScalar ry, SkScalar angle, SkPath::ArcSize arcLarge,
-                   SkPath::Direction arcSweep, SkScalar x, SkScalar y) {
+SkPath& SkPath::arcTo(SkScalar rx, SkScalar ry, SkScalar angle, SkPath::ArcSize arcLarge,
+                      SkPath::Direction arcSweep, SkScalar x, SkScalar y) {
     this->injectMoveToIfNeeded();
     SkPoint srcPts[2];
     this->getLastPt(&srcPts[0]);
@@ -1372,15 +1385,13 @@
     // joining the endpoints.
     // http://www.w3.org/TR/SVG/implnote.html#ArcOutOfRangeParameters
     if (!rx || !ry) {
-        this->lineTo(x, y);
-        return;
+        return this->lineTo(x, y);
     }
     // If the current point and target point for the arc are identical, it should be treated as a
     // zero length path. This ensures continuity in animations.
     srcPts[1].set(x, y);
     if (srcPts[0] == srcPts[1]) {
-        this->lineTo(x, y);
-        return;
+        return this->lineTo(x, y);
     }
     rx = SkScalarAbs(rx);
     ry = SkScalarAbs(ry);
@@ -1446,7 +1457,7 @@
     SkScalar thetaWidth = thetaArc / segments;
     SkScalar t = SkScalarTan(0.5f * thetaWidth);
     if (!SkScalarIsFinite(t)) {
-        return;
+        return *this;
     }
     SkScalar startTheta = theta1;
     SkScalar w = SkScalarSqrt(SK_ScalarHalf + SkScalarCos(thetaWidth) * SK_ScalarHalf);
@@ -1484,18 +1495,20 @@
         this->conicTo(mapped[0], mapped[1], w);
         startTheta = endTheta;
     }
+    return *this;
 }
 
-void SkPath::rArcTo(SkScalar rx, SkScalar ry, SkScalar xAxisRotate, SkPath::ArcSize largeArc,
-                    SkPath::Direction sweep, SkScalar dx, SkScalar dy) {
+SkPath& SkPath::rArcTo(SkScalar rx, SkScalar ry, SkScalar xAxisRotate, SkPath::ArcSize largeArc,
+                       SkPath::Direction sweep, SkScalar dx, SkScalar dy) {
     SkPoint currentPoint;
     this->getLastPt(&currentPoint);
-    this->arcTo(rx, ry, xAxisRotate, largeArc, sweep, currentPoint.fX + dx, currentPoint.fY + dy);
+    return this->arcTo(rx, ry, xAxisRotate, largeArc, sweep,
+                       currentPoint.fX + dx, currentPoint.fY + dy);
 }
 
-void SkPath::addArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle) {
+SkPath& SkPath::addArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle) {
     if (oval.isEmpty() || 0 == sweepAngle) {
-        return;
+        return *this;
     }
 
     const SkScalar kFullCircleAngle = SkIntToScalar(360);
@@ -1510,22 +1523,20 @@
             // Index 1 is at startAngle == 0.
             SkScalar startIndex = std::fmod(startOver90I + 1.f, 4.f);
             startIndex = startIndex < 0 ? startIndex + 4.f : startIndex;
-            this->addOval(oval, sweepAngle > 0 ? kCW_Direction : kCCW_Direction,
-                          (unsigned) startIndex);
-            return;
+            return this->addOval(oval, sweepAngle > 0 ? kCW_Direction : kCCW_Direction,
+                                 (unsigned) startIndex);
         }
     }
-    this->arcTo(oval, startAngle, sweepAngle, true);
+    return this->arcTo(oval, startAngle, sweepAngle, true);
 }
 
 /*
     Need to handle the case when the angle is sharp, and our computed end-points
     for the arc go behind pt1 and/or p2...
 */
-void SkPath::arcTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar radius) {
+SkPath& SkPath::arcTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar radius) {
     if (radius == 0) {
-        this->lineTo(x1, y1);
-        return;
+        return this->lineTo(x1, y1);
     }
 
     SkVector before, after;
@@ -1544,8 +1555,7 @@
     SkScalar sinh = SkPoint::CrossProduct(before, after);
 
     if (SkScalarNearlyZero(sinh)) {   // angle is too tight
-        this->lineTo(x1, y1);
-        return;
+        return this->lineTo(x1, y1);
     }
 
     SkScalar dist = SkScalarAbs(radius * (1 - cosh) / sinh);
@@ -1555,19 +1565,19 @@
     after.setLength(dist);
     this->lineTo(xx, yy);
     SkScalar weight = SkScalarSqrt(SK_ScalarHalf + cosh * SK_ScalarHalf);
-    this->conicTo(x1, y1, x1 + after.fX, y1 + after.fY, weight);
+    return this->conicTo(x1, y1, x1 + after.fX, y1 + after.fY, weight);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 
-void SkPath::addPath(const SkPath& path, SkScalar dx, SkScalar dy, AddPathMode mode) {
+SkPath& SkPath::addPath(const SkPath& path, SkScalar dx, SkScalar dy, AddPathMode mode) {
     SkMatrix matrix;
 
     matrix.setTranslate(dx, dy);
-    this->addPath(path, matrix, mode);
+    return this->addPath(path, matrix, mode);
 }
 
-void SkPath::addPath(const SkPath& path, const SkMatrix& matrix, AddPathMode mode) {
+SkPath& SkPath::addPath(const SkPath& path, const SkMatrix& matrix, AddPathMode mode) {
     SkPathRef::Editor(&fPathRef, path.countVerbs(), path.countPoints());
 
     RawIter iter(path);
@@ -1611,6 +1621,7 @@
         }
         firstVerb = false;
     }
+    return *this;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -1631,10 +1642,10 @@
 }
 
 // ignore the last point of the 1st contour
-void SkPath::reversePathTo(const SkPath& path) {
+SkPath& SkPath::reversePathTo(const SkPath& path) {
     const uint8_t* verbs = path.fPathRef->verbsMemBegin(); // points at the last verb
     if (!verbs) {  // empty path returns nullptr
-        return;
+        return *this;
     }
     const uint8_t* verbsEnd = path.fPathRef->verbs() - 1; // points just past the first verb
     SkASSERT(verbsEnd[0] == kMove_Verb);
@@ -1647,7 +1658,7 @@
         switch (v) {
             case kMove_Verb:
                 // if the path has multiple contours, stop after reversing the last
-                return;
+                return *this;
             case kLine_Verb:
                 this->lineTo(pts[0]);
                 break;
@@ -1668,9 +1679,10 @@
                 break;
         }
     }
+    return *this;
 }
 
-void SkPath::reverseAddPath(const SkPath& src) {
+SkPath& SkPath::reverseAddPath(const SkPath& src) {
     SkPathRef::Editor ed(&fPathRef, src.fPathRef->countPoints(), src.fPathRef->countVerbs());
 
     const SkPoint* pts = src.fPathRef->pointsEnd();
@@ -1719,6 +1731,7 @@
                 SkDEBUGFAIL("unexpected verb");
         }
     }
+    return *this;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/tests/DrawPathTest.cpp b/tests/DrawPathTest.cpp
index 5a69214..53ebad1 100644
--- a/tests/DrawPathTest.cpp
+++ b/tests/DrawPathTest.cpp
@@ -121,12 +121,9 @@
     bm.allocN32Pixels(2700, 30*1024);
     SkCanvas canvas(bm);
 
-    SkPath path;
-    path.moveTo(2762, 20);
-    path.quadTo(11, 21702, 10, 21706);
     SkPaint paint;
     paint.setAntiAlias(true);
-    canvas.drawPath(path, paint);
+    canvas.drawPath(SkPath().moveTo(2762, 20).quadTo(11, 21702, 10, 21706), paint);
 }
 
 // Need to exercise drawing an inverse-path whose bounds intersect the clip,
diff --git a/tests/EmptyPathTest.cpp b/tests/EmptyPathTest.cpp
index 5b857a0..78f1816 100644
--- a/tests/EmptyPathTest.cpp
+++ b/tests/EmptyPathTest.cpp
@@ -106,11 +106,11 @@
 
 static void make_empty(SkPath*) {}
 static void make_M(SkPath* path) { path->moveTo(CX, CY); }
-static void make_MM(SkPath* path) { path->moveTo(CX, CY); path->moveTo(CX, CY); }
-static void make_MZM(SkPath* path) { path->moveTo(CX, CY); path->close(); path->moveTo(CX, CY); }
-static void make_L(SkPath* path) { path->moveTo(CX, CY); path->lineTo(CX, CY); }
-static void make_Q(SkPath* path) { path->moveTo(CX, CY); path->quadTo(CX, CY, CX, CY); }
-static void make_C(SkPath* path) { path->moveTo(CX, CY); path->cubicTo(CX, CY, CX, CY, CX, CY); }
+static void make_MM(SkPath* path) { path->moveTo(CX, CY).moveTo(CX, CY); }
+static void make_MZM(SkPath* path) { path->moveTo(CX, CY).close().moveTo(CX, CY); }
+static void make_L(SkPath* path) { path->moveTo(CX, CY).lineTo(CX, CY); }
+static void make_Q(SkPath* path) { path->moveTo(CX, CY).quadTo(CX, CY, CX, CY); }
+static void make_C(SkPath* path) { path->moveTo(CX, CY).cubicTo(CX, CY, CX, CY, CX, CY); }
 
 /*  Two invariants are tested: How does an empty/degenerate path draw?
  *  - if the path is drawn inverse, it should draw everywhere
diff --git a/tests/FillPathTest.cpp b/tests/FillPathTest.cpp
index 1f14d4f..01489d7 100644
--- a/tests/FillPathTest.cpp
+++ b/tests/FillPathTest.cpp
@@ -37,11 +37,11 @@
     int width  = 200;
     int expected_lines = 5;
     clip.set(0, height - expected_lines, width, height);
-    path.moveTo(0.0f, 0.0f);
-    path.quadTo(SkIntToScalar(width/2), SkIntToScalar(height),
-              SkIntToScalar(width), 0.0f);
-    path.close();
-    path.setFillType(SkPath::kInverseWinding_FillType);
+    path.moveTo(0.0f, 0.0f)
+        .quadTo(SkIntToScalar(width/2), SkIntToScalar(height),
+              SkIntToScalar(width), 0.0f)
+        .close()
+        .setFillType(SkPath::kInverseWinding_FillType);
     SkScan::FillPath(path, clip, &blitter);
 
     REPORTER_ASSERT(reporter, blitter.m_blitCount == expected_lines);