blob: 022f1b1920bc989bbaec925f9016969d7425131a [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"
8#include "SkCanvas.h"
9#include "SkPaint.h"
10#include "SkRandom.h"
11
12namespace skiagm {
13
14class DegenerateSegmentsGM : public GM {
15public:
16 DegenerateSegmentsGM() {}
17
18protected:
19 struct PathAndName {
20 SkPath fPath;
21 const char* fName1;
22 const char* fName2;
23 };
24
commit-bot@chromium.orga90c6802014-04-30 13:20:45 +000025 virtual uint32_t onGetFlags() const SK_OVERRIDE {
26 return kSkipTiled_Flag;
27 }
28
schenney@chromium.org4da06ab2011-12-20 15:14:18 +000029 SkString onShortName() {
30 return SkString("degeneratesegments");
31 }
rmistry@google.comd6176b02012-08-23 18:14:13 +000032
schenney@chromium.org45cbfdd2011-12-20 21:48:14 +000033 SkISize onISize() { return make_isize(896, 930); }
schenney@chromium.org4da06ab2011-12-20 15:14:18 +000034
35 typedef SkPoint (*AddSegmentFunc)(SkPath&, SkPoint&);
rmistry@google.comd6176b02012-08-23 18:14:13 +000036
schenney@chromium.org4da06ab2011-12-20 15:14:18 +000037 // We need to use explicit commands here, instead of addPath, because we
schenney@chromium.org6630d8d2012-01-04 21:05:51 +000038 // do not want the moveTo that is added at the beginning of a path to
39 // appear in the appended path.
schenney@chromium.org4da06ab2011-12-20 15:14:18 +000040 static SkPoint AddMove(SkPath& path, SkPoint& startPt) {
41 SkPoint moveToPt = startPt + SkPoint::Make(0, 10*SK_Scalar1);
42 path.moveTo(moveToPt);
43 return moveToPt;
44 }
45
46 static SkPoint AddMoveClose(SkPath& path, SkPoint& startPt) {
47 SkPoint moveToPt = startPt + SkPoint::Make(0, 10*SK_Scalar1);
48 path.moveTo(moveToPt);
49 path.close();
50 return moveToPt;
51 }
52
53 static SkPoint AddDegenLine(SkPath& path, SkPoint& startPt) {
54 path.lineTo(startPt);
55 return startPt;
56 }
57
58 static SkPoint AddMoveDegenLine(SkPath& path, SkPoint& startPt) {
59 SkPoint moveToPt = startPt + SkPoint::Make(0, 10*SK_Scalar1);
60 path.moveTo(moveToPt);
61 path.lineTo(moveToPt);
62 return moveToPt;
63 }
64
65 static SkPoint AddMoveDegenLineClose(SkPath& path, SkPoint& startPt) {
66 SkPoint moveToPt = startPt + SkPoint::Make(0, 10*SK_Scalar1);
67 path.moveTo(moveToPt);
68 path.lineTo(moveToPt);
69 path.close();
70 return moveToPt;
71 }
72
73 static SkPoint AddDegenQuad(SkPath& path, SkPoint& startPt) {
74 path.quadTo(startPt, startPt);
75 return startPt;
76 }
77
78 static SkPoint AddMoveDegenQuad(SkPath& path, SkPoint& startPt) {
79 SkPoint moveToPt = startPt + SkPoint::Make(0, 10*SK_Scalar1);
80 path.moveTo(moveToPt);
81 path.quadTo(moveToPt, moveToPt);
82 return moveToPt;
83 }
84
85 static SkPoint AddMoveDegenQuadClose(SkPath& path, SkPoint& startPt) {
86 SkPoint moveToPt = startPt + SkPoint::Make(0, 10*SK_Scalar1);
87 path.moveTo(moveToPt);
88 path.quadTo(moveToPt, moveToPt);
89 path.close();
90 return moveToPt;
91 }
92
93 static SkPoint AddDegenCubic(SkPath& path, SkPoint& startPt) {
94 path.cubicTo(startPt, startPt, startPt);
95 return startPt;
96 }
97
98 static SkPoint AddMoveDegenCubic(SkPath& path, SkPoint& startPt) {
99 SkPoint moveToPt = startPt + SkPoint::Make(0, 10*SK_Scalar1);
100 path.moveTo(moveToPt);
101 path.cubicTo(moveToPt, moveToPt, moveToPt);
102 return moveToPt;
103 }
104
105 static SkPoint AddMoveDegenCubicClose(SkPath& path, SkPoint& startPt) {
106 SkPoint moveToPt = startPt + SkPoint::Make(0, 10*SK_Scalar1);
107 path.moveTo(moveToPt);
108 path.cubicTo(moveToPt, moveToPt, moveToPt);
109 path.close();
110 return moveToPt;
111 }
112
113 static SkPoint AddClose(SkPath& path, SkPoint& startPt) {
114 path.close();
115 return startPt;
116 }
117
118 static SkPoint AddLine(SkPath& path, SkPoint& startPt) {
119 SkPoint endPt = startPt + SkPoint::Make(40*SK_Scalar1, 0);
120 path.lineTo(endPt);
121 return endPt;
122 }
123
124 static SkPoint AddMoveLine(SkPath& path, SkPoint& startPt) {
125 SkPoint moveToPt = startPt + SkPoint::Make(0, 10*SK_Scalar1);
126 SkPoint endPt = moveToPt + SkPoint::Make(40*SK_Scalar1, 0);
127 path.moveTo(moveToPt);
128 path.lineTo(endPt);
129 return endPt;
130 }
131
132 static SkPoint AddMoveLineClose(SkPath& path, SkPoint& startPt) {
133 SkPoint moveToPt = startPt + SkPoint::Make(0, 10*SK_Scalar1);
134 SkPoint endPt = moveToPt + SkPoint::Make(40*SK_Scalar1, 0);
135 path.moveTo(moveToPt);
136 path.lineTo(endPt);
137 path.close();
138 return endPt;
139 }
140
141 static SkPoint AddQuad(SkPath& path, SkPoint& startPt) {
142 SkPoint midPt = startPt + SkPoint::Make(20*SK_Scalar1, 5*SK_Scalar1);
143 SkPoint endPt = startPt + SkPoint::Make(40*SK_Scalar1, 0);
144 path.quadTo(midPt, endPt);
145 return endPt;
146 }
147
148 static SkPoint AddMoveQuad(SkPath& path, SkPoint& startPt) {
149 SkPoint moveToPt = startPt + SkPoint::Make(0, 10*SK_Scalar1);
150 SkPoint midPt = moveToPt + SkPoint::Make(20*SK_Scalar1, 5*SK_Scalar1);
151 SkPoint endPt = moveToPt + SkPoint::Make(40*SK_Scalar1, 0);
152 path.moveTo(moveToPt);
153 path.quadTo(midPt, endPt);
154 return endPt;
155 }
156
157 static SkPoint AddMoveQuadClose(SkPath& path, SkPoint& startPt) {
158 SkPoint moveToPt = startPt + SkPoint::Make(0, 10*SK_Scalar1);
159 SkPoint midPt = moveToPt + SkPoint::Make(20*SK_Scalar1, 5*SK_Scalar1);
160 SkPoint endPt = moveToPt + SkPoint::Make(40*SK_Scalar1, 0);
161 path.moveTo(moveToPt);
162 path.quadTo(midPt, endPt);
163 path.close();
164 return endPt;
165 }
166
167 static SkPoint AddCubic(SkPath& path, SkPoint& startPt) {
168 SkPoint t1Pt = startPt + SkPoint::Make(15*SK_Scalar1, 5*SK_Scalar1);
169 SkPoint t2Pt = startPt + SkPoint::Make(25*SK_Scalar1, 5*SK_Scalar1);
170 SkPoint endPt = startPt + SkPoint::Make(40*SK_Scalar1, 0);
171 path.cubicTo(t1Pt, t2Pt, endPt);
172 return endPt;
173 }
174
175 static SkPoint AddMoveCubic(SkPath& path, SkPoint& startPt) {
176 SkPoint moveToPt = startPt + SkPoint::Make(0, 10*SK_Scalar1);
177 SkPoint t1Pt = moveToPt + SkPoint::Make(15*SK_Scalar1, 5*SK_Scalar1);
178 SkPoint t2Pt = moveToPt + SkPoint::Make(25*SK_Scalar1, 5*SK_Scalar1);
179 SkPoint endPt = moveToPt + SkPoint::Make(40*SK_Scalar1, 0);
180 path.moveTo(moveToPt);
181 path.cubicTo(t1Pt, t2Pt, endPt);
182 return endPt;
183 }
184
185 static SkPoint AddMoveCubicClose(SkPath& path, SkPoint& startPt) {
186 SkPoint moveToPt = startPt + SkPoint::Make(0, 10*SK_Scalar1);
187 SkPoint t1Pt = moveToPt + SkPoint::Make(15*SK_Scalar1, 5*SK_Scalar1);
188 SkPoint t2Pt = moveToPt + SkPoint::Make(25*SK_Scalar1, 5*SK_Scalar1);
189 SkPoint endPt = moveToPt + SkPoint::Make(40*SK_Scalar1, 0);
190 path.moveTo(moveToPt);
191 path.cubicTo(t1Pt, t2Pt, endPt);
192 path.close();
193 return endPt;
194 }
195
196 void drawPath(SkPath& path, SkCanvas* canvas, SkColor color,
schenney@chromium.org45cbfdd2011-12-20 21:48:14 +0000197 const SkRect& clip, SkPaint::Cap cap, SkPaint::Join join,
schenney@chromium.org4da06ab2011-12-20 15:14:18 +0000198 SkPaint::Style style, SkPath::FillType fill,
199 SkScalar strokeWidth) {
200 path.setFillType(fill);
201 SkPaint paint;
202 paint.setStrokeCap(cap);
203 paint.setStrokeWidth(strokeWidth);
schenney@chromium.org45cbfdd2011-12-20 21:48:14 +0000204 paint.setStrokeJoin(join);
schenney@chromium.org4da06ab2011-12-20 15:14:18 +0000205 paint.setColor(color);
206 paint.setStyle(style);
207 canvas->save();
208 canvas->clipRect(clip);
209 canvas->drawPath(path, paint);
210 canvas->restore();
211 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000212
schenney@chromium.org4da06ab2011-12-20 15:14:18 +0000213 virtual void onDraw(SkCanvas* canvas) {
schenney@chromium.org6630d8d2012-01-04 21:05:51 +0000214 static const AddSegmentFunc gSegmentFunctions[] = {
215 AddMove,
216 AddMoveClose,
217 AddDegenLine,
218 AddMoveDegenLine,
219 AddMoveDegenLineClose,
220 AddDegenQuad,
221 AddMoveDegenQuad,
222 AddMoveDegenQuadClose,
223 AddDegenCubic,
224 AddMoveDegenCubic,
225 AddMoveDegenCubicClose,
226 AddClose,
227 AddLine,
228 AddMoveLine,
229 AddMoveLineClose,
230 AddQuad,
231 AddMoveQuad,
232 AddMoveQuadClose,
233 AddCubic,
234 AddMoveCubic,
235 AddMoveCubicClose
236 };
237 static const char* gSegmentNames[] = {
238 "Move",
239 "MoveClose",
240 "DegenLine",
241 "MoveDegenLine",
242 "MoveDegenLineClose",
243 "DegenQuad",
244 "MoveDegenQuad",
245 "MoveDegenQuadClose",
246 "DegenCubic",
247 "MoveDegenCubic",
248 "MoveDegenCubicClose",
249 "Close",
250 "Line",
251 "MoveLine",
252 "MoveLineClose",
253 "Quad",
254 "MoveQuad",
255 "MoveQuadClose",
256 "Cubic",
257 "MoveCubic",
258 "MoveCubicClose"
259 };
schenney@chromium.org4da06ab2011-12-20 15:14:18 +0000260
261 struct FillAndName {
262 SkPath::FillType fFill;
263 const char* fName;
264 };
265 static const FillAndName gFills[] = {
266 {SkPath::kWinding_FillType, "Winding"},
267 {SkPath::kEvenOdd_FillType, "Even / Odd"},
268 {SkPath::kInverseWinding_FillType, "Inverse Winding"},
269 {SkPath::kInverseEvenOdd_FillType, "Inverse Even / Odd"}
270 };
271 struct StyleAndName {
272 SkPaint::Style fStyle;
273 const char* fName;
274 };
275 static const StyleAndName gStyles[] = {
276 {SkPaint::kFill_Style, "Fill"},
277 {SkPaint::kStroke_Style, "Stroke 10"},
278 {SkPaint::kStrokeAndFill_Style, "Stroke 10 And Fill"}
279 };
280 struct CapAndName {
schenney@chromium.org45cbfdd2011-12-20 21:48:14 +0000281 SkPaint::Cap fCap;
282 SkPaint::Join fJoin;
283 const char* fName;
schenney@chromium.org4da06ab2011-12-20 15:14:18 +0000284 };
285 static const CapAndName gCaps[] = {
schenney@chromium.org45cbfdd2011-12-20 21:48:14 +0000286 {SkPaint::kButt_Cap, SkPaint::kBevel_Join, "Butt"},
287 {SkPaint::kRound_Cap, SkPaint::kRound_Join, "Round"},
288 {SkPaint::kSquare_Cap, SkPaint::kBevel_Join, "Square"}
schenney@chromium.org4da06ab2011-12-20 15:14:18 +0000289 };
290
291 SkPaint titlePaint;
292 titlePaint.setColor(SK_ColorBLACK);
293 titlePaint.setAntiAlias(true);
294 titlePaint.setLCDRenderText(true);
295 titlePaint.setTextSize(15 * SK_Scalar1);
296 const char title[] = "Random Paths Drawn Into Rectangle Clips With "
297 "Indicated Style, Fill and Linecaps, "
298 "with Stroke width 6";
299 canvas->drawText(title, strlen(title),
300 20 * SK_Scalar1,
301 20 * SK_Scalar1,
302 titlePaint);
303
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +0000304 SkLCGRandom rand;
schenney@chromium.org4da06ab2011-12-20 15:14:18 +0000305 SkRect rect = SkRect::MakeWH(220*SK_Scalar1, 50*SK_Scalar1);
306 canvas->save();
307 canvas->translate(2*SK_Scalar1, 30 * SK_Scalar1); // The title
308 canvas->save();
309 unsigned numSegments = SK_ARRAY_COUNT(gSegmentFunctions);
310 unsigned numCaps = SK_ARRAY_COUNT(gCaps);
311 unsigned numStyles = SK_ARRAY_COUNT(gStyles);
312 unsigned numFills = SK_ARRAY_COUNT(gFills);
schenney@chromium.org45cbfdd2011-12-20 21:48:14 +0000313 for (size_t row = 0; row < 6; ++row) {
schenney@chromium.org4da06ab2011-12-20 15:14:18 +0000314 if (0 < row) {
315 canvas->translate(0, rect.height() + 100*SK_Scalar1);
316 }
317 canvas->save();
schenney@chromium.org45cbfdd2011-12-20 21:48:14 +0000318 for (size_t column = 0; column < 4; ++column) {
schenney@chromium.org4da06ab2011-12-20 15:14:18 +0000319 if (0 < column) {
320 canvas->translate(rect.width() + 4*SK_Scalar1, 0);
321 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000322
schenney@chromium.org4da06ab2011-12-20 15:14:18 +0000323 SkColor color = 0xff007000;
324 StyleAndName style = gStyles[(rand.nextU() >> 16) % numStyles];
325 CapAndName cap = gCaps[(rand.nextU() >> 16) % numCaps];
326 FillAndName fill = gFills[(rand.nextU() >> 16) % numFills];
327 SkPath path;
328 unsigned s1 = (rand.nextU() >> 16) % numSegments;
329 unsigned s2 = (rand.nextU() >> 16) % numSegments;
330 unsigned s3 = (rand.nextU() >> 16) % numSegments;
331 unsigned s4 = (rand.nextU() >> 16) % numSegments;
332 unsigned s5 = (rand.nextU() >> 16) % numSegments;
333 SkPoint pt = SkPoint::Make(10*SK_Scalar1, 0);
334 pt = gSegmentFunctions[s1](path, pt);
335 pt = gSegmentFunctions[s2](path, pt);
336 pt = gSegmentFunctions[s3](path, pt);
337 pt = gSegmentFunctions[s4](path, pt);
338 pt = gSegmentFunctions[s5](path, pt);
339
340 this->drawPath(path, canvas, color, rect,
schenney@chromium.org45cbfdd2011-12-20 21:48:14 +0000341 cap.fCap, cap.fJoin, style.fStyle,
schenney@chromium.org4da06ab2011-12-20 15:14:18 +0000342 fill.fFill, SK_Scalar1*6);
343
344 SkPaint rectPaint;
345 rectPaint.setColor(SK_ColorBLACK);
346 rectPaint.setStyle(SkPaint::kStroke_Style);
347 rectPaint.setStrokeWidth(-1);
348 rectPaint.setAntiAlias(true);
349 canvas->drawRect(rect, rectPaint);
350
351 SkPaint labelPaint;
352 labelPaint.setColor(color);
353 labelPaint.setAntiAlias(true);
354 labelPaint.setLCDRenderText(true);
355 labelPaint.setTextSize(10 * SK_Scalar1);
356 canvas->drawText(style.fName,
357 strlen(style.fName),
358 0, rect.height() + 12 * SK_Scalar1,
359 labelPaint);
360 canvas->drawText(fill.fName,
361 strlen(fill.fName),
362 0, rect.height() + 24 * SK_Scalar1,
363 labelPaint);
364 canvas->drawText(cap.fName,
365 strlen(cap.fName),
366 0, rect.height() + 36 * SK_Scalar1,
367 labelPaint);
368 canvas->drawText(gSegmentNames[s1],
369 strlen(gSegmentNames[s1]),
370 0, rect.height() + 48 * SK_Scalar1,
371 labelPaint);
372 canvas->drawText(gSegmentNames[s2],
373 strlen(gSegmentNames[s2]),
374 0, rect.height() + 60 * SK_Scalar1,
375 labelPaint);
376 canvas->drawText(gSegmentNames[s3],
377 strlen(gSegmentNames[s3]),
378 0, rect.height() + 72 * SK_Scalar1,
379 labelPaint);
380 canvas->drawText(gSegmentNames[s4],
381 strlen(gSegmentNames[s4]),
382 0, rect.height() + 84 * SK_Scalar1,
383 labelPaint);
384 canvas->drawText(gSegmentNames[s5],
385 strlen(gSegmentNames[s5]),
386 0, rect.height() + 96 * SK_Scalar1,
387 labelPaint);
388 }
389 canvas->restore();
390 }
391 canvas->restore();
392 canvas->restore();
393 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000394
schenney@chromium.org4da06ab2011-12-20 15:14:18 +0000395private:
396 typedef GM INHERITED;
397};
398
399//////////////////////////////////////////////////////////////////////////////
400
401static GM* MyFactory(void*) { return new DegenerateSegmentsGM; }
402static GMRegistry reg(MyFactory);
403
404}