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 <qpdfwriter.h>
41
42#ifndef QT_NO_PDF
43
44#include "qpagedpaintdevice_p.h"
45#include <QtCore/private/qobject_p.h>
46#include "private/qpdf_p.h"
47#include <QtCore/qfile.h>
48
49QT_BEGIN_NAMESPACE
50
51class QPdfWriterPrivate : public QObjectPrivate
52{
53public:
54 QPdfWriterPrivate()
55 : QObjectPrivate()
56 {
57 engine = new QPdfEngine();
58 output = nullptr;
59 pdfVersion = QPdfWriter::PdfVersion_1_4;
60 }
61 ~QPdfWriterPrivate()
62 {
63 delete engine;
64 delete output;
65 }
66
67 QPdfEngine *engine;
68 QFile *output;
69 QPdfWriter::PdfVersion pdfVersion;
70};
71
72class QPdfPagedPaintDevicePrivate : public QPagedPaintDevicePrivate
73{
74public:
75 QPdfPagedPaintDevicePrivate(QPdfWriterPrivate *d)
76 : QPagedPaintDevicePrivate(), pd(d)
77 {}
78
79 ~QPdfPagedPaintDevicePrivate()
80 {}
81
82 bool setPageLayout(const QPageLayout &newPageLayout) override
83 {
84 // Try to set the paint engine page layout
85 pd->engine->setPageLayout(newPageLayout);
86 return pageLayout().isEquivalentTo(other: newPageLayout);
87 }
88
89 bool setPageSize(const QPageSize &pageSize) override
90 {
91 // Try to set the paint engine page size
92 pd->engine->setPageSize(pageSize);
93 return pageLayout().pageSize().isEquivalentTo(other: pageSize);
94 }
95
96 bool setPageOrientation(QPageLayout::Orientation orientation) override
97 {
98 // Set the print engine value
99 pd->engine->setPageOrientation(orientation);
100 return pageLayout().orientation() == orientation;
101 }
102
103 bool setPageMargins(const QMarginsF &margins, QPageLayout::Unit units) override
104 {
105 // Try to set engine margins
106 pd->engine->setPageMargins(margins, units);
107 return pageLayout().margins() == margins && pageLayout().units() == units;
108 }
109
110 QPageLayout pageLayout() const override
111 {
112 return pd->engine->pageLayout();
113 }
114
115 QPdfWriterPrivate *pd;
116};
117
118/*! \class QPdfWriter
119 \inmodule QtGui
120
121 \brief The QPdfWriter class is a class to generate PDFs
122 that can be used as a paint device.
123
124 \ingroup painting
125
126 QPdfWriter generates PDF out of a series of drawing commands using QPainter.
127 The newPage() method can be used to create several pages.
128 */
129
130/*!
131 Constructs a PDF writer that will write the pdf to \a filename.
132 */
133QPdfWriter::QPdfWriter(const QString &filename)
134 : QObject(*new QPdfWriterPrivate),
135 QPagedPaintDevice(new QPdfPagedPaintDevicePrivate(d_func()))
136{
137 Q_D(QPdfWriter);
138
139 d->engine->setOutputFilename(filename);
140}
141
142/*!
143 Constructs a PDF writer that will write the pdf to \a device.
144 */
145QPdfWriter::QPdfWriter(QIODevice *device)
146 : QObject(*new QPdfWriterPrivate),
147 QPagedPaintDevice(new QPdfPagedPaintDevicePrivate(d_func()))
148{
149 Q_D(QPdfWriter);
150
151 d->engine->d_func()->outDevice = device;
152}
153
154/*!
155 Destroys the pdf writer.
156 */
157QPdfWriter::~QPdfWriter()
158{
159
160}
161
162/*!
163 \since 5.10
164
165 Sets the PDF version for this writer to \a version.
166
167 If \a version is the same value as currently set then no change will be made.
168*/
169void QPdfWriter::setPdfVersion(PdfVersion version)
170{
171 Q_D(QPdfWriter);
172
173 if (d->pdfVersion == version)
174 return;
175
176 d->pdfVersion = version;
177 d->engine->setPdfVersion(static_cast<QPdfEngine::PdfVersion>(static_cast<int>(version)));
178}
179
180/*!
181 \since 5.10
182
183 Returns the PDF version for this writer. The default is \c PdfVersion_1_4.
184*/
185QPdfWriter::PdfVersion QPdfWriter::pdfVersion() const
186{
187 Q_D(const QPdfWriter);
188 return d->pdfVersion;
189}
190
191/*!
192 Returns the title of the document.
193 */
194QString QPdfWriter::title() const
195{
196 Q_D(const QPdfWriter);
197 return d->engine->d_func()->title;
198}
199
200/*!
201 Sets the title of the document being created to \a title.
202 */
203void QPdfWriter::setTitle(const QString &title)
204{
205 Q_D(QPdfWriter);
206 d->engine->d_func()->title = title;
207}
208
209/*!
210 Returns the creator of the document.
211 */
212QString QPdfWriter::creator() const
213{
214 Q_D(const QPdfWriter);
215 return d->engine->d_func()->creator;
216}
217
218/*!
219 Sets the creator of the document to \a creator.
220 */
221void QPdfWriter::setCreator(const QString &creator)
222{
223 Q_D(QPdfWriter);
224 d->engine->d_func()->creator = creator;
225}
226
227/*!
228 \reimp
229 */
230QPaintEngine *QPdfWriter::paintEngine() const
231{
232 Q_D(const QPdfWriter);
233
234 return d->engine;
235}
236
237/*!
238 \since 5.3
239
240 Sets the PDF \a resolution in DPI.
241
242 This setting affects the coordinate system as returned by, for
243 example QPainter::viewport().
244
245 \sa resolution()
246*/
247
248void QPdfWriter::setResolution(int resolution)
249{
250 Q_D(const QPdfWriter);
251 if (resolution > 0)
252 d->engine->setResolution(resolution);
253}
254
255/*!
256 \since 5.3
257
258 Returns the resolution of the PDF in DPI.
259
260 \sa setResolution()
261*/
262
263int QPdfWriter::resolution() const
264{
265 Q_D(const QPdfWriter);
266 return d->engine->resolution();
267}
268
269/*!
270 \since 5.15
271
272 Sets the document metadata. This metadata is not influenced by the setTitle / setCreator methods,
273 so is up to the user to keep it consistent.
274 \a xmpMetadata contains XML formatted metadata to embed into the PDF file.
275
276 \sa documentXmpMetadata()
277*/
278
279void QPdfWriter::setDocumentXmpMetadata(const QByteArray &xmpMetadata)
280{
281 Q_D(const QPdfWriter);
282 d->engine->setDocumentXmpMetadata(xmpMetadata);
283}
284
285/*!
286 \since 5.15
287
288 Gets the document metadata, as it was provided with a call to setDocumentXmpMetadata. It will not
289 return the default metadata.
290
291 \sa setDocumentXmpMetadata()
292*/
293
294QByteArray QPdfWriter::documentXmpMetadata() const
295{
296 Q_D(const QPdfWriter);
297 return d->engine->documentXmpMetadata();
298}
299
300/*!
301 \since 5.15
302
303 Adds \a fileName attachment to the PDF with (optional) \a mimeType.
304 \a data contains the raw file data to embed into the PDF file.
305*/
306
307void QPdfWriter::addFileAttachment(const QString &fileName, const QByteArray &data, const QString &mimeType)
308{
309 Q_D(QPdfWriter);
310 d->engine->addFileAttachment(fileName, data, mimeType);
311}
312
313// Defined in QPagedPaintDevice but non-virtual, add QPdfWriter specific doc here
314#ifdef Q_QDOC
315/*!
316 \fn bool QPdfWriter::setPageLayout(const QPageLayout &newPageLayout)
317 \since 5.3
318
319 Sets the PDF page layout to \a newPageLayout.
320
321 You should call this before calling QPainter::begin(), or immediately
322 before calling newPage() to apply the new page layout to a new page.
323 You should not call any painting methods between a call to setPageLayout()
324 and newPage() as the wrong paint metrics may be used.
325
326 Returns true if the page layout was successfully set to \a newPageLayout.
327
328 \sa pageLayout()
329*/
330
331/*!
332 \fn bool QPdfWriter::setPageSize(const QPageSize &pageSize)
333 \since 5.3
334
335 Sets the PDF page size to \a pageSize.
336
337 To get the current QPageSize use pageLayout().pageSize().
338
339 You should call this before calling QPainter::begin(), or immediately
340 before calling newPage() to apply the new page size to a new page.
341 You should not call any painting methods between a call to setPageSize()
342 and newPage() as the wrong paint metrics may be used.
343
344 Returns true if the page size was successfully set to \a pageSize.
345
346 \sa pageLayout()
347*/
348
349/*!
350 \fn bool QPdfWriter::setPageOrientation(QPageLayout::Orientation orientation)
351 \since 5.3
352
353 Sets the PDF page \a orientation.
354
355 The page orientation is used to define the orientation of the
356 page size when obtaining the page rect.
357
358 You should call this before calling QPainter::begin(), or immediately
359 before calling newPage() to apply the new orientation to a new page.
360 You should not call any painting methods between a call to setPageOrientation()
361 and newPage() as the wrong paint metrics may be used.
362
363 To get the current QPageLayout::Orientation use pageLayout().orientation().
364
365 Returns true if the page orientation was successfully set to \a orientation.
366
367 \sa pageLayout()
368*/
369
370/*!
371 \fn bool QPdfWriter::setPageMargins(const QMarginsF &margins)
372 \since 5.3
373
374 Set the PDF page \a margins in the current page layout units.
375
376 You should call this before calling QPainter::begin(), or immediately
377 before calling newPage() to apply the new margins to a new page.
378 You should not call any painting methods between a call to setPageMargins()
379 and newPage() as the wrong paint metrics may be used.
380
381 To get the current page margins use pageLayout().margins().
382
383 Returns true if the page margins were successfully set to \a margins.
384
385 \sa pageLayout()
386*/
387
388/*!
389 \fn bool QPdfWriter::setPageMargins(const QMarginsF &margins, QPageLayout::Unit units)
390 \since 5.3
391
392 Set the PDF page \a margins defined in the given \a units.
393
394 You should call this before calling QPainter::begin(), or immediately
395 before calling newPage() to apply the new margins to a new page.
396 You should not call any painting methods between a call to setPageMargins()
397 and newPage() as the wrong paint metrics may be used.
398
399 To get the current page margins use pageLayout().margins().
400
401 Returns true if the page margins were successfully set to \a margins.
402
403 \sa pageLayout()
404*/
405
406/*!
407 \fn QPageLayout QPdfWriter::pageLayout() const
408 \since 5.3
409
410 Returns the current page layout. Use this method to access the current
411 QPageSize, QPageLayout::Orientation, QMarginsF, fullRect() and paintRect().
412
413 Note that you cannot use the setters on the returned object, you must either
414 call the individual QPdfWriter methods or use setPageLayout().
415
416 \sa setPageLayout(), setPageSize(), setPageOrientation(), setPageMargins()
417*/
418#endif
419
420#if QT_DEPRECATED_SINCE(5, 14)
421QT_WARNING_PUSH
422QT_WARNING_DISABLE_DEPRECATED
423/*!
424 \reimp
425
426 \obsolete Use setPageSize(QPageSize(id)) instead
427
428 \sa setPageSize()
429*/
430
431void QPdfWriter::setPageSize(PageSize size)
432{
433 setPageSize(QPageSize(QPageSize::PageSizeId(size)));
434}
435
436/*!
437 \reimp
438
439 \obsolete Use setPageSize(QPageSize(size, QPageSize::Millimeter)) instead
440
441 \sa setPageSize()
442*/
443
444void QPdfWriter::setPageSizeMM(const QSizeF &size)
445{
446 setPageSize(QPageSize(size, QPageSize::Millimeter));
447}
448QT_WARNING_POP
449#endif
450
451/*!
452 \internal
453
454 Returns the metric for the given \a id.
455*/
456int QPdfWriter::metric(PaintDeviceMetric id) const
457{
458 Q_D(const QPdfWriter);
459 return d->engine->metric(metricType: id);
460}
461
462/*!
463 \reimp
464*/
465bool QPdfWriter::newPage()
466{
467 Q_D(QPdfWriter);
468
469 return d->engine->newPage();
470}
471
472
473#if QT_DEPRECATED_SINCE(5, 14)
474QT_WARNING_PUSH
475QT_WARNING_DISABLE_DEPRECATED
476/*!
477 \reimp
478
479 \obsolete Use setPageMargins(QMarginsF(l, t, r, b), QPageLayout::Millimeter) instead
480
481 \sa setPageMargins()
482 */
483void QPdfWriter::setMargins(const Margins &m)
484{
485 setPageMargins(margins: QMarginsF(m.left, m.top, m.right, m.bottom), units: QPageLayout::Millimeter);
486}
487QT_WARNING_POP
488#endif
489
490QT_END_NAMESPACE
491
492#endif // QT_NO_PDF
493

source code of qtbase/src/gui/painting/qpdfwriter.cpp