summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gui/painting/qregion.cpp114
-rw-r--r--src/gui/painting/qregion.h12
-rw-r--r--tests/auto/gui/painting/qregion/tst_qregion.cpp40
3 files changed, 163 insertions, 3 deletions
diff --git a/src/gui/painting/qregion.cpp b/src/gui/painting/qregion.cpp
index 35c4abb3ac..ddeca291b5 100644
--- a/src/gui/painting/qregion.cpp
+++ b/src/gui/painting/qregion.cpp
@@ -81,8 +81,8 @@ QT_BEGIN_NAMESPACE
contains() a QPoint or QRect. The bounding rectangle can be found
with boundingRect().
- The function rects() gives a decomposition of the region into
- rectangles.
+ Iteration over the region (with begin(), end()) gives a decomposition of
+ the region into rectangles. The same sequence of rectangles is returned by rects().
Example of using complex regions:
\snippet code/src_gui_painting_qregion.cpp 0
@@ -928,6 +928,100 @@ QRegion QRegion::intersect(const QRect &r) const
*/
/*!
+ \typedef QRegion::const_iterator
+ \since 5.8
+
+ An iterator over the QRects that make up the region.
+
+ QRegion does not offer mutable iterators.
+
+ \sa begin(), end()
+*/
+
+/*!
+ \typedef QRegion::const_reverse_iterator
+ \since 5.8
+
+ A reverse iterator over the QRects that make up the region.
+
+ QRegion does not offer mutable iterators.
+
+ \sa rbegin(), rend()
+*/
+
+/*!
+ \fn QRegion::begin() const
+ \since 5.8
+
+ Returns a const_iterator pointing to the beginning of the range of
+ rectangles that make up this range, in the order in which rects()
+ returns them.
+
+ \sa rbegin(), cbegin(), end()
+*/
+
+/*!
+ \fn QRegion::cbegin() const
+ \since 5.8
+
+ Same as begin().
+*/
+
+/*!
+ \fn QRegion::end() const
+ \since 5.8
+
+ Returns a const_iterator pointing to one past the end of the range of
+ rectangles that make up this range, in the order in which rects()
+ returns them.
+
+ \sa rend(), cend(), begin()
+*/
+
+/*!
+ \fn QRegion::cend() const
+ \since 5.8
+
+ Same as end().
+*/
+
+/*!
+ \fn QRegion::rbegin() const
+ \since 5.8
+
+ Returns a const_reverse_iterator pointing to the beginning of the range of
+ rectangles that make up this range, in the reverse order in which rects()
+ returns them.
+
+ \sa begin(), crbegin(), rend()
+*/
+
+/*!
+ \fn QRegion::crbegin() const
+ \since 5.8
+
+ Same as rbegin().
+*/
+
+/*!
+ \fn QRegion::rend() const
+ \since 5.8
+
+ Returns a const_reverse_iterator pointing to one past the end of the range of
+ rectangles that make up this range, in the reverse order in which rects()
+ returns them.
+
+ \sa end(), crend(), rbegin()
+*/
+
+/*!
+ \fn QRegion::crend() const
+ \since 5.8
+
+ Same as rend().
+*/
+
+/*!
\fn void QRegion::setRects(const QRect *rects, int number)
Sets the region using the array of rectangles specified by \a rects and
@@ -1171,6 +1265,12 @@ struct QRegionPrivate {
}
}
+ const QRect *begin() const Q_DECL_NOTHROW
+ { return numRects == 1 ? &extents : rects.data(); } // avoid vectorize()
+
+ const QRect *end() const Q_DECL_NOTHROW
+ { return begin() + numRects; }
+
inline void append(const QRect *r);
void append(const QRegionPrivate *r);
void prepend(const QRect *r);
@@ -4248,6 +4348,16 @@ QVector<QRect> QRegion::rects() const
}
}
+QRegion::const_iterator QRegion::begin() const Q_DECL_NOTHROW
+{
+ return d->qt_rgn ? d->qt_rgn->begin() : nullptr;
+}
+
+QRegion::const_iterator QRegion::end() const Q_DECL_NOTHROW
+{
+ return d->qt_rgn ? d->qt_rgn->end() : nullptr;
+}
+
void QRegion::setRects(const QRect *rects, int num)
{
*this = QRegion();
diff --git a/src/gui/painting/qregion.h b/src/gui/painting/qregion.h
index d66f80fcde..f00b1fd284 100644
--- a/src/gui/painting/qregion.h
+++ b/src/gui/painting/qregion.h
@@ -81,6 +81,18 @@ public:
bool isEmpty() const;
bool isNull() const;
+ typedef const QRect *const_iterator;
+ typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+
+ const_iterator begin() const Q_DECL_NOTHROW;
+ const_iterator cbegin() const Q_DECL_NOTHROW { return begin(); }
+ const_iterator end() const Q_DECL_NOTHROW;
+ const_iterator cend() const Q_DECL_NOTHROW { return end(); }
+ const_reverse_iterator rbegin() const Q_DECL_NOTHROW { return const_reverse_iterator(end()); }
+ const_reverse_iterator crbegin() const Q_DECL_NOTHROW { return rbegin(); }
+ const_reverse_iterator rend() const Q_DECL_NOTHROW { return const_reverse_iterator(begin()); }
+ const_reverse_iterator crend() const Q_DECL_NOTHROW { return rend(); }
+
bool contains(const QPoint &p) const;
bool contains(const QRect &r) const;
diff --git a/tests/auto/gui/painting/qregion/tst_qregion.cpp b/tests/auto/gui/painting/qregion/tst_qregion.cpp
index d24435198e..6a297dbfc2 100644
--- a/tests/auto/gui/painting/qregion/tst_qregion.cpp
+++ b/tests/auto/gui/painting/qregion/tst_qregion.cpp
@@ -47,6 +47,7 @@ public:
private slots:
void moveSemantics();
void boundingRect();
+ void rangeFor();
void rects();
void swap();
void setRects();
@@ -136,17 +137,34 @@ void tst_QRegion::boundingRect()
}
+void tst_QRegion::rangeFor()
+{
+ // compile-only test for range-for over QRegion, so really useless
+ // content otherwise:
+ QRect rect(10, -20, 30, 40);
+ QRegion region(rect);
+ int equal = 0;
+ for (const QRect &r : region) // check this compiles
+ equal += int(r == rect); // can't use QCOMPARE here b/c of the
+ // MSVC 201272013 parse bug re:
+ // do-while in range-for loops
+ QCOMPARE(equal, 1);
+}
+
void tst_QRegion::rects()
{
{
QRect rect;
QRegion region(rect);
QVERIFY(region.isEmpty());
+ QCOMPARE(region.begin(), region.end());
QVERIFY(region.rects().isEmpty());
}
{
QRect rect(10, -20, 30, 40);
QRegion region(rect);
+ QCOMPARE(region.end(), region.begin() + 1);
+ QCOMPARE(*region.begin(), rect);
QCOMPARE(region.rects().count(), 1);
QCOMPARE(region.rects()[0], rect);
}
@@ -192,6 +210,7 @@ void tst_QRegion::setRects()
region.setRects(&rect, 0);
QVERIFY(region.isEmpty());
QCOMPARE(region, QRegion());
+ QCOMPARE(region.begin(), region.end());
QVERIFY(!region.boundingRect().isValid());
QVERIFY(region.rects().isEmpty());
}
@@ -199,6 +218,7 @@ void tst_QRegion::setRects()
QRegion region;
QRect rect;
region.setRects(&rect, 1);
+ QCOMPARE(region.begin(), region.end());
QVERIFY(!region.boundingRect().isValid());
QVERIFY(region.rects().isEmpty());
}
@@ -206,8 +226,10 @@ void tst_QRegion::setRects()
QRegion region;
QRect rect(10, -20, 30, 40);
region.setRects(&rect, 1);
+ QCOMPARE(region.end(), region.begin() + 1);
QCOMPARE(region.rects().count(), 1);
QCOMPARE(region.rects()[0], rect);
+ QCOMPARE(*region.begin(), rect);
}
}
@@ -320,8 +342,12 @@ void tst_QRegion::emptyPolygonRegion()
QRegion r(pa);
QTEST(r.isEmpty(), "isEmpty");
+ QTEST(int(std::distance(r.begin(), r.end())), "numRects");
+ QVector<QRect> rects;
+ std::copy(r.begin(), r.end(), std::back_inserter(rects));
QTEST(r.rects().count(), "numRects");
QTEST(r.rects(), "rects");
+ QCOMPARE(r.rects(), rects);
}
@@ -860,6 +886,7 @@ void tst_QRegion::isEmpty()
QFETCH(QRegion, region);
QVERIFY(region.isEmpty());
+ QCOMPARE(region.begin(), region.end());
QCOMPARE(region, QRegion());
QCOMPARE(region.rectCount(), 0);
QCOMPARE(region.boundingRect(), QRect());
@@ -892,6 +919,11 @@ void tst_QRegion::regionFromPath()
path.addRect(0, 100, 100, 1000);
QRegion rgn(path.toFillPolygon().toPolygon());
+
+ QCOMPARE(rgn.end(), rgn.begin() + 2);
+ QCOMPARE(rgn.begin()[0], QRect(0, 0, 10, 10));
+ QCOMPARE(rgn.begin()[1], QRect(0, 100, 100, 1000));
+
QCOMPARE(rgn.rects().size(), 2);
QCOMPARE(rgn.rects().at(0), QRect(0, 0, 10, 10));
QCOMPARE(rgn.rects().at(1), QRect(0, 100, 100, 1000));
@@ -905,8 +937,14 @@ void tst_QRegion::regionFromPath()
path.addRect(10, 10, 80, 80);
QRegion rgn(path.toFillPolygon().toPolygon());
- QCOMPARE(rgn.rects().size(), 4);
+ QCOMPARE(rgn.end(), rgn.begin() + 4);
+ QCOMPARE(rgn.begin()[0], QRect(0, 0, 100, 10));
+ QCOMPARE(rgn.begin()[1], QRect(0, 10, 10, 80));
+ QCOMPARE(rgn.begin()[2], QRect(90, 10, 10, 80));
+ QCOMPARE(rgn.begin()[3], QRect(0, 90, 100, 10));
+
+ QCOMPARE(rgn.rects().size(), 4);
QCOMPARE(rgn.rects().at(0), QRect(0, 0, 100, 10));
QCOMPARE(rgn.rects().at(1), QRect(0, 10, 10, 80));
QCOMPARE(rgn.rects().at(2), QRect(90, 10, 10, 80));