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