11#include <private/qbezier_p.h>
12#include <QtCore/qmath.h>
13#include <QtCore/private/qnumeric_p.h>
146 return d->startX.isNull ? 0 :
d->startX.value;
162 return d->startX.isValid();
168 return d->startY.isNull ? 0 :
d->startY.value;
184 return d->startY.isValid();
242 return d->_pathElements.at(
index);
250 d->_pathElements.append(pathElement);
252 if (
d->componentComplete) {
253 QQuickCurve *curve = qobject_cast<QQuickCurve *>(pathElement);
255 d->_pathCurves.append(curve);
257 d->_pathTexts.append(
text);
274 return d->_pathElements.size();
283 d->_pathElements.clear();
284 d->_pathCurves.clear();
285 d->_pointCache.clear();
286 d->_pathTexts.clear();
292 interpolate(
d->_attributePoints, idx,
name,
value);
301 qreal lastPercent = 0;
302 int search = idx - 1;
304 const AttributePoint &point = attributePoints.
at(search);
305 if (point.values.contains(
name)) {
306 lastValue = point.values.value(
name);
307 lastPercent = point.origpercent;
315 const AttributePoint &curPoint = attributePoints.
at(idx);
317 for (
int ii = search; ii < idx; ++ii) {
318 AttributePoint &point = attributePoints[ii];
320 qreal val = lastValue + (
value - lastValue) * (point.origpercent - lastPercent) / (curPoint.origpercent - lastPercent);
328 const AttributePoint &
first =
d->_attributePoints.first();
330 for (
int ii =
d->_attributePoints.size() - 1; ii >= 0; ii--) {
331 const AttributePoint &point =
d->_attributePoints.at(ii);
332 if (point.values.contains(
name)) {
333 for (
int jj = ii + 1; jj <
d->_attributePoints.size(); ++jj) {
334 AttributePoint &setPoint =
d->_attributePoints[jj];
335 setPoint.values.insert(
name,
val);
344 const AttributePoint &
first = attributePoints.
first();
346 for (
int ii = attributePoints.
size() - 1; ii >= 0; ii--) {
347 const AttributePoint &point = attributePoints.
at(ii);
348 if (point.values.contains(
name)) {
349 for (
int jj = ii + 1; jj < attributePoints.
size(); ++jj) {
350 AttributePoint &setPoint = attributePoints[jj];
358void QQuickPath::processPath()
362 if (!
d->componentComplete)
365 d->_pointCache.clear();
366 d->prevBez.isValid =
false;
368 if (
d->isShapePath) {
376 d->_path =
d->_path.simplified();
388 for (
int i = 0;
i <
path.elementCount(); ++
i) {
399 attributePoints.
clear();
401 if (!
d->componentComplete)
406 AttributePoint
first;
407 for (
int ii = 0; ii <
attributes.size(); ++ii)
409 attributePoints <<
first;
411 qreal startX =
d->startX.isValid() ?
d->startX.value : startPoint.
x();
412 qreal startY =
d->startY.isValid() ?
d->startY.value : startPoint.
y();
417 bool usesPercent =
false;
420 if (
QQuickCurve *curve = qobject_cast<QQuickCurve *>(pathElement)) {
423 data.endPoint = endPoint;
424 data.curves =
d->_pathCurves;
427 p.origpercent =
path.length();
428 attributePoints <<
p;
431 AttributePoint &point = attributePoints.
last();
434 }
else if (
QQuickPathPercent *percent = qobject_cast<QQuickPathPercent *>(pathElement)) {
435 AttributePoint &point = attributePoints.
last();
436 point.values[percentString] = percent->value();
437 interpolate(attributePoints, attributePoints.
size() - 1, percentString, percent->value());
445 const AttributePoint &last = attributePoints.
constLast();
446 for (
int ii = 0; ii <
attributes.size(); ++ii) {
450 if (usesPercent && !last.values.contains(percentString)) {
451 d->_attributePoints.last().values[percentString] = 1;
452 interpolate(
d->_attributePoints.size() - 1, percentString, 1);
458 qreal prevpercent = 0;
459 qreal prevorigpercent = 0;
460 for (
int ii = 0; ii < attributePoints.
size(); ++ii) {
461 const AttributePoint &point = attributePoints.
at(ii);
462 if (point.values.contains(percentString)) {
465 (point.values.value(percentString)-prevpercent);
466 attributePoints[ii].scale =
scale;
468 attributePoints[ii].origpercent /=
length;
469 attributePoints[ii].percent = point.values.
value(percentString);
470 prevorigpercent = attributePoints.
at(ii).origpercent;
471 prevpercent = attributePoints.
at(ii).percent;
473 attributePoints[ii].origpercent /=
length;
474 attributePoints[ii].percent = attributePoints.
at(ii).origpercent;
491 if (!
d->componentComplete)
496 qreal startX =
d->startX.isValid() ?
d->startX.value : startPoint.
x();
497 qreal startY =
d->startY.isValid() ?
d->startY.value : startPoint.
y();
501 for (
QQuickCurve *curve : std::as_const(
d->_pathCurves)) {
504 data.endPoint = endPoint;
505 data.curves =
d->_pathCurves;
530 d->componentComplete =
false;
557 if (
QQuickCurve *curve = qobject_cast<QQuickCurve *>(pathElement))
558 d->_pathCurves.append(curve);
560 d->_pathTexts.append(
text);
571 d->componentComplete =
true;
589 if (!
d->componentComplete) {
595 qobject_cast<QQuickPathAttribute *>(pathElement))
598 return attrs.values();
600 return d->_attributes;
605 const int lastElement = reverse ? 0 :
path.elementCount() - 1;
606 const int start = reverse ? *current - 1 : *current + 1;
607 for (
int i=
start; reverse ?
i >= lastElement :
i <= lastElement; reverse ? --
i : ++
i) {
627 path.elementAt(
i+2));
628 *bezLength =
b.length();
636 *current = lastElement;
645 if (
path.elementCount() == 2
652 return qCeil(pathLength*5);
658 return 3*
t*
t*(
d - 3*
c + 3*
b -
a) + 6*
t*(
c - 2*
b +
a) + 3*(
b -
a);
661void QQuickPath::createPointCache()
const
664 qreal pathLength =
d->pathLength;
665 if (pathLength <= 0 ||
qt_is_nan(pathLength))
669 const int lastElement =
d->_path.elementCount() - 1;
672 int currElement = -1;
675 qreal currLength = bezLength;
676 qreal epc = currLength / pathLength;
678 for (
int i = 0;
i <
d->_pointCache.size();
i++) {
680 qreal prevPercent = 0;
681 qreal prevOrigPercent = 0;
682 for (
int ii = 0; ii <
d->_attributePoints.size(); ++ii) {
684 const AttributePoint &point =
d->_attributePoints.at(ii);
685 if (percent < point.percent || ii == d->_attributePoints.size() - 1) {
686 qreal elementPercent = (percent - prevPercent);
688 qreal spc = prevOrigPercent + elementPercent * point.scale;
691 if (currElement > lastElement)
693 currBez =
nextBezier(
d->_path, &currElement, &bezLength);
694 if (bezLength == 0.0) {
695 currLength = pathLength;
699 currLength += bezLength;
700 epc = currLength / pathLength;
702 qreal realT = (pathLength * spc - (currLength - bezLength)) / bezLength;
706 prevOrigPercent = point.origpercent;
707 prevPercent = point.percent;
715 d->prevBez.isValid =
false;
735 emit simplifiedChanged();
741 return d->simplified;
782 return p > .5 ? backwardsPointAt(
path, pathLength, attributePoints, prevBez,
p,
angle) :
783 forwardsPointAt(
path, pathLength, attributePoints, prevBez,
p,
angle);
785 return p < prevBez.
p ? backwardsPointAt(
path, pathLength, attributePoints, prevBez,
p,
angle) :
786 forwardsPointAt(
path, pathLength, attributePoints, prevBez,
p,
angle);
791 if (pathLength <= 0 ||
qt_is_nan(pathLength))
792 return path.pointAtPercent(0);
794 const int lastElement =
path.elementCount() - 1;
795 bool haveCachedBez = prevBez.
isValid;
796 int currElement = haveCachedBez ? prevBez.
element : -1;
800 qreal epc = currLength / pathLength;
803 qreal prevPercent = 0;
804 qreal prevOrigPercent = 0;
805 for (
int ii = 0; ii < attributePoints.
size(); ++ii) {
807 const AttributePoint &point = attributePoints.
at(ii);
808 if (percent < point.percent || ii == attributePoints.
size() - 1) {
809 qreal elementPercent = (percent - prevPercent);
811 qreal spc = prevOrigPercent + elementPercent * point.scale;
814 Q_ASSERT(!(currElement > lastElement));
817 currLength += bezLength;
818 epc = currLength / pathLength;
827 qreal realT = (pathLength * spc - (currLength - bezLength)) / bezLength;
837 prevOrigPercent = point.origpercent;
838 prevPercent = point.percent;
847 if (pathLength <= 0 ||
qt_is_nan(pathLength))
848 return path.pointAtPercent(0);
850 const int firstElement = 1;
851 bool haveCachedBez = prevBez.
isValid;
852 int currElement = haveCachedBez ? prevBez.
element :
path.elementCount();
856 qreal prevLength = currLength - bezLength;
857 qreal epc = prevLength / pathLength;
859 for (
int ii = attributePoints.
size() - 1; ii > 0; --ii) {
861 const AttributePoint &point = attributePoints.
at(ii);
862 const AttributePoint &prevPoint = attributePoints.
at(ii-1);
863 if (percent > prevPoint.percent || ii == 1) {
864 qreal elementPercent = (percent - prevPoint.percent);
866 qreal spc = prevPoint.origpercent + elementPercent * point.scale;
869 Q_ASSERT(!(currElement < firstElement));
874 currLength = (currElement == firstElement) ? bezLength : prevLength;
875 prevLength = currLength - bezLength;
876 epc = prevLength / pathLength;
885 qreal realT = (pathLength * spc - (currLength - bezLength)) / bezLength;
920 return d->_path.pointAtPercent(
t);
922 if (
d->_pointCache.isEmpty()) {
924 if (
d->_pointCache.isEmpty())
931 qreal delta = idxf - idx1;
938 return d->_pointCache.at(idx1);
941 int idx2 =
qCeil(idxf);
957 if (percent < 0 || percent > 1)
960 for (
int ii = 0; ii <
d->_attributePoints.size(); ++ii) {
961 const AttributePoint &point =
d->_attributePoints.at(ii);
963 if (point.percent == percent) {
964 return point.values.value(
name);
965 }
else if (point.percent > percent) {
967 ii?(
d->_attributePoints.at(ii - 1).values.value(
name)):0;
969 ii?(
d->_attributePoints.at(ii - 1).percent):0;
970 qreal curValue = point.values.value(
name);
971 qreal curPercent = point.percent;
973 return lastValue + (curValue - lastValue) * (percent - lastPercent) / (curPercent - lastPercent);
1027 if (_relativeX.
isNull || _relativeX !=
x) {
1046 if (_relativeY.
isNull || _relativeY !=
y) {
1168 if (_value !=
value) {
1224 bool isEnd =
data.index ==
data.curves.size() - 1;
1358 if (_controlX !=
x) {
1376 if (_controlY !=
y) {
1400 return _relativeControlX;
1405 if (_relativeControlX.
isNull || _relativeControlX !=
x) {
1406 _relativeControlX =
x;
1414 return _relativeControlX.
isValid();
1419 return _relativeControlY;
1424 if (_relativeControlY.
isNull || _relativeControlY !=
y) {
1425 _relativeControlY =
y;
1433 return _relativeControlY.
isValid();
1438 const QPointF &prevPoint =
path.currentPosition();
1510 if (_control1X !=
x) {
1524 if (_control1Y !=
y) {
1544 if (_control2X !=
x) {
1558 if (_control2Y !=
y) {
1584 return _relativeControl1X;
1589 if (_relativeControl1X.
isNull || _relativeControl1X !=
x) {
1590 _relativeControl1X =
x;
1598 return _relativeControl1X.
isValid();
1603 return _relativeControl1Y;
1608 if (_relativeControl1Y.
isNull || _relativeControl1Y !=
y) {
1609 _relativeControl1Y =
y;
1617 return _relativeControl1Y.
isValid();
1622 return _relativeControl2X;
1627 if (_relativeControl2X.
isNull || _relativeControl2X !=
x) {
1628 _relativeControl2X =
x;
1636 return _relativeControl2X.
isValid();
1641 return _relativeControl2Y;
1646 if (_relativeControl2Y.
isNull || _relativeControl2Y !=
y) {
1647 _relativeControl2Y =
y;
1655 return _relativeControl2Y.
isValid();
1660 const QPointF &prevPoint =
path.currentPosition();
1737 if (qobject_cast<QQuickPathCatmullRomCurve*>(curve)) {
1738 prev =
path.currentPosition();
1741 prev =
path.currentPosition();
1742 bool prevFarSet =
false;
1743 if (
index == -1 &&
data.curves.size() > 1) {
1744 if (qobject_cast<QQuickPathCatmullRomCurve*>(
data.curves.at(
data.curves.size()-1))) {
1750 for (
int i =
data.index;
i <
data.curves.size(); ++
i) {
1753 if (
i ==
data.curves.size()-2)
1772 if (
index <
data.curves.size() && qobject_cast<QQuickPathCatmullRomCurve*>(
data.curves.at(
index))) {
1779 if (point ==
QPointF(
path.elementAt(0)) && qobject_cast<QQuickPathCatmullRomCurve*>(
data.curves.at(0)) &&
path.elementCount() >= 3) {
1799 point.
x() *
qreal(0.167),
1800 prevFar.
y() *
qreal(-0.167) +
1802 point.
y() *
qreal(0.167));
1807 prev.
y() *
qreal(0.167) +
1811 path.cubicTo(control1, control2, point);
1885 if (_radiusX == radius)
1900 if (_radiusY == radius)
1929 return _useLargeArc;
1934 if (_useLargeArc == largeArc)
1937 _useLargeArc = largeArc;
1997 return _xAxisRotation;
2002 if (_xAxisRotation == rotation)
2005 _xAxisRotation = rotation;
2006 emit xAxisRotationChanged();
2012 const QPointF &startPoint =
path.currentPosition();
2022 startPoint.
x(), startPoint.
y());
2092 if (_radiusX == radius)
2107 if (_radiusY == radius)
2130 if (_startAngle ==
angle)
2133 _startAngle =
angle;
2154 if (_sweepAngle ==
angle)
2157 _sweepAngle =
angle;
2174 return _moveToStart;
2179 if (_moveToStart == move)
2182 _moveToStart = move;
2189 qreal x = _centerX - _radiusX;
2190 qreal y = _centerY - _radiusY;
2342 if (_value !=
value) {
2404 if (
path.userType() == QMetaType::QPolygonF) {
2417 pathList.
append(
v.toPointF());
2420 qWarning() <<
"PathPolyline: path of type" <<
path.userType() <<
"not supported";
2426 if (m_path !=
path) {
2431 if (oldStart != newStart)
2439 if (m_path.size()) {
2448 if (m_path.size() < 2)
2451 path.moveTo(m_path.first());
2452 for (
int i = 1;
i < m_path.size(); ++
i)
2453 path.lineTo(m_path.at(
i));
2563 if (point.canConvert<
QPointF>())
2564 l.
append(point.toPointF());
2572 qWarning() <<
"PathMultiline: paths of type" <<
paths.userType() <<
"not supported";
2579 if (m_paths !=
paths) {
2584 if (oldStart != newStart)
2593 return m_paths.first().first();
2599 if (!m_paths.size())
2602 path.moveTo(
p.first());
2603 for (
int i = 1;
i <
p.size(); ++
i)
2805void QQuickPathText::updatePath()
const
2810 _path.
addText(0.0, 0.0, _font, _text);
2822 path.addPath(_path);
2827#include "moc_qquickpath_p.cpp"
static QBezier fromPoints(const QPointF &p1, const QPointF &p2, const QPointF &p3, const QPointF &p4)
QPointF pointAt(qreal t) const
qsizetype size() const noexcept
const T & constLast() const noexcept
iterator insert(qsizetype i, parameter_type t)
const_reference at(qsizetype i) const noexcept
T value(qsizetype i) const
void append(parameter_type t)
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
void translate(qreal dx, qreal dy)
Translates all elements in the path by ({dx}, {dy}).
QRectF boundingRect() const
Returns the bounding rectangle of this painter path as a rectangle with floating point precision.
bool isEmpty() const
Returns true if either there are no elements in this path, or if the only element is a MoveToElement;...
void addText(const QPointF &point, const QFont &f, const QString &text)
Adds the given text to this path as a set of closed subpaths created from the font supplied.
\inmodule QtCore\reentrant
constexpr qreal x() const noexcept
Returns the x coordinate of this point.
constexpr qreal y() const noexcept
Returns the y coordinate of this point.
The QPolygonF class provides a list of points using floating point precision.
The QQmlListProperty class allows applications to expose list-like properties of QObject-derived clas...
void setRelativeY(qreal y)
void setRelativeX(qreal x)
void setMoveToStart(bool)
void setStartAngle(qreal)
void moveToStartChanged()
void addToPath(QPainterPath &path, const QQuickPathData &) override
void setSweepAngle(qreal)
void setUseLargeArc(bool)
void setXAxisRotation(qreal rotation)
void addToPath(QPainterPath &path, const QQuickPathData &) override
void setDirection(ArcDirection direction)
void useLargeArcChanged()
void setValue(qreal value)
void setName(const QString &name)
void addToPath(QPainterPath &path, const QQuickPathData &) override
void relativeControl1XChanged()
void setControl2X(qreal x)
bool hasRelativeControl1X()
bool hasRelativeControl2X()
void setControl2Y(qreal y)
bool hasRelativeControl1Y()
void addToPath(QPainterPath &path, const QQuickPathData &) override
void setRelativeControl1X(qreal x)
bool hasRelativeControl2Y()
void setRelativeControl1Y(qreal y)
void relativeControl2YChanged()
void relativeControl1YChanged()
void setControl1Y(qreal y)
void setControl1X(qreal x)
void setRelativeControl2X(qreal x)
void relativeControl2XChanged()
void setRelativeControl2Y(qreal y)
void addToPath(QPainterPath &path, const QQuickPathData &) override
void addToPath(QPainterPath &path, const QQuickPathData &) override
\qmltype PathMove \instantiates QQuickPathMove \inqmlmodule QtQuick
void addToPath(QPainterPath &path, const QQuickPathData &) override
void setPaths(const QVariant &paths)
QQuickPathMultiline(QObject *parent=nullptr)
\qmltype PathMultiline \instantiates QQuickPathMultiline \inqmlmodule QtQuick
void setValue(qreal value)
QQuickPathPolyline(QObject *parent=nullptr)
\qmltype PathPolyline \instantiates QQuickPathPolyline \inqmlmodule QtQuick
void addToPath(QPainterPath &path, const QQuickPathData &data) override
void setPath(const QVariant &path)
static QQuickPathPrivate * get(QQuickPath *path)
void setRelativeControlY(qreal y)
void addToPath(QPainterPath &path, const QQuickPathData &) override
void setControlX(qreal x)
void setRelativeControlX(qreal x)
bool hasRelativeControlY()
void relativeControlYChanged()
bool hasRelativeControlX()
void relativeControlXChanged()
void setControlY(qreal y)
void setPath(const QString &path)
void addToPath(QPainterPath &path, const QQuickPathData &) override
void addToPath(QPainterPath &path)
qreal attributeAt(const QString &, qreal) const
void classBegin() override
Invoked after class creation, but before any properties have been set.
QPainterPath createShapePath(const QPointF &startPoint, const QPointF &endPoint, qreal &pathLength, bool *closed=nullptr)
void connectPathElements()
void setScale(const QSizeF &scale)
static QQuickPathElement * pathElements_at(QQmlListProperty< QQuickPathElement > *, qsizetype)
static qsizetype pathElements_count(QQmlListProperty< QQuickPathElement > *)
void componentComplete() override
Invoked after the root component that caused this instantiation has completed construction.
QPointF sequentialPointAt(qreal p, qreal *angle=nullptr) const
QQmlListProperty< QQuickPathElement > pathElements
\qmlproperty list<PathElement> QtQuick::Path::pathElements This property holds the objects composing ...
QPainterPath createPath(const QPointF &startPoint, const QPointF &endPoint, const QStringList &attributes, qreal &pathLength, QList< AttributePoint > &attributePoints, bool *closed=nullptr)
void invalidateSequentialHistory() const
QQuickPath(QObject *parent=nullptr)
\qmltype PathElement \instantiates QQuickPathElement \inqmlmodule QtQuick
void disconnectPathElements()
static void pathElements_append(QQmlListProperty< QQuickPathElement > *, QQuickPathElement *)
QStringList attributes() const
void setSimplified(bool simplified)
\qmlproperty bool QtQuick::Path::simplified
QPainterPath path() const
bool isClosed() const
\qmlproperty bool QtQuick::Path::closed This property holds whether the start and end of the path are...
static void pathElements_clear(QQmlListProperty< QQuickPathElement > *)
\inmodule QtCore\reentrant
constexpr qreal y() const noexcept
Returns the y-coordinate of the rectangle's top edge.
\macro QT_RESTRICTED_CAST_FROM_ASCII
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
qsizetype length() const
Returns the number of characters in this string.
static auto fromValue(T &&value) noexcept(std::is_nothrow_copy_constructible_v< T > &&Private::CanUseInternalSpace< T >) -> std::enable_if_t< std::conjunction_v< std::is_copy_constructible< T >, std::is_destructible< T > >, QVariant >
Q_QUICK_PRIVATE_EXPORT void pathArc(QPainterPath &path, qreal rx, qreal ry, qreal x_axis_rotation, int large_arc_flag, int sweep_flag, qreal x, qreal y, qreal curx, qreal cury)
bool parsePathDataFast(const QString &dataStr, QPainterPath &path)
Combined button and popup list for selecting options.
static struct AttrInfo attrs[]
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
EGLOutputLayerEXT EGLint attribute
bool qFuzzyCompare(qfloat16 p1, qfloat16 p2) noexcept
constexpr const T & qBound(const T &min, const T &val, const T &max)
static Q_DECL_CONST_FUNCTION bool qt_is_nan(double d)
GLboolean GLboolean GLboolean b
GLsizei const GLfloat * v
[13]
GLint GLint GLint GLint GLint x
[0]
GLenum GLenum GLuint GLint GLint GLint yscale
GLint GLsizei GLsizei height
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLuint GLenum GLsizei length
GLenum GLenum GLsizei count
GLsizei const GLuint * paths
GLenum GLenum GLuint GLint GLint xscale
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLsizei const GLchar *const * path
GLenum GLenum GLenum GLenum GLenum scale
static qreal slopeAt(qreal t, qreal a, qreal b, qreal c, qreal d)
static qreal slopeAt(qreal t, qreal a, qreal b, qreal c, qreal d)
static QQuickPathPrivate * privatePath(QObject *object)
static int segmentCount(const QPainterPath &path, qreal pathLength)
QPointF positionForCurve(const QQuickPathData &data, const QPointF &prevPoint)
\qmltype PathLine \instantiates QQuickPathLine \inqmlmodule QtQuick
QPointF previousPathPosition(const QPainterPath &path)
\qmltype PathCurve \instantiates QQuickPathCatmullRomCurve \inqmlmodule QtQuick
static QBezier nextBezier(const QPainterPath &path, int *current, qreal *bezLength, bool reverse=false)
static void scalePath(QPainterPath &path, const QSizeF &scale)
#define QStringLiteral(str)
myObject disconnect()
[26]
QList< QQuickCurve * > curves
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent