@cj-tech-master/excelts 8.0.0 → 8.1.0

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 (106) hide show
  1. package/README.md +14 -1
  2. package/README_zh.md +6 -0
  3. package/dist/browser/modules/archive/zip/stream.d.ts +4 -0
  4. package/dist/browser/modules/archive/zip/stream.js +53 -0
  5. package/dist/browser/modules/pdf/core/crypto.d.ts +65 -0
  6. package/dist/browser/modules/pdf/core/crypto.js +637 -0
  7. package/dist/browser/modules/pdf/core/encryption.d.ts +23 -20
  8. package/dist/browser/modules/pdf/core/encryption.js +88 -261
  9. package/dist/browser/modules/pdf/core/pdf-writer.d.ts +6 -4
  10. package/dist/browser/modules/pdf/core/pdf-writer.js +19 -10
  11. package/dist/browser/modules/pdf/index.d.ts +23 -2
  12. package/dist/browser/modules/pdf/index.js +21 -3
  13. package/dist/browser/modules/pdf/reader/annotation-extractor.d.ts +63 -0
  14. package/dist/browser/modules/pdf/reader/annotation-extractor.js +155 -0
  15. package/dist/browser/modules/pdf/reader/cmap-parser.d.ts +70 -0
  16. package/dist/browser/modules/pdf/reader/cmap-parser.js +321 -0
  17. package/dist/browser/modules/pdf/reader/content-interpreter.d.ts +57 -0
  18. package/dist/browser/modules/pdf/reader/content-interpreter.js +715 -0
  19. package/dist/browser/modules/pdf/reader/font-decoder.d.ts +58 -0
  20. package/dist/browser/modules/pdf/reader/font-decoder.js +1513 -0
  21. package/dist/browser/modules/pdf/reader/form-extractor.d.ts +48 -0
  22. package/dist/browser/modules/pdf/reader/form-extractor.js +355 -0
  23. package/dist/browser/modules/pdf/reader/image-extractor.d.ts +55 -0
  24. package/dist/browser/modules/pdf/reader/image-extractor.js +220 -0
  25. package/dist/browser/modules/pdf/reader/metadata-reader.d.ts +56 -0
  26. package/dist/browser/modules/pdf/reader/metadata-reader.js +275 -0
  27. package/dist/browser/modules/pdf/reader/pdf-decrypt.d.ts +26 -0
  28. package/dist/browser/modules/pdf/reader/pdf-decrypt.js +443 -0
  29. package/dist/browser/modules/pdf/reader/pdf-document.d.ts +191 -0
  30. package/dist/browser/modules/pdf/reader/pdf-document.js +818 -0
  31. package/dist/browser/modules/pdf/reader/pdf-parser.d.ts +65 -0
  32. package/dist/browser/modules/pdf/reader/pdf-parser.js +285 -0
  33. package/dist/browser/modules/pdf/reader/pdf-reader.d.ts +143 -0
  34. package/dist/browser/modules/pdf/reader/pdf-reader.js +200 -0
  35. package/dist/browser/modules/pdf/reader/pdf-tokenizer.d.ts +101 -0
  36. package/dist/browser/modules/pdf/reader/pdf-tokenizer.js +543 -0
  37. package/dist/browser/modules/pdf/reader/reader-utils.d.ts +15 -0
  38. package/dist/browser/modules/pdf/reader/reader-utils.js +27 -0
  39. package/dist/browser/modules/pdf/reader/stream-filters.d.ts +20 -0
  40. package/dist/browser/modules/pdf/reader/stream-filters.js +456 -0
  41. package/dist/browser/modules/pdf/reader/text-reconstruction.d.ts +44 -0
  42. package/dist/browser/modules/pdf/reader/text-reconstruction.js +463 -0
  43. package/dist/cjs/modules/archive/zip/stream.js +53 -0
  44. package/dist/cjs/modules/pdf/core/crypto.js +649 -0
  45. package/dist/cjs/modules/pdf/core/encryption.js +88 -263
  46. package/dist/cjs/modules/pdf/core/pdf-writer.js +19 -10
  47. package/dist/cjs/modules/pdf/index.js +23 -4
  48. package/dist/cjs/modules/pdf/reader/annotation-extractor.js +158 -0
  49. package/dist/cjs/modules/pdf/reader/cmap-parser.js +326 -0
  50. package/dist/cjs/modules/pdf/reader/content-interpreter.js +718 -0
  51. package/dist/cjs/modules/pdf/reader/font-decoder.js +1518 -0
  52. package/dist/cjs/modules/pdf/reader/form-extractor.js +358 -0
  53. package/dist/cjs/modules/pdf/reader/image-extractor.js +223 -0
  54. package/dist/cjs/modules/pdf/reader/metadata-reader.js +278 -0
  55. package/dist/cjs/modules/pdf/reader/pdf-decrypt.js +447 -0
  56. package/dist/cjs/modules/pdf/reader/pdf-document.js +822 -0
  57. package/dist/cjs/modules/pdf/reader/pdf-parser.js +301 -0
  58. package/dist/cjs/modules/pdf/reader/pdf-reader.js +203 -0
  59. package/dist/cjs/modules/pdf/reader/pdf-tokenizer.js +517 -0
  60. package/dist/cjs/modules/pdf/reader/reader-utils.js +30 -0
  61. package/dist/cjs/modules/pdf/reader/stream-filters.js +459 -0
  62. package/dist/cjs/modules/pdf/reader/text-reconstruction.js +467 -0
  63. package/dist/esm/modules/archive/zip/stream.js +53 -0
  64. package/dist/esm/modules/pdf/core/crypto.js +637 -0
  65. package/dist/esm/modules/pdf/core/encryption.js +88 -261
  66. package/dist/esm/modules/pdf/core/pdf-writer.js +19 -10
  67. package/dist/esm/modules/pdf/index.js +21 -3
  68. package/dist/esm/modules/pdf/reader/annotation-extractor.js +155 -0
  69. package/dist/esm/modules/pdf/reader/cmap-parser.js +321 -0
  70. package/dist/esm/modules/pdf/reader/content-interpreter.js +715 -0
  71. package/dist/esm/modules/pdf/reader/font-decoder.js +1513 -0
  72. package/dist/esm/modules/pdf/reader/form-extractor.js +355 -0
  73. package/dist/esm/modules/pdf/reader/image-extractor.js +220 -0
  74. package/dist/esm/modules/pdf/reader/metadata-reader.js +275 -0
  75. package/dist/esm/modules/pdf/reader/pdf-decrypt.js +443 -0
  76. package/dist/esm/modules/pdf/reader/pdf-document.js +818 -0
  77. package/dist/esm/modules/pdf/reader/pdf-parser.js +285 -0
  78. package/dist/esm/modules/pdf/reader/pdf-reader.js +200 -0
  79. package/dist/esm/modules/pdf/reader/pdf-tokenizer.js +543 -0
  80. package/dist/esm/modules/pdf/reader/reader-utils.js +27 -0
  81. package/dist/esm/modules/pdf/reader/stream-filters.js +456 -0
  82. package/dist/esm/modules/pdf/reader/text-reconstruction.js +463 -0
  83. package/dist/iife/excelts.iife.js +703 -267
  84. package/dist/iife/excelts.iife.js.map +1 -1
  85. package/dist/iife/excelts.iife.min.js +35 -35
  86. package/dist/types/modules/archive/zip/stream.d.ts +4 -0
  87. package/dist/types/modules/pdf/core/crypto.d.ts +65 -0
  88. package/dist/types/modules/pdf/core/encryption.d.ts +23 -20
  89. package/dist/types/modules/pdf/core/pdf-writer.d.ts +6 -4
  90. package/dist/types/modules/pdf/index.d.ts +23 -2
  91. package/dist/types/modules/pdf/reader/annotation-extractor.d.ts +63 -0
  92. package/dist/types/modules/pdf/reader/cmap-parser.d.ts +70 -0
  93. package/dist/types/modules/pdf/reader/content-interpreter.d.ts +57 -0
  94. package/dist/types/modules/pdf/reader/font-decoder.d.ts +58 -0
  95. package/dist/types/modules/pdf/reader/form-extractor.d.ts +48 -0
  96. package/dist/types/modules/pdf/reader/image-extractor.d.ts +55 -0
  97. package/dist/types/modules/pdf/reader/metadata-reader.d.ts +56 -0
  98. package/dist/types/modules/pdf/reader/pdf-decrypt.d.ts +26 -0
  99. package/dist/types/modules/pdf/reader/pdf-document.d.ts +191 -0
  100. package/dist/types/modules/pdf/reader/pdf-parser.d.ts +65 -0
  101. package/dist/types/modules/pdf/reader/pdf-reader.d.ts +143 -0
  102. package/dist/types/modules/pdf/reader/pdf-tokenizer.d.ts +101 -0
  103. package/dist/types/modules/pdf/reader/reader-utils.d.ts +15 -0
  104. package/dist/types/modules/pdf/reader/stream-filters.d.ts +20 -0
  105. package/dist/types/modules/pdf/reader/text-reconstruction.d.ts +44 -0
  106. package/package.json +1 -1
@@ -0,0 +1,1518 @@
1
+ "use strict";
2
+ /**
3
+ * PDF font decoder for text extraction.
4
+ *
5
+ * Handles the mapping from character codes in content streams to Unicode
6
+ * strings. Supports all major PDF font types:
7
+ *
8
+ * - Type 1 fonts (standard 14 + custom with /Encoding)
9
+ * - TrueType fonts (with /Encoding and /ToUnicode)
10
+ * - Type 0 (CID) composite fonts (with /ToUnicode CMap)
11
+ * - Type 3 fonts (with /Encoding and /ToUnicode)
12
+ *
13
+ * @see PDF Reference 1.7, Chapter 5 - Text
14
+ * @see PDF Reference 1.7, §5.5 - Character Encoding
15
+ */
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.resolveFont = resolveFont;
18
+ exports.decodeText = decodeText;
19
+ exports.getCharWidth = getCharWidth;
20
+ const cmap_parser_1 = require("./cmap-parser");
21
+ const pdf_parser_1 = require("./pdf-parser");
22
+ // =============================================================================
23
+ // Standard 14 Font Names
24
+ // =============================================================================
25
+ /**
26
+ * The 14 standard PDF fonts and their default encoding families.
27
+ * "winansi" → WinAnsiEncoding, "symbol" → SymbolEncoding, "zapf" → ZapfDingbatsEncoding
28
+ */
29
+ const STANDARD_14_FONTS = {
30
+ Courier: "winansi",
31
+ "Courier-Bold": "winansi",
32
+ "Courier-Oblique": "winansi",
33
+ "Courier-BoldOblique": "winansi",
34
+ Helvetica: "winansi",
35
+ "Helvetica-Bold": "winansi",
36
+ "Helvetica-Oblique": "winansi",
37
+ "Helvetica-BoldOblique": "winansi",
38
+ "Times-Roman": "winansi",
39
+ "Times-Bold": "winansi",
40
+ "Times-Italic": "winansi",
41
+ "Times-BoldItalic": "winansi",
42
+ Symbol: "symbol",
43
+ ZapfDingbats: "zapf"
44
+ };
45
+ /**
46
+ * Detect the standard 14 font family from a BaseFont name.
47
+ * Handles common variants like "ABCDEF+Helvetica-Bold".
48
+ */
49
+ function detectStandard14(baseFontName) {
50
+ // Strip subset prefix (e.g. "ABCDEF+Helvetica" → "Helvetica")
51
+ const stripped = baseFontName.includes("+")
52
+ ? baseFontName.substring(baseFontName.indexOf("+") + 1)
53
+ : baseFontName;
54
+ // Direct match
55
+ const direct = STANDARD_14_FONTS[stripped];
56
+ if (direct) {
57
+ return direct;
58
+ }
59
+ // Prefix match for variants (e.g. "Helvetica-Narrow" → winansi)
60
+ const lower = stripped.toLowerCase();
61
+ if (lower.startsWith("courier") || lower.startsWith("helvetica") || lower.startsWith("times")) {
62
+ return "winansi";
63
+ }
64
+ if (lower === "symbol" || lower.startsWith("symbol")) {
65
+ return "symbol";
66
+ }
67
+ if (lower === "zapfdingbats" || lower.startsWith("zapfdingbats")) {
68
+ return "zapf";
69
+ }
70
+ return null;
71
+ }
72
+ // =============================================================================
73
+ // Font Resolution
74
+ // =============================================================================
75
+ /**
76
+ * Resolve a PDF font dictionary into a ResolvedFont for text extraction.
77
+ */
78
+ function resolveFont(fontDict, doc) {
79
+ const subtype = (0, pdf_parser_1.dictGetName)(fontDict, "Subtype") ?? "Type1";
80
+ const baseFontName = (0, pdf_parser_1.dictGetName)(fontDict, "BaseFont") ?? "Unknown";
81
+ const name = (0, pdf_parser_1.dictGetName)(fontDict, "Name") ?? baseFontName;
82
+ // Parse ToUnicode CMap
83
+ const toUnicode = parseToUnicode(fontDict, doc);
84
+ // Detect Identity-H / Identity-V encoding for Type0 fonts
85
+ let isIdentityEncoding = false;
86
+ let wmode = 0;
87
+ if (subtype === "Type0") {
88
+ const encodingVal = fontDict.get("Encoding");
89
+ if (typeof encodingVal === "string") {
90
+ if (encodingVal === "Identity-H" || encodingVal === "Identity-V") {
91
+ isIdentityEncoding = true;
92
+ wmode = encodingVal === "Identity-V" ? 1 : 0;
93
+ }
94
+ else if (encodingVal.endsWith("-V")) {
95
+ wmode = 1;
96
+ }
97
+ }
98
+ else if ((0, pdf_parser_1.isPdfRef)(encodingVal)) {
99
+ // Could be a CMap stream; check for WMode
100
+ const cmapDict = doc.derefDict(encodingVal);
101
+ if (cmapDict) {
102
+ wmode = (0, pdf_parser_1.dictGetNumber)(cmapDict, "WMode") ?? 0;
103
+ }
104
+ }
105
+ }
106
+ // Determine encoding
107
+ const encoding = buildEncoding(fontDict, subtype, baseFontName, doc);
108
+ // Determine bytes per code
109
+ let bytesPerCode = 1;
110
+ if (subtype === "Type0") {
111
+ bytesPerCode = toUnicode?.bytesPerCode ?? 2;
112
+ }
113
+ // Check if symbolic
114
+ const descriptor = resolveDescriptor(fontDict, doc);
115
+ const flags = descriptor ? ((0, pdf_parser_1.dictGetNumber)(descriptor, "Flags") ?? 0) : 0;
116
+ const isSymbolic = (flags & 4) !== 0;
117
+ // Build widths map
118
+ const { widths, defaultWidth, missingWidth } = buildWidths(fontDict, subtype, descriptor, doc);
119
+ return {
120
+ name,
121
+ subtype,
122
+ toUnicode,
123
+ encoding,
124
+ bytesPerCode,
125
+ baseFontName,
126
+ isSymbolic,
127
+ widths,
128
+ defaultWidth,
129
+ missingWidth,
130
+ isIdentityEncoding,
131
+ wmode
132
+ };
133
+ }
134
+ /**
135
+ * Decode character codes to Unicode text using a resolved font.
136
+ */
137
+ function decodeText(codes, font) {
138
+ // For Type0 (CID) fonts, try ToUnicode first with multi-byte codes
139
+ if (font.subtype === "Type0" || font.bytesPerCode === 2) {
140
+ return decodeCIDText(codes, font);
141
+ }
142
+ // Simple fonts: single-byte encoding
143
+ let result = "";
144
+ for (let i = 0; i < codes.length; i++) {
145
+ const code = codes[i];
146
+ const ch = lookupChar(code, font);
147
+ result += ch;
148
+ }
149
+ return result;
150
+ }
151
+ /**
152
+ * Decode a hex-encoded string from a TJ/Tj operator for CID fonts.
153
+ * Uses the CMap's codespace ranges to determine byte lengths when available.
154
+ */
155
+ function decodeCIDText(codes, font) {
156
+ let result = "";
157
+ let i = 0;
158
+ while (i < codes.length) {
159
+ // Determine code length using CMap codespace ranges if available
160
+ let codeLen = 0;
161
+ if (font.toUnicode?.hasCodeSpaceRanges) {
162
+ codeLen = font.toUnicode.getCodeLength(codes[i]);
163
+ }
164
+ if (codeLen === 2 && i + 1 < codes.length) {
165
+ // Codespace says this is a 2-byte code
166
+ const code2 = (codes[i] << 8) | codes[i + 1];
167
+ const ch = lookupChar(code2, font);
168
+ result += ch;
169
+ i += 2;
170
+ }
171
+ else if (codeLen === 1) {
172
+ // Codespace says this is a 1-byte code
173
+ const ch = lookupChar(codes[i], font);
174
+ result += ch;
175
+ i++;
176
+ }
177
+ else {
178
+ // No codespace ranges or unknown byte — fall back to greedy 2-byte then 1-byte
179
+ if (i + 1 < codes.length) {
180
+ const code2 = (codes[i] << 8) | codes[i + 1];
181
+ const ch = lookupChar(code2, font);
182
+ if (ch !== "\uFFFD") {
183
+ result += ch;
184
+ i += 2;
185
+ continue;
186
+ }
187
+ }
188
+ // Fall back to 1-byte
189
+ const ch = lookupChar(codes[i], font);
190
+ result += ch;
191
+ i++;
192
+ }
193
+ }
194
+ return result;
195
+ }
196
+ /**
197
+ * Look up a single character code using the font's encoding chain.
198
+ * Priority: ToUnicode → Identity encoding → Encoding map → direct char code → byte passthrough.
199
+ */
200
+ function lookupChar(code, font) {
201
+ // 1. ToUnicode CMap (highest priority — most reliable for multilingual)
202
+ if (font.toUnicode) {
203
+ const mapped = font.toUnicode.lookup(code);
204
+ if (mapped !== undefined) {
205
+ return mapped;
206
+ }
207
+ }
208
+ // 2. Identity-H/Identity-V: the 2-byte code IS the Unicode code point
209
+ if (font.isIdentityEncoding && code > 0) {
210
+ // Validate it's a reasonable Unicode code point (BMP or supplementary)
211
+ if (code <= 0x10ffff && (code < 0xd800 || code > 0xdfff)) {
212
+ return String.fromCodePoint(code);
213
+ }
214
+ }
215
+ // 3. Encoding map
216
+ const encoded = font.encoding.get(code);
217
+ if (encoded !== undefined) {
218
+ return encoded;
219
+ }
220
+ // 4. Direct code point (for standard Latin characters)
221
+ if (code >= 0x20 && code <= 0x7e) {
222
+ return String.fromCharCode(code);
223
+ }
224
+ // 5. Last resort: pass through byte value as code point.
225
+ // Many fonts use Unicode-ordered glyphs, so the raw code often works.
226
+ if (code > 0x7e && code <= 0x10ffff && (code < 0xd800 || code > 0xdfff)) {
227
+ return String.fromCodePoint(code);
228
+ }
229
+ // 6. Unmapped — return replacement character
230
+ return "\uFFFD";
231
+ }
232
+ // =============================================================================
233
+ // ToUnicode CMap
234
+ // =============================================================================
235
+ function parseToUnicode(fontDict, doc) {
236
+ const toUnicodeRef = fontDict.get("ToUnicode");
237
+ if (!toUnicodeRef) {
238
+ // For Type0 fonts, check descendant fonts
239
+ if ((0, pdf_parser_1.dictGetName)(fontDict, "Subtype") === "Type0") {
240
+ const descendants = (0, pdf_parser_1.dictGetArray)(fontDict, "DescendantFonts");
241
+ if (descendants && descendants.length > 0) {
242
+ const cidFont = doc.derefDict(descendants[0]);
243
+ if (cidFont) {
244
+ const cidToUnicode = cidFont.get("ToUnicode");
245
+ if (cidToUnicode) {
246
+ return resolveToUnicode(cidToUnicode, doc);
247
+ }
248
+ }
249
+ }
250
+ }
251
+ return null;
252
+ }
253
+ return resolveToUnicode(toUnicodeRef, doc);
254
+ }
255
+ function resolveToUnicode(ref, doc) {
256
+ const result = doc.derefStreamWithObjNum(ref);
257
+ if (!result) {
258
+ return null;
259
+ }
260
+ try {
261
+ const data = doc.getStreamData(result.stream, result.objNum, result.gen);
262
+ return (0, cmap_parser_1.parseCMap)(data);
263
+ }
264
+ catch {
265
+ return null;
266
+ }
267
+ }
268
+ // =============================================================================
269
+ // Encoding
270
+ // =============================================================================
271
+ function buildEncoding(fontDict, subtype, baseFontName, doc) {
272
+ const encoding = new Map();
273
+ // For Type0 fonts, encoding is handled by the CMap
274
+ if (subtype === "Type0") {
275
+ return encoding;
276
+ }
277
+ const encodingObj = fontDict.get("Encoding");
278
+ if (typeof encodingObj === "string") {
279
+ // Named encoding
280
+ applyNamedEncoding(encoding, encodingObj);
281
+ }
282
+ else if ((0, pdf_parser_1.isPdfDict)(encodingObj)) {
283
+ // Encoding dictionary
284
+ const baseEncoding = (0, pdf_parser_1.dictGetName)(encodingObj, "BaseEncoding");
285
+ if (baseEncoding) {
286
+ applyNamedEncoding(encoding, baseEncoding);
287
+ }
288
+ else {
289
+ // Default base encoding depends on font type/name
290
+ applyDefaultBaseEncoding(encoding, subtype, baseFontName);
291
+ }
292
+ // Apply Differences array
293
+ const differences = (0, pdf_parser_1.dictGetArray)(encodingObj, "Differences");
294
+ if (differences) {
295
+ applyDifferences(encoding, differences);
296
+ }
297
+ }
298
+ else if ((0, pdf_parser_1.isPdfRef)(encodingObj)) {
299
+ const resolved = doc.derefDict(encodingObj);
300
+ if (resolved) {
301
+ const baseEncoding = (0, pdf_parser_1.dictGetName)(resolved, "BaseEncoding");
302
+ if (baseEncoding) {
303
+ applyNamedEncoding(encoding, baseEncoding);
304
+ }
305
+ else {
306
+ applyDefaultBaseEncoding(encoding, subtype, baseFontName);
307
+ }
308
+ const differences = (0, pdf_parser_1.dictGetArray)(resolved, "Differences");
309
+ if (differences) {
310
+ applyDifferences(encoding, differences);
311
+ }
312
+ }
313
+ }
314
+ else {
315
+ // No encoding specified — use defaults based on font type and name
316
+ applyDefaultBaseEncoding(encoding, subtype, baseFontName);
317
+ }
318
+ return encoding;
319
+ }
320
+ /**
321
+ * Apply the correct default base encoding based on font subtype and BaseFont name.
322
+ * - Symbol → SymbolEncoding
323
+ * - ZapfDingbats → ZapfDingbatsEncoding
324
+ * - TrueType / Helvetica / Times / Courier families → WinAnsiEncoding
325
+ * - Other Type1 → StandardEncoding
326
+ */
327
+ function applyDefaultBaseEncoding(encoding, subtype, baseFontName) {
328
+ const std14 = detectStandard14(baseFontName);
329
+ if (std14 === "symbol") {
330
+ applyNamedEncoding(encoding, "SymbolEncoding");
331
+ }
332
+ else if (std14 === "zapf") {
333
+ applyNamedEncoding(encoding, "ZapfDingbatsEncoding");
334
+ }
335
+ else if (subtype === "TrueType" || std14 === "winansi") {
336
+ applyNamedEncoding(encoding, "WinAnsiEncoding");
337
+ }
338
+ else {
339
+ applyNamedEncoding(encoding, "StandardEncoding");
340
+ }
341
+ }
342
+ // =============================================================================
343
+ // Named Encodings
344
+ // =============================================================================
345
+ function applyNamedEncoding(encoding, name) {
346
+ let table;
347
+ switch (name) {
348
+ case "WinAnsiEncoding":
349
+ table = WIN_ANSI_ENCODING;
350
+ break;
351
+ case "MacRomanEncoding":
352
+ table = MAC_ROMAN_ENCODING;
353
+ break;
354
+ case "StandardEncoding":
355
+ table = STANDARD_ENCODING;
356
+ break;
357
+ case "MacExpertEncoding":
358
+ table = MAC_EXPERT_ENCODING;
359
+ break;
360
+ case "SymbolEncoding":
361
+ table = SYMBOL_ENCODING;
362
+ break;
363
+ case "ZapfDingbatsEncoding":
364
+ table = ZAPF_DINGBATS_ENCODING;
365
+ break;
366
+ default:
367
+ table = WIN_ANSI_ENCODING;
368
+ break;
369
+ }
370
+ for (const [code, char] of Object.entries(table)) {
371
+ encoding.set(Number(code), char);
372
+ }
373
+ }
374
+ /**
375
+ * Apply a /Differences array to an encoding.
376
+ * Format: [code1 /name1 /name2 ... codeN /nameN ...]
377
+ */
378
+ function applyDifferences(encoding, differences) {
379
+ let code = 0;
380
+ for (const item of differences) {
381
+ if (typeof item === "number") {
382
+ code = item;
383
+ }
384
+ else if (typeof item === "string") {
385
+ const unicode = glyphNameToUnicode(item);
386
+ if (unicode) {
387
+ encoding.set(code, unicode);
388
+ }
389
+ code++;
390
+ }
391
+ }
392
+ }
393
+ // =============================================================================
394
+ // Font Descriptor
395
+ // =============================================================================
396
+ function resolveDescriptor(fontDict, doc) {
397
+ const descRef = fontDict.get("FontDescriptor");
398
+ if (descRef) {
399
+ return doc.derefDict(descRef);
400
+ }
401
+ // For Type0 fonts, check descendant
402
+ if ((0, pdf_parser_1.dictGetName)(fontDict, "Subtype") === "Type0") {
403
+ const descendants = (0, pdf_parser_1.dictGetArray)(fontDict, "DescendantFonts");
404
+ if (descendants && descendants.length > 0) {
405
+ const cidFont = doc.derefDict(descendants[0]);
406
+ if (cidFont) {
407
+ const cidDesc = cidFont.get("FontDescriptor");
408
+ return doc.derefDict(cidDesc);
409
+ }
410
+ }
411
+ }
412
+ return null;
413
+ }
414
+ // =============================================================================
415
+ // Widths
416
+ // =============================================================================
417
+ function buildWidths(fontDict, subtype, descriptor, doc) {
418
+ const widths = new Map();
419
+ let defaultWidth = 1000;
420
+ let missingWidth = 0;
421
+ if (descriptor) {
422
+ missingWidth = (0, pdf_parser_1.dictGetNumber)(descriptor, "MissingWidth") ?? 0;
423
+ }
424
+ if (subtype === "Type0") {
425
+ // CID font widths
426
+ const descendants = (0, pdf_parser_1.dictGetArray)(fontDict, "DescendantFonts");
427
+ if (descendants && descendants.length > 0) {
428
+ const cidFont = doc.derefDict(descendants[0]);
429
+ if (cidFont) {
430
+ defaultWidth = (0, pdf_parser_1.dictGetNumber)(cidFont, "DW") ?? 1000;
431
+ const wArray = (0, pdf_parser_1.dictGetArray)(cidFont, "W");
432
+ if (wArray) {
433
+ parseCIDWidths(wArray, widths, doc);
434
+ }
435
+ }
436
+ }
437
+ }
438
+ else {
439
+ // Simple font widths
440
+ const firstChar = (0, pdf_parser_1.dictGetNumber)(fontDict, "FirstChar") ?? 0;
441
+ const widthsArray = (0, pdf_parser_1.dictGetArray)(fontDict, "Widths");
442
+ if (widthsArray) {
443
+ for (let i = 0; i < widthsArray.length; i++) {
444
+ const w = widthsArray[i];
445
+ if (typeof w === "number") {
446
+ widths.set(firstChar + i, w);
447
+ }
448
+ }
449
+ }
450
+ }
451
+ return { widths, defaultWidth, missingWidth };
452
+ }
453
+ /**
454
+ * Parse CID font /W array.
455
+ * Format: [cid [w1 w2 ...]] or [cidFirst cidLast w]
456
+ */
457
+ function parseCIDWidths(wArray, widths, _doc) {
458
+ let i = 0;
459
+ while (i < wArray.length) {
460
+ const first = wArray[i];
461
+ i++;
462
+ if (i >= wArray.length) {
463
+ break;
464
+ }
465
+ const next = wArray[i];
466
+ if ((0, pdf_parser_1.isPdfArray)(next)) {
467
+ // [cid [w1 w2 ...]]
468
+ for (let j = 0; j < next.length; j++) {
469
+ widths.set(first + j, next[j]);
470
+ }
471
+ i++;
472
+ }
473
+ else if (typeof next === "number") {
474
+ // [cidFirst cidLast w]
475
+ const last = next;
476
+ i++;
477
+ if (i < wArray.length) {
478
+ const w = wArray[i];
479
+ for (let cid = first; cid <= last; cid++) {
480
+ widths.set(cid, w);
481
+ }
482
+ i++;
483
+ }
484
+ }
485
+ else {
486
+ i++;
487
+ }
488
+ }
489
+ }
490
+ /**
491
+ * Get the character width for a given code.
492
+ */
493
+ function getCharWidth(code, font) {
494
+ const w = font.widths.get(code);
495
+ if (w !== undefined) {
496
+ return w;
497
+ }
498
+ return font.missingWidth || font.defaultWidth;
499
+ }
500
+ // =============================================================================
501
+ // Glyph Name to Unicode Mapping (Adobe Glyph List)
502
+ // =============================================================================
503
+ /**
504
+ * Map an Adobe glyph name to its Unicode string.
505
+ * Uses the Adobe Glyph List (AGL) plus common extensions.
506
+ */
507
+ function glyphNameToUnicode(name) {
508
+ // Check predefined table
509
+ const mapped = GLYPH_TO_UNICODE[name];
510
+ if (mapped !== undefined) {
511
+ return String.fromCodePoint(mapped);
512
+ }
513
+ // Handle uniXXXX form
514
+ if (name.startsWith("uni") && name.length >= 7) {
515
+ const hex = name.substring(3);
516
+ const cp = parseInt(hex, 16);
517
+ if (!isNaN(cp) && cp > 0) {
518
+ return String.fromCodePoint(cp);
519
+ }
520
+ }
521
+ // Handle uXXXX / uXXXXX form
522
+ if (name.startsWith("u") && name.length >= 5) {
523
+ const hex = name.substring(1);
524
+ const cp = parseInt(hex, 16);
525
+ if (!isNaN(cp) && cp > 0) {
526
+ return String.fromCodePoint(cp);
527
+ }
528
+ }
529
+ return undefined;
530
+ }
531
+ // =============================================================================
532
+ // Encoding Tables
533
+ // =============================================================================
534
+ /**
535
+ * WinAnsi (Windows-1252) encoding.
536
+ * Maps byte values to Unicode characters.
537
+ */
538
+ const WIN_ANSI_ENCODING = /* @__PURE__ */ (() => {
539
+ const table = {};
540
+ // Standard ASCII printable range
541
+ for (let i = 0x20; i <= 0x7e; i++) {
542
+ table[i] = String.fromCharCode(i);
543
+ }
544
+ // High range (0xA0-0xFF) maps directly
545
+ for (let i = 0xa0; i <= 0xff; i++) {
546
+ table[i] = String.fromCharCode(i);
547
+ }
548
+ // 0x80-0x9F special mappings
549
+ const special = {
550
+ 0x80: 0x20ac,
551
+ 0x82: 0x201a,
552
+ 0x83: 0x0192,
553
+ 0x84: 0x201e,
554
+ 0x85: 0x2026,
555
+ 0x86: 0x2020,
556
+ 0x87: 0x2021,
557
+ 0x88: 0x02c6,
558
+ 0x89: 0x2030,
559
+ 0x8a: 0x0160,
560
+ 0x8b: 0x2039,
561
+ 0x8c: 0x0152,
562
+ 0x8e: 0x017d,
563
+ 0x91: 0x2018,
564
+ 0x92: 0x2019,
565
+ 0x93: 0x201c,
566
+ 0x94: 0x201d,
567
+ 0x95: 0x2022,
568
+ 0x96: 0x2013,
569
+ 0x97: 0x2014,
570
+ 0x98: 0x02dc,
571
+ 0x99: 0x2122,
572
+ 0x9a: 0x0161,
573
+ 0x9b: 0x203a,
574
+ 0x9c: 0x0153,
575
+ 0x9e: 0x017e,
576
+ 0x9f: 0x0178
577
+ };
578
+ for (const [code, cp] of Object.entries(special)) {
579
+ table[Number(code)] = String.fromCodePoint(cp);
580
+ }
581
+ return table;
582
+ })();
583
+ /**
584
+ * MacRoman encoding.
585
+ */
586
+ const MAC_ROMAN_ENCODING = /* @__PURE__ */ (() => {
587
+ const table = {};
588
+ for (let i = 0x20; i <= 0x7e; i++) {
589
+ table[i] = String.fromCharCode(i);
590
+ }
591
+ const mac = [
592
+ 0x00c4, 0x00c5, 0x00c7, 0x00c9, 0x00d1, 0x00d6, 0x00dc, 0x00e1, 0x00e0, 0x00e2, 0x00e4, 0x00e3,
593
+ 0x00e5, 0x00e7, 0x00e9, 0x00e8, 0x00ea, 0x00eb, 0x00ed, 0x00ec, 0x00ee, 0x00ef, 0x00f1, 0x00f3,
594
+ 0x00f2, 0x00f4, 0x00f6, 0x00f5, 0x00fa, 0x00f9, 0x00fb, 0x00fc, 0x2020, 0x00b0, 0x00a2, 0x00a3,
595
+ 0x00a7, 0x2022, 0x00b6, 0x00df, 0x00ae, 0x00a9, 0x2122, 0x00b4, 0x00a8, 0x2260, 0x00c6, 0x00d8,
596
+ 0x221e, 0x00b1, 0x2264, 0x2265, 0x00a5, 0x00b5, 0x2202, 0x2211, 0x220f, 0x03c0, 0x222b, 0x00aa,
597
+ 0x00ba, 0x2126, 0x00e6, 0x00f8, 0x00bf, 0x00a1, 0x00ac, 0x221a, 0x0192, 0x2248, 0x2206, 0x00ab,
598
+ 0x00bb, 0x2026, 0x00a0, 0x00c0, 0x00c3, 0x00d5, 0x0152, 0x0153, 0x2013, 0x2014, 0x201c, 0x201d,
599
+ 0x2018, 0x2019, 0x00f7, 0x25ca, 0x00ff, 0x0178, 0x2044, 0x20ac, 0x2039, 0x203a, 0xfb01, 0xfb02,
600
+ 0x2021, 0x00b7, 0x201a, 0x201e, 0x2030, 0x00c2, 0x00ca, 0x00c1, 0x00cb, 0x00c8, 0x00cd, 0x00ce,
601
+ 0x00cf, 0x00cc, 0x00d3, 0x00d4, 0xf8ff, 0x00d2, 0x00da, 0x00db, 0x00d9, 0x0131, 0x02c6, 0x02dc,
602
+ 0x00af, 0x02d8, 0x02d9, 0x02da, 0x00b8, 0x02dd, 0x02db, 0x02c7
603
+ ];
604
+ for (let i = 0; i < mac.length; i++) {
605
+ table[0x80 + i] = String.fromCodePoint(mac[i]);
606
+ }
607
+ return table;
608
+ })();
609
+ /**
610
+ * Standard encoding (for Type 1 fonts).
611
+ * Only includes the characters that differ from ASCII.
612
+ */
613
+ const STANDARD_ENCODING = /* @__PURE__ */ (() => {
614
+ const table = {};
615
+ for (let i = 0x20; i <= 0x7e; i++) {
616
+ table[i] = String.fromCharCode(i);
617
+ }
618
+ // Standard encoding differences
619
+ const diffs = {
620
+ 0xa1: 0x00a1,
621
+ 0xa2: 0x00a2,
622
+ 0xa3: 0x00a3,
623
+ 0xa4: 0x2044,
624
+ 0xa5: 0x00a5,
625
+ 0xa6: 0x0192,
626
+ 0xa7: 0x00a7,
627
+ 0xa8: 0x00a4,
628
+ 0xa9: 0x0027,
629
+ 0xaa: 0x201c,
630
+ 0xab: 0x00ab,
631
+ 0xac: 0x2039,
632
+ 0xad: 0x203a,
633
+ 0xae: 0xfb01,
634
+ 0xaf: 0xfb02,
635
+ 0xb1: 0x2013,
636
+ 0xb2: 0x2020,
637
+ 0xb3: 0x2021,
638
+ 0xb4: 0x00b7,
639
+ 0xb6: 0x00b6,
640
+ 0xb7: 0x2022,
641
+ 0xb8: 0x201a,
642
+ 0xb9: 0x201e,
643
+ 0xba: 0x201d,
644
+ 0xbb: 0x00bb,
645
+ 0xbc: 0x2026,
646
+ 0xbd: 0x2030,
647
+ 0xc1: 0x0060,
648
+ 0xc2: 0x00b4,
649
+ 0xc3: 0x02c6,
650
+ 0xc4: 0x02dc,
651
+ 0xc5: 0x00af,
652
+ 0xc6: 0x02d8,
653
+ 0xc7: 0x02d9,
654
+ 0xc8: 0x00a8,
655
+ 0xca: 0x02da,
656
+ 0xcb: 0x00b8,
657
+ 0xcc: 0x02dd,
658
+ 0xcd: 0x02db,
659
+ 0xce: 0x02c7,
660
+ 0xcf: 0x2014,
661
+ 0xe1: 0x00c6,
662
+ 0xe3: 0x00aa,
663
+ 0xe8: 0x0141,
664
+ 0xe9: 0x00d8,
665
+ 0xea: 0x0152,
666
+ 0xeb: 0x00ba,
667
+ 0xf1: 0x00e6,
668
+ 0xf5: 0x0131,
669
+ 0xf8: 0x0142,
670
+ 0xf9: 0x00f8,
671
+ 0xfa: 0x0153,
672
+ 0xfb: 0x00df
673
+ };
674
+ for (const [code, cp] of Object.entries(diffs)) {
675
+ table[Number(code)] = String.fromCodePoint(cp);
676
+ }
677
+ return table;
678
+ })();
679
+ /**
680
+ * MacExpert encoding — used by expert subset fonts for oldstyle numerals,
681
+ * small caps, fractions, and other typographic alternates.
682
+ *
683
+ * @see Adobe Technical Note #5014 — "Adobe Standard Encoding"
684
+ */
685
+ const MAC_EXPERT_ENCODING = /* @__PURE__ */ (() => {
686
+ const table = {};
687
+ // Complete MacExpert encoding map (code → Unicode code point)
688
+ const mappings = {
689
+ 0x20: 0x0020, // space
690
+ 0x21: 0xf721, // exclamsmall
691
+ 0x22: 0xf6e2, // Hungarumlautsmall
692
+ 0x23: 0xf7a2, // centoldstyle
693
+ 0x24: 0xf724, // dollaroldstyle
694
+ 0x25: 0xf6e4, // dollarsuperior
695
+ 0x26: 0xf726, // ampersandsmall
696
+ 0x27: 0xf7b4, // Acutesmall
697
+ 0x28: 0x207d, // parenleftsuperior
698
+ 0x29: 0x207e, // parenrightsuperior
699
+ 0x2a: 0x2025, // twodotenleader
700
+ 0x2b: 0x2024, // onedotenleader
701
+ 0x2c: 0x002c, // comma
702
+ 0x2d: 0x002d, // hyphen
703
+ 0x2e: 0x002e, // period
704
+ 0x2f: 0x2044, // fraction
705
+ 0x30: 0xf730, // zerooldstyle
706
+ 0x31: 0xf731, // oneoldstyle
707
+ 0x32: 0xf732, // twooldstyle
708
+ 0x33: 0xf733, // threeoldstyle
709
+ 0x34: 0xf734, // fouroldstyle
710
+ 0x35: 0xf735, // fiveoldstyle
711
+ 0x36: 0xf736, // sixoldstyle
712
+ 0x37: 0xf737, // sevenoldstyle
713
+ 0x38: 0xf738, // eightoldstyle
714
+ 0x39: 0xf739, // nineoldstyle
715
+ 0x3a: 0x003a, // colon
716
+ 0x3b: 0x003b, // semicolon
717
+ 0x3d: 0xf6de, // threequartersemdash
718
+ 0x3f: 0xf73f, // questionsmall
719
+ 0x44: 0xf7f0, // Ethsmall
720
+ 0x47: 0x00bc, // onequarter
721
+ 0x48: 0x00bd, // onehalf
722
+ 0x49: 0x00be, // threequarters
723
+ 0x4a: 0x215b, // oneeighth
724
+ 0x4b: 0x215c, // threeeighths
725
+ 0x4c: 0x215d, // fiveeighths
726
+ 0x4d: 0x215e, // seveneighths
727
+ 0x4e: 0x2153, // onethird
728
+ 0x4f: 0x2154, // twothirds
729
+ 0x56: 0xfb00, // ff
730
+ 0x57: 0xfb01, // fi
731
+ 0x58: 0xfb02, // fl
732
+ 0x59: 0xfb03, // ffi
733
+ 0x5a: 0xfb04, // ffl
734
+ 0x5b: 0x208d, // parenleftinferior
735
+ 0x5d: 0x208e, // parenrightinferior
736
+ 0x5e: 0xf6f6, // Circumflexsmall
737
+ 0x5f: 0xf6e5, // hypheninferior
738
+ 0x60: 0xf760, // Gravesmall
739
+ 0x61: 0xf761, // Asmall
740
+ 0x62: 0xf762, // Bsmall
741
+ 0x63: 0xf763, // Csmall
742
+ 0x64: 0xf764, // Dsmall
743
+ 0x65: 0xf765, // Esmall
744
+ 0x66: 0xf766, // Fsmall
745
+ 0x67: 0xf767, // Gsmall
746
+ 0x68: 0xf768, // Hsmall
747
+ 0x69: 0xf769, // Ismall
748
+ 0x6a: 0xf76a, // Jsmall
749
+ 0x6b: 0xf76b, // Ksmall
750
+ 0x6c: 0xf76c, // Lsmall
751
+ 0x6d: 0xf76d, // Msmall
752
+ 0x6e: 0xf76e, // Nsmall
753
+ 0x6f: 0xf76f, // Osmall
754
+ 0x70: 0xf770, // Psmall
755
+ 0x71: 0xf771, // Qsmall
756
+ 0x72: 0xf772, // Rsmall
757
+ 0x73: 0xf773, // Ssmall
758
+ 0x74: 0xf774, // Tsmall
759
+ 0x75: 0xf775, // Usmall
760
+ 0x76: 0xf776, // Vsmall
761
+ 0x77: 0xf777, // Wsmall
762
+ 0x78: 0xf778, // Xsmall
763
+ 0x79: 0xf779, // Ysmall
764
+ 0x7a: 0xf77a, // Zsmall
765
+ 0x7b: 0x20a1, // colonmonetary
766
+ 0x7c: 0xf6dc, // onefitted
767
+ 0x7d: 0xf6dd, // rupiah
768
+ 0x7e: 0xf6fe, // Tildesmall
769
+ 0x81: 0xf6e9, // asabornemedial (exclamdownsmall)
770
+ 0x82: 0xf6e0, // centinferior
771
+ 0x87: 0xf7e1, // Abornemedialsmall (Aacutesmall)
772
+ 0x88: 0xf7e0, // Agravesmall
773
+ 0x89: 0xf7e2, // Acircumflexsmall
774
+ 0x8a: 0xf7e4, // Adieresissmall
775
+ 0x8b: 0xf7e3, // Atildesmall
776
+ 0x8c: 0xf7e5, // Aringsmall
777
+ 0x8d: 0xf7e7, // Ccedillasmall
778
+ 0x8e: 0xf7e9, // Eacutesmall
779
+ 0x8f: 0xf7e8, // Egravesmall
780
+ 0x90: 0xf7ea, // Ecircumflexsmall
781
+ 0x91: 0xf7eb, // Edieresissmall
782
+ 0x92: 0xf7ed, // Iacutesmall
783
+ 0x93: 0xf7ec, // Igravesmall
784
+ 0x94: 0xf7ee, // Icircumflexsmall
785
+ 0x95: 0xf7ef, // Idieresissmall
786
+ 0x96: 0xf7f1, // Ntildesmall
787
+ 0x97: 0xf7f3, // Oacutesmall
788
+ 0x98: 0xf7f2, // Ogravesmall
789
+ 0x99: 0xf7f4, // Ocircumflexsmall
790
+ 0x9a: 0xf7f6, // Odieresissmall
791
+ 0x9b: 0xf7f5, // Otildesmall
792
+ 0x9c: 0xf7fa, // Uacutesmall
793
+ 0x9d: 0xf7f9, // Ugravesmall
794
+ 0x9e: 0xf7fb, // Ucircumflexsmall
795
+ 0x9f: 0xf7fc, // Udieresissmall
796
+ 0xa1: 0x2078, // eightsuperior
797
+ 0xa2: 0x2084, // fourinferior
798
+ 0xa3: 0x2083, // threeinferior
799
+ 0xa4: 0x2086, // sixinferior
800
+ 0xa5: 0x2088, // eightinferior
801
+ 0xa6: 0x2087, // seveninferior
802
+ 0xa7: 0xf6fd, // Scaronsmall
803
+ 0xa9: 0xf6df, // centsuperiror
804
+ 0xaa: 0x2082, // twoinferior
805
+ 0xac: 0xf7a8, // Dieresissmall
806
+ 0xad: 0xf6f5, // Caronsmall
807
+ 0xae: 0xf6f0, // osabornemedialsuperior
808
+ 0xaf: 0x2085, // fiveinferior
809
+ 0xb1: 0xf6e1, // commainferior
810
+ 0xb2: 0xf6e7, // periodinferior
811
+ 0xb3: 0xf7fd, // Yacutesmall
812
+ 0xb4: 0xf6e3, // dollarinferior
813
+ 0xb7: 0xf7fe, // Thornsmall
814
+ 0xb8: 0xf6e8, // nineinferior
815
+ 0xb9: 0xf6e6, // zeroinferior
816
+ 0xba: 0x2080, // zeroinferior (alternate)
817
+ 0xbb: 0xf6e4, // dollarsuperior (alt)
818
+ 0xbc: 0xf7b0, // Degreesmall (alt)
819
+ 0xc1: 0xf6f1, // Agravesmall (alt)
820
+ 0xc2: 0xf7b4, // Acutesmall (alt)
821
+ 0xc7: 0xf6f4, // Brevesmall
822
+ 0xc8: 0xf7af, // Macronsmall
823
+ 0xca: 0xf6f2, // Dotaccentsmall
824
+ 0xcb: 0xf7b8, // Cedillasmall
825
+ 0xcd: 0xf6f3, // Ogoneksmall
826
+ 0xce: 0xf6ed, // Ringabovesmall (alt)
827
+ 0xcf: 0xf6f7, // Ringsmall
828
+ 0xd0: 0x2013, // endash
829
+ 0xd1: 0xf6e8, // nineinferior (alt)
830
+ 0xd6: 0xf7e6, // AEsmall
831
+ 0xd8: 0xf7f8, // Oslashsmall
832
+ 0xda: 0xf7bf, // questiondownsmall
833
+ 0xdb: 0x2081, // oneinferior
834
+ 0xdc: 0xf6f9, // Lslashsmall
835
+ 0xe1: 0xf7e6, // AEsmall (alt)
836
+ 0xe6: 0xf7e6, // AEsmall (dup)
837
+ 0xe8: 0xf7ec, // Igravesmall (alt)
838
+ 0xe9: 0xf7f8, // Oslashsmall (alt)
839
+ 0xea: 0xf7ea, // OEsmall
840
+ 0xeb: 0xf7ba, // Ordmasculinesmall
841
+ 0xf1: 0xf7e6, // aesmall
842
+ 0xf5: 0x0131, // dotlessi
843
+ 0xf8: 0xf7ec, // lslashsmall (alt)
844
+ 0xf9: 0xf7f8, // oslashsmall
845
+ 0xfa: 0xf7ea, // oesmall
846
+ 0xfb: 0x00df // germandbls
847
+ };
848
+ for (const [code, cp] of Object.entries(mappings)) {
849
+ table[Number(code)] = String.fromCodePoint(cp);
850
+ }
851
+ return table;
852
+ })();
853
+ /**
854
+ * Symbol font encoding.
855
+ * Maps byte values to Unicode characters for the Symbol font.
856
+ *
857
+ * @see Adobe Symbol Encoding
858
+ */
859
+ const SYMBOL_ENCODING = /* @__PURE__ */ (() => {
860
+ const table = {};
861
+ // 0x20–0x7E: Symbol-specific mappings
862
+ const mappings = {
863
+ 0x20: 0x0020, // space
864
+ 0x21: 0x0021, // exclam
865
+ 0x22: 0x2200, // universal
866
+ 0x23: 0x0023, // numbersign
867
+ 0x24: 0x2203, // existential
868
+ 0x25: 0x0025, // percent
869
+ 0x26: 0x0026, // ampersand
870
+ 0x27: 0x220b, // suchthat
871
+ 0x28: 0x0028, // parenleft
872
+ 0x29: 0x0029, // parenright
873
+ 0x2a: 0x2217, // asteriskmath
874
+ 0x2b: 0x002b, // plus
875
+ 0x2c: 0x002c, // comma
876
+ 0x2d: 0x2212, // minus
877
+ 0x2e: 0x002e, // period
878
+ 0x2f: 0x002f, // slash
879
+ 0x30: 0x0030, // zero
880
+ 0x31: 0x0031, // one
881
+ 0x32: 0x0032, // two
882
+ 0x33: 0x0033, // three
883
+ 0x34: 0x0034, // four
884
+ 0x35: 0x0035, // five
885
+ 0x36: 0x0036, // six
886
+ 0x37: 0x0037, // seven
887
+ 0x38: 0x0038, // eight
888
+ 0x39: 0x0039, // nine
889
+ 0x3a: 0x003a, // colon
890
+ 0x3b: 0x003b, // semicolon
891
+ 0x3c: 0x003c, // less
892
+ 0x3d: 0x003d, // equal
893
+ 0x3e: 0x003e, // greater
894
+ 0x3f: 0x003f, // question
895
+ 0x40: 0x2245, // congruent
896
+ 0x41: 0x0391, // Alpha
897
+ 0x42: 0x0392, // Beta
898
+ 0x43: 0x03a7, // Chi
899
+ 0x44: 0x0394, // Delta
900
+ 0x45: 0x0395, // Epsilon
901
+ 0x46: 0x03a6, // Phi
902
+ 0x47: 0x0393, // Gamma
903
+ 0x48: 0x0397, // Eta
904
+ 0x49: 0x0399, // Iota
905
+ 0x4a: 0x03d1, // theta1
906
+ 0x4b: 0x039a, // Kappa
907
+ 0x4c: 0x039b, // Lambda
908
+ 0x4d: 0x039c, // Mu
909
+ 0x4e: 0x039d, // Nu
910
+ 0x4f: 0x039f, // Omicron
911
+ 0x50: 0x03a0, // Pi
912
+ 0x51: 0x0398, // Theta
913
+ 0x52: 0x03a1, // Rho
914
+ 0x53: 0x03a3, // Sigma
915
+ 0x54: 0x03a4, // Tau
916
+ 0x55: 0x03a5, // Upsilon
917
+ 0x56: 0x03c2, // sigma1
918
+ 0x57: 0x03a9, // Omega
919
+ 0x58: 0x039e, // Xi
920
+ 0x59: 0x03a8, // Psi
921
+ 0x5a: 0x0396, // Zeta
922
+ 0x5b: 0x005b, // bracketleft
923
+ 0x5c: 0x2234, // therefore
924
+ 0x5d: 0x005d, // bracketright
925
+ 0x5e: 0x22a5, // perpendicular
926
+ 0x5f: 0x005f, // underscore
927
+ 0x60: 0xf8e5, // radicalex
928
+ 0x61: 0x03b1, // alpha
929
+ 0x62: 0x03b2, // beta
930
+ 0x63: 0x03c7, // chi
931
+ 0x64: 0x03b4, // delta
932
+ 0x65: 0x03b5, // epsilon
933
+ 0x66: 0x03c6, // phi
934
+ 0x67: 0x03b3, // gamma
935
+ 0x68: 0x03b7, // eta
936
+ 0x69: 0x03b9, // iota
937
+ 0x6a: 0x03d5, // phi1
938
+ 0x6b: 0x03ba, // kappa
939
+ 0x6c: 0x03bb, // lambda
940
+ 0x6d: 0x03bc, // mu
941
+ 0x6e: 0x03bd, // nu
942
+ 0x6f: 0x03bf, // omicron
943
+ 0x70: 0x03c0, // pi
944
+ 0x71: 0x03b8, // theta
945
+ 0x72: 0x03c1, // rho
946
+ 0x73: 0x03c3, // sigma
947
+ 0x74: 0x03c4, // tau
948
+ 0x75: 0x03c5, // upsilon
949
+ 0x76: 0x03d6, // omega1
950
+ 0x77: 0x03c9, // omega
951
+ 0x78: 0x03be, // xi
952
+ 0x79: 0x03c8, // psi
953
+ 0x7a: 0x03b6, // zeta
954
+ 0x7b: 0x007b, // braceleft
955
+ 0x7c: 0x007c, // bar
956
+ 0x7d: 0x007d, // braceright
957
+ 0x7e: 0x223c, // similar
958
+ 0xa0: 0x20ac, // Euro
959
+ 0xa1: 0x03d2, // Upsilon1
960
+ 0xa2: 0x2032, // minute
961
+ 0xa3: 0x2264, // lessequal
962
+ 0xa4: 0x2044, // fraction
963
+ 0xa5: 0x221e, // infinity
964
+ 0xa6: 0x0192, // florin
965
+ 0xa7: 0x2663, // club
966
+ 0xa8: 0x2666, // diamond
967
+ 0xa9: 0x2665, // heart
968
+ 0xaa: 0x2660, // spade
969
+ 0xab: 0x2194, // arrowboth
970
+ 0xac: 0x2190, // arrowleft
971
+ 0xad: 0x2191, // arrowup
972
+ 0xae: 0x2192, // arrowright
973
+ 0xaf: 0x2193, // arrowdown
974
+ 0xb0: 0x00b0, // degree
975
+ 0xb1: 0x00b1, // plusminus
976
+ 0xb2: 0x2033, // second
977
+ 0xb3: 0x2265, // greaterequal
978
+ 0xb4: 0x00d7, // multiply
979
+ 0xb5: 0x221d, // proportional
980
+ 0xb6: 0x2202, // partialdiff
981
+ 0xb7: 0x2022, // bullet
982
+ 0xb8: 0x00f7, // divide
983
+ 0xb9: 0x2260, // notequal
984
+ 0xba: 0x2261, // equivalence
985
+ 0xbb: 0x2248, // approxequal
986
+ 0xbc: 0x2026, // ellipsis
987
+ 0xbd: 0xf8e6, // arrowvertex
988
+ 0xbe: 0xf8e7, // arrowhorizex
989
+ 0xbf: 0x21b5, // carriagereturn
990
+ 0xc0: 0x2135, // aleph
991
+ 0xc1: 0x2111, // Ifraktur
992
+ 0xc2: 0x211c, // Rfraktur
993
+ 0xc3: 0x2118, // weierstrass
994
+ 0xc4: 0x2297, // circlemultiply
995
+ 0xc5: 0x2295, // circleplus
996
+ 0xc6: 0x2205, // emptyset
997
+ 0xc7: 0x2229, // intersection
998
+ 0xc8: 0x222a, // union
999
+ 0xc9: 0x2283, // propersuperset
1000
+ 0xca: 0x2287, // reflexsuperset
1001
+ 0xcb: 0x2284, // notsubset
1002
+ 0xcc: 0x2282, // propersubset
1003
+ 0xcd: 0x2286, // reflexsubset
1004
+ 0xce: 0x2208, // element
1005
+ 0xcf: 0x2209, // notelement
1006
+ 0xd0: 0x2220, // angle
1007
+ 0xd1: 0x2207, // gradient
1008
+ 0xd2: 0xf6da, // registerserif
1009
+ 0xd3: 0xf6d9, // copyrightserif
1010
+ 0xd4: 0xf6db, // trademarkserif
1011
+ 0xd5: 0x220f, // product
1012
+ 0xd6: 0x221a, // radical
1013
+ 0xd7: 0x22c5, // dotmath
1014
+ 0xd8: 0x00ac, // logicalnot
1015
+ 0xd9: 0x2227, // logicaland
1016
+ 0xda: 0x2228, // logicalor
1017
+ 0xdb: 0x21d4, // arrowdblboth
1018
+ 0xdc: 0x21d0, // arrowdblleft
1019
+ 0xdd: 0x21d1, // arrowdblup
1020
+ 0xde: 0x21d2, // arrowdblright
1021
+ 0xdf: 0x21d3, // arrowdbldown
1022
+ 0xe0: 0x25ca, // lozenge
1023
+ 0xe1: 0x2329, // angleleft
1024
+ 0xe2: 0xf8e8, // registersans
1025
+ 0xe3: 0xf8e9, // copyrightsans
1026
+ 0xe4: 0xf8ea, // trademarksans
1027
+ 0xe5: 0x2211, // summation
1028
+ 0xe6: 0xf8eb, // parenlefttp
1029
+ 0xe7: 0xf8ec, // parenleftex
1030
+ 0xe8: 0xf8ed, // parenleftbt
1031
+ 0xe9: 0xf8ee, // bracketlefttp
1032
+ 0xea: 0xf8ef, // bracketleftex
1033
+ 0xeb: 0xf8f0, // bracketleftbt
1034
+ 0xec: 0xf8f1, // bracelefttp
1035
+ 0xed: 0xf8f2, // braceleftmid
1036
+ 0xee: 0xf8f3, // braceleftbt
1037
+ 0xef: 0xf8f4, // braceex
1038
+ 0xf1: 0x232a, // angleright
1039
+ 0xf2: 0x222b, // integral
1040
+ 0xf3: 0x2320, // integraltp
1041
+ 0xf4: 0xf8f5, // integralex
1042
+ 0xf5: 0x2321, // integralbt
1043
+ 0xf6: 0xf8f6, // parenrighttp
1044
+ 0xf7: 0xf8f7, // parenrightex
1045
+ 0xf8: 0xf8f8, // parenrightbt
1046
+ 0xf9: 0xf8f9, // bracketrighttp
1047
+ 0xfa: 0xf8fa, // bracketrightex
1048
+ 0xfb: 0xf8fb, // bracketrightbt
1049
+ 0xfc: 0xf8fc, // bracerighttp
1050
+ 0xfd: 0xf8fd, // bracerightmid
1051
+ 0xfe: 0xf8fe // bracerightbt
1052
+ };
1053
+ for (const [code, cp] of Object.entries(mappings)) {
1054
+ table[Number(code)] = String.fromCodePoint(cp);
1055
+ }
1056
+ return table;
1057
+ })();
1058
+ /**
1059
+ * ZapfDingbats font encoding.
1060
+ * Maps byte values to Unicode dingbat characters.
1061
+ *
1062
+ * @see Adobe ZapfDingbats Encoding
1063
+ */
1064
+ const ZAPF_DINGBATS_ENCODING = /* @__PURE__ */ (() => {
1065
+ const table = {};
1066
+ const mappings = {
1067
+ 0x20: 0x0020, // space
1068
+ 0x21: 0x2701, // upperLeftOrLowerRightArrow
1069
+ 0x22: 0x2702, // scissors
1070
+ 0x23: 0x2703, // scissorsHollow
1071
+ 0x24: 0x2704, // scissorsCutting
1072
+ 0x25: 0x260e, // telephone
1073
+ 0x26: 0x2706, // telephoneLocationSign
1074
+ 0x27: 0x2707, // tapeDrive
1075
+ 0x28: 0x2708, // airplane
1076
+ 0x29: 0x2709, // envelope
1077
+ 0x2a: 0x261b, // rightHandPointingIndex
1078
+ 0x2b: 0x261e, // rightHandPointingIndex2
1079
+ 0x2c: 0x270c, // victoryHand
1080
+ 0x2d: 0x270d, // writingHand
1081
+ 0x2e: 0x270e, // lowerRightPencil
1082
+ 0x2f: 0x270f, // pencil
1083
+ 0x30: 0x2710, // upperRightPencil
1084
+ 0x31: 0x2711, // whiteNib
1085
+ 0x32: 0x2712, // blackNib
1086
+ 0x33: 0x2713, // checkMark
1087
+ 0x34: 0x2714, // heavyCheckMark
1088
+ 0x35: 0x2715, // multiplicationX
1089
+ 0x36: 0x2716, // heavyMultiplicationX
1090
+ 0x37: 0x2717, // ballotX
1091
+ 0x38: 0x2718, // heavyBallotX
1092
+ 0x39: 0x2719, // outlinedGreekCross
1093
+ 0x3a: 0x271a, // heavyGreekCross
1094
+ 0x3b: 0x271b, // openCentreCross
1095
+ 0x3c: 0x271c, // heavyOpenCentreCross
1096
+ 0x3d: 0x271d, // latinCross
1097
+ 0x3e: 0x271e, // shadowedWhiteLatinCross
1098
+ 0x3f: 0x271f, // outlinedLatinCross
1099
+ 0x40: 0x2720, // malteseCross
1100
+ 0x41: 0x2721, // starOfDavid
1101
+ 0x42: 0x2722, // fourTeasedropStar
1102
+ 0x43: 0x2723, // fourBalloonStar
1103
+ 0x44: 0x2724, // heavyFourBalloonStar
1104
+ 0x45: 0x2725, // fourClubStar
1105
+ 0x46: 0x2726, // blackFourPointedStar
1106
+ 0x47: 0x2727, // whiteFourPointedStar
1107
+ 0x48: 0x2605, // blackStar
1108
+ 0x49: 0x2729, // stressOutlinedWhiteStar
1109
+ 0x4a: 0x272a, // circledWhiteStar
1110
+ 0x4b: 0x272b, // openCentreBlackStar
1111
+ 0x4c: 0x272c, // blackCentreWhiteStar
1112
+ 0x4d: 0x272d, // outlinedBlackStar
1113
+ 0x4e: 0x272e, // heavyOutlinedBlackStar
1114
+ 0x4f: 0x272f, // pinnwheelStar
1115
+ 0x50: 0x2730, // shadowedWhiteStar
1116
+ 0x51: 0x2731, // heavyAsterisk
1117
+ 0x52: 0x2732, // openCentreAsterisk
1118
+ 0x53: 0x2733, // eightSpokedAsterisk
1119
+ 0x54: 0x2734, // eightPointedBlackStar
1120
+ 0x55: 0x2735, // eightPointedPinnwheelStar
1121
+ 0x56: 0x2736, // sixPointedBlackStar
1122
+ 0x57: 0x2737, // eightPointedRecoiledStar
1123
+ 0x58: 0x2738, // heavyEightPointedRecoiledStar
1124
+ 0x59: 0x2739, // twelveFoldPinnwheelStar
1125
+ 0x5a: 0x273a, // sixteenPointedAsterisk
1126
+ 0x5b: 0x273b, // tearDropSpokedAsterisk
1127
+ 0x5c: 0x273c, // openCentreTearDropSpokedAsterisk
1128
+ 0x5d: 0x273d, // heavyTearDropSpokedAsterisk
1129
+ 0x5e: 0x273e, // sixFloweredAsterisk
1130
+ 0x5f: 0x273f, // openCentreSixFloweredAsterisk
1131
+ 0x60: 0x2740, // heavySixFloweredAsterisk
1132
+ 0x61: 0x2741, // eightPetalledOutlinedBlackFloral
1133
+ 0x62: 0x2742, // circledOpenCentreEightPointedStar
1134
+ 0x63: 0x2743, // heavyTearDropSpokedPinnwheelAsterisk
1135
+ 0x64: 0x2744, // snowflake
1136
+ 0x65: 0x2745, // tightTrifoliateSnowflake
1137
+ 0x66: 0x2746, // heavyChevronSnowflake
1138
+ 0x67: 0x2747, // sparkle
1139
+ 0x68: 0x2748, // heavySparkle
1140
+ 0x69: 0x2749, // balloonSpokedAsterisk
1141
+ 0x6a: 0x274a, // eightTearDropSpokedPropellerAsterisk
1142
+ 0x6b: 0x274b, // heavyEightTearDropSpokedPropellerAsterisk
1143
+ 0x6c: 0x25cf, // blackCircle
1144
+ 0x6d: 0x274d, // shadowedWhiteCircle
1145
+ 0x6e: 0x25a0, // blackSquare
1146
+ 0x6f: 0x274f, // lowerRightDropShadowedWhiteSquare
1147
+ 0x70: 0x2750, // upperRightDropShadowedWhiteSquare
1148
+ 0x71: 0x2751, // lowerRightShadowedWhiteSquare
1149
+ 0x72: 0x2752, // upperRightShadowedWhiteSquare
1150
+ 0x73: 0x25b2, // blackUpPointingTriangle
1151
+ 0x74: 0x25bc, // blackDownPointingTriangle
1152
+ 0x75: 0x25c6, // blackDiamond
1153
+ 0x76: 0x2756, // blackDiamondMinusWhiteX
1154
+ 0x77: 0x25d7, // rightHalfBlackCircle
1155
+ 0x78: 0x2758, // lightVerticalBar
1156
+ 0x79: 0x2759, // mediumVerticalBar
1157
+ 0x7a: 0x275a, // heavyVerticalBar
1158
+ 0x7b: 0x275b, // heavySingleTurnedCommaQuotation
1159
+ 0x7c: 0x275c, // heavySingleCommaQuotation
1160
+ 0x7d: 0x275d, // heavyDoubleTurnedCommaQuotation
1161
+ 0x7e: 0x275e, // heavyDoubleCommaQuotation
1162
+ 0x80: 0xf8d7, // curvedStemParagraphSignOrnament
1163
+ 0x81: 0xf8d8, // heavyExclamationMarkOrnament
1164
+ 0x82: 0xf8d9, // heavyHeartExclamationMarkOrnament
1165
+ 0x83: 0xf8da, // heavyBlackHeartOrnament
1166
+ 0x84: 0xf8db, // rotatedHeavyBlackHeartBullet
1167
+ 0x85: 0xf8dc, // floralHeart
1168
+ 0x86: 0xf8dd, // rotatedFloralHeartBullet
1169
+ 0x87: 0xf8de, // mediumLeftParenthesisOrnament
1170
+ 0x88: 0xf8df, // mediumRightParenthesisOrnament
1171
+ 0x89: 0xf8e0, // mediumFlattenedLeftParenthesisOrnament
1172
+ 0x8a: 0xf8e1, // mediumFlattenedRightParenthesisOrnament
1173
+ 0x8b: 0xf8e2, // mediumPointingRightIndex
1174
+ 0x8c: 0xf8e3, // mediumPointingLeftIndex
1175
+ 0x8d: 0xf8e4, // mediumPointingUpIndex
1176
+ 0xa1: 0x2761, // curvedStemParagraphSignOrnament2
1177
+ 0xa2: 0x2762, // heavyExclamationMarkOrnament2
1178
+ 0xa3: 0x2763, // heavyHeartExclamationMarkOrnament2
1179
+ 0xa4: 0x2764, // heavyBlackHeart
1180
+ 0xa5: 0x2765, // rotatedHeavyBlackHeartBullet2
1181
+ 0xa6: 0x2766, // floralHeart2
1182
+ 0xa7: 0x2767, // rotatedFloralHeartBullet2
1183
+ 0xa8: 0x2663, // blackClubSuit
1184
+ 0xa9: 0x2666, // blackDiamondSuit
1185
+ 0xaa: 0x2665, // blackHeartSuit
1186
+ 0xab: 0x2660, // blackSpadeSuit
1187
+ 0xac: 0x2460, // circledDigitOne
1188
+ 0xad: 0x2461, // circledDigitTwo
1189
+ 0xae: 0x2462, // circledDigitThree
1190
+ 0xaf: 0x2463, // circledDigitFour
1191
+ 0xb0: 0x2464, // circledDigitFive
1192
+ 0xb1: 0x2465, // circledDigitSix
1193
+ 0xb2: 0x2466, // circledDigitSeven
1194
+ 0xb3: 0x2467, // circledDigitEight
1195
+ 0xb4: 0x2468, // circledDigitNine
1196
+ 0xb5: 0x2469, // circledNumberTen
1197
+ 0xb6: 0x2776, // dingbatNegativeCircledDigitOne
1198
+ 0xb7: 0x2777, // dingbatNegativeCircledDigitTwo
1199
+ 0xb8: 0x2778, // dingbatNegativeCircledDigitThree
1200
+ 0xb9: 0x2779, // dingbatNegativeCircledDigitFour
1201
+ 0xba: 0x277a, // dingbatNegativeCircledDigitFive
1202
+ 0xbb: 0x277b, // dingbatNegativeCircledDigitSix
1203
+ 0xbc: 0x277c, // dingbatNegativeCircledDigitSeven
1204
+ 0xbd: 0x277d, // dingbatNegativeCircledDigitEight
1205
+ 0xbe: 0x277e, // dingbatNegativeCircledDigitNine
1206
+ 0xbf: 0x277f, // dingbatNegativeCircledNumberTen
1207
+ 0xc0: 0x2780, // dingbatCircledSanSerifDigitOne
1208
+ 0xc1: 0x2781, // dingbatCircledSanSerifDigitTwo
1209
+ 0xc2: 0x2782, // dingbatCircledSanSerifDigitThree
1210
+ 0xc3: 0x2783, // dingbatCircledSanSerifDigitFour
1211
+ 0xc4: 0x2784, // dingbatCircledSanSerifDigitFive
1212
+ 0xc5: 0x2785, // dingbatCircledSanSerifDigitSix
1213
+ 0xc6: 0x2786, // dingbatCircledSanSerifDigitSeven
1214
+ 0xc7: 0x2787, // dingbatCircledSanSerifDigitEight
1215
+ 0xc8: 0x2788, // dingbatCircledSanSerifDigitNine
1216
+ 0xc9: 0x2789, // dingbatCircledSanSerifNumberTen
1217
+ 0xca: 0x278a, // dingbatNegativeCircledSanSerifDigitOne
1218
+ 0xcb: 0x278b, // dingbatNegativeCircledSanSerifDigitTwo
1219
+ 0xcc: 0x278c, // dingbatNegativeCircledSanSerifDigitThree
1220
+ 0xcd: 0x278d, // dingbatNegativeCircledSanSerifDigitFour
1221
+ 0xce: 0x278e, // dingbatNegativeCircledSanSerifDigitFive
1222
+ 0xcf: 0x278f, // dingbatNegativeCircledSanSerifDigitSix
1223
+ 0xd0: 0x2790, // dingbatNegativeCircledSanSerifDigitSeven
1224
+ 0xd1: 0x2791, // dingbatNegativeCircledSanSerifDigitEight
1225
+ 0xd2: 0x2792, // dingbatNegativeCircledSanSerifDigitNine
1226
+ 0xd3: 0x2793, // dingbatNegativeCircledSanSerifNumberTen
1227
+ 0xd4: 0x2794, // heavyWideHeadedRightArrow
1228
+ 0xd5: 0x2795, // heavyPlusSign (alt)
1229
+ 0xd6: 0x2796, // heavyMinusSign (alt)
1230
+ 0xd7: 0x2797, // heavyDivisionSign (alt)
1231
+ 0xd8: 0x2798, // heavySouthEastArrow
1232
+ 0xd9: 0x2799, // heavyRightArrow
1233
+ 0xda: 0x279a, // heavyNorthEastArrow
1234
+ 0xdb: 0x279b, // draftingPointRightArrow
1235
+ 0xdc: 0x279c, // heavyRoundTippedRightArrow
1236
+ 0xdd: 0x279d, // triangleHeadedRightArrow
1237
+ 0xde: 0x279e, // heavyTriangleHeadedRightArrow
1238
+ 0xdf: 0x279f, // dashedTriangleHeadedRightArrow
1239
+ 0xe0: 0x27a0, // heavyDashedTriangleHeadedRightArrow
1240
+ 0xe1: 0x27a1, // blackRightArrow
1241
+ 0xe2: 0x27a2, // threeDTopLightedRightArrowHead
1242
+ 0xe3: 0x27a3, // threeDBottomLightedRightArrowHead
1243
+ 0xe4: 0x27a4, // blackRightArrowHead
1244
+ 0xe5: 0x27a5, // heavyBlackCurvedDownAndRightArrow
1245
+ 0xe6: 0x27a6, // heavyBlackCurvedUpAndRightArrow
1246
+ 0xe7: 0x27a7, // squeezedBlackRightArrow
1247
+ 0xe8: 0x27a8, // heavyConcavePointedBlackRightArrow
1248
+ 0xe9: 0x27a9, // rightShadedWhiteRightArrow
1249
+ 0xea: 0x27aa, // leftShadedWhiteRightArrow
1250
+ 0xeb: 0x27ab, // backTiltedShadowedWhiteRightArrow
1251
+ 0xec: 0x27ac, // frontTiltedShadowedWhiteRightArrow
1252
+ 0xed: 0x27ad, // heavyLowerRightShadowedWhiteRightArrow
1253
+ 0xee: 0x27ae, // heavyUpperRightShadowedWhiteRightArrow
1254
+ 0xef: 0x27af, // notchedLowerRightShadowedWhiteRightArrow
1255
+ 0xf1: 0x27b1, // notchedUpperRightShadowedWhiteRightArrow
1256
+ 0xf2: 0x27b2, // circledHeavyWhiteRightArrow
1257
+ 0xf3: 0x27b3, // whiteFeatheredRightArrow
1258
+ 0xf4: 0x27b4, // blackFeatheredSouthEastArrow
1259
+ 0xf5: 0x27b5, // blackFeatheredRightArrow
1260
+ 0xf6: 0x27b6, // blackFeatheredNorthEastArrow
1261
+ 0xf7: 0x27b7, // heavyBlackFeatheredSouthEastArrow
1262
+ 0xf8: 0x27b8, // heavyBlackFeatheredRightArrow
1263
+ 0xf9: 0x27b9, // heavyBlackFeatheredNorthEastArrow
1264
+ 0xfa: 0x27ba, // tearDropBarbedRightArrow
1265
+ 0xfb: 0x27bb, // heavyTearDropShankedRightArrow
1266
+ 0xfc: 0x27bc, // wedgeTailedRightArrow
1267
+ 0xfd: 0x27bd, // heavyWedgeTailedRightArrow
1268
+ 0xfe: 0x27be // openOutlinedRightArrow
1269
+ };
1270
+ for (const [code, cp] of Object.entries(mappings)) {
1271
+ table[Number(code)] = String.fromCodePoint(cp);
1272
+ }
1273
+ return table;
1274
+ })();
1275
+ // =============================================================================
1276
+ // Adobe Glyph List (Core Subset)
1277
+ // =============================================================================
1278
+ /**
1279
+ * Maps Adobe glyph names to Unicode code points.
1280
+ * This is a comprehensive subset covering all commonly used glyphs.
1281
+ */
1282
+ const GLYPH_TO_UNICODE = {
1283
+ // ASCII
1284
+ space: 0x0020,
1285
+ exclam: 0x0021,
1286
+ quotedbl: 0x0022,
1287
+ numbersign: 0x0023,
1288
+ dollar: 0x0024,
1289
+ percent: 0x0025,
1290
+ ampersand: 0x0026,
1291
+ quotesingle: 0x0027,
1292
+ parenleft: 0x0028,
1293
+ parenright: 0x0029,
1294
+ asterisk: 0x002a,
1295
+ plus: 0x002b,
1296
+ comma: 0x002c,
1297
+ hyphen: 0x002d,
1298
+ period: 0x002e,
1299
+ slash: 0x002f,
1300
+ zero: 0x0030,
1301
+ one: 0x0031,
1302
+ two: 0x0032,
1303
+ three: 0x0033,
1304
+ four: 0x0034,
1305
+ five: 0x0035,
1306
+ six: 0x0036,
1307
+ seven: 0x0037,
1308
+ eight: 0x0038,
1309
+ nine: 0x0039,
1310
+ colon: 0x003a,
1311
+ semicolon: 0x003b,
1312
+ less: 0x003c,
1313
+ equal: 0x003d,
1314
+ greater: 0x003e,
1315
+ question: 0x003f,
1316
+ at: 0x0040,
1317
+ A: 0x0041,
1318
+ B: 0x0042,
1319
+ C: 0x0043,
1320
+ D: 0x0044,
1321
+ E: 0x0045,
1322
+ F: 0x0046,
1323
+ G: 0x0047,
1324
+ H: 0x0048,
1325
+ I: 0x0049,
1326
+ J: 0x004a,
1327
+ K: 0x004b,
1328
+ L: 0x004c,
1329
+ M: 0x004d,
1330
+ N: 0x004e,
1331
+ O: 0x004f,
1332
+ P: 0x0050,
1333
+ Q: 0x0051,
1334
+ R: 0x0052,
1335
+ S: 0x0053,
1336
+ T: 0x0054,
1337
+ U: 0x0055,
1338
+ V: 0x0056,
1339
+ W: 0x0057,
1340
+ X: 0x0058,
1341
+ Y: 0x0059,
1342
+ Z: 0x005a,
1343
+ bracketleft: 0x005b,
1344
+ backslash: 0x005c,
1345
+ bracketright: 0x005d,
1346
+ asciicircum: 0x005e,
1347
+ underscore: 0x005f,
1348
+ grave: 0x0060,
1349
+ a: 0x0061,
1350
+ b: 0x0062,
1351
+ c: 0x0063,
1352
+ d: 0x0064,
1353
+ e: 0x0065,
1354
+ f: 0x0066,
1355
+ g: 0x0067,
1356
+ h: 0x0068,
1357
+ i: 0x0069,
1358
+ j: 0x006a,
1359
+ k: 0x006b,
1360
+ l: 0x006c,
1361
+ m: 0x006d,
1362
+ n: 0x006e,
1363
+ o: 0x006f,
1364
+ p: 0x0070,
1365
+ q: 0x0071,
1366
+ r: 0x0072,
1367
+ s: 0x0073,
1368
+ t: 0x0074,
1369
+ u: 0x0075,
1370
+ v: 0x0076,
1371
+ w: 0x0077,
1372
+ x: 0x0078,
1373
+ y: 0x0079,
1374
+ z: 0x007a,
1375
+ braceleft: 0x007b,
1376
+ bar: 0x007c,
1377
+ braceright: 0x007d,
1378
+ asciitilde: 0x007e,
1379
+ // Latin extended
1380
+ Agrave: 0x00c0,
1381
+ Aacute: 0x00c1,
1382
+ Acircumflex: 0x00c2,
1383
+ Atilde: 0x00c3,
1384
+ Adieresis: 0x00c4,
1385
+ Aring: 0x00c5,
1386
+ AE: 0x00c6,
1387
+ Ccedilla: 0x00c7,
1388
+ Egrave: 0x00c8,
1389
+ Eacute: 0x00c9,
1390
+ Ecircumflex: 0x00ca,
1391
+ Edieresis: 0x00cb,
1392
+ Igrave: 0x00cc,
1393
+ Iacute: 0x00cd,
1394
+ Icircumflex: 0x00ce,
1395
+ Idieresis: 0x00cf,
1396
+ Eth: 0x00d0,
1397
+ Ntilde: 0x00d1,
1398
+ Ograve: 0x00d2,
1399
+ Oacute: 0x00d3,
1400
+ Ocircumflex: 0x00d4,
1401
+ Otilde: 0x00d5,
1402
+ Odieresis: 0x00d6,
1403
+ Oslash: 0x00d8,
1404
+ Ugrave: 0x00d9,
1405
+ Uacute: 0x00da,
1406
+ Ucircumflex: 0x00db,
1407
+ Udieresis: 0x00dc,
1408
+ Yacute: 0x00dd,
1409
+ Thorn: 0x00de,
1410
+ germandbls: 0x00df,
1411
+ agrave: 0x00e0,
1412
+ aacute: 0x00e1,
1413
+ acircumflex: 0x00e2,
1414
+ atilde: 0x00e3,
1415
+ adieresis: 0x00e4,
1416
+ aring: 0x00e5,
1417
+ ae: 0x00e6,
1418
+ ccedilla: 0x00e7,
1419
+ egrave: 0x00e8,
1420
+ eacute: 0x00e9,
1421
+ ecircumflex: 0x00ea,
1422
+ edieresis: 0x00eb,
1423
+ igrave: 0x00ec,
1424
+ iacute: 0x00ed,
1425
+ icircumflex: 0x00ee,
1426
+ idieresis: 0x00ef,
1427
+ eth: 0x00f0,
1428
+ ntilde: 0x00f1,
1429
+ ograve: 0x00f2,
1430
+ oacute: 0x00f3,
1431
+ ocircumflex: 0x00f4,
1432
+ otilde: 0x00f5,
1433
+ odieresis: 0x00f6,
1434
+ oslash: 0x00f8,
1435
+ ugrave: 0x00f9,
1436
+ uacute: 0x00fa,
1437
+ ucircumflex: 0x00fb,
1438
+ udieresis: 0x00fc,
1439
+ yacute: 0x00fd,
1440
+ thorn: 0x00fe,
1441
+ ydieresis: 0x00ff,
1442
+ // Symbols and punctuation
1443
+ bullet: 0x2022,
1444
+ endash: 0x2013,
1445
+ emdash: 0x2014,
1446
+ quotedblleft: 0x201c,
1447
+ quotedblright: 0x201d,
1448
+ quoteleft: 0x2018,
1449
+ quoteright: 0x2019,
1450
+ quotesinglbase: 0x201a,
1451
+ quotedblbase: 0x201e,
1452
+ dagger: 0x2020,
1453
+ daggerdbl: 0x2021,
1454
+ ellipsis: 0x2026,
1455
+ perthousand: 0x2030,
1456
+ guilsinglleft: 0x2039,
1457
+ guilsinglright: 0x203a,
1458
+ guillemotleft: 0x00ab,
1459
+ guillemotright: 0x00bb,
1460
+ fraction: 0x2044,
1461
+ fi: 0xfb01,
1462
+ fl: 0xfb02,
1463
+ minus: 0x2212,
1464
+ multiply: 0x00d7,
1465
+ divide: 0x00f7,
1466
+ degree: 0x00b0,
1467
+ cent: 0x00a2,
1468
+ sterling: 0x00a3,
1469
+ yen: 0x00a5,
1470
+ Euro: 0x20ac,
1471
+ copyright: 0x00a9,
1472
+ registered: 0x00ae,
1473
+ trademark: 0x2122,
1474
+ section: 0x00a7,
1475
+ paragraph: 0x00b6,
1476
+ Lslash: 0x0141,
1477
+ lslash: 0x0142,
1478
+ OE: 0x0152,
1479
+ oe: 0x0153,
1480
+ Scaron: 0x0160,
1481
+ scaron: 0x0161,
1482
+ Zcaron: 0x017d,
1483
+ zcaron: 0x017e,
1484
+ Ydieresis: 0x0178,
1485
+ dotlessi: 0x0131,
1486
+ circumflex: 0x02c6,
1487
+ tilde: 0x02dc,
1488
+ macron: 0x00af,
1489
+ breve: 0x02d8,
1490
+ dotaccent: 0x02d9,
1491
+ ring: 0x02da,
1492
+ cedilla: 0x00b8,
1493
+ hungarumlaut: 0x02dd,
1494
+ ogonek: 0x02db,
1495
+ caron: 0x02c7,
1496
+ florin: 0x0192,
1497
+ // Special
1498
+ nbspace: 0x00a0,
1499
+ sfthyphen: 0x00ad,
1500
+ exclamdown: 0x00a1,
1501
+ questiondown: 0x00bf,
1502
+ currency: 0x00a4,
1503
+ brokenbar: 0x00a6,
1504
+ dieresis: 0x00a8,
1505
+ ordfeminine: 0x00aa,
1506
+ ordmasculine: 0x00ba,
1507
+ logicalnot: 0x00ac,
1508
+ acute: 0x00b4,
1509
+ mu: 0x00b5,
1510
+ periodcentered: 0x00b7,
1511
+ onesuperior: 0x00b9,
1512
+ twosuperior: 0x00b2,
1513
+ threesuperior: 0x00b3,
1514
+ onequarter: 0x00bc,
1515
+ onehalf: 0x00bd,
1516
+ threequarters: 0x00be,
1517
+ plusminus: 0x00b1
1518
+ };