Home | History | Annotate | Download | only in SimpleCocoaApp
      1 /*
      2  * Copyright 2011 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 #include "SkCanvas.h"
      8 #include "SkCGUtils.h"
      9 #include "SkGraphics.h"
     10 #include "SkImageDecoder.h"
     11 #include "SkOSFile.h"
     12 #include "SkPaint.h"
     13 #include "SkPicture.h"
     14 #include "SkStream.h"
     15 #include "SkWindow.h"
     16 
     17 static void make_filepath(SkString* path, const char* dir, const SkString& name) {
     18     size_t len = strlen(dir);
     19     path->set(dir);
     20     if (len > 0 && dir[len - 1] != '/') {
     21         path->append("/");
     22     }
     23     path->append(name);
     24 }
     25 
     26 static SkPicture* LoadPicture(const char path[]) {
     27     SkPicture* pic = NULL;
     28 
     29     SkBitmap bm;
     30     if (SkImageDecoder::DecodeFile(path, &bm)) {
     31         bm.setImmutable();
     32         pic = new SkPicture;
     33         SkCanvas* can = pic->beginRecording(bm.width(), bm.height());
     34         can->drawBitmap(bm, 0, 0, NULL);
     35         pic->endRecording();
     36     } else {
     37         SkFILEStream stream(path);
     38         if (stream.isValid()) {
     39             pic = new SkPicture(&stream, NULL, &SkImageDecoder::DecodeStream);
     40         }
     41 
     42         if (false) { // re-record
     43             SkPicture p2;
     44             pic->draw(p2.beginRecording(pic->width(), pic->height()));
     45             p2.endRecording();
     46 
     47             SkString path2(path);
     48             path2.append(".new.skp");
     49             SkFILEWStream writer(path2.c_str());
     50             p2.serialize(&writer);
     51         }
     52     }
     53     return pic;
     54 }
     55 
     56 class SkSampleView : public SkView {
     57 public:
     58     SkSampleView() {
     59         this->setVisibleP(true);
     60         this->setClipToBounds(false);
     61     };
     62 protected:
     63     virtual void onDraw(SkCanvas* canvas) {
     64         canvas->drawColor(0xFFFFFFFF);
     65         SkPaint p;
     66         p.setTextSize(20);
     67         p.setAntiAlias(true);
     68         canvas->drawText("Hello World!", 13, 50, 30, p);
     69      //   SkRect r = {50, 50, 80, 80};
     70         p.setColor(0xAA11EEAA);
     71    //     canvas->drawRect(r, p);
     72 
     73         SkRect result;
     74         SkPath path;
     75         path.moveTo(0, 0);
     76         path.lineTo(1, 1);
     77         path.lineTo(1, 8);
     78         path.lineTo(0, 9);
     79         SkASSERT(path.hasRectangularInterior(&result));
     80 
     81         path.reset();
     82         path.addRect(10, 10, 100, 100, SkPath::kCW_Direction);
     83         path.addRect(20, 20, 50, 50, SkPath::kCW_Direction);
     84         path.addRect(50, 50, 90, 90, SkPath::kCCW_Direction);
     85         p.setColor(0xAA335577);
     86         canvas->drawPath(path, p);
     87         SkASSERT(!path.hasRectangularInterior(NULL));
     88         path.reset();
     89         path.addRect(10, 10, 100, 100, SkPath::kCW_Direction);
     90         path.addRect(20, 20, 80, 80, SkPath::kCW_Direction);
     91         SkRect expected = {20, 20, 80, 80};
     92         SkASSERT(path.hasRectangularInterior(&result));
     93         SkASSERT(result == expected);
     94 
     95     }
     96 private:
     97     typedef SkView INHERITED;
     98 };
     99 
    100 void application_init();
    101 void application_term();
    102 
    103 static int showPathContour(SkPath::Iter& iter) {
    104     uint8_t verb;
    105     SkPoint pts[4];
    106     int moves = 0;
    107     bool waitForClose = false;
    108     while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
    109         switch (verb) {
    110             case SkPath::kMove_Verb:
    111                 if (!waitForClose) {
    112                     ++moves;
    113                     waitForClose = true;
    114                 }
    115                 SkDebugf("path.moveTo(%1.9g, %1.9g);\n", pts[0].fX, pts[0].fY);
    116                 break;
    117             case SkPath::kLine_Verb:
    118                 SkDebugf("path.lineTo(%1.9g, %1.9g);\n", pts[1].fX, pts[1].fY);
    119                 break;
    120             case SkPath::kQuad_Verb:
    121                 SkDebugf("path.quadTo(%1.9g, %1.9g, %1.9g, %1.9g);\n",
    122                     pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY);
    123                 break;
    124             case SkPath::kCubic_Verb:
    125                 SkDebugf("path.cubicTo(%1.9g, %1.9g, %1.9g, %1.9g, %1.9g, %1.9g);\n",
    126                     pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY,
    127                     pts[3].fX, pts[3].fY);
    128                 break;
    129             case SkPath::kClose_Verb:
    130                 waitForClose = false;
    131                 SkDebugf("path.close();\n");
    132                 break;
    133             default:
    134                 SkDEBUGFAIL("bad verb");
    135                 SkASSERT(0);
    136                 return 0;
    137         }
    138     }
    139     return moves;
    140 }
    141 
    142 class PathCanvas : public SkCanvas {
    143     virtual void drawPath(const SkPath& path, const SkPaint& paint) {
    144         if (nameonly) {
    145             SkDebugf("    %s%d,\n", filename.c_str(), ++count);
    146             return;
    147         }
    148         SkPath::Iter iter(path, true);
    149         SkDebugf("<div id=\"%s%d\">\n", filename.c_str(), ++count);
    150         SkASSERT(path.getFillType() < SkPath::kInverseWinding_FillType);
    151         SkDebugf("path.setFillType(SkPath::k%s_FillType);\n",
    152             path.getFillType() == SkPath::kWinding_FillType ? "Winding" : "EvenOdd");
    153         int contours = showPathContour(iter);
    154         SkRect r;
    155         SkRect copy = r;
    156         bool hasOne = path.hasRectangularInterior(&r);
    157         bool expected = (path.getFillType() == SkPath::kWinding_FillType && contours == 1)
    158             || (path.getFillType() == SkPath::kEvenOdd_FillType && contours == 2);
    159         if (!expected) {
    160             SkDebugf("suspect contours=%d\n", contours);
    161         }
    162         int verbs = path.countVerbs();
    163         int points = path.countPoints();
    164         if (hasOne) {
    165             if (rectVerbsMin > verbs) {
    166                 rectVerbsMin = verbs;
    167             }
    168             if (rectVerbsMax < verbs) {
    169                 rectVerbsMax = verbs;
    170             }
    171             if (rectPointsMin > points) {
    172                 rectPointsMin = points;
    173             }
    174             if (rectPointsMax < points) {
    175                 rectPointsMax = points;
    176             }
    177             SkDebugf("path.addRect(%1.9g, %1.9g, %1.9g, %1.9g);\n",
    178                     r.fLeft, r.fTop, r.fRight, r.fBottom);
    179         } else {
    180             if (verbsMin > verbs) {
    181                 verbsMin = verbs;
    182             }
    183             if (verbsMax < verbs) {
    184                 verbsMax = verbs;
    185             }
    186             if (pointsMin > points) {
    187                 pointsMin = points;
    188             }
    189             if (pointsMax < points) {
    190                 pointsMax = points;
    191             }
    192             SkDebugf("no interior bounds\n");
    193         }
    194         path.hasRectangularInterior(&copy);
    195         SkDebugf("</div>\n\n");
    196     }
    197 
    198     virtual void drawPosTextH(const void* text, size_t byteLength,
    199                               const SkScalar xpos[], SkScalar constY,
    200                               const SkPaint& paint) {
    201     }
    202 
    203 public:
    204     void divName(const SkString& str, bool only) {
    205         filename = str;
    206         char* chars = filename.writable_str();
    207         while (*chars) {
    208             if (*chars == '.' || *chars == '-') *chars = '_';
    209             chars++;
    210         }
    211         count = 0;
    212         nameonly = only;
    213     }
    214 
    215     void init() {
    216         pointsMin = verbsMin = SK_MaxS32;
    217         pointsMax = verbsMax = SK_MinS32;
    218         rectPointsMin = rectVerbsMin = SK_MaxS32;
    219         rectPointsMax = rectVerbsMax = SK_MinS32;
    220     }
    221 
    222     SkString filename;
    223     int count;
    224     bool nameonly;
    225     int pointsMin;
    226     int pointsMax;
    227     int verbsMin;
    228     int verbsMax;
    229     int rectPointsMin;
    230     int rectPointsMax;
    231     int rectVerbsMin;
    232     int rectVerbsMax;
    233 };
    234 
    235 bool runone = false;
    236 
    237 void application_init() {
    238     SkGraphics::Init();
    239     SkEvent::Init();
    240     if (runone) {
    241         return;
    242     }
    243     const char pictDir[] = "/Volumes/chrome/nih/skia/skp/skp";
    244     SkOSFile::Iter iter(pictDir, "skp");
    245     SkString filename;
    246     PathCanvas canvas;
    247     canvas.init();
    248     while (iter.next(&filename)) {
    249         SkString path;
    250      //   if (true) filename.set("tabl_www_sahadan_com.skp");
    251         make_filepath(&path, pictDir, filename);
    252         canvas.divName(filename, false);
    253         SkPicture* pic = LoadPicture(path.c_str());
    254         pic->draw(&canvas);
    255         delete pic;
    256     }
    257     SkDebugf("\n</div>\n\n");
    258 
    259     SkDebugf("<script type=\"text/javascript\">\n\n");
    260     SkDebugf("var testDivs = [\n");
    261 
    262     iter.reset(pictDir, "skp");
    263     while (iter.next(&filename)) {
    264         SkString path;
    265         make_filepath(&path, pictDir, filename);
    266         canvas.divName(filename, true);
    267         SkPicture* pic = LoadPicture(path.c_str());
    268         pic->draw(&canvas);
    269         delete pic;
    270     }
    271     SkDebugf("];\n\n");
    272 
    273     SkDebugf("points min=%d max=%d verbs min=%d max=%d\n", canvas.pointsMin, canvas.pointsMax,
    274             canvas.verbsMin, canvas.verbsMax);
    275     SkDebugf("rect points min=%d max=%d verbs min=%d max=%d\n", canvas.rectPointsMin, canvas.rectPointsMax,
    276             canvas.rectVerbsMin, canvas.rectVerbsMax);
    277 
    278     SkDebugf("\n");
    279 }
    280 
    281 void application_term() {
    282     SkEvent::Term();
    283 }
    284 
    285 class FillLayout : public SkView::Layout {
    286 protected:
    287     virtual void onLayoutChildren(SkView* parent) {
    288         SkView* view = SkView::F2BIter(parent).next();
    289         view->setSize(parent->width(), parent->height());
    290     }
    291 };
    292 
    293 #import "SimpleApp.h"
    294 @implementation SimpleNSView
    295 
    296 - (id)initWithDefaults {
    297     if ((self = [super initWithDefaults])) {
    298         fWind = new SkOSWindow(self);
    299         fWind->setLayout(new FillLayout, false);
    300         fWind->attachChildToFront(new SkSampleView)->unref();
    301     }
    302     return self;
    303 }
    304 
    305 - (void)drawRect:(NSRect)dirtyRect {
    306     CGContextRef ctx = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
    307     SkCGDrawBitmap(ctx, fWind->getBitmap(), 0, 0);
    308 }
    309 
    310 @end
    311