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

Last change on this file since 743 was 651, checked in by Dmitry A. Kuminov, 16 years ago

trunk: Merged in qt 4.6.2 sources.

File size: 11.8 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
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 [email protected].
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
91private:
92 Q_DISABLE_COPY(QPathClipper)
93
94 enum ClipperMode {
95 ClipMode, // do the full clip
96 CheckMode // for contains/intersects (only interested in whether the result path is non-empty)
97 };
98
99 bool handleCrossingEdges(QWingedEdge &list, qreal y, ClipperMode mode);
100 bool doClip(QWingedEdge &list, ClipperMode mode);
101
102 QPainterPath subjectPath;
103 QPainterPath clipPath;
104 Operation op;
105
106 int aMask;
107 int bMask;
108};
109
110struct QPathVertex
111{
112public:
113 QPathVertex(const QPointF &p = QPointF(), int e = -1);
114 operator QPointF() const;
115
116 int edge;
117
118 qreal x;
119 qreal y;
120};
121
122class QPathEdge
123{
124public:
125 enum Traversal {
126 RightTraversal,
127 LeftTraversal
128 };
129
130 enum Direction {
131 Forward,
132 Backward
133 };
134
135 enum Type {
136 Line,
137 Curve
138 };
139
140 QPathEdge(int a = -1, int b = -1);
141
142 mutable int flag;
143
144 int windingA;
145 int windingB;
146
147 int first;
148 int second;
149
150 qreal angle;
151 qreal invAngle;
152
153 const QBezier *bezier;
154 qreal t0;
155 qreal t1;
156
157 int next(Traversal traversal, Direction direction) const;
158
159 void setNext(Traversal traversal, Direction direction, int next);
160 void setNext(Direction direction, int next);
161
162 Direction directionTo(int vertex) const;
163 int vertex(Direction direction) const;
164
165private:
166 int m_next[2][2];
167};
168
169class QPathSegments
170{
171public:
172 struct Intersection {
173 int vertex;
174 qreal t;
175
176 int next;
177
178 bool operator<(const Intersection &o) const {
179 return t < o.t;
180 }
181 };
182
183 struct Segment {
184 Segment(int pathId, int vertexA, int vertexB, int bezierIndex = -1)
185 : path(pathId)
186 , bezier(bezierIndex)
187 , va(vertexA)
188 , vb(vertexB)
189 , intersection(-1)
190 {
191 }
192
193 int path;
194 int bezier;
195
196 // vertices
197 int va;
198 int vb;
199
200 // intersection index
201 int intersection;
202
203 QRectF bounds;
204 };
205
206
207 QPathSegments();
208
209 void setPath(const QPainterPath &path);
210 void addPath(const QPainterPath &path);
211
212 int intersections() const;
213 int segments() const;
214 int points() const;
215
216 const Segment &segmentAt(int index) const;
217 const QLineF lineAt(int index) const;
218 const QBezier *bezierAt(int index) const;
219 const QRectF &elementBounds(int index) const;
220 int pathId(int index) const;
221
222 const QPointF &pointAt(int vertex) const;
223 int addPoint(const QPointF &point);
224
225 const Intersection *intersectionAt(int index) const;
226 void addIntersection(int index, const Intersection &intersection);
227
228 void mergePoints();
229
230private:
231 QDataBuffer<QPointF> m_points;
232 QDataBuffer<Segment> m_segments;
233 QDataBuffer<QBezier> m_beziers;
234 QDataBuffer<Intersection> m_intersections;
235
236 int m_pathId;
237};
238
239class Q_AUTOTEST_EXPORT QWingedEdge
240{
241public:
242 struct TraversalStatus
243 {
244 int edge;
245 QPathEdge::Traversal traversal;
246 QPathEdge::Direction direction;
247
248 void flipDirection();
249 void flipTraversal();
250
251 void flip();
252 };
253
254 QWingedEdge();
255 QWingedEdge(const QPainterPath &subject, const QPainterPath &clip);
256
257 void simplify();
258 QPainterPath toPath() const;
259
260 int edgeCount() const;
261
262 QPathEdge *edge(int edge);
263 const QPathEdge *edge(int edge) const;
264
265 int vertexCount() const;
266
267 int addVertex(const QPointF &p);
268
269 QPathVertex *vertex(int vertex);
270 const QPathVertex *vertex(int vertex) const;
271
272 TraversalStatus next(const TraversalStatus &status) const;
273
274 int addEdge(const QPointF &a, const QPointF &b, const QBezier *bezier = 0, qreal t0 = 0, qreal t1 = 1);
275 int addEdge(int vertexA, int vertexB, const QBezier *bezier = 0, qreal t0 = 0, qreal t1 = 1);
276
277 bool isInside(qreal x, qreal y) const;
278
279 static QPathEdge::Traversal flip(QPathEdge::Traversal traversal);
280 static QPathEdge::Direction flip(QPathEdge::Direction direction);
281
282private:
283 void intersectAndAdd();
284
285 void printNode(int i, FILE *handle);
286
287 QBezier bezierFromIndex(int index) const;
288
289 void removeEdge(int ei);
290 void addBezierEdge(const QBezier *bezier, const QPointF &a, const QPointF &b, qreal alphaA, qreal alphaB, int path);
291 void addBezierEdge(const QBezier *bezier, int vertexA, int vertexB, qreal alphaA, qreal alphaB, int path);
292
293 int insert(const QPathVertex &vertex);
294 TraversalStatus findInsertStatus(int vertex, int edge) const;
295
296 qreal delta(int vertex, int a, int b) const;
297
298 QDataBuffer<QPathEdge> m_edges;
299 QDataBuffer<QPathVertex> m_vertices;
300
301 QVector<qreal> m_splitPoints;
302
303 QPathSegments m_segments;
304};
305
306inline QPathEdge::QPathEdge(int a, int b)
307 : flag(0)
308 , windingA(0)
309 , windingB(0)
310 , first(a)
311 , second(b)
312 , angle(0)
313 , invAngle(0)
314 , bezier(0)
315 , t0(0)
316 , t1(0)
317{
318 m_next[0][0] = -1;
319 m_next[1][0] = -1;
320 m_next[0][0] = -1;
321 m_next[1][0] = -1;
322}
323
324inline int QPathEdge::next(Traversal traversal, Direction direction) const
325{
326 return m_next[int(traversal)][int(direction)];
327}
328
329inline void QPathEdge::setNext(Traversal traversal, Direction direction, int next)
330{
331 m_next[int(traversal)][int(direction)] = next;
332}
333
334inline void QPathEdge::setNext(Direction direction, int next)
335{
336 m_next[0][int(direction)] = next;
337 m_next[1][int(direction)] = next;
338}
339
340inline QPathEdge::Direction QPathEdge::directionTo(int vertex) const
341{
342 return first == vertex ? Backward : Forward;
343}
344
345inline int QPathEdge::vertex(Direction direction) const
346{
347 return direction == Backward ? first : second;
348}
349
350inline QPathVertex::QPathVertex(const QPointF &p, int e)
351 : edge(e)
352 , x(p.x())
353 , y(p.y())
354{
355}
356
357inline QPathVertex::operator QPointF() const
358{
359 return QPointF(x, y);
360}
361
362inline QPathSegments::QPathSegments()
363{
364}
365
366inline int QPathSegments::segments() const
367{
368 return m_segments.size();
369}
370
371inline int QPathSegments::points() const
372{
373 return m_points.size();
374}
375
376inline const QPointF &QPathSegments::pointAt(int i) const
377{
378 return m_points.at(i);
379}
380
381inline int QPathSegments::addPoint(const QPointF &point)
382{
383 m_points << point;
384 return m_points.size() - 1;
385}
386
387inline const QPathSegments::Segment &QPathSegments::segmentAt(int index) const
388{
389 return m_segments.at(index);
390}
391
392inline const QLineF QPathSegments::lineAt(int index) const
393{
394 const Segment &segment = m_segments.at(index);
395 return QLineF(m_points.at(segment.va), m_points.at(segment.vb));
396}
397
398inline const QBezier *QPathSegments::bezierAt(int index) const
399{
400 const Segment &segment = m_segments.at(index);
401 if (segment.bezier >= 0)
402 return &m_beziers.at(segment.bezier);
403 else
404 return 0;
405}
406
407inline const QRectF &QPathSegments::elementBounds(int index) const
408{
409 return m_segments.at(index).bounds;
410}
411
412inline int QPathSegments::pathId(int index) const
413{
414 return m_segments.at(index).path;
415}
416
417inline const QPathSegments::Intersection *QPathSegments::intersectionAt(int index) const
418{
419 const int intersection = m_segments.at(index).intersection;
420 if (intersection < 0)
421 return 0;
422 else
423 return &m_intersections.at(intersection);
424}
425
426inline int QPathSegments::intersections() const
427{
428 return m_intersections.size();
429}
430
431inline void QPathSegments::addIntersection(int index, const Intersection &intersection)
432{
433 m_intersections << intersection;
434
435 Segment &segment = m_segments.at(index);
436 if (segment.intersection < 0) {
437 segment.intersection = m_intersections.size() - 1;
438 } else {
439 Intersection *isect = &m_intersections.at(segment.intersection);
440
441 while (isect->next != 0)
442 isect += isect->next;
443
444 isect->next = (m_intersections.size() - 1) - (isect - m_intersections.data());
445 }
446}
447
448inline void QWingedEdge::TraversalStatus::flipDirection()
449{
450 direction = QWingedEdge::flip(direction);
451}
452
453inline void QWingedEdge::TraversalStatus::flipTraversal()
454{
455 traversal = QWingedEdge::flip(traversal);
456}
457
458inline void QWingedEdge::TraversalStatus::flip()
459{
460 flipDirection();
461 flipTraversal();
462}
463
464inline int QWingedEdge::edgeCount() const
465{
466 return m_edges.size();
467}
468
469inline QPathEdge *QWingedEdge::edge(int edge)
470{
471 return edge < 0 ? 0 : &m_edges.at(edge);
472}
473
474inline const QPathEdge *QWingedEdge::edge(int edge) const
475{
476 return edge < 0 ? 0 : &m_edges.at(edge);
477}
478
479inline int QWingedEdge::vertexCount() const
480{
481 return m_vertices.size();
482}
483
484inline int QWingedEdge::addVertex(const QPointF &p)
485{
486 m_vertices << p;
487 return m_vertices.size() - 1;
488}
489
490inline QPathVertex *QWingedEdge::vertex(int vertex)
491{
492 return vertex < 0 ? 0 : &m_vertices.at(vertex);
493}
494
495inline const QPathVertex *QWingedEdge::vertex(int vertex) const
496{
497 return vertex < 0 ? 0 : &m_vertices.at(vertex);
498}
499
500inline QPathEdge::Traversal QWingedEdge::flip(QPathEdge::Traversal traversal)
501{
502 return traversal == QPathEdge::RightTraversal ? QPathEdge::LeftTraversal : QPathEdge::RightTraversal;
503}
504
505inline QPathEdge::Direction QWingedEdge::flip(QPathEdge::Direction direction)
506{
507 return direction == QPathEdge::Forward ? QPathEdge::Backward : QPathEdge::Forward;
508}
509
510QT_END_NAMESPACE
511
512QT_END_HEADER
513
514#endif // QPATHCLIPPER_P_H
Note: See TracBrowser for help on using the repository browser.