blob: abac5b21776bcebf952a3f41d79161263e5933fd [file] [log] [blame]
schenney@chromium.org4da06ab2011-12-20 15:14:18 +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 */
bungemand3ebb482015-08-05 13:57:49 -07007
schenney@chromium.org4da06ab2011-12-20 15:14:18 +00008#include "gm.h"
9#include "SkCanvas.h"
10#include "SkPaint.h"
bungemand3ebb482015-08-05 13:57:49 -070011#include "SkPath.h"
schenney@chromium.org4da06ab2011-12-20 15:14:18 +000012#include "SkRandom.h"
13
halcanary6950de62015-11-07 05:29:00 -080014// https://bug.skia.org/1316 shows that this cubic, when slightly clipped, creates big
reed@google.com22999c62013-05-23 19:30:48 +000015// (incorrect) changes to its control points.
16class ClippedCubicGM : public skiagm::GM {
17public:
18 ClippedCubicGM() {}
skia.committer@gmail.com3e2345a2013-05-24 07:01:26 +000019
reed@google.com22999c62013-05-23 19:30:48 +000020protected:
commit-bot@chromium.orga90c6802014-04-30 13:20:45 +000021
reed@google.com22999c62013-05-23 19:30:48 +000022 SkString onShortName() {
reed@google.com03ca64b2013-05-23 19:39:15 +000023 return SkString("clippedcubic");
reed@google.com22999c62013-05-23 19:30:48 +000024 }
skia.committer@gmail.com3e2345a2013-05-24 07:01:26 +000025
reed@google.com22999c62013-05-23 19:30:48 +000026 SkISize onISize() { return SkISize::Make(1240, 390); }
skia.committer@gmail.com3e2345a2013-05-24 07:01:26 +000027
reed@google.com22999c62013-05-23 19:30:48 +000028 virtual void onDraw(SkCanvas* canvas) {
29 SkPath path;
30 path.moveTo(0, 0);
31 path.cubicTo(140, 150, 40, 10, 170, 150);
skia.committer@gmail.com3e2345a2013-05-24 07:01:26 +000032
reed@google.com22999c62013-05-23 19:30:48 +000033 SkPaint paint;
34 SkRect bounds = path.getBounds();
skia.committer@gmail.com3e2345a2013-05-24 07:01:26 +000035
reed@google.com0f8990c2013-05-23 19:47:05 +000036 for (SkScalar dy = -1; dy <= 1; dy += 1) {
reed@google.com22999c62013-05-23 19:30:48 +000037 canvas->save();
reed@google.com0f8990c2013-05-23 19:47:05 +000038 for (SkScalar dx = -1; dx <= 1; dx += 1) {
reed@google.com22999c62013-05-23 19:30:48 +000039 canvas->save();
40 canvas->clipRect(bounds);
41 canvas->translate(dx, dy);
42 canvas->drawPath(path, paint);
43 canvas->restore();
skia.committer@gmail.com3e2345a2013-05-24 07:01:26 +000044
reed@google.com22999c62013-05-23 19:30:48 +000045 canvas->translate(bounds.width(), 0);
46 }
47 canvas->restore();
48 canvas->translate(0, bounds.height());
49 }
50 }
skia.committer@gmail.com3e2345a2013-05-24 07:01:26 +000051
reed@google.com22999c62013-05-23 19:30:48 +000052private:
53 typedef skiagm::GM INHERITED;
54};
55
caryclark7d173402015-08-20 08:23:52 -070056
57class ClippedCubic2GM : public skiagm::GM {
58public:
59 ClippedCubic2GM() {}
60
61protected:
62
caryclark02833bf2015-08-20 10:53:13 -070063 SkString onShortName() override {
caryclark7d173402015-08-20 08:23:52 -070064 return SkString("clippedcubic2");
65 }
66
caryclark02833bf2015-08-20 10:53:13 -070067 SkISize onISize() override { return SkISize::Make(1240, 390); }
caryclark7d173402015-08-20 08:23:52 -070068
69 void onDraw(SkCanvas* canvas) override {
70 canvas->save();
caryclark05424f72015-08-20 10:35:43 -070071 canvas->translate(-2, 120);
caryclark7d173402015-08-20 08:23:52 -070072 drawOne(canvas, fPath, SkRect::MakeLTRB(0, 0, 80, 150));
73 canvas->translate(0, 170);
74 drawOne(canvas, fPath, SkRect::MakeLTRB(0, 0, 80, 100));
75 canvas->translate(0, 170);
76 drawOne(canvas, fPath, SkRect::MakeLTRB(0, 0, 30, 150));
77 canvas->translate(0, 170);
78 drawOne(canvas, fPath, SkRect::MakeLTRB(0, 0, 10, 150));
79 canvas->restore();
caryclark05424f72015-08-20 10:35:43 -070080 canvas->save();
81 canvas->translate(20, -2);
82 drawOne(canvas, fFlipped, SkRect::MakeLTRB(0, 0, 150, 80));
83 canvas->translate(170, 0);
84 drawOne(canvas, fFlipped, SkRect::MakeLTRB(0, 0, 100, 80));
85 canvas->translate(170, 0);
86 drawOne(canvas, fFlipped, SkRect::MakeLTRB(0, 0, 150, 30));
87 canvas->translate(170, 0);
88 drawOne(canvas, fFlipped, SkRect::MakeLTRB(0, 0, 150, 10));
89 canvas->restore();
caryclark7d173402015-08-20 08:23:52 -070090 }
91
92 void drawOne(SkCanvas* canvas, const SkPath& path, const SkRect& clip) {
93 SkPaint framePaint, fillPaint;
94 framePaint.setStyle(SkPaint::kStroke_Style);
95 canvas->drawRect(clip, framePaint);
96 canvas->drawPath(path, framePaint);
97 canvas->save();
98 canvas->clipRect(clip);
99 canvas->drawPath(path, fillPaint);
100 canvas->restore();
101 }
102
103 void onOnceBeforeDraw() override {
104 fPath.moveTo(69.7030518991886f, 0);
105 fPath.cubicTo( 69.7030518991886f, 21.831149999999997f,
106 58.08369508178456f, 43.66448333333333f, 34.8449814469765f, 65.5f);
107 fPath.cubicTo( 11.608591683531916f, 87.33115f, -0.010765133872116195f, 109.16448333333332f,
108 -0.013089005235602302f, 131);
109 fPath.close();
caryclark05424f72015-08-20 10:35:43 -0700110 fFlipped = fPath;
111 SkMatrix matrix;
112 matrix.reset();
113 matrix.setScaleX(0);
114 matrix.setScaleY(0);
115 matrix.setSkewX(1);
116 matrix.setSkewY(1);
117 fFlipped.transform(matrix);
caryclark7d173402015-08-20 08:23:52 -0700118 }
119
120 SkPath fPath;
caryclark05424f72015-08-20 10:35:43 -0700121 SkPath fFlipped;
caryclark7d173402015-08-20 08:23:52 -0700122private:
123 typedef skiagm::GM INHERITED;
124};
125
126
reed@google.com27b90fa2013-03-08 18:44:01 +0000127class CubicPathGM : public skiagm::GM {
schenney@chromium.org45cbfdd2011-12-20 21:48:14 +0000128public:
129 CubicPathGM() {}
130
131protected:
commit-bot@chromium.orga90c6802014-04-30 13:20:45 +0000132
schenney@chromium.org45cbfdd2011-12-20 21:48:14 +0000133 SkString onShortName() {
134 return SkString("cubicpath");
135 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000136
reed@google.com27b90fa2013-03-08 18:44:01 +0000137 SkISize onISize() { return SkISize::Make(1240, 390); }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000138
schenney@chromium.org45cbfdd2011-12-20 21:48:14 +0000139 void drawPath(SkPath& path,SkCanvas* canvas,SkColor color,
140 const SkRect& clip,SkPaint::Cap cap, SkPaint::Join join,
141 SkPaint::Style style, SkPath::FillType fill,
142 SkScalar strokeWidth) {
143 path.setFillType(fill);
144 SkPaint paint;
145 paint.setStrokeCap(cap);
146 paint.setStrokeWidth(strokeWidth);
147 paint.setStrokeJoin(join);
148 paint.setColor(color);
149 paint.setStyle(style);
150 canvas->save();
151 canvas->clipRect(clip);
152 canvas->drawPath(path, paint);
153 canvas->restore();
154 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000155
schenney@chromium.org45cbfdd2011-12-20 21:48:14 +0000156 virtual void onDraw(SkCanvas* canvas) {
157 struct FillAndName {
158 SkPath::FillType fFill;
159 const char* fName;
160 };
mtkleindbfd7ab2016-09-01 11:24:54 -0700161 constexpr FillAndName gFills[] = {
schenney@chromium.org45cbfdd2011-12-20 21:48:14 +0000162 {SkPath::kWinding_FillType, "Winding"},
163 {SkPath::kEvenOdd_FillType, "Even / Odd"},
164 {SkPath::kInverseWinding_FillType, "Inverse Winding"},
165 {SkPath::kInverseEvenOdd_FillType, "Inverse Even / Odd"},
166 };
167 struct StyleAndName {
168 SkPaint::Style fStyle;
169 const char* fName;
170 };
mtkleindbfd7ab2016-09-01 11:24:54 -0700171 constexpr StyleAndName gStyles[] = {
schenney@chromium.org45cbfdd2011-12-20 21:48:14 +0000172 {SkPaint::kFill_Style, "Fill"},
173 {SkPaint::kStroke_Style, "Stroke"},
174 {SkPaint::kStrokeAndFill_Style, "Stroke And Fill"},
175 };
176 struct CapAndName {
177 SkPaint::Cap fCap;
178 SkPaint::Join fJoin;
179 const char* fName;
180 };
mtkleindbfd7ab2016-09-01 11:24:54 -0700181 constexpr CapAndName gCaps[] = {
schenney@chromium.org45cbfdd2011-12-20 21:48:14 +0000182 {SkPaint::kButt_Cap, SkPaint::kBevel_Join, "Butt"},
183 {SkPaint::kRound_Cap, SkPaint::kRound_Join, "Round"},
184 {SkPaint::kSquare_Cap, SkPaint::kBevel_Join, "Square"}
185 };
186 struct PathAndName {
187 SkPath fPath;
188 const char* fName;
189 };
190 PathAndName path;
191 path.fPath.moveTo(25*SK_Scalar1, 10*SK_Scalar1);
192 path.fPath.cubicTo(40*SK_Scalar1, 20*SK_Scalar1,
193 60*SK_Scalar1, 20*SK_Scalar1,
194 75*SK_Scalar1, 10*SK_Scalar1);
195 path.fName = "moveTo-cubic";
196
197 SkPaint titlePaint;
198 titlePaint.setColor(SK_ColorBLACK);
199 titlePaint.setAntiAlias(true);
caryclark1818acb2015-07-24 12:09:25 -0700200 sk_tool_utils::set_portable_typeface(&titlePaint);
schenney@chromium.org45cbfdd2011-12-20 21:48:14 +0000201 titlePaint.setTextSize(15 * SK_Scalar1);
202 const char title[] = "Cubic Drawn Into Rectangle Clips With "
203 "Indicated Style, Fill and Linecaps, with stroke width 10";
204 canvas->drawText(title, strlen(title),
205 20 * SK_Scalar1,
206 20 * SK_Scalar1,
207 titlePaint);
208
scroggof9d61012014-12-15 12:54:51 -0800209 SkRandom rand;
schenney@chromium.org45cbfdd2011-12-20 21:48:14 +0000210 SkRect rect = SkRect::MakeWH(100*SK_Scalar1, 30*SK_Scalar1);
211 canvas->save();
212 canvas->translate(10 * SK_Scalar1, 30 * SK_Scalar1);
213 canvas->save();
214 for (size_t cap = 0; cap < SK_ARRAY_COUNT(gCaps); ++cap) {
215 if (0 < cap) {
216 canvas->translate((rect.width() + 40 * SK_Scalar1) * SK_ARRAY_COUNT(gStyles), 0);
217 }
218 canvas->save();
219 for (size_t fill = 0; fill < SK_ARRAY_COUNT(gFills); ++fill) {
220 if (0 < fill) {
221 canvas->translate(0, rect.height() + 40 * SK_Scalar1);
222 }
223 canvas->save();
224 for (size_t style = 0; style < SK_ARRAY_COUNT(gStyles); ++style) {
225 if (0 < style) {
226 canvas->translate(rect.width() + 40 * SK_Scalar1, 0);
227 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000228
schenney@chromium.org45cbfdd2011-12-20 21:48:14 +0000229 SkColor color = 0xff007000;
230 this->drawPath(path.fPath, canvas, color, rect,
231 gCaps[cap].fCap, gCaps[cap].fJoin, gStyles[style].fStyle,
232 gFills[fill].fFill, SK_Scalar1*10);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000233
schenney@chromium.org45cbfdd2011-12-20 21:48:14 +0000234 SkPaint rectPaint;
235 rectPaint.setColor(SK_ColorBLACK);
236 rectPaint.setStyle(SkPaint::kStroke_Style);
237 rectPaint.setStrokeWidth(-1);
238 rectPaint.setAntiAlias(true);
239 canvas->drawRect(rect, rectPaint);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000240
schenney@chromium.org45cbfdd2011-12-20 21:48:14 +0000241 SkPaint labelPaint;
242 labelPaint.setColor(color);
243 labelPaint.setAntiAlias(true);
caryclark1818acb2015-07-24 12:09:25 -0700244 sk_tool_utils::set_portable_typeface(&labelPaint);
schenney@chromium.org45cbfdd2011-12-20 21:48:14 +0000245 labelPaint.setTextSize(10 * SK_Scalar1);
246 canvas->drawText(gStyles[style].fName,
247 strlen(gStyles[style].fName),
248 0, rect.height() + 12 * SK_Scalar1,
249 labelPaint);
250 canvas->drawText(gFills[fill].fName,
251 strlen(gFills[fill].fName),
252 0, rect.height() + 24 * SK_Scalar1,
253 labelPaint);
254 canvas->drawText(gCaps[cap].fName,
255 strlen(gCaps[cap].fName),
256 0, rect.height() + 36 * SK_Scalar1,
257 labelPaint);
258 }
259 canvas->restore();
260 }
261 canvas->restore();
262 }
263 canvas->restore();
264 canvas->restore();
265 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000266
schenney@chromium.org45cbfdd2011-12-20 21:48:14 +0000267private:
reed@google.com27b90fa2013-03-08 18:44:01 +0000268 typedef skiagm::GM INHERITED;
schenney@chromium.org45cbfdd2011-12-20 21:48:14 +0000269};
270
reed@google.com27b90fa2013-03-08 18:44:01 +0000271class CubicClosePathGM : public skiagm::GM {
schenney@chromium.org45cbfdd2011-12-20 21:48:14 +0000272public:
273 CubicClosePathGM() {}
274
275protected:
commit-bot@chromium.orga90c6802014-04-30 13:20:45 +0000276
schenney@chromium.org45cbfdd2011-12-20 21:48:14 +0000277 SkString onShortName() {
278 return SkString("cubicclosepath");
279 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000280
reed@google.com27b90fa2013-03-08 18:44:01 +0000281 SkISize onISize() { return SkISize::Make(1240, 390); }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000282
schenney@chromium.org45cbfdd2011-12-20 21:48:14 +0000283 void drawPath(SkPath& path,SkCanvas* canvas,SkColor color,
284 const SkRect& clip,SkPaint::Cap cap, SkPaint::Join join,
285 SkPaint::Style style, SkPath::FillType fill,
286 SkScalar strokeWidth) {
287 path.setFillType(fill);
288 SkPaint paint;
289 paint.setStrokeCap(cap);
290 paint.setStrokeWidth(strokeWidth);
291 paint.setStrokeJoin(join);
292 paint.setColor(color);
293 paint.setStyle(style);
294 canvas->save();
295 canvas->clipRect(clip);
296 canvas->drawPath(path, paint);
297 canvas->restore();
298 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000299
schenney@chromium.org45cbfdd2011-12-20 21:48:14 +0000300 virtual void onDraw(SkCanvas* canvas) {
301 struct FillAndName {
302 SkPath::FillType fFill;
303 const char* fName;
304 };
mtkleindbfd7ab2016-09-01 11:24:54 -0700305 constexpr FillAndName gFills[] = {
schenney@chromium.org45cbfdd2011-12-20 21:48:14 +0000306 {SkPath::kWinding_FillType, "Winding"},
307 {SkPath::kEvenOdd_FillType, "Even / Odd"},
308 {SkPath::kInverseWinding_FillType, "Inverse Winding"},
309 {SkPath::kInverseEvenOdd_FillType, "Inverse Even / Odd"},
310 };
311 struct StyleAndName {
312 SkPaint::Style fStyle;
313 const char* fName;
314 };
mtkleindbfd7ab2016-09-01 11:24:54 -0700315 constexpr StyleAndName gStyles[] = {
schenney@chromium.org45cbfdd2011-12-20 21:48:14 +0000316 {SkPaint::kFill_Style, "Fill"},
317 {SkPaint::kStroke_Style, "Stroke"},
318 {SkPaint::kStrokeAndFill_Style, "Stroke And Fill"},
319 };
320 struct CapAndName {
321 SkPaint::Cap fCap;
322 SkPaint::Join fJoin;
323 const char* fName;
324 };
mtkleindbfd7ab2016-09-01 11:24:54 -0700325 constexpr CapAndName gCaps[] = {
schenney@chromium.org45cbfdd2011-12-20 21:48:14 +0000326 {SkPaint::kButt_Cap, SkPaint::kBevel_Join, "Butt"},
327 {SkPaint::kRound_Cap, SkPaint::kRound_Join, "Round"},
328 {SkPaint::kSquare_Cap, SkPaint::kBevel_Join, "Square"}
329 };
330 struct PathAndName {
331 SkPath fPath;
332 const char* fName;
333 };
334 PathAndName path;
335 path.fPath.moveTo(25*SK_Scalar1, 10*SK_Scalar1);
336 path.fPath.cubicTo(40*SK_Scalar1, 20*SK_Scalar1,
337 60*SK_Scalar1, 20*SK_Scalar1,
338 75*SK_Scalar1, 10*SK_Scalar1);
339 path.fPath.close();
340 path.fName = "moveTo-cubic-close";
341
342 SkPaint titlePaint;
343 titlePaint.setColor(SK_ColorBLACK);
344 titlePaint.setAntiAlias(true);
caryclark1818acb2015-07-24 12:09:25 -0700345 sk_tool_utils::set_portable_typeface(&titlePaint);
schenney@chromium.org45cbfdd2011-12-20 21:48:14 +0000346 titlePaint.setTextSize(15 * SK_Scalar1);
347 const char title[] = "Cubic Closed Drawn Into Rectangle Clips With "
348 "Indicated Style, Fill and Linecaps, with stroke width 10";
349 canvas->drawText(title, strlen(title),
350 20 * SK_Scalar1,
351 20 * SK_Scalar1,
352 titlePaint);
353
scroggof9d61012014-12-15 12:54:51 -0800354 SkRandom rand;
schenney@chromium.org45cbfdd2011-12-20 21:48:14 +0000355 SkRect rect = SkRect::MakeWH(100*SK_Scalar1, 30*SK_Scalar1);
356 canvas->save();
357 canvas->translate(10 * SK_Scalar1, 30 * SK_Scalar1);
358 canvas->save();
359 for (size_t cap = 0; cap < SK_ARRAY_COUNT(gCaps); ++cap) {
360 if (0 < cap) {
361 canvas->translate((rect.width() + 40 * SK_Scalar1) * SK_ARRAY_COUNT(gStyles), 0);
362 }
363 canvas->save();
364 for (size_t fill = 0; fill < SK_ARRAY_COUNT(gFills); ++fill) {
365 if (0 < fill) {
366 canvas->translate(0, rect.height() + 40 * SK_Scalar1);
367 }
368 canvas->save();
369 for (size_t style = 0; style < SK_ARRAY_COUNT(gStyles); ++style) {
370 if (0 < style) {
371 canvas->translate(rect.width() + 40 * SK_Scalar1, 0);
372 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000373
schenney@chromium.org45cbfdd2011-12-20 21:48:14 +0000374 SkColor color = 0xff007000;
375 this->drawPath(path.fPath, canvas, color, rect,
376 gCaps[cap].fCap, gCaps[cap].fJoin, gStyles[style].fStyle,
377 gFills[fill].fFill, SK_Scalar1*10);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000378
schenney@chromium.org45cbfdd2011-12-20 21:48:14 +0000379 SkPaint rectPaint;
380 rectPaint.setColor(SK_ColorBLACK);
381 rectPaint.setStyle(SkPaint::kStroke_Style);
382 rectPaint.setStrokeWidth(-1);
383 rectPaint.setAntiAlias(true);
384 canvas->drawRect(rect, rectPaint);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000385
schenney@chromium.org45cbfdd2011-12-20 21:48:14 +0000386 SkPaint labelPaint;
387 labelPaint.setColor(color);
388 labelPaint.setAntiAlias(true);
caryclark1818acb2015-07-24 12:09:25 -0700389 sk_tool_utils::set_portable_typeface(&labelPaint);
schenney@chromium.org45cbfdd2011-12-20 21:48:14 +0000390 labelPaint.setTextSize(10 * SK_Scalar1);
391 canvas->drawText(gStyles[style].fName,
392 strlen(gStyles[style].fName),
393 0, rect.height() + 12 * SK_Scalar1,
394 labelPaint);
395 canvas->drawText(gFills[fill].fName,
396 strlen(gFills[fill].fName),
397 0, rect.height() + 24 * SK_Scalar1,
398 labelPaint);
399 canvas->drawText(gCaps[cap].fName,
400 strlen(gCaps[cap].fName),
401 0, rect.height() + 36 * SK_Scalar1,
402 labelPaint);
schenney@chromium.org4da06ab2011-12-20 15:14:18 +0000403 }
404 canvas->restore();
405 }
406 canvas->restore();
407 }
408 canvas->restore();
409 canvas->restore();
410 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000411
schenney@chromium.org4da06ab2011-12-20 15:14:18 +0000412private:
reed@google.com27b90fa2013-03-08 18:44:01 +0000413 typedef skiagm::GM INHERITED;
schenney@chromium.org4da06ab2011-12-20 15:14:18 +0000414};
415
caryclark4693a172016-04-06 08:54:06 -0700416DEF_SIMPLE_GM(bug5099, canvas, 50, 50) {
417 SkPaint p;
418 p.setColor(SK_ColorRED);
419 p.setAntiAlias(true);
420 p.setStyle(SkPaint::kStroke_Style);
421 p.setStrokeWidth(10);
422
423 SkPath path;
424 path.moveTo(6, 27);
425 path.cubicTo(31.5f, 1.5f, 3.5f, 4.5f, 29, 29);
426 canvas->drawPath(path, p);
427}
428
schenney@chromium.org4da06ab2011-12-20 15:14:18 +0000429//////////////////////////////////////////////////////////////////////////////
430
reed@google.com27b90fa2013-03-08 18:44:01 +0000431DEF_GM( return new CubicPathGM; )
432DEF_GM( return new CubicClosePathGM; )
reed@google.com22999c62013-05-23 19:30:48 +0000433DEF_GM( return new ClippedCubicGM; )
caryclark7d173402015-08-20 08:23:52 -0700434DEF_GM( return new ClippedCubic2GM; )