1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the QtQuick module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39 
40 #ifndef QQUICKPATH_H
41 #define QQUICKPATH_H
42 
43 //
44 //  W A R N I N G
45 //  -------------
46 //
47 // This file is not part of the Qt API.  It exists purely as an
48 // implementation detail.  This header file may change from version to
49 // version without notice, or even be removed.
50 //
51 // We mean it.
52 //
53 
54 #include <private/qtquickglobal_p.h>
55 
56 QT_REQUIRE_CONFIG(quick_path);
57 
58 #include <qqml.h>
59 
60 #include <private/qqmlnullablevalue_p.h>
61 #include <private/qbezier_p.h>
62 #include <private/qtquickglobal_p.h>
63 
64 #include <QtCore/QObject>
65 #include <QtGui/QPainterPath>
66 #include <QtGui/QFont>
67 
68 QT_BEGIN_NAMESPACE
69 
70 class QQuickCurve;
71 struct QQuickPathData
72 {
73     int index;
74     QPointF endPoint;
75     QList<QQuickCurve*> curves;
76 };
77 
78 class Q_QUICK_PRIVATE_EXPORT QQuickPathElement : public QObject
79 {
80     Q_OBJECT
81     QML_ANONYMOUS
82 public:
QObject(parent)83     QQuickPathElement(QObject *parent=nullptr) : QObject(parent) {}
84 Q_SIGNALS:
85     void changed();
86 };
87 
88 class Q_QUICK_PRIVATE_EXPORT QQuickPathAttribute : public QQuickPathElement
89 {
90     Q_OBJECT
91 
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)92     Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
93     Q_PROPERTY(qreal value READ value WRITE setValue NOTIFY valueChanged)
94     QML_NAMED_ELEMENT(PathAttribute)
95 public:
96     QQuickPathAttribute(QObject *parent=nullptr) : QQuickPathElement(parent) {}
97 
98 
99     QString name() const;
100     void setName(const QString &name);
101 
102     qreal value() const;
103     void setValue(qreal value);
104 
105 Q_SIGNALS:
106     void nameChanged();
107     void valueChanged();
108 
109 private:
110     QString _name;
111     qreal _value = 0;
112 };
113 
114 class Q_QUICK_PRIVATE_EXPORT QQuickCurve : public QQuickPathElement
115 {
116     Q_OBJECT
117 
Q_PROPERTY(qreal x READ x WRITE setX NOTIFY xChanged)118     Q_PROPERTY(qreal x READ x WRITE setX NOTIFY xChanged)
119     Q_PROPERTY(qreal y READ y WRITE setY NOTIFY yChanged)
120     Q_PROPERTY(qreal relativeX READ relativeX WRITE setRelativeX NOTIFY relativeXChanged)
121     Q_PROPERTY(qreal relativeY READ relativeY WRITE setRelativeY NOTIFY relativeYChanged)
122     QML_ANONYMOUS
123 public:
124     QQuickCurve(QObject *parent=nullptr) : QQuickPathElement(parent) {}
125 
126     qreal x() const;
127     void setX(qreal x);
128     bool hasX();
129 
130     qreal y() const;
131     void setY(qreal y);
132     bool hasY();
133 
134     qreal relativeX() const;
135     void setRelativeX(qreal x);
136     bool hasRelativeX();
137 
138     qreal relativeY() const;
139     void setRelativeY(qreal y);
140     bool hasRelativeY();
141 
addToPath(QPainterPath &,const QQuickPathData &)142     virtual void addToPath(QPainterPath &, const QQuickPathData &) {}
143 
144 Q_SIGNALS:
145     void xChanged();
146     void yChanged();
147     void relativeXChanged();
148     void relativeYChanged();
149 
150 private:
151     QQmlNullableValue<qreal> _x;
152     QQmlNullableValue<qreal> _y;
153     QQmlNullableValue<qreal> _relativeX;
154     QQmlNullableValue<qreal> _relativeY;
155 };
156 
157 class Q_QUICK_PRIVATE_EXPORT QQuickPathLine : public QQuickCurve
158 {
159     Q_OBJECT
QML_NAMED_ELEMENT(PathLine)160     QML_NAMED_ELEMENT(PathLine)
161 public:
162     QQuickPathLine(QObject *parent=nullptr) : QQuickCurve(parent) {}
163 
164     void addToPath(QPainterPath &path, const QQuickPathData &) override;
165 };
166 
167 class Q_QUICK_PRIVATE_EXPORT QQuickPathMove : public QQuickCurve
168 {
169     Q_OBJECT
QML_NAMED_ELEMENT(PathMove)170     QML_NAMED_ELEMENT(PathMove)
171     QML_ADDED_IN_MINOR_VERSION(9)
172 public:
173     QQuickPathMove(QObject *parent=nullptr) : QQuickCurve(parent) {}
174 
175     void addToPath(QPainterPath &path, const QQuickPathData &) override;
176 };
177 
178 class Q_QUICK_PRIVATE_EXPORT QQuickPathQuad : public QQuickCurve
179 {
180     Q_OBJECT
181 
Q_PROPERTY(qreal controlX READ controlX WRITE setControlX NOTIFY controlXChanged)182     Q_PROPERTY(qreal controlX READ controlX WRITE setControlX NOTIFY controlXChanged)
183     Q_PROPERTY(qreal controlY READ controlY WRITE setControlY NOTIFY controlYChanged)
184     Q_PROPERTY(qreal relativeControlX READ relativeControlX WRITE setRelativeControlX NOTIFY relativeControlXChanged)
185     Q_PROPERTY(qreal relativeControlY READ relativeControlY WRITE setRelativeControlY NOTIFY relativeControlYChanged)
186 
187     QML_NAMED_ELEMENT(PathQuad)
188 public:
189     QQuickPathQuad(QObject *parent=nullptr) : QQuickCurve(parent) {}
190 
191     qreal controlX() const;
192     void setControlX(qreal x);
193 
194     qreal controlY() const;
195     void setControlY(qreal y);
196 
197     qreal relativeControlX() const;
198     void setRelativeControlX(qreal x);
199     bool hasRelativeControlX();
200 
201     qreal relativeControlY() const;
202     void setRelativeControlY(qreal y);
203     bool hasRelativeControlY();
204 
205     void addToPath(QPainterPath &path, const QQuickPathData &) override;
206 
207 Q_SIGNALS:
208     void controlXChanged();
209     void controlYChanged();
210     void relativeControlXChanged();
211     void relativeControlYChanged();
212 
213 private:
214     qreal _controlX = 0;
215     qreal _controlY = 0;
216     QQmlNullableValue<qreal> _relativeControlX;
217     QQmlNullableValue<qreal> _relativeControlY;
218 };
219 
220 class Q_QUICK_PRIVATE_EXPORT QQuickPathCubic : public QQuickCurve
221 {
222     Q_OBJECT
223 
Q_PROPERTY(qreal control1X READ control1X WRITE setControl1X NOTIFY control1XChanged)224     Q_PROPERTY(qreal control1X READ control1X WRITE setControl1X NOTIFY control1XChanged)
225     Q_PROPERTY(qreal control1Y READ control1Y WRITE setControl1Y NOTIFY control1YChanged)
226     Q_PROPERTY(qreal control2X READ control2X WRITE setControl2X NOTIFY control2XChanged)
227     Q_PROPERTY(qreal control2Y READ control2Y WRITE setControl2Y NOTIFY control2YChanged)
228     Q_PROPERTY(qreal relativeControl1X READ relativeControl1X WRITE setRelativeControl1X NOTIFY relativeControl1XChanged)
229     Q_PROPERTY(qreal relativeControl1Y READ relativeControl1Y WRITE setRelativeControl1Y NOTIFY relativeControl1YChanged)
230     Q_PROPERTY(qreal relativeControl2X READ relativeControl2X WRITE setRelativeControl2X NOTIFY relativeControl2XChanged)
231     Q_PROPERTY(qreal relativeControl2Y READ relativeControl2Y WRITE setRelativeControl2Y NOTIFY relativeControl2YChanged)
232     QML_NAMED_ELEMENT(PathCubic)
233 public:
234     QQuickPathCubic(QObject *parent=nullptr) : QQuickCurve(parent) {}
235 
236     qreal control1X() const;
237     void setControl1X(qreal x);
238 
239     qreal control1Y() const;
240     void setControl1Y(qreal y);
241 
242     qreal control2X() const;
243     void setControl2X(qreal x);
244 
245     qreal control2Y() const;
246     void setControl2Y(qreal y);
247 
248     qreal relativeControl1X() const;
249     void setRelativeControl1X(qreal x);
250     bool hasRelativeControl1X();
251 
252     qreal relativeControl1Y() const;
253     void setRelativeControl1Y(qreal y);
254     bool hasRelativeControl1Y();
255 
256     qreal relativeControl2X() const;
257     void setRelativeControl2X(qreal x);
258     bool hasRelativeControl2X();
259 
260     qreal relativeControl2Y() const;
261     void setRelativeControl2Y(qreal y);
262     bool hasRelativeControl2Y();
263 
264     void addToPath(QPainterPath &path, const QQuickPathData &) override;
265 
266 Q_SIGNALS:
267     void control1XChanged();
268     void control1YChanged();
269     void control2XChanged();
270     void control2YChanged();
271     void relativeControl1XChanged();
272     void relativeControl1YChanged();
273     void relativeControl2XChanged();
274     void relativeControl2YChanged();
275 
276 private:
277     qreal _control1X = 0;
278     qreal _control1Y = 0;
279     qreal _control2X = 0;
280     qreal _control2Y = 0;
281     QQmlNullableValue<qreal> _relativeControl1X;
282     QQmlNullableValue<qreal> _relativeControl1Y;
283     QQmlNullableValue<qreal> _relativeControl2X;
284     QQmlNullableValue<qreal> _relativeControl2Y;
285 };
286 
287 class Q_QUICK_PRIVATE_EXPORT QQuickPathCatmullRomCurve : public QQuickCurve
288 {
289     Q_OBJECT
QML_NAMED_ELEMENT(PathCurve)290     QML_NAMED_ELEMENT(PathCurve)
291 public:
292     QQuickPathCatmullRomCurve(QObject *parent=nullptr) : QQuickCurve(parent) {}
293 
294     void addToPath(QPainterPath &path, const QQuickPathData &) override;
295 };
296 
297 class Q_QUICK_PRIVATE_EXPORT QQuickPathArc : public QQuickCurve
298 {
299     Q_OBJECT
Q_PROPERTY(qreal radiusX READ radiusX WRITE setRadiusX NOTIFY radiusXChanged)300     Q_PROPERTY(qreal radiusX READ radiusX WRITE setRadiusX NOTIFY radiusXChanged)
301     Q_PROPERTY(qreal radiusY READ radiusY WRITE setRadiusY NOTIFY radiusYChanged)
302     Q_PROPERTY(bool useLargeArc READ useLargeArc WRITE setUseLargeArc NOTIFY useLargeArcChanged)
303     Q_PROPERTY(ArcDirection direction READ direction WRITE setDirection NOTIFY directionChanged)
304     Q_PROPERTY(qreal xAxisRotation READ xAxisRotation WRITE setXAxisRotation NOTIFY xAxisRotationChanged REVISION 9)
305     QML_NAMED_ELEMENT(PathArc)
306 
307 public:
308     QQuickPathArc(QObject *parent=nullptr)
309         : QQuickCurve(parent) {}
310 
311     enum ArcDirection { Clockwise, Counterclockwise };
312     Q_ENUM(ArcDirection)
313 
314     qreal radiusX() const;
315     void setRadiusX(qreal);
316 
317     qreal radiusY() const;
318     void setRadiusY(qreal);
319 
320     bool useLargeArc() const;
321     void setUseLargeArc(bool);
322 
323     ArcDirection direction() const;
324     void setDirection(ArcDirection direction);
325 
326     qreal xAxisRotation() const;
327     void setXAxisRotation(qreal rotation);
328 
329     void addToPath(QPainterPath &path, const QQuickPathData &) override;
330 
331 Q_SIGNALS:
332     void radiusXChanged();
333     void radiusYChanged();
334     void useLargeArcChanged();
335     void directionChanged();
336     Q_REVISION(9) void xAxisRotationChanged();
337 
338 private:
339     qreal _radiusX = 0;
340     qreal _radiusY = 0;
341     bool _useLargeArc = false;
342     ArcDirection _direction = Clockwise;
343     qreal _xAxisRotation = 0;
344 };
345 
346 class Q_QUICK_PRIVATE_EXPORT QQuickPathAngleArc : public QQuickCurve
347 {
348     Q_OBJECT
Q_PROPERTY(qreal centerX READ centerX WRITE setCenterX NOTIFY centerXChanged)349     Q_PROPERTY(qreal centerX READ centerX WRITE setCenterX NOTIFY centerXChanged)
350     Q_PROPERTY(qreal centerY READ centerY WRITE setCenterY NOTIFY centerYChanged)
351     Q_PROPERTY(qreal radiusX READ radiusX WRITE setRadiusX NOTIFY radiusXChanged)
352     Q_PROPERTY(qreal radiusY READ radiusY WRITE setRadiusY NOTIFY radiusYChanged)
353     Q_PROPERTY(qreal startAngle READ startAngle WRITE setStartAngle NOTIFY startAngleChanged)
354     Q_PROPERTY(qreal sweepAngle READ sweepAngle WRITE setSweepAngle NOTIFY sweepAngleChanged)
355     Q_PROPERTY(bool moveToStart READ moveToStart WRITE setMoveToStart NOTIFY moveToStartChanged)
356 
357     QML_NAMED_ELEMENT(PathAngleArc)
358     QML_ADDED_IN_MINOR_VERSION(11)
359 
360 public:
361     QQuickPathAngleArc(QObject *parent=nullptr)
362         : QQuickCurve(parent) {}
363 
364     qreal centerX() const;
365     void setCenterX(qreal);
366 
367     qreal centerY() const;
368     void setCenterY(qreal);
369 
370     qreal radiusX() const;
371     void setRadiusX(qreal);
372 
373     qreal radiusY() const;
374     void setRadiusY(qreal);
375 
376     qreal startAngle() const;
377     void setStartAngle(qreal);
378 
379     qreal sweepAngle() const;
380     void setSweepAngle(qreal);
381 
382     bool moveToStart() const;
383     void setMoveToStart(bool);
384 
385     void addToPath(QPainterPath &path, const QQuickPathData &) override;
386 
387 Q_SIGNALS:
388     void centerXChanged();
389     void centerYChanged();
390     void radiusXChanged();
391     void radiusYChanged();
392     void startAngleChanged();
393     void sweepAngleChanged();
394     void moveToStartChanged();
395 
396 private:
397     qreal _centerX = 0;
398     qreal _centerY = 0;
399     qreal _radiusX = 0;
400     qreal _radiusY = 0;
401     qreal _startAngle = 0;
402     qreal _sweepAngle = 0;
403     bool _moveToStart = true;
404 };
405 
406 class Q_QUICK_PRIVATE_EXPORT QQuickPathSvg : public QQuickCurve
407 {
408     Q_OBJECT
Q_PROPERTY(QString path READ path WRITE setPath NOTIFY pathChanged)409     Q_PROPERTY(QString path READ path WRITE setPath NOTIFY pathChanged)
410     QML_NAMED_ELEMENT(PathSvg)
411 public:
412     QQuickPathSvg(QObject *parent=nullptr) : QQuickCurve(parent) {}
413 
414     QString path() const;
415     void setPath(const QString &path);
416 
417     void addToPath(QPainterPath &path, const QQuickPathData &) override;
418 
419 Q_SIGNALS:
420     void pathChanged();
421 
422 private:
423     QString _path;
424 };
425 
426 class Q_QUICK_PRIVATE_EXPORT QQuickPathPercent : public QQuickPathElement
427 {
428     Q_OBJECT
Q_PROPERTY(qreal value READ value WRITE setValue NOTIFY valueChanged)429     Q_PROPERTY(qreal value READ value WRITE setValue NOTIFY valueChanged)
430     QML_NAMED_ELEMENT(PathPercent)
431 public:
432     QQuickPathPercent(QObject *parent=nullptr) : QQuickPathElement(parent) {}
433 
434     qreal value() const;
435     void setValue(qreal value);
436 
437 Q_SIGNALS:
438     void valueChanged();
439 
440 private:
441     qreal _value = 0;
442 };
443 
444 class Q_QUICK_PRIVATE_EXPORT QQuickPathPolyline : public QQuickCurve
445 {
446     Q_OBJECT
447     Q_PROPERTY(QPointF start READ start NOTIFY startChanged)
448     Q_PROPERTY(QVariant path READ path WRITE setPath NOTIFY pathChanged)
449     QML_NAMED_ELEMENT(PathPolyline)
450     QML_ADDED_IN_MINOR_VERSION(14)
451 public:
452     QQuickPathPolyline(QObject *parent=nullptr);
453 
454     QVariant path() const;
455     void setPath(const QVariant &path);
456     void setPath(const QVector<QPointF> &path);
457     QPointF start() const;
458     void addToPath(QPainterPath &path, const QQuickPathData &data) override;
459 
460 Q_SIGNALS:
461     void pathChanged();
462     void startChanged();
463 
464 private:
465     QVector<QPointF> m_path;
466 };
467 
468 class Q_QUICK_PRIVATE_EXPORT QQuickPathMultiline : public QQuickCurve
469 {
470     Q_OBJECT
471     Q_PROPERTY(QPointF start READ start NOTIFY startChanged)
472     Q_PROPERTY(QVariant paths READ paths WRITE setPaths NOTIFY pathsChanged)
473     QML_NAMED_ELEMENT(PathMultiline)
474     QML_ADDED_IN_MINOR_VERSION(14)
475 public:
476     QQuickPathMultiline(QObject *parent=nullptr);
477 
478     QVariant paths() const;
479     void setPaths(const QVariant &paths);
480     void setPaths(const QVector<QVector<QPointF>> &paths);
481     QPointF start() const;
482     void addToPath(QPainterPath &path, const QQuickPathData &) override;
483 
484 Q_SIGNALS:
485     void pathsChanged();
486     void startChanged();
487 
488 private:
489     QPointF absolute(const QPointF &relative) const;
490 
491     QVector<QVector<QPointF>> m_paths;
492 };
493 
494 struct QQuickCachedBezier
495 {
QQuickCachedBezierQQuickCachedBezier496     QQuickCachedBezier() {}
497     QBezier bezier;
498     int element;
499     qreal bezLength;
500     qreal currLength;
501     qreal p;
502     bool isValid = false;
503 };
504 
505 class QQuickPathPrivate;
506 class Q_QUICK_PRIVATE_EXPORT QQuickPath : public QObject, public QQmlParserStatus
507 {
508     Q_OBJECT
509 
510     Q_INTERFACES(QQmlParserStatus)
511     Q_PROPERTY(QQmlListProperty<QQuickPathElement> pathElements READ pathElements)
512     Q_PROPERTY(qreal startX READ startX WRITE setStartX NOTIFY startXChanged)
513     Q_PROPERTY(qreal startY READ startY WRITE setStartY NOTIFY startYChanged)
514     Q_PROPERTY(bool closed READ isClosed NOTIFY changed)
515     Q_PROPERTY(QSizeF scale READ scale WRITE setScale NOTIFY scaleChanged REVISION 14)
516     Q_CLASSINFO("DefaultProperty", "pathElements")
517     QML_NAMED_ELEMENT(Path)
518     Q_INTERFACES(QQmlParserStatus)
519 public:
520     QQuickPath(QObject *parent=nullptr);
521     ~QQuickPath() override;
522 
523     QQmlListProperty<QQuickPathElement> pathElements();
524 
525     qreal startX() const;
526     void setStartX(qreal x);
527     bool hasStartX() const;
528 
529     qreal startY() const;
530     void setStartY(qreal y);
531     bool hasStartY() const;
532 
533     bool isClosed() const;
534 
535     QPainterPath path() const;
536     QStringList attributes() const;
537     qreal attributeAt(const QString &, qreal) const;
538     Q_REVISION(14) Q_INVOKABLE QPointF pointAtPercent(qreal t) const;
539     QPointF sequentialPointAt(qreal p, qreal *angle = nullptr) const;
540     void invalidateSequentialHistory() const;
541 
542     QSizeF scale() const;
543     void setScale(const QSizeF &scale);
544 
545 Q_SIGNALS:
546     void changed();
547     void startXChanged();
548     void startYChanged();
549     Q_REVISION(14) void scaleChanged();
550 
551 protected:
552     QQuickPath(QQuickPathPrivate &dd, QObject *parent = nullptr);
553     void componentComplete() override;
554     void classBegin() override;
555     void disconnectPathElements();
556     void connectPathElements();
557     void gatherAttributes();
558 
559     // pathElements property
560     static QQuickPathElement *pathElements_at(QQmlListProperty<QQuickPathElement> *, int);
561     static void pathElements_append(QQmlListProperty<QQuickPathElement> *, QQuickPathElement *);
562     static int pathElements_count(QQmlListProperty<QQuickPathElement> *);
563     static void pathElements_clear(QQmlListProperty<QQuickPathElement> *);
564 
565 private Q_SLOTS:
566     void processPath();
567 
568 private:
569     struct AttributePoint {
AttributePointAttributePoint570         AttributePoint() {}
AttributePointAttributePoint571         AttributePoint(const AttributePoint &other)
572             : percent(other.percent), scale(other.scale), origpercent(other.origpercent), values(other.values) {}
573         AttributePoint &operator=(const AttributePoint &other) {
574             percent = other.percent; scale = other.scale; origpercent = other.origpercent; values = other.values; return *this;
575         }
576         qreal percent = 0;      //massaged percent along the painter path
577         qreal scale = 1;
578         qreal origpercent = 0;  //'real' percent along the painter path
579         QHash<QString, qreal> values;
580     };
581 
582     void interpolate(int idx, const QString &name, qreal value);
583     void endpoint(const QString &name);
584     void createPointCache() const;
585 
586     static void interpolate(QList<AttributePoint> &points, int idx, const QString &name, qreal value);
587     static void endpoint(QList<AttributePoint> &attributePoints, const QString &name);
588     static QPointF forwardsPointAt(const QPainterPath &path, const qreal &pathLength, const QList<AttributePoint> &attributePoints, QQuickCachedBezier &prevBez, qreal p, qreal *angle = nullptr);
589     static QPointF backwardsPointAt(const QPainterPath &path, const qreal &pathLength, const QList<AttributePoint> &attributePoints, QQuickCachedBezier &prevBez, qreal p, qreal *angle = nullptr);
590 
591 private:
592     Q_DISABLE_COPY(QQuickPath)
593     Q_DECLARE_PRIVATE(QQuickPath)
594     friend class QQuickPathAnimationUpdater;
595 
596 public:
597     QPainterPath createPath(const QPointF &startPoint, const QPointF &endPoint, const QStringList &attributes, qreal &pathLength, QList<AttributePoint> &attributePoints, bool *closed = nullptr);
598     QPainterPath createShapePath(const QPointF &startPoint, const QPointF &endPoint, qreal &pathLength, bool *closed = nullptr);
599     static QPointF sequentialPointAt(const QPainterPath &path, const qreal &pathLength, const QList<AttributePoint> &attributePoints, QQuickCachedBezier &prevBez, qreal p, qreal *angle = nullptr);
600 };
601 
602 class Q_QUICK_PRIVATE_EXPORT QQuickPathText : public QQuickPathElement
603 {
604     Q_OBJECT
Q_PROPERTY(qreal x READ x WRITE setX NOTIFY xChanged)605     Q_PROPERTY(qreal x READ x WRITE setX NOTIFY xChanged)
606     Q_PROPERTY(qreal y READ y WRITE setY NOTIFY yChanged)
607     Q_PROPERTY(qreal width READ width NOTIFY changed)
608     Q_PROPERTY(qreal height READ height NOTIFY changed)
609     Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
610     Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY fontChanged)
611     QML_NAMED_ELEMENT(PathText)
612     QML_ADDED_IN_MINOR_VERSION(15)
613 public:
614     QQuickPathText(QObject *parent=nullptr) : QQuickPathElement(parent)
615     {
616         connect(this, &QQuickPathText::xChanged, this, &QQuickPathElement::changed);
617         connect(this, &QQuickPathText::yChanged, this, &QQuickPathElement::changed);
618         connect(this, &QQuickPathText::textChanged, this, &QQuickPathElement::changed);
619         connect(this, &QQuickPathText::fontChanged, this, &QQuickPathElement::changed);
620 
621         connect(this, &QQuickPathElement::changed, this, &QQuickPathText::invalidate);
622     }
623 
624     void addToPath(QPainterPath &path);
625 
x()626     qreal x() const { return _x; }
y()627     qreal y() const { return _y; }
text()628     QString text() const { return _text; }
font()629     QFont font() const { return _font; }
630 
setX(qreal x)631     void setX(qreal x)
632     {
633         if (qFuzzyCompare(_x, x))
634             return;
635 
636         _x = x;
637         Q_EMIT xChanged();
638     }
639 
setY(qreal y)640     void setY(qreal y)
641     {
642         if (qFuzzyCompare(_y, y))
643             return;
644 
645         _y = y;
646         Q_EMIT yChanged();
647     }
648 
setText(const QString & text)649     void setText(const QString &text)
650     {
651         if (text == _text)
652             return;
653 
654         _text = text;
655         Q_EMIT textChanged();
656     }
657 
setFont(const QFont & font)658     void setFont(const QFont &font)
659     {
660         if (font == _font)
661             return;
662 
663         _font = font;
664         Q_EMIT fontChanged();
665     }
666 
width()667     qreal width() const
668     {
669         updatePath();
670         return _path.boundingRect().width();
671     }
672 
height()673     qreal height() const
674     {
675         updatePath();
676         return _path.boundingRect().height();
677     }
678 
679 Q_SIGNALS:
680     void xChanged();
681     void yChanged();
682     void textChanged();
683     void fontChanged();
684 
685 private Q_SLOTS:
invalidate()686     void invalidate()
687     {
688         _path.clear();
689     }
690 
691 private:
692     void updatePath() const;
693 
694     QString _text;
695     qreal _x = qreal(0.0);
696     qreal _y = qreal(0.0);
697     QFont _font;
698 
699     mutable QPainterPath _path;
700 };
701 
702 QT_END_NAMESPACE
703 
704 QML_DECLARE_TYPE(QQuickPathElement)
705 QML_DECLARE_TYPE(QQuickPathAttribute)
706 QML_DECLARE_TYPE(QQuickCurve)
707 QML_DECLARE_TYPE(QQuickPathLine)
708 QML_DECLARE_TYPE(QQuickPathMove)
709 QML_DECLARE_TYPE(QQuickPathQuad)
710 QML_DECLARE_TYPE(QQuickPathCubic)
711 QML_DECLARE_TYPE(QQuickPathCatmullRomCurve)
712 QML_DECLARE_TYPE(QQuickPathArc)
713 QML_DECLARE_TYPE(QQuickPathAngleArc)
714 QML_DECLARE_TYPE(QQuickPathSvg)
715 QML_DECLARE_TYPE(QQuickPathPercent)
716 QML_DECLARE_TYPE(QQuickPathPolyline)
717 QML_DECLARE_TYPE(QQuickPath)
718 QML_DECLARE_TYPE(QQuickPathText)
719 
720 #endif // QQUICKPATH_H
721