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 sk_tool_utils::set_portable_typeface(&fFillPaint); 41 fStrokePaint.setAntiAlias(true); 42 fStrokePaint.setStyle(SkPaint::kStroke_Style); 43 fStrokePaint.setStrokeWidth(SK_Scalar1); 44 } 45 46 SkJSCanvas::~SkJSCanvas() {} 47 48 void SkJSCanvas::save() { fTarget->save(); } 49 void SkJSCanvas::restore() { fTarget->restore(); } 50 51 void SkJSCanvas::beginPath() { fPath.reset(); } 52 void SkJSCanvas::moveTo(double x, double y) { 53 fPath.moveTo(SkDoubleToScalar(x), SkDoubleToScalar(y)); 54 } 55 56 void SkJSCanvas::lineTo(double x, double y) { 57 fPath.lineTo(SkDoubleToScalar(x), SkDoubleToScalar(y)); 58 } 59 60 void SkJSCanvas::closePath() { fPath.close(); } 61 62 void SkJSCanvas::fill() { 63 fTarget->drawPath(fPath, fFillPaint); 64 } 65 66 void SkJSCanvas::stroke() { 67 fStrokePaint.setStrokeWidth(SkDoubleToScalar(lineWidth)); 68 fTarget->drawPath(fPath, fStrokePaint); 69 } 70 71 void 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 78 static 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 84 static 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 177 class Poly2PolyGM : public skiagm::GM { 178 public: 179 Poly2PolyGM() {} 180 181 protected: 182 virtual uint32_t onGetFlags() const SK_OVERRIDE { 183 return kSkipTiled_Flag; 184 } 185 186 virtual SkString onShortName() SK_OVERRIDE { 187 return SkString("poly2poly"); 188 } 189 190 virtual SkISize onISize() SK_OVERRIDE { 191 return SkISize::Make(835, 840); 192 } 193 194 static void doDraw(SkCanvas* canvas, SkPaint* paint, const int isrc[], 195 const int idst[], int count) { 196 SkMatrix matrix; 197 SkPoint src[4], dst[4]; 198 199 for (int i = 0; i < count; i++) { 200 src[i].set(SkIntToScalar(isrc[2*i+0]), SkIntToScalar(isrc[2*i+1])); 201 dst[i].set(SkIntToScalar(idst[2*i+0]), SkIntToScalar(idst[2*i+1])); 202 } 203 204 canvas->save(); 205 matrix.setPolyToPoly(src, dst, count); 206 canvas->concat(matrix); 207 208 paint->setColor(SK_ColorGRAY); 209 paint->setStyle(SkPaint::kStroke_Style); 210 const SkScalar D = SkIntToScalar(64); 211 canvas->drawRectCoords(0, 0, D, D, *paint); 212 canvas->drawLine(0, 0, D, D, *paint); 213 canvas->drawLine(0, D, D, 0, *paint); 214 215 SkPaint::FontMetrics fm; 216 paint->getFontMetrics(&fm); 217 paint->setColor(SK_ColorRED); 218 paint->setStyle(SkPaint::kFill_Style); 219 SkScalar x = D/2; 220 SkScalar y = D/2 - (fm.fAscent + fm.fDescent)/2; 221 SkString str; 222 str.appendS32(count); 223 canvas->drawText(str.c_str(), str.size(), x, y, *paint); 224 225 canvas->restore(); 226 } 227 228 virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE { 229 if (false) { test_stroke(canvas); return; } 230 231 SkPaint paint; 232 paint.setAntiAlias(true); 233 sk_tool_utils::set_portable_typeface(&paint); 234 paint.setStrokeWidth(SkIntToScalar(4)); 235 paint.setTextSize(SkIntToScalar(40)); 236 paint.setTextAlign(SkPaint::kCenter_Align); 237 238 canvas->save(); 239 canvas->translate(SkIntToScalar(10), SkIntToScalar(10)); 240 // translate (1 point) 241 const int src1[] = { 0, 0 }; 242 const int dst1[] = { 5, 5 }; 243 doDraw(canvas, &paint, src1, dst1, 1); 244 canvas->restore(); 245 246 canvas->save(); 247 canvas->translate(SkIntToScalar(160), SkIntToScalar(10)); 248 // rotate/uniform-scale (2 points) 249 const int src2[] = { 32, 32, 64, 32 }; 250 const int dst2[] = { 32, 32, 64, 48 }; 251 doDraw(canvas, &paint, src2, dst2, 2); 252 canvas->restore(); 253 254 canvas->save(); 255 canvas->translate(SkIntToScalar(10), SkIntToScalar(110)); 256 // rotate/skew (3 points) 257 const int src3[] = { 0, 0, 64, 0, 0, 64 }; 258 const int dst3[] = { 0, 0, 96, 0, 24, 64 }; 259 doDraw(canvas, &paint, src3, dst3, 3); 260 canvas->restore(); 261 262 canvas->save(); 263 canvas->translate(SkIntToScalar(160), SkIntToScalar(110)); 264 // perspective (4 points) 265 const int src4[] = { 0, 0, 64, 0, 64, 64, 0, 64 }; 266 const int dst4[] = { 0, 0, 96, 0, 64, 96, 0, 64 }; 267 doDraw(canvas, &paint, src4, dst4, 4); 268 canvas->restore(); 269 } 270 271 private: 272 typedef skiagm::GM INHERITED; 273 }; 274 275 ////////////////////////////////////////////////////////////////////////////// 276 277 DEF_GM( return new Poly2PolyGM; ) 278