@cantoo/fontkit 2.0.4

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 (163) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +274 -0
  3. package/dist/browser-module.mjs +13660 -0
  4. package/dist/browser-module.mjs.map +1 -0
  5. package/dist/browser.cjs +13689 -0
  6. package/dist/browser.cjs.map +1 -0
  7. package/dist/main.cjs +13712 -0
  8. package/dist/main.cjs.map +1 -0
  9. package/dist/module.mjs +13673 -0
  10. package/dist/module.mjs.map +1 -0
  11. package/package.json +99 -0
  12. package/src/CmapProcessor.js +285 -0
  13. package/src/DFont.js +113 -0
  14. package/src/TTFFont.js +621 -0
  15. package/src/TrueTypeCollection.js +65 -0
  16. package/src/WOFF2Font.js +222 -0
  17. package/src/WOFFFont.js +56 -0
  18. package/src/aat/AATFeatureMap.js +545 -0
  19. package/src/aat/AATLayoutEngine.js +48 -0
  20. package/src/aat/AATLookupTable.js +125 -0
  21. package/src/aat/AATMorxProcessor.js +429 -0
  22. package/src/aat/AATStateMachine.js +96 -0
  23. package/src/base.js +29 -0
  24. package/src/cff/CFFCharsets.js +99 -0
  25. package/src/cff/CFFDict.js +166 -0
  26. package/src/cff/CFFEncodings.js +48 -0
  27. package/src/cff/CFFFont.js +158 -0
  28. package/src/cff/CFFIndex.js +150 -0
  29. package/src/cff/CFFOperand.js +135 -0
  30. package/src/cff/CFFPointer.js +50 -0
  31. package/src/cff/CFFPrivateDict.js +39 -0
  32. package/src/cff/CFFStandardStrings.js +71 -0
  33. package/src/cff/CFFTop.js +236 -0
  34. package/src/decorators.js +36 -0
  35. package/src/encodings.js +219 -0
  36. package/src/fs.js +12 -0
  37. package/src/glyph/BBox.js +72 -0
  38. package/src/glyph/CBDTGlyph.js +9 -0
  39. package/src/glyph/CFFGlyph.js +635 -0
  40. package/src/glyph/COLRGlyph.js +108 -0
  41. package/src/glyph/Glyph.js +270 -0
  42. package/src/glyph/GlyphVariationProcessor.js +487 -0
  43. package/src/glyph/Path.js +257 -0
  44. package/src/glyph/SBIXGlyph.js +54 -0
  45. package/src/glyph/StandardNames.js +27 -0
  46. package/src/glyph/TTFGlyph.js +408 -0
  47. package/src/glyph/TTFGlyphEncoder.js +158 -0
  48. package/src/glyph/WOFF2Glyph.js +70 -0
  49. package/src/index.js +15 -0
  50. package/src/layout/GlyphPosition.js +30 -0
  51. package/src/layout/GlyphRun.js +108 -0
  52. package/src/layout/KernProcessor.js +97 -0
  53. package/src/layout/LayoutEngine.js +190 -0
  54. package/src/layout/Script.js +231 -0
  55. package/src/layout/UnicodeLayoutEngine.js +250 -0
  56. package/src/node.js +16 -0
  57. package/src/opentype/GPOSProcessor.js +311 -0
  58. package/src/opentype/GSUBProcessor.js +208 -0
  59. package/src/opentype/GlyphInfo.js +57 -0
  60. package/src/opentype/GlyphIterator.js +82 -0
  61. package/src/opentype/OTLayoutEngine.js +117 -0
  62. package/src/opentype/OTProcessor.js +472 -0
  63. package/src/opentype/ShapingPlan.js +121 -0
  64. package/src/opentype/shapers/ArabicShaper.js +124 -0
  65. package/src/opentype/shapers/DefaultShaper.js +116 -0
  66. package/src/opentype/shapers/HangulShaper.js +285 -0
  67. package/src/opentype/shapers/HebrewShaper.js +105 -0
  68. package/src/opentype/shapers/IndicShaper.js +914 -0
  69. package/src/opentype/shapers/ThaiShaper.js +238 -0
  70. package/src/opentype/shapers/UniversalShaper.js +186 -0
  71. package/src/opentype/shapers/data.trie +0 -0
  72. package/src/opentype/shapers/gen-indic.js +208 -0
  73. package/src/opentype/shapers/gen-use.js +287 -0
  74. package/src/opentype/shapers/generate-data.js +33 -0
  75. package/src/opentype/shapers/index.js +109 -0
  76. package/src/opentype/shapers/indic-data.js +175 -0
  77. package/src/opentype/shapers/indic.json +1 -0
  78. package/src/opentype/shapers/indic.machine +31 -0
  79. package/src/opentype/shapers/indic.trie +0 -0
  80. package/src/opentype/shapers/use.json +1 -0
  81. package/src/opentype/shapers/use.machine +44 -0
  82. package/src/opentype/shapers/use.trie +0 -0
  83. package/src/packages/unicode-properties/LICENSE +8 -0
  84. package/src/packages/unicode-properties/README.md +12 -0
  85. package/src/packages/unicode-properties/data-trie.js +1 -0
  86. package/src/packages/unicode-properties/data.js +1 -0
  87. package/src/packages/unicode-properties/data.json +1 -0
  88. package/src/packages/unicode-properties/data.trie +0 -0
  89. package/src/packages/unicode-properties/dist/index.cjs +257 -0
  90. package/src/packages/unicode-properties/dist/index.cjs.map +7 -0
  91. package/src/packages/unicode-properties/dist/index.mjs +234 -0
  92. package/src/packages/unicode-properties/dist/index.mjs.map +7 -0
  93. package/src/packages/unicode-properties/generate.js +107 -0
  94. package/src/packages/unicode-properties/index.js +184 -0
  95. package/src/packages/unicode-properties/package.json +50 -0
  96. package/src/packages/unicode-trie/LICENSE +8 -0
  97. package/src/packages/unicode-trie/README.md +13 -0
  98. package/src/packages/unicode-trie/builder.js +965 -0
  99. package/src/packages/unicode-trie/dist/builder.cjs +711 -0
  100. package/src/packages/unicode-trie/dist/builder.cjs.map +7 -0
  101. package/src/packages/unicode-trie/dist/builder.mjs +690 -0
  102. package/src/packages/unicode-trie/dist/builder.mjs.map +7 -0
  103. package/src/packages/unicode-trie/dist/index.cjs +112 -0
  104. package/src/packages/unicode-trie/dist/index.cjs.map +7 -0
  105. package/src/packages/unicode-trie/dist/index.mjs +91 -0
  106. package/src/packages/unicode-trie/dist/index.mjs.map +7 -0
  107. package/src/packages/unicode-trie/index.js +135 -0
  108. package/src/packages/unicode-trie/package.json +49 -0
  109. package/src/packages/unicode-trie/swap.js +21 -0
  110. package/src/subset/CFFSubset.js +176 -0
  111. package/src/subset/Subset.js +63 -0
  112. package/src/subset/TTFSubset.js +130 -0
  113. package/src/tables/BASE.js +78 -0
  114. package/src/tables/COLR.js +25 -0
  115. package/src/tables/CPAL.js +24 -0
  116. package/src/tables/DSIG.js +21 -0
  117. package/src/tables/EBDT.js +91 -0
  118. package/src/tables/EBLC.js +80 -0
  119. package/src/tables/GDEF.js +57 -0
  120. package/src/tables/GPOS.js +209 -0
  121. package/src/tables/GSUB.js +85 -0
  122. package/src/tables/HVAR.js +44 -0
  123. package/src/tables/JSTF.js +43 -0
  124. package/src/tables/LTSH.js +10 -0
  125. package/src/tables/OS2.js +84 -0
  126. package/src/tables/PCLT.js +21 -0
  127. package/src/tables/STAT.js +99 -0
  128. package/src/tables/VDMX.js +33 -0
  129. package/src/tables/VORG.js +14 -0
  130. package/src/tables/WOFF2Directory.js +73 -0
  131. package/src/tables/WOFFDirectory.js +37 -0
  132. package/src/tables/aat.js +157 -0
  133. package/src/tables/avar.js +19 -0
  134. package/src/tables/bsln.js +31 -0
  135. package/src/tables/cmap.js +127 -0
  136. package/src/tables/cvt.js +6 -0
  137. package/src/tables/directory.js +58 -0
  138. package/src/tables/feat.js +28 -0
  139. package/src/tables/fpgm.js +8 -0
  140. package/src/tables/fvar.js +31 -0
  141. package/src/tables/gasp.js +15 -0
  142. package/src/tables/glyf.js +4 -0
  143. package/src/tables/gvar.js +27 -0
  144. package/src/tables/hdmx.js +15 -0
  145. package/src/tables/head.js +25 -0
  146. package/src/tables/hhea.js +19 -0
  147. package/src/tables/hmtx.js +11 -0
  148. package/src/tables/index.js +119 -0
  149. package/src/tables/just.js +81 -0
  150. package/src/tables/kern.js +91 -0
  151. package/src/tables/loca.js +30 -0
  152. package/src/tables/maxp.js +20 -0
  153. package/src/tables/morx.js +79 -0
  154. package/src/tables/name.js +157 -0
  155. package/src/tables/opbd.js +15 -0
  156. package/src/tables/opentype.js +217 -0
  157. package/src/tables/post.js +34 -0
  158. package/src/tables/prep.js +6 -0
  159. package/src/tables/sbix.js +17 -0
  160. package/src/tables/variations.js +80 -0
  161. package/src/tables/vhea.js +19 -0
  162. package/src/tables/vmtx.js +12 -0
  163. package/src/utils.js +62 -0
@@ -0,0 +1,545 @@
1
+ // see https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html
2
+ // and /System/Library/Frameworks/CoreText.framework/Versions/A/Headers/SFNTLayoutTypes.h on a Mac
3
+ const features = {
4
+ allTypographicFeatures: {
5
+ code: 0,
6
+ exclusive: false,
7
+ allTypeFeatures: 0
8
+ },
9
+ ligatures: {
10
+ code: 1,
11
+ exclusive: false,
12
+ requiredLigatures: 0,
13
+ commonLigatures: 2,
14
+ rareLigatures: 4,
15
+ // logos: 6
16
+ rebusPictures: 8,
17
+ diphthongLigatures: 10,
18
+ squaredLigatures: 12,
19
+ abbrevSquaredLigatures: 14,
20
+ symbolLigatures: 16,
21
+ contextualLigatures: 18,
22
+ historicalLigatures: 20
23
+ },
24
+ cursiveConnection: {
25
+ code: 2,
26
+ exclusive: true,
27
+ unconnected: 0,
28
+ partiallyConnected: 1,
29
+ cursive: 2
30
+ },
31
+ letterCase: {
32
+ code: 3,
33
+ exclusive: true
34
+ },
35
+ // upperAndLowerCase: 0 # deprecated
36
+ // allCaps: 1 # deprecated
37
+ // allLowerCase: 2 # deprecated
38
+ // smallCaps: 3 # deprecated
39
+ // initialCaps: 4 # deprecated
40
+ // initialCapsAndSmallCaps: 5 # deprecated
41
+ verticalSubstitution: {
42
+ code: 4,
43
+ exclusive: false,
44
+ substituteVerticalForms: 0
45
+ },
46
+ linguisticRearrangement: {
47
+ code: 5,
48
+ exclusive: false,
49
+ linguisticRearrangement: 0
50
+ },
51
+ numberSpacing: {
52
+ code: 6,
53
+ exclusive: true,
54
+ monospacedNumbers: 0,
55
+ proportionalNumbers: 1,
56
+ thirdWidthNumbers: 2,
57
+ quarterWidthNumbers: 3
58
+ },
59
+ smartSwash: {
60
+ code: 8,
61
+ exclusive: false,
62
+ wordInitialSwashes: 0,
63
+ wordFinalSwashes: 2,
64
+ // lineInitialSwashes: 4
65
+ // lineFinalSwashes: 6
66
+ nonFinalSwashes: 8
67
+ },
68
+ diacritics: {
69
+ code: 9,
70
+ exclusive: true,
71
+ showDiacritics: 0,
72
+ hideDiacritics: 1,
73
+ decomposeDiacritics: 2
74
+ },
75
+ verticalPosition: {
76
+ code: 10,
77
+ exclusive: true,
78
+ normalPosition: 0,
79
+ superiors: 1,
80
+ inferiors: 2,
81
+ ordinals: 3,
82
+ scientificInferiors: 4
83
+ },
84
+ fractions: {
85
+ code: 11,
86
+ exclusive: true,
87
+ noFractions: 0,
88
+ verticalFractions: 1,
89
+ diagonalFractions: 2
90
+ },
91
+ overlappingCharacters: {
92
+ code: 13,
93
+ exclusive: false,
94
+ preventOverlap: 0
95
+ },
96
+ typographicExtras: {
97
+ code: 14,
98
+ exclusive: false,
99
+ // hyphensToEmDash: 0
100
+ // hyphenToEnDash: 2
101
+ slashedZero: 4
102
+ },
103
+ // formInterrobang: 6
104
+ // smartQuotes: 8
105
+ // periodsToEllipsis: 10
106
+ mathematicalExtras: {
107
+ code: 15,
108
+ exclusive: false,
109
+ // hyphenToMinus: 0
110
+ // asteristoMultiply: 2
111
+ // slashToDivide: 4
112
+ // inequalityLigatures: 6
113
+ // exponents: 8
114
+ mathematicalGreek: 10
115
+ },
116
+ ornamentSets: {
117
+ code: 16,
118
+ exclusive: true,
119
+ noOrnaments: 0,
120
+ dingbats: 1,
121
+ piCharacters: 2,
122
+ fleurons: 3,
123
+ decorativeBorders: 4,
124
+ internationalSymbols: 5,
125
+ mathSymbols: 6
126
+ },
127
+ characterAlternatives: {
128
+ code: 17,
129
+ exclusive: true,
130
+ noAlternates: 0
131
+ },
132
+ // user defined options
133
+ designComplexity: {
134
+ code: 18,
135
+ exclusive: true,
136
+ designLevel1: 0,
137
+ designLevel2: 1,
138
+ designLevel3: 2,
139
+ designLevel4: 3,
140
+ designLevel5: 4
141
+ },
142
+ styleOptions: {
143
+ code: 19,
144
+ exclusive: true,
145
+ noStyleOptions: 0,
146
+ displayText: 1,
147
+ engravedText: 2,
148
+ illuminatedCaps: 3,
149
+ titlingCaps: 4,
150
+ tallCaps: 5
151
+ },
152
+ characterShape: {
153
+ code: 20,
154
+ exclusive: true,
155
+ traditionalCharacters: 0,
156
+ simplifiedCharacters: 1,
157
+ JIS1978Characters: 2,
158
+ JIS1983Characters: 3,
159
+ JIS1990Characters: 4,
160
+ traditionalAltOne: 5,
161
+ traditionalAltTwo: 6,
162
+ traditionalAltThree: 7,
163
+ traditionalAltFour: 8,
164
+ traditionalAltFive: 9,
165
+ expertCharacters: 10,
166
+ JIS2004Characters: 11,
167
+ hojoCharacters: 12,
168
+ NLCCharacters: 13,
169
+ traditionalNamesCharacters: 14
170
+ },
171
+ numberCase: {
172
+ code: 21,
173
+ exclusive: true,
174
+ lowerCaseNumbers: 0,
175
+ upperCaseNumbers: 1
176
+ },
177
+ textSpacing: {
178
+ code: 22,
179
+ exclusive: true,
180
+ proportionalText: 0,
181
+ monospacedText: 1,
182
+ halfWidthText: 2,
183
+ thirdWidthText: 3,
184
+ quarterWidthText: 4,
185
+ altProportionalText: 5,
186
+ altHalfWidthText: 6
187
+ },
188
+ transliteration: {
189
+ code: 23,
190
+ exclusive: true,
191
+ noTransliteration: 0
192
+ },
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
202
+ annotation: {
203
+ code: 24,
204
+ exclusive: true,
205
+ noAnnotation: 0,
206
+ boxAnnotation: 1,
207
+ roundedBoxAnnotation: 2,
208
+ circleAnnotation: 3,
209
+ invertedCircleAnnotation: 4,
210
+ parenthesisAnnotation: 5,
211
+ periodAnnotation: 6,
212
+ romanNumeralAnnotation: 7,
213
+ diamondAnnotation: 8,
214
+ invertedBoxAnnotation: 9,
215
+ invertedRoundedBoxAnnotation: 10
216
+ },
217
+ kanaSpacing: {
218
+ code: 25,
219
+ exclusive: true,
220
+ fullWidthKana: 0,
221
+ proportionalKana: 1
222
+ },
223
+ ideographicSpacing: {
224
+ code: 26,
225
+ exclusive: true,
226
+ fullWidthIdeographs: 0,
227
+ proportionalIdeographs: 1,
228
+ halfWidthIdeographs: 2
229
+ },
230
+ unicodeDecomposition: {
231
+ code: 27,
232
+ exclusive: false,
233
+ canonicalComposition: 0,
234
+ compatibilityComposition: 2,
235
+ transcodingComposition: 4
236
+ },
237
+ rubyKana: {
238
+ code: 28,
239
+ exclusive: false,
240
+ // noRubyKana: 0 # deprecated - use rubyKanaOff instead
241
+ // rubyKana: 1 # deprecated - use rubyKanaOn instead
242
+ rubyKana: 2
243
+ },
244
+ CJKSymbolAlternatives: {
245
+ code: 29,
246
+ exclusive: true,
247
+ noCJKSymbolAlternatives: 0,
248
+ CJKSymbolAltOne: 1,
249
+ CJKSymbolAltTwo: 2,
250
+ CJKSymbolAltThree: 3,
251
+ CJKSymbolAltFour: 4,
252
+ CJKSymbolAltFive: 5
253
+ },
254
+ ideographicAlternatives: {
255
+ code: 30,
256
+ exclusive: true,
257
+ noIdeographicAlternatives: 0,
258
+ ideographicAltOne: 1,
259
+ ideographicAltTwo: 2,
260
+ ideographicAltThree: 3,
261
+ ideographicAltFour: 4,
262
+ ideographicAltFive: 5
263
+ },
264
+ CJKVerticalRomanPlacement: {
265
+ code: 31,
266
+ exclusive: true,
267
+ CJKVerticalRomanCentered: 0,
268
+ CJKVerticalRomanHBaseline: 1
269
+ },
270
+ italicCJKRoman: {
271
+ code: 32,
272
+ exclusive: false,
273
+ // noCJKItalicRoman: 0 # deprecated - use CJKItalicRomanOff instead
274
+ // CJKItalicRoman: 1 # deprecated - use CJKItalicRomanOn instead
275
+ CJKItalicRoman: 2
276
+ },
277
+ caseSensitiveLayout: {
278
+ code: 33,
279
+ exclusive: false,
280
+ caseSensitiveLayout: 0,
281
+ caseSensitiveSpacing: 2
282
+ },
283
+ alternateKana: {
284
+ code: 34,
285
+ exclusive: false,
286
+ alternateHorizKana: 0,
287
+ alternateVertKana: 2
288
+ },
289
+ stylisticAlternatives: {
290
+ code: 35,
291
+ exclusive: false,
292
+ noStylisticAlternates: 0,
293
+ stylisticAltOne: 2,
294
+ stylisticAltTwo: 4,
295
+ stylisticAltThree: 6,
296
+ stylisticAltFour: 8,
297
+ stylisticAltFive: 10,
298
+ stylisticAltSix: 12,
299
+ stylisticAltSeven: 14,
300
+ stylisticAltEight: 16,
301
+ stylisticAltNine: 18,
302
+ stylisticAltTen: 20,
303
+ stylisticAltEleven: 22,
304
+ stylisticAltTwelve: 24,
305
+ stylisticAltThirteen: 26,
306
+ stylisticAltFourteen: 28,
307
+ stylisticAltFifteen: 30,
308
+ stylisticAltSixteen: 32,
309
+ stylisticAltSeventeen: 34,
310
+ stylisticAltEighteen: 36,
311
+ stylisticAltNineteen: 38,
312
+ stylisticAltTwenty: 40
313
+ },
314
+ contextualAlternates: {
315
+ code: 36,
316
+ exclusive: false,
317
+ contextualAlternates: 0,
318
+ swashAlternates: 2,
319
+ contextualSwashAlternates: 4
320
+ },
321
+ lowerCase: {
322
+ code: 37,
323
+ exclusive: true,
324
+ defaultLowerCase: 0,
325
+ lowerCaseSmallCaps: 1,
326
+ lowerCasePetiteCaps: 2
327
+ },
328
+ upperCase: {
329
+ code: 38,
330
+ exclusive: true,
331
+ defaultUpperCase: 0,
332
+ upperCaseSmallCaps: 1,
333
+ upperCasePetiteCaps: 2
334
+ },
335
+ languageTag: { // indices into ltag table
336
+ code: 39,
337
+ exclusive: true
338
+ },
339
+ CJKRomanSpacing: {
340
+ code: 103,
341
+ exclusive: true,
342
+ halfWidthCJKRoman: 0,
343
+ proportionalCJKRoman: 1,
344
+ defaultCJKRoman: 2,
345
+ fullWidthCJKRoman: 3
346
+ }
347
+ };
348
+
349
+ const feature = (name, selector) => [features[name].code, features[name][selector]];
350
+
351
+ const OTMapping = {
352
+ rlig: feature('ligatures', 'requiredLigatures'),
353
+ clig: feature('ligatures', 'contextualLigatures'),
354
+ dlig: feature('ligatures', 'rareLigatures'),
355
+ hlig: feature('ligatures', 'historicalLigatures'),
356
+ liga: feature('ligatures', 'commonLigatures'),
357
+ hist: feature('ligatures', 'historicalLigatures'), // ??
358
+
359
+ smcp: feature('lowerCase', 'lowerCaseSmallCaps'),
360
+ pcap: feature('lowerCase', 'lowerCasePetiteCaps'),
361
+
362
+ frac: feature('fractions', 'diagonalFractions'),
363
+ dnom: feature('fractions', 'diagonalFractions'), // ??
364
+ numr: feature('fractions', 'diagonalFractions'), // ??
365
+ afrc: feature('fractions', 'verticalFractions'),
366
+ // aalt
367
+ // abvf, abvm, abvs, akhn, blwf, blwm, blws, cfar, cjct, cpsp, falt, isol, jalt, ljmo, mset?
368
+ // ltra, ltrm, nukt, pref, pres, pstf, psts, rand, rkrf, rphf, rtla, rtlm, size, tjmo, tnum?
369
+ // unic, vatu, vhal, vjmo, vpal, vrt2
370
+ // dist -> trak table?
371
+ // kern, vkrn -> kern table
372
+ // lfbd + opbd + rtbd -> opbd table?
373
+ // mark, mkmk -> acnt table?
374
+ // locl -> languageTag + ltag table
375
+
376
+ case: feature('caseSensitiveLayout', 'caseSensitiveLayout'), // also caseSensitiveSpacing
377
+ ccmp: feature('unicodeDecomposition', 'canonicalComposition'), // compatibilityComposition?
378
+ cpct: feature('CJKVerticalRomanPlacement', 'CJKVerticalRomanCentered'), // guess..., probably not given below
379
+ valt: feature('CJKVerticalRomanPlacement', 'CJKVerticalRomanCentered'),
380
+ swsh: feature('contextualAlternates', 'swashAlternates'),
381
+ cswh: feature('contextualAlternates', 'contextualSwashAlternates'),
382
+ curs: feature('cursiveConnection', 'cursive'), // ??
383
+ c2pc: feature('upperCase', 'upperCasePetiteCaps'),
384
+ c2sc: feature('upperCase', 'upperCaseSmallCaps'),
385
+
386
+ init: feature('smartSwash', 'wordInitialSwashes'), // ??
387
+ fin2: feature('smartSwash', 'wordFinalSwashes'), // ??
388
+ medi: feature('smartSwash', 'nonFinalSwashes'), // ??
389
+ med2: feature('smartSwash', 'nonFinalSwashes'), // ??
390
+ fin3: feature('smartSwash', 'wordFinalSwashes'), // ??
391
+ fina: feature('smartSwash', 'wordFinalSwashes'), // ??
392
+
393
+ pkna: feature('kanaSpacing', 'proportionalKana'),
394
+ half: feature('textSpacing', 'halfWidthText'), // also HalfWidthCJKRoman, HalfWidthIdeographs?
395
+ halt: feature('textSpacing', 'altHalfWidthText'),
396
+
397
+ hkna: feature('alternateKana', 'alternateHorizKana'),
398
+ vkna: feature('alternateKana', 'alternateVertKana'),
399
+ // hngl: feature 'transliteration', 'hanjaToHangulSelector' # deprecated
400
+
401
+ ital: feature('italicCJKRoman', 'CJKItalicRoman'),
402
+ lnum: feature('numberCase', 'upperCaseNumbers'),
403
+ onum: feature('numberCase', 'lowerCaseNumbers'),
404
+ mgrk: feature('mathematicalExtras', 'mathematicalGreek'),
405
+
406
+ // nalt: not enough info. what type of annotation?
407
+ // ornm: ditto, which ornament style?
408
+
409
+ calt: feature('contextualAlternates', 'contextualAlternates'), // or more?
410
+ vrt2: feature('verticalSubstitution', 'substituteVerticalForms'), // oh... below?
411
+ vert: feature('verticalSubstitution', 'substituteVerticalForms'),
412
+ tnum: feature('numberSpacing', 'monospacedNumbers'),
413
+ pnum: feature('numberSpacing', 'proportionalNumbers'),
414
+ sups: feature('verticalPosition', 'superiors'),
415
+ subs: feature('verticalPosition', 'inferiors'),
416
+ ordn: feature('verticalPosition', 'ordinals'),
417
+ pwid: feature('textSpacing', 'proportionalText'),
418
+ hwid: feature('textSpacing', 'halfWidthText'),
419
+ qwid: feature('textSpacing', 'quarterWidthText'), // also QuarterWidthNumbers?
420
+ twid: feature('textSpacing', 'thirdWidthText'), // also ThirdWidthNumbers?
421
+ fwid: feature('textSpacing', 'proportionalText'), //??
422
+ palt: feature('textSpacing', 'altProportionalText'),
423
+ trad: feature('characterShape', 'traditionalCharacters'),
424
+ smpl: feature('characterShape', 'simplifiedCharacters'),
425
+ jp78: feature('characterShape', 'JIS1978Characters'),
426
+ jp83: feature('characterShape', 'JIS1983Characters'),
427
+ jp90: feature('characterShape', 'JIS1990Characters'),
428
+ jp04: feature('characterShape', 'JIS2004Characters'),
429
+ expt: feature('characterShape', 'expertCharacters'),
430
+ hojo: feature('characterShape', 'hojoCharacters'),
431
+ nlck: feature('characterShape', 'NLCCharacters'),
432
+ tnam: feature('characterShape', 'traditionalNamesCharacters'),
433
+ ruby: feature('rubyKana', 'rubyKana'),
434
+ titl: feature('styleOptions', 'titlingCaps'),
435
+ zero: feature('typographicExtras', 'slashedZero'),
436
+
437
+ ss01: feature('stylisticAlternatives', 'stylisticAltOne'),
438
+ ss02: feature('stylisticAlternatives', 'stylisticAltTwo'),
439
+ ss03: feature('stylisticAlternatives', 'stylisticAltThree'),
440
+ ss04: feature('stylisticAlternatives', 'stylisticAltFour'),
441
+ ss05: feature('stylisticAlternatives', 'stylisticAltFive'),
442
+ ss06: feature('stylisticAlternatives', 'stylisticAltSix'),
443
+ ss07: feature('stylisticAlternatives', 'stylisticAltSeven'),
444
+ ss08: feature('stylisticAlternatives', 'stylisticAltEight'),
445
+ ss09: feature('stylisticAlternatives', 'stylisticAltNine'),
446
+ ss10: feature('stylisticAlternatives', 'stylisticAltTen'),
447
+ ss11: feature('stylisticAlternatives', 'stylisticAltEleven'),
448
+ ss12: feature('stylisticAlternatives', 'stylisticAltTwelve'),
449
+ ss13: feature('stylisticAlternatives', 'stylisticAltThirteen'),
450
+ ss14: feature('stylisticAlternatives', 'stylisticAltFourteen'),
451
+ ss15: feature('stylisticAlternatives', 'stylisticAltFifteen'),
452
+ ss16: feature('stylisticAlternatives', 'stylisticAltSixteen'),
453
+ ss17: feature('stylisticAlternatives', 'stylisticAltSeventeen'),
454
+ ss18: feature('stylisticAlternatives', 'stylisticAltEighteen'),
455
+ ss19: feature('stylisticAlternatives', 'stylisticAltNineteen'),
456
+ ss20: feature('stylisticAlternatives', 'stylisticAltTwenty')
457
+ };
458
+
459
+ // salt: feature 'stylisticAlternatives', 'stylisticAltOne' # hmm, which one to choose
460
+
461
+ // Add cv01-cv99 features
462
+ for (let i = 1; i <= 99; i++) {
463
+ OTMapping[`cv${`00${i}`.slice(-2)}`] = [features.characterAlternatives.code, i];
464
+ }
465
+
466
+ // create inverse mapping
467
+ let AATMapping = {};
468
+ for (let ot in OTMapping) {
469
+ let aat = OTMapping[ot];
470
+ if (AATMapping[aat[0]] == null) {
471
+ AATMapping[aat[0]] = {};
472
+ }
473
+
474
+ AATMapping[aat[0]][aat[1]] = ot;
475
+ }
476
+
477
+ // Maps an array of OpenType features to AAT features
478
+ // in the form of {featureType:{featureSetting:true}}
479
+ export function mapOTToAAT(features) {
480
+ let res = {};
481
+ for (let k in features) {
482
+ let r;
483
+ if ((r = OTMapping[k])) {
484
+ if (res[r[0]] == null) {
485
+ res[r[0]] = {};
486
+ }
487
+
488
+ res[r[0]][r[1]] = features[k];
489
+ }
490
+ }
491
+
492
+ return res;
493
+ }
494
+
495
+ // Maps strings in a [featureType, featureSetting]
496
+ // to their equivalent number codes
497
+ function mapFeatureStrings(f) {
498
+ let [type, setting] = f;
499
+ let typeCode;
500
+ if (isNaN(type)) {
501
+ typeCode = features[type] && features[type].code;
502
+ } else {
503
+ typeCode = type;
504
+ }
505
+
506
+ let settingCode;
507
+ if (isNaN(setting)) {
508
+ settingCode = features[type] && features[type][setting];
509
+ } else {
510
+ settingCode = setting;
511
+ }
512
+
513
+ return [typeCode, settingCode];
514
+ }
515
+
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
520
+ export function mapAATToOT(features) {
521
+ let res = {};
522
+ if (Array.isArray(features)) {
523
+ for (let k = 0; k < features.length; k++) {
524
+ let r;
525
+ let f = mapFeatureStrings(features[k]);
526
+ if ((r = AATMapping[f[0]] && AATMapping[f[0]][f[1]])) {
527
+ res[r] = true;
528
+ }
529
+ }
530
+
531
+ } else if (typeof features === 'object') {
532
+ for (let type in features) {
533
+ let feature = features[type];
534
+ for (let setting in feature) {
535
+ let r;
536
+ let f = mapFeatureStrings([type, setting]);
537
+ if (feature[setting] && (r = AATMapping[f[0]] && AATMapping[f[0]][f[1]])) {
538
+ res[r] = true;
539
+ }
540
+ }
541
+ }
542
+ }
543
+
544
+ return Object.keys(res);
545
+ }
@@ -0,0 +1,48 @@
1
+ import * as AATFeatureMap from './AATFeatureMap';
2
+ import AATMorxProcessor from './AATMorxProcessor';
3
+
4
+ export default class AATLayoutEngine {
5
+ constructor(font) {
6
+ this.font = font;
7
+ this.morxProcessor = new AATMorxProcessor(font);
8
+ this.fallbackPosition = false;
9
+ }
10
+
11
+ substitute(glyphRun) {
12
+ // AAT expects the glyphs to be in visual order prior to morx processing,
13
+ // so reverse the glyphs if the script is right-to-left.
14
+ if (glyphRun.direction === 'rtl') {
15
+ glyphRun.glyphs.reverse();
16
+ }
17
+
18
+ this.morxProcessor.process(glyphRun.glyphs, AATFeatureMap.mapOTToAAT(glyphRun.features));
19
+ }
20
+
21
+ getAvailableFeatures(_script, _language) {
22
+ return AATFeatureMap.mapAATToOT(this.morxProcessor.getSupportedFeatures());
23
+ }
24
+
25
+ stringsForGlyph(gid) {
26
+ let glyphStrings = this.morxProcessor.generateInputs(gid);
27
+ let result = new Set;
28
+
29
+ for (let glyphs of glyphStrings) {
30
+ this._addStrings(glyphs, 0, result, '');
31
+ }
32
+
33
+ return result;
34
+ }
35
+
36
+ _addStrings(glyphs, index, strings, string) {
37
+ let codePoints = this.font._cmapProcessor.codePointsForGlyph(glyphs[index]);
38
+
39
+ for (let codePoint of codePoints) {
40
+ let s = string + String.fromCodePoint(codePoint);
41
+ if (index < glyphs.length - 1) {
42
+ this._addStrings(glyphs, index + 1, strings, s);
43
+ } else {
44
+ strings.add(s);
45
+ }
46
+ }
47
+ }
48
+ }
@@ -0,0 +1,125 @@
1
+ import {cache} from '../decorators';
2
+ import {range} from '../utils';
3
+
4
+ export default class AATLookupTable {
5
+ constructor(table) {
6
+ this.table = table;
7
+ }
8
+
9
+ lookup(glyph) {
10
+ switch (this.table.version) {
11
+ case 0: // simple array format
12
+ return this.table.values.getItem(glyph);
13
+
14
+ case 2: // segment format
15
+ case 4: {
16
+ let min = 0;
17
+ let max = this.table.binarySearchHeader.nUnits - 1;
18
+
19
+ while (min <= max) {
20
+ let mid = (min + max) >> 1;
21
+ let seg = this.table.segments[mid];
22
+
23
+ // special end of search value
24
+ if (seg.firstGlyph === 0xffff) {
25
+ return null;
26
+ }
27
+
28
+ if (glyph < seg.firstGlyph) {
29
+ max = mid - 1;
30
+ } else if (glyph > seg.lastGlyph) {
31
+ min = mid + 1;
32
+ } else {
33
+ if (this.table.version === 2) {
34
+ return seg.value;
35
+ } else {
36
+ return seg.values[glyph - seg.firstGlyph];
37
+ }
38
+ }
39
+ }
40
+
41
+ return null;
42
+ }
43
+
44
+ case 6: { // lookup single
45
+ let min = 0;
46
+ let max = this.table.binarySearchHeader.nUnits - 1;
47
+
48
+ while (min <= max) {
49
+ let mid = (min + max) >> 1;
50
+ let seg = this.table.segments[mid];
51
+
52
+ // special end of search value
53
+ if (seg.glyph === 0xffff) {
54
+ return null;
55
+ }
56
+
57
+ if (glyph < seg.glyph) {
58
+ max = mid - 1;
59
+ } else if (glyph > seg.glyph) {
60
+ min = mid + 1;
61
+ } else {
62
+ return seg.value;
63
+ }
64
+ }
65
+
66
+ return null;
67
+ }
68
+
69
+ case 8: // lookup trimmed
70
+ return this.table.values[glyph - this.table.firstGlyph];
71
+
72
+ default:
73
+ throw new Error(`Unknown lookup table format: ${this.table.version}`);
74
+ }
75
+ }
76
+
77
+ @cache
78
+ glyphsForValue(classValue) {
79
+ let res = [];
80
+
81
+ switch (this.table.version) {
82
+ case 2: // segment format
83
+ case 4: {
84
+ for (let segment of this.table.segments) {
85
+ if ((this.table.version === 2 && segment.value === classValue)) {
86
+ res.push(...range(segment.firstGlyph, segment.lastGlyph + 1));
87
+ } else {
88
+ for (let index = 0; index < segment.values.length; index++) {
89
+ if (segment.values[index] === classValue) {
90
+ res.push(segment.firstGlyph + index);
91
+ }
92
+ }
93
+ }
94
+ }
95
+
96
+ break;
97
+ }
98
+
99
+ case 6: { // lookup single
100
+ for (let segment of this.table.segments) {
101
+ if (segment.value === classValue) {
102
+ res.push(segment.glyph);
103
+ }
104
+ }
105
+
106
+ break;
107
+ }
108
+
109
+ case 8: { // lookup trimmed
110
+ for (let i = 0; i < this.table.values.length; i++) {
111
+ if (this.table.values[i] === classValue) {
112
+ res.push(this.table.firstGlyph + i);
113
+ }
114
+ }
115
+
116
+ break;
117
+ }
118
+
119
+ default:
120
+ throw new Error(`Unknown lookup table format: ${this.table.version}`);
121
+ }
122
+
123
+ return res;
124
+ }
125
+ }