pdf-parser.js 3.0.8 → 4.5.1

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 (240) hide show
  1. package/README.md +105 -54
  2. package/dist/{afm-widths-Dxucrg7D.js → afm-widths-BTu0IDp2.cjs} +1517 -4
  3. package/dist/{afm-widths-DyDq56Ph.d.cts → afm-widths-CneRyu5l.d.cts} +1 -1
  4. package/dist/{afm-widths-DyDq56Ph.d.ts → afm-widths-CneRyu5l.d.ts} +1 -1
  5. package/dist/{afm-widths-BoeTOK2r.cjs → afm-widths-De_QMWgC.js} +1416 -51
  6. package/dist/afm-widths.cjs +1 -1
  7. package/dist/afm-widths.d.cts +1 -1
  8. package/dist/afm-widths.d.ts +1 -1
  9. package/dist/afm-widths.js +1 -1
  10. package/dist/annotations.cjs +104 -0
  11. package/dist/annotations.d.cts +9 -0
  12. package/dist/annotations.d.ts +9 -0
  13. package/dist/annotations.js +103 -0
  14. package/dist/attachments.cjs +65 -0
  15. package/dist/attachments.d.cts +8 -0
  16. package/dist/attachments.d.ts +8 -0
  17. package/dist/attachments.js +64 -0
  18. package/dist/builtin-encoding.cjs +221 -0
  19. package/dist/builtin-encoding.d.cts +8 -0
  20. package/dist/builtin-encoding.d.ts +8 -0
  21. package/dist/builtin-encoding.js +220 -0
  22. package/dist/bytes/flate.cjs +1 -1
  23. package/dist/bytes/flate.js +1 -1
  24. package/dist/cff.cjs +14 -0
  25. package/dist/cff.d.cts +4 -1
  26. package/dist/cff.d.ts +4 -1
  27. package/dist/cff.js +12 -1
  28. package/dist/cmap-table.cjs +76 -13
  29. package/dist/cmap-table.d.cts +9 -1
  30. package/dist/cmap-table.d.ts +9 -1
  31. package/dist/cmap-table.js +77 -15
  32. package/dist/codec.cjs +1 -1
  33. package/dist/codec.d.cts +134 -0
  34. package/dist/codec.d.ts +134 -0
  35. package/dist/codec.js +1 -1
  36. package/dist/content-read.cjs +1 -1
  37. package/dist/content-read.d.cts +3 -3
  38. package/dist/content-read.d.ts +3 -3
  39. package/dist/content-read.js +1 -1
  40. package/dist/content-write.cjs +32 -10
  41. package/dist/content-write.d.cts +12 -5
  42. package/dist/content-write.d.ts +12 -5
  43. package/dist/content-write.js +32 -10
  44. package/dist/crypto/random.cjs +9 -0
  45. package/dist/crypto/random.d.cts +4 -0
  46. package/dist/crypto/random.d.ts +4 -0
  47. package/dist/crypto/random.js +8 -0
  48. package/dist/diagnostics.d.cts +1 -1
  49. package/dist/diagnostics.d.ts +1 -1
  50. package/dist/document.cjs +12 -3
  51. package/dist/document.d.cts +3 -1
  52. package/dist/document.d.ts +3 -1
  53. package/dist/document.js +12 -3
  54. package/dist/{embedded-font-fREdbxnr.d.ts → embedded-font-B4p9a3O3.d.ts} +3 -1
  55. package/dist/{embedded-font-BU6Jgcof.d.cts → embedded-font-oc65VGlr.d.cts} +3 -1
  56. package/dist/embedded-font-write.cjs +1 -1
  57. package/dist/embedded-font-write.d.cts +3 -3
  58. package/dist/embedded-font-write.d.ts +3 -3
  59. package/dist/embedded-font-write.js +1 -1
  60. package/dist/embedded-font.cjs +46 -15
  61. package/dist/embedded-font.d.cts +1 -1
  62. package/dist/embedded-font.d.ts +1 -1
  63. package/dist/embedded-font.js +46 -15
  64. package/dist/encoding.cjs +10 -1
  65. package/dist/encoding.d.cts +10 -1
  66. package/dist/encoding.d.ts +10 -1
  67. package/dist/encoding.js +2 -2
  68. package/dist/encrypt-write.cjs +234 -0
  69. package/dist/encrypt-write.d.cts +31 -0
  70. package/dist/encrypt-write.d.ts +31 -0
  71. package/dist/encrypt-write.js +231 -0
  72. package/dist/encrypt.cjs +51 -21
  73. package/dist/encrypt.d.cts +19 -3
  74. package/dist/encrypt.d.ts +19 -3
  75. package/dist/encrypt.js +36 -22
  76. package/dist/filters.cjs +18 -14
  77. package/dist/filters.d.cts +1 -1
  78. package/dist/filters.d.ts +1 -1
  79. package/dist/filters.js +18 -14
  80. package/dist/font-read.cjs +68 -13
  81. package/dist/font-read.d.cts +1 -1
  82. package/dist/font-read.d.ts +1 -1
  83. package/dist/font-read.js +69 -14
  84. package/dist/font-registry.cjs +1 -1
  85. package/dist/font-registry.d.cts +4 -4
  86. package/dist/font-registry.d.ts +4 -4
  87. package/dist/font-registry.js +1 -1
  88. package/dist/font-substitutes.d.cts +1 -1
  89. package/dist/font-substitutes.d.ts +1 -1
  90. package/dist/font-tables.cjs +31 -0
  91. package/dist/font-tables.d.cts +3 -1
  92. package/dist/font-tables.d.ts +3 -1
  93. package/dist/font-tables.js +31 -2
  94. package/dist/fonts.d.cts +2 -2
  95. package/dist/fonts.d.ts +2 -2
  96. package/dist/form.cjs +138 -0
  97. package/dist/form.d.cts +9 -0
  98. package/dist/form.d.ts +9 -0
  99. package/dist/form.js +137 -0
  100. package/dist/gsub-table-BRTQ8EUW.d.ts +10 -0
  101. package/dist/gsub-table-URczLd85.d.cts +10 -0
  102. package/dist/gsub-table.cjs +225 -0
  103. package/dist/gsub-table.d.cts +2 -0
  104. package/dist/gsub-table.d.ts +2 -0
  105. package/dist/gsub-table.js +224 -0
  106. package/dist/image/ccitt-encode.cjs +119 -0
  107. package/dist/image/ccitt-encode.d.cts +9 -0
  108. package/dist/image/ccitt-encode.d.ts +9 -0
  109. package/dist/image/ccitt-encode.js +118 -0
  110. package/dist/image/ccitt.cjs +3 -0
  111. package/dist/image/ccitt.d.cts +4 -1
  112. package/dist/image/ccitt.d.ts +4 -1
  113. package/dist/image/ccitt.js +1 -1
  114. package/dist/image/jbig2-bitmap.d.cts +1 -1
  115. package/dist/image/jbig2-bitmap.d.ts +1 -1
  116. package/dist/image/jbig2.cjs +3 -1
  117. package/dist/image/jbig2.js +3 -1
  118. package/dist/image/jp2-boxes.d.cts +1 -1
  119. package/dist/image/jp2-boxes.d.ts +1 -1
  120. package/dist/image/jpeg2000-codestream.d.cts +3 -3
  121. package/dist/image/jpeg2000-codestream.d.ts +3 -3
  122. package/dist/image/jpeg2000-t1.d.cts +1 -1
  123. package/dist/image/jpeg2000-t1.d.ts +1 -1
  124. package/dist/image/jpeg2000.cjs +1 -0
  125. package/dist/image/jpeg2000.d.cts +3 -0
  126. package/dist/image/jpeg2000.d.ts +3 -0
  127. package/dist/image/jpeg2000.js +1 -0
  128. package/dist/image/png-decode.cjs +1 -1
  129. package/dist/image/png-decode.js +1 -1
  130. package/dist/image/png-filter.d.cts +1 -1
  131. package/dist/image/png-filter.d.ts +1 -1
  132. package/dist/images-read.cjs +18 -12
  133. package/dist/images-read.d.cts +2 -2
  134. package/dist/images-read.d.ts +2 -2
  135. package/dist/images-read.js +15 -9
  136. package/dist/index.cjs +17 -4
  137. package/dist/index.d.cts +7 -6
  138. package/dist/index.d.ts +7 -6
  139. package/dist/index.js +6 -5
  140. package/dist/interpret.cjs +178 -56
  141. package/dist/interpret.d.cts +27 -12
  142. package/dist/interpret.d.ts +27 -12
  143. package/dist/interpret.js +178 -56
  144. package/dist/layout.cjs +149 -2
  145. package/dist/layout.d.cts +394 -1
  146. package/dist/layout.d.ts +394 -1
  147. package/dist/layout.js +140 -4
  148. package/dist/lexer.d.cts +9 -9
  149. package/dist/lexer.d.ts +9 -9
  150. package/dist/math-content-write.cjs +1 -1
  151. package/dist/math-content-write.js +1 -1
  152. package/dist/math-font-write.cjs +1 -1
  153. package/dist/math-font-write.d.cts +1 -1
  154. package/dist/math-font-write.d.ts +1 -1
  155. package/dist/math-font-write.js +1 -1
  156. package/dist/math-font.cjs +2 -2
  157. package/dist/math-font.d.cts +1 -1
  158. package/dist/math-font.d.ts +1 -1
  159. package/dist/math-font.js +2 -2
  160. package/dist/{math-stretch-a_rHNRvc.d.ts → math-stretch-BbC2o4Br.d.ts} +1 -1
  161. package/dist/{math-stretch-E26z6byT.d.cts → math-stretch-C2JanDAz.d.cts} +1 -1
  162. package/dist/math-stretch.d.cts +1 -1
  163. package/dist/math-stretch.d.ts +1 -1
  164. package/dist/measure.cjs +1 -1
  165. package/dist/measure.d.cts +1 -1
  166. package/dist/measure.d.ts +1 -1
  167. package/dist/measure.js +1 -1
  168. package/dist/names.cjs +41 -0
  169. package/dist/names.d.cts +11 -0
  170. package/dist/names.d.ts +11 -0
  171. package/dist/names.js +40 -0
  172. package/dist/navigation.cjs +210 -0
  173. package/dist/navigation.d.cts +18 -0
  174. package/dist/navigation.d.ts +18 -0
  175. package/dist/navigation.js +207 -0
  176. package/dist/notes-annotation-author.cjs +5 -0
  177. package/dist/notes-annotation-author.d.cts +4 -0
  178. package/dist/notes-annotation-author.d.ts +4 -0
  179. package/dist/notes-annotation-author.js +4 -0
  180. package/dist/objects-B7HdMeWS.d.cts +59 -0
  181. package/dist/objects-B7HdMeWS.d.ts +59 -0
  182. package/dist/objects.d.cts +1 -58
  183. package/dist/objects.d.ts +1 -58
  184. package/dist/optional-content.cjs +63 -0
  185. package/dist/optional-content.d.cts +12 -0
  186. package/dist/optional-content.d.ts +12 -0
  187. package/dist/optional-content.js +62 -0
  188. package/dist/parse.cjs +1 -1
  189. package/dist/parse.d.cts +2 -2
  190. package/dist/parse.d.ts +2 -2
  191. package/dist/parse.js +1 -1
  192. package/dist/pdf-text.cjs +21 -0
  193. package/dist/pdf-text.d.cts +5 -0
  194. package/dist/pdf-text.d.ts +5 -0
  195. package/dist/pdf-text.js +19 -0
  196. package/dist/predictors.d.cts +1 -1
  197. package/dist/predictors.d.ts +1 -1
  198. package/dist/read.cjs +287 -72
  199. package/dist/read.d.cts +2 -4
  200. package/dist/read.d.ts +2 -4
  201. package/dist/read.js +284 -67
  202. package/dist/serialize.cjs +5 -1
  203. package/dist/serialize.d.cts +3 -2
  204. package/dist/serialize.d.ts +3 -2
  205. package/dist/serialize.js +5 -2
  206. package/dist/sfnt-subset.cjs +10 -3
  207. package/dist/sfnt-subset.d.cts +1 -1
  208. package/dist/sfnt-subset.d.ts +1 -1
  209. package/dist/sfnt-subset.js +10 -3
  210. package/dist/structure.cjs +184 -0
  211. package/dist/structure.d.cts +12 -0
  212. package/dist/structure.d.ts +12 -0
  213. package/dist/structure.js +183 -0
  214. package/dist/tounicode.cjs +8 -3
  215. package/dist/tounicode.d.cts +2 -2
  216. package/dist/tounicode.d.ts +2 -2
  217. package/dist/tounicode.js +8 -3
  218. package/dist/util/base64.cjs +4 -4
  219. package/dist/util/base64.js +4 -4
  220. package/dist/winansi.cjs +1 -1
  221. package/dist/winansi.d.cts +1 -1
  222. package/dist/winansi.d.ts +1 -1
  223. package/dist/winansi.js +1 -1
  224. package/dist/write.cjs +464 -21
  225. package/dist/write.d.cts +4 -3
  226. package/dist/write.d.ts +4 -3
  227. package/dist/write.js +464 -20
  228. package/dist/xmp.cjs +46 -0
  229. package/dist/xmp.d.cts +14 -0
  230. package/dist/xmp.d.ts +14 -0
  231. package/dist/xmp.js +45 -0
  232. package/dist/xref.cjs +2 -2
  233. package/dist/xref.d.cts +3 -3
  234. package/dist/xref.d.ts +3 -3
  235. package/dist/xref.js +2 -2
  236. package/package.json +46 -31
  237. package/dist/image/png-encode.cjs +0 -64
  238. package/dist/image/png-encode.d.cts +0 -8
  239. package/dist/image/png-encode.d.ts +0 -8
  240. package/dist/image/png-encode.js +0 -63
@@ -0,0 +1,220 @@
1
+ import { c as glyphNameToUnicode, d as standardGlyphName } from "./afm-widths-De_QMWgC.js";
2
+ import { hasBytes, parseSfnt, sfntTableBytes, u16, u8 } from "./sfnt.js";
3
+ import { cffStringForSid, parseCffDict, readCffIndex } from "./cff.js";
4
+ import { readCmapSubtables } from "./cmap-table.js";
5
+ import { parsePostGlyphNames } from "./font-tables.js";
6
+ //#region src/builtin-encoding.ts
7
+ function isPrivateUse(codePoint) {
8
+ return codePoint >= 57344 && codePoint <= 63743 || codePoint >= 983040 && codePoint <= 1048573 || codePoint >= 1048576 && codePoint <= 1114109;
9
+ }
10
+ function encodingFromSources(sources) {
11
+ const { codeToGlyphId, codeToName, glyphIdToName, glyphIdToUnicode } = sources;
12
+ const glyphUnicode = (glyphId) => {
13
+ const name = glyphIdToName?.(glyphId);
14
+ return (name !== void 0 ? glyphNameToUnicode(name) : void 0) ?? glyphIdToUnicode?.(glyphId);
15
+ };
16
+ const codeUnicode = (code) => {
17
+ const name = codeToName?.(code);
18
+ if (name !== void 0) {
19
+ const named = glyphNameToUnicode(name);
20
+ if (named !== void 0) return named;
21
+ }
22
+ const glyphId = codeToGlyphId?.(code);
23
+ return glyphId === void 0 ? void 0 : glyphUnicode(glyphId);
24
+ };
25
+ return codeToName !== void 0 || codeToGlyphId !== void 0 || glyphIdToName !== void 0 || glyphIdToUnicode !== void 0 ? {
26
+ codeToUnicode: codeUnicode,
27
+ glyphIdToUnicode: glyphUnicode
28
+ } : void 0;
29
+ }
30
+ const SYMBOL_CMAP_CODE_BASE = 61440;
31
+ function symbolSubtable(subtables) {
32
+ return subtables.find((s) => s.platformId === 3 && s.encodingId === 0) ?? subtables.find((s) => s.platformId === 1 && s.encodingId === 0);
33
+ }
34
+ function unicodeSubtable(subtables) {
35
+ return subtables.find((s) => s.platformId === 3 && s.encodingId === 10) ?? subtables.find((s) => s.platformId === 3 && s.encodingId === 1) ?? subtables.find((s) => s.platformId === 0);
36
+ }
37
+ function invertUnicodeSubtable(subtable) {
38
+ let inverse;
39
+ return (glyphId) => {
40
+ if (inverse === void 0) {
41
+ const built = /* @__PURE__ */ new Map();
42
+ subtable.forEachMapping((code, mappedGlyphId) => {
43
+ if (!isPrivateUse(code) && !built.has(mappedGlyphId)) built.set(mappedGlyphId, code);
44
+ });
45
+ inverse = built;
46
+ }
47
+ return inverse.get(glyphId);
48
+ };
49
+ }
50
+ function trueTypeSources(font) {
51
+ const subtables = readCmapSubtables(font);
52
+ const symbol = symbolSubtable(subtables);
53
+ const unicode = unicodeSubtable(subtables);
54
+ return {
55
+ codeToGlyphId: symbol !== void 0 ? (code) => symbol.lookup(SYMBOL_CMAP_CODE_BASE | code) ?? symbol.lookup(code) : unicode !== void 0 ? (code) => unicode.lookup(SYMBOL_CMAP_CODE_BASE | code) : void 0,
56
+ glyphIdToName: parsePostGlyphNames(font),
57
+ glyphIdToUnicode: unicode !== void 0 ? invertUnicodeSubtable(unicode) : void 0
58
+ };
59
+ }
60
+ const CFF_HEADER_SIZE = 4;
61
+ const CFF_MAJOR_VERSION = 1;
62
+ const CFF_PREDEFINED_CHARSET_ISO_ADOBE = 0;
63
+ const CFF_PREDEFINED_ENCODING_STANDARD = 0;
64
+ const CFF_ENCODING_FORMAT_MASK = 127;
65
+ const CFF_ENCODING_SUPPLEMENT_FLAG = 128;
66
+ function readCffCharset(bytes, offset, glyphCount) {
67
+ const sidByGlyph = /* @__PURE__ */ new Map();
68
+ if (offset === CFF_PREDEFINED_CHARSET_ISO_ADOBE) {
69
+ for (let glyphId = 1; glyphId < glyphCount; glyphId++) sidByGlyph.set(glyphId, glyphId);
70
+ return sidByGlyph;
71
+ }
72
+ if (offset < CFF_HEADER_SIZE || !hasBytes(bytes, offset, 1)) return;
73
+ const format = u8(bytes, offset);
74
+ let cursor = offset + 1;
75
+ if (format === 0) {
76
+ for (let glyphId = 1; glyphId < glyphCount; glyphId++) {
77
+ if (!hasBytes(bytes, cursor, 2)) return sidByGlyph;
78
+ sidByGlyph.set(glyphId, u16(bytes, cursor));
79
+ cursor += 2;
80
+ }
81
+ return sidByGlyph;
82
+ }
83
+ if (format !== 1 && format !== 2) return;
84
+ const nLeftSize = format === 1 ? 1 : 2;
85
+ let glyphId = 1;
86
+ while (glyphId < glyphCount) {
87
+ if (!hasBytes(bytes, cursor, 2 + nLeftSize)) return sidByGlyph;
88
+ const firstSid = u16(bytes, cursor);
89
+ const nLeft = format === 1 ? u8(bytes, cursor + 2) : u16(bytes, cursor + 2);
90
+ for (let i = 0; i <= nLeft && glyphId < glyphCount; i++) {
91
+ sidByGlyph.set(glyphId, firstSid + i);
92
+ glyphId++;
93
+ }
94
+ cursor += 2 + nLeftSize;
95
+ }
96
+ return sidByGlyph;
97
+ }
98
+ function readCffEncoding(bytes, offset, glyphCount, glyphBySid) {
99
+ if (offset < CFF_HEADER_SIZE || !hasBytes(bytes, offset, 2)) return;
100
+ const formatByte = u8(bytes, offset);
101
+ const format = formatByte & CFF_ENCODING_FORMAT_MASK;
102
+ const glyphByCode = /* @__PURE__ */ new Map();
103
+ let cursor = offset + 1;
104
+ if (format === 0) {
105
+ const nCodes = u8(bytes, cursor);
106
+ cursor += 1;
107
+ for (let i = 0; i < nCodes; i++) {
108
+ if (!hasBytes(bytes, cursor, 1)) return glyphByCode;
109
+ const glyphId = i + 1;
110
+ if (glyphId < glyphCount) glyphByCode.set(u8(bytes, cursor), glyphId);
111
+ cursor += 1;
112
+ }
113
+ } else if (format === 1) {
114
+ const nRanges = u8(bytes, cursor);
115
+ cursor += 1;
116
+ let glyphId = 1;
117
+ for (let i = 0; i < nRanges; i++) {
118
+ if (!hasBytes(bytes, cursor, 2)) return glyphByCode;
119
+ const first = u8(bytes, cursor);
120
+ const nLeft = u8(bytes, cursor + 1);
121
+ for (let j = 0; j <= nLeft && glyphId < glyphCount; j++) {
122
+ glyphByCode.set(first + j, glyphId);
123
+ glyphId++;
124
+ }
125
+ cursor += 2;
126
+ }
127
+ } else return;
128
+ if ((formatByte & CFF_ENCODING_SUPPLEMENT_FLAG) !== 0) {
129
+ if (!hasBytes(bytes, cursor, 1)) return glyphByCode;
130
+ const nSups = u8(bytes, cursor);
131
+ cursor += 1;
132
+ for (let i = 0; i < nSups; i++) {
133
+ if (!hasBytes(bytes, cursor, 3)) return glyphByCode;
134
+ const glyphId = glyphBySid.get(u16(bytes, cursor + 1));
135
+ if (glyphId !== void 0) glyphByCode.set(u8(bytes, cursor), glyphId);
136
+ cursor += 3;
137
+ }
138
+ }
139
+ return glyphByCode;
140
+ }
141
+ function cffSources(bytes, predefinedEncodingApplies) {
142
+ if (!hasBytes(bytes, 0, CFF_HEADER_SIZE)) return;
143
+ const headerSize = u8(bytes, 2);
144
+ if (u8(bytes, 0) !== CFF_MAJOR_VERSION || headerSize < CFF_HEADER_SIZE) return;
145
+ const nameIndex = readCffIndex(bytes, headerSize);
146
+ if (nameIndex === void 0) return;
147
+ const topDictIndex = readCffIndex(bytes, nameIndex.endOffset);
148
+ const topDictBytes = topDictIndex?.entry(0);
149
+ if (topDictIndex === void 0 || topDictBytes === void 0) return;
150
+ const topDict = parseCffDict(topDictBytes);
151
+ if (topDict === void 0 || topDict.has(1230)) return;
152
+ const stringIndex = readCffIndex(bytes, topDictIndex.endOffset);
153
+ const charStringsOffset = topDict.get(17)?.[0];
154
+ const glyphCount = charStringsOffset === void 0 ? void 0 : readCffIndex(bytes, charStringsOffset)?.count;
155
+ if (glyphCount === void 0) return;
156
+ const sidByGlyph = readCffCharset(bytes, topDict.get(15)?.[0] ?? CFF_PREDEFINED_CHARSET_ISO_ADOBE, glyphCount);
157
+ const glyphIdToName = sidByGlyph === void 0 ? void 0 : (glyphId) => {
158
+ const sid = sidByGlyph.get(glyphId);
159
+ return sid === void 0 ? void 0 : cffStringForSid(sid, stringIndex);
160
+ };
161
+ const encodingOffset = topDict.get(16)?.[0] ?? CFF_PREDEFINED_ENCODING_STANDARD;
162
+ if (encodingOffset === CFF_PREDEFINED_ENCODING_STANDARD) return predefinedEncodingApplies ? {
163
+ codeToName: standardGlyphName,
164
+ glyphIdToName
165
+ } : { glyphIdToName };
166
+ const glyphBySid = /* @__PURE__ */ new Map();
167
+ for (const [glyphId, sid] of sidByGlyph ?? []) if (!glyphBySid.has(sid)) glyphBySid.set(sid, glyphId);
168
+ const glyphByCode = readCffEncoding(bytes, encodingOffset, glyphCount, glyphBySid);
169
+ return glyphByCode === void 0 ? { glyphIdToName } : {
170
+ codeToGlyphId: (code) => glyphByCode.get(code),
171
+ glyphIdToName
172
+ };
173
+ }
174
+ function matchesAscii(bytes, offset, text) {
175
+ for (let i = 0; i < text.length; i++) if (bytes[offset + i] !== text.charCodeAt(i)) return false;
176
+ return true;
177
+ }
178
+ const TYPE1_CLEARTEXT_TERMINATOR = "eexec";
179
+ const PFB_SEGMENT_MARKER = 128;
180
+ const PFB_SEGMENT_HEADER_SIZE = 6;
181
+ const POSTSCRIPT_MAGIC = "%!";
182
+ function type1Sources(bytes) {
183
+ const start = bytes[0] === PFB_SEGMENT_MARKER ? PFB_SEGMENT_HEADER_SIZE : 0;
184
+ if (!matchesAscii(bytes, start, POSTSCRIPT_MAGIC)) return;
185
+ let cleartextEnd = bytes.length;
186
+ for (let i = start; i + 5 <= bytes.length; i++) if (matchesAscii(bytes, i, TYPE1_CLEARTEXT_TERMINATOR)) {
187
+ cleartextEnd = i;
188
+ break;
189
+ }
190
+ let header = "";
191
+ for (let i = start; i < cleartextEnd; i++) header += String.fromCharCode(bytes[i] ?? 0);
192
+ if (!header.includes("/Encoding")) return;
193
+ if (/\/Encoding\s+StandardEncoding\s+def/.test(header)) return { codeToName: standardGlyphName };
194
+ const nameByCode = /* @__PURE__ */ new Map();
195
+ for (const match of header.matchAll(/dup\s+(\d+)\s*\/([^\s/[\]{}<>()%]+)\s+put/g)) {
196
+ const code = Number(match[1]);
197
+ const name = match[2];
198
+ if (name !== void 0 && Number.isInteger(code)) nameByCode.set(code, name);
199
+ }
200
+ return nameByCode.size === 0 ? void 0 : { codeToName: (code) => nameByCode.get(code) };
201
+ }
202
+ function readFontProgramEncoding(program) {
203
+ const font = parseSfnt(program);
204
+ if (font !== void 0) {
205
+ const cff = sfntTableBytes(font, "CFF ");
206
+ const container = trueTypeSources(font);
207
+ const outlines = cff === void 0 ? void 0 : cffSources(cff, false);
208
+ return encodingFromSources({
209
+ codeToGlyphId: container.codeToGlyphId ?? outlines?.codeToGlyphId,
210
+ glyphIdToName: container.glyphIdToName ?? outlines?.glyphIdToName,
211
+ glyphIdToUnicode: container.glyphIdToUnicode
212
+ });
213
+ }
214
+ const cff = cffSources(program, true);
215
+ if (cff !== void 0) return encodingFromSources(cff);
216
+ const type1 = type1Sources(program);
217
+ return type1 === void 0 ? void 0 : encodingFromSources(type1);
218
+ }
219
+ //#endregion
220
+ export { readFontProgramEncoding };
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_bytes_reader = require("./reader.cjs");
3
2
  const require_bytes_writer = require("./writer.cjs");
3
+ const require_bytes_reader = require("./reader.cjs");
4
4
  let fflate = require("fflate");
5
5
  //#region src/bytes/flate.ts
6
6
  const MAX_INFLATE_OUTPUT_BYTES = 536870912;
@@ -1,5 +1,5 @@
1
- import { isAsciiWhitespace } from "./reader.js";
2
1
  import { concatBytes } from "./writer.js";
2
+ import { isAsciiWhitespace } from "./reader.js";
3
3
  import { Unzlib, inflateSync, unzlibSync, zlibSync } from "fflate";
4
4
  //#region src/bytes/flate.ts
5
5
  const MAX_INFLATE_OUTPUT_BYTES = 536870912;
package/dist/cff.cjs CHANGED
@@ -3,6 +3,7 @@ const require_sfnt = require("./sfnt.cjs");
3
3
  //#region src/cff.ts
4
4
  const CFF_ESCAPED_OPERATOR_BASE = 1200;
5
5
  const CFF_DICT_OP_CHARSET = 15;
6
+ const CFF_DICT_OP_ENCODING = 16;
6
7
  const CFF_DICT_OP_CHARSTRINGS = 17;
7
8
  const CFF_DICT_OP_PRIVATE = 18;
8
9
  const CFF_DICT_OP_SUBRS = 19;
@@ -147,12 +148,25 @@ function parseCffDict(data) {
147
148
  }
148
149
  return dict;
149
150
  }
151
+ const CFF_STANDARD_STRINGS = ".notdef space exclam quotedbl numbersign dollar percent ampersand quoteright parenleft parenright asterisk plus comma hyphen period slash zero one two three four five six seven eight nine colon semicolon less equal greater question at A B C D E F G H I J K L M N O P Q R S T U V W X Y Z bracketleft backslash bracketright asciicircum underscore quoteleft a b c d e f g h i j k l m n o p q r s t u v w x y z braceleft bar braceright asciitilde exclamdown cent sterling fraction yen florin section currency quotesingle quotedblleft guillemotleft guilsinglleft guilsinglright fi fl endash dagger daggerdbl periodcentered paragraph bullet quotesinglbase quotedblbase quotedblright guillemotright ellipsis perthousand questiondown grave acute circumflex tilde macron breve dotaccent dieresis ring cedilla hungarumlaut ogonek caron emdash AE ordfeminine Lslash Oslash OE ordmasculine ae dotlessi lslash oslash oe germandbls onesuperior logicalnot mu trademark Eth onehalf plusminus Thorn onequarter divide brokenbar degree thorn threequarters twosuperior registered minus eth multiply threesuperior copyright Aacute Acircumflex Adieresis Agrave Aring Atilde Ccedilla Eacute Ecircumflex Edieresis Egrave Iacute Icircumflex Idieresis Igrave Ntilde Oacute Ocircumflex Odieresis Ograve Otilde Scaron Uacute Ucircumflex Udieresis Ugrave Yacute Ydieresis Zcaron aacute acircumflex adieresis agrave aring atilde ccedilla eacute ecircumflex edieresis egrave iacute icircumflex idieresis igrave ntilde oacute ocircumflex odieresis ograve otilde scaron uacute ucircumflex udieresis ugrave yacute ydieresis zcaron exclamsmall Hungarumlautsmall dollaroldstyle dollarsuperior ampersandsmall Acutesmall parenleftsuperior parenrightsuperior twodotenleader onedotenleader zerooldstyle oneoldstyle twooldstyle threeoldstyle fouroldstyle fiveoldstyle sixoldstyle sevenoldstyle eightoldstyle nineoldstyle commasuperior threequartersemdash periodsuperior questionsmall asuperior bsuperior centsuperior dsuperior esuperior isuperior lsuperior msuperior nsuperior osuperior rsuperior ssuperior tsuperior ff ffi ffl parenleftinferior parenrightinferior Circumflexsmall hyphensuperior Gravesmall Asmall Bsmall Csmall Dsmall Esmall Fsmall Gsmall Hsmall Ismall Jsmall Ksmall Lsmall Msmall Nsmall Osmall Psmall Qsmall Rsmall Ssmall Tsmall Usmall Vsmall Wsmall Xsmall Ysmall Zsmall colonmonetary onefitted rupiah Tildesmall exclamdownsmall centoldstyle Lslashsmall Scaronsmall Zcaronsmall Dieresissmall Brevesmall Caronsmall Dotaccentsmall Macronsmall figuredash hypheninferior Ogoneksmall Ringsmall Cedillasmall questiondownsmall oneeighth threeeighths fiveeighths seveneighths onethird twothirds zerosuperior foursuperior fivesuperior sixsuperior sevensuperior eightsuperior ninesuperior zeroinferior oneinferior twoinferior threeinferior fourinferior fiveinferior sixinferior seveninferior eightinferior nineinferior centinferior dollarinferior periodinferior commainferior Agravesmall Aacutesmall Acircumflexsmall Atildesmall Adieresissmall Aringsmall AEsmall Ccedillasmall Egravesmall Eacutesmall Ecircumflexsmall Edieresissmall Igravesmall Iacutesmall Icircumflexsmall Idieresissmall Ethsmall Ntildesmall Ogravesmall Oacutesmall Ocircumflexsmall Otildesmall Odieresissmall OEsmall Oslashsmall Ugravesmall Uacutesmall Ucircumflexsmall Udieresissmall Yacutesmall Thornsmall Ydieresissmall 001.000 001.001 001.002 001.003 Black Bold Book Light Medium Regular Roman Semibold".split(" ");
152
+ function cffStringForSid(sid, stringIndex) {
153
+ const standard = CFF_STANDARD_STRINGS[sid];
154
+ if (standard !== void 0) return standard;
155
+ const entry = stringIndex?.entry(sid - CFF_STANDARD_STRINGS.length);
156
+ if (entry === void 0) return;
157
+ let text = "";
158
+ for (const byte of entry) text += String.fromCharCode(byte);
159
+ return text;
160
+ }
150
161
  //#endregion
151
162
  exports.CFF_DICT_OP_CHARSET = CFF_DICT_OP_CHARSET;
152
163
  exports.CFF_DICT_OP_CHARSTRINGS = CFF_DICT_OP_CHARSTRINGS;
164
+ exports.CFF_DICT_OP_ENCODING = CFF_DICT_OP_ENCODING;
153
165
  exports.CFF_DICT_OP_PRIVATE = CFF_DICT_OP_PRIVATE;
154
166
  exports.CFF_DICT_OP_ROS = CFF_DICT_OP_ROS;
155
167
  exports.CFF_DICT_OP_SUBRS = CFF_DICT_OP_SUBRS;
156
168
  exports.CFF_ESCAPED_OPERATOR_BASE = CFF_ESCAPED_OPERATOR_BASE;
169
+ exports.CFF_STANDARD_STRINGS = CFF_STANDARD_STRINGS;
170
+ exports.cffStringForSid = cffStringForSid;
157
171
  exports.parseCffDict = parseCffDict;
158
172
  exports.readCffIndex = readCffIndex;
package/dist/cff.d.cts CHANGED
@@ -7,11 +7,14 @@ interface CffIndex {
7
7
  type CffDict = ReadonlyMap<number, readonly number[]>;
8
8
  declare const CFF_ESCAPED_OPERATOR_BASE = 1200;
9
9
  declare const CFF_DICT_OP_CHARSET = 15;
10
+ declare const CFF_DICT_OP_ENCODING = 16;
10
11
  declare const CFF_DICT_OP_CHARSTRINGS = 17;
11
12
  declare const CFF_DICT_OP_PRIVATE = 18;
12
13
  declare const CFF_DICT_OP_SUBRS = 19;
13
14
  declare const CFF_DICT_OP_ROS: number;
14
15
  declare function readCffIndex(bytes: Uint8Array<ArrayBuffer>, offset: number): CffIndex | undefined;
15
16
  declare function parseCffDict(data: Uint8Array<ArrayBuffer>): CffDict | undefined;
17
+ declare const CFF_STANDARD_STRINGS: readonly string[];
18
+ declare function cffStringForSid(sid: number, stringIndex: CffIndex | undefined): string | undefined;
16
19
  //#endregion
17
- export { CFF_DICT_OP_CHARSET, CFF_DICT_OP_CHARSTRINGS, CFF_DICT_OP_PRIVATE, CFF_DICT_OP_ROS, CFF_DICT_OP_SUBRS, CFF_ESCAPED_OPERATOR_BASE, CffDict, CffIndex, parseCffDict, readCffIndex };
20
+ export { CFF_DICT_OP_CHARSET, CFF_DICT_OP_CHARSTRINGS, CFF_DICT_OP_ENCODING, CFF_DICT_OP_PRIVATE, CFF_DICT_OP_ROS, CFF_DICT_OP_SUBRS, CFF_ESCAPED_OPERATOR_BASE, CFF_STANDARD_STRINGS, CffDict, CffIndex, cffStringForSid, parseCffDict, readCffIndex };
package/dist/cff.d.ts CHANGED
@@ -7,11 +7,14 @@ interface CffIndex {
7
7
  type CffDict = ReadonlyMap<number, readonly number[]>;
8
8
  declare const CFF_ESCAPED_OPERATOR_BASE = 1200;
9
9
  declare const CFF_DICT_OP_CHARSET = 15;
10
+ declare const CFF_DICT_OP_ENCODING = 16;
10
11
  declare const CFF_DICT_OP_CHARSTRINGS = 17;
11
12
  declare const CFF_DICT_OP_PRIVATE = 18;
12
13
  declare const CFF_DICT_OP_SUBRS = 19;
13
14
  declare const CFF_DICT_OP_ROS: number;
14
15
  declare function readCffIndex(bytes: Uint8Array<ArrayBuffer>, offset: number): CffIndex | undefined;
15
16
  declare function parseCffDict(data: Uint8Array<ArrayBuffer>): CffDict | undefined;
17
+ declare const CFF_STANDARD_STRINGS: readonly string[];
18
+ declare function cffStringForSid(sid: number, stringIndex: CffIndex | undefined): string | undefined;
16
19
  //#endregion
17
- export { CFF_DICT_OP_CHARSET, CFF_DICT_OP_CHARSTRINGS, CFF_DICT_OP_PRIVATE, CFF_DICT_OP_ROS, CFF_DICT_OP_SUBRS, CFF_ESCAPED_OPERATOR_BASE, CffDict, CffIndex, parseCffDict, readCffIndex };
20
+ export { CFF_DICT_OP_CHARSET, CFF_DICT_OP_CHARSTRINGS, CFF_DICT_OP_ENCODING, CFF_DICT_OP_PRIVATE, CFF_DICT_OP_ROS, CFF_DICT_OP_SUBRS, CFF_ESCAPED_OPERATOR_BASE, CFF_STANDARD_STRINGS, CffDict, CffIndex, cffStringForSid, parseCffDict, readCffIndex };
package/dist/cff.js CHANGED
@@ -2,6 +2,7 @@ import { hasBytes, u16, u24, u32, u8 } from "./sfnt.js";
2
2
  //#region src/cff.ts
3
3
  const CFF_ESCAPED_OPERATOR_BASE = 1200;
4
4
  const CFF_DICT_OP_CHARSET = 15;
5
+ const CFF_DICT_OP_ENCODING = 16;
5
6
  const CFF_DICT_OP_CHARSTRINGS = 17;
6
7
  const CFF_DICT_OP_PRIVATE = 18;
7
8
  const CFF_DICT_OP_SUBRS = 19;
@@ -146,5 +147,15 @@ function parseCffDict(data) {
146
147
  }
147
148
  return dict;
148
149
  }
150
+ const CFF_STANDARD_STRINGS = ".notdef space exclam quotedbl numbersign dollar percent ampersand quoteright parenleft parenright asterisk plus comma hyphen period slash zero one two three four five six seven eight nine colon semicolon less equal greater question at A B C D E F G H I J K L M N O P Q R S T U V W X Y Z bracketleft backslash bracketright asciicircum underscore quoteleft a b c d e f g h i j k l m n o p q r s t u v w x y z braceleft bar braceright asciitilde exclamdown cent sterling fraction yen florin section currency quotesingle quotedblleft guillemotleft guilsinglleft guilsinglright fi fl endash dagger daggerdbl periodcentered paragraph bullet quotesinglbase quotedblbase quotedblright guillemotright ellipsis perthousand questiondown grave acute circumflex tilde macron breve dotaccent dieresis ring cedilla hungarumlaut ogonek caron emdash AE ordfeminine Lslash Oslash OE ordmasculine ae dotlessi lslash oslash oe germandbls onesuperior logicalnot mu trademark Eth onehalf plusminus Thorn onequarter divide brokenbar degree thorn threequarters twosuperior registered minus eth multiply threesuperior copyright Aacute Acircumflex Adieresis Agrave Aring Atilde Ccedilla Eacute Ecircumflex Edieresis Egrave Iacute Icircumflex Idieresis Igrave Ntilde Oacute Ocircumflex Odieresis Ograve Otilde Scaron Uacute Ucircumflex Udieresis Ugrave Yacute Ydieresis Zcaron aacute acircumflex adieresis agrave aring atilde ccedilla eacute ecircumflex edieresis egrave iacute icircumflex idieresis igrave ntilde oacute ocircumflex odieresis ograve otilde scaron uacute ucircumflex udieresis ugrave yacute ydieresis zcaron exclamsmall Hungarumlautsmall dollaroldstyle dollarsuperior ampersandsmall Acutesmall parenleftsuperior parenrightsuperior twodotenleader onedotenleader zerooldstyle oneoldstyle twooldstyle threeoldstyle fouroldstyle fiveoldstyle sixoldstyle sevenoldstyle eightoldstyle nineoldstyle commasuperior threequartersemdash periodsuperior questionsmall asuperior bsuperior centsuperior dsuperior esuperior isuperior lsuperior msuperior nsuperior osuperior rsuperior ssuperior tsuperior ff ffi ffl parenleftinferior parenrightinferior Circumflexsmall hyphensuperior Gravesmall Asmall Bsmall Csmall Dsmall Esmall Fsmall Gsmall Hsmall Ismall Jsmall Ksmall Lsmall Msmall Nsmall Osmall Psmall Qsmall Rsmall Ssmall Tsmall Usmall Vsmall Wsmall Xsmall Ysmall Zsmall colonmonetary onefitted rupiah Tildesmall exclamdownsmall centoldstyle Lslashsmall Scaronsmall Zcaronsmall Dieresissmall Brevesmall Caronsmall Dotaccentsmall Macronsmall figuredash hypheninferior Ogoneksmall Ringsmall Cedillasmall questiondownsmall oneeighth threeeighths fiveeighths seveneighths onethird twothirds zerosuperior foursuperior fivesuperior sixsuperior sevensuperior eightsuperior ninesuperior zeroinferior oneinferior twoinferior threeinferior fourinferior fiveinferior sixinferior seveninferior eightinferior nineinferior centinferior dollarinferior periodinferior commainferior Agravesmall Aacutesmall Acircumflexsmall Atildesmall Adieresissmall Aringsmall AEsmall Ccedillasmall Egravesmall Eacutesmall Ecircumflexsmall Edieresissmall Igravesmall Iacutesmall Icircumflexsmall Idieresissmall Ethsmall Ntildesmall Ogravesmall Oacutesmall Ocircumflexsmall Otildesmall Odieresissmall OEsmall Oslashsmall Ugravesmall Uacutesmall Ucircumflexsmall Udieresissmall Yacutesmall Thornsmall Ydieresissmall 001.000 001.001 001.002 001.003 Black Bold Book Light Medium Regular Roman Semibold".split(" ");
151
+ function cffStringForSid(sid, stringIndex) {
152
+ const standard = CFF_STANDARD_STRINGS[sid];
153
+ if (standard !== void 0) return standard;
154
+ const entry = stringIndex?.entry(sid - CFF_STANDARD_STRINGS.length);
155
+ if (entry === void 0) return;
156
+ let text = "";
157
+ for (const byte of entry) text += String.fromCharCode(byte);
158
+ return text;
159
+ }
149
160
  //#endregion
150
- export { CFF_DICT_OP_CHARSET, CFF_DICT_OP_CHARSTRINGS, CFF_DICT_OP_PRIVATE, CFF_DICT_OP_ROS, CFF_DICT_OP_SUBRS, CFF_ESCAPED_OPERATOR_BASE, parseCffDict, readCffIndex };
161
+ export { CFF_DICT_OP_CHARSET, CFF_DICT_OP_CHARSTRINGS, CFF_DICT_OP_ENCODING, CFF_DICT_OP_PRIVATE, CFF_DICT_OP_ROS, CFF_DICT_OP_SUBRS, CFF_ESCAPED_OPERATOR_BASE, CFF_STANDARD_STRINGS, cffStringForSid, parseCffDict, readCffIndex };
@@ -3,6 +3,7 @@ const require_sfnt = require("./sfnt.cjs");
3
3
  //#region src/cmap-table.ts
4
4
  const CMAP_HEADER_SIZE = 4;
5
5
  const SUBTABLE_RECORD_SIZE = 8;
6
+ const MAX_UNICODE_CODE_POINT = 1114111;
6
7
  const FORMAT_4_HEADER_SIZE = 14;
7
8
  function parseFormat4(bytes, subtableOffset) {
8
9
  if (!require_sfnt.hasBytes(bytes, subtableOffset, FORMAT_4_HEADER_SIZE)) return;
@@ -26,7 +27,7 @@ function parseFormat4(bytes, subtableOffset) {
26
27
  idRangeOffset: require_sfnt.u16(bytes, idRangeOffsetPos)
27
28
  });
28
29
  }
29
- return (codePoint) => {
30
+ const lookup = (codePoint) => {
30
31
  if (codePoint > 65535) return;
31
32
  for (const segment of segments) {
32
33
  if (codePoint < segment.startCode || codePoint > segment.endCode) continue;
@@ -37,6 +38,18 @@ function parseFormat4(bytes, subtableOffset) {
37
38
  return glyphId === 0 ? void 0 : glyphId + segment.idDelta & 65535;
38
39
  }
39
40
  };
41
+ return {
42
+ lookup,
43
+ forEachMapping(visit) {
44
+ for (const segment of segments) {
45
+ const end = Math.min(segment.endCode, 65534);
46
+ for (let code = segment.startCode; code <= end; code++) {
47
+ const glyphId = lookup(code);
48
+ if (glyphId !== void 0 && glyphId !== 0) visit(code, glyphId);
49
+ }
50
+ }
51
+ }
52
+ };
40
53
  }
41
54
  const FORMAT_12_HEADER_SIZE = 16;
42
55
  const FORMAT_12_GROUP_SIZE = 12;
@@ -54,8 +67,35 @@ function parseFormat12(bytes, subtableOffset) {
54
67
  startGlyphId: require_sfnt.u32(bytes, recordOffset + 8)
55
68
  });
56
69
  }
57
- return (codePoint) => {
58
- for (const group of groups) if (codePoint >= group.startCharCode && codePoint <= group.endCharCode) return group.startGlyphId + (codePoint - group.startCharCode);
70
+ return {
71
+ lookup(codePoint) {
72
+ for (const group of groups) if (codePoint >= group.startCharCode && codePoint <= group.endCharCode) return group.startGlyphId + (codePoint - group.startCharCode);
73
+ },
74
+ forEachMapping(visit) {
75
+ for (const group of groups) {
76
+ const end = Math.min(group.endCharCode, MAX_UNICODE_CODE_POINT);
77
+ for (let code = group.startCharCode; code <= end; code++) visit(code, group.startGlyphId + (code - group.startCharCode));
78
+ }
79
+ }
80
+ };
81
+ }
82
+ const FORMAT_0_SIZE = 262;
83
+ function parseFormat0(bytes, subtableOffset) {
84
+ if (!require_sfnt.hasBytes(bytes, subtableOffset, FORMAT_0_SIZE)) return;
85
+ const glyphIdArrayOffset = subtableOffset + 6;
86
+ const lookup = (codePoint) => {
87
+ if (codePoint < 0 || codePoint > 255) return;
88
+ const glyphId = require_sfnt.u8(bytes, glyphIdArrayOffset + codePoint);
89
+ return glyphId === 0 ? void 0 : glyphId;
90
+ };
91
+ return {
92
+ lookup,
93
+ forEachMapping(visit) {
94
+ for (let code = 0; code <= 255; code++) {
95
+ const glyphId = lookup(code);
96
+ if (glyphId !== void 0) visit(code, glyphId);
97
+ }
98
+ }
59
99
  };
60
100
  }
61
101
  const FORMAT_6_HEADER_SIZE = 10;
@@ -65,12 +105,22 @@ function parseFormat6(bytes, subtableOffset) {
65
105
  const entryCount = require_sfnt.u16(bytes, subtableOffset + 8);
66
106
  const glyphIdArrayOffset = subtableOffset + FORMAT_6_HEADER_SIZE;
67
107
  if (!require_sfnt.hasBytes(bytes, glyphIdArrayOffset, entryCount * 2)) return;
68
- return (codePoint) => {
108
+ const lookup = (codePoint) => {
69
109
  const index = codePoint - firstCode;
70
110
  if (index < 0 || index >= entryCount) return;
71
111
  const glyphId = require_sfnt.u16(bytes, glyphIdArrayOffset + index * 2);
72
112
  return glyphId === 0 ? void 0 : glyphId;
73
113
  };
114
+ return {
115
+ lookup,
116
+ forEachMapping(visit) {
117
+ for (let index = 0; index < entryCount; index++) {
118
+ const code = firstCode + index;
119
+ const glyphId = lookup(code);
120
+ if (glyphId !== void 0) visit(code, glyphId);
121
+ }
122
+ }
123
+ };
74
124
  }
75
125
  function preferenceRank(subtable) {
76
126
  if (subtable.format === 12) {
@@ -81,28 +131,41 @@ function preferenceRank(subtable) {
81
131
  if (subtable.format === 4) return subtable.platformId === 3 && subtable.encodingId === 1 ? 3 : 4;
82
132
  return 5;
83
133
  }
84
- function buildCmapLookup(font) {
134
+ function parseSubtable(bytes, record) {
135
+ if (record.format === 12) return parseFormat12(bytes, record.offset);
136
+ if (record.format === 4) return parseFormat4(bytes, record.offset);
137
+ if (record.format === 6) return parseFormat6(bytes, record.offset);
138
+ return record.format === 0 ? parseFormat0(bytes, record.offset) : void 0;
139
+ }
140
+ function readCmapSubtables(font) {
85
141
  const cmapBytes = require_sfnt.sfntTableBytes(font, "cmap");
86
- if (cmapBytes === void 0 || !require_sfnt.hasBytes(cmapBytes, 0, CMAP_HEADER_SIZE)) return;
142
+ if (cmapBytes === void 0 || !require_sfnt.hasBytes(cmapBytes, 0, CMAP_HEADER_SIZE)) return [];
87
143
  const numTables = require_sfnt.u16(cmapBytes, 2);
88
- if (!require_sfnt.hasBytes(cmapBytes, CMAP_HEADER_SIZE, numTables * SUBTABLE_RECORD_SIZE)) return;
144
+ if (!require_sfnt.hasBytes(cmapBytes, CMAP_HEADER_SIZE, numTables * SUBTABLE_RECORD_SIZE)) return [];
89
145
  const subtables = [];
90
146
  for (let i = 0; i < numTables; i++) {
91
147
  const recordOffset = CMAP_HEADER_SIZE + i * SUBTABLE_RECORD_SIZE;
92
148
  const offset = require_sfnt.u32(cmapBytes, recordOffset + 4);
93
149
  if (!require_sfnt.hasBytes(cmapBytes, offset, 2)) continue;
94
- subtables.push({
150
+ const record = {
95
151
  platformId: require_sfnt.u16(cmapBytes, recordOffset),
96
152
  encodingId: require_sfnt.u16(cmapBytes, recordOffset + 2),
97
153
  offset,
98
154
  format: require_sfnt.u16(cmapBytes, offset)
155
+ };
156
+ const parsed = parseSubtable(cmapBytes, record);
157
+ if (parsed !== void 0) subtables.push({
158
+ platformId: record.platformId,
159
+ encodingId: record.encodingId,
160
+ format: record.format,
161
+ ...parsed
99
162
  });
100
163
  }
101
- const candidates = subtables.filter((s) => s.format === 4 || s.format === 6 || s.format === 12).sort((a, b) => preferenceRank(a) - preferenceRank(b));
102
- for (const candidate of candidates) {
103
- const lookup = candidate.format === 12 ? parseFormat12(cmapBytes, candidate.offset) : candidate.format === 4 ? parseFormat4(cmapBytes, candidate.offset) : parseFormat6(cmapBytes, candidate.offset);
104
- if (lookup !== void 0) return lookup;
105
- }
164
+ return subtables;
165
+ }
166
+ function buildCmapLookup(font) {
167
+ return readCmapSubtables(font).filter((s) => s.format === 4 || s.format === 6 || s.format === 12).sort((a, b) => preferenceRank(a) - preferenceRank(b))[0]?.lookup;
106
168
  }
107
169
  //#endregion
108
170
  exports.buildCmapLookup = buildCmapLookup;
171
+ exports.readCmapSubtables = readCmapSubtables;
@@ -1,6 +1,14 @@
1
1
  import { t as SfntFont } from "./sfnt-V08bb5ut.cjs";
2
2
  //#region src/cmap-table.d.ts
3
3
  type CmapLookup = (codePoint: number) => number | undefined;
4
+ interface CmapSubtable {
5
+ readonly platformId: number;
6
+ readonly encodingId: number;
7
+ readonly format: number;
8
+ readonly lookup: CmapLookup;
9
+ forEachMapping(visit: (code: number, glyphId: number) => void): void;
10
+ }
11
+ declare function readCmapSubtables(font: SfntFont): readonly CmapSubtable[];
4
12
  declare function buildCmapLookup(font: SfntFont): CmapLookup | undefined;
5
13
  //#endregion
6
- export { CmapLookup, buildCmapLookup };
14
+ export { CmapLookup, CmapSubtable, buildCmapLookup, readCmapSubtables };
@@ -1,6 +1,14 @@
1
1
  import { t as SfntFont } from "./sfnt-V08bb5ut.js";
2
2
  //#region src/cmap-table.d.ts
3
3
  type CmapLookup = (codePoint: number) => number | undefined;
4
+ interface CmapSubtable {
5
+ readonly platformId: number;
6
+ readonly encodingId: number;
7
+ readonly format: number;
8
+ readonly lookup: CmapLookup;
9
+ forEachMapping(visit: (code: number, glyphId: number) => void): void;
10
+ }
11
+ declare function readCmapSubtables(font: SfntFont): readonly CmapSubtable[];
4
12
  declare function buildCmapLookup(font: SfntFont): CmapLookup | undefined;
5
13
  //#endregion
6
- export { CmapLookup, buildCmapLookup };
14
+ export { CmapLookup, CmapSubtable, buildCmapLookup, readCmapSubtables };
@@ -1,7 +1,8 @@
1
- import { hasBytes, sfntTableBytes, u16, u32 } from "./sfnt.js";
1
+ import { hasBytes, sfntTableBytes, u16, u32, u8 } from "./sfnt.js";
2
2
  //#region src/cmap-table.ts
3
3
  const CMAP_HEADER_SIZE = 4;
4
4
  const SUBTABLE_RECORD_SIZE = 8;
5
+ const MAX_UNICODE_CODE_POINT = 1114111;
5
6
  const FORMAT_4_HEADER_SIZE = 14;
6
7
  function parseFormat4(bytes, subtableOffset) {
7
8
  if (!hasBytes(bytes, subtableOffset, FORMAT_4_HEADER_SIZE)) return;
@@ -25,7 +26,7 @@ function parseFormat4(bytes, subtableOffset) {
25
26
  idRangeOffset: u16(bytes, idRangeOffsetPos)
26
27
  });
27
28
  }
28
- return (codePoint) => {
29
+ const lookup = (codePoint) => {
29
30
  if (codePoint > 65535) return;
30
31
  for (const segment of segments) {
31
32
  if (codePoint < segment.startCode || codePoint > segment.endCode) continue;
@@ -36,6 +37,18 @@ function parseFormat4(bytes, subtableOffset) {
36
37
  return glyphId === 0 ? void 0 : glyphId + segment.idDelta & 65535;
37
38
  }
38
39
  };
40
+ return {
41
+ lookup,
42
+ forEachMapping(visit) {
43
+ for (const segment of segments) {
44
+ const end = Math.min(segment.endCode, 65534);
45
+ for (let code = segment.startCode; code <= end; code++) {
46
+ const glyphId = lookup(code);
47
+ if (glyphId !== void 0 && glyphId !== 0) visit(code, glyphId);
48
+ }
49
+ }
50
+ }
51
+ };
39
52
  }
40
53
  const FORMAT_12_HEADER_SIZE = 16;
41
54
  const FORMAT_12_GROUP_SIZE = 12;
@@ -53,8 +66,35 @@ function parseFormat12(bytes, subtableOffset) {
53
66
  startGlyphId: u32(bytes, recordOffset + 8)
54
67
  });
55
68
  }
56
- return (codePoint) => {
57
- for (const group of groups) if (codePoint >= group.startCharCode && codePoint <= group.endCharCode) return group.startGlyphId + (codePoint - group.startCharCode);
69
+ return {
70
+ lookup(codePoint) {
71
+ for (const group of groups) if (codePoint >= group.startCharCode && codePoint <= group.endCharCode) return group.startGlyphId + (codePoint - group.startCharCode);
72
+ },
73
+ forEachMapping(visit) {
74
+ for (const group of groups) {
75
+ const end = Math.min(group.endCharCode, MAX_UNICODE_CODE_POINT);
76
+ for (let code = group.startCharCode; code <= end; code++) visit(code, group.startGlyphId + (code - group.startCharCode));
77
+ }
78
+ }
79
+ };
80
+ }
81
+ const FORMAT_0_SIZE = 262;
82
+ function parseFormat0(bytes, subtableOffset) {
83
+ if (!hasBytes(bytes, subtableOffset, FORMAT_0_SIZE)) return;
84
+ const glyphIdArrayOffset = subtableOffset + 6;
85
+ const lookup = (codePoint) => {
86
+ if (codePoint < 0 || codePoint > 255) return;
87
+ const glyphId = u8(bytes, glyphIdArrayOffset + codePoint);
88
+ return glyphId === 0 ? void 0 : glyphId;
89
+ };
90
+ return {
91
+ lookup,
92
+ forEachMapping(visit) {
93
+ for (let code = 0; code <= 255; code++) {
94
+ const glyphId = lookup(code);
95
+ if (glyphId !== void 0) visit(code, glyphId);
96
+ }
97
+ }
58
98
  };
59
99
  }
60
100
  const FORMAT_6_HEADER_SIZE = 10;
@@ -64,12 +104,22 @@ function parseFormat6(bytes, subtableOffset) {
64
104
  const entryCount = u16(bytes, subtableOffset + 8);
65
105
  const glyphIdArrayOffset = subtableOffset + FORMAT_6_HEADER_SIZE;
66
106
  if (!hasBytes(bytes, glyphIdArrayOffset, entryCount * 2)) return;
67
- return (codePoint) => {
107
+ const lookup = (codePoint) => {
68
108
  const index = codePoint - firstCode;
69
109
  if (index < 0 || index >= entryCount) return;
70
110
  const glyphId = u16(bytes, glyphIdArrayOffset + index * 2);
71
111
  return glyphId === 0 ? void 0 : glyphId;
72
112
  };
113
+ return {
114
+ lookup,
115
+ forEachMapping(visit) {
116
+ for (let index = 0; index < entryCount; index++) {
117
+ const code = firstCode + index;
118
+ const glyphId = lookup(code);
119
+ if (glyphId !== void 0) visit(code, glyphId);
120
+ }
121
+ }
122
+ };
73
123
  }
74
124
  function preferenceRank(subtable) {
75
125
  if (subtable.format === 12) {
@@ -80,28 +130,40 @@ function preferenceRank(subtable) {
80
130
  if (subtable.format === 4) return subtable.platformId === 3 && subtable.encodingId === 1 ? 3 : 4;
81
131
  return 5;
82
132
  }
83
- function buildCmapLookup(font) {
133
+ function parseSubtable(bytes, record) {
134
+ if (record.format === 12) return parseFormat12(bytes, record.offset);
135
+ if (record.format === 4) return parseFormat4(bytes, record.offset);
136
+ if (record.format === 6) return parseFormat6(bytes, record.offset);
137
+ return record.format === 0 ? parseFormat0(bytes, record.offset) : void 0;
138
+ }
139
+ function readCmapSubtables(font) {
84
140
  const cmapBytes = sfntTableBytes(font, "cmap");
85
- if (cmapBytes === void 0 || !hasBytes(cmapBytes, 0, CMAP_HEADER_SIZE)) return;
141
+ if (cmapBytes === void 0 || !hasBytes(cmapBytes, 0, CMAP_HEADER_SIZE)) return [];
86
142
  const numTables = u16(cmapBytes, 2);
87
- if (!hasBytes(cmapBytes, CMAP_HEADER_SIZE, numTables * SUBTABLE_RECORD_SIZE)) return;
143
+ if (!hasBytes(cmapBytes, CMAP_HEADER_SIZE, numTables * SUBTABLE_RECORD_SIZE)) return [];
88
144
  const subtables = [];
89
145
  for (let i = 0; i < numTables; i++) {
90
146
  const recordOffset = CMAP_HEADER_SIZE + i * SUBTABLE_RECORD_SIZE;
91
147
  const offset = u32(cmapBytes, recordOffset + 4);
92
148
  if (!hasBytes(cmapBytes, offset, 2)) continue;
93
- subtables.push({
149
+ const record = {
94
150
  platformId: u16(cmapBytes, recordOffset),
95
151
  encodingId: u16(cmapBytes, recordOffset + 2),
96
152
  offset,
97
153
  format: u16(cmapBytes, offset)
154
+ };
155
+ const parsed = parseSubtable(cmapBytes, record);
156
+ if (parsed !== void 0) subtables.push({
157
+ platformId: record.platformId,
158
+ encodingId: record.encodingId,
159
+ format: record.format,
160
+ ...parsed
98
161
  });
99
162
  }
100
- const candidates = subtables.filter((s) => s.format === 4 || s.format === 6 || s.format === 12).sort((a, b) => preferenceRank(a) - preferenceRank(b));
101
- for (const candidate of candidates) {
102
- const lookup = candidate.format === 12 ? parseFormat12(cmapBytes, candidate.offset) : candidate.format === 4 ? parseFormat4(cmapBytes, candidate.offset) : parseFormat6(cmapBytes, candidate.offset);
103
- if (lookup !== void 0) return lookup;
104
- }
163
+ return subtables;
164
+ }
165
+ function buildCmapLookup(font) {
166
+ return readCmapSubtables(font).filter((s) => s.format === 4 || s.format === 6 || s.format === 12).sort((a, b) => preferenceRank(a) - preferenceRank(b))[0]?.lookup;
105
167
  }
106
168
  //#endregion
107
- export { buildCmapLookup };
169
+ export { buildCmapLookup, readCmapSubtables };