blob: 9b3b1a46380e979cc7a174724f346cc14d410998 [file] [log] [blame]
mike@reedtribe.orgf2c21cd2011-06-18 00:15:04 +00001/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00002 * 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.
mike@reedtribe.orgf2c21cd2011-06-18 00:15:04 +00006 */
7
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "gm/gm.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -04009#include "include/core/SkCanvas.h"
10#include "include/core/SkColor.h"
11#include "include/core/SkPaint.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050012#include "include/core/SkPath.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040013#include "include/core/SkPathEffect.h"
14#include "include/core/SkPoint.h"
15#include "include/core/SkRect.h"
16#include "include/core/SkScalar.h"
17#include "include/core/SkSize.h"
18#include "include/core/SkString.h"
19#include "include/core/SkTypes.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050020#include "include/effects/SkDashPathEffect.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040021#include "include/private/SkFloatBits.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050022#include "include/utils/SkParsePath.h"
23#include "include/utils/SkRandom.h"
24#include "tools/ToolUtils.h"
mike@reedtribe.orgf2c21cd2011-06-18 00:15:04 +000025
Ben Wagner7fde8e12019-05-01 17:28:53 -040026#include <string.h>
27
mike@reedtribe.orgf2c21cd2011-06-18 00:15:04 +000028#define W 400
29#define H 400
30#define N 50
31
mtkleindbfd7ab2016-09-01 11:24:54 -070032constexpr SkScalar SW = SkIntToScalar(W);
33constexpr SkScalar SH = SkIntToScalar(H);
mike@reedtribe.orgf2c21cd2011-06-18 00:15:04 +000034
scroggof9d61012014-12-15 12:54:51 -080035static void rnd_rect(SkRect* r, SkPaint* paint, SkRandom& rand) {
mike@reedtribe.orgf2c21cd2011-06-18 00:15:04 +000036 SkScalar x = rand.nextUScalar1() * W;
37 SkScalar y = rand.nextUScalar1() * H;
38 SkScalar w = rand.nextUScalar1() * (W >> 2);
39 SkScalar h = rand.nextUScalar1() * (H >> 2);
epoger@google.com17b78942011-08-26 14:40:38 +000040 SkScalar hoffset = rand.nextSScalar1();
41 SkScalar woffset = rand.nextSScalar1();
rmistry@google.comae933ce2012-08-23 18:19:56 +000042
Mike Reed92b33352019-08-24 19:39:13 -040043 r->setXYWH(x, y, w, h);
epoger@google.com17b78942011-08-26 14:40:38 +000044 r->offset(-w/2 + woffset, -h/2 + hoffset);
rmistry@google.comae933ce2012-08-23 18:19:56 +000045
mike@reedtribe.orgf2c21cd2011-06-18 00:15:04 +000046 paint->setColor(rand.nextU());
Mike Reed9407e242019-02-15 16:13:57 -050047 paint->setAlphaf(1.0f);
mike@reedtribe.orgf2c21cd2011-06-18 00:15:04 +000048}
49
rmistry@google.comae933ce2012-08-23 18:19:56 +000050
reed@google.com4384fab2012-06-05 16:14:23 +000051class StrokesGM : public skiagm::GM {
mike@reedtribe.orgf2c21cd2011-06-18 00:15:04 +000052public:
53 StrokesGM() {}
rmistry@google.comae933ce2012-08-23 18:19:56 +000054
mike@reedtribe.orgf2c21cd2011-06-18 00:15:04 +000055protected:
commit-bot@chromium.orga90c6802014-04-30 13:20:45 +000056
mtklein36352bf2015-03-25 18:17:31 -070057 SkString onShortName() override {
mike@reedtribe.orgf2c21cd2011-06-18 00:15:04 +000058 return SkString("strokes_round");
59 }
rmistry@google.comae933ce2012-08-23 18:19:56 +000060
mtklein36352bf2015-03-25 18:17:31 -070061 SkISize onISize() override {
reed@google.com4384fab2012-06-05 16:14:23 +000062 return SkISize::Make(W, H*2);
mike@reedtribe.orgf2c21cd2011-06-18 00:15:04 +000063 }
rmistry@google.comae933ce2012-08-23 18:19:56 +000064
mtklein36352bf2015-03-25 18:17:31 -070065 void onDraw(SkCanvas* canvas) override {
mike@reedtribe.orgf2c21cd2011-06-18 00:15:04 +000066 SkPaint paint;
67 paint.setStyle(SkPaint::kStroke_Style);
68 paint.setStrokeWidth(SkIntToScalar(9)/2);
rmistry@google.comae933ce2012-08-23 18:19:56 +000069
mike@reedtribe.orgf2c21cd2011-06-18 00:15:04 +000070 for (int y = 0; y < 2; y++) {
71 paint.setAntiAlias(!!y);
72 SkAutoCanvasRestore acr(canvas, true);
73 canvas->translate(0, SH * y);
74 canvas->clipRect(SkRect::MakeLTRB(
75 SkIntToScalar(2), SkIntToScalar(2)
76 , SW - SkIntToScalar(2), SH - SkIntToScalar(2)
77 ));
rmistry@google.comae933ce2012-08-23 18:19:56 +000078
scroggof9d61012014-12-15 12:54:51 -080079 SkRandom rand;
mike@reedtribe.orgf2c21cd2011-06-18 00:15:04 +000080 for (int i = 0; i < N; i++) {
81 SkRect r;
82 rnd_rect(&r, &paint, rand);
83 canvas->drawOval(r, paint);
84 rnd_rect(&r, &paint, rand);
85 canvas->drawRoundRect(r, r.width()/4, r.height()/4, paint);
86 rnd_rect(&r, &paint, rand);
87 }
88 }
89 }
rmistry@google.comae933ce2012-08-23 18:19:56 +000090
mike@reedtribe.orgf2c21cd2011-06-18 00:15:04 +000091private:
reed@google.com4384fab2012-06-05 16:14:23 +000092 typedef skiagm::GM INHERITED;
mike@reedtribe.orgf2c21cd2011-06-18 00:15:04 +000093};
94
caryclark5cb00a92015-08-26 09:04:55 -070095/* See
96 https://code.google.com/p/chromium/issues/detail?id=422974 and
97 http://jsfiddle.net/1xnku3sg/2/
98 */
99class ZeroLenStrokesGM : public skiagm::GM {
100 SkPath fMoveHfPath, fMoveZfPath, fDashedfPath, fRefPath[4];
caryclark6651a322015-09-09 13:20:49 -0700101 SkPath fCubicPath, fQuadPath, fLinePath;
caryclark5cb00a92015-08-26 09:04:55 -0700102protected:
103 void onOnceBeforeDraw() override {
104
105 SkAssertResult(SkParsePath::FromSVGString("M0,0h0M10,0h0M20,0h0", &fMoveHfPath));
106 SkAssertResult(SkParsePath::FromSVGString("M0,0zM10,0zM20,0z", &fMoveZfPath));
107 SkAssertResult(SkParsePath::FromSVGString("M0,0h25", &fDashedfPath));
caryclark6651a322015-09-09 13:20:49 -0700108 SkAssertResult(SkParsePath::FromSVGString("M 0 0 C 0 0 0 0 0 0", &fCubicPath));
109 SkAssertResult(SkParsePath::FromSVGString("M 0 0 Q 0 0 0 0", &fQuadPath));
110 SkAssertResult(SkParsePath::FromSVGString("M 0 0 L 0 0", &fLinePath));
caryclark5cb00a92015-08-26 09:04:55 -0700111
112 for (int i = 0; i < 3; ++i) {
113 fRefPath[0].addCircle(i * 10.f, 0, 5);
114 fRefPath[1].addCircle(i * 10.f, 0, 10);
115 fRefPath[2].addRect(i * 10.f - 4, -2, i * 10.f + 4, 6);
116 fRefPath[3].addRect(i * 10.f - 10, -10, i * 10.f + 10, 10);
117 }
118 }
119
120 SkString onShortName() override {
121 return SkString("zeroPath");
122 }
123
124 SkISize onISize() override {
125 return SkISize::Make(W, H*2);
126 }
127
128 void onDraw(SkCanvas* canvas) override {
129 SkPaint fillPaint, strokePaint, dashPaint;
130 fillPaint.setAntiAlias(true);
131 strokePaint = fillPaint;
132 strokePaint.setStyle(SkPaint::kStroke_Style);
133 for (int i = 0; i < 2; ++i) {
Mike Reed9407e242019-02-15 16:13:57 -0500134 fillPaint.setAlphaf(1.0f);
135 strokePaint.setAlphaf(1.0f);
caryclark5cb00a92015-08-26 09:04:55 -0700136 strokePaint.setStrokeWidth(i ? 8.f : 10.f);
137 strokePaint.setStrokeCap(i ? SkPaint::kSquare_Cap : SkPaint::kRound_Cap);
138 canvas->save();
139 canvas->translate(10 + i * 100.f, 10);
140 canvas->drawPath(fMoveHfPath, strokePaint);
141 canvas->translate(0, 20);
142 canvas->drawPath(fMoveZfPath, strokePaint);
143 dashPaint = strokePaint;
144 const SkScalar intervals[] = { 0, 10 };
reeda4393342016-03-18 11:22:57 -0700145 dashPaint.setPathEffect(SkDashPathEffect::Make(intervals, 2, 0));
caryclark5cb00a92015-08-26 09:04:55 -0700146 SkPath fillPath;
147 dashPaint.getFillPath(fDashedfPath, &fillPath);
148 canvas->translate(0, 20);
149 canvas->drawPath(fDashedfPath, dashPaint);
150 canvas->translate(0, 20);
151 canvas->drawPath(fRefPath[i * 2], fillPaint);
152 strokePaint.setStrokeWidth(20);
Mike Reed9407e242019-02-15 16:13:57 -0500153 strokePaint.setAlphaf(0.5f);
caryclark5cb00a92015-08-26 09:04:55 -0700154 canvas->translate(0, 50);
155 canvas->drawPath(fMoveHfPath, strokePaint);
156 canvas->translate(0, 30);
157 canvas->drawPath(fMoveZfPath, strokePaint);
158 canvas->translate(0, 30);
Mike Reed9407e242019-02-15 16:13:57 -0500159 fillPaint.setAlphaf(0.5f);
caryclark5cb00a92015-08-26 09:04:55 -0700160 canvas->drawPath(fRefPath[1 + i * 2], fillPaint);
caryclark6651a322015-09-09 13:20:49 -0700161 canvas->translate(0, 30);
162 canvas->drawPath(fCubicPath, strokePaint);
163 canvas->translate(0, 30);
164 canvas->drawPath(fQuadPath, strokePaint);
165 canvas->translate(0, 30);
166 canvas->drawPath(fLinePath, strokePaint);
caryclark5cb00a92015-08-26 09:04:55 -0700167 canvas->restore();
168 }
169 }
170
171private:
172 typedef skiagm::GM INHERITED;
173};
174
caryclark950305e2015-10-26 08:17:04 -0700175class TeenyStrokesGM : public skiagm::GM {
176
177 SkString onShortName() override {
178 return SkString("teenyStrokes");
179 }
180
181 SkISize onISize() override {
182 return SkISize::Make(W, H*2);
183 }
184
185 static void line(SkScalar scale, SkCanvas* canvas, SkColor color) {
186 SkPaint p;
187 p.setAntiAlias(true);
188 p.setStyle(SkPaint::kStroke_Style);
189 p.setColor(color);
190 canvas->translate(50, 0);
191 canvas->save();
192 p.setStrokeWidth(scale * 5);
193 canvas->scale(1 / scale, 1 / scale);
194 canvas->drawLine(20 * scale, 20 * scale, 20 * scale, 100 * scale, p);
195 canvas->drawLine(20 * scale, 20 * scale, 100 * scale, 100 * scale, p);
196 canvas->restore();
197 }
198
199 void onDraw(SkCanvas* canvas) override {
200 line(0.00005f, canvas, SK_ColorBLACK);
201 line(0.000045f, canvas, SK_ColorRED);
202 line(0.0000035f, canvas, SK_ColorGREEN);
203 line(0.000003f, canvas, SK_ColorBLUE);
204 line(0.000002f, canvas, SK_ColorBLACK);
205 }
206private:
207 typedef skiagm::GM INHERITED;
208};
209
caryclarkb775e912015-11-30 13:47:11 -0800210DEF_SIMPLE_GM(CubicStroke, canvas, 384, 384) {
211 SkPaint p;
212 p.setAntiAlias(true);
213 p.setStyle(SkPaint::kStroke_Style);
214 p.setStrokeWidth(1.0720f);
215 SkPath path;
216 path.moveTo(-6000,-6000);
217 path.cubicTo(-3500,5500,-500,5500,2500,-6500);
218 canvas->drawPath(path, p);
219 p.setStrokeWidth(1.0721f);
220 canvas->translate(10, 10);
221 canvas->drawPath(path, p);
222 p.setStrokeWidth(1.0722f);
223 canvas->translate(10, 10);
224 canvas->drawPath(path, p);
225}
caryclark950305e2015-10-26 08:17:04 -0700226
caryclark57eecc12015-12-08 04:29:45 -0800227DEF_SIMPLE_GM(zerolinestroke, canvas, 90, 120) {
228 SkPaint paint;
229 paint.setStyle(SkPaint::kStroke_Style);
230 paint.setStrokeWidth(20);
231 paint.setAntiAlias(true);
232 paint.setStrokeCap(SkPaint::kRound_Cap);
233
234 SkPath path;
235 path.moveTo(30, 90);
236 path.lineTo(30, 90);
237 path.lineTo(60, 90);
238 path.lineTo(60, 90);
239 canvas->drawPath(path, paint);
240
241 path.reset();
242 path.moveTo(30, 30);
243 path.lineTo(60, 30);
244 canvas->drawPath(path, paint);
245
246 path.reset();
247 path.moveTo(30, 60);
248 path.lineTo(30, 60);
249 path.lineTo(60, 60);
250 canvas->drawPath(path, paint);
251}
252
caryclark40b7d3b2015-12-22 06:13:33 -0800253DEF_SIMPLE_GM(quadcap, canvas, 200, 200) {
254 SkPaint p;
255 p.setAntiAlias(true);
256 p.setStyle(SkPaint::kStroke_Style);
257 p.setStrokeWidth(0);
258 SkPath path;
259 SkPoint pts[] = {{105.738571f,13.126318f},
halcanary9d524f22016-03-29 09:03:52 -0700260 {105.738571f,13.126318f},
caryclark40b7d3b2015-12-22 06:13:33 -0800261 {123.753784f,1.f}};
262 SkVector tangent = pts[1] - pts[2];
263 tangent.normalize();
264 SkPoint pts2[3];
265 memcpy(pts2, pts, sizeof(pts));
266 const SkScalar capOutset = SK_ScalarPI / 8;
267 pts2[0].fX += tangent.fX * capOutset;
268 pts2[0].fY += tangent.fY * capOutset;
269 pts2[1].fX += tangent.fX * capOutset;
270 pts2[1].fY += tangent.fY * capOutset;
271 pts2[2].fX += -tangent.fX * capOutset;
272 pts2[2].fY += -tangent.fY * capOutset;
273 path.moveTo(pts2[0]);
274 path.quadTo(pts2[1], pts2[2]);
275 canvas->drawPath(path, p);
276
277 path.reset();
278 path.moveTo(pts[0]);
279 path.quadTo(pts[1], pts[2]);
280 p.setStrokeCap(SkPaint::kRound_Cap);
281 canvas->translate(30, 0);
282 canvas->drawPath(path, p);
283}
284
reed@google.com4384fab2012-06-05 16:14:23 +0000285class Strokes2GM : public skiagm::GM {
mike@reedtribe.orgf2c21cd2011-06-18 00:15:04 +0000286 SkPath fPath;
caryclark63c684a2015-02-25 09:04:04 -0800287protected:
mtklein36352bf2015-03-25 18:17:31 -0700288 void onOnceBeforeDraw() override {
scroggof9d61012014-12-15 12:54:51 -0800289 SkRandom rand;
mike@reedtribe.orgf2c21cd2011-06-18 00:15:04 +0000290 fPath.moveTo(0, 0);
291 for (int i = 0; i < 13; i++) {
292 SkScalar x = rand.nextUScalar1() * (W >> 1);
293 SkScalar y = rand.nextUScalar1() * (H >> 1);
294 fPath.lineTo(x, y);
295 }
296 }
rmistry@google.comae933ce2012-08-23 18:19:56 +0000297
commit-bot@chromium.orga90c6802014-04-30 13:20:45 +0000298
mtklein36352bf2015-03-25 18:17:31 -0700299 SkString onShortName() override {
mike@reedtribe.orgf2c21cd2011-06-18 00:15:04 +0000300 return SkString("strokes_poly");
301 }
rmistry@google.comae933ce2012-08-23 18:19:56 +0000302
mtklein36352bf2015-03-25 18:17:31 -0700303 SkISize onISize() override {
reed@google.com4384fab2012-06-05 16:14:23 +0000304 return SkISize::Make(W, H*2);
mike@reedtribe.orgf2c21cd2011-06-18 00:15:04 +0000305 }
rmistry@google.comae933ce2012-08-23 18:19:56 +0000306
mtklein36352bf2015-03-25 18:17:31 -0700307 void onDraw(SkCanvas* canvas) override {
mike@reedtribe.orgf2c21cd2011-06-18 00:15:04 +0000308 canvas->drawColor(SK_ColorWHITE);
rmistry@google.comae933ce2012-08-23 18:19:56 +0000309
mike@reedtribe.orgf2c21cd2011-06-18 00:15:04 +0000310 SkPaint paint;
311 paint.setStyle(SkPaint::kStroke_Style);
312 paint.setStrokeWidth(SkIntToScalar(9)/2);
rmistry@google.comae933ce2012-08-23 18:19:56 +0000313
mike@reedtribe.orgf2c21cd2011-06-18 00:15:04 +0000314 for (int y = 0; y < 2; y++) {
315 paint.setAntiAlias(!!y);
316 SkAutoCanvasRestore acr(canvas, true);
317 canvas->translate(0, SH * y);
318 canvas->clipRect(SkRect::MakeLTRB(SkIntToScalar(2),
319 SkIntToScalar(2),
320 SW - SkIntToScalar(2),
321 SH - SkIntToScalar(2)));
rmistry@google.comae933ce2012-08-23 18:19:56 +0000322
scroggof9d61012014-12-15 12:54:51 -0800323 SkRandom rand;
mike@reedtribe.orgf2c21cd2011-06-18 00:15:04 +0000324 for (int i = 0; i < N/2; i++) {
325 SkRect r;
326 rnd_rect(&r, &paint, rand);
bungeman7438bfc2016-07-12 15:01:19 -0700327 canvas->rotate(SkIntToScalar(15), SW/2, SH/2);
mike@reedtribe.orgf2c21cd2011-06-18 00:15:04 +0000328 canvas->drawPath(fPath, paint);
329 }
330 }
331 }
rmistry@google.comae933ce2012-08-23 18:19:56 +0000332
mike@reedtribe.orgf2c21cd2011-06-18 00:15:04 +0000333private:
reed@google.com4384fab2012-06-05 16:14:23 +0000334 typedef skiagm::GM INHERITED;
mike@reedtribe.orgf2c21cd2011-06-18 00:15:04 +0000335};
336
337//////////////////////////////////////////////////////////////////////////////
338
reed@google.com4384fab2012-06-05 16:14:23 +0000339static SkRect inset(const SkRect& r) {
340 SkRect rr(r);
341 rr.inset(r.width()/10, r.height()/10);
342 return rr;
mike@reedtribe.orgf2c21cd2011-06-18 00:15:04 +0000343}
344
reed@google.com4384fab2012-06-05 16:14:23 +0000345class Strokes3GM : public skiagm::GM {
346 static void make0(SkPath* path, const SkRect& bounds, SkString* title) {
Mike Reed30bc5272019-11-22 18:34:02 +0000347 path->addRect(bounds, SkPathDirection::kCW);
348 path->addRect(inset(bounds), SkPathDirection::kCW);
reed@google.com4384fab2012-06-05 16:14:23 +0000349 title->set("CW CW");
350 }
rmistry@google.comae933ce2012-08-23 18:19:56 +0000351
reed@google.com4384fab2012-06-05 16:14:23 +0000352 static void make1(SkPath* path, const SkRect& bounds, SkString* title) {
Mike Reed30bc5272019-11-22 18:34:02 +0000353 path->addRect(bounds, SkPathDirection::kCW);
354 path->addRect(inset(bounds), SkPathDirection::kCCW);
reed@google.com4384fab2012-06-05 16:14:23 +0000355 title->set("CW CCW");
356 }
rmistry@google.comae933ce2012-08-23 18:19:56 +0000357
reed@google.com4384fab2012-06-05 16:14:23 +0000358 static void make2(SkPath* path, const SkRect& bounds, SkString* title) {
Mike Reed30bc5272019-11-22 18:34:02 +0000359 path->addOval(bounds, SkPathDirection::kCW);
360 path->addOval(inset(bounds), SkPathDirection::kCW);
reed@google.com4384fab2012-06-05 16:14:23 +0000361 title->set("CW CW");
362 }
rmistry@google.comae933ce2012-08-23 18:19:56 +0000363
reed@google.com4384fab2012-06-05 16:14:23 +0000364 static void make3(SkPath* path, const SkRect& bounds, SkString* title) {
Mike Reed30bc5272019-11-22 18:34:02 +0000365 path->addOval(bounds, SkPathDirection::kCW);
366 path->addOval(inset(bounds), SkPathDirection::kCCW);
reed@google.com4384fab2012-06-05 16:14:23 +0000367 title->set("CW CCW");
368 }
rmistry@google.comae933ce2012-08-23 18:19:56 +0000369
reed@google.com4384fab2012-06-05 16:14:23 +0000370 static void make4(SkPath* path, const SkRect& bounds, SkString* title) {
Mike Reed30bc5272019-11-22 18:34:02 +0000371 path->addRect(bounds, SkPathDirection::kCW);
reed@google.com4384fab2012-06-05 16:14:23 +0000372 SkRect r = bounds;
373 r.inset(bounds.width() / 10, -bounds.height() / 10);
Mike Reed30bc5272019-11-22 18:34:02 +0000374 path->addOval(r, SkPathDirection::kCW);
reed@google.com4384fab2012-06-05 16:14:23 +0000375 title->set("CW CW");
376 }
rmistry@google.comae933ce2012-08-23 18:19:56 +0000377
reed@google.com4384fab2012-06-05 16:14:23 +0000378 static void make5(SkPath* path, const SkRect& bounds, SkString* title) {
Mike Reed30bc5272019-11-22 18:34:02 +0000379 path->addRect(bounds, SkPathDirection::kCW);
reed@google.com4384fab2012-06-05 16:14:23 +0000380 SkRect r = bounds;
381 r.inset(bounds.width() / 10, -bounds.height() / 10);
Mike Reed30bc5272019-11-22 18:34:02 +0000382 path->addOval(r, SkPathDirection::kCCW);
reed@google.com4384fab2012-06-05 16:14:23 +0000383 title->set("CW CCW");
384 }
385
386public:
387 Strokes3GM() {}
rmistry@google.comae933ce2012-08-23 18:19:56 +0000388
reed@google.com4384fab2012-06-05 16:14:23 +0000389protected:
commit-bot@chromium.orga90c6802014-04-30 13:20:45 +0000390
mtklein36352bf2015-03-25 18:17:31 -0700391 SkString onShortName() override {
reed@google.com4384fab2012-06-05 16:14:23 +0000392 return SkString("strokes3");
393 }
rmistry@google.comae933ce2012-08-23 18:19:56 +0000394
mtklein36352bf2015-03-25 18:17:31 -0700395 SkISize onISize() override {
caryclark37604572015-02-23 06:51:04 -0800396 return SkISize::Make(1500, 1500);
reed@google.com4384fab2012-06-05 16:14:23 +0000397 }
rmistry@google.comae933ce2012-08-23 18:19:56 +0000398
mtklein36352bf2015-03-25 18:17:31 -0700399 void onDraw(SkCanvas* canvas) override {
reed@google.com4384fab2012-06-05 16:14:23 +0000400 SkPaint origPaint;
401 origPaint.setAntiAlias(true);
402 origPaint.setStyle(SkPaint::kStroke_Style);
403 SkPaint fillPaint(origPaint);
404 fillPaint.setColor(SK_ColorRED);
405 SkPaint strokePaint(origPaint);
Mike Kleinea3f0142019-03-20 11:12:10 -0500406 strokePaint.setColor(ToolUtils::color_to_565(0xFF4444FF));
reed@google.com4384fab2012-06-05 16:14:23 +0000407
408 void (*procs[])(SkPath*, const SkRect&, SkString*) = {
409 make0, make1, make2, make3, make4, make5
410 };
411
caryclark37604572015-02-23 06:51:04 -0800412 canvas->translate(SkIntToScalar(20), SkIntToScalar(80));
reed@google.com4384fab2012-06-05 16:14:23 +0000413
414 SkRect bounds = SkRect::MakeWH(SkIntToScalar(50), SkIntToScalar(50));
415 SkScalar dx = bounds.width() * 4/3;
416 SkScalar dy = bounds.height() * 5;
417
418 for (size_t i = 0; i < SK_ARRAY_COUNT(procs); ++i) {
419 SkPath orig;
420 SkString str;
421 procs[i](&orig, bounds, &str);
rmistry@google.comae933ce2012-08-23 18:19:56 +0000422
reed@google.com4384fab2012-06-05 16:14:23 +0000423 canvas->save();
424 for (int j = 0; j < 13; ++j) {
425 strokePaint.setStrokeWidth(SK_Scalar1 * j * j);
426 canvas->drawPath(orig, strokePaint);
427 canvas->drawPath(orig, origPaint);
428 SkPath fill;
429 strokePaint.getFillPath(orig, &fill);
430 canvas->drawPath(fill, fillPaint);
431 canvas->translate(dx + strokePaint.getStrokeWidth(), 0);
432 }
433 canvas->restore();
434 canvas->translate(0, dy);
435 }
436 }
rmistry@google.comae933ce2012-08-23 18:19:56 +0000437
reed@google.com4384fab2012-06-05 16:14:23 +0000438private:
439 typedef skiagm::GM INHERITED;
440};
441
caryclark612f70d2015-05-19 11:05:37 -0700442class Strokes4GM : public skiagm::GM {
443public:
444 Strokes4GM() {}
445
446protected:
447
448 SkString onShortName() override {
449 return SkString("strokes_zoomed");
450 }
451
452 SkISize onISize() override {
453 return SkISize::Make(W, H*2);
454 }
455
456 void onDraw(SkCanvas* canvas) override {
457 SkPaint paint;
458 paint.setStyle(SkPaint::kStroke_Style);
459 paint.setStrokeWidth(0.055f);
halcanary9d524f22016-03-29 09:03:52 -0700460
caryclark612f70d2015-05-19 11:05:37 -0700461 canvas->scale(1000, 1000);
462 canvas->drawCircle(0, 2, 1.97f, paint);
463 }
464
465private:
466 typedef skiagm::GM INHERITED;
467};
468
caryclark45398df2015-08-25 13:19:06 -0700469// Test stroking for curves that produce degenerate tangents when t is 0 or 1 (see bug 4191)
470class Strokes5GM : public skiagm::GM {
471public:
472 Strokes5GM() {}
473
474protected:
475
476 SkString onShortName() override {
477 return SkString("zero_control_stroke");
478 }
479
480 SkISize onISize() override {
481 return SkISize::Make(W, H*2);
482 }
483
484 void onDraw(SkCanvas* canvas) override {
485 SkPaint p;
486 p.setColor(SK_ColorRED);
487 p.setAntiAlias(true);
488 p.setStyle(SkPaint::kStroke_Style);
489 p.setStrokeWidth(40);
490 p.setStrokeCap(SkPaint::kButt_Cap);
491
492 SkPath path;
493 path.moveTo(157.474f,111.753f);
494 path.cubicTo(128.5f,111.5f,35.5f,29.5f,35.5f,29.5f);
495 canvas->drawPath(path, p);
496 path.reset();
497 path.moveTo(250, 50);
498 path.quadTo(280, 80, 280, 80);
499 canvas->drawPath(path, p);
500 path.reset();
501 path.moveTo(150, 50);
502 path.conicTo(180, 80, 180, 80, 0.707f);
503 canvas->drawPath(path, p);
504
505 path.reset();
506 path.moveTo(157.474f,311.753f);
507 path.cubicTo(157.474f,311.753f,85.5f,229.5f,35.5f,229.5f);
508 canvas->drawPath(path, p);
509 path.reset();
510 path.moveTo(280, 250);
511 path.quadTo(280, 250, 310, 280);
512 canvas->drawPath(path, p);
513 path.reset();
514 path.moveTo(180, 250);
515 path.conicTo(180, 250, 210, 280, 0.707f);
516 canvas->drawPath(path, p);
517 }
518
519private:
520 typedef skiagm::GM INHERITED;
521};
522
caryclark612f70d2015-05-19 11:05:37 -0700523
reed@google.com4384fab2012-06-05 16:14:23 +0000524//////////////////////////////////////////////////////////////////////////////
525
scroggo96f16e82015-12-10 13:31:59 -0800526DEF_GM( return new StrokesGM; )
527DEF_GM( return new Strokes2GM; )
528DEF_GM( return new Strokes3GM; )
529DEF_GM( return new Strokes4GM; )
530DEF_GM( return new Strokes5GM; )
caryclark5cb00a92015-08-26 09:04:55 -0700531
halcanary385fe4d2015-08-26 13:07:48 -0700532DEF_GM( return new ZeroLenStrokesGM; )
caryclark950305e2015-10-26 08:17:04 -0700533DEF_GM( return new TeenyStrokesGM; )
Cary Clark0b1df4b2017-12-13 12:47:15 -0500534
535DEF_SIMPLE_GM(zerolinedash, canvas, 256, 256) {
536 canvas->clear(SK_ColorWHITE);
537
538 SkPaint paint;
539 paint.setColor(SkColorSetARGB(255, 0, 0, 0));
540 paint.setStrokeWidth(11);
541 paint.setStrokeCap(SkPaint::kRound_Cap);
542 paint.setStrokeJoin(SkPaint::kBevel_Join);
543
544 SkScalar dash_pattern[] = {1, 5};
545 paint.setPathEffect(SkDashPathEffect::Make(dash_pattern, 2, 0));
546
547 canvas->drawLine(100, 100, 100, 100, paint);
548}
Greg Daniel9838b492017-12-21 14:55:00 +0000549
550#ifdef PDF_IS_FIXED_SO_THIS_DOESNT_BREAK_IT
551DEF_SIMPLE_GM(longrect_dash, canvas, 250, 250) {
552 canvas->clear(SK_ColorWHITE);
553
554 SkPaint paint;
555 paint.setColor(SkColorSetARGB(255, 0, 0, 0));
556 paint.setStrokeWidth(5);
557 paint.setStrokeCap(SkPaint::kRound_Cap);
558 paint.setStrokeJoin(SkPaint::kBevel_Join);
559 paint.setStyle(SkPaint::kStroke_Style);
560 SkScalar dash_pattern[] = {1, 5};
561 paint.setPathEffect(SkDashPathEffect::Make(dash_pattern, 2, 0));
562 // try all combinations of stretching bounds
563 for (auto left : { 20.f, -100001.f } ) {
564 for (auto top : { 20.f, -100001.f } ) {
565 for (auto right : { 40.f, 100001.f } ) {
566 for (auto bottom : { 40.f, 100001.f } ) {
567 canvas->save();
568 canvas->clipRect({10, 10, 50, 50});
569 canvas->drawRect({left, top, right, bottom}, paint);
570 canvas->restore();
571 canvas->translate(60, 0);
572 }
573 }
574 canvas->translate(-60 * 4, 60);
575 }
576 }
577}
578#endif