diff options
-rw-r--r-- | src/gui/painting/qregion.cpp | 65 | ||||
-rw-r--r-- | src/gui/painting/qregion.h | 6 | ||||
-rw-r--r-- | tests/auto/gui/painting/qregion/tst_qregion.cpp | 24 |
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" |