52 #include <private/qdebug_p.h>
210 void QRegion::detach()
212 if (d->ref.isShared())
217 #define QRGN_SETRECT 1
218 #define QRGN_SETELLIPSE 2
219 #define QRGN_SETPTARRAY_ALT 3
220 #define QRGN_SETPTARRAY_WIND 4
221 #define QRGN_TRANSLATE 5
226 #define QRGN_RECTS 10
229 #ifndef QT_NO_DATASTREAM
246 s.setByteOrder(byteOrder);
253 if (
s.version() == 1) {
262 qWarning(
"QRegion::exec: Internal error");
293 rgn =
r1.subtracted(
r2);
304 for (
int i=0; i < static_cast<int>(
n);
i++) {
351 auto b =
r.begin(),
e =
r.end();
356 if (
s.version() == 1) {
357 for (
auto i =
size - 1;
i > 0; --
i) {
387 r.exec(
b,
s.version(),
s.byteOrder());
392 #ifndef QT_NO_DEBUG_STREAM
400 }
else if (
r.isEmpty()) {
403 const int count =
r.rectCount();
405 s <<
"size=" <<
count <<
", bounds=(";
406 QtDebugUtils::formatQRect(
s,
r.boundingRect());
414 QtDebugUtils::formatQRect(
s,
rect);
500 {
return *
this = *
this |
r; }
518 #if !defined (Q_OS_UNIX) && !defined (Q_OS_WIN)
535 {
return *
this = *
this &
r; }
541 #if defined (Q_OS_UNIX) || defined (Q_OS_WIN)
544 return *
this = *
this &
r;
563 {
return *
this = *
this -
r; }
573 {
return *
this = *
this ^
r; }
632 ret.translate(dx, dy);
659 for (
const QRect &myRect : *
this)
660 for (
const QRect &otherRect : region)
675 #if !defined (Q_OS_UNIX) && !defined (Q_OS_WIN) || defined(Q_CLANG_QDOC)
946 return qMin(point.x(),
next->point.x());
951 return qMax(point.x(),
next->point.x());
954 bool overlaps(
const Segment &
other)
const
964 horizontal = (point.y() ==
other.point.y());
967 void merge(Segment &
other)
971 Segment *oprev =
other.prev;
981 Segment *onext =
other.next;
998 void mergeSegments(Segment *
a,
int na, Segment *
b,
int nb)
1003 while (
i != na &&
j != nb) {
1006 const int ra = sa.right();
1007 const int rb = sb.right();
1008 if (sa.overlaps(sb))
1018 path.moveTo(current->point);
1020 current->added =
true;
1022 Segment *last = current;
1023 current = current->next;
1025 if (current->horizontal != last->horizontal)
1026 path.lineTo(current->point);
1027 current->added =
true;
1029 current = current->next;
1052 const auto end = region.
end();
1057 int lastRowSegmentCount = 0;
1058 Segment *lastRowSegments =
nullptr;
1060 int lastSegment = 0;
1063 const int y =
rect[0].y();
1076 for (
int j = 0;
j < 4; ++
j)
1080 if (lastRowSegments && lastY ==
y)
1081 mergeSegments(lastRowSegments, lastRowSegmentCount, &
segments[lastSegment],
count);
1084 lastRowSegmentCount =
count;
1085 lastSegment += 4 *
count;
1086 lastY =
y +
rect[0].height();
1090 for (
int i = 0;
i < lastSegment; ++
i) {
1099 #if defined(Q_OS_UNIX) || defined(Q_OS_WIN)
1106 struct QRegionPrivate {
1113 inline QRegionPrivate() : numRects(0), innerArea(-1) {}
1114 inline QRegionPrivate(
const QRect &
r)
1122 void intersect(
const QRect &
r);
1128 inline bool contains(
const QRegionPrivate &
r)
const {
1141 inline bool within(
const QRect &r1)
const {
1147 inline void updateInnerRect(
const QRect &
rect) {
1148 const int area =
rect.width() *
rect.height();
1149 if (area > innerArea) {
1155 inline void vectorize() {
1156 if (numRects == 1) {
1164 {
return numRects == 1 ? &extents : rects.
data(); }
1167 {
return begin() + numRects; }
1170 void append(
const QRegionPrivate *
r);
1172 void prepend(
const QRegionPrivate *
r);
1173 inline bool canAppend(
const QRect *
r)
const;
1174 inline bool canAppend(
const QRegionPrivate *
r)
const;
1175 inline bool canPrepend(
const QRect *
r)
const;
1176 inline bool canPrepend(
const QRegionPrivate *
r)
const;
1181 const QRect *nextToTop,
1182 const QRect *nextToBottom);
1184 const QRect *nextToBottom,
1185 const QRect *nextToTop);
1187 #ifdef QT_REGION_DEBUG
1188 void selfTest()
const;
1192 static inline bool isEmptyHelper(
const QRegionPrivate *preg)
1194 return !preg || preg->numRects == 0;
1201 &&
right->left() <= (
left->right() + 1));
1213 updateInnerRect(*
left);
1223 updateInnerRect(*
right);
1230 const QRect *nextToTop,
1231 const QRect *nextToBottom)
1233 if (nextToTop && nextToTop->
y() ==
top->y())
1235 if (nextToBottom && nextToBottom->
y() ==
bottom->y())
1238 return ((
top->bottom() >= (
bottom->top() - 1))
1244 const QRect *nextToTop,
1245 const QRect *nextToBottom)
1247 if (canMergeFromBelow(
top,
bottom, nextToTop, nextToBottom)) {
1249 updateInnerRect(*
top);
1256 const QRect *nextToBottom,
1257 const QRect *nextToTop)
1259 if (canMergeFromBelow(
top,
bottom, nextToTop, nextToBottom)) {
1261 updateInnerRect(*
bottom);
1267 static inline QRect qt_rect_intersect_normalized(
const QRect &r1,
1278 void QRegionPrivate::intersect(
const QRect &
rect)
1283 #ifdef QT_REGION_DEBUG
1289 innerRect =
QRect();
1297 *dest = qt_rect_intersect_normalized(*
src++,
r);
1301 if (numRects == 0) {
1310 const QRect *nextToLast = (numRects > 1 ? dest - 2 :
nullptr);
1313 if (canMergeFromBelow(dest - 1, dest, nextToLast,
nullptr)) {
1314 if (!
n ||
src->y() != dest->
y() ||
src->left() >
r.right()) {
1315 QRect *prev = dest - 1;
1317 updateInnerRect(*prev);
1322 updateInnerRect(*dest);
1326 #ifdef QT_REGION_DEBUG
1335 QRect *myLast = (numRects == 1 ? &extents : rects.
data() + (numRects - 1));
1336 if (mergeFromRight(myLast,
r)) {
1338 const QRect *nextToTop = (numRects > 2 ? myLast - 2 :
nullptr);
1339 if (mergeFromBelow(myLast - 1, myLast, nextToTop,
nullptr))
1342 }
else if (mergeFromBelow(myLast,
r, (numRects > 1 ? myLast - 1 :
nullptr),
nullptr)) {
1347 updateInnerRect(*
r);
1348 if (rects.
size() < numRects)
1350 rects[numRects - 1] = *
r;
1353 qMin(extents.
top(),
r->top()),
1354 qMax(extents.
right(),
r->right()),
1355 qMax(extents.
bottom(),
r->bottom()));
1357 #ifdef QT_REGION_DEBUG
1366 if (
r->numRects == 1) {
1373 QRect *destRect = rects.
data() + numRects;
1374 const QRect *srcRect =
r->rects.constData();
1375 int numAppend =
r->numRects;
1379 const QRect *rFirst = srcRect;
1380 QRect *myLast = destRect - 1;
1381 const QRect *nextToLast = (numRects > 1 ? myLast - 1 :
nullptr);
1382 if (mergeFromRight(myLast, rFirst)) {
1385 const QRect *rNextToFirst = (numAppend > 1 ? rFirst + 2 :
nullptr);
1386 if (mergeFromBelow(myLast, rFirst + 1, nextToLast, rNextToFirst)) {
1391 nextToLast = (numRects > 2 ? myLast - 2 :
nullptr);
1392 rNextToFirst = (numAppend > 0 ? srcRect :
nullptr);
1393 if (mergeFromBelow(myLast - 1, myLast, nextToLast, rNextToFirst)) {
1398 }
else if (mergeFromBelow(myLast, rFirst, nextToLast, rFirst + 1)) {
1405 if (numAppend > 0) {
1406 const int newNumRects = numRects + numAppend;
1407 if (newNumRects > rects.
size()) {
1408 rects.
resize(newNumRects);
1409 destRect = rects.
data() + numRects;
1411 memcpy(destRect, srcRect, numAppend *
sizeof(
QRect));
1413 numRects = newNumRects;
1417 if (innerArea < r->innerArea) {
1418 innerArea =
r->innerArea;
1419 innerRect =
r->innerRect;
1423 destRect = &extents;
1424 srcRect = &
r->extents;
1426 qMin(destRect->
top(), srcRect->
top()),
1430 #ifdef QT_REGION_DEBUG
1439 if (
r->numRects == 1) {
1446 int numPrepend =
r->numRects;
1452 const QRect *nextToFirst = (numRects > 1 ? myFirst + 1 :
nullptr);
1453 const QRect *rLast =
r->rects.constData() +
r->numRects - 1;
1454 const QRect *rNextToLast = (
r->numRects > 1 ? rLast - 1 :
nullptr);
1455 if (mergeFromLeft(myFirst, rLast)) {
1458 rNextToLast = (numPrepend > 1 ? rLast - 1 :
nullptr);
1459 if (mergeFromAbove(myFirst, rLast, nextToFirst, rNextToLast)) {
1464 nextToFirst = (numRects > 2? myFirst + 2 :
nullptr);
1465 rNextToLast = (numPrepend > 0 ? rLast :
nullptr);
1466 if (mergeFromAbove(myFirst + 1, myFirst, nextToFirst, rNextToLast)) {
1471 }
else if (mergeFromAbove(myFirst, rLast, nextToFirst, rNextToLast)) {
1476 if (numPrepend > 0) {
1477 const int newNumRects = numRects + numPrepend;
1478 if (newNumRects > rects.
size())
1479 rects.
resize(newNumRects);
1483 numRects *
sizeof(
QRect));
1486 memcpy(rects.
data(),
r->rects.constData(), numPrepend *
sizeof(
QRect));
1488 numRects = newNumRects;
1492 if (innerArea < r->innerArea) {
1493 innerArea =
r->innerArea;
1494 innerRect =
r->innerRect;
1499 qMin(extents.
top(),
r->extents.top()),
1500 qMax(extents.
right(),
r->extents.right()),
1501 qMax(extents.
bottom(),
r->extents.bottom()));
1503 #ifdef QT_REGION_DEBUG
1512 QRect *myFirst = (numRects == 1 ? &extents : rects.
data());
1513 if (mergeFromLeft(myFirst,
r)) {
1515 const QRect *nextToFirst = (numRects > 2 ? myFirst + 2 :
nullptr);
1516 if (mergeFromAbove(myFirst + 1, myFirst, nextToFirst,
nullptr)) {
1519 numRects *
sizeof(
QRect));
1522 }
else if (mergeFromAbove(myFirst,
r, (numRects > 1 ? myFirst + 1 :
nullptr),
nullptr)) {
1527 updateInnerRect(*
r);
1531 qMin(extents.
top(),
r->top()),
1532 qMax(extents.
right(),
r->right()),
1533 qMax(extents.
bottom(),
r->bottom()));
1535 #ifdef QT_REGION_DEBUG
1540 bool QRegionPrivate::canAppend(
const QRect *
r)
const
1544 const QRect *myLast = (numRects == 1) ? &extents : (rects.
constData() + (numRects - 1));
1545 if (
r->top() > myLast->
bottom())
1547 if (
r->top() == myLast->
top()
1548 &&
r->height() == myLast->
height()
1549 &&
r->left() > myLast->
right())
1557 bool QRegionPrivate::canAppend(
const QRegionPrivate *
r)
const
1559 return canAppend(
r->numRects == 1 ? &
r->extents :
r->rects.constData());
1562 bool QRegionPrivate::canPrepend(
const QRect *
r)
const
1566 const QRect *myFirst = (numRects == 1) ? &extents : rects.
constData();
1567 if (
r->bottom() < myFirst->
top())
1569 if (
r->top() == myFirst->
top()
1570 &&
r->height() == myFirst->
height()
1571 &&
r->right() < myFirst->
left())
1579 bool QRegionPrivate::canPrepend(
const QRegionPrivate *
r)
const
1581 return canPrepend(
r->numRects == 1 ? &
r->extents :
r->rects.constData() +
r->numRects - 1);
1584 #ifdef QT_REGION_DEBUG
1585 void QRegionPrivate::selfTest()
const
1587 if (numRects == 0) {
1595 if (numRects == 1) {
1601 for (
int i = 0;
i < numRects; ++
i) {
1603 if ((
r.width() *
r.height()) > innerArea)
1604 qDebug() <<
"selfTest(): innerRect" << innerRect <<
'<' <<
r;
1608 for (
int i = 1;
i < numRects; ++
i) {
1611 if (
r2.
y() ==
r.y()) {
1622 static QRegionPrivate qrp;
1625 typedef void (*OverlapFunc)(QRegionPrivate &dest,
const QRect *
r1,
const QRect *r1End,
1627 typedef void (*NonOverlapFunc)(QRegionPrivate &dest,
const QRect *
r,
const QRect *rEnd,
1630 static bool EqualRegion(
const QRegionPrivate *r1,
const QRegionPrivate *r2);
1631 static void UnionRegion(
const QRegionPrivate *
reg1,
const QRegionPrivate *
reg2, QRegionPrivate &dest);
1632 static void miRegionOp(QRegionPrivate &dest,
const QRegionPrivate *
reg1,
const QRegionPrivate *
reg2,
1633 OverlapFunc overlapFunc, NonOverlapFunc nonOverlap1Func,
1634 NonOverlapFunc nonOverlap2Func);
1636 #define RectangleOut 0
1637 #define RectangleIn 1
1638 #define RectanglePart 2
1639 #define EvenOddRule 0
1640 #define WindingRule 1
1703 #define EXTENTCHECK(r1, r2) \
1704 ((r1)->right() >= (r2)->left() && \
1705 (r1)->left() <= (r2)->right() && \
1706 (r1)->bottom() >= (r2)->top() && \
1707 (r1)->top() <= (r2)->bottom())
1712 #define EXTENTS(r,idRect){\
1713 if((r)->left() < (idRect)->extents.left())\
1714 (idRect)->extents.setLeft((r)->left());\
1715 if((r)->top() < (idRect)->extents.top())\
1716 (idRect)->extents.setTop((r)->top());\
1717 if((r)->right() > (idRect)->extents.right())\
1718 (idRect)->extents.setRight((r)->right());\
1719 if((r)->bottom() > (idRect)->extents.bottom())\
1720 (idRect)->extents.setBottom((r)->bottom());\
1726 #define MEMCHECK(dest, rect, firstrect){\
1727 if ((dest).numRects >= ((dest).rects.size()-1)){\
1728 firstrect.resize(firstrect.size() * 2); \
1729 (rect) = (firstrect).data() + (dest).numRects;\
1738 #define NUMPTSTOBUFFER 200
1744 typedef struct _POINTBLOCK {
1747 struct _POINTBLOCK *
next;
1829 static void UnionRectWithRegion(
const QRect *
rect,
const QRegionPrivate *
source,
1830 QRegionPrivate &dest)
1832 if (
rect->isEmpty())
1837 if (dest.numRects == 0) {
1838 dest = QRegionPrivate(*
rect);
1839 }
else if (dest.canAppend(
rect)) {
1842 QRegionPrivate
p(*
rect);
1843 UnionRegion(&
p,
source, dest);
1862 static void miSetExtents(QRegionPrivate &dest)
1869 dest.innerArea = -1;
1870 if (dest.numRects == 0) {
1871 dest.extents.setCoords(0, 0, -1, -1);
1875 pExtents = &dest.extents;
1876 if (dest.rects.isEmpty())
1877 pBox = &dest.extents;
1879 pBox = dest.rects.constData();
1880 pBoxEnd = pBox + dest.numRects - 1;
1895 while (pBox <= pBoxEnd) {
1896 if (pBox->
left() < pExtents->
left())
1900 dest.updateInnerRect(*pBox);
1911 static void OffsetRegion(QRegionPrivate ®ion,
int x,
int y)
1913 if (region.rects.size()) {
1914 QRect *pbox = region.rects.data();
1915 int nbox = region.numRects;
1923 region.innerRect.translate(
x,
y);
1942 static void miIntersectO(QRegionPrivate &dest,
const QRect *r1,
const QRect *r1End,
1949 pNextRect = dest.rects.data() + dest.numRects;
1951 while (r1 != r1End && r2 != r2End) {
1964 MEMCHECK(dest, pNextRect, dest.rects)
1965 pNextRect->setCoords(
x1,
y1,
x2,
y2);
2007 static int miCoalesce(QRegionPrivate &dest,
int prevStart,
int curStart)
2015 QRect *rData = dest.rects.data();
2017 pRegEnd = rData + dest.numRects;
2019 pPrevBox = rData + prevStart;
2020 prevNumRects = curStart - prevStart;
2027 pCurBox = rData + curStart;
2028 bandY1 = pCurBox->
top();
2029 for (curNumRects = 0; pCurBox != pRegEnd && pCurBox->
top() == bandY1; ++curNumRects) {
2033 if (pCurBox != pRegEnd) {
2041 while ((pRegEnd - 1)->
top() == pRegEnd->
top())
2043 curStart = pRegEnd - rData;
2044 pRegEnd = rData + dest.numRects;
2047 if (curNumRects == prevNumRects && curNumRects != 0) {
2048 pCurBox -= curNumRects;
2053 if (pPrevBox->
bottom() == pCurBox->
top() - 1) {
2068 }
while (prevNumRects != 0);
2070 dest.numRects -= curNumRects;
2071 pCurBox -= curNumRects;
2072 pPrevBox -= curNumRects;
2081 dest.updateInnerRect(*pPrevBox);
2085 }
while (curNumRects != 0);
2097 if (pCurBox == pRegEnd) {
2098 curStart = prevStart;
2101 *pPrevBox++ = *pCurBox++;
2102 dest.updateInnerRect(*pPrevBox);
2103 }
while (pCurBox != pRegEnd);
2136 static void miRegionOp(QRegionPrivate &dest,
2137 const QRegionPrivate *
reg1,
const QRegionPrivate *
reg2,
2138 OverlapFunc overlapFunc, NonOverlapFunc nonOverlap1Func,
2139 NonOverlapFunc nonOverlap2Func)
2149 const QRect *r1BandEnd;
2150 const QRect *r2BandEnd;
2161 if (
reg1->numRects == 1)
2164 r1 =
reg1->rects.constData();
2165 if (
reg2->numRects == 1)
2168 r2 =
reg2->rects.constData();
2170 r1End =
r1 +
reg1->numRects;
2171 r2End =
r2 +
reg2->numRects;
2193 dest.rects.resize(qMax(
reg1->numRects,
reg2->numRects) * 2);
2208 if (
reg1->extents.top() <
reg2->extents.top())
2209 ybot =
reg1->extents.top() - 1;
2211 ybot =
reg2->extents.top() - 1;
2225 curBand = dest.numRects;
2235 while (r1BandEnd != r1End && r1BandEnd->
top() ==
r1->
top())
2239 while (r2BandEnd != r2End && r2BandEnd->
top() ==
r2->
top())
2254 if (nonOverlap1Func !=
nullptr && bot >=
top)
2255 (*nonOverlap1Func)(dest,
r1, r1BandEnd,
top, bot);
2261 if (nonOverlap2Func !=
nullptr && bot >=
top)
2262 (*nonOverlap2Func)(dest,
r2, r2BandEnd,
top, bot);
2274 if (dest.numRects != curBand)
2275 prevBand = miCoalesce(dest, prevBand, curBand);
2282 curBand = dest.numRects;
2284 (*overlapFunc)(dest,
r1, r1BandEnd,
r2, r2BandEnd, ytop, ybot);
2286 if (dest.numRects != curBand)
2287 prevBand = miCoalesce(dest, prevBand, curBand);
2297 }
while (r1 != r1End && r2 != r2End);
2302 curBand = dest.numRects;
2304 if (nonOverlap1Func !=
nullptr) {
2307 while (r1BandEnd < r1End && r1BandEnd->
top() ==
r1->
top())
2309 (*nonOverlap1Func)(dest,
r1, r1BandEnd, qMax(
r1->
top(), ybot + 1),
r1->
bottom());
2311 }
while (r1 != r1End);
2313 }
else if ((r2 != r2End) && (nonOverlap2Func !=
nullptr)) {
2316 while (r2BandEnd < r2End && r2BandEnd->
top() ==
r2->
top())
2318 (*nonOverlap2Func)(dest,
r2, r2BandEnd, qMax(
r2->
top(), ybot + 1),
r2->
bottom());
2320 }
while (r2 != r2End);
2323 if (dest.numRects != curBand)
2324 (
void)miCoalesce(dest, prevBand, curBand);
2334 if (qMax(4, dest.numRects) < (dest.rects.size() >> 1))
2335 dest.rects.resize(dest.numRects);
2359 static void miUnionNonO(QRegionPrivate &dest,
const QRect *
r,
const QRect *rEnd,
2364 pNextRect = dest.rects.data() + dest.numRects;
2370 MEMCHECK(dest, pNextRect, dest.rects)
2400 pNextRect = dest.rects.data() + dest.numRects;
2402 #define MERGERECT(r) \
2403 if ((dest.numRects != 0) && \
2404 (pNextRect[-1].top() == y1) && \
2405 (pNextRect[-1].bottom() == y2) && \
2406 (pNextRect[-1].right() >= r->left()-1)) { \
2407 if (pNextRect[-1].right() < r->right()) { \
2408 pNextRect[-1].setRight(r->right()); \
2409 dest.updateInnerRect(pNextRect[-1]); \
2410 Q_ASSERT(pNextRect[-1].left() <= pNextRect[-1].right()); \
2413 MEMCHECK(dest, pNextRect, dest.rects) \
2414 pNextRect->setCoords(r->left(), y1, r->right(), y2); \
2415 dest.updateInnerRect(*pNextRect); \
2422 while (r1 != r1End && r2 != r2End) {
2433 }
while (r1 != r1End);
2435 while (r2 != r2End) {
2441 static void UnionRegion(
const QRegionPrivate *
reg1,
const QRegionPrivate *
reg2, QRegionPrivate &dest)
2450 if (
reg1->innerArea >
reg2->innerArea) {
2451 dest.innerArea =
reg1->innerArea;
2452 dest.innerRect =
reg1->innerRect;
2454 dest.innerArea =
reg2->innerArea;
2455 dest.innerRect =
reg2->innerRect;
2457 miRegionOp(dest,
reg1,
reg2, miUnionO, miUnionNonO, miUnionNonO);
2459 dest.extents.setCoords(qMin(
reg1->extents.left(),
reg2->extents.left()),
2460 qMin(
reg1->extents.top(),
reg2->extents.top()),
2461 qMax(
reg1->extents.right(),
reg2->extents.right()),
2462 qMax(
reg1->extents.bottom(),
reg2->extents.bottom()));
2484 static void miSubtractNonO1(QRegionPrivate &dest,
const QRect *
r,
2489 pNextRect = dest.rects.data() + dest.numRects;
2495 MEMCHECK(dest, pNextRect, dest.rects)
2527 pNextRect = dest.rects.data() + dest.numRects;
2529 while (r1 != r1End && r2 != r2End) {
2558 MEMCHECK(dest, pNextRect, dest.rects)
2559 pNextRect->setCoords(
x1,
y1, r2->
left() - 1,
y2);
2580 MEMCHECK(dest, pNextRect, dest.rects)
2594 while (r1 != r1End) {
2596 MEMCHECK(dest, pNextRect, dest.rects)
2619 static
void SubtractRegion(QRegionPrivate *regM, QRegionPrivate *regS,
2620 QRegionPrivate &dest)
2624 Q_ASSERT(EXTENTCHECK(®M->extents, ®S->extents));
2626 Q_ASSERT(!EqualRegion(regM, regS));
2628 miRegionOp(dest, regM, regS, miSubtractO, miSubtractNonO1,
nullptr);
2640 static void XorRegion(QRegionPrivate *sra, QRegionPrivate *
srb, QRegionPrivate &dest)
2642 Q_ASSERT(!isEmptyHelper(sra) && !isEmptyHelper(
srb));
2643 Q_ASSERT(EXTENTCHECK(&sra->extents, &
srb->extents));
2646 QRegionPrivate tra, trb;
2648 if (!
srb->contains(*sra))
2649 SubtractRegion(sra,
srb, tra);
2650 if (!sra->contains(*
srb))
2651 SubtractRegion(
srb, sra, trb);
2653 Q_ASSERT(isEmptyHelper(&trb) || !tra.contains(trb));
2654 Q_ASSERT(isEmptyHelper(&tra) || !trb.contains(tra));
2656 if (isEmptyHelper(&tra)) {
2658 }
else if (isEmptyHelper(&trb)) {
2660 }
else if (tra.canAppend(&trb)) {
2663 }
else if (trb.canAppend(&tra)) {
2667 UnionRegion(&tra, &trb, dest);
2674 static bool EqualRegion(
const QRegionPrivate *r1,
const QRegionPrivate *r2)
2676 if (
r1->numRects !=
r2->numRects) {
2678 }
else if (
r1->numRects == 0) {
2680 }
else if (
r1->extents !=
r2->extents) {
2682 }
else if (
r1->numRects == 1 &&
r2->numRects == 1) {
2685 const QRect *rr1 = (
r1->numRects == 1) ? &
r1->extents :
r1->rects.constData();
2686 const QRect *rr2 = (
r2->numRects == 1) ? &
r2->extents :
r2->rects.constData();
2687 for (
int i = 0;
i <
r1->numRects; ++
i, ++rr1, ++rr2) {
2696 static bool PointInRegion(QRegionPrivate *pRegion,
int x,
int y)
2700 if (isEmptyHelper(pRegion))
2702 if (!pRegion->extents.contains(
x,
y))
2704 if (pRegion->numRects == 1)
2705 return pRegion->extents.contains(
x,
y);
2706 if (pRegion->innerRect.contains(
x,
y))
2708 for (
i = 0;
i < pRegion->numRects; ++
i) {
2709 if (pRegion->rects[
i].contains(
x,
y))
2718 const QRect *pboxEnd;
2721 int partIn, partOut;
2723 if (!region || region->numRects == 0 || !EXTENTCHECK(®ion->extents, prect))
2724 return RectangleOut;
2730 pbox = (region->numRects == 1) ? ®ion->extents : region->rects.constData();
2731 pboxEnd = pbox + region->numRects;
2732 for (; pbox < pboxEnd; ++pbox) {
2736 if (pbox->
top() >
ry) {
2738 if (partIn || pbox->
top() > prect->
bottom())
2862 #define BRESINITPGON(dy, x1, x2, xStart, d, m, m1, incr1, incr2) { \
2871 dx = (x2) - xStart; \
2875 incr1 = -2 * dx + 2 * (dy) * m1; \
2876 incr2 = -2 * dx + 2 * (dy) * m; \
2877 d = 2 * m * (dy) - 2 * dx - 2 * (dy); \
2881 incr1 = 2 * dx - 2 * (dy) * m1; \
2882 incr2 = 2 * dx - 2 * (dy) * m; \
2883 d = -2 * m * (dy) + 2 * dx; \
2888 #define BRESINCRPGON(d, minval, m, m1, incr1, incr2) { \
2926 #define BRESINITPGONSTRUCT(dmaj, min1, min2, bres) \
2927 BRESINITPGON(dmaj, min1, min2, bres.minor_axis, bres.d, \
2928 bres.m, bres.m1, bres.incr1, bres.incr2)
2930 #define BRESINCRPGONSTRUCT(bres) \
2931 BRESINCRPGON(bres.d, bres.minor_axis, bres.m, bres.m1, bres.incr1, bres.incr2)
2985 #define COUNTERCLOCKWISE -1
2987 typedef struct _EdgeTableEntry {
2991 struct _EdgeTableEntry *
next;
2992 struct _EdgeTableEntry *back;
2993 struct _EdgeTableEntry *nextWETE;
2997 typedef struct _ScanLineList{
2999 EdgeTableEntry *edgelist;
3000 struct _ScanLineList *
next;
3016 #define SLLSPERBLOCK 25
3018 typedef struct _ScanLineListBlock {
3019 ScanLineList SLLs[SLLSPERBLOCK];
3020 struct _ScanLineListBlock *
next;
3021 } ScanLineListBlock;
3038 #define EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET) { \
3039 if (pAET->ymax == y) { \
3040 pPrevAET->next = pAET->next; \
3041 pAET = pPrevAET->next; \
3044 pAET->back = pPrevAET; \
3047 BRESINCRPGONSTRUCT(pAET->bres) \
3049 pAET = pAET->next; \
3061 #define EVALUATEEDGEEVENODD(pAET, pPrevAET, y) { \
3062 if (pAET->ymax == y) { \
3063 pPrevAET->next = pAET->next; \
3064 pAET = pPrevAET->next; \
3066 pAET->back = pPrevAET; \
3069 BRESINCRPGONSTRUCT(pAET->bres) \
3071 pAET = pAET->next; \
3126 #define LARGE_COORDINATE INT_MAX
3127 #define SMALL_COORDINATE INT_MIN
3138 static void InsertEdgeInET(EdgeTable *ET, EdgeTableEntry *ETE,
int scanline,
3139 ScanLineListBlock **SLLBlock,
int *iSLLBlock)
3141 EdgeTableEntry *
start, *prev;
3142 ScanLineList *pSLL, *pPrevSLL;
3143 ScanLineListBlock *tmpSLLBlock;
3148 pPrevSLL = &ET->scanlines;
3149 pSLL = pPrevSLL->next;
3150 while (pSLL && (pSLL->scanline < scanline)) {
3158 if ((!pSLL) || (pSLL->scanline > scanline)) {
3159 if (*iSLLBlock > SLLSPERBLOCK-1)
3162 (ScanLineListBlock *)malloc(
sizeof(ScanLineListBlock));
3164 (*SLLBlock)->next = tmpSLLBlock;
3165 tmpSLLBlock->next = (ScanLineListBlock *)
nullptr;
3166 *SLLBlock = tmpSLLBlock;
3169 pSLL = &((*SLLBlock)->SLLs[(*iSLLBlock)++]);
3171 pSLL->next = pPrevSLL->next;
3172 pSLL->edgelist = (EdgeTableEntry *)
nullptr;
3173 pPrevSLL->next = pSLL;
3175 pSLL->scanline = scanline;
3181 start = pSLL->edgelist;
3182 while (
start && (
start->bres.minor_axis < ETE->bres.minor_axis)) {
3191 pSLL->edgelist = ETE;
3219 static void CreateETandAET(
int count,
const QPoint *pts,
3220 EdgeTable *ET, EdgeTableEntry *AET, EdgeTableEntry *pETEs,
3221 ScanLineListBlock *pSLLBlock)
3236 AET->next =
nullptr;
3237 AET->back =
nullptr;
3238 AET->nextWETE =
nullptr;
3239 AET->bres.minor_axis = SMALL_COORDINATE;
3244 ET->scanlines.next =
nullptr;
3245 ET->ymax = SMALL_COORDINATE;
3246 ET->ymin = LARGE_COORDINATE;
3247 pSLLBlock->next =
nullptr;
3249 PrevPt = &pts[
count - 1];
3262 if (PrevPt->
y() > CurrPt->
y()) {
3265 pETEs->ClockWise = 0;
3269 pETEs->ClockWise = 1;
3276 pETEs->ymax =
bottom->
y() - 1;
3282 BRESINITPGONSTRUCT(dy,
top->x(),
bottom->x(), pETEs->bres)
3284 InsertEdgeInET(ET, pETEs,
top->
y(), &pSLLBlock, &iSLLBlock);
3286 if (PrevPt->
y() > ET->ymax)
3287 ET->ymax = PrevPt->
y();
3288 if (PrevPt->
y() < ET->ymin)
3289 ET->ymin = PrevPt->
y();
3306 static
void loadAET(EdgeTableEntry *AET, EdgeTableEntry *ETEs)
3308 EdgeTableEntry *pPrevAET;
3309 EdgeTableEntry *tmp;
3314 while (AET && AET->bres.minor_axis < ETEs->bres.minor_axis) {
3322 ETEs->back = pPrevAET;
3323 pPrevAET->next = ETEs;
3350 static void computeWAET(EdgeTableEntry *AET)
3352 EdgeTableEntry *pWETE;
3356 AET->nextWETE =
nullptr;
3365 if ((!inside && !isInside) || (inside && isInside)) {
3366 pWETE->nextWETE = AET;
3372 pWETE->nextWETE =
nullptr;
3384 static int InsertionSort(EdgeTableEntry *AET)
3386 EdgeTableEntry *pETEchase;
3387 EdgeTableEntry *pETEinsert;
3388 EdgeTableEntry *pETEchaseBackTMP;
3395 while (pETEchase->back->bres.minor_axis > AET->bres.minor_axis)
3396 pETEchase = pETEchase->back;
3399 if (pETEchase != pETEinsert) {
3400 pETEchaseBackTMP = pETEchase->back;
3401 pETEinsert->back->next = AET;
3403 AET->back = pETEinsert->back;
3404 pETEinsert->next = pETEchase;
3405 pETEchase->back->next = pETEinsert;
3406 pETEchase->back = pETEinsert;
3407 pETEinsert->back = pETEchaseBackTMP;
3417 static void FreeStorage(ScanLineListBlock *pSLLBlock)
3419 ScanLineListBlock *tmpSLLBlock;
3422 tmpSLLBlock = pSLLBlock->next;
3424 pSLLBlock = tmpSLLBlock;
3428 struct QRegionSpan {
3430 QRegionSpan(
int x1_,
int x2_) :
x1(x1_),
x2(x2_) {}
3439 static inline void flushRow(
const QRegionSpan *spans,
int y,
int numSpans, QRegionPrivate *reg,
int *lastRow,
int *extendTo,
bool *needsExtend)
3441 QRect *regRects = reg->rects.data() + *lastRow;
3442 bool canExtend = reg->rects.
size() - *lastRow == numSpans
3443 && !(*needsExtend && *extendTo + 1 !=
y)
3444 && (*needsExtend || regRects[0].
y() + regRects[0].
height() ==
y);
3446 for (
int i = 0;
i < numSpans && canExtend; ++
i) {
3447 if (regRects[
i].
x() != spans[
i].x1 || regRects[
i].
right() != spans[
i].x2 - 1)
3453 *needsExtend =
true;
3456 for (
int i = 0;
i < reg->rects.size() - *lastRow; ++
i)
3457 regRects[
i].setBottom(*extendTo);
3460 *lastRow = reg->rects.size();
3461 reg->rects.reserve(*lastRow + numSpans);
3462 for (
int i = 0;
i < numSpans; ++
i)
3466 reg->extents.
setLeft(spans[0].x1);
3468 if (spans[numSpans-1].
x2 - 1 > reg->extents.right())
3469 reg->extents.setRight(spans[numSpans-1].x2 - 1);
3471 *needsExtend =
false;
3483 static void PtsToRegion(
int numFullPtBlocks,
int iCurPtBlock,
3484 POINTBLOCK *FirstPtBlock, QRegionPrivate *reg)
3488 bool needsExtend =
false;
3492 reg->extents.setLeft(INT_MAX);
3493 reg->extents.setRight(INT_MIN);
3494 reg->innerArea = -1;
3496 POINTBLOCK *CurPtBlock = FirstPtBlock;
3497 for (; numFullPtBlocks >= 0; --numFullPtBlocks) {
3499 int i = NUMPTSTOBUFFER >> 1;
3500 if (!numFullPtBlocks)
3501 i = iCurPtBlock >> 1;
3503 row.resize(qMax(
row.size(), rowSize +
i));
3504 for (
QPoint *pts = CurPtBlock->pts;
i--; pts += 2) {
3505 const int width = pts[1].
x() - pts[0].
x();
3507 if (rowSize &&
row[rowSize-1].
x2 == pts[0].
x())
3508 row[rowSize-1].x2 = pts[1].
x();
3510 row[rowSize++] = QRegionSpan(pts[0].
x(), pts[1].
x());
3514 QPoint *
next =
i ? &pts[2] : (numFullPtBlocks && iCurPtBlock ? CurPtBlock->next->pts :
nullptr);
3517 flushRow(
row.data(), pts[0].y(), rowSize, reg, &lastRow, &extendTo, &needsExtend);
3523 CurPtBlock = CurPtBlock->next;
3527 for (
int i = lastRow;
i < reg->rects.size(); ++
i)
3528 reg->rects[
i].setBottom(extendTo);
3531 reg->numRects = reg->rects.size();
3533 if (reg->numRects) {
3534 reg->extents.setTop(reg->rects[0].top());
3535 reg->extents.setBottom(reg->rects[lastRow].bottom());
3537 for (
int i = 0;
i < reg->rects.size(); ++
i)
3538 reg->updateInnerRect(reg->rects[
i]);
3540 reg->extents.setCoords(0, 0, 0, 0);
3553 static QRegionPrivate *PolygonRegion(
const QPoint *Pts,
int Count,
int rule)
3558 QRegionPrivate *region;
3559 EdgeTableEntry *pAET;
3562 EdgeTableEntry *pWETE;
3565 EdgeTableEntry *pPrevAET;
3567 EdgeTableEntry *AET;
3568 EdgeTableEntry *pETEs;
3569 ScanLineListBlock SLLBlock;
3570 int fixWAET =
false;
3571 POINTBLOCK FirstPtBlock, *curPtBlock;
3572 FirstPtBlock.pts =
reinterpret_cast<QPoint *
>(FirstPtBlock.data);
3573 FirstPtBlock.next =
nullptr;
3574 POINTBLOCK *tmpPtBlock;
3575 int numFullPtBlocks = 0;
3579 region =
new QRegionPrivate;
3582 if (((Count == 4) ||
3583 ((Count == 5) && (Pts[4].
x() == Pts[0].
x()) && (Pts[4].
y() == Pts[0].
y())))
3584 && (((Pts[0].
y() == Pts[1].
y()) && (Pts[1].
x() == Pts[2].
x()) && (Pts[2].
y() == Pts[3].
y())
3585 && (Pts[3].
x() == Pts[0].
x())) || ((Pts[0].
x() == Pts[1].
x())
3586 && (Pts[1].
y() == Pts[2].
y()) && (Pts[2].
x() == Pts[3].
x())
3587 && (Pts[3].
y() == Pts[0].
y())))) {
3588 int x = qMin(Pts[0].
x(), Pts[2].
x());
3589 region->extents.setLeft(
x);
3590 int y = qMin(Pts[0].
y(), Pts[2].
y());
3591 region->extents.setTop(
y);
3592 region->extents.setWidth(qMax(Pts[0].
x(), Pts[2].
x()) -
x);
3593 region->extents.setHeight(qMax(Pts[0].
y(), Pts[2].
y()) -
y);
3594 if ((region->extents.left() <= region->extents.right()) &&
3595 (region->extents.top() <= region->extents.bottom())) {
3596 region->numRects = 1;
3597 region->innerRect = region->extents;
3598 region->innerArea = region->innerRect.width() * region->innerRect.height();
3603 if (!(pETEs =
static_cast<EdgeTableEntry *
>(malloc(
sizeof(EdgeTableEntry) * Count)))) {
3608 region->vectorize();
3610 AET =
new EdgeTableEntry;
3611 pts = FirstPtBlock.pts;
3612 CreateETandAET(Count, Pts, &ET, AET, pETEs, &SLLBlock);
3614 pSLL = ET.scanlines.next;
3615 curPtBlock = &FirstPtBlock;
3618 if (ET.ymax - ET.ymin > 100000) {
3621 qWarning(
"QRegion: creating region from big polygon failed...!");
3630 if (
rule == EvenOddRule) {
3634 for (
y = ET.ymin;
y < ET.ymax; ++
y) {
3640 if (pSLL &&
y == pSLL->scanline) {
3641 loadAET(AET, pSLL->edgelist);
3651 pts->
setX(pAET->bres.minor_axis);
3659 if (iPts == NUMPTSTOBUFFER) {
3660 tmpPtBlock = (POINTBLOCK *)malloc(
sizeof(POINTBLOCK));
3662 tmpPtBlock->pts =
reinterpret_cast<QPoint *
>(tmpPtBlock->data);
3663 curPtBlock->next = tmpPtBlock;
3664 curPtBlock = tmpPtBlock;
3665 pts = curPtBlock->pts;
3669 EVALUATEEDGEEVENODD(pAET, pPrevAET,
y)
3677 for (
y = ET.ymin;
y < ET.ymax; ++
y) {
3682 if (pSLL &&
y == pSLL->scanline) {
3683 loadAET(AET, pSLL->edgelist);
3699 if (pWETE == pAET) {
3700 pts->
setX(pAET->bres.minor_axis);
3708 if (iPts == NUMPTSTOBUFFER) {
3709 tmpPtBlock =
static_cast<POINTBLOCK *
>(malloc(
sizeof(POINTBLOCK)));
3710 tmpPtBlock->pts =
reinterpret_cast<QPoint *
>(tmpPtBlock->data);
3711 curPtBlock->next = tmpPtBlock;
3712 curPtBlock = tmpPtBlock;
3713 pts = curPtBlock->pts;
3717 pWETE = pWETE->nextWETE;
3719 EVALUATEEDGEWINDING(pAET, pPrevAET,
y, fixWAET)
3726 if (InsertionSort(AET) || fixWAET) {
3733 FreeStorage(SLLBlock.next);
3734 PtsToRegion(numFullPtBlocks, iPts, &FirstPtBlock, region);
3735 for (curPtBlock = FirstPtBlock.next; --numFullPtBlocks >= 0;) {
3736 tmpPtBlock = curPtBlock->next;
3738 curPtBlock = tmpPtBlock;
3744 FreeStorage(SLLBlock.next);
3745 PtsToRegion(numFullPtBlocks, iPts, &FirstPtBlock, region);
3746 for (curPtBlock = FirstPtBlock.next; --numFullPtBlocks >= 0;) {
3747 tmpPtBlock = curPtBlock->next;
3749 curPtBlock = tmpPtBlock;
3761 QRegionPrivate *region =
new QRegionPrivate;
3767 xr.setCoords(prev1, y, x-1, y); \
3768 UnionRectWithRegion(&xr, region, *region); \
3776 for (
y = 0;
y <
image.height(); ++
y) {
3781 for (
x = 0;
x <
w;) {
3783 if (
x >
w - 8 ||
byte!=all) {
3785 for (
int b = 8;
b > 0 &&
x <
w; --
b) {
3786 if (!(
byte & 0x01) == !all) {
3802 for (
int b = 8;
b > 0 &&
x <
w; --
b) {
3803 if (!(
byte & 0x80) == !all) {
3833 :
d(const_cast<QRegionData*>(&shared_empty))
3840 d =
const_cast<QRegionData*
>(&shared_empty);
3842 d =
new QRegionData;
3843 d->ref.initializeOwned();
3848 path.addEllipse(
r.x(),
r.y(),
r.width(),
r.height());
3850 d->qt_rgn = PolygonRegion(
a.constData(),
a.size(), EvenOddRule);
3857 if (
a.count() > 2) {
3861 d =
new QRegionData;
3862 d->ref.initializeOwned();
3865 d =
const_cast<QRegionData*
>(&shared_empty);
3868 d =
const_cast<QRegionData*
>(&shared_empty);
3882 d =
const_cast<QRegionData*
>(&shared_empty);
3884 d =
new QRegionData;
3885 d->ref.initializeOwned();
3886 d->qt_rgn = qt_bitmapToRegion(
bm);
3890 void QRegion::cleanUp(QRegion::QRegionData *
x)
3898 if (!d->ref.deref())
3906 if (!d->ref.deref())
3919 auto x = std::make_unique<QRegionData>();
3920 x->ref.initializeOwned();
3925 if (!
r.d->ref.deref())
3933 return d == &shared_empty || d->qt_rgn->numRects == 0;
3938 return d == &shared_empty || d->qt_rgn->numRects == 0;
3943 return PointInRegion(d->qt_rgn,
p.x(),
p.y());
3948 return RectInRegion(d->qt_rgn,
r.left(),
r.top(),
r.width(),
r.height()) != RectangleOut;
3955 if ((dx == 0 && dy == 0) || isEmptyHelper(d->qt_rgn))
3959 OffsetRegion(*d->qt_rgn, dx, dy);
3964 if (isEmptyHelper(d->qt_rgn))
3966 if (isEmptyHelper(
r.d->qt_rgn))
3971 if (d->qt_rgn->contains(*
r.d->qt_rgn)) {
3973 }
else if (
r.d->qt_rgn->contains(*d->qt_rgn)) {
3975 }
else if (d->qt_rgn->canAppend(
r.d->qt_rgn)) {
3978 result.d->qt_rgn->append(
r.d->qt_rgn);
3980 }
else if (d->qt_rgn->canPrepend(
r.d->qt_rgn)) {
3983 result.d->qt_rgn->prepend(
r.d->qt_rgn);
3985 }
else if (EqualRegion(d->qt_rgn,
r.d->qt_rgn)) {
3990 UnionRegion(d->qt_rgn,
r.d->qt_rgn, *
result.d->qt_rgn);
3997 if (isEmptyHelper(d->qt_rgn))
3999 if (isEmptyHelper(
r.d->qt_rgn))
4004 if (d->qt_rgn->contains(*
r.d->qt_rgn)) {
4006 }
else if (
r.d->qt_rgn->contains(*d->qt_rgn)) {
4008 }
else if (d->qt_rgn->canAppend(
r.d->qt_rgn)) {
4010 d->qt_rgn->append(
r.d->qt_rgn);
4012 }
else if (d->qt_rgn->canPrepend(
r.d->qt_rgn)) {
4014 d->qt_rgn->prepend(
r.d->qt_rgn);
4016 }
else if (EqualRegion(d->qt_rgn,
r.d->qt_rgn)) {
4020 UnionRegion(d->qt_rgn,
r.d->qt_rgn, *d->qt_rgn);
4027 if (isEmptyHelper(d->qt_rgn))
4032 if (d->qt_rgn->contains(
r)) {
4034 }
else if (d->qt_rgn->within(
r)) {
4036 }
else if (d->qt_rgn->numRects == 1 && d->qt_rgn->extents ==
r) {
4038 }
else if (d->qt_rgn->canAppend(&
r)) {
4043 }
else if (d->qt_rgn->canPrepend(&
r)) {
4046 result.d->qt_rgn->prepend(&
r);
4052 UnionRegion(d->qt_rgn, &rp, *
result.d->qt_rgn);
4059 if (isEmptyHelper(d->qt_rgn))
4064 if (d->qt_rgn->contains(
r)) {
4066 }
else if (d->qt_rgn->within(
r)) {
4068 }
else if (d->qt_rgn->canAppend(&
r)) {
4070 d->qt_rgn->append(&
r);
4072 }
else if (d->qt_rgn->canPrepend(&
r)) {
4074 d->qt_rgn->prepend(&
r);
4076 }
else if (d->qt_rgn->numRects == 1 && d->qt_rgn->extents ==
r) {
4081 UnionRegion(d->qt_rgn, &
p, *d->qt_rgn);
4088 if (isEmptyHelper(d->qt_rgn) || isEmptyHelper(
r.d->qt_rgn)
4089 || !EXTENTCHECK(&d->qt_rgn->extents, &
r.d->qt_rgn->extents))
4093 if (
r.d->qt_rgn->contains(*d->qt_rgn))
4097 if (d->qt_rgn->contains(*
r.d->qt_rgn))
4100 if (
r.d->qt_rgn->numRects == 1 && d->qt_rgn->numRects == 1) {
4101 const QRect rect = qt_rect_intersect_normalized(
r.d->qt_rgn->extents,
4102 d->qt_rgn->extents);
4104 }
else if (
r.d->qt_rgn->numRects == 1) {
4107 result.d->qt_rgn->intersect(
r.d->qt_rgn->extents);
4109 }
else if (d->qt_rgn->numRects == 1) {
4112 result.d->qt_rgn->intersect(d->qt_rgn->extents);
4118 miRegionOp(*
result.d->qt_rgn, d->qt_rgn,
r.d->qt_rgn, miIntersectO,
nullptr,
nullptr);
4127 miSetExtents(*
result.d->qt_rgn);
4133 if (isEmptyHelper(d->qt_rgn) ||
r.isEmpty()
4134 || !EXTENTCHECK(&d->qt_rgn->extents, &
r))
4138 if (d->qt_rgn->within(
r))
4142 if (d->qt_rgn->contains(
r))
4145 if (d->qt_rgn->numRects == 1) {
4146 const QRect rect = qt_rect_intersect_normalized(d->qt_rgn->extents,
4153 result.d->qt_rgn->intersect(
r);
4159 if (isEmptyHelper(d->qt_rgn) || isEmptyHelper(
r.d->qt_rgn))
4161 if (
r.d->qt_rgn->contains(*d->qt_rgn))
4163 if (!EXTENTCHECK(&d->qt_rgn->extents, &
r.d->qt_rgn->extents))
4165 if (d ==
r.d || EqualRegion(d->qt_rgn,
r.d->qt_rgn))
4168 #ifdef QT_REGION_DEBUG
4169 d->qt_rgn->selfTest();
4170 r.d->qt_rgn->selfTest();
4175 SubtractRegion(d->qt_rgn,
r.d->qt_rgn, *
result.d->qt_rgn);
4176 #ifdef QT_REGION_DEBUG
4177 result.d->qt_rgn->selfTest();
4184 if (isEmptyHelper(d->qt_rgn)) {
4186 }
else if (isEmptyHelper(
r.d->qt_rgn)) {
4188 }
else if (!EXTENTCHECK(&d->qt_rgn->extents, &
r.d->qt_rgn->extents)) {
4190 }
else if (d ==
r.d || EqualRegion(d->qt_rgn,
r.d->qt_rgn)) {
4195 XorRegion(d->qt_rgn,
r.d->qt_rgn, *
result.d->qt_rgn);
4204 return d->qt_rgn->extents;
4214 if (isEmptyHelper(region.d->qt_rgn) || !
rect.isValid())
4218 static bool guard =
false;
4222 QRegion inner = region.d->qt_rgn->innerRect;
4223 Q_ASSERT((inner - region).isEmpty());
4227 for (
int i = 0;
i < region.d->qt_rgn->numRects; ++
i) {
4228 const QRect r = region.d->qt_rgn->rects.at(
i);
4229 if (
r.width() *
r.height() > maxArea)
4230 maxArea =
r.width() *
r.height();
4233 if (maxArea > region.d->qt_rgn->innerArea) {
4234 qDebug() <<
"not largest rectangle" << region << region.d->qt_rgn->innerRect;
4236 Q_ASSERT(maxArea <= region.d->qt_rgn->innerArea);
4239 const QRect r1 = region.d->qt_rgn->innerRect;
4246 return d->qt_rgn ? d->qt_rgn->begin() :
nullptr;
4251 return d->qt_rgn ? d->qt_rgn->end() :
nullptr;
4262 d->qt_rgn->numRects =
num;
4264 d->qt_rgn->extents = *rects;
4265 d->qt_rgn->innerRect = *rects;
4267 d->qt_rgn->rects.resize(
num);
4273 for (
int i = 0;
i <
num; ++
i) {
4275 d->qt_rgn->rects[
i] =
rect;
4280 d->qt_rgn->updateInnerRect(
rect);
4288 return (d->qt_rgn ? d->qt_rgn->numRects : 0);
4302 return EqualRegion(d->qt_rgn,
r.d->qt_rgn);
4307 if (isEmptyHelper(d->qt_rgn) ||
rect.isNull())
4313 if (d->qt_rgn->numRects == 1)
4326 #if defined(Q_OS_WIN) || defined(Q_QDOC)
4328 static inline HRGN qt_RectToHRGN(
const QRect &rc)
4338 HRGN QRegion::toHRGN()
const
4344 HRGN resultRgn =
nullptr;
4345 const auto rects =
begin();
4346 resultRgn = qt_RectToHRGN(rects[0]);
4347 for (
int i = 1;
i <
size; ++
i) {
4348 HRGN tmpRgn = qt_RectToHRGN(rects[
i]);
4349 int err = CombineRgn(resultRgn, resultRgn, tmpRgn, RGN_OR);
4351 qWarning(
"Error combining HRGNs.");
4352 DeleteObject(tmpRgn);
4362 QRegion QRegion::fromHRGN(HRGN hrgn)
4364 DWORD regionDataSize = GetRegionData(hrgn, 0,
nullptr);
4365 if (regionDataSize == 0)
4368 auto regionData =
reinterpret_cast<LPRGNDATA
>(malloc(regionDataSize));
4373 if (GetRegionData(hrgn, regionDataSize, regionData) == regionDataSize) {
4374 auto pRect =
reinterpret_cast<LPRECT
>(regionData->Buffer);
4375 for (DWORD
i = 0;
i < regionData->rdh.nCount; ++
i)
small capitals from c petite p scientific i
[1]
The QBitmap class provides monochrome (1-bit depth) pixmaps.
The QByteArray class provides an array of bytes.
The QDataStream class provides serialization of binary data to a QIODevice.
operator>>(QDataStream &ds, qfloat16 &f)
operator<<(QDataStream &ds, qfloat16 f)
The QDebug class provides an output stream for debugging information.
Convenience class for custom QDebug operators.
The QImage class provides a hardware-independent image representation that allows direct access to th...
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)
The QPainterPath class provides a container for painting operations, enabling graphical shapes to be ...
The QPoint class defines a point in the plane using integer precision.
constexpr int x() const noexcept
constexpr void setY(int y) noexcept
constexpr int y() const noexcept
constexpr void setX(int x) noexcept
The QPolygon class provides a list of points using integer precision. \inmodule QtGui.
The QRect class defines a rectangle in the plane using integer precision.
constexpr bool isEmpty() const noexcept
bool intersects(const QRect &r) const noexcept
constexpr int height() const noexcept
QRect intersected(const QRect &other) const noexcept
constexpr int bottom() const noexcept
constexpr void setRight(int pos) noexcept
constexpr int top() const noexcept
constexpr void setBottom(int pos) noexcept
constexpr void setLeft(int pos) noexcept
constexpr int left() const noexcept
constexpr QSize size() const noexcept
constexpr void translate(int dx, int dy) noexcept
constexpr void setCoords(int x1, int y1, int x2, int y2) noexcept
constexpr int width() const noexcept
QRect united(const QRect &other) const noexcept
constexpr int y() const noexcept
constexpr int right() const noexcept
constexpr void setTop(int pos) noexcept
The QRegion class specifies a clip region for a painter.
QRegion operator&(const QRegion &r) const
QRegion united(const QRegion &r) const
QRegion & operator^=(const QRegion &r)
QRect boundingRect() const noexcept
int rectCount() const noexcept
QRegion & operator|=(const QRegion &r)
QRegion & operator=(const QRegion &)
QRegion & operator+=(const QRegion &r)
void translate(int dx, int dy)
void setRects(const QRect *rect, int num)
bool intersects(const QRegion &r) const
bool contains(const QPoint &p) const
const_iterator end() const noexcept
const_iterator begin() const noexcept
QRegion & operator&=(const QRegion &r)
friend struct QRegionPrivate
QRegion operator^(const QRegion &r) const
QRegion xored(const QRegion &r) const
QRegion intersected(const QRegion &r) const
bool operator==(const QRegion &r) const
QRegion subtracted(const QRegion &r) const
QRegion & operator-=(const QRegion &r)
QRegion operator|(const QRegion &r) const
QRegion translated(int dx, int dy) const
QRegion operator-(const QRegion &r) const
QRegion operator+(const QRegion &r) const
The QVariant class acts like a union for the most common Qt data types.
static auto fromValue(const T &value) -> std::enable_if_t< std::is_copy_constructible_v< T >, QVariant >
QRhiShaderResourceBindings * srb
list append(new Employee("Blackpool", "Stephen"))
auto it unsigned count const
void *PRIV() memmove(void *d, const void *s, size_t n)
set set set set set set set macro pixldst1 reg1
set set set set set set set macro pixldst1 abits if abits op else op endif endm macro pixldst2 reg2
set set set set set set set macro pixldst1 abits if abits op else op endif endm macro pixldst2 abits if abits op else op endif endm macro pixldst4 abits if abits op else op endif endm macro pixldst0 abits op endm macro pixldst3 mem_operand op endm macro pixldst30 mem_operand op endm macro pixldst abits if abits elseif abits elseif abits elseif abits elseif abits pixldst0 abits else pixldst0 abits pixldst0 abits pixldst0 abits pixldst0 abits endif elseif abits else pixldst0 abits pixldst0 abits endif elseif abits else error unsupported bpp *numpix else pixst endif endm macro vuzp8 reg2 vuzp d d ®2 endm macro vzip8 reg2 vzip d d ®2 endm macro pixdeinterleave basereg basereg basereg basereg basereg endif endm macro pixinterleave basereg basereg basereg basereg basereg endif endm macro PF boost_increment endif if endif PF tst PF addne PF subne PF cmp ORIG_W if endif if endif if endif PF subge ORIG_W PF subges if endif if endif if endif endif endm macro cache_preload_simple endif if dst_r_bpp pld[DST_R, #(PREFETCH_DISTANCE_SIMPLE *dst_r_bpp/8)] endif if mask_bpp pld if[MASK, #(PREFETCH_DISTANCE_SIMPLE *mask_bpp/8)] endif endif endm macro ensure_destination_ptr_alignment process_pixblock_tail_head if beq irp skip1(dst_w_bpp<=(lowbit *8)) &&((lowbit *8)<(pixblock_size *dst_w_bpp)) .if lowbit< 16 tst DST_R
[3]
DBusConnection const char * rule
#define QT_BEGIN_INCLUDE_NAMESPACE
QT_BEGIN_INCLUDE_NAMESPACE typedef unsigned char uchar
#define QT_END_INCLUDE_NAMESPACE
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
#define Q_REFCOUNT_INITIALIZE_STATIC
Q_DECLARE_TYPEINFO(Segment, Q_PRIMITIVE_TYPE)
Q_GUI_EXPORT QPainterPath qt_regionToPath(const QRegion ®ion)
#define QRGN_SETPTARRAY_ALT
bool rect_intersects(const QRect &r1, const QRect &r2)
#define QRGN_SETPTARRAY_WIND
QtPrivate::QRegularExpressionMatchIteratorRangeBasedForIterator begin(const QRegularExpressionMatchIterator &iterator)
Q_CHECK_PTR(a=new int[80])
connect(quitButton, &QPushButton::clicked, &app, &QCoreApplication::quit, Qt::QueuedConnection)
QBitmap bm(8, 8, arrow_bits, true)