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 SkString onShortName() SK_OVERRIDE { 182 return SkString("poly2poly"); 183 } 184 185 virtual SkISize onISize() SK_OVERRIDE { 186 return SkISize::Make(835, 840); 187 } 188 189 static void doDraw(SkCanvas* canvas, SkPaint* paint, const int isrc[], 190 const int idst[], int count) { 191 SkMatrix matrix; 192 SkPoint src[4], dst[4]; 193 194 for (int i = 0; i < count; i++) { 195 src[i].set(SkIntToScalar(isrc[2*i+0]), SkIntToScalar(isrc[2*i+1])); 196 dst[i].set(SkIntToScalar(idst[2*i+0]), SkIntToScalar(idst[2*i+1])); 197 } 198 199 canvas->save(); 200 matrix.setPolyToPoly(src, dst, count); 201 canvas->concat(matrix); 202 203 paint->setColor(SK_ColorGRAY); 204 paint->setStyle(SkPaint::kStroke_Style); 205 const SkScalar D = SkIntToScalar(64); 206 canvas->drawRectCoords(0, 0, D, D, *paint); 207 canvas->drawLine(0, 0, D, D, *paint); 208 canvas->drawLine(0, D, D, 0, *paint); 209 210 SkPaint::FontMetrics fm; 211 paint->getFontMetrics(&fm); 212 paint->setColor(SK_ColorRED); 213 paint->setStyle(SkPaint::kFill_Style); 214 SkScalar x = D/2; 215 SkScalar y = D/2 - (fm.fAscent + fm.fDescent)/2; 216 SkString str; 217 str.appendS32(count); 218 canvas->drawText(str.c_str(), str.size(), x, y, *paint); 219 220 canvas->restore(); 221 } 222 223 virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE { 224 if (false) { test_stroke(canvas); return; } 225 226 SkPaint paint; 227 paint.setAntiAlias(true); 228 paint.setStrokeWidth(SkIntToScalar(4)); 229 paint.setTextSize(SkIntToScalar(40)); 230 paint.setTextAlign(SkPaint::kCenter_Align); 231 232 canvas->save(); 233 canvas->translate(SkIntToScalar(10), SkIntToScalar(10)); 234 // translate (1 point) 235 const int src1[] = { 0, 0 }; 236 const int dst1[] = { 5, 5 }; 237 doDraw(canvas, &paint, src1, dst1, 1); 238 canvas->restore(); 239 240 canvas->save(); 241 canvas->translate(SkIntToScalar(160), SkIntToScalar(10)); 242 // rotate/uniform-scale (2 points) 243 const int src2[] = { 32, 32, 64, 32 }; 244 const int dst2[] = { 32, 32, 64, 48 }; 245 doDraw(canvas, &paint, src2, dst2, 2); 246 canvas->restore(); 247 248 canvas->save(); 249 canvas->translate(SkIntToScalar(10), SkIntToScalar(110)); 250 // rotate/skew (3 points) 251 const int src3[] = { 0, 0, 64, 0, 0, 64 }; 252 const int dst3[] = { 0, 0, 96, 0, 24, 64 }; 253 doDraw(canvas, &paint, src3, dst3, 3); 254 canvas->restore(); 255 256 canvas->save(); 257 canvas->translate(SkIntToScalar(160), SkIntToScalar(110)); 258 // perspective (4 points) 259 const int src4[] = { 0, 0, 64, 0, 64, 64, 0, 64 }; 260 const int dst4[] = { 0, 0, 96, 0, 64, 96, 0, 64 }; 261 doDraw(canvas, &paint, src4, dst4, 4); 262 canvas->restore(); 263 } 264 265 private: 266 typedef skiagm::GM INHERITED; 267 }; 268 269 ////////////////////////////////////////////////////////////////////////////// 270 271 DEF_GM( return new Poly2PolyGM; ) 272