QLabel: don't cache scaled pixmap in QIcon

Caching the scaled QPixmap directly in QIcon is not a good idea
 - the cached pixmap might be used as starting point for a pixmap with
   another size so it gets blurry
 - QIcon has no caching mechanism to throw away unneeded QPixmaps after
   some time so the memory usage grows indefinitely

Fixes: QTBUG-134930
Change-Id: Ic490ba15438a5cd07a555692e1d08cd1c211d005
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
(cherry picked from commit 7a238e1225f49b81772516ed5d0a5a4f4f2e9268)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
(cherry picked from commit 04cb0a1b55cc3c2b402d22f9f7a76b726407dc71)
Reviewed-by: Topi Reiniö <topi.reinio@qt.io>
This commit is contained in:
Christian Ehrlicher 2025-03-19 20:32:56 +01:00 committed by Qt Cherry-pick Bot
parent 4c02701ecd
commit c63c918f3a

View File

@ -6,6 +6,7 @@
#include "qstyle.h" #include "qstyle.h"
#include "qstyleoption.h" #include "qstyleoption.h"
#include "qlabel_p.h" #include "qlabel_p.h"
#include "private/qhexstring_p.h"
#include "private/qstylesheetstyle_p.h" #include "private/qstylesheetstyle_p.h"
#include <qmath.h> #include <qmath.h>
@ -1054,9 +1055,21 @@ void QLabel::paintEvent(QPaintEvent *)
const auto mode = isEnabled() ? QIcon::Normal : QIcon::Disabled; const auto mode = isEnabled() ? QIcon::Normal : QIcon::Disabled;
QPixmap pix = d->icon->pixmap(size, dpr, mode); QPixmap pix = d->icon->pixmap(size, dpr, mode);
if (d->scaledcontents && pix.size() != size * dpr) { if (d->scaledcontents && pix.size() != size * dpr) {
const QString key = "qt_label_"_L1 % HexString<quint64>(pix.cacheKey())
% HexString<quint8>(mode)
% HexString<uint>(size.width())
% HexString<uint>(size.height())
% HexString<quint16>(qRound(dpr * 1000));
if (!QPixmapCache::find(key, &pix)) {
pix = pix.scaled(size * dpr, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); pix = pix.scaled(size * dpr, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
pix.setDevicePixelRatio(dpr); pix.setDevicePixelRatio(dpr);
d->icon->addPixmap(pix, mode); // using QIcon to cache the newly create pixmap is not possible
// because QIcon does not clear this cache (so we grow indefinitely)
// and also uses the newly added pixmap as starting point for new
// scaled pixmap which makes it very blurry.
// Therefore use QPixmapCache here.
QPixmapCache::insert(key, pix);
}
} }
QStyleOption opt; QStyleOption opt;
opt.initFrom(this); opt.initFrom(this);