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.
- package/README.md +38 -0
- package/dist/afm-widths-BoeTOK2r.cjs +826 -0
- package/dist/afm-widths-Dxucrg7D.js +779 -0
- package/dist/afm-widths-DyDq56Ph.d.cts +19 -0
- package/dist/afm-widths-DyDq56Ph.d.ts +19 -0
- package/dist/afm-widths.cjs +4 -0
- package/dist/afm-widths.d.cts +2 -0
- package/dist/afm-widths.d.ts +2 -0
- package/dist/afm-widths.js +2 -0
- package/dist/assets/stix-two-math-font.cjs +5 -0
- package/dist/assets/stix-two-math-font.d.cts +4 -0
- package/dist/assets/stix-two-math-font.d.ts +4 -0
- package/dist/assets/stix-two-math-font.js +4 -0
- package/dist/bytes/crc32.cjs +21 -0
- package/dist/bytes/crc32.d.cts +4 -0
- package/dist/bytes/crc32.d.ts +4 -0
- package/dist/bytes/crc32.js +20 -0
- package/dist/bytes/flate.cjs +53 -0
- package/dist/bytes/flate.d.cts +12 -0
- package/dist/bytes/flate.d.ts +12 -0
- package/dist/bytes/flate.js +49 -0
- package/dist/bytes/reader.cjs +60 -0
- package/dist/bytes/reader.d.cts +20 -0
- package/dist/bytes/reader.d.ts +20 -0
- package/dist/bytes/reader.js +58 -0
- package/dist/bytes/writer.cjs +37 -0
- package/dist/bytes/writer.d.cts +13 -0
- package/dist/bytes/writer.d.ts +13 -0
- package/dist/bytes/writer.js +35 -0
- package/dist/cmap.cjs +110 -0
- package/dist/cmap.d.cts +8 -0
- package/dist/cmap.d.ts +8 -0
- package/dist/cmap.js +109 -0
- package/dist/codec.cjs +34 -0
- package/dist/codec.d.cts +167 -0
- package/dist/codec.d.ts +167 -0
- package/dist/codec.js +32 -0
- package/dist/content-read.cjs +126 -0
- package/dist/content-read.d.cts +21 -0
- package/dist/content-read.d.ts +21 -0
- package/dist/content-read.js +125 -0
- package/dist/content-write.cjs +138 -0
- package/dist/content-write.d.cts +24 -0
- package/dist/content-write.d.ts +24 -0
- package/dist/content-write.js +137 -0
- package/dist/diagnostics.cjs +21 -0
- package/dist/diagnostics.d.cts +19 -0
- package/dist/diagnostics.d.ts +19 -0
- package/dist/diagnostics.js +18 -0
- package/dist/document.cjs +162 -0
- package/dist/document.d.cts +12 -0
- package/dist/document.d.ts +12 -0
- package/dist/document.js +161 -0
- package/dist/encoding.cjs +5 -0
- package/dist/encoding.d.cts +6 -0
- package/dist/encoding.d.ts +6 -0
- package/dist/encoding.js +2 -0
- package/dist/filters.cjs +223 -0
- package/dist/filters.d.cts +14 -0
- package/dist/filters.d.ts +14 -0
- package/dist/filters.js +218 -0
- package/dist/font-read.cjs +199 -0
- package/dist/font-read.d.cts +23 -0
- package/dist/font-read.d.ts +23 -0
- package/dist/font-read.js +198 -0
- package/dist/font-style.cjs +35 -0
- package/dist/font-style.d.cts +14 -0
- package/dist/font-style.d.ts +14 -0
- package/dist/font-style.js +34 -0
- package/dist/fonts.cjs +124 -0
- package/dist/fonts.d.cts +15 -0
- package/dist/fonts.d.ts +15 -0
- package/dist/fonts.js +122 -0
- package/dist/formula.cjs +0 -0
- package/dist/formula.d.cts +10 -0
- package/dist/formula.d.ts +10 -0
- package/dist/formula.js +0 -0
- package/dist/image/jpeg-info.cjs +71 -0
- package/dist/image/jpeg-info.d.cts +12 -0
- package/dist/image/jpeg-info.d.ts +12 -0
- package/dist/image/jpeg-info.js +70 -0
- package/dist/image/png-decode.cjs +181 -0
- package/dist/image/png-decode.d.cts +14 -0
- package/dist/image/png-decode.d.ts +14 -0
- package/dist/image/png-decode.js +180 -0
- package/dist/image/png-encode.cjs +64 -0
- package/dist/image/png-encode.d.cts +8 -0
- package/dist/image/png-encode.d.ts +8 -0
- package/dist/image/png-encode.js +63 -0
- package/dist/image/png-filter.cjs +95 -0
- package/dist/image/png-filter.d.cts +6 -0
- package/dist/image/png-filter.d.ts +6 -0
- package/dist/image/png-filter.js +93 -0
- package/dist/images-read.cjs +250 -0
- package/dist/images-read.d.cts +13 -0
- package/dist/images-read.d.ts +13 -0
- package/dist/images-read.js +249 -0
- package/dist/index.cjs +45 -5912
- package/dist/index.d.cts +21 -483
- package/dist/index.d.ts +21 -483
- package/dist/index.js +18 -5885
- package/dist/interpret.cjs +587 -0
- package/dist/interpret.d.cts +84 -0
- package/dist/interpret.d.ts +84 -0
- package/dist/interpret.js +586 -0
- package/dist/lexer.cjs +180 -0
- package/dist/lexer.d.cts +29 -0
- package/dist/lexer.d.ts +29 -0
- package/dist/lexer.js +179 -0
- package/dist/math-cmap.cjs +81 -0
- package/dist/math-cmap.d.cts +6 -0
- package/dist/math-cmap.d.ts +6 -0
- package/dist/math-cmap.js +80 -0
- package/dist/math-content-write.cjs +83 -0
- package/dist/math-content-write.d.cts +11 -0
- package/dist/math-content-write.d.ts +11 -0
- package/dist/math-content-write.js +81 -0
- package/dist/math-font-write.cjs +100 -0
- package/dist/math-font-write.d.cts +19 -0
- package/dist/math-font-write.d.ts +19 -0
- package/dist/math-font-write.js +99 -0
- package/dist/math-font.cjs +103 -0
- package/dist/math-font.d.cts +25 -0
- package/dist/math-font.d.ts +25 -0
- package/dist/math-font.js +102 -0
- package/dist/math-hmtx.cjs +17 -0
- package/dist/math-hmtx.d.cts +8 -0
- package/dist/math-hmtx.d.ts +8 -0
- package/dist/math-hmtx.js +16 -0
- package/dist/math-table.cjs +117 -0
- package/dist/math-table.d.cts +45 -0
- package/dist/math-table.d.ts +45 -0
- package/dist/math-table.js +116 -0
- package/dist/math-types-Ba8qAf1p.d.cts +82 -0
- package/dist/math-types-Ba8qAf1p.d.ts +82 -0
- package/dist/math-types.cjs +0 -0
- package/dist/math-types.d.cts +2 -0
- package/dist/math-types.d.ts +2 -0
- package/dist/math-types.js +0 -0
- package/dist/matrix-B3c2_a2f.d.cts +18 -0
- package/dist/matrix-B3c2_a2f.d.ts +18 -0
- package/dist/matrix.cjs +93 -0
- package/dist/matrix.d.cts +2 -0
- package/dist/matrix.d.ts +2 -0
- package/dist/matrix.js +83 -0
- package/dist/measure.cjs +54 -0
- package/dist/measure.d.cts +20 -0
- package/dist/measure.d.ts +20 -0
- package/dist/measure.js +53 -0
- package/dist/objects.cjs +100 -0
- package/dist/objects.d.cts +58 -0
- package/dist/objects.d.ts +58 -0
- package/dist/objects.js +84 -0
- package/dist/parse.cjs +230 -0
- package/dist/parse.d.cts +13 -0
- package/dist/parse.d.ts +13 -0
- package/dist/parse.js +228 -0
- package/dist/predictors.cjs +64 -0
- package/dist/predictors.d.cts +13 -0
- package/dist/predictors.d.ts +13 -0
- package/dist/predictors.js +62 -0
- package/dist/read.cjs +418 -0
- package/dist/read.d.cts +21 -0
- package/dist/read.d.ts +21 -0
- package/dist/read.js +413 -0
- package/dist/serialize.cjs +69 -0
- package/dist/serialize.d.cts +8 -0
- package/dist/serialize.d.ts +8 -0
- package/dist/serialize.js +66 -0
- package/dist/sfnt.cjs +52 -0
- package/dist/sfnt.d.cts +17 -0
- package/dist/sfnt.d.ts +17 -0
- package/dist/sfnt.js +46 -0
- package/dist/text-layout.cjs +224 -0
- package/dist/text-layout.d.cts +37 -0
- package/dist/text-layout.d.ts +37 -0
- package/dist/text-layout.js +222 -0
- package/dist/util/abort.cjs +7 -0
- package/dist/util/abort.d.cts +4 -0
- package/dist/util/abort.d.ts +4 -0
- package/dist/util/abort.js +6 -0
- package/dist/util/base64.cjs +48 -0
- package/dist/util/base64.d.cts +5 -0
- package/dist/util/base64.d.ts +5 -0
- package/dist/util/base64.js +46 -0
- package/dist/winansi.cjs +5 -0
- package/dist/winansi.d.cts +20 -0
- package/dist/winansi.d.ts +20 -0
- package/dist/winansi.js +2 -0
- package/dist/write.cjs +421 -0
- package/dist/write.d.cts +16 -0
- package/dist/write.d.ts +16 -0
- package/dist/write.js +419 -0
- package/dist/xref.cjs +325 -0
- package/dist/xref.d.cts +21 -0
- package/dist/xref.d.ts +21 -0
- package/dist/xref.js +324 -0
- 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;
|
package/dist/fonts.d.cts
ADDED
|
@@ -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 };
|