summaryrefslogtreecommitdiffstats
path: root/src/gui/painting/qcoregraphics.mm
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/painting/qcoregraphics.mm')
-rw-r--r--src/gui/painting/qcoregraphics.mm215
1 files changed, 125 insertions, 90 deletions
diff --git a/src/gui/painting/qcoregraphics.mm b/src/gui/painting/qcoregraphics.mm
index e2497eaadb..27b46202f5 100644
--- a/src/gui/painting/qcoregraphics.mm
+++ b/src/gui/painting/qcoregraphics.mm
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qcoregraphics_p.h"
@@ -47,6 +11,8 @@
#include <QtCore/qcoreapplication.h>
#include <QtCore/qoperatingsystemversion.h>
+QT_USE_NAMESPACE
+
QT_BEGIN_NAMESPACE
// ---------------------- Images ----------------------
@@ -56,22 +22,22 @@ CGBitmapInfo qt_mac_bitmapInfoForImage(const QImage &image)
CGBitmapInfo bitmapInfo = kCGImageAlphaNone;
switch (image.format()) {
case QImage::Format_ARGB32:
- bitmapInfo = kCGImageAlphaFirst | kCGBitmapByteOrder32Host;
+ bitmapInfo = CGBitmapInfo(kCGImageAlphaFirst) | kCGBitmapByteOrder32Host;
break;
case QImage::Format_RGB32:
- bitmapInfo = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host;
+ bitmapInfo = CGBitmapInfo(kCGImageAlphaNoneSkipFirst) | kCGBitmapByteOrder32Host;
break;
case QImage::Format_RGBA8888_Premultiplied:
- bitmapInfo = kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big;
+ bitmapInfo = CGBitmapInfo(kCGImageAlphaPremultipliedLast) | kCGBitmapByteOrder32Big;
break;
case QImage::Format_RGBA8888:
- bitmapInfo = kCGImageAlphaLast | kCGBitmapByteOrder32Big;
+ bitmapInfo = CGBitmapInfo(kCGImageAlphaLast) | kCGBitmapByteOrder32Big;
break;
case QImage::Format_RGBX8888:
- bitmapInfo = kCGImageAlphaNoneSkipLast | kCGBitmapByteOrder32Big;
+ bitmapInfo = CGBitmapInfo(kCGImageAlphaNoneSkipLast) | kCGBitmapByteOrder32Big;
break;
case QImage::Format_ARGB32_Premultiplied:
- bitmapInfo = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host;
+ bitmapInfo = CGBitmapInfo(kCGImageAlphaPremultipliedFirst) | kCGBitmapByteOrder32Host;
break;
default: break;
}
@@ -124,49 +90,81 @@ QImage qt_mac_toQImage(CGImageRef image)
#ifdef Q_OS_MACOS
-static NSImage *qt_mac_cgimage_to_nsimage(CGImageRef image)
+QT_END_NAMESPACE
+
+@implementation NSImage (QtExtras)
++ (instancetype)imageFromQImage:(const QImage &)image
{
- NSImage *newImage = [[NSImage alloc] initWithCGImage:image size:NSZeroSize];
- return newImage;
+ if (image.isNull())
+ return nil;
+
+ QCFType<CGImageRef> cgImage = image.toCGImage();
+ if (!cgImage)
+ return nil;
+
+ // We set up the NSImage using an explicit NSBitmapImageRep, instead of
+ // [NSImage initWithCGImage:size:], as the former allows us to correctly
+ // set the size of the representation to account for the device pixel
+ // ratio of the original image, which in turn will be reflected by the
+ // NSImage.
+ auto nsImage = [[NSImage alloc] initWithSize:NSZeroSize];
+ auto *imageRep = [[NSBitmapImageRep alloc] initWithCGImage:cgImage];
+ imageRep.size = image.deviceIndependentSize().toCGSize();
+ [nsImage addRepresentation:[imageRep autorelease]];
+ Q_ASSERT(CGSizeEqualToSize(nsImage.size, imageRep.size));
+
+ return [nsImage autorelease];
}
-NSImage *qt_mac_create_nsimage(const QPixmap &pm)
++ (instancetype)imageFromQIcon:(const QIcon &)icon
{
- if (pm.isNull())
- return 0;
- QImage image = pm.toImage();
- CGImageRef cgImage = qt_mac_toCGImage(image);
- NSImage *nsImage = qt_mac_cgimage_to_nsimage(cgImage);
- nsImage.size = (pm.size() / pm.devicePixelRatioF()).toCGSize();
- CGImageRelease(cgImage);
- return nsImage;
+ 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);
- for (QSize size : qAsConst(availableSizes)) {
- QPixmap pm = icon.pixmap(size);
- if (pm.isNull())
+ auto availableSizes = icon.availableSizes();
+ if (availableSizes.isEmpty() && size > 0)
+ availableSizes << QSize(size, size);
+
+ auto nsImage = [[[NSImage alloc] initWithSize:NSZeroSize] autorelease];
+
+ for (QSize size : std::as_const(availableSizes)) {
+ 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.deviceIndependentSize().toCGSize();
+ [nsImage addRepresentation:[imageRep autorelease]];
}
+
+ if (!nsImage.representations.count)
+ return nil;
+
+ [nsImage setTemplate:icon.isMask()];
+
+ if (size)
+ nsImage.size = CGSizeMake(size, size);
+
return nsImage;
}
+@end
+
+QT_BEGIN_NAMESPACE
QPixmap qt_mac_toQPixmap(const NSImage *image, const QSizeF &size)
{
+ // ### TODO: add parameter so that we can decide whether to maintain the aspect
+ // ratio of the image (positioning the image inside the pixmap of size \a size),
+ // or whether we want to fill the resulting pixmap by stretching the image.
const NSSize pixmapSize = NSMakeSize(size.width(), size.height());
QPixmap pixmap(pixmapSize.width, pixmapSize.height);
pixmap.fill(Qt::transparent);
@@ -187,6 +185,25 @@ QPixmap qt_mac_toQPixmap(const NSImage *image, const QSizeF &size)
#endif // Q_OS_MACOS
+#ifdef QT_PLATFORM_UIKIT
+
+QImage qt_mac_toQImage(const UIImage *image, QSizeF size)
+{
+ // ### TODO: same as above
+ QImage ret(size.width(), size.height(), QImage::Format_ARGB32_Premultiplied);
+ ret.fill(Qt::transparent);
+ QMacCGContext ctx(&ret);
+ if (!ctx)
+ return QImage();
+ UIGraphicsPushContext(ctx);
+ const CGRect rect = CGRectMake(0, 0, size.width(), size.height());
+ [image drawInRect:rect];
+ UIGraphicsPopContext();
+ return ret;
+}
+
+#endif // QT_PLATFORM_UIKIT
+
// ---------------------- Colors and Brushes ----------------------
QColor qt_mac_toQColor(CGColorRef color)
@@ -212,18 +229,33 @@ QColor qt_mac_toQColor(CGColorRef color)
QColor qt_mac_toQColor(const NSColor *color)
{
QColor qtColor;
- NSString *colorSpace = [color colorSpaceName];
- if (colorSpace == NSDeviceCMYKColorSpace) {
- CGFloat cyan, magenta, yellow, black, alpha;
- [color getCyan:&cyan magenta:&magenta yellow:&yellow black:&black alpha:&alpha];
- qtColor.setCmykF(cyan, magenta, yellow, black, alpha);
- } else {
- NSColor *tmpColor;
- tmpColor = [color colorUsingColorSpaceName:NSDeviceRGBColorSpace];
- CGFloat red, green, blue, alpha;
+ switch (color.type) {
+ case NSColorTypeComponentBased: {
+ const NSColorSpace *colorSpace = [color colorSpace];
+ if (colorSpace == NSColorSpace.genericRGBColorSpace
+ && color.numberOfComponents == 4) { // rbga
+ CGFloat components[4];
+ [color getComponents:components];
+ qtColor.setRgbF(components[0], components[1], components[2], components[3]);
+ break;
+ } else if (colorSpace == NSColorSpace.genericCMYKColorSpace
+ && color.numberOfComponents == 5) { // cmyk + alpha
+ CGFloat components[5];
+ [color getComponents:components];
+ qtColor.setCmykF(components[0], components[1], components[2], components[3], components[4]);
+ break;
+ }
+ }
+ Q_FALLTHROUGH();
+ default: {
+ const NSColor *tmpColor = [color colorUsingColorSpace:NSColorSpace.genericRGBColorSpace];
+ CGFloat red = 0, green = 0, blue = 0, alpha = 0;
[tmpColor getRed:&red green:&green blue:&blue alpha:&alpha];
qtColor.setRgbF(red, green, blue, alpha);
+ break;
+ }
}
+
return qtColor;
}
#endif
@@ -249,9 +281,9 @@ static bool qt_mac_isSystemColorOrInstance(const NSColor *color, NSString *color
// We specifically do not want isKindOfClass: here
if ([color.className isEqualToString:className]) // NSPatternColorSpace
return true;
- if ([color.catalogNameComponent isEqualToString:@"System"] &&
- [color.colorNameComponent isEqualToString:colorNameComponent] &&
- [color.colorSpaceName isEqualToString:NSNamedColorSpace])
+ if (color.type == NSColorTypeCatalog &&
+ [color.catalogNameComponent isEqualToString:@"System"] &&
+ [color.colorNameComponent isEqualToString:colorNameComponent])
return true;
return false;
}
@@ -307,8 +339,8 @@ QBrush qt_mac_toQBrush(const NSColor *color, QPalette::ColorGroup colorGroup)
return qtBrush;
}
- if (NSColor *patternColor = [color colorUsingColorSpaceName:NSPatternColorSpace]) {
- NSImage *patternImage = patternColor.patternImage;
+ if (color.type == NSColorTypePattern) {
+ NSImage *patternImage = color.patternImage;
const QSizeF sz(patternImage.size.width, patternImage.size.height);
// FIXME: QBrush is not resolution independent (QTBUG-49774)
qtBrush.setTexture(qt_mac_toQPixmap(patternImage, sz));
@@ -376,11 +408,14 @@ void QMacCGContext::initialize(QPaintDevice *paintDevice)
// Find the underlying QImage of the paint device
switch (int deviceType = paintDevice->devType()) {
case QInternal::Pixmap: {
- auto *platformPixmap = static_cast<QPixmap*>(paintDevice)->handle();
- if (platformPixmap && platformPixmap->classId() == QPlatformPixmap::RasterClass)
- initialize(platformPixmap->buffer());
- else
- qWarning() << "QMacCGContext: Unsupported pixmap class" << platformPixmap->classId();
+ if (auto *platformPixmap = static_cast<QPixmap*>(paintDevice)->handle()) {
+ if (platformPixmap->classId() == QPlatformPixmap::RasterClass)
+ initialize(platformPixmap->buffer());
+ else
+ qWarning() << "QMacCGContext: Unsupported pixmap class" << platformPixmap->classId();
+ } else {
+ qWarning() << "QMacCGContext: Empty platformPixmap";
+ }
break;
}
case QInternal::Image:
@@ -464,7 +499,7 @@ void QMacCGContext::initialize(const QImage *image, QPainter *painter)
clip &= painterClip;
}
- qt_mac_clip_cg(context, clip, 0);
+ qt_mac_clip_cg(context, clip, nullptr);
CGContextTranslateCTM(context, deviceTransform.dx(), deviceTransform.dy());
}