24 #include "wtf/Platform.h" 26 #include "xml/Document.h" 49 #include <wtf/MathExtras.h> 57 template <
typename FloatType>
static bool _parseNumber(
const UChar*& ptr,
const UChar* end, FloatType& number,
bool skip)
59 int integer, exponent;
60 FloatType decimal, frac;
62 const UChar* start = ptr;
72 if (ptr < end && *ptr ==
'+')
74 else if (ptr < end && *ptr ==
'-') {
79 if (ptr == end || ((*ptr < '0' || *ptr >
'9') && *ptr !=
'.'))
84 while (ptr < end && *ptr >=
'0' && *ptr <=
'9')
85 integer = (integer * 10) + (ptr++)->unicode() -
'0';
87 if (ptr < end && *ptr ==
'.') {
91 if (ptr >= end || *ptr < '0' || *ptr >
'9')
94 while (ptr < end && *ptr >=
'0' && *ptr <=
'9')
95 decimal += ((ptr++)->unicode() -
'0') * (frac *= static_cast<FloatType>(0.1));
99 if (ptr != start && ptr + 1 < end && (*ptr ==
'e' || *ptr ==
'E')
100 && (ptr[1] !=
'x' && ptr[1] !=
'm')) {
106 else if (*ptr ==
'-') {
112 if (ptr >= end || *ptr < '0' || *ptr >
'9')
115 while (ptr < end && *ptr >=
'0' && *ptr <=
'9') {
117 exponent += ptr->unicode() -
'0';
122 number = integer + decimal;
123 number *= sign *
static_cast<FloatType
>(pow(10.0, expsign * exponent));
129 skipOptionalSpacesOrDelimiter(ptr, end);
134 bool parseNumber(
const UChar*& ptr,
const UChar* end,
float& number,
bool skip)
136 return _parseNumber(ptr, end, number, skip);
140 static bool parseNumber(
const UChar*& ptr,
const UChar* end,
double& number,
bool skip =
true)
142 return _parseNumber(ptr, end, number, skip);
145 bool parseNumberOptionalNumber(
const String& s,
float& x,
float& y)
149 const UChar* cur = s.characters();
150 const UChar* end = cur + s.length();
152 if (!parseNumber(cur, end, x))
157 else if (!parseNumber(cur, end, y,
false))
163 bool pointsListFromSVGData(SVGPointList* pointsList,
const String& points)
165 if (points.isEmpty())
167 const UChar* cur = points.characters();
168 const UChar* end = cur + points.length();
170 skipOptionalSpaces(cur, end);
172 bool delimParsed =
false;
176 if (!parseNumber(cur, end, xPos))
180 if (!parseNumber(cur, end, yPos,
false))
183 skipOptionalSpaces(cur, end);
185 if (cur < end && *cur ==
',') {
189 skipOptionalSpaces(cur, end);
192 pointsList->appendItem(FloatPoint(xPos, yPos), ec);
194 return cur == end && !delimParsed;
211 virtual ~SVGPathParser() { }
212 bool parseSVG(
const String&
d,
bool process =
false);
215 virtual void svgMoveTo(
double x1,
double y1,
bool closed,
bool abs =
true) = 0;
216 virtual void svgLineTo(
double x1,
double y1,
bool abs =
true) = 0;
217 virtual void svgLineToHorizontal(
double x,
bool abs =
true) { Q_UNUSED(x); Q_UNUSED(abs); }
218 virtual void svgLineToVertical(
double y,
bool abs =
true) { Q_UNUSED(y); Q_UNUSED(abs); }
219 virtual void svgCurveToCubic(
double x1,
double y1,
double x2,
double y2,
double x,
double y,
bool abs =
true) = 0;
220 virtual void svgCurveToCubicSmooth(
double x,
double y,
double x2,
double y2,
bool abs =
true) { Q_UNUSED(x); Q_UNUSED(y); Q_UNUSED(x2); Q_UNUSED(y2); Q_UNUSED(abs); }
221 virtual void svgCurveToQuadratic(
double x,
double y,
double x1,
double y1,
bool abs =
true) { Q_UNUSED(x); Q_UNUSED(y); Q_UNUSED(x1); Q_UNUSED(y1); Q_UNUSED(abs); }
222 virtual void svgCurveToQuadraticSmooth(
double x,
double y,
bool abs =
true) {Q_UNUSED(x); Q_UNUSED(y); Q_UNUSED(abs);}
223 virtual void svgArcTo(
double x,
double y,
double r1,
double r2,
double angle,
bool largeArcFlag,
bool sweepFlag,
bool abs =
true) { Q_UNUSED(x); Q_UNUSED(y); Q_UNUSED(r1); Q_UNUSED(r2); Q_UNUSED(angle); Q_UNUSED(largeArcFlag); Q_UNUSED(sweepFlag); Q_UNUSED(abs);}
224 virtual void svgClosePath() = 0;
226 void calculateArc(
bool relative,
double& curx,
double& cury,
double angle,
double x,
double y,
double r1,
double r2,
bool largeArcFlag,
bool sweepFlag);
229 bool SVGPathParser::parseSVG(
const String& s,
bool process)
234 const UChar* ptr = s.characters();
235 const UChar* end = ptr + s.length();
237 double contrlx, contrly, curx, cury, subpathx, subpathy, tox, toy, x1, y1, x2, y2, xc, yc;
238 double px1, py1, px2, py2, px3, py3;
241 if (!skipOptionalSpaces(ptr, end))
244 char command = (ptr++)->unicode(), lastCommand =
' ';
245 if (command !=
'm' && command !=
'M')
248 subpathx = subpathy = curx = cury = contrlx = contrly = 0.0;
250 skipOptionalSpaces(ptr, end);
252 bool relative =
false;
260 if (!parseNumber(ptr, end, tox) || !parseNumber(ptr, end, toy))
264 subpathx = curx = relative ? curx + tox : tox;
265 subpathy = cury = relative ? cury + toy : toy;
277 if (!parseNumber(ptr, end, tox) || !parseNumber(ptr, end, toy))
281 curx = relative ? curx + tox : tox;
282 cury = relative ? cury + toy : toy;
292 if (!parseNumber(ptr, end, tox))
304 if (!parseNumber(ptr, end, tox))
316 if (!parseNumber(ptr, end, toy))
328 if (!parseNumber(ptr, end, toy))
354 if (!parseNumber(ptr, end, x1) || !parseNumber(ptr, end, y1) ||
355 !parseNumber(ptr, end, x2) || !parseNumber(ptr, end, y2) ||
356 !parseNumber(ptr, end, tox) || !parseNumber(ptr, end, toy))
360 px1 = relative ? curx + x1 : x1;
361 py1 = relative ? cury + y1 : y1;
362 px2 = relative ? curx + x2 : x2;
363 py2 = relative ? cury + y2 : y2;
364 px3 = relative ? curx + tox : tox;
365 py3 = relative ? cury + toy : toy;
370 contrlx = relative ? curx + x2 : x2;
371 contrly = relative ? cury + y2 : y2;
372 curx = relative ? curx + tox : tox;
373 cury = relative ? cury + toy : toy;
385 if (!parseNumber(ptr, end, x2) || !parseNumber(ptr, end, y2) ||
386 !parseNumber(ptr, end, tox) || !parseNumber(ptr, end, toy))
389 if (!(lastCommand ==
'c' || lastCommand ==
'C' ||
390 lastCommand ==
's' || lastCommand ==
'S')) {
396 px1 = 2 * curx - contrlx;
397 py1 = 2 * cury - contrly;
398 px2 = relative ? curx + x2 : x2;
399 py2 = relative ? cury + y2 : y2;
400 px3 = relative ? curx + tox : tox;
401 py3 = relative ? cury + toy : toy;
406 contrlx = relative ? curx + x2 : x2;
407 contrly = relative ? cury + y2 : y2;
408 curx = relative ? curx + tox : tox;
409 cury = relative ? cury + toy : toy;
420 if (!parseNumber(ptr, end, x1) || !parseNumber(ptr, end, y1) ||
421 !parseNumber(ptr, end, tox) || !parseNumber(ptr, end, toy))
425 px1 = relative ? (curx + 2 * (x1 + curx)) * (1.0 / 3.0) : (curx + 2 * x1) * (1.0 / 3.0);
426 py1 = relative ? (cury + 2 * (y1 + cury)) * (1.0 / 3.0) : (cury + 2 * y1) * (1.0 / 3.0);
427 px2 = relative ? ((curx + tox) + 2 * (x1 + curx)) * (1.0 / 3.0) : (tox + 2 * x1) * (1.0 / 3.0);
428 py2 = relative ? ((cury + toy) + 2 * (y1 + cury)) * (1.0 / 3.0) : (toy + 2 * y1) * (1.0 / 3.0);
429 px3 = relative ? curx + tox : tox;
430 py3 = relative ? cury + toy : toy;
435 contrlx = relative ? curx + x1 : x1;
436 contrly = relative ? cury + y1 : y1;
437 curx = relative ? curx + tox : tox;
438 cury = relative ? cury + toy : toy;
449 if (!parseNumber(ptr, end, tox) || !parseNumber(ptr, end, toy))
451 if (!(lastCommand ==
'q' || lastCommand ==
'Q' ||
452 lastCommand ==
't' || lastCommand ==
'T')) {
458 xc = 2 * curx - contrlx;
459 yc = 2 * cury - contrly;
461 px1 = relative ? (curx + 2 * xc) * (1.0 / 3.0) : (curx + 2 * xc) * (1.0 / 3.0);
462 py1 = relative ? (cury + 2 * yc) * (1.0 / 3.0) : (cury + 2 * yc) * (1.0 / 3.0);
463 px2 = relative ? ((curx + tox) + 2 * xc) * (1.0 / 3.0) : (tox + 2 * xc) * (1.0 / 3.0);
464 py2 = relative ? ((cury + toy) + 2 * yc) * (1.0 / 3.0) : (toy + 2 * yc) * (1.0 / 3.0);
465 px3 = relative ? curx + tox : tox;
466 py3 = relative ? cury + toy : toy;
473 curx = relative ? curx + tox : tox;
474 cury = relative ? cury + toy : toy;
484 bool largeArc, sweep;
485 double angle, rx, ry;
486 if (!parseNumber(ptr, end, rx) || !parseNumber(ptr, end, ry) ||
487 !parseNumber(ptr, end, angle) || !parseNumber(ptr, end, tox))
490 if (!parseNumber(ptr, end, tox))
493 if (!parseNumber(ptr, end, tox) || !parseNumber(ptr, end, toy))
501 calculateArc(relative, curx, cury, angle, tox, toy, rx, ry, largeArc, sweep);
511 lastCommand = command;
517 if ((*ptr ==
'+' || *ptr ==
'-' || (*ptr >=
'0' && *ptr <=
'9')) &&
518 (command !=
'z' && command !=
'Z')) {
521 else if (command ==
'm')
524 command = (ptr++)->unicode();
526 if (lastCommand !=
'C' && lastCommand !=
'c' &&
527 lastCommand !=
'S' && lastCommand !=
's' &&
528 lastCommand !=
'Q' && lastCommand !=
'q' &&
529 lastCommand !=
'T' && lastCommand !=
't') {
542 void SVGPathParser::calculateArc(
bool relative,
double& curx,
double& cury,
double angle,
double x,
double y,
double r1,
double r2,
bool largeArcFlag,
bool sweepFlag)
544 double sin_th, cos_th;
545 double a00, a01, a10, a11;
546 double x0, y0, x1, y1, xc, yc;
547 double d, sfactor, sfactor_sq;
548 double th0, th1, th_arc;
551 sin_th = sin(angle * (piDouble / 180.0));
552 cos_th = cos(angle * (piDouble / 180.0));
557 dx = (curx - x) / 2.0;
564 dy = (cury - y) / 2.0;
568 double _x1 = cos_th * dx + sin_th * dy;
569 double _y1 = -sin_th * dx + cos_th * dy;
570 double Pr1 = r1 * r1;
571 double Pr2 = r2 * r2;
572 double Px = _x1 * _x1;
573 double Py = _y1 * _y1;
576 double check = Px / Pr1 + Py / Pr2;
578 r1 = r1 * sqrt(check);
579 r2 = r2 * sqrt(check);
587 x0 = a00 * curx + a01 * cury;
588 y0 = a10 * curx + a11 * cury;
591 x1 = a00 * x + a01 * y;
593 x1 = a00 * (curx + x) + a01 * (cury + y);
596 y1 = a10 * x + a11 * y;
598 y1 = a10 * (curx + x) + a11 * (cury + y);
606 d = (x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0);
608 sfactor_sq = 1.0 / d - 0.25;
613 sfactor = sqrt(sfactor_sq);
615 if (sweepFlag == largeArcFlag)
618 xc = 0.5 * (x0 + x1) - sfactor * (y1 - y0);
619 yc = 0.5 * (y0 + y1) + sfactor * (x1 - x0);
622 th0 = atan2(y0 - yc, x0 - xc);
623 th1 = atan2(y1 - yc, x1 - xc);
626 if (th_arc < 0 && sweepFlag)
627 th_arc += 2 * piDouble;
628 else if (th_arc > 0 && !sweepFlag)
629 th_arc -= 2 * piDouble;
631 n_segs = (int) (
int) ceil(fabs(th_arc / (piDouble * 0.5 + 0.001)));
633 for(i = 0; i < n_segs; i++) {
634 double sin_th, cos_th;
635 double a00, a01, a10, a11;
636 double x1, y1, x2, y2, x3, y3;
640 double _th0 = th0 + i * th_arc / n_segs;
641 double _th1 = th0 + (i + 1) * th_arc / n_segs;
643 sin_th = sin(angle * (piDouble / 180.0));
644 cos_th = cos(angle * (piDouble / 180.0));
652 th_half = 0.5 * (_th1 - _th0);
653 t = (8.0 / 3.0) * sin(th_half * 0.5) * sin(th_half * 0.5) / sin(th_half);
654 x1 = xc + cos(_th0) - t * sin(_th0);
655 y1 = yc + sin(_th0) + t * cos(_th0);
658 x2 = x3 + t * sin(_th1);
659 y2 = y3 - t * cos(_th1);
677 class PathBuilder :
public SVGPathParser
683 return parseSVG(d,
true);
687 virtual void svgMoveTo(
double x1,
double y1,
bool closed,
bool abs =
true)
692 m_path->closeSubpath();
693 m_path->moveTo(current);
695 virtual void svgLineTo(
double x1,
double y1,
bool abs =
true)
699 m_path->addLineTo(current);
701 virtual void svgCurveToCubic(
double x1,
double y1,
double x2,
double y2,
double x,
double y,
bool abs =
true)
713 virtual void svgClosePath()
715 m_path->closeSubpath();
721 bool pathFromSVGData(
Path& path,
const String& d)
724 return builder.build(&path, d);
727 class SVGPathSegListBuilder :
public SVGPathParser
730 bool build(SVGPathSegList* segList,
const String& d,
bool process)
732 m_pathSegList = segList;
733 return parseSVG(d, process);
737 virtual void svgMoveTo(
double x1,
double y1,
bool,
bool abs =
true)
746 virtual void svgLineTo(
double x1,
double y1,
bool abs =
true)
755 virtual void svgLineToHorizontal(
double x,
bool abs)
760 m_pathSegList->appendItem(SVGPathElement::createSVGPathSegLinetoHorizontalAbs(
narrowPrecisionToFloat(x)), ec);
762 m_pathSegList->appendItem(SVGPathElement::createSVGPathSegLinetoHorizontalRel(
narrowPrecisionToFloat(x)), ec);
764 virtual void svgLineToVertical(
double y,
bool abs)
769 m_pathSegList->appendItem(SVGPathElement::createSVGPathSegLinetoVerticalAbs(
narrowPrecisionToFloat(y)), ec);
771 m_pathSegList->appendItem(SVGPathElement::createSVGPathSegLinetoVerticalRel(
narrowPrecisionToFloat(y)), ec);
773 virtual void svgCurveToCubic(
double x1,
double y1,
double x2,
double y2,
double x,
double y,
bool abs =
true)
786 virtual void svgCurveToCubicSmooth(
double x,
double y,
double x2,
double y2,
bool abs)
797 virtual void svgCurveToQuadratic(
double x,
double y,
double x1,
double y1,
bool abs)
808 virtual void svgCurveToQuadraticSmooth(
double x,
double y,
bool abs)
817 virtual void svgArcTo(
double x,
double y,
double r1,
double r2,
double angle,
bool largeArcFlag,
bool sweepFlag,
bool abs)
830 virtual void svgClosePath()
833 m_pathSegList->appendItem(SVGPathElement::createSVGPathSegClosePath(), ec);
835 SVGPathSegList* m_pathSegList;
838 bool pathSegListFromSVGData(SVGPathSegList* path ,
const String& d,
bool process)
840 SVGPathSegListBuilder builder;
841 return builder.build(path, d, process);
844 Vector<String> parseDelimitedString(
const String& input,
const char separator)
846 Vector<String> values;
848 const UChar* ptr = input.characters();
849 const UChar* end = ptr + input.length();
850 skipOptionalSpaces(ptr, end);
854 const UChar* inputStart = ptr;
855 while (ptr < end && *ptr != separator)
858 if (ptr == inputStart)
862 const UChar* inputEnd = ptr - 1;
863 while (inputStart < inputEnd && isWhitespace(*inputEnd))
866 values.append(
String(inputStart, inputEnd - inputStart + 1));
867 skipOptionalSpacesOrDelimiter(ptr, end, separator);
875 #endif // ENABLE(SVG)
float narrowPrecisionToFloat(T)
static FloatPoint narrowPrecision(double x, double y)
unsigned short ExceptionCode
void check(DocumentImpl *doc, const QString &statement, const QString &expected)