pdf-parser.js 5.2.27 → 5.2.28
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/dist/{afm-widths-BYiX2L9D.cjs → afm-widths-BHD2HZIL.cjs} +553 -642
- package/dist/{afm-widths-blUDDjlI.js → afm-widths-B_IGbGky.js} +553 -642
- package/dist/afm-widths.cjs +1 -1
- package/dist/afm-widths.js +1 -1
- package/dist/annotations.cjs +5 -3
- package/dist/annotations.js +5 -3
- package/dist/builtin-encoding.cjs +17 -6
- package/dist/builtin-encoding.js +17 -6
- package/dist/bytes/crc32.cjs +5 -3
- package/dist/bytes/crc32.js +5 -3
- package/dist/bytes/flate.cjs +0 -1
- package/dist/bytes/flate.js +0 -1
- package/dist/cff-bounds.cjs +42 -24
- package/dist/cff-bounds.js +42 -24
- package/dist/cff.cjs +13 -6
- package/dist/cff.js +13 -6
- package/dist/cmap-table.cjs +54 -26
- package/dist/cmap-table.js +54 -26
- package/dist/cmap.cjs +5 -3
- package/dist/cmap.js +5 -3
- package/dist/content-write.cjs +3 -2
- package/dist/content-write.js +3 -2
- package/dist/crypto/aes.cjs +76 -55
- package/dist/crypto/aes.js +76 -55
- package/dist/crypto/md5.cjs +345 -149
- package/dist/crypto/md5.js +345 -149
- package/dist/crypto/rc4.cjs +5 -4
- package/dist/crypto/rc4.js +5 -4
- package/dist/crypto/sha2.cjs +92 -43
- package/dist/crypto/sha2.js +92 -43
- package/dist/embedded-font.cjs +4 -2
- package/dist/embedded-font.js +4 -2
- package/dist/encoding.cjs +1 -1
- package/dist/encoding.js +1 -1
- package/dist/encrypt-write.cjs +25 -21
- package/dist/encrypt-write.js +25 -21
- package/dist/encrypt.cjs +43 -64
- package/dist/encrypt.js +43 -64
- package/dist/filters.cjs +40 -20
- package/dist/filters.js +40 -20
- package/dist/font-face.cjs +2 -1
- package/dist/font-face.js +2 -1
- package/dist/font-read.cjs +12 -6
- package/dist/font-read.js +12 -6
- package/dist/font-tables.cjs +55 -28
- package/dist/font-tables.js +55 -28
- package/dist/gdef-table.cjs +6 -3
- package/dist/gdef-table.js +6 -3
- package/dist/glyf-contours.cjs +3 -1
- package/dist/glyf-contours.js +3 -1
- package/dist/glyf.cjs +22 -11
- package/dist/glyf.js +22 -11
- package/dist/gpos-table.cjs +37 -19
- package/dist/gpos-table.js +37 -19
- package/dist/gsub-table.cjs +28 -17
- package/dist/gsub-table.js +28 -17
- package/dist/hmtx-table.cjs +5 -3
- package/dist/hmtx-table.js +5 -3
- package/dist/image/ccitt-encode.cjs +8 -5
- package/dist/image/ccitt-encode.js +8 -5
- package/dist/image/ccitt.cjs +801 -209
- package/dist/image/ccitt.js +801 -209
- package/dist/image/jbig2-arith.cjs +340 -306
- package/dist/image/jbig2-arith.js +340 -306
- package/dist/image/jbig2-bitmap.cjs +8 -5
- package/dist/image/jbig2-bitmap.js +8 -5
- package/dist/image/jbig2-generic.cjs +240 -69
- package/dist/image/jbig2-generic.js +240 -69
- package/dist/image/jbig2-text.cjs +4 -2
- package/dist/image/jbig2-text.js +4 -2
- package/dist/image/jbig2.cjs +69 -31
- package/dist/image/jbig2.js +69 -31
- package/dist/image/jp2-boxes.cjs +52 -27
- package/dist/image/jp2-boxes.js +52 -27
- package/dist/image/jpeg-info.cjs +29 -24
- package/dist/image/jpeg-info.js +29 -24
- package/dist/image/jpeg2000-codestream.cjs +44 -24
- package/dist/image/jpeg2000-codestream.js +44 -24
- package/dist/image/jpeg2000-dwt.cjs +2 -1
- package/dist/image/jpeg2000-dwt.js +2 -1
- package/dist/image/jpeg2000-t1.cjs +21 -11
- package/dist/image/jpeg2000-t1.js +21 -11
- package/dist/image/jpeg2000-t2.cjs +12 -5
- package/dist/image/jpeg2000-t2.js +12 -5
- package/dist/image/jpeg2000-tagtree.cjs +8 -4
- package/dist/image/jpeg2000-tagtree.js +8 -4
- package/dist/image/jpeg2000.cjs +11 -6
- package/dist/image/jpeg2000.js +11 -6
- package/dist/image/png-decode.cjs +62 -39
- package/dist/image/png-decode.d.cts +3 -2
- package/dist/image/png-decode.d.ts +3 -2
- package/dist/image/png-decode.js +62 -39
- package/dist/image/png-filter.cjs +23 -15
- package/dist/image/png-filter.js +23 -15
- package/dist/images-read.cjs +41 -36
- package/dist/images-read.js +41 -36
- package/dist/index.cjs +1 -1
- package/dist/index.js +1 -1
- package/dist/interpret.cjs +39 -24
- package/dist/interpret.js +39 -24
- package/dist/lexer.cjs +86 -51
- package/dist/lexer.js +86 -51
- package/dist/math-content-write.cjs +9 -5
- package/dist/math-content-write.js +9 -5
- package/dist/math-font-write.cjs +2 -1
- package/dist/math-font-write.js +2 -1
- package/dist/math-font.cjs +16 -7
- package/dist/math-font.js +16 -7
- package/dist/math-table.cjs +25 -13
- package/dist/math-table.js +25 -13
- package/dist/matrix.cjs +3 -2
- package/dist/matrix.js +3 -2
- package/dist/measure.cjs +1 -1
- package/dist/measure.js +1 -1
- package/dist/navigation.cjs +10 -5
- package/dist/navigation.js +10 -5
- package/dist/ot-layout-common.cjs +4 -2
- package/dist/ot-layout-common.js +4 -2
- package/dist/parse.cjs +7 -5
- package/dist/parse.js +7 -5
- package/dist/pdf-text.cjs +5 -2
- package/dist/pdf-text.js +5 -2
- package/dist/predictors.cjs +14 -9
- package/dist/predictors.js +14 -9
- package/dist/raster.cjs +30 -19
- package/dist/raster.js +30 -19
- package/dist/read.cjs +17 -8
- package/dist/read.js +17 -8
- package/dist/serialize.cjs +6 -2
- package/dist/serialize.js +6 -2
- package/dist/sfnt-subset.cjs +25 -13
- package/dist/sfnt-subset.js +25 -13
- package/dist/sfnt.cjs +20 -10
- package/dist/sfnt.js +20 -10
- package/dist/text-group.cjs +0 -1
- package/dist/text-group.js +0 -1
- package/dist/tounicode.cjs +4 -2
- package/dist/tounicode.js +4 -2
- package/dist/winansi.cjs +1 -1
- package/dist/winansi.js +1 -1
- package/dist/write.cjs +20 -12
- package/dist/write.js +20 -12
- package/dist/xref.cjs +5 -2
- package/dist/xref.js +5 -2
- package/package.json +1 -1
package/dist/filters.js
CHANGED
|
@@ -5,6 +5,8 @@ import { decodeCcittFax } from "./image/ccitt.js";
|
|
|
5
5
|
import { decodeJbig2Embedded } from "./image/jbig2.js";
|
|
6
6
|
import { applyPredictor, readPredictorParams } from "./predictors.js";
|
|
7
7
|
//#region src/filters.ts
|
|
8
|
+
const BITS_PER_BYTE = 8;
|
|
9
|
+
const BYTE_MASK = 255;
|
|
8
10
|
function decodeStream(raw, dict, sink, resolve) {
|
|
9
11
|
const filters = filterNames(dict);
|
|
10
12
|
const parms = decodeParmsList(dict, filters.length);
|
|
@@ -102,7 +104,7 @@ function jbig2Decode(data, parm, dict, sink, resolve) {
|
|
|
102
104
|
}
|
|
103
105
|
});
|
|
104
106
|
return {
|
|
105
|
-
bytes: Uint8Array.from(image.bytes, (byte) => byte ^
|
|
107
|
+
bytes: Uint8Array.from(image.bytes, (byte) => byte ^ BYTE_MASK),
|
|
106
108
|
globals
|
|
107
109
|
};
|
|
108
110
|
} catch (error) {
|
|
@@ -145,6 +147,9 @@ function decodeParmsList(dict, count) {
|
|
|
145
147
|
const LZW_CLEAR_TABLE = 256;
|
|
146
148
|
const LZW_EOD = 257;
|
|
147
149
|
const LZW_INITIAL_CODE_WIDTH = 9;
|
|
150
|
+
const LZW_CODE_WIDTH_10 = 10;
|
|
151
|
+
const LZW_CODE_WIDTH_11 = 11;
|
|
152
|
+
const LZW_CODE_WIDTH_12 = 12;
|
|
148
153
|
const LZW_FIRST_NEW_CODE = 258;
|
|
149
154
|
function initialLzwDictionary() {
|
|
150
155
|
return Array.from({ length: 256 }, (_, i) => new Uint8Array([i]));
|
|
@@ -168,9 +173,9 @@ function lzwDecode(data, earlyChange, sink) {
|
|
|
168
173
|
const readCode = () => {
|
|
169
174
|
while (bitCount < codeWidth) {
|
|
170
175
|
if (pos >= data.length) return;
|
|
171
|
-
bitBuffer = bitBuffer <<
|
|
176
|
+
bitBuffer = bitBuffer << BITS_PER_BYTE | data[pos];
|
|
172
177
|
pos++;
|
|
173
|
-
bitCount +=
|
|
178
|
+
bitCount += BITS_PER_BYTE;
|
|
174
179
|
}
|
|
175
180
|
const value = bitBuffer >>> bitCount - codeWidth & (1 << codeWidth) - 1;
|
|
176
181
|
bitCount -= codeWidth;
|
|
@@ -202,9 +207,9 @@ function lzwDecode(data, earlyChange, sink) {
|
|
|
202
207
|
if (prevEntry !== void 0) {
|
|
203
208
|
dict[nextCode] = concatTwo(prevEntry, new Uint8Array([entry[0] ?? 0]));
|
|
204
209
|
nextCode++;
|
|
205
|
-
if (nextCode + bias ===
|
|
206
|
-
else if (nextCode + bias ===
|
|
207
|
-
else if (nextCode + bias ===
|
|
210
|
+
if (nextCode + bias === 2 ** LZW_INITIAL_CODE_WIDTH) codeWidth = LZW_CODE_WIDTH_10;
|
|
211
|
+
else if (nextCode + bias === 2 ** LZW_CODE_WIDTH_10) codeWidth = LZW_CODE_WIDTH_11;
|
|
212
|
+
else if (nextCode + bias === 2 ** LZW_CODE_WIDTH_11) codeWidth = LZW_CODE_WIDTH_12;
|
|
208
213
|
}
|
|
209
214
|
prevEntry = entry;
|
|
210
215
|
}
|
|
@@ -216,21 +221,26 @@ const ASCII85_END_MARKER = 126;
|
|
|
216
221
|
const ASCII85_MIN_DIGIT = 33;
|
|
217
222
|
const ASCII85_MAX_DIGIT = 117;
|
|
218
223
|
const ASCII85_MAX_DIGIT_VALUE = 84;
|
|
224
|
+
const ASCII85_RADIX = 85;
|
|
225
|
+
const ASCII85_GROUP_DIGITS = 5;
|
|
226
|
+
const ASCII85_OPTIONAL_PREFIX_LT = 60;
|
|
227
|
+
const ASCII85_BYTE_3_SHIFT = 24;
|
|
228
|
+
const ASCII85_BYTE_2_SHIFT = 16;
|
|
219
229
|
function ascii85GroupBytes(digits, byteCount) {
|
|
220
230
|
let value = 0;
|
|
221
|
-
for (const digit of digits) value = value *
|
|
231
|
+
for (const digit of digits) value = value * ASCII85_RADIX + digit;
|
|
222
232
|
return [
|
|
223
|
-
value >>>
|
|
224
|
-
value >>>
|
|
225
|
-
value >>>
|
|
226
|
-
value &
|
|
233
|
+
value >>> ASCII85_BYTE_3_SHIFT & BYTE_MASK,
|
|
234
|
+
value >>> ASCII85_BYTE_2_SHIFT & BYTE_MASK,
|
|
235
|
+
value >>> BITS_PER_BYTE & BYTE_MASK,
|
|
236
|
+
value & BYTE_MASK
|
|
227
237
|
].slice(0, byteCount);
|
|
228
238
|
}
|
|
229
239
|
function ascii85Decode(data) {
|
|
230
240
|
const out = [];
|
|
231
241
|
let tuple = [];
|
|
232
242
|
let i = 0;
|
|
233
|
-
if (data.length >= 2 && data[0] ===
|
|
243
|
+
if (data.length >= 2 && data[0] === ASCII85_OPTIONAL_PREFIX_LT && data[1] === ASCII85_END_MARKER) i = 2;
|
|
234
244
|
for (; i < data.length; i++) {
|
|
235
245
|
const byte = data[i];
|
|
236
246
|
if (byte === ASCII85_END_MARKER) break;
|
|
@@ -241,36 +251,46 @@ function ascii85Decode(data) {
|
|
|
241
251
|
}
|
|
242
252
|
if (byte < ASCII85_MIN_DIGIT || byte > ASCII85_MAX_DIGIT) continue;
|
|
243
253
|
tuple.push(byte - ASCII85_MIN_DIGIT);
|
|
244
|
-
if (tuple.length ===
|
|
254
|
+
if (tuple.length === ASCII85_GROUP_DIGITS) {
|
|
245
255
|
out.push(...ascii85GroupBytes(tuple, ASCII85_GROUP_BYTES));
|
|
246
256
|
tuple = [];
|
|
247
257
|
}
|
|
248
258
|
}
|
|
249
259
|
if (tuple.length > 1) {
|
|
250
260
|
const padded = tuple.slice();
|
|
251
|
-
while (padded.length <
|
|
261
|
+
while (padded.length < ASCII85_GROUP_DIGITS) padded.push(ASCII85_MAX_DIGIT_VALUE);
|
|
252
262
|
out.push(...ascii85GroupBytes(padded, tuple.length - 1));
|
|
253
263
|
}
|
|
254
264
|
return Uint8Array.from(out);
|
|
255
265
|
}
|
|
266
|
+
const ASCII_DIGIT_ZERO = 48;
|
|
267
|
+
const ASCII_DIGIT_NINE = 57;
|
|
268
|
+
const ASCII_UPPER_A = 65;
|
|
269
|
+
const ASCII_UPPER_F = 70;
|
|
270
|
+
const ASCII_LOWER_A = 97;
|
|
271
|
+
const ASCII_LOWER_F = 102;
|
|
272
|
+
const HEX_LETTER_DIGIT_OFFSET = 10;
|
|
273
|
+
const ASCII_HEX_TERMINATOR = 62;
|
|
274
|
+
const HEX_NIBBLE_BITS = 4;
|
|
256
275
|
function hexDigitValue(byte) {
|
|
257
|
-
if (byte >=
|
|
258
|
-
if (byte >=
|
|
259
|
-
if (byte >=
|
|
276
|
+
if (byte >= ASCII_DIGIT_ZERO && byte <= ASCII_DIGIT_NINE) return byte - ASCII_DIGIT_ZERO;
|
|
277
|
+
if (byte >= ASCII_UPPER_A && byte <= ASCII_UPPER_F) return byte - ASCII_UPPER_A + HEX_LETTER_DIGIT_OFFSET;
|
|
278
|
+
if (byte >= ASCII_LOWER_A && byte <= ASCII_LOWER_F) return byte - ASCII_LOWER_A + HEX_LETTER_DIGIT_OFFSET;
|
|
260
279
|
}
|
|
261
280
|
function asciiHexDecode(data) {
|
|
262
281
|
const digits = [];
|
|
263
282
|
for (const byte of data) {
|
|
264
|
-
if (byte ===
|
|
283
|
+
if (byte === ASCII_HEX_TERMINATOR) break;
|
|
265
284
|
const value = hexDigitValue(byte);
|
|
266
285
|
if (value !== void 0) digits.push(value);
|
|
267
286
|
}
|
|
268
287
|
if (digits.length % 2 === 1) digits.push(0);
|
|
269
288
|
const out = new Uint8Array(digits.length / 2);
|
|
270
|
-
for (let i = 0; i < out.length; i++) out[i] = digits[i * 2] <<
|
|
289
|
+
for (let i = 0; i < out.length; i++) out[i] = digits[i * 2] << HEX_NIBBLE_BITS | digits[i * 2 + 1];
|
|
271
290
|
return out;
|
|
272
291
|
}
|
|
273
292
|
const RUN_LENGTH_EOD = 128;
|
|
293
|
+
const RUN_LENGTH_REPEAT_COUNT_BASE = 257;
|
|
274
294
|
function runLengthDecode(data) {
|
|
275
295
|
const out = [];
|
|
276
296
|
let i = 0;
|
|
@@ -282,7 +302,7 @@ function runLengthDecode(data) {
|
|
|
282
302
|
const count = length + 1;
|
|
283
303
|
for (let j = 0; j < count && i < data.length; j++, i++) out.push(data[i]);
|
|
284
304
|
} else {
|
|
285
|
-
const count =
|
|
305
|
+
const count = RUN_LENGTH_REPEAT_COUNT_BASE - length;
|
|
286
306
|
const byte = data[i] ?? 0;
|
|
287
307
|
i++;
|
|
288
308
|
for (let j = 0; j < count; j++) out.push(byte);
|
package/dist/font-face.cjs
CHANGED
|
@@ -9,8 +9,9 @@ var FontFaceParseError = class extends Error {
|
|
|
9
9
|
}
|
|
10
10
|
};
|
|
11
11
|
const SFNT_VERSION_COLLECTION = 1953784678;
|
|
12
|
+
const SFNT_VERSION_TAG_BYTES = 4;
|
|
12
13
|
function isTrueTypeCollection(bytes) {
|
|
13
|
-
return require_sfnt.hasBytes(bytes, 0,
|
|
14
|
+
return require_sfnt.hasBytes(bytes, 0, SFNT_VERSION_TAG_BYTES) && require_sfnt.u32(bytes, 0) === SFNT_VERSION_COLLECTION;
|
|
14
15
|
}
|
|
15
16
|
const OS2_FS_SELECTION_ITALIC = 1;
|
|
16
17
|
const OS2_FS_SELECTION_BOLD = 32;
|
package/dist/font-face.js
CHANGED
|
@@ -8,8 +8,9 @@ var FontFaceParseError = class extends Error {
|
|
|
8
8
|
}
|
|
9
9
|
};
|
|
10
10
|
const SFNT_VERSION_COLLECTION = 1953784678;
|
|
11
|
+
const SFNT_VERSION_TAG_BYTES = 4;
|
|
11
12
|
function isTrueTypeCollection(bytes) {
|
|
12
|
-
return hasBytes(bytes, 0,
|
|
13
|
+
return hasBytes(bytes, 0, SFNT_VERSION_TAG_BYTES) && u32(bytes, 0) === SFNT_VERSION_COLLECTION;
|
|
13
14
|
}
|
|
14
15
|
const OS2_FS_SELECTION_ITALIC = 1;
|
|
15
16
|
const OS2_FS_SELECTION_BOLD = 32;
|
package/dist/font-read.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_afm_widths = require("./afm-widths-
|
|
2
|
+
const require_afm_widths = require("./afm-widths-BHD2HZIL.cjs");
|
|
3
3
|
const require_objects = require("./objects.cjs");
|
|
4
4
|
const require_filters = require("./filters.cjs");
|
|
5
5
|
const require_builtin_encoding = require("./builtin-encoding.cjs");
|
|
@@ -7,6 +7,7 @@ const require_cmap = require("./cmap.cjs");
|
|
|
7
7
|
const require_fonts = require("./fonts.cjs");
|
|
8
8
|
const require_font_style = require("./font-style.cjs");
|
|
9
9
|
//#region src/font-read.ts
|
|
10
|
+
const BITS_PER_BYTE = 8;
|
|
10
11
|
const SYMBOLIC_FLAG_BIT = 4;
|
|
11
12
|
const ITALIC_FLAG_BIT = 64;
|
|
12
13
|
const FORCE_BOLD_FLAG_BIT = 1 << 18;
|
|
@@ -150,6 +151,7 @@ function buildSimpleFont(fontDict, context) {
|
|
|
150
151
|
decodeToUnicode
|
|
151
152
|
};
|
|
152
153
|
}
|
|
154
|
+
const W_RANGE_ENTRY_COUNT = 3;
|
|
153
155
|
function readCidWidths(w) {
|
|
154
156
|
const map = /* @__PURE__ */ new Map();
|
|
155
157
|
if (w === void 0) return map;
|
|
@@ -171,7 +173,7 @@ function readCidWidths(w) {
|
|
|
171
173
|
const last = require_objects.asNumber(next);
|
|
172
174
|
const width = require_objects.asNumber(w[i + 2]);
|
|
173
175
|
if (last !== void 0 && width !== void 0) for (let cid = first; cid <= last; cid++) map.set(cid, width);
|
|
174
|
-
i +=
|
|
176
|
+
i += W_RANGE_ENTRY_COUNT;
|
|
175
177
|
}
|
|
176
178
|
}
|
|
177
179
|
return map;
|
|
@@ -182,6 +184,10 @@ const DEFAULT_VERTICAL_DISPLACEMENT_Y = -1e3;
|
|
|
182
184
|
const DW2_ENTRY_COUNT = 2;
|
|
183
185
|
const W2_TRIPLET_LENGTH = 3;
|
|
184
186
|
const VERTICAL_WRITING_MODE = 1;
|
|
187
|
+
const W2_RANGE_W1Y_OFFSET = 2;
|
|
188
|
+
const W2_RANGE_VX_OFFSET = 3;
|
|
189
|
+
const W2_RANGE_VY_OFFSET = 4;
|
|
190
|
+
const W2_RANGE_ENTRY_COUNT = 5;
|
|
185
191
|
function readCidVerticalMetrics(w2) {
|
|
186
192
|
const map = /* @__PURE__ */ new Map();
|
|
187
193
|
if (w2 === void 0) return map;
|
|
@@ -202,9 +208,9 @@ function readCidVerticalMetrics(w2) {
|
|
|
202
208
|
continue;
|
|
203
209
|
}
|
|
204
210
|
const last = require_objects.asNumber(next);
|
|
205
|
-
const entry = verticalEntryFrom(require_objects.asNumber(w2[i +
|
|
211
|
+
const entry = verticalEntryFrom(require_objects.asNumber(w2[i + W2_RANGE_W1Y_OFFSET]), require_objects.asNumber(w2[i + W2_RANGE_VX_OFFSET]), require_objects.asNumber(w2[i + W2_RANGE_VY_OFFSET]));
|
|
206
212
|
if (last !== void 0 && entry !== void 0) for (let cid = first; cid <= last; cid++) map.set(cid, entry);
|
|
207
|
-
i +=
|
|
213
|
+
i += W2_RANGE_ENTRY_COUNT;
|
|
208
214
|
}
|
|
209
215
|
return map;
|
|
210
216
|
}
|
|
@@ -265,7 +271,7 @@ function buildCompositeFont(fontDict, context) {
|
|
|
265
271
|
let unmapped = 0;
|
|
266
272
|
for (let i = 0; i + 1 < codes.length; i += 2) {
|
|
267
273
|
glyphCount++;
|
|
268
|
-
const cid = (codes[i] ?? 0) <<
|
|
274
|
+
const cid = (codes[i] ?? 0) << BITS_PER_BYTE | (codes[i + 1] ?? 0);
|
|
269
275
|
const mapped = toUnicode?.lookup(cid);
|
|
270
276
|
if (mapped !== void 0) {
|
|
271
277
|
out += mapped;
|
|
@@ -313,7 +319,7 @@ function createFontResolver(context) {
|
|
|
313
319
|
const font = resolve(fontResourceName, resources);
|
|
314
320
|
if (font === void 0) return;
|
|
315
321
|
const byteLengthConsumed = font.composite ? 2 : 1;
|
|
316
|
-
const code = font.composite ? (codes[byteOffset] ?? 0) <<
|
|
322
|
+
const code = font.composite ? (codes[byteOffset] ?? 0) << BITS_PER_BYTE | (codes[byteOffset + 1] ?? 0) : codes[byteOffset] ?? 0;
|
|
317
323
|
const vertical = font.verticalMetricsOf?.(code);
|
|
318
324
|
return {
|
|
319
325
|
widthPer1000: font.widthOf(code),
|
package/dist/font-read.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { c as glyphNameToUnicode, f as symbolGlyphName, m as zapfDingbatsGlyphName, n as widthOfCode, p as winAnsiGlyphName, u as namedEncodingGlyphName } from "./afm-widths-
|
|
1
|
+
import { c as glyphNameToUnicode, f as symbolGlyphName, m as zapfDingbatsGlyphName, n as widthOfCode, p as winAnsiGlyphName, u as namedEncodingGlyphName } from "./afm-widths-B_IGbGky.js";
|
|
2
2
|
import { asArray, asName, asNumber, dictGet, isName } from "./objects.js";
|
|
3
3
|
import { decodeStream } from "./filters.js";
|
|
4
4
|
import { readFontProgramEncoding } from "./builtin-encoding.js";
|
|
@@ -6,6 +6,7 @@ import { parseToUnicodeCMap } from "./cmap.js";
|
|
|
6
6
|
import { resolveStandardFont } from "./fonts.js";
|
|
7
7
|
import { styleFromBaseFontName } from "./font-style.js";
|
|
8
8
|
//#region src/font-read.ts
|
|
9
|
+
const BITS_PER_BYTE = 8;
|
|
9
10
|
const SYMBOLIC_FLAG_BIT = 4;
|
|
10
11
|
const ITALIC_FLAG_BIT = 64;
|
|
11
12
|
const FORCE_BOLD_FLAG_BIT = 1 << 18;
|
|
@@ -149,6 +150,7 @@ function buildSimpleFont(fontDict, context) {
|
|
|
149
150
|
decodeToUnicode
|
|
150
151
|
};
|
|
151
152
|
}
|
|
153
|
+
const W_RANGE_ENTRY_COUNT = 3;
|
|
152
154
|
function readCidWidths(w) {
|
|
153
155
|
const map = /* @__PURE__ */ new Map();
|
|
154
156
|
if (w === void 0) return map;
|
|
@@ -170,7 +172,7 @@ function readCidWidths(w) {
|
|
|
170
172
|
const last = asNumber(next);
|
|
171
173
|
const width = asNumber(w[i + 2]);
|
|
172
174
|
if (last !== void 0 && width !== void 0) for (let cid = first; cid <= last; cid++) map.set(cid, width);
|
|
173
|
-
i +=
|
|
175
|
+
i += W_RANGE_ENTRY_COUNT;
|
|
174
176
|
}
|
|
175
177
|
}
|
|
176
178
|
return map;
|
|
@@ -181,6 +183,10 @@ const DEFAULT_VERTICAL_DISPLACEMENT_Y = -1e3;
|
|
|
181
183
|
const DW2_ENTRY_COUNT = 2;
|
|
182
184
|
const W2_TRIPLET_LENGTH = 3;
|
|
183
185
|
const VERTICAL_WRITING_MODE = 1;
|
|
186
|
+
const W2_RANGE_W1Y_OFFSET = 2;
|
|
187
|
+
const W2_RANGE_VX_OFFSET = 3;
|
|
188
|
+
const W2_RANGE_VY_OFFSET = 4;
|
|
189
|
+
const W2_RANGE_ENTRY_COUNT = 5;
|
|
184
190
|
function readCidVerticalMetrics(w2) {
|
|
185
191
|
const map = /* @__PURE__ */ new Map();
|
|
186
192
|
if (w2 === void 0) return map;
|
|
@@ -201,9 +207,9 @@ function readCidVerticalMetrics(w2) {
|
|
|
201
207
|
continue;
|
|
202
208
|
}
|
|
203
209
|
const last = asNumber(next);
|
|
204
|
-
const entry = verticalEntryFrom(asNumber(w2[i +
|
|
210
|
+
const entry = verticalEntryFrom(asNumber(w2[i + W2_RANGE_W1Y_OFFSET]), asNumber(w2[i + W2_RANGE_VX_OFFSET]), asNumber(w2[i + W2_RANGE_VY_OFFSET]));
|
|
205
211
|
if (last !== void 0 && entry !== void 0) for (let cid = first; cid <= last; cid++) map.set(cid, entry);
|
|
206
|
-
i +=
|
|
212
|
+
i += W2_RANGE_ENTRY_COUNT;
|
|
207
213
|
}
|
|
208
214
|
return map;
|
|
209
215
|
}
|
|
@@ -264,7 +270,7 @@ function buildCompositeFont(fontDict, context) {
|
|
|
264
270
|
let unmapped = 0;
|
|
265
271
|
for (let i = 0; i + 1 < codes.length; i += 2) {
|
|
266
272
|
glyphCount++;
|
|
267
|
-
const cid = (codes[i] ?? 0) <<
|
|
273
|
+
const cid = (codes[i] ?? 0) << BITS_PER_BYTE | (codes[i + 1] ?? 0);
|
|
268
274
|
const mapped = toUnicode?.lookup(cid);
|
|
269
275
|
if (mapped !== void 0) {
|
|
270
276
|
out += mapped;
|
|
@@ -312,7 +318,7 @@ function createFontResolver(context) {
|
|
|
312
318
|
const font = resolve(fontResourceName, resources);
|
|
313
319
|
if (font === void 0) return;
|
|
314
320
|
const byteLengthConsumed = font.composite ? 2 : 1;
|
|
315
|
-
const code = font.composite ? (codes[byteOffset] ?? 0) <<
|
|
321
|
+
const code = font.composite ? (codes[byteOffset] ?? 0) << BITS_PER_BYTE | (codes[byteOffset + 1] ?? 0) : codes[byteOffset] ?? 0;
|
|
316
322
|
const vertical = font.verticalMetricsOf?.(code);
|
|
317
323
|
return {
|
|
318
324
|
widthPer1000: font.widthOf(code),
|
package/dist/font-tables.cjs
CHANGED
|
@@ -5,35 +5,53 @@ const HEAD_TABLE_SIZE = 54;
|
|
|
5
5
|
const HEAD_MAGIC_NUMBER = 1594834165;
|
|
6
6
|
const MIN_UNITS_PER_EM = 16;
|
|
7
7
|
const MAX_UNITS_PER_EM = 16384;
|
|
8
|
+
const HEAD_CHECKSUM_ADJUSTMENT_OFFSET = 8;
|
|
9
|
+
const HEAD_MAGIC_NUMBER_OFFSET = 12;
|
|
10
|
+
const HEAD_UNITS_PER_EM_OFFSET = 18;
|
|
11
|
+
const HEAD_X_MIN_OFFSET = 36;
|
|
12
|
+
const HEAD_Y_MIN_OFFSET = 38;
|
|
13
|
+
const HEAD_X_MAX_OFFSET = 40;
|
|
14
|
+
const HEAD_Y_MAX_OFFSET = 42;
|
|
15
|
+
const HEAD_MAC_STYLE_OFFSET = 44;
|
|
16
|
+
const HEAD_INDEX_TO_LOC_FORMAT_OFFSET = 50;
|
|
8
17
|
function parseHead(font) {
|
|
9
18
|
const bytes = require_sfnt.sfntTableBytes(font, "head");
|
|
10
19
|
if (bytes === void 0 || !require_sfnt.hasBytes(bytes, 0, HEAD_TABLE_SIZE)) return;
|
|
11
|
-
if (require_sfnt.u32(bytes,
|
|
12
|
-
const unitsPerEm = require_sfnt.u16(bytes,
|
|
20
|
+
if (require_sfnt.u32(bytes, HEAD_MAGIC_NUMBER_OFFSET) !== HEAD_MAGIC_NUMBER) return;
|
|
21
|
+
const unitsPerEm = require_sfnt.u16(bytes, HEAD_UNITS_PER_EM_OFFSET);
|
|
13
22
|
if (unitsPerEm < MIN_UNITS_PER_EM || unitsPerEm > MAX_UNITS_PER_EM) return;
|
|
14
|
-
const indexToLocFormat = require_sfnt.i16(bytes,
|
|
23
|
+
const indexToLocFormat = require_sfnt.i16(bytes, HEAD_INDEX_TO_LOC_FORMAT_OFFSET);
|
|
15
24
|
if (indexToLocFormat !== 0 && indexToLocFormat !== 1) return;
|
|
16
25
|
return {
|
|
17
26
|
unitsPerEm,
|
|
18
|
-
checkSumAdjustment: require_sfnt.u32(bytes,
|
|
19
|
-
xMin: require_sfnt.i16(bytes,
|
|
20
|
-
yMin: require_sfnt.i16(bytes,
|
|
21
|
-
xMax: require_sfnt.i16(bytes,
|
|
22
|
-
yMax: require_sfnt.i16(bytes,
|
|
27
|
+
checkSumAdjustment: require_sfnt.u32(bytes, HEAD_CHECKSUM_ADJUSTMENT_OFFSET),
|
|
28
|
+
xMin: require_sfnt.i16(bytes, HEAD_X_MIN_OFFSET),
|
|
29
|
+
yMin: require_sfnt.i16(bytes, HEAD_Y_MIN_OFFSET),
|
|
30
|
+
xMax: require_sfnt.i16(bytes, HEAD_X_MAX_OFFSET),
|
|
31
|
+
yMax: require_sfnt.i16(bytes, HEAD_Y_MAX_OFFSET),
|
|
23
32
|
indexToLocFormat,
|
|
24
|
-
macStyle: require_sfnt.u16(bytes,
|
|
33
|
+
macStyle: require_sfnt.u16(bytes, HEAD_MAC_STYLE_OFFSET)
|
|
25
34
|
};
|
|
26
35
|
}
|
|
27
36
|
const MAXP_HEADER_SIZE = 6;
|
|
37
|
+
const MAXP_NUM_GLYPHS_OFFSET = 4;
|
|
28
38
|
function parseMaxp(font) {
|
|
29
39
|
const bytes = require_sfnt.sfntTableBytes(font, "maxp");
|
|
30
40
|
if (bytes === void 0 || !require_sfnt.hasBytes(bytes, 0, MAXP_HEADER_SIZE)) return;
|
|
31
|
-
return { numGlyphs: require_sfnt.u16(bytes,
|
|
41
|
+
return { numGlyphs: require_sfnt.u16(bytes, MAXP_NUM_GLYPHS_OFFSET) };
|
|
32
42
|
}
|
|
33
43
|
const OS2_VERSION_0_SIZE = 78;
|
|
34
44
|
const OS2_VERSION_2_SIZE = 96;
|
|
35
45
|
const OS2_VERSION_WITH_HEIGHTS = 2;
|
|
36
46
|
const OS2_PANOSE_OFFSET = 32;
|
|
47
|
+
const OS2_FS_SELECTION_OFFSET = 62;
|
|
48
|
+
const OS2_S_TYPO_ASCENDER_OFFSET = 68;
|
|
49
|
+
const OS2_S_TYPO_DESCENDER_OFFSET = 70;
|
|
50
|
+
const OS2_S_TYPO_LINE_GAP_OFFSET = 72;
|
|
51
|
+
const OS2_US_WIN_ASCENT_OFFSET = 74;
|
|
52
|
+
const OS2_US_WIN_DESCENT_OFFSET = 76;
|
|
53
|
+
const OS2_SX_HEIGHT_OFFSET = 86;
|
|
54
|
+
const OS2_S_CAP_HEIGHT_OFFSET = 88;
|
|
37
55
|
function parseOs2(font) {
|
|
38
56
|
const bytes = require_sfnt.sfntTableBytes(font, "OS/2");
|
|
39
57
|
if (bytes === void 0 || !require_sfnt.hasBytes(bytes, 0, OS2_VERSION_0_SIZE)) return;
|
|
@@ -41,27 +59,30 @@ function parseOs2(font) {
|
|
|
41
59
|
const hasHeights = version >= OS2_VERSION_WITH_HEIGHTS && require_sfnt.hasBytes(bytes, 0, OS2_VERSION_2_SIZE);
|
|
42
60
|
return {
|
|
43
61
|
version,
|
|
44
|
-
fsSelection: require_sfnt.u16(bytes,
|
|
62
|
+
fsSelection: require_sfnt.u16(bytes, OS2_FS_SELECTION_OFFSET),
|
|
45
63
|
panose: [...bytes.subarray(OS2_PANOSE_OFFSET, 42)],
|
|
46
|
-
sTypoAscender: require_sfnt.i16(bytes,
|
|
47
|
-
sTypoDescender: require_sfnt.i16(bytes,
|
|
48
|
-
sTypoLineGap: require_sfnt.i16(bytes,
|
|
49
|
-
usWinAscent: require_sfnt.u16(bytes,
|
|
50
|
-
usWinDescent: require_sfnt.u16(bytes,
|
|
51
|
-
sxHeight: hasHeights ? require_sfnt.i16(bytes,
|
|
52
|
-
sCapHeight: hasHeights ? require_sfnt.i16(bytes,
|
|
64
|
+
sTypoAscender: require_sfnt.i16(bytes, OS2_S_TYPO_ASCENDER_OFFSET),
|
|
65
|
+
sTypoDescender: require_sfnt.i16(bytes, OS2_S_TYPO_DESCENDER_OFFSET),
|
|
66
|
+
sTypoLineGap: require_sfnt.i16(bytes, OS2_S_TYPO_LINE_GAP_OFFSET),
|
|
67
|
+
usWinAscent: require_sfnt.u16(bytes, OS2_US_WIN_ASCENT_OFFSET),
|
|
68
|
+
usWinDescent: require_sfnt.u16(bytes, OS2_US_WIN_DESCENT_OFFSET),
|
|
69
|
+
sxHeight: hasHeights ? require_sfnt.i16(bytes, OS2_SX_HEIGHT_OFFSET) : void 0,
|
|
70
|
+
sCapHeight: hasHeights ? require_sfnt.i16(bytes, OS2_S_CAP_HEIGHT_OFFSET) : void 0
|
|
53
71
|
};
|
|
54
72
|
}
|
|
55
73
|
const POST_HEADER_SIZE = 32;
|
|
56
74
|
const FIXED_16_16_SCALE = 65536;
|
|
75
|
+
const POST_ITALIC_ANGLE_OFFSET = 4;
|
|
76
|
+
const POST_UNDERLINE_POSITION_OFFSET = 8;
|
|
77
|
+
const POST_UNDERLINE_THICKNESS_OFFSET = 10;
|
|
57
78
|
function parsePost(font) {
|
|
58
79
|
const bytes = require_sfnt.sfntTableBytes(font, "post");
|
|
59
80
|
if (bytes === void 0 || !require_sfnt.hasBytes(bytes, 0, POST_HEADER_SIZE)) return;
|
|
60
81
|
return {
|
|
61
82
|
version: require_sfnt.u32(bytes, 0),
|
|
62
|
-
italicAngle: require_sfnt.i32(bytes,
|
|
63
|
-
underlinePosition: require_sfnt.i16(bytes,
|
|
64
|
-
underlineThickness: require_sfnt.i16(bytes,
|
|
83
|
+
italicAngle: require_sfnt.i32(bytes, POST_ITALIC_ANGLE_OFFSET) / FIXED_16_16_SCALE,
|
|
84
|
+
underlinePosition: require_sfnt.i16(bytes, POST_UNDERLINE_POSITION_OFFSET),
|
|
85
|
+
underlineThickness: require_sfnt.i16(bytes, POST_UNDERLINE_THICKNESS_OFFSET)
|
|
65
86
|
};
|
|
66
87
|
}
|
|
67
88
|
const MAC_STANDARD_GLYPH_ORDER = ".notdef .null nonmarkingreturn space exclam quotedbl numbersign dollar percent ampersand quotesingle parenleft parenright asterisk plus comma hyphen period slash zero one two three four five six seven eight nine colon semicolon less equal greater question at A B C D E F G H I J K L M N O P Q R S T U V W X Y Z bracketleft backslash bracketright asciicircum underscore grave a b c d e f g h i j k l m n o p q r s t u v w x y z braceleft bar braceright asciitilde Adieresis Aring Ccedilla Eacute Ntilde Odieresis Udieresis aacute agrave acircumflex adieresis atilde aring ccedilla eacute egrave ecircumflex edieresis iacute igrave icircumflex idieresis ntilde oacute ograve ocircumflex odieresis otilde uacute ugrave ucircumflex udieresis dagger degree cent sterling section bullet paragraph germandbls registered copyright trademark acute dieresis notequal AE Oslash infinity plusminus lessequal greaterequal yen mu partialdiff summation product pi integral ordfeminine ordmasculine Omega ae oslash questiondown exclamdown logicalnot radical florin approxequal Delta guillemotleft guillemotright ellipsis nonbreakingspace Agrave Atilde Otilde OE oe endash emdash quotedblleft quotedblright quoteleft quoteright divide lozenge ydieresis Ydieresis fraction currency guilsinglleft guilsinglright fi fl daggerdbl periodcentered quotesinglbase quotedblbase perthousand Acircumflex Ecircumflex Aacute Edieresis Egrave Iacute Icircumflex Idieresis Igrave Oacute Ocircumflex apple Ograve Uacute Ucircumflex Ugrave dotlessi circumflex tilde macron breve dotaccent ring cedilla hungarumlaut ogonek caron Lslash lslash Scaron scaron Zcaron zcaron brokenbar Eth eth Yacute yacute Thorn thorn minus multiply onesuperior twosuperior threesuperior onehalf onequarter threequarters franc Gbreve gbreve Idotaccent Scedilla scedilla Cacute cacute Ccaron ccaron dcroat".split(" ");
|
|
@@ -95,6 +116,10 @@ function parsePostGlyphNames(font) {
|
|
|
95
116
|
}
|
|
96
117
|
const NAME_HEADER_SIZE = 6;
|
|
97
118
|
const NAME_RECORD_SIZE = 12;
|
|
119
|
+
const NAME_HEADER_STORAGE_OFFSET_FIELD_OFFSET = 4;
|
|
120
|
+
const NAME_RECORD_NAME_ID_OFFSET = 6;
|
|
121
|
+
const NAME_RECORD_LENGTH_OFFSET = 8;
|
|
122
|
+
const NAME_RECORD_STRING_OFFSET_FIELD_OFFSET = 10;
|
|
98
123
|
const NAME_ID_FAMILY = 1;
|
|
99
124
|
const NAME_ID_POSTSCRIPT = 6;
|
|
100
125
|
const NAME_ID_TYPOGRAPHIC_FAMILY = 16;
|
|
@@ -103,9 +128,10 @@ const PLATFORM_MACINTOSH = 1;
|
|
|
103
128
|
const PLATFORM_WINDOWS = 3;
|
|
104
129
|
const WINDOWS_ENCODING_UNICODE_BMP = 1;
|
|
105
130
|
const MACINTOSH_ENCODING_ROMAN = 0;
|
|
131
|
+
const BITS_PER_BYTE = 8;
|
|
106
132
|
function decodeUtf16Be(bytes, offset, length) {
|
|
107
133
|
let text = "";
|
|
108
|
-
for (let i = 0; i + 1 < length; i += 2) text += String.fromCharCode(bytes[offset + i] <<
|
|
134
|
+
for (let i = 0; i + 1 < length; i += 2) text += String.fromCharCode(bytes[offset + i] << BITS_PER_BYTE | bytes[offset + i + 1]);
|
|
109
135
|
return text;
|
|
110
136
|
}
|
|
111
137
|
function decodeMacRoman(bytes, offset, length) {
|
|
@@ -113,14 +139,15 @@ function decodeMacRoman(bytes, offset, length) {
|
|
|
113
139
|
for (let i = 0; i < length; i++) text += String.fromCharCode(bytes[offset + i]);
|
|
114
140
|
return text;
|
|
115
141
|
}
|
|
142
|
+
const PLATFORM_RANK_UNSUPPORTED = 3;
|
|
116
143
|
function platformRank(record) {
|
|
117
144
|
if (record.platformId === PLATFORM_WINDOWS && record.encodingId === WINDOWS_ENCODING_UNICODE_BMP) return 0;
|
|
118
145
|
if (record.platformId === PLATFORM_UNICODE) return 1;
|
|
119
146
|
if (record.platformId === PLATFORM_MACINTOSH && record.encodingId === MACINTOSH_ENCODING_ROMAN) return 2;
|
|
120
|
-
return
|
|
147
|
+
return PLATFORM_RANK_UNSUPPORTED;
|
|
121
148
|
}
|
|
122
149
|
function readName(bytes, records, nameId) {
|
|
123
|
-
const matches = records.filter((record) => record.nameId === nameId && platformRank(record) <
|
|
150
|
+
const matches = records.filter((record) => record.nameId === nameId && platformRank(record) < PLATFORM_RANK_UNSUPPORTED).sort((a, b) => platformRank(a) - platformRank(b));
|
|
124
151
|
for (const record of matches) {
|
|
125
152
|
if (!require_sfnt.hasBytes(bytes, record.stringOffset, record.length)) continue;
|
|
126
153
|
const text = record.platformId === PLATFORM_MACINTOSH ? decodeMacRoman(bytes, record.stringOffset, record.length) : decodeUtf16Be(bytes, record.stringOffset, record.length);
|
|
@@ -131,7 +158,7 @@ function parseName(font) {
|
|
|
131
158
|
const bytes = require_sfnt.sfntTableBytes(font, "name");
|
|
132
159
|
if (bytes === void 0 || !require_sfnt.hasBytes(bytes, 0, NAME_HEADER_SIZE)) return;
|
|
133
160
|
const count = require_sfnt.u16(bytes, 2);
|
|
134
|
-
const storageOffset = require_sfnt.u16(bytes,
|
|
161
|
+
const storageOffset = require_sfnt.u16(bytes, NAME_HEADER_STORAGE_OFFSET_FIELD_OFFSET);
|
|
135
162
|
if (!require_sfnt.hasBytes(bytes, NAME_HEADER_SIZE, count * NAME_RECORD_SIZE)) return;
|
|
136
163
|
const records = [];
|
|
137
164
|
for (let i = 0; i < count; i++) {
|
|
@@ -139,9 +166,9 @@ function parseName(font) {
|
|
|
139
166
|
records.push({
|
|
140
167
|
platformId: require_sfnt.u16(bytes, recordOffset),
|
|
141
168
|
encodingId: require_sfnt.u16(bytes, recordOffset + 2),
|
|
142
|
-
nameId: require_sfnt.u16(bytes, recordOffset +
|
|
143
|
-
length: require_sfnt.u16(bytes, recordOffset +
|
|
144
|
-
stringOffset: storageOffset + require_sfnt.u16(bytes, recordOffset +
|
|
169
|
+
nameId: require_sfnt.u16(bytes, recordOffset + NAME_RECORD_NAME_ID_OFFSET),
|
|
170
|
+
length: require_sfnt.u16(bytes, recordOffset + NAME_RECORD_LENGTH_OFFSET),
|
|
171
|
+
stringOffset: storageOffset + require_sfnt.u16(bytes, recordOffset + NAME_RECORD_STRING_OFFSET_FIELD_OFFSET)
|
|
145
172
|
});
|
|
146
173
|
}
|
|
147
174
|
return {
|
package/dist/font-tables.js
CHANGED
|
@@ -4,35 +4,53 @@ const HEAD_TABLE_SIZE = 54;
|
|
|
4
4
|
const HEAD_MAGIC_NUMBER = 1594834165;
|
|
5
5
|
const MIN_UNITS_PER_EM = 16;
|
|
6
6
|
const MAX_UNITS_PER_EM = 16384;
|
|
7
|
+
const HEAD_CHECKSUM_ADJUSTMENT_OFFSET = 8;
|
|
8
|
+
const HEAD_MAGIC_NUMBER_OFFSET = 12;
|
|
9
|
+
const HEAD_UNITS_PER_EM_OFFSET = 18;
|
|
10
|
+
const HEAD_X_MIN_OFFSET = 36;
|
|
11
|
+
const HEAD_Y_MIN_OFFSET = 38;
|
|
12
|
+
const HEAD_X_MAX_OFFSET = 40;
|
|
13
|
+
const HEAD_Y_MAX_OFFSET = 42;
|
|
14
|
+
const HEAD_MAC_STYLE_OFFSET = 44;
|
|
15
|
+
const HEAD_INDEX_TO_LOC_FORMAT_OFFSET = 50;
|
|
7
16
|
function parseHead(font) {
|
|
8
17
|
const bytes = sfntTableBytes(font, "head");
|
|
9
18
|
if (bytes === void 0 || !hasBytes(bytes, 0, HEAD_TABLE_SIZE)) return;
|
|
10
|
-
if (u32(bytes,
|
|
11
|
-
const unitsPerEm = u16(bytes,
|
|
19
|
+
if (u32(bytes, HEAD_MAGIC_NUMBER_OFFSET) !== HEAD_MAGIC_NUMBER) return;
|
|
20
|
+
const unitsPerEm = u16(bytes, HEAD_UNITS_PER_EM_OFFSET);
|
|
12
21
|
if (unitsPerEm < MIN_UNITS_PER_EM || unitsPerEm > MAX_UNITS_PER_EM) return;
|
|
13
|
-
const indexToLocFormat = i16(bytes,
|
|
22
|
+
const indexToLocFormat = i16(bytes, HEAD_INDEX_TO_LOC_FORMAT_OFFSET);
|
|
14
23
|
if (indexToLocFormat !== 0 && indexToLocFormat !== 1) return;
|
|
15
24
|
return {
|
|
16
25
|
unitsPerEm,
|
|
17
|
-
checkSumAdjustment: u32(bytes,
|
|
18
|
-
xMin: i16(bytes,
|
|
19
|
-
yMin: i16(bytes,
|
|
20
|
-
xMax: i16(bytes,
|
|
21
|
-
yMax: i16(bytes,
|
|
26
|
+
checkSumAdjustment: u32(bytes, HEAD_CHECKSUM_ADJUSTMENT_OFFSET),
|
|
27
|
+
xMin: i16(bytes, HEAD_X_MIN_OFFSET),
|
|
28
|
+
yMin: i16(bytes, HEAD_Y_MIN_OFFSET),
|
|
29
|
+
xMax: i16(bytes, HEAD_X_MAX_OFFSET),
|
|
30
|
+
yMax: i16(bytes, HEAD_Y_MAX_OFFSET),
|
|
22
31
|
indexToLocFormat,
|
|
23
|
-
macStyle: u16(bytes,
|
|
32
|
+
macStyle: u16(bytes, HEAD_MAC_STYLE_OFFSET)
|
|
24
33
|
};
|
|
25
34
|
}
|
|
26
35
|
const MAXP_HEADER_SIZE = 6;
|
|
36
|
+
const MAXP_NUM_GLYPHS_OFFSET = 4;
|
|
27
37
|
function parseMaxp(font) {
|
|
28
38
|
const bytes = sfntTableBytes(font, "maxp");
|
|
29
39
|
if (bytes === void 0 || !hasBytes(bytes, 0, MAXP_HEADER_SIZE)) return;
|
|
30
|
-
return { numGlyphs: u16(bytes,
|
|
40
|
+
return { numGlyphs: u16(bytes, MAXP_NUM_GLYPHS_OFFSET) };
|
|
31
41
|
}
|
|
32
42
|
const OS2_VERSION_0_SIZE = 78;
|
|
33
43
|
const OS2_VERSION_2_SIZE = 96;
|
|
34
44
|
const OS2_VERSION_WITH_HEIGHTS = 2;
|
|
35
45
|
const OS2_PANOSE_OFFSET = 32;
|
|
46
|
+
const OS2_FS_SELECTION_OFFSET = 62;
|
|
47
|
+
const OS2_S_TYPO_ASCENDER_OFFSET = 68;
|
|
48
|
+
const OS2_S_TYPO_DESCENDER_OFFSET = 70;
|
|
49
|
+
const OS2_S_TYPO_LINE_GAP_OFFSET = 72;
|
|
50
|
+
const OS2_US_WIN_ASCENT_OFFSET = 74;
|
|
51
|
+
const OS2_US_WIN_DESCENT_OFFSET = 76;
|
|
52
|
+
const OS2_SX_HEIGHT_OFFSET = 86;
|
|
53
|
+
const OS2_S_CAP_HEIGHT_OFFSET = 88;
|
|
36
54
|
function parseOs2(font) {
|
|
37
55
|
const bytes = sfntTableBytes(font, "OS/2");
|
|
38
56
|
if (bytes === void 0 || !hasBytes(bytes, 0, OS2_VERSION_0_SIZE)) return;
|
|
@@ -40,27 +58,30 @@ function parseOs2(font) {
|
|
|
40
58
|
const hasHeights = version >= OS2_VERSION_WITH_HEIGHTS && hasBytes(bytes, 0, OS2_VERSION_2_SIZE);
|
|
41
59
|
return {
|
|
42
60
|
version,
|
|
43
|
-
fsSelection: u16(bytes,
|
|
61
|
+
fsSelection: u16(bytes, OS2_FS_SELECTION_OFFSET),
|
|
44
62
|
panose: [...bytes.subarray(OS2_PANOSE_OFFSET, 42)],
|
|
45
|
-
sTypoAscender: i16(bytes,
|
|
46
|
-
sTypoDescender: i16(bytes,
|
|
47
|
-
sTypoLineGap: i16(bytes,
|
|
48
|
-
usWinAscent: u16(bytes,
|
|
49
|
-
usWinDescent: u16(bytes,
|
|
50
|
-
sxHeight: hasHeights ? i16(bytes,
|
|
51
|
-
sCapHeight: hasHeights ? i16(bytes,
|
|
63
|
+
sTypoAscender: i16(bytes, OS2_S_TYPO_ASCENDER_OFFSET),
|
|
64
|
+
sTypoDescender: i16(bytes, OS2_S_TYPO_DESCENDER_OFFSET),
|
|
65
|
+
sTypoLineGap: i16(bytes, OS2_S_TYPO_LINE_GAP_OFFSET),
|
|
66
|
+
usWinAscent: u16(bytes, OS2_US_WIN_ASCENT_OFFSET),
|
|
67
|
+
usWinDescent: u16(bytes, OS2_US_WIN_DESCENT_OFFSET),
|
|
68
|
+
sxHeight: hasHeights ? i16(bytes, OS2_SX_HEIGHT_OFFSET) : void 0,
|
|
69
|
+
sCapHeight: hasHeights ? i16(bytes, OS2_S_CAP_HEIGHT_OFFSET) : void 0
|
|
52
70
|
};
|
|
53
71
|
}
|
|
54
72
|
const POST_HEADER_SIZE = 32;
|
|
55
73
|
const FIXED_16_16_SCALE = 65536;
|
|
74
|
+
const POST_ITALIC_ANGLE_OFFSET = 4;
|
|
75
|
+
const POST_UNDERLINE_POSITION_OFFSET = 8;
|
|
76
|
+
const POST_UNDERLINE_THICKNESS_OFFSET = 10;
|
|
56
77
|
function parsePost(font) {
|
|
57
78
|
const bytes = sfntTableBytes(font, "post");
|
|
58
79
|
if (bytes === void 0 || !hasBytes(bytes, 0, POST_HEADER_SIZE)) return;
|
|
59
80
|
return {
|
|
60
81
|
version: u32(bytes, 0),
|
|
61
|
-
italicAngle: i32(bytes,
|
|
62
|
-
underlinePosition: i16(bytes,
|
|
63
|
-
underlineThickness: i16(bytes,
|
|
82
|
+
italicAngle: i32(bytes, POST_ITALIC_ANGLE_OFFSET) / FIXED_16_16_SCALE,
|
|
83
|
+
underlinePosition: i16(bytes, POST_UNDERLINE_POSITION_OFFSET),
|
|
84
|
+
underlineThickness: i16(bytes, POST_UNDERLINE_THICKNESS_OFFSET)
|
|
64
85
|
};
|
|
65
86
|
}
|
|
66
87
|
const MAC_STANDARD_GLYPH_ORDER = ".notdef .null nonmarkingreturn space exclam quotedbl numbersign dollar percent ampersand quotesingle parenleft parenright asterisk plus comma hyphen period slash zero one two three four five six seven eight nine colon semicolon less equal greater question at A B C D E F G H I J K L M N O P Q R S T U V W X Y Z bracketleft backslash bracketright asciicircum underscore grave a b c d e f g h i j k l m n o p q r s t u v w x y z braceleft bar braceright asciitilde Adieresis Aring Ccedilla Eacute Ntilde Odieresis Udieresis aacute agrave acircumflex adieresis atilde aring ccedilla eacute egrave ecircumflex edieresis iacute igrave icircumflex idieresis ntilde oacute ograve ocircumflex odieresis otilde uacute ugrave ucircumflex udieresis dagger degree cent sterling section bullet paragraph germandbls registered copyright trademark acute dieresis notequal AE Oslash infinity plusminus lessequal greaterequal yen mu partialdiff summation product pi integral ordfeminine ordmasculine Omega ae oslash questiondown exclamdown logicalnot radical florin approxequal Delta guillemotleft guillemotright ellipsis nonbreakingspace Agrave Atilde Otilde OE oe endash emdash quotedblleft quotedblright quoteleft quoteright divide lozenge ydieresis Ydieresis fraction currency guilsinglleft guilsinglright fi fl daggerdbl periodcentered quotesinglbase quotedblbase perthousand Acircumflex Ecircumflex Aacute Edieresis Egrave Iacute Icircumflex Idieresis Igrave Oacute Ocircumflex apple Ograve Uacute Ucircumflex Ugrave dotlessi circumflex tilde macron breve dotaccent ring cedilla hungarumlaut ogonek caron Lslash lslash Scaron scaron Zcaron zcaron brokenbar Eth eth Yacute yacute Thorn thorn minus multiply onesuperior twosuperior threesuperior onehalf onequarter threequarters franc Gbreve gbreve Idotaccent Scedilla scedilla Cacute cacute Ccaron ccaron dcroat".split(" ");
|
|
@@ -94,6 +115,10 @@ function parsePostGlyphNames(font) {
|
|
|
94
115
|
}
|
|
95
116
|
const NAME_HEADER_SIZE = 6;
|
|
96
117
|
const NAME_RECORD_SIZE = 12;
|
|
118
|
+
const NAME_HEADER_STORAGE_OFFSET_FIELD_OFFSET = 4;
|
|
119
|
+
const NAME_RECORD_NAME_ID_OFFSET = 6;
|
|
120
|
+
const NAME_RECORD_LENGTH_OFFSET = 8;
|
|
121
|
+
const NAME_RECORD_STRING_OFFSET_FIELD_OFFSET = 10;
|
|
97
122
|
const NAME_ID_FAMILY = 1;
|
|
98
123
|
const NAME_ID_POSTSCRIPT = 6;
|
|
99
124
|
const NAME_ID_TYPOGRAPHIC_FAMILY = 16;
|
|
@@ -102,9 +127,10 @@ const PLATFORM_MACINTOSH = 1;
|
|
|
102
127
|
const PLATFORM_WINDOWS = 3;
|
|
103
128
|
const WINDOWS_ENCODING_UNICODE_BMP = 1;
|
|
104
129
|
const MACINTOSH_ENCODING_ROMAN = 0;
|
|
130
|
+
const BITS_PER_BYTE = 8;
|
|
105
131
|
function decodeUtf16Be(bytes, offset, length) {
|
|
106
132
|
let text = "";
|
|
107
|
-
for (let i = 0; i + 1 < length; i += 2) text += String.fromCharCode(bytes[offset + i] <<
|
|
133
|
+
for (let i = 0; i + 1 < length; i += 2) text += String.fromCharCode(bytes[offset + i] << BITS_PER_BYTE | bytes[offset + i + 1]);
|
|
108
134
|
return text;
|
|
109
135
|
}
|
|
110
136
|
function decodeMacRoman(bytes, offset, length) {
|
|
@@ -112,14 +138,15 @@ function decodeMacRoman(bytes, offset, length) {
|
|
|
112
138
|
for (let i = 0; i < length; i++) text += String.fromCharCode(bytes[offset + i]);
|
|
113
139
|
return text;
|
|
114
140
|
}
|
|
141
|
+
const PLATFORM_RANK_UNSUPPORTED = 3;
|
|
115
142
|
function platformRank(record) {
|
|
116
143
|
if (record.platformId === PLATFORM_WINDOWS && record.encodingId === WINDOWS_ENCODING_UNICODE_BMP) return 0;
|
|
117
144
|
if (record.platformId === PLATFORM_UNICODE) return 1;
|
|
118
145
|
if (record.platformId === PLATFORM_MACINTOSH && record.encodingId === MACINTOSH_ENCODING_ROMAN) return 2;
|
|
119
|
-
return
|
|
146
|
+
return PLATFORM_RANK_UNSUPPORTED;
|
|
120
147
|
}
|
|
121
148
|
function readName(bytes, records, nameId) {
|
|
122
|
-
const matches = records.filter((record) => record.nameId === nameId && platformRank(record) <
|
|
149
|
+
const matches = records.filter((record) => record.nameId === nameId && platformRank(record) < PLATFORM_RANK_UNSUPPORTED).sort((a, b) => platformRank(a) - platformRank(b));
|
|
123
150
|
for (const record of matches) {
|
|
124
151
|
if (!hasBytes(bytes, record.stringOffset, record.length)) continue;
|
|
125
152
|
const text = record.platformId === PLATFORM_MACINTOSH ? decodeMacRoman(bytes, record.stringOffset, record.length) : decodeUtf16Be(bytes, record.stringOffset, record.length);
|
|
@@ -130,7 +157,7 @@ function parseName(font) {
|
|
|
130
157
|
const bytes = sfntTableBytes(font, "name");
|
|
131
158
|
if (bytes === void 0 || !hasBytes(bytes, 0, NAME_HEADER_SIZE)) return;
|
|
132
159
|
const count = u16(bytes, 2);
|
|
133
|
-
const storageOffset = u16(bytes,
|
|
160
|
+
const storageOffset = u16(bytes, NAME_HEADER_STORAGE_OFFSET_FIELD_OFFSET);
|
|
134
161
|
if (!hasBytes(bytes, NAME_HEADER_SIZE, count * NAME_RECORD_SIZE)) return;
|
|
135
162
|
const records = [];
|
|
136
163
|
for (let i = 0; i < count; i++) {
|
|
@@ -138,9 +165,9 @@ function parseName(font) {
|
|
|
138
165
|
records.push({
|
|
139
166
|
platformId: u16(bytes, recordOffset),
|
|
140
167
|
encodingId: u16(bytes, recordOffset + 2),
|
|
141
|
-
nameId: u16(bytes, recordOffset +
|
|
142
|
-
length: u16(bytes, recordOffset +
|
|
143
|
-
stringOffset: storageOffset + u16(bytes, recordOffset +
|
|
168
|
+
nameId: u16(bytes, recordOffset + NAME_RECORD_NAME_ID_OFFSET),
|
|
169
|
+
length: u16(bytes, recordOffset + NAME_RECORD_LENGTH_OFFSET),
|
|
170
|
+
stringOffset: storageOffset + u16(bytes, recordOffset + NAME_RECORD_STRING_OFFSET_FIELD_OFFSET)
|
|
144
171
|
});
|
|
145
172
|
}
|
|
146
173
|
return {
|