GrTessellator: collinear edges during sanitize.

When three collinear edges occur during the sanitize_contours() pass,
their vertices may not yet have been discovered to be coincident.  So
we must do the vertex comparison by point, rather than by pointer.

Bug: 860655
Change-Id: I89dc7526905bb5473206661348fee431371731a0
Reviewed-on: https://skia-review.googlesource.com/141523
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Stephen White <senorblanco@chromium.org>
diff --git a/src/gpu/GrTessellator.cpp b/src/gpu/GrTessellator.cpp
index 3424ee3..dd87999 100644
--- a/src/gpu/GrTessellator.cpp
+++ b/src/gpu/GrTessellator.cpp
@@ -1053,16 +1053,18 @@
 
 void merge_collinear_edges(Edge* edge, EdgeList* activeEdges, Vertex** current, Comparator& c) {
     for (;;) {
-        if (edge->fPrevEdgeAbove && (edge->fTop == edge->fPrevEdgeAbove->fTop ||
+        const SkPoint& top = edge->fTop->fPoint;
+        const SkPoint& bottom = edge->fBottom->fPoint;
+        if (edge->fPrevEdgeAbove && (edge->fPrevEdgeAbove->fTop->fPoint == top ||
                                      !edge->fPrevEdgeAbove->isLeftOf(edge->fTop))) {
             merge_edges_above(edge->fPrevEdgeAbove, edge, activeEdges, current, c);
-        } else if (edge->fNextEdgeAbove && (edge->fTop == edge->fNextEdgeAbove->fTop ||
+        } else if (edge->fNextEdgeAbove && (edge->fNextEdgeAbove->fTop->fPoint == top ||
                                             !edge->isLeftOf(edge->fNextEdgeAbove->fTop))) {
             merge_edges_above(edge->fNextEdgeAbove, edge, activeEdges, current, c);
-        } else if (edge->fPrevEdgeBelow && (edge->fBottom == edge->fPrevEdgeBelow->fBottom ||
+        } else if (edge->fPrevEdgeBelow && (edge->fPrevEdgeBelow->fBottom->fPoint == bottom ||
                                      !edge->fPrevEdgeBelow->isLeftOf(edge->fBottom))) {
             merge_edges_below(edge->fPrevEdgeBelow, edge, activeEdges, current, c);
-        } else if (edge->fNextEdgeBelow && (edge->fBottom == edge->fNextEdgeBelow->fBottom ||
+        } else if (edge->fNextEdgeBelow && (edge->fNextEdgeBelow->fBottom->fPoint == bottom ||
                                             !edge->isLeftOf(edge->fNextEdgeBelow->fBottom))) {
             merge_edges_below(edge->fNextEdgeBelow, edge, activeEdges, current, c);
         } else {
diff --git a/tests/TessellatingPathRendererTests.cpp b/tests/TessellatingPathRendererTests.cpp
index 4b3b321..ae20171 100644
--- a/tests/TessellatingPathRendererTests.cpp
+++ b/tests/TessellatingPathRendererTests.cpp
@@ -600,6 +600,22 @@
     return path;
 }
 
+// Reduction from crbug.com/860655. Cause is three collinear edges discovered during
+// sanitize_contours pass, before the vertices have been found coincident.
+static SkPath create_path_42() {
+    SkPath path;
+    path.moveTo(   32572426382475264,    -3053391034974208);
+    path.lineTo(           521289856,            -48865776);
+    path.lineTo(           130322464,            -12215873);
+    path.moveTo(   32572426382475264,    -3053391034974208);
+    path.lineTo(           521289856,            -48865776);
+    path.lineTo(           130322464,            -12215873);
+    path.moveTo(   32572426382475264,    -3053391034974208);
+    path.lineTo(   32114477642022912,    -3010462031544320);
+    path.lineTo(   32111784697528320,    -3010209702215680);
+    return path;
+}
+
 static std::unique_ptr<GrFragmentProcessor> create_linear_gradient_processor(GrContext* ctx) {
 
     SkPoint pts[2] = { {0, 0}, {1, 1} };
@@ -701,4 +717,5 @@
     test_path(ctx, rtc.get(), create_path_39());
     test_path(ctx, rtc.get(), create_path_40());
     test_path(ctx, rtc.get(), create_path_41(), SkMatrix(), GrAAType::kCoverage);
+    test_path(ctx, rtc.get(), create_path_42());
 }