@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
@@ -1,5 +1,15 @@
1
1
  // see https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html
2
2
  // and /System/Library/Frameworks/CoreText.framework/Versions/A/Headers/SFNTLayoutTypes.h on a Mac
3
+
4
+ /** @typedef {import('../../types/fontkit').FeatureMap} FeatureMap */
5
+ /** @typedef {import('../../types/fontkit').FeatureValue} FeatureValue */
6
+ /** @typedef {import('../../types/fontkit').AATFeatureSettings} AATFeatureSettings */
7
+
8
+ /**
9
+ * @typedef {{ code: number, exclusive: boolean, [selector: string]: number | boolean }} AATFeatureDef
10
+ */
11
+
12
+ /** @type {Record<string, AATFeatureDef>} */
3
13
  const features = {
4
14
  allTypographicFeatures: {
5
15
  code: 0,
@@ -32,12 +42,12 @@ const features = {
32
42
  code: 3,
33
43
  exclusive: true
34
44
  },
35
- // upperAndLowerCase: 0 # deprecated
36
- // allCaps: 1 # deprecated
37
- // allLowerCase: 2 # deprecated
38
- // smallCaps: 3 # deprecated
39
- // initialCaps: 4 # deprecated
40
- // initialCapsAndSmallCaps: 5 # deprecated
45
+ // upperAndLowerCase: 0 # deprecated
46
+ // allCaps: 1 # deprecated
47
+ // allLowerCase: 2 # deprecated
48
+ // smallCaps: 3 # deprecated
49
+ // initialCaps: 4 # deprecated
50
+ // initialCapsAndSmallCaps: 5 # deprecated
41
51
  verticalSubstitution: {
42
52
  code: 4,
43
53
  exclusive: false,
@@ -100,9 +110,9 @@ const features = {
100
110
  // hyphenToEnDash: 2
101
111
  slashedZero: 4
102
112
  },
103
- // formInterrobang: 6
104
- // smartQuotes: 8
105
- // periodsToEllipsis: 10
113
+ // formInterrobang: 6
114
+ // smartQuotes: 8
115
+ // periodsToEllipsis: 10
106
116
  mathematicalExtras: {
107
117
  code: 15,
108
118
  exclusive: false,
@@ -129,7 +139,7 @@ const features = {
129
139
  exclusive: true,
130
140
  noAlternates: 0
131
141
  },
132
- // user defined options
142
+ // user defined options
133
143
  designComplexity: {
134
144
  code: 18,
135
145
  exclusive: true,
@@ -190,15 +200,15 @@ const features = {
190
200
  exclusive: true,
191
201
  noTransliteration: 0
192
202
  },
193
- // hanjaToHangul: 1
194
- // hiraganaToKatakana: 2
195
- // katakanaToHiragana: 3
196
- // kanaToRomanization: 4
197
- // romanizationToHiragana: 5
198
- // romanizationToKatakana: 6
199
- // hanjaToHangulAltOne: 7
200
- // hanjaToHangulAltTwo: 8
201
- // hanjaToHangulAltThree: 9
203
+ // hanjaToHangul: 1
204
+ // hiraganaToKatakana: 2
205
+ // katakanaToHiragana: 3
206
+ // kanaToRomanization: 4
207
+ // romanizationToHiragana: 5
208
+ // romanizationToKatakana: 6
209
+ // hanjaToHangulAltOne: 7
210
+ // hanjaToHangulAltTwo: 8
211
+ // hanjaToHangulAltThree: 9
202
212
  annotation: {
203
213
  code: 24,
204
214
  exclusive: true,
@@ -346,8 +356,17 @@ const features = {
346
356
  }
347
357
  };
348
358
 
349
- const feature = (name, selector) => [features[name].code, features[name][selector]];
359
+ /**
360
+ * @param {string} name
361
+ * @param {string} selector
362
+ * @returns {[number, number]}
363
+ */
364
+ const feature = (name, selector) => {
365
+ let f = features[name];
366
+ return [(f.code), /** @type {number} */ (f[selector])];
367
+ };
350
368
 
369
+ /** @type {Record<string, [number, number]>} */
351
370
  const OTMapping = {
352
371
  rlig: feature('ligatures', 'requiredLigatures'),
353
372
  clig: feature('ligatures', 'contextualLigatures'),
@@ -418,7 +437,7 @@ const OTMapping = {
418
437
  hwid: feature('textSpacing', 'halfWidthText'),
419
438
  qwid: feature('textSpacing', 'quarterWidthText'), // also QuarterWidthNumbers?
420
439
  twid: feature('textSpacing', 'thirdWidthText'), // also ThirdWidthNumbers?
421
- fwid: feature('textSpacing', 'proportionalText'), //??
440
+ fwid: feature('textSpacing', 'proportionalText'), // ??
422
441
  palt: feature('textSpacing', 'altProportionalText'),
423
442
  trad: feature('characterShape', 'traditionalCharacters'),
424
443
  smpl: feature('characterShape', 'simplifiedCharacters'),
@@ -456,14 +475,14 @@ const OTMapping = {
456
475
  ss20: feature('stylisticAlternatives', 'stylisticAltTwenty')
457
476
  };
458
477
 
459
- // salt: feature 'stylisticAlternatives', 'stylisticAltOne' # hmm, which one to choose
478
+ // salt: feature 'stylisticAlternatives', 'stylisticAltOne' # hmm, which one to choose
460
479
 
461
480
  // Add cv01-cv99 features
462
481
  for (let i = 1; i <= 99; i++) {
463
482
  OTMapping[`cv${`00${i}`.slice(-2)}`] = [features.characterAlternatives.code, i];
464
483
  }
465
484
 
466
- // create inverse mapping
485
+ /** @type {Record<number, Record<number, string>>} */
467
486
  let AATMapping = {};
468
487
  for (let ot in OTMapping) {
469
488
  let aat = OTMapping[ot];
@@ -474,9 +493,14 @@ for (let ot in OTMapping) {
474
493
  AATMapping[aat[0]][aat[1]] = ot;
475
494
  }
476
495
 
477
- // Maps an array of OpenType features to AAT features
478
- // in the form of {featureType:{featureSetting:true}}
496
+ /**
497
+ * Maps an OpenType feature map to AAT features
498
+ * in the form of {featureType:{featureSetting:true}}
499
+ * @param {FeatureMap | Record<string, FeatureValue>} features
500
+ * @returns {AATFeatureSettings}
501
+ */
479
502
  export function mapOTToAAT(features) {
503
+ /** @type {AATFeatureSettings} */
480
504
  let res = {};
481
505
  for (let k in features) {
482
506
  let r;
@@ -492,49 +516,68 @@ export function mapOTToAAT(features) {
492
516
  return res;
493
517
  }
494
518
 
495
- // Maps strings in a [featureType, featureSetting]
496
- // to their equivalent number codes
519
+ /**
520
+ * @param {string | number} value
521
+ * @returns {value is string}
522
+ */
523
+ function isFeatureName(value) {
524
+ return typeof value === 'string' && Number.isNaN(Number(value));
525
+ }
526
+
527
+ /**
528
+ * Maps strings in a [featureType, featureSetting]
529
+ * to their equivalent number codes
530
+ * @param {[string | number, string | number]} f
531
+ * @returns {[number | undefined, number | undefined]}
532
+ */
497
533
  function mapFeatureStrings(f) {
498
534
  let [type, setting] = f;
535
+ /** @type {number | undefined} */
499
536
  let typeCode;
500
- if (isNaN(type)) {
501
- typeCode = features[type] && features[type].code;
537
+ if (isFeatureName(type)) {
538
+ typeCode = features[type] && /** @type {number} */ (features[type].code);
502
539
  } else {
503
- typeCode = type;
540
+ typeCode = Number(type);
504
541
  }
505
542
 
543
+ /** @type {number | undefined} */
506
544
  let settingCode;
507
- if (isNaN(setting)) {
508
- settingCode = features[type] && features[type][setting];
545
+ if (isFeatureName(setting)) {
546
+ let feat = isFeatureName(type) ? features[type] : undefined;
547
+ settingCode = feat ? /** @type {number} */ (feat[setting]) : undefined;
509
548
  } else {
510
- settingCode = setting;
549
+ settingCode = Number(setting);
511
550
  }
512
551
 
513
552
  return [typeCode, settingCode];
514
553
  }
515
554
 
516
- // Maps AAT features to an array of OpenType features
517
- // Supports both arrays in the form of [[featureType, featureSetting]]
518
- // and objects in the form of {featureType:{featureSetting:true}}
519
- // featureTypes and featureSettings can be either strings or number codes
555
+ /**
556
+ * Maps AAT features to an array of OpenType features.
557
+ * Supports both arrays in the form of [[featureType, featureSetting]]
558
+ * and objects in the form of {featureType:{featureSetting:true}}.
559
+ * featureTypes and featureSettings can be either strings or number codes.
560
+ * @param {Array<[string | number, string | number]> | Record<string, Record<string, FeatureValue>>} features
561
+ * @returns {string[]}
562
+ */
520
563
  export function mapAATToOT(features) {
564
+ /** @type {Record<string, true>} */
521
565
  let res = {};
522
566
  if (Array.isArray(features)) {
523
567
  for (let k = 0; k < features.length; k++) {
524
568
  let r;
525
569
  let f = mapFeatureStrings(features[k]);
526
- if ((r = AATMapping[f[0]] && AATMapping[f[0]][f[1]])) {
570
+ if (f[0] != null && f[1] != null && (r = AATMapping[f[0]] && AATMapping[f[0]][f[1]])) {
527
571
  res[r] = true;
528
572
  }
529
573
  }
530
-
531
574
  } else if (typeof features === 'object') {
532
575
  for (let type in features) {
533
576
  let feature = features[type];
534
577
  for (let setting in feature) {
535
578
  let r;
536
579
  let f = mapFeatureStrings([type, setting]);
537
- if (feature[setting] && (r = AATMapping[f[0]] && AATMapping[f[0]][f[1]])) {
580
+ if (feature[setting] && f[0] != null && f[1] != null && (r = AATMapping[f[0]] && AATMapping[f[0]][f[1]])) {
538
581
  res[r] = true;
539
582
  }
540
583
  }
@@ -1,13 +1,27 @@
1
1
  import * as AATFeatureMap from './AATFeatureMap';
2
2
  import AATMorxProcessor from './AATMorxProcessor';
3
3
 
4
+ /** @typedef {import('../../types/fontkit').LayoutFont} LayoutFont */
5
+ /** @typedef {import('../../types/fontkit').GlyphRunLike} GlyphRunLike */
6
+ /** @typedef {import('../../types/fontkit').ScriptTag} ScriptTag */
7
+ /** @typedef {import('../../types/fontkit').LanguageTag} LanguageTag */
8
+
4
9
  export default class AATLayoutEngine {
10
+ /**
11
+ * @param {LayoutFont} font
12
+ */
5
13
  constructor(font) {
14
+ /** @type {LayoutFont} */
6
15
  this.font = font;
16
+ /** @type {AATMorxProcessor} */
7
17
  this.morxProcessor = new AATMorxProcessor(font);
18
+ /** @type {boolean} */
8
19
  this.fallbackPosition = false;
9
20
  }
10
21
 
22
+ /**
23
+ * @param {GlyphRunLike} glyphRun
24
+ */
11
25
  substitute(glyphRun) {
12
26
  // AAT expects the glyphs to be in visual order prior to morx processing,
13
27
  // so reverse the glyphs if the script is right-to-left.
@@ -15,16 +29,28 @@ export default class AATLayoutEngine {
15
29
  glyphRun.glyphs.reverse();
16
30
  }
17
31
 
18
- this.morxProcessor.process(glyphRun.glyphs, AATFeatureMap.mapOTToAAT(glyphRun.features));
32
+ this.morxProcessor.process(
33
+ /** @type {import('../../types/fontkit').LayoutGlyph[]} */ (glyphRun.glyphs),
34
+ AATFeatureMap.mapOTToAAT(glyphRun.features)
35
+ );
19
36
  }
20
37
 
38
+ /**
39
+ * @param {ScriptTag | string[] | null | undefined} [_script]
40
+ * @param {LanguageTag | null | undefined} [_language]
41
+ * @returns {string[]}
42
+ */
21
43
  getAvailableFeatures(_script, _language) {
22
44
  return AATFeatureMap.mapAATToOT(this.morxProcessor.getSupportedFeatures());
23
45
  }
24
46
 
47
+ /**
48
+ * @param {number} gid
49
+ * @returns {Set<string>}
50
+ */
25
51
  stringsForGlyph(gid) {
26
52
  let glyphStrings = this.morxProcessor.generateInputs(gid);
27
- let result = new Set;
53
+ let result = new Set();
28
54
 
29
55
  for (let glyphs of glyphStrings) {
30
56
  this._addStrings(glyphs, 0, result, '');
@@ -33,6 +59,12 @@ export default class AATLayoutEngine {
33
59
  return result;
34
60
  }
35
61
 
62
+ /**
63
+ * @param {number[]} glyphs
64
+ * @param {number} index
65
+ * @param {Set<string>} strings
66
+ * @param {string} string
67
+ */
36
68
  _addStrings(glyphs, index, strings, string) {
37
69
  let codePoints = this.font._cmapProcessor.codePointsForGlyph(glyphs[index]);
38
70
 
@@ -1,15 +1,27 @@
1
- import {cache} from '../decorators';
2
- import {range} from '../utils';
1
+ import { cache } from '../decorators';
2
+ import { range } from '../utils';
3
+
4
+ /** @typedef {import('../../types/fontkit').AATLookupTableData} AATLookupTableData */
5
+ /** @typedef {import('../../types/fontkit').AATUnboundedArray<number>} AATNumberArray */
6
+ /** @typedef {import('../../types/fontkit').AATLookupSegmentSingle} AATLookupSegmentSingle */
3
7
 
4
8
  export default class AATLookupTable {
9
+ /**
10
+ * @param {AATLookupTableData} table
11
+ */
5
12
  constructor(table) {
13
+ /** @type {AATLookupTableData} */
6
14
  this.table = table;
7
15
  }
8
16
 
17
+ /**
18
+ * @param {number} glyph
19
+ * @returns {number | null | undefined}
20
+ */
9
21
  lookup(glyph) {
10
22
  switch (this.table.version) {
11
23
  case 0: // simple array format
12
- return this.table.values.getItem(glyph);
24
+ return /** @type {AATNumberArray} */ (this.table.values).getItem(glyph);
13
25
 
14
26
  case 2: // segment format
15
27
  case 4: {
@@ -67,15 +79,20 @@ export default class AATLookupTable {
67
79
  }
68
80
 
69
81
  case 8: // lookup trimmed
70
- return this.table.values[glyph - this.table.firstGlyph];
82
+ return /** @type {number[]} */ (this.table.values)[glyph - this.table.firstGlyph];
71
83
 
72
84
  default:
73
85
  throw new Error(`Unknown lookup table format: ${this.table.version}`);
74
86
  }
75
87
  }
76
88
 
89
+ /**
90
+ * @param {number} classValue
91
+ * @returns {number[]}
92
+ */
77
93
  @cache
78
94
  glyphsForValue(classValue) {
95
+ /** @type {number[]} */
79
96
  let res = [];
80
97
 
81
98
  switch (this.table.version) {
@@ -107,8 +124,9 @@ export default class AATLookupTable {
107
124
  }
108
125
 
109
126
  case 8: { // lookup trimmed
110
- for (let i = 0; i < this.table.values.length; i++) {
111
- if (this.table.values[i] === classValue) {
127
+ let values = /** @type {number[]} */ (this.table.values);
128
+ for (let i = 0; i < values.length; i++) {
129
+ if (values[i] === classValue) {
112
130
  res.push(this.table.firstGlyph + i);
113
131
  }
114
132
  }