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