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