Cocoa: Export QImage <-> CGImage conversion funcs.

For implementing to/fromMacCGImageRef in QtMacExtras.

These do not depend on internal Qt state. The main
reason for exporting them is to keep the implementation
in one place to ease maintenance.

Refactor qt_mac_cg_context to support QImage.
Add qt_mac_toQImage.

Change-Id: Ia9c226ed52d087b2c6b47aa8210ed8f2645b9cf2
Reviewed-by: Gabriel de Dietrich <gabriel.dedietrich@digia.com>
This commit is contained in:
Morten Johan Sørvig 2013-01-07 22:38:10 +01:00 committed by The Qt Project
parent 00d8de8589
commit 784b965559
5 changed files with 61 additions and 23 deletions

View File

@ -158,8 +158,9 @@ public:
} }
}; };
CGContextRef qt_mac_cg_context(const QPaintDevice *pdev); CGContextRef qt_mac_cg_context(QPaintDevice *pdev);
CGImageRef qt_mac_toCGImage(const QImage &qImage, bool isMask, uchar **dataCopy); CGImageRef qt_mac_toCGImage(const QImage &qImage, bool isMask, uchar **dataCopy);
QImage qt_mac_toQImage(CGImageRef image);
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@ -719,35 +719,38 @@ QString qt_mac_removeAmpersandEscapes(QString s)
\warning This function is only available on Mac OS X. \warning This function is only available on Mac OS X.
\warning This function is duplicated in qmacstyle_mac.mm \warning This function is duplicated in qmacstyle_mac.mm
*/ */
CGContextRef qt_mac_cg_context(const QPaintDevice *pdev) CGContextRef qt_mac_cg_context(QPaintDevice *pdev)
{ {
if (pdev->devType() == QInternal::Pixmap) { // In Qt 5, QWidget and QPixmap (and QImage) paint devices are all QImages under the hood.
const QPixmap *pm = static_cast<const QPixmap*>(pdev); QImage *image = 0;
CGColorSpaceRef colorspace = qt_mac_colorSpaceForDeviceType(pdev); if (pdev->devType() == QInternal::Image) {
uint flags = kCGImageAlphaPremultipliedFirst; image = static_cast<QImage *>(pdev);
flags |= kCGBitmapByteOrder32Host; } else if (pdev->devType() == QInternal::Pixmap) {
CGContextRef ret = 0;
const QPixmap *pm = static_cast<const QPixmap*>(pdev);
QPlatformPixmap *data = const_cast<QPixmap *>(pm)->data_ptr().data(); QPlatformPixmap *data = const_cast<QPixmap *>(pm)->data_ptr().data();
if (data && data->classId() == QPlatformPixmap::RasterClass) { if (data && data->classId() == QPlatformPixmap::RasterClass) {
QImage *image = data->buffer(); image = data->buffer();
ret = CGBitmapContextCreate(image->bits(), image->width(), image->height(),
8, image->bytesPerLine(), colorspace, flags);
} else { } else {
qDebug() << "qt_mac_cg_context: Unsupported pixmap class"; qDebug() << "qt_mac_cg_context: Unsupported pixmap class";
} }
CGContextTranslateCTM(ret, 0, pm->height());
CGContextScaleCTM(ret, 1, -1);
return ret;
} else if (pdev->devType() == QInternal::Widget) { } else if (pdev->devType() == QInternal::Widget) {
//CGContextRef ret = static_cast<CGContextRef>(static_cast<const QWidget *>(pdev)->macCGHandle()); // TODO test: image = static_cast<QImage *>(static_cast<const QWidget *>(pdev)->backingStore()->paintDevice());
///CGContextRetain(ret);
//return ret;
qDebug() << "qt_mac_cg_context: not implemented: Widget class"; qDebug() << "qt_mac_cg_context: not implemented: Widget class";
return 0;
} }
return 0;
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;
} }
CGImageRef qt_mac_toCGImage(const QImage &qImage, bool isMask, uchar **dataCopy) CGImageRef qt_mac_toCGImage(const QImage &qImage, bool isMask, uchar **dataCopy)
@ -841,4 +844,18 @@ CGImageRef qt_mac_toCGImage(const QImage &qImage, bool isMask, uchar **dataCopy)
return cgImage; return cgImage;
} }
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 QT_END_NAMESPACE

View File

@ -42,6 +42,8 @@
#ifndef QCOCOANATIVEINTERFACE_H #ifndef QCOCOANATIVEINTERFACE_H
#define QCOCOANATIVEINTERFACE_H #define QCOCOANATIVEINTERFACE_H
#include <ApplicationServices/ApplicationServices.h>
#include <qpa/qplatformnativeinterface.h> #include <qpa/qplatformnativeinterface.h>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
@ -96,6 +98,10 @@ private:
// Dock menu support // Dock menu support
static void setDockMenu(QPlatformMenu *platformMenu); static void setDockMenu(QPlatformMenu *platformMenu);
// QImage <-> CGImage conversion functions
static CGImageRef qImageToCGImage(const QImage &image);
static QImage cgImageToQImage(CGImageRef image);
}; };
#endif // QCOCOANATIVEINTERFACE_H #endif // QCOCOANATIVEINTERFACE_H

View File

@ -45,6 +45,7 @@
#include "qcocoamenu.h" #include "qcocoamenu.h"
#include "qcocoamenubar.h" #include "qcocoamenubar.h"
#include "qmacmime.h" #include "qmacmime.h"
#include "qcocoahelpers.h"
#include <qbytearray.h> #include <qbytearray.h>
#include <qwindow.h> #include <qwindow.h>
@ -108,6 +109,10 @@ QPlatformNativeInterface::NativeResourceForIntegrationFunction QCocoaNativeInter
return NativeResourceForIntegrationFunction(QCocoaNativeInterface::registerDraggedTypes); return NativeResourceForIntegrationFunction(QCocoaNativeInterface::registerDraggedTypes);
if (resource.toLower() == "setdockmenu") if (resource.toLower() == "setdockmenu")
return NativeResourceForIntegrationFunction(QCocoaNativeInterface::setDockMenu); return NativeResourceForIntegrationFunction(QCocoaNativeInterface::setDockMenu);
if (resource.toLower() == "qimagetocgimage")
return NativeResourceForIntegrationFunction(QCocoaNativeInterface::qImageToCGImage);
if (resource.toLower() == "cgimagetoqimage")
return NativeResourceForIntegrationFunction(QCocoaNativeInterface::cgImageToQImage);
return 0; return 0;
} }
@ -183,4 +188,15 @@ void QCocoaNativeInterface::setDockMenu(QPlatformMenu *platformMenu)
[NSApp setDockMenu: menu]; [NSApp setDockMenu: menu];
} }
CGImageRef QCocoaNativeInterface::qImageToCGImage(const QImage &image)
{
return qt_mac_toCGImage(image, false, 0);
}
QImage QCocoaNativeInterface::cgImageToQImage(CGImageRef image)
{
return qt_mac_toQImage(image);
}
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@ -53,6 +53,7 @@
#include "qcocoamenuitem.h" #include "qcocoamenuitem.h"
#include "qcocoamenu.h" #include "qcocoamenu.h"
#include "qcocoamenubar.h" #include "qcocoamenubar.h"
#include "qcocoahelpers.h"
#include <QtCore/qfileinfo.h> #include <QtCore/qfileinfo.h>
#include <QtGui/private/qguiapplication_p.h> #include <QtGui/private/qguiapplication_p.h>
@ -137,9 +138,6 @@ const QFont *QCocoaTheme::font(Font type) const
return m_fonts.value(type, 0); return m_fonts.value(type, 0);
} }
// Defined in qpaintengine_mac.mm
extern CGContextRef qt_mac_cg_context(const QPaintDevice *pdev);
//! \internal //! \internal
QPixmap qt_mac_convert_iconref(const IconRef icon, int width, int height) QPixmap qt_mac_convert_iconref(const IconRef icon, int width, int height)
{ {