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