| 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 |