/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 |