src/gui/painting/qprintengine_mac.mm
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtGui module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include <private/qprintengine_mac_p.h>
       
    43 #include <qdebug.h>
       
    44 #include <qthread.h>
       
    45 #include <QtCore/qcoreapplication.h>
       
    46 
       
    47 #ifndef QT_NO_PRINTER
       
    48 
       
    49 QT_BEGIN_NAMESPACE
       
    50 
       
    51 extern QSizeF qt_paperSizeToQSizeF(QPrinter::PaperSize size);
       
    52 extern int qt_defaultDpi();
       
    53 
       
    54 QMacPrintEngine::QMacPrintEngine(QPrinter::PrinterMode mode) : QPaintEngine(*(new QMacPrintEnginePrivate))
       
    55 {
       
    56     Q_D(QMacPrintEngine);
       
    57     d->mode = mode;
       
    58     d->initialize();
       
    59 }
       
    60 
       
    61 bool QMacPrintEngine::begin(QPaintDevice *dev)
       
    62 {
       
    63     Q_D(QMacPrintEngine);
       
    64 
       
    65     Q_ASSERT(dev && dev->devType() == QInternal::Printer);
       
    66     if (!static_cast<QPrinter *>(dev)->isValid())
       
    67 	return false;
       
    68 
       
    69     if (d->state == QPrinter::Idle && !d->isPrintSessionInitialized()) // Need to reinitialize
       
    70         d->initialize();
       
    71 
       
    72     d->paintEngine->state = state;
       
    73     d->paintEngine->begin(dev);
       
    74     Q_ASSERT_X(d->state == QPrinter::Idle, "QMacPrintEngine", "printer already active");
       
    75 
       
    76     if (PMSessionValidatePrintSettings(d->session, d->settings, kPMDontWantBoolean) != noErr
       
    77         || PMSessionValidatePageFormat(d->session, d->format, kPMDontWantBoolean) != noErr) {
       
    78         d->state = QPrinter::Error;
       
    79         return false;
       
    80     }
       
    81 
       
    82     if (!d->outputFilename.isEmpty()) {
       
    83         QCFType<CFURLRef> outFile = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault,
       
    84                                                                   QCFString(d->outputFilename),
       
    85                                                                   kCFURLPOSIXPathStyle,
       
    86                                                                   false);
       
    87         if (PMSessionSetDestination(d->session, d->settings, kPMDestinationFile,
       
    88                                     kPMDocumentFormatPDF, outFile) != noErr) {
       
    89             qWarning("QMacPrintEngine::begin: Problem setting file [%s]", d->outputFilename.toUtf8().constData());
       
    90             return false;
       
    91         }
       
    92     }
       
    93     OSStatus status = noErr;
       
    94 #ifndef QT_MAC_USE_COCOA
       
    95     status = d->shouldSuppressStatus() ? PMSessionBeginCGDocumentNoDialog(d->session, d->settings, d->format)
       
    96                                        : PMSessionBeginCGDocument(d->session, d->settings, d->format);
       
    97 #else
       
    98     status = PMSessionBeginCGDocumentNoDialog(d->session, d->settings, d->format);
       
    99 #endif
       
   100 
       
   101     if (status != noErr) {
       
   102         d->state = QPrinter::Error;
       
   103         return false;
       
   104     }
       
   105 
       
   106     d->state = QPrinter::Active;
       
   107     setActive(true);
       
   108     d->newPage_helper();
       
   109     return true;
       
   110 }
       
   111 
       
   112 bool QMacPrintEngine::end()
       
   113 {
       
   114     Q_D(QMacPrintEngine);
       
   115     if (d->state == QPrinter::Aborted)
       
   116         return true;  // I was just here a function call ago :)
       
   117     if(d->paintEngine->type() == QPaintEngine::CoreGraphics)
       
   118         static_cast<QCoreGraphicsPaintEngine*>(d->paintEngine)->d_func()->hd = 0;
       
   119     d->paintEngine->end();
       
   120     if (d->state != QPrinter::Idle)
       
   121 	d->releaseSession();
       
   122     d->state  = QPrinter::Idle;
       
   123     return true;
       
   124 }
       
   125 
       
   126 QPaintEngine *
       
   127 QMacPrintEngine::paintEngine() const
       
   128 {
       
   129     return d_func()->paintEngine;
       
   130 }
       
   131 
       
   132 Qt::HANDLE QMacPrintEngine::handle() const
       
   133 {
       
   134     QCoreGraphicsPaintEngine *cgEngine = static_cast<QCoreGraphicsPaintEngine*>(paintEngine());
       
   135     return cgEngine->d_func()->hd;
       
   136 }
       
   137 
       
   138 QMacPrintEnginePrivate::~QMacPrintEnginePrivate()
       
   139 {
       
   140 #ifdef QT_MAC_USE_COCOA
       
   141     [printInfo release];
       
   142 #endif
       
   143     delete paintEngine;
       
   144 }
       
   145 
       
   146 void QMacPrintEnginePrivate::setPaperSize(QPrinter::PaperSize ps)
       
   147 {
       
   148     Q_Q(QMacPrintEngine);
       
   149     QSizeF newSize = qt_paperSizeToQSizeF(ps);
       
   150     QCFType<CFArrayRef> formats;
       
   151     PMPrinter printer;
       
   152 
       
   153     if (PMSessionGetCurrentPrinter(session, &printer) == noErr
       
   154         && PMSessionCreatePageFormatList(session, printer, &formats) == noErr) {
       
   155         CFIndex total = CFArrayGetCount(formats);
       
   156         PMPageFormat tmp;
       
   157         PMRect paper;
       
   158         for (CFIndex idx = 0; idx < total; ++idx) {
       
   159             tmp = static_cast<PMPageFormat>(
       
   160                                         const_cast<void *>(CFArrayGetValueAtIndex(formats, idx)));
       
   161             PMGetUnadjustedPaperRect(tmp, &paper);
       
   162             int wMM = int((paper.right - paper.left) / 72 * 25.4 + 0.5);
       
   163             int hMM = int((paper.bottom - paper.top) / 72 * 25.4 + 0.5);
       
   164             if (newSize.width() == wMM && newSize.height() == hMM) {
       
   165                 PMCopyPageFormat(tmp, format);
       
   166                 // reset the orientation and resolution as they are lost in the copy.
       
   167                 q->setProperty(QPrintEngine::PPK_Orientation, orient);
       
   168                 if (PMSessionValidatePageFormat(session, format, kPMDontWantBoolean) != noErr) {
       
   169                     // Don't know, warn for the moment.
       
   170                     qWarning("QMacPrintEngine, problem setting format and resolution for this page size");
       
   171                 }
       
   172                 break;
       
   173             }
       
   174         }
       
   175     }
       
   176 }
       
   177 
       
   178 QPrinter::PaperSize QMacPrintEnginePrivate::paperSize() const
       
   179 {
       
   180     PMRect paper;
       
   181     PMGetUnadjustedPaperRect(format, &paper);
       
   182     int wMM = int((paper.right - paper.left) / 72 * 25.4 + 0.5);
       
   183     int hMM = int((paper.bottom - paper.top) / 72 * 25.4 + 0.5);
       
   184     for (int i = QPrinter::A4; i < QPrinter::NPaperSize; ++i) {
       
   185         QSizeF s = qt_paperSizeToQSizeF(QPrinter::PaperSize(i));
       
   186         if (s.width() == wMM && s.height() == hMM)
       
   187             return (QPrinter::PaperSize)i;
       
   188     }
       
   189     return QPrinter::Custom;
       
   190 }
       
   191 
       
   192 QList<QVariant> QMacPrintEnginePrivate::supportedResolutions() const
       
   193 {
       
   194     Q_ASSERT_X(session, "QMacPrinterEngine::supportedResolutions",
       
   195                "must have a valid printer session");
       
   196     UInt32 resCount;
       
   197     QList<QVariant> resolutions;
       
   198     PMPrinter printer;
       
   199     if (PMSessionGetCurrentPrinter(session, &printer) == noErr) {
       
   200         PMResolution res;
       
   201         OSStatus status = PMPrinterGetPrinterResolutionCount(printer, &resCount);
       
   202         if (status  == kPMNotImplemented) {
       
   203 #if (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5)
       
   204             // *Sigh* we have to use the non-indexed version.
       
   205             if (PMPrinterGetPrinterResolution(printer, kPMMinSquareResolution, &res) == noErr)
       
   206                 resolutions.append(int(res.hRes));
       
   207             if (PMPrinterGetPrinterResolution(printer, kPMMaxSquareResolution, &res) == noErr) {
       
   208                 QVariant var(int(res.hRes));
       
   209                 if (!resolutions.contains(var))
       
   210                     resolutions.append(var);
       
   211             }
       
   212             if (PMPrinterGetPrinterResolution(printer, kPMDefaultResolution, &res) == noErr) {
       
   213                 QVariant var(int(res.hRes));
       
   214                 if (!resolutions.contains(var))
       
   215                     resolutions.append(var);
       
   216             }
       
   217 #endif
       
   218         } else if (status == noErr) {
       
   219             // According to the docs, index start at 1.
       
   220             for (UInt32 i = 1; i <= resCount; ++i) {
       
   221                 if (PMPrinterGetIndexedPrinterResolution(printer, i, &res) == noErr)
       
   222                     resolutions.append(QVariant(int(res.hRes)));
       
   223             }
       
   224         } else {
       
   225             qWarning("QMacPrintEngine::supportedResolutions: Unexpected error: %ld", long(status));
       
   226         }
       
   227     }
       
   228     return resolutions;
       
   229 }
       
   230 
       
   231 bool QMacPrintEnginePrivate::shouldSuppressStatus() const
       
   232 {
       
   233     if (suppressStatus == true)
       
   234         return true;
       
   235 
       
   236     // Supress displaying the automatic progress dialog if we are printing
       
   237     // from a non-gui thread.
       
   238     return (qApp->thread() != QThread::currentThread());
       
   239 }
       
   240 
       
   241 QPrinter::PrinterState QMacPrintEngine::printerState() const
       
   242 {
       
   243     return d_func()->state;
       
   244 }
       
   245 
       
   246 bool QMacPrintEngine::newPage()
       
   247 {
       
   248     Q_D(QMacPrintEngine);
       
   249     Q_ASSERT(d->state == QPrinter::Active);
       
   250     OSStatus err =
       
   251 #ifndef QT_MAC_USE_COCOA
       
   252     d->shouldSuppressStatus() ? PMSessionEndPageNoDialog(d->session)
       
   253                               : PMSessionEndPage(d->session);
       
   254 #else
       
   255     PMSessionEndPageNoDialog(d->session);
       
   256 #endif
       
   257     if (err != noErr)  {
       
   258         if (err == kPMCancel) {
       
   259             // User canceled, we need to abort!
       
   260             abort();
       
   261         } else {
       
   262             // Not sure what the problem is...
       
   263             qWarning("QMacPrintEngine::newPage: Cannot end current page. %ld", long(err));
       
   264             d->state = QPrinter::Error;
       
   265         }
       
   266         return false;
       
   267     }
       
   268     return d->newPage_helper();
       
   269 }
       
   270 
       
   271 bool QMacPrintEngine::abort()
       
   272 {
       
   273     Q_D(QMacPrintEngine);
       
   274     if (d->state != QPrinter::Active)
       
   275         return false;
       
   276     bool ret = end();
       
   277     d->state = QPrinter::Aborted;
       
   278     return ret;
       
   279 }
       
   280 
       
   281 static inline int qt_get_PDMWidth(PMPageFormat pformat, bool fullPage,
       
   282                                   const PMResolution &resolution)
       
   283 {
       
   284     int val = 0;
       
   285     PMRect r;
       
   286     qreal hRatio = resolution.hRes / 72;
       
   287     if (fullPage) {
       
   288         if (PMGetAdjustedPaperRect(pformat, &r) == noErr)
       
   289             val = qRound((r.right - r.left) * hRatio);
       
   290     } else {
       
   291         if (PMGetAdjustedPageRect(pformat, &r) == noErr)
       
   292             val = qRound((r.right - r.left) * hRatio);
       
   293     }
       
   294     return val;
       
   295 }
       
   296 
       
   297 static inline int qt_get_PDMHeight(PMPageFormat pformat, bool fullPage,
       
   298                                    const PMResolution &resolution)
       
   299 {
       
   300     int val = 0;
       
   301     PMRect r;
       
   302     qreal vRatio = resolution.vRes / 72;
       
   303     if (fullPage) {
       
   304         if (PMGetAdjustedPaperRect(pformat, &r) == noErr)
       
   305             val = qRound((r.bottom - r.top) * vRatio);
       
   306     } else {
       
   307         if (PMGetAdjustedPageRect(pformat, &r) == noErr)
       
   308             val = qRound((r.bottom - r.top) * vRatio);
       
   309     }
       
   310     return val;
       
   311 }
       
   312 
       
   313 
       
   314 int QMacPrintEngine::metric(QPaintDevice::PaintDeviceMetric m) const
       
   315 {
       
   316     Q_D(const QMacPrintEngine);
       
   317     int val = 1;
       
   318     switch (m) {
       
   319     case QPaintDevice::PdmWidth:
       
   320         if (d->hasCustomPaperSize) {
       
   321             val = qRound(d->customSize.width());
       
   322             if (d->hasCustomPageMargins) {
       
   323                 val -= qRound(d->leftMargin + d->rightMargin);
       
   324             } else {
       
   325                 QList<QVariant> margins = property(QPrintEngine::PPK_PageMargins).toList();
       
   326                 val -= qRound(margins.at(0).toDouble() + margins.at(2).toDouble());
       
   327             }
       
   328         } else {
       
   329             val = qt_get_PDMWidth(d->format, property(PPK_FullPage).toBool(), d->resolution);
       
   330         }
       
   331         break;
       
   332     case QPaintDevice::PdmHeight:
       
   333         if (d->hasCustomPaperSize) {
       
   334             val = qRound(d->customSize.height());
       
   335             if (d->hasCustomPageMargins) {
       
   336                 val -= qRound(d->topMargin + d->bottomMargin);
       
   337             } else {
       
   338                 QList<QVariant> margins = property(QPrintEngine::PPK_PageMargins).toList();
       
   339                 val -= qRound(margins.at(1).toDouble() + margins.at(3).toDouble());
       
   340             }
       
   341         } else {
       
   342             val = qt_get_PDMHeight(d->format, property(PPK_FullPage).toBool(), d->resolution);
       
   343         }
       
   344         break;
       
   345     case QPaintDevice::PdmWidthMM:
       
   346         val = metric(QPaintDevice::PdmWidth);
       
   347         val = int((val * 254 + 5 * d->resolution.hRes) / (10 * d->resolution.hRes));
       
   348         break;
       
   349     case QPaintDevice::PdmHeightMM:
       
   350         val = metric(QPaintDevice::PdmHeight);
       
   351         val = int((val * 254 + 5 * d->resolution.vRes) / (10 * d->resolution.vRes));
       
   352         break;
       
   353     case QPaintDevice::PdmPhysicalDpiX:
       
   354     case QPaintDevice::PdmPhysicalDpiY: {
       
   355         PMPrinter printer;
       
   356         if(PMSessionGetCurrentPrinter(d->session, &printer) == noErr) {
       
   357             PMResolution resolution;
       
   358 #ifndef QT_MAC_USE_COCOA
       
   359 #  if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5)
       
   360             if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) {
       
   361                 PMPrinterGetOutputResolution(printer, d->settings, &resolution);
       
   362             } else
       
   363 #  endif
       
   364             {
       
   365                 PMPrinterGetPrinterResolution(printer, kPMCurrentValue, &resolution);
       
   366             }
       
   367 #else
       
   368             PMPrinterGetOutputResolution(printer, d->settings, &resolution);
       
   369 #endif
       
   370             val = (int)resolution.vRes;
       
   371             break;
       
   372         }
       
   373         //otherwise fall through
       
   374     }
       
   375     case QPaintDevice::PdmDpiY:
       
   376         val = (int)d->resolution.vRes;
       
   377         break;
       
   378     case QPaintDevice::PdmDpiX:
       
   379         val = (int)d->resolution.hRes;
       
   380         break;
       
   381     case QPaintDevice::PdmNumColors:
       
   382         val = (1 << metric(QPaintDevice::PdmDepth));
       
   383         break;
       
   384     case QPaintDevice::PdmDepth:
       
   385         val = 24;
       
   386         break;
       
   387     default:
       
   388         val = 0;
       
   389         qWarning("QPrinter::metric: Invalid metric command");
       
   390     }
       
   391     return val;
       
   392 }
       
   393 
       
   394 void QMacPrintEnginePrivate::initialize()
       
   395 {
       
   396     Q_Q(QMacPrintEngine);
       
   397 
       
   398 #ifndef QT_MAC_USE_COCOA
       
   399     Q_ASSERT(!session);
       
   400 #else
       
   401     Q_ASSERT(!printInfo);
       
   402 #endif
       
   403 
       
   404     if (!paintEngine)
       
   405         paintEngine = new QCoreGraphicsPaintEngine();
       
   406 
       
   407     q->gccaps = paintEngine->gccaps;
       
   408 
       
   409     fullPage = false;
       
   410 
       
   411 #ifndef QT_MAC_USE_COCOA
       
   412     if (PMCreateSession(&session) != 0)
       
   413         session = 0;
       
   414 #else
       
   415     QMacCocoaAutoReleasePool pool;
       
   416     printInfo = [[NSPrintInfo alloc] initWithDictionary:[NSDictionary dictionary]];
       
   417     session = static_cast<PMPrintSession>([printInfo PMPrintSession]);
       
   418 #endif
       
   419 
       
   420     PMPrinter printer;
       
   421     if (session && PMSessionGetCurrentPrinter(session, &printer) == noErr) {
       
   422         QList<QVariant> resolutions = supportedResolutions();
       
   423         if (!resolutions.isEmpty() && mode != QPrinter::ScreenResolution) {
       
   424             if (resolutions.count() > 1 && mode == QPrinter::HighResolution) {
       
   425                 int max = 0;
       
   426                 for (int i = 0; i < resolutions.count(); ++i) {
       
   427                     int value = resolutions.at(i).toInt();
       
   428                     if (value > max)
       
   429                         max = value;
       
   430                 }
       
   431                 resolution.hRes = resolution.vRes = max;
       
   432             } else {
       
   433                 resolution.hRes = resolution.vRes = resolutions.at(0).toInt();
       
   434             }
       
   435             if(resolution.hRes == 0)
       
   436                 resolution.hRes = resolution.vRes = 600;
       
   437         } else {
       
   438             resolution.hRes = resolution.vRes = qt_defaultDpi();
       
   439         }
       
   440     }
       
   441 
       
   442 #ifndef QT_MAC_USE_COCOA
       
   443     bool settingsInitialized = (settings != 0);
       
   444     bool settingsOK = !settingsInitialized ? PMCreatePrintSettings(&settings) == noErr : true;
       
   445     if (settingsOK && !settingsInitialized)
       
   446         settingsOK = PMSessionDefaultPrintSettings(session, settings) == noErr;
       
   447 
       
   448 
       
   449     bool formatInitialized = (format != 0);
       
   450     bool formatOK = !formatInitialized ? PMCreatePageFormat(&format) == noErr : true;
       
   451     if (formatOK) {
       
   452         if (!formatInitialized) {
       
   453             formatOK = PMSessionDefaultPageFormat(session, format) == noErr;
       
   454         }
       
   455         formatOK = PMSessionValidatePageFormat(session, format, kPMDontWantBoolean) == noErr;
       
   456     }
       
   457 #else
       
   458     settings = static_cast<PMPrintSettings>([printInfo PMPrintSettings]);
       
   459     format = static_cast<PMPageFormat>([printInfo PMPageFormat]);
       
   460 #endif
       
   461 
       
   462 #ifndef QT_MAC_USE_COCOA
       
   463     if (!settingsOK || !formatOK) {
       
   464         qWarning("QMacPrintEngine::initialize: Unable to initialize QPainter");
       
   465         state = QPrinter::Error;
       
   466     }
       
   467 #endif
       
   468 
       
   469     QHash<QMacPrintEngine::PrintEnginePropertyKey, QVariant>::const_iterator propC;
       
   470     for (propC = valueCache.constBegin(); propC != valueCache.constEnd(); propC++) {
       
   471         q->setProperty(propC.key(), propC.value());
       
   472     }
       
   473 }
       
   474 
       
   475 void QMacPrintEnginePrivate::releaseSession()
       
   476 {
       
   477 #ifndef QT_MAC_USE_COCOA
       
   478     if (shouldSuppressStatus()) {
       
   479 	PMSessionEndPageNoDialog(session);
       
   480 	PMSessionEndDocumentNoDialog(session);
       
   481     } else {
       
   482 	PMSessionEndPage(session);
       
   483 	PMSessionEndDocument(session);
       
   484     }
       
   485     PMRelease(session);
       
   486 #else
       
   487     PMSessionEndPageNoDialog(session);
       
   488     PMSessionEndDocumentNoDialog(session);
       
   489     [printInfo release];
       
   490 #endif
       
   491     printInfo = 0;
       
   492     session = 0;
       
   493 }
       
   494 
       
   495 bool QMacPrintEnginePrivate::newPage_helper()
       
   496 {
       
   497     Q_Q(QMacPrintEngine);
       
   498     Q_ASSERT(state == QPrinter::Active);
       
   499 
       
   500     if (PMSessionError(session) != noErr) {
       
   501         q->abort();
       
   502         return false;
       
   503     }
       
   504 
       
   505     // pop the stack of saved graphic states, in case we get the same
       
   506     // context back - either way, the stack count should be 0 when we
       
   507     // get the new one
       
   508     QCoreGraphicsPaintEngine *cgEngine = static_cast<QCoreGraphicsPaintEngine*>(paintEngine);
       
   509     while (cgEngine->d_func()->stackCount > 0)
       
   510         cgEngine->d_func()->restoreGraphicsState();
       
   511 
       
   512     OSStatus status =
       
   513 #ifndef QT_MAC_USE_COCOA
       
   514         shouldSuppressStatus() ? PMSessionBeginPageNoDialog(session, format, 0)
       
   515                                : PMSessionBeginPage(session, format, 0);
       
   516 #else
       
   517         PMSessionBeginPageNoDialog(session, format, 0);
       
   518 #endif
       
   519     if(status != noErr) {
       
   520         state = QPrinter::Error;
       
   521         return false;
       
   522     }
       
   523 
       
   524     QRect page = q->property(QPrintEngine::PPK_PageRect).toRect();
       
   525     QRect paper = q->property(QPrintEngine::PPK_PaperRect).toRect();
       
   526 
       
   527     CGContextRef cgContext;
       
   528     OSStatus err = noErr;
       
   529     err = PMSessionGetCGGraphicsContext(session, &cgContext);
       
   530     if(err != noErr) {
       
   531         qWarning("QMacPrintEngine::newPage: Cannot retrieve CoreGraphics context: %ld", long(err));
       
   532         state = QPrinter::Error;
       
   533         return false;
       
   534     }
       
   535     cgEngine->d_func()->hd = cgContext;
       
   536 
       
   537     // Set the resolution as a scaling ration of 72 (the default).
       
   538     CGContextScaleCTM(cgContext, 72 / resolution.hRes, 72 / resolution.vRes);
       
   539 
       
   540     CGContextScaleCTM(cgContext, 1, -1);
       
   541     CGContextTranslateCTM(cgContext, 0, -paper.height());
       
   542     if (!fullPage)
       
   543         CGContextTranslateCTM(cgContext, page.x() - paper.x(), page.y() - paper.y());
       
   544     cgEngine->d_func()->orig_xform = CGContextGetCTM(cgContext);
       
   545     cgEngine->d_func()->setClip(0);
       
   546     cgEngine->state->dirtyFlags = QPaintEngine::DirtyFlag(QPaintEngine::AllDirty
       
   547 							  & ~(QPaintEngine::DirtyClipEnabled
       
   548 							      | QPaintEngine::DirtyClipRegion
       
   549 							      | QPaintEngine::DirtyClipPath));
       
   550     if (cgEngine->painter()->hasClipping())
       
   551         cgEngine->state->dirtyFlags |= QPaintEngine::DirtyClipEnabled;
       
   552     cgEngine->syncState();
       
   553     return true;
       
   554 }
       
   555 
       
   556 
       
   557 void QMacPrintEngine::updateState(const QPaintEngineState &state)
       
   558 {
       
   559     d_func()->paintEngine->updateState(state);
       
   560 }
       
   561 
       
   562 void QMacPrintEngine::drawRects(const QRectF *r, int num)
       
   563 {
       
   564     Q_D(QMacPrintEngine);
       
   565     Q_ASSERT(d->state == QPrinter::Active);
       
   566     d->paintEngine->drawRects(r, num);
       
   567 }
       
   568 
       
   569 void QMacPrintEngine::drawPoints(const QPointF *points, int pointCount)
       
   570 {
       
   571     Q_D(QMacPrintEngine);
       
   572     Q_ASSERT(d->state == QPrinter::Active);
       
   573     d->paintEngine->drawPoints(points, pointCount);
       
   574 }
       
   575 
       
   576 void QMacPrintEngine::drawEllipse(const QRectF &r)
       
   577 {
       
   578     Q_D(QMacPrintEngine);
       
   579     Q_ASSERT(d->state == QPrinter::Active);
       
   580     d->paintEngine->drawEllipse(r);
       
   581 }
       
   582 
       
   583 void QMacPrintEngine::drawLines(const QLineF *lines, int lineCount)
       
   584 {
       
   585     Q_D(QMacPrintEngine);
       
   586     Q_ASSERT(d->state == QPrinter::Active);
       
   587     d->paintEngine->drawLines(lines, lineCount);
       
   588 }
       
   589 
       
   590 void QMacPrintEngine::drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode)
       
   591 {
       
   592     Q_D(QMacPrintEngine);
       
   593     Q_ASSERT(d->state == QPrinter::Active);
       
   594     d->paintEngine->drawPolygon(points, pointCount, mode);
       
   595 }
       
   596 
       
   597 void QMacPrintEngine::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr)
       
   598 {
       
   599     Q_D(QMacPrintEngine);
       
   600     Q_ASSERT(d->state == QPrinter::Active);
       
   601     d->paintEngine->drawPixmap(r, pm, sr);
       
   602 }
       
   603 
       
   604 void QMacPrintEngine::drawImage(const QRectF &r, const QImage &pm, const QRectF &sr, Qt::ImageConversionFlags flags)
       
   605 {
       
   606     Q_D(QMacPrintEngine);
       
   607     Q_ASSERT(d->state == QPrinter::Active);
       
   608     d->paintEngine->drawImage(r, pm, sr, flags);
       
   609 }
       
   610 
       
   611 void QMacPrintEngine::drawTextItem(const QPointF &p, const QTextItem &ti)
       
   612 {
       
   613     Q_D(QMacPrintEngine);
       
   614     Q_ASSERT(d->state == QPrinter::Active);
       
   615     d->paintEngine->drawTextItem(p, ti);
       
   616 }
       
   617 
       
   618 void QMacPrintEngine::drawTiledPixmap(const QRectF &dr, const QPixmap &pixmap, const QPointF &sr)
       
   619 {
       
   620     Q_D(QMacPrintEngine);
       
   621     Q_ASSERT(d->state == QPrinter::Active);
       
   622     d->paintEngine->drawTiledPixmap(dr, pixmap, sr);
       
   623 }
       
   624 
       
   625 void QMacPrintEngine::drawPath(const QPainterPath &path)
       
   626 {
       
   627     Q_D(QMacPrintEngine);
       
   628     Q_ASSERT(d->state == QPrinter::Active);
       
   629     d->paintEngine->drawPath(path);
       
   630 }
       
   631 
       
   632 
       
   633 void QMacPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &value)
       
   634 {
       
   635     Q_D(QMacPrintEngine);
       
   636 
       
   637     d->valueCache.insert(key, value);
       
   638     if (!d->session)
       
   639         return;
       
   640 
       
   641     switch (key) {
       
   642     case PPK_CollateCopies:
       
   643         break;
       
   644     case PPK_ColorMode:
       
   645         break;
       
   646     case PPK_Creator:
       
   647         break;
       
   648     case PPK_DocumentName:
       
   649         break;
       
   650     case PPK_PageOrder:
       
   651         break;
       
   652     case PPK_PaperSource:
       
   653         break;
       
   654     case PPK_SelectionOption:
       
   655         break;
       
   656     case PPK_Resolution:  {
       
   657         PMPrinter printer;
       
   658         UInt32 count;
       
   659         if (PMSessionGetCurrentPrinter(d->session, &printer) != noErr)
       
   660             break;
       
   661         if (PMPrinterGetPrinterResolutionCount(printer, &count) != noErr)
       
   662             break;
       
   663         PMResolution resolution = { 0.0, 0.0 };
       
   664         PMResolution bestResolution = { 0.0, 0.0 };
       
   665         int dpi = value.toInt();
       
   666         int bestDistance = INT_MAX;
       
   667         for (UInt32 i = 1; i <= count; ++i) {  // Yes, it starts at 1
       
   668             if (PMPrinterGetIndexedPrinterResolution(printer, i, &resolution) == noErr) {
       
   669                 if (dpi == int(resolution.hRes)) {
       
   670                     bestResolution = resolution;
       
   671                     break;
       
   672                 } else {
       
   673                     int distance = qAbs(dpi - int(resolution.hRes));
       
   674                     if (distance < bestDistance) {
       
   675                         bestDistance = distance;
       
   676                         bestResolution = resolution;
       
   677                     }
       
   678                 }
       
   679             }
       
   680         }
       
   681         PMSessionValidatePageFormat(d->session, d->format, kPMDontWantBoolean);
       
   682         break;
       
   683     }
       
   684 
       
   685     case PPK_FullPage:
       
   686         d->fullPage = value.toBool();
       
   687         break;
       
   688     case PPK_NumberOfCopies:
       
   689         PMSetCopies(d->settings, value.toInt(), false);
       
   690         break;
       
   691     case PPK_Orientation: {
       
   692         if (d->state == QPrinter::Active) {
       
   693             qWarning("QMacPrintEngine::setOrientation: Orientation cannot be changed during a print job, ignoring change");
       
   694         } else {
       
   695             QPrinter::Orientation newOrientation = QPrinter::Orientation(value.toInt());
       
   696             if (d->hasCustomPaperSize && (d->orient != newOrientation))
       
   697                 d->customSize = QSizeF(d->customSize.height(), d->customSize.width());
       
   698             d->orient = newOrientation;
       
   699             PMOrientation o = d->orient == QPrinter::Portrait ? kPMPortrait : kPMLandscape;
       
   700             PMSetOrientation(d->format, o, false);
       
   701             PMSessionValidatePageFormat(d->session, d->format, kPMDontWantBoolean);
       
   702         }
       
   703         break; }
       
   704     case PPK_OutputFileName:
       
   705         d->outputFilename = value.toString();
       
   706         break;
       
   707     case PPK_PaperSize:
       
   708         d->setPaperSize(QPrinter::PaperSize(value.toInt()));
       
   709         break;
       
   710     case PPK_PrinterName: {
       
   711         bool printerNameSet = false;
       
   712         OSStatus status = noErr;
       
   713         QCFType<CFArrayRef> printerList;
       
   714         status = PMServerCreatePrinterList(kPMServerLocal, &printerList);
       
   715         if (status == noErr) {
       
   716             CFIndex count = CFArrayGetCount(printerList);
       
   717             for (CFIndex i=0; i<count; ++i) {
       
   718                 PMPrinter printer = static_cast<PMPrinter>(const_cast<void *>(CFArrayGetValueAtIndex(printerList, i)));
       
   719                 QString name = QCFString::toQString(PMPrinterGetName(printer));
       
   720                 if (name == value.toString()) {
       
   721                     status = PMSessionSetCurrentPMPrinter(d->session, printer);
       
   722                     printerNameSet = true;
       
   723                     break;
       
   724                 }
       
   725             }
       
   726         }
       
   727         if (status != noErr)
       
   728             qWarning("QMacPrintEngine::setPrinterName: Error setting printer: %ld", long(status));
       
   729 	if (!printerNameSet) {
       
   730             qWarning("QMacPrintEngine::setPrinterName: Failed to set printer named '%s'.", qPrintable(value.toString()));
       
   731             d->releaseSession();
       
   732             d->state = QPrinter::Idle;
       
   733         }
       
   734         break; }
       
   735     case PPK_SuppressSystemPrintStatus:
       
   736         d->suppressStatus = value.toBool();
       
   737         break;
       
   738     case PPK_CustomPaperSize:
       
   739     {
       
   740         PMOrientation orientation;
       
   741         PMGetOrientation(d->format, &orientation);
       
   742         d->hasCustomPaperSize = true;
       
   743         d->customSize = value.toSizeF();
       
   744         if (orientation != kPMPortrait)
       
   745             d->customSize = QSizeF(d->customSize.height(), d->customSize.width());
       
   746         break;
       
   747     }
       
   748     case PPK_PageMargins:
       
   749     {
       
   750         QList<QVariant> margins(value.toList());
       
   751         Q_ASSERT(margins.size() == 4);
       
   752         d->leftMargin = margins.at(0).toDouble();
       
   753         d->topMargin = margins.at(1).toDouble();
       
   754         d->rightMargin = margins.at(2).toDouble();
       
   755         d->bottomMargin = margins.at(3).toDouble();
       
   756         d->hasCustomPageMargins = true;
       
   757         break;
       
   758     }
       
   759 
       
   760     default:
       
   761         break;
       
   762     }
       
   763 }
       
   764 
       
   765 QVariant QMacPrintEngine::property(PrintEnginePropertyKey key) const
       
   766 {
       
   767     Q_D(const QMacPrintEngine);
       
   768     QVariant ret;
       
   769 
       
   770     if (!d->session && d->valueCache.contains(key))
       
   771         return *d->valueCache.find(key);
       
   772 
       
   773     switch (key) {
       
   774     case PPK_CollateCopies:
       
   775         ret = false;
       
   776         break;
       
   777     case PPK_ColorMode:
       
   778         ret = QPrinter::Color;
       
   779         break;
       
   780     case PPK_Creator:
       
   781         break;
       
   782     case PPK_DocumentName:
       
   783         break;
       
   784     case PPK_FullPage:
       
   785         ret = d->fullPage;
       
   786         break;
       
   787     case PPK_NumberOfCopies:
       
   788         ret = 1;
       
   789         break;
       
   790     case PPK_Orientation:
       
   791         PMOrientation orientation;
       
   792         PMGetOrientation(d->format, &orientation);
       
   793         ret = orientation == kPMPortrait ? QPrinter::Portrait : QPrinter::Landscape;
       
   794         break;
       
   795     case PPK_OutputFileName:
       
   796         ret = d->outputFilename;
       
   797         break;
       
   798     case PPK_PageOrder:
       
   799         break;
       
   800     case PPK_PaperSource:
       
   801         break;
       
   802     case PPK_PageRect: {
       
   803         // PageRect is returned in device pixels
       
   804         QRect r;
       
   805         PMRect macrect, macpaper;
       
   806         qreal hRatio = d->resolution.hRes / 72;
       
   807         qreal vRatio = d->resolution.vRes / 72;
       
   808         if (d->hasCustomPaperSize) {
       
   809             r = QRect(0, 0, qRound(d->customSize.width() * hRatio), qRound(d->customSize.height() * vRatio));
       
   810             if (d->hasCustomPageMargins) {
       
   811                 r.adjust(qRound(d->leftMargin * hRatio), qRound(d->topMargin * vRatio), 
       
   812                          -qRound(d->rightMargin * hRatio), -qRound(d->bottomMargin * vRatio));
       
   813             } else {
       
   814                 QList<QVariant> margins = property(QPrintEngine::PPK_PageMargins).toList();
       
   815                 r.adjust(qRound(margins.at(0).toDouble() * hRatio),
       
   816                          qRound(margins.at(1).toDouble() * vRatio),
       
   817                          -qRound(margins.at(2).toDouble() * hRatio),
       
   818                          -qRound(margins.at(3).toDouble()) * vRatio);
       
   819             }
       
   820         } else if (PMGetAdjustedPageRect(d->format, &macrect) == noErr
       
   821                    && PMGetAdjustedPaperRect(d->format, &macpaper) == noErr)
       
   822         {
       
   823             if (d->fullPage || d->hasCustomPageMargins) {
       
   824                 r.setCoords(int(macpaper.left * hRatio), int(macpaper.top * vRatio),
       
   825                             int(macpaper.right * hRatio), int(macpaper.bottom * vRatio));
       
   826                 r.translate(-r.x(), -r.y());
       
   827                 if (d->hasCustomPageMargins) {
       
   828                     r.adjust(qRound(d->leftMargin * hRatio), qRound(d->topMargin * vRatio),
       
   829                              -qRound(d->rightMargin * hRatio), -qRound(d->bottomMargin * vRatio));
       
   830                 }
       
   831             } else {
       
   832                 r.setCoords(int(macrect.left * hRatio), int(macrect.top * vRatio),
       
   833                             int(macrect.right * hRatio), int(macrect.bottom * vRatio));
       
   834                 r.translate(int(-macpaper.left * hRatio), int(-macpaper.top * vRatio));
       
   835             } 
       
   836         }
       
   837         ret = r;
       
   838         break; }
       
   839     case PPK_PaperSize:
       
   840         ret = d->paperSize();
       
   841         break;
       
   842     case PPK_PaperRect: {
       
   843         QRect r;
       
   844         PMRect macrect;
       
   845         if (d->hasCustomPaperSize) {
       
   846             r = QRect(0, 0, qRound(d->customSize.width()), qRound(d->customSize.height()));
       
   847         } else if (PMGetAdjustedPaperRect(d->format, &macrect) == noErr) {
       
   848             qreal hRatio = d->resolution.hRes / 72;
       
   849             qreal vRatio = d->resolution.vRes / 72;
       
   850             r.setCoords(int(macrect.left * hRatio), int(macrect.top * vRatio),
       
   851                         int(macrect.right * hRatio), int(macrect.bottom * vRatio));
       
   852             r.translate(-r.x(), -r.y());
       
   853         }
       
   854         ret = r;
       
   855         break; }
       
   856     case PPK_PrinterName: {
       
   857         PMPrinter printer;
       
   858         OSStatus status = PMSessionGetCurrentPrinter(d->session, &printer);
       
   859         if (status != noErr)
       
   860             qWarning("QMacPrintEngine::printerName: Failed getting current PMPrinter: %ld", long(status));
       
   861         if (printer)
       
   862             ret = QCFString::toQString(PMPrinterGetName(printer));
       
   863         break; }
       
   864     case PPK_Resolution: {
       
   865         ret = d->resolution.hRes;
       
   866         break;
       
   867     }
       
   868     case PPK_SupportedResolutions:
       
   869         ret = d->supportedResolutions();
       
   870         break;
       
   871     case PPK_CustomPaperSize:
       
   872         ret = d->customSize;
       
   873         break;
       
   874     case PPK_PageMargins:
       
   875     {
       
   876         QList<QVariant> margins;
       
   877         if (d->hasCustomPageMargins) {
       
   878             margins << d->leftMargin << d->topMargin
       
   879                     << d->rightMargin << d->bottomMargin;
       
   880         } else {
       
   881             PMPaperMargins paperMargins;
       
   882             PMPaper paper;
       
   883             PMGetPageFormatPaper(d->format, &paper);
       
   884             PMPaperGetMargins(paper, &paperMargins);
       
   885             margins << paperMargins.left << paperMargins.top
       
   886                     << paperMargins.right << paperMargins.bottom;
       
   887         }
       
   888         ret = margins;
       
   889         break;
       
   890     }
       
   891     default:
       
   892         break;
       
   893     }
       
   894     return ret;
       
   895 }
       
   896 
       
   897 QT_END_NAMESPACE
       
   898 
       
   899 #endif // QT_NO_PRINTER