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

Last change on this file since 184 was 2, checked in by Dmitry A. Kuminov, 17 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 11.9 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the QtGui module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** 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 are unsure which license is appropriate for your use, please
37** contact the sales department 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
89private:
90 Q_DISABLE_COPY(QPathClipper)
91
92 enum ClipperMode {
93 ClipMode, // do the full clip
94 CheckMode // for contains/intersects (only interested in whether the result path is non-empty)
95 };
96
97 bool handleCrossingEdges(QWingedEdge &list, qreal y, ClipperMode mode);
98 bool doClip(QWingedEdge &list, ClipperMode mode);
99
100 QPainterPath subjectPath;
101 QPainterPath clipPath;
102 Operation op;
103
104 int aMask;
105 int bMask;
106};
107
108struct QPathVertex
109{
110public:
111 QPathVertex(const QPointF &p = QPointF(), int e = -1);
112 operator QPointF() const;
113
114 int edge;
115
116 qreal x;
117 qreal y;
118};
119
120class QPathEdge
121{
122public:
123 enum Traversal {
124 RightTraversal,
125 LeftTraversal
126 };
127
128 enum Direction {
129 Forward,
130 Backward
131 };
132
133 enum Type {
134 Line,
135 Curve
136 };
137
138 QPathEdge(int a = -1, int b = -1);
139
140 mutable int flag;
141
142 int windingA;
143 int windingB;
144
145 int first;
146 int second;
147
148 qreal angle;
149 qreal invAngle;
150
151 const QBezier *bezier;
152 qreal t0;
153 qreal t1;
154
155 int next(Traversal traversal, Direction direction) const;
156
157 void setNext(Traversal traversal, Direction direction, int next);
158 void setNext(Direction direction, int next);
159
160 Direction directionTo(int vertex) const;
161 int vertex(Direction direction) const;
162
163 bool isBezier() 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 bool QPathEdge::isBezier() const
351{
352 return bezier >= 0;
353}
354
355inline QPathVertex::QPathVertex(const QPointF &p, int e)
356 : edge(e)
357 , x(p.x())
358 , y(p.y())
359{
360}
361
362inline QPathVertex::operator QPointF() const
363{
364 return QPointF(x, y);
365}
366
367inline QPathSegments::QPathSegments()
368{
369}
370
371inline int QPathSegments::segments() const
372{
373 return m_segments.size();
374}
375
376inline int QPathSegments::points() const
377{
378 return m_points.size();
379}
380
381inline const QPointF &QPathSegments::pointAt(int i) const
382{
383 return m_points.at(i);
384}
385
386inline int QPathSegments::addPoint(const QPointF &point)
387{
388 m_points << point;
389 return m_points.size() - 1;
390}
391
392inline const QPathSegments::Segment &QPathSegments::segmentAt(int index) const
393{
394 return m_segments.at(index);
395}
396
397inline const QLineF QPathSegments::lineAt(int index) const
398{
399 const Segment &segment = m_segments.at(index);
400 return QLineF(m_points.at(segment.va), m_points.at(segment.vb));
401}
402
403inline const QBezier *QPathSegments::bezierAt(int index) const
404{
405 const Segment &segment = m_segments.at(index);
406 if (segment.bezier >= 0)
407 return &m_beziers.at(segment.bezier);
408 else
409 return 0;
410}
411
412inline const QRectF &QPathSegments::elementBounds(int index) const
413{
414 return m_segments.at(index).bounds;
415}
416
417inline int QPathSegments::pathId(int index) const
418{
419 return m_segments.at(index).path;
420}
421
422inline const QPathSegments::Intersection *QPathSegments::intersectionAt(int index) const
423{
424 const int intersection = m_segments.at(index).intersection;
425 if (intersection < 0)
426 return 0;
427 else
428 return &m_intersections.at(intersection);
429}
430
431inline int QPathSegments::intersections() const
432{
433 return m_intersections.size();
434}
435
436inline void QPathSegments::addIntersection(int index, const Intersection &intersection)
437{
438 m_intersections << intersection;
439
440 Segment &segment = m_segments.at(index);
441 if (segment.intersection < 0) {
442 segment.intersection = m_intersections.size() - 1;
443 } else {
444 Intersection *isect = &m_intersections.at(segment.intersection);
445
446 while (isect->next != 0)
447 isect += isect->next;
448
449 isect->next = (m_intersections.size() - 1) - (isect - m_intersections.data());
450 }
451}
452
453inline void QWingedEdge::TraversalStatus::flipDirection()
454{
455 direction = QWingedEdge::flip(direction);
456}
457
458inline void QWingedEdge::TraversalStatus::flipTraversal()
459{
460 traversal = QWingedEdge::flip(traversal);
461}
462
463inline void QWingedEdge::TraversalStatus::flip()
464{
465 flipDirection();
466 flipTraversal();
467}
468
469inline int QWingedEdge::edgeCount() const
470{
471 return m_edges.size();
472}
473
474inline QPathEdge *QWingedEdge::edge(int edge)
475{
476 return edge < 0 ? 0 : &m_edges.at(edge);
477}
478
479inline const QPathEdge *QWingedEdge::edge(int edge) const
480{
481 return edge < 0 ? 0 : &m_edges.at(edge);
482}
483
484inline int QWingedEdge::vertexCount() const
485{
486 return m_vertices.size();
487}
488
489inline int QWingedEdge::addVertex(const QPointF &p)
490{
491 m_vertices << p;
492 return m_vertices.size() - 1;
493}
494
495inline QPathVertex *QWingedEdge::vertex(int vertex)
496{
497 return vertex < 0 ? 0 : &m_vertices.at(vertex);
498}
499
500inline const QPathVertex *QWingedEdge::vertex(int vertex) const
501{
502 return vertex < 0 ? 0 : &m_vertices.at(vertex);
503}
504
505inline QPathEdge::Traversal QWingedEdge::flip(QPathEdge::Traversal traversal)
506{
507 return traversal == QPathEdge::RightTraversal ? QPathEdge::LeftTraversal : QPathEdge::RightTraversal;
508}
509
510inline QPathEdge::Direction QWingedEdge::flip(QPathEdge::Direction direction)
511{
512 return direction == QPathEdge::Forward ? QPathEdge::Backward : QPathEdge::Forward;
513}
514
515QT_END_NAMESPACE
516
517QT_END_HEADER
518
519#endif // QPATHCLIPPER_P_H
Note: See TracBrowser for help on using the repository browser.