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