Define inverted QRects consistently

Changes the definition of invalid QRects to be more consistent.
This simplifies the logic, and makes it possible for us to fix
normalized() so dimensions don't change.

The actual API is not changed except for inverted rects.

Only one use-case for the old normalized() function existed,
and has been reimplemented as QRect::span().

Fixes: QTBUG-22934
Change-Id: I29dad2952dc6c8e84a6d931898dc7e43d66780f3
Reviewed-by: hjk <hjk@qt.io>
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
This commit is contained in:
Allan Sandfeld Jensen 2020-08-11 15:34:48 +02:00
parent b8a0341178
commit 5f198584e2
7 changed files with 189 additions and 161 deletions

View File

@ -223,9 +223,14 @@ QT_BEGIN_NAMESPACE
/*! /*!
\fn QRect::QRect(const QPoint &topLeft, const QPoint &bottomRight) \fn QRect::QRect(const QPoint &topLeft, const QPoint &bottomRight)
Constructs a rectangle with the given \a topLeft and \a bottomRight corners. Constructs a rectangle with the given \a topLeft and \a bottomRight corners, both included.
\sa setTopLeft(), setBottomRight() If \a bottomRight is to higher and to the left of \a topLeft, the rectangle defined
is instead non-inclusive of the corners.
\note To ensure both points are included regardless of relative order, use span().
\sa setTopLeft(), setBottomRight(), span()
*/ */
@ -295,27 +300,22 @@ QT_BEGIN_NAMESPACE
non-negative width and height. non-negative width and height.
If width() < 0 the function swaps the left and right corners, and If width() < 0 the function swaps the left and right corners, and
it swaps the top and bottom corners if height() < 0. it swaps the top and bottom corners if height() < 0. The corners
are at the same time changed from being non-inclusive to inclusive.
\sa isValid(), isEmpty() \sa isValid(), isEmpty()
*/ */
QRect QRect::normalized() const noexcept QRect QRect::normalized() const noexcept
{ {
QRect r; QRect r(*this);
if (x2 < x1 - 1) { // swap bad x values if (x2 < x1) { // swap bad x values
r.x1 = x2; r.x1 = x2 + 1;
r.x2 = x1; r.x2 = x1 - 1;
} else {
r.x1 = x1;
r.x2 = x2;
} }
if (y2 < y1 - 1) { // swap bad y values if (y2 < y1) { // swap bad y values
r.y1 = y2; r.y1 = y2 + 1;
r.y2 = y1; r.y2 = y1 - 1;
} else {
r.y1 = y1;
r.y2 = y2;
} }
return r; return r;
} }
@ -824,8 +824,8 @@ bool QRect::contains(const QPoint &p, bool proper) const noexcept
{ {
int l, r; int l, r;
if (x2 < x1 - 1) { if (x2 < x1 - 1) {
l = x2; l = x2 + 1;
r = x1; r = x1 - 1;
} else { } else {
l = x1; l = x1;
r = x2; r = x2;
@ -839,8 +839,8 @@ bool QRect::contains(const QPoint &p, bool proper) const noexcept
} }
int t, b; int t, b;
if (y2 < y1 - 1) { if (y2 < y1 - 1) {
t = y2; t = y2 + 1;
b = y1; b = y1 - 1;
} else { } else {
t = y1; t = y1;
b = y2; b = y2;
@ -890,16 +890,16 @@ bool QRect::contains(const QRect &r, bool proper) const noexcept
return false; return false;
int l1 = x1; int l1 = x1;
int r1 = x1; int r1 = x1 - 1;
if (x2 - x1 + 1 < 0) if (x2 < x1 - 1)
l1 = x2; l1 = x2 + 1;
else else
r1 = x2; r1 = x2;
int l2 = r.x1; int l2 = r.x1;
int r2 = r.x1; int r2 = r.x1 - 1;
if (r.x2 - r.x1 + 1 < 0) if (r.x2 < r.x1 - 1)
l2 = r.x2; l2 = r.x2 + 1;
else else
r2 = r.x2; r2 = r.x2;
@ -912,16 +912,16 @@ bool QRect::contains(const QRect &r, bool proper) const noexcept
} }
int t1 = y1; int t1 = y1;
int b1 = y1; int b1 = y1 - 1;
if (y2 - y1 + 1 < 0) if (y2 < y1 - 1)
t1 = y2; t1 = y2 + 1;
else else
b1 = y2; b1 = y2;
int t2 = r.y1; int t2 = r.y1;
int b2 = r.y1; int b2 = r.y1 - 1;
if (r.y2 - r.y1 + 1 < 0) if (r.y2 < r.y1 - 1)
t2 = r.y2; t2 = r.y2 + 1;
else else
b2 = r.y2; b2 = r.y2;
@ -970,30 +970,30 @@ QRect QRect::operator|(const QRect &r) const noexcept
return *this; return *this;
int l1 = x1; int l1 = x1;
int r1 = x1; int r1 = x1 - 1;
if (x2 - x1 + 1 < 0) if (x2 < x1 - 1)
l1 = x2; l1 = x2 + 1;
else else
r1 = x2; r1 = x2;
int l2 = r.x1; int l2 = r.x1;
int r2 = r.x1; int r2 = r.x1 - 1;
if (r.x2 - r.x1 + 1 < 0) if (r.x2 < r.x1 - 1)
l2 = r.x2; l2 = r.x2 + 1;
else else
r2 = r.x2; r2 = r.x2;
int t1 = y1; int t1 = y1;
int b1 = y1; int b1 = y1 - 1;
if (y2 - y1 + 1 < 0) if (y2 < y1 - 1)
t1 = y2; t1 = y2 + 1;
else else
b1 = y2; b1 = y2;
int t2 = r.y1; int t2 = r.y1;
int b2 = r.y1; int b2 = r.y1 - 1;
if (r.y2 - r.y1 + 1 < 0) if (r.y2 < r.y1 - 1)
t2 = r.y2; t2 = r.y2 + 1;
else else
b2 = r.y2; b2 = r.y2;
@ -1032,35 +1032,35 @@ QRect QRect::operator&(const QRect &r) const noexcept
return QRect(); return QRect();
int l1 = x1; int l1 = x1;
int r1 = x1; int r1 = x2;
if (x2 - x1 + 1 < 0) if (x2 < x1 - 1) {
l1 = x2; l1 = x2 + 1;
else r1 = x1 - 1;
r1 = x2; }
int l2 = r.x1; int l2 = r.x1;
int r2 = r.x1; int r2 = r.x2;
if (r.x2 - r.x1 + 1 < 0) if (r.x2 < r.x1 - 1) {
l2 = r.x2; l2 = r.x2 + 1;
else r2 = r.x1 - 1;
r2 = r.x2; }
if (l1 > r2 || l2 > r1) if (l1 > r2 || l2 > r1)
return QRect(); return QRect();
int t1 = y1; int t1 = y1;
int b1 = y1; int b1 = y2;
if (y2 - y1 + 1 < 0) if (y2 < y1 - 1) {
t1 = y2; t1 = y2 + 1;
else b1 = y1 - 1;
b1 = y2; }
int t2 = r.y1; int t2 = r.y1;
int b2 = r.y1; int b2 = r.y2;
if (r.y2 - r.y1 + 1 < 0) if (r.y2 < r.y1 - 1) {
t2 = r.y2; t2 = r.y2 + 1;
else b2 = r.y1 - 1;
b2 = r.y2; }
if (t1 > b2 || t2 > b1) if (t1 > b2 || t2 > b1)
return QRect(); return QRect();
@ -1104,35 +1104,35 @@ bool QRect::intersects(const QRect &r) const noexcept
return false; return false;
int l1 = x1; int l1 = x1;
int r1 = x1; int r1 = x2;
if (x2 - x1 + 1 < 0) if (x2 < x1 - 1) {
l1 = x2; l1 = x2 + 1;
else r1 = x1 - 1;
r1 = x2; }
int l2 = r.x1; int l2 = r.x1;
int r2 = r.x1; int r2 = r.x2;
if (r.x2 - r.x1 + 1 < 0) if (r.x2 < r.x1 - 1) {
l2 = r.x2; l2 = r.x2 + 1;
else r2 = r.x1 - 1;
r2 = r.x2; }
if (l1 > r2 || l2 > r1) if (l1 > r2 || l2 > r1)
return false; return false;
int t1 = y1; int t1 = y1;
int b1 = y1; int b1 = y2;
if (y2 - y1 + 1 < 0) if (y2 < y1 - 1) {
t1 = y2; t1 = y2 + 1;
else b1 = y1 - 1;
b1 = y2; }
int t2 = r.y1; int t2 = r.y1;
int b2 = r.y1; int b2 = r.y2;
if (r.y2 - r.y1 + 1 < 0) if (r.y2 < r.y1 - 1) {
t2 = r.y2; t2 = r.y2 + 1;
else b2 = r.y1 - 1;
b2 = r.y2; }
if (t1 > b2 || t2 > b1) if (t1 > b2 || t2 > b1)
return false; return false;
@ -1225,6 +1225,14 @@ bool QRect::intersects(const QRect &r) const noexcept
\since 5.1 \since 5.1
*/ */
/*!
\fn static QRect QRect::span(const QPoint &p1, const QPoint &p2)
Returns a rectangle spanning the two points, including both and everything
in between.
\since 6.0
*/
/***************************************************************************** /*****************************************************************************
QRect stream functions QRect stream functions

View File

@ -146,6 +146,8 @@ public:
constexpr inline QRect &operator+=(const QMargins &margins) noexcept; constexpr inline QRect &operator+=(const QMargins &margins) noexcept;
constexpr inline QRect &operator-=(const QMargins &margins) noexcept; constexpr inline QRect &operator-=(const QMargins &margins) noexcept;
Q_REQUIRED_RESULT static constexpr inline QRect span(const QPoint &p1, const QPoint &p2) noexcept;
friend constexpr inline bool operator==(const QRect &, const QRect &) noexcept; friend constexpr inline bool operator==(const QRect &, const QRect &) noexcept;
friend constexpr inline bool operator!=(const QRect &, const QRect &) noexcept; friend constexpr inline bool operator!=(const QRect &, const QRect &) noexcept;
friend constexpr inline size_t qHash(const QRect &, size_t) noexcept; friend constexpr inline size_t qHash(const QRect &, size_t) noexcept;
@ -505,6 +507,12 @@ constexpr inline QRect &QRect::operator-=(const QMargins &margins) noexcept
return *this; return *this;
} }
constexpr QRect QRect::span(const QPoint &p1, const QPoint &p2) noexcept
{
return QRect(QPoint(qMin(p1.x(), p2.x()), qMin(p1.y(), p2.y())),
QPoint(qMax(p1.x(), p2.x()), qMax(p1.y(), p2.y())));
}
#ifndef QT_NO_DEBUG_STREAM #ifndef QT_NO_DEBUG_STREAM
Q_CORE_EXPORT QDebug operator<<(QDebug, const QRect &); Q_CORE_EXPORT QDebug operator<<(QDebug, const QRect &);
#endif #endif

View File

@ -271,35 +271,6 @@ static void qt_debug_path(const QPainterPath &path)
} }
#endif #endif
// QRect::normalized() will change the width/height of the rectangle due to
// its incusive-integer definition of left/right vs width. This is not
// something we want to change in QRect as that would potentially introduce
// regressions all over the place, so we implement a straightforward
// normalized here. QRectF already does this, so QRectF::normalized() is ok to
// use.
static QRect qrect_normalized(const QRect &rect)
{
int x, y, w, h;
if (Q_UNLIKELY(rect.width() < 0)) {
x = rect.x() + rect.width();
w = -rect.width();
} else {
x = rect.x();
w = rect.width();
}
if (Q_UNLIKELY(rect.height() < 0)) {
y = rect.y() + rect.height();
h = -rect.height();
} else {
y = rect.y();
h = rect.height();
}
return QRect(x, y, w, h);
}
QRasterPaintEnginePrivate::QRasterPaintEnginePrivate() : QRasterPaintEnginePrivate::QRasterPaintEnginePrivate() :
QPaintEngineExPrivate(), QPaintEngineExPrivate(),
cachedLines(0) cachedLines(0)
@ -1320,9 +1291,7 @@ void QRasterPaintEngine::clip(const QRect &rect, Qt::ClipOperation op)
bool QRasterPaintEngine::setClipRectInDeviceCoords(const QRect &r, Qt::ClipOperation op) bool QRasterPaintEngine::setClipRectInDeviceCoords(const QRect &r, Qt::ClipOperation op)
{ {
Q_D(QRasterPaintEngine); Q_D(QRasterPaintEngine);
// normalize before using the & operator which uses QRect::normalize() QRect clipRect = r & d->deviceRect;
// internally which will give us the wrong values.
QRect clipRect = qrect_normalized(r) & d->deviceRect;
QRasterPaintEngineState *s = state(); QRasterPaintEngineState *s = state();
if (op == Qt::ReplaceClip || s->clip == nullptr) { if (op == Qt::ReplaceClip || s->clip == nullptr) {
@ -1557,7 +1526,7 @@ void QRasterPaintEngine::drawRects(const QRect *rects, int rectCount)
int offset_x = int(s->matrix.dx()); int offset_x = int(s->matrix.dx());
int offset_y = int(s->matrix.dy()); int offset_y = int(s->matrix.dy());
while (r < lastRect) { while (r < lastRect) {
QRect rect = qrect_normalized(*r); QRect rect = r->normalized();
QRect rr = rect.translated(offset_x, offset_y); QRect rr = rect.translated(offset_x, offset_y);
fillRect_normalized(rr, &s->brushData, d); fillRect_normalized(rr, &s->brushData, d);
++r; ++r;
@ -3006,8 +2975,8 @@ bool QRasterPaintEnginePrivate::isUnclipped(const QRect &rect,
Q_Q(const QRasterPaintEngine); Q_Q(const QRasterPaintEngine);
const QRasterPaintEngineState *s = q->state(); const QRasterPaintEngineState *s = q->state();
const QClipData *cl = clip(); const QClipData *cl = clip();
QRect r = rect.normalized();
if (!cl) { if (!cl) {
QRect r = qrect_normalized(rect);
// inline contains() for performance (we know the rects are normalized) // inline contains() for performance (we know the rects are normalized)
const QRect &r1 = deviceRect; const QRect &r1 = deviceRect;
return (r.left() >= r1.left() && r.right() <= r1.right() return (r.left() >= r1.left() && r.right() <= r1.right()
@ -3022,7 +2991,6 @@ bool QRasterPaintEnginePrivate::isUnclipped(const QRect &rect,
if (s->flags.antialiased) if (s->flags.antialiased)
++penWidth; ++penWidth;
QRect r = qrect_normalized(rect);
if (penWidth > 0) { if (penWidth > 0) {
r.setX(r.x() - penWidth); r.setX(r.x() - penWidth);
r.setY(r.y() - penWidth); r.setY(r.y() - penWidth);

View File

@ -164,14 +164,17 @@ private slots:
void intersectsRectF(); void intersectsRectF();
void containsRect_data(); void containsRect_data();
void containsRect(); void containsRect();
void containsRectNormalized();
void containsRectF_data(); void containsRectF_data();
void containsRectF(); void containsRectF();
void containsPoint_data(); void containsPoint_data();
void containsPoint(); void containsPoint();
void containsPointNormalized();
void containsPointF_data(); void containsPointF_data();
void containsPointF(); void containsPointF();
void smallRects() const; void smallRects() const;
void toRect(); void toRect();
void span();
}; };
// Used to work around some floating point precision problems. // Used to work around some floating point precision problems.
@ -372,17 +375,20 @@ void tst_QRect::normalized_data()
QTest::newRow( "LargestCoordQRect" ) << getQRectCase( LargestCoordQRect ) QTest::newRow( "LargestCoordQRect" ) << getQRectCase( LargestCoordQRect )
<< getQRectCase( LargestCoordQRect ); // overflow << getQRectCase( LargestCoordQRect ); // overflow
QTest::newRow( "RandomQRect" ) << getQRectCase( RandomQRect ) << QRect( 100, 200, 11, 16 ); QTest::newRow( "RandomQRect" ) << getQRectCase( RandomQRect ) << QRect( 100, 200, 11, 16 );
QTest::newRow( "NegativeSizeQRect" ) << getQRectCase( NegativeSizeQRect ) << QRect(QPoint(-10,-10),QPoint(1,1)); QTest::newRow( "NegativeSizeQRect" ) << getQRectCase( NegativeSizeQRect ) << QRect(-9, -9, 10, 10);
QTest::newRow( "NegativePointQRect" ) << getQRectCase( NegativePointQRect ) << QRect( -10, -10, 5, 5 ); QTest::newRow( "NegativePointQRect" ) << getQRectCase( NegativePointQRect ) << QRect( -10, -10, 5, 5 );
QTest::newRow( "NullQRect" ) << getQRectCase( NullQRect ) << getQRectCase( NullQRect ); QTest::newRow( "NullQRect" ) << getQRectCase( NullQRect ) << getQRectCase( NullQRect );
QTest::newRow( "EmptyQRect" ) << getQRectCase( EmptyQRect ) << getQRectCase( EmptyQRect ); QTest::newRow( "EmptyQRect" ) << getQRectCase( EmptyQRect ) << getQRectCase( EmptyQRect );
QTest::newRow( "ZeroWidth" ) << QRect(100, 200, 100, 0) << QRect(100, 200, 100, 0); QTest::newRow( "ZeroWidth" ) << QRect(100, 200, 100, 0) << QRect(100, 200, 100, 0);
QTest::newRow( "ZeroHeight" ) << QRect(100, 200, 0, 100) << QRect(100, 200, 0, 100);
// Since "NegativeSizeQRect passes, I expect both of these to pass too. // Since "NegativeSizeQRect passes, I expect both of these to pass too.
// This passes, since height() returns -1 before normalization // This passes, since height() returns -1 before normalization
QTest::newRow( "NegativeHeight") << QRect(QPoint(100,201), QPoint(199,199)) << QRect(QPoint(100,199), QPoint(199,201)); QTest::newRow( "NegativeWidth") << QRect(QPoint(200,100), QSize(-1,100)) << QRect(QPoint(199,100), QSize(1,100));
QTest::newRow( "NegativeHeight") << QRect(QPoint(100,200), QSize(100,-1)) << QRect(QPoint(100,199), QSize(100,1));
QTest::newRow( "NegativeWidth2") << QRect(QPoint(200,100), QPoint(198,199)) << QRect(QPoint(199,100), QPoint(199,199));
// This, on the other hand height() returns 0 before normalization. // This, on the other hand height() returns 0 before normalization.
QTest::newRow( "ZeroHeight1" ) << QRect(QPoint(100,200), QPoint(199,199)) << QRect(QPoint(100,199), QPoint(199,200)); QTest::newRow( "ZeroHeight1" ) << QRect(QPoint(100,200), QPoint(199,199)) << QRect(QPoint(100,200), QPoint(199,199));
QTest::newRow( "ZeroHeight2" ) << QRect(QPoint(263,113), QPoint(136,112)) << QRect(QPoint(136,113), QPoint(263,112)); QTest::newRow( "ZeroHeight2" ) << QRect(QPoint(263,113), QPoint(136,112)) << QRect(QPoint(137,113), QPoint(262,112));
} }
void tst_QRect::normalized() void tst_QRect::normalized()
@ -390,7 +396,6 @@ void tst_QRect::normalized()
QFETCH(QRect, r); QFETCH(QRect, r);
QFETCH(QRect, nr); QFETCH(QRect, nr);
QEXPECT_FAIL("ZeroHeight1", "due to broken QRect definition (not possible to change, see QTBUG-22934)", Continue);
QCOMPARE(r.normalized(), nr); QCOMPARE(r.normalized(), nr);
} }
@ -478,6 +483,9 @@ void tst_QRect::right()
if (isLarge(r.width())) if (isLarge(r.width()))
return; return;
// width overflow
if (r.left() < r.right() && r.width() < 0)
return;
QCOMPARE(QRectF(r).right(), qreal(right+1)); QCOMPARE(QRectF(r).right(), qreal(right+1));
} }
@ -510,6 +518,9 @@ void tst_QRect::bottom()
if (isLarge(r.height())) if (isLarge(r.height()))
return; return;
// height overflow
if (r.top() < r.bottom() && r.height() < 0)
return;
QCOMPARE(QRectF(r).bottom(), qreal(bottom + 1)); QCOMPARE(QRectF(r).bottom(), qreal(bottom + 1));
} }
@ -3931,15 +3942,15 @@ void tst_QRect::intersectedRect_data()
QTest::newRow("test 03") << QRect(0, 0, 10, 10) << QRect( 2, 2, 10, 10) << QRect(2, 2, 8, 8); QTest::newRow("test 03") << QRect(0, 0, 10, 10) << QRect( 2, 2, 10, 10) << QRect(2, 2, 8, 8);
QTest::newRow("test 04") << QRect(0, 0, 10, 10) << QRect(20, 20, 10, 10) << QRect(); QTest::newRow("test 04") << QRect(0, 0, 10, 10) << QRect(20, 20, 10, 10) << QRect();
QTest::newRow("test 05") << QRect(9, 9, -8, -8) << QRect( 2, 2, 6, 6) << QRect(2, 2, 6, 6); QTest::newRow("test 05") << QRect(10, 10, -10, -10) << QRect( 2, 2, 6, 6) << QRect(2, 2, 6, 6);
QTest::newRow("test 06") << QRect(9, 9, -8, -8) << QRect( 0, 0, 10, 10) << QRect(0, 0, 10, 10); QTest::newRow("test 06") << QRect(10, 10, -10, -10) << QRect( 0, 0, 10, 10) << QRect(0, 0, 10, 10);
QTest::newRow("test 07") << QRect(9, 9, -8, -8) << QRect( 2, 2, 10, 10) << QRect(2, 2, 8, 8); QTest::newRow("test 07") << QRect(10, 10, -10, -10) << QRect( 2, 2, 10, 10) << QRect(2, 2, 8, 8);
QTest::newRow("test 08") << QRect(9, 9, -8, -8) << QRect(20, 20, 10, 10) << QRect(); QTest::newRow("test 08") << QRect(10, 10, -10, -10) << QRect(20, 20, 10, 10) << QRect();
QTest::newRow("test 09") << QRect(0, 0, 10, 10) << QRect( 7, 7, -4, -4) << QRect(2, 2, 6, 6); QTest::newRow("test 09") << QRect(0, 0, 10, 10) << QRect( 6, 6, -4, -4) << QRect(2, 2, 4, 4);
QTest::newRow("test 10") << QRect(0, 0, 10, 10) << QRect( 9, 9, -8, -8) << QRect(0, 0, 10, 10); QTest::newRow("test 10") << QRect(0, 0, 10, 10) << QRect(10, 10, -10, -10) << QRect(0, 0, 10, 10);
QTest::newRow("test 11") << QRect(0, 0, 10, 10) << QRect(11, 11, -8, -8) << QRect(2, 2, 8, 8); QTest::newRow("test 11") << QRect(0, 0, 10, 10) << QRect(12, 12, -10, -10) << QRect(2, 2, 8, 8);
QTest::newRow("test 12") << QRect(0, 0, 10, 10) << QRect(29, 29, -8, -8) << QRect(); QTest::newRow("test 12") << QRect(0, 0, 10, 10) << QRect(30, 30, -10, -10) << QRect();
QTest::newRow("test 13") << QRect(0, 0, 10, 10) << QRect() << QRect(); QTest::newRow("test 13") << QRect(0, 0, 10, 10) << QRect() << QRect();
QTest::newRow("test 14") << QRect() << QRect(0, 0, 10, 10) << QRect(); QTest::newRow("test 14") << QRect() << QRect(0, 0, 10, 10) << QRect();
@ -4016,15 +4027,15 @@ void tst_QRect::unitedRect_data()
QTest::newRow("test 03") << QRect(0, 0, 10, 10) << QRect( 2, 2, 10, 10) << QRect(0, 0, 12, 12); QTest::newRow("test 03") << QRect(0, 0, 10, 10) << QRect( 2, 2, 10, 10) << QRect(0, 0, 12, 12);
QTest::newRow("test 04") << QRect(0, 0, 10, 10) << QRect(20, 20, 10, 10) << QRect(0, 0, 30, 30); QTest::newRow("test 04") << QRect(0, 0, 10, 10) << QRect(20, 20, 10, 10) << QRect(0, 0, 30, 30);
QTest::newRow("test 05") << QRect(9, 9, -8, -8) << QRect( 2, 2, 6, 6) << QRect(0, 0, 10, 10); QTest::newRow("test 05") << QRect(10, 10, -10, -10) << QRect( 2, 2, 6, 6) << QRect(0, 0, 10, 10);
QTest::newRow("test 06") << QRect(9, 9, -8, -8) << QRect( 0, 0, 10, 10) << QRect(0, 0, 10, 10); QTest::newRow("test 06") << QRect(10, 10, -10, -10) << QRect( 0, 0, 10, 10) << QRect(0, 0, 10, 10);
QTest::newRow("test 07") << QRect(9, 9, -8, -8) << QRect( 2, 2, 10, 10) << QRect(0, 0, 12, 12); QTest::newRow("test 07") << QRect(10, 10, -10, -10) << QRect( 2, 2, 10, 10) << QRect(0, 0, 12, 12);
QTest::newRow("test 08") << QRect(9, 9, -8, -8) << QRect(20, 20, 10, 10) << QRect(0, 0, 30, 30); QTest::newRow("test 08") << QRect(10, 10, -10, -10) << QRect(20, 20, 10, 10) << QRect(0, 0, 30, 30);
QTest::newRow("test 09") << QRect(0, 0, 10, 10) << QRect( 7, 7, -4, -4) << QRect(0, 0, 10, 10); QTest::newRow("test 09") << QRect(0, 0, 10, 10) << QRect( 7, 7, -4, -4) << QRect(0, 0, 10, 10);
QTest::newRow("test 10") << QRect(0, 0, 10, 10) << QRect( 9, 9, -8, -8) << QRect(0, 0, 10, 10); QTest::newRow("test 10") << QRect(0, 0, 10, 10) << QRect( 9, 9, -8, -8) << QRect(0, 0, 10, 10);
QTest::newRow("test 11") << QRect(0, 0, 10, 10) << QRect(11, 11, -8, -8) << QRect(0, 0, 12, 12); QTest::newRow("test 11") << QRect(0, 0, 10, 10) << QRect(12, 12, -8, -8) << QRect(0, 0, 12, 12);
QTest::newRow("test 12") << QRect(0, 0, 10, 10) << QRect(29, 29, -8, -8) << QRect(0, 0, 30, 30); QTest::newRow("test 12") << QRect(0, 0, 10, 10) << QRect(30, 30, -8, -8) << QRect(0, 0, 30, 30);
QTest::newRow("test 13") << QRect() << QRect(10, 10, 10, 10) << QRect(10, 10, 10, 10); QTest::newRow("test 13") << QRect() << QRect(10, 10, 10, 10) << QRect(10, 10, 10, 10);
QTest::newRow("test 14") << QRect(10, 10, 10, 10) << QRect() << QRect(10, 10, 10, 10); QTest::newRow("test 14") << QRect(10, 10, 10, 10) << QRect() << QRect(10, 10, 10, 10);
@ -4166,10 +4177,10 @@ void tst_QRect::containsRect_data()
QTest::newRow("test 03") << QRect(0, 0, 10, 10) << QRect( 2, 2, 10, 10) << false; QTest::newRow("test 03") << QRect(0, 0, 10, 10) << QRect( 2, 2, 10, 10) << false;
QTest::newRow("test 04") << QRect(0, 0, 10, 10) << QRect(20, 20, 10, 10) << false; QTest::newRow("test 04") << QRect(0, 0, 10, 10) << QRect(20, 20, 10, 10) << false;
QTest::newRow("test 05") << QRect(9, 9, -8, -8) << QRect( 2, 2, 6, 6) << true; QTest::newRow("test 05") << QRect(9, 9, -9, -9) << QRect( 2, 2, 6, 6) << true;
QTest::newRow("test 06") << QRect(9, 9, -8, -8) << QRect( 0, 0, 10, 10) << true; QTest::newRow("test 06") << QRect(9, 9, -9, -9) << QRect( 0, 0, 9, 9) << true;
QTest::newRow("test 07") << QRect(9, 9, -8, -8) << QRect( 2, 2, 10, 10) << false; QTest::newRow("test 07") << QRect(9, 9, -9, -9) << QRect( 2, 2, 9, 9) << false;
QTest::newRow("test 08") << QRect(9, 9, -8, -8) << QRect(20, 20, 10, 10) << false; QTest::newRow("test 08") << QRect(9, 9, -9, -9) << QRect(20, 20, 10, 10) << false;
QTest::newRow("test 09") << QRect(0, 0, 10, 10) << QRect( 7, 7, -4, -4) << true; QTest::newRow("test 09") << QRect(0, 0, 10, 10) << QRect( 7, 7, -4, -4) << true;
QTest::newRow("test 10") << QRect(0, 0, 10, 10) << QRect( 9, 9, -8, -8) << true; QTest::newRow("test 10") << QRect(0, 0, 10, 10) << QRect( 9, 9, -8, -8) << true;
@ -4190,6 +4201,18 @@ void tst_QRect::containsRect()
QVERIFY(rect1.contains(rect2) == contains); QVERIFY(rect1.contains(rect2) == contains);
} }
void tst_QRect::containsRectNormalized()
{
QRect rect(QPoint(10, 10), QPoint(0,0));
QRect normalized = rect.normalized();
for (int i = -2 ; i < 12; ++i) {
for (int j = -2 ; j < 12; ++j) {
for (int k = -2 ; k <= 2; ++k)
QCOMPARE(rect.contains(QRect(i,j,k,k)), normalized.contains(QRect(i,j,k,k)));
}
}
}
void tst_QRect::containsRectF_data() void tst_QRect::containsRectF_data()
{ {
QTest::addColumn<QRectF>("rect1"); QTest::addColumn<QRectF>("rect1");
@ -4245,18 +4268,18 @@ void tst_QRect::containsPoint_data()
QTest::newRow("test 11") << QRect(0, 0, 10, 10) << QPoint( 1, 8) << true << true; QTest::newRow("test 11") << QRect(0, 0, 10, 10) << QPoint( 1, 8) << true << true;
QTest::newRow("test 12") << QRect(0, 0, 10, 10) << QPoint( 8, 8) << true << true; QTest::newRow("test 12") << QRect(0, 0, 10, 10) << QPoint( 8, 8) << true << true;
QTest::newRow("test 13") << QRect(9, 9, -8, -8) << QPoint( 0, 0) << true << false; QTest::newRow("test 13") << QRect(9, 9, -9, -9) << QPoint( 0, 0) << true << false;
QTest::newRow("test 14") << QRect(9, 9, -8, -8) << QPoint( 0, 10) << false << false; QTest::newRow("test 14") << QRect(9, 9, -9, -9) << QPoint( 0, 9) << false << false;
QTest::newRow("test 15") << QRect(9, 9, -8, -8) << QPoint(10, 0) << false << false; QTest::newRow("test 15") << QRect(9, 9, -9, -9) << QPoint( 9, 0) << false << false;
QTest::newRow("test 16") << QRect(9, 9, -8, -8) << QPoint(10, 10) << false << false; QTest::newRow("test 16") << QRect(9, 9, -9, -9) << QPoint( 9, 9) << false << false;
QTest::newRow("test 17") << QRect(9, 9, -8, -8) << QPoint( 0, 9) << true << false; QTest::newRow("test 17") << QRect(9, 9, -9, -9) << QPoint( 0, 8) << true << false;
QTest::newRow("test 18") << QRect(9, 9, -8, -8) << QPoint( 9, 0) << true << false; QTest::newRow("test 18") << QRect(9, 9, -9, -9) << QPoint( 8, 0) << true << false;
QTest::newRow("test 19") << QRect(9, 9, -8, -8) << QPoint( 9, 9) << true << false; QTest::newRow("test 19") << QRect(9, 9, -9, -9) << QPoint( 8, 8) << true << false;
QTest::newRow("test 20") << QRect(9, 9, -8, -8) << QPoint( 1, 0) << true << false; QTest::newRow("test 20") << QRect(9, 9, -9, -9) << QPoint( 1, 0) << true << false;
QTest::newRow("test 21") << QRect(9, 9, -8, -8) << QPoint( 9, 1) << true << false; QTest::newRow("test 21") << QRect(9, 9, -9, -9) << QPoint( 8, 1) << true << false;
QTest::newRow("test 22") << QRect(9, 9, -8, -8) << QPoint( 1, 1) << true << true; QTest::newRow("test 22") << QRect(9, 9, -9, -9) << QPoint( 1, 1) << true << true;
QTest::newRow("test 23") << QRect(9, 9, -8, -8) << QPoint( 1, 8) << true << true; QTest::newRow("test 23") << QRect(9, 9, -9, -9) << QPoint( 1, 7) << true << true;
QTest::newRow("test 24") << QRect(9, 9, -8, -8) << QPoint( 8, 8) << true << true; QTest::newRow("test 24") << QRect(9, 9, -9, -9) << QPoint( 7, 7) << true << true;
QTest::newRow("test 25") << QRect(-1, 1, 10, 10) << QPoint() << false << false; QTest::newRow("test 25") << QRect(-1, 1, 10, 10) << QPoint() << false << false;
QTest::newRow("test 26") << QRect() << QPoint(1, 1) << false << false; QTest::newRow("test 26") << QRect() << QPoint(1, 1) << false << false;
@ -4274,6 +4297,16 @@ void tst_QRect::containsPoint()
QVERIFY(rect.contains(point, true) == containsProper); QVERIFY(rect.contains(point, true) == containsProper);
} }
void tst_QRect::containsPointNormalized()
{
QRect rect(QPoint(10, 10), QPoint(0,0));
QRect normalized = rect.normalized();
for (int i = 0 ; i < 10; ++i) {
for (int j = 0 ; j < 10; ++j)
QCOMPARE(rect.contains(QPoint(i,j)), normalized.contains(QPoint(i,j)));
}
}
void tst_QRect::containsPointF_data() void tst_QRect::containsPointF_data()
{ {
QTest::addColumn<QRectF>("rect"); QTest::addColumn<QRectF>("rect");
@ -4363,5 +4396,16 @@ void tst_QRect::toRect()
} }
} }
void tst_QRect::span()
{
QCOMPARE(QRect::span(QPoint( 0, 1), QPoint(9, 10)), QRect(QPoint(0, 1), QPoint( 9, 10)));
QCOMPARE(QRect::span(QPoint(10, 9), QPoint(1, 0)), QRect(QPoint(1, 0), QPoint(10, 9)));
QCOMPARE(QRect::span(QPoint(10, 1), QPoint(0, 9)), QRect(QPoint(0, 1), QPoint(10, 9)));
QCOMPARE(QRect::span(QPoint( 1, 10), QPoint(9, 0)), QRect(QPoint(1, 0), QPoint( 9, 10)));
}
QTEST_MAIN(tst_QRect) QTEST_MAIN(tst_QRect)
#include "tst_qrect.moc" #include "tst_qrect.moc"

View File

@ -815,7 +815,7 @@ void tst_QPainter::drawLine()
qMin(line.y1(), line.y2()) qMin(line.y1(), line.y2())
+ 2*offset + qAbs(line.dy())); + 2*offset + qAbs(line.dy()));
{ // clipped { // clipped
const QRect clip = QRect(line.p1(), line.p2()).normalized(); const QRect clip = QRect::span(line.p1(), line.p2());
pixmapClipped.fill(Qt::white); pixmapClipped.fill(Qt::white);
QPainter p(&pixmapClipped); QPainter p(&pixmapClipped);

View File

@ -8780,7 +8780,7 @@ public:
void resizeEvent(QResizeEvent *) override void resizeEvent(QResizeEvent *) override
{ {
setMask(QRegion(QRect(0, 0, width(), 10).normalized())); setMask(QRegion(QRect(0, 0, width(), 10)));
} }
QRegion paintedRegion; QRegion paintedRegion;
@ -9288,7 +9288,7 @@ class MaskResizeTestWidget : public QWidget
public: public:
explicit MaskResizeTestWidget(QWidget* p = nullptr) : QWidget(p) explicit MaskResizeTestWidget(QWidget* p = nullptr) : QWidget(p)
{ {
setMask(QRegion(QRect(0, 0, 100, 100).normalized())); setMask(QRegion(QRect(0, 0, 100, 100)));
} }
void paintEvent(QPaintEvent* event) override void paintEvent(QPaintEvent* event) override
@ -9304,12 +9304,12 @@ public:
public slots: public slots:
void enlargeMask() { void enlargeMask() {
QRegion newMask(QRect(0, 0, 150, 150).normalized()); QRegion newMask(QRect(0, 0, 150, 150));
setMask(newMask); setMask(newMask);
} }
void shrinkMask() { void shrinkMask() {
QRegion newMask(QRect(0, 0, 50, 50).normalized()); QRegion newMask(QRect(0, 0, 50, 50));
setMask(newMask); setMask(newMask);
} }

View File

@ -554,7 +554,7 @@ void tst_QPainter::drawLine_clipped()
qMin(line.y1(), line.y2()) qMin(line.y1(), line.y2())
+ 2*offset + qAbs(line.dy())); + 2*offset + qAbs(line.dy()));
const QRect clip = QRect(line.p1(), line.p2()).normalized(); const QRect clip = QRect::span(line.p1(), line.p2());
pixmapClipped.fill(Qt::white); pixmapClipped.fill(Qt::white);
QPainter p(&pixmapClipped); QPainter p(&pixmapClipped);
@ -589,7 +589,7 @@ void tst_QPainter::drawLine_antialiased_clipped()
qMin(line.y1(), line.y2()) qMin(line.y1(), line.y2())
+ 2*offset + qAbs(line.dy())); + 2*offset + qAbs(line.dy()));
const QRect clip = QRect(line.p1(), line.p2()).normalized(); const QRect clip = QRect::span(line.p1(), line.p2());
pixmapClipped.fill(Qt::white); pixmapClipped.fill(Qt::white);
QPainter p(&pixmapClipped); QPainter p(&pixmapClipped);