diff options
Diffstat (limited to 'src/printsupport/platform/macos/qprintengine_mac.mm')
-rw-r--r-- | src/printsupport/platform/macos/qprintengine_mac.mm | 805 |
1 files changed, 805 insertions, 0 deletions
diff --git a/src/printsupport/platform/macos/qprintengine_mac.mm b/src/printsupport/platform/macos/qprintengine_mac.mm new file mode 100644 index 0000000000..1b06722447 --- /dev/null +++ b/src/printsupport/platform/macos/qprintengine_mac.mm @@ -0,0 +1,805 @@ +/**************************************************************************** +** +** 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 <AppKit/AppKit.h> +#include <ApplicationServices/ApplicationServices.h> + +#include "qprintengine_mac_p.h" +#include "qcocoaprintersupport_p.h" +#include <quuid.h> +#include <QtGui/qpagelayout.h> +#include <QtCore/qcoreapplication.h> +#include <QtCore/qdebug.h> + +#include <QtCore/private/qcore_mac_p.h> + +#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<QPrinter *>(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<CFURLRef> 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<QCoreGraphicsPaintEngine*>(d->paintEngine)->d_func()->stackCount = 0; + static_cast<QCoreGraphicsPaintEngine*>(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<QCoreGraphicsPaintEngine*>(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<int> 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<QMacPrintEngine::PrintEnginePropertyKey, QVariant>::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<QCoreGraphicsPaintEngine*>(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<QMarginsF, QPageLayout::Unit>(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<QPageSize>()).isValid()) + setProperty(PPK_QPageSize, pageSize); + else + setProperty(PPK_CustomPaperSize, pageSize.value<QPageSize>().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<QVariant> 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<QPageSize>()); + break; + case PPK_QPageMargins: { + QPair<QMarginsF, QPageLayout::Unit> pair = value.value<QPair<QMarginsF, QPageLayout::Unit> >(); + d->m_pageLayout.setUnits(pair.second); + d->m_pageLayout.setMargins(pair.first); + break; + } + case PPK_QPageLayout: { + QPageLayout pageLayout = value.value<QPageLayout>(); + 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<QVariant> 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<QVariant> 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<QVariant> 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<QMarginsF, QPageLayout::Unit> 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; +} + +NSPrintInfo *QMacPrintEngine::printInfo() +{ + Q_D(QMacPrintEngine); + if (d->state == QPrinter::Idle && !d->isPrintSessionInitialized()) + d->initialize(); + return d->printInfo; +} + +QT_END_NAMESPACE + +#endif // QT_NO_PRINTER |