summaryrefslogtreecommitdiffstats
path: root/src/gui/platform
diff options
context:
space:
mode:
authorVolker Hilsheimer <volker.hilsheimer@qt.io>2024-03-22 15:59:36 +0100
committerVolker Hilsheimer <volker.hilsheimer@qt.io>2024-04-04 01:51:46 +0100
commit9d8c5bc7186b0553c47ddabc9ad6c9d509b35f81 (patch)
tree9a615f63f02999a4179f8f5d8435c0fcdc76d9f0 /src/gui/platform
parent72c242c7a21d28d652cea082fa08efc7b419bc20 (diff)
Apple icon engine: reverse implementation to avoid pixmaps
Instead of implementing scaledPixmap() to rasterize the vector image we get from App/UIKit, and calling that from paint, implement paint() to draw the vector image directly through the painter, and use that in scaledPixmap. Pick-to: 6.7 Change-Id: I2c62826f29406543bc8d8c7fa71199e91586d83b Reviewed-by: Amr Elsayed <amr.elsayed@qt.io> Reviewed-by: Doris Verria <doris.verria@qt.io> Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
Diffstat (limited to 'src/gui/platform')
-rw-r--r--src/gui/platform/darwin/qappleiconengine.mm105
1 files changed, 53 insertions, 52 deletions
diff --git a/src/gui/platform/darwin/qappleiconengine.mm b/src/gui/platform/darwin/qappleiconengine.mm
index 79feea82c5..8300222dea 100644
--- a/src/gui/platform/darwin/qappleiconengine.mm
+++ b/src/gui/platform/darwin/qappleiconengine.mm
@@ -395,59 +395,23 @@ auto *configuredImage(const UIImage *image, const QColor &color)
#endif
}
-namespace {
-template <typename Image>
-QPixmap imageToPixmap(const Image *image, QSizeF renderSize)
-{
- if constexpr (std::is_same_v<Image, NSImage>)
- return qt_mac_toQPixmap(image, renderSize.toSize());
- else
- return QPixmap::fromImage(qt_mac_toQImage(image, renderSize.toSize()));
-}
-}
-
QPixmap QAppleIconEngine::scaledPixmap(const QSize &size, QIcon::Mode mode, QIcon::State state, qreal scale)
{
const quint64 cacheKey = calculateCacheKey(mode, state);
if (cacheKey != m_cacheKey || m_pixmap.size() != size || m_pixmap.devicePixelRatio() != scale) {
- QColor color;
- const QPalette palette;
- switch (mode) {
- case QIcon::Normal:
- color = palette.color(QPalette::Inactive, QPalette::Text);
- break;
- case QIcon::Disabled:
- color = palette.color(QPalette::Disabled, QPalette::Text);
- break;
- case QIcon::Active:
- color = palette.color(QPalette::Active, QPalette::Text);
- break;
- case QIcon::Selected:
- color = palette.color(QPalette::Active, QPalette::HighlightedText);
- break;
- }
- const auto *image = configuredImage(m_image, color);
-
- // 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.
- const QSize requestedSize = size * scale;
- const QSizeF renderSize = actualSize(requestedSize, mode, state);
- QPixmap iconPixmap = imageToPixmap(image, renderSize);
- iconPixmap.setDevicePixelRatio(scale);
-
- if (renderSize != requestedSize) {
- m_pixmap = QPixmap(requestedSize);
- m_pixmap.fill(Qt::transparent);
- m_pixmap.setDevicePixelRatio(scale);
-
- QPainter painter(&m_pixmap);
- const QSize offset = ((m_pixmap.deviceIndependentSize()
- - iconPixmap.deviceIndependentSize()) / 2).toSize();
- painter.drawPixmap(offset.width(), offset.height(), iconPixmap);
- } else {
- m_pixmap = iconPixmap;
- }
+ const QSize paintSize = actualSize(size, mode, state);
+ const QSize paintOffset = paintSize != size
+ ? (QSizeF(size - paintSize) * 0.5).toSize()
+ : QSize();
+
+ m_pixmap = QPixmap(size * scale);
+ m_pixmap.setDevicePixelRatio(scale);
+ m_pixmap.fill(Qt::transparent);
+
+ QPainter painter(&m_pixmap);
+ paint(&painter, QRect(paintOffset.width(), paintOffset.height(),
+ paintSize.width(), paintSize.height()), mode, state);
+
m_cacheKey = cacheKey;
}
return m_pixmap;
@@ -455,9 +419,46 @@ QPixmap QAppleIconEngine::scaledPixmap(const QSize &size, QIcon::Mode mode, QIco
void QAppleIconEngine::paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state)
{
- const qreal scale = painter->device()->devicePixelRatio();
- // TODO: render the image directly if we don't have the pixmap yet and paint on an image
- painter->drawPixmap(rect, scaledPixmap(rect.size(), mode, state, scale));
+ Q_UNUSED(state);
+
+ QColor color;
+ const QPalette palette;
+ switch (mode) {
+ case QIcon::Normal:
+ color = palette.color(QPalette::Inactive, QPalette::Text);
+ break;
+ case QIcon::Disabled:
+ color = palette.color(QPalette::Disabled, QPalette::Text);
+ break;
+ case QIcon::Active:
+ color = palette.color(QPalette::Active, QPalette::Text);
+ break;
+ case QIcon::Selected:
+ color = palette.color(QPalette::Active, QPalette::HighlightedText);
+ break;
+ }
+ const auto *image = configuredImage(m_image, color);
+
+ QMacCGContext ctx(painter);
+
+#if defined(Q_OS_MACOS)
+ NSGraphicsContext *gc = [NSGraphicsContext graphicsContextWithCGContext:ctx flipped:YES];
+ [NSGraphicsContext saveGraphicsState];
+ [NSGraphicsContext setCurrentContext:gc];
+
+ const NSSize pixmapSize = NSMakeSize(rect.width(), rect.height());
+ [image setSize:pixmapSize];
+ const NSRect sourceRect = NSMakeRect(0, 0, pixmapSize.width, pixmapSize.height);
+ const NSRect iconRect = NSMakeRect(rect.x(), rect.y(), pixmapSize.width, pixmapSize.height);
+
+ [image drawInRect:iconRect fromRect:sourceRect operation:NSCompositingOperationSourceOver fraction:1.0 respectFlipped:YES hints:nil];
+ [NSGraphicsContext restoreGraphicsState];
+#elif defined(Q_OS_IOS)
+ UIGraphicsPushContext(ctx);
+ const CGRect cgrect = CGRectMake(rect.x(), rect.y(), rect.width(), rect.height());
+ [image drawInRect:cgrect];
+ UIGraphicsPopContext();
+#endif
}
QT_END_NAMESPACE