Enabling the canvas bit to turn the clip stack into a flat replace exposed around 100 failures when testing the 800K skp set generated from the top 1M web sites.

This fixes all but one of those failures.

Major changes include:
- Replace angle indices with angle pointers. This was motivated by the need to add angles later but not renumber existing angles.
- Aggressive segment chase. When the winding is known on a segment, more aggressively passing that winding to adjacent segments allows fragmented data sets to succeed.
- Line segments with ends nearly the same are treated as coincident first.
- Transfer partial coincidence by observing that if segment A is partially coincident to B and C then B and C may be partially coincident.

TBR=reed

Author: caryclark@google.com

Review URL: https://codereview.chromium.org/272153002
diff --git a/src/pathops/SkDCubicIntersection.cpp b/src/pathops/SkDCubicIntersection.cpp
index dd51195..1c237d9 100644
--- a/src/pathops/SkDCubicIntersection.cpp
+++ b/src/pathops/SkDCubicIntersection.cpp
@@ -303,15 +303,39 @@
             continue;
         }
         if (swap) {
-            insert(testT, impTs[0][index], tmpLine[0]);
+            cubicInsert(testT, impTs[0][index], tmpLine[0], cubic2, cubic1);
         } else {
-            insert(impTs[0][index], testT, tmpLine[0]);
+            cubicInsert(impTs[0][index], testT, tmpLine[0], cubic1, cubic2);
         }
         return true;
     }
     return false;
 }
 
+
+void SkIntersections::cubicInsert(double one, double two, const SkDPoint& pt,
+        const SkDCubic& cubic1, const SkDCubic& cubic2) {
+    for (int index = 0; index < fUsed; ++index) {
+        if (fT[0][index] == one) {
+            double oldTwo = fT[1][index];
+            if (oldTwo == two) {
+                return;
+            }
+            SkDPoint mid = cubic2.ptAtT((oldTwo + two) / 2);
+            if (mid.approximatelyEqual(fPt[index])) {
+                return;
+            }
+        }
+        if (fT[1][index] == two) {
+            SkDPoint mid = cubic1.ptAtT((fT[0][index] + two) / 2);
+            if (mid.approximatelyEqual(fPt[index])) {
+                return;
+            }
+        }
+    }
+    insert(one, two, pt);
+}
+
 void SkIntersections::cubicNearEnd(const SkDCubic& cubic1, bool start, const SkDCubic& cubic2,
                          const SkDRect& bounds2) {
     SkDLine line;
@@ -371,11 +395,15 @@
         double tMin2 = SkTMax(tVals[tIdx] - LINE_FRACTION, 0.0);
         double tMax2 = SkTMin(tVals[tLast] + LINE_FRACTION, 1.0);
         int lastUsed = used();
-        ::intersect(cubic1, tMin1, tMax1, cubic2, tMin2, tMax2, 1, *this);
+        if (start ? tMax1 < tMin2 : tMax2 < tMin1) {
+            ::intersect(cubic1, tMin1, tMax1, cubic2, tMin2, tMax2, 1, *this);
+        }
         if (lastUsed == used()) {
             tMin2 = SkTMax(tVals[tIdx] - (1.0 / SkDCubic::gPrecisionUnit), 0.0);
             tMax2 = SkTMin(tVals[tLast] + (1.0 / SkDCubic::gPrecisionUnit), 1.0);
-            ::intersect(cubic1, tMin1, tMax1, cubic2, tMin2, tMax2, 1, *this);
+            if (start ? tMax1 < tMin2 : tMax2 < tMin1) {
+                ::intersect(cubic1, tMin1, tMax1, cubic2, tMin2, tMax2, 1, *this);
+            }
         }
         tIdx = tLast + 1;
     } while (tIdx < tVals.count());
@@ -421,6 +449,9 @@
             }
             double adj = endPt[oppTest]->fX - origX;
             double opp = endPt[oppTest]->fY - origY;
+            if (adj == 0 && opp == 0) {  // if the other point equals the test point, ignore it
+                continue;
+            }
             double sign = (c1[oddMan].fY - origY) * adj - (c1[oddMan].fX - origX) * opp;
             if (approximately_zero(sign)) {
                 goto tryNextHalfPlane;
@@ -531,7 +562,7 @@
     if (compCount) {
         int exactCount = used();
         if (exactCount == 0) {
-            set(i);
+            *this = i;
         } else {
             // at least one is exact or near, and at least one was computed. Eliminate duplicates
             for (int exIdx = 0; exIdx < exactCount; ++exIdx) {