Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: PDF driver
4 : * Purpose: GDALDataset driver for PDF dataset.
5 : * Author: Even Rouault, <even dot rouault at spatialys.com>
6 : *
7 : ******************************************************************************
8 : *
9 : * Support for open-source PDFium library
10 : *
11 : * Copyright (C) 2015 Klokan Technologies GmbH (http://www.klokantech.com/)
12 : * Author: Martin Mikita <martin.mikita@klokantech.com>, xmikit00 @ FIT VUT Brno
13 : *
14 : ******************************************************************************
15 : * Copyright (c) 2011-2013, Even Rouault <even dot rouault at spatialys.com>
16 : *
17 : * SPDX-License-Identifier: MIT
18 : ****************************************************************************/
19 :
20 : #include "gdal_pdf.h"
21 :
22 : #include <limits>
23 : #include <vector>
24 : #include "pdfobject.h"
25 :
26 : /************************************************************************/
27 : /* ROUND_IF_CLOSE() */
28 : /************************************************************************/
29 :
30 7759 : double ROUND_IF_CLOSE(double x, double eps)
31 : {
32 7759 : if (eps == 0.0)
33 5533 : eps = fabs(x) < 1 ? 1e-10 : 1e-8;
34 7759 : const double dfRounded = std::round(x);
35 7759 : if (fabs(x - dfRounded) < eps)
36 5034 : return dfRounded;
37 : else
38 2725 : return x;
39 : }
40 :
41 : /************************************************************************/
42 : /* GDALPDFGetPDFString() */
43 : /************************************************************************/
44 :
45 778 : static CPLString GDALPDFGetPDFString(const char *pszStr)
46 : {
47 778 : const GByte *pabyData = reinterpret_cast<const GByte *>(pszStr);
48 : GByte ch;
49 32872 : for (size_t i = 0; (ch = pabyData[i]) != '\0'; i++)
50 : {
51 32107 : if (ch < 32 || ch > 127 || ch == '(' || ch == ')' || ch == '\\' ||
52 32094 : ch == '%' || ch == '#')
53 : break;
54 : }
55 778 : CPLString osStr;
56 778 : if (ch == 0)
57 : {
58 765 : osStr = "(";
59 765 : osStr += pszStr;
60 765 : osStr += ")";
61 765 : return osStr;
62 : }
63 :
64 13 : wchar_t *pwszDest = CPLRecodeToWChar(pszStr, CPL_ENC_UTF8, CPL_ENC_UCS2);
65 13 : osStr = "<FEFF";
66 806 : for (size_t i = 0; pwszDest[i] != 0; i++)
67 : {
68 : #ifndef _WIN32
69 793 : if (pwszDest[i] >= 0x10000 /* && pwszDest[i] <= 0x10FFFF */)
70 : {
71 : /* Generate UTF-16 surrogate pairs (on Windows, CPLRecodeToWChar
72 : * does it for us) */
73 0 : int nHeadSurrogate = ((pwszDest[i] - 0x10000) >> 10) | 0xd800;
74 0 : int nTrailSurrogate = ((pwszDest[i] - 0x10000) & 0x3ff) | 0xdc00;
75 0 : osStr += CPLSPrintf("%02X", (nHeadSurrogate >> 8) & 0xff);
76 0 : osStr += CPLSPrintf("%02X", (nHeadSurrogate)&0xff);
77 0 : osStr += CPLSPrintf("%02X", (nTrailSurrogate >> 8) & 0xff);
78 0 : osStr += CPLSPrintf("%02X", (nTrailSurrogate)&0xff);
79 : }
80 : else
81 : #endif
82 : {
83 : osStr +=
84 793 : CPLSPrintf("%02X", static_cast<int>(pwszDest[i] >> 8) & 0xff);
85 793 : osStr += CPLSPrintf("%02X", static_cast<int>(pwszDest[i]) & 0xff);
86 : }
87 : }
88 13 : osStr += ">";
89 13 : CPLFree(pwszDest);
90 13 : return osStr;
91 : }
92 :
93 : #if defined(HAVE_POPPLER) || defined(HAVE_PDFIUM)
94 :
95 : /************************************************************************/
96 : /* GDALPDFGetUTF8StringFromBytes() */
97 : /************************************************************************/
98 :
99 1523 : static std::string GDALPDFGetUTF8StringFromBytes(const GByte *pabySrc,
100 : size_t nLen)
101 : {
102 1523 : const bool bLEUnicodeMarker =
103 1523 : nLen >= 2 && pabySrc[0] == 0xFE && pabySrc[1] == 0xFF;
104 1523 : const bool bBEUnicodeMarker =
105 1523 : nLen >= 2 && pabySrc[0] == 0xFF && pabySrc[1] == 0xFE;
106 1523 : if (!bLEUnicodeMarker && !bBEUnicodeMarker)
107 : {
108 1828 : std::string osStr;
109 : try
110 : {
111 914 : osStr.reserve(nLen);
112 : }
113 0 : catch (const std::exception &e)
114 : {
115 0 : CPLError(CE_Failure, CPLE_OutOfMemory,
116 0 : "GDALPDFGetUTF8StringFromBytes(): %s", e.what());
117 0 : return osStr;
118 : }
119 914 : osStr.assign(reinterpret_cast<const char *>(pabySrc), nLen);
120 914 : const char *pszStr = osStr.c_str();
121 914 : if (CPLIsUTF8(pszStr, -1))
122 914 : return osStr;
123 : else
124 : {
125 0 : char *pszUTF8 = CPLRecode(pszStr, CPL_ENC_ISO8859_1, CPL_ENC_UTF8);
126 0 : std::string osRet = pszUTF8;
127 0 : CPLFree(pszUTF8);
128 0 : return osRet;
129 : }
130 : }
131 :
132 : /* This is UTF-16 content */
133 609 : pabySrc += 2;
134 609 : nLen = (nLen - 2) / 2;
135 1218 : std::wstring awszSource;
136 609 : awszSource.resize(nLen + 1);
137 609 : size_t j = 0;
138 8169 : for (size_t i = 0; i < nLen; i++, j++)
139 : {
140 7560 : if (!bBEUnicodeMarker)
141 6160 : awszSource[j] = (pabySrc[2 * i] << 8) + pabySrc[2 * i + 1];
142 : else
143 1400 : awszSource[j] = (pabySrc[2 * i + 1] << 8) + pabySrc[2 * i];
144 : #ifndef _WIN32
145 : /* Is there a surrogate pair ? See http://en.wikipedia.org/wiki/UTF-16
146 : */
147 : /* On Windows, CPLRecodeFromWChar does this for us, because wchar_t is
148 : * only */
149 : /* 2 bytes wide, whereas on Unix it is 32bits */
150 7560 : if (awszSource[j] >= 0xD800 && awszSource[j] <= 0xDBFF && i + 1 < nLen)
151 : {
152 : /* should be in the range 0xDC00... 0xDFFF */
153 : wchar_t nTrailSurrogate;
154 0 : if (!bBEUnicodeMarker)
155 0 : nTrailSurrogate =
156 0 : (pabySrc[2 * (i + 1)] << 8) + pabySrc[2 * (i + 1) + 1];
157 : else
158 0 : nTrailSurrogate =
159 0 : (pabySrc[2 * (i + 1) + 1] << 8) + pabySrc[2 * (i + 1)];
160 0 : if (nTrailSurrogate >= 0xDC00 && nTrailSurrogate <= 0xDFFF)
161 : {
162 0 : awszSource[j] = ((awszSource[j] - 0xD800) << 10) +
163 0 : (nTrailSurrogate - 0xDC00) + 0x10000;
164 0 : i++;
165 : }
166 : }
167 : #endif
168 : }
169 609 : awszSource[j] = 0;
170 :
171 : char *pszUTF8 =
172 609 : CPLRecodeFromWChar(awszSource.data(), CPL_ENC_UCS2, CPL_ENC_UTF8);
173 609 : awszSource.clear();
174 1218 : std::string osStrUTF8(pszUTF8);
175 609 : CPLFree(pszUTF8);
176 609 : return osStrUTF8;
177 : }
178 :
179 : #endif // defined(HAVE_POPPLER) || defined(HAVE_PDFIUM)
180 :
181 : /************************************************************************/
182 : /* GDALPDFGetPDFName() */
183 : /************************************************************************/
184 :
185 3199 : static std::string GDALPDFGetPDFName(const std::string &osStr)
186 : {
187 3199 : std::string osRet;
188 27121 : for (const char ch : osStr)
189 : {
190 23922 : if (!((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') ||
191 19 : (ch >= '0' && ch <= '9') || ch == '-'))
192 0 : osRet += '_';
193 : else
194 23922 : osRet += ch;
195 : }
196 3199 : return osRet;
197 : }
198 :
199 : /************************************************************************/
200 : /* ==================================================================== */
201 : /* GDALPDFObject */
202 : /* ==================================================================== */
203 : /************************************************************************/
204 :
205 : /************************************************************************/
206 : /* ~GDALPDFObject() */
207 : /************************************************************************/
208 :
209 42831 : GDALPDFObject::~GDALPDFObject()
210 : {
211 42831 : }
212 :
213 : /************************************************************************/
214 : /* LookupObject() */
215 : /************************************************************************/
216 :
217 2585 : GDALPDFObject *GDALPDFObject::LookupObject(const char *pszPath)
218 : {
219 2585 : if (GetType() != PDFObjectType_Dictionary)
220 0 : return nullptr;
221 2585 : return GetDictionary()->LookupObject(pszPath);
222 : }
223 :
224 : /************************************************************************/
225 : /* GetTypeName() */
226 : /************************************************************************/
227 :
228 140 : const char *GDALPDFObject::GetTypeName()
229 : {
230 140 : switch (GetType())
231 : {
232 0 : case PDFObjectType_Unknown:
233 0 : return GetTypeNameNative();
234 0 : case PDFObjectType_Null:
235 0 : return "null";
236 0 : case PDFObjectType_Bool:
237 0 : return "bool";
238 0 : case PDFObjectType_Int:
239 0 : return "int";
240 0 : case PDFObjectType_Real:
241 0 : return "real";
242 0 : case PDFObjectType_String:
243 0 : return "string";
244 0 : case PDFObjectType_Name:
245 0 : return "name";
246 6 : case PDFObjectType_Array:
247 6 : return "array";
248 134 : case PDFObjectType_Dictionary:
249 134 : return "dictionary";
250 0 : default:
251 0 : return GetTypeNameNative();
252 : }
253 : }
254 :
255 : /************************************************************************/
256 : /* Serialize() */
257 : /************************************************************************/
258 :
259 15681 : void GDALPDFObject::Serialize(CPLString &osStr, bool bEmitRef)
260 : {
261 15681 : auto nRefNum = GetRefNum();
262 15681 : if (bEmitRef && nRefNum.toBool())
263 : {
264 2999 : int nRefGen = GetRefGen();
265 2999 : osStr.append(CPLSPrintf("%d %d R", nRefNum.toInt(), nRefGen));
266 2999 : return;
267 : }
268 :
269 12682 : switch (GetType())
270 : {
271 12 : case PDFObjectType_Null:
272 12 : osStr.append("null");
273 12 : return;
274 26 : case PDFObjectType_Bool:
275 26 : osStr.append(GetBool() ? "true" : "false");
276 26 : return;
277 3764 : case PDFObjectType_Int:
278 3764 : osStr.append(CPLSPrintf("%d", GetInt()));
279 3764 : return;
280 2553 : case PDFObjectType_Real:
281 : {
282 : char szReal[512];
283 2553 : double dfRealNonRounded = GetReal();
284 2553 : double dfReal = ROUND_IF_CLOSE(dfRealNonRounded);
285 2553 : if (dfReal >=
286 2553 : static_cast<double>(std::numeric_limits<GIntBig>::min()) &&
287 : dfReal <=
288 5106 : static_cast<double>(std::numeric_limits<GIntBig>::max()) &&
289 2553 : dfReal == static_cast<double>(static_cast<GIntBig>(dfReal)))
290 : {
291 1840 : snprintf(szReal, sizeof(szReal), CPL_FRMT_GIB,
292 : static_cast<GIntBig>(dfReal));
293 : }
294 713 : else if (CanRepresentRealAsString())
295 : {
296 : /* Used for OGC BP numeric values */
297 0 : CPLsnprintf(szReal, sizeof(szReal), "(%.*g)", GetPrecision(),
298 : dfReal);
299 : }
300 : else
301 : {
302 713 : CPLsnprintf(szReal, sizeof(szReal), "%.*f", GetPrecision(),
303 : dfReal);
304 :
305 : /* Remove non significant trailing zeroes */
306 713 : char *pszDot = strchr(szReal, '.');
307 713 : if (pszDot)
308 : {
309 713 : int iDot = static_cast<int>(pszDot - szReal);
310 713 : int nLen = static_cast<int>(strlen(szReal));
311 2860 : for (int i = nLen - 1; i > iDot; i--)
312 : {
313 2860 : if (szReal[i] == '0')
314 2147 : szReal[i] = '\0';
315 : else
316 713 : break;
317 : }
318 : }
319 : }
320 2553 : osStr.append(szReal);
321 2553 : return;
322 : }
323 778 : case PDFObjectType_String:
324 778 : osStr.append(GDALPDFGetPDFString(GetString().c_str()));
325 778 : return;
326 3199 : case PDFObjectType_Name:
327 3199 : osStr.append("/");
328 3199 : osStr.append(GDALPDFGetPDFName(GetName()));
329 3199 : return;
330 1178 : case PDFObjectType_Array:
331 1178 : GetArray()->Serialize(osStr);
332 1178 : return;
333 1172 : case PDFObjectType_Dictionary:
334 1172 : GetDictionary()->Serialize(osStr);
335 1172 : return;
336 0 : case PDFObjectType_Unknown:
337 : default:
338 0 : CPLError(CE_Warning, CPLE_AppDefined,
339 : "Serializing unknown object !");
340 0 : return;
341 : }
342 : }
343 :
344 : /************************************************************************/
345 : /* Clone() */
346 : /************************************************************************/
347 :
348 303 : GDALPDFObjectRW *GDALPDFObject::Clone()
349 : {
350 303 : auto nRefNum = GetRefNum();
351 303 : if (nRefNum.toBool())
352 : {
353 121 : int nRefGen = GetRefGen();
354 121 : return GDALPDFObjectRW::CreateIndirect(nRefNum, nRefGen);
355 : }
356 :
357 182 : switch (GetType())
358 : {
359 0 : case PDFObjectType_Null:
360 0 : return GDALPDFObjectRW::CreateNull();
361 0 : case PDFObjectType_Bool:
362 0 : return GDALPDFObjectRW::CreateBool(GetBool());
363 103 : case PDFObjectType_Int:
364 103 : return GDALPDFObjectRW::CreateInt(GetInt());
365 8 : case PDFObjectType_Real:
366 8 : return GDALPDFObjectRW::CreateReal(GetReal());
367 0 : case PDFObjectType_String:
368 0 : return GDALPDFObjectRW::CreateString(GetString().c_str());
369 29 : case PDFObjectType_Name:
370 29 : return GDALPDFObjectRW::CreateName(GetName().c_str());
371 42 : case PDFObjectType_Array:
372 42 : return GDALPDFObjectRW::CreateArray(GetArray()->Clone());
373 0 : case PDFObjectType_Dictionary:
374 0 : return GDALPDFObjectRW::CreateDictionary(GetDictionary()->Clone());
375 0 : case PDFObjectType_Unknown:
376 : default:
377 0 : CPLError(CE_Warning, CPLE_AppDefined, "Cloning unknown object !");
378 0 : return nullptr;
379 : }
380 : }
381 :
382 : /************************************************************************/
383 : /* ==================================================================== */
384 : /* GDALPDFDictionary */
385 : /* ==================================================================== */
386 : /************************************************************************/
387 :
388 : /************************************************************************/
389 : /* ~GDALPDFDictionary() */
390 : /************************************************************************/
391 :
392 11234 : GDALPDFDictionary::~GDALPDFDictionary()
393 : {
394 11234 : }
395 :
396 : /************************************************************************/
397 : /* LookupObject() */
398 : /************************************************************************/
399 :
400 3412 : GDALPDFObject *GDALPDFDictionary::LookupObject(const char *pszPath)
401 : {
402 3412 : GDALPDFObject *poCurObj = nullptr;
403 3412 : char **papszTokens = CSLTokenizeString2(pszPath, ".", 0);
404 7848 : for (int i = 0; papszTokens[i] != nullptr; i++)
405 : {
406 5951 : int iElt = -1;
407 5951 : char *pszBracket = strchr(papszTokens[i], '[');
408 5951 : if (pszBracket != nullptr)
409 : {
410 0 : iElt = atoi(pszBracket + 1);
411 0 : *pszBracket = '\0';
412 : }
413 :
414 5951 : if (i == 0)
415 : {
416 3412 : poCurObj = Get(papszTokens[i]);
417 : }
418 : else
419 : {
420 2539 : if (poCurObj->GetType() != PDFObjectType_Dictionary)
421 : {
422 0 : poCurObj = nullptr;
423 0 : break;
424 : }
425 2539 : poCurObj = poCurObj->GetDictionary()->Get(papszTokens[i]);
426 : }
427 :
428 5951 : if (poCurObj == nullptr)
429 : {
430 1515 : poCurObj = nullptr;
431 1515 : break;
432 : }
433 :
434 4436 : if (iElt >= 0)
435 : {
436 0 : if (poCurObj->GetType() != PDFObjectType_Array)
437 : {
438 0 : poCurObj = nullptr;
439 0 : break;
440 : }
441 0 : poCurObj = poCurObj->GetArray()->Get(iElt);
442 : }
443 : }
444 3412 : CSLDestroy(papszTokens);
445 3412 : return poCurObj;
446 : }
447 :
448 : /************************************************************************/
449 : /* Serialize() */
450 : /************************************************************************/
451 :
452 3033 : void GDALPDFDictionary::Serialize(CPLString &osStr)
453 : {
454 3033 : osStr.append("<< ");
455 13334 : for (const auto &oIter : GetValues())
456 : {
457 10301 : const char *pszKey = oIter.first.c_str();
458 10301 : GDALPDFObject *poObj = oIter.second;
459 10301 : osStr.append("/");
460 10301 : osStr.append(pszKey);
461 10301 : osStr.append(" ");
462 10301 : poObj->Serialize(osStr);
463 10301 : osStr.append(" ");
464 : }
465 3033 : osStr.append(">>");
466 3033 : }
467 :
468 : /************************************************************************/
469 : /* Clone() */
470 : /************************************************************************/
471 :
472 29 : GDALPDFDictionaryRW *GDALPDFDictionary::Clone()
473 : {
474 29 : GDALPDFDictionaryRW *poDict = new GDALPDFDictionaryRW();
475 221 : for (const auto &oIter : GetValues())
476 : {
477 192 : const char *pszKey = oIter.first.c_str();
478 192 : GDALPDFObject *poObj = oIter.second;
479 192 : poDict->Add(pszKey, poObj->Clone());
480 : }
481 29 : return poDict;
482 : }
483 :
484 : /************************************************************************/
485 : /* ==================================================================== */
486 : /* GDALPDFArray */
487 : /* ==================================================================== */
488 : /************************************************************************/
489 :
490 : /************************************************************************/
491 : /* ~GDALPDFArray() */
492 : /************************************************************************/
493 :
494 3566 : GDALPDFArray::~GDALPDFArray()
495 : {
496 3566 : }
497 :
498 : /************************************************************************/
499 : /* Serialize() */
500 : /************************************************************************/
501 :
502 1293 : void GDALPDFArray::Serialize(CPLString &osStr)
503 : {
504 1293 : int nLength = GetLength();
505 : int i;
506 :
507 1293 : osStr.append("[ ");
508 5841 : for (i = 0; i < nLength; i++)
509 : {
510 4548 : Get(i)->Serialize(osStr);
511 4548 : osStr.append(" ");
512 : }
513 1293 : osStr.append("]");
514 1293 : }
515 :
516 : /************************************************************************/
517 : /* Clone() */
518 : /************************************************************************/
519 :
520 42 : GDALPDFArrayRW *GDALPDFArray::Clone()
521 : {
522 42 : GDALPDFArrayRW *poArray = new GDALPDFArrayRW();
523 42 : int nLength = GetLength();
524 : int i;
525 153 : for (i = 0; i < nLength; i++)
526 : {
527 111 : poArray->Add(Get(i)->Clone());
528 : }
529 42 : return poArray;
530 : }
531 :
532 : /************************************************************************/
533 : /* ==================================================================== */
534 : /* GDALPDFStream */
535 : /* ==================================================================== */
536 : /************************************************************************/
537 :
538 : /************************************************************************/
539 : /* ~GDALPDFStream() */
540 : /************************************************************************/
541 :
542 : GDALPDFStream::~GDALPDFStream() = default;
543 :
544 : /************************************************************************/
545 : /* ==================================================================== */
546 : /* GDALPDFObjectRW */
547 : /* ==================================================================== */
548 : /************************************************************************/
549 :
550 : /************************************************************************/
551 : /* GDALPDFObjectRW() */
552 : /************************************************************************/
553 :
554 15845 : GDALPDFObjectRW::GDALPDFObjectRW(GDALPDFObjectType eType) : m_eType(eType)
555 : {
556 15845 : }
557 :
558 : /************************************************************************/
559 : /* ~GDALPDFObjectRW() */
560 : /************************************************************************/
561 :
562 31690 : GDALPDFObjectRW::~GDALPDFObjectRW()
563 : {
564 15845 : delete m_poDict;
565 15845 : delete m_poArray;
566 31690 : }
567 :
568 : /************************************************************************/
569 : /* CreateIndirect() */
570 : /************************************************************************/
571 :
572 3072 : GDALPDFObjectRW *GDALPDFObjectRW::CreateIndirect(const GDALPDFObjectNum &nNum,
573 : int nGen)
574 : {
575 3072 : GDALPDFObjectRW *poObj = new GDALPDFObjectRW(PDFObjectType_Unknown);
576 3072 : poObj->m_nNum = nNum;
577 3072 : poObj->m_nGen = nGen;
578 3072 : return poObj;
579 : }
580 :
581 : /************************************************************************/
582 : /* CreateNull() */
583 : /************************************************************************/
584 :
585 12 : GDALPDFObjectRW *GDALPDFObjectRW::CreateNull()
586 : {
587 12 : return new GDALPDFObjectRW(PDFObjectType_Null);
588 : }
589 :
590 : /************************************************************************/
591 : /* CreateBool() */
592 : /************************************************************************/
593 :
594 26 : GDALPDFObjectRW *GDALPDFObjectRW::CreateBool(int bVal)
595 : {
596 26 : GDALPDFObjectRW *poObj = new GDALPDFObjectRW(PDFObjectType_Bool);
597 26 : poObj->m_nVal = bVal;
598 26 : return poObj;
599 : }
600 :
601 : /************************************************************************/
602 : /* CreateInt() */
603 : /************************************************************************/
604 :
605 3812 : GDALPDFObjectRW *GDALPDFObjectRW::CreateInt(int nVal)
606 : {
607 3812 : GDALPDFObjectRW *poObj = new GDALPDFObjectRW(PDFObjectType_Int);
608 3812 : poObj->m_nVal = nVal;
609 3812 : return poObj;
610 : }
611 :
612 : /************************************************************************/
613 : /* CreateReal() */
614 : /************************************************************************/
615 :
616 2493 : GDALPDFObjectRW *GDALPDFObjectRW::CreateReal(double dfVal,
617 : int bCanRepresentRealAsString)
618 : {
619 2493 : GDALPDFObjectRW *poObj = new GDALPDFObjectRW(PDFObjectType_Real);
620 2493 : poObj->m_dfVal = dfVal;
621 2493 : poObj->m_bCanRepresentRealAsString = bCanRepresentRealAsString;
622 2493 : return poObj;
623 : }
624 :
625 : /************************************************************************/
626 : /* CreateRealWithPrecision() */
627 : /************************************************************************/
628 :
629 64 : GDALPDFObjectRW *GDALPDFObjectRW::CreateRealWithPrecision(double dfVal,
630 : int nPrecision)
631 : {
632 64 : GDALPDFObjectRW *poObj = new GDALPDFObjectRW(PDFObjectType_Real);
633 64 : poObj->m_dfVal = dfVal;
634 64 : poObj->m_nPrecision = nPrecision;
635 64 : return poObj;
636 : }
637 :
638 : /************************************************************************/
639 : /* CreateString() */
640 : /************************************************************************/
641 :
642 778 : GDALPDFObjectRW *GDALPDFObjectRW::CreateString(const char *pszStr)
643 : {
644 778 : GDALPDFObjectRW *poObj = new GDALPDFObjectRW(PDFObjectType_String);
645 778 : poObj->m_osVal = pszStr;
646 778 : return poObj;
647 : }
648 :
649 : /************************************************************************/
650 : /* CreateName() */
651 : /************************************************************************/
652 :
653 3203 : GDALPDFObjectRW *GDALPDFObjectRW::CreateName(const char *pszName)
654 : {
655 3203 : GDALPDFObjectRW *poObj = new GDALPDFObjectRW(PDFObjectType_Name);
656 3203 : poObj->m_osVal = pszName;
657 3203 : return poObj;
658 : }
659 :
660 : /************************************************************************/
661 : /* CreateDictionary() */
662 : /************************************************************************/
663 :
664 1174 : GDALPDFObjectRW *GDALPDFObjectRW::CreateDictionary(GDALPDFDictionaryRW *poDict)
665 : {
666 1174 : CPLAssert(poDict);
667 1174 : GDALPDFObjectRW *poObj = new GDALPDFObjectRW(PDFObjectType_Dictionary);
668 1174 : poObj->m_poDict = poDict;
669 1174 : return poObj;
670 : }
671 :
672 : /************************************************************************/
673 : /* CreateArray() */
674 : /************************************************************************/
675 :
676 1211 : GDALPDFObjectRW *GDALPDFObjectRW::CreateArray(GDALPDFArrayRW *poArray)
677 : {
678 1211 : CPLAssert(poArray);
679 1211 : GDALPDFObjectRW *poObj = new GDALPDFObjectRW(PDFObjectType_Array);
680 1211 : poObj->m_poArray = poArray;
681 1211 : return poObj;
682 : }
683 :
684 : /************************************************************************/
685 : /* GetTypeNameNative() */
686 : /************************************************************************/
687 :
688 0 : const char *GDALPDFObjectRW::GetTypeNameNative()
689 : {
690 0 : CPLError(CE_Failure, CPLE_AppDefined, "Should not go here");
691 0 : return "";
692 : }
693 :
694 : /************************************************************************/
695 : /* GetType() */
696 : /************************************************************************/
697 :
698 12650 : GDALPDFObjectType GDALPDFObjectRW::GetType()
699 : {
700 12650 : return m_eType;
701 : }
702 :
703 : /************************************************************************/
704 : /* GetBool() */
705 : /************************************************************************/
706 :
707 26 : int GDALPDFObjectRW::GetBool()
708 : {
709 26 : if (m_eType == PDFObjectType_Bool)
710 26 : return m_nVal;
711 :
712 0 : return FALSE;
713 : }
714 :
715 : /************************************************************************/
716 : /* GetInt() */
717 : /************************************************************************/
718 :
719 3748 : int GDALPDFObjectRW::GetInt()
720 : {
721 3748 : if (m_eType == PDFObjectType_Int)
722 3748 : return m_nVal;
723 :
724 0 : return 0;
725 : }
726 :
727 : /************************************************************************/
728 : /* GetReal() */
729 : /************************************************************************/
730 :
731 2553 : double GDALPDFObjectRW::GetReal()
732 : {
733 2553 : return m_dfVal;
734 : }
735 :
736 : /************************************************************************/
737 : /* GetString() */
738 : /************************************************************************/
739 :
740 778 : const CPLString &GDALPDFObjectRW::GetString()
741 : {
742 778 : return m_osVal;
743 : }
744 :
745 : /************************************************************************/
746 : /* GetName() */
747 : /************************************************************************/
748 :
749 3183 : const CPLString &GDALPDFObjectRW::GetName()
750 : {
751 3183 : return m_osVal;
752 : }
753 :
754 : /************************************************************************/
755 : /* GetDictionary() */
756 : /************************************************************************/
757 :
758 1172 : GDALPDFDictionary *GDALPDFObjectRW::GetDictionary()
759 : {
760 1172 : return m_poDict;
761 : }
762 :
763 : /************************************************************************/
764 : /* GetArray() */
765 : /************************************************************************/
766 :
767 1178 : GDALPDFArray *GDALPDFObjectRW::GetArray()
768 : {
769 1178 : return m_poArray;
770 : }
771 :
772 : /************************************************************************/
773 : /* GetStream() */
774 : /************************************************************************/
775 :
776 0 : GDALPDFStream *GDALPDFObjectRW::GetStream()
777 : {
778 0 : return nullptr;
779 : }
780 :
781 : /************************************************************************/
782 : /* GetRefNum() */
783 : /************************************************************************/
784 :
785 15653 : GDALPDFObjectNum GDALPDFObjectRW::GetRefNum()
786 : {
787 15653 : return m_nNum;
788 : }
789 :
790 : /************************************************************************/
791 : /* GetRefGen() */
792 : /************************************************************************/
793 :
794 3003 : int GDALPDFObjectRW::GetRefGen()
795 : {
796 3003 : return m_nGen;
797 : }
798 :
799 : /************************************************************************/
800 : /* ==================================================================== */
801 : /* GDALPDFDictionaryRW */
802 : /* ==================================================================== */
803 : /************************************************************************/
804 :
805 : /************************************************************************/
806 : /* GDALPDFDictionaryRW() */
807 : /************************************************************************/
808 :
809 : GDALPDFDictionaryRW::GDALPDFDictionaryRW() = default;
810 :
811 : /************************************************************************/
812 : /* ~GDALPDFDictionaryRW() */
813 : /************************************************************************/
814 :
815 4252 : GDALPDFDictionaryRW::~GDALPDFDictionaryRW()
816 : {
817 3049 : std::map<CPLString, GDALPDFObject *>::iterator oIter = m_map.begin();
818 3049 : std::map<CPLString, GDALPDFObject *>::iterator oEnd = m_map.end();
819 13460 : for (; oIter != oEnd; ++oIter)
820 10411 : delete oIter->second;
821 4252 : }
822 :
823 : /************************************************************************/
824 : /* Get() */
825 : /************************************************************************/
826 :
827 6 : GDALPDFObject *GDALPDFDictionaryRW::Get(const char *pszKey)
828 : {
829 6 : std::map<CPLString, GDALPDFObject *>::iterator oIter = m_map.find(pszKey);
830 6 : if (oIter != m_map.end())
831 4 : return oIter->second;
832 2 : return nullptr;
833 : }
834 :
835 : /************************************************************************/
836 : /* GetValues() */
837 : /************************************************************************/
838 :
839 3033 : std::map<CPLString, GDALPDFObject *> &GDALPDFDictionaryRW::GetValues()
840 : {
841 3033 : return m_map;
842 : }
843 :
844 : /************************************************************************/
845 : /* Add() */
846 : /************************************************************************/
847 :
848 10422 : GDALPDFDictionaryRW &GDALPDFDictionaryRW::Add(const char *pszKey,
849 : GDALPDFObject *poVal)
850 : {
851 10422 : std::map<CPLString, GDALPDFObject *>::iterator oIter = m_map.find(pszKey);
852 10422 : if (oIter != m_map.end())
853 : {
854 0 : delete oIter->second;
855 0 : oIter->second = poVal;
856 : }
857 : else
858 10422 : m_map[pszKey] = poVal;
859 :
860 10422 : return *this;
861 : }
862 :
863 : /************************************************************************/
864 : /* Remove() */
865 : /************************************************************************/
866 :
867 28 : GDALPDFDictionaryRW &GDALPDFDictionaryRW::Remove(const char *pszKey)
868 : {
869 28 : std::map<CPLString, GDALPDFObject *>::iterator oIter = m_map.find(pszKey);
870 28 : if (oIter != m_map.end())
871 : {
872 11 : delete oIter->second;
873 11 : m_map.erase(pszKey);
874 : }
875 :
876 28 : return *this;
877 : }
878 :
879 : /************************************************************************/
880 : /* ==================================================================== */
881 : /* GDALPDFArrayRW */
882 : /* ==================================================================== */
883 : /************************************************************************/
884 :
885 : /************************************************************************/
886 : /* GDALPDFArrayRW() */
887 : /************************************************************************/
888 :
889 1326 : GDALPDFArrayRW::GDALPDFArrayRW()
890 : {
891 1326 : }
892 :
893 : /************************************************************************/
894 : /* ~GDALPDFArrayRW() */
895 : /************************************************************************/
896 :
897 2537 : GDALPDFArrayRW::~GDALPDFArrayRW()
898 : {
899 5949 : for (size_t i = 0; i < m_array.size(); i++)
900 4623 : delete m_array[i];
901 2537 : }
902 :
903 : /************************************************************************/
904 : /* GetLength() */
905 : /************************************************************************/
906 :
907 5843 : int GDALPDFArrayRW::GetLength()
908 : {
909 5843 : return static_cast<int>(m_array.size());
910 : }
911 :
912 : /************************************************************************/
913 : /* Get() */
914 : /************************************************************************/
915 :
916 4548 : GDALPDFObject *GDALPDFArrayRW::Get(int nIndex)
917 : {
918 4548 : if (nIndex < 0 || nIndex >= GetLength())
919 0 : return nullptr;
920 4548 : return m_array[nIndex];
921 : }
922 :
923 : /************************************************************************/
924 : /* Add() */
925 : /************************************************************************/
926 :
927 4623 : GDALPDFArrayRW &GDALPDFArrayRW::Add(GDALPDFObject *poObj)
928 : {
929 4623 : m_array.push_back(poObj);
930 4623 : return *this;
931 : }
932 :
933 : /************************************************************************/
934 : /* Add() */
935 : /************************************************************************/
936 :
937 0 : GDALPDFArrayRW &GDALPDFArrayRW::Add(double *padfVal, int nCount,
938 : int bCanRepresentRealAsString)
939 : {
940 0 : for (int i = 0; i < nCount; i++)
941 0 : m_array.push_back(
942 0 : GDALPDFObjectRW::CreateReal(padfVal[i], bCanRepresentRealAsString));
943 0 : return *this;
944 : }
945 :
946 : #ifdef HAVE_POPPLER
947 :
948 : /************************************************************************/
949 : /* ==================================================================== */
950 : /* GDALPDFDictionaryPoppler */
951 : /* ==================================================================== */
952 : /************************************************************************/
953 :
954 : class GDALPDFDictionaryPoppler : public GDALPDFDictionary
955 : {
956 : private:
957 : Dict *m_poDict;
958 : std::map<CPLString, GDALPDFObject *> m_map{};
959 :
960 : CPL_DISALLOW_COPY_ASSIGN(GDALPDFDictionaryPoppler)
961 :
962 : public:
963 3213 : GDALPDFDictionaryPoppler(Dict *poDict) : m_poDict(poDict)
964 : {
965 3213 : }
966 :
967 : virtual ~GDALPDFDictionaryPoppler();
968 :
969 : virtual GDALPDFObject *Get(const char *pszKey) override;
970 : virtual std::map<CPLString, GDALPDFObject *> &GetValues() override;
971 : };
972 :
973 : /************************************************************************/
974 : /* ==================================================================== */
975 : /* GDALPDFArrayPoppler */
976 : /* ==================================================================== */
977 : /************************************************************************/
978 :
979 : class GDALPDFArrayPoppler : public GDALPDFArray
980 : {
981 : private:
982 : const Array *m_poArray;
983 : std::vector<std::unique_ptr<GDALPDFObject>> m_v{};
984 :
985 : CPL_DISALLOW_COPY_ASSIGN(GDALPDFArrayPoppler)
986 :
987 : public:
988 975 : GDALPDFArrayPoppler(const Array *poArray) : m_poArray(poArray)
989 : {
990 975 : }
991 :
992 : virtual int GetLength() override;
993 : virtual GDALPDFObject *Get(int nIndex) override;
994 : };
995 :
996 : /************************************************************************/
997 : /* ==================================================================== */
998 : /* GDALPDFStreamPoppler */
999 : /* ==================================================================== */
1000 : /************************************************************************/
1001 :
1002 : class GDALPDFStreamPoppler : public GDALPDFStream
1003 : {
1004 : private:
1005 : int64_t m_nLength = -1;
1006 : Stream *m_poStream;
1007 : int64_t m_nRawLength = -1;
1008 :
1009 : CPL_DISALLOW_COPY_ASSIGN(GDALPDFStreamPoppler)
1010 :
1011 : public:
1012 300 : GDALPDFStreamPoppler(Stream *poStream) : m_poStream(poStream)
1013 : {
1014 300 : }
1015 :
1016 : virtual int64_t GetLength(int64_t nMaxSize = 0) override;
1017 : virtual char *GetBytes() override;
1018 :
1019 : virtual int64_t GetRawLength() override;
1020 : virtual char *GetRawBytes() override;
1021 : };
1022 :
1023 : /************************************************************************/
1024 : /* ==================================================================== */
1025 : /* GDALPDFObjectPoppler */
1026 : /* ==================================================================== */
1027 : /************************************************************************/
1028 :
1029 : /************************************************************************/
1030 : /* ~GDALPDFObjectPoppler() */
1031 : /************************************************************************/
1032 :
1033 22563 : GDALPDFObjectPoppler::~GDALPDFObjectPoppler()
1034 : {
1035 11365 : if (m_bDestroy)
1036 10864 : delete m_po;
1037 11365 : delete m_poDict;
1038 11365 : delete m_poArray;
1039 11365 : delete m_poStream;
1040 22563 : }
1041 :
1042 : /************************************************************************/
1043 : /* GetType() */
1044 : /************************************************************************/
1045 :
1046 46451 : GDALPDFObjectType GDALPDFObjectPoppler::GetType()
1047 : {
1048 46451 : switch (m_po->getType())
1049 : {
1050 136 : case objNull:
1051 136 : return PDFObjectType_Null;
1052 0 : case objBool:
1053 0 : return PDFObjectType_Bool;
1054 14051 : case objInt:
1055 14051 : return PDFObjectType_Int;
1056 4032 : case objReal:
1057 4032 : return PDFObjectType_Real;
1058 1617 : case objString:
1059 1617 : return PDFObjectType_String;
1060 5250 : case objName:
1061 5250 : return PDFObjectType_Name;
1062 10409 : case objArray:
1063 10409 : return PDFObjectType_Array;
1064 7802 : case objDict:
1065 7802 : return PDFObjectType_Dictionary;
1066 3154 : case objStream:
1067 3154 : return PDFObjectType_Dictionary;
1068 0 : default:
1069 0 : return PDFObjectType_Unknown;
1070 : }
1071 : }
1072 :
1073 : /************************************************************************/
1074 : /* GetTypeNameNative() */
1075 : /************************************************************************/
1076 :
1077 0 : const char *GDALPDFObjectPoppler::GetTypeNameNative()
1078 : {
1079 0 : return m_po->getTypeName();
1080 : }
1081 :
1082 : /************************************************************************/
1083 : /* GetBool() */
1084 : /************************************************************************/
1085 :
1086 0 : int GDALPDFObjectPoppler::GetBool()
1087 : {
1088 0 : if (GetType() == PDFObjectType_Bool)
1089 0 : return m_po->getBool();
1090 : else
1091 0 : return 0;
1092 : }
1093 :
1094 : /************************************************************************/
1095 : /* GetInt() */
1096 : /************************************************************************/
1097 :
1098 4450 : int GDALPDFObjectPoppler::GetInt()
1099 : {
1100 4450 : if (GetType() == PDFObjectType_Int)
1101 4450 : return m_po->getInt();
1102 : else
1103 0 : return 0;
1104 : }
1105 :
1106 : /************************************************************************/
1107 : /* GetReal() */
1108 : /************************************************************************/
1109 :
1110 1004 : double GDALPDFObjectPoppler::GetReal()
1111 : {
1112 1004 : if (GetType() == PDFObjectType_Real)
1113 1004 : return m_po->getReal();
1114 : else
1115 0 : return 0.0;
1116 : }
1117 :
1118 : /************************************************************************/
1119 : /* GetString() */
1120 : /************************************************************************/
1121 :
1122 882 : const std::string &GDALPDFObjectPoppler::GetString()
1123 : {
1124 882 : if (GetType() == PDFObjectType_String)
1125 : {
1126 882 : const GooString *gooString = m_po->getString();
1127 882 : const std::string &osStdStr = gooString->toStr();
1128 : const bool bLEUnicodeMarker =
1129 1019 : osStdStr.size() >= 2 && static_cast<uint8_t>(osStdStr[0]) == 0xFE &&
1130 137 : static_cast<uint8_t>(osStdStr[1]) == 0xFF;
1131 : const bool bBEUnicodeMarker =
1132 936 : osStdStr.size() >= 2 && static_cast<uint8_t>(osStdStr[0]) == 0xFF &&
1133 54 : static_cast<uint8_t>(osStdStr[1]) == 0xFE;
1134 882 : if (!bLEUnicodeMarker && !bBEUnicodeMarker)
1135 : {
1136 691 : if (CPLIsUTF8(osStdStr.c_str(), -1))
1137 : {
1138 691 : return osStdStr;
1139 : }
1140 : else
1141 : {
1142 : char *pszUTF8 =
1143 0 : CPLRecode(osStdStr.data(), CPL_ENC_ISO8859_1, CPL_ENC_UTF8);
1144 0 : osStr = pszUTF8;
1145 0 : CPLFree(pszUTF8);
1146 0 : return osStr;
1147 : }
1148 : }
1149 573 : return (osStr = GDALPDFGetUTF8StringFromBytes(
1150 191 : reinterpret_cast<const GByte *>(osStdStr.data()),
1151 191 : osStdStr.size()));
1152 : }
1153 : else
1154 0 : return (osStr = "");
1155 : }
1156 :
1157 : /************************************************************************/
1158 : /* GetName() */
1159 : /************************************************************************/
1160 :
1161 2179 : const std::string &GDALPDFObjectPoppler::GetName()
1162 : {
1163 2179 : if (GetType() == PDFObjectType_Name)
1164 2179 : return (osStr = m_po->getName());
1165 : else
1166 0 : return (osStr = "");
1167 : }
1168 :
1169 : /************************************************************************/
1170 : /* GetDictionary() */
1171 : /************************************************************************/
1172 :
1173 5028 : GDALPDFDictionary *GDALPDFObjectPoppler::GetDictionary()
1174 : {
1175 5028 : if (GetType() != PDFObjectType_Dictionary)
1176 0 : return nullptr;
1177 :
1178 5028 : if (m_poDict)
1179 1815 : return m_poDict;
1180 :
1181 3213 : Dict *poDict = (m_po->getType() == objStream) ? m_po->getStream()->getDict()
1182 2428 : : m_po->getDict();
1183 3213 : if (poDict == nullptr)
1184 0 : return nullptr;
1185 3213 : m_poDict = new GDALPDFDictionaryPoppler(poDict);
1186 3213 : return m_poDict;
1187 : }
1188 :
1189 : /************************************************************************/
1190 : /* GetArray() */
1191 : /************************************************************************/
1192 :
1193 5188 : GDALPDFArray *GDALPDFObjectPoppler::GetArray()
1194 : {
1195 5188 : if (GetType() != PDFObjectType_Array)
1196 0 : return nullptr;
1197 :
1198 5188 : if (m_poArray)
1199 4251 : return m_poArray;
1200 :
1201 937 : Array *poArray = m_po->getArray();
1202 937 : if (poArray == nullptr)
1203 0 : return nullptr;
1204 937 : m_poArray = new GDALPDFArrayPoppler(poArray);
1205 937 : return m_poArray;
1206 : }
1207 :
1208 : /************************************************************************/
1209 : /* GetStream() */
1210 : /************************************************************************/
1211 :
1212 441 : GDALPDFStream *GDALPDFObjectPoppler::GetStream()
1213 : {
1214 441 : if (m_po->getType() != objStream)
1215 14 : return nullptr;
1216 :
1217 427 : if (m_poStream)
1218 127 : return m_poStream;
1219 300 : m_poStream = new GDALPDFStreamPoppler(m_po->getStream());
1220 300 : return m_poStream;
1221 : }
1222 :
1223 : /************************************************************************/
1224 : /* SetRefNumAndGen() */
1225 : /************************************************************************/
1226 :
1227 11031 : void GDALPDFObjectPoppler::SetRefNumAndGen(const GDALPDFObjectNum &nNum,
1228 : int nGen)
1229 : {
1230 11031 : m_nRefNum = nNum;
1231 11031 : m_nRefGen = nGen;
1232 11031 : }
1233 :
1234 : /************************************************************************/
1235 : /* GetRefNum() */
1236 : /************************************************************************/
1237 :
1238 1176 : GDALPDFObjectNum GDALPDFObjectPoppler::GetRefNum()
1239 : {
1240 1176 : return m_nRefNum;
1241 : }
1242 :
1243 : /************************************************************************/
1244 : /* GetRefGen() */
1245 : /************************************************************************/
1246 :
1247 789 : int GDALPDFObjectPoppler::GetRefGen()
1248 : {
1249 789 : return m_nRefGen;
1250 : }
1251 :
1252 : /************************************************************************/
1253 : /* ==================================================================== */
1254 : /* GDALPDFDictionaryPoppler */
1255 : /* ==================================================================== */
1256 : /************************************************************************/
1257 :
1258 : /************************************************************************/
1259 : /* ~GDALPDFDictionaryPoppler() */
1260 : /************************************************************************/
1261 :
1262 6426 : GDALPDFDictionaryPoppler::~GDALPDFDictionaryPoppler()
1263 : {
1264 3213 : std::map<CPLString, GDALPDFObject *>::iterator oIter = m_map.begin();
1265 3213 : std::map<CPLString, GDALPDFObject *>::iterator oEnd = m_map.end();
1266 9929 : for (; oIter != oEnd; ++oIter)
1267 6716 : delete oIter->second;
1268 6426 : }
1269 :
1270 : /************************************************************************/
1271 : /* Get() */
1272 : /************************************************************************/
1273 :
1274 10483 : GDALPDFObject *GDALPDFDictionaryPoppler::Get(const char *pszKey)
1275 : {
1276 10483 : std::map<CPLString, GDALPDFObject *>::iterator oIter = m_map.find(pszKey);
1277 10483 : if (oIter != m_map.end())
1278 1945 : return oIter->second;
1279 :
1280 8538 : auto &&o(m_poDict->lookupNF(pszKey));
1281 8538 : if (!o.isNull())
1282 : {
1283 6716 : GDALPDFObjectNum nRefNum;
1284 6716 : int nRefGen = 0;
1285 6716 : if (o.isRef())
1286 : {
1287 2064 : nRefNum = o.getRefNum();
1288 2064 : nRefGen = o.getRefGen();
1289 2064 : Object o2(m_poDict->lookup(pszKey));
1290 2064 : if (!o2.isNull())
1291 : {
1292 : GDALPDFObjectPoppler *poObj =
1293 2064 : new GDALPDFObjectPoppler(new Object(std::move(o2)), TRUE);
1294 2064 : poObj->SetRefNumAndGen(nRefNum, nRefGen);
1295 2064 : m_map[pszKey] = poObj;
1296 2064 : return poObj;
1297 : }
1298 : }
1299 : else
1300 : {
1301 : GDALPDFObjectPoppler *poObj =
1302 4652 : new GDALPDFObjectPoppler(new Object(o.copy()), TRUE);
1303 4652 : poObj->SetRefNumAndGen(nRefNum, nRefGen);
1304 4652 : m_map[pszKey] = poObj;
1305 4652 : return poObj;
1306 : }
1307 : }
1308 1822 : return nullptr;
1309 : }
1310 :
1311 : /************************************************************************/
1312 : /* GetValues() */
1313 : /************************************************************************/
1314 :
1315 382 : std::map<CPLString, GDALPDFObject *> &GDALPDFDictionaryPoppler::GetValues()
1316 : {
1317 382 : int i = 0;
1318 382 : int nLength = m_poDict->getLength();
1319 1764 : for (i = 0; i < nLength; i++)
1320 : {
1321 1382 : const char *pszKey = m_poDict->getKey(i);
1322 1382 : Get(pszKey);
1323 : }
1324 382 : return m_map;
1325 : }
1326 :
1327 : /************************************************************************/
1328 : /* ==================================================================== */
1329 : /* GDALPDFArrayPoppler */
1330 : /* ==================================================================== */
1331 : /************************************************************************/
1332 :
1333 : /************************************************************************/
1334 : /* GDALPDFCreateArray() */
1335 : /************************************************************************/
1336 :
1337 38 : GDALPDFArray *GDALPDFCreateArray(const Array *array)
1338 : {
1339 38 : return new GDALPDFArrayPoppler(array);
1340 : }
1341 :
1342 : /************************************************************************/
1343 : /* GetLength() */
1344 : /************************************************************************/
1345 :
1346 7192 : int GDALPDFArrayPoppler::GetLength()
1347 : {
1348 7192 : return m_poArray->getLength();
1349 : }
1350 :
1351 : /************************************************************************/
1352 : /* Get() */
1353 : /************************************************************************/
1354 :
1355 4856 : GDALPDFObject *GDALPDFArrayPoppler::Get(int nIndex)
1356 : {
1357 4856 : if (nIndex < 0 || nIndex >= GetLength())
1358 0 : return nullptr;
1359 :
1360 4856 : if (m_v.empty())
1361 953 : m_v.resize(GetLength());
1362 :
1363 4856 : if (m_v[nIndex] != nullptr)
1364 708 : return m_v[nIndex].get();
1365 :
1366 4148 : auto &&o(m_poArray->getNF(nIndex));
1367 4148 : if (!o.isNull())
1368 : {
1369 4148 : GDALPDFObjectNum nRefNum;
1370 4148 : int nRefGen = 0;
1371 4148 : if (o.isRef())
1372 : {
1373 517 : nRefNum = o.getRefNum();
1374 517 : nRefGen = o.getRefGen();
1375 517 : Object o2(m_poArray->get(nIndex));
1376 517 : if (!o2.isNull())
1377 : {
1378 : auto poObj = std::make_unique<GDALPDFObjectPoppler>(
1379 1034 : new Object(std::move(o2)), TRUE);
1380 517 : poObj->SetRefNumAndGen(nRefNum, nRefGen);
1381 517 : m_v[nIndex] = std::move(poObj);
1382 517 : return m_v[nIndex].get();
1383 : }
1384 : }
1385 : else
1386 : {
1387 : auto poObj = std::make_unique<GDALPDFObjectPoppler>(
1388 7262 : new Object(o.copy()), TRUE);
1389 3631 : poObj->SetRefNumAndGen(nRefNum, nRefGen);
1390 3631 : m_v[nIndex] = std::move(poObj);
1391 3631 : return m_v[nIndex].get();
1392 : }
1393 : }
1394 0 : return nullptr;
1395 : }
1396 :
1397 : /************************************************************************/
1398 : /* ==================================================================== */
1399 : /* GDALPDFStreamPoppler */
1400 : /* ==================================================================== */
1401 : /************************************************************************/
1402 :
1403 : /************************************************************************/
1404 : /* GetLength() */
1405 : /************************************************************************/
1406 :
1407 508 : int64_t GDALPDFStreamPoppler::GetLength(int64_t nMaxSize)
1408 : {
1409 508 : if (m_nLength >= 0)
1410 292 : return m_nLength;
1411 :
1412 : #if POPPLER_MAJOR_VERSION > 25 || \
1413 : (POPPLER_MAJOR_VERSION == 25 && POPPLER_MINOR_VERSION >= 2)
1414 : if (!m_poStream->reset())
1415 : return 0;
1416 : #else
1417 216 : m_poStream->reset();
1418 : #endif
1419 216 : m_nLength = 0;
1420 : unsigned char readBuf[4096];
1421 : int readChars;
1422 432 : while ((readChars = m_poStream->doGetChars(4096, readBuf)) != 0)
1423 : {
1424 216 : m_nLength += readChars;
1425 216 : if (nMaxSize != 0 && m_nLength > nMaxSize)
1426 : {
1427 0 : m_nLength = -1;
1428 0 : return std::numeric_limits<int64_t>::max();
1429 : }
1430 : }
1431 216 : return m_nLength;
1432 : }
1433 :
1434 : /************************************************************************/
1435 : /* GooStringToCharStart() */
1436 : /************************************************************************/
1437 :
1438 366 : static char *GooStringToCharStart(GooString &gstr)
1439 : {
1440 366 : auto nLength = gstr.getLength();
1441 366 : if (nLength)
1442 : {
1443 365 : char *pszContent = static_cast<char *>(VSI_MALLOC_VERBOSE(nLength + 1));
1444 365 : if (pszContent)
1445 : {
1446 365 : const char *srcStr = gstr.c_str();
1447 365 : memcpy(pszContent, srcStr, nLength);
1448 365 : pszContent[nLength] = '\0';
1449 : }
1450 365 : return pszContent;
1451 : }
1452 1 : return nullptr;
1453 : }
1454 :
1455 : /************************************************************************/
1456 : /* GetBytes() */
1457 : /************************************************************************/
1458 :
1459 364 : char *GDALPDFStreamPoppler::GetBytes()
1460 : {
1461 728 : GooString gstr;
1462 : try
1463 : {
1464 364 : m_poStream->fillGooString(&gstr);
1465 : }
1466 0 : catch (const std::exception &e)
1467 : {
1468 0 : CPLError(CE_Failure, CPLE_OutOfMemory,
1469 0 : "GDALPDFStreamPoppler::GetBytes(): %s", e.what());
1470 0 : return nullptr;
1471 : }
1472 364 : m_nLength = static_cast<int64_t>(gstr.toStr().size());
1473 364 : return GooStringToCharStart(gstr);
1474 : }
1475 :
1476 : /************************************************************************/
1477 : /* GetRawLength() */
1478 : /************************************************************************/
1479 :
1480 63 : int64_t GDALPDFStreamPoppler::GetRawLength()
1481 : {
1482 63 : if (m_nRawLength >= 0)
1483 2 : return m_nRawLength;
1484 :
1485 61 : auto undecodeStream = m_poStream->getUndecodedStream();
1486 : #if POPPLER_MAJOR_VERSION > 25 || \
1487 : (POPPLER_MAJOR_VERSION == 25 && POPPLER_MINOR_VERSION >= 2)
1488 : if (!undecodeStream->reset())
1489 : return 0;
1490 : #else
1491 61 : undecodeStream->reset();
1492 : #endif
1493 61 : m_nRawLength = 0;
1494 25531 : while (undecodeStream->getChar() != EOF)
1495 25470 : m_nRawLength++;
1496 61 : return m_nRawLength;
1497 : }
1498 :
1499 : /************************************************************************/
1500 : /* GetRawBytes() */
1501 : /************************************************************************/
1502 :
1503 2 : char *GDALPDFStreamPoppler::GetRawBytes()
1504 : {
1505 4 : GooString gstr;
1506 2 : auto undecodeStream = m_poStream->getUndecodedStream();
1507 : try
1508 : {
1509 2 : undecodeStream->fillGooString(&gstr);
1510 : }
1511 0 : catch (const std::exception &e)
1512 : {
1513 0 : CPLError(CE_Failure, CPLE_OutOfMemory,
1514 0 : "GDALPDFStreamPoppler::GetRawBytes(): %s", e.what());
1515 0 : return nullptr;
1516 : }
1517 2 : m_nRawLength = gstr.getLength();
1518 2 : return GooStringToCharStart(gstr);
1519 : }
1520 :
1521 : #endif // HAVE_POPPLER
1522 :
1523 : #ifdef HAVE_PODOFO
1524 :
1525 : /************************************************************************/
1526 : /* ==================================================================== */
1527 : /* GDALPDFDictionaryPodofo */
1528 : /* ==================================================================== */
1529 : /************************************************************************/
1530 :
1531 : class GDALPDFDictionaryPodofo : public GDALPDFDictionary
1532 : {
1533 : private:
1534 : const PoDoFo::PdfDictionary *m_poDict;
1535 : const PoDoFo::PdfVecObjects &m_poObjects;
1536 : std::map<CPLString, GDALPDFObject *> m_map{};
1537 :
1538 : CPL_DISALLOW_COPY_ASSIGN(GDALPDFDictionaryPodofo)
1539 :
1540 : public:
1541 : GDALPDFDictionaryPodofo(const PoDoFo::PdfDictionary *poDict,
1542 : const PoDoFo::PdfVecObjects &poObjects)
1543 : : m_poDict(poDict), m_poObjects(poObjects)
1544 : {
1545 : }
1546 :
1547 : virtual ~GDALPDFDictionaryPodofo();
1548 :
1549 : virtual GDALPDFObject *Get(const char *pszKey) override;
1550 : virtual std::map<CPLString, GDALPDFObject *> &GetValues() override;
1551 : };
1552 :
1553 : /************************************************************************/
1554 : /* ==================================================================== */
1555 : /* GDALPDFArrayPodofo */
1556 : /* ==================================================================== */
1557 : /************************************************************************/
1558 :
1559 : class GDALPDFArrayPodofo : public GDALPDFArray
1560 : {
1561 : private:
1562 : const PoDoFo::PdfArray *m_poArray;
1563 : const PoDoFo::PdfVecObjects &m_poObjects;
1564 : std::vector<std::unique_ptr<GDALPDFObject>> m_v{};
1565 :
1566 : CPL_DISALLOW_COPY_ASSIGN(GDALPDFArrayPodofo)
1567 :
1568 : public:
1569 : GDALPDFArrayPodofo(const PoDoFo::PdfArray *poArray,
1570 : const PoDoFo::PdfVecObjects &poObjects)
1571 : : m_poArray(poArray), m_poObjects(poObjects)
1572 : {
1573 : }
1574 :
1575 : virtual int GetLength() override;
1576 : virtual GDALPDFObject *Get(int nIndex) override;
1577 : };
1578 :
1579 : /************************************************************************/
1580 : /* ==================================================================== */
1581 : /* GDALPDFStreamPodofo */
1582 : /* ==================================================================== */
1583 : /************************************************************************/
1584 :
1585 : class GDALPDFStreamPodofo : public GDALPDFStream
1586 : {
1587 : private:
1588 : #if PODOFO_VERSION_MAJOR > 0 || \
1589 : (PODOFO_VERSION_MAJOR == 0 && PODOFO_VERSION_MINOR >= 10)
1590 : const PoDoFo::PdfObjectStream *m_pStream;
1591 : #else
1592 : const PoDoFo::PdfStream *m_pStream;
1593 : #endif
1594 :
1595 : CPL_DISALLOW_COPY_ASSIGN(GDALPDFStreamPodofo)
1596 :
1597 : public:
1598 : GDALPDFStreamPodofo(
1599 : #if PODOFO_VERSION_MAJOR > 0 || \
1600 : (PODOFO_VERSION_MAJOR == 0 && PODOFO_VERSION_MINOR >= 10)
1601 : const PoDoFo::PdfObjectStream *
1602 : #else
1603 : const PoDoFo::PdfStream *
1604 : #endif
1605 : pStream)
1606 : : m_pStream(pStream)
1607 : {
1608 : }
1609 :
1610 : virtual ~GDALPDFStreamPodofo()
1611 : {
1612 : }
1613 :
1614 : virtual int64_t GetLength(int64_t nMaxSize = 0) override;
1615 : virtual char *GetBytes() override;
1616 :
1617 : virtual int64_t GetRawLength() override;
1618 : virtual char *GetRawBytes() override;
1619 : };
1620 :
1621 : /************************************************************************/
1622 : /* ==================================================================== */
1623 : /* GDALPDFObjectPodofo */
1624 : /* ==================================================================== */
1625 : /************************************************************************/
1626 :
1627 : /************************************************************************/
1628 : /* GDALPDFObjectPodofo() */
1629 : /************************************************************************/
1630 :
1631 : GDALPDFObjectPodofo::GDALPDFObjectPodofo(const PoDoFo::PdfObject *po,
1632 : const PoDoFo::PdfVecObjects &poObjects)
1633 : : m_po(po), m_poObjects(poObjects)
1634 : {
1635 : try
1636 : {
1637 : #if PODOFO_VERSION_MAJOR > 0 || \
1638 : (PODOFO_VERSION_MAJOR == 0 && PODOFO_VERSION_MINOR >= 10)
1639 : if (m_po->GetDataType() == PoDoFo::PdfDataType::Reference)
1640 : {
1641 : PoDoFo::PdfObject *poObj =
1642 : m_poObjects.GetObject(m_po->GetReference());
1643 : if (poObj)
1644 : m_po = poObj;
1645 : }
1646 : #else
1647 : if (m_po->GetDataType() == PoDoFo::ePdfDataType_Reference)
1648 : {
1649 : PoDoFo::PdfObject *poObj =
1650 : m_poObjects.GetObject(m_po->GetReference());
1651 : if (poObj)
1652 : m_po = poObj;
1653 : }
1654 : #endif
1655 : }
1656 : catch (PoDoFo::PdfError &oError)
1657 : {
1658 : CPLError(CE_Failure, CPLE_AppDefined, "Invalid PDF : %s",
1659 : oError.what());
1660 : }
1661 : }
1662 :
1663 : /************************************************************************/
1664 : /* ~GDALPDFObjectPodofo() */
1665 : /************************************************************************/
1666 :
1667 : GDALPDFObjectPodofo::~GDALPDFObjectPodofo()
1668 : {
1669 : delete m_poDict;
1670 : delete m_poArray;
1671 : delete m_poStream;
1672 : }
1673 :
1674 : /************************************************************************/
1675 : /* GetType() */
1676 : /************************************************************************/
1677 :
1678 : GDALPDFObjectType GDALPDFObjectPodofo::GetType()
1679 : {
1680 : try
1681 : {
1682 : switch (m_po->GetDataType())
1683 : {
1684 : #if PODOFO_VERSION_MAJOR > 0 || \
1685 : (PODOFO_VERSION_MAJOR == 0 && PODOFO_VERSION_MINOR >= 10)
1686 : case PoDoFo::PdfDataType::Null:
1687 : return PDFObjectType_Null;
1688 : case PoDoFo::PdfDataType::Bool:
1689 : return PDFObjectType_Bool;
1690 : case PoDoFo::PdfDataType::Number:
1691 : return PDFObjectType_Int;
1692 : case PoDoFo::PdfDataType::Real:
1693 : return PDFObjectType_Real;
1694 : case PoDoFo::PdfDataType::String:
1695 : return PDFObjectType_String;
1696 : case PoDoFo::PdfDataType::Name:
1697 : return PDFObjectType_Name;
1698 : case PoDoFo::PdfDataType::Array:
1699 : return PDFObjectType_Array;
1700 : case PoDoFo::PdfDataType::Dictionary:
1701 : return PDFObjectType_Dictionary;
1702 : default:
1703 : return PDFObjectType_Unknown;
1704 : #else
1705 : case PoDoFo::ePdfDataType_Null:
1706 : return PDFObjectType_Null;
1707 : case PoDoFo::ePdfDataType_Bool:
1708 : return PDFObjectType_Bool;
1709 : case PoDoFo::ePdfDataType_Number:
1710 : return PDFObjectType_Int;
1711 : case PoDoFo::ePdfDataType_Real:
1712 : return PDFObjectType_Real;
1713 : case PoDoFo::ePdfDataType_HexString:
1714 : return PDFObjectType_String;
1715 : case PoDoFo::ePdfDataType_String:
1716 : return PDFObjectType_String;
1717 : case PoDoFo::ePdfDataType_Name:
1718 : return PDFObjectType_Name;
1719 : case PoDoFo::ePdfDataType_Array:
1720 : return PDFObjectType_Array;
1721 : case PoDoFo::ePdfDataType_Dictionary:
1722 : return PDFObjectType_Dictionary;
1723 : default:
1724 : return PDFObjectType_Unknown;
1725 : #endif
1726 : }
1727 : }
1728 : catch (PoDoFo::PdfError &oError)
1729 : {
1730 : CPLError(CE_Failure, CPLE_AppDefined, "Invalid PDF : %s",
1731 : oError.what());
1732 : return PDFObjectType_Unknown;
1733 : }
1734 : }
1735 :
1736 : /************************************************************************/
1737 : /* GetTypeNameNative() */
1738 : /************************************************************************/
1739 :
1740 : const char *GDALPDFObjectPodofo::GetTypeNameNative()
1741 : {
1742 : try
1743 : {
1744 : return m_po->GetDataTypeString();
1745 : }
1746 : catch (PoDoFo::PdfError &oError)
1747 : {
1748 : CPLError(CE_Failure, CPLE_AppDefined, "Invalid PDF : %s",
1749 : oError.what());
1750 : return "unknown";
1751 : }
1752 : }
1753 :
1754 : /************************************************************************/
1755 : /* GetBool() */
1756 : /************************************************************************/
1757 :
1758 : int GDALPDFObjectPodofo::GetBool()
1759 : {
1760 : #if PODOFO_VERSION_MAJOR > 0 || \
1761 : (PODOFO_VERSION_MAJOR == 0 && PODOFO_VERSION_MINOR >= 10)
1762 : if (m_po->GetDataType() == PoDoFo::PdfDataType::Bool)
1763 : #else
1764 : if (m_po->GetDataType() == PoDoFo::ePdfDataType_Bool)
1765 : #endif
1766 : return m_po->GetBool();
1767 : else
1768 : return 0;
1769 : }
1770 :
1771 : /************************************************************************/
1772 : /* GetInt() */
1773 : /************************************************************************/
1774 :
1775 : int GDALPDFObjectPodofo::GetInt()
1776 : {
1777 : #if PODOFO_VERSION_MAJOR > 0 || \
1778 : (PODOFO_VERSION_MAJOR == 0 && PODOFO_VERSION_MINOR >= 10)
1779 : if (m_po->GetDataType() == PoDoFo::PdfDataType::Number)
1780 : #else
1781 : if (m_po->GetDataType() == PoDoFo::ePdfDataType_Number)
1782 : #endif
1783 : return static_cast<int>(m_po->GetNumber());
1784 : else
1785 : return 0;
1786 : }
1787 :
1788 : /************************************************************************/
1789 : /* GetReal() */
1790 : /************************************************************************/
1791 :
1792 : double GDALPDFObjectPodofo::GetReal()
1793 : {
1794 : if (GetType() == PDFObjectType_Real)
1795 : return m_po->GetReal();
1796 : else
1797 : return 0.0;
1798 : }
1799 :
1800 : /************************************************************************/
1801 : /* GetString() */
1802 : /************************************************************************/
1803 :
1804 : const std::string &GDALPDFObjectPodofo::GetString()
1805 : {
1806 : if (GetType() == PDFObjectType_String)
1807 : #if PODOFO_VERSION_MAJOR > 0 || \
1808 : (PODOFO_VERSION_MAJOR == 0 && PODOFO_VERSION_MINOR >= 10)
1809 : return (osStr = m_po->GetString().GetString());
1810 : #else
1811 : return (osStr = m_po->GetString().GetStringUtf8());
1812 : #endif
1813 : else
1814 : return (osStr = "");
1815 : }
1816 :
1817 : /************************************************************************/
1818 : /* GetName() */
1819 : /************************************************************************/
1820 :
1821 : const std::string &GDALPDFObjectPodofo::GetName()
1822 : {
1823 : if (GetType() == PDFObjectType_Name)
1824 : #if PODOFO_VERSION_MAJOR > 0 || \
1825 : (PODOFO_VERSION_MAJOR == 0 && PODOFO_VERSION_MINOR >= 10)
1826 : return (osStr = m_po->GetName().GetString());
1827 : #else
1828 : return (osStr = m_po->GetName().GetName());
1829 : #endif
1830 : else
1831 : return (osStr = "");
1832 : }
1833 :
1834 : /************************************************************************/
1835 : /* GetDictionary() */
1836 : /************************************************************************/
1837 :
1838 : GDALPDFDictionary *GDALPDFObjectPodofo::GetDictionary()
1839 : {
1840 : if (GetType() != PDFObjectType_Dictionary)
1841 : return nullptr;
1842 :
1843 : if (m_poDict)
1844 : return m_poDict;
1845 :
1846 : m_poDict = new GDALPDFDictionaryPodofo(&m_po->GetDictionary(), m_poObjects);
1847 : return m_poDict;
1848 : }
1849 :
1850 : /************************************************************************/
1851 : /* GetArray() */
1852 : /************************************************************************/
1853 :
1854 : GDALPDFArray *GDALPDFObjectPodofo::GetArray()
1855 : {
1856 : if (GetType() != PDFObjectType_Array)
1857 : return nullptr;
1858 :
1859 : if (m_poArray)
1860 : return m_poArray;
1861 :
1862 : m_poArray = new GDALPDFArrayPodofo(&m_po->GetArray(), m_poObjects);
1863 : return m_poArray;
1864 : }
1865 :
1866 : /************************************************************************/
1867 : /* GetStream() */
1868 : /************************************************************************/
1869 :
1870 : GDALPDFStream *GDALPDFObjectPodofo::GetStream()
1871 : {
1872 : try
1873 : {
1874 : if (!m_po->HasStream())
1875 : return nullptr;
1876 : }
1877 : catch (PoDoFo::PdfError &oError)
1878 : {
1879 : CPLError(CE_Failure, CPLE_AppDefined, "Invalid object : %s",
1880 : oError.what());
1881 : return nullptr;
1882 : }
1883 : catch (...)
1884 : {
1885 : CPLError(CE_Failure, CPLE_AppDefined, "Invalid object");
1886 : return nullptr;
1887 : }
1888 :
1889 : if (m_poStream == nullptr)
1890 : m_poStream = new GDALPDFStreamPodofo(m_po->GetStream());
1891 : return m_poStream;
1892 : }
1893 :
1894 : /************************************************************************/
1895 : /* GetRefNum() */
1896 : /************************************************************************/
1897 :
1898 : GDALPDFObjectNum GDALPDFObjectPodofo::GetRefNum()
1899 : {
1900 : #if PODOFO_VERSION_MAJOR > 0 || \
1901 : (PODOFO_VERSION_MAJOR == 0 && PODOFO_VERSION_MINOR >= 10)
1902 : return GDALPDFObjectNum(m_po->GetIndirectReference().ObjectNumber());
1903 : #else
1904 : return GDALPDFObjectNum(m_po->Reference().ObjectNumber());
1905 : #endif
1906 : }
1907 :
1908 : /************************************************************************/
1909 : /* GetRefGen() */
1910 : /************************************************************************/
1911 :
1912 : int GDALPDFObjectPodofo::GetRefGen()
1913 : {
1914 : #if PODOFO_VERSION_MAJOR > 0 || \
1915 : (PODOFO_VERSION_MAJOR == 0 && PODOFO_VERSION_MINOR >= 10)
1916 : return m_po->GetIndirectReference().GenerationNumber();
1917 : #else
1918 : return m_po->Reference().GenerationNumber();
1919 : #endif
1920 : }
1921 :
1922 : /************************************************************************/
1923 : /* ==================================================================== */
1924 : /* GDALPDFDictionaryPodofo */
1925 : /* ==================================================================== */
1926 : /************************************************************************/
1927 :
1928 : /************************************************************************/
1929 : /* ~GDALPDFDictionaryPodofo() */
1930 : /************************************************************************/
1931 :
1932 : GDALPDFDictionaryPodofo::~GDALPDFDictionaryPodofo()
1933 : {
1934 : std::map<CPLString, GDALPDFObject *>::iterator oIter = m_map.begin();
1935 : std::map<CPLString, GDALPDFObject *>::iterator oEnd = m_map.end();
1936 : for (; oIter != oEnd; ++oIter)
1937 : delete oIter->second;
1938 : }
1939 :
1940 : /************************************************************************/
1941 : /* Get() */
1942 : /************************************************************************/
1943 :
1944 : GDALPDFObject *GDALPDFDictionaryPodofo::Get(const char *pszKey)
1945 : {
1946 : std::map<CPLString, GDALPDFObject *>::iterator oIter = m_map.find(pszKey);
1947 : if (oIter != m_map.end())
1948 : return oIter->second;
1949 :
1950 : const PoDoFo::PdfObject *poVal = m_poDict->GetKey(PoDoFo::PdfName(pszKey));
1951 : if (poVal)
1952 : {
1953 : GDALPDFObjectPodofo *poObj =
1954 : new GDALPDFObjectPodofo(poVal, m_poObjects);
1955 : m_map[pszKey] = poObj;
1956 : return poObj;
1957 : }
1958 : else
1959 : {
1960 : return nullptr;
1961 : }
1962 : }
1963 :
1964 : /************************************************************************/
1965 : /* GetValues() */
1966 : /************************************************************************/
1967 :
1968 : std::map<CPLString, GDALPDFObject *> &GDALPDFDictionaryPodofo::GetValues()
1969 : {
1970 : #if PODOFO_VERSION_MAJOR > 0 || \
1971 : (PODOFO_VERSION_MAJOR == 0 && PODOFO_VERSION_MINOR >= 10)
1972 : for (const auto &oIter : *m_poDict)
1973 : {
1974 : Get(oIter.first.GetString().c_str());
1975 : }
1976 : #else
1977 : for (const auto &oIter : m_poDict->GetKeys())
1978 : {
1979 : Get(oIter.first.GetName().c_str());
1980 : }
1981 : #endif
1982 : return m_map;
1983 : }
1984 :
1985 : /************************************************************************/
1986 : /* ==================================================================== */
1987 : /* GDALPDFArrayPodofo */
1988 : /* ==================================================================== */
1989 : /************************************************************************/
1990 :
1991 : /************************************************************************/
1992 : /* GetLength() */
1993 : /************************************************************************/
1994 :
1995 : int GDALPDFArrayPodofo::GetLength()
1996 : {
1997 : return static_cast<int>(m_poArray->GetSize());
1998 : }
1999 :
2000 : /************************************************************************/
2001 : /* Get() */
2002 : /************************************************************************/
2003 :
2004 : GDALPDFObject *GDALPDFArrayPodofo::Get(int nIndex)
2005 : {
2006 : if (nIndex < 0 || nIndex >= GetLength())
2007 : return nullptr;
2008 :
2009 : if (m_v.empty())
2010 : m_v.resize(GetLength());
2011 :
2012 : if (m_v[nIndex] != nullptr)
2013 : return m_v[nIndex].get();
2014 :
2015 : const PoDoFo::PdfObject &oVal = (*m_poArray)[nIndex];
2016 : m_v[nIndex] = std::make_unique<GDALPDFObjectPodofo>(&oVal, m_poObjects);
2017 : return m_v[nIndex].get();
2018 : }
2019 :
2020 : /************************************************************************/
2021 : /* ==================================================================== */
2022 : /* GDALPDFStreamPodofo */
2023 : /* ==================================================================== */
2024 : /************************************************************************/
2025 :
2026 : /************************************************************************/
2027 : /* GetLength() */
2028 : /************************************************************************/
2029 :
2030 : int64_t GDALPDFStreamPodofo::GetLength(int64_t /* nMaxSize */)
2031 : {
2032 : #if PODOFO_VERSION_MAJOR > 0 || \
2033 : (PODOFO_VERSION_MAJOR == 0 && PODOFO_VERSION_MINOR >= 10)
2034 : PoDoFo::charbuff str;
2035 : try
2036 : {
2037 : m_pStream->CopyToSafe(str);
2038 : }
2039 : catch (PoDoFo::PdfError &e)
2040 : {
2041 : CPLError(CE_Failure, CPLE_AppDefined, "CopyToSafe() failed: %s",
2042 : e.what());
2043 : return 0;
2044 : }
2045 : return static_cast<int64_t>(str.size());
2046 : #else
2047 : char *pBuffer = nullptr;
2048 : PoDoFo::pdf_long nLen = 0;
2049 : try
2050 : {
2051 : m_pStream->GetFilteredCopy(&pBuffer, &nLen);
2052 : PoDoFo::podofo_free(pBuffer);
2053 : return static_cast<int64_t>(nLen);
2054 : }
2055 : catch (PoDoFo::PdfError &e)
2056 : {
2057 : }
2058 : return 0;
2059 : #endif
2060 : }
2061 :
2062 : /************************************************************************/
2063 : /* GetBytes() */
2064 : /************************************************************************/
2065 :
2066 : char *GDALPDFStreamPodofo::GetBytes()
2067 : {
2068 : #if PODOFO_VERSION_MAJOR > 0 || \
2069 : (PODOFO_VERSION_MAJOR == 0 && PODOFO_VERSION_MINOR >= 10)
2070 : PoDoFo::charbuff str;
2071 : try
2072 : {
2073 : m_pStream->CopyToSafe(str);
2074 : }
2075 : catch (PoDoFo::PdfError &e)
2076 : {
2077 : CPLError(CE_Failure, CPLE_AppDefined, "CopyToSafe() failed: %s",
2078 : e.what());
2079 : return nullptr;
2080 : }
2081 : char *pszContent = static_cast<char *>(VSI_MALLOC_VERBOSE(str.size() + 1));
2082 : if (!pszContent)
2083 : {
2084 : return nullptr;
2085 : }
2086 : memcpy(pszContent, str.data(), str.size());
2087 : pszContent[str.size()] = '\0';
2088 : return pszContent;
2089 : #else
2090 : char *pBuffer = nullptr;
2091 : PoDoFo::pdf_long nLen = 0;
2092 : try
2093 : {
2094 : m_pStream->GetFilteredCopy(&pBuffer, &nLen);
2095 : }
2096 : catch (PoDoFo::PdfError &e)
2097 : {
2098 : return nullptr;
2099 : }
2100 : char *pszContent = static_cast<char *>(VSI_MALLOC_VERBOSE(nLen + 1));
2101 : if (!pszContent)
2102 : {
2103 : PoDoFo::podofo_free(pBuffer);
2104 : return nullptr;
2105 : }
2106 : memcpy(pszContent, pBuffer, nLen);
2107 : PoDoFo::podofo_free(pBuffer);
2108 : pszContent[nLen] = '\0';
2109 : return pszContent;
2110 : #endif
2111 : }
2112 :
2113 : /************************************************************************/
2114 : /* GetRawLength() */
2115 : /************************************************************************/
2116 :
2117 : int64_t GDALPDFStreamPodofo::GetRawLength()
2118 : {
2119 : try
2120 : {
2121 : auto nLen = m_pStream->GetLength();
2122 : return static_cast<int64_t>(nLen);
2123 : }
2124 : catch (PoDoFo::PdfError &e)
2125 : {
2126 : }
2127 : return 0;
2128 : }
2129 :
2130 : /************************************************************************/
2131 : /* GetRawBytes() */
2132 : /************************************************************************/
2133 :
2134 : char *GDALPDFStreamPodofo::GetRawBytes()
2135 : {
2136 : #if PODOFO_VERSION_MAJOR > 0 || \
2137 : (PODOFO_VERSION_MAJOR == 0 && PODOFO_VERSION_MINOR >= 10)
2138 : PoDoFo::charbuff str;
2139 : try
2140 : {
2141 : PoDoFo::StringStreamDevice stream(str);
2142 : #ifdef USE_HACK_BECAUSE_PdfInputStream_constructor_is_not_exported_in_podofo_0_11
2143 : auto *poNonConstStream =
2144 : const_cast<PoDoFo::PdfObjectStream *>(m_pStream);
2145 : auto inputStream = poNonConstStream->GetProvider().GetInputStream(
2146 : poNonConstStream->GetParent());
2147 : inputStream->CopyTo(stream);
2148 : #else
2149 : // Should work but fails to link because PdfInputStream destructor
2150 : // is not exported
2151 : auto inputStream = m_pStream->GetInputStream(/*raw=*/true);
2152 : inputStream.CopyTo(stream);
2153 : #endif
2154 : stream.Flush();
2155 : }
2156 : catch (PoDoFo::PdfError &e)
2157 : {
2158 : CPLError(CE_Failure, CPLE_AppDefined, "CopyToSafe() failed: %s",
2159 : e.what());
2160 : return nullptr;
2161 : }
2162 : char *pszContent = static_cast<char *>(VSI_MALLOC_VERBOSE(str.size() + 1));
2163 : if (!pszContent)
2164 : {
2165 : return nullptr;
2166 : }
2167 : memcpy(pszContent, str.data(), str.size());
2168 : pszContent[str.size()] = '\0';
2169 : return pszContent;
2170 : #else
2171 : char *pBuffer = nullptr;
2172 : PoDoFo::pdf_long nLen = 0;
2173 : try
2174 : {
2175 : m_pStream->GetCopy(&pBuffer, &nLen);
2176 : }
2177 : catch (PoDoFo::PdfError &e)
2178 : {
2179 : return nullptr;
2180 : }
2181 : char *pszContent = static_cast<char *>(VSI_MALLOC_VERBOSE(nLen + 1));
2182 : if (!pszContent)
2183 : {
2184 : PoDoFo::podofo_free(pBuffer);
2185 : return nullptr;
2186 : }
2187 : memcpy(pszContent, pBuffer, nLen);
2188 : PoDoFo::podofo_free(pBuffer);
2189 : pszContent[nLen] = '\0';
2190 : return pszContent;
2191 : #endif
2192 : }
2193 :
2194 : #endif // HAVE_PODOFO
2195 :
2196 : #ifdef HAVE_PDFIUM
2197 :
2198 : /************************************************************************/
2199 : /* ==================================================================== */
2200 : /* GDALPDFDictionaryPdfium */
2201 : /* ==================================================================== */
2202 : /************************************************************************/
2203 :
2204 : class GDALPDFDictionaryPdfium : public GDALPDFDictionary
2205 : {
2206 : private:
2207 : RetainPtr<const CPDF_Dictionary> m_poDict;
2208 : std::map<CPLString, GDALPDFObject *> m_map{};
2209 :
2210 : public:
2211 4972 : GDALPDFDictionaryPdfium(RetainPtr<const CPDF_Dictionary> poDict)
2212 4972 : : m_poDict(std::move(poDict))
2213 : {
2214 4972 : }
2215 :
2216 : virtual ~GDALPDFDictionaryPdfium();
2217 :
2218 : virtual GDALPDFObject *Get(const char *pszKey) override;
2219 : virtual std::map<CPLString, GDALPDFObject *> &GetValues() override;
2220 : };
2221 :
2222 : /************************************************************************/
2223 : /* ==================================================================== */
2224 : /* GDALPDFArrayPdfium */
2225 : /* ==================================================================== */
2226 : /************************************************************************/
2227 :
2228 : class GDALPDFArrayPdfium : public GDALPDFArray
2229 : {
2230 : private:
2231 : const CPDF_Array *m_poArray;
2232 : std::vector<std::unique_ptr<GDALPDFObject>> m_v{};
2233 :
2234 : CPL_DISALLOW_COPY_ASSIGN(GDALPDFArrayPdfium)
2235 :
2236 : public:
2237 1265 : GDALPDFArrayPdfium(const CPDF_Array *poArray) : m_poArray(poArray)
2238 : {
2239 1265 : }
2240 :
2241 : virtual int GetLength() override;
2242 : virtual GDALPDFObject *Get(int nIndex) override;
2243 : };
2244 :
2245 : /************************************************************************/
2246 : /* ==================================================================== */
2247 : /* GDALPDFStreamPdfium */
2248 : /* ==================================================================== */
2249 : /************************************************************************/
2250 :
2251 : class GDALPDFStreamPdfium : public GDALPDFStream
2252 : {
2253 : private:
2254 : RetainPtr<const CPDF_Stream> m_pStream;
2255 : int64_t m_nSize = 0;
2256 : std::unique_ptr<uint8_t, VSIFreeReleaser> m_pData = nullptr;
2257 : int64_t m_nRawSize = 0;
2258 : std::unique_ptr<uint8_t, VSIFreeReleaser> m_pRawData = nullptr;
2259 :
2260 : void Decompress();
2261 : void FillRaw();
2262 :
2263 : public:
2264 469 : GDALPDFStreamPdfium(RetainPtr<const CPDF_Stream> pStream)
2265 469 : : m_pStream(std::move(pStream))
2266 : {
2267 469 : }
2268 :
2269 : virtual int64_t GetLength(int64_t nMaxSize = 0) override;
2270 : virtual char *GetBytes() override;
2271 :
2272 : virtual int64_t GetRawLength() override;
2273 : virtual char *GetRawBytes() override;
2274 : };
2275 :
2276 : /************************************************************************/
2277 : /* ==================================================================== */
2278 : /* GDALPDFObjectPdfium */
2279 : /* ==================================================================== */
2280 : /************************************************************************/
2281 :
2282 : /************************************************************************/
2283 : /* GDALPDFObjectPdfium() */
2284 : /************************************************************************/
2285 :
2286 15621 : GDALPDFObjectPdfium::GDALPDFObjectPdfium(RetainPtr<const CPDF_Object> obj)
2287 15621 : : m_obj(std::move(obj))
2288 : {
2289 15621 : CPLAssert(m_obj != nullptr);
2290 15621 : }
2291 :
2292 : /************************************************************************/
2293 : /* ~GDALPDFObjectPdfium() */
2294 : /************************************************************************/
2295 :
2296 31242 : GDALPDFObjectPdfium::~GDALPDFObjectPdfium()
2297 : {
2298 15621 : delete m_poDict;
2299 15621 : delete m_poArray;
2300 15621 : delete m_poStream;
2301 31242 : }
2302 :
2303 : /************************************************************************/
2304 : /* Build() */
2305 : /************************************************************************/
2306 :
2307 : GDALPDFObjectPdfium *
2308 18597 : GDALPDFObjectPdfium::Build(RetainPtr<const CPDF_Object> obj)
2309 : {
2310 18597 : if (obj == nullptr)
2311 2976 : return nullptr;
2312 15621 : if (obj->GetType() == CPDF_Object::Type::kReference)
2313 : {
2314 3784 : obj = obj->GetDirect();
2315 3784 : if (obj == nullptr)
2316 : {
2317 0 : CPLError(CE_Failure, CPLE_AppDefined,
2318 : "Cannot resolve indirect object");
2319 0 : return nullptr;
2320 : }
2321 : }
2322 15621 : return new GDALPDFObjectPdfium(std::move(obj));
2323 : }
2324 :
2325 : /************************************************************************/
2326 : /* GetType() */
2327 : /************************************************************************/
2328 :
2329 55272 : GDALPDFObjectType GDALPDFObjectPdfium::GetType()
2330 : {
2331 55272 : switch (m_obj->GetType())
2332 : {
2333 0 : case CPDF_Object::Type::kNullobj:
2334 0 : return PDFObjectType_Null;
2335 0 : case CPDF_Object::Type::kBoolean:
2336 0 : return PDFObjectType_Bool;
2337 15019 : case CPDF_Object::Type::kNumber:
2338 : return (cpl::down_cast<const CPDF_Number *>(m_obj.Get()))
2339 15019 : ->IsInteger()
2340 15019 : ? PDFObjectType_Int
2341 15019 : : PDFObjectType_Real;
2342 2594 : case CPDF_Object::Type::kString:
2343 2594 : return PDFObjectType_String;
2344 6585 : case CPDF_Object::Type::kName:
2345 6585 : return PDFObjectType_Name;
2346 13152 : case CPDF_Object::Type::kArray:
2347 13152 : return PDFObjectType_Array;
2348 13770 : case CPDF_Object::Type::kDictionary:
2349 13770 : return PDFObjectType_Dictionary;
2350 4152 : case CPDF_Object::Type::kStream:
2351 4152 : return PDFObjectType_Dictionary;
2352 0 : case CPDF_Object::Type::kReference:
2353 : // unresolved reference
2354 0 : return PDFObjectType_Unknown;
2355 0 : default:
2356 0 : CPLAssert(false);
2357 : return PDFObjectType_Unknown;
2358 : }
2359 : }
2360 :
2361 : /************************************************************************/
2362 : /* GetTypeNameNative() */
2363 : /************************************************************************/
2364 :
2365 0 : const char *GDALPDFObjectPdfium::GetTypeNameNative()
2366 : {
2367 0 : if (m_obj->GetType() == CPDF_Object::Type::kStream)
2368 0 : return "stream";
2369 : else
2370 0 : return "";
2371 : }
2372 :
2373 : /************************************************************************/
2374 : /* GetBool() */
2375 : /************************************************************************/
2376 :
2377 0 : int GDALPDFObjectPdfium::GetBool()
2378 : {
2379 0 : return m_obj->GetInteger();
2380 : }
2381 :
2382 : /************************************************************************/
2383 : /* GetInt() */
2384 : /************************************************************************/
2385 :
2386 5315 : int GDALPDFObjectPdfium::GetInt()
2387 : {
2388 5315 : return m_obj->GetInteger();
2389 : }
2390 :
2391 : /************************************************************************/
2392 : /* CPLRoundToMoreLikelyDouble() */
2393 : /************************************************************************/
2394 :
2395 : // We try to compensate for rounding errors when converting the number
2396 : // in the PDF expressed as a string (e.g 297.84) to float32 by pdfium :
2397 : // 297.8399963378906 Which is technically correct per the PDF spec, but in
2398 : // practice poppler or podofo use double and Geospatial PDF are often encoded
2399 : // with double precision.
2400 :
2401 1222 : static double CPLRoundToMoreLikelyDouble(float f)
2402 : {
2403 1222 : if (std::round(f) == f)
2404 0 : return f;
2405 :
2406 : char szBuffer[80];
2407 1222 : CPLsnprintf(szBuffer, 80, "%f\n", f);
2408 1222 : double d = f;
2409 1222 : char *pszDot = strchr(szBuffer, '.');
2410 1222 : if (pszDot == nullptr)
2411 0 : return d;
2412 1222 : pszDot++;
2413 1222 : if (pszDot[0] == 0 || pszDot[1] == 0)
2414 0 : return d;
2415 1222 : if (STARTS_WITH(pszDot + 2, "99"))
2416 : {
2417 9 : pszDot[2] = 0;
2418 9 : double d2 = CPLAtof(szBuffer) + 0.01;
2419 9 : float f2 = static_cast<float>(d2);
2420 14 : if (f == f2 || nextafterf(f, f + 1.0f) == f2 ||
2421 5 : nextafterf(f, f - 1.0f) == f2)
2422 4 : d = d2;
2423 : }
2424 1213 : else if (STARTS_WITH(pszDot + 2, "00"))
2425 : {
2426 85 : pszDot[2] = 0;
2427 85 : double d2 = CPLAtof(szBuffer);
2428 85 : float f2 = static_cast<float>(d2);
2429 88 : if (f == f2 || nextafterf(f, f + 1.0f) == f2 ||
2430 3 : nextafterf(f, f - 1.0f) == f2)
2431 82 : d = d2;
2432 : }
2433 1222 : return d;
2434 : }
2435 :
2436 : /************************************************************************/
2437 : /* GetReal() */
2438 : /************************************************************************/
2439 :
2440 1222 : double GDALPDFObjectPdfium::GetReal()
2441 : {
2442 1222 : return CPLRoundToMoreLikelyDouble(m_obj->GetNumber());
2443 : }
2444 :
2445 : /************************************************************************/
2446 : /* GetString() */
2447 : /************************************************************************/
2448 :
2449 1333 : const std::string &GDALPDFObjectPdfium::GetString()
2450 : {
2451 1333 : if (GetType() == PDFObjectType_String)
2452 : {
2453 2666 : const auto bs = m_obj->GetString();
2454 : // If empty string, code crashes
2455 1333 : if (bs.IsEmpty())
2456 1 : return (osStr = "");
2457 1332 : return (osStr = GDALPDFGetUTF8StringFromBytes(
2458 1332 : reinterpret_cast<const GByte *>(bs.c_str()),
2459 2664 : static_cast<int>(bs.GetLength())));
2460 : }
2461 : else
2462 0 : return (osStr = "");
2463 : }
2464 :
2465 : /************************************************************************/
2466 : /* GetName() */
2467 : /************************************************************************/
2468 :
2469 2893 : const std::string &GDALPDFObjectPdfium::GetName()
2470 : {
2471 2893 : if (GetType() == PDFObjectType_Name)
2472 2893 : return (osStr = m_obj->GetString().c_str());
2473 : else
2474 0 : return (osStr = "");
2475 : }
2476 :
2477 : /************************************************************************/
2478 : /* GetDictionary() */
2479 : /************************************************************************/
2480 :
2481 8211 : GDALPDFDictionary *GDALPDFObjectPdfium::GetDictionary()
2482 : {
2483 8211 : if (GetType() != PDFObjectType_Dictionary)
2484 0 : return nullptr;
2485 :
2486 8211 : if (m_poDict)
2487 3239 : return m_poDict;
2488 :
2489 4972 : m_poDict = new GDALPDFDictionaryPdfium(m_obj->GetDict());
2490 4972 : return m_poDict;
2491 : }
2492 :
2493 : /************************************************************************/
2494 : /* GetArray() */
2495 : /************************************************************************/
2496 :
2497 6527 : GDALPDFArray *GDALPDFObjectPdfium::GetArray()
2498 : {
2499 6527 : if (GetType() != PDFObjectType_Array)
2500 0 : return nullptr;
2501 :
2502 6527 : if (m_poArray)
2503 5262 : return m_poArray;
2504 :
2505 1265 : m_poArray =
2506 1265 : new GDALPDFArrayPdfium(cpl::down_cast<const CPDF_Array *>(m_obj.Get()));
2507 1265 : return m_poArray;
2508 : }
2509 :
2510 : /************************************************************************/
2511 : /* GetStream() */
2512 : /************************************************************************/
2513 :
2514 618 : GDALPDFStream *GDALPDFObjectPdfium::GetStream()
2515 : {
2516 618 : if (m_obj->GetType() != CPDF_Object::Type::kStream)
2517 16 : return nullptr;
2518 :
2519 602 : if (m_poStream)
2520 133 : return m_poStream;
2521 938 : auto pStream = pdfium::WrapRetain(m_obj->AsStream());
2522 469 : if (pStream)
2523 : {
2524 469 : m_poStream = new GDALPDFStreamPdfium(std::move(pStream));
2525 469 : return m_poStream;
2526 : }
2527 : else
2528 0 : return nullptr;
2529 : }
2530 :
2531 : /************************************************************************/
2532 : /* GetRefNum() */
2533 : /************************************************************************/
2534 :
2535 2160 : GDALPDFObjectNum GDALPDFObjectPdfium::GetRefNum()
2536 : {
2537 2160 : return GDALPDFObjectNum(m_obj->GetObjNum());
2538 : }
2539 :
2540 : /************************************************************************/
2541 : /* GetRefGen() */
2542 : /************************************************************************/
2543 :
2544 1556 : int GDALPDFObjectPdfium::GetRefGen()
2545 : {
2546 1556 : return m_obj->GetGenNum();
2547 : }
2548 :
2549 : /************************************************************************/
2550 : /* ==================================================================== */
2551 : /* GDALPDFDictionaryPdfium */
2552 : /* ==================================================================== */
2553 : /************************************************************************/
2554 :
2555 : /************************************************************************/
2556 : /* ~GDALPDFDictionaryPdfium() */
2557 : /************************************************************************/
2558 :
2559 9944 : GDALPDFDictionaryPdfium::~GDALPDFDictionaryPdfium()
2560 : {
2561 4972 : std::map<CPLString, GDALPDFObject *>::iterator oIter = m_map.begin();
2562 4972 : std::map<CPLString, GDALPDFObject *>::iterator oEnd = m_map.end();
2563 14543 : for (; oIter != oEnd; ++oIter)
2564 9571 : delete oIter->second;
2565 9944 : }
2566 :
2567 : /************************************************************************/
2568 : /* Get() */
2569 : /************************************************************************/
2570 :
2571 12980 : GDALPDFObject *GDALPDFDictionaryPdfium::Get(const char *pszKey)
2572 : {
2573 12980 : std::map<CPLString, GDALPDFObject *>::iterator oIter = m_map.find(pszKey);
2574 12980 : if (oIter != m_map.end())
2575 2265 : return oIter->second;
2576 :
2577 21430 : ByteString pdfiumKey(pszKey);
2578 : GDALPDFObjectPdfium *poObj =
2579 10715 : GDALPDFObjectPdfium::Build(m_poDict->GetObjectFor(pdfiumKey));
2580 10715 : if (poObj)
2581 : {
2582 7913 : m_map[pszKey] = poObj;
2583 7913 : return poObj;
2584 : }
2585 : else
2586 : {
2587 2802 : return nullptr;
2588 : }
2589 : }
2590 :
2591 : /************************************************************************/
2592 : /* GetValues() */
2593 : /************************************************************************/
2594 :
2595 463 : std::map<CPLString, GDALPDFObject *> &GDALPDFDictionaryPdfium::GetValues()
2596 : {
2597 463 : CPDF_DictionaryLocker dictIterator(m_poDict);
2598 2312 : for (const auto &iter : dictIterator)
2599 : {
2600 : // No object for this key
2601 1849 : if (!iter.second)
2602 0 : continue;
2603 :
2604 1849 : const char *pszKey = iter.first.c_str();
2605 : // Objects exists in the map
2606 1849 : if (m_map.find(pszKey) != m_map.end())
2607 191 : continue;
2608 1658 : GDALPDFObjectPdfium *poObj = GDALPDFObjectPdfium::Build(iter.second);
2609 1658 : if (poObj == nullptr)
2610 0 : continue;
2611 1658 : m_map[pszKey] = poObj;
2612 : }
2613 :
2614 926 : return m_map;
2615 : }
2616 :
2617 : /************************************************************************/
2618 : /* ==================================================================== */
2619 : /* GDALPDFArrayPdfium */
2620 : /* ==================================================================== */
2621 : /************************************************************************/
2622 :
2623 : /************************************************************************/
2624 : /* GetLength() */
2625 : /************************************************************************/
2626 :
2627 9314 : int GDALPDFArrayPdfium::GetLength()
2628 : {
2629 9314 : return static_cast<int>(m_poArray->size());
2630 : }
2631 :
2632 : /************************************************************************/
2633 : /* Get() */
2634 : /************************************************************************/
2635 :
2636 6277 : GDALPDFObject *GDALPDFArrayPdfium::Get(int nIndex)
2637 : {
2638 6277 : if (nIndex < 0 || nIndex >= GetLength())
2639 0 : return nullptr;
2640 :
2641 6277 : if (m_v.empty())
2642 1230 : m_v.resize(GetLength());
2643 :
2644 6277 : if (m_v[nIndex] != nullptr)
2645 897 : return m_v[nIndex].get();
2646 :
2647 : auto poObj = std::unique_ptr<GDALPDFObjectPdfium>(
2648 10760 : GDALPDFObjectPdfium::Build(m_poArray->GetObjectAt(nIndex)));
2649 5380 : if (poObj == nullptr)
2650 0 : return nullptr;
2651 5380 : m_v[nIndex] = std::move(poObj);
2652 5380 : return m_v[nIndex].get();
2653 : }
2654 :
2655 : /************************************************************************/
2656 : /* ==================================================================== */
2657 : /* GDALPDFStreamPdfium */
2658 : /* ==================================================================== */
2659 : /************************************************************************/
2660 :
2661 1108 : void GDALPDFStreamPdfium::Decompress()
2662 : {
2663 1108 : if (m_pData != nullptr)
2664 641 : return;
2665 934 : auto acc(pdfium::MakeRetain<CPDF_StreamAcc>(m_pStream));
2666 467 : acc->LoadAllDataFiltered();
2667 467 : m_nSize = static_cast<int64_t>(acc->GetSize());
2668 467 : m_pData.reset();
2669 467 : const auto nSize = static_cast<size_t>(m_nSize);
2670 467 : if (static_cast<int64_t>(nSize) != m_nSize)
2671 : {
2672 0 : m_nSize = 0;
2673 : }
2674 467 : if (m_nSize)
2675 : {
2676 465 : m_pData.reset(static_cast<uint8_t *>(VSI_MALLOC_VERBOSE(nSize)));
2677 465 : if (!m_pData)
2678 0 : m_nSize = 0;
2679 : else
2680 465 : memcpy(&m_pData.get()[0], acc->DetachData().data(), nSize);
2681 : }
2682 : }
2683 :
2684 : /************************************************************************/
2685 : /* GetLength() */
2686 : /************************************************************************/
2687 :
2688 1108 : int64_t GDALPDFStreamPdfium::GetLength(int64_t /* nMaxSize */)
2689 : {
2690 1108 : Decompress();
2691 1108 : return m_nSize;
2692 : }
2693 :
2694 : /************************************************************************/
2695 : /* GetBytes() */
2696 : /************************************************************************/
2697 :
2698 539 : char *GDALPDFStreamPdfium::GetBytes()
2699 : {
2700 539 : size_t nLength = static_cast<size_t>(GetLength());
2701 539 : if (nLength == 0)
2702 2 : return nullptr;
2703 537 : char *pszContent = static_cast<char *>(VSI_MALLOC_VERBOSE(nLength + 1));
2704 537 : if (!pszContent)
2705 0 : return nullptr;
2706 537 : memcpy(pszContent, m_pData.get(), nLength);
2707 537 : pszContent[nLength] = '\0';
2708 537 : return pszContent;
2709 : }
2710 :
2711 : /************************************************************************/
2712 : /* FillRaw() */
2713 : /************************************************************************/
2714 :
2715 65 : void GDALPDFStreamPdfium::FillRaw()
2716 : {
2717 65 : if (m_pRawData != nullptr)
2718 2 : return;
2719 126 : auto acc(pdfium::MakeRetain<CPDF_StreamAcc>(m_pStream));
2720 63 : acc->LoadAllDataRaw();
2721 63 : m_nRawSize = static_cast<int64_t>(acc->GetSize());
2722 63 : m_pRawData.reset();
2723 63 : const auto nSize = static_cast<size_t>(m_nRawSize);
2724 63 : if (static_cast<int64_t>(nSize) != m_nRawSize)
2725 : {
2726 0 : m_nRawSize = 0;
2727 : }
2728 63 : if (m_nRawSize)
2729 : {
2730 126 : m_pRawData.reset(
2731 63 : static_cast<uint8_t *>(VSI_MALLOC_VERBOSE(m_nRawSize)));
2732 63 : if (!m_pRawData)
2733 0 : m_nRawSize = 0;
2734 : else
2735 63 : memcpy(&m_pRawData.get()[0], acc->DetachData().data(), m_nRawSize);
2736 : }
2737 : }
2738 :
2739 : /************************************************************************/
2740 : /* GetRawLength() */
2741 : /************************************************************************/
2742 :
2743 65 : int64_t GDALPDFStreamPdfium::GetRawLength()
2744 : {
2745 65 : FillRaw();
2746 65 : return m_nRawSize;
2747 : }
2748 :
2749 : /************************************************************************/
2750 : /* GetRawBytes() */
2751 : /************************************************************************/
2752 :
2753 2 : char *GDALPDFStreamPdfium::GetRawBytes()
2754 : {
2755 2 : size_t nLength = static_cast<size_t>(GetRawLength());
2756 2 : if (nLength == 0)
2757 0 : return nullptr;
2758 : char *pszContent =
2759 2 : static_cast<char *>(VSI_MALLOC_VERBOSE(sizeof(char) * (nLength + 1)));
2760 2 : if (!pszContent)
2761 0 : return nullptr;
2762 2 : memcpy(pszContent, m_pRawData.get(), nLength);
2763 2 : pszContent[nLength] = '\0';
2764 2 : return pszContent;
2765 : }
2766 :
2767 : #endif // HAVE_PDFIUM
|