pdf-codec 1.3.0 → 1.4.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 (198) hide show
  1. package/README.md +38 -0
  2. package/dist/afm-widths-BoeTOK2r.cjs +826 -0
  3. package/dist/afm-widths-Dxucrg7D.js +779 -0
  4. package/dist/afm-widths-DyDq56Ph.d.cts +19 -0
  5. package/dist/afm-widths-DyDq56Ph.d.ts +19 -0
  6. package/dist/afm-widths.cjs +4 -0
  7. package/dist/afm-widths.d.cts +2 -0
  8. package/dist/afm-widths.d.ts +2 -0
  9. package/dist/afm-widths.js +2 -0
  10. package/dist/assets/stix-two-math-font.cjs +5 -0
  11. package/dist/assets/stix-two-math-font.d.cts +4 -0
  12. package/dist/assets/stix-two-math-font.d.ts +4 -0
  13. package/dist/assets/stix-two-math-font.js +4 -0
  14. package/dist/bytes/crc32.cjs +21 -0
  15. package/dist/bytes/crc32.d.cts +4 -0
  16. package/dist/bytes/crc32.d.ts +4 -0
  17. package/dist/bytes/crc32.js +20 -0
  18. package/dist/bytes/flate.cjs +53 -0
  19. package/dist/bytes/flate.d.cts +12 -0
  20. package/dist/bytes/flate.d.ts +12 -0
  21. package/dist/bytes/flate.js +49 -0
  22. package/dist/bytes/reader.cjs +60 -0
  23. package/dist/bytes/reader.d.cts +20 -0
  24. package/dist/bytes/reader.d.ts +20 -0
  25. package/dist/bytes/reader.js +58 -0
  26. package/dist/bytes/writer.cjs +37 -0
  27. package/dist/bytes/writer.d.cts +13 -0
  28. package/dist/bytes/writer.d.ts +13 -0
  29. package/dist/bytes/writer.js +35 -0
  30. package/dist/cmap.cjs +110 -0
  31. package/dist/cmap.d.cts +8 -0
  32. package/dist/cmap.d.ts +8 -0
  33. package/dist/cmap.js +109 -0
  34. package/dist/codec.cjs +34 -0
  35. package/dist/codec.d.cts +167 -0
  36. package/dist/codec.d.ts +167 -0
  37. package/dist/codec.js +32 -0
  38. package/dist/content-read.cjs +126 -0
  39. package/dist/content-read.d.cts +21 -0
  40. package/dist/content-read.d.ts +21 -0
  41. package/dist/content-read.js +125 -0
  42. package/dist/content-write.cjs +138 -0
  43. package/dist/content-write.d.cts +24 -0
  44. package/dist/content-write.d.ts +24 -0
  45. package/dist/content-write.js +137 -0
  46. package/dist/diagnostics.cjs +21 -0
  47. package/dist/diagnostics.d.cts +19 -0
  48. package/dist/diagnostics.d.ts +19 -0
  49. package/dist/diagnostics.js +18 -0
  50. package/dist/document.cjs +162 -0
  51. package/dist/document.d.cts +12 -0
  52. package/dist/document.d.ts +12 -0
  53. package/dist/document.js +161 -0
  54. package/dist/encoding.cjs +5 -0
  55. package/dist/encoding.d.cts +6 -0
  56. package/dist/encoding.d.ts +6 -0
  57. package/dist/encoding.js +2 -0
  58. package/dist/filters.cjs +223 -0
  59. package/dist/filters.d.cts +14 -0
  60. package/dist/filters.d.ts +14 -0
  61. package/dist/filters.js +218 -0
  62. package/dist/font-read.cjs +199 -0
  63. package/dist/font-read.d.cts +23 -0
  64. package/dist/font-read.d.ts +23 -0
  65. package/dist/font-read.js +198 -0
  66. package/dist/font-style.cjs +35 -0
  67. package/dist/font-style.d.cts +14 -0
  68. package/dist/font-style.d.ts +14 -0
  69. package/dist/font-style.js +34 -0
  70. package/dist/fonts.cjs +124 -0
  71. package/dist/fonts.d.cts +15 -0
  72. package/dist/fonts.d.ts +15 -0
  73. package/dist/fonts.js +122 -0
  74. package/dist/formula.cjs +0 -0
  75. package/dist/formula.d.cts +10 -0
  76. package/dist/formula.d.ts +10 -0
  77. package/dist/formula.js +0 -0
  78. package/dist/image/jpeg-info.cjs +71 -0
  79. package/dist/image/jpeg-info.d.cts +12 -0
  80. package/dist/image/jpeg-info.d.ts +12 -0
  81. package/dist/image/jpeg-info.js +70 -0
  82. package/dist/image/png-decode.cjs +181 -0
  83. package/dist/image/png-decode.d.cts +14 -0
  84. package/dist/image/png-decode.d.ts +14 -0
  85. package/dist/image/png-decode.js +180 -0
  86. package/dist/image/png-encode.cjs +64 -0
  87. package/dist/image/png-encode.d.cts +8 -0
  88. package/dist/image/png-encode.d.ts +8 -0
  89. package/dist/image/png-encode.js +63 -0
  90. package/dist/image/png-filter.cjs +95 -0
  91. package/dist/image/png-filter.d.cts +6 -0
  92. package/dist/image/png-filter.d.ts +6 -0
  93. package/dist/image/png-filter.js +93 -0
  94. package/dist/images-read.cjs +250 -0
  95. package/dist/images-read.d.cts +13 -0
  96. package/dist/images-read.d.ts +13 -0
  97. package/dist/images-read.js +249 -0
  98. package/dist/index.cjs +45 -5912
  99. package/dist/index.d.cts +21 -483
  100. package/dist/index.d.ts +21 -483
  101. package/dist/index.js +18 -5885
  102. package/dist/interpret.cjs +587 -0
  103. package/dist/interpret.d.cts +84 -0
  104. package/dist/interpret.d.ts +84 -0
  105. package/dist/interpret.js +586 -0
  106. package/dist/lexer.cjs +180 -0
  107. package/dist/lexer.d.cts +29 -0
  108. package/dist/lexer.d.ts +29 -0
  109. package/dist/lexer.js +179 -0
  110. package/dist/math-cmap.cjs +81 -0
  111. package/dist/math-cmap.d.cts +6 -0
  112. package/dist/math-cmap.d.ts +6 -0
  113. package/dist/math-cmap.js +80 -0
  114. package/dist/math-content-write.cjs +83 -0
  115. package/dist/math-content-write.d.cts +11 -0
  116. package/dist/math-content-write.d.ts +11 -0
  117. package/dist/math-content-write.js +81 -0
  118. package/dist/math-font-write.cjs +100 -0
  119. package/dist/math-font-write.d.cts +19 -0
  120. package/dist/math-font-write.d.ts +19 -0
  121. package/dist/math-font-write.js +99 -0
  122. package/dist/math-font.cjs +103 -0
  123. package/dist/math-font.d.cts +25 -0
  124. package/dist/math-font.d.ts +25 -0
  125. package/dist/math-font.js +102 -0
  126. package/dist/math-hmtx.cjs +17 -0
  127. package/dist/math-hmtx.d.cts +8 -0
  128. package/dist/math-hmtx.d.ts +8 -0
  129. package/dist/math-hmtx.js +16 -0
  130. package/dist/math-table.cjs +117 -0
  131. package/dist/math-table.d.cts +45 -0
  132. package/dist/math-table.d.ts +45 -0
  133. package/dist/math-table.js +116 -0
  134. package/dist/math-types-Ba8qAf1p.d.cts +82 -0
  135. package/dist/math-types-Ba8qAf1p.d.ts +82 -0
  136. package/dist/math-types.cjs +0 -0
  137. package/dist/math-types.d.cts +2 -0
  138. package/dist/math-types.d.ts +2 -0
  139. package/dist/math-types.js +0 -0
  140. package/dist/matrix-B3c2_a2f.d.cts +18 -0
  141. package/dist/matrix-B3c2_a2f.d.ts +18 -0
  142. package/dist/matrix.cjs +93 -0
  143. package/dist/matrix.d.cts +2 -0
  144. package/dist/matrix.d.ts +2 -0
  145. package/dist/matrix.js +83 -0
  146. package/dist/measure.cjs +54 -0
  147. package/dist/measure.d.cts +20 -0
  148. package/dist/measure.d.ts +20 -0
  149. package/dist/measure.js +53 -0
  150. package/dist/objects.cjs +100 -0
  151. package/dist/objects.d.cts +58 -0
  152. package/dist/objects.d.ts +58 -0
  153. package/dist/objects.js +84 -0
  154. package/dist/parse.cjs +230 -0
  155. package/dist/parse.d.cts +13 -0
  156. package/dist/parse.d.ts +13 -0
  157. package/dist/parse.js +228 -0
  158. package/dist/predictors.cjs +64 -0
  159. package/dist/predictors.d.cts +13 -0
  160. package/dist/predictors.d.ts +13 -0
  161. package/dist/predictors.js +62 -0
  162. package/dist/read.cjs +418 -0
  163. package/dist/read.d.cts +21 -0
  164. package/dist/read.d.ts +21 -0
  165. package/dist/read.js +413 -0
  166. package/dist/serialize.cjs +69 -0
  167. package/dist/serialize.d.cts +8 -0
  168. package/dist/serialize.d.ts +8 -0
  169. package/dist/serialize.js +66 -0
  170. package/dist/sfnt.cjs +52 -0
  171. package/dist/sfnt.d.cts +17 -0
  172. package/dist/sfnt.d.ts +17 -0
  173. package/dist/sfnt.js +46 -0
  174. package/dist/text-layout.cjs +224 -0
  175. package/dist/text-layout.d.cts +37 -0
  176. package/dist/text-layout.d.ts +37 -0
  177. package/dist/text-layout.js +222 -0
  178. package/dist/util/abort.cjs +7 -0
  179. package/dist/util/abort.d.cts +4 -0
  180. package/dist/util/abort.d.ts +4 -0
  181. package/dist/util/abort.js +6 -0
  182. package/dist/util/base64.cjs +48 -0
  183. package/dist/util/base64.d.cts +5 -0
  184. package/dist/util/base64.d.ts +5 -0
  185. package/dist/util/base64.js +46 -0
  186. package/dist/winansi.cjs +5 -0
  187. package/dist/winansi.d.cts +20 -0
  188. package/dist/winansi.d.ts +20 -0
  189. package/dist/winansi.js +2 -0
  190. package/dist/write.cjs +421 -0
  191. package/dist/write.d.cts +16 -0
  192. package/dist/write.d.ts +16 -0
  193. package/dist/write.js +419 -0
  194. package/dist/xref.cjs +325 -0
  195. package/dist/xref.d.cts +21 -0
  196. package/dist/xref.d.ts +21 -0
  197. package/dist/xref.js +324 -0
  198. package/package.json +9 -1
@@ -0,0 +1,199 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_afm_widths = require("./afm-widths-BoeTOK2r.cjs");
3
+ const require_cmap = require("./cmap.cjs");
4
+ const require_objects = require("./objects.cjs");
5
+ const require_filters = require("./filters.cjs");
6
+ const require_fonts = require("./fonts.cjs");
7
+ const require_font_style = require("./font-style.cjs");
8
+ //#region src/font-read.ts
9
+ const ITALIC_FLAG_BIT = 64;
10
+ const FORCE_BOLD_FLAG_BIT = 1 << 18;
11
+ const REPLACEMENT_CHARACTER = "�";
12
+ function styleFlagsFromDescriptor(descriptor) {
13
+ const flags = descriptor !== void 0 ? require_objects.asNumber(require_objects.dictGet(descriptor, "Flags")) : void 0;
14
+ return {
15
+ forceBold: flags !== void 0 ? (flags & FORCE_BOLD_FLAG_BIT) !== 0 : void 0,
16
+ italicFlag: flags !== void 0 ? (flags & ITALIC_FLAG_BIT) !== 0 : void 0,
17
+ italicAngle: descriptor !== void 0 ? require_objects.asNumber(require_objects.dictGet(descriptor, "ItalicAngle")) : void 0
18
+ };
19
+ }
20
+ function glyphNameToUnicodeWithUniFallback(name) {
21
+ const direct = require_afm_widths.glyphNameToUnicode(name);
22
+ if (direct !== void 0) return direct;
23
+ const uniMatch = /^uni([0-9A-Fa-f]{4,6})$/.exec(name);
24
+ return uniMatch?.[1] !== void 0 ? Number.parseInt(uniMatch[1], 16) : void 0;
25
+ }
26
+ function readDifferencesMap(differences) {
27
+ const map = /* @__PURE__ */ new Map();
28
+ if (differences === void 0) return map;
29
+ let currentCode = 0;
30
+ for (const el of differences) if (el.kind === "number") currentCode = el.value;
31
+ else if (el.kind === "name") {
32
+ map.set(currentCode, el.name);
33
+ currentCode++;
34
+ }
35
+ return map;
36
+ }
37
+ function readToUnicodeCMap(fontDict, context) {
38
+ const stream = context.resolver.resolve(require_objects.dictGet(fontDict, "ToUnicode"));
39
+ if (stream?.kind !== "stream") return;
40
+ const decoded = require_filters.decodeStream(stream.raw, stream.dict, context.sink);
41
+ return require_cmap.parseToUnicodeCMap(decoded.bytes, context.sink);
42
+ }
43
+ function buildSimpleFont(fontDict, context) {
44
+ const baseFont = require_objects.asName(require_objects.dictGet(fontDict, "BaseFont")) ?? "Helvetica";
45
+ const descriptor = context.resolver.resolveDict(require_objects.dictGet(fontDict, "FontDescriptor"));
46
+ const { baseFamily, bold, italic } = require_font_style.styleFromBaseFontName(baseFont, styleFlagsFromDescriptor(descriptor));
47
+ const widthsArr = require_objects.asArray(require_objects.dictGet(fontDict, "Widths"));
48
+ const firstChar = require_objects.asNumber(require_objects.dictGet(fontDict, "FirstChar")) ?? 0;
49
+ const missingWidth = (descriptor !== void 0 ? require_objects.asNumber(require_objects.dictGet(descriptor, "MissingWidth")) : void 0) ?? 0;
50
+ let widthOf;
51
+ if (widthsArr !== void 0) widthOf = (code) => require_objects.asNumber(widthsArr[code - firstChar]) ?? missingWidth;
52
+ else {
53
+ const standardMatch = require_fonts.resolveStandardFont(baseFamily, bold, italic);
54
+ widthOf = (code) => require_afm_widths.widthOfCode(standardMatch.standardName, code);
55
+ if (!standardMatch.matched) context.sink({
56
+ code: "pdf/font-widths-missing",
57
+ severity: "warning",
58
+ message: `font "${baseFont}" has no /Widths array and does not match a standard-14 family; falling back to Helvetica metrics`
59
+ });
60
+ }
61
+ const toUnicode = readToUnicodeCMap(fontDict, context);
62
+ const encodingObj = require_objects.dictGet(fontDict, "Encoding");
63
+ const encodingDict = context.resolver.resolveDict(encodingObj);
64
+ const baseEncodingName = require_objects.asName(encodingDict !== void 0 ? require_objects.dictGet(encodingDict, "BaseEncoding") : encodingObj);
65
+ if (baseEncodingName !== void 0 && baseEncodingName !== "WinAnsiEncoding") context.sink({
66
+ code: "char/encoding-approximated",
67
+ severity: "info",
68
+ message: `base encoding "${baseEncodingName}" has no dedicated table here and is approximated as WinAnsiEncoding`
69
+ });
70
+ const differencesMap = readDifferencesMap(encodingDict !== void 0 ? require_objects.asArray(require_objects.dictGet(encodingDict, "Differences")) : void 0);
71
+ const decodeToUnicode = (codes) => {
72
+ let out = "";
73
+ let unmapped = 0;
74
+ for (const code of codes) {
75
+ const viaToUnicode = toUnicode?.lookup(code);
76
+ if (viaToUnicode !== void 0) {
77
+ out += viaToUnicode;
78
+ continue;
79
+ }
80
+ const name = differencesMap.get(code) ?? require_afm_widths.winAnsiGlyphName(code);
81
+ const unicode = name !== void 0 ? glyphNameToUnicodeWithUniFallback(name) : void 0;
82
+ if (unicode !== void 0) {
83
+ out += String.fromCharCode(unicode);
84
+ continue;
85
+ }
86
+ unmapped++;
87
+ out += REPLACEMENT_CHARACTER;
88
+ }
89
+ if (unmapped > 0) context.sink({
90
+ code: "text/unmapped-encoding",
91
+ severity: unmapped > codes.length / 2 ? "warning" : "info",
92
+ message: `${String(unmapped)} of ${String(codes.length)} character code(s) in font "${baseFont}" could not be mapped to Unicode`
93
+ });
94
+ return out;
95
+ };
96
+ return {
97
+ composite: false,
98
+ family: baseFamily,
99
+ bold,
100
+ italic,
101
+ widthOf,
102
+ decodeToUnicode
103
+ };
104
+ }
105
+ function readCidWidths(w) {
106
+ const map = /* @__PURE__ */ new Map();
107
+ if (w === void 0) return map;
108
+ let i = 0;
109
+ while (i < w.length) {
110
+ const first = require_objects.asNumber(w[i]);
111
+ if (first === void 0) {
112
+ i++;
113
+ continue;
114
+ }
115
+ const next = w[i + 1];
116
+ if (next?.kind === "array") {
117
+ next.items.forEach((item, offset) => {
118
+ const width = require_objects.asNumber(item);
119
+ if (width !== void 0) map.set(first + offset, width);
120
+ });
121
+ i += 2;
122
+ } else {
123
+ const last = require_objects.asNumber(next);
124
+ const width = require_objects.asNumber(w[i + 2]);
125
+ if (last !== void 0 && width !== void 0) for (let cid = first; cid <= last; cid++) map.set(cid, width);
126
+ i += 3;
127
+ }
128
+ }
129
+ return map;
130
+ }
131
+ const DEFAULT_CID_WIDTH = 1e3;
132
+ function buildCompositeFont(fontDict, context) {
133
+ const baseFont = require_objects.asName(require_objects.dictGet(fontDict, "BaseFont")) ?? "Helvetica";
134
+ const descendants = require_objects.asArray(require_objects.dictGet(fontDict, "DescendantFonts"));
135
+ const descendantDict = descendants !== void 0 ? context.resolver.resolveDict(descendants[0]) : void 0;
136
+ const descriptor = descendantDict !== void 0 ? context.resolver.resolveDict(require_objects.dictGet(descendantDict, "FontDescriptor")) : void 0;
137
+ const { baseFamily, bold, italic } = require_font_style.styleFromBaseFontName(baseFont, styleFlagsFromDescriptor(descriptor));
138
+ const dw = descendantDict !== void 0 ? require_objects.asNumber(require_objects.dictGet(descendantDict, "DW")) ?? DEFAULT_CID_WIDTH : DEFAULT_CID_WIDTH;
139
+ const widthMap = readCidWidths(descendantDict !== void 0 ? require_objects.asArray(require_objects.dictGet(descendantDict, "W")) : void 0);
140
+ const widthOf = (cid) => widthMap.get(cid) ?? dw;
141
+ const toUnicode = readToUnicodeCMap(fontDict, context);
142
+ const decodeToUnicode = (codes) => {
143
+ let out = "";
144
+ let glyphCount = 0;
145
+ let unmapped = 0;
146
+ for (let i = 0; i + 1 < codes.length; i += 2) {
147
+ glyphCount++;
148
+ const cid = (codes[i] ?? 0) << 8 | (codes[i + 1] ?? 0);
149
+ const mapped = toUnicode?.lookup(cid);
150
+ if (mapped !== void 0) {
151
+ out += mapped;
152
+ continue;
153
+ }
154
+ unmapped++;
155
+ out += REPLACEMENT_CHARACTER;
156
+ }
157
+ if (unmapped > 0) context.sink({
158
+ code: "text/unmapped-encoding",
159
+ severity: unmapped > glyphCount / 2 ? "warning" : "info",
160
+ message: `${String(unmapped)} of ${String(glyphCount)} character code(s) in font "${baseFont}" could not be mapped to Unicode (no /ToUnicode CMap, or an incomplete one)`
161
+ });
162
+ return out;
163
+ };
164
+ return {
165
+ composite: true,
166
+ family: baseFamily,
167
+ bold,
168
+ italic,
169
+ widthOf,
170
+ decodeToUnicode
171
+ };
172
+ }
173
+ function createFontResolver(context) {
174
+ const cache = /* @__PURE__ */ new Map();
175
+ const resolve = (fontResourceName, resources) => {
176
+ const fontsDict = context.resolver.resolveDict(require_objects.dictGet(resources, "Font"));
177
+ const fontDict = fontsDict !== void 0 ? context.resolver.resolveDict(require_objects.dictGet(fontsDict, fontResourceName)) : void 0;
178
+ if (fontDict === void 0) return;
179
+ if (cache.has(fontDict)) return cache.get(fontDict);
180
+ const resolved = require_objects.asName(require_objects.dictGet(fontDict, "Subtype")) === "Type0" ? buildCompositeFont(fontDict, context) : buildSimpleFont(fontDict, context);
181
+ cache.set(fontDict, resolved);
182
+ return resolved;
183
+ };
184
+ return {
185
+ metrics: { glyphAdvance(fontResourceName, resources, codes, byteOffset) {
186
+ const font = resolve(fontResourceName, resources);
187
+ if (font === void 0) return;
188
+ const byteLengthConsumed = font.composite ? 2 : 1;
189
+ const code = font.composite ? (codes[byteOffset] ?? 0) << 8 | (codes[byteOffset + 1] ?? 0) : codes[byteOffset] ?? 0;
190
+ return {
191
+ widthPer1000: font.widthOf(code),
192
+ byteLengthConsumed
193
+ };
194
+ } },
195
+ resolve
196
+ };
197
+ }
198
+ //#endregion
199
+ exports.createFontResolver = createFontResolver;
@@ -0,0 +1,23 @@
1
+ import { PdfDiagnosticSink } from "./diagnostics.cjs";
2
+ import { PdfDict } from "./objects.cjs";
3
+ import { FontMetricsPort, PdfObjectResolver } from "./interpret.cjs";
4
+ //#region src/font-read.d.ts
5
+ interface PdfFont {
6
+ readonly composite: boolean;
7
+ readonly family: string;
8
+ readonly bold: boolean;
9
+ readonly italic: boolean;
10
+ widthOf(code: number): number;
11
+ decodeToUnicode(codes: Uint8Array<ArrayBuffer>): string;
12
+ }
13
+ interface FontReadContext {
14
+ readonly resolver: PdfObjectResolver;
15
+ readonly sink: PdfDiagnosticSink;
16
+ }
17
+ interface FontResolverService {
18
+ readonly metrics: FontMetricsPort;
19
+ readonly resolve: (fontResourceName: string, resources: PdfDict) => PdfFont | undefined;
20
+ }
21
+ declare function createFontResolver(context: FontReadContext): FontResolverService;
22
+ //#endregion
23
+ export { FontReadContext, FontResolverService, PdfFont, createFontResolver };
@@ -0,0 +1,23 @@
1
+ import { PdfDiagnosticSink } from "./diagnostics.js";
2
+ import { PdfDict } from "./objects.js";
3
+ import { FontMetricsPort, PdfObjectResolver } from "./interpret.js";
4
+ //#region src/font-read.d.ts
5
+ interface PdfFont {
6
+ readonly composite: boolean;
7
+ readonly family: string;
8
+ readonly bold: boolean;
9
+ readonly italic: boolean;
10
+ widthOf(code: number): number;
11
+ decodeToUnicode(codes: Uint8Array<ArrayBuffer>): string;
12
+ }
13
+ interface FontReadContext {
14
+ readonly resolver: PdfObjectResolver;
15
+ readonly sink: PdfDiagnosticSink;
16
+ }
17
+ interface FontResolverService {
18
+ readonly metrics: FontMetricsPort;
19
+ readonly resolve: (fontResourceName: string, resources: PdfDict) => PdfFont | undefined;
20
+ }
21
+ declare function createFontResolver(context: FontReadContext): FontResolverService;
22
+ //#endregion
23
+ export { FontReadContext, FontResolverService, PdfFont, createFontResolver };
@@ -0,0 +1,198 @@
1
+ import { a as winAnsiGlyphName, i as glyphNameToUnicode, n as widthOfCode } from "./afm-widths-Dxucrg7D.js";
2
+ import { parseToUnicodeCMap } from "./cmap.js";
3
+ import { asArray, asName, asNumber, dictGet } from "./objects.js";
4
+ import { decodeStream } from "./filters.js";
5
+ import { resolveStandardFont } from "./fonts.js";
6
+ import { styleFromBaseFontName } from "./font-style.js";
7
+ //#region src/font-read.ts
8
+ const ITALIC_FLAG_BIT = 64;
9
+ const FORCE_BOLD_FLAG_BIT = 1 << 18;
10
+ const REPLACEMENT_CHARACTER = "�";
11
+ function styleFlagsFromDescriptor(descriptor) {
12
+ const flags = descriptor !== void 0 ? asNumber(dictGet(descriptor, "Flags")) : void 0;
13
+ return {
14
+ forceBold: flags !== void 0 ? (flags & FORCE_BOLD_FLAG_BIT) !== 0 : void 0,
15
+ italicFlag: flags !== void 0 ? (flags & ITALIC_FLAG_BIT) !== 0 : void 0,
16
+ italicAngle: descriptor !== void 0 ? asNumber(dictGet(descriptor, "ItalicAngle")) : void 0
17
+ };
18
+ }
19
+ function glyphNameToUnicodeWithUniFallback(name) {
20
+ const direct = glyphNameToUnicode(name);
21
+ if (direct !== void 0) return direct;
22
+ const uniMatch = /^uni([0-9A-Fa-f]{4,6})$/.exec(name);
23
+ return uniMatch?.[1] !== void 0 ? Number.parseInt(uniMatch[1], 16) : void 0;
24
+ }
25
+ function readDifferencesMap(differences) {
26
+ const map = /* @__PURE__ */ new Map();
27
+ if (differences === void 0) return map;
28
+ let currentCode = 0;
29
+ for (const el of differences) if (el.kind === "number") currentCode = el.value;
30
+ else if (el.kind === "name") {
31
+ map.set(currentCode, el.name);
32
+ currentCode++;
33
+ }
34
+ return map;
35
+ }
36
+ function readToUnicodeCMap(fontDict, context) {
37
+ const stream = context.resolver.resolve(dictGet(fontDict, "ToUnicode"));
38
+ if (stream?.kind !== "stream") return;
39
+ const decoded = decodeStream(stream.raw, stream.dict, context.sink);
40
+ return parseToUnicodeCMap(decoded.bytes, context.sink);
41
+ }
42
+ function buildSimpleFont(fontDict, context) {
43
+ const baseFont = asName(dictGet(fontDict, "BaseFont")) ?? "Helvetica";
44
+ const descriptor = context.resolver.resolveDict(dictGet(fontDict, "FontDescriptor"));
45
+ const { baseFamily, bold, italic } = styleFromBaseFontName(baseFont, styleFlagsFromDescriptor(descriptor));
46
+ const widthsArr = asArray(dictGet(fontDict, "Widths"));
47
+ const firstChar = asNumber(dictGet(fontDict, "FirstChar")) ?? 0;
48
+ const missingWidth = (descriptor !== void 0 ? asNumber(dictGet(descriptor, "MissingWidth")) : void 0) ?? 0;
49
+ let widthOf;
50
+ if (widthsArr !== void 0) widthOf = (code) => asNumber(widthsArr[code - firstChar]) ?? missingWidth;
51
+ else {
52
+ const standardMatch = resolveStandardFont(baseFamily, bold, italic);
53
+ widthOf = (code) => widthOfCode(standardMatch.standardName, code);
54
+ if (!standardMatch.matched) context.sink({
55
+ code: "pdf/font-widths-missing",
56
+ severity: "warning",
57
+ message: `font "${baseFont}" has no /Widths array and does not match a standard-14 family; falling back to Helvetica metrics`
58
+ });
59
+ }
60
+ const toUnicode = readToUnicodeCMap(fontDict, context);
61
+ const encodingObj = dictGet(fontDict, "Encoding");
62
+ const encodingDict = context.resolver.resolveDict(encodingObj);
63
+ const baseEncodingName = asName(encodingDict !== void 0 ? dictGet(encodingDict, "BaseEncoding") : encodingObj);
64
+ if (baseEncodingName !== void 0 && baseEncodingName !== "WinAnsiEncoding") context.sink({
65
+ code: "char/encoding-approximated",
66
+ severity: "info",
67
+ message: `base encoding "${baseEncodingName}" has no dedicated table here and is approximated as WinAnsiEncoding`
68
+ });
69
+ const differencesMap = readDifferencesMap(encodingDict !== void 0 ? asArray(dictGet(encodingDict, "Differences")) : void 0);
70
+ const decodeToUnicode = (codes) => {
71
+ let out = "";
72
+ let unmapped = 0;
73
+ for (const code of codes) {
74
+ const viaToUnicode = toUnicode?.lookup(code);
75
+ if (viaToUnicode !== void 0) {
76
+ out += viaToUnicode;
77
+ continue;
78
+ }
79
+ const name = differencesMap.get(code) ?? winAnsiGlyphName(code);
80
+ const unicode = name !== void 0 ? glyphNameToUnicodeWithUniFallback(name) : void 0;
81
+ if (unicode !== void 0) {
82
+ out += String.fromCharCode(unicode);
83
+ continue;
84
+ }
85
+ unmapped++;
86
+ out += REPLACEMENT_CHARACTER;
87
+ }
88
+ if (unmapped > 0) context.sink({
89
+ code: "text/unmapped-encoding",
90
+ severity: unmapped > codes.length / 2 ? "warning" : "info",
91
+ message: `${String(unmapped)} of ${String(codes.length)} character code(s) in font "${baseFont}" could not be mapped to Unicode`
92
+ });
93
+ return out;
94
+ };
95
+ return {
96
+ composite: false,
97
+ family: baseFamily,
98
+ bold,
99
+ italic,
100
+ widthOf,
101
+ decodeToUnicode
102
+ };
103
+ }
104
+ function readCidWidths(w) {
105
+ const map = /* @__PURE__ */ new Map();
106
+ if (w === void 0) return map;
107
+ let i = 0;
108
+ while (i < w.length) {
109
+ const first = asNumber(w[i]);
110
+ if (first === void 0) {
111
+ i++;
112
+ continue;
113
+ }
114
+ const next = w[i + 1];
115
+ if (next?.kind === "array") {
116
+ next.items.forEach((item, offset) => {
117
+ const width = asNumber(item);
118
+ if (width !== void 0) map.set(first + offset, width);
119
+ });
120
+ i += 2;
121
+ } else {
122
+ const last = asNumber(next);
123
+ const width = asNumber(w[i + 2]);
124
+ if (last !== void 0 && width !== void 0) for (let cid = first; cid <= last; cid++) map.set(cid, width);
125
+ i += 3;
126
+ }
127
+ }
128
+ return map;
129
+ }
130
+ const DEFAULT_CID_WIDTH = 1e3;
131
+ function buildCompositeFont(fontDict, context) {
132
+ const baseFont = asName(dictGet(fontDict, "BaseFont")) ?? "Helvetica";
133
+ const descendants = asArray(dictGet(fontDict, "DescendantFonts"));
134
+ const descendantDict = descendants !== void 0 ? context.resolver.resolveDict(descendants[0]) : void 0;
135
+ const descriptor = descendantDict !== void 0 ? context.resolver.resolveDict(dictGet(descendantDict, "FontDescriptor")) : void 0;
136
+ const { baseFamily, bold, italic } = styleFromBaseFontName(baseFont, styleFlagsFromDescriptor(descriptor));
137
+ const dw = descendantDict !== void 0 ? asNumber(dictGet(descendantDict, "DW")) ?? DEFAULT_CID_WIDTH : DEFAULT_CID_WIDTH;
138
+ const widthMap = readCidWidths(descendantDict !== void 0 ? asArray(dictGet(descendantDict, "W")) : void 0);
139
+ const widthOf = (cid) => widthMap.get(cid) ?? dw;
140
+ const toUnicode = readToUnicodeCMap(fontDict, context);
141
+ const decodeToUnicode = (codes) => {
142
+ let out = "";
143
+ let glyphCount = 0;
144
+ let unmapped = 0;
145
+ for (let i = 0; i + 1 < codes.length; i += 2) {
146
+ glyphCount++;
147
+ const cid = (codes[i] ?? 0) << 8 | (codes[i + 1] ?? 0);
148
+ const mapped = toUnicode?.lookup(cid);
149
+ if (mapped !== void 0) {
150
+ out += mapped;
151
+ continue;
152
+ }
153
+ unmapped++;
154
+ out += REPLACEMENT_CHARACTER;
155
+ }
156
+ if (unmapped > 0) context.sink({
157
+ code: "text/unmapped-encoding",
158
+ severity: unmapped > glyphCount / 2 ? "warning" : "info",
159
+ message: `${String(unmapped)} of ${String(glyphCount)} character code(s) in font "${baseFont}" could not be mapped to Unicode (no /ToUnicode CMap, or an incomplete one)`
160
+ });
161
+ return out;
162
+ };
163
+ return {
164
+ composite: true,
165
+ family: baseFamily,
166
+ bold,
167
+ italic,
168
+ widthOf,
169
+ decodeToUnicode
170
+ };
171
+ }
172
+ function createFontResolver(context) {
173
+ const cache = /* @__PURE__ */ new Map();
174
+ const resolve = (fontResourceName, resources) => {
175
+ const fontsDict = context.resolver.resolveDict(dictGet(resources, "Font"));
176
+ const fontDict = fontsDict !== void 0 ? context.resolver.resolveDict(dictGet(fontsDict, fontResourceName)) : void 0;
177
+ if (fontDict === void 0) return;
178
+ if (cache.has(fontDict)) return cache.get(fontDict);
179
+ const resolved = asName(dictGet(fontDict, "Subtype")) === "Type0" ? buildCompositeFont(fontDict, context) : buildSimpleFont(fontDict, context);
180
+ cache.set(fontDict, resolved);
181
+ return resolved;
182
+ };
183
+ return {
184
+ metrics: { glyphAdvance(fontResourceName, resources, codes, byteOffset) {
185
+ const font = resolve(fontResourceName, resources);
186
+ if (font === void 0) return;
187
+ const byteLengthConsumed = font.composite ? 2 : 1;
188
+ const code = font.composite ? (codes[byteOffset] ?? 0) << 8 | (codes[byteOffset + 1] ?? 0) : codes[byteOffset] ?? 0;
189
+ return {
190
+ widthPer1000: font.widthOf(code),
191
+ byteLengthConsumed
192
+ };
193
+ } },
194
+ resolve
195
+ };
196
+ }
197
+ //#endregion
198
+ export { createFontResolver };
@@ -0,0 +1,35 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ //#region src/font-style.ts
3
+ const SUBSET_TAG_PATTERN = /^[A-Z]{6}\+/;
4
+ const KNOWN_STYLE_SUFFIXES = [
5
+ "BoldItalic",
6
+ "BoldOblique",
7
+ "Bold",
8
+ "Italic",
9
+ "Oblique",
10
+ "Regular"
11
+ ];
12
+ function stripStyleSuffix(name) {
13
+ for (const suffix of KNOWN_STYLE_SUFFIXES) {
14
+ const commaPattern = new RegExp(`,${suffix}$`, "i");
15
+ const hyphenPattern = new RegExp(`-${suffix}$`, "i");
16
+ if (commaPattern.test(name)) return name.replace(commaPattern, "");
17
+ if (hyphenPattern.test(name)) return name.replace(hyphenPattern, "");
18
+ }
19
+ return name;
20
+ }
21
+ function styleFromBaseFontName(baseFont, flags) {
22
+ const withoutSubset = baseFont.replace(SUBSET_TAG_PATTERN, "");
23
+ const lower = withoutSubset.toLowerCase();
24
+ const nameBold = lower.includes("bold");
25
+ const nameItalic = /italic|oblique/.test(lower);
26
+ const bold = nameBold || (flags?.forceBold ?? false);
27
+ const italic = nameItalic || (flags?.italicFlag ?? false) || flags?.italicAngle !== void 0 && flags.italicAngle !== 0;
28
+ return {
29
+ baseFamily: stripStyleSuffix(withoutSubset),
30
+ bold,
31
+ italic
32
+ };
33
+ }
34
+ //#endregion
35
+ exports.styleFromBaseFontName = styleFromBaseFontName;
@@ -0,0 +1,14 @@
1
+ //#region src/font-style.d.ts
2
+ interface FontStyleFlags {
3
+ readonly forceBold?: boolean;
4
+ readonly italicFlag?: boolean;
5
+ readonly italicAngle?: number;
6
+ }
7
+ interface FontNameStyle {
8
+ readonly baseFamily: string;
9
+ readonly bold: boolean;
10
+ readonly italic: boolean;
11
+ }
12
+ declare function styleFromBaseFontName(baseFont: string, flags?: FontStyleFlags): FontNameStyle;
13
+ //#endregion
14
+ export { FontNameStyle, FontStyleFlags, styleFromBaseFontName };
@@ -0,0 +1,14 @@
1
+ //#region src/font-style.d.ts
2
+ interface FontStyleFlags {
3
+ readonly forceBold?: boolean;
4
+ readonly italicFlag?: boolean;
5
+ readonly italicAngle?: number;
6
+ }
7
+ interface FontNameStyle {
8
+ readonly baseFamily: string;
9
+ readonly bold: boolean;
10
+ readonly italic: boolean;
11
+ }
12
+ declare function styleFromBaseFontName(baseFont: string, flags?: FontStyleFlags): FontNameStyle;
13
+ //#endregion
14
+ export { FontNameStyle, FontStyleFlags, styleFromBaseFontName };
@@ -0,0 +1,34 @@
1
+ //#region src/font-style.ts
2
+ const SUBSET_TAG_PATTERN = /^[A-Z]{6}\+/;
3
+ const KNOWN_STYLE_SUFFIXES = [
4
+ "BoldItalic",
5
+ "BoldOblique",
6
+ "Bold",
7
+ "Italic",
8
+ "Oblique",
9
+ "Regular"
10
+ ];
11
+ function stripStyleSuffix(name) {
12
+ for (const suffix of KNOWN_STYLE_SUFFIXES) {
13
+ const commaPattern = new RegExp(`,${suffix}$`, "i");
14
+ const hyphenPattern = new RegExp(`-${suffix}$`, "i");
15
+ if (commaPattern.test(name)) return name.replace(commaPattern, "");
16
+ if (hyphenPattern.test(name)) return name.replace(hyphenPattern, "");
17
+ }
18
+ return name;
19
+ }
20
+ function styleFromBaseFontName(baseFont, flags) {
21
+ const withoutSubset = baseFont.replace(SUBSET_TAG_PATTERN, "");
22
+ const lower = withoutSubset.toLowerCase();
23
+ const nameBold = lower.includes("bold");
24
+ const nameItalic = /italic|oblique/.test(lower);
25
+ const bold = nameBold || (flags?.forceBold ?? false);
26
+ const italic = nameItalic || (flags?.italicFlag ?? false) || flags?.italicAngle !== void 0 && flags.italicAngle !== 0;
27
+ return {
28
+ baseFamily: stripStyleSuffix(withoutSubset),
29
+ bold,
30
+ italic
31
+ };
32
+ }
33
+ //#endregion
34
+ export { styleFromBaseFontName };
package/dist/fonts.cjs ADDED
@@ -0,0 +1,124 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ //#region src/fonts.ts
3
+ const FAMILY_BY_NORMALIZED_NAME = /* @__PURE__ */ new Map([
4
+ ["helvetica", "helvetica"],
5
+ ["helveticaneue", "helvetica"],
6
+ ["arial", "helvetica"],
7
+ ["arialnarrow", "helvetica"],
8
+ ["arialblack", "helvetica"],
9
+ ["calibri", "helvetica"],
10
+ ["aptos", "helvetica"],
11
+ ["aptosdisplay", "helvetica"],
12
+ ["segoeui", "helvetica"],
13
+ ["tahoma", "helvetica"],
14
+ ["verdana", "helvetica"],
15
+ ["trebuchetms", "helvetica"],
16
+ ["centurygothic", "helvetica"],
17
+ ["franklingothicbook", "helvetica"],
18
+ ["gillsans", "helvetica"],
19
+ ["futura", "helvetica"],
20
+ ["roboto", "helvetica"],
21
+ ["opensans", "helvetica"],
22
+ ["lato", "helvetica"],
23
+ ["montserrat", "helvetica"],
24
+ ["poppins", "helvetica"],
25
+ ["inter", "helvetica"],
26
+ ["notosans", "helvetica"],
27
+ ["dejavusans", "helvetica"],
28
+ ["sourcesanspro", "helvetica"],
29
+ ["sansserif", "helvetica"],
30
+ ["liberationsans", "helvetica"],
31
+ ["nimbussans", "helvetica"],
32
+ ["times", "times"],
33
+ ["timesnewroman", "times"],
34
+ ["liberationserif", "times"],
35
+ ["nimbusroman", "times"],
36
+ ["georgia", "times"],
37
+ ["cambria", "times"],
38
+ ["constantia", "times"],
39
+ ["garamond", "times"],
40
+ ["bookantiqua", "times"],
41
+ ["palatino", "times"],
42
+ ["palatinolinotype", "times"],
43
+ ["bookmanoldstyle", "times"],
44
+ ["century", "times"],
45
+ ["centuryschoolbook", "times"],
46
+ ["minionpro", "times"],
47
+ ["merriweather", "times"],
48
+ ["notoserif", "times"],
49
+ ["dejavuserif", "times"],
50
+ ["serif", "times"],
51
+ ["courier", "courier"],
52
+ ["couriernew", "courier"],
53
+ ["liberationmono", "courier"],
54
+ ["nimbusmono", "courier"],
55
+ ["consolas", "courier"],
56
+ ["monaco", "courier"],
57
+ ["menlo", "courier"],
58
+ ["lucidaconsole", "courier"],
59
+ ["andalemono", "courier"],
60
+ ["cascadiacode", "courier"],
61
+ ["cascadiamono", "courier"],
62
+ ["sfmono", "courier"],
63
+ ["jetbrainsmono", "courier"],
64
+ ["firacode", "courier"],
65
+ ["sourcecodepro", "courier"],
66
+ ["notosansmono", "courier"],
67
+ ["dejavusansmono", "courier"],
68
+ ["monospace", "courier"]
69
+ ]);
70
+ const DEFAULT_FAMILY = "helvetica";
71
+ function normalizeFamilyName(raw) {
72
+ return raw.toLowerCase().replace(/[^a-z0-9]/g, "");
73
+ }
74
+ function resolveFontFamily(rawFamily) {
75
+ const normalized = normalizeFamilyName(rawFamily);
76
+ const exact = FAMILY_BY_NORMALIZED_NAME.get(normalized);
77
+ if (exact !== void 0) return {
78
+ family: exact,
79
+ matched: true
80
+ };
81
+ if (normalized.includes("mono")) return {
82
+ family: "courier",
83
+ matched: true
84
+ };
85
+ if (normalized.includes("serif") && !normalized.includes("sansserif")) return {
86
+ family: "times",
87
+ matched: true
88
+ };
89
+ return {
90
+ family: DEFAULT_FAMILY,
91
+ matched: false
92
+ };
93
+ }
94
+ const VARIANTS = {
95
+ helvetica: {
96
+ regular: "Helvetica",
97
+ bold: "Helvetica-Bold",
98
+ italic: "Helvetica-Oblique",
99
+ boldItalic: "Helvetica-BoldOblique"
100
+ },
101
+ times: {
102
+ regular: "Times-Roman",
103
+ bold: "Times-Bold",
104
+ italic: "Times-Italic",
105
+ boldItalic: "Times-BoldItalic"
106
+ },
107
+ courier: {
108
+ regular: "Courier",
109
+ bold: "Courier-Bold",
110
+ italic: "Courier-Oblique",
111
+ boldItalic: "Courier-BoldOblique"
112
+ }
113
+ };
114
+ function resolveStandardFont(family, bold, italic) {
115
+ const { family: standardFamily, matched } = resolveFontFamily(family);
116
+ const variants = VARIANTS[standardFamily];
117
+ return {
118
+ standardName: bold && italic ? variants.boldItalic : bold ? variants.bold : italic ? variants.italic : variants.regular,
119
+ matched
120
+ };
121
+ }
122
+ //#endregion
123
+ exports.resolveFontFamily = resolveFontFamily;
124
+ exports.resolveStandardFont = resolveStandardFont;
@@ -0,0 +1,15 @@
1
+ import { r as StandardFontName } from "./afm-widths-DyDq56Ph.cjs";
2
+ //#region src/fonts.d.ts
3
+ type StandardFamily = 'helvetica' | 'times' | 'courier';
4
+ interface FontFamilyResolution {
5
+ readonly family: StandardFamily;
6
+ readonly matched: boolean;
7
+ }
8
+ declare function resolveFontFamily(rawFamily: string): FontFamilyResolution;
9
+ interface ResolvedFont {
10
+ readonly standardName: StandardFontName;
11
+ readonly matched: boolean;
12
+ }
13
+ declare function resolveStandardFont(family: string, bold: boolean, italic: boolean): ResolvedFont;
14
+ //#endregion
15
+ export { FontFamilyResolution, ResolvedFont, resolveFontFamily, resolveStandardFont };