Apple icon engine: maintain aspect ratio of image

Don't return fixed square icon sizes from availableSizes(), respect the
aspect ratio of the input image we get from the system, and return an
actualSize() that fits into the requested size, but uses the image's
aspect ratio as well.

Reuse the calculation in the rendering code.

Amends 5b993fa8ede67871a8b2434505bc3c3d8bb906c6.

Fixes: QTBUG-121764
Change-Id: I672b90a1fbecb662fd6614dcfa5090e28b16f3c8
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
(cherry picked from commit 8a19f3c089deafa8a3a5fa5a05baa7ca01d8ec14)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Volker Hilsheimer 2024-02-16 11:44:52 +01:00 committed by Qt Cherry-pick Bot
parent 5e7cd47721
commit 746e6d4b48
2 changed files with 22 additions and 24 deletions

View File

@ -84,27 +84,35 @@ bool QAppleIconEngine::isNull()
return m_image == nullptr;
}
QList<QSize> QAppleIconEngine::availableIconSizes()
QList<QSize> QAppleIconEngine::availableIconSizes(double aspectRatio)
{
const qreal devicePixelRatio = qGuiApp->devicePixelRatio();
const QList<QSize> sizes = {
{qRound(16 * devicePixelRatio), qRound(16 * devicePixelRatio)},
{qRound(32 * devicePixelRatio), qRound(32 * devicePixelRatio)},
{qRound(64 * devicePixelRatio), qRound(64 * devicePixelRatio)},
{qRound(128 * devicePixelRatio), qRound(128 * devicePixelRatio)},
{qRound(256 * devicePixelRatio), qRound(256 * devicePixelRatio)},
{qRound(16 * devicePixelRatio), qRound(16. * devicePixelRatio / aspectRatio)},
{qRound(32 * devicePixelRatio), qRound(32. * devicePixelRatio / aspectRatio)},
{qRound(64 * devicePixelRatio), qRound(64. * devicePixelRatio / aspectRatio)},
{qRound(128 * devicePixelRatio), qRound(128. * devicePixelRatio / aspectRatio)},
{qRound(256 * devicePixelRatio), qRound(256. * devicePixelRatio / aspectRatio)},
};
return sizes;
}
QList<QSize> QAppleIconEngine::availableSizes(QIcon::Mode, QIcon::State)
{
return availableIconSizes();
const double aspectRatio = isNull() ? 1.0 : m_image.size.width / m_image.size.height;
return availableIconSizes(aspectRatio);
}
QSize QAppleIconEngine::actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state)
QSize QAppleIconEngine::actualSize(const QSize &size, QIcon::Mode /*mode*/, QIcon::State /*state*/)
{
return QIconEngine::actualSize(size, mode, state);
const double inputAspectRatio = isNull() ? 1.0 : m_image.size.width / m_image.size.height;
const double outputAspectRatio = size.width() / size.height();
QSize result = size;
if (outputAspectRatio > inputAspectRatio)
result.rwidth() = result.height() * inputAspectRatio;
else
result.rheight() = result.width() / inputAspectRatio;
return result;
}
QPixmap QAppleIconEngine::pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state)
@ -188,23 +196,13 @@ QPixmap QAppleIconEngine::scaledPixmap(const QSize &size, QIcon::Mode mode, QIco
// The size we want might have a different aspect ratio than the icon we have.
// So ask for a pixmap with the same aspect ratio as the icon, constrained to the
// size we want, and then center that within a pixmap of the requested size.
QSizeF renderSize = size * scale;
const double inputAspectRatio = image.size.width / image.size.height;
const double outputAspectRatio = size.width() / size.height();
const bool aspectRatioAdjusted = !qFuzzyCompare(inputAspectRatio, outputAspectRatio);
if (aspectRatioAdjusted) {
// don't grow
if (outputAspectRatio > inputAspectRatio)
renderSize.rwidth() = renderSize.height() * inputAspectRatio;
else
renderSize.rheight() = renderSize.width() / inputAspectRatio;
}
const QSize requestedSize = size * scale;
const QSizeF renderSize = actualSize(requestedSize, mode, state);
QPixmap iconPixmap = imageToPixmap(image, renderSize);
iconPixmap.setDevicePixelRatio(scale);
if (aspectRatioAdjusted) {
m_pixmap = QPixmap(size * scale);
if (renderSize != requestedSize) {
m_pixmap = QPixmap(requestedSize);
m_pixmap.fill(Qt::transparent);
m_pixmap.setDevicePixelRatio(scale);

View File

@ -40,7 +40,7 @@ public:
QPixmap scaledPixmap(const QSize &size, QIcon::Mode mode, QIcon::State state, qreal scale) override;
void paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state) override;
static QList<QSize> availableIconSizes();
static QList<QSize> availableIconSizes(double aspectRatio = 1.0);
private:
static constexpr quint64 calculateCacheKey(QIcon::Mode mode, QIcon::State state)