reamkit 1.27.0 → 1.28.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 +6 -5
- package/dist/esm/core/converter/ream.d.ts +0 -9
- package/dist/esm/core/converter/ream.js +0 -1
- package/dist/esm/core/document-model/types.d.ts +5 -3
- package/dist/esm/core/font/index.d.ts +1 -0
- package/dist/esm/core/font/ligatures.d.ts +17 -0
- package/dist/esm/core/font/ligatures.js +49 -0
- package/dist/esm/core/font/ttf-parser.d.ts +2 -1
- package/dist/esm/core/font/ttf-parser.js +11 -2
- package/dist/esm/core/fonts/remote-fonts.d.ts +1 -1
- package/dist/esm/core/fonts/remote-fonts.js +47 -2
- package/dist/esm/core/fonts/scripts.js +10 -5
- package/dist/esm/excel/header-footer.js +53 -8
- package/dist/esm/layout/styled-layout.js +53 -3
- package/dist/esm/pdf/cid-font.js +35 -8
- package/dist/esm/pdf-reader/annot-draw.js +114 -1
- package/dist/esm/pdf-reader/annots.d.ts +0 -14
- package/dist/esm/pdf-reader/annots.js +13 -1
- package/dist/esm/pdf-reader/ccitt.d.ts +2 -3
- package/dist/esm/pdf-reader/ccitt.js +32 -4
- package/dist/esm/pdf-reader/cff-outline.d.ts +36 -0
- package/dist/esm/pdf-reader/cff-outline.js +1122 -0
- package/dist/esm/pdf-reader/cmap.js +5 -2
- package/dist/esm/pdf-reader/content.d.ts +76 -0
- package/dist/esm/pdf-reader/content.js +142 -59
- package/dist/esm/pdf-reader/dingbats.d.ts +11 -0
- package/dist/esm/pdf-reader/dingbats.js +1033 -0
- package/dist/esm/pdf-reader/display.js +41 -1
- package/dist/esm/pdf-reader/document.js +26 -9
- package/dist/esm/pdf-reader/embedded-fonts.d.ts +11 -0
- package/dist/esm/pdf-reader/embedded-fonts.js +14 -1
- package/dist/esm/pdf-reader/encodings.d.ts +25 -0
- package/dist/esm/pdf-reader/encodings.js +110 -0
- package/dist/esm/pdf-reader/flow-build.d.ts +9 -3
- package/dist/esm/pdf-reader/flow-build.js +13 -7
- package/dist/esm/pdf-reader/font.js +329 -8
- package/dist/esm/pdf-reader/glyf-outline.d.ts +43 -0
- package/dist/esm/pdf-reader/glyf-outline.js +351 -0
- package/dist/esm/pdf-reader/glyph-names.js +20 -0
- package/dist/esm/pdf-reader/icc.d.ts +10 -0
- package/dist/esm/pdf-reader/icc.js +210 -0
- package/dist/esm/pdf-reader/image-decode.d.ts +4 -3
- package/dist/esm/pdf-reader/image-decode.js +85 -64
- package/dist/esm/pdf-reader/images.d.ts +6 -0
- package/dist/esm/pdf-reader/images.js +50 -7
- package/dist/esm/pdf-reader/jbig2.js +104 -19
- package/dist/esm/pdf-reader/layout.js +1148 -45
- package/dist/esm/pdf-reader/math-rows.d.ts +23 -0
- package/dist/esm/pdf-reader/math-rows.js +198 -0
- package/dist/esm/pdf-reader/predefined-cmap.d.ts +21 -0
- package/dist/esm/pdf-reader/predefined-cmap.js +102 -0
- package/dist/esm/pdf-reader/reader.d.ts +6 -9
- package/dist/esm/pdf-reader/reader.js +34 -21
- package/dist/esm/pdf-reader/shading.d.ts +81 -2
- package/dist/esm/pdf-reader/shading.js +191 -25
- package/dist/esm/pdf-reader/stream-filters.d.ts +6 -0
- package/dist/esm/pdf-reader/stream-filters.js +67 -0
- package/dist/esm/pdf-reader/text-rules.js +83 -10
- package/dist/esm/pdf-reader/text.js +82 -3
- package/dist/esm/pdf-reader/type1-outline.d.ts +21 -0
- package/dist/esm/pdf-reader/type1-outline.js +576 -0
- package/dist/esm/pdf-reader/vector.js +43 -4
- package/dist/esm/word/document-parser.js +4 -1
- package/dist/esm/word/docx-writer.js +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,1122 @@
|
|
|
1
|
+
//#region src/pdf-reader/cff-outline.ts
|
|
2
|
+
/**
|
|
3
|
+
* Prepare an embedded CFF program for outline reading.
|
|
4
|
+
*
|
|
5
|
+
* @param program The raw `/FontFile3` bytes (bare CFF, or the `CFF ` table of
|
|
6
|
+
* an OpenType wrapper — the caller unwraps that).
|
|
7
|
+
* @returns A reader keyed by GLYPH INDEX, or `undefined` where the program
|
|
8
|
+
* cannot be read.
|
|
9
|
+
*/
|
|
10
|
+
function cffOutlineSource(program) {
|
|
11
|
+
let font;
|
|
12
|
+
try {
|
|
13
|
+
const parsed = parseCff(program);
|
|
14
|
+
if (!parsed) return void 0;
|
|
15
|
+
font = parsed;
|
|
16
|
+
} catch {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
const cache = /* @__PURE__ */ new Map();
|
|
20
|
+
return {
|
|
21
|
+
count: font.charStrings.length,
|
|
22
|
+
path: (gid) => {
|
|
23
|
+
const had = cache.get(gid);
|
|
24
|
+
if (had !== void 0 || cache.has(gid)) return had;
|
|
25
|
+
let out;
|
|
26
|
+
try {
|
|
27
|
+
out = runGlyph(font, gid);
|
|
28
|
+
} catch {
|
|
29
|
+
out = void 0;
|
|
30
|
+
}
|
|
31
|
+
cache.set(gid, out);
|
|
32
|
+
return out;
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* TN 5176 §13 — the NAME a CFF gives each glyph, inverted.
|
|
38
|
+
*
|
|
39
|
+
* A simple font selects its glyphs by name, not by index: `/Differences` says
|
|
40
|
+
* code 2 is `g18`, and only the program's charset says which glyph `g18` is.
|
|
41
|
+
* TAMReview.pdf sets most of its body in a Cambria subset named that way.
|
|
42
|
+
*
|
|
43
|
+
* @param program The raw CFF bytes.
|
|
44
|
+
* @returns Glyph name → glyph index, or `undefined` for a CID-keyed program
|
|
45
|
+
* (which names nothing) or one that cannot be read.
|
|
46
|
+
*/
|
|
47
|
+
function cffNameToGid(program) {
|
|
48
|
+
try {
|
|
49
|
+
return parseCff(program)?.nameToGid;
|
|
50
|
+
} catch {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* TN 5176 §10 — the CID a CID-keyed CFF gives each glyph, inverted.
|
|
56
|
+
*
|
|
57
|
+
* A `CIDFontType0C` program is charset-ordered by CID, not by glyph index, so a
|
|
58
|
+
* composite font's code (its CID) is not the index into `CharStrings`. Where the
|
|
59
|
+
* program is not CID-keyed the two are the same and this gives nothing.
|
|
60
|
+
*
|
|
61
|
+
* @param program The raw CFF bytes.
|
|
62
|
+
* @returns CID → glyph index, or `undefined` for a program that is not
|
|
63
|
+
* CID-keyed or cannot be read.
|
|
64
|
+
*/
|
|
65
|
+
function cffCidToGid(program) {
|
|
66
|
+
try {
|
|
67
|
+
return parseCff(program)?.cidToGid;
|
|
68
|
+
} catch {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/** The `CFF ` table of an OpenType wrapper, where the program is one. */
|
|
73
|
+
function openTypeCff(program) {
|
|
74
|
+
if (program.length < 12) return void 0;
|
|
75
|
+
const view = new DataView(program.buffer, program.byteOffset, program.byteLength);
|
|
76
|
+
if (view.getUint32(0) !== 1330926671) return void 0;
|
|
77
|
+
const count = view.getUint16(4);
|
|
78
|
+
for (let i = 0; i < count; i++) {
|
|
79
|
+
const at = 12 + i * 16;
|
|
80
|
+
if (at + 16 > program.length) break;
|
|
81
|
+
if (String.fromCharCode(program[at], program[at + 1], program[at + 2], program[at + 3]) !== "CFF ") continue;
|
|
82
|
+
const offset = view.getUint32(at + 8);
|
|
83
|
+
const length = view.getUint32(at + 12);
|
|
84
|
+
if (offset + length > program.length) return void 0;
|
|
85
|
+
return program.subarray(offset, offset + length);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
function parseCff(program) {
|
|
89
|
+
if (program.length < 4) return void 0;
|
|
90
|
+
const names = readIndex(program, program[2] ?? 4);
|
|
91
|
+
if (!names) return void 0;
|
|
92
|
+
const tops = readIndex(program, names.end);
|
|
93
|
+
if (!tops || tops.items.length === 0) return void 0;
|
|
94
|
+
const strings = readIndex(program, tops.end);
|
|
95
|
+
if (!strings) return void 0;
|
|
96
|
+
const gsubrs = readIndex(program, strings.end);
|
|
97
|
+
if (!gsubrs) return void 0;
|
|
98
|
+
const top = parseDict(tops.items[0]);
|
|
99
|
+
const csOffset = top.get(17)?.[0];
|
|
100
|
+
if (csOffset === void 0) return void 0;
|
|
101
|
+
const charStrings = readIndex(program, csOffset);
|
|
102
|
+
if (!charStrings) return void 0;
|
|
103
|
+
const matrix = top.get(1207);
|
|
104
|
+
const scale = matrix && matrix.length >= 4 ? matrix[0] ?? .001 : .001;
|
|
105
|
+
const privateSubrs = (dict) => {
|
|
106
|
+
const priv = dict.get(18);
|
|
107
|
+
if (!priv || priv.length < 2) return [];
|
|
108
|
+
const size = priv[0];
|
|
109
|
+
const offset = priv[1];
|
|
110
|
+
if (offset < 0 || offset + size > program.length) return [];
|
|
111
|
+
const subrsAt = parseDict(program.subarray(offset, offset + size)).get(19)?.[0];
|
|
112
|
+
if (subrsAt === void 0) return [];
|
|
113
|
+
return readIndex(program, offset + subrsAt)?.items ?? [];
|
|
114
|
+
};
|
|
115
|
+
const isCid = top.has(1230);
|
|
116
|
+
let localSubrs;
|
|
117
|
+
if (isCid) {
|
|
118
|
+
const fdArrayAt = top.get(1236)?.[0];
|
|
119
|
+
const fdSelectAt = top.get(1237)?.[0];
|
|
120
|
+
const subrsPerFd = (fdArrayAt !== void 0 ? readIndex(program, fdArrayAt)?.items ?? [] : []).map((fd) => privateSubrs(parseDict(fd)));
|
|
121
|
+
const select = fdSelectAt !== void 0 ? readFdSelect(program, fdSelectAt, charStrings.items.length) : void 0;
|
|
122
|
+
localSubrs = (gid) => subrsPerFd[select ? select[gid] ?? 0 : 0] ?? [];
|
|
123
|
+
} else {
|
|
124
|
+
const only = privateSubrs(top);
|
|
125
|
+
localSubrs = () => only;
|
|
126
|
+
}
|
|
127
|
+
const charsetAt = top.get(15)?.[0];
|
|
128
|
+
const sids = charsetAt !== void 0 && charsetAt > 2 ? readCharset(program, charsetAt, charStrings.items.length) : void 0;
|
|
129
|
+
const cidToGid = isCid ? sids : void 0;
|
|
130
|
+
const nameToGid = isCid ? void 0 : namesOf(sids, strings.items, charStrings.items.length);
|
|
131
|
+
return {
|
|
132
|
+
charStrings: charStrings.items,
|
|
133
|
+
globalSubrs: gsubrs.items,
|
|
134
|
+
localSubrs,
|
|
135
|
+
scale,
|
|
136
|
+
...cidToGid ? { cidToGid } : {},
|
|
137
|
+
...nameToGid ? { nameToGid } : {}
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* TN 5176 §13 — glyph name → glyph index, from the charset's SIDs.
|
|
142
|
+
*
|
|
143
|
+
* An SID below 391 is one of the standard strings; above it indexes the
|
|
144
|
+
* program's own String INDEX. A font with no charset uses ISOAdobe, which is
|
|
145
|
+
* the standard strings in order — so the SID is the glyph index itself.
|
|
146
|
+
*/
|
|
147
|
+
function namesOf(sids, strings, glyphs) {
|
|
148
|
+
const nameOf = (sid) => {
|
|
149
|
+
if (sid < STANDARD_STRINGS.length) return STANDARD_STRINGS[sid];
|
|
150
|
+
const own = strings[sid - STANDARD_STRINGS.length];
|
|
151
|
+
return own ? new TextDecoder("latin1").decode(own) : void 0;
|
|
152
|
+
};
|
|
153
|
+
const out = /* @__PURE__ */ new Map();
|
|
154
|
+
if (sids) for (const [sid, gid] of sids) {
|
|
155
|
+
const name = nameOf(sid);
|
|
156
|
+
if (name !== void 0 && !out.has(name)) out.set(name, gid);
|
|
157
|
+
}
|
|
158
|
+
else for (let gid = 0; gid < glyphs && gid < STANDARD_STRINGS.length; gid++) {
|
|
159
|
+
const name = STANDARD_STRINGS[gid];
|
|
160
|
+
if (name !== void 0 && !out.has(name)) out.set(name, gid);
|
|
161
|
+
}
|
|
162
|
+
return out.size > 0 ? out : void 0;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* TN 5176 Appendix A — the 391 strings every CFF program shares. An SID below
|
|
166
|
+
* this many is one of these; above it indexes the program's own String INDEX.
|
|
167
|
+
*/
|
|
168
|
+
var STANDARD_STRINGS = [
|
|
169
|
+
".notdef",
|
|
170
|
+
"space",
|
|
171
|
+
"exclam",
|
|
172
|
+
"quotedbl",
|
|
173
|
+
"numbersign",
|
|
174
|
+
"dollar",
|
|
175
|
+
"percent",
|
|
176
|
+
"ampersand",
|
|
177
|
+
"quoteright",
|
|
178
|
+
"parenleft",
|
|
179
|
+
"parenright",
|
|
180
|
+
"asterisk",
|
|
181
|
+
"plus",
|
|
182
|
+
"comma",
|
|
183
|
+
"hyphen",
|
|
184
|
+
"period",
|
|
185
|
+
"slash",
|
|
186
|
+
"zero",
|
|
187
|
+
"one",
|
|
188
|
+
"two",
|
|
189
|
+
"three",
|
|
190
|
+
"four",
|
|
191
|
+
"five",
|
|
192
|
+
"six",
|
|
193
|
+
"seven",
|
|
194
|
+
"eight",
|
|
195
|
+
"nine",
|
|
196
|
+
"colon",
|
|
197
|
+
"semicolon",
|
|
198
|
+
"less",
|
|
199
|
+
"equal",
|
|
200
|
+
"greater",
|
|
201
|
+
"question",
|
|
202
|
+
"at",
|
|
203
|
+
"A",
|
|
204
|
+
"B",
|
|
205
|
+
"C",
|
|
206
|
+
"D",
|
|
207
|
+
"E",
|
|
208
|
+
"F",
|
|
209
|
+
"G",
|
|
210
|
+
"H",
|
|
211
|
+
"I",
|
|
212
|
+
"J",
|
|
213
|
+
"K",
|
|
214
|
+
"L",
|
|
215
|
+
"M",
|
|
216
|
+
"N",
|
|
217
|
+
"O",
|
|
218
|
+
"P",
|
|
219
|
+
"Q",
|
|
220
|
+
"R",
|
|
221
|
+
"S",
|
|
222
|
+
"T",
|
|
223
|
+
"U",
|
|
224
|
+
"V",
|
|
225
|
+
"W",
|
|
226
|
+
"X",
|
|
227
|
+
"Y",
|
|
228
|
+
"Z",
|
|
229
|
+
"bracketleft",
|
|
230
|
+
"backslash",
|
|
231
|
+
"bracketright",
|
|
232
|
+
"asciicircum",
|
|
233
|
+
"underscore",
|
|
234
|
+
"quoteleft",
|
|
235
|
+
"a",
|
|
236
|
+
"b",
|
|
237
|
+
"c",
|
|
238
|
+
"d",
|
|
239
|
+
"e",
|
|
240
|
+
"f",
|
|
241
|
+
"g",
|
|
242
|
+
"h",
|
|
243
|
+
"i",
|
|
244
|
+
"j",
|
|
245
|
+
"k",
|
|
246
|
+
"l",
|
|
247
|
+
"m",
|
|
248
|
+
"n",
|
|
249
|
+
"o",
|
|
250
|
+
"p",
|
|
251
|
+
"q",
|
|
252
|
+
"r",
|
|
253
|
+
"s",
|
|
254
|
+
"t",
|
|
255
|
+
"u",
|
|
256
|
+
"v",
|
|
257
|
+
"w",
|
|
258
|
+
"x",
|
|
259
|
+
"y",
|
|
260
|
+
"z",
|
|
261
|
+
"braceleft",
|
|
262
|
+
"bar",
|
|
263
|
+
"braceright",
|
|
264
|
+
"asciitilde",
|
|
265
|
+
"exclamdown",
|
|
266
|
+
"cent",
|
|
267
|
+
"sterling",
|
|
268
|
+
"fraction",
|
|
269
|
+
"yen",
|
|
270
|
+
"florin",
|
|
271
|
+
"section",
|
|
272
|
+
"currency",
|
|
273
|
+
"quotesingle",
|
|
274
|
+
"quotedblleft",
|
|
275
|
+
"guillemotleft",
|
|
276
|
+
"guilsinglleft",
|
|
277
|
+
"guilsinglright",
|
|
278
|
+
"fi",
|
|
279
|
+
"fl",
|
|
280
|
+
"endash",
|
|
281
|
+
"dagger",
|
|
282
|
+
"daggerdbl",
|
|
283
|
+
"periodcentered",
|
|
284
|
+
"paragraph",
|
|
285
|
+
"bullet",
|
|
286
|
+
"quotesinglbase",
|
|
287
|
+
"quotedblbase",
|
|
288
|
+
"quotedblright",
|
|
289
|
+
"guillemotright",
|
|
290
|
+
"ellipsis",
|
|
291
|
+
"perthousand",
|
|
292
|
+
"questiondown",
|
|
293
|
+
"grave",
|
|
294
|
+
"acute",
|
|
295
|
+
"circumflex",
|
|
296
|
+
"tilde",
|
|
297
|
+
"macron",
|
|
298
|
+
"breve",
|
|
299
|
+
"dotaccent",
|
|
300
|
+
"dieresis",
|
|
301
|
+
"ring",
|
|
302
|
+
"cedilla",
|
|
303
|
+
"hungarumlaut",
|
|
304
|
+
"ogonek",
|
|
305
|
+
"caron",
|
|
306
|
+
"emdash",
|
|
307
|
+
"AE",
|
|
308
|
+
"ordfeminine",
|
|
309
|
+
"Lslash",
|
|
310
|
+
"Oslash",
|
|
311
|
+
"OE",
|
|
312
|
+
"ordmasculine",
|
|
313
|
+
"ae",
|
|
314
|
+
"dotlessi",
|
|
315
|
+
"lslash",
|
|
316
|
+
"oslash",
|
|
317
|
+
"oe",
|
|
318
|
+
"germandbls",
|
|
319
|
+
"onesuperior",
|
|
320
|
+
"logicalnot",
|
|
321
|
+
"mu",
|
|
322
|
+
"trademark",
|
|
323
|
+
"Eth",
|
|
324
|
+
"onehalf",
|
|
325
|
+
"plusminus",
|
|
326
|
+
"Thorn",
|
|
327
|
+
"onequarter",
|
|
328
|
+
"divide",
|
|
329
|
+
"brokenbar",
|
|
330
|
+
"degree",
|
|
331
|
+
"thorn",
|
|
332
|
+
"threequarters",
|
|
333
|
+
"twosuperior",
|
|
334
|
+
"registered",
|
|
335
|
+
"minus",
|
|
336
|
+
"eth",
|
|
337
|
+
"multiply",
|
|
338
|
+
"threesuperior",
|
|
339
|
+
"copyright",
|
|
340
|
+
"Aacute",
|
|
341
|
+
"Acircumflex",
|
|
342
|
+
"Adieresis",
|
|
343
|
+
"Agrave",
|
|
344
|
+
"Aring",
|
|
345
|
+
"Atilde",
|
|
346
|
+
"Ccedilla",
|
|
347
|
+
"Eacute",
|
|
348
|
+
"Ecircumflex",
|
|
349
|
+
"Edieresis",
|
|
350
|
+
"Egrave",
|
|
351
|
+
"Iacute",
|
|
352
|
+
"Icircumflex",
|
|
353
|
+
"Idieresis",
|
|
354
|
+
"Igrave",
|
|
355
|
+
"Ntilde",
|
|
356
|
+
"Oacute",
|
|
357
|
+
"Ocircumflex",
|
|
358
|
+
"Odieresis",
|
|
359
|
+
"Ograve",
|
|
360
|
+
"Otilde",
|
|
361
|
+
"Scaron",
|
|
362
|
+
"Uacute",
|
|
363
|
+
"Ucircumflex",
|
|
364
|
+
"Udieresis",
|
|
365
|
+
"Ugrave",
|
|
366
|
+
"Yacute",
|
|
367
|
+
"Ydieresis",
|
|
368
|
+
"Zcaron",
|
|
369
|
+
"aacute",
|
|
370
|
+
"acircumflex",
|
|
371
|
+
"adieresis",
|
|
372
|
+
"agrave",
|
|
373
|
+
"aring",
|
|
374
|
+
"atilde",
|
|
375
|
+
"ccedilla",
|
|
376
|
+
"eacute",
|
|
377
|
+
"ecircumflex",
|
|
378
|
+
"edieresis",
|
|
379
|
+
"egrave",
|
|
380
|
+
"iacute",
|
|
381
|
+
"icircumflex",
|
|
382
|
+
"idieresis",
|
|
383
|
+
"igrave",
|
|
384
|
+
"ntilde",
|
|
385
|
+
"oacute",
|
|
386
|
+
"ocircumflex",
|
|
387
|
+
"odieresis",
|
|
388
|
+
"ograve",
|
|
389
|
+
"otilde",
|
|
390
|
+
"scaron",
|
|
391
|
+
"uacute",
|
|
392
|
+
"ucircumflex",
|
|
393
|
+
"udieresis",
|
|
394
|
+
"ugrave",
|
|
395
|
+
"yacute",
|
|
396
|
+
"ydieresis",
|
|
397
|
+
"zcaron",
|
|
398
|
+
"exclamsmall",
|
|
399
|
+
"Hungarumlautsmall",
|
|
400
|
+
"dollaroldstyle",
|
|
401
|
+
"dollarsuperior",
|
|
402
|
+
"ampersandsmall",
|
|
403
|
+
"Acutesmall",
|
|
404
|
+
"parenleftsuperior",
|
|
405
|
+
"parenrightsuperior",
|
|
406
|
+
"twodotenleader",
|
|
407
|
+
"onedotenleader",
|
|
408
|
+
"zerooldstyle",
|
|
409
|
+
"oneoldstyle",
|
|
410
|
+
"twooldstyle",
|
|
411
|
+
"threeoldstyle",
|
|
412
|
+
"fouroldstyle",
|
|
413
|
+
"fiveoldstyle",
|
|
414
|
+
"sixoldstyle",
|
|
415
|
+
"sevenoldstyle",
|
|
416
|
+
"eightoldstyle",
|
|
417
|
+
"nineoldstyle",
|
|
418
|
+
"commasuperior",
|
|
419
|
+
"threequartersemdash",
|
|
420
|
+
"periodsuperior",
|
|
421
|
+
"questionsmall",
|
|
422
|
+
"asuperior",
|
|
423
|
+
"bsuperior",
|
|
424
|
+
"centsuperior",
|
|
425
|
+
"dsuperior",
|
|
426
|
+
"esuperior",
|
|
427
|
+
"isuperior",
|
|
428
|
+
"lsuperior",
|
|
429
|
+
"msuperior",
|
|
430
|
+
"nsuperior",
|
|
431
|
+
"osuperior",
|
|
432
|
+
"rsuperior",
|
|
433
|
+
"ssuperior",
|
|
434
|
+
"tsuperior",
|
|
435
|
+
"ff",
|
|
436
|
+
"ffi",
|
|
437
|
+
"ffl",
|
|
438
|
+
"parenleftinferior",
|
|
439
|
+
"parenrightinferior",
|
|
440
|
+
"Circumflexsmall",
|
|
441
|
+
"hyphensuperior",
|
|
442
|
+
"Gravesmall",
|
|
443
|
+
"Asmall",
|
|
444
|
+
"Bsmall",
|
|
445
|
+
"Csmall",
|
|
446
|
+
"Dsmall",
|
|
447
|
+
"Esmall",
|
|
448
|
+
"Fsmall",
|
|
449
|
+
"Gsmall",
|
|
450
|
+
"Hsmall",
|
|
451
|
+
"Ismall",
|
|
452
|
+
"Jsmall",
|
|
453
|
+
"Ksmall",
|
|
454
|
+
"Lsmall",
|
|
455
|
+
"Msmall",
|
|
456
|
+
"Nsmall",
|
|
457
|
+
"Osmall",
|
|
458
|
+
"Psmall",
|
|
459
|
+
"Qsmall",
|
|
460
|
+
"Rsmall",
|
|
461
|
+
"Ssmall",
|
|
462
|
+
"Tsmall",
|
|
463
|
+
"Usmall",
|
|
464
|
+
"Vsmall",
|
|
465
|
+
"Wsmall",
|
|
466
|
+
"Xsmall",
|
|
467
|
+
"Ysmall",
|
|
468
|
+
"Zsmall",
|
|
469
|
+
"colonmonetary",
|
|
470
|
+
"onefitted",
|
|
471
|
+
"rupiah",
|
|
472
|
+
"Tildesmall",
|
|
473
|
+
"exclamdownsmall",
|
|
474
|
+
"centoldstyle",
|
|
475
|
+
"Lslashsmall",
|
|
476
|
+
"Scaronsmall",
|
|
477
|
+
"Zcaronsmall",
|
|
478
|
+
"Dieresissmall",
|
|
479
|
+
"Brevesmall",
|
|
480
|
+
"Caronsmall",
|
|
481
|
+
"Dotaccentsmall",
|
|
482
|
+
"Macronsmall",
|
|
483
|
+
"figuredash",
|
|
484
|
+
"hypheninferior",
|
|
485
|
+
"Ogoneksmall",
|
|
486
|
+
"Ringsmall",
|
|
487
|
+
"Cedillasmall",
|
|
488
|
+
"questiondownsmall",
|
|
489
|
+
"oneeighth",
|
|
490
|
+
"threeeighths",
|
|
491
|
+
"fiveeighths",
|
|
492
|
+
"seveneighths",
|
|
493
|
+
"onethird",
|
|
494
|
+
"twothirds",
|
|
495
|
+
"zerosuperior",
|
|
496
|
+
"foursuperior",
|
|
497
|
+
"fivesuperior",
|
|
498
|
+
"sixsuperior",
|
|
499
|
+
"sevensuperior",
|
|
500
|
+
"eightsuperior",
|
|
501
|
+
"ninesuperior",
|
|
502
|
+
"zeroinferior",
|
|
503
|
+
"oneinferior",
|
|
504
|
+
"twoinferior",
|
|
505
|
+
"threeinferior",
|
|
506
|
+
"fourinferior",
|
|
507
|
+
"fiveinferior",
|
|
508
|
+
"sixinferior",
|
|
509
|
+
"seveninferior",
|
|
510
|
+
"eightinferior",
|
|
511
|
+
"nineinferior",
|
|
512
|
+
"centinferior",
|
|
513
|
+
"dollarinferior",
|
|
514
|
+
"periodinferior",
|
|
515
|
+
"commainferior",
|
|
516
|
+
"Agravesmall",
|
|
517
|
+
"Aacutesmall",
|
|
518
|
+
"Acircumflexsmall",
|
|
519
|
+
"Atildesmall",
|
|
520
|
+
"Adieresissmall",
|
|
521
|
+
"Aringsmall",
|
|
522
|
+
"AEsmall",
|
|
523
|
+
"Ccedillasmall",
|
|
524
|
+
"Egravesmall",
|
|
525
|
+
"Eacutesmall",
|
|
526
|
+
"Ecircumflexsmall",
|
|
527
|
+
"Edieresissmall",
|
|
528
|
+
"Igravesmall",
|
|
529
|
+
"Iacutesmall",
|
|
530
|
+
"Icircumflexsmall",
|
|
531
|
+
"Idieresissmall",
|
|
532
|
+
"Ethsmall",
|
|
533
|
+
"Ntildesmall",
|
|
534
|
+
"Ogravesmall",
|
|
535
|
+
"Oacutesmall",
|
|
536
|
+
"Ocircumflexsmall",
|
|
537
|
+
"Otildesmall",
|
|
538
|
+
"Odieresissmall",
|
|
539
|
+
"OEsmall",
|
|
540
|
+
"Oslashsmall",
|
|
541
|
+
"Ugravesmall",
|
|
542
|
+
"Uacutesmall",
|
|
543
|
+
"Ucircumflexsmall",
|
|
544
|
+
"Udieresissmall",
|
|
545
|
+
"Yacutesmall",
|
|
546
|
+
"Thornsmall",
|
|
547
|
+
"Ydieresissmall",
|
|
548
|
+
"001.000",
|
|
549
|
+
"001.001",
|
|
550
|
+
"001.002",
|
|
551
|
+
"001.003",
|
|
552
|
+
"Black",
|
|
553
|
+
"Bold",
|
|
554
|
+
"Book",
|
|
555
|
+
"Light",
|
|
556
|
+
"Medium",
|
|
557
|
+
"Regular",
|
|
558
|
+
"Roman",
|
|
559
|
+
"Semibold"
|
|
560
|
+
];
|
|
561
|
+
/** TN 5176 §5 — an INDEX: a count, an offset size, the offsets, then the data. */
|
|
562
|
+
function readIndex(data, at) {
|
|
563
|
+
if (at < 0 || at + 2 > data.length) return void 0;
|
|
564
|
+
const count = data[at] << 8 | data[at + 1];
|
|
565
|
+
if (count === 0) return {
|
|
566
|
+
items: [],
|
|
567
|
+
end: at + 2
|
|
568
|
+
};
|
|
569
|
+
const offSize = data[at + 2] ?? 1;
|
|
570
|
+
if (offSize < 1 || offSize > 4) return void 0;
|
|
571
|
+
const offsets = [];
|
|
572
|
+
let p = at + 3;
|
|
573
|
+
for (let i = 0; i <= count; i++) {
|
|
574
|
+
let v = 0;
|
|
575
|
+
for (let k = 0; k < offSize; k++) v = v << 8 | (data[p++] ?? 0);
|
|
576
|
+
offsets.push(v);
|
|
577
|
+
}
|
|
578
|
+
const base = p - 1;
|
|
579
|
+
const items = [];
|
|
580
|
+
for (let i = 0; i < count; i++) {
|
|
581
|
+
const from = base + (offsets[i] ?? 1);
|
|
582
|
+
const to = base + (offsets[i + 1] ?? 1);
|
|
583
|
+
if (from < 0 || to > data.length || to < from) return void 0;
|
|
584
|
+
items.push(data.subarray(from, to));
|
|
585
|
+
}
|
|
586
|
+
return {
|
|
587
|
+
items,
|
|
588
|
+
end: base + (offsets[count] ?? 1)
|
|
589
|
+
};
|
|
590
|
+
}
|
|
591
|
+
/**
|
|
592
|
+
* TN 5176 §4 — a DICT: operands then an operator. Two-byte operators (`12 x`)
|
|
593
|
+
* are keyed as `1200 + x` so one map holds both.
|
|
594
|
+
*/
|
|
595
|
+
function parseDict(data) {
|
|
596
|
+
const out = /* @__PURE__ */ new Map();
|
|
597
|
+
let operands = [];
|
|
598
|
+
for (let i = 0; i < data.length;) {
|
|
599
|
+
const b = data[i];
|
|
600
|
+
if (b <= 21) {
|
|
601
|
+
const key = b === 12 ? 1200 + (data[i + 1] ?? 0) : b;
|
|
602
|
+
i += b === 12 ? 2 : 1;
|
|
603
|
+
out.set(key, operands);
|
|
604
|
+
operands = [];
|
|
605
|
+
} else if (b === 28) {
|
|
606
|
+
operands.push((data[i + 1] << 8 | data[i + 2]) << 16 >> 16);
|
|
607
|
+
i += 3;
|
|
608
|
+
} else if (b === 29) {
|
|
609
|
+
operands.push(data[i + 1] << 24 | data[i + 2] << 16 | data[i + 3] << 8 | data[i + 4] | 0);
|
|
610
|
+
i += 5;
|
|
611
|
+
} else if (b === 30) {
|
|
612
|
+
let text = "";
|
|
613
|
+
i++;
|
|
614
|
+
let done = false;
|
|
615
|
+
while (i < data.length && !done) {
|
|
616
|
+
const byte = data[i++];
|
|
617
|
+
for (const nibble of [byte >> 4, byte & 15]) if (nibble <= 9) text += String(nibble);
|
|
618
|
+
else if (nibble === 10) text += ".";
|
|
619
|
+
else if (nibble === 11) text += "E";
|
|
620
|
+
else if (nibble === 12) text += "E-";
|
|
621
|
+
else if (nibble === 14) text += "-";
|
|
622
|
+
else if (nibble === 15) {
|
|
623
|
+
done = true;
|
|
624
|
+
break;
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
operands.push(Number.parseFloat(text) || 0);
|
|
628
|
+
} else if (b >= 32 && b <= 246) {
|
|
629
|
+
operands.push(b - 139);
|
|
630
|
+
i++;
|
|
631
|
+
} else if (b >= 247 && b <= 250) {
|
|
632
|
+
operands.push((b - 247) * 256 + (data[i + 1] ?? 0) + 108);
|
|
633
|
+
i += 2;
|
|
634
|
+
} else if (b >= 251 && b <= 254) {
|
|
635
|
+
operands.push(-(b - 251) * 256 - (data[i + 1] ?? 0) - 108);
|
|
636
|
+
i += 2;
|
|
637
|
+
} else i++;
|
|
638
|
+
}
|
|
639
|
+
return out;
|
|
640
|
+
}
|
|
641
|
+
/** TN 5176 §19 — FDSelect: which Private DICT each glyph belongs to. */
|
|
642
|
+
function readFdSelect(data, at, glyphs) {
|
|
643
|
+
if (at < 0 || at >= data.length) return void 0;
|
|
644
|
+
const out = new Array(glyphs).fill(0);
|
|
645
|
+
const format = data[at];
|
|
646
|
+
if (format === 0) {
|
|
647
|
+
for (let i = 0; i < glyphs; i++) out[i] = data[at + 1 + i] ?? 0;
|
|
648
|
+
return out;
|
|
649
|
+
}
|
|
650
|
+
if (format !== 3) return void 0;
|
|
651
|
+
const ranges = data[at + 1] << 8 | data[at + 2];
|
|
652
|
+
let p = at + 3;
|
|
653
|
+
let first = data[p] << 8 | data[p + 1];
|
|
654
|
+
p += 2;
|
|
655
|
+
for (let r = 0; r < ranges; r++) {
|
|
656
|
+
const fd = data[p];
|
|
657
|
+
const next = data[p + 1] << 8 | data[p + 2];
|
|
658
|
+
p += 3;
|
|
659
|
+
for (let g = first; g < next && g < glyphs; g++) out[g] = fd;
|
|
660
|
+
first = next;
|
|
661
|
+
}
|
|
662
|
+
return out;
|
|
663
|
+
}
|
|
664
|
+
/** TN 5176 §13 — the charset, which for a CID-keyed font lists CIDs by glyph. */
|
|
665
|
+
function readCharset(data, at, glyphs) {
|
|
666
|
+
if (at < 0 || at >= data.length) return void 0;
|
|
667
|
+
const out = /* @__PURE__ */ new Map();
|
|
668
|
+
out.set(0, 0);
|
|
669
|
+
const format = data[at];
|
|
670
|
+
let p = at + 1;
|
|
671
|
+
if (format === 0) {
|
|
672
|
+
for (let gid = 1; gid < glyphs && p + 1 < data.length; gid++, p += 2) out.set(data[p] << 8 | data[p + 1], gid);
|
|
673
|
+
return out;
|
|
674
|
+
}
|
|
675
|
+
if (format !== 1 && format !== 2) return void 0;
|
|
676
|
+
const wide = format === 2;
|
|
677
|
+
for (let gid = 1; gid < glyphs && p < data.length;) {
|
|
678
|
+
const first = data[p] << 8 | data[p + 1];
|
|
679
|
+
const left = wide ? data[p + 2] << 8 | data[p + 3] : data[p + 2];
|
|
680
|
+
p += wide ? 4 : 3;
|
|
681
|
+
for (let k = 0; k <= left && gid < glyphs; k++) out.set(first + k, gid++);
|
|
682
|
+
}
|
|
683
|
+
return out;
|
|
684
|
+
}
|
|
685
|
+
/** TN 5177 §4.7 — the index a subroutine call is biased by. */
|
|
686
|
+
function bias(subrs) {
|
|
687
|
+
return subrs.length < 1240 ? 107 : subrs.length < 33900 ? 1131 : 32768;
|
|
688
|
+
}
|
|
689
|
+
/** How deep a charstring may call, and how many operators it may run. */
|
|
690
|
+
var MAX_CALL_DEPTH = 10;
|
|
691
|
+
var MAX_STEPS = 65536;
|
|
692
|
+
function runGlyph(font, gid) {
|
|
693
|
+
const program = font.charStrings[gid];
|
|
694
|
+
if (!program) return void 0;
|
|
695
|
+
const local = font.localSubrs(gid);
|
|
696
|
+
const localBias = bias(local);
|
|
697
|
+
const globalBias = bias(font.globalSubrs);
|
|
698
|
+
const out = [];
|
|
699
|
+
const stack = [];
|
|
700
|
+
const trans = [];
|
|
701
|
+
let x = 0;
|
|
702
|
+
let y = 0;
|
|
703
|
+
let stems = 0;
|
|
704
|
+
let open = false;
|
|
705
|
+
let widthParsed = false;
|
|
706
|
+
let steps = 0;
|
|
707
|
+
const moveTo = (nx, ny) => {
|
|
708
|
+
if (open) out.push({ op: "close" });
|
|
709
|
+
out.push({
|
|
710
|
+
op: "move",
|
|
711
|
+
x: nx,
|
|
712
|
+
y: ny
|
|
713
|
+
});
|
|
714
|
+
open = true;
|
|
715
|
+
};
|
|
716
|
+
const lineTo = (nx, ny) => {
|
|
717
|
+
out.push({
|
|
718
|
+
op: "line",
|
|
719
|
+
x: nx,
|
|
720
|
+
y: ny
|
|
721
|
+
});
|
|
722
|
+
};
|
|
723
|
+
const curveTo = (x1, y1, x2, y2, nx, ny) => {
|
|
724
|
+
out.push({
|
|
725
|
+
op: "cubic",
|
|
726
|
+
x1,
|
|
727
|
+
y1,
|
|
728
|
+
x2,
|
|
729
|
+
y2,
|
|
730
|
+
x: nx,
|
|
731
|
+
y: ny
|
|
732
|
+
});
|
|
733
|
+
};
|
|
734
|
+
const takeWidth = (arity) => {
|
|
735
|
+
if (widthParsed) return;
|
|
736
|
+
widthParsed = true;
|
|
737
|
+
if (arity === "even" ? stack.length % 2 === 1 : stack.length > arity) stack.shift();
|
|
738
|
+
};
|
|
739
|
+
const run = (code, depth) => {
|
|
740
|
+
for (let i = 0; i < code.length;) {
|
|
741
|
+
if (++steps > MAX_STEPS) return false;
|
|
742
|
+
const b = code[i++];
|
|
743
|
+
if (b >= 32 || b === 28) {
|
|
744
|
+
if (b === 28) {
|
|
745
|
+
stack.push((code[i] << 8 | code[i + 1]) << 16 >> 16);
|
|
746
|
+
i += 2;
|
|
747
|
+
} else if (b <= 246) stack.push(b - 139);
|
|
748
|
+
else if (b <= 250) stack.push((b - 247) * 256 + (code[i++] ?? 0) + 108);
|
|
749
|
+
else if (b <= 254) stack.push(-(b - 251) * 256 - (code[i++] ?? 0) - 108);
|
|
750
|
+
else {
|
|
751
|
+
stack.push((code[i] << 24 | code[i + 1] << 16 | code[i + 2] << 8 | code[i + 3] | 0) / 65536);
|
|
752
|
+
i += 4;
|
|
753
|
+
}
|
|
754
|
+
continue;
|
|
755
|
+
}
|
|
756
|
+
switch (b) {
|
|
757
|
+
case 1:
|
|
758
|
+
case 3:
|
|
759
|
+
case 18:
|
|
760
|
+
case 23:
|
|
761
|
+
takeWidth("even");
|
|
762
|
+
stems += stack.length >> 1;
|
|
763
|
+
stack.length = 0;
|
|
764
|
+
break;
|
|
765
|
+
case 19:
|
|
766
|
+
case 20:
|
|
767
|
+
takeWidth("even");
|
|
768
|
+
stems += stack.length >> 1;
|
|
769
|
+
stack.length = 0;
|
|
770
|
+
i += stems + 7 >> 3;
|
|
771
|
+
break;
|
|
772
|
+
case 21:
|
|
773
|
+
takeWidth(2);
|
|
774
|
+
x += stack[stack.length - 2] ?? 0;
|
|
775
|
+
y += stack[stack.length - 1] ?? 0;
|
|
776
|
+
moveTo(x, y);
|
|
777
|
+
stack.length = 0;
|
|
778
|
+
break;
|
|
779
|
+
case 22:
|
|
780
|
+
takeWidth(1);
|
|
781
|
+
x += stack[stack.length - 1] ?? 0;
|
|
782
|
+
moveTo(x, y);
|
|
783
|
+
stack.length = 0;
|
|
784
|
+
break;
|
|
785
|
+
case 4:
|
|
786
|
+
takeWidth(1);
|
|
787
|
+
y += stack[stack.length - 1] ?? 0;
|
|
788
|
+
moveTo(x, y);
|
|
789
|
+
stack.length = 0;
|
|
790
|
+
break;
|
|
791
|
+
case 5:
|
|
792
|
+
for (let k = 0; k + 1 < stack.length; k += 2) {
|
|
793
|
+
x += stack[k];
|
|
794
|
+
y += stack[k + 1];
|
|
795
|
+
lineTo(x, y);
|
|
796
|
+
}
|
|
797
|
+
stack.length = 0;
|
|
798
|
+
break;
|
|
799
|
+
case 6:
|
|
800
|
+
case 7: {
|
|
801
|
+
let horizontal = b === 6;
|
|
802
|
+
for (const d of stack) {
|
|
803
|
+
if (horizontal) x += d;
|
|
804
|
+
else y += d;
|
|
805
|
+
lineTo(x, y);
|
|
806
|
+
horizontal = !horizontal;
|
|
807
|
+
}
|
|
808
|
+
stack.length = 0;
|
|
809
|
+
break;
|
|
810
|
+
}
|
|
811
|
+
case 8:
|
|
812
|
+
for (let k = 0; k + 5 < stack.length; k += 6) curve(stack, k);
|
|
813
|
+
stack.length = 0;
|
|
814
|
+
break;
|
|
815
|
+
case 24:
|
|
816
|
+
{
|
|
817
|
+
let k = 0;
|
|
818
|
+
for (; k + 5 < stack.length - 2; k += 6) curve(stack, k);
|
|
819
|
+
x += stack[k] ?? 0;
|
|
820
|
+
y += stack[k + 1] ?? 0;
|
|
821
|
+
lineTo(x, y);
|
|
822
|
+
}
|
|
823
|
+
stack.length = 0;
|
|
824
|
+
break;
|
|
825
|
+
case 25:
|
|
826
|
+
{
|
|
827
|
+
let k = 0;
|
|
828
|
+
for (; stack.length - k > 6; k += 2) {
|
|
829
|
+
x += stack[k];
|
|
830
|
+
y += stack[k + 1];
|
|
831
|
+
lineTo(x, y);
|
|
832
|
+
}
|
|
833
|
+
curve(stack, k);
|
|
834
|
+
}
|
|
835
|
+
stack.length = 0;
|
|
836
|
+
break;
|
|
837
|
+
case 26:
|
|
838
|
+
case 27: {
|
|
839
|
+
let k = 0;
|
|
840
|
+
let d1 = 0;
|
|
841
|
+
if (stack.length % 4 === 1) d1 = stack[k++];
|
|
842
|
+
for (; k + 3 < stack.length; k += 4) {
|
|
843
|
+
const vertical = b === 26;
|
|
844
|
+
const x1 = vertical ? x + d1 : x + stack[k];
|
|
845
|
+
const y1 = vertical ? y + stack[k] : y + d1;
|
|
846
|
+
const x2 = x1 + stack[k + 1];
|
|
847
|
+
const y2 = y1 + stack[k + 2];
|
|
848
|
+
x = vertical ? x2 : x2 + stack[k + 3];
|
|
849
|
+
y = vertical ? y2 + stack[k + 3] : y2;
|
|
850
|
+
curveTo(x1, y1, x2, y2, x, y);
|
|
851
|
+
d1 = 0;
|
|
852
|
+
}
|
|
853
|
+
stack.length = 0;
|
|
854
|
+
break;
|
|
855
|
+
}
|
|
856
|
+
case 30:
|
|
857
|
+
case 31: {
|
|
858
|
+
let horizontal = b === 31;
|
|
859
|
+
let k = 0;
|
|
860
|
+
while (k + 3 < stack.length) {
|
|
861
|
+
const last = stack.length - k === 5;
|
|
862
|
+
const x1 = horizontal ? x + stack[k] : x;
|
|
863
|
+
const y1 = horizontal ? y : y + stack[k];
|
|
864
|
+
const x2 = x1 + stack[k + 1];
|
|
865
|
+
const y2 = y1 + stack[k + 2];
|
|
866
|
+
if (horizontal) {
|
|
867
|
+
y = y2 + stack[k + 3];
|
|
868
|
+
x = x2 + (last ? stack[k + 4] : 0);
|
|
869
|
+
} else {
|
|
870
|
+
x = x2 + stack[k + 3];
|
|
871
|
+
y = y2 + (last ? stack[k + 4] : 0);
|
|
872
|
+
}
|
|
873
|
+
curveTo(x1, y1, x2, y2, x, y);
|
|
874
|
+
k += 4;
|
|
875
|
+
horizontal = !horizontal;
|
|
876
|
+
}
|
|
877
|
+
stack.length = 0;
|
|
878
|
+
break;
|
|
879
|
+
}
|
|
880
|
+
case 10:
|
|
881
|
+
case 29: {
|
|
882
|
+
const sub = (b === 10 ? local : font.globalSubrs)[(stack.pop() ?? 0) + (b === 10 ? localBias : globalBias)];
|
|
883
|
+
if (sub && depth < MAX_CALL_DEPTH && !run(sub, depth + 1)) return false;
|
|
884
|
+
break;
|
|
885
|
+
}
|
|
886
|
+
case 11: return true;
|
|
887
|
+
case 14:
|
|
888
|
+
takeWidth(stack.length > 4 ? 4 : 0);
|
|
889
|
+
if (open) out.push({ op: "close" });
|
|
890
|
+
open = false;
|
|
891
|
+
return false;
|
|
892
|
+
case 12: {
|
|
893
|
+
const op2 = code[i++];
|
|
894
|
+
runEscape(op2, stack, trans);
|
|
895
|
+
if (op2 === 35 || op2 === 34 || op2 === 36 || op2 === 37) {
|
|
896
|
+
const drawn = flexCurves(op2, stack, x, y);
|
|
897
|
+
for (const c of drawn.curves) curveTo(c[0], c[1], c[2], c[3], c[4], c[5]);
|
|
898
|
+
x = drawn.x;
|
|
899
|
+
y = drawn.y;
|
|
900
|
+
}
|
|
901
|
+
stack.length = 0;
|
|
902
|
+
break;
|
|
903
|
+
}
|
|
904
|
+
default:
|
|
905
|
+
stack.length = 0;
|
|
906
|
+
break;
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
return true;
|
|
910
|
+
};
|
|
911
|
+
function curve(operands, k) {
|
|
912
|
+
const x1 = x + (operands[k] ?? 0);
|
|
913
|
+
const y1 = y + (operands[k + 1] ?? 0);
|
|
914
|
+
const x2 = x1 + (operands[k + 2] ?? 0);
|
|
915
|
+
const y2 = y1 + (operands[k + 3] ?? 0);
|
|
916
|
+
x = x2 + (operands[k + 4] ?? 0);
|
|
917
|
+
y = y2 + (operands[k + 5] ?? 0);
|
|
918
|
+
curveTo(x1, y1, x2, y2, x, y);
|
|
919
|
+
}
|
|
920
|
+
run(program, 0);
|
|
921
|
+
if (out.length > 0 && out[out.length - 1]?.op !== "close") out.push({ op: "close" });
|
|
922
|
+
if (out.length === 0) return void 0;
|
|
923
|
+
return out.map((seg) => scaleSeg(seg, font.scale));
|
|
924
|
+
}
|
|
925
|
+
function runEscape(op, stack, trans) {
|
|
926
|
+
switch (op) {
|
|
927
|
+
case 3:
|
|
928
|
+
case 4:
|
|
929
|
+
case 10:
|
|
930
|
+
case 11:
|
|
931
|
+
case 12:
|
|
932
|
+
case 24:
|
|
933
|
+
{
|
|
934
|
+
const b = stack.pop() ?? 0;
|
|
935
|
+
const a = stack.pop() ?? 0;
|
|
936
|
+
stack.push(op === 3 ? a !== 0 && b !== 0 ? 1 : 0 : op === 4 ? a !== 0 || b !== 0 ? 1 : 0 : op === 10 ? a + b : op === 11 ? a - b : op === 12 ? b === 0 ? 0 : a / b : a * b);
|
|
937
|
+
}
|
|
938
|
+
break;
|
|
939
|
+
case 5:
|
|
940
|
+
stack.push((stack.pop() ?? 0) === 0 ? 1 : 0);
|
|
941
|
+
break;
|
|
942
|
+
case 9:
|
|
943
|
+
stack.push(Math.abs(stack.pop() ?? 0));
|
|
944
|
+
break;
|
|
945
|
+
case 14:
|
|
946
|
+
stack.push(-(stack.pop() ?? 0));
|
|
947
|
+
break;
|
|
948
|
+
case 18:
|
|
949
|
+
stack.pop();
|
|
950
|
+
break;
|
|
951
|
+
case 20: {
|
|
952
|
+
const index = stack.pop() ?? 0;
|
|
953
|
+
trans[index & 31] = stack.pop() ?? 0;
|
|
954
|
+
break;
|
|
955
|
+
}
|
|
956
|
+
case 21:
|
|
957
|
+
stack.push(trans[(stack.pop() ?? 0) & 31] ?? 0);
|
|
958
|
+
break;
|
|
959
|
+
case 26:
|
|
960
|
+
stack.push(Math.sqrt(Math.abs(stack.pop() ?? 0)));
|
|
961
|
+
break;
|
|
962
|
+
case 27: {
|
|
963
|
+
const v = stack[stack.length - 1] ?? 0;
|
|
964
|
+
stack.push(v);
|
|
965
|
+
break;
|
|
966
|
+
}
|
|
967
|
+
case 28: {
|
|
968
|
+
const b = stack.pop() ?? 0;
|
|
969
|
+
const a = stack.pop() ?? 0;
|
|
970
|
+
stack.push(b, a);
|
|
971
|
+
break;
|
|
972
|
+
}
|
|
973
|
+
default: break;
|
|
974
|
+
}
|
|
975
|
+
}
|
|
976
|
+
/**
|
|
977
|
+
* TN 5177 §4.2 — the flex operators, which draw two curves as one. `hflex` and
|
|
978
|
+
* friends leave axes implicit; this expands them to the six-tuples to draw.
|
|
979
|
+
*/
|
|
980
|
+
function flexCurves(op, stack, x0, y0) {
|
|
981
|
+
const n = (i) => stack[i] ?? 0;
|
|
982
|
+
const curves = [];
|
|
983
|
+
let x = x0;
|
|
984
|
+
let y = y0;
|
|
985
|
+
const push = (dxs, dys) => {
|
|
986
|
+
const x1 = x + (dxs[0] ?? 0);
|
|
987
|
+
const y1 = y + (dys[0] ?? 0);
|
|
988
|
+
const x2 = x1 + (dxs[1] ?? 0);
|
|
989
|
+
const y2 = y1 + (dys[1] ?? 0);
|
|
990
|
+
x = x2 + (dxs[2] ?? 0);
|
|
991
|
+
y = y2 + (dys[2] ?? 0);
|
|
992
|
+
curves.push([
|
|
993
|
+
x1,
|
|
994
|
+
y1,
|
|
995
|
+
x2,
|
|
996
|
+
y2,
|
|
997
|
+
x,
|
|
998
|
+
y
|
|
999
|
+
]);
|
|
1000
|
+
};
|
|
1001
|
+
if (op === 35) {
|
|
1002
|
+
push([
|
|
1003
|
+
n(0),
|
|
1004
|
+
n(2),
|
|
1005
|
+
n(4)
|
|
1006
|
+
], [
|
|
1007
|
+
n(1),
|
|
1008
|
+
n(3),
|
|
1009
|
+
n(5)
|
|
1010
|
+
]);
|
|
1011
|
+
push([
|
|
1012
|
+
n(6),
|
|
1013
|
+
n(8),
|
|
1014
|
+
n(10)
|
|
1015
|
+
], [
|
|
1016
|
+
n(7),
|
|
1017
|
+
n(9),
|
|
1018
|
+
n(11)
|
|
1019
|
+
]);
|
|
1020
|
+
} else if (op === 34) {
|
|
1021
|
+
const startY = y;
|
|
1022
|
+
push([
|
|
1023
|
+
n(0),
|
|
1024
|
+
n(1),
|
|
1025
|
+
n(3)
|
|
1026
|
+
], [
|
|
1027
|
+
0,
|
|
1028
|
+
n(2),
|
|
1029
|
+
0
|
|
1030
|
+
]);
|
|
1031
|
+
push([
|
|
1032
|
+
n(4),
|
|
1033
|
+
n(6),
|
|
1034
|
+
0
|
|
1035
|
+
], [
|
|
1036
|
+
0,
|
|
1037
|
+
startY - y,
|
|
1038
|
+
0
|
|
1039
|
+
]);
|
|
1040
|
+
y = startY;
|
|
1041
|
+
} else if (op === 36) {
|
|
1042
|
+
const startY = y;
|
|
1043
|
+
push([
|
|
1044
|
+
n(0),
|
|
1045
|
+
n(2),
|
|
1046
|
+
n(4)
|
|
1047
|
+
], [
|
|
1048
|
+
n(1),
|
|
1049
|
+
n(3),
|
|
1050
|
+
0
|
|
1051
|
+
]);
|
|
1052
|
+
push([
|
|
1053
|
+
n(5),
|
|
1054
|
+
n(7),
|
|
1055
|
+
n(8)
|
|
1056
|
+
], [
|
|
1057
|
+
0,
|
|
1058
|
+
n(6),
|
|
1059
|
+
startY - (y + n(6))
|
|
1060
|
+
]);
|
|
1061
|
+
y = startY;
|
|
1062
|
+
} else if (op === 37) {
|
|
1063
|
+
const startX = x;
|
|
1064
|
+
const startY = y;
|
|
1065
|
+
let dx = 0;
|
|
1066
|
+
let dy = 0;
|
|
1067
|
+
for (let k = 0; k < 10; k += 2) {
|
|
1068
|
+
dx += n(k);
|
|
1069
|
+
dy += n(k + 1);
|
|
1070
|
+
}
|
|
1071
|
+
push([
|
|
1072
|
+
n(0),
|
|
1073
|
+
n(2),
|
|
1074
|
+
n(4)
|
|
1075
|
+
], [
|
|
1076
|
+
n(1),
|
|
1077
|
+
n(3),
|
|
1078
|
+
n(5)
|
|
1079
|
+
]);
|
|
1080
|
+
const lastIsX = Math.abs(dx) > Math.abs(dy);
|
|
1081
|
+
const endX = lastIsX ? x + n(6) + n(8) + n(10) : startX;
|
|
1082
|
+
const endY = lastIsX ? startY : y + n(7) + n(9) + n(10);
|
|
1083
|
+
const x1 = x + n(6);
|
|
1084
|
+
const y1 = y + n(7);
|
|
1085
|
+
const x2 = x1 + n(8);
|
|
1086
|
+
const y2 = y1 + n(9);
|
|
1087
|
+
curves.push([
|
|
1088
|
+
x1,
|
|
1089
|
+
y1,
|
|
1090
|
+
x2,
|
|
1091
|
+
y2,
|
|
1092
|
+
endX,
|
|
1093
|
+
endY
|
|
1094
|
+
]);
|
|
1095
|
+
x = endX;
|
|
1096
|
+
y = endY;
|
|
1097
|
+
}
|
|
1098
|
+
return {
|
|
1099
|
+
curves,
|
|
1100
|
+
x,
|
|
1101
|
+
y
|
|
1102
|
+
};
|
|
1103
|
+
}
|
|
1104
|
+
function scaleSeg(seg, k) {
|
|
1105
|
+
if (seg.op === "close") return seg;
|
|
1106
|
+
if (seg.op === "cubic") return {
|
|
1107
|
+
op: "cubic",
|
|
1108
|
+
x1: seg.x1 * k,
|
|
1109
|
+
y1: seg.y1 * k,
|
|
1110
|
+
x2: seg.x2 * k,
|
|
1111
|
+
y2: seg.y2 * k,
|
|
1112
|
+
x: seg.x * k,
|
|
1113
|
+
y: seg.y * k
|
|
1114
|
+
};
|
|
1115
|
+
return {
|
|
1116
|
+
op: seg.op,
|
|
1117
|
+
x: seg.x * k,
|
|
1118
|
+
y: seg.y * k
|
|
1119
|
+
};
|
|
1120
|
+
}
|
|
1121
|
+
//#endregion
|
|
1122
|
+
export { cffCidToGid, cffNameToGid, cffOutlineSource, openTypeCff };
|