156 QStringView numStr = QGuiSvg::trimmed(str, tiny12FeaturesOnly);
158 if (numStr.isEmpty()) {
164 if (numStr.endsWith(QLatin1Char(
'%'))) {
167 }
else if (numStr.endsWith(QLatin1String(
"px"))) {
170 }
else if (numStr.endsWith(QLatin1String(
"pc"))) {
173 }
else if (numStr.endsWith(QLatin1String(
"pt"))) {
176 }
else if (numStr.endsWith(QLatin1String(
"mm"))) {
179 }
else if (numStr.endsWith(QLatin1String(
"cm"))) {
182 }
else if (numStr.endsWith(QLatin1String(
"in"))) {
189 qreal len = toDouble(numStr, ok);
230 QStringView numStr = QGuiSvg::trimmed(str, tiny12FeaturesOnly);
232 if (numStr.isEmpty())
235 qreal unitFactor = 1.0;
236 if (numStr.endsWith(QLatin1String(
"deg"))) {
239 }
else if (numStr.endsWith(QLatin1String(
"grad"))) {
243 }
else if (numStr.endsWith(QLatin1String(
"rad"))) {
245 unitFactor = 180.0 / Q_PI;
246 }
else if (numStr.endsWith(QLatin1String(
"turn"))) {
255 qreal angle = numStr.toDouble(&ok);
259 return angle * unitFactor;
294 if (dataStr.isEmpty())
298 constexpr int maxElementCount = 0x7fff;
301 constexpr auto paramCountFor = [](
char16_t c) {
303 case 'm':
case 'l':
case 't':
return 2;
305 case 'h':
case 'v':
return 1;
306 case 's':
case 'q':
return 4;
316 char16_t lastMode = 0;
319 while (!dataStr.isEmpty()) {
320 while (dataStr.first().isSpace() && dataStr.length() > 1)
323 const char16_t rawCmd = dataStr.first().unicode();
324 char16_t cmd = rawCmd | 0x20;
326 int paramCount = paramCountFor(cmd);
327 if (paramCount == -1)
330 const bool isRelative = rawCmd >=
'a' && rawCmd <=
'z';
333 const char *pattern =
nullptr;
336 QVarLengthArray<qreal, 8> arg;
338 const qreal *num = arg.constData();
339 int count = arg.size();
342 if (count < paramCount)
345 QPointF offset = isRelative ? currPoint : QPointF {0., 0.};
348 currPoint = startPoint = QPointF {num[0], num[1]} + offset;
349 path.moveTo(startPoint);
358 currPoint = startPoint;
363 currPoint = QPointF {num[0], num[1]} + offset;
364 path.lineTo(currPoint);
368 currPoint.setX(num[0] + offset.x());
369 path.lineTo(currPoint);
373 currPoint.setY(num[0] + offset.y());
374 path.lineTo(currPoint);
378 QPointF c1 = QPointF {num[0], num[1]} + offset;
379 QPointF c2 = QPointF {num[2], num[3]} + offset;
380 QPointF e = QPointF {num[4], num[5]} + offset;
381 path.cubicTo(c1, c2, e);
388 if (lastMode ==
'c' || lastMode ==
's')
389 c1 = 2 * currPoint - ctrlPoint;
392 QPointF c2 = QPointF {num[0], num[1]} + offset;
393 QPointF e = QPointF {num[2], num[3]} + offset;
395 path.cubicTo(c1, c2, e);
401 QPointF c = QPointF {num[0], num[1]} + offset;
402 QPointF e = QPointF {num[2], num[3]} + offset;
409 QPointF e = QPointF {num[0], num[1]} + offset;
411 if (lastMode ==
'q' || lastMode ==
't')
412 c = 2 * currPoint - ctrlPoint;
423 qreal xAxisRotation = num[2];
424 qreal largeArcFlag = num[3];
425 qreal sweepFlag = num[4];
426 qreal ex = num[5] + offset.x();
427 qreal ey = num[6] + offset.y();
428 qreal curx = currPoint.x();
429 qreal cury = currPoint.y();
430 pathArc(path, rx, ry, xAxisRotation,
int(largeArcFlag),
431 int(sweepFlag), ex, ey, curx, cury);
433 currPoint = QPointF {ex, ey};
437 Q_ASSERT_X(
false,
"parsePath",
"command table out of sync with switch");
442 if (limitLength && path.elementCount() > maxElementCount)
447 if (cmd ==
'z' && count != 0)
484void pathArc(QPainterPath &path, qreal rx, qreal ry,
485 qreal x_axis_rotation,
int large_arc_flag,
486 int sweep_flag, qreal x, qreal y,
487 qreal curx, qreal cury)
490 if (QPointF(curx, cury) == QPointF(x, y))
493 const qreal Pr1 = rx * rx;
494 const qreal Pr2 = ry * ry;
497 if (qFuzzyIsNull(Pr1) || qFuzzyIsNull(Pr2)) {
505 qreal sin_th, cos_th;
506 qreal a00, a01, a10, a11;
507 qreal x0, y0, x1, y1, xc, yc;
508 qreal d, sfactor, sfactor_sq;
509 qreal th0, th1, th_arc;
511 qreal dx, dy, dx1, dy1, Px, Py, check;
516 sin_th = qSin(x_axis_rotation * (Q_PI / 180.0));
517 cos_th = qCos(x_axis_rotation * (Q_PI / 180.0));
519 dx = (curx - x) / 2.0;
520 dy = (cury - y) / 2.0;
521 dx1 = cos_th * dx + sin_th * dy;
522 dy1 = -sin_th * dx + cos_th * dy;
526 check = Px / Pr1 + Py / Pr2;
528 rx = rx * qSqrt(check);
529 ry = ry * qSqrt(check);
536 x0 = a00 * curx + a01 * cury;
537 y0 = a10 * curx + a11 * cury;
538 x1 = a00 * x + a01 * y;
539 y1 = a10 * x + a11 * y;
541
542
543
544
545 d = (x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0);
548 sfactor_sq = 1.0 / d - 0.25;
549 if (sfactor_sq < 0) sfactor_sq = 0;
550 sfactor = qSqrt(sfactor_sq);
551 if (sweep_flag == large_arc_flag) sfactor = -sfactor;
552 xc = 0.5 * (x0 + x1) - sfactor * (y1 - y0);
553 yc = 0.5 * (y0 + y1) + sfactor * (x1 - x0);
556 th0 = qAtan2(y0 - yc, x0 - xc);
557 th1 = qAtan2(y1 - yc, x1 - xc);
560 if (th_arc < 0 && sweep_flag)
562 else if (th_arc > 0 && !sweep_flag)
565 n_segs = qCeil(qAbs(th_arc / (Q_PI * 0.5 + 0.001)));
567 for (i = 0; i < n_segs; i++) {
568 pathArcSegment(path, xc, yc,
569 th0 + i * th_arc / n_segs,
570 th0 + (i + 1) * th_arc / n_segs,
571 rx, ry, x_axis_rotation);