diff options
Diffstat (limited to 'tests/auto/qregion/tst_qregion.cpp')
-rw-r--r-- | tests/auto/qregion/tst_qregion.cpp | 1021 |
1 files changed, 1021 insertions, 0 deletions
diff --git a/tests/auto/qregion/tst_qregion.cpp b/tests/auto/qregion/tst_qregion.cpp new file mode 100644 index 0000000..2afeaed --- /dev/null +++ b/tests/auto/qregion/tst_qregion.cpp @@ -0,0 +1,1021 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <QtTest/QtTest> +#include <qregion.h> + +#include <qbitmap.h> +#include <qpainter.h> +#include <qpolygon.h> +#ifdef Q_WS_X11 +#include <private/qt_x11_p.h> +#endif + + +//TESTED_CLASS= +//TESTED_FILES= + +class tst_QRegion : public QObject +{ + Q_OBJECT + +public: + tst_QRegion(); + +private slots: + void boundingRect(); + void rects(); + void setRects(); + void ellipseRegion(); + void polygonRegion(); + void bitmapRegion(); + void intersected_data(); + void intersected(); + void emptyPolygonRegion_data(); + void emptyPolygonRegion(); + + void intersects_region_data(); + void intersects_region(); + void intersects_rect_data(); + void intersects_rect(); + void contains_point(); + + void operator_plus_data(); + void operator_plus(); + void operator_minus_data(); + void operator_minus(); + void operator_intersect_data(); + void operator_intersect(); + void operator_xor_data(); + void operator_xor(); + + void numRects_data(); + void numRects(); + + void isEmpty_data(); + void isEmpty(); +#ifdef Q_OS_WIN + void handle(); +#endif +#ifdef Q_WS_X11 + void clipRectangles(); +#endif + + void regionFromPath(); + + void regionToPath_data(); + void regionToPath(); +}; + +Q_DECLARE_METATYPE(QPolygon) +Q_DECLARE_METATYPE(QVector<QRect>) +Q_DECLARE_METATYPE(QRegion) + +tst_QRegion::tst_QRegion() +{ +} + +void tst_QRegion::boundingRect() +{ + { + QRect rect; + QRegion region( rect ); + QCOMPARE( region.boundingRect(), rect ); + } + { + QRect rect( 10, -20, 30, 40 ); + QRegion region( rect ); + QCOMPARE( region.boundingRect(), rect ); + } + { + QRect rect(15,25,10,10); + QRegion region( rect ); + QCOMPARE( region.boundingRect(), rect ); + } + +} + +void tst_QRegion::rects() +{ + { + QRect rect; + QRegion region( rect ); + QVERIFY( region.isEmpty() ); + QVERIFY( region.rects().isEmpty() ); + } + { + QRect rect( 10, -20, 30, 40 ); + QRegion region( rect ); +#if QT_VERSION < 0x040000 + QCOMPARE( region.rects().count(), (uint)1 ); +#else + QCOMPARE( region.rects().count(), 1 ); +#endif + + QCOMPARE( region.rects()[0], rect ); + } + { + QRect r( QPoint(10, 10), QPoint(40, 40) ); + QRegion region( r ); + QVERIFY( region.contains( QPoint(10,10) ) ); + QVERIFY( region.contains( QPoint(20,40) ) ); + QVERIFY( region.contains( QPoint(40,20) ) ); + QVERIFY( !region.contains( QPoint(20,41) ) ); + QVERIFY( !region.contains( QPoint(41,20) ) ); + } + { + QRect r( 10, 10, 30, 30 ); + QRegion region( r ); + QVERIFY( region.contains( QPoint(10,10) ) ); + QVERIFY( region.contains( QPoint(20,39) ) ); + QVERIFY( region.contains( QPoint(39,20) ) ); + QVERIFY( !region.contains( QPoint(20,40) ) ); + QVERIFY( !region.contains( QPoint(40,20) ) ); + } +} + +void tst_QRegion::setRects() +{ + { + QRegion region; + region.setRects( 0, 0 ); + QVERIFY( region.rects().isEmpty() ); + } + { + QRegion region; + QRect rect; + region.setRects( &rect, 0 ); + QVERIFY(region.isEmpty()); + QVERIFY(region == QRegion()); + QVERIFY(!region.boundingRect().isValid()); + QVERIFY(region.rects().isEmpty()); + } + { + QRegion region; + QRect rect; + region.setRects( &rect, 1 ); + QVERIFY( !region.boundingRect().isValid() ); + QVERIFY( region.rects().isEmpty() ); + } + { + QRegion region; + QRect rect( 10, -20, 30, 40 ); + region.setRects( &rect, 1 ); +#if QT_VERSION < 0x040000 + QCOMPARE( region.rects().count(), (uint)1 ); +#else + QCOMPARE( region.rects().count(), 1 ); +#endif + QCOMPARE( region.rects()[0], rect ); + } +} + +void tst_QRegion::ellipseRegion() +{ + QRegion region(0, 0, 100, 100, QRegion::Ellipse); + + // These should not be inside the circe + QVERIFY(!region.contains(QPoint(13, 13))); + QVERIFY(!region.contains(QPoint(13, 86))); + QVERIFY(!region.contains(QPoint(86, 13))); + QVERIFY(!region.contains(QPoint(86, 86))); + + // These should be inside + QVERIFY(region.contains(QPoint(16, 16))); + QVERIFY(region.contains(QPoint(16, 83))); + QVERIFY(region.contains(QPoint(83, 16))); + QVERIFY(region.contains(QPoint(83, 83))); + + // ..a.. + // .. .. + // . . + // . . + // b c + // . . + // . . + // .. .. + // ..d.. + QVERIFY(region.contains(QPoint(50, 0))); // Mid-top (a) + QVERIFY(region.contains(QPoint(0, 50))); // Mid-left (b) + QVERIFY(region.contains(QPoint(99, 50))); // Mid-right (c) + QVERIFY(region.contains(QPoint(50, 99))); // Mid-bottom (d) + + QRect bounds = region.boundingRect(); + QCOMPARE(bounds.x(), 0); + QCOMPARE(bounds.y(), 0); + QCOMPARE(bounds.width(), 100); + QCOMPARE(bounds.height(), 100); +} + +void tst_QRegion::polygonRegion() +{ + QPolygon pa; + { + QRegion region ( pa ); + QVERIFY( region.isEmpty() ); + } + { + pa.setPoints( 8, 10, 10, // a____________b + 40, 10, // | | + 40, 20, // |___ ___| + 30, 20, // | | + 30, 40, // | | + 20, 40, // | | + 20, 20, // |____c + 10, 20 ); + + QRegion region ( pa ); + QVERIFY( !region.isEmpty() ); + + // These should not be inside the circle + QVERIFY( !region.contains( QPoint( 9, 9 ) ) ); + QVERIFY( !region.contains( QPoint( 30, 41 ) ) ); + QVERIFY( !region.contains( QPoint( 41, 10 ) ) ); + QVERIFY( !region.contains( QPoint( 31, 21 ) ) ); + + // These should be inside + QVERIFY( region.contains( QPoint( 10, 10 ) ) ); // Upper-left (a) + + } +} + +void tst_QRegion::emptyPolygonRegion_data() +{ + QTest::addColumn<QPolygon>("pa"); + QTest::addColumn<bool>("isEmpty"); + QTest::addColumn<int>("numRects"); + QTest::addColumn<QVector<QRect> >("rects"); + + QPolygon pa; + + + QTest::newRow("no points") << pa << true << 0 << QVector<QRect>(); + pa = QPolygon() << QPoint(10,10); + QTest::newRow("one point") << pa << true << 0 << QVector<QRect>(); + pa = QPolygon() << QPoint(10,10) << QPoint(10,20); + QTest::newRow("two points, horizontal") << pa << true << 0 << QVector<QRect>(); + + pa = QPolygon() << QPoint(10,10) << QPoint(20,10); + QTest::newRow("two points, vertical") << pa << true << 0 << QVector<QRect>(); + + pa = QPolygon() << QPoint(10,10) << QPoint(20,20); + QTest::newRow("two points, diagonal") << pa << true << 0 << QVector<QRect>(); + + pa = QPolygon() << QPoint(10,10) << QPoint(15,15) << QPoint(10,15) << QPoint(10, 10) ; + QVector<QRect> v; + v << QRect(10,11,1, 1) << QRect(10,12,2,1) << QRect(10,13,3,1) << QRect(10,14,4,1); + QTest::newRow("triangle") << pa << false << 4 << v; + + v.clear(); + v << QRect(10,10,10,10); + + QTest::newRow("rectangle") << QPolygon(QRect(10,10,10,10)) << false << 1 << v; + +} + +void tst_QRegion::emptyPolygonRegion() +{ + QFETCH(QPolygon, pa); + + QRegion r(pa); + QTEST(r.isEmpty(), "isEmpty"); + QTEST(r.rects().count(), "numRects"); + QTEST(r.rects(), "rects"); +} + + +static const char *circle_xpm[] = { + "20 20 2 1", + " c #FFFFFF", + ". c #000000", + " ...... ", + " .......... ", + " .............. ", + " ................ ", + " ................ ", + " .................. ", + " .................. ", + "....................", + "....................", + "....................", + "....................", + "....................", + "....................", + " .................. ", + " .................. ", + " ................ ", + " ................ ", + " .............. ", + " .......... ", + " ...... " +}; + +void tst_QRegion::bitmapRegion() +{ + QBitmap circle; + { + QRegion region( circle ); + QVERIFY( region.isEmpty() ); + } + { + circle = QPixmap( circle_xpm ); + QRegion region( circle ); + + //// These should not be inside the circe + QVERIFY( !region.contains( QPoint( 2, 2 ) ) ); + QVERIFY( !region.contains( QPoint( 2, 17 ) ) ); + QVERIFY( !region.contains( QPoint( 17, 2 ) ) ); + QVERIFY( !region.contains( QPoint( 17, 17 ) ) ); + + //// These should be inside + QVERIFY( region.contains( QPoint( 3, 3 ) ) ); + QVERIFY( region.contains( QPoint( 3, 16 ) ) ); + QVERIFY( region.contains( QPoint( 16, 3 ) ) ); + QVERIFY( region.contains( QPoint( 16, 16 ) ) ); + + QVERIFY( region.contains( QPoint( 0, 10 ) ) ); // Mid-left + QVERIFY( region.contains( QPoint( 10, 0 ) ) ); // Mid-top +#if ( QT_VERSION >= 0x030100 ) + QVERIFY( region.contains( QPoint( 19, 10 ) ) ); // Mid-right +#endif + QVERIFY( region.contains( QPoint( 10, 19 ) ) ); // Mid-bottom + } +} + +void tst_QRegion::intersected_data() +{ + QTest::addColumn<QRegion>("r1"); + QTest::addColumn<QRegion>("r2"); + QTest::addColumn<bool>("intersects"); + // QTest::addColumn<QRegion>("intersected"); + + QPolygon ps1(8); + QPolygon ps2(8); + ps1.putPoints(0,8, 20,20, 50,20, 50,100, 70,100, 70,20, 120,20, 120,200, 20, 200); + ps2.putPoints(0,8, 100,150, 140,150, 140,160, 160,160, 160,150, 200,150, 200,180, 100,180); + QTest::newRow("task30716") << QRegion(ps1) << QRegion(ps2) << true; +} + +void tst_QRegion::intersected() +{ + QFETCH(QRegion, r1); + QFETCH(QRegion, r2); + QFETCH(bool, intersects); + + QRegion interReg = r1.intersected(r2); + QVERIFY(interReg.isEmpty() != intersects); + // Need a way to test the intersected QRegion is right +} + +void tst_QRegion::intersects_region_data() +{ + QTest::addColumn<QRegion>("r1"); + QTest::addColumn<QRegion>("r2"); + QTest::addColumn<bool>("intersects"); + + QTest::newRow("rect overlap rect") << QRegion(100, 100, 200, 200) + << QRegion(200, 200, 200, 200) + << true; + + QTest::newRow("rect not overlap rect") << QRegion(100, 100, 200, 200) + << QRegion(400, 400, 200, 200) + << false; + + QTest::newRow("ellipse overlap ellipse") << QRegion(100, 100, 200, 200, QRegion::Ellipse) + << QRegion(200, 200, 200, 200, QRegion::Ellipse) + << true; + + QTest::newRow("ellipse not overlap ellipse") << QRegion(100, 100, 200, 200, QRegion::Ellipse) + << QRegion(400, 400, 200, 200, QRegion::Ellipse) + << false; +} + +void tst_QRegion::intersects_region() +{ + QFETCH(QRegion, r1); + QFETCH(QRegion, r2); + QFETCH(bool, intersects); + QCOMPARE(r1.intersects(r2), intersects); +} + + +void tst_QRegion::intersects_rect_data() +{ + QTest::addColumn<QRegion>("region"); + QTest::addColumn<QRect>("rect"); + QTest::addColumn<bool>("intersects"); + + QTest::newRow("rect overlap rect") << QRegion(100, 100, 200, 200) + << QRect(200, 200, 200, 200) + << true; + + QTest::newRow("rect not overlap rect") << QRegion(100, 100, 200, 200) + << QRect(400, 400, 200, 200) + << false; + + QTest::newRow("ellipse overlap rect") << QRegion(100, 100, 200, 200, QRegion::Ellipse) + << QRect(200, 200, 200, 200) + << true; + + QTest::newRow("ellipse not overlap rect") << QRegion(100, 100, 200, 200, QRegion::Ellipse) + << QRect(400, 400, 200, 200) + << false; +} + +void tst_QRegion::intersects_rect() +{ + QFETCH(QRegion, region); + QFETCH(QRect, rect); + QFETCH(bool, intersects); + QCOMPARE(region.intersects(rect), intersects); +} + +void tst_QRegion::contains_point() +{ + QCOMPARE(QRegion().contains(QPoint(1,1)),false); + QCOMPARE(QRegion(0,0,2,2).contains(QPoint(1,1)),true); +} + +void tst_QRegion::operator_plus_data() +{ + QTest::addColumn<QRegion>("r1"); + QTest::addColumn<QRegion>("r2"); + QTest::addColumn<QRegion>("expected"); + + QTest::newRow("empty 0") << QRegion() << QRegion() << QRegion(); + QTest::newRow("empty 1") << QRegion() << QRegion(QRect(10, 10, 10, 10)) + << QRegion(QRect(10, 10, 10, 10)); + QTest::newRow("empty 2") << QRegion(QRect(10, 10, 10, 10)) << QRegion() + << QRegion(QRect(10, 10, 10, 10)); + + QRegion expected; + QVector<QRect> rects; + rects << QRect(10, 10, 10, 10) << QRect(22, 10, 10, 10); + expected.setRects(rects.constData(), rects.size()); + QTest::newRow("non overlapping") << QRegion(10, 10, 10, 10) + << QRegion(22, 10, 10, 10) + << expected; + + rects.clear(); + rects << QRect(50, 0, 50, 2); + expected.setRects(rects.constData(), rects.size()); + QTest::newRow("adjacent y-rects") << QRegion(50, 0, 50, 1) + << QRegion(50, 1, 50, 1) + << expected; + + rects.clear(); + rects << QRect(50, 0, 2, 1); + expected.setRects(rects.constData(), rects.size()); + QTest::newRow("adjacent x-rects") << QRegion(50, 0, 1, 1) + << QRegion(51, 0, 1, 1) + << expected; + + rects.clear(); + rects << QRect(10, 10, 10, 10) << QRect(10, 20, 5, 10); + QRegion r1; + r1.setRects(rects.constData(), rects.size()); + QTest::newRow("double merge") << r1 << QRegion(15, 20, 5, 10) + << QRegion(10, 10, 10, 20); + rects.clear(); + rects << QRect(15, 10, 5, 10) << QRect(10, 20, 10, 10); + r1.setRects(rects.constData(), rects.size()); + QTest::newRow("double merge 2") << r1 << QRegion(10, 10, 5, 10) + << QRegion(10, 10, 10, 20); + QTest::newRow("overlapping x") << QRegion(10, 10, 10, 10) + << QRegion(15, 10, 10, 10) + << QRegion(10, 10, 15, 10); + QTest::newRow("overlapping y") << QRegion(10, 10, 10, 10) + << QRegion(10, 15, 10, 10) + << QRegion(10, 10, 10, 15); + rects.clear(); + rects << QRect(10, 10, 10, 10) << QRect(10, 20, 5, 10); + r1.setRects(rects.constData(), rects.size()); + rects.clear(); + rects << QRect(15, 20, 5, 10) << QRect(10, 30, 10, 10); + QRegion r2; + r2.setRects(rects.constData(), rects.size()); + QTest::newRow("triple merge") << r1 << r2 + << QRegion(10, 10, 10, 30); + + rects.clear(); + rects << QRect(10, 10, 4, 10) << QRect(15, 10, 10, 10); + r1.setRects(rects.constData(), rects.size()); + rects.clear(); + rects << QRect(15, 20, 10, 10); + r2.setRects(rects.constData(), rects.size()); + rects.clear(); + rects << QRect(10, 10, 4, 10) << QRect(15, 10, 10, 10) + << QRect(15, 20, 10, 10); + expected.setRects(rects.constData(), rects.size()); + QTest::newRow("don't merge y") << r1 << r2 << expected; + + QTest::newRow("equal 1") << QRegion(10, 10, 10, 10) + << QRegion(10, 10, 10, 10) + << QRegion(10, 10, 10, 10); + QTest::newRow("equal 2") << expected << expected << expected; +} + +void tst_QRegion::operator_plus() +{ + QFETCH(QRegion, r1); + QFETCH(QRegion, r2); + QFETCH(QRegion, expected); + + if (r1 + r2 != expected) { + qDebug() << "r1 + r2" << (r1 + r2); + qDebug() << "expected" << expected; + } + QCOMPARE(r1 + r2, expected); + if (r2.numRects() == 1) { + if (r1 + r2.boundingRect() != expected) { + qDebug() << "r1 + QRect(r2)" << (r1 + r2.boundingRect()); + qDebug() << "expected" << expected; + } + QCOMPARE(r1 + r2.boundingRect(), expected); + } + + if (r2 + r1 != expected) { + qDebug() << "r2 + r1" << (r2 + r1); + qDebug() << "expected" << expected; + } + QCOMPARE(r2 + r1, expected); + if (r1.numRects() == 1) { + if (r1 + r2.boundingRect() != expected) { + qDebug() << "r2 + QRect(r1)" << (r2 + r1.boundingRect()); + qDebug() << "expected" << expected; + } + QCOMPARE(r2 + r1.boundingRect(), expected); + } + + QRegion result1 = r1; + result1 += r2; + if (result1 != expected) { + qDebug() << "r1 += r2" << result1; + qDebug() << "expected" << expected; + } + QCOMPARE(result1, expected); + if (r2.numRects() == 1) { + result1 = r1; + result1 += r2.boundingRect(); + if (result1 != expected) { + qDebug() << "r1 += QRect(r2)" << result1; + qDebug() << "expected" << expected; + } + QCOMPARE(result1, expected); + } + + QRegion result2 = r2; + result2 += r1; + if (result2 != expected) { + qDebug() << "r2 += r1" << result2; + qDebug() << "expected" << expected; + } + QCOMPARE(result2, expected); + if (r1.numRects() == 1) { + result2 = r2; + result2 += r1.boundingRect(); + if (result2 != expected) { + qDebug() << "r2 += QRect(r1)" << result2; + qDebug() << "expected" << expected; + } + QCOMPARE(result2, expected); + } +} + +void tst_QRegion::operator_minus_data() +{ + QTest::addColumn<QRegion>("dest"); + QTest::addColumn<QRegion>("subtract"); + QTest::addColumn<QRegion>("expected"); + +#if !defined(Q_WS_X11) || QT_VERSION >= 0x040300 + QTest::newRow("empty 0") << QRegion() << QRegion() << QRegion(); + QTest::newRow("empty 1") << QRegion() << QRegion(QRect(10, 10, 10, 10)) + << QRegion(); +#endif + QTest::newRow("empty 2") << QRegion(QRect(10, 10, 10, 10)) << QRegion() + << QRegion(QRect(10, 10, 10, 10)); + + QRegion dest; + QVector<QRect> rects; + rects << QRect(10, 10, 10, 10) << QRect(22, 10, 10, 10); + dest.setRects(rects.constData(), rects.size()); + QTest::newRow("simple 1") << dest + << QRegion(22, 10, 10, 10) + << QRegion(10, 10, 10, 10); + QTest::newRow("simple 2") << dest + << QRegion(10, 10, 10, 10) + << QRegion(22, 10, 10, 10); + + rects.clear(); + rects << QRect(0, 0, 10, 10) << QRect(15, 0, 10, 10); + dest.setRects(rects.constData(), rects.size()); + + QRegion minus; + rects.clear(); + rects << QRect(0, 0, 12, 12) << QRect(15, 0, 12, 12); + minus.setRects(rects.constData(), rects.size()); + QTest::newRow("empty 3") << dest << minus << QRegion(); +} + +void tst_QRegion::operator_minus() +{ + QFETCH(QRegion, dest); + QFETCH(QRegion, subtract); + QFETCH(QRegion, expected); + + if (dest - subtract != expected) { + qDebug() << "dest - subtract" << (dest - subtract); + qDebug() << "expected" << expected; + }; + QCOMPARE(dest - subtract, expected); + + dest -= subtract; + + if (dest != expected) { + qDebug() << "dest" << dest; + qDebug() << "expected" << expected; + }; + QCOMPARE(dest, expected); +} + +void tst_QRegion::operator_intersect_data() +{ + QTest::addColumn<QRegion>("r1"); + QTest::addColumn<QRegion>("r2"); + QTest::addColumn<QRegion>("expected"); + + QTest::newRow("empty 0") << QRegion() << QRegion() << QRegion(); + QTest::newRow("empty 1") << QRegion() << QRegion(QRect(10, 10, 10, 10)) + << QRegion(); + QTest::newRow("empty 2") << QRegion(QRect(10, 10, 10, 10)) << QRegion() + << QRegion(); + + QRegion dest; + QVector<QRect> rects; + rects << QRect(10, 10, 10, 10) << QRect(22, 10, 10, 10); + dest.setRects(rects.constData(), rects.size()); + QTest::newRow("simple 1") << dest + << QRegion(22, 10, 10, 10) + << QRegion(22, 10, 10, 10); + QTest::newRow("simple 2") << dest + << QRegion(10, 10, 10, 10) + << QRegion(10, 10, 10, 10); + + rects.clear(); + rects << QRect(10, 10, 10, 10) << QRect(10, 20, 15, 10); + dest.setRects(rects.constData(), rects.size()); + QTest::newRow("merge 1") << dest + << QRegion(10, 10, 10, 20) + << QRegion(10, 10, 10, 20); + + rects.clear(); + rects << QRect(11, 11, 218, 117) << QRect(11, 128, 218, 27) + << QRect(264, 128, 122, 27) << QRect(11, 155, 218, 43) + << QRect(11, 198, 218, 27) << QRect(264, 198, 122, 27) + << QRect(11, 225, 218, 221); + dest.setRects(rects.constData(), rects.size()); + QTest::newRow("merge 2") << dest << QRegion(11, 11, 218, 458) + << QRegion(11, 11, 218, 435); + + rects.clear(); + rects << QRect(0, 0, 10, 10) << QRect(20, 0, 10, 10); + dest.setRects(rects.constData(), rects.size()); + QTest::newRow("empty 3") << dest << QRegion(11, 0, 5, 5) << QRegion(); + + QTest::newRow("extents check") << dest << QRegion(0, 0, 15, 15) + << QRegion(0, 0, 10, 10); + + rects.clear(); + rects << QRect(10, 10, 10, 10) << QRect(10, 20, 10, 10) + << QRect(30, 20, 10, 10) << QRect(10, 30, 10, 10); + dest.setRects(rects.constData(), rects.size()); + rects.clear(); + rects << QRect(10, 10, 10, 10) << QRect(10, 20, 10, 10) + << QRect(30, 20, 10, 10); + QRegion expected; + expected.setRects(rects.constData(), rects.size()); + QTest::newRow("dont merge") << dest << QRegion(0, 0, 100, 30) + << expected; +} + +void tst_QRegion::operator_intersect() +{ + QFETCH(QRegion, r1); + QFETCH(QRegion, r2); + QFETCH(QRegion, expected); + + if ((r1 & r2) != expected) { + qDebug() << "r1 & r2" << (r1 & r2); + qDebug() << "expected" << expected; + } + QCOMPARE(r1 & r2, expected); + + if ((r2 & r1) != expected) { + qDebug() << "r2 & r1" << (r2 & r1); + qDebug() << "expected" << expected; + } + QCOMPARE(r2 & r1, expected); + + r1 &= r2; + QCOMPARE(r1, expected); +} + +void tst_QRegion::operator_xor_data() +{ + QTest::addColumn<QRegion>("dest"); + QTest::addColumn<QRegion>("arg"); + QTest::addColumn<QRegion>("expected"); + + QTest::newRow("empty 0") << QRegion() << QRegion() << QRegion(); + QTest::newRow("empty 1") << QRegion() << QRegion(QRect(10, 10, 10, 10)) + << QRegion(QRect(10, 10, 10, 10)); + QTest::newRow("empty 2") << QRegion(QRect(10, 10, 10, 10)) << QRegion() + << QRegion(QRect(10, 10, 10, 10)); + + QRegion dest; + QVector<QRect> rects; + rects << QRect(10, 10, 10, 10) << QRect(22, 10, 10, 10); + dest.setRects(rects.constData(), rects.size()); + QTest::newRow("simple 1") << dest + << QRegion(22, 10, 10, 10) + << QRegion(10, 10, 10, 10); + QTest::newRow("simple 2") << dest + << QRegion(10, 10, 10, 10) + << QRegion(22, 10, 10, 10); + QTest::newRow("simple 3") << dest << dest << QRegion(); + QTest::newRow("simple 4") << QRegion(10, 10, 10, 10) + << QRegion(10, 10, 5, 10) + << QRegion(15, 10, 5, 10); + QTest::newRow("simple 5") << QRegion(10, 10, 10, 10) + << QRegion(10, 10, 10, 5) + << QRegion(10, 15, 10, 5); + + const QRegion rgnA(0, 0, 100, 100); + const QRegion rgnB(0, 0, 10, 10); + + QTest::newRow("simple 6") << rgnA + << rgnA - rgnB + << rgnB; + + QTest::newRow("simple 7") << rgnB + << rgnA + << rgnA - rgnB; +} + +void tst_QRegion::operator_xor() +{ + QFETCH(QRegion, dest); + QFETCH(QRegion, arg); + QFETCH(QRegion, expected); + + QCOMPARE(dest ^ arg, expected); + QCOMPARE(dest.xored(arg), expected); + + dest ^= arg; + QCOMPARE(dest, expected); +} + +void tst_QRegion::numRects_data() +{ + QTest::addColumn<QRegion>("region"); + QTest::addColumn<int>("expected"); + + QTest::newRow("empty") << QRegion() << 0; + QTest::newRow("rect") << QRegion(10, 10, 10, 10) << 1; + + QRegion dest; + QVector<QRect> rects; + rects << QRect(10, 10, 10, 10) << QRect(22, 10, 10, 10); + dest.setRects(rects.constData(), rects.size()); + + QTest::newRow("2 rects") << dest << rects.size(); +} + +void tst_QRegion::numRects() +{ + QFETCH(QRegion, region); + QFETCH(int, expected); + + QCOMPARE(region.numRects(), expected); +} + +void tst_QRegion::isEmpty_data() +{ + QTest::addColumn<QRegion>("region"); + + QTest::newRow("QRegion") << QRegion(); + + QVector<QRect> rects; + rects << QRect(0, 0, 10, 10) << QRect(15, 0, 10, 10); + QRegion r1; + r1.setRects(rects.constData(), rects.size()); + + QRegion r2; + rects.clear(); + rects << QRect(0, 0, 12, 12) << QRect(15, 0, 12, 12); + r2.setRects(rects.constData(), rects.size()); + QTest::newRow("minus") << (r1 - r2); +} + +void tst_QRegion::isEmpty() +{ + QFETCH(QRegion, region); + + QVERIFY(region.isEmpty()); + QCOMPARE(region, QRegion()); + QCOMPARE(region.numRects(), 0); + QCOMPARE(region.boundingRect(), QRect()); + QVERIFY(region.rects().isEmpty()); +} + +#ifdef Q_OS_WIN +void tst_QRegion::handle() +{ + QRegion r; + HRGN hrgn = r.handle(); + QRegion r2(QRect(0,0,10,10)); + hrgn = r2.handle(); +} +#endif + +#ifdef Q_WS_X11 +void tst_QRegion::clipRectangles() +{ + QRegion region(30, 30, 30, 30); + int num = 0; + qt_getClipRects(region, num); + QCOMPARE(num, 1); + + region += QRegion(10, 10, 10, 10); + XRectangle *rects2 = static_cast<XRectangle *>(qt_getClipRects(region, num)); + QCOMPARE(num, 2); + + // Here's the important part (Y-sorted): + QCOMPARE(int(rects2[0].y), 10); + QCOMPARE(int(rects2[1].y), 30); +} +#endif + +void tst_QRegion::regionFromPath() +{ + { + QPainterPath path; + path.addRect(0, 0, 10, 10); + path.addRect(0, 100, 100, 1000); + + QRegion rgn(path.toFillPolygon().toPolygon()); + 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)); + + QCOMPARE(rgn.boundingRect(), QRect(0, 0, 100, 1100)); + } + + { + QPainterPath path; + path.addRect(0, 0, 100, 100); + path.addRect(10, 10, 80, 80); + + QRegion rgn(path.toFillPolygon().toPolygon()); + 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)); + QCOMPARE(rgn.rects().at(3), QRect(0, 90, 100, 10)); + + QCOMPARE(rgn.boundingRect(), QRect(0, 0, 100, 100)); + } +} + +Q_DECLARE_METATYPE(QPainterPath) + +void tst_QRegion::regionToPath_data() +{ + QTest::addColumn<QPainterPath>("path"); + { + QPainterPath path; + path.addRect(QRect(0, 0, 10, 10)); + + QTest::newRow("Rectangle") << path; + } + + { + QPainterPath path; + path.addRect(QRect(0, 0, 10, 10)); + path.addRect(QRect(20, 0, 10, 10)); + + QTest::newRow("Two rects") << path; + } + + { + QPainterPath path; + path.addEllipse(QRect(0, 0, 10, 10)); + + QTest::newRow("Ellipse") << path; + } + + { + QPainterPath path; + path.addRect(QRect(0, 0, 3, 8)); + path.addRect(QRect(6, 0, 3, 8)); + path.addRect(QRect(3, 3, 3, 2)); + path.addRect(QRect(12, 3, 3, 2)); + + QTest::newRow("H-dot") << path; + } + + { + QPainterPath path; + for (int y = 0; y <= 10; ++y) { + for (int x = 0; x <= 10; ++x) { + if (!(y & 1) || ((x ^ y) & 1)) + path.addRect(QRect(x, y, 1, 1)); + } + } + + QTest::newRow("Grid") << path; + } +} + +void tst_QRegion::regionToPath() +{ + extern QPainterPath qt_regionToPath(const QRegion ®ion); + + QFETCH(QPainterPath, path); + + for (int i = 0; i < 360; i += 10) { + + QTransform transform; + transform.scale(5, 5); + transform.rotate(i); + + QPainterPath mapped = transform.map(path); + QRegion region(mapped.toFillPolygon().toPolygon()); + + QPainterPath a; + a.addRegion(region); + + QPainterPath b = qt_regionToPath(region); + + QRect r = a.boundingRect().toAlignedRect(); + QImage ia(r.size(), QImage::Format_RGB32); + ia.fill(0xffffffff); + QImage ib = ia; + + QPainter p(&ia); + p.translate(-r.x(), -r.y()); + p.fillPath(a, Qt::red); + p.end(); + p.begin(&ib); + p.translate(-r.x(), -r.y()); + p.fillPath(b, Qt::red); + p.end(); + + QCOMPARE(ia, ib); + QCOMPARE(a.boundingRect(), b.boundingRect()); + } +} + +QTEST_MAIN(tst_QRegion) +#include "tst_qregion.moc" |