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