/src/poppler/qt6/src/poppler-private.h
Line | Count | Source |
1 | | /* poppler-private.h: qt interface to poppler |
2 | | * Copyright (C) 2005, Net Integration Technologies, Inc. |
3 | | * Copyright (C) 2005, 2008, Brad Hards <bradh@frogmouth.net> |
4 | | * Copyright (C) 2006-2009, 2011, 2012, 2017-2022, 2024-2026 by Albert Astals Cid <aacid@kde.org> |
5 | | * Copyright (C) 2007-2009, 2011, 2014 by Pino Toscano <pino@kde.org> |
6 | | * Copyright (C) 2011 Andreas Hartmetz <ahartmetz@gmail.com> |
7 | | * Copyright (C) 2011 Hib Eris <hib@hiberis.nl> |
8 | | * Copyright (C) 2012, 2013 Thomas Freitag <Thomas.Freitag@alfa.de> |
9 | | * Copyright (C) 2013 Anthony Granger <grangeranthony@gmail.com> |
10 | | * Copyright (C) 2014 Bogdan Cristea <cristeab@gmail.com> |
11 | | * Copyright (C) 2014 Aki Koskinen <freedesktop@akikoskinen.info> |
12 | | * Copyright (C) 2016 Jakub Alba <jakubalba@gmail.com> |
13 | | * Copyright (C) 2017 Christoph Cullmann <cullmann@kde.org> |
14 | | * Copyright (C) 2018 Klarälvdalens Datakonsult AB, a KDAB Group company, <info@kdab.com>. Work sponsored by the LiMux project of the city of Munich |
15 | | * Copyright (C) 2018, 2020 Adam Reichold <adam.reichold@t-online.de> |
16 | | * Copyright (C) 2019-2021 Oliver Sander <oliver.sander@tu-dresden.de> |
17 | | * Copyright (C) 2019 João Netto <joaonetto901@gmail.com> |
18 | | * Copyright (C) 2019 Jan Grulich <jgrulich@redhat.com> |
19 | | * Copyright (C) 2019 Alexander Volkov <a.volkov@rusbitech.ru> |
20 | | * Copyright (C) 2020 Philipp Knechtges <philipp-dev@knechtges.com> |
21 | | * Copyright (C) 2021 Mahmoud Khalil <mahmoudkhalil11@gmail.com> |
22 | | * Copyright (C) 2021 Hubert Figuiere <hub@figuiere.net> |
23 | | * Copyright (C) 2021 Georgiy Sgibnev <georgiy@sgibnev.com>. Work sponsored by lab50.net. |
24 | | * Copyright (C) 2024-2026 g10 Code GmbH, Author: Sune Stolborg Vuorela <sune@vuorela.dk> |
25 | | * Inspired on code by |
26 | | * Copyright (C) 2004 by Albert Astals Cid <tsdgeos@terra.es> |
27 | | * Copyright (C) 2004 by Enrico Ros <eros.kde@email.it> |
28 | | * |
29 | | * This program is free software; you can redistribute it and/or modify |
30 | | * it under the terms of the GNU General Public License as published by |
31 | | * the Free Software Foundation; either version 2, or (at your option) |
32 | | * any later version. |
33 | | * |
34 | | * This program is distributed in the hope that it will be useful, |
35 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
36 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
37 | | * GNU General Public License for more details. |
38 | | * |
39 | | * You should have received a copy of the GNU General Public License |
40 | | * along with this program; if not, write to the Free Software |
41 | | * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. |
42 | | */ |
43 | | |
44 | | #ifndef _POPPLER_PRIVATE_H_ |
45 | | #define _POPPLER_PRIVATE_H_ |
46 | | |
47 | | #include <QtCore/QFile> |
48 | | #include <QtCore/QMutex> |
49 | | #include <QtCore/QPointer> |
50 | | #include <QtCore/QVector> |
51 | | |
52 | | #include <functional> |
53 | | #include <config.h> |
54 | | #include <poppler-config.h> |
55 | | #include <Annot.h> |
56 | | #include <GfxState.h> |
57 | | #include <GlobalParams.h> |
58 | | #include <FileSpec.h> |
59 | | #include <PDFDoc.h> |
60 | | #include <FontInfo.h> |
61 | | #include <OutputDev.h> |
62 | | #include <Error.h> |
63 | | #include <SplashOutputDev.h> |
64 | | |
65 | | #include "poppler-qt6.h" |
66 | | #include "poppler-embeddedfile-private.h" |
67 | | #include "poppler-qiodeviceinstream-private.h" |
68 | | |
69 | | class LinkDest; |
70 | | class FormWidget; |
71 | | |
72 | | namespace Poppler { |
73 | | |
74 | | /* borrowed from kpdf */ |
75 | | POPPLER_QT6_EXPORT QString unicodeToQString(const Unicode *u, int len); |
76 | | POPPLER_QT6_EXPORT QString unicodeToQString(const std::vector<Unicode> &u); |
77 | | |
78 | | POPPLER_QT6_EXPORT QString UnicodeParsedString(const GooString *s1); |
79 | | |
80 | | POPPLER_QT6_EXPORT QString UnicodeParsedString(const std::string &s1); |
81 | | |
82 | | POPPLER_QT6_EXPORT std::unique_ptr<GooString> QStringToUnicodeGooString(const QString &s); |
83 | | |
84 | | // Returns a big endian UTF-16 string with BOM or an empty string without BOM. |
85 | | // The caller owns the returned pointer. |
86 | | POPPLER_QT6_EXPORT std::unique_ptr<GooString> QStringToGooString(const QString &s); |
87 | | |
88 | | std::unique_ptr<GooString> QDateTimeToUnicodeGooString(const QDateTime &dt); |
89 | | |
90 | | void qt6ErrorFunction(ErrorCategory /*category*/, Goffset pos, const char *msg); |
91 | | |
92 | | Annot::AdditionalActionsType toPopplerAdditionalActionType(Annotation::AdditionalActionType type); |
93 | | |
94 | | class LinkDestinationData |
95 | | { |
96 | | public: |
97 | 0 | LinkDestinationData(const LinkDest *l, const GooString *nd, Poppler::DocumentData *pdfdoc, bool external) : ld(l), namedDest(nd), doc(pdfdoc), externalDest(external) { } |
98 | | |
99 | | const LinkDest *ld; |
100 | | const GooString *namedDest; |
101 | | Poppler::DocumentData *doc; |
102 | | bool externalDest; |
103 | | }; |
104 | | |
105 | | class DocumentData : private GlobalParamsIniter |
106 | | { |
107 | | public: |
108 | 7.13k | DocumentData(const QString &filePath, const std::optional<GooString> &ownerPassword, const std::optional<GooString> &userPassword) : GlobalParamsIniter(qt6ErrorFunction) |
109 | 7.13k | { |
110 | 7.13k | init(); |
111 | 7.13k | m_device = nullptr; |
112 | 7.13k | m_filePath = filePath; |
113 | | |
114 | | #ifdef _WIN32 |
115 | | doc = std::make_unique<PDFDoc>((wchar_t *)filePath.utf16(), filePath.length(), ownerPassword, userPassword, [this] { notifyXRefReconstructed(); }); |
116 | | #else |
117 | 16.1k | doc = std::make_unique<PDFDoc>(std::make_unique<GooString>(QFile::encodeName(filePath).constData()), ownerPassword, userPassword, [this] { notifyXRefReconstructed(); }); |
118 | 7.13k | #endif |
119 | 7.13k | } |
120 | | |
121 | 0 | DocumentData(QIODevice *device, const std::optional<GooString> &ownerPassword, const std::optional<GooString> &userPassword) : GlobalParamsIniter(qt6ErrorFunction) |
122 | 0 | { |
123 | 0 | m_device = device; |
124 | 0 | auto str = std::make_unique<QIODeviceInStream>(device, 0, false, device->size(), Object::null()); |
125 | 0 | init(); |
126 | 0 | doc = std::make_unique<PDFDoc>(std::move(str), ownerPassword, userPassword, [this] { notifyXRefReconstructed(); }); |
127 | 0 | } |
128 | | |
129 | 0 | DocumentData(const QByteArray &data, const std::optional<GooString> &ownerPassword, const std::optional<GooString> &userPassword) : GlobalParamsIniter(qt6ErrorFunction) |
130 | 0 | { |
131 | 0 | m_device = nullptr; |
132 | 0 | fileContents = data; |
133 | 0 | auto str = std::make_unique<MemStream>(fileContents.data(), 0, fileContents.length(), Object::null()); |
134 | 0 | init(); |
135 | 0 | doc = std::make_unique<PDFDoc>(std::move(str), ownerPassword, userPassword, [this] { notifyXRefReconstructed(); }); |
136 | 0 | } |
137 | | |
138 | | void init(); |
139 | | |
140 | | ~DocumentData(); |
141 | | |
142 | | DocumentData(const DocumentData &) = delete; |
143 | | DocumentData &operator=(const DocumentData &) = delete; |
144 | | |
145 | 0 | void setPaperColor(const QColor &color) { paperColor = color; } |
146 | | |
147 | | void fillMembers() |
148 | 4.25k | { |
149 | 4.25k | int numEmb = doc->getCatalog()->numEmbeddedFiles(); |
150 | 4.25k | if (!(0 == numEmb)) { |
151 | | // we have some embedded documents, build the list |
152 | 0 | for (int yalv = 0; yalv < numEmb; ++yalv) { |
153 | 0 | std::unique_ptr<FileSpec> fs = doc->getCatalog()->embeddedFile(yalv); |
154 | 0 | m_embeddedFiles.append(new EmbeddedFile(*new EmbeddedFileData(std::move(fs)))); |
155 | 0 | } |
156 | 0 | } |
157 | 4.25k | } |
158 | | |
159 | | /** |
160 | | * a method that is being called whenever PDFDoc's XRef is reconstructed |
161 | | * where we'll set xrefReconstructed flag and notify users of the |
162 | | * reconstruction event |
163 | | */ |
164 | | void notifyXRefReconstructed(); |
165 | | |
166 | | static std::unique_ptr<Document> checkDocument(DocumentData *doc); |
167 | | |
168 | | std::unique_ptr<PDFDoc> doc; |
169 | | QString m_filePath; |
170 | | QIODevice *m_device; |
171 | | QByteArray fileContents; |
172 | | bool locked; |
173 | | Document::RenderBackend m_backend; |
174 | | QList<EmbeddedFile *> m_embeddedFiles; |
175 | | QPointer<OptContentModel> m_optContentModel; |
176 | | QColor paperColor; |
177 | | int m_hints; |
178 | | #if USE_CMS |
179 | | GfxLCMSProfilePtr m_sRGBProfile; |
180 | | GfxLCMSProfilePtr m_displayProfile; |
181 | | #endif |
182 | | bool xrefReconstructed; |
183 | | // notifies the user whenever the backend's PDFDoc XRef is reconstructed |
184 | | std::function<void()> xrefReconstructedCallback; |
185 | | }; |
186 | | |
187 | | class FontInfoData |
188 | | { |
189 | | public: |
190 | | FontInfoData() |
191 | 0 | { |
192 | 0 | isEmbedded = false; |
193 | 0 | isSubset = false; |
194 | 0 | type = FontInfo::unknown; |
195 | 0 | } |
196 | | |
197 | | explicit FontInfoData(::FontInfo *fi) |
198 | 0 | { |
199 | 0 | const std::optional<std::string> &fiName = fi->getName(); |
200 | 0 | if (fiName) { |
201 | 0 | fontName = QString::fromStdString(fiName.value()); |
202 | 0 | } |
203 | 0 | const std::optional<std::string> &fiFile = fi->getFile(); |
204 | 0 | if (fiFile) { |
205 | 0 | fontFile = QString::fromStdString(fiFile.value()); |
206 | 0 | } |
207 | 0 | const std::optional<std::string> &fiSubstituteName = fi->getSubstituteName(); |
208 | 0 | if (fiSubstituteName) { |
209 | 0 | fontSubstituteName = QString::fromStdString(fiSubstituteName.value()); |
210 | 0 | } |
211 | 0 | isEmbedded = fi->getEmbedded(); |
212 | 0 | isSubset = fi->getSubset(); |
213 | 0 | type = static_cast<Poppler::FontInfo::Type>(fi->getType()); |
214 | 0 | embRef = fi->getEmbRef(); |
215 | 0 | } |
216 | | |
217 | 0 | FontInfoData(const FontInfoData &fid) = default; |
218 | 0 | FontInfoData &operator=(const FontInfoData &) = default; |
219 | | |
220 | | QString fontName; |
221 | | QString fontSubstituteName; |
222 | | QString fontFile; |
223 | | bool isEmbedded : 1; |
224 | | bool isSubset : 1; |
225 | | FontInfo::Type type; |
226 | | Ref embRef; |
227 | | }; |
228 | | |
229 | | class FontIteratorData |
230 | | { |
231 | | public: |
232 | 0 | FontIteratorData(int startPage, DocumentData *dd) : fontInfoScanner(dd->doc.get(), startPage), totalPages(dd->doc->getNumPages()), currentPage(qMax(startPage, 0) - 1) { } |
233 | | |
234 | 0 | ~FontIteratorData() = default; |
235 | | |
236 | | FontInfoScanner fontInfoScanner; |
237 | | int totalPages; |
238 | | int currentPage; |
239 | | }; |
240 | | |
241 | | class TextBoxData |
242 | | { |
243 | | public: |
244 | 0 | TextBoxData() = default; |
245 | | |
246 | | QString text; |
247 | | QRectF bBox; |
248 | | TextBox *nextWord = nullptr; |
249 | | QVector<QRectF> charBBoxes; // the boundingRect of each character |
250 | | bool hasSpaceAfter = false; |
251 | | }; |
252 | | |
253 | | inline Poppler::ErrorStringType fromPopplerCore(::ErrorStringType type) |
254 | 0 | { |
255 | 0 | switch (type) { |
256 | 0 | case ::ErrorStringType::ErrorCodeString: |
257 | 0 | return Poppler::ErrorStringType::ErrorCodeString; |
258 | 0 | case ::ErrorStringType::UserString: |
259 | 0 | return Poppler::ErrorStringType::UserString; |
260 | 0 | } |
261 | 0 | return Poppler::ErrorStringType::ErrorCodeString; |
262 | 0 | } |
263 | | |
264 | | inline Poppler::ErrorString fromPopplerCore(const ::ErrorString &str) |
265 | 0 | { |
266 | 0 | Poppler::ErrorString res; |
267 | 0 | res.type = fromPopplerCore(str.type); |
268 | 0 | res.data = QString::fromStdString(str.text); |
269 | 0 | return res; |
270 | 0 | } |
271 | | |
272 | | class FormFieldData |
273 | | { |
274 | | public: |
275 | 0 | FormFieldData(DocumentData *_doc, ::Page *p, ::FormWidget *w) : doc(_doc), page(p), fm(w) { } |
276 | | |
277 | | DocumentData *doc; |
278 | | ::Page *page; // Note for some signatures it can be null since there's signatures that don't belong to a given page |
279 | | ::FormWidget *fm; |
280 | | QRectF box; |
281 | | static POPPLER_QT6_EXPORT ::FormWidget *getFormWidget(const FormField *f); |
282 | | Poppler::ErrorString lastSigningErrorDetails; |
283 | | }; |
284 | | |
285 | | class FormFieldIcon; |
286 | | class FormFieldIconData |
287 | | { |
288 | | public: |
289 | | static POPPLER_QT6_EXPORT FormFieldIconData *getData(const FormFieldIcon &f); |
290 | | Dict *icon; |
291 | | }; |
292 | | |
293 | | } |
294 | | |
295 | | #endif |