font-ott.lua /size: 35 Kb    last modification: 2023-12-21 09:44
1if not modules then modules = { } end modules ["font-ott"] = {
2    version   = 1.001,
3    comment   = "companion to font-ini.mkiv",
4    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
5    copyright = "PRAGMA ADE / ConTeXt Development Team",
6    license   = "see context related readme files",
7 -- dataonly  = true,
8}
9
10local type, next, tonumber, tostring, rawget, rawset = type, next, tonumber, tostring, rawget, rawset
11local gsub, lower, format, match, gmatch, find = string.gsub, string.lower, string.format, string.match, string.gmatch, string.find
12local sequenced = table.sequenced
13local is_boolean = string.is_boolean
14
15local setmetatableindex    = table.setmetatableindex
16local setmetatablenewindex = table.setmetatablenewindex
17local allocate             = utilities.storage.allocate
18
19local fonts                = fonts
20local otf                  = fonts.handlers.otf
21local otffeatures          = otf.features
22
23local tables               = otf.tables or { }
24otf.tables                 = tables
25
26local statistics           = otf.statistics or { }
27otf.statistics             = statistics
28
29local scripts = allocate {
30    ["adlm"] = "adlam",
31    ["aghb"] = "caucasian albanian",
32    ["ahom"] = "ahom",
33    ["arab"] = "arabic",
34    ["armi"] = "imperial aramaic",
35    ["armn"] = "armenian",
36    ["avst"] = "avestan",
37    ["bali"] = "balinese",
38    ["bamu"] = "bamum",
39    ["bass"] = "bassa vah",
40    ["batk"] = "batak",
41    ["beng"] = "bengali",
42    ["bhks"] = "bhaiksuki",
43    ["bng2"] = "bengali variant 2",
44    ["bopo"] = "bopomofo",
45    ["brah"] = "brahmi",
46    ["brai"] = "braille",
47    ["bugi"] = "buginese",
48    ["buhd"] = "buhid",
49    ["byzm"] = "byzantine music",
50    ["cakm"] = "chakma",
51    ["cans"] = "canadian syllabics",
52    ["cari"] = "carian",
53    ["cham"] = "cham",
54    ["cher"] = "cherokee",
55    ["chrs"] = "chorasmian",
56    ["copt"] = "coptic",
57    ["cpmn"] = "cypro-minoan",
58    ["cprt"] = "cypriot syllabary",
59    ["cyrl"] = "cyrillic",
60    ["dev2"] = "devanagari variant 2",
61    ["deva"] = "devanagari",
62    ["diak"] = "dives akuru",
63    ["dogr"] = "dogra",
64    ["dsrt"] = "deseret",
65    ["dupl"] = "duployan",
66    ["egyp"] = "egyptian heiroglyphs",
67    ["elba"] = "elbasan",
68    ["elym"] = "elymaic",
69    ["ethi"] = "ethiopic",
70    ["geor"] = "georgian",
71    ["gjr2"] = "gujarati variant 2",
72    ["glag"] = "glagolitic",
73    ["gong"] = "gunjala gondi",
74    ["gonm"] = "masaram gondi",
75    ["goth"] = "gothic",
76    ["gran"] = "grantha",
77    ["grek"] = "greek",
78    ["gujr"] = "gujarati",
79    ["gur2"] = "gurmukhi variant 2",
80    ["guru"] = "gurmukhi",
81    ["hang"] = "hangul",
82    ["hani"] = "cjk ideographic",
83    ["hano"] = "hanunoo",
84    ["hatr"] = "hatran",
85    ["hebr"] = "hebrew",
86    ["hluw"] = "anatolian hieroglyphs",
87    ["hmng"] = "pahawh hmong",
88    ["hmnp"] = "nyiakeng puachue hmong",
89    ["hung"] = "old hungarian",
90    ["ital"] = "old italic",
91    ["jamo"] = "hangul jamo",
92    ["java"] = "javanese",
93    ["kali"] = "kayah li",
94    ["kana"] = "hiragana and katakana",
95    ["khar"] = "kharosthi",
96    ["khmr"] = "khmer",
97    ["khoj"] = "khojki",
98    ["kits"] = "khitan small script",
99    ["knd2"] = "kannada variant 2",
100    ["knda"] = "kannada",
101    ["kthi"] = "kaithi",
102    ["lana"] = "tai tham",
103    ["lao" ] = "lao",
104    ["latn"] = "latin",
105    ["lepc"] = "lepcha",
106    ["limb"] = "limbu",
107    ["lina"] = "linear a",
108    ["linb"] = "linear b",
109    ["lisu"] = "lisu",
110    ["lyci"] = "lycian",
111    ["lydi"] = "lydian",
112    ["mahj"] = "mahajani",
113    ["maka"] = "makasar",
114    ["mand"] = "mandaic and mandaean",
115    ["mani"] = "manichaean",
116    ["marc"] = "marchen",
117    ["math"] = "mathematical alphanumeric symbols",
118    ["medf"] = "medefaidrin",
119    ["mend"] = "mende kikakui",
120    ["merc"] = "meroitic cursive",
121    ["mero"] = "meroitic hieroglyphs",
122    ["mlm2"] = "malayalam variant 2",
123    ["mlym"] = "malayalam",
124    ["modi"] = "modi",
125    ["mong"] = "mongolian",
126    ["mroo"] = "mro",
127    ["mtei"] = "meitei Mayek",
128    ["mult"] = "multani",
129    ["musc"] = "musical symbols",
130    ["mym2"] = "myanmar variant 2",
131    ["mymr"] = "myanmar",
132    ["nand"] = "nandinagari",
133    ["narb"] = "old north arabian",
134    ["nbat"] = "nabataean",
135    ["newa"] = "newa",
136    ["nko" ] = 'n"ko',
137    ["nshu"] = "nüshu",
138    ["ogam"] = "ogham",
139    ["olck"] = "ol chiki",
140    ["orkh"] = "old turkic and orkhon runic",
141    ["ory2"] = "odia variant 2",
142    ["orya"] = "odia",
143    ["osge"] = "osage",
144    ["osma"] = "osmanya",
145    ["ougr"] = "old uyghur",
146    ["palm"] = "palmyrene",
147    ["pauc"] = "pau cin hau",
148    ["perm"] = "old permic",
149    ["phag"] = "phags-pa",
150    ["phli"] = "inscriptional pahlavi",
151    ["phlp"] = "psalter pahlavi",
152    ["phnx"] = "phoenician",
153    ["plrd"] = "miao",
154    ["prti"] = "inscriptional parthian",
155    ["rjng"] = "rejang",
156    ["rohg"] = "hanifi rohingya",
157    ["runr"] = "runic",
158    ["samr"] = "samaritan",
159    ["sarb"] = "old south arabian",
160    ["saur"] = "saurashtra",
161    ["sgnw"] = "sign writing",
162    ["shaw"] = "shavian",
163    ["shrd"] = "sharada",
164    ["sidd"] = "siddham",
165    ["sind"] = "khudawadi",
166    ["sinh"] = "sinhala",
167    ["sogd"] = "sogdian",
168    ["sogo"] = "old sogdian",
169    ["sora"] = "sora sompeng",
170    ["soyo"] = "soyombo",
171    ["sund"] = "sundanese",
172    ["sylo"] = "syloti nagri",
173    ["syrc"] = "syriac",
174    ["tagb"] = "tagbanwa",
175    ["takr"] = "takri",
176    ["tale"] = "tai le",
177    ["talu"] = "new tai lue",
178    ["taml"] = "tamil",
179    ["tang"] = "tangut",
180    ["tavt"] = "tai viet",
181    ["tel2"] = "telugu variant 2",
182    ["telu"] = "telugu",
183    ["tfng"] = "tifinagh",
184    ["tglg"] = "tagalog",
185    ["thaa"] = "thaana",
186    ["thai"] = "thai",
187    ["tibt"] = "tibetan",
188    ["tirh"] = "tirhuta",
189    ["tnsa"] = "tangsa",
190    ["tml2"] = "tamil variant 2",
191    ["toto"] = "toto",
192    ["ugar"] = "ugaritic cuneiform",
193    ["vai" ] = "vai",
194    ["wara"] = "warang citi",
195    ["wcho"] = "wancho",
196    ["xpeo"] = "old persian cuneiform",
197    ["xsux"] = "sumero-akkadian cuneiform",
198    ["yezi"] = "yezidi",
199    ["yi"  ] = "yi",
200    ["zanb"] = "zanabazar square",
201}
202
203local languages = allocate {
204    ["aba" ] = "abaza",
205    ["abk" ] = "abkhazian",
206    ["ach" ] = "acholi",
207    ["acr" ] = "achi",
208    ["ady" ] = "adyghe",
209    ["afk" ] = "afrikaans",
210    ["afr" ] = "afar",
211    ["agw" ] = "agaw",
212    ["aio" ] = "aiton",
213    ["aka" ] = "akan",
214    ["akb" ] = "batak angkola",
215    ["als" ] = "alsatian",
216    ["alt" ] = "altai",
217    ["amh" ] = "amharic",
218    ["ang" ] = "anglo-saxon",
219    ["apph"] = "phonetic transcription—americanist conventions",
220    ["ara" ] = "arabic",
221    ["arg" ] = "aragonese",
222    ["ari" ] = "aari",
223    ["ark" ] = "rakhine",
224    ["asm" ] = "assamese",
225    ["ast" ] = "asturian",
226    ["ath" ] = "athapaskan",
227    ["avn" ] = "avatime",
228    ["avr" ] = "avar",
229    ["awa" ] = "awadhi",
230    ["aym" ] = "aymara",
231    ["azb" ] = "torki",
232    ["aze" ] = "azerbaijani",
233    ["bad" ] = "badaga",
234    ["bad0"] = "banda",
235    ["bag" ] = "baghelkhandi",
236    ["bal" ] = "balkar",
237    ["ban" ] = "balinese",
238    ["bar" ] = "bavarian",
239    ["bau" ] = "baulé",
240    ["bbc" ] = "batak toba",
241    ["bbr" ] = "berber",
242    ["bch" ] = "bench",
243    ["bcr" ] = "bible cree",
244    ["bdy" ] = "bandjalang",
245    ["bel" ] = "belarussian",
246    ["bem" ] = "bemba",
247    ["ben" ] = "bengali",
248    ["bgc" ] = "haryanvi",
249    ["bgq" ] = "bagri",
250    ["bgr" ] = "bulgarian",
251    ["bhi" ] = "bhili",
252    ["bho" ] = "bhojpuri",
253    ["bik" ] = "bikol",
254    ["bil" ] = "bilen",
255    ["bis" ] = "bislama",
256    ["bjj" ] = "kanauji",
257    ["bkf" ] = "blackfoot",
258    ["bli" ] = "baluchi",
259    ["blk" ] = "pa'o karen",
260    ["bln" ] = "balante",
261    ["blt" ] = "balti",
262    ["bmb" ] = "bambara (bamanankan)",
263    ["bml" ] = "bamileke",
264    ["bos" ] = "bosnian",
265    ["bpy" ] = "bishnupriya manipuri",
266    ["bre" ] = "breton",
267    ["brh" ] = "brahui",
268    ["bri" ] = "braj bhasha",
269    ["brm" ] = "burmese",
270    ["brx" ] = "bodo",
271    ["bsh" ] = "bashkir",
272    ["bsk" ] = "burushaski",
273    ["bta" ] = "batak alas kluet",
274    ["btd" ] = "batak dairi (pakpak)",
275    ["bti" ] = "beti",
276    ["btm" ] = "batak mandailing",
277    ["bts" ] = "batak simalungun",
278    ["btx" ] = "batak karo",
279    ["bug" ] = "bugis",
280    ["byv" ] = "medumba",
281    ["cak" ] = "kaqchikel",
282    ["cat" ] = "catalan",
283    ["cbk" ] = "zamboanga chavacano",
284    ["cchn"] = "chinantec",
285    ["ceb" ] = "cebuano",
286    ["cgg" ] = "chiga",
287    ["cha" ] = "chamorro",
288    ["che" ] = "chechen",
289    ["chg" ] = "chaha gurage",
290    ["chh" ] = "chattisgarhi",
291    ["chi" ] = "chichewa (chewa, nyanja)",
292    ["chk" ] = "chukchi",
293    ["chk0"] = "chuukese",
294    ["cho" ] = "choctaw",
295    ["chp" ] = "chipewyan",
296    ["chr" ] = "cherokee",
297    ["chu" ] = "chuvash",
298    ["chy" ] = "cheyenne",
299    ["cja" ] = "western cham",
300    ["cjm" ] = "eastern cham",
301    ["cmr" ] = "comorian",
302    ["cop" ] = "coptic",
303    ["cor" ] = "cornish",
304    ["cos" ] = "corsican",
305    ["cpp" ] = "creoles",
306    ["cre" ] = "cree",
307    ["crr" ] = "carrier",
308    ["crt" ] = "crimean tatar",
309    ["csb" ] = "kashubian",
310    ["csl" ] = "church slavonic",
311    ["csy" ] = "czech",
312    ["ctg" ] = "chittagonian",
313    ["ctt" ] = "wayanad chetti",
314    ["cuk" ] = "san blas kuna",
315    ["dag" ] = "dagbani",
316    ["dan" ] = "danish",
317    ["dar" ] = "dargwa",
318    ["dax" ] = "dayi",
319    ["dcr" ] = "woods cree",
320    ["deu" ] = "german",
321    ["dgo" ] = "dogri (individual language)",
322    ["dgr" ] = "dogri (macro language)",
323    ["dhg" ] = "dhangu",
324    ["dhv" ] = "divehi (dhivehi, maldivian)",
325    ["diq" ] = "dimli",
326    ["div" ] = "divehi (dhivehi, maldivian)",
327    ["djr" ] = "zarma",
328    ["djr0"] = "djambarrpuyngu",
329    ["dng" ] = "dangme",
330    ["dnj" ] = "dan",
331    ["dnk" ] = "dinka",
332    ["dri" ] = "dari",
333    ["duj" ] = "dhuwal",
334    ["dun" ] = "dungan",
335    ["dzn" ] = "dzongkha",
336    ["ebi" ] = "ebira",
337    ["ecr" ] = "eastern cree",
338    ["edo" ] = "edo",
339    ["efi" ] = "efik",
340    ["ell" ] = "greek",
341    ["emk" ] = "eastern maninkakan",
342    ["eng" ] = "english",
343    ["erz" ] = "erzya",
344    ["esp" ] = "spanish",
345    ["esu" ] = "central yupik",
346    ["eti" ] = "estonian",
347    ["euq" ] = "basque",
348    ["evk" ] = "evenki",
349    ["evn" ] = "even",
350    ["ewe" ] = "ewe",
351    ["fan" ] = "french antillean",
352    ["fan0"] = " fang",
353    ["far" ] = "persian",
354    ["fat" ] = "fanti",
355    ["fin" ] = "finnish",
356    ["fji" ] = "fijian",
357    ["fle" ] = "dutch (flemish)",
358    ["fmp" ] = "fe’fe’",
359    ["fne" ] = "forest nenets",
360    ["fon" ] = "fon",
361    ["fos" ] = "faroese",
362    ["fra" ] = "french",
363    ["frc" ] = "cajun french",
364    ["fri" ] = "frisian",
365    ["frl" ] = "friulian",
366    ["frp" ] = "arpitan",
367    ["fta" ] = "futa",
368    ["ful" ] = "fulah",
369    ["fuv" ] = "nigerian fulfulde",
370    ["gad" ] = "ga",
371    ["gae" ] = "scottish gaelic (gaelic)",
372    ["gag" ] = "gagauz",
373    ["gal" ] = "galician",
374    ["gar" ] = "garshuni",
375    ["gaw" ] = "garhwali",
376    ["gez" ] = "ge'ez",
377    ["gih" ] = "githabul",
378    ["gil" ] = "gilyak",
379    ["gil0"] = "kiribati (gilbertese)",
380    ["gkp" ] = "kpelle (guinea)",
381    ["glk" ] = "gilaki",
382    ["gmz" ] = "gumuz",
383    ["gnn" ] = "gumatj",
384    ["gog" ] = "gogo",
385    ["gon" ] = "gondi",
386    ["grn" ] = "greenlandic",
387    ["gro" ] = "garo",
388    ["gua" ] = "guarani",
389    ["guc" ] = "wayuu",
390    ["guf" ] = "gupapuyngu",
391    ["guj" ] = "gujarati",
392    ["guz" ] = "gusii",
393    ["hai" ] = "haitian (haitian creole)",
394    ["hai0"] = "haida",
395    ["hal" ] = "halam",
396    ["har" ] = "harauti",
397    ["hau" ] = "hausa",
398    ["haw" ] = "hawaiian",
399    ["hay" ] = "haya",
400    ["haz" ] = "hazaragi",
401    ["hmz" ] = "hmong shuat",
402    ["hbn" ] = "hammer-banna",
403    ["hei" ] = "heiltsuk",
404    ["her" ] = "herero",
405    ["hil" ] = "hiligaynon",
406    ["hin" ] = "hindi",
407    ["hma" ] = "high mari",
408    ["hmn" ] = "hmong",
409    ["hmo" ] = "hiri motu",
410    ["hnd" ] = "hindko",
411    ["ho"  ] = "ho",
412    ["hri" ] = "harari",
413    ["hrv" ] = "croatian",
414    ["hun" ] = "hungarian",
415    ["hye" ] = "armenian",
416    ["hye0"] = "armenian east",
417    ["iba" ] = "iban",
418    ["ibb" ] = "ibibio",
419    ["ibo" ] = "igbo",
420    ["ido" ] = "ido",
421    ["ijo" ] = "ijo languages",
422    ["ile" ] = "interlingue",
423    ["ilo" ] = "ilokano",
424    ["ina" ] = "interlingua",
425    ["ind" ] = "indonesian",
426    ["ing" ] = "ingush",
427    ["inu" ] = "inuktitut",
428    ["inuk"] = "nunavik inuktitut",
429    ["ipk" ] = "inupiat",
430    ["ipph"] = "phonetic transcription—ipa conventions",
431    ["iri" ] = "irish",
432    ["irt" ] = "irish traditional",
433    ["uri" ] = "irula",
434    ["isl" ] = "icelandic",
435    ["ism" ] = "inari sami",
436    ["ita" ] = "italian",
437    ["iwr" ] = "hebrew",
438    ["jam" ] = "jamaican creole",
439    ["jan" ] = "japanese",
440    ["jav" ] = "javanese",
441    ["jbo" ] = "lojban",
442    ["jct" ] = "krymchak",
443    ["jii" ] = "yiddish",
444    ["jud" ] = "ladino",
445    ["jul" ] = "jula",
446    ["kab" ] = "kabardian",
447    ["kab0"] = "kabyle",
448    ["kac" ] = "kachchi",
449    ["kal" ] = "kalenjin",
450    ["kan" ] = "kannada",
451    ["kar" ] = "karachay",
452    ["kat" ] = "georgian",
453    ["kaw" ] = "kawi (old javanese)",
454    ["kaz" ] = "kazakh",
455    ["kde" ] = "makonde",
456    ["kea" ] = "kabuverdianu (crioulo)",
457    ["keb" ] = "kebena",
458    ["kek" ] = "kekchi",
459    ["kge" ] = "khutsuri georgian",
460    ["kha" ] = "khakass",
461    ["khk" ] = "khanty-kazim",
462    ["khm" ] = "khmer",
463    ["khs" ] = "khanty-shurishkar",
464    ["kht" ] = "khamti shan",
465    ["khv" ] = "khanty-vakhi",
466    ["khw" ] = "khowar",
467    ["kik" ] = "kikuyu (gikuyu)",
468    ["kir" ] = "kirghiz (kyrgyz)",
469    ["kis" ] = "kisii",
470    ["kiu" ] = "kirmanjki",
471    ["kjd" ] = "southern kiwai",
472    ["kjp" ] = "eastern pwo karen",
473    ["kjz" ] = "bumthangkha",
474    ["kkn" ] = "kokni",
475    ["klm" ] = "kalmyk",
476    ["kmb" ] = "kamba",
477    ["kmn" ] = "kumaoni",
478    ["kmo" ] = "komo",
479    ["kms" ] = "komso",
480    ["kmz" ] = "khorasani turkic",
481    ["knr" ] = "kanuri",
482    ["kod" ] = "kodagu",
483    ["koh" ] = "korean old hangul",
484    ["kok" ] = "konkani",
485    ["kom" ] = "komi",
486    ["kon" ] = "kikongo",
487    ["kon0"] = "kongo",
488    ["kop" ] = "komi-permyak",
489    ["kor" ] = "korean",
490    ["kos" ] = "kosraean",
491    ["koz" ] = "komi-zyrian",
492    ["kpl" ] = "kpelle",
493    ["kri" ] = "krio",
494    ["krk" ] = "karakalpak",
495    ["krl" ] = "karelian",
496    ["krm" ] = "karaim",
497    ["krn" ] = "karen",
498    ["krt" ] = "koorete",
499    ["ksh" ] = "kashmiri",
500    ["ksh0"] = "ripuarian",
501    ["ksi" ] = "khasi",
502    ["ksm" ] = "kildin sami",
503    ["ksw" ] = "s’gaw karen",
504    ["kua" ] = "kuanyama",
505    ["kui" ] = "kui",
506    ["kul" ] = "kulvi",
507    ["kum" ] = "kumyk",
508    ["kur" ] = "kurdish",
509    ["kuu" ] = "kurukh",
510    ["kuy" ] = "kuy",
511    ["kwk" ] = "kwakʼwala",
512    ["kyk" ] = "koryak",
513    ["kyu" ] = "western kayah",
514    ["lad" ] = "ladin",
515    ["lah" ] = "lahuli",
516    ["lak" ] = "lak",
517    ["lam" ] = "lambani",
518    ["lao" ] = "lao",
519    ["lat" ] = "latin",
520    ["laz" ] = "laz",
521    ["lcr" ] = "l-cree",
522    ["ldk" ] = "ladakhi",
523    ["lef" ] = "lelemi",
524    ["lez" ] = "lezgi",
525    ["lij" ] = "ligurian",
526    ["lim" ] = "limburgish",
527    ["lin" ] = "lingala",
528    ["lis" ] = "lisu",
529    ["ljp" ] = "lampung",
530    ["lki" ] = "laki",
531    ["lma" ] = "low mari",
532    ["lmb" ] = "limbu",
533    ["lmo" ] = "lombard",
534    ["lmw" ] = "lomwe",
535    ["lom" ] = "loma",
536    ["lpo" ] = "lipo",
537    ["lrc" ] = "luri",
538    ["lsb" ] = "lower sorbian",
539    ["lsm" ] = "lule sami",
540    ["lth" ] = "lithuanian",
541    ["ltz" ] = "luxembourgish",
542    ["lua" ] = "luba-lulua",
543    ["lub" ] = "luba-katanga",
544    ["lug" ] = "ganda",
545    ["luh" ] = "luyia",
546    ["luo" ] = "luo",
547    ["lvi" ] = "latvian",
548    ["mad" ] = "madura",
549    ["mag" ] = "magahi",
550    ["mah" ] = "marshallese",
551    ["maj" ] = "majang",
552    ["mak" ] = "makhuwa",
553    ["mal" ] = "malayalam",
554    ["mam" ] = "mam",
555    ["man" ] = "mansi",
556    ["map" ] = "mapudungun",
557    ["mar" ] = "marathi",
558    ["maw" ] = "marwari",
559    ["mbn" ] = "mbundu",
560    ["mbo" ] = "mbo",
561    ["mch" ] = "manchu",
562    ["mcr" ] = "moose cree",
563    ["mde" ] = "mende",
564    ["mdr" ] = "mandar",
565    ["men" ] = "me'en",
566    ["mer" ] = "meru",
567    ["mfa" ] = "pattani malay",
568    ["mfe" ] = "morisyen",
569    ["min" ] = "minangkabau",
570    ["miz" ] = "mizo",
571    ["mkd" ] = "macedonian",
572    ["mkr" ] = "makasar",
573    ["mkw" ] = "kituba",
574    ["mle" ] = "male",
575    ["mlg" ] = "malagasy",
576    ["mln" ] = "malinke",
577    ["mlr" ] = "malayalam reformed",
578    ["mly" ] = "malay",
579    ["mnd" ] = "mandinka",
580    ["mng" ] = "mongolian",
581    ["mni" ] = "manipuri",
582    ["mnk" ] = "maninka",
583    ["mnx" ] = "manx",
584    ["moh" ] = "mohawk",
585    ["mok" ] = "moksha",
586    ["mol" ] = "moldavian",
587    ["mon" ] = "mon",
588    ["mnw" ] = "thailand mon",
589    ["mor" ] = "moroccan",
590    ["mos" ] = "mossi",
591    ["mri" ] = "maori",
592    ["mth" ] = "maithili",
593    ["mts" ] = "maltese",
594    ["mun" ] = "mundari",
595    ["mus" ] = "muscogee",
596    ["mwl" ] = "mirandese",
597    ["mww" ] = "hmong daw",
598    ["myn" ] = "mayan",
599    ["mzn" ] = "mazanderani",
600    ["nag" ] = "naga-assamese",
601    ["nah" ] = "nahuatl",
602    ["nan" ] = "nanai",
603    ["nap" ] = "neapolitan",
604    ["nas" ] = "naskapi",
605    ["nau" ] = "nauruan",
606    ["nav" ] = "navajo",
607    ["ncr" ] = "n-cree",
608    ["ndb" ] = "ndebele",
609    ["ndc" ] = "ndau",
610    ["ndg" ] = "ndonga",
611    ["nds" ] = "low saxon",
612    ["nep" ] = "nepali",
613    ["new" ] = "newari",
614    ["nga" ] = "ngbaka",
615    ["ngr" ] = "nagari",
616    ["nhc" ] = "norway house cree",
617    ["nis" ] = "nisi",
618    ["niu" ] = "niuean",
619    ["nkl" ] = "nyankole",
620    ["nko" ] = "n'ko",
621    ["nld" ] = "dutch",
622    ["noe" ] = "nimadi",
623    ["nog" ] = "nogai",
624    ["nor" ] = "norwegian",
625    ["nov" ] = "novial",
626    ["nsm" ] = "northern sami",
627    ["nso" ] = "northern sotho",
628    ["nta" ] = "northern tai",
629    ["nto" ] = "esperanto",
630    ["nym" ] = "nyamwezi",
631    ["nyn" ] = "norwegian nynorsk",
632    ["nza" ] = "mbembe tigon",
633    ["oci" ] = "occitan",
634    ["ocr" ] = "oji-cree",
635    ["ojb" ] = "ojibway",
636    ["ori" ] = "odia",
637    ["oro" ] = "oromo",
638    ["oss" ] = "ossetian",
639    ["paa" ] = "palestinian aramaic",
640    ["pag" ] = "pangasinan",
641    ["pal" ] = "pali",
642    ["pam" ] = "pampangan",
643    ["pan" ] = "punjabi",
644    ["pap" ] = "palpa",
645    ["pap0"] = "papiamentu",
646    ["pas" ] = "pashto",
647    ["pau" ] = "palauan",
648    ["pcc" ] = "bouyei",
649    ["pcd" ] = "picard",
650    ["pdc" ] = "pennsylvania german",
651    ["pgr" ] = "polytonic greek",
652    ["phk" ] = "phake",
653    ["pih" ] = "norfolk",
654    ["pil" ] = "filipino",
655    ["plg" ] = "palaung",
656    ["plk" ] = "polish",
657    ["pms" ] = "piemontese",
658    ["pnb" ] = "western panjabi",
659    ["poh" ] = "pocomchi",
660    ["pon" ] = "pohnpeian",
661    ["pro" ] = "provencal",
662    ["ptg" ] = "portuguese",
663    ["pwo" ] = "western pwo karen",
664    ["qin" ] = "chin",
665    ["quc" ] = "k’iche’",
666    ["quh" ] = "quechua (bolivia)",
667    ["quz" ] = "quechua",
668    ["qvi" ] = "quechua (ecuador)",
669    ["qwh" ] = "quechua (peru)",
670    ["raj" ] = "rajasthani",
671    ["rar" ] = "rarotongan",
672    ["rbu" ] = "russian buriat",
673    ["rcr" ] = "r-cree",
674    ["rej" ] = "rejang",
675    ["rhg" ] = "rohingya",
676    ["ria" ] = "riang",
677    ["rif" ] = "tarifit",
678    ["rit" ] = "ritarungo",
679    ["rkw" ] = "arakwal",
680    ["rms" ] = "romansh",
681    ["rmy" ] = "vlax romani",
682    ["rom" ] = "romanian",
683    ["roy" ] = "romany",
684    ["rsy" ] = "rusyn",
685    ["rtm" ] = "rotuman",
686    ["rua" ] = "kinyarwanda",
687    ["run" ] = "rundi",
688    ["rup" ] = "aromanian",
689    ["rus" ] = "russian",
690    ["sad" ] = "sadri",
691    ["san" ] = "sanskrit",
692    ["sas" ] = "sasak",
693    ["sat" ] = "santali",
694    ["say" ] = "sayisi",
695    ["scn" ] = "sicilian",
696    ["sco" ] = "scots",
697    ["scs" ] = "north slavey",
698    ["sek" ] = "sekota",
699    ["sel" ] = "selkup",
700    ["sfm" ] = "small flowery miao",
701    ["sga" ] = "old irish",
702    ["sgo" ] = "sango",
703    ["sgs" ] = "samogitian",
704    ["shi" ] = "tachelhit",
705    ["shn" ] = "shan",
706    ["sib" ] = "sibe",
707    ["sid" ] = "sidamo",
708    ["sig" ] = "silte gurage",
709    ["sks" ] = "skolt sami",
710    ["sky" ] = "slovak",
711    ["sla" ] = "slavey",
712    ["slv" ] = "slovenian",
713    ["sml" ] = "somali",
714    ["smo" ] = "samoan",
715    ["sna" ] = "sena",
716    ["sna0"] = "shona",
717    ["snd" ] = "sindhi",
718    ["snh" ] = "sinhala (sinhalese)",
719    ["snk" ] = "soninke",
720    ["sog" ] = "sodo gurage",
721    ["sop" ] = "songe",
722    ["sot" ] = "southern sotho",
723    ["sqi" ] = "albanian",
724    ["srb" ] = "serbian",
725    ["srd" ] = "sardinian",
726    ["srk" ] = "saraiki",
727    ["srr" ] = "serer",
728    ["ssl" ] = "south slavey",
729    ["ssm" ] = "southern sami",
730    ["stq" ] = "saterland frisian",
731    ["suk" ] = "sukuma",
732    ["sun" ] = "sundanese",
733    ["sur" ] = "suri",
734    ["sva" ] = "svan",
735    ["sve" ] = "swedish",
736    ["swa" ] = "swadaya aramaic",
737    ["swk" ] = "swahili",
738    ["swz" ] = "swati",
739    ["sxt" ] = "sutu",
740    ["sxu" ] = "upper saxon",
741    ["syl" ] = "sylheti",
742    ["syr" ] = "syriac",
743    ["syre"] = "estrangela syriac",
744    ["syrj"] = "western syriac",
745    ["syrn"] = "eastern syriac",
746    ["szl" ] = "silesian",
747    ["tab" ] = "tabasaran",
748    ["taj" ] = "tajiki",
749    ["tam" ] = "tamil",
750    ["tat" ] = "tatar",
751    ["tcr" ] = "th-cree",
752    ["tdd" ] = "dehong dai",
753    ["tel" ] = "telugu",
754    ["tet" ] = "tetum",
755    ["tgl" ] = "tagalog",
756    ["tgn" ] = "tongan",
757    ["tgr" ] = "tigre",
758    ["tgy" ] = "tigrinya",
759    ["tha" ] = "thai",
760    ["tht" ] = "tahitian",
761    ["tib" ] = "tibetan",
762    ["tiv" ] = "tiv",
763    ["tj;" ] = "tai laing",
764    ["tkm" ] = "turkmen",
765    ["tli" ] = "tlingit",
766    ["tmh" ] = "tamashek",
767    ["tmn" ] = "temne",
768    ["tna" ] = "tswana",
769    ["tne" ] = "tundra nenets",
770    ["tng" ] = "tonga",
771    ["tod" ] = "todo",
772    ["tod0"] = "toma",
773    ["tpi" ] = "tok pisin",
774    ["trk" ] = "turkish",
775    ["tsg" ] = "tsonga",
776    ["tsj" ] = "tshangla",
777    ["tua" ] = "turoyo aramaic",
778    ["tul" ] = "tulu",
779    ["tum" ] = "tumbuka",
780    ["tuv" ] = "tuvin",
781    ["tvl" ] = "tuvalu",
782    ["twi" ] = "twi",
783    ["tyz" ] = "tày",
784    ["tzm" ] = "tamazight",
785    ["tzo" ] = "tzotzil",
786    ["udm" ] = "udmurt",
787    ["ukr" ] = "ukrainian",
788    ["umb" ] = "umbundu",
789    ["urd" ] = "urdu",
790    ["usb" ] = "upper sorbian",
791    ["uyg" ] = "uyghur",
792    ["uzb" ] = "uzbek",
793    ["vec" ] = "venetian",
794    ["ven" ] = "venda",
795    ["vit" ] = "vietnamese",
796    ["vol" ] = "volapük",
797    ["vro" ] = "võro",
798    ["wa"  ] = "wa",
799    ["wag" ] = "wagdi",
800    ["war" ] = "waray-waray",
801    ["wci" ] = "waci gbe",
802    ["wcr" ] = "west-cree",
803    ["wel" ] = "welsh",
804    ["wlf" ] = "wolof",
805    ["wln" ] = "walloon",
806    ["wtm" ] = "mewati",
807    ["xbd" ] = "lü",
808    ["xhs" ] = "xhosa",
809    ["xjb" ] = "minjangbal",
810    ["xkf" ] = "khengkha",
811    ["xog" ] = "soga",
812    ["xpe" ] = "kpelle (liberia)",
813    ["xub" ] = "bette kuruma",
814    ["xuj" ] = "jennu kuruma",
815    ["yak" ] = "sakha",
816    ["yao" ] = "yao",
817    ["yap" ] = "yapese",
818    ["yba" ] = "yoruba",
819    ["ycr" ] = "y-cree",
820    ["ygp" ] = "gepo",
821    ["yic" ] = "yi classic",
822    ["yim" ] = "yi modern",
823    ["yna" ] = "aluo",
824    ["ywq" ] = "wuding-luquan",
825    ["zea" ] = "zealandic",
826    ["zgh" ] = "standard morrocan tamazigh",
827    ["zha" ] = "zhuang",
828    ["zhh" ] = "chinese, hong kong sar",
829    ["zho" ] = "chinese traditional, macao",
830    ["zhp" ] = "chinese phonetic",
831    ["zhs" ] = "chinese simplified",
832    ["zht" ] = "chinese traditional",
833    ["znd" ] = "zande",
834    ["zul" ] = "zulu",
835    ["zza" ] = "zazaki",
836}
837
838local features = allocate {
839    ["aalt"] = "access all alternates",
840    ["abvf"] = "above-base forms",
841    ["abvm"] = "above-base mark positioning",
842    ["abvs"] = "above-base substitutions",
843    ["afrc"] = "alternative fractions",
844    ["akhn"] = "akhands",
845    ["blwf"] = "below-base forms",
846    ["blwm"] = "below-base mark positioning",
847    ["blws"] = "below-base substitutions",
848    ["c2pc"] = "petite capitals from capitals",
849    ["c2sc"] = "small capitals from capitals",
850    ["calt"] = "contextual alternates",
851    ["case"] = "case-sensitive forms",
852    ["ccmp"] = "glyph composition/decomposition",
853    ["cfar"] = "conjunct form after ro",
854    ["chws"] = "contextual half-width spacing",
855    ["cjct"] = "conjunct forms",
856    ["clig"] = "contextual ligatures",
857    ["cpct"] = "centered cjk punctuation",
858    ["cpsp"] = "capital spacing",
859    ["cswh"] = "contextual swash",
860    ["curs"] = "cursive positioning",
861    ["dflt"] = "default processing",
862    ["dist"] = "distances",
863    ["dlig"] = "discretionary ligatures",
864    ["dnom"] = "denominators",
865    ["dtls"] = "dotless forms",                    -- math
866    ["expt"] = "expert forms",
867    ["falt"] = "final glyph alternates",
868    ["fin2"] = "terminal forms #2",
869    ["fin3"] = "terminal forms #3",
870    ["fina"] = "terminal forms",
871    ["flac"] = "flattened accents over capitals",  -- math
872    ["frac"] = "fractions",
873    ["fwid"] = "full width",
874    ["half"] = "half forms",
875    ["haln"] = "halant forms",
876    ["halt"] = "alternate half width",
877    ["hist"] = "historical forms",
878    ["hkna"] = "horizontal kana alternates",
879    ["hlig"] = "historical ligatures",
880    ["hngl"] = "hangul",                           -- depricated
881    ["hojo"] = "hojo kanji forms",
882    ["hwid"] = "half width",
883    ["init"] = "initial forms",
884    ["isol"] = "isolated forms",
885    ["ital"] = "italics",
886    ["jalt"] = "justification alternatives",
887    ["jp04"] = "jis2004 forms",
888    ["jp78"] = "jis78 forms",
889    ["jp83"] = "jis83 forms",
890    ["jp90"] = "jis90 forms",
891    ["kern"] = "kerning",
892    ["lfbd"] = "left bounds",
893    ["liga"] = "standard ligatures",
894    ["ljmo"] = "leading jamo forms",
895    ["lnum"] = "lining figures",
896    ["locl"] = "localized forms",
897    ["ltra"] = "left-to-right alternates",
898    ["ltrm"] = "left-to-right mirrored forms",
899    ["mark"] = "mark positioning",
900    ["med2"] = "medial forms #2",
901    ["medi"] = "medial forms",
902    ["mgrk"] = "mathematical greek",
903    ["mkmk"] = "mark to mark positioning",
904    ["mset"] = "mark positioning via substitution",
905    ["nalt"] = "alternate annotation forms",
906    ["nlck"] = "nlc kanji forms",
907    ["nukt"] = "nukta forms",
908    ["numr"] = "numerators",
909    ["onum"] = "old style figures",
910    ["opbd"] = "optical bounds", -- funny, this is obsolete (too hard?) (and was recomended always true)
911    ["ordn"] = "ordinals",
912    ["ornm"] = "ornaments",
913    ["palt"] = "proportional alternate width",
914    ["pcap"] = "petite capitals",
915    ["pkna"] = "proportional kana",
916    ["pnum"] = "proportional figures",
917    ["pref"] = "pre-base forms",
918    ["pres"] = "pre-base substitutions",
919    ["pstf"] = "post-base forms",
920    ["psts"] = "post-base substitutions",
921    ["pwid"] = "proportional widths",
922    ["qwid"] = "quarter widths",
923    ["rand"] = "randomize",
924    ["rclt"] = "required contextual alternates",
925    ["rkrf"] = "rakar forms",
926    ["rlig"] = "required ligatures",
927    ["rphf"] = "reph form",
928    ["rtbd"] = "right bounds",
929    ["rtla"] = "right-to-left alternates",
930    ["rtlm"] = "right to left mirrored forms",
931    ["ruby"] = "ruby notation forms",
932    ["rvrn"] = "required variation alternates",
933    ["salt"] = "stylistic alternates",
934    ["sinf"] = "scientific inferiors",
935    ["size"] = "optical size", -- now stat table
936    ["smcp"] = "small capitals",
937    ["smpl"] = "simplified forms",
938 -- ["ss01"] = "stylistic set 1",
939 -- ["ss02"] = "stylistic set 2",
940 -- ["ss03"] = "stylistic set 3",
941 -- ["ss04"] = "stylistic set 4",
942 -- ["ss05"] = "stylistic set 5",
943 -- ["ss06"] = "stylistic set 6",
944 -- ["ss07"] = "stylistic set 7",
945 -- ["ss08"] = "stylistic set 8",
946 -- ["ss09"] = "stylistic set 9",
947 -- ["ss10"] = "stylistic set 10",
948 -- ["ss11"] = "stylistic set 11",
949 -- ["ss12"] = "stylistic set 12",
950 -- ["ss13"] = "stylistic set 13",
951 -- ["ss14"] = "stylistic set 14",
952 -- ["ss15"] = "stylistic set 15",
953 -- ["ss16"] = "stylistic set 16",
954 -- ["ss17"] = "stylistic set 17",
955 -- ["ss18"] = "stylistic set 18",
956 -- ["ss19"] = "stylistic set 19",
957 -- ["ss20"] = "stylistic set 20",
958    ["ssty"] = "script style", -- math
959    ["stch"] = "stretching glyph decomposition",
960    ["subs"] = "subscript",
961    ["sups"] = "superscript",
962    ["swsh"] = "swash",
963    ["titl"] = "titling",
964    ["tjmo"] = "trailing jamo forms",
965    ["tnam"] = "traditional name forms",
966    ["tnum"] = "tabular figures",
967    ["trad"] = "traditional forms",
968    ["twid"] = "third widths",
969    ["unic"] = "unicase",
970    ["valt"] = "alternate vertical metrics",
971    ["vatu"] = "vattu variants",
972    ["vchw"] = "vertical contextual half-width spacing",
973    ["vert"] = "vertical writing",
974    ["vhal"] = "alternate vertical half metrics",
975    ["vjmo"] = "vowel jamo forms",
976    ["vkna"] = "vertical kana alternates",
977    ["vkrn"] = "vertical kerning",
978    ["vpal"] = "proportional alternate vertical metrics",
979    ["vrtr"] = "vertical alternates for rotation",
980    ["vrt2"] = "vertical rotation",
981    ["zero"] = "slashed zero",
982
983    ["trep"] = "traditional tex replacements",
984    ["tlig"] = "traditional tex ligatures",
985
986    ["ss.."] = "stylistic set ..",
987    ["cv.."] = "character variant ..",
988    ["js.."] = "justification ..",
989
990    ["dv.."] = "devanagari ..", -- for internal use
991    ["ml.."] = "malayalam ..",  -- for internal use
992
993}
994
995local baselines = allocate {
996    ["hang"] = "hanging baseline",
997    ["icfb"] = "ideographic character face bottom edge baseline",
998    ["icft"] = "ideographic character face tope edige baseline",
999    ["ideo"] = "ideographic em-box bottom edge baseline",
1000    ["idtp"] = "ideographic em-box top edge baseline",
1001    ["math"] = "mathematical centered baseline",
1002    ["romn"] = "roman baseline"
1003}
1004
1005tables.scripts   = scripts
1006tables.languages = languages
1007tables.features  = features
1008tables.baselines = baselines
1009
1010local acceptscripts   = true  directives.register("otf.acceptscripts",   function(v) acceptscripts   = v end)
1011local acceptlanguages = true  directives.register("otf.acceptlanguages", function(v) acceptlanguages = v end)
1012
1013local report_checks   = logs.reporter("fonts","checks")
1014
1015-- hm, we overload the metatables
1016
1017if otffeatures.features then
1018    for k, v in next, otffeatures.features do
1019        features[k] = v
1020    end
1021    otffeatures.features = features
1022end
1023
1024local function swapped(h)
1025    local r = { }
1026    for k, v in next, h do
1027        r[gsub(v,"[^a-z0-9]","")] = k -- is already lower
1028    end
1029    return r
1030end
1031
1032local verbosescripts   = allocate(swapped(scripts  ))
1033local verboselanguages = allocate(swapped(languages))
1034local verbosefeatures  = allocate(swapped(features ))
1035local verbosebaselines = allocate(swapped(baselines))
1036
1037-- lets forget about trailing spaces
1038
1039local function resolve(t,k)
1040    if k then
1041        k = gsub(lower(k),"[^a-z0-9]","")
1042        local v = rawget(t,k)
1043        if v then
1044            return v
1045        end
1046    end
1047end
1048
1049setmetatableindex(verbosescripts,   resolve)
1050setmetatableindex(verboselanguages, resolve)
1051setmetatableindex(verbosefeatures,  resolve)
1052setmetatableindex(verbosebaselines, resolve)
1053
1054-- We could optimize the next lookups by using an extra metatable and storing
1055-- already found values but in practice there are not that many lookups so
1056-- it's never a bottleneck.
1057
1058setmetatableindex(scripts, function(t,k)
1059    if k then
1060        k = lower(k)
1061        if k == "dflt" then
1062            return k
1063        end
1064        local v = rawget(t,k)
1065        if v then
1066            return v
1067        end
1068        k = gsub(k," ","")
1069        v = rawget(t,v)
1070        if v then
1071            return v
1072        elseif acceptscripts then
1073            report_checks("registering extra script %a",k)
1074            rawset(t,k,k)
1075            return k
1076        end
1077    end
1078    return "dflt"
1079end)
1080
1081setmetatableindex(languages, function(t,k)
1082    if k then
1083        k = lower(k)
1084        if k == "dflt" then
1085            return k
1086        end
1087        local v = rawget(t,k)
1088        if v then
1089            return v
1090        end
1091        k = gsub(k," ","")
1092        v = rawget(t,v)
1093        if v then
1094            return v
1095        elseif acceptlanguages then
1096            report_checks("registering extra language %a",k)
1097            rawset(t,k,k)
1098            return k
1099        end
1100    end
1101    return "dflt"
1102end)
1103
1104if setmetatablenewindex then
1105
1106    setmetatablenewindex(languages, "ignore")
1107    setmetatablenewindex(scripts,   "ignore")
1108    setmetatablenewindex(baselines, "ignore")
1109
1110end
1111
1112local function resolve(t,k)
1113    if k then
1114        k = lower(k)
1115        local v = rawget(t,k)
1116        if v then
1117            return v
1118        end
1119        k = gsub(k," ","")
1120        local v = rawget(t,k)
1121        if v then
1122            return v
1123        end
1124        local tag, dd = match(k,"(..)(%d+)")
1125        if tag and dd then
1126            local v = rawget(t,tag)
1127            if v then
1128                return v -- return format(v,tonumber(dd)) -- old way
1129            else
1130                local v = rawget(t,tag.."..") -- nicer in overview
1131                if v then
1132                    return (gsub(v,"%.%.",tonumber(dd))) -- new way
1133                end
1134            end
1135        end
1136    end
1137    return k -- "dflt"
1138end
1139
1140setmetatableindex(features, resolve)
1141
1142local function assign(t,k,v)
1143    if k and v then
1144        v = lower(v)
1145        rawset(t,k,v) -- rawset ?
1146     -- rawset(features,gsub(v,"[^a-z0-9]",""),k) -- why ? old code
1147    end
1148end
1149
1150if setmetatablenewindex then
1151
1152    setmetatablenewindex(features, assign)
1153
1154end
1155
1156local checkers = {
1157    rand = function(v)
1158        return v == true and "random" or v
1159    end
1160}
1161
1162if not storage then
1163    return
1164end
1165
1166local usedfeatures      = statistics.usedfeatures or { }
1167statistics.usedfeatures = usedfeatures
1168
1169table.setmetatableindex(usedfeatures, function(t,k) if k then local v = { } t[k] = v return v end end) -- table.autotable
1170
1171storage.register("fonts/otf/usedfeatures", usedfeatures, "fonts.handlers.otf.statistics.usedfeatures" )
1172
1173local normalizedaxis = otf.readers.helpers.normalizedaxis or function(s) return s end
1174
1175function otffeatures.normalize(features,wrap) -- wrap is for context
1176    if features then
1177        local h = { }
1178        for key, value in next, features do
1179            local k = lower(key)
1180            if k == "language" then
1181                local v = gsub(lower(value),"[^a-z0-9]","")
1182                h.language = rawget(verboselanguages,v) or (languages[v] and v) or "dflt" -- auto adds
1183            elseif k == "script" then
1184                local v = gsub(lower(value),"[^a-z0-9]","")
1185                h.script = rawget(verbosescripts,v) or (scripts[v] and v) or "dflt" -- auto adds
1186            elseif k == "axis" then
1187                h[k] = normalizedaxis(value)
1188            else
1189                local uk = usedfeatures[key]
1190                local uv = uk[value]
1191                if uv then
1192                 -- report_checks("feature value %a first seen at %a",value,key)
1193                else
1194                    uv = tonumber(value) -- before boolean as there we also handle 0/1
1195                    if uv then
1196                        -- we're okay
1197                    elseif type(value) == "string" then
1198                        local b = is_boolean(value)
1199                        if type(b) == "nil" then
1200                         -- we do this elsewhere
1201                         --
1202                         -- if find(value,"=") then
1203                         --     local t = { }
1204                         --     for k, v in gmatch(value,"([^%s,=]+)%s*=%s*([^%s,=]+)") do
1205                         --         t[k] = tonumber(v) or v
1206                         --     end
1207                         --     if next(t) then
1208                         --         value = sequenced(t,",")
1209                         --     end
1210                         -- end
1211                            if wrap and find(value,",") then
1212                                uv = "{"..lower(value).."}"
1213                            else
1214                                uv = lower(value)
1215                            end
1216                        else
1217                            uv = b
1218                        end
1219                    elseif type(value) == "table" then
1220                        uv = sequenced(t,",")
1221                    else
1222                        uv = value
1223                    end
1224                    if not rawget(features,k) then
1225                        k = rawget(verbosefeatures,k) or k
1226                    end
1227                    local c = checkers[k]
1228                    if c then
1229                        uv = c(uv) or vc
1230                    end
1231                    uk[value] = uv
1232                end
1233                h[k] = uv
1234            end
1235        end
1236        return h
1237    end
1238end
1239