diff options
author | Volker Hilsheimer <volker.hilsheimer@qt.io> | 2024-03-22 15:59:36 +0100 |
---|---|---|
committer | Volker Hilsheimer <volker.hilsheimer@qt.io> | 2024-04-04 01:51:46 +0100 |
commit | 9d8c5bc7186b0553c47ddabc9ad6c9d509b35f81 (patch) | |
tree | 9a615f63f02999a4179f8f5d8435c0fcdc76d9f0 /src/gui/platform | |
parent | 72c242c7a21d28d652cea082fa08efc7b419bc20 (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.mm | 105 |
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 |