43{
44 if (!s.isEmpty()) {
48
49 const QByteArray buffer =
d.toLatin1();
50 const char *ptr = buffer.constData();
51 const char *end = buffer.constData() + buffer.length() + 1;
52
53 qreal curx = 0.0;
54 qreal cury = 0.0;
55 qreal contrlx, contrly, subpathx, subpathy, tox, toy, x1, y1, x2, y2, xc, yc;
56 qreal px1, py1, px2, py2, px3, py3;
57 bool relative;
58 char command = *(ptr++), lastCommand = ' ';
59
60 subpathx = subpathy = curx = cury = contrlx = contrly = 0.0;
61 while (ptr < end) {
62 if (*ptr == ' ')
63 ++ptr;
64
65 relative = false;
66
67 switch (command) {
68 case 'm':
69 relative = true;
70 Q_FALLTHROUGH();
71 case 'M': {
74
75 if (process) {
76 subpathx = curx = relative ? curx + tox : tox;
77 subpathy = cury = relative ? cury + toy : toy;
78
80 } else
82 break;
83 }
84 case 'l':
85 relative = true;
86 Q_FALLTHROUGH();
87 case 'L': {
90
91 if (process) {
92 curx = relative ? curx + tox : tox;
93 cury = relative ? cury + toy : toy;
94
96 } else
98 break;
99 }
100 case 'h': {
102 if (process) {
103 curx = curx + tox;
105 } else
107 break;
108 }
109 case 'H': {
111 if (process) {
112 curx = tox;
114 } else
116 break;
117 }
118 case 'v': {
120 if (process) {
121 cury = cury + toy;
123 } else
125 break;
126 }
127 case 'V': {
129 if (process) {
130 cury = toy;
132 } else
134 break;
135 }
136 case 'z':
137 Q_FALLTHROUGH();
138 case 'Z': {
139
140 if (process) {
141 curx = subpathx;
142 cury = subpathy;
143 }
145 break;
146 }
147 case 'c':
148 relative = true;
149 Q_FALLTHROUGH();
150 case 'C': {
157
158 if (process) {
159 px1 = relative ? curx + x1 : x1;
160 py1 = relative ? cury + y1 : y1;
161 px2 = relative ? curx + x2 : x2;
162 py2 = relative ? cury + y2 : y2;
163 px3 = relative ? curx + tox : tox;
164 py3 = relative ? cury + toy : toy;
165
167
168 contrlx = relative ? curx + x2 : x2;
169 contrly = relative ? cury + y2 : y2;
170 curx = relative ? curx + tox : tox;
171 cury = relative ? cury + toy : toy;
172 } else
174
175 break;
176 }
177 case 's':
178 relative = true;
179 Q_FALLTHROUGH();
180 case 'S': {
185 if (!(lastCommand == 'c' || lastCommand == 'C' ||
186 lastCommand == 's' || lastCommand == 'S')) {
187 contrlx = curx;
188 contrly = cury;
189 }
190
191 if (process) {
192 px1 = 2 * curx - contrlx;
193 py1 = 2 * cury - contrly;
194 px2 = relative ? curx + x2 : x2;
195 py2 = relative ? cury + y2 : y2;
196 px3 = relative ? curx + tox : tox;
197 py3 = relative ? cury + toy : toy;
198
200
201 contrlx = relative ? curx + x2 : x2;
202 contrly = relative ? cury + y2 : y2;
203 curx = relative ? curx + tox : tox;
204 cury = relative ? cury + toy : toy;
205 } else
207 break;
208 }
209 case 'q':
210 relative = true;
211 Q_FALLTHROUGH();
212 case 'Q': {
217
218 if (process) {
219 px1 = relative ? (curx + 2 * (x1 + curx)) * (1.0 / 3.0) : (curx + 2 * x1) * (1.0 / 3.0);
220 py1 = relative ? (cury + 2 * (y1 + cury)) * (1.0 / 3.0) : (cury + 2 * y1) * (1.0 / 3.0);
221 px2 = relative ? ((curx + tox) + 2 * (x1 + curx)) * (1.0 / 3.0) : (tox + 2 * x1) * (1.0 / 3.0);
222 py2 = relative ? ((cury + toy) + 2 * (y1 + cury)) * (1.0 / 3.0) : (toy + 2 * y1) * (1.0 / 3.0);
223 px3 = relative ? curx + tox : tox;
224 py3 = relative ? cury + toy : toy;
225
227
228 contrlx = relative ? curx + x1 : x1;
229 contrly = relative ? cury + y1 : y1;
230 curx = relative ? curx + tox : tox;
231 cury = relative ? cury + toy : toy;
232 } else
234 break;
235 }
236 case 't':
237 relative = true;
238 Q_FALLTHROUGH();
239 case 'T': {
242 if (!(lastCommand == 'q' || lastCommand == 'Q' ||
243 lastCommand == 't' || lastCommand == 'T')) {
244 contrlx = curx;
245 contrly = cury;
246 }
247
248 if (process) {
249 xc = 2 * curx - contrlx;
250 yc = 2 * cury - contrly;
251
252 px1 = (curx + 2 * xc) * (1.0 / 3.0);
253 py1 = (cury + 2 * yc) * (1.0 / 3.0);
254 px2 = relative ? ((curx + tox) + 2 * xc) * (1.0 / 3.0) : (tox + 2 * xc) * (1.0 / 3.0);
255 py2 = relative ? ((cury + toy) + 2 * yc) * (1.0 / 3.0) : (toy + 2 * yc) * (1.0 / 3.0);
256 px3 = relative ? curx + tox : tox;
257 py3 = relative ? cury + toy : toy;
258
260
261 contrlx = xc;
262 contrly = yc;
263 curx = relative ? curx + tox : tox;
264 cury = relative ? cury + toy : toy;
265 } else
267 break;
268 }
269 case 'a':
270 relative = true;
271 Q_FALLTHROUGH();
272 case 'A': {
273 bool largeArc = false;
274 bool sweep = false;
275 qreal angle, rx, ry;
283
284
285 rx = fabs(rx);
286 ry = fabs(ry);
287
288 if (process)
289 calculateArc(relative, curx, cury, angle, tox, toy, rx, ry, largeArc, sweep);
290 else
291 svgArcTo(tox, toy, rx, ry, angle, largeArc, sweep, !relative);
292 break;
293 }
294 default: {
295
296
297 debugFlake <<
"KoSvgPathParser::parseSVG(): unknown command \"" << command <<
"\"";
298 return;
299 }
300 }
301
302 lastCommand = command;
303
304 if (*ptr == '+' || *ptr == '-' || *ptr == '.' || (*ptr >= '0' && *ptr <= '9')) {
305
306 if (command == 'M')
307 command = 'L';
308 else if (command == 'm')
309 command = 'l';
310 } else
311 command = *(ptr++);
312
313 if (lastCommand != 'C' && lastCommand != 'c' &&
314 lastCommand != 'S' && lastCommand != 's' &&
315 lastCommand != 'Q' && lastCommand != 'q' &&
316 lastCommand != 'T' && lastCommand != 't') {
317 contrlx = curx;
318 contrly = cury;
319 }
320 }
321 }
322}
const char * getFlag(const char *ptr, bool &flag)
void svgCurveToQuadraticSmooth(qreal x, qreal y, bool abs=true)
void svgArcTo(qreal x, qreal y, qreal r1, qreal r2, qreal angle, bool largeArcFlag, bool sweepFlag, bool abs=true)
void svgCurveToQuadratic(qreal x, qreal y, qreal x1, qreal y1, bool abs=true)
void calculateArc(bool relative, qreal &curx, qreal &cury, qreal angle, qreal x, qreal y, qreal r1, qreal r2, bool largeArcFlag, bool sweepFlag)
void svgCurveToCubicSmooth(qreal x, qreal y, qreal x2, qreal y2, bool abs=true)
void svgMoveTo(qreal x1, qreal y1, bool abs=true)
void svgLineToHorizontal(qreal x, bool abs=true)
const char * getCoord(const char *, qreal &)
void svgLineToVertical(qreal y, bool abs=true)