@cantoo/fontkit 2.0.4 → 2.0.6
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/browser-module.mjs +4448 -1142
- package/dist/browser-module.mjs.map +1 -1
- package/dist/browser.cjs +4449 -1142
- package/dist/browser.cjs.map +1 -1
- package/dist/main.cjs +4449 -1142
- package/dist/main.cjs.map +1 -1
- package/dist/module.mjs +4448 -1142
- package/dist/module.mjs.map +1 -1
- package/package.json +4 -1
- package/src/CmapProcessor.js +60 -21
- package/src/DFont.js +114 -14
- package/src/TTFFont.js +260 -62
- package/src/TrueTypeCollection.js +59 -15
- package/src/WOFF2Font.js +128 -22
- package/src/WOFFFont.js +45 -8
- package/src/aat/AATFeatureMap.js +83 -40
- package/src/aat/AATLayoutEngine.js +34 -2
- package/src/aat/AATLookupTable.js +24 -6
- package/src/aat/AATMorxProcessor.js +202 -65
- package/src/aat/AATStateMachine.js +35 -3
- package/src/base.js +20 -1
- package/src/cff/CFFCharsets.js +3 -0
- package/src/cff/CFFDict.js +81 -11
- package/src/cff/CFFEncodings.js +2 -0
- package/src/cff/CFFFont.js +120 -24
- package/src/cff/CFFIndex.js +66 -9
- package/src/cff/CFFOperand.js +53 -28
- package/src/cff/CFFPointer.js +41 -2
- package/src/cff/CFFPrivateDict.js +34 -24
- package/src/cff/CFFStandardStrings.js +68 -67
- package/src/cff/CFFTop.js +161 -68
- package/src/decorators.js +34 -15
- package/src/encodings.js +133 -116
- package/src/fs.js +10 -0
- package/src/glyph/BBox.js +14 -0
- package/src/glyph/CFFGlyph.js +293 -152
- package/src/glyph/COLRGlyph.js +40 -5
- package/src/glyph/Glyph.js +72 -13
- package/src/glyph/GlyphVariationProcessor.js +158 -62
- package/src/glyph/Path.js +119 -32
- package/src/glyph/SBIXGlyph.js +57 -8
- package/src/glyph/StandardNames.js +1 -0
- package/src/glyph/TTFGlyph.js +203 -63
- package/src/glyph/TTFGlyphEncoder.js +58 -26
- package/src/glyph/WOFF2Glyph.js +25 -6
- package/src/layout/GlyphPosition.js +6 -0
- package/src/layout/GlyphRun.js +28 -10
- package/src/layout/KernProcessor.js +63 -4
- package/src/layout/LayoutEngine.js +99 -26
- package/src/layout/Script.js +52 -26
- package/src/layout/UnicodeLayoutEngine.js +34 -10
- package/src/opentype/GPOSProcessor.js +156 -45
- package/src/opentype/GSUBProcessor.js +92 -33
- package/src/opentype/GlyphInfo.js +53 -5
- package/src/opentype/GlyphIterator.js +51 -2
- package/src/opentype/OTLayoutEngine.js +66 -8
- package/src/opentype/OTProcessor.js +284 -71
- package/src/opentype/ShapingPlan.js +52 -5
- package/src/opentype/shapers/ArabicShaper.js +27 -8
- package/src/opentype/shapers/DefaultShaper.js +54 -10
- package/src/opentype/shapers/HangulShaper.js +120 -42
- package/src/opentype/shapers/HebrewShaper.js +50 -16
- package/src/opentype/shapers/IndicShaper.js +159 -44
- package/src/opentype/shapers/ThaiShaper.js +50 -19
- package/src/opentype/shapers/UniversalShaper.js +83 -17
- package/src/opentype/shapers/index.js +48 -35
- package/src/opentype/shapers/indic-data.js +2 -2
- package/src/packages/unicode-properties/data-trie.js +2 -1
- package/src/packages/unicode-properties/data.js +13 -1
- package/src/packages/unicode-properties/dist/index.cjs +23 -10
- package/src/packages/unicode-properties/dist/index.cjs.map +2 -2
- package/src/packages/unicode-properties/dist/index.mjs +22 -10
- package/src/packages/unicode-properties/dist/index.mjs.map +2 -2
- package/src/packages/unicode-properties/generate.js +3 -4
- package/src/packages/unicode-properties/index.js +95 -30
- package/src/packages/unicode-properties/package.json +1 -1
- package/src/packages/unicode-trie/builder.js +146 -29
- package/src/packages/unicode-trie/dist/builder.cjs +135 -25
- package/src/packages/unicode-trie/dist/builder.cjs.map +2 -2
- package/src/packages/unicode-trie/dist/builder.mjs +134 -25
- package/src/packages/unicode-trie/dist/builder.mjs.map +2 -2
- package/src/packages/unicode-trie/dist/index.cjs +22 -9
- package/src/packages/unicode-trie/dist/index.cjs.map +2 -2
- package/src/packages/unicode-trie/dist/index.mjs +21 -9
- package/src/packages/unicode-trie/dist/index.mjs.map +2 -2
- package/src/packages/unicode-trie/index.js +63 -12
- package/src/packages/unicode-trie/package.json +1 -1
- package/src/packages/unicode-trie/swap.js +15 -2
- package/src/subset/CFFSubset.js +112 -22
- package/src/subset/Subset.js +23 -3
- package/src/subset/TTFSubset.js +84 -41
- package/src/tables/BASE.js +28 -27
- package/src/tables/COLR.js +10 -9
- package/src/tables/CPAL.js +2 -1
- package/src/tables/DSIG.js +8 -7
- package/src/tables/EBDT.js +10 -4
- package/src/tables/EBLC.js +70 -10
- package/src/tables/GDEF.js +18 -17
- package/src/tables/GPOS.js +153 -90
- package/src/tables/GSUB.js +50 -39
- package/src/tables/HVAR.js +51 -5
- package/src/tables/JSTF.js +17 -16
- package/src/tables/LTSH.js +4 -3
- package/src/tables/OS2.js +50 -49
- package/src/tables/PCLT.js +16 -15
- package/src/tables/STAT.js +46 -6
- package/src/tables/VDMX.js +18 -17
- package/src/tables/VORG.js +8 -7
- package/src/tables/WOFF2Directory.js +57 -9
- package/src/tables/WOFFDirectory.js +32 -20
- package/src/tables/aat.js +160 -35
- package/src/tables/avar.js +1 -0
- package/src/tables/bsln.js +3 -2
- package/src/tables/cmap.js +83 -63
- package/src/tables/cvt.js +1 -0
- package/src/tables/directory.js +56 -28
- package/src/tables/feat.js +24 -2
- package/src/tables/fpgm.js +1 -0
- package/src/tables/fvar.js +32 -4
- package/src/tables/gasp.js +6 -5
- package/src/tables/glyf.js +2 -1
- package/src/tables/gvar.js +29 -2
- package/src/tables/hdmx.js +18 -7
- package/src/tables/head.js +17 -16
- package/src/tables/hhea.js +15 -14
- package/src/tables/hmtx.js +18 -2
- package/src/tables/index.js +1 -5
- package/src/tables/just.js +15 -4
- package/src/tables/kern.js +84 -47
- package/src/tables/loca.js +23 -10
- package/src/tables/maxp.js +16 -15
- package/src/tables/morx.js +27 -20
- package/src/tables/name.js +120 -39
- package/src/tables/opbd.js +2 -1
- package/src/tables/opentype.js +126 -91
- package/src/tables/post.js +18 -11
- package/src/tables/prep.js +1 -0
- package/src/tables/sbix.js +12 -1
- package/src/tables/variations.js +29 -9
- package/src/tables/vhea.js +15 -14
- package/src/tables/vmtx.js +20 -4
- package/src/utils.js +15 -0
package/src/subset/Subset.js
CHANGED
|
@@ -1,22 +1,37 @@
|
|
|
1
1
|
import Tables from '../tables';
|
|
2
2
|
|
|
3
|
+
/** @typedef {import('../../types/fontkit').SubsetFont} SubsetFont */
|
|
4
|
+
/** @typedef {import('../../types/fontkit').SubsetGlyph} SubsetGlyph */
|
|
5
|
+
/** @typedef {import('../../types/fontkit').TableCodec} TableCodec */
|
|
6
|
+
|
|
3
7
|
// Tables written by TTFSubset.encode; must not be overwritten via includeTable.
|
|
4
8
|
const MANAGED_TTF_TABLES = [
|
|
5
9
|
'head', 'hhea', 'loca', 'maxp', 'cvt ', 'prep', 'glyf', 'hmtx', 'fpgm'
|
|
6
10
|
];
|
|
7
11
|
|
|
8
12
|
export default class Subset {
|
|
13
|
+
/**
|
|
14
|
+
* @param {SubsetFont} font
|
|
15
|
+
*/
|
|
9
16
|
constructor(font) {
|
|
17
|
+
/** @type {SubsetFont} */
|
|
10
18
|
this.font = font;
|
|
19
|
+
/** @type {number[]} */
|
|
11
20
|
this.glyphs = [];
|
|
21
|
+
/** @type {Record<number, number>} */
|
|
12
22
|
this.mapping = {};
|
|
13
23
|
// Extra OT table tags to copy into a TTF subset (e.g. 'OS/2', 'name', 'post').
|
|
24
|
+
/** @type {string[]} */
|
|
14
25
|
this.includedTables = [];
|
|
15
26
|
|
|
16
27
|
// always include the missing glyph
|
|
17
28
|
this.includeGlyph(0);
|
|
18
29
|
}
|
|
19
30
|
|
|
31
|
+
/**
|
|
32
|
+
* @param {number | SubsetGlyph} glyph
|
|
33
|
+
* @returns {number}
|
|
34
|
+
*/
|
|
20
35
|
includeGlyph(glyph) {
|
|
21
36
|
if (typeof glyph === 'object') {
|
|
22
37
|
glyph = glyph.id;
|
|
@@ -32,11 +47,15 @@ export default class Subset {
|
|
|
32
47
|
|
|
33
48
|
// Copy an OT table into the TTF subset (tag is a 4-byte string, e.g. 'OS/2').
|
|
34
49
|
// Only honored by TTFSubset.encode; CFFSubset overrides this to throw.
|
|
50
|
+
/**
|
|
51
|
+
* @param {string} [tag]
|
|
52
|
+
* @returns {this}
|
|
53
|
+
*/
|
|
35
54
|
includeTable(tag) {
|
|
36
55
|
if (typeof tag !== 'string' || tag.length !== 4) {
|
|
37
56
|
throw new Error(
|
|
38
|
-
`Invalid OpenType table tag ${JSON.stringify(tag)}: tags must be 4 characters `
|
|
39
|
-
`(pad with spaces if needed, e.g. "cvt ").`
|
|
57
|
+
`Invalid OpenType table tag ${JSON.stringify(tag)}: tags must be 4 characters `
|
|
58
|
+
+ `(pad with spaces if needed, e.g. "cvt ").`
|
|
40
59
|
);
|
|
41
60
|
}
|
|
42
61
|
|
|
@@ -50,7 +69,8 @@ export default class Subset {
|
|
|
50
69
|
throw new Error(`Table "${tag}" is not present in this font.`);
|
|
51
70
|
}
|
|
52
71
|
|
|
53
|
-
|
|
72
|
+
let encoders = /** @type {Record<string, TableCodec | undefined>} */ (/** @type {unknown} */ (Tables));
|
|
73
|
+
if (!encoders[tag]) {
|
|
54
74
|
throw new Error(`Table "${tag}" cannot be encoded (no encoder registered in fontkit).`);
|
|
55
75
|
}
|
|
56
76
|
|
package/src/subset/TTFSubset.js
CHANGED
|
@@ -3,36 +3,88 @@ import Subset from './Subset';
|
|
|
3
3
|
import Directory from '../tables/directory';
|
|
4
4
|
import TTFGlyphEncoder from '../glyph/TTFGlyphEncoder';
|
|
5
5
|
|
|
6
|
+
/** @typedef {import('../../types/fontkit').SubsetFont} SubsetFont */
|
|
7
|
+
/** @typedef {import('../../types/fontkit').DecodedGlyf} DecodedGlyf */
|
|
8
|
+
/** @typedef {import('restructure').BinaryBuffer} BinaryBuffer */
|
|
9
|
+
/** @typedef {import('restructure').StructValue} StructValue */
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @typedef {{ advance: number, bearing: number }} HmtxMetric
|
|
13
|
+
*/
|
|
14
|
+
|
|
6
15
|
export default class TTFSubset extends Subset {
|
|
16
|
+
/** @type {TTFGlyphEncoder} */
|
|
17
|
+
glyphEncoder;
|
|
18
|
+
/** @type {Uint8Array[] | null} */
|
|
19
|
+
glyf = null;
|
|
20
|
+
/** @type {number} */
|
|
21
|
+
offset = 0;
|
|
22
|
+
/** @type {{ offsets: number[], version: number } | null} */
|
|
23
|
+
loca = null;
|
|
24
|
+
/** @type {{ metrics: HmtxMetric[], bearings: number[] } | null} */
|
|
25
|
+
hmtx = null;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @param {SubsetFont} font
|
|
29
|
+
*/
|
|
7
30
|
constructor(font) {
|
|
8
31
|
super(font);
|
|
9
|
-
this.glyphEncoder = new TTFGlyphEncoder;
|
|
32
|
+
this.glyphEncoder = new TTFGlyphEncoder();
|
|
10
33
|
}
|
|
11
34
|
|
|
35
|
+
/**
|
|
36
|
+
* @param {number} gid
|
|
37
|
+
* @returns {number}
|
|
38
|
+
*/
|
|
12
39
|
_addGlyph(gid) {
|
|
13
40
|
let glyph = this.font.getGlyph(gid);
|
|
41
|
+
if (!glyph || !glyph._decode) {
|
|
42
|
+
throw new Error(`Cannot decode glyph ${gid}`);
|
|
43
|
+
}
|
|
14
44
|
let glyf = glyph._decode();
|
|
15
45
|
|
|
46
|
+
if (!this.font.loca) {
|
|
47
|
+
throw new Error('Font missing loca table');
|
|
48
|
+
}
|
|
49
|
+
|
|
16
50
|
// get the offset to the glyph from the loca table
|
|
17
51
|
let curOffset = this.font.loca.offsets[gid];
|
|
18
52
|
let nextOffset = this.font.loca.offsets[gid + 1];
|
|
19
53
|
|
|
20
54
|
let stream = this.font._getTableStream('glyf');
|
|
55
|
+
if (!stream) {
|
|
56
|
+
throw new Error('Font missing glyf table');
|
|
57
|
+
}
|
|
21
58
|
stream.pos += curOffset;
|
|
22
59
|
|
|
23
|
-
let
|
|
60
|
+
let raw = stream.readBuffer(nextOffset - curOffset);
|
|
61
|
+
/** @type {Uint8Array} */
|
|
62
|
+
let buffer = raw instanceof Uint8Array
|
|
63
|
+
? raw
|
|
64
|
+
: Uint8Array.from(/** @type {Iterable<number>} */ (/** @type {unknown} */ (raw)));
|
|
24
65
|
|
|
25
66
|
// if it is a compound glyph, include its components
|
|
26
67
|
if (glyf && glyf.numberOfContours < 0) {
|
|
27
68
|
buffer = new Uint8Array(buffer);
|
|
28
|
-
let
|
|
29
|
-
|
|
69
|
+
let ab = buffer.buffer instanceof ArrayBuffer ? buffer.buffer : new Uint8Array(buffer).buffer;
|
|
70
|
+
let view = new DataView(ab, buffer.byteOffset, buffer.byteLength);
|
|
71
|
+
for (let component of glyf.components || []) {
|
|
30
72
|
gid = this.includeGlyph(component.glyphID);
|
|
31
73
|
view.setUint16(component.pos, gid);
|
|
32
74
|
}
|
|
33
75
|
} else if (glyf && this.font._variationProcessor) {
|
|
34
76
|
// If this is a TrueType variation glyph, re-encode the path
|
|
35
|
-
|
|
77
|
+
let encoded = this.glyphEncoder.encodeSimple(
|
|
78
|
+
/** @type {import('../glyph/Path').default} */ (/** @type {unknown} */ (glyph.path)),
|
|
79
|
+
glyf.instructions
|
|
80
|
+
);
|
|
81
|
+
buffer = encoded instanceof Uint8Array
|
|
82
|
+
? encoded
|
|
83
|
+
: Uint8Array.from(/** @type {Iterable<number>} */ (/** @type {unknown} */ (encoded)));
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (!this.glyf || !this.loca || !this.hmtx) {
|
|
87
|
+
throw new Error('TTFSubset.encode must initialize glyf/loca/hmtx before _addGlyph');
|
|
36
88
|
}
|
|
37
89
|
|
|
38
90
|
this.glyf.push(buffer);
|
|
@@ -43,10 +95,13 @@ export default class TTFSubset extends Subset {
|
|
|
43
95
|
bearing: glyph._getMetrics().leftBearing
|
|
44
96
|
});
|
|
45
97
|
|
|
46
|
-
this.offset += buffer.
|
|
98
|
+
this.offset += buffer.byteLength;
|
|
47
99
|
return this.glyf.length - 1;
|
|
48
100
|
}
|
|
49
101
|
|
|
102
|
+
/**
|
|
103
|
+
* @returns {BinaryBuffer}
|
|
104
|
+
*/
|
|
50
105
|
encode() {
|
|
51
106
|
// tables required by PDF spec:
|
|
52
107
|
// head, hhea, loca, maxp, cvt , prep, glyf, hmtx, fpgm
|
|
@@ -54,16 +109,17 @@ export default class TTFSubset extends Subset {
|
|
|
54
109
|
// additional tables required for standalone fonts:
|
|
55
110
|
// name, cmap, OS/2, post
|
|
56
111
|
|
|
112
|
+
/** @type {Uint8Array[]} */
|
|
57
113
|
this.glyf = [];
|
|
58
114
|
this.offset = 0;
|
|
59
115
|
this.loca = {
|
|
60
|
-
offsets: [],
|
|
61
|
-
version: this.font.loca.version
|
|
116
|
+
offsets: /** @type {number[]} */ ([]),
|
|
117
|
+
version: this.font.loca ? (this.font.loca.version ?? 0) : 0
|
|
62
118
|
};
|
|
63
119
|
|
|
64
120
|
this.hmtx = {
|
|
65
|
-
metrics: [],
|
|
66
|
-
bearings: []
|
|
121
|
+
metrics: /** @type {HmtxMetric[]} */ ([]),
|
|
122
|
+
bearings: /** @type {number[]} */ ([])
|
|
67
123
|
};
|
|
68
124
|
|
|
69
125
|
// include all the glyphs
|
|
@@ -75,41 +131,27 @@ export default class TTFSubset extends Subset {
|
|
|
75
131
|
}
|
|
76
132
|
|
|
77
133
|
let maxp = cloneDeep(this.font.maxp);
|
|
78
|
-
maxp
|
|
134
|
+
if (maxp && typeof maxp === 'object') {
|
|
135
|
+
/** @type {StructValue} */ (maxp).numGlyphs = this.glyf.length;
|
|
136
|
+
}
|
|
79
137
|
|
|
80
|
-
this.loca
|
|
138
|
+
let loca = this.loca;
|
|
139
|
+
loca.offsets.push(this.offset);
|
|
81
140
|
|
|
82
141
|
let head = cloneDeep(this.font.head);
|
|
83
|
-
head
|
|
142
|
+
if (head && typeof head === 'object') {
|
|
143
|
+
/** @type {StructValue} */ (head).indexToLocFormat = loca.version;
|
|
144
|
+
}
|
|
84
145
|
|
|
85
146
|
let hhea = cloneDeep(this.font.hhea);
|
|
86
|
-
hhea
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
// for index in [0...256]
|
|
90
|
-
// if index < @numGlyphs
|
|
91
|
-
// map[index] = index
|
|
92
|
-
// else
|
|
93
|
-
// map[index] = 0
|
|
94
|
-
//
|
|
95
|
-
// cmapTable =
|
|
96
|
-
// version: 0
|
|
97
|
-
// length: 262
|
|
98
|
-
// language: 0
|
|
99
|
-
// codeMap: map
|
|
100
|
-
//
|
|
101
|
-
// cmap =
|
|
102
|
-
// version: 0
|
|
103
|
-
// numSubtables: 1
|
|
104
|
-
// tables: [
|
|
105
|
-
// platformID: 1
|
|
106
|
-
// encodingID: 0
|
|
107
|
-
// table: cmapTable
|
|
108
|
-
// ]
|
|
147
|
+
if (hhea && typeof hhea === 'object') {
|
|
148
|
+
/** @type {StructValue} */ (hhea).numberOfMetrics = this.hmtx.metrics.length;
|
|
149
|
+
}
|
|
109
150
|
|
|
110
151
|
// TODO: subset prep, cvt, fpgm?
|
|
111
152
|
// The following is the minimum set of tables.
|
|
112
|
-
|
|
153
|
+
/** @type {Record<string, unknown>} */
|
|
154
|
+
let t = {
|
|
113
155
|
head,
|
|
114
156
|
hhea,
|
|
115
157
|
loca: this.loca,
|
|
@@ -118,13 +160,14 @@ export default class TTFSubset extends Subset {
|
|
|
118
160
|
prep: this.font.prep,
|
|
119
161
|
glyf: this.glyf,
|
|
120
162
|
hmtx: this.hmtx,
|
|
121
|
-
fpgm: this.font.fpgm
|
|
122
|
-
}
|
|
163
|
+
fpgm: this.font.fpgm
|
|
164
|
+
};
|
|
123
165
|
|
|
166
|
+
let fontTables = /** @type {Record<string, unknown>} */ (/** @type {unknown} */ (this.font));
|
|
124
167
|
for (const tag of this.includedTables) {
|
|
125
|
-
t[tag] = cloneDeep(
|
|
168
|
+
t[tag] = cloneDeep(fontTables[tag]);
|
|
126
169
|
}
|
|
127
170
|
|
|
128
|
-
return Directory.toBuffer({tables: t});
|
|
171
|
+
return Directory.toBuffer({ tables: t });
|
|
129
172
|
}
|
|
130
173
|
}
|
package/src/tables/BASE.js
CHANGED
|
@@ -1,58 +1,58 @@
|
|
|
1
1
|
import * as r from 'restructure';
|
|
2
|
-
import {Device} from './opentype';
|
|
3
|
-
import {ItemVariationStore} from './variations';
|
|
2
|
+
import { Device } from './opentype';
|
|
3
|
+
import { ItemVariationStore } from './variations';
|
|
4
4
|
|
|
5
5
|
let BaseCoord = new r.VersionedStruct(r.uint16, {
|
|
6
6
|
1: { // Design units only
|
|
7
|
-
coordinate:
|
|
7
|
+
coordinate: r.int16 // X or Y value, in design units
|
|
8
8
|
},
|
|
9
9
|
|
|
10
10
|
2: { // Design units plus contour point
|
|
11
|
-
coordinate:
|
|
12
|
-
referenceGlyph: r.uint16,
|
|
13
|
-
baseCoordPoint: r.uint16
|
|
11
|
+
coordinate: r.int16, // X or Y value, in design units
|
|
12
|
+
referenceGlyph: r.uint16, // GlyphID of control glyph
|
|
13
|
+
baseCoordPoint: r.uint16 // Index of contour point on the referenceGlyph
|
|
14
14
|
},
|
|
15
15
|
|
|
16
16
|
3: { // Design units plus Device table
|
|
17
|
-
coordinate:
|
|
18
|
-
deviceTable:
|
|
17
|
+
coordinate: r.int16, // X or Y value, in design units
|
|
18
|
+
deviceTable: new r.Pointer(r.uint16, Device) // Device table for X or Y value
|
|
19
19
|
}
|
|
20
20
|
});
|
|
21
21
|
|
|
22
22
|
let BaseValues = new r.Struct({
|
|
23
|
-
defaultIndex:
|
|
23
|
+
defaultIndex: r.uint16, // Index of default baseline for this script-same index in the BaseTagList
|
|
24
24
|
baseCoordCount: r.uint16,
|
|
25
|
-
baseCoords:
|
|
25
|
+
baseCoords: new r.Array(new r.Pointer(r.uint16, BaseCoord), 'baseCoordCount')
|
|
26
26
|
});
|
|
27
27
|
|
|
28
28
|
let FeatMinMaxRecord = new r.Struct({
|
|
29
|
-
tag:
|
|
30
|
-
minCoord:
|
|
31
|
-
maxCoord:
|
|
29
|
+
tag: new r.String(4), // 4-byte feature identification tag-must match FeatureTag in FeatureList
|
|
30
|
+
minCoord: new r.Pointer(r.uint16, BaseCoord, { type: 'parent' }), // May be NULL
|
|
31
|
+
maxCoord: new r.Pointer(r.uint16, BaseCoord, { type: 'parent' }) // May be NULL
|
|
32
32
|
});
|
|
33
33
|
|
|
34
34
|
let MinMax = new r.Struct({
|
|
35
|
-
minCoord:
|
|
36
|
-
maxCoord:
|
|
37
|
-
featMinMaxCount:
|
|
38
|
-
featMinMaxRecords:
|
|
35
|
+
minCoord: new r.Pointer(r.uint16, BaseCoord), // May be NULL
|
|
36
|
+
maxCoord: new r.Pointer(r.uint16, BaseCoord), // May be NULL
|
|
37
|
+
featMinMaxCount: r.uint16, // May be 0
|
|
38
|
+
featMinMaxRecords: new r.Array(FeatMinMaxRecord, 'featMinMaxCount') // In alphabetical order
|
|
39
39
|
});
|
|
40
40
|
|
|
41
41
|
let BaseLangSysRecord = new r.Struct({
|
|
42
|
-
tag:
|
|
43
|
-
minMax: new r.Pointer(r.uint16, MinMax, {type: 'parent'})
|
|
42
|
+
tag: new r.String(4), // 4-byte language system identification tag
|
|
43
|
+
minMax: new r.Pointer(r.uint16, MinMax, { type: 'parent' })
|
|
44
44
|
});
|
|
45
45
|
|
|
46
46
|
let BaseScript = new r.Struct({
|
|
47
|
-
baseValues:
|
|
48
|
-
defaultMinMax:
|
|
49
|
-
baseLangSysCount:
|
|
47
|
+
baseValues: new r.Pointer(r.uint16, BaseValues), // May be NULL
|
|
48
|
+
defaultMinMax: new r.Pointer(r.uint16, MinMax), // May be NULL
|
|
49
|
+
baseLangSysCount: r.uint16, // May be 0
|
|
50
50
|
baseLangSysRecords: new r.Array(BaseLangSysRecord, 'baseLangSysCount') // in alphabetical order by BaseLangSysTag
|
|
51
51
|
});
|
|
52
52
|
|
|
53
53
|
let BaseScriptRecord = new r.Struct({
|
|
54
|
-
tag:
|
|
55
|
-
script:
|
|
54
|
+
tag: new r.String(4), // 4-byte script identification tag
|
|
55
|
+
script: new r.Pointer(r.uint16, BaseScript, { type: 'parent' })
|
|
56
56
|
});
|
|
57
57
|
|
|
58
58
|
let BaseScriptList = new r.Array(BaseScriptRecord, r.uint16);
|
|
@@ -61,14 +61,15 @@ let BaseScriptList = new r.Array(BaseScriptRecord, r.uint16);
|
|
|
61
61
|
let BaseTagList = new r.Array(new r.String(4), r.uint16);
|
|
62
62
|
|
|
63
63
|
let Axis = new r.Struct({
|
|
64
|
-
baseTagList:
|
|
64
|
+
baseTagList: new r.Pointer(r.uint16, BaseTagList), // May be NULL
|
|
65
65
|
baseScriptList: new r.Pointer(r.uint16, BaseScriptList)
|
|
66
66
|
});
|
|
67
67
|
|
|
68
|
+
/** @type {import('restructure').VersionedStruct} */
|
|
68
69
|
export default new r.VersionedStruct(r.uint32, {
|
|
69
70
|
header: {
|
|
70
|
-
horizAxis:
|
|
71
|
-
vertAxis:
|
|
71
|
+
horizAxis: new r.Pointer(r.uint16, Axis), // May be NULL
|
|
72
|
+
vertAxis: new r.Pointer(r.uint16, Axis) // May be NULL
|
|
72
73
|
},
|
|
73
74
|
|
|
74
75
|
0x00010000: {},
|
package/src/tables/COLR.js
CHANGED
|
@@ -1,21 +1,22 @@
|
|
|
1
1
|
import * as r from 'restructure';
|
|
2
2
|
|
|
3
3
|
let LayerRecord = new r.Struct({
|
|
4
|
-
gid: r.uint16,
|
|
5
|
-
paletteIndex: r.uint16
|
|
6
|
-
});
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
4
|
+
gid: r.uint16, // Glyph ID of layer glyph (must be in z-order from bottom to top).
|
|
5
|
+
paletteIndex: r.uint16 // Index value to use in the appropriate palette. This value must
|
|
6
|
+
}); // be less than numPaletteEntries in the CPAL table, except for
|
|
7
|
+
// the special case noted below. Each palette entry is 16 bits.
|
|
8
|
+
// A palette index of 0xFFFF is a special case indicating that
|
|
9
|
+
// the text foreground color should be used.
|
|
10
10
|
|
|
11
11
|
let BaseGlyphRecord = new r.Struct({
|
|
12
|
-
gid: r.uint16,
|
|
13
|
-
|
|
12
|
+
gid: r.uint16, // Glyph ID of reference glyph. This glyph is for reference only
|
|
13
|
+
// and is not rendered for color.
|
|
14
14
|
firstLayerIndex: r.uint16, // Index (from beginning of the Layer Records) to the layer record.
|
|
15
|
-
|
|
15
|
+
// There will be numLayers consecutive entries for this base glyph.
|
|
16
16
|
numLayers: r.uint16
|
|
17
17
|
});
|
|
18
18
|
|
|
19
|
+
/** @type {import('restructure').Struct} */
|
|
19
20
|
export default new r.Struct({
|
|
20
21
|
version: r.uint16,
|
|
21
22
|
numBaseGlyphRecords: r.uint16,
|
package/src/tables/CPAL.js
CHANGED
|
@@ -7,13 +7,14 @@ let ColorRecord = new r.Struct({
|
|
|
7
7
|
alpha: r.uint8
|
|
8
8
|
});
|
|
9
9
|
|
|
10
|
+
/** @type {import('restructure').VersionedStruct} */
|
|
10
11
|
export default new r.VersionedStruct(r.uint16, {
|
|
11
12
|
header: {
|
|
12
13
|
numPaletteEntries: r.uint16,
|
|
13
14
|
numPalettes: r.uint16,
|
|
14
15
|
numColorRecords: r.uint16,
|
|
15
16
|
colorRecords: new r.Pointer(r.uint32, new r.Array(ColorRecord, 'numColorRecords')),
|
|
16
|
-
colorRecordIndices: new r.Array(r.uint16, 'numPalettes')
|
|
17
|
+
colorRecordIndices: new r.Array(r.uint16, 'numPalettes')
|
|
17
18
|
},
|
|
18
19
|
0: {},
|
|
19
20
|
1: {
|
package/src/tables/DSIG.js
CHANGED
|
@@ -7,15 +7,16 @@ let Signature = new r.Struct({
|
|
|
7
7
|
});
|
|
8
8
|
|
|
9
9
|
let SignatureBlock = new r.Struct({
|
|
10
|
-
reserved:
|
|
11
|
-
cbSignature:
|
|
12
|
-
signature:
|
|
10
|
+
reserved: new r.Reserved(r.uint16, 2),
|
|
11
|
+
cbSignature: r.uint32, // Length (in bytes) of the PKCS#7 packet in pbSignature
|
|
12
|
+
signature: new r.Buffer('cbSignature')
|
|
13
13
|
});
|
|
14
14
|
|
|
15
|
+
/** @type {import('restructure').Struct} */
|
|
15
16
|
export default new r.Struct({
|
|
16
|
-
ulVersion:
|
|
17
|
-
usNumSigs:
|
|
18
|
-
usFlag:
|
|
19
|
-
signatures:
|
|
17
|
+
ulVersion: r.uint32, // Version number of the DSIG table (0x00000001)
|
|
18
|
+
usNumSigs: r.uint16, // Number of signatures in the table
|
|
19
|
+
usFlag: r.uint16, // Permission flags
|
|
20
|
+
signatures: new r.Array(Signature, 'usNumSigs'),
|
|
20
21
|
signatureBlocks: new r.Array(SignatureBlock, 'usNumSigs')
|
|
21
22
|
});
|
package/src/tables/EBDT.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import * as r from 'restructure';
|
|
2
2
|
|
|
3
|
+
/** @typedef {import('restructure').BaseType} BaseType */
|
|
4
|
+
|
|
5
|
+
/** @type {import('restructure').Struct} */
|
|
3
6
|
export let BigMetrics = new r.Struct({
|
|
4
7
|
height: r.uint8,
|
|
5
8
|
width: r.uint8,
|
|
@@ -11,6 +14,7 @@ export let BigMetrics = new r.Struct({
|
|
|
11
14
|
vertAdvance: r.uint8
|
|
12
15
|
});
|
|
13
16
|
|
|
17
|
+
/** @type {import('restructure').Struct} */
|
|
14
18
|
export let SmallMetrics = new r.Struct({
|
|
15
19
|
height: r.uint8,
|
|
16
20
|
width: r.uint8,
|
|
@@ -25,10 +29,13 @@ let EBDTComponent = new r.Struct({
|
|
|
25
29
|
yOffset: r.int8
|
|
26
30
|
});
|
|
27
31
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
32
|
+
/** Marker codecs for bitmap payload layout (decoded by glyph consumers). */
|
|
33
|
+
/** @type {BaseType} */
|
|
34
|
+
const ByteAligned = {};
|
|
35
|
+
/** @type {BaseType} */
|
|
36
|
+
const BitAligned = {};
|
|
31
37
|
|
|
38
|
+
/** @type {import('restructure').VersionedStruct} */
|
|
32
39
|
export let glyph = new r.VersionedStruct('version', {
|
|
33
40
|
1: {
|
|
34
41
|
metrics: SmallMetrics,
|
|
@@ -88,4 +95,3 @@ export let glyph = new r.VersionedStruct('version', {
|
|
|
88
95
|
data: new r.Buffer('dataLen')
|
|
89
96
|
}
|
|
90
97
|
});
|
|
91
|
-
|
package/src/tables/EBLC.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import * as r from 'restructure';
|
|
2
|
-
import {BigMetrics} from './EBDT';
|
|
2
|
+
import { BigMetrics } from './EBDT';
|
|
3
|
+
|
|
4
|
+
/** @typedef {import('restructure').StructValue} StructValue */
|
|
3
5
|
|
|
4
6
|
let SBitLineMetrics = new r.Struct({
|
|
5
7
|
ascender: r.int8,
|
|
@@ -20,6 +22,17 @@ let CodeOffsetPair = new r.Struct({
|
|
|
20
22
|
offset: r.uint16
|
|
21
23
|
});
|
|
22
24
|
|
|
25
|
+
/**
|
|
26
|
+
* Spec: numOffsets = lastGlyphIndex - firstGlyphIndex + 2 (extra sentinel for last glyph size).
|
|
27
|
+
* @param {StructValue} t
|
|
28
|
+
* @returns {number}
|
|
29
|
+
*/
|
|
30
|
+
function glyphRangeOffsetCount(t) {
|
|
31
|
+
let parent = /** @type {StructValue} */ (t.parent);
|
|
32
|
+
return /** @type {number} */ (parent.lastGlyphIndex)
|
|
33
|
+
- /** @type {number} */ (parent.firstGlyphIndex) + 2;
|
|
34
|
+
}
|
|
35
|
+
|
|
23
36
|
let IndexSubtable = new r.VersionedStruct(r.uint16, {
|
|
24
37
|
header: {
|
|
25
38
|
imageFormat: r.uint16,
|
|
@@ -27,7 +40,7 @@ let IndexSubtable = new r.VersionedStruct(r.uint16, {
|
|
|
27
40
|
},
|
|
28
41
|
|
|
29
42
|
1: {
|
|
30
|
-
offsetArray: new r.Array(r.uint32,
|
|
43
|
+
offsetArray: new r.Array(r.uint32, glyphRangeOffsetCount)
|
|
31
44
|
},
|
|
32
45
|
|
|
33
46
|
2: {
|
|
@@ -36,30 +49,67 @@ let IndexSubtable = new r.VersionedStruct(r.uint16, {
|
|
|
36
49
|
},
|
|
37
50
|
|
|
38
51
|
3: {
|
|
39
|
-
offsetArray: new r.Array(r.uint16,
|
|
52
|
+
offsetArray: new r.Array(r.uint16, glyphRangeOffsetCount),
|
|
53
|
+
// Format 3 pads to 32-bit alignment when the offset count is odd.
|
|
54
|
+
pad: new r.Reserved(
|
|
55
|
+
r.uint16,
|
|
56
|
+
/** @param {StructValue} t @returns {number} */
|
|
57
|
+
t => glyphRangeOffsetCount(t) % 2
|
|
58
|
+
)
|
|
40
59
|
},
|
|
41
60
|
|
|
42
61
|
4: {
|
|
43
62
|
numGlyphs: r.uint32,
|
|
44
|
-
glyphArray: new r.Array(
|
|
63
|
+
glyphArray: new r.Array(
|
|
64
|
+
CodeOffsetPair,
|
|
65
|
+
/** @param {StructValue} t @returns {number} */
|
|
66
|
+
t => /** @type {number} */ (t.numGlyphs) + 1
|
|
67
|
+
)
|
|
45
68
|
},
|
|
46
69
|
|
|
47
70
|
5: {
|
|
48
71
|
imageSize: r.uint32,
|
|
49
72
|
bigMetrics: BigMetrics,
|
|
50
73
|
numGlyphs: r.uint32,
|
|
51
|
-
glyphCodeArray: new r.Array(r.uint16, 'numGlyphs')
|
|
74
|
+
glyphCodeArray: new r.Array(r.uint16, 'numGlyphs'),
|
|
75
|
+
// Format 5 pads to 32-bit alignment when glyphCodeArray length is odd.
|
|
76
|
+
pad: new r.Reserved(
|
|
77
|
+
r.uint16,
|
|
78
|
+
/** @param {StructValue} t @returns {number} */
|
|
79
|
+
t => /** @type {number} */ (t.numGlyphs) % 2
|
|
80
|
+
)
|
|
52
81
|
}
|
|
53
82
|
});
|
|
54
83
|
|
|
55
|
-
let
|
|
84
|
+
let IndexSubtableRecord = new r.Struct({
|
|
56
85
|
firstGlyphIndex: r.uint16,
|
|
57
86
|
lastGlyphIndex: r.uint16,
|
|
58
|
-
|
|
87
|
+
// Offset from the start of IndexSubTableList (OpenType IndexSubTableArray).
|
|
88
|
+
subtable: new r.Pointer(r.uint32, IndexSubtable, { type: 'parent' })
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Wrapper so record pointers resolve relative to the list start.
|
|
93
|
+
* process() on BitmapSizeTable unwraps `.tables` so the public shape stays an array.
|
|
94
|
+
*/
|
|
95
|
+
let IndexSubTableList = new r.Struct({
|
|
96
|
+
tables: new r.Array(
|
|
97
|
+
IndexSubtableRecord,
|
|
98
|
+
/** @param {StructValue} t @returns {number} */
|
|
99
|
+
t => /** @type {number} */ (/** @type {StructValue} */ (t.parent).numberOfIndexSubTables)
|
|
100
|
+
)
|
|
59
101
|
});
|
|
60
102
|
|
|
103
|
+
/**
|
|
104
|
+
* @typedef {StructValue & {
|
|
105
|
+
* indexSubTableArray: { tables: StructValue[] } | StructValue[],
|
|
106
|
+
* numberOfIndexSubTables: number
|
|
107
|
+
* }} BitmapSizeTableValue
|
|
108
|
+
*/
|
|
109
|
+
|
|
61
110
|
let BitmapSizeTable = new r.Struct({
|
|
62
|
-
|
|
111
|
+
// Lazy: numberOfIndexSubTables is stored after this pointer in the binary layout.
|
|
112
|
+
indexSubTableArray: new r.Pointer(r.uint32, IndexSubTableList, { type: 'parent', lazy: true }),
|
|
63
113
|
indexTablesSize: r.uint32,
|
|
64
114
|
numberOfIndexSubTables: r.uint32,
|
|
65
115
|
colorRef: r.uint32,
|
|
@@ -73,8 +123,18 @@ let BitmapSizeTable = new r.Struct({
|
|
|
73
123
|
flags: new r.Bitfield(r.uint8, ['horizontal', 'vertical'])
|
|
74
124
|
});
|
|
75
125
|
|
|
126
|
+
BitmapSizeTable.process = function () {
|
|
127
|
+
let self = /** @type {BitmapSizeTableValue} */ (this);
|
|
128
|
+
// Access forces lazy decode now that numberOfIndexSubTables is available.
|
|
129
|
+
let list = self.indexSubTableArray;
|
|
130
|
+
if (list && !Array.isArray(list) && Array.isArray(list.tables)) {
|
|
131
|
+
self.indexSubTableArray = list.tables;
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
/** @type {import('restructure').Struct} */
|
|
76
136
|
export default new r.Struct({
|
|
77
|
-
version:
|
|
137
|
+
version: r.uint32, // 0x00020000
|
|
78
138
|
numSizes: r.uint32,
|
|
79
|
-
sizes:
|
|
139
|
+
sizes: new r.Array(BitmapSizeTable, 'numSizes')
|
|
80
140
|
});
|