Index: src/utils/SkParsePath.cpp |
diff --git a/src/utils/SkParsePath.cpp b/src/utils/SkParsePath.cpp |
index c0f39aa06fd74b93d4989234472ea4c7496211cf..8baa6611ee437abfbc0a058c56e18822501dd6e6 100644 |
--- a/src/utils/SkParsePath.cpp |
+++ b/src/utils/SkParsePath.cpp |
@@ -40,7 +40,9 @@ static const char* skip_ws(const char str[]) { |
} |
static const char* skip_sep(const char str[]) { |
- SkASSERT(str); |
+ if (!str) { |
+ return nullptr; |
+ } |
while (is_sep(*str)) |
str++; |
return str; |
@@ -61,6 +63,9 @@ static const char* find_points(const char str[], SkPoint value[], int count, |
static const char* find_scalar(const char str[], SkScalar* value, |
bool isRelative, SkScalar relative) { |
str = SkParse::FindScalar(str, value); |
+ if (!str) { |
+ return nullptr; |
+ } |
if (isRelative) { |
*value += relative; |
} |
@@ -70,7 +75,7 @@ static const char* find_scalar(const char str[], SkScalar* value, |
bool SkParsePath::FromSVGString(const char data[], SkPath* result) { |
SkPath path; |
- SkPoint f = {0, 0}; |
+ SkPoint first = {0, 0}; |
SkPoint c = {0, 0}; |
SkPoint lastc = {0, 0}; |
SkPoint points[3]; |
@@ -107,6 +112,7 @@ bool SkParsePath::FromSVGString(const char data[], SkPath* result) { |
case 'M': |
data = find_points(data, points, 1, relative, &c); |
path.moveTo(points[0]); |
+ previousOp = '\0'; |
op = 'L'; |
c = points[0]; |
break; |
@@ -147,10 +153,10 @@ bool SkParsePath::FromSVGString(const char data[], SkPath* result) { |
goto quadraticCommon; |
case 'T': |
data = find_points(data, &points[1], 1, relative, &c); |
- points[0] = points[1]; |
+ points[0] = c; |
if (previousOp == 'Q' || previousOp == 'T') { |
- points[0].fX = c.fX * 2 - lastc.fX; |
- points[0].fY = c.fY * 2 - lastc.fY; |
+ points[0].fX -= lastc.fX - c.fX; |
+ points[0].fY -= lastc.fY - c.fY; |
} |
quadraticCommon: |
path.quadTo(points[0], points[1]); |
@@ -159,27 +165,24 @@ bool SkParsePath::FromSVGString(const char data[], SkPath* result) { |
break; |
case 'A': { |
SkPoint radii; |
- data = find_points(data, &radii, 1, false, nullptr); |
SkScalar angle, largeArc, sweep; |
- data = find_scalar(data, &angle, false, 0); |
- data = find_scalar(data, &largeArc, false, 0); |
- data = find_scalar(data, &sweep, false, 0); |
- data = find_points(data, &points[0], 1, relative, &c); |
- path.arcTo(radii, angle, (SkPath::ArcSize) SkToBool(largeArc), |
- (SkPath::Direction) !SkToBool(sweep), points[0]); |
+ if ((data = find_points(data, &radii, 1, false, nullptr)) |
+ && (data = skip_sep(data)) |
+ && (data = find_scalar(data, &angle, false, 0)) |
+ && (data = skip_sep(data)) |
+ && (data = find_scalar(data, &largeArc, false, 0)) |
+ && (data = skip_sep(data)) |
+ && (data = find_scalar(data, &sweep, false, 0)) |
+ && (data = skip_sep(data)) |
+ && (data = find_points(data, &points[0], 1, relative, &c))) { |
+ path.arcTo(radii, angle, (SkPath::ArcSize) SkToBool(largeArc), |
+ (SkPath::Direction) !SkToBool(sweep), points[0]); |
+ path.getLastPt(&c); |
+ } |
} break; |
case 'Z': |
path.close(); |
-#if 0 // !!! still a bug? |
- if (fPath.isEmpty() && (f.fX != 0 || f.fY != 0)) { |
- c.fX -= SkScalar.Epsilon; // !!! enough? |
- fPath.moveTo(c); |
- fPath.lineTo(f); |
- fPath.close(); |
- } |
-#endif |
- c = f; |
- op = '\0'; |
+ c = first; |
break; |
case '~': { |
SkPoint args[2]; |
@@ -191,7 +194,7 @@ bool SkParsePath::FromSVGString(const char data[], SkPath* result) { |
return false; |
} |
if (previousOp == 0) { |
- f = c; |
+ first = c; |
} |
previousOp = op; |
} |