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 EmptyPathGM : public GM {
17 public:
EmptyPathGM()18     EmptyPathGM() {}
19 
20 protected:
onShortName()21     SkString onShortName() {
22         return SkString("emptypath");
23     }
24 
onISize()25     SkISize onISize() { return SkISize::Make(600, 280); }
26 
drawEmpty(SkCanvas * canvas,SkColor color,const SkRect & clip,SkPaint::Style style,SkPath::FillType fill)27     void drawEmpty(SkCanvas* canvas,
28                     SkColor color,
29                     const SkRect& clip,
30                     SkPaint::Style style,
31                     SkPath::FillType fill) {
32         SkPath path;
33         path.setFillType(fill);
34         SkPaint paint;
35         paint.setColor(color);
36         paint.setStyle(style);
37         canvas->save();
38         canvas->clipRect(clip);
39         canvas->drawPath(path, paint);
40         canvas->restore();
41     }
42 
onDraw(SkCanvas * canvas)43     virtual void onDraw(SkCanvas* canvas) {
44         struct FillAndName {
45             SkPath::FillType fFill;
46             const char*      fName;
47         };
48         constexpr FillAndName gFills[] = {
49             {SkPath::kWinding_FillType, "Winding"},
50             {SkPath::kEvenOdd_FillType, "Even / Odd"},
51             {SkPath::kInverseWinding_FillType, "Inverse Winding"},
52             {SkPath::kInverseEvenOdd_FillType, "Inverse Even / Odd"},
53         };
54         struct StyleAndName {
55             SkPaint::Style fStyle;
56             const char*    fName;
57         };
58         constexpr StyleAndName gStyles[] = {
59             {SkPaint::kFill_Style, "Fill"},
60             {SkPaint::kStroke_Style, "Stroke"},
61             {SkPaint::kStrokeAndFill_Style, "Stroke And Fill"},
62         };
63 
64         SkFont font(sk_tool_utils::create_portable_typeface(), 15);
65         const char title[] = "Empty Paths Drawn Into Rectangle Clips With "
66                              "Indicated Style and Fill";
67         canvas->drawString(title, 20.0f, 20.0f, font, SkPaint());
68 
69         SkRandom rand;
70         SkRect rect = SkRect::MakeWH(100*SK_Scalar1, 30*SK_Scalar1);
71         int i = 0;
72         canvas->save();
73         canvas->translate(10 * SK_Scalar1, 0);
74         canvas->save();
75         for (size_t style = 0; style < SK_ARRAY_COUNT(gStyles); ++style) {
76             for (size_t fill = 0; fill < SK_ARRAY_COUNT(gFills); ++fill) {
77                 if (0 == i % 4) {
78                     canvas->restore();
79                     canvas->translate(0, rect.height() + 40 * SK_Scalar1);
80                     canvas->save();
81                 } else {
82                     canvas->translate(rect.width() + 40 * SK_Scalar1, 0);
83                 }
84                 ++i;
85 
86 
87                 SkColor color = rand.nextU();
88                 color = 0xff000000 | color; // force solid
89                 color = sk_tool_utils::color_to_565(color);
90                 this->drawEmpty(canvas, color, rect,
91                                 gStyles[style].fStyle, gFills[fill].fFill);
92 
93                 SkPaint rectPaint;
94                 rectPaint.setColor(SK_ColorBLACK);
95                 rectPaint.setStyle(SkPaint::kStroke_Style);
96                 rectPaint.setStrokeWidth(-1);
97                 rectPaint.setAntiAlias(true);
98                 canvas->drawRect(rect, rectPaint);
99 
100                 SkPaint labelPaint;
101                 labelPaint.setColor(color);
102                 SkFont labelFont(sk_tool_utils::create_portable_typeface(), 12);
103                 canvas->drawString(gStyles[style].fName, 0, rect.height() + 15.0f,
104                                    labelFont, labelPaint);
105                 canvas->drawString(gFills[fill].fName, 0, rect.height() + 28.0f,
106                                    labelFont, labelPaint);
107             }
108         }
109         canvas->restore();
110         canvas->restore();
111     }
112 
113 private:
114     typedef GM INHERITED;
115 };
DEF_GM(return new EmptyPathGM;)116 DEF_GM( return new EmptyPathGM; )
117 
118 //////////////////////////////////////////////////////////////////////////////
119 
120 static void make_path_move(SkPath* path, const SkPoint pts[3]) {
121     for (int i = 0; i < 3; ++i) {
122         path->moveTo(pts[i]);
123     }
124 }
125 
make_path_move_close(SkPath * path,const SkPoint pts[3])126 static void make_path_move_close(SkPath* path, const SkPoint pts[3]) {
127     for (int i = 0; i < 3; ++i) {
128         path->moveTo(pts[i]);
129         path->close();
130     }
131 }
132 
make_path_move_line(SkPath * path,const SkPoint pts[3])133 static void make_path_move_line(SkPath* path, const SkPoint pts[3]) {
134     for (int i = 0; i < 3; ++i) {
135         path->moveTo(pts[i]);
136         path->lineTo(pts[i]);
137     }
138 }
139 
140 typedef void (*MakePathProc)(SkPath*, const SkPoint pts[3]);
141 
make_path_move_mix(SkPath * path,const SkPoint pts[3])142 static void make_path_move_mix(SkPath* path, const SkPoint pts[3]) {
143     path->moveTo(pts[0]);
144     path->moveTo(pts[1]); path->close();
145     path->moveTo(pts[2]); path->lineTo(pts[2]);
146 }
147 
148 class EmptyStrokeGM : public GM {
149     SkPoint fPts[3];
150 
151 public:
EmptyStrokeGM()152     EmptyStrokeGM() {
153         fPts[0].set(40, 40);
154         fPts[1].set(80, 40);
155         fPts[2].set(120, 40);
156     }
157 
158 protected:
onShortName()159     SkString onShortName() override {
160         return SkString("emptystroke");
161     }
162 
onISize()163     SkISize onISize() override { return SkISize::Make(200, 240); }
164 
onDraw(SkCanvas * canvas)165     void onDraw(SkCanvas* canvas) override {
166         const MakePathProc procs[] = {
167             make_path_move,             // expect red red red
168             make_path_move_close,       // expect black black black
169             make_path_move_line,        // expect black black black
170             make_path_move_mix,         // expect red black black,
171         };
172 
173         SkPaint strokePaint;
174         strokePaint.setStyle(SkPaint::kStroke_Style);
175         strokePaint.setStrokeWidth(21);
176         strokePaint.setStrokeCap(SkPaint::kSquare_Cap);
177 
178         SkPaint dotPaint;
179         dotPaint.setColor(SK_ColorRED);
180         strokePaint.setStyle(SkPaint::kStroke_Style);
181         dotPaint.setStrokeWidth(7);
182 
183         for (size_t i = 0; i < SK_ARRAY_COUNT(procs); ++i) {
184             SkPath path;
185             procs[i](&path, fPts);
186             canvas->drawPoints(SkCanvas::kPoints_PointMode, 3, fPts, dotPaint);
187             canvas->drawPath(path, strokePaint);
188             canvas->translate(0, 40);
189         }
190     }
191 
192 private:
193     typedef GM INHERITED;
194 };
195 DEF_GM( return new EmptyStrokeGM; )
196 
197 }
198