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

Last change on this file since 811 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: