shape ops work in progress

git-svn-id: http://skia.googlecode.com/svn/trunk@7788 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/experimental/Intersection/Simplify.cpp b/experimental/Intersection/Simplify.cpp
index 2c71039..70038e6 100644
--- a/experimental/Intersection/Simplify.cpp
+++ b/experimental/Intersection/Simplify.cpp
@@ -32,7 +32,7 @@
 
 #define DEBUG_UNUSED 0 // set to expose unused functions
 
-#define FORCE_RELEASE 0  // set force release to 1 for multiple thread -- no debugging
+#define FORCE_RELEASE 1  // set force release to 1 for multiple thread -- no debugging
 
 #if FORCE_RELEASE || defined SK_RELEASE
 
@@ -51,8 +51,8 @@
 #define DEBUG_MARK_DONE 0
 #define DEBUG_PATH_CONSTRUCTION 0
 #define DEBUG_SHOW_WINDING 0
-#define DEBUG_SORT 0
-#define DEBUG_SWAP_TOP 1
+#define DEBUG_SORT 1
+#define DEBUG_SWAP_TOP 0
 #define DEBUG_UNSORTABLE 0
 #define DEBUG_WIND_BUMP 0
 #define DEBUG_WINDING 0
@@ -88,13 +88,16 @@
         DEBUG_PATH_CONSTRUCTION)
 
 #if DEBUG_DUMP
-static const char* kShapeOpStr[] = {"diff", "sect", "union", "xor"};
 static const char* kLVerbStr[] = {"", "line", "quad", "cubic"};
 // static const char* kUVerbStr[] = {"", "Line", "Quad", "Cubic"};
 static int gContourID;
 static int gSegmentID;
 #endif
 
+#if DEBUG_ACTIVE_OP
+static const char* kShapeOpStr[] = {"diff", "sect", "union", "xor"};
+#endif
+
 #ifndef DEBUG_TEST
 #define DEBUG_TEST 0
 #endif
@@ -1041,7 +1044,7 @@
     int absIn = abs(innerWinding);
     bool result = absOut == absIn ? outerWinding < 0 : absOut < absIn;
     if (outerWinding * innerWinding < 0) {
-#if DEBUG_WINDING
+#if 0 && DEBUG_WINDING
         SkDebugf("%s outer=%d inner=%d result=%s\n", __FUNCTION__,
                 outerWinding, innerWinding, result ? "true" : "false");
 #endif
@@ -2822,14 +2825,24 @@
             endIndex = angle->start();
         } while (leftSegment->fTs[SkMin32(tIndex, endIndex)].fDone);
         if (leftSegment->verb() >= SkPath::kQuad_Verb) {
+            bool bumpsUp = leftSegment->bumpsUp(tIndex, endIndex);
+            SkPoint xyE = leftSegment->xyAtT(endIndex);
+            SkPoint xyS = leftSegment->xyAtT(tIndex);
             SkPoint dxyE = leftSegment->dxdy(endIndex);
             SkPoint dxyS = leftSegment->dxdy(tIndex);
             double cross = dxyE.cross(dxyS);
+            bool bumpCheck = bumpsUp && xyE.fY < xyS.fY;
         #if DEBUG_SWAP_TOP
-            SkDebugf("%s dxyE=(%1.9g,%1.9g) dxyS=(%1.9g,%1.9g) cross=%1.9g\n", __FUNCTION__,
-                    dxyE.fX, dxyE.fY, dxyS.fX, dxyS.fY, cross);
+            SkDebugf("%s xyE=(%1.9g,%1.9g) xyS=(%1.9g,%1.9g)\n", __FUNCTION__,
+                    xyE.fX, xyE.fY, xyS.fX, xyS.fY);
+            SkDebugf("%s dxyE=(%1.9g,%1.9g) dxyS=(%1.9g,%1.9g) cross=%1.9g bump=%s\n", __FUNCTION__,
+                    dxyE.fX, dxyE.fY, dxyS.fX, dxyS.fY, cross, bumpCheck ? "true" : "false");
         #endif
-            if (cross >= 1) {
+            if ((cross > 0) ^ bumpCheck) {
+                leftSegment->bumpsUp(tIndex, endIndex);
+                SkDebugf("%s cross bump disagree\n", __FUNCTION__);
+            }
+            if (bumpCheck) {
         #if DEBUG_SWAP_TOP
                 SkDebugf("%s swap\n", __FUNCTION__);
         #endif
@@ -3298,6 +3311,27 @@
         return &span;
     }
 
+    bool bumpsUp(int tStart, int tEnd) const {
+        SkPoint edge[4];
+        (*SegmentSubDivide[fVerb])(fPts, fTs[tStart].fT, fTs[tEnd].fT, edge);
+        switch (fVerb) {
+            case SkPath::kLine_Verb:
+                SkASSERT(0); // shouldn't call in for lines
+                return true;
+            case SkPath::kQuad_Verb:
+                return approximately_greater(edge[0].fY, edge[1].fY)
+                        && approximately_lesser(edge[1].fY, edge[2].fY);
+            case SkPath::kCubic_Verb:
+                return (approximately_greater(edge[0].fY, edge[1].fY)
+                        && approximately_lesser(edge[1].fY, edge[3].fY))
+                        || (approximately_greater(edge[0].fY, edge[2].fY)
+                        && approximately_lesser(edge[2].fY, edge[3].fY));
+            default:
+                SkASSERT(0);
+                return false;
+        }
+    }
+
     Span* verifyOneWinding(const char* funName, int tIndex) {
         Span& span = fTs[tIndex];
         if (span.fDone) {
@@ -3685,7 +3719,8 @@
         int lesser = SkMin32(index, endIndex);
         int oppWinding = oppSum(lesser);
         int oppSpanWinding = oppSign(index, endIndex);
-        if (oppSpanWinding && useInnerWinding(oppWinding - oppSpanWinding, oppWinding)) {
+        if (oppSpanWinding && useInnerWinding(oppWinding - oppSpanWinding, oppWinding)
+                && oppWinding != SK_MaxS32) {
             oppWinding -= oppSpanWinding;
         }
         return oppWinding;
@@ -3707,7 +3742,7 @@
         int lesser = SkMin32(index, endIndex);
         int winding = windSum(lesser);
         int spanWinding = spanSign(index, endIndex);
-        if (winding && useInnerWinding(winding - spanWinding, winding)) {
+        if (winding && useInnerWinding(winding - spanWinding, winding) && winding != SK_MaxS32) {
             winding -= spanWinding;
         }
         return winding;
@@ -4130,6 +4165,8 @@
                     start, segment.xAtT(&sSpan), segment.yAtT(&sSpan), end,
                     segment.xAtT(&eSpan), segment.yAtT(&eSpan), angle.sign(),
                     mSpan.fWindValue);
+            start here; 
+            // create an inline to replace this conditional
             if (mSpan.fWindSum == SK_MinS32) {
                 SkDebugf("?");
             } else {