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 <a.kudryavtsev@netris.ru>
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
This commit is contained in:
Marc Mutz 2016-08-26 12:29:48 +02:00
parent 237b36a72c
commit f9acbaccde
2 changed files with 55 additions and 30 deletions

View File

@ -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<uint>(info.lastModified().toTime_t())
% HexString<quint64>(info.size())
% HexString<uint>(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<uint>(info.lastModified().toTime_t())
% HexString<quint64>(info.size())
% HexString<uint>(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;
}

View File

@ -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<const char *>(&garbage), sizeof garbage);
garbage.close();
ok = bitmap.load(garbagePath);
QVERIFY(!ok);
QVERIFY(bitmap.isNull());
QVERIFY(bitmap.isQBitmap());
}
void tst_QPixmap::toImageDeepCopy()