blob: 0ebca10030d5ac09cf89eda3e0411ad9c9afecc1 [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 */
7#include "gm.h"
Mike Klein33d20552017-03-22 13:47:51 -04008#include "sk_tool_utils.h"
schenney@chromium.org4da06ab2011-12-20 15:14:18 +00009#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
14namespace skiagm {
15
16class DegenerateSegmentsGM : public GM {
17public:
18 DegenerateSegmentsGM() {}
19
20protected:
21 struct PathAndName {
22 SkPath fPath;
23 const char* fName1;
24 const char* fName2;
25 };
26
27 SkString onShortName() {
28 return SkString("degeneratesegments");
29 }
rmistry@google.comd6176b02012-08-23 18:14:13 +000030
tfarinaf5393182014-06-09 23:59:03 -070031 SkISize onISize() { return SkISize::Make(896, 930); }
schenney@chromium.org4da06ab2011-12-20 15:14:18 +000032
33 typedef SkPoint (*AddSegmentFunc)(SkPath&, SkPoint&);
rmistry@google.comd6176b02012-08-23 18:14:13 +000034
schenney@chromium.org4da06ab2011-12-20 15:14:18 +000035 // We need to use explicit commands here, instead of addPath, because we
schenney@chromium.org6630d8d2012-01-04 21:05:51 +000036 // do not want the moveTo that is added at the beginning of a path to
37 // appear in the appended path.
schenney@chromium.org4da06ab2011-12-20 15:14:18 +000038 static SkPoint AddMove(SkPath& path, SkPoint& startPt) {
39 SkPoint moveToPt = startPt + SkPoint::Make(0, 10*SK_Scalar1);
40 path.moveTo(moveToPt);
41 return moveToPt;
42 }
43
44 static SkPoint AddMoveClose(SkPath& path, SkPoint& startPt) {
45 SkPoint moveToPt = startPt + SkPoint::Make(0, 10*SK_Scalar1);
46 path.moveTo(moveToPt);
47 path.close();
48 return moveToPt;
49 }
50
51 static SkPoint AddDegenLine(SkPath& path, SkPoint& startPt) {
52 path.lineTo(startPt);
53 return startPt;
54 }
55
56 static SkPoint AddMoveDegenLine(SkPath& path, SkPoint& startPt) {
57 SkPoint moveToPt = startPt + SkPoint::Make(0, 10*SK_Scalar1);
58 path.moveTo(moveToPt);
59 path.lineTo(moveToPt);
60 return moveToPt;
61 }
62
63 static SkPoint AddMoveDegenLineClose(SkPath& path, SkPoint& startPt) {
64 SkPoint moveToPt = startPt + SkPoint::Make(0, 10*SK_Scalar1);
65 path.moveTo(moveToPt);
66 path.lineTo(moveToPt);
67 path.close();
68 return moveToPt;
69 }
70
71 static SkPoint AddDegenQuad(SkPath& path, SkPoint& startPt) {
72 path.quadTo(startPt, startPt);
73 return startPt;
74 }
75
76 static SkPoint AddMoveDegenQuad(SkPath& path, SkPoint& startPt) {
77 SkPoint moveToPt = startPt + SkPoint::Make(0, 10*SK_Scalar1);
78 path.moveTo(moveToPt);
79 path.quadTo(moveToPt, moveToPt);
80 return moveToPt;
81 }
82
83 static SkPoint AddMoveDegenQuadClose(SkPath& path, SkPoint& startPt) {
84 SkPoint moveToPt = startPt + SkPoint::Make(0, 10*SK_Scalar1);
85 path.moveTo(moveToPt);
86 path.quadTo(moveToPt, moveToPt);
87 path.close();
88 return moveToPt;
89 }
90
91 static SkPoint AddDegenCubic(SkPath& path, SkPoint& startPt) {
92 path.cubicTo(startPt, startPt, startPt);
93 return startPt;
94 }
95
96 static SkPoint AddMoveDegenCubic(SkPath& path, SkPoint& startPt) {
97 SkPoint moveToPt = startPt + SkPoint::Make(0, 10*SK_Scalar1);
98 path.moveTo(moveToPt);
99 path.cubicTo(moveToPt, moveToPt, moveToPt);
100 return moveToPt;
101 }
102
103 static SkPoint AddMoveDegenCubicClose(SkPath& path, SkPoint& startPt) {
104 SkPoint moveToPt = startPt + SkPoint::Make(0, 10*SK_Scalar1);
105 path.moveTo(moveToPt);
106 path.cubicTo(moveToPt, moveToPt, moveToPt);
107 path.close();
108 return moveToPt;
109 }
110
111 static SkPoint AddClose(SkPath& path, SkPoint& startPt) {
112 path.close();
113 return startPt;
114 }
115
116 static SkPoint AddLine(SkPath& path, SkPoint& startPt) {
117 SkPoint endPt = startPt + SkPoint::Make(40*SK_Scalar1, 0);
118 path.lineTo(endPt);
119 return endPt;
120 }
121
122 static SkPoint AddMoveLine(SkPath& path, SkPoint& startPt) {
123 SkPoint moveToPt = startPt + SkPoint::Make(0, 10*SK_Scalar1);
124 SkPoint endPt = moveToPt + SkPoint::Make(40*SK_Scalar1, 0);
125 path.moveTo(moveToPt);
126 path.lineTo(endPt);
127 return endPt;
128 }
129
130 static SkPoint AddMoveLineClose(SkPath& path, SkPoint& startPt) {
131 SkPoint moveToPt = startPt + SkPoint::Make(0, 10*SK_Scalar1);
132 SkPoint endPt = moveToPt + SkPoint::Make(40*SK_Scalar1, 0);
133 path.moveTo(moveToPt);
134 path.lineTo(endPt);
135 path.close();
136 return endPt;
137 }
138
139 static SkPoint AddQuad(SkPath& path, SkPoint& startPt) {
140 SkPoint midPt = startPt + SkPoint::Make(20*SK_Scalar1, 5*SK_Scalar1);
141 SkPoint endPt = startPt + SkPoint::Make(40*SK_Scalar1, 0);
142 path.quadTo(midPt, endPt);
143 return endPt;
144 }
145
146 static SkPoint AddMoveQuad(SkPath& path, SkPoint& startPt) {
147 SkPoint moveToPt = startPt + SkPoint::Make(0, 10*SK_Scalar1);
148 SkPoint midPt = moveToPt + SkPoint::Make(20*SK_Scalar1, 5*SK_Scalar1);
149 SkPoint endPt = moveToPt + SkPoint::Make(40*SK_Scalar1, 0);
150 path.moveTo(moveToPt);
151 path.quadTo(midPt, endPt);
152 return endPt;
153 }
154
155 static SkPoint AddMoveQuadClose(SkPath& path, SkPoint& startPt) {
156 SkPoint moveToPt = startPt + SkPoint::Make(0, 10*SK_Scalar1);
157 SkPoint midPt = moveToPt + SkPoint::Make(20*SK_Scalar1, 5*SK_Scalar1);
158 SkPoint endPt = moveToPt + SkPoint::Make(40*SK_Scalar1, 0);
159 path.moveTo(moveToPt);
160 path.quadTo(midPt, endPt);
161 path.close();
162 return endPt;
163 }
164
165 static SkPoint AddCubic(SkPath& path, SkPoint& startPt) {
166 SkPoint t1Pt = startPt + SkPoint::Make(15*SK_Scalar1, 5*SK_Scalar1);
167 SkPoint t2Pt = startPt + SkPoint::Make(25*SK_Scalar1, 5*SK_Scalar1);
168 SkPoint endPt = startPt + SkPoint::Make(40*SK_Scalar1, 0);
169 path.cubicTo(t1Pt, t2Pt, endPt);
170 return endPt;
171 }
172
173 static SkPoint AddMoveCubic(SkPath& path, SkPoint& startPt) {
174 SkPoint moveToPt = startPt + SkPoint::Make(0, 10*SK_Scalar1);
175 SkPoint t1Pt = moveToPt + SkPoint::Make(15*SK_Scalar1, 5*SK_Scalar1);
176 SkPoint t2Pt = moveToPt + SkPoint::Make(25*SK_Scalar1, 5*SK_Scalar1);
177 SkPoint endPt = moveToPt + SkPoint::Make(40*SK_Scalar1, 0);
178 path.moveTo(moveToPt);
179 path.cubicTo(t1Pt, t2Pt, endPt);
180 return endPt;
181 }
182
183 static SkPoint AddMoveCubicClose(SkPath& path, SkPoint& startPt) {
184 SkPoint moveToPt = startPt + SkPoint::Make(0, 10*SK_Scalar1);
185 SkPoint t1Pt = moveToPt + SkPoint::Make(15*SK_Scalar1, 5*SK_Scalar1);
186 SkPoint t2Pt = moveToPt + SkPoint::Make(25*SK_Scalar1, 5*SK_Scalar1);
187 SkPoint endPt = moveToPt + SkPoint::Make(40*SK_Scalar1, 0);
188 path.moveTo(moveToPt);
189 path.cubicTo(t1Pt, t2Pt, endPt);
190 path.close();
191 return endPt;
192 }
193
194 void drawPath(SkPath& path, SkCanvas* canvas, SkColor color,
schenney@chromium.org45cbfdd2011-12-20 21:48:14 +0000195 const SkRect& clip, SkPaint::Cap cap, SkPaint::Join join,
schenney@chromium.org4da06ab2011-12-20 15:14:18 +0000196 SkPaint::Style style, SkPath::FillType fill,
197 SkScalar strokeWidth) {
198 path.setFillType(fill);
199 SkPaint paint;
200 paint.setStrokeCap(cap);
201 paint.setStrokeWidth(strokeWidth);
schenney@chromium.org45cbfdd2011-12-20 21:48:14 +0000202 paint.setStrokeJoin(join);
schenney@chromium.org4da06ab2011-12-20 15:14:18 +0000203 paint.setColor(color);
204 paint.setStyle(style);
205 canvas->save();
206 canvas->clipRect(clip);
207 canvas->drawPath(path, paint);
208 canvas->restore();
209 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000210
schenney@chromium.org4da06ab2011-12-20 15:14:18 +0000211 virtual void onDraw(SkCanvas* canvas) {
mtkleindbfd7ab2016-09-01 11:24:54 -0700212 constexpr AddSegmentFunc gSegmentFunctions[] = {
schenney@chromium.org6630d8d2012-01-04 21:05:51 +0000213 AddMove,
214 AddMoveClose,
215 AddDegenLine,
216 AddMoveDegenLine,
217 AddMoveDegenLineClose,
218 AddDegenQuad,
219 AddMoveDegenQuad,
220 AddMoveDegenQuadClose,
221 AddDegenCubic,
222 AddMoveDegenCubic,
223 AddMoveDegenCubicClose,
224 AddClose,
225 AddLine,
226 AddMoveLine,
227 AddMoveLineClose,
228 AddQuad,
229 AddMoveQuad,
230 AddMoveQuadClose,
231 AddCubic,
232 AddMoveCubic,
233 AddMoveCubicClose
234 };
mtkleindbfd7ab2016-09-01 11:24:54 -0700235 const char* gSegmentNames[] = {
schenney@chromium.org6630d8d2012-01-04 21:05:51 +0000236 "Move",
237 "MoveClose",
238 "DegenLine",
239 "MoveDegenLine",
240 "MoveDegenLineClose",
241 "DegenQuad",
242 "MoveDegenQuad",
243 "MoveDegenQuadClose",
244 "DegenCubic",
245 "MoveDegenCubic",
246 "MoveDegenCubicClose",
247 "Close",
248 "Line",
249 "MoveLine",
250 "MoveLineClose",
251 "Quad",
252 "MoveQuad",
253 "MoveQuadClose",
254 "Cubic",
255 "MoveCubic",
256 "MoveCubicClose"
257 };
schenney@chromium.org4da06ab2011-12-20 15:14:18 +0000258
259 struct FillAndName {
260 SkPath::FillType fFill;
261 const char* fName;
262 };
mtkleindbfd7ab2016-09-01 11:24:54 -0700263 constexpr FillAndName gFills[] = {
schenney@chromium.org4da06ab2011-12-20 15:14:18 +0000264 {SkPath::kWinding_FillType, "Winding"},
265 {SkPath::kEvenOdd_FillType, "Even / Odd"},
266 {SkPath::kInverseWinding_FillType, "Inverse Winding"},
267 {SkPath::kInverseEvenOdd_FillType, "Inverse Even / Odd"}
268 };
269 struct StyleAndName {
270 SkPaint::Style fStyle;
271 const char* fName;
272 };
mtkleindbfd7ab2016-09-01 11:24:54 -0700273 constexpr StyleAndName gStyles[] = {
schenney@chromium.org4da06ab2011-12-20 15:14:18 +0000274 {SkPaint::kFill_Style, "Fill"},
275 {SkPaint::kStroke_Style, "Stroke 10"},
276 {SkPaint::kStrokeAndFill_Style, "Stroke 10 And Fill"}
277 };
278 struct CapAndName {
schenney@chromium.org45cbfdd2011-12-20 21:48:14 +0000279 SkPaint::Cap fCap;
280 SkPaint::Join fJoin;
281 const char* fName;
schenney@chromium.org4da06ab2011-12-20 15:14:18 +0000282 };
mtkleindbfd7ab2016-09-01 11:24:54 -0700283 constexpr CapAndName gCaps[] = {
schenney@chromium.org45cbfdd2011-12-20 21:48:14 +0000284 {SkPaint::kButt_Cap, SkPaint::kBevel_Join, "Butt"},
285 {SkPaint::kRound_Cap, SkPaint::kRound_Join, "Round"},
286 {SkPaint::kSquare_Cap, SkPaint::kBevel_Join, "Square"}
schenney@chromium.org4da06ab2011-12-20 15:14:18 +0000287 };
288
289 SkPaint titlePaint;
290 titlePaint.setColor(SK_ColorBLACK);
291 titlePaint.setAntiAlias(true);
Mike Reed1af9b482019-01-07 11:01:57 -0500292 SkFont font(sk_tool_utils::create_portable_typeface(), 15);
schenney@chromium.org4da06ab2011-12-20 15:14:18 +0000293 const char title[] = "Random Paths Drawn Into Rectangle Clips With "
294 "Indicated Style, Fill and Linecaps, "
295 "with Stroke width 6";
Mike Reed1af9b482019-01-07 11:01:57 -0500296 canvas->drawString(title, 20, 20, font, titlePaint);
schenney@chromium.org4da06ab2011-12-20 15:14:18 +0000297
scroggof9d61012014-12-15 12:54:51 -0800298 SkRandom rand;
schenney@chromium.org4da06ab2011-12-20 15:14:18 +0000299 SkRect rect = SkRect::MakeWH(220*SK_Scalar1, 50*SK_Scalar1);
300 canvas->save();
301 canvas->translate(2*SK_Scalar1, 30 * SK_Scalar1); // The title
302 canvas->save();
303 unsigned numSegments = SK_ARRAY_COUNT(gSegmentFunctions);
304 unsigned numCaps = SK_ARRAY_COUNT(gCaps);
305 unsigned numStyles = SK_ARRAY_COUNT(gStyles);
306 unsigned numFills = SK_ARRAY_COUNT(gFills);
schenney@chromium.org45cbfdd2011-12-20 21:48:14 +0000307 for (size_t row = 0; row < 6; ++row) {
schenney@chromium.org4da06ab2011-12-20 15:14:18 +0000308 if (0 < row) {
309 canvas->translate(0, rect.height() + 100*SK_Scalar1);
310 }
311 canvas->save();
schenney@chromium.org45cbfdd2011-12-20 21:48:14 +0000312 for (size_t column = 0; column < 4; ++column) {
schenney@chromium.org4da06ab2011-12-20 15:14:18 +0000313 if (0 < column) {
314 canvas->translate(rect.width() + 4*SK_Scalar1, 0);
315 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000316
caryclarkdfcb7ab2015-07-17 09:39:16 -0700317 SkColor color = sk_tool_utils::color_to_565(0xff007000);
schenney@chromium.org4da06ab2011-12-20 15:14:18 +0000318 StyleAndName style = gStyles[(rand.nextU() >> 16) % numStyles];
319 CapAndName cap = gCaps[(rand.nextU() >> 16) % numCaps];
320 FillAndName fill = gFills[(rand.nextU() >> 16) % numFills];
321 SkPath path;
322 unsigned s1 = (rand.nextU() >> 16) % numSegments;
323 unsigned s2 = (rand.nextU() >> 16) % numSegments;
324 unsigned s3 = (rand.nextU() >> 16) % numSegments;
325 unsigned s4 = (rand.nextU() >> 16) % numSegments;
326 unsigned s5 = (rand.nextU() >> 16) % numSegments;
327 SkPoint pt = SkPoint::Make(10*SK_Scalar1, 0);
328 pt = gSegmentFunctions[s1](path, pt);
329 pt = gSegmentFunctions[s2](path, pt);
330 pt = gSegmentFunctions[s3](path, pt);
331 pt = gSegmentFunctions[s4](path, pt);
332 pt = gSegmentFunctions[s5](path, pt);
333
334 this->drawPath(path, canvas, color, rect,
schenney@chromium.org45cbfdd2011-12-20 21:48:14 +0000335 cap.fCap, cap.fJoin, style.fStyle,
schenney@chromium.org4da06ab2011-12-20 15:14:18 +0000336 fill.fFill, SK_Scalar1*6);
337
338 SkPaint rectPaint;
339 rectPaint.setColor(SK_ColorBLACK);
340 rectPaint.setStyle(SkPaint::kStroke_Style);
341 rectPaint.setStrokeWidth(-1);
342 rectPaint.setAntiAlias(true);
343 canvas->drawRect(rect, rectPaint);
344
345 SkPaint labelPaint;
346 labelPaint.setColor(color);
347 labelPaint.setAntiAlias(true);
Mike Reed1af9b482019-01-07 11:01:57 -0500348 font.setSize(10);
349 canvas->drawString(style.fName, 0, rect.height() + 12, font, labelPaint);
350 canvas->drawString(fill.fName, 0, rect.height() + 24, font, labelPaint);
351 canvas->drawString(cap.fName, 0, rect.height() + 36, font, labelPaint);
352 canvas->drawString(gSegmentNames[s1], 0, rect.height() + 48, font, labelPaint);
353 canvas->drawString(gSegmentNames[s2], 0, rect.height() + 60, font, labelPaint);
354 canvas->drawString(gSegmentNames[s3], 0, rect.height() + 72, font, labelPaint);
355 canvas->drawString(gSegmentNames[s4], 0, rect.height() + 84, font, labelPaint);
356 canvas->drawString(gSegmentNames[s5], 0, rect.height() + 96, font, labelPaint);
schenney@chromium.org4da06ab2011-12-20 15:14:18 +0000357 }
358 canvas->restore();
359 }
360 canvas->restore();
361 canvas->restore();
362 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000363
schenney@chromium.org4da06ab2011-12-20 15:14:18 +0000364private:
365 typedef GM INHERITED;
366};
367
368//////////////////////////////////////////////////////////////////////////////
369
Hal Canarye964c182019-01-23 10:22:01 -0500370DEF_GM( return new DegenerateSegmentsGM; )
schenney@chromium.org4da06ab2011-12-20 15:14:18 +0000371
372}