shape ops work in progress

git-svn-id: http://skia.googlecode.com/svn/trunk@7453 2bbb7eff-a529-9590-31e7-b0007b416f81
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