Start to migrate pathops to builder

Change-Id: Ie95aeaa9154ba924db0fa400d50c9b80f5ac30c2
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/1056517
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Mike Reed <mike@reedtribe.org>
Reviewed-by: Florin Malita <fmalita@google.com>
diff --git a/src/core/SkPathPriv.h b/src/core/SkPathPriv.h
index e8c12cd..804bc1f 100644
--- a/src/core/SkPathPriv.h
+++ b/src/core/SkPathPriv.h
@@ -408,6 +408,10 @@
         builder->privateReverseAddPath(reverseMe);
     }
 
+    static void ReversePathTo(SkPathBuilder* builder, const SkPath& reverseMe) {
+        builder->privateReversePathTo(reverseMe);
+    }
+
     static std::optional<SkPoint> GetPoint(const SkPathBuilder& builder, int index) {
         if ((unsigned)index < (unsigned)builder.fPts.size()) {
             return builder.fPts.at(index);
diff --git a/src/pathops/SkOpBuilder.cpp b/src/pathops/SkOpBuilder.cpp
index 3fea4e9..f9c72ed 100644
--- a/src/pathops/SkOpBuilder.cpp
+++ b/src/pathops/SkOpBuilder.cpp
@@ -105,8 +105,8 @@
         path->setFillType(fillType);
         return true;
     }
-    SkPath empty;
-    SkPathWriter woundPath(empty);
+
+    SkPathWriter woundPath(fillType);
     SkOpContour* test = &contourHead;
     do {
         if (!test->count()) {
@@ -118,8 +118,7 @@
             test->toPath(&woundPath);
         }
     } while ((test = test->next()));
-    *path = *woundPath.nativePath();
-    path->setFillType(fillType);
+    *path = woundPath.nativePath();
     return true;
 }
 
diff --git a/src/pathops/SkOpEdgeBuilder.h b/src/pathops/SkOpEdgeBuilder.h
index 7c01756..1b5e1bb 100644
--- a/src/pathops/SkOpEdgeBuilder.h
+++ b/src/pathops/SkOpEdgeBuilder.h
@@ -20,16 +20,6 @@
 
 class SkOpEdgeBuilder {
 public:
-    SkOpEdgeBuilder(const SkPathWriter& path, SkOpContourHead* contours2,
-            SkOpGlobalState* globalState)
-        : fGlobalState(globalState)
-        , fPath(path.nativePath())
-        , fContourBuilder(contours2)
-        , fContoursHead(contours2)
-        , fAllowOpenContours(true) {
-        init();
-    }
-
     SkOpEdgeBuilder(const SkPath& path, SkOpContourHead* contours2, SkOpGlobalState* globalState)
         : fGlobalState(globalState)
         , fPath(&path)
diff --git a/src/pathops/SkPathOpsOp.cpp b/src/pathops/SkPathOpsOp.cpp
index ad7665f..4389248 100644
--- a/src/pathops/SkPathOpsOp.cpp
+++ b/src/pathops/SkPathOpsOp.cpp
@@ -358,15 +358,12 @@
     contourList->dumpSegments("aligned");
 #endif
     // construct closed contours
-    SkPath original = *result;
-    result->reset();
-    result->setFillType(fillType);
-    SkPathWriter wrapper(*result);
+    SkPathWriter wrapper(fillType);
     if (!bridgeOp(contourList, op, xorMask, xorOpMask, &wrapper)) {
-        *result = original;
         return false;
     }
     wrapper.assemble();  // if some edges could not be resolved, assemble remaining
+    *result = wrapper.nativePath();
 #if DEBUG_T_SECT_LOOP_COUNT
     static SkMutex& debugWorstLoop = *(new SkMutex);
     {
diff --git a/src/pathops/SkPathOpsSimplify.cpp b/src/pathops/SkPathOpsSimplify.cpp
index ae45680..a78bf06 100644
--- a/src/pathops/SkPathOpsSimplify.cpp
+++ b/src/pathops/SkPathOpsSimplify.cpp
@@ -266,14 +266,13 @@
     contour.dumpSegments("aligned");
 #endif
     // construct closed contours
-    result->reset();
-    result->setFillType(fillType);
-    SkPathWriter wrapper(*result);
+    SkPathWriter wrapper(fillType);
     if (builder.xorMask() == kWinding_PathOpsMask ? !bridgeWinding(contourList, &wrapper)
             : !bridgeXor(contourList, &wrapper)) {
         return false;
     }
     wrapper.assemble();  // if some edges could not be resolved, assemble remaining
+    *result = wrapper.nativePath();
     return true;
 }
 
diff --git a/src/pathops/SkPathWriter.cpp b/src/pathops/SkPathWriter.cpp
index 1f88fd4..4c6a550 100644
--- a/src/pathops/SkPathWriter.cpp
+++ b/src/pathops/SkPathWriter.cpp
@@ -9,6 +9,7 @@
 #include "include/core/SkTypes.h"
 #include "include/private/base/SkMath.h"
 #include "src/base/SkTSort.h"
+#include "src/core/SkPathPriv.h"
 #include "src/pathops/SkOpSegment.h"
 #include "src/pathops/SkOpSpan.h"
 #include "src/pathops/SkPathOpsDebug.h"
@@ -16,10 +17,7 @@
 
 using namespace skia_private;
 
-// wrap path to keep track of whether the contour is initialized and non-empty
-SkPathWriter::SkPathWriter(SkPath& path)
-    : fPathPtr(&path)
-{
+SkPathWriter::SkPathWriter(SkPathFillType ft) : fBuilder(ft) {
     init();
 }
 
@@ -32,7 +30,7 @@
     SkDebugf("path.close();\n");
 #endif
     fCurrent.close();
-    fPathPtr->addPath(fCurrent);
+    fBuilder.addPath(fCurrent);
     fCurrent.reset();
     init();
 }
@@ -228,8 +226,7 @@
     // lengthen any partial contour adjacent to a simple segment
     for (int pIndex = 0; pIndex < endCount; pIndex++) {
         SkOpPtT* opPtT = const_cast<SkOpPtT*>(runs[pIndex]);
-        SkPath p;
-        SkPathWriter partWriter(p);
+        SkPathWriter partWriter(SkPathFillType::kDefault);
         do {
             if (!zero_or_one(opPtT->fT)) {
                 break;
@@ -356,16 +353,17 @@
         do {
             const SkPath& contour = fPartials[rIndex];
             if (!first) {
-                SkPoint prior, next;
-                if (!fPathPtr->getLastPt(&prior)) {
+                auto prior = fBuilder.getLastPt();
+                if (!prior) {
                     return;
                 }
+                SkPoint next;
                 if (forward) {
                     next = contour.getPoint(0);
                 } else {
                     SkAssertResult(contour.getLastPt(&next));
                 }
-                if (prior != next) {
+                if (*prior != next) {
                     /* TODO: if there is a gap between open path written so far and path to come,
                        connect by following segments from one to the other, rather than introducing
                        a diagonal to connect the two.
@@ -373,11 +371,11 @@
                 }
             }
             if (forward) {
-                fPathPtr->addPath(contour,
+                fBuilder.addPath(contour,
                         first ? SkPath::kAppend_AddPathMode : SkPath::kExtend_AddPathMode);
             } else {
                 SkASSERT(!first);
-                fPathPtr->reversePathTo(contour);
+                SkPathPriv::ReversePathTo(&fBuilder, contour);
             }
             if (first) {
                 first = false;
@@ -388,7 +386,7 @@
                 sIndex == ((rIndex != eIndex) ^ forward ? eIndex : ~eIndex));
 #endif
             if (sIndex == ((rIndex != eIndex) ^ forward ? eIndex : ~eIndex)) {
-                fPathPtr->close();
+                fBuilder.close();
                 break;
             }
             if (forward) {
diff --git a/src/pathops/SkPathWriter.h b/src/pathops/SkPathWriter.h
index 6b6626f..2760796 100644
--- a/src/pathops/SkPathWriter.h
+++ b/src/pathops/SkPathWriter.h
@@ -8,6 +8,7 @@
 #define SkPathWriter_DEFINED
 
 #include "include/core/SkPath.h"
+#include "include/core/SkPathBuilder.h"
 #include "include/core/SkPoint.h"
 #include "include/core/SkScalar.h"
 #include "include/private/base/SkTArray.h"
@@ -21,7 +22,7 @@
 
 class SkPathWriter {
 public:
-    SkPathWriter(SkPath& path);
+    SkPathWriter(SkPathFillType);
     void assemble();
     void conicTo(const SkPoint& pt1, const SkOpPtT* pt2, SkScalar weight);
     void cubicTo(const SkPoint& pt1, const SkPoint& pt2, const SkOpPtT* pt3);
@@ -31,7 +32,7 @@
     bool hasMove() const { return !fFirstPtT; }
     void init();
     bool isClosed() const;
-    const SkPath* nativePath() const { return fPathPtr; }
+    SkPath nativePath() { return fBuilder.detach(); }
     void quadTo(const SkPoint& pt1, const SkOpPtT* pt2);
 
 private:
@@ -45,10 +46,10 @@
     bool someAssemblyRequired();
     SkPoint update(const SkOpPtT* pt);
 
+    SkPathBuilder fBuilder;
     SkPath fCurrent;  // contour under construction
     skia_private::TArray<SkPath> fPartials;   // contours with mismatched starts and ends
     SkTDArray<const SkOpPtT*> fEndPtTs;  // possible pt values for partial starts and ends
-    SkPath* fPathPtr;  // closed contours are written here
     const SkOpPtT* fDefer[2];  // [0] deferred move, [1] deferred line
     const SkOpPtT* fFirstPtT;  // first in current contour
 };