1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtGui module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #ifndef QPATHCLIPPER_P_H
43 #define QPATHCLIPPER_P_H
49 // This file is not part of the Qt API. It exists purely as an
50 // implementation detail. This header file may change from version to
51 // version without notice, or even be removed.
56 #include <QtGui/qpainterpath.h>
57 #include <QtCore/qlist.h>
59 #include <private/qbezier_p.h>
60 #include <private/qdatabuffer_p.h>
71 class Q_AUTOTEST_EXPORT QPathClipper
81 QPathClipper(const QPainterPath &subject,
82 const QPainterPath &clip);
84 QPainterPath clip(Operation op = BoolAnd);
89 static bool pathToRect(const QPainterPath &path, QRectF *rect = 0);
90 static QPainterPath intersect(const QPainterPath &path, const QRectF &rect);
93 Q_DISABLE_COPY(QPathClipper)
96 ClipMode, // do the full clip
97 CheckMode // for contains/intersects (only interested in whether the result path is non-empty)
100 bool handleCrossingEdges(QWingedEdge &list, qreal y, ClipperMode mode);
101 bool doClip(QWingedEdge &list, ClipperMode mode);
103 QPainterPath subjectPath;
104 QPainterPath clipPath;
114 QPathVertex(const QPointF &p = QPointF(), int e = -1);
115 operator QPointF() const;
141 QPathEdge(int a = -1, int b = -1);
154 int next(Traversal traversal, Direction direction) const;
156 void setNext(Traversal traversal, Direction direction, int next);
157 void setNext(Direction direction, int next);
159 Direction directionTo(int vertex) const;
160 int vertex(Direction direction) const;
169 struct Intersection {
175 bool operator<(const Intersection &o) const {
181 Segment(int pathId, int vertexA, int vertexB)
195 // intersection index
202 QPathSegments(int reserve);
204 void setPath(const QPainterPath &path);
205 void addPath(const QPainterPath &path);
207 int intersections() const;
208 int segments() const;
211 const Segment &segmentAt(int index) const;
212 const QLineF lineAt(int index) const;
213 const QRectF &elementBounds(int index) const;
214 int pathId(int index) const;
216 const QPointF &pointAt(int vertex) const;
217 int addPoint(const QPointF &point);
219 const Intersection *intersectionAt(int index) const;
220 void addIntersection(int index, const Intersection &intersection);
225 QDataBuffer<QPointF> m_points;
226 QDataBuffer<Segment> m_segments;
227 QDataBuffer<Intersection> m_intersections;
232 class Q_AUTOTEST_EXPORT QWingedEdge
235 struct TraversalStatus
238 QPathEdge::Traversal traversal;
239 QPathEdge::Direction direction;
241 void flipDirection();
242 void flipTraversal();
248 QWingedEdge(const QPainterPath &subject, const QPainterPath &clip);
251 QPainterPath toPath() const;
253 int edgeCount() const;
255 QPathEdge *edge(int edge);
256 const QPathEdge *edge(int edge) const;
258 int vertexCount() const;
260 int addVertex(const QPointF &p);
262 QPathVertex *vertex(int vertex);
263 const QPathVertex *vertex(int vertex) const;
265 TraversalStatus next(const TraversalStatus &status) const;
267 int addEdge(const QPointF &a, const QPointF &b);
268 int addEdge(int vertexA, int vertexB);
270 bool isInside(qreal x, qreal y) const;
272 static QPathEdge::Traversal flip(QPathEdge::Traversal traversal);
273 static QPathEdge::Direction flip(QPathEdge::Direction direction);
276 void intersectAndAdd();
278 void printNode(int i, FILE *handle);
280 void removeEdge(int ei);
282 int insert(const QPathVertex &vertex);
283 TraversalStatus findInsertStatus(int vertex, int edge) const;
285 qreal delta(int vertex, int a, int b) const;
287 QDataBuffer<QPathEdge> m_edges;
288 QDataBuffer<QPathVertex> m_vertices;
290 QVector<qreal> m_splitPoints;
292 QPathSegments m_segments;
295 inline QPathEdge::QPathEdge(int a, int b)
310 inline int QPathEdge::next(Traversal traversal, Direction direction) const
312 return m_next[int(traversal)][int(direction)];
315 inline void QPathEdge::setNext(Traversal traversal, Direction direction, int next)
317 m_next[int(traversal)][int(direction)] = next;
320 inline void QPathEdge::setNext(Direction direction, int next)
322 m_next[0][int(direction)] = next;
323 m_next[1][int(direction)] = next;
326 inline QPathEdge::Direction QPathEdge::directionTo(int vertex) const
328 return first == vertex ? Backward : Forward;
331 inline int QPathEdge::vertex(Direction direction) const
333 return direction == Backward ? first : second;
336 inline QPathVertex::QPathVertex(const QPointF &p, int e)
343 inline QPathVertex::operator QPointF() const
345 return QPointF(x, y);
348 inline QPathSegments::QPathSegments(int reserve) :
351 m_intersections(reserve)
355 inline int QPathSegments::segments() const
357 return m_segments.size();
360 inline int QPathSegments::points() const
362 return m_points.size();
365 inline const QPointF &QPathSegments::pointAt(int i) const
367 return m_points.at(i);
370 inline int QPathSegments::addPoint(const QPointF &point)
373 return m_points.size() - 1;
376 inline const QPathSegments::Segment &QPathSegments::segmentAt(int index) const
378 return m_segments.at(index);
381 inline const QLineF QPathSegments::lineAt(int index) const
383 const Segment &segment = m_segments.at(index);
384 return QLineF(m_points.at(segment.va), m_points.at(segment.vb));
387 inline const QRectF &QPathSegments::elementBounds(int index) const
389 return m_segments.at(index).bounds;
392 inline int QPathSegments::pathId(int index) const
394 return m_segments.at(index).path;
397 inline const QPathSegments::Intersection *QPathSegments::intersectionAt(int index) const
399 const int intersection = m_segments.at(index).intersection;
400 if (intersection < 0)
403 return &m_intersections.at(intersection);
406 inline int QPathSegments::intersections() const
408 return m_intersections.size();
411 inline void QPathSegments::addIntersection(int index, const Intersection &intersection)
413 m_intersections << intersection;
415 Segment &segment = m_segments.at(index);
416 if (segment.intersection < 0) {
417 segment.intersection = m_intersections.size() - 1;
419 Intersection *isect = &m_intersections.at(segment.intersection);
421 while (isect->next != 0)
422 isect += isect->next;
424 isect->next = (m_intersections.size() - 1) - (isect - m_intersections.data());
428 inline void QWingedEdge::TraversalStatus::flipDirection()
430 direction = QWingedEdge::flip(direction);
433 inline void QWingedEdge::TraversalStatus::flipTraversal()
435 traversal = QWingedEdge::flip(traversal);
438 inline void QWingedEdge::TraversalStatus::flip()
444 inline int QWingedEdge::edgeCount() const
446 return m_edges.size();
449 inline QPathEdge *QWingedEdge::edge(int edge)
451 return edge < 0 ? 0 : &m_edges.at(edge);
454 inline const QPathEdge *QWingedEdge::edge(int edge) const
456 return edge < 0 ? 0 : &m_edges.at(edge);
459 inline int QWingedEdge::vertexCount() const
461 return m_vertices.size();
464 inline int QWingedEdge::addVertex(const QPointF &p)
467 return m_vertices.size() - 1;
470 inline QPathVertex *QWingedEdge::vertex(int vertex)
472 return vertex < 0 ? 0 : &m_vertices.at(vertex);
475 inline const QPathVertex *QWingedEdge::vertex(int vertex) const
477 return vertex < 0 ? 0 : &m_vertices.at(vertex);
480 inline QPathEdge::Traversal QWingedEdge::flip(QPathEdge::Traversal traversal)
482 return traversal == QPathEdge::RightTraversal ? QPathEdge::LeftTraversal : QPathEdge::RightTraversal;
485 inline QPathEdge::Direction QWingedEdge::flip(QPathEdge::Direction direction)
487 return direction == QPathEdge::Forward ? QPathEdge::Backward : QPathEdge::Forward;
494 #endif // QPATHCLIPPER_P_H