Coverage Report

Created: 2026-02-14 09:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gdal/frmts/pdf/pdfobject.h
Line
Count
Source
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-2014, Even Rouault <even dot rouault at spatialys.com>
16
 *
17
 * SPDX-License-Identifier: MIT
18
 ****************************************************************************/
19
20
#ifndef PDFOBJECT_H_INCLUDED
21
#define PDFOBJECT_H_INCLUDED
22
23
#include "pdfsdk_headers_all.h"
24
25
#include "cpl_string.h"
26
#include <map>
27
#include <vector>
28
29
651k
#define DEFAULT_DPI (72.0)
30
636k
#define USER_UNIT_IN_INCH (1.0 / DEFAULT_DPI)
31
32
double ROUND_IF_CLOSE(double x, double eps = 0);
33
34
typedef enum
35
{
36
    PDFObjectType_Unknown,
37
    PDFObjectType_Null,
38
    PDFObjectType_Bool,
39
    PDFObjectType_Int,
40
    PDFObjectType_Real,
41
    PDFObjectType_String,
42
    PDFObjectType_Name,
43
    PDFObjectType_Array,
44
    PDFObjectType_Dictionary
45
} GDALPDFObjectType;
46
47
class GDALPDFDictionary;
48
class GDALPDFArray;
49
class GDALPDFStream;
50
51
class GDALPDFObjectRW;
52
class GDALPDFDictionaryRW;
53
class GDALPDFArrayRW;
54
55
class GDALPDFObjectNum
56
{
57
    int m_nId;
58
59
  public:
60
8.06M
    explicit GDALPDFObjectNum(int nId = 0) : m_nId(nId)
61
8.06M
    {
62
8.06M
    }
63
64
    GDALPDFObjectNum(const GDALPDFObjectNum &other) = default;
65
    GDALPDFObjectNum &operator=(const GDALPDFObjectNum &) = default;
66
67
    GDALPDFObjectNum &operator=(int nId)
68
1.04M
    {
69
1.04M
        m_nId = nId;
70
1.04M
        return *this;
71
1.04M
    }
72
73
    int toInt() const
74
1.65M
    {
75
1.65M
        return m_nId;
76
1.65M
    }
77
78
    bool toBool() const
79
1.15M
    {
80
1.15M
        return m_nId > 0;
81
1.15M
    }
82
83
    bool operator==(const GDALPDFObjectNum &other) const
84
6.29k
    {
85
6.29k
        return m_nId == other.m_nId;
86
6.29k
    }
87
88
    bool operator<(const GDALPDFObjectNum &other) const
89
0
    {
90
0
        return m_nId < other.m_nId;
91
0
    }
92
};
93
94
class GDALPDFObject /* non final */
95
{
96
  protected:
97
    virtual const char *GetTypeNameNative() = 0;
98
99
  public:
100
    virtual ~GDALPDFObject();
101
102
    virtual GDALPDFObjectType GetType() = 0;
103
    virtual const char *GetTypeName();
104
    virtual int GetBool() = 0;
105
    virtual int GetInt() = 0;
106
    virtual double GetReal() = 0;
107
108
    virtual int CanRepresentRealAsString()
109
0
    {
110
0
        return FALSE;
111
0
    }
112
113
    virtual const std::string &GetString() = 0;
114
    virtual const std::string &GetName() = 0;
115
    virtual GDALPDFDictionary *GetDictionary() = 0;
116
    virtual GDALPDFArray *GetArray() = 0;
117
    virtual GDALPDFStream *GetStream() = 0;
118
    virtual GDALPDFObjectNum GetRefNum() = 0;
119
    virtual int GetRefGen() = 0;
120
121
    virtual int GetPrecision() const
122
0
    {
123
0
        return 16;
124
0
    }
125
126
    GDALPDFObject *LookupObject(const char *pszPath);
127
128
    void Serialize(CPLString &osStr, bool bEmitRef = true);
129
130
    CPLString Serialize()
131
212
    {
132
212
        CPLString osStr;
133
212
        Serialize(osStr);
134
212
        return osStr;
135
212
    }
136
137
    GDALPDFObjectRW *Clone();
138
};
139
140
class GDALPDFDictionary /* non final */
141
{
142
  public:
143
    virtual ~GDALPDFDictionary();
144
145
    virtual GDALPDFObject *Get(const char *pszKey) = 0;
146
    virtual std::map<CPLString, GDALPDFObject *> &GetValues() = 0;
147
148
    GDALPDFObject *LookupObject(const char *pszPath);
149
150
    void Serialize(CPLString &osStr);
151
152
    CPLString Serialize()
153
67.4k
    {
154
67.4k
        CPLString osStr;
155
67.4k
        Serialize(osStr);
156
67.4k
        return osStr;
157
67.4k
    }
158
159
    GDALPDFDictionaryRW *Clone();
160
};
161
162
class GDALPDFArray /* non final */
163
{
164
  public:
165
    virtual ~GDALPDFArray();
166
167
    virtual int GetLength() = 0;
168
    virtual GDALPDFObject *Get(int nIndex) = 0;
169
170
    void Serialize(CPLString &osStr);
171
172
    CPLString Serialize()
173
664
    {
174
664
        CPLString osStr;
175
664
        Serialize(osStr);
176
664
        return osStr;
177
664
    }
178
179
    GDALPDFArrayRW *Clone();
180
};
181
182
class GDALPDFStream /* non final */
183
{
184
  public:
185
    virtual ~GDALPDFStream();
186
187
    /** Return the uncompressed stream length, or 0 if empty or error.
188
     * If nMaxSize > 0, GetLength() will possibly stop the decompression once
189
     * the threshold is reached, and return INT64_MAX */
190
    virtual int64_t GetLength(int64_t nMaxSize = 0) = 0;
191
    virtual char *GetBytes() = 0;
192
193
    virtual int64_t GetRawLength() = 0;
194
    virtual char *GetRawBytes() = 0;
195
};
196
197
class GDALPDFObjectRW final : public GDALPDFObject
198
{
199
  private:
200
    const GDALPDFObjectType m_eType;
201
    int m_nVal = 0;
202
    double m_dfVal = 0;
203
    CPLString m_osVal{};
204
    GDALPDFDictionaryRW *m_poDict = nullptr;
205
    GDALPDFArrayRW *m_poArray = nullptr;
206
    GDALPDFObjectNum m_nNum{};
207
    int m_nGen = 0;
208
    int m_bCanRepresentRealAsString = FALSE;
209
    int m_nPrecision = 16;
210
211
    explicit GDALPDFObjectRW(GDALPDFObjectType eType);
212
213
    CPL_DISALLOW_COPY_ASSIGN(GDALPDFObjectRW)
214
215
  protected:
216
    const char *GetTypeNameNative() override;
217
218
  public:
219
    static GDALPDFObjectRW *CreateIndirect(const GDALPDFObjectNum &nNum,
220
                                           int nGen);
221
    static GDALPDFObjectRW *CreateNull();
222
    static GDALPDFObjectRW *CreateBool(int bVal);
223
    static GDALPDFObjectRW *CreateInt(int nVal);
224
    static GDALPDFObjectRW *CreateReal(double dfVal,
225
                                       int bCanRepresentRealAsString = FALSE);
226
    static GDALPDFObjectRW *CreateRealWithPrecision(double dfVal,
227
                                                    int nPrecision);
228
    static GDALPDFObjectRW *CreateString(const char *pszStr);
229
    static GDALPDFObjectRW *CreateName(const char *pszName);
230
    static GDALPDFObjectRW *CreateDictionary(GDALPDFDictionaryRW *poDict);
231
    static GDALPDFObjectRW *CreateArray(GDALPDFArrayRW *poArray);
232
    ~GDALPDFObjectRW() override;
233
234
    GDALPDFObjectType GetType() override;
235
    int GetBool() override;
236
    int GetInt() override;
237
    double GetReal() override;
238
239
    int CanRepresentRealAsString() override
240
25.7k
    {
241
25.7k
        return m_bCanRepresentRealAsString;
242
25.7k
    }
243
244
    const CPLString &GetString() override;
245
    const CPLString &GetName() override;
246
    GDALPDFDictionary *GetDictionary() override;
247
    GDALPDFArray *GetArray() override;
248
    GDALPDFStream *GetStream() override;
249
    GDALPDFObjectNum GetRefNum() override;
250
    int GetRefGen() override;
251
252
    int GetPrecision() const override
253
25.7k
    {
254
25.7k
        return m_nPrecision;
255
25.7k
    }
256
};
257
258
class GDALPDFDictionaryRW final : public GDALPDFDictionary
259
{
260
  private:
261
    std::map<CPLString, GDALPDFObject *> m_map{};
262
263
    CPL_DISALLOW_COPY_ASSIGN(GDALPDFDictionaryRW)
264
265
  public:
266
    GDALPDFDictionaryRW();
267
    ~GDALPDFDictionaryRW() override;
268
269
    GDALPDFObject *Get(const char *pszKey) override;
270
    std::map<CPLString, GDALPDFObject *> &GetValues() override;
271
272
    GDALPDFDictionaryRW &Add(const char *pszKey, GDALPDFObject *poVal);
273
    GDALPDFDictionaryRW &Remove(const char *pszKey);
274
275
    GDALPDFDictionaryRW &Add(const char *pszKey, GDALPDFArrayRW *poArray)
276
59.4k
    {
277
59.4k
        return Add(pszKey, GDALPDFObjectRW::CreateArray(poArray));
278
59.4k
    }
279
280
    GDALPDFDictionaryRW &Add(const char *pszKey, GDALPDFDictionaryRW *poDict)
281
107k
    {
282
107k
        return Add(pszKey, GDALPDFObjectRW::CreateDictionary(poDict));
283
107k
    }
284
285
    GDALPDFDictionaryRW &Add(const char *pszKey, const char *pszVal)
286
136k
    {
287
136k
        return Add(pszKey, GDALPDFObjectRW::CreateString(pszVal));
288
136k
    }
289
290
    GDALPDFDictionaryRW &Add(const char *pszKey, int nVal)
291
26.7k
    {
292
26.7k
        return Add(pszKey, GDALPDFObjectRW::CreateInt(nVal));
293
26.7k
    }
294
295
    GDALPDFDictionaryRW &Add(const char *pszKey, double dfVal,
296
                             int bCanRepresentRealAsString = FALSE)
297
25.0k
    {
298
25.0k
        return Add(pszKey, GDALPDFObjectRW::CreateReal(
299
25.0k
                               dfVal, bCanRepresentRealAsString));
300
25.0k
    }
301
302
    GDALPDFDictionaryRW &Add(const char *pszKey, const GDALPDFObjectNum &nNum,
303
                             int nGen)
304
117k
    {
305
117k
        return Add(pszKey, GDALPDFObjectRW::CreateIndirect(nNum, nGen));
306
117k
    }
307
};
308
309
class GDALPDFArrayRW final : public GDALPDFArray
310
{
311
  private:
312
    std::vector<GDALPDFObject *> m_array{};
313
314
    CPL_DISALLOW_COPY_ASSIGN(GDALPDFArrayRW)
315
316
  public:
317
    GDALPDFArrayRW();
318
    ~GDALPDFArrayRW() override;
319
320
    int GetLength() override;
321
    GDALPDFObject *Get(int nIndex) override;
322
323
    GDALPDFArrayRW &Add(GDALPDFObject *poObj);
324
325
    GDALPDFArrayRW &Add(GDALPDFArrayRW *poArray)
326
7
    {
327
7
        return Add(GDALPDFObjectRW::CreateArray(poArray));
328
7
    }
329
330
    GDALPDFArrayRW &Add(GDALPDFDictionaryRW *poDict)
331
48.7k
    {
332
48.7k
        return Add(GDALPDFObjectRW::CreateDictionary(poDict));
333
48.7k
    }
334
335
    GDALPDFArrayRW &Add(const char *pszVal)
336
0
    {
337
0
        return Add(GDALPDFObjectRW::CreateString(pszVal));
338
0
    }
339
340
    GDALPDFArrayRW &Add(int nVal)
341
102k
    {
342
102k
        return Add(GDALPDFObjectRW::CreateInt(nVal));
343
102k
    }
344
345
    GDALPDFArrayRW &Add(double dfVal, int bCanRepresentRealAsString = FALSE)
346
4.39k
    {
347
4.39k
        return Add(
348
4.39k
            GDALPDFObjectRW::CreateReal(dfVal, bCanRepresentRealAsString));
349
4.39k
    }
350
351
    GDALPDFArrayRW &AddWithPrecision(double dfVal, int nPrecision)
352
0
    {
353
0
        return Add(GDALPDFObjectRW::CreateRealWithPrecision(dfVal, nPrecision));
354
0
    }
355
356
    GDALPDFArrayRW &Add(double *padfVal, int nCount,
357
                        int bCanRepresentRealAsString = FALSE);
358
359
    GDALPDFArrayRW &Add(const GDALPDFObjectNum &nNum, int nGen)
360
39.1k
    {
361
39.1k
        return Add(GDALPDFObjectRW::CreateIndirect(nNum, nGen));
362
39.1k
    }
363
};
364
365
#ifdef HAVE_POPPLER
366
367
class GDALPDFObjectPoppler final : public GDALPDFObject
368
{
369
  private:
370
    Object *m_poToDestroy;
371
    const Object *m_poConst;
372
    GDALPDFDictionary *m_poDict = nullptr;
373
    GDALPDFArray *m_poArray = nullptr;
374
    GDALPDFStream *m_poStream = nullptr;
375
    std::string osStr{};
376
    GDALPDFObjectNum m_nRefNum{};
377
    int m_nRefGen = 0;
378
379
    CPL_DISALLOW_COPY_ASSIGN(GDALPDFObjectPoppler)
380
381
  protected:
382
    const char *GetTypeNameNative() override;
383
384
  public:
385
    GDALPDFObjectPoppler(Object *po, bool bDestroy)
386
3.41M
        : m_poToDestroy(bDestroy ? po : nullptr), m_poConst(po)
387
3.41M
    {
388
3.41M
    }
389
390
    GDALPDFObjectPoppler(const Object *po)
391
32.6k
        : m_poToDestroy(nullptr), m_poConst(po)
392
32.6k
    {
393
32.6k
    }
394
395
    void SetRefNumAndGen(const GDALPDFObjectNum &nNum, int nGen);
396
397
    ~GDALPDFObjectPoppler() override;
398
399
    GDALPDFObjectType GetType() override;
400
    int GetBool() override;
401
    int GetInt() override;
402
    double GetReal() override;
403
    const std::string &GetString() override;
404
    const std::string &GetName() override;
405
    GDALPDFDictionary *GetDictionary() override;
406
    GDALPDFArray *GetArray() override;
407
    GDALPDFStream *GetStream() override;
408
    GDALPDFObjectNum GetRefNum() override;
409
    int GetRefGen() override;
410
};
411
412
GDALPDFArray *GDALPDFCreateArray(const Array *array);
413
414
#endif  // HAVE_POPPLER
415
416
#ifdef HAVE_PODOFO
417
418
class GDALPDFObjectPodofo final : public GDALPDFObject
419
{
420
  private:
421
    const PoDoFo::PdfObject *m_po;
422
    const PoDoFo::PdfVecObjects &m_poObjects;
423
    GDALPDFDictionary *m_poDict = nullptr;
424
    GDALPDFArray *m_poArray = nullptr;
425
    GDALPDFStream *m_poStream = nullptr;
426
    std::string osStr{};
427
428
    CPL_DISALLOW_COPY_ASSIGN(GDALPDFObjectPodofo)
429
430
  protected:
431
    const char *GetTypeNameNative() override;
432
433
  public:
434
    GDALPDFObjectPodofo(const PoDoFo::PdfObject *po,
435
                        const PoDoFo::PdfVecObjects &poObjects);
436
437
    ~GDALPDFObjectPodofo() override;
438
439
    GDALPDFObjectType GetType() override;
440
    int GetBool() override;
441
    int GetInt() override;
442
    double GetReal() override;
443
    const std::string &GetString() override;
444
    const std::string &GetName() override;
445
    GDALPDFDictionary *GetDictionary() override;
446
    GDALPDFArray *GetArray() override;
447
    GDALPDFStream *GetStream() override;
448
    GDALPDFObjectNum GetRefNum() override;
449
    int GetRefGen() override;
450
};
451
452
#endif  // HAVE_PODOFO
453
454
#ifdef HAVE_PDFIUM
455
456
class GDALPDFObjectPdfium final : public GDALPDFObject
457
{
458
  private:
459
    RetainPtr<const CPDF_Object> m_obj;
460
    GDALPDFDictionary *m_poDict = nullptr;
461
    GDALPDFArray *m_poArray = nullptr;
462
    GDALPDFStream *m_poStream = nullptr;
463
    std::string osStr{};
464
465
    GDALPDFObjectPdfium(RetainPtr<const CPDF_Object> obj);
466
467
    CPL_DISALLOW_COPY_ASSIGN(GDALPDFObjectPdfium)
468
469
  protected:
470
    const char *GetTypeNameNative() override;
471
472
  public:
473
    static GDALPDFObjectPdfium *Build(RetainPtr<const CPDF_Object> obj);
474
475
    ~GDALPDFObjectPdfium() override;
476
477
    GDALPDFObjectType GetType() override;
478
    int GetBool() override;
479
    int GetInt() override;
480
    double GetReal() override;
481
    const std::string &GetString() override;
482
    const std::string &GetName() override;
483
    GDALPDFDictionary *GetDictionary() override;
484
    GDALPDFArray *GetArray() override;
485
    GDALPDFStream *GetStream() override;
486
    GDALPDFObjectNum GetRefNum() override;
487
    int GetRefGen() override;
488
};
489
490
#endif  // HAVE_PDFIUM
491
492
#endif  // PDFOBJECT_H_INCLUDED