checkpoint for shape ops

at minimum, the unit tests in SimplyNew_Test pass

git-svn-id: http://skia.googlecode.com/svn/trunk@5860 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/experimental/Intersection/EdgeDemo.cpp b/experimental/Intersection/EdgeDemo.cpp
index 33aae21..14ede5b 100644
--- a/experimental/Intersection/EdgeDemo.cpp
+++ b/experimental/Intersection/EdgeDemo.cpp
@@ -4,6 +4,35 @@
 #import "SkCanvas.h"
 #import "SkPaint.h"
 
+extern void showPath(const SkPath& path, const char* str);
+
+static bool drawPaths(SkCanvas* canvas, const SkPath& path, bool useOld)
+{
+    SkPath out;
+#define SHOW_PATH 0
+#if SHOW_PATH
+    showPath(path, "original:");
+#endif
+    if (useOld) {
+        simplify(path, true, out);
+    } else {
+        simplifyx(path, out);
+    }
+#if SHOW_PATH
+    showPath(out, "simplified:");
+#endif
+    SkPaint paint;
+    paint.setAntiAlias(true);
+    paint.setStyle(SkPaint::kStroke_Style);
+  //  paint.setStrokeWidth(6);
+  //  paint.setColor(0x1F003f7f);
+ //   canvas->drawPath(path, paint);
+    paint.setColor(0xFF305F00);
+    paint.setStrokeWidth(1);
+    canvas->drawPath(out, paint);
+    return true;
+}
+
 // Three circles bounce inside a rectangle. The circles describe three, four
 // or five points which in turn describe a polygon. The polygon points
 // bounce inside the circles. The circles rotate and scale over time. The
@@ -26,7 +55,7 @@
             pts[c * 8 + p * 2 + 1] = abs(110 - ((step + c * 223 + p * 17) % 230));
         }
     }
-    SkPath path, out;
+    SkPath path;
     for (c = 0; c < circles; ++c) {
         for (p = 0; p < 4; ++p) {
             SkScalar x = pts[c * 8 + p * 2];
@@ -49,23 +78,7 @@
         }
         path.close();
     }
-    showPath(path, "original:");
-    if (useOld) {
-        simplify(path, true, out);
-    } else {
-        simplifyx(path, out);
-    }
-    showPath(out, "simplified:");
-    SkPaint paint;
-    paint.setAntiAlias(true);
-    paint.setStyle(SkPaint::kStroke_Style);
-    paint.setStrokeWidth(3);
-    paint.setColor(0x3F007fbF);
-    canvas->drawPath(path, paint);
-    paint.setColor(0xFF60FF00);
-    paint.setStrokeWidth(1);
-    canvas->drawPath(out, paint);
-    return true;
+    return drawPaths(canvas, path, useOld);
 }
 
 static void createStar(SkPath& path, SkScalar innerRadius, SkScalar outerRadius,
@@ -89,7 +102,7 @@
 
 static bool drawStars(SkCanvas* canvas, int step, bool useOld)
 {
-    SkPath path, out;
+    SkPath path;
     const int stars = 25;
     int pts[stars];
  //   static bool initialize = true;
@@ -134,43 +147,171 @@
         createStar(path, innerRadius[s] / 4.0f, outerRadius[s] / 4.0f,
                 angles[s], pts[s], locs[s]);
     }
-#define SHOW_PATH 0
-#if SHOW_PATH
-    showPath(path, "original:");
-#endif
-#define TEST_SIMPLIFY 01
-#if TEST_SIMPLIFY
-    if (useOld) {
-        simplify(path, true, out);
+    return drawPaths(canvas, path, useOld);
+}
+
+static void tryRoncoOnce(const SkPath& path, const SkRect& target, bool show) {
+    // capture everything in a desired rectangle
+    SkPath tiny;
+    bool closed = true;
+    SkPath::Iter iter(path, false);
+    SkPoint pts[4];
+    SkPath::Verb verb;
+    int count = 0;
+    SkPoint lastPt;
+    while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
+        switch (verb) {
+            case SkPath::kMove_Verb:
+                count = 0;
+                break;
+            case SkPath::kLine_Verb:
+                count = 1;
+                break;
+            case SkPath::kQuad_Verb:
+                count = 2;
+                break;
+            case SkPath::kCubic_Verb:
+                count = 3;
+                break;
+            case SkPath::kClose_Verb:
+                if (!closed) {
+                    tiny.close();
+                    closed = true;
+                }
+                count = 0;
+                break;
+            default:
+                SkDEBUGFAIL("bad verb");
+        }
+        if (!count) {
+            continue;
+        }
+        SkRect bounds;
+        bounds.set(pts[0].fX, pts[0].fY, pts[0].fX, pts[0].fY);
+        for (int i = 1; i <= count; ++i) {
+            bounds.growToInclude(pts[i].fX + 0.1f, pts[i].fY + 0.1f);
+        }
+        if (!SkRect::Intersects(target, bounds)) {
+            continue;
+        }
+        if (closed) {
+            tiny.moveTo(pts[0].fX, pts[0].fY);
+            closed = false;
+        } else if (pts[0] != lastPt) {
+            tiny.lineTo(pts[0].fX, pts[0].fY);
+        }
+        switch (verb) {
+            case SkPath::kLine_Verb:
+                tiny.lineTo(pts[1].fX, pts[1].fY);
+                lastPt = pts[1];
+                break;
+            case SkPath::kQuad_Verb:
+                tiny.quadTo(pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY);
+                lastPt = pts[2];
+                break;
+            case SkPath::kCubic_Verb:
+                tiny.cubicTo(pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY, pts[3].fX, pts[3].fY);
+                lastPt = pts[3];
+                break;
+            default:
+                SkDEBUGFAIL("bad verb");
+        }
+    }
+    if (!closed) {
+        tiny.close();
+    }
+    if (show) {
+        showPath(tiny, NULL);
+        SkDebugf("simplified:\n");
+    }
+    SkPath out;
+    simplifyx(tiny, out);
+}
+
+static void tryRonco(const SkPath& path) {
+    const SkRect& overall = path.getBounds();
+    const int divs = 50;
+    SkScalar cellWidth = overall.width() / divs * 2;
+    SkScalar cellHeight = overall.height() / divs * 2; 
+    SkRect target;
+    if (true) {
+        int xDiv = 21;
+        int yDiv = 9;
+        target.setXYWH(overall.fLeft + (overall.width() - cellWidth) * xDiv / divs,
+                overall.fTop + (overall.height() - cellHeight) * yDiv / divs,
+                 cellWidth, cellHeight);
+        tryRoncoOnce(path, target, true);
     } else {
+        for (int xDiv = 0; xDiv < divs; ++xDiv) {
+            for (int yDiv = 0; yDiv < divs; ++yDiv) {
+                target.setXYWH(overall.fLeft + (overall.width() - cellWidth) * xDiv / divs,
+                        overall.fTop + (overall.height() - cellHeight) * yDiv / divs,
+                         cellWidth, cellHeight);
+                tryRoncoOnce(path, target, false);
+            }
+        }
+    }
+}
+    
+static bool drawLetters(SkCanvas* canvas, int step, bool useOld)
+{
+    SkPath path;
+    const int width = 640;
+    const int height = 480;
+    const char testStr[] = "Merge";
+    const int testStrLen = sizeof(testStr) - 1;
+    SkPoint textPos[testStrLen];
+    SkScalar widths[testStrLen];
+    SkPaint paint;
+    paint.setTextSize(40);
+    paint.setAntiAlias(true);
+    paint.getTextWidths(testStr, testStrLen, widths, NULL);
+    SkScalar running = 0;
+    for (int x = 0; x < testStrLen; ++x) {
+        SkScalar width = widths[x];
+        widths[x] = running;
+        running += width;
+    }
+    SkScalar bias = (width - widths[testStrLen - 1]) / 2;
+    for (int x = 0; x < testStrLen; ++x) {
+        textPos[x].fX = bias + widths[x];
+        textPos[x].fY = height / 2;
+    }
+    paint.setTextSize(40 + step / 100.0f);
+#if 0
+    for (int mask = 0; mask < 1 << testStrLen; ++mask) {
+        char maskStr[testStrLen];
+    //    mask = 26;
+        for (int letter = 0; letter < testStrLen; ++letter) {
+            maskStr[letter] = mask & (1 << letter) ? testStr[letter] : ' ';
+        }
+        paint.getPosTextPath(maskStr, testStrLen, textPos, &path);
+        showPath(path, NULL);
+        SkDebugf("%d simplified:\n", mask);
+        SkPath out;
         simplifyx(path, out);
     }
 #endif
-#if SHOW_PATH
-    showPath(out, "simplified:");
+    paint.getPosTextPath(testStr, testStrLen, textPos, &path);
+#if 1
+    tryRonco(path);
 #endif
-    SkPaint paint;
-    paint.setAntiAlias(true);
-    paint.setStyle(SkPaint::kStroke_Style);
-    paint.setStrokeWidth(6);
-    paint.setColor(0x1F003f7f);
-    canvas->drawPath(path, paint);
-    paint.setColor(0xFF305F00);
-    paint.setStrokeWidth(1);
-#if TEST_SIMPLIFY
-    canvas->drawPath(out, paint);
+#if 1
+    showPath(path, NULL);
+    SkDebugf("simplified:\n");
 #endif
-    return true;
+    return drawPaths(canvas, path, false);
 }
 
 static bool (*drawDemos[])(SkCanvas* , int , bool ) = {
     drawStars,
-    drawCircles
+    drawCircles,
+    drawLetters,
 };
 
 static size_t drawDemosCount = sizeof(drawDemos) / sizeof(drawDemos[0]);
 
-static bool (*firstTest)(SkCanvas* , int , bool) = 0;
+static bool (*firstTest)(SkCanvas* , int , bool) = drawLetters;
 
 
 bool DrawEdgeDemo(SkCanvas* canvas, int step, bool useOld) {