Parse arc flags correctly when there is no optional ws
Today, if the arc command flags are not separated by whitespace, the parser fails to parse the string. I noticed this when trying to parse a path similar to the one in the test case when playing around with PathKit.FromSVGString. Change-Id: I40967c07dfa03d76d26ac2e060b3ef7ac488d0fc Reviewed-on: https://skia-review.googlesource.com/c/skia/+/520256 Reviewed-by: Florin Malita <fmalita@google.com> Commit-Queue: Dan Field <dnfield@google.com>
This commit is contained in:
parent
bd11ec8eab
commit
23cb294413
@ -72,6 +72,22 @@ static const char* find_scalar(const char str[], SkScalar* value,
|
|||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://www.w3.org/TR/SVG11/paths.html#PathDataBNF
|
||||||
|
//
|
||||||
|
// flag:
|
||||||
|
// "0" | "1"
|
||||||
|
static const char* find_flag(const char str[], bool* value) {
|
||||||
|
if (!str) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
if (str[0] != '1' && str[0] != '0') {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
*value = str[0] != '0';
|
||||||
|
str = skip_sep(str + 1);
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
bool SkParsePath::FromSVGString(const char data[], SkPath* result) {
|
bool SkParsePath::FromSVGString(const char data[], SkPath* result) {
|
||||||
SkPath path;
|
SkPath path;
|
||||||
SkPoint first = {0, 0};
|
SkPoint first = {0, 0};
|
||||||
@ -164,18 +180,19 @@ bool SkParsePath::FromSVGString(const char data[], SkPath* result) {
|
|||||||
break;
|
break;
|
||||||
case 'A': {
|
case 'A': {
|
||||||
SkPoint radii;
|
SkPoint radii;
|
||||||
SkScalar angle, largeArc, sweep;
|
SkScalar angle;
|
||||||
|
bool largeArc, sweep;
|
||||||
if ((data = find_points(data, &radii, 1, false, nullptr))
|
if ((data = find_points(data, &radii, 1, false, nullptr))
|
||||||
&& (data = skip_sep(data))
|
&& (data = skip_sep(data))
|
||||||
&& (data = find_scalar(data, &angle, false, 0))
|
&& (data = find_scalar(data, &angle, false, 0))
|
||||||
&& (data = skip_sep(data))
|
&& (data = skip_sep(data))
|
||||||
&& (data = find_scalar(data, &largeArc, false, 0))
|
&& (data = find_flag(data, &largeArc))
|
||||||
&& (data = skip_sep(data))
|
&& (data = skip_sep(data))
|
||||||
&& (data = find_scalar(data, &sweep, false, 0))
|
&& (data = find_flag(data, &sweep))
|
||||||
&& (data = skip_sep(data))
|
&& (data = skip_sep(data))
|
||||||
&& (data = find_points(data, &points[0], 1, relative, &c))) {
|
&& (data = find_points(data, &points[0], 1, relative, &c))) {
|
||||||
path.arcTo(radii, angle, (SkPath::ArcSize) SkToBool(largeArc),
|
path.arcTo(radii, angle, (SkPath::ArcSize) largeArc,
|
||||||
(SkPathDirection) !SkToBool(sweep), points[0]);
|
(SkPathDirection) !sweep, points[0]);
|
||||||
path.getLastPt(&c);
|
path.getLastPt(&c);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
@ -128,3 +128,13 @@ DEF_TEST(ParsePathOptionalCommand, r) {
|
|||||||
REPORTER_ASSERT(r, path.countPoints() == gTests[i].fPoints);
|
REPORTER_ASSERT(r, path.countPoints() == gTests[i].fPoints);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEF_TEST(ParsePathArcFlags, r) {
|
||||||
|
const char* arcs = "M10 10a2.143 2.143 0 100-4.285 2.143 2.143 0 000 4.286";
|
||||||
|
SkPath path;
|
||||||
|
REPORTER_ASSERT(r, SkParsePath::FromSVGString(arcs, &path));
|
||||||
|
// Arcs decompose to two conics.
|
||||||
|
REPORTER_ASSERT(r, path.countVerbs() == 5);
|
||||||
|
// One for move, 2x per conic.
|
||||||
|
REPORTER_ASSERT(r, path.countPoints() == 9);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user