Coverage Report

Created: 2026-08-11 07:29

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/poppler/poppler/GfxFont.h
Line
Count
Source
1
//========================================================================
2
//
3
// GfxFont.h
4
//
5
// Copyright 1996-2003 Glyph & Cog, LLC
6
//
7
//========================================================================
8
9
//========================================================================
10
//
11
// Modified under the Poppler project - http://poppler.freedesktop.org
12
//
13
// All changes made under the Poppler project to this file are licensed
14
// under GPL version 2 or later
15
//
16
// Copyright (C) 2005, 2008, 2015, 2017-2022, 2024-2026 Albert Astals Cid <aacid@kde.org>
17
// Copyright (C) 2006 Takashi Iwai <tiwai@suse.de>
18
// Copyright (C) 2006 Kristian Høgsberg <krh@redhat.com>
19
// Copyright (C) 2007 Julien Rebetez <julienr@svn.gnome.org>
20
// Copyright (C) 2007 Jeff Muizelaar <jeff@infidigm.net>
21
// Copyright (C) 2007 Koji Otani <sho@bbr.jp>
22
// Copyright (C) 2011 Axel Strübing <axel.struebing@freenet.de>
23
// Copyright (C) 2011, 2012, 2014 Adrian Johnson <ajohnson@redneon.com>
24
// Copyright (C) 2015, 2018 Jason Crain <jason@aquaticape.us>
25
// Copyright (C) 2015 Thomas Freitag <Thomas.Freitag@alfa.de>
26
// Copyright (C) 2018 Klarälvdalens Datakonsult AB, a KDAB Group company, <info@kdab.com>. Work sponsored by the LiMux project of the city of Munich
27
// Copyright (C) 2021, 2022, 2024 Oliver Sander <oliver.sander@tu-dresden.de>
28
// Copyright (C) 2024-2026 g10 Code GmbH, Author: Sune Stolborg Vuorela <sune@vuorela.dk>
29
// Copyright (C) 2026 Stefan Brüns <stefan.bruens@rwth-aachen.de>
30
//
31
// To see a description of the changes please see the Changelog file that
32
// came with your tarball or type make ChangeLog if you are building from git
33
//
34
//========================================================================
35
36
#ifndef GFXFONT_H
37
#define GFXFONT_H
38
39
#include <memory>
40
#include <array>
41
#include <optional>
42
43
#include "goo/GooString.h"
44
#include "Object.h"
45
#include "CharTypes.h"
46
#include "poppler_private_export.h"
47
48
class Dict;
49
class CMap;
50
class CharCodeToUnicode;
51
class FoFiTrueType;
52
class PSOutputDev;
53
struct GfxFontCIDWidths;
54
struct Base14FontMapEntry;
55
class FNVHash;
56
57
//------------------------------------------------------------------------
58
// GfxFontType
59
//------------------------------------------------------------------------
60
61
enum GfxFontType
62
{
63
    //----- Gfx8BitFont
64
    fontUnknownType,
65
    fontType1,
66
    fontType1C,
67
    fontType1COT,
68
    fontType3,
69
    fontTrueType,
70
    fontTrueTypeOT,
71
    //----- GfxCIDFont
72
    fontCIDType0,
73
    fontCIDType0C,
74
    fontCIDType0COT,
75
    fontCIDType2,
76
    fontCIDType2OT
77
};
78
79
//------------------------------------------------------------------------
80
// GfxFontCIDWidths
81
//------------------------------------------------------------------------
82
83
struct GfxFontCIDWidthExcep
84
{
85
    CID first; // this record applies to
86
    CID last; //   CIDs <first>..<last>
87
    double width; // char width
88
};
89
90
struct GfxFontCIDWidthExcepV
91
{
92
    CID first; // this record applies to
93
    CID last; //   CIDs <first>..<last>
94
    double height; // char height
95
    double vx, vy; // origin position
96
};
97
98
struct GfxFontCIDWidths
99
{
100
    double defWidth; // default char width
101
    double defHeight; // default char height
102
    double defVY; // default origin position
103
    std::vector<GfxFontCIDWidthExcep> exceps; // exceptions
104
    std::vector<GfxFontCIDWidthExcepV> excepsV; // exceptions for vertical font
105
};
106
107
//------------------------------------------------------------------------
108
// GfxFontLoc
109
//------------------------------------------------------------------------
110
111
enum GfxFontLocType
112
{
113
    gfxFontLocEmbedded, // font embedded in PDF file
114
    gfxFontLocExternal, // external font file
115
    gfxFontLocResident // font resident in PS printer
116
};
117
118
class POPPLER_PRIVATE_EXPORT GfxFontLoc
119
{
120
public:
121
    GfxFontLoc();
122
    ~GfxFontLoc();
123
124
    GfxFontLoc(const GfxFontLoc &) = delete;
125
    GfxFontLoc(GfxFontLoc &&) noexcept;
126
    GfxFontLoc &operator=(const GfxFontLoc &) = delete;
127
    GfxFontLoc &operator=(GfxFontLoc &&other) noexcept;
128
129
    GfxFontLocType locType;
130
    GfxFontType fontType;
131
    Ref embFontID; // embedded stream obj ID
132
                   //   (if locType == gfxFontLocEmbedded)
133
    std::string path; // font file path
134
                      //   (if locType == gfxFontLocExternal)
135
                      // PS font name
136
                      //   (if locType == gfxFontLocResident)
137
    int fontNum; // for TrueType collections
138
                 //   (if locType == gfxFontLocExternal)
139
    int substIdx; // substitute font index
140
                  //   (if locType == gfxFontLocExternal,
141
                  //   and a Base-14 substitution was made)
142
};
143
144
//------------------------------------------------------------------------
145
// GfxFont
146
//------------------------------------------------------------------------
147
148
77.1k
#define fontFixedWidth (1 << 0)
149
7.46k
#define fontSerif (1 << 1)
150
0
#define fontSymbolic (1 << 2)
151
1.45k
#define fontItalic (1 << 6)
152
1.45k
#define fontBold (1 << 18)
153
154
class POPPLER_PRIVATE_EXPORT GfxFont
155
{
156
public:
157
    enum Stretch
158
    {
159
        StretchNotDefined,
160
        UltraCondensed,
161
        ExtraCondensed,
162
        Condensed,
163
        SemiCondensed,
164
        Normal,
165
        SemiExpanded,
166
        Expanded,
167
        ExtraExpanded,
168
        UltraExpanded
169
    };
170
171
    enum Weight
172
    {
173
        WeightNotDefined,
174
        W100,
175
        W200,
176
        W300,
177
        W400, // Normal
178
        W500,
179
        W600,
180
        W700, // Bold
181
        W800,
182
        W900
183
    };
184
185
    // Build a GfxFont object.
186
    static std::unique_ptr<GfxFont> makeFont(XRef *xref, std::string_view tagA, Ref idA, const Dict &fontDict);
187
188
    GfxFont(const GfxFont &) = delete;
189
    GfxFont &operator=(const GfxFont &other) = delete;
190
    virtual ~GfxFont();
191
192
6.02k
    bool isOk() const { return ok; }
193
194
    // Get font tag.
195
0
    const std::string &getTag() const { return tag; }
196
197
    // Get font dictionary ID.
198
0
    const Ref *getID() const { return &id; }
199
200
    // Does this font match the tag?
201
40.0k
    bool matches(std::string_view tagA) const { return tag == tagA; }
202
203
    // Get font family name.
204
0
    const std::optional<std::string> &getFamily() const { return family; }
205
206
    // Get font stretch.
207
0
    Stretch getStretch() const { return stretch; }
208
209
    // Get font weight.
210
0
    Weight getWeight() const { return weight; }
211
212
    // Get the original font name (ignornig any munging that might have
213
    // been done to map to a canonical Base-14 font name).
214
3.94k
    const std::optional<std::string> &getName() const { return name; }
215
216
    bool isSubset() const;
217
218
    // Returns the original font name without the subset tag (if it has one)
219
    std::string getNameWithoutSubsetTag() const;
220
221
    // Get font type.
222
1.07M
    GfxFontType getType() const { return type; }
223
0
    virtual bool isCIDFont() const { return false; }
224
225
    // Get embedded font ID, i.e., a ref for the font file stream.
226
    // Returns false if there is no embedded font.
227
    bool getEmbeddedFontID(Ref *embID) const
228
0
    {
229
0
        *embID = embFontID;
230
0
        return embFontID != Ref::INVALID();
231
0
    }
232
233
    // Invalidate an embedded font
234
    // Returns false if there is no embedded font.
235
    bool invalidateEmbeddedFont()
236
0
    {
237
0
        if (embFontID != Ref::INVALID()) {
238
0
            embFontID = Ref::INVALID();
239
0
            return true;
240
0
        }
241
0
        return false;
242
0
    }
243
244
    // Get the PostScript font name for the embedded font.  Returns
245
    // NULL if there is no embedded font.
246
0
    const GooString *getEmbeddedFontName() const { return embFontName.get(); }
247
248
    // Get font descriptor flags.
249
3.94k
    int getFlags() const { return flags; }
250
1.45k
    bool isFixedWidth() const { return flags & fontFixedWidth; }
251
1.44k
    bool isSerif() const { return flags & fontSerif; }
252
0
    bool isSymbolic() const { return flags & fontSymbolic; }
253
1.45k
    bool isItalic() const { return flags & fontItalic; }
254
1.45k
    bool isBold() const { return flags & fontBold; }
255
256
    // Return the Unicode map.
257
    virtual const CharCodeToUnicode *getToUnicode() const = 0;
258
259
    // Return the font matrix.
260
0
    const std::array<double, 6> &getFontMatrix() const { return fontMat; }
261
262
    // Return the font bounding box.
263
0
    const std::array<double, 4> &getFontBBox() const { return fontBBox; }
264
265
    // Return the ascent and descent values.
266
866k
    double getAscent() const { return ascent; }
267
866k
    double getDescent() const { return descent; }
268
269
    enum class WritingMode
270
    {
271
        Horizontal,
272
        Vertical
273
    };
274
275
    // Return the writing mode
276
3.53M
    virtual WritingMode getWMode() const { return WritingMode::Horizontal; }
277
278
    // Locate the font file for this font.  If <ps> is not null, includes PS
279
    // printer-resident fonts.  Returns std::optional without a value on failure.
280
    // substituteFontName is passed down to the GlobalParams::findSystemFontFile/findBase14FontFile call
281
    std::optional<GfxFontLoc> locateFont(XRef *xref, PSOutputDev *ps, GooString *substituteFontName = nullptr);
282
283
    // Read an external or embedded font file into a buffer.
284
    std::optional<std::vector<unsigned char>> readEmbFontFile(XRef *xref);
285
286
    // Get the next char from a string <s> of <len> bytes, returning the
287
    // char <code>, its Unicode mapping <u>, its displacement vector
288
    // (<dx>, <dy>), and its origin offset vector (<ox>, <oy>).  <uSize>
289
    // is the number of entries available in <u>, and <uLen> is set to
290
    // the number actually used.  Returns the number of bytes used by
291
    // the char code.
292
    virtual int getNextChar(const char *s, int len, CharCode *code, Unicode const **u, int *uLen, double *dx, double *dy, double *ox, double *oy) const = 0;
293
294
    // Does this font have a toUnicode map?
295
0
    bool hasToUnicodeCMap() const { return hasToUnicode; }
296
297
    // Return the name of the encoding
298
0
    const std::string &getEncodingName() const { return encodingName; }
299
300
    // Return AGLFN names of ligatures in the Standard and Expert encodings
301
    // for use with fonts that are not compatible with the Standard 14 fonts.
302
    // http://sourceforge.net/adobe/aglfn/wiki/AGL%20Specification/
303
    static const char *getAlternateName(const char *name);
304
305
    static bool isBase14Font(std::string_view family, std::string_view style);
306
307
protected:
308
    GfxFont(std::string_view tagA, Ref idA, std::optional<std::string> &&nameA, GfxFontType typeA, Ref embFontIDA);
309
310
    static GfxFontType getFontType(XRef *xref, const Dict &fontDict, Ref *embID);
311
    void readFontDescriptor(const Dict &fontDict);
312
    [[nodiscard]] std::unique_ptr<CharCodeToUnicode> readToUnicodeCMap(const Dict &fontDict, int nBits, std::unique_ptr<CharCodeToUnicode> ctu);
313
    static std::optional<GfxFontLoc> getExternalFont(const std::string &path, bool cid);
314
315
    const std::string tag; // PDF font tag
316
    const Ref id; // reference (used as unique ID)
317
    std::optional<std::string> name; // font name
318
    std::optional<std::string> family; // font family
319
    Stretch stretch; // font stretch
320
    Weight weight; // font weight
321
    const GfxFontType type; // type of font
322
    int flags; // font descriptor flags
323
    std::unique_ptr<GooString> embFontName; // name of embedded font
324
    Ref embFontID; // ref to embedded font file stream
325
    std::array<double, 6> fontMat; // font matrix (Type 3 only)
326
    std::array<double, 4> fontBBox; // font bounding box (Type 3 only)
327
    double missingWidth; // "default" width
328
    double ascent; // max height above baseline
329
    double descent; // max depth below baseline
330
    bool ok;
331
    bool hasToUnicode;
332
    std::string encodingName;
333
};
334
335
//------------------------------------------------------------------------
336
// Gfx8BitFont
337
//------------------------------------------------------------------------
338
339
class POPPLER_PRIVATE_EXPORT Gfx8BitFont : public GfxFont
340
{
341
public:
342
    Gfx8BitFont(XRef *xref, std::string_view tagA, Ref idA, std::optional<std::string> &&nameA, GfxFontType typeA, Ref embFontIDA, const Dict &fontDict);
343
344
    int getNextChar(const char *s, int len, CharCode *code, Unicode const **u, int *uLen, double *dx, double *dy, double *ox, double *oy) const override;
345
346
    // Return the encoding.
347
0
    const std::array<const char *, 256> &getEncoding() const { return enc; }
348
349
    // Return the Unicode map.
350
    const CharCodeToUnicode *getToUnicode() const override;
351
352
    // Return the character name associated with <code>.
353
0
    const char *getCharName(int code) const { return enc[code]; }
354
355
    // Returns true if the PDF font specified an encoding.
356
0
    bool getHasEncoding() const { return hasEncoding; }
357
358
    // Returns true if the PDF font specified MacRomanEncoding.
359
0
    bool getUsesMacRomanEnc() const { return usesMacRomanEnc; }
360
361
    // Get width of a character.
362
0
    double getWidth(unsigned char c) const { return widths[c]; }
363
364
    // Return a char code-to-GID mapping for the provided font file.
365
    // (This is only useful for TrueType fonts.)
366
    std::vector<int> getCodeToGIDMap(FoFiTrueType *ff);
367
368
    // Return the Type 3 CharProc dictionary, or NULL if none.
369
    Dict *getCharProcs();
370
371
    // Return the Type 3 CharProc for the character associated with <code>.
372
    Object getCharProc(int code);
373
    Object getCharProcNF(int code);
374
375
    // Return the Type 3 Resources dictionary, or NULL if none.
376
    Dict *getResources();
377
378
    ~Gfx8BitFont() override;
379
380
private:
381
    const Base14FontMapEntry *base14; // for Base-14 fonts only; NULL otherwise
382
    std::array<const char *, 256> enc; // char code --> char name
383
    char encFree[256]; // boolean for each char name: if set,
384
                       //   the string is malloc'ed
385
    std::unique_ptr<CharCodeToUnicode> ctu; // char code --> Unicode
386
    bool hasEncoding;
387
    bool usesMacRomanEnc;
388
    double widths[256]; // character widths
389
    Object charProcs; // Type 3 CharProcs dictionary
390
    Object resources; // Type 3 Resources dictionary
391
392
    friend class GfxFont;
393
};
394
395
//------------------------------------------------------------------------
396
// GfxCIDFont
397
//------------------------------------------------------------------------
398
399
class POPPLER_PRIVATE_EXPORT GfxCIDFont : public GfxFont
400
{
401
public:
402
    GfxCIDFont(std::string_view tagA, Ref idA, std::optional<std::string> &&nameA, GfxFontType typeA, Ref embFontIDA, const Dict &fontDict);
403
404
0
    bool isCIDFont() const override { return true; }
405
406
    int getNextChar(const char *s, int len, CharCode *code, Unicode const **u, int *uLen, double *dx, double *dy, double *ox, double *oy) const override;
407
408
    // Return the writing mode (0=horizontal, 1=vertical).
409
    WritingMode getWMode() const override;
410
411
    // Return the Unicode map.
412
    const CharCodeToUnicode *getToUnicode() const override;
413
414
    // Get the collection name (<registry>-<ordering>).
415
    const GooString *getCollection() const;
416
417
    // Return the CID-to-GID mapping table.  These should only be called
418
    // if type is fontCIDType2.
419
0
    const std::vector<int> &getCIDToGID() const { return cidToGID; }
420
0
    unsigned int getCIDToGIDLen() const { return cidToGID.size(); }
421
422
    std::vector<int> getCodeToGIDMap(FoFiTrueType *ff);
423
424
    double getWidth(char *s, int len) const;
425
426
    ~GfxCIDFont() override;
427
428
private:
429
    static int mapCodeToGID(FoFiTrueType *ff, int cmapi, Unicode unicode, GfxFont::WritingMode wmode);
430
    double getWidth(CID cid) const; // Get width of a character.
431
432
    std::shared_ptr<CMap> cMap; // char code --> CID
433
    std::shared_ptr<CharCodeToUnicode> ctu; // CID --> Unicode
434
    bool ctuUsesCharCode; // true: ctu maps char code to Unicode;
435
                          //   false: ctu maps CID to Unicode
436
    GfxFontCIDWidths widths; // character widths
437
    std::vector<int> cidToGID; // CID --> GID mapping (for embedded
438
                               //   TrueType fonts)
439
};
440
441
//------------------------------------------------------------------------
442
// GfxFontDict
443
//------------------------------------------------------------------------
444
445
class GfxFontDict
446
{
447
public:
448
    // Build the font dictionary, given the PDF font dictionary.
449
    GfxFontDict(XRef *xref, Ref fontDictRef, const Dict &fontDict);
450
451
    GfxFontDict(const GfxFontDict &) = delete;
452
    GfxFontDict &operator=(const GfxFontDict &) = delete;
453
454
    // Get the specified font.
455
    std::shared_ptr<GfxFont> lookup(std::string_view tag) const;
456
457
    // Iterative access.
458
0
    int getNumFonts() const { return fonts.size(); }
459
0
    const std::shared_ptr<GfxFont> &getFont(int i) const { return fonts[i]; }
460
461
private:
462
    int hashFontObject(Object *obj);
463
    void hashFontObject1(const Object *obj, FNVHash *h);
464
465
    std::vector<std::shared_ptr<GfxFont>> fonts;
466
};
467
468
#endif