QIcon/QPixmapIconEngine: render svgs with the given size

Currently scalable images are rendered with the default size set in the
image and not the size they were added with QIcon::addPixmap(). This
might give scaling artifacts when the both sizes do not match at all.
Therefore set the wanted size through QImageReader::setScaledSize() when
(and only when) the reader supports this. Setting it unconditionally
will also force the scaling of pixel-based formats which is not what we
want.

Task-number: QTBUG-135652
Change-Id: I2dc78587854b4c7c32438e0386385e980a9c4059
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
(cherry picked from commit 9eddf930a274757c91290d56d10177f4ff94c4bb)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Christian Ehrlicher 2025-04-22 14:10:50 +02:00 committed by Qt Cherry-pick Bot
parent 40edcb4157
commit f71e7ce350

View File

@ -37,7 +37,13 @@ namespace {
class ImageReader
{
public:
ImageReader(const QString &fileName) : m_reader(fileName), m_atEnd(false) { }
ImageReader(const QString &fileName, QSize size)
: m_reader(fileName)
, m_atEnd(false)
{
if (m_reader.supportsOption(QImageIOHandler::ScaledSize))
m_reader.setScaledSize(size);
}
QByteArray format() const { return m_reader.format(); }
bool supportsReadSize() const { return m_reader.supportsOption(QImageIOHandler::Size); }
@ -289,9 +295,9 @@ QPixmapIconEngineEntry *QPixmapIconEngine::bestMatch(const QSize &size, qreal sc
if (pe->pixmap.isNull()) {
// delay-load the image
ImageReader imageReader(pe->fileName);
QImage image, prevImage;
const QSize realSize = size * scale;
ImageReader imageReader(pe->fileName, realSize);
bool fittingImageFound = false;
if (imageReader.supportsReadSize()) {
// find the image with the best size without loading the entire image
@ -450,7 +456,7 @@ void QPixmapIconEngine::addFile(const QString &fileName, const QSize &size, QIco
return;
const QString abs = fileName.startsWith(u':') ? fileName : QFileInfo(fileName).absoluteFilePath();
const bool ignoreSize = !size.isValid();
ImageReader imageReader(abs);
ImageReader imageReader(abs, size);
const QByteArray format = imageReader.format();
if (format.isEmpty()) // Device failed to open or unsupported format.
return;