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