OLD | NEW |
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2011 Google Inc. | 3 * Copyright 2011 Google Inc. |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 */ | 7 */ |
8 #include "SkParse.h" | 8 #include "SkParse.h" |
9 #include "SkParsePath.h" | 9 #include "SkParsePath.h" |
10 | 10 |
(...skipping 22 matching lines...) Expand all Loading... |
33 } | 33 } |
34 | 34 |
35 static const char* skip_ws(const char str[]) { | 35 static const char* skip_ws(const char str[]) { |
36 SkASSERT(str); | 36 SkASSERT(str); |
37 while (is_ws(*str)) | 37 while (is_ws(*str)) |
38 str++; | 38 str++; |
39 return str; | 39 return str; |
40 } | 40 } |
41 | 41 |
42 static const char* skip_sep(const char str[]) { | 42 static const char* skip_sep(const char str[]) { |
43 SkASSERT(str); | 43 if (!str) { |
| 44 return nullptr; |
| 45 } |
44 while (is_sep(*str)) | 46 while (is_sep(*str)) |
45 str++; | 47 str++; |
46 return str; | 48 return str; |
47 } | 49 } |
48 | 50 |
49 static const char* find_points(const char str[], SkPoint value[], int count, | 51 static const char* find_points(const char str[], SkPoint value[], int count, |
50 bool isRelative, SkPoint* relative) { | 52 bool isRelative, SkPoint* relative) { |
51 str = SkParse::FindScalars(str, &value[0].fX, count * 2); | 53 str = SkParse::FindScalars(str, &value[0].fX, count * 2); |
52 if (isRelative) { | 54 if (isRelative) { |
53 for (int index = 0; index < count; index++) { | 55 for (int index = 0; index < count; index++) { |
54 value[index].fX += relative->fX; | 56 value[index].fX += relative->fX; |
55 value[index].fY += relative->fY; | 57 value[index].fY += relative->fY; |
56 } | 58 } |
57 } | 59 } |
58 return str; | 60 return str; |
59 } | 61 } |
60 | 62 |
61 static const char* find_scalar(const char str[], SkScalar* value, | 63 static const char* find_scalar(const char str[], SkScalar* value, |
62 bool isRelative, SkScalar relative) { | 64 bool isRelative, SkScalar relative) { |
63 str = SkParse::FindScalar(str, value); | 65 str = SkParse::FindScalar(str, value); |
| 66 if (!str) { |
| 67 return nullptr; |
| 68 } |
64 if (isRelative) { | 69 if (isRelative) { |
65 *value += relative; | 70 *value += relative; |
66 } | 71 } |
67 str = skip_sep(str); | 72 str = skip_sep(str); |
68 return str; | 73 return str; |
69 } | 74 } |
70 | 75 |
71 bool SkParsePath::FromSVGString(const char data[], SkPath* result) { | 76 bool SkParsePath::FromSVGString(const char data[], SkPath* result) { |
72 SkPath path; | 77 SkPath path; |
73 SkPoint f = {0, 0}; | 78 SkPoint first = {0, 0}; |
74 SkPoint c = {0, 0}; | 79 SkPoint c = {0, 0}; |
75 SkPoint lastc = {0, 0}; | 80 SkPoint lastc = {0, 0}; |
76 SkPoint points[3]; | 81 SkPoint points[3]; |
77 char op = '\0'; | 82 char op = '\0'; |
78 char previousOp = '\0'; | 83 char previousOp = '\0'; |
79 bool relative = false; | 84 bool relative = false; |
80 for (;;) { | 85 for (;;) { |
81 if (!data) { | 86 if (!data) { |
82 // Truncated data | 87 // Truncated data |
83 return false; | 88 return false; |
(...skipping 16 matching lines...) Expand all Loading... |
100 op = (char) to_upper(op); | 105 op = (char) to_upper(op); |
101 relative = true; | 106 relative = true; |
102 } | 107 } |
103 data++; | 108 data++; |
104 data = skip_sep(data); | 109 data = skip_sep(data); |
105 } | 110 } |
106 switch (op) { | 111 switch (op) { |
107 case 'M': | 112 case 'M': |
108 data = find_points(data, points, 1, relative, &c); | 113 data = find_points(data, points, 1, relative, &c); |
109 path.moveTo(points[0]); | 114 path.moveTo(points[0]); |
| 115 previousOp = '\0'; |
110 op = 'L'; | 116 op = 'L'; |
111 c = points[0]; | 117 c = points[0]; |
112 break; | 118 break; |
113 case 'L': | 119 case 'L': |
114 data = find_points(data, points, 1, relative, &c); | 120 data = find_points(data, points, 1, relative, &c); |
115 path.lineTo(points[0]); | 121 path.lineTo(points[0]); |
116 c = points[0]; | 122 c = points[0]; |
117 break; | 123 break; |
118 case 'H': { | 124 case 'H': { |
119 SkScalar x; | 125 SkScalar x; |
(...skipping 20 matching lines...) Expand all Loading... |
140 cubicCommon: | 146 cubicCommon: |
141 path.cubicTo(points[0], points[1], points[2]); | 147 path.cubicTo(points[0], points[1], points[2]); |
142 lastc = points[1]; | 148 lastc = points[1]; |
143 c = points[2]; | 149 c = points[2]; |
144 break; | 150 break; |
145 case 'Q': // Quadratic Bezier Curve | 151 case 'Q': // Quadratic Bezier Curve |
146 data = find_points(data, points, 2, relative, &c); | 152 data = find_points(data, points, 2, relative, &c); |
147 goto quadraticCommon; | 153 goto quadraticCommon; |
148 case 'T': | 154 case 'T': |
149 data = find_points(data, &points[1], 1, relative, &c); | 155 data = find_points(data, &points[1], 1, relative, &c); |
150 points[0] = points[1]; | 156 points[0] = c; |
151 if (previousOp == 'Q' || previousOp == 'T') { | 157 if (previousOp == 'Q' || previousOp == 'T') { |
152 points[0].fX = c.fX * 2 - lastc.fX; | 158 points[0].fX -= lastc.fX - c.fX; |
153 points[0].fY = c.fY * 2 - lastc.fY; | 159 points[0].fY -= lastc.fY - c.fY; |
154 } | 160 } |
155 quadraticCommon: | 161 quadraticCommon: |
156 path.quadTo(points[0], points[1]); | 162 path.quadTo(points[0], points[1]); |
157 lastc = points[0]; | 163 lastc = points[0]; |
158 c = points[1]; | 164 c = points[1]; |
159 break; | 165 break; |
160 case 'A': { | 166 case 'A': { |
161 SkPoint radii; | 167 SkPoint radii; |
162 data = find_points(data, &radii, 1, false, nullptr); | |
163 SkScalar angle, largeArc, sweep; | 168 SkScalar angle, largeArc, sweep; |
164 data = find_scalar(data, &angle, false, 0); | 169 if ((data = find_points(data, &radii, 1, false, nullptr)) |
165 data = find_scalar(data, &largeArc, false, 0); | 170 && (data = skip_sep(data)) |
166 data = find_scalar(data, &sweep, false, 0); | 171 && (data = find_scalar(data, &angle, false, 0)) |
167 data = find_points(data, &points[0], 1, relative, &c); | 172 && (data = skip_sep(data)) |
168 path.arcTo(radii, angle, (SkPath::ArcSize) SkToBool(largeArc), | 173 && (data = find_scalar(data, &largeArc, false, 0)) |
169 (SkPath::Direction) !SkToBool(sweep), points[0]); | 174 && (data = skip_sep(data)) |
| 175 && (data = find_scalar(data, &sweep, false, 0)) |
| 176 && (data = skip_sep(data)) |
| 177 && (data = find_points(data, &points[0], 1, relative, &c
))) { |
| 178 path.arcTo(radii, angle, (SkPath::ArcSize) SkToBool(largeArc
), |
| 179 (SkPath::Direction) !SkToBool(sweep), points[0]); |
| 180 path.getLastPt(&c); |
| 181 } |
170 } break; | 182 } break; |
171 case 'Z': | 183 case 'Z': |
172 path.close(); | 184 path.close(); |
173 #if 0 // !!! still a bug? | 185 c = first; |
174 if (fPath.isEmpty() && (f.fX != 0 || f.fY != 0)) { | |
175 c.fX -= SkScalar.Epsilon; // !!! enough? | |
176 fPath.moveTo(c); | |
177 fPath.lineTo(f); | |
178 fPath.close(); | |
179 } | |
180 #endif | |
181 c = f; | |
182 op = '\0'; | |
183 break; | 186 break; |
184 case '~': { | 187 case '~': { |
185 SkPoint args[2]; | 188 SkPoint args[2]; |
186 data = find_points(data, args, 2, false, nullptr); | 189 data = find_points(data, args, 2, false, nullptr); |
187 path.moveTo(args[0].fX, args[0].fY); | 190 path.moveTo(args[0].fX, args[0].fY); |
188 path.lineTo(args[1].fX, args[1].fY); | 191 path.lineTo(args[1].fX, args[1].fY); |
189 } break; | 192 } break; |
190 default: | 193 default: |
191 return false; | 194 return false; |
192 } | 195 } |
193 if (previousOp == 0) { | 196 if (previousOp == 0) { |
194 f = c; | 197 first = c; |
195 } | 198 } |
196 previousOp = op; | 199 previousOp = op; |
197 } | 200 } |
198 // we're good, go ahead and swap in the result | 201 // we're good, go ahead and swap in the result |
199 result->swap(path); | 202 result->swap(path); |
200 return true; | 203 return true; |
201 } | 204 } |
202 | 205 |
203 /////////////////////////////////////////////////////////////////////////////// | 206 /////////////////////////////////////////////////////////////////////////////// |
204 | 207 |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
258 case SkPath::kClose_Verb: | 261 case SkPath::kClose_Verb: |
259 stream.write("Z", 1); | 262 stream.write("Z", 1); |
260 break; | 263 break; |
261 case SkPath::kDone_Verb: | 264 case SkPath::kDone_Verb: |
262 str->resize(stream.getOffset()); | 265 str->resize(stream.getOffset()); |
263 stream.copyTo(str->writable_str()); | 266 stream.copyTo(str->writable_str()); |
264 return; | 267 return; |
265 } | 268 } |
266 } | 269 } |
267 } | 270 } |
OLD | NEW |