Flutter Engine
The Flutter Engine
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
convexpaths.cpp
Go to the documentation of this file.
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"
15#include "include/core/SkRect.h"
17#include "include/core/SkSize.h"
21#include "src/base/SkRandom.h"
22
23using namespace skia_private;
24
25namespace {
26
27class SkDoOnce {
28public:
29 SkDoOnce() { fDidOnce = false; }
30 // Make noncopyable
31 SkDoOnce(SkDoOnce&) = delete;
32 SkDoOnce& operator=(SkDoOnce&) = delete;
33
34 bool needToDo() const { return !fDidOnce; }
35 bool alreadyDone() const { return fDidOnce; }
36 void accomplished() {
37 SkASSERT(!fDidOnce);
38 fDidOnce = true;
39 }
40
41private:
42 bool fDidOnce;
43};
44
45class ConvexPathsGM : public skiagm::GM {
46 SkDoOnce fOnce;
47
48 void onOnceBeforeDraw() override { this->setBGColor(0xFF000000); }
49
50 SkString getName() const override { return SkString("convexpaths"); }
51
52 SkISize getISize() override { return {1200, 1100}; }
53
54 void makePaths() {
55 if (fOnce.alreadyDone()) {
56 return;
57 }
58 fOnce.accomplished();
59
61 fPaths.push_back(b.moveTo(0, 0)
62 .quadTo(50, 100, 0, 100)
63 .lineTo(0, 0)
64 .detach());
65
66 fPaths.push_back(b.moveTo(0, 50)
67 .quadTo(50, 0, 100, 50)
68 .quadTo(50, 100, 0, 50)
69 .detach());
70
71 fPaths.push_back(SkPath::Rect({0, 0, 100, 100}, SkPathDirection::kCW));
72 fPaths.push_back(SkPath::Rect({0, 0, 100, 100}, SkPathDirection::kCCW));
73 fPaths.push_back(SkPath::Circle(50, 50, 50, SkPathDirection::kCW));
74 fPaths.push_back(SkPath::Oval(SkRect::MakeXYWH(0, 0, 50, 100), SkPathDirection::kCW));
75 fPaths.push_back(SkPath::Oval(SkRect::MakeXYWH(0, 0, 100, 5), SkPathDirection::kCCW));
76 fPaths.push_back(SkPath::Oval(SkRect::MakeXYWH(0, 0, 1, 100), SkPathDirection::kCCW));
77 fPaths.push_back(SkPath::RRect(SkRRect::MakeRectXY({0, 0, 100, 100}, 40, 20),
79
80 // large number of points
81 static constexpr int kLength = 100;
82 static constexpr int kPtsPerSide = (1 << 12);
83
84 b.moveTo(0, 0);
85 for (int i = 1; i < kPtsPerSide; ++i) { // skip the first point due to moveTo.
86 b.lineTo(kLength * SkIntToScalar(i) / kPtsPerSide, 0);
87 }
88 for (int i = 0; i < kPtsPerSide; ++i) {
89 b.lineTo(kLength, kLength * SkIntToScalar(i) / kPtsPerSide);
90 }
91 for (int i = kPtsPerSide; i > 0; --i) {
92 b.lineTo(kLength * SkIntToScalar(i) / kPtsPerSide, kLength);
93 }
94 for (int i = kPtsPerSide; i > 0; --i) {
95 b.lineTo(0, kLength * SkIntToScalar(i) / kPtsPerSide);
96 }
97 fPaths.push_back(b.detach());
98
99 // shallow diagonals
100 fPaths.push_back(SkPath::Polygon({{0,0}, {100,1}, {98,100}, {3,96}}, false));
101
102 fPaths.push_back(b.arcTo(SkRect::MakeXYWH(0, 0, 50, 100), 25, 130, false)
103 .detach());
104
105 // cubics
106 fPaths.push_back(b.cubicTo( 1, 1, 10, 90, 0, 100).detach());
107 fPaths.push_back(b.cubicTo(100, 50, 20, 100, 0, 0).detach());
108
109 // path that has a cubic with a repeated first control point and
110 // a repeated last control point.
111 fPaths.push_back(b.moveTo(10, 10)
112 .cubicTo(10, 10, 10, 0, 20, 0)
113 .lineTo(40, 0)
114 .cubicTo(40, 0, 50, 0, 50, 10)
115 .detach());
116
117 // path that has two cubics with repeated middle control points.
118 fPaths.push_back(b.moveTo(10, 10)
119 .cubicTo(10, 0, 10, 0, 20, 0)
120 .lineTo(40, 0)
121 .cubicTo(50, 0, 50, 0, 50, 10)
122 .detach());
123
124 // cubic where last three points are almost a line
125 fPaths.push_back(b.moveTo(0, 228.0f/8)
126 .cubicTo( 628.0f/ 8, 82.0f/8,
127 1255.0f/ 8, 141.0f/8,
128 1883.0f/ 8, 202.0f/8)
129 .detach());
130
131 // flat cubic where the at end point tangents both point outward.
132 fPaths.push_back(b.moveTo(10, 0)
133 .cubicTo(0, 1, 30, 1, 20, 0)
134 .detach());
135
136 // flat cubic where initial tangent is in, end tangent out
137 fPaths.push_back(b.moveTo(0, 0)
138 .cubicTo(10, 1, 30, 1, 20, 0)
139 .detach());
140
141 // flat cubic where initial tangent is out, end tangent in
142 fPaths.push_back(b.moveTo(10, 0)
143 .cubicTo(0, 1, 20, 1, 30, 0)
144 .detach());
145
146 // triangle where one edge is a degenerate quad
147 fPaths.push_back(b.moveTo(8.59375f, 45)
148 .quadTo(16.9921875f, 45,
149 31.25f, 45)
150 .lineTo(100, 100)
151 .lineTo(8.59375f, 45)
152 .detach());
153
154 // triangle where one edge is a quad with a repeated point
155 fPaths.push_back(b.moveTo(0, 25)
156 .lineTo(50, 0)
157 .quadTo(50, 50, 50, 50)
158 .detach());
159
160 // triangle where one edge is a cubic with a 2x repeated point
161 fPaths.push_back(b.moveTo(0, 25)
162 .lineTo(50, 0)
163 .cubicTo(50, 0, 50, 50, 50, 50)
164 .detach());
165
166 // triangle where one edge is a quad with a nearly repeated point
167 fPaths.push_back(b.moveTo(0, 25)
168 .lineTo(50, 0)
169 .quadTo(50, 49.95f, 50, 50)
170 .detach());
171
172 // triangle where one edge is a cubic with a 3x nearly repeated point
173 fPaths.push_back(b.moveTo(0, 25)
174 .lineTo(50, 0)
175 .cubicTo(50, 49.95f, 50, 49.97f, 50, 50)
176 .detach());
177
178 // triangle where there is a point degenerate cubic at one corner
179 fPaths.push_back(b.moveTo(0, 25)
180 .lineTo(50, 0)
181 .lineTo(50, 50)
182 .cubicTo(50, 50, 50, 50, 50, 50)
183 .detach());
184
185 // point line
186 fPaths.push_back(SkPath::Line({50, 50}, {50, 50}));
187
188 // point quad
189 fPaths.push_back(b.moveTo(50, 50)
190 .quadTo(50, 50, 50, 50)
191 .detach());
192
193 // point cubic
194 fPaths.push_back(b.moveTo(50, 50)
195 .cubicTo(50, 50, 50, 50, 50, 50)
196 .detach());
197
198 // moveTo only paths
199 fPaths.push_back(b.moveTo(0, 0)
200 .moveTo(0, 0)
201 .moveTo(1, 1)
202 .moveTo(1, 1)
203 .moveTo(10, 10)
204 .detach());
205
206 fPaths.push_back(b.moveTo(0, 0)
207 .moveTo(0, 0)
208 .detach());
209
210 // line degenerate
211 fPaths.push_back(b.lineTo(100, 100).detach());
212 fPaths.push_back(b.quadTo(100, 100, 0, 0).detach());
213 fPaths.push_back(b.quadTo(100, 100, 50, 50).detach());
214 fPaths.push_back(b.quadTo(50, 50, 100, 100).detach());
215 fPaths.push_back(b.cubicTo(0, 0, 0, 0, 100, 100).detach());
216
217 // skbug.com/8928
218 fPaths.push_back(b.moveTo(16.875f, 192.594f)
219 .cubicTo(45.625f, 192.594f, 74.375f, 192.594f, 103.125f, 192.594f)
220 .cubicTo(88.75f, 167.708f, 74.375f, 142.823f, 60, 117.938f)
221 .cubicTo(45.625f, 142.823f, 31.25f, 167.708f, 16.875f, 192.594f)
222 .close()
223 .detach());
224 SkMatrix m;
225 m.setAll(0.1f, 0, -1, 0, 0.115207f, -2.64977f, 0, 0, 1);
226 fPaths.back().transform(m);
227
228 // small circle. This is listed last so that it has device coords far
229 // from the origin (small area relative to x,y values).
230 fPaths.push_back(SkPath::Circle(0, 0, 1.2f));
231 }
232
233 void onDraw(SkCanvas* canvas) override {
234 this->makePaths();
235
237 paint.setAntiAlias(true);
238 SkRandom rand;
239 canvas->translate(20, 20);
240
241 // As we've added more paths this has gotten pretty big. Scale the whole thing down.
242 canvas->scale(2.0f/3, 2.0f/3);
243
244 for (int i = 0; i < fPaths.size(); ++i) {
245 canvas->save();
246 // position the path, and make it at off-integer coords.
247 canvas->translate(200.0f * (i % 5) + 1.0f/10,
248 200.0f * (i / 5) + 9.0f/10);
249 SkColor color = rand.nextU();
250 color |= 0xff000000;
251 paint.setColor(color);
252#if 0 // This hitting on 32bit Linux builds for some paths. Temporarily disabling while it is
253 // debugged.
254 SkASSERT(fPaths[i].isConvex());
255#endif
256 canvas->drawPath(fPaths[i], paint);
257 canvas->restore();
258 }
259 }
260
261 TArray<SkPath> fPaths;
262};
263} // namespace
264
265DEF_GM( return new ConvexPathsGM; )
#define SkASSERT(cond)
Definition: SkAssert.h:116
uint32_t SkColor
Definition: SkColor.h:37
#define SkIntToScalar(x)
Definition: SkScalar.h:57
void restore()
Definition: SkCanvas.cpp:461
void translate(SkScalar dx, SkScalar dy)
Definition: SkCanvas.cpp:1278
int save()
Definition: SkCanvas.cpp:447
void drawPath(const SkPath &path, const SkPaint &paint)
Definition: SkCanvas.cpp:1747
void scale(SkScalar sx, SkScalar sy)
Definition: SkCanvas.cpp:1289
static SkPath RRect(const SkRRect &, SkPathDirection dir=SkPathDirection::kCW)
Definition: SkPath.cpp:3602
static SkPath Rect(const SkRect &, SkPathDirection=SkPathDirection::kCW, unsigned startIndex=0)
Definition: SkPath.cpp:3586
static SkPath Circle(SkScalar center_x, SkScalar center_y, SkScalar radius, SkPathDirection dir=SkPathDirection::kCW)
Definition: SkPath.cpp:3598
static SkPath Oval(const SkRect &, SkPathDirection=SkPathDirection::kCW)
Definition: SkPath.cpp:3590
static SkPath Polygon(const SkPoint pts[], int count, bool isClosed, SkPathFillType=SkPathFillType::kWinding, bool isVolatile=false)
Definition: SkPath.cpp:3614
static SkPath Line(const SkPoint a, const SkPoint b)
Definition: SkPath.h:106
static SkRRect MakeRectXY(const SkRect &rect, SkScalar xRad, SkScalar yRad)
Definition: SkRRect.h:180
uint32_t nextU()
Definition: SkRandom.h:42
Definition: gm.h:110
virtual SkISize getISize()=0
virtual void onOnceBeforeDraw()
Definition: gm.cpp:167
void setBGColor(SkColor)
Definition: gm.cpp:159
virtual SkString getName() const =0
virtual DrawResult onDraw(SkCanvas *, SkString *errorMsg)
Definition: gm.cpp:139
const Paint & paint
Definition: color_source.cc:38
DlColor color
static bool b
#define DEF_GM(CODE)
Definition: gm.h:40
static int kLength
Definition: SkSize.h:16
static constexpr SkRect MakeXYWH(float x, float y, float w, float h)
Definition: SkRect.h:659