pathops coincidence and security rewrite

Most changes stem from working on an examples bracketed
by #if DEBUG_UNDER_DEVELOPMENT  // tiger
These exposed many problems with coincident curves,
as well as errors throughout the code.

Fixing these errors also fixed a number of fuzzer-inspired
bug reports.

* Line/Curve Intersections
Check to see if the end of the line nearly intersects
the curve. This was a FIXME in the old code.

* Performance
Use a central chunk allocator.
Plumb the allocator into the global variable state
so that it can be shared. (Note that 'SkGlobalState'
is allocated on the stack and is visible to children
functions but not other threads.)

* Refactor
Let SkOpAngle grow up from a structure to a class.
Let SkCoincidentSpans grow up from a structure to a class.
Rename enum Alias to AliasMatch.

* Coincidence Rewrite
Add more debugging to coincidence detection.
Parallel debugging routines have read-only logic to report
the current coincidence state so that steps through the
logic can expose whether things got better or worse.

More functions can error-out and cause the pathops
engine to non-destructively exit.

* Accuracy
Remove code that adjusted point locations. Instead,
offset the curve part so that sorted curves all use
the same origin.
Reduce the size (and influence) of magic numbers.

* Testing
The debug suite with verify and the full release suite
./out/Debug/pathops_unittest -v -V
./out/Release/pathops_unittest -v -V -x
expose one error. That error is captured as cubics_d3.
This error exists in the checked in code as well.

BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003

BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2128633003

Review-Url: https://codereview.chromium.org/2128633003
diff --git a/tests/PathOpsAngleTest.cpp b/tests/PathOpsAngleTest.cpp
index 6389c30..fa8d314 100644
--- a/tests/PathOpsAngleTest.cpp
+++ b/tests/PathOpsAngleTest.cpp
@@ -194,6 +194,10 @@
         return lh.after(&rh);
     }
 
+    static int AllOnOneSide(SkOpAngle& lh, SkOpAngle& rh) {
+        return lh.allOnOneSide(&rh);
+    }
+
     static int ConvexHullOverlaps(SkOpAngle& lh, SkOpAngle& rh) {
         return lh.convexHullOverlaps(&rh);
     }
@@ -235,7 +239,7 @@
 DEF_TEST(PathOpsAngleCircle, reporter) {
     SkChunkAlloc allocator(4096);
     SkOpContourHead contour;
-    SkOpGlobalState state(nullptr, &contour  SkDEBUGPARAMS(false) SkDEBUGPARAMS(nullptr));
+    SkOpGlobalState state(&contour, &allocator  SkDEBUGPARAMS(false) SkDEBUGPARAMS(nullptr));
     contour.init(&state, false, false);
     for (int index = 0; index < circleDataSetSize; ++index) {
         CircleData& data = circleDataSet[index];
@@ -244,20 +248,20 @@
         }
         switch (data.fPtCount) {
             case 2:
-                contour.addLine(data.fShortPts, &allocator);
+                contour.addLine(data.fShortPts);
                 break;
             case 3:
-                contour.addQuad(data.fShortPts, &allocator);
+                contour.addQuad(data.fShortPts);
                 break;
             case 4:
-                contour.addCubic(data.fShortPts, &allocator);
+                contour.addCubic(data.fShortPts);
                 break;
         }
     }
     SkOpSegment* first = contour.first();
-    first->debugAddAngle(0, 1, &allocator);
+    first->debugAddAngle(0, 1);
     SkOpSegment* next = first->next();
-    next->debugAddAngle(0, 1, &allocator);
+    next->debugAddAngle(0, 1);
     PathOpsAngleTester::Orderable(*first->debugLastAngle(), *next->debugLastAngle());
 }
 
@@ -427,7 +431,7 @@
 DEF_TEST(PathOpsAngleAfter, reporter) {
     SkChunkAlloc allocator(4096);
     SkOpContourHead contour;
-    SkOpGlobalState state(nullptr, &contour  SkDEBUGPARAMS(false) SkDEBUGPARAMS(nullptr));
+    SkOpGlobalState state(&contour, &allocator  SkDEBUGPARAMS(false) SkDEBUGPARAMS(nullptr));
     contour.init(&state, false, false);
     for (int index = intersectDataSetsSize - 1; index >= 0; --index) {
         IntersectData* dataArray = intersectDataSets[index];
@@ -443,22 +447,22 @@
                 }
                 switch (data.fPtCount) {
                     case 2: {
-                        contour.addLine(temp, &allocator);
+                        contour.addLine(temp);
                         } break;
                     case 3: {
-                        contour.addQuad(temp, &allocator);
+                        contour.addQuad(temp);
                         } break;
                     case 4: {
-                        contour.addCubic(temp, &allocator);
+                        contour.addCubic(temp);
                         } break;
                 }
             }
             SkOpSegment* seg1 = contour.first();
-            seg1->debugAddAngle(dataArray[index2 + 0].fTStart, dataArray[index2 + 0].fTEnd, &allocator);
+            seg1->debugAddAngle(dataArray[index2 + 0].fTStart, dataArray[index2 + 0].fTEnd);
             SkOpSegment* seg2 = seg1->next();
-            seg2->debugAddAngle(dataArray[index2 + 1].fTStart, dataArray[index2 + 1].fTEnd, &allocator);
+            seg2->debugAddAngle(dataArray[index2 + 1].fTStart, dataArray[index2 + 1].fTEnd);
             SkOpSegment* seg3 = seg2->next();
-            seg3->debugAddAngle(dataArray[index2 + 2].fTStart, dataArray[index2 + 2].fTEnd, &allocator);
+            seg3->debugAddAngle(dataArray[index2 + 2].fTStart, dataArray[index2 + 2].fTEnd);
             SkOpAngle& angle1 = *seg1->debugLastAngle();
             SkOpAngle& angle2 = *seg2->debugLastAngle();
             SkOpAngle& angle3 = *seg3->debugLastAngle();
@@ -472,12 +476,12 @@
     }
 }
 
-void SkOpSegment::debugAddAngle(double startT, double endT, SkChunkAlloc* allocator) {
+void SkOpSegment::debugAddAngle(double startT, double endT) {
     SkOpPtT* startPtT = startT == 0 ? fHead.ptT() : startT == 1 ? fTail.ptT()
-            : this->addT(startT, kNoAlias, allocator);
+            : this->addT(startT, kNoAliasMatch, nullptr);
     SkOpPtT* endPtT = endT == 0 ? fHead.ptT() : endT == 1 ? fTail.ptT()
-            : this->addT(endT, kNoAlias, allocator);
-    SkOpAngle* angle = SkOpTAllocator<SkOpAngle>::Allocate(allocator);
+            : this->addT(endT, kNoAliasMatch, nullptr);
+    SkOpAngle* angle = SkOpTAllocator<SkOpAngle>::Allocate(this->globalState()->allocator());
     SkOpSpanBase* startSpan = &fHead;
     while (startSpan->ptT() != startPtT) {
         startSpan = startSpan->upCast()->next();
@@ -495,3 +499,29 @@
         startSpan->setFromAngle(angle);
     }
 }
+
+DEF_TEST(PathOpsAngleAllOnOneSide, reporter) {
+    SkChunkAlloc allocator(4096);
+    SkOpContourHead contour;
+    SkOpGlobalState state(&contour, &allocator  SkDEBUGPARAMS(false) SkDEBUGPARAMS(nullptr));
+    contour.init(&state, false, false);
+    SkPoint conicPts[3] = {{494.37100219726562f, 224.66200256347656f},
+        {494.37360910682298f, 224.6729026561527f},
+        {494.37600708007813f, 224.68400573730469f}};
+    SkPoint linePts[2] = {{494.371002f, 224.662003f}, {494.375000f, 224.675995f}};
+    for (int i = 10; i >= 0; --i) {
+        SkPoint modLinePts[2] = { linePts[0], linePts[1] };
+        modLinePts[1].fX += i * .1f;
+        contour.addLine(modLinePts);
+        contour.addQuad(conicPts);
+   //     contour.addConic(conicPts, 0.999935746f, &allocator);
+        SkOpSegment* first = contour.first();
+        first->debugAddAngle(0, 1);
+        SkOpSegment* next = first->next();
+        next->debugAddAngle(0, 1);
+        /* int result = */
+            PathOpsAngleTester::AllOnOneSide(*first->debugLastAngle(), *next->debugLastAngle());
+  //      SkDebugf("i=%d result=%d\n", i , result);
+  //      SkDebugf("");
+    }
+}