OpenCoverage

qregion.cpp

Absolute File Name:/home/qt/qt5_coco/qt5/qtbase/src/gui/painting/qregion.cpp
Source codeSwitch to Preprocessed file
LineSourceCount
1/****************************************************************************-
2**-
3** Copyright (C) 2016 The Qt Company Ltd.-
4** Contact: https://www.qt.io/licensing/-
5**-
6** This file is part of the QtGui module of the Qt Toolkit.-
7**-
8** $QT_BEGIN_LICENSE:LGPL$-
9** Commercial License Usage-
10** Licensees holding valid commercial Qt licenses may use this file in-
11** accordance with the commercial license agreement provided with the-
12** Software or, alternatively, in accordance with the terms contained in-
13** a written agreement between you and The Qt Company. For licensing terms-
14** and conditions see https://www.qt.io/terms-conditions. For further-
15** information use the contact form at https://www.qt.io/contact-us.-
16**-
17** GNU Lesser General Public License Usage-
18** Alternatively, this file may be used under the terms of the GNU Lesser-
19** General Public License version 3 as published by the Free Software-
20** Foundation and appearing in the file LICENSE.LGPL3 included in the-
21** packaging of this file. Please review the following information to-
22** ensure the GNU Lesser General Public License version 3 requirements-
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.-
24**-
25** GNU General Public License Usage-
26** Alternatively, this file may be used under the terms of the GNU-
27** General Public License version 2.0 or (at your option) the GNU General-
28** Public license version 3 or any later version approved by the KDE Free-
29** Qt Foundation. The licenses are as published by the Free Software-
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3-
31** included in the packaging of this file. Please review the following-
32** information to ensure the GNU General Public License requirements will-
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and-
34** https://www.gnu.org/licenses/gpl-3.0.html.-
35**-
36** $QT_END_LICENSE$-
37**-
38****************************************************************************/-
39-
40#include "qregion.h"-
41#include "qpainterpath.h"-
42#include "qpolygon.h"-
43#include "qbuffer.h"-
44#include "qdatastream.h"-
45#include "qvariant.h"-
46#include "qvarlengtharray.h"-
47#include "qimage.h"-
48#include "qbitmap.h"-
49-
50#include <private/qdebug_p.h>-
51-
52QT_BEGIN_NAMESPACE-
53-
54/*!-
55 \class QRegion-
56 \brief The QRegion class specifies a clip region for a painter.-
57-
58 \inmodule QtGui-
59 \ingroup painting-
60 \ingroup shared-
61-
62 QRegion is used with QPainter::setClipRegion() to limit the paint-
63 area to what needs to be painted. There is also a QWidget::repaint()-
64 function that takes a QRegion parameter. QRegion is the best tool for-
65 minimizing the amount of screen area to be updated by a repaint.-
66-
67 This class is not suitable for constructing shapes for rendering, especially-
68 as outlines. Use QPainterPath to create paths and shapes for use with-
69 QPainter.-
70-
71 QRegion is an \l{implicitly shared} class.-
72-
73 \section1 Creating and Using Regions-
74-
75 A region can be created from a rectangle, an ellipse, a polygon or-
76 a bitmap. Complex regions may be created by combining simple-
77 regions using united(), intersected(), subtracted(), or xored() (exclusive-
78 or). You can move a region using translate().-
79-
80 You can test whether a region isEmpty() or if it-
81 contains() a QPoint or QRect. The bounding rectangle can be found-
82 with boundingRect().-
83-
84 The function rects() gives a decomposition of the region into-
85 rectangles.-
86-
87 Example of using complex regions:-
88 \snippet code/src_gui_painting_qregion.cpp 0-
89-
90 \section1 Additional License Information-
91-
92 On Embedded Linux and X11 platforms, parts of this class rely on-
93 code obtained under the following licenses:-
94-
95 \legalese-
96 Copyright (c) 1987 X Consortium-
97-
98 Permission is hereby granted, free of charge, to any person obtaining a copy-
99 of this software and associated documentation files (the "Software"), to deal-
100 in the Software without restriction, including without limitation the rights-
101 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell-
102 copies of the Software, and to permit persons to whom the Software is-
103 furnished to do so, subject to the following conditions:-
104-
105 The above copyright notice and this permission notice shall be included in-
106 all copies or substantial portions of the Software.-
107-
108 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR-
109 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,-
110 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE-
111 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN-
112 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN-
113 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.-
114-
115 Except as contained in this notice, the name of the X Consortium shall not be-
116 used in advertising or otherwise to promote the sale, use or other dealings-
117 in this Software without prior written authorization from the X Consortium.-
118 \endlegalese-
119-
120 \br-
121-
122 \legalese-
123 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.-
124-
125 All Rights Reserved-
126-
127 Permission to use, copy, modify, and distribute this software and its-
128 documentation for any purpose and without fee is hereby granted,-
129 provided that the above copyright notice appear in all copies and that-
130 both that copyright notice and this permission notice appear in-
131 supporting documentation, and that the name of Digital not be-
132 used in advertising or publicity pertaining to distribution of the-
133 software without specific, written prior permission.-
134-
135 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING-
136 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL-
137 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR-
138 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,-
139 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,-
140 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS-
141 SOFTWARE.-
142 \endlegalese-
143-
144 \sa QPainter::setClipRegion(), QPainter::setClipRect(), QPainterPath-
145*/-
146-
147-
148/*!-
149 \enum QRegion::RegionType-
150-
151 Specifies the shape of the region to be created.-
152-
153 \value Rectangle the region covers the entire rectangle.-
154 \value Ellipse the region is an ellipse inside the rectangle.-
155*/-
156-
157/*!-
158 \fn void QRegion::translate(const QPoint &point)-
159-
160 \overload-
161-
162 Translates the region \a{point}\e{.x()} along the x axis and-
163 \a{point}\e{.y()} along the y axis, relative to the current-
164 position. Positive values move the region to the right and down.-
165-
166 Translates to the given \a point.-
167*/-
168-
169/*****************************************************************************-
170 QRegion member functions-
171 *****************************************************************************/-
172-
173/*!-
174 \fn QRegion::QRegion()-
175-
176 Constructs an empty region.-
177-
178 \sa isEmpty()-
179*/-
180-
181/*!-
182 \fn QRegion::QRegion(const QRect &r, RegionType t)-
183 \overload-
184-
185 Create a region based on the rectange \a r with region type \a t.-
186-
187 If the rectangle is invalid a null region will be created.-
188-
189 \sa QRegion::RegionType-
190*/-
191-
192/*!-
193 \fn QRegion::QRegion(const QPolygon &a, Qt::FillRule fillRule)-
194-
195 Constructs a polygon region from the point array \a a with the fill rule-
196 specified by \a fillRule.-
197-
198 If \a fillRule is \l{Qt::WindingFill}, the polygon region is defined-
199 using the winding algorithm; if it is \l{Qt::OddEvenFill}, the odd-even fill-
200 algorithm is used.-
201-
202 \warning This constructor can be used to create complex regions that will-
203 slow down painting when used.-
204*/-
205-
206/*!-
207 \fn QRegion::QRegion(const QRegion &r)-
208-
209 Constructs a new region which is equal to region \a r.-
210*/-
211-
212/*!-
213 \fn QRegion::QRegion(QRegion &&other)-
214 \since 5.7-
215-
216 Move-constructs a new region from region \a other.-
217 After the call, \a other is null.-
218-
219 \sa isNull()-
220*/-
221-
222/*!-
223 \fn QRegion::QRegion(const QBitmap &bm)-
224-
225 Constructs a region from the bitmap \a bm.-
226-
227 The resulting region consists of the pixels in bitmap \a bm that-
228 are Qt::color1, as if each pixel was a 1 by 1 rectangle.-
229-
230 This constructor may create complex regions that will slow down-
231 painting when used. Note that drawing masked pixmaps can be done-
232 much faster using QPixmap::setMask().-
233*/-
234-
235/*!-
236 Constructs a rectangular or elliptic region.-
237-
238 If \a t is \c Rectangle, the region is the filled rectangle (\a x,-
239 \a y, \a w, \a h). If \a t is \c Ellipse, the region is the filled-
240 ellipse with center at (\a x + \a w / 2, \a y + \a h / 2) and size-
241 (\a w ,\a h).-
242*/-
243QRegion::QRegion(int x, int y, int w, int h, RegionType t)-
244{-
245 QRegion tmp(QRect(x, y, w, h), t);-
246 tmp.d->ref.ref();-
247 d = tmp.d;-
248}
never executed: end of block
0
249-
250/*!-
251 \fn QRegion::~QRegion()-
252 \internal-
253-
254 Destroys the region.-
255*/-
256-
257void QRegion::detach()-
258{-
259 if (d->ref.isShared())
d->ref.isShared()Description
TRUEnever evaluated
FALSEnever evaluated
0
260 *this = copy();
never executed: *this = copy();
0
261}
never executed: end of block
0
262-
263// duplicates in qregion_win.cpp and qregion_wce.cpp-
264#define QRGN_SETRECT 1 // region stream commands-
265#define QRGN_SETELLIPSE 2 // (these are internal)-
266#define QRGN_SETPTARRAY_ALT 3-
267#define QRGN_SETPTARRAY_WIND 4-
268#define QRGN_TRANSLATE 5-
269#define QRGN_OR 6-
270#define QRGN_AND 7-
271#define QRGN_SUB 8-
272#define QRGN_XOR 9-
273#define QRGN_RECTS 10-
274-
275-
276#ifndef QT_NO_DATASTREAM-
277-
278/*-
279 Executes region commands in the internal buffer and rebuilds the-
280 original region.-
281-
282 We do this when we read a region from the data stream.-
283-
284 If \a ver is non-0, uses the format version \a ver on reading the-
285 byte array.-
286*/-
287void QRegion::exec(const QByteArray &buffer, int ver, QDataStream::ByteOrder byteOrder)-
288{-
289 QByteArray copy = buffer;-
290 QDataStream s(&copy, QIODevice::ReadOnly);-
291 if (ver)
verDescription
TRUEnever evaluated
FALSEnever evaluated
0
292 s.setVersion(ver);
never executed: s.setVersion(ver);
0
293 s.setByteOrder(byteOrder);-
294 QRegion rgn;-
295#ifndef QT_NO_DEBUG-
296 int test_cnt = 0;-
297#endif-
298 while (!s.atEnd()) {
!s.atEnd()Description
TRUEnever evaluated
FALSEnever evaluated
0
299 qint32 id;-
300 if (s.version() == 1) {
s.version() == 1Description
TRUEnever evaluated
FALSEnever evaluated
0
301 int id_int;-
302 s >> id_int;-
303 id = id_int;-
304 } else {
never executed: end of block
0
305 s >> id;-
306 }
never executed: end of block
0
307#ifndef QT_NO_DEBUG-
308 if (test_cnt > 0 && id != QRGN_TRANSLATE)
test_cnt > 0Description
TRUEnever evaluated
FALSEnever evaluated
id != 5Description
TRUEnever evaluated
FALSEnever evaluated
0
309 qWarning("QRegion::exec: Internal error");
never executed: QMessageLogger(__FILE__, 309, __PRETTY_FUNCTION__).warning("QRegion::exec: Internal error");
0
310 test_cnt++;-
311#endif-
312 if (id == QRGN_SETRECT || id == QRGN_SETELLIPSE) {
id == 1Description
TRUEnever evaluated
FALSEnever evaluated
id == 2Description
TRUEnever evaluated
FALSEnever evaluated
0
313 QRect r;-
314 s >> r;-
315 rgn = QRegion(r, id == QRGN_SETRECT ? Rectangle : Ellipse);-
316 } else if (id == QRGN_SETPTARRAY_ALT || id == QRGN_SETPTARRAY_WIND) {
never executed: end of block
id == 3Description
TRUEnever evaluated
FALSEnever evaluated
id == 4Description
TRUEnever evaluated
FALSEnever evaluated
0
317 QPolygon a;-
318 s >> a;-
319 rgn = QRegion(a, id == QRGN_SETPTARRAY_WIND ? Qt::WindingFill : Qt::OddEvenFill);-
320 } else if (id == QRGN_TRANSLATE) {
never executed: end of block
id == 5Description
TRUEnever evaluated
FALSEnever evaluated
0
321 QPoint p;-
322 s >> p;-
323 rgn.translate(p.x(), p.y());-
324 } else if (id >= QRGN_OR && id <= QRGN_XOR) {
never executed: end of block
id >= 6Description
TRUEnever evaluated
FALSEnever evaluated
id <= 9Description
TRUEnever evaluated
FALSEnever evaluated
0
325 QByteArray bop1, bop2;-
326 QRegion r1, r2;-
327 s >> bop1;-
328 r1.exec(bop1);-
329 s >> bop2;-
330 r2.exec(bop2);-
331-
332 switch (id) {-
333 case QRGN_OR:
never executed: case 6:
0
334 rgn = r1.united(r2);-
335 break;
never executed: break;
0
336 case QRGN_AND:
never executed: case 7:
0
337 rgn = r1.intersected(r2);-
338 break;
never executed: break;
0
339 case QRGN_SUB:
never executed: case 8:
0
340 rgn = r1.subtracted(r2);-
341 break;
never executed: break;
0
342 case QRGN_XOR:
never executed: case 9:
0
343 rgn = r1.xored(r2);-
344 break;
never executed: break;
0
345 }-
346 } else if (id == QRGN_RECTS) {
never executed: end of block
id == 10Description
TRUEnever evaluated
FALSEnever evaluated
0
347 // (This is the only form used in Qt 2.0)-
348 quint32 n;-
349 s >> n;-
350 QRect r;-
351 for (int i=0; i<(int)n; i++) {
i<(int)nDescription
TRUEnever evaluated
FALSEnever evaluated
0
352 s >> r;-
353 rgn = rgn.united(QRegion(r));-
354 }
never executed: end of block
0
355 }
never executed: end of block
0
356 }
never executed: end of block
0
357 *this = rgn;-
358}
never executed: end of block
0
359-
360-
361/*****************************************************************************-
362 QRegion stream functions-
363 *****************************************************************************/-
364-
365/*!-
366 \fn QRegion &QRegion::operator=(const QRegion &r)-
367-
368 Assigns \a r to this region and returns a reference to the region.-
369*/-
370-
371/*!-
372 \fn QRegion &QRegion::operator=(QRegion &&other)-
373-
374 Move-assigns \a other to this QRegion instance.-
375-
376 \since 5.2-
377*/-
378-
379/*!-
380 \fn void QRegion::swap(QRegion &other)-
381 \since 4.8-
382-
383 Swaps region \a other with this region. This operation is very-
384 fast and never fails.-
385*/-
386-
387/*!-
388 \relates QRegion-
389-
390 Writes the region \a r to the stream \a s and returns a reference-
391 to the stream.-
392-
393 \sa{Serializing Qt Data Types}{Format of the QDataStream operators}-
394*/-
395-
396QDataStream &operator<<(QDataStream &s, const QRegion &r)-
397{-
398 QVector<QRect> a = r.rects();-
399 if (a.isEmpty()) {
a.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
400 s << (quint32)0;-
401 } else {
never executed: end of block
0
402 if (s.version() == 1) {
s.version() == 1Description
TRUEnever evaluated
FALSEnever evaluated
0
403 int i;-
404 for (i = a.size() - 1; i > 0; --i) {
i > 0Description
TRUEnever evaluated
FALSEnever evaluated
0
405 s << (quint32)(12 + i * 24);-
406 s << (int)QRGN_OR;-
407 }
never executed: end of block
0
408 for (i = 0; i < a.size(); ++i) {
i < a.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
409 s << (quint32)(4+8) << (int)QRGN_SETRECT << a[i];-
410 }
never executed: end of block
0
411 } else {
never executed: end of block
0
412 s << (quint32)(4 + 4 + 16 * a.size()); // 16: storage size of QRect-
413 s << (qint32)QRGN_RECTS;-
414 s << a;-
415 }
never executed: end of block
0
416 }-
417 return s;
never executed: return s;
0
418}-
419-
420/*!-
421 \relates QRegion-
422-
423 Reads a region from the stream \a s into \a r and returns a-
424 reference to the stream.-
425-
426 \sa{Serializing Qt Data Types}{Format of the QDataStream operators}-
427*/-
428-
429QDataStream &operator>>(QDataStream &s, QRegion &r)-
430{-
431 QByteArray b;-
432 s >> b;-
433 r.exec(b, s.version(), s.byteOrder());-
434 return s;
never executed: return s;
0
435}-
436#endif //QT_NO_DATASTREAM-
437-
438#ifndef QT_NO_DEBUG_STREAM-
439QDebug operator<<(QDebug s, const QRegion &r)-
440{-
441 QDebugStateSaver saver(s);-
442 s.nospace();-
443 s << "QRegion(";-
444 if (r.isNull()) {
r.isNull()Description
TRUEnever evaluated
FALSEnever evaluated
0
445 s << "null";-
446 } else if (r.isEmpty()) {
never executed: end of block
r.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
447 s << "empty";-
448 } else {
never executed: end of block
0
449 const QVector<QRect> rects = r.rects();-
450 const int count = rects.size();-
451 if (count > 1)
count > 1Description
TRUEnever evaluated
FALSEnever evaluated
0
452 s << "size=" << count << ", bounds=(";
never executed: s << "size=" << count << ", bounds=(";
0
453 QtDebugUtils::formatQRect(s, r.boundingRect());-
454 if (count > 1) {
count > 1Description
TRUEnever evaluated
FALSEnever evaluated
0
455 s << ") - [";-
456 for (int i = 0; i < count; ++i) {
i < countDescription
TRUEnever evaluated
FALSEnever evaluated
0
457 if (i)
iDescription
TRUEnever evaluated
FALSEnever evaluated
0
458 s << ", ";
never executed: s << ", ";
0
459 s << '(';-
460 QtDebugUtils::formatQRect(s, rects.at(i));-
461 s << ')';-
462 }
never executed: end of block
0
463 s << ']';-
464 }
never executed: end of block
0
465 }
never executed: end of block
0
466 s << ')';-
467 return s;
never executed: return s;
0
468}-
469#endif-
470-
471-
472// These are not inline - they can be implemented better on some platforms-
473// (eg. Windows at least provides 3-variable operations). For now, simple.-
474-
475-
476/*!-
477 Applies the united() function to this region and \a r. \c r1|r2 is-
478 equivalent to \c r1.united(r2).-
479-
480 \sa united(), operator+()-
481*/-
482#ifdef Q_COMPILER_MANGLES_RETURN_TYPE-
483const-
484#endif-
485QRegion QRegion::operator|(const QRegion &r) const-
486 { return united(r); }
never executed: return united(r);
0
487-
488/*!-
489 Applies the united() function to this region and \a r. \c r1+r2 is-
490 equivalent to \c r1.united(r2).-
491-
492 \sa united(), operator|()-
493*/-
494#ifdef Q_COMPILER_MANGLES_RETURN_TYPE-
495const-
496#endif-
497QRegion QRegion::operator+(const QRegion &r) const-
498 { return united(r); }
never executed: return united(r);
0
499-
500/*!-
501 \overload-
502 \since 4.4-
503 */-
504#ifdef Q_COMPILER_MANGLES_RETURN_TYPE-
505const-
506#endif-
507QRegion QRegion::operator+(const QRect &r) const-
508 { return united(r); }
never executed: return united(r);
0
509-
510/*!-
511 Applies the intersected() function to this region and \a r. \c r1&r2-
512 is equivalent to \c r1.intersected(r2).-
513-
514 \sa intersected()-
515*/-
516#ifdef Q_COMPILER_MANGLES_RETURN_TYPE-
517const-
518#endif-
519QRegion QRegion::operator&(const QRegion &r) const-
520 { return intersected(r); }
never executed: return intersected(r);
0
521-
522/*!-
523 \overload-
524 \since 4.4-
525 */-
526#ifdef Q_COMPILER_MANGLES_RETURN_TYPE-
527const-
528#endif-
529QRegion QRegion::operator&(const QRect &r) const-
530{-
531 return intersected(r);
never executed: return intersected(r);
0
532}-
533-
534/*!-
535 Applies the subtracted() function to this region and \a r. \c r1-r2-
536 is equivalent to \c r1.subtracted(r2).-
537-
538 \sa subtracted()-
539*/-
540#ifdef Q_COMPILER_MANGLES_RETURN_TYPE-
541const-
542#endif-
543QRegion QRegion::operator-(const QRegion &r) const-
544 { return subtracted(r); }
never executed: return subtracted(r);
0
545-
546/*!-
547 Applies the xored() function to this region and \a r. \c r1^r2 is-
548 equivalent to \c r1.xored(r2).-
549-
550 \sa xored()-
551*/-
552#ifdef Q_COMPILER_MANGLES_RETURN_TYPE-
553const-
554#endif-
555QRegion QRegion::operator^(const QRegion &r) const-
556 { return xored(r); }
never executed: return xored(r);
0
557-
558/*!-
559 Applies the united() function to this region and \a r and assigns-
560 the result to this region. \c r1|=r2 is equivalent to \c-
561 {r1 = r1.united(r2)}.-
562-
563 \sa united()-
564*/-
565QRegion& QRegion::operator|=(const QRegion &r)-
566 { return *this = *this | r; }
never executed: return *this = *this | r;
0
567-
568/*!-
569 \fn QRegion& QRegion::operator+=(const QRect &rect)-
570-
571 Returns a region that is the union of this region with the specified \a rect.-
572-
573 \sa united()-
574*/-
575/*!-
576 \fn QRegion& QRegion::operator+=(const QRegion &r)-
577-
578 Applies the united() function to this region and \a r and assigns-
579 the result to this region. \c r1+=r2 is equivalent to \c-
580 {r1 = r1.united(r2)}.-
581-
582 \sa intersected()-
583*/-
584#if !defined (Q_OS_UNIX) && !defined (Q_OS_WIN)-
585QRegion& QRegion::operator+=(const QRect &r)-
586{-
587 return operator+=(QRegion(r));-
588}-
589#endif-
590-
591/*!-
592 \fn QRegion& QRegion::operator&=(const QRegion &r)-
593-
594 Applies the intersected() function to this region and \a r and-
595 assigns the result to this region. \c r1&=r2 is equivalent to \c-
596 r1 = r1.intersected(r2).-
597-
598 \sa intersected()-
599*/-
600QRegion& QRegion::operator&=(const QRegion &r)-
601 { return *this = *this & r; }
never executed: return *this = *this & r;
0
602-
603/*!-
604 \overload-
605 \since 4.4-
606 */-
607#if defined (Q_OS_UNIX) || defined (Q_OS_WIN)-
608QRegion& QRegion::operator&=(const QRect &r)-
609{-
610 return *this = *this & r;
never executed: return *this = *this & r;
0
611}-
612#else-
613QRegion& QRegion::operator&=(const QRect &r)-
614{-
615 return *this &= (QRegion(r));-
616}-
617#endif-
618-
619/*!-
620 \fn QRegion& QRegion::operator-=(const QRegion &r)-
621-
622 Applies the subtracted() function to this region and \a r and-
623 assigns the result to this region. \c r1-=r2 is equivalent to \c-
624 {r1 = r1.subtracted(r2)}.-
625-
626 \sa subtracted()-
627*/-
628QRegion& QRegion::operator-=(const QRegion &r)-
629 { return *this = *this - r; }
never executed: return *this = *this - r;
0
630-
631/*!-
632 Applies the xored() function to this region and \a r and-
633 assigns the result to this region. \c r1^=r2 is equivalent to \c-
634 {r1 = r1.xored(r2)}.-
635-
636 \sa xored()-
637*/-
638QRegion& QRegion::operator^=(const QRegion &r)-
639 { return *this = *this ^ r; }
never executed: return *this = *this ^ r;
0
640-
641/*!-
642 \fn bool QRegion::operator!=(const QRegion &other) const-
643-
644 Returns \c true if this region is different from the \a other region;-
645 otherwise returns \c false.-
646*/-
647-
648/*!-
649 Returns the region as a QVariant-
650*/-
651QRegion::operator QVariant() const-
652{-
653 return QVariant(QVariant::Region, this);
never executed: return QVariant(QVariant::Region, this);
0
654}-
655-
656/*!-
657 \fn bool QRegion::operator==(const QRegion &r) const-
658-
659 Returns \c true if the region is equal to \a r; otherwise returns-
660 false.-
661*/-
662-
663/*!-
664 \fn void QRegion::translate(int dx, int dy)-
665-
666 Translates (moves) the region \a dx along the X axis and \a dy-
667 along the Y axis.-
668*/-
669-
670/*!-
671 \fn QRegion QRegion::translated(const QPoint &p) const-
672 \overload-
673 \since 4.1-
674-
675 Returns a copy of the regtion that is translated \a{p}\e{.x()}-
676 along the x axis and \a{p}\e{.y()} along the y axis, relative to-
677 the current position. Positive values move the rectangle to the-
678 right and down.-
679-
680 \sa translate()-
681*/-
682-
683/*!-
684 \since 4.1-
685-
686 Returns a copy of the region that is translated \a dx along the-
687 x axis and \a dy along the y axis, relative to the current-
688 position. Positive values move the region to the right and-
689 down.-
690-
691 \sa translate()-
692*/-
693-
694QRegion-
695QRegion::translated(int dx, int dy) const-
696{-
697 QRegion ret(*this);-
698 ret.translate(dx, dy);-
699 return ret;
never executed: return ret;
0
700}-
701-
702-
703inline bool rect_intersects(const QRect &r1, const QRect &r2)-
704{-
705 return (r1.right() >= r2.left() && r1.left() <= r2.right() &&
never executed: return (r1.right() >= r2.left() && r1.left() <= r2.right() && r1.bottom() >= r2.top() && r1.top() <= r2.bottom());
0
706 r1.bottom() >= r2.top() && r1.top() <= r2.bottom());
never executed: return (r1.right() >= r2.left() && r1.left() <= r2.right() && r1.bottom() >= r2.top() && r1.top() <= r2.bottom());
0
707}-
708-
709/*!-
710 \since 4.2-
711-
712 Returns \c true if this region intersects with \a region, otherwise-
713 returns \c false.-
714*/-
715bool QRegion::intersects(const QRegion &region) const-
716{-
717 if (isEmpty() || region.isEmpty())
isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
region.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
718 return false;
never executed: return false;
0
719-
720 if (!rect_intersects(boundingRect(), region.boundingRect()))
!rect_intersec...oundingRect())Description
TRUEnever evaluated
FALSEnever evaluated
0
721 return false;
never executed: return false;
0
722 if (rectCount() == 1 && region.rectCount() == 1)
rectCount() == 1Description
TRUEnever evaluated
FALSEnever evaluated
region.rectCount() == 1Description
TRUEnever evaluated
FALSEnever evaluated
0
723 return true;
never executed: return true;
0
724-
725 const QVector<QRect> myRects = rects();-
726 const QVector<QRect> otherRects = region.rects();-
727-
728 for (QVector<QRect>::const_iterator i1 = myRects.constBegin(); i1 < myRects.constEnd(); ++i1)
i1 < myRects.constEnd()Description
TRUEnever evaluated
FALSEnever evaluated
0
729 for (QVector<QRect>::const_iterator i2 = otherRects.constBegin(); i2 < otherRects.constEnd(); ++i2)
i2 < otherRects.constEnd()Description
TRUEnever evaluated
FALSEnever evaluated
0
730 if (rect_intersects(*i1, *i2))
rect_intersects(*i1, *i2)Description
TRUEnever evaluated
FALSEnever evaluated
0
731 return true;
never executed: return true;
0
732 return false;
never executed: return false;
0
733}-
734-
735/*!-
736 \fn bool QRegion::intersects(const QRect &rect) const-
737 \since 4.2-
738-
739 Returns \c true if this region intersects with \a rect, otherwise-
740 returns \c false.-
741*/-
742-
743-
744#if !defined (Q_OS_UNIX) && !defined (Q_OS_WIN)-
745/*!-
746 \overload-
747 \since 4.4-
748*/-
749QRegion QRegion::intersect(const QRect &r) const-
750{-
751 return intersect(QRegion(r));-
752}-
753#endif-
754-
755/*!-
756 \fn int QRegion::rectCount() const-
757 \since 4.6-
758-
759 Returns the number of rectangles that will be returned in rects().-
760*/-
761-
762/*!-
763 \fn bool QRegion::isEmpty() const-
764-
765 Returns \c true if the region is empty; otherwise returns \c false. An-
766 empty region is a region that contains no points.-
767-
768 Example:-
769 \snippet code/src_gui_painting_qregion_unix.cpp 0-
770*/-
771-
772/*!-
773 \fn bool QRegion::isNull() const-
774 \since 5.0-
775-
776 Returns \c true if the region is empty; otherwise returns \c false. An-
777 empty region is a region that contains no points. This function is-
778 the same as isEmpty-
779-
780 \sa isEmpty()-
781*/-
782-
783/*!-
784 \fn bool QRegion::contains(const QPoint &p) const-
785-
786 Returns \c true if the region contains the point \a p; otherwise-
787 returns \c false.-
788*/-
789-
790/*!-
791 \fn bool QRegion::contains(const QRect &r) const-
792 \overload-
793-
794 Returns \c true if the region overlaps the rectangle \a r; otherwise-
795 returns \c false.-
796*/-
797-
798/*!-
799 \fn QRegion QRegion::unite(const QRegion &r) const-
800 \obsolete-
801-
802 Use united(\a r) instead.-
803*/-
804-
805/*!-
806 \fn QRegion QRegion::unite(const QRect &rect) const-
807 \since 4.4-
808 \obsolete-
809-
810 Use united(\a rect) instead.-
811*/-
812-
813/*!-
814 \fn QRegion QRegion::united(const QRect &rect) const-
815 \since 4.4-
816-
817 Returns a region which is the union of this region and the given \a rect.-
818-
819 \sa intersected(), subtracted(), xored()-
820*/-
821-
822/*!-
823 \fn QRegion QRegion::united(const QRegion &r) const-
824 \since 4.2-
825-
826 Returns a region which is the union of this region and \a r.-
827-
828 \image runion.png Region Union-
829-
830 The figure shows the union of two elliptical regions.-
831-
832 \sa intersected(), subtracted(), xored()-
833*/-
834-
835/*!-
836 \fn QRegion QRegion::intersect(const QRegion &r) const-
837 \obsolete-
838-
839 Use intersected(\a r) instead.-
840*/-
841-
842/*!-
843 \fn QRegion QRegion::intersect(const QRect &rect) const-
844 \since 4.4-
845 \obsolete-
846-
847 Use intersected(\a rect) instead.-
848*/-
849-
850/*!-
851 \fn QRegion QRegion::intersected(const QRect &rect) const-
852 \since 4.4-
853-
854 Returns a region which is the intersection of this region and the given \a rect.-
855-
856 \sa subtracted(), united(), xored()-
857*/-
858-
859/*!-
860 \fn QRegion QRegion::intersected(const QRegion &r) const-
861 \since 4.2-
862-
863 Returns a region which is the intersection of this region and \a r.-
864-
865 \image rintersect.png Region Intersection-
866-
867 The figure shows the intersection of two elliptical regions.-
868-
869 \sa subtracted(), united(), xored()-
870*/-
871-
872/*!-
873 \fn QRegion QRegion::subtract(const QRegion &r) const-
874 \obsolete-
875-
876 Use subtracted(\a r) instead.-
877*/-
878-
879/*!-
880 \fn QRegion QRegion::subtracted(const QRegion &r) const-
881 \since 4.2-
882-
883 Returns a region which is \a r subtracted from this region.-
884-
885 \image rsubtract.png Region Subtraction-
886-
887 The figure shows the result when the ellipse on the right is-
888 subtracted from the ellipse on the left (\c {left - right}).-
889-
890 \sa intersected(), united(), xored()-
891*/-
892-
893/*!-
894 \fn QRegion QRegion::eor(const QRegion &r) const-
895 \obsolete-
896-
897 Use xored(\a r) instead.-
898*/-
899-
900/*!-
901 \fn QRegion QRegion::xored(const QRegion &r) const-
902 \since 4.2-
903-
904 Returns a region which is the exclusive or (XOR) of this region-
905 and \a r.-
906-
907 \image rxor.png Region XORed-
908-
909 The figure shows the exclusive or of two elliptical regions.-
910-
911 \sa intersected(), united(), subtracted()-
912*/-
913-
914/*!-
915 \fn QRect QRegion::boundingRect() const-
916-
917 Returns the bounding rectangle of this region. An empty region-
918 gives a rectangle that is QRect::isNull().-
919*/-
920-
921/*!-
922 \fn QVector<QRect> QRegion::rects() const-
923-
924 Returns an array of non-overlapping rectangles that make up the-
925 region.-
926-
927 The union of all the rectangles is equal to the original region.-
928*/-
929-
930/*!-
931 \fn void QRegion::setRects(const QRect *rects, int number)-
932-
933 Sets the region using the array of rectangles specified by \a rects and-
934 \a number.-
935 The rectangles \e must be optimally Y-X sorted and follow these restrictions:-
936-
937 \list-
938 \li The rectangles must not intersect.-
939 \li All rectangles with a given top coordinate must have the same height.-
940 \li No two rectangles may abut horizontally (they should be combined-
941 into a single wider rectangle in that case).-
942 \li The rectangles must be sorted in ascending order, with Y as the major-
943 sort key and X as the minor sort key.-
944 \endlist-
945 \omit-
946 Only some platforms have these restrictions (Qt for Embedded Linux, X11 and \macos).-
947 \endomit-
948*/-
949-
950namespace {-
951-
952struct Segment-
953{-
954 Segment() {}-
955 Segment(const QPoint &p)-
956 : added(false)-
957 , point(p)-
958 {-
959 }
never executed: end of block
0
960-
961 int left() const-
962 {-
963 return qMin(point.x(), next->point.x());
never executed: return qMin(point.x(), next->point.x());
0
964 }-
965-
966 int right() const-
967 {-
968 return qMax(point.x(), next->point.x());
never executed: return qMax(point.x(), next->point.x());
0
969 }-
970-
971 bool overlaps(const Segment &other) const-
972 {-
973 return left() < other.right() && other.left() < right();
never executed: return left() < other.right() && other.left() < right();
0
974 }-
975-
976 void connect(Segment &other)-
977 {-
978 next = &other;-
979 other.prev = this;-
980-
981 horizontal = (point.y() == other.point.y());-
982 }
never executed: end of block
0
983-
984 void merge(Segment &other)-
985 {-
986 if (right() <= other.right()) {
right() <= other.right()Description
TRUEnever evaluated
FALSEnever evaluated
0
987 QPoint p = other.point;-
988 Segment *oprev = other.prev;-
989-
990 other.point = point;-
991 other.prev = prev;-
992 prev->next = &other;-
993-
994 point = p;-
995 prev = oprev;-
996 oprev->next = this;-
997 } else {
never executed: end of block
0
998 Segment *onext = other.next;-
999 other.next = next;-
1000 next->prev = &other;-
1001-
1002 next = onext;-
1003 next->prev = this;-
1004 }
never executed: end of block
0
1005 }-
1006-
1007 int horizontal : 1;-
1008 int added : 1;-
1009-
1010 QPoint point;-
1011 Segment *prev;-
1012 Segment *next;-
1013};-
1014-
1015void mergeSegments(Segment *a, int na, Segment *b, int nb)-
1016{-
1017 int i = 0;-
1018 int j = 0;-
1019-
1020 while (i != na && j != nb) {
i != naDescription
TRUEnever evaluated
FALSEnever evaluated
j != nbDescription
TRUEnever evaluated
FALSEnever evaluated
0
1021 Segment &sa = a[i];-
1022 Segment &sb = b[j];-
1023 const int ra = sa.right();-
1024 const int rb = sb.right();-
1025 if (sa.overlaps(sb))
sa.overlaps(sb)Description
TRUEnever evaluated
FALSEnever evaluated
0
1026 sa.merge(sb);
never executed: sa.merge(sb);
0
1027 i += (rb >= ra);-
1028 j += (ra >= rb);-
1029 }
never executed: end of block
0
1030}
never executed: end of block
0
1031-
1032void addSegmentsToPath(Segment *segment, QPainterPath &path)-
1033{-
1034 Segment *current = segment;-
1035 path.moveTo(current->point);-
1036-
1037 current->added = true;-
1038-
1039 Segment *last = current;-
1040 current = current->next;-
1041 while (current != segment) {
current != segmentDescription
TRUEnever evaluated
FALSEnever evaluated
0
1042 if (current->horizontal != last->horizontal)
current->horiz...st->horizontalDescription
TRUEnever evaluated
FALSEnever evaluated
0
1043 path.lineTo(current->point);
never executed: path.lineTo(current->point);
0
1044 current->added = true;-
1045 last = current;-
1046 current = current->next;-
1047 }
never executed: end of block
0
1048}
never executed: end of block
0
1049-
1050} // unnamed namespace-
1051-
1052// the following is really a lie, because Segments cannot be relocated, as they-
1053// reference each other by address. For the same reason, they aren't even copyable,-
1054// but the code works with the compiler-generated (wrong) copy and move special-
1055// members, so use this as an optimization. The only container these are used in-
1056// (a QVarLengthArray in qt_regionToPath()) is resized once up-front, so doesn't-
1057// have a problem with this, but benefits from not having to run Segment ctors:-
1058Q_DECLARE_TYPEINFO(Segment, Q_PRIMITIVE_TYPE);-
1059-
1060Q_GUI_EXPORT QPainterPath qt_regionToPath(const QRegion &region)-
1061{-
1062 QPainterPath result;-
1063 if (region.rectCount() == 1) {
region.rectCount() == 1Description
TRUEnever evaluated
FALSEnever evaluated
0
1064 result.addRect(region.boundingRect());-
1065 return result;
never executed: return result;
0
1066 }-
1067-
1068 const QVector<QRect> rects = region.rects();-
1069-
1070 QVarLengthArray<Segment> segments;-
1071 segments.resize(4 * rects.size());-
1072-
1073 const QRect *rect = rects.constData();-
1074 const QRect *end = rect + rects.size();-
1075-
1076 int lastRowSegmentCount = 0;-
1077 Segment *lastRowSegments = 0;-
1078-
1079 int lastSegment = 0;-
1080 int lastY = 0;-
1081 while (rect != end) {
rect != endDescription
TRUEnever evaluated
FALSEnever evaluated
0
1082 const int y = rect[0].y();-
1083 int count = 0;-
1084 while (&rect[count] != end && rect[count].y() == y)
&rect[count] != endDescription
TRUEnever evaluated
FALSEnever evaluated
rect[count].y() == yDescription
TRUEnever evaluated
FALSEnever evaluated
0
1085 ++count;
never executed: ++count;
0
1086-
1087 for (int i = 0; i < count; ++i) {
i < countDescription
TRUEnever evaluated
FALSEnever evaluated
0
1088 int offset = lastSegment + i;-
1089 segments[offset] = Segment(rect[i].topLeft());-
1090 segments[offset += count] = Segment(rect[i].topRight() + QPoint(1, 0));-
1091 segments[offset += count] = Segment(rect[i].bottomRight() + QPoint(1, 1));-
1092 segments[offset += count] = Segment(rect[i].bottomLeft() + QPoint(0, 1));-
1093-
1094 offset = lastSegment + i;-
1095 for (int j = 0; j < 4; ++j)
j < 4Description
TRUEnever evaluated
FALSEnever evaluated
0
1096 segments[offset + j * count].connect(segments[offset + ((j + 1) % 4) * count]);
never executed: segments[offset + j * count].connect(segments[offset + ((j + 1) % 4) * count]);
0
1097 }
never executed: end of block
0
1098-
1099 if (lastRowSegments && lastY == y)
lastRowSegmentsDescription
TRUEnever evaluated
FALSEnever evaluated
lastY == yDescription
TRUEnever evaluated
FALSEnever evaluated
0
1100 mergeSegments(lastRowSegments, lastRowSegmentCount, &segments[lastSegment], count);
never executed: mergeSegments(lastRowSegments, lastRowSegmentCount, &segments[lastSegment], count);
0
1101-
1102 lastRowSegments = &segments[lastSegment + 2 * count];-
1103 lastRowSegmentCount = count;-
1104 lastSegment += 4 * count;-
1105 lastY = y + rect[0].height();-
1106 rect += count;-
1107 }
never executed: end of block
0
1108-
1109 for (int i = 0; i < lastSegment; ++i) {
i < lastSegmentDescription
TRUEnever evaluated
FALSEnever evaluated
0
1110 Segment *segment = &segments[i];-
1111 if (!segment->added)
!segment->addedDescription
TRUEnever evaluated
FALSEnever evaluated
0
1112 addSegmentsToPath(segment, result);
never executed: addSegmentsToPath(segment, result);
0
1113 }
never executed: end of block
0
1114-
1115 return result;
never executed: return result;
0
1116}-
1117-
1118#if defined(Q_OS_UNIX) || defined(Q_OS_WIN)-
1119-
1120//#define QT_REGION_DEBUG-
1121/*-
1122 * clip region-
1123 */-
1124-
1125struct QRegionPrivate {-
1126 int numRects;-
1127 int innerArea;-
1128 QVector<QRect> rects;-
1129 QRect extents;-
1130 QRect innerRect;-
1131-
1132 inline QRegionPrivate() : numRects(0), innerArea(-1) {}
never executed: end of block
0
1133 inline QRegionPrivate(const QRect &r)-
1134 : numRects(1),-
1135 innerArea(r.width() * r.height()),-
1136 extents(r),-
1137 innerRect(r)-
1138 {-
1139 }
never executed: end of block
0
1140-
1141 void intersect(const QRect &r);-
1142-
1143 /*-
1144 * Returns \c true if r is guaranteed to be fully contained in this region.-
1145 * A false return value does not guarantee the opposite.-
1146 */-
1147 inline bool contains(const QRegionPrivate &r) const {-
1148 return contains(r.extents);
never executed: return contains(r.extents);
0
1149 }-
1150-
1151 inline bool contains(const QRect &r2) const {-
1152 const QRect &r1 = innerRect;-
1153 return r2.left() >= r1.left() && r2.right() <= r1.right()
never executed: return r2.left() >= r1.left() && r2.right() <= r1.right() && r2.top() >= r1.top() && r2.bottom() <= r1.bottom();
0
1154 && r2.top() >= r1.top() && r2.bottom() <= r1.bottom();
never executed: return r2.left() >= r1.left() && r2.right() <= r1.right() && r2.top() >= r1.top() && r2.bottom() <= r1.bottom();
0
1155 }-
1156-
1157 /*-
1158 * Returns \c true if this region is guaranteed to be fully contained in r.-
1159 */-
1160 inline bool within(const QRect &r1) const {-
1161 const QRect &r2 = extents;-
1162 return r2.left() >= r1.left() && r2.right() <= r1.right()
never executed: return r2.left() >= r1.left() && r2.right() <= r1.right() && r2.top() >= r1.top() && r2.bottom() <= r1.bottom();
0
1163 && r2.top() >= r1.top() && r2.bottom() <= r1.bottom();
never executed: return r2.left() >= r1.left() && r2.right() <= r1.right() && r2.top() >= r1.top() && r2.bottom() <= r1.bottom();
0
1164 }-
1165-
1166 inline void updateInnerRect(const QRect &rect) {-
1167 const int area = rect.width() * rect.height();-
1168 if (area > innerArea) {
area > innerAreaDescription
TRUEnever evaluated
FALSEnever evaluated
0
1169 innerArea = area;-
1170 innerRect = rect;-
1171 }
never executed: end of block
0
1172 }
never executed: end of block
0
1173-
1174 inline void vectorize() {-
1175 if (numRects == 1) {
numRects == 1Description
TRUEnever evaluated
FALSEnever evaluated
0
1176 if (!rects.size())
!rects.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
1177 rects.resize(1);
never executed: rects.resize(1);
0
1178 rects[0] = extents;-
1179 }
never executed: end of block
0
1180 }
never executed: end of block
0
1181-
1182 inline void append(const QRect *r);-
1183 void append(const QRegionPrivate *r);-
1184 void prepend(const QRect *r);-
1185 void prepend(const QRegionPrivate *r);-
1186 inline bool canAppend(const QRect *r) const;-
1187 inline bool canAppend(const QRegionPrivate *r) const;-
1188 inline bool canPrepend(const QRect *r) const;-
1189 inline bool canPrepend(const QRegionPrivate *r) const;-
1190-
1191 inline bool mergeFromRight(QRect *left, const QRect *right);-
1192 inline bool mergeFromLeft(QRect *left, const QRect *right);-
1193 inline bool mergeFromBelow(QRect *top, const QRect *bottom,-
1194 const QRect *nextToTop,-
1195 const QRect *nextToBottom);-
1196 inline bool mergeFromAbove(QRect *bottom, const QRect *top,-
1197 const QRect *nextToBottom,-
1198 const QRect *nextToTop);-
1199-
1200#ifdef QT_REGION_DEBUG-
1201 void selfTest() const;-
1202#endif-
1203};-
1204-
1205static inline bool isEmptyHelper(const QRegionPrivate *preg)-
1206{-
1207 return !preg || preg->numRects == 0;
never executed: return !preg || preg->numRects == 0;
0
1208}-
1209-
1210static inline bool canMergeFromRight(const QRect *left, const QRect *right)-
1211{-
1212 return (right->top() == left->top()
never executed: return (right->top() == left->top() && right->bottom() == left->bottom() && right->left() <= (left->right() + 1));
0
1213 && right->bottom() == left->bottom()
never executed: return (right->top() == left->top() && right->bottom() == left->bottom() && right->left() <= (left->right() + 1));
0
1214 && right->left() <= (left->right() + 1));
never executed: return (right->top() == left->top() && right->bottom() == left->bottom() && right->left() <= (left->right() + 1));
0
1215}-
1216-
1217static inline bool canMergeFromLeft(const QRect *right, const QRect *left)-
1218{-
1219 return canMergeFromRight(left, right);
never executed: return canMergeFromRight(left, right);
0
1220}-
1221-
1222bool QRegionPrivate::mergeFromRight(QRect *left, const QRect *right)-
1223{-
1224 if (canMergeFromRight(left, right)) {
canMergeFromRight(left, right)Description
TRUEnever evaluated
FALSEnever evaluated
0
1225 left->setRight(right->right());-
1226 updateInnerRect(*left);-
1227 return true;
never executed: return true;
0
1228 }-
1229 return false;
never executed: return false;
0
1230}-
1231-
1232bool QRegionPrivate::mergeFromLeft(QRect *right, const QRect *left)-
1233{-
1234 if (canMergeFromLeft(right, left)) {
canMergeFromLeft(right, left)Description
TRUEnever evaluated
FALSEnever evaluated
0
1235 right->setLeft(left->left());-
1236 updateInnerRect(*right);-
1237 return true;
never executed: return true;
0
1238 }-
1239 return false;
never executed: return false;
0
1240}-
1241-
1242static inline bool canMergeFromBelow(const QRect *top, const QRect *bottom,-
1243 const QRect *nextToTop,-
1244 const QRect *nextToBottom)-
1245{-
1246 if (nextToTop && nextToTop->y() == top->y())
nextToTopDescription
TRUEnever evaluated
FALSEnever evaluated
nextToTop->y() == top->y()Description
TRUEnever evaluated
FALSEnever evaluated
0
1247 return false;
never executed: return false;
0
1248 if (nextToBottom && nextToBottom->y() == bottom->y())
nextToBottomDescription
TRUEnever evaluated
FALSEnever evaluated
nextToBottom->...== bottom->y()Description
TRUEnever evaluated
FALSEnever evaluated
0
1249 return false;
never executed: return false;
0
1250-
1251 return ((top->bottom() >= (bottom->top() - 1))
never executed: return ((top->bottom() >= (bottom->top() - 1)) && top->left() == bottom->left() && top->right() == bottom->right());
0
1252 && top->left() == bottom->left()
never executed: return ((top->bottom() >= (bottom->top() - 1)) && top->left() == bottom->left() && top->right() == bottom->right());
0
1253 && top->right() == bottom->right());
never executed: return ((top->bottom() >= (bottom->top() - 1)) && top->left() == bottom->left() && top->right() == bottom->right());
0
1254}-
1255-
1256bool QRegionPrivate::mergeFromBelow(QRect *top, const QRect *bottom,-
1257 const QRect *nextToTop,-
1258 const QRect *nextToBottom)-
1259{-
1260 if (canMergeFromBelow(top, bottom, nextToTop, nextToBottom)) {
canMergeFromBe... nextToBottom)Description
TRUEnever evaluated
FALSEnever evaluated
0
1261 top->setBottom(bottom->bottom());-
1262 updateInnerRect(*top);-
1263 return true;
never executed: return true;
0
1264 }-
1265 return false;
never executed: return false;
0
1266}-
1267-
1268bool QRegionPrivate::mergeFromAbove(QRect *bottom, const QRect *top,-
1269 const QRect *nextToBottom,-
1270 const QRect *nextToTop)-
1271{-
1272 if (canMergeFromBelow(top, bottom, nextToTop, nextToBottom)) {
canMergeFromBe... nextToBottom)Description
TRUEnever evaluated
FALSEnever evaluated
0
1273 bottom->setTop(top->top());-
1274 updateInnerRect(*bottom);-
1275 return true;
never executed: return true;
0
1276 }-
1277 return false;
never executed: return false;
0
1278}-
1279-
1280static inline QRect qt_rect_intersect_normalized(const QRect &r1,-
1281 const QRect &r2)-
1282{-
1283 QRect r;-
1284 r.setLeft(qMax(r1.left(), r2.left()));-
1285 r.setRight(qMin(r1.right(), r2.right()));-
1286 r.setTop(qMax(r1.top(), r2.top()));-
1287 r.setBottom(qMin(r1.bottom(), r2.bottom()));-
1288 return r;
never executed: return r;
0
1289}-
1290-
1291void QRegionPrivate::intersect(const QRect &rect)-
1292{-
1293 Q_ASSERT(extents.intersects(rect));-
1294 Q_ASSERT(numRects > 1);-
1295-
1296#ifdef QT_REGION_DEBUG-
1297 selfTest();-
1298#endif-
1299-
1300 const QRect r = rect.normalized();-
1301 extents = QRect();-
1302 innerRect = QRect();-
1303 innerArea = -1;-
1304-
1305 QRect *dest = rects.data();-
1306 const QRect *src = dest;-
1307 int n = numRects;-
1308 numRects = 0;-
1309 while (n--) {
n--Description
TRUEnever evaluated
FALSEnever evaluated
0
1310 *dest = qt_rect_intersect_normalized(*src++, r);-
1311 if (dest->isEmpty())
dest->isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
1312 continue;
never executed: continue;
0
1313-
1314 if (numRects == 0) {
numRects == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1315 extents = *dest;-
1316 } else {
never executed: end of block
0
1317 extents.setLeft(qMin(extents.left(), dest->left()));-
1318 // hw: extents.top() will never change after initialization-
1319 //extents.setTop(qMin(extents.top(), dest->top()));-
1320 extents.setRight(qMax(extents.right(), dest->right()));-
1321 extents.setBottom(qMax(extents.bottom(), dest->bottom()));-
1322-
1323 const QRect *nextToLast = (numRects > 1 ? dest - 2 : 0);
numRects > 1Description
TRUEnever evaluated
FALSEnever evaluated
0
1324-
1325 // mergeFromBelow inlined and optimized-
1326 if (canMergeFromBelow(dest - 1, dest, nextToLast, 0)) {
canMergeFromBe...nextToLast, 0)Description
TRUEnever evaluated
FALSEnever evaluated
0
1327 if (!n || src->y() != dest->y() || src->left() > r.right()) {
!nDescription
TRUEnever evaluated
FALSEnever evaluated
src->y() != dest->y()Description
TRUEnever evaluated
FALSEnever evaluated
src->left() > r.right()Description
TRUEnever evaluated
FALSEnever evaluated
0
1328 QRect *prev = dest - 1;-
1329 prev->setBottom(dest->bottom());-
1330 updateInnerRect(*prev);-
1331 continue;
never executed: continue;
0
1332 }-
1333 }
never executed: end of block
0
1334 }
never executed: end of block
0
1335 updateInnerRect(*dest);-
1336 ++dest;-
1337 ++numRects;-
1338 }
never executed: end of block
0
1339#ifdef QT_REGION_DEBUG-
1340 selfTest();-
1341#endif-
1342}
never executed: end of block
0
1343-
1344void QRegionPrivate::append(const QRect *r)-
1345{-
1346 Q_ASSERT(!r->isEmpty());-
1347-
1348 QRect *myLast = (numRects == 1 ? &extents : rects.data() + (numRects - 1));
numRects == 1Description
TRUEnever evaluated
FALSEnever evaluated
0
1349 if (mergeFromRight(myLast, r)) {
mergeFromRight(myLast, r)Description
TRUEnever evaluated
FALSEnever evaluated
0
1350 if (numRects > 1) {
numRects > 1Description
TRUEnever evaluated
FALSEnever evaluated
0
1351 const QRect *nextToTop = (numRects > 2 ? myLast - 2 : 0);
numRects > 2Description
TRUEnever evaluated
FALSEnever evaluated
0
1352 if (mergeFromBelow(myLast - 1, myLast, nextToTop, 0))
mergeFromBelow... nextToTop, 0)Description
TRUEnever evaluated
FALSEnever evaluated
0
1353 --numRects;
never executed: --numRects;
0
1354 }
never executed: end of block
0
1355 } else if (mergeFromBelow(myLast, r, (numRects > 1 ? myLast - 1 : 0), 0)) {
never executed: end of block
mergeFromBelow...t - 1 : 0), 0)Description
TRUEnever evaluated
FALSEnever evaluated
0
1356 // nothing-
1357 } else {
never executed: end of block
0
1358 vectorize();-
1359 ++numRects;-
1360 updateInnerRect(*r);-
1361 if (rects.size() < numRects)
rects.size() < numRectsDescription
TRUEnever evaluated
FALSEnever evaluated
0
1362 rects.resize(numRects);
never executed: rects.resize(numRects);
0
1363 rects[numRects - 1] = *r;-
1364 }
never executed: end of block
0
1365 extents.setCoords(qMin(extents.left(), r->left()),-
1366 qMin(extents.top(), r->top()),-
1367 qMax(extents.right(), r->right()),-
1368 qMax(extents.bottom(), r->bottom()));-
1369-
1370#ifdef QT_REGION_DEBUG-
1371 selfTest();-
1372#endif-
1373}
never executed: end of block
0
1374-
1375void QRegionPrivate::append(const QRegionPrivate *r)-
1376{-
1377 Q_ASSERT(!isEmptyHelper(r));-
1378-
1379 if (r->numRects == 1) {
r->numRects == 1Description
TRUEnever evaluated
FALSEnever evaluated
0
1380 append(&r->extents);-
1381 return;
never executed: return;
0
1382 }-
1383-
1384 vectorize();-
1385-
1386 QRect *destRect = rects.data() + numRects;-
1387 const QRect *srcRect = r->rects.constData();-
1388 int numAppend = r->numRects;-
1389-
1390 // try merging-
1391 {-
1392 const QRect *rFirst = srcRect;-
1393 QRect *myLast = destRect - 1;-
1394 const QRect *nextToLast = (numRects > 1 ? myLast - 1 : 0);
numRects > 1Description
TRUEnever evaluated
FALSEnever evaluated
0
1395 if (mergeFromRight(myLast, rFirst)) {
mergeFromRight(myLast, rFirst)Description
TRUEnever evaluated
FALSEnever evaluated
0
1396 ++srcRect;-
1397 --numAppend;-
1398 const QRect *rNextToFirst = (numAppend > 1 ? rFirst + 2 : 0);
numAppend > 1Description
TRUEnever evaluated
FALSEnever evaluated
0
1399 if (mergeFromBelow(myLast, rFirst + 1, nextToLast, rNextToFirst)) {
mergeFromBelow... rNextToFirst)Description
TRUEnever evaluated
FALSEnever evaluated
0
1400 ++srcRect;-
1401 --numAppend;-
1402 }
never executed: end of block
0
1403 if (numRects > 1) {
numRects > 1Description
TRUEnever evaluated
FALSEnever evaluated
0
1404 nextToLast = (numRects > 2 ? myLast - 2 : 0);
numRects > 2Description
TRUEnever evaluated
FALSEnever evaluated
0
1405 rNextToFirst = (numAppend > 0 ? srcRect : 0);
numAppend > 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1406 if (mergeFromBelow(myLast - 1, myLast, nextToLast, rNextToFirst)) {
mergeFromBelow... rNextToFirst)Description
TRUEnever evaluated
FALSEnever evaluated
0
1407 --destRect;-
1408 --numRects;-
1409 }
never executed: end of block
0
1410 }
never executed: end of block
0
1411 } else if (mergeFromBelow(myLast, rFirst, nextToLast, rFirst + 1)) {
never executed: end of block
mergeFromBelow...t, rFirst + 1)Description
TRUEnever evaluated
FALSEnever evaluated
0
1412 ++srcRect;-
1413 --numAppend;-
1414 }
never executed: end of block
0
1415 }-
1416-
1417 // append rectangles-
1418 if (numAppend > 0) {
numAppend > 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1419 const int newNumRects = numRects + numAppend;-
1420 if (newNumRects > rects.size()) {
newNumRects > rects.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
1421 rects.resize(newNumRects);-
1422 destRect = rects.data() + numRects;-
1423 }
never executed: end of block
0
1424 memcpy(destRect, srcRect, numAppend * sizeof(QRect));-
1425-
1426 numRects = newNumRects;-
1427 }
never executed: end of block
0
1428-
1429 // update inner rectangle-
1430 if (innerArea < r->innerArea) {
innerArea < r->innerAreaDescription
TRUEnever evaluated
FALSEnever evaluated
0
1431 innerArea = r->innerArea;-
1432 innerRect = r->innerRect;-
1433 }
never executed: end of block
0
1434-
1435 // update extents-
1436 destRect = &extents;-
1437 srcRect = &r->extents;-
1438 extents.setCoords(qMin(destRect->left(), srcRect->left()),-
1439 qMin(destRect->top(), srcRect->top()),-
1440 qMax(destRect->right(), srcRect->right()),-
1441 qMax(destRect->bottom(), srcRect->bottom()));-
1442-
1443#ifdef QT_REGION_DEBUG-
1444 selfTest();-
1445#endif-
1446}
never executed: end of block
0
1447-
1448void QRegionPrivate::prepend(const QRegionPrivate *r)-
1449{-
1450 Q_ASSERT(!isEmptyHelper(r));-
1451-
1452 if (r->numRects == 1) {
r->numRects == 1Description
TRUEnever evaluated
FALSEnever evaluated
0
1453 prepend(&r->extents);-
1454 return;
never executed: return;
0
1455 }-
1456-
1457 vectorize();-
1458-
1459 int numPrepend = r->numRects;-
1460 int numSkip = 0;-
1461-
1462 // try merging-
1463 {-
1464 QRect *myFirst = rects.data();-
1465 const QRect *nextToFirst = (numRects > 1 ? myFirst + 1 : 0);
numRects > 1Description
TRUEnever evaluated
FALSEnever evaluated
0
1466 const QRect *rLast = r->rects.constData() + r->numRects - 1;-
1467 const QRect *rNextToLast = (r->numRects > 1 ? rLast - 1 : 0);
r->numRects > 1Description
TRUEnever evaluated
FALSEnever evaluated
0
1468 if (mergeFromLeft(myFirst, rLast)) {
mergeFromLeft(myFirst, rLast)Description
TRUEnever evaluated
FALSEnever evaluated
0
1469 --numPrepend;-
1470 --rLast;-
1471 rNextToLast = (numPrepend > 1 ? rLast - 1 : 0);
numPrepend > 1Description
TRUEnever evaluated
FALSEnever evaluated
0
1472 if (mergeFromAbove(myFirst, rLast, nextToFirst, rNextToLast)) {
mergeFromAbove..., rNextToLast)Description
TRUEnever evaluated
FALSEnever evaluated
0
1473 --numPrepend;-
1474 --rLast;-
1475 }
never executed: end of block
0
1476 if (numRects > 1) {
numRects > 1Description
TRUEnever evaluated
FALSEnever evaluated
0
1477 nextToFirst = (numRects > 2? myFirst + 2 : 0);
numRects > 2Description
TRUEnever evaluated
FALSEnever evaluated
0
1478 rNextToLast = (numPrepend > 0 ? rLast : 0);
numPrepend > 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1479 if (mergeFromAbove(myFirst + 1, myFirst, nextToFirst, rNextToLast)) {
mergeFromAbove..., rNextToLast)Description
TRUEnever evaluated
FALSEnever evaluated
0
1480 --numRects;-
1481 ++numSkip;-
1482 }
never executed: end of block
0
1483 }
never executed: end of block
0
1484 } else if (mergeFromAbove(myFirst, rLast, nextToFirst, rNextToLast)) {
never executed: end of block
mergeFromAbove..., rNextToLast)Description
TRUEnever evaluated
FALSEnever evaluated
0
1485 --numPrepend;-
1486 }
never executed: end of block
0
1487 }-
1488-
1489 if (numPrepend > 0) {
numPrepend > 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1490 const int newNumRects = numRects + numPrepend;-
1491 if (newNumRects > rects.size())
newNumRects > rects.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
1492 rects.resize(newNumRects);
never executed: rects.resize(newNumRects);
0
1493-
1494 // move existing rectangles-
1495 memmove(rects.data() + numPrepend, rects.constData() + numSkip,-
1496 numRects * sizeof(QRect));-
1497-
1498 // prepend new rectangles-
1499 memcpy(rects.data(), r->rects.constData(), numPrepend * sizeof(QRect));-
1500-
1501 numRects = newNumRects;-
1502 }
never executed: end of block
0
1503-
1504 // update inner rectangle-
1505 if (innerArea < r->innerArea) {
innerArea < r->innerAreaDescription
TRUEnever evaluated
FALSEnever evaluated
0
1506 innerArea = r->innerArea;-
1507 innerRect = r->innerRect;-
1508 }
never executed: end of block
0
1509-
1510 // update extents-
1511 extents.setCoords(qMin(extents.left(), r->extents.left()),-
1512 qMin(extents.top(), r->extents.top()),-
1513 qMax(extents.right(), r->extents.right()),-
1514 qMax(extents.bottom(), r->extents.bottom()));-
1515-
1516#ifdef QT_REGION_DEBUG-
1517 selfTest();-
1518#endif-
1519}
never executed: end of block
0
1520-
1521void QRegionPrivate::prepend(const QRect *r)-
1522{-
1523 Q_ASSERT(!r->isEmpty());-
1524-
1525 QRect *myFirst = (numRects == 1 ? &extents : rects.data());
numRects == 1Description
TRUEnever evaluated
FALSEnever evaluated
0
1526 if (mergeFromLeft(myFirst, r)) {
mergeFromLeft(myFirst, r)Description
TRUEnever evaluated
FALSEnever evaluated
0
1527 if (numRects > 1) {
numRects > 1Description
TRUEnever evaluated
FALSEnever evaluated
0
1528 const QRect *nextToFirst = (numRects > 2 ? myFirst + 2 : 0);
numRects > 2Description
TRUEnever evaluated
FALSEnever evaluated
0
1529 if (mergeFromAbove(myFirst + 1, myFirst, nextToFirst, 0)) {
mergeFromAbove...extToFirst, 0)Description
TRUEnever evaluated
FALSEnever evaluated
0
1530 --numRects;-
1531 memmove(rects.data(), rects.constData() + 1,-
1532 numRects * sizeof(QRect));-
1533 }
never executed: end of block
0
1534 }
never executed: end of block
0
1535 } else if (mergeFromAbove(myFirst, r, (numRects > 1 ? myFirst + 1 : 0), 0)) {
never executed: end of block
mergeFromAbove...t + 1 : 0), 0)Description
TRUEnever evaluated
FALSEnever evaluated
0
1536 // nothing-
1537 } else {
never executed: end of block
0
1538 vectorize();-
1539 ++numRects;-
1540 updateInnerRect(*r);-
1541 rects.prepend(*r);-
1542 }
never executed: end of block
0
1543 extents.setCoords(qMin(extents.left(), r->left()),-
1544 qMin(extents.top(), r->top()),-
1545 qMax(extents.right(), r->right()),-
1546 qMax(extents.bottom(), r->bottom()));-
1547-
1548#ifdef QT_REGION_DEBUG-
1549 selfTest();-
1550#endif-
1551}
never executed: end of block
0
1552-
1553bool QRegionPrivate::canAppend(const QRect *r) const-
1554{-
1555 Q_ASSERT(!r->isEmpty());-
1556-
1557 const QRect *myLast = (numRects == 1) ? &extents : (rects.constData() + (numRects - 1));
(numRects == 1)Description
TRUEnever evaluated
FALSEnever evaluated
0
1558 if (r->top() > myLast->bottom())
r->top() > myLast->bottom()Description
TRUEnever evaluated
FALSEnever evaluated
0
1559 return true;
never executed: return true;
0
1560 if (r->top() == myLast->top()
r->top() == myLast->top()Description
TRUEnever evaluated
FALSEnever evaluated
0
1561 && r->height() == myLast->height()
r->height() ==...Last->height()Description
TRUEnever evaluated
FALSEnever evaluated
0
1562 && r->left() > myLast->right())
r->left() > myLast->right()Description
TRUEnever evaluated
FALSEnever evaluated
0
1563 {-
1564 return true;
never executed: return true;
0
1565 }-
1566-
1567 return false;
never executed: return false;
0
1568}-
1569-
1570bool QRegionPrivate::canAppend(const QRegionPrivate *r) const-
1571{-
1572 return canAppend(r->numRects == 1 ? &r->extents : r->rects.constData());
never executed: return canAppend(r->numRects == 1 ? &r->extents : r->rects.constData());
0
1573}-
1574-
1575bool QRegionPrivate::canPrepend(const QRect *r) const-
1576{-
1577 Q_ASSERT(!r->isEmpty());-
1578-
1579 const QRect *myFirst = (numRects == 1) ? &extents : rects.constData();
(numRects == 1)Description
TRUEnever evaluated
FALSEnever evaluated
0
1580 if (r->bottom() < myFirst->top()) // not overlapping
r->bottom() < myFirst->top()Description
TRUEnever evaluated
FALSEnever evaluated
0
1581 return true;
never executed: return true;
0
1582 if (r->top() == myFirst->top()
r->top() == myFirst->top()Description
TRUEnever evaluated
FALSEnever evaluated
0
1583 && r->height() == myFirst->height()
r->height() ==...irst->height()Description
TRUEnever evaluated
FALSEnever evaluated
0
1584 && r->right() < myFirst->left())
r->right() < myFirst->left()Description
TRUEnever evaluated
FALSEnever evaluated
0
1585 {-
1586 return true;
never executed: return true;
0
1587 }-
1588-
1589 return false;
never executed: return false;
0
1590}-
1591-
1592bool QRegionPrivate::canPrepend(const QRegionPrivate *r) const-
1593{-
1594 return canPrepend(r->numRects == 1 ? &r->extents : r->rects.constData() + r->numRects - 1);
never executed: return canPrepend(r->numRects == 1 ? &r->extents : r->rects.constData() + r->numRects - 1);
0
1595}-
1596-
1597#ifdef QT_REGION_DEBUG-
1598void QRegionPrivate::selfTest() const-
1599{-
1600 if (numRects == 0) {-
1601 Q_ASSERT(extents.isEmpty());-
1602 Q_ASSERT(innerRect.isEmpty());-
1603 return;-
1604 }-
1605-
1606 Q_ASSERT(innerArea == (innerRect.width() * innerRect.height()));-
1607-
1608 if (numRects == 1) {-
1609 Q_ASSERT(innerRect == extents);-
1610 Q_ASSERT(!innerRect.isEmpty());-
1611 return;-
1612 }-
1613-
1614 for (int i = 0; i < numRects; ++i) {-
1615 const QRect r = rects.at(i);-
1616 if ((r.width() * r.height()) > innerArea)-
1617 qDebug() << "selfTest(): innerRect" << innerRect << '<' << r;-
1618 }-
1619-
1620 QRect r = rects.first();-
1621 for (int i = 1; i < numRects; ++i) {-
1622 const QRect r2 = rects.at(i);-
1623 Q_ASSERT(!r2.isEmpty());-
1624 if (r2.y() == r.y()) {-
1625 Q_ASSERT(r.bottom() == r2.bottom());-
1626 Q_ASSERT(r.right() < (r2.left() + 1));-
1627 } else {-
1628 Q_ASSERT(r2.y() >= r.bottom());-
1629 }-
1630 r = r2;-
1631 }-
1632}-
1633#endif // QT_REGION_DEBUG-
1634-
1635static QRegionPrivate qrp;-
1636const QRegion::QRegionData QRegion::shared_empty = {Q_REFCOUNT_INITIALIZE_STATIC, &qrp};-
1637-
1638typedef void (*OverlapFunc)(QRegionPrivate &dest, const QRect *r1, const QRect *r1End,-
1639 const QRect *r2, const QRect *r2End, int y1, int y2);-
1640typedef void (*NonOverlapFunc)(QRegionPrivate &dest, const QRect *r, const QRect *rEnd,-
1641 int y1, int y2);-
1642-
1643static bool EqualRegion(const QRegionPrivate *r1, const QRegionPrivate *r2);-
1644static void UnionRegion(const QRegionPrivate *reg1, const QRegionPrivate *reg2, QRegionPrivate &dest);-
1645static void miRegionOp(QRegionPrivate &dest, const QRegionPrivate *reg1, const QRegionPrivate *reg2,-
1646 OverlapFunc overlapFunc, NonOverlapFunc nonOverlap1Func,-
1647 NonOverlapFunc nonOverlap2Func);-
1648-
1649#define RectangleOut 0-
1650#define RectangleIn 1-
1651#define RectanglePart 2-
1652#define EvenOddRule 0-
1653#define WindingRule 1-
1654-
1655// START OF region.h extract-
1656/* $XConsortium: region.h,v 11.14 94/04/17 20:22:20 rws Exp $ */-
1657/************************************************************************-
1658-
1659Copyright (c) 1987 X Consortium-
1660-
1661Permission is hereby granted, free of charge, to any person obtaining a copy-
1662of this software and associated documentation files (the "Software"), to deal-
1663in the Software without restriction, including without limitation the rights-
1664to use, copy, modify, merge, publish, distribute, sublicense, and/or sell-
1665copies of the Software, and to permit persons to whom the Software is-
1666furnished to do so, subject to the following conditions:-
1667-
1668The above copyright notice and this permission notice shall be included in-
1669all copies or substantial portions of the Software.-
1670-
1671THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR-
1672IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,-
1673FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE-
1674X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN-
1675AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN-
1676CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.-
1677-
1678Except as contained in this notice, the name of the X Consortium shall not be-
1679used in advertising or otherwise to promote the sale, use or other dealings-
1680in this Software without prior written authorization from the X Consortium.-
1681-
1682-
1683Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.-
1684-
1685 All Rights Reserved-
1686-
1687Permission to use, copy, modify, and distribute this software and its-
1688documentation for any purpose and without fee is hereby granted,-
1689provided that the above copyright notice appear in all copies and that-
1690both that copyright notice and this permission notice appear in-
1691supporting documentation, and that the name of Digital not be-
1692used in advertising or publicity pertaining to distribution of the-
1693software without specific, written prior permission.-
1694-
1695DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING-
1696ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL-
1697DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR-
1698ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,-
1699WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,-
1700ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS-
1701SOFTWARE.-
1702-
1703************************************************************************/-
1704-
1705#ifndef _XREGION_H-
1706#define _XREGION_H-
1707-
1708QT_BEGIN_INCLUDE_NAMESPACE-
1709#include <limits.h>-
1710QT_END_INCLUDE_NAMESPACE-
1711-
1712/* 1 if two BOXes overlap.-
1713 * 0 if two BOXes do not overlap.-
1714 * Remember, x2 and y2 are not in the region-
1715 */-
1716#define EXTENTCHECK(r1, r2) \-
1717 ((r1)->right() >= (r2)->left() && \-
1718 (r1)->left() <= (r2)->right() && \-
1719 (r1)->bottom() >= (r2)->top() && \-
1720 (r1)->top() <= (r2)->bottom())-
1721-
1722/*-
1723 * update region extents-
1724 */-
1725#define EXTENTS(r,idRect){\-
1726 if((r)->left() < (idRect)->extents.left())\-
1727 (idRect)->extents.setLeft((r)->left());\-
1728 if((r)->top() < (idRect)->extents.top())\-
1729 (idRect)->extents.setTop((r)->top());\-
1730 if((r)->right() > (idRect)->extents.right())\-
1731 (idRect)->extents.setRight((r)->right());\-
1732 if((r)->bottom() > (idRect)->extents.bottom())\-
1733 (idRect)->extents.setBottom((r)->bottom());\-
1734 }-
1735-
1736/*-
1737 * Check to see if there is enough memory in the present region.-
1738 */-
1739#define MEMCHECK(dest, rect, firstrect){\-
1740 if ((dest).numRects >= ((dest).rects.size()-1)){\-
1741 firstrect.resize(firstrect.size() * 2); \-
1742 (rect) = (firstrect).data() + (dest).numRects;\-
1743 }\-
1744 }-
1745-
1746-
1747/*-
1748 * number of points to buffer before sending them off-
1749 * to scanlines(): Must be an even number-
1750 */-
1751#define NUMPTSTOBUFFER 200-
1752-
1753/*-
1754 * used to allocate buffers for points and link-
1755 * the buffers together-
1756 */-
1757typedef struct _POINTBLOCK {-
1758 char data[NUMPTSTOBUFFER * sizeof(QPoint)];-
1759 QPoint *pts;-
1760 struct _POINTBLOCK *next;-
1761} POINTBLOCK;-
1762-
1763#endif-
1764// END OF region.h extract-
1765-
1766// START OF Region.c extract-
1767/* $XConsortium: Region.c /main/30 1996/10/22 14:21:24 kaleb $ */-
1768/************************************************************************-
1769-
1770Copyright (c) 1987, 1988 X Consortium-
1771-
1772Permission is hereby granted, free of charge, to any person obtaining a copy-
1773of this software and associated documentation files (the "Software"), to deal-
1774in the Software without restriction, including without limitation the rights-
1775to use, copy, modify, merge, publish, distribute, sublicense, and/or sell-
1776copies of the Software, and to permit persons to whom the Software is-
1777furnished to do so, subject to the following conditions:-
1778-
1779The above copyright notice and this permission notice shall be included in-
1780all copies or substantial portions of the Software.-
1781-
1782THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR-
1783IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,-
1784FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE-
1785X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN-
1786AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN-
1787CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.-
1788-
1789Except as contained in this notice, the name of the X Consortium shall not be-
1790used in advertising or otherwise to promote the sale, use or other dealings-
1791in this Software without prior written authorization from the X Consortium.-
1792-
1793-
1794Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.-
1795-
1796 All Rights Reserved-
1797-
1798Permission to use, copy, modify, and distribute this software and its-
1799documentation for any purpose and without fee is hereby granted,-
1800provided that the above copyright notice appear in all copies and that-
1801both that copyright notice and this permission notice appear in-
1802supporting documentation, and that the name of Digital not be-
1803used in advertising or publicity pertaining to distribution of the-
1804software without specific, written prior permission.-
1805-
1806DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING-
1807ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL-
1808DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR-
1809ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,-
1810WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,-
1811ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS-
1812SOFTWARE.-
1813-
1814************************************************************************/-
1815/*-
1816 * The functions in this file implement the Region abstraction, similar to one-
1817 * used in the X11 sample server. A Region is simply an area, as the name-
1818 * implies, and is implemented as a "y-x-banded" array of rectangles. To-
1819 * explain: Each Region is made up of a certain number of rectangles sorted-
1820 * by y coordinate first, and then by x coordinate.-
1821 *-
1822 * Furthermore, the rectangles are banded such that every rectangle with a-
1823 * given upper-left y coordinate (y1) will have the same lower-right y-
1824 * coordinate (y2) and vice versa. If a rectangle has scanlines in a band, it-
1825 * will span the entire vertical distance of the band. This means that some-
1826 * areas that could be merged into a taller rectangle will be represented as-
1827 * several shorter rectangles to account for shorter rectangles to its left-
1828 * or right but within its "vertical scope".-
1829 *-
1830 * An added constraint on the rectangles is that they must cover as much-
1831 * horizontal area as possible. E.g. no two rectangles in a band are allowed-
1832 * to touch.-
1833 *-
1834 * Whenever possible, bands will be merged together to cover a greater vertical-
1835 * distance (and thus reduce the number of rectangles). Two bands can be merged-
1836 * only if the bottom of one touches the top of the other and they have-
1837 * rectangles in the same places (of the same width, of course). This maintains-
1838 * the y-x-banding that's so nice to have...-
1839 */-
1840/* $XFree86: xc/lib/X11/Region.c,v 1.1.1.2.2.2 1998/10/04 15:22:50 hohndel Exp $ */-
1841-
1842static void UnionRectWithRegion(const QRect *rect, const QRegionPrivate *source,-
1843 QRegionPrivate &dest)-
1844{-
1845 if (rect->isEmpty())
rect->isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
1846 return;
never executed: return;
0
1847-
1848 Q_ASSERT(EqualRegion(source, &dest));-
1849-
1850 if (dest.numRects == 0) {
dest.numRects == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1851 dest = QRegionPrivate(*rect);-
1852 } else if (dest.canAppend(rect)) {
never executed: end of block
dest.canAppend(rect)Description
TRUEnever evaluated
FALSEnever evaluated
0
1853 dest.append(rect);-
1854 } else {
never executed: end of block
0
1855 QRegionPrivate p(*rect);-
1856 UnionRegion(&p, source, dest);-
1857 }
never executed: end of block
0
1858}-
1859-
1860/*--
1861 *------------------------------------------------------------------------
1862 * miSetExtents ---
1863 * Reset the extents and innerRect of a region to what they should be.-
1864 * Called by miSubtract and miIntersect b/c they can't figure it out-
1865 * along the way or do so easily, as miUnion can.-
1866 *-
1867 * Results:-
1868 * None.-
1869 *-
1870 * Side Effects:-
1871 * The region's 'extents' and 'innerRect' structure is overwritten.-
1872 *-
1873 *------------------------------------------------------------------------
1874 */-
1875static void miSetExtents(QRegionPrivate &dest)-
1876{-
1877 const QRect *pBox,-
1878 *pBoxEnd;-
1879 QRect *pExtents;-
1880-
1881 dest.innerRect.setCoords(0, 0, -1, -1);-
1882 dest.innerArea = -1;-
1883 if (dest.numRects == 0) {
dest.numRects == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1884 dest.extents.setCoords(0, 0, -1, -1);-
1885 return;
never executed: return;
0
1886 }-
1887-
1888 pExtents = &dest.extents;-
1889 if (dest.rects.isEmpty())
dest.rects.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
1890 pBox = &dest.extents;
never executed: pBox = &dest.extents;
0
1891 else-
1892 pBox = dest.rects.constData();
never executed: pBox = dest.rects.constData();
0
1893 pBoxEnd = pBox + dest.numRects - 1;-
1894-
1895 /*-
1896 * Since pBox is the first rectangle in the region, it must have the-
1897 * smallest y1 and since pBoxEnd is the last rectangle in the region,-
1898 * it must have the largest y2, because of banding. Initialize x1 and-
1899 * x2 from pBox and pBoxEnd, resp., as good things to initialize them-
1900 * to...-
1901 */-
1902 pExtents->setLeft(pBox->left());-
1903 pExtents->setTop(pBox->top());-
1904 pExtents->setRight(pBoxEnd->right());-
1905 pExtents->setBottom(pBoxEnd->bottom());-
1906-
1907 Q_ASSERT(pExtents->top() <= pExtents->bottom());-
1908 while (pBox <= pBoxEnd) {
pBox <= pBoxEndDescription
TRUEnever evaluated
FALSEnever evaluated
0
1909 if (pBox->left() < pExtents->left())
pBox->left() <...xtents->left()Description
TRUEnever evaluated
FALSEnever evaluated
0
1910 pExtents->setLeft(pBox->left());
never executed: pExtents->setLeft(pBox->left());
0
1911 if (pBox->right() > pExtents->right())
pBox->right() ...tents->right()Description
TRUEnever evaluated
FALSEnever evaluated
0
1912 pExtents->setRight(pBox->right());
never executed: pExtents->setRight(pBox->right());
0
1913 dest.updateInnerRect(*pBox);-
1914 ++pBox;-
1915 }
never executed: end of block
0
1916 Q_ASSERT(pExtents->left() <= pExtents->right());-
1917}
never executed: end of block
0
1918-
1919/* TranslateRegion(pRegion, x, y)-
1920 translates in place-
1921 added by raymond-
1922*/-
1923-
1924static void OffsetRegion(QRegionPrivate &region, int x, int y)-
1925{-
1926 if (region.rects.size()) {
region.rects.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
1927 QRect *pbox = region.rects.data();-
1928 int nbox = region.numRects;-
1929-
1930 while (nbox--) {
nbox--Description
TRUEnever evaluated
FALSEnever evaluated
0
1931 pbox->translate(x, y);-
1932 ++pbox;-
1933 }
never executed: end of block
0
1934 }
never executed: end of block
0
1935 region.extents.translate(x, y);-
1936 region.innerRect.translate(x, y);-
1937}
never executed: end of block
0
1938-
1939/*======================================================================-
1940 * Region Intersection-
1941 *====================================================================*/-
1942/*--
1943 *------------------------------------------------------------------------
1944 * miIntersectO ---
1945 * Handle an overlapping band for miIntersect.-
1946 *-
1947 * Results:-
1948 * None.-
1949 *-
1950 * Side Effects:-
1951 * Rectangles may be added to the region.-
1952 *-
1953 *------------------------------------------------------------------------
1954 */-
1955static void miIntersectO(QRegionPrivate &dest, const QRect *r1, const QRect *r1End,-
1956 const QRect *r2, const QRect *r2End, int y1, int y2)-
1957{-
1958 int x1;-
1959 int x2;-
1960 QRect *pNextRect;-
1961-
1962 pNextRect = dest.rects.data() + dest.numRects;-
1963-
1964 while (r1 != r1End && r2 != r2End) {
r1 != r1EndDescription
TRUEnever evaluated
FALSEnever evaluated
r2 != r2EndDescription
TRUEnever evaluated
FALSEnever evaluated
0
1965 x1 = qMax(r1->left(), r2->left());-
1966 x2 = qMin(r1->right(), r2->right());-
1967-
1968 /*-
1969 * If there's any overlap between the two rectangles, add that-
1970 * overlap to the new region.-
1971 * There's no need to check for subsumption because the only way-
1972 * such a need could arise is if some region has two rectangles-
1973 * right next to each other. Since that should never happen...-
1974 */-
1975 if (x1 <= x2) {
x1 <= x2Description
TRUEnever evaluated
FALSEnever evaluated
0
1976 Q_ASSERT(y1 <= y2);-
1977 MEMCHECK(dest, pNextRect, dest.rects)
never executed: end of block
(dest).numRect...ects.size()-1)Description
TRUEnever evaluated
FALSEnever evaluated
0
1978 pNextRect->setCoords(x1, y1, x2, y2);-
1979 ++dest.numRects;-
1980 ++pNextRect;-
1981 }
never executed: end of block
0
1982-
1983 /*-
1984 * Need to advance the pointers. Shift the one that extends-
1985 * to the right the least, since the other still has a chance to-
1986 * overlap with that region's next rectangle, if you see what I mean.-
1987 */-
1988 if (r1->right() < r2->right()) {
r1->right() < r2->right()Description
TRUEnever evaluated
FALSEnever evaluated
0
1989 ++r1;-
1990 } else if (r2->right() < r1->right()) {
never executed: end of block
r2->right() < r1->right()Description
TRUEnever evaluated
FALSEnever evaluated
0
1991 ++r2;-
1992 } else {
never executed: end of block
0
1993 ++r1;-
1994 ++r2;-
1995 }
never executed: end of block
0
1996 }-
1997}
never executed: end of block
0
1998-
1999/*======================================================================-
2000 * Generic Region Operator-
2001 *====================================================================*/-
2002-
2003/*--
2004 *------------------------------------------------------------------------
2005 * miCoalesce ---
2006 * Attempt to merge the boxes in the current band with those in the-
2007 * previous one. Used only by miRegionOp.-
2008 *-
2009 * Results:-
2010 * The new index for the previous band.-
2011 *-
2012 * Side Effects:-
2013 * If coalescing takes place:-
2014 * - rectangles in the previous band will have their y2 fields-
2015 * altered.-
2016 * - dest.numRects will be decreased.-
2017 *-
2018 *------------------------------------------------------------------------
2019 */-
2020static int miCoalesce(QRegionPrivate &dest, int prevStart, int curStart)-
2021{-
2022 QRect *pPrevBox; /* Current box in previous band */-
2023 QRect *pCurBox; /* Current box in current band */-
2024 QRect *pRegEnd; /* End of region */-
2025 int curNumRects; /* Number of rectangles in current band */-
2026 int prevNumRects; /* Number of rectangles in previous band */-
2027 int bandY1; /* Y1 coordinate for current band */-
2028 QRect *rData = dest.rects.data();-
2029-
2030 pRegEnd = rData + dest.numRects;-
2031-
2032 pPrevBox = rData + prevStart;-
2033 prevNumRects = curStart - prevStart;-
2034-
2035 /*-
2036 * Figure out how many rectangles are in the current band. Have to do-
2037 * this because multiple bands could have been added in miRegionOp-
2038 * at the end when one region has been exhausted.-
2039 */-
2040 pCurBox = rData + curStart;-
2041 bandY1 = pCurBox->top();-
2042 for (curNumRects = 0; pCurBox != pRegEnd && pCurBox->top() == bandY1; ++curNumRects) {
pCurBox != pRegEndDescription
TRUEnever evaluated
FALSEnever evaluated
pCurBox->top() == bandY1Description
TRUEnever evaluated
FALSEnever evaluated
0
2043 ++pCurBox;-
2044 }
never executed: end of block
0
2045-
2046 if (pCurBox != pRegEnd) {
pCurBox != pRegEndDescription
TRUEnever evaluated
FALSEnever evaluated
0
2047 /*-
2048 * If more than one band was added, we have to find the start-
2049 * of the last band added so the next coalescing job can start-
2050 * at the right place... (given when multiple bands are added,-
2051 * this may be pointless -- see above).-
2052 */-
2053 --pRegEnd;-
2054 while ((pRegEnd - 1)->top() == pRegEnd->top())
(pRegEnd - 1)-...pRegEnd->top()Description
TRUEnever evaluated
FALSEnever evaluated
0
2055 --pRegEnd;
never executed: --pRegEnd;
0
2056 curStart = pRegEnd - rData;-
2057 pRegEnd = rData + dest.numRects;-
2058 }
never executed: end of block
0
2059-
2060 if (curNumRects == prevNumRects && curNumRects != 0) {
curNumRects == prevNumRectsDescription
TRUEnever evaluated
FALSEnever evaluated
curNumRects != 0Description
TRUEnever evaluated
FALSEnever evaluated
0
2061 pCurBox -= curNumRects;-
2062 /*-
2063 * The bands may only be coalesced if the bottom of the previous-
2064 * matches the top scanline of the current.-
2065 */-
2066 if (pPrevBox->bottom() == pCurBox->top() - 1) {
pPrevBox->bott...Box->top() - 1Description
TRUEnever evaluated
FALSEnever evaluated
0
2067 /*-
2068 * Make sure the bands have boxes in the same places. This-
2069 * assumes that boxes have been added in such a way that they-
2070 * cover the most area possible. I.e. two boxes in a band must-
2071 * have some horizontal space between them.-
2072 */-
2073 do {-
2074 if (pPrevBox->left() != pCurBox->left() || pPrevBox->right() != pCurBox->right()) {
pPrevBox->left...CurBox->left()Description
TRUEnever evaluated
FALSEnever evaluated
pPrevBox->righ...urBox->right()Description
TRUEnever evaluated
FALSEnever evaluated
0
2075 // The bands don't line up so they can't be coalesced.-
2076 return curStart;
never executed: return curStart;
0
2077 }-
2078 ++pPrevBox;-
2079 ++pCurBox;-
2080 --prevNumRects;-
2081 } while (prevNumRects != 0);
never executed: end of block
prevNumRects != 0Description
TRUEnever evaluated
FALSEnever evaluated
0
2082-
2083 dest.numRects -= curNumRects;-
2084 pCurBox -= curNumRects;-
2085 pPrevBox -= curNumRects;-
2086-
2087 /*-
2088 * The bands may be merged, so set the bottom y of each box-
2089 * in the previous band to that of the corresponding box in-
2090 * the current band.-
2091 */-
2092 do {-
2093 pPrevBox->setBottom(pCurBox->bottom());-
2094 dest.updateInnerRect(*pPrevBox);-
2095 ++pPrevBox;-
2096 ++pCurBox;-
2097 curNumRects -= 1;-
2098 } while (curNumRects != 0);
never executed: end of block
curNumRects != 0Description
TRUEnever evaluated
FALSEnever evaluated
0
2099-
2100 /*-
2101 * If only one band was added to the region, we have to backup-
2102 * curStart to the start of the previous band.-
2103 *-
2104 * If more than one band was added to the region, copy the-
2105 * other bands down. The assumption here is that the other bands-
2106 * came from the same region as the current one and no further-
2107 * coalescing can be done on them since it's all been done-
2108 * already... curStart is already in the right place.-
2109 */-
2110 if (pCurBox == pRegEnd) {
pCurBox == pRegEndDescription
TRUEnever evaluated
FALSEnever evaluated
0
2111 curStart = prevStart;-
2112 } else {
never executed: end of block
0
2113 do {-
2114 *pPrevBox++ = *pCurBox++;-
2115 dest.updateInnerRect(*pPrevBox);-
2116 } while (pCurBox != pRegEnd);
never executed: end of block
pCurBox != pRegEndDescription
TRUEnever evaluated
FALSEnever evaluated
0
2117 }
never executed: end of block
0
2118 }-
2119 }
never executed: end of block
0
2120 return curStart;
never executed: return curStart;
0
2121}-
2122-
2123/*--
2124 *------------------------------------------------------------------------
2125 * miRegionOp ---
2126 * Apply an operation to two regions. Called by miUnion, miInverse,-
2127 * miSubtract, miIntersect...-
2128 *-
2129 * Results:-
2130 * None.-
2131 *-
2132 * Side Effects:-
2133 * The new region is overwritten.-
2134 *-
2135 * Notes:-
2136 * The idea behind this function is to view the two regions as sets.-
2137 * Together they cover a rectangle of area that this function divides-
2138 * into horizontal bands where points are covered only by one region-
2139 * or by both. For the first case, the nonOverlapFunc is called with-
2140 * each the band and the band's upper and lower extents. For the-
2141 * second, the overlapFunc is called to process the entire band. It-
2142 * is responsible for clipping the rectangles in the band, though-
2143 * this function provides the boundaries.-
2144 * At the end of each band, the new region is coalesced, if possible,-
2145 * to reduce the number of rectangles in the region.-
2146 *-
2147 *------------------------------------------------------------------------
2148 */-
2149static void miRegionOp(QRegionPrivate &dest,-
2150 const QRegionPrivate *reg1, const QRegionPrivate *reg2,-
2151 OverlapFunc overlapFunc, NonOverlapFunc nonOverlap1Func,-
2152 NonOverlapFunc nonOverlap2Func)-
2153{-
2154 const QRect *r1; // Pointer into first region-
2155 const QRect *r2; // Pointer into 2d region-
2156 const QRect *r1End; // End of 1st region-
2157 const QRect *r2End; // End of 2d region-
2158 int ybot; // Bottom of intersection-
2159 int ytop; // Top of intersection-
2160 int prevBand; // Index of start of previous band in dest-
2161 int curBand; // Index of start of current band in dest-
2162 const QRect *r1BandEnd; // End of current band in r1-
2163 const QRect *r2BandEnd; // End of current band in r2-
2164 int top; // Top of non-overlapping band-
2165 int bot; // Bottom of non-overlapping band-
2166-
2167 /*-
2168 * Initialization:-
2169 * set r1, r2, r1End and r2End appropriately, preserve the important-
2170 * parts of the destination region until the end in case it's one of-
2171 * the two source regions, then mark the "new" region empty, allocating-
2172 * another array of rectangles for it to use.-
2173 */-
2174 if (reg1->numRects == 1)
reg1->numRects == 1Description
TRUEnever evaluated
FALSEnever evaluated
0
2175 r1 = &reg1->extents;
never executed: r1 = &reg1->extents;
0
2176 else-
2177 r1 = reg1->rects.constData();
never executed: r1 = reg1->rects.constData();
0
2178 if (reg2->numRects == 1)
reg2->numRects == 1Description
TRUEnever evaluated
FALSEnever evaluated
0
2179 r2 = &reg2->extents;
never executed: r2 = &reg2->extents;
0
2180 else-
2181 r2 = reg2->rects.constData();
never executed: r2 = reg2->rects.constData();
0
2182-
2183 r1End = r1 + reg1->numRects;-
2184 r2End = r2 + reg2->numRects;-
2185-
2186 dest.vectorize();-
2187-
2188 QVector<QRect> oldRects = dest.rects;-
2189-
2190 dest.numRects = 0;-
2191-
2192 /*-
2193 * Allocate a reasonable number of rectangles for the new region. The idea-
2194 * is to allocate enough so the individual functions don't need to-
2195 * reallocate and copy the array, which is time consuming, yet we don't-
2196 * have to worry about using too much memory. I hope to be able to-
2197 * nuke the realloc() at the end of this function eventually.-
2198 */-
2199 dest.rects.resize(qMax(reg1->numRects,reg2->numRects) * 2);-
2200-
2201 /*-
2202 * Initialize ybot and ytop.-
2203 * In the upcoming loop, ybot and ytop serve different functions depending-
2204 * on whether the band being handled is an overlapping or non-overlapping-
2205 * band.-
2206 * In the case of a non-overlapping band (only one of the regions-
2207 * has points in the band), ybot is the bottom of the most recent-
2208 * intersection and thus clips the top of the rectangles in that band.-
2209 * ytop is the top of the next intersection between the two regions and-
2210 * serves to clip the bottom of the rectangles in the current band.-
2211 * For an overlapping band (where the two regions intersect), ytop clips-
2212 * the top of the rectangles of both regions and ybot clips the bottoms.-
2213 */-
2214 if (reg1->extents.top() < reg2->extents.top())
reg1->extents....>extents.top()Description
TRUEnever evaluated
FALSEnever evaluated
0
2215 ybot = reg1->extents.top() - 1;
never executed: ybot = reg1->extents.top() - 1;
0
2216 else-
2217 ybot = reg2->extents.top() - 1;
never executed: ybot = reg2->extents.top() - 1;
0
2218-
2219 /*-
2220 * prevBand serves to mark the start of the previous band so rectangles-
2221 * can be coalesced into larger rectangles. qv. miCoalesce, above.-
2222 * In the beginning, there is no previous band, so prevBand == curBand-
2223 * (curBand is set later on, of course, but the first band will always-
2224 * start at index 0). prevBand and curBand must be indices because of-
2225 * the possible expansion, and resultant moving, of the new region's-
2226 * array of rectangles.-
2227 */-
2228 prevBand = 0;-
2229-
2230 do {-
2231 curBand = dest.numRects;-
2232-
2233 /*-
2234 * This algorithm proceeds one source-band (as opposed to a-
2235 * destination band, which is determined by where the two regions-
2236 * intersect) at a time. r1BandEnd and r2BandEnd serve to mark the-
2237 * rectangle after the last one in the current band for their-
2238 * respective regions.-
2239 */-
2240 r1BandEnd = r1;-
2241 while (r1BandEnd != r1End && r1BandEnd->top() == r1->top())
r1BandEnd != r1EndDescription
TRUEnever evaluated
FALSEnever evaluated
r1BandEnd->top() == r1->top()Description
TRUEnever evaluated
FALSEnever evaluated
0
2242 ++r1BandEnd;
never executed: ++r1BandEnd;
0
2243-
2244 r2BandEnd = r2;-
2245 while (r2BandEnd != r2End && r2BandEnd->top() == r2->top())
r2BandEnd != r2EndDescription
TRUEnever evaluated
FALSEnever evaluated
r2BandEnd->top() == r2->top()Description
TRUEnever evaluated
FALSEnever evaluated
0
2246 ++r2BandEnd;
never executed: ++r2BandEnd;
0
2247-
2248 /*-
2249 * First handle the band that doesn't intersect, if any.-
2250 *-
2251 * Note that attention is restricted to one band in the-
2252 * non-intersecting region at once, so if a region has n-
2253 * bands between the current position and the next place it overlaps-
2254 * the other, this entire loop will be passed through n times.-
2255 */-
2256 if (r1->top() < r2->top()) {
r1->top() < r2->top()Description
TRUEnever evaluated
FALSEnever evaluated
0
2257 top = qMax(r1->top(), ybot + 1);-
2258 bot = qMin(r1->bottom(), r2->top() - 1);-
2259-
2260 if (nonOverlap1Func != 0 && bot >= top)
nonOverlap1Func != 0Description
TRUEnever evaluated
FALSEnever evaluated
bot >= topDescription
TRUEnever evaluated
FALSEnever evaluated
0
2261 (*nonOverlap1Func)(dest, r1, r1BandEnd, top, bot);
never executed: (*nonOverlap1Func)(dest, r1, r1BandEnd, top, bot);
0
2262 ytop = r2->top();-
2263 } else if (r2->top() < r1->top()) {
never executed: end of block
r2->top() < r1->top()Description
TRUEnever evaluated
FALSEnever evaluated
0
2264 top = qMax(r2->top(), ybot + 1);-
2265 bot = qMin(r2->bottom(), r1->top() - 1);-
2266-
2267 if (nonOverlap2Func != 0 && bot >= top)
nonOverlap2Func != 0Description
TRUEnever evaluated
FALSEnever evaluated
bot >= topDescription
TRUEnever evaluated
FALSEnever evaluated
0
2268 (*nonOverlap2Func)(dest, r2, r2BandEnd, top, bot);
never executed: (*nonOverlap2Func)(dest, r2, r2BandEnd, top, bot);
0
2269 ytop = r1->top();-
2270 } else {
never executed: end of block
0
2271 ytop = r1->top();-
2272 }
never executed: end of block
0
2273-
2274 /*-
2275 * If any rectangles got added to the region, try and coalesce them-
2276 * with rectangles from the previous band. Note we could just do-
2277 * this test in miCoalesce, but some machines incur a not-
2278 * inconsiderable cost for function calls, so...-
2279 */-
2280 if (dest.numRects != curBand)
dest.numRects != curBandDescription
TRUEnever evaluated
FALSEnever evaluated
0
2281 prevBand = miCoalesce(dest, prevBand, curBand);
never executed: prevBand = miCoalesce(dest, prevBand, curBand);
0
2282-
2283 /*-
2284 * Now see if we've hit an intersecting band. The two bands only-
2285 * intersect if ybot >= ytop-
2286 */-
2287 ybot = qMin(r1->bottom(), r2->bottom());-
2288 curBand = dest.numRects;-
2289 if (ybot >= ytop)
ybot >= ytopDescription
TRUEnever evaluated
FALSEnever evaluated
0
2290 (*overlapFunc)(dest, r1, r1BandEnd, r2, r2BandEnd, ytop, ybot);
never executed: (*overlapFunc)(dest, r1, r1BandEnd, r2, r2BandEnd, ytop, ybot);
0
2291-
2292 if (dest.numRects != curBand)
dest.numRects != curBandDescription
TRUEnever evaluated
FALSEnever evaluated
0
2293 prevBand = miCoalesce(dest, prevBand, curBand);
never executed: prevBand = miCoalesce(dest, prevBand, curBand);
0
2294-
2295 /*-
2296 * If we've finished with a band (y2 == ybot) we skip forward-
2297 * in the region to the next band.-
2298 */-
2299 if (r1->bottom() == ybot)
r1->bottom() == ybotDescription
TRUEnever evaluated
FALSEnever evaluated
0
2300 r1 = r1BandEnd;
never executed: r1 = r1BandEnd;
0
2301 if (r2->bottom() == ybot)
r2->bottom() == ybotDescription
TRUEnever evaluated
FALSEnever evaluated
0
2302 r2 = r2BandEnd;
never executed: r2 = r2BandEnd;
0
2303 } while (r1 != r1End && r2 != r2End);
never executed: end of block
r1 != r1EndDescription
TRUEnever evaluated
FALSEnever evaluated
r2 != r2EndDescription
TRUEnever evaluated
FALSEnever evaluated
0
2304-
2305 /*-
2306 * Deal with whichever region still has rectangles left.-
2307 */-
2308 curBand = dest.numRects;-
2309 if (r1 != r1End) {
r1 != r1EndDescription
TRUEnever evaluated
FALSEnever evaluated
0
2310 if (nonOverlap1Func != 0) {
nonOverlap1Func != 0Description
TRUEnever evaluated
FALSEnever evaluated
0
2311 do {-
2312 r1BandEnd = r1;-
2313 while (r1BandEnd < r1End && r1BandEnd->top() == r1->top())
r1BandEnd < r1EndDescription
TRUEnever evaluated
FALSEnever evaluated
r1BandEnd->top() == r1->top()Description
TRUEnever evaluated
FALSEnever evaluated
0
2314 ++r1BandEnd;
never executed: ++r1BandEnd;
0
2315 (*nonOverlap1Func)(dest, r1, r1BandEnd, qMax(r1->top(), ybot + 1), r1->bottom());-
2316 r1 = r1BandEnd;-
2317 } while (r1 != r1End);
never executed: end of block
r1 != r1EndDescription
TRUEnever evaluated
FALSEnever evaluated
0
2318 }
never executed: end of block
0
2319 } else if ((r2 != r2End) && (nonOverlap2Func != 0)) {
never executed: end of block
(r2 != r2End)Description
TRUEnever evaluated
FALSEnever evaluated
(nonOverlap2Func != 0)Description
TRUEnever evaluated
FALSEnever evaluated
0
2320 do {-
2321 r2BandEnd = r2;-
2322 while (r2BandEnd < r2End && r2BandEnd->top() == r2->top())
r2BandEnd < r2EndDescription
TRUEnever evaluated
FALSEnever evaluated
r2BandEnd->top() == r2->top()Description
TRUEnever evaluated
FALSEnever evaluated
0
2323 ++r2BandEnd;
never executed: ++r2BandEnd;
0
2324 (*nonOverlap2Func)(dest, r2, r2BandEnd, qMax(r2->top(), ybot + 1), r2->bottom());-
2325 r2 = r2BandEnd;-
2326 } while (r2 != r2End);
never executed: end of block
r2 != r2EndDescription
TRUEnever evaluated
FALSEnever evaluated
0
2327 }
never executed: end of block
0
2328-
2329 if (dest.numRects != curBand)
dest.numRects != curBandDescription
TRUEnever evaluated
FALSEnever evaluated
0
2330 (void)miCoalesce(dest, prevBand, curBand);
never executed: (void)miCoalesce(dest, prevBand, curBand);
0
2331-
2332 /*-
2333 * A bit of cleanup. To keep regions from growing without bound,-
2334 * we shrink the array of rectangles to match the new number of-
2335 * rectangles in the region.-
2336 *-
2337 * Only do this stuff if the number of rectangles allocated is more than-
2338 * twice the number of rectangles in the region (a simple optimization).-
2339 */-
2340 if (qMax(4, dest.numRects) < (dest.rects.size() >> 1))
qMax(4, dest.n...s.size() >> 1)Description
TRUEnever evaluated
FALSEnever evaluated
0
2341 dest.rects.resize(dest.numRects);
never executed: dest.rects.resize(dest.numRects);
0
2342}
never executed: end of block
0
2343-
2344/*======================================================================-
2345 * Region Union-
2346 *====================================================================*/-
2347-
2348/*--
2349 *------------------------------------------------------------------------
2350 * miUnionNonO ---
2351 * Handle a non-overlapping band for the union operation. Just-
2352 * Adds the rectangles into the region. Doesn't have to check for-
2353 * subsumption or anything.-
2354 *-
2355 * Results:-
2356 * None.-
2357 *-
2358 * Side Effects:-
2359 * dest.numRects is incremented and the final rectangles overwritten-
2360 * with the rectangles we're passed.-
2361 *-
2362 *------------------------------------------------------------------------
2363 */-
2364-
2365static void miUnionNonO(QRegionPrivate &dest, const QRect *r, const QRect *rEnd,-
2366 int y1, int y2)-
2367{-
2368 QRect *pNextRect;-
2369-
2370 pNextRect = dest.rects.data() + dest.numRects;-
2371-
2372 Q_ASSERT(y1 <= y2);-
2373-
2374 while (r != rEnd) {
r != rEndDescription
TRUEnever evaluated
FALSEnever evaluated
0
2375 Q_ASSERT(r->left() <= r->right());-
2376 MEMCHECK(dest, pNextRect, dest.rects)
never executed: end of block
(dest).numRect...ects.size()-1)Description
TRUEnever evaluated
FALSEnever evaluated
0
2377 pNextRect->setCoords(r->left(), y1, r->right(), y2);-
2378 dest.numRects++;-
2379 ++pNextRect;-
2380 ++r;-
2381 }
never executed: end of block
0
2382}
never executed: end of block
0
2383-
2384-
2385/*--
2386 *------------------------------------------------------------------------
2387 * miUnionO ---
2388 * Handle an overlapping band for the union operation. Picks the-
2389 * left-most rectangle each time and merges it into the region.-
2390 *-
2391 * Results:-
2392 * None.-
2393 *-
2394 * Side Effects:-
2395 * Rectangles are overwritten in dest.rects and dest.numRects will-
2396 * be changed.-
2397 *-
2398 *------------------------------------------------------------------------
2399 */-
2400-
2401static void miUnionO(QRegionPrivate &dest, const QRect *r1, const QRect *r1End,-
2402 const QRect *r2, const QRect *r2End, int y1, int y2)-
2403{-
2404 QRect *pNextRect;-
2405-
2406 pNextRect = dest.rects.data() + dest.numRects;-
2407-
2408#define MERGERECT(r) \-
2409 if ((dest.numRects != 0) && \-
2410 (pNextRect[-1].top() == y1) && \-
2411 (pNextRect[-1].bottom() == y2) && \-
2412 (pNextRect[-1].right() >= r->left()-1)) { \-
2413 if (pNextRect[-1].right() < r->right()) { \-
2414 pNextRect[-1].setRight(r->right()); \-
2415 dest.updateInnerRect(pNextRect[-1]); \-
2416 Q_ASSERT(pNextRect[-1].left() <= pNextRect[-1].right()); \-
2417 } \-
2418 } else { \-
2419 MEMCHECK(dest, pNextRect, dest.rects) \-
2420 pNextRect->setCoords(r->left(), y1, r->right(), y2); \-
2421 dest.updateInnerRect(*pNextRect); \-
2422 dest.numRects++; \-
2423 pNextRect++; \-
2424 } \-
2425 r++;-
2426-
2427 Q_ASSERT(y1 <= y2);-
2428 while (r1 != r1End && r2 != r2End) {
r1 != r1EndDescription
TRUEnever evaluated
FALSEnever evaluated
r2 != r2EndDescription
TRUEnever evaluated
FALSEnever evaluated
0
2429 if (r1->left() < r2->left()) {
r1->left() < r2->left()Description
TRUEnever evaluated
FALSEnever evaluated
0
2430 MERGERECT(r1)
never executed: end of block
never executed: end of block
never executed: end of block
never executed: end of block
pNextRect[-1].... < r1->right()Description
TRUEnever evaluated
FALSEnever evaluated
(dest).numRect...ects.size()-1)Description
TRUEnever evaluated
FALSEnever evaluated
(dest.numRects != 0)Description
TRUEnever evaluated
FALSEnever evaluated
(pNextRect[-1].top() == y1)Description
TRUEnever evaluated
FALSEnever evaluated
(pNextRect[-1].bottom() == y2)Description
TRUEnever evaluated
FALSEnever evaluated
(pNextRect[-1]... r1->left()-1)Description
TRUEnever evaluated
FALSEnever evaluated
0
2431 } else {
never executed: end of block
0
2432 MERGERECT(r2)
never executed: end of block
never executed: end of block
never executed: end of block
never executed: end of block
pNextRect[-1].... < r2->right()Description
TRUEnever evaluated
FALSEnever evaluated
(dest).numRect...ects.size()-1)Description
TRUEnever evaluated
FALSEnever evaluated
(dest.numRects != 0)Description
TRUEnever evaluated
FALSEnever evaluated
(pNextRect[-1].top() == y1)Description
TRUEnever evaluated
FALSEnever evaluated
(pNextRect[-1].bottom() == y2)Description
TRUEnever evaluated
FALSEnever evaluated
(pNextRect[-1]... r2->left()-1)Description
TRUEnever evaluated
FALSEnever evaluated
0
2433 }
never executed: end of block
0
2434 }-
2435-
2436 if (r1 != r1End) {
r1 != r1EndDescription
TRUEnever evaluated
FALSEnever evaluated
0
2437 do {-
2438 MERGERECT(r1)
never executed: end of block
never executed: end of block
never executed: end of block
never executed: end of block
pNextRect[-1].... < r1->right()Description
TRUEnever evaluated
FALSEnever evaluated
(dest).numRect...ects.size()-1)Description
TRUEnever evaluated
FALSEnever evaluated
(dest.numRects != 0)Description
TRUEnever evaluated
FALSEnever evaluated
(pNextRect[-1].top() == y1)Description
TRUEnever evaluated
FALSEnever evaluated
(pNextRect[-1].bottom() == y2)Description
TRUEnever evaluated
FALSEnever evaluated
(pNextRect[-1]... r1->left()-1)Description
TRUEnever evaluated
FALSEnever evaluated
0
2439 } while (r1 != r1End);
never executed: end of block
r1 != r1EndDescription
TRUEnever evaluated
FALSEnever evaluated
0
2440 } else {
never executed: end of block
0
2441 while (r2 != r2End) {
r2 != r2EndDescription
TRUEnever evaluated
FALSEnever evaluated
0
2442 MERGERECT(r2)
never executed: end of block
never executed: end of block
never executed: end of block
never executed: end of block
pNextRect[-1].... < r2->right()Description
TRUEnever evaluated
FALSEnever evaluated
(dest).numRect...ects.size()-1)Description
TRUEnever evaluated
FALSEnever evaluated
(dest.numRects != 0)Description
TRUEnever evaluated
FALSEnever evaluated
(pNextRect[-1].top() == y1)Description
TRUEnever evaluated
FALSEnever evaluated
(pNextRect[-1].bottom() == y2)Description
TRUEnever evaluated
FALSEnever evaluated
(pNextRect[-1]... r2->left()-1)Description
TRUEnever evaluated
FALSEnever evaluated
0
2443 }
never executed: end of block
0
2444 }
never executed: end of block
0
2445}-
2446-
2447static void UnionRegion(const QRegionPrivate *reg1, const QRegionPrivate *reg2, QRegionPrivate &dest)-
2448{-
2449 Q_ASSERT(!isEmptyHelper(reg1) && !isEmptyHelper(reg2));-
2450 Q_ASSERT(!reg1->contains(*reg2));-
2451 Q_ASSERT(!reg2->contains(*reg1));-
2452 Q_ASSERT(!EqualRegion(reg1, reg2));-
2453 Q_ASSERT(!reg1->canAppend(reg2));-
2454 Q_ASSERT(!reg2->canAppend(reg1));-
2455-
2456 if (reg1->innerArea > reg2->innerArea) {
reg1->innerAre...eg2->innerAreaDescription
TRUEnever evaluated
FALSEnever evaluated
0
2457 dest.innerArea = reg1->innerArea;-
2458 dest.innerRect = reg1->innerRect;-
2459 } else {
never executed: end of block
0
2460 dest.innerArea = reg2->innerArea;-
2461 dest.innerRect = reg2->innerRect;-
2462 }
never executed: end of block
0
2463 miRegionOp(dest, reg1, reg2, miUnionO, miUnionNonO, miUnionNonO);-
2464-
2465 dest.extents.setCoords(qMin(reg1->extents.left(), reg2->extents.left()),-
2466 qMin(reg1->extents.top(), reg2->extents.top()),-
2467 qMax(reg1->extents.right(), reg2->extents.right()),-
2468 qMax(reg1->extents.bottom(), reg2->extents.bottom()));-
2469}
never executed: end of block
0
2470-
2471/*======================================================================-
2472 * Region Subtraction-
2473 *====================================================================*/-
2474-
2475/*--
2476 *------------------------------------------------------------------------
2477 * miSubtractNonO ---
2478 * Deal with non-overlapping band for subtraction. Any parts from-
2479 * region 2 we discard. Anything from region 1 we add to the region.-
2480 *-
2481 * Results:-
2482 * None.-
2483 *-
2484 * Side Effects:-
2485 * dest may be affected.-
2486 *-
2487 *------------------------------------------------------------------------
2488 */-
2489-
2490static void miSubtractNonO1(QRegionPrivate &dest, const QRect *r,-
2491 const QRect *rEnd, int y1, int y2)-
2492{-
2493 QRect *pNextRect;-
2494-
2495 pNextRect = dest.rects.data() + dest.numRects;-
2496-
2497 Q_ASSERT(y1<=y2);-
2498-
2499 while (r != rEnd) {
r != rEndDescription
TRUEnever evaluated
FALSEnever evaluated
0
2500 Q_ASSERT(r->left() <= r->right());-
2501 MEMCHECK(dest, pNextRect, dest.rects)
never executed: end of block
(dest).numRect...ects.size()-1)Description
TRUEnever evaluated
FALSEnever evaluated
0
2502 pNextRect->setCoords(r->left(), y1, r->right(), y2);-
2503 ++dest.numRects;-
2504 ++pNextRect;-
2505 ++r;-
2506 }
never executed: end of block
0
2507}
never executed: end of block
0
2508-
2509/*--
2510 *-----------------------------------------------------------------------