xref: /aosp_15_r20/external/skia/gm/emptypath.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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/SkPathBuilder.h"
14 #include "include/core/SkPoint.h"
15 #include "include/core/SkRect.h"
16 #include "include/core/SkScalar.h"
17 #include "include/core/SkSize.h"
18 #include "include/core/SkString.h"
19 #include "include/core/SkTypeface.h"
20 #include "include/core/SkTypes.h"
21 #include "src/base/SkRandom.h"
22 #include "tools/ToolUtils.h"
23 #include "tools/fonts/FontToolUtils.h"
24 
25 namespace skiagm {
26 
27 class EmptyPathGM : public GM {
getName() const28     SkString getName() const override { return SkString("emptypath"); }
29 
getISize()30     SkISize getISize() override { return {600, 280}; }
31 
drawEmpty(SkCanvas * canvas,SkColor color,const SkRect & clip,SkPaint::Style style,SkPathFillType fill)32     void drawEmpty(SkCanvas* canvas,
33                     SkColor color,
34                     const SkRect& clip,
35                     SkPaint::Style style,
36                     SkPathFillType fill) {
37         SkPath path;
38         path.setFillType(fill);
39         SkPaint paint;
40         paint.setColor(color);
41         paint.setStyle(style);
42         canvas->save();
43         canvas->clipRect(clip);
44         canvas->drawPath(path, paint);
45         canvas->restore();
46     }
47 
onDraw(SkCanvas * canvas)48     void onDraw(SkCanvas* canvas) override {
49         struct FillAndName {
50             SkPathFillType fFill;
51             const char*      fName;
52         };
53         constexpr FillAndName gFills[] = {
54             {SkPathFillType::kWinding, "Winding"},
55             {SkPathFillType::kEvenOdd, "Even / Odd"},
56             {SkPathFillType::kInverseWinding, "Inverse Winding"},
57             {SkPathFillType::kInverseEvenOdd, "Inverse Even / Odd"},
58         };
59         struct StyleAndName {
60             SkPaint::Style fStyle;
61             const char*    fName;
62         };
63         constexpr StyleAndName gStyles[] = {
64             {SkPaint::kFill_Style, "Fill"},
65             {SkPaint::kStroke_Style, "Stroke"},
66             {SkPaint::kStrokeAndFill_Style, "Stroke And Fill"},
67         };
68 
69         SkFont     font(ToolUtils::DefaultPortableTypeface(), 15);
70         const char title[] = "Empty Paths Drawn Into Rectangle Clips With "
71                              "Indicated Style and Fill";
72         canvas->drawString(title, 20.0f, 20.0f, font, SkPaint());
73 
74         SkRandom rand;
75         SkRect rect = SkRect::MakeWH(100*SK_Scalar1, 30*SK_Scalar1);
76         int i = 0;
77         canvas->save();
78         canvas->translate(10 * SK_Scalar1, 0);
79         canvas->save();
80         for (size_t style = 0; style < std::size(gStyles); ++style) {
81             for (size_t fill = 0; fill < std::size(gFills); ++fill) {
82                 if (0 == i % 4) {
83                     canvas->restore();
84                     canvas->translate(0, rect.height() + 40 * SK_Scalar1);
85                     canvas->save();
86                 } else {
87                     canvas->translate(rect.width() + 40 * SK_Scalar1, 0);
88                 }
89                 ++i;
90 
91 
92                 SkColor color = rand.nextU();
93                 color = 0xff000000 | color; // force solid
94                 color         = ToolUtils::color_to_565(color);
95                 this->drawEmpty(canvas, color, rect,
96                                 gStyles[style].fStyle, gFills[fill].fFill);
97 
98                 SkPaint rectPaint;
99                 rectPaint.setColor(SK_ColorBLACK);
100                 rectPaint.setStyle(SkPaint::kStroke_Style);
101                 rectPaint.setStrokeWidth(-1);
102                 rectPaint.setAntiAlias(true);
103                 canvas->drawRect(rect, rectPaint);
104 
105                 SkPaint labelPaint;
106                 labelPaint.setColor(color);
107                 SkFont labelFont(ToolUtils::DefaultPortableTypeface(), 12);
108                 canvas->drawString(gStyles[style].fName, 0, rect.height() + 15.0f,
109                                    labelFont, labelPaint);
110                 canvas->drawString(gFills[fill].fName, 0, rect.height() + 28.0f,
111                                    labelFont, labelPaint);
112             }
113         }
114         canvas->restore();
115         canvas->restore();
116     }
117 };
118 DEF_GM( return new EmptyPathGM; )
119 
120 //////////////////////////////////////////////////////////////////////////////
121 
122 static constexpr int kPtsCount = 3;
123 static constexpr SkPoint kPts[kPtsCount] = {
124     {40, 40},
125     {80, 40},
126     {120, 40},
127 };
128 
make_path_move()129 static SkPath make_path_move() {
130     SkPathBuilder builder;
131     for (SkPoint p : kPts) {
132         builder.moveTo(p);
133     }
134     return builder.detach();
135 }
136 
make_path_move_close()137 static SkPath make_path_move_close() {
138     SkPathBuilder builder;
139     for (SkPoint p : kPts) {
140         builder.moveTo(p).close();
141     }
142     return builder.detach();
143 }
144 
make_path_move_line()145 static SkPath make_path_move_line() {
146     SkPathBuilder builder;
147     for (SkPoint p : kPts) {
148         builder.moveTo(p).lineTo(p);
149     }
150     return builder.detach();
151 }
152 
make_path_move_mix()153 static SkPath make_path_move_mix() {
154     return SkPathBuilder().moveTo(kPts[0])
155                           .moveTo(kPts[1]).close()
156                           .moveTo(kPts[2]).lineTo(kPts[2])
157                           .detach();
158 }
159 
160 class EmptyStrokeGM : public GM {
getName() const161     SkString getName() const override { return SkString("emptystroke"); }
162 
getISize()163     SkISize getISize() override { return {200, 240}; }
164 
onDraw(SkCanvas * canvas)165     void onDraw(SkCanvas* canvas) override {
166         static constexpr SkPath (*kProcs[])() = {
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 (auto proc : kProcs) {
184             canvas->drawPoints(SkCanvas::kPoints_PointMode, kPtsCount, kPts, dotPaint);
185             canvas->drawPath(proc(), strokePaint);
186             canvas->translate(0, 40);
187         }
188     }
189 };
190 DEF_GM( return new EmptyStrokeGM; )
191 
192 }  // namespace skiagm
193