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/src/pathops/SkPathOpsCurve.h b/src/pathops/SkPathOpsCurve.h
index 97e20be..dc9cec9 100644
--- a/src/pathops/SkPathOpsCurve.h
+++ b/src/pathops/SkPathOpsCurve.h
@@ -64,14 +64,17 @@
         return fCubic[n];
     }
 
-    SkDPoint conicTop(const SkPoint curve[3], SkScalar curveWeight, 
+    SkDPoint conicTop(const SkPoint curve[3], SkScalar curveWeight,
                       double s, double e, double* topT);
     SkDPoint cubicTop(const SkPoint curve[4], SkScalar , double s, double e, double* topT);
+    void dump() const;
     void dumpID(int ) const;
     SkDPoint lineTop(const SkPoint[2], SkScalar , double , double , double* topT);
+    double nearPoint(SkPath::Verb verb, const SkDPoint& xy, const SkDPoint& opp) const;
+    void offset(SkPath::Verb verb, const SkDVector& );
     SkDPoint quadTop(const SkPoint curve[3], SkScalar , double s, double e, double* topT);
 
-    void setConicBounds(const SkPoint curve[3], SkScalar curveWeight, 
+    void setConicBounds(const SkPoint curve[3], SkScalar curveWeight,
                         double s, double e, SkPathOpsBounds* );
     void setCubicBounds(const SkPoint curve[4], SkScalar ,
                         double s, double e, SkPathOpsBounds* );
@@ -115,6 +118,30 @@
     dcubic_xy_at_t
 };
 
+static SkDPoint ddline_xy_at_t(const SkDCurve& c, double t) {
+    return c.fLine.ptAtT(t);
+}
+
+static SkDPoint ddquad_xy_at_t(const SkDCurve& c, double t) {
+    return c.fQuad.ptAtT(t);
+}
+
+static SkDPoint ddconic_xy_at_t(const SkDCurve& c, double t) {
+    return c.fConic.ptAtT(t);
+}
+
+static SkDPoint ddcubic_xy_at_t(const SkDCurve& c, double t) {
+    return c.fCubic.ptAtT(t);
+}
+
+static SkDPoint (* const CurveDDPointAtT[])(const SkDCurve& , double ) = {
+    nullptr,
+    ddline_xy_at_t,
+    ddquad_xy_at_t,
+    ddconic_xy_at_t,
+    ddcubic_xy_at_t
+};
+
 static SkPoint fline_xy_at_t(const SkPoint a[2], SkScalar weight, double t) {
     return dline_xy_at_t(a, weight, t).asSkPoint();
 }
@@ -171,6 +198,30 @@
     dcubic_dxdy_at_t
 };
 
+static SkDVector ddline_dxdy_at_t(const SkDCurve& c, double ) {
+    return c.fLine.fPts[1] - c.fLine.fPts[0];
+}
+
+static SkDVector ddquad_dxdy_at_t(const SkDCurve& c, double t) {
+    return c.fQuad.dxdyAtT(t);
+}
+
+static SkDVector ddconic_dxdy_at_t(const SkDCurve& c, double t) {
+    return c.fConic.dxdyAtT(t);
+}
+
+static SkDVector ddcubic_dxdy_at_t(const SkDCurve& c, double t) {
+    return c.fCubic.dxdyAtT(t);
+}
+
+static SkDVector (* const CurveDDSlopeAtT[])(const SkDCurve& , double ) = {
+    nullptr,
+    ddline_dxdy_at_t,
+    ddquad_dxdy_at_t,
+    ddconic_dxdy_at_t,
+    ddcubic_dxdy_at_t
+};
+
 static SkVector fline_dxdy_at_t(const SkPoint a[2], SkScalar , double ) {
     return a[1] - a[0];
 }
@@ -269,6 +320,30 @@
     cubic_intersect_ray
 };
 
+static void dline_intersect_ray(const SkDCurve& c, const SkDLine& ray,  SkIntersections* i) {
+    i->intersectRay(c.fLine, ray);
+}
+
+static void dquad_intersect_ray(const SkDCurve& c, const SkDLine& ray, SkIntersections* i) {
+    i->intersectRay(c.fQuad, ray);
+}
+
+static void dconic_intersect_ray(const SkDCurve& c, const SkDLine& ray, SkIntersections* i) {
+    i->intersectRay(c.fConic, ray);
+}
+
+static void dcubic_intersect_ray(const SkDCurve& c, const SkDLine& ray, SkIntersections* i) {
+    i->intersectRay(c.fCubic, ray);
+}
+
+static void (* const CurveDIntersectRay[])(const SkDCurve& , const SkDLine& , SkIntersections* ) = {
+    nullptr,
+    dline_intersect_ray,
+    dquad_intersect_ray,
+    dconic_intersect_ray,
+    dcubic_intersect_ray
+};
+
 static int line_intercept_h(const SkPoint a[2], SkScalar , SkScalar y, double* roots) {
     SkDLine line;
     roots[0] = SkIntersections::HorizontalIntercept(line.set(a), y);