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