1//========================================================================
2//
3// FoFiTrueType.cc
4//
5// Copyright 1999-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) 2006 Takashi Iwai <tiwai@suse.de>
17// Copyright (C) 2007 Koji Otani <sho@bbr.jp>
18// Copyright (C) 2007 Carlos Garcia Campos <carlosgc@gnome.org>
19// Copyright (C) 2008, 2009, 2012, 2014-2022 Albert Astals Cid <aacid@kde.org>
20// Copyright (C) 2008 Tomas Are Haavet <tomasare@gmail.com>
21// Copyright (C) 2012 Suzuki Toshiya <mpsuzuki@hiroshima-u.ac.jp>
22// Copyright (C) 2012, 2017 Adrian Johnson <ajohnson@redneon.com>
23// Copyright (C) 2014 Thomas Freitag <Thomas.Freitag@alfa.de>
24// Copyright (C) 2015 Aleksei Volkov <Aleksei Volkov>
25// Copyright (C) 2015, 2016 William Bader <williambader@hotmail.com>
26// Copyright (C) 2018 Adam Reichold <adam.reichold@t-online.de>
27// Copyright (C) 2022 Zachary Travis <ztravis@everlaw.com>
28// Copyright (C) 2022 Oliver Sander <oliver.sander@tu-dresden.de>
29//
30// To see a description of the changes please see the Changelog file that
31// came with your tarball or type make ChangeLog if you are building from git
32//
33//========================================================================
34
35#include <config.h>
36
37#include <cstdlib>
38#include <cstring>
39#include <climits>
40#include <algorithm>
41#include "goo/gmem.h"
42#include "goo/GooLikely.h"
43#include "goo/GooString.h"
44#include "FoFiType1C.h"
45#include "FoFiTrueType.h"
46#include "poppler/Error.h"
47
48//
49// Terminology
50// -----------
51//
52// character code = number used as an element of a text string
53//
54// character name = glyph name = name for a particular glyph within a
55// font
56//
57// glyph index = GID = position (within some internal table in the font)
58// where the instructions to draw a particular glyph are
59// stored
60//
61// Type 1 fonts
62// ------------
63//
64// Type 1 fonts contain:
65//
66// Encoding: array of glyph names, maps char codes to glyph names
67//
68// Encoding[charCode] = charName
69//
70// CharStrings: dictionary of instructions, keyed by character names,
71// maps character name to glyph data
72//
73// CharStrings[charName] = glyphData
74//
75// TrueType fonts
76// --------------
77//
78// TrueType fonts contain:
79//
80// 'cmap' table: mapping from character code to glyph index; there may
81// be multiple cmaps in a TrueType font
82//
83// cmap[charCode] = gid
84//
85// 'post' table: mapping from glyph index to glyph name
86//
87// post[gid] = glyphName
88//
89// Type 42 fonts
90// -------------
91//
92// Type 42 fonts contain:
93//
94// Encoding: array of glyph names, maps char codes to glyph names
95//
96// Encoding[charCode] = charName
97//
98// CharStrings: dictionary of glyph indexes, keyed by character names,
99// maps character name to glyph index
100//
101// CharStrings[charName] = gid
102//
103
104//------------------------------------------------------------------------
105
106#define ttcfTag 0x74746366
107
108//------------------------------------------------------------------------
109
110struct TrueTypeTable
111{
112 unsigned int tag;
113 unsigned int checksum;
114 int offset;
115 int origOffset;
116 int len;
117};
118
119struct TrueTypeCmap
120{
121 int platform;
122 int encoding;
123 int offset;
124 int len;
125 int fmt;
126};
127
128struct TrueTypeLoca
129{
130 int idx;
131 int origOffset;
132 int newOffset;
133 int len;
134};
135
136#define cmapTag 0x636d6170
137#define glyfTag 0x676c7966
138#define headTag 0x68656164
139#define hheaTag 0x68686561
140#define hmtxTag 0x686d7478
141#define locaTag 0x6c6f6361
142#define nameTag 0x6e616d65
143#define os2Tag 0x4f532f32
144#define postTag 0x706f7374
145#define vrt2Tag 0x76727432
146#define vertTag 0x76657274
147
148struct cmpTrueTypeLocaOffsetFunctor
149{
150 bool operator()(const TrueTypeLoca loca1, const TrueTypeLoca loca2)
151 {
152 if (loca1.origOffset == loca2.origOffset) {
153 return loca1.idx < loca2.idx;
154 }
155 return loca1.origOffset < loca2.origOffset;
156 }
157};
158
159struct cmpTrueTypeLocaIdxFunctor
160{
161 bool operator()(const TrueTypeLoca loca1, const TrueTypeLoca loca2) { return loca1.idx < loca2.idx; }
162};
163
164struct cmpTrueTypeTableTagFunctor
165{
166 bool operator()(const TrueTypeTable &tab1, const TrueTypeTable &tab2) { return tab1.tag < tab2.tag; }
167};
168
169//------------------------------------------------------------------------
170
171struct T42Table
172{
173 const char *tag; // 4-byte tag
174 bool required; // required by the TrueType spec?
175};
176
177// TrueType tables to be embedded in Type 42 fonts.
178// NB: the table names must be in alphabetical order here.
179#define nT42Tables 11
180static const T42Table t42Tables[nT42Tables] = { { .tag: "cvt ", .required: true }, { .tag: "fpgm", .required: true }, { .tag: "glyf", .required: true }, { .tag: "head", .required: true }, { .tag: "hhea", .required: true }, { .tag: "hmtx", .required: true },
181 { .tag: "loca", .required: true }, { .tag: "maxp", .required: true }, { .tag: "prep", .required: true }, { .tag: "vhea", .required: false }, { .tag: "vmtx", .required: false } };
182#define t42HeadTable 3
183#define t42LocaTable 6
184#define t42GlyfTable 2
185#define t42VheaTable 9
186#define t42VmtxTable 10
187
188//------------------------------------------------------------------------
189
190// Glyph names in some arbitrary standard order that Apple uses for
191// their TrueType fonts.
192static const char *macGlyphNames[258] = { ".notdef",
193 "null",
194 "CR",
195 "space",
196 "exclam",
197 "quotedbl",
198 "numbersign",
199 "dollar",
200 "percent",
201 "ampersand",
202 "quotesingle",
203 "parenleft",
204 "parenright",
205 "asterisk",
206 "plus",
207 "comma",
208 "hyphen",
209 "period",
210 "slash",
211 "zero",
212 "one",
213 "two",
214 "three",
215 "four",
216 "five",
217 "six",
218 "seven",
219 "eight",
220 "nine",
221 "colon",
222 "semicolon",
223 "less",
224 "equal",
225 "greater",
226 "question",
227 "at",
228 "A",
229 "B",
230 "C",
231 "D",
232 "E",
233 "F",
234 "G",
235 "H",
236 "I",
237 "J",
238 "K",
239 "L",
240 "M",
241 "N",
242 "O",
243 "P",
244 "Q",
245 "R",
246 "S",
247 "T",
248 "U",
249 "V",
250 "W",
251 "X",
252 "Y",
253 "Z",
254 "bracketleft",
255 "backslash",
256 "bracketright",
257 "asciicircum",
258 "underscore",
259 "grave",
260 "a",
261 "b",
262 "c",
263 "d",
264 "e",
265 "f",
266 "g",
267 "h",
268 "i",
269 "j",
270 "k",
271 "l",
272 "m",
273 "n",
274 "o",
275 "p",
276 "q",
277 "r",
278 "s",
279 "t",
280 "u",
281 "v",
282 "w",
283 "x",
284 "y",
285 "z",
286 "braceleft",
287 "bar",
288 "braceright",
289 "asciitilde",
290 "Adieresis",
291 "Aring",
292 "Ccedilla",
293 "Eacute",
294 "Ntilde",
295 "Odieresis",
296 "Udieresis",
297 "aacute",
298 "agrave",
299 "acircumflex",
300 "adieresis",
301 "atilde",
302 "aring",
303 "ccedilla",
304 "eacute",
305 "egrave",
306 "ecircumflex",
307 "edieresis",
308 "iacute",
309 "igrave",
310 "icircumflex",
311 "idieresis",
312 "ntilde",
313 "oacute",
314 "ograve",
315 "ocircumflex",
316 "odieresis",
317 "otilde",
318 "uacute",
319 "ugrave",
320 "ucircumflex",
321 "udieresis",
322 "dagger",
323 "degree",
324 "cent",
325 "sterling",
326 "section",
327 "bullet",
328 "paragraph",
329 "germandbls",
330 "registered",
331 "copyright",
332 "trademark",
333 "acute",
334 "dieresis",
335 "notequal",
336 "AE",
337 "Oslash",
338 "infinity",
339 "plusminus",
340 "lessequal",
341 "greaterequal",
342 "yen",
343 "mu",
344 "partialdiff",
345 "summation",
346 "product",
347 "pi",
348 "integral",
349 "ordfeminine",
350 "ordmasculine",
351 "Omega",
352 "ae",
353 "oslash",
354 "questiondown",
355 "exclamdown",
356 "logicalnot",
357 "radical",
358 "florin",
359 "approxequal",
360 "increment",
361 "guillemotleft",
362 "guillemotright",
363 "ellipsis",
364 "nbspace",
365 "Agrave",
366 "Atilde",
367 "Otilde",
368 "OE",
369 "oe",
370 "endash",
371 "emdash",
372 "quotedblleft",
373 "quotedblright",
374 "quoteleft",
375 "quoteright",
376 "divide",
377 "lozenge",
378 "ydieresis",
379 "Ydieresis",
380 "fraction",
381 "currency",
382 "guilsinglleft",
383 "guilsinglright",
384 "fi",
385 "fl",
386 "daggerdbl",
387 "periodcentered",
388 "quotesinglbase",
389 "quotedblbase",
390 "perthousand",
391 "Acircumflex",
392 "Ecircumflex",
393 "Aacute",
394 "Edieresis",
395 "Egrave",
396 "Iacute",
397 "Icircumflex",
398 "Idieresis",
399 "Igrave",
400 "Oacute",
401 "Ocircumflex",
402 "applelogo",
403 "Ograve",
404 "Uacute",
405 "Ucircumflex",
406 "Ugrave",
407 "dotlessi",
408 "circumflex",
409 "tilde",
410 "overscore",
411 "breve",
412 "dotaccent",
413 "ring",
414 "cedilla",
415 "hungarumlaut",
416 "ogonek",
417 "caron",
418 "Lslash",
419 "lslash",
420 "Scaron",
421 "scaron",
422 "Zcaron",
423 "zcaron",
424 "brokenbar",
425 "Eth",
426 "eth",
427 "Yacute",
428 "yacute",
429 "Thorn",
430 "thorn",
431 "minus",
432 "multiply",
433 "onesuperior",
434 "twosuperior",
435 "threesuperior",
436 "onehalf",
437 "onequarter",
438 "threequarters",
439 "franc",
440 "Gbreve",
441 "gbreve",
442 "Idot",
443 "Scedilla",
444 "scedilla",
445 "Cacute",
446 "cacute",
447 "Ccaron",
448 "ccaron",
449 "dmacron" };
450
451//------------------------------------------------------------------------
452// FoFiTrueType
453//------------------------------------------------------------------------
454
455std::unique_ptr<FoFiTrueType> FoFiTrueType::make(const unsigned char *fileA, int lenA, int faceIndexA)
456{
457 // Cannot use std::make_unique, because the constructor is private
458 auto ff = new FoFiTrueType(fileA, lenA, false, faceIndexA);
459 if (!ff->parsedOk) {
460 delete ff;
461 return nullptr;
462 }
463 return std::unique_ptr<FoFiTrueType>(ff);
464}
465
466std::unique_ptr<FoFiTrueType> FoFiTrueType::load(const char *fileName, int faceIndexA)
467{
468 char *fileA;
469 int lenA;
470
471 if (!(fileA = FoFiBase::readFile(fileName, fileLen: &lenA))) {
472 return nullptr;
473 }
474 // Cannot use std::make_unique, because the constructor is private
475 auto ff = new FoFiTrueType((unsigned char *)fileA, lenA, true, faceIndexA);
476 if (!ff->parsedOk) {
477 delete ff;
478 return nullptr;
479 }
480 return std::unique_ptr<FoFiTrueType>(ff);
481}
482
483FoFiTrueType::FoFiTrueType(const unsigned char *fileA, int lenA, bool freeFileDataA, int faceIndexA) : FoFiBase(fileA, lenA, freeFileDataA)
484{
485 tables = nullptr;
486 nTables = 0;
487 cmaps = nullptr;
488 nCmaps = 0;
489 parsedOk = false;
490 faceIndex = faceIndexA;
491 gsubFeatureTable = 0;
492 gsubLookupList = 0;
493
494 parse();
495}
496
497FoFiTrueType::~FoFiTrueType()
498{
499 gfree(p: tables);
500 gfree(p: cmaps);
501}
502
503int FoFiTrueType::getNumCmaps() const
504{
505 return nCmaps;
506}
507
508int FoFiTrueType::getCmapPlatform(int i) const
509{
510 return cmaps[i].platform;
511}
512
513int FoFiTrueType::getCmapEncoding(int i) const
514{
515 return cmaps[i].encoding;
516}
517
518int FoFiTrueType::findCmap(int platform, int encoding) const
519{
520 int i;
521
522 for (i = 0; i < nCmaps; ++i) {
523 if (cmaps[i].platform == platform && cmaps[i].encoding == encoding) {
524 return i;
525 }
526 }
527 return -1;
528}
529
530int FoFiTrueType::mapCodeToGID(int i, unsigned int c) const
531{
532 int gid;
533 unsigned int segCnt, segEnd, segStart, segDelta, segOffset;
534 unsigned int cmapFirst, cmapLen;
535 int pos, a, b, m;
536 unsigned int high, low, idx;
537 bool ok;
538
539 if (i < 0 || i >= nCmaps) {
540 return 0;
541 }
542 ok = true;
543 pos = cmaps[i].offset;
544 switch (cmaps[i].fmt) {
545 case 0:
546 if (c + 6 >= (unsigned int)cmaps[i].len) {
547 return 0;
548 }
549 gid = getU8(pos: cmaps[i].offset + 6 + c, ok: &ok);
550 break;
551 case 2:
552 high = c >> 8;
553 low = c & 0xFFU;
554 idx = getU16BE(pos: pos + 6 + high * 2, ok: &ok);
555 segStart = getU16BE(pos: pos + 6 + 512 + idx, ok: &ok);
556 segCnt = getU16BE(pos: pos + 6 + 512 + idx + 2, ok: &ok);
557 segDelta = getS16BE(pos: pos + 6 + 512 + idx + 4, ok: &ok);
558 segOffset = getU16BE(pos: pos + 6 + 512 + idx + 6, ok: &ok);
559 if (low < segStart || low >= segStart + segCnt) {
560 gid = 0;
561 } else {
562 int val = getU16BE(pos: pos + 6 + 512 + idx + 6 + segOffset + (low - segStart) * 2, ok: &ok);
563 gid = val == 0 ? 0 : (val + segDelta) & 0xFFFFU;
564 }
565 break;
566 case 4:
567 segCnt = getU16BE(pos: pos + 6, ok: &ok) / 2;
568 a = -1;
569 b = segCnt - 1;
570 segEnd = getU16BE(pos: pos + 14 + 2 * b, ok: &ok);
571 if (c > segEnd) {
572 // malformed font -- the TrueType spec requires the last segEnd
573 // to be 0xffff
574 return 0;
575 }
576 // invariant: seg[a].end < code <= seg[b].end
577 while (b - a > 1 && ok) {
578 m = (a + b) / 2;
579 segEnd = getU16BE(pos: pos + 14 + 2 * m, ok: &ok);
580 if (segEnd < c) {
581 a = m;
582 } else {
583 b = m;
584 }
585 }
586 segStart = getU16BE(pos: pos + 16 + 2 * segCnt + 2 * b, ok: &ok);
587 segDelta = getU16BE(pos: pos + 16 + 4 * segCnt + 2 * b, ok: &ok);
588 segOffset = getU16BE(pos: pos + 16 + 6 * segCnt + 2 * b, ok: &ok);
589 if (c < segStart) {
590 return 0;
591 }
592 if (segOffset == 0) {
593 gid = (c + segDelta) & 0xffff;
594 } else {
595 gid = getU16BE(pos: pos + 16 + 6 * segCnt + 2 * b + segOffset + 2 * (c - segStart), ok: &ok);
596 if (gid != 0) {
597 gid = (gid + segDelta) & 0xffff;
598 }
599 }
600 break;
601 case 6:
602 cmapFirst = getU16BE(pos: pos + 6, ok: &ok);
603 cmapLen = getU16BE(pos: pos + 8, ok: &ok);
604 if (c < cmapFirst || c >= cmapFirst + cmapLen) {
605 return 0;
606 }
607 gid = getU16BE(pos: pos + 10 + 2 * (c - cmapFirst), ok: &ok);
608 break;
609 case 12:
610 case 13:
611 segCnt = getU32BE(pos: pos + 12, ok: &ok);
612 a = -1;
613 b = segCnt - 1;
614 segEnd = getU32BE(pos: pos + 16 + 12 * b + 4, ok: &ok);
615 if (c > segEnd) {
616 return 0;
617 }
618 // invariant: seg[a].end < code <= seg[b].end
619 while (b - a > 1 && ok) {
620 m = (a + b) / 2;
621 segEnd = getU32BE(pos: pos + 16 + 12 * m + 4, ok: &ok);
622 if (segEnd < c) {
623 a = m;
624 } else {
625 b = m;
626 }
627 }
628 segStart = getU32BE(pos: pos + 16 + 12 * b, ok: &ok);
629 segDelta = getU32BE(pos: pos + 16 + 12 * b + 8, ok: &ok);
630 if (c < segStart) {
631 return 0;
632 }
633 // In format 12, the glyph codes increment through
634 // each segment; in format 13 the same glyph code is used
635 // for an entire segment.
636 gid = segDelta + (cmaps[i].fmt == 12 ? (c - segStart) : 0);
637 break;
638 default:
639 return 0;
640 }
641 if (!ok) {
642 return 0;
643 }
644 return gid;
645}
646
647int FoFiTrueType::mapNameToGID(const char *name) const
648{
649 const auto gid = nameToGID.find(x: name);
650 if (gid == nameToGID.end()) {
651 return 0;
652 }
653 return gid->second;
654}
655
656bool FoFiTrueType::getCFFBlock(char **start, int *length) const
657{
658 int i;
659
660 if (!openTypeCFF || !tables) {
661 return false;
662 }
663 i = seekTable(tag: "CFF ");
664 if (i < 0 || !checkRegion(pos: tables[i].offset, size: tables[i].len)) {
665 return false;
666 }
667 *start = (char *)file + tables[i].offset;
668 *length = tables[i].len;
669 return true;
670}
671
672int *FoFiTrueType::getCIDToGIDMap(int *nCIDs) const
673{
674 char *start;
675 int length;
676 FoFiType1C *ff;
677 int *map;
678
679 *nCIDs = 0;
680 if (!getCFFBlock(start: &start, length: &length)) {
681 return nullptr;
682 }
683 if (!(ff = FoFiType1C::make(fileA: (unsigned char *)start, lenA: length))) {
684 return nullptr;
685 }
686 map = ff->getCIDToGIDMap(nCIDs);
687 delete ff;
688 return map;
689}
690
691int FoFiTrueType::getEmbeddingRights() const
692{
693 int i, fsType;
694 bool ok;
695
696 if ((i = seekTable(tag: "OS/2")) < 0) {
697 return 4;
698 }
699 ok = true;
700 fsType = getU16BE(pos: tables[i].offset + 8, ok: &ok);
701 if (!ok) {
702 return 4;
703 }
704 if (fsType & 0x0008) {
705 return 2;
706 }
707 if (fsType & 0x0004) {
708 return 1;
709 }
710 if (fsType & 0x0002) {
711 return 0;
712 }
713 return 3;
714}
715
716void FoFiTrueType::getFontMatrix(double *mat) const
717{
718 char *start;
719 int length;
720 FoFiType1C *ff;
721
722 if (!getCFFBlock(start: &start, length: &length)) {
723 return;
724 }
725 if (!(ff = FoFiType1C::make(fileA: (unsigned char *)start, lenA: length))) {
726 return;
727 }
728 ff->getFontMatrix(mat);
729 delete ff;
730}
731
732void FoFiTrueType::convertToType42(const char *psName, char **encoding, int *codeToGID, FoFiOutputFunc outputFunc, void *outputStream) const
733{
734 int maxUsedGlyph;
735 bool ok;
736
737 if (openTypeCFF) {
738 return;
739 }
740
741 // write the header
742 ok = true;
743 std::unique_ptr<GooString> buf = GooString::format(fmt: "%!PS-TrueTypeFont-{0:2g}\n", (double)getS32BE(pos: 0, ok: &ok) / 65536.0);
744 (*outputFunc)(outputStream, buf->c_str(), buf->getLength());
745
746 // begin the font dictionary
747 (*outputFunc)(outputStream, "10 dict begin\n", 14);
748 (*outputFunc)(outputStream, "/FontName /", 11);
749 (*outputFunc)(outputStream, psName, strlen(s: psName));
750 (*outputFunc)(outputStream, " def\n", 5);
751 (*outputFunc)(outputStream, "/FontType 42 def\n", 17);
752 (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
753 buf = GooString::format(fmt: "/FontBBox [{0:d} {1:d} {2:d} {3:d}] def\n", bbox[0], bbox[1], bbox[2], bbox[3]);
754 (*outputFunc)(outputStream, buf->c_str(), buf->getLength());
755 (*outputFunc)(outputStream, "/PaintType 0 def\n", 17);
756
757 // write the guts of the dictionary
758 cvtEncoding(encoding, outputFunc, outputStream);
759 cvtCharStrings(encoding, codeToGID, outputFunc, outputStream);
760 cvtSfnts(outputFunc, outputStream, name: nullptr, needVerticalMetrics: false, maxUsedGlyph: &maxUsedGlyph);
761
762 // end the dictionary and define the font
763 (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
764}
765
766void FoFiTrueType::convertToType1(const char *psName, const char **newEncoding, bool ascii, FoFiOutputFunc outputFunc, void *outputStream) const
767{
768 char *start;
769 int length;
770 FoFiType1C *ff;
771
772 if (!getCFFBlock(start: &start, length: &length)) {
773 return;
774 }
775 if (!(ff = FoFiType1C::make(fileA: (unsigned char *)start, lenA: length))) {
776 return;
777 }
778 ff->convertToType1(psName, newEncoding, ascii, outputFunc, outputStream);
779 delete ff;
780}
781
782void FoFiTrueType::convertToCIDType2(const char *psName, const int *cidMap, int nCIDs, bool needVerticalMetrics, FoFiOutputFunc outputFunc, void *outputStream) const
783{
784 int cid, maxUsedGlyph;
785 bool ok;
786 int i, j, k;
787
788 if (openTypeCFF) {
789 return;
790 }
791
792 // write the header
793 ok = true;
794 std::unique_ptr<GooString> buf = GooString::format(fmt: "%!PS-TrueTypeFont-{0:2g}\n", (double)getS32BE(pos: 0, ok: &ok) / 65536.0);
795 (*outputFunc)(outputStream, buf->c_str(), buf->getLength());
796
797 // begin the font dictionary
798 (*outputFunc)(outputStream, "20 dict begin\n", 14);
799 (*outputFunc)(outputStream, "/CIDFontName /", 14);
800 (*outputFunc)(outputStream, psName, strlen(s: psName));
801 (*outputFunc)(outputStream, " def\n", 5);
802 (*outputFunc)(outputStream, "/CIDFontType 2 def\n", 19);
803 (*outputFunc)(outputStream, "/FontType 42 def\n", 17);
804 (*outputFunc)(outputStream, "/CIDSystemInfo 3 dict dup begin\n", 32);
805 (*outputFunc)(outputStream, " /Registry (Adobe) def\n", 24);
806 (*outputFunc)(outputStream, " /Ordering (Identity) def\n", 27);
807 (*outputFunc)(outputStream, " /Supplement 0 def\n", 20);
808 (*outputFunc)(outputStream, " end def\n", 10);
809 (*outputFunc)(outputStream, "/GDBytes 2 def\n", 15);
810 if (cidMap) {
811 buf = GooString::format(fmt: "/CIDCount {0:d} def\n", nCIDs);
812 (*outputFunc)(outputStream, buf->c_str(), buf->getLength());
813 if (nCIDs > 32767) {
814 (*outputFunc)(outputStream, "/CIDMap [", 9);
815 for (i = 0; i < nCIDs; i += 32768 - 16) {
816 (*outputFunc)(outputStream, "<\n", 2);
817 for (j = 0; j < 32768 - 16 && i + j < nCIDs; j += 16) {
818 (*outputFunc)(outputStream, " ", 2);
819 for (k = 0; k < 16 && i + j + k < nCIDs; ++k) {
820 cid = cidMap[i + j + k];
821 buf = GooString::format(fmt: "{0:02x}{1:02x}", (cid >> 8) & 0xff, cid & 0xff);
822 (*outputFunc)(outputStream, buf->c_str(), buf->getLength());
823 }
824 (*outputFunc)(outputStream, "\n", 1);
825 }
826 (*outputFunc)(outputStream, " >", 3);
827 }
828 (*outputFunc)(outputStream, "\n", 1);
829 (*outputFunc)(outputStream, "] def\n", 6);
830 } else {
831 (*outputFunc)(outputStream, "/CIDMap <\n", 10);
832 for (i = 0; i < nCIDs; i += 16) {
833 (*outputFunc)(outputStream, " ", 2);
834 for (j = 0; j < 16 && i + j < nCIDs; ++j) {
835 cid = cidMap[i + j];
836 buf = GooString::format(fmt: "{0:02x}{1:02x}", (cid >> 8) & 0xff, cid & 0xff);
837 (*outputFunc)(outputStream, buf->c_str(), buf->getLength());
838 }
839 (*outputFunc)(outputStream, "\n", 1);
840 }
841 (*outputFunc)(outputStream, "> def\n", 6);
842 }
843 } else {
844 // direct mapping - just fill the string(s) with s[i]=i
845 buf = GooString::format(fmt: "/CIDCount {0:d} def\n", nGlyphs);
846 (*outputFunc)(outputStream, buf->c_str(), buf->getLength());
847 if (nGlyphs > 32767) {
848 (*outputFunc)(outputStream, "/CIDMap [\n", 10);
849 for (i = 0; i < nGlyphs; i += 32767) {
850 j = nGlyphs - i < 32767 ? nGlyphs - i : 32767;
851 buf = GooString::format(fmt: " {0:d} string 0 1 {1:d} {{\n", 2 * j, j - 1);
852 (*outputFunc)(outputStream, buf->c_str(), buf->getLength());
853 buf = GooString::format(fmt: " 2 copy dup 2 mul exch {0:d} add -8 bitshift put\n", i);
854 (*outputFunc)(outputStream, buf->c_str(), buf->getLength());
855 buf = GooString::format(fmt: " 1 index exch dup 2 mul 1 add exch {0:d} add"
856 " 255 and put\n",
857 i);
858 (*outputFunc)(outputStream, buf->c_str(), buf->getLength());
859 (*outputFunc)(outputStream, " } for\n", 8);
860 }
861 (*outputFunc)(outputStream, "] def\n", 6);
862 } else {
863 buf = GooString::format(fmt: "/CIDMap {0:d} string\n", 2 * nGlyphs);
864 (*outputFunc)(outputStream, buf->c_str(), buf->getLength());
865 buf = GooString::format(fmt: " 0 1 {0:d} {{\n", nGlyphs - 1);
866 (*outputFunc)(outputStream, buf->c_str(), buf->getLength());
867 (*outputFunc)(outputStream, " 2 copy dup 2 mul exch -8 bitshift put\n", 42);
868 (*outputFunc)(outputStream, " 1 index exch dup 2 mul 1 add exch 255 and put\n", 50);
869 (*outputFunc)(outputStream, " } for\n", 8);
870 (*outputFunc)(outputStream, "def\n", 4);
871 }
872 }
873 (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
874 buf = GooString::format(fmt: "/FontBBox [{0:d} {1:d} {2:d} {3:d}] def\n", bbox[0], bbox[1], bbox[2], bbox[3]);
875 (*outputFunc)(outputStream, buf->c_str(), buf->getLength());
876 (*outputFunc)(outputStream, "/PaintType 0 def\n", 17);
877 (*outputFunc)(outputStream, "/Encoding [] readonly def\n", 26);
878 (*outputFunc)(outputStream, "/CharStrings 1 dict dup begin\n", 30);
879 (*outputFunc)(outputStream, " /.notdef 0 def\n", 17);
880 (*outputFunc)(outputStream, " end readonly def\n", 19);
881
882 // write the guts of the dictionary
883 cvtSfnts(outputFunc, outputStream, name: nullptr, needVerticalMetrics, maxUsedGlyph: &maxUsedGlyph);
884
885 // end the dictionary and define the font
886 (*outputFunc)(outputStream, "CIDFontName currentdict end /CIDFont defineresource pop\n", 56);
887}
888
889void FoFiTrueType::convertToCIDType0(const char *psName, int *cidMap, int nCIDs, FoFiOutputFunc outputFunc, void *outputStream) const
890{
891 char *start;
892 int length;
893 FoFiType1C *ff;
894
895 if (!getCFFBlock(start: &start, length: &length)) {
896 return;
897 }
898 if (!(ff = FoFiType1C::make(fileA: (unsigned char *)start, lenA: length))) {
899 return;
900 }
901 ff->convertToCIDType0(psName, codeMap: cidMap, nCodes: nCIDs, outputFunc, outputStream);
902 delete ff;
903}
904
905void FoFiTrueType::convertToType0(const char *psName, int *cidMap, int nCIDs, bool needVerticalMetrics, int *maxValidGlyph, FoFiOutputFunc outputFunc, void *outputStream) const
906{
907 GooString *sfntsName;
908 int maxUsedGlyph, n, i, j;
909
910 *maxValidGlyph = -1;
911
912 if (openTypeCFF) {
913 return;
914 }
915
916 // write the Type 42 sfnts array
917 sfntsName = (new GooString(psName))->append(str: "_sfnts");
918 cvtSfnts(outputFunc, outputStream, name: sfntsName, needVerticalMetrics, maxUsedGlyph: &maxUsedGlyph);
919 delete sfntsName;
920
921 // write the descendant Type 42 fonts
922 // (The following is a kludge: nGlyphs is the glyph count from the
923 // maxp table; maxUsedGlyph is the max glyph number that has a
924 // non-zero-length description, from the loca table. The problem is
925 // that some TrueType font subsets fail to change the glyph count,
926 // i.e., nGlyphs is much larger than maxUsedGlyph+1, which results
927 // in an unnecessarily huge Type 0 font. But some other PDF files
928 // have fonts with only zero or one used glyph, and a content stream
929 // that refers to one of the unused glyphs -- this results in PS
930 // errors if we simply use maxUsedGlyph+1 for the Type 0 font. So
931 // we compromise by always defining at least 256 glyphs.)
932 // Some fonts have a large nGlyphs but maxUsedGlyph of 0.
933 // These fonts might reference any glyph.
934 // Return the last written glyph number in maxValidGlyph.
935 // PSOutputDev::drawString() can use maxValidGlyph to avoid
936 // referencing zero-length glyphs that we trimmed.
937 // This allows pdftops to avoid writing huge files while still
938 // handling the rare PDF that uses a zero-length glyph.
939 if (cidMap) {
940 n = nCIDs;
941 } else if (nGlyphs > maxUsedGlyph + 256) {
942 if (maxUsedGlyph <= 255) {
943 n = 256;
944 } else {
945 n = maxUsedGlyph + 1;
946 }
947 } else {
948 n = nGlyphs;
949 }
950 *maxValidGlyph = n - 1;
951 for (i = 0; i < n; i += 256) {
952 (*outputFunc)(outputStream, "10 dict begin\n", 14);
953 (*outputFunc)(outputStream, "/FontName /", 11);
954 (*outputFunc)(outputStream, psName, strlen(s: psName));
955 std::unique_ptr<GooString> buf = GooString::format(fmt: "_{0:02x} def\n", i >> 8);
956 (*outputFunc)(outputStream, buf->c_str(), buf->getLength());
957 (*outputFunc)(outputStream, "/FontType 42 def\n", 17);
958 (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
959 buf = GooString::format(fmt: "/FontBBox [{0:d} {1:d} {2:d} {3:d}] def\n", bbox[0], bbox[1], bbox[2], bbox[3]);
960 (*outputFunc)(outputStream, buf->c_str(), buf->getLength());
961 (*outputFunc)(outputStream, "/PaintType 0 def\n", 17);
962 (*outputFunc)(outputStream, "/sfnts ", 7);
963 (*outputFunc)(outputStream, psName, strlen(s: psName));
964 (*outputFunc)(outputStream, "_sfnts def\n", 11);
965 (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
966 for (j = 0; j < 256 && i + j < n; ++j) {
967 buf = GooString::format(fmt: "dup {0:d} /c{1:02x} put\n", j, j);
968 (*outputFunc)(outputStream, buf->c_str(), buf->getLength());
969 }
970 (*outputFunc)(outputStream, "readonly def\n", 13);
971 (*outputFunc)(outputStream, "/CharStrings 257 dict dup begin\n", 32);
972 (*outputFunc)(outputStream, "/.notdef 0 def\n", 15);
973 for (j = 0; j < 256 && i + j < n; ++j) {
974 buf = GooString::format(fmt: "/c{0:02x} {1:d} def\n", j, cidMap ? cidMap[i + j] : i + j);
975 (*outputFunc)(outputStream, buf->c_str(), buf->getLength());
976 }
977 (*outputFunc)(outputStream, "end readonly def\n", 17);
978 (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
979 }
980
981 // write the Type 0 parent font
982 (*outputFunc)(outputStream, "16 dict begin\n", 14);
983 (*outputFunc)(outputStream, "/FontName /", 11);
984 (*outputFunc)(outputStream, psName, strlen(s: psName));
985 (*outputFunc)(outputStream, " def\n", 5);
986 (*outputFunc)(outputStream, "/FontType 0 def\n", 16);
987 (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
988 (*outputFunc)(outputStream, "/FMapType 2 def\n", 16);
989 (*outputFunc)(outputStream, "/Encoding [\n", 12);
990 for (i = 0; i < n; i += 256) {
991 const std::unique_ptr<GooString> buf = GooString::format(fmt: "{0:d}\n", i >> 8);
992 (*outputFunc)(outputStream, buf->c_str(), buf->getLength());
993 }
994 (*outputFunc)(outputStream, "] def\n", 6);
995 (*outputFunc)(outputStream, "/FDepVector [\n", 14);
996 for (i = 0; i < n; i += 256) {
997 (*outputFunc)(outputStream, "/", 1);
998 (*outputFunc)(outputStream, psName, strlen(s: psName));
999 const std::unique_ptr<GooString> buf = GooString::format(fmt: "_{0:02x} findfont\n", i >> 8);
1000 (*outputFunc)(outputStream, buf->c_str(), buf->getLength());
1001 }
1002 (*outputFunc)(outputStream, "] def\n", 6);
1003 (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
1004}
1005
1006void FoFiTrueType::convertToType0(const char *psName, int *cidMap, int nCIDs, FoFiOutputFunc outputFunc, void *outputStream) const
1007{
1008 char *start;
1009 int length;
1010 FoFiType1C *ff;
1011
1012 if (!getCFFBlock(start: &start, length: &length)) {
1013 return;
1014 }
1015 if (!(ff = FoFiType1C::make(fileA: (unsigned char *)start, lenA: length))) {
1016 return;
1017 }
1018 ff->convertToType0(psName, codeMap: cidMap, nCodes: nCIDs, outputFunc, outputStream);
1019 delete ff;
1020}
1021
1022void FoFiTrueType::cvtEncoding(char **encoding, FoFiOutputFunc outputFunc, void *outputStream) const
1023{
1024 const char *name;
1025 int i;
1026
1027 (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
1028 if (encoding) {
1029 for (i = 0; i < 256; ++i) {
1030 if (!(name = encoding[i])) {
1031 name = ".notdef";
1032 }
1033 const std::unique_ptr<GooString> buf = GooString::format(fmt: "dup {0:d} /", i);
1034 (*outputFunc)(outputStream, buf->c_str(), buf->getLength());
1035 (*outputFunc)(outputStream, name, strlen(s: name));
1036 (*outputFunc)(outputStream, " put\n", 5);
1037 }
1038 } else {
1039 for (i = 0; i < 256; ++i) {
1040 const std::unique_ptr<GooString> buf = GooString::format(fmt: "dup {0:d} /c{1:02x} put\n", i, i);
1041 (*outputFunc)(outputStream, buf->c_str(), buf->getLength());
1042 }
1043 }
1044 (*outputFunc)(outputStream, "readonly def\n", 13);
1045}
1046
1047void FoFiTrueType::cvtCharStrings(char **encoding, const int *codeToGID, FoFiOutputFunc outputFunc, void *outputStream) const
1048{
1049 const char *name;
1050 char buf2[16];
1051 int i, k;
1052
1053 // always define '.notdef'
1054 (*outputFunc)(outputStream, "/CharStrings 256 dict dup begin\n", 32);
1055 (*outputFunc)(outputStream, "/.notdef 0 def\n", 15);
1056
1057 // if there's no 'cmap' table, punt
1058 if (nCmaps == 0) {
1059 goto err;
1060 }
1061
1062 // map char name to glyph index:
1063 // 1. use encoding to map name to char code
1064 // 2. use codeToGID to map char code to glyph index
1065 // N.B. We do this in reverse order because font subsets can have
1066 // weird encodings that use the same character name twice, and
1067 // the first definition is probably the one we want.
1068 k = 0; // make gcc happy
1069 for (i = 255; i >= 0; --i) {
1070 if (encoding) {
1071 name = encoding[i];
1072 } else {
1073 sprintf(s: buf2, format: "c%02x", i);
1074 name = buf2;
1075 }
1076 if (name && strcmp(s1: name, s2: ".notdef")) {
1077 k = codeToGID[i];
1078 // note: Distiller (maybe Adobe's PS interpreter in general)
1079 // doesn't like TrueType fonts that have CharStrings entries
1080 // which point to nonexistent glyphs, hence the (k < nGlyphs)
1081 // test
1082 if (k > 0 && k < nGlyphs) {
1083 (*outputFunc)(outputStream, "/", 1);
1084 (*outputFunc)(outputStream, name, strlen(s: name));
1085 const std::unique_ptr<GooString> buf = GooString::format(fmt: " {0:d} def\n", k);
1086 (*outputFunc)(outputStream, buf->c_str(), buf->getLength());
1087 }
1088 }
1089 }
1090
1091err:
1092 (*outputFunc)(outputStream, "end readonly def\n", 17);
1093}
1094
1095void FoFiTrueType::cvtSfnts(FoFiOutputFunc outputFunc, void *outputStream, const GooString *name, bool needVerticalMetrics, int *maxUsedGlyph) const
1096{
1097 unsigned char headData[54];
1098 TrueTypeLoca *locaTable;
1099 unsigned char *locaData;
1100 TrueTypeTable newTables[nT42Tables];
1101 unsigned char tableDir[12 + nT42Tables * 16];
1102 bool ok;
1103 unsigned int checksum;
1104 int nNewTables;
1105 int glyfTableLen, length, pos, glyfPos, i, j, k, vmtxTabLength;
1106 unsigned char vheaTab[36] = {
1107 0, 1, 0, 0, // table version number
1108 0, 0, // ascent
1109 0, 0, // descent
1110 0, 0, // reserved
1111 0, 0, // max advance height
1112 0, 0, // min top side bearing
1113 0, 0, // min bottom side bearing
1114 0, 0, // y max extent
1115 0, 0, // caret slope rise
1116 0, 1, // caret slope run
1117 0, 0, // caret offset
1118 0, 0, // reserved
1119 0, 0, // reserved
1120 0, 0, // reserved
1121 0, 0, // reserved
1122 0, 0, // metric data format
1123 0, 1 // number of advance heights in vmtx table
1124 };
1125 unsigned char *vmtxTab;
1126 bool needVhea, needVmtx;
1127 int advance;
1128
1129 *maxUsedGlyph = -1;
1130
1131 // construct the 'head' table, zero out the font checksum
1132 i = seekTable(tag: "head");
1133 if (i < 0 || i >= nTables) {
1134 return;
1135 }
1136 pos = tables[i].offset;
1137 if (!checkRegion(pos, size: 54)) {
1138 return;
1139 }
1140 memcpy(dest: headData, src: file + pos, n: 54);
1141 headData[8] = headData[9] = headData[10] = headData[11] = (unsigned char)0;
1142
1143 // check for a bogus loca format field in the 'head' table
1144 // (I've encountered fonts with loca format set to 0x0100 instead of 0x0001)
1145 if (locaFmt != 0 && locaFmt != 1) {
1146 headData[50] = 0;
1147 headData[51] = 1;
1148 }
1149
1150 // read the original 'loca' table, pad entries out to 4 bytes, and
1151 // sort it into proper order -- some (non-compliant) fonts have
1152 // out-of-order loca tables; in order to correctly handle the case
1153 // where (compliant) fonts have empty entries in the middle of the
1154 // table, cmpTrueTypeLocaOffset uses offset as its primary sort key,
1155 // and idx as its secondary key (ensuring that adjacent entries with
1156 // the same pos value remain in the same order)
1157 locaTable = (TrueTypeLoca *)gmallocn(count: nGlyphs + 1, size: sizeof(TrueTypeLoca));
1158 i = seekTable(tag: "loca");
1159 pos = tables[i].offset;
1160 i = seekTable(tag: "glyf");
1161 glyfTableLen = tables[i].len;
1162 ok = true;
1163 for (i = 0; i <= nGlyphs; ++i) {
1164 locaTable[i].idx = i;
1165 if (locaFmt) {
1166 locaTable[i].origOffset = (int)getU32BE(pos: pos + i * 4, ok: &ok);
1167 } else {
1168 locaTable[i].origOffset = 2 * getU16BE(pos: pos + i * 2, ok: &ok);
1169 }
1170 if (locaTable[i].origOffset > glyfTableLen) {
1171 locaTable[i].origOffset = glyfTableLen;
1172 }
1173 }
1174 std::sort(first: locaTable, last: locaTable + nGlyphs + 1, comp: cmpTrueTypeLocaOffsetFunctor());
1175 for (i = 0; i < nGlyphs; ++i) {
1176 locaTable[i].len = locaTable[i + 1].origOffset - locaTable[i].origOffset;
1177 }
1178 locaTable[nGlyphs].len = 0;
1179 std::sort(first: locaTable, last: locaTable + nGlyphs + 1, comp: cmpTrueTypeLocaIdxFunctor());
1180 pos = 0;
1181 for (i = 0; i <= nGlyphs; ++i) {
1182 locaTable[i].newOffset = pos;
1183
1184 int newPos;
1185 if (unlikely(checkedAdd(pos, locaTable[i].len, &newPos))) {
1186 ok = false;
1187 } else {
1188 pos = newPos;
1189 if (pos & 3) {
1190 pos += 4 - (pos & 3);
1191 }
1192 }
1193 if (locaTable[i].len > 0) {
1194 *maxUsedGlyph = i;
1195 }
1196 }
1197
1198 // construct the new 'loca' table
1199 locaData = (unsigned char *)gmallocn(count: nGlyphs + 1, size: (locaFmt ? 4 : 2));
1200 for (i = 0; i <= nGlyphs; ++i) {
1201 pos = locaTable[i].newOffset;
1202 if (locaFmt) {
1203 locaData[4 * i] = (unsigned char)(pos >> 24);
1204 locaData[4 * i + 1] = (unsigned char)(pos >> 16);
1205 locaData[4 * i + 2] = (unsigned char)(pos >> 8);
1206 locaData[4 * i + 3] = (unsigned char)pos;
1207 } else {
1208 locaData[2 * i] = (unsigned char)(pos >> 9);
1209 locaData[2 * i + 1] = (unsigned char)(pos >> 1);
1210 }
1211 }
1212
1213 // count the number of tables
1214 nNewTables = 0;
1215 for (i = 0; i < nT42Tables; ++i) {
1216 if (t42Tables[i].required || seekTable(tag: t42Tables[i].tag) >= 0) {
1217 ++nNewTables;
1218 }
1219 }
1220 vmtxTab = nullptr; // make gcc happy
1221 vmtxTabLength = 0;
1222 advance = 0; // make gcc happy
1223 if (needVerticalMetrics) {
1224 needVhea = seekTable(tag: "vhea") < 0;
1225 needVmtx = seekTable(tag: "vmtx") < 0;
1226 if (needVhea || needVmtx) {
1227 i = seekTable(tag: "head");
1228 advance = getU16BE(pos: tables[i].offset + 18, ok: &ok); // units per em
1229 if (needVhea) {
1230 ++nNewTables;
1231 }
1232 if (needVmtx) {
1233 ++nNewTables;
1234 }
1235 }
1236 }
1237
1238 // construct the new table headers, including table checksums
1239 // (pad each table out to a multiple of 4 bytes)
1240 pos = 12 + nNewTables * 16;
1241 k = 0;
1242 for (i = 0; i < nT42Tables; ++i) {
1243 length = -1;
1244 checksum = 0; // make gcc happy
1245 if (i == t42HeadTable) {
1246 length = 54;
1247 checksum = computeTableChecksum(data: headData, length: 54);
1248 } else if (i == t42LocaTable) {
1249 length = (nGlyphs + 1) * (locaFmt ? 4 : 2);
1250 checksum = computeTableChecksum(data: locaData, length);
1251 } else if (i == t42GlyfTable) {
1252 length = 0;
1253 checksum = 0;
1254 glyfPos = tables[seekTable(tag: "glyf")].offset;
1255 for (j = 0; j < nGlyphs; ++j) {
1256 length += locaTable[j].len;
1257 if (length & 3) {
1258 length += 4 - (length & 3);
1259 }
1260 if (checkRegion(pos: glyfPos + locaTable[j].origOffset, size: locaTable[j].len)) {
1261 checksum += computeTableChecksum(data: file + glyfPos + locaTable[j].origOffset, length: locaTable[j].len);
1262 }
1263 }
1264 } else {
1265 if ((j = seekTable(tag: t42Tables[i].tag)) >= 0) {
1266 length = tables[j].len;
1267 if (checkRegion(pos: tables[j].offset, size: length)) {
1268 checksum = computeTableChecksum(data: file + tables[j].offset, length);
1269 }
1270 } else if (needVerticalMetrics && i == t42VheaTable) {
1271 vheaTab[10] = advance / 256; // max advance height
1272 vheaTab[11] = advance % 256;
1273 length = sizeof(vheaTab);
1274 checksum = computeTableChecksum(data: vheaTab, length);
1275 } else if (needVerticalMetrics && i == t42VmtxTable) {
1276 length = 4 + (nGlyphs - 1) * 2;
1277 vmtxTabLength = length;
1278 vmtxTab = (unsigned char *)gmalloc(size: length);
1279 vmtxTab[0] = advance / 256;
1280 vmtxTab[1] = advance % 256;
1281 for (j = 2; j < length; j += 2) {
1282 vmtxTab[j] = 0;
1283 vmtxTab[j + 1] = 0;
1284 }
1285 checksum = computeTableChecksum(data: vmtxTab, length);
1286 } else if (t42Tables[i].required) {
1287 //~ error(-1, "Embedded TrueType font is missing a required table ('%s')",
1288 //~ t42Tables[i].tag);
1289 length = 0;
1290 checksum = 0;
1291 }
1292 }
1293 if (length >= 0) {
1294 newTables[k].tag = ((t42Tables[i].tag[0] & 0xff) << 24) | ((t42Tables[i].tag[1] & 0xff) << 16) | ((t42Tables[i].tag[2] & 0xff) << 8) | (t42Tables[i].tag[3] & 0xff);
1295 newTables[k].checksum = checksum;
1296 newTables[k].offset = pos;
1297 newTables[k].len = length;
1298 int newPos;
1299 if (unlikely(checkedAdd(pos, length, &newPos))) {
1300 ok = false;
1301 } else {
1302 pos = newPos;
1303 if (pos & 3) {
1304 pos += 4 - (length & 3);
1305 }
1306 }
1307 ++k;
1308 }
1309 }
1310 if (unlikely(k < nNewTables)) {
1311 error(category: errSyntaxWarning, pos: -1, msg: "unexpected number of tables");
1312 nNewTables = k;
1313 }
1314
1315 // construct the table directory
1316 tableDir[0] = 0x00; // sfnt version
1317 tableDir[1] = 0x01;
1318 tableDir[2] = 0x00;
1319 tableDir[3] = 0x00;
1320 tableDir[4] = 0; // numTables
1321 tableDir[5] = nNewTables;
1322 tableDir[6] = 0; // searchRange
1323 tableDir[7] = (unsigned char)128;
1324 tableDir[8] = 0; // entrySelector
1325 tableDir[9] = 3;
1326 tableDir[10] = 0; // rangeShift
1327 tableDir[11] = (unsigned char)(16 * nNewTables - 128);
1328 pos = 12;
1329 for (i = 0; i < nNewTables; ++i) {
1330 tableDir[pos] = (unsigned char)(newTables[i].tag >> 24);
1331 tableDir[pos + 1] = (unsigned char)(newTables[i].tag >> 16);
1332 tableDir[pos + 2] = (unsigned char)(newTables[i].tag >> 8);
1333 tableDir[pos + 3] = (unsigned char)newTables[i].tag;
1334 tableDir[pos + 4] = (unsigned char)(newTables[i].checksum >> 24);
1335 tableDir[pos + 5] = (unsigned char)(newTables[i].checksum >> 16);
1336 tableDir[pos + 6] = (unsigned char)(newTables[i].checksum >> 8);
1337 tableDir[pos + 7] = (unsigned char)newTables[i].checksum;
1338 tableDir[pos + 8] = (unsigned char)(newTables[i].offset >> 24);
1339 tableDir[pos + 9] = (unsigned char)(newTables[i].offset >> 16);
1340 tableDir[pos + 10] = (unsigned char)(newTables[i].offset >> 8);
1341 tableDir[pos + 11] = (unsigned char)newTables[i].offset;
1342 tableDir[pos + 12] = (unsigned char)(newTables[i].len >> 24);
1343 tableDir[pos + 13] = (unsigned char)(newTables[i].len >> 16);
1344 tableDir[pos + 14] = (unsigned char)(newTables[i].len >> 8);
1345 tableDir[pos + 15] = (unsigned char)newTables[i].len;
1346 pos += 16;
1347 }
1348
1349 // compute the font checksum and store it in the head table
1350 checksum = computeTableChecksum(data: tableDir, length: 12 + nNewTables * 16);
1351 for (i = 0; i < nNewTables; ++i) {
1352 checksum += newTables[i].checksum;
1353 }
1354 checksum = 0xb1b0afba - checksum; // because the TrueType spec says so
1355 headData[8] = (unsigned char)(checksum >> 24);
1356 headData[9] = (unsigned char)(checksum >> 16);
1357 headData[10] = (unsigned char)(checksum >> 8);
1358 headData[11] = (unsigned char)checksum;
1359
1360 // start the sfnts array
1361 if (name) {
1362 (*outputFunc)(outputStream, "/", 1);
1363 (*outputFunc)(outputStream, name->c_str(), name->getLength());
1364 (*outputFunc)(outputStream, " [\n", 3);
1365 } else {
1366 (*outputFunc)(outputStream, "/sfnts [\n", 9);
1367 }
1368
1369 // write the table directory
1370 dumpString(s: tableDir, length: 12 + nNewTables * 16, outputFunc, outputStream);
1371
1372 // write the tables
1373 for (i = 0; i < nNewTables; ++i) {
1374 if (i == t42HeadTable) {
1375 dumpString(s: headData, length: 54, outputFunc, outputStream);
1376 } else if (i == t42LocaTable) {
1377 length = (nGlyphs + 1) * (locaFmt ? 4 : 2);
1378 dumpString(s: locaData, length, outputFunc, outputStream);
1379 } else if (i == t42GlyfTable) {
1380 glyfPos = tables[seekTable(tag: "glyf")].offset;
1381 for (j = 0; j < nGlyphs; ++j) {
1382 if (locaTable[j].len > 0 && checkRegion(pos: glyfPos + locaTable[j].origOffset, size: locaTable[j].len)) {
1383 dumpString(s: file + glyfPos + locaTable[j].origOffset, length: locaTable[j].len, outputFunc, outputStream);
1384 }
1385 }
1386 } else {
1387 // length == 0 means the table is missing and the error was
1388 // already reported during the construction of the table
1389 // headers
1390 if ((length = newTables[i].len) > 0) {
1391 if ((j = seekTable(tag: t42Tables[i].tag)) >= 0 && checkRegion(pos: tables[j].offset, size: tables[j].len)) {
1392 dumpString(s: file + tables[j].offset, length: tables[j].len, outputFunc, outputStream);
1393 } else if (needVerticalMetrics && i == t42VheaTable) {
1394 if (unlikely(length > (int)sizeof(vheaTab))) {
1395 error(category: errSyntaxWarning, pos: -1, msg: "length bigger than vheaTab size");
1396 length = sizeof(vheaTab);
1397 }
1398 dumpString(s: vheaTab, length, outputFunc, outputStream);
1399 } else if (needVerticalMetrics && i == t42VmtxTable) {
1400 if (unlikely(length > vmtxTabLength)) {
1401 error(category: errSyntaxWarning, pos: -1, msg: "length bigger than vmtxTab size");
1402 length = vmtxTabLength;
1403 }
1404 dumpString(s: vmtxTab, length, outputFunc, outputStream);
1405 }
1406 }
1407 }
1408 }
1409
1410 // end the sfnts array
1411 (*outputFunc)(outputStream, "] def\n", 6);
1412
1413 gfree(p: locaData);
1414 gfree(p: locaTable);
1415 if (vmtxTab) {
1416 gfree(p: vmtxTab);
1417 }
1418}
1419
1420void FoFiTrueType::dumpString(const unsigned char *s, int length, FoFiOutputFunc outputFunc, void *outputStream) const
1421{
1422 int pad, i, j;
1423
1424 (*outputFunc)(outputStream, "<", 1);
1425 for (i = 0; i < length; i += 32) {
1426 for (j = 0; j < 32 && i + j < length; ++j) {
1427 const std::unique_ptr<GooString> buf = GooString::format(fmt: "{0:02x}", s[i + j] & 0xff);
1428 (*outputFunc)(outputStream, buf->c_str(), buf->getLength());
1429 }
1430 if (i % (65536 - 32) == 65536 - 64) {
1431 (*outputFunc)(outputStream, ">\n<", 3);
1432 } else if (i + 32 < length) {
1433 (*outputFunc)(outputStream, "\n", 1);
1434 }
1435 }
1436 if (length & 3) {
1437 pad = 4 - (length & 3);
1438 for (i = 0; i < pad; ++i) {
1439 (*outputFunc)(outputStream, "00", 2);
1440 }
1441 }
1442 // add an extra zero byte because the Adobe Type 42 spec says so
1443 (*outputFunc)(outputStream, "00>\n", 4);
1444}
1445
1446unsigned int FoFiTrueType::computeTableChecksum(const unsigned char *data, int length) const
1447{
1448 unsigned int checksum, word;
1449 int i;
1450
1451 checksum = 0;
1452 for (i = 0; i + 3 < length; i += 4) {
1453 word = ((data[i] & 0xff) << 24) + ((data[i + 1] & 0xff) << 16) + ((data[i + 2] & 0xff) << 8) + (data[i + 3] & 0xff);
1454 checksum += word;
1455 }
1456 if (length & 3) {
1457 word = 0;
1458 i = length & ~3;
1459 switch (length & 3) {
1460 case 3:
1461 word |= (data[i + 2] & 0xff) << 8;
1462 // fallthrough
1463 case 2:
1464 word |= (data[i + 1] & 0xff) << 16;
1465 // fallthrough
1466 case 1:
1467 word |= (data[i] & 0xff) << 24;
1468 break;
1469 }
1470 checksum += word;
1471 }
1472 return checksum;
1473}
1474
1475void FoFiTrueType::parse()
1476{
1477 unsigned int topTag;
1478 int pos, ver, i, j;
1479
1480 parsedOk = true;
1481
1482 // look for a collection (TTC)
1483 topTag = getU32BE(pos: 0, ok: &parsedOk);
1484 if (!parsedOk) {
1485 return;
1486 }
1487 if (topTag == ttcfTag) {
1488 /* TTC font */
1489 int dircount;
1490
1491 dircount = getU32BE(pos: 8, ok: &parsedOk);
1492 if (!parsedOk) {
1493 return;
1494 }
1495 if (!dircount) {
1496 parsedOk = false;
1497 return;
1498 }
1499
1500 if (faceIndex >= dircount) {
1501 faceIndex = 0;
1502 }
1503 pos = getU32BE(pos: 12 + faceIndex * 4, ok: &parsedOk);
1504 if (!parsedOk) {
1505 return;
1506 }
1507 } else {
1508 pos = 0;
1509 }
1510
1511 // check the sfnt version
1512 ver = getU32BE(pos, ok: &parsedOk);
1513 if (!parsedOk) {
1514 return;
1515 }
1516 openTypeCFF = ver == 0x4f54544f; // 'OTTO'
1517
1518 // read the table directory
1519 nTables = getU16BE(pos: pos + 4, ok: &parsedOk);
1520 if (!parsedOk) {
1521 return;
1522 }
1523 tables = (TrueTypeTable *)gmallocn(count: nTables, size: sizeof(TrueTypeTable));
1524 pos += 12;
1525 j = 0;
1526 for (i = 0; i < nTables; ++i) {
1527 tables[j].tag = getU32BE(pos, ok: &parsedOk);
1528 tables[j].checksum = getU32BE(pos: pos + 4, ok: &parsedOk);
1529 tables[j].offset = (int)getU32BE(pos: pos + 8, ok: &parsedOk);
1530 tables[j].len = (int)getU32BE(pos: pos + 12, ok: &parsedOk);
1531 if (unlikely((tables[j].offset < 0) || (tables[j].len < 0) || (tables[j].offset < INT_MAX - tables[j].len) || (tables[j].len > INT_MAX - tables[j].offset)
1532 || (tables[j].offset + tables[j].len >= tables[j].offset && tables[j].offset + tables[j].len <= len))) {
1533 // ignore any bogus entries in the table directory
1534 ++j;
1535 }
1536 pos += 16;
1537 }
1538 if (nTables != j) {
1539 nTables = j;
1540 tables = (TrueTypeTable *)greallocn_checkoverflow(p: tables, count: nTables, size: sizeof(TrueTypeTable));
1541 }
1542 if (!parsedOk || tables == nullptr) {
1543 parsedOk = false;
1544 return;
1545 }
1546
1547 // check for tables that are required by both the TrueType spec and
1548 // the Type 42 spec
1549 if (seekTable(tag: "head") < 0 || seekTable(tag: "hhea") < 0 || seekTable(tag: "maxp") < 0 || (!openTypeCFF && seekTable(tag: "loca") < 0) || (!openTypeCFF && seekTable(tag: "glyf") < 0) || (openTypeCFF && (seekTable(tag: "CFF ") < 0 && seekTable(tag: "CFF2") < 0))) {
1550 parsedOk = false;
1551 return;
1552 }
1553
1554 // read the cmaps
1555 if ((i = seekTable(tag: "cmap")) >= 0) {
1556 pos = tables[i].offset + 2;
1557 nCmaps = getU16BE(pos, ok: &parsedOk);
1558 pos += 2;
1559 if (!parsedOk) {
1560 return;
1561 }
1562 cmaps = (TrueTypeCmap *)gmallocn(count: nCmaps, size: sizeof(TrueTypeCmap));
1563 for (j = 0; j < nCmaps; ++j) {
1564 cmaps[j].platform = getU16BE(pos, ok: &parsedOk);
1565 cmaps[j].encoding = getU16BE(pos: pos + 2, ok: &parsedOk);
1566 cmaps[j].offset = tables[i].offset + getU32BE(pos: pos + 4, ok: &parsedOk);
1567 pos += 8;
1568 cmaps[j].fmt = getU16BE(pos: cmaps[j].offset, ok: &parsedOk);
1569 cmaps[j].len = getU16BE(pos: cmaps[j].offset + 2, ok: &parsedOk);
1570 }
1571 if (!parsedOk) {
1572 return;
1573 }
1574 } else {
1575 nCmaps = 0;
1576 }
1577
1578 // get the number of glyphs from the maxp table
1579 i = seekTable(tag: "maxp");
1580 nGlyphs = getU16BE(pos: tables[i].offset + 4, ok: &parsedOk);
1581 if (!parsedOk) {
1582 return;
1583 }
1584
1585 // get the bbox and loca table format from the head table
1586 i = seekTable(tag: "head");
1587 bbox[0] = getS16BE(pos: tables[i].offset + 36, ok: &parsedOk);
1588 bbox[1] = getS16BE(pos: tables[i].offset + 38, ok: &parsedOk);
1589 bbox[2] = getS16BE(pos: tables[i].offset + 40, ok: &parsedOk);
1590 bbox[3] = getS16BE(pos: tables[i].offset + 42, ok: &parsedOk);
1591 locaFmt = getS16BE(pos: tables[i].offset + 50, ok: &parsedOk);
1592 if (!parsedOk) {
1593 return;
1594 }
1595
1596 // read the post table
1597 readPostTable();
1598}
1599
1600void FoFiTrueType::readPostTable()
1601{
1602 std::string name;
1603 int tablePos, postFmt, stringIdx, stringPos;
1604 bool ok;
1605 int i, j, n, m;
1606
1607 ok = true;
1608 if ((i = seekTable(tag: "post")) < 0) {
1609 return;
1610 }
1611 tablePos = tables[i].offset;
1612 postFmt = getU32BE(pos: tablePos, ok: &ok);
1613 if (!ok) {
1614 goto err;
1615 }
1616 if (postFmt == 0x00010000) {
1617 nameToGID.reserve(n: 258);
1618 for (i = 0; i < 258; ++i) {
1619 nameToGID.emplace(args&: macGlyphNames[i], args&: i);
1620 }
1621 } else if (postFmt == 0x00020000) {
1622 nameToGID.reserve(n: 258);
1623 n = getU16BE(pos: tablePos + 32, ok: &ok);
1624 if (!ok) {
1625 goto err;
1626 }
1627 if (n > nGlyphs) {
1628 n = nGlyphs;
1629 }
1630 stringIdx = 0;
1631 stringPos = tablePos + 34 + 2 * n;
1632 for (i = 0; i < n; ++i) {
1633 ok = true;
1634 j = getU16BE(pos: tablePos + 34 + 2 * i, ok: &ok);
1635 if (j < 258) {
1636 nameToGID[macGlyphNames[j]] = i;
1637 } else {
1638 j -= 258;
1639 if (j != stringIdx) {
1640 for (stringIdx = 0, stringPos = tablePos + 34 + 2 * n; stringIdx < j; ++stringIdx, stringPos += 1 + getU8(pos: stringPos, ok: &ok)) {
1641 ;
1642 }
1643 if (!ok) {
1644 continue;
1645 }
1646 }
1647 m = getU8(pos: stringPos, ok: &ok);
1648 if (!ok || !checkRegion(pos: stringPos + 1, size: m)) {
1649 continue;
1650 }
1651 name.assign(s: (char *)&file[stringPos + 1], n: m);
1652 nameToGID[name] = i;
1653 ++stringIdx;
1654 stringPos += 1 + m;
1655 }
1656 }
1657 } else if (postFmt == 0x00028000) {
1658 nameToGID.reserve(n: 258);
1659 for (i = 0; i < nGlyphs; ++i) {
1660 j = getU8(pos: tablePos + 32 + i, ok: &ok);
1661 if (!ok) {
1662 continue;
1663 }
1664 if (j < 258) {
1665 nameToGID[macGlyphNames[j]] = i;
1666 }
1667 }
1668 }
1669
1670 return;
1671
1672err:
1673 nameToGID.clear();
1674}
1675
1676int FoFiTrueType::seekTable(const char *tag) const
1677{
1678 unsigned int tagI;
1679 int i;
1680
1681 tagI = ((tag[0] & 0xff) << 24) | ((tag[1] & 0xff) << 16) | ((tag[2] & 0xff) << 8) | (tag[3] & 0xff);
1682 for (i = 0; i < nTables; ++i) {
1683 if (tables[i].tag == tagI) {
1684 return i;
1685 }
1686 }
1687 return -1;
1688}
1689
1690unsigned int FoFiTrueType::charToTag(const char *tagName)
1691{
1692 int n = strlen(s: tagName);
1693 unsigned int tag = 0;
1694 int i;
1695
1696 if (n > 4) {
1697 n = 4;
1698 }
1699 for (i = 0; i < n; i++) {
1700 tag <<= 8;
1701 tag |= tagName[i] & 0xff;
1702 }
1703 for (; i < 4; i++) {
1704 tag <<= 8;
1705 tag |= ' ';
1706 }
1707 return tag;
1708}
1709
1710/*
1711 setup GSUB table data
1712 Only supporting vertical text substitution.
1713*/
1714int FoFiTrueType::setupGSUB(const char *scriptName)
1715{
1716 return setupGSUB(scriptName, languageName: nullptr);
1717}
1718
1719/*
1720 setup GSUB table data
1721 Only supporting vertical text substitution.
1722*/
1723int FoFiTrueType::setupGSUB(const char *scriptName, const char *languageName)
1724{
1725 unsigned int gsubTable;
1726 unsigned int i;
1727 unsigned int scriptList, featureList;
1728 unsigned int scriptCount;
1729 unsigned int tag;
1730 unsigned int scriptTable = 0;
1731 unsigned int langSys;
1732 unsigned int featureCount;
1733 unsigned int featureIndex;
1734 unsigned int ftable = 0;
1735 unsigned int llist;
1736 unsigned int scriptTag;
1737 int x;
1738 unsigned int pos;
1739
1740 if (scriptName == nullptr) {
1741 gsubFeatureTable = 0;
1742 return 0;
1743 }
1744 scriptTag = charToTag(tagName: scriptName);
1745 /* read GSUB Header */
1746 if ((x = seekTable(tag: "GSUB")) < 0) {
1747 return 0; /* GSUB table not found */
1748 }
1749 gsubTable = tables[x].offset;
1750 pos = gsubTable + 4;
1751 scriptList = getU16BE(pos, ok: &parsedOk);
1752 pos += 2;
1753 featureList = getU16BE(pos, ok: &parsedOk);
1754 pos += 2;
1755 llist = getU16BE(pos, ok: &parsedOk);
1756
1757 gsubLookupList = llist + gsubTable; /* change to offset from top of file */
1758 /* read script list table */
1759 pos = gsubTable + scriptList;
1760 scriptCount = getU16BE(pos, ok: &parsedOk);
1761 pos += 2;
1762 /* find script */
1763 for (i = 0; i < scriptCount; i++) {
1764 tag = getU32BE(pos, ok: &parsedOk);
1765 pos += 4;
1766 scriptTable = getU16BE(pos, ok: &parsedOk);
1767 pos += 2;
1768 if (tag == scriptTag) {
1769 /* found */
1770 break;
1771 }
1772 }
1773 if (i >= scriptCount) {
1774 /* not found */
1775 return 0;
1776 }
1777
1778 /* read script table */
1779 /* use default language system */
1780 pos = gsubTable + scriptList + scriptTable;
1781 langSys = 0;
1782 if (languageName) {
1783 unsigned int langTag = charToTag(tagName: languageName);
1784 unsigned int langCount = getU16BE(pos: pos + 2, ok: &parsedOk);
1785 for (i = 0; i < langCount && langSys == 0; i++) {
1786 tag = getU32BE(pos: pos + 4 + i * (4 + 2), ok: &parsedOk);
1787 if (tag == langTag) {
1788 langSys = getU16BE(pos: pos + 4 + i * (4 + 2) + 4, ok: &parsedOk);
1789 }
1790 }
1791 }
1792 if (langSys == 0) {
1793 /* default language system */
1794 langSys = getU16BE(pos, ok: &parsedOk);
1795 }
1796
1797 /* read LangSys table */
1798 if (langSys == 0) {
1799 /* no default LangSys */
1800 return 0;
1801 }
1802
1803 pos = gsubTable + scriptList + scriptTable + langSys + 2;
1804 featureIndex = getU16BE(pos, ok: &parsedOk); /* ReqFeatureIndex */
1805 pos += 2;
1806
1807 if (featureIndex != 0xffff) {
1808 unsigned int tpos;
1809 /* read feature record */
1810 tpos = gsubTable + featureList;
1811 featureCount = getU16BE(pos: tpos, ok: &parsedOk);
1812 tpos = gsubTable + featureList + 2 + featureIndex * (4 + 2);
1813 tag = getU32BE(pos: tpos, ok: &parsedOk);
1814 tpos += 4;
1815 if (tag == vrt2Tag) {
1816 /* vrt2 is preferred, overwrite vert */
1817 ftable = getU16BE(pos: tpos, ok: &parsedOk);
1818 /* convert to offset from file top */
1819 gsubFeatureTable = ftable + gsubTable + featureList;
1820 return 0;
1821 } else if (tag == vertTag) {
1822 ftable = getU16BE(pos: tpos, ok: &parsedOk);
1823 }
1824 }
1825 featureCount = getU16BE(pos, ok: &parsedOk);
1826 pos += 2;
1827 /* find 'vrt2' or 'vert' feature */
1828 for (i = 0; i < featureCount; i++) {
1829 unsigned int oldPos;
1830
1831 featureIndex = getU16BE(pos, ok: &parsedOk);
1832 pos += 2;
1833 oldPos = pos; /* save position */
1834 /* read feature record */
1835 pos = gsubTable + featureList + 2 + featureIndex * (4 + 2);
1836 tag = getU32BE(pos, ok: &parsedOk);
1837 pos += 4;
1838 if (tag == vrt2Tag) {
1839 /* vrt2 is preferred, overwrite vert */
1840 ftable = getU16BE(pos, ok: &parsedOk);
1841 break;
1842 } else if (ftable == 0 && tag == vertTag) {
1843 ftable = getU16BE(pos, ok: &parsedOk);
1844 }
1845 pos = oldPos; /* restore old position */
1846 }
1847 if (ftable == 0) {
1848 /* vert nor vrt2 are not found */
1849 return 0;
1850 }
1851 /* convert to offset from file top */
1852 gsubFeatureTable = ftable + gsubTable + featureList;
1853 return 0;
1854}
1855
1856unsigned int FoFiTrueType::doMapToVertGID(unsigned int orgGID)
1857{
1858 unsigned int lookupCount;
1859 unsigned int lookupListIndex;
1860 unsigned int i;
1861 unsigned int gid = 0;
1862 unsigned int pos;
1863
1864 pos = gsubFeatureTable + 2;
1865 lookupCount = getU16BE(pos, ok: &parsedOk);
1866 pos += 2;
1867 for (i = 0; i < lookupCount; i++) {
1868 lookupListIndex = getU16BE(pos, ok: &parsedOk);
1869 pos += 2;
1870 if ((gid = scanLookupList(listIndex: lookupListIndex, orgGID)) != 0) {
1871 break;
1872 }
1873 }
1874 return gid;
1875}
1876
1877unsigned int FoFiTrueType::mapToVertGID(unsigned int orgGID)
1878{
1879 unsigned int mapped;
1880
1881 if (gsubFeatureTable == 0) {
1882 return orgGID;
1883 }
1884 if ((mapped = doMapToVertGID(orgGID)) != 0) {
1885 return mapped;
1886 }
1887 return orgGID;
1888}
1889
1890unsigned int FoFiTrueType::scanLookupList(unsigned int listIndex, unsigned int orgGID)
1891{
1892 unsigned int lookupTable;
1893 unsigned int subTableCount;
1894 unsigned int subTable;
1895 unsigned int i;
1896 unsigned int gid = 0;
1897 unsigned int pos;
1898
1899 if (gsubLookupList == 0) {
1900 return 0; /* no lookup list */
1901 }
1902 pos = gsubLookupList + 2 + listIndex * 2;
1903 lookupTable = getU16BE(pos, ok: &parsedOk);
1904 /* read lookup table */
1905 pos = gsubLookupList + lookupTable + 4;
1906 subTableCount = getU16BE(pos, ok: &parsedOk);
1907 pos += 2;
1908 ;
1909 for (i = 0; i < subTableCount; i++) {
1910 subTable = getU16BE(pos, ok: &parsedOk);
1911 pos += 2;
1912 if ((gid = scanLookupSubTable(subTable: gsubLookupList + lookupTable + subTable, orgGID)) != 0) {
1913 break;
1914 }
1915 }
1916 return gid;
1917}
1918
1919unsigned int FoFiTrueType::scanLookupSubTable(unsigned int subTable, unsigned int orgGID)
1920{
1921 unsigned int format;
1922 unsigned int coverage;
1923 int delta;
1924 int glyphCount;
1925 unsigned int substitute;
1926 unsigned int gid = 0;
1927 int coverageIndex;
1928 int pos;
1929
1930 pos = subTable;
1931 format = getU16BE(pos, ok: &parsedOk);
1932 pos += 2;
1933 coverage = getU16BE(pos, ok: &parsedOk);
1934 pos += 2;
1935 if ((coverageIndex = checkGIDInCoverage(coverage: subTable + coverage, orgGID)) >= 0) {
1936 switch (format) {
1937 case 1:
1938 /* format 1 */
1939 delta = getS16BE(pos, ok: &parsedOk);
1940 pos += 2;
1941 gid = orgGID + delta;
1942 break;
1943 case 2:
1944 /* format 2 */
1945 glyphCount = getS16BE(pos, ok: &parsedOk);
1946 pos += 2;
1947 if (glyphCount > coverageIndex) {
1948 pos += coverageIndex * 2;
1949 substitute = getU16BE(pos, ok: &parsedOk);
1950 gid = substitute;
1951 }
1952 break;
1953 default:
1954 /* unknown format */
1955 break;
1956 }
1957 }
1958 return gid;
1959}
1960
1961int FoFiTrueType::checkGIDInCoverage(unsigned int coverage, unsigned int orgGID)
1962{
1963 int index = -1;
1964 unsigned int format;
1965 unsigned int count;
1966 unsigned int i;
1967 unsigned int pos;
1968
1969 pos = coverage;
1970 format = getU16BE(pos, ok: &parsedOk);
1971 pos += 2;
1972 switch (format) {
1973 case 1:
1974 count = getU16BE(pos, ok: &parsedOk);
1975 pos += 2;
1976 // In some poor CJK fonts, key GIDs are not sorted,
1977 // thus we cannot finish checking even when the range
1978 // including orgGID seems to have already passed.
1979 for (i = 0; i < count; i++) {
1980 unsigned int gid;
1981
1982 gid = getU16BE(pos, ok: &parsedOk);
1983 pos += 2;
1984 if (gid == orgGID) {
1985 /* found */
1986 index = i;
1987 break;
1988 }
1989 }
1990 break;
1991 case 2:
1992 count = getU16BE(pos, ok: &parsedOk);
1993 pos += 2;
1994 for (i = 0; i < count; i++) {
1995 unsigned int startGID, endGID;
1996 unsigned int startIndex;
1997
1998 startGID = getU16BE(pos, ok: &parsedOk);
1999 pos += 2;
2000 endGID = getU16BE(pos, ok: &parsedOk);
2001 pos += 2;
2002 startIndex = getU16BE(pos, ok: &parsedOk);
2003 pos += 2;
2004 // In some poor CJK fonts, key GIDs are not sorted,
2005 // thus we cannot finish checking even when the range
2006 // including orgGID seems to have already passed.
2007 if (startGID <= orgGID && orgGID <= endGID) {
2008 /* found */
2009 index = startIndex + orgGID - startGID;
2010 break;
2011 }
2012 }
2013 break;
2014 default:
2015 break;
2016 }
2017 return index;
2018}
2019

source code of poppler/fofi/FoFiTrueType.cc