@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,20 +1,21 @@
1
1
  import * as r from 'restructure';
2
2
 
3
3
  // maxiumum profile
4
+ /** @type {import('restructure').Struct} */
4
5
  export default new r.Struct({
5
- version: r.int32,
6
- numGlyphs: r.uint16, // The number of glyphs in the font
7
- maxPoints: r.uint16, // Maximum points in a non-composite glyph
8
- maxContours: r.uint16, // Maximum contours in a non-composite glyph
9
- maxComponentPoints: r.uint16, // Maximum points in a composite glyph
10
- maxComponentContours: r.uint16, // Maximum contours in a composite glyph
11
- maxZones: r.uint16, // 1 if instructions do not use the twilight zone, 2 otherwise
12
- maxTwilightPoints: r.uint16, // Maximum points used in Z0
13
- maxStorage: r.uint16, // Number of Storage Area locations
14
- maxFunctionDefs: r.uint16, // Number of FDEFs
15
- maxInstructionDefs: r.uint16, // Number of IDEFs
16
- maxStackElements: r.uint16, // Maximum stack depth
17
- maxSizeOfInstructions: r.uint16, // Maximum byte count for glyph instructions
18
- maxComponentElements: r.uint16, // Maximum number of components referenced at “top level” for any composite glyph
19
- maxComponentDepth: r.uint16 // Maximum levels of recursion; 1 for simple components
6
+ version: r.int32,
7
+ numGlyphs: r.uint16, // The number of glyphs in the font
8
+ maxPoints: r.uint16, // Maximum points in a non-composite glyph
9
+ maxContours: r.uint16, // Maximum contours in a non-composite glyph
10
+ maxComponentPoints: r.uint16, // Maximum points in a composite glyph
11
+ maxComponentContours: r.uint16, // Maximum contours in a composite glyph
12
+ maxZones: r.uint16, // 1 if instructions do not use the twilight zone, 2 otherwise
13
+ maxTwilightPoints: r.uint16, // Maximum points used in Z0
14
+ maxStorage: r.uint16, // Number of Storage Area locations
15
+ maxFunctionDefs: r.uint16, // Number of FDEFs
16
+ maxInstructionDefs: r.uint16, // Number of IDEFs
17
+ maxStackElements: r.uint16, // Maximum stack depth
18
+ maxSizeOfInstructions: r.uint16, // Maximum byte count for glyph instructions
19
+ maxComponentElements: r.uint16, // Maximum number of components referenced at “top level” for any composite glyph
20
+ maxComponentDepth: r.uint16 // Maximum levels of recursion; 1 for simple components
20
21
  });
@@ -1,6 +1,8 @@
1
1
  import * as r from 'restructure';
2
2
  import { UnboundedArray, LookupTable, StateTable } from './aat';
3
3
 
4
+ /** @typedef {import('restructure').StructValue} StructValue */
5
+
4
6
  let LigatureData = {
5
7
  action: r.uint16
6
8
  };
@@ -16,32 +18,32 @@ let InsertionData = {
16
18
  };
17
19
 
18
20
  let SubstitutionTable = new r.Struct({
19
- items: new UnboundedArray(new r.Pointer(r.uint32, new LookupTable))
21
+ items: new UnboundedArray(new r.Pointer(r.uint32, LookupTable()))
20
22
  });
21
23
 
22
24
  let SubtableData = new r.VersionedStruct('type', {
23
25
  0: { // Indic Rearrangement Subtable
24
- stateTable: new StateTable
26
+ stateTable: StateTable()
25
27
  },
26
28
 
27
29
  1: { // Contextual Glyph Substitution Subtable
28
- stateTable: new StateTable(ContextualData),
30
+ stateTable: StateTable(ContextualData),
29
31
  substitutionTable: new r.Pointer(r.uint32, SubstitutionTable)
30
32
  },
31
33
 
32
34
  2: { // Ligature subtable
33
- stateTable: new StateTable(LigatureData),
35
+ stateTable: StateTable(LigatureData),
34
36
  ligatureActions: new r.Pointer(r.uint32, new UnboundedArray(r.uint32)),
35
37
  components: new r.Pointer(r.uint32, new UnboundedArray(r.uint16)),
36
38
  ligatureList: new r.Pointer(r.uint32, new UnboundedArray(r.uint16))
37
39
  },
38
40
 
39
41
  4: { // Non-contextual Glyph Substitution Subtable
40
- lookupTable: new LookupTable
42
+ lookupTable: LookupTable()
41
43
  },
42
44
 
43
45
  5: { // Glyph Insertion Subtable
44
- stateTable: new StateTable(InsertionData),
46
+ stateTable: StateTable(InsertionData),
45
47
  insertionActions: new r.Pointer(r.uint32, new UnboundedArray(r.uint16))
46
48
  }
47
49
  });
@@ -52,28 +54,33 @@ let Subtable = new r.Struct({
52
54
  type: r.uint8,
53
55
  subFeatureFlags: r.uint32,
54
56
  table: SubtableData,
55
- padding: new r.Reserved(r.uint8, t => t.length - t._currentOffset)
57
+ padding: new r.Reserved(
58
+ r.uint8,
59
+ /** @param {StructValue} t @returns {number} */
60
+ t => /** @type {number} */ (t.length) - /** @type {number} */ (t._currentOffset)
61
+ )
56
62
  });
57
63
 
58
64
  let FeatureEntry = new r.Struct({
59
- featureType: r.uint16,
65
+ featureType: r.uint16,
60
66
  featureSetting: r.uint16,
61
- enableFlags: r.uint32,
62
- disableFlags: r.uint32
67
+ enableFlags: r.uint32,
68
+ disableFlags: r.uint32
63
69
  });
64
70
 
65
71
  let MorxChain = new r.Struct({
66
- defaultFlags: r.uint32,
67
- chainLength: r.uint32,
68
- nFeatureEntries: r.uint32,
69
- nSubtables: r.uint32,
70
- features: new r.Array(FeatureEntry, 'nFeatureEntries'),
71
- subtables: new r.Array(Subtable, 'nSubtables')
72
+ defaultFlags: r.uint32,
73
+ chainLength: r.uint32,
74
+ nFeatureEntries: r.uint32,
75
+ nSubtables: r.uint32,
76
+ features: new r.Array(FeatureEntry, 'nFeatureEntries'),
77
+ subtables: new r.Array(Subtable, 'nSubtables')
72
78
  });
73
79
 
80
+ /** @type {import('restructure').Struct} */
74
81
  export default new r.Struct({
75
- version: r.uint16,
76
- unused: new r.Reserved(r.uint16),
77
- nChains: r.uint32,
78
- chains: new r.Array(MorxChain, 'nChains')
82
+ version: r.uint16,
83
+ unused: new r.Reserved(r.uint16),
84
+ nChains: r.uint32,
85
+ chains: new r.Array(MorxChain, 'nChains')
79
86
  });
@@ -1,35 +1,93 @@
1
1
  import * as r from 'restructure';
2
- import {getEncoding, LANGUAGES} from '../encodings';
2
+ import { getEncoding, LANGUAGES } from '../encodings';
3
+
4
+ /** @typedef {import('restructure').StructValue} StructValue */
5
+
6
+ /**
7
+ * @typedef {{
8
+ * platformID: number,
9
+ * encodingID: number,
10
+ * languageID: number,
11
+ * nameID: number,
12
+ * length: number,
13
+ * string: string
14
+ * }} NameRecordValue
15
+ */
16
+
17
+ /**
18
+ * @typedef {Record<string, string | unknown>} LangStringMap
19
+ */
20
+
21
+ /**
22
+ * @typedef {{
23
+ * fontFeatures: Record<number, LangStringMap>,
24
+ * reservedNameID?: Record<number, LangStringMap>,
25
+ * [key: string]: LangStringMap | Record<number, LangStringMap> | undefined
26
+ * }} NameRecordsMap
27
+ */
28
+
29
+ /**
30
+ * @typedef {StructValue & {
31
+ * version: number,
32
+ * count: number,
33
+ * stringOffset: number,
34
+ * records: NameRecordValue[] | NameRecordsMap,
35
+ * langTags?: Array<{ tag: string }>
36
+ * }} NameTableValue
37
+ */
3
38
 
4
39
  let NameRecord = new r.Struct({
5
40
  platformID: r.uint16,
6
41
  encodingID: r.uint16,
7
42
  languageID: r.uint16,
8
- nameID: r.uint16,
9
- length: r.uint16,
10
- string: new r.Pointer(r.uint16,
11
- new r.String('length', t => getEncoding(t.platformID, t.encodingID, t.languageID)),
12
- { type: 'parent', relativeTo: ctx => ctx.parent.stringOffset, allowNull: false }
43
+ nameID: r.uint16,
44
+ length: r.uint16,
45
+ string: new r.Pointer(
46
+ r.uint16,
47
+ new r.String(
48
+ 'length',
49
+ /** @param {StructValue} t @returns {string} */
50
+ t => getEncoding(
51
+ /** @type {number} */ (t.platformID),
52
+ /** @type {number} */ (t.encodingID),
53
+ /** @type {number} */ (t.languageID)
54
+ ) || 'utf16be'
55
+ ),
56
+ {
57
+ type: 'parent',
58
+ /** @param {StructValue} ctx @returns {number} */
59
+ relativeTo: ctx => /** @type {number} */ (/** @type {StructValue} */ (ctx.parent).stringOffset),
60
+ allowNull: false
61
+ }
13
62
  )
14
63
  });
15
64
 
16
65
  let LangTagRecord = new r.Struct({
17
- length: r.uint16,
18
- tag: new r.Pointer(r.uint16, new r.String('length', 'utf16be'), {type: 'parent', relativeTo: ctx => ctx.stringOffset})
66
+ length: r.uint16,
67
+ tag: new r.Pointer(
68
+ r.uint16,
69
+ new r.String('length', 'utf16be'),
70
+ {
71
+ type: 'parent',
72
+ /** @param {StructValue} ctx @returns {number} */
73
+ relativeTo: ctx => /** @type {number} */ (ctx.stringOffset)
74
+ }
75
+ )
19
76
  });
20
77
 
78
+ /** @type {import('restructure').VersionedStruct} */
21
79
  var NameTable = new r.VersionedStruct(r.uint16, {
22
80
  0: {
23
- count: r.uint16,
24
- stringOffset: r.uint16,
25
- records: new r.Array(NameRecord, 'count')
81
+ count: r.uint16,
82
+ stringOffset: r.uint16,
83
+ records: new r.Array(NameRecord, 'count')
26
84
  },
27
85
  1: {
28
- count: r.uint16,
29
- stringOffset: r.uint16,
30
- records: new r.Array(NameRecord, 'count'),
31
- langTagCount: r.uint16,
32
- langTags: new r.Array(LangTagRecord, 'langTagCount')
86
+ count: r.uint16,
87
+ stringOffset: r.uint16,
88
+ records: new r.Array(NameRecord, 'count'),
89
+ langTagCount: r.uint16,
90
+ langTags: new r.Array(LangTagRecord, 'langTagCount')
33
91
  }
34
92
  });
35
93
 
@@ -61,9 +119,15 @@ const NAMES = [
61
119
  'wwsSubfamilyName',
62
120
  'lightBackgroundPalette',
63
121
  'darkBackgroundPalette',
64
- 'variationsPostScriptNamePrefix',
122
+ 'variationsPostScriptNamePrefix'
65
123
  ];
66
124
 
125
+ /**
126
+ * @param {NameRecordValue[]} out
127
+ * @param {number} nameID
128
+ * @param {unknown} string
129
+ * @returns {void}
130
+ */
67
131
  function pushEnRecord(out, nameID, string) {
68
132
  if (typeof string !== 'string') return;
69
133
 
@@ -77,14 +141,18 @@ function pushEnRecord(out, nameID, string) {
77
141
  });
78
142
  }
79
143
 
80
- NameTable.process = function(_stream) {
81
- let records = {fontFeatures: {}};
144
+ NameTable.process = function (_stream) {
145
+ let self = /** @type {NameTableValue} */ (this);
146
+ /** @type {NameRecordsMap} */
147
+ let records = { fontFeatures: {} };
82
148
 
83
- for (let record of this.records) {
84
- let language = LANGUAGES[record.platformID][record.languageID];
149
+ for (let record of /** @type {NameRecordValue[]} */ (self.records)) {
150
+ let platformMap = LANGUAGES[record.platformID] || {};
151
+ /** @type {string | undefined} */
152
+ let language = platformMap[record.languageID];
85
153
 
86
- if (language == null && this.langTags != null && record.languageID >= 0x8000) {
87
- language = this.langTags[record.languageID - 0x8000].tag;
154
+ if (language == null && self.langTags != null && record.languageID >= 0x8000) {
155
+ language = self.langTags[record.languageID - 0x8000].tag;
88
156
  }
89
157
 
90
158
  if (language == null) {
@@ -109,49 +177,62 @@ NameTable.process = function(_stream) {
109
177
  }
110
178
  }
111
179
 
112
- this.records = records;
180
+ self.records = records;
113
181
  };
114
182
 
115
- NameTable.preEncode = function() {
116
- if (Array.isArray(this.records)) return;
117
- this.version = 0;
183
+ NameTable.preEncode = function () {
184
+ let self = /** @type {NameTableValue} */ (this);
185
+ if (Array.isArray(self.records)) return;
186
+ self.version = 0;
118
187
 
188
+ /** @type {NameRecordValue[]} */
119
189
  let records = [];
120
- for (let key in this.records) {
121
- let val = this.records[key];
190
+ /** @type {NameRecordsMap} */
191
+ let map = self.records;
192
+ for (let key of Object.keys(map)) {
193
+ let val = map[key];
122
194
 
123
195
  if (key === 'fontFeatures') {
124
196
  // Mirrors of IDs < 256 are encoded via named/reserved keys above.
125
- for (let id in val) {
126
- if (+id >= 256) pushEnRecord(records, +id, val[id].en);
197
+ let features = /** @type {Record<number, LangStringMap>} */ (val);
198
+ for (let id of Object.keys(features)) {
199
+ if (+id >= 256) {
200
+ let langs = features[+id];
201
+ pushEnRecord(records, +id, langs && langs.en);
202
+ }
127
203
  }
128
204
  continue;
129
205
  }
130
206
 
131
207
  if (key === 'reservedNameID') {
132
- for (let id in val) pushEnRecord(records, +id, val[id].en);
208
+ let reserved = /** @type {Record<number, LangStringMap>} */ (val);
209
+ for (let id of Object.keys(reserved)) {
210
+ let langs = reserved[+id];
211
+ pushEnRecord(records, +id, langs && langs.en);
212
+ }
133
213
  continue;
134
214
  }
135
215
 
136
216
  let nameID = NAMES.indexOf(key);
137
217
  if (nameID < 0) continue;
138
218
 
139
- pushEnRecord(records, nameID, val.en);
219
+ let langs = /** @type {LangStringMap} */ (val);
220
+ pushEnRecord(records, nameID, langs.en);
140
221
 
141
222
  // Match historical behaviour: also write PostScript name for Mac platform.
142
- if (key === 'postscriptName' && typeof val.en === 'string') {
223
+ if (key === 'postscriptName' && typeof langs.en === 'string') {
143
224
  records.push({
144
225
  platformID: 1,
145
226
  encodingID: 0,
146
227
  languageID: 0,
147
228
  nameID,
148
- length: val.en.length,
149
- string: val.en
229
+ length: langs.en.length,
230
+ string: langs.en
150
231
  });
151
232
  }
152
233
  }
153
234
 
154
- this.records = records;
155
- this.count = records.length;
156
- this.stringOffset = NameTable.size(this, null, false);
235
+ self.records = records;
236
+ self.count = records.length;
237
+ self.stringOffset = NameTable.size(self, null, false);
157
238
  };
@@ -8,8 +8,9 @@ let OpticalBounds = new r.Struct({
8
8
  bottom: r.int16
9
9
  });
10
10
 
11
+ /** @type {import('restructure').Struct} */
11
12
  export default new r.Struct({
12
13
  version: r.fixed32,
13
14
  format: r.uint16,
14
- lookupTable: new LookupTable(OpticalBounds)
15
+ lookupTable: LookupTable(OpticalBounds)
15
16
  });