@cantoo/fontkit 2.0.5 → 2.0.7

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 (153) hide show
  1. package/dist/browser-module.d.ts +239 -0
  2. package/dist/browser-module.mjs +4423 -1117
  3. package/dist/browser-module.mjs.map +1 -1
  4. package/dist/browser.cjs +4424 -1117
  5. package/dist/browser.cjs.map +1 -1
  6. package/dist/browser.d.ts +239 -0
  7. package/dist/fontkit.umd.d.ts +239 -0
  8. package/dist/fontkit.umd.js +22076 -0
  9. package/dist/fontkit.umd.js.map +7 -0
  10. package/dist/index.d.ts +239 -0
  11. package/dist/main.cjs +4424 -1117
  12. package/dist/main.cjs.map +1 -1
  13. package/dist/main.d.ts +239 -0
  14. package/dist/module.d.ts +239 -0
  15. package/dist/module.mjs +4423 -1117
  16. package/dist/module.mjs.map +1 -1
  17. package/package.json +22 -5
  18. package/src/CmapProcessor.js +59 -20
  19. package/src/DFont.js +114 -14
  20. package/src/TTFFont.js +259 -57
  21. package/src/TrueTypeCollection.js +54 -10
  22. package/src/WOFF2Font.js +128 -16
  23. package/src/WOFFFont.js +45 -8
  24. package/src/aat/AATFeatureMap.js +62 -18
  25. package/src/aat/AATLayoutEngine.js +33 -1
  26. package/src/aat/AATLookupTable.js +22 -4
  27. package/src/aat/AATMorxProcessor.js +189 -52
  28. package/src/aat/AATStateMachine.js +32 -0
  29. package/src/base.js +19 -0
  30. package/src/cff/CFFCharsets.js +3 -0
  31. package/src/cff/CFFDict.js +79 -9
  32. package/src/cff/CFFEncodings.js +2 -0
  33. package/src/cff/CFFFont.js +119 -23
  34. package/src/cff/CFFIndex.js +62 -5
  35. package/src/cff/CFFOperand.js +52 -17
  36. package/src/cff/CFFPointer.js +41 -2
  37. package/src/cff/CFFPrivateDict.js +14 -4
  38. package/src/cff/CFFStandardStrings.js +1 -0
  39. package/src/cff/CFFTop.js +103 -10
  40. package/src/decorators.js +32 -13
  41. package/src/encodings.js +22 -5
  42. package/src/fs.js +10 -0
  43. package/src/glyph/BBox.js +14 -0
  44. package/src/glyph/CFFGlyph.js +290 -148
  45. package/src/glyph/COLRGlyph.js +38 -3
  46. package/src/glyph/Glyph.js +68 -9
  47. package/src/glyph/GlyphVariationProcessor.js +135 -34
  48. package/src/glyph/Path.js +107 -20
  49. package/src/glyph/SBIXGlyph.js +57 -8
  50. package/src/glyph/StandardNames.js +1 -0
  51. package/src/glyph/TTFGlyph.js +176 -29
  52. package/src/glyph/TTFGlyphEncoder.js +32 -0
  53. package/src/glyph/WOFF2Glyph.js +23 -4
  54. package/src/layout/GlyphPosition.js +6 -0
  55. package/src/layout/GlyphRun.js +25 -7
  56. package/src/layout/KernProcessor.js +62 -3
  57. package/src/layout/LayoutEngine.js +86 -12
  58. package/src/layout/Script.js +27 -1
  59. package/src/layout/UnicodeLayoutEngine.js +29 -4
  60. package/src/opentype/GPOSProcessor.js +156 -45
  61. package/src/opentype/GSUBProcessor.js +92 -33
  62. package/src/opentype/GlyphInfo.js +52 -4
  63. package/src/opentype/GlyphIterator.js +51 -2
  64. package/src/opentype/OTLayoutEngine.js +66 -8
  65. package/src/opentype/OTProcessor.js +283 -70
  66. package/src/opentype/ShapingPlan.js +51 -3
  67. package/src/opentype/shapers/ArabicShaper.js +19 -0
  68. package/src/opentype/shapers/DefaultShaper.js +51 -7
  69. package/src/opentype/shapers/HangulShaper.js +85 -7
  70. package/src/opentype/shapers/HebrewShaper.js +45 -11
  71. package/src/opentype/shapers/IndicShaper.js +141 -26
  72. package/src/opentype/shapers/ThaiShaper.js +35 -4
  73. package/src/opentype/shapers/UniversalShaper.js +83 -17
  74. package/src/opentype/shapers/index.js +15 -2
  75. package/src/packages/unicode-properties/data-trie.js +1 -0
  76. package/src/packages/unicode-properties/data.js +12 -0
  77. package/src/packages/unicode-properties/dist/index.cjs +22 -9
  78. package/src/packages/unicode-properties/dist/index.cjs.map +2 -2
  79. package/src/packages/unicode-properties/dist/index.mjs +21 -9
  80. package/src/packages/unicode-properties/dist/index.mjs.map +2 -2
  81. package/src/packages/unicode-properties/index.js +65 -0
  82. package/src/packages/unicode-properties/package.json +1 -1
  83. package/src/packages/unicode-trie/builder.js +128 -7
  84. package/src/packages/unicode-trie/dist/builder.cjs +129 -16
  85. package/src/packages/unicode-trie/dist/builder.cjs.map +2 -2
  86. package/src/packages/unicode-trie/dist/builder.mjs +128 -16
  87. package/src/packages/unicode-trie/dist/builder.mjs.map +2 -2
  88. package/src/packages/unicode-trie/dist/index.cjs +22 -9
  89. package/src/packages/unicode-trie/dist/index.cjs.map +2 -2
  90. package/src/packages/unicode-trie/dist/index.mjs +21 -9
  91. package/src/packages/unicode-trie/dist/index.mjs.map +2 -2
  92. package/src/packages/unicode-trie/index.js +62 -10
  93. package/src/packages/unicode-trie/package.json +1 -1
  94. package/src/packages/unicode-trie/swap.js +13 -0
  95. package/src/subset/CFFSubset.js +112 -22
  96. package/src/subset/Subset.js +21 -1
  97. package/src/subset/TTFSubset.js +79 -36
  98. package/src/tables/BASE.js +1 -0
  99. package/src/tables/COLR.js +1 -0
  100. package/src/tables/CPAL.js +1 -0
  101. package/src/tables/DSIG.js +1 -0
  102. package/src/tables/EBDT.js +10 -3
  103. package/src/tables/EBLC.js +67 -7
  104. package/src/tables/GDEF.js +1 -0
  105. package/src/tables/GPOS.js +79 -16
  106. package/src/tables/GSUB.js +14 -3
  107. package/src/tables/HVAR.js +51 -5
  108. package/src/tables/JSTF.js +3 -2
  109. package/src/tables/LTSH.js +1 -0
  110. package/src/tables/OS2.js +1 -0
  111. package/src/tables/PCLT.js +1 -0
  112. package/src/tables/STAT.js +46 -6
  113. package/src/tables/VDMX.js +1 -0
  114. package/src/tables/VORG.js +1 -0
  115. package/src/tables/WOFF2Directory.js +56 -8
  116. package/src/tables/WOFFDirectory.js +14 -2
  117. package/src/tables/aat.js +160 -35
  118. package/src/tables/avar.js +1 -0
  119. package/src/tables/bsln.js +3 -2
  120. package/src/tables/cmap.js +26 -6
  121. package/src/tables/cvt.js +1 -0
  122. package/src/tables/directory.js +44 -16
  123. package/src/tables/feat.js +24 -2
  124. package/src/tables/fpgm.js +1 -0
  125. package/src/tables/fvar.js +32 -4
  126. package/src/tables/gasp.js +1 -0
  127. package/src/tables/glyf.js +1 -0
  128. package/src/tables/gvar.js +29 -2
  129. package/src/tables/hdmx.js +12 -1
  130. package/src/tables/head.js +1 -0
  131. package/src/tables/hhea.js +1 -0
  132. package/src/tables/hmtx.js +18 -2
  133. package/src/tables/index.js +1 -0
  134. package/src/tables/just.js +15 -4
  135. package/src/tables/kern.js +43 -6
  136. package/src/tables/loca.js +21 -8
  137. package/src/tables/maxp.js +1 -0
  138. package/src/tables/morx.js +14 -7
  139. package/src/tables/name.js +104 -23
  140. package/src/tables/opbd.js +2 -1
  141. package/src/tables/opentype.js +39 -4
  142. package/src/tables/post.js +8 -1
  143. package/src/tables/prep.js +1 -0
  144. package/src/tables/sbix.js +12 -1
  145. package/src/tables/variations.js +23 -3
  146. package/src/tables/vhea.js +1 -0
  147. package/src/tables/vmtx.js +18 -2
  148. package/src/utils.js +15 -0
  149. package/types/assets.d.ts +13 -0
  150. package/types/deps.d.ts +83 -0
  151. package/types/fontkit.d.ts +1324 -0
  152. package/types/index.d.ts +239 -0
  153. package/types/restructure.d.ts +354 -0
@@ -1,10 +1,54 @@
1
1
  import { binarySearch } from '../utils';
2
2
 
3
+ /** @typedef {import('../../types/fontkit').LayoutFont} LayoutFont */
4
+ /** @typedef {import('../../types/fontkit').KernTable} KernTable */
5
+ /** @typedef {import('../../types/fontkit').KernPair} KernPair */
6
+ /** @typedef {import('../../types/fontkit').KernFormat0} KernFormat0 */
7
+ /** @typedef {import('../../types/fontkit').KernFormat2} KernFormat2 */
8
+ /** @typedef {import('../../types/fontkit').KernFormat3} KernFormat3 */
9
+ /** @typedef {import('../../types/fontkit').GlyphInfoLike} GlyphInfoLike */
10
+ /** @typedef {import('../../types/fontkit').LayoutGlyph} LayoutGlyph */
11
+ /** @typedef {import('../../types/fontkit').GlyphPositionLike} GlyphPositionLike */
12
+
13
+ /**
14
+ * @param {unknown} s
15
+ * @returns {s is KernFormat0}
16
+ */
17
+ function isKernFormat0(s) {
18
+ return typeof s === 'object' && s !== null && Array.isArray(/** @type {{ pairs?: unknown }} */ (s).pairs);
19
+ }
20
+
21
+ /**
22
+ * @param {unknown} s
23
+ * @returns {s is KernFormat2}
24
+ */
25
+ function isKernFormat2(s) {
26
+ return typeof s === 'object' && s !== null
27
+ && 'leftTable' in s && 'rightTable' in s && 'array' in s;
28
+ }
29
+
30
+ /**
31
+ * @param {unknown} s
32
+ * @returns {s is KernFormat3}
33
+ */
34
+ function isKernFormat3(s) {
35
+ return typeof s === 'object' && s !== null
36
+ && 'glyphCount' in s && 'kernValue' in s && 'kernIndex' in s;
37
+ }
38
+
3
39
  export default class KernProcessor {
40
+ /**
41
+ * @param {LayoutFont} font
42
+ */
4
43
  constructor(font) {
5
- this.kern = font.kern;
44
+ /** @type {KernTable} */
45
+ this.kern = /** @type {KernTable} */ (font.kern);
6
46
  }
7
47
 
48
+ /**
49
+ * @param {Array<LayoutGlyph | GlyphInfoLike>} glyphs
50
+ * @param {GlyphPositionLike[]} positions
51
+ */
8
52
  process(glyphs, positions) {
9
53
  for (let glyphIndex = 0; glyphIndex < glyphs.length - 1; glyphIndex++) {
10
54
  let left = glyphs[glyphIndex].id;
@@ -13,6 +57,11 @@ export default class KernProcessor {
13
57
  }
14
58
  }
15
59
 
60
+ /**
61
+ * @param {number} left
62
+ * @param {number} right
63
+ * @returns {number}
64
+ */
16
65
  getKerning(left, right) {
17
66
  let res = 0;
18
67
 
@@ -42,7 +91,10 @@ export default class KernProcessor {
42
91
  let s = table.subtable;
43
92
  switch (table.format) {
44
93
  case 0: {
45
- let pairIdx = binarySearch(s.pairs, function (pair) {
94
+ if (!isKernFormat0(s)) {
95
+ break;
96
+ }
97
+ let pairIdx = binarySearch(s.pairs, /** @param {KernPair} pair */ (pair) => {
46
98
  return (left - pair.left) || (right - pair.right);
47
99
  });
48
100
 
@@ -54,7 +106,11 @@ export default class KernProcessor {
54
106
  }
55
107
 
56
108
  case 2: {
57
- let leftOffset, rightOffset = 0;
109
+ if (!isKernFormat2(s)) {
110
+ break;
111
+ }
112
+ let leftOffset = 0;
113
+ let rightOffset = 0;
58
114
  if (left >= s.leftTable.firstGlyph && left < s.leftTable.firstGlyph + s.leftTable.nGlyphs) {
59
115
  leftOffset = s.leftTable.offsets[left - s.leftTable.firstGlyph];
60
116
  } else {
@@ -71,6 +127,9 @@ export default class KernProcessor {
71
127
  }
72
128
 
73
129
  case 3: {
130
+ if (!isKernFormat3(s)) {
131
+ break;
132
+ }
74
133
  if (left >= s.glyphCount || right >= s.glyphCount) {
75
134
  return 0;
76
135
  }
@@ -6,31 +6,60 @@ import * as Script from './Script';
6
6
  import AATLayoutEngine from '../aat/AATLayoutEngine';
7
7
  import OTLayoutEngine from '../opentype/OTLayoutEngine';
8
8
 
9
+ /** @typedef {import('../../types/fontkit').LayoutFont} LayoutFont */
10
+ /** @typedef {import('../../types/fontkit').LayoutGlyph} LayoutGlyph */
11
+ /** @typedef {import('../../types/fontkit').FeatureInput} FeatureInput */
12
+ /** @typedef {import('../../types/fontkit').FeatureMap} FeatureMap */
13
+ /** @typedef {import('../../types/fontkit').ScriptTag} ScriptTag */
14
+ /** @typedef {import('../../types/fontkit').LanguageTag} LanguageTag */
15
+ /** @typedef {import('../../types/fontkit').TextDirection} TextDirection */
16
+ /** @typedef {import('../../types/fontkit').AdvancedLayoutEngine} AdvancedLayoutEngine */
17
+ /** @typedef {import('../../types/fontkit').GlyphRunLike} GlyphRunLike */
18
+ /** @typedef {import('../../types/fontkit').GlyphPositionLike} GlyphPositionLike */
19
+ /** @typedef {import('./GlyphRun').default} GlyphRunInstance */
20
+
9
21
  export default class LayoutEngine {
22
+ /**
23
+ * @param {LayoutFont} font
24
+ */
10
25
  constructor(font) {
26
+ /** @type {LayoutFont} */
11
27
  this.font = font;
28
+ /** @type {UnicodeLayoutEngine | null} */
12
29
  this.unicodeLayoutEngine = null;
30
+ /** @type {KernProcessor | null} */
13
31
  this.kernProcessor = null;
32
+ /** @type {AdvancedLayoutEngine | undefined} */
33
+ this.engine = undefined;
14
34
 
15
35
  // Choose an advanced layout engine. We try the AAT morx table first since more
16
36
  // scripts are currently supported because the shaping logic is built into the font.
17
37
  if (this.font.morx) {
18
- this.engine = new AATLayoutEngine(this.font);
38
+ this.engine = /** @type {AdvancedLayoutEngine} */ (new AATLayoutEngine(this.font));
19
39
  } else if (this.font.GSUB || this.font.GPOS) {
20
- this.engine = new OTLayoutEngine(this.font);
40
+ this.engine = /** @type {AdvancedLayoutEngine} */ (new OTLayoutEngine(this.font));
21
41
  }
22
42
  }
23
43
 
44
+ /**
45
+ * @param {string | LayoutGlyph[]} string
46
+ * @param {FeatureInput | ScriptTag | string[] | null | undefined} [features]
47
+ * @param {ScriptTag | string[] | LanguageTag | null | undefined} [script]
48
+ * @param {LanguageTag | TextDirection | null | undefined} [language]
49
+ * @param {TextDirection | null | undefined} [direction]
50
+ * @returns {GlyphRunInstance}
51
+ */
24
52
  layout(string, features, script, language, direction) {
25
53
  // Make the features parameter optional
26
54
  if (typeof features === 'string') {
27
- direction = language;
28
- language = script;
55
+ direction = /** @type {TextDirection | null | undefined} */ (language);
56
+ language = /** @type {LanguageTag | null | undefined} */ (script);
29
57
  script = features;
30
58
  features = [];
31
59
  }
32
60
 
33
61
  // Map string to glyphs if needed
62
+ /** @type {LayoutGlyph[]} */
34
63
  let glyphs;
35
64
  if (typeof string === 'string') {
36
65
  // Attempt to detect the script from the string if not provided.
@@ -42,6 +71,7 @@ export default class LayoutEngine {
42
71
  } else {
43
72
  // Attempt to detect the script from the glyph code points if not provided.
44
73
  if (script == null) {
74
+ /** @type {number[]} */
45
75
  let codePoints = [];
46
76
  for (let glyph of string) {
47
77
  codePoints.push(...glyph.codePoints);
@@ -53,7 +83,13 @@ export default class LayoutEngine {
53
83
  glyphs = string;
54
84
  }
55
85
 
56
- let glyphRun = new GlyphRun(glyphs, features, script, language, direction);
86
+ let glyphRun = new GlyphRun(
87
+ /** @type {import('../glyph/Glyph').default[]} */ (glyphs),
88
+ /** @type {FeatureInput | null | undefined} */ (features),
89
+ script,
90
+ /** @type {LanguageTag | null | undefined} */ (language),
91
+ /** @type {TextDirection | null | undefined} */ (direction)
92
+ );
57
93
 
58
94
  // Return early if there are no glyphs
59
95
  if (glyphs.length === 0) {
@@ -63,14 +99,16 @@ export default class LayoutEngine {
63
99
 
64
100
  // Setup the advanced layout engine
65
101
  if (this.engine && this.engine.setup) {
66
- this.engine.setup(glyphRun);
102
+ this.engine.setup(/** @type {GlyphRunLike} */ (glyphRun));
67
103
  }
68
104
 
69
105
  // Substitute and position the glyphs
70
106
  this.substitute(glyphRun);
71
107
  this.position(glyphRun);
72
108
 
73
- this.hideDefaultIgnorables(glyphRun.glyphs, glyphRun.positions);
109
+ if (glyphRun.positions) {
110
+ this.hideDefaultIgnorables(/** @type {LayoutGlyph[]} */ (glyphRun.glyphs), glyphRun.positions);
111
+ }
74
112
 
75
113
  // Let the layout engine clean up any state it might have
76
114
  if (this.engine && this.engine.cleanup) {
@@ -80,21 +118,30 @@ export default class LayoutEngine {
80
118
  return glyphRun;
81
119
  }
82
120
 
121
+ /**
122
+ * @param {GlyphRunInstance} glyphRun
123
+ */
83
124
  substitute(glyphRun) {
84
125
  // Call the advanced layout engine to make substitutions
85
126
  if (this.engine && this.engine.substitute) {
86
- this.engine.substitute(glyphRun);
127
+ this.engine.substitute(/** @type {GlyphRunLike} */ (glyphRun));
87
128
  }
88
129
  }
89
130
 
131
+ /**
132
+ * @param {GlyphRunInstance} glyphRun
133
+ */
90
134
  position(glyphRun) {
91
135
  // Get initial glyph positions
92
- glyphRun.positions = glyphRun.glyphs.map(glyph => new GlyphPosition(glyph.advanceWidth));
136
+ glyphRun.positions = /** @type {LayoutGlyph[]} */ (glyphRun.glyphs).map(
137
+ /** @param {LayoutGlyph} glyph */ glyph => new GlyphPosition(glyph.advanceWidth)
138
+ );
139
+ /** @type {FeatureMap | Record<string, import('../../types/fontkit').OTFeature> | null | undefined | false} */
93
140
  let positioned = null;
94
141
 
95
142
  // Call the advanced layout engine. Returns the features applied.
96
143
  if (this.engine && this.engine.position) {
97
- positioned = this.engine.position(glyphRun);
144
+ positioned = this.engine.position(/** @type {GlyphRunLike} */ (glyphRun));
98
145
  }
99
146
 
100
147
  // if there is no GPOS table, use unicode properties to position marks.
@@ -103,7 +150,10 @@ export default class LayoutEngine {
103
150
  this.unicodeLayoutEngine = new UnicodeLayoutEngine(this.font);
104
151
  }
105
152
 
106
- this.unicodeLayoutEngine.positionGlyphs(glyphRun.glyphs, glyphRun.positions);
153
+ this.unicodeLayoutEngine.positionGlyphs(
154
+ /** @type {LayoutGlyph[]} */ (glyphRun.glyphs),
155
+ /** @type {GlyphPositionLike[]} */ (glyphRun.positions)
156
+ );
107
157
  }
108
158
 
109
159
  // if kerning is not supported by GPOS, do kerning with the TrueType/AAT kern table
@@ -112,13 +162,23 @@ export default class LayoutEngine {
112
162
  this.kernProcessor = new KernProcessor(this.font);
113
163
  }
114
164
 
115
- this.kernProcessor.process(glyphRun.glyphs, glyphRun.positions);
165
+ this.kernProcessor.process(
166
+ /** @type {LayoutGlyph[]} */ (glyphRun.glyphs),
167
+ /** @type {GlyphPositionLike[]} */ (glyphRun.positions)
168
+ );
116
169
  glyphRun.features.kern = true;
117
170
  }
118
171
  }
119
172
 
173
+ /**
174
+ * @param {LayoutGlyph[]} glyphs
175
+ * @param {GlyphPositionLike[]} positions
176
+ */
120
177
  hideDefaultIgnorables(glyphs, positions) {
121
178
  let space = this.font.glyphForCodePoint(0x20);
179
+ if (!space) {
180
+ return;
181
+ }
122
182
  for (let i = 0; i < glyphs.length; i++) {
123
183
  if (this.isDefaultIgnorable(glyphs[i].codePoints[0])) {
124
184
  glyphs[i] = space;
@@ -128,6 +188,10 @@ export default class LayoutEngine {
128
188
  }
129
189
  }
130
190
 
191
+ /**
192
+ * @param {number} ch
193
+ * @returns {boolean}
194
+ */
131
195
  isDefaultIgnorable(ch) {
132
196
  // From DerivedCoreProperties.txt in the Unicode database,
133
197
  // minus U+115F, U+1160, U+3164 and U+FFA0, which is what
@@ -156,7 +220,13 @@ export default class LayoutEngine {
156
220
  }
157
221
  }
158
222
 
223
+ /**
224
+ * @param {ScriptTag | string[] | null | undefined} [script]
225
+ * @param {LanguageTag | null | undefined} [language]
226
+ * @returns {string[]}
227
+ */
159
228
  getAvailableFeatures(script, language) {
229
+ /** @type {string[]} */
160
230
  let features = [];
161
231
 
162
232
  if (this.engine) {
@@ -170,6 +240,10 @@ export default class LayoutEngine {
170
240
  return features;
171
241
  }
172
242
 
243
+ /**
244
+ * @param {number} gid
245
+ * @returns {string[]}
246
+ */
173
247
  stringsForGlyph(gid) {
174
248
  let result = new Set();
175
249
 
@@ -1,8 +1,11 @@
1
1
  import { getScript } from '../packages/unicode-properties/index.js';
2
2
 
3
+ /** @typedef {import('../../types/fontkit').TextDirection} TextDirection */
4
+
3
5
  // This maps the Unicode Script property to an OpenType script tag
4
6
  // Data from http://www.microsoft.com/typography/otspec/scripttags.htm
5
7
  // and http://www.unicode.org/Public/UNIDATA/PropertyValueAliases.txt.
8
+ /** @type {Record<string, string | string[]>} */
6
9
  const UNICODE_SCRIPTS = {
7
10
  Caucasian_Albanian: 'aghb',
8
11
  Arabic: 'arab',
@@ -133,6 +136,7 @@ const UNICODE_SCRIPTS = {
133
136
  Unknown: 'zzzz'
134
137
  };
135
138
 
139
+ /** @type {Record<string, string>} */
136
140
  const OPENTYPE_SCRIPTS = {};
137
141
  for (let script in UNICODE_SCRIPTS) {
138
142
  let tag = UNICODE_SCRIPTS[script];
@@ -145,14 +149,26 @@ for (let script in UNICODE_SCRIPTS) {
145
149
  }
146
150
  }
147
151
 
152
+ /**
153
+ * @param {string} script
154
+ * @returns {string | string[] | undefined}
155
+ */
148
156
  export function fromUnicode(script) {
149
157
  return UNICODE_SCRIPTS[script];
150
158
  }
151
159
 
160
+ /**
161
+ * @param {string} tag
162
+ * @returns {string | undefined}
163
+ */
152
164
  export function fromOpenType(tag) {
153
165
  return OPENTYPE_SCRIPTS[tag];
154
166
  }
155
167
 
168
+ /**
169
+ * @param {string} string
170
+ * @returns {string | string[]}
171
+ */
156
172
  export function forString(string) {
157
173
  let len = string.length;
158
174
  let idx = 0;
@@ -179,6 +195,10 @@ export function forString(string) {
179
195
  return UNICODE_SCRIPTS.Unknown;
180
196
  }
181
197
 
198
+ /**
199
+ * @param {number[]} codePoints
200
+ * @returns {string | string[]}
201
+ */
182
202
  export function forCodePoints(codePoints) {
183
203
  for (let i = 0; i < codePoints.length; i++) {
184
204
  let codePoint = codePoints[i];
@@ -192,6 +212,7 @@ export function forCodePoints(codePoints) {
192
212
  }
193
213
 
194
214
  // The scripts in this map are written from right to left
215
+ /** @type {Record<string, boolean>} */
195
216
  const RTL = {
196
217
  arab: true, // Arabic
197
218
  hebr: true, // Hebrew
@@ -222,8 +243,13 @@ const RTL = {
222
243
  phlp: true // Psalter Pahlavi
223
244
  };
224
245
 
246
+ /**
247
+ * @param {string | string[] | null | undefined} script
248
+ * @returns {TextDirection}
249
+ */
225
250
  export function direction(script) {
226
- if (RTL[script]) {
251
+ let tag = Array.isArray(script) ? script[0] : script;
252
+ if (tag && RTL[tag]) {
227
253
  return 'rtl';
228
254
  }
229
255
 
@@ -1,5 +1,10 @@
1
1
  import { getCombiningClass } from '../packages/unicode-properties/index.js';
2
2
 
3
+ /** @typedef {import('../../types/fontkit').LayoutFont} LayoutFont */
4
+ /** @typedef {import('../../types/fontkit').LayoutGlyph} LayoutGlyph */
5
+ /** @typedef {import('../../types/fontkit').GlyphInfoLike} GlyphInfoLike */
6
+ /** @typedef {import('../../types/fontkit').GlyphPositionLike} GlyphPositionLike */
7
+
3
8
  /**
4
9
  * This class is used when GPOS does not define 'mark' or 'mkmk' features
5
10
  * for positioning marks relative to base glyphs. It uses the unicode
@@ -9,10 +14,19 @@ import { getCombiningClass } from '../packages/unicode-properties/index.js';
9
14
  * https://github.com/behdad/harfbuzz/blob/master/src/hb-ot-shape-fallback.cc
10
15
  */
11
16
  export default class UnicodeLayoutEngine {
17
+ /**
18
+ * @param {LayoutFont} font
19
+ */
12
20
  constructor(font) {
21
+ /** @type {LayoutFont} */
13
22
  this.font = font;
14
23
  }
15
24
 
25
+ /**
26
+ * @param {Array<LayoutGlyph | GlyphInfoLike & { cbox?: import('../../types/fontkit').BBoxLike }>} glyphs
27
+ * @param {GlyphPositionLike[]} positions
28
+ * @returns {GlyphPositionLike[]}
29
+ */
16
30
  positionGlyphs(glyphs, positions) {
17
31
  // find each base + mark cluster, and position the marks relative to the base
18
32
  let clusterStart = 0;
@@ -37,9 +51,16 @@ export default class UnicodeLayoutEngine {
37
51
  return positions;
38
52
  }
39
53
 
54
+ /**
55
+ * @param {Array<LayoutGlyph | (GlyphInfoLike & { cbox?: import('../../types/fontkit').BBoxLike, advanceWidth?: number })>} glyphs
56
+ * @param {GlyphPositionLike[]} positions
57
+ * @param {number} clusterStart
58
+ * @param {number} clusterEnd
59
+ * @returns {void}
60
+ */
40
61
  positionCluster(glyphs, positions, clusterStart, clusterEnd) {
41
- let base = glyphs[clusterStart];
42
- let baseBox = base.cbox.copy();
62
+ let base = /** @type {LayoutGlyph} */ (glyphs[clusterStart]);
63
+ let baseBox = /** @type {import('../../types/fontkit').BBoxLike} */ (base.cbox).copy();
43
64
 
44
65
  // adjust bounding box for ligature glyphs
45
66
  if (base.codePoints.length > 1) {
@@ -53,8 +74,8 @@ export default class UnicodeLayoutEngine {
53
74
 
54
75
  // position each of the mark glyphs relative to the base glyph
55
76
  for (let index = clusterStart + 1; index <= clusterEnd; index++) {
56
- let mark = glyphs[index];
57
- let markBox = mark.cbox;
77
+ let mark = /** @type {LayoutGlyph} */ (glyphs[index]);
78
+ let markBox = /** @type {import('../../types/fontkit').BBoxLike} */ (mark.cbox);
58
79
  let position = positions[index];
59
80
 
60
81
  let combiningClass = this.getCombiningClass(mark.codePoints[0]);
@@ -134,6 +155,10 @@ export default class UnicodeLayoutEngine {
134
155
  return;
135
156
  }
136
157
 
158
+ /**
159
+ * @param {number} codePoint
160
+ * @returns {string}
161
+ */
137
162
  getCombiningClass(codePoint) {
138
163
  let combiningClass = getCombiningClass(codePoint);
139
164