1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39
40 #include "qprintengine_pdf_p.h"
41
42 #ifndef QT_NO_PRINTER
43
44 #include <qiodevice.h>
45 #include <qfile.h>
46 #include <qdebug.h>
47 #include <qbuffer.h>
48 #include "qprinterinfo.h"
49 #include <QtGui/qpagelayout.h>
50
51 #ifdef Q_OS_UNIX
52 #include "private/qcore_unix_p.h" // overrides QT_OPEN
53 #endif
54
55 #ifdef Q_OS_WIN
56 #include <io.h> // _close.
57 #endif
58
59 QT_BEGIN_NAMESPACE
60
QPdfPrintEngine(QPrinter::PrinterMode m,QPdfEngine::PdfVersion version)61 QPdfPrintEngine::QPdfPrintEngine(QPrinter::PrinterMode m, QPdfEngine::PdfVersion version)
62 : QPdfEngine(*new QPdfPrintEnginePrivate(m))
63 {
64 state = QPrinter::Idle;
65
66 setPdfVersion(version);
67 }
68
QPdfPrintEngine(QPdfPrintEnginePrivate & p)69 QPdfPrintEngine::QPdfPrintEngine(QPdfPrintEnginePrivate &p)
70 : QPdfEngine(p)
71 {
72 state = QPrinter::Idle;
73 }
74
~QPdfPrintEngine()75 QPdfPrintEngine::~QPdfPrintEngine()
76 {
77 }
78
begin(QPaintDevice * pdev)79 bool QPdfPrintEngine::begin(QPaintDevice *pdev)
80 {
81 Q_D(QPdfPrintEngine);
82
83 if (!d->openPrintDevice()) {
84 state = QPrinter::Error;
85 return false;
86 }
87 state = QPrinter::Active;
88
89 return QPdfEngine::begin(pdev);
90 }
91
end()92 bool QPdfPrintEngine::end()
93 {
94 Q_D(QPdfPrintEngine);
95
96 QPdfEngine::end();
97
98 d->closePrintDevice();
99 state = QPrinter::Idle;
100
101 return true;
102 }
103
newPage()104 bool QPdfPrintEngine::newPage()
105 {
106 return QPdfEngine::newPage();
107 }
108
metric(QPaintDevice::PaintDeviceMetric m) const109 int QPdfPrintEngine::metric(QPaintDevice::PaintDeviceMetric m) const
110 {
111 return QPdfEngine::metric(m);
112 }
113
setProperty(PrintEnginePropertyKey key,const QVariant & value)114 void QPdfPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &value)
115 {
116 Q_D(QPdfPrintEngine);
117
118 switch (int(key)) {
119
120 // The following keys are properties or derived values and so cannot be set
121 case PPK_PageRect:
122 break;
123 case PPK_PaperRect:
124 break;
125 case PPK_PaperSources:
126 break;
127 case PPK_SupportsMultipleCopies:
128 break;
129 case PPK_SupportedResolutions:
130 break;
131
132 // The following keys are settings that are unsupported by the PDF PrintEngine
133 case PPK_CustomBase:
134 break;
135 case PPK_Duplex:
136 break;
137
138 // The following keys are properties and settings that are supported by the PDF PrintEngine
139 case PPK_CollateCopies:
140 d->collate = value.toBool();
141 break;
142 case PPK_ColorMode:
143 d->grayscale = (QPrinter::ColorMode(value.toInt()) == QPrinter::GrayScale);
144 break;
145 case PPK_Creator:
146 d->creator = value.toString();
147 break;
148 case PPK_DocumentName:
149 d->title = value.toString();
150 break;
151 case PPK_FullPage:
152 if (value.toBool())
153 d->m_pageLayout.setMode(QPageLayout::FullPageMode);
154 else
155 d->m_pageLayout.setMode(QPageLayout::StandardMode);
156 break;
157 case PPK_CopyCount:
158 case PPK_NumberOfCopies:
159 d->copies = value.toInt();
160 break;
161 case PPK_Orientation:
162 d->m_pageLayout.setOrientation(QPageLayout::Orientation(value.toInt()));
163 break;
164 case PPK_OutputFileName:
165 d->outputFileName = value.toString();
166 break;
167 case PPK_PageOrder:
168 d->pageOrder = QPrinter::PageOrder(value.toInt());
169 break;
170 case PPK_PageSize: {
171 QPageSize pageSize = QPageSize(QPageSize::PageSizeId(value.toInt()));
172 if (pageSize.isValid())
173 d->m_pageLayout.setPageSize(pageSize);
174 break;
175 }
176 case PPK_PaperName: {
177 QString name = value.toString();
178 for (int i = 0; i <= QPageSize::LastPageSize; ++i) {
179 QPageSize pageSize = QPageSize(QPageSize::PageSizeId(i));
180 if (name == pageSize.name()) {
181 d->m_pageLayout.setPageSize(pageSize);
182 break;
183 }
184 }
185 break;
186 }
187 case PPK_WindowsPageSize:
188 d->m_pageLayout.setPageSize(QPageSize(QPageSize::id(value.toInt())));
189 break;
190 case PPK_PaperSource:
191 d->paperSource = QPrinter::PaperSource(value.toInt());
192 break;
193 case PPK_PrinterName:
194 d->printerName = value.toString();
195 break;
196 case PPK_PrinterProgram:
197 d->printProgram = value.toString();
198 break;
199 case PPK_Resolution:
200 d->resolution = value.toInt();
201 break;
202 case PPK_SelectionOption:
203 d->selectionOption = value.toString();
204 break;
205 case PPK_FontEmbedding:
206 d->embedFonts = value.toBool();
207 break;
208 case PPK_CustomPaperSize:
209 d->m_pageLayout.setPageSize(QPageSize(value.toSizeF(), QPageSize::Point));
210 break;
211 case PPK_PageMargins: {
212 QList<QVariant> margins(value.toList());
213 Q_ASSERT(margins.size() == 4);
214 d->m_pageLayout.setUnits(QPageLayout::Point);
215 d->m_pageLayout.setMargins(QMarginsF(margins.at(0).toReal(), margins.at(1).toReal(),
216 margins.at(2).toReal(), margins.at(3).toReal()));
217 break;
218 }
219 case PPK_QPageSize: {
220 QPageSize pageSize = qvariant_cast<QPageSize>(value);
221 if (pageSize.isValid())
222 d->m_pageLayout.setPageSize(pageSize);
223 break;
224 }
225 case PPK_QPageMargins: {
226 QPair<QMarginsF, QPageLayout::Unit> pair = qvariant_cast<QPair<QMarginsF, QPageLayout::Unit> >(value);
227 d->m_pageLayout.setUnits(pair.second);
228 d->m_pageLayout.setMargins(pair.first);
229 break;
230 }
231 case PPK_QPageLayout: {
232 QPageLayout pageLayout = qvariant_cast<QPageLayout>(value);
233 if (pageLayout.isValid())
234 d->m_pageLayout = pageLayout;
235 break;
236 }
237 // No default so that compiler will complain if new keys added and not handled in this engine
238 }
239 }
240
property(PrintEnginePropertyKey key) const241 QVariant QPdfPrintEngine::property(PrintEnginePropertyKey key) const
242 {
243 Q_D(const QPdfPrintEngine);
244
245 QVariant ret;
246 switch (int(key)) {
247
248 // The following keys are settings that are unsupported by the PDF PrintEngine
249 // Return sensible default values to ensure consistent behavior across platforms
250 case PPK_CustomBase:
251 case PPK_Duplex:
252 // Special case, leave null
253 break;
254
255 // The following keys are properties and settings that are supported by the PDF PrintEngine
256 case PPK_CollateCopies:
257 ret = d->collate;
258 break;
259 case PPK_ColorMode:
260 ret = d->grayscale ? QPrinter::GrayScale : QPrinter::Color;
261 break;
262 case PPK_Creator:
263 ret = d->creator;
264 break;
265 case PPK_DocumentName:
266 ret = d->title;
267 break;
268 case PPK_FullPage:
269 ret = d->m_pageLayout.mode() == QPageLayout::FullPageMode;
270 break;
271 case PPK_CopyCount:
272 ret = d->copies;
273 break;
274 case PPK_SupportsMultipleCopies:
275 ret = false;
276 break;
277 case PPK_NumberOfCopies:
278 ret = d->copies;
279 break;
280 case PPK_Orientation:
281 ret = d->m_pageLayout.orientation();
282 break;
283 case PPK_OutputFileName:
284 ret = d->outputFileName;
285 break;
286 case PPK_PageOrder:
287 ret = d->pageOrder;
288 break;
289 case PPK_PageSize:
290 ret = d->m_pageLayout.pageSize().id();
291 break;
292 case PPK_PaperName:
293 ret = d->m_pageLayout.pageSize().name();
294 break;
295 case PPK_WindowsPageSize:
296 ret = d->m_pageLayout.pageSize().windowsId();
297 break;
298 case PPK_PaperSource:
299 ret = d->paperSource;
300 break;
301 case PPK_PrinterName:
302 ret = d->printerName;
303 break;
304 case PPK_PrinterProgram:
305 ret = d->printProgram;
306 break;
307 case PPK_Resolution:
308 ret = d->resolution;
309 break;
310 case PPK_SupportedResolutions:
311 ret = QList<QVariant>() << 72;
312 break;
313 case PPK_PaperRect:
314 ret = d->m_pageLayout.fullRectPixels(d->resolution);
315 break;
316 case PPK_PageRect:
317 ret = d->m_pageLayout.paintRectPixels(d->resolution);
318 break;
319 case PPK_SelectionOption:
320 ret = d->selectionOption;
321 break;
322 case PPK_FontEmbedding:
323 ret = d->embedFonts;
324 break;
325 case PPK_CustomPaperSize:
326 ret = d->m_pageLayout.fullRectPoints().size();
327 break;
328 case PPK_PageMargins: {
329 QList<QVariant> list;
330 QMarginsF margins = d->m_pageLayout.margins(QPageLayout::Point);
331 list << margins.left() << margins.top() << margins.right() << margins.bottom();
332 ret = list;
333 break;
334 }
335 case PPK_QPageSize:
336 ret.setValue(d->m_pageLayout.pageSize());
337 break;
338 case PPK_QPageMargins: {
339 QPair<QMarginsF, QPageLayout::Unit> pair = qMakePair(d->m_pageLayout.margins(), d->m_pageLayout.units());
340 ret.setValue(pair);
341 break;
342 }
343 case PPK_QPageLayout:
344 ret.setValue(d->m_pageLayout);
345 break;
346 // No default so that compiler will complain if new keys added and not handled in this engine
347 }
348 return ret;
349 }
350
351
openPrintDevice()352 bool QPdfPrintEnginePrivate::openPrintDevice()
353 {
354 if (outDevice)
355 return false;
356
357 if (!outputFileName.isEmpty()) {
358 QFile *file = new QFile(outputFileName);
359 if (! file->open(QFile::WriteOnly|QFile::Truncate)) {
360 delete file;
361 return false;
362 }
363 outDevice = file;
364 }
365
366 return true;
367 }
368
closePrintDevice()369 void QPdfPrintEnginePrivate::closePrintDevice()
370 {
371 if (outDevice) {
372 outDevice->close();
373 if (fd >= 0)
374 #if defined(Q_OS_WIN) && defined(Q_CC_MSVC)
375 ::_close(fd);
376 #else
377 ::close(fd);
378 #endif
379 fd = -1;
380 delete outDevice;
381 outDevice = nullptr;
382 }
383 }
384
385
386
QPdfPrintEnginePrivate(QPrinter::PrinterMode m)387 QPdfPrintEnginePrivate::QPdfPrintEnginePrivate(QPrinter::PrinterMode m)
388 : QPdfEnginePrivate(),
389 collate(true),
390 copies(1),
391 pageOrder(QPrinter::FirstPageFirst),
392 paperSource(QPrinter::Auto),
393 fd(-1)
394 {
395 resolution = 72;
396 if (m == QPrinter::HighResolution)
397 resolution = 1200;
398 else if (m == QPrinter::ScreenResolution)
399 resolution = qt_defaultDpi();
400 }
401
~QPdfPrintEnginePrivate()402 QPdfPrintEnginePrivate::~QPdfPrintEnginePrivate()
403 {
404 }
405
406 QT_END_NAMESPACE
407
408 #endif // QT_NO_PRINTER
409