pdf-codec 5.7.3 → 5.7.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/README.md +6 -3
  2. package/dist/afm-widths.cjs +247 -4
  3. package/dist/afm-widths.js +244 -1
  4. package/dist/builtin-encoding.cjs +75 -16
  5. package/dist/builtin-encoding.d.cts +10 -3
  6. package/dist/builtin-encoding.d.ts +10 -3
  7. package/dist/builtin-encoding.js +74 -15
  8. package/dist/content-write.cjs +2 -2
  9. package/dist/content-write.js +1 -1
  10. package/dist/core-font-glyph-orders.cjs +62 -0
  11. package/dist/core-font-glyph-orders.d.cts +10 -0
  12. package/dist/core-font-glyph-orders.d.ts +10 -0
  13. package/dist/core-font-glyph-orders.js +61 -0
  14. package/dist/encoding.cjs +273 -5
  15. package/dist/encoding.d.cts +1 -2
  16. package/dist/encoding.d.ts +1 -2
  17. package/dist/encoding.js +271 -2
  18. package/dist/font-read.cjs +52 -18
  19. package/dist/font-read.js +49 -15
  20. package/dist/font-style.cjs +12 -1
  21. package/dist/font-style.d.cts +9 -1
  22. package/dist/font-style.d.ts +9 -1
  23. package/dist/font-style.js +12 -2
  24. package/dist/glyph-data/adobe-glyph-list.cjs +7 -0
  25. package/dist/glyph-data/adobe-glyph-list.d.cts +5 -0
  26. package/dist/glyph-data/adobe-glyph-list.d.ts +5 -0
  27. package/dist/glyph-data/adobe-glyph-list.js +5 -0
  28. package/dist/glyph-data/core-font-glyph-orders.cjs +5 -0
  29. package/dist/glyph-data/core-font-glyph-orders.d.cts +4 -0
  30. package/dist/glyph-data/core-font-glyph-orders.d.ts +4 -0
  31. package/dist/glyph-data/core-font-glyph-orders.js +4 -0
  32. package/dist/glyph-names.cjs +63 -0
  33. package/dist/glyph-names.d.cts +9 -0
  34. package/dist/glyph-names.d.ts +9 -0
  35. package/dist/glyph-names.js +62 -0
  36. package/dist/index.cjs +1 -1
  37. package/dist/index.js +1 -1
  38. package/dist/measure.cjs +3 -2
  39. package/dist/measure.js +2 -1
  40. package/dist/winansi.cjs +162 -4
  41. package/dist/winansi.d.cts +1 -2
  42. package/dist/winansi.d.ts +1 -2
  43. package/dist/winansi.js +161 -2
  44. package/dist/write.cjs +1 -1
  45. package/dist/write.js +1 -1
  46. package/package.json +1 -1
  47. package/dist/afm-widths-BNI8qa2S.js +0 -710
  48. package/dist/afm-widths-sjaRvmQX.cjs +0 -769
  49. package/dist/encoding-glyph-unicode.cjs +0 -353
  50. package/dist/encoding-glyph-unicode.d.cts +0 -4
  51. package/dist/encoding-glyph-unicode.d.ts +0 -4
  52. package/dist/encoding-glyph-unicode.js +0 -352
package/dist/encoding.js CHANGED
@@ -1,2 +1,271 @@
1
- import { a as glyphNameToUnicode, i as WINANSI_GLYPH_NAMES, o as namedEncodingGlyphName, s as winAnsiGlyphName } from "./afm-widths-BNI8qa2S.js";
2
- export { WINANSI_GLYPH_NAMES, glyphNameToUnicode, namedEncodingGlyphName, winAnsiGlyphName };
1
+ import { macRomanGlyphName, standardGlyphName } from "./encoding-standard-tables.js";
2
+ //#region src/encoding.ts
3
+ const WINANSI_GLYPH_NAMES = [
4
+ "",
5
+ "",
6
+ "",
7
+ "",
8
+ "",
9
+ "",
10
+ "",
11
+ "",
12
+ "",
13
+ "",
14
+ "",
15
+ "",
16
+ "",
17
+ "",
18
+ "",
19
+ "",
20
+ "",
21
+ "",
22
+ "",
23
+ "",
24
+ "",
25
+ "",
26
+ "",
27
+ "",
28
+ "",
29
+ "",
30
+ "",
31
+ "",
32
+ "",
33
+ "",
34
+ "",
35
+ "",
36
+ "space",
37
+ "exclam",
38
+ "quotedbl",
39
+ "numbersign",
40
+ "dollar",
41
+ "percent",
42
+ "ampersand",
43
+ "quotesingle",
44
+ "parenleft",
45
+ "parenright",
46
+ "asterisk",
47
+ "plus",
48
+ "comma",
49
+ "hyphen",
50
+ "period",
51
+ "slash",
52
+ "zero",
53
+ "one",
54
+ "two",
55
+ "three",
56
+ "four",
57
+ "five",
58
+ "six",
59
+ "seven",
60
+ "eight",
61
+ "nine",
62
+ "colon",
63
+ "semicolon",
64
+ "less",
65
+ "equal",
66
+ "greater",
67
+ "question",
68
+ "at",
69
+ "A",
70
+ "B",
71
+ "C",
72
+ "D",
73
+ "E",
74
+ "F",
75
+ "G",
76
+ "H",
77
+ "I",
78
+ "J",
79
+ "K",
80
+ "L",
81
+ "M",
82
+ "N",
83
+ "O",
84
+ "P",
85
+ "Q",
86
+ "R",
87
+ "S",
88
+ "T",
89
+ "U",
90
+ "V",
91
+ "W",
92
+ "X",
93
+ "Y",
94
+ "Z",
95
+ "bracketleft",
96
+ "backslash",
97
+ "bracketright",
98
+ "asciicircum",
99
+ "underscore",
100
+ "grave",
101
+ "a",
102
+ "b",
103
+ "c",
104
+ "d",
105
+ "e",
106
+ "f",
107
+ "g",
108
+ "h",
109
+ "i",
110
+ "j",
111
+ "k",
112
+ "l",
113
+ "m",
114
+ "n",
115
+ "o",
116
+ "p",
117
+ "q",
118
+ "r",
119
+ "s",
120
+ "t",
121
+ "u",
122
+ "v",
123
+ "w",
124
+ "x",
125
+ "y",
126
+ "z",
127
+ "braceleft",
128
+ "bar",
129
+ "braceright",
130
+ "asciitilde",
131
+ "bullet",
132
+ "Euro",
133
+ "bullet",
134
+ "quotesinglbase",
135
+ "florin",
136
+ "quotedblbase",
137
+ "ellipsis",
138
+ "dagger",
139
+ "daggerdbl",
140
+ "circumflex",
141
+ "perthousand",
142
+ "Scaron",
143
+ "guilsinglleft",
144
+ "OE",
145
+ "bullet",
146
+ "Zcaron",
147
+ "bullet",
148
+ "bullet",
149
+ "quoteleft",
150
+ "quoteright",
151
+ "quotedblleft",
152
+ "quotedblright",
153
+ "bullet",
154
+ "endash",
155
+ "emdash",
156
+ "tilde",
157
+ "trademark",
158
+ "scaron",
159
+ "guilsinglright",
160
+ "oe",
161
+ "bullet",
162
+ "zcaron",
163
+ "Ydieresis",
164
+ "space",
165
+ "exclamdown",
166
+ "cent",
167
+ "sterling",
168
+ "currency",
169
+ "yen",
170
+ "brokenbar",
171
+ "section",
172
+ "dieresis",
173
+ "copyright",
174
+ "ordfeminine",
175
+ "guillemotleft",
176
+ "logicalnot",
177
+ "hyphen",
178
+ "registered",
179
+ "macron",
180
+ "degree",
181
+ "plusminus",
182
+ "twosuperior",
183
+ "threesuperior",
184
+ "acute",
185
+ "mu",
186
+ "paragraph",
187
+ "periodcentered",
188
+ "cedilla",
189
+ "onesuperior",
190
+ "ordmasculine",
191
+ "guillemotright",
192
+ "onequarter",
193
+ "onehalf",
194
+ "threequarters",
195
+ "questiondown",
196
+ "Agrave",
197
+ "Aacute",
198
+ "Acircumflex",
199
+ "Atilde",
200
+ "Adieresis",
201
+ "Aring",
202
+ "AE",
203
+ "Ccedilla",
204
+ "Egrave",
205
+ "Eacute",
206
+ "Ecircumflex",
207
+ "Edieresis",
208
+ "Igrave",
209
+ "Iacute",
210
+ "Icircumflex",
211
+ "Idieresis",
212
+ "Eth",
213
+ "Ntilde",
214
+ "Ograve",
215
+ "Oacute",
216
+ "Ocircumflex",
217
+ "Otilde",
218
+ "Odieresis",
219
+ "multiply",
220
+ "Oslash",
221
+ "Ugrave",
222
+ "Uacute",
223
+ "Ucircumflex",
224
+ "Udieresis",
225
+ "Yacute",
226
+ "Thorn",
227
+ "germandbls",
228
+ "agrave",
229
+ "aacute",
230
+ "acircumflex",
231
+ "atilde",
232
+ "adieresis",
233
+ "aring",
234
+ "ae",
235
+ "ccedilla",
236
+ "egrave",
237
+ "eacute",
238
+ "ecircumflex",
239
+ "edieresis",
240
+ "igrave",
241
+ "iacute",
242
+ "icircumflex",
243
+ "idieresis",
244
+ "eth",
245
+ "ntilde",
246
+ "ograve",
247
+ "oacute",
248
+ "ocircumflex",
249
+ "otilde",
250
+ "odieresis",
251
+ "divide",
252
+ "oslash",
253
+ "ugrave",
254
+ "uacute",
255
+ "ucircumflex",
256
+ "udieresis",
257
+ "yacute",
258
+ "thorn",
259
+ "ydieresis"
260
+ ];
261
+ function winAnsiGlyphName(code) {
262
+ const name = WINANSI_GLYPH_NAMES[code];
263
+ return name === void 0 || name === "" ? void 0 : name;
264
+ }
265
+ function namedEncodingGlyphName(encodingName) {
266
+ if (encodingName === "WinAnsiEncoding") return winAnsiGlyphName;
267
+ if (encodingName === "MacRomanEncoding") return macRomanGlyphName;
268
+ if (encodingName === "StandardEncoding") return standardGlyphName;
269
+ }
270
+ //#endregion
271
+ export { WINANSI_GLYPH_NAMES, namedEncodingGlyphName, winAnsiGlyphName };
@@ -1,12 +1,14 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_afm_widths = require("./afm-widths-sjaRvmQX.cjs");
2
+ const require_encoding = require("./encoding.cjs");
3
+ const require_afm_widths = require("./afm-widths.cjs");
3
4
  const require_objects = require("./objects.cjs");
4
5
  const require_filters = require("./filters.cjs");
6
+ const require_font_style = require("./font-style.cjs");
7
+ const require_glyph_names = require("./glyph-names.cjs");
5
8
  const require_builtin_encoding = require("./builtin-encoding.cjs");
6
9
  const require_cmap = require("./cmap.cjs");
7
10
  const require_encoding_symbol_tables = require("./encoding-symbol-tables.cjs");
8
11
  const require_fonts = require("./fonts.cjs");
9
- const require_font_style = require("./font-style.cjs");
10
12
  //#region src/font-read.ts
11
13
  const BITS_PER_BYTE = 8;
12
14
  const SYMBOLIC_FLAG_BIT = 4;
@@ -26,7 +28,7 @@ function builtinSymbolGlyphNameLookup(baseFamily) {
26
28
  if (baseFamily === "Symbol") return require_encoding_symbol_tables.symbolGlyphName;
27
29
  if (baseFamily === "ZapfDingbats") return require_encoding_symbol_tables.zapfDingbatsGlyphName;
28
30
  }
29
- function readFontProgram(descriptor, context) {
31
+ function readFontProgram(descriptor, baseFont, context) {
30
32
  if (descriptor === void 0) return;
31
33
  for (const key of [
32
34
  "FontFile2",
@@ -36,14 +38,14 @@ function readFontProgram(descriptor, context) {
36
38
  const stream = context.resolver.resolve(require_objects.dictGet(descriptor, key));
37
39
  if (stream?.kind !== "stream") continue;
38
40
  const decoded = require_filters.decodeStream(stream.raw, stream.dict, context.sink);
39
- const encoding = require_builtin_encoding.readFontProgramEncoding(decoded.bytes);
41
+ const encoding = require_builtin_encoding.readFontProgramEncoding(decoded.bytes, baseFont);
40
42
  if (encoding !== void 0) return encoding;
41
43
  }
42
44
  }
43
- function lazyFontProgram(descriptor, context) {
45
+ function lazyFontProgram(descriptor, baseFont, context) {
44
46
  let read;
45
47
  return () => {
46
- read ??= { encoding: readFontProgram(descriptor, context) };
48
+ read ??= { encoding: readFontProgram(descriptor, baseFont, context) };
47
49
  return read.encoding;
48
50
  };
49
51
  }
@@ -113,31 +115,40 @@ function buildSimpleFont(fontDict, context) {
113
115
  const encodingObj = require_objects.dictGet(fontDict, "Encoding");
114
116
  const encodingDict = context.resolver.resolveDict(encodingObj);
115
117
  const baseEncodingName = require_objects.asName(encodingDict !== void 0 ? require_objects.dictGet(encodingDict, "BaseEncoding") : encodingObj);
116
- const namedBaseGlyphName = baseEncodingName !== void 0 ? require_afm_widths.namedEncodingGlyphName(baseEncodingName) : void 0;
118
+ const namedBaseGlyphName = baseEncodingName !== void 0 ? require_encoding.namedEncodingGlyphName(baseEncodingName) : void 0;
117
119
  if (baseEncodingName !== void 0 && namedBaseGlyphName === void 0) context.sink({
118
120
  code: "char/encoding-approximated",
119
121
  severity: "info",
120
122
  message: `base encoding "${baseEncodingName}" has no dedicated table here and is approximated as WinAnsiEncoding`
121
123
  });
122
124
  const differencesMap = readDifferencesMap(encodingDict !== void 0 ? resolvedArray(require_objects.dictGet(encodingDict, "Differences"), context) : void 0);
123
- const programEncoding = lazyFontProgram(descriptor, context);
125
+ const programEncoding = lazyFontProgram(descriptor, baseFont, context);
126
+ const unicodeForDifferencesName = (name) => {
127
+ const named = require_glyph_names.glyphNameToUnicode(name);
128
+ if (named !== void 0) return named;
129
+ const program = programEncoding();
130
+ const glyphId = program?.glyphIdOfName(name);
131
+ return glyphId === void 0 ? void 0 : program?.glyphIdToUnicode(glyphId);
132
+ };
124
133
  const symbolEncoded = symbolic || builtinGlyphName !== void 0;
125
134
  const byGlyphName = (source) => (code) => {
126
135
  const name = source(code);
127
- return name === void 0 ? void 0 : require_afm_widths.glyphNameToUnicode(name);
136
+ return name === void 0 ? void 0 : require_glyph_names.glyphNameToUnicode(name);
128
137
  };
129
138
  const fromProgram = (code) => programEncoding()?.codeToUnicode(code);
130
139
  const namedBase = namedBaseGlyphName === void 0 ? void 0 : byGlyphName(namedBaseGlyphName);
131
- const resolvers = [byGlyphName((code) => differencesMap.get(code)), ...symbolEncoded ? [
140
+ const resolvers = (symbolEncoded ? [
132
141
  fromProgram,
133
142
  builtinGlyphName === void 0 ? void 0 : byGlyphName(builtinGlyphName),
134
143
  namedBase
135
144
  ] : [
136
145
  namedBase,
137
146
  fromProgram,
138
- byGlyphName(require_afm_widths.winAnsiGlyphName)
139
- ]].filter((resolver) => resolver !== void 0);
147
+ byGlyphName(require_encoding.winAnsiGlyphName)
148
+ ]).filter((resolver) => resolver !== void 0);
140
149
  const unicodeForCode = (code) => {
150
+ const differencesName = differencesMap.get(code);
151
+ if (differencesName !== void 0) return unicodeForDifferencesName(differencesName);
141
152
  for (const resolve of resolvers) {
142
153
  const unicode = resolve(code);
143
154
  if (unicode !== void 0) return unicode;
@@ -154,7 +165,7 @@ function buildSimpleFont(fontDict, context) {
154
165
  }
155
166
  const unicode = unicodeForCode(code);
156
167
  if (unicode !== void 0) {
157
- out += String.fromCodePoint(unicode);
168
+ out += unicode;
158
169
  continue;
159
170
  }
160
171
  unmapped++;
@@ -265,6 +276,29 @@ function readsVertically(fontDict, context) {
265
276
  if (encoding?.kind === "stream") return require_objects.asNumber(require_objects.dictGet(encoding.dict, "WMode")) === VERTICAL_WRITING_MODE;
266
277
  return false;
267
278
  }
279
+ const CID_TO_GID_ENTRY_SIZE = 2;
280
+ /**
281
+ * How a composite font's codes reach the embedded program's glyphs, so the program itself can say what a glyph is when the font dictionary's /ToUnicode CMap is absent or incomplete: through the glyph's own name, its program's Unicode mapping read backwards, or the glyph order of the core face the program is.
282
+ *
283
+ * With /Identity-H or /Identity-V a code is its CID. A /CIDToGIDMap that is absent or /Identity then makes the CID the glyph index, and a /CIDToGIDMap stream gives each CID its glyph index explicitly (ISO 32000-1 9.7.4.2). Any other /Encoding is a CMap from codes to CIDs this reader does not apply, and then the program is not consulted at all rather than being read against the wrong glyph.
284
+ * @param fontDict - the Type0 font dictionary
285
+ * @param descendantDict - its descendant CIDFont dictionary, if it has a readable one
286
+ * @param context - the font read whose resolver follows references and whose sink receives stream-decoding diagnostics
287
+ * @returns a lookup from CID to glyph index, answering undefined for a CID the map does not reach, or undefined when codes do not reach glyphs in a way this reader applies
288
+ */
289
+ function cidToGlyphId(fontDict, descendantDict, context) {
290
+ const encodingName = require_objects.dictGet(fontDict, "Encoding");
291
+ if (!require_objects.isName(encodingName, "Identity-H") && !require_objects.isName(encodingName, "Identity-V")) return;
292
+ const map = context.resolver.resolve(descendantDict !== void 0 ? require_objects.dictGet(descendantDict, "CIDToGIDMap") : void 0);
293
+ if (map === void 0 || require_objects.isName(map, "Identity")) return (cid) => cid;
294
+ if (map.kind !== "stream") return;
295
+ const bytes = require_filters.decodeStream(map.raw, map.dict, context.sink).bytes;
296
+ return (cid) => {
297
+ const at = cid * CID_TO_GID_ENTRY_SIZE;
298
+ if (at + 1 >= bytes.length) return;
299
+ return (bytes[at] ?? 0) << BITS_PER_BYTE | (bytes[at + 1] ?? 0);
300
+ };
301
+ }
268
302
  function buildCompositeFont(fontDict, context) {
269
303
  const baseFont = require_objects.asName(require_objects.dictGet(fontDict, "BaseFont")) ?? "Helvetica";
270
304
  const descendants = resolvedArray(require_objects.dictGet(fontDict, "DescendantFonts"), context);
@@ -287,9 +321,8 @@ function buildCompositeFont(fontDict, context) {
287
321
  };
288
322
  };
289
323
  const toUnicode = readToUnicodeCMap(fontDict, context);
290
- const cidToGidMap = descendantDict !== void 0 ? require_objects.dictGet(descendantDict, "CIDToGIDMap") : void 0;
291
- const encodingName = require_objects.dictGet(fontDict, "Encoding");
292
- const programEncoding = (require_objects.isName(encodingName, "Identity-H") || require_objects.isName(encodingName, "Identity-V")) && (cidToGidMap === void 0 || require_objects.isName(cidToGidMap, "Identity")) ? lazyFontProgram(descriptor, context) : void 0;
324
+ const glyphIdOf = cidToGlyphId(fontDict, descendantDict, context);
325
+ const programEncoding = glyphIdOf !== void 0 ? lazyFontProgram(descriptor, baseFont, context) : void 0;
293
326
  const decodeToUnicode = (codes) => {
294
327
  let out = "";
295
328
  let glyphCount = 0;
@@ -302,9 +335,10 @@ function buildCompositeFont(fontDict, context) {
302
335
  out += mapped;
303
336
  continue;
304
337
  }
305
- const fromProgram = programEncoding?.()?.glyphIdToUnicode(cid);
338
+ const glyphId = glyphIdOf?.(cid);
339
+ const fromProgram = glyphId === void 0 ? void 0 : programEncoding?.()?.glyphIdToUnicode(glyphId);
306
340
  if (fromProgram !== void 0) {
307
- out += String.fromCodePoint(fromProgram);
341
+ out += fromProgram;
308
342
  continue;
309
343
  }
310
344
  unmapped++;
package/dist/font-read.js CHANGED
@@ -1,11 +1,13 @@
1
- import { a as glyphNameToUnicode, n as afmWidthOfCode, o as namedEncodingGlyphName, s as winAnsiGlyphName } from "./afm-widths-BNI8qa2S.js";
1
+ import { namedEncodingGlyphName, winAnsiGlyphName } from "./encoding.js";
2
+ import { afmWidthOfCode } from "./afm-widths.js";
2
3
  import { asArray, asName, asNumber, dictGet, isName } from "./objects.js";
3
4
  import { decodeStream } from "./filters.js";
5
+ import { styleFromBaseFontName } from "./font-style.js";
6
+ import { glyphNameToUnicode } from "./glyph-names.js";
4
7
  import { readFontProgramEncoding } from "./builtin-encoding.js";
5
8
  import { parseToUnicodeCMap } from "./cmap.js";
6
9
  import { symbolGlyphName, zapfDingbatsGlyphName } from "./encoding-symbol-tables.js";
7
10
  import { resolveStandardFont } from "./fonts.js";
8
- import { styleFromBaseFontName } from "./font-style.js";
9
11
  //#region src/font-read.ts
10
12
  const BITS_PER_BYTE = 8;
11
13
  const SYMBOLIC_FLAG_BIT = 4;
@@ -25,7 +27,7 @@ function builtinSymbolGlyphNameLookup(baseFamily) {
25
27
  if (baseFamily === "Symbol") return symbolGlyphName;
26
28
  if (baseFamily === "ZapfDingbats") return zapfDingbatsGlyphName;
27
29
  }
28
- function readFontProgram(descriptor, context) {
30
+ function readFontProgram(descriptor, baseFont, context) {
29
31
  if (descriptor === void 0) return;
30
32
  for (const key of [
31
33
  "FontFile2",
@@ -35,14 +37,14 @@ function readFontProgram(descriptor, context) {
35
37
  const stream = context.resolver.resolve(dictGet(descriptor, key));
36
38
  if (stream?.kind !== "stream") continue;
37
39
  const decoded = decodeStream(stream.raw, stream.dict, context.sink);
38
- const encoding = readFontProgramEncoding(decoded.bytes);
40
+ const encoding = readFontProgramEncoding(decoded.bytes, baseFont);
39
41
  if (encoding !== void 0) return encoding;
40
42
  }
41
43
  }
42
- function lazyFontProgram(descriptor, context) {
44
+ function lazyFontProgram(descriptor, baseFont, context) {
43
45
  let read;
44
46
  return () => {
45
- read ??= { encoding: readFontProgram(descriptor, context) };
47
+ read ??= { encoding: readFontProgram(descriptor, baseFont, context) };
46
48
  return read.encoding;
47
49
  };
48
50
  }
@@ -119,7 +121,14 @@ function buildSimpleFont(fontDict, context) {
119
121
  message: `base encoding "${baseEncodingName}" has no dedicated table here and is approximated as WinAnsiEncoding`
120
122
  });
121
123
  const differencesMap = readDifferencesMap(encodingDict !== void 0 ? resolvedArray(dictGet(encodingDict, "Differences"), context) : void 0);
122
- const programEncoding = lazyFontProgram(descriptor, context);
124
+ const programEncoding = lazyFontProgram(descriptor, baseFont, context);
125
+ const unicodeForDifferencesName = (name) => {
126
+ const named = glyphNameToUnicode(name);
127
+ if (named !== void 0) return named;
128
+ const program = programEncoding();
129
+ const glyphId = program?.glyphIdOfName(name);
130
+ return glyphId === void 0 ? void 0 : program?.glyphIdToUnicode(glyphId);
131
+ };
123
132
  const symbolEncoded = symbolic || builtinGlyphName !== void 0;
124
133
  const byGlyphName = (source) => (code) => {
125
134
  const name = source(code);
@@ -127,7 +136,7 @@ function buildSimpleFont(fontDict, context) {
127
136
  };
128
137
  const fromProgram = (code) => programEncoding()?.codeToUnicode(code);
129
138
  const namedBase = namedBaseGlyphName === void 0 ? void 0 : byGlyphName(namedBaseGlyphName);
130
- const resolvers = [byGlyphName((code) => differencesMap.get(code)), ...symbolEncoded ? [
139
+ const resolvers = (symbolEncoded ? [
131
140
  fromProgram,
132
141
  builtinGlyphName === void 0 ? void 0 : byGlyphName(builtinGlyphName),
133
142
  namedBase
@@ -135,8 +144,10 @@ function buildSimpleFont(fontDict, context) {
135
144
  namedBase,
136
145
  fromProgram,
137
146
  byGlyphName(winAnsiGlyphName)
138
- ]].filter((resolver) => resolver !== void 0);
147
+ ]).filter((resolver) => resolver !== void 0);
139
148
  const unicodeForCode = (code) => {
149
+ const differencesName = differencesMap.get(code);
150
+ if (differencesName !== void 0) return unicodeForDifferencesName(differencesName);
140
151
  for (const resolve of resolvers) {
141
152
  const unicode = resolve(code);
142
153
  if (unicode !== void 0) return unicode;
@@ -153,7 +164,7 @@ function buildSimpleFont(fontDict, context) {
153
164
  }
154
165
  const unicode = unicodeForCode(code);
155
166
  if (unicode !== void 0) {
156
- out += String.fromCodePoint(unicode);
167
+ out += unicode;
157
168
  continue;
158
169
  }
159
170
  unmapped++;
@@ -264,6 +275,29 @@ function readsVertically(fontDict, context) {
264
275
  if (encoding?.kind === "stream") return asNumber(dictGet(encoding.dict, "WMode")) === VERTICAL_WRITING_MODE;
265
276
  return false;
266
277
  }
278
+ const CID_TO_GID_ENTRY_SIZE = 2;
279
+ /**
280
+ * How a composite font's codes reach the embedded program's glyphs, so the program itself can say what a glyph is when the font dictionary's /ToUnicode CMap is absent or incomplete: through the glyph's own name, its program's Unicode mapping read backwards, or the glyph order of the core face the program is.
281
+ *
282
+ * With /Identity-H or /Identity-V a code is its CID. A /CIDToGIDMap that is absent or /Identity then makes the CID the glyph index, and a /CIDToGIDMap stream gives each CID its glyph index explicitly (ISO 32000-1 9.7.4.2). Any other /Encoding is a CMap from codes to CIDs this reader does not apply, and then the program is not consulted at all rather than being read against the wrong glyph.
283
+ * @param fontDict - the Type0 font dictionary
284
+ * @param descendantDict - its descendant CIDFont dictionary, if it has a readable one
285
+ * @param context - the font read whose resolver follows references and whose sink receives stream-decoding diagnostics
286
+ * @returns a lookup from CID to glyph index, answering undefined for a CID the map does not reach, or undefined when codes do not reach glyphs in a way this reader applies
287
+ */
288
+ function cidToGlyphId(fontDict, descendantDict, context) {
289
+ const encodingName = dictGet(fontDict, "Encoding");
290
+ if (!isName(encodingName, "Identity-H") && !isName(encodingName, "Identity-V")) return;
291
+ const map = context.resolver.resolve(descendantDict !== void 0 ? dictGet(descendantDict, "CIDToGIDMap") : void 0);
292
+ if (map === void 0 || isName(map, "Identity")) return (cid) => cid;
293
+ if (map.kind !== "stream") return;
294
+ const bytes = decodeStream(map.raw, map.dict, context.sink).bytes;
295
+ return (cid) => {
296
+ const at = cid * CID_TO_GID_ENTRY_SIZE;
297
+ if (at + 1 >= bytes.length) return;
298
+ return (bytes[at] ?? 0) << BITS_PER_BYTE | (bytes[at + 1] ?? 0);
299
+ };
300
+ }
267
301
  function buildCompositeFont(fontDict, context) {
268
302
  const baseFont = asName(dictGet(fontDict, "BaseFont")) ?? "Helvetica";
269
303
  const descendants = resolvedArray(dictGet(fontDict, "DescendantFonts"), context);
@@ -286,9 +320,8 @@ function buildCompositeFont(fontDict, context) {
286
320
  };
287
321
  };
288
322
  const toUnicode = readToUnicodeCMap(fontDict, context);
289
- const cidToGidMap = descendantDict !== void 0 ? dictGet(descendantDict, "CIDToGIDMap") : void 0;
290
- const encodingName = dictGet(fontDict, "Encoding");
291
- const programEncoding = (isName(encodingName, "Identity-H") || isName(encodingName, "Identity-V")) && (cidToGidMap === void 0 || isName(cidToGidMap, "Identity")) ? lazyFontProgram(descriptor, context) : void 0;
323
+ const glyphIdOf = cidToGlyphId(fontDict, descendantDict, context);
324
+ const programEncoding = glyphIdOf !== void 0 ? lazyFontProgram(descriptor, baseFont, context) : void 0;
292
325
  const decodeToUnicode = (codes) => {
293
326
  let out = "";
294
327
  let glyphCount = 0;
@@ -301,9 +334,10 @@ function buildCompositeFont(fontDict, context) {
301
334
  out += mapped;
302
335
  continue;
303
336
  }
304
- const fromProgram = programEncoding?.()?.glyphIdToUnicode(cid);
337
+ const glyphId = glyphIdOf?.(cid);
338
+ const fromProgram = glyphId === void 0 ? void 0 : programEncoding?.()?.glyphIdToUnicode(glyphId);
305
339
  if (fromProgram !== void 0) {
306
- out += String.fromCodePoint(fromProgram);
340
+ out += fromProgram;
307
341
  continue;
308
342
  }
309
343
  unmapped++;
@@ -16,8 +16,18 @@ function stripStyleSuffix(name) {
16
16
  }
17
17
  return name;
18
18
  }
19
+ /**
20
+ * A font name with any subset tag removed.
21
+ *
22
+ * Exactly six uppercase letters followed by '+' (ISO 32000-1 9.6.4) marks a subsetted font's unique tag, meaningless to a reader and never part of the real font name. The same tag prefixes the PostScript name inside the embedded program a producer subsetted.
23
+ * @param fontName - a /BaseFont value or an embedded program's own PostScript name
24
+ * @returns the name without its leading subset tag, or the name unchanged when it carries none
25
+ */
26
+ function withoutSubsetTag(fontName) {
27
+ return fontName.replace(/^[A-Z]{6}\+/, "");
28
+ }
19
29
  function styleFromBaseFontName(baseFont, flags) {
20
- const withoutSubset = baseFont.replace(/^[A-Z]{6}\+/, "");
30
+ const withoutSubset = withoutSubsetTag(baseFont);
21
31
  const lower = withoutSubset.toLowerCase();
22
32
  const nameBold = lower.includes("bold");
23
33
  const nameItalic = /italic|oblique/.test(lower);
@@ -31,3 +41,4 @@ function styleFromBaseFontName(baseFont, flags) {
31
41
  }
32
42
  //#endregion
33
43
  exports.styleFromBaseFontName = styleFromBaseFontName;
44
+ exports.withoutSubsetTag = withoutSubsetTag;
@@ -9,6 +9,14 @@ interface FontNameStyle {
9
9
  readonly bold: boolean;
10
10
  readonly italic: boolean;
11
11
  }
12
+ /**
13
+ * A font name with any subset tag removed.
14
+ *
15
+ * Exactly six uppercase letters followed by '+' (ISO 32000-1 9.6.4) marks a subsetted font's unique tag, meaningless to a reader and never part of the real font name. The same tag prefixes the PostScript name inside the embedded program a producer subsetted.
16
+ * @param fontName - a /BaseFont value or an embedded program's own PostScript name
17
+ * @returns the name without its leading subset tag, or the name unchanged when it carries none
18
+ */
19
+ declare function withoutSubsetTag(fontName: string): string;
12
20
  declare function styleFromBaseFontName(baseFont: string, flags?: FontStyleFlags): FontNameStyle;
13
21
  //#endregion
14
- export { FontNameStyle, FontStyleFlags, styleFromBaseFontName };
22
+ export { FontNameStyle, FontStyleFlags, styleFromBaseFontName, withoutSubsetTag };
@@ -9,6 +9,14 @@ interface FontNameStyle {
9
9
  readonly bold: boolean;
10
10
  readonly italic: boolean;
11
11
  }
12
+ /**
13
+ * A font name with any subset tag removed.
14
+ *
15
+ * Exactly six uppercase letters followed by '+' (ISO 32000-1 9.6.4) marks a subsetted font's unique tag, meaningless to a reader and never part of the real font name. The same tag prefixes the PostScript name inside the embedded program a producer subsetted.
16
+ * @param fontName - a /BaseFont value or an embedded program's own PostScript name
17
+ * @returns the name without its leading subset tag, or the name unchanged when it carries none
18
+ */
19
+ declare function withoutSubsetTag(fontName: string): string;
12
20
  declare function styleFromBaseFontName(baseFont: string, flags?: FontStyleFlags): FontNameStyle;
13
21
  //#endregion
14
- export { FontNameStyle, FontStyleFlags, styleFromBaseFontName };
22
+ export { FontNameStyle, FontStyleFlags, styleFromBaseFontName, withoutSubsetTag };
@@ -15,8 +15,18 @@ function stripStyleSuffix(name) {
15
15
  }
16
16
  return name;
17
17
  }
18
+ /**
19
+ * A font name with any subset tag removed.
20
+ *
21
+ * Exactly six uppercase letters followed by '+' (ISO 32000-1 9.6.4) marks a subsetted font's unique tag, meaningless to a reader and never part of the real font name. The same tag prefixes the PostScript name inside the embedded program a producer subsetted.
22
+ * @param fontName - a /BaseFont value or an embedded program's own PostScript name
23
+ * @returns the name without its leading subset tag, or the name unchanged when it carries none
24
+ */
25
+ function withoutSubsetTag(fontName) {
26
+ return fontName.replace(/^[A-Z]{6}\+/, "");
27
+ }
18
28
  function styleFromBaseFontName(baseFont, flags) {
19
- const withoutSubset = baseFont.replace(/^[A-Z]{6}\+/, "");
29
+ const withoutSubset = withoutSubsetTag(baseFont);
20
30
  const lower = withoutSubset.toLowerCase();
21
31
  const nameBold = lower.includes("bold");
22
32
  const nameItalic = /italic|oblique/.test(lower);
@@ -29,4 +39,4 @@ function styleFromBaseFontName(baseFont, flags) {
29
39
  };
30
40
  }
31
41
  //#endregion
32
- export { styleFromBaseFontName };
42
+ export { styleFromBaseFontName, withoutSubsetTag };