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#ifndef QPDF_P_H
41#define QPDF_P_H
42
43//
44// W A R N I N G
45// -------------
46//
47// This file is not part of the Qt API. It exists purely as an
48// implementation detail. This header file may change from version to
49// version without notice, or even be removed.
50//
51// We mean it.
52//
53
54#include <QtGui/private/qtguiglobal_p.h>
55
56#ifndef QT_NO_PDF
57
58#include "QtCore/qlist.h"
59#include "QtCore/qstring.h"
60#include "private/qfontengine_p.h"
61#include "private/qfontsubset_p.h"
62#include "private/qpaintengine_p.h"
63#include "private/qstroker_p.h"
64#include "qpagelayout.h"
65
66QT_BEGIN_NAMESPACE
67
68const char *qt_real_to_string(qreal val, char *buf);
69const char *qt_int_to_string(int val, char *buf);
70
71namespace QPdf {
72
73 class ByteStream
74 {
75 public:
76 // fileBacking means that ByteStream will buffer the contents on disk
77 // if the size exceeds a certain threshold. In this case, if a byte
78 // array was passed in, its contents may no longer correspond to the
79 // ByteStream contents.
80 explicit ByteStream(bool fileBacking = false);
81 explicit ByteStream(QByteArray *ba, bool fileBacking = false);
82 ~ByteStream();
83 ByteStream &operator <<(char chr);
84 ByteStream &operator <<(const char *str);
85 ByteStream &operator <<(const QByteArray &str);
86 ByteStream &operator <<(const ByteStream &src);
87 ByteStream &operator <<(qreal val);
88 ByteStream &operator <<(int val);
89 ByteStream &operator <<(uint val) { return (*this << int(val)); }
90 ByteStream &operator <<(qint64 val) { return (*this << int(val)); }
91 ByteStream &operator <<(const QPointF &p);
92 // Note that the stream may be invalidated by calls that insert data.
93 QIODevice *stream();
94 void clear();
95
96 static inline int maxMemorySize() { return 100000000; }
97 static inline int chunkSize() { return 10000000; }
98
99 protected:
100 void constructor_helper(QIODevice *dev);
101 void constructor_helper(QByteArray *ba);
102
103 private:
104 void prepareBuffer();
105
106 private:
107 QIODevice *dev;
108 QByteArray ba;
109 bool fileBackingEnabled;
110 bool fileBackingActive;
111 bool handleDirty;
112 };
113
114 enum PathFlags {
115 ClipPath,
116 FillPath,
117 StrokePath,
118 FillAndStrokePath
119 };
120 QByteArray generatePath(const QPainterPath &path, const QTransform &matrix, PathFlags flags);
121 QByteArray generateMatrix(const QTransform &matrix);
122 QByteArray generateDashes(const QPen &pen);
123 QByteArray patternForBrush(const QBrush &b);
124
125 struct Stroker {
126 Stroker();
127 void setPen(const QPen &pen, QPainter::RenderHints hints);
128 void strokePath(const QPainterPath &path);
129 ByteStream *stream;
130 bool first;
131 QTransform matrix;
132 bool cosmeticPen;
133 private:
134 QStroker basicStroker;
135 QDashStroker dashStroker;
136 QStrokerOps *stroker;
137 };
138
139 QByteArray ascii85Encode(const QByteArray &input);
140
141 const char *toHex(ushort u, char *buffer);
142 const char *toHex(uchar u, char *buffer);
143
144}
145
146
147class QPdfPage : public QPdf::ByteStream
148{
149public:
150 QPdfPage();
151
152 QList<uint> images;
153 QList<uint> graphicStates;
154 QList<uint> patterns;
155 QList<uint> fonts;
156 QList<uint> annotations;
157
158 void streamImage(int w, int h, uint object);
159
160 QSize pageSize;
161private:
162};
163
164class QPdfWriter;
165class QPdfEnginePrivate;
166
167class Q_GUI_EXPORT QPdfEngine : public QPaintEngine
168{
169 Q_DECLARE_PRIVATE(QPdfEngine)
170 friend class QPdfWriter;
171public:
172 // keep in sync with QPagedPaintDevice::PdfVersion and QPdfEnginePrivate::writeHeader()::mapping!
173 enum PdfVersion
174 {
175 Version_1_4,
176 Version_A1b,
177 Version_1_6
178 };
179
180 QPdfEngine();
181 QPdfEngine(QPdfEnginePrivate &d);
182 ~QPdfEngine() {}
183
184 void setOutputFilename(const QString &filename);
185
186 void setResolution(int resolution);
187 int resolution() const;
188
189 void setPdfVersion(PdfVersion version);
190
191 void setDocumentXmpMetadata(const QByteArray &xmpMetadata);
192 QByteArray documentXmpMetadata() const;
193
194 void addFileAttachment(const QString &fileName, const QByteArray &data, const QString &mimeType);
195
196 // reimplementations QPaintEngine
197 bool begin(QPaintDevice *pdev) override;
198 bool end() override;
199
200 void drawPoints(const QPointF *points, int pointCount) override;
201 void drawLines(const QLineF *lines, int lineCount) override;
202 void drawRects(const QRectF *rects, int rectCount) override;
203 void drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode) override;
204 void drawPath (const QPainterPath & path) override;
205
206 void drawTextItem(const QPointF &p, const QTextItem &textItem) override;
207
208 void drawPixmap (const QRectF & rectangle, const QPixmap & pixmap, const QRectF & sr) override;
209 void drawImage(const QRectF &r, const QImage &pm, const QRectF &sr,
210 Qt::ImageConversionFlags flags = Qt::AutoColor) override;
211 void drawTiledPixmap (const QRectF & rectangle, const QPixmap & pixmap, const QPointF & point) override;
212
213 void drawHyperlink(const QRectF &r, const QUrl &url);
214
215 void updateState(const QPaintEngineState &state) override;
216
217 int metric(QPaintDevice::PaintDeviceMetric metricType) const;
218 Type type() const override;
219 // end reimplementations QPaintEngine
220
221 // Printer stuff...
222 bool newPage();
223
224 // Page layout stuff
225 void setPageLayout(const QPageLayout &pageLayout);
226 void setPageSize(const QPageSize &pageSize);
227 void setPageOrientation(QPageLayout::Orientation orientation);
228 void setPageMargins(const QMarginsF &margins, QPageLayout::Unit units = QPageLayout::Point);
229
230 QPageLayout pageLayout() const;
231
232 void setPen();
233 void setBrush();
234 void setupGraphicsState(QPaintEngine::DirtyFlags flags);
235
236private:
237 void updateClipPath(const QPainterPath & path, Qt::ClipOperation op);
238};
239
240class Q_GUI_EXPORT QPdfEnginePrivate : public QPaintEnginePrivate
241{
242 Q_DECLARE_PUBLIC(QPdfEngine)
243public:
244 QPdfEnginePrivate();
245 ~QPdfEnginePrivate();
246
247 inline uint requestObject() { return currentObject++; }
248
249 void writeHeader();
250 void writeTail();
251
252 int addImage(const QImage &image, bool *bitmap, bool lossless, qint64 serial_no);
253 int addConstantAlphaObject(int brushAlpha, int penAlpha = 255);
254 int addBrushPattern(const QTransform &matrix, bool *specifyColor, int *gStateObject);
255
256 void drawTextItem(const QPointF &p, const QTextItemInt &ti);
257
258 QTransform pageMatrix() const;
259
260 void newPage();
261
262 int currentObject;
263
264 QPdfPage* currentPage;
265 QPdf::Stroker stroker;
266
267 QPointF brushOrigin;
268 QBrush brush;
269 QPen pen;
270 QList<QPainterPath> clips;
271 bool clipEnabled;
272 bool allClipped;
273 bool hasPen;
274 bool hasBrush;
275 bool simplePen;
276 qreal opacity;
277 QPdfEngine::PdfVersion pdfVersion;
278
279 QHash<QFontEngine::FaceId, QFontSubset *> fonts;
280
281 QPaintDevice *pdev;
282
283 // the device the output is in the end streamed to.
284 QIODevice *outDevice;
285 bool ownsDevice;
286
287 // printer options
288 QString outputFileName;
289 QString title;
290 QString creator;
291 bool embedFonts;
292 int resolution;
293 bool grayscale;
294
295 // Page layout: size, orientation and margins
296 QPageLayout m_pageLayout;
297
298private:
299 int gradientBrush(const QBrush &b, const QTransform &matrix, int *gStateObject);
300 int generateGradientShader(const QGradient *gradient, const QTransform &matrix, bool alpha = false);
301 int generateLinearGradientShader(const QLinearGradient *lg, const QTransform &matrix, bool alpha);
302 int generateRadialGradientShader(const QRadialGradient *gradient, const QTransform &matrix, bool alpha);
303 int createShadingFunction(const QGradient *gradient, int from, int to, bool reflect, bool alpha);
304
305 void writeInfo();
306 int writeXmpDcumentMetaData();
307 int writeOutputIntent();
308 void writePageRoot();
309 void writeAttachmentRoot();
310 void writeFonts();
311 void embedFont(QFontSubset *font);
312 qreal calcUserUnit() const;
313
314 QList<int> xrefPositions;
315 QDataStream* stream;
316 int streampos;
317
318 int writeImage(const QByteArray &data, int width, int height, int depth,
319 int maskObject, int softMaskObject, bool dct = false, bool isMono = false);
320 void writePage();
321
322 int addXrefEntry(int object, bool printostr = true);
323 void printString(const QString &string);
324 void xprintf(const char* fmt, ...);
325 inline void write(const QByteArray &data) {
326 stream->writeRawData(data.constData(), data.size());
327 streampos += data.size();
328 }
329
330 int writeCompressed(const char *src, int len);
331 inline int writeCompressed(const QByteArray &data) { return writeCompressed(data.constData(), data.length()); }
332 int writeCompressed(QIODevice *dev);
333
334 struct AttachmentInfo
335 {
336 AttachmentInfo (const QString &fileName, const QByteArray &data, const QString &mimeType)
337 : fileName(fileName), data(data), mimeType(mimeType) {}
338 QString fileName;
339 QByteArray data;
340 QString mimeType;
341 };
342
343 // various PDF objects
344 int pageRoot, embeddedfilesRoot, namesRoot, catalog, info, graphicsState, patternColorSpace;
345 QList<uint> pages;
346 QHash<qint64, uint> imageCache;
347 QHash<QPair<uint, uint>, uint > alphaCache;
348 QList<AttachmentInfo> fileCache;
349 QByteArray xmpDocumentMetadata;
350};
351
352QT_END_NAMESPACE
353
354#endif // QT_NO_PDF
355
356#endif // QPDF_P_H
357
358