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 8 #include "gm.h" 9 10 class SkJSCanvas { 11 public: 12 SkJSCanvas(SkCanvas* target); 13 ~SkJSCanvas(); 14 15 void save(); 16 void restore(); 17 18 double lineWidth; 19 void setLineWidth(double); 20 21 void beginPath(); 22 void moveTo(double x, double y); 23 void lineTo(double x, double y); 24 void closePath(); 25 26 void fill(); 27 void stroke(); 28 29 void fillText(const char text[], double x, double y); 30 31 private: 32 SkCanvas* fTarget; 33 SkPaint fFillPaint; 34 SkPaint fStrokePaint; 35 SkPath fPath; 36 }; 37 38 SkJSCanvas::SkJSCanvas(SkCanvas* target) : fTarget(target) { 39 fFillPaint.setAntiAlias(true); 40 fStrokePaint.setAntiAlias(true); 41 fStrokePaint.setStyle(SkPaint::kStroke_Style); 42 fStrokePaint.setStrokeWidth(SK_Scalar1); 43 } 44 45 SkJSCanvas::~SkJSCanvas() {} 46 47 void SkJSCanvas::save() { fTarget->save(); } 48 void SkJSCanvas::restore() { fTarget->restore(); } 49 50 void SkJSCanvas::beginPath() { fPath.reset(); } 51 void SkJSCanvas::moveTo(double x, double y) { 52 fPath.moveTo(SkDoubleToScalar(x), SkDoubleToScalar(y)); 53 } 54 55 void SkJSCanvas::lineTo(double x, double y) { 56 fPath.lineTo(SkDoubleToScalar(x), SkDoubleToScalar(y)); 57 } 58 59 void SkJSCanvas::closePath() { fPath.close(); } 60 61 void SkJSCanvas::fill() { 62 fTarget->drawPath(fPath, fFillPaint); 63 } 64 65 void SkJSCanvas::stroke() { 66 fStrokePaint.setStrokeWidth(SkDoubleToScalar(lineWidth)); 67 fTarget->drawPath(fPath, fStrokePaint); 68 } 69 70 void SkJSCanvas::fillText(const char text[], double x, double y) { 71 fTarget->drawText(text, strlen(text), 72 SkDoubleToScalar(x), SkDoubleToScalar(y), fFillPaint); 73 } 74 75 /////////////////////////////////////////////////////////////////////////////// 76 77 static void dump(const SkPath& path) { 78 const SkRect& r = path.getBounds(); 79 SkDebugf("isEmpty %d, bounds [%g %g %g %g]\n", path.isEmpty(), 80 r.fLeft, r.fTop, r.fRight, r.fBottom); 81 } 82 83 static void test_stroke(SkCanvas* canvas) { 84 if (true) { 85 SkPath path; 86 dump(path); 87 path.reset(); path.moveTo(0, 0); 88 dump(path); 89 path.reset(); path.moveTo(100, 100); 90 dump(path); 91 path.reset(); path.moveTo(0, 0); path.moveTo(100, 100); 92 dump(path); 93 path.reset(); path.moveTo(0, 0); path.lineTo(100, 100); 94 dump(path); 95 path.reset(); path.moveTo(0, 0); path.lineTo(100, 100); path.moveTo(200, 200); 96 dump(path); 97 } 98 99 #if 0 100 // TEST 1 - The rectangle as it's expected to look 101 var canvas = document.createElement('canvas'); 102 document.body.appendChild(canvas); 103 var ctx = canvas.getContext("2d"); 104 #else 105 SkJSCanvas ctx(canvas); 106 #endif 107 108 ctx.save(); 109 ctx.lineWidth = 2; 110 ctx.beginPath(); 111 ctx.moveTo(10, 100); 112 ctx.lineTo(150, 100); 113 ctx.lineTo(150, 15); 114 ctx.lineTo(10, 15); 115 ctx.closePath(); 116 117 // no extra moveTo here 118 // ctx.moveTo(175, 125); 119 120 ctx.stroke(); 121 ctx.restore(); 122 123 ctx.fillText("As Expected", 10, 10); 124 125 #if 0 126 // TEST 2 - Includes an extra moveTo call before stroke; the rectangle appears larger 127 canvas = document.createElement('canvas'); 128 document.body.appendChild(canvas); 129 ctx = canvas.getContext("2d"); 130 #else 131 canvas->translate(200, 0); 132 #endif 133 134 ctx.save(); 135 ctx.lineWidth = 2; 136 ctx.beginPath(); 137 ctx.moveTo(10, 100); 138 ctx.lineTo(150, 100); 139 ctx.lineTo(150, 15); 140 ctx.lineTo(10, 15); 141 ctx.closePath(); 142 143 ctx.moveTo(175, 125); 144 145 ctx.stroke(); 146 ctx.restore(); 147 148 ctx.fillText("Larger Rectangle", 10, 10); 149 150 #if 0 151 // TEST 3 - Identical to test 2 except the line width is 1 152 canvas = document.createElement('canvas'); 153 document.body.appendChild(canvas); 154 ctx = canvas.getContext("2d"); 155 #else 156 canvas->translate(200, 0); 157 #endif 158 159 ctx.save(); 160 ctx.lineWidth = 1; 161 ctx.beginPath(); 162 ctx.moveTo(10, 100); 163 ctx.lineTo(150, 100); 164 ctx.lineTo(150, 15); 165 ctx.lineTo(10, 15); 166 ctx.closePath(); 167 168 ctx.moveTo(175, 125); 169 170 ctx.stroke(); 171 ctx.restore(); 172 173 ctx.fillText("As Expected - line width 1", 10, 10); 174 } 175 176 class Poly2PolyGM : public skiagm::GM { 177 public: 178 Poly2PolyGM() {} 179 180 protected: 181 virtual uint32_t onGetFlags() const SK_OVERRIDE { 182 return kSkipTiled_Flag; 183 } 184 185 virtual SkString onShortName() SK_OVERRIDE { 186 return SkString("poly2poly"); 187 } 188 189 virtual SkISize onISize() SK_OVERRIDE { 190 return SkISize::Make(835, 840); 191 } 192 193 static void doDraw(SkCanvas* canvas, SkPaint* paint, const int isrc[], 194 const int idst[], int count) { 195 SkMatrix matrix; 196 SkPoint src[4], dst[4]; 197 198 for (int i = 0; i < count; i++) { 199 src[i].set(SkIntToScalar(isrc[2*i+0]), SkIntToScalar(isrc[2*i+1])); 200 dst[i].set(SkIntToScalar(idst[2*i+0]), SkIntToScalar(idst[2*i+1])); 201 } 202 203 canvas->save(); 204 matrix.setPolyToPoly(src, dst, count); 205 canvas->concat(matrix); 206 207 paint->setColor(SK_ColorGRAY); 208 paint->setStyle(SkPaint::kStroke_Style); 209 const SkScalar D = SkIntToScalar(64); 210 canvas->drawRectCoords(0, 0, D, D, *paint); 211 canvas->drawLine(0, 0, D, D, *paint); 212 canvas->drawLine(0, D, D, 0, *paint); 213 214 SkPaint::FontMetrics fm; 215 paint->getFontMetrics(&fm); 216 paint->setColor(SK_ColorRED); 217 paint->setStyle(SkPaint::kFill_Style); 218 SkScalar x = D/2; 219 SkScalar y = D/2 - (fm.fAscent + fm.fDescent)/2; 220 SkString str; 221 str.appendS32(count); 222 canvas->drawText(str.c_str(), str.size(), x, y, *paint); 223 224 canvas->restore(); 225 } 226 227 virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE { 228 if (false) { test_stroke(canvas); return; } 229 230 SkPaint paint; 231 paint.setAntiAlias(true); 232 paint.setStrokeWidth(SkIntToScalar(4)); 233 paint.setTextSize(SkIntToScalar(40)); 234 paint.setTextAlign(SkPaint::kCenter_Align); 235 236 canvas->save(); 237 canvas->translate(SkIntToScalar(10), SkIntToScalar(10)); 238 // translate (1 point) 239 const int src1[] = { 0, 0 }; 240 const int dst1[] = { 5, 5 }; 241 doDraw(canvas, &paint, src1, dst1, 1); 242 canvas->restore(); 243 244 canvas->save(); 245 canvas->translate(SkIntToScalar(160), SkIntToScalar(10)); 246 // rotate/uniform-scale (2 points) 247 const int src2[] = { 32, 32, 64, 32 }; 248 const int dst2[] = { 32, 32, 64, 48 }; 249 doDraw(canvas, &paint, src2, dst2, 2); 250 canvas->restore(); 251 252 canvas->save(); 253 canvas->translate(SkIntToScalar(10), SkIntToScalar(110)); 254 // rotate/skew (3 points) 255 const int src3[] = { 0, 0, 64, 0, 0, 64 }; 256 const int dst3[] = { 0, 0, 96, 0, 24, 64 }; 257 doDraw(canvas, &paint, src3, dst3, 3); 258 canvas->restore(); 259 260 canvas->save(); 261 canvas->translate(SkIntToScalar(160), SkIntToScalar(110)); 262 // perspective (4 points) 263 const int src4[] = { 0, 0, 64, 0, 64, 64, 0, 64 }; 264 const int dst4[] = { 0, 0, 96, 0, 64, 96, 0, 64 }; 265 doDraw(canvas, &paint, src4, dst4, 4); 266 canvas->restore(); 267 } 268 269 private: 270 typedef skiagm::GM INHERITED; 271 }; 272 273 ////////////////////////////////////////////////////////////////////////////// 274 275 DEF_GM( return new Poly2PolyGM; ) 276