From 7f179eff61826323afea474b8ecd1a04f0a41e32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Mon, 11 May 2020 17:57:24 +0200 Subject: Move macOS print support from platform plugin into QtPrintSupport MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Task-number: QTBUG-83256 Change-Id: I29044b6c3f952c259f501f94a175c8ef2cbaae55 Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/cocoa/CMakeLists.txt | 18 - src/plugins/platforms/cocoa/cocoa.pro | 17 +- .../platforms/cocoa/qcocoanativeinterface.h | 20 - .../platforms/cocoa/qcocoanativeinterface.mm | 30 - src/plugins/platforms/cocoa/qcocoaprintdevice.h | 122 -- src/plugins/platforms/cocoa/qcocoaprintdevice.mm | 498 ------- src/plugins/platforms/cocoa/qcocoaprintersupport.h | 65 - .../platforms/cocoa/qcocoaprintersupport.mm | 111 -- src/plugins/platforms/cocoa/qpaintengine_mac.mm | 1428 -------------------- src/plugins/platforms/cocoa/qpaintengine_mac_p.h | 205 --- src/plugins/platforms/cocoa/qprintengine_mac.mm | 797 ----------- src/plugins/platforms/cocoa/qprintengine_mac_p.h | 157 --- src/plugins/printsupport/cocoa/main.cpp | 16 +- 13 files changed, 5 insertions(+), 3479 deletions(-) delete mode 100644 src/plugins/platforms/cocoa/qcocoaprintdevice.h delete mode 100644 src/plugins/platforms/cocoa/qcocoaprintdevice.mm delete mode 100644 src/plugins/platforms/cocoa/qcocoaprintersupport.h delete mode 100644 src/plugins/platforms/cocoa/qcocoaprintersupport.mm delete mode 100644 src/plugins/platforms/cocoa/qpaintengine_mac.mm delete mode 100644 src/plugins/platforms/cocoa/qpaintengine_mac_p.h delete mode 100644 src/plugins/platforms/cocoa/qprintengine_mac.mm delete mode 100644 src/plugins/platforms/cocoa/qprintengine_mac_p.h (limited to 'src/plugins') diff --git a/src/plugins/platforms/cocoa/CMakeLists.txt b/src/plugins/platforms/cocoa/CMakeLists.txt index 9d578e7eed..11f3f99d8d 100644 --- a/src/plugins/platforms/cocoa/CMakeLists.txt +++ b/src/plugins/platforms/cocoa/CMakeLists.txt @@ -1,7 +1,6 @@ # Generated from cocoa.pro. # special case: -qt_find_package(Cups PROVIDED_TARGETS Cups::Cups) ##################################################################### ## QCocoaIntegrationPlugin Plugin: @@ -55,7 +54,6 @@ qt_internal_add_plugin(QCocoaIntegrationPlugin ${FWIOSurface} ${FWMetal} ${FWQuartzCore} - Cups::Cups Qt::Core Qt::CorePrivate Qt::Gui @@ -110,25 +108,9 @@ qt_extend_target(QCocoaIntegrationPlugin CONDITION QT_FEATURE_sessionmanager qcocoasessionmanager.cpp qcocoasessionmanager.h ) -qt_extend_target(QCocoaIntegrationPlugin CONDITION TARGET Qt::Widgets - SOURCES - qpaintengine_mac.mm qpaintengine_mac_p.h - PUBLIC_LIBRARIES - Qt::WidgetsPrivate -) - #### Keys ignored in scope 7:.:.:cocoa.pro:TARGET Qt::Widgets: # QT_FOR_CONFIG = "widgets" -qt_extend_target(QCocoaIntegrationPlugin CONDITION TARGET Qt::PrintSupport AND TARGET Qt::Widgets - SOURCES - qcocoaprintdevice.h qcocoaprintdevice.mm - qcocoaprintersupport.h qcocoaprintersupport.mm - qprintengine_mac.mm qprintengine_mac_p.h - PUBLIC_LIBRARIES - Qt::PrintSupportPrivate -) - qt_extend_target(QCocoaIntegrationPlugin CONDITION QT_FEATURE_colordialog AND TARGET Qt::Widgets SOURCES qcocoacolordialoghelper.h qcocoacolordialoghelper.mm diff --git a/src/plugins/platforms/cocoa/cocoa.pro b/src/plugins/platforms/cocoa/cocoa.pro index c0a7b4e6cf..a33b99e898 100644 --- a/src/plugins/platforms/cocoa/cocoa.pro +++ b/src/plugins/platforms/cocoa/cocoa.pro @@ -89,7 +89,7 @@ qtConfig(sessionmanager) { RESOURCES += qcocoaresources.qrc -LIBS += -framework AppKit -framework CoreServices -framework Carbon -framework IOKit -framework QuartzCore -framework CoreVideo -framework Metal -framework IOSurface -lcups +LIBS += -framework AppKit -framework CoreServices -framework Carbon -framework IOKit -framework QuartzCore -framework CoreVideo -framework Metal -framework IOSurface DEFINES += QT_NO_FOREACH @@ -100,21 +100,6 @@ CONFIG += no_app_extension_api_only qtHaveModule(widgets) { QT_FOR_CONFIG += widgets - SOURCES += qpaintengine_mac.mm - HEADERS += qpaintengine_mac_p.h - - qtHaveModule(printsupport) { - QT += printsupport-private - SOURCES += \ - qprintengine_mac.mm \ - qcocoaprintersupport.mm \ - qcocoaprintdevice.mm - HEADERS += \ - qcocoaprintersupport.h \ - qcocoaprintdevice.h \ - qprintengine_mac_p.h - } - qtConfig(colordialog) { SOURCES += qcocoacolordialoghelper.mm HEADERS += qcocoacolordialoghelper.h diff --git a/src/plugins/platforms/cocoa/qcocoanativeinterface.h b/src/plugins/platforms/cocoa/qcocoanativeinterface.h index c30297c8ca..45330cf1b8 100644 --- a/src/plugins/platforms/cocoa/qcocoanativeinterface.h +++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.h @@ -45,13 +45,10 @@ #include #include Q_MOC_INCLUDE() -Q_MOC_INCLUDE() -Q_MOC_INCLUDE() QT_BEGIN_NAMESPACE class QWidget; -class QPlatformPrinterSupport; class QPrintEngine; class QPlatformMenu; class QPlatformMenuBar; @@ -80,23 +77,6 @@ public Q_SLOTS: void onAppFocusWindowChanged(QWindow *window); private: - /* - "Virtual" function to create the platform printer support - implementation. - - We use an invokable function instead of a virtual one, we do not want - this in the QPlatform* API yet. - - This was added here only because QPlatformNativeInterface is a QObject - and allow us to use QMetaObject::indexOfMethod() from the printsupport - plugin. - */ - Q_INVOKABLE QPlatformPrinterSupport *createPlatformPrinterSupport(); - /* - Function to return the NSPrintInfo * from QMacPaintEnginePrivate. - Needed by the native print dialog in the Qt Print Support module. - */ - Q_INVOKABLE void *NSPrintInfoForPrintEngine(QPrintEngine *printEngine); /* Function to return the default background pixmap. Needed by QWizard in the Qt widget module. diff --git a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm index 8e336d9ee7..fbc2e8f13e 100644 --- a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm +++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm @@ -59,12 +59,6 @@ #include #include -#if !defined(QT_NO_WIDGETS) && defined(QT_PRINTSUPPORT_LIB) -#include "qcocoaprintersupport.h" -#include "qprintengine_mac_p.h" -#include -#endif - #include #include @@ -147,30 +141,6 @@ QPlatformNativeInterface::NativeResourceForIntegrationFunction QCocoaNativeInter return nullptr; } -QPlatformPrinterSupport *QCocoaNativeInterface::createPlatformPrinterSupport() -{ -#if !defined(QT_NO_WIDGETS) && !defined(QT_NO_PRINTER) && defined(QT_PRINTSUPPORT_LIB) - return new QCocoaPrinterSupport(); -#else - qFatal("Printing is not supported when Qt is configured with -no-widgets or -no-feature-printer"); - return nullptr; -#endif -} - -void *QCocoaNativeInterface::NSPrintInfoForPrintEngine(QPrintEngine *printEngine) -{ -#if !defined(QT_NO_WIDGETS) && !defined(QT_NO_PRINTER) && defined(QT_PRINTSUPPORT_LIB) - QMacPrintEnginePrivate *macPrintEnginePriv = static_cast(printEngine)->d_func(); - if (macPrintEnginePriv->state == QPrinter::Idle && !macPrintEnginePriv->isPrintSessionInitialized()) - macPrintEnginePriv->initialize(); - return macPrintEnginePriv->printInfo; -#else - Q_UNUSED(printEngine); - qFatal("Printing is not supported when Qt is configured with -no-widgets or -no-feature-printer"); - return nullptr; -#endif -} - QPixmap QCocoaNativeInterface::defaultBackgroundPixmapForQWizard() { // Note: starting with macOS 10.14, the KeyboardSetupAssistant app bundle no diff --git a/src/plugins/platforms/cocoa/qcocoaprintdevice.h b/src/plugins/platforms/cocoa/qcocoaprintdevice.h deleted file mode 100644 index 59a521e0b5..0000000000 --- a/src/plugins/platforms/cocoa/qcocoaprintdevice.h +++ /dev/null @@ -1,122 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 John Layt -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the plugins 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$ -** -****************************************************************************/ - -#ifndef QCOCOAPRINTDEVICE_H -#define QCOCOAPRINTDEVICE_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of internal files. This header file may change from version to version -// without notice, or even be removed. -// -// We mean it. -// - -#include - -#ifndef QT_NO_PRINTER - -#include - -QT_BEGIN_NAMESPACE - -class QCocoaPrintDevice : public QPlatformPrintDevice -{ -public: - QCocoaPrintDevice(); - explicit QCocoaPrintDevice(const QString &id); - virtual ~QCocoaPrintDevice(); - - bool isValid() const override; - bool isDefault() const override; - - QPrint::DeviceState state() const override; - - QPageSize defaultPageSize() const override; - - QMarginsF printableMargins(const QPageSize &pageSize, QPageLayout::Orientation orientation, - int resolution) const override; - - int defaultResolution() const override; - - QPrint::InputSlot defaultInputSlot() const override; - - QPrint::OutputBin defaultOutputBin() const override; - - QPrint::DuplexMode defaultDuplexMode() const override; - - QPrint::ColorMode defaultColorMode() const override; - - PMPrinter macPrinter() const; - PMPaper macPaper(const QPageSize &pageSize) const; - -protected: - void loadPageSizes() const override; - void loadResolutions() const override; - void loadInputSlots() const override; - void loadOutputBins() const override; - void loadDuplexModes() const override; - void loadColorModes() const override; -#if QT_CONFIG(mimetype) - void loadMimeTypes() const override; -#endif - -private: - QPageSize createPageSize(const PMPaper &paper) const; - bool openPpdFile(); - - // Mac Core Printing - PMPrinter m_printer; - PMPrintSession m_session; - mutable QHash m_macPapers; - - // PPD File - ppd_file_t *m_ppd; - - QMarginsF m_customMargins; - mutable QHash m_printableMargins; -}; - -QT_END_NAMESPACE - -#endif // QT_NO_PRINTER -#endif // QCOCOAPRINTDEVICE_H diff --git a/src/plugins/platforms/cocoa/qcocoaprintdevice.mm b/src/plugins/platforms/cocoa/qcocoaprintdevice.mm deleted file mode 100644 index ab304d9c04..0000000000 --- a/src/plugins/platforms/cocoa/qcocoaprintdevice.mm +++ /dev/null @@ -1,498 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 John Layt -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the plugins 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$ -** -****************************************************************************/ - -#include - -#include "qcocoaprintdevice.h" - -#if QT_CONFIG(mimetype) -#include -#endif -#include - -#include - -QT_BEGIN_NAMESPACE - -#ifndef QT_NO_PRINTER - -// The CUPS PPD APIs were deprecated in CUPS 1.6/macOS 10.8, but -// as long as we're supporting RHEL 6, which still ships CUPS 1.4 -// we're not going to rewrite this, as we want to share the code -// between macOS and Linux for the CUPS-bits. See discussion in -// https://bugreports.qt.io/browse/QTBUG-56545 -#pragma message "Disabling CUPS PPD deprecation warnings. This should be fixed once we drop support for RHEL6 (QTBUG-56545)" -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - -static QPrint::DuplexMode macToDuplexMode(const PMDuplexMode &mode) -{ - if (mode == kPMDuplexTumble) - return QPrint::DuplexShortSide; - else if (mode == kPMDuplexNoTumble) - return QPrint::DuplexLongSide; - else // kPMDuplexNone or kPMSimplexTumble - return QPrint::DuplexNone; -} - -QCocoaPrintDevice::QCocoaPrintDevice() - : QPlatformPrintDevice(), - m_printer(nullptr), - m_session(nullptr), - m_ppd(nullptr) -{ -} - -QCocoaPrintDevice::QCocoaPrintDevice(const QString &id) - : QPlatformPrintDevice(id), - m_printer(nullptr), - m_session(nullptr), - m_ppd(nullptr) -{ - if (!id.isEmpty()) { - m_printer = PMPrinterCreateFromPrinterID(id.toCFString()); - if (m_printer) { - m_name = QString::fromCFString(PMPrinterGetName(m_printer)); - m_location = QString::fromCFString(PMPrinterGetLocation(m_printer)); - CFStringRef cfMakeAndModel; - if (PMPrinterGetMakeAndModelName(m_printer, &cfMakeAndModel) == noErr) - m_makeAndModel = QString::fromCFString(cfMakeAndModel); - Boolean isRemote; - if (PMPrinterIsRemote(m_printer, &isRemote) == noErr) - m_isRemote = isRemote; - if (PMCreateSession(&m_session) == noErr) - PMSessionSetCurrentPMPrinter(m_session, m_printer); - - // No native api to query these options, need to use PPD directly, note is deprecated from 1.6 onwards - if (openPpdFile()) { - // Note this is if the hardware does multiple copies, not if Cups can - m_supportsMultipleCopies = !m_ppd->manual_copies; - // Note this is if the hardware does collation, not if Cups can - ppd_option_t *collate = ppdFindOption(m_ppd, "Collate"); - if (collate) - m_supportsCollateCopies = true; - m_supportsCustomPageSizes = m_ppd->custom_max[0] > 0 && m_ppd->custom_max[1] > 0; - m_minimumPhysicalPageSize = QSize(m_ppd->custom_min[0], m_ppd->custom_min[1]); - m_maximumPhysicalPageSize = QSize(m_ppd->custom_max[0], m_ppd->custom_max[1]); - m_customMargins = QMarginsF(m_ppd->custom_margins[0], m_ppd->custom_margins[3], - m_ppd->custom_margins[2], m_ppd->custom_margins[1]); - } - } - } -} - -QCocoaPrintDevice::~QCocoaPrintDevice() -{ - if (m_ppd) - ppdClose(m_ppd); - for (PMPaper paper : m_macPapers) - PMRelease(paper); - // Releasing the session appears to also release the printer - if (m_session) - PMRelease(m_session); - else if (m_printer) - PMRelease(m_printer); -} - -bool QCocoaPrintDevice::isValid() const -{ - return m_printer ? true : false; -} - -bool QCocoaPrintDevice::isDefault() const -{ - return PMPrinterIsDefault(m_printer); -} - -QPrint::DeviceState QCocoaPrintDevice::state() const -{ - PMPrinterState state; - if (PMPrinterGetState(m_printer, &state) == noErr) { - if (state == kPMPrinterIdle) - return QPrint::Idle; - else if (state == kPMPrinterProcessing) - return QPrint::Active; - else if (state == kPMPrinterStopped) - return QPrint::Error; - } - return QPrint::Error; -} - -QPageSize QCocoaPrintDevice::createPageSize(const PMPaper &paper) const -{ - CFStringRef key; - double width; - double height; - CFStringRef localizedName; - if (PMPaperGetPPDPaperName(paper, &key) == noErr - && PMPaperGetWidth(paper, &width) == noErr - && PMPaperGetHeight(paper, &height) == noErr - && PMPaperCreateLocalizedName(paper, m_printer, &localizedName) == noErr) { - QPageSize pageSize = QPlatformPrintDevice::createPageSize(QString::fromCFString(key),QSize(width, height), - QString::fromCFString(localizedName)); - CFRelease(localizedName); - return pageSize; - } - return QPageSize(); -} - -void QCocoaPrintDevice::loadPageSizes() const -{ - m_pageSizes.clear(); - for (PMPaper paper : m_macPapers) - PMRelease(paper); - m_macPapers.clear(); - m_printableMargins.clear(); - CFArrayRef paperSizes; - if (PMPrinterGetPaperList(m_printer, &paperSizes) == noErr) { - int count = CFArrayGetCount(paperSizes); - for (int i = 0; i < count; ++i) { - PMPaper paper = static_cast(const_cast(CFArrayGetValueAtIndex(paperSizes, i))); - QPageSize pageSize = createPageSize(paper); - if (pageSize.isValid()) { - m_pageSizes.append(pageSize); - PMRetain(paper); - m_macPapers.insert(pageSize.key(), paper); - PMPaperMargins printMargins; - PMPaperGetMargins(paper, &printMargins); - m_printableMargins.insert(pageSize.key(), QMarginsF(printMargins.left, printMargins.top, - printMargins.right, printMargins.bottom)); - } - } - } - m_havePageSizes = true; -} - -QPageSize QCocoaPrintDevice::defaultPageSize() const -{ - QPageSize pageSize; - PMPageFormat pageFormat; - PMPaper paper; - if (PMCreatePageFormat(&pageFormat) == noErr) { - if (PMSessionDefaultPageFormat(m_session, pageFormat) == noErr - && PMGetPageFormatPaper(pageFormat, &paper) == noErr) { - pageSize = createPageSize(paper); - } - PMRelease(pageFormat); - } - return pageSize; -} - -QMarginsF QCocoaPrintDevice::printableMargins(const QPageSize &pageSize, - QPageLayout::Orientation orientation, - int resolution) const -{ - Q_UNUSED(orientation) - Q_UNUSED(resolution) - if (!m_havePageSizes) - loadPageSizes(); - if (m_printableMargins.contains(pageSize.key())) - return m_printableMargins.value(pageSize.key()); - return m_customMargins; -} - -void QCocoaPrintDevice::loadResolutions() const -{ - m_resolutions.clear(); - UInt32 count; - if (PMPrinterGetPrinterResolutionCount(m_printer, &count) == noErr) { - // 1-based index - for (UInt32 i = 1; i <= count; ++i) { - PMResolution resolution; - if (PMPrinterGetIndexedPrinterResolution(m_printer, i, &resolution) == noErr) - m_resolutions.append(int(resolution.hRes)); - } - } - m_haveResolutions = true; -} - -int QCocoaPrintDevice::defaultResolution() const -{ - int defaultResolution = 72; - PMPrintSettings settings; - if (PMCreatePrintSettings(&settings) == noErr) { - PMResolution resolution; - if (PMSessionDefaultPrintSettings(m_session, settings) == noErr - && PMPrinterGetOutputResolution(m_printer, settings, &resolution) == noErr) { - // PMPrinterGetOutputResolution usually fails with -9589 kPMKeyNotFound as not set in PPD - defaultResolution = int(resolution.hRes); - } - PMRelease(settings); - } - // If no value returned (usually means not set in PPD) then use supported resolutions which - // OSX will have populated with at least one default value (but why not returned by call?) - if (defaultResolution <= 0) { - if (!m_haveResolutions) - loadResolutions(); - if (m_resolutions.count() > 0) - return m_resolutions.at(0); // First value or highest? Only likely to be one anyway. - return 72; // TDOD More sensible default value??? - } - return defaultResolution; -} - -void QCocoaPrintDevice::loadInputSlots() const -{ - // NOTE: Implemented in both CUPS and Mac plugins, please keep in sync - // TODO Deal with concatenated names like Tray1Manual or Tray1_Man, - // will currently show as CustomInputSlot - // TODO Deal with separate ManualFeed key - // Try load standard PPD options first - m_inputSlots.clear(); - if (m_ppd) { - ppd_option_t *inputSlots = ppdFindOption(m_ppd, "InputSlot"); - if (inputSlots) { - for (int i = 0; i < inputSlots->num_choices; ++i) - m_inputSlots.append(QPrintUtils::ppdChoiceToInputSlot(inputSlots->choices[i])); - } - // If no result, try just the default - if (m_inputSlots.size() == 0) { - inputSlots = ppdFindOption(m_ppd, "DefaultInputSlot"); - if (inputSlots) - m_inputSlots.append(QPrintUtils::ppdChoiceToInputSlot(inputSlots->choices[0])); - } - } - // If still no result, just use Auto - if (m_inputSlots.size() == 0) - m_inputSlots.append(QPlatformPrintDevice::defaultInputSlot()); - m_haveInputSlots = true; -} - -QPrint::InputSlot QCocoaPrintDevice::defaultInputSlot() const -{ - // No native api to query, use PPD directly - // NOTE: Implemented in both CUPS and Mac plugins, please keep in sync - // Try load standard PPD option first - if (m_ppd) { - ppd_option_t *inputSlot = ppdFindOption(m_ppd, "DefaultInputSlot"); - if (inputSlot) - return QPrintUtils::ppdChoiceToInputSlot(inputSlot->choices[0]); - // If no result, then try a marked option - ppd_choice_t *defaultChoice = ppdFindMarkedChoice(m_ppd, "InputSlot"); - if (defaultChoice) - return QPrintUtils::ppdChoiceToInputSlot(*defaultChoice); - } - // Otherwise return Auto - return QPlatformPrintDevice::defaultInputSlot(); -} - -void QCocoaPrintDevice::loadOutputBins() const -{ - // No native api to query, use PPD directly - // NOTE: Implemented in both CUPS and Mac plugins, please keep in sync - m_outputBins.clear(); - if (m_ppd) { - ppd_option_t *outputBins = ppdFindOption(m_ppd, "OutputBin"); - if (outputBins) { - for (int i = 0; i < outputBins->num_choices; ++i) - m_outputBins.append(QPrintUtils::ppdChoiceToOutputBin(outputBins->choices[i])); - } - // If no result, try just the default - if (m_outputBins.size() == 0) { - outputBins = ppdFindOption(m_ppd, "DefaultOutputBin"); - if (outputBins) - m_outputBins.append(QPrintUtils::ppdChoiceToOutputBin(outputBins->choices[0])); - } - } - // If still no result, just use Auto - if (m_outputBins.size() == 0) - m_outputBins.append(QPlatformPrintDevice::defaultOutputBin()); - m_haveOutputBins = true; -} - -QPrint::OutputBin QCocoaPrintDevice::defaultOutputBin() const -{ - // No native api to query, use PPD directly - // NOTE: Implemented in both CUPS and Mac plugins, please keep in sync - // Try load standard PPD option first - if (m_ppd) { - ppd_option_t *outputBin = ppdFindOption(m_ppd, "DefaultOutputBin"); - if (outputBin) - return QPrintUtils::ppdChoiceToOutputBin(outputBin->choices[0]); - // If no result, then try a marked option - ppd_choice_t *defaultChoice = ppdFindMarkedChoice(m_ppd, "OutputBin"); - if (defaultChoice) - return QPrintUtils::ppdChoiceToOutputBin(*defaultChoice); - } - // Otherwise return AutoBin - return QPlatformPrintDevice::defaultOutputBin(); -} - -void QCocoaPrintDevice::loadDuplexModes() const -{ - // No native api to query, use PPD directly - // NOTE: Implemented in both CUPS and Mac plugins, please keep in sync - // Try load standard PPD options first - m_duplexModes.clear(); - if (m_ppd) { - ppd_option_t *duplexModes = ppdFindOption(m_ppd, "Duplex"); - if (duplexModes) { - for (int i = 0; i < duplexModes->num_choices; ++i) - m_duplexModes.append(QPrintUtils::ppdChoiceToDuplexMode(duplexModes->choices[i].choice)); - } - // If no result, try just the default - if (m_duplexModes.size() == 0) { - duplexModes = ppdFindOption(m_ppd, "DefaultDuplex"); - if (duplexModes) - m_duplexModes.append(QPrintUtils::ppdChoiceToDuplexMode(duplexModes->choices[0].choice)); - } - } - // If still no result, or not added in PPD, then add None - if (m_duplexModes.size() == 0 || !m_duplexModes.contains(QPrint::DuplexNone)) - m_duplexModes.append(QPrint::DuplexNone); - // If have both modes, then can support DuplexAuto - if (m_duplexModes.contains(QPrint::DuplexLongSide) && m_duplexModes.contains(QPrint::DuplexShortSide)) - m_duplexModes.append(QPrint::DuplexAuto); - m_haveDuplexModes = true; -} - -QPrint::DuplexMode QCocoaPrintDevice::defaultDuplexMode() const -{ - QPrint::DuplexMode defaultMode = QPrint::DuplexNone; - PMPrintSettings settings; - if (PMCreatePrintSettings(&settings) == noErr) { - PMDuplexMode duplexMode; - if (PMSessionDefaultPrintSettings(m_session, settings) == noErr - && PMGetDuplex(settings, &duplexMode) == noErr) { - defaultMode = macToDuplexMode(duplexMode); - } - PMRelease(settings); - } - return defaultMode; -} - -void QCocoaPrintDevice::loadColorModes() const -{ - // No native api to query, use PPD directly - m_colorModes.clear(); - m_colorModes.append(QPrint::GrayScale); - if (!m_ppd || (m_ppd && m_ppd->color_device)) - m_colorModes.append(QPrint::Color); - m_haveColorModes = true; -} - -QPrint::ColorMode QCocoaPrintDevice::defaultColorMode() const -{ - // No native api to query, use PPD directly - // NOTE: Implemented in both CUPS and Mac plugins, please keep in sync - // Not a proper option, usually only know if supports color or not, but some - // users known to abuse ColorModel to always force GrayScale. - if (m_ppd && supportedColorModes().contains(QPrint::Color)) { - ppd_option_t *colorModel = ppdFindOption(m_ppd, "DefaultColorModel"); - if (!colorModel) - colorModel = ppdFindOption(m_ppd, "ColorModel"); - if (!colorModel || qstrcmp(colorModel->defchoice, "Gray") != 0) - return QPrint::Color; - } - return QPrint::GrayScale; -} - -#if QT_CONFIG(mimetype) -void QCocoaPrintDevice::loadMimeTypes() const -{ - // TODO Check how settings affect returned list - m_mimeTypes.clear(); - QMimeDatabase db; - PMPrintSettings settings; - if (PMCreatePrintSettings(&settings) == noErr) { - CFArrayRef mimeTypes; - if (PMPrinterGetMimeTypes(m_printer, settings, &mimeTypes) == noErr) { - int count = CFArrayGetCount(mimeTypes); - for (int i = 0; i < count; ++i) { - CFStringRef mimeName = static_cast(const_cast(CFArrayGetValueAtIndex(mimeTypes, i))); - QMimeType mimeType = db.mimeTypeForName(QString::fromCFString(mimeName)); - if (mimeType.isValid()) - m_mimeTypes.append(mimeType); - } - } - PMRelease(settings); - } - m_haveMimeTypes = true; -} -#endif // mimetype - -bool QCocoaPrintDevice::openPpdFile() -{ - if (m_ppd) - ppdClose(m_ppd); - m_ppd = nullptr; - CFURLRef ppdURL = nullptr; - char ppdPath[MAXPATHLEN]; - if (PMPrinterCopyDescriptionURL(m_printer, kPMPPDDescriptionType, &ppdURL) == noErr - && ppdURL) { - if (CFURLGetFileSystemRepresentation(ppdURL, true, (UInt8*)ppdPath, sizeof(ppdPath))) - m_ppd = ppdOpenFile(ppdPath); - CFRelease(ppdURL); - } - return m_ppd ? true : false; -} - -PMPrinter QCocoaPrintDevice::macPrinter() const -{ - return m_printer; -} - -// Returns a cached printer PMPaper, or creates and caches a new custom PMPaper -// Caller should never release a cached PMPaper! -PMPaper QCocoaPrintDevice::macPaper(const QPageSize &pageSize) const -{ - if (!m_havePageSizes) - loadPageSizes(); - // If keys match, then is a supported size or an existing custom size - if (m_macPapers.contains(pageSize.key())) - return m_macPapers.value(pageSize.key()); - // For any other page size, whether custom or just unsupported, needs to be a custom PMPaper - PMPaper paper = nullptr; - PMPaperMargins paperMargins; - paperMargins.left = m_customMargins.left(); - paperMargins.right = m_customMargins.right(); - paperMargins.top = m_customMargins.top(); - paperMargins.bottom = m_customMargins.bottom(); - PMPaperCreateCustom(m_printer, QCFString(pageSize.key()), QCFString(pageSize.name()), - pageSize.sizePoints().width(), pageSize.sizePoints().height(), - &paperMargins, &paper); - m_macPapers.insert(pageSize.key(), paper); - return paper; -} - -#pragma clang diagnostic pop - -#endif // QT_NO_PRINTER - -QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoaprintersupport.h b/src/plugins/platforms/cocoa/qcocoaprintersupport.h deleted file mode 100644 index b1a9541c03..0000000000 --- a/src/plugins/platforms/cocoa/qcocoaprintersupport.h +++ /dev/null @@ -1,65 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtPrintSupport 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$ -** -****************************************************************************/ - -#ifndef QCOCOAPRINTERSUPPORT_H -#define QCOCOAPRINTERSUPPORT_H - -#include -#ifndef QT_NO_PRINTER - -QT_BEGIN_NAMESPACE - -class QCocoaPrinterSupport : public QPlatformPrinterSupport -{ -public: - QCocoaPrinterSupport(); - ~QCocoaPrinterSupport(); - - QPrintEngine *createNativePrintEngine(QPrinter::PrinterMode printerMode, const QString &deviceId = QString()) override; - QPaintEngine *createPaintEngine(QPrintEngine *, QPrinter::PrinterMode printerMode) override; - - QPrintDevice createPrintDevice(const QString &id) override; - QStringList availablePrintDeviceIds() const override; - QString defaultPrintDeviceId() const override; -}; - -QT_END_NAMESPACE - -#endif // QT_NO_PRINTER -#endif // QCOCOAPRINTERSUPPORT_H diff --git a/src/plugins/platforms/cocoa/qcocoaprintersupport.mm b/src/plugins/platforms/cocoa/qcocoaprintersupport.mm deleted file mode 100644 index 4c5c7aef88..0000000000 --- a/src/plugins/platforms/cocoa/qcocoaprintersupport.mm +++ /dev/null @@ -1,111 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtPrintSupport 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$ -** -****************************************************************************/ - -#include "qcocoaprintersupport.h" - -#ifndef QT_NO_PRINTER - -#include - -#include - -#include "qcocoaprintdevice.h" -#include "qprintengine_mac_p.h" - -#include - -QT_BEGIN_NAMESPACE - -QCocoaPrinterSupport::QCocoaPrinterSupport() -{ } - -QCocoaPrinterSupport::~QCocoaPrinterSupport() -{ } - -QPrintEngine *QCocoaPrinterSupport::createNativePrintEngine(QPrinter::PrinterMode printerMode, const QString &deviceId) -{ - return new QMacPrintEngine(printerMode, deviceId); -} - -QPaintEngine *QCocoaPrinterSupport::createPaintEngine(QPrintEngine *printEngine, QPrinter::PrinterMode printerMode) -{ - Q_UNUSED(printerMode); - /* - QMacPrintEngine multiply inherits from QPrintEngine and QPaintEngine, - the cast here allows conversion of QMacPrintEngine* to QPaintEngine* - */ - return static_cast(printEngine); -} - -QPrintDevice QCocoaPrinterSupport::createPrintDevice(const QString &id) -{ - return QPlatformPrinterSupport::createPrintDevice(new QCocoaPrintDevice(id)); -} - -QStringList QCocoaPrinterSupport::availablePrintDeviceIds() const -{ - QStringList list; - QCFType printerList; - if (PMServerCreatePrinterList(kPMServerLocal, &printerList) == noErr) { - CFIndex count = CFArrayGetCount(printerList); - for (CFIndex i = 0; i < count; ++i) { - PMPrinter printer = static_cast(const_cast(CFArrayGetValueAtIndex(printerList, i))); - list.append(QString::fromCFString(PMPrinterGetID(printer))); - } - } - return list; -} - -QString QCocoaPrinterSupport::defaultPrintDeviceId() const -{ - QCFType printerList; - if (PMServerCreatePrinterList(kPMServerLocal, &printerList) == noErr) { - CFIndex count = CFArrayGetCount(printerList); - for (CFIndex i = 0; i < count; ++i) { - PMPrinter printer = static_cast(const_cast(CFArrayGetValueAtIndex(printerList, i))); - if (PMPrinterIsDefault(printer)) - return QString::fromCFString(PMPrinterGetID(printer)); - } - } - return QString(); -} - -QT_END_NAMESPACE - -#endif //QT_NO_PRINTER diff --git a/src/plugins/platforms/cocoa/qpaintengine_mac.mm b/src/plugins/platforms/cocoa/qpaintengine_mac.mm deleted file mode 100644 index b50c39c9b0..0000000000 --- a/src/plugins/platforms/cocoa/qpaintengine_mac.mm +++ /dev/null @@ -1,1428 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the plugins 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$ -** -****************************************************************************/ - -#include -#include - -#include "qpaintengine_mac_p.h" -#if defined(QT_PRINTSUPPORT_LIB) -#include "qprintengine_mac_p.h" -#endif - -#include -#include -#include -#include -#include -#if defined(QT_PRINTSUPPORT_LIB) -#include -#endif -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "qcocoahelpers.h" - -#include - -QT_BEGIN_NAMESPACE - -/***************************************************************************** - QCoreGraphicsPaintEngine utility functions - *****************************************************************************/ - -void qt_mac_cgimage_data_free(void *, const void *memoryToFree, size_t) -{ - free(const_cast(memoryToFree)); -} - -CGImageRef qt_mac_create_imagemask(const QPixmap &pixmap, const QRectF &sr) -{ - QImage image = pixmap.toImage(); - if (image.format() != QImage::Format_ARGB32_Premultiplied) - image = image.convertToFormat(QImage::Format_ARGB32_Premultiplied); - - const int sx = qRound(sr.x()), sy = qRound(sr.y()), sw = qRound(sr.width()), sh = qRound(sr.height()); - const qsizetype sbpr = image.bytesPerLine(); - const uint nbytes = sw * sh; - // alpha is always 255 for bitmaps, ignore it in this case. - const quint32 mask = pixmap.depth() == 1 ? 0x00ffffff : 0xffffffff; - quint8 *dptr = static_cast(malloc(nbytes)); - quint32 *sptr = reinterpret_cast(image.scanLine(0)), *srow; - for (int y = sy, offset=0; y < sh; ++y) { - srow = sptr + (y * (sbpr / 4)); - for (int x = sx; x < sw; ++x) - *(dptr+(offset++)) = (*(srow+x) & mask) ? 255 : 0; - } - QCFType provider = CGDataProviderCreateWithData(nullptr, dptr, nbytes, qt_mac_cgimage_data_free); - return CGImageMaskCreate(sw, sh, 8, 8, nbytes / sh, provider, nullptr, false); -} - -//conversion -inline static float qt_mac_convert_color_to_cg(int c) { return ((float)c * 1000 / 255) / 1000; } -CGAffineTransform qt_mac_convert_transform_to_cg(const QTransform &t) { - return CGAffineTransformMake(t.m11(), t.m12(), t.m21(), t.m22(), t.dx(), t.dy()); -} - -inline static QCFType cgColorForQColor(const QColor &col) -{ - CGFloat components[] = { - qt_mac_convert_color_to_cg(col.red()), - qt_mac_convert_color_to_cg(col.green()), - qt_mac_convert_color_to_cg(col.blue()), - qt_mac_convert_color_to_cg(col.alpha()) - }; - QCFType colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB); - return CGColorCreate(colorSpace, components); -} - -// There's architectural problems with using native gradients -// on the Mac at the moment, so disable them. -// #define QT_MAC_USE_NATIVE_GRADIENTS - -#ifdef QT_MAC_USE_NATIVE_GRADIENTS -static bool drawGradientNatively(const QGradient *gradient) -{ - return gradient->spread() == QGradient::PadSpread; -} - -// gradiant callback -static void qt_mac_color_gradient_function(void *info, const CGFloat *in, CGFloat *out) -{ - QBrush *brush = static_cast(info); - Q_ASSERT(brush && brush->gradient()); - - const QGradientStops stops = brush->gradient()->stops(); - const int n = stops.count(); - Q_ASSERT(n >= 1); - const QGradientStop *begin = stops.constBegin(); - const QGradientStop *end = begin + n; - - qreal p = in[0]; - const QGradientStop *i = begin; - while (i != end && i->first < p) - ++i; - - QRgb c; - if (i == begin) { - c = begin->second.rgba(); - } else if (i == end) { - c = (end - 1)->second.rgba(); - } else { - const QGradientStop &s1 = *(i - 1); - const QGradientStop &s2 = *i; - qreal p1 = s1.first; - qreal p2 = s2.first; - QRgb c1 = s1.second.rgba(); - QRgb c2 = s2.second.rgba(); - int idist = 256 * (p - p1) / (p2 - p1); - int dist = 256 - idist; - c = qRgba(INTERPOLATE_PIXEL_256(qRed(c1), dist, qRed(c2), idist), - INTERPOLATE_PIXEL_256(qGreen(c1), dist, qGreen(c2), idist), - INTERPOLATE_PIXEL_256(qBlue(c1), dist, qBlue(c2), idist), - INTERPOLATE_PIXEL_256(qAlpha(c1), dist, qAlpha(c2), idist)); - } - - out[0] = qt_mac_convert_color_to_cg(qRed(c)); - out[1] = qt_mac_convert_color_to_cg(qGreen(c)); - out[2] = qt_mac_convert_color_to_cg(qBlue(c)); - out[3] = qt_mac_convert_color_to_cg(qAlpha(c)); -} -#endif - -//clipping handling -void QCoreGraphicsPaintEnginePrivate::resetClip() -{ - static bool inReset = false; - if (inReset) - return; - inReset = true; - - CGAffineTransform old_xform = CGContextGetCTM(hd); - - //setup xforms - CGContextConcatCTM(hd, CGAffineTransformInvert(old_xform)); - while (stackCount > 0) { - restoreGraphicsState(); - } - saveGraphicsState(); - inReset = false; - //reset xforms - CGContextConcatCTM(hd, CGAffineTransformInvert(CGContextGetCTM(hd))); - CGContextConcatCTM(hd, old_xform); -} - -static CGRect qt_mac_compose_rect(const QRectF &r, float off=0) -{ - return CGRectMake(r.x()+off, r.y()+off, r.width(), r.height()); -} - -static CGMutablePathRef qt_mac_compose_path(const QPainterPath &p, float off=0) -{ - CGMutablePathRef ret = CGPathCreateMutable(); - QPointF startPt; - for (int i=0; i 0 - && p.elementAt(i - 1).x == startPt.x() - && p.elementAt(i - 1).y == startPt.y()) - CGPathCloseSubpath(ret); - startPt = QPointF(elm.x, elm.y); - CGPathMoveToPoint(ret, 0, elm.x+off, elm.y+off); - break; - case QPainterPath::LineToElement: - CGPathAddLineToPoint(ret, 0, elm.x+off, elm.y+off); - break; - case QPainterPath::CurveToElement: - Q_ASSERT(p.elementAt(i+1).type == QPainterPath::CurveToDataElement); - Q_ASSERT(p.elementAt(i+2).type == QPainterPath::CurveToDataElement); - CGPathAddCurveToPoint(ret, 0, - elm.x+off, elm.y+off, - p.elementAt(i+1).x+off, p.elementAt(i+1).y+off, - p.elementAt(i+2).x+off, p.elementAt(i+2).y+off); - i+=2; - break; - default: - qFatal("QCoreGraphicsPaintEngine::drawPath(), unhandled type: %d", elm.type); - break; - } - } - if (!p.isEmpty() - && p.elementAt(p.elementCount() - 1).x == startPt.x() - && p.elementAt(p.elementCount() - 1).y == startPt.y()) - CGPathCloseSubpath(ret); - return ret; -} - -//pattern handling (tiling) -#if 1 -# define QMACPATTERN_MASK_MULTIPLIER 32 -#else -# define QMACPATTERN_MASK_MULTIPLIER 1 -#endif -class QMacPattern -{ -public: - QMacPattern() : as_mask(false), pdev(0), image(0) { data.bytes = 0; } - ~QMacPattern() { CGImageRelease(image); } - int width() { - if (image) - return CGImageGetWidth(image); - if (data.bytes) - return 8*QMACPATTERN_MASK_MULTIPLIER; - return data.pixmap.width(); - } - int height() { - if (image) - return CGImageGetHeight(image); - if (data.bytes) - return 8*QMACPATTERN_MASK_MULTIPLIER; - return data.pixmap.height(); - } - - //input - QColor foreground; - bool as_mask; - struct { - QPixmap pixmap; - const uchar *bytes; - } data; - QPaintDevice *pdev; - //output - CGImageRef image; -}; -static void qt_mac_draw_pattern(void *info, CGContextRef c) -{ - QMacPattern *pat = (QMacPattern*)info; - int w = 0, h = 0; - bool isBitmap = (pat->data.pixmap.depth() == 1); - if (!pat->image) { //lazy cache - if (pat->as_mask) { - Q_ASSERT(pat->data.bytes); - w = h = 8; -#if (QMACPATTERN_MASK_MULTIPLIER == 1) - CGDataProviderRef provider = CGDataProviderCreateWithData(nullptr, pat->data.bytes, w*h, nullptr); - pat->image = CGImageMaskCreate(w, h, 1, 1, 1, provider, nullptr, false); - CGDataProviderRelease(provider); -#else - const int numBytes = (w*h)/sizeof(uchar); - uchar xor_bytes[numBytes]; - for (int i = 0; i < numBytes; ++i) - xor_bytes[i] = pat->data.bytes[i] ^ 0xFF; - CGDataProviderRef provider = CGDataProviderCreateWithData(nullptr, xor_bytes, w*h, nullptr); - CGImageRef swatch = CGImageMaskCreate(w, h, 1, 1, 1, provider, nullptr, false); - CGDataProviderRelease(provider); - - 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); - QMacCGContext pm_ctx(&pm); - CGContextSetFillColorWithColor(c, cgColorForQColor(c1)); - CGRect rect = CGRectMake(0, 0, w, h); - for (int x = 0; x < QMACPATTERN_MASK_MULTIPLIER; ++x) { - rect.origin.x = x * w; - for (int y = 0; y < QMACPATTERN_MASK_MULTIPLIER; ++y) { - rect.origin.y = y * h; - qt_mac_drawCGImage(pm_ctx, &rect, swatch); - } - } - pat->image = qt_mac_create_imagemask(pm, pm.rect()); - CGImageRelease(swatch); - w *= QMACPATTERN_MASK_MULTIPLIER; - h *= QMACPATTERN_MASK_MULTIPLIER; -#endif - } else { - w = pat->data.pixmap.width(); - h = pat->data.pixmap.height(); - if (isBitmap) - pat->image = qt_mac_create_imagemask(pat->data.pixmap, pat->data.pixmap.rect()); - else - pat->image = qt_mac_toCGImage(pat->data.pixmap.toImage()); - } - } else { - w = CGImageGetWidth(pat->image); - h = CGImageGetHeight(pat->image); - } - - //draw - bool needRestore = false; - if (CGImageIsMask(pat->image)) { - CGContextSaveGState(c); - CGContextSetFillColorWithColor(c, cgColorForQColor(pat->foreground)); - } - CGRect rect = CGRectMake(0, 0, w, h); - qt_mac_drawCGImage(c, &rect, pat->image); - if (needRestore) - CGContextRestoreGState(c); -} -static void qt_mac_dispose_pattern(void *info) -{ - QMacPattern *pat = (QMacPattern*)info; - delete pat; -} - -/***************************************************************************** - QCoreGraphicsPaintEngine member functions - *****************************************************************************/ - -inline static QPaintEngine::PaintEngineFeatures qt_mac_cg_features() -{ - return QPaintEngine::PaintEngineFeatures(QPaintEngine::AllFeatures & ~QPaintEngine::PaintOutsidePaintEvent - & ~QPaintEngine::PerspectiveTransform - & ~QPaintEngine::ConicalGradientFill - & ~QPaintEngine::LinearGradientFill - & ~QPaintEngine::RadialGradientFill - & ~QPaintEngine::BrushStroke); -} - -QCoreGraphicsPaintEngine::QCoreGraphicsPaintEngine() -: QPaintEngine(*(new QCoreGraphicsPaintEnginePrivate), qt_mac_cg_features()) -{ -} - -QCoreGraphicsPaintEngine::QCoreGraphicsPaintEngine(QPaintEnginePrivate &dptr) -: QPaintEngine(dptr, qt_mac_cg_features()) -{ -} - -QCoreGraphicsPaintEngine::~QCoreGraphicsPaintEngine() -{ -} - -bool -QCoreGraphicsPaintEngine::begin(QPaintDevice *pdev) -{ - Q_D(QCoreGraphicsPaintEngine); - if (isActive()) { // already active painting - qWarning("QCoreGraphicsPaintEngine::begin: Painter already active"); - return false; - } - - //initialization - d->pdev = pdev; - d->complexXForm = false; - d->cosmeticPen = QCoreGraphicsPaintEnginePrivate::CosmeticSetPenWidth; - d->cosmeticPenSize = 1; - d->current.clipEnabled = false; - d->pixelSize = QPoint(1,1); - - if (pdev->devType() != QInternal::Printer) { - QMacCGContext ctx(pdev); - d->hd = CGContextRetain(ctx); - if (d->hd) { - d->saveGraphicsState(); - d->orig_xform = CGContextGetCTM(d->hd); - if (d->shading) { - CGShadingRelease(d->shading); - d->shading = nullptr; - } - d->setClip(nullptr); //clear the context's clipping - } - } - - setActive(true); - - if (d->pdev->devType() == QInternal::Widget) { // device is a widget - QWidget *w = (QWidget*)d->pdev; - bool unclipped = w->testAttribute(Qt::WA_PaintUnclipped); - - if ((w->windowType() == Qt::Desktop)) { - if (!unclipped) - qWarning("QCoreGraphicsPaintEngine::begin: Does not support clipped desktop on OS X"); - // ## need to do [qt_mac_window_for(w) makeKeyAndOrderFront]; (need to rename the file) - } else if (unclipped) { - qWarning("QCoreGraphicsPaintEngine::begin: Does not support unclipped painting"); - } - } else if (d->pdev->devType() == QInternal::Pixmap) { // device is a pixmap - QPixmap *pm = (QPixmap*)d->pdev; - if (pm->isNull()) { - qWarning("QCoreGraphicsPaintEngine::begin: Cannot paint null pixmap"); - end(); - return false; - } - } - - setDirty(QPaintEngine::DirtyPen); - setDirty(QPaintEngine::DirtyBrush); - setDirty(QPaintEngine::DirtyBackground); - setDirty(QPaintEngine::DirtyHints); - return true; -} - -bool -QCoreGraphicsPaintEngine::end() -{ - Q_D(QCoreGraphicsPaintEngine); - setActive(false); - if (d->pdev->devType() == QInternal::Widget && static_cast(d->pdev)->windowType() == Qt::Desktop) { - // ### need to do [qt_mac_window_for(static_cast(d->pdev)) orderOut]; (need to rename) - } - if (d->shading) { - CGShadingRelease(d->shading); - d->shading = 0; - } - d->pdev = nullptr; - if (d->hd) { - d->restoreGraphicsState(); - CGContextSynchronize(d->hd); - CGContextRelease(d->hd); - d->hd = nullptr; - } - return true; -} - -void -QCoreGraphicsPaintEngine::updateState(const QPaintEngineState &state) -{ - Q_D(QCoreGraphicsPaintEngine); - QPaintEngine::DirtyFlags flags = state.state(); - - if (flags & DirtyTransform) - updateMatrix(state.transform()); - - if (flags & DirtyClipEnabled) { - if (state.isClipEnabled()) - updateClipPath(painter()->clipPath(), Qt::ReplaceClip); - else - updateClipPath(QPainterPath(), Qt::NoClip); - } - - if (flags & DirtyClipPath) { - updateClipPath(state.clipPath(), state.clipOperation()); - } else if (flags & DirtyClipRegion) { - updateClipRegion(state.clipRegion(), state.clipOperation()); - } - - // If the clip has changed we need to update all other states - // too, since they are included in the system context on OSX, - // and changing the clip resets that context back to scratch. - if (flags & (DirtyClipPath | DirtyClipRegion | DirtyClipEnabled)) - flags |= AllDirty; - - if (flags & DirtyPen) - updatePen(state.pen()); - if (flags & (DirtyBrush|DirtyBrushOrigin)) - updateBrush(state.brush(), state.brushOrigin()); - if (flags & DirtyFont) - updateFont(state.font()); - if (flags & DirtyOpacity) - updateOpacity(state.opacity()); - if (flags & DirtyHints) - updateRenderHints(state.renderHints()); - if (flags & DirtyCompositionMode) - updateCompositionMode(state.compositionMode()); - - if (flags & (DirtyPen | DirtyTransform | DirtyHints)) { - if (!qt_pen_is_cosmetic(d->current.pen, state.renderHints())) { - d->cosmeticPen = QCoreGraphicsPaintEnginePrivate::CosmeticNone; - } else if (d->current.transform.m11() < d->current.transform.m22()-1.0 || - d->current.transform.m11() > d->current.transform.m22()+1.0) { - d->cosmeticPen = QCoreGraphicsPaintEnginePrivate::CosmeticTransformPath; - d->cosmeticPenSize = d->adjustPenWidth(d->current.pen.widthF()); - if (!d->cosmeticPenSize) - d->cosmeticPenSize = 1.0; - } else { - d->cosmeticPen = QCoreGraphicsPaintEnginePrivate::CosmeticSetPenWidth; - static const float sqrt2 = std::sqrt(2.0f); - qreal width = d->current.pen.widthF(); - if (!width) - width = 1; - d->cosmeticPenSize = std::sqrt(std::pow(d->pixelSize.y(), 2) + std::pow(d->pixelSize.x(), 2)) / sqrt2 * width; - } - } -} - -void -QCoreGraphicsPaintEngine::updatePen(const QPen &pen) -{ - Q_D(QCoreGraphicsPaintEngine); - Q_ASSERT(isActive()); - d->current.pen = pen; - d->setStrokePen(pen); -} - -void -QCoreGraphicsPaintEngine::updateBrush(const QBrush &brush, const QPointF &brushOrigin) -{ - Q_D(QCoreGraphicsPaintEngine); - Q_ASSERT(isActive()); - d->current.brush = brush; - -#ifdef QT_MAC_USE_NATIVE_GRADIENTS - // Quartz supports only pad spread - if (const QGradient *gradient = brush.gradient()) { - if (drawGradientNatively(gradient)) { - gccaps |= QPaintEngine::LinearGradientFill | QPaintEngine::RadialGradientFill; - } else { - gccaps &= ~(QPaintEngine::LinearGradientFill | QPaintEngine::RadialGradientFill); - } - } -#endif - - if (d->shading) { - CGShadingRelease(d->shading); - d->shading = nullptr; - } - d->setFillBrush(brushOrigin); -} - -void -QCoreGraphicsPaintEngine::updateOpacity(qreal opacity) -{ - Q_D(QCoreGraphicsPaintEngine); - CGContextSetAlpha(d->hd, opacity); -} - -void -QCoreGraphicsPaintEngine::updateFont(const QFont &) -{ - Q_D(QCoreGraphicsPaintEngine); - Q_ASSERT(isActive()); - updatePen(d->current.pen); -} - -void -QCoreGraphicsPaintEngine::updateMatrix(const QTransform &transform) -{ - Q_D(QCoreGraphicsPaintEngine); - Q_ASSERT(isActive()); - - if (qt_is_nan(transform.m11()) || qt_is_nan(transform.m12()) || qt_is_nan(transform.m13()) - || qt_is_nan(transform.m21()) || qt_is_nan(transform.m22()) || qt_is_nan(transform.m23()) - || qt_is_nan(transform.m31()) || qt_is_nan(transform.m32()) || qt_is_nan(transform.m33())) - return; - - d->current.transform = transform; - d->setTransform(transform.isIdentity() ? 0 : &transform); - d->complexXForm = (transform.m11() != 1 || transform.m22() != 1 - || transform.m12() != 0 || transform.m21() != 0); - d->pixelSize = d->devicePixelSize(d->hd); -} - -void -QCoreGraphicsPaintEngine::updateClipPath(const QPainterPath &p, Qt::ClipOperation op) -{ - Q_D(QCoreGraphicsPaintEngine); - Q_ASSERT(isActive()); - if (op == Qt::NoClip) { - if (d->current.clipEnabled) { - d->current.clipEnabled = false; - d->current.clip = QRegion(); - d->setClip(nullptr); - } - } else { - if (!d->current.clipEnabled) - op = Qt::ReplaceClip; - d->current.clipEnabled = true; - QRegion clipRegion(p.toFillPolygon().toPolygon(), p.fillRule()); - if (op == Qt::ReplaceClip) { - d->current.clip = clipRegion; - d->setClip(nullptr); - if (p.isEmpty()) { - CGRect rect = CGRectMake(0, 0, 0, 0); - CGContextClipToRect(d->hd, rect); - } else { - CGMutablePathRef path = qt_mac_compose_path(p); - CGContextBeginPath(d->hd); - CGContextAddPath(d->hd, path); - if (p.fillRule() == Qt::WindingFill) - CGContextClip(d->hd); - else - CGContextEOClip(d->hd); - CGPathRelease(path); - } - } else if (op == Qt::IntersectClip) { - d->current.clip = d->current.clip.intersected(clipRegion); - d->setClip(&d->current.clip); - } - } -} - -void -QCoreGraphicsPaintEngine::updateClipRegion(const QRegion &clipRegion, Qt::ClipOperation op) -{ - Q_D(QCoreGraphicsPaintEngine); - Q_ASSERT(isActive()); - if (op == Qt::NoClip) { - d->current.clipEnabled = false; - d->current.clip = QRegion(); - d->setClip(nullptr); - } else { - if (!d->current.clipEnabled) - op = Qt::ReplaceClip; - d->current.clipEnabled = true; - if (op == Qt::IntersectClip) - d->current.clip = d->current.clip.intersected(clipRegion); - else if (op == Qt::ReplaceClip) - d->current.clip = clipRegion; - d->setClip(&d->current.clip); - } -} - -void -QCoreGraphicsPaintEngine::drawPath(const QPainterPath &p) -{ - Q_D(QCoreGraphicsPaintEngine); - Q_ASSERT(isActive()); - - if (state->compositionMode() == QPainter::CompositionMode_Destination) - return; - - CGMutablePathRef path = qt_mac_compose_path(p); - uchar ops = QCoreGraphicsPaintEnginePrivate::CGStroke; - if (p.fillRule() == Qt::WindingFill) - ops |= QCoreGraphicsPaintEnginePrivate::CGFill; - else - ops |= QCoreGraphicsPaintEnginePrivate::CGEOFill; - CGContextBeginPath(d->hd); - d->drawPath(ops, path); - CGPathRelease(path); -} - -void -QCoreGraphicsPaintEngine::drawRects(const QRectF *rects, int rectCount) -{ - Q_D(QCoreGraphicsPaintEngine); - Q_ASSERT(isActive()); - - if (state->compositionMode() == QPainter::CompositionMode_Destination) - return; - - for (int i=0; idrawPath(QCoreGraphicsPaintEnginePrivate::CGFill|QCoreGraphicsPaintEnginePrivate::CGStroke, - path); - CGPathRelease(path); - } -} - -void -QCoreGraphicsPaintEngine::drawPoints(const QPointF *points, int pointCount) -{ - Q_D(QCoreGraphicsPaintEngine); - Q_ASSERT(isActive()); - - if (state->compositionMode() == QPainter::CompositionMode_Destination) - return; - - if (d->current.pen.capStyle() == Qt::FlatCap) - CGContextSetLineCap(d->hd, kCGLineCapSquare); - - CGMutablePathRef path = CGPathCreateMutable(); - for (int i=0; i < pointCount; i++) { - float x = points[i].x(), y = points[i].y(); - CGPathMoveToPoint(path, nullptr, x, y); - CGPathAddLineToPoint(path, nullptr, x+0.001, y); - } - - bool doRestore = false; - if (d->cosmeticPen == QCoreGraphicsPaintEnginePrivate::CosmeticNone && !(state->renderHints() & QPainter::Antialiasing)) { - //we don't want adjusted pens for point rendering - doRestore = true; - d->saveGraphicsState(); - CGContextSetLineWidth(d->hd, d->current.pen.widthF()); - } - d->drawPath(QCoreGraphicsPaintEnginePrivate::CGStroke, path); - if (doRestore) - d->restoreGraphicsState(); - CGPathRelease(path); - if (d->current.pen.capStyle() == Qt::FlatCap) - CGContextSetLineCap(d->hd, kCGLineCapButt); -} - -void -QCoreGraphicsPaintEngine::drawEllipse(const QRectF &r) -{ - Q_D(QCoreGraphicsPaintEngine); - Q_ASSERT(isActive()); - - if (state->compositionMode() == QPainter::CompositionMode_Destination) - return; - - CGMutablePathRef path = CGPathCreateMutable(); - CGAffineTransform transform = CGAffineTransformMakeScale(r.width() / r.height(), 1); - CGPathAddArc(path, &transform,(r.x() + (r.width() / 2)) / (r.width() / r.height()), - r.y() + (r.height() / 2), r.height() / 2, 0, (2 * M_PI), false); - d->drawPath(QCoreGraphicsPaintEnginePrivate::CGFill | QCoreGraphicsPaintEnginePrivate::CGStroke, - path); - CGPathRelease(path); -} - -void -QCoreGraphicsPaintEngine::drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode) -{ - Q_D(QCoreGraphicsPaintEngine); - Q_ASSERT(isActive()); - - if (state->compositionMode() == QPainter::CompositionMode_Destination) - return; - - CGMutablePathRef path = CGPathCreateMutable(); - CGPathMoveToPoint(path, nullptr, points[0].x(), points[0].y()); - for (int x = 1; x < pointCount; ++x) - CGPathAddLineToPoint(path, nullptr, points[x].x(), points[x].y()); - if (mode != PolylineMode && points[0] != points[pointCount-1]) - CGPathAddLineToPoint(path, nullptr, points[0].x(), points[0].y()); - uint op = QCoreGraphicsPaintEnginePrivate::CGStroke; - if (mode != PolylineMode) - op |= mode == OddEvenMode ? QCoreGraphicsPaintEnginePrivate::CGEOFill - : QCoreGraphicsPaintEnginePrivate::CGFill; - d->drawPath(op, path); - CGPathRelease(path); -} - -void -QCoreGraphicsPaintEngine::drawLines(const QLineF *lines, int lineCount) -{ - Q_D(QCoreGraphicsPaintEngine); - Q_ASSERT(isActive()); - - if (state->compositionMode() == QPainter::CompositionMode_Destination) - return; - - CGMutablePathRef path = CGPathCreateMutable(); - for (int i = 0; i < lineCount; i++) { - const QPointF start = lines[i].p1(), end = lines[i].p2(); - CGPathMoveToPoint(path, nullptr, start.x(), start.y()); - CGPathAddLineToPoint(path, nullptr, end.x(), end.y()); - } - d->drawPath(QCoreGraphicsPaintEnginePrivate::CGStroke, path); - CGPathRelease(path); -} - -void QCoreGraphicsPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr) -{ - Q_D(QCoreGraphicsPaintEngine); - Q_ASSERT(isActive()); - - if (state->compositionMode() == QPainter::CompositionMode_Destination) - return; - - if (pm.isNull()) - return; - - bool differentSize = (QRectF(0, 0, pm.width(), pm.height()) != sr), doRestore = false; - CGRect rect = CGRectMake(r.x(), r.y(), r.width(), r.height()); - QCFType image; - bool isBitmap = (pm.depth() == 1); - if (isBitmap) { - doRestore = true; - d->saveGraphicsState(); - - const QColor &col = d->current.pen.color(); - CGContextSetFillColorWithColor(d->hd, cgColorForQColor(col)); - image = qt_mac_create_imagemask(pm, sr); - } else if (differentSize) { - QCFType img = qt_mac_toCGImage(pm.toImage()); - if (img) - image = CGImageCreateWithImageInRect(img, CGRectMake(qRound(sr.x()), qRound(sr.y()), qRound(sr.width()), qRound(sr.height()))); - } else { - image = qt_mac_toCGImage(pm.toImage()); - } - qt_mac_drawCGImage(d->hd, &rect, image); - if (doRestore) - d->restoreGraphicsState(); -} - -void QCoreGraphicsPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRectF &sr, - Qt::ImageConversionFlags flags) -{ - Q_D(QCoreGraphicsPaintEngine); - Q_UNUSED(flags); - Q_ASSERT(isActive()); - - if (img.isNull() || state->compositionMode() == QPainter::CompositionMode_Destination) - return; - - QCFType cgimage = qt_mac_toCGImage(img); - CGRect rect = CGRectMake(r.x(), r.y(), r.width(), r.height()); - if (QRectF(0, 0, img.width(), img.height()) != sr) - cgimage = CGImageCreateWithImageInRect(cgimage, CGRectMake(sr.x(), sr.y(), - sr.width(), sr.height())); - qt_mac_drawCGImage(d->hd, &rect, cgimage); -} - -void QCoreGraphicsPaintEngine::initialize() -{ -} - -void QCoreGraphicsPaintEngine::cleanup() -{ -} - -CGContextRef -QCoreGraphicsPaintEngine::handle() const -{ - return d_func()->hd; -} - -void -QCoreGraphicsPaintEngine::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, - const QPointF &p) -{ - Q_D(QCoreGraphicsPaintEngine); - Q_ASSERT(isActive()); - - if (state->compositionMode() == QPainter::CompositionMode_Destination) - return; - - //save the old state - d->saveGraphicsState(); - - //setup the pattern - QMacPattern *qpattern = new QMacPattern; - qpattern->data.pixmap = pixmap; - qpattern->foreground = d->current.pen.color(); - qpattern->pdev = d->pdev; - CGPatternCallbacks callbks; - callbks.version = 0; - callbks.drawPattern = qt_mac_draw_pattern; - callbks.releaseInfo = qt_mac_dispose_pattern; - const int width = qpattern->width(), height = qpattern->height(); - CGAffineTransform trans = CGContextGetCTM(d->hd); - CGPatternRef pat = CGPatternCreate(qpattern, CGRectMake(0, 0, width, height), - trans, width, height, - kCGPatternTilingNoDistortion, true, &callbks); - CGColorSpaceRef cs = CGColorSpaceCreatePattern(nullptr); - CGContextSetFillColorSpace(d->hd, cs); - CGFloat component = 1.0; //just one - CGContextSetFillPattern(d->hd, pat, &component); - CGSize phase = CGSizeApplyAffineTransform(CGSizeMake(-(p.x()-r.x()), -(p.y()-r.y())), trans); - CGContextSetPatternPhase(d->hd, phase); - - //fill the rectangle - CGRect mac_rect = CGRectMake(r.x(), r.y(), r.width(), r.height()); - CGContextFillRect(d->hd, mac_rect); - - //restore the state - d->restoreGraphicsState(); - //cleanup - CGColorSpaceRelease(cs); - CGPatternRelease(pat); -} - -void QCoreGraphicsPaintEngine::drawTextItem(const QPointF &pos, const QTextItem &item) -{ - Q_D(QCoreGraphicsPaintEngine); - if (d->current.transform.type() == QTransform::TxProject -#ifndef QMAC_NATIVE_GRADIENTS - || painter()->pen().brush().gradient() //Just let the base engine "emulate" the gradient -#endif - ) { - QPaintEngine::drawTextItem(pos, item); - return; - } - - if (state->compositionMode() == QPainter::CompositionMode_Destination) - return; - - const QTextItemInt &ti = static_cast(item); - - QPen oldPen = painter()->pen(); - QBrush oldBrush = painter()->brush(); - QPointF oldBrushOrigin = painter()->brushOrigin(); - updatePen(Qt::NoPen); - updateBrush(oldPen.brush(), QPointF(0, 0)); - - Q_ASSERT(type() == QPaintEngine::CoreGraphics); - - QFontEngine *fe = ti.fontEngine; - - const bool textAA = ((state->renderHints() & QPainter::TextAntialiasing) - && !(fe->fontDef.styleStrategy & QFont::NoAntialias)); - const bool lineAA = state->renderHints() & QPainter::Antialiasing; - if (textAA != lineAA) - CGContextSetShouldAntialias(d->hd, textAA); - - const bool smoothing = textAA && !(fe->fontDef.styleStrategy & QFont::NoSubpixelAntialias); - if (d->disabledSmoothFonts == smoothing) - CGContextSetShouldSmoothFonts(d->hd, smoothing); - - if (ti.glyphs.numGlyphs) { - switch (fe->type()) { - case QFontEngine::Mac: - static_cast(fe)->draw(d->hd, pos.x(), pos.y(), ti, paintDevice()->height()); - break; - case QFontEngine::Box: - d->drawBoxTextItem(pos, ti); - break; - default: - break; - } - } - - if (textAA != lineAA) - CGContextSetShouldAntialias(d->hd, !textAA); - - if (smoothing == d->disabledSmoothFonts) - CGContextSetShouldSmoothFonts(d->hd, !d->disabledSmoothFonts); - - updatePen(oldPen); - updateBrush(oldBrush, oldBrushOrigin); -} - -QPainter::RenderHints -QCoreGraphicsPaintEngine::supportedRenderHints() const -{ - return QPainter::RenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform); -} -enum CGCompositeMode { - kCGCompositeModeClear = 0, - kCGCompositeModeCopy = 1, - kCGCompositeModeSourceOver = 2, - kCGCompositeModeSourceIn = 3, - kCGCompositeModeSourceOut = 4, - kCGCompositeModeSourceAtop = 5, - kCGCompositeModeDestinationOver = 6, - kCGCompositeModeDestinationIn = 7, - kCGCompositeModeDestinationOut = 8, - kCGCompositeModeDestinationAtop = 9, - kCGCompositeModeXOR = 10, - kCGCompositeModePlusDarker = 11, // (max (0, (1-d) + (1-s))) - kCGCompositeModePlusLighter = 12, // (min (1, s + d)) - }; -extern "C" { - extern void CGContextSetCompositeOperation(CGContextRef, int); -} // private function, but is in all versions of OS X. -void -QCoreGraphicsPaintEngine::updateCompositionMode(QPainter::CompositionMode mode) -{ - int cg_mode = kCGBlendModeNormal; - switch (mode) { - case QPainter::CompositionMode_Multiply: - cg_mode = kCGBlendModeMultiply; - break; - case QPainter::CompositionMode_Screen: - cg_mode = kCGBlendModeScreen; - break; - case QPainter::CompositionMode_Overlay: - cg_mode = kCGBlendModeOverlay; - break; - case QPainter::CompositionMode_Darken: - cg_mode = kCGBlendModeDarken; - break; - case QPainter::CompositionMode_Lighten: - cg_mode = kCGBlendModeLighten; - break; - case QPainter::CompositionMode_ColorDodge: - cg_mode = kCGBlendModeColorDodge; - break; - case QPainter::CompositionMode_ColorBurn: - cg_mode = kCGBlendModeColorBurn; - break; - case QPainter::CompositionMode_HardLight: - cg_mode = kCGBlendModeHardLight; - break; - case QPainter::CompositionMode_SoftLight: - cg_mode = kCGBlendModeSoftLight; - break; - case QPainter::CompositionMode_Difference: - cg_mode = kCGBlendModeDifference; - break; - case QPainter::CompositionMode_Exclusion: - cg_mode = kCGBlendModeExclusion; - break; - case QPainter::CompositionMode_Plus: - cg_mode = kCGBlendModePlusLighter; - break; - case QPainter::CompositionMode_SourceOver: - cg_mode = kCGBlendModeNormal; - break; - case QPainter::CompositionMode_DestinationOver: - cg_mode = kCGBlendModeDestinationOver; - break; - case QPainter::CompositionMode_Clear: - cg_mode = kCGBlendModeClear; - break; - case QPainter::CompositionMode_Source: - cg_mode = kCGBlendModeCopy; - break; - case QPainter::CompositionMode_Destination: - cg_mode = -1; - break; - case QPainter::CompositionMode_SourceIn: - cg_mode = kCGBlendModeSourceIn; - break; - case QPainter::CompositionMode_DestinationIn: - cg_mode = kCGCompositeModeDestinationIn; - break; - case QPainter::CompositionMode_SourceOut: - cg_mode = kCGBlendModeSourceOut; - break; - case QPainter::CompositionMode_DestinationOut: - cg_mode = kCGBlendModeDestinationOver; - break; - case QPainter::CompositionMode_SourceAtop: - cg_mode = kCGBlendModeSourceAtop; - break; - case QPainter::CompositionMode_DestinationAtop: - cg_mode = kCGBlendModeDestinationAtop; - break; - case QPainter::CompositionMode_Xor: - cg_mode = kCGBlendModeXOR; - break; - default: - break; - } - if (cg_mode > -1) { - CGContextSetBlendMode(d_func()->hd, CGBlendMode(cg_mode)); - } -} - -void -QCoreGraphicsPaintEngine::updateRenderHints(QPainter::RenderHints hints) -{ - Q_D(QCoreGraphicsPaintEngine); - CGContextSetShouldAntialias(d->hd, hints & QPainter::Antialiasing); - CGContextSetInterpolationQuality(d->hd, (hints & QPainter::SmoothPixmapTransform) ? - kCGInterpolationHigh : kCGInterpolationNone); - bool textAntialiasing = (hints & QPainter::TextAntialiasing) == QPainter::TextAntialiasing; - if (!textAntialiasing || d->disabledSmoothFonts) { - d->disabledSmoothFonts = !textAntialiasing; - CGContextSetShouldSmoothFonts(d->hd, textAntialiasing); - } -} - -/* - Returns the size of one device pixel in user-space coordinates. -*/ -QPointF QCoreGraphicsPaintEnginePrivate::devicePixelSize(CGContextRef) -{ - QPointF p1 = current.transform.inverted().map(QPointF(0, 0)); - QPointF p2 = current.transform.inverted().map(QPointF(1, 1)); - return QPointF(qAbs(p2.x() - p1.x()), qAbs(p2.y() - p1.y())); -} - -/* - Adjusts the pen width so we get correct line widths in the - non-transformed, aliased case. -*/ -float QCoreGraphicsPaintEnginePrivate::adjustPenWidth(float penWidth) -{ - Q_Q(QCoreGraphicsPaintEngine); - float ret = penWidth; - if (!complexXForm && !(q->state->renderHints() & QPainter::Antialiasing)) { - if (penWidth < 2) - ret = 1; - else if (penWidth < 3) - ret = 1.5; - else - ret = penWidth -1; - } - return ret; -} - -void -QCoreGraphicsPaintEnginePrivate::setStrokePen(const QPen &pen) -{ - //pencap - CGLineCap cglinecap = kCGLineCapButt; - if (pen.capStyle() == Qt::SquareCap) - cglinecap = kCGLineCapSquare; - else if (pen.capStyle() == Qt::RoundCap) - cglinecap = kCGLineCapRound; - CGContextSetLineCap(hd, cglinecap); - CGContextSetLineWidth(hd, adjustPenWidth(pen.widthF())); - - //join - CGLineJoin cglinejoin = kCGLineJoinMiter; - if (pen.joinStyle() == Qt::BevelJoin) - cglinejoin = kCGLineJoinBevel; - else if (pen.joinStyle() == Qt::RoundJoin) - cglinejoin = kCGLineJoinRound; - CGContextSetLineJoin(hd, cglinejoin); -// CGContextSetMiterLimit(hd, pen.miterLimit()); - - //pen style - QVector linedashes; - if (pen.style() == Qt::CustomDashLine) { - QVector customs = pen.dashPattern(); - for (int i = 0; i < customs.size(); ++i) - linedashes.append(customs.at(i)); - } else if (pen.style() == Qt::DashLine) { - linedashes.append(4); - linedashes.append(2); - } else if (pen.style() == Qt::DotLine) { - linedashes.append(1); - linedashes.append(2); - } else if (pen.style() == Qt::DashDotLine) { - linedashes.append(4); - linedashes.append(2); - linedashes.append(1); - linedashes.append(2); - } else if (pen.style() == Qt::DashDotDotLine) { - linedashes.append(4); - linedashes.append(2); - linedashes.append(1); - linedashes.append(2); - linedashes.append(1); - linedashes.append(2); - } - const CGFloat cglinewidth = pen.widthF() <= 0.0f ? 1.0f : float(pen.widthF()); - for (int i = 0; i < linedashes.size(); ++i) { - linedashes[i] *= cglinewidth; - if (cglinewidth < 3 && (cglinecap == kCGLineCapSquare || cglinecap == kCGLineCapRound)) { - if ((i%2)) - linedashes[i] += cglinewidth/2; - else - linedashes[i] -= cglinewidth/2; - } - } - CGContextSetLineDash(hd, pen.dashOffset() * cglinewidth, linedashes.data(), linedashes.size()); - - // color - CGContextSetStrokeColorWithColor(hd, cgColorForQColor(pen.color())); -} - -// Add our own patterns here to deal with the fact that the coordinate system -// is flipped vertically with Quartz2D. -static const uchar *qt_mac_patternForBrush(int brushStyle) -{ - Q_ASSERT(brushStyle > Qt::SolidPattern && brushStyle < Qt::LinearGradientPattern); - static const uchar dense1_pat[] = { 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x44, 0x00 }; - static const uchar dense2_pat[] = { 0x00, 0x22, 0x00, 0x88, 0x00, 0x22, 0x00, 0x88 }; - static const uchar dense3_pat[] = { 0x11, 0xaa, 0x44, 0xaa, 0x11, 0xaa, 0x44, 0xaa }; - static const uchar dense4_pat[] = { 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55 }; - static const uchar dense5_pat[] = { 0xee, 0x55, 0xbb, 0x55, 0xee, 0x55, 0xbb, 0x55 }; - static const uchar dense6_pat[] = { 0xff, 0xdd, 0xff, 0x77, 0xff, 0xdd, 0xff, 0x77 }; - static const uchar dense7_pat[] = { 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff, 0xbb, 0xff }; - static const uchar hor_pat[] = { 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff }; - static const uchar ver_pat[] = { 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef }; - static const uchar cross_pat[] = { 0xef, 0xef, 0xef, 0xef, 0x00, 0xef, 0xef, 0xef }; - static const uchar fdiag_pat[] = { 0x7f, 0xbf, 0xdf, 0xef, 0xf7, 0xfb, 0xfd, 0xfe }; - static const uchar bdiag_pat[] = { 0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f }; - static const uchar dcross_pat[] = { 0x7e, 0xbd, 0xdb, 0xe7, 0xe7, 0xdb, 0xbd, 0x7e }; - static const uchar *const pat_tbl[] = { - dense1_pat, dense2_pat, dense3_pat, dense4_pat, dense5_pat, - dense6_pat, dense7_pat, - hor_pat, ver_pat, cross_pat, bdiag_pat, fdiag_pat, dcross_pat }; - return pat_tbl[brushStyle - Qt::Dense1Pattern]; -} - -void QCoreGraphicsPaintEnginePrivate::setFillBrush(const QPointF &offset) -{ - // pattern - Qt::BrushStyle bs = current.brush.style(); -#ifdef QT_MAC_USE_NATIVE_GRADIENTS - if (bs == Qt::LinearGradientPattern || bs == Qt::RadialGradientPattern) { - const QGradient *grad = static_cast(current.brush.gradient()); - if (drawGradientNatively(grad)) { - Q_ASSERT(grad->spread() == QGradient::PadSpread); - - static const CGFloat domain[] = { 0.0f, +1.0f }; - static const CGFunctionCallbacks callbacks = { 0, qt_mac_color_gradient_function, nullptr }; - CGFunctionRef fill_func = CGFunctionCreate(reinterpret_cast(¤t.brush), - 1, domain, 4, nullptr, &callbacks); - - CGColorSpaceRef colorspace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB) - if (bs == Qt::LinearGradientPattern) { - const QLinearGradient *linearGrad = static_cast(grad); - const QPointF start(linearGrad->start()); - const QPointF stop(linearGrad->finalStop()); - shading = CGShadingCreateAxial(colorspace, CGPointMake(start.x(), start.y()), - CGPointMake(stop.x(), stop.y()), fill_func, true, true); - } else { - Q_ASSERT(bs == Qt::RadialGradientPattern); - const QRadialGradient *radialGrad = static_cast(grad); - QPointF center(radialGrad->center()); - QPointF focal(radialGrad->focalPoint()); - qreal radius = radialGrad->radius(); - qreal focalRadius = radialGrad->focalRadius(); - shading = CGShadingCreateRadial(colorspace, CGPointMake(focal.x(), focal.y()), - focalRadius, CGPointMake(center.x(), center.y()), radius, fill_func, false, true); - } - - CGFunctionRelease(fill_func); - } - } else -#endif - if (bs != Qt::SolidPattern && bs != Qt::NoBrush -#ifndef QT_MAC_USE_NATIVE_GRADIENTS - && (bs < Qt::LinearGradientPattern || bs > Qt::ConicalGradientPattern) -#endif - ) - { - QMacPattern *qpattern = new QMacPattern; - qpattern->pdev = pdev; - CGFloat components[4] = { 1.0, 1.0, 1.0, 1.0 }; - CGColorSpaceRef base_colorspace = nullptr; - if (bs == Qt::TexturePattern) { - qpattern->data.pixmap = current.brush.texture(); - if (qpattern->data.pixmap.isQBitmap()) { - const QColor &col = current.brush.color(); - components[0] = qt_mac_convert_color_to_cg(col.red()); - components[1] = qt_mac_convert_color_to_cg(col.green()); - components[2] = qt_mac_convert_color_to_cg(col.blue()); - base_colorspace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB); - } - } else { - qpattern->as_mask = true; - - qpattern->data.bytes = qt_mac_patternForBrush(bs); - const QColor &col = current.brush.color(); - components[0] = qt_mac_convert_color_to_cg(col.red()); - components[1] = qt_mac_convert_color_to_cg(col.green()); - components[2] = qt_mac_convert_color_to_cg(col.blue()); - base_colorspace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB); - } - int width = qpattern->width(), height = qpattern->height(); - qpattern->foreground = current.brush.color(); - - CGColorSpaceRef fill_colorspace = CGColorSpaceCreatePattern(base_colorspace); - CGContextSetFillColorSpace(hd, fill_colorspace); - - CGAffineTransform xform = CGContextGetCTM(hd); - xform = CGAffineTransformConcat(qt_mac_convert_transform_to_cg(current.brush.transform()), xform); - xform = CGAffineTransformTranslate(xform, offset.x(), offset.y()); - - CGPatternCallbacks callbks; - callbks.version = 0; - callbks.drawPattern = qt_mac_draw_pattern; - callbks.releaseInfo = qt_mac_dispose_pattern; - CGPatternRef fill_pattern = CGPatternCreate(qpattern, CGRectMake(0, 0, width, height), - xform, width, height, kCGPatternTilingNoDistortion, - !base_colorspace, &callbks); - CGContextSetFillPattern(hd, fill_pattern, components); - - - CGPatternRelease(fill_pattern); - CGColorSpaceRelease(base_colorspace); - CGColorSpaceRelease(fill_colorspace); - } else if (bs != Qt::NoBrush) { - CGContextSetFillColorWithColor(hd, cgColorForQColor(current.brush.color())); - } -} - -void -QCoreGraphicsPaintEnginePrivate::setClip(const QRegion *rgn) -{ - Q_Q(QCoreGraphicsPaintEngine); - if (hd) { - resetClip(); - QRegion sysClip = q->systemClip(); - if (!sysClip.isEmpty()) - qt_mac_clip_cg(hd, sysClip, &orig_xform); - if (rgn) - qt_mac_clip_cg(hd, *rgn, nullptr); - } -} - -struct qt_mac_cg_transform_path { - CGMutablePathRef path; - CGAffineTransform transform; -}; - -void qt_mac_cg_transform_path_apply(void *info, const CGPathElement *element) -{ - Q_ASSERT(info && element); - qt_mac_cg_transform_path *t = (qt_mac_cg_transform_path*)info; - switch (element->type) { - case kCGPathElementMoveToPoint: - CGPathMoveToPoint(t->path, &t->transform, element->points[0].x, element->points[0].y); - break; - case kCGPathElementAddLineToPoint: - CGPathAddLineToPoint(t->path, &t->transform, element->points[0].x, element->points[0].y); - break; - case kCGPathElementAddQuadCurveToPoint: - CGPathAddQuadCurveToPoint(t->path, &t->transform, element->points[0].x, element->points[0].y, - element->points[1].x, element->points[1].y); - break; - case kCGPathElementAddCurveToPoint: - CGPathAddCurveToPoint(t->path, &t->transform, element->points[0].x, element->points[0].y, - element->points[1].x, element->points[1].y, - element->points[2].x, element->points[2].y); - break; - case kCGPathElementCloseSubpath: - CGPathCloseSubpath(t->path); - break; - default: - qDebug() << "Unhandled path transform type: " << element->type; - } -} - -void QCoreGraphicsPaintEnginePrivate::drawPath(uchar ops, CGMutablePathRef path) -{ - Q_Q(QCoreGraphicsPaintEngine); - Q_ASSERT((ops & (CGFill | CGEOFill)) != (CGFill | CGEOFill)); //can't really happen - if ((ops & (CGFill | CGEOFill))) { - if (shading) { - Q_ASSERT(path); - CGContextBeginPath(hd); - CGContextAddPath(hd, path); - saveGraphicsState(); - if (ops & CGFill) - CGContextClip(hd); - else if (ops & CGEOFill) - CGContextEOClip(hd); - if (current.brush.gradient()->coordinateMode() == QGradient::ObjectBoundingMode) { - CGRect boundingBox = CGPathGetBoundingBox(path); - CGContextConcatCTM(hd, - CGAffineTransformMake(boundingBox.size.width, 0, - 0, boundingBox.size.height, - boundingBox.origin.x, boundingBox.origin.y)); - } - CGContextDrawShading(hd, shading); - restoreGraphicsState(); - ops &= ~CGFill; - ops &= ~CGEOFill; - } else if (current.brush.style() == Qt::NoBrush) { - ops &= ~CGFill; - ops &= ~CGEOFill; - } - } - if ((ops & CGStroke) && current.pen.style() == Qt::NoPen) - ops &= ~CGStroke; - - if (ops & (CGEOFill | CGFill)) { - CGContextBeginPath(hd); - CGContextAddPath(hd, path); - if (ops & CGEOFill) { - CGContextEOFillPath(hd); - } else { - CGContextFillPath(hd); - } - } - - // Avoid saving and restoring the context if we can. - const bool needContextSave = (cosmeticPen != QCoreGraphicsPaintEnginePrivate::CosmeticNone || - !(q->state->renderHints() & QPainter::Antialiasing)); - if (ops & CGStroke) { - if (needContextSave) - saveGraphicsState(); - CGContextBeginPath(hd); - - // Translate a fraction of a pixel size in the y direction - // to make sure that primitives painted at pixel borders - // fills the right pixel. This is needed since the y xais - // in the Quartz coordinate system is inverted compared to Qt. - if (!(q->state->renderHints() & QPainter::Antialiasing)) { - if (current.pen.style() == Qt::SolidLine || current.pen.width() >= 3) - CGContextTranslateCTM(hd, double(pixelSize.x()) * 0.25, double(pixelSize.y()) * 0.25); - else - CGContextTranslateCTM(hd, 0, double(pixelSize.y()) * 0.1); - } - - if (cosmeticPen != QCoreGraphicsPaintEnginePrivate::CosmeticNone) { - // If antialiazing is enabled, use the cosmetic pen size directly. - if (q->state->renderHints() & QPainter::Antialiasing) - CGContextSetLineWidth(hd, cosmeticPenSize); - else if (current.pen.widthF() <= 1) - CGContextSetLineWidth(hd, cosmeticPenSize * 0.9f); - else - CGContextSetLineWidth(hd, cosmeticPenSize); - } - if (cosmeticPen == QCoreGraphicsPaintEnginePrivate::CosmeticTransformPath) { - qt_mac_cg_transform_path t; - t.transform = qt_mac_convert_transform_to_cg(current.transform); - t.path = CGPathCreateMutable(); - CGPathApply(path, &t, qt_mac_cg_transform_path_apply); //transform the path - setTransform(nullptr); //unset the context transform - CGContextSetLineWidth(hd, cosmeticPenSize); - CGContextAddPath(hd, t.path); - CGPathRelease(t.path); - } else { - CGContextAddPath(hd, path); - } - - CGContextStrokePath(hd); - if (needContextSave) - restoreGraphicsState(); - } -} - -QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qpaintengine_mac_p.h b/src/plugins/platforms/cocoa/qpaintengine_mac_p.h deleted file mode 100644 index a52e9cbe1c..0000000000 --- a/src/plugins/platforms/cocoa/qpaintengine_mac_p.h +++ /dev/null @@ -1,205 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the plugins 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$ -** -****************************************************************************/ - -#ifndef QPAINTENGINE_MAC_P_H -#define QPAINTENGINE_MAC_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include -#include -#include -#include -#include - -typedef struct CGColorSpace *CGColorSpaceRef; -typedef struct CGContext *CGContextRef; - -QT_BEGIN_NAMESPACE - -class QCoreGraphicsPaintEnginePrivate; -class QCoreGraphicsPaintEngine : public QPaintEngine -{ - Q_DECLARE_PRIVATE(QCoreGraphicsPaintEngine) - -public: - QCoreGraphicsPaintEngine(); - ~QCoreGraphicsPaintEngine(); - - bool begin(QPaintDevice *pdev); - bool end(); - - void updateState(const QPaintEngineState &state); - - void updatePen(const QPen &pen); - void updateBrush(const QBrush &brush, const QPointF &pt); - void updateFont(const QFont &font); - void updateOpacity(qreal opacity); - void updateMatrix(const QTransform &matrix); - void updateTransform(const QTransform &matrix); - void updateClipRegion(const QRegion ®ion, Qt::ClipOperation op); - void updateClipPath(const QPainterPath &path, Qt::ClipOperation op); - void updateCompositionMode(QPainter::CompositionMode mode); - void updateRenderHints(QPainter::RenderHints hints); - - void drawLines(const QLineF *lines, int lineCount); - void drawRects(const QRectF *rects, int rectCount); - void drawPoints(const QPointF *p, int pointCount); - void drawEllipse(const QRectF &r); - void drawPath(const QPainterPath &path); - - void drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode); - void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr); - void drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &s); - - void drawTextItem(const QPointF &pos, const QTextItem &item); - void drawImage(const QRectF &r, const QImage &pm, const QRectF &sr, - Qt::ImageConversionFlags flags = Qt::AutoColor); - - Type type() const { return QPaintEngine::CoreGraphics; } - - CGContextRef handle() const; - - static void initialize(); - static void cleanup(); - - QPainter::RenderHints supportedRenderHints() const; - - //avoid partial shadowed overload warnings... - void drawLines(const QLine *lines, int lineCount) { QPaintEngine::drawLines(lines, lineCount); } - void drawRects(const QRect *rects, int rectCount) { QPaintEngine::drawRects(rects, rectCount); } - void drawPoints(const QPoint *p, int pointCount) { QPaintEngine::drawPoints(p, pointCount); } - void drawEllipse(const QRect &r) { QPaintEngine::drawEllipse(r); } - void drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode) - { QPaintEngine::drawPolygon(points, pointCount, mode); } - -protected: - friend class QMacPrintEngine; - friend class QMacPrintEnginePrivate; - QCoreGraphicsPaintEngine(QPaintEnginePrivate &dptr); - -private: - Q_DISABLE_COPY(QCoreGraphicsPaintEngine) -}; - -/***************************************************************************** - Private data - *****************************************************************************/ -class QCoreGraphicsPaintEnginePrivate : public QPaintEnginePrivate -{ - Q_DECLARE_PUBLIC(QCoreGraphicsPaintEngine) -public: - QCoreGraphicsPaintEnginePrivate() - : hd(nullptr), shading(nullptr), stackCount(0), complexXForm(false), disabledSmoothFonts(false) - { - } - - struct { - QPen pen; - QBrush brush; - uint clipEnabled : 1; - QRegion clip; - QTransform transform; - } current; - - //state info (shared with QD) - CGAffineTransform orig_xform; - - //cg structures - CGContextRef hd; - CGShadingRef shading; - int stackCount; - bool complexXForm; - bool disabledSmoothFonts; - enum { CosmeticNone, CosmeticTransformPath, CosmeticSetPenWidth } cosmeticPen; - - // pixel and cosmetic pen size in user coordinates. - QPointF pixelSize; - float cosmeticPenSize; - - //internal functions - enum { CGStroke=0x01, CGEOFill=0x02, CGFill=0x04 }; - void drawPath(uchar ops, CGMutablePathRef path = nullptr); - void setClip(const QRegion *rgn = nullptr); - void resetClip(); - void setFillBrush(const QPointF &origin=QPoint()); - void setStrokePen(const QPen &pen); - inline void saveGraphicsState(); - inline void restoreGraphicsState(); - float penOffset(); - QPointF devicePixelSize(CGContextRef context); - float adjustPenWidth(float penWidth); - inline void setTransform(const QTransform *matrix = nullptr) - { - CGContextConcatCTM(hd, CGAffineTransformInvert(CGContextGetCTM(hd))); - CGAffineTransform xform = orig_xform; - if (matrix) { - extern CGAffineTransform qt_mac_convert_transform_to_cg(const QTransform &); - xform = CGAffineTransformConcat(qt_mac_convert_transform_to_cg(*matrix), xform); - } - CGContextConcatCTM(hd, xform); - CGContextSetTextMatrix(hd, xform); - } -}; - -inline void QCoreGraphicsPaintEnginePrivate::saveGraphicsState() -{ - ++stackCount; - CGContextSaveGState(hd); -} - -inline void QCoreGraphicsPaintEnginePrivate::restoreGraphicsState() -{ - --stackCount; - Q_ASSERT(stackCount >= 0); - CGContextRestoreGState(hd); -} - -QT_END_NAMESPACE - -#endif // QPAINTENGINE_MAC_P_H diff --git a/src/plugins/platforms/cocoa/qprintengine_mac.mm b/src/plugins/platforms/cocoa/qprintengine_mac.mm deleted file mode 100644 index 9391f921ec..0000000000 --- a/src/plugins/platforms/cocoa/qprintengine_mac.mm +++ /dev/null @@ -1,797 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the plugins 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$ -** -****************************************************************************/ - -#include -#include - -#include "qprintengine_mac_p.h" -#include "qcocoaprintersupport.h" -#include -#include -#include -#include - -#include - -#ifndef QT_NO_PRINTER - -QT_BEGIN_NAMESPACE - -extern QMarginsF qt_convertMargins(const QMarginsF &margins, QPageLayout::Unit fromUnits, QPageLayout::Unit toUnits); - -QMacPrintEngine::QMacPrintEngine(QPrinter::PrinterMode mode, const QString &deviceId) - : QPaintEngine(*(new QMacPrintEnginePrivate)) -{ - Q_D(QMacPrintEngine); - d->mode = mode; - QString id = deviceId; - if (id.isEmpty()) - id = QCocoaPrinterSupport().defaultPrintDeviceId(); - else - setProperty(QPrintEngine::PPK_PrinterName, deviceId); - d->m_printDevice.reset(new QCocoaPrintDevice(id)); - d->m_pageLayout.setPageSize(d->m_printDevice->defaultPageSize()); - d->initialize(); -} - -bool QMacPrintEngine::begin(QPaintDevice *dev) -{ - Q_D(QMacPrintEngine); - - Q_ASSERT(dev && dev->devType() == QInternal::Printer); - if (!static_cast(dev)->isValid()) - return false; - - if (d->state == QPrinter::Idle && !d->isPrintSessionInitialized()) // Need to reinitialize - d->initialize(); - - d->paintEngine->state = state; - d->paintEngine->begin(dev); - Q_ASSERT_X(d->state == QPrinter::Idle, "QMacPrintEngine", "printer already active"); - - if (PMSessionValidatePrintSettings(d->session(), d->settings(), kPMDontWantBoolean) != noErr - || PMSessionValidatePageFormat(d->session(), d->format(), kPMDontWantBoolean) != noErr) { - d->state = QPrinter::Error; - return false; - } - - if (!d->outputFilename.isEmpty()) { - QCFType outFile = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, - QCFString(d->outputFilename), - kCFURLPOSIXPathStyle, - false); - if (PMSessionSetDestination(d->session(), d->settings(), kPMDestinationFile, - kPMDocumentFormatPDF, outFile) != noErr) { - qWarning("QMacPrintEngine::begin: Problem setting file [%s]", d->outputFilename.toUtf8().constData()); - return false; - } - } - - OSStatus status = PMSessionBeginCGDocumentNoDialog(d->session(), d->settings(), d->format()); - if (status != noErr) { - d->state = QPrinter::Error; - return false; - } - - d->state = QPrinter::Active; - setActive(true); - d->newPage_helper(); - return true; -} - -bool QMacPrintEngine::end() -{ - Q_D(QMacPrintEngine); - if (d->state == QPrinter::Aborted) - return true; // I was just here a function call ago :) - if (d->paintEngine->type() == QPaintEngine::CoreGraphics) { - // We don't need the paint engine to call restoreGraphicsState() - static_cast(d->paintEngine)->d_func()->stackCount = 0; - static_cast(d->paintEngine)->d_func()->hd = nullptr; - } - d->paintEngine->end(); - if (d->state != QPrinter::Idle) - d->releaseSession(); - d->state = QPrinter::Idle; - return true; -} - -QPaintEngine * -QMacPrintEngine::paintEngine() const -{ - return d_func()->paintEngine; -} - -Qt::HANDLE QMacPrintEngine::handle() const -{ - QCoreGraphicsPaintEngine *cgEngine = static_cast(paintEngine()); - return cgEngine->d_func()->hd; -} - -QMacPrintEnginePrivate::~QMacPrintEnginePrivate() -{ - [printInfo release]; - delete paintEngine; -} - -QPrinter::PrinterState QMacPrintEngine::printerState() const -{ - return d_func()->state; -} - -bool QMacPrintEngine::newPage() -{ - Q_D(QMacPrintEngine); - Q_ASSERT(d->state == QPrinter::Active); - OSStatus err = PMSessionEndPageNoDialog(d->session()); - if (err != noErr) { - if (err == kPMCancel) { - // User canceled, we need to abort! - abort(); - } else { - // Not sure what the problem is... - qWarning("QMacPrintEngine::newPage: Cannot end current page. %ld", long(err)); - d->state = QPrinter::Error; - } - return false; - } - return d->newPage_helper(); -} - -bool QMacPrintEngine::abort() -{ - Q_D(QMacPrintEngine); - if (d->state != QPrinter::Active) - return false; - bool ret = end(); - d->state = QPrinter::Aborted; - return ret; -} - -int QMacPrintEngine::metric(QPaintDevice::PaintDeviceMetric m) const -{ - Q_D(const QMacPrintEngine); - int val = 1; - switch (m) { - case QPaintDevice::PdmWidth: - val = d->m_pageLayout.paintRectPixels(d->resolution.hRes).width(); - break; - case QPaintDevice::PdmHeight: - val = d->m_pageLayout.paintRectPixels(d->resolution.hRes).height(); - break; - case QPaintDevice::PdmWidthMM: - val = qRound(d->m_pageLayout.paintRect(QPageLayout::Millimeter).width()); - break; - case QPaintDevice::PdmHeightMM: - val = qRound(d->m_pageLayout.paintRect(QPageLayout::Millimeter).height()); - break; - case QPaintDevice::PdmPhysicalDpiX: - case QPaintDevice::PdmPhysicalDpiY: { - PMPrinter printer; - if (PMSessionGetCurrentPrinter(d->session(), &printer) == noErr) { - PMResolution resolution; - PMPrinterGetOutputResolution(printer, d->settings(), &resolution); - val = (int)resolution.vRes; - break; - } - Q_FALLTHROUGH(); - } - case QPaintDevice::PdmDpiY: - val = (int)d->resolution.vRes; - break; - case QPaintDevice::PdmDpiX: - val = (int)d->resolution.hRes; - break; - case QPaintDevice::PdmNumColors: - val = (1 << metric(QPaintDevice::PdmDepth)); - break; - case QPaintDevice::PdmDepth: - val = 24; - break; - case QPaintDevice::PdmDevicePixelRatio: - val = 1; - break; - case QPaintDevice::PdmDevicePixelRatioScaled: - val = 1 * QPaintDevice::devicePixelRatioFScale(); - break; - default: - val = 0; - qWarning("QPrinter::metric: Invalid metric command"); - } - return val; -} - -void QMacPrintEnginePrivate::initialize() -{ - Q_Q(QMacPrintEngine); - - Q_ASSERT(!printInfo); - - if (!paintEngine) - paintEngine = new QCoreGraphicsPaintEngine(); - - q->gccaps = paintEngine->gccaps; - - QMacAutoReleasePool pool; - printInfo = [[NSPrintInfo alloc] initWithDictionary:[NSDictionary dictionary]]; - - QList resolutions = m_printDevice->supportedResolutions(); - if (!resolutions.isEmpty() && mode != QPrinter::ScreenResolution) { - std::sort(resolutions.begin(), resolutions.end()); - if (resolutions.count() > 1 && mode == QPrinter::HighResolution) - resolution.hRes = resolution.vRes = resolutions.last(); - else - resolution.hRes = resolution.vRes = resolutions.first(); - if (resolution.hRes == 0) - resolution.hRes = resolution.vRes = 600; - } else { - resolution.hRes = resolution.vRes = qt_defaultDpi(); - } - - setPageSize(m_pageLayout.pageSize()); - - QHash::const_iterator propC; - for (propC = valueCache.constBegin(); propC != valueCache.constEnd(); ++propC) { - q->setProperty(propC.key(), propC.value()); - } -} - -void QMacPrintEnginePrivate::releaseSession() -{ - PMSessionEndPageNoDialog(session()); - PMSessionEndDocumentNoDialog(session()); - [printInfo release]; - printInfo = nil; -} - -bool QMacPrintEnginePrivate::newPage_helper() -{ - Q_Q(QMacPrintEngine); - Q_ASSERT(state == QPrinter::Active); - - if (PMSessionError(session()) != noErr) { - q->abort(); - return false; - } - - // pop the stack of saved graphic states, in case we get the same - // context back - either way, the stack count should be 0 when we - // get the new one - QCoreGraphicsPaintEngine *cgEngine = static_cast(paintEngine); - while (cgEngine->d_func()->stackCount > 0) - cgEngine->d_func()->restoreGraphicsState(); - - OSStatus status = PMSessionBeginPageNoDialog(session(), format(), nullptr); - if (status != noErr) { - state = QPrinter::Error; - return false; - } - - QRect page = m_pageLayout.paintRectPixels(resolution.hRes); - QRect paper = m_pageLayout.fullRectPixels(resolution.hRes); - - CGContextRef cgContext; - OSStatus err = noErr; - err = PMSessionGetCGGraphicsContext(session(), &cgContext); - if (err != noErr) { - qWarning("QMacPrintEngine::newPage: Cannot retrieve CoreGraphics context: %ld", long(err)); - state = QPrinter::Error; - return false; - } - cgEngine->d_func()->hd = cgContext; - - // Set the resolution as a scaling ration of 72 (the default). - CGContextScaleCTM(cgContext, 72 / resolution.hRes, 72 / resolution.vRes); - - CGContextScaleCTM(cgContext, 1, -1); - CGContextTranslateCTM(cgContext, 0, -paper.height()); - if (m_pageLayout.mode() != QPageLayout::FullPageMode) - CGContextTranslateCTM(cgContext, page.x() - paper.x(), page.y() - paper.y()); - cgEngine->d_func()->orig_xform = CGContextGetCTM(cgContext); - cgEngine->d_func()->setClip(nullptr); - cgEngine->state->dirtyFlags = QPaintEngine::DirtyFlag(QPaintEngine::AllDirty - & ~(QPaintEngine::DirtyClipEnabled - | QPaintEngine::DirtyClipRegion - | QPaintEngine::DirtyClipPath)); - if (cgEngine->painter()->hasClipping()) - cgEngine->state->dirtyFlags |= QPaintEngine::DirtyClipEnabled; - cgEngine->syncState(); - return true; -} - -void QMacPrintEnginePrivate::setPageSize(const QPageSize &pageSize) -{ - if (!pageSize.isValid()) - return; - - // Get the matching printer paper - QPageSize printerPageSize = m_printDevice->supportedPageSize(pageSize); - QPageSize usePageSize = printerPageSize.isValid() ? printerPageSize : pageSize; - - // Get the PMPaper and check it is valid - PMPaper macPaper = m_printDevice->macPaper(usePageSize); - if (!macPaper) { - qWarning() << "QMacPrintEngine: Invalid PMPaper returned for " << pageSize; - return; - } - - QMarginsF printable = m_printDevice->printableMargins(usePageSize, m_pageLayout.orientation(), resolution.hRes); - m_pageLayout.setPageSize(usePageSize, qt_convertMargins(printable, QPageLayout::Point, m_pageLayout.units())); - - // You cannot set the page size on a PMPageFormat, you must create a new PMPageFormat - PMPageFormat pageFormat; - PMCreatePageFormatWithPMPaper(&pageFormat, macPaper); - PMSetOrientation(pageFormat, m_pageLayout.orientation() == QPageLayout::Landscape ? kPMLandscape : kPMPortrait, kPMUnlocked); - PMCopyPageFormat(pageFormat, format()); - if (PMSessionValidatePageFormat(session(), format(), kPMDontWantBoolean) != noErr) - qWarning("QMacPrintEngine: Invalid page format"); - PMRelease(pageFormat); -} - -void QMacPrintEngine::updateState(const QPaintEngineState &state) -{ - d_func()->paintEngine->updateState(state); -} - -void QMacPrintEngine::drawRects(const QRectF *r, int num) -{ - Q_D(QMacPrintEngine); - Q_ASSERT(d->state == QPrinter::Active); - d->paintEngine->drawRects(r, num); -} - -void QMacPrintEngine::drawPoints(const QPointF *points, int pointCount) -{ - Q_D(QMacPrintEngine); - Q_ASSERT(d->state == QPrinter::Active); - d->paintEngine->drawPoints(points, pointCount); -} - -void QMacPrintEngine::drawEllipse(const QRectF &r) -{ - Q_D(QMacPrintEngine); - Q_ASSERT(d->state == QPrinter::Active); - d->paintEngine->drawEllipse(r); -} - -void QMacPrintEngine::drawLines(const QLineF *lines, int lineCount) -{ - Q_D(QMacPrintEngine); - Q_ASSERT(d->state == QPrinter::Active); - d->paintEngine->drawLines(lines, lineCount); -} - -void QMacPrintEngine::drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode) -{ - Q_D(QMacPrintEngine); - Q_ASSERT(d->state == QPrinter::Active); - d->paintEngine->drawPolygon(points, pointCount, mode); -} - -void QMacPrintEngine::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr) -{ - Q_D(QMacPrintEngine); - Q_ASSERT(d->state == QPrinter::Active); - d->paintEngine->drawPixmap(r, pm, sr); -} - -void QMacPrintEngine::drawImage(const QRectF &r, const QImage &pm, const QRectF &sr, Qt::ImageConversionFlags flags) -{ - Q_D(QMacPrintEngine); - Q_ASSERT(d->state == QPrinter::Active); - d->paintEngine->drawImage(r, pm, sr, flags); -} - -void QMacPrintEngine::drawTextItem(const QPointF &p, const QTextItem &ti) -{ - Q_D(QMacPrintEngine); - Q_ASSERT(d->state == QPrinter::Active); - if (!d->embedFonts) - QPaintEngine::drawTextItem(p, ti); - else - d->paintEngine->drawTextItem(p, ti); -} - -void QMacPrintEngine::drawTiledPixmap(const QRectF &dr, const QPixmap &pixmap, const QPointF &sr) -{ - Q_D(QMacPrintEngine); - Q_ASSERT(d->state == QPrinter::Active); - d->paintEngine->drawTiledPixmap(dr, pixmap, sr); -} - -void QMacPrintEngine::drawPath(const QPainterPath &path) -{ - Q_D(QMacPrintEngine); - Q_ASSERT(d->state == QPrinter::Active); - d->paintEngine->drawPath(path); -} - - -void QMacPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &value) -{ - Q_D(QMacPrintEngine); - - d->valueCache.insert(key, value); - if (!d->printInfo) - return; - - switch (key) { - - // The following keys are properties or derived values and so cannot be set - case PPK_PageRect: - break; - case PPK_PaperRect: - break; - case PPK_PaperSources: - break; - case PPK_SupportsMultipleCopies: - break; - case PPK_SupportedResolutions: - break; - - // The following keys are settings that are unsupported by the Mac PrintEngine - case PPK_ColorMode: - break; - case PPK_CustomBase: - break; - case PPK_PageOrder: - // TODO Check if can be supported via Cups Options - break; - case PPK_PaperSource: - // TODO Check if can be supported via Cups Options - break; - case PPK_PrinterProgram: - break; - case PPK_SelectionOption: - break; - - // The following keys are properties and settings that are supported by the Mac PrintEngine - case PPK_FontEmbedding: - d->embedFonts = value.toBool(); - break; - case PPK_Resolution: { - int bestResolution = 0; - int dpi = value.toInt(); - int bestDistance = INT_MAX; - for (int resolution : d->m_printDevice->supportedResolutions()) { - if (dpi == resolution) { - bestResolution = resolution; - break; - } else { - int distance = qAbs(dpi - resolution); - if (distance < bestDistance) { - bestDistance = distance; - bestResolution = resolution; - } - } - } - PMResolution resolution; - resolution.hRes = resolution.vRes = bestResolution; - if (PMPrinterSetOutputResolution(d->m_printDevice->macPrinter(), d->settings(), &resolution) == noErr) { - // Setting the resolution succeeded. - // Now try to read the actual resolution selected by the OS. - if (PMPrinterGetOutputResolution(d->m_printDevice->macPrinter(), d->settings(), &d->resolution) != noErr) { - // Reading the resolution somehow failed; d->resolution is in undefined state. - // So use the value which was acceptable to PMPrinterSetOutputResolution. - d->resolution = resolution; - } - } - break; - } - case PPK_CollateCopies: - PMSetCollate(d->settings(), value.toBool()); - break; - case PPK_Creator: - d->m_creator = value.toString(); - break; - case PPK_DocumentName: - PMPrintSettingsSetJobName(d->settings(), QCFString(value.toString())); - break; - case PPK_Duplex: { - QPrint::DuplexMode mode = QPrint::DuplexMode(value.toInt()); - if (mode == property(PPK_Duplex).toInt() || !d->m_printDevice->supportedDuplexModes().contains(mode)) - break; - switch (mode) { - case QPrint::DuplexNone: - PMSetDuplex(d->settings(), kPMDuplexNone); - break; - case QPrint::DuplexAuto: - PMSetDuplex(d->settings(), d->m_pageLayout.orientation() == QPageLayout::Landscape ? kPMDuplexTumble : kPMDuplexNoTumble); - break; - case QPrint::DuplexLongSide: - PMSetDuplex(d->settings(), kPMDuplexNoTumble); - break; - case QPrint::DuplexShortSide: - PMSetDuplex(d->settings(), kPMDuplexTumble); - break; - default: - // Don't change - break; - } - break; - } - case PPK_FullPage: - if (value.toBool()) - d->m_pageLayout.setMode(QPageLayout::FullPageMode); - else - d->m_pageLayout.setMode(QPageLayout::StandardMode); - break; - case PPK_CopyCount: // fallthrough - case PPK_NumberOfCopies: - PMSetCopies(d->settings(), value.toInt(), false); - break; - case PPK_Orientation: { - // First try set the Mac format orientation, then set our orientation to match result - QPageLayout::Orientation newOrientation = QPageLayout::Orientation(value.toInt()); - PMOrientation macOrientation = (newOrientation == QPageLayout::Landscape) ? kPMLandscape : kPMPortrait; - PMSetOrientation(d->format(), macOrientation, kPMUnlocked); - PMSessionValidatePageFormat(d->session(), d->format(), kPMDontWantBoolean); - PMGetOrientation(d->format(), &macOrientation); - d->m_pageLayout.setOrientation(macOrientation == kPMLandscape ? QPageLayout::Landscape : QPageLayout::Portrait); - break; - } - case PPK_OutputFileName: - d->outputFilename = value.toString(); - break; - case PPK_PageSize: - d->setPageSize(QPageSize(QPageSize::PageSizeId(value.toInt()))); - break; - case PPK_PaperName: - // Get the named page size from the printer if supported - d->setPageSize(d->m_printDevice->supportedPageSize(value.toString())); - break; - case PPK_WindowsPageSize: - d->setPageSize(QPageSize(QPageSize::id(value.toInt()))); - break; - case PPK_PrinterName: { - QVariant pageSize = QVariant::fromValue(d->m_pageLayout.pageSize()); - const bool isFullPage = d->m_pageLayout.mode() == QPageLayout::FullPageMode; - QVariant orientation = QVariant::fromValue(d->m_pageLayout.orientation()); - QVariant margins = QVariant::fromValue(QPair(d->m_pageLayout.margins(), - d->m_pageLayout.units())); - QString id = value.toString(); - if (id.isEmpty()) - id = QCocoaPrinterSupport().defaultPrintDeviceId(); - else if (!QCocoaPrinterSupport().availablePrintDeviceIds().contains(id)) - break; - d->m_printDevice.reset(new QCocoaPrintDevice(id)); - PMPrinter printer = d->m_printDevice->macPrinter(); - PMRetain(printer); - PMSessionSetCurrentPMPrinter(d->session(), printer); - // Ensure the settings are up to date and valid - if (d->m_printDevice->supportedPageSize(pageSize.value()).isValid()) - setProperty(PPK_QPageSize, pageSize); - else - setProperty(PPK_CustomPaperSize, pageSize.value().size(QPageSize::Point)); - setProperty(PPK_FullPage, QVariant(isFullPage)); - setProperty(PPK_Orientation, orientation); - setProperty(PPK_QPageMargins, margins); - break; - } - case PPK_CustomPaperSize: - d->setPageSize(QPageSize(value.toSizeF(), QPageSize::Point)); - break; - case PPK_PageMargins: - { - QList margins(value.toList()); - Q_ASSERT(margins.size() == 4); - d->m_pageLayout.setMargins(QMarginsF(margins.at(0).toReal(), margins.at(1).toReal(), - margins.at(2).toReal(), margins.at(3).toReal())); - break; - } - case PPK_QPageSize: - d->setPageSize(value.value()); - break; - case PPK_QPageMargins: { - QPair pair = value.value >(); - d->m_pageLayout.setUnits(pair.second); - d->m_pageLayout.setMargins(pair.first); - break; - } - case PPK_QPageLayout: { - QPageLayout pageLayout = value.value(); - if (pageLayout.isValid() && d->m_printDevice->isValidPageLayout(pageLayout, d->resolution.hRes)) { - setProperty(PPK_QPageSize, QVariant::fromValue(pageLayout.pageSize())); - setProperty(PPK_FullPage, pageLayout.mode() == QPageLayout::FullPageMode); - setProperty(PPK_Orientation, QVariant::fromValue(pageLayout.orientation())); - d->m_pageLayout.setUnits(pageLayout.units()); - d->m_pageLayout.setMargins(pageLayout.margins()); - } - break; - } - // No default so that compiler will complain if new keys added and not handled in this engine - } -} - -QVariant QMacPrintEngine::property(PrintEnginePropertyKey key) const -{ - Q_D(const QMacPrintEngine); - QVariant ret; - - if (!d->printInfo && d->valueCache.contains(key)) - return *d->valueCache.find(key); - - switch (key) { - - // The following keys are settings that are unsupported by the Mac PrintEngine - // Return sensible default values to ensure consistent behavior across platforms - case PPK_ColorMode: - ret = QPrinter::Color; - break; - case PPK_CustomBase: - // Special case, leave null - break; - case PPK_PageOrder: - // TODO Check if can be supported via Cups Options - ret = QPrinter::FirstPageFirst; - break; - case PPK_PaperSource: - // TODO Check if can be supported via Cups Options - ret = QPrinter::Auto; - break; - case PPK_PaperSources: { - // TODO Check if can be supported via Cups Options - QList out; - out << int(QPrinter::Auto); - ret = out; - break; - } - case PPK_PrinterProgram: - ret = QString(); - break; - case PPK_SelectionOption: - ret = QString(); - break; - - // The following keys are properties and settings that are supported by the Mac PrintEngine - case PPK_FontEmbedding: - ret = d->embedFonts; - break; - case PPK_CollateCopies: { - Boolean status; - PMGetCollate(d->settings(), &status); - ret = bool(status); - break; - } - case PPK_Creator: - ret = d->m_creator; - break; - case PPK_DocumentName: { - CFStringRef name; - PMPrintSettingsGetJobName(d->settings(), &name); - ret = QString::fromCFString(name); - break; - } - case PPK_Duplex: { - PMDuplexMode mode = kPMDuplexNone; - PMGetDuplex(d->settings(), &mode); - switch (mode) { - case kPMDuplexNoTumble: - ret = QPrinter::DuplexLongSide; - break; - case kPMDuplexTumble: - ret = QPrinter::DuplexShortSide; - break; - case kPMDuplexNone: - default: - ret = QPrinter::DuplexNone; - break; - } - break; - } - case PPK_FullPage: - ret = d->m_pageLayout.mode() == QPageLayout::FullPageMode; - break; - case PPK_NumberOfCopies: - ret = 1; - break; - case PPK_CopyCount: { - UInt32 copies = 1; - PMGetCopies(d->settings(), &copies); - ret = (uint) copies; - break; - } - case PPK_SupportsMultipleCopies: - ret = true; - break; - case PPK_Orientation: - ret = d->m_pageLayout.orientation(); - break; - case PPK_OutputFileName: - ret = d->outputFilename; - break; - case PPK_PageRect: - // PageRect is returned in device pixels - ret = d->m_pageLayout.paintRectPixels(d->resolution.hRes); - break; - case PPK_PageSize: - ret = d->m_pageLayout.pageSize().id(); - break; - case PPK_PaperName: - ret = d->m_pageLayout.pageSize().name(); - break; - case PPK_WindowsPageSize: - ret = d->m_pageLayout.pageSize().windowsId(); - break; - case PPK_PaperRect: - // PaperRect is returned in device pixels - ret = d->m_pageLayout.fullRectPixels(d->resolution.hRes); - break; - case PPK_PrinterName: - return d->m_printDevice->id(); - break; - case PPK_Resolution: { - ret = d->resolution.hRes; - break; - } - case PPK_SupportedResolutions: { - QList list; - for (int resolution : d->m_printDevice->supportedResolutions()) - list << resolution; - ret = list; - break; - } - case PPK_CustomPaperSize: - ret = d->m_pageLayout.fullRectPoints().size(); - break; - case PPK_PageMargins: { - QList list; - QMarginsF margins = d->m_pageLayout.margins(QPageLayout::Point); - list << margins.left() << margins.top() << margins.right() << margins.bottom(); - ret = list; - break; - } - case PPK_QPageSize: - ret.setValue(d->m_pageLayout.pageSize()); - break; - case PPK_QPageMargins: { - QPair pair = qMakePair(d->m_pageLayout.margins(), d->m_pageLayout.units()); - ret.setValue(pair); - break; - } - case PPK_QPageLayout: - ret.setValue(d->m_pageLayout); - // No default so that compiler will complain if new keys added and not handled in this engine - } - return ret; -} - -QT_END_NAMESPACE - -#endif // QT_NO_PRINTER diff --git a/src/plugins/platforms/cocoa/qprintengine_mac_p.h b/src/plugins/platforms/cocoa/qprintengine_mac_p.h deleted file mode 100644 index 6a1ed2e263..0000000000 --- a/src/plugins/platforms/cocoa/qprintengine_mac_p.h +++ /dev/null @@ -1,157 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the plugins 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$ -** -****************************************************************************/ - -#ifndef QPRINTENGINE_MAC_P_H -#define QPRINTENGINE_MAC_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include - -#ifndef QT_NO_PRINTER - -#include -#include -#include -#include - -#include "qcocoaprintdevice.h" - -#include "qpaintengine_mac_p.h" - -Q_FORWARD_DECLARE_OBJC_CLASS(NSPrintInfo); - -QT_BEGIN_NAMESPACE - -class QPrinterPrivate; -class QMacPrintEnginePrivate; -class QMacPrintEngine : public QPaintEngine, public QPrintEngine -{ - Q_DECLARE_PRIVATE(QMacPrintEngine) -public: - QMacPrintEngine(QPrinter::PrinterMode mode, const QString &deviceId); - - Qt::HANDLE handle() const; - - bool begin(QPaintDevice *dev); - bool end(); - virtual QPaintEngine::Type type() const { return QPaintEngine::MacPrinter; } - - QPaintEngine *paintEngine() const; - - void setProperty(PrintEnginePropertyKey key, const QVariant &value); - QVariant property(PrintEnginePropertyKey key) const; - - QPrinter::PrinterState printerState() const; - - bool newPage(); - bool abort(); - int metric(QPaintDevice::PaintDeviceMetric) const; - - //forwarded functions - - void updateState(const QPaintEngineState &state); - - virtual void drawLines(const QLineF *lines, int lineCount); - virtual void drawRects(const QRectF *r, int num); - virtual void drawPoints(const QPointF *p, int pointCount); - virtual void drawEllipse(const QRectF &r); - virtual void drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode); - virtual void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr); - virtual void drawImage(const QRectF &r, const QImage &pm, const QRectF &sr, Qt::ImageConversionFlags flags); - virtual void drawTextItem(const QPointF &p, const QTextItem &ti); - virtual void drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &s); - virtual void drawPath(const QPainterPath &); - -private: - friend class QCocoaNativeInterface; -}; - -class QMacPrintEnginePrivate : public QPaintEnginePrivate -{ - Q_DECLARE_PUBLIC(QMacPrintEngine) -public: - QPrinter::PrinterMode mode; - QPrinter::PrinterState state; - QSharedPointer m_printDevice; - QPageLayout m_pageLayout; - NSPrintInfo *printInfo; - PMResolution resolution; - QString outputFilename; - QString m_creator; - QPaintEngine *paintEngine; - QHash valueCache; - uint embedFonts; - - QMacPrintEnginePrivate() : mode(QPrinter::ScreenResolution), state(QPrinter::Idle), - m_pageLayout(QPageLayout(QPageSize(QPageSize::A4), QPageLayout::Portrait, QMarginsF(0, 0, 0, 0))), - printInfo(nullptr), paintEngine(nullptr), embedFonts(true) {} - ~QMacPrintEnginePrivate(); - - void initialize(); - void releaseSession(); - bool newPage_helper(); - void setPageSize(const QPageSize &pageSize); - inline bool isPrintSessionInitialized() const - { - return printInfo != 0; - } - - 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() override { return paintEngine; } - Qt::HANDLE nativeHandle() override { return q_func()->handle(); } -}; - -QT_END_NAMESPACE - -#endif // QT_NO_PRINTER - -#endif // QPRINTENGINE_WIN_P_H diff --git a/src/plugins/printsupport/cocoa/main.cpp b/src/plugins/printsupport/cocoa/main.cpp index b6830c88d4..26ef5cca22 100644 --- a/src/plugins/printsupport/cocoa/main.cpp +++ b/src/plugins/printsupport/cocoa/main.cpp @@ -42,6 +42,8 @@ #include #include +#include + QT_BEGIN_NAMESPACE class QCocoaPrinterSupportPlugin : public QPlatformPrinterSupportPlugin @@ -57,18 +59,8 @@ QPlatformPrinterSupport *QCocoaPrinterSupportPlugin::create(const QString &key) { if (key.compare(key, QLatin1String("cocoaprintersupport"), Qt::CaseInsensitive) != 0) return 0; - QGuiApplication *app = qobject_cast(QCoreApplication::instance()); - if (!app) - return 0; - QPlatformNativeInterface *platformNativeInterface = app->platformNativeInterface(); - int at = platformNativeInterface->metaObject()->indexOfMethod("createPlatformPrinterSupport()"); - if (at == -1) - return 0; - QMetaMethod createPlatformPrinterSupport = platformNativeInterface->metaObject()->method(at); - QPlatformPrinterSupport *platformPrinterSupport = 0; - if (!createPlatformPrinterSupport.invoke(platformNativeInterface, Q_RETURN_ARG(QPlatformPrinterSupport *, platformPrinterSupport))) - return 0; - return platformPrinterSupport; + + return new QCocoaPrinterSupport(); } QT_END_NAMESPACE -- cgit v1.2.3