source: trunk/src/gui/painting/qpathclipper_p.h

Last change on this file was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 11.2 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation (qt-info@nokia.com)
6**
7** This file is part of the QtGui module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at qt-info@nokia.com.
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#ifndef QPATHCLIPPER_P_H
43#define QPATHCLIPPER_P_H
44
45//
46// W A R N I N G
47// -------------
48//
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.
52//
53// We mean it.
54//
55
56#include <QtGui/qpainterpath.h>
57#include <QtCore/qlist.h>
58
59#include <private/qbezier_p.h>
60#include <private/qdatabuffer_p.h>
61#include <stdio.h>
62
63QT_BEGIN_HEADER
64
65QT_BEGIN_NAMESPACE
66
67QT_MODULE(Gui)
68
69class QWingedEdge;
70
71class Q_AUTOTEST_EXPORT QPathClipper
72{
73public:
74 enum Operation {
75 BoolAnd,
76 BoolOr,
77 BoolSub,
78 Simplify
79 };
80public:
81 QPathClipper(const QPainterPath &subject,
82 const QPainterPath &clip);
83
84 QPainterPath clip(Operation op = BoolAnd);
85
86 bool intersect();
87 bool contains();
88
89 static bool pathToRect(const QPainterPath &path, QRectF *rect = 0);
90 static QPainterPath intersect(const QPainterPath &path, const QRectF &rect);
91
92private:
93 Q_DISABLE_COPY(QPathClipper)
94
95 enum ClipperMode {
96 ClipMode, // do the full clip
97 CheckMode // for contains/intersects (only interested in whether the result path is non-empty)
98 };
99
100 bool handleCrossingEdges(QWingedEdge &list, qreal y, ClipperMode mode);
101 bool doClip(QWingedEdge &list, ClipperMode mode);
102
103 QPainterPath subjectPath;
104 QPainterPath clipPath;
105 Operation op;
106
107 int aMask;
108 int bMask;
109};
110
111struct QPathVertex
112{
113public:
114 QPathVertex(const QPointF &p = QPointF(), int e = -1);
115 operator QPointF() const;
116
117 int edge;
118
119 qreal x;
120 qreal y;
121};
122
123class QPathEdge
124{
125public:
126 enum Traversal {
127 RightTraversal,
128 LeftTraversal
129 };
130
131 enum Direction {
132 Forward,
133 Backward
134 };
135
136 enum Type {
137 Line,
138 Curve
139 };
140
141 QPathEdge(int a = -1, int b = -1);
142
143 mutable int flag;
144
145 int windingA;
146 int windingB;
147
148 int first;
149 int second;
150
151 double angle;
152 double invAngle;
153
154 int next(Traversal traversal, Direction direction) const;
155
156 void setNext(Traversal traversal, Direction direction, int next);
157 void setNext(Direction direction, int next);
158
159 Direction directionTo(int vertex) const;
160 int vertex(Direction direction) const;
161
162private:
163 int m_next[2][2];
164};
165
166class QPathSegments
167{
168public:
169 struct Intersection {
170 int vertex;
171 qreal t;
172
173 int next;
174
175 bool operator<(const Intersection &o) const {
176 return t < o.t;
177 }
178 };
179
180 struct Segment {
181 Segment(int pathId, int vertexA, int vertexB)
182 : path(pathId)
183 , va(vertexA)
184 , vb(vertexB)
185 , intersection(-1)
186 {
187 }
188
189 int path;
190
191 // vertices
192 int va;
193 int vb;
194
195 // intersection index
196 int intersection;
197
198 QRectF bounds;
199 };
200
201
202 QPathSegments(int reserve);
203
204 void setPath(const QPainterPath &path);
205 void addPath(const QPainterPath &path);
206
207 int intersections() const;
208 int segments() const;
209 int points() const;
210
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;
215
216 const QPointF &pointAt(int vertex) const;
217 int addPoint(const QPointF &point);
218
219 const Intersection *intersectionAt(int index) const;
220 void addIntersection(int index, const Intersection &intersection);
221
222 void mergePoints();
223
224private:
225 QDataBuffer<QPointF> m_points;
226 QDataBuffer<Segment> m_segments;
227 QDataBuffer<Intersection> m_intersections;
228
229 int m_pathId;
230};
231
232class Q_AUTOTEST_EXPORT QWingedEdge
233{
234public:
235 struct TraversalStatus
236 {
237 int edge;
238 QPathEdge::Traversal traversal;
239 QPathEdge::Direction direction;
240
241 void flipDirection();
242 void flipTraversal();
243
244 void flip();
245 };
246
247 QWingedEdge();
248 QWingedEdge(const QPainterPath &subject, const QPainterPath &clip);
249
250 void simplify();
251 QPainterPath toPath() const;
252
253 int edgeCount() const;
254
255 QPathEdge *edge(int edge);
256 const QPathEdge *edge(int edge) const;
257
258 int vertexCount() const;
259
260 int addVertex(const QPointF &p);
261
262 QPathVertex *vertex(int vertex);
263 const QPathVertex *vertex(int vertex) const;
264
265 TraversalStatus next(const TraversalStatus &status) const;
266
267 int addEdge(const QPointF &a, const QPointF &b);
268 int addEdge(int vertexA, int vertexB);
269
270 bool isInside(qreal x, qreal y) const;
271
272 static QPathEdge::Traversal flip(QPathEdge::Traversal traversal);
273 static QPathEdge::Direction flip(QPathEdge::Direction direction);
274
275private:
276 void intersectAndAdd();
277
278 void printNode(int i, FILE *handle);
279
280 void removeEdge(int ei);
281
282 int insert(const QPathVertex &vertex);
283 TraversalStatus findInsertStatus(int vertex, int edge) const;
284
285 qreal delta(int vertex, int a, int b) const;
286
287 QDataBuffer<QPathEdge> m_edges;
288 QDataBuffer<QPathVertex> m_vertices;
289
290 QVector<qreal> m_splitPoints;
291
292 QPathSegments m_segments;
293};
294
295inline QPathEdge::QPathEdge(int a, int b)
296 : flag(0)
297 , windingA(0)
298 , windingB(0)
299 , first(a)
300 , second(b)
301 , angle(0)
302 , invAngle(0)
303{
304 m_next[0][0] = -1;
305 m_next[1][0] = -1;
306 m_next[0][0] = -1;
307 m_next[1][0] = -1;
308}
309
310inline int QPathEdge::next(Traversal traversal, Direction direction) const
311{
312 return m_next[int(traversal)][int(direction)];
313}
314
315inline void QPathEdge::setNext(Traversal traversal, Direction direction, int next)
316{
317 m_next[int(traversal)][int(direction)] = next;
318}
319
320inline void QPathEdge::setNext(Direction direction, int next)
321{
322 m_next[0][int(direction)] = next;
323 m_next[1][int(direction)] = next;
324}
325
326inline QPathEdge::Direction QPathEdge::directionTo(int vertex) const
327{
328 return first == vertex ? Backward : Forward;
329}
330
331inline int QPathEdge::vertex(Direction direction) const
332{
333 return direction == Backward ? first : second;
334}
335
336inline QPathVertex::QPathVertex(const QPointF &p, int e)
337 : edge(e)
338 , x(p.x())
339 , y(p.y())
340{
341}
342
343inline QPathVertex::operator QPointF() const
344{
345 return QPointF(x, y);
346}
347
348inline QPathSegments::QPathSegments(int reserve) :
349 m_points(reserve),
350 m_segments(reserve),
351 m_intersections(reserve)
352{
353}
354
355inline int QPathSegments::segments() const
356{
357 return m_segments.size();
358}
359
360inline int QPathSegments::points() const
361{
362 return m_points.size();
363}
364
365inline const QPointF &QPathSegments::pointAt(int i) const
366{
367 return m_points.at(i);
368}
369
370inline int QPathSegments::addPoint(const QPointF &point)
371{
372 m_points << point;
373 return m_points.size() - 1;
374}
375
376inline const QPathSegments::Segment &QPathSegments::segmentAt(int index) const
377{
378 return m_segments.at(index);
379}
380
381inline const QLineF QPathSegments::lineAt(int index) const
382{
383 const Segment &segment = m_segments.at(index);
384 return QLineF(m_points.at(segment.va), m_points.at(segment.vb));
385}
386
387inline const QRectF &QPathSegments::elementBounds(int index) const
388{
389 return m_segments.at(index).bounds;
390}
391
392inline int QPathSegments::pathId(int index) const
393{
394 return m_segments.at(index).path;
395}
396
397inline const QPathSegments::Intersection *QPathSegments::intersectionAt(int index) const
398{
399 const int intersection = m_segments.at(index).intersection;
400 if (intersection < 0)
401 return 0;
402 else
403 return &m_intersections.at(intersection);
404}
405
406inline int QPathSegments::intersections() const
407{
408 return m_intersections.size();
409}
410
411inline void QPathSegments::addIntersection(int index, const Intersection &intersection)
412{
413 m_intersections << intersection;
414
415 Segment &segment = m_segments.at(index);
416 if (segment.intersection < 0) {
417 segment.intersection = m_intersections.size() - 1;
418 } else {
419 Intersection *isect = &m_intersections.at(segment.intersection);
420
421 while (isect->next != 0)
422 isect += isect->next;
423
424 isect->next = (m_intersections.size() - 1) - (isect - m_intersections.data());
425 }
426}
427
428inline void QWingedEdge::TraversalStatus::flipDirection()
429{
430 direction = QWingedEdge::flip(direction);
431}
432
433inline void QWingedEdge::TraversalStatus::flipTraversal()
434{
435 traversal = QWingedEdge::flip(traversal);
436}
437
438inline void QWingedEdge::TraversalStatus::flip()
439{
440 flipDirection();
441 flipTraversal();
442}
443
444inline int QWingedEdge::edgeCount() const
445{
446 return m_edges.size();
447}
448
449inline QPathEdge *QWingedEdge::edge(int edge)
450{
451 return edge < 0 ? 0 : &m_edges.at(edge);
452}
453
454inline const QPathEdge *QWingedEdge::edge(int edge) const
455{
456 return edge < 0 ? 0 : &m_edges.at(edge);
457}
458
459inline int QWingedEdge::vertexCount() const
460{
461 return m_vertices.size();
462}
463
464inline int QWingedEdge::addVertex(const QPointF &p)
465{
466 m_vertices << p;
467 return m_vertices.size() - 1;
468}
469
470inline QPathVertex *QWingedEdge::vertex(int vertex)
471{
472 return vertex < 0 ? 0 : &m_vertices.at(vertex);
473}
474
475inline const QPathVertex *QWingedEdge::vertex(int vertex) const
476{
477 return vertex < 0 ? 0 : &m_vertices.at(vertex);
478}
479
480inline QPathEdge::Traversal QWingedEdge::flip(QPathEdge::Traversal traversal)
481{
482 return traversal == QPathEdge::RightTraversal ? QPathEdge::LeftTraversal : QPathEdge::RightTraversal;
483}
484
485inline QPathEdge::Direction QWingedEdge::flip(QPathEdge::Direction direction)
486{
487 return direction == QPathEdge::Forward ? QPathEdge::Backward : QPathEdge::Forward;
488}
489
490QT_END_NAMESPACE
491
492QT_END_HEADER
493
494#endif // QPATHCLIPPER_P_H
Note: See TracBrowser for help on using the repository browser.