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

source code of qtbase/src/printsupport/kernel/qprintengine_pdf.cpp