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-2021 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, 2020 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  * Inspired on code by
25  * Copyright (C) 2004 by Albert Astals Cid <tsdgeos@terra.es>
26  * Copyright (C) 2004 by Enrico Ros <eros.kde@email.it>
27  *
28  * This program is free software; you can redistribute it and/or modify
29  * it under the terms of the GNU General Public License as published by
30  * the Free Software Foundation; either version 2, or (at your option)
31  * any later version.
32  *
33  * This program is distributed in the hope that it will be useful,
34  * but WITHOUT ANY WARRANTY; without even the implied warranty of
35  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
36  * GNU General Public License for more details.
37  *
38  * You should have received a copy of the GNU General Public License
39  * along with this program; if not, write to the Free Software
40  * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
41  */
42 
43 #ifndef _POPPLER_PRIVATE_H_
44 #define _POPPLER_PRIVATE_H_
45 
46 #include <QtCore/QFile>
47 #include <QtCore/QMutex>
48 #include <QtCore/QPointer>
49 #include <QtCore/QVector>
50 
51 #include <functional>
52 #include <config.h>
53 #include <poppler-config.h>
54 #include <GfxState.h>
55 #include <GlobalParams.h>
56 #include <Form.h>
57 #include <PDFDoc.h>
58 #include <FontInfo.h>
59 #include <OutputDev.h>
60 #include <Error.h>
61 #include <SplashOutputDev.h>
62 
63 #include "poppler-qt5.h"
64 #include "poppler-embeddedfile-private.h"
65 #include "poppler-qiodeviceinstream-private.h"
66 
67 class LinkDest;
68 class FormWidget;
69 class OutlineItem;
70 
71 namespace Poppler {
72 
73 /* borrowed from kpdf */
74 POPPLER_QT5_EXPORT QString unicodeToQString(const Unicode *u, int len);
75 
76 POPPLER_QT5_EXPORT QString UnicodeParsedString(const GooString *s1);
77 
78 POPPLER_QT5_EXPORT QString UnicodeParsedString(const std::string &s1);
79 
80 // Returns a big endian UTF-16 string with BOM or an empty string without BOM.
81 // The caller owns the returned pointer.
82 POPPLER_QT5_EXPORT GooString *QStringToUnicodeGooString(const QString &s);
83 
84 POPPLER_QT5_EXPORT GooString *QStringToGooString(const QString &s);
85 
86 GooString *QDateTimeToUnicodeGooString(const QDateTime &dt);
87 
88 void qt5ErrorFunction(ErrorCategory /*category*/, Goffset pos, const char *msg);
89 
90 Annot::AdditionalActionsType toPopplerAdditionalActionType(Annotation::AdditionalActionType type);
91 
92 class LinkDestinationData
93 {
94 public:
LinkDestinationData(const LinkDest * l,const GooString * nd,Poppler::DocumentData * pdfdoc,bool external)95     LinkDestinationData(const LinkDest *l, const GooString *nd, Poppler::DocumentData *pdfdoc, bool external) : ld(l), namedDest(nd), doc(pdfdoc), externalDest(external) { }
96 
97     const LinkDest *ld;
98     const GooString *namedDest;
99     Poppler::DocumentData *doc;
100     bool externalDest;
101 };
102 
103 class DocumentData : private GlobalParamsIniter
104 {
105 public:
DocumentData(const QString & filePath,GooString * ownerPassword,GooString * userPassword)106     DocumentData(const QString &filePath, GooString *ownerPassword, GooString *userPassword) : GlobalParamsIniter(qt5ErrorFunction)
107     {
108         init();
109         m_device = nullptr;
110         m_filePath = filePath;
111 
112 #ifdef _WIN32
113         doc = new PDFDoc((wchar_t *)filePath.utf16(), filePath.length(), ownerPassword, userPassword, nullptr, std::bind(&DocumentData::noitfyXRefReconstructed, this));
114 #else
115         GooString *fileName = new GooString(QFile::encodeName(filePath).constData());
116         doc = new PDFDoc(fileName, ownerPassword, userPassword, nullptr, std::bind(&DocumentData::noitfyXRefReconstructed, this));
117 #endif
118 
119         delete ownerPassword;
120         delete userPassword;
121     }
122 
DocumentData(QIODevice * device,GooString * ownerPassword,GooString * userPassword)123     DocumentData(QIODevice *device, GooString *ownerPassword, GooString *userPassword) : GlobalParamsIniter(qt5ErrorFunction)
124     {
125         m_device = device;
126         QIODeviceInStream *str = new QIODeviceInStream(device, 0, false, device->size(), Object(objNull));
127         init();
128         doc = new PDFDoc(str, ownerPassword, userPassword, nullptr, std::bind(&DocumentData::noitfyXRefReconstructed, this));
129         delete ownerPassword;
130         delete userPassword;
131     }
132 
DocumentData(const QByteArray & data,GooString * ownerPassword,GooString * userPassword)133     DocumentData(const QByteArray &data, GooString *ownerPassword, GooString *userPassword) : GlobalParamsIniter(qt5ErrorFunction)
134     {
135         m_device = nullptr;
136         fileContents = data;
137         MemStream *str = new MemStream((char *)fileContents.data(), 0, fileContents.length(), Object(objNull));
138         init();
139         doc = new PDFDoc(str, ownerPassword, userPassword, nullptr, std::bind(&DocumentData::noitfyXRefReconstructed, this));
140         delete ownerPassword;
141         delete userPassword;
142     }
143 
144     void init();
145 
146     ~DocumentData();
147 
148     DocumentData(const DocumentData &) = delete;
149     DocumentData &operator=(const DocumentData &) = delete;
150 
151     void addTocChildren(QDomDocument *docSyn, QDomNode *parent, const std::vector<::OutlineItem *> *items);
152 
setPaperColor(const QColor & color)153     void setPaperColor(const QColor &color) { paperColor = color; }
154 
fillMembers()155     void fillMembers()
156     {
157         int numEmb = doc->getCatalog()->numEmbeddedFiles();
158         if (!(0 == numEmb)) {
159             // we have some embedded documents, build the list
160             for (int yalv = 0; yalv < numEmb; ++yalv) {
161                 FileSpec *fs = doc->getCatalog()->embeddedFile(yalv);
162                 m_embeddedFiles.append(new EmbeddedFile(*new EmbeddedFileData(fs)));
163             }
164         }
165     }
166 
167     /**
168      * a method that is being called whenever PDFDoc's XRef is reconstructed
169      * where we'll set xrefReconstructed flag and notify users of the
170      * reconstruction event
171      */
172     void noitfyXRefReconstructed();
173 
174     static Document *checkDocument(DocumentData *doc);
175 
176     PDFDoc *doc;
177     QString m_filePath;
178     QIODevice *m_device;
179     QByteArray fileContents;
180     bool locked;
181     Document::RenderBackend m_backend;
182     QList<EmbeddedFile *> m_embeddedFiles;
183     QPointer<OptContentModel> m_optContentModel;
184     QColor paperColor;
185     int m_hints;
186 #ifdef USE_CMS
187     GfxLCMSProfilePtr m_sRGBProfile;
188     GfxLCMSProfilePtr m_displayProfile;
189 #endif
190     bool xrefReconstructed;
191     // notifies the user whenever the backend's PDFDoc XRef is reconstructed
192     std::function<void()> xrefReconstructedCallback;
193 };
194 
195 class FontInfoData
196 {
197 public:
FontInfoData()198     FontInfoData()
199     {
200         isEmbedded = false;
201         isSubset = false;
202         type = FontInfo::unknown;
203     }
204 
FontInfoData(::FontInfo * fi)205     explicit FontInfoData(::FontInfo *fi)
206     {
207         if (fi->getName())
208             fontName = fi->getName()->c_str();
209         if (fi->getFile())
210             fontFile = fi->getFile()->c_str();
211         if (fi->getSubstituteName())
212             fontSubstituteName = fi->getSubstituteName()->c_str();
213         isEmbedded = fi->getEmbedded();
214         isSubset = fi->getSubset();
215         type = (Poppler::FontInfo::Type)fi->getType();
216         embRef = fi->getEmbRef();
217     }
218 
219     FontInfoData(const FontInfoData &fid) = default;
220     FontInfoData &operator=(const FontInfoData &) = default;
221 
222     QString fontName;
223     QString fontSubstituteName;
224     QString fontFile;
225     bool isEmbedded : 1;
226     bool isSubset : 1;
227     FontInfo::Type type;
228     Ref embRef;
229 };
230 
231 class FontIteratorData
232 {
233 public:
FontIteratorData(int startPage,DocumentData * dd)234     FontIteratorData(int startPage, DocumentData *dd) : fontInfoScanner(dd->doc, startPage), totalPages(dd->doc->getNumPages()), currentPage(qMax(startPage, 0) - 1) { }
235 
~FontIteratorData()236     ~FontIteratorData() { }
237 
238     FontInfoScanner fontInfoScanner;
239     int totalPages;
240     int currentPage;
241 };
242 
243 class TextBoxData
244 {
245 public:
TextBoxData()246     TextBoxData() : nextWord(nullptr), hasSpaceAfter(false) { }
247 
248     QString text;
249     QRectF bBox;
250     TextBox *nextWord;
251     QVector<QRectF> charBBoxes; // the boundingRect of each character
252     bool hasSpaceAfter;
253 };
254 
255 class FormFieldData
256 {
257 public:
FormFieldData(DocumentData * _doc,::Page * p,::FormWidget * w)258     FormFieldData(DocumentData *_doc, ::Page *p, ::FormWidget *w) : doc(_doc), page(p), fm(w) { }
259 
260     DocumentData *doc;
261     ::Page *page; // Note for some signatures it can be null since there's signatures that don't belong to a given page
262     ::FormWidget *fm;
263     QRectF box;
264     static POPPLER_QT5_EXPORT ::FormWidget *getFormWidget(const FormField *f);
265 };
266 
267 class FormFieldIcon;
268 class FormFieldIconData
269 {
270 public:
271     static POPPLER_QT5_EXPORT FormFieldIconData *getData(const FormFieldIcon &f);
272     Dict *icon;
273 };
274 
275 }
276 
277 #endif
278