shape ops work in progress
authorcaryclark@google.com <caryclark@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Fri, 13 Jul 2012 21:07:52 +0000 (21:07 +0000)
committercaryclark@google.com <caryclark@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Fri, 13 Jul 2012 21:07:52 +0000 (21:07 +0000)
git-svn-id: http://skia.googlecode.com/svn/trunk@4610 2bbb7eff-a529-9590-31e7-b0007b416f81

experimental/Intersection/Simplify.cpp
experimental/Intersection/SimplifyNew_Test.cpp
experimental/Intersection/op.htm

index 859755f..1fd8185 100644 (file)
@@ -1158,9 +1158,8 @@ public:
     // winding -1 means ccw, 1 means cw
     // firstFind allows coincident edges to be treated differently
     Segment* findNext(SkTDArray<Span*>& chase, int winding,
-            const int startIndex, const int endIndex,
-            int& nextStart, int& nextEnd, int& flipped, bool firstFind
-            ,bool active /* active param is debugging only */ ) {
+            const int startIndex, const int endIndex, int& nextStart,
+            int& nextEnd, int& flipped, bool firstFind, bool active) {
         SkASSERT(startIndex != endIndex);
         int count = fTs.count();
         SkASSERT(startIndex < endIndex ? startIndex < count - 1
@@ -1190,9 +1189,18 @@ public:
         sortAngles(angles, sorted);
         int angleCount = angles.count();
         int firstIndex = findStartingEdge(sorted, startIndex, end);
-        
         SkASSERT(firstIndex >= 0);
+    #if DEBUG_WINDING
+        SkDebugf("%s (first) winding=%d sign=%d\n", __FUNCTION__,
+                winding, sorted[firstIndex]->sign());
+    #endif
+        bool innerSwap = false;
         int startWinding = winding;
+        if (winding * sorted[firstIndex]->sign() > 0 && active) {
+            // FIXME: this means winding was computed wrong by caller ?
+            winding = 0;
+            innerSwap = true;
+        }
         int nextIndex = firstIndex + 1;
         int lastIndex = firstIndex != 0 ? firstIndex : angleCount;
         const Angle* foundAngle = NULL;
@@ -1209,8 +1217,8 @@ public:
             SkASSERT(windValue > 0);
             winding -= nextAngle->sign() * windValue;
     #if DEBUG_WINDING
-            SkDebugf("%s maxWinding=%d winding=%d\n", __FUNCTION__, maxWinding,
-                    winding);
+            SkDebugf("%s maxWinding=%d winding=%d sign=%d\n", __FUNCTION__,
+                    maxWinding, winding, nextAngle->sign());
     #endif
             if (maxWinding * winding < 0) {
                 flipped = -flipped;
@@ -1222,7 +1230,9 @@ public:
                     SkASSERT(nextAngle->segment() == this);
                     markWinding(SkMin32(nextAngle->start(), nextAngle->end()),
                                 maxWinding);
+    #if DEBUG_WINDING
                     SkDebugf("%s inactive\n", __FUNCTION__);
+    #endif
                     return NULL;
                 }
                 if (!foundAngle) {
@@ -1230,6 +1240,9 @@ public:
                 }
                 continue;
             }
+            if (!maxWinding && innerSwap && !foundAngle) {
+                foundAngle = nextAngle;
+            }
             if (nextSegment->done()) {
                 continue;
             }
@@ -1242,7 +1255,7 @@ public:
                     maxWinding = winding;
                 }
                 Span* last;
-                if (foundAngle) {
+                if (foundAngle || innerSwap) {
                     last = nextSegment->markAndChaseWinding(nextAngle, maxWinding);
                 } else {
                     last = nextSegment->markAndChaseDone(nextAngle, maxWinding);
@@ -1499,7 +1512,7 @@ public:
         int otherEnd = other->nextSpan(index, step);
         int min = SkMin32(index, otherEnd);
         if (other->fTs[min].fWindSum != SK_MinS32) {
-            SkASSERT(other->fTs[index].fWindSum == winding);
+            SkASSERT(other->fTs[min].fWindSum == winding);
             return NULL;
         }
         Span* last = other->innerChaseWinding(index, step, winding);
@@ -2939,14 +2952,19 @@ static void bridge(SkTDArray<Contour*>& contourList, SkPath& simple) {
         SkTDArray<Span*> chaseArray;
         do {
             bool active = winding * spanWinding <= 0;
+        #if DEBUG_WINDING
+            if (!active) {
+                SkDebugf("%s !active winding=%d spanWinding=%d\n",
+                        __FUNCTION__, winding, spanWinding);
+            }
+        #endif
             const SkPoint* firstPt = NULL;
             do {
                 SkASSERT(!current->done());
                 int nextStart, nextEnd, flipped = 1;
                 Segment* next = current->findNext(chaseArray, 
-                        winding + spanWinding, index,
-                        endIndex, nextStart, nextEnd, flipped, firstTime
-                        , active /* active is debugging only */ );
+                        winding + spanWinding, index, endIndex,
+                        nextStart, nextEnd, flipped, firstTime, active);
                 if (!next) {
                     break;
                 }
@@ -2971,9 +2989,9 @@ static void bridge(SkTDArray<Contour*>& contourList, SkPath& simple) {
                 simple.close();
             }
             current = findChase(chaseArray, index, endIndex);
-#if DEBUG_ACTIVE_SPANS
+        #if DEBUG_ACTIVE_SPANS
             debugShowActiveSpans(contourList);
-#endif
+        #endif
             if (!current) {
                 break;
             }
@@ -2993,12 +3011,19 @@ static void bridge(SkTDArray<Contour*>& contourList, SkPath& simple) {
    //             SkTSwap<int>(index, endIndex);
             }
             if (abs(spanWinding) > spanValue) {
-        #if DEBUG_WINDING
-                SkDebugf("%s abs(spanWinding) > spanValue\n", __FUNCTION__);
-        #endif
                 winding = spanWinding;
                 spanWinding = spanValue * SkSign32(spanWinding);
                 winding -= spanWinding;
+        #if DEBUG_WINDING
+                SkDebugf("%s spanWinding=%d winding=%d\n", __FUNCTION__,
+                        spanWinding, winding);
+        #endif
+            } else {
+        #if DEBUG_WINDING
+                SkDebugf("%s ->0 contourWinding=%d winding=%d\n", __FUNCTION__,
+                        contourWinding, winding);
+        #endif
+                winding = 0;
             }
         } while (true);
     } while (true);
index 06b0167..a7c5c31 100644 (file)
@@ -396,6 +396,14 @@ static void testLine35() {
     testSimplifyx(path);
 }
 
+static void testLine36() {
+    SkPath path, simple;
+    path.addRect(0, 10, 20, 20, (SkPath::Direction) 0);
+    path.addRect(6, 12, 18, 18, (SkPath::Direction) 0);
+    path.addRect(4, 16, 13, 13, (SkPath::Direction) 0);
+    testSimplifyx(path);
+}
+
 #define TEST(name) { name, #name }
 
 static struct {
@@ -441,6 +449,7 @@ static struct {
     TEST(testLine33),
     TEST(testLine34),
     TEST(testLine35),
+    TEST(testLine36),
 };
 
 static const size_t testCount = sizeof(tests) / sizeof(tests[0]);
index 0400561..a1f390c 100644 (file)
@@ -395,11 +395,18 @@ path.close();
     path.addRect(4, 16, 13, 13, (SkPath::Direction) 0);
 </div>
 
+<div id="testLine36">
+    path.addRect(0, 10, 20, 20, (SkPath::Direction) 0);
+    path.addRect(6, 12, 18, 18, (SkPath::Direction) 0);
+    path.addRect(4, 16, 13, 13, (SkPath::Direction) 0);
+</div>
+
 </div>
 
 <script type="text/javascript">
 
 var testDivs = [
+    testLine36,
     testLine35,
     testLine34,
     testLine33,
@@ -441,11 +448,12 @@ var at_x = 13 + 0.5;
 var at_y = 13 + 0.5;
 
 var tests = [];
+var testTitles = [];
 var testIndex = 0;
 
 var ctx;
 
-function parse(test) {
+function parse(test, title) {
     var contours = [];
     var contourStrs = test.split("path.close();");
     var pattern = /-?\d+\.*\d*/g;
@@ -478,11 +486,13 @@ function parse(test) {
             contours.push(verbs);
         }
     }
-    if (contours.length > 0)
+    if (contours.length > 0) {
         tests.push(contours);
+        testTitles.push(title);
+    }
 }
 
-function parseRect(test) {
+function parseRect(test, title) {
     var contours = [];
     var rectStrs = test.split("path.addRect");
     var pattern = /-?\d+\.*\d*/g;
@@ -519,8 +529,10 @@ function parseRect(test) {
         verbs.push(topLeft);
         contours.push(verbs);
     }
-    if (contours.length > 0)
+    if (contours.length > 0) {
         tests.push(contours);
+        testTitles.push(title);
+    }
 }
 
 function init(test) {
@@ -570,7 +582,12 @@ function drawPoint(px, py, xoffset, yoffset, unit) {
     ctx.fillText(label, _px + 5, _py);
 }
 
-function draw(test, _at_x, _at_y, scale) {
+function draw(test, title, _at_x, _at_y, scale) {
+    ctx.fillStyle = "rgba(0,0,0, 0.1)";
+    ctx.font = "normal 50px Arial";
+    ctx.fillText(title, 50, 50);
+    ctx.font = "normal 10px Arial";
+    
     var unit = scale * ticks;
     ctx.lineWidth = 1;
     var i;
@@ -689,7 +706,7 @@ function redraw() {
     ctx.rect(0, 0, ctx.canvas.width, ctx.canvas.height);
     ctx.fillStyle="white";
     ctx.fill();
-    draw(tests[testIndex], at_x, at_y, scale);
+    draw(tests[testIndex], testTitles[testIndex], at_x, at_y, scale);
 //    if (insetScale != scale && mouseX != Infinity)
 //        drawInset();
 }
@@ -726,11 +743,12 @@ function doKeyPress(evt) {
 
 function start() {
     for (i = 0; i < testDivs.length; ++i) {
+        var title = testDivs[i].id.toString();
         var str = testDivs[i].firstChild.data;
         if (str.split("addRect").length > 1) {
-            parseRect(str);
+            parseRect(str, title);
         } else {
-            parse(str);
+            parse(str, title);
         }
     }
     drawTop();