blob: ea57208cae9cea707138ded96c0cdd9a7b804d48 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001/*
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 */
reed@google.com8ea69832013-06-21 15:11:40 +00007
reed@google.com67981c52011-02-17 14:21:01 +00008#include "gm.h"
Mike Klein33d20552017-03-22 13:47:51 -04009#include "sk_tool_utils.h"
caryclarkf597c422015-07-28 10:37:53 -070010#include "Resources.h"
Mike Reed9cd2a5c2019-01-22 15:17:59 -050011#include "SkFontMetrics.h"
bungemand3ebb482015-08-05 13:57:49 -070012#include "SkPath.h"
Mike Reed71f5a0b2018-10-25 16:12:39 -040013#include "SkTextUtils.h"
caryclarkf597c422015-07-28 10:37:53 -070014#include "SkTypeface.h"
reed@google.com67981c52011-02-17 14:21:01 +000015
reed@google.com8ea69832013-06-21 15:11:40 +000016class SkJSCanvas {
17public:
18 SkJSCanvas(SkCanvas* target);
19 ~SkJSCanvas();
reed@google.com67981c52011-02-17 14:21:01 +000020
reed@google.com8ea69832013-06-21 15:11:40 +000021 void save();
22 void restore();
skia.committer@gmail.com020b25b2013-06-22 07:00:58 +000023
reed@google.com8ea69832013-06-21 15:11:40 +000024 double lineWidth;
25 void setLineWidth(double);
skia.committer@gmail.com020b25b2013-06-22 07:00:58 +000026
reed@google.com8ea69832013-06-21 15:11:40 +000027 void beginPath();
28 void moveTo(double x, double y);
29 void lineTo(double x, double y);
30 void closePath();
skia.committer@gmail.com020b25b2013-06-22 07:00:58 +000031
reed@google.com8ea69832013-06-21 15:11:40 +000032 void fill();
33 void stroke();
skia.committer@gmail.com020b25b2013-06-22 07:00:58 +000034
reed@google.com8ea69832013-06-21 15:11:40 +000035 void fillText(const char text[], double x, double y);
36
37private:
38 SkCanvas* fTarget;
39 SkPaint fFillPaint;
40 SkPaint fStrokePaint;
41 SkPath fPath;
Hal Canarydf2d27e2019-01-08 09:38:02 -050042 SkFont fFont;
reed@google.com8ea69832013-06-21 15:11:40 +000043};
44
Hal Canarydf2d27e2019-01-08 09:38:02 -050045SkJSCanvas::SkJSCanvas(SkCanvas* target)
46 : fTarget(target)
47 , fFont(sk_tool_utils::create_portable_typeface(), 12) {
reed@google.com8ea69832013-06-21 15:11:40 +000048 fFillPaint.setAntiAlias(true);
49 fStrokePaint.setAntiAlias(true);
50 fStrokePaint.setStyle(SkPaint::kStroke_Style);
51 fStrokePaint.setStrokeWidth(SK_Scalar1);
52}
53
54SkJSCanvas::~SkJSCanvas() {}
55
56void SkJSCanvas::save() { fTarget->save(); }
57void SkJSCanvas::restore() { fTarget->restore(); }
58
59void SkJSCanvas::beginPath() { fPath.reset(); }
60void SkJSCanvas::moveTo(double x, double y) {
61 fPath.moveTo(SkDoubleToScalar(x), SkDoubleToScalar(y));
62}
63
64void SkJSCanvas::lineTo(double x, double y) {
65 fPath.lineTo(SkDoubleToScalar(x), SkDoubleToScalar(y));
66}
67
68void SkJSCanvas::closePath() { fPath.close(); }
69
70void SkJSCanvas::fill() {
71 fTarget->drawPath(fPath, fFillPaint);
72}
73
74void SkJSCanvas::stroke() {
75 fStrokePaint.setStrokeWidth(SkDoubleToScalar(lineWidth));
76 fTarget->drawPath(fPath, fStrokePaint);
77}
78
79void SkJSCanvas::fillText(const char text[], double x, double y) {
Hal Canarydf2d27e2019-01-08 09:38:02 -050080 fTarget->drawString(text, SkDoubleToScalar(x), SkDoubleToScalar(y), fFont, fFillPaint);
reed@google.com8ea69832013-06-21 15:11:40 +000081}
82
83///////////////////////////////////////////////////////////////////////////////
84
85static 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
91static 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 }
skia.committer@gmail.com020b25b2013-06-22 07:00:58 +0000106
reed@google.com8ea69832013-06-21 15:11:40 +0000107#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();
skia.committer@gmail.com020b25b2013-06-22 07:00:58 +0000124
reed@google.com8ea69832013-06-21 15:11:40 +0000125 // no extra moveTo here
126 // ctx.moveTo(175, 125);
skia.committer@gmail.com020b25b2013-06-22 07:00:58 +0000127
reed@google.com8ea69832013-06-21 15:11:40 +0000128 ctx.stroke();
129 ctx.restore();
skia.committer@gmail.com020b25b2013-06-22 07:00:58 +0000130
reed@google.com8ea69832013-06-21 15:11:40 +0000131 ctx.fillText("As Expected", 10, 10);
skia.committer@gmail.com020b25b2013-06-22 07:00:58 +0000132
reed@google.com8ea69832013-06-21 15:11:40 +0000133#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();
skia.committer@gmail.com020b25b2013-06-22 07:00:58 +0000150
reed@google.com8ea69832013-06-21 15:11:40 +0000151 ctx.moveTo(175, 125);
skia.committer@gmail.com020b25b2013-06-22 07:00:58 +0000152
reed@google.com8ea69832013-06-21 15:11:40 +0000153 ctx.stroke();
154 ctx.restore();
skia.committer@gmail.com020b25b2013-06-22 07:00:58 +0000155
reed@google.com8ea69832013-06-21 15:11:40 +0000156 ctx.fillText("Larger Rectangle", 10, 10);
skia.committer@gmail.com020b25b2013-06-22 07:00:58 +0000157
reed@google.com8ea69832013-06-21 15:11:40 +0000158#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();
skia.committer@gmail.com020b25b2013-06-22 07:00:58 +0000175
reed@google.com8ea69832013-06-21 15:11:40 +0000176 ctx.moveTo(175, 125);
skia.committer@gmail.com020b25b2013-06-22 07:00:58 +0000177
reed@google.com8ea69832013-06-21 15:11:40 +0000178 ctx.stroke();
179 ctx.restore();
skia.committer@gmail.com020b25b2013-06-22 07:00:58 +0000180
reed@google.com8ea69832013-06-21 15:11:40 +0000181 ctx.fillText("As Expected - line width 1", 10, 10);
182}
183
184class Poly2PolyGM : public skiagm::GM {
reed@google.com67981c52011-02-17 14:21:01 +0000185public:
rmistry@google.comd6176b02012-08-23 18:14:13 +0000186 Poly2PolyGM() {}
187
reed@google.com67981c52011-02-17 14:21:01 +0000188protected:
commit-bot@chromium.orga90c6802014-04-30 13:20:45 +0000189
mtklein36352bf2015-03-25 18:17:31 -0700190 SkString onShortName() override {
reed@google.com67981c52011-02-17 14:21:01 +0000191 return SkString("poly2poly");
192 }
193
mtklein36352bf2015-03-25 18:17:31 -0700194 SkISize onISize() override {
reed@google.com8ea69832013-06-21 15:11:40 +0000195 return SkISize::Make(835, 840);
reed@google.com67981c52011-02-17 14:21:01 +0000196 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000197
Mike Reeddc5863c2018-12-23 23:19:14 -0500198 static void doDraw(SkCanvas* canvas, const SkFont& font, SkPaint* paint, const int isrc[],
reed@google.com67981c52011-02-17 14:21:01 +0000199 const int idst[], int count) {
200 SkMatrix matrix;
201 SkPoint src[4], dst[4];
rmistry@google.comd6176b02012-08-23 18:14:13 +0000202
reed@google.com67981c52011-02-17 14:21:01 +0000203 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 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000207
reed@google.com67981c52011-02-17 14:21:01 +0000208 canvas->save();
209 matrix.setPolyToPoly(src, dst, count);
210 canvas->concat(matrix);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000211
Mike Kleind46dce32018-08-16 10:17:03 -0400212 paint->setColor(SK_ColorGRAY);
reed@google.com67981c52011-02-17 14:21:01 +0000213 paint->setStyle(SkPaint::kStroke_Style);
Mike Reed3661bc92017-02-22 13:21:42 -0500214 const SkScalar D = 64;
215 canvas->drawRect(SkRect::MakeWH(D, D), *paint);
reed@google.com67981c52011-02-17 14:21:01 +0000216 canvas->drawLine(0, 0, D, D, *paint);
217 canvas->drawLine(0, D, D, 0, *paint);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000218
Mike Reedb5784ac2018-11-12 09:35:15 -0500219 SkFontMetrics fm;
Mike Reeddc5863c2018-12-23 23:19:14 -0500220 font.getMetrics(&fm);
reed@google.com67981c52011-02-17 14:21:01 +0000221 paint->setColor(SK_ColorRED);
222 paint->setStyle(SkPaint::kFill_Style);
223 SkScalar x = D/2;
bsalomon@google.com72e49b82011-10-27 21:47:03 +0000224 SkScalar y = D/2 - (fm.fAscent + fm.fDescent)/2;
caryclarkf597c422015-07-28 10:37:53 -0700225 uint16_t glyphID = 3; // X
Mike Reeddc5863c2018-12-23 23:19:14 -0500226 SkTextUtils::Draw(canvas, &glyphID, sizeof(glyphID), kGlyphID_SkTextEncoding, x, y,
227 font, *paint, SkTextUtils::kCenter_Align);
reed@google.com67981c52011-02-17 14:21:01 +0000228 canvas->restore();
229 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000230
caryclarkf597c422015-07-28 10:37:53 -0700231 void onOnceBeforeDraw() override {
Hal Canary53e5e7d2017-12-08 14:25:14 -0500232 fEmFace = MakeResourceAsTypeface("fonts/Em.ttf");
caryclarkf597c422015-07-28 10:37:53 -0700233 }
234
mtklein36352bf2015-03-25 18:17:31 -0700235 void onDraw(SkCanvas* canvas) override {
reed@google.com8ea69832013-06-21 15:11:40 +0000236 if (false) { test_stroke(canvas); return; }
237
reed@google.com67981c52011-02-17 14:21:01 +0000238 SkPaint paint;
239 paint.setAntiAlias(true);
240 paint.setStrokeWidth(SkIntToScalar(4));
Mike Reeddc5863c2018-12-23 23:19:14 -0500241 SkFont font(fEmFace, 40);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000242
reed@google.com67981c52011-02-17 14:21:01 +0000243 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 };
Mike Reeddc5863c2018-12-23 23:19:14 -0500248 doDraw(canvas, font, &paint, src1, dst1, 1);
reed@google.com67981c52011-02-17 14:21:01 +0000249 canvas->restore();
rmistry@google.comd6176b02012-08-23 18:14:13 +0000250
reed@google.com67981c52011-02-17 14:21:01 +0000251 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 };
Mike Reeddc5863c2018-12-23 23:19:14 -0500256 doDraw(canvas, font, &paint, src2, dst2, 2);
reed@google.com67981c52011-02-17 14:21:01 +0000257 canvas->restore();
rmistry@google.comd6176b02012-08-23 18:14:13 +0000258
reed@google.com67981c52011-02-17 14:21:01 +0000259 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 };
Mike Reeddc5863c2018-12-23 23:19:14 -0500264 doDraw(canvas, font, &paint, src3, dst3, 3);
reed@google.com67981c52011-02-17 14:21:01 +0000265 canvas->restore();
rmistry@google.comd6176b02012-08-23 18:14:13 +0000266
reed@google.com67981c52011-02-17 14:21:01 +0000267 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 };
Mike Reeddc5863c2018-12-23 23:19:14 -0500272 doDraw(canvas, font, &paint, src4, dst4, 4);
reed@google.com67981c52011-02-17 14:21:01 +0000273 canvas->restore();
274 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000275
reed@google.com67981c52011-02-17 14:21:01 +0000276private:
reed@google.com8ea69832013-06-21 15:11:40 +0000277 typedef skiagm::GM INHERITED;
bungeman13b9c952016-05-12 10:09:30 -0700278 sk_sp<SkTypeface> fEmFace;
reed@google.com67981c52011-02-17 14:21:01 +0000279};
280
281//////////////////////////////////////////////////////////////////////////////
282
reed@google.com8ea69832013-06-21 15:11:40 +0000283DEF_GM( return new Poly2PolyGM; )