61 const int maxLen = 255;
65 if (str->startsWith(QLatin1Char(
'-'))) {
68 }
else if (str->startsWith(QLatin1Char(
'+'))) {
71 while (!str->isEmpty() && isDigit(str->first().unicode()) && pos < maxLen) {
72 temp[pos++] = str->first().toLatin1();
75 if (str->startsWith(QLatin1Char(
'.')) && pos < maxLen) {
79 while (!str->isEmpty() && isDigit(str->first().unicode()) && pos < maxLen) {
80 temp[pos++] = str->first().toLatin1();
83 bool exponent =
false;
84 if ((str->startsWith(QLatin1Char(
'e')) || str->startsWith(QLatin1Char(
'E'))) && pos < maxLen) {
88 if ((str->startsWith(QLatin1Char(
'-')) || str->startsWith(QLatin1Char(
'+')))
90 temp[pos++] = str->first().toLatin1();
93 while (!str->isEmpty() && isDigit(str->first().unicode()) && pos < maxLen) {
94 temp[pos++] = str->first().toLatin1();
102 if (!exponent && pos < 10) {
104 const char *t = temp;
110 while (*t && *t !=
'.') {
124 val = ((qreal)ival)/((qreal)div);
131 val = QByteArray::fromRawData(temp, pos).toDouble();
133 if (qFpClassify(
float(val)) != FP_NORMAL)
258 const size_t patternLen = qstrlen(pattern);
259 while (!str->isEmpty() && str->first().isSpace())
262 || str->startsWith(QLatin1Char(
'-')) || str->startsWith(QLatin1Char(
'+'))
263 || str->startsWith(QLatin1Char(
'.'))) {
265 if (patternLen && pattern[points.size() % patternLen] ==
'f') {
267 if (!str->startsWith(QLatin1Char(
'0')) && !str->startsWith(QLatin1Char(
'1')))
269 points.append(str->startsWith(QLatin1Char(
'0')) ? 0.0 : 1.0);
272 points.append(QGuiSvg::toDouble(str));
275 while (!str->isEmpty() && str->first().isSpace())
277 if (str->startsWith(QLatin1Char(
',')))
281 while (!str->isEmpty() && str->first().isSpace())
288 if (dataStr.isEmpty())
291 const int maxElementCount = 0x7fff;
292 qreal x0 = 0, y0 = 0;
298 while (!dataStr.isEmpty()) {
299 while (dataStr.first().isSpace() && dataStr.length() > 1)
301 QChar pathElem = dataStr.first();
303 const char *pattern =
nullptr;
304 if (pathElem == QLatin1Char(
'a') || pathElem == QLatin1Char(
'A'))
306 QVarLengthArray<qreal, 8> arg;
307 parseNumbersArray(&dataStr, arg, pattern);
308 if (pathElem == QLatin1Char(
'z') || pathElem == QLatin1Char(
'Z'))
310 const qreal *num = arg.constData();
311 int count = arg.size();
315 switch (pathElem.unicode()) {
319 x = x0 = num[0] + offsetX;
320 y = y0 = num[1] + offsetY;
328 pathElem = QLatin1Char(
'l');
344 pathElem = QLatin1Char(
'L');
360 x = num[0] + offsetX;
361 y = num[1] + offsetY;
380 x = num[0] + offsetX;
394 y = num[0] + offsetY;
411 QPointF c1(num[0] + offsetX, num[1] + offsetY);
412 QPointF c2(num[2] + offsetX, num[3] + offsetY);
413 QPointF e(num[4] + offsetX, num[5] + offsetY);
416 path.cubicTo(c1, c2, e);
426 QPointF c1(num[0], num[1]);
427 QPointF c2(num[2], num[3]);
428 QPointF e(num[4], num[5]);
431 path.cubicTo(c1, c2, e);
442 if (lastMode ==
'c' || lastMode ==
'C' ||
443 lastMode ==
's' || lastMode ==
'S')
444 c1 = QPointF(2*x-ctrlPt.x(), 2*y-ctrlPt.y());
447 QPointF c2(num[0] + offsetX, num[1] + offsetY);
448 QPointF e(num[2] + offsetX, num[3] + offsetY);
451 path.cubicTo(c1, c2, e);
462 if (lastMode ==
'c' || lastMode ==
'C' ||
463 lastMode ==
's' || lastMode ==
'S')
464 c1 = QPointF(2*x-ctrlPt.x(), 2*y-ctrlPt.y());
467 QPointF c2(num[0], num[1]);
468 QPointF e(num[2], num[3]);
471 path.cubicTo(c1, c2, e);
481 QPointF c(num[0] + offsetX, num[1] + offsetY);
482 QPointF e(num[2] + offsetX, num[3] + offsetY);
495 QPointF c(num[0], num[1]);
496 QPointF e(num[2], num[3]);
509 QPointF e(num[0] + offsetX, num[1] + offsetY);
513 if (lastMode ==
'q' || lastMode ==
'Q' ||
514 lastMode ==
't' || lastMode ==
'T')
515 c = QPointF(2*x-ctrlPt.x(), 2*y-ctrlPt.y());
528 QPointF e(num[0], num[1]);
532 if (lastMode ==
'q' || lastMode ==
'Q' ||
533 lastMode ==
't' || lastMode ==
'T')
534 c = QPointF(2*x-ctrlPt.x(), 2*y-ctrlPt.y());
549 qreal xAxisRotation = (*num++);
550 qreal largeArcFlag = (*num++);
551 qreal sweepFlag = (*num++);
552 qreal ex = (*num++) + offsetX;
553 qreal ey = (*num++) + offsetY;
557 pathArc(path, rx, ry, xAxisRotation,
int(largeArcFlag),
558 int(sweepFlag), ex, ey, curx, cury);
570 qreal xAxisRotation = (*num++);
571 qreal largeArcFlag = (*num++);
572 qreal sweepFlag = (*num++);
578 pathArc(path, rx, ry, xAxisRotation,
int(largeArcFlag),
579 int(sweepFlag), ex, ey, curx, cury);
588 lastMode = pathElem.toLatin1();
589 if (limitLength && path.elementCount() > maxElementCount)
623void pathArc(QPainterPath &path, qreal rx, qreal ry,
624 qreal x_axis_rotation,
int large_arc_flag,
625 int sweep_flag, qreal x, qreal y,
626 qreal curx, qreal cury)
628 const qreal Pr1 = rx * rx;
629 const qreal Pr2 = ry * ry;
634 qreal sin_th, cos_th;
635 qreal a00, a01, a10, a11;
636 qreal x0, y0, x1, y1, xc, yc;
637 qreal d, sfactor, sfactor_sq;
638 qreal th0, th1, th_arc;
640 qreal dx, dy, dx1, dy1, Px, Py, check;
645 sin_th = qSin(x_axis_rotation * (Q_PI / 180.0));
646 cos_th = qCos(x_axis_rotation * (Q_PI / 180.0));
648 dx = (curx - x) / 2.0;
649 dy = (cury - y) / 2.0;
650 dx1 = cos_th * dx + sin_th * dy;
651 dy1 = -sin_th * dx + cos_th * dy;
655 check = Px / Pr1 + Py / Pr2;
657 rx = rx * qSqrt(check);
658 ry = ry * qSqrt(check);
665 x0 = a00 * curx + a01 * cury;
666 y0 = a10 * curx + a11 * cury;
667 x1 = a00 * x + a01 * y;
668 y1 = a10 * x + a11 * y;
670
671
672
673
674 d = (x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0);
677 sfactor_sq = 1.0 / d - 0.25;
678 if (sfactor_sq < 0) sfactor_sq = 0;
679 sfactor = qSqrt(sfactor_sq);
680 if (sweep_flag == large_arc_flag) sfactor = -sfactor;
681 xc = 0.5 * (x0 + x1) - sfactor * (y1 - y0);
682 yc = 0.5 * (y0 + y1) + sfactor * (x1 - x0);
685 th0 = qAtan2(y0 - yc, x0 - xc);
686 th1 = qAtan2(y1 - yc, x1 - xc);
689 if (th_arc < 0 && sweep_flag)
691 else if (th_arc > 0 && !sweep_flag)
694 n_segs = qCeil(qAbs(th_arc / (Q_PI * 0.5 + 0.001)));
696 for (i = 0; i < n_segs; i++) {
697 pathArcSegment(path, xc, yc,
698 th0 + i * th_arc / n_segs,
699 th0 + (i + 1) * th_arc / n_segs,
700 rx, ry, x_axis_rotation);