source: trunk/src/gui/painting/qprintengine_mac.mm@ 1168

Last change on this file since 1168 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

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