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
59QT_BEGIN_NAMESPACE
60
61QPdfPrintEngine::QPdfPrintEngine(QPrinter::PrinterMode m, QPdfEngine::PdfVersion version)
62 : QPdfEngine(*new QPdfPrintEnginePrivate(m))
63{
64 state = QPrinter::Idle;
65
66 setPdfVersion(version);
67}
68
69QPdfPrintEngine::QPdfPrintEngine(QPdfPrintEnginePrivate &p)
70 : QPdfEngine(p)
71{
72 state = QPrinter::Idle;
73}
74
75QPdfPrintEngine::~QPdfPrintEngine()
76{
77}
78
79bool 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
92bool 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
104bool QPdfPrintEngine::newPage()
105{
106 return QPdfEngine::newPage();
107}
108
109int QPdfPrintEngine::metric(QPaintDevice::PaintDeviceMetric m) const
110{
111 return QPdfEngine::metric(m);
112}
113
114void 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
241QVariant 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
352bool 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
369void 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
387QPdfPrintEnginePrivate::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
402QPdfPrintEnginePrivate::~QPdfPrintEnginePrivate()
403{
404}
405
406QT_END_NAMESPACE
407
408#endif // QT_NO_PRINTER
409