xref: /third_party/skia/gm/quadpaths.cpp (revision cb93a386)
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
8#include "gm/gm.h"
9#include "include/core/SkCanvas.h"
10#include "include/core/SkColor.h"
11#include "include/core/SkFont.h"
12#include "include/core/SkPaint.h"
13#include "include/core/SkPath.h"
14#include "include/core/SkRect.h"
15#include "include/core/SkScalar.h"
16#include "include/core/SkSize.h"
17#include "include/core/SkString.h"
18#include "include/core/SkTypeface.h"
19#include "include/core/SkTypes.h"
20#include "include/utils/SkRandom.h"
21#include "tools/ToolUtils.h"
22
23namespace skiagm {
24
25class QuadPathGM : public GM {
26public:
27    QuadPathGM() {}
28
29protected:
30
31    SkString onShortName() override {
32        return SkString("quadpath");
33    }
34
35    SkISize onISize() override { return SkISize::Make(1240, 390); }
36
37    void drawPath(SkPath& path,SkCanvas* canvas,SkColor color,
38                  const SkRect& clip,SkPaint::Cap cap, SkPaint::Join join,
39                  SkPaint::Style style, SkPathFillType fill,
40                  SkScalar strokeWidth) {
41        path.setFillType(fill);
42        SkPaint paint;
43        paint.setStrokeCap(cap);
44        paint.setStrokeWidth(strokeWidth);
45        paint.setStrokeJoin(join);
46        paint.setColor(color);
47        paint.setStyle(style);
48        canvas->save();
49        canvas->clipRect(clip);
50        canvas->drawPath(path, paint);
51        canvas->restore();
52    }
53
54    void onDraw(SkCanvas* canvas) override {
55        struct FillAndName {
56            SkPathFillType fFill;
57            const char*      fName;
58        };
59        constexpr FillAndName gFills[] = {
60            {SkPathFillType::kWinding, "Winding"},
61            {SkPathFillType::kEvenOdd, "Even / Odd"},
62            {SkPathFillType::kInverseWinding, "Inverse Winding"},
63            {SkPathFillType::kInverseEvenOdd, "Inverse Even / Odd"},
64        };
65        struct StyleAndName {
66            SkPaint::Style fStyle;
67            const char*    fName;
68        };
69        constexpr StyleAndName gStyles[] = {
70            {SkPaint::kFill_Style, "Fill"},
71            {SkPaint::kStroke_Style, "Stroke"},
72            {SkPaint::kStrokeAndFill_Style, "Stroke And Fill"},
73        };
74        struct CapAndName {
75            SkPaint::Cap  fCap;
76            SkPaint::Join fJoin;
77            const char*   fName;
78        };
79        constexpr CapAndName gCaps[] = {
80            {SkPaint::kButt_Cap, SkPaint::kBevel_Join, "Butt"},
81            {SkPaint::kRound_Cap, SkPaint::kRound_Join, "Round"},
82            {SkPaint::kSquare_Cap, SkPaint::kBevel_Join, "Square"}
83        };
84        struct PathAndName {
85            SkPath      fPath;
86            const char* fName;
87        };
88        PathAndName path;
89        path.fPath.moveTo(25*SK_Scalar1, 10*SK_Scalar1);
90        path.fPath.quadTo(50*SK_Scalar1, 20*SK_Scalar1,
91                          75*SK_Scalar1, 10*SK_Scalar1);
92        path.fName = "moveTo-quad";
93
94        SkPaint titlePaint;
95        SkFont  font(ToolUtils::create_portable_typeface(), 15);
96        SkFont  labelFont(ToolUtils::create_portable_typeface(), 10);
97
98        const char title[] = "Quad Drawn Into Rectangle Clips With "
99                             "Indicated Style, Fill and Linecaps, with stroke width 10";
100        canvas->drawString(title, 20.0f, 20.0f, font, titlePaint);
101
102        SkRandom rand;
103        SkRect rect = SkRect::MakeWH(100*SK_Scalar1, 30*SK_Scalar1);
104        canvas->save();
105        canvas->translate(10 * SK_Scalar1, 30 * SK_Scalar1);
106        canvas->save();
107        for (size_t cap = 0; cap < SK_ARRAY_COUNT(gCaps); ++cap) {
108            if (0 < cap) {
109                canvas->translate((rect.width() + 40 * SK_Scalar1) * SK_ARRAY_COUNT(gStyles), 0);
110            }
111            canvas->save();
112            for (size_t fill = 0; fill < SK_ARRAY_COUNT(gFills); ++fill) {
113                if (0 < fill) {
114                    canvas->translate(0, rect.height() + 40 * SK_Scalar1);
115                }
116                canvas->save();
117                for (size_t style = 0; style < SK_ARRAY_COUNT(gStyles); ++style) {
118                    if (0 < style) {
119                        canvas->translate(rect.width() + 40 * SK_Scalar1, 0);
120                    }
121
122                    SkColor color = ToolUtils::color_to_565(0xff007000);
123                    this->drawPath(path.fPath, canvas, color, rect,
124                                    gCaps[cap].fCap, gCaps[cap].fJoin, gStyles[style].fStyle,
125                                    gFills[fill].fFill, SK_Scalar1*10);
126
127                    SkPaint rectPaint;
128                    rectPaint.setColor(SK_ColorBLACK);
129                    rectPaint.setStyle(SkPaint::kStroke_Style);
130                    rectPaint.setStrokeWidth(-1);
131                    rectPaint.setAntiAlias(true);
132                    canvas->drawRect(rect, rectPaint);
133
134                    SkPaint labelPaint;
135                    labelPaint.setColor(color);
136                    canvas->drawString(gStyles[style].fName, 0, rect.height() + 12.0f,
137                                       labelFont, labelPaint);
138                    canvas->drawString(gFills[fill].fName, 0, rect.height() + 24.0f,
139                                       labelFont, labelPaint);
140                    canvas->drawString(gCaps[cap].fName, 0, rect.height() + 36.0f,
141                                       labelFont, labelPaint);
142                }
143                canvas->restore();
144            }
145            canvas->restore();
146        }
147        canvas->restore();
148        canvas->restore();
149    }
150
151private:
152    using INHERITED = GM;
153};
154
155class QuadClosePathGM : public GM {
156public:
157    QuadClosePathGM() {}
158
159protected:
160
161    SkString onShortName() override {
162        return SkString("quadclosepath");
163    }
164
165    SkISize onISize() override { return SkISize::Make(1240, 390); }
166
167    void drawPath(SkPath& path,SkCanvas* canvas,SkColor color,
168                  const SkRect& clip,SkPaint::Cap cap, SkPaint::Join join,
169                  SkPaint::Style style, SkPathFillType fill,
170                  SkScalar strokeWidth) {
171        path.setFillType(fill);
172        SkPaint paint;
173        paint.setStrokeCap(cap);
174        paint.setStrokeWidth(strokeWidth);
175        paint.setStrokeJoin(join);
176        paint.setColor(color);
177        paint.setStyle(style);
178        canvas->save();
179        canvas->clipRect(clip);
180        canvas->drawPath(path, paint);
181        canvas->restore();
182    }
183
184    void onDraw(SkCanvas* canvas) override {
185        struct FillAndName {
186            SkPathFillType fFill;
187            const char*      fName;
188        };
189        constexpr FillAndName gFills[] = {
190            {SkPathFillType::kWinding, "Winding"},
191            {SkPathFillType::kEvenOdd, "Even / Odd"},
192            {SkPathFillType::kInverseWinding, "Inverse Winding"},
193            {SkPathFillType::kInverseEvenOdd, "Inverse Even / Odd"},
194        };
195        struct StyleAndName {
196            SkPaint::Style fStyle;
197            const char*    fName;
198        };
199        constexpr StyleAndName gStyles[] = {
200            {SkPaint::kFill_Style, "Fill"},
201            {SkPaint::kStroke_Style, "Stroke"},
202            {SkPaint::kStrokeAndFill_Style, "Stroke And Fill"},
203        };
204        struct CapAndName {
205            SkPaint::Cap  fCap;
206            SkPaint::Join fJoin;
207            const char*   fName;
208        };
209        constexpr CapAndName gCaps[] = {
210            {SkPaint::kButt_Cap, SkPaint::kBevel_Join, "Butt"},
211            {SkPaint::kRound_Cap, SkPaint::kRound_Join, "Round"},
212            {SkPaint::kSquare_Cap, SkPaint::kBevel_Join, "Square"}
213        };
214        struct PathAndName {
215            SkPath      fPath;
216            const char* fName;
217        };
218        PathAndName path;
219        path.fPath.moveTo(25*SK_Scalar1, 10*SK_Scalar1);
220        path.fPath.quadTo(50*SK_Scalar1, 20*SK_Scalar1,
221                          75*SK_Scalar1, 10*SK_Scalar1);
222        path.fPath.close();
223        path.fName = "moveTo-quad-close";
224
225        SkPaint titlePaint;
226        SkFont     font(ToolUtils::create_portable_typeface(), 15);
227        SkFont     labelFont(ToolUtils::create_portable_typeface(), 10);
228        const char title[] = "Quad Closed Drawn Into Rectangle Clips With "
229                             "Indicated Style, Fill and Linecaps, with stroke width 10";
230        canvas->drawString(title, 20.0f, 20.0f, font, titlePaint);
231
232        SkRandom rand;
233        SkRect rect = SkRect::MakeWH(100*SK_Scalar1, 30*SK_Scalar1);
234        canvas->save();
235        canvas->translate(10 * SK_Scalar1, 30 * SK_Scalar1);
236        canvas->save();
237        for (size_t cap = 0; cap < SK_ARRAY_COUNT(gCaps); ++cap) {
238            if (0 < cap) {
239                canvas->translate((rect.width() + 40 * SK_Scalar1) * SK_ARRAY_COUNT(gStyles), 0);
240            }
241            canvas->save();
242            for (size_t fill = 0; fill < SK_ARRAY_COUNT(gFills); ++fill) {
243                if (0 < fill) {
244                    canvas->translate(0, rect.height() + 40 * SK_Scalar1);
245                }
246                canvas->save();
247                for (size_t style = 0; style < SK_ARRAY_COUNT(gStyles); ++style) {
248                    if (0 < style) {
249                        canvas->translate(rect.width() + 40 * SK_Scalar1, 0);
250                    }
251
252                    SkColor color = ToolUtils::color_to_565(0xff007000);
253                    this->drawPath(path.fPath, canvas, color, rect,
254                                    gCaps[cap].fCap, gCaps[cap].fJoin, gStyles[style].fStyle,
255                                    gFills[fill].fFill, SK_Scalar1*10);
256
257                    SkPaint rectPaint;
258                    rectPaint.setColor(SK_ColorBLACK);
259                    rectPaint.setStyle(SkPaint::kStroke_Style);
260                    rectPaint.setStrokeWidth(-1);
261                    rectPaint.setAntiAlias(true);
262                    canvas->drawRect(rect, rectPaint);
263
264                    SkPaint labelPaint;
265                    labelPaint.setColor(color);
266                    canvas->drawString(gStyles[style].fName, 0, rect.height() + 12.0f,
267                                       labelFont, labelPaint);
268                    canvas->drawString(gFills[fill].fName, 0, rect.height() + 24.0f,
269                                       labelFont, labelPaint);
270                    canvas->drawString(gCaps[cap].fName, 0, rect.height() + 36.0f,
271                                       labelFont, labelPaint);
272                }
273                canvas->restore();
274            }
275            canvas->restore();
276        }
277        canvas->restore();
278        canvas->restore();
279    }
280
281private:
282    using INHERITED = GM;
283};
284
285//////////////////////////////////////////////////////////////////////////////
286
287DEF_GM( return new QuadPathGM; )
288
289DEF_GM( return new QuadClosePathGM; )
290
291}  // namespace skiagm
292