1 : /******************************************************************************
2 : * $Id: pdfobject.cpp 25295 2012-12-09 12:27:08Z rouault $
3 : *
4 : * Project: PDF driver
5 : * Purpose: GDALDataset driver for PDF dataset.
6 : * Author: Even Rouault, <even dot rouault at mines dash paris dot org>
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2011, Even Rouault
10 : *
11 : * Permission is hereby granted, free of charge, to any person obtaining a
12 : * copy of this software and associated documentation files (the "Software"),
13 : * to deal in the Software without restriction, including without limitation
14 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 : * and/or sell copies of the Software, and to permit persons to whom the
16 : * Software is furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be included
19 : * in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 : * DEALINGS IN THE SOFTWARE.
28 : ****************************************************************************/
29 :
30 : /* hack for PDF driver and poppler >= 0.15.0 that defines incompatible "typedef bool GBool" */
31 : /* in include/poppler/goo/gtypes.h with the one defined in cpl_port.h */
32 : #define CPL_GBOOL_DEFINED
33 :
34 : #include <vector>
35 : #include "pdfobject.h"
36 :
37 : CPL_CVSID("$Id: pdfobject.cpp 25295 2012-12-09 12:27:08Z rouault $");
38 :
39 : /************************************************************************/
40 : /* ROUND_TO_INT_IF_CLOSE() */
41 : /************************************************************************/
42 :
43 3999 : double ROUND_TO_INT_IF_CLOSE(double x, double eps)
44 : {
45 3999 : if( eps == 0.0 )
46 2967 : eps = fabs(x) < 1 ? 1e-10 : 1e-8;
47 3999 : int nClosestInt = (int)floor(x + 0.5);
48 3999 : if ( fabs(x - nClosestInt) < eps )
49 3284 : return nClosestInt;
50 : else
51 715 : return x;
52 : }
53 :
54 : /************************************************************************/
55 : /* GDALPDFGetPDFString() */
56 : /************************************************************************/
57 :
58 222 : static CPLString GDALPDFGetPDFString(const char* pszStr)
59 : {
60 222 : GByte* pabyData = (GByte*)pszStr;
61 : int i;
62 : GByte ch;
63 18266 : for(i=0;(ch = pabyData[i]) != '\0';i++)
64 : {
65 18049 : if (ch < 32 || ch > 127 ||
66 : ch == '(' || ch == ')' ||
67 : ch == '\\' || ch == '%' || ch == '#')
68 5 : break;
69 : }
70 222 : CPLString osStr;
71 222 : if (ch == 0)
72 : {
73 217 : osStr = "(";
74 217 : osStr += pszStr;
75 217 : osStr += ")";
76 217 : return osStr;
77 : }
78 :
79 5 : wchar_t* pwszDest = CPLRecodeToWChar( pszStr, CPL_ENC_UTF8, CPL_ENC_UCS2 );
80 5 : osStr = "<FEFF";
81 326 : for(i=0;pwszDest[i] != 0;i++)
82 : {
83 : #ifndef _WIN32
84 321 : if (pwszDest[i] >= 0x10000 /* && pwszDest[i] <= 0x10FFFF */)
85 : {
86 : /* Generate UTF-16 surrogate pairs (on Windows, CPLRecodeToWChar does it for us) */
87 0 : int nHeadSurrogate = ((pwszDest[i] - 0x10000) >> 10) | 0xd800;
88 0 : int nTrailSurrogate = ((pwszDest[i] - 0x10000) & 0x3ff) | 0xdc00;
89 0 : osStr += CPLSPrintf("%02X", (nHeadSurrogate >> 8) & 0xff);
90 0 : osStr += CPLSPrintf("%02X", (nHeadSurrogate) & 0xff);
91 0 : osStr += CPLSPrintf("%02X", (nTrailSurrogate >> 8) & 0xff);
92 0 : osStr += CPLSPrintf("%02X", (nTrailSurrogate) & 0xff);
93 : }
94 : else
95 : #endif
96 : {
97 321 : osStr += CPLSPrintf("%02X", (pwszDest[i] >> 8) & 0xff);
98 321 : osStr += CPLSPrintf("%02X", (pwszDest[i]) & 0xff);
99 : }
100 : }
101 5 : osStr += ">";
102 5 : CPLFree(pwszDest);
103 5 : return osStr;
104 : }
105 :
106 : /************************************************************************/
107 : /* GDALPDFGetPDFName() */
108 : /************************************************************************/
109 :
110 1500 : static CPLString GDALPDFGetPDFName(const char* pszStr)
111 : {
112 1500 : GByte* pabyData = (GByte*)pszStr;
113 : int i;
114 : GByte ch;
115 1500 : CPLString osStr;
116 12816 : for(i=0;(ch = pabyData[i]) != '\0';i++)
117 : {
118 11316 : if (!((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9') || ch == '-'))
119 0 : osStr += '_';
120 : else
121 11316 : osStr += ch;
122 : }
123 0 : return osStr;
124 : }
125 :
126 : /************************************************************************/
127 : /* ==================================================================== */
128 : /* GDALPDFObject */
129 : /* ==================================================================== */
130 : /************************************************************************/
131 :
132 : /************************************************************************/
133 : /* ~GDALPDFObject() */
134 : /************************************************************************/
135 :
136 23356 : GDALPDFObject::~GDALPDFObject()
137 : {
138 23356 : }
139 :
140 : /************************************************************************/
141 : /* GetTypeName() */
142 : /************************************************************************/
143 :
144 0 : const char* GDALPDFObject::GetTypeName()
145 : {
146 0 : switch(GetType())
147 : {
148 0 : case PDFObjectType_Unknown: return GetTypeNameNative();
149 0 : case PDFObjectType_Null: return "null";
150 0 : case PDFObjectType_Bool: return "bool";
151 0 : case PDFObjectType_Int: return "int";
152 0 : case PDFObjectType_Real: return "real";
153 0 : case PDFObjectType_String: return "string";
154 0 : case PDFObjectType_Name: return "name";
155 0 : case PDFObjectType_Array: return "array";
156 0 : case PDFObjectType_Dictionary: return "dictionary";
157 0 : default: return GetTypeNameNative();
158 : }
159 : }
160 :
161 : /************************************************************************/
162 : /* Serialize() */
163 : /************************************************************************/
164 :
165 7005 : void GDALPDFObject::Serialize(CPLString& osStr)
166 : {
167 7005 : int nRefNum = GetRefNum();
168 7005 : if( nRefNum )
169 : {
170 1241 : int nRefGen = GetRefGen();
171 1241 : osStr.append(CPLSPrintf("%d %d R", nRefNum, nRefGen));
172 1241 : return;
173 : }
174 :
175 5764 : switch(GetType())
176 : {
177 0 : case PDFObjectType_Null: osStr.append("null"); return;
178 3 : case PDFObjectType_Bool: osStr.append(GetBool() ? "true": "false"); return;
179 1909 : case PDFObjectType_Int: osStr.append(CPLSPrintf("%d", GetInt())); return;
180 : case PDFObjectType_Real:
181 : {
182 : char szReal[512];
183 1395 : double dfRealNonRounded = GetReal();
184 1395 : double dfReal = ROUND_TO_INT_IF_CLOSE(dfRealNonRounded);
185 1395 : if (dfReal == (double)(int)dfReal)
186 957 : sprintf(szReal, "%d", (int)dfReal);
187 438 : else if (CanRepresentRealAsString())
188 : {
189 : /* Used for OGC BP numeric values */
190 39 : sprintf(szReal, "(%.16g)", dfReal);
191 : }
192 : else
193 : {
194 399 : sprintf(szReal, "%.16f", dfReal);
195 :
196 : /* Remove non significant trailing zeroes */
197 399 : char* pszDot = strchr(szReal, '.');
198 399 : if (pszDot)
199 : {
200 399 : int iDot = (int)(pszDot - szReal);
201 399 : int nLen = (int)strlen(szReal);
202 1894 : for(int i=nLen-1; i > iDot; i --)
203 : {
204 947 : if (szReal[i] == '0')
205 548 : szReal[i] = '\0';
206 : else
207 399 : break;
208 : }
209 : }
210 : }
211 1395 : osStr.append(szReal);
212 1395 : return;
213 : }
214 222 : case PDFObjectType_String: osStr.append(GDALPDFGetPDFString(GetString())); return;
215 1500 : case PDFObjectType_Name: osStr.append("/"); osStr.append(GDALPDFGetPDFName(GetName())); return;
216 460 : case PDFObjectType_Array: GetArray()->Serialize(osStr); return;
217 275 : case PDFObjectType_Dictionary: GetDictionary()->Serialize(osStr); return;
218 : case PDFObjectType_Unknown:
219 0 : default: fprintf(stderr, "Serializing unknown object !\n"); return;
220 : }
221 : }
222 :
223 : /************************************************************************/
224 : /* Clone() */
225 : /************************************************************************/
226 :
227 293 : GDALPDFObjectRW* GDALPDFObject::Clone()
228 : {
229 293 : int nRefNum = GetRefNum();
230 293 : if( nRefNum )
231 : {
232 116 : int nRefGen = GetRefGen();
233 116 : return GDALPDFObjectRW::CreateIndirect(nRefNum, nRefGen);
234 : }
235 :
236 177 : switch(GetType())
237 : {
238 0 : case PDFObjectType_Null: return GDALPDFObjectRW::CreateNull();
239 0 : case PDFObjectType_Bool: return GDALPDFObjectRW::CreateBool(GetBool());
240 98 : case PDFObjectType_Int: return GDALPDFObjectRW::CreateInt(GetInt());
241 12 : case PDFObjectType_Real: return GDALPDFObjectRW::CreateReal(GetReal());
242 0 : case PDFObjectType_String: return GDALPDFObjectRW::CreateString(GetString());
243 28 : case PDFObjectType_Name: return GDALPDFObjectRW::CreateName(GetName());
244 39 : case PDFObjectType_Array: return GDALPDFObjectRW::CreateArray(GetArray()->Clone());
245 0 : case PDFObjectType_Dictionary: return GDALPDFObjectRW::CreateDictionary(GetDictionary()->Clone());
246 : case PDFObjectType_Unknown:
247 0 : default: fprintf(stderr, "Cloning unknown object !\n"); return NULL;
248 : }
249 : }
250 :
251 : /************************************************************************/
252 : /* ==================================================================== */
253 : /* GDALPDFDictionary */
254 : /* ==================================================================== */
255 : /************************************************************************/
256 :
257 : /************************************************************************/
258 : /* ~GDALPDFDictionary() */
259 : /************************************************************************/
260 :
261 4976 : GDALPDFDictionary::~GDALPDFDictionary()
262 : {
263 4976 : }
264 :
265 : /************************************************************************/
266 : /* Serialize() */
267 : /************************************************************************/
268 :
269 1066 : void GDALPDFDictionary::Serialize(CPLString& osStr)
270 : {
271 1066 : osStr.append("<< ");
272 1066 : std::map<CPLString, GDALPDFObject*>& oMap = GetValues();
273 1066 : std::map<CPLString, GDALPDFObject*>::iterator oIter = oMap.begin();
274 1066 : std::map<CPLString, GDALPDFObject*>::iterator oEnd = oMap.end();
275 5502 : for(;oIter != oEnd;++oIter)
276 : {
277 4436 : const char* pszKey = oIter->first.c_str();
278 4436 : GDALPDFObject* poObj = oIter->second;
279 4436 : osStr.append("/");
280 4436 : osStr.append(pszKey);
281 4436 : osStr.append(" ");
282 4436 : poObj->Serialize(osStr);
283 4436 : osStr.append(" ");
284 : }
285 1066 : osStr.append(">>");
286 1066 : }
287 :
288 : /************************************************************************/
289 : /* Clone() */
290 : /************************************************************************/
291 :
292 28 : GDALPDFDictionaryRW* GDALPDFDictionary::Clone()
293 : {
294 28 : GDALPDFDictionaryRW* poDict = new GDALPDFDictionaryRW();
295 28 : std::map<CPLString, GDALPDFObject*>& oMap = GetValues();
296 28 : std::map<CPLString, GDALPDFObject*>::iterator oIter = oMap.begin();
297 28 : std::map<CPLString, GDALPDFObject*>::iterator oEnd = oMap.end();
298 216 : for(;oIter != oEnd;++oIter)
299 : {
300 188 : const char* pszKey = oIter->first.c_str();
301 188 : GDALPDFObject* poObj = oIter->second;
302 188 : poDict->Add(pszKey, poObj->Clone());
303 : }
304 28 : return poDict;
305 : }
306 :
307 : /************************************************************************/
308 : /* ==================================================================== */
309 : /* GDALPDFArray */
310 : /* ==================================================================== */
311 : /************************************************************************/
312 :
313 : /************************************************************************/
314 : /* ~GDALPDFArray() */
315 : /************************************************************************/
316 :
317 1757 : GDALPDFArray::~GDALPDFArray()
318 : {
319 1757 : }
320 :
321 : /************************************************************************/
322 : /* Serialize() */
323 : /************************************************************************/
324 :
325 514 : void GDALPDFArray::Serialize(CPLString& osStr)
326 : {
327 514 : int nLength = GetLength();
328 : int i;
329 :
330 514 : osStr.append("[ ");
331 2563 : for(i=0;i<nLength;i++)
332 : {
333 2049 : Get(i)->Serialize(osStr);
334 2049 : osStr.append(" ");
335 : }
336 514 : osStr.append("]");
337 514 : }
338 :
339 : /************************************************************************/
340 : /* Clone() */
341 : /************************************************************************/
342 :
343 39 : GDALPDFArrayRW* GDALPDFArray::Clone()
344 : {
345 39 : GDALPDFArrayRW* poArray = new GDALPDFArrayRW();
346 39 : int nLength = GetLength();
347 : int i;
348 144 : for(i=0;i<nLength;i++)
349 : {
350 105 : poArray->Add(Get(i)->Clone());
351 : }
352 39 : return poArray;
353 : }
354 :
355 : /************************************************************************/
356 : /* ==================================================================== */
357 : /* GDALPDFStream */
358 : /* ==================================================================== */
359 : /************************************************************************/
360 :
361 : /************************************************************************/
362 : /* ~GDALPDFStream() */
363 : /************************************************************************/
364 :
365 398 : GDALPDFStream::~GDALPDFStream()
366 : {
367 398 : }
368 :
369 : /************************************************************************/
370 : /* ==================================================================== */
371 : /* GDALPDFObjectRW */
372 : /* ==================================================================== */
373 : /************************************************************************/
374 :
375 : /************************************************************************/
376 : /* GDALPDFObjectRW() */
377 : /************************************************************************/
378 :
379 7176 : GDALPDFObjectRW::GDALPDFObjectRW(GDALPDFObjectType eType)
380 : {
381 7176 : m_eType = eType;
382 7176 : m_nVal = 0;
383 7176 : m_dfVal = 0.0;
384 : //m_osVal;
385 7176 : m_poDict = NULL;
386 7176 : m_poArray = NULL;
387 7176 : m_nNum = 0;
388 7176 : m_nGen = 0;
389 7176 : m_bCanRepresentRealAsString = FALSE;
390 7176 : }
391 :
392 : /************************************************************************/
393 : /* ~GDALPDFObjectRW() */
394 : /************************************************************************/
395 :
396 7176 : GDALPDFObjectRW::~GDALPDFObjectRW()
397 : {
398 7176 : delete m_poDict;
399 7176 : delete m_poArray;
400 7176 : }
401 :
402 : /************************************************************************/
403 : /* CreateIndirect() */
404 : /************************************************************************/
405 :
406 1311 : GDALPDFObjectRW* GDALPDFObjectRW::CreateIndirect(int nNum, int nGen)
407 : {
408 1311 : GDALPDFObjectRW* poObj = new GDALPDFObjectRW(PDFObjectType_Unknown);
409 1311 : poObj->m_nNum = nNum;
410 1311 : poObj->m_nGen = nGen;
411 1311 : return poObj;
412 : }
413 :
414 : /************************************************************************/
415 : /* CreateNull() */
416 : /************************************************************************/
417 :
418 0 : GDALPDFObjectRW* GDALPDFObjectRW::CreateNull()
419 : {
420 0 : return new GDALPDFObjectRW(PDFObjectType_Null);
421 : }
422 :
423 : /************************************************************************/
424 : /* CreateBool() */
425 : /************************************************************************/
426 :
427 3 : GDALPDFObjectRW* GDALPDFObjectRW::CreateBool(int bVal)
428 : {
429 3 : GDALPDFObjectRW* poObj = new GDALPDFObjectRW(PDFObjectType_Bool);
430 3 : poObj->m_nVal = bVal;
431 3 : return poObj;
432 : }
433 :
434 : /************************************************************************/
435 : /* CreateInt() */
436 : /************************************************************************/
437 :
438 1969 : GDALPDFObjectRW* GDALPDFObjectRW::CreateInt(int nVal)
439 : {
440 1969 : GDALPDFObjectRW* poObj = new GDALPDFObjectRW(PDFObjectType_Int);
441 1969 : poObj->m_nVal = nVal;
442 1969 : return poObj;
443 : }
444 :
445 : /************************************************************************/
446 : /* CreateReal() */
447 : /************************************************************************/
448 :
449 1395 : GDALPDFObjectRW* GDALPDFObjectRW::CreateReal(double dfVal,
450 : int bCanRepresentRealAsString)
451 : {
452 1395 : GDALPDFObjectRW* poObj = new GDALPDFObjectRW(PDFObjectType_Real);
453 1395 : poObj->m_dfVal = dfVal;
454 1395 : poObj->m_bCanRepresentRealAsString = bCanRepresentRealAsString;
455 1395 : return poObj;
456 : }
457 :
458 : /************************************************************************/
459 : /* CreateString() */
460 : /************************************************************************/
461 :
462 222 : GDALPDFObjectRW* GDALPDFObjectRW::CreateString(const char* pszStr)
463 : {
464 222 : GDALPDFObjectRW* poObj = new GDALPDFObjectRW(PDFObjectType_String);
465 444 : poObj->m_osVal = pszStr;
466 222 : return poObj;
467 : }
468 :
469 : /************************************************************************/
470 : /* CreateName() */
471 : /************************************************************************/
472 :
473 1512 : GDALPDFObjectRW* GDALPDFObjectRW::CreateName(const char* pszName)
474 : {
475 1512 : GDALPDFObjectRW* poObj = new GDALPDFObjectRW(PDFObjectType_Name);
476 3024 : poObj->m_osVal = pszName;
477 1512 : return poObj;
478 : }
479 :
480 : /************************************************************************/
481 : /* CreateDictionary() */
482 : /************************************************************************/
483 :
484 275 : GDALPDFObjectRW* GDALPDFObjectRW::CreateDictionary(GDALPDFDictionaryRW* poDict)
485 : {
486 275 : CPLAssert(poDict);
487 275 : GDALPDFObjectRW* poObj = new GDALPDFObjectRW(PDFObjectType_Dictionary);
488 275 : poObj->m_poDict = poDict;
489 275 : return poObj;
490 : }
491 :
492 : /************************************************************************/
493 : /* CreateArray() */
494 : /************************************************************************/
495 :
496 489 : GDALPDFObjectRW* GDALPDFObjectRW::CreateArray(GDALPDFArrayRW* poArray)
497 : {
498 489 : CPLAssert(poArray);
499 489 : GDALPDFObjectRW* poObj = new GDALPDFObjectRW(PDFObjectType_Array);
500 489 : poObj->m_poArray = poArray;
501 489 : return poObj;
502 : }
503 :
504 : /************************************************************************/
505 : /* GetTypeNameNative() */
506 : /************************************************************************/
507 :
508 0 : const char* GDALPDFObjectRW::GetTypeNameNative()
509 : {
510 0 : fprintf(stderr, "Should not go here");
511 0 : return "";
512 : }
513 :
514 : /************************************************************************/
515 : /* GetType() */
516 : /************************************************************************/
517 :
518 5764 : GDALPDFObjectType GDALPDFObjectRW::GetType()
519 : {
520 5764 : return m_eType;
521 : }
522 :
523 : /************************************************************************/
524 : /* GetBool() */
525 : /************************************************************************/
526 :
527 3 : int GDALPDFObjectRW::GetBool()
528 : {
529 3 : if (m_eType == PDFObjectType_Bool)
530 3 : return m_nVal;
531 :
532 0 : return FALSE;
533 : }
534 :
535 : /************************************************************************/
536 : /* GetInt() */
537 : /************************************************************************/
538 :
539 1909 : int GDALPDFObjectRW::GetInt()
540 : {
541 1909 : if (m_eType == PDFObjectType_Int)
542 1909 : return m_nVal;
543 :
544 0 : return 0;
545 : }
546 :
547 : /************************************************************************/
548 : /* GetReal() */
549 : /************************************************************************/
550 :
551 1395 : double GDALPDFObjectRW::GetReal()
552 : {
553 1395 : return m_dfVal;
554 : }
555 :
556 : /************************************************************************/
557 : /* GetString() */
558 : /************************************************************************/
559 :
560 222 : const CPLString& GDALPDFObjectRW::GetString()
561 : {
562 222 : return m_osVal;
563 : }
564 :
565 : /************************************************************************/
566 : /* GetName() */
567 : /************************************************************************/
568 :
569 1500 : const CPLString& GDALPDFObjectRW::GetName()
570 : {
571 1500 : return m_osVal;
572 : }
573 :
574 : /************************************************************************/
575 : /* GetDictionary() */
576 : /************************************************************************/
577 :
578 275 : GDALPDFDictionary* GDALPDFObjectRW::GetDictionary()
579 : {
580 275 : return m_poDict;
581 : }
582 :
583 : /************************************************************************/
584 : /* GetArray() */
585 : /************************************************************************/
586 :
587 460 : GDALPDFArray* GDALPDFObjectRW::GetArray()
588 : {
589 460 : return m_poArray;
590 : }
591 :
592 : /************************************************************************/
593 : /* GetStream() */
594 : /************************************************************************/
595 :
596 0 : GDALPDFStream* GDALPDFObjectRW::GetStream()
597 : {
598 0 : return NULL;
599 : }
600 :
601 : /************************************************************************/
602 : /* GetRefNum() */
603 : /************************************************************************/
604 :
605 7009 : int GDALPDFObjectRW::GetRefNum()
606 : {
607 7009 : return m_nNum;
608 : }
609 :
610 : /************************************************************************/
611 : /* GetRefGen() */
612 : /************************************************************************/
613 :
614 1245 : int GDALPDFObjectRW::GetRefGen()
615 : {
616 1245 : return m_nGen;
617 : }
618 :
619 : /************************************************************************/
620 : /* ==================================================================== */
621 : /* GDALPDFDictionaryRW */
622 : /* ==================================================================== */
623 : /************************************************************************/
624 :
625 : /************************************************************************/
626 : /* GDALPDFDictionaryRW() */
627 : /************************************************************************/
628 :
629 1078 : GDALPDFDictionaryRW::GDALPDFDictionaryRW()
630 : {
631 1078 : }
632 :
633 : /************************************************************************/
634 : /* ~GDALPDFDictionaryRW() */
635 : /************************************************************************/
636 :
637 1078 : GDALPDFDictionaryRW::~GDALPDFDictionaryRW()
638 : {
639 1078 : std::map<CPLString, GDALPDFObject*>::iterator oIter = m_map.begin();
640 1078 : std::map<CPLString, GDALPDFObject*>::iterator oEnd = m_map.end();
641 5610 : for(; oIter != oEnd; ++oIter)
642 4532 : delete oIter->second;
643 1078 : }
644 :
645 : /************************************************************************/
646 : /* Get() */
647 : /************************************************************************/
648 :
649 6 : GDALPDFObject* GDALPDFDictionaryRW::Get(const char* pszKey)
650 : {
651 6 : std::map<CPLString, GDALPDFObject*>::iterator oIter = m_map.find(pszKey);
652 6 : if (oIter != m_map.end())
653 4 : return oIter->second;
654 2 : return NULL;
655 : }
656 :
657 : /************************************************************************/
658 : /* GetValues() */
659 : /************************************************************************/
660 :
661 1066 : std::map<CPLString, GDALPDFObject*>& GDALPDFDictionaryRW::GetValues()
662 : {
663 1066 : return m_map;
664 : }
665 :
666 : /************************************************************************/
667 : /* Add() */
668 : /************************************************************************/
669 :
670 4542 : GDALPDFDictionaryRW& GDALPDFDictionaryRW::Add(const char* pszKey, GDALPDFObject* poVal)
671 : {
672 4542 : std::map<CPLString, GDALPDFObject*>::iterator oIter = m_map.find(pszKey);
673 4542 : if (oIter != m_map.end())
674 : {
675 0 : delete oIter->second;
676 0 : oIter->second = poVal;
677 : }
678 : else
679 4542 : m_map[pszKey] = poVal;
680 :
681 4542 : return *this;
682 : }
683 :
684 : /************************************************************************/
685 : /* Remove() */
686 : /************************************************************************/
687 :
688 26 : GDALPDFDictionaryRW& GDALPDFDictionaryRW::Remove(const char* pszKey)
689 : {
690 26 : std::map<CPLString, GDALPDFObject*>::iterator oIter = m_map.find(pszKey);
691 26 : if (oIter != m_map.end())
692 : {
693 10 : delete oIter->second;
694 10 : m_map.erase(pszKey);
695 : }
696 :
697 26 : return *this;
698 : }
699 :
700 : /************************************************************************/
701 : /* ==================================================================== */
702 : /* GDALPDFArrayRW */
703 : /* ==================================================================== */
704 : /************************************************************************/
705 :
706 : /************************************************************************/
707 : /* GDALPDFArrayRW() */
708 : /************************************************************************/
709 :
710 543 : GDALPDFArrayRW::GDALPDFArrayRW()
711 : {
712 543 : }
713 :
714 : /************************************************************************/
715 : /* ~GDALPDFArrayRW() */
716 : /************************************************************************/
717 :
718 543 : GDALPDFArrayRW::~GDALPDFArrayRW()
719 : {
720 2657 : for(int i=0; i < (int)m_array.size(); i++)
721 2114 : delete m_array[i];
722 543 : }
723 :
724 : /************************************************************************/
725 : /* GetLength() */
726 : /************************************************************************/
727 :
728 2564 : int GDALPDFArrayRW::GetLength()
729 : {
730 2564 : return (int)m_array.size();
731 : }
732 :
733 : /************************************************************************/
734 : /* Get() */
735 : /************************************************************************/
736 :
737 2049 : GDALPDFObject* GDALPDFArrayRW::Get(int nIndex)
738 : {
739 2049 : if (nIndex < 0 || nIndex >= GetLength())
740 0 : return NULL;
741 2049 : return m_array[nIndex];
742 : }
743 :
744 : /************************************************************************/
745 : /* Add() */
746 : /************************************************************************/
747 :
748 2070 : GDALPDFArrayRW& GDALPDFArrayRW::Add(GDALPDFObject* poObj)
749 : {
750 2070 : m_array.push_back(poObj);
751 2070 : return *this;
752 : }
753 :
754 : /************************************************************************/
755 : /* Add() */
756 : /************************************************************************/
757 :
758 7 : GDALPDFArrayRW& GDALPDFArrayRW::Add(double* padfVal, int nCount,
759 : int bCanRepresentRealAsString)
760 : {
761 51 : for(int i=0;i<nCount;i++)
762 44 : m_array.push_back(GDALPDFObjectRW::CreateReal(padfVal[i], bCanRepresentRealAsString));
763 7 : return *this;
764 : }
765 :
766 : #ifdef HAVE_POPPLER
767 :
768 : /************************************************************************/
769 : /* ==================================================================== */
770 : /* GDALPDFDictionaryPoppler */
771 : /* ==================================================================== */
772 : /************************************************************************/
773 :
774 : class GDALPDFDictionaryPoppler: public GDALPDFDictionary
775 : {
776 : private:
777 : Dict* m_poDict;
778 : std::map<CPLString, GDALPDFObject*> m_map;
779 :
780 : public:
781 3053 : GDALPDFDictionaryPoppler(Dict* poDict) : m_poDict(poDict) {}
782 : virtual ~GDALPDFDictionaryPoppler();
783 :
784 : virtual GDALPDFObject* Get(const char* pszKey);
785 : virtual std::map<CPLString, GDALPDFObject*>& GetValues();
786 : };
787 :
788 : /************************************************************************/
789 : /* ==================================================================== */
790 : /* GDALPDFArrayPoppler */
791 : /* ==================================================================== */
792 : /************************************************************************/
793 :
794 : class GDALPDFArrayPoppler : public GDALPDFArray
795 : {
796 : private:
797 : Array* m_poArray;
798 : std::vector<GDALPDFObject*> m_v;
799 :
800 : public:
801 1068 : GDALPDFArrayPoppler(Array* poArray) : m_poArray(poArray) {}
802 : virtual ~GDALPDFArrayPoppler();
803 :
804 : virtual int GetLength();
805 : virtual GDALPDFObject* Get(int nIndex);
806 : };
807 :
808 : /************************************************************************/
809 : /* ==================================================================== */
810 : /* GDALPDFStreamPoppler */
811 : /* ==================================================================== */
812 : /************************************************************************/
813 :
814 : class GDALPDFStreamPoppler : public GDALPDFStream
815 : {
816 : private:
817 : int m_nLength;
818 : Stream* m_poStream;
819 :
820 : public:
821 285 : GDALPDFStreamPoppler(Stream* poStream) : m_nLength(-1), m_poStream(poStream) {}
822 285 : virtual ~GDALPDFStreamPoppler() {}
823 :
824 : virtual int GetLength();
825 : virtual char* GetBytes();
826 : };
827 :
828 : /************************************************************************/
829 : /* ==================================================================== */
830 : /* GDALPDFObjectPoppler */
831 : /* ==================================================================== */
832 : /************************************************************************/
833 :
834 : /************************************************************************/
835 : /* ~GDALPDFObjectPoppler() */
836 : /************************************************************************/
837 :
838 12582 : GDALPDFObjectPoppler::~GDALPDFObjectPoppler()
839 : {
840 12582 : m_po->free();
841 12582 : if (m_bDestroy)
842 12282 : delete m_po;
843 12582 : delete m_poDict;
844 12582 : delete m_poArray;
845 12582 : delete m_poStream;
846 12582 : }
847 :
848 : /************************************************************************/
849 : /* GetType() */
850 : /************************************************************************/
851 :
852 50543 : GDALPDFObjectType GDALPDFObjectPoppler::GetType()
853 : {
854 50543 : switch(m_po->getType())
855 : {
856 127 : case objNull: return PDFObjectType_Null;
857 0 : case objBool: return PDFObjectType_Bool;
858 12459 : case objInt: return PDFObjectType_Int;
859 3548 : case objReal: return PDFObjectType_Real;
860 10188 : case objString: return PDFObjectType_String;
861 2193 : case objName: return PDFObjectType_Name;
862 10096 : case objArray: return PDFObjectType_Array;
863 10555 : case objDict: return PDFObjectType_Dictionary;
864 1377 : case objStream: return PDFObjectType_Dictionary;
865 0 : default: return PDFObjectType_Unknown;
866 : }
867 : }
868 :
869 : /************************************************************************/
870 : /* GetTypeNameNative() */
871 : /************************************************************************/
872 :
873 0 : const char* GDALPDFObjectPoppler::GetTypeNameNative()
874 : {
875 0 : return m_po->getTypeName();
876 : }
877 :
878 : /************************************************************************/
879 : /* GetBool() */
880 : /************************************************************************/
881 :
882 0 : int GDALPDFObjectPoppler::GetBool()
883 : {
884 0 : if (GetType() == PDFObjectType_Bool)
885 0 : return m_po->getBool();
886 : else
887 0 : return 0;
888 : }
889 :
890 : /************************************************************************/
891 : /* GetInt() */
892 : /************************************************************************/
893 :
894 4297 : int GDALPDFObjectPoppler::GetInt()
895 : {
896 4297 : if (GetType() == PDFObjectType_Int)
897 4297 : return m_po->getInt();
898 : else
899 0 : return 0;
900 : }
901 :
902 : /************************************************************************/
903 : /* GetReal() */
904 : /************************************************************************/
905 :
906 878 : double GDALPDFObjectPoppler::GetReal()
907 : {
908 878 : if (GetType() == PDFObjectType_Real)
909 878 : return m_po->getReal();
910 : else
911 0 : return 0.0;
912 : }
913 :
914 : /************************************************************************/
915 : /* GDALPDFPopplerGetUTF8() */
916 : /************************************************************************/
917 :
918 3723 : static CPLString GDALPDFPopplerGetUTF8(GooString* poStr)
919 : {
920 3723 : GByte* pabySrc = (GByte*)poStr->getCString();
921 3723 : int nLen = poStr->getLength();
922 3723 : int bBEUnicodeMarker = nLen > 2 && pabySrc[0] == 0xFF && pabySrc[1] == 0xFE;
923 3723 : if (!poStr->hasUnicodeMarker() && !bBEUnicodeMarker)
924 : {
925 3678 : const char* pszStr = poStr->getCString();
926 3678 : if (CPLIsUTF8(pszStr, -1))
927 3678 : return pszStr;
928 : else
929 : {
930 0 : char* pszUTF8 = CPLRecode( pszStr, CPL_ENC_ISO8859_1, CPL_ENC_UTF8 );
931 0 : CPLString osRet = pszUTF8;
932 0 : CPLFree(pszUTF8);
933 0 : return osRet;
934 : }
935 : }
936 :
937 : /* This is UTF-16 content */
938 45 : pabySrc += 2;
939 45 : nLen = (nLen - 2) / 2;
940 45 : wchar_t *pwszSource = new wchar_t[nLen + 1];
941 45 : int j = 0;
942 814 : for(int i=0; i<nLen; i++, j++)
943 : {
944 769 : if (!bBEUnicodeMarker)
945 321 : pwszSource[j] = (pabySrc[2 * i] << 8) + pabySrc[2 * i + 1];
946 : else
947 448 : pwszSource[j] = (pabySrc[2 * i + 1] << 8) + pabySrc[2 * i];
948 : #ifndef _WIN32
949 : /* Is there a surrogate pair ? See http://en.wikipedia.org/wiki/UTF-16 */
950 : /* On Windows, CPLRecodeFromWChar does this for us, because wchar_t is only */
951 : /* 2 bytes wide, whereas on Unix it is 32bits */
952 769 : if (pwszSource[j] >= 0xD800 && pwszSource[j] <= 0xDBFF && i + 1 < nLen)
953 : {
954 : /* should be in the range 0xDC00... 0xDFFF */
955 : wchar_t nTrailSurrogate;
956 0 : if (!bBEUnicodeMarker)
957 0 : nTrailSurrogate = (pabySrc[2 * (i+1)] << 8) + pabySrc[2 * (i+1) + 1];
958 : else
959 0 : nTrailSurrogate = (pabySrc[2 * (i+1) + 1] << 8) + pabySrc[2 * (i+1)];
960 0 : if (nTrailSurrogate >= 0xDC00 && nTrailSurrogate <= 0xDFFF)
961 : {
962 0 : pwszSource[j] = ((pwszSource[j] - 0xD800) << 10) + (nTrailSurrogate - 0xDC00) + 0x10000;
963 0 : i++;
964 : }
965 : }
966 : #endif
967 : }
968 45 : pwszSource[j] = 0;
969 :
970 45 : char* pszUTF8 = CPLRecodeFromWChar( pwszSource, CPL_ENC_UCS2, CPL_ENC_UTF8 );
971 45 : delete[] pwszSource;
972 45 : CPLString osStrUTF8(pszUTF8);
973 45 : CPLFree(pszUTF8);
974 45 : return osStrUTF8;
975 : }
976 :
977 : /************************************************************************/
978 : /* GetString() */
979 : /************************************************************************/
980 :
981 3723 : const CPLString& GDALPDFObjectPoppler::GetString()
982 : {
983 3723 : if (GetType() == PDFObjectType_String)
984 3723 : return (osStr = GDALPDFPopplerGetUTF8(m_po->getString()));
985 : else
986 0 : return (osStr = "");
987 : }
988 :
989 : /************************************************************************/
990 : /* GetName() */
991 : /************************************************************************/
992 :
993 1263 : const CPLString& GDALPDFObjectPoppler::GetName()
994 : {
995 1263 : if (GetType() == PDFObjectType_Name)
996 1263 : return (osStr = m_po->getName());
997 : else
998 0 : return (osStr = "");
999 : }
1000 :
1001 : /************************************************************************/
1002 : /* GetDictionary() */
1003 : /************************************************************************/
1004 :
1005 7233 : GDALPDFDictionary* GDALPDFObjectPoppler::GetDictionary()
1006 : {
1007 7233 : if (GetType() != PDFObjectType_Dictionary)
1008 0 : return NULL;
1009 :
1010 7233 : if (m_poDict)
1011 4180 : return m_poDict;
1012 :
1013 3053 : Dict* poDict = (m_po->getType() == objStream) ? m_po->getStream()->getDict() : m_po->getDict();
1014 3053 : if (poDict == NULL)
1015 0 : return NULL;
1016 3053 : m_poDict = new GDALPDFDictionaryPoppler(poDict);
1017 3053 : return m_poDict;
1018 : }
1019 :
1020 : /************************************************************************/
1021 : /* GetArray() */
1022 : /************************************************************************/
1023 :
1024 5049 : GDALPDFArray* GDALPDFObjectPoppler::GetArray()
1025 : {
1026 5049 : if (GetType() != PDFObjectType_Array)
1027 0 : return NULL;
1028 :
1029 5049 : if (m_poArray)
1030 4001 : return m_poArray;
1031 :
1032 1048 : Array* poArray = m_po->getArray();
1033 1048 : if (poArray == NULL)
1034 0 : return NULL;
1035 1048 : m_poArray = new GDALPDFArrayPoppler(poArray);
1036 1048 : return m_poArray;
1037 : }
1038 :
1039 : /************************************************************************/
1040 : /* GetStream() */
1041 : /************************************************************************/
1042 :
1043 349 : GDALPDFStream* GDALPDFObjectPoppler::GetStream()
1044 : {
1045 349 : if (m_po->getType() != objStream)
1046 0 : return NULL;
1047 :
1048 349 : if (m_poStream)
1049 64 : return m_poStream;
1050 285 : m_poStream = new GDALPDFStreamPoppler(m_po->getStream());
1051 285 : return m_poStream;
1052 : }
1053 :
1054 : /************************************************************************/
1055 : /* SetRefNumAndGen() */
1056 : /************************************************************************/
1057 :
1058 12428 : void GDALPDFObjectPoppler::SetRefNumAndGen(int nNum, int nGen)
1059 : {
1060 12428 : m_nRefNum = nNum;
1061 12428 : m_nRefGen = nGen;
1062 12428 : }
1063 :
1064 : /************************************************************************/
1065 : /* GetRefNum() */
1066 : /************************************************************************/
1067 :
1068 408 : int GDALPDFObjectPoppler::GetRefNum()
1069 : {
1070 408 : return m_nRefNum;
1071 : }
1072 :
1073 : /************************************************************************/
1074 : /* GetRefGen() */
1075 : /************************************************************************/
1076 :
1077 293 : int GDALPDFObjectPoppler::GetRefGen()
1078 : {
1079 293 : return m_nRefGen;
1080 : }
1081 :
1082 : /************************************************************************/
1083 : /* ==================================================================== */
1084 : /* GDALPDFDictionaryPoppler */
1085 : /* ==================================================================== */
1086 : /************************************************************************/
1087 :
1088 : /************************************************************************/
1089 : /* ~GDALPDFDictionaryPoppler() */
1090 : /************************************************************************/
1091 :
1092 3053 : GDALPDFDictionaryPoppler::~GDALPDFDictionaryPoppler()
1093 : {
1094 3053 : std::map<CPLString, GDALPDFObject*>::iterator oIter = m_map.begin();
1095 3053 : std::map<CPLString, GDALPDFObject*>::iterator oEnd = m_map.end();
1096 10312 : for(; oIter != oEnd; ++oIter)
1097 7259 : delete oIter->second;
1098 3053 : }
1099 :
1100 : /************************************************************************/
1101 : /* Get() */
1102 : /************************************************************************/
1103 :
1104 10998 : GDALPDFObject* GDALPDFDictionaryPoppler::Get(const char* pszKey)
1105 : {
1106 10998 : std::map<CPLString, GDALPDFObject*>::iterator oIter = m_map.find(pszKey);
1107 10998 : if (oIter != m_map.end())
1108 2744 : return oIter->second;
1109 :
1110 8254 : Object* po = new Object;
1111 16508 : if (m_poDict->lookupNF((char*)pszKey, po) && !po->isNull())
1112 : {
1113 7259 : int nRefNum = 0, nRefGen = 0;
1114 7259 : if( po->isRef())
1115 : {
1116 912 : nRefNum = po->getRefNum();
1117 912 : nRefGen = po->getRefGen();
1118 : }
1119 7259 : if( !po->isRef() || (m_poDict->lookup((char*)pszKey, po) && !po->isNull()) )
1120 : {
1121 7259 : GDALPDFObjectPoppler* poObj = new GDALPDFObjectPoppler(po, TRUE);
1122 7259 : poObj->SetRefNumAndGen(nRefNum, nRefGen);
1123 14518 : m_map[pszKey] = poObj;
1124 7259 : return poObj;
1125 : }
1126 : else
1127 : {
1128 0 : delete po;
1129 0 : return NULL;
1130 : }
1131 : }
1132 : else
1133 : {
1134 995 : delete po;
1135 995 : return NULL;
1136 : }
1137 : }
1138 :
1139 : /************************************************************************/
1140 : /* GetValues() */
1141 : /************************************************************************/
1142 :
1143 41 : std::map<CPLString, GDALPDFObject*>& GDALPDFDictionaryPoppler::GetValues()
1144 : {
1145 41 : int i = 0;
1146 41 : int nLength = m_poDict->getLength();
1147 234 : for(i=0;i<nLength;i++)
1148 : {
1149 193 : const char* pszKey = (const char*)m_poDict->getKey(i);
1150 193 : Get(pszKey);
1151 : }
1152 41 : return m_map;
1153 : }
1154 :
1155 : /************************************************************************/
1156 : /* ==================================================================== */
1157 : /* GDALPDFArrayPoppler */
1158 : /* ==================================================================== */
1159 : /************************************************************************/
1160 :
1161 : /************************************************************************/
1162 : /* GDALPDFCreateArray() */
1163 : /************************************************************************/
1164 :
1165 20 : GDALPDFArray* GDALPDFCreateArray(Array* array)
1166 : {
1167 20 : return new GDALPDFArrayPoppler(array);
1168 : }
1169 :
1170 : /************************************************************************/
1171 : /* ~GDALPDFArrayPoppler() */
1172 : /************************************************************************/
1173 :
1174 1068 : GDALPDFArrayPoppler::~GDALPDFArrayPoppler()
1175 : {
1176 6101 : for(int i=0;i<(int)m_v.size();i++)
1177 : {
1178 5033 : delete m_v[i];
1179 : }
1180 1068 : }
1181 :
1182 : /************************************************************************/
1183 : /* GetLength() */
1184 : /************************************************************************/
1185 :
1186 10942 : int GDALPDFArrayPoppler::GetLength()
1187 : {
1188 10942 : return m_poArray->getLength();
1189 : }
1190 :
1191 : /************************************************************************/
1192 : /* Get() */
1193 : /************************************************************************/
1194 :
1195 6854 : GDALPDFObject* GDALPDFArrayPoppler::Get(int nIndex)
1196 : {
1197 6854 : if (nIndex < 0 || nIndex >= GetLength())
1198 0 : return NULL;
1199 :
1200 6854 : int nOldSize = (int)m_v.size();
1201 6854 : if (nIndex >= nOldSize)
1202 : {
1203 5023 : m_v.resize(nIndex+1);
1204 10056 : for(int i=nOldSize;i<=nIndex;i++)
1205 : {
1206 5033 : m_v[i] = NULL;
1207 : }
1208 : }
1209 :
1210 6854 : if (m_v[nIndex] != NULL)
1211 1831 : return m_v[nIndex];
1212 :
1213 5023 : Object* po = new Object;
1214 5023 : if (m_poArray->getNF(nIndex, po))
1215 : {
1216 5023 : int nRefNum = 0, nRefGen = 0;
1217 5023 : if( po->isRef())
1218 : {
1219 589 : nRefNum = po->getRefNum();
1220 589 : nRefGen = po->getRefGen();
1221 : }
1222 5023 : if( !po->isRef() || (m_poArray->get(nIndex, po)) )
1223 : {
1224 5023 : GDALPDFObjectPoppler* poObj = new GDALPDFObjectPoppler(po, TRUE);
1225 5023 : poObj->SetRefNumAndGen(nRefNum, nRefGen);
1226 5023 : m_v[nIndex] = poObj;
1227 5023 : return poObj;
1228 : }
1229 : else
1230 : {
1231 0 : delete po;
1232 0 : return NULL;
1233 : }
1234 : }
1235 : else
1236 : {
1237 0 : delete po;
1238 0 : return NULL;
1239 : }
1240 : }
1241 :
1242 : /************************************************************************/
1243 : /* ==================================================================== */
1244 : /* GDALPDFStreamPoppler */
1245 : /* ==================================================================== */
1246 : /************************************************************************/
1247 :
1248 : /************************************************************************/
1249 : /* GetLength() */
1250 : /************************************************************************/
1251 :
1252 437 : int GDALPDFStreamPoppler::GetLength()
1253 : {
1254 437 : if (m_nLength >= 0)
1255 298 : return m_nLength;
1256 :
1257 139 : m_poStream->reset();
1258 139 : m_nLength = 0;
1259 20795 : while(m_poStream->getChar() != EOF)
1260 20517 : m_nLength ++;
1261 139 : return m_nLength;
1262 : }
1263 :
1264 : /************************************************************************/
1265 : /* GetBytes() */
1266 : /************************************************************************/
1267 :
1268 349 : char* GDALPDFStreamPoppler::GetBytes()
1269 : {
1270 : /* fillGooString() available in poppler >= 0.16.0 */
1271 : #ifdef POPPLER_BASE_STREAM_HAS_TWO_ARGS
1272 349 : GooString* gstr = new GooString();
1273 349 : m_poStream->fillGooString(gstr);
1274 :
1275 349 : if( gstr->getLength() )
1276 : {
1277 349 : m_nLength = gstr->getLength();
1278 349 : char* pszContent = (char*) VSIMalloc(m_nLength + 1);
1279 349 : if (!pszContent)
1280 0 : return NULL;
1281 349 : memcpy(pszContent, gstr->getCString(), m_nLength);
1282 349 : pszContent[m_nLength] = '\0';
1283 349 : delete gstr;
1284 349 : return pszContent;
1285 : }
1286 : else
1287 : {
1288 0 : delete gstr;
1289 0 : return NULL;
1290 : }
1291 : #else
1292 : int i;
1293 : int nLengthAlloc = 0;
1294 : char* pszContent = NULL;
1295 : if( m_nLength >= 0 )
1296 : {
1297 : pszContent = (char*) VSIMalloc(m_nLength + 1);
1298 : if (!pszContent)
1299 : return NULL;
1300 : nLengthAlloc = m_nLength;
1301 : }
1302 : m_poStream->reset();
1303 : for(i = 0; ; ++i )
1304 : {
1305 : int nVal = m_poStream->getChar();
1306 : if (nVal == EOF)
1307 : break;
1308 : if( i >= nLengthAlloc )
1309 : {
1310 : nLengthAlloc = 32 + nLengthAlloc + nLengthAlloc / 3;
1311 : char* pszContentNew = (char*) VSIRealloc(pszContent, nLengthAlloc + 1);
1312 : if( pszContentNew == NULL )
1313 : {
1314 : CPLFree(pszContent);
1315 : m_nLength = 0;
1316 : return NULL;
1317 : }
1318 : pszContent = pszContentNew;
1319 : }
1320 : pszContent[i] = (GByte)nVal;
1321 : }
1322 : m_nLength = i;
1323 : pszContent[i] = '\0';
1324 : return pszContent;
1325 : #endif
1326 : }
1327 :
1328 : #endif // HAVE_POPPLER
1329 :
1330 : #ifdef HAVE_PODOFO
1331 :
1332 : /************************************************************************/
1333 : /* ==================================================================== */
1334 : /* GDALPDFDictionaryPodofo */
1335 : /* ==================================================================== */
1336 : /************************************************************************/
1337 :
1338 : class GDALPDFDictionaryPodofo: public GDALPDFDictionary
1339 : {
1340 : private:
1341 : PoDoFo::PdfDictionary* m_poDict;
1342 : PoDoFo::PdfVecObjects& m_poObjects;
1343 : std::map<CPLString, GDALPDFObject*> m_map;
1344 :
1345 : public:
1346 845 : GDALPDFDictionaryPodofo(PoDoFo::PdfDictionary* poDict, PoDoFo::PdfVecObjects& poObjects) : m_poDict(poDict), m_poObjects(poObjects) {}
1347 : virtual ~GDALPDFDictionaryPodofo();
1348 :
1349 : virtual GDALPDFObject* Get(const char* pszKey);
1350 : virtual std::map<CPLString, GDALPDFObject*>& GetValues();
1351 : };
1352 :
1353 : /************************************************************************/
1354 : /* ==================================================================== */
1355 : /* GDALPDFArrayPodofo */
1356 : /* ==================================================================== */
1357 : /************************************************************************/
1358 :
1359 : class GDALPDFArrayPodofo : public GDALPDFArray
1360 : {
1361 : private:
1362 : PoDoFo::PdfArray* m_poArray;
1363 : PoDoFo::PdfVecObjects& m_poObjects;
1364 : std::vector<GDALPDFObject*> m_v;
1365 :
1366 : public:
1367 146 : GDALPDFArrayPodofo(PoDoFo::PdfArray* poArray, PoDoFo::PdfVecObjects& poObjects) : m_poArray(poArray), m_poObjects(poObjects) {}
1368 : virtual ~GDALPDFArrayPodofo();
1369 :
1370 : virtual int GetLength();
1371 : virtual GDALPDFObject* Get(int nIndex);
1372 : };
1373 :
1374 : /************************************************************************/
1375 : /* ==================================================================== */
1376 : /* GDALPDFStreamPodofo */
1377 : /* ==================================================================== */
1378 : /************************************************************************/
1379 :
1380 : class GDALPDFStreamPodofo : public GDALPDFStream
1381 : {
1382 : private:
1383 : int m_nLength;
1384 : PoDoFo::PdfMemStream* m_pStream;
1385 :
1386 : public:
1387 113 : GDALPDFStreamPodofo(PoDoFo::PdfMemStream* pStream) : m_nLength(-1), m_pStream(pStream) { }
1388 113 : virtual ~GDALPDFStreamPodofo() {}
1389 :
1390 : virtual int GetLength();
1391 : virtual char* GetBytes();
1392 : };
1393 :
1394 : /************************************************************************/
1395 : /* ==================================================================== */
1396 : /* GDALPDFObjectPodofo */
1397 : /* ==================================================================== */
1398 : /************************************************************************/
1399 :
1400 : /************************************************************************/
1401 : /* GDALPDFObjectPodofo() */
1402 : /************************************************************************/
1403 :
1404 3598 : GDALPDFObjectPodofo::GDALPDFObjectPodofo(PoDoFo::PdfObject* po, PoDoFo::PdfVecObjects& poObjects) :
1405 3598 : m_po(po), m_poObjects(poObjects), m_poDict(NULL), m_poArray(NULL), m_poStream(NULL)
1406 : {
1407 : try
1408 : {
1409 3598 : if (m_po->GetDataType() == PoDoFo::ePdfDataType_Reference)
1410 : {
1411 338 : PoDoFo::PdfObject* poObj = m_poObjects.GetObject(m_po->GetReference());
1412 338 : if (poObj)
1413 338 : m_po = poObj;
1414 : }
1415 : }
1416 0 : catch(PoDoFo::PdfError& oError)
1417 : {
1418 0 : CPLError(CE_Failure, CPLE_AppDefined, "Invalid PDF : %s", oError.what());
1419 : }
1420 3598 : }
1421 :
1422 : /************************************************************************/
1423 : /* ~GDALPDFObjectPodofo() */
1424 : /************************************************************************/
1425 :
1426 3598 : GDALPDFObjectPodofo::~GDALPDFObjectPodofo()
1427 : {
1428 3598 : delete m_poDict;
1429 3598 : delete m_poArray;
1430 3598 : delete m_poStream;
1431 3598 : }
1432 :
1433 : /************************************************************************/
1434 : /* GetType() */
1435 : /************************************************************************/
1436 :
1437 9533 : GDALPDFObjectType GDALPDFObjectPodofo::GetType()
1438 : {
1439 : try
1440 : {
1441 9533 : switch(m_po->GetDataType())
1442 : {
1443 0 : case PoDoFo::ePdfDataType_Null: return PDFObjectType_Null;
1444 0 : case PoDoFo::ePdfDataType_Bool: return PDFObjectType_Bool;
1445 2560 : case PoDoFo::ePdfDataType_Number: return PDFObjectType_Int;
1446 672 : case PoDoFo::ePdfDataType_Real: return PDFObjectType_Real;
1447 0 : case PoDoFo::ePdfDataType_HexString: return PDFObjectType_String;
1448 181 : case PoDoFo::ePdfDataType_String: return PDFObjectType_String;
1449 1738 : case PoDoFo::ePdfDataType_Name: return PDFObjectType_Name;
1450 2195 : case PoDoFo::ePdfDataType_Array: return PDFObjectType_Array;
1451 2187 : case PoDoFo::ePdfDataType_Dictionary: return PDFObjectType_Dictionary;
1452 0 : default: return PDFObjectType_Unknown;
1453 : }
1454 : }
1455 0 : catch(PoDoFo::PdfError& oError)
1456 : {
1457 0 : CPLError(CE_Failure, CPLE_AppDefined, "Invalid PDF : %s", oError.what());
1458 0 : return PDFObjectType_Unknown;
1459 : }
1460 : }
1461 :
1462 : /************************************************************************/
1463 : /* GetTypeNameNative() */
1464 : /************************************************************************/
1465 :
1466 0 : const char* GDALPDFObjectPodofo::GetTypeNameNative()
1467 : {
1468 : try
1469 : {
1470 0 : return m_po->GetDataTypeString();
1471 : }
1472 0 : catch(PoDoFo::PdfError& oError)
1473 : {
1474 0 : CPLError(CE_Failure, CPLE_AppDefined, "Invalid PDF : %s", oError.what());
1475 0 : return "unknown";
1476 : }
1477 : }
1478 :
1479 : /************************************************************************/
1480 : /* GetBool() */
1481 : /************************************************************************/
1482 :
1483 0 : int GDALPDFObjectPodofo::GetBool()
1484 : {
1485 0 : if (m_po->GetDataType() == PoDoFo::ePdfDataType_Bool)
1486 0 : return m_po->GetBool();
1487 : else
1488 0 : return 0;
1489 : }
1490 :
1491 : /************************************************************************/
1492 : /* GetInt() */
1493 : /************************************************************************/
1494 :
1495 1199 : int GDALPDFObjectPodofo::GetInt()
1496 : {
1497 1199 : if (m_po->GetDataType() == PoDoFo::ePdfDataType_Number)
1498 1199 : return (int)m_po->GetNumber();
1499 : else
1500 0 : return 0;
1501 : }
1502 :
1503 : /************************************************************************/
1504 : /* GetReal() */
1505 : /************************************************************************/
1506 :
1507 168 : double GDALPDFObjectPodofo::GetReal()
1508 : {
1509 168 : if (GetType() == PDFObjectType_Real)
1510 168 : return m_po->GetReal();
1511 : else
1512 0 : return 0.0;
1513 : }
1514 :
1515 : /************************************************************************/
1516 : /* GetString() */
1517 : /************************************************************************/
1518 :
1519 77 : const CPLString& GDALPDFObjectPodofo::GetString()
1520 : {
1521 77 : if (GetType() == PDFObjectType_String)
1522 77 : return (osStr = m_po->GetString().GetStringUtf8());
1523 : else
1524 0 : return (osStr = "");
1525 : }
1526 :
1527 : /************************************************************************/
1528 : /* GetName() */
1529 : /************************************************************************/
1530 :
1531 899 : const CPLString& GDALPDFObjectPodofo::GetName()
1532 : {
1533 899 : if (GetType() == PDFObjectType_Name)
1534 899 : return (osStr = m_po->GetName().GetName());
1535 : else
1536 0 : return (osStr = "");
1537 : }
1538 :
1539 : /************************************************************************/
1540 : /* GetDictionary() */
1541 : /************************************************************************/
1542 :
1543 1145 : GDALPDFDictionary* GDALPDFObjectPodofo::GetDictionary()
1544 : {
1545 1145 : if (GetType() != PDFObjectType_Dictionary)
1546 0 : return NULL;
1547 :
1548 1145 : if (m_poDict)
1549 300 : return m_poDict;
1550 :
1551 845 : m_poDict = new GDALPDFDictionaryPodofo(&m_po->GetDictionary(), m_poObjects);
1552 845 : return m_poDict;
1553 : }
1554 :
1555 : /************************************************************************/
1556 : /* GetArray() */
1557 : /************************************************************************/
1558 :
1559 1084 : GDALPDFArray* GDALPDFObjectPodofo::GetArray()
1560 : {
1561 1084 : if (GetType() != PDFObjectType_Array)
1562 0 : return NULL;
1563 :
1564 1084 : if (m_poArray)
1565 938 : return m_poArray;
1566 :
1567 146 : m_poArray = new GDALPDFArrayPodofo(&m_po->GetArray(), m_poObjects);
1568 146 : return m_poArray;
1569 : }
1570 :
1571 : /************************************************************************/
1572 : /* GetStream() */
1573 : /************************************************************************/
1574 :
1575 174 : GDALPDFStream* GDALPDFObjectPodofo::GetStream()
1576 : {
1577 174 : if (!m_po->HasStream())
1578 0 : return NULL;
1579 :
1580 174 : if (m_poStream)
1581 61 : return m_poStream;
1582 113 : PoDoFo::PdfMemStream* pStream = NULL;
1583 : try
1584 : {
1585 113 : pStream = dynamic_cast<PoDoFo::PdfMemStream*>(m_po->GetStream());
1586 113 : pStream->Uncompress();
1587 : }
1588 0 : catch( const PoDoFo::PdfError & e )
1589 : {
1590 0 : e.PrintErrorMsg();
1591 0 : pStream = NULL;
1592 : }
1593 113 : if (pStream)
1594 : {
1595 113 : m_poStream = new GDALPDFStreamPodofo(pStream);
1596 113 : return m_poStream;
1597 : }
1598 : else
1599 0 : return NULL;
1600 : }
1601 :
1602 : /************************************************************************/
1603 : /* GetRefNum() */
1604 : /************************************************************************/
1605 :
1606 164 : int GDALPDFObjectPodofo::GetRefNum()
1607 : {
1608 164 : return m_po->Reference().ObjectNumber();
1609 : }
1610 :
1611 : /************************************************************************/
1612 : /* GetRefGen() */
1613 : /************************************************************************/
1614 :
1615 86 : int GDALPDFObjectPodofo::GetRefGen()
1616 : {
1617 86 : return m_po->Reference().GenerationNumber();
1618 : }
1619 :
1620 : /************************************************************************/
1621 : /* ==================================================================== */
1622 : /* GDALPDFDictionaryPodofo */
1623 : /* ==================================================================== */
1624 : /************************************************************************/
1625 :
1626 : /************************************************************************/
1627 : /* ~GDALPDFDictionaryPodofo() */
1628 : /************************************************************************/
1629 :
1630 845 : GDALPDFDictionaryPodofo::~GDALPDFDictionaryPodofo()
1631 : {
1632 845 : std::map<CPLString, GDALPDFObject*>::iterator oIter = m_map.begin();
1633 845 : std::map<CPLString, GDALPDFObject*>::iterator oEnd = m_map.end();
1634 2820 : for(; oIter != oEnd; ++oIter)
1635 1975 : delete oIter->second;
1636 845 : }
1637 :
1638 : /************************************************************************/
1639 : /* Get() */
1640 : /************************************************************************/
1641 :
1642 3100 : GDALPDFObject* GDALPDFDictionaryPodofo::Get(const char* pszKey)
1643 : {
1644 3100 : std::map<CPLString, GDALPDFObject*>::iterator oIter = m_map.find(pszKey);
1645 3100 : if (oIter != m_map.end())
1646 305 : return oIter->second;
1647 :
1648 2795 : PoDoFo::PdfObject* poVal = m_poDict->GetKey(PoDoFo::PdfName(pszKey));
1649 2795 : if (poVal)
1650 : {
1651 1975 : GDALPDFObjectPodofo* poObj = new GDALPDFObjectPodofo(poVal, m_poObjects);
1652 3950 : m_map[pszKey] = poObj;
1653 1975 : return poObj;
1654 : }
1655 : else
1656 : {
1657 820 : return NULL;
1658 : }
1659 : }
1660 :
1661 : /************************************************************************/
1662 : /* GetValues() */
1663 : /************************************************************************/
1664 :
1665 18 : std::map<CPLString, GDALPDFObject*>& GDALPDFDictionaryPodofo::GetValues()
1666 : {
1667 18 : PoDoFo::TKeyMap::iterator oIter = m_poDict->GetKeys().begin();
1668 18 : PoDoFo::TKeyMap::iterator oEnd = m_poDict->GetKeys().end();
1669 163 : for( ; oIter != oEnd; ++oIter)
1670 : {
1671 145 : const char* pszKey = oIter->first.GetName().c_str();
1672 145 : Get(pszKey);
1673 : }
1674 :
1675 18 : return m_map;
1676 : }
1677 :
1678 : /************************************************************************/
1679 : /* ==================================================================== */
1680 : /* GDALPDFArrayPodofo */
1681 : /* ==================================================================== */
1682 : /************************************************************************/
1683 :
1684 146 : GDALPDFArrayPodofo::~GDALPDFArrayPodofo()
1685 : {
1686 982 : for(int i=0;i<(int)m_v.size();i++)
1687 : {
1688 836 : delete m_v[i];
1689 : }
1690 146 : }
1691 :
1692 : /************************************************************************/
1693 : /* GetLength() */
1694 : /************************************************************************/
1695 :
1696 1180 : int GDALPDFArrayPodofo::GetLength()
1697 : {
1698 1180 : return (int)m_poArray->GetSize();
1699 : }
1700 :
1701 : /************************************************************************/
1702 : /* Get() */
1703 : /************************************************************************/
1704 :
1705 1000 : GDALPDFObject* GDALPDFArrayPodofo::Get(int nIndex)
1706 : {
1707 1000 : if (nIndex < 0 || nIndex >= GetLength())
1708 0 : return NULL;
1709 :
1710 1000 : int nOldSize = (int)m_v.size();
1711 1000 : if (nIndex >= nOldSize)
1712 : {
1713 834 : m_v.resize(nIndex+1);
1714 1670 : for(int i=nOldSize;i<=nIndex;i++)
1715 : {
1716 836 : m_v[i] = NULL;
1717 : }
1718 : }
1719 :
1720 1000 : if (m_v[nIndex] != NULL)
1721 166 : return m_v[nIndex];
1722 :
1723 834 : PoDoFo::PdfObject& oVal = (*m_poArray)[nIndex];
1724 834 : GDALPDFObjectPodofo* poObj = new GDALPDFObjectPodofo(&oVal, m_poObjects);
1725 834 : m_v[nIndex] = poObj;
1726 834 : return poObj;
1727 : }
1728 :
1729 : /************************************************************************/
1730 : /* ==================================================================== */
1731 : /* GDALPDFStreamPodofo */
1732 : /* ==================================================================== */
1733 : /************************************************************************/
1734 :
1735 : /************************************************************************/
1736 : /* GetLength() */
1737 : /************************************************************************/
1738 :
1739 421 : int GDALPDFStreamPodofo::GetLength()
1740 : {
1741 421 : return (int)m_pStream->GetLength();
1742 : }
1743 :
1744 : /************************************************************************/
1745 : /* GetBytes() */
1746 : /************************************************************************/
1747 :
1748 174 : char* GDALPDFStreamPodofo::GetBytes()
1749 : {
1750 174 : int nLength = GetLength();
1751 174 : char* pszContent = (char*) VSIMalloc(nLength + 1);
1752 174 : if (!pszContent)
1753 0 : return NULL;
1754 174 : memcpy(pszContent, m_pStream->Get(), nLength);
1755 174 : pszContent[nLength] = '\0';
1756 174 : return pszContent;
1757 2139 : }
1758 :
1759 : #endif // HAVE_PODOFO
|