shape ops work in progress

git-svn-id: http://skia.googlecode.com/svn/trunk@7453 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/experimental/Intersection/ConvexHull_Test.cpp b/experimental/Intersection/ConvexHull_Test.cpp
index 3e53b17..3979b1e 100644
--- a/experimental/Intersection/ConvexHull_Test.cpp
+++ b/experimental/Intersection/ConvexHull_Test.cpp
@@ -146,17 +146,17 @@
             int zeroes;
             zeroes = -1;
             bzero(sides, sizeof(sides));
-            if (debug_rotate_to_hull) printf("%s [%d,%d] [o=%d,i=%d] src=(%g,%g) rot=", __FUNCTION__,
+            if (debug_rotate_to_hull) SkDebugf("%s [%d,%d] [o=%d,i=%d] src=(%g,%g) rot=", __FUNCTION__,
                     (int)idx, (int)inr, (int)outer, (int)inner,
                     cubic[inner].x, cubic[inner].y);
             for (int index = 0; index < 4; ++index) {
-                if (debug_rotate_to_hull) printf("(%g,%g) ", rotPath[index].x, rotPath[index].y);
+                if (debug_rotate_to_hull) SkDebugf("(%g,%g) ", rotPath[index].x, rotPath[index].y);
                 sides[side(rotPath[index].y - rotPath[inner].y)]++;
                 if (index != outer && index != inner
                         && side(rotPath[index].y - rotPath[inner].y) == 1)
                     zeroes = index;
             }
-            if (debug_rotate_to_hull) printf("sides=(%d,%d,%d)\n", sides[0], sides[1], sides[2]);
+            if (debug_rotate_to_hull) SkDebugf("sides=(%d,%d,%d)\n", sides[0], sides[1], sides[2]);
             if (sides[0] && sides[2]) {
                 continue;
             }
@@ -165,25 +165,25 @@
                 // if either of remaining two equals outer or equal, pick lower
                 if (rotPath[zeroes].approximatelyEqual(rotPath[inner])
                         && zeroes < inner) {
-                    if (debug_rotate_to_hull) printf("%s [%d,%d] [o=%d,i=%d] zeroes < inner\n",
+                    if (debug_rotate_to_hull) SkDebugf("%s [%d,%d] [o=%d,i=%d] zeroes < inner\n",
                         __FUNCTION__, (int)idx, (int)inr, (int)outer, (int)inner);
                     continue;
                 }
                  if (rotPath[zeroes].approximatelyEqual(rotPath[outer])
                         && zeroes < outer) {
-                    if (debug_rotate_to_hull) printf("%s [%d,%d] [o=%d,i=%d] zeroes < outer\n",
+                    if (debug_rotate_to_hull) SkDebugf("%s [%d,%d] [o=%d,i=%d] zeroes < outer\n",
                         __FUNCTION__, (int)idx, (int)inr, (int)outer, (int)inner);
                     continue;
                 }
                 if (rotPath[zeroes].x < rotPath[inner].x
                         && rotPath[zeroes].x < rotPath[outer].x) {
-                    if (debug_rotate_to_hull) printf("%s [%d,%d] [o=%d,i=%d] zeroes < inner && outer\n",
+                    if (debug_rotate_to_hull) SkDebugf("%s [%d,%d] [o=%d,i=%d] zeroes < inner && outer\n",
                         __FUNCTION__, (int)idx, (int)inr, (int)outer, (int)inner);
                     continue;
                 }
                 if (rotPath[zeroes].x > rotPath[inner].x
                         && rotPath[zeroes].x > rotPath[outer].x) {
-                    if (debug_rotate_to_hull) printf("%s [%d,%d] [o=%d,i=%d] zeroes > inner && outer\n",
+                    if (debug_rotate_to_hull) SkDebugf("%s [%d,%d] [o=%d,i=%d] zeroes > inner && outer\n",
                         __FUNCTION__, (int)idx, (int)inr, (int)outer, (int)inner);
                     continue;
                 }
@@ -192,7 +192,7 @@
                 outsidePtSet[outer] = inner;
             } else {
                 if (outsidePtSet[inner] > 0) {
-                    if (debug_rotate_to_hull) printf("%s [%d,%d] [o=%d,i=%d] too many rays from one point\n",
+                    if (debug_rotate_to_hull) SkDebugf("%s [%d,%d] [o=%d,i=%d] too many rays from one point\n",
                         __FUNCTION__, (int)idx, (int)inr, (int)outer, (int)inner);
                 }
                 outsidePtSet[inner] = outer;
@@ -237,7 +237,7 @@
             }
             int result = convex_hull(cubic, order);
             if (cmp != result) {
-                printf("%s [%d,%d] result=%d cmp=%d\n", __FUNCTION__,
+                SkDebugf("%s [%d,%d] result=%d cmp=%d\n", __FUNCTION__,
                     (int)index, (int)inner, result, cmp);
                 continue;
             }
@@ -247,23 +247,23 @@
             int pt, bit;
             for (pt = 0; pt < cmp; ++pt) {
                 if (pts & 1 << order[pt]) {
-                    printf("%s [%d,%d] duplicate index in order: %d,%d,%d",
+                    SkDebugf("%s [%d,%d] duplicate index in order: %d,%d,%d",
                             __FUNCTION__, (int)index, (int)inner,
                             order[0], order[1], order[2]);
                     if (cmp == 4) {
-                        printf(",%d", order[3]);
+                        SkDebugf(",%d", order[3]);
                     }
-                    printf("\n");
+                    SkDebugf("\n");
                     goto next;
                 }
                 if (cmpPts & 1 << cmpOrder[pt]) {
-                    printf("%s [%d,%d] duplicate index in order: %d,%d,%d",
+                    SkDebugf("%s [%d,%d] duplicate index in order: %d,%d,%d",
                             __FUNCTION__, (int)index, (int)inner,
                             cmpOrder[0], cmpOrder[1], cmpOrder[2]);
                     if (cmp == 4) {
-                        printf(",%d", cmpOrder[3]);
+                        SkDebugf(",%d", cmpOrder[3]);
                     }
-                    printf("\n");
+                    SkDebugf("\n");
                     goto next;
                 }
                 pts |= 1 << order[pt];
@@ -296,17 +296,17 @@
                 }
             }
             if (pts != cmpPts) {
-                printf("%s [%d,%d] mismatch indices: order=%d,%d,%d",
+                SkDebugf("%s [%d,%d] mismatch indices: order=%d,%d,%d",
                         __FUNCTION__, (int)index, (int)inner,
                         order[0], order[1], order[2]);
                 if (cmp == 4) {
-                    printf(",%d", order[3]);
+                    SkDebugf(",%d", order[3]);
                 }
-                printf(" cmpOrder=%d,%d,%d", cmpOrder[0], cmpOrder[1], cmpOrder[2]);
+                SkDebugf(" cmpOrder=%d,%d,%d", cmpOrder[0], cmpOrder[1], cmpOrder[2]);
                 if (cmp == 4) {
-                    printf(",%d", cmpOrder[3]);
+                    SkDebugf(",%d", cmpOrder[3]);
                 }
-                printf("\n");
+                SkDebugf("\n");
                 continue;
             }
             if (cmp == 4) { // check for bow ties
@@ -315,7 +315,7 @@
                     ++match;
                 }
                 if (cmpOrder[match ^ 2] != order[2]) {
-                    printf("%s [%d,%d] bowtie mismatch: order=%d,%d,%d,%d"
+                    SkDebugf("%s [%d,%d] bowtie mismatch: order=%d,%d,%d,%d"
                             " cmpOrder=%d,%d,%d,%d\n",
                             __FUNCTION__, (int)index, (int)inner,
                             order[0], order[1], order[2], order[3],
@@ -365,12 +365,12 @@
             if (connectTo0[idx] >= 1 && connectTo0[idx] < 4) {
                 continue;
             } else {
-                printf("%s connectTo0[idx]=%d", __FUNCTION__, connectTo0[idx]);
+                SkDebugf("%s connectTo0[idx]=%d", __FUNCTION__, connectTo0[idx]);
             }
             if (connectTo3[idx] >= 0 && connectTo3[idx] < 3) {
                 continue;
             } else {
-                printf("%s connectTo3[idx]=%d", __FUNCTION__, connectTo3[idx]);
+                SkDebugf("%s connectTo3[idx]=%d", __FUNCTION__, connectTo3[idx]);
             }
             goto nextTest;
         }
@@ -398,7 +398,7 @@
         }
         if (connectTo0[0] != connectTo0[1]) {
             if (rOrder[0] == rOrder[1]) {
-                printf("%s [%d] (1) order=(%d,%d,%d,%d) r_order=(%d,%d,%d,%d)\n",
+                SkDebugf("%s [%d] (1) order=(%d,%d,%d,%d) r_order=(%d,%d,%d,%d)\n",
                     __FUNCTION__, (int)index, connectTo0[0], connectTo0[1],
                     connectTo3[0], connectTo3[1],
                     rOrder[0], rOrder[1], rOrder[2], rOrder[3]);
@@ -407,7 +407,7 @@
             int unused = 6 - connectTo0[0] - connectTo0[1];
             int rUnused = 6 - rOrder[0] - rOrder[1];
             if (unused != rUnused) {
-                printf("%s [%d] (2) order=(%d,%d,%d,%d) r_order=(%d,%d,%d,%d)\n",
+                SkDebugf("%s [%d] (2) order=(%d,%d,%d,%d) r_order=(%d,%d,%d,%d)\n",
                     __FUNCTION__, (int)index, connectTo0[0], connectTo0[1],
                     connectTo3[0], connectTo3[1],
                     rOrder[0], rOrder[1], rOrder[2], rOrder[3]);
@@ -415,14 +415,14 @@
             }
         } else {
             if (rOrder[0] != rOrder[1]) {
-                printf("%s [%d] (3) order=(%d,%d,%d,%d) r_order=(%d,%d,%d,%d)\n",
+                SkDebugf("%s [%d] (3) order=(%d,%d,%d,%d) r_order=(%d,%d,%d,%d)\n",
                     __FUNCTION__, (int)index, connectTo0[0], connectTo0[1],
                     connectTo3[0], connectTo3[1],
                     rOrder[0], rOrder[1], rOrder[2], rOrder[3]);
                 continue;
             }
             if (connectTo0[0] != rOrder[0]) {
-                printf("%s [%d] (4) order=(%d,%d,%d,%d) r_order=(%d,%d,%d,%d)\n",
+                SkDebugf("%s [%d] (4) order=(%d,%d,%d,%d) r_order=(%d,%d,%d,%d)\n",
                     __FUNCTION__, (int)index, connectTo0[0], connectTo0[1],
                     connectTo3[0], connectTo3[1],
                     rOrder[0], rOrder[1], rOrder[2], rOrder[3]);
@@ -431,7 +431,7 @@
         }
         if (connectTo3[0] != connectTo3[1]) {
              if (rOrder[2] == rOrder[3]) {
-                printf("%s [%d] (5) order=(%d,%d,%d,%d) r_order=(%d,%d,%d,%d)\n",
+                SkDebugf("%s [%d] (5) order=(%d,%d,%d,%d) r_order=(%d,%d,%d,%d)\n",
                     __FUNCTION__, (int)index, connectTo0[0], connectTo0[1],
                     connectTo3[0], connectTo3[1],
                     rOrder[0], rOrder[1], rOrder[2], rOrder[3]);
@@ -440,7 +440,7 @@
            int unused = 6 - connectTo3[0] - connectTo3[1];
            int rUnused = 6 - rOrder[2] - rOrder[3];
             if (unused != rUnused) {
-                printf("%s [%d] (6) order=(%d,%d,%d,%d) r_order=(%d,%d,%d,%d)\n",
+                SkDebugf("%s [%d] (6) order=(%d,%d,%d,%d) r_order=(%d,%d,%d,%d)\n",
                     __FUNCTION__, (int)index, connectTo0[0], connectTo0[1],
                     connectTo3[0], connectTo3[1],
                     rOrder[0], rOrder[1], rOrder[2], rOrder[3]);
@@ -448,14 +448,14 @@
             }
         } else {
             if (rOrder[2] != rOrder[3]) {
-                printf("%s [%d] (7) order=(%d,%d,%d,%d) r_order=(%d,%d,%d,%d)\n",
+                SkDebugf("%s [%d] (7) order=(%d,%d,%d,%d) r_order=(%d,%d,%d,%d)\n",
                     __FUNCTION__, (int)index, connectTo0[0], connectTo0[1],
                     connectTo3[0], connectTo3[1],
                     rOrder[0], rOrder[1], rOrder[2], rOrder[3]);
                 continue;
             }
             if (connectTo3[1] != rOrder[3]) {
-                printf("%s [%d] (8) order=(%d,%d,%d,%d) r_order=(%d,%d,%d,%d)\n",
+                SkDebugf("%s [%d] (8) order=(%d,%d,%d,%d) r_order=(%d,%d,%d,%d)\n",
                     __FUNCTION__, (int)index, connectTo0[0], connectTo0[1],
                     connectTo3[0], connectTo3[1],
                     rOrder[0], rOrder[1], rOrder[2], rOrder[3]);
diff --git a/experimental/Intersection/CubicBezierClip.cpp b/experimental/Intersection/CubicBezierClip.cpp
index 825a7b9..378e45f 100644
--- a/experimental/Intersection/CubicBezierClip.cpp
+++ b/experimental/Intersection/CubicBezierClip.cpp
@@ -7,7 +7,6 @@
 #include "CurveIntersection.h"
 #include "CurveUtilities.h"
 #include "LineParameters.h"
-#include <algorithm> // used for std::swap
 
 // return false if unable to clip (e.g., unable to create implicit line)
 // caller should subdivide, or create degenerate if the values are too small
@@ -33,7 +32,7 @@
     double top = distance[0];
     double bottom = distance[1];
     if (top > bottom) {
-        std::swap(top, bottom);
+        SkTSwap(top, bottom);
     }
     if (top * bottom >= 0) {
         const double scale = 3/4.0; // http://cagd.cs.byu.edu/~tom/papers/bezclip.pdf (13)
diff --git a/experimental/Intersection/CubicBezierClip_Test.cpp b/experimental/Intersection/CubicBezierClip_Test.cpp
index 2f1e3c6..1a9092f 100644
--- a/experimental/Intersection/CubicBezierClip_Test.cpp
+++ b/experimental/Intersection/CubicBezierClip_Test.cpp
@@ -16,10 +16,10 @@
         int order1 = reduceOrder(cubic1, reduce1, kReduceOrder_NoQuadraticsAllowed);
         int order2 = reduceOrder(cubic2, reduce2, kReduceOrder_NoQuadraticsAllowed);
         if (order1 < 4) {
-            printf("%s [%d] cubic1 order=%d\n", __FUNCTION__, (int) index, order1);
+            SkDebugf("%s [%d] cubic1 order=%d\n", __FUNCTION__, (int) index, order1);
         }
         if (order2 < 4) {
-            printf("%s [%d] cubic2 order=%d\n", __FUNCTION__, (int) index, order2);
+            SkDebugf("%s [%d] cubic2 order=%d\n", __FUNCTION__, (int) index, order2);
         }
         if (order1 == 4 && order2 == 4) {
             double minT = 0;
diff --git a/experimental/Intersection/CubicIntersection.cpp b/experimental/Intersection/CubicIntersection.cpp
index 9316f34..bedbfa1 100644
--- a/experimental/Intersection/CubicIntersection.cpp
+++ b/experimental/Intersection/CubicIntersection.cpp
@@ -287,7 +287,7 @@
                     }
 #if SK_DEBUG
                     ++debugDepth;
-                    assert(debugDepth < 10);
+                    SkASSERT(debugDepth < 10);
 #endif
                     i.swap();
                     intersect2(cubic2, SkTMax(to2 - dt2, 0.), SkTMin(to2 + dt2, 1.),
@@ -340,12 +340,12 @@
     double tMin, tMax;
     tMin = tMax = local1.fT[0][0];
     for (int index = 1; index < local1.fUsed; ++index) {
-        tMin = std::min(tMin, local1.fT[0][index]);
-        tMax = std::max(tMax, local1.fT[0][index]);
+        tMin = SkTMin(tMin, local1.fT[0][index]);
+        tMax = SkTMax(tMax, local1.fT[0][index]);
     }
     for (int index = 1; index < local2.fUsed; ++index) {
-        tMin = std::min(tMin, local2.fT[0][index]);
-        tMax = std::max(tMax, local2.fT[0][index]);
+        tMin = SkTMin(tMin, local2.fT[0][index]);
+        tMax = SkTMax(tMax, local2.fT[0][index]);
     }
 #if SK_DEBUG
     debugDepth = 0;
diff --git a/experimental/Intersection/CubicIntersection_Test.cpp b/experimental/Intersection/CubicIntersection_Test.cpp
index 94d86ea..738a0dc 100644
--- a/experimental/Intersection/CubicIntersection_Test.cpp
+++ b/experimental/Intersection/CubicIntersection_Test.cpp
@@ -93,11 +93,14 @@
         SkDebugf("%s t1=%1.9g (%1.9g, %1.9g) (%1.9g, %1.9g) t2=%1.9g\n", __FUNCTION__,
             tt1, xy1.x, xy1.y, xy2.x, xy2.y, tt2);
 #endif
-        assert(xy1.approximatelyEqual(xy2));
+        SkASSERT(xy1.approximatelyEqual(xy2));
     }
 }
 
 static const Cubic testSet[] = {
+{{0, 1}, {0, 2}, {1, 0}, {1, 0}},
+{{0, 1}, {0, 1}, {1, 0}, {2, 0}},
+
 {{0, 0}, {0, 1}, {1, 1}, {1, 0}},
 {{1, 0}, {0, 0}, {0, 1}, {1, 1}},
 
@@ -250,12 +253,12 @@
             SkDebugf("%s %d unexpected intersection boundsIntersect=%d oldIntersects=%d"
                     " newIntersects=%d\n%s %s\n", __FUNCTION__, test, boundsIntersect,
                     oldIntersects, newIntersects, __FUNCTION__, str);
-            assert(0);
+            SkASSERT(0);
         }
         if (oldIntersects && !newIntersects) {
             SkDebugf("%s %d missing intersection oldIntersects=%d newIntersects=%d\n%s %s\n",
                     __FUNCTION__, test, oldIntersects, newIntersects, __FUNCTION__, str);
-            assert(0);
+            SkASSERT(0);
         }
         if (!oldIntersects && !newIntersects) {
             continue;
@@ -336,7 +339,7 @@
             SkDebugf("%s %d unexpected intersection boundsIntersect=%d "
                     " newIntersects=%d\n%s %s\n", __FUNCTION__, test, boundsIntersect,
                     newIntersects, __FUNCTION__, str);
-            assert(0);
+            SkASSERT(0);
         }
         for (int pt = 0; pt < intersections2.used(); ++pt) {
             double tt1 = intersections2.fT[0][pt];
@@ -349,7 +352,7 @@
             SkDebugf("%s t1=%1.9g (%1.9g, %1.9g) (%1.9g, %1.9g) t2=%1.9g\n", __FUNCTION__,
                 tt1, xy1.x, xy1.y, xy2.x, xy2.y, tt2);
         #endif
-            assert(xy1.approximatelyEqual(xy2));
+            SkASSERT(xy1.approximatelyEqual(xy2));
         }
     }
 }
diff --git a/experimental/Intersection/CubicLineSegments.cpp b/experimental/Intersection/CubicLineSegments.cpp
index b7408a8..58b7b85 100644
--- a/experimental/Intersection/CubicLineSegments.cpp
+++ b/experimental/Intersection/CubicLineSegments.cpp
@@ -6,7 +6,6 @@
  */
 #include "CubicLineSegments.h"
 #include "QuadraticLineSegments.h"
-#include <algorithm> // used for std::max
 
 // http://cagd.cs.byu.edu/~557/text/cagd.pdf 2.7
 // A hodograph is the first derivative curve
@@ -31,8 +30,8 @@
 double subDivisions(const Cubic& cubic) {
     _Line hodo2;
     secondHodograph(cubic, hodo2);
-    double maxX = std::max(hodo2[1].x, hodo2[1].x);
-    double maxY = std::max(hodo2[1].y, hodo2[1].y);
+    double maxX = SkTMax(hodo2[1].x, hodo2[1].x);
+    double maxY = SkTMax(hodo2[1].y, hodo2[1].y);
     double dist = sqrt(maxX * maxX + maxY * maxY);
     double segments = sqrt(dist / (8 * FLT_EPSILON));
     return segments;
diff --git a/experimental/Intersection/CubicParameterization_Test.cpp b/experimental/Intersection/CubicParameterization_Test.cpp
index 517ae11..cc095b6 100644
--- a/experimental/Intersection/CubicParameterization_Test.cpp
+++ b/experimental/Intersection/CubicParameterization_Test.cpp
@@ -34,19 +34,19 @@
         quad_to_cubic(split.second(), second);
         quad_to_cubic(midThird, mid);
         if (!implicit_matches(whole, first)) {
-            printf("%s-1 %d\n", __FUNCTION__, (int)index);
+            SkDebugf("%s-1 %d\n", __FUNCTION__, (int)index);
         }
         if (!implicit_matches(whole, second)) {
-            printf("%s-2 %d\n", __FUNCTION__, (int)index);
+            SkDebugf("%s-2 %d\n", __FUNCTION__, (int)index);
         }
         if (!implicit_matches(mid, first)) {
-            printf("%s-3 %d\n", __FUNCTION__, (int)index);
+            SkDebugf("%s-3 %d\n", __FUNCTION__, (int)index);
         }
         if (!implicit_matches(mid, second)) {
-            printf("%s-4 %d\n", __FUNCTION__, (int)index);
+            SkDebugf("%s-4 %d\n", __FUNCTION__, (int)index);
         }
         if (!implicit_matches(first, second)) {
-            printf("%s-5 %d\n", __FUNCTION__, (int)index);
+            SkDebugf("%s-5 %d\n", __FUNCTION__, (int)index);
         }
     }
 }
@@ -98,16 +98,16 @@
     for (size_t index = firstCubicParameterizationTest; index < cubics_count; ++index) {
         for (size_t inner = 0; inner < 4; inner += 3) {
             if (!point_on_parameterized_curve(cubics[index], cubics[index][inner])) {
-                    printf("%s [%zu,%zu] 1 parameterization failed\n",
+                    SkDebugf("%s [%zu,%zu] 1 parameterization failed\n",
                         __FUNCTION__, index, inner);
             }
             if (!point_on_parameterized_curve(cubics[index], cubics[index ^ 1][inner])) {
-                    printf("%s [%zu,%zu] 2 parameterization failed\n",
+                    SkDebugf("%s [%zu,%zu] 2 parameterization failed\n",
                         __FUNCTION__, index, inner);
             }
         }
         if (!implicit_matches(cubics[index], cubics[index ^ 1])) {
-            printf("%s %d\n", __FUNCTION__, (int)index);
+            SkDebugf("%s %d\n", __FUNCTION__, (int)index);
         }
     }
 }
diff --git a/experimental/Intersection/CubicReduceOrder.cpp b/experimental/Intersection/CubicReduceOrder.cpp
index 87d9fd8..29920ab 100644
--- a/experimental/Intersection/CubicReduceOrder.cpp
+++ b/experimental/Intersection/CubicReduceOrder.cpp
@@ -93,7 +93,7 @@
         --endIndex;
         if (endIndex == 0) {
             printf("%s shouldn't get here if all four points are about equal\n", __FUNCTION__);
-            assert(0);
+            SkASSERT(0);
         }
     }
     if (!isLinear(cubic, startIndex, endIndex)) {
diff --git a/experimental/Intersection/CubicReduceOrder_Test.cpp b/experimental/Intersection/CubicReduceOrder_Test.cpp
index 17d9c47..1011fab 100644
--- a/experimental/Intersection/CubicReduceOrder_Test.cpp
+++ b/experimental/Intersection/CubicReduceOrder_Test.cpp
@@ -33,64 +33,64 @@
     run = RunComputedLines;
     firstTestIndex = 18;
 #endif
-    int firstPointDegeneratesTest = run == RunAll ? 0 : run == RunPointDegenerates ? firstTestIndex : INT_MAX;
-    int firstNotPointDegeneratesTest = run == RunAll ? 0 : run == RunNotPointDegenerates ? firstTestIndex : INT_MAX;
-    int firstLinesTest = run == RunAll ? 0 : run == RunLines ? firstTestIndex : INT_MAX;
-    int firstNotLinesTest = run == RunAll ? 0 : run == RunNotLines ? firstTestIndex : INT_MAX;
-    int firstModEpsilonTest = run == RunAll ? 0 : run == RunModEpsilonLines ? firstTestIndex : INT_MAX;
-    int firstLessEpsilonTest = run == RunAll ? 0 : run == RunLessEpsilonLines ? firstTestIndex : INT_MAX;
-    int firstNegEpsilonTest = run == RunAll ? 0 : run == RunNegEpsilonLines ? firstTestIndex : INT_MAX;
-    int firstQuadraticLineTest = run == RunAll ? 0 : run == RunQuadraticLines ? firstTestIndex : INT_MAX;
-    int firstQuadraticModLineTest = run == RunAll ? 0 : run == RunQuadraticModLines ? firstTestIndex : INT_MAX;
-    int firstComputedLinesTest = run == RunAll ? 0 : run == RunComputedLines ? firstTestIndex : INT_MAX;
+    int firstPointDegeneratesTest = run == RunAll ? 0 : run == RunPointDegenerates ? firstTestIndex : SK_MaxS32;
+    int firstNotPointDegeneratesTest = run == RunAll ? 0 : run == RunNotPointDegenerates ? firstTestIndex : SK_MaxS32;
+    int firstLinesTest = run == RunAll ? 0 : run == RunLines ? firstTestIndex : SK_MaxS32;
+    int firstNotLinesTest = run == RunAll ? 0 : run == RunNotLines ? firstTestIndex : SK_MaxS32;
+    int firstModEpsilonTest = run == RunAll ? 0 : run == RunModEpsilonLines ? firstTestIndex : SK_MaxS32;
+    int firstLessEpsilonTest = run == RunAll ? 0 : run == RunLessEpsilonLines ? firstTestIndex : SK_MaxS32;
+    int firstNegEpsilonTest = run == RunAll ? 0 : run == RunNegEpsilonLines ? firstTestIndex : SK_MaxS32;
+    int firstQuadraticLineTest = run == RunAll ? 0 : run == RunQuadraticLines ? firstTestIndex : SK_MaxS32;
+    int firstQuadraticModLineTest = run == RunAll ? 0 : run == RunQuadraticModLines ? firstTestIndex : SK_MaxS32;
+    int firstComputedLinesTest = run == RunAll ? 0 : run == RunComputedLines ? firstTestIndex : SK_MaxS32;
 
     for (index = firstPointDegeneratesTest; index < pointDegenerates_count; ++index) {
         const Cubic& cubic = pointDegenerates[index];
         order = reduceOrder(cubic, reduce, kReduceOrder_QuadraticsAllowed);
         if (order != 1) {
-            printf("[%d] pointDegenerates order=%d\n", (int) index, order);
+            SkDebugf("[%d] pointDegenerates order=%d\n", (int) index, order);
         }
     }
     for (index = firstNotPointDegeneratesTest; index < notPointDegenerates_count; ++index) {
         const Cubic& cubic = notPointDegenerates[index];
         order = reduceOrder(cubic, reduce, kReduceOrder_QuadraticsAllowed);
         if (order == 1) {
-            printf("[%d] notPointDegenerates order=%d\n", (int) index, order);
+            SkDebugf("[%d] notPointDegenerates order=%d\n", (int) index, order);
         }
     }
     for (index = firstLinesTest; index < lines_count; ++index) {
         const Cubic& cubic = lines[index];
         order = reduceOrder(cubic, reduce, kReduceOrder_QuadraticsAllowed);
         if (order != 2) {
-            printf("[%d] lines order=%d\n", (int) index, order);
+            SkDebugf("[%d] lines order=%d\n", (int) index, order);
         }
     }
     for (index = firstNotLinesTest; index < notLines_count; ++index) {
         const Cubic& cubic = notLines[index];
         order = reduceOrder(cubic, reduce, kReduceOrder_QuadraticsAllowed);
         if (order == 2) {
-            printf("[%d] notLines order=%d\n", (int) index, order);
+            SkDebugf("[%d] notLines order=%d\n", (int) index, order);
         }
     }
     for (index = firstModEpsilonTest; index < modEpsilonLines_count; ++index) {
         const Cubic& cubic = modEpsilonLines[index];
         order = reduceOrder(cubic, reduce, kReduceOrder_QuadraticsAllowed);
         if (order == 2) {
-            printf("[%d] line mod by epsilon order=%d\n", (int) index, order);
+            SkDebugf("[%d] line mod by epsilon order=%d\n", (int) index, order);
         }
     }
     for (index = firstLessEpsilonTest; index < lessEpsilonLines_count; ++index) {
         const Cubic& cubic = lessEpsilonLines[index];
         order = reduceOrder(cubic, reduce, kReduceOrder_QuadraticsAllowed);
         if (order != 2) {
-            printf("[%d] line less by epsilon/2 order=%d\n", (int) index, order);
+            SkDebugf("[%d] line less by epsilon/2 order=%d\n", (int) index, order);
         }
     }
     for (index = firstNegEpsilonTest; index < negEpsilonLines_count; ++index) {
         const Cubic& cubic = negEpsilonLines[index];
         order = reduceOrder(cubic, reduce, kReduceOrder_QuadraticsAllowed);
         if (order != 2) {
-            printf("[%d] line neg by epsilon/2 order=%d\n", (int) index, order);
+            SkDebugf("[%d] line neg by epsilon/2 order=%d\n", (int) index, order);
         }
     }
     for (index = firstQuadraticLineTest; index < quadraticLines_count; ++index) {
@@ -99,7 +99,7 @@
         quad_to_cubic(quad, cubic);
         order = reduceOrder(cubic, reduce, kReduceOrder_QuadraticsAllowed);
         if (order != 2) {
-            printf("[%d] line quad order=%d\n", (int) index, order);
+            SkDebugf("[%d] line quad order=%d\n", (int) index, order);
         }
     }
     for (index = firstQuadraticModLineTest; index < quadraticModEpsilonLines_count; ++index) {
@@ -108,7 +108,7 @@
         quad_to_cubic(quad, cubic);
         order = reduceOrder(cubic, reduce, kReduceOrder_QuadraticsAllowed);
         if (order != 3) {
-            printf("[%d] line mod quad order=%d\n", (int) index, order);
+            SkDebugf("[%d] line mod quad order=%d\n", (int) index, order);
         }
     }
 
@@ -118,14 +118,14 @@
         bool controlsInside = controls_inside(cubic);
         order = reduceOrder(cubic, reduce, kReduceOrder_QuadraticsAllowed);
         if (reduce[0].x == reduce[1].x && reduce[0].y == reduce[1].y) {
-            printf("[%d] line computed ends match order=%d\n", (int) index, order);
+            SkDebugf("[%d] line computed ends match order=%d\n", (int) index, order);
         }
         if (controlsInside) {
             if (       (reduce[0].x != cubic[0].x && reduce[0].x != cubic[3].x)
                     || (reduce[0].y != cubic[0].y && reduce[0].y != cubic[3].y)
                     || (reduce[1].x != cubic[0].x && reduce[1].x != cubic[3].x)
                     || (reduce[1].y != cubic[0].y && reduce[1].y != cubic[3].y)) {
-                printf("[%d] line computed ends order=%d\n", (int) index, order);
+                SkDebugf("[%d] line computed ends order=%d\n", (int) index, order);
             }
         } else {
             // binary search for extrema, compare against actual results
@@ -136,7 +136,7 @@
                     || (!AlmostEqualUlps(reduce[0].y, bounds.top) && !AlmostEqualUlps(reduce[0].y, bounds.bottom))
                     || (!AlmostEqualUlps(reduce[1].x, bounds.left) && !AlmostEqualUlps(reduce[1].x, bounds.right))
                     || (!AlmostEqualUlps(reduce[1].y, bounds.top) && !AlmostEqualUlps(reduce[1].y, bounds.bottom))) {
-                printf("[%d] line computed tight bounds order=%d\n", (int) index, order);
+                SkDebugf("[%d] line computed tight bounds order=%d\n", (int) index, order);
             }
 
         }
diff --git a/experimental/Intersection/CubicToQuadratics_Test.cpp b/experimental/Intersection/CubicToQuadratics_Test.cpp
index 843833f..9688164 100644
--- a/experimental/Intersection/CubicToQuadratics_Test.cpp
+++ b/experimental/Intersection/CubicToQuadratics_Test.cpp
@@ -40,7 +40,7 @@
         const Cubic& cubic = cubics[index];
         double precision = calcPrecision(cubic);
         int order = cubic_to_quadratics(cubic, precision, quads);
-        assert(order != 4);
+        SkASSERT(order != 4);
         if (order < 3) {
             continue;
         }
@@ -63,7 +63,7 @@
             const Cubic& cubic = cubics[index][idx2];
             double precision = calcPrecision(cubic);
             int order = cubic_to_quadratics(cubic, precision, quads);
-        assert(order != 4);
+        SkASSERT(order != 4);
         if (order < 3) {
                 continue;
             }
@@ -101,17 +101,17 @@
     run = RunComputedLines;
     firstTestIndex = 18;
 #endif
-    int firstPointDegeneratesTest = run == RunAll ? 0 : run == RunPointDegenerates ? firstTestIndex : INT_MAX;
-    int firstNotPointDegeneratesTest = run == RunAll ? 0 : run == RunNotPointDegenerates ? firstTestIndex : INT_MAX;
-    int firstLinesTest = run == RunAll ? 0 : run == RunLines ? firstTestIndex : INT_MAX;
-    int firstNotLinesTest = run == RunAll ? 0 : run == RunNotLines ? firstTestIndex : INT_MAX;
-    int firstModEpsilonTest = run == RunAll ? 0 : run == RunModEpsilonLines ? firstTestIndex : INT_MAX;
-    int firstLessEpsilonTest = run == RunAll ? 0 : run == RunLessEpsilonLines ? firstTestIndex : INT_MAX;
-    int firstNegEpsilonTest = run == RunAll ? 0 : run == RunNegEpsilonLines ? firstTestIndex : INT_MAX;
-    int firstQuadraticLineTest = run == RunAll ? 0 : run == RunQuadraticLines ? firstTestIndex : INT_MAX;
-    int firstQuadraticModLineTest = run == RunAll ? 0 : run == RunQuadraticModLines ? firstTestIndex : INT_MAX;
-    int firstComputedLinesTest = run == RunAll ? 0 : run == RunComputedLines ? firstTestIndex : INT_MAX;
-    int firstComputedCubicsTest = run == RunAll ? 0 : run == RunComputedTests ? firstTestIndex : INT_MAX;
+    int firstPointDegeneratesTest = run == RunAll ? 0 : run == RunPointDegenerates ? firstTestIndex : SK_MaxS32;
+    int firstNotPointDegeneratesTest = run == RunAll ? 0 : run == RunNotPointDegenerates ? firstTestIndex : SK_MaxS32;
+    int firstLinesTest = run == RunAll ? 0 : run == RunLines ? firstTestIndex : SK_MaxS32;
+    int firstNotLinesTest = run == RunAll ? 0 : run == RunNotLines ? firstTestIndex : SK_MaxS32;
+    int firstModEpsilonTest = run == RunAll ? 0 : run == RunModEpsilonLines ? firstTestIndex : SK_MaxS32;
+    int firstLessEpsilonTest = run == RunAll ? 0 : run == RunLessEpsilonLines ? firstTestIndex : SK_MaxS32;
+    int firstNegEpsilonTest = run == RunAll ? 0 : run == RunNegEpsilonLines ? firstTestIndex : SK_MaxS32;
+    int firstQuadraticLineTest = run == RunAll ? 0 : run == RunQuadraticLines ? firstTestIndex : SK_MaxS32;
+    int firstQuadraticModLineTest = run == RunAll ? 0 : run == RunQuadraticModLines ? firstTestIndex : SK_MaxS32;
+    int firstComputedLinesTest = run == RunAll ? 0 : run == RunComputedLines ? firstTestIndex : SK_MaxS32;
+    int firstComputedCubicsTest = run == RunAll ? 0 : run == RunComputedTests ? firstTestIndex : SK_MaxS32;
 
     test(pointDegenerates, "pointDegenerates", firstPointDegeneratesTest, pointDegenerates_count);
     test(notPointDegenerates, "notPointDegenerates", firstNotPointDegeneratesTest, notPointDegenerates_count);
@@ -191,8 +191,8 @@
         double precision = calcPrecision(cubic);
         (void) cubic_to_quadratics(cubic, precision, quads);
         int count = quads.count();
-        assert(count > 0);
-        assert(--count < arrayMax);
+        SkASSERT(count > 0);
+        SkASSERT(--count < arrayMax);
         quadDist[count]++;
         int sCount = sampleCount[count];
         if (sCount < sampleMax) {
diff --git a/experimental/Intersection/DataTypes.h b/experimental/Intersection/DataTypes.h
index ef9bcef..e3d18af 100644
--- a/experimental/Intersection/DataTypes.h
+++ b/experimental/Intersection/DataTypes.h
@@ -7,16 +7,10 @@
 #ifndef __DataTypes_h__
 #define __DataTypes_h__
 
-#include <assert.h>
-#include <float.h>
-#include <limits.h>
-#include <math.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <strings.h>
-#include <sys/types.h>
+#include <float.h> // for FLT_EPSILON
+#include <math.h> // for fabs, sqrt
+
+#include "SkTypes.h"
 
 extern bool AlmostEqualUlps(float A, float B);
 inline bool AlmostEqualUlps(double A, double B) { return AlmostEqualUlps((float) A, (float) B); }
@@ -146,14 +140,14 @@
 }
 
 inline bool approximately_between(double a, double b, double c) {
-    assert(a <= c);
+    SkASSERT(a <= c);
     return a <= c ? approximately_negative(a - b) && approximately_negative(b - c)
             : approximately_negative(b - a) && approximately_negative(c - b);
 }
 
 // returns true if (a <= b <= c) || (a >= b >= c)
 inline bool between(double a, double b, double c) {
-    assert(((a <= b && b <= c) || (a >= b && b >= c)) == ((a - b) * (c - b) <= 0));
+    SkASSERT(((a <= b && b <= c) || (a >= b && b >= c)) == ((a - b) * (c - b) <= 0));
     return (a - b) * (c - b) <= 0;
 }
 
@@ -252,10 +246,10 @@
     }
 
     bool intersects(_Rect& r) const {
-        assert(left <= right);
-        assert(top <= bottom);
-        assert(r.left <= r.right);
-        assert(r.top <= r.bottom);
+        SkASSERT(left <= right);
+        SkASSERT(top <= bottom);
+        SkASSERT(r.left <= r.right);
+        SkASSERT(r.top <= r.bottom);
         return r.left <= right && left <= r.right && r.top <= bottom && top <= r.bottom;
     }
 
diff --git a/experimental/Intersection/EdgeDemo.cpp b/experimental/Intersection/EdgeDemo.cpp
index 841678a..684dfd9 100644
--- a/experimental/Intersection/EdgeDemo.cpp
+++ b/experimental/Intersection/EdgeDemo.cpp
@@ -150,6 +150,7 @@
     return drawPaths(canvas, path, useOld);
 }
 
+#if 0
 static void tryRoncoOnce(const SkPath& path, const SkRect& target, bool show) {
     // capture everything in a desired rectangle
     SkPath tiny;
@@ -226,7 +227,9 @@
     }
     testSimplifyx(tiny);
 }
+#endif
 
+#if 0
 static void tryRonco(const SkPath& path) {
     int divMax = 64;
     int divMin = 1;
@@ -261,6 +264,7 @@
         }
     }
 }
+#endif
 
 static bool drawLetters(SkCanvas* canvas, int step, bool useOld)
 {
@@ -329,7 +333,7 @@
 
 static size_t drawDemosCount = sizeof(drawDemos) / sizeof(drawDemos[0]);
 
-static bool (*firstTest)(SkCanvas* , int , bool) = drawLetters;
+static bool (*firstTest)(SkCanvas* , int , bool) = drawStars;
 
 
 bool DrawEdgeDemo(SkCanvas* canvas, int step, bool useOld) {
diff --git a/experimental/Intersection/EdgeWalkerQuadratic4x4_Test.cpp b/experimental/Intersection/EdgeWalkerQuadratic4x4_Test.cpp
index 3a0a8f5..a55f6ab 100644
--- a/experimental/Intersection/EdgeWalkerQuadratic4x4_Test.cpp
+++ b/experimental/Intersection/EdgeWalkerQuadratic4x4_Test.cpp
@@ -8,7 +8,6 @@
 #include "Intersection_Tests.h"
 #include "SkBitmap.h"
 #include "SkCanvas.h"
-#include <assert.h>
 
 
 static void* testSimplify4x4QuadraticsMain(void* data)
diff --git a/experimental/Intersection/EdgeWalker_TestUtility.cpp b/experimental/Intersection/EdgeWalker_TestUtility.cpp
index de5967c..f0af4f4 100644
--- a/experimental/Intersection/EdgeWalker_TestUtility.cpp
+++ b/experimental/Intersection/EdgeWalker_TestUtility.cpp
@@ -12,7 +12,6 @@
 #include "SkStream.h"
 
 #include <algorithm>
-#include <assert.h>
 #include <errno.h>
 #include <pthread.h>
 #include <unistd.h>
@@ -581,7 +580,11 @@
 
     outFile.writeText("static void ");
     writeTestName(nameSuffix, outFile);
-    outFile.writeText("() {\n    SkPath path;\n");
+    outFile.writeText("() {\n    SkPath path");
+    if (!pathPrefix) {
+        outFile.writeText(", pathB");
+    }
+    outFile.writeText(";\n");
     if (pathPrefix) {
         outFile.writeText(pathPrefix);
     }
diff --git a/experimental/Intersection/Inline_Tests.cpp b/experimental/Intersection/Inline_Tests.cpp
index 00a1c6c..90f5e7a 100644
--- a/experimental/Intersection/Inline_Tests.cpp
+++ b/experimental/Intersection/Inline_Tests.cpp
@@ -12,7 +12,7 @@
     if (x == y) {
         return;
     }
-    printf("result=%d expected=%d %s\n", x, y, s);
+    SkDebugf("result=%d expected=%d %s\n", x, y, s);
 }
 
 static void side_test() {
@@ -41,7 +41,7 @@
             if (all == 0x0F) {
                 continue;
             }
-            printf("[%d,%d] other_two failed mask=%d [%d,%d]\n",
+            SkDebugf("[%d,%d] other_two failed mask=%d [%d,%d]\n",
                 x, y, mask, x ^ mask, y ^ mask);
         }
     }
diff --git a/experimental/Intersection/Intersection_Tests.cpp b/experimental/Intersection/Intersection_Tests.cpp
index 8b4052f..fc68da4 100644
--- a/experimental/Intersection/Intersection_Tests.cpp
+++ b/experimental/Intersection/Intersection_Tests.cpp
@@ -6,7 +6,6 @@
  */
 #include "CubicIntersection_TestData.h"
 #include "Intersection_Tests.h"
-#include "SkTypes.h"
 
 void cubecode_test(int test);
 
@@ -16,8 +15,9 @@
     int testsRun = 0;
 
     SimplifyNew_Test();
-    CubicToQuadratics_Test();
     CubicIntersection_OneOffTest();
+    ShapeOps4x4CubicsThreaded_Test(testsRun);
+    CubicToQuadratics_Test();
     QuadraticIntersection_Test();
     QuarticRoot_Test();
     CubicIntersection_RandTest();
diff --git a/experimental/Intersection/Intersection_Tests.h b/experimental/Intersection/Intersection_Tests.h
index 4bf3068..c5a6d33 100644
--- a/experimental/Intersection/Intersection_Tests.h
+++ b/experimental/Intersection/Intersection_Tests.h
@@ -41,6 +41,7 @@
 void Simplify4x4QuadraticsThreaded_Test(int& );
 void Simplify4x4RectsThreaded_Test(int& );
 void SimplifyRectangularPaths_Test();
+void ShapeOps4x4CubicsThreaded_Test(int& );
 void ShapeOps4x4RectsThreaded_Test(int& );
 void QuadLineIntersectThreaded_Test(int& );
 void QuadraticBezierClip_Test();
diff --git a/experimental/Intersection/Intersections.cpp b/experimental/Intersection/Intersections.cpp
index 2ed6a1d..cffeaec 100644
--- a/experimental/Intersection/Intersections.cpp
+++ b/experimental/Intersection/Intersections.cpp
@@ -9,7 +9,7 @@
 #include "Intersections.h"
 
 void Intersections::addCoincident(double s1, double e1, double s2, double e2) {
-    assert((fCoincidentUsed & 1) != 1);
+    SkASSERT((fCoincidentUsed & 1) != 1);
     for (int index = 0; index < fCoincidentUsed; index += 2) {
         double cs1 = fCoincidentT[fSwap][index];
         double ce1 = fCoincidentT[fSwap][index + 1];
@@ -20,7 +20,7 @@
         bool s2in = approximately_between(cs2, s2, ce2);
         bool e2in = approximately_between(cs2, e2, ce2);
         if ((s1in | e1in) & (s2in | e2in)) {
-            double lesser1 = std::min(cs1, ce1);
+            double lesser1 = SkTMin(cs1, ce1);
             index += cs1 > ce1;
             if (s1in < lesser1) {
                 fCoincidentT[fSwap][index] = s1in;
@@ -35,7 +35,7 @@
                 fCoincidentT[fSwap][index] = e1in;
             }
             index &= ~1;
-            double lesser2 = std::min(cs2, ce2);
+            double lesser2 = SkTMin(cs2, ce2);
             index += cs2 > ce2;
             if (s2in < lesser2) {
                 fCoincidentT[fSwap ^ 1][index] = s2in;
@@ -52,7 +52,7 @@
             return;
         }
     }
-    assert(fCoincidentUsed < 9);
+    SkASSERT(fCoincidentUsed < 9);
     fCoincidentT[fSwap][fCoincidentUsed] = s1;
     fCoincidentT[fSwap ^ 1][fCoincidentUsed] = s2;
     ++fCoincidentUsed;
@@ -62,15 +62,15 @@
 }
 
 void Intersections::cleanUp() {
-    assert(fCoincidentUsed);
-    assert(fUsed);
+    SkASSERT(fCoincidentUsed);
+    SkASSERT(fUsed);
     // find any entries in fT that could be part of the coincident range
 
 }
 
 // FIXME: this doesn't respect swap, but add coincident does -- seems inconsistent
 void Intersections::insert(double one, double two) {
-    assert(fUsed <= 1 || fT[0][0] < fT[0][1]);
+    SkASSERT(fUsed <= 1 || fT[0][0] < fT[0][1]);
     int index;
     for (index = 0; index < fUsed; ++index) {
         if (approximately_equal(fT[0][index], one)
@@ -81,7 +81,7 @@
             break;
         }
     }
-    assert(fUsed < 9);
+    SkASSERT(fUsed < 9);
     int remaining = fUsed - index;
     if (remaining > 0) {
         memmove(&fT[0][index + 1], &fT[0][index], sizeof(fT[0][0]) * remaining);
@@ -96,7 +96,7 @@
 // if two separate callers differ on whether ts are equal or not
 void Intersections::insertOne(double t, int side) {
     int used = side ? fUsed2 : fUsed;
-    assert(used <= 1 || fT[side][0] < fT[side][1]);
+    SkASSERT(used <= 1 || fT[side][0] < fT[side][1]);
     int index;
     for (index = 0; index < used; ++index) {
         if (approximately_equal(fT[side][index], t)) {
@@ -106,7 +106,7 @@
             break;
         }
     }
-    assert(used < 9);
+    SkASSERT(used < 9);
     int remaining = used - index;
     if (remaining > 0) {
         memmove(&fT[side][index + 1], &fT[side][index], sizeof(fT[side][0]) * remaining);
diff --git a/experimental/Intersection/Intersections.h b/experimental/Intersection/Intersections.h
index 26e0d9b..779ff33 100644
--- a/experimental/Intersection/Intersections.h
+++ b/experimental/Intersection/Intersections.h
@@ -7,9 +7,6 @@
 #ifndef Intersections_DEFINE
 #define Intersections_DEFINE
 
-#include <algorithm> // for std::min -- Skia doesn't have a SkMinDouble
-#include "SkTypes.h"
-
 class Intersections {
 public:
     Intersections()
@@ -29,7 +26,7 @@
                 return;
             }
         }
-        assert(fUsed < 9);
+        SkASSERT(fUsed < 9);
         fT[fSwap][fUsed] = one;
         fT[fSwap ^ 1][fUsed] = two;
         ++fUsed;
@@ -43,7 +40,7 @@
                 return;
             }
         }
-        assert(fCoincidentUsed < 9);
+        SkASSERT(fCoincidentUsed < 9);
         fCoincidentT[fSwap][fCoincidentUsed] = one;
         fCoincidentT[fSwap ^ 1][fCoincidentUsed] = two;
         ++fCoincidentUsed;
diff --git a/experimental/Intersection/LineIntersection.cpp b/experimental/Intersection/LineIntersection.cpp
index 5308a26..f5501db 100644
--- a/experimental/Intersection/LineIntersection.cpp
+++ b/experimental/Intersection/LineIntersection.cpp
@@ -7,7 +7,6 @@
 #include "CurveIntersection.h"
 #include "Intersections.h"
 #include "LineIntersection.h"
-#include <algorithm> // used for std::swap
 
 /* Determine the intersection point of two lines. This assumes the lines are not parallel,
    and that that the lines are infinite.
@@ -19,7 +18,7 @@
     double bxLen = b[1].x - b[0].x;
     double byLen = b[1].y - b[0].y;
     double denom = byLen * axLen - ayLen * bxLen;
-    assert(denom);
+    SkASSERT(denom);
     double term1 = a[1].x * a[0].y - a[1].y * a[0].x;
     double term2 = b[1].x * b[0].y - b[1].y * b[0].x;
     p.x = (term1 * bxLen - axLen * term2) / denom;
@@ -68,10 +67,10 @@
             double bMin = bPtr[0];
             double bMax = bPtr[2];
             if (aMin > aMax) {
-                std::swap(aMin, aMax);
+                SkTSwap(aMin, aMax);
             }
             if (bMin > bMax) {
-                std::swap(bMin, bMax);
+                SkTSwap(bMin, bMax);
             }
             if (aMax < bMin || bMax < aMin) {
                 return 0;
@@ -87,8 +86,8 @@
             }
             return 1 + ((aRange[0] != aRange[1]) || (bRange[0] != bRange[1]));
         #else
-            assert(aRange);
-            assert(bRange);
+            SkASSERT(aRange);
+            SkASSERT(bRange);
             double a0 = aPtr[0];
             double a1 = aPtr[2];
             double b0 = bPtr[0];
@@ -101,13 +100,18 @@
             if ((at0 < 0 && at1 < 0) || (at0 > 1 && at1 > 1)) {
                 return 0;
             }
-            aRange[0] = std::max(std::min(at0, 1.0), 0.0);
-            aRange[1] = std::max(std::min(at1, 1.0), 0.0);
+            aRange[0] = SkTMax(SkTMin(at0, 1.0), 0.0);
+            aRange[1] = SkTMax(SkTMin(at1, 1.0), 0.0);
             int bIn = (a0 - a1) * (b0 - b1) < 0;
-            bRange[bIn] = std::max(std::min((b0 - a0) / (b0 - b1), 1.0), 0.0);
-            bRange[!bIn] = std::max(std::min((b0 - a1) / (b0 - b1), 1.0), 0.0);
+            double bDenom = b0 - b1;
+            if (approximately_zero(bDenom)) {
+                bRange[0] = bRange[1] = 0;
+            } else {
+                bRange[bIn] = SkTMax(SkTMin((b0 - a0) / bDenom, 1.0), 0.0);
+                bRange[!bIn] = SkTMax(SkTMin((b0 - a1) / bDenom, 1.0), 0.0);
+            }
             bool second = fabs(aRange[0] - aRange[1]) > FLT_EPSILON;
-            assert((fabs(bRange[0] - bRange[1]) <= FLT_EPSILON) ^ second);
+            SkASSERT((fabs(bRange[0] - bRange[1]) <= FLT_EPSILON) ^ second);
             return 1 + second;
         #endif
         }
@@ -136,7 +140,7 @@
     double min = line[0].y;
     double max = line[1].y;
     if (min > max) {
-        std::swap(min, max);
+        SkTSwap(min, max);
     }
     if (min > y || max < y) {
         return 0;
@@ -192,10 +196,10 @@
             double lineL = line[0].x;
             double lineR = line[1].x;
             if (lineL > lineR) {
-                std::swap(lineL, lineR);
+                SkTSwap(lineL, lineR);
             }
-            double overlapL = std::max(left, lineL);
-            double overlapR = std::min(right, lineR);
+            double overlapL = SkTMax(left, lineL);
+            double overlapR = SkTMin(right, lineR);
             if (overlapL > overlapR) {
                 return 0;
             }
@@ -219,16 +223,16 @@
             if ((at0 < 0 && at1 < 0) || (at0 > 1 && at1 > 1)) {
                 return 0;
             }
-            intersections.fT[0][0] = std::max(std::min(at0, 1.0), 0.0);
-            intersections.fT[0][1] = std::max(std::min(at1, 1.0), 0.0);
+            intersections.fT[0][0] = SkTMax(SkTMin(at0, 1.0), 0.0);
+            intersections.fT[0][1] = SkTMax(SkTMin(at1, 1.0), 0.0);
             int bIn = (a0 - a1) * (b0 - b1) < 0;
-            intersections.fT[1][bIn] = std::max(std::min((b0 - a0) / (b0 - b1),
+            intersections.fT[1][bIn] = SkTMax(SkTMin((b0 - a0) / (b0 - b1),
                     1.0), 0.0);
-            intersections.fT[1][!bIn] = std::max(std::min((b0 - a1) / (b0 - b1),
+            intersections.fT[1][!bIn] = SkTMax(SkTMin((b0 - a1) / (b0 - b1),
                     1.0), 0.0);
             bool second = fabs(intersections.fT[0][0] - intersections.fT[0][1])
                     > FLT_EPSILON;
-            assert((fabs(intersections.fT[1][0] - intersections.fT[1][1])
+            SkASSERT((fabs(intersections.fT[1][0] - intersections.fT[1][1])
                     <= FLT_EPSILON) ^ second);
             return 1 + second;
         #endif
@@ -247,7 +251,7 @@
     double min = line[0].x;
     double max = line[1].x;
     if (min > max) {
-        std::swap(min, max);
+        SkTSwap(min, max);
     }
     if (min > x || max < x) {
         return 0;
@@ -281,10 +285,10 @@
             double lineT = line[0].y;
             double lineB = line[1].y;
             if (lineT > lineB) {
-                std::swap(lineT, lineB);
+                SkTSwap(lineT, lineB);
             }
-            double overlapT = std::max(top, lineT);
-            double overlapB = std::min(bottom, lineB);
+            double overlapT = SkTMax(top, lineT);
+            double overlapB = SkTMin(bottom, lineB);
             if (overlapT > overlapB) {
                 return 0;
             }
@@ -308,16 +312,16 @@
             if ((at0 < 0 && at1 < 0) || (at0 > 1 && at1 > 1)) {
                 return 0;
             }
-            intersections.fT[0][0] = std::max(std::min(at0, 1.0), 0.0);
-            intersections.fT[0][1] = std::max(std::min(at1, 1.0), 0.0);
+            intersections.fT[0][0] = SkTMax(SkTMin(at0, 1.0), 0.0);
+            intersections.fT[0][1] = SkTMax(SkTMin(at1, 1.0), 0.0);
             int bIn = (a0 - a1) * (b0 - b1) < 0;
-            intersections.fT[1][bIn] = std::max(std::min((b0 - a0) / (b0 - b1),
+            intersections.fT[1][bIn] = SkTMax(SkTMin((b0 - a0) / (b0 - b1),
                     1.0), 0.0);
-            intersections.fT[1][!bIn] = std::max(std::min((b0 - a1) / (b0 - b1),
+            intersections.fT[1][!bIn] = SkTMax(SkTMin((b0 - a1) / (b0 - b1),
                     1.0), 0.0);
             bool second = fabs(intersections.fT[0][0] - intersections.fT[0][1])
                     > FLT_EPSILON;
-            assert((fabs(intersections.fT[1][0] - intersections.fT[1][1])
+            SkASSERT((fabs(intersections.fT[1][0] - intersections.fT[1][1])
                     <= FLT_EPSILON) ^ second);
             return 1 + second;
         #endif
diff --git a/experimental/Intersection/LineParameters.h b/experimental/Intersection/LineParameters.h
index 8155ad8..637b3b6 100644
--- a/experimental/Intersection/LineParameters.h
+++ b/experimental/Intersection/LineParameters.h
@@ -81,7 +81,7 @@
     }
 
     double controlPtDistance(const Cubic& pts, int index) const {
-        assert(index == 1 || index == 2);
+        SkASSERT(index == 1 || index == 2);
         return a * pts[index].x + b * pts[index].y + c;
     }
 
diff --git a/experimental/Intersection/LineParameteters_Test.cpp b/experimental/Intersection/LineParameteters_Test.cpp
index 326477e..462ca16 100644
--- a/experimental/Intersection/LineParameteters_Test.cpp
+++ b/experimental/Intersection/LineParameteters_Test.cpp
@@ -57,7 +57,7 @@
             if (AlmostEqualUlps(distSq, normalSquared * answersSq)) {
                 continue;
             }
-            printf("%s [%d,%d] denormalizedDistance:%g != answer:%g"
+            SkDebugf("%s [%d,%d] denormalizedDistance:%g != answer:%g"
                     " distSq:%g answerSq:%g normalSquared:%g\n",
                     __FUNCTION__, (int)index, (int)inner,
                     denormalizedDistance[inner], answers[index][inner],
@@ -71,7 +71,7 @@
             if (AlmostEqualUlps(fabs(normalizedDistance[inner]), answers[index][inner])) {
                 continue;
             }
-            printf("%s [%d,%d] normalizedDistance:%1.10g != answer:%g\n",
+            SkDebugf("%s [%d,%d] normalizedDistance:%1.10g != answer:%g\n",
                     __FUNCTION__, (int)index, (int)inner,
                     normalizedDistance[inner], answers[index][inner]);
         }
diff --git a/experimental/Intersection/LineQuadraticIntersection_Test.cpp b/experimental/Intersection/LineQuadraticIntersection_Test.cpp
index 6167c6d..6c3986c 100644
--- a/experimental/Intersection/LineQuadraticIntersection_Test.cpp
+++ b/experimental/Intersection/LineQuadraticIntersection_Test.cpp
@@ -80,7 +80,7 @@
             double lineT = intersections.fT[1][inner];
             double lineX, lineY;
             xy_at_t(line, lineT, lineX, lineY);
-            assert(AlmostEqualUlps(quadX, lineX)
+            SkASSERT(AlmostEqualUlps(quadX, lineX)
                     && AlmostEqualUlps(quadY, lineY));
         }
     }
diff --git a/experimental/Intersection/QuadraticBezierClip.cpp b/experimental/Intersection/QuadraticBezierClip.cpp
index 6100914..0e948a0 100644
--- a/experimental/Intersection/QuadraticBezierClip.cpp
+++ b/experimental/Intersection/QuadraticBezierClip.cpp
@@ -7,7 +7,6 @@
 #include "CurveIntersection.h"
 #include "CurveUtilities.h"
 #include "LineParameters.h"
-#include <algorithm> // used for std::swap
 
 #define DEBUG_BEZIER_CLIP 1
 
@@ -24,7 +23,7 @@
     endLine.quadEndPoints(q1);
     if (!endLine.normalize()) {
         printf("line cannot be normalized: need more code here\n");
-        assert(0);
+        SkASSERT(0);
         return false;
     }
 
@@ -34,7 +33,7 @@
     double top = 0;
     double bottom = distance / 2; // http://students.cs.byu.edu/~tom/557/text/cic.pdf (7.6)
     if (top > bottom) {
-        std::swap(top, bottom);
+        SkTSwap(top, bottom);
     }
 
     // compute intersecting candidate distance
diff --git a/experimental/Intersection/QuadraticBezierClip_Test.cpp b/experimental/Intersection/QuadraticBezierClip_Test.cpp
index 4c6f0d7..0d25faf 100644
--- a/experimental/Intersection/QuadraticBezierClip_Test.cpp
+++ b/experimental/Intersection/QuadraticBezierClip_Test.cpp
@@ -50,10 +50,10 @@
         int order1 = reduceOrder(quad1, reduce1);
         int order2 = reduceOrder(quad2, reduce2);
         if (order1 < 3) {
-            printf("%s [%d] quad1 order=%d\n", __FUNCTION__, (int)index, order1);
+            SkDebugf("%s [%d] quad1 order=%d\n", __FUNCTION__, (int)index, order1);
         }
         if (order2 < 3) {
-            printf("%s [%d] quad2 order=%d\n", __FUNCTION__, (int)index, order2);
+            SkDebugf("%s [%d] quad2 order=%d\n", __FUNCTION__, (int)index, order2);
         }
         if (order1 == 3 && order2 == 3) {
             double minT = 0;
diff --git a/experimental/Intersection/QuadraticImplicit.cpp b/experimental/Intersection/QuadraticImplicit.cpp
index a72a57d..660ffe5 100644
--- a/experimental/Intersection/QuadraticImplicit.cpp
+++ b/experimental/Intersection/QuadraticImplicit.cpp
@@ -110,7 +110,7 @@
                 }
             }
         }
-        assert(i.fUsed < 3);
+        SkASSERT(i.fUsed < 3);
         return true;
 tryNextHalfPlane:
         ;
@@ -340,7 +340,7 @@
             perp[1].y += dxdy.x;
             Intersections hitData;
             int hits = intersectRay(*qs[qIdx ^ 1], perp, hitData);
-            assert(hits <= 1);
+            SkASSERT(hits <= 1);
             if (hits) {
                 if (flip < 0) {
                     _Point dxdy2;
@@ -397,7 +397,7 @@
         if ((t = axialIntersect(q2, q1[2], useVertical)) >= 0) {
             i.addCoincident(1, t);
         }
-        assert(i.fCoincidentUsed <= 2);
+        SkASSERT(i.fCoincidentUsed <= 2);
         return i.fCoincidentUsed > 0;
     }
     double roots1[4], roots2[4];
diff --git a/experimental/Intersection/QuadraticIntersection.cpp b/experimental/Intersection/QuadraticIntersection.cpp
index 9c2dee3..07b8ecf 100644
--- a/experimental/Intersection/QuadraticIntersection.cpp
+++ b/experimental/Intersection/QuadraticIntersection.cpp
@@ -76,7 +76,7 @@
                     smallT = minT1;
                 } else {
                     xy_at_t(quad1, maxT1, q1pt.x, q1pt.y); // FIXME: debug code
-                    assert(AlmostEqualUlps(q2pt.x, q1pt.x) && AlmostEqualUlps(q2pt.y, q1pt.y));
+                    SkASSERT(AlmostEqualUlps(q2pt.x, q1pt.x) && AlmostEqualUlps(q2pt.y, q1pt.y));
                     smallT = maxT1;
                 }
             } else {
@@ -87,7 +87,7 @@
                     largeT = minT2;
                 } else {
                     xy_at_t(quad2, maxT2, q2pt.x, q2pt.y); // FIXME: debug code
-                    assert(AlmostEqualUlps(q2pt.x, q1pt.x) && AlmostEqualUlps(q2pt.y, q1pt.y));
+                    SkASSERT(AlmostEqualUlps(q2pt.x, q1pt.x) && AlmostEqualUlps(q2pt.y, q1pt.y));
                     largeT = maxT2;
                 }
             }
@@ -127,9 +127,9 @@
 {
     _Line line1, line2;
     if (intersections.swapped()) {
-        std::swap(treat1AsLine, treat2AsLine);
-        std::swap(minT1, minT2);
-        std::swap(maxT1, maxT2);
+        SkTSwap(treat1AsLine, treat2AsLine);
+        SkTSwap(minT1, minT2);
+        SkTSwap(maxT1, maxT2);
     }
     if (coinMinT1 >= 0) {
         bool earlyExit;
@@ -388,7 +388,7 @@
         if ((t = axialIntersect(q2, q1[2], useVertical)) >= 0) {
             i.addCoincident(1, t);
         }
-        assert(i.fCoincidentUsed <= 2);
+        SkASSERT(i.fCoincidentUsed <= 2);
         return i.fCoincidentUsed > 0;
     }
     QuadraticIntersections q(q1, q2, i);
diff --git a/experimental/Intersection/QuadraticIntersection_Test.cpp b/experimental/Intersection/QuadraticIntersection_Test.cpp
index 055a18e8..41ccb8b 100644
--- a/experimental/Intersection/QuadraticIntersection_Test.cpp
+++ b/experimental/Intersection/QuadraticIntersection_Test.cpp
@@ -10,7 +10,6 @@
 #include "Intersections.h"
 #include "QuadraticIntersection_TestData.h"
 #include "TestUtilities.h"
-#include "SkTypes.h"
 
 const int firstQuadIntersectionTest = 9;
 
diff --git a/experimental/Intersection/QuadraticParameterization_Test.cpp b/experimental/Intersection/QuadraticParameterization_Test.cpp
index 95eaccd..eedd6a4 100644
--- a/experimental/Intersection/QuadraticParameterization_Test.cpp
+++ b/experimental/Intersection/QuadraticParameterization_Test.cpp
@@ -34,12 +34,12 @@
             for (size_t two = 0; two < quadsCount; ++two) {
                 for (size_t inner = 0; inner < 3; inner += 2) {
                     if (!point_on_parameterized_curve(*quads[one], (*quads[two])[inner])) {
-                            printf("%s %zu [%zu,%zu] %zu parameterization failed\n",
+                            SkDebugf("%s %zu [%zu,%zu] %zu parameterization failed\n",
                                 __FUNCTION__, index, one, two, inner);
                     }
                 }
                 if (!implicit_matches(*quads[one], *quads[two])) {
-                    printf("%s %zu [%zu,%zu] coincidence failed\n", __FUNCTION__,
+                    SkDebugf("%s %zu [%zu,%zu] coincidence failed\n", __FUNCTION__,
                             index, one, two);
                 }
             }
diff --git a/experimental/Intersection/QuadraticReduceOrder.cpp b/experimental/Intersection/QuadraticReduceOrder.cpp
index 096f6b6..700d4c5 100644
--- a/experimental/Intersection/QuadraticReduceOrder.cpp
+++ b/experimental/Intersection/QuadraticReduceOrder.cpp
@@ -63,7 +63,7 @@
         --endIndex;
         if (endIndex == 0) {
             printf("%s shouldn't get here if all four points are about equal", __FUNCTION__);
-            assert(0);
+            SkASSERT(0);
         }
     }
     if (!isLinear(quad, startIndex, endIndex)) {
diff --git a/experimental/Intersection/QuadraticReduceOrder_Test.cpp b/experimental/Intersection/QuadraticReduceOrder_Test.cpp
index 3f49b95..abf8fa7 100644
--- a/experimental/Intersection/QuadraticReduceOrder_Test.cpp
+++ b/experimental/Intersection/QuadraticReduceOrder_Test.cpp
@@ -8,7 +8,6 @@
 #include "Intersection_Tests.h"
 #include "QuadraticIntersection_TestData.h"
 #include "TestUtilities.h"
-#include "SkTypes.h"
 
 static const Quadratic testSet[] = {
     {{1, 1}, {2, 2}, {1, 1.000003}},
@@ -43,8 +42,8 @@
     run = RunQuadraticLines;
     firstTestIndex = 1;
 #endif
-    int firstQuadraticLineTest = run == RunAll ? 0 : run == RunQuadraticLines ? firstTestIndex : INT_MAX;
-    int firstQuadraticModLineTest = run == RunAll ? 0 : run == RunQuadraticModLines ? firstTestIndex : INT_MAX;
+    int firstQuadraticLineTest = run == RunAll ? 0 : run == RunQuadraticLines ? firstTestIndex : SK_MaxS32;
+    int firstQuadraticModLineTest = run == RunAll ? 0 : run == RunQuadraticModLines ? firstTestIndex : SK_MaxS32;
 
     for (index = firstQuadraticLineTest; index < quadraticLines_count; ++index) {
         const Quadratic& quad = quadraticLines[index];
diff --git a/experimental/Intersection/QuadraticUtilities.cpp b/experimental/Intersection/QuadraticUtilities.cpp
index d8755a3..32f95ed 100644
--- a/experimental/Intersection/QuadraticUtilities.cpp
+++ b/experimental/Intersection/QuadraticUtilities.cpp
@@ -5,7 +5,6 @@
  * found in the LICENSE file.
  */
 #include "QuadraticUtilities.h"
-#include "SkTypes.h"
 #include <math.h>
 
 /*
diff --git a/experimental/Intersection/QuarticRoot.cpp b/experimental/Intersection/QuarticRoot.cpp
index 6941935..759e209 100644
--- a/experimental/Intersection/QuarticRoot.cpp
+++ b/experimental/Intersection/QuarticRoot.cpp
@@ -58,7 +58,7 @@
         return num;
     }
     if (oneHint) {
-        assert(approximately_zero(t4 + t3 + t2 + t1 + t0)); // 1 is one root
+        SkASSERT(approximately_zero(t4 + t3 + t2 + t1 + t0)); // 1 is one root
         int num = cubicRootsReal(t4, t4 + t3, -(t1 + t0), -t0, roots); // note that -C==A+B+D+E
         for (int i = 0; i < num; ++i) {
             if (approximately_equal(roots[i], 1)) {
diff --git a/experimental/Intersection/QuarticRoot_Test.cpp b/experimental/Intersection/QuarticRoot_Test.cpp
index 027d19b..18a3a8d 100644
--- a/experimental/Intersection/QuarticRoot_Test.cpp
+++ b/experimental/Intersection/QuarticRoot_Test.cpp
@@ -1,5 +1,3 @@
-#include <assert.h>
-#include <math.h>
 #include "CubicUtilities.h"
 #include "Intersection_Tests.h"
 #include "QuadraticUtilities.h"
@@ -41,15 +39,15 @@
                 } else {
                     expected = 1 + (B != C);
                 }
-                assert(rootCount == expected);
+                SkASSERT(rootCount == expected);
                 if (!rootCount) {
                     continue;
                 }
-                assert(approximately_equal(roots[0], -B)
+                SkASSERT(approximately_equal(roots[0], -B)
                         || approximately_equal(roots[0], -C));
                 if (expected > 1) {
-                    assert(!approximately_equal(roots[0], roots[1]));
-                    assert(approximately_equal(roots[1], -B)
+                    SkASSERT(!approximately_equal(roots[0], roots[1]));
+                    SkASSERT(approximately_equal(roots[1], -B)
                             || approximately_equal(roots[1], -C));
                 }
             }
@@ -81,26 +79,26 @@
     } else {
         expected = 1 + (B != C) + (B != D && C != D);
     }
-    assert(rootCount == expected);
+    SkASSERT(rootCount == expected);
     if (!rootCount) {
         return;
     }
-    assert(approximately_equal(roots[0], -B)
+    SkASSERT(approximately_equal(roots[0], -B)
             || approximately_equal(roots[0], -C)
             || approximately_equal(roots[0], -D));
     if (expected <= 1) {
         return;
     }
-    assert(!approximately_equal(roots[0], roots[1]));
-    assert(approximately_equal(roots[1], -B)
+    SkASSERT(!approximately_equal(roots[0], roots[1]));
+    SkASSERT(approximately_equal(roots[1], -B)
             || approximately_equal(roots[1], -C)
             || approximately_equal(roots[1], -D));
     if (expected <= 2) {
         return;
     }
-    assert(!approximately_equal(roots[0], roots[2])
+    SkASSERT(!approximately_equal(roots[0], roots[2])
             && !approximately_equal(roots[1], roots[2]));
-    assert(approximately_equal(roots[2], -B)
+    SkASSERT(approximately_equal(roots[2], -B)
             || approximately_equal(roots[2], -C)
             || approximately_equal(roots[2], -D));
 }
@@ -136,35 +134,35 @@
         rootCount = quarticRootsReal(A, b, c, d, e, roots);
     }
     const int expected = 1 + (B != C) + (B != D && C != D) + (B != E && C != E && D != E);
-    assert(rootCount == expected);
-    assert(AlmostEqualUlps(roots[0], -B)
+    SkASSERT(rootCount == expected);
+    SkASSERT(AlmostEqualUlps(roots[0], -B)
             || AlmostEqualUlps(roots[0], -C)
             || AlmostEqualUlps(roots[0], -D)
             || AlmostEqualUlps(roots[0], -E));
     if (expected <= 1) {
         return;
     }
-    assert(!AlmostEqualUlps(roots[0], roots[1]));
-    assert(AlmostEqualUlps(roots[1], -B)
+    SkASSERT(!AlmostEqualUlps(roots[0], roots[1]));
+    SkASSERT(AlmostEqualUlps(roots[1], -B)
             || AlmostEqualUlps(roots[1], -C)
             || AlmostEqualUlps(roots[1], -D)
             || AlmostEqualUlps(roots[1], -E));
     if (expected <= 2) {
         return;
     }
-    assert(!AlmostEqualUlps(roots[0], roots[2])
+    SkASSERT(!AlmostEqualUlps(roots[0], roots[2])
             && !AlmostEqualUlps(roots[1], roots[2]));
-    assert(AlmostEqualUlps(roots[2], -B)
+    SkASSERT(AlmostEqualUlps(roots[2], -B)
             || AlmostEqualUlps(roots[2], -C)
             || AlmostEqualUlps(roots[2], -D)
             || AlmostEqualUlps(roots[2], -E));
     if (expected <= 3) {
         return;
     }
-    assert(!AlmostEqualUlps(roots[0], roots[3])
+    SkASSERT(!AlmostEqualUlps(roots[0], roots[3])
             && !AlmostEqualUlps(roots[1], roots[3])
             && !AlmostEqualUlps(roots[2], roots[3]));
-    assert(AlmostEqualUlps(roots[3], -B)
+    SkASSERT(AlmostEqualUlps(roots[3], -B)
             || AlmostEqualUlps(roots[3], -C)
             || AlmostEqualUlps(roots[3], -D)
             || AlmostEqualUlps(roots[3], -E));
diff --git a/experimental/Intersection/ShapeOpCubic4x4_Test.cpp b/experimental/Intersection/ShapeOpCubic4x4_Test.cpp
new file mode 100644
index 0000000..607b349
--- /dev/null
+++ b/experimental/Intersection/ShapeOpCubic4x4_Test.cpp
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include "EdgeWalker_Test.h"
+#include "Intersection_Tests.h"
+#include "ShapeOps.h"
+
+// four rects, of four sizes
+// for 3 smaller sizes, tall, wide
+    // top upper mid lower bottom aligned (3 bits, 5 values)
+    // same with x (3 bits, 5 values)
+// not included, square, tall, wide (2 bits)
+// cw or ccw (1 bit)
+
+static void* testShapeOps4x4CubicsMain(void* data)
+{
+    SkASSERT(data);
+    State4& state = *(State4*) data;
+    char pathStr[1024]; // gdb: set print elements 400
+    bzero(pathStr, sizeof(pathStr));
+    do {
+        for (int a = 0 ; a < 6; ++a) {
+        for (int b = a + 1 ; b < 7; ++b)  {
+        for (int c = 0 ; c < 6; ++c)          {
+        for (int d = c + 1 ; d < 7; ++d)           {
+        for (int e = SkPath::kWinding_FillType ; e <= SkPath::kEvenOdd_FillType; ++e) {
+        for (int f = SkPath::kWinding_FillType ; f <= SkPath::kEvenOdd_FillType; ++f)   {
+            SkPath pathA, pathB;
+            char* str = pathStr;
+            pathA.setFillType((SkPath::FillType) e);
+            str += sprintf(str, "    path.setFillType(SkPath::k%s_FillType);\n",
+                    e == SkPath::kWinding_FillType ? "Winding" : e == SkPath::kEvenOdd_FillType
+                    ? "EvenOdd" : "?UNDEFINED");
+            pathA.moveTo(state.a, state.b);
+            str += sprintf(str, "    path.moveTo(%d,%d);\n", state.a, state.b);
+            pathA.cubicTo(state.c, state.d, b, a, d, c);
+            str += sprintf(str, "    path.cubicTo(%d,%d, %d,%d, %d,%d);\n", state.c, state.d,
+                    b, a, d, c);
+            pathA.close();
+            str += sprintf(str, "    path.close();\n");
+            pathB.setFillType((SkPath::FillType) f);
+            str += sprintf(str, "    pathB.setFillType(SkPath::k%s_FillType);\n",
+                    f == SkPath::kWinding_FillType ? "Winding" : f == SkPath::kEvenOdd_FillType
+                    ? "EvenOdd" : "?UNDEFINED");
+            pathB.moveTo(a, b);
+            str += sprintf(str, "    pathB.moveTo(%d,%d);\n", a, b);
+            pathB.cubicTo(c, d, state.b, state.a, state.d, state.c);
+            str += sprintf(str, "    pathB.cubicTo(%d,%d, %d,%d, %d,%d);\n", c, d, 
+                    state.b, state.a, state.d, state.c);
+            pathB.close();
+            str += sprintf(str, "    pathB.close();\n");
+            for (int op = 0 ; op < kShapeOp_Count; ++op)    {
+                outputProgress(state, pathStr, (ShapeOp) op);
+                testShapeOp(pathA, pathB, (ShapeOp) op);
+                state.testsRun++;
+            }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+    } while (runNextTestSet(state));
+    return NULL;
+}
+
+void ShapeOps4x4CubicsThreaded_Test(int& testsRun)
+{
+    SkDebugf("%s\n", __FUNCTION__);
+#ifdef SK_DEBUG
+    gDebugMaxWindSum = 4;
+    gDebugMaxWindValue = 4;
+#endif
+    const char testLineStr[] = "cubicOp";
+    initializeTests(testLineStr, sizeof(testLineStr));
+    int testsStart = testsRun;
+    for (int a = 0; a < 6; ++a) { // outermost
+        for (int b = a + 1; b < 7; ++b) {
+            for (int c = 0 ; c < 6; ++c) {
+                for (int d = c + 1; d < 7; ++d) {
+                    testsRun += dispatchTest4(testShapeOps4x4CubicsMain, a, b, c, d);
+                }
+                if (!gRunTestsInOneThread) SkDebugf(".");
+            }
+            if (!gRunTestsInOneThread) SkDebugf("%d", b);
+        }
+        if (!gRunTestsInOneThread) SkDebugf("\n%d", a);
+    }
+    testsRun += waitForCompletion();
+    SkDebugf("%s tests=%d total=%d\n", __FUNCTION__, testsRun - testsStart, testsRun);
+}
diff --git a/experimental/Intersection/ShapeOpRect4x4_Test.cpp b/experimental/Intersection/ShapeOpRect4x4_Test.cpp
index d149377..e6e44c1 100644
--- a/experimental/Intersection/ShapeOpRect4x4_Test.cpp
+++ b/experimental/Intersection/ShapeOpRect4x4_Test.cpp
@@ -26,7 +26,6 @@
         for (int b = a + 1 ; b < 7; ++b)  {
         for (int c = 0 ; c < 6; ++c)          {
         for (int d = c + 1 ; d < 7; ++d)           {
-        for (int op = 0 ; op < kShapeOp_Count; ++op)    {
         for (int e = SkPath::kWinding_FillType ; e <= SkPath::kEvenOdd_FillType; ++e) {
         for (int f = SkPath::kWinding_FillType ; f <= SkPath::kEvenOdd_FillType; ++f)   {
             SkPath pathA, pathB;
@@ -53,19 +52,11 @@
             str += sprintf(str, "    pathB.addRect(%d, %d, %d, %d,"
                     " SkPath::kCW_Direction);\n", c, c, d, d);
             pathB.close();
-            outputProgress(state, pathStr, kDifference_Op);
-            testShapeOp(pathA, pathB, kDifference_Op);
-            state.testsRun++;
-            outputProgress(state, pathStr, kIntersect_Op);
-            testShapeOp(pathA, pathB, kIntersect_Op);
-            state.testsRun++;
-            outputProgress(state, pathStr, kUnion_Op);
-            testShapeOp(pathA, pathB, kUnion_Op);
-            state.testsRun++;
-            outputProgress(state, pathStr, kXor_Op);
-            testShapeOp(pathA, pathB, kXor_Op);
-            state.testsRun++;
-                                    }
+            for (int op = 0 ; op < kShapeOp_Count; ++op)    {
+                outputProgress(state, pathStr, (ShapeOp) op);
+                testShapeOp(pathA, pathB, (ShapeOp) op);
+                state.testsRun++;
+            }
                                 }
                             }
                         }
diff --git a/experimental/Intersection/Simplify.cpp b/experimental/Intersection/Simplify.cpp
index 10196db..ad3767a 100644
--- a/experimental/Intersection/Simplify.cpp
+++ b/experimental/Intersection/Simplify.cpp
@@ -392,34 +392,19 @@
     CubicSubDivide
 };
 
-static void LineSubDivideHD(const SkPoint a[2], double startT, double endT,
-        _Line sub) {
+static void LineSubDivideHD(const SkPoint a[2], double startT, double endT, _Line& dst) {
     MAKE_CONST_LINE(aLine, a);
-    _Line dst;
     sub_divide(aLine, startT, endT, dst);
-    sub[0] = dst[0];
-    sub[1] = dst[1];
 }
 
-static void QuadSubDivideHD(const SkPoint a[3], double startT, double endT,
-        Quadratic sub) {
+static void QuadSubDivideHD(const SkPoint a[3], double startT, double endT, Quadratic& dst) {
     MAKE_CONST_QUAD(aQuad, a);
-    Quadratic dst;
     sub_divide(aQuad, startT, endT, dst);
-    sub[0] = dst[0];
-    sub[1] = dst[1];
-    sub[2] = dst[2];
 }
 
-static void CubicSubDivideHD(const SkPoint a[4], double startT, double endT,
-        Cubic sub) {
+static void CubicSubDivideHD(const SkPoint a[4], double startT, double endT, Cubic& dst) {
     MAKE_CONST_CUBIC(aCubic, a);
-    Cubic dst;
     sub_divide(aCubic, startT, endT, dst);
-    sub[0] = dst[0];
-    sub[1] = dst[1];
-    sub[2] = dst[2];
-    sub[3] = dst[3];
 }
 
 #if DEBUG_UNUSED
@@ -780,12 +765,27 @@
         case SkPath::kQuad_Verb:
             QuadSubDivideHD(fPts, startT, endT, fQ);
             fTangent1.quadEndPoints(fQ, 0, 1);
+        #if 1 // FIXME: try enabling this and see if a) it's called and b) does it break anything
+            if (dx() == 0 && dy() == 0) {
+                SkDebugf("*** %s quad is line\n");
+                fTangent1.quadEndPoints(fQ);
+            }
+        #endif
             fSide = -fTangent1.pointDistance(fQ[2]); // not normalized -- compare sign only
             break;
         case SkPath::kCubic_Verb:
             Cubic c;
             CubicSubDivideHD(fPts, startT, endT, c);
             fTangent1.cubicEndPoints(c, 0, 1);
+            if (dx() == 0 && dy() == 0) {
+                fTangent1.cubicEndPoints(c, 0, 2);
+        #if 1 // FIXME: try enabling this and see if a) it's called and b) does it break anything
+                if (dx() == 0 && dy() == 0) {
+                    SkDebugf("*** %s cubic is line\n");
+                    fTangent1.cubicEndPoints(c, 0, 3);
+                }
+        #endif
+            }
             fSide = -fTangent1.pointDistance(c[2]); // not normalized -- compare sign only
             break;
         default:
@@ -1792,7 +1792,7 @@
     }
 
     // FIXME: this doesn't prevent the same span from being added twice
-    // fix in caller, assert here?
+    // fix in caller, SkASSERT here?
     void addTPair(double t, Segment& other, double otherT, bool borrowWind) {
         int tCount = fTs.count();
         for (int tIndex = 0; tIndex < tCount; ++tIndex) {
@@ -3346,7 +3346,9 @@
         const Span& endSpan = fTs[end];
         Segment* other = endSpan.fOther;
         index = endSpan.fOtherIndex;
+        SkASSERT(index >= 0);
         int otherEnd = other->nextExactSpan(index, step);
+        SkASSERT(otherEnd >= 0);
         min = SkMin32(index, otherEnd);
         return other;
     }
@@ -3765,7 +3767,7 @@
 #endif
 
 #if DEBUG_CONCIDENT
-    // assert if pair has not already been added
+    // SkASSERT if pair has not already been added
      void debugAddTPair(double t, const Segment& other, double otherT) const {
         for (int i = 0; i < fTs.count(); ++i) {
             if (fTs[i].fT == t && fTs[i].fOther == &other && fTs[i].fOtherT == otherT) {
@@ -6051,7 +6053,7 @@
     eLink.setCount(count);
     int rIndex, iIndex;
     for (rIndex = 0; rIndex < count; ++rIndex) {
-        sLink[rIndex] = eLink[rIndex] = INT_MAX;
+        sLink[rIndex] = eLink[rIndex] = SK_MaxS32;
     }
     SkTDArray<double> distances;
     const int ends = count * 2; // all starts and ends
@@ -6088,14 +6090,14 @@
         int ndxOne = thingOne >> 1;
         bool endOne = thingOne & 1;
         int* linkOne = endOne ? eLink.begin() : sLink.begin();
-        if (linkOne[ndxOne] != INT_MAX) {
+        if (linkOne[ndxOne] != SK_MaxS32) {
             continue;
         }
         int thingTwo = row < col ? col : ends - row + col - 1;
         int ndxTwo = thingTwo >> 1;
         bool endTwo = thingTwo & 1;
         int* linkTwo = endTwo ? eLink.begin() : sLink.begin();
-        if (linkTwo[ndxTwo] != INT_MAX) {
+        if (linkTwo[ndxTwo] != SK_MaxS32) {
             continue;
         }
         SkASSERT(&linkOne[ndxOne] != &linkTwo[ndxTwo]);
@@ -6120,17 +6122,17 @@
         bool forward = true;
         bool first = true;
         int sIndex = sLink[rIndex];
-        SkASSERT(sIndex != INT_MAX);
-        sLink[rIndex] = INT_MAX;
+        SkASSERT(sIndex != SK_MaxS32);
+        sLink[rIndex] = SK_MaxS32;
         int eIndex;
         if (sIndex < 0) {
             eIndex = sLink[~sIndex];
-            sLink[~sIndex] = INT_MAX;
+            sLink[~sIndex] = SK_MaxS32;
         } else {
             eIndex = eLink[sIndex];
-            eLink[sIndex] = INT_MAX;
+            eLink[sIndex] = SK_MaxS32;
         }
-        SkASSERT(eIndex != INT_MAX);
+        SkASSERT(eIndex != SK_MaxS32);
 #if DEBUG_ASSEMBLE
         SkDebugf("%s sIndex=%c%d eIndex=%c%d\n", __FUNCTION__, sIndex < 0 ? 's' : 'e',
                     sIndex < 0 ? ~sIndex : sIndex, eIndex < 0 ? 's' : 'e',
@@ -6160,25 +6162,25 @@
             }
             if (forward) {
                 eIndex = eLink[rIndex];
-                SkASSERT(eIndex != INT_MAX);
-                eLink[rIndex] = INT_MAX;
+                SkASSERT(eIndex != SK_MaxS32);
+                eLink[rIndex] = SK_MaxS32;
                 if (eIndex >= 0) {
                     SkASSERT(sLink[eIndex] == rIndex);
-                    sLink[eIndex] = INT_MAX;
+                    sLink[eIndex] = SK_MaxS32;
                 } else {
                     SkASSERT(eLink[~eIndex] == ~rIndex);
-                    eLink[~eIndex] = INT_MAX;
+                    eLink[~eIndex] = SK_MaxS32;
                 }
             } else {
                 eIndex = sLink[rIndex];
-                SkASSERT(eIndex != INT_MAX);
-                sLink[rIndex] = INT_MAX;
+                SkASSERT(eIndex != SK_MaxS32);
+                sLink[rIndex] = SK_MaxS32;
                 if (eIndex >= 0) {
                     SkASSERT(eLink[eIndex] == rIndex);
-                    eLink[eIndex] = INT_MAX;
+                    eLink[eIndex] = SK_MaxS32;
                 } else {
                     SkASSERT(sLink[~eIndex] == ~rIndex);
-                    sLink[~eIndex] = INT_MAX;
+                    sLink[~eIndex] = SK_MaxS32;
                 }
             }
             rIndex = eIndex;
@@ -6188,15 +6190,15 @@
             }
         } while (true);
         for (rIndex = 0; rIndex < count; ++rIndex) {
-            if (sLink[rIndex] != INT_MAX) {
+            if (sLink[rIndex] != SK_MaxS32) {
                 break;
             }
         }
     } while (rIndex < count);
 #if DEBUG_ASSEMBLE
     for (rIndex = 0; rIndex < count; ++rIndex) {
-       SkASSERT(sLink[rIndex] == INT_MAX);
-       SkASSERT(eLink[rIndex] == INT_MAX);
+       SkASSERT(sLink[rIndex] == SK_MaxS32);
+       SkASSERT(eLink[rIndex] == SK_MaxS32);
     }
 #endif
 }
diff --git a/experimental/Intersection/Simplify.h b/experimental/Intersection/Simplify.h
index 111daf0..d2e238f 100644
--- a/experimental/Intersection/Simplify.h
+++ b/experimental/Intersection/Simplify.h
@@ -15,4 +15,3 @@
 #include "SkTDArray.h"
 #include "ShapeOps.h"
 #include "TSearch.h"
-#include <algorithm> // used for std::min
diff --git a/experimental/Intersection/SimplifyNew_Test.cpp b/experimental/Intersection/SimplifyNew_Test.cpp
index 4cad7e1..aa0a45b 100644
--- a/experimental/Intersection/SimplifyNew_Test.cpp
+++ b/experimental/Intersection/SimplifyNew_Test.cpp
@@ -3536,6 +3536,7 @@
     testSimplifyx(path);
 }
 
+#if 0
 static void testQuadratic93() {
     SkPath path;
     path.moveTo(3, 0);
@@ -3548,6 +3549,20 @@
     path.close();
     testSimplifyx(path);
 }
+#endif
+
+static void cubicOp1d() {
+    SkPath path, pathB;
+    path.setFillType(SkPath::kWinding_FillType);
+    path.moveTo(0,1);
+    path.cubicTo(0,2, 1,0, 1,0);
+    path.close();
+    pathB.setFillType(SkPath::kWinding_FillType);
+    pathB.moveTo(0,1);
+    pathB.cubicTo(0,1, 1,0, 2,0);
+    pathB.close();
+    testShapeOp(path, pathB, kDifference_Op);
+}
 
 static void (*firstTest)() = 0;
 
@@ -3555,7 +3570,8 @@
     void (*fun)();
     const char* str;
 } tests[] = {
-    TEST(testQuadratic93),
+    TEST(cubicOp1d),
+ //   TEST(testQuadratic93),    // FIXME: gets stuck in a loop because top is unsortable
     TEST(testCubic1),
     TEST(testQuadralateral1),
     TEST(testLine85),
diff --git a/experimental/Intersection/TSearch.h b/experimental/Intersection/TSearch.h
index 6952425..2635470 100644
--- a/experimental/Intersection/TSearch.h
+++ b/experimental/Intersection/TSearch.h
@@ -7,8 +7,6 @@
 #ifndef TSearch_DEFINED
 #define TSearch_DEFINED
 
-#include "SkTypes.h"
-
 // FIXME: Move this templated version into SKTSearch.h
 
 template <typename T>
diff --git a/experimental/Intersection/op.htm b/experimental/Intersection/op.htm
index e2db44b..94d8adf 100644
--- a/experimental/Intersection/op.htm
+++ b/experimental/Intersection/op.htm
@@ -3328,11 +3328,23 @@
     path.close();
 </div>
 
+<div id="cubicOp1d">
+    path.setFillType(SkPath::kWinding_FillType);
+    path.moveTo(0,1);
+    path.cubicTo(0,2, 1,0, 1,0);
+    path.close();
+    pathB.setFillType(SkPath::kWinding_FillType);
+    pathB.moveTo(0,1);
+    pathB.cubicTo(0,1, 1,0, 2,0);
+    pathB.close();
+</div>
+
 </div>
 
 <script type="text/javascript">
 
 var testDivs = [
+    cubicOp1d,
     testQuadratic93,
     testCubic1,
     testQuadralateral1,
diff --git a/experimental/Intersection/qc.htm b/experimental/Intersection/qc.htm
index 9b1cbbe..2053b9b 100644
--- a/experimental/Intersection/qc.htm
+++ b/experimental/Intersection/qc.htm
@@ -1703,11 +1703,26 @@
 {{x = 0.30387252963474076, y = 0.69616688005807803}, {x = 0.3039751936710845, y = 0.69622610811401087}}
 </div>
 
+<div id="cubicOp1d">
+{{0, 1}, {0, 2}, {1, 0}, {1, 0}},
+{{0, 1}, {0, 1}, {1, 0}, {2, 0}},
+
+  {{0,1}, {0.0078125,1.35546875}, {0.15625,1.265625}},
+  {{0.15625,1.265625}, {0.3046875,1.17578125}, {0.5,0.875}},
+  {{0.5,0.875}, {0.6953125,0.57421875}, {0.84375,0.296875}},
+  {{0.84375,0.296875}, {0.9921875,0.01953125}, {1,0}},
+
+  {{0,1}, {0.00925925926,0.981481481}, {0.296296296,0.740740741}},
+  {{0.296296296,0.740740741}, {0.583333333,0.5}, {1.03703704,0.259259259}},
+  {{1.03703704,0.259259259}, {1.49074074,0.0185185185}, {2,0}},
+</div>
+
 </div>
 
 <script type="text/javascript">
 
 var testDivs = [
+    cubicOp1d,
     testCubic1b,
     testCubic1a,
     testCubic1,
diff --git a/experimental/SimpleCocoaApp/SimpleApp.mm b/experimental/SimpleCocoaApp/SimpleApp.mm
index 922177e..7dac2a4 100644
--- a/experimental/SimpleCocoaApp/SimpleApp.mm
+++ b/experimental/SimpleCocoaApp/SimpleApp.mm
@@ -1,8 +1,53 @@
-#import "SkCanvas.h"
-#import "SkPaint.h"
-#import "SkWindow.h"
-#include "SkGraphics.h"
+#include "SkCanvas.h"
 #include "SkCGUtils.h"
+#include "SkGraphics.h"
+#include "SkImageDecoder.h"
+#include "SkOSFile.h"
+#include "SkPaint.h"
+#include "SkPicture.h"
+#include "SkStream.h"
+#include "SkWindow.h"
+
+static void make_filepath(SkString* path, const char* dir, const SkString& name) {
+    size_t len = strlen(dir);
+    path->set(dir);
+    if (len > 0 && dir[len - 1] != '/') {
+        path->append("/");
+    }
+    path->append(name);
+}
+
+static SkPicture* LoadPicture(const char path[]) {
+    SkPicture* pic = NULL;
+
+    SkBitmap bm;
+    if (SkImageDecoder::DecodeFile(path, &bm)) {
+        bm.setImmutable();
+        pic = SkNEW(SkPicture);
+        SkCanvas* can = pic->beginRecording(bm.width(), bm.height());
+        can->drawBitmap(bm, 0, 0, NULL);
+        pic->endRecording();
+    } else {
+        SkFILEStream stream(path);
+        if (stream.isValid()) {
+            pic = SkNEW_ARGS(SkPicture,
+                             (&stream, NULL, &SkImageDecoder::DecodeStream));
+        }
+
+        if (false) { // re-record
+            SkPicture p2;
+            pic->draw(p2.beginRecording(pic->width(), pic->height()));
+            p2.endRecording();
+
+            SkString path2(path);
+            path2.append(".new.skp");
+            SkFILEWStream writer(path2.c_str());
+            p2.serialize(&writer);
+        }
+    }
+    return pic;
+}
+
 class SkSampleView : public SkView {
 public:
     SkSampleView() {
@@ -16,17 +61,216 @@
         p.setTextSize(20);
         p.setAntiAlias(true);
         canvas->drawText("Hello World!", 13, 50, 30, p);
-        SkRect r = {50, 50, 80, 80};
+     //   SkRect r = {50, 50, 80, 80};
         p.setColor(0xAA11EEAA);
-        canvas->drawRect(r, p);
+   //     canvas->drawRect(r, p);
+        
+        SkRect result;
+        SkPath path;
+        path.moveTo(0, 0);
+        path.lineTo(1, 1);
+        path.lineTo(1, 8);
+        path.lineTo(0, 9);
+        SkASSERT(path.hasRectangularInterior(&result));
+        
+        path.reset();
+        path.addRect(10, 10, 100, 100, SkPath::kCW_Direction);
+        path.addRect(20, 20, 50, 50, SkPath::kCW_Direction);
+        path.addRect(50, 50, 90, 90, SkPath::kCCW_Direction);
+        p.setColor(0xAA335577);
+        canvas->drawPath(path, p);
+        SkASSERT(!path.hasRectangularInterior(NULL));
+        path.reset();
+        path.addRect(10, 10, 100, 100, SkPath::kCW_Direction);
+        path.addRect(20, 20, 80, 80, SkPath::kCW_Direction);
+        SkRect expected = {20, 20, 80, 80};
+        SkASSERT(path.hasRectangularInterior(&result));
+        SkASSERT(result == expected);
+
     }
 private:
     typedef SkView INHERITED; 
 };
 
+void application_init();
+void application_term();
+
+static int showPathContour(SkPath::Iter& iter) {
+    uint8_t verb;
+    SkPoint pts[4];
+    int moves = 0;
+    bool waitForClose = false;
+    while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
+        switch (verb) {
+            case SkPath::kMove_Verb:
+                if (!waitForClose) {
+                    ++moves;
+                    waitForClose = true;
+                }
+                SkDebugf("path.moveTo(%1.9g, %1.9g);\n", pts[0].fX, pts[0].fY);
+                break;
+            case SkPath::kLine_Verb:
+                SkDebugf("path.lineTo(%1.9g, %1.9g);\n", pts[1].fX, pts[1].fY);
+                break;
+            case SkPath::kQuad_Verb:
+                SkDebugf("path.quadTo(%1.9g, %1.9g, %1.9g, %1.9g);\n",
+                    pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY);
+                break;
+            case SkPath::kCubic_Verb:
+                SkDebugf("path.cubicTo(%1.9g, %1.9g, %1.9g, %1.9g, %1.9g, %1.9g);\n",
+                    pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY,
+                    pts[3].fX, pts[3].fY);
+                break;
+            case SkPath::kClose_Verb:
+                waitForClose = false;
+                SkDebugf("path.close();\n");
+                break;
+            default:
+                SkDEBUGFAIL("bad verb");
+                SkASSERT(0);
+                return 0;
+        }
+    }
+    return moves;
+}
+
+class PathCanvas : public SkCanvas {
+    virtual void drawPath(const SkPath& path, const SkPaint& paint) {
+        if (nameonly) {
+            SkDebugf("    %s%d,\n", filename.c_str(), ++count);
+            return;
+        }
+        SkPath::Iter iter(path, true);
+        SkDebugf("<div id=\"%s%d\">\n", filename.c_str(), ++count);
+        SkASSERT(path.getFillType() < SkPath::kInverseWinding_FillType);
+        SkDebugf("path.setFillType(SkPath::k%s_FillType);\n",
+            path.getFillType() == SkPath::kWinding_FillType ? "Winding" : "EvenOdd");
+        int contours = showPathContour(iter);
+        SkRect r;
+        SkRect copy = r;
+        bool hasOne = path.hasRectangularInterior(&r);
+        bool expected = (path.getFillType() == SkPath::kWinding_FillType && contours == 1)
+            || (path.getFillType() == SkPath::kEvenOdd_FillType && contours == 2);
+        if (!expected) {
+            SkDebugf("suspect contours=%d\n", contours);
+        }
+        int verbs = path.countVerbs();
+        int points = path.countPoints();
+        if (hasOne) {
+            if (rectVerbsMin > verbs) {
+                rectVerbsMin = verbs;
+            }
+            if (rectVerbsMax < verbs) {
+                rectVerbsMax = verbs;
+            }
+            if (rectPointsMin > points) {
+                rectPointsMin = points;
+            }
+            if (rectPointsMax < points) {
+                rectPointsMax = points;
+            }
+            SkDebugf("path.addRect(%1.9g, %1.9g, %1.9g, %1.9g);\n",
+                    r.fLeft, r.fTop, r.fRight, r.fBottom);
+        } else {
+            if (verbsMin > verbs) {
+                verbsMin = verbs;
+            }
+            if (verbsMax < verbs) {
+                verbsMax = verbs;
+            }
+            if (pointsMin > points) {
+                pointsMin = points;
+            }
+            if (pointsMax < points) {
+                pointsMax = points;
+            }
+            SkDebugf("no interior bounds\n");
+        }
+        path.hasRectangularInterior(&copy);
+        SkDebugf("</div>\n\n");
+    }
+    
+    virtual void drawPosTextH(const void* text, size_t byteLength,
+                              const SkScalar xpos[], SkScalar constY,
+                              const SkPaint& paint) {
+    }
+    
+public:
+    void divName(const SkString& str, bool only) {
+        filename = str;
+        char* chars = filename.writable_str();
+        while (*chars) {
+            if (*chars == '.' || *chars == '-') *chars = '_';
+            chars++;
+        }
+        count = 0;
+        nameonly = only;
+    }
+    
+    void init() {
+        pointsMin = verbsMin = SK_MaxS32;
+        pointsMax = verbsMax = SK_MinS32;
+        rectPointsMin = rectVerbsMin = SK_MaxS32;
+        rectPointsMax = rectVerbsMax = SK_MinS32;
+    }
+    
+    SkString filename;
+    int count;
+    bool nameonly;
+    int pointsMin;
+    int pointsMax;
+    int verbsMin;
+    int verbsMax;
+    int rectPointsMin;
+    int rectPointsMax;
+    int rectVerbsMin;
+    int rectVerbsMax;
+};
+
+bool runone = false;
+
 void application_init() {
     SkGraphics::Init();
     SkEvent::Init();
+    if (runone) {
+        return;
+    }
+    const char pictDir[] = "/Volumes/chrome/nih/skia/skp/skp";
+    SkOSFile::Iter iter(pictDir, "skp");
+    SkString filename;
+    PathCanvas canvas;
+    canvas.init();
+    while (iter.next(&filename)) {
+        SkString path;
+     //   if (true) filename.set("tabl_www_sahadan_com.skp");
+        make_filepath(&path, pictDir, filename);
+        canvas.divName(filename, false);
+        SkPicture* pic = LoadPicture(path.c_str());
+        pic->draw(&canvas);
+        SkDELETE(pic);
+    }
+    SkDebugf("\n</div>\n\n");
+
+    SkDebugf("<script type=\"text/javascript\">\n\n");
+    SkDebugf("var testDivs = [\n");
+
+    iter.reset(pictDir, "skp");
+    while (iter.next(&filename)) {
+        SkString path;
+        make_filepath(&path, pictDir, filename);
+        canvas.divName(filename, true);
+        SkPicture* pic = LoadPicture(path.c_str());
+        pic->draw(&canvas);
+        SkDELETE(pic);
+    }
+    SkDebugf("];\n\n");
+
+    SkDebugf("points min=%d max=%d verbs min=%d max=%d\n", canvas.pointsMin, canvas.pointsMax,
+            canvas.verbsMin, canvas.verbsMax);
+    SkDebugf("rect points min=%d max=%d verbs min=%d max=%d\n", canvas.rectPointsMin, canvas.rectPointsMax,
+            canvas.rectVerbsMin, canvas.rectVerbsMax);
+
+    SkDebugf("\n");
 }
 
 void application_term() {
@@ -46,7 +290,7 @@
 @implementation SimpleNSView
 
 - (id)initWithDefaults {
-    if (self = [super initWithDefaults]) {
+    if ((self = [super initWithDefaults])) {
         fWind = new SkOSWindow(self);
         fWind->setLayout(new FillLayout, false);
         fWind->attachChildToFront(new SkSampleView)->unref();
@@ -59,4 +303,4 @@
     SkCGDrawBitmap(ctx, fWind->getBitmap(), 0, 0);
 }
 
-@end
\ No newline at end of file
+@end
diff --git a/gyp/shapeops_edge.gyp b/gyp/shapeops_edge.gyp
index 32b5c6e..34d60f4 100644
--- a/gyp/shapeops_edge.gyp
+++ b/gyp/shapeops_edge.gyp
@@ -75,6 +75,7 @@
         '../experimental/Intersection/QuarticRoot.cpp',
         '../experimental/Intersection/QuarticRoot_Test.cpp',
         '../experimental/Intersection/ShapeOps.cpp',
+        '../experimental/Intersection/ShapeOpCubic4x4_Test.cpp',
         '../experimental/Intersection/ShapeOpRect4x4_Test.cpp',
         '../experimental/Intersection/Simplify.cpp',
         '../experimental/Intersection/SimplifyAddIntersectingTs_Test.cpp',