| /**************************************************************************** |
| ** |
| ** Copyright (C) 2016 The Qt Company Ltd. |
| ** Contact: https://www.qt.io/licensing/ |
| ** |
| ** This file is part of the test suite of the Qt Toolkit. |
| ** |
| ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ |
| ** Commercial License Usage |
| ** Licensees holding valid commercial Qt licenses may use this file in |
| ** accordance with the commercial license agreement provided with the |
| ** Software or, alternatively, in accordance with the terms contained in |
| ** a written agreement between you and The Qt Company. For licensing terms |
| ** and conditions see https://www.qt.io/terms-conditions. For further |
| ** information use the contact form at https://www.qt.io/contact-us. |
| ** |
| ** GNU General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU |
| ** General Public License version 3 as published by the Free Software |
| ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT |
| ** included in the packaging of this file. Please review the following |
| ** information to ensure the GNU General Public License requirements will |
| ** be met: https://www.gnu.org/licenses/gpl-3.0.html. |
| ** |
| ** $QT_END_LICENSE$ |
| ** |
| ****************************************************************************/ |
| |
| |
| #include <QtTest/QtTest> |
| #include <qpixmap.h> |
| #include <qbitmap.h> |
| #include <qimage.h> |
| #include <qimagereader.h> |
| #include <qmatrix.h> |
| #ifndef QT_NO_WIDGETS |
| #include <qdesktopwidget.h> |
| #include <qsplashscreen.h> |
| #endif |
| #include <qpaintengine.h> |
| |
| #include <qpa/qplatformpixmap.h> |
| #include <qpa/qplatformintegration.h> |
| #include <private/qguiapplication_p.h> |
| #include <private/qdrawhelper_p.h> |
| |
| #include <QSet> |
| |
| #ifdef Q_OS_WIN |
| #include <windows.h> |
| #endif |
| |
| |
| Q_DECLARE_METATYPE(QImage::Format) |
| |
| class tst_QPixmap : public QObject |
| { |
| Q_OBJECT |
| |
| public: |
| tst_QPixmap(); |
| |
| public slots: |
| void initTestCase(); |
| void cleanupTestCase(); |
| |
| private slots: |
| void swap(); |
| |
| void fromImage_data(); |
| void fromImage(); |
| |
| void fromUninitializedImage_data(); |
| void fromUninitializedImage(); |
| |
| void convertFromImage_data(); |
| void convertFromImage(); |
| void convertFromImageShouldDetach(); |
| |
| void testMetrics(); |
| |
| void scroll_data(); |
| void scroll(); |
| |
| void fill_data(); |
| void fill(); |
| void fill_transparent(); |
| |
| void createMaskFromColor(); |
| |
| void mask(); |
| void bitmapMask(); |
| void bitmapFromImageRvalue(); |
| void setGetMask_data(); |
| void setGetMask(); |
| void cacheKey(); |
| void drawBitmap(); |
| void isNull(); |
| void task_246446(); |
| void task_51271(); |
| |
| void convertFromImageNoDetach(); |
| void convertFromImageNoDetach2(); |
| void convertFromImageDetach(); |
| void convertFromImageCacheKey(); |
| |
| #if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) |
| void toWinHBITMAP_data(); |
| void toWinHBITMAP(); |
| void fromWinHBITMAP_data(); |
| void fromWinHBITMAP(); |
| |
| void toWinHICON_data(); |
| void toWinHICON(); |
| void fromWinHICON_data(); |
| void fromWinHICON(); |
| #endif |
| |
| void onlyNullPixmapsOutsideGuiThread(); |
| void refUnref(); |
| |
| void copy(); |
| void deepCopyPreservesDpr(); |
| void dprPassthrough(); |
| void depthOfNullObjects(); |
| |
| void transformed(); |
| void transformed2(); |
| |
| void fromImage_crash(); |
| |
| void load(); |
| void loadFromData(); |
| #if !defined(QT_NO_DATASTREAM) |
| void loadFromDataStream(); |
| #endif |
| |
| void fromData(); |
| void loadFromDataNullValues(); |
| |
| void loadFromDataImage_data(); |
| void loadFromDataImage(); |
| |
| void fromImageReader_data(); |
| void fromImageReader(); |
| |
| void fromImageReaderAnimatedGif_data(); |
| void fromImageReaderAnimatedGif(); |
| |
| void preserveDepth(); |
| #ifndef QT_NO_WIDGETS |
| void splash_crash(); |
| #endif |
| |
| void toImageDeepCopy(); |
| |
| void loadAsBitmapOrPixmap(); |
| |
| void scaled_QTBUG19157(); |
| void detachOnLoad_QTBUG29639(); |
| |
| void copyOnNonAlignedBoundary(); |
| void devicePixelRatio(); |
| |
| private: |
| const QString m_prefix; |
| const QString m_convertFromImage; |
| const QString m_loadFromData; |
| const QTemporaryDir m_tempDir; |
| }; |
| |
| static bool lenientCompare(const QPixmap &actual, const QPixmap &expected) |
| { |
| QImage expectedImage = expected.toImage().convertToFormat(QImage::Format_RGB32); |
| QImage actualImage = actual.toImage().convertToFormat(QImage::Format_RGB32); |
| |
| if (expectedImage.size() != actualImage.size()) { |
| qWarning("Image size comparison failed: expected: %dx%d, got %dx%d", |
| expectedImage.size().width(), expectedImage.size().height(), |
| actualImage.size().width(), actualImage.size().height()); |
| return false; |
| } |
| |
| const int size = actual.width() * actual.height(); |
| const int threshold = QPixmap::defaultDepth() == 16 ? 10 : 2; |
| |
| QRgb *a = (QRgb *)actualImage.bits(); |
| QRgb *e = (QRgb *)expectedImage.bits(); |
| for (int i = 0; i < size; ++i) { |
| const QColor ca(a[i]); |
| const QColor ce(e[i]); |
| if (qAbs(ca.red() - ce.red()) > threshold |
| || qAbs(ca.green() - ce.green()) > threshold |
| || qAbs(ca.blue() - ce.blue()) > threshold) { |
| qWarning("Color mismatch at pixel #%d: Expected: %d,%d,%d, got %d,%d,%d", |
| i, ce.red(), ce.green(), ce.blue(), ca.red(), ca.green(), ca.blue()); |
| return false; |
| } |
| } |
| |
| return true; |
| } |
| |
| |
| tst_QPixmap::tst_QPixmap() |
| : m_prefix(QFINDTESTDATA("images/")) |
| , m_convertFromImage(QFINDTESTDATA("convertFromImage")) |
| , m_loadFromData(QFINDTESTDATA("loadFromData")) |
| { |
| } |
| |
| void tst_QPixmap::initTestCase() |
| { |
| QVERIFY(!m_prefix.isEmpty()); |
| QVERIFY(!m_convertFromImage.isEmpty()); |
| QVERIFY(!m_loadFromData.isEmpty()); |
| QVERIFY2(m_tempDir.isValid(), qPrintable(m_tempDir.errorString())); |
| } |
| |
| void tst_QPixmap::cleanupTestCase() |
| { |
| } |
| |
| void tst_QPixmap::swap() |
| { |
| QPixmap p1( 16, 16 ), p2( 32, 32 ); |
| p1.fill( Qt::white ); |
| p2.fill( Qt::black ); |
| const qint64 p1k = p1.cacheKey(); |
| const qint64 p2k = p2.cacheKey(); |
| p1.swap(p2); |
| QCOMPARE(p1.cacheKey(), p2k); |
| QCOMPARE(p1.size(), QSize(32,32)); |
| QCOMPARE(p2.cacheKey(), p1k); |
| QCOMPARE(p2.size(), QSize(16,16)); |
| } |
| |
| void tst_QPixmap::fromImage_data() |
| { |
| bool is16bit = false; |
| if (QPixmap::defaultDepth() == 16) |
| is16bit = true; |
| |
| QTest::addColumn<QImage::Format>("format"); |
| |
| QTest::newRow("Format_Mono") << QImage::Format_Mono; |
| QTest::newRow("Format_MonoLSB") << QImage::Format_MonoLSB; |
| // QTest::newRow("Format_Indexed8") << QImage::Format_Indexed8; |
| if (!is16bit) |
| QTest::newRow("Format_RGB32") << QImage::Format_RGB32; |
| QTest::newRow("Format_ARGB32") << QImage::Format_ARGB32; |
| QTest::newRow("Format_ARGB32_Premultiplied") << QImage::Format_ARGB32_Premultiplied; |
| if (!is16bit) |
| QTest::newRow("Format_RGB16") << QImage::Format_RGB16; |
| } |
| |
| void tst_QPixmap::fromImage() |
| { |
| QFETCH(QImage::Format, format); |
| |
| QImage image(37, 16, format); |
| |
| if (image.colorCount() == 2) { |
| image.setColor(0, QColor(Qt::color0).rgba()); |
| image.setColor(1, QColor(Qt::color1).rgba()); |
| } |
| image.fill(0x7f7f7f7f); |
| |
| const QPixmap pixmap = QPixmap::fromImage(image); |
| const QImage result = pixmap.toImage(); |
| image = image.convertToFormat(result.format()); |
| QCOMPARE(result, image); |
| } |
| |
| |
| void tst_QPixmap::fromUninitializedImage_data() |
| { |
| QTest::addColumn<QImage::Format>("format"); |
| |
| QTest::newRow("Format_Mono") << QImage::Format_Mono; |
| QTest::newRow("Format_MonoLSB") << QImage::Format_MonoLSB; |
| QTest::newRow("Format_Indexed8") << QImage::Format_Indexed8; |
| QTest::newRow("Format_RGB32") << QImage::Format_RGB32; |
| QTest::newRow("Format_ARGB32") << QImage::Format_ARGB32; |
| QTest::newRow("Format_ARGB32_Premultiplied") << QImage::Format_ARGB32_Premultiplied; |
| QTest::newRow("Format_RGB16") << QImage::Format_RGB16; |
| } |
| |
| void tst_QPixmap::fromUninitializedImage() |
| { |
| QFETCH(QImage::Format, format); |
| |
| QImage image(100, 100, format); |
| QPixmap pix = QPixmap::fromImage(image); |
| |
| // it simply shouldn't crash... |
| QVERIFY(true); |
| |
| } |
| |
| void tst_QPixmap::convertFromImage_data() |
| { |
| QTest::addColumn<QImage>("img1"); |
| QTest::addColumn<QImage>("img2"); |
| |
| { |
| QImage img1; |
| QImage img2; |
| QVERIFY(img1.load(m_convertFromImage + "/task31722_0/img1.png")); |
| QVERIFY(img2.load(m_convertFromImage + "/task31722_0/img2.png")); |
| QVERIFY(img1.load(m_convertFromImage + "/task31722_0/img1.png")); |
| QVERIFY(img2.load(m_convertFromImage + "/task31722_0/img2.png")); |
| QTest::newRow("Task 31722 0") << img1 << img2; |
| } |
| { |
| QImage img1; |
| QImage img2; |
| QVERIFY(img1.load(m_convertFromImage + "/task31722_1/img1.png")); |
| QVERIFY(img2.load(m_convertFromImage + "/task31722_1/img2.png")); |
| QTest::newRow("Task 31722 1") << img1 << img2; |
| } |
| } |
| |
| void tst_QPixmap::convertFromImage() |
| { |
| QFETCH(QImage, img1); |
| QFETCH(QImage, img2); |
| |
| QPixmap pix = QPixmap::fromImage(img1); |
| pix = QPixmap::fromImage(img2); |
| |
| QPixmap res = QPixmap::fromImage(img2); |
| QCOMPARE(pix, res); |
| } |
| |
| void tst_QPixmap::convertFromImageShouldDetach() |
| { |
| QImage img1; |
| QImage img2; |
| QVERIFY(img1.load(m_convertFromImage + "/task31722_0/img1.png")); |
| QVERIFY(img2.load(m_convertFromImage + "/task31722_0/img2.png")); |
| QPixmap pix = QPixmap::fromImage(img1); |
| QPixmap pix1 = pix; |
| pix.convertFromImage(img2); |
| QCOMPARE(pix, QPixmap::fromImage(img2)); |
| QCOMPARE(pix1, QPixmap::fromImage(img1)); // unchanged |
| } |
| |
| void tst_QPixmap::scroll_data() |
| { |
| QTest::addColumn<QImage>("input"); |
| QTest::addColumn<int>("dx"); |
| QTest::addColumn<int>("dy"); |
| QTest::addColumn<QRect>("rect"); |
| QTest::addColumn<QRegion>("exposed"); |
| QTest::addColumn<bool>("newPix"); |
| |
| QImage input(":/images/designer.png"); |
| |
| // Noop tests |
| QTest::newRow("null") << QImage() << 0 << 0 << QRect() << QRegion() << false; |
| QTest::newRow("dx_0_dy_0_null") << input << 0 << 0 << QRect() << QRegion() << false; |
| QTest::newRow("dx_1_dy_0_null") << input << 1 << 0 << QRect() << QRegion() << false; |
| QTest::newRow("dx_0_dy_1_null") << input << 0 << 1 << QRect() << QRegion() << false; |
| QTest::newRow("dx_0_dy_0_x_y_w_h") << input << 0 << 0 << input.rect() << QRegion() << false; |
| |
| QRegion r; |
| // Scroll whole pixmap |
| r = QRegion(); r += QRect(0, 0, 128, 10); |
| QTest::newRow("dx_0_dy_10_x_y_w_h") << input << 0 << 10 << input.rect() << r << true; |
| r = QRegion(); r += QRect(0, 0, 10, 128); |
| QTest::newRow("dx_10_dy_0_x_y_w_h") << input << 10 << 0 << input.rect() << r << true; |
| r = QRegion(); r += QRect(0, 0, 128, 10); r += QRect(0, 10, 10, 118); |
| QTest::newRow("dx_10_dy_10_x_y_w_h") << input << 10 << 10 << input.rect() << r << true; |
| r = QRegion(); r += QRect(118, 0, 10, 128); |
| QTest::newRow("dx_-10_dy_0_x_y_w_h") << input << -10 << 0 << input.rect() << r << true; |
| r = QRegion(); r += QRect(0, 118, 128, 10); |
| QTest::newRow("dx_0_dy_-10_x_y_w_h") << input << 0 << -10 << input.rect() << r << true; |
| r = QRegion(); r += QRect(118, 0, 10, 118); r += QRect(0, 118, 128, 10); |
| QTest::newRow("dx_-10_dy_-10_x_y_w_h") << input << -10 << -10 << input.rect() << r << true; |
| |
| // Scroll part of pixmap |
| QTest::newRow("dx_0_dy_0_50_50_100_100") << input << 0 << 0 << QRect(50, 50, 100, 100) << QRegion() << false; |
| r = QRegion(); r += QRect(50, 50, 10, 78); |
| QTest::newRow("dx_10_dy_0_50_50_100_100") << input << 10 << 0 << QRect(50, 50, 100, 100) << r << true; |
| r = QRegion(); r += QRect(50, 50, 78, 10); |
| QTest::newRow("dx_0_dy_10_50_50_100_100") << input << 0 << 10 << QRect(50, 50, 100, 100) << r << true; |
| r = QRegion(); r += QRect(50, 50, 78, 10); r += QRect(50, 60, 10, 68); |
| QTest::newRow("dx_10_dy_10_50_50_100_100") << input << 10 << 10 << QRect(50, 50, 100, 100) << r << true; |
| r = QRegion(); r += QRect(118, 50, 10, 78); |
| QTest::newRow("dx_-10_dy_0_50_50_100_100") << input << -10 << 0 << QRect(50, 50, 100, 100) << r << true; |
| r = QRegion(); r += QRect(50, 118, 78, 10); |
| QTest::newRow("dx_0_dy_-10_50_50_100_100") << input << 0 << -10 << QRect(50, 50, 100, 100) << r << true; |
| r = QRegion(); r += QRect(118, 50, 10, 68); r += QRect(50, 118, 78, 10); |
| QTest::newRow("dx_-10_dy_-10_50_50_100_100") << input << -10 << -10 << QRect(50, 50, 100, 100) << r << true; |
| |
| // Scroll away the whole pixmap |
| r = input.rect(); |
| QTest::newRow("dx_128_dy_0_x_y_w_h") << input << 128 << 0 << input.rect() << r << false; |
| QTest::newRow("dx_0_dy_128_x_y_w_h") << input << 0 << 128 << input.rect() << r << false; |
| QTest::newRow("dx_128_dy_128_x_y_w_h") << input << 128 << 128 << input.rect() << r << false; |
| QTest::newRow("dx_-128_dy_0_x_y_w_h") << input << -128 << 0 << input.rect() << r << false; |
| QTest::newRow("dx_0_dy_-128_x_y_w_h") << input << 0 << -128 << input.rect() << r << false; |
| QTest::newRow("dx_-128_dy_-128_x_y_w_h") << input << -128 << -128 << input.rect() << r << false; |
| |
| // Scroll away part of the pixmap |
| r = QRegion(); r += QRect(64, 64, 64, 64); |
| QTest::newRow("dx_128_dy_128_64_64_128_128") << input << 128 << 128 << QRect(64, 64, 128, 128) << r << false; |
| } |
| |
| void tst_QPixmap::scroll() |
| { |
| QFETCH(QImage, input); |
| QFETCH(int, dx); |
| QFETCH(int, dy); |
| QFETCH(QRect, rect); |
| QFETCH(QRegion, exposed); |
| QFETCH(bool, newPix); |
| |
| QPixmap pixmap = QPixmap::fromImage(input); |
| QRegion exp; |
| qint64 oldKey = pixmap.cacheKey(); |
| pixmap.scroll(dx, dy, rect, &exp); |
| if (!newPix) |
| QCOMPARE(pixmap.cacheKey(), oldKey); |
| else |
| QVERIFY(pixmap.cacheKey() != oldKey); |
| |
| const QString fileName = QLatin1String(":/images/") + QLatin1String(QTest::currentDataTag()) |
| + QLatin1String(".png"); |
| QPixmap output(fileName); |
| QCOMPARE(input.isNull(), output.isNull()); |
| QVERIFY(lenientCompare(pixmap, output)); |
| QCOMPARE(exp, exposed); |
| } |
| |
| void tst_QPixmap::fill_data() |
| { |
| QTest::addColumn<uint>("pixel"); |
| QTest::addColumn<bool>("syscolor"); |
| QTest::addColumn<bool>("bitmap"); |
| for (int color = Qt::black; color < Qt::darkYellow; ++color) |
| QTest::newRow(("syscolor_" + QByteArray::number(color)).constData()) |
| << uint(color) << true << false; |
| |
| QPixmap pixmap(1, 1); |
| QTest::newRow("alpha_7f_red") << 0x7fff0000u << false << false; |
| QTest::newRow("alpha_3f_blue") << 0x3f0000ffu << false << false; |
| QTest::newRow("alpha_b7_green") << 0xbf00ff00u << false << false; |
| QTest::newRow("alpha_7f_white") << 0x7fffffffu << false << false; |
| QTest::newRow("alpha_3f_white") << 0x3fffffffu << false << false; |
| QTest::newRow("alpha_b7_white") << 0xb7ffffffu << false << false; |
| QTest::newRow("alpha_7f_black") << 0x7f000000u << false << false; |
| QTest::newRow("alpha_3f_black") << 0x3f000000u << false << false; |
| QTest::newRow("alpha_b7_black") << 0xbf000000u << false << false; |
| |
| QTest::newRow("bitmap_color0") << uint(Qt::color0) << true << true; |
| QTest::newRow("bitmap_color1") << uint(Qt::color1) << true << true; |
| } |
| |
| void tst_QPixmap::fill() |
| { |
| QFETCH(uint, pixel); |
| QFETCH(bool, syscolor); |
| QFETCH(bool, bitmap); |
| |
| QColor color; |
| |
| if (syscolor) |
| color = QColor(Qt::GlobalColor(pixel)); |
| else |
| color = QColor(qRed(pixel), qGreen(pixel), qBlue(pixel), qAlpha(pixel)); |
| |
| QColor compareColor = color; |
| if (bitmap && syscolor) { |
| // special case color0 and color1 for bitmaps. |
| if (pixel == Qt::color0) |
| compareColor.setRgb(255, 255, 255); |
| else |
| compareColor.setRgb(0, 0, 0); |
| } |
| |
| QPixmap pm; |
| |
| if (bitmap) |
| pm = QBitmap(400, 400); |
| else |
| pm = QPixmap(400, 400); |
| |
| pm.fill(color); |
| if (syscolor && !bitmap && pm.depth() < 24) { |
| QSKIP("Test does not work on displays without true color"); |
| } |
| |
| QImage image = pm.toImage(); |
| if (bitmap && syscolor) { |
| int pixelindex = (pixel == Qt::color0) ? 0 : 1; |
| QCOMPARE(image.pixelIndex(0,0), pixelindex); |
| } |
| QImage::Format format = compareColor.alpha() != 255 |
| ? QImage::Format_ARGB32 |
| : QImage::Format_RGB32; |
| image = image.convertToFormat(format); |
| |
| |
| QImage shouldBe(400, 400, format); |
| shouldBe.fill(compareColor.rgba()); |
| |
| QCOMPARE(image, shouldBe); |
| } |
| |
| void tst_QPixmap::fill_transparent() |
| { |
| QPixmap pixmap(10, 10); |
| pixmap.fill(Qt::transparent); |
| QVERIFY(pixmap.hasAlphaChannel()); |
| } |
| |
| void tst_QPixmap::mask() |
| { |
| QPixmap pm(100, 100); |
| QBitmap bm(100, 100); |
| |
| pm.fill(); |
| bm.fill(); |
| |
| QVERIFY(!pm.isNull()); |
| QVERIFY(!bm.isNull()); |
| if (!pm.hasAlphaChannel()) { |
| // This would fail if the default pixmap format is |
| // argb32_premultiplied. The mask will be all 1's. |
| // Therefore this is skipped when the alpha channel is present. |
| QVERIFY(pm.mask().isNull()); |
| } |
| |
| QImage img = bm.toImage(); |
| QVERIFY(img.format() == QImage::Format_MonoLSB |
| || img.format() == QImage::Format_Mono); |
| |
| pm.setMask(bm); |
| QVERIFY(!pm.mask().isNull()); |
| |
| bm = QBitmap(); |
| // Invalid format here, since isNull() == true |
| QVERIFY(bm.toImage().isNull()); |
| QCOMPARE(bm.toImage().format(), QImage::Format_Invalid); |
| pm.setMask(bm); |
| QVERIFY(pm.mask().isNull()); |
| |
| bm = QBitmap(100, 100); |
| bm.fill(); |
| pm.setMask(bm); |
| QVERIFY(!pm.mask().isNull()); |
| } |
| |
| void tst_QPixmap::bitmapMask() |
| { |
| QImage image(3, 3, QImage::Format_Mono); |
| image.setColor(0, Qt::color0); |
| image.setColor(1, Qt::color1); |
| image.fill(Qt::color0); |
| image.setPixel(1, 1, Qt::color1); |
| image.setPixel(0, 0, Qt::color1); |
| |
| QImage image_mask(3, 3, QImage::Format_Mono); |
| image_mask.setColor(0, Qt::color0); |
| image_mask.setColor(1, Qt::color1); |
| image_mask.fill(Qt::color0); |
| image_mask.setPixel(1, 1, Qt::color1); |
| image_mask.setPixel(2, 0, Qt::color1); |
| |
| QBitmap pm = QBitmap::fromImage(image); |
| QBitmap pm_mask = QBitmap::fromImage(image_mask); |
| pm.setMask(pm_mask); |
| |
| image = pm.toImage(); |
| image.setColor(0, Qt::color0); |
| image.setColor(1, Qt::color1); |
| image_mask = pm_mask.toImage(); |
| image_mask.setColor(0, Qt::color0); |
| image_mask.setColor(1, Qt::color1); |
| |
| QVERIFY(!image.pixel(0, 0)); |
| QVERIFY(!image.pixel(2, 0)); |
| QVERIFY(image.pixel(1, 1)); |
| } |
| |
| void tst_QPixmap::bitmapFromImageRvalue() |
| { |
| auto makeImage = [](){ |
| QImage image(3, 3, QImage::Format_MonoLSB); |
| image.setColor(0, Qt::color0); |
| image.setColor(1, Qt::color1); |
| image.fill(Qt::color0); |
| image.setPixel(1, 1, Qt::color1); |
| image.setPixel(0, 0, Qt::color1); |
| return image; |
| }; |
| |
| auto image1 = makeImage(); |
| auto image2 = makeImage(); |
| auto bitmap1 = QBitmap::fromImage(image1); |
| auto bitmap2 = QBitmap::fromImage(std::move(image2)); |
| QCOMPARE(bitmap1.toImage(), bitmap2.toImage()); |
| QVERIFY(!image1.isNull()); |
| QVERIFY(image2.isNull()); |
| } |
| |
| void tst_QPixmap::setGetMask_data() |
| { |
| QTest::addColumn<QPixmap>("pixmap"); |
| QTest::addColumn<QBitmap>("mask"); |
| QTest::addColumn<QBitmap>("expected"); |
| |
| QPixmap pixmap(10, 10); |
| QBitmap mask(10, 10); |
| QPainter p; |
| |
| p.begin(&pixmap); |
| p.fillRect(0, 0, 10, 10, QColor(Qt::black)); |
| p.end(); |
| |
| QTest::newRow("nullmask 0") << QPixmap() << QBitmap() << QBitmap(); |
| QTest::newRow("nullmask 1") << pixmap << QBitmap() << QBitmap(); |
| mask.clear(); |
| QTest::newRow("nullmask 2") << pixmap << mask << mask; |
| QTest::newRow("nullmask 3") << QPixmap(QBitmap()) << QBitmap() << QBitmap(); |
| |
| p.begin(&mask); |
| p.fillRect(1, 1, 5, 5, QColor(Qt::color1)); |
| p.end(); |
| QTest::newRow("simple mask 0") << pixmap << mask << mask; |
| } |
| |
| void tst_QPixmap::setGetMask() |
| { |
| QFETCH(QPixmap, pixmap); |
| QFETCH(QBitmap, mask); |
| QFETCH(QBitmap, expected); |
| |
| pixmap.setMask(mask); |
| QBitmap result = pixmap.mask(); |
| |
| QImage resultImage = result.toImage(); |
| QImage expectedImage = expected.toImage(); |
| QCOMPARE(resultImage.convertToFormat(expectedImage.format()), |
| expectedImage); |
| } |
| |
| void tst_QPixmap::testMetrics() |
| { |
| QPixmap pixmap(100, 100); |
| |
| QCOMPARE(pixmap.width(), 100); |
| QCOMPARE(pixmap.height(), 100); |
| QVERIFY(pixmap.depth() >= QPixmap::defaultDepth()); |
| |
| QBitmap bitmap(100, 100); |
| |
| QCOMPARE(bitmap.width(), 100); |
| QCOMPARE(bitmap.height(), 100); |
| QCOMPARE(bitmap.depth(), 1); |
| |
| QPixmap null; |
| |
| QCOMPARE(null.size().width(), null.width()); |
| QCOMPARE(null.size().height(), null.height()); |
| } |
| |
| void tst_QPixmap::createMaskFromColor() |
| { |
| QImage image(3, 3, QImage::Format_Indexed8); |
| image.setColorCount(10); |
| image.setColor(0, 0xffffffff); |
| image.setColor(1, 0xff000000); |
| image.setColor(2, 0xffff0000); |
| image.setColor(3, 0xff0000ff); |
| image.fill(0); |
| image.setPixel(1, 0, 1); |
| image.setPixel(0, 1, 2); |
| image.setPixel(1, 1, 3); |
| |
| QImage im_mask = image.createMaskFromColor(0xffff0000); |
| QCOMPARE((uint) im_mask.pixel(0, 1), QColor(Qt::color0).rgba()); |
| QCOMPARE((uint) im_mask.pixel(0, 1), QColor(Qt::color0).rgba()); |
| |
| QPixmap pixmap = QPixmap::fromImage(image); |
| QBitmap mask = pixmap.createMaskFromColor(Qt::red); |
| QBitmap inv_mask = pixmap.createMaskFromColor(Qt::red, Qt::MaskOutColor); |
| QCOMPARE((uint) mask.toImage().pixel(0, 1), QColor(Qt::color0).rgba()); |
| QCOMPARE((uint) inv_mask.toImage().pixel(0, 1), QColor(Qt::color1).rgba()); |
| } |
| |
| |
| void tst_QPixmap::cacheKey() |
| { |
| QPixmap pixmap1(1, 1); |
| QPixmap pixmap2(1, 1); |
| qint64 pixmap1_key = pixmap1.cacheKey(); |
| |
| QVERIFY(pixmap1.cacheKey() != pixmap2.cacheKey()); |
| |
| pixmap2 = pixmap1; |
| QCOMPARE(pixmap2.cacheKey(), pixmap1.cacheKey()); |
| |
| pixmap2.detach(); |
| QVERIFY(pixmap2.cacheKey() != pixmap1.cacheKey()); |
| QCOMPARE(pixmap1.cacheKey(), pixmap1_key); |
| } |
| |
| // Test drawing a bitmap on a pixmap. |
| void tst_QPixmap::drawBitmap() |
| { |
| QBitmap bitmap(10,10); |
| bitmap.fill(Qt::color1); |
| |
| QPixmap pixmap(10,10); |
| QPainter painter2(&pixmap); |
| painter2.fillRect(0,0,10,10, QBrush(Qt::green)); |
| painter2.setPen(Qt::red); |
| painter2.drawPixmap(0,0,10,10, bitmap); |
| painter2.end(); |
| |
| QPixmap expected(10, 10); |
| expected.fill(Qt::red); |
| |
| QVERIFY(lenientCompare(pixmap, expected)); |
| } |
| |
| void tst_QPixmap::isNull() |
| { |
| { |
| QPixmap pixmap(1,1); |
| QVERIFY(!pixmap.isNull()); |
| } |
| { |
| QPixmap pixmap(0,0); |
| QVERIFY(pixmap.isNull()); |
| } |
| |
| { |
| QPixmap pixmap(0,1); |
| QVERIFY(pixmap.isNull()); |
| } |
| { |
| QPixmap pixmap(1,0); |
| QVERIFY(pixmap.isNull()); |
| } |
| { |
| QPixmap pixmap(-1,-1); |
| QVERIFY(pixmap.isNull()); |
| } |
| { |
| QPixmap pixmap(-1,5); |
| QVERIFY(pixmap.isNull()); |
| } |
| } |
| |
| void tst_QPixmap::convertFromImageNoDetach() |
| { |
| QPixmap randomPixmap(10, 10); |
| if (randomPixmap.handle()->classId() != QPlatformPixmap::RasterClass) |
| QSKIP("Test only valid for raster pixmaps"); |
| |
| //first get the screen format |
| QImage::Format screenFormat = randomPixmap.toImage().format(); |
| QVERIFY(screenFormat != QImage::Format_Invalid); |
| |
| QImage orig(100,100, screenFormat); |
| |
| QPixmap pix = QPixmap::fromImage(orig); |
| QImage copy = pix.toImage(); |
| |
| QCOMPARE(copy.format(), screenFormat); |
| |
| const QImage constOrig = orig; |
| const QImage constCopy = copy; |
| QCOMPARE(constOrig.bits(), constCopy.bits()); |
| } |
| |
| void tst_QPixmap::convertFromImageNoDetach2() |
| { |
| QPixmap randomPixmap(10, 10); |
| if (randomPixmap.handle()->classId() != QPlatformPixmap::RasterClass) |
| QSKIP("Test only valid for raster pixmaps"); |
| |
| //first get the screen format |
| QImage::Format screenFormat = randomPixmap.toImage().format(); |
| QVERIFY(screenFormat != QImage::Format_Invalid); |
| if (screenFormat != QImage::Format_RGB32 && |
| screenFormat != QImage::Format_ARGB32_Premultiplied) |
| QSKIP("Test only valid for platforms with RGB32 pixmaps"); |
| |
| QImage orig(100,100, QImage::Format_ARGB32_Premultiplied); |
| orig.fill(Qt::white); |
| |
| const uchar *origBits = orig.constBits(); |
| |
| QPixmap pix = QPixmap::fromImage(std::move(orig)); |
| QImage copy = pix.toImage(); |
| |
| QVERIFY(!copy.hasAlphaChannel()); |
| QCOMPARE(copy.format(), QImage::Format_RGB32); |
| |
| QCOMPARE(origBits, copy.constBits()); |
| } |
| |
| void tst_QPixmap::convertFromImageDetach() |
| { |
| QImage img(10,10, QImage::Format_RGB32); |
| img.fill(0); |
| QVERIFY(!img.isNull()); |
| QPixmap p = QPixmap::fromImage(img); |
| QVERIFY(p.isDetached()); |
| QPixmap copy = p; |
| QVERIFY(!copy.isDetached()); |
| QVERIFY(!p.isDetached()); |
| img.fill(1); |
| p = QPixmap::fromImage(img); |
| QVERIFY(copy.isDetached()); |
| } |
| |
| void tst_QPixmap::convertFromImageCacheKey() |
| { |
| QPixmap randomPixmap(10, 10); |
| if (randomPixmap.handle()->classId() != QPlatformPixmap::RasterClass) |
| QSKIP("Test only valid for raster pixmaps"); |
| |
| //first get the screen format |
| QImage::Format screenFormat = randomPixmap.toImage().format(); |
| QVERIFY(screenFormat != QImage::Format_Invalid); |
| |
| QImage orig(100,100, screenFormat); |
| orig.fill(0); |
| |
| QPixmap pix = QPixmap::fromImage(orig); |
| QImage copy = pix.toImage(); |
| |
| QCOMPARE(copy.format(), screenFormat); |
| |
| QCOMPARE(orig.cacheKey(), pix.cacheKey()); |
| QCOMPARE(copy.cacheKey(), pix.cacheKey()); |
| } |
| |
| #if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) |
| |
| QT_BEGIN_NAMESPACE |
| Q_GUI_EXPORT HBITMAP qt_createIconMask(const QBitmap &bitmap); |
| Q_GUI_EXPORT HBITMAP qt_pixmapToWinHBITMAP(const QPixmap &p, int hbitmapFormat = 0); |
| Q_GUI_EXPORT QPixmap qt_pixmapFromWinHBITMAP(HBITMAP bitmap, int hbitmapFormat = 0); |
| Q_GUI_EXPORT HICON qt_pixmapToWinHICON(const QPixmap &p); |
| Q_GUI_EXPORT QImage qt_imageFromWinHBITMAP(HDC hdc, HBITMAP bitmap, int w, int h); |
| Q_GUI_EXPORT QPixmap qt_pixmapFromWinHICON(HICON icon); |
| QT_END_NAMESPACE |
| |
| void tst_QPixmap::toWinHBITMAP_data() |
| { |
| QTest::addColumn<int>("red"); |
| QTest::addColumn<int>("green"); |
| QTest::addColumn<int>("blue"); |
| |
| QTest::newRow("red") << 255 << 0 << 0; |
| QTest::newRow("green") << 0 << 255 << 0; |
| QTest::newRow("blue") << 0 << 0 << 255; |
| } |
| |
| void tst_QPixmap::toWinHBITMAP() |
| { |
| QFETCH(int, red); |
| QFETCH(int, green); |
| QFETCH(int, blue); |
| |
| QPixmap pm(100, 100); |
| pm.fill(QColor(red, green, blue)); |
| |
| HBITMAP bitmap = qt_pixmapToWinHBITMAP(pm); |
| |
| QVERIFY(bitmap != 0); |
| |
| // Verify size |
| BITMAP bitmap_info; |
| memset(&bitmap_info, 0, sizeof(BITMAP)); |
| |
| int res = GetObject(bitmap, sizeof(BITMAP), &bitmap_info); |
| QVERIFY(res); |
| |
| QCOMPARE(100, (int) bitmap_info.bmWidth); |
| QCOMPARE(100, (int) bitmap_info.bmHeight); |
| |
| HDC display_dc = GetDC(0); |
| HDC bitmap_dc = CreateCompatibleDC(display_dc); |
| |
| HBITMAP null_bitmap = (HBITMAP) SelectObject(bitmap_dc, bitmap); |
| |
| COLORREF pixel = GetPixel(bitmap_dc, 0, 0); |
| QCOMPARE((int)GetRValue(pixel), red); |
| QCOMPARE((int)GetGValue(pixel), green); |
| QCOMPARE((int)GetBValue(pixel), blue); |
| |
| // Clean up |
| SelectObject(bitmap_dc, null_bitmap); |
| DeleteObject(bitmap); |
| DeleteDC(bitmap_dc); |
| ReleaseDC(0, display_dc); |
| |
| } |
| |
| void tst_QPixmap::fromWinHBITMAP_data() |
| { |
| toWinHBITMAP_data(); |
| } |
| |
| void tst_QPixmap::fromWinHBITMAP() |
| { |
| QFETCH(int, red); |
| QFETCH(int, green); |
| QFETCH(int, blue); |
| |
| HDC display_dc = GetDC(0); |
| HDC bitmap_dc = CreateCompatibleDC(display_dc); |
| HBITMAP bitmap = CreateCompatibleBitmap(display_dc, 100, 100); |
| SelectObject(bitmap_dc, bitmap); |
| |
| SelectObject(bitmap_dc, GetStockObject(NULL_PEN)); |
| HGDIOBJ old_brush = SelectObject(bitmap_dc, CreateSolidBrush(RGB(red, green, blue))); |
| Rectangle(bitmap_dc, 0, 0, 100, 100); |
| |
| QPixmap pixmap = qt_pixmapFromWinHBITMAP(bitmap); |
| QCOMPARE(pixmap.width(), 100); |
| QCOMPARE(pixmap.height(), 100); |
| |
| QImage image = pixmap.toImage(); |
| QRgb pixel = image.pixel(0, 0); |
| QCOMPARE(qRed(pixel), red); |
| QCOMPARE(qGreen(pixel), green); |
| QCOMPARE(qBlue(pixel), blue); |
| |
| DeleteObject(SelectObject(bitmap_dc, old_brush)); |
| DeleteObject(SelectObject(bitmap_dc, bitmap)); |
| DeleteDC(bitmap_dc); |
| ReleaseDC(0, display_dc); |
| } |
| |
| static bool compareImages(const QImage &actualImage, const QImage &expectedImage) |
| { |
| if (actualImage.width() != expectedImage.width() |
| || actualImage.height() != expectedImage.height()) { |
| qWarning("Image size comparison failed: expected: %dx%d, got %dx%d", |
| expectedImage.size().width(), expectedImage.size().height(), |
| actualImage.size().width(), actualImage.size().height()); |
| return false; |
| } |
| if (actualImage.format() != expectedImage.format()) { |
| qWarning("Image format comparison failed: expected: %d, got %d", |
| expectedImage.format(), actualImage.format()); |
| return false; |
| } |
| |
| static const int fuzz = 1; |
| |
| for (int y = 0; y < actualImage.height(); ++y) { |
| for (int x = 0; x < expectedImage.width(); ++x) { |
| const QRgb p1 = actualImage.pixel(x, y); |
| const QRgb p2 = expectedImage.pixel(x, y); |
| |
| if (qAbs(qRed(p1) - qRed(p2)) > fuzz |
| || qAbs(qGreen(p1) - qGreen(p2)) > fuzz |
| || qAbs(qBlue(p1) - qBlue(p2)) > fuzz |
| || qAbs(qAlpha(p1) - qAlpha(p2)) > fuzz) { |
| qWarning("Color mismatch at pixel %d,%d: Expected: 0x%x. got 0x%x", |
| x, y, p2, p1); |
| return false; |
| } |
| } |
| } |
| return true; |
| } |
| |
| void tst_QPixmap::toWinHICON_data() |
| { |
| QTest::addColumn<QString>("image"); |
| QTest::addColumn<int>("width"); |
| QTest::addColumn<int>("height"); |
| |
| const QString prefix = QFINDTESTDATA("convertFromToHICON"); |
| |
| QTest::newRow("32bpp_16x16") << prefix + QLatin1String("/icon_32bpp") << 16 << 16; |
| QTest::newRow("32bpp_32x32") << prefix + QLatin1String("/icon_32bpp") << 32 << 32; |
| QTest::newRow("32bpp_48x48") << prefix + QLatin1String("/icon_32bpp") << 48 << 48; |
| QTest::newRow("32bpp_256x256") << prefix + QLatin1String("/icon_32bpp") << 256 << 256; |
| |
| QTest::newRow("8bpp_16x16") << prefix + QLatin1String("/icon_8bpp") << 16 << 16; |
| QTest::newRow("8bpp_32x32") << prefix + QLatin1String("/icon_8bpp") << 32 << 32; |
| QTest::newRow("8bpp_48x48") << prefix + QLatin1String("/icon_8bpp") << 48 << 48; |
| } |
| |
| void tst_QPixmap::toWinHICON() |
| { |
| enum { Alpha = 2 }; |
| |
| QFETCH(int, width); |
| QFETCH(int, height); |
| QFETCH(QString, image); |
| |
| QPixmap empty(width, height); |
| empty.fill(Qt::transparent); |
| |
| HDC display_dc = GetDC(0); |
| HDC bitmap_dc = CreateCompatibleDC(display_dc); |
| HBITMAP bitmap = qt_pixmapToWinHBITMAP(empty, Alpha); |
| SelectObject(bitmap_dc, bitmap); |
| |
| const QString fileName = image + QLatin1Char('_') + QString::number(width) + QLatin1Char('x') |
| + QString::number(height) + QLatin1String(".png"); |
| QImage imageFromFile(fileName); |
| imageFromFile = imageFromFile.convertToFormat(QImage::Format_ARGB32_Premultiplied); |
| |
| HICON icon = qt_pixmapToWinHICON(QPixmap::fromImage(imageFromFile)); |
| |
| DrawIconEx(bitmap_dc, 0, 0, icon, width, height, 0, 0, DI_NORMAL); |
| |
| DestroyIcon(icon); |
| DeleteDC(bitmap_dc); |
| |
| QImage imageFromHICON = qt_pixmapFromWinHBITMAP(bitmap, Alpha).toImage(); |
| |
| ReleaseDC(0, display_dc); |
| |
| // fuzzy comparison must be used, as the pixel values change slightly during conversion |
| // between QImage::Format_ARGB32 and QImage::Format_ARGB32_Premultiplied, or elsewhere |
| |
| QVERIFY(compareImages(imageFromHICON, imageFromFile)); |
| } |
| |
| void tst_QPixmap::fromWinHICON_data() |
| { |
| toWinHICON_data(); |
| } |
| |
| void tst_QPixmap::fromWinHICON() |
| { |
| QFETCH(int, width); |
| QFETCH(int, height); |
| QFETCH(QString, image); |
| |
| HICON icon = (HICON)LoadImage(0, (wchar_t*)(image + QLatin1String(".ico")).utf16(), IMAGE_ICON, width, height, LR_LOADFROMFILE); |
| QImage imageFromHICON = qt_pixmapFromWinHICON(icon).toImage(); |
| DestroyIcon(icon); |
| |
| const QString fileName = image + QLatin1Char('_') + QString::number(width) + QLatin1Char('x') |
| + QString::number(height) + QLatin1String(".png"); |
| QImage imageFromFile(fileName); |
| imageFromFile = imageFromFile.convertToFormat(QImage::Format_ARGB32_Premultiplied); |
| |
| // fuzzy comparison must be used, as the pixel values change slightly during conversion |
| // between QImage::Format_ARGB32 and QImage::Format_ARGB32_Premultiplied, or elsewhere |
| |
| QVERIFY(compareImages(imageFromHICON, imageFromFile)); |
| } |
| |
| #endif // Q_OS_WIN && !Q_OS_WINRT |
| |
| void tst_QPixmap::onlyNullPixmapsOutsideGuiThread() |
| { |
| class Thread : public QThread |
| { |
| public: |
| void run() |
| { |
| QTest::ignoreMessage(QtWarningMsg, |
| "QPixmap: It is not safe to use pixmaps outside the GUI thread"); |
| QPixmap pixmap; |
| QVERIFY(pixmap.isNull()); |
| |
| QTest::ignoreMessage(QtWarningMsg, |
| "QPixmap: It is not safe to use pixmaps outside the GUI thread"); |
| QPixmap pixmap1(100, 100); |
| QVERIFY(pixmap1.isNull()); |
| |
| QTest::ignoreMessage(QtWarningMsg, |
| "QPixmap: It is not safe to use pixmaps outside the GUI thread"); |
| QPixmap pixmap2(pixmap1); |
| QVERIFY(pixmap2.isNull()); |
| } |
| }; |
| if (QGuiApplicationPrivate::platform_integration->hasCapability(QPlatformIntegration::ThreadedPixmaps)) |
| QSKIP("This platform supports threaded pixmaps."); |
| |
| Thread thread; |
| thread.start(); |
| thread.wait(); |
| } |
| |
| void tst_QPixmap::refUnref() |
| { |
| // Simple ref/unref |
| { |
| QPixmap p; |
| } |
| { |
| QBitmap b; |
| } |
| |
| // Get a copy of a pixmap that goes out of scope |
| { |
| QPixmap b; |
| { |
| QPixmap a(10, 10); |
| a.fill(Qt::color0); |
| b = a; |
| } |
| } |
| { |
| QBitmap mask; |
| { |
| QBitmap bitmap(10, 10); |
| bitmap.fill(Qt::color1); |
| mask = bitmap.mask(); |
| } |
| mask.fill(Qt::color0); |
| } |
| |
| } |
| |
| void tst_QPixmap::copy() |
| { |
| QPixmap src(32, 32); |
| { |
| QPainter p(&src); |
| p.fillRect(0, 0, 32, 32, Qt::red); |
| p.fillRect(10, 10, 10, 10, Qt::blue); |
| } |
| |
| QPixmap dest = src.copy(10, 10, 10, 10); |
| |
| QPixmap expected(10, 10); |
| expected.fill(Qt::blue); |
| QVERIFY(lenientCompare(dest, expected)); |
| |
| QPixmap trans; |
| trans.fill(Qt::transparent); |
| |
| QPixmap transCopy = trans.copy(); |
| QCOMPARE(trans, transCopy); |
| } |
| |
| // QTBUG-58653: Force a deep copy of a pixmap by |
| // having a QPainter and check whether DevicePixelRatio is preserved |
| void tst_QPixmap::deepCopyPreservesDpr() |
| { |
| const qreal dpr = 2; |
| QPixmap src(32, 32); |
| src.setDevicePixelRatio(dpr); |
| src.fill(Qt::red); |
| QPainter painter(&src); |
| const QPixmap dest = src.copy(); |
| QCOMPARE(dest.devicePixelRatio(), dpr); |
| } |
| |
| void tst_QPixmap::dprPassthrough() |
| { |
| const qreal dpr = 2; |
| QPixmap src(32, 32); |
| src.setDevicePixelRatio(dpr); |
| src.fill(Qt::transparent); |
| QCOMPARE(src.devicePixelRatio(), dpr); |
| |
| QImage img = src.toImage(); |
| QCOMPARE(img.devicePixelRatio(), dpr); |
| |
| QPixmap pm(1, 1); |
| pm.convertFromImage(img); |
| QCOMPARE(pm.devicePixelRatio(), dpr); |
| |
| QBitmap heuristicMask = src.createHeuristicMask(); |
| QCOMPARE(heuristicMask.devicePixelRatio(), dpr); |
| |
| QBitmap maskFromColor = src.createMaskFromColor(Qt::white); |
| QCOMPARE(maskFromColor.devicePixelRatio(), dpr); |
| |
| QBitmap mask = src.mask(); |
| QCOMPARE(mask.devicePixelRatio(), dpr); |
| |
| QPixmap scaled = src.scaled(16, 16); |
| QCOMPARE(scaled.devicePixelRatio(), dpr); |
| |
| QTransform t; |
| t.rotate(90); |
| QPixmap transformed = src.transformed(t); |
| QCOMPARE(transformed.devicePixelRatio(), dpr); |
| } |
| |
| void tst_QPixmap::depthOfNullObjects() |
| { |
| QBitmap b1; |
| QCOMPARE(b1.depth(), 0); |
| QPixmap p4; |
| QCOMPARE(p4.depth(), 0); |
| } |
| |
| void tst_QPixmap::transformed() |
| { |
| QPixmap p1(20, 10); |
| p1.fill(Qt::red); |
| { |
| QPainter p(&p1); |
| p.drawRect(0, 0, p1.width() - 1, p1.height() - 1); |
| } |
| |
| QPixmap p2(10, 20); |
| { |
| QPainter p(&p2); |
| p.rotate(90); |
| p.drawPixmap(0, -p1.height(), p1); |
| } |
| |
| QPixmap p3(20, 10); |
| { |
| QPainter p(&p3); |
| p.rotate(180); |
| p.drawPixmap(-p1.width(), -p1.height(), p1); |
| } |
| |
| QPixmap p4(10, 20); |
| { |
| QPainter p(&p4); |
| p.rotate(270); |
| p.drawPixmap(-p1.width(), 0, p1); |
| } |
| |
| QPixmap p1_90 = p1.transformed(QTransform().rotate(90)); |
| QPixmap p1_180 = p1.transformed(QTransform().rotate(180)); |
| QPixmap p1_270 = p1.transformed(QTransform().rotate(270)); |
| |
| QVERIFY(lenientCompare(p1_90, p2)); |
| QVERIFY(lenientCompare(p1_180, p3)); |
| QVERIFY(lenientCompare(p1_270, p4)); |
| } |
| |
| void tst_QPixmap::transformed2() |
| { |
| QPixmap pm(3, 3); |
| pm.fill(Qt::red); |
| QPainter p(&pm); |
| p.fillRect(0, 0, 3, 3, QBrush(Qt::Dense4Pattern)); |
| p.end(); |
| |
| QTransform transform; |
| transform.rotate(-90); |
| transform.scale(3, 3); |
| |
| QPixmap actual = pm.transformed(transform); |
| |
| QPixmap expected(9, 9); |
| expected.fill(Qt::red); |
| p.begin(&expected); |
| p.setBrush(Qt::black); |
| p.setPen(Qt::NoPen); |
| p.drawRect(3, 0, 3, 3); |
| p.drawRect(0, 3, 3, 3); |
| p.drawRect(6, 3, 3, 3); |
| p.drawRect(3, 6, 3, 3); |
| p.end(); |
| |
| QVERIFY(lenientCompare(actual, expected)); |
| } |
| |
| void tst_QPixmap::load() |
| { |
| const QString filePath = m_prefix + QLatin1String("designer.png"); |
| |
| QPixmap dest(filePath); |
| QVERIFY(!dest.isNull()); |
| QVERIFY(!dest.load("image_that_does_not_exist.png")); |
| QVERIFY(dest.isNull()); |
| QVERIFY(dest.load(filePath)); |
| QVERIFY(!dest.isNull()); |
| } |
| |
| void tst_QPixmap::loadFromData() |
| { |
| const QString filePath = m_prefix + QLatin1String("designer.png"); |
| |
| QPixmap original(filePath); |
| QVERIFY(!original.isNull()); |
| |
| QByteArray ba; |
| { |
| QBuffer buf(&ba); |
| QVERIFY(buf.open(QIODevice::WriteOnly)); |
| QVERIFY(original.save(&buf, "BMP")); |
| } |
| QVERIFY(!ba.isEmpty()); |
| |
| QPixmap dest; |
| QVERIFY(dest.loadFromData(ba, "BMP")); |
| QVERIFY(!dest.isNull()); |
| |
| QCOMPARE(original, dest); |
| |
| QVERIFY(!dest.loadFromData(QByteArray())); |
| QVERIFY(dest.isNull()); |
| } |
| |
| #if !defined(QT_NO_DATASTREAM) |
| void tst_QPixmap::loadFromDataStream() |
| { |
| const QString filePath = m_prefix + QLatin1String("designer.png"); |
| |
| QPixmap original(filePath); |
| QVERIFY(!original.isNull()); |
| |
| QByteArray ba; |
| { |
| QDataStream s(&ba, QIODevice::WriteOnly); |
| s << original; |
| } |
| QVERIFY(!ba.isEmpty()); |
| |
| QPixmap dest; |
| { |
| QDataStream s(&ba, QIODevice::ReadOnly); |
| s >> dest; |
| } |
| QVERIFY(!dest.isNull()); |
| |
| QCOMPARE(original, dest); |
| |
| { |
| ba.clear(); |
| QDataStream s(&ba, QIODevice::ReadOnly); |
| s >> dest; |
| } |
| QVERIFY(dest.isNull()); |
| } |
| #endif // QT_NO_DATASTREAM |
| |
| void tst_QPixmap::fromImage_crash() |
| { |
| QImage *img = new QImage(64, 64, QImage::Format_ARGB32_Premultiplied); |
| |
| QPixmap pm = QPixmap::fromImage(*img); |
| QPainter painter(&pm); |
| |
| delete img; |
| } |
| |
| #ifndef QT_NO_WIDGETS |
| //This is testing QPlatformPixmap::createCompatiblePlatformPixmap - see QTBUG-5977 |
| void tst_QPixmap::splash_crash() |
| { |
| QPixmap pix; |
| pix = QPixmap(":/images/designer.png"); |
| QSplashScreen splash(pix); |
| splash.show(); |
| QCoreApplication::processEvents(); |
| splash.close(); |
| } |
| #endif |
| |
| void tst_QPixmap::fromData() |
| { |
| unsigned char bits[] = { 0xaa, 0x55 }; |
| |
| QBitmap bm = QBitmap::fromData(QSize(8, 2), bits); |
| QImage img = bm.toImage(); |
| |
| QSet<QRgb> colors; |
| for (int y = 0; y < img.height(); ++y) |
| for (int x = 0; x < img.width(); ++x) |
| colors << img.pixel(x, y); |
| |
| QCOMPARE(colors.size(), 2); |
| |
| QCOMPARE(img.pixel(0, 0), QRgb(0xffffffff)); |
| QCOMPARE(img.pixel(0, 1), QRgb(0xff000000)); |
| } |
| |
| void tst_QPixmap::loadFromDataNullValues() |
| { |
| { |
| QPixmap pixmap; |
| pixmap.loadFromData(QByteArray()); |
| QVERIFY(pixmap.isNull()); |
| } |
| { |
| QPixmap pixmap; |
| pixmap.loadFromData(0, 123); |
| QVERIFY(pixmap.isNull()); |
| } |
| { |
| QPixmap pixmap; |
| const uchar bla[] = "bla"; |
| pixmap.loadFromData(bla, 0); |
| QVERIFY(pixmap.isNull()); |
| } |
| } |
| |
| void tst_QPixmap::loadFromDataImage_data() |
| { |
| QTest::addColumn<QString>("imagePath"); |
| |
| QTest::newRow("designer_argb32.png") << m_loadFromData + "/designer_argb32.png"; |
| // When no extension is provided we try all extensions that has been registered by image providers |
| QTest::newRow("designer_argb32") << m_loadFromData + "/designer_argb32.png"; |
| QTest::newRow("designer_indexed8_no_alpha.png") << m_loadFromData + "/designer_indexed8_no_alpha.png"; |
| QTest::newRow("designer_indexed8_with_alpha.png") << m_loadFromData + "/designer_indexed8_with_alpha.png"; |
| QTest::newRow("designer_rgb32.png") << m_loadFromData + "/designer_rgb32.png"; |
| QTest::newRow("designer_indexed8_no_alpha.gif") << m_loadFromData + "/designer_indexed8_no_alpha.gif"; |
| QTest::newRow("designer_indexed8_with_alpha.gif") << m_loadFromData + "/designer_indexed8_with_alpha.gif"; |
| QTest::newRow("designer_rgb32.jpg") << m_loadFromData + "/designer_rgb32.jpg"; |
| } |
| |
| void tst_QPixmap::loadFromDataImage() |
| { |
| QFETCH(QString, imagePath); |
| |
| QImage imageRef(imagePath); |
| QPixmap pixmapWithCopy = QPixmap::fromImage(imageRef); |
| |
| QFile file(imagePath); |
| file.open(QIODevice::ReadOnly); |
| QByteArray rawData = file.readAll(); |
| |
| QPixmap directLoadingPixmap; |
| directLoadingPixmap.loadFromData(rawData); |
| |
| QCOMPARE(pixmapWithCopy, directLoadingPixmap); |
| } |
| |
| void tst_QPixmap::fromImageReader_data() |
| { |
| QTest::addColumn<QString>("imagePath"); |
| |
| QTest::newRow("designer_argb32.png") << m_loadFromData + "/designer_argb32.png"; |
| QTest::newRow("designer_indexed8_no_alpha.png") << m_loadFromData + "/designer_indexed8_no_alpha.png"; |
| QTest::newRow("designer_indexed8_with_alpha.png") << m_loadFromData + "/designer_indexed8_with_alpha.png"; |
| QTest::newRow("designer_rgb32.png") << m_loadFromData + "/designer_rgb32.png"; |
| QTest::newRow("designer_indexed8_no_alpha.gif") << m_loadFromData + "/designer_indexed8_no_alpha.gif"; |
| QTest::newRow("designer_indexed8_with_alpha.gif") << m_loadFromData + "/designer_indexed8_with_alpha.gif"; |
| QTest::newRow("designer_rgb32.jpg") << m_loadFromData + "/designer_rgb32.jpg"; |
| QTest::newRow("designer_indexed8_with_alpha_animated") << m_loadFromData + "/designer_indexed8_with_alpha_animated.gif"; |
| QTest::newRow("designer_indexed8_no_alpha_animated") << m_loadFromData + "/designer_indexed8_no_alpha_animated.gif"; |
| } |
| |
| void tst_QPixmap::fromImageReader() |
| { |
| QFETCH(QString, imagePath); |
| |
| QImage imageRef(imagePath); |
| QPixmap pixmapWithCopy = QPixmap::fromImage(imageRef); |
| |
| QImageReader imageReader(imagePath); |
| |
| QPixmap directLoadingPixmap = QPixmap::fromImageReader(&imageReader); |
| |
| QCOMPARE(pixmapWithCopy, directLoadingPixmap); |
| } |
| |
| void tst_QPixmap::fromImageReaderAnimatedGif_data() |
| { |
| QTest::addColumn<QString>("imagePath"); |
| QTest::newRow("gif with alpha") << QString::fromLatin1("/designer_indexed8_with_alpha_animated.gif"); |
| QTest::newRow("gif without alpha") << QString::fromLatin1("/designer_indexed8_no_alpha_animated.gif"); |
| } |
| |
| void tst_QPixmap::fromImageReaderAnimatedGif() |
| { |
| QFETCH(QString, imagePath); |
| |
| const QString path = m_loadFromData + imagePath; |
| |
| QImageReader referenceReader(path); |
| QImageReader pixmapReader(path); |
| |
| QVERIFY(referenceReader.canRead()); |
| QVERIFY(referenceReader.imageCount() > 1); |
| |
| for (int i = 0; i < referenceReader.imageCount(); ++i) { |
| QImage refImage = referenceReader.read(); |
| QPixmap refPixmap = QPixmap::fromImage(refImage); |
| |
| QPixmap directLoadingPixmap = QPixmap::fromImageReader(&pixmapReader); |
| QCOMPARE(refPixmap, directLoadingPixmap); |
| } |
| } |
| |
| void tst_QPixmap::task_246446() |
| { |
| // This crashed without the bugfix in 246446 |
| QPixmap pm(10, 10); |
| pm.fill(Qt::transparent); // force 32-bit depth |
| QBitmap bm; |
| pm.setMask(bm); |
| { |
| QPixmap pm2(pm); |
| } |
| QCOMPARE(pm.width(), 10); |
| QVERIFY(pm.mask().isNull()); |
| } |
| |
| void tst_QPixmap::task_51271() |
| { |
| QPixmap pm; |
| QBitmap bm; |
| QVERIFY(!pm.isQBitmap()); // Should not crash ! |
| QVERIFY(bm.isQBitmap()); |
| } |
| |
| void tst_QPixmap::preserveDepth() |
| { |
| QPixmap target(64, 64); |
| target.fill(Qt::transparent); |
| |
| QPixmap source(64, 64); |
| source.fill(Qt::white); |
| |
| int depth = source.depth(); |
| |
| QPainter painter(&target); |
| painter.setBrush(source); |
| painter.drawRect(target.rect()); |
| painter.end(); |
| |
| QCOMPARE(depth, source.depth()); |
| } |
| |
| void tst_QPixmap::loadAsBitmapOrPixmap() |
| { |
| QImage tmp(10, 10, QImage::Format_RGB32); |
| tmp.save(m_tempDir.path() + "/temp_image.png"); |
| |
| bool ok; |
| |
| // Check that we can load the pixmap as a pixmap and that it then turns into a pixmap |
| QPixmap pixmap(m_tempDir.path() + "/temp_image.png"); |
| QVERIFY(!pixmap.isNull()); |
| QVERIFY(pixmap.depth() > 1); |
| QVERIFY(!pixmap.isQBitmap()); |
| |
| pixmap = QPixmap(); |
| ok = pixmap.load(m_tempDir.path() + "/temp_image.png"); |
| QVERIFY(ok); |
| QVERIFY(!pixmap.isNull()); |
| QVERIFY(pixmap.depth() > 1); |
| QVERIFY(!pixmap.isQBitmap()); |
| |
| //now we can try to load it without an extension |
| pixmap = QPixmap(); |
| ok = pixmap.load(m_tempDir.path() + "/temp_image"); |
| QVERIFY(ok); |
| QVERIFY(!pixmap.isNull()); |
| QVERIFY(pixmap.depth() > 1); |
| QVERIFY(!pixmap.isQBitmap()); |
| |
| // The do the same check for bitmaps.. |
| QBitmap bitmap(m_tempDir.path() + "/temp_image.png"); |
| QVERIFY(!bitmap.isNull()); |
| QCOMPARE(bitmap.depth(), 1); |
| QVERIFY(bitmap.isQBitmap()); |
| |
| bitmap = QBitmap(); |
| ok = bitmap.load(m_tempDir.path() + "/temp_image.png"); |
| QVERIFY(ok); |
| QVERIFY(!bitmap.isNull()); |
| QCOMPARE(bitmap.depth(), 1); |
| QVERIFY(bitmap.isQBitmap()); |
| |
| // check that a QBitmap stays a QBitmap even when loading fails: |
| ok = bitmap.load(QString()); |
| QVERIFY(!ok); |
| QVERIFY(bitmap.isNull()); |
| QVERIFY(bitmap.isQBitmap()); |
| |
| ok = bitmap.load("does not exist"); |
| QVERIFY(!ok); |
| QVERIFY(bitmap.isNull()); |
| QVERIFY(bitmap.isQBitmap()); |
| |
| ok = bitmap.load("does not exist.png"); |
| QVERIFY(!ok); |
| QVERIFY(bitmap.isNull()); |
| QVERIFY(bitmap.isQBitmap()); |
| |
| QTemporaryFile garbage; |
| QVERIFY(garbage.open()); |
| const QString garbagePath = garbage.fileName(); |
| garbage.write(reinterpret_cast<const char *>(&garbage), sizeof garbage); |
| garbage.close(); |
| |
| ok = bitmap.load(garbagePath); |
| QVERIFY(!ok); |
| QVERIFY(bitmap.isNull()); |
| QVERIFY(bitmap.isQBitmap()); |
| } |
| |
| void tst_QPixmap::toImageDeepCopy() |
| { |
| QPixmap pixmap(64, 64); |
| pixmap.fill(Qt::white); |
| |
| QPainter painter(&pixmap); |
| QImage first = pixmap.toImage(); |
| |
| painter.setBrush(Qt::black); |
| painter.drawEllipse(pixmap.rect()); |
| |
| QImage second = pixmap.toImage(); |
| |
| QVERIFY(first != second); |
| } |
| |
| void tst_QPixmap::scaled_QTBUG19157() |
| { |
| QPixmap foo(5000, 1); |
| foo = foo.scaled(1024, 1024, Qt::KeepAspectRatio); |
| QVERIFY(!foo.isNull()); |
| } |
| |
| void tst_QPixmap::detachOnLoad_QTBUG29639() |
| { |
| QPixmap a; |
| a.load(m_convertFromImage + "/task31722_0/img1.png"); |
| a.load(m_convertFromImage + "/task31722_0/img2.png"); |
| |
| QPixmap b; |
| b.load(m_convertFromImage + "/task31722_0/img1.png"); |
| |
| QVERIFY(a.toImage() != b.toImage()); |
| } |
| |
| void tst_QPixmap::copyOnNonAlignedBoundary() |
| { |
| QImage img(8, 2, QImage::Format_RGB16); |
| |
| QPixmap pm1 = QPixmap::fromImage(img, Qt::NoFormatConversion); |
| QPixmap pm2 = pm1.copy(QRect(5, 0, 3, 2)); // When copying second line: 2 bytes too many are read which might cause an access violation. |
| } |
| |
| // test pixmap devicePixelRatio setting and detaching |
| void tst_QPixmap::devicePixelRatio() |
| { |
| // create pixmap |
| QPixmap a(64, 64); |
| a.fill(Qt::white); |
| QCOMPARE(a.devicePixelRatio(), qreal(1.0)); |
| QCOMPARE(a.isDetached(), true); |
| |
| // copy pixmap |
| QPixmap b = a; |
| QCOMPARE(b.devicePixelRatio(), qreal(1.0)); |
| QCOMPARE(a.isDetached(), false); |
| QCOMPARE(b.isDetached(), false); |
| |
| // set devicePixelRatio to the current value: does not detach |
| a.setDevicePixelRatio(qreal(1.0)); |
| QCOMPARE(a.isDetached(), false); |
| QCOMPARE(b.isDetached(), false); |
| |
| // set devicePixelRatio to a new value: may detach (currently |
| // does, but we may want to avoid the data copy the future) |
| a.setDevicePixelRatio(qreal(2.0)); |
| QCOMPARE(a.devicePixelRatio(), qreal(2.0)); |
| QCOMPARE(b.devicePixelRatio(), qreal(1.0)); |
| } |
| |
| QTEST_MAIN(tst_QPixmap) |
| #include "tst_qpixmap.moc" |