@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/tables/aat.js
CHANGED
|
@@ -1,64 +1,135 @@
|
|
|
1
1
|
import * as r from 'restructure';
|
|
2
2
|
|
|
3
|
+
/** @typedef {import('restructure').BaseType} BaseType */
|
|
4
|
+
/** @typedef {import('restructure').DecodeStream} DecodeStream */
|
|
5
|
+
/** @typedef {import('restructure').EncodeStream} EncodeStream */
|
|
6
|
+
/** @typedef {import('restructure').StructFields} StructFields */
|
|
7
|
+
/** @typedef {import('restructure').StructValue} StructValue */
|
|
8
|
+
/** @typedef {import('restructure').VersionedStruct} VersionedStruct */
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Lazy random-access view over an unbounded run of encoded items.
|
|
12
|
+
*/
|
|
3
13
|
class UnboundedArrayAccessor {
|
|
14
|
+
/**
|
|
15
|
+
* @param {BaseType} type
|
|
16
|
+
* @param {DecodeStream} stream
|
|
17
|
+
* @param {StructValue | null | undefined} parent
|
|
18
|
+
*/
|
|
4
19
|
constructor(type, stream, parent) {
|
|
20
|
+
/** @type {BaseType} */
|
|
5
21
|
this.type = type;
|
|
22
|
+
/** @type {DecodeStream} */
|
|
6
23
|
this.stream = stream;
|
|
24
|
+
/** @type {StructValue | null | undefined} */
|
|
7
25
|
this.parent = parent;
|
|
26
|
+
/** @type {number} */
|
|
8
27
|
this.base = this.stream.pos;
|
|
28
|
+
/** @type {unknown[]} */
|
|
9
29
|
this._items = [];
|
|
10
30
|
}
|
|
11
31
|
|
|
32
|
+
/**
|
|
33
|
+
* @param {number} index
|
|
34
|
+
* @returns {unknown}
|
|
35
|
+
*/
|
|
12
36
|
getItem(index) {
|
|
13
37
|
if (this._items[index] == null) {
|
|
14
38
|
let pos = this.stream.pos;
|
|
15
|
-
|
|
16
|
-
this.
|
|
39
|
+
let itemSize = this.type.size?.(null, this.parent);
|
|
40
|
+
this.stream.pos = this.base + /** @type {number} */ (itemSize) * index;
|
|
41
|
+
this._items[index] = this.type.decode?.(this.stream, this.parent);
|
|
17
42
|
this.stream.pos = pos;
|
|
18
43
|
}
|
|
19
44
|
|
|
20
45
|
return this._items[index];
|
|
21
46
|
}
|
|
22
47
|
|
|
48
|
+
/**
|
|
49
|
+
* @returns {string}
|
|
50
|
+
*/
|
|
23
51
|
inspect() {
|
|
24
|
-
|
|
52
|
+
let name = this.type.constructor && this.type.constructor.name
|
|
53
|
+
? this.type.constructor.name
|
|
54
|
+
: 'Type';
|
|
55
|
+
return `[UnboundedArray ${name}]`;
|
|
25
56
|
}
|
|
26
57
|
}
|
|
27
58
|
|
|
28
|
-
|
|
59
|
+
/**
|
|
60
|
+
* Array whose length is not stored; consumers index via getItem().
|
|
61
|
+
* @implements {BaseType}
|
|
62
|
+
*/
|
|
63
|
+
export class UnboundedArray {
|
|
64
|
+
/**
|
|
65
|
+
* @param {BaseType} type
|
|
66
|
+
*/
|
|
29
67
|
constructor(type) {
|
|
30
|
-
|
|
68
|
+
/** @type {BaseType} */
|
|
69
|
+
this.type = type;
|
|
31
70
|
}
|
|
32
71
|
|
|
72
|
+
/**
|
|
73
|
+
* @param {DecodeStream} stream
|
|
74
|
+
* @param {StructValue | null | undefined} parent
|
|
75
|
+
* @returns {UnboundedArrayAccessor}
|
|
76
|
+
*/
|
|
33
77
|
decode(stream, parent) {
|
|
34
78
|
return new UnboundedArrayAccessor(this.type, stream, parent);
|
|
35
79
|
}
|
|
36
80
|
}
|
|
37
81
|
|
|
38
|
-
|
|
39
|
-
|
|
82
|
+
/**
|
|
83
|
+
* @param {BaseType} [ValueType]
|
|
84
|
+
* @returns {VersionedStruct}
|
|
85
|
+
*/
|
|
86
|
+
export function LookupTable(ValueType = r.uint16) {
|
|
87
|
+
/**
|
|
88
|
+
* Re-parents decode/encode so internal lookup structs stay invisible to pointers.
|
|
89
|
+
* @implements {BaseType}
|
|
90
|
+
*/
|
|
40
91
|
class Shadow {
|
|
92
|
+
/**
|
|
93
|
+
* @param {BaseType} type
|
|
94
|
+
*/
|
|
41
95
|
constructor(type) {
|
|
96
|
+
/** @type {BaseType} */
|
|
42
97
|
this.type = type;
|
|
43
98
|
}
|
|
44
99
|
|
|
100
|
+
/**
|
|
101
|
+
* @param {DecodeStream} stream
|
|
102
|
+
* @param {StructValue | null | undefined} ctx
|
|
103
|
+
* @returns {unknown}
|
|
104
|
+
*/
|
|
45
105
|
decode(stream, ctx) {
|
|
46
|
-
|
|
47
|
-
return this.type.decode(stream,
|
|
106
|
+
let parent = ctx && ctx.parent && ctx.parent.parent ? ctx.parent.parent : ctx;
|
|
107
|
+
return this.type.decode?.(stream, parent);
|
|
48
108
|
}
|
|
49
109
|
|
|
110
|
+
/**
|
|
111
|
+
* @param {unknown} val
|
|
112
|
+
* @param {StructValue | null | undefined} ctx
|
|
113
|
+
* @returns {number}
|
|
114
|
+
*/
|
|
50
115
|
size(val, ctx) {
|
|
51
|
-
|
|
52
|
-
return this.type.size(val,
|
|
116
|
+
let parent = ctx && ctx.parent && ctx.parent.parent ? ctx.parent.parent : ctx;
|
|
117
|
+
return /** @type {number} */ (this.type.size?.(val, parent));
|
|
53
118
|
}
|
|
54
119
|
|
|
120
|
+
/**
|
|
121
|
+
* @param {EncodeStream | null} stream
|
|
122
|
+
* @param {unknown} val
|
|
123
|
+
* @param {StructValue | null | undefined} ctx
|
|
124
|
+
* @returns {unknown}
|
|
125
|
+
*/
|
|
55
126
|
encode(stream, val, ctx) {
|
|
56
|
-
|
|
57
|
-
return this.type.encode(stream, val,
|
|
127
|
+
let parent = ctx && ctx.parent && ctx.parent.parent ? ctx.parent.parent : ctx;
|
|
128
|
+
return this.type.encode?.(stream, val, parent);
|
|
58
129
|
}
|
|
59
130
|
}
|
|
60
131
|
|
|
61
|
-
|
|
132
|
+
let shadowed = new Shadow(ValueType);
|
|
62
133
|
|
|
63
134
|
let BinarySearchHeader = new r.Struct({
|
|
64
135
|
unitSize: r.uint16,
|
|
@@ -71,44 +142,69 @@ export let LookupTable = function(ValueType = r.uint16) {
|
|
|
71
142
|
let LookupSegmentSingle = new r.Struct({
|
|
72
143
|
lastGlyph: r.uint16,
|
|
73
144
|
firstGlyph: r.uint16,
|
|
74
|
-
value:
|
|
145
|
+
value: shadowed
|
|
75
146
|
});
|
|
76
147
|
|
|
77
148
|
let LookupSegmentArray = new r.Struct({
|
|
78
149
|
lastGlyph: r.uint16,
|
|
79
150
|
firstGlyph: r.uint16,
|
|
80
|
-
values: new r.Pointer(
|
|
151
|
+
values: new r.Pointer(
|
|
152
|
+
r.uint16,
|
|
153
|
+
new r.Array(
|
|
154
|
+
shadowed,
|
|
155
|
+
/** @param {StructValue} t @returns {number} */
|
|
156
|
+
t => /** @type {number} */ (t.lastGlyph) - /** @type {number} */ (t.firstGlyph) + 1
|
|
157
|
+
),
|
|
158
|
+
{ type: 'parent' }
|
|
159
|
+
)
|
|
81
160
|
});
|
|
82
161
|
|
|
83
162
|
let LookupSingle = new r.Struct({
|
|
84
163
|
glyph: r.uint16,
|
|
85
|
-
value:
|
|
164
|
+
value: shadowed
|
|
86
165
|
});
|
|
87
166
|
|
|
88
167
|
return new r.VersionedStruct(r.uint16, {
|
|
89
168
|
0: {
|
|
90
|
-
values: new UnboundedArray(
|
|
169
|
+
values: new UnboundedArray(shadowed) // length == number of glyphs maybe?
|
|
91
170
|
},
|
|
92
171
|
2: {
|
|
93
172
|
binarySearchHeader: BinarySearchHeader,
|
|
94
|
-
segments: new r.Array(
|
|
173
|
+
segments: new r.Array(
|
|
174
|
+
LookupSegmentSingle,
|
|
175
|
+
/** @param {StructValue} t @returns {number} */
|
|
176
|
+
t => /** @type {number} */ (/** @type {StructValue} */ (t.binarySearchHeader).nUnits)
|
|
177
|
+
)
|
|
95
178
|
},
|
|
96
179
|
4: {
|
|
97
180
|
binarySearchHeader: BinarySearchHeader,
|
|
98
|
-
segments: new r.Array(
|
|
181
|
+
segments: new r.Array(
|
|
182
|
+
LookupSegmentArray,
|
|
183
|
+
/** @param {StructValue} t @returns {number} */
|
|
184
|
+
t => /** @type {number} */ (/** @type {StructValue} */ (t.binarySearchHeader).nUnits)
|
|
185
|
+
)
|
|
99
186
|
},
|
|
100
187
|
6: {
|
|
101
188
|
binarySearchHeader: BinarySearchHeader,
|
|
102
|
-
segments: new r.Array(
|
|
189
|
+
segments: new r.Array(
|
|
190
|
+
LookupSingle,
|
|
191
|
+
/** @param {StructValue} t @returns {number} */
|
|
192
|
+
t => /** @type {number} */ (/** @type {StructValue} */ (t.binarySearchHeader).nUnits)
|
|
193
|
+
)
|
|
103
194
|
},
|
|
104
195
|
8: {
|
|
105
196
|
firstGlyph: r.uint16,
|
|
106
197
|
count: r.uint16,
|
|
107
|
-
values: new r.Array(
|
|
198
|
+
values: new r.Array(shadowed, 'count')
|
|
108
199
|
}
|
|
109
200
|
});
|
|
110
|
-
}
|
|
201
|
+
}
|
|
111
202
|
|
|
203
|
+
/**
|
|
204
|
+
* @param {StructFields} [entryData]
|
|
205
|
+
* @param {BaseType} [lookupType]
|
|
206
|
+
* @returns {import('restructure').Struct}
|
|
207
|
+
*/
|
|
112
208
|
export function StateTable(entryData = {}, lookupType = r.uint16) {
|
|
113
209
|
let entry = Object.assign({
|
|
114
210
|
newState: r.uint16,
|
|
@@ -116,21 +212,31 @@ export function StateTable(entryData = {}, lookupType = r.uint16) {
|
|
|
116
212
|
}, entryData);
|
|
117
213
|
|
|
118
214
|
let Entry = new r.Struct(entry);
|
|
119
|
-
let StateArray = new UnboundedArray(
|
|
215
|
+
let StateArray = new UnboundedArray(
|
|
216
|
+
new r.Array(
|
|
217
|
+
r.uint16,
|
|
218
|
+
/** @param {StructValue} t @returns {number} */
|
|
219
|
+
t => /** @type {number} */ (t.nClasses)
|
|
220
|
+
)
|
|
221
|
+
);
|
|
120
222
|
|
|
121
|
-
|
|
223
|
+
return new r.Struct({
|
|
122
224
|
nClasses: r.uint32,
|
|
123
|
-
classTable: new r.Pointer(r.uint32,
|
|
225
|
+
classTable: new r.Pointer(r.uint32, LookupTable(lookupType)),
|
|
124
226
|
stateArray: new r.Pointer(r.uint32, StateArray),
|
|
125
227
|
entryTable: new r.Pointer(r.uint32, new UnboundedArray(Entry))
|
|
126
228
|
});
|
|
127
|
-
|
|
128
|
-
return StateHeader;
|
|
129
229
|
}
|
|
130
230
|
|
|
131
|
-
|
|
231
|
+
/**
|
|
232
|
+
* Old (16-bit) StateTable structure.
|
|
233
|
+
* @param {StructFields} [entryData]
|
|
234
|
+
* @param {BaseType} [_lookupType]
|
|
235
|
+
* @returns {import('restructure').Struct}
|
|
236
|
+
*/
|
|
132
237
|
export function StateTable1(entryData = {}, _lookupType = r.uint16) {
|
|
133
238
|
let ClassLookupTable = new r.Struct({
|
|
239
|
+
/** @returns {number} */
|
|
134
240
|
version() { return 8; }, // simulate LookupTable
|
|
135
241
|
firstGlyph: r.uint16,
|
|
136
242
|
values: new r.Array(r.uint8, r.uint16)
|
|
@@ -138,20 +244,39 @@ export function StateTable1(entryData = {}, _lookupType = r.uint16) {
|
|
|
138
244
|
|
|
139
245
|
let entry = Object.assign({
|
|
140
246
|
newStateOffset: r.uint16,
|
|
141
|
-
|
|
142
|
-
|
|
247
|
+
/**
|
|
248
|
+
* Convert offset to stateArray index.
|
|
249
|
+
* @param {StructValue} t
|
|
250
|
+
* @returns {number}
|
|
251
|
+
*/
|
|
252
|
+
newState: (t) => {
|
|
253
|
+
/**
|
|
254
|
+
* @typedef {{
|
|
255
|
+
* stateArray: { base: number },
|
|
256
|
+
* _startOffset: number,
|
|
257
|
+
* nClasses: number
|
|
258
|
+
* }} StateParent
|
|
259
|
+
*/
|
|
260
|
+
let parent = /** @type {StructValue & StateParent} */ (t.parent);
|
|
261
|
+
return (/** @type {number} */ (t.newStateOffset)
|
|
262
|
+
- (parent.stateArray.base - parent._startOffset)) / parent.nClasses;
|
|
263
|
+
},
|
|
143
264
|
flags: r.uint16
|
|
144
265
|
}, entryData);
|
|
145
266
|
|
|
146
267
|
let Entry = new r.Struct(entry);
|
|
147
|
-
let StateArray = new UnboundedArray(
|
|
268
|
+
let StateArray = new UnboundedArray(
|
|
269
|
+
new r.Array(
|
|
270
|
+
r.uint8,
|
|
271
|
+
/** @param {StructValue} t @returns {number} */
|
|
272
|
+
t => /** @type {number} */ (t.nClasses)
|
|
273
|
+
)
|
|
274
|
+
);
|
|
148
275
|
|
|
149
|
-
|
|
276
|
+
return new r.Struct({
|
|
150
277
|
nClasses: r.uint16,
|
|
151
278
|
classTable: new r.Pointer(r.uint16, ClassLookupTable),
|
|
152
279
|
stateArray: new r.Pointer(r.uint16, StateArray),
|
|
153
280
|
entryTable: new r.Pointer(r.uint16, new UnboundedArray(Entry))
|
|
154
281
|
});
|
|
155
|
-
|
|
156
|
-
return StateHeader1;
|
|
157
282
|
}
|
package/src/tables/avar.js
CHANGED
package/src/tables/bsln.js
CHANGED
|
@@ -8,7 +8,7 @@ let BslnSubtable = new r.VersionedStruct('format', {
|
|
|
8
8
|
|
|
9
9
|
1: { // Distance-based, with mapping
|
|
10
10
|
deltas: new r.Array(r.int16, 32),
|
|
11
|
-
mappingData:
|
|
11
|
+
mappingData: LookupTable(r.uint16)
|
|
12
12
|
},
|
|
13
13
|
|
|
14
14
|
2: { // Control point-based, no mapping
|
|
@@ -19,10 +19,11 @@ let BslnSubtable = new r.VersionedStruct('format', {
|
|
|
19
19
|
3: { // Control point-based, with mapping
|
|
20
20
|
standardGlyph: r.uint16,
|
|
21
21
|
controlPoints: new r.Array(r.uint16, 32),
|
|
22
|
-
mappingData:
|
|
22
|
+
mappingData: LookupTable(r.uint16)
|
|
23
23
|
}
|
|
24
24
|
});
|
|
25
25
|
|
|
26
|
+
/** @type {import('restructure').Struct} */
|
|
26
27
|
export default new r.Struct({
|
|
27
28
|
version: r.fixed32,
|
|
28
29
|
format: r.uint16,
|
package/src/tables/cmap.js
CHANGED
|
@@ -1,127 +1,147 @@
|
|
|
1
1
|
import * as r from 'restructure';
|
|
2
2
|
|
|
3
|
+
/** @typedef {import('restructure').StructValue} StructValue */
|
|
4
|
+
|
|
3
5
|
let SubHeader = new r.Struct({
|
|
4
|
-
firstCode:
|
|
5
|
-
entryCount:
|
|
6
|
-
idDelta:
|
|
7
|
-
idRangeOffset:
|
|
6
|
+
firstCode: r.uint16,
|
|
7
|
+
entryCount: r.uint16,
|
|
8
|
+
idDelta: r.int16,
|
|
9
|
+
idRangeOffset: r.uint16
|
|
8
10
|
});
|
|
9
11
|
|
|
10
12
|
let CmapGroup = new r.Struct({
|
|
11
|
-
startCharCode:
|
|
12
|
-
endCharCode:
|
|
13
|
-
glyphID:
|
|
13
|
+
startCharCode: r.uint32,
|
|
14
|
+
endCharCode: r.uint32,
|
|
15
|
+
glyphID: r.uint32
|
|
14
16
|
});
|
|
15
17
|
|
|
16
18
|
let UnicodeValueRange = new r.Struct({
|
|
17
|
-
startUnicodeValue:
|
|
18
|
-
additionalCount:
|
|
19
|
+
startUnicodeValue: r.uint24,
|
|
20
|
+
additionalCount: r.uint8
|
|
19
21
|
});
|
|
20
22
|
|
|
21
23
|
let UVSMapping = new r.Struct({
|
|
22
24
|
unicodeValue: r.uint24,
|
|
23
|
-
glyphID:
|
|
25
|
+
glyphID: r.uint16
|
|
24
26
|
});
|
|
25
27
|
|
|
26
28
|
let DefaultUVS = new r.Array(UnicodeValueRange, r.uint32);
|
|
27
29
|
let NonDefaultUVS = new r.Array(UVSMapping, r.uint32);
|
|
28
30
|
|
|
29
31
|
let VarSelectorRecord = new r.Struct({
|
|
30
|
-
varSelector:
|
|
31
|
-
defaultUVS:
|
|
32
|
-
nonDefaultUVS:
|
|
32
|
+
varSelector: r.uint24,
|
|
33
|
+
defaultUVS: new r.Pointer(r.uint32, DefaultUVS, { type: 'parent' }),
|
|
34
|
+
nonDefaultUVS: new r.Pointer(r.uint32, NonDefaultUVS, { type: 'parent' })
|
|
33
35
|
});
|
|
34
36
|
|
|
35
37
|
let CmapSubtable = new r.VersionedStruct(r.uint16, {
|
|
36
38
|
0: { // Byte encoding
|
|
37
|
-
length:
|
|
38
|
-
language:
|
|
39
|
-
codeMap:
|
|
39
|
+
length: r.uint16, // Total table length in bytes (set to 262 for format 0)
|
|
40
|
+
language: r.uint16, // Language code for this encoding subtable, or zero if language-independent
|
|
41
|
+
codeMap: new r.LazyArray(r.uint8, 256)
|
|
40
42
|
},
|
|
41
43
|
|
|
42
44
|
2: { // High-byte mapping (CJK)
|
|
43
|
-
length:
|
|
44
|
-
language:
|
|
45
|
-
subHeaderKeys:
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
45
|
+
length: r.uint16,
|
|
46
|
+
language: r.uint16,
|
|
47
|
+
subHeaderKeys: new r.Array(r.uint16, 256),
|
|
48
|
+
/**
|
|
49
|
+
* Keys store subHeaderIndex * 8; count is max index + 1.
|
|
50
|
+
* @param {StructValue} t
|
|
51
|
+
* @returns {number}
|
|
52
|
+
*/
|
|
53
|
+
subHeaderCount: t => (Math.max.apply(Math, /** @type {number[]} */ (t.subHeaderKeys)) / 8) + 1,
|
|
54
|
+
subHeaders: new r.LazyArray(SubHeader, 'subHeaderCount'),
|
|
55
|
+
glyphIndexArray: new r.LazyArray(
|
|
56
|
+
r.uint16,
|
|
57
|
+
/** @param {StructValue} t @returns {number} */
|
|
58
|
+
t => (/** @type {number} */ (t.length) - /** @type {number} */ (t._currentOffset)) / 2
|
|
59
|
+
)
|
|
49
60
|
},
|
|
50
61
|
|
|
51
62
|
4: { // Segment mapping to delta values
|
|
52
|
-
length:
|
|
53
|
-
language:
|
|
54
|
-
segCountX2:
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
63
|
+
length: r.uint16, // Total table length in bytes
|
|
64
|
+
language: r.uint16, // Language code
|
|
65
|
+
segCountX2: r.uint16,
|
|
66
|
+
/**
|
|
67
|
+
* @param {StructValue} t
|
|
68
|
+
* @returns {number}
|
|
69
|
+
*/
|
|
70
|
+
segCount: t => /** @type {number} */ (t.segCountX2) >> 1,
|
|
71
|
+
searchRange: r.uint16,
|
|
72
|
+
entrySelector: r.uint16,
|
|
73
|
+
rangeShift: r.uint16,
|
|
74
|
+
endCode: new r.LazyArray(r.uint16, 'segCount'),
|
|
75
|
+
reservedPad: new r.Reserved(r.uint16), // This value should be zero
|
|
76
|
+
startCode: new r.LazyArray(r.uint16, 'segCount'),
|
|
77
|
+
idDelta: new r.LazyArray(r.int16, 'segCount'),
|
|
78
|
+
idRangeOffset: new r.LazyArray(r.uint16, 'segCount'),
|
|
79
|
+
glyphIndexArray: new r.LazyArray(
|
|
80
|
+
r.uint16,
|
|
81
|
+
/** @param {StructValue} t @returns {number} */
|
|
82
|
+
t => (/** @type {number} */ (t.length) - /** @type {number} */ (t._currentOffset)) / 2
|
|
83
|
+
)
|
|
65
84
|
},
|
|
66
85
|
|
|
67
86
|
6: { // Trimmed table
|
|
68
|
-
length:
|
|
69
|
-
language:
|
|
70
|
-
firstCode:
|
|
71
|
-
entryCount:
|
|
72
|
-
glyphIndices:
|
|
87
|
+
length: r.uint16,
|
|
88
|
+
language: r.uint16,
|
|
89
|
+
firstCode: r.uint16,
|
|
90
|
+
entryCount: r.uint16,
|
|
91
|
+
glyphIndices: new r.LazyArray(r.uint16, 'entryCount')
|
|
73
92
|
},
|
|
74
93
|
|
|
75
94
|
8: { // mixed 16-bit and 32-bit coverage
|
|
76
95
|
reserved: new r.Reserved(r.uint16),
|
|
77
|
-
length:
|
|
96
|
+
length: r.uint32,
|
|
78
97
|
language: r.uint16,
|
|
79
|
-
is32:
|
|
80
|
-
nGroups:
|
|
81
|
-
groups:
|
|
98
|
+
is32: new r.LazyArray(r.uint8, 8192),
|
|
99
|
+
nGroups: r.uint32,
|
|
100
|
+
groups: new r.LazyArray(CmapGroup, 'nGroups')
|
|
82
101
|
},
|
|
83
102
|
|
|
84
103
|
10: { // Trimmed Array
|
|
85
|
-
reserved:
|
|
86
|
-
length:
|
|
87
|
-
language:
|
|
88
|
-
firstCode:
|
|
89
|
-
entryCount:
|
|
90
|
-
glyphIndices:
|
|
104
|
+
reserved: new r.Reserved(r.uint16),
|
|
105
|
+
length: r.uint32,
|
|
106
|
+
language: r.uint32,
|
|
107
|
+
firstCode: r.uint32,
|
|
108
|
+
entryCount: r.uint32, // OpenType name: numChars
|
|
109
|
+
glyphIndices: new r.LazyArray(r.uint16, 'entryCount')
|
|
91
110
|
},
|
|
92
111
|
|
|
93
112
|
12: { // Segmented coverage
|
|
94
113
|
reserved: new r.Reserved(r.uint16),
|
|
95
|
-
length:
|
|
114
|
+
length: r.uint32,
|
|
96
115
|
language: r.uint32,
|
|
97
|
-
nGroups:
|
|
98
|
-
groups:
|
|
116
|
+
nGroups: r.uint32,
|
|
117
|
+
groups: new r.LazyArray(CmapGroup, 'nGroups')
|
|
99
118
|
},
|
|
100
119
|
|
|
101
120
|
13: { // Many-to-one range mappings (same as 12 except for group.startGlyphID)
|
|
102
121
|
reserved: new r.Reserved(r.uint16),
|
|
103
|
-
length:
|
|
122
|
+
length: r.uint32,
|
|
104
123
|
language: r.uint32,
|
|
105
|
-
nGroups:
|
|
106
|
-
groups:
|
|
124
|
+
nGroups: r.uint32,
|
|
125
|
+
groups: new r.LazyArray(CmapGroup, 'nGroups')
|
|
107
126
|
},
|
|
108
127
|
|
|
109
128
|
14: { // Unicode Variation Sequences
|
|
110
|
-
length:
|
|
111
|
-
numRecords:
|
|
129
|
+
length: r.uint32,
|
|
130
|
+
numRecords: r.uint32,
|
|
112
131
|
varSelectors: new r.LazyArray(VarSelectorRecord, 'numRecords')
|
|
113
132
|
}
|
|
114
133
|
});
|
|
115
134
|
|
|
116
135
|
let CmapEntry = new r.Struct({
|
|
117
|
-
platformID:
|
|
118
|
-
encodingID:
|
|
119
|
-
table:
|
|
136
|
+
platformID: r.uint16, // Platform identifier
|
|
137
|
+
encodingID: r.uint16, // Platform-specific encoding identifier
|
|
138
|
+
table: new r.Pointer(r.uint32, CmapSubtable, { type: 'parent', lazy: true })
|
|
120
139
|
});
|
|
121
140
|
|
|
122
141
|
// character to glyph mapping
|
|
142
|
+
/** @type {import('restructure').Struct} */
|
|
123
143
|
export default new r.Struct({
|
|
124
|
-
version:
|
|
144
|
+
version: r.uint16,
|
|
125
145
|
numSubtables: r.uint16,
|
|
126
|
-
tables:
|
|
146
|
+
tables: new r.Array(CmapEntry, 'numSubtables')
|
|
127
147
|
});
|
package/src/tables/cvt.js
CHANGED
package/src/tables/directory.js
CHANGED
|
@@ -1,58 +1,86 @@
|
|
|
1
1
|
import * as r from 'restructure';
|
|
2
2
|
import Tables from './';
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
/** @typedef {import('restructure').StructValue} StructValue */
|
|
5
|
+
/** @typedef {import('../../types/fontkit').TableEntry} TableEntry */
|
|
6
|
+
/** @typedef {import('../../types/fontkit').TableCodec} TableCodec */
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @typedef {StructValue & {
|
|
10
|
+
* tag: string,
|
|
11
|
+
* numTables: number,
|
|
12
|
+
* searchRange: number,
|
|
13
|
+
* entrySelector: number,
|
|
14
|
+
* rangeShift: number,
|
|
15
|
+
* tables: TableEntry[] | Record<string, TableEntry>
|
|
16
|
+
* }} DirectoryValue
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
let TableEntryStruct = new r.Struct({
|
|
20
|
+
tag: new r.String(4),
|
|
21
|
+
checkSum: r.uint32,
|
|
22
|
+
offset: new r.Pointer(r.uint32, 'void', { type: 'global' }),
|
|
23
|
+
length: r.uint32
|
|
9
24
|
});
|
|
10
25
|
|
|
26
|
+
/** @type {import('restructure').Struct} */
|
|
11
27
|
let Directory = new r.Struct({
|
|
12
|
-
tag:
|
|
13
|
-
numTables:
|
|
14
|
-
searchRange:
|
|
15
|
-
entrySelector:
|
|
16
|
-
rangeShift:
|
|
17
|
-
tables:
|
|
28
|
+
tag: new r.String(4),
|
|
29
|
+
numTables: r.uint16,
|
|
30
|
+
searchRange: r.uint16,
|
|
31
|
+
entrySelector: r.uint16,
|
|
32
|
+
rangeShift: r.uint16,
|
|
33
|
+
tables: new r.Array(TableEntryStruct, 'numTables')
|
|
18
34
|
});
|
|
19
35
|
|
|
20
|
-
Directory.process = function() {
|
|
36
|
+
Directory.process = function () {
|
|
37
|
+
let self = /** @type {DirectoryValue} */ (this);
|
|
38
|
+
/** @type {Record<string, TableEntry>} */
|
|
21
39
|
let tables = {};
|
|
22
|
-
for (let table of
|
|
40
|
+
for (let table of /** @type {TableEntry[]} */ (self.tables)) {
|
|
23
41
|
tables[table.tag] = table;
|
|
24
42
|
}
|
|
25
43
|
|
|
26
|
-
|
|
44
|
+
self.tables = tables;
|
|
27
45
|
};
|
|
28
46
|
|
|
29
|
-
Directory.preEncode = function() {
|
|
30
|
-
|
|
47
|
+
Directory.preEncode = function () {
|
|
48
|
+
let self = /** @type {DirectoryValue} */ (this);
|
|
49
|
+
if (!Array.isArray(self.tables)) {
|
|
50
|
+
/** @type {TableEntry[]} */
|
|
31
51
|
let tables = [];
|
|
32
|
-
|
|
33
|
-
|
|
52
|
+
/** @type {Record<string, TableEntry>} */
|
|
53
|
+
let byTag = self.tables;
|
|
54
|
+
for (let tag of Object.keys(byTag)) {
|
|
55
|
+
let table = byTag[tag];
|
|
34
56
|
if (table) {
|
|
57
|
+
let codec = /** @type {TableCodec | undefined} */ (Tables[tag]);
|
|
58
|
+
if (!codec || typeof codec.size !== 'function') {
|
|
59
|
+
throw new Error(`Missing encoder for table "${tag}"`);
|
|
60
|
+
}
|
|
35
61
|
tables.push({
|
|
36
62
|
tag: tag,
|
|
37
63
|
checkSum: 0,
|
|
38
|
-
offset:
|
|
39
|
-
|
|
64
|
+
offset: /** @type {number} */ (/** @type {unknown} */ (
|
|
65
|
+
new r.VoidPointer(/** @type {import('restructure').BaseType} */ (/** @type {unknown} */ (codec)), table)
|
|
66
|
+
)),
|
|
67
|
+
length: codec.size(table)
|
|
40
68
|
});
|
|
41
69
|
}
|
|
42
70
|
}
|
|
43
|
-
|
|
44
|
-
|
|
71
|
+
|
|
72
|
+
self.tables = tables;
|
|
45
73
|
}
|
|
46
74
|
|
|
47
|
-
|
|
48
|
-
|
|
75
|
+
self.tag = 'true';
|
|
76
|
+
self.numTables = self.tables.length;
|
|
49
77
|
|
|
50
|
-
let maxExponentFor2 = Math.floor((Math.log(
|
|
78
|
+
let maxExponentFor2 = Math.floor((Math.log(self.numTables) / Math.LN2));
|
|
51
79
|
let maxPowerOf2 = Math.pow(2, maxExponentFor2);
|
|
52
80
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
81
|
+
self.searchRange = maxPowerOf2 * 16;
|
|
82
|
+
self.entrySelector = Math.log(maxPowerOf2) / Math.LN2;
|
|
83
|
+
self.rangeShift = self.numTables * 16 - self.searchRange;
|
|
56
84
|
};
|
|
57
85
|
|
|
58
86
|
export default Directory;
|