shape ops work in progress
milestone: about 1.6M tests pass

git-svn-id: http://skia.googlecode.com/svn/trunk@5035 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/experimental/Intersection/EdgeWalkerPolygon4x4_Test.cpp b/experimental/Intersection/EdgeWalkerPolygon4x4_Test.cpp
index c9d6bdd..e795cd0 100755
--- a/experimental/Intersection/EdgeWalkerPolygon4x4_Test.cpp
+++ b/experimental/Intersection/EdgeWalkerPolygon4x4_Test.cpp
@@ -1,169 +1,176 @@
 #include "EdgeWalker_Test.h"
 #include "Intersection_Tests.h"
-#include "SkBitmap.h"
-#include "SkCanvas.h"
-#include <assert.h>
-#include <pthread.h>
 
 static void* testSimplify4x4QuadralateralsMain(void* data)
 {
-    char pathStr[1024];
-    bzero(pathStr, sizeof(pathStr));
     SkASSERT(data);
     State4& state = *(State4*) data;
-    int ax = state.a & 0x03;
-    int ay = state.a >> 2;
-    int bx = state.b & 0x03;
-    int by = state.b >> 2;
-    int cx = state.c & 0x03;
-    int cy = state.c >> 2;
-    int dx = state.d & 0x03;
-    int dy = state.d >> 2;
-    for (int e = 0 ; e < 16; ++e) {
-        int ex = e & 0x03;
-        int ey = e >> 2;
-        for (int f = e ; f < 16; ++f) {
-            int fx = f & 0x03;
-            int fy = f >> 2;
-            for (int g = f ; g < 16; ++g) {
-                int gx = g & 0x03;
-                int gy = g >> 2;
-                for (int h = g ; h < 16; ++h) {
-                    int hx = h & 0x03;
-                    int hy = h >> 2;
+    char pathStr[1024];
+    bzero(pathStr, sizeof(pathStr));
+    do {
+        int ax = state.a & 0x03;
+        int ay = state.a >> 2;
+        int bx = state.b & 0x03;
+        int by = state.b >> 2;
+        int cx = state.c & 0x03;
+        int cy = state.c >> 2;
+        int dx = state.d & 0x03;
+        int dy = state.d >> 2;
+        for (int e = 0 ; e < 16; ++e) {
+            int ex = e & 0x03;
+            int ey = e >> 2;
+            for (int f = e ; f < 16; ++f) {
+                int fx = f & 0x03;
+                int fy = f >> 2;
+                for (int g = f ; g < 16; ++g) {
+                    int gx = g & 0x03;
+                    int gy = g >> 2;
+                    for (int h = g ; h < 16; ++h) {
+                        int hx = h & 0x03;
+                        int hy = h >> 2;
+                        SkPath path, out;
+                        path.setFillType(SkPath::kWinding_FillType);
+                        path.moveTo(ax, ay);
+                        path.lineTo(bx, by);
+                        path.lineTo(cx, cy);
+                        path.lineTo(dx, dy);
+                        path.close();
+                        path.moveTo(ex, ey);
+                        path.lineTo(fx, fy);
+                        path.lineTo(gx, gy);
+                        path.lineTo(hx, hy);
+                        path.close();
+                        if (1) {  // gdb: set print elements 400
+                            char* str = pathStr;
+                            str += sprintf(str, "    path.moveTo(%d, %d);\n", ax, ay);
+                            str += sprintf(str, "    path.lineTo(%d, %d);\n", bx, by);
+                            str += sprintf(str, "    path.lineTo(%d, %d);\n", cx, cy);
+                            str += sprintf(str, "    path.lineTo(%d, %d);\n", dx, dy);
+                            str += sprintf(str, "    path.close();\n");
+                            str += sprintf(str, "    path.moveTo(%d, %d);\n", ex, ey);
+                            str += sprintf(str, "    path.lineTo(%d, %d);\n", fx, fy);
+                            str += sprintf(str, "    path.lineTo(%d, %d);\n", gx, gy);
+                            str += sprintf(str, "    path.lineTo(%d, %d);\n", hx, hy);
+                            str += sprintf(str, "    path.close();\n");
+                        }
+                        outputProgress(state, pathStr);
+                        testSimplifyx(path, out, state, pathStr);
+                        state.testsRun++;
+                #if 0 // FIXME: enable once we have support for even/odd
+                        path.setFillType(SkPath::kEvenOdd_FillType);
+                        outputProgress(state, pathStr, SkPath::kEvenOdd_FillType);
+                        testSimplifyx(path, true, out, state, pathStr);
+                        state.testsRun++;
+                #endif
+                    }
+                }
+            }
+        }
+    } while (runNextTestSet(state));
+    return NULL;
+}
+
+void Simplify4x4QuadralateralsThreaded_Test()
+{
+    SkDebugf("%s\n", __FUNCTION__);
+#ifdef SK_DEBUG
+    gDebugMaxWindSum = 4; // FIXME: 3?
+    gDebugMaxWindValue = 4;
+#endif
+    const char testStr[] = "testQuadralateral";
+    initializeTests(testStr, sizeof(testStr));
+    int testsRun = 0;
+    for (int a = 0; a < 16; ++a) {
+        for (int b = a ; b < 16; ++b) {
+            for (int c = b ; c < 16; ++c) {
+                for (int d = c; d < 16; ++d) {                 
+                    testsRun += dispatchTest4(testSimplify4x4QuadralateralsMain,
+                            a, b, c, d);
+                }
+                if (!gRunTestsInOneThread) SkDebugf(".");
+            }
+            if (!gRunTestsInOneThread) SkDebugf("%d", b);
+        }
+        if (!gRunTestsInOneThread) SkDebugf("\n%d", a);
+    }
+    testsRun += waitForCompletion();
+    SkDebugf("%s total tests run=%d\n", __FUNCTION__, testsRun);
+}
+
+
+static void* testSimplify4x4NondegeneratesMain(void* data) {
+    SkASSERT(data);
+    State4& state = *(State4*) data;
+    char pathStr[1024];
+    bzero(pathStr, sizeof(pathStr));
+    do {
+        int ax = state.a & 0x03;
+        int ay = state.a >> 2;
+        int bx = state.b & 0x03;
+        int by = state.b >> 2;
+        int cx = state.c & 0x03;
+        int cy = state.c >> 2;
+        for (int d = 0; d < 15; ++d) {
+            int dx = d & 0x03;
+            int dy = d >> 2;
+            for (int e = d + 1; e < 16; ++e) {
+                int ex = e & 0x03;
+                int ey = e >> 2;
+                for (int f = d + 1; f < 16; ++f) {
+                    if (e == f) {
+                        continue;
+                    }
+                    int fx = f & 0x03;
+                    int fy = f >> 2;
+                    if ((ex - dx) * (fy - dy) == (ey - dy) * (fx - dx)) {
+                        continue;
+                    }
                     SkPath path, out;
                     path.setFillType(SkPath::kWinding_FillType);
                     path.moveTo(ax, ay);
                     path.lineTo(bx, by);
                     path.lineTo(cx, cy);
-                    path.lineTo(dx, dy);
                     path.close();
-                    path.moveTo(ex, ey);
+                    path.moveTo(dx, dy);
+                    path.lineTo(ex, ey);
                     path.lineTo(fx, fy);
-                    path.lineTo(gx, gy);
-                    path.lineTo(hx, hy);
                     path.close();
-                    if (1) {  // gdb: set print elements 400
+                    if (1) {
                         char* str = pathStr;
                         str += sprintf(str, "    path.moveTo(%d, %d);\n", ax, ay);
                         str += sprintf(str, "    path.lineTo(%d, %d);\n", bx, by);
                         str += sprintf(str, "    path.lineTo(%d, %d);\n", cx, cy);
-                        str += sprintf(str, "    path.lineTo(%d, %d);\n", dx, dy);
                         str += sprintf(str, "    path.close();\n");
-                        str += sprintf(str, "    path.moveTo(%d, %d);\n", ex, ey);
+                        str += sprintf(str, "    path.moveTo(%d, %d);\n", dx, dy);
+                        str += sprintf(str, "    path.lineTo(%d, %d);\n", ex, ey);
                         str += sprintf(str, "    path.lineTo(%d, %d);\n", fx, fy);
-                        str += sprintf(str, "    path.lineTo(%d, %d);\n", gx, gy);
-                        str += sprintf(str, "    path.lineTo(%d, %d);\n", hx, hy);
-                        str += sprintf(str, "    path.close();");
+                        str += sprintf(str, "    path.close();\n");
                     }
-                    if (!testSimplify(path, true, out, state.bitmap, state.canvas)) {
-                        SkDebugf("*/\n{ SkPath::kWinding_FillType, %d, %d, %d, %d,"
-                                " %d, %d, %d, %d },\n/*\n", state.a, state.b, state.c, state.d,
-                                e, f, g, h);
-                    }
+                    outputProgress(state, pathStr);
+                    testSimplifyx(path, out, state, pathStr);
+                    state.testsRun++;
+            #if 0 // FIXME: enable once we have support for even/odd
                     path.setFillType(SkPath::kEvenOdd_FillType);
-                    if (!testSimplify(path, true, out, state.bitmap, state.canvas)) {
-                        SkDebugf("*/\n{ SkPath::kEvenOdd_FillType, %d, %d, %d, %d,"
-                                " %d, %d, %d, %d },\n/*\n", state.a, state.b, state.c, state.d,
-                                e, f, g, h);
-                    }
+                    outputProgress(state, pathStr, SkPath::kEvenOdd_FillType);
+                    testSimplifyx(path, true, out, state, pathStr);
+                    state.testsRun++;
+            #endif
                 }
             }
         }
-    }
-    return NULL;
-}
-
-const int maxThreads = gRunTestsInOneThread ? 1 : 24;
-
-void Simplify4x4QuadralateralsThreaded_Test()
-{
-    State4 threadState[maxThreads];
-    int threadIndex = 0;
-    for (int a = 0; a < 16; ++a) {
-        for (int b = a ; b < 16; ++b) {
-            for (int c = b ; c < 16; ++c) {
-                for (int d = c; d < 16; ++d) {                 
-                    State4* statePtr = &threadState[threadIndex];
-                    statePtr->a = a;
-                    statePtr->b = b;
-                    statePtr->c = c;
-                    statePtr->d = d;
-                    if (maxThreads > 1) {
-                        createThread(statePtr, testSimplify4x4QuadralateralsMain);
-                        if (++threadIndex >= maxThreads) {
-                            waitForCompletion(threadState, threadIndex);
-                        }
-                    } else {
-                        testSimplify4x4QuadralateralsMain(statePtr);
-                    }
-                }
-            }
-        }
-    }
-    waitForCompletion(threadState, threadIndex);
-}
-
-
-static void* testSimplify4x4NondegeneratesMain(void* data) {
-    char pathStr[1024];
-    bzero(pathStr, sizeof(pathStr));
-    SkASSERT(data);
-    State4& state = *(State4*) data;
-    int ax = state.a & 0x03;
-    int ay = state.a >> 2;
-    int bx = state.b & 0x03;
-    int by = state.b >> 2;
-    int cx = state.c & 0x03;
-    int cy = state.c >> 2;
-    for (int d = 0; d < 15; ++d) {
-        int dx = d & 0x03;
-        int dy = d >> 2;
-        for (int e = d + 1; e < 16; ++e) {
-            int ex = e & 0x03;
-            int ey = e >> 2;
-            for (int f = d + 1; f < 16; ++f) {
-                if (e == f) {
-                    continue;
-                }
-                int fx = f & 0x03;
-                int fy = f >> 2;
-                if ((ex - dx) * (fy - dy) == (ey - dy) * (fx - dx)) {
-                    continue;
-                }
-                SkPath path, out;
-                path.setFillType(SkPath::kWinding_FillType);
-                path.moveTo(ax, ay);
-                path.lineTo(bx, by);
-                path.lineTo(cx, cy);
-                path.close();
-                path.moveTo(dx, dy);
-                path.lineTo(ex, ey);
-                path.lineTo(fx, fy);
-                path.close();
-                if (1) {
-                    char* str = pathStr;
-                    str += sprintf(str, "    path.moveTo(%d, %d);\n", ax, ay);
-                    str += sprintf(str, "    path.lineTo(%d, %d);\n", bx, by);
-                    str += sprintf(str, "    path.lineTo(%d, %d);\n", cx, cy);
-                    str += sprintf(str, "    path.close();\n");
-                    str += sprintf(str, "    path.moveTo(%d, %d);\n", dx, dy);
-                    str += sprintf(str, "    path.lineTo(%d, %d);\n", ex, ey);
-                    str += sprintf(str, "    path.lineTo(%d, %d);\n", fx, fy);
-                    str += sprintf(str, "    path.close();");
-                }
-                testSimplify(path, true, out, state.bitmap, state.canvas);
-                path.setFillType(SkPath::kEvenOdd_FillType);
-                testSimplify(path, true, out, state.bitmap, state.canvas);
-            }
-        }
-    }
+    } while (runNextTestSet(state));
     return NULL;
 }
 
 void SimplifyNondegenerate4x4TrianglesThreaded_Test() {
-    State4 threadState[maxThreads];
-    int threadIndex = 0;
+    SkDebugf("%s\n", __FUNCTION__);
+#ifdef SK_DEBUG
+    gDebugMaxWindSum = 2;
+    gDebugMaxWindValue = 2;
+#endif
+    const char testStr[] = "testNondegenerate";
+    initializeTests(testStr, sizeof(testStr));
+    int testsRun = 0;
     for (int a = 0; a < 15; ++a) {
         int ax = a & 0x03;
         int ay = a >> 2;
@@ -179,81 +186,88 @@
                 if ((bx - ax) * (cy - ay) == (by - ay) * (cx - ax)) {
                     continue;
                 }
-                State4* statePtr = &threadState[threadIndex];
-                statePtr->a = a;
-                statePtr->b = b;
-                statePtr->c = c;
-                if (maxThreads > 1) {
-                    createThread(statePtr, testSimplify4x4NondegeneratesMain);
-                    if (++threadIndex >= maxThreads) {
-                        waitForCompletion(threadState, threadIndex);
-                    }
-                } else {
-                    testSimplify4x4NondegeneratesMain(statePtr);
-                }
+                testsRun += dispatchTest4(testSimplify4x4NondegeneratesMain,
+                        a, b, c, 0);
             }
+            if (!gRunTestsInOneThread) SkDebugf(".");
         }
+        if (!gRunTestsInOneThread) SkDebugf("\n%d", a);
     }
-    waitForCompletion(threadState, threadIndex);
+    testsRun += waitForCompletion();
+    SkDebugf("%s total tests run=%d\n", __FUNCTION__, testsRun);
 }
 
 static void* testSimplify4x4DegeneratesMain(void* data) {
-    char pathStr[1024];
-    bzero(pathStr, sizeof(pathStr));
     SkASSERT(data);
     State4& state = *(State4*) data;
-    int ax = state.a & 0x03;
-    int ay = state.a >> 2;
-    int bx = state.b & 0x03;
-    int by = state.b >> 2;
-    int cx = state.c & 0x03;
-    int cy = state.c >> 2;
-    for (int d = 0; d < 16; ++d) {
-        int dx = d & 0x03;
-        int dy = d >> 2;
-        for (int e = d ; e < 16; ++e) {
-            int ex = e & 0x03;
-            int ey = e >> 2;
-            for (int f = d ; f < 16; ++f) {
-                int fx = f & 0x03;
-                int fy = f >> 2;
-                if (state.abcIsATriangle && (ex - dx) * (fy - dy)
-                        != (ey - dy) * (fx - dx)) {
-                    continue;
+    char pathStr[1024];
+    bzero(pathStr, sizeof(pathStr));
+    do {
+        int ax = state.a & 0x03;
+        int ay = state.a >> 2;
+        int bx = state.b & 0x03;
+        int by = state.b >> 2;
+        int cx = state.c & 0x03;
+        int cy = state.c >> 2;
+        for (int d = 0; d < 16; ++d) {
+            int dx = d & 0x03;
+            int dy = d >> 2;
+            for (int e = d ; e < 16; ++e) {
+                int ex = e & 0x03;
+                int ey = e >> 2;
+                for (int f = d ; f < 16; ++f) {
+                    int fx = f & 0x03;
+                    int fy = f >> 2;
+                    if (state.d && (ex - dx) * (fy - dy)
+                            != (ey - dy) * (fx - dx)) {
+                        continue;
+                    }
+                    SkPath path, out;
+                    path.setFillType(SkPath::kWinding_FillType);
+                    path.moveTo(ax, ay);
+                    path.lineTo(bx, by);
+                    path.lineTo(cx, cy);
+                    path.close();
+                    path.moveTo(dx, dy);
+                    path.lineTo(ex, ey);
+                    path.lineTo(fx, fy);
+                    path.close();
+                    if (1) {
+                        char* str = pathStr;
+                        str += sprintf(str, "    path.moveTo(%d, %d);\n", ax, ay);
+                        str += sprintf(str, "    path.lineTo(%d, %d);\n", bx, by);
+                        str += sprintf(str, "    path.lineTo(%d, %d);\n", cx, cy);
+                        str += sprintf(str, "    path.close();\n");
+                        str += sprintf(str, "    path.moveTo(%d, %d);\n", dx, dy);
+                        str += sprintf(str, "    path.lineTo(%d, %d);\n", ex, ey);
+                        str += sprintf(str, "    path.lineTo(%d, %d);\n", fx, fy);
+                        str += sprintf(str, "    path.close();\n");
+                    }
+                    outputProgress(state, pathStr);
+                    testSimplifyx(path, out, state, pathStr);
+                    state.testsRun++;
+            #if 0 // FIXME: enable once we have support for even/odd
+                    path.setFillType(SkPath::kEvenOdd_FillType);
+                    outputProgress(state, pathStr, SkPath::kEvenOdd_FillType);
+                    testSimplifyx(path, true, out, state, pathStr);
+                    state.testsRun++;
+            #endif
                 }
-                SkPath path, out;
-                path.setFillType(SkPath::kWinding_FillType);
-                path.moveTo(ax, ay);
-                path.lineTo(bx, by);
-                path.lineTo(cx, cy);
-                path.close();
-                path.moveTo(dx, dy);
-                path.lineTo(ex, ey);
-                path.lineTo(fx, fy);
-                path.close();
-                if (1) {
-                    char* str = pathStr;
-                    str += sprintf(str, "    path.moveTo(%d, %d);\n", ax, ay);
-                    str += sprintf(str, "    path.lineTo(%d, %d);\n", bx, by);
-                    str += sprintf(str, "    path.lineTo(%d, %d);\n", cx, cy);
-                    str += sprintf(str, "    path.close();\n");
-                    str += sprintf(str, "    path.moveTo(%d, %d);\n", dx, dy);
-                    str += sprintf(str, "    path.lineTo(%d, %d);\n", ex, ey);
-                    str += sprintf(str, "    path.lineTo(%d, %d);\n", fx, fy);
-                    str += sprintf(str, "    path.close();");
-                }
-                testSimplify(path, true, out, state.bitmap, state.canvas);
-                path.setFillType(SkPath::kEvenOdd_FillType);
-                testSimplify(path, true, out, state.bitmap, state.canvas);
             }
         }
-    }
+    } while (runNextTestSet(state));
     return NULL;
 }
 
 void SimplifyDegenerate4x4TrianglesThreaded_Test() {
-    State4 threadState[maxThreads];
-    int threadIndex = 0;
+    SkDebugf("%s\n", __FUNCTION__);
+#ifdef SK_DEBUG
+    gDebugMaxWindSum = 2;
+    gDebugMaxWindValue = 2;
+#endif
+    const char testStr[] = "testDegenerate";
+    initializeTests(testStr, sizeof(testStr));
+    int testsRun = 0;
     for (int a = 0; a < 16; ++a) {
         int ax = a & 0x03;
         int ay = a >> 2;
@@ -263,23 +277,15 @@
             for (int c = a ; c < 16; ++c) {
                 int cx = c & 0x03;
                 int cy = c >> 2;
-                State4* statePtr = &threadState[threadIndex];
-                statePtr->abcIsATriangle = (bx - ax) * (cy - ay)
-                        != (by - ay) * (cx - ax);
-                statePtr->a = a;
-                statePtr->b = b;
-                statePtr->c = c;
-                if (maxThreads > 1) {
-                    createThread(statePtr, testSimplify4x4DegeneratesMain);
-                    if (++threadIndex >= maxThreads) {
-                        waitForCompletion(threadState, threadIndex);
-                    }
-                } else {
-                    testSimplify4x4DegeneratesMain(statePtr);
-                }
+                bool abcIsATriangle = (bx - ax) * (cy - ay) != (by - ay) * (cx - ax);
+                testsRun += dispatchTest4(testSimplify4x4DegeneratesMain,
+                        a, b, c, abcIsATriangle);
             }
+            if (!gRunTestsInOneThread) SkDebugf(".");
         }
+        if (!gRunTestsInOneThread) SkDebugf("\n%d", a);
     }
-    waitForCompletion(threadState, threadIndex);
+    testsRun += waitForCompletion();
+    SkDebugf("%s total tests run=%d\n", __FUNCTION__, testsRun);
 }
 
diff --git a/experimental/Intersection/EdgeWalkerQuadratic4x4_Test.cpp b/experimental/Intersection/EdgeWalkerQuadratic4x4_Test.cpp
index 75fd9a4..f714249 100644
--- a/experimental/Intersection/EdgeWalkerQuadratic4x4_Test.cpp
+++ b/experimental/Intersection/EdgeWalkerQuadratic4x4_Test.cpp
@@ -7,95 +7,92 @@
 
 static void* testSimplify4x4QuadraticsMain(void* data)
 {
-    char pathStr[1024];
-    bzero(pathStr, sizeof(pathStr));
     SkASSERT(data);
     State4& state = *(State4*) data;
-    int ax = state.a & 0x03;
-    int ay = state.a >> 2;
-    int bx = state.b & 0x03;
-    int by = state.b >> 2;
-    int cx = state.c & 0x03;
-    int cy = state.c >> 2;
-    int dx = state.d & 0x03;
-    int dy = state.d >> 2;
-    for (int e = 0 ; e < 16; ++e) {
-        int ex = e & 0x03;
-        int ey = e >> 2;
-        for (int f = e ; f < 16; ++f) {
-            int fx = f & 0x03;
-            int fy = f >> 2;
-            for (int g = f ; g < 16; ++g) {
-                int gx = g & 0x03;
-                int gy = g >> 2;
-                for (int h = g ; h < 16; ++h) {
-                    int hx = h & 0x03;
-                    int hy = h >> 2;
-                    SkPath path, out;
-                    path.setFillType(SkPath::kWinding_FillType);
-                    path.moveTo(ax, ay);
-                    path.quadTo(bx, by, cx, cy);
-                    path.lineTo(dx, dy);
-                    path.close();
-                    path.moveTo(ex, ey);
-                    path.lineTo(fx, fy);
-                    path.quadTo(gx, gy, hx, hy);
-                    path.close();
-                    if (1) {  // gdb: set print elements 400
-                        char* str = pathStr;
-                        str += sprintf(str, "    path.moveTo(%d, %d);\n", ax, ay);
-                        str += sprintf(str, "    path.quadTo(%d, %d, %d, %d);\n", bx, by, cx, cy);
-                        str += sprintf(str, "    path.lineTo(%d, %d);\n", dx, dy);
-                        str += sprintf(str, "    path.close();\n");
-                        str += sprintf(str, "    path.moveTo(%d, %d);\n", ex, ey);
-                        str += sprintf(str, "    path.lineTo(%d, %d);\n", fx, fy);
-                        str += sprintf(str, "    path.quadTo(%d, %d, %d, %d);\n", gx, gy, hx, hy);
-                        str += sprintf(str, "    path.close();");
-                    }
-                    if (!testSimplify(path, true, out, state.bitmap, state.canvas)) {
-                        SkDebugf("*/\n{ SkPath::kWinding_FillType, %d, %d, %d, %d,"
-                                " %d, %d, %d, %d },\n/*\n", state.a, state.b, state.c, state.d,
-                                e, f, g, h);
-                    }
-                    path.setFillType(SkPath::kEvenOdd_FillType);
-                    if (!testSimplify(path, true, out, state.bitmap, state.canvas)) {
-                        SkDebugf("*/\n{ SkPath::kEvenOdd_FillType, %d, %d, %d, %d,"
-                                " %d, %d, %d, %d },\n/*\n", state.a, state.b, state.c, state.d,
-                                e, f, g, h);
+    char pathStr[1024];
+    bzero(pathStr, sizeof(pathStr));
+    do {
+        int ax = state.a & 0x03;
+        int ay = state.a >> 2;
+        int bx = state.b & 0x03;
+        int by = state.b >> 2;
+        int cx = state.c & 0x03;
+        int cy = state.c >> 2;
+        int dx = state.d & 0x03;
+        int dy = state.d >> 2;
+        for (int e = 0 ; e < 16; ++e) {
+            int ex = e & 0x03;
+            int ey = e >> 2;
+            for (int f = e ; f < 16; ++f) {
+                int fx = f & 0x03;
+                int fy = f >> 2;
+                for (int g = f ; g < 16; ++g) {
+                    int gx = g & 0x03;
+                    int gy = g >> 2;
+                    for (int h = g ; h < 16; ++h) {
+                        int hx = h & 0x03;
+                        int hy = h >> 2;
+                        SkPath path, out;
+                        path.setFillType(SkPath::kWinding_FillType);
+                        path.moveTo(ax, ay);
+                        path.quadTo(bx, by, cx, cy);
+                        path.lineTo(dx, dy);
+                        path.close();
+                        path.moveTo(ex, ey);
+                        path.lineTo(fx, fy);
+                        path.quadTo(gx, gy, hx, hy);
+                        path.close();
+                        if (1) {  // gdb: set print elements 400
+                            char* str = pathStr;
+                            str += sprintf(str, "    path.moveTo(%d, %d);\n", ax, ay);
+                            str += sprintf(str, "    path.quadTo(%d, %d, %d, %d);\n", bx, by, cx, cy);
+                            str += sprintf(str, "    path.lineTo(%d, %d);\n", dx, dy);
+                            str += sprintf(str, "    path.close();\n");
+                            str += sprintf(str, "    path.moveTo(%d, %d);\n", ex, ey);
+                            str += sprintf(str, "    path.lineTo(%d, %d);\n", fx, fy);
+                            str += sprintf(str, "    path.quadTo(%d, %d, %d, %d);\n", gx, gy, hx, hy);
+                            str += sprintf(str, "    path.close();\n");
+                        }
+                        outputProgress(state, pathStr);
+                        testSimplifyx(path, out, state, pathStr);
+                        state.testsRun++;
+                #if 0 // FIXME: enable once we have support for even/odd
+                        path.setFillType(SkPath::kEvenOdd_FillType);
+                        outputProgress(state, pathStr, SkPath::kEvenOdd_FillType);
+                        testSimplifyx(path, true, out, state, pathStr);
+                        state.testsRun++;
+                #endif
                     }
                 }
             }
         }
-    }
+    } while (runNextTestSet(state));
     return NULL;
 }
 
-const int maxThreads = gRunTestsInOneThread ? 1 : 24;
-
 void Simplify4x4QuadraticsThreaded_Test()
 {
-    State4 threadState[maxThreads];
-    int threadIndex = 0;
+    SkDebugf("%s\n", __FUNCTION__);
+#ifdef SK_DEBUG
+    gDebugMaxWindSum = 4; // FIXME: 3?
+    gDebugMaxWindValue = 4;
+#endif
+    const char testStr[] = "testQuadratic";
+    initializeTests(testStr, sizeof(testStr));
+    int testsRun = 0;
     for (int a = 0; a < 16; ++a) {
         for (int b = a ; b < 16; ++b) {
             for (int c = b ; c < 16; ++c) {
                 for (int d = c; d < 16; ++d) {                 
-                    State4* statePtr = &threadState[threadIndex];
-                    statePtr->a = a;
-                    statePtr->b = b;
-                    statePtr->c = c;
-                    statePtr->d = d;
-                    if (maxThreads > 1) {
-                        createThread(statePtr, testSimplify4x4QuadraticsMain);
-                        if (++threadIndex >= maxThreads) {
-                            waitForCompletion(threadState, threadIndex);
-                        }
-                    } else {
-                        testSimplify4x4QuadraticsMain(statePtr);
-                    }
+                    testsRun += dispatchTest4(testSimplify4x4QuadraticsMain,
+                            a, b, c, d);
                 }
+                if (!gRunTestsInOneThread) SkDebugf(".");
             }
+            if (!gRunTestsInOneThread) SkDebugf("%d", b);
         }
+        if (!gRunTestsInOneThread) SkDebugf("\n%d", a);
     }
-    waitForCompletion(threadState, threadIndex);
+    testsRun += waitForCompletion();
+    SkDebugf("%s total tests run=%d\n", __FUNCTION__, testsRun);
 }
diff --git a/experimental/Intersection/EdgeWalker_Test.h b/experimental/Intersection/EdgeWalker_Test.h
index 492ba70..229a94d 100644
--- a/experimental/Intersection/EdgeWalker_Test.h
+++ b/experimental/Intersection/EdgeWalker_Test.h
@@ -5,6 +5,7 @@
 #include <pthread.h>
 
 class SkCanvas;
+struct State4;
 
 //extern int comparePaths(const SkPath& one, const SkPath& two);
 extern int comparePaths(const SkPath& one, const SkPath& two, SkBitmap& bitmap,
@@ -16,7 +17,7 @@
 extern bool testSimplify(const SkPath& path, bool fill, SkPath& out,
         SkBitmap& bitmap, SkCanvas* canvas = 0);
 extern bool testSimplifyx(const SkPath& path, SkPath& out,
-        SkBitmap& bitmap, SkCanvas* canvas = 0);
+        State4& state, const char* pathStr);
 extern bool testSimplifyx(const SkPath& path);
 
 struct State4 {
@@ -25,7 +26,6 @@
     static pthread_cond_t checkQueue;
     pthread_cond_t initialized;
     static State4* queue;
-    State4* next;
     pthread_t threadID;
     int index;
     bool done;
@@ -33,14 +33,18 @@
     int a;
     int b;
     int c;
-    int d;
+    int d; // sometimes 1 if abc_is_a_triangle
     int testsRun;
     char filename[256];
     
     SkCanvas* canvas;
     SkBitmap bitmap;
-    bool abcIsATriangle;
 };
 
 void createThread(State4* statePtr, void* (*test)(void* ));
-void waitForCompletion(State4 threadState[], int& threadIndex);
+int dispatchTest4(void* (*testFun)(void* ), int a, int b, int c, int d);
+void initializeTests(const char* testName, size_t testNameSize);
+void outputProgress(const State4& state, const char* pathStr);
+void outputToStream(const State4& state, const char* pathStr, SkWStream& outFile);
+bool runNextTestSet(State4& state);
+int waitForCompletion();
diff --git a/experimental/Intersection/EdgeWalker_TestUtility.cpp b/experimental/Intersection/EdgeWalker_TestUtility.cpp
index 7e65e8f..7baa17b 100644
--- a/experimental/Intersection/EdgeWalker_TestUtility.cpp
+++ b/experimental/Intersection/EdgeWalker_TestUtility.cpp
@@ -3,17 +3,38 @@
 #include "SkBitmap.h"
 #include "SkCanvas.h"
 #include "SkPaint.h"
+#include "SkStream.h"
+
 #include <algorithm>
+#include <assert.h>
+#include <errno.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/sysctl.h>
 
 #undef SkASSERT
 #define SkASSERT(cond) while (!(cond)) { sk_throw(); }
 
+static const char marker[] =
+    "</div>\n"
+    "\n"
+    "<script type=\"text/javascript\">\n"
+    "\n"
+    "var testDivs = [\n";
+#if 0
+static const char filename[] = "../../experimental/Intersection/debugXX.txt";
+#else
+static const char filename[] = "/flash/debug/XX.txt";
+#endif
+
 static bool gShowPath = false;
 static bool gComparePaths = true;
 //static bool gDrawLastAsciiPaths = true;
 static bool gDrawAllAsciiPaths = false;
 static bool gShowAsciiPaths = false;
-static bool gComparePathsAssert = true;
+static bool gComparePathsAssert = false;
+static bool gPathStrAssert = true;
 
 void showPath(const SkPath& path, const char* str) {
     SkDebugf("%s\n", !str ? "original:" : str);
@@ -196,16 +217,17 @@
         SkScalar yScale = std::max(24.0f / larger.height(), 1.0f);
         errors = scaledDrawTheSame(one, two, xScale, yScale, false, bitmap, canvas);
         if (errors > 5) {
+            SkDebugf("\n");
             scaledDrawTheSame(one, two, xScale, yScale, true, bitmap, canvas);
         }
     }
-    if (errors > max) {
-        SkDebugf("\n%s errors=%d\n", __FUNCTION__, errors); 
+    const int MAX_ERRORS = 20;
+    if (errors > max && errors <= MAX_ERRORS) {
+        SkDebugf("%s errors=%d\n", __FUNCTION__, errors); 
         max = errors;
     }
-    const int MAX_ERRORS = 20;
-    if (errors > MAX_ERRORS) SkDebugf("\n%s errors=%d\n", __FUNCTION__, errors); 
     if (errors > MAX_ERRORS && gComparePathsAssert) {
+        SkDebugf("%s errors=%d\n", __FUNCTION__, errors); 
         showPath(one);
         showPath(two, "simplified:");
         SkASSERT(0);
@@ -256,8 +278,8 @@
     return comparePaths(path, out, bitmap, canvas) == 0;
 }
 
-bool testSimplifyx(const SkPath& path, SkPath& out, SkBitmap& bitmap,
-        SkCanvas* canvas) {
+bool testSimplifyx(const SkPath& path, SkPath& out, State4& state,
+        const char* pathStr) {
     if (gShowPath) {
         showPath(path);
     }
@@ -265,7 +287,16 @@
     if (!gComparePaths) {
         return true;
     }
-    return comparePaths(path, out, bitmap, canvas) == 0;
+    int result = comparePaths(path, out, state.bitmap, state.canvas);
+    if (result && gPathStrAssert) {
+        char temp[8192];
+        bzero(temp, sizeof(temp));
+        SkMemoryWStream stream(temp, sizeof(temp));
+        outputToStream(state, pathStr, stream);
+        SkDebugf(temp);
+        SkASSERT(0);
+    }
+    return result == 0;
 }
 
 bool testSimplifyx(const SkPath& path) {
@@ -281,22 +312,232 @@
     return comparePaths(path, out, bitmap, 0) == 0;
 }
 
+const int maxThreadsAllocated = 64;
+static int maxThreads = 1;
+static int threadIndex;
+State4 threadState[maxThreadsAllocated];
+static int testNumber;
+static const char* testName;
+static bool debugThreads = false;
+
+State4* State4::queue = NULL;
+pthread_mutex_t State4::addQueue = PTHREAD_MUTEX_INITIALIZER;
+pthread_cond_t State4::checkQueue = PTHREAD_COND_INITIALIZER;
+
 State4::State4() {
     bitmap.setConfig(SkBitmap::kARGB_8888_Config, 150 * 2, 100);
     bitmap.allocPixels();
     canvas = new SkCanvas(bitmap);
 }
 
-void createThread(State4* statePtr, void* (*test)(void* )) {
-    int threadError = pthread_create(&statePtr->threadID, NULL, test,
+void createThread(State4* statePtr, void* (*testFun)(void* )) {
+    int threadError = pthread_create(&statePtr->threadID, NULL, testFun,
             (void*) statePtr);
     SkASSERT(!threadError);
 }
 
-void waitForCompletion(State4 threadState[], int& threadIndex) {
-    for (int index = 0; index < threadIndex; ++index) {
-        pthread_join(threadState[index].threadID, NULL);
+int dispatchTest4(void* (*testFun)(void* ), int a, int b, int c, int d) {
+    int testsRun = 0;
+    
+    if (!gRunTestsInOneThread) {
+        State4* statePtr;
+        pthread_mutex_lock(&State4::addQueue);
+        if (threadIndex < maxThreads) {
+            statePtr = &threadState[threadIndex];
+            statePtr->testsRun = 0;
+            statePtr->a = a;
+            statePtr->b = b;
+            statePtr->c = c;
+            statePtr->d = d;
+            statePtr->done = false;
+            statePtr->index = threadIndex;
+            statePtr->last = false;
+            if (debugThreads) SkDebugf("%s %d create done=%d last=%d\n", __FUNCTION__,
+                    statePtr->index, statePtr->done, statePtr->last);
+            pthread_cond_init(&statePtr->initialized, NULL);
+            ++threadIndex;
+            createThread(statePtr, testFun);
+        } else {
+            while (!State4::queue) {
+                if (debugThreads) SkDebugf("%s checkQueue\n", __FUNCTION__);
+                pthread_cond_wait(&State4::checkQueue, &State4::addQueue);
+            }
+            statePtr = State4::queue;
+            testsRun += statePtr->testsRun;
+            statePtr->testsRun = 0;
+            statePtr->a = a;
+            statePtr->b = b;
+            statePtr->c = c;
+            statePtr->d = d;
+            statePtr->done = false;
+            State4::queue = NULL;
+            for (int index = 0; index < maxThreads; ++index) {
+                if (threadState[index].done) {
+                    State4::queue = &threadState[index];
+                }
+            }
+            if (debugThreads) SkDebugf("%s %d init done=%d last=%d queued=%d\n", __FUNCTION__,
+                    statePtr->index, statePtr->done, statePtr->last,
+                    State4::queue ? State4::queue->index : -1);
+            pthread_cond_signal(&statePtr->initialized);
+        }
+        pthread_mutex_unlock(&State4::addQueue);
+    } else {
+        State4 state;
+        state.a = a;
+        state.b = b;
+        state.c = c;
+        state.d = d;
+        (*testFun)(&state);
+        testsRun++;
     }
-    SkDebugf(".");
+    return testsRun;
+}
+
+void initializeTests(const char* test, size_t testNameSize) {
+    testName = test;
+    if (!gRunTestsInOneThread) {
+        int threads = -1;
+        size_t size = sizeof(threads);
+        sysctlbyname("hw.logicalcpu_max", &threads, &size, NULL, 0);
+        if (threads > 0) {
+            maxThreads = threads;
+        } else {
+            maxThreads = 8;
+        }
+    }
+    if (!gRunTestsInOneThread) {
+        SkFILEStream inFile("../../experimental/Intersection/op.htm");
+        if (inFile.isValid()) {
+            SkTDArray<char> inData;
+            inData.setCount(inFile.getLength());
+            size_t inLen = inData.count();
+            inFile.read(inData.begin(), inLen);
+            inFile.setPath(NULL);
+            char* insert = strstr(inData.begin(), marker);   
+            if (insert) {
+                insert += sizeof(marker) - 1;
+                const char* numLoc = insert + 4 /* indent spaces */ + testNameSize - 1;
+                testNumber = atoi(numLoc) + 1;
+            }
+        }
+    }
+    for (int index = 0; index < maxThreads; ++index) {
+        State4* statePtr = &threadState[index];
+        strcpy(statePtr->filename, filename);
+        SkASSERT(statePtr->filename[sizeof(filename) - 7] == 'X');
+        SkASSERT(statePtr->filename[sizeof(filename) - 6] == 'X');
+        statePtr->filename[sizeof(filename) - 7] = '0' + index / 10;
+        statePtr->filename[sizeof(filename) - 6] = '0' + index % 10;
+    }
     threadIndex = 0;
 }
+
+void outputProgress(const State4& state, const char* pathStr) {
+    if (gRunTestsInOneThread) {
+        SkDebugf("%s\n", pathStr);
+    } else {
+        SkFILEWStream outFile(state.filename);
+        if (!outFile.isValid()) {
+            SkASSERT(0);
+            return;
+        }
+        outputToStream(state, pathStr, outFile);
+    }
+}
+
+void outputToStream(const State4& state, const char* pathStr, SkWStream& outFile) {
+    outFile.writeText("<div id=\"");
+    outFile.writeText(testName);
+    outFile.writeDecAsText(testNumber);
+    outFile.writeText("\">\n");
+    outFile.writeText(pathStr);
+    outFile.writeText("</div>\n\n");
+    
+    outFile.writeText(marker);
+    outFile.writeText("    ");
+    outFile.writeText(testName);
+    outFile.writeDecAsText(testNumber);
+    outFile.writeText(",\n\n\n");
+    
+    outFile.writeText("static void ");
+    outFile.writeText(testName);
+    outFile.writeDecAsText(testNumber);
+    outFile.writeText("() {\n    SkPath path;\n");
+    outFile.writeText(pathStr);
+    outFile.writeText("    testSimplifyx(path);\n}\n\n");
+    outFile.writeText("static void (*firstTest)() = ");
+    outFile.writeText(testName);
+    outFile.writeDecAsText(testNumber);
+    outFile.writeText(";\n\n");
+
+    outFile.writeText("static struct {\n");
+    outFile.writeText("    void (*fun)();\n");
+    outFile.writeText("    const char* str;\n");
+    outFile.writeText("} tests[] = {\n");
+    outFile.writeText("    TEST(");
+    outFile.writeText(testName);
+    outFile.writeDecAsText(testNumber);
+    outFile.writeText("),\n");
+    outFile.flush();
+}
+
+bool runNextTestSet(State4& state) {
+    if (gRunTestsInOneThread) {
+        return false;
+    }
+    pthread_mutex_lock(&State4::addQueue);
+    state.done = true;
+    State4::queue = &state;
+    if (debugThreads) SkDebugf("%s %d checkQueue done=%d last=%d\n", __FUNCTION__, state.index,
+        state.done, state.last);
+    pthread_cond_signal(&State4::checkQueue);
+    while (state.done && !state.last) {
+        if (debugThreads) SkDebugf("%s %d done=%d last=%d\n", __FUNCTION__, state.index, state.done, state.last);
+        pthread_cond_wait(&state.initialized, &State4::addQueue);
+    }
+    pthread_mutex_unlock(&State4::addQueue);
+    return !state.last;
+}
+
+int waitForCompletion() {
+    int testsRun = 0;
+    if (!gRunTestsInOneThread) {
+        pthread_mutex_lock(&State4::addQueue);
+        int runningThreads = maxThreads;
+        int index;
+        while (runningThreads > 0) {
+            while (!State4::queue) {
+                if (debugThreads) SkDebugf("%s checkQueue\n", __FUNCTION__);
+                pthread_cond_wait(&State4::checkQueue, &State4::addQueue);
+            }
+            while (State4::queue) {
+                --runningThreads;
+                SkDebugf("•");
+                State4::queue->last = true;
+                State4* next;
+                for (index = 0; index < maxThreads; ++index) {
+                    State4& test = threadState[index];
+                    if (test.done && !test.last) {
+                        next = &test;
+                    }
+                }
+                if (debugThreads) SkDebugf("%s %d next=%d deQueue\n", __FUNCTION__,
+                    State4::queue->index, next ? next->index : -1);
+                pthread_cond_signal(&State4::queue->initialized);
+                State4::queue = next;
+            }
+        }
+        pthread_mutex_unlock(&State4::addQueue);
+        for (index = 0; index < maxThreads; ++index) {
+            pthread_join(threadState[index].threadID, NULL);
+            testsRun += threadState[index].testsRun;
+        }
+        SkDebugf("\n");
+    }
+#ifdef SK_DEBUG
+    gDebugMaxWindSum = SK_MaxS32;
+    gDebugMaxWindValue = SK_MaxS32;
+#endif
+    return testsRun;
+}
diff --git a/experimental/Intersection/Intersection_Tests.cpp b/experimental/Intersection/Intersection_Tests.cpp
index 017f1d1..414b911 100644
--- a/experimental/Intersection/Intersection_Tests.cpp
+++ b/experimental/Intersection/Intersection_Tests.cpp
@@ -7,7 +7,11 @@
 
 void Intersection_Tests() {
     SimplifyNew_Test();
+    Simplify4x4QuadralateralsThreaded_Test();
+    Simplify4x4QuadraticsThreaded_Test();
     Simplify4x4RectsThreaded_Test();
+    SimplifyNondegenerate4x4TrianglesThreaded_Test();
+    SimplifyDegenerate4x4TrianglesThreaded_Test();
     SimplifyFindNext_Test();
     SimplifyFindTop_Test();
     SimplifyAngle_Test();
@@ -35,15 +39,6 @@
     SimplifyQuadralateralPaths_Test();
 
     ActiveEdge_Test();
-#if TEST_QUADS_FIRST
-    Simplify4x4QuadraticsThreaded_Test();
-#endif
-    SimplifyDegenerate4x4TrianglesThreaded_Test();
-    SimplifyNondegenerate4x4TrianglesThreaded_Test();
-    Simplify4x4QuadralateralsThreaded_Test();
-#if !TEST_QUADS_FIRST
-    Simplify4x4QuadraticsThreaded_Test();
-#endif
 
     QuadraticCoincidence_Test();
     QuadraticIntersection_Test();
diff --git a/experimental/Intersection/Simplify.cpp b/experimental/Intersection/Simplify.cpp
index 0b8eccf..9ffa33c 100644
--- a/experimental/Intersection/Simplify.cpp
+++ b/experimental/Intersection/Simplify.cpp
@@ -27,7 +27,7 @@
 
 #define DEBUG_UNUSED 0 // set to expose unused functions
 
-#if 01 // set to 1 for multiple thread -- no debugging
+#if 0 // set to 1 for multiple thread -- no debugging
 
 const bool gRunTestsInOneThread = false;
 
@@ -677,7 +677,6 @@
     int fWindSum; // accumulated from contours surrounding this one
     int fWindValue; // 0 == canceled; 1 == normal; >1 == coincident
     bool fDone; // if set, this span to next higher T has been processed
-    bool fOutside; // if set, sum is outside, sum + sign * value computes inside
 };
 
 class Segment {
@@ -981,7 +980,6 @@
         span->fPt.fX = SK_ScalarNaN;
         span->fWindSum = SK_MinS32;
         span->fWindValue = 1;
-        span->fOutside = false;
         if ((span->fDone = newT == 1)) {
             ++fDoneSpans;
         } 
@@ -1008,6 +1006,7 @@
         int oIndex = other.fTs.count();
         while (other.fTs[--oIndex].fT - oEndT > -FLT_EPSILON)
             ;
+        double tRatio = (oEndT - oStartT) / (endT - startT);
         Span* test = &fTs[index];
         Span* oTest = &other.fTs[oIndex];
         SkTDArray<double> outsideTs;
@@ -1027,7 +1026,12 @@
                 span = &fTs[++index];
             } while (span->fT - testT < FLT_EPSILON);
             Span* oSpan = oTest;
-            do {
+            double otherTMatchStart = oEndT - (span->fT - startT) * tRatio;
+            double otherTMatchEnd = oEndT - (test->fT - startT) * tRatio;
+            SkDEBUGCODE(int originalWindValue = oSpan->fWindValue);
+            while (oSpan->fT > otherTMatchStart - FLT_EPSILON
+                    && otherTMatchEnd - FLT_EPSILON > oSpan->fT) {
+                SkASSERT(originalWindValue == oSpan->fWindValue);
                 if (decrement) {
                     other.decrementSpan(oSpan);
                 } else if (track && oSpan->fT < 1 && testT < 1) {
@@ -1037,11 +1041,11 @@
                     break;
                 }
                 oSpan = &other.fTs[--oIndex];
-            } while (oTestT - oSpan->fT < FLT_EPSILON); 
+            } 
             test = span;
             oTest = oSpan;
         } while (test->fT < endT - FLT_EPSILON);
-        SkASSERT(!oIndex || oTest->fT <= oStartT - FLT_EPSILON);
+        SkASSERT(!oIndex || oTest->fT < oStartT + FLT_EPSILON);
         // FIXME: determine if canceled edges need outside ts added
         if (!done() && outsideTs.count()) {
             double tStart = outsideTs[0];
@@ -1075,6 +1079,7 @@
         while (oStartT - other.fTs[oIndex].fT >= FLT_EPSILON) {
             ++oIndex;
         }
+        double tRatio = (oEndT - oStartT) / (endT - startT);
         Span* test = &fTs[index];
         Span* oTest = &other.fTs[oIndex];
         SkTDArray<double> outsideTs;
@@ -1092,7 +1097,7 @@
             do {
                 if (transfer) {
                     if (decrementOther) {
-                        SkASSERT(abs(end->fWindValue) <= gDebugMaxWindValue);
+                        SkASSERT(abs(end->fWindValue) < gDebugMaxWindValue);
                         ++(end->fWindValue);
                     } else if (decrementSpan(end)) {
                         TrackOutside(outsideTs, end->fT, oStartT);
@@ -1105,11 +1110,16 @@
                 }
                 end = &fTs[++index];
             } while (end->fT - test->fT < FLT_EPSILON);
+        // because of the order in which coincidences are resolved, this and other
+        // may not have the same intermediate points. Compute the corresponding
+        // intermediate T values (using this as the master, other as the follower)
+        // and walk other conditionally -- hoping that it catches up in the end
+            double otherTMatch = (test->fT - startT) * tRatio + oStartT;
             Span* oEnd = oTest;
-            do {
+            while (oEnd->fT < oEndT - FLT_EPSILON && oEnd->fT - otherTMatch < FLT_EPSILON) {
                 if (transfer) {
                     if (!decrementOther) {
-                        SkASSERT(abs(oEnd->fWindValue) <= gDebugMaxWindValue);
+                        SkASSERT(abs(oEnd->fWindValue) < gDebugMaxWindValue);
                         ++(oEnd->fWindValue);
                     } else if (other.decrementSpan(oEnd)) {
                         TrackOutside(oOutsideTs, oEnd->fT, startT);
@@ -1121,7 +1131,7 @@
                     }
                 }
                 oEnd = &other.fTs[++oIndex];
-            } while (oEnd->fT - oTest->fT < FLT_EPSILON);
+            }
             test = end;
             oTest = oEnd;
         } while (test->fT < endT - FLT_EPSILON);
@@ -1261,8 +1271,8 @@
         int spanWinding = base->spanSign(angle);
         bool inner = useInnerWinding(winding + spanWinding, winding);
     #if DEBUG_WINDING
-        SkDebugf("%s --- spanWinding=%d winding=%d sign=%d inner=%d outside=%d result=%d\n", __FUNCTION__,
-            spanWinding, winding, angle->sign(), inner, base->spanOutside(angle->start(), angle->end()),
+        SkDebugf("%s --- spanWinding=%d winding=%d sign=%d inner=%d result=%d\n", __FUNCTION__,
+            spanWinding, winding, angle->sign(), inner,
             inner ? winding + spanWinding : winding);
     #endif
         if (inner) {
@@ -1283,11 +1293,10 @@
             int maxWinding = winding;
             winding -= segment->spanSign(angle);
             if (segment->windSum(angle) == SK_MinS32) {
-                bool inside = useInnerWinding(maxWinding, winding);
-                if (inside) {
+                if (useInnerWinding(maxWinding, winding)) {
                     maxWinding = winding;
                 }
-                segment->markAndChaseWinding(angle, maxWinding, !inside);
+                segment->markAndChaseWinding(angle, maxWinding);
             }
         } while (++nextIndex != lastIndex);
         return windSum(SkMin32(startIndex, endIndex));
@@ -1323,7 +1332,7 @@
             SkPoint pt;
             double foundT = intersections.fT[0][0];
             (*SegmentXYAtT[fVerb])(fPts, foundT, &pt);
-            if (bestY < pt.fY) {
+            if (bestY < pt.fY && pt.fY < basePt.fY) {
                 bestY = pt.fY;
                 bestT = foundT < 1 ? start : end;
                 hitT = fTs[start].fT + (fTs[end].fT - fTs[start].fT) * foundT;
@@ -1422,8 +1431,7 @@
         SkDebugf("%s winding=%d spanWinding=%d outerWinding=%d innerWinding=%d\n",
                 __FUNCTION__, winding, spanWinding, outerWinding, innerWinding);
     #endif
-        bool inside = useInnerWinding(outerWinding, innerWinding);
-        if (inside) {
+        if (useInnerWinding(outerWinding, innerWinding)) {
             outerWinding = innerWinding;
         }
         SkASSERT(startIndex != endIndex);
@@ -1441,7 +1449,7 @@
     #if DEBUG_WINDING
             SkDebugf("%s simple\n", __FUNCTION__);
     #endif
-            markDone(SkMin32(startIndex, endIndex), outerWinding, !inside);
+            markDone(SkMin32(startIndex, endIndex), outerWinding);
             other = endSpan->fOther;
             nextStart = endSpan->fOtherIndex;
             double startT = other->fTs[nextStart].fT;
@@ -1502,10 +1510,10 @@
             }
             if (!sumWinding) {
                 if (!active) {
-                    markDone(SkMin32(startIndex, endIndex), outerWinding, !inside);
+                    markDone(SkMin32(startIndex, endIndex), outerWinding);
                     // FIXME: seems like a bug that this isn't calling userInnerWinding
                     nextSegment->markWinding(SkMin32(nextAngle->start(),
-                                nextAngle->end()), maxWinding, true);
+                                nextAngle->end()), maxWinding);
     #if DEBUG_WINDING
                     SkDebugf("%s inactive\n", __FUNCTION__);
     #endif
@@ -1561,15 +1569,14 @@
             // as done, record the winding value, and mark connected unambiguous
             // segments as well.
             if (nextSegment->windSum(nextAngle) == SK_MinS32) {
-                bool inside = useInnerWinding(maxWinding, sumWinding);
-                if (inside) {
+                if (useInnerWinding(maxWinding, sumWinding)) {
                     maxWinding = sumWinding;
                 }
                 Span* last;
                 if (foundAngle) {
-                    last = nextSegment->markAndChaseWinding(nextAngle, maxWinding, !inside);
+                    last = nextSegment->markAndChaseWinding(nextAngle, maxWinding);
                 } else {
-                    last = nextSegment->markAndChaseDone(nextAngle, maxWinding, !inside);
+                    last = nextSegment->markAndChaseDone(nextAngle, maxWinding);
                 }
                 if (last) {
                     *chase.append() = last;
@@ -1577,7 +1584,7 @@
             }
         } while (++nextIndex != lastIndex);
         SkASSERT(sorted[firstIndex]->segment() == this);
-        markDone(SkMin32(startIndex, endIndex), outerWinding, !inside);
+        markDone(SkMin32(startIndex, endIndex), outerWinding);
         if (!foundAngle) {
             return NULL;
         }
@@ -1806,7 +1813,7 @@
     }
     
     // OPTIMIZATION: uses tail recursion. Unwise?
-    Span* innerChaseDone(int index, int step, int winding, bool outside) {
+    Span* innerChaseDone(int index, int step, int winding) {
         int end = nextSpan(index, step);
         SkASSERT(end >= 0);
         if (multipleSpans(end)) {
@@ -1816,12 +1823,12 @@
         Segment* other = endSpan.fOther;
         index = endSpan.fOtherIndex;
         int otherEnd = other->nextSpan(index, step);
-        Span* last = other->innerChaseDone(index, step, winding, outside);
-        other->markDone(SkMin32(index, otherEnd), winding, outside);
+        Span* last = other->innerChaseDone(index, step, winding);
+        other->markDone(SkMin32(index, otherEnd), winding);
         return last;
     }
     
-    Span* innerChaseWinding(int index, int step, int winding, bool outside) {
+    Span* innerChaseWinding(int index, int step, int winding) {
         int end = nextSpan(index, step);
         SkASSERT(end >= 0);
         if (multipleSpans(end)) {
@@ -1836,8 +1843,8 @@
             SkASSERT(other->fTs[min].fWindSum == winding);
             return NULL;
         }
-        Span* last = other->innerChaseWinding(index, step, winding, outside);
-        other->markWinding(min, winding, outside);
+        Span* last = other->innerChaseWinding(index, step, winding);
+        other->markWinding(min, winding);
         return last;
     }
     
@@ -1914,22 +1921,22 @@
     // this span is excluded by the winding rule -- chase the ends
     // as long as they are unambiguous to mark connections as done
     // and give them the same winding value
-    Span* markAndChaseDone(const Angle* angle, int winding, bool outside) {
+    Span* markAndChaseDone(const Angle* angle, int winding) {
         int index = angle->start();
         int endIndex = angle->end();
         int step = SkSign32(endIndex - index);
-        Span* last = innerChaseDone(index, step, winding, outside);
-        markDone(SkMin32(index, endIndex), winding, outside);
+        Span* last = innerChaseDone(index, step, winding);
+        markDone(SkMin32(index, endIndex), winding);
         return last;
     }
     
-    Span* markAndChaseWinding(const Angle* angle, int winding, bool outside) {
+    Span* markAndChaseWinding(const Angle* angle, int winding) {
         int index = angle->start();
         int endIndex = angle->end();
         int min = SkMin32(index, endIndex);
         int step = SkSign32(endIndex - index);
-        Span* last = innerChaseWinding(index, step, winding, outside);
-        markWinding(min, winding, outside);
+        Span* last = innerChaseWinding(index, step, winding);
+        markWinding(min, winding);
         return last;
     }
     
@@ -1938,7 +1945,7 @@
     // wastes time, it shouldn't do any more than spin through the T spans.
     // OPTIMIZATION: abort on first done found (assuming that this code is 
     // always called to mark segments done).
-    void markDone(int index, int winding, bool outside) {
+    void markDone(int index, int winding) {
       //  SkASSERT(!done());
         double referenceT = fTs[index].fT;
         int lesser = index;
@@ -1954,7 +1961,6 @@
             SkASSERT(span.fWindSum == SK_MinS32 || span.fWindSum == winding);
             SkASSERT(abs(winding) <= gDebugMaxWindSum);
             span.fWindSum = winding;
-            span.fOutside = outside;
             fDoneSpans++;
         }
         do {
@@ -1970,12 +1976,11 @@
             SkASSERT(span.fWindSum == SK_MinS32 || span.fWindSum == winding);
             SkASSERT(abs(winding) <= gDebugMaxWindSum);
             span.fWindSum = winding;
-            span.fOutside = outside;
             fDoneSpans++;
         } while (++index < fTs.count() && fTs[index].fT - referenceT < FLT_EPSILON);
     }
 
-    void markWinding(int index, int winding, bool outside) {
+    void markWinding(int index, int winding) {
     //    SkASSERT(!done());
         double referenceT = fTs[index].fT;
         int lesser = index;
@@ -1991,7 +1996,6 @@
             SkASSERT(span.fWindSum == SK_MinS32 || span.fWindSum == winding);
             SkASSERT(abs(winding) <= gDebugMaxWindSum);
             span.fWindSum = winding;
-            span.fOutside = outside;
         }
         do {
             Span& span = fTs[index];
@@ -2006,7 +2010,6 @@
         #endif
             SkASSERT(abs(winding) <= gDebugMaxWindSum);
             span.fWindSum = winding;
-            span.fOutside = outside;
         } while (++index < fTs.count() && fTs[index].fT - referenceT < FLT_EPSILON);
     }
 
@@ -2083,10 +2086,6 @@
         return fTs[tIndex];
     }
     
-    const bool spanOutside(int startIndex, int endIndex) const {
-        return fTs[SkMin32(startIndex, endIndex)].fOutside;
-    }
-    
     int spanSign(int startIndex, int endIndex) const {
         int result = startIndex < endIndex ? -fTs[startIndex].fWindValue :
                 fTs[endIndex].fWindValue;
@@ -2711,9 +2710,9 @@
                 complete();
                 if (!fCurrentContour) {
                     fCurrentContour = fContours.push_back_n(1);
-                    finalCurveEnd = pointsPtr++;
                     *fExtra.append() = -1; // start new contour
                 }
+                finalCurveEnd = pointsPtr++;
                 continue;
             case SkPath::kLine_Verb:
                 // skip degenerate points
@@ -3240,6 +3239,13 @@
             end = test->nextSpan(tIndex, -1);
         }
         test->addTwoAngles(end, tIndex, angles);
+        SkASSERT(angles.count() > 0);
+        if (angles[0].segment()->yAtT(angles[0].start()) >= basePt.fY) {
+#if DEBUG_SORT
+            SkDebugf("%s *** early return\n", __FUNCTION__);
+#endif
+            return 0;
+        }
         test->buildAngles(tIndex, angles);
         SkTDArray<Angle*> sorted;
         // OPTIMIZATION: call a sort that, if base point is the leftmost, 
@@ -3259,7 +3265,7 @@
         int right = -1;
         bool baseMatches = test->yAtT(tIndex) == basePt.fY;
         for (int index = 0; index < count; ++index) {
-            const Angle* angle = sorted[index];
+            angle = sorted[index];
             if (baseMatches && angle->isHorizontal()) {
                 continue;
             }
@@ -3268,6 +3274,17 @@
                 left = index;
             } else if (indexDx > 0) {
                 right = index;
+                int previous = index - 1;
+                if (previous < 0) {
+                    previous = count - 1;
+                }
+                const Angle* prev = sorted[previous];
+                if (prev->dy() >= 0 && prev->dx() > 0 && angle->dy() < 0) {
+#if DEBUG_SORT
+                    SkDebugf("%s use prev\n", __FUNCTION__);
+#endif
+                    right = previous;
+                }
                 break;
             } else {
                 mid = index;
@@ -3427,11 +3444,10 @@
             // FIXME: this be wrong. assign startWinding if edge is in
             // same direction. If the direction is opposite, winding to
             // assign is flipped sign or +/- 1?
-                bool inside = useInnerWinding(maxWinding, winding);
-                if (inside) {
+                if (useInnerWinding(maxWinding, winding)) {
                     maxWinding = winding;
                 }
-                segment->markWinding(lesser, maxWinding, !inside);
+                segment->markWinding(lesser, maxWinding);
 #endif
                 break;
             }
@@ -3495,9 +3511,9 @@
                     contourWinding -= spanWinding;
                 }
 #if DEBUG_WINDING
-                SkDebugf("%s --- sumWinding=%d spanWinding=%d sign=%d inner=%d outside=%d result=%d\n", __FUNCTION__,
+                SkDebugf("%s --- sumWinding=%d spanWinding=%d sign=%d inner=%d result=%d\n", __FUNCTION__,
                         sumWinding, spanWinding, SkSign32(index - endIndex), 
-                        inner, current->spanOutside(index, endIndex), contourWinding);
+                        inner, contourWinding);
 #endif
             }
 #if DEBUG_WINDING
@@ -3561,11 +3577,10 @@
             bool inner = useInnerWinding(winding - spanWinding, winding);
         #if DEBUG_WINDING
             SkDebugf("%s --- id=%d t=%1.9g spanWinding=%d winding=%d sign=%d"
-                    " inner=%d outside=%d result=%d\n",
+                    " inner=%d result=%d\n",
                     __FUNCTION__, current->debugID(), current->t(lesser),
                     spanWinding, winding, SkSign32(index - endIndex),
                     useInnerWinding(winding - spanWinding, winding),
-                    current->spanOutside(index, endIndex),
                     inner ? winding - spanWinding : winding);
         #endif
             if (inner) {
diff --git a/experimental/Intersection/SimplifyNew_Test.cpp b/experimental/Intersection/SimplifyNew_Test.cpp
index 74e78f5..3d21908 100644
--- a/experimental/Intersection/SimplifyNew_Test.cpp
+++ b/experimental/Intersection/SimplifyNew_Test.cpp
@@ -12,7 +12,7 @@
 #define TEST(name) { name, #name }
 
 static void testLine1() {
-    SkPath path, simple;
+    SkPath path;
     path.moveTo(2,0);
     path.lineTo(1,1);
     path.lineTo(0,0);
@@ -49,49 +49,49 @@
 }
 
 static void testLine2() {
-    SkPath path, simple;
+    SkPath path;
     addInnerCWTriangle(path);
     addOuterCWTriangle(path);
     testSimplifyx(path);
 }
 
 static void testLine3() {
-    SkPath path, simple;
+    SkPath path;
     addInnerCCWTriangle(path);
     addOuterCWTriangle(path);
     testSimplifyx(path);
 }
 
 static void testLine3a() {
-    SkPath path, simple;
+    SkPath path;
     addInnerCWTriangle(path);
     addOuterCCWTriangle(path);
     testSimplifyx(path);
 }
 
 static void testLine3b() {
-    SkPath path, simple;
+    SkPath path;
     addInnerCCWTriangle(path);
     addOuterCCWTriangle(path);
     testSimplifyx(path);
 }
 
 static void testLine4() {
-    SkPath path, simple;
+    SkPath path;
     addOuterCCWTriangle(path);
     addOuterCWTriangle(path);
     testSimplifyx(path);
 }
 
 static void testLine5() {
-    SkPath path, simple;
+    SkPath path;
     addOuterCWTriangle(path);
     addOuterCWTriangle(path);
     testSimplifyx(path);
 }
 
 static void testLine6() {
-    SkPath path, simple;
+    SkPath path;
     path.moveTo(0,0);
     path.lineTo(4,0);
     path.lineTo(2,2);
@@ -104,7 +104,7 @@
 }
 
 static void testLine7() {
-    SkPath path, simple;
+    SkPath path;
     path.moveTo(0,0);
     path.lineTo(4,0);
     path.lineTo(2,2);
@@ -117,7 +117,7 @@
 }
 
 static void testLine7a() {
-    SkPath path, simple;
+    SkPath path;
     path.moveTo(0,0);
     path.lineTo(4,0);
     path.lineTo(2,2);
@@ -126,7 +126,7 @@
 }
 
 static void testLine7b() {
-    SkPath path, simple;
+    SkPath path;
     path.moveTo(0,0);
     path.lineTo(4,0);
     path.close();
@@ -138,7 +138,7 @@
 }
 
 static void testLine8() {
-    SkPath path, simple;
+    SkPath path;
     path.moveTo(0,4);
     path.lineTo(4,4);
     path.lineTo(2,2);
@@ -151,7 +151,7 @@
 }
 
 static void testLine9() {
-    SkPath path, simple;
+    SkPath path;
     path.moveTo(0,4);
     path.lineTo(4,4);
     path.lineTo(2,2);
@@ -164,7 +164,7 @@
 }
 
 static void testLine10() {
-    SkPath path, simple;
+    SkPath path;
     path.moveTo(0,4);
     path.lineTo(4,4);
     path.lineTo(2,2);
@@ -177,7 +177,7 @@
 }
 
 static void testLine10a() {
-    SkPath path, simple;
+    SkPath path;
     path.moveTo(0,4);
     path.lineTo(8,4);
     path.lineTo(4,0);
@@ -218,90 +218,90 @@
 }
 
 static void testLine11() {
-    SkPath path, simple;
+    SkPath path;
     addCWContainer(path);
     addCWContents(path);
     testSimplifyx(path);
 }
 
 static void testLine12() {
-    SkPath path, simple;
+    SkPath path;
     addCCWContainer(path);
     addCWContents(path);
     testSimplifyx(path);
 }
 
 static void testLine13() {
-    SkPath path, simple;
+    SkPath path;
     addCWContainer(path);
     addCCWContents(path);
     testSimplifyx(path);
 }
 
 static void testLine14() {
-    SkPath path, simple;
+    SkPath path;
     addCCWContainer(path);
     addCCWContents(path);
     testSimplifyx(path);
 }
 
 static void testLine15() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(0, 0, 9, 9, (SkPath::Direction) 0);
     testSimplifyx(path);
 }
 
 static void testLine16() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(0, 0, 12, 12, (SkPath::Direction) 0);
     path.addRect(0, 4, 9, 9, (SkPath::Direction) 0);
     testSimplifyx(path);
 }
 
 static void testLine17() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(0, 0, 12, 12, (SkPath::Direction) 0);
     path.addRect(4, 12, 13, 13, (SkPath::Direction) 0);
     testSimplifyx(path);
 }
 
 static void testLine18() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(0, 0, 12, 12, (SkPath::Direction) 0);
     path.addRect(12, 4, 21, 21, (SkPath::Direction) 0);
     testSimplifyx(path);
 }
 
 static void testLine19() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(0, 0, 12, 12, (SkPath::Direction) 0);
     path.addRect(12, 16, 21, 21, (SkPath::Direction) 0);    
     testSimplifyx(path);
 }
 
 static void testLine20() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(0, 12, 12, 12, (SkPath::Direction) 0);
     path.addRect(0, 12, 9, 9, (SkPath::Direction) 0);
     testSimplifyx(path);
 }
 
 static void testLine21() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(0, 12, 12, 12, (SkPath::Direction) 0);
     path.addRect(0, 16, 9, 9, (SkPath::Direction) 0);
     testSimplifyx(path);
 }
 
 static void testLine22() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(0, 12, 12, 12, (SkPath::Direction) 0);
     path.addRect(4, 12, 13, 13, (SkPath::Direction) 0);
     testSimplifyx(path);
 }
 
 static void testLine23() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(0, 12, 12, 12, (SkPath::Direction) 0);
     path.addRect(12, 0, 21, 21, (SkPath::Direction) 0);
     testSimplifyx(path);
@@ -310,7 +310,7 @@
 
 
 static void testLine24a() {
-    SkPath path, simple;
+    SkPath path;
     path.moveTo(2,0);
     path.lineTo(4,4);
     path.lineTo(0,4);
@@ -323,49 +323,49 @@
 }
 
 static void testLine24() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(0, 18, 12, 12, (SkPath::Direction) 0);
     path.addRect(4, 12, 13, 13, (SkPath::Direction) 0);
     testSimplifyx(path);
 }
 
 static void testLine25() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(0, 6, 12, 12, (SkPath::Direction) 0);
     path.addRect(12, 0, 21, 21, (SkPath::Direction) 0);
     testSimplifyx(path);
 }
 
 static void testLine26() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(0, 18, 12, 12, (SkPath::Direction) 0);
     path.addRect(0, 12, 9, 9, (SkPath::Direction) 0);
     testSimplifyx(path);
 }
 
 static void testLine27() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(0, 18, 12, 12, (SkPath::Direction) 0);
     path.addRect(12, 8, 21, 21, (SkPath::Direction) 0);
     testSimplifyx(path);
 }
 
 static void testLine28() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(0, 6, 12, 12, (SkPath::Direction) 0);
     path.addRect(0, 0, 9, 9, (SkPath::Direction) 0);
     testSimplifyx(path);
 }
 
 static void testLine29() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(0, 18, 12, 12, (SkPath::Direction) 0);
     path.addRect(12, 12, 21, 21, (SkPath::Direction) 0);
     testSimplifyx(path);
 }
 
 static void testLine30() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(0, 0, 20, 20, (SkPath::Direction) 0);
     path.addRect(0, 0, 12, 12, (SkPath::Direction) 0);
     path.addRect(4, 4, 13, 13, (SkPath::Direction) 0);
@@ -373,7 +373,7 @@
 }
 
 static void testLine31() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(0, 0, 20, 20, (SkPath::Direction) 0);
     path.addRect(0, 0, 12, 12, (SkPath::Direction) 0);
     path.addRect(0, 4, 9, 9, (SkPath::Direction) 0);
@@ -381,7 +381,7 @@
 }
 
 static void testLine32() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(0, 0, 20, 20, (SkPath::Direction) 0);
     path.addRect(0, 0, 12, 12, (SkPath::Direction) 0);
     path.addRect(4, 12, 13, 13, (SkPath::Direction) 0);
@@ -389,7 +389,7 @@
 }
 
 static void testLine33() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(0, 0, 20, 20, (SkPath::Direction) 0);
     path.addRect(0, 0, 12, 12, (SkPath::Direction) 0);
     path.addRect(4, 16, 13, 13, (SkPath::Direction) 0);
@@ -397,7 +397,7 @@
 }
 
 static void testLine34() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(0, 0, 20, 20, (SkPath::Direction) 0);
     path.addRect(0, 6, 12, 12, (SkPath::Direction) 0);
     path.addRect(4, 12, 13, 13, (SkPath::Direction) 0);
@@ -405,7 +405,7 @@
 }
 
 static void testLine35() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(0, 0, 20, 20, (SkPath::Direction) 0);
     path.addRect(6, 0, 18, 18, (SkPath::Direction) 0);
     path.addRect(4, 16, 13, 13, (SkPath::Direction) 0);
@@ -413,7 +413,7 @@
 }
 
 static void testLine36() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(0, 10, 20, 20, (SkPath::Direction) 0);
     path.addRect(6, 12, 18, 18, (SkPath::Direction) 0);
     path.addRect(4, 16, 13, 13, (SkPath::Direction) 0);
@@ -421,7 +421,7 @@
 }
 
 static void testLine37() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(0, 20, 20, 20, (SkPath::Direction) 0);
     path.addRect(18, 24, 30, 30, (SkPath::Direction) 0);
     path.addRect(0, 0, 9, 9, (SkPath::Direction) 0);
@@ -429,7 +429,7 @@
 }
 
 static void testLine38() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(10, 0, 30, 30, (SkPath::Direction) 0);
     path.addRect(6, 12, 18, 18, (SkPath::Direction) 0);
     path.addRect(12, 12, 21, 21, (SkPath::Direction) 0);
@@ -437,7 +437,7 @@
 }
 
 static void testLine40() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(10, 0, 30, 30, (SkPath::Direction) 0);
     path.addRect(12, 18, 24, 24, (SkPath::Direction) 0);
     path.addRect(4, 16, 13, 13, (SkPath::Direction) 0);
@@ -445,7 +445,7 @@
 }
 
 static void testLine41() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(0, 0, 20, 20, (SkPath::Direction) 0);
     path.addRect(18, 24, 30, 30, (SkPath::Direction) 0);
     path.addRect(12, 0, 21, 21, (SkPath::Direction) 0);
@@ -453,7 +453,7 @@
 }
 
 static void testLine42() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(0, 0, 20, 20, (SkPath::Direction) 0);
     path.addRect(0, 0, 12, 12, (SkPath::Direction) 0);
     path.addRect(8, 16, 17, 17, (SkPath::Direction) 0);
@@ -461,7 +461,7 @@
 }
 
 static void testLine43() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(0, 0, 20, 20, (SkPath::Direction) 0);
     path.addRect(6, 24, 18, 18, (SkPath::Direction) 0);
     path.addRect(0, 32, 9, 36, (SkPath::Direction) 1);
@@ -469,7 +469,7 @@
 }
 
 static void testLine44() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(10, 40, 30, 30, (SkPath::Direction) 0);
     path.addRect(18, 0, 30, 30, (SkPath::Direction) 0);
     path.addRect(18, 32, 27, 36, (SkPath::Direction) 1);
@@ -477,7 +477,7 @@
 }
 
 static void testLine45() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(10, 0, 30, 30, (SkPath::Direction) 0);
     path.addRect(18, 0, 30, 30, (SkPath::Direction) 0);
     path.addRect(24, 32, 33, 36, (SkPath::Direction) 0);
@@ -485,7 +485,7 @@
 }
 
 static void testLine46() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(10, 40, 30, 30, (SkPath::Direction) 0);
     path.addRect(24, 0, 36, 36, (SkPath::Direction) 0);
     path.addRect(24, 32, 33, 36, (SkPath::Direction) 0);
@@ -493,7 +493,7 @@
 }
 
 static void testLine47() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(0, 0, 20, 20, (SkPath::Direction) 0);
     path.addRect(0, 0, 12, 12, (SkPath::Direction) 0);
     path.addRect(0, 0, 9, 9, (SkPath::Direction) 1);
@@ -501,7 +501,7 @@
 }
 
 static void testLine48() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(0, 0, 20, 20, (SkPath::Direction) 0);
     path.addRect(0, 6, 12, 12, (SkPath::Direction) 0);
     path.addRect(0, 0, 9, 9, (SkPath::Direction) 1);
@@ -509,7 +509,7 @@
 }
 
 static void testLine49() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(0, 0, 20, 20, (SkPath::Direction) 0);
     path.addRect(0, 0, 12, 12, (SkPath::Direction) 0);
     path.addRect(0, 0, 9, 9, (SkPath::Direction) 0);
@@ -517,7 +517,7 @@
 }
 
 static void testLine50() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(10, 30, 30, 30, (SkPath::Direction) 0);
     path.addRect(24, 20, 36, 30, (SkPath::Direction) 0);
     testSimplifyx(path);
@@ -525,7 +525,7 @@
 
 
 static void testLine51() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(0, 0, 20, 20, (SkPath::Direction) 0);
     path.addRect(0, 12, 12, 12, (SkPath::Direction) 0);
     path.addRect(4, 12, 13, 13, (SkPath::Direction) 1);
@@ -533,7 +533,7 @@
 }
 
 static void testLine52() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(0, 30, 20, 20, (SkPath::Direction) 0);
     path.addRect(6, 20, 18, 30, (SkPath::Direction) 0);
     path.addRect(32, 0, 36, 41, (SkPath::Direction) 0);
@@ -541,7 +541,7 @@
 }
 
 static void testLine53() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(10, 30, 30, 30, (SkPath::Direction) 0);
     path.addRect(12, 20, 24, 30, (SkPath::Direction) 0);
     path.addRect(12, 32, 21, 36, (SkPath::Direction) 1);
@@ -549,7 +549,7 @@
 }
 
 static void testLine54() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(0, 0, 20, 20, (SkPath::Direction) 0);
     path.addRect(6, 0, 18, 18, (SkPath::Direction) 0);
     path.addRect(8, 4, 17, 17, (SkPath::Direction) 1);
@@ -557,7 +557,7 @@
 }
 
 static void testLine55() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(0, 0, 20, 20, (SkPath::Direction) 0);
     path.addRect(6, 6, 18, 18, (SkPath::Direction) 0);
     path.addRect(4, 4, 13, 13, (SkPath::Direction) 1);
@@ -565,7 +565,7 @@
 }
 
 static void testLine56() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(0, 20, 20, 20, (SkPath::Direction) 0);
     path.addRect(18, 20, 30, 30, (SkPath::Direction) 0);
     path.addRect(12, 0, 21, 21, (SkPath::Direction) 1);
@@ -573,7 +573,7 @@
 }
 
 static void testLine57() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(20, 0, 40, 40, (SkPath::Direction) 0);
     path.addRect(20, 0, 30, 40, (SkPath::Direction) 0);
     path.addRect(12, 0, 21, 21, (SkPath::Direction) 1);
@@ -581,7 +581,7 @@
 }
 
 static void testLine58() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(0, 0, 20, 20, (SkPath::Direction) 0);
     path.addRect(0, 0, 12, 12, (SkPath::Direction) 1);
     path.addRect(0, 12, 9, 9, (SkPath::Direction) 1);
@@ -589,7 +589,7 @@
 }
 
 static void testLine59() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(0, 0, 20, 20, (SkPath::Direction) 0);
     path.addRect(6, 6, 18, 18, (SkPath::Direction) 1);
     path.addRect(4, 4, 13, 13, (SkPath::Direction) 1);
@@ -597,7 +597,7 @@
 }
 
 static void testLine60() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(0, 0, 20, 20, (SkPath::Direction) 0);
     path.addRect(6, 12, 18, 18, (SkPath::Direction) 1);
     path.addRect(4, 12, 13, 13, (SkPath::Direction) 1);
@@ -605,7 +605,7 @@
 }
 
 static void testLine61() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(0, 0, 20, 20, (SkPath::Direction) 0);
     path.addRect(12, 0, 24, 24, (SkPath::Direction) 1);
     path.addRect(12, 0, 21, 21, (SkPath::Direction) 1);
@@ -613,7 +613,7 @@
 }
 
 static void testLine62() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(0, 0, 60, 60, (SkPath::Direction) 0);
     path.addRect(0, 0, 20, 20, (SkPath::Direction) 0);
     path.addRect(0, 12, 12, 12, (SkPath::Direction) 0);
@@ -622,7 +622,7 @@
 }
 
 static void testLine63() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(0, 0, 60, 60, (SkPath::Direction) 0);
     path.addRect(0, 10, 20, 20, (SkPath::Direction) 0);
     path.addRect(0, 6, 12, 12, (SkPath::Direction) 1);
@@ -631,7 +631,7 @@
 }
 
 static void testLine64() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(0, 0, 60, 60, (SkPath::Direction) 0);
     path.addRect(10, 40, 30, 30, (SkPath::Direction) 0);
     path.addRect(18, 6, 30, 30, (SkPath::Direction) 0);
@@ -639,7 +639,7 @@
 }
 
 static void testLine65() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(0, 0, 60, 60, (SkPath::Direction) 0);
     path.addRect(10, 0, 30, 30, (SkPath::Direction) 0);
     path.addRect(24, 0, 36, 36, (SkPath::Direction) 0);
@@ -648,7 +648,7 @@
 }
 
 static void testLine66() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(0, 0, 60, 60, (SkPath::Direction) 0);
     path.addRect(0, 30, 20, 20, (SkPath::Direction) 0);
     path.addRect(12, 20, 24, 30, (SkPath::Direction) 0);
@@ -656,7 +656,7 @@
 }
 
 static void testLine67() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(0, 0, 60, 60, (SkPath::Direction) 0);
     path.addRect(10, 40, 30, 30, (SkPath::Direction) 0);
     path.addRect(24, 20, 36, 30, (SkPath::Direction) 0);
@@ -665,7 +665,7 @@
 }
 
 static void testLine68a() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(0, 0, 8, 8, (SkPath::Direction) 0);
     path.addRect(2, 2, 6, 6, (SkPath::Direction) 0);
     path.addRect(1, 2, 4, 2, (SkPath::Direction) 0);
@@ -673,7 +673,7 @@
 }
 
 static void testLine68b() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(0, 0, 8, 8, (SkPath::Direction) 0);
     path.addRect(2, 2, 6, 6, (SkPath::Direction) 1);
     path.addRect(1, 2, 2, 2, (SkPath::Direction) 0);
@@ -681,7 +681,7 @@
 }
 
 static void testLine68c() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(0, 0, 8, 8, (SkPath::Direction) 1);
     path.addRect(2, 2, 6, 6, (SkPath::Direction) 0);
     path.addRect(1, 2, 4, 2, (SkPath::Direction) 0);
@@ -689,7 +689,7 @@
 }
 
 static void testLine68d() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(0, 0, 8, 8, (SkPath::Direction) 1);
     path.addRect(2, 2, 6, 6, (SkPath::Direction) 1);
     path.addRect(1, 2, 4, 2, (SkPath::Direction) 0);
@@ -697,7 +697,7 @@
 }
 
 static void testLine68e() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(0, 0, 8, 8, (SkPath::Direction) 0);
     path.addRect(0, 0, 8, 8, (SkPath::Direction) 0);
     path.addRect(2, 2, 6, 6, (SkPath::Direction) 1);
@@ -706,7 +706,7 @@
 }
 
 static void testLine68f() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(0, 0, 8, 8, (SkPath::Direction) 0);
     path.addRect(2, 2, 6, 6, (SkPath::Direction) 1);
     path.addRect(2, 2, 6, 6, (SkPath::Direction) 1);
@@ -715,7 +715,7 @@
 }
 
 static void testLine68g() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(0, 0, 8, 8, (SkPath::Direction) 0);
     path.addRect(0, 0, 8, 8, (SkPath::Direction) 0);
     path.addRect(2, 2, 6, 6, (SkPath::Direction) 1);
@@ -725,7 +725,7 @@
 }
 
 static void testLine68h() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(0, 0, 8, 8, (SkPath::Direction) 0);
     path.addRect(2, 2, 6, 6, (SkPath::Direction) 1);
     path.addRect(2, 2, 6, 6, (SkPath::Direction) 1);
@@ -735,7 +735,7 @@
 }
 
 static void testLine69() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(0, 20, 20, 20, (SkPath::Direction) 0);
     path.addRect(0, 20, 12, 30, (SkPath::Direction) 0);
     path.addRect(12, 32, 21, 36, (SkPath::Direction) 0);
@@ -743,7 +743,7 @@
 }
 
 static void testLine70() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(0, 0, 20, 20, (SkPath::Direction) 0);
     path.addRect(0, 24, 12, 12, (SkPath::Direction) 0);
     path.addRect(12, 32, 21, 36, (SkPath::Direction) 1);
@@ -751,7 +751,7 @@
 }
 
 static void testLine71() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(0, 0, 20, 20, (SkPath::Direction) 0);
     path.addRect(12, 0, 24, 24, (SkPath::Direction) 0);
     path.addRect(12, 32, 21, 36, (SkPath::Direction) 0);
@@ -759,7 +759,7 @@
 }
 
 static void testLine72() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(0, 0, 60, 60, (SkPath::Direction) 0);
     path.addRect(10, 40, 30, 30, (SkPath::Direction) 0);
     path.addRect(6, 20, 18, 30, (SkPath::Direction) 0);
@@ -767,7 +767,7 @@
 }
 
 static void testLine73() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(0, 0, 60, 60, (SkPath::Direction) 0);
     path.addRect(0, 40, 20, 20, (SkPath::Direction) 0);
     path.addRect(0, 20, 12, 30, (SkPath::Direction) 0);
@@ -776,7 +776,7 @@
 }
 
 static void testLine74() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(20, 30, 40, 40, (SkPath::Direction) 0);
     path.addRect(24, 20, 36, 30, (SkPath::Direction) 1);
     path.addRect(32, 24, 36, 41, (SkPath::Direction) 1);
@@ -784,7 +784,7 @@
 }
 
 static void testLine75() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(0, 0, 60, 60, (SkPath::Direction) 0);
     path.addRect(10, 0, 30, 30, (SkPath::Direction) 1);
     path.addRect(18, 0, 30, 30, (SkPath::Direction) 1);
@@ -793,7 +793,7 @@
 }
 
 static void testLine76() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(36, 0, 66, 60, (SkPath::Direction) 0);
     path.addRect(10, 20, 40, 30, (SkPath::Direction) 0);
     path.addRect(24, 20, 36, 30, (SkPath::Direction) 1);
@@ -802,7 +802,7 @@
 }
 
 static void testLine77() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(20, 0, 40, 40, (SkPath::Direction) 0);
     path.addRect(24, 6, 36, 36, (SkPath::Direction) 1);
     path.addRect(24, 32, 33, 36, (SkPath::Direction) 1);
@@ -810,7 +810,7 @@
 }
 
 static void testLine78() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(0, 0, 30, 60, (SkPath::Direction) 0);
     path.addRect(10, 20, 30, 30, (SkPath::Direction) 1);
     path.addRect(18, 20, 30, 30, (SkPath::Direction) 1);
@@ -819,7 +819,7 @@
 }
 
 static void testLine79() {
-    SkPath path, simple;
+    SkPath path;
     path.addRect(0, 36, 60, 30, (SkPath::Direction) 0);
     path.addRect(10, 30, 40, 30, (SkPath::Direction) 0);
     path.addRect(0, 20, 12, 30, (SkPath::Direction) 1);
@@ -827,12 +827,156 @@
     testSimplifyx(path);
 }
 
+static void testDegenerate1() {
+    SkPath path;
+    path.moveTo(0, 0);
+    path.lineTo(0, 0);
+    path.lineTo(2, 0);
+    path.close();
+    path.moveTo(0, 0);
+    path.lineTo(1, 0);
+    path.lineTo(2, 0);
+    path.close();
+    testSimplifyx(path);
+}
+
+static void testDegenerate2() {
+    SkPath path;
+    path.moveTo(0, 0);
+    path.lineTo(0, 0);
+    path.lineTo(0, 0);
+    path.close();
+    path.moveTo(0, 0);
+    path.lineTo(1, 0);
+    path.lineTo(0, 1);
+    path.close();
+    testSimplifyx(path);
+}
+
+static void testDegenerate3() {
+    SkPath path;
+    path.moveTo(0, 0);
+    path.lineTo(2, 0);
+    path.lineTo(1, 0);
+    path.close();
+    path.moveTo(0, 0);
+    path.lineTo(0, 0);
+    path.lineTo(3, 0);
+    path.close();
+    testSimplifyx(path);
+}
+
+static void testDegenerate4() {
+    SkPath path;
+    path.moveTo(0, 0);
+    path.lineTo(1, 0);
+    path.lineTo(1, 3);
+    path.close();
+    path.moveTo(1, 0);
+    path.lineTo(1, 1);
+    path.lineTo(1, 2);
+    path.close();
+    testSimplifyx(path);
+}
+
+static void testNondegenerate1() {
+    SkPath path;
+    path.moveTo(0, 0);
+    path.lineTo(3, 0);
+    path.lineTo(1, 3);
+    path.close();
+    path.moveTo(1, 1);
+    path.lineTo(2, 1);
+    path.lineTo(1, 2);
+    path.close();
+    testSimplifyx(path);
+}
+
+static void testNondegenerate2() {
+    SkPath path;
+    path.moveTo(1, 0);
+    path.lineTo(0, 1);
+    path.lineTo(1, 1);
+    path.close();
+    path.moveTo(0, 2);
+    path.lineTo(0, 3);
+    path.lineTo(1, 2);
+    path.close();
+    testSimplifyx(path);
+}
+
+static void testNondegenerate3() {
+    SkPath path;
+    path.moveTo(0, 0);
+    path.lineTo(1, 0);
+    path.lineTo(2, 1);
+    path.close();
+    path.moveTo(0, 1);
+    path.lineTo(1, 1);
+    path.lineTo(0, 2);
+    path.close();
+    testSimplifyx(path);
+}
+
+static void testNondegenerate4() {
+    SkPath path;
+    path.moveTo(1, 0);
+    path.lineTo(0, 1);
+    path.lineTo(1, 2);
+    path.close();
+    path.moveTo(0, 2);
+    path.lineTo(0, 3);
+    path.lineTo(1, 3);
+    path.close();
+    testSimplifyx(path);
+}
+
+static void testQuadralateral5() {
+    SkPath path;
+    path.moveTo(0, 0);
+    path.lineTo(0, 0);
+    path.lineTo(1, 0);
+    path.lineTo(1, 1);
+    path.close();
+    path.moveTo(0, 0);
+    path.lineTo(2, 2);
+    path.lineTo(3, 2);
+    path.lineTo(3, 3);
+    path.close();
+    testSimplifyx(path);
+}
+
+static void testQuadralateral6() {
+    SkPath path;
+    path.moveTo(0, 0);
+    path.lineTo(0, 0);
+    path.lineTo(1, 0);
+    path.lineTo(1, 1);
+    path.close();
+    path.moveTo(1, 0);
+    path.lineTo(2, 0);
+    path.lineTo(0, 2);
+    path.lineTo(2, 2);
+    path.close();
+    testSimplifyx(path);
+}
+
 static void (*firstTest)() = 0;
 
 static struct {
     void (*fun)();
     const char* str;
 } tests[] = {
+    TEST(testQuadralateral6),
+    TEST(testQuadralateral5),
+    TEST(testNondegenerate4),
+    TEST(testNondegenerate3),
+    TEST(testNondegenerate2),
+    TEST(testNondegenerate1),
+    TEST(testDegenerate4),
+    TEST(testDegenerate3),
+    TEST(testDegenerate2),
+    TEST(testDegenerate1),
     TEST(testLine79),
     TEST(testLine78),
     TEST(testLine77),
@@ -968,7 +1112,9 @@
         while (index > 0 && tests[index].fun != firstTest) {
             --index;
         }
+        (*tests[index].fun)();
     }
+    index = testCount - 1;
     bool firstTestComplete = false;
     do {
         SkDebugf("  %s [%s]\n", __FUNCTION__, tests[index].str);
diff --git a/experimental/Intersection/SimplifyRect4x4_Test.cpp b/experimental/Intersection/SimplifyRect4x4_Test.cpp
index 3f8145b..6782d53 100644
--- a/experimental/Intersection/SimplifyRect4x4_Test.cpp
+++ b/experimental/Intersection/SimplifyRect4x4_Test.cpp
@@ -7,15 +7,6 @@
 #include "EdgeWalker_Test.h"
 #include "Intersection_Tests.h"
 #include "ShapeOps.h"
-#include "SkBitmap.h"
-#include "SkCanvas.h"
-#include "SkStream.h"
-#include <assert.h>
-#include <errno.h>
-#include <pthread.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/sysctl.h>
 
 // four rects, of four sizes
 // for 3 smaller sizes, tall, wide
@@ -23,211 +14,151 @@
     // same with x (3 bits, 5 values)
 // not included, square, tall, wide (2 bits)
 // cw or ccw (1 bit)
-static const char marker[] =
-    "</div>\n"
-    "\n"
-    "<script type=\"text/javascript\">\n"
-    "\n"
-    "var testDivs = [\n";
-static const char testLineStr[] = "    testLine";
-#if 0
-static const char filename[] = "../../experimental/Intersection/debugXX.txt";
-#else
-static const char filename[] = "/flash/debug/XX.txt";
-#endif
-static int testNumber;
-
-#define BETTER_THREADS 01
-#define DEBUG_BETTER_THREADS 0
 
 static void* testSimplify4x4RectsMain(void* data)
 {
     SkASSERT(data);
     State4& state = *(State4*) data;
-#if BETTER_THREADS
-    do {
-#endif
     char pathStr[1024]; // gdb: set print elements 400
     bzero(pathStr, sizeof(pathStr));
-    state.testsRun = 0;
-    int aShape = state.a & 0x03;
-    int aCW = state.a >> 2;
-    int bShape = state.b & 0x03;
-    int bCW = state.b >> 2;
-    int cShape = state.c & 0x03;
-    int cCW = state.c >> 2;
-    int dShape = state.d & 0x03;
-    int dCW = state.d >> 2;
-    for (int aXAlign = 0 ; aXAlign < 5; ++aXAlign) {
-    for (int aYAlign = 0 ; aYAlign < 5; ++aYAlign) {
-    for (int bXAlign = 0 ; bXAlign < 5; ++bXAlign) {
-    for (int bYAlign = 0 ; bYAlign < 5; ++bYAlign) {
-    for (int cXAlign = 0 ; cXAlign < 5; ++cXAlign) {
-    for (int cYAlign = 0 ; cYAlign < 5; ++cYAlign) {
-    for (int dXAlign = 0 ; dXAlign < 5; ++dXAlign) {
-    for (int dYAlign = 0 ; dYAlign < 5; ++dYAlign) {
-        SkPath path, out;
-        char* str = pathStr;
-        path.setFillType(SkPath::kWinding_FillType);
-        int l, t, r, b;
-        if (aShape) {
-            switch (aShape) {
-                case 1: // square
-                    l =  0; r = 60;
-                    t =  0; b = 60;
-                    aXAlign = 5;
-                    aYAlign = 5;
-                    break;
-                case 2:
-                    l =  aXAlign * 12;
-                    r =  l + 30; 
-                    t =  0; b = 60;
-                    aYAlign = 5;
-                    break;
-                case 3:
-                    l =  0; r = 60;
-                    t =  aYAlign * 12;
-                    b =  l + 30; 
-                    aXAlign = 5;
-                    break;
+    do {
+        int aShape = state.a & 0x03;
+        int aCW = state.a >> 2;
+        int bShape = state.b & 0x03;
+        int bCW = state.b >> 2;
+        int cShape = state.c & 0x03;
+        int cCW = state.c >> 2;
+        int dShape = state.d & 0x03;
+        int dCW = state.d >> 2;
+        for (int aXAlign = 0 ; aXAlign < 5; ++aXAlign) {
+        for (int aYAlign = 0 ; aYAlign < 5; ++aYAlign)      {
+        for (int bXAlign = 0 ; bXAlign < 5; ++bXAlign)          {
+        for (int bYAlign = 0 ; bYAlign < 5; ++bYAlign)              {
+        for (int cXAlign = 0 ; cXAlign < 5; ++cXAlign)                  {
+        for (int cYAlign = 0 ; cYAlign < 5; ++cYAlign)                      {
+        for (int dXAlign = 0 ; dXAlign < 5; ++dXAlign)                          {
+        for (int dYAlign = 0 ; dYAlign < 5; ++dYAlign)                              {
+            SkPath path, out;
+            char* str = pathStr;
+            path.setFillType(SkPath::kWinding_FillType);
+            int l, t, r, b;
+            if (aShape) {
+                switch (aShape) {
+                    case 1: // square
+                        l =  0; r = 60;
+                        t =  0; b = 60;
+                        aXAlign = 5;
+                        aYAlign = 5;
+                        break;
+                    case 2:
+                        l =  aXAlign * 12;
+                        r =  l + 30; 
+                        t =  0; b = 60;
+                        aYAlign = 5;
+                        break;
+                    case 3:
+                        l =  0; r = 60;
+                        t =  aYAlign * 12;
+                        b =  l + 30; 
+                        aXAlign = 5;
+                        break;
+                }
+                path.addRect(l, t, r, b, (SkPath::Direction) aCW);
+                str += sprintf(str, "    path.addRect(%d, %d, %d, %d,"
+                        " (SkPath::Direction) %d);\n", l, t, r, b, aCW);
+            } else {
+                aXAlign = 5;
+                aYAlign = 5;
             }
-            path.addRect(l, t, r, b, (SkPath::Direction) aCW);
-            str += sprintf(str, "    path.addRect(%d, %d, %d, %d,"
-                    " (SkPath::Direction) %d);\n", l, t, r, b, aCW);
-        } else {
-            aXAlign = 5;
-            aYAlign = 5;
-        }
-        if (bShape) {
-            switch (bShape) {
-                case 1: // square
-                    l =  bXAlign * 10;
-                    r =  l + 20; 
-                    t =  bYAlign * 10;
-                    b =  l + 20; 
-                    break;
-                case 2:
-                    l =  bXAlign * 10;
-                    r =  l + 20; 
-                    t =  10; b = 40;
-                    bYAlign = 5;
-                    break;
-                case 3:
-                    l =  10; r = 40;
-                    t =  bYAlign * 10;
-                    b =  l + 20; 
-                    bXAlign = 5;
-                    break;
+            if (bShape) {
+                switch (bShape) {
+                    case 1: // square
+                        l =  bXAlign * 10;
+                        r =  l + 20; 
+                        t =  bYAlign * 10;
+                        b =  l + 20; 
+                        break;
+                    case 2:
+                        l =  bXAlign * 10;
+                        r =  l + 20; 
+                        t =  10; b = 40;
+                        bYAlign = 5;
+                        break;
+                    case 3:
+                        l =  10; r = 40;
+                        t =  bYAlign * 10;
+                        b =  l + 20; 
+                        bXAlign = 5;
+                        break;
+                }
+                path.addRect(l, t, r, b, (SkPath::Direction) bCW);
+                str += sprintf(str, "    path.addRect(%d, %d, %d, %d,"
+                        " (SkPath::Direction) %d);\n", l, t, r, b, bCW);
+            } else {
+                bXAlign = 5;
+                bYAlign = 5;
             }
-            path.addRect(l, t, r, b, (SkPath::Direction) bCW);
-            str += sprintf(str, "    path.addRect(%d, %d, %d, %d,"
-                    " (SkPath::Direction) %d);\n", l, t, r, b, bCW);
-        } else {
-            bXAlign = 5;
-            bYAlign = 5;
-        }
-        if (cShape) {
-            switch (cShape) {
-                case 1: // square
-                    l =  cXAlign * 6;
-                    r =  l + 12; 
-                    t =  cYAlign * 6;
-                    b =  l + 12; 
-                    break;
-                case 2:
-                    l =  cXAlign * 6;
-                    r =  l + 12; 
-                    t =  20; b = 30;
-                    cYAlign = 5;
-                    break;
-                case 3:
-                    l =  20; r = 30;
-                    t =  cYAlign * 6;
-                    b =  l + 20; 
-                    cXAlign = 5;
-                    break;
+            if (cShape) {
+                switch (cShape) {
+                    case 1: // square
+                        l =  cXAlign * 6;
+                        r =  l + 12; 
+                        t =  cYAlign * 6;
+                        b =  l + 12; 
+                        break;
+                    case 2:
+                        l =  cXAlign * 6;
+                        r =  l + 12; 
+                        t =  20; b = 30;
+                        cYAlign = 5;
+                        break;
+                    case 3:
+                        l =  20; r = 30;
+                        t =  cYAlign * 6;
+                        b =  l + 20; 
+                        cXAlign = 5;
+                        break;
+                }
+                path.addRect(l, t, r, b, (SkPath::Direction) cCW);
+                str += sprintf(str, "    path.addRect(%d, %d, %d, %d,"
+                        " (SkPath::Direction) %d);\n", l, t, r, b, cCW);
+            } else {
+                cXAlign = 5;
+                cYAlign = 5;
             }
-            path.addRect(l, t, r, b, (SkPath::Direction) cCW);
-            str += sprintf(str, "    path.addRect(%d, %d, %d, %d,"
-                    " (SkPath::Direction) %d);\n", l, t, r, b, cCW);
-        } else {
-            cXAlign = 5;
-            cYAlign = 5;
-        }
-        if (dShape) {
-            switch (dShape) {
-                case 1: // square
-                    l =  dXAlign * 4;
-                    r =  l + 9; 
-                    t =  dYAlign * 4;
-                    b =  l + 9; 
-                    break;
-                case 2:
-                    l =  dXAlign * 6;
-                    r =  l + 9; 
-                    t =  32; b = 36;
-                    dYAlign = 5;
-                    break;
-                case 3:
-                    l =  32; r = 36;
-                    t =  dYAlign * 6;
-                    b =  l + 9; 
-                    dXAlign = 5;
-                    break;
+            if (dShape) {
+                switch (dShape) {
+                    case 1: // square
+                        l =  dXAlign * 4;
+                        r =  l + 9; 
+                        t =  dYAlign * 4;
+                        b =  l + 9; 
+                        break;
+                    case 2:
+                        l =  dXAlign * 6;
+                        r =  l + 9; 
+                        t =  32; b = 36;
+                        dYAlign = 5;
+                        break;
+                    case 3:
+                        l =  32; r = 36;
+                        t =  dYAlign * 6;
+                        b =  l + 9; 
+                        dXAlign = 5;
+                        break;
+                }
+                path.addRect(l, t, r, b, (SkPath::Direction) dCW);
+                str += sprintf(str, "    path.addRect(%d, %d, %d, %d,"
+                        " (SkPath::Direction) %d);\n", l, t, r, b, dCW);
+            } else {
+                dXAlign = 5;
+                dYAlign = 5;
             }
-            path.addRect(l, t, r, b, (SkPath::Direction) dCW);
-            str += sprintf(str, "    path.addRect(%d, %d, %d, %d,"
-                    " (SkPath::Direction) %d);\n", l, t, r, b, dCW);
-        } else {
-            dXAlign = 5;
-            dYAlign = 5;
-        }
-        path.close();
-        if (gRunTestsInOneThread) {
-            SkDebugf("%s\n", pathStr);
-        } else {
-    #if 0
-            char pwd[1024];
-            getcwd(pwd, sizeof(pwd));
-            SkDebugf("%s\n", pwd);
-    #endif
-    #if 1
-            SkFILEWStream outFile(state.filename);
-            if (!outFile.isValid()) {
-                continue;
-            }
-            outFile.writeText("<div id=\"testLine");
-            outFile.writeDecAsText(testNumber);
-            outFile.writeText("\">\n");
-            outFile.writeText(pathStr);
-            outFile.writeText("</div>\n\n");
-            
-            outFile.writeText(marker);
-            outFile.writeText(testLineStr);
-            outFile.writeDecAsText(testNumber);
-            outFile.writeText(",\n\n\n");
-            
-            outFile.writeText("static void testLine");
-            outFile.writeDecAsText(testNumber);
-            outFile.writeText("() {\n    SkPath path, simple;\n");
-            outFile.writeText(pathStr);
-            outFile.writeText("    testSimplifyx(path);\n}\n\n");
-            outFile.writeText("static void (*firstTest)() = testLine");
-            outFile.writeDecAsText(testNumber);
-            outFile.writeText(";\n\n");
-
-            outFile.writeText("static struct {\n");
-            outFile.writeText("    void (*fun)();\n");
-            outFile.writeText("    const char* str;\n");
-            outFile.writeText("} tests[] = {\n");
-            outFile.writeText("    TEST(testLine");
-            outFile.writeDecAsText(testNumber);
-            outFile.writeText("),\n");
-            outFile.flush();
-    #endif
-        }
-        testSimplifyx(path, out, state.bitmap, state.canvas);
-        state.testsRun++;
+            path.close();
+            outputProgress(state, pathStr);
+            testSimplifyx(path, out, state, pathStr);
+            state.testsRun++;
+                                    }
                                 }
                             }
                         }
@@ -235,176 +166,33 @@
                 }
             }
         }
-    }
-    if (gRunTestsInOneThread) {
-        return NULL;
-    }
-#if BETTER_THREADS
-    if (DEBUG_BETTER_THREADS) SkDebugf("%s done %d\n", __FUNCTION__, state.index);
-    pthread_mutex_lock(&State4::addQueue);
-    if (DEBUG_BETTER_THREADS) SkDebugf("%s lock %d\n", __FUNCTION__, state.index);
-    state.next = State4::queue ? State4::queue->next : NULL;
-    state.done = true;
-    State4::queue = &state;
-    pthread_cond_signal(&State4::checkQueue);
-    while (state.done && !state.last) {
-        if (DEBUG_BETTER_THREADS) SkDebugf("%s wait %d\n", __FUNCTION__, state.index);
-        pthread_cond_wait(&state.initialized, &State4::addQueue);
-        if (DEBUG_BETTER_THREADS) SkDebugf("%s wait done %d\n", __FUNCTION__, state.index);
-    }
-    pthread_mutex_unlock(&State4::addQueue);
-    if (DEBUG_BETTER_THREADS) SkDebugf("%s unlock %d\n", __FUNCTION__, state.index);
-} while (!state.last);
-#endif
+    } while (runNextTestSet(state));
     return NULL;
 }
 
-const int maxThreadsAllocated = 64;
-
-State4* State4::queue = NULL;
-pthread_mutex_t State4::addQueue = PTHREAD_MUTEX_INITIALIZER;
-pthread_cond_t State4::checkQueue = PTHREAD_COND_INITIALIZER;
-
 void Simplify4x4RectsThreaded_Test()
 {
+    SkDebugf("%s\n", __FUNCTION__);
 #ifdef SK_DEBUG
     gDebugMaxWindSum = 4;
     gDebugMaxWindValue = 4;
 #endif
-    int maxThreads = 1;
-    if (!gRunTestsInOneThread) {
-        int threads = -1;
-        size_t size = sizeof(threads);
-        sysctlbyname("hw.logicalcpu_max", &threads, &size, NULL, 0);
-        SkDebugf("%s errno=%d size=%d processors=%d\n", __FUNCTION__, 
-                errno, size, threads);
-        if (threads > 0) {
-            maxThreads = threads;
-        } else {
-            maxThreads = 8;
-        }
-        SkDebugf("%s maxThreads=%d\n", __FUNCTION__, maxThreads);
-    }
-    if (!gRunTestsInOneThread) {
-        SkFILEStream inFile("../../experimental/Intersection/op.htm");
-        if (inFile.isValid()) {
-            SkTDArray<char> inData;
-            inData.setCount(inFile.getLength());
-            size_t inLen = inData.count();
-            inFile.read(inData.begin(), inLen);
-            inFile.setPath(NULL);
-            char* insert = strstr(inData.begin(), marker);   
-            if (insert) {
-                insert += sizeof(marker) - 1;
-                const char* numLoc = insert + sizeof(testLineStr) - 1;
-                testNumber = atoi(numLoc) + 1;
-            }
-        }
-    }
-    State4 threadState[maxThreadsAllocated];
-    int threadIndex;
-    for (threadIndex = 0; threadIndex < maxThreads; ++threadIndex) {
-        State4* statePtr = &threadState[threadIndex];
-        strcpy(statePtr->filename, filename);
-        SkASSERT(statePtr->filename[sizeof(filename) - 7] == 'X');
-        SkASSERT(statePtr->filename[sizeof(filename) - 6] == 'X');
-        statePtr->filename[sizeof(filename) - 7] = '0' + threadIndex / 10;
-        statePtr->filename[sizeof(filename) - 6] = '0' + threadIndex % 10;
-    }
-    threadIndex = 0;
+    const char testLineStr[] = "testLine";
+    initializeTests(testLineStr, sizeof(testLineStr));
     int testsRun = 0;
     for (int a = 0; a < 8; ++a) { // outermost
         for (int b = a ; b < 8; ++b) {
             for (int c = b ; c < 8; ++c) {
                 for (int d = c; d < 8; ++d) {                 
-                    if (!gRunTestsInOneThread) {
-                #if BETTER_THREADS == 0
-                        State4* statePtr = &threadState[threadIndex];
-                        statePtr->a = a;
-                        statePtr->b = b;
-                        statePtr->c = c;
-                        statePtr->d = d;
-                        createThread(statePtr, testSimplify4x4RectsMain);
-                        if (++threadIndex >= maxThreads) {
-                            waitForCompletion(threadState, threadIndex);
-                            for (int index = 0; index < maxThreads; ++index) {
-                                testsRun += threadState[index].testsRun;
-                            }
-                        }
-                #else
-                        State4* statePtr;
-                        pthread_mutex_lock(&State4::addQueue);
-                        if (threadIndex < maxThreads) {
-                            statePtr = &threadState[threadIndex];
-                            statePtr->a = a;
-                            statePtr->b = b;
-                            statePtr->c = c;
-                            statePtr->d = d;
-                            statePtr->index = threadIndex;
-                            statePtr->done = false;
-                            statePtr->last = false;
-                            pthread_cond_init(&statePtr->initialized, NULL);
-                            ++threadIndex;
-                            createThread(statePtr, testSimplify4x4RectsMain);
-                        } else {
-                            while (!State4::queue) {
-                                if (DEBUG_BETTER_THREADS) SkDebugf("%s wait\n", __FUNCTION__);
-                                pthread_cond_wait(&State4::checkQueue, &State4::addQueue);
-                            }
-                            statePtr = State4::queue;
-                            testsRun += statePtr->testsRun;
-                            if (DEBUG_BETTER_THREADS) SkDebugf("%s dequeue %d\n", __FUNCTION__, statePtr->index);
-                            statePtr->a = a;
-                            statePtr->b = b;
-                            statePtr->c = c;
-                            statePtr->d = d;
-                            statePtr->done = false;
-                            State4::queue = State4::queue->next;
-                            pthread_cond_signal(&statePtr->initialized);
-                        }
-                        pthread_mutex_unlock(&State4::addQueue);
-                #endif
-                    } else {
-                        State4 state;
-                        state.a = a;
-                        state.b = b;
-                        state.c = c;
-                        state.d = d;
-                        testSimplify4x4RectsMain(&state);
-                    }
-                    if (!gRunTestsInOneThread) SkDebugf(".");
+                    testsRun += dispatchTest4(testSimplify4x4RectsMain, a, b, c, d);
                 }
-                if (!gRunTestsInOneThread) SkDebugf("%d", c);
+                if (!gRunTestsInOneThread) SkDebugf(".");
             }
-            if (!gRunTestsInOneThread) SkDebugf("\n%d", b);
+            if (!gRunTestsInOneThread) SkDebugf("%d", b);
         }
-        if (!gRunTestsInOneThread) SkDebugf("\n\n%d", a);
+        if (!gRunTestsInOneThread) SkDebugf("\n%d", a);
     }
-    if (!gRunTestsInOneThread) {
-        pthread_mutex_lock(&State4::addQueue);
-        int runningThreads = maxThreads;
-        while (runningThreads > 0) {
-            while (!State4::queue) {
-                if (DEBUG_BETTER_THREADS) SkDebugf("%s wait\n", __FUNCTION__);
-                pthread_cond_wait(&State4::checkQueue, &State4::addQueue);
-            }
-            while (State4::queue) {
-                State4::queue->last = true;
-                pthread_cond_signal(&State4::queue->initialized);
-                State4::queue = State4::queue->next;
-                --runningThreads;
-            }
-        }
-        pthread_mutex_unlock(&State4::addQueue);
-        for (threadIndex = 0; threadIndex < maxThreads; ++threadIndex) {
-            pthread_join(threadState[threadIndex].threadID, NULL);
-            testsRun += threadState[threadIndex].testsRun;
-        }
-        SkDebugf("%s total tests run=%d\n", __FUNCTION__, testsRun);
-    }
-#ifdef SK_DEBUG
-    gDebugMaxWindSum = SK_MaxS32;
-    gDebugMaxWindValue = SK_MaxS32;
-#endif
+    testsRun += waitForCompletion();
+    SkDebugf("%s total tests run=%d\n", __FUNCTION__, testsRun);
 }
 
diff --git a/experimental/Intersection/op.htm b/experimental/Intersection/op.htm
index c4a465d..ce40130 100644
--- a/experimental/Intersection/op.htm
+++ b/experimental/Intersection/op.htm
@@ -748,11 +748,135 @@
     path.addRect(0, 32, 9, 36, (SkPath::Direction) 1);
 </div>
 
+<div id="testDegenerate1">
+    path.moveTo(0, 0);
+    path.lineTo(0, 0);
+    path.lineTo(2, 0);
+    path.close();
+    path.moveTo(0, 0);
+    path.lineTo(1, 0);
+    path.lineTo(2, 0);
+    path.close();
+</div>
+
+<div id="testDegenerate2">
+    path.moveTo(0, 0);
+    path.lineTo(0, 0);
+    path.lineTo(0, 0);
+    path.close();
+    path.moveTo(0, 0);
+    path.lineTo(1, 0);
+    path.lineTo(0, 1);
+    path.close();
+</div>
+
+<div id="testDegenerate3">
+    path.moveTo(0, 0);
+    path.lineTo(2, 0);
+    path.lineTo(1, 0);
+    path.close();
+    path.moveTo(0, 0);
+    path.lineTo(0, 0);
+    path.lineTo(3, 0);
+    path.close();
+</div>
+
+<div id="testDegenerate4">
+    path.moveTo(0, 0);
+    path.lineTo(1, 0);
+    path.lineTo(1, 3);
+    path.close();
+    path.moveTo(1, 0);
+    path.lineTo(1, 1);
+    path.lineTo(1, 2);
+    path.close();
+</div>
+
+<div id="testNondegenerate1">
+    path.moveTo(0, 0);
+    path.lineTo(3, 0);
+    path.lineTo(1, 3);
+    path.close();
+    path.moveTo(1, 1);
+    path.lineTo(2, 1);
+    path.lineTo(1, 2);
+    path.close();
+</div>
+
+<div id="testNondegenerate2">
+    path.moveTo(1, 0);
+    path.lineTo(0, 1);
+    path.lineTo(1, 1);
+    path.close();
+    path.moveTo(0, 2);
+    path.lineTo(0, 3);
+    path.lineTo(1, 2);
+    path.close();
+</div>
+
+<div id="testNondegenerate3">
+    path.moveTo(0, 0);
+    path.lineTo(1, 0);
+    path.lineTo(2, 1);
+    path.close();
+    path.moveTo(0, 1);
+    path.lineTo(1, 1);
+    path.lineTo(0, 2);
+    path.close();
+</div>
+
+<div id="testNondegenerate4">
+    path.moveTo(1, 0);
+    path.lineTo(0, 1);
+    path.lineTo(1, 2);
+    path.close();
+    path.moveTo(0, 2);
+    path.lineTo(0, 3);
+    path.lineTo(1, 3);
+    path.close();
+</div>
+
+<div id="testQuadralateral5">
+    path.moveTo(0, 0);
+    path.lineTo(0, 0);
+    path.lineTo(1, 0);
+    path.lineTo(1, 1);
+    path.close();
+    path.moveTo(0, 0);
+    path.lineTo(2, 2);
+    path.lineTo(3, 2);
+    path.lineTo(3, 3);
+    path.close();
+</div>
+
+<div id="testQuadralateral6">
+    path.moveTo(0, 0);
+    path.lineTo(0, 0);
+    path.lineTo(1, 0);
+    path.lineTo(1, 1);
+    path.close();
+    path.moveTo(1, 0);
+    path.lineTo(2, 0);
+    path.lineTo(0, 2);
+    path.lineTo(2, 2);
+    path.close();
+</div>
+
 </div>
 
 <script type="text/javascript">
 
 var testDivs = [
+    testQuadralateral6,
+    testQuadralateral5,
+    testNondegenerate4,
+    testNondegenerate3,
+    testNondegenerate2,
+    testNondegenerate1,
+    testDegenerate4,
+    testDegenerate3,
+    testDegenerate2,
+    testDegenerate1,
     testLine79,
     testLine78,
     testLine77,