Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qpathclipper_p.h
Go to the documentation of this file.
1// Copyright (C) 2016 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// Qt-Security score:significant reason:default
4
5#ifndef QPATHCLIPPER_P_H
6#define QPATHCLIPPER_P_H
7
8//
9// W A R N I N G
10// -------------
11//
12// This file is not part of the Qt API. It exists purely as an
13// implementation detail. This header file may change from version to
14// version without notice, or even be removed.
15//
16// We mean it.
17//
18
19#include <QtGui/private/qtguiglobal_p.h>
20#include <QtGui/qpainterpath.h>
21#include <QtCore/qlist.h>
22
23#include <private/qbezier_p.h>
24#include <private/qdatabuffer_p.h>
25#include <stdio.h>
26
27QT_BEGIN_NAMESPACE
28
29
30class QWingedEdge;
31
32class Q_GUI_EXPORT QPathClipper
33{
34public:
35 enum Operation {
36 BoolAnd,
37 BoolOr,
38 BoolSub,
39 Simplify
40 };
41public:
42 QPathClipper(const QPainterPath &subject,
43 const QPainterPath &clip);
44
45 QPainterPath clip(Operation op = BoolAnd);
46
47 bool intersect();
48 bool contains();
49
50 static bool pathToRect(const QPainterPath &path, QRectF *rect = nullptr);
51 static QPainterPath intersect(const QPainterPath &path, const QRectF &rect);
52
53private:
54 Q_DISABLE_COPY_MOVE(QPathClipper)
55
56 enum ClipperMode {
57 ClipMode, // do the full clip
58 CheckMode // for contains/intersects (only interested in whether the result path is non-empty)
59 };
60
61 bool handleCrossingEdges(QWingedEdge &list, qreal y, ClipperMode mode);
62 bool doClip(QWingedEdge &list, ClipperMode mode);
63
64 QPainterPath subjectPath;
65 QPainterPath clipPath;
66 Operation op;
67
68 int aMask;
69 int bMask;
70};
71
73{
74public:
75 QPathVertex(const QPointF &p = QPointF(), int e = -1);
76 operator QPointF() const;
77
78 int edge;
79
82};
84
86{
87public:
92
97
98 enum Type {
101 };
102
103 explicit QPathEdge(int a = -1, int b = -1);
104
105 mutable int flag;
106
109
110 int first;
112
113 double angle;
114 double invAngle;
115
116 int next(Traversal traversal, Direction direction) const;
117
118 void setNext(Traversal traversal, Direction direction, int next);
119 void setNext(Direction direction, int next);
120
121 Direction directionTo(int vertex) const;
122 int vertex(Direction direction) const;
123
124private:
125 int m_next[2][2] = { { -1, -1 }, { -1, -1 } };
126};
128
130{
131public:
135 int next;
136
137 bool operator<(const Intersection &o) const {
138 return t < o.t;
139 }
140 };
141 friend class QTypeInfo<Intersection>;
142
143 struct Segment {
144 Segment(int pathId, int vertexA, int vertexB)
145 : path(pathId)
146 , va(vertexA)
147 , vb(vertexB)
148 , intersection(-1)
149 {
150 }
151
152 int path;
153
154 // vertices
155 int va;
156 int vb;
157
158 // intersection index
160
162 };
163 friend class QTypeInfo<Segment>;
164
165
166 QPathSegments(int reserve);
167
168 void setPath(const QPainterPath &path);
169 void addPath(const QPainterPath &path);
170
171 int intersections() const;
172 int segments() const;
173 int points() const;
174
175 const Segment &segmentAt(int index) const;
176 const QLineF lineAt(int index) const;
177 const QRectF &elementBounds(int index) const;
178 int pathId(int index) const;
179
180 const QPointF &pointAt(int vertex) const;
181 int addPoint(const QPointF &point);
182
183 const Intersection *intersectionAt(int index) const;
184 void addIntersection(int index, const Intersection &intersection);
185
186 void mergePoints();
187
188private:
189 QDataBuffer<QPointF> m_points;
190 QDataBuffer<Segment> m_segments;
191 QDataBuffer<Intersection> m_intersections;
192
193 int m_pathId;
194};
197
198class Q_AUTOTEST_EXPORT QWingedEdge
199{
200public:
201 struct TraversalStatus
202 {
203 int edge;
204 QPathEdge::Traversal traversal;
205 QPathEdge::Direction direction;
206
207 void flipDirection();
208 void flipTraversal();
209
210 void flip();
211 };
212
213 QWingedEdge();
214 QWingedEdge(const QPainterPath &subject, const QPainterPath &clip);
215
216 void simplify();
217 QPainterPath toPath() const;
218
219 int edgeCount() const;
220
221 QPathEdge *edge(int edge);
222 const QPathEdge *edge(int edge) const;
223
224 int vertexCount() const;
225
226 int addVertex(const QPointF &p);
227
228 QPathVertex *vertex(int vertex);
229 const QPathVertex *vertex(int vertex) const;
230
231 TraversalStatus next(const TraversalStatus &status) const;
232
233 int addEdge(const QPointF &a, const QPointF &b);
234 int addEdge(int vertexA, int vertexB);
235
236 bool isInside(qreal x, qreal y) const;
237
238 static QPathEdge::Traversal flip(QPathEdge::Traversal traversal);
239 static QPathEdge::Direction flip(QPathEdge::Direction direction);
240
241private:
242 void intersectAndAdd();
243
244 void printNode(int i, FILE *handle);
245
246 void removeEdge(int ei);
247
248 int insert(const QPathVertex &vertex);
249 TraversalStatus findInsertStatus(int vertex, int edge) const;
250
251 qreal delta(int vertex, int a, int b) const;
252
253 QDataBuffer<QPathEdge> m_edges;
254 QDataBuffer<QPathVertex> m_vertices;
255
256 QList<qreal> m_splitPoints;
257
258 QPathSegments m_segments;
259};
260
261inline QPathEdge::QPathEdge(int a, int b)
262 : flag(0)
263 , windingA(0)
264 , windingB(0)
265 , first(a)
266 , second(b)
267 , angle(0)
268 , invAngle(0)
269{
270}
271
272inline int QPathEdge::next(Traversal traversal, Direction direction) const
273{
274 return m_next[int(traversal)][int(direction)];
275}
276
277inline void QPathEdge::setNext(Traversal traversal, Direction direction, int next)
278{
279 m_next[int(traversal)][int(direction)] = next;
280}
281
282inline void QPathEdge::setNext(Direction direction, int next)
283{
284 m_next[0][int(direction)] = next;
285 m_next[1][int(direction)] = next;
286}
287
288inline QPathEdge::Direction QPathEdge::directionTo(int vertex) const
289{
290 return first == vertex ? Backward : Forward;
291}
292
293inline int QPathEdge::vertex(Direction direction) const
294{
295 return direction == Backward ? first : second;
296}
297
298inline QPathVertex::QPathVertex(const QPointF &p, int e)
299 : edge(e)
300 , x(p.x())
301 , y(p.y())
302{
303}
304
305inline QPathVertex::operator QPointF() const
306{
307 return QPointF(x, y);
308}
309
310inline QPathSegments::QPathSegments(int reserve) :
314 m_pathId(0)
315{
316}
317
318inline int QPathSegments::segments() const
319{
320 return m_segments.size();
321}
322
323inline int QPathSegments::points() const
324{
325 return m_points.size();
326}
327
328inline const QPointF &QPathSegments::pointAt(int i) const
329{
330 return m_points.at(i);
331}
332
333inline int QPathSegments::addPoint(const QPointF &point)
334{
335 m_points << point;
336 return m_points.size() - 1;
337}
338
339inline const QPathSegments::Segment &QPathSegments::segmentAt(int index) const
340{
341 return m_segments.at(index);
342}
343
344inline const QLineF QPathSegments::lineAt(int index) const
345{
346 const Segment &segment = m_segments.at(index);
347 return QLineF(m_points.at(segment.va), m_points.at(segment.vb));
348}
349
350inline const QRectF &QPathSegments::elementBounds(int index) const
351{
352 return m_segments.at(index).bounds;
353}
354
355inline int QPathSegments::pathId(int index) const
356{
357 return m_segments.at(index).path;
358}
359
361{
362 const int intersection = m_segments.at(index).intersection;
363 if (intersection < 0)
364 return nullptr;
365 else
366 return &m_intersections.at(intersection);
367}
368
369inline int QPathSegments::intersections() const
370{
371 return m_intersections.size();
372}
373
374inline void QPathSegments::addIntersection(int index, const Intersection &intersection)
375{
376 m_intersections << intersection;
377
378 Segment &segment = m_segments.at(index);
379 if (segment.intersection < 0) {
380 segment.intersection = m_intersections.size() - 1;
381 } else {
382 Intersection *isect = &m_intersections.at(segment.intersection);
383
384 while (isect->next != 0)
385 isect += isect->next;
386
387 isect->next = (m_intersections.size() - 1) - (isect - m_intersections.data());
388 }
389}
390
391inline int QWingedEdge::edgeCount() const
392{
393 return m_edges.size();
394}
395
396inline QPathEdge *QWingedEdge::edge(int edge)
397{
398 return edge < 0 ? nullptr : &m_edges.at(edge);
399}
400
401inline const QPathEdge *QWingedEdge::edge(int edge) const
402{
403 return edge < 0 ? nullptr : &m_edges.at(edge);
404}
405
406inline int QWingedEdge::vertexCount() const
407{
408 return m_vertices.size();
409}
410
411inline int QWingedEdge::addVertex(const QPointF &p)
412{
413 m_vertices << p;
414 return m_vertices.size() - 1;
415}
416
417inline QPathVertex *QWingedEdge::vertex(int vertex)
418{
419 return vertex < 0 ? nullptr : &m_vertices.at(vertex);
420}
421
422inline const QPathVertex *QWingedEdge::vertex(int vertex) const
423{
424 return vertex < 0 ? nullptr : &m_vertices.at(vertex);
425}
426
427inline QPathEdge::Traversal QWingedEdge::flip(QPathEdge::Traversal traversal)
428{
429 return traversal == QPathEdge::RightTraversal ? QPathEdge::LeftTraversal : QPathEdge::RightTraversal;
430}
431
432inline void QWingedEdge::TraversalStatus::flipTraversal()
433{
434 traversal = QWingedEdge::flip(traversal);
435}
436
437inline QPathEdge::Direction QWingedEdge::flip(QPathEdge::Direction direction)
438{
439 return direction == QPathEdge::Forward ? QPathEdge::Backward : QPathEdge::Forward;
440}
441
442inline void QWingedEdge::TraversalStatus::flipDirection()
443{
444 direction = QWingedEdge::flip(direction);
445}
446
447inline void QWingedEdge::TraversalStatus::flip()
448{
449 flipDirection();
450 flipTraversal();
451}
452
453QT_END_NAMESPACE
454
455#endif // QPATHCLIPPER_P_H
bool hasIntersections(const QPathSegments &a, const QPathSegments &b) const
void produceIntersections(QPathSegments &segments)
QKdPointFinder(int point, const QPathSegments &segments, QKdPointTree &tree)
int result() const
QKdPointTree::Traversal operator()(QKdPointTree::Node &node, int depth)
Node * rootNode()
QKdPointTree(const QPathSegments &segments)
int build(int begin, int end, int depth=0)
QPathEdge(int a=-1, int b=-1)
void setNext(Traversal traversal, Direction direction, int next)
Direction directionTo(int vertex) const
int next(Traversal traversal, Direction direction) const
void setNext(Direction direction, int next)
double invAngle
int vertex(Direction direction) const
int points() const
int segments() const
int intersections() const
const Segment & segmentAt(int index) const
const Intersection * intersectionAt(int index) const
void setPath(const QPainterPath &path)
void addPath(const QPainterPath &path)
void addIntersection(int index, const Intersection &intersection)
int addPoint(const QPointF &point)
QPathSegments(int reserve)
const QRectF & elementBounds(int index) const
int pathId(int index) const
const QLineF lineAt(int index) const
const QPointF & pointAt(int vertex) const
Combined button and popup list for selecting options.
Q_DECLARE_TYPEINFO(QCrossingEdge, Q_PRIMITIVE_TYPE)
static qreal dot(const QPointF &a, const QPointF &b)
Q_DECLARE_TYPEINFO(QIntersection, Q_PRIMITIVE_TYPE)
static QList< QCrossingEdge > findCrossings(const QWingedEdge &list, qreal y)
static bool bool_op(bool a, bool b, QPathClipper::Operation op)
static void normalize(double &x, double &y)
static QT_BEGIN_NAMESPACE bool fuzzyIsNull(qreal d)
static bool fuzzyCompare(qreal a, qreal b)
static bool comparePoints(const QPointF &a, const QPointF &b)
static void clear(QWingedEdge &list, int edge, QPathEdge::Traversal traversal)
static void add(QPainterPath &path, const QWingedEdge &list, int edge, QPathEdge::Traversal traversal)
void qTraverseKdPointTree(QKdPointTree::Node &node, T &t, int depth=0)
static qreal component(const QPointF &point, unsigned int i)
static void addLineTo(QPainterPath &path, const QPointF &point)
static int commonEdge(const QWingedEdge &list, int a, int b)
static bool isLine(const QBezier &bezier)
InputIterator qFuzzyFind(InputIterator first, InputIterator last, qreal val)
static double computeAngle(const QPointF &v)
static void traverse(QWingedEdge &list, int edge, QPathEdge::Traversal traversal)
Q_DECLARE_TYPEINFO(QPathEdge, Q_PRIMITIVE_TYPE)
Q_DECLARE_TYPEINFO(QPathSegments::Segment, Q_PRIMITIVE_TYPE)
Q_DECLARE_TYPEINFO(QPathSegments::Intersection, Q_PRIMITIVE_TYPE)
Q_DECLARE_TYPEINFO(QPathVertex, Q_PRIMITIVE_TYPE)
bool operator<(const QCrossingEdge &edge) const
bool operator<(const Intersection &o) const
Segment(int pathId, int vertexA, int vertexB)
QPathVertex(const QPointF &p=QPointF(), int e=-1)