Flutter Engine
The Flutter Engine
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
Public Types | Static Public Member Functions | List of all members
SkParsePath Class Reference

#include <SkParsePath.h>

Public Types

enum class  PathEncoding { Absolute , Relative }
 

Static Public Member Functions

static bool FromSVGString (const char str[], SkPath *)
 
static SkString ToSVGString (const SkPath &, PathEncoding=PathEncoding::Absolute)
 

Detailed Description

Definition at line 17 of file SkParsePath.h.

Member Enumeration Documentation

◆ PathEncoding

enum class SkParsePath::PathEncoding
strong
Enumerator
Absolute 
Relative 

Definition at line 21 of file SkParsePath.h.

21{ Absolute, Relative };
constexpr T Absolute(const T &val)
Definition: scalar.h:21

Member Function Documentation

◆ FromSVGString()

bool SkParsePath::FromSVGString ( const char  str[],
SkPath result 
)
static

Definition at line 107 of file SkParsePath.cpp.

107 {
108 // We will write all data to this local path and only write it
109 // to result if the whole parsing succeeds.
110 SkPath path;
111 SkPoint first = {0, 0};
112 SkPoint c = {0, 0};
113 SkPoint lastc = {0, 0};
114 // We will use find_points and find_scalar to read into these.
115 // There might not be enough data to fill them, so to avoid
116 // MSAN warnings about using uninitialized bytes, we initialize
117 // them there.
118 SkPoint points[3] = {};
119 SkScalar scratch = 0;
120 char op = '\0';
121 char previousOp = '\0';
122 bool relative = false;
123 for (;;) {
124 if (!data) {
125 // Truncated data
126 return false;
127 }
128 data = skip_ws(data);
129 if (data[0] == '\0') {
130 break;
131 }
132 char ch = data[0];
133 if (is_digit(ch) || ch == '-' || ch == '+' || ch == '.') {
134 if (op == '\0' || op == 'Z') {
135 return false;
136 }
137 } else if (is_sep(ch)) {
138 data = skip_sep(data);
139 } else {
140 op = ch;
141 relative = false;
142 if (is_lower(op)) {
143 op = (char) to_upper(op);
144 relative = true;
145 }
146 data++;
147 data = skip_sep(data);
148 }
149 switch (op) {
150 case 'M': // Move
151 data = find_points(data, points, 1, relative, &c);
152 // find_points might have failed, so this might be the
153 // previous point. However, data will be set to nullptr
154 // if it failed, so we will check this at the top of the loop.
155 path.moveTo(points[0]);
156 previousOp = '\0';
157 op = 'L';
158 c = points[0];
159 break;
160 case 'L': // Line
161 data = find_points(data, points, 1, relative, &c);
162 path.lineTo(points[0]);
163 c = points[0];
164 break;
165 case 'H': // Horizontal Line
166 data = find_scalar(data, &scratch, relative, c.fX);
167 // Similarly, if there wasn't a scalar to read, data will
168 // be set to nullptr and this lineTo is bogus but will
169 // be ultimately ignored when the next time through the loop
170 // detects that and bails out.
171 path.lineTo(scratch, c.fY);
172 c.fX = scratch;
173 break;
174 case 'V': // Vertical Line
175 data = find_scalar(data, &scratch, relative, c.fY);
176 path.lineTo(c.fX, scratch);
177 c.fY = scratch;
178 break;
179 case 'C': // Cubic Bezier Curve
180 data = find_points(data, points, 3, relative, &c);
181 goto cubicCommon;
182 case 'S': // Continued "Smooth" Cubic Bezier Curve
183 data = find_points(data, &points[1], 2, relative, &c);
184 points[0] = c;
185 if (previousOp == 'C' || previousOp == 'S') {
186 points[0].fX -= lastc.fX - c.fX;
187 points[0].fY -= lastc.fY - c.fY;
188 }
189 cubicCommon:
190 path.cubicTo(points[0], points[1], points[2]);
191 lastc = points[1];
192 c = points[2];
193 break;
194 case 'Q': // Quadratic Bezier Curve
195 data = find_points(data, points, 2, relative, &c);
196 goto quadraticCommon;
197 case 'T': // Continued Quadratic Bezier Curve
198 data = find_points(data, &points[1], 1, relative, &c);
199 points[0] = c;
200 if (previousOp == 'Q' || previousOp == 'T') {
201 points[0].fX -= lastc.fX - c.fX;
202 points[0].fY -= lastc.fY - c.fY;
203 }
204 quadraticCommon:
205 path.quadTo(points[0], points[1]);
206 lastc = points[0];
207 c = points[1];
208 break;
209 case 'A': { // Arc (Elliptical)
210 SkPoint radii;
211 SkScalar angle;
212 bool largeArc, sweep;
213 if ((data = find_points(data, &radii, 1, false, nullptr))
214 && (data = skip_sep(data))
215 && (data = find_scalar(data, &angle, false, 0))
216 && (data = skip_sep(data))
217 && (data = find_flag(data, &largeArc))
218 && (data = skip_sep(data))
219 && (data = find_flag(data, &sweep))
220 && (data = skip_sep(data))
221 && (data = find_points(data, &points[0], 1, relative, &c))) {
222 path.arcTo(radii, angle, (SkPath::ArcSize) largeArc,
223 (SkPathDirection) !sweep, points[0]);
224 path.getLastPt(&c);
225 }
226 } break;
227 case 'Z': // Close Path
228 path.close();
229 c = first;
230 break;
231 default:
232 return false;
233 }
234 if (previousOp == 0) {
235 first = c;
236 }
237 previousOp = op;
238 }
239 // we're good, go ahead and swap in the result
240 result->swap(path);
241 return true;
242}
static const int points[]
static bool is_sep(int c)
Definition: SkParsePath.cpp:34
static const char * skip_sep(const char str[])
Definition: SkParsePath.cpp:53
static int to_upper(int c)
Definition: SkParsePath.cpp:42
static bool is_digit(int c)
Definition: SkParsePath.cpp:30
static const char * find_flag(const char str[], bool *value)
Definition: SkParsePath.cpp:95
static const char * skip_ws(const char str[])
Definition: SkParsePath.cpp:46
static const char * find_scalar(const char str[], SkScalar *value, bool isRelative, SkScalar relative)
Definition: SkParsePath.cpp:78
static const char * find_points(const char str[], SkPoint value[], int count, bool isRelative, SkPoint *relative)
Definition: SkParsePath.cpp:64
static bool is_lower(int c)
Definition: SkParsePath.cpp:38
SkPathDirection
Definition: SkPathTypes.h:34
Definition: SkPath.h:59
ArcSize
Definition: SkPath.h:923
float SkScalar
Definition: extension.cpp:12
GAsyncResult * result
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
Definition: switches.h:57
float fX
x-axis value
Definition: SkPoint_impl.h:164
float fY
y-axis value
Definition: SkPoint_impl.h:165
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:63

◆ ToSVGString()

SkString SkParsePath::ToSVGString ( const SkPath path,
PathEncoding  encoding = PathEncoding::Absolute 
)
static

Definition at line 246 of file SkParsePath.cpp.

246 {
248
249 SkPoint current_point{0,0};
250 const auto rel_selector = encoding == PathEncoding::Relative;
251
252 const auto append_command = [&](char cmd, const SkPoint pts[], size_t count) {
253 // Use lower case cmds for relative encoding.
254 cmd += 32 * rel_selector;
255 stream.write(&cmd, 1);
256
257 for (size_t i = 0; i < count; ++i) {
258 const auto pt = pts[i] - current_point;
259 if (i > 0) {
260 stream.write(" ", 1);
261 }
262 stream.writeScalarAsText(pt.fX);
263 stream.write(" ", 1);
264 stream.writeScalarAsText(pt.fY);
265 }
266
267 SkASSERT(count > 0);
268 // For relative encoding, track the current point (otherwise == origin).
269 current_point = pts[count - 1] * rel_selector;
270 };
271
272 SkPath::Iter iter(path, false);
273 SkPoint pts[4];
274
275 for (;;) {
276 switch (iter.next(pts)) {
277 case SkPath::kConic_Verb: {
278 const SkScalar tol = SK_Scalar1 / 1024; // how close to a quad
279 SkAutoConicToQuads quadder;
280 const SkPoint* quadPts = quadder.computeQuads(pts, iter.conicWeight(), tol);
281 for (int i = 0; i < quadder.countQuads(); ++i) {
282 append_command('Q', &quadPts[i*2 + 1], 2);
283 }
284 } break;
286 append_command('M', &pts[0], 1);
287 break;
289 append_command('L', &pts[1], 1);
290 break;
292 append_command('Q', &pts[1], 2);
293 break;
295 append_command('C', &pts[1], 3);
296 break;
298 stream.write("Z", 1);
299 break;
300 case SkPath::kDone_Verb: {
301 SkString str;
302 str.resize(stream.bytesWritten());
303 stream.copyTo(str.data());
304 return str;
305 }
306 }
307 }
308}
int count
Definition: FontMgrTest.cpp:50
#define SkASSERT(cond)
Definition: SkAssert.h:116
#define SK_Scalar1
Definition: SkScalar.h:18
const SkPoint * computeQuads(const SkConic &conic, SkScalar tol)
Definition: SkGeometry.h:524
int countQuads() const
Definition: SkGeometry.h:539
@ kClose_Verb
Definition: SkPath.h:1471
@ kMove_Verb
Definition: SkPath.h:1466
@ kConic_Verb
Definition: SkPath.h:1469
@ kDone_Verb
Definition: SkPath.h:1472
@ kCubic_Verb
Definition: SkPath.h:1470
@ kQuad_Verb
Definition: SkPath.h:1468
@ kLine_Verb
Definition: SkPath.h:1467
const char * data() const
Definition: SkString.h:132
void resize(size_t len)
Definition: SkString.cpp:374

The documentation for this class was generated from the following files: