16#include <private/qdebug_p.h>
174void QRegion::detach()
176 if (d->ref.isShared())
181#define QRGN_SETRECT 1
182#define QRGN_SETELLIPSE 2
183#define QRGN_SETPTARRAY_ALT 3
184#define QRGN_SETPTARRAY_WIND 4
185#define QRGN_TRANSLATE 5
193#ifndef QT_NO_DATASTREAM
210 s.setByteOrder(byteOrder);
217 if (
s.version() == 1) {
226 qWarning(
"QRegion::exec: Internal error");
257 rgn =
r1.subtracted(
r2);
268 for (
int i=0; i < static_cast<int>(
n);
i++) {
315 auto b =
r.begin(),
e =
r.end();
317 s << static_cast<quint32>(0);
320 if (
s.version() == 1) {
321 for (
auto i =
size - 1;
i > 0; --
i) {
322 s << static_cast<quint32>(12 +
i * 24);
323 s << static_cast<int>(
QRGN_OR);
351 r.exec(
b,
s.version(),
s.byteOrder());
356#ifndef QT_NO_DEBUG_STREAM
364 }
else if (
r.isEmpty()) {
367 const int count =
r.rectCount();
369 s <<
"size=" <<
count <<
", bounds=(";
464 {
return *
this = *
this |
r; }
482#if !defined (Q_OS_UNIX) && !defined (Q_OS_WIN)
499 {
return *
this = *
this &
r; }
505#if defined (Q_OS_UNIX) || defined (Q_OS_WIN)
508 return *
this = *
this &
r;
527 {
return *
this = *
this -
r; }
537 {
return *
this = *
this ^
r; }
596 ret.translate(dx, dy);
623 for (
const QRect &myRect : *
this)
624 for (
const QRect &otherRect : region)
639#if !defined (Q_OS_UNIX) && !defined (Q_OS_WIN) || defined(Q_QDOC)
910 return qMin(point.x(),
next->point.x());
915 return qMax(point.x(),
next->point.x());
918 bool overlaps(
const Segment &
other)
const
928 horizontal = (point.y() ==
other.point.y());
931 void merge(Segment &
other)
935 Segment *oprev =
other.prev;
945 Segment *onext =
other.next;
962void mergeSegments(Segment *
a,
int na, Segment *
b,
int nb)
967 while (
i != na &&
j != nb) {
970 const int ra = sa.right();
971 const int rb = sb.right();
982 path.moveTo(current->point);
984 current->added =
true;
986 Segment *last = current;
987 current = current->next;
989 if (current->horizontal != last->horizontal)
990 path.lineTo(current->point);
991 current->added =
true;
993 current = current->next;
1016 const auto end = region.
end();
1021 int lastRowSegmentCount = 0;
1022 Segment *lastRowSegments =
nullptr;
1024 int lastSegment = 0;
1027 const int y =
rect[0].y();
1040 for (
int j = 0;
j < 4; ++
j)
1044 if (lastRowSegments && lastY ==
y)
1045 mergeSegments(lastRowSegments, lastRowSegmentCount, &
segments[lastSegment],
count);
1048 lastRowSegmentCount =
count;
1049 lastSegment += 4 *
count;
1050 lastY =
y +
rect[0].height();
1054 for (
int i = 0;
i < lastSegment; ++
i) {
1063#if defined(Q_OS_UNIX) || defined(Q_OS_WIN)
1070struct QRegionPrivate {
1077 inline QRegionPrivate() : numRects(0), innerArea(-1) {}
1078 inline QRegionPrivate(
const QRect &
r)
1086 void intersect(
const QRect &
r);
1092 inline bool contains(
const QRegionPrivate &
r)
const {
1105 inline bool within(
const QRect &
r1)
const {
1111 inline void updateInnerRect(
const QRect &
rect) {
1113 if (
area > innerArea) {
1119 inline void vectorize() {
1120 if (numRects == 1) {
1128 {
return numRects == 1 ? &extents : rects.
data(); }
1131 {
return begin() + numRects; }
1134 void append(
const QRegionPrivate *
r);
1136 void prepend(
const QRegionPrivate *
r);
1137 inline bool canAppend(
const QRect *
r)
const;
1138 inline bool canAppend(
const QRegionPrivate *
r)
const;
1139 inline bool canPrepend(
const QRect *
r)
const;
1140 inline bool canPrepend(
const QRegionPrivate *
r)
const;
1145 const QRect *nextToTop,
1146 const QRect *nextToBottom);
1148 const QRect *nextToBottom,
1149 const QRect *nextToTop);
1151#ifdef QT_REGION_DEBUG
1152 void selfTest()
const;
1156static inline bool isEmptyHelper(
const QRegionPrivate *preg)
1158 return !preg || preg->numRects == 0;
1165 &&
right->left() <= (
left->right() + 1));
1177 updateInnerRect(*
left);
1187 updateInnerRect(*
right);
1194 const QRect *nextToTop,
1195 const QRect *nextToBottom)
1197 if (nextToTop && nextToTop->
y() ==
top->y())
1199 if (nextToBottom && nextToBottom->
y() ==
bottom->y())
1202 return ((
top->bottom() >= (
bottom->top() - 1))
1208 const QRect *nextToTop,
1209 const QRect *nextToBottom)
1211 if (canMergeFromBelow(
top,
bottom, nextToTop, nextToBottom)) {
1213 updateInnerRect(*
top);
1220 const QRect *nextToBottom,
1221 const QRect *nextToTop)
1223 if (canMergeFromBelow(
top,
bottom, nextToTop, nextToBottom)) {
1225 updateInnerRect(*
bottom);
1231static inline QRect qt_rect_intersect_normalized(
const QRect &
r1,
1242void QRegionPrivate::intersect(
const QRect &
rect)
1247#ifdef QT_REGION_DEBUG
1253 innerRect =
QRect();
1261 *dest = qt_rect_intersect_normalized(*
src++,
r);
1265 if (numRects == 0) {
1274 const QRect *nextToLast = (numRects > 1 ? dest - 2 :
nullptr);
1277 if (canMergeFromBelow(dest - 1, dest, nextToLast,
nullptr)) {
1278 if (!
n ||
src->y() != dest->
y() ||
src->left() >
r.right()) {
1279 QRect *prev = dest - 1;
1281 updateInnerRect(*prev);
1286 updateInnerRect(*dest);
1290#ifdef QT_REGION_DEBUG
1295void QRegionPrivate::append(
const QRect *
r)
1299 QRect *myLast = (numRects == 1 ? &extents : rects.
data() + (numRects - 1));
1300 if (mergeFromRight(myLast,
r)) {
1302 const QRect *nextToTop = (numRects > 2 ? myLast - 2 :
nullptr);
1303 if (mergeFromBelow(myLast - 1, myLast, nextToTop,
nullptr))
1306 }
else if (mergeFromBelow(myLast,
r, (numRects > 1 ? myLast - 1 :
nullptr),
nullptr)) {
1311 updateInnerRect(*
r);
1312 if (rects.
size() < numRects)
1314 rects[numRects - 1] = *
r;
1321#ifdef QT_REGION_DEBUG
1326void QRegionPrivate::append(
const QRegionPrivate *
r)
1330 if (
r->numRects == 1) {
1337 QRect *destRect = rects.
data() + numRects;
1338 const QRect *srcRect =
r->rects.constData();
1339 int numAppend =
r->numRects;
1343 const QRect *rFirst = srcRect;
1344 QRect *myLast = destRect - 1;
1345 const QRect *nextToLast = (numRects > 1 ? myLast - 1 :
nullptr);
1346 if (mergeFromRight(myLast, rFirst)) {
1349 const QRect *rNextToFirst = (numAppend > 1 ? rFirst + 2 :
nullptr);
1350 if (mergeFromBelow(myLast, rFirst + 1, nextToLast, rNextToFirst)) {
1355 nextToLast = (numRects > 2 ? myLast - 2 :
nullptr);
1356 rNextToFirst = (numAppend > 0 ? srcRect :
nullptr);
1357 if (mergeFromBelow(myLast - 1, myLast, nextToLast, rNextToFirst)) {
1362 }
else if (mergeFromBelow(myLast, rFirst, nextToLast, rFirst + 1)) {
1369 if (numAppend > 0) {
1370 const int newNumRects = numRects + numAppend;
1371 if (newNumRects > rects.
size()) {
1372 rects.
resize(newNumRects);
1373 destRect = rects.
data() + numRects;
1375 memcpy(destRect, srcRect, numAppend *
sizeof(
QRect));
1377 numRects = newNumRects;
1381 if (innerArea < r->innerArea) {
1382 innerArea =
r->innerArea;
1383 innerRect =
r->innerRect;
1387 destRect = &extents;
1388 srcRect = &
r->extents;
1394#ifdef QT_REGION_DEBUG
1399void QRegionPrivate::prepend(
const QRegionPrivate *
r)
1403 if (
r->numRects == 1) {
1410 int numPrepend =
r->numRects;
1416 const QRect *nextToFirst = (numRects > 1 ? myFirst + 1 :
nullptr);
1417 const QRect *rLast =
r->rects.constData() +
r->numRects - 1;
1418 const QRect *rNextToLast = (
r->numRects > 1 ? rLast - 1 :
nullptr);
1419 if (mergeFromLeft(myFirst, rLast)) {
1422 rNextToLast = (numPrepend > 1 ? rLast - 1 :
nullptr);
1423 if (mergeFromAbove(myFirst, rLast, nextToFirst, rNextToLast)) {
1428 nextToFirst = (numRects > 2? myFirst + 2 :
nullptr);
1429 rNextToLast = (numPrepend > 0 ? rLast :
nullptr);
1430 if (mergeFromAbove(myFirst + 1, myFirst, nextToFirst, rNextToLast)) {
1435 }
else if (mergeFromAbove(myFirst, rLast, nextToFirst, rNextToLast)) {
1440 if (numPrepend > 0) {
1441 const int newNumRects = numRects + numPrepend;
1442 if (newNumRects > rects.
size())
1443 rects.
resize(newNumRects);
1446 memmove(rects.
data() + numPrepend, rects.
constData() + numSkip,
1447 numRects *
sizeof(
QRect));
1450 memcpy(rects.
data(),
r->rects.constData(), numPrepend *
sizeof(
QRect));
1452 numRects = newNumRects;
1456 if (innerArea < r->innerArea) {
1457 innerArea =
r->innerArea;
1458 innerRect =
r->innerRect;
1463 qMin(extents.
top(),
r->extents.top()),
1467#ifdef QT_REGION_DEBUG
1472void QRegionPrivate::prepend(
const QRect *
r)
1476 QRect *myFirst = (numRects == 1 ? &extents : rects.
data());
1477 if (mergeFromLeft(myFirst,
r)) {
1479 const QRect *nextToFirst = (numRects > 2 ? myFirst + 2 :
nullptr);
1480 if (mergeFromAbove(myFirst + 1, myFirst, nextToFirst,
nullptr)) {
1483 numRects *
sizeof(
QRect));
1486 }
else if (mergeFromAbove(myFirst,
r, (numRects > 1 ? myFirst + 1 :
nullptr),
nullptr)) {
1491 updateInnerRect(*
r);
1499#ifdef QT_REGION_DEBUG
1504bool QRegionPrivate::canAppend(
const QRect *
r)
const
1508 const QRect *myLast = (numRects == 1) ? &extents : (rects.constData() + (numRects - 1));
1509 if (
r->top() > myLast->
bottom())
1511 if (
r->top() == myLast->
top()
1512 &&
r->height() == myLast->
height()
1513 &&
r->left() > myLast->
right())
1521bool QRegionPrivate::canAppend(
const QRegionPrivate *
r)
const
1523 return canAppend(
r->numRects == 1 ? &
r->extents :
r->rects.constData());
1526bool QRegionPrivate::canPrepend(
const QRect *
r)
const
1530 const QRect *myFirst = (numRects == 1) ? &extents : rects.constData();
1531 if (
r->bottom() < myFirst->
top())
1533 if (
r->top() == myFirst->
top()
1534 &&
r->height() == myFirst->
height()
1535 &&
r->right() < myFirst->
left())
1543bool QRegionPrivate::canPrepend(
const QRegionPrivate *
r)
const
1545 return canPrepend(
r->numRects == 1 ? &
r->extents :
r->rects.constData() +
r->numRects - 1);
1548#ifdef QT_REGION_DEBUG
1549void QRegionPrivate::selfTest()
const
1551 if (numRects == 0) {
1559 if (numRects == 1) {
1565 for (
int i = 0;
i < numRects; ++
i) {
1567 if ((
r.width() *
r.height()) > innerArea)
1568 qDebug() <<
"selfTest(): innerRect" << innerRect <<
'<' <<
r;
1572 for (
int i = 1;
i < numRects; ++
i) {
1575 if (
r2.
y() ==
r.y()) {
1586static QRegionPrivate qrp;
1589typedef void (*OverlapFunc)(QRegionPrivate &dest,
const QRect *
r1,
const QRect *r1End,
1591typedef void (*NonOverlapFunc)(QRegionPrivate &dest,
const QRect *
r,
const QRect *rEnd,
1594static bool EqualRegion(
const QRegionPrivate *
r1,
const QRegionPrivate *
r2);
1595static void UnionRegion(
const QRegionPrivate *reg1,
const QRegionPrivate *reg2, QRegionPrivate &dest);
1596static void miRegionOp(QRegionPrivate &dest,
const QRegionPrivate *reg1,
const QRegionPrivate *reg2,
1597 OverlapFunc overlapFunc, NonOverlapFunc nonOverlap1Func,
1598 NonOverlapFunc nonOverlap2Func);
1600#define RectangleOut 0
1601#define RectangleIn 1
1602#define RectanglePart 2
1603#define EvenOddRule 0
1604#define WindingRule 1
1667#define EXTENTCHECK(r1, r2) \
1668 ((r1)->right() >= (r2)->left() && \
1669 (r1)->left() <= (r2)->right() && \
1670 (r1)->bottom() >= (r2)->top() && \
1671 (r1)->top() <= (r2)->bottom())
1676#define EXTENTS(r,idRect){\
1677 if((r)->left() < (idRect)->extents.left())\
1678 (idRect)->extents.setLeft((r)->left());\
1679 if((r)->top() < (idRect)->extents.top())\
1680 (idRect)->extents.setTop((r)->top());\
1681 if((r)->right() > (idRect)->extents.right())\
1682 (idRect)->extents.setRight((r)->right());\
1683 if((r)->bottom() > (idRect)->extents.bottom())\
1684 (idRect)->extents.setBottom((r)->bottom());\
1690#define MEMCHECK(dest, rect, firstrect){\
1691 if ((dest).numRects >= ((dest).rects.size()-1)){\
1692 firstrect.resize(firstrect.size() * 2); \
1693 (rect) = (firstrect).data() + (dest).numRects;\
1702#define NUMPTSTOBUFFER 200
1708typedef struct _POINTBLOCK {
1711 struct _POINTBLOCK *
next;
1793static void UnionRectWithRegion(
const QRect *
rect,
const QRegionPrivate *
source,
1794 QRegionPrivate &dest)
1796 if (
rect->isEmpty())
1801 if (dest.numRects == 0) {
1802 dest = QRegionPrivate(*
rect);
1803 }
else if (dest.canAppend(
rect)) {
1806 QRegionPrivate
p(*
rect);
1807 UnionRegion(&
p,
source, dest);
1826static void miSetExtents(QRegionPrivate &dest)
1832 dest.innerRect.setCoords(0, 0, -1, -1);
1833 dest.innerArea = -1;
1834 if (dest.numRects == 0) {
1835 dest.extents.setCoords(0, 0, -1, -1);
1839 pExtents = &dest.extents;
1840 if (dest.rects.isEmpty())
1841 pBox = &dest.extents;
1843 pBox = dest.rects.constData();
1844 pBoxEnd = pBox + dest.numRects - 1;
1859 while (pBox <= pBoxEnd) {
1860 if (pBox->
left() < pExtents->
left())
1864 dest.updateInnerRect(*pBox);
1875static void OffsetRegion(QRegionPrivate ®ion,
int x,
int y)
1877 if (region.rects.size()) {
1878 QRect *pbox = region.rects.data();
1879 int nbox = region.numRects;
1886 region.extents.translate(
x,
y);
1887 region.innerRect.translate(
x,
y);
1906static void miIntersectO(QRegionPrivate &dest,
const QRect *
r1,
const QRect *r1End,
1913 pNextRect = dest.rects.data() + dest.numRects;
1915 while (
r1 != r1End &&
r2 != r2End) {
1928 MEMCHECK(dest, pNextRect, dest.rects)
1971static int miCoalesce(QRegionPrivate &dest,
int prevStart,
int curStart)
1979 QRect *rData = dest.rects.data();
1981 pRegEnd = rData + dest.numRects;
1983 pPrevBox = rData + prevStart;
1984 prevNumRects = curStart - prevStart;
1991 pCurBox = rData + curStart;
1992 bandY1 = pCurBox->
top();
1993 for (curNumRects = 0; pCurBox != pRegEnd && pCurBox->
top() == bandY1; ++curNumRects) {
1997 if (pCurBox != pRegEnd) {
2005 while ((pRegEnd - 1)->
top() == pRegEnd->
top())
2007 curStart = pRegEnd - rData;
2008 pRegEnd = rData + dest.numRects;
2011 if (curNumRects == prevNumRects && curNumRects != 0) {
2012 pCurBox -= curNumRects;
2017 if (pPrevBox->
bottom() == pCurBox->
top() - 1) {
2032 }
while (prevNumRects != 0);
2034 dest.numRects -= curNumRects;
2035 pCurBox -= curNumRects;
2036 pPrevBox -= curNumRects;
2045 dest.updateInnerRect(*pPrevBox);
2049 }
while (curNumRects != 0);
2061 if (pCurBox == pRegEnd) {
2062 curStart = prevStart;
2065 *pPrevBox++ = *pCurBox++;
2066 dest.updateInnerRect(*pPrevBox);
2067 }
while (pCurBox != pRegEnd);
2100static void miRegionOp(QRegionPrivate &dest,
2101 const QRegionPrivate *reg1,
const QRegionPrivate *reg2,
2102 OverlapFunc overlapFunc, NonOverlapFunc nonOverlap1Func,
2103 NonOverlapFunc nonOverlap2Func)
2113 const QRect *r1BandEnd;
2114 const QRect *r2BandEnd;
2125 if (reg1->numRects == 1)
2126 r1 = ®1->extents;
2128 r1 = reg1->rects.constData();
2129 if (reg2->numRects == 1)
2130 r2 = ®2->extents;
2132 r2 = reg2->rects.constData();
2134 r1End =
r1 + reg1->numRects;
2135 r2End =
r2 + reg2->numRects;
2157 dest.rects.resize(
qMax(reg1->numRects,reg2->numRects) * 2);
2172 if (reg1->extents.top() < reg2->extents.top())
2173 ybot = reg1->extents.top() - 1;
2175 ybot = reg2->extents.top() - 1;
2189 curBand = dest.numRects;
2199 while (r1BandEnd != r1End && r1BandEnd->
top() ==
r1->
top())
2203 while (r2BandEnd != r2End && r2BandEnd->
top() ==
r2->
top())
2218 if (nonOverlap1Func !=
nullptr && bot >=
top)
2219 (*nonOverlap1Func)(dest,
r1, r1BandEnd,
top, bot);
2225 if (nonOverlap2Func !=
nullptr && bot >=
top)
2226 (*nonOverlap2Func)(dest,
r2, r2BandEnd,
top, bot);
2238 if (dest.numRects != curBand)
2239 prevBand = miCoalesce(dest, prevBand, curBand);
2246 curBand = dest.numRects;
2248 (*overlapFunc)(dest,
r1, r1BandEnd,
r2, r2BandEnd, ytop, ybot);
2250 if (dest.numRects != curBand)
2251 prevBand = miCoalesce(dest, prevBand, curBand);
2261 }
while (
r1 != r1End &&
r2 != r2End);
2266 curBand = dest.numRects;
2268 if (nonOverlap1Func !=
nullptr) {
2271 while (r1BandEnd < r1End && r1BandEnd->
top() ==
r1->
top())
2275 }
while (
r1 != r1End);
2277 }
else if ((
r2 != r2End) && (nonOverlap2Func !=
nullptr)) {
2280 while (r2BandEnd < r2End && r2BandEnd->
top() ==
r2->
top())
2284 }
while (
r2 != r2End);
2287 if (dest.numRects != curBand)
2288 (
void)miCoalesce(dest, prevBand, curBand);
2298 if (
qMax(4, dest.numRects) < (dest.rects.size() >> 1))
2299 dest.rects.resize(dest.numRects);
2323static void miUnionNonO(QRegionPrivate &dest,
const QRect *
r,
const QRect *rEnd,
2328 pNextRect = dest.rects.data() + dest.numRects;
2334 MEMCHECK(dest, pNextRect, dest.rects)
2359static
void miUnionO(QRegionPrivate &dest, const
QRect *
r1, const
QRect *r1End,
2364 pNextRect = dest.rects.data() + dest.numRects;
2366#define MERGERECT(r) \
2367 if ((dest.numRects != 0) && \
2368 (pNextRect[-1].top() == y1) && \
2369 (pNextRect[-1].bottom() == y2) && \
2370 (pNextRect[-1].right() >= r->left()-1)) { \
2371 if (pNextRect[-1].right() < r->right()) { \
2372 pNextRect[-1].setRight(r->right()); \
2373 dest.updateInnerRect(pNextRect[-1]); \
2374 Q_ASSERT(pNextRect[-1].left() <= pNextRect[-1].right()); \
2377 MEMCHECK(dest, pNextRect, dest.rects) \
2378 pNextRect->setCoords(r->left(), y1, r->right(), y2); \
2379 dest.updateInnerRect(*pNextRect); \
2386 while (
r1 != r1End &&
r2 != r2End) {
2397 }
while (
r1 != r1End);
2399 while (
r2 != r2End) {
2405static void UnionRegion(
const QRegionPrivate *reg1,
const QRegionPrivate *reg2, QRegionPrivate &dest)
2407 Q_ASSERT(!isEmptyHelper(reg1) && !isEmptyHelper(reg2));
2410 Q_ASSERT(!EqualRegion(reg1, reg2));
2414 if (reg1->innerArea > reg2->innerArea) {
2415 dest.innerArea = reg1->innerArea;
2416 dest.innerRect = reg1->innerRect;
2418 dest.innerArea = reg2->innerArea;
2419 dest.innerRect = reg2->innerRect;
2421 miRegionOp(dest, reg1, reg2, miUnionO, miUnionNonO, miUnionNonO);
2423 dest.extents.setCoords(
qMin(reg1->extents.left(), reg2->extents.left()),
2424 qMin(reg1->extents.top(), reg2->extents.top()),
2425 qMax(reg1->extents.right(), reg2->extents.right()),
2426 qMax(reg1->extents.bottom(), reg2->extents.bottom()));
2448static void miSubtractNonO1(QRegionPrivate &dest,
const QRect *
r,
2453 pNextRect = dest.rects.data() + dest.numRects;
2459 MEMCHECK(dest, pNextRect, dest.rects)
2482static
void miSubtractO(QRegionPrivate &dest, const
QRect *
r1, const
QRect *r1End,
2491 pNextRect = dest.rects.data() + dest.numRects;
2493 while (
r1 != r1End &&
r2 != r2End) {
2522 MEMCHECK(dest, pNextRect, dest.rects)
2544 MEMCHECK(dest, pNextRect, dest.rects)
2560 MEMCHECK(dest, pNextRect, dest.rects)
2583static
void SubtractRegion(QRegionPrivate *regM, QRegionPrivate *regS,
2584 QRegionPrivate &dest)
2588 Q_ASSERT(EXTENTCHECK(®M->extents, ®S->extents));
2590 Q_ASSERT(!EqualRegion(regM, regS));
2592 miRegionOp(dest, regM, regS, miSubtractO, miSubtractNonO1,
nullptr);
2604static void XorRegion(QRegionPrivate *sra, QRegionPrivate *srb, QRegionPrivate &dest)
2606 Q_ASSERT(!isEmptyHelper(sra) && !isEmptyHelper(srb));
2607 Q_ASSERT(EXTENTCHECK(&sra->extents, &srb->extents));
2610 QRegionPrivate tra, trb;
2612 if (!srb->contains(*sra))
2613 SubtractRegion(sra, srb, tra);
2614 if (!sra->contains(*srb))
2615 SubtractRegion(srb, sra, trb);
2617 Q_ASSERT(isEmptyHelper(&trb) || !tra.contains(trb));
2618 Q_ASSERT(isEmptyHelper(&tra) || !trb.contains(tra));
2620 if (isEmptyHelper(&tra)) {
2622 }
else if (isEmptyHelper(&trb)) {
2624 }
else if (tra.canAppend(&trb)) {
2627 }
else if (trb.canAppend(&tra)) {
2631 UnionRegion(&tra, &trb, dest);
2638static bool EqualRegion(
const QRegionPrivate *
r1,
const QRegionPrivate *
r2)
2640 if (
r1->numRects !=
r2->numRects) {
2642 }
else if (
r1->numRects == 0) {
2644 }
else if (
r1->extents !=
r2->extents) {
2646 }
else if (
r1->numRects == 1 &&
r2->numRects == 1) {
2649 const QRect *rr1 = (
r1->numRects == 1) ? &
r1->extents :
r1->rects.constData();
2650 const QRect *rr2 = (
r2->numRects == 1) ? &
r2->extents :
r2->rects.constData();
2651 for (
int i = 0;
i <
r1->numRects; ++
i, ++rr1, ++rr2) {
2660static bool PointInRegion(QRegionPrivate *pRegion,
int x,
int y)
2664 if (isEmptyHelper(pRegion))
2666 if (!pRegion->extents.contains(
x,
y))
2668 if (pRegion->numRects == 1)
2669 return pRegion->extents.contains(
x,
y);
2670 if (pRegion->innerRect.contains(
x,
y))
2672 for (
i = 0;
i < pRegion->numRects; ++
i) {
2673 if (pRegion->rects[
i].contains(
x,
y))
2682 const QRect *pboxEnd;
2685 int partIn, partOut;
2687 if (!region || region->numRects == 0 || !EXTENTCHECK(®ion->extents, prect))
2688 return RectangleOut;
2694 pbox = (region->numRects == 1) ? ®ion->extents : region->rects.constData();
2695 pboxEnd = pbox + region->numRects;
2696 for (; pbox < pboxEnd; ++pbox) {
2700 if (pbox->
top() >
ry) {
2702 if (partIn || pbox->
top() > prect->
bottom())
2826#define BRESINITPGON(dy, x1, x2, xStart, d, m, m1, incr1, incr2) { \
2835 dx = (x2) - xStart; \
2839 incr1 = -2 * dx + 2 * (dy) * m1; \
2840 incr2 = -2 * dx + 2 * (dy) * m; \
2841 d = 2 * m * (dy) - 2 * dx - 2 * (dy); \
2845 incr1 = 2 * dx - 2 * (dy) * m1; \
2846 incr2 = 2 * dx - 2 * (dy) * m; \
2847 d = -2 * m * (dy) + 2 * dx; \
2852#define BRESINCRPGON(d, minval, m, m1, incr1, incr2) { \
2890#define BRESINITPGONSTRUCT(dmaj, min1, min2, bres) \
2891 BRESINITPGON(dmaj, min1, min2, bres.minor_axis, bres.d, \
2892 bres.m, bres.m1, bres.incr1, bres.incr2)
2894#define BRESINCRPGONSTRUCT(bres) \
2895 BRESINCRPGON(bres.d, bres.minor_axis, bres.m, bres.m1, bres.incr1, bres.incr2)
2949#define COUNTERCLOCKWISE -1
2951typedef struct _EdgeTableEntry {
2955 struct _EdgeTableEntry *
next;
2956 struct _EdgeTableEntry *back;
2957 struct _EdgeTableEntry *nextWETE;
2961typedef struct _ScanLineList{
2963 EdgeTableEntry *edgelist;
2964 struct _ScanLineList *
next;
2971 ScanLineList scanlines;
2980#define SLLSPERBLOCK 25
2982typedef struct _ScanLineListBlock {
2983 ScanLineList SLLs[SLLSPERBLOCK];
2984 struct _ScanLineListBlock *
next;
3002#define EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET) { \
3003 if (pAET->ymax == y) { \
3004 pPrevAET->next = pAET->next; \
3005 pAET = pPrevAET->next; \
3008 pAET->back = pPrevAET; \
3011 BRESINCRPGONSTRUCT(pAET->bres) \
3013 pAET = pAET->next; \
3025#define EVALUATEEDGEEVENODD(pAET, pPrevAET, y) { \
3026 if (pAET->ymax == y) { \
3027 pPrevAET->next = pAET->next; \
3028 pAET = pPrevAET->next; \
3030 pAET->back = pPrevAET; \
3033 BRESINCRPGONSTRUCT(pAET->bres) \
3035 pAET = pAET->next; \
3090#define LARGE_COORDINATE INT_MAX
3091#define SMALL_COORDINATE INT_MIN
3102static void InsertEdgeInET(EdgeTable *ET, EdgeTableEntry *ETE,
int scanline,
3103 ScanLineListBlock **SLLBlock,
int *iSLLBlock)
3105 EdgeTableEntry *
start, *prev;
3106 ScanLineList *pSLL, *pPrevSLL;
3107 ScanLineListBlock *tmpSLLBlock;
3112 pPrevSLL = &ET->scanlines;
3113 pSLL = pPrevSLL->next;
3114 while (pSLL && (pSLL->scanline < scanline)) {
3122 if ((!pSLL) || (pSLL->scanline > scanline)) {
3123 if (*iSLLBlock > SLLSPERBLOCK-1)
3126 (ScanLineListBlock *)malloc(
sizeof(ScanLineListBlock));
3128 (*SLLBlock)->next = tmpSLLBlock;
3129 tmpSLLBlock->next = (ScanLineListBlock *)
nullptr;
3130 *SLLBlock = tmpSLLBlock;
3133 pSLL = &((*SLLBlock)->SLLs[(*iSLLBlock)++]);
3135 pSLL->next = pPrevSLL->next;
3136 pSLL->edgelist = (EdgeTableEntry *)
nullptr;
3137 pPrevSLL->next = pSLL;
3139 pSLL->scanline = scanline;
3145 start = pSLL->edgelist;
3146 while (
start && (
start->bres.minor_axis < ETE->bres.minor_axis)) {
3155 pSLL->edgelist = ETE;
3183static void CreateETandAET(
int count,
const QPoint *pts,
3184 EdgeTable *ET, EdgeTableEntry *AET, EdgeTableEntry *pETEs,
3185 ScanLineListBlock *pSLLBlock)
3199 AET->next =
nullptr;
3200 AET->back =
nullptr;
3201 AET->nextWETE =
nullptr;
3202 AET->bres.minor_axis = SMALL_COORDINATE;
3207 ET->scanlines.next =
nullptr;
3208 ET->ymax = SMALL_COORDINATE;
3209 ET->ymin = LARGE_COORDINATE;
3210 pSLLBlock->next =
nullptr;
3212 PrevPt = &pts[
count - 1];
3225 if (PrevPt->
y() > CurrPt->
y()) {
3228 pETEs->ClockWise = 0;
3232 pETEs->ClockWise = 1;
3239 pETEs->ymax =
bottom->
y() - 1;
3245 BRESINITPGONSTRUCT(dy,
top->x(),
bottom->x(), pETEs->bres)
3247 InsertEdgeInET(ET, pETEs,
top->
y(), &pSLLBlock, &iSLLBlock);
3249 if (PrevPt->
y() > ET->ymax)
3250 ET->ymax = PrevPt->
y();
3251 if (PrevPt->
y() < ET->ymin)
3252 ET->ymin = PrevPt->
y();
3269static
void loadAET(EdgeTableEntry *AET, EdgeTableEntry *ETEs)
3271 EdgeTableEntry *pPrevAET;
3272 EdgeTableEntry *tmp;
3277 while (AET && AET->bres.minor_axis < ETEs->bres.minor_axis) {
3285 ETEs->back = pPrevAET;
3286 pPrevAET->next = ETEs;
3313static void computeWAET(EdgeTableEntry *AET)
3315 EdgeTableEntry *pWETE;
3319 AET->nextWETE =
nullptr;
3328 if ((!inside && !isInside) || (inside && isInside)) {
3329 pWETE->nextWETE = AET;
3335 pWETE->nextWETE =
nullptr;
3347static int InsertionSort(EdgeTableEntry *AET)
3349 EdgeTableEntry *pETEchase;
3350 EdgeTableEntry *pETEinsert;
3351 EdgeTableEntry *pETEchaseBackTMP;
3358 while (pETEchase->back->bres.minor_axis > AET->bres.minor_axis)
3359 pETEchase = pETEchase->back;
3362 if (pETEchase != pETEinsert) {
3363 pETEchaseBackTMP = pETEchase->back;
3364 pETEinsert->back->next = AET;
3366 AET->back = pETEinsert->back;
3367 pETEinsert->next = pETEchase;
3368 pETEchase->back->next = pETEinsert;
3369 pETEchase->back = pETEinsert;
3370 pETEinsert->back = pETEchaseBackTMP;
3380static void FreeStorage(ScanLineListBlock *pSLLBlock)
3382 ScanLineListBlock *tmpSLLBlock;
3385 tmpSLLBlock = pSLLBlock->next;
3387 pSLLBlock = tmpSLLBlock;
3393 QRegionSpan(
int x1_,
int x2_) :
x1(x1_),
x2(x2_) {}
3402static inline void flushRow(
const QRegionSpan *spans,
int y,
int numSpans, QRegionPrivate *reg,
int *lastRow,
int *extendTo,
bool *needsExtend)
3404 QRect *regRects = reg->rects.data() + *lastRow;
3405 bool canExtend = reg->rects.size() - *lastRow == numSpans
3406 && !(*needsExtend && *extendTo + 1 !=
y)
3407 && (*needsExtend || regRects[0].
y() + regRects[0].
height() ==
y);
3409 for (
int i = 0;
i < numSpans && canExtend; ++
i) {
3410 if (regRects[
i].
x() != spans[
i].x1 || regRects[
i].
right() != spans[
i].x2 - 1)
3416 *needsExtend =
true;
3419 for (
int i = 0;
i < reg->rects.size() - *lastRow; ++
i)
3420 regRects[
i].setBottom(*extendTo);
3423 *lastRow = reg->rects.size();
3424 reg->rects.reserve(*lastRow + numSpans);
3425 for (
int i = 0;
i < numSpans; ++
i)
3428 if (spans[0].x1 < reg->extents.
left())
3429 reg->extents.setLeft(spans[0].x1);
3431 if (spans[numSpans-1].
x2 - 1 > reg->extents.right())
3432 reg->extents.setRight(spans[numSpans-1].x2 - 1);
3434 *needsExtend =
false;
3446static void PtsToRegion(
int numFullPtBlocks,
int iCurPtBlock,
3447 POINTBLOCK *FirstPtBlock, QRegionPrivate *reg)
3451 bool needsExtend =
false;
3455 reg->extents.setLeft(INT_MAX);
3456 reg->extents.setRight(INT_MIN);
3457 reg->innerArea = -1;
3459 POINTBLOCK *CurPtBlock = FirstPtBlock;
3460 for (; numFullPtBlocks >= 0; --numFullPtBlocks) {
3462 int i = NUMPTSTOBUFFER >> 1;
3463 if (!numFullPtBlocks)
3464 i = iCurPtBlock >> 1;
3467 for (
QPoint *pts = CurPtBlock->pts;
i--; pts += 2) {
3468 const int width = pts[1].
x() - pts[0].
x();
3470 if (rowSize &&
row[rowSize-1].
x2 == pts[0].
x())
3471 row[rowSize-1].
x2 = pts[1].
x();
3473 row[rowSize++] = QRegionSpan(pts[0].
x(), pts[1].
x());
3477 QPoint *
next =
i ? &pts[2] : (numFullPtBlocks && iCurPtBlock ? CurPtBlock->next->pts :
nullptr);
3480 flushRow(
row.data(), pts[0].y(), rowSize, reg, &lastRow, &extendTo, &needsExtend);
3486 CurPtBlock = CurPtBlock->next;
3490 for (
int i = lastRow;
i < reg->rects.size(); ++
i)
3491 reg->rects[
i].setBottom(extendTo);
3494 reg->numRects = reg->rects.size();
3496 if (reg->numRects) {
3497 reg->extents.setTop(reg->rects[0].top());
3498 reg->extents.setBottom(reg->rects[lastRow].bottom());
3500 for (
int i = 0;
i < reg->rects.size(); ++
i)
3501 reg->updateInnerRect(reg->rects[
i]);
3503 reg->extents.setCoords(0, 0, 0, 0);
3516static QRegionPrivate *PolygonRegion(
const QPoint *Pts,
int Count,
int rule)
3521 QRegionPrivate *region;
3522 EdgeTableEntry *pAET;
3525 EdgeTableEntry *pWETE;
3528 EdgeTableEntry *pPrevAET;
3530 EdgeTableEntry *AET;
3531 EdgeTableEntry *pETEs;
3532 ScanLineListBlock SLLBlock;
3533 int fixWAET =
false;
3534 POINTBLOCK FirstPtBlock, *curPtBlock;
3535 FirstPtBlock.pts =
reinterpret_cast<QPoint *
>(FirstPtBlock.data);
3536 FirstPtBlock.next =
nullptr;
3537 POINTBLOCK *tmpPtBlock;
3538 int numFullPtBlocks = 0;
3542 region =
new QRegionPrivate;
3545 if (((Count == 4) ||
3546 ((Count == 5) && (Pts[4].
x() == Pts[0].
x()) && (Pts[4].
y() == Pts[0].
y())))
3547 && (((Pts[0].
y() == Pts[1].
y()) && (Pts[1].
x() == Pts[2].
x()) && (Pts[2].
y() == Pts[3].
y())
3548 && (Pts[3].
x() == Pts[0].
x())) || ((Pts[0].
x() == Pts[1].
x())
3549 && (Pts[1].
y() == Pts[2].
y()) && (Pts[2].
x() == Pts[3].
x())
3550 && (Pts[3].
y() == Pts[0].
y())))) {
3551 int x =
qMin(Pts[0].
x(), Pts[2].
x());
3552 region->extents.setLeft(
x);
3553 int y =
qMin(Pts[0].
y(), Pts[2].
y());
3554 region->extents.setTop(
y);
3555 region->extents.setWidth(
qMax(Pts[0].
x(), Pts[2].
x()) -
x);
3556 region->extents.setHeight(
qMax(Pts[0].
y(), Pts[2].
y()) -
y);
3557 if ((region->extents.left() <= region->extents.right()) &&
3558 (region->extents.top() <= region->extents.bottom())) {
3559 region->numRects = 1;
3560 region->innerRect = region->extents;
3561 region->innerArea = region->innerRect.width() * region->innerRect.height();
3566 if (!(pETEs =
static_cast<EdgeTableEntry *
>(malloc(
sizeof(EdgeTableEntry) * Count)))) {
3571 region->vectorize();
3573 AET =
new EdgeTableEntry;
3574 pts = FirstPtBlock.pts;
3575 CreateETandAET(Count, Pts, &ET, AET, pETEs, &SLLBlock);
3577 pSLL = ET.scanlines.next;
3578 curPtBlock = &FirstPtBlock;
3581 if (ET.ymax - ET.ymin > 100000) {
3584 qWarning(
"QRegion: creating region from big polygon failed...!");
3593 if (
rule == EvenOddRule) {
3597 for (
y = ET.ymin;
y < ET.ymax; ++
y) {
3603 if (pSLL &&
y == pSLL->scanline) {
3604 loadAET(AET, pSLL->edgelist);
3614 pts->
setX(pAET->bres.minor_axis);
3622 if (iPts == NUMPTSTOBUFFER) {
3623 tmpPtBlock = (POINTBLOCK *)malloc(
sizeof(POINTBLOCK));
3625 tmpPtBlock->pts =
reinterpret_cast<QPoint *
>(tmpPtBlock->data);
3626 curPtBlock->next = tmpPtBlock;
3627 curPtBlock = tmpPtBlock;
3628 pts = curPtBlock->pts;
3632 EVALUATEEDGEEVENODD(pAET, pPrevAET,
y)
3640 for (
y = ET.ymin;
y < ET.ymax; ++
y) {
3645 if (pSLL &&
y == pSLL->scanline) {
3646 loadAET(AET, pSLL->edgelist);
3662 if (pWETE == pAET) {
3663 pts->
setX(pAET->bres.minor_axis);
3671 if (iPts == NUMPTSTOBUFFER) {
3672 tmpPtBlock =
static_cast<POINTBLOCK *
>(malloc(
sizeof(POINTBLOCK)));
3673 tmpPtBlock->pts =
reinterpret_cast<QPoint *
>(tmpPtBlock->data);
3674 curPtBlock->next = tmpPtBlock;
3675 curPtBlock = tmpPtBlock;
3676 pts = curPtBlock->pts;
3680 pWETE = pWETE->nextWETE;
3682 EVALUATEEDGEWINDING(pAET, pPrevAET,
y, fixWAET)
3689 if (InsertionSort(AET) || fixWAET) {
3696 FreeStorage(SLLBlock.next);
3697 PtsToRegion(numFullPtBlocks, iPts, &FirstPtBlock, region);
3698 for (curPtBlock = FirstPtBlock.next; --numFullPtBlocks >= 0;) {
3699 tmpPtBlock = curPtBlock->next;
3701 curPtBlock = tmpPtBlock;
3707 FreeStorage(SLLBlock.next);
3708 PtsToRegion(numFullPtBlocks, iPts, &FirstPtBlock, region);
3709 for (curPtBlock = FirstPtBlock.next; --numFullPtBlocks >= 0;) {
3710 tmpPtBlock = curPtBlock->next;
3712 curPtBlock = tmpPtBlock;
3724 QRegionPrivate *region =
new QRegionPrivate;
3730 xr.setCoords(prev1, y, x-1, y); \
3731 UnionRectWithRegion(&xr, region, *region); \
3739 for (
y = 0;
y <
image.height(); ++
y) {
3744 for (
x = 0;
x <
w;) {
3746 if (
x >
w - 8 ||
byte!=all) {
3748 for (
int b = 8;
b > 0 &&
x <
w; --
b) {
3749 if (!(
byte & 0x01) == !all) {
3765 for (
int b = 8;
b > 0 &&
x <
w; --
b) {
3766 if (!(
byte & 0x80) == !all) {
3796 :
d(const_cast<QRegionData*>(&shared_empty))
3803 d =
const_cast<QRegionData*
>(&shared_empty);
3805 d =
new QRegionData;
3806 d->ref.initializeOwned();
3811 path.addEllipse(
r.x(),
r.y(),
r.width(),
r.height());
3813 d->qt_rgn = PolygonRegion(
a.constData(),
a.size(), EvenOddRule);
3824 d =
new QRegionData;
3825 d->ref.initializeOwned();
3828 d =
const_cast<QRegionData*
>(&shared_empty);
3831 d =
const_cast<QRegionData*
>(&shared_empty);
3845 d =
const_cast<QRegionData*
>(&shared_empty);
3847 d =
new QRegionData;
3848 d->ref.initializeOwned();
3849 d->qt_rgn = qt_bitmapToRegion(bm);
3853void QRegion::cleanUp(QRegion::QRegionData *
x)
3861 if (!d->ref.deref())
3869 if (!d->ref.deref())
3882 auto x = std::make_unique<QRegionData>();
3883 x->ref.initializeOwned();
3888 if (!
r.d->ref.deref())
3896 return d == &shared_empty || d->qt_rgn->numRects == 0;
3901 return d == &shared_empty || d->qt_rgn->numRects == 0;
3906 return PointInRegion(d->qt_rgn,
p.x(),
p.y());
3911 return RectInRegion(d->qt_rgn,
r.left(),
r.top(),
r.width(),
r.height()) != RectangleOut;
3918 if ((dx == 0 && dy == 0) || isEmptyHelper(d->qt_rgn))
3922 OffsetRegion(*d->qt_rgn, dx, dy);
3927 if (isEmptyHelper(d->qt_rgn))
3929 if (isEmptyHelper(
r.d->qt_rgn))
3934 if (d->qt_rgn->contains(*
r.d->qt_rgn)) {
3936 }
else if (
r.d->qt_rgn->contains(*d->qt_rgn)) {
3938 }
else if (d->qt_rgn->canAppend(
r.d->qt_rgn)) {
3941 result.d->qt_rgn->append(
r.d->qt_rgn);
3943 }
else if (d->qt_rgn->canPrepend(
r.d->qt_rgn)) {
3946 result.d->qt_rgn->prepend(
r.d->qt_rgn);
3948 }
else if (EqualRegion(d->qt_rgn,
r.d->qt_rgn)) {
3953 UnionRegion(d->qt_rgn,
r.d->qt_rgn, *
result.d->qt_rgn);
3960 if (isEmptyHelper(d->qt_rgn))
3962 if (isEmptyHelper(
r.d->qt_rgn))
3967 if (d->qt_rgn->contains(*
r.d->qt_rgn)) {
3969 }
else if (
r.d->qt_rgn->contains(*d->qt_rgn)) {
3971 }
else if (d->qt_rgn->canAppend(
r.d->qt_rgn)) {
3973 d->qt_rgn->append(
r.d->qt_rgn);
3975 }
else if (d->qt_rgn->canPrepend(
r.d->qt_rgn)) {
3977 d->qt_rgn->prepend(
r.d->qt_rgn);
3979 }
else if (EqualRegion(d->qt_rgn,
r.d->qt_rgn)) {
3983 UnionRegion(d->qt_rgn,
r.d->qt_rgn, *d->qt_rgn);
3990 if (isEmptyHelper(d->qt_rgn))
3995 if (d->qt_rgn->contains(
r)) {
3997 }
else if (d->qt_rgn->within(
r)) {
3999 }
else if (d->qt_rgn->numRects == 1 && d->qt_rgn->extents ==
r) {
4001 }
else if (d->qt_rgn->canAppend(&
r)) {
4006 }
else if (d->qt_rgn->canPrepend(&
r)) {
4009 result.d->qt_rgn->prepend(&
r);
4015 UnionRegion(d->qt_rgn, &rp, *
result.d->qt_rgn);
4022 if (isEmptyHelper(d->qt_rgn))
4027 if (d->qt_rgn->contains(
r)) {
4029 }
else if (d->qt_rgn->within(
r)) {
4031 }
else if (d->qt_rgn->canAppend(&
r)) {
4033 d->qt_rgn->append(&
r);
4035 }
else if (d->qt_rgn->canPrepend(&
r)) {
4037 d->qt_rgn->prepend(&
r);
4039 }
else if (d->qt_rgn->numRects == 1 && d->qt_rgn->extents ==
r) {
4044 UnionRegion(d->qt_rgn, &
p, *d->qt_rgn);
4051 if (isEmptyHelper(d->qt_rgn) || isEmptyHelper(
r.d->qt_rgn)
4052 || !EXTENTCHECK(&d->qt_rgn->extents, &
r.d->qt_rgn->extents))
4056 if (
r.d->qt_rgn->contains(*d->qt_rgn))
4060 if (d->qt_rgn->contains(*
r.d->qt_rgn))
4063 if (
r.d->qt_rgn->numRects == 1 && d->qt_rgn->numRects == 1) {
4064 const QRect rect = qt_rect_intersect_normalized(
r.d->qt_rgn->extents,
4065 d->qt_rgn->extents);
4067 }
else if (
r.d->qt_rgn->numRects == 1) {
4070 result.d->qt_rgn->intersect(
r.d->qt_rgn->extents);
4072 }
else if (d->qt_rgn->numRects == 1) {
4075 result.d->qt_rgn->intersect(d->qt_rgn->extents);
4081 miRegionOp(*
result.d->qt_rgn, d->qt_rgn,
r.d->qt_rgn, miIntersectO,
nullptr,
nullptr);
4090 miSetExtents(*
result.d->qt_rgn);
4096 if (isEmptyHelper(d->qt_rgn) ||
r.isEmpty()
4097 || !EXTENTCHECK(&d->qt_rgn->extents, &
r))
4101 if (d->qt_rgn->within(
r))
4105 if (d->qt_rgn->contains(
r))
4108 if (d->qt_rgn->numRects == 1) {
4109 const QRect rect = qt_rect_intersect_normalized(d->qt_rgn->extents,
4116 result.d->qt_rgn->intersect(
r);
4122 if (isEmptyHelper(d->qt_rgn) || isEmptyHelper(
r.d->qt_rgn))
4124 if (
r.d->qt_rgn->contains(*d->qt_rgn))
4126 if (!EXTENTCHECK(&d->qt_rgn->extents, &
r.d->qt_rgn->extents))
4128 if (d ==
r.d || EqualRegion(d->qt_rgn,
r.d->qt_rgn))
4131#ifdef QT_REGION_DEBUG
4132 d->qt_rgn->selfTest();
4133 r.d->qt_rgn->selfTest();
4138 SubtractRegion(d->qt_rgn,
r.d->qt_rgn, *
result.d->qt_rgn);
4139#ifdef QT_REGION_DEBUG
4140 result.d->qt_rgn->selfTest();
4147 if (isEmptyHelper(d->qt_rgn)) {
4149 }
else if (isEmptyHelper(
r.d->qt_rgn)) {
4151 }
else if (!EXTENTCHECK(&d->qt_rgn->extents, &
r.d->qt_rgn->extents)) {
4153 }
else if (d ==
r.d || EqualRegion(d->qt_rgn,
r.d->qt_rgn)) {
4158 XorRegion(d->qt_rgn,
r.d->qt_rgn, *
result.d->qt_rgn);
4167 return d->qt_rgn->extents;
4177 if (isEmptyHelper(region.d->qt_rgn) || !
rect.isValid())
4181 static bool guard =
false;
4185 QRegion inner = region.d->qt_rgn->innerRect;
4186 Q_ASSERT((inner - region).isEmpty());
4190 for (
int i = 0;
i < region.d->qt_rgn->numRects; ++
i) {
4191 const QRect r = region.d->qt_rgn->rects.at(
i);
4192 if (
r.width() *
r.height() > maxArea)
4193 maxArea =
r.width() *
r.height();
4196 if (maxArea > region.d->qt_rgn->innerArea) {
4197 qDebug() <<
"not largest rectangle" << region << region.d->qt_rgn->innerRect;
4199 Q_ASSERT(maxArea <= region.d->qt_rgn->innerArea);
4202 const QRect r1 = region.d->qt_rgn->innerRect;
4209 return d->qt_rgn ? d->qt_rgn->begin() :
nullptr;
4214 return d->qt_rgn ? d->qt_rgn->end() :
nullptr;
4225 d->qt_rgn->numRects =
num;
4227 d->qt_rgn->extents = *rects;
4228 d->qt_rgn->innerRect = *rects;
4230 d->qt_rgn->rects.resize(
num);
4236 for (
int i = 0;
i <
num; ++
i) {
4238 d->qt_rgn->rects[
i] =
rect;
4243 d->qt_rgn->updateInnerRect(
rect);
4251 return (d->qt_rgn ? d->qt_rgn->numRects : 0);
4265 return EqualRegion(d->qt_rgn,
r.d->qt_rgn);
4270 if (isEmptyHelper(d->qt_rgn) ||
rect.isNull())
4276 if (d->qt_rgn->numRects == 1)
4289#if defined(Q_OS_WIN) || defined(Q_QDOC)
4291static inline HRGN qt_RectToHRGN(
const QRect &rc)
4301HRGN QRegion::toHRGN()
const
4307 HRGN resultRgn =
nullptr;
4308 const auto rects =
begin();
4309 resultRgn = qt_RectToHRGN(rects[0]);
4310 for (
int i = 1;
i <
size; ++
i) {
4311 HRGN tmpRgn = qt_RectToHRGN(rects[
i]);
4312 int err = CombineRgn(resultRgn, resultRgn, tmpRgn, RGN_OR);
4314 qWarning(
"Error combining HRGNs.");
4315 DeleteObject(tmpRgn);
4325QRegion QRegion::fromHRGN(HRGN hrgn)
4327 DWORD regionDataSize = GetRegionData(hrgn, 0,
nullptr);
4328 if (regionDataSize == 0)
4331 auto regionData =
reinterpret_cast<LPRGNDATA
>(malloc(regionDataSize));
4336 if (GetRegionData(hrgn, regionDataSize, regionData) == regionDataSize) {
4337 auto pRect =
reinterpret_cast<LPRECT
>(regionData->Buffer);
4338 for (DWORD
i = 0;
i < regionData->rdh.nCount; ++
i)
\inmodule QtCore\reentrant
ByteOrder
The byte order used for reading/writing the data.
qsizetype size() const noexcept
const_pointer constData() const noexcept
const_reference at(qsizetype i) const noexcept
void prepend(rvalue_ref t)
void resize(qsizetype size)
bool isNull() const
Returns true if this is a null pixmap; otherwise returns false.
\inmodule QtCore\reentrant
constexpr int x() const noexcept
Returns the x coordinate of this point.
constexpr void setY(int y) noexcept
Sets the y coordinate of this point to the given y coordinate.
constexpr int y() const noexcept
Returns the y coordinate of this point.
constexpr void setX(int x) noexcept
Sets the x coordinate of this point to the given x coordinate.
The QPolygon class provides a list of points using integer precision.
\inmodule QtCore\reentrant
constexpr bool isEmpty() const noexcept
Returns true if the rectangle is empty, otherwise returns false.
bool intersects(const QRect &r) const noexcept
Returns true if this rectangle intersects with the given rectangle (i.e., there is at least one pixel...
constexpr int height() const noexcept
Returns the height of the rectangle.
QRect intersected(const QRect &other) const noexcept
constexpr int bottom() const noexcept
Returns the y-coordinate of the rectangle's bottom edge.
constexpr void setRight(int pos) noexcept
Sets the right edge of the rectangle to the given x coordinate.
constexpr int top() const noexcept
Returns the y-coordinate of the rectangle's top edge.
constexpr void setBottom(int pos) noexcept
Sets the bottom edge of the rectangle to the given y coordinate.
constexpr void setLeft(int pos) noexcept
Sets the left edge of the rectangle to the given x coordinate.
constexpr int left() const noexcept
Returns the x-coordinate of the rectangle's left edge.
constexpr void translate(int dx, int dy) noexcept
Moves the rectangle dx along the x axis and dy along the y axis, relative to the current position.
constexpr void setCoords(int x1, int y1, int x2, int y2) noexcept
Sets the coordinates of the rectangle's top-left corner to (x1, y1), and the coordinates of its botto...
constexpr int width() const noexcept
Returns the width of the rectangle.
QRect united(const QRect &other) const noexcept
constexpr int y() const noexcept
Returns the y-coordinate of the rectangle's top edge.
constexpr int right() const noexcept
Returns the x-coordinate of the rectangle's right edge.
constexpr void setTop(int pos) noexcept
Sets the top edge of the rectangle to the given y coordinate.
The QRegion class specifies a clip region for a painter.
QRegion operator&(const QRegion &r) const
Applies the intersected() function to this region and r.
QRegion united(const QRegion &r) const
QRegion & operator^=(const QRegion &r)
Applies the xored() function to this region and r and assigns the result to this region.
QRect boundingRect() const noexcept
Returns the bounding rectangle of this region.
int rectCount() const noexcept
QRegion & operator|=(const QRegion &r)
Applies the united() function to this region and r and assigns the result to this region.
QRegion & operator=(const QRegion &)
Assigns r to this region and returns a reference to the region.
QRegion & operator+=(const QRegion &r)
Applies the united() function to this region and r and assigns the result to this region.
void translate(int dx, int dy)
Translates (moves) the region dx along the X axis and dy along the Y axis.
void setRects(const QRect *rect, int num)
Sets the region using the array of rectangles specified by rects and number.
bool intersects(const QRegion &r) const
bool contains(const QPoint &p) const
Returns true if the region contains the point p; otherwise returns false.
const_iterator end() const noexcept
QRegion()
Constructs an empty region.
bool isEmpty() const
Returns true if the region is empty; otherwise returns false.
const_iterator begin() const noexcept
QRegion & operator&=(const QRegion &r)
Applies the intersected() function to this region and r and assigns the result to this region.
friend struct QRegionPrivate
QRegion operator^(const QRegion &r) const
Applies the xored() function to this region and r.
QRegion xored(const QRegion &r) const
QRegion intersected(const QRegion &r) const
RegionType
Specifies the shape of the region to be created.
bool operator==(const QRegion &r) const
Returns true if the region is equal to r; otherwise returns false.
QRegion subtracted(const QRegion &r) const
QRegion & operator-=(const QRegion &r)
Applies the subtracted() function to this region and r and assigns the result to this region.
QRegion operator|(const QRegion &r) const
Applies the united() function to this region and r.
QRegion translated(int dx, int dy) const
QRegion operator-(const QRegion &r) const
Applies the subtracted() function to this region and r.
QRegion operator+(const QRegion &r) const
Applies the united() function to this region and r.
static auto fromValue(T &&value) noexcept(std::is_nothrow_copy_constructible_v< T > &&Private::CanUseInternalSpace< T >) -> std::enable_if_t< std::conjunction_v< std::is_copy_constructible< T >, std::is_destructible< T > >, QVariant >
while(i.hasNext()) QString s
list append(new Employee("Blackpool", "Stephen"))
QSet< QString >::iterator it
Combined button and popup list for selecting options.
static void formatQRect(QDebug &debug, const Rect &rect)
void all(std::vector< emscripten::val > promises, PromiseCallbacks callbacks)
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage void
DBusConnection const char * rule
static int area(const QSize &s)
constexpr const T & qMin(const T &a, const T &b)
constexpr const T & qMax(const T &a, const T &b)
static bool contains(const QJsonArray &haystack, unsigned needle)
GLboolean GLboolean GLboolean b
GLint GLint GLint GLint GLint x
[0]
GLfloat GLfloat GLfloat w
[0]
GLint GLsizei GLsizei height
GLboolean GLboolean GLboolean GLboolean a
[7]
GLuint GLfloat GLfloat GLfloat GLfloat y1
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint GLfloat GLfloat GLfloat x1
GLdouble GLdouble GLdouble GLdouble top
GLenum GLenum GLsizei count
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLuint GLintptr offset
GLfloat GLfloat GLfloat GLfloat h
GLsizei GLsizei GLchar * source
GLfixed GLfixed GLfixed y2
GLsizei GLfixed GLfixed GLfixed GLfixed const GLubyte * bitmap
GLsizei const GLchar *const * path
GLenum GLenum GLsizei void * row
static void setCoords(GLfloat *coords, const QOpenGLRect &rect)
#define ERROR(description)
#define Q_REFCOUNT_INITIALIZE_STATIC
Q_GUI_EXPORT QPainterPath qt_regionToPath(const QRegion ®ion)
#define QRGN_SETPTARRAY_ALT
QDebug operator<<(QDebug s, const QRegion &r)
bool rect_intersects(const QRect &r1, const QRect &r2)
#define QRGN_SETPTARRAY_WIND
QtPrivate::QRegularExpressionMatchIteratorRangeBasedForIterator begin(const QRegularExpressionMatchIterator &iterator)
#define QT_BEGIN_INCLUDE_NAMESPACE
#define QT_END_INCLUDE_NAMESPACE
#define Q_DECLARE_TYPEINFO(TYPE, FLAGS)
Q_CHECK_PTR(a=new int[80])
if(qFloatDistance(a, b)<(1<< 7))
[0]
connect(quitButton, &QPushButton::clicked, &app, &QCoreApplication::quit, Qt::QueuedConnection)