1/* poppler-private.cc: qt interface to poppler
2 * Copyright (C) 2005, Net Integration Technologies, Inc.
3 * Copyright (C) 2006, 2011, 2015, 2017-2020 by Albert Astals Cid <aacid@kde.org>
4 * Copyright (C) 2008, 2010, 2011, 2014 by Pino Toscano <pino@kde.org>
5 * Copyright (C) 2013 by Thomas Freitag <Thomas.Freitag@alfa.de>
6 * Copyright (C) 2013 Adrian Johnson <ajohnson@redneon.com>
7 * Copyright (C) 2016 Jakub Alba <jakubalba@gmail.com>
8 * 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
9 * Copyright (C) 2018-2020 Adam Reichold <adam.reichold@t-online.de>
10 * Copyright (C) 2019, 2020, 2024 Oliver Sander <oliver.sander@tu-dresden.de>
11 * Copyright (C) 2019 João Netto <joaonetto901@gmail.com>
12 * Copyright (C) 2021 Klarälvdalens Datakonsult AB, a KDAB Group company, <info@kdab.com>
13 * Copyright (C) 2021 Mahmoud Khalil <mahmoudkhalil11@gmail.com>
14 * Copyright (C) 2023 Shivodit Gill <shivodit.gill@gmail.com>
15 * Copyright (C) 2024 g10 Code GmbH, Author: Sune Stolborg Vuorela <sune@vuorela.dk>
16 * Inspired on code by
17 * Copyright (C) 2004 by Albert Astals Cid <tsdgeos@terra.es>
18 * Copyright (C) 2004 by Enrico Ros <eros.kde@email.it>
19 *
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License as published by
22 * the Free Software Foundation; either version 2, or (at your option)
23 * any later version.
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
29 *
30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
32 * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
33 */
34
35#include "poppler-private.h"
36#include "poppler-form.h"
37
38#include <QtCore/QByteArray>
39#include <QtCore/QDebug>
40#include <QtCore/QVariant>
41
42#include <Link.h>
43#include <Outline.h>
44#include <PDFDocEncoding.h>
45#include <UnicodeMap.h>
46#include <UTF.h>
47
48#ifdef ANDROID
49# include <QtCore/QString>
50# include <QtCore/QDir>
51# include <QtCore/QFile>
52# include <QtCore/QFileInfo>
53# include <QtCore/QStandardPaths>
54# include <QtCore/QDirIterator>
55#endif
56
57namespace Poppler {
58
59namespace Debug {
60
61static void qDebugDebugFunction(const QString &message, const QVariant & /*closure*/)
62{
63 qDebug() << message;
64}
65
66PopplerDebugFunc debugFunction = qDebugDebugFunction;
67QVariant debugClosure;
68
69}
70
71void setDebugErrorFunction(PopplerDebugFunc function, const QVariant &closure)
72{
73 Debug::debugFunction = function ? function : Debug::qDebugDebugFunction;
74 Debug::debugClosure = closure;
75}
76
77void qt6ErrorFunction(ErrorCategory /*category*/, Goffset pos, const char *msg)
78{
79 QString emsg;
80
81 if (pos >= 0) {
82 emsg = QStringLiteral("Error (%1): ").arg(a: pos);
83 } else {
84 emsg = QStringLiteral("Error: ");
85 }
86 emsg += QString::fromLatin1(ba: msg);
87 (*Debug::debugFunction)(emsg, Debug::debugClosure);
88}
89
90QString unicodeToQString(const Unicode *u, int len)
91{
92 const UnicodeMap *utf8Map = globalParams->getUtf8Map();
93
94 // ignore the last characters if they are 0x0
95 while ((len > 0) && (u[len - 1] == 0)) {
96 --len;
97 }
98
99 GooString convertedStr;
100 for (int i = 0; i < len; ++i) {
101 char buf[8];
102 const int n = utf8Map->mapUnicode(u: u[i], buf, bufSize: sizeof(buf));
103 convertedStr.append(str: buf, lengthA: n);
104 }
105
106 return QString::fromUtf8(utf8: convertedStr.c_str(), size: convertedStr.getLength());
107}
108
109QString unicodeToQString(const std::vector<Unicode> &u)
110{
111 return unicodeToQString(u: u.data(), len: u.size());
112}
113
114QString UnicodeParsedString(const GooString *s1)
115{
116 return (s1) ? UnicodeParsedString(s1: s1->toStr()) : QString();
117}
118
119QString UnicodeParsedString(const std::string &s1)
120{
121 if (s1.empty()) {
122 return QString();
123 }
124
125 if (hasUnicodeByteOrderMark(s: s1) || hasUnicodeByteOrderMarkLE(s: s1)) {
126 return QString::fromUtf16(reinterpret_cast<const char16_t *>(s1.c_str()), size: s1.size() / 2);
127 } else {
128 int stringLength;
129 const char *cString = pdfDocEncodingToUTF16(orig: s1, length: &stringLength);
130 auto result = QString::fromUtf16(reinterpret_cast<const char16_t *>(cString), size: stringLength / 2);
131 delete[] cString;
132 return result;
133 }
134}
135
136GooString *QStringToUnicodeGooString(const QString &s)
137{
138 if (s.isEmpty()) {
139 return new GooString();
140 }
141 int len = s.length() * 2 + 2;
142 char *cstring = (char *)gmallocn(count: len, size: sizeof(char));
143 cstring[0] = (char)0xfe;
144 cstring[1] = (char)0xff;
145 for (int i = 0; i < s.length(); ++i) {
146 cstring[2 + i * 2] = s.at(i).row();
147 cstring[3 + i * 2] = s.at(i).cell();
148 }
149 GooString *ret = new GooString(cstring, len);
150 gfree(p: cstring);
151 return ret;
152}
153
154GooString *QStringToGooString(const QString &s)
155{
156 int len = s.length();
157 char *cstring = (char *)gmallocn(count: s.length(), size: sizeof(char));
158 for (int i = 0; i < len; ++i) {
159 cstring[i] = s.at(i).unicode();
160 }
161 GooString *ret = new GooString(cstring, len);
162 gfree(p: cstring);
163 return ret;
164}
165
166GooString *QDateTimeToUnicodeGooString(const QDateTime &dt)
167{
168 if (!dt.isValid()) {
169 return nullptr;
170 }
171
172 return QStringToUnicodeGooString(s: dt.toUTC().toString(QStringLiteral("yyyyMMddhhmmss+00'00'")));
173}
174
175Annot::AdditionalActionsType toPopplerAdditionalActionType(Annotation::AdditionalActionType type)
176{
177 switch (type) {
178 case Annotation::CursorEnteringAction:
179 return Annot::actionCursorEntering;
180 case Annotation::CursorLeavingAction:
181 return Annot::actionCursorLeaving;
182 case Annotation::MousePressedAction:
183 return Annot::actionMousePressed;
184 case Annotation::MouseReleasedAction:
185 return Annot::actionMouseReleased;
186 case Annotation::FocusInAction:
187 return Annot::actionFocusIn;
188 case Annotation::FocusOutAction:
189 return Annot::actionFocusOut;
190 case Annotation::PageOpeningAction:
191 return Annot::actionPageOpening;
192 case Annotation::PageClosingAction:
193 return Annot::actionPageClosing;
194 case Annotation::PageVisibleAction:
195 return Annot::actionPageVisible;
196 case Annotation::PageInvisibleAction:
197 return Annot::actionPageInvisible;
198 }
199
200 return Annot::actionCursorEntering;
201}
202
203DocumentData::~DocumentData()
204{
205 qDeleteAll(c: m_embeddedFiles);
206 delete (OptContentModel *)m_optContentModel;
207 delete doc;
208}
209
210void DocumentData::init()
211{
212 m_backend = Document::SplashBackend;
213 paperColor = Qt::white;
214 m_hints = 0;
215 m_optContentModel = nullptr;
216 xrefReconstructed = false;
217 xrefReconstructedCallback = {};
218
219#ifdef ANDROID
220 // Copy fonts from android apk to the app's storage dir, and
221 // set the font directory path
222 QString assetsFontDir = QStringLiteral("assets:/share/fonts");
223 QString fontsdir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QStringLiteral("/fonts");
224 QDir fontPath = QDir(fontsdir);
225
226 if (fontPath.mkpath(fontPath.absolutePath())) {
227 GlobalParams::setFontDir(fontPath.absolutePath().toStdString());
228 QDirIterator iterator(assetsFontDir, QDir::NoFilter, QDirIterator::Subdirectories);
229
230 while (iterator.hasNext()) {
231 iterator.next();
232 QFileInfo fontFileInfo = iterator.fileInfo();
233 QString fontFilePath = assetsFontDir + QStringLiteral("/") + fontFileInfo.fileName();
234 QString destPath = fontPath.absolutePath() + QStringLiteral("/") + fontFileInfo.fileName();
235 QFile::copy(fontFilePath, destPath);
236 }
237 } else {
238 GlobalParams::setFontDir("");
239 }
240#endif
241}
242
243void DocumentData::noitfyXRefReconstructed()
244{
245 if (!xrefReconstructed) {
246 xrefReconstructed = true;
247 }
248
249 if (xrefReconstructedCallback) {
250 xrefReconstructedCallback();
251 }
252}
253
254FormWidget *FormFieldData::getFormWidget(const FormField *f)
255{
256 return f->m_formData->fm;
257}
258
259FormFieldIconData *FormFieldIconData::getData(const FormFieldIcon &f)
260{
261 return f.d_ptr;
262}
263
264}
265

source code of poppler/qt6/src/poppler-private.cc