1// Copyright (C) 2022 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#ifndef QQUADPATH_P_H
5#define QQUADPATH_P_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists for the convenience
12// of a number of Qt sources files. This header file may change from
13// version to version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include <QtCore/qrect.h>
19#include <QtCore/qlist.h>
20#include <QtCore/qdebug.h>
21#include <QtGui/qvector2d.h>
22#include <QtGui/qpainterpath.h>
23
24QT_BEGIN_NAMESPACE
25
26class QQuadPath
27{
28public:
29 class Element
30 {
31 public:
32 Element ()
33 : m_isSubpathStart(false), m_isSubpathEnd(false), m_isLine(false)
34 {
35 }
36
37 bool isSubpathStart() const
38 {
39 return m_isSubpathStart;
40 }
41
42 bool isSubpathEnd() const
43 {
44 return m_isSubpathEnd;
45 }
46
47 bool isLine() const
48 {
49 return m_isLine;
50 }
51
52 bool isConvex() const
53 {
54 return m_curvatureFlags & Convex;
55 }
56
57 QVector2D startPoint() const
58 {
59 return sp;
60 }
61
62 QVector2D controlPoint() const
63 {
64 return cp;
65 }
66
67 QVector2D endPoint() const
68 {
69 return ep;
70 }
71
72 QVector2D midPoint() const
73 {
74 return isLine() ? 0.5f * (sp + ep) : (0.25f * sp) + (0.5f * cp) + (0.25 * ep);
75 }
76
77 int childCount() const { return m_numChildren; }
78
79 int indexOfChild(int childNumber) const
80 {
81 Q_ASSERT(childNumber >= 0 && childNumber < childCount());
82 return -(m_firstChildIndex + 1 + childNumber);
83 }
84
85 QVector2D pointAtFraction(float t) const;
86
87 QVector2D tangentAtFraction(float t) const
88 {
89 return isLine() ? (ep - sp) : ((1 - t) * 2 * (cp - sp)) + (t * 2 * (ep - cp));
90 }
91
92 QVector2D normalAtFraction(float t) const
93 {
94 const QVector2D tan = tangentAtFraction(t);
95 return QVector2D(-tan.y(), tan.x());
96 }
97
98 float extent() const;
99
100 void setAsConvex(bool isConvex)
101 {
102 if (isConvex)
103 m_curvatureFlags = Element::CurvatureFlags(m_curvatureFlags | Element::Convex);
104 else
105 m_curvatureFlags = Element::CurvatureFlags(m_curvatureFlags & ~Element::Convex);
106 }
107
108 bool isControlPointOnLeft() const
109 {
110 return isPointOnLeft(p: cp, sp, ep);
111 }
112
113 private:
114 int intersectionsAtY(float y, float *fractions) const;
115
116 enum CurvatureFlags : quint8 {
117 CurvatureUndetermined = 0,
118 FillOnRight = 1,
119 Convex = 2
120 };
121
122 QVector2D sp;
123 QVector2D cp;
124 QVector2D ep;
125 int m_firstChildIndex = 0;
126 quint8 m_numChildren = 0;
127 CurvatureFlags m_curvatureFlags = CurvatureUndetermined;
128 quint8 m_isSubpathStart : 1;
129 quint8 m_isSubpathEnd : 1;
130 quint8 m_isLine : 1;
131 friend class QQuadPath;
132 friend QDebug operator<<(QDebug, const QQuadPath::Element &);
133 };
134
135 void moveTo(const QVector2D &to)
136 {
137 subPathToStart = true;
138 currentPoint = to;
139 }
140
141 void lineTo(const QVector2D &to)
142 {
143 addElement(control: {}, to, isLine: true);
144 }
145
146 void quadTo(const QVector2D &control, const QVector2D &to)
147 {
148 addElement(control, to);
149 }
150
151 Element &elementAt(int i)
152 {
153 return i < 0 ? m_childElements[-(i + 1)] : m_elements[i];
154 }
155
156 const Element &elementAt(int i) const
157 {
158 return i < 0 ? m_childElements[-(i + 1)] : m_elements[i];
159 }
160
161 int indexOfChildAt(int i, int childNumber) const
162 {
163 return elementAt(i).indexOfChild(childNumber);
164 }
165
166 QRectF controlPointRect() const;
167
168 Qt::FillRule fillRule() const { return m_fillRule; }
169 void setFillRule(Qt::FillRule rule) { m_fillRule = rule; }
170
171 void reserve(int size) { m_elements.reserve(size); }
172 int elementCount() const { return m_elements.size(); }
173 bool isEmpty() const { return m_elements.size() == 0; }
174 int elementCountRecursive() const;
175
176 static QQuadPath fromPainterPath(const QPainterPath &path);
177 QPainterPath toPainterPath() const;
178
179 QQuadPath subPathsClosed() const;
180 void addCurvatureData();
181 QQuadPath flattened() const;
182 QQuadPath dashed(qreal lineWidth, const QList<qreal> &dashPattern, qreal dashOffset = 0) const;
183 void splitElementAt(int index);
184 bool contains(const QVector2D &point) const;
185
186 template<typename Func>
187 void iterateChildrenOf(Element &e, Func &&lambda)
188 {
189 const int lastChildIndex = e.m_firstChildIndex + e.childCount() - 1;
190 for (int i = e.m_firstChildIndex; i <= lastChildIndex; i++) {
191 Element &c = m_childElements[i];
192 if (c.childCount() > 0)
193 iterateChildrenOf(c, lambda);
194 else
195 lambda(c);
196 }
197 }
198
199 template<typename Func>
200 void iterateChildrenOf(const Element &e, Func &&lambda) const
201 {
202 const int lastChildIndex = e.m_firstChildIndex + e.childCount() - 1;
203 for (int i = e.m_firstChildIndex; i <= lastChildIndex; i++) {
204 const Element &c = m_childElements[i];
205 if (c.childCount() > 0)
206 iterateChildrenOf(c, lambda);
207 else
208 lambda(c);
209 }
210 }
211
212 template<typename Func>
213 void iterateElements(Func &&lambda)
214 {
215 for (auto &e : m_elements) {
216 if (e.childCount() > 0)
217 iterateChildrenOf(e, lambda);
218 else
219 lambda(e);
220 }
221 }
222
223 template<typename Func>
224 void iterateElements(Func &&lambda) const
225 {
226 for (auto &e : m_elements) {
227 if (e.childCount() > 0)
228 iterateChildrenOf(e, lambda);
229 else
230 lambda(e);
231 }
232 }
233
234 static QVector2D closestPointOnLine(const QVector2D &p, const QVector2D &sp, const QVector2D &ep);
235 static bool isPointOnLeft(const QVector2D &p, const QVector2D &sp, const QVector2D &ep);
236 static bool isPointOnLine(const QVector2D &p, const QVector2D &sp, const QVector2D &ep);
237 static bool isPointNearLine(const QVector2D &p, const QVector2D &sp, const QVector2D &ep);
238
239private:
240 void addElement(const QVector2D &control, const QVector2D &to, bool isLine = false);
241 Element::CurvatureFlags coordinateOrderOfElement(const Element &element) const;
242
243 friend QDebug operator<<(QDebug, const QQuadPath &);
244
245 bool subPathToStart = true;
246 Qt::FillRule m_fillRule = Qt::OddEvenFill;
247 QVector2D currentPoint;
248 QList<Element> m_elements;
249 QList<Element> m_childElements;
250};
251
252QDebug operator<<(QDebug, const QQuadPath::Element &);
253QDebug operator<<(QDebug, const QQuadPath &);
254
255QT_END_NAMESPACE
256
257#endif
258

source code of qtdeclarative/src/quickshapes/qquadpath_p.h