|
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, ¯ect) == 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, ¯ect) == 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 |