macOS: Streamline QIcon to NSImage conversion

The conversion uses NSBitmapImageRep and correctly sets the display
pixel ratio and size of the resulting image, reducing the need for
clients to deal with this.

It also propagates the isMask property of the icon to the NSImage.

The function returns an auto-released object, as is customary for
class-functions like these.

Change-Id: If97f3d383959cd0f58a0d1249f5c26e52c1da9cd
Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
bb10
Tor Arne Vestbø 2020-03-09 18:43:52 +01:00 committed by Tor Arne Vestbø
parent 52e9c8b4be
commit bee3d0fc13
4 changed files with 35 additions and 30 deletions

View File

@ -151,32 +151,47 @@ QT_END_NAMESPACE
return [nsImage autorelease];
}
@end
QT_BEGIN_NAMESPACE
+ (instancetype)imageFromQIcon:(const QIcon &)icon
{
return [NSImage imageFromQIcon:icon withSize:0];
}
NSImage *qt_mac_create_nsimage(const QIcon &icon, int defaultSize)
+ (instancetype)imageFromQIcon:(const QIcon &)icon withSize:(int)size
{
if (icon.isNull())
return nil;
NSImage *nsImage = [[NSImage alloc] init];
QList<QSize> availableSizes = icon.availableSizes();
if (availableSizes.isEmpty() && defaultSize > 0)
availableSizes << QSize(defaultSize, defaultSize);
auto nsImage = [[NSImage alloc] initWithSize:NSZeroSize];
auto availableSizes = icon.availableSizes();
if (availableSizes.isEmpty() && size > 0)
availableSizes << QSize(size, size);
for (QSize size : qAsConst(availableSizes)) {
QPixmap pm = icon.pixmap(size);
if (pm.isNull())
QImage image = icon.pixmap(size).toImage();
if (image.isNull())
continue;
QImage image = pm.toImage();
CGImageRef cgImage = qt_mac_toCGImage(image);
NSBitmapImageRep *imageRep = [[NSBitmapImageRep alloc] initWithCGImage:cgImage];
[nsImage addRepresentation:imageRep];
[imageRep release];
CGImageRelease(cgImage);
QCFType<CGImageRef> cgImage = image.toCGImage();
if (!cgImage)
continue;
auto *imageRep = [[NSBitmapImageRep alloc] initWithCGImage:cgImage];
imageRep.size = (image.size() / image.devicePixelRatioF()).toCGSize();
[nsImage addRepresentation:[imageRep autorelease]];
}
return nsImage;
[nsImage setTemplate:icon.isMask()];
if (size)
nsImage.size = CGSizeMake(size, size);
return [nsImage autorelease];
}
@end
QT_BEGIN_NAMESPACE
QPixmap qt_mac_toQPixmap(const NSImage *image, const QSizeF &size)
{

View File

@ -69,12 +69,13 @@ QT_BEGIN_NAMESPACE
Q_GUI_EXPORT CGBitmapInfo qt_mac_bitmapInfoForImage(const QImage &image);
#ifdef HAVE_APPKIT
Q_GUI_EXPORT NSImage *qt_mac_create_nsimage(const QIcon &icon, int defaultSize = 0);
Q_GUI_EXPORT QPixmap qt_mac_toQPixmap(const NSImage *image, const QSizeF &size);
QT_END_NAMESPACE
@interface NSImage (QtExtras)
+ (instancetype)imageFromQImage:(const QT_PREPEND_NAMESPACE(QImage) &)image;
+ (instancetype)imageFromQIcon:(const QT_PREPEND_NAMESPACE(QIcon) &)icon;
+ (instancetype)imageFromQIcon:(const QT_PREPEND_NAMESPACE(QIcon) &)icon withSize:(int)size;
@end
QT_BEGIN_NAMESPACE

View File

@ -341,13 +341,7 @@ NSMenuItem *QCocoaMenuItem::sync()
m_native.keyEquivalentModifierMask = NSEventModifierFlagCommand;
}
NSImage *img = nil;
if (!m_icon.isNull()) {
img = qt_mac_create_nsimage(m_icon, m_iconSize);
img.size = CGSizeMake(m_iconSize, m_iconSize);
}
m_native.image = img;
[img release];
m_native.image = [NSImage imageFromQIcon:m_icon withSize:m_iconSize];
m_native.state = m_checked ? NSOnState : NSOffState;
return m_native;

View File

@ -272,12 +272,7 @@ void QCocoaSystemTrayIcon::showMessage(const QString &title, const QString &mess
NSUserNotification *notification = [[NSUserNotification alloc] init];
notification.title = [NSString stringWithUTF8String:title.toUtf8().data()];
notification.informativeText = [NSString stringWithUTF8String:message.toUtf8().data()];
if (!icon.isNull()) {
auto *nsimage = qt_mac_create_nsimage(icon);
[nsimage setTemplate:icon.isMask()];
notification.contentImage = [nsimage autorelease];
}
notification.contentImage = [NSImage imageFromQIcon:icon];
NSUserNotificationCenter *center = NSUserNotificationCenter.defaultUserNotificationCenter;
center.delegate = m_sys->item;