@grida/refig 0.0.2 → 0.0.4
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 +123 -40
- package/dist/browser.d.mts +63 -5
- package/dist/browser.mjs +1 -1
- package/dist/{chunk-YI7PIULZ.mjs → chunk-INJ5F2RK.mjs} +521 -42
- package/dist/cli.mjs +2580 -31
- package/dist/index.d.mts +1 -0
- package/dist/index.mjs +1 -1
- package/package.json +2 -1
package/dist/cli.mjs
CHANGED
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
exportSettingToRenderOptions,
|
|
7
7
|
figFileToRestLikeDocument,
|
|
8
8
|
iofigma
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-INJ5F2RK.mjs";
|
|
10
10
|
|
|
11
11
|
// cli.ts
|
|
12
12
|
import {
|
|
@@ -15,13 +15,2449 @@ import {
|
|
|
15
15
|
mkdirSync,
|
|
16
16
|
writeFileSync,
|
|
17
17
|
existsSync,
|
|
18
|
-
statSync
|
|
18
|
+
statSync,
|
|
19
|
+
mkdtempSync,
|
|
20
|
+
createReadStream
|
|
19
21
|
} from "fs";
|
|
20
22
|
import path from "path";
|
|
23
|
+
import { tmpdir } from "os";
|
|
21
24
|
import { program } from "commander";
|
|
25
|
+
|
|
26
|
+
// ../../node_modules/.pnpm/@grida+fonts@0.0.0/node_modules/@grida/fonts/dist/chunk-WQYZ3GYH.mjs
|
|
27
|
+
var Typr;
|
|
28
|
+
((Typr2) => {
|
|
29
|
+
function findTable(data, tab, foff) {
|
|
30
|
+
const bin = Typr2.B;
|
|
31
|
+
const numTables = bin.readUshort(data, foff + 4);
|
|
32
|
+
let offset = foff + 12;
|
|
33
|
+
for (let i = 0; i < numTables; i++) {
|
|
34
|
+
const tag = bin.readASCII(data, offset, 4);
|
|
35
|
+
const checkSum = bin.readUint(data, offset + 4);
|
|
36
|
+
const toffset = bin.readUint(data, offset + 8);
|
|
37
|
+
const length = bin.readUint(data, offset + 12);
|
|
38
|
+
if (tag == tab) return [toffset, length];
|
|
39
|
+
offset += 16;
|
|
40
|
+
}
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
Typr2.findTable = findTable;
|
|
44
|
+
function parse(buff) {
|
|
45
|
+
const bin = Typr2.B;
|
|
46
|
+
const readFont = function(data2, idx, offset, tmap2) {
|
|
47
|
+
const T2 = Typr2.T;
|
|
48
|
+
const prsr = {
|
|
49
|
+
cmap: T2.cmap,
|
|
50
|
+
head: T2.head,
|
|
51
|
+
hhea: T2.hhea,
|
|
52
|
+
maxp: T2.maxp,
|
|
53
|
+
hmtx: T2.hmtx,
|
|
54
|
+
name: T2.name,
|
|
55
|
+
"OS/2": T2.OS2,
|
|
56
|
+
post: T2.post,
|
|
57
|
+
loca: T2.loca,
|
|
58
|
+
kern: T2.kern,
|
|
59
|
+
glyf: T2.glyf,
|
|
60
|
+
"CFF ": T2.CFF,
|
|
61
|
+
GSUB: T2.GSUB,
|
|
62
|
+
CBLC: T2.CBLC,
|
|
63
|
+
CBDT: T2.CBDT,
|
|
64
|
+
"SVG ": T2.SVG,
|
|
65
|
+
COLR: T2.colr,
|
|
66
|
+
CPAL: T2.cpal,
|
|
67
|
+
sbix: T2.sbix,
|
|
68
|
+
fvar: T2.fvar,
|
|
69
|
+
gvar: T2.gvar,
|
|
70
|
+
avar: T2.avar,
|
|
71
|
+
STAT: T2.STAT,
|
|
72
|
+
HVAR: T2.HVAR
|
|
73
|
+
};
|
|
74
|
+
const obj = { _data: data2, _index: idx, _offset: offset };
|
|
75
|
+
for (const t in prsr) {
|
|
76
|
+
const tab = Typr2.findTable(data2, t, offset);
|
|
77
|
+
if (tab) {
|
|
78
|
+
const off = tab[0];
|
|
79
|
+
let tobj = tmap2[off];
|
|
80
|
+
if (tobj == null) tobj = prsr[t].parseTab(data2, off, tab[1], obj);
|
|
81
|
+
obj[t] = tmap2[off] = tobj;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return obj;
|
|
85
|
+
};
|
|
86
|
+
function woffToOtf(data2) {
|
|
87
|
+
const numTables = bin.readUshort(data2, 12);
|
|
88
|
+
const totalSize = bin.readUint(data2, 16);
|
|
89
|
+
const otf = new Uint8Array(totalSize);
|
|
90
|
+
let toff = 12 + numTables * 16;
|
|
91
|
+
bin.writeASCII(otf, 0, "OTTO");
|
|
92
|
+
bin.writeUshort(otf, 4, numTables);
|
|
93
|
+
let off = 44;
|
|
94
|
+
for (let i = 0; i < numTables; i++) {
|
|
95
|
+
const tag2 = bin.readASCII(data2, off, 4);
|
|
96
|
+
const tof = bin.readUint(data2, off + 4);
|
|
97
|
+
const cLe = bin.readUint(data2, off + 8);
|
|
98
|
+
const oLe = bin.readUint(data2, off + 12);
|
|
99
|
+
off += 20;
|
|
100
|
+
let tab = data2.slice(tof, tof + cLe);
|
|
101
|
+
if (cLe != oLe) {
|
|
102
|
+
console.warn("pako inflate not available, using original data");
|
|
103
|
+
}
|
|
104
|
+
const to = 12 + i * 16;
|
|
105
|
+
bin.writeASCII(otf, to, tag2);
|
|
106
|
+
bin.writeUint(otf, to + 8, toff);
|
|
107
|
+
bin.writeUint(otf, to + 12, oLe);
|
|
108
|
+
otf.set(tab, toff);
|
|
109
|
+
toff += oLe;
|
|
110
|
+
}
|
|
111
|
+
return otf;
|
|
112
|
+
}
|
|
113
|
+
let data = buff instanceof Uint8Array ? buff : new Uint8Array(buff);
|
|
114
|
+
if (data[0] == 119) data = woffToOtf(data);
|
|
115
|
+
const tmap = {};
|
|
116
|
+
const tag = bin.readASCII(data, 0, 4);
|
|
117
|
+
if (tag == "ttcf") {
|
|
118
|
+
let offset = 4;
|
|
119
|
+
const majV = bin.readUshort(data, offset);
|
|
120
|
+
offset += 2;
|
|
121
|
+
const minV = bin.readUshort(data, offset);
|
|
122
|
+
offset += 2;
|
|
123
|
+
const numF = bin.readUint(data, offset);
|
|
124
|
+
offset += 4;
|
|
125
|
+
const fnts = [];
|
|
126
|
+
for (let i = 0; i < numF; i++) {
|
|
127
|
+
const foff = bin.readUint(data, offset);
|
|
128
|
+
offset += 4;
|
|
129
|
+
fnts.push(readFont(data, i, foff, tmap));
|
|
130
|
+
}
|
|
131
|
+
return fnts;
|
|
132
|
+
}
|
|
133
|
+
const fnt = readFont(data, 0, 0, tmap);
|
|
134
|
+
const fvar = fnt["fvar"];
|
|
135
|
+
if (fvar && fvar[1] && Array.isArray(fvar[1])) {
|
|
136
|
+
const out = [fnt];
|
|
137
|
+
for (let i = 0; i < fvar[1].length; i++) {
|
|
138
|
+
const fv = fvar[1][i];
|
|
139
|
+
const obj = {
|
|
140
|
+
_data: fnt._data,
|
|
141
|
+
_index: i,
|
|
142
|
+
_offset: fnt._offset
|
|
143
|
+
};
|
|
144
|
+
out.push(obj);
|
|
145
|
+
for (const p in fnt) obj[p] = fnt[p];
|
|
146
|
+
const name = obj["name"] = JSON.parse(JSON.stringify(obj["name"]));
|
|
147
|
+
name["fontSubfamily"] = fv[0];
|
|
148
|
+
}
|
|
149
|
+
return out;
|
|
150
|
+
}
|
|
151
|
+
return [fnt];
|
|
152
|
+
}
|
|
153
|
+
Typr2.parse = parse;
|
|
154
|
+
let B;
|
|
155
|
+
((B2) => {
|
|
156
|
+
function readFixed(data, offset) {
|
|
157
|
+
const value = Typr2.B.readInt(data, offset);
|
|
158
|
+
return value / 65536;
|
|
159
|
+
}
|
|
160
|
+
B2.readFixed = readFixed;
|
|
161
|
+
function readF2dot14(data, offset) {
|
|
162
|
+
const num = Typr2.B.readShort(data, offset);
|
|
163
|
+
return num / 16384;
|
|
164
|
+
}
|
|
165
|
+
B2.readF2dot14 = readF2dot14;
|
|
166
|
+
function readInt(buff, offset) {
|
|
167
|
+
const a = Typr2.B.t.uint8;
|
|
168
|
+
a[0] = buff[offset + 3];
|
|
169
|
+
a[1] = buff[offset + 2];
|
|
170
|
+
a[2] = buff[offset + 1];
|
|
171
|
+
a[3] = buff[offset];
|
|
172
|
+
return Typr2.B.t.int32[0];
|
|
173
|
+
}
|
|
174
|
+
B2.readInt = readInt;
|
|
175
|
+
function readInt8(buff, offset) {
|
|
176
|
+
const a = Typr2.B.t.uint8;
|
|
177
|
+
a[0] = buff[offset];
|
|
178
|
+
return Typr2.B.t.int8[0];
|
|
179
|
+
}
|
|
180
|
+
B2.readInt8 = readInt8;
|
|
181
|
+
function readShort(buff, offset) {
|
|
182
|
+
const a = Typr2.B.t.uint16;
|
|
183
|
+
a[0] = buff[offset] << 8 | buff[offset + 1];
|
|
184
|
+
return Typr2.B.t.int16[0];
|
|
185
|
+
}
|
|
186
|
+
B2.readShort = readShort;
|
|
187
|
+
function readUshort(buff, offset) {
|
|
188
|
+
return buff[offset] << 8 | buff[offset + 1];
|
|
189
|
+
}
|
|
190
|
+
B2.readUshort = readUshort;
|
|
191
|
+
function writeUshort(buff, offset, value) {
|
|
192
|
+
buff[offset] = value >> 8 & 255;
|
|
193
|
+
buff[offset + 1] = value & 255;
|
|
194
|
+
}
|
|
195
|
+
B2.writeUshort = writeUshort;
|
|
196
|
+
function readUshorts(buff, offset, length) {
|
|
197
|
+
const arr = [];
|
|
198
|
+
for (let i = 0; i < length; i++) {
|
|
199
|
+
const v = Typr2.B.readUshort(buff, offset + i * 2);
|
|
200
|
+
arr.push(v);
|
|
201
|
+
}
|
|
202
|
+
return arr;
|
|
203
|
+
}
|
|
204
|
+
B2.readUshorts = readUshorts;
|
|
205
|
+
function readUint(buff, offset) {
|
|
206
|
+
const a = Typr2.B.t.uint8;
|
|
207
|
+
a[3] = buff[offset];
|
|
208
|
+
a[2] = buff[offset + 1];
|
|
209
|
+
a[1] = buff[offset + 2];
|
|
210
|
+
a[0] = buff[offset + 3];
|
|
211
|
+
return Typr2.B.t.uint32[0];
|
|
212
|
+
}
|
|
213
|
+
B2.readUint = readUint;
|
|
214
|
+
function writeUint(buff, offset, value) {
|
|
215
|
+
buff[offset] = value >> 24 & 255;
|
|
216
|
+
buff[offset + 1] = value >> 16 & 255;
|
|
217
|
+
buff[offset + 2] = value >> 8 & 255;
|
|
218
|
+
buff[offset + 3] = value >> 0 & 255;
|
|
219
|
+
}
|
|
220
|
+
B2.writeUint = writeUint;
|
|
221
|
+
function readUint64(buff, offset) {
|
|
222
|
+
return Typr2.B.readUint(buff, offset) * (4294967295 + 1) + Typr2.B.readUint(buff, offset + 4);
|
|
223
|
+
}
|
|
224
|
+
B2.readUint64 = readUint64;
|
|
225
|
+
function readASCII(buff, offset, length) {
|
|
226
|
+
let s = "";
|
|
227
|
+
for (let i = 0; i < length; i++)
|
|
228
|
+
s += String.fromCharCode(buff[offset + i]);
|
|
229
|
+
return s;
|
|
230
|
+
}
|
|
231
|
+
B2.readASCII = readASCII;
|
|
232
|
+
function writeASCII(buff, offset, str) {
|
|
233
|
+
for (let i = 0; i < str.length; i++) buff[offset + i] = str.charCodeAt(i);
|
|
234
|
+
}
|
|
235
|
+
B2.writeASCII = writeASCII;
|
|
236
|
+
function readUnicode(buff, offset, length) {
|
|
237
|
+
let s = "";
|
|
238
|
+
for (let i = 0; i < length; i++) {
|
|
239
|
+
const c = buff[offset++] << 8 | buff[offset++];
|
|
240
|
+
s += String.fromCharCode(c);
|
|
241
|
+
}
|
|
242
|
+
return s;
|
|
243
|
+
}
|
|
244
|
+
B2.readUnicode = readUnicode;
|
|
245
|
+
B2._tdec = typeof TextDecoder !== "undefined" ? new TextDecoder() : null;
|
|
246
|
+
function readUTF8(buff, offset, length) {
|
|
247
|
+
const tdec = Typr2.B._tdec;
|
|
248
|
+
if (tdec && offset == 0 && length == buff.length)
|
|
249
|
+
return tdec.decode(buff);
|
|
250
|
+
return Typr2.B.readASCII(buff, offset, length);
|
|
251
|
+
}
|
|
252
|
+
B2.readUTF8 = readUTF8;
|
|
253
|
+
function readBytes(buff, offset, length) {
|
|
254
|
+
const arr = [];
|
|
255
|
+
for (let i = 0; i < length; i++) arr.push(buff[offset + i]);
|
|
256
|
+
return arr;
|
|
257
|
+
}
|
|
258
|
+
B2.readBytes = readBytes;
|
|
259
|
+
function readASCIIArray(buff, offset, length) {
|
|
260
|
+
const s = [];
|
|
261
|
+
for (let i = 0; i < length; i++)
|
|
262
|
+
s.push(String.fromCharCode(buff[offset + i]));
|
|
263
|
+
return s;
|
|
264
|
+
}
|
|
265
|
+
B2.readASCIIArray = readASCIIArray;
|
|
266
|
+
B2.t = (function() {
|
|
267
|
+
const ab = new ArrayBuffer(8);
|
|
268
|
+
return {
|
|
269
|
+
buff: ab,
|
|
270
|
+
int8: new Int8Array(ab),
|
|
271
|
+
uint8: new Uint8Array(ab),
|
|
272
|
+
int16: new Int16Array(ab),
|
|
273
|
+
uint16: new Uint16Array(ab),
|
|
274
|
+
int32: new Int32Array(ab),
|
|
275
|
+
uint32: new Uint32Array(ab)
|
|
276
|
+
};
|
|
277
|
+
})();
|
|
278
|
+
})(B = Typr2.B || (Typr2.B = {}));
|
|
279
|
+
let T;
|
|
280
|
+
((T2) => {
|
|
281
|
+
T2.CFF = {
|
|
282
|
+
parseTab: function(data, offset, length) {
|
|
283
|
+
const bin = Typr2.B;
|
|
284
|
+
const CFF2 = Typr2.T.CFF;
|
|
285
|
+
data = new Uint8Array(data.buffer, offset, length);
|
|
286
|
+
offset = 0;
|
|
287
|
+
const major = data[offset];
|
|
288
|
+
offset++;
|
|
289
|
+
const minor = data[offset];
|
|
290
|
+
offset++;
|
|
291
|
+
const hdrSize = data[offset];
|
|
292
|
+
offset++;
|
|
293
|
+
const offsize = data[offset];
|
|
294
|
+
offset++;
|
|
295
|
+
const ninds = [];
|
|
296
|
+
offset = CFF2.readIndex(data, offset, ninds);
|
|
297
|
+
const names = [];
|
|
298
|
+
for (let i = 0; i < ninds.length - 1; i++)
|
|
299
|
+
names.push(
|
|
300
|
+
bin.readASCII(data, offset + ninds[i], ninds[i + 1] - ninds[i])
|
|
301
|
+
);
|
|
302
|
+
offset += ninds[ninds.length - 1];
|
|
303
|
+
const tdinds = [];
|
|
304
|
+
offset = CFF2.readIndex(data, offset, tdinds);
|
|
305
|
+
const topDicts = [];
|
|
306
|
+
for (let i = 0; i < tdinds.length - 1; i++)
|
|
307
|
+
topDicts.push(
|
|
308
|
+
CFF2.readDict(data, offset + tdinds[i], offset + tdinds[i + 1])
|
|
309
|
+
);
|
|
310
|
+
offset += tdinds[tdinds.length - 1];
|
|
311
|
+
const topdict = topDicts[0];
|
|
312
|
+
const sinds = [];
|
|
313
|
+
offset = CFF2.readIndex(data, offset, sinds);
|
|
314
|
+
const strings = [];
|
|
315
|
+
for (let i = 0; i < sinds.length - 1; i++)
|
|
316
|
+
strings.push(
|
|
317
|
+
bin.readASCII(data, offset + sinds[i], sinds[i + 1] - sinds[i])
|
|
318
|
+
);
|
|
319
|
+
offset += sinds[sinds.length - 1];
|
|
320
|
+
CFF2.readSubrs(data, offset, topdict);
|
|
321
|
+
if (topdict["CharStrings"])
|
|
322
|
+
topdict["CharStrings"] = CFF2.readBytes(data, topdict["CharStrings"]);
|
|
323
|
+
if (topdict["ROS"]) {
|
|
324
|
+
offset = topdict["FDArray"];
|
|
325
|
+
const fdind = [];
|
|
326
|
+
offset = CFF2.readIndex(data, offset, fdind);
|
|
327
|
+
topdict["FDArray"] = [];
|
|
328
|
+
for (let i = 0; i < fdind.length - 1; i++) {
|
|
329
|
+
const dict = CFF2.readDict(
|
|
330
|
+
data,
|
|
331
|
+
offset + fdind[i],
|
|
332
|
+
offset + fdind[i + 1]
|
|
333
|
+
);
|
|
334
|
+
CFF2._readFDict(data, dict, strings);
|
|
335
|
+
topdict["FDArray"].push(dict);
|
|
336
|
+
}
|
|
337
|
+
offset += fdind[fdind.length - 1];
|
|
338
|
+
offset = topdict["FDSelect"];
|
|
339
|
+
topdict["FDSelect"] = [];
|
|
340
|
+
const fmt = data[offset];
|
|
341
|
+
offset++;
|
|
342
|
+
if (fmt == 3) {
|
|
343
|
+
const rns = bin.readUshort(data, offset);
|
|
344
|
+
offset += 2;
|
|
345
|
+
for (let i = 0; i < rns + 1; i++) {
|
|
346
|
+
topdict["FDSelect"].push(
|
|
347
|
+
bin.readUshort(data, offset),
|
|
348
|
+
data[offset + 2]
|
|
349
|
+
);
|
|
350
|
+
offset += 3;
|
|
351
|
+
}
|
|
352
|
+
} else throw new Error(`Unknown format: ${fmt}`);
|
|
353
|
+
}
|
|
354
|
+
if (topdict["charset"] && topdict["CharStrings"])
|
|
355
|
+
topdict["charset"] = CFF2.readCharset(
|
|
356
|
+
data,
|
|
357
|
+
topdict["charset"],
|
|
358
|
+
topdict["CharStrings"].length
|
|
359
|
+
);
|
|
360
|
+
CFF2._readFDict(data, topdict, strings);
|
|
361
|
+
return topdict;
|
|
362
|
+
},
|
|
363
|
+
_readFDict: function(data, dict, ss) {
|
|
364
|
+
const CFF2 = Typr2.T.CFF;
|
|
365
|
+
let offset;
|
|
366
|
+
if (dict["Private"]) {
|
|
367
|
+
offset = dict["Private"][1];
|
|
368
|
+
dict["Private"] = CFF2.readDict(
|
|
369
|
+
data,
|
|
370
|
+
offset,
|
|
371
|
+
offset + dict["Private"][0]
|
|
372
|
+
);
|
|
373
|
+
if (dict["Private"]["Subrs"])
|
|
374
|
+
CFF2.readSubrs(
|
|
375
|
+
data,
|
|
376
|
+
offset + dict["Private"]["Subrs"],
|
|
377
|
+
dict["Private"]
|
|
378
|
+
);
|
|
379
|
+
}
|
|
380
|
+
for (const p in dict)
|
|
381
|
+
if ([
|
|
382
|
+
"FamilyName",
|
|
383
|
+
"FontName",
|
|
384
|
+
"FullName",
|
|
385
|
+
"Notice",
|
|
386
|
+
"version",
|
|
387
|
+
"Copyright"
|
|
388
|
+
].indexOf(p) != -1)
|
|
389
|
+
dict[p] = ss[dict[p] - 426 + 35];
|
|
390
|
+
},
|
|
391
|
+
readSubrs: function(data, offset, obj) {
|
|
392
|
+
obj["Subrs"] = Typr2.T.CFF.readBytes(data, offset);
|
|
393
|
+
let bias;
|
|
394
|
+
const nSubrs = obj["Subrs"].length + 1;
|
|
395
|
+
if (false) bias = 0;
|
|
396
|
+
else if (nSubrs < 1240) bias = 107;
|
|
397
|
+
else if (nSubrs < 33900) bias = 1131;
|
|
398
|
+
else bias = 32768;
|
|
399
|
+
obj["Bias"] = bias;
|
|
400
|
+
},
|
|
401
|
+
readBytes: function(data, offset) {
|
|
402
|
+
const bin = Typr2.B;
|
|
403
|
+
const arr = [];
|
|
404
|
+
offset = Typr2.T.CFF.readIndex(data, offset, arr);
|
|
405
|
+
const subrs = [];
|
|
406
|
+
const arl = arr.length - 1;
|
|
407
|
+
const no = data.byteOffset + offset;
|
|
408
|
+
for (let i = 0; i < arl; i++) {
|
|
409
|
+
const ari = arr[i];
|
|
410
|
+
subrs.push(
|
|
411
|
+
new Uint8Array(
|
|
412
|
+
data.buffer,
|
|
413
|
+
no + ari,
|
|
414
|
+
arr[i + 1] - ari
|
|
415
|
+
)
|
|
416
|
+
);
|
|
417
|
+
}
|
|
418
|
+
return subrs;
|
|
419
|
+
},
|
|
420
|
+
tableSE: [
|
|
421
|
+
0,
|
|
422
|
+
0,
|
|
423
|
+
0,
|
|
424
|
+
0,
|
|
425
|
+
0,
|
|
426
|
+
0,
|
|
427
|
+
0,
|
|
428
|
+
0,
|
|
429
|
+
0,
|
|
430
|
+
0,
|
|
431
|
+
0,
|
|
432
|
+
0,
|
|
433
|
+
0,
|
|
434
|
+
0,
|
|
435
|
+
0,
|
|
436
|
+
0,
|
|
437
|
+
0,
|
|
438
|
+
0,
|
|
439
|
+
0,
|
|
440
|
+
0,
|
|
441
|
+
0,
|
|
442
|
+
0,
|
|
443
|
+
0,
|
|
444
|
+
0,
|
|
445
|
+
0,
|
|
446
|
+
0,
|
|
447
|
+
0,
|
|
448
|
+
0,
|
|
449
|
+
0,
|
|
450
|
+
0,
|
|
451
|
+
0,
|
|
452
|
+
0,
|
|
453
|
+
1,
|
|
454
|
+
2,
|
|
455
|
+
3,
|
|
456
|
+
4,
|
|
457
|
+
5,
|
|
458
|
+
6,
|
|
459
|
+
7,
|
|
460
|
+
8,
|
|
461
|
+
9,
|
|
462
|
+
10,
|
|
463
|
+
11,
|
|
464
|
+
12,
|
|
465
|
+
13,
|
|
466
|
+
14,
|
|
467
|
+
15,
|
|
468
|
+
16,
|
|
469
|
+
17,
|
|
470
|
+
18,
|
|
471
|
+
19,
|
|
472
|
+
20,
|
|
473
|
+
21,
|
|
474
|
+
22,
|
|
475
|
+
23,
|
|
476
|
+
24,
|
|
477
|
+
25,
|
|
478
|
+
26,
|
|
479
|
+
27,
|
|
480
|
+
28,
|
|
481
|
+
29,
|
|
482
|
+
30,
|
|
483
|
+
31,
|
|
484
|
+
32,
|
|
485
|
+
33,
|
|
486
|
+
34,
|
|
487
|
+
35,
|
|
488
|
+
36,
|
|
489
|
+
37,
|
|
490
|
+
38,
|
|
491
|
+
39,
|
|
492
|
+
40,
|
|
493
|
+
41,
|
|
494
|
+
42,
|
|
495
|
+
43,
|
|
496
|
+
44,
|
|
497
|
+
45,
|
|
498
|
+
46,
|
|
499
|
+
47,
|
|
500
|
+
48,
|
|
501
|
+
49,
|
|
502
|
+
50,
|
|
503
|
+
51,
|
|
504
|
+
52,
|
|
505
|
+
53,
|
|
506
|
+
54,
|
|
507
|
+
55,
|
|
508
|
+
56,
|
|
509
|
+
57,
|
|
510
|
+
58,
|
|
511
|
+
59,
|
|
512
|
+
60,
|
|
513
|
+
61,
|
|
514
|
+
62,
|
|
515
|
+
63,
|
|
516
|
+
64,
|
|
517
|
+
65,
|
|
518
|
+
66,
|
|
519
|
+
67,
|
|
520
|
+
68,
|
|
521
|
+
69,
|
|
522
|
+
70,
|
|
523
|
+
71,
|
|
524
|
+
72,
|
|
525
|
+
73,
|
|
526
|
+
74,
|
|
527
|
+
75,
|
|
528
|
+
76,
|
|
529
|
+
77,
|
|
530
|
+
78,
|
|
531
|
+
79,
|
|
532
|
+
80,
|
|
533
|
+
81,
|
|
534
|
+
82,
|
|
535
|
+
83,
|
|
536
|
+
84,
|
|
537
|
+
85,
|
|
538
|
+
86,
|
|
539
|
+
87,
|
|
540
|
+
88,
|
|
541
|
+
89,
|
|
542
|
+
90,
|
|
543
|
+
91,
|
|
544
|
+
92,
|
|
545
|
+
93,
|
|
546
|
+
94,
|
|
547
|
+
95,
|
|
548
|
+
0,
|
|
549
|
+
0,
|
|
550
|
+
0,
|
|
551
|
+
0,
|
|
552
|
+
0,
|
|
553
|
+
0,
|
|
554
|
+
0,
|
|
555
|
+
0,
|
|
556
|
+
0,
|
|
557
|
+
0,
|
|
558
|
+
0,
|
|
559
|
+
0,
|
|
560
|
+
0,
|
|
561
|
+
0,
|
|
562
|
+
0,
|
|
563
|
+
0,
|
|
564
|
+
0,
|
|
565
|
+
0,
|
|
566
|
+
0,
|
|
567
|
+
0,
|
|
568
|
+
0,
|
|
569
|
+
0,
|
|
570
|
+
0,
|
|
571
|
+
0,
|
|
572
|
+
0,
|
|
573
|
+
0,
|
|
574
|
+
0,
|
|
575
|
+
0,
|
|
576
|
+
0,
|
|
577
|
+
0,
|
|
578
|
+
0,
|
|
579
|
+
0,
|
|
580
|
+
0,
|
|
581
|
+
0,
|
|
582
|
+
96,
|
|
583
|
+
97,
|
|
584
|
+
98,
|
|
585
|
+
99,
|
|
586
|
+
100,
|
|
587
|
+
101,
|
|
588
|
+
102,
|
|
589
|
+
103,
|
|
590
|
+
104,
|
|
591
|
+
105,
|
|
592
|
+
106,
|
|
593
|
+
107,
|
|
594
|
+
108,
|
|
595
|
+
109,
|
|
596
|
+
110,
|
|
597
|
+
0,
|
|
598
|
+
111,
|
|
599
|
+
112,
|
|
600
|
+
113,
|
|
601
|
+
114,
|
|
602
|
+
0,
|
|
603
|
+
115,
|
|
604
|
+
116,
|
|
605
|
+
117,
|
|
606
|
+
118,
|
|
607
|
+
119,
|
|
608
|
+
120,
|
|
609
|
+
121,
|
|
610
|
+
122,
|
|
611
|
+
0,
|
|
612
|
+
123,
|
|
613
|
+
0,
|
|
614
|
+
124,
|
|
615
|
+
125,
|
|
616
|
+
126,
|
|
617
|
+
127,
|
|
618
|
+
128,
|
|
619
|
+
129,
|
|
620
|
+
130,
|
|
621
|
+
131,
|
|
622
|
+
0,
|
|
623
|
+
132,
|
|
624
|
+
133,
|
|
625
|
+
0,
|
|
626
|
+
134,
|
|
627
|
+
135,
|
|
628
|
+
136,
|
|
629
|
+
137,
|
|
630
|
+
0,
|
|
631
|
+
0,
|
|
632
|
+
0,
|
|
633
|
+
0,
|
|
634
|
+
0,
|
|
635
|
+
0,
|
|
636
|
+
0,
|
|
637
|
+
0,
|
|
638
|
+
0,
|
|
639
|
+
0,
|
|
640
|
+
0,
|
|
641
|
+
0,
|
|
642
|
+
0,
|
|
643
|
+
0,
|
|
644
|
+
0,
|
|
645
|
+
0,
|
|
646
|
+
138,
|
|
647
|
+
0,
|
|
648
|
+
139,
|
|
649
|
+
0,
|
|
650
|
+
0,
|
|
651
|
+
0,
|
|
652
|
+
0,
|
|
653
|
+
140,
|
|
654
|
+
141,
|
|
655
|
+
142,
|
|
656
|
+
143,
|
|
657
|
+
0,
|
|
658
|
+
0,
|
|
659
|
+
0,
|
|
660
|
+
0,
|
|
661
|
+
0,
|
|
662
|
+
144,
|
|
663
|
+
0,
|
|
664
|
+
0,
|
|
665
|
+
0,
|
|
666
|
+
145,
|
|
667
|
+
0,
|
|
668
|
+
0,
|
|
669
|
+
146,
|
|
670
|
+
147,
|
|
671
|
+
148,
|
|
672
|
+
149,
|
|
673
|
+
0,
|
|
674
|
+
0,
|
|
675
|
+
0,
|
|
676
|
+
0
|
|
677
|
+
],
|
|
678
|
+
glyphByUnicode: function(cff, code) {
|
|
679
|
+
if (!cff["charset"]) return -1;
|
|
680
|
+
for (let i = 0; i < cff["charset"].length; i++)
|
|
681
|
+
if (cff["charset"][i] == code) return i;
|
|
682
|
+
return -1;
|
|
683
|
+
},
|
|
684
|
+
glyphBySE: function(cff, charcode) {
|
|
685
|
+
if (charcode < 0 || charcode > 255) return -1;
|
|
686
|
+
return Typr2.T.CFF.glyphByUnicode(cff, Typr2.T.CFF.tableSE[charcode]);
|
|
687
|
+
},
|
|
688
|
+
readCharset: function(data, offset, num) {
|
|
689
|
+
const bin = Typr2.B;
|
|
690
|
+
const charset = [0];
|
|
691
|
+
const format = data[offset];
|
|
692
|
+
offset++;
|
|
693
|
+
if (format == 0) {
|
|
694
|
+
for (let i = 0; i < num; i++) {
|
|
695
|
+
const first = bin.readUshort(data, offset);
|
|
696
|
+
offset += 2;
|
|
697
|
+
charset.push(first);
|
|
698
|
+
}
|
|
699
|
+
} else if (format == 1 || format == 2) {
|
|
700
|
+
while (charset.length < num) {
|
|
701
|
+
let first = bin.readUshort(data, offset);
|
|
702
|
+
offset += 2;
|
|
703
|
+
let nLeft = 0;
|
|
704
|
+
if (format == 1) {
|
|
705
|
+
nLeft = data[offset];
|
|
706
|
+
offset++;
|
|
707
|
+
} else {
|
|
708
|
+
nLeft = bin.readUshort(data, offset);
|
|
709
|
+
offset += 2;
|
|
710
|
+
}
|
|
711
|
+
for (let i = 0; i <= nLeft; i++) {
|
|
712
|
+
charset.push(first);
|
|
713
|
+
first++;
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
} else throw new Error(`Unknown format: ${format}`);
|
|
717
|
+
return charset;
|
|
718
|
+
},
|
|
719
|
+
readIndex: function(data, offset, inds) {
|
|
720
|
+
const bin = Typr2.B;
|
|
721
|
+
const count = bin.readUshort(data, offset) + 1;
|
|
722
|
+
offset += 2;
|
|
723
|
+
const offsize = data[offset];
|
|
724
|
+
offset++;
|
|
725
|
+
if (offsize == 1)
|
|
726
|
+
for (let i = 0; i < count; i++) inds.push(data[offset + i]);
|
|
727
|
+
else if (offsize == 2)
|
|
728
|
+
for (let i = 0; i < count; i++)
|
|
729
|
+
inds.push(bin.readUshort(data, offset + i * 2));
|
|
730
|
+
else if (offsize == 3)
|
|
731
|
+
for (let i = 0; i < count; i++)
|
|
732
|
+
inds.push(bin.readUint(data, offset + i * 3 - 1) & 16777215);
|
|
733
|
+
else if (offsize == 4)
|
|
734
|
+
for (let i = 0; i < count; i++)
|
|
735
|
+
inds.push(bin.readUint(data, offset + i * 4));
|
|
736
|
+
else if (count != 1)
|
|
737
|
+
throw new Error(
|
|
738
|
+
`Unsupported offset size: ${offsize}, count: ${count}`
|
|
739
|
+
);
|
|
740
|
+
offset += count * offsize;
|
|
741
|
+
return offset - 1;
|
|
742
|
+
},
|
|
743
|
+
getCharString: function(data, offset, o) {
|
|
744
|
+
const bin = Typr2.B;
|
|
745
|
+
const b0 = data[offset];
|
|
746
|
+
const b1 = data[offset + 1];
|
|
747
|
+
const b2 = data[offset + 2];
|
|
748
|
+
const b3 = data[offset + 3];
|
|
749
|
+
const b4 = data[offset + 4];
|
|
750
|
+
let vs = 1;
|
|
751
|
+
let op = null;
|
|
752
|
+
let val = null;
|
|
753
|
+
if (b0 <= 20) {
|
|
754
|
+
op = b0;
|
|
755
|
+
vs = 1;
|
|
756
|
+
}
|
|
757
|
+
if (b0 == 12) {
|
|
758
|
+
op = b0 * 100 + b1;
|
|
759
|
+
vs = 2;
|
|
760
|
+
}
|
|
761
|
+
if (21 <= b0 && b0 <= 27) {
|
|
762
|
+
op = b0;
|
|
763
|
+
vs = 1;
|
|
764
|
+
}
|
|
765
|
+
if (b0 == 28) {
|
|
766
|
+
val = bin.readShort(data, offset + 1);
|
|
767
|
+
vs = 3;
|
|
768
|
+
}
|
|
769
|
+
if (29 <= b0 && b0 <= 31) {
|
|
770
|
+
op = b0;
|
|
771
|
+
vs = 1;
|
|
772
|
+
}
|
|
773
|
+
if (32 <= b0 && b0 <= 246) {
|
|
774
|
+
val = b0 - 139;
|
|
775
|
+
vs = 1;
|
|
776
|
+
}
|
|
777
|
+
if (247 <= b0 && b0 <= 250) {
|
|
778
|
+
val = (b0 - 247) * 256 + b1 + 108;
|
|
779
|
+
vs = 2;
|
|
780
|
+
}
|
|
781
|
+
if (251 <= b0 && b0 <= 254) {
|
|
782
|
+
val = -(b0 - 251) * 256 - b1 - 108;
|
|
783
|
+
vs = 2;
|
|
784
|
+
}
|
|
785
|
+
if (b0 == 255) {
|
|
786
|
+
val = bin.readInt(data, offset + 1) / 65535;
|
|
787
|
+
vs = 5;
|
|
788
|
+
}
|
|
789
|
+
o.val = val != null ? val : "o" + op;
|
|
790
|
+
o.size = vs;
|
|
791
|
+
},
|
|
792
|
+
readCharString: function(data, offset, length) {
|
|
793
|
+
const end = offset + length;
|
|
794
|
+
const bin = Typr2.B;
|
|
795
|
+
const arr = [];
|
|
796
|
+
while (offset < end) {
|
|
797
|
+
const b0 = data[offset];
|
|
798
|
+
const b1 = data[offset + 1];
|
|
799
|
+
const b2 = data[offset + 2];
|
|
800
|
+
const b3 = data[offset + 3];
|
|
801
|
+
const b4 = data[offset + 4];
|
|
802
|
+
let vs = 1;
|
|
803
|
+
let op = null;
|
|
804
|
+
let val = null;
|
|
805
|
+
if (b0 <= 20) {
|
|
806
|
+
op = b0;
|
|
807
|
+
vs = 1;
|
|
808
|
+
}
|
|
809
|
+
if (b0 == 12) {
|
|
810
|
+
op = b0 * 100 + b1;
|
|
811
|
+
vs = 2;
|
|
812
|
+
}
|
|
813
|
+
if (b0 == 19 || b0 == 20) {
|
|
814
|
+
op = b0;
|
|
815
|
+
vs = 2;
|
|
816
|
+
}
|
|
817
|
+
if (21 <= b0 && b0 <= 27) {
|
|
818
|
+
op = b0;
|
|
819
|
+
vs = 1;
|
|
820
|
+
}
|
|
821
|
+
if (b0 == 28) {
|
|
822
|
+
val = bin.readShort(data, offset + 1);
|
|
823
|
+
vs = 3;
|
|
824
|
+
}
|
|
825
|
+
if (29 <= b0 && b0 <= 31) {
|
|
826
|
+
op = b0;
|
|
827
|
+
vs = 1;
|
|
828
|
+
}
|
|
829
|
+
if (32 <= b0 && b0 <= 246) {
|
|
830
|
+
val = b0 - 139;
|
|
831
|
+
vs = 1;
|
|
832
|
+
}
|
|
833
|
+
if (247 <= b0 && b0 <= 250) {
|
|
834
|
+
val = (b0 - 247) * 256 + b1 + 108;
|
|
835
|
+
vs = 2;
|
|
836
|
+
}
|
|
837
|
+
if (251 <= b0 && b0 <= 254) {
|
|
838
|
+
val = -(b0 - 251) * 256 - b1 - 108;
|
|
839
|
+
vs = 2;
|
|
840
|
+
}
|
|
841
|
+
if (b0 == 255) {
|
|
842
|
+
val = bin.readInt(data, offset + 1) / 65535;
|
|
843
|
+
vs = 5;
|
|
844
|
+
}
|
|
845
|
+
arr.push(val != null ? val : "o" + op);
|
|
846
|
+
offset += vs;
|
|
847
|
+
}
|
|
848
|
+
return arr;
|
|
849
|
+
},
|
|
850
|
+
readDict: function(data, offset, end) {
|
|
851
|
+
const bin = Typr2.B;
|
|
852
|
+
const dict = {};
|
|
853
|
+
const carr = [];
|
|
854
|
+
while (offset < end) {
|
|
855
|
+
const b0 = data[offset];
|
|
856
|
+
const b1 = data[offset + 1];
|
|
857
|
+
const b2 = data[offset + 2];
|
|
858
|
+
const b3 = data[offset + 3];
|
|
859
|
+
const b4 = data[offset + 4];
|
|
860
|
+
let vs = 1;
|
|
861
|
+
let key = null;
|
|
862
|
+
let val = null;
|
|
863
|
+
if (b0 == 28) {
|
|
864
|
+
val = bin.readShort(data, offset + 1);
|
|
865
|
+
vs = 3;
|
|
866
|
+
}
|
|
867
|
+
if (b0 == 29) {
|
|
868
|
+
val = bin.readInt(data, offset + 1);
|
|
869
|
+
vs = 5;
|
|
870
|
+
}
|
|
871
|
+
if (32 <= b0 && b0 <= 246) {
|
|
872
|
+
val = b0 - 139;
|
|
873
|
+
vs = 1;
|
|
874
|
+
}
|
|
875
|
+
if (247 <= b0 && b0 <= 250) {
|
|
876
|
+
val = (b0 - 247) * 256 + b1 + 108;
|
|
877
|
+
vs = 2;
|
|
878
|
+
}
|
|
879
|
+
if (251 <= b0 && b0 <= 254) {
|
|
880
|
+
val = -(b0 - 251) * 256 - b1 - 108;
|
|
881
|
+
vs = 2;
|
|
882
|
+
}
|
|
883
|
+
if (b0 == 255) {
|
|
884
|
+
val = bin.readInt(data, offset + 1) / 65535;
|
|
885
|
+
vs = 5;
|
|
886
|
+
throw new Error("Unknown number");
|
|
887
|
+
}
|
|
888
|
+
if (b0 == 30) {
|
|
889
|
+
const nibs = [];
|
|
890
|
+
vs = 1;
|
|
891
|
+
while (true) {
|
|
892
|
+
const b = data[offset + vs];
|
|
893
|
+
vs++;
|
|
894
|
+
const nib0 = b >> 4;
|
|
895
|
+
const nib1 = b & 15;
|
|
896
|
+
if (nib0 != 15) nibs.push(nib0);
|
|
897
|
+
if (nib1 != 15) nibs.push(nib1);
|
|
898
|
+
if (nib1 == 15) break;
|
|
899
|
+
}
|
|
900
|
+
let s = "";
|
|
901
|
+
const chars = [
|
|
902
|
+
0,
|
|
903
|
+
1,
|
|
904
|
+
2,
|
|
905
|
+
3,
|
|
906
|
+
4,
|
|
907
|
+
5,
|
|
908
|
+
6,
|
|
909
|
+
7,
|
|
910
|
+
8,
|
|
911
|
+
9,
|
|
912
|
+
".",
|
|
913
|
+
"e",
|
|
914
|
+
"e-",
|
|
915
|
+
"reserved",
|
|
916
|
+
"-",
|
|
917
|
+
"endOfNumber"
|
|
918
|
+
];
|
|
919
|
+
for (let i = 0; i < nibs.length; i++) s += chars[nibs[i]];
|
|
920
|
+
val = parseFloat(s);
|
|
921
|
+
}
|
|
922
|
+
if (b0 <= 21) {
|
|
923
|
+
const keys = [
|
|
924
|
+
"version",
|
|
925
|
+
"Notice",
|
|
926
|
+
"FullName",
|
|
927
|
+
"FamilyName",
|
|
928
|
+
"Weight",
|
|
929
|
+
"FontBBox",
|
|
930
|
+
"BlueValues",
|
|
931
|
+
"OtherBlues",
|
|
932
|
+
"FamilyBlues",
|
|
933
|
+
"FamilyOtherBlues",
|
|
934
|
+
"StdHW",
|
|
935
|
+
"StdVW",
|
|
936
|
+
"escape",
|
|
937
|
+
"UniqueID",
|
|
938
|
+
"XUID",
|
|
939
|
+
"charset",
|
|
940
|
+
"Encoding",
|
|
941
|
+
"CharStrings",
|
|
942
|
+
"Private",
|
|
943
|
+
"Subrs",
|
|
944
|
+
"defaultWidthX",
|
|
945
|
+
"nominalWidthX"
|
|
946
|
+
];
|
|
947
|
+
key = keys[b0];
|
|
948
|
+
vs = 1;
|
|
949
|
+
if (b0 == 12) {
|
|
950
|
+
const keys2 = [
|
|
951
|
+
"Copyright",
|
|
952
|
+
"isFixedPitch",
|
|
953
|
+
"ItalicAngle",
|
|
954
|
+
"UnderlinePosition",
|
|
955
|
+
"UnderlineThickness",
|
|
956
|
+
"PaintType",
|
|
957
|
+
"CharstringType",
|
|
958
|
+
"FontMatrix",
|
|
959
|
+
"StrokeWidth",
|
|
960
|
+
"BlueScale",
|
|
961
|
+
"BlueShift",
|
|
962
|
+
"BlueFuzz",
|
|
963
|
+
"StemSnapH",
|
|
964
|
+
"StemSnapV",
|
|
965
|
+
"ForceBold",
|
|
966
|
+
"",
|
|
967
|
+
"",
|
|
968
|
+
"LanguageGroup",
|
|
969
|
+
"ExpansionFactor",
|
|
970
|
+
"initialRandomSeed",
|
|
971
|
+
"SyntheticBase",
|
|
972
|
+
"PostScript",
|
|
973
|
+
"BaseFontName",
|
|
974
|
+
"BaseFontBlend",
|
|
975
|
+
"",
|
|
976
|
+
"",
|
|
977
|
+
"",
|
|
978
|
+
"",
|
|
979
|
+
"",
|
|
980
|
+
"",
|
|
981
|
+
"ROS",
|
|
982
|
+
"CIDFontVersion",
|
|
983
|
+
"CIDFontRevision",
|
|
984
|
+
"CIDFontType",
|
|
985
|
+
"CIDCount",
|
|
986
|
+
"UIDBase",
|
|
987
|
+
"FDArray",
|
|
988
|
+
"FDSelect",
|
|
989
|
+
"FontName"
|
|
990
|
+
];
|
|
991
|
+
key = keys2[b1];
|
|
992
|
+
vs = 2;
|
|
993
|
+
}
|
|
994
|
+
}
|
|
995
|
+
if (key != null) {
|
|
996
|
+
dict[key] = carr.length == 1 ? carr[0] : carr;
|
|
997
|
+
carr.length = 0;
|
|
998
|
+
} else carr.push(val);
|
|
999
|
+
offset += vs;
|
|
1000
|
+
}
|
|
1001
|
+
return dict;
|
|
1002
|
+
}
|
|
1003
|
+
};
|
|
1004
|
+
T2.cmap = {
|
|
1005
|
+
parseTab: function(data, offset, length) {
|
|
1006
|
+
const obj = { tables: [], ids: {}, off: offset };
|
|
1007
|
+
data = new Uint8Array(data.buffer, offset, length);
|
|
1008
|
+
offset = 0;
|
|
1009
|
+
const offset0 = offset;
|
|
1010
|
+
const bin = Typr2.B;
|
|
1011
|
+
const rU = bin.readUshort;
|
|
1012
|
+
const cmap2 = Typr2.T.cmap;
|
|
1013
|
+
const version = rU(data, offset);
|
|
1014
|
+
offset += 2;
|
|
1015
|
+
const numTables = rU(data, offset);
|
|
1016
|
+
offset += 2;
|
|
1017
|
+
const offs = [];
|
|
1018
|
+
for (let i = 0; i < numTables; i++) {
|
|
1019
|
+
const platformID = rU(data, offset);
|
|
1020
|
+
offset += 2;
|
|
1021
|
+
const encodingID = rU(data, offset);
|
|
1022
|
+
offset += 2;
|
|
1023
|
+
const noffset = bin.readUint(data, offset);
|
|
1024
|
+
offset += 4;
|
|
1025
|
+
const id = "p" + platformID + "e" + encodingID;
|
|
1026
|
+
const tind = offs.indexOf(noffset);
|
|
1027
|
+
if (tind == -1) {
|
|
1028
|
+
const tind2 = obj.tables.length;
|
|
1029
|
+
const subt = { format: 0 };
|
|
1030
|
+
offs.push(noffset);
|
|
1031
|
+
const format = subt.format = rU(data, noffset);
|
|
1032
|
+
if (format == 0)
|
|
1033
|
+
Object.assign(subt, cmap2.parse0(data, noffset, subt));
|
|
1034
|
+
else if (format == 4)
|
|
1035
|
+
Object.assign(subt, cmap2.parse4(data, noffset, subt));
|
|
1036
|
+
else if (format == 6)
|
|
1037
|
+
Object.assign(subt, cmap2.parse6(data, noffset, subt));
|
|
1038
|
+
else if (format == 12)
|
|
1039
|
+
Object.assign(subt, cmap2.parse12(data, noffset, subt));
|
|
1040
|
+
obj.tables.push(subt);
|
|
1041
|
+
}
|
|
1042
|
+
if (obj.ids[id] != null)
|
|
1043
|
+
console.log("multiple tables for one platform+encoding: " + id);
|
|
1044
|
+
obj.ids[id] = tind;
|
|
1045
|
+
}
|
|
1046
|
+
return obj;
|
|
1047
|
+
},
|
|
1048
|
+
parse0: function(data, offset, obj) {
|
|
1049
|
+
const bin = Typr2.B;
|
|
1050
|
+
offset += 2;
|
|
1051
|
+
const len = bin.readUshort(data, offset);
|
|
1052
|
+
offset += 2;
|
|
1053
|
+
const lang = bin.readUshort(data, offset);
|
|
1054
|
+
offset += 2;
|
|
1055
|
+
obj.map = [];
|
|
1056
|
+
for (let i = 0; i < len - 6; i++) obj.map.push(data[offset + i]);
|
|
1057
|
+
return obj;
|
|
1058
|
+
},
|
|
1059
|
+
parse4: function(data, offset, obj) {
|
|
1060
|
+
const bin = Typr2.B;
|
|
1061
|
+
const rU = bin.readUshort;
|
|
1062
|
+
const rUs = bin.readUshorts;
|
|
1063
|
+
const offset0 = offset;
|
|
1064
|
+
offset += 2;
|
|
1065
|
+
const length = rU(data, offset);
|
|
1066
|
+
offset += 2;
|
|
1067
|
+
const language = rU(data, offset);
|
|
1068
|
+
offset += 2;
|
|
1069
|
+
const segCountX2 = rU(data, offset);
|
|
1070
|
+
offset += 2;
|
|
1071
|
+
const segCount = segCountX2 >>> 1;
|
|
1072
|
+
obj.searchRange = rU(data, offset);
|
|
1073
|
+
offset += 2;
|
|
1074
|
+
obj.entrySelector = rU(data, offset);
|
|
1075
|
+
offset += 2;
|
|
1076
|
+
obj.rangeShift = rU(data, offset);
|
|
1077
|
+
offset += 2;
|
|
1078
|
+
obj.endCount = rUs(data, offset, segCount);
|
|
1079
|
+
offset += segCount * 2;
|
|
1080
|
+
offset += 2;
|
|
1081
|
+
obj.startCount = rUs(data, offset, segCount);
|
|
1082
|
+
offset += segCount * 2;
|
|
1083
|
+
obj.idDelta = [];
|
|
1084
|
+
for (let i = 0; i < segCount; i++) {
|
|
1085
|
+
obj.idDelta.push(bin.readShort(data, offset));
|
|
1086
|
+
offset += 2;
|
|
1087
|
+
}
|
|
1088
|
+
obj.idRangeOffset = rUs(data, offset, segCount);
|
|
1089
|
+
offset += segCount * 2;
|
|
1090
|
+
obj.glyphIdArray = rUs(data, offset, offset0 + length - offset >> 1);
|
|
1091
|
+
return obj;
|
|
1092
|
+
},
|
|
1093
|
+
parse6: function(data, offset, obj) {
|
|
1094
|
+
const bin = Typr2.B;
|
|
1095
|
+
const offset0 = offset;
|
|
1096
|
+
offset += 2;
|
|
1097
|
+
const length = bin.readUshort(data, offset);
|
|
1098
|
+
offset += 2;
|
|
1099
|
+
const language = bin.readUshort(data, offset);
|
|
1100
|
+
offset += 2;
|
|
1101
|
+
obj.firstCode = bin.readUshort(data, offset);
|
|
1102
|
+
offset += 2;
|
|
1103
|
+
const entryCount = bin.readUshort(data, offset);
|
|
1104
|
+
offset += 2;
|
|
1105
|
+
obj.glyphIdArray = [];
|
|
1106
|
+
for (let i = 0; i < entryCount; i++) {
|
|
1107
|
+
obj.glyphIdArray.push(bin.readUshort(data, offset));
|
|
1108
|
+
offset += 2;
|
|
1109
|
+
}
|
|
1110
|
+
return obj;
|
|
1111
|
+
},
|
|
1112
|
+
parse12: function(data, offset, obj) {
|
|
1113
|
+
const bin = Typr2.B;
|
|
1114
|
+
const rU = bin.readUint;
|
|
1115
|
+
const offset0 = offset;
|
|
1116
|
+
offset += 4;
|
|
1117
|
+
const length = rU(data, offset);
|
|
1118
|
+
offset += 4;
|
|
1119
|
+
const lang = rU(data, offset);
|
|
1120
|
+
offset += 4;
|
|
1121
|
+
const nGroups = rU(data, offset) * 3;
|
|
1122
|
+
offset += 4;
|
|
1123
|
+
const gps = obj.groups = new Uint32Array(nGroups);
|
|
1124
|
+
for (let i = 0; i < nGroups; i += 3) {
|
|
1125
|
+
gps[i] = rU(data, offset + (i << 2));
|
|
1126
|
+
gps[i + 1] = rU(data, offset + (i << 2) + 4);
|
|
1127
|
+
gps[i + 2] = rU(data, offset + (i << 2) + 8);
|
|
1128
|
+
}
|
|
1129
|
+
return obj;
|
|
1130
|
+
}
|
|
1131
|
+
};
|
|
1132
|
+
T2.head = {
|
|
1133
|
+
parseTab: function(data, offset, length) {
|
|
1134
|
+
const bin = Typr2.B;
|
|
1135
|
+
const obj = {};
|
|
1136
|
+
const tableVersion = bin.readFixed(data, offset);
|
|
1137
|
+
offset += 4;
|
|
1138
|
+
obj.fontRevision = bin.readFixed(data, offset);
|
|
1139
|
+
offset += 4;
|
|
1140
|
+
const checkSumAdjustment = bin.readUint(data, offset);
|
|
1141
|
+
offset += 4;
|
|
1142
|
+
const magicNumber = bin.readUint(data, offset);
|
|
1143
|
+
offset += 4;
|
|
1144
|
+
obj.flags = bin.readUshort(data, offset);
|
|
1145
|
+
offset += 2;
|
|
1146
|
+
obj.unitsPerEm = bin.readUshort(data, offset);
|
|
1147
|
+
offset += 2;
|
|
1148
|
+
obj.created = bin.readUint64(data, offset);
|
|
1149
|
+
offset += 8;
|
|
1150
|
+
obj.modified = bin.readUint64(data, offset);
|
|
1151
|
+
offset += 8;
|
|
1152
|
+
obj.xMin = bin.readShort(data, offset);
|
|
1153
|
+
offset += 2;
|
|
1154
|
+
obj.yMin = bin.readShort(data, offset);
|
|
1155
|
+
offset += 2;
|
|
1156
|
+
obj.xMax = bin.readShort(data, offset);
|
|
1157
|
+
offset += 2;
|
|
1158
|
+
obj.yMax = bin.readShort(data, offset);
|
|
1159
|
+
offset += 2;
|
|
1160
|
+
obj.macStyle = bin.readUshort(data, offset);
|
|
1161
|
+
offset += 2;
|
|
1162
|
+
obj.lowestRecPPEM = bin.readUshort(data, offset);
|
|
1163
|
+
offset += 2;
|
|
1164
|
+
obj.fontDirectionHint = bin.readShort(data, offset);
|
|
1165
|
+
offset += 2;
|
|
1166
|
+
obj.indexToLocFormat = bin.readShort(data, offset);
|
|
1167
|
+
offset += 2;
|
|
1168
|
+
obj.glyphDataFormat = bin.readShort(data, offset);
|
|
1169
|
+
offset += 2;
|
|
1170
|
+
return obj;
|
|
1171
|
+
}
|
|
1172
|
+
};
|
|
1173
|
+
T2.hhea = {
|
|
1174
|
+
parseTab: function(data, offset, length) {
|
|
1175
|
+
const bin = Typr2.B;
|
|
1176
|
+
const obj = {};
|
|
1177
|
+
const tableVersion = bin.readFixed(data, offset);
|
|
1178
|
+
offset += 4;
|
|
1179
|
+
const keys = [
|
|
1180
|
+
"ascender",
|
|
1181
|
+
"descender",
|
|
1182
|
+
"lineGap",
|
|
1183
|
+
"advanceWidthMax",
|
|
1184
|
+
"minLeftSideBearing",
|
|
1185
|
+
"minRightSideBearing",
|
|
1186
|
+
"xMaxExtent",
|
|
1187
|
+
"caretSlopeRise",
|
|
1188
|
+
"caretSlopeRun",
|
|
1189
|
+
"caretOffset",
|
|
1190
|
+
"res0",
|
|
1191
|
+
"res1",
|
|
1192
|
+
"res2",
|
|
1193
|
+
"res3",
|
|
1194
|
+
"metricDataFormat",
|
|
1195
|
+
"numberOfHMetrics"
|
|
1196
|
+
];
|
|
1197
|
+
for (let i = 0; i < keys.length; i++) {
|
|
1198
|
+
const key = keys[i];
|
|
1199
|
+
const func = key == "advanceWidthMax" || key == "numberOfHMetrics" ? bin.readUshort : bin.readShort;
|
|
1200
|
+
obj[key] = func(data, offset + i * 2);
|
|
1201
|
+
}
|
|
1202
|
+
return obj;
|
|
1203
|
+
}
|
|
1204
|
+
};
|
|
1205
|
+
T2.maxp = {
|
|
1206
|
+
parseTab: function(data, offset, length) {
|
|
1207
|
+
const bin = Typr2.B;
|
|
1208
|
+
const obj = {};
|
|
1209
|
+
const ver = bin.readUint(data, offset);
|
|
1210
|
+
offset += 4;
|
|
1211
|
+
obj.numGlyphs = bin.readUshort(data, offset);
|
|
1212
|
+
offset += 2;
|
|
1213
|
+
return obj;
|
|
1214
|
+
}
|
|
1215
|
+
};
|
|
1216
|
+
T2.hmtx = {
|
|
1217
|
+
parseTab: function(data, offset, length, font) {
|
|
1218
|
+
const bin = Typr2.B;
|
|
1219
|
+
const aWidth = [];
|
|
1220
|
+
const lsBearing = [];
|
|
1221
|
+
const nG = font["maxp"]?.["numGlyphs"] || 0;
|
|
1222
|
+
const nH = font["hhea"]?.["numberOfHMetrics"] || 0;
|
|
1223
|
+
let aw = 0, lsb = 0, i = 0;
|
|
1224
|
+
while (i < nH) {
|
|
1225
|
+
aw = bin.readUshort(data, offset + (i << 2));
|
|
1226
|
+
lsb = bin.readShort(data, offset + (i << 2) + 2);
|
|
1227
|
+
aWidth.push(aw);
|
|
1228
|
+
lsBearing.push(lsb);
|
|
1229
|
+
i++;
|
|
1230
|
+
}
|
|
1231
|
+
while (i < nG) {
|
|
1232
|
+
aWidth.push(aw);
|
|
1233
|
+
lsBearing.push(lsb);
|
|
1234
|
+
i++;
|
|
1235
|
+
}
|
|
1236
|
+
return { aWidth, lsBearing };
|
|
1237
|
+
}
|
|
1238
|
+
};
|
|
1239
|
+
T2.loca = {
|
|
1240
|
+
parseTab: function(data, offset, length, font) {
|
|
1241
|
+
const bin = Typr2.B;
|
|
1242
|
+
const obj = [];
|
|
1243
|
+
const ver = font["head"]?.["indexToLocFormat"] || 0;
|
|
1244
|
+
const len = (font["maxp"]?.["numGlyphs"] || 0) + 1;
|
|
1245
|
+
if (ver == 0)
|
|
1246
|
+
for (let i = 0; i < len; i++)
|
|
1247
|
+
obj.push(bin.readUshort(data, offset + (i << 1)) << 1);
|
|
1248
|
+
if (ver == 1)
|
|
1249
|
+
for (let i = 0; i < len; i++)
|
|
1250
|
+
obj.push(bin.readUint(data, offset + (i << 2)));
|
|
1251
|
+
return obj;
|
|
1252
|
+
}
|
|
1253
|
+
};
|
|
1254
|
+
T2.glyf = {
|
|
1255
|
+
parseTab: function(data, offset, length, font) {
|
|
1256
|
+
const obj = [];
|
|
1257
|
+
const ng = font["maxp"]?.["numGlyphs"] || 0;
|
|
1258
|
+
for (let g = 0; g < ng; g++) obj.push(null);
|
|
1259
|
+
return obj;
|
|
1260
|
+
},
|
|
1261
|
+
_parseGlyf: function(font, g) {
|
|
1262
|
+
const bin = Typr2.B;
|
|
1263
|
+
const data = font["_data"];
|
|
1264
|
+
const loca2 = font["loca"];
|
|
1265
|
+
if (!loca2) return null;
|
|
1266
|
+
if (loca2[g] == loca2[g + 1]) return null;
|
|
1267
|
+
const tableInfo = Typr2.findTable(data, "glyf", font["_offset"]);
|
|
1268
|
+
if (!tableInfo) return null;
|
|
1269
|
+
const offset = tableInfo[0] + loca2[g];
|
|
1270
|
+
const gl = {};
|
|
1271
|
+
gl.noc = bin.readShort(data, offset);
|
|
1272
|
+
let currentOffset = offset + 2;
|
|
1273
|
+
gl.xMin = bin.readShort(data, currentOffset);
|
|
1274
|
+
currentOffset += 2;
|
|
1275
|
+
gl.yMin = bin.readShort(data, currentOffset);
|
|
1276
|
+
currentOffset += 2;
|
|
1277
|
+
gl.xMax = bin.readShort(data, currentOffset);
|
|
1278
|
+
currentOffset += 2;
|
|
1279
|
+
gl.yMax = bin.readShort(data, currentOffset);
|
|
1280
|
+
currentOffset += 2;
|
|
1281
|
+
if (gl.xMin >= gl.xMax || gl.yMin >= gl.yMax) return null;
|
|
1282
|
+
if (gl.noc > 0) {
|
|
1283
|
+
gl.endPts = [];
|
|
1284
|
+
for (let i = 0; i < gl.noc; i++) {
|
|
1285
|
+
gl.endPts.push(bin.readUshort(data, currentOffset));
|
|
1286
|
+
currentOffset += 2;
|
|
1287
|
+
}
|
|
1288
|
+
const instructionLength = bin.readUshort(data, currentOffset);
|
|
1289
|
+
currentOffset += 2;
|
|
1290
|
+
if (data.length - currentOffset < instructionLength) return null;
|
|
1291
|
+
gl.instructions = bin.readBytes(
|
|
1292
|
+
data,
|
|
1293
|
+
currentOffset,
|
|
1294
|
+
instructionLength
|
|
1295
|
+
);
|
|
1296
|
+
currentOffset += instructionLength;
|
|
1297
|
+
const crdnum = gl.endPts[gl.noc - 1] + 1;
|
|
1298
|
+
gl.flags = [];
|
|
1299
|
+
for (let i = 0; i < crdnum; i++) {
|
|
1300
|
+
const flag = data[currentOffset];
|
|
1301
|
+
currentOffset++;
|
|
1302
|
+
gl.flags.push(flag);
|
|
1303
|
+
if ((flag & 8) != 0) {
|
|
1304
|
+
const rep = data[currentOffset];
|
|
1305
|
+
currentOffset++;
|
|
1306
|
+
for (let j = 0; j < rep; j++) {
|
|
1307
|
+
gl.flags.push(flag);
|
|
1308
|
+
i++;
|
|
1309
|
+
}
|
|
1310
|
+
}
|
|
1311
|
+
}
|
|
1312
|
+
gl.xs = [];
|
|
1313
|
+
for (let i = 0; i < crdnum; i++) {
|
|
1314
|
+
const i8 = (gl.flags[i] & 2) != 0;
|
|
1315
|
+
const same = (gl.flags[i] & 16) != 0;
|
|
1316
|
+
if (i8) {
|
|
1317
|
+
gl.xs.push(same ? data[currentOffset] : -data[currentOffset]);
|
|
1318
|
+
currentOffset++;
|
|
1319
|
+
} else {
|
|
1320
|
+
if (same) gl.xs.push(0);
|
|
1321
|
+
else {
|
|
1322
|
+
gl.xs.push(bin.readShort(data, currentOffset));
|
|
1323
|
+
currentOffset += 2;
|
|
1324
|
+
}
|
|
1325
|
+
}
|
|
1326
|
+
}
|
|
1327
|
+
gl.ys = [];
|
|
1328
|
+
for (let i = 0; i < crdnum; i++) {
|
|
1329
|
+
const i8 = (gl.flags[i] & 4) != 0;
|
|
1330
|
+
const same = (gl.flags[i] & 32) != 0;
|
|
1331
|
+
if (i8) {
|
|
1332
|
+
gl.ys.push(same ? data[currentOffset] : -data[currentOffset]);
|
|
1333
|
+
currentOffset++;
|
|
1334
|
+
} else {
|
|
1335
|
+
if (same) gl.ys.push(0);
|
|
1336
|
+
else {
|
|
1337
|
+
gl.ys.push(bin.readShort(data, currentOffset));
|
|
1338
|
+
currentOffset += 2;
|
|
1339
|
+
}
|
|
1340
|
+
}
|
|
1341
|
+
}
|
|
1342
|
+
let x = 0;
|
|
1343
|
+
let y = 0;
|
|
1344
|
+
for (let i = 0; i < crdnum; i++) {
|
|
1345
|
+
x += gl.xs[i];
|
|
1346
|
+
y += gl.ys[i];
|
|
1347
|
+
gl.xs[i] = x;
|
|
1348
|
+
gl.ys[i] = y;
|
|
1349
|
+
}
|
|
1350
|
+
} else {
|
|
1351
|
+
const ARG_1_AND_2_ARE_WORDS = 1 << 0;
|
|
1352
|
+
const ARGS_ARE_XY_VALUES = 1 << 1;
|
|
1353
|
+
const ROUND_XY_TO_GRID = 1 << 2;
|
|
1354
|
+
const WE_HAVE_A_SCALE = 1 << 3;
|
|
1355
|
+
const RESERVED = 1 << 4;
|
|
1356
|
+
const MORE_COMPONENTS = 1 << 5;
|
|
1357
|
+
const WE_HAVE_AN_X_AND_Y_SCALE = 1 << 6;
|
|
1358
|
+
const WE_HAVE_A_TWO_BY_TWO = 1 << 7;
|
|
1359
|
+
const WE_HAVE_INSTRUCTIONS = 1 << 8;
|
|
1360
|
+
const USE_MY_METRICS = 1 << 9;
|
|
1361
|
+
const OVERLAP_COMPOUND = 1 << 10;
|
|
1362
|
+
const SCALED_COMPONENT_OFFSET = 1 << 11;
|
|
1363
|
+
const UNSCALED_COMPONENT_OFFSET = 1 << 12;
|
|
1364
|
+
gl.parts = [];
|
|
1365
|
+
let flags;
|
|
1366
|
+
do {
|
|
1367
|
+
flags = bin.readUshort(data, currentOffset);
|
|
1368
|
+
currentOffset += 2;
|
|
1369
|
+
const part = {
|
|
1370
|
+
m: { a: 1, b: 0, c: 0, d: 1, tx: 0, ty: 0 },
|
|
1371
|
+
p1: -1,
|
|
1372
|
+
p2: -1
|
|
1373
|
+
};
|
|
1374
|
+
gl.parts.push(part);
|
|
1375
|
+
part.glyphIndex = bin.readUshort(data, currentOffset);
|
|
1376
|
+
currentOffset += 2;
|
|
1377
|
+
let arg1, arg2;
|
|
1378
|
+
if (flags & ARG_1_AND_2_ARE_WORDS) {
|
|
1379
|
+
arg1 = bin.readShort(data, currentOffset);
|
|
1380
|
+
currentOffset += 2;
|
|
1381
|
+
arg2 = bin.readShort(data, currentOffset);
|
|
1382
|
+
currentOffset += 2;
|
|
1383
|
+
} else {
|
|
1384
|
+
arg1 = bin.readInt8(data, currentOffset);
|
|
1385
|
+
currentOffset++;
|
|
1386
|
+
arg2 = bin.readInt8(data, currentOffset);
|
|
1387
|
+
currentOffset++;
|
|
1388
|
+
}
|
|
1389
|
+
if (flags & ARGS_ARE_XY_VALUES) {
|
|
1390
|
+
part.m.tx = arg1;
|
|
1391
|
+
part.m.ty = arg2;
|
|
1392
|
+
} else {
|
|
1393
|
+
part.p1 = arg1;
|
|
1394
|
+
part.p2 = arg2;
|
|
1395
|
+
}
|
|
1396
|
+
if (flags & WE_HAVE_A_SCALE) {
|
|
1397
|
+
part.m.a = part.m.d = bin.readF2dot14(data, currentOffset);
|
|
1398
|
+
currentOffset += 2;
|
|
1399
|
+
} else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) {
|
|
1400
|
+
part.m.a = bin.readF2dot14(data, currentOffset);
|
|
1401
|
+
currentOffset += 2;
|
|
1402
|
+
part.m.d = bin.readF2dot14(data, currentOffset);
|
|
1403
|
+
currentOffset += 2;
|
|
1404
|
+
} else if (flags & WE_HAVE_A_TWO_BY_TWO) {
|
|
1405
|
+
part.m.a = bin.readF2dot14(data, currentOffset);
|
|
1406
|
+
currentOffset += 2;
|
|
1407
|
+
part.m.b = bin.readF2dot14(data, currentOffset);
|
|
1408
|
+
currentOffset += 2;
|
|
1409
|
+
part.m.c = bin.readF2dot14(data, currentOffset);
|
|
1410
|
+
currentOffset += 2;
|
|
1411
|
+
part.m.d = bin.readF2dot14(data, currentOffset);
|
|
1412
|
+
currentOffset += 2;
|
|
1413
|
+
}
|
|
1414
|
+
} while (flags & MORE_COMPONENTS);
|
|
1415
|
+
if (flags & WE_HAVE_INSTRUCTIONS) {
|
|
1416
|
+
const numInstr = bin.readUshort(data, currentOffset);
|
|
1417
|
+
currentOffset += 2;
|
|
1418
|
+
gl.instr = [];
|
|
1419
|
+
for (let i = 0; i < numInstr; i++) {
|
|
1420
|
+
gl.instr.push(data[currentOffset]);
|
|
1421
|
+
currentOffset++;
|
|
1422
|
+
}
|
|
1423
|
+
}
|
|
1424
|
+
}
|
|
1425
|
+
return gl;
|
|
1426
|
+
}
|
|
1427
|
+
};
|
|
1428
|
+
T2.name = {
|
|
1429
|
+
parseTab: function(data, offset, length) {
|
|
1430
|
+
const bin = Typr2.B;
|
|
1431
|
+
const obj = {};
|
|
1432
|
+
const format = bin.readUshort(data, offset);
|
|
1433
|
+
offset += 2;
|
|
1434
|
+
const count = bin.readUshort(data, offset);
|
|
1435
|
+
offset += 2;
|
|
1436
|
+
const stringOffset = bin.readUshort(data, offset);
|
|
1437
|
+
offset += 2;
|
|
1438
|
+
const ooo = offset - 6 + stringOffset;
|
|
1439
|
+
const names = [
|
|
1440
|
+
"copyright",
|
|
1441
|
+
"fontFamily",
|
|
1442
|
+
"fontSubfamily",
|
|
1443
|
+
"ID",
|
|
1444
|
+
"fullName",
|
|
1445
|
+
"version",
|
|
1446
|
+
"postScriptName",
|
|
1447
|
+
"trademark",
|
|
1448
|
+
"manufacturer",
|
|
1449
|
+
"designer",
|
|
1450
|
+
"description",
|
|
1451
|
+
"urlVendor",
|
|
1452
|
+
"urlDesigner",
|
|
1453
|
+
"licence",
|
|
1454
|
+
"licenceURL",
|
|
1455
|
+
"---",
|
|
1456
|
+
"typoFamilyName",
|
|
1457
|
+
"typoSubfamilyName",
|
|
1458
|
+
"compatibleFull",
|
|
1459
|
+
"sampleText",
|
|
1460
|
+
"postScriptCID",
|
|
1461
|
+
"wwsFamilyName",
|
|
1462
|
+
"wwsSubfamilyName",
|
|
1463
|
+
"lightPalette",
|
|
1464
|
+
"darkPalette"
|
|
1465
|
+
];
|
|
1466
|
+
const rU = bin.readUshort;
|
|
1467
|
+
for (let i = 0; i < count; i++) {
|
|
1468
|
+
const platformID = rU(data, offset);
|
|
1469
|
+
offset += 2;
|
|
1470
|
+
const encodingID = rU(data, offset);
|
|
1471
|
+
offset += 2;
|
|
1472
|
+
const languageID = rU(data, offset);
|
|
1473
|
+
offset += 2;
|
|
1474
|
+
const nameID = rU(data, offset);
|
|
1475
|
+
offset += 2;
|
|
1476
|
+
const slen = rU(data, offset);
|
|
1477
|
+
offset += 2;
|
|
1478
|
+
const noffset = rU(data, offset);
|
|
1479
|
+
offset += 2;
|
|
1480
|
+
const soff = ooo + noffset;
|
|
1481
|
+
let str;
|
|
1482
|
+
if (false) {
|
|
1483
|
+
} else if (platformID == 0)
|
|
1484
|
+
str = bin.readUnicode(data, soff, slen / 2);
|
|
1485
|
+
else if (platformID == 3 && encodingID == 0)
|
|
1486
|
+
str = bin.readUnicode(data, soff, slen / 2);
|
|
1487
|
+
else if (platformID == 1 && encodingID == 25)
|
|
1488
|
+
str = bin.readUnicode(data, soff, slen / 2);
|
|
1489
|
+
else if (encodingID == 0) str = bin.readASCII(data, soff, slen);
|
|
1490
|
+
else if (encodingID == 1) str = bin.readUnicode(data, soff, slen / 2);
|
|
1491
|
+
else if (encodingID == 3) str = bin.readUnicode(data, soff, slen / 2);
|
|
1492
|
+
else if (encodingID == 4) str = bin.readUnicode(data, soff, slen / 2);
|
|
1493
|
+
else if (encodingID == 5) str = bin.readUnicode(data, soff, slen / 2);
|
|
1494
|
+
else if (encodingID == 10)
|
|
1495
|
+
str = bin.readUnicode(data, soff, slen / 2);
|
|
1496
|
+
else if (platformID == 1) {
|
|
1497
|
+
str = bin.readASCII(data, soff, slen);
|
|
1498
|
+
console.log(
|
|
1499
|
+
"reading unknown MAC encoding " + encodingID + " as ASCII"
|
|
1500
|
+
);
|
|
1501
|
+
} else {
|
|
1502
|
+
console.log(
|
|
1503
|
+
"unknown encoding " + encodingID + ", platformID: " + platformID
|
|
1504
|
+
);
|
|
1505
|
+
str = bin.readASCII(data, soff, slen);
|
|
1506
|
+
}
|
|
1507
|
+
const tid = "p" + platformID + "," + languageID.toString(16);
|
|
1508
|
+
if (obj[tid] == null) obj[tid] = {};
|
|
1509
|
+
let name2 = names[nameID];
|
|
1510
|
+
if (name2 == null) name2 = "_" + nameID;
|
|
1511
|
+
obj[tid][name2] = str;
|
|
1512
|
+
obj[tid]["_lang"] = languageID;
|
|
1513
|
+
}
|
|
1514
|
+
const out = Typr2.T.name.selectOne(obj);
|
|
1515
|
+
const ff = "fontFamily";
|
|
1516
|
+
if (out[ff] == null) {
|
|
1517
|
+
for (const p in obj) if (obj[p][ff] != null) out[ff] = obj[p][ff];
|
|
1518
|
+
}
|
|
1519
|
+
return out;
|
|
1520
|
+
},
|
|
1521
|
+
selectOne: function(obj) {
|
|
1522
|
+
const psn = "postScriptName";
|
|
1523
|
+
for (const p in obj)
|
|
1524
|
+
if (obj[p][psn] != null && obj[p]["_lang"] == 1033) return obj[p];
|
|
1525
|
+
for (const p in obj)
|
|
1526
|
+
if (obj[p][psn] != null && obj[p]["_lang"] == 0) return obj[p];
|
|
1527
|
+
for (const p in obj)
|
|
1528
|
+
if (obj[p][psn] != null && obj[p]["_lang"] == 3084) return obj[p];
|
|
1529
|
+
for (const p in obj) if (obj[p][psn] != null) return obj[p];
|
|
1530
|
+
let out;
|
|
1531
|
+
for (const p in obj) {
|
|
1532
|
+
out = obj[p];
|
|
1533
|
+
break;
|
|
1534
|
+
}
|
|
1535
|
+
console.log("returning name table with languageID " + out._lang);
|
|
1536
|
+
if (out[psn] == null && out["ID"] != null) out[psn] = out["ID"];
|
|
1537
|
+
return out;
|
|
1538
|
+
}
|
|
1539
|
+
};
|
|
1540
|
+
T2.OS2 = {
|
|
1541
|
+
parseTab: function(data, offset, length) {
|
|
1542
|
+
const bin = Typr2.B;
|
|
1543
|
+
const ver = bin.readUshort(data, offset);
|
|
1544
|
+
offset += 2;
|
|
1545
|
+
const OS22 = Typr2.T.OS2;
|
|
1546
|
+
const obj = {};
|
|
1547
|
+
if (ver == 0) OS22.version0(data, offset, obj);
|
|
1548
|
+
else if (ver == 1) OS22.version1(data, offset, obj);
|
|
1549
|
+
else if (ver == 2 || ver == 3 || ver == 4)
|
|
1550
|
+
OS22.version2(data, offset, obj);
|
|
1551
|
+
else if (ver == 5) OS22.version5(data, offset, obj);
|
|
1552
|
+
else throw new Error("unknown OS/2 table version: " + ver);
|
|
1553
|
+
return obj;
|
|
1554
|
+
},
|
|
1555
|
+
version0: function(data, offset, obj) {
|
|
1556
|
+
const bin = Typr2.B;
|
|
1557
|
+
obj["xAvgCharWidth"] = bin.readShort(data, offset);
|
|
1558
|
+
offset += 2;
|
|
1559
|
+
obj["usWeightClass"] = bin.readUshort(data, offset);
|
|
1560
|
+
offset += 2;
|
|
1561
|
+
obj["usWidthClass"] = bin.readUshort(data, offset);
|
|
1562
|
+
offset += 2;
|
|
1563
|
+
obj["fsType"] = bin.readUshort(data, offset);
|
|
1564
|
+
offset += 2;
|
|
1565
|
+
obj["ySubscriptXSize"] = bin.readShort(data, offset);
|
|
1566
|
+
offset += 2;
|
|
1567
|
+
obj["ySubscriptYSize"] = bin.readShort(data, offset);
|
|
1568
|
+
offset += 2;
|
|
1569
|
+
obj["ySubscriptXOffset"] = bin.readShort(data, offset);
|
|
1570
|
+
offset += 2;
|
|
1571
|
+
obj["ySubscriptYOffset"] = bin.readShort(data, offset);
|
|
1572
|
+
offset += 2;
|
|
1573
|
+
obj["ySuperscriptXSize"] = bin.readShort(data, offset);
|
|
1574
|
+
offset += 2;
|
|
1575
|
+
obj["ySuperscriptYSize"] = bin.readShort(data, offset);
|
|
1576
|
+
offset += 2;
|
|
1577
|
+
obj["ySuperscriptXOffset"] = bin.readShort(data, offset);
|
|
1578
|
+
offset += 2;
|
|
1579
|
+
obj["ySuperscriptYOffset"] = bin.readShort(data, offset);
|
|
1580
|
+
offset += 2;
|
|
1581
|
+
obj["yStrikeoutSize"] = bin.readShort(data, offset);
|
|
1582
|
+
offset += 2;
|
|
1583
|
+
obj["yStrikeoutPosition"] = bin.readShort(data, offset);
|
|
1584
|
+
offset += 2;
|
|
1585
|
+
obj["sFamilyClass"] = bin.readShort(data, offset);
|
|
1586
|
+
offset += 2;
|
|
1587
|
+
obj["panose"] = bin.readBytes(data, offset, 10);
|
|
1588
|
+
offset += 10;
|
|
1589
|
+
obj["ulUnicodeRange1"] = bin.readUint(data, offset);
|
|
1590
|
+
offset += 4;
|
|
1591
|
+
obj["ulUnicodeRange2"] = bin.readUint(data, offset);
|
|
1592
|
+
offset += 4;
|
|
1593
|
+
obj["ulUnicodeRange3"] = bin.readUint(data, offset);
|
|
1594
|
+
offset += 4;
|
|
1595
|
+
obj["ulUnicodeRange4"] = bin.readUint(data, offset);
|
|
1596
|
+
offset += 4;
|
|
1597
|
+
obj["achVendID"] = bin.readASCII(data, offset, 4);
|
|
1598
|
+
offset += 4;
|
|
1599
|
+
obj["fsSelection"] = bin.readUshort(data, offset);
|
|
1600
|
+
offset += 2;
|
|
1601
|
+
obj["usFirstCharIndex"] = bin.readUshort(data, offset);
|
|
1602
|
+
offset += 2;
|
|
1603
|
+
obj["usLastCharIndex"] = bin.readUshort(data, offset);
|
|
1604
|
+
offset += 2;
|
|
1605
|
+
obj["sTypoAscender"] = bin.readShort(data, offset);
|
|
1606
|
+
offset += 2;
|
|
1607
|
+
obj["sTypoDescender"] = bin.readShort(data, offset);
|
|
1608
|
+
offset += 2;
|
|
1609
|
+
obj["sTypoLineGap"] = bin.readShort(data, offset);
|
|
1610
|
+
offset += 2;
|
|
1611
|
+
obj["usWinAscent"] = bin.readUshort(data, offset);
|
|
1612
|
+
offset += 2;
|
|
1613
|
+
obj["usWinDescent"] = bin.readUshort(data, offset);
|
|
1614
|
+
offset += 2;
|
|
1615
|
+
return offset;
|
|
1616
|
+
},
|
|
1617
|
+
version1: function(data, offset, obj) {
|
|
1618
|
+
const bin = Typr2.B;
|
|
1619
|
+
offset = Typr2.T.OS2.version0(data, offset, obj);
|
|
1620
|
+
obj["ulCodePageRange1"] = bin.readUint(data, offset);
|
|
1621
|
+
offset += 4;
|
|
1622
|
+
obj["ulCodePageRange2"] = bin.readUint(data, offset);
|
|
1623
|
+
offset += 4;
|
|
1624
|
+
return offset;
|
|
1625
|
+
},
|
|
1626
|
+
version2: function(data, offset, obj) {
|
|
1627
|
+
const bin = Typr2.B;
|
|
1628
|
+
const rU = bin.readUshort;
|
|
1629
|
+
offset = Typr2.T.OS2.version1(data, offset, obj);
|
|
1630
|
+
obj["sxHeight"] = bin.readShort(data, offset);
|
|
1631
|
+
offset += 2;
|
|
1632
|
+
obj["sCapHeight"] = bin.readShort(data, offset);
|
|
1633
|
+
offset += 2;
|
|
1634
|
+
obj["usDefault"] = rU(data, offset);
|
|
1635
|
+
offset += 2;
|
|
1636
|
+
obj["usBreak"] = rU(data, offset);
|
|
1637
|
+
offset += 2;
|
|
1638
|
+
obj["usMaxContext"] = rU(data, offset);
|
|
1639
|
+
offset += 2;
|
|
1640
|
+
return offset;
|
|
1641
|
+
},
|
|
1642
|
+
version5: function(data, offset, obj) {
|
|
1643
|
+
const rU = Typr2.B.readUshort;
|
|
1644
|
+
offset = Typr2.T.OS2.version2(data, offset, obj);
|
|
1645
|
+
obj["usLowerOpticalPointSize"] = rU(data, offset);
|
|
1646
|
+
offset += 2;
|
|
1647
|
+
obj["usUpperOpticalPointSize"] = rU(data, offset);
|
|
1648
|
+
offset += 2;
|
|
1649
|
+
return offset;
|
|
1650
|
+
}
|
|
1651
|
+
};
|
|
1652
|
+
T2.post = {
|
|
1653
|
+
parseTab: function(data, offset, length) {
|
|
1654
|
+
const bin = Typr2.B;
|
|
1655
|
+
const obj = {};
|
|
1656
|
+
obj.version = bin.readFixed(data, offset);
|
|
1657
|
+
offset += 4;
|
|
1658
|
+
obj.italicAngle = bin.readFixed(data, offset);
|
|
1659
|
+
offset += 4;
|
|
1660
|
+
obj.underlinePosition = bin.readShort(data, offset);
|
|
1661
|
+
offset += 2;
|
|
1662
|
+
obj.underlineThickness = bin.readShort(data, offset);
|
|
1663
|
+
offset += 2;
|
|
1664
|
+
return obj;
|
|
1665
|
+
}
|
|
1666
|
+
};
|
|
1667
|
+
T2.kern = {
|
|
1668
|
+
parseTab: function(data, offset, length, font) {
|
|
1669
|
+
const bin = Typr2.B;
|
|
1670
|
+
const kern2 = Typr2.T.kern;
|
|
1671
|
+
const version = bin.readUshort(data, offset);
|
|
1672
|
+
if (version == 1) return kern2.parseV1(data, offset, length, font);
|
|
1673
|
+
const nTables = bin.readUshort(data, offset + 2);
|
|
1674
|
+
offset += 4;
|
|
1675
|
+
const map = { glyph1: [], rval: [] };
|
|
1676
|
+
for (let i = 0; i < nTables; i++) {
|
|
1677
|
+
offset += 2;
|
|
1678
|
+
const length2 = bin.readUshort(data, offset);
|
|
1679
|
+
offset += 2;
|
|
1680
|
+
const coverage = bin.readUshort(data, offset);
|
|
1681
|
+
offset += 2;
|
|
1682
|
+
let format = coverage >>> 8;
|
|
1683
|
+
format &= 15;
|
|
1684
|
+
if (format == 0) offset = kern2.readFormat0(data, offset, map);
|
|
1685
|
+
}
|
|
1686
|
+
return map;
|
|
1687
|
+
},
|
|
1688
|
+
parseV1: function(data, offset, length, font) {
|
|
1689
|
+
const bin = Typr2.B;
|
|
1690
|
+
const kern2 = Typr2.T.kern;
|
|
1691
|
+
const version = bin.readFixed(data, offset);
|
|
1692
|
+
const nTables = bin.readUint(data, offset + 4);
|
|
1693
|
+
offset += 8;
|
|
1694
|
+
const map = { glyph1: [], rval: [] };
|
|
1695
|
+
for (let i = 0; i < nTables; i++) {
|
|
1696
|
+
const length2 = bin.readUint(data, offset);
|
|
1697
|
+
offset += 4;
|
|
1698
|
+
const coverage = bin.readUshort(data, offset);
|
|
1699
|
+
offset += 2;
|
|
1700
|
+
const tupleIndex = bin.readUshort(data, offset);
|
|
1701
|
+
offset += 2;
|
|
1702
|
+
const format = coverage & 255;
|
|
1703
|
+
if (format == 0) offset = kern2.readFormat0(data, offset, map);
|
|
1704
|
+
}
|
|
1705
|
+
return map;
|
|
1706
|
+
},
|
|
1707
|
+
readFormat0: function(data, offset, map) {
|
|
1708
|
+
const bin = Typr2.B;
|
|
1709
|
+
const rUs = bin.readUshort;
|
|
1710
|
+
let pleft = -1;
|
|
1711
|
+
const nPairs = rUs(data, offset);
|
|
1712
|
+
const searchRange = rUs(data, offset + 2);
|
|
1713
|
+
const entrySelector = rUs(data, offset + 4);
|
|
1714
|
+
const rangeShift = rUs(data, offset + 6);
|
|
1715
|
+
offset += 8;
|
|
1716
|
+
for (let j = 0; j < nPairs; j++) {
|
|
1717
|
+
const left = rUs(data, offset);
|
|
1718
|
+
offset += 2;
|
|
1719
|
+
const right = rUs(data, offset);
|
|
1720
|
+
offset += 2;
|
|
1721
|
+
const value = bin.readShort(data, offset);
|
|
1722
|
+
offset += 2;
|
|
1723
|
+
if (left != pleft) {
|
|
1724
|
+
map.glyph1.push(left);
|
|
1725
|
+
map.rval.push({ glyph2: [], vals: [] });
|
|
1726
|
+
}
|
|
1727
|
+
const rval = map.rval[map.rval.length - 1];
|
|
1728
|
+
rval.glyph2.push(right);
|
|
1729
|
+
rval.vals.push(value);
|
|
1730
|
+
pleft = left;
|
|
1731
|
+
}
|
|
1732
|
+
return offset;
|
|
1733
|
+
}
|
|
1734
|
+
};
|
|
1735
|
+
T2.GSUB = {
|
|
1736
|
+
parseTab: function(data, offset, length, obj) {
|
|
1737
|
+
const bin = Typr2.B;
|
|
1738
|
+
const rU = bin.readUshort;
|
|
1739
|
+
let off = offset;
|
|
1740
|
+
const maj = rU(data, off);
|
|
1741
|
+
off += 2;
|
|
1742
|
+
const min = rU(data, off);
|
|
1743
|
+
off += 2;
|
|
1744
|
+
const slO = rU(data, off);
|
|
1745
|
+
off += 2;
|
|
1746
|
+
const flO = rU(data, off);
|
|
1747
|
+
off += 2;
|
|
1748
|
+
const llO = rU(data, off);
|
|
1749
|
+
off += 2;
|
|
1750
|
+
const name2 = obj.name || {};
|
|
1751
|
+
const flBase = offset + flO;
|
|
1752
|
+
let foff = flBase;
|
|
1753
|
+
const fcnt = rU(data, foff);
|
|
1754
|
+
foff += 2;
|
|
1755
|
+
const features = {};
|
|
1756
|
+
for (let i = 0; i < fcnt; i++) {
|
|
1757
|
+
const tag = bin.readASCII(data, foff, 4);
|
|
1758
|
+
foff += 4;
|
|
1759
|
+
const fo = rU(data, foff);
|
|
1760
|
+
foff += 2;
|
|
1761
|
+
const rOff = flBase + fo;
|
|
1762
|
+
const pOff = rU(data, rOff);
|
|
1763
|
+
const lcnt = rU(data, rOff + 2);
|
|
1764
|
+
const lookups = [];
|
|
1765
|
+
let lo = rOff + 4;
|
|
1766
|
+
for (let j = 0; j < lcnt; j++) {
|
|
1767
|
+
lookups.push(rU(data, lo));
|
|
1768
|
+
lo += 2;
|
|
1769
|
+
}
|
|
1770
|
+
const feat = { tag, lookups };
|
|
1771
|
+
if (pOff !== 0) {
|
|
1772
|
+
const po = rOff + pOff;
|
|
1773
|
+
if (/^ss\d\d$/i.test(tag)) {
|
|
1774
|
+
const ui = rU(data, po + 2);
|
|
1775
|
+
feat.uiName = name2["_" + ui];
|
|
1776
|
+
} else if (/^cv\d\d$/i.test(tag)) {
|
|
1777
|
+
const ui = rU(data, po + 2);
|
|
1778
|
+
const ti = rU(data, po + 4);
|
|
1779
|
+
const si = rU(data, po + 6);
|
|
1780
|
+
const pcnt = rU(data, po + 8);
|
|
1781
|
+
const first = rU(data, po + 10);
|
|
1782
|
+
const labels = [];
|
|
1783
|
+
for (let k = 0; k < pcnt; k++) {
|
|
1784
|
+
const str = name2["_" + (first + k)];
|
|
1785
|
+
if (str) labels.push(str);
|
|
1786
|
+
}
|
|
1787
|
+
feat.uiName = name2["_" + ui];
|
|
1788
|
+
feat.tooltip = name2["_" + ti];
|
|
1789
|
+
feat.sampleText = name2["_" + si];
|
|
1790
|
+
if (labels.length) feat.paramLabels = labels;
|
|
1791
|
+
}
|
|
1792
|
+
}
|
|
1793
|
+
features[tag] = feat;
|
|
1794
|
+
}
|
|
1795
|
+
return { features };
|
|
1796
|
+
}
|
|
1797
|
+
};
|
|
1798
|
+
T2.CBLC = {
|
|
1799
|
+
parseTab: function(data, offset, length) {
|
|
1800
|
+
const bin = Typr2.B;
|
|
1801
|
+
const ooff = offset;
|
|
1802
|
+
const maj = bin.readUshort(data, offset);
|
|
1803
|
+
offset += 2;
|
|
1804
|
+
const min = bin.readUshort(data, offset);
|
|
1805
|
+
offset += 2;
|
|
1806
|
+
const numSizes = bin.readUint(data, offset);
|
|
1807
|
+
offset += 4;
|
|
1808
|
+
const out = [];
|
|
1809
|
+
for (let i = 0; i < numSizes; i++) {
|
|
1810
|
+
const off = bin.readUint(data, offset);
|
|
1811
|
+
offset += 4;
|
|
1812
|
+
const siz = bin.readUint(data, offset);
|
|
1813
|
+
offset += 4;
|
|
1814
|
+
const num = bin.readUint(data, offset);
|
|
1815
|
+
offset += 4;
|
|
1816
|
+
offset += 4;
|
|
1817
|
+
offset += 2 * 12;
|
|
1818
|
+
const sGlyph = bin.readUshort(data, offset);
|
|
1819
|
+
offset += 2;
|
|
1820
|
+
const eGlyph = bin.readUshort(data, offset);
|
|
1821
|
+
offset += 2;
|
|
1822
|
+
offset += 4;
|
|
1823
|
+
let coff = ooff + off;
|
|
1824
|
+
for (let j = 0; j < 3; j++) {
|
|
1825
|
+
const fgI = bin.readUshort(data, coff);
|
|
1826
|
+
coff += 2;
|
|
1827
|
+
const lgI = bin.readUshort(data, coff);
|
|
1828
|
+
coff += 2;
|
|
1829
|
+
const nxt = bin.readUint(data, coff);
|
|
1830
|
+
coff += 4;
|
|
1831
|
+
const gcnt = lgI - fgI + 1;
|
|
1832
|
+
let ioff = ooff + off + nxt;
|
|
1833
|
+
const inF = bin.readUshort(data, ioff);
|
|
1834
|
+
ioff += 2;
|
|
1835
|
+
if (inF != 1) throw new Error(`Invalid format: ${inF}`);
|
|
1836
|
+
const imF = bin.readUshort(data, ioff);
|
|
1837
|
+
ioff += 2;
|
|
1838
|
+
const imgo = bin.readUint(data, ioff);
|
|
1839
|
+
ioff += 4;
|
|
1840
|
+
const oarr = [];
|
|
1841
|
+
for (let gi = 0; gi < gcnt; gi++) {
|
|
1842
|
+
const sbitO = bin.readUint(data, ioff + gi * 4);
|
|
1843
|
+
oarr.push(imgo + sbitO);
|
|
1844
|
+
}
|
|
1845
|
+
out.push([fgI, lgI, imF, oarr]);
|
|
1846
|
+
}
|
|
1847
|
+
}
|
|
1848
|
+
return out;
|
|
1849
|
+
}
|
|
1850
|
+
};
|
|
1851
|
+
T2.CBDT = {
|
|
1852
|
+
parseTab: function(data, offset, length) {
|
|
1853
|
+
return new Uint8Array(data.buffer, data.byteOffset + offset, length);
|
|
1854
|
+
}
|
|
1855
|
+
};
|
|
1856
|
+
T2.SVG = {
|
|
1857
|
+
parseTab: function(data, offset, length) {
|
|
1858
|
+
const bin = Typr2.B;
|
|
1859
|
+
const obj = { entries: [], svgs: [] };
|
|
1860
|
+
const offset0 = offset;
|
|
1861
|
+
const tableVersion = bin.readUshort(data, offset);
|
|
1862
|
+
offset += 2;
|
|
1863
|
+
const svgDocIndexOffset = bin.readUint(data, offset);
|
|
1864
|
+
offset += 4;
|
|
1865
|
+
const reserved = bin.readUint(data, offset);
|
|
1866
|
+
offset += 4;
|
|
1867
|
+
offset = svgDocIndexOffset + offset0;
|
|
1868
|
+
const numEntries = bin.readUshort(data, offset);
|
|
1869
|
+
offset += 2;
|
|
1870
|
+
for (let i = 0; i < numEntries; i++) {
|
|
1871
|
+
const startGlyphID = bin.readUshort(data, offset);
|
|
1872
|
+
offset += 2;
|
|
1873
|
+
const endGlyphID = bin.readUshort(data, offset);
|
|
1874
|
+
offset += 2;
|
|
1875
|
+
const svgDocOffset = bin.readUint(data, offset);
|
|
1876
|
+
offset += 4;
|
|
1877
|
+
const svgDocLength = bin.readUint(data, offset);
|
|
1878
|
+
offset += 4;
|
|
1879
|
+
const sbuf = new Uint8Array(
|
|
1880
|
+
data.buffer,
|
|
1881
|
+
offset0 + svgDocOffset + svgDocIndexOffset,
|
|
1882
|
+
svgDocLength
|
|
1883
|
+
);
|
|
1884
|
+
const svg = bin.readUTF8(sbuf, 0, sbuf.length);
|
|
1885
|
+
for (let f = startGlyphID; f <= endGlyphID; f++) {
|
|
1886
|
+
obj.entries[f] = obj.svgs.length;
|
|
1887
|
+
}
|
|
1888
|
+
obj.svgs.push(svg);
|
|
1889
|
+
}
|
|
1890
|
+
return obj;
|
|
1891
|
+
}
|
|
1892
|
+
};
|
|
1893
|
+
T2.colr = {
|
|
1894
|
+
parseTab: function(data, offset, length) {
|
|
1895
|
+
const bin = Typr2.B;
|
|
1896
|
+
const ooff = offset;
|
|
1897
|
+
offset += 2;
|
|
1898
|
+
const num = bin.readUshort(data, offset);
|
|
1899
|
+
offset += 2;
|
|
1900
|
+
const boff = bin.readUint(data, offset);
|
|
1901
|
+
offset += 4;
|
|
1902
|
+
const loff = bin.readUint(data, offset);
|
|
1903
|
+
offset += 4;
|
|
1904
|
+
const lnum = bin.readUshort(data, offset);
|
|
1905
|
+
offset += 2;
|
|
1906
|
+
const base = {};
|
|
1907
|
+
let coff = ooff + boff;
|
|
1908
|
+
for (let i = 0; i < num; i++) {
|
|
1909
|
+
base["g" + bin.readUshort(data, coff)] = [
|
|
1910
|
+
bin.readUshort(data, coff + 2),
|
|
1911
|
+
bin.readUshort(data, coff + 4)
|
|
1912
|
+
];
|
|
1913
|
+
coff += 6;
|
|
1914
|
+
}
|
|
1915
|
+
const lays = [];
|
|
1916
|
+
coff = ooff + loff;
|
|
1917
|
+
for (let i = 0; i < lnum; i++) {
|
|
1918
|
+
lays.push(bin.readUshort(data, coff), bin.readUshort(data, coff + 2));
|
|
1919
|
+
coff += 4;
|
|
1920
|
+
}
|
|
1921
|
+
return [base, lays];
|
|
1922
|
+
}
|
|
1923
|
+
};
|
|
1924
|
+
T2.cpal = {
|
|
1925
|
+
parseTab: function(data, offset, length) {
|
|
1926
|
+
const bin = Typr2.B;
|
|
1927
|
+
const ooff = offset;
|
|
1928
|
+
const vsn = bin.readUshort(data, offset);
|
|
1929
|
+
offset += 2;
|
|
1930
|
+
if (vsn == 0) {
|
|
1931
|
+
const ets = bin.readUshort(data, offset);
|
|
1932
|
+
offset += 2;
|
|
1933
|
+
const pts = bin.readUshort(data, offset);
|
|
1934
|
+
offset += 2;
|
|
1935
|
+
const tot = bin.readUshort(data, offset);
|
|
1936
|
+
offset += 2;
|
|
1937
|
+
const fst = bin.readUint(data, offset);
|
|
1938
|
+
offset += 4;
|
|
1939
|
+
return new Uint8Array(data.buffer, ooff + fst, tot * 4);
|
|
1940
|
+
} else throw new Error(`Unknown color palette version: ${vsn}`);
|
|
1941
|
+
}
|
|
1942
|
+
};
|
|
1943
|
+
T2.sbix = {
|
|
1944
|
+
parseTab: function(data, offset, length, obj) {
|
|
1945
|
+
const numGlyphs = obj["maxp"]["numGlyphs"];
|
|
1946
|
+
const ooff = offset;
|
|
1947
|
+
const bin = Typr2.B;
|
|
1948
|
+
const numStrikes = bin.readUint(data, offset + 4);
|
|
1949
|
+
const out = [];
|
|
1950
|
+
for (let si = numStrikes - 1; si < numStrikes; si++) {
|
|
1951
|
+
const off = ooff + bin.readUint(data, offset + 8 + si * 4);
|
|
1952
|
+
for (let gi = 0; gi < numGlyphs; gi++) {
|
|
1953
|
+
const aoff = bin.readUint(data, off + 4 + gi * 4);
|
|
1954
|
+
const noff = bin.readUint(data, off + 4 + gi * 4 + 4);
|
|
1955
|
+
if (aoff == noff) {
|
|
1956
|
+
out[gi] = null;
|
|
1957
|
+
continue;
|
|
1958
|
+
}
|
|
1959
|
+
const go = off + aoff;
|
|
1960
|
+
const tag = bin.readASCII(data, go + 4, 4);
|
|
1961
|
+
if (tag != "png ") throw new Error(`Invalid tag: ${tag}`);
|
|
1962
|
+
out[gi] = new Uint8Array(
|
|
1963
|
+
data.buffer,
|
|
1964
|
+
data.byteOffset + go + 8,
|
|
1965
|
+
noff - aoff - 8
|
|
1966
|
+
);
|
|
1967
|
+
}
|
|
1968
|
+
}
|
|
1969
|
+
return out;
|
|
1970
|
+
}
|
|
1971
|
+
};
|
|
1972
|
+
T2.fvar = {
|
|
1973
|
+
parseTab: function(data, offset, length, obj) {
|
|
1974
|
+
const name2 = obj["name"];
|
|
1975
|
+
let off = offset;
|
|
1976
|
+
const bin = Typr2.B;
|
|
1977
|
+
const axes = [];
|
|
1978
|
+
const inst = [];
|
|
1979
|
+
off += 8;
|
|
1980
|
+
const acnt = bin.readUshort(data, off);
|
|
1981
|
+
off += 2;
|
|
1982
|
+
off += 2;
|
|
1983
|
+
const icnt = bin.readUshort(data, off);
|
|
1984
|
+
off += 2;
|
|
1985
|
+
const isiz = bin.readUshort(data, off);
|
|
1986
|
+
off += 2;
|
|
1987
|
+
for (let i = 0; i < acnt; i++) {
|
|
1988
|
+
const tag = bin.readASCII(data, off, 4);
|
|
1989
|
+
const min = bin.readFixed(data, off + 4);
|
|
1990
|
+
const def = bin.readFixed(data, off + 8);
|
|
1991
|
+
const max = bin.readFixed(data, off + 12);
|
|
1992
|
+
const flg = bin.readUshort(data, off + 16);
|
|
1993
|
+
const nid = bin.readUshort(data, off + 18);
|
|
1994
|
+
axes.push([tag, min, def, max, flg, name2["_" + nid]]);
|
|
1995
|
+
off += 20;
|
|
1996
|
+
}
|
|
1997
|
+
for (let i = 0; i < icnt; i++) {
|
|
1998
|
+
const snid = bin.readUshort(data, off);
|
|
1999
|
+
let pnid = null;
|
|
2000
|
+
const flg = bin.readUshort(data, off + 2);
|
|
2001
|
+
const crd = [];
|
|
2002
|
+
for (let j = 0; j < acnt; j++)
|
|
2003
|
+
crd.push(bin.readFixed(data, off + 4 + j * 4));
|
|
2004
|
+
off += 4 + acnt * 4;
|
|
2005
|
+
if ((isiz & 3) == 2) {
|
|
2006
|
+
pnid = bin.readUshort(data, off);
|
|
2007
|
+
off += 2;
|
|
2008
|
+
}
|
|
2009
|
+
inst.push([name2["_" + snid], flg, crd, pnid]);
|
|
2010
|
+
}
|
|
2011
|
+
return [axes, inst];
|
|
2012
|
+
}
|
|
2013
|
+
};
|
|
2014
|
+
T2.gvar = {
|
|
2015
|
+
parseTab: function(data, offset, length, obj) {
|
|
2016
|
+
const EMBEDDED_PEAK_TUPLE = 32768;
|
|
2017
|
+
const INTERMEDIATE_REGION = 16384;
|
|
2018
|
+
const PRIVATE_POINT_NUMBERS = 8192;
|
|
2019
|
+
const DELTAS_ARE_ZERO = 128;
|
|
2020
|
+
const DELTAS_ARE_WORDS = 64;
|
|
2021
|
+
const POINTS_ARE_WORDS = 128;
|
|
2022
|
+
const SHARED_POINT_NUMBERS = 32768;
|
|
2023
|
+
const bin = Typr2.B;
|
|
2024
|
+
function readTuple(data2, o, acnt2) {
|
|
2025
|
+
const tup = [];
|
|
2026
|
+
for (let j = 0; j < acnt2; j++)
|
|
2027
|
+
tup.push(bin.readF2dot14(data2, o + j * 2));
|
|
2028
|
+
return tup;
|
|
2029
|
+
}
|
|
2030
|
+
function readTupleVarHeader(data2, off2, vcnt, acnt2, eoff) {
|
|
2031
|
+
const out = [];
|
|
2032
|
+
for (let j = 0; j < vcnt; j++) {
|
|
2033
|
+
const dsiz = bin.readUshort(data2, off2);
|
|
2034
|
+
off2 += 2;
|
|
2035
|
+
let tind = bin.readUshort(data2, off2);
|
|
2036
|
+
const flag = tind & 61440;
|
|
2037
|
+
tind = tind & 4095;
|
|
2038
|
+
off2 += 2;
|
|
2039
|
+
let peak = null;
|
|
2040
|
+
let start = null;
|
|
2041
|
+
let end = null;
|
|
2042
|
+
if (flag & EMBEDDED_PEAK_TUPLE) {
|
|
2043
|
+
peak = readTuple(data2, off2, acnt2);
|
|
2044
|
+
off2 += acnt2 * 2;
|
|
2045
|
+
}
|
|
2046
|
+
if (flag & INTERMEDIATE_REGION) {
|
|
2047
|
+
start = readTuple(data2, off2, acnt2);
|
|
2048
|
+
off2 += acnt2 * 2;
|
|
2049
|
+
}
|
|
2050
|
+
if (flag & INTERMEDIATE_REGION) {
|
|
2051
|
+
end = readTuple(data2, off2, acnt2);
|
|
2052
|
+
off2 += acnt2 * 2;
|
|
2053
|
+
}
|
|
2054
|
+
out.push([dsiz, tind, flag, start, peak, end]);
|
|
2055
|
+
}
|
|
2056
|
+
return out;
|
|
2057
|
+
}
|
|
2058
|
+
function readPointNumbers(data2, off2, gid) {
|
|
2059
|
+
let cnt = data2[off2];
|
|
2060
|
+
off2++;
|
|
2061
|
+
if (cnt == 0) return [[], off2];
|
|
2062
|
+
if (127 < cnt) {
|
|
2063
|
+
cnt = (cnt & 127) << 8 | data2[off2++];
|
|
2064
|
+
}
|
|
2065
|
+
const pts = [];
|
|
2066
|
+
let last = 0;
|
|
2067
|
+
while (pts.length < cnt) {
|
|
2068
|
+
const v = data2[off2++];
|
|
2069
|
+
const wds = (v & POINTS_ARE_WORDS) != 0;
|
|
2070
|
+
const vv = (v & 127) + 1;
|
|
2071
|
+
for (let i = 0; i < vv; i++) {
|
|
2072
|
+
let dif = 0;
|
|
2073
|
+
if (wds) {
|
|
2074
|
+
dif = bin.readUshort(data2, off2);
|
|
2075
|
+
off2 += 2;
|
|
2076
|
+
} else {
|
|
2077
|
+
dif = data2[off2];
|
|
2078
|
+
off2++;
|
|
2079
|
+
}
|
|
2080
|
+
last += dif;
|
|
2081
|
+
pts.push(last);
|
|
2082
|
+
}
|
|
2083
|
+
}
|
|
2084
|
+
return [pts, off2];
|
|
2085
|
+
}
|
|
2086
|
+
let off = offset + 4;
|
|
2087
|
+
const acnt = bin.readUshort(data, off);
|
|
2088
|
+
off += 2;
|
|
2089
|
+
const tcnt = bin.readUshort(data, off);
|
|
2090
|
+
off += 2;
|
|
2091
|
+
const toff = bin.readUint(data, off);
|
|
2092
|
+
off += 4;
|
|
2093
|
+
const gcnt = bin.readUshort(data, off);
|
|
2094
|
+
off += 2;
|
|
2095
|
+
const flgs = bin.readUshort(data, off);
|
|
2096
|
+
off += 2;
|
|
2097
|
+
const goff = bin.readUint(data, off);
|
|
2098
|
+
off += 4;
|
|
2099
|
+
const offs = [];
|
|
2100
|
+
for (let i = 0; i < gcnt + 1; i++)
|
|
2101
|
+
offs.push(bin.readUint(data, off + i * 4));
|
|
2102
|
+
const tups = [];
|
|
2103
|
+
const mins = [];
|
|
2104
|
+
const maxs = [];
|
|
2105
|
+
off = offset + toff;
|
|
2106
|
+
for (let i = 0; i < tcnt; i++) {
|
|
2107
|
+
const peak = readTuple(data, off + i * acnt * 2, acnt);
|
|
2108
|
+
const imin = [];
|
|
2109
|
+
const imax = [];
|
|
2110
|
+
tups.push(peak);
|
|
2111
|
+
mins.push(imin);
|
|
2112
|
+
maxs.push(imax);
|
|
2113
|
+
for (let k = 0; k < acnt; k++) {
|
|
2114
|
+
imin[k] = Math.min(peak[k], 0);
|
|
2115
|
+
imax[k] = Math.max(peak[k], 0);
|
|
2116
|
+
}
|
|
2117
|
+
}
|
|
2118
|
+
const i8 = new Int8Array(data.buffer);
|
|
2119
|
+
const tabs = [];
|
|
2120
|
+
for (let i = 0; i < gcnt; i++) {
|
|
2121
|
+
off = offset + goff + offs[i];
|
|
2122
|
+
let vcnt = bin.readUshort(data, off);
|
|
2123
|
+
off += 2;
|
|
2124
|
+
const snum = vcnt & SHARED_POINT_NUMBERS;
|
|
2125
|
+
vcnt &= 4095;
|
|
2126
|
+
const soff = bin.readUshort(data, off);
|
|
2127
|
+
off += 2;
|
|
2128
|
+
const hdr = readTupleVarHeader(
|
|
2129
|
+
data,
|
|
2130
|
+
off,
|
|
2131
|
+
vcnt,
|
|
2132
|
+
acnt,
|
|
2133
|
+
offset + goff + offs[i + 1]
|
|
2134
|
+
);
|
|
2135
|
+
const tab = [];
|
|
2136
|
+
tabs.push(tab);
|
|
2137
|
+
off = offset + goff + offs[i] + soff;
|
|
2138
|
+
let sind = null;
|
|
2139
|
+
if (snum) {
|
|
2140
|
+
const oo = readPointNumbers(data, off, i);
|
|
2141
|
+
sind = oo[0];
|
|
2142
|
+
off = oo[1];
|
|
2143
|
+
}
|
|
2144
|
+
for (let j = 0; j < vcnt; j++) {
|
|
2145
|
+
const vr = hdr[j];
|
|
2146
|
+
const end = off + vr[0];
|
|
2147
|
+
let ind = sind;
|
|
2148
|
+
if (vr[2] & PRIVATE_POINT_NUMBERS) {
|
|
2149
|
+
const oo = readPointNumbers(data, off, i);
|
|
2150
|
+
ind = oo[0];
|
|
2151
|
+
off = oo[1];
|
|
2152
|
+
}
|
|
2153
|
+
const ds = [];
|
|
2154
|
+
while (off < end) {
|
|
2155
|
+
const cb = data[off++];
|
|
2156
|
+
const cnt = (cb & 63) + 1;
|
|
2157
|
+
if (cb & DELTAS_ARE_ZERO) {
|
|
2158
|
+
for (let k = 0; k < cnt; k++) ds.push(0);
|
|
2159
|
+
} else if (cb & DELTAS_ARE_WORDS) {
|
|
2160
|
+
for (let k = 0; k < cnt; k++)
|
|
2161
|
+
ds.push(bin.readShort(data, off + k * 2));
|
|
2162
|
+
off += cnt * 2;
|
|
2163
|
+
} else {
|
|
2164
|
+
for (let k = 0; k < cnt; k++) ds.push(i8[off + k]);
|
|
2165
|
+
off += cnt;
|
|
2166
|
+
}
|
|
2167
|
+
}
|
|
2168
|
+
const ti = vr[1];
|
|
2169
|
+
const outInd = ind && ind.length * 2 == ds.length ? ind : null;
|
|
2170
|
+
tab.push([
|
|
2171
|
+
[
|
|
2172
|
+
vr[3] ? vr[3] : mins[ti],
|
|
2173
|
+
vr[4] ? vr[4] : tups[ti],
|
|
2174
|
+
vr[5] ? vr[5] : maxs[ti]
|
|
2175
|
+
],
|
|
2176
|
+
ds,
|
|
2177
|
+
outInd
|
|
2178
|
+
]);
|
|
2179
|
+
}
|
|
2180
|
+
}
|
|
2181
|
+
return tabs;
|
|
2182
|
+
}
|
|
2183
|
+
};
|
|
2184
|
+
T2.avar = {
|
|
2185
|
+
parseTab: function(data, offset, length, obj) {
|
|
2186
|
+
let off = offset;
|
|
2187
|
+
const bin = Typr2.B;
|
|
2188
|
+
const out = [];
|
|
2189
|
+
off += 6;
|
|
2190
|
+
const acnt = bin.readUshort(data, off);
|
|
2191
|
+
off += 2;
|
|
2192
|
+
for (let ai = 0; ai < acnt; ai++) {
|
|
2193
|
+
const cnt = bin.readUshort(data, off);
|
|
2194
|
+
off += 2;
|
|
2195
|
+
const poly = [];
|
|
2196
|
+
out.push(poly);
|
|
2197
|
+
for (let i = 0; i < cnt; i++) {
|
|
2198
|
+
const x = bin.readF2dot14(data, off);
|
|
2199
|
+
const y = bin.readF2dot14(data, off + 2);
|
|
2200
|
+
off += 4;
|
|
2201
|
+
poly.push(x, y);
|
|
2202
|
+
}
|
|
2203
|
+
}
|
|
2204
|
+
return out;
|
|
2205
|
+
}
|
|
2206
|
+
};
|
|
2207
|
+
T2.STAT = {
|
|
2208
|
+
parseTab: function(data, offset, length, font) {
|
|
2209
|
+
const bin = Typr2.B;
|
|
2210
|
+
let off = offset;
|
|
2211
|
+
const majorVersion = bin.readUshort(data, off);
|
|
2212
|
+
off += 2;
|
|
2213
|
+
const minorVersion = bin.readUshort(data, off);
|
|
2214
|
+
off += 2;
|
|
2215
|
+
const designAxisSize = bin.readUshort(data, off);
|
|
2216
|
+
off += 2;
|
|
2217
|
+
const designAxisCount = bin.readUshort(data, off);
|
|
2218
|
+
off += 2;
|
|
2219
|
+
const designAxesOffset = bin.readUint(data, off);
|
|
2220
|
+
off += 4;
|
|
2221
|
+
const axisValueCount = bin.readUshort(data, off);
|
|
2222
|
+
off += 2;
|
|
2223
|
+
const axisValueOffsetsOffset = bin.readUint(data, off);
|
|
2224
|
+
off += 4;
|
|
2225
|
+
let elidedFallbackNameID;
|
|
2226
|
+
if (majorVersion > 1 || majorVersion === 1 && minorVersion >= 1) {
|
|
2227
|
+
elidedFallbackNameID = bin.readUshort(data, off);
|
|
2228
|
+
off += 2;
|
|
2229
|
+
}
|
|
2230
|
+
const name2 = font.name || {};
|
|
2231
|
+
const designAxes = [];
|
|
2232
|
+
if (designAxisCount > 0) {
|
|
2233
|
+
let aoff = offset + designAxesOffset;
|
|
2234
|
+
for (let i = 0; i < designAxisCount; i++) {
|
|
2235
|
+
const tag = bin.readASCII(data, aoff, 4);
|
|
2236
|
+
const axisNameID = bin.readUshort(data, aoff + 4);
|
|
2237
|
+
const ordering = bin.readUshort(data, aoff + 6);
|
|
2238
|
+
designAxes.push({ tag, name: name2["_" + axisNameID], ordering });
|
|
2239
|
+
aoff += designAxisSize;
|
|
2240
|
+
}
|
|
2241
|
+
}
|
|
2242
|
+
const valueOffsets = [];
|
|
2243
|
+
if (axisValueCount > 0) {
|
|
2244
|
+
const arrBase = offset + axisValueOffsetsOffset;
|
|
2245
|
+
let voff = arrBase;
|
|
2246
|
+
for (let i = 0; i < axisValueCount; i++) {
|
|
2247
|
+
const relOff = bin.readUshort(data, voff);
|
|
2248
|
+
valueOffsets.push(arrBase + relOff);
|
|
2249
|
+
voff += 2;
|
|
2250
|
+
}
|
|
2251
|
+
}
|
|
2252
|
+
const axisValues = [];
|
|
2253
|
+
for (const rel of valueOffsets) {
|
|
2254
|
+
let voff = rel;
|
|
2255
|
+
const format = bin.readUshort(data, voff);
|
|
2256
|
+
voff += 2;
|
|
2257
|
+
if (format === 1) {
|
|
2258
|
+
const axisIndex = bin.readUshort(data, voff);
|
|
2259
|
+
voff += 2;
|
|
2260
|
+
const flags = bin.readUshort(data, voff);
|
|
2261
|
+
voff += 2;
|
|
2262
|
+
const valueNameID = bin.readUshort(data, voff);
|
|
2263
|
+
voff += 2;
|
|
2264
|
+
const value = bin.readFixed(data, voff);
|
|
2265
|
+
axisValues.push({
|
|
2266
|
+
format: 1,
|
|
2267
|
+
axisIndex,
|
|
2268
|
+
flags,
|
|
2269
|
+
name: name2["_" + valueNameID],
|
|
2270
|
+
value
|
|
2271
|
+
});
|
|
2272
|
+
} else if (format === 2) {
|
|
2273
|
+
const axisIndex = bin.readUshort(data, voff);
|
|
2274
|
+
voff += 2;
|
|
2275
|
+
const flags = bin.readUshort(data, voff);
|
|
2276
|
+
voff += 2;
|
|
2277
|
+
const valueNameID = bin.readUshort(data, voff);
|
|
2278
|
+
voff += 2;
|
|
2279
|
+
const nominalValue = bin.readFixed(data, voff);
|
|
2280
|
+
voff += 4;
|
|
2281
|
+
const rangeMinValue = bin.readFixed(data, voff);
|
|
2282
|
+
voff += 4;
|
|
2283
|
+
const rangeMaxValue = bin.readFixed(data, voff);
|
|
2284
|
+
axisValues.push({
|
|
2285
|
+
format: 2,
|
|
2286
|
+
axisIndex,
|
|
2287
|
+
flags,
|
|
2288
|
+
name: name2["_" + valueNameID],
|
|
2289
|
+
nominalValue,
|
|
2290
|
+
rangeMinValue,
|
|
2291
|
+
rangeMaxValue
|
|
2292
|
+
});
|
|
2293
|
+
} else if (format === 3) {
|
|
2294
|
+
const axisIndex = bin.readUshort(data, voff);
|
|
2295
|
+
voff += 2;
|
|
2296
|
+
const flags = bin.readUshort(data, voff);
|
|
2297
|
+
voff += 2;
|
|
2298
|
+
const valueNameID = bin.readUshort(data, voff);
|
|
2299
|
+
voff += 2;
|
|
2300
|
+
const value = bin.readFixed(data, voff);
|
|
2301
|
+
voff += 4;
|
|
2302
|
+
const linkedValue = bin.readFixed(data, voff);
|
|
2303
|
+
axisValues.push({
|
|
2304
|
+
format: 3,
|
|
2305
|
+
axisIndex,
|
|
2306
|
+
flags,
|
|
2307
|
+
name: name2["_" + valueNameID],
|
|
2308
|
+
value,
|
|
2309
|
+
linkedValue
|
|
2310
|
+
});
|
|
2311
|
+
} else if (format === 4) {
|
|
2312
|
+
const axisCount = bin.readUshort(data, voff);
|
|
2313
|
+
voff += 2;
|
|
2314
|
+
const flags = bin.readUshort(data, voff);
|
|
2315
|
+
voff += 2;
|
|
2316
|
+
const valueNameID = bin.readUshort(data, voff);
|
|
2317
|
+
voff += 2;
|
|
2318
|
+
const axisValuesArr = [];
|
|
2319
|
+
for (let i = 0; i < axisCount; i++) {
|
|
2320
|
+
const axisIndex = bin.readUshort(data, voff);
|
|
2321
|
+
const value = bin.readFixed(data, voff + 2);
|
|
2322
|
+
voff += 6;
|
|
2323
|
+
axisValuesArr.push({ axisIndex, value });
|
|
2324
|
+
}
|
|
2325
|
+
axisValues.push({
|
|
2326
|
+
format: 4,
|
|
2327
|
+
flags,
|
|
2328
|
+
name: name2["_" + valueNameID],
|
|
2329
|
+
axisValues: axisValuesArr
|
|
2330
|
+
});
|
|
2331
|
+
}
|
|
2332
|
+
}
|
|
2333
|
+
return {
|
|
2334
|
+
majorVersion,
|
|
2335
|
+
minorVersion,
|
|
2336
|
+
designAxes,
|
|
2337
|
+
axisValues,
|
|
2338
|
+
elidedFallbackNameID
|
|
2339
|
+
};
|
|
2340
|
+
}
|
|
2341
|
+
};
|
|
2342
|
+
T2.HVAR = {
|
|
2343
|
+
parseTab: function(data, offset, length, obj) {
|
|
2344
|
+
let off = offset;
|
|
2345
|
+
const oo = offset;
|
|
2346
|
+
const bin = Typr2.B;
|
|
2347
|
+
const out = [];
|
|
2348
|
+
off += 4;
|
|
2349
|
+
const varO = bin.readUint(data, off);
|
|
2350
|
+
off += 4;
|
|
2351
|
+
const advO = bin.readUint(data, off);
|
|
2352
|
+
off += 4;
|
|
2353
|
+
const lsbO = bin.readUint(data, off);
|
|
2354
|
+
off += 4;
|
|
2355
|
+
const rsbO = bin.readUint(data, off);
|
|
2356
|
+
off += 4;
|
|
2357
|
+
if (lsbO != 0 || rsbO != 0) throw new Error(`Invalid offset: ${lsbO}`);
|
|
2358
|
+
off = oo + varO;
|
|
2359
|
+
const ioff = off;
|
|
2360
|
+
const fmt = bin.readUshort(data, off);
|
|
2361
|
+
off += 2;
|
|
2362
|
+
if (fmt != 1) throw new Error("Invalid format");
|
|
2363
|
+
const vregO = bin.readUint(data, off);
|
|
2364
|
+
off += 4;
|
|
2365
|
+
const vcnt = bin.readUshort(data, off);
|
|
2366
|
+
off += 2;
|
|
2367
|
+
const offs = [];
|
|
2368
|
+
for (let i = 0; i < vcnt; i++)
|
|
2369
|
+
offs.push(bin.readUint(data, off + i * 4));
|
|
2370
|
+
off += vcnt * 4;
|
|
2371
|
+
off = ioff + vregO;
|
|
2372
|
+
const acnt = bin.readUshort(data, off);
|
|
2373
|
+
off += 2;
|
|
2374
|
+
const rcnt = bin.readUshort(data, off);
|
|
2375
|
+
off += 2;
|
|
2376
|
+
const regs = [];
|
|
2377
|
+
for (let i = 0; i < rcnt; i++) {
|
|
2378
|
+
const crd = [[], [], []];
|
|
2379
|
+
regs.push(crd);
|
|
2380
|
+
for (let j = 0; j < acnt; j++) {
|
|
2381
|
+
crd[0].push(bin.readF2dot14(data, off + 0));
|
|
2382
|
+
crd[1].push(bin.readF2dot14(data, off + 2));
|
|
2383
|
+
crd[2].push(bin.readF2dot14(data, off + 4));
|
|
2384
|
+
off += 6;
|
|
2385
|
+
}
|
|
2386
|
+
}
|
|
2387
|
+
const i8 = new Int8Array(data.buffer);
|
|
2388
|
+
const varStore = [];
|
|
2389
|
+
for (let i = 0; i < offs.length; i++) {
|
|
2390
|
+
off = oo + varO + offs[i];
|
|
2391
|
+
const vdata = [];
|
|
2392
|
+
varStore.push(vdata);
|
|
2393
|
+
const icnt = bin.readUshort(data, off);
|
|
2394
|
+
off += 2;
|
|
2395
|
+
const dcnt = bin.readUshort(data, off);
|
|
2396
|
+
off += 2;
|
|
2397
|
+
if (dcnt & 32768) throw new Error("Invalid delta count");
|
|
2398
|
+
const rcnt2 = bin.readUshort(data, off);
|
|
2399
|
+
off += 2;
|
|
2400
|
+
const ixs = [];
|
|
2401
|
+
for (let j = 0; j < rcnt2; j++)
|
|
2402
|
+
ixs.push(bin.readUshort(data, off + j * 2));
|
|
2403
|
+
off += rcnt2 * 2;
|
|
2404
|
+
for (let k = 0; k < icnt; k++) {
|
|
2405
|
+
const deltaData = [];
|
|
2406
|
+
for (let ri = 0; ri < rcnt2; ri++) {
|
|
2407
|
+
deltaData.push(ri < dcnt ? bin.readShort(data, off) : i8[off]);
|
|
2408
|
+
off += ri < dcnt ? 2 : 1;
|
|
2409
|
+
}
|
|
2410
|
+
const dd = new Array(regs.length);
|
|
2411
|
+
dd.fill(0);
|
|
2412
|
+
vdata.push(dd);
|
|
2413
|
+
for (let j = 0; j < ixs.length; j++) {
|
|
2414
|
+
if (ixs[j] < dd.length && j < deltaData.length) {
|
|
2415
|
+
dd[ixs[j]] = deltaData[j];
|
|
2416
|
+
}
|
|
2417
|
+
}
|
|
2418
|
+
}
|
|
2419
|
+
}
|
|
2420
|
+
off = oo + advO;
|
|
2421
|
+
const fmt2 = data[off++];
|
|
2422
|
+
if (fmt2 != 0) throw new Error("Invalid format");
|
|
2423
|
+
const entryFormat = data[off++];
|
|
2424
|
+
const mapCount = bin.readUshort(data, off);
|
|
2425
|
+
off += 2;
|
|
2426
|
+
const INNER_INDEX_BIT_COUNT_MASK = 15;
|
|
2427
|
+
const MAP_ENTRY_SIZE_MASK = 48;
|
|
2428
|
+
const entrySize = ((entryFormat & MAP_ENTRY_SIZE_MASK) >> 4) + 1;
|
|
2429
|
+
const dfs = [];
|
|
2430
|
+
for (let i = 0; i < mapCount; i++) {
|
|
2431
|
+
let entry = 0;
|
|
2432
|
+
if (entrySize == 1) entry = data[off++];
|
|
2433
|
+
else {
|
|
2434
|
+
entry = bin.readUshort(data, off);
|
|
2435
|
+
off += 2;
|
|
2436
|
+
}
|
|
2437
|
+
const outerIndex = entry >> (entryFormat & INNER_INDEX_BIT_COUNT_MASK) + 1;
|
|
2438
|
+
const innerIndex = entry & (1 << (entryFormat & INNER_INDEX_BIT_COUNT_MASK) + 1) - 1;
|
|
2439
|
+
if (outerIndex < varStore.length && varStore[outerIndex] && innerIndex < varStore[outerIndex].length) {
|
|
2440
|
+
dfs.push(varStore[outerIndex][innerIndex]);
|
|
2441
|
+
} else {
|
|
2442
|
+
const defaultDelta = new Array(regs.length);
|
|
2443
|
+
defaultDelta.fill(0);
|
|
2444
|
+
dfs.push(defaultDelta);
|
|
2445
|
+
}
|
|
2446
|
+
}
|
|
2447
|
+
return [regs, dfs];
|
|
2448
|
+
}
|
|
2449
|
+
};
|
|
2450
|
+
})(T = Typr2.T || (Typr2.T = {}));
|
|
2451
|
+
})(Typr || (Typr = {}));
|
|
2452
|
+
var typr_default = Typr;
|
|
2453
|
+
|
|
2454
|
+
// cli.ts
|
|
22
2455
|
var FORMAT_SET = /* @__PURE__ */ new Set(["png", "jpeg", "webp", "pdf", "svg"]);
|
|
23
2456
|
var DOCUMENT_JSON = "document.json";
|
|
24
2457
|
var IMAGES_SUBDIR = "images";
|
|
2458
|
+
var FONTS_SUBDIR = "fonts";
|
|
2459
|
+
var FONT_EXTENSIONS = /* @__PURE__ */ new Set([".ttf", ".otf"]);
|
|
2460
|
+
var LARGE_FILE_THRESHOLD = 2 * 1024 * 1024 * 1024;
|
|
25
2461
|
function formatFromOutFile(outPath) {
|
|
26
2462
|
const ext = path.extname(outPath).replace(/^\./, "").toLowerCase();
|
|
27
2463
|
if (ext === "jpg") return "jpeg";
|
|
@@ -38,7 +2474,7 @@ var EXT_BY_FORMAT = {
|
|
|
38
2474
|
function sanitizeForFilename(s) {
|
|
39
2475
|
return String(s).replace(/[:/\\]/g, "_").replace(/\s+/g, "_") || "_";
|
|
40
2476
|
}
|
|
41
|
-
function resolveInput(inputPath, explicitImagesDir) {
|
|
2477
|
+
function resolveInput(inputPath, explicitImagesDir, explicitFontsDir) {
|
|
42
2478
|
const resolved = path.resolve(inputPath);
|
|
43
2479
|
const stat = statSync(resolved);
|
|
44
2480
|
if (stat.isDirectory()) {
|
|
@@ -50,15 +2486,19 @@ function resolveInput(inputPath, explicitImagesDir) {
|
|
|
50
2486
|
}
|
|
51
2487
|
const imagesDir = path.join(resolved, IMAGES_SUBDIR);
|
|
52
2488
|
const useImagesDir = existsSync(imagesDir) && statSync(imagesDir).isDirectory() ? imagesDir : void 0;
|
|
2489
|
+
const fontsDir = path.join(resolved, FONTS_SUBDIR);
|
|
2490
|
+
const useFontsDir = existsSync(fontsDir) && statSync(fontsDir).isDirectory() ? fontsDir : void 0;
|
|
53
2491
|
return {
|
|
54
2492
|
documentPath,
|
|
55
2493
|
imagesDir: explicitImagesDir ? path.resolve(explicitImagesDir) : useImagesDir,
|
|
2494
|
+
fontsDir: explicitFontsDir ? path.resolve(explicitFontsDir) : useFontsDir,
|
|
56
2495
|
isRestJson: true
|
|
57
2496
|
};
|
|
58
2497
|
}
|
|
59
2498
|
return {
|
|
60
2499
|
documentPath: resolved,
|
|
61
2500
|
imagesDir: explicitImagesDir ? path.resolve(explicitImagesDir) : void 0,
|
|
2501
|
+
fontsDir: explicitFontsDir ? path.resolve(explicitFontsDir) : void 0,
|
|
62
2502
|
isRestJson: resolved.toLowerCase().endsWith(".json")
|
|
63
2503
|
};
|
|
64
2504
|
}
|
|
@@ -74,6 +2514,43 @@ function readImagesFromDir(dirPath) {
|
|
|
74
2514
|
}
|
|
75
2515
|
return out;
|
|
76
2516
|
}
|
|
2517
|
+
function* walkFontFiles(dirPath) {
|
|
2518
|
+
for (const entry of readdirSync(dirPath, { withFileTypes: true })) {
|
|
2519
|
+
const fullPath = path.join(dirPath, entry.name);
|
|
2520
|
+
if (entry.isDirectory()) {
|
|
2521
|
+
yield* walkFontFiles(fullPath);
|
|
2522
|
+
} else if (entry.isFile()) {
|
|
2523
|
+
const ext = path.extname(entry.name).toLowerCase();
|
|
2524
|
+
if (FONT_EXTENSIONS.has(ext)) {
|
|
2525
|
+
yield fullPath;
|
|
2526
|
+
}
|
|
2527
|
+
}
|
|
2528
|
+
}
|
|
2529
|
+
}
|
|
2530
|
+
function readFontsFromDir(dirPath) {
|
|
2531
|
+
const out = {};
|
|
2532
|
+
for (const fullPath of walkFontFiles(dirPath)) {
|
|
2533
|
+
const file = path.basename(fullPath);
|
|
2534
|
+
const buf = readFileSync(fullPath);
|
|
2535
|
+
const bytes = new Uint8Array(buf);
|
|
2536
|
+
const basenameNoExt = file.replace(/\.[^.]+$/, "") || file;
|
|
2537
|
+
let family;
|
|
2538
|
+
try {
|
|
2539
|
+
const [font] = typr_default.parse(bytes);
|
|
2540
|
+
family = font?.name?.fontFamily ?? basenameNoExt;
|
|
2541
|
+
} catch {
|
|
2542
|
+
family = basenameNoExt;
|
|
2543
|
+
}
|
|
2544
|
+
if (!family) continue;
|
|
2545
|
+
const existing = out[family];
|
|
2546
|
+
if (existing === void 0) {
|
|
2547
|
+
out[family] = [bytes];
|
|
2548
|
+
} else {
|
|
2549
|
+
existing.push(bytes);
|
|
2550
|
+
}
|
|
2551
|
+
}
|
|
2552
|
+
return out;
|
|
2553
|
+
}
|
|
77
2554
|
function exportAllOutputBasename(nodeId, suffix, format) {
|
|
78
2555
|
const ext = EXT_BY_FORMAT[format] ?? "png";
|
|
79
2556
|
const safeId = sanitizeForFilename(nodeId);
|
|
@@ -81,17 +2558,28 @@ function exportAllOutputBasename(nodeId, suffix, format) {
|
|
|
81
2558
|
const name = safeSuffix ? `${safeId}_${safeSuffix}` : safeId;
|
|
82
2559
|
return `${name}.${ext}`;
|
|
83
2560
|
}
|
|
84
|
-
async function runExportAll(documentPath, outDir, imagesDir, skipDefaultFonts) {
|
|
2561
|
+
async function runExportAll(documentPath, outDir, imagesDir, fontsDir, skipDefaultFonts) {
|
|
85
2562
|
const isFig = documentPath.toLowerCase().endsWith(".fig");
|
|
86
2563
|
let document;
|
|
87
2564
|
let items;
|
|
88
2565
|
let rendererOptions = {};
|
|
89
2566
|
if (isFig) {
|
|
90
|
-
const
|
|
91
|
-
const
|
|
2567
|
+
const stat = statSync(documentPath);
|
|
2568
|
+
const useStreaming = stat.size >= LARGE_FILE_THRESHOLD;
|
|
2569
|
+
let figFile;
|
|
2570
|
+
if (useStreaming) {
|
|
2571
|
+
const stream = createReadStream(documentPath, {
|
|
2572
|
+
highWaterMark: 1024 * 1024
|
|
2573
|
+
});
|
|
2574
|
+
figFile = await iofigma.kiwi.parseFileFromStream(stream);
|
|
2575
|
+
document = new FigmaDocument(figFile);
|
|
2576
|
+
} else {
|
|
2577
|
+
const bytes = new Uint8Array(readFileSync(documentPath));
|
|
2578
|
+
figFile = iofigma.kiwi.parseFile(bytes);
|
|
2579
|
+
document = new FigmaDocument(bytes);
|
|
2580
|
+
}
|
|
92
2581
|
const restDoc = figFileToRestLikeDocument(figFile);
|
|
93
2582
|
items = collectExportsFromDocument(restDoc);
|
|
94
|
-
document = new FigmaDocument(bytes);
|
|
95
2583
|
const imagesMap = iofigma.kiwi.extractImages(figFile.zip_files);
|
|
96
2584
|
const images = {};
|
|
97
2585
|
imagesMap.forEach((imgBytes, ref) => {
|
|
@@ -107,9 +2595,18 @@ async function runExportAll(documentPath, outDir, imagesDir, skipDefaultFonts) {
|
|
|
107
2595
|
document.payload
|
|
108
2596
|
);
|
|
109
2597
|
if (imagesDir) {
|
|
110
|
-
rendererOptions = {
|
|
2598
|
+
rendererOptions = {
|
|
2599
|
+
...rendererOptions,
|
|
2600
|
+
images: readImagesFromDir(imagesDir)
|
|
2601
|
+
};
|
|
111
2602
|
}
|
|
112
2603
|
}
|
|
2604
|
+
if (fontsDir) {
|
|
2605
|
+
rendererOptions = {
|
|
2606
|
+
...rendererOptions,
|
|
2607
|
+
fonts: readFontsFromDir(fontsDir)
|
|
2608
|
+
};
|
|
2609
|
+
}
|
|
113
2610
|
if (skipDefaultFonts || process.env.REFIG_SKIP_DEFAULT_FONTS === "1") {
|
|
114
2611
|
rendererOptions = { ...rendererOptions, loadFigmaDefaultFonts: false };
|
|
115
2612
|
}
|
|
@@ -146,8 +2643,33 @@ async function runSingleNode(documentPath, nodeId, outPath, opts) {
|
|
|
146
2643
|
throw new Error(`Unsupported --format "${format}"`);
|
|
147
2644
|
}
|
|
148
2645
|
const isJson = documentPath.toLowerCase().endsWith(".json");
|
|
149
|
-
|
|
150
|
-
|
|
2646
|
+
let document;
|
|
2647
|
+
if (isJson) {
|
|
2648
|
+
document = new FigmaDocument(
|
|
2649
|
+
JSON.parse(readFileSync(documentPath, "utf8"))
|
|
2650
|
+
);
|
|
2651
|
+
} else {
|
|
2652
|
+
const isFig = documentPath.toLowerCase().endsWith(".fig");
|
|
2653
|
+
const useStreaming = isFig && statSync(documentPath).size >= LARGE_FILE_THRESHOLD;
|
|
2654
|
+
if (useStreaming) {
|
|
2655
|
+
const stream = createReadStream(documentPath, {
|
|
2656
|
+
highWaterMark: 1024 * 1024
|
|
2657
|
+
});
|
|
2658
|
+
const figFile = await iofigma.kiwi.parseFileFromStream(stream);
|
|
2659
|
+
document = new FigmaDocument(figFile);
|
|
2660
|
+
} else {
|
|
2661
|
+
document = new FigmaDocument(
|
|
2662
|
+
new Uint8Array(readFileSync(documentPath))
|
|
2663
|
+
);
|
|
2664
|
+
}
|
|
2665
|
+
}
|
|
2666
|
+
const rendererOptions = {};
|
|
2667
|
+
if (isJson && opts.imagesDir) {
|
|
2668
|
+
rendererOptions.images = readImagesFromDir(opts.imagesDir);
|
|
2669
|
+
}
|
|
2670
|
+
if (opts.fontsDir) {
|
|
2671
|
+
rendererOptions.fonts = readFontsFromDir(opts.fontsDir);
|
|
2672
|
+
}
|
|
151
2673
|
if (opts.skipDefaultFonts || process.env.REFIG_SKIP_DEFAULT_FONTS === "1") {
|
|
152
2674
|
rendererOptions.loadFigmaDefaultFonts = false;
|
|
153
2675
|
}
|
|
@@ -174,19 +2696,22 @@ async function main() {
|
|
|
174
2696
|
"Headless Figma renderer \u2014 render .fig and REST API JSON to PNG/JPEG/WebP/PDF/SVG"
|
|
175
2697
|
).argument(
|
|
176
2698
|
"<input>",
|
|
177
|
-
"Path to .fig, JSON file (REST API response), or directory containing document.json (and optionally images/)"
|
|
178
|
-
).
|
|
2699
|
+
"Path to .fig, JSON file (REST API response), or directory containing document.json (and optionally images/, fonts/)"
|
|
2700
|
+
).option(
|
|
179
2701
|
"--out <path>",
|
|
180
|
-
"Output file path (single node) or output directory (--export-all)"
|
|
2702
|
+
"Output file path (single node) or output directory (--export-all); when omitted, uses OS temp directory (valid with --export-all or with both --format and --node)"
|
|
181
2703
|
).option(
|
|
182
2704
|
"--images <dir>",
|
|
183
2705
|
"Directory of image files for REST API document (optional; not used if <input> is a dir with images/)"
|
|
2706
|
+
).option(
|
|
2707
|
+
"--fonts <dir>",
|
|
2708
|
+
"Directory of font files (TTF/OTF) for custom fonts (optional; not used if <input> is a dir with fonts/)"
|
|
184
2709
|
).option(
|
|
185
2710
|
"--node <id>",
|
|
186
2711
|
"Figma node ID to render (required unless --export-all)"
|
|
187
2712
|
).option(
|
|
188
2713
|
"--export-all",
|
|
189
|
-
"Export every node that has exportSettings (REST JSON
|
|
2714
|
+
"Export every node that has exportSettings (REST JSON or .fig)"
|
|
190
2715
|
).option(
|
|
191
2716
|
"--format <fmt>",
|
|
192
2717
|
"png | jpeg | webp | pdf | svg (single-node only; default: from --out extension)"
|
|
@@ -199,32 +2724,35 @@ async function main() {
|
|
|
199
2724
|
const exportAll = options.exportAll === true;
|
|
200
2725
|
const nodeId = String(options.node ?? "").trim();
|
|
201
2726
|
const explicitImagesDir = typeof options.images === "string" ? options.images : void 0;
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
}
|
|
205
|
-
const { documentPath, imagesDir, isRestJson } = resolveInput(
|
|
2727
|
+
const explicitFontsDir = typeof options.fonts === "string" ? options.fonts : void 0;
|
|
2728
|
+
const { documentPath, imagesDir, fontsDir } = resolveInput(
|
|
206
2729
|
input.trim(),
|
|
207
|
-
explicitImagesDir
|
|
2730
|
+
explicitImagesDir,
|
|
2731
|
+
explicitFontsDir
|
|
208
2732
|
);
|
|
209
2733
|
if (exportAll) {
|
|
210
2734
|
if (nodeId) {
|
|
211
2735
|
program.error("--node must not be used with --export-all");
|
|
212
2736
|
}
|
|
213
|
-
const outDir =
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
2737
|
+
const outDir = outPath ? (() => {
|
|
2738
|
+
const resolved = path.resolve(outPath);
|
|
2739
|
+
if (existsSync(resolved)) {
|
|
2740
|
+
const stat = statSync(resolved);
|
|
2741
|
+
if (!stat.isDirectory()) {
|
|
2742
|
+
program.error(
|
|
2743
|
+
"--out must be a directory when using --export-all"
|
|
2744
|
+
);
|
|
2745
|
+
}
|
|
2746
|
+
} else {
|
|
2747
|
+
mkdirSync(resolved, { recursive: true });
|
|
220
2748
|
}
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
}
|
|
2749
|
+
return resolved;
|
|
2750
|
+
})() : mkdtempSync(path.join(tmpdir(), "refig-export-"));
|
|
224
2751
|
await runExportAll(
|
|
225
2752
|
documentPath,
|
|
226
2753
|
outDir,
|
|
227
2754
|
imagesDir,
|
|
2755
|
+
fontsDir,
|
|
228
2756
|
options.skipDefaultFonts === true
|
|
229
2757
|
);
|
|
230
2758
|
return;
|
|
@@ -235,12 +2763,33 @@ async function main() {
|
|
|
235
2763
|
const width = Number(options.width ?? 1024);
|
|
236
2764
|
const height = Number(options.height ?? 1024);
|
|
237
2765
|
const scale = Number(options.scale ?? 1);
|
|
238
|
-
|
|
239
|
-
|
|
2766
|
+
const formatOption = typeof options.format === "string" ? options.format : void 0;
|
|
2767
|
+
let singleOutPath;
|
|
2768
|
+
if (outPath) {
|
|
2769
|
+
singleOutPath = path.resolve(outPath);
|
|
2770
|
+
} else {
|
|
2771
|
+
if (!formatOption) {
|
|
2772
|
+
program.error(
|
|
2773
|
+
"When --out is omitted, both --node and --format are required"
|
|
2774
|
+
);
|
|
2775
|
+
}
|
|
2776
|
+
const format = formatOption.toLowerCase();
|
|
2777
|
+
if (!FORMAT_SET.has(format)) {
|
|
2778
|
+
program.error(`Unsupported --format "${format}"`);
|
|
2779
|
+
}
|
|
2780
|
+
const ext = EXT_BY_FORMAT[format] ?? "png";
|
|
2781
|
+
singleOutPath = path.join(
|
|
2782
|
+
tmpdir(),
|
|
2783
|
+
`refig-${sanitizeForFilename(nodeId)}.${ext}`
|
|
2784
|
+
);
|
|
2785
|
+
}
|
|
2786
|
+
await runSingleNode(documentPath, nodeId, singleOutPath, {
|
|
2787
|
+
format: formatOption,
|
|
240
2788
|
width,
|
|
241
2789
|
height,
|
|
242
2790
|
scale,
|
|
243
2791
|
imagesDir,
|
|
2792
|
+
fontsDir,
|
|
244
2793
|
skipDefaultFonts: options.skipDefaultFonts === true
|
|
245
2794
|
});
|
|
246
2795
|
}
|