path ops work in progress

path ops work in progress

BUG=

Review URL: https://codereview.chromium.org/21359002

git-svn-id: http://skia.googlecode.com/svn/trunk@11291 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/tests/PathOpsAngleTest.cpp b/tests/PathOpsAngleTest.cpp
index f7507a0..7f5e456 100644
--- a/tests/PathOpsAngleTest.cpp
+++ b/tests/PathOpsAngleTest.cpp
@@ -233,7 +233,7 @@
     { TEST_ENTRY(set3), {0, 0}},
     { TEST_ENTRY(set2), {0, 0}},
 //    { TEST_ENTRY(set1a), {3.70370364f,3.14814806f} },
-    { TEST_ENTRY(set1), {0, 0}},
+//    { TEST_ENTRY(set1), {0, 0}},
 };
 
 #undef TEST_ENTRY
@@ -287,13 +287,13 @@
     }
     double tStart = set[idx].tStart;
     double tEnd = set[idx].tEnd;
-    seg->addT(NULL, start, tStart);
-    seg->addT(NULL, end, tEnd);
+    seg->addT(NULL, start, tStart, SkOpSpan::kPointIsExact);
+    seg->addT(NULL, end, tEnd, SkOpSpan::kPointIsExact);
     if (tStart != 0 && tEnd != 0) {
-        seg->addT(NULL, set[idx].ptData[0], 0);
+        seg->addT(NULL, set[idx].ptData[0], 0, SkOpSpan::kPointIsExact);
     }
     if (tStart != 1 && tEnd != 1) {
-        seg->addT(NULL, set[idx].ptData[set[idx].ptCount - 1], 1);
+        seg->addT(NULL, set[idx].ptData[set[idx].ptCount - 1], 1, SkOpSpan::kPointIsExact);
     }
     int tIndex = 0;
     ts[0] = 0;
diff --git a/tests/PathOpsCubicIntersectionTest.cpp b/tests/PathOpsCubicIntersectionTest.cpp
index 1cc037f..d04f2db 100644
--- a/tests/PathOpsCubicIntersectionTest.cpp
+++ b/tests/PathOpsCubicIntersectionTest.cpp
@@ -163,6 +163,9 @@
 const size_t testSetCount = SK_ARRAY_COUNT(testSet);
 
 static const SkDCubic newTestSet[] = {
+{{{134, 11414}, {131.990234375, 11414}, {130.32666015625, 11415.482421875}, {130.04275512695312, 11417.4130859375}}},
+{{{132, 11419}, {130.89543151855469, 11419}, {130, 11418.1044921875}, {130, 11417}}},
+
 {{{3, 4}, {1, 5}, {4, 3}, {6, 4}}},
 {{{3, 4}, {4, 6}, {4, 3}, {5, 1}}},
 
diff --git a/tests/PathOpsCubicLineIntersectionTest.cpp b/tests/PathOpsCubicLineIntersectionTest.cpp
index 866acb3..95eb621 100644
--- a/tests/PathOpsCubicLineIntersectionTest.cpp
+++ b/tests/PathOpsCubicLineIntersectionTest.cpp
@@ -15,6 +15,8 @@
     SkDCubic cubic;
     SkDLine line;
 } lineCubicTests[] = {
+    {{{{0,4}, {3,4}, {6,2}, {5,2}}},
+            {{{4,3}, {2,6}}}},
 #if 0
     {{{{258, 122}, {260.761414, 122}, { 263, 124.238579}, {263, 127}}},
             {{{259.82843, 125.17157}, {261.535522, 123.46447}}}},
diff --git a/tests/PathOpsExtendedTest.cpp b/tests/PathOpsExtendedTest.cpp
index b85644d..efee0fc 100644
--- a/tests/PathOpsExtendedTest.cpp
+++ b/tests/PathOpsExtendedTest.cpp
@@ -554,11 +554,12 @@
 }
 
 #if DEBUG_SHOW_TEST_NAME
-void DebugShowPath(const SkPath& a, const SkPath& b, SkPathOp shapeOp, const char* testName) {
-        ShowFunctionHeader(testName);
-        showPath(a, "path", true);
-        showPath(b, "pathB", true);
-        ShowOp(shapeOp, "path", "pathB");
+void SkPathOpsDebug::ShowPath(const SkPath& a, const SkPath& b, SkPathOp shapeOp,
+        const char* testName) {
+    ShowFunctionHeader(testName);
+    showPath(a, "path", true);
+    showPath(b, "pathB", true);
+    ShowOp(shapeOp, "path", "pathB");
 }
 #endif
 
@@ -571,7 +572,7 @@
         showOp(shapeOp);
         showPathData(b);
     } else {
-        DebugShowPath(a, b, shapeOp, testName);
+        SkPathOpsDebug::ShowPath(a, b, shapeOp, testName);
     }
 #endif
     SkPath out;
@@ -628,8 +629,8 @@
 
 int initializeTests(skiatest::Reporter* reporter, const char* test) {
 #ifdef SK_DEBUG
-    gDebugMaxWindSum = 4;
-    gDebugMaxWindValue = 4;
+    SkPathOpsDebug::gMaxWindSum = 4;
+    SkPathOpsDebug::gMaxWindValue = 4;
 #endif
     testName = test;
     size_t testNameSize = strlen(test);
diff --git a/tests/PathOpsLineIntersectionTest.cpp b/tests/PathOpsLineIntersectionTest.cpp
index ea3f7e0..ee15363 100644
--- a/tests/PathOpsLineIntersectionTest.cpp
+++ b/tests/PathOpsLineIntersectionTest.cpp
@@ -11,6 +11,8 @@
 
 // FIXME: add tests for intersecting, non-intersecting, degenerate, coincident
 static const SkDLine tests[][2] = {
+    {{{{90,230}, {160,60}}}, {{{60,120}, {260,120}}}},
+    {{{{90,230}, {160,60}}}, {{{181.176468,120}, {135.294128,120}}}},
     {{{{181.1764678955078125f, 120}, {186.3661956787109375f, 134.7042236328125f}}},
      {{{175.8309783935546875f, 141.5211334228515625f}, {187.8782806396484375f, 133.7258148193359375f}}}},
 #if 0  // FIXME: these fail because one line is too short and appears quasi-coincident
@@ -33,6 +35,9 @@
 static const size_t tests_count = SK_ARRAY_COUNT(tests);
 
 static const SkDLine noIntersect[][2] = {
+   {{{{(double) (2 - 1e-6f),2}, {(double) (2 - 1e-6f),4}}},
+    {{{2,1}, {2,3}}}},
+
     {{{{0, 0}, {1, 0}}}, {{{3, 0}, {2, 0}}}},
     {{{{0, 0}, {0, 0}}}, {{{1, 0}, {2, 0}}}},
     {{{{0, 1}, {0, 1}}}, {{{0, 3}, {0, 2}}}},
@@ -43,6 +48,12 @@
 static const size_t noIntersect_count = SK_ARRAY_COUNT(noIntersect);
 
 static const SkDLine coincidentTests[][2] = {
+   {{{{979.304871, 561}, {1036.69507, 291}}},
+    {{{985.681519, 531}, {982.159790, 547.568542}}}},
+
+   {{{{232.159805, 547.568542}, {235.681549, 531}}},
+    {{{286.695129,291}, {229.304855,561}}}},
+
     {{{{186.3661956787109375f, 134.7042236328125f}, {187.8782806396484375f, 133.7258148193359375f}}},
      {{{175.8309783935546875f, 141.5211334228515625f}, {187.8782806396484375f, 133.7258148193359375f}}}},
 
@@ -111,19 +122,11 @@
                               const SkDLine& line2) {
     SkASSERT(ValidLine(line1));
     SkASSERT(ValidLine(line2));
-    SkIntersections ts2;
-    int pts2 = ts2.intersect(line1, line2);
-    REPORTER_ASSERT(reporter, pts2 == 2);
-    REPORTER_ASSERT(reporter, pts2 == ts2.used());
-    check_results(reporter, line1, line2, ts2);
-#if 0
     SkIntersections ts;
     int pts = ts.intersect(line1, line2);
-    REPORTER_ASSERT(reporter, pts == pts2);
     REPORTER_ASSERT(reporter, pts == 2);
     REPORTER_ASSERT(reporter, pts == ts.used());
     check_results(reporter, line1, line2, ts);
-#endif
 }
 
 static void PathOpsLineIntersectionTest(skiatest::Reporter* reporter) {
@@ -154,9 +157,8 @@
 static void PathOpsLineIntersectionOneOffTest(skiatest::Reporter* reporter) {
     int index = 0;
     SkASSERT(index < (int) tests_count);
-    const SkDLine& line1 = tests[index][0];
-    const SkDLine& line2 = tests[index][1];
-    testOne(reporter, line1, line2);
+    testOne(reporter, tests[index][0], tests[index][1]);
+    testOne(reporter, tests[1][0], tests[1][1]);
 }
 
 static void PathOpsLineIntersectionOneCoincidentTest(skiatest::Reporter* reporter) {
diff --git a/tests/PathOpsOpTest.cpp b/tests/PathOpsOpTest.cpp
index e0a7cf5..dee99db 100644
--- a/tests/PathOpsOpTest.cpp
+++ b/tests/PathOpsOpTest.cpp
@@ -1987,6 +1987,149 @@
     testPathOp(reporter, path, pathB, kIntersect_PathOp);
 }
 
+static void issue1418b(skiatest::Reporter* reporter) {
+    SkPath path1;
+    path1.moveTo(0, 0);
+    path1.lineTo(1, 0);
+    path1.lineTo(1, 1);
+    path1.lineTo(0, 1);
+    path1.lineTo(0, 0);
+    path1.close();
+    path1.setFillType(SkPath::kWinding_FillType);
+    SkPath path2;
+    path2.moveTo(0.646446645f, -0.353553414f);
+    path2.quadTo(0.792893291f, -0.50000006f, 1.00000012f, -0.50000006f);
+    path2.quadTo(1.20710683f, -0.50000006f, 1.35355353f, -0.353553414f);
+    path2.quadTo(1.50000012f, -0.207106799f, 1.50000012f, 0);
+    path2.quadTo(1.50000012f, 0.207106799f, 1.35355353f, 0.353553414f);
+    path2.quadTo(1.20710683f, 0.50000006f, 1.00000012f, 0.50000006f);
+    path2.quadTo(0.792893291f, 0.50000006f, 0.646446645f, 0.353553414f);
+    path2.quadTo(0.50000006f, 0.207106799f, 0.50000006f, 0);
+    path2.quadTo(0.50000006f, -0.207106799f, 0.646446645f, -0.353553414f);
+    path2.close();
+    path2.moveTo(1.00000012f, 0.50000006f);
+    path2.lineTo(1.00000012f, 1.00000012f);
+    path2.lineTo(0.50000006f, 1.00000012f);
+    path2.quadTo(0.50000006f, 0.792893291f, 0.646446645f, 0.646446645f);
+    path2.quadTo(0.792893291f, 0.50000006f, 1.00000012f, 0.50000006f);
+    path2.close();
+    path2.setFillType(SkPath::kEvenOdd_FillType);
+    testPathOp(reporter, path1, path2, kIntersect_PathOp);
+}
+
+static void rectOp1i(skiatest::Reporter* reporter) {
+    SkPath path, pathB;
+    path.setFillType(SkPath::kWinding_FillType);
+    path.addRect(0, 0, 1, 1, SkPath::kCW_Direction);
+    path.addRect(2, 2, 4, 4, SkPath::kCW_Direction);
+    pathB.setFillType(SkPath::kWinding_FillType);
+    pathB.addRect(0, 0, 1, 1, SkPath::kCW_Direction);
+    pathB.addRect(0, 0, 2, 2, SkPath::kCW_Direction);
+    testPathOp(reporter, path, pathB, kIntersect_PathOp);
+}
+
+static void rectOp2i(skiatest::Reporter* reporter) {
+    SkPath path, pathB;
+    path.setFillType(SkPath::kEvenOdd_FillType);
+    path.addRect(0, 0, 1, 1, SkPath::kCW_Direction);
+    path.addRect(0, 0, 3, 3, SkPath::kCW_Direction);
+    pathB.setFillType(SkPath::kWinding_FillType);
+    pathB.addRect(0, 0, 2, 2, SkPath::kCW_Direction);
+    pathB.addRect(0, 0, 2, 2, SkPath::kCW_Direction);
+    testPathOp(reporter, path, pathB, kIntersect_PathOp);
+}
+
+static void rectOp3x(skiatest::Reporter* reporter) {
+    SkPath path, pathB;
+    path.setFillType(SkPath::kEvenOdd_FillType);
+    path.moveTo(0, 0);
+    path.lineTo(3, 0);
+    path.lineTo(3, 3);
+    path.lineTo(0, 3);
+    path.close();
+    path.moveTo(2, 2);
+    path.lineTo(3, 2);
+    path.lineTo(3, 3);
+    path.lineTo(2, 3);
+    path.close();
+    pathB.setFillType(SkPath::kWinding_FillType);
+    pathB.moveTo(1, 1);
+    pathB.lineTo(3, 1);
+    pathB.lineTo(3, 3);
+    pathB.lineTo(1, 3);
+    pathB.close();
+    pathB.moveTo(2, 2);
+    pathB.lineTo(3, 2);
+    pathB.lineTo(3, 3);
+    pathB.lineTo(2, 3);
+    pathB.close();
+    testPathOp(reporter, path, pathB, kXOR_PathOp);
+}
+
+#if 0
+static void issue1435(skiatest::Reporter* reporter) {
+    SkPath path1;
+    path1.moveTo(160, 60);
+    path1.lineTo(220, 230);
+    path1.lineTo(60, 120);
+    path1.lineTo(260, 120);
+    path1.lineTo(90, 230);
+    path1.lineTo(160, 60);
+    path1.close();
+    path1.setFillType(SkPath::kEvenOdd_FillType);
+
+
+    SkPath path2;
+    path2.moveTo(142.589081f, 102.283646f);
+    path2.quadTo(149.821579f, 100, 158, 100);
+    path2.quadTo(167.156921f, 100, 175.128036f, 102.862793f);
+    path2.lineTo(181.176468f, 120);
+    path2.lineTo(135.294128f, 120);
+    path2.lineTo(142.589081f, 102.283646f);
+    path2.close();
+    path2.moveTo(118.681946f, 160.343842f);
+    path2.lineTo(135.294128f, 120);
+    path2.lineTo(117.933762f, 120);
+    path2.quadTo(108, 132.942657f, 108, 150);
+    path2.quadTo(108, 151.54483f, 108.08149f, 153.05603f);
+    path2.lineTo(118.681946f, 160.343842f);
+    path2.close();
+    path2.moveTo(156.969696f, 186.666672f);
+    path2.lineTo(118.681946f, 160.343842f);
+    path2.lineTo(113.458946f, 173.028259f);
+    path2.quadTo(116.94117f, 179.651855f, 122.644661f, 185.355347f);
+    path2.quadTo(130.792465f, 193.503143f, 140.817978f, 197.117783f);
+    path2.lineTo(156.969696f, 186.666672f);
+    path2.close();
+    path2.moveTo(195.830978f, 161.521133f);
+    path2.lineTo(156.969696f, 186.666672f);
+    path2.lineTo(173.157288f, 197.795639f);
+    path2.quadTo(184.392426f, 194.318268f, 193.355347f, 185.355347f);
+    path2.quadTo(197.805817f, 180.904861f, 200.903809f, 175.894165f);
+    path2.lineTo(195.830978f, 161.521133f);
+    path2.close();
+    path2.moveTo(195.830978f, 161.521133f);
+    path2.lineTo(207.878281f, 153.725815f);
+    path2.quadTo(208, 151.888062f, 208, 150);
+    path2.quadTo(208, 132.942657f, 198.066238f, 120);
+    path2.lineTo(181.176468f, 120);
+    path2.lineTo(195.830978f, 161.521133f);
+    path2.close();
+    path2.setFillType(SkPath::kEvenOdd_FillType);
+    testPathOp(reporter, path1, path2, kIntersect_PathOp);
+}
+#endif
+
+#if 0
+static void bufferOverflow(skiatest::Reporter* reporter) {
+    SkPath path;
+    path.addRect(0,0, 300,170141183460469231731687303715884105728.);
+    SkPath pathB;
+    pathB.addRect(0,0, 300,16);
+    testPathOp(reporter, path, pathB, kUnion_PathOp);
+}
+#endif
+
 #if 0
 static void skpkkiste_to716(skiatest::Reporter* reporter) {
     SkPath path;
@@ -2013,10 +2156,145 @@
 }
 #endif
 
+static void loopEdge1(skiatest::Reporter* reporter) {
+    SkPath path;
+    path.setFillType(SkPath::kEvenOdd_FillType);
+    path.moveTo(0,0);
+    path.lineTo(3,0);
+    path.lineTo(3,2);
+    path.lineTo(1,2);
+    path.lineTo(1,1);
+    path.lineTo(2,1);
+    path.lineTo(2,3);
+    path.lineTo(0,3);
+    path.close();
+    SkPath pathB;
+    pathB.setFillType(SkPath::kEvenOdd_FillType);
+    pathB.moveTo(1,2);
+    pathB.lineTo(2,2);
+    pathB.lineTo(2,4);
+    pathB.lineTo(1,4);
+    pathB.close();
+    testPathOp(reporter, path, pathB, kIntersect_PathOp);
+}
+
+static void loopEdge2(skiatest::Reporter* reporter) {
+    SkPath path;
+    path.setFillType(SkPath::kEvenOdd_FillType);
+    path.moveTo(0,0);
+    path.lineTo(3,0);
+    path.lineTo(3,2);
+    path.lineTo(1,2);
+    path.lineTo(1,1);
+    path.lineTo(2,1);
+    path.lineTo(2,3);
+    path.lineTo(0,3);
+    path.close();
+    SkPath pathB;
+    pathB.setFillType(SkPath::kEvenOdd_FillType);
+    pathB.moveTo(1 - 1e-6f,2);
+    pathB.lineTo(2 - 1e-6f,2);
+    pathB.lineTo(2 - 1e-6f,4);
+    pathB.lineTo(1 - 1e-6f,4);
+    pathB.close();
+    testPathOp(reporter, path, pathB, kIntersect_PathOp);
+}
+
+static void cubicOp86i(skiatest::Reporter* reporter) {
+    SkPath path, pathB;
+    path.setFillType(SkPath::kWinding_FillType);
+    path.moveTo(0, 4);
+    path.cubicTo(3, 4, 6, 2, 5, 2);
+    path.close();
+    pathB.setFillType(SkPath::kEvenOdd_FillType);
+    pathB.moveTo(2, 6);
+    pathB.cubicTo(2, 5, 4, 0, 4, 3);
+    pathB.close();
+    testPathOp(reporter, path, pathB, kIntersect_PathOp);
+}
+
+static void cubicOp87u(skiatest::Reporter* reporter) {
+    SkPath path, pathB;
+    path.setFillType(SkPath::kWinding_FillType);
+    path.moveTo(0,1);
+    path.cubicTo(0,2, 2,0, 6,4);
+    path.close();
+    pathB.setFillType(SkPath::kWinding_FillType);
+    pathB.moveTo(0,2);
+    pathB.cubicTo(4,6, 1,0, 2,0);
+    pathB.close();
+    testPathOp(reporter, path, pathB, kUnion_PathOp);
+}
+
+static void cubicOp88u(skiatest::Reporter* reporter) {
+    SkPath path, pathB;
+    path.setFillType(SkPath::kWinding_FillType);
+    path.moveTo(0,1);
+    path.cubicTo(2,5, 5,0, 6,4);
+    path.close();
+    pathB.setFillType(SkPath::kWinding_FillType);
+    pathB.moveTo(0,5);
+    pathB.cubicTo(4,6, 1,0, 5,2);
+    pathB.close();
+    testPathOp(reporter, path, pathB, kUnion_PathOp);
+}
+
+static void cubicOp89u(skiatest::Reporter* reporter) {
+    SkPath path, pathB;
+    path.setFillType(SkPath::kWinding_FillType);
+    path.moveTo(0, 3);
+    path.cubicTo(1, 6, 5, 0, 6, 3);
+    path.close();
+    pathB.setFillType(SkPath::kWinding_FillType);
+    pathB.moveTo(0, 5);
+    pathB.cubicTo(3, 6, 3, 0, 6, 1);
+    pathB.close();
+    testPathOp(reporter, path, pathB, kUnion_PathOp);
+}
+
+static void cubicOp90u(skiatest::Reporter* reporter) {
+    SkPath path, pathB;
+    path.setFillType(SkPath::kEvenOdd_FillType);
+    path.moveTo(0, 5);
+    path.cubicTo(1, 2, 5, 2, 4, 1);
+    path.close();
+    pathB.setFillType(SkPath::kEvenOdd_FillType);
+    pathB.moveTo(2, 5);
+    pathB.cubicTo(1, 4, 5, 0, 2, 1);
+    pathB.close();
+    testPathOp(reporter, path, pathB, kUnion_PathOp);
+}
+
+static void cubicOp91u(skiatest::Reporter* reporter) {
+    SkPath path, pathB;
+    path.setFillType(SkPath::kWinding_FillType);
+    path.moveTo(1, 6);
+    path.cubicTo(0, 3, 6, 3, 5, 0);
+    path.close();
+    pathB.setFillType(SkPath::kWinding_FillType);
+    pathB.moveTo(3, 6);
+    pathB.cubicTo(0, 5, 6, 1, 3, 0);
+    pathB.close();
+    testPathOp(reporter, path, pathB, kUnion_PathOp);
+}
 static void (*firstTest)(skiatest::Reporter* ) = 0;
 
 static struct TestDesc tests[] = {
  //   TEST(skpkkiste_to716),
+ //   TEST(bufferOverflow),
+ //   TEST(issue1435),
+    TEST(cubicOp91u),
+    TEST(cubicOp90u),
+    TEST(cubicOp89u),
+    TEST(cubicOp88u),
+    TEST(cubicOp87u),
+    TEST(cubicOp86i),
+    TEST(loopEdge2),
+    TEST(loopEdge1),
+    TEST(rectOp3x),
+    TEST(rectOp2i),
+    TEST(rectOp1i),
+    TEST(issue1418b),
     TEST(cubicOp85i),
     TEST(issue1417),
     TEST(issue1418),
@@ -2167,8 +2445,8 @@
 
 static void PathOpsOpTest(skiatest::Reporter* reporter) {
 #ifdef SK_DEBUG
-    gDebugMaxWindSum = 4;
-    gDebugMaxWindValue = 4;
+    SkPathOpsDebug::gMaxWindSum = 4;
+    SkPathOpsDebug::gMaxWindValue = 4;
 #endif
 #if DEBUG_SHOW_TEST_NAME
     strncpy(DEBUG_FILENAME_STRING, "", DEBUG_FILENAME_STRING_LENGTH);
@@ -2181,8 +2459,8 @@
         RunTestSet(reporter, subTests, subTestCount, firstSubTest, stopTest, runReverse);
     }
 #ifdef SK_DEBUG
-    gDebugMaxWindSum = SK_MaxS32;
-    gDebugMaxWindValue = SK_MaxS32;
+    SkPathOpsDebug::gMaxWindSum = SK_MaxS32;
+    SkPathOpsDebug::gMaxWindValue = SK_MaxS32;
 #endif
 }
 
diff --git a/tests/PathOpsQuadLineIntersectionTest.cpp b/tests/PathOpsQuadLineIntersectionTest.cpp
index 555a90c..7ec8066 100644
--- a/tests/PathOpsQuadLineIntersectionTest.cpp
+++ b/tests/PathOpsQuadLineIntersectionTest.cpp
@@ -59,6 +59,8 @@
     SkDQuad quad;
     SkDLine line;
 } oneOffs[] = {
+    {{{{142.589081, 102.283646}, {149.821579, 100}, {158, 100}}},
+        {{{90, 230}, {160, 60}}}},
     {{{{1101, 10}, {1101, 8.3431453704833984}, {1099.828857421875, 7.1711997985839844}}},
         {{{1099.828857421875,7.1711711883544922}, {1099.121337890625,7.8786783218383789}}}},
     {{{{973, 507}, {973, 508.24264526367187}, {972.12158203125, 509.12161254882812}}},
diff --git a/tests/PathOpsSimplifyFailTest.cpp b/tests/PathOpsSimplifyFailTest.cpp
index 0245f87..8c0f9ba 100644
--- a/tests/PathOpsSimplifyFailTest.cpp
+++ b/tests/PathOpsSimplifyFailTest.cpp
@@ -37,63 +37,82 @@
 
 const size_t finitePtsCount = sizeof(finitePts) / sizeof(finitePts[0]);
 
+static void failOne(skiatest::Reporter* reporter, int index) {
+    SkPath path;
+    int i = (int) (index % nonFinitePtsCount);
+    int f = (int) (index % finitePtsCount);
+    int g = (int) ((f + 1) % finitePtsCount);
+    switch (index % 13) {
+        case 0: path.lineTo(nonFinitePts[i]); break;
+        case 1: path.quadTo(nonFinitePts[i], nonFinitePts[i]); break;
+        case 2: path.quadTo(nonFinitePts[i], finitePts[f]); break;
+        case 3: path.quadTo(finitePts[f], nonFinitePts[i]); break;
+        case 4: path.cubicTo(nonFinitePts[i], finitePts[f], finitePts[f]); break;
+        case 5: path.cubicTo(finitePts[f], nonFinitePts[i], finitePts[f]); break;
+        case 6: path.cubicTo(finitePts[f], finitePts[f], nonFinitePts[i]); break;
+        case 7: path.cubicTo(nonFinitePts[i], nonFinitePts[i], finitePts[f]); break;
+        case 8: path.cubicTo(nonFinitePts[i], finitePts[f], nonFinitePts[i]); break;
+        case 9: path.cubicTo(finitePts[f], nonFinitePts[i], nonFinitePts[i]); break;
+        case 10: path.cubicTo(nonFinitePts[i], nonFinitePts[i], nonFinitePts[i]); break;
+        case 11: path.cubicTo(nonFinitePts[i], finitePts[f], finitePts[g]); break;
+        case 12: path.moveTo(nonFinitePts[i]); break;
+    }
+    SkPath result;
+    result.setFillType(SkPath::kWinding_FillType);
+    bool success = Simplify(path, &result);
+    REPORTER_ASSERT(reporter, !success);
+    REPORTER_ASSERT(reporter, result.isEmpty());
+    REPORTER_ASSERT(reporter, result.getFillType() == SkPath::kWinding_FillType);
+    reporter->bumpTestCount();
+}
+
+static void dontFailOne(skiatest::Reporter* reporter, int index) {
+    SkPath path;
+    int f = (int) (index % finitePtsCount);
+    int g = (int) ((f + 1) % finitePtsCount);
+    switch (index % 11) {
+        case 0: path.lineTo(finitePts[f]); break;
+        case 1: path.quadTo(finitePts[f], finitePts[f]); break;
+        case 2: path.quadTo(finitePts[f], finitePts[g]); break;
+        case 3: path.quadTo(finitePts[g], finitePts[f]); break;
+        case 4: path.cubicTo(finitePts[f], finitePts[f], finitePts[f]); break;
+        case 5: path.cubicTo(finitePts[f], finitePts[f], finitePts[g]); break;
+        case 6: path.cubicTo(finitePts[f], finitePts[g], finitePts[f]); break;
+        case 7: path.cubicTo(finitePts[f], finitePts[g], finitePts[g]); break;
+        case 8: path.cubicTo(finitePts[g], finitePts[f], finitePts[f]); break;
+        case 9: path.cubicTo(finitePts[g], finitePts[f], finitePts[g]); break;
+        case 10: path.moveTo(finitePts[f]); break;
+    }
+    SkPath result;
+    result.setFillType(SkPath::kWinding_FillType);
+    bool success = Simplify(path, &result);
+    REPORTER_ASSERT(reporter, success);
+    REPORTER_ASSERT(reporter, result.getFillType() != SkPath::kWinding_FillType);
+    reporter->bumpTestCount();
+}
+
 static void PathOpsSimplifyFailTest(skiatest::Reporter* reporter) {
     for (int index = 0; index < (int) (13 * nonFinitePtsCount * finitePtsCount); ++index) {
-        SkPath path;
-        int i = (int) (index % nonFinitePtsCount);
-        int f = (int) (index % finitePtsCount);
-        int g = (int) ((f + 1) % finitePtsCount);
-        switch (index % 13) {
-            case 0: path.lineTo(nonFinitePts[i]); break;
-            case 1: path.quadTo(nonFinitePts[i], nonFinitePts[i]); break;
-            case 2: path.quadTo(nonFinitePts[i], finitePts[f]); break;
-            case 3: path.quadTo(finitePts[f], nonFinitePts[i]); break;
-            case 4: path.cubicTo(nonFinitePts[i], finitePts[f], finitePts[f]); break;
-            case 5: path.cubicTo(finitePts[f], nonFinitePts[i], finitePts[f]); break;
-            case 6: path.cubicTo(finitePts[f], finitePts[f], nonFinitePts[i]); break;
-            case 7: path.cubicTo(nonFinitePts[i], nonFinitePts[i], finitePts[f]); break;
-            case 8: path.cubicTo(nonFinitePts[i], finitePts[f], nonFinitePts[i]); break;
-            case 9: path.cubicTo(finitePts[f], nonFinitePts[i], nonFinitePts[i]); break;
-            case 10: path.cubicTo(nonFinitePts[i], nonFinitePts[i], nonFinitePts[i]); break;
-            case 11: path.cubicTo(nonFinitePts[i], finitePts[f], finitePts[g]); break;
-            case 12: path.moveTo(nonFinitePts[i]); break;
-        }
-        SkPath result;
-        result.setFillType(SkPath::kWinding_FillType);
-        bool success = Simplify(path, &result);
-        REPORTER_ASSERT(reporter, !success);
-        REPORTER_ASSERT(reporter, result.isEmpty());
-        REPORTER_ASSERT(reporter, result.getFillType() == SkPath::kWinding_FillType);
-        reporter->bumpTestCount();
-    }
-    if (sizeof(reporter) == 4) {
-        return;
+        failOne(reporter, index);
     }
     for (int index = 0; index < (int) (11 * finitePtsCount); ++index) {
-        SkPath path;
-        int f = (int) (index % finitePtsCount);
-        int g = (int) ((f + 1) % finitePtsCount);
-        switch (index % 11) {
-            case 0: path.lineTo(finitePts[f]); break;
-            case 1: path.quadTo(finitePts[f], finitePts[f]); break;
-            case 2: path.quadTo(finitePts[f], finitePts[g]); break;
-            case 3: path.quadTo(finitePts[g], finitePts[f]); break;
-            case 4: path.cubicTo(finitePts[f], finitePts[f], finitePts[f]); break;
-            case 5: path.cubicTo(finitePts[f], finitePts[f], finitePts[g]); break;
-            case 6: path.cubicTo(finitePts[f], finitePts[g], finitePts[f]); break;
-            case 7: path.cubicTo(finitePts[f], finitePts[g], finitePts[g]); break;
-            case 8: path.cubicTo(finitePts[g], finitePts[f], finitePts[f]); break;
-            case 9: path.cubicTo(finitePts[g], finitePts[f], finitePts[g]); break;
-            case 10: path.moveTo(finitePts[f]); break;
-        }
-        SkPath result;
-        result.setFillType(SkPath::kWinding_FillType);
-        bool success = Simplify(path, &result);
-        REPORTER_ASSERT(reporter, success);
-        REPORTER_ASSERT(reporter, result.getFillType() != SkPath::kWinding_FillType);
-        reporter->bumpTestCount();
+        dontFailOne(reporter, index);
     }
 }
 
+static void PathOpsSimplifyFailOneTest(skiatest::Reporter* reporter) {
+    int index = 0;
+    failOne(reporter, index);
+}
+
+static void PathOpsSimplifyDontFailOneTest(skiatest::Reporter* reporter) {
+    int index = 6;
+    dontFailOne(reporter, index);
+}
+
 #include "TestClassDef.h"
 DEFINE_TESTCLASS_SHORT(PathOpsSimplifyFailTest)
+
+DEFINE_TESTCLASS_SHORT(PathOpsSimplifyFailOneTest)
+
+DEFINE_TESTCLASS_SHORT(PathOpsSimplifyDontFailOneTest)
diff --git a/tests/PathOpsSimplifyTest.cpp b/tests/PathOpsSimplifyTest.cpp
index 954435f..65b8d98 100644
--- a/tests/PathOpsSimplifyTest.cpp
+++ b/tests/PathOpsSimplifyTest.cpp
@@ -2813,6 +2813,7 @@
     path.close();
     testSimplify(reporter, path);
 }
+
 static void testQuadratic55(skiatest::Reporter* reporter) {
     SkPath path;
 path.moveTo(303.12088f, 141.299606f);
@@ -3828,9 +3829,90 @@
     testSimplify(reporter, path);
 }
 
-static void (*firstTest)(skiatest::Reporter* ) = testQuad6;
+static void tooCloseTest(skiatest::Reporter* reporter) {
+    SkPath path;
+    path.moveTo(0, 0);
+    path.lineTo(1, 1);
+    path.lineTo(1,-1);
+    path.close();
+    path.moveTo(0, 0);
+    path.lineTo(1,-2);
+    path.lineTo(1, 2);
+    path.lineTo(2, 0);
+    path.close();
+    testSimplify(reporter, path);
+}
+
+static void testRect1(skiatest::Reporter* reporter) {
+    SkPath path;
+    path.addRect(0, 0, 60, 60, SkPath::kCCW_Direction);
+    path.addRect(30, 20, 50, 50, SkPath::kCCW_Direction);
+    path.addRect(24, 20, 36, 30, SkPath::kCCW_Direction);
+    path.addRect(32, 24, 36, 41, SkPath::kCCW_Direction);
+    testSimplify(reporter, path);
+}
+
+static void testRect2(skiatest::Reporter* reporter) {
+    SkPath path;
+    path.setFillType(SkPath::kWinding_FillType);
+    path.moveTo(0, 0);
+    path.lineTo(60, 0);
+    path.lineTo(60, 60);
+    path.lineTo(0, 60);
+    path.close();
+    path.moveTo(30, 20);
+    path.lineTo(30, 50);
+    path.lineTo(50, 50);
+    path.lineTo(50, 20);
+    path.close();
+    path.moveTo(24, 20);
+    path.lineTo(24, 30);
+    path.lineTo(36, 30);
+    path.lineTo(36, 20);
+    path.close();
+    path.moveTo(32, 24);
+    path.lineTo(32, 41);
+    path.lineTo(36, 41);
+    path.lineTo(36, 24);
+    path.close();
+    testSimplify(reporter, path);
+}
+
+static void testTriangles3x(skiatest::Reporter* reporter) {
+    SkPath path;
+    path.setFillType(SkPath::kEvenOdd_FillType);
+    path.moveTo(1, 0);
+    path.quadTo(0, 1, 3, 2);
+    path.lineTo(1, 3);
+    path.close();
+    path.moveTo(0, 0);
+    path.lineTo(1, 1);
+    path.quadTo(2, 1, 0, 2);
+    path.close();
+    testSimplify(reporter, path);
+}
+
+static void testQuad8(skiatest::Reporter* reporter) {
+    SkPath path;
+    path.moveTo(3, 0);
+    path.quadTo(0, 1, 3, 2);
+    path.lineTo(0, 3);
+    path.close();
+    path.moveTo(1, 0);
+    path.lineTo(3, 0);
+    path.quadTo(1, 1, 2, 2);
+    path.close();
+    testSimplify(reporter, path);
+}
+
+static void (*firstTest)(skiatest::Reporter* ) = testRect2;
 
 static TestDesc tests[] = {
+    TEST(testQuad8),
+    TEST(testTriangles3x),
+    TEST(testRect2),
+    TEST(testRect1),
+    TEST(tooCloseTest),
     TEST(skphealth_com76),
     TEST(testQuadLineIntersect1),
     TEST(testQuadLineIntersect2),
@@ -4199,8 +4281,8 @@
 
 static void PathOpsSimplifyTest(skiatest::Reporter* reporter) {
 #ifdef SK_DEBUG
-    gDebugMaxWindSum = 4;
-    gDebugMaxWindValue = 4;
+    SkPathOpsDebug::gMaxWindSum = 4;
+    SkPathOpsDebug::gMaxWindValue = 4;
 #endif
     if (runSubTestsFirst) {
         RunTestSet(reporter, subTests, subTestCount, firstSubTest, stopTest, runReverse);
@@ -4210,8 +4292,8 @@
         RunTestSet(reporter, subTests, subTestCount, firstSubTest, stopTest, runReverse);
     }
 #ifdef SK_DEBUG
-    gDebugMaxWindSum = SK_MaxS32;
-    gDebugMaxWindValue = SK_MaxS32;
+    SkPathOpsDebug::gMaxWindSum = SK_MaxS32;
+    SkPathOpsDebug::gMaxWindValue = SK_MaxS32;
 #endif
 }
 
diff --git a/tests/PathOpsThreadedCommon.cpp b/tests/PathOpsThreadedCommon.cpp
index 0abf816..a66ec71 100644
--- a/tests/PathOpsThreadedCommon.cpp
+++ b/tests/PathOpsThreadedCommon.cpp
@@ -21,7 +21,7 @@
         pool.add(fRunnables[index]);
     }
 #ifdef SK_DEBUG
-    gDebugMaxWindSum = SK_MaxS32;
-    gDebugMaxWindValue = SK_MaxS32;
+    SkPathOpsDebug::gMaxWindSum = SK_MaxS32;
+    SkPathOpsDebug::gMaxWindValue = SK_MaxS32;
 #endif
 }