From f9acbaccde278eaf44a5324c2a63a99a4cccfb1c Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Fri, 26 Aug 2016 12:29:48 +0200 Subject: [PATCH] QPixmap::load: ensure QBitmap stays a QBitmap even on failure ... and avoid detach()ing potentially large data for just preserving the QPlatformPixmap::pixelType(). A QBitmap differs from a QPixmap (its base class, urgh) by always having a data != nullptr and a Bitmap pixel type, yet load() was unconditionally setting 'data' to nullptr on failure, turning a QBitmap into a non-QBitmap. Fix by move-assigning a null QBitmap instead of resetting 'data'. Add some tests. Change-Id: Ida58b3b24d96472a5f9d0f18f81cc763edcf3c16 Reviewed-by: Anton Kudryavtsev Reviewed-by: Edward Welbourne Reviewed-by: Ulf Hermann --- src/gui/image/qpixmap.cpp | 58 ++++++++++---------- tests/auto/gui/image/qpixmap/tst_qpixmap.cpp | 27 +++++++++ 2 files changed, 55 insertions(+), 30 deletions(-) diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp index 78031bca970..3726b2124c2 100644 --- a/src/gui/image/qpixmap.cpp +++ b/src/gui/image/qpixmap.cpp @@ -762,39 +762,37 @@ QBitmap QPixmap::createMaskFromColor(const QColor &maskColor, Qt::MaskMode mode) bool QPixmap::load(const QString &fileName, const char *format, Qt::ImageConversionFlags flags) { - if (fileName.isEmpty()) { - data.reset(); - return false; + if (!fileName.isEmpty()) { + + QFileInfo info(fileName); + // Note: If no extension is provided, we try to match the + // file against known plugin extensions + if (info.completeSuffix().isEmpty() || info.exists()) { + + QString key = QLatin1String("qt_pixmap") + % info.absoluteFilePath() + % HexString(info.lastModified().toTime_t()) + % HexString(info.size()) + % HexString(data ? data->pixelType() : QPlatformPixmap::PixmapType); + + if (QPixmapCache::find(key, this)) + return true; + + data = QPlatformPixmap::create(0, 0, data ? data->pixelType() : QPlatformPixmap::PixmapType); + + if (data->fromFile(fileName, format, flags)) { + QPixmapCache::insert(key, *this); + return true; + } + } } - detach(); - - QFileInfo info(fileName); - QString key = QLatin1String("qt_pixmap") - % info.absoluteFilePath() - % HexString(info.lastModified().toTime_t()) - % HexString(info.size()) - % HexString(data ? data->pixelType() : QPlatformPixmap::PixmapType); - - // Note: If no extension is provided, we try to match the - // file against known plugin extensions - if (!info.completeSuffix().isEmpty() && !info.exists()) { - data.reset(); - return false; + if (!isNull()) { + if (isQBitmap()) + *this = QBitmap(); + else + data.reset(); } - - if (QPixmapCache::find(key, this)) - return true; - - if (!data) - data = QPlatformPixmap::create(0, 0, QPlatformPixmap::PixmapType); - - if (data->fromFile(fileName, format, flags)) { - QPixmapCache::insert(key, *this); - return true; - } - - data.reset(); return false; } diff --git a/tests/auto/gui/image/qpixmap/tst_qpixmap.cpp b/tests/auto/gui/image/qpixmap/tst_qpixmap.cpp index 4ffe357d097..286f00c1115 100644 --- a/tests/auto/gui/image/qpixmap/tst_qpixmap.cpp +++ b/tests/auto/gui/image/qpixmap/tst_qpixmap.cpp @@ -1508,6 +1508,33 @@ void tst_QPixmap::loadAsBitmapOrPixmap() 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(&garbage), sizeof garbage); + garbage.close(); + + ok = bitmap.load(garbagePath); + QVERIFY(!ok); + QVERIFY(bitmap.isNull()); + QVERIFY(bitmap.isQBitmap()); } void tst_QPixmap::toImageDeepCopy()