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 17static 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 26static 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 56class SkSampleView : public SkView { 57public: 58 SkSampleView() { 59 this->setVisibleP(true); 60 this->setClipToBounds(false); 61 }; 62protected: 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 } 96private: 97 typedef SkView INHERITED; 98}; 99 100void application_init(); 101void application_term(); 102 103static 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 142class 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(©); 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 203public: 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 235bool runone = false; 236 237void 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 281void application_term() { 282 SkEvent::Term(); 283} 284 285class FillLayout : public SkView::Layout { 286protected: 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