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
56QT_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
67QT_BEGIN_NAMESPACE
68
69class QQuickCurve;
70struct QQuickPathData
71{
72 int index;
73 QPointF endPoint;
74 QList<QQuickCurve*> curves;
75};
76
77class Q_QUICK_PRIVATE_EXPORT QQuickPathElement : public QObject
78{
79 Q_OBJECT
80public:
81 QQuickPathElement(QObject *parent=nullptr) : QObject(parent) {}
82Q_SIGNALS:
83 void changed();
84};
85
86class Q_QUICK_PRIVATE_EXPORT QQuickPathAttribute : public QQuickPathElement
87{
88 Q_OBJECT
89
90 Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
91 Q_PROPERTY(qreal value READ value WRITE setValue NOTIFY valueChanged)
92public:
93 QQuickPathAttribute(QObject *parent=nullptr) : QQuickPathElement(parent) {}
94
95
96 QString name() const;
97 void setName(const QString &name);
98
99 qreal value() const;
100 void setValue(qreal value);
101
102Q_SIGNALS:
103 void nameChanged();
104 void valueChanged();
105
106private:
107 QString _name;
108 qreal _value = 0;
109};
110
111class Q_QUICK_PRIVATE_EXPORT QQuickCurve : public QQuickPathElement
112{
113 Q_OBJECT
114
115 Q_PROPERTY(qreal x READ x WRITE setX NOTIFY xChanged)
116 Q_PROPERTY(qreal y READ y WRITE setY NOTIFY yChanged)
117 Q_PROPERTY(qreal relativeX READ relativeX WRITE setRelativeX NOTIFY relativeXChanged)
118 Q_PROPERTY(qreal relativeY READ relativeY WRITE setRelativeY NOTIFY relativeYChanged)
119public:
120 QQuickCurve(QObject *parent=nullptr) : QQuickPathElement(parent) {}
121
122 qreal x() const;
123 void setX(qreal x);
124 bool hasX();
125
126 qreal y() const;
127 void setY(qreal y);
128 bool hasY();
129
130 qreal relativeX() const;
131 void setRelativeX(qreal x);
132 bool hasRelativeX();
133
134 qreal relativeY() const;
135 void setRelativeY(qreal y);
136 bool hasRelativeY();
137
138 virtual void addToPath(QPainterPath &, const QQuickPathData &) {}
139
140Q_SIGNALS:
141 void xChanged();
142 void yChanged();
143 void relativeXChanged();
144 void relativeYChanged();
145
146private:
147 QQmlNullableValue<qreal> _x;
148 QQmlNullableValue<qreal> _y;
149 QQmlNullableValue<qreal> _relativeX;
150 QQmlNullableValue<qreal> _relativeY;
151};
152
153class Q_QUICK_PRIVATE_EXPORT QQuickPathLine : public QQuickCurve
154{
155 Q_OBJECT
156public:
157 QQuickPathLine(QObject *parent=nullptr) : QQuickCurve(parent) {}
158
159 void addToPath(QPainterPath &path, const QQuickPathData &) override;
160};
161
162class Q_QUICK_PRIVATE_EXPORT QQuickPathMove : public QQuickCurve
163{
164 Q_OBJECT
165public:
166 QQuickPathMove(QObject *parent=nullptr) : QQuickCurve(parent) {}
167
168 void addToPath(QPainterPath &path, const QQuickPathData &) override;
169};
170
171class Q_QUICK_PRIVATE_EXPORT QQuickPathQuad : public QQuickCurve
172{
173 Q_OBJECT
174
175 Q_PROPERTY(qreal controlX READ controlX WRITE setControlX NOTIFY controlXChanged)
176 Q_PROPERTY(qreal controlY READ controlY WRITE setControlY NOTIFY controlYChanged)
177 Q_PROPERTY(qreal relativeControlX READ relativeControlX WRITE setRelativeControlX NOTIFY relativeControlXChanged)
178 Q_PROPERTY(qreal relativeControlY READ relativeControlY WRITE setRelativeControlY NOTIFY relativeControlYChanged)
179public:
180 QQuickPathQuad(QObject *parent=nullptr) : QQuickCurve(parent) {}
181
182 qreal controlX() const;
183 void setControlX(qreal x);
184
185 qreal controlY() const;
186 void setControlY(qreal y);
187
188 qreal relativeControlX() const;
189 void setRelativeControlX(qreal x);
190 bool hasRelativeControlX();
191
192 qreal relativeControlY() const;
193 void setRelativeControlY(qreal y);
194 bool hasRelativeControlY();
195
196 void addToPath(QPainterPath &path, const QQuickPathData &) override;
197
198Q_SIGNALS:
199 void controlXChanged();
200 void controlYChanged();
201 void relativeControlXChanged();
202 void relativeControlYChanged();
203
204private:
205 qreal _controlX = 0;
206 qreal _controlY = 0;
207 QQmlNullableValue<qreal> _relativeControlX;
208 QQmlNullableValue<qreal> _relativeControlY;
209};
210
211class Q_QUICK_PRIVATE_EXPORT QQuickPathCubic : public QQuickCurve
212{
213 Q_OBJECT
214
215 Q_PROPERTY(qreal control1X READ control1X WRITE setControl1X NOTIFY control1XChanged)
216 Q_PROPERTY(qreal control1Y READ control1Y WRITE setControl1Y NOTIFY control1YChanged)
217 Q_PROPERTY(qreal control2X READ control2X WRITE setControl2X NOTIFY control2XChanged)
218 Q_PROPERTY(qreal control2Y READ control2Y WRITE setControl2Y NOTIFY control2YChanged)
219 Q_PROPERTY(qreal relativeControl1X READ relativeControl1X WRITE setRelativeControl1X NOTIFY relativeControl1XChanged)
220 Q_PROPERTY(qreal relativeControl1Y READ relativeControl1Y WRITE setRelativeControl1Y NOTIFY relativeControl1YChanged)
221 Q_PROPERTY(qreal relativeControl2X READ relativeControl2X WRITE setRelativeControl2X NOTIFY relativeControl2XChanged)
222 Q_PROPERTY(qreal relativeControl2Y READ relativeControl2Y WRITE setRelativeControl2Y NOTIFY relativeControl2YChanged)
223public:
224 QQuickPathCubic(QObject *parent=nullptr) : QQuickCurve(parent) {}
225
226 qreal control1X() const;
227 void setControl1X(qreal x);
228
229 qreal control1Y() const;
230 void setControl1Y(qreal y);
231
232 qreal control2X() const;
233 void setControl2X(qreal x);
234
235 qreal control2Y() const;
236 void setControl2Y(qreal y);
237
238 qreal relativeControl1X() const;
239 void setRelativeControl1X(qreal x);
240 bool hasRelativeControl1X();
241
242 qreal relativeControl1Y() const;
243 void setRelativeControl1Y(qreal y);
244 bool hasRelativeControl1Y();
245
246 qreal relativeControl2X() const;
247 void setRelativeControl2X(qreal x);
248 bool hasRelativeControl2X();
249
250 qreal relativeControl2Y() const;
251 void setRelativeControl2Y(qreal y);
252 bool hasRelativeControl2Y();
253
254 void addToPath(QPainterPath &path, const QQuickPathData &) override;
255
256Q_SIGNALS:
257 void control1XChanged();
258 void control1YChanged();
259 void control2XChanged();
260 void control2YChanged();
261 void relativeControl1XChanged();
262 void relativeControl1YChanged();
263 void relativeControl2XChanged();
264 void relativeControl2YChanged();
265
266private:
267 qreal _control1X = 0;
268 qreal _control1Y = 0;
269 qreal _control2X = 0;
270 qreal _control2Y = 0;
271 QQmlNullableValue<qreal> _relativeControl1X;
272 QQmlNullableValue<qreal> _relativeControl1Y;
273 QQmlNullableValue<qreal> _relativeControl2X;
274 QQmlNullableValue<qreal> _relativeControl2Y;
275};
276
277class Q_QUICK_PRIVATE_EXPORT QQuickPathCatmullRomCurve : public QQuickCurve
278{
279 Q_OBJECT
280public:
281 QQuickPathCatmullRomCurve(QObject *parent=nullptr) : QQuickCurve(parent) {}
282
283 void addToPath(QPainterPath &path, const QQuickPathData &) override;
284};
285
286class Q_QUICK_PRIVATE_EXPORT QQuickPathArc : public QQuickCurve
287{
288 Q_OBJECT
289 Q_PROPERTY(qreal radiusX READ radiusX WRITE setRadiusX NOTIFY radiusXChanged)
290 Q_PROPERTY(qreal radiusY READ radiusY WRITE setRadiusY NOTIFY radiusYChanged)
291 Q_PROPERTY(bool useLargeArc READ useLargeArc WRITE setUseLargeArc NOTIFY useLargeArcChanged)
292 Q_PROPERTY(ArcDirection direction READ direction WRITE setDirection NOTIFY directionChanged)
293 Q_PROPERTY(qreal xAxisRotation READ xAxisRotation WRITE setXAxisRotation NOTIFY xAxisRotationChanged REVISION 2)
294
295public:
296 QQuickPathArc(QObject *parent=nullptr)
297 : QQuickCurve(parent) {}
298
299 enum ArcDirection { Clockwise, Counterclockwise };
300 Q_ENUM(ArcDirection)
301
302 qreal radiusX() const;
303 void setRadiusX(qreal);
304
305 qreal radiusY() const;
306 void setRadiusY(qreal);
307
308 bool useLargeArc() const;
309 void setUseLargeArc(bool);
310
311 ArcDirection direction() const;
312 void setDirection(ArcDirection direction);
313
314 qreal xAxisRotation() const;
315 void setXAxisRotation(qreal rotation);
316
317 void addToPath(QPainterPath &path, const QQuickPathData &) override;
318
319Q_SIGNALS:
320 void radiusXChanged();
321 void radiusYChanged();
322 void useLargeArcChanged();
323 void directionChanged();
324 Q_REVISION(2) void xAxisRotationChanged();
325
326private:
327 qreal _radiusX = 0;
328 qreal _radiusY = 0;
329 bool _useLargeArc = false;
330 ArcDirection _direction = Clockwise;
331 qreal _xAxisRotation = 0;
332};
333
334class Q_QUICK_PRIVATE_EXPORT QQuickPathAngleArc : public QQuickCurve
335{
336 Q_OBJECT
337 Q_PROPERTY(qreal centerX READ centerX WRITE setCenterX NOTIFY centerXChanged)
338 Q_PROPERTY(qreal centerY READ centerY WRITE setCenterY NOTIFY centerYChanged)
339 Q_PROPERTY(qreal radiusX READ radiusX WRITE setRadiusX NOTIFY radiusXChanged)
340 Q_PROPERTY(qreal radiusY READ radiusY WRITE setRadiusY NOTIFY radiusYChanged)
341 Q_PROPERTY(qreal startAngle READ startAngle WRITE setStartAngle NOTIFY startAngleChanged)
342 Q_PROPERTY(qreal sweepAngle READ sweepAngle WRITE setSweepAngle NOTIFY sweepAngleChanged)
343 Q_PROPERTY(bool moveToStart READ moveToStart WRITE setMoveToStart NOTIFY moveToStartChanged)
344
345public:
346 QQuickPathAngleArc(QObject *parent=nullptr)
347 : QQuickCurve(parent) {}
348
349 qreal centerX() const;
350 void setCenterX(qreal);
351
352 qreal centerY() const;
353 void setCenterY(qreal);
354
355 qreal radiusX() const;
356 void setRadiusX(qreal);
357
358 qreal radiusY() const;
359 void setRadiusY(qreal);
360
361 qreal startAngle() const;
362 void setStartAngle(qreal);
363
364 qreal sweepAngle() const;
365 void setSweepAngle(qreal);
366
367 bool moveToStart() const;
368 void setMoveToStart(bool);
369
370 void addToPath(QPainterPath &path, const QQuickPathData &) override;
371
372Q_SIGNALS:
373 void centerXChanged();
374 void centerYChanged();
375 void radiusXChanged();
376 void radiusYChanged();
377 void startAngleChanged();
378 void sweepAngleChanged();
379 void moveToStartChanged();
380
381private:
382 qreal _centerX = 0;
383 qreal _centerY = 0;
384 qreal _radiusX = 0;
385 qreal _radiusY = 0;
386 qreal _startAngle = 0;
387 qreal _sweepAngle = 0;
388 bool _moveToStart = true;
389};
390
391class Q_QUICK_PRIVATE_EXPORT QQuickPathSvg : public QQuickCurve
392{
393 Q_OBJECT
394 Q_PROPERTY(QString path READ path WRITE setPath NOTIFY pathChanged)
395public:
396 QQuickPathSvg(QObject *parent=nullptr) : QQuickCurve(parent) {}
397
398 QString path() const;
399 void setPath(const QString &path);
400
401 void addToPath(QPainterPath &path, const QQuickPathData &) override;
402
403Q_SIGNALS:
404 void pathChanged();
405
406private:
407 QString _path;
408};
409
410class Q_QUICK_PRIVATE_EXPORT QQuickPathPercent : public QQuickPathElement
411{
412 Q_OBJECT
413 Q_PROPERTY(qreal value READ value WRITE setValue NOTIFY valueChanged)
414public:
415 QQuickPathPercent(QObject *parent=nullptr) : QQuickPathElement(parent) {}
416
417 qreal value() const;
418 void setValue(qreal value);
419
420Q_SIGNALS:
421 void valueChanged();
422
423private:
424 qreal _value = 0;
425};
426
427class Q_QUICK_PRIVATE_EXPORT QQuickPathPolyline : public QQuickCurve
428{
429 Q_OBJECT
430 Q_PROPERTY(QPointF start READ start NOTIFY startChanged)
431 Q_PROPERTY(QVariantList path READ path WRITE setPath NOTIFY pathChanged)
432public:
433 QQuickPathPolyline(QObject *parent=nullptr);
434
435 QVariantList path() const;
436 void setPath(const QVariantList &path);
437 void setPath(const QVector<QPointF> &path);
438 QPointF start() const;
439 void addToPath(QPainterPath &path, const QQuickPathData &data) override;
440
441Q_SIGNALS:
442 void pathChanged();
443 void startChanged();
444
445private:
446 QVector<QPointF> m_path;
447};
448
449class Q_QUICK_PRIVATE_EXPORT QQuickPathMultiline : public QQuickCurve
450{
451 Q_OBJECT
452 Q_PROPERTY(QPointF start READ start NOTIFY startChanged)
453 Q_PROPERTY(QVariantList paths READ paths WRITE setPaths NOTIFY pathsChanged)
454public:
455 QQuickPathMultiline(QObject *parent=nullptr);
456
457 QVariantList paths() const;
458 void setPaths(const QVariantList &paths);
459 void setPaths(const QVector<QVector<QPointF>> &paths);
460 QPointF start() const;
461 void addToPath(QPainterPath &path, const QQuickPathData &) override;
462
463Q_SIGNALS:
464 void pathsChanged();
465 void startChanged();
466
467private:
468 QPointF absolute(const QPointF &relative) const;
469
470 QVector<QVector<QPointF>> m_paths;
471};
472
473struct QQuickCachedBezier
474{
475 QQuickCachedBezier() {}
476 QBezier bezier;
477 int element;
478 qreal bezLength;
479 qreal currLength;
480 qreal p;
481 bool isValid = false;
482};
483
484class QQuickPathPrivate;
485class Q_QUICK_PRIVATE_EXPORT QQuickPath : public QObject, public QQmlParserStatus
486{
487 Q_OBJECT
488
489 Q_INTERFACES(QQmlParserStatus)
490 Q_PROPERTY(QQmlListProperty<QQuickPathElement> pathElements READ pathElements)
491 Q_PROPERTY(qreal startX READ startX WRITE setStartX NOTIFY startXChanged)
492 Q_PROPERTY(qreal startY READ startY WRITE setStartY NOTIFY startYChanged)
493 Q_PROPERTY(bool closed READ isClosed NOTIFY changed)
494 Q_PROPERTY(QSizeF scale READ scale WRITE setScale NOTIFY scaleChanged REVISION 14)
495 Q_CLASSINFO("DefaultProperty", "pathElements")
496 Q_INTERFACES(QQmlParserStatus)
497public:
498 QQuickPath(QObject *parent=nullptr);
499 ~QQuickPath() override;
500
501 QQmlListProperty<QQuickPathElement> pathElements();
502
503 qreal startX() const;
504 void setStartX(qreal x);
505 bool hasStartX() const;
506
507 qreal startY() const;
508 void setStartY(qreal y);
509 bool hasStartY() const;
510
511 bool isClosed() const;
512
513 QPainterPath path() const;
514 QStringList attributes() const;
515 qreal attributeAt(const QString &, qreal) const;
516 Q_REVISION(14) Q_INVOKABLE QPointF pointAtPercent(qreal t) const;
517 QPointF sequentialPointAt(qreal p, qreal *angle = nullptr) const;
518 void invalidateSequentialHistory() const;
519
520 QSizeF scale() const;
521 void setScale(const QSizeF &scale);
522
523Q_SIGNALS:
524 void changed();
525 void startXChanged();
526 void startYChanged();
527 Q_REVISION(14) void scaleChanged();
528
529protected:
530 QQuickPath(QQuickPathPrivate &dd, QObject *parent = nullptr);
531 void componentComplete() override;
532 void classBegin() override;
533 void disconnectPathElements();
534 void connectPathElements();
535 void gatherAttributes();
536
537 // pathElements property
538 static QQuickPathElement *pathElements_at(QQmlListProperty<QQuickPathElement> *, int);
539 static void pathElements_append(QQmlListProperty<QQuickPathElement> *, QQuickPathElement *);
540 static int pathElements_count(QQmlListProperty<QQuickPathElement> *);
541 static void pathElements_clear(QQmlListProperty<QQuickPathElement> *);
542
543private Q_SLOTS:
544 void processPath();
545
546private:
547 struct AttributePoint {
548 AttributePoint() {}
549 AttributePoint(const AttributePoint &other)
550 : percent(other.percent), scale(other.scale), origpercent(other.origpercent), values(other.values) {}
551 AttributePoint &operator=(const AttributePoint &other) {
552 percent = other.percent; scale = other.scale; origpercent = other.origpercent; values = other.values; return *this;
553 }
554 qreal percent = 0; //massaged percent along the painter path
555 qreal scale = 1;
556 qreal origpercent = 0; //'real' percent along the painter path
557 QHash<QString, qreal> values;
558 };
559
560 void interpolate(int idx, const QString &name, qreal value);
561 void endpoint(const QString &name);
562 void createPointCache() const;
563
564 static void interpolate(QList<AttributePoint> &points, int idx, const QString &name, qreal value);
565 static void endpoint(QList<AttributePoint> &attributePoints, const QString &name);
566 static QPointF forwardsPointAt(const QPainterPath &path, const qreal &pathLength, const QList<AttributePoint> &attributePoints, QQuickCachedBezier &prevBez, qreal p, qreal *angle = nullptr);
567 static QPointF backwardsPointAt(const QPainterPath &path, const qreal &pathLength, const QList<AttributePoint> &attributePoints, QQuickCachedBezier &prevBez, qreal p, qreal *angle = nullptr);
568
569private:
570 Q_DISABLE_COPY(QQuickPath)
571 Q_DECLARE_PRIVATE(QQuickPath)
572 friend class QQuickPathAnimationUpdater;
573
574public:
575 QPainterPath createPath(const QPointF &startPoint, const QPointF &endPoint, const QStringList &attributes, qreal &pathLength, QList<AttributePoint> &attributePoints, bool *closed = nullptr);
576 QPainterPath createShapePath(const QPointF &startPoint, const QPointF &endPoint, qreal &pathLength, bool *closed = nullptr);
577 static QPointF sequentialPointAt(const QPainterPath &path, const qreal &pathLength, const QList<AttributePoint> &attributePoints, QQuickCachedBezier &prevBez, qreal p, qreal *angle = nullptr);
578};
579
580QT_END_NAMESPACE
581
582QML_DECLARE_TYPE(QQuickPathElement)
583QML_DECLARE_TYPE(QQuickPathAttribute)
584QML_DECLARE_TYPE(QQuickCurve)
585QML_DECLARE_TYPE(QQuickPathLine)
586QML_DECLARE_TYPE(QQuickPathMove)
587QML_DECLARE_TYPE(QQuickPathQuad)
588QML_DECLARE_TYPE(QQuickPathCubic)
589QML_DECLARE_TYPE(QQuickPathCatmullRomCurve)
590QML_DECLARE_TYPE(QQuickPathArc)
591QML_DECLARE_TYPE(QQuickPathAngleArc)
592QML_DECLARE_TYPE(QQuickPathSvg)
593QML_DECLARE_TYPE(QQuickPathPercent)
594QML_DECLARE_TYPE(QQuickPathPolyline)
595QML_DECLARE_TYPE(QQuickPath)
596
597#endif // QQUICKPATH_H
598