From c52bb0309071bed9e040c79d87f764bac6a396b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Mon, 12 Sep 2016 17:05:39 +0200 Subject: macOS: Move QMacCGContext helper into QtGui MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The implementation was duplicated and spread out between QMacStyle, QMacPaintEngine, and the Cocoa platform plugin. Moving it into QtGui allows using it on other Apple platform. Change-Id: Iadcbd71998204887e116271c575037789b6e2163 Reviewed-by: Jake Petroules Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/cocoa/qcocoahelpers.h | 5 - src/plugins/platforms/cocoa/qcocoahelpers.mm | 138 +---------------------- src/plugins/platforms/cocoa/qcocoaintegration.mm | 7 +- src/plugins/platforms/cocoa/qcocoatheme.mm | 4 +- src/plugins/platforms/cocoa/qpaintengine_mac.mm | 84 +------------- src/plugins/platforms/cocoa/qprintengine_mac_p.h | 3 + src/plugins/platforms/cocoa/qt_mac_p.h | 38 ------- 7 files changed, 14 insertions(+), 265 deletions(-) (limited to 'src/plugins/platforms/cocoa') diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.h b/src/plugins/platforms/cocoa/qcocoahelpers.h index 9b061bbae8..272b443b68 100644 --- a/src/plugins/platforms/cocoa/qcocoahelpers.h +++ b/src/plugins/platforms/cocoa/qcocoahelpers.h @@ -95,9 +95,6 @@ Qt::DropActions qt_mac_mapNSDragOperations(NSDragOperation nsActions); // Misc void qt_mac_transformProccessToForegroundApplication(); -CGColorSpaceRef qt_mac_genericColorSpace(); -CGColorSpaceRef qt_mac_displayColorSpace(const QWidget *widget); -CGColorSpaceRef qt_mac_colorSpaceForDeviceType(const QPaintDevice *paintDevice); QString qt_mac_applicationName(); int qt_mac_flipYCoordinate(int y); @@ -143,8 +140,6 @@ public: } }; -CGContextRef qt_mac_cg_context(QPaintDevice *pdev); - template T qt_mac_resolveOption(const T &fallback, const QByteArray &environment) { diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.mm b/src/plugins/platforms/cocoa/qcocoahelpers.mm index 6920f75887..21ffd8599f 100644 --- a/src/plugins/platforms/cocoa/qcocoahelpers.mm +++ b/src/plugins/platforms/cocoa/qcocoahelpers.mm @@ -47,6 +47,7 @@ #include #include #include +#include #ifndef QT_NO_WIDGETS #include @@ -402,97 +403,6 @@ void qt_mac_transformProccessToForegroundApplication() [[NSApplication sharedApplication] setActivationPolicy:NSApplicationActivationPolicyRegular]; } } -static CGColorSpaceRef m_genericColorSpace = 0; -static QHash 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::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(paintDevice): 0); -#endif - -} QString qt_mac_applicationName() { @@ -599,49 +509,6 @@ 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(pdev); - } else if (pdev->devType() == QInternal::Pixmap) { - - const QPixmap *pm = static_cast(pdev); - QPlatformPixmap *data = const_cast(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(static_cast(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()); @@ -669,9 +536,8 @@ QImage qt_mac_toQImage(CGImageRef 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); + QMacCGContext ctx(&ret); qt_mac_drawCGImage(ctx, &rect, image); - CGContextRelease(ctx); return ret; } diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index 1793bd404e..f3f720654e 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -58,6 +58,8 @@ #include #include +#include + #include static void initResources() @@ -199,8 +201,6 @@ QWindow *QCocoaScreen::topLevelAt(const QPoint &point) const return window; } -extern CGContextRef qt_mac_cg_context(const QPaintDevice *pdev); - QPixmap QCocoaScreen::grabWindow(WId window, int x, int y, int width, int height) const { // TODO window should be handled @@ -251,9 +251,8 @@ QPixmap QCocoaScreen::grabWindow(WId window, int x, int y, int width, int height QPixmap pix(w, h); pix.fill(Qt::transparent); CGRect rect = CGRectMake(0, 0, w, h); - CGContextRef ctx = qt_mac_cg_context(&pix); + QMacCGContext ctx(&pix); qt_mac_drawCGImage(ctx, &rect, image); - CGContextRelease(ctx); QPainter painter(&windowPixmap); painter.drawPixmap(0, 0, pix); diff --git a/src/plugins/platforms/cocoa/qcocoatheme.mm b/src/plugins/platforms/cocoa/qcocoatheme.mm index 95175871a4..d0879ed457 100644 --- a/src/plugins/platforms/cocoa/qcocoatheme.mm +++ b/src/plugins/platforms/cocoa/qcocoatheme.mm @@ -56,6 +56,7 @@ #include #include +#include #include #include #include @@ -197,7 +198,7 @@ QPixmap qt_mac_convert_iconref(const IconRef icon, int width, int height) CGRect rect = CGRectMake(0, 0, width, height); - CGContextRef ctx = qt_mac_cg_context(&ret); + QMacCGContext ctx(&ret); CGAffineTransform old_xform = CGContextGetCTM(ctx); CGContextConcatCTM(ctx, CGAffineTransformInvert(old_xform)); CGContextConcatCTM(ctx, CGAffineTransformIdentity); @@ -205,7 +206,6 @@ QPixmap qt_mac_convert_iconref(const IconRef icon, int width, int height) ::RGBColor b; b.blue = b.green = b.red = 255*255; PlotIconRefInContext(ctx, &rect, kAlignNone, kTransformNone, &b, kPlotIconRefNormalFlags, icon); - CGContextRelease(ctx); return ret; } diff --git a/src/plugins/platforms/cocoa/qpaintengine_mac.mm b/src/plugins/platforms/cocoa/qpaintengine_mac.mm index 759c4d26a5..7e241e3ae6 100644 --- a/src/plugins/platforms/cocoa/qpaintengine_mac.mm +++ b/src/plugins/platforms/cocoa/qpaintengine_mac.mm @@ -63,6 +63,7 @@ #include #include #include +#include #include "qcocoahelpers.h" @@ -74,84 +75,6 @@ QT_BEGIN_NAMESPACE QCoreGraphicsPaintEngine utility functions *****************************************************************************/ -static void qt_mac_clip_cg(CGContextRef hd, const QRegion &rgn, CGAffineTransform *orig_xform) -{ - CGAffineTransform old_xform = CGAffineTransformIdentity; - if (orig_xform) { //setup xforms - old_xform = CGContextGetCTM(hd); - CGContextConcatCTM(hd, CGAffineTransformInvert(old_xform)); - CGContextConcatCTM(hd, *orig_xform); - } - - //do the clipping - CGContextBeginPath(hd); - if (rgn.isEmpty()) { - CGContextAddRect(hd, CGRectMake(0, 0, 0, 0)); - } else { - for (const QRect &r : rgn) { - CGRect mac_r = CGRectMake(r.x(), r.y(), r.width(), r.height()); - CGContextAddRect(hd, mac_r); - } - } - CGContextClip(hd); - - if (orig_xform) {//reset xforms - CGContextConcatCTM(hd, CGAffineTransformInvert(CGContextGetCTM(hd))); - CGContextConcatCTM(hd, old_xform); - } -} - -// Implemented for qt_mac_p.h -QMacCGContext::QMacCGContext(QPainter *p) -{ - QPaintEngine *pe = p->paintEngine(); -#ifndef QT_NO_PRINTER - if (pe->type() == QPaintEngine::MacPrinter) - pe = static_cast(pe)->paintEngine(); -#endif - pe->syncState(); - context = 0; - if (pe->type() == QPaintEngine::CoreGraphics) - context = static_cast(pe)->handle(); - - int devType = p->device()->devType(); - if (pe->type() == QPaintEngine::Raster - && (devType == QInternal::Widget || devType == QInternal::Pixmap || devType == QInternal::Image)) { - - CGColorSpaceRef colorspace = qt_mac_colorSpaceForDeviceType(pe->paintDevice()); - uint flags = kCGImageAlphaPremultipliedFirst; -#ifdef kCGBitmapByteOrder32Host //only needed because CGImage.h added symbols in the minor version - flags |= kCGBitmapByteOrder32Host; -#endif - const QImage *image = (const QImage *) pe->paintDevice(); - - context = CGBitmapContextCreate((void *) image->bits(), image->width(), image->height(), - 8, image->bytesPerLine(), colorspace, flags); - - CGContextTranslateCTM(context, 0, image->height()); - CGContextScaleCTM(context, 1, -1); - - if (devType == QInternal::Widget) { - QRegion clip = p->paintEngine()->systemClip(); - QTransform native = p->deviceTransform(); - - if (p->hasClipping()) { - QRegion r = p->clipRegion(); - r.translate(native.dx(), native.dy()); - if (clip.isEmpty()) - clip = r; - else - clip &= r; - } - qt_mac_clip_cg(context, clip, 0); - - CGContextTranslateCTM(context, native.dx(), native.dy()); - } - } else { - CGContextRetain(context); - } -} - void qt_mac_cgimage_data_free(void *, const void *memoryToFree, size_t) { free(const_cast(memoryToFree)); @@ -453,7 +376,7 @@ static void qt_mac_draw_pattern(void *info, CGContextRef c) const QColor c0(0, 0, 0, 0), c1(255, 255, 255, 255); QPixmap pm(w*QMACPATTERN_MASK_MULTIPLIER, h*QMACPATTERN_MASK_MULTIPLIER); pm.fill(c0); - CGContextRef pm_ctx = qt_mac_cg_context(&pm); + QMacCGContext pm_ctx(&pm); CGContextSetFillColorWithColor(c, cgColorForQColor(c1, pat->pdev)); CGRect rect = CGRectMake(0, 0, w, h); for (int x = 0; x < QMACPATTERN_MASK_MULTIPLIER; ++x) { @@ -543,7 +466,8 @@ QCoreGraphicsPaintEngine::begin(QPaintDevice *pdev) d->cosmeticPenSize = 1; d->current.clipEnabled = false; d->pixelSize = QPoint(1,1); - d->hd = qt_mac_cg_context(pdev); + QMacCGContext ctx(pdev); + d->hd = CGContextRetain(ctx); if (d->hd) { d->saveGraphicsState(); d->orig_xform = CGContextGetCTM(d->hd); diff --git a/src/plugins/platforms/cocoa/qprintengine_mac_p.h b/src/plugins/platforms/cocoa/qprintengine_mac_p.h index e3cad3fd57..ee98275b63 100644 --- a/src/plugins/platforms/cocoa/qprintengine_mac_p.h +++ b/src/plugins/platforms/cocoa/qprintengine_mac_p.h @@ -149,6 +149,9 @@ public: PMPageFormat format() const { return static_cast([printInfo PMPageFormat]); } PMPrintSession session() const { return static_cast([printInfo PMPrintSession]); } PMPrintSettings settings() const { return static_cast([printInfo PMPrintSettings]); } + + QPaintEngine *aggregateEngine() Q_DECL_OVERRIDE { return paintEngine; } + Qt::HANDLE nativeHandle() Q_DECL_OVERRIDE { return q_func()->handle(); } }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qt_mac_p.h b/src/plugins/platforms/cocoa/qt_mac_p.h index 902cf5c636..ce17919e8c 100644 --- a/src/plugins/platforms/cocoa/qt_mac_p.h +++ b/src/plugins/platforms/cocoa/qt_mac_p.h @@ -90,44 +90,6 @@ public: } }; -class QMacCGContext -{ - CGContextRef context; -public: - QMacCGContext(QPainter *p); //qpaintengine_mac.mm - inline QMacCGContext() { context = 0; } - inline QMacCGContext(QPaintDevice *pdev) { - extern CGContextRef qt_mac_cg_context(QPaintDevice *); - context = qt_mac_cg_context(pdev); - } - inline QMacCGContext(CGContextRef cg, bool takeOwnership=false) { - context = cg; - if(!takeOwnership) - CGContextRetain(context); - } - inline QMacCGContext(const QMacCGContext ©) : context(0) { *this = copy; } - inline ~QMacCGContext() { - if(context) - CGContextRelease(context); - } - inline bool isNull() const { return context; } - inline operator CGContextRef() { return context; } - inline QMacCGContext &operator=(const QMacCGContext ©) { - if(context) - CGContextRelease(context); - context = copy.context; - CGContextRetain(context); - return *this; - } - inline QMacCGContext &operator=(CGContextRef cg) { - if(context) - CGContextRelease(context); - context = cg; - CGContextRetain(context); //we do not take ownership - return *this; - } -}; - class QMacInternalPasteboardMime; class QMimeData; -- cgit v1.2.3