@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.
Files changed (142) hide show
  1. package/dist/browser-module.mjs +4448 -1142
  2. package/dist/browser-module.mjs.map +1 -1
  3. package/dist/browser.cjs +4449 -1142
  4. package/dist/browser.cjs.map +1 -1
  5. package/dist/main.cjs +4449 -1142
  6. package/dist/main.cjs.map +1 -1
  7. package/dist/module.mjs +4448 -1142
  8. package/dist/module.mjs.map +1 -1
  9. package/package.json +4 -1
  10. package/src/CmapProcessor.js +60 -21
  11. package/src/DFont.js +114 -14
  12. package/src/TTFFont.js +260 -62
  13. package/src/TrueTypeCollection.js +59 -15
  14. package/src/WOFF2Font.js +128 -22
  15. package/src/WOFFFont.js +45 -8
  16. package/src/aat/AATFeatureMap.js +83 -40
  17. package/src/aat/AATLayoutEngine.js +34 -2
  18. package/src/aat/AATLookupTable.js +24 -6
  19. package/src/aat/AATMorxProcessor.js +202 -65
  20. package/src/aat/AATStateMachine.js +35 -3
  21. package/src/base.js +20 -1
  22. package/src/cff/CFFCharsets.js +3 -0
  23. package/src/cff/CFFDict.js +81 -11
  24. package/src/cff/CFFEncodings.js +2 -0
  25. package/src/cff/CFFFont.js +120 -24
  26. package/src/cff/CFFIndex.js +66 -9
  27. package/src/cff/CFFOperand.js +53 -28
  28. package/src/cff/CFFPointer.js +41 -2
  29. package/src/cff/CFFPrivateDict.js +34 -24
  30. package/src/cff/CFFStandardStrings.js +68 -67
  31. package/src/cff/CFFTop.js +161 -68
  32. package/src/decorators.js +34 -15
  33. package/src/encodings.js +133 -116
  34. package/src/fs.js +10 -0
  35. package/src/glyph/BBox.js +14 -0
  36. package/src/glyph/CFFGlyph.js +293 -152
  37. package/src/glyph/COLRGlyph.js +40 -5
  38. package/src/glyph/Glyph.js +72 -13
  39. package/src/glyph/GlyphVariationProcessor.js +158 -62
  40. package/src/glyph/Path.js +119 -32
  41. package/src/glyph/SBIXGlyph.js +57 -8
  42. package/src/glyph/StandardNames.js +1 -0
  43. package/src/glyph/TTFGlyph.js +203 -63
  44. package/src/glyph/TTFGlyphEncoder.js +58 -26
  45. package/src/glyph/WOFF2Glyph.js +25 -6
  46. package/src/layout/GlyphPosition.js +6 -0
  47. package/src/layout/GlyphRun.js +28 -10
  48. package/src/layout/KernProcessor.js +63 -4
  49. package/src/layout/LayoutEngine.js +99 -26
  50. package/src/layout/Script.js +52 -26
  51. package/src/layout/UnicodeLayoutEngine.js +34 -10
  52. package/src/opentype/GPOSProcessor.js +156 -45
  53. package/src/opentype/GSUBProcessor.js +92 -33
  54. package/src/opentype/GlyphInfo.js +53 -5
  55. package/src/opentype/GlyphIterator.js +51 -2
  56. package/src/opentype/OTLayoutEngine.js +66 -8
  57. package/src/opentype/OTProcessor.js +284 -71
  58. package/src/opentype/ShapingPlan.js +52 -5
  59. package/src/opentype/shapers/ArabicShaper.js +27 -8
  60. package/src/opentype/shapers/DefaultShaper.js +54 -10
  61. package/src/opentype/shapers/HangulShaper.js +120 -42
  62. package/src/opentype/shapers/HebrewShaper.js +50 -16
  63. package/src/opentype/shapers/IndicShaper.js +159 -44
  64. package/src/opentype/shapers/ThaiShaper.js +50 -19
  65. package/src/opentype/shapers/UniversalShaper.js +83 -17
  66. package/src/opentype/shapers/index.js +48 -35
  67. package/src/opentype/shapers/indic-data.js +2 -2
  68. package/src/packages/unicode-properties/data-trie.js +2 -1
  69. package/src/packages/unicode-properties/data.js +13 -1
  70. package/src/packages/unicode-properties/dist/index.cjs +23 -10
  71. package/src/packages/unicode-properties/dist/index.cjs.map +2 -2
  72. package/src/packages/unicode-properties/dist/index.mjs +22 -10
  73. package/src/packages/unicode-properties/dist/index.mjs.map +2 -2
  74. package/src/packages/unicode-properties/generate.js +3 -4
  75. package/src/packages/unicode-properties/index.js +95 -30
  76. package/src/packages/unicode-properties/package.json +1 -1
  77. package/src/packages/unicode-trie/builder.js +146 -29
  78. package/src/packages/unicode-trie/dist/builder.cjs +135 -25
  79. package/src/packages/unicode-trie/dist/builder.cjs.map +2 -2
  80. package/src/packages/unicode-trie/dist/builder.mjs +134 -25
  81. package/src/packages/unicode-trie/dist/builder.mjs.map +2 -2
  82. package/src/packages/unicode-trie/dist/index.cjs +22 -9
  83. package/src/packages/unicode-trie/dist/index.cjs.map +2 -2
  84. package/src/packages/unicode-trie/dist/index.mjs +21 -9
  85. package/src/packages/unicode-trie/dist/index.mjs.map +2 -2
  86. package/src/packages/unicode-trie/index.js +63 -12
  87. package/src/packages/unicode-trie/package.json +1 -1
  88. package/src/packages/unicode-trie/swap.js +15 -2
  89. package/src/subset/CFFSubset.js +112 -22
  90. package/src/subset/Subset.js +23 -3
  91. package/src/subset/TTFSubset.js +84 -41
  92. package/src/tables/BASE.js +28 -27
  93. package/src/tables/COLR.js +10 -9
  94. package/src/tables/CPAL.js +2 -1
  95. package/src/tables/DSIG.js +8 -7
  96. package/src/tables/EBDT.js +10 -4
  97. package/src/tables/EBLC.js +70 -10
  98. package/src/tables/GDEF.js +18 -17
  99. package/src/tables/GPOS.js +153 -90
  100. package/src/tables/GSUB.js +50 -39
  101. package/src/tables/HVAR.js +51 -5
  102. package/src/tables/JSTF.js +17 -16
  103. package/src/tables/LTSH.js +4 -3
  104. package/src/tables/OS2.js +50 -49
  105. package/src/tables/PCLT.js +16 -15
  106. package/src/tables/STAT.js +46 -6
  107. package/src/tables/VDMX.js +18 -17
  108. package/src/tables/VORG.js +8 -7
  109. package/src/tables/WOFF2Directory.js +57 -9
  110. package/src/tables/WOFFDirectory.js +32 -20
  111. package/src/tables/aat.js +160 -35
  112. package/src/tables/avar.js +1 -0
  113. package/src/tables/bsln.js +3 -2
  114. package/src/tables/cmap.js +83 -63
  115. package/src/tables/cvt.js +1 -0
  116. package/src/tables/directory.js +56 -28
  117. package/src/tables/feat.js +24 -2
  118. package/src/tables/fpgm.js +1 -0
  119. package/src/tables/fvar.js +32 -4
  120. package/src/tables/gasp.js +6 -5
  121. package/src/tables/glyf.js +2 -1
  122. package/src/tables/gvar.js +29 -2
  123. package/src/tables/hdmx.js +18 -7
  124. package/src/tables/head.js +17 -16
  125. package/src/tables/hhea.js +15 -14
  126. package/src/tables/hmtx.js +18 -2
  127. package/src/tables/index.js +1 -5
  128. package/src/tables/just.js +15 -4
  129. package/src/tables/kern.js +84 -47
  130. package/src/tables/loca.js +23 -10
  131. package/src/tables/maxp.js +16 -15
  132. package/src/tables/morx.js +27 -20
  133. package/src/tables/name.js +120 -39
  134. package/src/tables/opbd.js +2 -1
  135. package/src/tables/opentype.js +126 -91
  136. package/src/tables/post.js +18 -11
  137. package/src/tables/prep.js +1 -0
  138. package/src/tables/sbix.js +12 -1
  139. package/src/tables/variations.js +29 -9
  140. package/src/tables/vhea.js +15 -14
  141. package/src/tables/vmtx.js +20 -4
  142. 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
- this.stream.pos = this.base + this.type.size(null, this.parent) * index;
16
- this._items[index] = this.type.decode(this.stream, this.parent);
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
- return `[UnboundedArray ${this.type.constructor.name}]`;
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
- export class UnboundedArray extends r.Array {
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
- super(type, 0);
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
- export let LookupTable = function(ValueType = r.uint16) {
39
- // Helper class that makes internal structures invisible to pointers
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
- ctx = ctx.parent.parent;
47
- return this.type.decode(stream, ctx);
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
- ctx = ctx.parent.parent;
52
- return this.type.size(val, ctx);
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
- ctx = ctx.parent.parent;
57
- return this.type.encode(stream, val, ctx);
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
- ValueType = new Shadow(ValueType);
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: ValueType
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(r.uint16, new r.Array(ValueType, t => t.lastGlyph - t.firstGlyph + 1), {type: 'parent'})
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: ValueType
164
+ value: shadowed
86
165
  });
87
166
 
88
167
  return new r.VersionedStruct(r.uint16, {
89
168
  0: {
90
- values: new UnboundedArray(ValueType) // length == number of glyphs maybe?
169
+ values: new UnboundedArray(shadowed) // length == number of glyphs maybe?
91
170
  },
92
171
  2: {
93
172
  binarySearchHeader: BinarySearchHeader,
94
- segments: new r.Array(LookupSegmentSingle, t => t.binarySearchHeader.nUnits)
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(LookupSegmentArray, t => t.binarySearchHeader.nUnits)
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(LookupSingle, t => t.binarySearchHeader.nUnits)
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(ValueType, 'count')
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(new r.Array(r.uint16, t => t.nClasses));
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
- let StateHeader = new r.Struct({
223
+ return new r.Struct({
122
224
  nClasses: r.uint32,
123
- classTable: new r.Pointer(r.uint32, new LookupTable(lookupType)),
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
- // This is the old version of the StateTable structure
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
- // convert offset to stateArray index
142
- newState: t => (t.newStateOffset - (t.parent.stateArray.base - t.parent._startOffset)) / t.parent.nClasses,
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(new r.Array(r.uint8, t => t.nClasses));
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
- let StateHeader1 = new r.Struct({
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
  }
@@ -12,6 +12,7 @@ let Segment = new r.Struct({
12
12
  correspondence: new r.Array(Correspondence, 'pairCount')
13
13
  });
14
14
 
15
+ /** @type {import('restructure').Struct} */
15
16
  export default new r.Struct({
16
17
  version: r.fixed32,
17
18
  axisCount: r.uint32,
@@ -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: new LookupTable(r.uint16)
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: new LookupTable(r.uint16)
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,
@@ -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: r.uint16,
5
- entryCount: r.uint16,
6
- idDelta: r.int16,
7
- idRangeOffset: r.uint16
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: r.uint32,
12
- endCharCode: r.uint32,
13
- glyphID: r.uint32
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: r.uint24,
18
- additionalCount: r.uint8
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: r.uint16
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: r.uint24,
31
- defaultUVS: new r.Pointer(r.uint32, DefaultUVS, {type: 'parent'}),
32
- nonDefaultUVS: new r.Pointer(r.uint32, NonDefaultUVS, {type: 'parent'})
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: r.uint16, // Total table length in bytes (set to 262 for format 0)
38
- language: r.uint16, // Language code for this encoding subtable, or zero if language-independent
39
- codeMap: new r.LazyArray(r.uint8, 256)
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: r.uint16,
44
- language: r.uint16,
45
- subHeaderKeys: new r.Array(r.uint16, 256),
46
- subHeaderCount: t => Math.max.apply(Math, t.subHeaderKeys),
47
- subHeaders: new r.LazyArray(SubHeader, 'subHeaderCount'),
48
- glyphIndexArray: new r.LazyArray(r.uint16, 'subHeaderCount')
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: r.uint16, // Total table length in bytes
53
- language: r.uint16, // Language code
54
- segCountX2: r.uint16,
55
- segCount: t => t.segCountX2 >> 1,
56
- searchRange: r.uint16,
57
- entrySelector: r.uint16,
58
- rangeShift: r.uint16,
59
- endCode: new r.LazyArray(r.uint16, 'segCount'),
60
- reservedPad: new r.Reserved(r.uint16), // This value should be zero
61
- startCode: new r.LazyArray(r.uint16, 'segCount'),
62
- idDelta: new r.LazyArray(r.int16, 'segCount'),
63
- idRangeOffset: new r.LazyArray(r.uint16, 'segCount'),
64
- glyphIndexArray: new r.LazyArray(r.uint16, t => (t.length - t._currentOffset) / 2)
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: r.uint16,
69
- language: r.uint16,
70
- firstCode: r.uint16,
71
- entryCount: r.uint16,
72
- glyphIndices: new r.LazyArray(r.uint16, 'entryCount')
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: r.uint32,
96
+ length: r.uint32,
78
97
  language: r.uint16,
79
- is32: new r.LazyArray(r.uint8, 8192),
80
- nGroups: r.uint32,
81
- groups: new r.LazyArray(CmapGroup, 'nGroups')
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: new r.Reserved(r.uint16),
86
- length: r.uint32,
87
- language: r.uint32,
88
- firstCode: r.uint32,
89
- entryCount: r.uint32,
90
- glyphIndices: new r.LazyArray(r.uint16, 'numChars')
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: r.uint32,
114
+ length: r.uint32,
96
115
  language: r.uint32,
97
- nGroups: r.uint32,
98
- groups: new r.LazyArray(CmapGroup, 'nGroups')
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: r.uint32,
122
+ length: r.uint32,
104
123
  language: r.uint32,
105
- nGroups: r.uint32,
106
- groups: new r.LazyArray(CmapGroup, 'nGroups')
124
+ nGroups: r.uint32,
125
+ groups: new r.LazyArray(CmapGroup, 'nGroups')
107
126
  },
108
127
 
109
128
  14: { // Unicode Variation Sequences
110
- length: r.uint32,
111
- numRecords: r.uint32,
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: r.uint16, // Platform identifier
118
- encodingID: r.uint16, // Platform-specific encoding identifier
119
- table: new r.Pointer(r.uint32, CmapSubtable, {type: 'parent', lazy: true})
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: r.uint16,
144
+ version: r.uint16,
125
145
  numSubtables: r.uint16,
126
- tables: new r.Array(CmapEntry, 'numSubtables')
146
+ tables: new r.Array(CmapEntry, 'numSubtables')
127
147
  });
package/src/tables/cvt.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import * as r from 'restructure';
2
2
 
3
3
  // An array of predefined values accessible by instructions
4
+ /** @type {import('restructure').Struct} */
4
5
  export default new r.Struct({
5
6
  controlValues: new r.Array(r.int16)
6
7
  });
@@ -1,58 +1,86 @@
1
1
  import * as r from 'restructure';
2
2
  import Tables from './';
3
3
 
4
- let TableEntry = new r.Struct({
5
- tag: new r.String(4),
6
- checkSum: r.uint32,
7
- offset: new r.Pointer(r.uint32, 'void', { type: 'global' }),
8
- length: r.uint32
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: new r.String(4),
13
- numTables: r.uint16,
14
- searchRange: r.uint16,
15
- entrySelector: r.uint16,
16
- rangeShift: r.uint16,
17
- tables: new r.Array(TableEntry, 'numTables')
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 this.tables) {
40
+ for (let table of /** @type {TableEntry[]} */ (self.tables)) {
23
41
  tables[table.tag] = table;
24
42
  }
25
43
 
26
- this.tables = tables;
44
+ self.tables = tables;
27
45
  };
28
46
 
29
- Directory.preEncode = function() {
30
- if (!Array.isArray(this.tables)) {
47
+ Directory.preEncode = function () {
48
+ let self = /** @type {DirectoryValue} */ (this);
49
+ if (!Array.isArray(self.tables)) {
50
+ /** @type {TableEntry[]} */
31
51
  let tables = [];
32
- for (let tag in this.tables) {
33
- let table = this.tables[tag];
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: new r.VoidPointer(Tables[tag], table),
39
- length: Tables[tag].size(table)
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
- this.tables = tables;
71
+
72
+ self.tables = tables;
45
73
  }
46
74
 
47
- this.tag = 'true';
48
- this.numTables = this.tables.length;
75
+ self.tag = 'true';
76
+ self.numTables = self.tables.length;
49
77
 
50
- let maxExponentFor2 = Math.floor((Math.log(this.numTables) / Math.LN2));
78
+ let maxExponentFor2 = Math.floor((Math.log(self.numTables) / Math.LN2));
51
79
  let maxPowerOf2 = Math.pow(2, maxExponentFor2);
52
80
 
53
- this.searchRange = maxPowerOf2 * 16;
54
- this.entrySelector = Math.log(maxPowerOf2) / Math.LN2;
55
- this.rangeShift = this.numTables * 16 - this.searchRange;
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;