• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 "sk_tool_utils.h"
9 #include "SkCanvas.h"
10 #include "SkPaint.h"
11 #include "SkPath.h"
12 #include "SkRandom.h"
13 
14 namespace skiagm {
15 
16 class DegenerateSegmentsGM : public GM {
17 public:
DegenerateSegmentsGM()18     DegenerateSegmentsGM() {}
19 
20 protected:
21     struct PathAndName {
22         SkPath      fPath;
23         const char* fName1;
24         const char* fName2;
25     };
26 
onShortName()27     SkString onShortName() {
28         return SkString("degeneratesegments");
29     }
30 
onISize()31     SkISize onISize() { return SkISize::Make(896, 930); }
32 
33     typedef SkPoint (*AddSegmentFunc)(SkPath&, SkPoint&);
34 
35     // We need to use explicit commands here, instead of addPath, because we
36     // do not want the moveTo that is added at the beginning of a path to
37     // appear in the appended path.
AddMove(SkPath & path,SkPoint & startPt)38     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 
AddMoveClose(SkPath & path,SkPoint & startPt)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 
AddDegenLine(SkPath & path,SkPoint & startPt)51     static SkPoint AddDegenLine(SkPath& path, SkPoint& startPt) {
52         path.lineTo(startPt);
53         return startPt;
54     }
55 
AddMoveDegenLine(SkPath & path,SkPoint & startPt)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 
AddMoveDegenLineClose(SkPath & path,SkPoint & startPt)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 
AddDegenQuad(SkPath & path,SkPoint & startPt)71     static SkPoint AddDegenQuad(SkPath& path, SkPoint& startPt) {
72         path.quadTo(startPt, startPt);
73         return startPt;
74     }
75 
AddMoveDegenQuad(SkPath & path,SkPoint & startPt)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 
AddMoveDegenQuadClose(SkPath & path,SkPoint & startPt)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 
AddDegenCubic(SkPath & path,SkPoint & startPt)91     static SkPoint AddDegenCubic(SkPath& path, SkPoint& startPt) {
92         path.cubicTo(startPt, startPt, startPt);
93         return startPt;
94     }
95 
AddMoveDegenCubic(SkPath & path,SkPoint & startPt)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 
AddMoveDegenCubicClose(SkPath & path,SkPoint & startPt)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 
AddClose(SkPath & path,SkPoint & startPt)111     static SkPoint AddClose(SkPath& path, SkPoint& startPt) {
112         path.close();
113         return startPt;
114     }
115 
AddLine(SkPath & path,SkPoint & startPt)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 
AddMoveLine(SkPath & path,SkPoint & startPt)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 
AddMoveLineClose(SkPath & path,SkPoint & startPt)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 
AddQuad(SkPath & path,SkPoint & startPt)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 
AddMoveQuad(SkPath & path,SkPoint & startPt)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 
AddMoveQuadClose(SkPath & path,SkPoint & startPt)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 
AddCubic(SkPath & path,SkPoint & startPt)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 
AddMoveCubic(SkPath & path,SkPoint & startPt)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 
AddMoveCubicClose(SkPath & path,SkPoint & startPt)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 
drawPath(SkPath & path,SkCanvas * canvas,SkColor color,const SkRect & clip,SkPaint::Cap cap,SkPaint::Join join,SkPaint::Style style,SkPath::FillType fill,SkScalar strokeWidth)194     void drawPath(SkPath& path, SkCanvas* canvas, SkColor color,
195                   const SkRect& clip, SkPaint::Cap cap, SkPaint::Join join,
196                   SkPaint::Style style, SkPath::FillType fill,
197                   SkScalar strokeWidth) {
198         path.setFillType(fill);
199         SkPaint paint;
200         paint.setStrokeCap(cap);
201         paint.setStrokeWidth(strokeWidth);
202         paint.setStrokeJoin(join);
203         paint.setColor(color);
204         paint.setStyle(style);
205         canvas->save();
206         canvas->clipRect(clip);
207         canvas->drawPath(path, paint);
208         canvas->restore();
209     }
210 
onDraw(SkCanvas * canvas)211     virtual void onDraw(SkCanvas* canvas) {
212     constexpr AddSegmentFunc gSegmentFunctions[] = {
213         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     };
235     const char* gSegmentNames[] = {
236         "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     };
258 
259         struct FillAndName {
260             SkPath::FillType fFill;
261             const char*      fName;
262         };
263         constexpr FillAndName gFills[] = {
264             {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         };
273         constexpr StyleAndName gStyles[] = {
274             {SkPaint::kFill_Style, "Fill"},
275             {SkPaint::kStroke_Style, "Stroke 10"},
276             {SkPaint::kStrokeAndFill_Style, "Stroke 10 And Fill"}
277         };
278         struct CapAndName {
279             SkPaint::Cap  fCap;
280             SkPaint::Join fJoin;
281             const char*   fName;
282         };
283         constexpr CapAndName gCaps[] = {
284             {SkPaint::kButt_Cap, SkPaint::kBevel_Join, "Butt"},
285             {SkPaint::kRound_Cap, SkPaint::kRound_Join, "Round"},
286             {SkPaint::kSquare_Cap, SkPaint::kBevel_Join, "Square"}
287         };
288 
289         SkPaint titlePaint;
290         titlePaint.setColor(SK_ColorBLACK);
291         titlePaint.setAntiAlias(true);
292         sk_tool_utils::set_portable_typeface(&titlePaint);
293         titlePaint.setTextSize(15 * SK_Scalar1);
294         const char title[] = "Random Paths Drawn Into Rectangle Clips With "
295                              "Indicated Style, Fill and Linecaps, "
296                              "with Stroke width 6";
297         canvas->drawString(title,
298                            20 * SK_Scalar1,
299                            20 * SK_Scalar1,
300                            titlePaint);
301 
302         SkRandom rand;
303         SkRect rect = SkRect::MakeWH(220*SK_Scalar1, 50*SK_Scalar1);
304         canvas->save();
305         canvas->translate(2*SK_Scalar1, 30 * SK_Scalar1); // The title
306         canvas->save();
307         unsigned numSegments = SK_ARRAY_COUNT(gSegmentFunctions);
308         unsigned numCaps = SK_ARRAY_COUNT(gCaps);
309         unsigned numStyles = SK_ARRAY_COUNT(gStyles);
310         unsigned numFills = SK_ARRAY_COUNT(gFills);
311         for (size_t row = 0; row < 6; ++row) {
312             if (0 < row) {
313                 canvas->translate(0, rect.height() + 100*SK_Scalar1);
314             }
315             canvas->save();
316             for (size_t column = 0; column < 4; ++column) {
317                 if (0 < column) {
318                     canvas->translate(rect.width() + 4*SK_Scalar1, 0);
319                 }
320 
321                 SkColor color = sk_tool_utils::color_to_565(0xff007000);
322                 StyleAndName style = gStyles[(rand.nextU() >> 16) % numStyles];
323                 CapAndName cap = gCaps[(rand.nextU() >> 16) % numCaps];
324                 FillAndName fill = gFills[(rand.nextU() >> 16) % numFills];
325                 SkPath path;
326                 unsigned s1 = (rand.nextU() >> 16) % numSegments;
327                 unsigned s2 = (rand.nextU() >> 16) % numSegments;
328                 unsigned s3 = (rand.nextU() >> 16) % numSegments;
329                 unsigned s4 = (rand.nextU() >> 16) % numSegments;
330                 unsigned s5 = (rand.nextU() >> 16) % numSegments;
331                 SkPoint pt = SkPoint::Make(10*SK_Scalar1, 0);
332                 pt = gSegmentFunctions[s1](path, pt);
333                 pt = gSegmentFunctions[s2](path, pt);
334                 pt = gSegmentFunctions[s3](path, pt);
335                 pt = gSegmentFunctions[s4](path, pt);
336                 pt = gSegmentFunctions[s5](path, pt);
337 
338                 this->drawPath(path, canvas, color, rect,
339                                cap.fCap, cap.fJoin, style.fStyle,
340                                fill.fFill, SK_Scalar1*6);
341 
342                 SkPaint rectPaint;
343                 rectPaint.setColor(SK_ColorBLACK);
344                 rectPaint.setStyle(SkPaint::kStroke_Style);
345                 rectPaint.setStrokeWidth(-1);
346                 rectPaint.setAntiAlias(true);
347                 canvas->drawRect(rect, rectPaint);
348 
349                 SkPaint labelPaint;
350                 labelPaint.setColor(color);
351                 labelPaint.setAntiAlias(true);
352                 sk_tool_utils::set_portable_typeface(&labelPaint);
353                 labelPaint.setTextSize(10 * SK_Scalar1);
354                 canvas->drawString(style.fName,
355                                    0, rect.height() + 12 * SK_Scalar1,
356                                    labelPaint);
357                 canvas->drawString(fill.fName,
358                                    0, rect.height() + 24 * SK_Scalar1,
359                                    labelPaint);
360                 canvas->drawString(cap.fName,
361                                    0, rect.height() + 36 * SK_Scalar1,
362                                    labelPaint);
363                 canvas->drawString(gSegmentNames[s1],
364                                    0, rect.height() + 48 * SK_Scalar1,
365                                    labelPaint);
366                 canvas->drawString(gSegmentNames[s2],
367                                    0, rect.height() + 60 * SK_Scalar1,
368                                    labelPaint);
369                 canvas->drawString(gSegmentNames[s3],
370                                    0, rect.height() + 72 * SK_Scalar1,
371                                    labelPaint);
372                 canvas->drawString(gSegmentNames[s4],
373                                    0, rect.height() + 84 * SK_Scalar1,
374                                    labelPaint);
375                 canvas->drawString(gSegmentNames[s5],
376                                    0, rect.height() + 96 * SK_Scalar1,
377                                    labelPaint);
378             }
379             canvas->restore();
380         }
381         canvas->restore();
382         canvas->restore();
383     }
384 
385 private:
386     typedef GM INHERITED;
387 };
388 
389 //////////////////////////////////////////////////////////////////////////////
390 
MyFactory(void *)391 static GM* MyFactory(void*) { return new DegenerateSegmentsGM; }
392 static GMRegistry reg(MyFactory);
393 
394 }
395