diff options
Diffstat (limited to 'src/plugins/platforms/cocoa/qcocoahelpers.mm')
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoahelpers.mm | 402 |
1 files changed, 1 insertions, 401 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.mm b/src/plugins/platforms/cocoa/qcocoahelpers.mm index 542c046d42..0c7c30579e 100644 --- a/src/plugins/platforms/cocoa/qcocoahelpers.mm +++ b/src/plugins/platforms/cocoa/qcocoahelpers.mm @@ -47,6 +47,7 @@ #include <qpa/qplatformscreen.h> #include <private/qguiapplication_p.h> #include <private/qwindow_p.h> +#include <QtGui/private/qcoregraphics_p.h> #ifndef QT_NO_WIDGETS #include <QtWidgets/QWidget> @@ -56,25 +57,6 @@ #include <Carbon/Carbon.h> -@interface NSGraphicsContext (QtAdditions) - -+ (NSGraphicsContext *)qt_graphicsContextWithCGContext:(CGContextRef)graphicsPort flipped:(BOOL)initialFlippedState; - -@end - -@implementation NSGraphicsContext (QtAdditions) - -+ (NSGraphicsContext *)qt_graphicsContextWithCGContext:(CGContextRef)graphicsPort flipped:(BOOL)initialFlippedState -{ -#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_10, __IPHONE_NA) - if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::OSXYosemite) - return [self graphicsContextWithCGContext:graphicsPort flipped:initialFlippedState]; -#endif - return [self graphicsContextWithGraphicsPort:graphicsPort flipped:initialFlippedState]; -} - -@end - QT_BEGIN_NAMESPACE Q_LOGGING_CATEGORY(lcQpaCocoaWindow, "qt.qpa.cocoa.window"); @@ -101,198 +83,6 @@ void *qt_mac_QStringListToNSMutableArrayVoid(const QStringList &list) return result; } -CGImageRef qt_mac_toCGImage(const QImage &inImage) -{ - CGImageRef cgImage = inImage.toCGImage(); - if (cgImage) - return cgImage; - - // Convert image data to a known-good format if the fast conversion fails. - return inImage.convertToFormat(QImage::Format_ARGB32_Premultiplied).toCGImage(); -} - -CGImageRef qt_mac_toCGImageMask(const QImage &image) -{ - static const auto deleter = [](void *image, const void *, size_t) { delete static_cast<QImage *>(image); }; - QCFType<CGDataProviderRef> dataProvider = - CGDataProviderCreateWithData(new QImage(image), image.bits(), - image.byteCount(), deleter); - - return CGImageMaskCreate(image.width(), image.height(), 8, image.depth(), - image.bytesPerLine(), dataProvider, NULL, false); -} - -NSImage *qt_mac_cgimage_to_nsimage(CGImageRef image) -{ - NSImage *newImage = [[NSImage alloc] initWithCGImage:image size:NSZeroSize]; - return newImage; -} - -NSImage *qt_mac_create_nsimage(const QPixmap &pm) -{ - if (pm.isNull()) - return 0; - QImage image = pm.toImage(); - CGImageRef cgImage = qt_mac_toCGImage(image); - NSImage *nsImage = qt_mac_cgimage_to_nsimage(cgImage); - CGImageRelease(cgImage); - return nsImage; -} - -NSImage *qt_mac_create_nsimage(const QIcon &icon) -{ - if (icon.isNull()) - return nil; - - NSImage *nsImage = [[NSImage alloc] init]; - foreach (QSize size, icon.availableSizes()) { - QPixmap pm = icon.pixmap(size); - QImage image = pm.toImage(); - CGImageRef cgImage = qt_mac_toCGImage(image); - NSBitmapImageRep *imageRep = [[NSBitmapImageRep alloc] initWithCGImage:cgImage]; - [nsImage addRepresentation:imageRep]; - [imageRep release]; - CGImageRelease(cgImage); - } - return nsImage; -} - -HIMutableShapeRef qt_mac_QRegionToHIMutableShape(const QRegion ®ion) -{ - HIMutableShapeRef shape = HIShapeCreateMutable(); - for (const QRect &rect : region) { - CGRect cgRect = CGRectMake(rect.x(), rect.y(), rect.width(), rect.height()); - HIShapeUnionWithRect(shape, &cgRect); - } - return shape; -} - -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; - [tmpColor getRed:&red green:&green blue:&blue alpha:&alpha]; - qtColor.setRgbF(red, green, blue, alpha); - } - return qtColor; -} - -QColor qt_mac_toQColor(CGColorRef color) -{ - QColor qtColor; - CGColorSpaceModel model = CGColorSpaceGetModel(CGColorGetColorSpace(color)); - const CGFloat *components = CGColorGetComponents(color); - if (model == kCGColorSpaceModelRGB) { - qtColor.setRgbF(components[0], components[1], components[2], components[3]); - } else if (model == kCGColorSpaceModelCMYK) { - qtColor.setCmykF(components[0], components[1], components[2], components[3]); - } else if (model == kCGColorSpaceModelMonochrome) { - qtColor.setRgbF(components[0], components[0], components[0], components[1]); - } else { - // Colorspace we can't deal with. - qWarning("Qt: qt_mac_toQColor: cannot convert from colorspace model: %d", model); - Q_ASSERT(false); - } - return qtColor; -} - -QBrush qt_mac_toQBrush(CGColorRef color) -{ - QBrush qtBrush; - CGColorSpaceModel model = CGColorSpaceGetModel(CGColorGetColorSpace(color)); - if (model == kCGColorSpaceModelPattern) { - // Colorspace we can't deal with; the color is drawn directly using a callback. - qWarning("Qt: qt_mac_toQBrush: cannot convert from colorspace model: %d", model); - Q_ASSERT(false); - } else { - qtBrush.setStyle(Qt::SolidPattern); - qtBrush.setColor(qt_mac_toQColor(color)); - } - return qtBrush; -} - -static bool qt_mac_isSystemColorOrInstance(const NSColor *color, NSString *colorNameComponent, NSString *className) -{ - // 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]) - return true; - return false; -} - -QBrush qt_mac_toQBrush(const NSColor *color, QPalette::ColorGroup colorGroup) -{ - QBrush qtBrush; - - // QTBUG-49773: This calls NSDrawMenuItemBackground to render a 1 by n gradient; could use HITheme - if ([color.className isEqualToString:@"NSMenuItemHighlightColor"]) { - qWarning("Qt: qt_mac_toQBrush: cannot convert from NSMenuItemHighlightColor"); - return qtBrush; - } - - // Not a catalog color or a manifestation of System.windowBackgroundColor; - // only retrieved from NSWindow.backgroundColor directly - if ([color.className isEqualToString:@"NSMetalPatternColor"]) { - // NSTexturedBackgroundWindowMask, could theoretically handle this without private API by - // creating a window with the appropriate properties and then calling NSWindow.backgroundColor.patternImage, - // which returns a texture sized 1 by (window height, including frame), backed by a CGPattern - // which follows the window key state... probably need to allow QBrush to store a function pointer - // like CGPattern does - qWarning("Qt: qt_mac_toQBrush: cannot convert from NSMetalPatternColor"); - return qtBrush; - } - - // No public API to get these colors/stops; - // both accurately obtained through runtime object inspection on OS X 10.11 - // (the NSColor object has NSGradient i-vars for both color groups) - if (qt_mac_isSystemColorOrInstance(color, @"_sourceListBackgroundColor", @"NSSourceListBackgroundColor")) { - QLinearGradient gradient; - if (colorGroup == QPalette::Active) { - gradient.setColorAt(0, QColor(233, 237, 242)); - gradient.setColorAt(0.5, QColor(225, 229, 235)); - gradient.setColorAt(1, QColor(209, 216, 224)); - } else { - gradient.setColorAt(0, QColor(248, 248, 248)); - gradient.setColorAt(0.5, QColor(240, 240, 240)); - gradient.setColorAt(1, QColor(235, 235, 235)); - } - return QBrush(gradient); - } - - // A couple colors are special... they are actually instances of NSGradientPatternColor, which - // override set/setFill/setStroke to instead initialize an internal color - // ([NSColor colorWithCalibratedWhite:0.909804 alpha:1.000000]) while still returning the - // ruled lines pattern image (from OS X 10.4) to the user from -[NSColor patternImage] - // (and providing no public API to get the underlying color without this insanity) - if (qt_mac_isSystemColorOrInstance(color, @"controlColor", @"NSGradientPatternColor") || - qt_mac_isSystemColorOrInstance(color, @"windowBackgroundColor", @"NSGradientPatternColor")) { - qtBrush.setStyle(Qt::SolidPattern); - qtBrush.setColor(qt_mac_toQColor(color.CGColor)); - return qtBrush; - } - - if (NSColor *patternColor = [color colorUsingColorSpaceName:NSPatternColorSpace]) { - NSImage *patternImage = patternColor.patternImage; - const QSizeF sz(patternImage.size.width, patternImage.size.height); - qtBrush.setTexture(qt_mac_toQPixmap(patternImage, sz)); // QTBUG-49774 - } else { - qtBrush.setStyle(Qt::SolidPattern); - qtBrush.setColor(qt_mac_toQColor(color)); - } - return qtBrush; -} - struct dndenum_mapper { NSDragOperation mac_code; @@ -402,97 +192,6 @@ void qt_mac_transformProccessToForegroundApplication() [[NSApplication sharedApplication] setActivationPolicy:NSApplicationActivationPolicyRegular]; } } -static CGColorSpaceRef m_genericColorSpace = 0; -static QHash<CGDirectDisplayID, CGColorSpaceRef> m_displayColorSpaceHash; -static bool m_postRoutineRegistered = false; - -CGColorSpaceRef qt_mac_genericColorSpace() -{ -#if 0 - if (!m_genericColorSpace) { - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) { - m_genericColorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); - } else - { - m_genericColorSpace = CGColorSpaceCreateDeviceRGB(); - } - if (!m_postRoutineRegistered) { - m_postRoutineRegistered = true; - qAddPostRoutine(QCoreGraphicsPaintEngine::cleanUpMacColorSpaces); - } - } - return m_genericColorSpace; -#else - // Just return the main display colorspace for the moment. - return qt_mac_displayColorSpace(0); -#endif -} - -/* - Ideally, we should pass the widget in here, and use CGGetDisplaysWithRect() etc. - to support multiple displays correctly. -*/ -CGColorSpaceRef qt_mac_displayColorSpace(const QWidget *widget) -{ - CGColorSpaceRef colorSpace; - - CGDirectDisplayID displayID; - if (widget == 0) { - displayID = CGMainDisplayID(); - } else { - displayID = CGMainDisplayID(); - /* - ### get correct display - const QRect &qrect = widget->window()->geometry(); - CGRect rect = CGRectMake(qrect.x(), qrect.y(), qrect.width(), qrect.height()); - CGDisplayCount throwAway; - CGDisplayErr dErr = CGGetDisplaysWithRect(rect, 1, &displayID, &throwAway); - if (dErr != kCGErrorSuccess) - return macDisplayColorSpace(0); // fall back on main display - */ - } - if ((colorSpace = m_displayColorSpaceHash.value(displayID))) - return colorSpace; - - colorSpace = CGDisplayCopyColorSpace(displayID); - if (colorSpace == 0) - colorSpace = CGColorSpaceCreateDeviceRGB(); - - m_displayColorSpaceHash.insert(displayID, colorSpace); - if (!m_postRoutineRegistered) { - m_postRoutineRegistered = true; - void qt_mac_cleanUpMacColorSpaces(); - qAddPostRoutine(qt_mac_cleanUpMacColorSpaces); - } - return colorSpace; -} - -void qt_mac_cleanUpMacColorSpaces() -{ - if (m_genericColorSpace) { - CFRelease(m_genericColorSpace); - m_genericColorSpace = 0; - } - QHash<CGDirectDisplayID, CGColorSpaceRef>::const_iterator it = m_displayColorSpaceHash.constBegin(); - while (it != m_displayColorSpaceHash.constEnd()) { - if (it.value()) - CFRelease(it.value()); - ++it; - } - m_displayColorSpaceHash.clear(); -} - -CGColorSpaceRef qt_mac_colorSpaceForDeviceType(const QPaintDevice *paintDevice) -{ -#ifdef QT_NO_WIDGETS - Q_UNUSED(paintDevice) - return qt_mac_displayColorSpace(0); -#else - bool isWidget = (paintDevice->devType() == QInternal::Widget); - return qt_mac_displayColorSpace(isWidget ? static_cast<const QWidget *>(paintDevice): 0); -#endif - -} QString qt_mac_applicationName() { @@ -557,28 +256,6 @@ NSRect qt_mac_flipRect(const QRect &rect) return NSMakeRect(rect.x(), flippedY, rect.width(), rect.height()); } -OSStatus qt_mac_drawCGImage(CGContextRef inContext, const CGRect *inBounds, CGImageRef inImage) -{ - // Verbatim copy if HIViewDrawCGImage (as shown on Carbon-Dev) - OSStatus err = noErr; - - require_action(inContext != NULL, InvalidContext, err = paramErr); - require_action(inBounds != NULL, InvalidBounds, err = paramErr); - require_action(inImage != NULL, InvalidImage, err = paramErr); - - CGContextSaveGState( inContext ); - CGContextTranslateCTM (inContext, 0, inBounds->origin.y + CGRectGetMaxY(*inBounds)); - CGContextScaleCTM(inContext, 1, -1); - - CGContextDrawImage(inContext, *inBounds, inImage); - - CGContextRestoreGState(inContext); -InvalidImage: -InvalidBounds: -InvalidContext: - return err; -} - Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum) { if (buttonNum == 0) @@ -599,81 +276,4 @@ QString qt_mac_removeAmpersandEscapes(QString s) return QPlatformTheme::removeMnemonics(s).trimmed(); } -/*! \internal - - Returns the CoreGraphics CGContextRef of the paint device. 0 is - returned if it can't be obtained. It is the caller's responsibility to - CGContextRelease the context when finished using it. - - \warning This function is only available on \macos. - \warning This function is duplicated in qmacstyle_mac.mm - */ -CGContextRef qt_mac_cg_context(QPaintDevice *pdev) -{ - // In Qt 5, QWidget and QPixmap (and QImage) paint devices are all QImages under the hood. - QImage *image = 0; - if (pdev->devType() == QInternal::Image) { - image = static_cast<QImage *>(pdev); - } else if (pdev->devType() == QInternal::Pixmap) { - - const QPixmap *pm = static_cast<const QPixmap*>(pdev); - QPlatformPixmap *data = const_cast<QPixmap *>(pm)->data_ptr().data(); - if (data && data->classId() == QPlatformPixmap::RasterClass) { - image = data->buffer(); - } else { - qDebug("qt_mac_cg_context: Unsupported pixmap class"); - } - } else if (pdev->devType() == QInternal::Widget) { - // TODO test: image = static_cast<QImage *>(static_cast<const QWidget *>(pdev)->backingStore()->paintDevice()); - qDebug("qt_mac_cg_context: not implemented: Widget class"); - } - - if (!image) - return 0; // Context type not supported. - - CGColorSpaceRef colorspace = qt_mac_colorSpaceForDeviceType(pdev); - uint flags = kCGImageAlphaPremultipliedFirst; - flags |= kCGBitmapByteOrder32Host; - CGContextRef ret = 0; - ret = CGBitmapContextCreate(image->bits(), image->width(), image->height(), - 8, image->bytesPerLine(), colorspace, flags); - CGContextTranslateCTM(ret, 0, image->height()); - CGContextScaleCTM(ret, 1, -1); - return ret; -} - -QPixmap qt_mac_toQPixmap(const NSImage *image, const QSizeF &size) -{ - const NSSize pixmapSize = NSMakeSize(size.width(), size.height()); - QPixmap pixmap(pixmapSize.width, pixmapSize.height); - pixmap.fill(Qt::transparent); - [image setSize:pixmapSize]; - const NSRect iconRect = NSMakeRect(0, 0, pixmapSize.width, pixmapSize.height); - QMacCGContext ctx(&pixmap); - if (!ctx) - return QPixmap(); - NSGraphicsContext *gc = [NSGraphicsContext qt_graphicsContextWithCGContext:ctx flipped:YES]; - if (!gc) - return QPixmap(); - [NSGraphicsContext saveGraphicsState]; - [NSGraphicsContext setCurrentContext:gc]; - [image drawInRect:iconRect fromRect:iconRect operation:NSCompositeSourceOver fraction:1.0 respectFlipped:YES hints:nil]; - [NSGraphicsContext restoreGraphicsState]; - return pixmap; -} - -QImage qt_mac_toQImage(CGImageRef image) -{ - const size_t w = CGImageGetWidth(image), - h = CGImageGetHeight(image); - QImage ret(w, h, QImage::Format_ARGB32_Premultiplied); - ret.fill(Qt::transparent); - CGRect rect = CGRectMake(0, 0, w, h); - CGContextRef ctx = qt_mac_cg_context(&ret); - qt_mac_drawCGImage(ctx, &rect, image); - CGContextRelease(ctx); - return ret; -} - - QT_END_NAMESPACE |