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 |
|
---|
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 | // 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 |
|
---|
129 | QPaintEngine *
|
---|
130 | QMacPrintEngine::paintEngine() const
|
---|
131 | {
|
---|
132 | return d_func()->paintEngine;
|
---|
133 | }
|
---|
134 |
|
---|
135 | Qt::HANDLE QMacPrintEngine::handle() const
|
---|
136 | {
|
---|
137 | QCoreGraphicsPaintEngine *cgEngine = static_cast<QCoreGraphicsPaintEngine*>(paintEngine());
|
---|
138 | return cgEngine->d_func()->hd;
|
---|
139 | }
|
---|
140 |
|
---|
141 | QMacPrintEnginePrivate::~QMacPrintEnginePrivate()
|
---|
142 | {
|
---|
143 | #ifdef QT_MAC_USE_COCOA
|
---|
144 | [printInfo release];
|
---|
145 | #endif
|
---|
146 | delete paintEngine;
|
---|
147 | }
|
---|
148 |
|
---|
149 | void 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 |
|
---|
181 | QPrinter::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 |
|
---|
195 | QList<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 |
|
---|
234 | bool 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 |
|
---|
244 | QPrinter::PrinterState QMacPrintEngine::printerState() const
|
---|
245 | {
|
---|
246 | return d_func()->state;
|
---|
247 | }
|
---|
248 |
|
---|
249 | bool 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 |
|
---|
274 | bool 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 |
|
---|
284 | static 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 |
|
---|
300 | static 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 |
|
---|
317 | int 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 |
|
---|
397 | void 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 |
|
---|
478 | void 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 |
|
---|
498 | bool 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 |
|
---|
560 | void QMacPrintEngine::updateState(const QPaintEngineState &state)
|
---|
561 | {
|
---|
562 | d_func()->paintEngine->updateState(state);
|
---|
563 | }
|
---|
564 |
|
---|
565 | void 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 |
|
---|
572 | void 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 |
|
---|
579 | void QMacPrintEngine::drawEllipse(const QRectF &r)
|
---|
580 | {
|
---|
581 | Q_D(QMacPrintEngine);
|
---|
582 | Q_ASSERT(d->state == QPrinter::Active);
|
---|
583 | d->paintEngine->drawEllipse(r);
|
---|
584 | }
|
---|
585 |
|
---|
586 | void 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 |
|
---|
593 | void 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 |
|
---|
600 | void 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 |
|
---|
607 | void 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 |
|
---|
614 | void 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 |
|
---|
621 | void 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 |
|
---|
628 | void 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 |
|
---|
636 | void 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 |
|
---|
769 | QVariant 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, ¯ect) == 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, ¯ect) == 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 |
|
---|
910 | QT_END_NAMESPACE
|
---|
911 |
|
---|
912 | #endif // QT_NO_PRINTER
|
---|