20#include "svgpathparser.h"
27SVGPathParser::getCoord(
const char *ptr,
double &number )
29 int integer, exponent;
50 while(*ptr !=
'\0' && *ptr >=
'0' && *ptr <=
'9')
51 integer = (integer * 10) + *(ptr++) -
'0';
55 while(*ptr !=
'\0' && *ptr >=
'0' && *ptr <=
'9')
56 decimal += (*(ptr++) -
'0') * (frac *= 0.1);
59 if(*ptr ==
'e' || *ptr ==
'E')
73 while(*ptr !=
'\0' && *ptr >=
'0' && *ptr <=
'9')
76 exponent += *ptr -
'0';
80 number = integer + decimal;
81 number *= sign * pow( (
double)10,
double( expsign * exponent ) );
91SVGPathParser::parseSVG(
const TQString &s,
bool process )
96 d = d.replace(
',',
' ' );
97 d = d.simplifyWhiteSpace();
99 const char *ptr = d.latin1();
100 const char *end = d.latin1() + d.length() + 1;
102 double contrlx, contrly, curx, cury, subpathx, subpathy, tox, toy, x1, y1, x2, y2, xc, yc;
103 double px1, py1, px2, py2, px3, py3;
105 char command = *(ptr++), lastCommand =
' ';
107 subpathx = subpathy = curx = cury = contrlx = contrly = 0.0;
122 ptr = getCoord( ptr, tox );
123 ptr = getCoord( ptr, toy );
127 subpathx = curx = relative ? curx + tox : tox;
128 subpathy = cury = relative ? cury + toy : toy;
130 svgMoveTo( curx, cury );
133 svgMoveTo( tox, toy, !relative );
140 ptr = getCoord( ptr, tox );
141 ptr = getCoord( ptr, toy );
145 curx = relative ? curx + tox : tox;
146 cury = relative ? cury + toy : toy;
148 svgLineTo( curx, cury );
151 svgLineTo( tox, toy, !relative );
156 ptr = getCoord( ptr, tox );
160 svgLineTo( curx, cury );
163 svgLineToHorizontal( tox,
false );
168 ptr = getCoord( ptr, tox );
172 svgLineTo( curx, cury );
175 svgLineToHorizontal( tox );
180 ptr = getCoord( ptr, toy );
184 svgLineTo( curx, cury );
187 svgLineToVertical( toy,
false );
192 ptr = getCoord( ptr, toy );
196 svgLineTo( curx, cury );
199 svgLineToVertical( toy );
218 ptr = getCoord( ptr, x1 );
219 ptr = getCoord( ptr, y1 );
220 ptr = getCoord( ptr, x2 );
221 ptr = getCoord( ptr, y2 );
222 ptr = getCoord( ptr, tox );
223 ptr = getCoord( ptr, toy );
227 px1 = relative ? curx + x1 : x1;
228 py1 = relative ? cury + y1 : y1;
229 px2 = relative ? curx + x2 : x2;
230 py2 = relative ? cury + y2 : y2;
231 px3 = relative ? curx + tox : tox;
232 py3 = relative ? cury + toy : toy;
234 svgCurveToCubic( px1, py1, px2, py2, px3, py3 );
236 contrlx = relative ? curx + x2 : x2;
237 contrly = relative ? cury + y2 : y2;
238 curx = relative ? curx + tox : tox;
239 cury = relative ? cury + toy : toy;
242 svgCurveToCubic( x1, y1, x2, y2, tox, toy, !relative );
250 ptr = getCoord( ptr, x2 );
251 ptr = getCoord( ptr, y2 );
252 ptr = getCoord( ptr, tox );
253 ptr = getCoord( ptr, toy );
254 if( !( lastCommand ==
'c' || lastCommand ==
'C' ||
255 lastCommand ==
's' || lastCommand ==
'S' ) )
264 px1 = 2 * curx - contrlx;
265 py1 = 2 * cury - contrly;
266 px2 = relative ? curx + x2 : x2;
267 py2 = relative ? cury + y2 : y2;
268 px3 = relative ? curx + tox : tox;
269 py3 = relative ? cury + toy : toy;
271 svgCurveToCubic( px1, py1, px2, py2, px3, py3 );
273 contrlx = relative ? curx + x2 : x2;
274 contrly = relative ? cury + y2 : y2;
275 curx = relative ? curx + tox : tox;
276 cury = relative ? cury + toy : toy;
279 svgCurveToCubicSmooth( x2, y2, tox, toy, !relative );
286 ptr = getCoord( ptr, x1 );
287 ptr = getCoord( ptr, y1 );
288 ptr = getCoord( ptr, tox );
289 ptr = getCoord( ptr, toy );
293 px1 = relative ? (curx + 2 * (x1 + curx)) * (1.0 / 3.0) : (curx + 2 * x1) * (1.0 / 3.0);
294 py1 = relative ? (cury + 2 * (y1 + cury)) * (1.0 / 3.0) : (cury + 2 * y1) * (1.0 / 3.0);
295 px2 = relative ? ((curx + tox) + 2 * (x1 + curx)) * (1.0 / 3.0) : (tox + 2 * x1) * (1.0 / 3.0);
296 py2 = relative ? ((cury + toy) + 2 * (y1 + cury)) * (1.0 / 3.0) : (toy + 2 * y1) * (1.0 / 3.0);
297 px3 = relative ? curx + tox : tox;
298 py3 = relative ? cury + toy : toy;
300 svgCurveToCubic( px1, py1, px2, py2, px3, py3 );
302 contrlx = relative ? curx + x1 : x1;
303 contrly = relative ? cury + y1 : y1;
304 curx = relative ? curx + tox : tox;
305 cury = relative ? cury + toy : toy;
308 svgCurveToQuadratic( x1, y1, tox, toy, !relative );
315 ptr = getCoord(ptr, tox);
316 ptr = getCoord(ptr, toy);
317 if( !( lastCommand ==
'q' || lastCommand ==
'Q' ||
318 lastCommand ==
't' || lastCommand ==
'T' ) )
326 xc = 2 * curx - contrlx;
327 yc = 2 * cury - contrly;
329 px1 = (curx + 2 * xc) * (1.0 / 3.0);
330 py1 = (cury + 2 * yc) * (1.0 / 3.0);
331 px2 = relative ? ((curx + tox) + 2 * xc) * (1.0 / 3.0) : (tox + 2 * xc) * (1.0 / 3.0);
332 py2 = relative ? ((cury + toy) + 2 * yc) * (1.0 / 3.0) : (toy + 2 * yc) * (1.0 / 3.0);
333 px3 = relative ? curx + tox : tox;
334 py3 = relative ? cury + toy : toy;
336 svgCurveToCubic( px1, py1, px2, py2, px3, py3 );
340 curx = relative ? curx + tox : tox;
341 cury = relative ? cury + toy : toy;
344 svgCurveToQuadraticSmooth( tox, toy, !relative );
351 bool largeArc, sweep;
352 double angle, rx, ry;
353 ptr = getCoord( ptr, rx );
354 ptr = getCoord( ptr, ry );
355 ptr = getCoord( ptr, angle );
356 ptr = getCoord( ptr, tox );
358 ptr = getCoord( ptr, tox );
360 ptr = getCoord( ptr, tox );
361 ptr = getCoord( ptr, toy );
368 calculateArc( relative, curx, cury, angle, tox, toy, rx, ry, largeArc, sweep );
370 svgArcTo( tox, toy, rx, ry, angle, largeArc, sweep, !relative );
376 kdDebug() <<
"SVGPathParser::parseSVG(): unknown command \"" << command <<
"\"" << endl;
381 lastCommand = command;
383 if(*ptr ==
'+' || *ptr ==
'-' || (*ptr >=
'0' && *ptr <=
'9'))
388 else if(command ==
'm')
394 if( lastCommand !=
'C' && lastCommand !=
'c' &&
395 lastCommand !=
'S' && lastCommand !=
's' &&
396 lastCommand !=
'Q' && lastCommand !=
'q' &&
397 lastCommand !=
'T' && lastCommand !=
't')
411SVGPathParser::calculateArc(
bool relative,
double &curx,
double &cury,
double angle,
double x,
double y,
double r1,
double r2,
bool largeArcFlag,
bool sweepFlag)
413 double sin_th, cos_th;
414 double a00, a01, a10, a11;
415 double x0, y0, x1, y1, xc, yc;
416 double d, sfactor, sfactor_sq;
417 double th0, th1, th_arc;
420 sin_th = sin(angle * (M_PI / 180.0));
421 cos_th = cos(angle * (M_PI / 180.0));
426 dx = (curx - x) / 2.0;
433 dy = (cury - y) / 2.0;
437 double _x1 = cos_th * dx + sin_th * dy;
438 double _y1 = -sin_th * dx + cos_th * dy;
439 double Pr1 = r1 * r1;
440 double Pr2 = r2 * r2;
441 double Px = _x1 * _x1;
442 double Py = _y1 * _y1;
445 double check = Px / Pr1 + Py / Pr2;
448 r1 = r1 * sqrt(check);
449 r2 = r2 * sqrt(check);
457 x0 = a00 * curx + a01 * cury;
458 y0 = a10 * curx + a11 * cury;
461 x1 = a00 * x + a01 * y;
463 x1 = a00 * (curx + x) + a01 * (cury + y);
466 y1 = a10 * x + a11 * y;
468 y1 = a10 * (curx + x) + a11 * (cury + y);
476 d = (x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0);
478 sfactor_sq = 1.0 / d - 0.25;
483 sfactor = sqrt(sfactor_sq);
485 if(sweepFlag == largeArcFlag)
488 xc = 0.5 * (x0 + x1) - sfactor * (y1 - y0);
489 yc = 0.5 * (y0 + y1) + sfactor * (x1 - x0);
492 th0 = atan2(y0 - yc, x0 - xc);
493 th1 = atan2(y1 - yc, x1 - xc);
496 if(th_arc < 0 && sweepFlag)
498 else if(th_arc > 0 && !sweepFlag)
501 n_segs = (int) (
int) ceil(fabs(th_arc / (M_PI * 0.5 + 0.001)));
503 for(i = 0; i < n_segs; i++)
506 double sin_th, cos_th;
507 double a00, a01, a10, a11;
508 double x1, y1, x2, y2, x3, y3;
512 double _th0 = th0 + i * th_arc / n_segs;
513 double _th1 = th0 + (i + 1) * th_arc / n_segs;
515 sin_th = sin(angle * (M_PI / 180.0));
516 cos_th = cos(angle * (M_PI / 180.0));
524 th_half = 0.5 * (_th1 - _th0);
525 t = (8.0 / 3.0) * sin(th_half * 0.5) * sin(th_half * 0.5) / sin(th_half);
526 x1 = xc + cos(_th0) - t * sin(_th0);
527 y1 = yc + sin(_th0) + t * cos(_th0);
530 x2 = x3 + t * sin(_th1);
531 y2 = y3 - t * cos(_th1);
533 svgCurveToCubic( a00 * x1 + a01 * y1, a10 * x1 + a11 * y1, a00 * x2 + a01 * y2, a10 * x2 + a11 * y2, a00 * x3 + a01 * y3, a10 * x3 + a11 * y3 );
549SVGPathParser::svgLineToHorizontal(
double,
bool )
554SVGPathParser::svgLineToVertical(
double,
bool )
559SVGPathParser::svgCurveToCubicSmooth(
double,
double,
double,
double,
bool )
564SVGPathParser::svgCurveToQuadratic(
double,
double,
double,
double,
bool )
569SVGPathParser::svgCurveToQuadraticSmooth(
double,
double,
bool )
574SVGPathParser::svgArcTo(
double,
double,
double,
double,
double,
bool,
bool,
bool )