From 746e6d4b48866bb7f97154c865424fc89649a382 Mon Sep 17 00:00:00 2001 From: Volker Hilsheimer Date: Fri, 16 Feb 2024 11:44:52 +0100 Subject: [PATCH] Apple icon engine: maintain aspect ratio of image MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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ø Reviewed-by: Eike Ziller (cherry picked from commit 8a19f3c089deafa8a3a5fa5a05baa7ca01d8ec14) Reviewed-by: Qt Cherry-pick Bot --- src/gui/platform/darwin/qappleiconengine.mm | 44 ++++++++++---------- src/gui/platform/darwin/qappleiconengine_p.h | 2 +- 2 files changed, 22 insertions(+), 24 deletions(-) diff --git a/src/gui/platform/darwin/qappleiconengine.mm b/src/gui/platform/darwin/qappleiconengine.mm index 049bd827f96..5cbafb66e33 100644 --- a/src/gui/platform/darwin/qappleiconengine.mm +++ b/src/gui/platform/darwin/qappleiconengine.mm @@ -84,27 +84,35 @@ bool QAppleIconEngine::isNull() return m_image == nullptr; } -QList QAppleIconEngine::availableIconSizes() +QList QAppleIconEngine::availableIconSizes(double aspectRatio) { const qreal devicePixelRatio = qGuiApp->devicePixelRatio(); const QList 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 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); diff --git a/src/gui/platform/darwin/qappleiconengine_p.h b/src/gui/platform/darwin/qappleiconengine_p.h index 1735d2f501e..8f48e8e6fcf 100644 --- a/src/gui/platform/darwin/qappleiconengine_p.h +++ b/src/gui/platform/darwin/qappleiconengine_p.h @@ -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 availableIconSizes(); + static QList availableIconSizes(double aspectRatio = 1.0); private: static constexpr quint64 calculateCacheKey(QIcon::Mode mode, QIcon::State state)