@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/glyph/Path.js CHANGED
@@ -1,5 +1,9 @@
1
1
  import BBox from './BBox';
2
2
 
3
+ /** @typedef {import('../../types/fontkit').PathCommand} PathCommand */
4
+ /** @typedef {import('../../types/fontkit').PathRenderingContext} PathRenderingContext */
5
+
6
+ /** @type {Record<PathCommand['command'], string>} */
3
7
  const SVG_COMMANDS = {
4
8
  moveTo: 'M',
5
9
  lineTo: 'L',
@@ -16,21 +20,94 @@ const SVG_COMMANDS = {
16
20
  */
17
21
  export default class Path {
18
22
  constructor() {
23
+ /** @type {PathCommand[]} */
19
24
  this.commands = [];
25
+ /** @type {BBox | null} */
20
26
  this._bbox = null;
27
+ /** @type {BBox | null} */
21
28
  this._cbox = null;
22
29
  }
23
30
 
31
+ /**
32
+ * @param {PathCommand['command']} command
33
+ * @param {...number} args
34
+ * @returns {this}
35
+ */
36
+ _addCommand(command, ...args) {
37
+ this._bbox = this._cbox = null;
38
+ this.commands.push({
39
+ command,
40
+ args
41
+ });
42
+ return this;
43
+ }
44
+
45
+ /**
46
+ * @param {number} x
47
+ * @param {number} y
48
+ * @returns {this}
49
+ */
50
+ moveTo(x, y) {
51
+ return this._addCommand('moveTo', x, y);
52
+ }
53
+
54
+ /**
55
+ * @param {number} x
56
+ * @param {number} y
57
+ * @returns {this}
58
+ */
59
+ lineTo(x, y) {
60
+ return this._addCommand('lineTo', x, y);
61
+ }
62
+
63
+ /**
64
+ * @param {number} cpx
65
+ * @param {number} cpy
66
+ * @param {number} x
67
+ * @param {number} y
68
+ * @returns {this}
69
+ */
70
+ quadraticCurveTo(cpx, cpy, x, y) {
71
+ return this._addCommand('quadraticCurveTo', cpx, cpy, x, y);
72
+ }
73
+
74
+ /**
75
+ * @param {number} cp1x
76
+ * @param {number} cp1y
77
+ * @param {number} cp2x
78
+ * @param {number} cp2y
79
+ * @param {number} x
80
+ * @param {number} y
81
+ * @returns {this}
82
+ */
83
+ bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y) {
84
+ return this._addCommand('bezierCurveTo', cp1x, cp1y, cp2x, cp2y, x, y);
85
+ }
86
+
87
+ /**
88
+ * @returns {this}
89
+ */
90
+ closePath() {
91
+ return this._addCommand('closePath');
92
+ }
93
+
24
94
  /**
25
95
  * Compiles the path to a JavaScript function that can be applied with
26
96
  * a graphics context in order to render the path.
27
- * @return {string}
97
+ * @return {(ctx: PathRenderingContext) => void}
28
98
  */
29
99
  toFunction() {
30
- return ctx => {
31
- this.commands.forEach(c => {
32
- return ctx[c.command].apply(ctx, c.args)
33
- })
100
+ /**
101
+ * @param {PathRenderingContext} ctx
102
+ * @returns {void}
103
+ */
104
+ return (ctx) => {
105
+ this.commands.forEach((c) => {
106
+ const fn = ctx[c.command];
107
+ if (typeof fn === 'function') {
108
+ Reflect.apply(fn, ctx, c.args);
109
+ }
110
+ });
34
111
  };
35
112
  }
36
113
 
@@ -39,8 +116,8 @@ export default class Path {
39
116
  * @return {string}
40
117
  */
41
118
  toSVG() {
42
- let cmds = this.commands.map(c => {
43
- let args = c.args.map(arg => Math.round(arg * 100) / 100);
119
+ let cmds = this.commands.map((c) => {
120
+ let args = c.args.map(/** @param {number} arg */ arg => Math.round(arg * 100) / 100);
44
121
  return `${SVG_COMMANDS[c.command]}${args.join(' ')}`;
45
122
  });
46
123
 
@@ -59,7 +136,7 @@ export default class Path {
59
136
  if (this.commands.length === 0) {
60
137
  this._cbox = Object.freeze(new BBox(0, 0, 0, 0));
61
138
  } else {
62
- let cbox = new BBox;
139
+ let cbox = new BBox();
63
140
  for (let command of this.commands) {
64
141
  for (let i = 0; i < command.args.length; i += 2) {
65
142
  cbox.addPoint(command.args[i], command.args[i + 1]);
@@ -87,7 +164,7 @@ export default class Path {
87
164
  return this._bbox = Object.freeze(new BBox(0, 0, 0, 0));
88
165
  }
89
166
 
90
- let bbox = new BBox;
167
+ let bbox = new BBox();
91
168
  let cx = 0, cy = 0;
92
169
 
93
170
  for (let c of this.commands) {
@@ -109,9 +186,9 @@ export default class Path {
109
186
  let [qp1x, qp1y, qp3x, qp3y] = c.args;
110
187
  p3x = qp3x;
111
188
  p3y = qp3y;
112
- cp1x = cx + 2 / 3 * (qp1x - cx); // CP1 = QP0 + 2/3 * (QP1-QP0)
189
+ cp1x = cx + 2 / 3 * (qp1x - cx); // CP1 = QP0 + 2/3 * (QP1-QP0)
113
190
  cp1y = cy + 2 / 3 * (qp1y - cy);
114
- cp2x = p3x + 2 / 3 * (qp1x - p3x); // CP2 = QP2 + 2/3 * (QP1-QP2)
191
+ cp2x = p3x + 2 / 3 * (qp1x - p3x); // CP2 = QP2 + 2/3 * (QP1-QP2)
115
192
  cp2y = p3y + 2 / 3 * (qp1y - p3y);
116
193
  } else {
117
194
  [cp1x, cp1y, cp2x, cp2y, p3x, p3y] = c.args;
@@ -125,24 +202,31 @@ export default class Path {
125
202
  let p2 = [cp2x, cp2y];
126
203
  let p3 = [p3x, p3y];
127
204
 
205
+ /**
206
+ * @param {number} t
207
+ * @param {number} i
208
+ * @returns {number}
209
+ */
128
210
  let f = (t, i) => (
129
211
  Math.pow(1 - t, 3) * p0[i]
130
- + 3 * Math.pow(1 - t, 2) * t * p1[i]
131
- + 3 * (1 - t) * Math.pow(t, 2) * p2[i]
132
- + Math.pow(t, 3) * p3[i]
212
+ + 3 * Math.pow(1 - t, 2) * t * p1[i]
213
+ + 3 * (1 - t) * Math.pow(t, 2) * p2[i]
214
+ + Math.pow(t, 3) * p3[i]
133
215
  );
134
216
 
135
217
  for (let i = 0; i <= 1; i++) {
136
218
  let b = 6 * p0[i] - 12 * p1[i] + 6 * p2[i];
137
219
  let a = -3 * p0[i] + 9 * p1[i] - 9 * p2[i] + 3 * p3[i];
138
- c = 3 * p1[i] - 3 * p0[i];
220
+ // Renamed from `c` reassigning the PathCommand loop variable to a number
221
+ // would corrupt subsequent iterations / confuse the type checker.
222
+ let coeff = 3 * p1[i] - 3 * p0[i];
139
223
 
140
224
  if (a === 0) {
141
225
  if (b === 0) {
142
226
  continue;
143
227
  }
144
228
 
145
- let t = -c / b;
229
+ let t = -coeff / b;
146
230
  if (0 < t && t < 1) {
147
231
  if (i === 0) {
148
232
  bbox.addPoint(f(t, i), bbox.maxY);
@@ -154,7 +238,7 @@ export default class Path {
154
238
  continue;
155
239
  }
156
240
 
157
- let b2ac = Math.pow(b, 2) - 4 * c * a;
241
+ let b2ac = Math.pow(b, 2) - 4 * coeff * a;
158
242
  if (b2ac < 0) {
159
243
  continue;
160
244
  }
@@ -190,11 +274,11 @@ export default class Path {
190
274
 
191
275
  /**
192
276
  * Applies a mapping function to each point in the path.
193
- * @param {function} fn
277
+ * @param {(x: number, y: number) => [number, number]} fn
194
278
  * @return {Path}
195
279
  */
196
280
  mapPoints(fn) {
197
- let path = new Path;
281
+ let path = new Path();
198
282
 
199
283
  for (let c of this.commands) {
200
284
  let args = [];
@@ -203,7 +287,7 @@ export default class Path {
203
287
  args.push(x, y);
204
288
  }
205
289
 
206
- path[c.command](...args);
290
+ path._addCommand(c.command, ...args);
207
291
  }
208
292
 
209
293
  return path;
@@ -211,6 +295,13 @@ export default class Path {
211
295
 
212
296
  /**
213
297
  * Transforms the path by the given matrix.
298
+ * @param {number} m0
299
+ * @param {number} m1
300
+ * @param {number} m2
301
+ * @param {number} m3
302
+ * @param {number} m4
303
+ * @param {number} m5
304
+ * @returns {Path}
214
305
  */
215
306
  transform(m0, m1, m2, m3, m4, m5) {
216
307
  return this.mapPoints((x, y) => {
@@ -222,6 +313,9 @@ export default class Path {
222
313
 
223
314
  /**
224
315
  * Translates the path by the given offset.
316
+ * @param {number} x
317
+ * @param {number} y
318
+ * @returns {Path}
225
319
  */
226
320
  translate(x, y) {
227
321
  return this.transform(1, 0, 0, 1, x, y);
@@ -229,6 +323,8 @@ export default class Path {
229
323
 
230
324
  /**
231
325
  * Rotates the path by the given angle (in radians).
326
+ * @param {number} angle
327
+ * @returns {Path}
232
328
  */
233
329
  rotate(angle) {
234
330
  let cos = Math.cos(angle);
@@ -238,20 +334,11 @@ export default class Path {
238
334
 
239
335
  /**
240
336
  * Scales the path.
337
+ * @param {number} scaleX
338
+ * @param {number} [scaleY]
339
+ * @returns {Path}
241
340
  */
242
341
  scale(scaleX, scaleY = scaleX) {
243
342
  return this.transform(scaleX, 0, 0, scaleY, 0, 0);
244
343
  }
245
344
  }
246
-
247
- for (let command of ['moveTo', 'lineTo', 'quadraticCurveTo', 'bezierCurveTo', 'closePath']) {
248
- Path.prototype[command] = function(...args) {
249
- this._bbox = this._cbox = null;
250
- this.commands.push({
251
- command,
252
- args
253
- });
254
-
255
- return this;
256
- };
257
- }
@@ -1,13 +1,47 @@
1
1
  import TTFGlyph from './TTFGlyph';
2
2
  import * as r from 'restructure';
3
3
 
4
- let SBIXImage = new r.Struct({
4
+ /** @typedef {import('restructure').StructValue} StructValue */
5
+ /** @typedef {import('../../types/fontkit').PathRenderingContext} PathRenderingContext */
6
+ /** @typedef {import('../../types/fontkit').SBIXImage} SBIXImageData */
7
+
8
+ let SBIXImageStruct = new r.Struct({
5
9
  originX: r.uint16,
6
10
  originY: r.uint16,
7
11
  type: new r.String(4),
8
- data: new r.Buffer(t => t.parent.buflen - t._currentOffset)
12
+ data: new r.Buffer((t) => {
13
+ let parent = t.parent;
14
+ let buflen = parent && typeof parent.buflen === 'number' ? parent.buflen : 0;
15
+ let offset = typeof t._currentOffset === 'number' ? t._currentOffset : 0;
16
+ return buflen - offset;
17
+ })
9
18
  });
10
19
 
20
+ /**
21
+ * @param {StructValue} raw
22
+ * @returns {SBIXImageData}
23
+ */
24
+ function asSBIXImage(raw) {
25
+ let originX = raw.originX;
26
+ let originY = raw.originY;
27
+ let type = raw.type;
28
+ let data = raw.data;
29
+ if (
30
+ typeof originX !== 'number'
31
+ || typeof originY !== 'number'
32
+ || typeof type !== 'string'
33
+ || !ArrayBuffer.isView(data)
34
+ ) {
35
+ throw new Error('Invalid SBIX image');
36
+ }
37
+ return {
38
+ originX,
39
+ originY,
40
+ type,
41
+ data
42
+ };
43
+ }
44
+
11
45
  /**
12
46
  * Represents a color (e.g. emoji) glyph in Apple's SBIX format.
13
47
  */
@@ -20,11 +54,18 @@ export default class SBIXGlyph extends TTFGlyph {
20
54
  * along with the image type, and origin.
21
55
  *
22
56
  * @param {number} size
23
- * @return {object}
57
+ * @return {SBIXImageData | null}
24
58
  */
25
59
  getImageForSize(size) {
26
- for (let i = 0; i < this._font.sbix.imageTables.length; i++) {
27
- var table = this._font.sbix.imageTables[i];
60
+ let sbix = this._font.sbix;
61
+ if (!sbix || sbix.imageTables.length === 0) {
62
+ return null;
63
+ }
64
+
65
+ /** @type {import('../../types/fontkit').SBIXImageTable} */
66
+ let table = sbix.imageTables[0];
67
+ for (let i = 0; i < sbix.imageTables.length; i++) {
68
+ table = sbix.imageTables[i];
28
69
  if (table.ppem >= size) { break; }
29
70
  }
30
71
 
@@ -37,17 +78,25 @@ export default class SBIXGlyph extends TTFGlyph {
37
78
  }
38
79
 
39
80
  this._font.stream.pos = start;
40
- return SBIXImage.decode(this._font.stream, {buflen: end - start});
81
+ return asSBIXImage(SBIXImageStruct.decode(this._font.stream, { buflen: end - start }));
41
82
  }
42
83
 
84
+ /**
85
+ * @param {PathRenderingContext} ctx
86
+ * @param {number} size
87
+ * @returns {void}
88
+ */
43
89
  render(ctx, size) {
44
90
  let img = this.getImageForSize(size);
45
91
  if (img != null) {
46
92
  let scale = size / this._font.unitsPerEm;
47
- ctx.image(img.data, {height: size, x: img.originX, y: (this.bbox.minY - img.originY) * scale});
93
+ if (typeof ctx.image === 'function') {
94
+ ctx.image(img.data, { height: size, x: img.originX, y: (this.bbox.minY - img.originY) * scale });
95
+ }
48
96
  }
49
97
 
50
- if (this._font.sbix.flags.renderOutlines) {
98
+ let sbix = this._font.sbix;
99
+ if (sbix && sbix.flags.renderOutlines) {
51
100
  super.render(ctx, size);
52
101
  }
53
102
  }
@@ -1,3 +1,4 @@
1
+ /** @type {string[]} */
1
2
  export default [
2
3
  '.notdef', '.null', 'nonmarkingreturn', 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent',
3
4
  'ampersand', 'quotesingle', 'parenleft', 'parenright', 'asterisk', 'plus', 'comma', 'hyphen', 'period', 'slash',