31 enum PathHint : quint8 {
35 PathFillOnRight = 0x8,
37 PathNonIntersecting = 0x20,
38 PathNonOverlappingControlPointTriangles = 0x40
40 Q_DECLARE_FLAGS(PathHints, PathHint)
42 class Q_QUICK_EXPORT Element
46 : m_isSubpathStart(
false), m_isSubpathEnd(
false), m_isLine(
false)
50 Element (QVector2D s, QVector2D c, QVector2D e)
51 : sp(s), cp(c), ep(e), m_isSubpathStart(
false), m_isSubpathEnd(
false), m_isLine(
false)
55 bool isSubpathStart()
const
57 return m_isSubpathStart;
60 bool isSubpathEnd()
const
62 return m_isSubpathEnd;
72 return m_curvatureFlags & Convex;
75 QVector2D startPoint()
const
80 QVector2D controlPoint()
const
85 QVector2D endPoint()
const
90 QVector2D midPoint()
const
92 return isLine() ? 0.5f * (sp + ep) : (0.25f * sp) + (0.5f * cp) + (0.25 * ep);
96
97
98
99 QVector2D referencePoint()
const
102 QVector2D normal(sp.y() - ep.y(), ep.x() - sp.x());
103 return m_curvatureFlags & Element::FillOnRight ? sp + normal : sp - normal;
109 Element segmentFromTo(
float t0,
float t1)
const;
111 Element reversed()
const;
113 int childCount()
const {
return m_numChildren; }
115 int indexOfChild(
int childNumber)
const
117 Q_ASSERT(childNumber >= 0 && childNumber < childCount());
118 return -(m_firstChildIndex + 1 + childNumber);
121 QVector2D pointAtFraction(
float t)
const;
123 QVector2D tangentAtFraction(
float t)
const
125 return isLine() ? (ep - sp) : ((1 - t) * 2 * (cp - sp)) + (t * 2 * (ep - cp));
128 QVector2D normalAtFraction(
float t)
const
130 const QVector2D tan = tangentAtFraction(t);
131 return QVector2D(-tan.y(), tan.x());
134 float extent()
const;
136 void setAsConvex(
bool isConvex)
139 m_curvatureFlags = Element::CurvatureFlags(m_curvatureFlags | Element::Convex);
141 m_curvatureFlags = Element::CurvatureFlags(m_curvatureFlags & ~Element::Convex);
144 void setFillOnRight(
bool isFillOnRight)
147 m_curvatureFlags = Element::CurvatureFlags(m_curvatureFlags | Element::FillOnRight);
149 m_curvatureFlags = Element::CurvatureFlags(m_curvatureFlags & ~Element::FillOnRight);
152 bool isFillOnRight()
const {
return m_curvatureFlags & FillOnRight; }
154 bool isControlPointOnLeft()
const
156 return isPointOnLeft(cp, sp, ep);
159 enum CurvatureFlags : quint8 {
160 CurvatureUndetermined = 0,
165 enum FillSide : quint8 {
166 FillSideUndetermined = 0,
173 int intersectionsAtY(
float y,
float *fractions,
bool swapXY =
false)
const;
178 int m_firstChildIndex = 0;
179 quint8 m_numChildren = 0;
180 CurvatureFlags m_curvatureFlags = CurvatureUndetermined;
181 quint8 m_isSubpathStart : 1;
182 quint8 m_isSubpathEnd : 1;
184 friend class QQuadPath;
185#ifndef QT_NO_DEBUG_STREAM
186 friend Q_QUICK_EXPORT QDebug operator<<(QDebug,
const QQuadPath::Element &);
190 void moveTo(
const QVector2D &to)
192 m_subPathToStart =
true;
196 void lineTo(
const QVector2D &to)
198 addElement({}, to,
true);
201 void quadTo(
const QVector2D &control,
const QVector2D &to)
203 addElement(control, to);
206 Element &elementAt(
int i)
208 return i < 0 ? m_childElements[-(i + 1)] : m_elements[i];
211 const Element &elementAt(
int i)
const
213 return i < 0 ? m_childElements[-(i + 1)] : m_elements[i];
216 int indexOfChildAt(
int i,
int childNumber)
const
218 return elementAt(i).indexOfChild(childNumber);
221 QRectF controlPointRect()
const;
223 Qt::FillRule fillRule()
const {
return m_windingFill ? Qt::WindingFill : Qt::OddEvenFill; }
224 void setFillRule(Qt::FillRule rule) { m_windingFill = (rule == Qt::WindingFill); }
226 void reserve(
int size) { m_elements.reserve(size); }
227 int elementCount()
const {
return m_elements.size(); }
228 bool isEmpty()
const {
return m_elements.size() == 0; }
229 int elementCountRecursive()
const;
231 static QQuadPath fromPainterPath(
const QPainterPath &path, PathHints hints = {});
232 QPainterPath toPainterPath()
const;
233 QString asSvgString()
const;
235 QQuadPath subPathsClosed(
bool *didClose =
nullptr)
const;
236 void addCurvatureData();
237 QQuadPath flattened()
const;
238 QQuadPath dashed(qreal lineWidth,
const QList<qreal> &dashPattern, qreal dashOffset = 0)
const;
239 void splitElementAt(
int index);
240 bool contains(
const QVector2D &point)
const;
241 bool contains(
const QVector2D &point,
int fromIndex,
int toIndex)
const;
242 Element::FillSide fillSideOf(
int elementIdx,
float elementT)
const;
244 template<
typename Func>
245 void iterateChildrenOf(Element &e, Func &&lambda)
247 const int lastChildIndex = e.m_firstChildIndex + e.childCount() - 1;
248 for (
int i = e.m_firstChildIndex; i <= lastChildIndex; i++) {
249 Element &c = m_childElements[i];
250 if (c.childCount() > 0)
251 iterateChildrenOf(c, lambda);
257 template<
typename Func>
258 void iterateChildrenOf(
const Element &e, Func &&lambda)
const
260 const int lastChildIndex = e.m_firstChildIndex + e.childCount() - 1;
261 for (
int i = e.m_firstChildIndex; i <= lastChildIndex; i++) {
262 const Element &c = m_childElements[i];
263 if (c.childCount() > 0)
264 iterateChildrenOf(c, lambda);
270 template<
typename Func>
271 void iterateElements(Func &&lambda)
273 for (
int i = 0; i < m_elements.size(); i++) {
274 Element &e = m_elements[i];
275 if (e.childCount() > 0)
276 iterateChildrenOf(e, lambda);
282 template<
typename Func>
283 void iterateElements(Func &&lambda)
const
285 for (
int i = 0; i < m_elements.size(); i++) {
286 const Element &e = m_elements[i];
287 if (e.childCount() > 0)
288 iterateChildrenOf(e, lambda);
294 static QVector2D closestPointOnLine(
const QVector2D &p,
const QVector2D &sp,
const QVector2D &ep);
295 static bool isPointOnLeft(
const QVector2D &p,
const QVector2D &sp,
const QVector2D &ep);
296 static bool isPointOnLine(
const QVector2D &p,
const QVector2D &sp,
const QVector2D &ep);
297 static bool isPointNearLine(
const QVector2D &p,
const QVector2D &sp,
const QVector2D &ep);
299 bool testHint(PathHint hint)
const
301 return m_hints.testFlag(hint);
304 void setHint(PathHint hint,
bool on =
true)
306 m_hints.setFlag(hint, on);
309 PathHints pathHints()
const
314 void setPathHints(PathHints newHints)
320 void addElement(
const QVector2D &control,
const QVector2D &to,
bool isLine =
false);
321 void addElement(
const Element &e);
322 Element::FillSide coordinateOrderOfElement(
const Element &element)
const;
324#ifndef QT_NO_DEBUG_STREAM
325 friend Q_QUICK_EXPORT QDebug operator<<(QDebug,
const QQuadPath &);
328 QList<Element> m_elements;
329 QList<Element> m_childElements;
330 QVector2D m_currentPoint;
331 bool m_subPathToStart =
true;
332 bool m_windingFill =
false;
335 friend class QSGCurveProcessor;