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