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

Last change on this file since 719 was 651, checked in by Dmitry A. Kuminov, 16 years ago

trunk: Merged in qt 4.6.2 sources.

File size: 30.6 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2010 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 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
126QPaintEngine *
127QMacPrintEngine::paintEngine() const
128{
129 return d_func()->paintEngine;
130}
131
132Qt::HANDLE QMacPrintEngine::handle() const
133{
134 QCoreGraphicsPaintEngine *cgEngine = static_cast<QCoreGraphicsPaintEngine*>(paintEngine());
135 return cgEngine->d_func()->hd;
136}
137
138QMacPrintEnginePrivate::~QMacPrintEnginePrivate()
139{
140#ifdef QT_MAC_USE_COCOA
141 [printInfo release];
142#endif
143 delete paintEngine;
144}
145
146void 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
178QPrinter::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
192QList<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
231bool 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
241QPrinter::PrinterState QMacPrintEngine::printerState() const
242{
243 return d_func()->state;
244}
245
246bool 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
271bool 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
281static 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
297static 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
314int 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
394void 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
475void 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
495bool 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
557void QMacPrintEngine::updateState(const QPaintEngineState &state)
558{
559 d_func()->paintEngine->updateState(state);
560}
561
562void 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
569void 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
576void QMacPrintEngine::drawEllipse(const QRectF &r)
577{
578 Q_D(QMacPrintEngine);
579 Q_ASSERT(d->state == QPrinter::Active);
580 d->paintEngine->drawEllipse(r);
581}
582
583void 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
590void 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
597void 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
604void 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
611void 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
618void 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
625void 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
633void 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
765QVariant 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
897QT_END_NAMESPACE
898
899#endif // QT_NO_PRINTER
Note: See TracBrowser for help on using the repository browser.