summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gui/painting/qregion.cpp65
-rw-r--r--src/gui/painting/qregion.h6
-rw-r--r--tests/auto/gui/painting/qregion/tst_qregion.cpp24
3 files changed, 94 insertions, 1 deletions
diff --git a/src/gui/painting/qregion.cpp b/src/gui/painting/qregion.cpp
index a635b66d27..5685d34ea7 100644
--- a/src/gui/painting/qregion.cpp
+++ b/src/gui/painting/qregion.cpp
@@ -50,6 +50,10 @@
#include <private/qdebug_p.h>
+#ifdef Q_OS_WIN
+# include <qt_windows.h>
+#endif
+
QT_BEGIN_NAMESPACE
/*!
@@ -4314,4 +4318,65 @@ bool QRegion::intersects(const QRect &rect) const
#endif
+
+#if defined(Q_OS_WIN) || defined(Q_QDOC)
+
+static inline HRGN qt_RectToHRGN(const QRect &rc)
+{
+ return CreateRectRgn(rc.left(), rc.top(), rc.right() + 1, rc.bottom() + 1);
+}
+
+/*!
+ \since 6.0
+
+ Returns a HRGN that is equivalent to the given region.
+*/
+HRGN QRegion::toHRGN() const
+{
+ const int size = rectCount();
+ if (size == 0)
+ return nullptr;
+
+ HRGN resultRgn = nullptr;
+ const auto rects = begin();
+ resultRgn = qt_RectToHRGN(rects[0]);
+ for (int i = 1; i < size; ++i) {
+ HRGN tmpRgn = qt_RectToHRGN(rects[i]);
+ int err = CombineRgn(resultRgn, resultRgn, tmpRgn, RGN_OR);
+ if (err == ERROR)
+ qWarning("Error combining HRGNs.");
+ DeleteObject(tmpRgn);
+ }
+ return resultRgn;
+}
+
+/*!
+ \since 6.0
+
+ Returns a QRegion that is equivalent to the given \a hrgn.
+ */
+QRegion QRegion::fromHRGN(HRGN hrgn)
+{
+ DWORD regionDataSize = GetRegionData(hrgn, 0, nullptr);
+ if (regionDataSize == 0)
+ return QRegion();
+
+ auto regionData = reinterpret_cast<LPRGNDATA>(malloc(regionDataSize));
+ if (!regionData)
+ return QRegion();
+
+ QRegion region;
+ if (GetRegionData(hrgn, regionDataSize, regionData) == regionDataSize) {
+ auto pRect = reinterpret_cast<LPRECT>(regionData->Buffer);
+ for (DWORD i = 0; i < regionData->rdh.nCount; ++i)
+ region += QRect(pRect[i].left, pRect[i].top,
+ pRect[i].right - pRect[i].left,
+ pRect[i].bottom - pRect[i].top);
+ }
+
+ free(regionData);
+ return region;
+}
+#endif // Q_OS_WIN || Q_QDOC
+
QT_END_NAMESPACE
diff --git a/src/gui/painting/qregion.h b/src/gui/painting/qregion.h
index 49174e7510..c4c0164a5b 100644
--- a/src/gui/painting/qregion.h
+++ b/src/gui/painting/qregion.h
@@ -134,6 +134,12 @@ public:
inline bool operator!=(const QRegion &r) const { return !(operator==(r)); }
operator QVariant() const;
+ // Platform specific conversion functions
+#if defined(Q_OS_WIN) || defined(Q_QDOC)
+ HRGN toHRGN() const;
+ static QRegion fromHRGN(HRGN hrgn);
+#endif
+
#ifndef QT_NO_DATASTREAM
friend Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QRegion &);
friend Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QRegion &);
diff --git a/tests/auto/gui/painting/qregion/tst_qregion.cpp b/tests/auto/gui/painting/qregion/tst_qregion.cpp
index 93d2baf332..dc694e1107 100644
--- a/tests/auto/gui/painting/qregion/tst_qregion.cpp
+++ b/tests/auto/gui/painting/qregion/tst_qregion.cpp
@@ -35,6 +35,10 @@
#include <qpainterpath.h>
#include <qpolygon.h>
+#ifdef Q_OS_WIN
+# include <qt_windows.h>
+#endif
+
class tst_QRegion : public QObject
{
Q_OBJECT
@@ -86,6 +90,10 @@ private slots:
void regionToPath_data();
void regionToPath();
#endif
+
+#ifdef Q_OS_WIN
+ void winConversion();
+#endif
};
tst_QRegion::tst_QRegion()
@@ -1061,7 +1069,21 @@ void tst_QRegion::regionToPath()
QCOMPARE(a.boundingRect(), b.boundingRect());
}
}
-#endif
+#endif // QT_BUILD_INTERNAL
+
+#ifdef Q_OS_WIN
+void tst_QRegion::winConversion()
+{
+ const QList<QRect> rects{QRect(10, 10, 10, 10), QRect(10, 20, 10, 10),
+ QRect(30, 20, 10, 10), QRect(10, 30, 10, 10)};
+ QRegion region;
+ region.setRects(rects.constData(), rects.size());
+ auto hrgn = region.toHRGN();
+ QVERIFY(hrgn);
+ QRegion convertedBack = QRegion::fromHRGN(hrgn);
+ QCOMPARE(region, convertedBack);
+}
+#endif // Q_OS_WIN
QTEST_MAIN(tst_QRegion)
#include "tst_qregion.moc"