pdf-parser.js 5.2.27 → 5.2.29
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 +2 -2
package/dist/gdef-table.cjs
CHANGED
|
@@ -10,13 +10,16 @@ const GLYPH_CLASS_COMPONENT = 4;
|
|
|
10
10
|
const GDEF_HEADER_SIZE_1_0 = 12;
|
|
11
11
|
const GDEF_HEADER_SIZE_1_2 = 14;
|
|
12
12
|
const MARK_GLYPH_SETS_HEADER_SIZE = 4;
|
|
13
|
+
const GDEF_GLYPH_CLASS_DEF_OFFSET = 4;
|
|
14
|
+
const GDEF_MARK_ATTACH_CLASS_DEF_OFFSET = 10;
|
|
15
|
+
const MARK_GLYPH_SETS_ENTRY_SIZE_BYTES = 4;
|
|
13
16
|
function parseGdefTable(font) {
|
|
14
17
|
const bytes = require_sfnt.sfntTableBytes(font, "GDEF");
|
|
15
18
|
if (bytes === void 0 || !require_sfnt.hasBytes(bytes, 0, GDEF_HEADER_SIZE_1_0) || require_sfnt.u16(bytes, 0) !== 1) return;
|
|
16
19
|
const minorVersion = require_sfnt.u16(bytes, 2);
|
|
17
|
-
const glyphClassDefOffset = require_sfnt.u16(bytes,
|
|
20
|
+
const glyphClassDefOffset = require_sfnt.u16(bytes, GDEF_GLYPH_CLASS_DEF_OFFSET);
|
|
18
21
|
const glyphClassDef = glyphClassDefOffset === 0 ? void 0 : require_ot_layout_common.parseClassDef(bytes, glyphClassDefOffset);
|
|
19
|
-
const markAttachClassDefOffset = require_sfnt.u16(bytes,
|
|
22
|
+
const markAttachClassDefOffset = require_sfnt.u16(bytes, GDEF_MARK_ATTACH_CLASS_DEF_OFFSET);
|
|
20
23
|
const markAttachClassDef = markAttachClassDefOffset === 0 ? void 0 : require_ot_layout_common.parseClassDef(bytes, markAttachClassDefOffset);
|
|
21
24
|
const markGlyphSets = [];
|
|
22
25
|
if (minorVersion >= 2 && require_sfnt.hasBytes(bytes, 0, GDEF_HEADER_SIZE_1_2)) {
|
|
@@ -24,7 +27,7 @@ function parseGdefTable(font) {
|
|
|
24
27
|
if (markGlyphSetsDefOffset !== 0 && require_sfnt.hasBytes(bytes, markGlyphSetsDefOffset, MARK_GLYPH_SETS_HEADER_SIZE) && require_sfnt.u16(bytes, markGlyphSetsDefOffset) === 1) {
|
|
25
28
|
const setCount = require_sfnt.u16(bytes, markGlyphSetsDefOffset + 2);
|
|
26
29
|
const coverageOffsetsOffset = markGlyphSetsDefOffset + MARK_GLYPH_SETS_HEADER_SIZE;
|
|
27
|
-
if (require_sfnt.hasBytes(bytes, coverageOffsetsOffset, setCount *
|
|
30
|
+
if (require_sfnt.hasBytes(bytes, coverageOffsetsOffset, setCount * MARK_GLYPH_SETS_ENTRY_SIZE_BYTES)) for (let i = 0; i < setCount; i++) markGlyphSets.push(require_ot_layout_common.parseCoverage(bytes, markGlyphSetsDefOffset + require_sfnt.u32(bytes, coverageOffsetsOffset + i * MARK_GLYPH_SETS_ENTRY_SIZE_BYTES)));
|
|
28
31
|
}
|
|
29
32
|
}
|
|
30
33
|
return {
|
package/dist/gdef-table.js
CHANGED
|
@@ -9,13 +9,16 @@ const GLYPH_CLASS_COMPONENT = 4;
|
|
|
9
9
|
const GDEF_HEADER_SIZE_1_0 = 12;
|
|
10
10
|
const GDEF_HEADER_SIZE_1_2 = 14;
|
|
11
11
|
const MARK_GLYPH_SETS_HEADER_SIZE = 4;
|
|
12
|
+
const GDEF_GLYPH_CLASS_DEF_OFFSET = 4;
|
|
13
|
+
const GDEF_MARK_ATTACH_CLASS_DEF_OFFSET = 10;
|
|
14
|
+
const MARK_GLYPH_SETS_ENTRY_SIZE_BYTES = 4;
|
|
12
15
|
function parseGdefTable(font) {
|
|
13
16
|
const bytes = sfntTableBytes(font, "GDEF");
|
|
14
17
|
if (bytes === void 0 || !hasBytes(bytes, 0, GDEF_HEADER_SIZE_1_0) || u16(bytes, 0) !== 1) return;
|
|
15
18
|
const minorVersion = u16(bytes, 2);
|
|
16
|
-
const glyphClassDefOffset = u16(bytes,
|
|
19
|
+
const glyphClassDefOffset = u16(bytes, GDEF_GLYPH_CLASS_DEF_OFFSET);
|
|
17
20
|
const glyphClassDef = glyphClassDefOffset === 0 ? void 0 : parseClassDef(bytes, glyphClassDefOffset);
|
|
18
|
-
const markAttachClassDefOffset = u16(bytes,
|
|
21
|
+
const markAttachClassDefOffset = u16(bytes, GDEF_MARK_ATTACH_CLASS_DEF_OFFSET);
|
|
19
22
|
const markAttachClassDef = markAttachClassDefOffset === 0 ? void 0 : parseClassDef(bytes, markAttachClassDefOffset);
|
|
20
23
|
const markGlyphSets = [];
|
|
21
24
|
if (minorVersion >= 2 && hasBytes(bytes, 0, GDEF_HEADER_SIZE_1_2)) {
|
|
@@ -23,7 +26,7 @@ function parseGdefTable(font) {
|
|
|
23
26
|
if (markGlyphSetsDefOffset !== 0 && hasBytes(bytes, markGlyphSetsDefOffset, MARK_GLYPH_SETS_HEADER_SIZE) && u16(bytes, markGlyphSetsDefOffset) === 1) {
|
|
24
27
|
const setCount = u16(bytes, markGlyphSetsDefOffset + 2);
|
|
25
28
|
const coverageOffsetsOffset = markGlyphSetsDefOffset + MARK_GLYPH_SETS_HEADER_SIZE;
|
|
26
|
-
if (hasBytes(bytes, coverageOffsetsOffset, setCount *
|
|
29
|
+
if (hasBytes(bytes, coverageOffsetsOffset, setCount * MARK_GLYPH_SETS_ENTRY_SIZE_BYTES)) for (let i = 0; i < setCount; i++) markGlyphSets.push(parseCoverage(bytes, markGlyphSetsDefOffset + u32(bytes, coverageOffsetsOffset + i * MARK_GLYPH_SETS_ENTRY_SIZE_BYTES)));
|
|
27
30
|
}
|
|
28
31
|
}
|
|
29
32
|
return {
|
package/dist/glyf-contours.cjs
CHANGED
|
@@ -8,6 +8,8 @@ const FLAG_REPEAT = 8;
|
|
|
8
8
|
const FLAG_X_SAME_OR_POSITIVE = 16;
|
|
9
9
|
const FLAG_Y_SAME_OR_POSITIVE = 32;
|
|
10
10
|
const MAX_COMPOSITE_DEPTH = 5;
|
|
11
|
+
const SCALED_COMPONENT_OFFSET = 2048;
|
|
12
|
+
const UNSCALED_COMPONENT_OFFSET = 4096;
|
|
11
13
|
function decodeSimpleContours(glyph) {
|
|
12
14
|
const numberOfContours = require_sfnt.i16(glyph, 0);
|
|
13
15
|
const endPtsOffset = 10;
|
|
@@ -87,7 +89,7 @@ function placeComponentContours(contours, component) {
|
|
|
87
89
|
0,
|
|
88
90
|
1
|
|
89
91
|
];
|
|
90
|
-
const scaledOffset = (component.flags &
|
|
92
|
+
const scaledOffset = (component.flags & SCALED_COMPONENT_OFFSET) !== 0 && (component.flags & UNSCALED_COMPONENT_OFFSET) === 0;
|
|
91
93
|
const dx = scaledOffset ? a * component.argument1 + c * component.argument2 : component.argument1;
|
|
92
94
|
const dy = scaledOffset ? b * component.argument1 + d * component.argument2 : component.argument2;
|
|
93
95
|
return contours.map((points) => points.map((point) => ({
|
package/dist/glyf-contours.js
CHANGED
|
@@ -7,6 +7,8 @@ const FLAG_REPEAT = 8;
|
|
|
7
7
|
const FLAG_X_SAME_OR_POSITIVE = 16;
|
|
8
8
|
const FLAG_Y_SAME_OR_POSITIVE = 32;
|
|
9
9
|
const MAX_COMPOSITE_DEPTH = 5;
|
|
10
|
+
const SCALED_COMPONENT_OFFSET = 2048;
|
|
11
|
+
const UNSCALED_COMPONENT_OFFSET = 4096;
|
|
10
12
|
function decodeSimpleContours(glyph) {
|
|
11
13
|
const numberOfContours = i16(glyph, 0);
|
|
12
14
|
const endPtsOffset = 10;
|
|
@@ -86,7 +88,7 @@ function placeComponentContours(contours, component) {
|
|
|
86
88
|
0,
|
|
87
89
|
1
|
|
88
90
|
];
|
|
89
|
-
const scaledOffset = (component.flags &
|
|
91
|
+
const scaledOffset = (component.flags & SCALED_COMPONENT_OFFSET) !== 0 && (component.flags & UNSCALED_COMPONENT_OFFSET) === 0;
|
|
90
92
|
const dx = scaledOffset ? a * component.argument1 + c * component.argument2 : component.argument1;
|
|
91
93
|
const dy = scaledOffset ? b * component.argument1 + d * component.argument2 : component.argument2;
|
|
92
94
|
return contours.map((points) => points.map((point) => ({
|
package/dist/glyf.cjs
CHANGED
|
@@ -16,6 +16,9 @@ function parseLoca(font, options) {
|
|
|
16
16
|
return offsets;
|
|
17
17
|
}
|
|
18
18
|
const GLYPH_HEADER_SIZE = 10;
|
|
19
|
+
const GLYPH_HEADER_Y_MIN_OFFSET = 4;
|
|
20
|
+
const GLYPH_HEADER_X_MAX_OFFSET = 6;
|
|
21
|
+
const GLYPH_HEADER_Y_MAX_OFFSET = 8;
|
|
19
22
|
const ARG_1_AND_2_ARE_WORDS = 1;
|
|
20
23
|
const ARGS_ARE_XY_VALUES = 2;
|
|
21
24
|
const WE_HAVE_A_SCALE = 8;
|
|
@@ -26,8 +29,16 @@ const SCALED_COMPONENT_OFFSET = 2048;
|
|
|
26
29
|
const UNSCALED_COMPONENT_OFFSET = 4096;
|
|
27
30
|
const MAX_COMPOSITE_DEPTH = 5;
|
|
28
31
|
const COMPONENT_RECORD_HEADER_SIZE = 4;
|
|
32
|
+
const X_AND_Y_SCALE_SIZE = 4;
|
|
33
|
+
const TWO_BY_TWO_SCALE10_OFFSET = 4;
|
|
34
|
+
const TWO_BY_TWO_Y_SCALE_OFFSET = 6;
|
|
35
|
+
const TWO_BY_TWO_SIZE = 8;
|
|
36
|
+
const WORD_ARGS_SIZE = 4;
|
|
37
|
+
const BYTE_ARGS_SIZE = 2;
|
|
38
|
+
const SIGNED_BYTE_SIGN_THRESHOLD = 128;
|
|
39
|
+
const SIGNED_BYTE_MODULUS = 256;
|
|
29
40
|
function signedByte(value) {
|
|
30
|
-
return value >=
|
|
41
|
+
return value >= SIGNED_BYTE_SIGN_THRESHOLD ? value - SIGNED_BYTE_MODULUS : value;
|
|
31
42
|
}
|
|
32
43
|
function readComponents(glyph) {
|
|
33
44
|
const components = [];
|
|
@@ -39,7 +50,7 @@ function readComponents(glyph) {
|
|
|
39
50
|
offset += COMPONENT_RECORD_HEADER_SIZE;
|
|
40
51
|
const argsAreWords = (flags & ARG_1_AND_2_ARE_WORDS) !== 0;
|
|
41
52
|
const argsAreXyValues = (flags & ARGS_ARE_XY_VALUES) !== 0;
|
|
42
|
-
const argsSize = argsAreWords ?
|
|
53
|
+
const argsSize = argsAreWords ? WORD_ARGS_SIZE : BYTE_ARGS_SIZE;
|
|
43
54
|
if (!require_sfnt.hasBytes(glyph, offset, argsSize)) return;
|
|
44
55
|
let argument1;
|
|
45
56
|
let argument2;
|
|
@@ -63,23 +74,23 @@ function readComponents(glyph) {
|
|
|
63
74
|
];
|
|
64
75
|
offset += 2;
|
|
65
76
|
} else if ((flags & WE_HAVE_AN_X_AND_Y_SCALE) !== 0) {
|
|
66
|
-
if (!require_sfnt.hasBytes(glyph, offset,
|
|
77
|
+
if (!require_sfnt.hasBytes(glyph, offset, X_AND_Y_SCALE_SIZE)) return;
|
|
67
78
|
transform = [
|
|
68
79
|
require_sfnt.f2dot14(glyph, offset),
|
|
69
80
|
0,
|
|
70
81
|
0,
|
|
71
82
|
require_sfnt.f2dot14(glyph, offset + 2)
|
|
72
83
|
];
|
|
73
|
-
offset +=
|
|
84
|
+
offset += X_AND_Y_SCALE_SIZE;
|
|
74
85
|
} else if ((flags & WE_HAVE_A_TWO_BY_TWO) !== 0) {
|
|
75
|
-
if (!require_sfnt.hasBytes(glyph, offset,
|
|
86
|
+
if (!require_sfnt.hasBytes(glyph, offset, TWO_BY_TWO_SIZE)) return;
|
|
76
87
|
transform = [
|
|
77
88
|
require_sfnt.f2dot14(glyph, offset),
|
|
78
89
|
require_sfnt.f2dot14(glyph, offset + 2),
|
|
79
|
-
require_sfnt.f2dot14(glyph, offset +
|
|
80
|
-
require_sfnt.f2dot14(glyph, offset +
|
|
90
|
+
require_sfnt.f2dot14(glyph, offset + TWO_BY_TWO_SCALE10_OFFSET),
|
|
91
|
+
require_sfnt.f2dot14(glyph, offset + TWO_BY_TWO_Y_SCALE_OFFSET)
|
|
81
92
|
];
|
|
82
|
-
offset +=
|
|
93
|
+
offset += TWO_BY_TWO_SIZE;
|
|
83
94
|
}
|
|
84
95
|
components.push({
|
|
85
96
|
flags,
|
|
@@ -134,9 +145,9 @@ function parseGlyf(font, options) {
|
|
|
134
145
|
return {
|
|
135
146
|
numberOfContours: require_sfnt.i16(glyph, 0),
|
|
136
147
|
xMin: require_sfnt.i16(glyph, 2),
|
|
137
|
-
yMin: require_sfnt.i16(glyph,
|
|
138
|
-
xMax: require_sfnt.i16(glyph,
|
|
139
|
-
yMax: require_sfnt.i16(glyph,
|
|
148
|
+
yMin: require_sfnt.i16(glyph, GLYPH_HEADER_Y_MIN_OFFSET),
|
|
149
|
+
xMax: require_sfnt.i16(glyph, GLYPH_HEADER_X_MAX_OFFSET),
|
|
150
|
+
yMax: require_sfnt.i16(glyph, GLYPH_HEADER_Y_MAX_OFFSET)
|
|
140
151
|
};
|
|
141
152
|
};
|
|
142
153
|
const compositeComponents = (glyphId) => {
|
package/dist/glyf.js
CHANGED
|
@@ -15,6 +15,9 @@ function parseLoca(font, options) {
|
|
|
15
15
|
return offsets;
|
|
16
16
|
}
|
|
17
17
|
const GLYPH_HEADER_SIZE = 10;
|
|
18
|
+
const GLYPH_HEADER_Y_MIN_OFFSET = 4;
|
|
19
|
+
const GLYPH_HEADER_X_MAX_OFFSET = 6;
|
|
20
|
+
const GLYPH_HEADER_Y_MAX_OFFSET = 8;
|
|
18
21
|
const ARG_1_AND_2_ARE_WORDS = 1;
|
|
19
22
|
const ARGS_ARE_XY_VALUES = 2;
|
|
20
23
|
const WE_HAVE_A_SCALE = 8;
|
|
@@ -25,8 +28,16 @@ const SCALED_COMPONENT_OFFSET = 2048;
|
|
|
25
28
|
const UNSCALED_COMPONENT_OFFSET = 4096;
|
|
26
29
|
const MAX_COMPOSITE_DEPTH = 5;
|
|
27
30
|
const COMPONENT_RECORD_HEADER_SIZE = 4;
|
|
31
|
+
const X_AND_Y_SCALE_SIZE = 4;
|
|
32
|
+
const TWO_BY_TWO_SCALE10_OFFSET = 4;
|
|
33
|
+
const TWO_BY_TWO_Y_SCALE_OFFSET = 6;
|
|
34
|
+
const TWO_BY_TWO_SIZE = 8;
|
|
35
|
+
const WORD_ARGS_SIZE = 4;
|
|
36
|
+
const BYTE_ARGS_SIZE = 2;
|
|
37
|
+
const SIGNED_BYTE_SIGN_THRESHOLD = 128;
|
|
38
|
+
const SIGNED_BYTE_MODULUS = 256;
|
|
28
39
|
function signedByte(value) {
|
|
29
|
-
return value >=
|
|
40
|
+
return value >= SIGNED_BYTE_SIGN_THRESHOLD ? value - SIGNED_BYTE_MODULUS : value;
|
|
30
41
|
}
|
|
31
42
|
function readComponents(glyph) {
|
|
32
43
|
const components = [];
|
|
@@ -38,7 +49,7 @@ function readComponents(glyph) {
|
|
|
38
49
|
offset += COMPONENT_RECORD_HEADER_SIZE;
|
|
39
50
|
const argsAreWords = (flags & ARG_1_AND_2_ARE_WORDS) !== 0;
|
|
40
51
|
const argsAreXyValues = (flags & ARGS_ARE_XY_VALUES) !== 0;
|
|
41
|
-
const argsSize = argsAreWords ?
|
|
52
|
+
const argsSize = argsAreWords ? WORD_ARGS_SIZE : BYTE_ARGS_SIZE;
|
|
42
53
|
if (!hasBytes(glyph, offset, argsSize)) return;
|
|
43
54
|
let argument1;
|
|
44
55
|
let argument2;
|
|
@@ -62,23 +73,23 @@ function readComponents(glyph) {
|
|
|
62
73
|
];
|
|
63
74
|
offset += 2;
|
|
64
75
|
} else if ((flags & WE_HAVE_AN_X_AND_Y_SCALE) !== 0) {
|
|
65
|
-
if (!hasBytes(glyph, offset,
|
|
76
|
+
if (!hasBytes(glyph, offset, X_AND_Y_SCALE_SIZE)) return;
|
|
66
77
|
transform = [
|
|
67
78
|
f2dot14(glyph, offset),
|
|
68
79
|
0,
|
|
69
80
|
0,
|
|
70
81
|
f2dot14(glyph, offset + 2)
|
|
71
82
|
];
|
|
72
|
-
offset +=
|
|
83
|
+
offset += X_AND_Y_SCALE_SIZE;
|
|
73
84
|
} else if ((flags & WE_HAVE_A_TWO_BY_TWO) !== 0) {
|
|
74
|
-
if (!hasBytes(glyph, offset,
|
|
85
|
+
if (!hasBytes(glyph, offset, TWO_BY_TWO_SIZE)) return;
|
|
75
86
|
transform = [
|
|
76
87
|
f2dot14(glyph, offset),
|
|
77
88
|
f2dot14(glyph, offset + 2),
|
|
78
|
-
f2dot14(glyph, offset +
|
|
79
|
-
f2dot14(glyph, offset +
|
|
89
|
+
f2dot14(glyph, offset + TWO_BY_TWO_SCALE10_OFFSET),
|
|
90
|
+
f2dot14(glyph, offset + TWO_BY_TWO_Y_SCALE_OFFSET)
|
|
80
91
|
];
|
|
81
|
-
offset +=
|
|
92
|
+
offset += TWO_BY_TWO_SIZE;
|
|
82
93
|
}
|
|
83
94
|
components.push({
|
|
84
95
|
flags,
|
|
@@ -133,9 +144,9 @@ function parseGlyf(font, options) {
|
|
|
133
144
|
return {
|
|
134
145
|
numberOfContours: i16(glyph, 0),
|
|
135
146
|
xMin: i16(glyph, 2),
|
|
136
|
-
yMin: i16(glyph,
|
|
137
|
-
xMax: i16(glyph,
|
|
138
|
-
yMax: i16(glyph,
|
|
147
|
+
yMin: i16(glyph, GLYPH_HEADER_Y_MIN_OFFSET),
|
|
148
|
+
xMax: i16(glyph, GLYPH_HEADER_X_MAX_OFFSET),
|
|
149
|
+
yMax: i16(glyph, GLYPH_HEADER_Y_MAX_OFFSET)
|
|
139
150
|
};
|
|
140
151
|
};
|
|
141
152
|
const compositeComponents = (glyphId) => {
|
package/dist/gpos-table.cjs
CHANGED
|
@@ -3,18 +3,27 @@ const require_sfnt = require("./sfnt.cjs");
|
|
|
3
3
|
const require_ot_layout_common = require("./ot-layout-common.cjs");
|
|
4
4
|
//#region src/gpos-table.ts
|
|
5
5
|
const GPOS_HEADER_SIZE = 10;
|
|
6
|
+
const GPOS_SCRIPT_LIST_OFFSET_FIELD = 4;
|
|
7
|
+
const GPOS_FEATURE_LIST_OFFSET_FIELD = 6;
|
|
8
|
+
const GPOS_LOOKUP_LIST_OFFSET_FIELD = 8;
|
|
6
9
|
const SCRIPT_RECORD_SIZE = 6;
|
|
10
|
+
const SCRIPT_RECORD_OFFSET_FIELD = 4;
|
|
7
11
|
const FEATURE_RECORD_SIZE = 6;
|
|
12
|
+
const FEATURE_RECORD_OFFSET_FIELD = 4;
|
|
8
13
|
const LANG_SYS_HEADER_SIZE = 6;
|
|
14
|
+
const LANG_SYS_FEATURE_INDEX_COUNT_FIELD = 4;
|
|
9
15
|
const FEATURE_HEADER_SIZE = 4;
|
|
10
16
|
const LOOKUP_HEADER_SIZE = 6;
|
|
17
|
+
const LOOKUP_SUB_TABLE_COUNT_FIELD = 4;
|
|
11
18
|
const EXTENSION_POS_HEADER_SIZE = 8;
|
|
19
|
+
const EXTENSION_POS_OFFSET_FIELD = 4;
|
|
12
20
|
const LOOKUP_TYPE_PAIR_POS = 2;
|
|
13
21
|
const LOOKUP_TYPE_EXTENSION_POS = 9;
|
|
14
22
|
const KERN_FEATURE_TAG = "kern";
|
|
15
23
|
const PREFERRED_SCRIPT_TAGS = ["latn", "DFLT"];
|
|
24
|
+
const TAG_LENGTH_BYTES = 4;
|
|
16
25
|
function readTag(bytes, offset) {
|
|
17
|
-
return String.fromCharCode(require_sfnt.u8(bytes, offset), require_sfnt.u8(bytes, offset + 1), require_sfnt.u8(bytes, offset + 2), require_sfnt.u8(bytes, offset +
|
|
26
|
+
return String.fromCharCode(require_sfnt.u8(bytes, offset), require_sfnt.u8(bytes, offset + 1), require_sfnt.u8(bytes, offset + 2), require_sfnt.u8(bytes, offset + TAG_LENGTH_BYTES - 1));
|
|
18
27
|
}
|
|
19
28
|
function valueRecordSize(valueFormat) {
|
|
20
29
|
let size = 0;
|
|
@@ -27,14 +36,17 @@ function xAdvanceOffset(valueFormat) {
|
|
|
27
36
|
return valueRecordSize(valueFormat & 3);
|
|
28
37
|
}
|
|
29
38
|
const PAIR_POS_FORMAT_1_HEADER_SIZE = 10;
|
|
39
|
+
const PAIR_POS_FORMAT_1_VALUE_FORMAT_1_FIELD = 4;
|
|
40
|
+
const PAIR_POS_FORMAT_1_VALUE_FORMAT_2_FIELD = 6;
|
|
41
|
+
const PAIR_POS_FORMAT_1_PAIR_SET_COUNT_FIELD = 8;
|
|
30
42
|
const PAIR_VALUE_RECORD_GLYPH_SIZE = 2;
|
|
31
43
|
function parsePairPosFormat1(bytes, subtableOffset) {
|
|
32
44
|
if (!require_sfnt.hasBytes(bytes, subtableOffset, PAIR_POS_FORMAT_1_HEADER_SIZE)) return;
|
|
33
45
|
const coverage = require_ot_layout_common.parseCoverage(bytes, subtableOffset + require_sfnt.u16(bytes, subtableOffset + 2));
|
|
34
46
|
if (coverage === void 0) return;
|
|
35
|
-
const valueFormat1 = require_sfnt.u16(bytes, subtableOffset +
|
|
36
|
-
const valueFormat2 = require_sfnt.u16(bytes, subtableOffset +
|
|
37
|
-
const pairSetCount = require_sfnt.u16(bytes, subtableOffset +
|
|
47
|
+
const valueFormat1 = require_sfnt.u16(bytes, subtableOffset + PAIR_POS_FORMAT_1_VALUE_FORMAT_1_FIELD);
|
|
48
|
+
const valueFormat2 = require_sfnt.u16(bytes, subtableOffset + PAIR_POS_FORMAT_1_VALUE_FORMAT_2_FIELD);
|
|
49
|
+
const pairSetCount = require_sfnt.u16(bytes, subtableOffset + PAIR_POS_FORMAT_1_PAIR_SET_COUNT_FIELD);
|
|
38
50
|
const pairSetOffsetsOffset = subtableOffset + PAIR_POS_FORMAT_1_HEADER_SIZE;
|
|
39
51
|
if (!require_sfnt.hasBytes(bytes, pairSetOffsetsOffset, pairSetCount * 2)) return;
|
|
40
52
|
const recordSize = PAIR_VALUE_RECORD_GLYPH_SIZE + valueRecordSize(valueFormat1) + valueRecordSize(valueFormat2);
|
|
@@ -60,16 +72,22 @@ function parsePairPosFormat1(bytes, subtableOffset) {
|
|
|
60
72
|
};
|
|
61
73
|
}
|
|
62
74
|
const PAIR_POS_FORMAT_2_HEADER_SIZE = 16;
|
|
75
|
+
const PAIR_POS_FORMAT_2_VALUE_FORMAT_1_FIELD = 4;
|
|
76
|
+
const PAIR_POS_FORMAT_2_VALUE_FORMAT_2_FIELD = 6;
|
|
77
|
+
const PAIR_POS_FORMAT_2_CLASS_DEF_1_FIELD = 8;
|
|
78
|
+
const PAIR_POS_FORMAT_2_CLASS_DEF_2_FIELD = 10;
|
|
79
|
+
const PAIR_POS_FORMAT_2_CLASS_1_COUNT_FIELD = 12;
|
|
80
|
+
const PAIR_POS_FORMAT_2_CLASS_2_COUNT_FIELD = 14;
|
|
63
81
|
function parsePairPosFormat2(bytes, subtableOffset) {
|
|
64
82
|
if (!require_sfnt.hasBytes(bytes, subtableOffset, PAIR_POS_FORMAT_2_HEADER_SIZE)) return;
|
|
65
83
|
const coverage = require_ot_layout_common.parseCoverage(bytes, subtableOffset + require_sfnt.u16(bytes, subtableOffset + 2));
|
|
66
|
-
const classDef1 = require_ot_layout_common.parseClassDef(bytes, subtableOffset + require_sfnt.u16(bytes, subtableOffset +
|
|
67
|
-
const classDef2 = require_ot_layout_common.parseClassDef(bytes, subtableOffset + require_sfnt.u16(bytes, subtableOffset +
|
|
84
|
+
const classDef1 = require_ot_layout_common.parseClassDef(bytes, subtableOffset + require_sfnt.u16(bytes, subtableOffset + PAIR_POS_FORMAT_2_CLASS_DEF_1_FIELD));
|
|
85
|
+
const classDef2 = require_ot_layout_common.parseClassDef(bytes, subtableOffset + require_sfnt.u16(bytes, subtableOffset + PAIR_POS_FORMAT_2_CLASS_DEF_2_FIELD));
|
|
68
86
|
if (coverage === void 0 || classDef1 === void 0 || classDef2 === void 0) return;
|
|
69
|
-
const valueFormat1 = require_sfnt.u16(bytes, subtableOffset +
|
|
70
|
-
const valueFormat2 = require_sfnt.u16(bytes, subtableOffset +
|
|
71
|
-
const class1Count = require_sfnt.u16(bytes, subtableOffset +
|
|
72
|
-
const class2Count = require_sfnt.u16(bytes, subtableOffset +
|
|
87
|
+
const valueFormat1 = require_sfnt.u16(bytes, subtableOffset + PAIR_POS_FORMAT_2_VALUE_FORMAT_1_FIELD);
|
|
88
|
+
const valueFormat2 = require_sfnt.u16(bytes, subtableOffset + PAIR_POS_FORMAT_2_VALUE_FORMAT_2_FIELD);
|
|
89
|
+
const class1Count = require_sfnt.u16(bytes, subtableOffset + PAIR_POS_FORMAT_2_CLASS_1_COUNT_FIELD);
|
|
90
|
+
const class2Count = require_sfnt.u16(bytes, subtableOffset + PAIR_POS_FORMAT_2_CLASS_2_COUNT_FIELD);
|
|
73
91
|
const class2RecordSize = valueRecordSize(valueFormat1) + valueRecordSize(valueFormat2);
|
|
74
92
|
const class1RecordSize = class2Count * class2RecordSize;
|
|
75
93
|
const matrixOffset = subtableOffset + PAIR_POS_FORMAT_2_HEADER_SIZE;
|
|
@@ -89,7 +107,7 @@ function parseSubtable(bytes, lookupType, subtableOffset) {
|
|
|
89
107
|
if (!require_sfnt.hasBytes(bytes, subtableOffset, EXTENSION_POS_HEADER_SIZE) || require_sfnt.u16(bytes, subtableOffset) !== 1) return;
|
|
90
108
|
const extensionLookupType = require_sfnt.u16(bytes, subtableOffset + 2);
|
|
91
109
|
if (extensionLookupType === LOOKUP_TYPE_EXTENSION_POS) return;
|
|
92
|
-
return parseSubtable(bytes, extensionLookupType, subtableOffset + require_sfnt.u32(bytes, subtableOffset +
|
|
110
|
+
return parseSubtable(bytes, extensionLookupType, subtableOffset + require_sfnt.u32(bytes, subtableOffset + EXTENSION_POS_OFFSET_FIELD));
|
|
93
111
|
}
|
|
94
112
|
if (lookupType !== LOOKUP_TYPE_PAIR_POS) return;
|
|
95
113
|
if (!require_sfnt.hasBytes(bytes, subtableOffset, 2)) return;
|
|
@@ -100,7 +118,7 @@ function parseSubtable(bytes, lookupType, subtableOffset) {
|
|
|
100
118
|
function parseLookupSubtables(bytes, lookupOffset) {
|
|
101
119
|
if (!require_sfnt.hasBytes(bytes, lookupOffset, LOOKUP_HEADER_SIZE)) return [];
|
|
102
120
|
const lookupType = require_sfnt.u16(bytes, lookupOffset);
|
|
103
|
-
const subTableCount = require_sfnt.u16(bytes, lookupOffset +
|
|
121
|
+
const subTableCount = require_sfnt.u16(bytes, lookupOffset + LOOKUP_SUB_TABLE_COUNT_FIELD);
|
|
104
122
|
const offsetsOffset = lookupOffset + LOOKUP_HEADER_SIZE;
|
|
105
123
|
if (!require_sfnt.hasBytes(bytes, offsetsOffset, subTableCount * 2)) return [];
|
|
106
124
|
const subtables = [];
|
|
@@ -116,7 +134,7 @@ function parseDefaultLangSysFeatureIndices(bytes, scriptOffset) {
|
|
|
116
134
|
if (defaultLangSysOffset === 0) return [];
|
|
117
135
|
const langSysOffset = scriptOffset + defaultLangSysOffset;
|
|
118
136
|
if (!require_sfnt.hasBytes(bytes, langSysOffset, LANG_SYS_HEADER_SIZE)) return [];
|
|
119
|
-
const featureIndexCount = require_sfnt.u16(bytes, langSysOffset +
|
|
137
|
+
const featureIndexCount = require_sfnt.u16(bytes, langSysOffset + LANG_SYS_FEATURE_INDEX_COUNT_FIELD);
|
|
120
138
|
const indicesOffset = langSysOffset + LANG_SYS_HEADER_SIZE;
|
|
121
139
|
if (!require_sfnt.hasBytes(bytes, indicesOffset, featureIndexCount * 2)) return [];
|
|
122
140
|
const indices = [];
|
|
@@ -130,9 +148,9 @@ function findScriptOffset(bytes, scriptListOffset) {
|
|
|
130
148
|
if (!require_sfnt.hasBytes(bytes, recordsOffset, scriptCount * SCRIPT_RECORD_SIZE) || scriptCount === 0) return;
|
|
131
149
|
for (const wanted of PREFERRED_SCRIPT_TAGS) for (let i = 0; i < scriptCount; i++) {
|
|
132
150
|
const recordOffset = recordsOffset + i * SCRIPT_RECORD_SIZE;
|
|
133
|
-
if (readTag(bytes, recordOffset) === wanted) return scriptListOffset + require_sfnt.u16(bytes, recordOffset +
|
|
151
|
+
if (readTag(bytes, recordOffset) === wanted) return scriptListOffset + require_sfnt.u16(bytes, recordOffset + SCRIPT_RECORD_OFFSET_FIELD);
|
|
134
152
|
}
|
|
135
|
-
return scriptListOffset + require_sfnt.u16(bytes, recordsOffset +
|
|
153
|
+
return scriptListOffset + require_sfnt.u16(bytes, recordsOffset + SCRIPT_RECORD_OFFSET_FIELD);
|
|
136
154
|
}
|
|
137
155
|
function collectKernLookupIndices(bytes, featureListOffset, featureIndices) {
|
|
138
156
|
if (!require_sfnt.hasBytes(bytes, featureListOffset, 2)) return [];
|
|
@@ -145,7 +163,7 @@ function collectKernLookupIndices(bytes, featureListOffset, featureIndices) {
|
|
|
145
163
|
if (featureIndex >= featureCount) continue;
|
|
146
164
|
const recordOffset = recordsOffset + featureIndex * FEATURE_RECORD_SIZE;
|
|
147
165
|
if (readTag(bytes, recordOffset) !== KERN_FEATURE_TAG) continue;
|
|
148
|
-
const featureOffset = featureListOffset + require_sfnt.u16(bytes, recordOffset +
|
|
166
|
+
const featureOffset = featureListOffset + require_sfnt.u16(bytes, recordOffset + FEATURE_RECORD_OFFSET_FIELD);
|
|
149
167
|
if (!require_sfnt.hasBytes(bytes, featureOffset, FEATURE_HEADER_SIZE)) continue;
|
|
150
168
|
const lookupIndexCount = require_sfnt.u16(bytes, featureOffset + 2);
|
|
151
169
|
const indicesOffset = featureOffset + FEATURE_HEADER_SIZE;
|
|
@@ -163,11 +181,11 @@ function collectKernLookupIndices(bytes, featureListOffset, featureIndices) {
|
|
|
163
181
|
function buildGposKernLookup(font) {
|
|
164
182
|
const bytes = require_sfnt.sfntTableBytes(font, "GPOS");
|
|
165
183
|
if (bytes === void 0 || !require_sfnt.hasBytes(bytes, 0, GPOS_HEADER_SIZE) || require_sfnt.u16(bytes, 0) !== 1) return;
|
|
166
|
-
const scriptOffset = findScriptOffset(bytes, require_sfnt.u16(bytes,
|
|
184
|
+
const scriptOffset = findScriptOffset(bytes, require_sfnt.u16(bytes, GPOS_SCRIPT_LIST_OFFSET_FIELD));
|
|
167
185
|
if (scriptOffset === void 0) return;
|
|
168
|
-
const lookupIndices = collectKernLookupIndices(bytes, require_sfnt.u16(bytes,
|
|
186
|
+
const lookupIndices = collectKernLookupIndices(bytes, require_sfnt.u16(bytes, GPOS_FEATURE_LIST_OFFSET_FIELD), parseDefaultLangSysFeatureIndices(bytes, scriptOffset));
|
|
169
187
|
if (lookupIndices.length === 0) return;
|
|
170
|
-
const lookupListOffset = require_sfnt.u16(bytes,
|
|
188
|
+
const lookupListOffset = require_sfnt.u16(bytes, GPOS_LOOKUP_LIST_OFFSET_FIELD);
|
|
171
189
|
if (!require_sfnt.hasBytes(bytes, lookupListOffset, 2)) return;
|
|
172
190
|
const lookupCount = require_sfnt.u16(bytes, lookupListOffset);
|
|
173
191
|
const lookupOffsetsOffset = lookupListOffset + 2;
|
package/dist/gpos-table.js
CHANGED
|
@@ -2,18 +2,27 @@ import { hasBytes, i16, sfntTableBytes, u16, u32, u8 } from "./sfnt.js";
|
|
|
2
2
|
import { parseClassDef, parseCoverage } from "./ot-layout-common.js";
|
|
3
3
|
//#region src/gpos-table.ts
|
|
4
4
|
const GPOS_HEADER_SIZE = 10;
|
|
5
|
+
const GPOS_SCRIPT_LIST_OFFSET_FIELD = 4;
|
|
6
|
+
const GPOS_FEATURE_LIST_OFFSET_FIELD = 6;
|
|
7
|
+
const GPOS_LOOKUP_LIST_OFFSET_FIELD = 8;
|
|
5
8
|
const SCRIPT_RECORD_SIZE = 6;
|
|
9
|
+
const SCRIPT_RECORD_OFFSET_FIELD = 4;
|
|
6
10
|
const FEATURE_RECORD_SIZE = 6;
|
|
11
|
+
const FEATURE_RECORD_OFFSET_FIELD = 4;
|
|
7
12
|
const LANG_SYS_HEADER_SIZE = 6;
|
|
13
|
+
const LANG_SYS_FEATURE_INDEX_COUNT_FIELD = 4;
|
|
8
14
|
const FEATURE_HEADER_SIZE = 4;
|
|
9
15
|
const LOOKUP_HEADER_SIZE = 6;
|
|
16
|
+
const LOOKUP_SUB_TABLE_COUNT_FIELD = 4;
|
|
10
17
|
const EXTENSION_POS_HEADER_SIZE = 8;
|
|
18
|
+
const EXTENSION_POS_OFFSET_FIELD = 4;
|
|
11
19
|
const LOOKUP_TYPE_PAIR_POS = 2;
|
|
12
20
|
const LOOKUP_TYPE_EXTENSION_POS = 9;
|
|
13
21
|
const KERN_FEATURE_TAG = "kern";
|
|
14
22
|
const PREFERRED_SCRIPT_TAGS = ["latn", "DFLT"];
|
|
23
|
+
const TAG_LENGTH_BYTES = 4;
|
|
15
24
|
function readTag(bytes, offset) {
|
|
16
|
-
return String.fromCharCode(u8(bytes, offset), u8(bytes, offset + 1), u8(bytes, offset + 2), u8(bytes, offset +
|
|
25
|
+
return String.fromCharCode(u8(bytes, offset), u8(bytes, offset + 1), u8(bytes, offset + 2), u8(bytes, offset + TAG_LENGTH_BYTES - 1));
|
|
17
26
|
}
|
|
18
27
|
function valueRecordSize(valueFormat) {
|
|
19
28
|
let size = 0;
|
|
@@ -26,14 +35,17 @@ function xAdvanceOffset(valueFormat) {
|
|
|
26
35
|
return valueRecordSize(valueFormat & 3);
|
|
27
36
|
}
|
|
28
37
|
const PAIR_POS_FORMAT_1_HEADER_SIZE = 10;
|
|
38
|
+
const PAIR_POS_FORMAT_1_VALUE_FORMAT_1_FIELD = 4;
|
|
39
|
+
const PAIR_POS_FORMAT_1_VALUE_FORMAT_2_FIELD = 6;
|
|
40
|
+
const PAIR_POS_FORMAT_1_PAIR_SET_COUNT_FIELD = 8;
|
|
29
41
|
const PAIR_VALUE_RECORD_GLYPH_SIZE = 2;
|
|
30
42
|
function parsePairPosFormat1(bytes, subtableOffset) {
|
|
31
43
|
if (!hasBytes(bytes, subtableOffset, PAIR_POS_FORMAT_1_HEADER_SIZE)) return;
|
|
32
44
|
const coverage = parseCoverage(bytes, subtableOffset + u16(bytes, subtableOffset + 2));
|
|
33
45
|
if (coverage === void 0) return;
|
|
34
|
-
const valueFormat1 = u16(bytes, subtableOffset +
|
|
35
|
-
const valueFormat2 = u16(bytes, subtableOffset +
|
|
36
|
-
const pairSetCount = u16(bytes, subtableOffset +
|
|
46
|
+
const valueFormat1 = u16(bytes, subtableOffset + PAIR_POS_FORMAT_1_VALUE_FORMAT_1_FIELD);
|
|
47
|
+
const valueFormat2 = u16(bytes, subtableOffset + PAIR_POS_FORMAT_1_VALUE_FORMAT_2_FIELD);
|
|
48
|
+
const pairSetCount = u16(bytes, subtableOffset + PAIR_POS_FORMAT_1_PAIR_SET_COUNT_FIELD);
|
|
37
49
|
const pairSetOffsetsOffset = subtableOffset + PAIR_POS_FORMAT_1_HEADER_SIZE;
|
|
38
50
|
if (!hasBytes(bytes, pairSetOffsetsOffset, pairSetCount * 2)) return;
|
|
39
51
|
const recordSize = PAIR_VALUE_RECORD_GLYPH_SIZE + valueRecordSize(valueFormat1) + valueRecordSize(valueFormat2);
|
|
@@ -59,16 +71,22 @@ function parsePairPosFormat1(bytes, subtableOffset) {
|
|
|
59
71
|
};
|
|
60
72
|
}
|
|
61
73
|
const PAIR_POS_FORMAT_2_HEADER_SIZE = 16;
|
|
74
|
+
const PAIR_POS_FORMAT_2_VALUE_FORMAT_1_FIELD = 4;
|
|
75
|
+
const PAIR_POS_FORMAT_2_VALUE_FORMAT_2_FIELD = 6;
|
|
76
|
+
const PAIR_POS_FORMAT_2_CLASS_DEF_1_FIELD = 8;
|
|
77
|
+
const PAIR_POS_FORMAT_2_CLASS_DEF_2_FIELD = 10;
|
|
78
|
+
const PAIR_POS_FORMAT_2_CLASS_1_COUNT_FIELD = 12;
|
|
79
|
+
const PAIR_POS_FORMAT_2_CLASS_2_COUNT_FIELD = 14;
|
|
62
80
|
function parsePairPosFormat2(bytes, subtableOffset) {
|
|
63
81
|
if (!hasBytes(bytes, subtableOffset, PAIR_POS_FORMAT_2_HEADER_SIZE)) return;
|
|
64
82
|
const coverage = parseCoverage(bytes, subtableOffset + u16(bytes, subtableOffset + 2));
|
|
65
|
-
const classDef1 = parseClassDef(bytes, subtableOffset + u16(bytes, subtableOffset +
|
|
66
|
-
const classDef2 = parseClassDef(bytes, subtableOffset + u16(bytes, subtableOffset +
|
|
83
|
+
const classDef1 = parseClassDef(bytes, subtableOffset + u16(bytes, subtableOffset + PAIR_POS_FORMAT_2_CLASS_DEF_1_FIELD));
|
|
84
|
+
const classDef2 = parseClassDef(bytes, subtableOffset + u16(bytes, subtableOffset + PAIR_POS_FORMAT_2_CLASS_DEF_2_FIELD));
|
|
67
85
|
if (coverage === void 0 || classDef1 === void 0 || classDef2 === void 0) return;
|
|
68
|
-
const valueFormat1 = u16(bytes, subtableOffset +
|
|
69
|
-
const valueFormat2 = u16(bytes, subtableOffset +
|
|
70
|
-
const class1Count = u16(bytes, subtableOffset +
|
|
71
|
-
const class2Count = u16(bytes, subtableOffset +
|
|
86
|
+
const valueFormat1 = u16(bytes, subtableOffset + PAIR_POS_FORMAT_2_VALUE_FORMAT_1_FIELD);
|
|
87
|
+
const valueFormat2 = u16(bytes, subtableOffset + PAIR_POS_FORMAT_2_VALUE_FORMAT_2_FIELD);
|
|
88
|
+
const class1Count = u16(bytes, subtableOffset + PAIR_POS_FORMAT_2_CLASS_1_COUNT_FIELD);
|
|
89
|
+
const class2Count = u16(bytes, subtableOffset + PAIR_POS_FORMAT_2_CLASS_2_COUNT_FIELD);
|
|
72
90
|
const class2RecordSize = valueRecordSize(valueFormat1) + valueRecordSize(valueFormat2);
|
|
73
91
|
const class1RecordSize = class2Count * class2RecordSize;
|
|
74
92
|
const matrixOffset = subtableOffset + PAIR_POS_FORMAT_2_HEADER_SIZE;
|
|
@@ -88,7 +106,7 @@ function parseSubtable(bytes, lookupType, subtableOffset) {
|
|
|
88
106
|
if (!hasBytes(bytes, subtableOffset, EXTENSION_POS_HEADER_SIZE) || u16(bytes, subtableOffset) !== 1) return;
|
|
89
107
|
const extensionLookupType = u16(bytes, subtableOffset + 2);
|
|
90
108
|
if (extensionLookupType === LOOKUP_TYPE_EXTENSION_POS) return;
|
|
91
|
-
return parseSubtable(bytes, extensionLookupType, subtableOffset + u32(bytes, subtableOffset +
|
|
109
|
+
return parseSubtable(bytes, extensionLookupType, subtableOffset + u32(bytes, subtableOffset + EXTENSION_POS_OFFSET_FIELD));
|
|
92
110
|
}
|
|
93
111
|
if (lookupType !== LOOKUP_TYPE_PAIR_POS) return;
|
|
94
112
|
if (!hasBytes(bytes, subtableOffset, 2)) return;
|
|
@@ -99,7 +117,7 @@ function parseSubtable(bytes, lookupType, subtableOffset) {
|
|
|
99
117
|
function parseLookupSubtables(bytes, lookupOffset) {
|
|
100
118
|
if (!hasBytes(bytes, lookupOffset, LOOKUP_HEADER_SIZE)) return [];
|
|
101
119
|
const lookupType = u16(bytes, lookupOffset);
|
|
102
|
-
const subTableCount = u16(bytes, lookupOffset +
|
|
120
|
+
const subTableCount = u16(bytes, lookupOffset + LOOKUP_SUB_TABLE_COUNT_FIELD);
|
|
103
121
|
const offsetsOffset = lookupOffset + LOOKUP_HEADER_SIZE;
|
|
104
122
|
if (!hasBytes(bytes, offsetsOffset, subTableCount * 2)) return [];
|
|
105
123
|
const subtables = [];
|
|
@@ -115,7 +133,7 @@ function parseDefaultLangSysFeatureIndices(bytes, scriptOffset) {
|
|
|
115
133
|
if (defaultLangSysOffset === 0) return [];
|
|
116
134
|
const langSysOffset = scriptOffset + defaultLangSysOffset;
|
|
117
135
|
if (!hasBytes(bytes, langSysOffset, LANG_SYS_HEADER_SIZE)) return [];
|
|
118
|
-
const featureIndexCount = u16(bytes, langSysOffset +
|
|
136
|
+
const featureIndexCount = u16(bytes, langSysOffset + LANG_SYS_FEATURE_INDEX_COUNT_FIELD);
|
|
119
137
|
const indicesOffset = langSysOffset + LANG_SYS_HEADER_SIZE;
|
|
120
138
|
if (!hasBytes(bytes, indicesOffset, featureIndexCount * 2)) return [];
|
|
121
139
|
const indices = [];
|
|
@@ -129,9 +147,9 @@ function findScriptOffset(bytes, scriptListOffset) {
|
|
|
129
147
|
if (!hasBytes(bytes, recordsOffset, scriptCount * SCRIPT_RECORD_SIZE) || scriptCount === 0) return;
|
|
130
148
|
for (const wanted of PREFERRED_SCRIPT_TAGS) for (let i = 0; i < scriptCount; i++) {
|
|
131
149
|
const recordOffset = recordsOffset + i * SCRIPT_RECORD_SIZE;
|
|
132
|
-
if (readTag(bytes, recordOffset) === wanted) return scriptListOffset + u16(bytes, recordOffset +
|
|
150
|
+
if (readTag(bytes, recordOffset) === wanted) return scriptListOffset + u16(bytes, recordOffset + SCRIPT_RECORD_OFFSET_FIELD);
|
|
133
151
|
}
|
|
134
|
-
return scriptListOffset + u16(bytes, recordsOffset +
|
|
152
|
+
return scriptListOffset + u16(bytes, recordsOffset + SCRIPT_RECORD_OFFSET_FIELD);
|
|
135
153
|
}
|
|
136
154
|
function collectKernLookupIndices(bytes, featureListOffset, featureIndices) {
|
|
137
155
|
if (!hasBytes(bytes, featureListOffset, 2)) return [];
|
|
@@ -144,7 +162,7 @@ function collectKernLookupIndices(bytes, featureListOffset, featureIndices) {
|
|
|
144
162
|
if (featureIndex >= featureCount) continue;
|
|
145
163
|
const recordOffset = recordsOffset + featureIndex * FEATURE_RECORD_SIZE;
|
|
146
164
|
if (readTag(bytes, recordOffset) !== KERN_FEATURE_TAG) continue;
|
|
147
|
-
const featureOffset = featureListOffset + u16(bytes, recordOffset +
|
|
165
|
+
const featureOffset = featureListOffset + u16(bytes, recordOffset + FEATURE_RECORD_OFFSET_FIELD);
|
|
148
166
|
if (!hasBytes(bytes, featureOffset, FEATURE_HEADER_SIZE)) continue;
|
|
149
167
|
const lookupIndexCount = u16(bytes, featureOffset + 2);
|
|
150
168
|
const indicesOffset = featureOffset + FEATURE_HEADER_SIZE;
|
|
@@ -162,11 +180,11 @@ function collectKernLookupIndices(bytes, featureListOffset, featureIndices) {
|
|
|
162
180
|
function buildGposKernLookup(font) {
|
|
163
181
|
const bytes = sfntTableBytes(font, "GPOS");
|
|
164
182
|
if (bytes === void 0 || !hasBytes(bytes, 0, GPOS_HEADER_SIZE) || u16(bytes, 0) !== 1) return;
|
|
165
|
-
const scriptOffset = findScriptOffset(bytes, u16(bytes,
|
|
183
|
+
const scriptOffset = findScriptOffset(bytes, u16(bytes, GPOS_SCRIPT_LIST_OFFSET_FIELD));
|
|
166
184
|
if (scriptOffset === void 0) return;
|
|
167
|
-
const lookupIndices = collectKernLookupIndices(bytes, u16(bytes,
|
|
185
|
+
const lookupIndices = collectKernLookupIndices(bytes, u16(bytes, GPOS_FEATURE_LIST_OFFSET_FIELD), parseDefaultLangSysFeatureIndices(bytes, scriptOffset));
|
|
168
186
|
if (lookupIndices.length === 0) return;
|
|
169
|
-
const lookupListOffset = u16(bytes,
|
|
187
|
+
const lookupListOffset = u16(bytes, GPOS_LOOKUP_LIST_OFFSET_FIELD);
|
|
170
188
|
if (!hasBytes(bytes, lookupListOffset, 2)) return;
|
|
171
189
|
const lookupCount = u16(bytes, lookupListOffset);
|
|
172
190
|
const lookupOffsetsOffset = lookupListOffset + 2;
|