/src/qtbase/src/gui/painting/qpolygon.cpp
Line | Count | Source |
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 | | #include "qpolygon.h" |
6 | | #include "qrect.h" |
7 | | #include "qdatastream.h" |
8 | | #include "qdebug.h" |
9 | | #include "qpainterpath.h" |
10 | | #include "qtransform.h" |
11 | | #include "qvariant.h" |
12 | | #include "qpainterpath_p.h" |
13 | | #include "qbezier_p.h" |
14 | | |
15 | | #include <stdarg.h> |
16 | | |
17 | | QT_BEGIN_NAMESPACE |
18 | | |
19 | | //same as qt_painterpath_isect_line in qpainterpath.cpp |
20 | | static void qt_polygon_isect_line(const QPointF &p1, const QPointF &p2, const QPointF &pos, |
21 | | int *winding) |
22 | 0 | { |
23 | 0 | qreal x1 = p1.x(); |
24 | 0 | qreal y1 = p1.y(); |
25 | 0 | qreal x2 = p2.x(); |
26 | 0 | qreal y2 = p2.y(); |
27 | 0 | qreal y = pos.y(); |
28 | |
|
29 | 0 | int dir = 1; |
30 | |
|
31 | 0 | if (qFuzzyCompare(y1, y2)) { |
32 | | // ignore horizontal lines according to scan conversion rule |
33 | 0 | return; |
34 | 0 | } else if (y2 < y1) { |
35 | 0 | qreal x_tmp = x2; x2 = x1; x1 = x_tmp; |
36 | 0 | qreal y_tmp = y2; y2 = y1; y1 = y_tmp; |
37 | 0 | dir = -1; |
38 | 0 | } |
39 | | |
40 | 0 | if (y >= y1 && y < y2) { |
41 | 0 | qreal x = x1 + ((x2 - x1) / (y2 - y1)) * (y - y1); |
42 | | |
43 | | // count up the winding number if we're |
44 | 0 | if (x<=pos.x()) { |
45 | 0 | (*winding) += dir; |
46 | 0 | } |
47 | 0 | } |
48 | 0 | } |
49 | | |
50 | | /*! |
51 | | \class QPolygon |
52 | | \brief The QPolygon class provides a list of points using |
53 | | integer precision. |
54 | | \inmodule QtGui |
55 | | |
56 | | \reentrant |
57 | | |
58 | | \ingroup painting |
59 | | \ingroup shared |
60 | | |
61 | | A QPolygon object is a QList<QPoint>. The easiest way to add |
62 | | points to a QPolygon is to use QList's streaming operator, as |
63 | | illustrated below: |
64 | | |
65 | | \snippet polygon/polygon.cpp 0 |
66 | | |
67 | | In addition to the functions provided by QList, QPolygon |
68 | | provides some point-specific functions. |
69 | | |
70 | | Each point in a polygon can be retrieved by passing its index to |
71 | | the point() function. To populate the polygon, QPolygon provides |
72 | | the setPoint() function to set the point at a given index, the |
73 | | setPoints() function to set all the points in the polygon |
74 | | (resizing it to the given number of points), and the putPoints() |
75 | | function which copies a number of given points into the polygon |
76 | | from a specified index (resizing the polygon if necessary). |
77 | | |
78 | | QPolygon provides the boundingRect() and translate() functions for |
79 | | geometry functions. Use the QTransform::map() function for more |
80 | | general transformations of QPolygons. |
81 | | |
82 | | The QPolygon class is \l {Implicit Data Sharing}{implicitly |
83 | | shared}. |
84 | | |
85 | | \sa QList, QPolygonF, QLine |
86 | | */ |
87 | | |
88 | | |
89 | | /***************************************************************************** |
90 | | QPolygon member functions |
91 | | *****************************************************************************/ |
92 | | |
93 | | /*! |
94 | | \fn QPolygon::QPolygon() |
95 | | |
96 | | Constructs a polygon with no points. |
97 | | |
98 | | \sa QList::isEmpty() |
99 | | */ |
100 | | |
101 | | /*! |
102 | | \fn QPolygon::QPolygon(const QList<QPoint> &points) |
103 | | |
104 | | Constructs a polygon containing the specified \a points. |
105 | | |
106 | | \sa setPoints() |
107 | | */ |
108 | | |
109 | | /*! |
110 | | \fn QPolygon::QPolygon(const QRect &rectangle, bool closed) |
111 | | |
112 | | Constructs a polygon from the given \a rectangle. If \a closed is |
113 | | false, the polygon just contains the four points of the rectangle |
114 | | ordered clockwise, otherwise the polygon's fifth point is set to |
115 | | \a {rectangle}.topLeft(). |
116 | | |
117 | | Note that the bottom-right corner of the rectangle is located at |
118 | | (rectangle.x() + rectangle.width(), rectangle.y() + |
119 | | rectangle.height()). |
120 | | |
121 | | \sa setPoints() |
122 | | */ |
123 | | |
124 | | QPolygon::QPolygon(const QRect &r, bool closed) |
125 | 0 | { |
126 | 0 | reserve(closed ? 5 : 4); |
127 | 0 | *this << QPoint(r.x(), r.y()) |
128 | 0 | << QPoint(r.x() + r.width(), r.y()) |
129 | 0 | << QPoint(r.x() + r.width(), r.y() + r.height()) |
130 | 0 | << QPoint(r.x(), r.y() + r.height()); |
131 | 0 | if (closed) |
132 | 0 | *this << QPoint(r.left(), r.top()); |
133 | 0 | } |
134 | | |
135 | | /*! |
136 | | \internal |
137 | | Constructs a point array with \a nPoints points, taken from the |
138 | | \a points array. |
139 | | |
140 | | Equivalent to setPoints(nPoints, points). |
141 | | */ |
142 | | |
143 | | QPolygon::QPolygon(int nPoints, const int *points) |
144 | 0 | { |
145 | 0 | setPoints(nPoints, points); |
146 | 0 | } |
147 | | |
148 | | /*! |
149 | | Translates all points in the polygon by (\a{dx}, \a{dy}). |
150 | | |
151 | | \sa translated() |
152 | | */ |
153 | | |
154 | | void QPolygon::translate(int dx, int dy) |
155 | 0 | { |
156 | 0 | if (dx == 0 && dy == 0) |
157 | 0 | return; |
158 | | |
159 | 0 | QPoint *p = data(); |
160 | 0 | int i = size(); |
161 | 0 | QPoint pt(dx, dy); |
162 | 0 | while (i--) { |
163 | 0 | *p += pt; |
164 | 0 | ++p; |
165 | 0 | } |
166 | 0 | } |
167 | | |
168 | | /*! |
169 | | \fn void QPolygon::translate(const QPoint &offset) |
170 | | \overload |
171 | | |
172 | | Translates all points in the polygon by the given \a offset. |
173 | | |
174 | | \sa translated() |
175 | | */ |
176 | | |
177 | | /*! |
178 | | Returns a copy of the polygon that is translated by (\a{dx}, \a{dy}). |
179 | | |
180 | | \since 4.6 |
181 | | \sa translate() |
182 | | */ |
183 | | QPolygon QPolygon::translated(int dx, int dy) const |
184 | 0 | { |
185 | 0 | QPolygon copy(*this); |
186 | 0 | copy.translate(dx, dy); |
187 | 0 | return copy; |
188 | 0 | } |
189 | | |
190 | | /*! |
191 | | \fn void QPolygon::translated(const QPoint &offset) const |
192 | | \overload |
193 | | \since 4.6 |
194 | | |
195 | | Returns a copy of the polygon that is translated by the given \a offset. |
196 | | |
197 | | \sa translate() |
198 | | */ |
199 | | |
200 | | /*! |
201 | | Extracts the coordinates of the point at the given \a index to |
202 | | *\a{x} and *\a{y} (if they are valid pointers). |
203 | | |
204 | | \sa setPoint() |
205 | | */ |
206 | | |
207 | | void QPolygon::point(int index, int *x, int *y) const |
208 | 0 | { |
209 | 0 | QPoint p = at(index); |
210 | 0 | if (x) |
211 | 0 | *x = (int)p.x(); |
212 | 0 | if (y) |
213 | 0 | *y = (int)p.y(); |
214 | 0 | } |
215 | | |
216 | | /*! |
217 | | \fn QPoint QPolygon::point(int index) const |
218 | | \overload |
219 | | |
220 | | Returns the point at the given \a index. |
221 | | */ |
222 | | |
223 | | /*! |
224 | | \fn void QPolygon::setPoint(int index, const QPoint &point) |
225 | | \overload |
226 | | |
227 | | Sets the point at the given \a index to the given \a point. |
228 | | */ |
229 | | |
230 | | /*! |
231 | | Sets the point at the given \a index to the point specified by |
232 | | (\a{x}, \a{y}). |
233 | | |
234 | | \sa point(), putPoints(), setPoints(), |
235 | | */ |
236 | | void QPolygon::setPoint(int index, int x, int y) |
237 | 0 | { |
238 | 0 | (*this)[index] = QPoint(x, y); |
239 | 0 | } |
240 | | |
241 | | |
242 | | /*! |
243 | | Resizes the polygon to \a nPoints and populates it with the given |
244 | | \a points. |
245 | | |
246 | | The example code creates a polygon with two points (10, 20) and |
247 | | (30, 40): |
248 | | |
249 | | \snippet polygon/polygon.cpp 2 |
250 | | |
251 | | \sa setPoint(), putPoints() |
252 | | */ |
253 | | |
254 | | void QPolygon::setPoints(int nPoints, const int *points) |
255 | 0 | { |
256 | 0 | resize(nPoints); |
257 | 0 | int i = 0; |
258 | 0 | while (nPoints--) { |
259 | 0 | setPoint(i++, *points, *(points+1)); |
260 | 0 | points += 2; |
261 | 0 | } |
262 | 0 | } |
263 | | |
264 | | /*! |
265 | | \overload |
266 | | |
267 | | Resizes the polygon to \a nPoints and populates it with the points |
268 | | specified by the variable argument list. The points are given as a |
269 | | sequence of integers, starting with \a firstx then \a firsty, and |
270 | | so on. |
271 | | |
272 | | The example code creates a polygon with two points (10, 20) and |
273 | | (30, 40): |
274 | | |
275 | | \snippet polygon/polygon.cpp 3 |
276 | | */ |
277 | | |
278 | | void QPolygon::setPoints(int nPoints, int firstx, int firsty, ...) |
279 | 0 | { |
280 | 0 | va_list ap; |
281 | 0 | resize(nPoints); |
282 | 0 | setPoint(0, firstx, firsty); |
283 | 0 | int i = 0, x, y; |
284 | 0 | va_start(ap, firsty); |
285 | 0 | while (--nPoints) { |
286 | 0 | x = va_arg(ap, int); |
287 | 0 | y = va_arg(ap, int); |
288 | 0 | setPoint(++i, x, y); |
289 | 0 | } |
290 | 0 | va_end(ap); |
291 | 0 | } |
292 | | |
293 | | /*! |
294 | | \overload |
295 | | \internal |
296 | | |
297 | | Copies \a nPoints points from the \a points coord array into this |
298 | | point array, and resizes the point array if \c{index+nPoints} |
299 | | exceeds the size of the array. |
300 | | |
301 | | \sa setPoint() |
302 | | */ |
303 | | |
304 | | void QPolygon::putPoints(int index, int nPoints, const int *points) |
305 | 0 | { |
306 | 0 | if (index + nPoints > size()) |
307 | 0 | resize(index + nPoints); |
308 | 0 | int i = index; |
309 | 0 | while (nPoints--) { |
310 | 0 | setPoint(i++, *points, *(points+1)); |
311 | 0 | points += 2; |
312 | 0 | } |
313 | 0 | } |
314 | | |
315 | | /*! |
316 | | Copies \a nPoints points from the variable argument list into this |
317 | | polygon from the given \a index. |
318 | | |
319 | | The points are given as a sequence of integers, starting with \a |
320 | | firstx then \a firsty, and so on. The polygon is resized if |
321 | | \c{index+nPoints} exceeds its current size. |
322 | | |
323 | | The example code creates a polygon with three points (4,5), (6,7) |
324 | | and (8,9), by expanding the polygon from 1 to 3 points: |
325 | | |
326 | | \snippet polygon/polygon.cpp 4 |
327 | | |
328 | | The following code has the same result, but here the putPoints() |
329 | | function overwrites rather than extends: |
330 | | |
331 | | \snippet polygon/polygon.cpp 5 |
332 | | |
333 | | \sa setPoints() |
334 | | */ |
335 | | |
336 | | void QPolygon::putPoints(int index, int nPoints, int firstx, int firsty, ...) |
337 | 0 | { |
338 | 0 | va_list ap; |
339 | 0 | if (index + nPoints > size()) |
340 | 0 | resize(index + nPoints); |
341 | 0 | if (nPoints <= 0) |
342 | 0 | return; |
343 | 0 | setPoint(index, firstx, firsty); |
344 | 0 | int i = index, x, y; |
345 | 0 | va_start(ap, firsty); |
346 | 0 | while (--nPoints) { |
347 | 0 | x = va_arg(ap, int); |
348 | 0 | y = va_arg(ap, int); |
349 | 0 | setPoint(++i, x, y); |
350 | 0 | } |
351 | 0 | va_end(ap); |
352 | 0 | } |
353 | | |
354 | | |
355 | | /*! |
356 | | \fn void QPolygon::putPoints(int index, int nPoints, const QPolygon &fromPolygon, int fromIndex) |
357 | | \overload |
358 | | |
359 | | Copies \a nPoints points from the given \a fromIndex ( 0 by |
360 | | default) in \a fromPolygon into this polygon, starting at the |
361 | | specified \a index. For example: |
362 | | |
363 | | \snippet polygon/polygon.cpp 6 |
364 | | */ |
365 | | |
366 | | void QPolygon::putPoints(int index, int nPoints, const QPolygon & from, int fromIndex) |
367 | 0 | { |
368 | 0 | if (index + nPoints > size()) |
369 | 0 | resize(index + nPoints); |
370 | 0 | if (nPoints <= 0) |
371 | 0 | return; |
372 | 0 | int n = 0; |
373 | 0 | while(n < nPoints) { |
374 | 0 | setPoint(index + n, from[fromIndex+n]); |
375 | 0 | ++n; |
376 | 0 | } |
377 | 0 | } |
378 | | |
379 | | |
380 | | /*! |
381 | | Returns the bounding rectangle of the polygon, or QRect(0, 0, 0, |
382 | | 0) if the polygon is empty. |
383 | | |
384 | | \sa QList::isEmpty() |
385 | | */ |
386 | | |
387 | | QRect QPolygon::boundingRect() const |
388 | 0 | { |
389 | 0 | const QPoint *pd = constData(); |
390 | 0 | const QPoint *pe = pd + size(); |
391 | 0 | if (pd == pe) |
392 | 0 | return QRect(0, 0, 0, 0); |
393 | 0 | int minx, maxx, miny, maxy; |
394 | 0 | minx = maxx = pd->x(); |
395 | 0 | miny = maxy = pd->y(); |
396 | 0 | ++pd; |
397 | 0 | for (; pd != pe; ++pd) { |
398 | 0 | if (pd->x() < minx) |
399 | 0 | minx = pd->x(); |
400 | 0 | else if (pd->x() > maxx) |
401 | 0 | maxx = pd->x(); |
402 | 0 | if (pd->y() < miny) |
403 | 0 | miny = pd->y(); |
404 | 0 | else if (pd->y() > maxy) |
405 | 0 | maxy = pd->y(); |
406 | 0 | } |
407 | 0 | return QRect(QPoint(minx,miny), QPoint(maxx,maxy)); |
408 | 0 | } |
409 | | |
410 | | /*! |
411 | | \fn QPolygon::toPolygonF() const |
412 | | \since 6.4 |
413 | | |
414 | | Returns this polygon as a polygon with floating point accuracy. |
415 | | |
416 | | \sa QPolygonF::toPolygon() |
417 | | */ |
418 | | |
419 | | |
420 | | #ifndef QT_NO_DEBUG_STREAM |
421 | | QDebug operator<<(QDebug dbg, const QPolygon &a) |
422 | 0 | { |
423 | 0 | return QtPrivate::printSequentialContainer(dbg, "QPolygon", a); |
424 | 0 | } |
425 | | #endif |
426 | | |
427 | | |
428 | | /*! |
429 | | \class QPolygonF |
430 | | \brief The QPolygonF class provides a list of points using |
431 | | floating point precision. |
432 | | \inmodule QtGui |
433 | | |
434 | | \reentrant |
435 | | \ingroup painting |
436 | | \ingroup shared |
437 | | |
438 | | A QPolygonF is a QList<QPointF>. The easiest way to add points |
439 | | to a QPolygonF is to use its streaming operator, as illustrated |
440 | | below: |
441 | | |
442 | | \snippet polygon/polygon.cpp 1 |
443 | | |
444 | | In addition to the functions provided by QList, QPolygonF |
445 | | provides the boundingRect() and translate() functions for geometry |
446 | | operations. Use the QTransform::map() function for more general |
447 | | transformations of QPolygonFs. |
448 | | |
449 | | QPolygonF also provides the isClosed() function to determine |
450 | | whether a polygon's start and end points are the same, and the |
451 | | toPolygon() function returning an integer precision copy of this |
452 | | polygon. |
453 | | |
454 | | The QPolygonF class is \l {Implicit Data Sharing}{implicitly |
455 | | shared}. |
456 | | |
457 | | \sa QList, QPolygon, QLineF |
458 | | */ |
459 | | |
460 | | |
461 | | /***************************************************************************** |
462 | | QPolygonF member functions |
463 | | *****************************************************************************/ |
464 | | |
465 | | /*! |
466 | | \fn QPolygonF::QPolygonF() |
467 | | |
468 | | Constructs a polygon with no points. |
469 | | |
470 | | \sa QList::isEmpty() |
471 | | */ |
472 | | |
473 | | /*! |
474 | | \fn QPolygonF::QPolygonF(const QList<QPointF> &points) |
475 | | |
476 | | Constructs a polygon containing the specified \a points. |
477 | | */ |
478 | | |
479 | | /*! |
480 | | \fn QPolygonF::QPolygonF(const QRectF &rectangle) |
481 | | |
482 | | Constructs a closed polygon from the specified \a rectangle. |
483 | | |
484 | | The polygon contains the four vertices of the rectangle in |
485 | | clockwise order starting and ending with the top-left vertex. |
486 | | |
487 | | \sa isClosed() |
488 | | */ |
489 | | |
490 | | QPolygonF::QPolygonF(const QRectF &r) |
491 | 0 | { |
492 | 0 | reserve(5); |
493 | 0 | append(QPointF(r.x(), r.y())); |
494 | 0 | append(QPointF(r.x() + r.width(), r.y())); |
495 | 0 | append(QPointF(r.x() + r.width(), r.y() + r.height())); |
496 | 0 | append(QPointF(r.x(), r.y() + r.height())); |
497 | 0 | append(QPointF(r.x(), r.y())); |
498 | 0 | } |
499 | | |
500 | | /*! |
501 | | \fn QPolygonF::QPolygonF(const QPolygon &polygon) |
502 | | |
503 | | Constructs a float based polygon from the specified integer based |
504 | | \a polygon. |
505 | | |
506 | | \sa toPolygon() |
507 | | */ |
508 | | |
509 | | QPolygonF::QPolygonF(const QPolygon &a) |
510 | 0 | { |
511 | 0 | reserve(a.size()); |
512 | 0 | for (int i=0; i<a.size(); ++i) |
513 | 0 | append(a.at(i)); |
514 | 0 | } |
515 | | |
516 | | /*! |
517 | | Translate all points in the polygon by the given \a offset. |
518 | | |
519 | | \sa translated() |
520 | | */ |
521 | | |
522 | | void QPolygonF::translate(const QPointF &offset) |
523 | 0 | { |
524 | 0 | if (offset.isNull()) |
525 | 0 | return; |
526 | | |
527 | 0 | QPointF *p = data(); |
528 | 0 | int i = size(); |
529 | 0 | while (i--) { |
530 | 0 | *p += offset; |
531 | 0 | ++p; |
532 | 0 | } |
533 | 0 | } |
534 | | |
535 | | /*! |
536 | | \fn void QPolygonF::translate(qreal dx, qreal dy) |
537 | | \overload |
538 | | |
539 | | Translates all points in the polygon by (\a{dx}, \a{dy}). |
540 | | |
541 | | \sa translated() |
542 | | */ |
543 | | |
544 | | /*! |
545 | | Returns a copy of the polygon that is translated by the given \a offset. |
546 | | |
547 | | \since 4.6 |
548 | | \sa translate() |
549 | | */ |
550 | | QPolygonF QPolygonF::translated(const QPointF &offset) const |
551 | 0 | { |
552 | 0 | QPolygonF copy(*this); |
553 | 0 | copy.translate(offset); |
554 | 0 | return copy; |
555 | 0 | } |
556 | | |
557 | | /*! |
558 | | \fn void QPolygonF::translated(qreal dx, qreal dy) const |
559 | | \overload |
560 | | \since 4.6 |
561 | | |
562 | | Returns a copy of the polygon that is translated by (\a{dx}, \a{dy}). |
563 | | |
564 | | \sa translate() |
565 | | */ |
566 | | |
567 | | /*! |
568 | | \fn bool QPolygonF::isClosed() const |
569 | | |
570 | | Returns \c true if the polygon is closed; otherwise returns \c false. |
571 | | |
572 | | A polygon is said to be closed if its start point and end point are equal. |
573 | | |
574 | | \sa QList::first(), QList::last() |
575 | | */ |
576 | | |
577 | | /*! |
578 | | Returns the bounding rectangle of the polygon, or QRectF(0,0,0,0) |
579 | | if the polygon is empty. |
580 | | |
581 | | \sa QList::isEmpty() |
582 | | */ |
583 | | |
584 | | QRectF QPolygonF::boundingRect() const |
585 | 0 | { |
586 | 0 | const QPointF *pd = constData(); |
587 | 0 | const QPointF *pe = pd + size(); |
588 | 0 | if (pd == pe) |
589 | 0 | return QRectF(0, 0, 0, 0); |
590 | 0 | qreal minx, maxx, miny, maxy; |
591 | 0 | minx = maxx = pd->x(); |
592 | 0 | miny = maxy = pd->y(); |
593 | 0 | ++pd; |
594 | 0 | while (pd != pe) { |
595 | 0 | if (pd->x() < minx) |
596 | 0 | minx = pd->x(); |
597 | 0 | else if (pd->x() > maxx) |
598 | 0 | maxx = pd->x(); |
599 | 0 | if (pd->y() < miny) |
600 | 0 | miny = pd->y(); |
601 | 0 | else if (pd->y() > maxy) |
602 | 0 | maxy = pd->y(); |
603 | 0 | ++pd; |
604 | 0 | } |
605 | 0 | return QRectF(minx,miny, maxx - minx, maxy - miny); |
606 | 0 | } |
607 | | |
608 | | /*! |
609 | | Creates and returns a QPolygon by converting each QPointF to a |
610 | | QPoint. |
611 | | |
612 | | \sa QPointF::toPoint() |
613 | | */ |
614 | | |
615 | | QPolygon QPolygonF::toPolygon() const |
616 | 0 | { |
617 | 0 | QPolygon a; |
618 | 0 | a.reserve(size()); |
619 | 0 | for (int i=0; i<size(); ++i) |
620 | 0 | a.append(at(i).toPoint()); |
621 | 0 | return a; |
622 | 0 | } |
623 | | |
624 | | /*! |
625 | | \fn void QPolygon::swap(QPolygon &other) |
626 | | \since 4.8 |
627 | | \memberswap{polygon} |
628 | | */ |
629 | | |
630 | | /*! |
631 | | \fn void QPolygonF::swap(QPolygonF &other) |
632 | | \since 4.8 |
633 | | \memberswap{polygon} |
634 | | */ |
635 | | |
636 | | /*! |
637 | | Returns the polygon as a QVariant |
638 | | */ |
639 | | QPolygon::operator QVariant() const |
640 | 0 | { |
641 | 0 | return QVariant::fromValue(*this); |
642 | 0 | } |
643 | | |
644 | | /***************************************************************************** |
645 | | QPolygon stream functions |
646 | | *****************************************************************************/ |
647 | | #ifndef QT_NO_DATASTREAM |
648 | | /*! |
649 | | \fn QDataStream &operator<<(QDataStream &stream, const QPolygon &polygon) |
650 | | \since 4.4 |
651 | | \relates QPolygon |
652 | | |
653 | | Writes the given \a polygon to the given \a stream, and returns a |
654 | | reference to the stream. |
655 | | |
656 | | \sa {Serializing Qt Data Types} |
657 | | */ |
658 | | QDataStream &operator<<(QDataStream &s, const QPolygon &a) |
659 | 0 | { |
660 | 0 | const QList<QPoint> &v = a; |
661 | 0 | return s << v; |
662 | 0 | } |
663 | | |
664 | | /*! |
665 | | \fn QDataStream &operator>>(QDataStream &stream, QPolygon &polygon) |
666 | | \since 4.4 |
667 | | \relates QPolygon |
668 | | |
669 | | Reads a polygon from the given \a stream into the given \a |
670 | | polygon, and returns a reference to the stream. |
671 | | |
672 | | \sa {Serializing Qt Data Types} |
673 | | */ |
674 | | QDataStream &operator>>(QDataStream &s, QPolygon &a) |
675 | 0 | { |
676 | 0 | QList<QPoint> &v = a; |
677 | 0 | return s >> v; |
678 | 0 | } |
679 | | #endif // QT_NO_DATASTREAM |
680 | | |
681 | | /***************************************************************************** |
682 | | QPolygonF stream functions |
683 | | *****************************************************************************/ |
684 | | #ifndef QT_NO_DATASTREAM |
685 | | /*! |
686 | | \fn QDataStream &operator<<(QDataStream &stream, const QPolygonF &polygon) |
687 | | \relates QPolygonF |
688 | | |
689 | | Writes the given \a polygon to the given \a stream, and returns a |
690 | | reference to the stream. |
691 | | |
692 | | \sa {Serializing Qt Data Types} |
693 | | */ |
694 | | |
695 | | QDataStream &operator<<(QDataStream &s, const QPolygonF &a) |
696 | 0 | { |
697 | 0 | return s << static_cast<const QList<QPointF> &>(a); |
698 | 0 | } |
699 | | |
700 | | /*! |
701 | | \fn QDataStream &operator>>(QDataStream &stream, QPolygonF &polygon) |
702 | | \relates QPolygonF |
703 | | |
704 | | Reads a polygon from the given \a stream into the given \a |
705 | | polygon, and returns a reference to the stream. |
706 | | |
707 | | \sa {Serializing Qt Data Types} |
708 | | */ |
709 | | |
710 | | QDataStream &operator>>(QDataStream &s, QPolygonF &a) |
711 | 0 | { |
712 | 0 | return s >> static_cast<QList<QPointF> &>(a); |
713 | 0 | } |
714 | | #endif //QT_NO_DATASTREAM |
715 | | |
716 | | #ifndef QT_NO_DEBUG_STREAM |
717 | | QDebug operator<<(QDebug dbg, const QPolygonF &a) |
718 | 0 | { |
719 | 0 | return QtPrivate::printSequentialContainer(dbg, "QPolygonF", a); |
720 | 0 | } |
721 | | #endif |
722 | | |
723 | | |
724 | | /*! |
725 | | \since 4.3 |
726 | | |
727 | | \fn bool QPolygonF::containsPoint(const QPointF &point, Qt::FillRule fillRule) const |
728 | | |
729 | | Returns \c true if the given \a point is inside the polygon according to |
730 | | the specified \a fillRule; otherwise returns \c false. |
731 | | */ |
732 | | bool QPolygonF::containsPoint(const QPointF &pt, Qt::FillRule fillRule) const |
733 | 0 | { |
734 | 0 | if (isEmpty()) |
735 | 0 | return false; |
736 | | |
737 | 0 | int winding_number = 0; |
738 | |
|
739 | 0 | QPointF last_pt = at(0); |
740 | 0 | QPointF last_start = at(0); |
741 | 0 | for (int i = 1; i < size(); ++i) { |
742 | 0 | const QPointF &e = at(i); |
743 | 0 | qt_polygon_isect_line(last_pt, e, pt, &winding_number); |
744 | 0 | last_pt = e; |
745 | 0 | } |
746 | | |
747 | | // implicitly close last subpath |
748 | 0 | if (last_pt != last_start) |
749 | 0 | qt_polygon_isect_line(last_pt, last_start, pt, &winding_number); |
750 | |
|
751 | 0 | return (fillRule == Qt::WindingFill |
752 | 0 | ? (winding_number != 0) |
753 | 0 | : ((winding_number % 2) != 0)); |
754 | 0 | } |
755 | | |
756 | | /*! |
757 | | \since 4.3 |
758 | | |
759 | | \fn bool QPolygon::containsPoint(const QPoint &point, Qt::FillRule fillRule) const |
760 | | Returns \c true if the given \a point is inside the polygon according to |
761 | | the specified \a fillRule; otherwise returns \c false. |
762 | | */ |
763 | | bool QPolygon::containsPoint(const QPoint &pt, Qt::FillRule fillRule) const |
764 | 0 | { |
765 | 0 | if (isEmpty()) |
766 | 0 | return false; |
767 | | |
768 | 0 | int winding_number = 0; |
769 | |
|
770 | 0 | QPoint last_pt = at(0); |
771 | 0 | QPoint last_start = at(0); |
772 | 0 | for (int i = 1; i < size(); ++i) { |
773 | 0 | const QPoint &e = at(i); |
774 | 0 | qt_polygon_isect_line(last_pt, e, pt, &winding_number); |
775 | 0 | last_pt = e; |
776 | 0 | } |
777 | | |
778 | | // implicitly close last subpath |
779 | 0 | if (last_pt != last_start) |
780 | 0 | qt_polygon_isect_line(last_pt, last_start, pt, &winding_number); |
781 | |
|
782 | 0 | return (fillRule == Qt::WindingFill |
783 | 0 | ? (winding_number != 0) |
784 | 0 | : ((winding_number % 2) != 0)); |
785 | 0 | } |
786 | | |
787 | | /*! |
788 | | \since 4.3 |
789 | | |
790 | | Returns a polygon which is the union of this polygon and \a r. |
791 | | |
792 | | Set operations on polygons, will treat the polygons as areas, and |
793 | | implicitly close the polygon. |
794 | | |
795 | | \sa intersected(), subtracted() |
796 | | */ |
797 | | |
798 | | QPolygon QPolygon::united(const QPolygon &r) const |
799 | 0 | { |
800 | 0 | QPainterPath subject; subject.addPolygon(*this); |
801 | 0 | QPainterPath clip; clip.addPolygon(r); |
802 | |
|
803 | 0 | return subject.united(clip).toFillPolygon().toPolygon(); |
804 | 0 | } |
805 | | |
806 | | /*! |
807 | | \since 4.3 |
808 | | |
809 | | Returns a polygon which is the intersection of this polygon and \a r. |
810 | | |
811 | | Set operations on polygons will treat the polygons as |
812 | | areas. Non-closed polygons will be treated as implicitly closed. |
813 | | |
814 | | \sa intersects() |
815 | | */ |
816 | | |
817 | | QPolygon QPolygon::intersected(const QPolygon &r) const |
818 | 0 | { |
819 | 0 | QPainterPath subject; subject.addPolygon(*this); |
820 | 0 | QPainterPath clip; clip.addPolygon(r); |
821 | |
|
822 | 0 | return subject.intersected(clip).toFillPolygon().toPolygon(); |
823 | 0 | } |
824 | | |
825 | | /*! |
826 | | \since 4.3 |
827 | | |
828 | | Returns a polygon which is \a r subtracted from this polygon. |
829 | | |
830 | | Set operations on polygons will treat the polygons as |
831 | | areas. Non-closed polygons will be treated as implicitly closed. |
832 | | |
833 | | */ |
834 | | |
835 | | QPolygon QPolygon::subtracted(const QPolygon &r) const |
836 | 0 | { |
837 | 0 | QPainterPath subject; subject.addPolygon(*this); |
838 | 0 | QPainterPath clip; clip.addPolygon(r); |
839 | |
|
840 | 0 | return subject.subtracted(clip).toFillPolygon().toPolygon(); |
841 | 0 | } |
842 | | |
843 | | /*! |
844 | | \since 5.10 |
845 | | |
846 | | Returns \c true if the current polygon intersects at any point the given polygon \a p. |
847 | | Also returns \c true if the current polygon contains or is contained by any part of \a p. |
848 | | |
849 | | Set operations on polygons will treat the polygons as |
850 | | areas. Non-closed polygons will be treated as implicitly closed. |
851 | | |
852 | | \sa intersected() |
853 | | */ |
854 | | |
855 | | bool QPolygon::intersects(const QPolygon &p) const |
856 | 0 | { |
857 | 0 | QPainterPath subject; subject.addPolygon(*this); |
858 | 0 | QPainterPath clip; clip.addPolygon(p); |
859 | |
|
860 | 0 | return subject.intersects(clip); |
861 | 0 | } |
862 | | |
863 | | /*! |
864 | | \since 4.3 |
865 | | |
866 | | Returns a polygon which is the union of this polygon and \a r. |
867 | | |
868 | | Set operations on polygons will treat the polygons as |
869 | | areas. Non-closed polygons will be treated as implicitly closed. |
870 | | |
871 | | \sa intersected(), subtracted() |
872 | | */ |
873 | | |
874 | | QPolygonF QPolygonF::united(const QPolygonF &r) const |
875 | 0 | { |
876 | 0 | QPainterPath subject; subject.addPolygon(*this); |
877 | 0 | QPainterPath clip; clip.addPolygon(r); |
878 | |
|
879 | 0 | return subject.united(clip).toFillPolygon(); |
880 | 0 | } |
881 | | |
882 | | /*! |
883 | | \since 4.3 |
884 | | |
885 | | Returns a polygon which is the intersection of this polygon and \a r. |
886 | | |
887 | | Set operations on polygons will treat the polygons as |
888 | | areas. Non-closed polygons will be treated as implicitly closed. |
889 | | |
890 | | \sa intersects() |
891 | | */ |
892 | | |
893 | | QPolygonF QPolygonF::intersected(const QPolygonF &r) const |
894 | 0 | { |
895 | 0 | QPainterPath subject; subject.addPolygon(*this); |
896 | 0 | QPainterPath clip; clip.addPolygon(r); |
897 | |
|
898 | 0 | return subject.intersected(clip).toFillPolygon(); |
899 | 0 | } |
900 | | |
901 | | /*! |
902 | | \since 4.3 |
903 | | |
904 | | Returns a polygon which is \a r subtracted from this polygon. |
905 | | |
906 | | Set operations on polygons will treat the polygons as |
907 | | areas. Non-closed polygons will be treated as implicitly closed. |
908 | | |
909 | | */ |
910 | | |
911 | | QPolygonF QPolygonF::subtracted(const QPolygonF &r) const |
912 | 0 | { |
913 | 0 | QPainterPath subject; subject.addPolygon(*this); |
914 | 0 | QPainterPath clip; clip.addPolygon(r); |
915 | 0 | return subject.subtracted(clip).toFillPolygon(); |
916 | 0 | } |
917 | | |
918 | | /*! |
919 | | \since 5.10 |
920 | | |
921 | | Returns \c true if the current polygon intersects at any point the given polygon \a p. |
922 | | Also returns \c true if the current polygon contains or is contained by any part of \a p. |
923 | | |
924 | | Set operations on polygons will treat the polygons as |
925 | | areas. Non-closed polygons will be treated as implicitly closed. |
926 | | |
927 | | \sa intersected() |
928 | | */ |
929 | | |
930 | | bool QPolygonF::intersects(const QPolygonF &p) const |
931 | 0 | { |
932 | 0 | QPainterPath subject; subject.addPolygon(*this); |
933 | 0 | QPainterPath clip; clip.addPolygon(p); |
934 | |
|
935 | 0 | return subject.intersects(clip); |
936 | 0 | } |
937 | | |
938 | | /*! |
939 | | Returns the polygon as a QVariant. |
940 | | */ |
941 | | |
942 | | QPolygonF::operator QVariant() const |
943 | 0 | { |
944 | 0 | return QVariant::fromValue(*this); |
945 | 0 | } |
946 | | |
947 | | QT_END_NAMESPACE |