@cantoo/fontkit 2.0.5 → 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 (140) hide show
  1. package/dist/browser-module.mjs +4423 -1117
  2. package/dist/browser-module.mjs.map +1 -1
  3. package/dist/browser.cjs +4424 -1117
  4. package/dist/browser.cjs.map +1 -1
  5. package/dist/main.cjs +4424 -1117
  6. package/dist/main.cjs.map +1 -1
  7. package/dist/module.mjs +4423 -1117
  8. package/dist/module.mjs.map +1 -1
  9. package/package.json +3 -1
  10. package/src/CmapProcessor.js +59 -20
  11. package/src/DFont.js +114 -14
  12. package/src/TTFFont.js +259 -57
  13. package/src/TrueTypeCollection.js +54 -10
  14. package/src/WOFF2Font.js +128 -16
  15. package/src/WOFFFont.js +45 -8
  16. package/src/aat/AATFeatureMap.js +62 -18
  17. package/src/aat/AATLayoutEngine.js +33 -1
  18. package/src/aat/AATLookupTable.js +22 -4
  19. package/src/aat/AATMorxProcessor.js +189 -52
  20. package/src/aat/AATStateMachine.js +32 -0
  21. package/src/base.js +19 -0
  22. package/src/cff/CFFCharsets.js +3 -0
  23. package/src/cff/CFFDict.js +79 -9
  24. package/src/cff/CFFEncodings.js +2 -0
  25. package/src/cff/CFFFont.js +119 -23
  26. package/src/cff/CFFIndex.js +62 -5
  27. package/src/cff/CFFOperand.js +52 -17
  28. package/src/cff/CFFPointer.js +41 -2
  29. package/src/cff/CFFPrivateDict.js +14 -4
  30. package/src/cff/CFFStandardStrings.js +1 -0
  31. package/src/cff/CFFTop.js +103 -10
  32. package/src/decorators.js +32 -13
  33. package/src/encodings.js +22 -5
  34. package/src/fs.js +10 -0
  35. package/src/glyph/BBox.js +14 -0
  36. package/src/glyph/CFFGlyph.js +290 -148
  37. package/src/glyph/COLRGlyph.js +38 -3
  38. package/src/glyph/Glyph.js +68 -9
  39. package/src/glyph/GlyphVariationProcessor.js +135 -34
  40. package/src/glyph/Path.js +107 -20
  41. package/src/glyph/SBIXGlyph.js +57 -8
  42. package/src/glyph/StandardNames.js +1 -0
  43. package/src/glyph/TTFGlyph.js +176 -29
  44. package/src/glyph/TTFGlyphEncoder.js +32 -0
  45. package/src/glyph/WOFF2Glyph.js +23 -4
  46. package/src/layout/GlyphPosition.js +6 -0
  47. package/src/layout/GlyphRun.js +25 -7
  48. package/src/layout/KernProcessor.js +62 -3
  49. package/src/layout/LayoutEngine.js +86 -12
  50. package/src/layout/Script.js +27 -1
  51. package/src/layout/UnicodeLayoutEngine.js +29 -4
  52. package/src/opentype/GPOSProcessor.js +156 -45
  53. package/src/opentype/GSUBProcessor.js +92 -33
  54. package/src/opentype/GlyphInfo.js +52 -4
  55. package/src/opentype/GlyphIterator.js +51 -2
  56. package/src/opentype/OTLayoutEngine.js +66 -8
  57. package/src/opentype/OTProcessor.js +283 -70
  58. package/src/opentype/ShapingPlan.js +51 -3
  59. package/src/opentype/shapers/ArabicShaper.js +19 -0
  60. package/src/opentype/shapers/DefaultShaper.js +51 -7
  61. package/src/opentype/shapers/HangulShaper.js +85 -7
  62. package/src/opentype/shapers/HebrewShaper.js +45 -11
  63. package/src/opentype/shapers/IndicShaper.js +141 -26
  64. package/src/opentype/shapers/ThaiShaper.js +35 -4
  65. package/src/opentype/shapers/UniversalShaper.js +83 -17
  66. package/src/opentype/shapers/index.js +15 -2
  67. package/src/packages/unicode-properties/data-trie.js +1 -0
  68. package/src/packages/unicode-properties/data.js +12 -0
  69. package/src/packages/unicode-properties/dist/index.cjs +22 -9
  70. package/src/packages/unicode-properties/dist/index.cjs.map +2 -2
  71. package/src/packages/unicode-properties/dist/index.mjs +21 -9
  72. package/src/packages/unicode-properties/dist/index.mjs.map +2 -2
  73. package/src/packages/unicode-properties/index.js +65 -0
  74. package/src/packages/unicode-properties/package.json +1 -1
  75. package/src/packages/unicode-trie/builder.js +128 -7
  76. package/src/packages/unicode-trie/dist/builder.cjs +129 -16
  77. package/src/packages/unicode-trie/dist/builder.cjs.map +2 -2
  78. package/src/packages/unicode-trie/dist/builder.mjs +128 -16
  79. package/src/packages/unicode-trie/dist/builder.mjs.map +2 -2
  80. package/src/packages/unicode-trie/dist/index.cjs +22 -9
  81. package/src/packages/unicode-trie/dist/index.cjs.map +2 -2
  82. package/src/packages/unicode-trie/dist/index.mjs +21 -9
  83. package/src/packages/unicode-trie/dist/index.mjs.map +2 -2
  84. package/src/packages/unicode-trie/index.js +62 -10
  85. package/src/packages/unicode-trie/package.json +1 -1
  86. package/src/packages/unicode-trie/swap.js +13 -0
  87. package/src/subset/CFFSubset.js +112 -22
  88. package/src/subset/Subset.js +21 -1
  89. package/src/subset/TTFSubset.js +79 -36
  90. package/src/tables/BASE.js +1 -0
  91. package/src/tables/COLR.js +1 -0
  92. package/src/tables/CPAL.js +1 -0
  93. package/src/tables/DSIG.js +1 -0
  94. package/src/tables/EBDT.js +10 -3
  95. package/src/tables/EBLC.js +67 -7
  96. package/src/tables/GDEF.js +1 -0
  97. package/src/tables/GPOS.js +79 -16
  98. package/src/tables/GSUB.js +14 -3
  99. package/src/tables/HVAR.js +51 -5
  100. package/src/tables/JSTF.js +3 -2
  101. package/src/tables/LTSH.js +1 -0
  102. package/src/tables/OS2.js +1 -0
  103. package/src/tables/PCLT.js +1 -0
  104. package/src/tables/STAT.js +46 -6
  105. package/src/tables/VDMX.js +1 -0
  106. package/src/tables/VORG.js +1 -0
  107. package/src/tables/WOFF2Directory.js +56 -8
  108. package/src/tables/WOFFDirectory.js +14 -2
  109. package/src/tables/aat.js +160 -35
  110. package/src/tables/avar.js +1 -0
  111. package/src/tables/bsln.js +3 -2
  112. package/src/tables/cmap.js +26 -6
  113. package/src/tables/cvt.js +1 -0
  114. package/src/tables/directory.js +44 -16
  115. package/src/tables/feat.js +24 -2
  116. package/src/tables/fpgm.js +1 -0
  117. package/src/tables/fvar.js +32 -4
  118. package/src/tables/gasp.js +1 -0
  119. package/src/tables/glyf.js +1 -0
  120. package/src/tables/gvar.js +29 -2
  121. package/src/tables/hdmx.js +12 -1
  122. package/src/tables/head.js +1 -0
  123. package/src/tables/hhea.js +1 -0
  124. package/src/tables/hmtx.js +18 -2
  125. package/src/tables/index.js +1 -0
  126. package/src/tables/just.js +15 -4
  127. package/src/tables/kern.js +43 -6
  128. package/src/tables/loca.js +21 -8
  129. package/src/tables/maxp.js +1 -0
  130. package/src/tables/morx.js +14 -7
  131. package/src/tables/name.js +104 -23
  132. package/src/tables/opbd.js +2 -1
  133. package/src/tables/opentype.js +39 -4
  134. package/src/tables/post.js +8 -1
  135. package/src/tables/prep.js +1 -0
  136. package/src/tables/sbix.js +12 -1
  137. package/src/tables/variations.js +23 -3
  138. package/src/tables/vhea.js +1 -0
  139. package/src/tables/vmtx.js +18 -2
  140. package/src/utils.js +15 -0
@@ -1,6 +1,19 @@
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').StructValue} StructValue */
6
+ /** @typedef {import('../../types/fontkit').TableEntry} TableEntry */
7
+
8
+ /**
9
+ * WOFF2 variable-length unsigned integer (Base128).
10
+ * @type {BaseType}
11
+ */
3
12
  const Base128 = {
13
+ /**
14
+ * @param {DecodeStream} stream
15
+ * @returns {number}
16
+ */
4
17
  decode(stream) {
5
18
  let result = 0;
6
19
  let iterable = [0, 1, 2, 3, 4];
@@ -34,14 +47,46 @@ let knownTags = [
34
47
 
35
48
  let WOFF2DirectoryEntry = new r.Struct({
36
49
  flags: r.uint8,
37
- customTag: new r.Optional(new r.String(4), t => (t.flags & 0x3f) === 0x3f),
38
- tag: t => t.customTag || knownTags[t.flags & 0x3f], // || (() => { throw new Error(`Bad tag: ${flags & 0x3f}`); })(); },
50
+ customTag: new r.Optional(
51
+ new r.String(4),
52
+ /** @param {StructValue} t @returns {boolean} */
53
+ t => (/** @type {number} */ (t.flags) & 0x3f) === 0x3f
54
+ ),
55
+ /**
56
+ * @param {StructValue} t
57
+ * @returns {string}
58
+ */
59
+ tag: (t) => {
60
+ let flags = /** @type {number} */ (t.flags);
61
+ return /** @type {string} */ (t.customTag) || knownTags[flags & 0x3f];
62
+ },
39
63
  length: Base128,
40
- transformVersion: t => (t.flags >>> 6) & 0x03,
41
- transformed: t => (t.tag === 'glyf' || t.tag === 'loca') ? t.transformVersion === 0 : t.transformVersion !== 0,
42
- transformLength: new r.Optional(Base128, t => t.transformed)
64
+ /**
65
+ * @param {StructValue} t
66
+ * @returns {number}
67
+ */
68
+ transformVersion: t => (/** @type {number} */ (t.flags) >>> 6) & 0x03,
69
+ /**
70
+ * @param {StructValue} t
71
+ * @returns {boolean}
72
+ */
73
+ transformed: t => (t.tag === 'glyf' || t.tag === 'loca')
74
+ ? t.transformVersion === 0
75
+ : t.transformVersion !== 0,
76
+ transformLength: new r.Optional(
77
+ Base128,
78
+ /** @param {StructValue} t @returns {boolean} */
79
+ t => !!t.transformed
80
+ )
43
81
  });
44
82
 
83
+ /**
84
+ * @typedef {StructValue & {
85
+ * tables: TableEntry[] | Record<string, TableEntry>
86
+ * }} WOFF2DirectoryValue
87
+ */
88
+
89
+ /** @type {import('restructure').Struct} */
45
90
  let WOFF2Directory = new r.Struct({
46
91
  tag: new r.String(4), // should be 'wOF2'
47
92
  flavor: r.uint32,
@@ -61,13 +106,16 @@ let WOFF2Directory = new r.Struct({
61
106
  });
62
107
 
63
108
  WOFF2Directory.process = function () {
109
+ let self = /** @type {WOFF2DirectoryValue} */ (this);
110
+ /** @type {Record<string, TableEntry>} */
64
111
  let tables = {};
65
- for (let i = 0; i < this.tables.length; i++) {
66
- let table = this.tables[i];
112
+ let list = /** @type {TableEntry[]} */ (self.tables);
113
+ for (let i = 0; i < list.length; i++) {
114
+ let table = list[i];
67
115
  tables[table.tag] = table;
68
116
  }
69
117
 
70
- return this.tables = tables;
118
+ self.tables = tables;
71
119
  };
72
120
 
73
121
  export default WOFF2Directory;
@@ -1,5 +1,14 @@
1
1
  import * as r from 'restructure';
2
2
 
3
+ /** @typedef {import('restructure').StructValue} StructValue */
4
+ /** @typedef {import('../../types/fontkit').TableEntry} TableEntry */
5
+
6
+ /**
7
+ * @typedef {StructValue & {
8
+ * tables: TableEntry[] | Record<string, TableEntry>
9
+ * }} WOFFDirectoryValue
10
+ */
11
+
3
12
  let WOFFDirectoryEntry = new r.Struct({
4
13
  tag: new r.String(4),
5
14
  offset: new r.Pointer(r.uint32, 'void', { type: 'global' }),
@@ -8,6 +17,7 @@ let WOFFDirectoryEntry = new r.Struct({
8
17
  origChecksum: r.uint32
9
18
  });
10
19
 
20
+ /** @type {import('restructure').Struct} */
11
21
  let WOFFDirectory = new r.Struct({
12
22
  tag: new r.String(4), // should be 'wOFF'
13
23
  flavor: r.uint32,
@@ -26,12 +36,14 @@ let WOFFDirectory = new r.Struct({
26
36
  });
27
37
 
28
38
  WOFFDirectory.process = function () {
39
+ let self = /** @type {WOFFDirectoryValue} */ (this);
40
+ /** @type {Record<string, TableEntry>} */
29
41
  let tables = {};
30
- for (let table of this.tables) {
42
+ for (let table of /** @type {TableEntry[]} */ (self.tables)) {
31
43
  tables[table.tag] = table;
32
44
  }
33
45
 
34
- this.tables = tables;
46
+ self.tables = tables;
35
47
  };
36
48
 
37
49
  export default WOFFDirectory;
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,5 +1,7 @@
1
1
  import * as r from 'restructure';
2
2
 
3
+ /** @typedef {import('restructure').StructValue} StructValue */
4
+
3
5
  let SubHeader = new r.Struct({
4
6
  firstCode: r.uint16,
5
7
  entryCount: r.uint16,
@@ -43,16 +45,29 @@ let CmapSubtable = new r.VersionedStruct(r.uint16, {
43
45
  length: r.uint16,
44
46
  language: r.uint16,
45
47
  subHeaderKeys: new r.Array(r.uint16, 256),
46
- subHeaderCount: t => Math.max.apply(Math, t.subHeaderKeys),
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,
47
54
  subHeaders: new r.LazyArray(SubHeader, 'subHeaderCount'),
48
- glyphIndexArray: new r.LazyArray(r.uint16, '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
63
  length: r.uint16, // Total table length in bytes
53
64
  language: r.uint16, // Language code
54
65
  segCountX2: r.uint16,
55
- segCount: t => t.segCountX2 >> 1,
66
+ /**
67
+ * @param {StructValue} t
68
+ * @returns {number}
69
+ */
70
+ segCount: t => /** @type {number} */ (t.segCountX2) >> 1,
56
71
  searchRange: r.uint16,
57
72
  entrySelector: r.uint16,
58
73
  rangeShift: r.uint16,
@@ -61,7 +76,11 @@ let CmapSubtable = new r.VersionedStruct(r.uint16, {
61
76
  startCode: new r.LazyArray(r.uint16, 'segCount'),
62
77
  idDelta: new r.LazyArray(r.int16, 'segCount'),
63
78
  idRangeOffset: new r.LazyArray(r.uint16, 'segCount'),
64
- glyphIndexArray: new r.LazyArray(r.uint16, t => (t.length - t._currentOffset) / 2)
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
@@ -86,8 +105,8 @@ let CmapSubtable = new r.VersionedStruct(r.uint16, {
86
105
  length: r.uint32,
87
106
  language: r.uint32,
88
107
  firstCode: r.uint32,
89
- entryCount: r.uint32,
90
- glyphIndices: new r.LazyArray(r.uint16, 'numChars')
108
+ entryCount: r.uint32, // OpenType name: numChars
109
+ glyphIndices: new r.LazyArray(r.uint16, 'entryCount')
91
110
  },
92
111
 
93
112
  12: { // Segmented coverage
@@ -120,6 +139,7 @@ let CmapEntry = new r.Struct({
120
139
  });
121
140
 
122
141
  // character to glyph mapping
142
+ /** @type {import('restructure').Struct} */
123
143
  export default new r.Struct({
124
144
  version: r.uint16,
125
145
  numSubtables: r.uint16,
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({
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({
5
20
  tag: new r.String(4),
6
21
  checkSum: r.uint32,
7
22
  offset: new r.Pointer(r.uint32, 'void', { type: 'global' }),
8
23
  length: r.uint32
9
24
  });
10
25
 
26
+ /** @type {import('restructure').Struct} */
11
27
  let Directory = new r.Struct({
12
28
  tag: new r.String(4),
13
29
  numTables: r.uint16,
14
30
  searchRange: r.uint16,
15
31
  entrySelector: r.uint16,
16
32
  rangeShift: r.uint16,
17
- tables: new r.Array(TableEntry, 'numTables')
33
+ tables: new r.Array(TableEntryStruct, 'numTables')
18
34
  });
19
35
 
20
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
47
  Directory.preEncode = function () {
30
- if (!Array.isArray(this.tables)) {
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
71
 
44
- this.tables = tables;
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;