diff options
| author | Elie Roux <elie.roux@telecom-bretagne.eu> | 2013-04-27 03:08:43 -0700 | 
|---|---|---|
| committer | Elie Roux <elie.roux@telecom-bretagne.eu> | 2013-04-27 03:08:43 -0700 | 
| commit | 7a7a17242c20dfd54dfce2e5ead889f62c66d61f (patch) | |
| tree | 942ffddaa830a52504831526512ce48ddb5ab83d | |
| parent | f3776cb0941e417f8aa2efe46773cc7330506387 (diff) | |
| parent | e6b0062da9c8315605e9c8a10202337416ea5cd5 (diff) | |
| download | luaotfload-7a7a17242c20dfd54dfce2e5ead889f62c66d61f.tar.gz | |
Merge pull request #11 from lualatex/master
update with lualatex master
| -rw-r--r-- | .gitignore | 2 | ||||
| -rw-r--r-- | Makefile | 51 | ||||
| -rw-r--r-- | filegraph.dot | 51 | ||||
| -rw-r--r-- | font-age.lua | 3744 | ||||
| -rwxr-xr-x | fontdbutil.lua | 72 | ||||
| -rw-r--r-- | luaotfload-basics-gen.lua | 48 | ||||
| -rw-r--r-- | luaotfload-database.lua | 880 | ||||
| -rw-r--r-- | luaotfload-features.lua | 74 | ||||
| -rw-r--r-- | luaotfload-merged.lua | 856 | ||||
| -rw-r--r-- | luaotfload-override.lua | 5 | ||||
| -rw-r--r-- | luaotfload.dtx | 89 | ||||
| -rwxr-xr-x | mkglyphlist | 143 | ||||
| -rw-r--r-- | tests/lookups.tex | 6 | 
13 files changed, 1773 insertions, 4248 deletions
| @@ -31,3 +31,5 @@ tests/*.dvi  tests/*.ofm  tests/*.ovp  tests/*.ovf +tests/*.sty +tests/luaotfload* @@ -1,30 +1,34 @@  # Makefile for luaotfload -NAME   = luaotfload -DOC    = $(NAME).pdf -DTX    = $(NAME).dtx -OTFL   = $(wildcard otfl-*.lua) otfl-blacklist.cnf font-age.lua -SCRIPT = mkluatexfontdb.lua +NAME         = luaotfload +DOC          = $(NAME).pdf +DTX          = $(NAME).dtx +OTFL         = $(wildcard otfl-*.lua) otfl-blacklist.cnf font-age.lua +SCRIPT       = fontdbutil + +GLYPHSCRIPT  = mkglyphlist +GLYPHSOURCE  = glyphlist.txt  GRAPH  = filegraph  DOTPDF = $(GRAPH).pdf  DOT    = $(GRAPH).dot  # Files grouped by generation mode -GRAPHED  = $(DOTPDF) -COMPILED = $(DOC) -UNPACKED = luaotfload.sty luaotfload.lua -GENERATED = $(GRAPHED) $(COMPILED) $(UNPACKED) -SOURCE = $(DTX) $(OTFL) README Makefile NEWS $(SCRIPT) +GLYPHS      = font-age.lua +GRAPHED     = $(DOTPDF) +COMPILED    = $(DOC) +UNPACKED    = luaotfload.sty luaotfload.lua +GENERATED   = $(GRAPHED) $(COMPILED) $(UNPACKED) $(GLYPHS) +SOURCE 		= $(DTX) $(OTFL) README Makefile NEWS $(SCRIPT) $(GLYPHSCRIPT)  # test files -TESTDIR = tests -TESTFILES = $(wildcard $(TESTDIR)/*.tex $(TESTDIR)/*.ltx) -TESTFILES_SYS = $(TESTDIR)/systemfonts.tex $(TESTDIR)/fontconfig_conf_reading.tex -TESTFILES_TL = $(filter-out $(TESTFILES_SYS), $(TESTFILES)) +TESTDIR 		= tests +TESTFILES 		= $(wildcard $(TESTDIR)/*.tex $(TESTDIR)/*.ltx) +TESTFILES_SYS 	= $(TESTDIR)/systemfonts.tex $(TESTDIR)/fontconfig_conf_reading.tex +TESTFILES_TL 	= $(filter-out $(TESTFILES_SYS), $(TESTFILES))  # Files grouped by installation location -SCRIPTFILES = $(SCRIPT) +SCRIPTFILES = $(SCRIPT) $(GLYPHSCRIPT)  RUNFILES    = $(UNPACKED) $(OTFL)  DOCFILES    = $(DOC) README NEWS  SRCFILES    = $(DTX) Makefile @@ -42,21 +46,26 @@ SRCDIR    = $(TEXMFROOT)/source/$(FORMAT)/$(NAME)  TEXMFROOT = $(shell kpsewhich --var-value TEXMFHOME)  CTAN_ZIP = $(NAME).zip -TDS_ZIP = $(NAME).tds.zip -ZIPS = $(CTAN_ZIP) $(TDS_ZIP) +TDS_ZIP  = $(NAME).tds.zip +ZIPS 	 = $(CTAN_ZIP) $(TDS_ZIP) -DO_TEX = tex --interaction=batchmode $< >/dev/null -DO_LATEX = latexmk -pdf -pdflatex=lualatex -silent $< >/dev/null -DO_GRAPHVIZ = dot -Tpdf -o $@ $< > /dev/null +DO_TEX 			= tex --interaction=batchmode $< >/dev/null +DO_LATEX 		= latexmk -pdf -pdflatex=lualatex -silent $< >/dev/null +DO_GRAPHVIZ 	= dot -Tpdf -o $@ $< > /dev/null +DO_GLYPHLIST 	= texlua ./mkglyphlist > /dev/null  all: $(GENERATED)  graph: $(GRAPHED)  doc: $(GRAPHED) $(COMPILED)  unpack: $(UNPACKED) +glyphs: $(GLYPHS)  ctan: check $(CTAN_ZIP)  tds: $(TDS_ZIP)  world: all ctan +$(GLYPHS): /dev/null +	$(DO_GLYPHLIST) +  $(GRAPHED): $(DOT)  	$(DO_GRAPHVIZ) @@ -118,5 +127,5 @@ clean:  	@$(RM) -- *.log *.aux *.toc *.idx *.ind *.ilg *.out $(TESTDIR)/*.log  mrproper: clean -	@$(RM) -- $(GENERATED) $(ZIPS) $(TESTDIR)/*.pdf +	@$(RM) -- $(GENERATED) $(ZIPS) $(GLYPHSOURCE) $(TESTDIR)/*.pdf diff --git a/filegraph.dot b/filegraph.dot index 9b79953..a0eadec 100644 --- a/filegraph.dot +++ b/filegraph.dot @@ -27,6 +27,9 @@ strict digraph luaotfload_files { //looks weird with circo ...  /* ····································································   * file structure   * ································································· */ +    fontdbutil  -> font_names   [label="--update", +                                 style=dashed] +      luaotfload -> otfl_fonts_merged [label="merged"]      luaotfload -> merged_lua_libs     [label="unmerged", style=solid]      luaotfload -> merged_luatex_fonts [label="unmerged", style=solid] @@ -35,7 +38,6 @@ strict digraph luaotfload_files { //looks weird with circo ...      luaotfload -> luaotfload_libs      luaotfload -> otfl_blacklist_cnf -      otfl_fonts_merged -> merged_lua_libs     [label="merged",                                                style=dotted,                                                lhead=cluster_merged] @@ -46,12 +48,36 @@ strict digraph luaotfload_files { //looks weird with circo ...                                                style=dotted,                                                lhead=cluster_merged] +    merged_luatex_fonts -> font_age [label="luatex-fonts-enc.lua", +                                     ltail=cluster_merged] + +    luaotfload_libs -> font_names [label="luaotfload-database.lua"] +    mkglyphlist -> font_age     [label="generates from glyphlist.txt", +                                 style=dashed] + +    subgraph { rank = same; mkglyphlist; fontdbutil; luaotfload }  /* ····································································   * main files   * ································································· */ +    fontdbutil        [label  = "fontdbutil\nmkluatexfontdb.lua", +                       shape  = rect, +                       width  = "3.2cm", +                       height = "1.2cm", +                       color  = "#01012222", +                       style  = "filled,rounded", +                       penwidth=2] + +    mkglyphlist       [label  = "mkglyphlist", +                       shape  = rect, +                       width  = "3.2cm", +                       height = "1.2cm", +                       color  = "#01012222", +                       style  = "filled,rounded", +                       penwidth=2] +      luaotfload        [label  = "luaotfload.lua",                         shape  = rect,                         width  = "3.2cm", @@ -81,6 +107,22 @@ strict digraph luaotfload_files { //looks weird with circo ...   * ································································· */ +    font_age [style      = "filled,dashed", +              shape      = rect, +              width      = "3.2cm", +              fillcolor  = "#01012222", +              color      = grey40, +              style      = "filled,dotted,rounded", +              label      = "font-age.lua"] + +    font_names [style      = "filled,dashed", +                shape      = rect, +                width      = "3.2cm", +                fillcolor  = "#01012222", +                color      = grey40, +                style      = "filled,dotted,rounded", +                label      = "luaotfload-names.lua\nluaotfload-names.luc"] +      otfl_blacklist_cnf [style      = "filled,dashed",                          shape      = rect,                          width      = "3.2cm", @@ -97,10 +139,9 @@ strict digraph luaotfload_files { //looks weird with circo ...          label      = <              <table cellborder="0" bgcolor="#FFFFFFAA">                  <th> <td colspan="2"> <font point-size="12" face="Iwona Italic">Luaotfload Libraries</font> </td> </th> -                <tr> <td>luaotfload-font-otc.lua</td> <td>luaotfload-lib-dir.lua</td> </tr> -                <tr> <td>luaotfload-override.lua</td> <td>luaotfload-loaders.lua</td> </tr> -                <tr> <td>luaotfload-database.lua</td> <td>luaotfload-color.lua</td>   </tr> -                <tr> <td>luaotfload-features.lua</td> </tr> +                <tr> <td>luaotfload-lib-dir.lua</td>  <td>luaotfload-features.lua</td> </tr> +                <tr> <td>luaotfload-override.lua</td> <td>luaotfload-loaders.lua</td>  </tr> +                <tr> <td>luaotfload-database.lua</td> <td>luaotfload-color.lua</td>    </tr>              </table>          >,      ] diff --git a/font-age.lua b/font-age.lua deleted file mode 100644 index 741bb47..0000000 --- a/font-age.lua +++ /dev/null @@ -1,3744 +0,0 @@ -if not modules then modules = { } end modules ['font-age'] = { -    version   = 1.001, -    comment   = "companion to font-gee.lua", -    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL", -    copyright = "derived from http://www.adobe.com/devnet/opentype/archives/glyphlist.txt", -    original  = "Adobe Glyph List, version 2.0, September 20, 2002", -} - -if context then -    texio.write_nl("fatal error: this module is not for context") -    os.exit() -end - -return { -- generated -    ["A"]=65, -    ["AE"]=198, -    ["AEacute"]=508, -    ["AEmacron"]=482, -    ["Aacute"]=193, -    ["Abreve"]=258, -    ["Abreveacute"]=7854, -    ["Abrevecyrillic"]=1232, -    ["Abrevedotbelow"]=7862, -    ["Abrevegrave"]=7856, -    ["Abrevehookabove"]=7858, -    ["Abrevetilde"]=7860, -    ["Acaron"]=461, -    ["Acircle"]=9398, -    ["Acircumflex"]=194, -    ["Acircumflexacute"]=7844, -    ["Acircumflexdotbelow"]=7852, -    ["Acircumflexgrave"]=7846, -    ["Acircumflexhookabove"]=7848, -    ["Acircumflextilde"]=7850, -    ["Adblgrave"]=512, -    ["Adieresis"]=196, -    ["Adieresiscyrillic"]=1234, -    ["Adieresismacron"]=478, -    ["Adotbelow"]=7840, -    ["Adotmacron"]=480, -    ["Agrave"]=192, -    ["Ahookabove"]=7842, -    ["Aiecyrillic"]=1236, -    ["Ainvertedbreve"]=514, -    ["Alpha"]=913, -    ["Alphatonos"]=902, -    ["Amacron"]=256, -    ["Amonospace"]=65313, -    ["Aogonek"]=260, -    ["Aring"]=197, -    ["Aringacute"]=506, -    ["Aringbelow"]=7680, -    ["Atilde"]=195, -    ["Aybarmenian"]=1329, -    ["B"]=66, -    ["Bcircle"]=9399, -    ["Bdotaccent"]=7682, -    ["Bdotbelow"]=7684, -    ["Benarmenian"]=1330, -    ["Beta"]=914, -    ["Bhook"]=385, -    ["Blinebelow"]=7686, -    ["Bmonospace"]=65314, -    ["Btopbar"]=386, -    ["C"]=67, -    ["Caarmenian"]=1342, -    ["Cacute"]=262, -    ["Ccaron"]=268, -    ["Ccedilla"]=199, -    ["Ccedillaacute"]=7688, -    ["Ccircle"]=9400, -    ["Ccircumflex"]=264, -    ["Cdotaccent"]=266, -    ["Chaarmenian"]=1353, -    ["Cheabkhasiancyrillic"]=1212, -    ["Chedescenderabkhasiancyrillic"]=1214, -    ["Chedescendercyrillic"]=1206, -    ["Chedieresiscyrillic"]=1268, -    ["Cheharmenian"]=1347, -    ["Chekhakassiancyrillic"]=1227, -    ["Cheverticalstrokecyrillic"]=1208, -    ["Chi"]=935, -    ["Chook"]=391, -    ["Cmonospace"]=65315, -    ["Coarmenian"]=1361, -    ["D"]=68, -    ["DZ"]=497, -    ["DZcaron"]=452, -    ["Daarmenian"]=1332, -    ["Dafrican"]=393, -    ["Dcaron"]=270, -    ["Dcedilla"]=7696, -    ["Dcircle"]=9401, -    ["Dcircumflexbelow"]=7698, -    ["Ddotaccent"]=7690, -    ["Ddotbelow"]=7692, -    ["Deicoptic"]=1006, -    ["Deltagreek"]=916, -    ["Dhook"]=394, -    ["Digammagreek"]=988, -    ["Dlinebelow"]=7694, -    ["Dmonospace"]=65316, -    ["Dslash"]=272, -    ["Dtopbar"]=395, -    ["Dz"]=498, -    ["Dzcaron"]=453, -    ["Dzeabkhasiancyrillic"]=1248, -    ["E"]=69, -    ["Eacute"]=201, -    ["Ebreve"]=276, -    ["Ecaron"]=282, -    ["Ecedillabreve"]=7708, -    ["Echarmenian"]=1333, -    ["Ecircle"]=9402, -    ["Ecircumflex"]=202, -    ["Ecircumflexacute"]=7870, -    ["Ecircumflexbelow"]=7704, -    ["Ecircumflexdotbelow"]=7878, -    ["Ecircumflexgrave"]=7872, -    ["Ecircumflexhookabove"]=7874, -    ["Ecircumflextilde"]=7876, -    ["Edblgrave"]=516, -    ["Edieresis"]=203, -    ["Edotaccent"]=278, -    ["Edotbelow"]=7864, -    ["Egrave"]=200, -    ["Eharmenian"]=1335, -    ["Ehookabove"]=7866, -    ["Eightroman"]=8551, -    ["Einvertedbreve"]=518, -    ["Eiotifiedcyrillic"]=1124, -    ["Elevenroman"]=8554, -    ["Emacron"]=274, -    ["Emacronacute"]=7702, -    ["Emacrongrave"]=7700, -    ["Emonospace"]=65317, -    ["Endescendercyrillic"]=1186, -    ["Eng"]=330, -    ["Enghecyrillic"]=1188, -    ["Enhookcyrillic"]=1223, -    ["Eogonek"]=280, -    ["Eopen"]=400, -    ["Epsilon"]=917, -    ["Epsilontonos"]=904, -    ["Ereversed"]=398, -    ["Esdescendercyrillic"]=1194, -    ["Esh"]=425, -    ["Eta"]=919, -    ["Etarmenian"]=1336, -    ["Etatonos"]=905, -    ["Eth"]=208, -    ["Etilde"]=7868, -    ["Etildebelow"]=7706, -    ["Ezh"]=439, -    ["Ezhcaron"]=494, -    ["Ezhreversed"]=440, -    ["F"]=70, -    ["Fcircle"]=9403, -    ["Fdotaccent"]=7710, -    ["Feharmenian"]=1366, -    ["Feicoptic"]=996, -    ["Fhook"]=401, -    ["Fiveroman"]=8548, -    ["Fmonospace"]=65318, -    ["Fourroman"]=8547, -    ["G"]=71, -    ["GBsquare"]=13191, -    ["Gacute"]=500, -    ["Gamma"]=915, -    ["Gammaafrican"]=404, -    ["Gangiacoptic"]=1002, -    ["Gbreve"]=286, -    ["Gcaron"]=486, -    ["Gcircle"]=9404, -    ["Gcircumflex"]=284, -    ["Gcommaaccent"]=290, -    ["Gdotaccent"]=288, -    ["Ghadarmenian"]=1346, -    ["Ghemiddlehookcyrillic"]=1172, -    ["Ghestrokecyrillic"]=1170, -    ["Ghook"]=403, -    ["Gimarmenian"]=1331, -    ["Gmacron"]=7712, -    ["Gmonospace"]=65319, -    ["Gsmallhook"]=667, -    ["Gstroke"]=484, -    ["H"]=72, -    ["HPsquare"]=13259, -    ["Haabkhasiancyrillic"]=1192, -    ["Hadescendercyrillic"]=1202, -    ["Hbar"]=294, -    ["Hbrevebelow"]=7722, -    ["Hcedilla"]=7720, -    ["Hcircle"]=9405, -    ["Hcircumflex"]=292, -    ["Hdieresis"]=7718, -    ["Hdotaccent"]=7714, -    ["Hdotbelow"]=7716, -    ["Hmonospace"]=65320, -    ["Hoarmenian"]=1344, -    ["Horicoptic"]=1000, -    ["Hzsquare"]=13200, -    ["I"]=73, -    ["IJ"]=306, -    ["Iacute"]=205, -    ["Ibreve"]=300, -    ["Icaron"]=463, -    ["Icircle"]=9406, -    ["Icircumflex"]=206, -    ["Idblgrave"]=520, -    ["Idieresis"]=207, -    ["Idieresisacute"]=7726, -    ["Idieresiscyrillic"]=1252, -    ["Idotaccent"]=304, -    ["Idotbelow"]=7882, -    ["Iebrevecyrillic"]=1238, -    ["Ifraktur"]=8465, -    ["Igrave"]=204, -    ["Ihookabove"]=7880, -    ["Iinvertedbreve"]=522, -    ["Imacron"]=298, -    ["Imacroncyrillic"]=1250, -    ["Imonospace"]=65321, -    ["Iniarmenian"]=1339, -    ["Iogonek"]=302, -    ["Iota"]=921, -    ["Iotaafrican"]=406, -    ["Iotadieresis"]=938, -    ["Iotatonos"]=906, -    ["Istroke"]=407, -    ["Itilde"]=296, -    ["Itildebelow"]=7724, -    ["Izhitsadblgravecyrillic"]=1142, -    ["J"]=74, -    ["Jaarmenian"]=1345, -    ["Jcircle"]=9407, -    ["Jcircumflex"]=308, -    ["Jheharmenian"]=1355, -    ["Jmonospace"]=65322, -    ["K"]=75, -    ["KBsquare"]=13189, -    ["KKsquare"]=13261, -    ["Kabashkircyrillic"]=1184, -    ["Kacute"]=7728, -    ["Kadescendercyrillic"]=1178, -    ["Kahookcyrillic"]=1219, -    ["Kappa"]=922, -    ["Kastrokecyrillic"]=1182, -    ["Kaverticalstrokecyrillic"]=1180, -    ["Kcaron"]=488, -    ["Kcircle"]=9408, -    ["Kcommaaccent"]=310, -    ["Kdotbelow"]=7730, -    ["Keharmenian"]=1364, -    ["Kenarmenian"]=1343, -    ["Kheicoptic"]=998, -    ["Khook"]=408, -    ["Klinebelow"]=7732, -    ["Kmonospace"]=65323, -    ["Koppacyrillic"]=1152, -    ["Koppagreek"]=990, -    ["Ksicyrillic"]=1134, -    ["L"]=76, -    ["LJ"]=455, -    ["Lacute"]=313, -    ["Lambda"]=923, -    ["Lcaron"]=317, -    ["Lcircle"]=9409, -    ["Lcircumflexbelow"]=7740, -    ["Lcommaaccent"]=315, -    ["Ldotaccent"]=319, -    ["Ldotbelow"]=7734, -    ["Ldotbelowmacron"]=7736, -    ["Liwnarmenian"]=1340, -    ["Lj"]=456, -    ["Llinebelow"]=7738, -    ["Lmonospace"]=65324, -    ["Lslash"]=321, -    ["M"]=77, -    ["MBsquare"]=13190, -    ["Macute"]=7742, -    ["Mcircle"]=9410, -    ["Mdotaccent"]=7744, -    ["Mdotbelow"]=7746, -    ["Menarmenian"]=1348, -    ["Mmonospace"]=65325, -    ["Mturned"]=412, -    ["Mu"]=924, -    ["N"]=78, -    ["NJ"]=458, -    ["Nacute"]=323, -    ["Ncaron"]=327, -    ["Ncircle"]=9411, -    ["Ncircumflexbelow"]=7754, -    ["Ncommaaccent"]=325, -    ["Ndotaccent"]=7748, -    ["Ndotbelow"]=7750, -    ["Nhookleft"]=413, -    ["Nineroman"]=8552, -    ["Nj"]=459, -    ["Nlinebelow"]=7752, -    ["Nmonospace"]=65326, -    ["Nowarmenian"]=1350, -    ["Ntilde"]=209, -    ["Nu"]=925, -    ["O"]=79, -    ["OE"]=338, -    ["Oacute"]=211, -    ["Obarredcyrillic"]=1256, -    ["Obarreddieresiscyrillic"]=1258, -    ["Obreve"]=334, -    ["Ocaron"]=465, -    ["Ocenteredtilde"]=415, -    ["Ocircle"]=9412, -    ["Ocircumflex"]=212, -    ["Ocircumflexacute"]=7888, -    ["Ocircumflexdotbelow"]=7896, -    ["Ocircumflexgrave"]=7890, -    ["Ocircumflexhookabove"]=7892, -    ["Ocircumflextilde"]=7894, -    ["Odblgrave"]=524, -    ["Odieresis"]=214, -    ["Odieresiscyrillic"]=1254, -    ["Odotbelow"]=7884, -    ["Ograve"]=210, -    ["Oharmenian"]=1365, -    ["Ohookabove"]=7886, -    ["Ohorn"]=416, -    ["Ohornacute"]=7898, -    ["Ohorndotbelow"]=7906, -    ["Ohorngrave"]=7900, -    ["Ohornhookabove"]=7902, -    ["Ohorntilde"]=7904, -    ["Ohungarumlaut"]=336, -    ["Oi"]=418, -    ["Oinvertedbreve"]=526, -    ["Omacron"]=332, -    ["Omacronacute"]=7762, -    ["Omacrongrave"]=7760, -    ["Omega"]=8486, -    ["Omegacyrillic"]=1120, -    ["Omegagreek"]=937, -    ["Omegaroundcyrillic"]=1146, -    ["Omegatitlocyrillic"]=1148, -    ["Omegatonos"]=911, -    ["Omicron"]=927, -    ["Omicrontonos"]=908, -    ["Omonospace"]=65327, -    ["Oneroman"]=8544, -    ["Oogonek"]=490, -    ["Oogonekmacron"]=492, -    ["Oopen"]=390, -    ["Oslash"]=216, -    ["Ostrokeacute"]=510, -    ["Otcyrillic"]=1150, -    ["Otilde"]=213, -    ["Otildeacute"]=7756, -    ["Otildedieresis"]=7758, -    ["P"]=80, -    ["Pacute"]=7764, -    ["Pcircle"]=9413, -    ["Pdotaccent"]=7766, -    ["Peharmenian"]=1354, -    ["Pemiddlehookcyrillic"]=1190, -    ["Phi"]=934, -    ["Phook"]=420, -    ["Pi"]=928, -    ["Piwrarmenian"]=1363, -    ["Pmonospace"]=65328, -    ["Psi"]=936, -    ["Psicyrillic"]=1136, -    ["Q"]=81, -    ["Qcircle"]=9414, -    ["Qmonospace"]=65329, -    ["R"]=82, -    ["Raarmenian"]=1356, -    ["Racute"]=340, -    ["Rcaron"]=344, -    ["Rcircle"]=9415, -    ["Rcommaaccent"]=342, -    ["Rdblgrave"]=528, -    ["Rdotaccent"]=7768, -    ["Rdotbelow"]=7770, -    ["Rdotbelowmacron"]=7772, -    ["Reharmenian"]=1360, -    ["Rfraktur"]=8476, -    ["Rho"]=929, -    ["Rinvertedbreve"]=530, -    ["Rlinebelow"]=7774, -    ["Rmonospace"]=65330, -    ["Rsmallinverted"]=641, -    ["Rsmallinvertedsuperior"]=694, -    ["S"]=83, -    ["SF010000"]=9484, -    ["SF020000"]=9492, -    ["SF030000"]=9488, -    ["SF040000"]=9496, -    ["SF050000"]=9532, -    ["SF060000"]=9516, -    ["SF070000"]=9524, -    ["SF080000"]=9500, -    ["SF090000"]=9508, -    ["SF100000"]=9472, -    ["SF110000"]=9474, -    ["SF190000"]=9569, -    ["SF200000"]=9570, -    ["SF210000"]=9558, -    ["SF220000"]=9557, -    ["SF230000"]=9571, -    ["SF240000"]=9553, -    ["SF250000"]=9559, -    ["SF260000"]=9565, -    ["SF270000"]=9564, -    ["SF280000"]=9563, -    ["SF360000"]=9566, -    ["SF370000"]=9567, -    ["SF380000"]=9562, -    ["SF390000"]=9556, -    ["SF400000"]=9577, -    ["SF410000"]=9574, -    ["SF420000"]=9568, -    ["SF430000"]=9552, -    ["SF440000"]=9580, -    ["SF450000"]=9575, -    ["SF460000"]=9576, -    ["SF470000"]=9572, -    ["SF480000"]=9573, -    ["SF490000"]=9561, -    ["SF500000"]=9560, -    ["SF510000"]=9554, -    ["SF520000"]=9555, -    ["SF530000"]=9579, -    ["SF540000"]=9578, -    ["Sacute"]=346, -    ["Sacutedotaccent"]=7780, -    ["Sampigreek"]=992, -    ["Scaron"]=352, -    ["Scarondotaccent"]=7782, -    ["Scedilla"]=350, -    ["Schwa"]=399, -    ["Schwacyrillic"]=1240, -    ["Schwadieresiscyrillic"]=1242, -    ["Scircle"]=9416, -    ["Scircumflex"]=348, -    ["Scommaaccent"]=536, -    ["Sdotaccent"]=7776, -    ["Sdotbelow"]=7778, -    ["Sdotbelowdotaccent"]=7784, -    ["Seharmenian"]=1357, -    ["Sevenroman"]=8550, -    ["Shaarmenian"]=1351, -    ["Sheicoptic"]=994, -    ["Shhacyrillic"]=1210, -    ["Shimacoptic"]=1004, -    ["Sigma"]=931, -    ["Sixroman"]=8549, -    ["Smonospace"]=65331, -    ["Stigmagreek"]=986, -    ["T"]=84, -    ["Tau"]=932, -    ["Tbar"]=358, -    ["Tcaron"]=356, -    ["Tcircle"]=9417, -    ["Tcircumflexbelow"]=7792, -    ["Tcommaaccent"]=354, -    ["Tdotaccent"]=7786, -    ["Tdotbelow"]=7788, -    ["Tedescendercyrillic"]=1196, -    ["Tenroman"]=8553, -    ["Tetsecyrillic"]=1204, -    ["Theta"]=920, -    ["Thook"]=428, -    ["Thorn"]=222, -    ["Threeroman"]=8546, -    ["Tiwnarmenian"]=1359, -    ["Tlinebelow"]=7790, -    ["Tmonospace"]=65332, -    ["Toarmenian"]=1337, -    ["Tonefive"]=444, -    ["Tonesix"]=388, -    ["Tonetwo"]=423, -    ["Tretroflexhook"]=430, -    ["Twelveroman"]=8555, -    ["Tworoman"]=8545, -    ["U"]=85, -    ["Uacute"]=218, -    ["Ubreve"]=364, -    ["Ucaron"]=467, -    ["Ucircle"]=9418, -    ["Ucircumflex"]=219, -    ["Ucircumflexbelow"]=7798, -    ["Udblgrave"]=532, -    ["Udieresis"]=220, -    ["Udieresisacute"]=471, -    ["Udieresisbelow"]=7794, -    ["Udieresiscaron"]=473, -    ["Udieresiscyrillic"]=1264, -    ["Udieresisgrave"]=475, -    ["Udieresismacron"]=469, -    ["Udotbelow"]=7908, -    ["Ugrave"]=217, -    ["Uhookabove"]=7910, -    ["Uhorn"]=431, -    ["Uhornacute"]=7912, -    ["Uhorndotbelow"]=7920, -    ["Uhorngrave"]=7914, -    ["Uhornhookabove"]=7916, -    ["Uhorntilde"]=7918, -    ["Uhungarumlaut"]=368, -    ["Uhungarumlautcyrillic"]=1266, -    ["Uinvertedbreve"]=534, -    ["Ukcyrillic"]=1144, -    ["Umacron"]=362, -    ["Umacroncyrillic"]=1262, -    ["Umacrondieresis"]=7802, -    ["Umonospace"]=65333, -    ["Uogonek"]=370, -    ["Upsilon"]=933, -    ["Upsilonacutehooksymbolgreek"]=979, -    ["Upsilonafrican"]=433, -    ["Upsilondieresis"]=939, -    ["Upsilondieresishooksymbolgreek"]=980, -    ["Upsilonhooksymbol"]=978, -    ["Upsilontonos"]=910, -    ["Uring"]=366, -    ["Ustraightcyrillic"]=1198, -    ["Ustraightstrokecyrillic"]=1200, -    ["Utilde"]=360, -    ["Utildeacute"]=7800, -    ["Utildebelow"]=7796, -    ["V"]=86, -    ["Vcircle"]=9419, -    ["Vdotbelow"]=7806, -    ["Vewarmenian"]=1358, -    ["Vhook"]=434, -    ["Vmonospace"]=65334, -    ["Voarmenian"]=1352, -    ["Vtilde"]=7804, -    ["W"]=87, -    ["Wacute"]=7810, -    ["Wcircle"]=9420, -    ["Wcircumflex"]=372, -    ["Wdieresis"]=7812, -    ["Wdotaccent"]=7814, -    ["Wdotbelow"]=7816, -    ["Wgrave"]=7808, -    ["Wmonospace"]=65335, -    ["X"]=88, -    ["Xcircle"]=9421, -    ["Xdieresis"]=7820, -    ["Xdotaccent"]=7818, -    ["Xeharmenian"]=1341, -    ["Xi"]=926, -    ["Xmonospace"]=65336, -    ["Y"]=89, -    ["Yacute"]=221, -    ["Ycircle"]=9422, -    ["Ycircumflex"]=374, -    ["Ydieresis"]=376, -    ["Ydotaccent"]=7822, -    ["Ydotbelow"]=7924, -    ["Yerudieresiscyrillic"]=1272, -    ["Ygrave"]=7922, -    ["Yhook"]=435, -    ["Yhookabove"]=7926, -    ["Yiarmenian"]=1349, -    ["Yiwnarmenian"]=1362, -    ["Ymonospace"]=65337, -    ["Ytilde"]=7928, -    ["Yusbigcyrillic"]=1130, -    ["Yusbigiotifiedcyrillic"]=1132, -    ["Yuslittlecyrillic"]=1126, -    ["Yuslittleiotifiedcyrillic"]=1128, -    ["Z"]=90, -    ["Zaarmenian"]=1334, -    ["Zacute"]=377, -    ["Zcaron"]=381, -    ["Zcircle"]=9423, -    ["Zcircumflex"]=7824, -    ["Zdotaccent"]=379, -    ["Zdotbelow"]=7826, -    ["Zedescendercyrillic"]=1176, -    ["Zedieresiscyrillic"]=1246, -    ["Zeta"]=918, -    ["Zhearmenian"]=1338, -    ["Zhebrevecyrillic"]=1217, -    ["Zhedescendercyrillic"]=1174, -    ["Zhedieresiscyrillic"]=1244, -    ["Zlinebelow"]=7828, -    ["Zmonospace"]=65338, -    ["Zstroke"]=437, -    ["a"]=97, -    ["aabengali"]=2438, -    ["aacute"]=225, -    ["aadeva"]=2310, -    ["aagujarati"]=2694, -    ["aagurmukhi"]=2566, -    ["aamatragurmukhi"]=2622, -    ["aarusquare"]=13059, -    ["aavowelsignbengali"]=2494, -    ["aavowelsigndeva"]=2366, -    ["aavowelsigngujarati"]=2750, -    ["abbreviationmarkarmenian"]=1375, -    ["abbreviationsigndeva"]=2416, -    ["abengali"]=2437, -    ["abopomofo"]=12570, -    ["abreve"]=259, -    ["abreveacute"]=7855, -    ["abrevecyrillic"]=1233, -    ["abrevedotbelow"]=7863, -    ["abrevegrave"]=7857, -    ["abrevehookabove"]=7859, -    ["abrevetilde"]=7861, -    ["acaron"]=462, -    ["acircle"]=9424, -    ["acircumflex"]=226, -    ["acircumflexacute"]=7845, -    ["acircumflexdotbelow"]=7853, -    ["acircumflexgrave"]=7847, -    ["acircumflexhookabove"]=7849, -    ["acircumflextilde"]=7851, -    ["acute"]=180, -    ["acutebelowcmb"]=791, -    ["acutecomb"]=769, -    ["acutedeva"]=2388, -    ["acutelowmod"]=719, -    ["acutetonecmb"]=833, -    ["adblgrave"]=513, -    ["addakgurmukhi"]=2673, -    ["adeva"]=2309, -    ["adieresis"]=228, -    ["adieresiscyrillic"]=1235, -    ["adieresismacron"]=479, -    ["adotbelow"]=7841, -    ["adotmacron"]=481, -    ["ae"]=230, -    ["aeacute"]=509, -    ["aekorean"]=12624, -    ["aemacron"]=483, -    ["afii10017"]=1040, -    ["afii10018"]=1041, -    ["afii10019"]=1042, -    ["afii10020"]=1043, -    ["afii10021"]=1044, -    ["afii10022"]=1045, -    ["afii10023"]=1025, -    ["afii10024"]=1046, -    ["afii10025"]=1047, -    ["afii10026"]=1048, -    ["afii10027"]=1049, -    ["afii10028"]=1050, -    ["afii10029"]=1051, -    ["afii10030"]=1052, -    ["afii10031"]=1053, -    ["afii10032"]=1054, -    ["afii10033"]=1055, -    ["afii10034"]=1056, -    ["afii10035"]=1057, -    ["afii10036"]=1058, -    ["afii10037"]=1059, -    ["afii10038"]=1060, -    ["afii10039"]=1061, -    ["afii10040"]=1062, -    ["afii10041"]=1063, -    ["afii10042"]=1064, -    ["afii10043"]=1065, -    ["afii10044"]=1066, -    ["afii10045"]=1067, -    ["afii10046"]=1068, -    ["afii10047"]=1069, -    ["afii10048"]=1070, -    ["afii10049"]=1071, -    ["afii10050"]=1168, -    ["afii10051"]=1026, -    ["afii10052"]=1027, -    ["afii10053"]=1028, -    ["afii10054"]=1029, -    ["afii10055"]=1030, -    ["afii10056"]=1031, -    ["afii10057"]=1032, -    ["afii10058"]=1033, -    ["afii10059"]=1034, -    ["afii10060"]=1035, -    ["afii10061"]=1036, -    ["afii10062"]=1038, -    ["afii10065"]=1072, -    ["afii10145"]=1039, -    ["afii10146"]=1122, -    ["afii10147"]=1138, -    ["afii10148"]=1140, -    ["afii299"]=8206, -    ["afii300"]=8207, -    ["afii301"]=8205, -    ["afii57534"]=1749, -    ["afii61573"]=8236, -    ["afii61574"]=8237, -    ["afii61575"]=8238, -    ["agrave"]=224, -    ["agujarati"]=2693, -    ["agurmukhi"]=2565, -    ["ahiragana"]=12354, -    ["ahookabove"]=7843, -    ["aibengali"]=2448, -    ["aibopomofo"]=12574, -    ["aideva"]=2320, -    ["aiecyrillic"]=1237, -    ["aigujarati"]=2704, -    ["aigurmukhi"]=2576, -    ["aimatragurmukhi"]=2632, -    ["ainarabic"]=1593, -    ["ainfinalarabic"]=65226, -    ["aininitialarabic"]=65227, -    ["ainmedialarabic"]=65228, -    ["ainvertedbreve"]=515, -    ["aivowelsignbengali"]=2504, -    ["aivowelsigndeva"]=2376, -    ["aivowelsigngujarati"]=2760, -    ["akatakana"]=12450, -    ["akatakanahalfwidth"]=65393, -    ["akorean"]=12623, -    ["alefarabic"]=1575, -    ["alefdageshhebrew"]=64304, -    ["aleffinalarabic"]=65166, -    ["alefhamzaabovearabic"]=1571, -    ["alefhamzaabovefinalarabic"]=65156, -    ["alefhamzabelowarabic"]=1573, -    ["alefhamzabelowfinalarabic"]=65160, -    ["alefhebrew"]=1488, -    ["aleflamedhebrew"]=64335, -    ["alefmaddaabovearabic"]=1570, -    ["alefmaddaabovefinalarabic"]=65154, -    ["alefmaksuraarabic"]=1609, -    ["alefmaksurafinalarabic"]=65264, -    ["alefpatahhebrew"]=64302, -    ["alefqamatshebrew"]=64303, -    ["aleph"]=8501, -    ["allequal"]=8780, -    ["alpha"]=945, -    ["alphatonos"]=940, -    ["amacron"]=257, -    ["amonospace"]=65345, -    ["ampersand"]=38, -    ["ampersandmonospace"]=65286, -    ["amsquare"]=13250, -    ["anbopomofo"]=12578, -    ["angbopomofo"]=12580, -    ["angkhankhuthai"]=3674, -    ["angle"]=8736, -    ["anglebracketleft"]=12296, -    ["anglebracketleftvertical"]=65087, -    ["anglebracketright"]=12297, -    ["anglebracketrightvertical"]=65088, -    ["angleleft"]=9001, -    ["angleright"]=9002, -    ["angstrom"]=8491, -    ["anoteleia"]=903, -    ["anudattadeva"]=2386, -    ["anusvarabengali"]=2434, -    ["anusvaradeva"]=2306, -    ["anusvaragujarati"]=2690, -    ["aogonek"]=261, -    ["apaatosquare"]=13056, -    ["aparen"]=9372, -    ["apostrophearmenian"]=1370, -    ["apostrophemod"]=700, -    ["apple"]=63743, -    ["approaches"]=8784, -    ["approxequal"]=8776, -    ["approxequalorimage"]=8786, -    ["araeaekorean"]=12686, -    ["araeakorean"]=12685, -    ["arc"]=8978, -    ["arighthalfring"]=7834, -    ["aring"]=229, -    ["aringacute"]=507, -    ["aringbelow"]=7681, -    ["arrowboth"]=8596, -    ["arrowdashdown"]=8675, -    ["arrowdashleft"]=8672, -    ["arrowdashright"]=8674, -    ["arrowdashup"]=8673, -    ["arrowdbldown"]=8659, -    ["arrowdblup"]=8657, -    ["arrowdown"]=8595, -    ["arrowdownleft"]=8601, -    ["arrowdownright"]=8600, -    ["arrowdownwhite"]=8681, -    ["arrowheaddownmod"]=709, -    ["arrowheadleftmod"]=706, -    ["arrowheadrightmod"]=707, -    ["arrowheadupmod"]=708, -    ["arrowleft"]=8592, -    ["arrowleftdbl"]=8656, -    ["arrowleftdblstroke"]=8653, -    ["arrowleftoverright"]=8646, -    ["arrowleftwhite"]=8678, -    ["arrowright"]=8594, -    ["arrowrightdblstroke"]=8655, -    ["arrowrightheavy"]=10142, -    ["arrowrightoverleft"]=8644, -    ["arrowrightwhite"]=8680, -    ["arrowtableft"]=8676, -    ["arrowtabright"]=8677, -    ["arrowup"]=8593, -    ["arrowupdn"]=8597, -    ["arrowupdownbase"]=8616, -    ["arrowupleft"]=8598, -    ["arrowupleftofdown"]=8645, -    ["arrowupright"]=8599, -    ["arrowupwhite"]=8679, -    ["asciicircum"]=94, -    ["asciicircummonospace"]=65342, -    ["asciitilde"]=126, -    ["asciitildemonospace"]=65374, -    ["ascript"]=593, -    ["ascriptturned"]=594, -    ["asmallhiragana"]=12353, -    ["asmallkatakana"]=12449, -    ["asmallkatakanahalfwidth"]=65383, -    ["asterisk"]=42, -    ["asteriskarabic"]=1645, -    ["asteriskmath"]=8727, -    ["asteriskmonospace"]=65290, -    ["asterisksmall"]=65121, -    ["asterism"]=8258, -    ["asymptoticallyequal"]=8771, -    ["at"]=64, -    ["atilde"]=227, -    ["atmonospace"]=65312, -    ["atsmall"]=65131, -    ["aturned"]=592, -    ["aubengali"]=2452, -    ["aubopomofo"]=12576, -    ["audeva"]=2324, -    ["augujarati"]=2708, -    ["augurmukhi"]=2580, -    ["aulengthmarkbengali"]=2519, -    ["aumatragurmukhi"]=2636, -    ["auvowelsignbengali"]=2508, -    ["auvowelsigndeva"]=2380, -    ["auvowelsigngujarati"]=2764, -    ["avagrahadeva"]=2365, -    ["aybarmenian"]=1377, -    ["ayinaltonehebrew"]=64288, -    ["ayinhebrew"]=1506, -    ["b"]=98, -    ["babengali"]=2476, -    ["backslash"]=92, -    ["backslashmonospace"]=65340, -    ["badeva"]=2348, -    ["bagujarati"]=2732, -    ["bagurmukhi"]=2604, -    ["bahiragana"]=12400, -    ["bahtthai"]=3647, -    ["bakatakana"]=12496, -    ["barmonospace"]=65372, -    ["bbopomofo"]=12549, -    ["bcircle"]=9425, -    ["bdotaccent"]=7683, -    ["bdotbelow"]=7685, -    ["beamedsixteenthnotes"]=9836, -    ["because"]=8757, -    ["becyrillic"]=1073, -    ["beharabic"]=1576, -    ["behfinalarabic"]=65168, -    ["behinitialarabic"]=65169, -    ["behiragana"]=12409, -    ["behmedialarabic"]=65170, -    ["behmeeminitialarabic"]=64671, -    ["behmeemisolatedarabic"]=64520, -    ["behnoonfinalarabic"]=64621, -    ["bekatakana"]=12505, -    ["benarmenian"]=1378, -    ["beta"]=946, -    ["betasymbolgreek"]=976, -    ["betdageshhebrew"]=64305, -    ["bethebrew"]=1489, -    ["betrafehebrew"]=64332, -    ["bhabengali"]=2477, -    ["bhadeva"]=2349, -    ["bhagujarati"]=2733, -    ["bhagurmukhi"]=2605, -    ["bhook"]=595, -    ["bihiragana"]=12403, -    ["bikatakana"]=12499, -    ["bilabialclick"]=664, -    ["bindigurmukhi"]=2562, -    ["birusquare"]=13105, -    ["blackcircle"]=9679, -    ["blackdiamond"]=9670, -    ["blackleftpointingtriangle"]=9664, -    ["blacklenticularbracketleft"]=12304, -    ["blacklenticularbracketleftvertical"]=65083, -    ["blacklenticularbracketright"]=12305, -    ["blacklenticularbracketrightvertical"]=65084, -    ["blacklowerlefttriangle"]=9699, -    ["blacklowerrighttriangle"]=9698, -    ["blackrightpointingtriangle"]=9654, -    ["blacksmallsquare"]=9642, -    ["blackstar"]=9733, -    ["blackupperlefttriangle"]=9700, -    ["blackupperrighttriangle"]=9701, -    ["blackuppointingsmalltriangle"]=9652, -    ["blank"]=9251, -    ["blinebelow"]=7687, -    ["block"]=9608, -    ["bmonospace"]=65346, -    ["bobaimaithai"]=3610, -    ["bohiragana"]=12412, -    ["bokatakana"]=12508, -    ["bparen"]=9373, -    ["bqsquare"]=13251, -    ["braceleft"]=123, -    ["braceleftmonospace"]=65371, -    ["braceleftsmall"]=65115, -    ["braceleftvertical"]=65079, -    ["braceright"]=125, -    ["bracerightmonospace"]=65373, -    ["bracerightsmall"]=65116, -    ["bracerightvertical"]=65080, -    ["bracketleft"]=91, -    ["bracketleftmonospace"]=65339, -    ["bracketright"]=93, -    ["bracketrightmonospace"]=65341, -    ["breve"]=728, -    ["brevebelowcmb"]=814, -    ["brevecmb"]=774, -    ["breveinvertedbelowcmb"]=815, -    ["breveinvertedcmb"]=785, -    ["breveinverteddoublecmb"]=865, -    ["bridgebelowcmb"]=810, -    ["bridgeinvertedbelowcmb"]=826, -    ["brokenbar"]=166, -    ["bstroke"]=384, -    ["btopbar"]=387, -    ["buhiragana"]=12406, -    ["bukatakana"]=12502, -    ["bullet"]=8226, -    ["bulletoperator"]=8729, -    ["bullseye"]=9678, -    ["c"]=99, -    ["caarmenian"]=1390, -    ["cabengali"]=2458, -    ["cacute"]=263, -    ["cadeva"]=2330, -    ["cagujarati"]=2714, -    ["cagurmukhi"]=2586, -    ["calsquare"]=13192, -    ["candrabindubengali"]=2433, -    ["candrabinducmb"]=784, -    ["candrabindudeva"]=2305, -    ["candrabindugujarati"]=2689, -    ["capslock"]=8682, -    ["careof"]=8453, -    ["caron"]=711, -    ["caronbelowcmb"]=812, -    ["caroncmb"]=780, -    ["carriagereturn"]=8629, -    ["cbopomofo"]=12568, -    ["ccaron"]=269, -    ["ccedilla"]=231, -    ["ccedillaacute"]=7689, -    ["ccircle"]=9426, -    ["ccircumflex"]=265, -    ["ccurl"]=597, -    ["cdotaccent"]=267, -    ["cdsquare"]=13253, -    ["cedilla"]=184, -    ["cedillacmb"]=807, -    ["cent"]=162, -    ["centigrade"]=8451, -    ["centmonospace"]=65504, -    ["chaarmenian"]=1401, -    ["chabengali"]=2459, -    ["chadeva"]=2331, -    ["chagujarati"]=2715, -    ["chagurmukhi"]=2587, -    ["chbopomofo"]=12564, -    ["cheabkhasiancyrillic"]=1213, -    ["checkmark"]=10003, -    ["checyrillic"]=1095, -    ["chedescenderabkhasiancyrillic"]=1215, -    ["chedescendercyrillic"]=1207, -    ["chedieresiscyrillic"]=1269, -    ["cheharmenian"]=1395, -    ["chekhakassiancyrillic"]=1228, -    ["cheverticalstrokecyrillic"]=1209, -    ["chi"]=967, -    ["chieuchacirclekorean"]=12919, -    ["chieuchaparenkorean"]=12823, -    ["chieuchcirclekorean"]=12905, -    ["chieuchkorean"]=12618, -    ["chieuchparenkorean"]=12809, -    ["chochangthai"]=3594, -    ["chochanthai"]=3592, -    ["chochingthai"]=3593, -    ["chochoethai"]=3596, -    ["chook"]=392, -    ["cieucacirclekorean"]=12918, -    ["cieucaparenkorean"]=12822, -    ["cieuccirclekorean"]=12904, -    ["cieuckorean"]=12616, -    ["cieucparenkorean"]=12808, -    ["cieucuparenkorean"]=12828, -    ["circleot"]=8857, -    ["circlepostalmark"]=12342, -    ["circlewithlefthalfblack"]=9680, -    ["circlewithrighthalfblack"]=9681, -    ["circumflex"]=710, -    ["circumflexbelowcmb"]=813, -    ["circumflexcmb"]=770, -    ["clear"]=8999, -    ["clickalveolar"]=450, -    ["clickdental"]=448, -    ["clicklateral"]=449, -    ["clickretroflex"]=451, -    ["clubsuitblack"]=9827, -    ["clubsuitwhite"]=9831, -    ["cmcubedsquare"]=13220, -    ["cmonospace"]=65347, -    ["cmsquaredsquare"]=13216, -    ["coarmenian"]=1409, -    ["colon"]=58, -    ["colonmonospace"]=65306, -    ["colonsign"]=8353, -    ["colonsmall"]=65109, -    ["colontriangularhalfmod"]=721, -    ["colontriangularmod"]=720, -    ["comma"]=44, -    ["commaabovecmb"]=787, -    ["commaaboverightcmb"]=789, -    ["commaarabic"]=1548, -    ["commaarmenian"]=1373, -    ["commamonospace"]=65292, -    ["commareversedabovecmb"]=788, -    ["commareversedmod"]=701, -    ["commasmall"]=65104, -    ["commaturnedabovecmb"]=786, -    ["commaturnedmod"]=699, -    ["congruent"]=8773, -    ["contourintegral"]=8750, -    ["control"]=8963, -    ["controlACK"]=6, -    ["controlBEL"]=7, -    ["controlBS"]=8, -    ["controlCAN"]=24, -    ["controlCR"]=13, -    ["controlDC1"]=17, -    ["controlDC2"]=18, -    ["controlDC3"]=19, -    ["controlDC4"]=20, -    ["controlDEL"]=127, -    ["controlDLE"]=16, -    ["controlEM"]=25, -    ["controlENQ"]=5, -    ["controlEOT"]=4, -    ["controlESC"]=27, -    ["controlETB"]=23, -    ["controlETX"]=3, -    ["controlFF"]=12, -    ["controlFS"]=28, -    ["controlGS"]=29, -    ["controlHT"]=9, -    ["controlLF"]=10, -    ["controlNAK"]=21, -    ["controlRS"]=30, -    ["controlSI"]=15, -    ["controlSO"]=14, -    ["controlSOT"]=2, -    ["controlSTX"]=1, -    ["controlSUB"]=26, -    ["controlSYN"]=22, -    ["controlUS"]=31, -    ["controlVT"]=11, -    ["copyright"]=169, -    ["cornerbracketleft"]=12300, -    ["cornerbracketlefthalfwidth"]=65378, -    ["cornerbracketleftvertical"]=65089, -    ["cornerbracketright"]=12301, -    ["cornerbracketrighthalfwidth"]=65379, -    ["cornerbracketrightvertical"]=65090, -    ["corporationsquare"]=13183, -    ["cosquare"]=13255, -    ["coverkgsquare"]=13254, -    ["cparen"]=9374, -    ["cruzeiro"]=8354, -    ["cstretched"]=663, -    ["curlyand"]=8911, -    ["curlyor"]=8910, -    ["currency"]=164, -    ["d"]=100, -    ["daarmenian"]=1380, -    ["dabengali"]=2470, -    ["dadarabic"]=1590, -    ["dadeva"]=2342, -    ["dadfinalarabic"]=65214, -    ["dadinitialarabic"]=65215, -    ["dadmedialarabic"]=65216, -    ["dageshhebrew"]=1468, -    ["dagger"]=8224, -    ["daggerdbl"]=8225, -    ["dagujarati"]=2726, -    ["dagurmukhi"]=2598, -    ["dahiragana"]=12384, -    ["dakatakana"]=12480, -    ["dalarabic"]=1583, -    ["daletdageshhebrew"]=64307, -    ["dalettserehebrew"]=1491, -    ["dalfinalarabic"]=65194, -    ["dammalowarabic"]=1615, -    ["dammatanarabic"]=1612, -    ["danda"]=2404, -    ["dargalefthebrew"]=1447, -    ["dasiapneumatacyrilliccmb"]=1157, -    ["dblanglebracketleft"]=12298, -    ["dblanglebracketleftvertical"]=65085, -    ["dblanglebracketright"]=12299, -    ["dblanglebracketrightvertical"]=65086, -    ["dblarchinvertedbelowcmb"]=811, -    ["dblarrowleft"]=8660, -    ["dblarrowright"]=8658, -    ["dbldanda"]=2405, -    ["dblgravecmb"]=783, -    ["dblintegral"]=8748, -    ["dbllowlinecmb"]=819, -    ["dbloverlinecmb"]=831, -    ["dblprimemod"]=698, -    ["dblverticalbar"]=8214, -    ["dblverticallineabovecmb"]=782, -    ["dbopomofo"]=12553, -    ["dbsquare"]=13256, -    ["dcaron"]=271, -    ["dcedilla"]=7697, -    ["dcircle"]=9427, -    ["dcircumflexbelow"]=7699, -    ["ddabengali"]=2465, -    ["ddadeva"]=2337, -    ["ddagujarati"]=2721, -    ["ddagurmukhi"]=2593, -    ["ddalarabic"]=1672, -    ["ddalfinalarabic"]=64393, -    ["dddhadeva"]=2396, -    ["ddhabengali"]=2466, -    ["ddhadeva"]=2338, -    ["ddhagujarati"]=2722, -    ["ddhagurmukhi"]=2594, -    ["ddotaccent"]=7691, -    ["ddotbelow"]=7693, -    ["decimalseparatorpersian"]=1643, -    ["decyrillic"]=1076, -    ["degree"]=176, -    ["dehihebrew"]=1453, -    ["dehiragana"]=12391, -    ["deicoptic"]=1007, -    ["dekatakana"]=12487, -    ["deleteleft"]=9003, -    ["deleteright"]=8998, -    ["delta"]=948, -    ["deltaturned"]=397, -    ["denominatorminusonenumeratorbengali"]=2552, -    ["dezh"]=676, -    ["dhabengali"]=2471, -    ["dhadeva"]=2343, -    ["dhagujarati"]=2727, -    ["dhagurmukhi"]=2599, -    ["dhook"]=599, -    ["dialytikatonoscmb"]=836, -    ["diamond"]=9830, -    ["diamondsuitwhite"]=9826, -    ["dieresis"]=168, -    ["dieresisbelowcmb"]=804, -    ["dieresiscmb"]=776, -    ["dieresistonos"]=901, -    ["dihiragana"]=12386, -    ["dikatakana"]=12482, -    ["dittomark"]=12291, -    ["divide"]=247, -    ["divides"]=8739, -    ["divisionslash"]=8725, -    ["djecyrillic"]=1106, -    ["dlinebelow"]=7695, -    ["dlsquare"]=13207, -    ["dmacron"]=273, -    ["dmonospace"]=65348, -    ["dnblock"]=9604, -    ["dochadathai"]=3598, -    ["dodekthai"]=3604, -    ["dohiragana"]=12393, -    ["dokatakana"]=12489, -    ["dollar"]=36, -    ["dollarmonospace"]=65284, -    ["dollarsmall"]=65129, -    ["dong"]=8363, -    ["dorusquare"]=13094, -    ["dotaccent"]=729, -    ["dotaccentcmb"]=775, -    ["dotbelowcomb"]=803, -    ["dotkatakana"]=12539, -    ["dotlessi"]=305, -    ["dotlessjstrokehook"]=644, -    ["dotmath"]=8901, -    ["dottedcircle"]=9676, -    ["downtackbelowcmb"]=798, -    ["downtackmod"]=725, -    ["dparen"]=9375, -    ["dtail"]=598, -    ["dtopbar"]=396, -    ["duhiragana"]=12389, -    ["dukatakana"]=12485, -    ["dz"]=499, -    ["dzaltone"]=675, -    ["dzcaron"]=454, -    ["dzcurl"]=677, -    ["dzeabkhasiancyrillic"]=1249, -    ["dzecyrillic"]=1109, -    ["dzhecyrillic"]=1119, -    ["e"]=101, -    ["eacute"]=233, -    ["earth"]=9793, -    ["ebengali"]=2447, -    ["ebopomofo"]=12572, -    ["ebreve"]=277, -    ["ecandradeva"]=2317, -    ["ecandragujarati"]=2701, -    ["ecandravowelsigndeva"]=2373, -    ["ecandravowelsigngujarati"]=2757, -    ["ecaron"]=283, -    ["ecedillabreve"]=7709, -    ["echarmenian"]=1381, -    ["echyiwnarmenian"]=1415, -    ["ecircle"]=9428, -    ["ecircumflex"]=234, -    ["ecircumflexacute"]=7871, -    ["ecircumflexbelow"]=7705, -    ["ecircumflexdotbelow"]=7879, -    ["ecircumflexgrave"]=7873, -    ["ecircumflexhookabove"]=7875, -    ["ecircumflextilde"]=7877, -    ["ecyrillic"]=1108, -    ["edblgrave"]=517, -    ["edeva"]=2319, -    ["edieresis"]=235, -    ["edotaccent"]=279, -    ["edotbelow"]=7865, -    ["eegurmukhi"]=2575, -    ["eematragurmukhi"]=2631, -    ["efcyrillic"]=1092, -    ["egrave"]=232, -    ["egujarati"]=2703, -    ["eharmenian"]=1383, -    ["ehbopomofo"]=12573, -    ["ehiragana"]=12360, -    ["ehookabove"]=7867, -    ["eibopomofo"]=12575, -    ["eight"]=56, -    ["eightbengali"]=2542, -    ["eightcircle"]=9319, -    ["eightcircleinversesansserif"]=10129, -    ["eightdeva"]=2414, -    ["eighteencircle"]=9329, -    ["eighteenparen"]=9349, -    ["eighteenperiod"]=9369, -    ["eightgujarati"]=2798, -    ["eightgurmukhi"]=2670, -    ["eighthackarabic"]=1640, -    ["eighthangzhou"]=12328, -    ["eightideographicparen"]=12839, -    ["eightinferior"]=8328, -    ["eightmonospace"]=65304, -    ["eightparen"]=9339, -    ["eightperiod"]=9359, -    ["eightpersian"]=1784, -    ["eightroman"]=8567, -    ["eightsuperior"]=8312, -    ["eightthai"]=3672, -    ["einvertedbreve"]=519, -    ["eiotifiedcyrillic"]=1125, -    ["ekatakana"]=12456, -    ["ekatakanahalfwidth"]=65396, -    ["ekonkargurmukhi"]=2676, -    ["ekorean"]=12628, -    ["elcyrillic"]=1083, -    ["element"]=8712, -    ["elevencircle"]=9322, -    ["elevenparen"]=9342, -    ["elevenperiod"]=9362, -    ["elevenroman"]=8570, -    ["ellipsis"]=8230, -    ["ellipsisvertical"]=8942, -    ["emacron"]=275, -    ["emacronacute"]=7703, -    ["emacrongrave"]=7701, -    ["emcyrillic"]=1084, -    ["emdash"]=8212, -    ["emdashvertical"]=65073, -    ["emonospace"]=65349, -    ["emphasismarkarmenian"]=1371, -    ["emptyset"]=8709, -    ["enbopomofo"]=12579, -    ["encyrillic"]=1085, -    ["endash"]=8211, -    ["endashvertical"]=65074, -    ["endescendercyrillic"]=1187, -    ["eng"]=331, -    ["engbopomofo"]=12581, -    ["enghecyrillic"]=1189, -    ["enhookcyrillic"]=1224, -    ["enspace"]=8194, -    ["eogonek"]=281, -    ["eokorean"]=12627, -    ["eopen"]=603, -    ["eopenclosed"]=666, -    ["eopenreversed"]=604, -    ["eopenreversedclosed"]=606, -    ["eopenreversedhook"]=605, -    ["eparen"]=9376, -    ["epsilon"]=949, -    ["epsilontonos"]=941, -    ["equal"]=61, -    ["equalmonospace"]=65309, -    ["equalsmall"]=65126, -    ["equalsuperior"]=8316, -    ["equivalence"]=8801, -    ["erbopomofo"]=12582, -    ["ercyrillic"]=1088, -    ["ereversed"]=600, -    ["ereversedcyrillic"]=1101, -    ["escyrillic"]=1089, -    ["esdescendercyrillic"]=1195, -    ["esh"]=643, -    ["eshcurl"]=646, -    ["eshortdeva"]=2318, -    ["eshortvowelsigndeva"]=2374, -    ["eshreversedloop"]=426, -    ["eshsquatreversed"]=645, -    ["esmallhiragana"]=12359, -    ["esmallkatakana"]=12455, -    ["esmallkatakanahalfwidth"]=65386, -    ["estimated"]=8494, -    ["eta"]=951, -    ["etarmenian"]=1384, -    ["etatonos"]=942, -    ["eth"]=240, -    ["etilde"]=7869, -    ["etildebelow"]=7707, -    ["etnahtalefthebrew"]=1425, -    ["eturned"]=477, -    ["eukorean"]=12641, -    ["euro"]=8364, -    ["evowelsignbengali"]=2503, -    ["evowelsigndeva"]=2375, -    ["evowelsigngujarati"]=2759, -    ["exclam"]=33, -    ["exclamarmenian"]=1372, -    ["exclamdbl"]=8252, -    ["exclamdown"]=161, -    ["exclammonospace"]=65281, -    ["ezh"]=658, -    ["ezhcaron"]=495, -    ["ezhcurl"]=659, -    ["ezhreversed"]=441, -    ["ezhtail"]=442, -    ["f"]=102, -    ["fadeva"]=2398, -    ["fagurmukhi"]=2654, -    ["fahrenheit"]=8457, -    ["fathalowarabic"]=1614, -    ["fathatanarabic"]=1611, -    ["fbopomofo"]=12552, -    ["fcircle"]=9429, -    ["fdotaccent"]=7711, -    ["feharabic"]=1601, -    ["feharmenian"]=1414, -    ["fehfinalarabic"]=65234, -    ["fehinitialarabic"]=65235, -    ["fehmedialarabic"]=65236, -    ["feicoptic"]=997, -    ["ff"]=64256, -    ["ffi"]=64259, -    ["ffl"]=64260, -    ["fi"]=64257, -    ["fifteencircle"]=9326, -    ["fifteenparen"]=9346, -    ["fifteenperiod"]=9366, -    ["figuredash"]=8210, -    ["filledbox"]=9632, -    ["filledrect"]=9644, -    ["finalkafdageshhebrew"]=64314, -    ["finalkafshevahebrew"]=1498, -    ["finalmemhebrew"]=1501, -    ["finalnunhebrew"]=1503, -    ["finalpehebrew"]=1507, -    ["finaltsadihebrew"]=1509, -    ["firsttonechinese"]=713, -    ["fisheye"]=9673, -    ["fitacyrillic"]=1139, -    ["five"]=53, -    ["fivebengali"]=2539, -    ["fivecircle"]=9316, -    ["fivecircleinversesansserif"]=10126, -    ["fivedeva"]=2411, -    ["fiveeighths"]=8541, -    ["fivegujarati"]=2795, -    ["fivegurmukhi"]=2667, -    ["fivehackarabic"]=1637, -    ["fivehangzhou"]=12325, -    ["fiveideographicparen"]=12836, -    ["fiveinferior"]=8325, -    ["fivemonospace"]=65301, -    ["fiveparen"]=9336, -    ["fiveperiod"]=9356, -    ["fivepersian"]=1781, -    ["fiveroman"]=8564, -    ["fivesuperior"]=8309, -    ["fivethai"]=3669, -    ["fl"]=64258, -    ["florin"]=402, -    ["fmonospace"]=65350, -    ["fmsquare"]=13209, -    ["fofanthai"]=3615, -    ["fofathai"]=3613, -    ["fongmanthai"]=3663, -    ["four"]=52, -    ["fourbengali"]=2538, -    ["fourcircle"]=9315, -    ["fourcircleinversesansserif"]=10125, -    ["fourdeva"]=2410, -    ["fourgujarati"]=2794, -    ["fourgurmukhi"]=2666, -    ["fourhackarabic"]=1636, -    ["fourhangzhou"]=12324, -    ["fourideographicparen"]=12835, -    ["fourinferior"]=8324, -    ["fourmonospace"]=65300, -    ["fournumeratorbengali"]=2551, -    ["fourparen"]=9335, -    ["fourperiod"]=9355, -    ["fourpersian"]=1780, -    ["fourroman"]=8563, -    ["foursuperior"]=8308, -    ["fourteencircle"]=9325, -    ["fourteenparen"]=9345, -    ["fourteenperiod"]=9365, -    ["fourthai"]=3668, -    ["fourthtonechinese"]=715, -    ["fparen"]=9377, -    ["fraction"]=8260, -    ["franc"]=8355, -    ["g"]=103, -    ["gabengali"]=2455, -    ["gacute"]=501, -    ["gadeva"]=2327, -    ["gafarabic"]=1711, -    ["gaffinalarabic"]=64403, -    ["gafinitialarabic"]=64404, -    ["gafmedialarabic"]=64405, -    ["gagujarati"]=2711, -    ["gagurmukhi"]=2583, -    ["gahiragana"]=12364, -    ["gakatakana"]=12460, -    ["gamma"]=947, -    ["gammalatinsmall"]=611, -    ["gammasuperior"]=736, -    ["gangiacoptic"]=1003, -    ["gbopomofo"]=12557, -    ["gbreve"]=287, -    ["gcaron"]=487, -    ["gcircle"]=9430, -    ["gcircumflex"]=285, -    ["gcommaaccent"]=291, -    ["gdotaccent"]=289, -    ["gecyrillic"]=1075, -    ["gehiragana"]=12370, -    ["gekatakana"]=12466, -    ["geometricallyequal"]=8785, -    ["gereshaccenthebrew"]=1436, -    ["gereshhebrew"]=1523, -    ["gereshmuqdamhebrew"]=1437, -    ["germandbls"]=223, -    ["gershayimaccenthebrew"]=1438, -    ["gershayimhebrew"]=1524, -    ["getamark"]=12307, -    ["ghabengali"]=2456, -    ["ghadarmenian"]=1394, -    ["ghadeva"]=2328, -    ["ghagujarati"]=2712, -    ["ghagurmukhi"]=2584, -    ["ghainarabic"]=1594, -    ["ghainfinalarabic"]=65230, -    ["ghaininitialarabic"]=65231, -    ["ghainmedialarabic"]=65232, -    ["ghemiddlehookcyrillic"]=1173, -    ["ghestrokecyrillic"]=1171, -    ["gheupturncyrillic"]=1169, -    ["ghhadeva"]=2394, -    ["ghhagurmukhi"]=2650, -    ["ghook"]=608, -    ["ghzsquare"]=13203, -    ["gihiragana"]=12366, -    ["gikatakana"]=12462, -    ["gimarmenian"]=1379, -    ["gimeldageshhebrew"]=64306, -    ["gimelhebrew"]=1490, -    ["gjecyrillic"]=1107, -    ["glottalinvertedstroke"]=446, -    ["glottalstop"]=660, -    ["glottalstopinverted"]=662, -    ["glottalstopmod"]=704, -    ["glottalstopreversed"]=661, -    ["glottalstopreversedmod"]=705, -    ["glottalstopreversedsuperior"]=740, -    ["glottalstopstroke"]=673, -    ["glottalstopstrokereversed"]=674, -    ["gmacron"]=7713, -    ["gmonospace"]=65351, -    ["gohiragana"]=12372, -    ["gokatakana"]=12468, -    ["gparen"]=9378, -    ["gpasquare"]=13228, -    ["grave"]=96, -    ["gravebelowcmb"]=790, -    ["gravecomb"]=768, -    ["gravedeva"]=2387, -    ["gravelowmod"]=718, -    ["gravemonospace"]=65344, -    ["gravetonecmb"]=832, -    ["greater"]=62, -    ["greaterequal"]=8805, -    ["greaterequalorless"]=8923, -    ["greatermonospace"]=65310, -    ["greaterorequivalent"]=8819, -    ["greaterorless"]=8823, -    ["greateroverequal"]=8807, -    ["greatersmall"]=65125, -    ["gscript"]=609, -    ["gstroke"]=485, -    ["guhiragana"]=12368, -    ["guillemotleft"]=171, -    ["guillemotright"]=187, -    ["guilsinglleft"]=8249, -    ["guilsinglright"]=8250, -    ["gukatakana"]=12464, -    ["guramusquare"]=13080, -    ["gysquare"]=13257, -    ["h"]=104, -    ["haabkhasiancyrillic"]=1193, -    ["habengali"]=2489, -    ["hadescendercyrillic"]=1203, -    ["hadeva"]=2361, -    ["hagujarati"]=2745, -    ["hagurmukhi"]=2617, -    ["haharabic"]=1581, -    ["hahfinalarabic"]=65186, -    ["hahinitialarabic"]=65187, -    ["hahiragana"]=12399, -    ["hahmedialarabic"]=65188, -    ["haitusquare"]=13098, -    ["hakatakana"]=12495, -    ["hakatakanahalfwidth"]=65418, -    ["halantgurmukhi"]=2637, -    ["hamzasukunarabic"]=1569, -    ["hangulfiller"]=12644, -    ["hardsigncyrillic"]=1098, -    ["harpoonleftbarbup"]=8636, -    ["harpoonrightbarbup"]=8640, -    ["hasquare"]=13258, -    ["hatafpatahwidehebrew"]=1458, -    ["hatafqamatswidehebrew"]=1459, -    ["hatafsegolwidehebrew"]=1457, -    ["hbar"]=295, -    ["hbopomofo"]=12559, -    ["hbrevebelow"]=7723, -    ["hcedilla"]=7721, -    ["hcircle"]=9431, -    ["hcircumflex"]=293, -    ["hdieresis"]=7719, -    ["hdotaccent"]=7715, -    ["hdotbelow"]=7717, -    ["heartsuitblack"]=9829, -    ["heartsuitwhite"]=9825, -    ["hedageshhebrew"]=64308, -    ["hehaltonearabic"]=1729, -    ["heharabic"]=1607, -    ["hehebrew"]=1492, -    ["hehfinalaltonearabic"]=64423, -    ["hehfinalarabic"]=65258, -    ["hehhamzaabovefinalarabic"]=64421, -    ["hehhamzaaboveisolatedarabic"]=64420, -    ["hehinitialaltonearabic"]=64424, -    ["hehinitialarabic"]=65259, -    ["hehiragana"]=12408, -    ["hehmedialaltonearabic"]=64425, -    ["hehmedialarabic"]=65260, -    ["heiseierasquare"]=13179, -    ["hekatakana"]=12504, -    ["hekatakanahalfwidth"]=65421, -    ["hekutaarusquare"]=13110, -    ["henghook"]=615, -    ["herutusquare"]=13113, -    ["hethebrew"]=1495, -    ["hhook"]=614, -    ["hhooksuperior"]=689, -    ["hieuhacirclekorean"]=12923, -    ["hieuhaparenkorean"]=12827, -    ["hieuhcirclekorean"]=12909, -    ["hieuhkorean"]=12622, -    ["hieuhparenkorean"]=12813, -    ["hihiragana"]=12402, -    ["hikatakana"]=12498, -    ["hikatakanahalfwidth"]=65419, -    ["hiriqwidehebrew"]=1460, -    ["hlinebelow"]=7830, -    ["hmonospace"]=65352, -    ["hoarmenian"]=1392, -    ["hohipthai"]=3627, -    ["hohiragana"]=12411, -    ["hokatakana"]=12507, -    ["hokatakanahalfwidth"]=65422, -    ["holamwidehebrew"]=1465, -    ["honokhukthai"]=3630, -    ["hookcmb"]=777, -    ["hookpalatalizedbelowcmb"]=801, -    ["hookretroflexbelowcmb"]=802, -    ["hoonsquare"]=13122, -    ["horicoptic"]=1001, -    ["horizontalbar"]=8213, -    ["horncmb"]=795, -    ["hotsprings"]=9832, -    ["house"]=8962, -    ["hparen"]=9379, -    ["hsuperior"]=688, -    ["hturned"]=613, -    ["huhiragana"]=12405, -    ["huiitosquare"]=13107, -    ["hukatakana"]=12501, -    ["hukatakanahalfwidth"]=65420, -    ["hungarumlaut"]=733, -    ["hungarumlautcmb"]=779, -    ["hv"]=405, -    ["hyphen"]=45, -    ["hyphenmonospace"]=65293, -    ["hyphensmall"]=65123, -    ["hyphentwo"]=8208, -    ["i"]=105, -    ["iacute"]=237, -    ["iacyrillic"]=1103, -    ["ibengali"]=2439, -    ["ibopomofo"]=12583, -    ["ibreve"]=301, -    ["icaron"]=464, -    ["icircle"]=9432, -    ["icircumflex"]=238, -    ["icyrillic"]=1110, -    ["idblgrave"]=521, -    ["ideographearthcircle"]=12943, -    ["ideographfirecircle"]=12939, -    ["ideographicallianceparen"]=12863, -    ["ideographiccallparen"]=12858, -    ["ideographiccentrecircle"]=12965, -    ["ideographicclose"]=12294, -    ["ideographiccomma"]=12289, -    ["ideographiccommaleft"]=65380, -    ["ideographiccongratulationparen"]=12855, -    ["ideographiccorrectcircle"]=12963, -    ["ideographicearthparen"]=12847, -    ["ideographicenterpriseparen"]=12861, -    ["ideographicexcellentcircle"]=12957, -    ["ideographicfestivalparen"]=12864, -    ["ideographicfinancialcircle"]=12950, -    ["ideographicfinancialparen"]=12854, -    ["ideographicfireparen"]=12843, -    ["ideographichaveparen"]=12850, -    ["ideographichighcircle"]=12964, -    ["ideographiciterationmark"]=12293, -    ["ideographiclaborcircle"]=12952, -    ["ideographiclaborparen"]=12856, -    ["ideographicleftcircle"]=12967, -    ["ideographiclowcircle"]=12966, -    ["ideographicmedicinecircle"]=12969, -    ["ideographicmetalparen"]=12846, -    ["ideographicmoonparen"]=12842, -    ["ideographicnameparen"]=12852, -    ["ideographicperiod"]=12290, -    ["ideographicprintcircle"]=12958, -    ["ideographicreachparen"]=12867, -    ["ideographicrepresentparen"]=12857, -    ["ideographicresourceparen"]=12862, -    ["ideographicrightcircle"]=12968, -    ["ideographicsecretcircle"]=12953, -    ["ideographicselfparen"]=12866, -    ["ideographicsocietyparen"]=12851, -    ["ideographicspace"]=12288, -    ["ideographicspecialparen"]=12853, -    ["ideographicstockparen"]=12849, -    ["ideographicstudyparen"]=12859, -    ["ideographicsunparen"]=12848, -    ["ideographicsuperviseparen"]=12860, -    ["ideographicwaterparen"]=12844, -    ["ideographicwoodparen"]=12845, -    ["ideographiczero"]=12295, -    ["ideographmetalcircle"]=12942, -    ["ideographmooncircle"]=12938, -    ["ideographnamecircle"]=12948, -    ["ideographsuncircle"]=12944, -    ["ideographwatercircle"]=12940, -    ["ideographwoodcircle"]=12941, -    ["ideva"]=2311, -    ["idieresis"]=239, -    ["idieresisacute"]=7727, -    ["idieresiscyrillic"]=1253, -    ["idotbelow"]=7883, -    ["iebrevecyrillic"]=1239, -    ["iecyrillic"]=1077, -    ["ieungacirclekorean"]=12917, -    ["ieungaparenkorean"]=12821, -    ["ieungcirclekorean"]=12903, -    ["ieungkorean"]=12615, -    ["ieungparenkorean"]=12807, -    ["igrave"]=236, -    ["igujarati"]=2695, -    ["igurmukhi"]=2567, -    ["ihiragana"]=12356, -    ["ihookabove"]=7881, -    ["iibengali"]=2440, -    ["iicyrillic"]=1080, -    ["iideva"]=2312, -    ["iigujarati"]=2696, -    ["iigurmukhi"]=2568, -    ["iimatragurmukhi"]=2624, -    ["iinvertedbreve"]=523, -    ["iishortcyrillic"]=1081, -    ["iivowelsignbengali"]=2496, -    ["iivowelsigndeva"]=2368, -    ["iivowelsigngujarati"]=2752, -    ["ij"]=307, -    ["ikatakana"]=12452, -    ["ikatakanahalfwidth"]=65394, -    ["ikorean"]=12643, -    ["iluyhebrew"]=1452, -    ["imacron"]=299, -    ["imacroncyrillic"]=1251, -    ["imageorapproximatelyequal"]=8787, -    ["imatragurmukhi"]=2623, -    ["imonospace"]=65353, -    ["increment"]=8710, -    ["infinity"]=8734, -    ["iniarmenian"]=1387, -    ["integral"]=8747, -    ["integralbt"]=8993, -    ["integraltp"]=8992, -    ["intersection"]=8745, -    ["intisquare"]=13061, -    ["invbullet"]=9688, -    ["invsmileface"]=9787, -    ["iocyrillic"]=1105, -    ["iogonek"]=303, -    ["iota"]=953, -    ["iotadieresis"]=970, -    ["iotadieresistonos"]=912, -    ["iotalatin"]=617, -    ["iotatonos"]=943, -    ["iparen"]=9380, -    ["irigurmukhi"]=2674, -    ["ismallhiragana"]=12355, -    ["ismallkatakana"]=12451, -    ["ismallkatakanahalfwidth"]=65384, -    ["issharbengali"]=2554, -    ["istroke"]=616, -    ["iterationhiragana"]=12445, -    ["iterationkatakana"]=12541, -    ["itilde"]=297, -    ["itildebelow"]=7725, -    ["iubopomofo"]=12585, -    ["iucyrillic"]=1102, -    ["ivowelsignbengali"]=2495, -    ["ivowelsigndeva"]=2367, -    ["ivowelsigngujarati"]=2751, -    ["izhitsacyrillic"]=1141, -    ["izhitsadblgravecyrillic"]=1143, -    ["j"]=106, -    ["jaarmenian"]=1393, -    ["jabengali"]=2460, -    ["jadeva"]=2332, -    ["jagujarati"]=2716, -    ["jagurmukhi"]=2588, -    ["jbopomofo"]=12560, -    ["jcaron"]=496, -    ["jcircle"]=9433, -    ["jcircumflex"]=309, -    ["jcrossedtail"]=669, -    ["jdotlessstroke"]=607, -    ["jecyrillic"]=1112, -    ["jeemarabic"]=1580, -    ["jeemfinalarabic"]=65182, -    ["jeeminitialarabic"]=65183, -    ["jeemmedialarabic"]=65184, -    ["jeharabic"]=1688, -    ["jehfinalarabic"]=64395, -    ["jhabengali"]=2461, -    ["jhadeva"]=2333, -    ["jhagujarati"]=2717, -    ["jhagurmukhi"]=2589, -    ["jheharmenian"]=1403, -    ["jis"]=12292, -    ["jmonospace"]=65354, -    ["jparen"]=9381, -    ["jsuperior"]=690, -    ["k"]=107, -    ["kabashkircyrillic"]=1185, -    ["kabengali"]=2453, -    ["kacute"]=7729, -    ["kacyrillic"]=1082, -    ["kadescendercyrillic"]=1179, -    ["kadeva"]=2325, -    ["kafarabic"]=1603, -    ["kafdageshhebrew"]=64315, -    ["kaffinalarabic"]=65242, -    ["kafhebrew"]=1499, -    ["kafinitialarabic"]=65243, -    ["kafmedialarabic"]=65244, -    ["kafrafehebrew"]=64333, -    ["kagujarati"]=2709, -    ["kagurmukhi"]=2581, -    ["kahiragana"]=12363, -    ["kahookcyrillic"]=1220, -    ["kakatakana"]=12459, -    ["kakatakanahalfwidth"]=65398, -    ["kappa"]=954, -    ["kappasymbolgreek"]=1008, -    ["kapyeounmieumkorean"]=12657, -    ["kapyeounphieuphkorean"]=12676, -    ["kapyeounpieupkorean"]=12664, -    ["kapyeounssangpieupkorean"]=12665, -    ["karoriisquare"]=13069, -    ["kasmallkatakana"]=12533, -    ["kasquare"]=13188, -    ["kasraarabic"]=1616, -    ["kasratanarabic"]=1613, -    ["kastrokecyrillic"]=1183, -    ["katahiraprolongmarkhalfwidth"]=65392, -    ["kaverticalstrokecyrillic"]=1181, -    ["kbopomofo"]=12558, -    ["kcalsquare"]=13193, -    ["kcaron"]=489, -    ["kcircle"]=9434, -    ["kcommaaccent"]=311, -    ["kdotbelow"]=7731, -    ["keharmenian"]=1412, -    ["kehiragana"]=12369, -    ["kekatakana"]=12465, -    ["kekatakanahalfwidth"]=65401, -    ["kenarmenian"]=1391, -    ["kesmallkatakana"]=12534, -    ["kgreenlandic"]=312, -    ["khabengali"]=2454, -    ["khacyrillic"]=1093, -    ["khadeva"]=2326, -    ["khagujarati"]=2710, -    ["khagurmukhi"]=2582, -    ["khaharabic"]=1582, -    ["khahfinalarabic"]=65190, -    ["khahinitialarabic"]=65191, -    ["khahmedialarabic"]=65192, -    ["kheicoptic"]=999, -    ["khhadeva"]=2393, -    ["khhagurmukhi"]=2649, -    ["khieukhacirclekorean"]=12920, -    ["khieukhaparenkorean"]=12824, -    ["khieukhcirclekorean"]=12906, -    ["khieukhkorean"]=12619, -    ["khieukhparenkorean"]=12810, -    ["khokhaithai"]=3586, -    ["khokhonthai"]=3589, -    ["khokhuatthai"]=3587, -    ["khokhwaithai"]=3588, -    ["khomutthai"]=3675, -    ["khook"]=409, -    ["khorakhangthai"]=3590, -    ["khzsquare"]=13201, -    ["kihiragana"]=12365, -    ["kikatakana"]=12461, -    ["kikatakanahalfwidth"]=65399, -    ["kiroguramusquare"]=13077, -    ["kiromeetorusquare"]=13078, -    ["kirosquare"]=13076, -    ["kiyeokacirclekorean"]=12910, -    ["kiyeokaparenkorean"]=12814, -    ["kiyeokcirclekorean"]=12896, -    ["kiyeokkorean"]=12593, -    ["kiyeokparenkorean"]=12800, -    ["kiyeoksioskorean"]=12595, -    ["kjecyrillic"]=1116, -    ["klinebelow"]=7733, -    ["klsquare"]=13208, -    ["kmcubedsquare"]=13222, -    ["kmonospace"]=65355, -    ["kmsquaredsquare"]=13218, -    ["kohiragana"]=12371, -    ["kohmsquare"]=13248, -    ["kokaithai"]=3585, -    ["kokatakana"]=12467, -    ["kokatakanahalfwidth"]=65402, -    ["kooposquare"]=13086, -    ["koppacyrillic"]=1153, -    ["koreanstandardsymbol"]=12927, -    ["koroniscmb"]=835, -    ["kparen"]=9382, -    ["kpasquare"]=13226, -    ["ksicyrillic"]=1135, -    ["ktsquare"]=13263, -    ["kturned"]=670, -    ["kuhiragana"]=12367, -    ["kukatakana"]=12463, -    ["kukatakanahalfwidth"]=65400, -    ["kvsquare"]=13240, -    ["kwsquare"]=13246, -    ["l"]=108, -    ["labengali"]=2482, -    ["lacute"]=314, -    ["ladeva"]=2354, -    ["lagujarati"]=2738, -    ["lagurmukhi"]=2610, -    ["lakkhangyaothai"]=3653, -    ["lamaleffinalarabic"]=65276, -    ["lamalefhamzaabovefinalarabic"]=65272, -    ["lamalefhamzaaboveisolatedarabic"]=65271, -    ["lamalefhamzabelowfinalarabic"]=65274, -    ["lamalefhamzabelowisolatedarabic"]=65273, -    ["lamalefisolatedarabic"]=65275, -    ["lamalefmaddaabovefinalarabic"]=65270, -    ["lamalefmaddaaboveisolatedarabic"]=65269, -    ["lamarabic"]=1604, -    ["lambda"]=955, -    ["lambdastroke"]=411, -    ["lameddageshhebrew"]=64316, -    ["lamedholamhebrew"]=1500, -    ["lamfinalarabic"]=65246, -    ["lamhahinitialarabic"]=64714, -    ["lamjeeminitialarabic"]=64713, -    ["lamkhahinitialarabic"]=64715, -    ["lamlamhehisolatedarabic"]=65010, -    ["lammedialarabic"]=65248, -    ["lammeemhahinitialarabic"]=64904, -    ["lammeeminitialarabic"]=64716, -    ["lammeemkhahinitialarabic"]=65247, -    ["largecircle"]=9711, -    ["lbar"]=410, -    ["lbelt"]=620, -    ["lbopomofo"]=12556, -    ["lcaron"]=318, -    ["lcircle"]=9435, -    ["lcircumflexbelow"]=7741, -    ["lcommaaccent"]=316, -    ["ldotaccent"]=320, -    ["ldotbelow"]=7735, -    ["ldotbelowmacron"]=7737, -    ["leftangleabovecmb"]=794, -    ["lefttackbelowcmb"]=792, -    ["less"]=60, -    ["lessequal"]=8804, -    ["lessequalorgreater"]=8922, -    ["lessmonospace"]=65308, -    ["lessorequivalent"]=8818, -    ["lessorgreater"]=8822, -    ["lessoverequal"]=8806, -    ["lesssmall"]=65124, -    ["lezh"]=622, -    ["lfblock"]=9612, -    ["lhookretroflex"]=621, -    ["lira"]=8356, -    ["liwnarmenian"]=1388, -    ["lj"]=457, -    ["ljecyrillic"]=1113, -    ["lladeva"]=2355, -    ["llagujarati"]=2739, -    ["llinebelow"]=7739, -    ["llladeva"]=2356, -    ["llvocalicbengali"]=2529, -    ["llvocalicdeva"]=2401, -    ["llvocalicvowelsignbengali"]=2531, -    ["llvocalicvowelsigndeva"]=2403, -    ["lmiddletilde"]=619, -    ["lmonospace"]=65356, -    ["lmsquare"]=13264, -    ["lochulathai"]=3628, -    ["logicaland"]=8743, -    ["logicalnot"]=172, -    ["logicalor"]=8744, -    ["lolingthai"]=3621, -    ["lowlinecenterline"]=65102, -    ["lowlinecmb"]=818, -    ["lowlinedashed"]=65101, -    ["lozenge"]=9674, -    ["lparen"]=9383, -    ["lslash"]=322, -    ["lsquare"]=8467, -    ["luthai"]=3622, -    ["lvocalicbengali"]=2444, -    ["lvocalicdeva"]=2316, -    ["lvocalicvowelsignbengali"]=2530, -    ["lvocalicvowelsigndeva"]=2402, -    ["lxsquare"]=13267, -    ["m"]=109, -    ["mabengali"]=2478, -    ["macron"]=175, -    ["macronbelowcmb"]=817, -    ["macroncmb"]=772, -    ["macronlowmod"]=717, -    ["macronmonospace"]=65507, -    ["macute"]=7743, -    ["madeva"]=2350, -    ["magujarati"]=2734, -    ["magurmukhi"]=2606, -    ["mahapakhlefthebrew"]=1444, -    ["mahiragana"]=12414, -    ["maichattawathai"]=3659, -    ["maiekthai"]=3656, -    ["maihanakatthai"]=3633, -    ["maitaikhuthai"]=3655, -    ["maithothai"]=3657, -    ["maitrithai"]=3658, -    ["maiyamokthai"]=3654, -    ["makatakana"]=12510, -    ["makatakanahalfwidth"]=65423, -    ["mansyonsquare"]=13127, -    ["maqafhebrew"]=1470, -    ["mars"]=9794, -    ["masoracirclehebrew"]=1455, -    ["masquare"]=13187, -    ["mbopomofo"]=12551, -    ["mbsquare"]=13268, -    ["mcircle"]=9436, -    ["mcubedsquare"]=13221, -    ["mdotaccent"]=7745, -    ["mdotbelow"]=7747, -    ["meemarabic"]=1605, -    ["meemfinalarabic"]=65250, -    ["meeminitialarabic"]=65251, -    ["meemmedialarabic"]=65252, -    ["meemmeeminitialarabic"]=64721, -    ["meemmeemisolatedarabic"]=64584, -    ["meetorusquare"]=13133, -    ["mehiragana"]=12417, -    ["meizierasquare"]=13182, -    ["mekatakana"]=12513, -    ["mekatakanahalfwidth"]=65426, -    ["memdageshhebrew"]=64318, -    ["memhebrew"]=1502, -    ["menarmenian"]=1396, -    ["merkhakefulalefthebrew"]=1446, -    ["merkhalefthebrew"]=1445, -    ["mhook"]=625, -    ["mhzsquare"]=13202, -    ["middledotkatakanahalfwidth"]=65381, -    ["mieumacirclekorean"]=12914, -    ["mieumaparenkorean"]=12818, -    ["mieumcirclekorean"]=12900, -    ["mieumkorean"]=12609, -    ["mieumpansioskorean"]=12656, -    ["mieumparenkorean"]=12804, -    ["mieumpieupkorean"]=12654, -    ["mieumsioskorean"]=12655, -    ["mihiragana"]=12415, -    ["mikatakana"]=12511, -    ["mikatakanahalfwidth"]=65424, -    ["minus"]=8722, -    ["minusbelowcmb"]=800, -    ["minuscircle"]=8854, -    ["minusmod"]=727, -    ["minusplus"]=8723, -    ["minute"]=8242, -    ["miribaarusquare"]=13130, -    ["mirisquare"]=13129, -    ["mlonglegturned"]=624, -    ["mlsquare"]=13206, -    ["mmcubedsquare"]=13219, -    ["mmonospace"]=65357, -    ["mmsquaredsquare"]=13215, -    ["mohiragana"]=12418, -    ["mohmsquare"]=13249, -    ["mokatakana"]=12514, -    ["mokatakanahalfwidth"]=65427, -    ["molsquare"]=13270, -    ["momathai"]=3617, -    ["moverssquare"]=13223, -    ["moverssquaredsquare"]=13224, -    ["mparen"]=9384, -    ["mpasquare"]=13227, -    ["mssquare"]=13235, -    ["mturned"]=623, -    ["mu1"]=181, -    ["muasquare"]=13186, -    ["muchgreater"]=8811, -    ["muchless"]=8810, -    ["mufsquare"]=13196, -    ["mugreek"]=956, -    ["mugsquare"]=13197, -    ["muhiragana"]=12416, -    ["mukatakana"]=12512, -    ["mukatakanahalfwidth"]=65425, -    ["mulsquare"]=13205, -    ["multiply"]=215, -    ["mumsquare"]=13211, -    ["munahlefthebrew"]=1443, -    ["musicalnote"]=9834, -    ["musicalnotedbl"]=9835, -    ["musicflatsign"]=9837, -    ["musicsharpsign"]=9839, -    ["mussquare"]=13234, -    ["muvsquare"]=13238, -    ["muwsquare"]=13244, -    ["mvmegasquare"]=13241, -    ["mvsquare"]=13239, -    ["mwmegasquare"]=13247, -    ["mwsquare"]=13245, -    ["n"]=110, -    ["nabengali"]=2472, -    ["nabla"]=8711, -    ["nacute"]=324, -    ["nadeva"]=2344, -    ["nagujarati"]=2728, -    ["nagurmukhi"]=2600, -    ["nahiragana"]=12394, -    ["nakatakana"]=12490, -    ["nakatakanahalfwidth"]=65413, -    ["nasquare"]=13185, -    ["nbopomofo"]=12555, -    ["ncaron"]=328, -    ["ncircle"]=9437, -    ["ncircumflexbelow"]=7755, -    ["ncommaaccent"]=326, -    ["ndotaccent"]=7749, -    ["ndotbelow"]=7751, -    ["nehiragana"]=12397, -    ["nekatakana"]=12493, -    ["nekatakanahalfwidth"]=65416, -    ["nfsquare"]=13195, -    ["ngabengali"]=2457, -    ["ngadeva"]=2329, -    ["ngagujarati"]=2713, -    ["ngagurmukhi"]=2585, -    ["ngonguthai"]=3591, -    ["nhiragana"]=12435, -    ["nhookleft"]=626, -    ["nhookretroflex"]=627, -    ["nieunacirclekorean"]=12911, -    ["nieunaparenkorean"]=12815, -    ["nieuncieuckorean"]=12597, -    ["nieuncirclekorean"]=12897, -    ["nieunhieuhkorean"]=12598, -    ["nieunkorean"]=12596, -    ["nieunpansioskorean"]=12648, -    ["nieunparenkorean"]=12801, -    ["nieunsioskorean"]=12647, -    ["nieuntikeutkorean"]=12646, -    ["nihiragana"]=12395, -    ["nikatakana"]=12491, -    ["nikatakanahalfwidth"]=65414, -    ["nikhahitthai"]=3661, -    ["nine"]=57, -    ["ninebengali"]=2543, -    ["ninecircle"]=9320, -    ["ninecircleinversesansserif"]=10130, -    ["ninedeva"]=2415, -    ["ninegujarati"]=2799, -    ["ninegurmukhi"]=2671, -    ["ninehackarabic"]=1641, -    ["ninehangzhou"]=12329, -    ["nineideographicparen"]=12840, -    ["nineinferior"]=8329, -    ["ninemonospace"]=65305, -    ["nineparen"]=9340, -    ["nineperiod"]=9360, -    ["ninepersian"]=1785, -    ["nineroman"]=8568, -    ["ninesuperior"]=8313, -    ["nineteencircle"]=9330, -    ["nineteenparen"]=9350, -    ["nineteenperiod"]=9370, -    ["ninethai"]=3673, -    ["nj"]=460, -    ["njecyrillic"]=1114, -    ["nkatakana"]=12531, -    ["nkatakanahalfwidth"]=65437, -    ["nlegrightlong"]=414, -    ["nlinebelow"]=7753, -    ["nmonospace"]=65358, -    ["nmsquare"]=13210, -    ["nnabengali"]=2467, -    ["nnadeva"]=2339, -    ["nnagujarati"]=2723, -    ["nnagurmukhi"]=2595, -    ["nnnadeva"]=2345, -    ["nohiragana"]=12398, -    ["nokatakana"]=12494, -    ["nokatakanahalfwidth"]=65417, -    ["nonbreakingspace"]=160, -    ["nonenthai"]=3603, -    ["nonuthai"]=3609, -    ["noonarabic"]=1606, -    ["noonfinalarabic"]=65254, -    ["noonghunnaarabic"]=1722, -    ["noonghunnafinalarabic"]=64415, -    ["nooninitialarabic"]=65255, -    ["noonjeeminitialarabic"]=64722, -    ["noonjeemisolatedarabic"]=64587, -    ["noonmedialarabic"]=65256, -    ["noonmeeminitialarabic"]=64725, -    ["noonmeemisolatedarabic"]=64590, -    ["noonnoonfinalarabic"]=64653, -    ["notcontains"]=8716, -    ["notelementof"]=8713, -    ["notequal"]=8800, -    ["notgreater"]=8815, -    ["notgreaternorequal"]=8817, -    ["notgreaternorless"]=8825, -    ["notidentical"]=8802, -    ["notless"]=8814, -    ["notlessnorequal"]=8816, -    ["notparallel"]=8742, -    ["notprecedes"]=8832, -    ["notsubset"]=8836, -    ["notsucceeds"]=8833, -    ["notsuperset"]=8837, -    ["nowarmenian"]=1398, -    ["nparen"]=9385, -    ["nssquare"]=13233, -    ["nsuperior"]=8319, -    ["ntilde"]=241, -    ["nu"]=957, -    ["nuhiragana"]=12396, -    ["nukatakana"]=12492, -    ["nukatakanahalfwidth"]=65415, -    ["nuktabengali"]=2492, -    ["nuktadeva"]=2364, -    ["nuktagujarati"]=2748, -    ["nuktagurmukhi"]=2620, -    ["numbersign"]=35, -    ["numbersignmonospace"]=65283, -    ["numbersignsmall"]=65119, -    ["numeralsigngreek"]=884, -    ["numeralsignlowergreek"]=885, -    ["numero"]=8470, -    ["nundageshhebrew"]=64320, -    ["nunhebrew"]=1504, -    ["nvsquare"]=13237, -    ["nwsquare"]=13243, -    ["nyabengali"]=2462, -    ["nyadeva"]=2334, -    ["nyagujarati"]=2718, -    ["nyagurmukhi"]=2590, -    ["o"]=111, -    ["oacute"]=243, -    ["oangthai"]=3629, -    ["obarred"]=629, -    ["obarredcyrillic"]=1257, -    ["obarreddieresiscyrillic"]=1259, -    ["obengali"]=2451, -    ["obopomofo"]=12571, -    ["obreve"]=335, -    ["ocandradeva"]=2321, -    ["ocandragujarati"]=2705, -    ["ocandravowelsigndeva"]=2377, -    ["ocandravowelsigngujarati"]=2761, -    ["ocaron"]=466, -    ["ocircle"]=9438, -    ["ocircumflex"]=244, -    ["ocircumflexacute"]=7889, -    ["ocircumflexdotbelow"]=7897, -    ["ocircumflexgrave"]=7891, -    ["ocircumflexhookabove"]=7893, -    ["ocircumflextilde"]=7895, -    ["ocyrillic"]=1086, -    ["odblgrave"]=525, -    ["odeva"]=2323, -    ["odieresis"]=246, -    ["odieresiscyrillic"]=1255, -    ["odotbelow"]=7885, -    ["oe"]=339, -    ["oekorean"]=12634, -    ["ogonek"]=731, -    ["ogonekcmb"]=808, -    ["ograve"]=242, -    ["ogujarati"]=2707, -    ["oharmenian"]=1413, -    ["ohiragana"]=12362, -    ["ohookabove"]=7887, -    ["ohorn"]=417, -    ["ohornacute"]=7899, -    ["ohorndotbelow"]=7907, -    ["ohorngrave"]=7901, -    ["ohornhookabove"]=7903, -    ["ohorntilde"]=7905, -    ["ohungarumlaut"]=337, -    ["oi"]=419, -    ["oinvertedbreve"]=527, -    ["okatakana"]=12458, -    ["okatakanahalfwidth"]=65397, -    ["okorean"]=12631, -    ["olehebrew"]=1451, -    ["omacron"]=333, -    ["omacronacute"]=7763, -    ["omacrongrave"]=7761, -    ["omdeva"]=2384, -    ["omega"]=969, -    ["omegacyrillic"]=1121, -    ["omegalatinclosed"]=631, -    ["omegaroundcyrillic"]=1147, -    ["omegatitlocyrillic"]=1149, -    ["omegatonos"]=974, -    ["omgujarati"]=2768, -    ["omicron"]=959, -    ["omicrontonos"]=972, -    ["omonospace"]=65359, -    ["one"]=49, -    ["onebengali"]=2535, -    ["onecircle"]=9312, -    ["onecircleinversesansserif"]=10122, -    ["onedeva"]=2407, -    ["onedotenleader"]=8228, -    ["oneeighth"]=8539, -    ["onegujarati"]=2791, -    ["onegurmukhi"]=2663, -    ["onehackarabic"]=1633, -    ["onehalf"]=189, -    ["onehangzhou"]=12321, -    ["oneideographicparen"]=12832, -    ["oneinferior"]=8321, -    ["onemonospace"]=65297, -    ["onenumeratorbengali"]=2548, -    ["oneparen"]=9332, -    ["oneperiod"]=9352, -    ["onepersian"]=1777, -    ["onequarter"]=188, -    ["oneroman"]=8560, -    ["onesuperior"]=185, -    ["onethai"]=3665, -    ["onethird"]=8531, -    ["oogonek"]=491, -    ["oogonekmacron"]=493, -    ["oogurmukhi"]=2579, -    ["oomatragurmukhi"]=2635, -    ["oopen"]=596, -    ["oparen"]=9386, -    ["option"]=8997, -    ["ordfeminine"]=170, -    ["ordmasculine"]=186, -    ["oshortdeva"]=2322, -    ["oshortvowelsigndeva"]=2378, -    ["oslash"]=248, -    ["osmallhiragana"]=12361, -    ["osmallkatakana"]=12457, -    ["osmallkatakanahalfwidth"]=65387, -    ["ostrokeacute"]=511, -    ["otcyrillic"]=1151, -    ["otilde"]=245, -    ["otildeacute"]=7757, -    ["otildedieresis"]=7759, -    ["oubopomofo"]=12577, -    ["overline"]=8254, -    ["overlinecenterline"]=65098, -    ["overlinecmb"]=773, -    ["overlinedashed"]=65097, -    ["overlinedblwavy"]=65100, -    ["overlinewavy"]=65099, -    ["ovowelsignbengali"]=2507, -    ["ovowelsigndeva"]=2379, -    ["ovowelsigngujarati"]=2763, -    ["p"]=112, -    ["paampssquare"]=13184, -    ["paasentosquare"]=13099, -    ["pabengali"]=2474, -    ["pacute"]=7765, -    ["padeva"]=2346, -    ["pagedown"]=8671, -    ["pageup"]=8670, -    ["pagujarati"]=2730, -    ["pagurmukhi"]=2602, -    ["pahiragana"]=12401, -    ["paiyannoithai"]=3631, -    ["pakatakana"]=12497, -    ["palatalizationcyrilliccmb"]=1156, -    ["palochkacyrillic"]=1216, -    ["pansioskorean"]=12671, -    ["paragraph"]=182, -    ["parallel"]=8741, -    ["parenleft"]=40, -    ["parenleftaltonearabic"]=64830, -    ["parenleftinferior"]=8333, -    ["parenleftmonospace"]=65288, -    ["parenleftsmall"]=65113, -    ["parenleftsuperior"]=8317, -    ["parenleftvertical"]=65077, -    ["parenright"]=41, -    ["parenrightaltonearabic"]=64831, -    ["parenrightinferior"]=8334, -    ["parenrightmonospace"]=65289, -    ["parenrightsmall"]=65114, -    ["parenrightsuperior"]=8318, -    ["parenrightvertical"]=65078, -    ["partialdiff"]=8706, -    ["paseqhebrew"]=1472, -    ["pashtahebrew"]=1433, -    ["pasquare"]=13225, -    ["patahwidehebrew"]=1463, -    ["pazerhebrew"]=1441, -    ["pbopomofo"]=12550, -    ["pcircle"]=9439, -    ["pdotaccent"]=7767, -    ["pecyrillic"]=1087, -    ["pedageshhebrew"]=64324, -    ["peezisquare"]=13115, -    ["pefinaldageshhebrew"]=64323, -    ["peharabic"]=1662, -    ["peharmenian"]=1402, -    ["pehebrew"]=1508, -    ["pehfinalarabic"]=64343, -    ["pehinitialarabic"]=64344, -    ["pehiragana"]=12410, -    ["pehmedialarabic"]=64345, -    ["pekatakana"]=12506, -    ["pemiddlehookcyrillic"]=1191, -    ["perafehebrew"]=64334, -    ["percent"]=37, -    ["percentarabic"]=1642, -    ["percentmonospace"]=65285, -    ["percentsmall"]=65130, -    ["period"]=46, -    ["periodarmenian"]=1417, -    ["periodcentered"]=183, -    ["periodhalfwidth"]=65377, -    ["periodmonospace"]=65294, -    ["periodsmall"]=65106, -    ["perispomenigreekcmb"]=834, -    ["perpendicular"]=8869, -    ["perthousand"]=8240, -    ["peseta"]=8359, -    ["pfsquare"]=13194, -    ["phabengali"]=2475, -    ["phadeva"]=2347, -    ["phagujarati"]=2731, -    ["phagurmukhi"]=2603, -    ["phi"]=966, -    ["phieuphacirclekorean"]=12922, -    ["phieuphaparenkorean"]=12826, -    ["phieuphcirclekorean"]=12908, -    ["phieuphkorean"]=12621, -    ["phieuphparenkorean"]=12812, -    ["philatin"]=632, -    ["phinthuthai"]=3642, -    ["phisymbolgreek"]=981, -    ["phook"]=421, -    ["phophanthai"]=3614, -    ["phophungthai"]=3612, -    ["phosamphaothai"]=3616, -    ["pi"]=960, -    ["pieupacirclekorean"]=12915, -    ["pieupaparenkorean"]=12819, -    ["pieupcieuckorean"]=12662, -    ["pieupcirclekorean"]=12901, -    ["pieupkiyeokkorean"]=12658, -    ["pieupkorean"]=12610, -    ["pieupparenkorean"]=12805, -    ["pieupsioskiyeokkorean"]=12660, -    ["pieupsioskorean"]=12612, -    ["pieupsiostikeutkorean"]=12661, -    ["pieupthieuthkorean"]=12663, -    ["pieuptikeutkorean"]=12659, -    ["pihiragana"]=12404, -    ["pikatakana"]=12500, -    ["pisymbolgreek"]=982, -    ["piwrarmenian"]=1411, -    ["plus"]=43, -    ["plusbelowcmb"]=799, -    ["pluscircle"]=8853, -    ["plusminus"]=177, -    ["plusmod"]=726, -    ["plusmonospace"]=65291, -    ["plussmall"]=65122, -    ["plussuperior"]=8314, -    ["pmonospace"]=65360, -    ["pmsquare"]=13272, -    ["pohiragana"]=12413, -    ["pointingindexdownwhite"]=9759, -    ["pointingindexleftwhite"]=9756, -    ["pointingindexrightwhite"]=9758, -    ["pointingindexupwhite"]=9757, -    ["pokatakana"]=12509, -    ["poplathai"]=3611, -    ["postalmark"]=12306, -    ["postalmarkface"]=12320, -    ["pparen"]=9387, -    ["precedes"]=8826, -    ["prescription"]=8478, -    ["primemod"]=697, -    ["primereversed"]=8245, -    ["product"]=8719, -    ["projective"]=8965, -    ["prolongedkana"]=12540, -    ["propellor"]=8984, -    ["proportion"]=8759, -    ["proportional"]=8733, -    ["psi"]=968, -    ["psicyrillic"]=1137, -    ["psilipneumatacyrilliccmb"]=1158, -    ["pssquare"]=13232, -    ["puhiragana"]=12407, -    ["pukatakana"]=12503, -    ["pvsquare"]=13236, -    ["pwsquare"]=13242, -    ["q"]=113, -    ["qadeva"]=2392, -    ["qadmahebrew"]=1448, -    ["qafarabic"]=1602, -    ["qaffinalarabic"]=65238, -    ["qafinitialarabic"]=65239, -    ["qafmedialarabic"]=65240, -    ["qamatswidehebrew"]=1464, -    ["qarneyparahebrew"]=1439, -    ["qbopomofo"]=12561, -    ["qcircle"]=9440, -    ["qhook"]=672, -    ["qmonospace"]=65361, -    ["qofdageshhebrew"]=64327, -    ["qoftserehebrew"]=1511, -    ["qparen"]=9388, -    ["quarternote"]=9833, -    ["qubutswidehebrew"]=1467, -    ["question"]=63, -    ["questionarabic"]=1567, -    ["questionarmenian"]=1374, -    ["questiondown"]=191, -    ["questiongreek"]=894, -    ["questionmonospace"]=65311, -    ["quotedbl"]=34, -    ["quotedblbase"]=8222, -    ["quotedblleft"]=8220, -    ["quotedblmonospace"]=65282, -    ["quotedblprime"]=12318, -    ["quotedblprimereversed"]=12317, -    ["quotedblright"]=8221, -    ["quoteleft"]=8216, -    ["quotereversed"]=8219, -    ["quoteright"]=8217, -    ["quoterightn"]=329, -    ["quotesinglbase"]=8218, -    ["quotesingle"]=39, -    ["quotesinglemonospace"]=65287, -    ["r"]=114, -    ["raarmenian"]=1404, -    ["rabengali"]=2480, -    ["racute"]=341, -    ["radeva"]=2352, -    ["radical"]=8730, -    ["radoverssquare"]=13230, -    ["radoverssquaredsquare"]=13231, -    ["radsquare"]=13229, -    ["rafehebrew"]=1471, -    ["ragujarati"]=2736, -    ["ragurmukhi"]=2608, -    ["rahiragana"]=12425, -    ["rakatakana"]=12521, -    ["rakatakanahalfwidth"]=65431, -    ["ralowerdiagonalbengali"]=2545, -    ["ramiddlediagonalbengali"]=2544, -    ["ramshorn"]=612, -    ["ratio"]=8758, -    ["rbopomofo"]=12566, -    ["rcaron"]=345, -    ["rcircle"]=9441, -    ["rcommaaccent"]=343, -    ["rdblgrave"]=529, -    ["rdotaccent"]=7769, -    ["rdotbelow"]=7771, -    ["rdotbelowmacron"]=7773, -    ["referencemark"]=8251, -    ["registered"]=174, -    ["reharmenian"]=1408, -    ["rehfinalarabic"]=65198, -    ["rehiragana"]=12428, -    ["rehyehaleflamarabic"]=1585, -    ["rekatakana"]=12524, -    ["rekatakanahalfwidth"]=65434, -    ["reshdageshhebrew"]=64328, -    ["reshtserehebrew"]=1512, -    ["reversedtilde"]=8765, -    ["reviamugrashhebrew"]=1431, -    ["revlogicalnot"]=8976, -    ["rfishhook"]=638, -    ["rfishhookreversed"]=639, -    ["rhabengali"]=2525, -    ["rhadeva"]=2397, -    ["rho"]=961, -    ["rhook"]=637, -    ["rhookturned"]=635, -    ["rhookturnedsuperior"]=693, -    ["rhosymbolgreek"]=1009, -    ["rhotichookmod"]=734, -    ["rieulacirclekorean"]=12913, -    ["rieulaparenkorean"]=12817, -    ["rieulcirclekorean"]=12899, -    ["rieulhieuhkorean"]=12608, -    ["rieulkiyeokkorean"]=12602, -    ["rieulkiyeoksioskorean"]=12649, -    ["rieulkorean"]=12601, -    ["rieulmieumkorean"]=12603, -    ["rieulpansioskorean"]=12652, -    ["rieulparenkorean"]=12803, -    ["rieulphieuphkorean"]=12607, -    ["rieulpieupkorean"]=12604, -    ["rieulpieupsioskorean"]=12651, -    ["rieulsioskorean"]=12605, -    ["rieulthieuthkorean"]=12606, -    ["rieultikeutkorean"]=12650, -    ["rieulyeorinhieuhkorean"]=12653, -    ["rightangle"]=8735, -    ["righttackbelowcmb"]=793, -    ["righttriangle"]=8895, -    ["rihiragana"]=12426, -    ["rikatakana"]=12522, -    ["rikatakanahalfwidth"]=65432, -    ["ring"]=730, -    ["ringbelowcmb"]=805, -    ["ringcmb"]=778, -    ["ringhalfleft"]=703, -    ["ringhalfleftarmenian"]=1369, -    ["ringhalfleftbelowcmb"]=796, -    ["ringhalfleftcentered"]=723, -    ["ringhalfright"]=702, -    ["ringhalfrightbelowcmb"]=825, -    ["ringhalfrightcentered"]=722, -    ["rinvertedbreve"]=531, -    ["rittorusquare"]=13137, -    ["rlinebelow"]=7775, -    ["rlongleg"]=636, -    ["rlonglegturned"]=634, -    ["rmonospace"]=65362, -    ["rohiragana"]=12429, -    ["rokatakana"]=12525, -    ["rokatakanahalfwidth"]=65435, -    ["roruathai"]=3619, -    ["rparen"]=9389, -    ["rrabengali"]=2524, -    ["rradeva"]=2353, -    ["rragurmukhi"]=2652, -    ["rreharabic"]=1681, -    ["rrehfinalarabic"]=64397, -    ["rrvocalicbengali"]=2528, -    ["rrvocalicdeva"]=2400, -    ["rrvocalicgujarati"]=2784, -    ["rrvocalicvowelsignbengali"]=2500, -    ["rrvocalicvowelsigndeva"]=2372, -    ["rrvocalicvowelsigngujarati"]=2756, -    ["rtblock"]=9616, -    ["rturned"]=633, -    ["rturnedsuperior"]=692, -    ["ruhiragana"]=12427, -    ["rukatakana"]=12523, -    ["rukatakanahalfwidth"]=65433, -    ["rupeemarkbengali"]=2546, -    ["rupeesignbengali"]=2547, -    ["ruthai"]=3620, -    ["rvocalicbengali"]=2443, -    ["rvocalicdeva"]=2315, -    ["rvocalicgujarati"]=2699, -    ["rvocalicvowelsignbengali"]=2499, -    ["rvocalicvowelsigndeva"]=2371, -    ["rvocalicvowelsigngujarati"]=2755, -    ["s"]=115, -    ["sabengali"]=2488, -    ["sacute"]=347, -    ["sacutedotaccent"]=7781, -    ["sadarabic"]=1589, -    ["sadeva"]=2360, -    ["sadfinalarabic"]=65210, -    ["sadinitialarabic"]=65211, -    ["sadmedialarabic"]=65212, -    ["sagujarati"]=2744, -    ["sagurmukhi"]=2616, -    ["sahiragana"]=12373, -    ["sakatakana"]=12469, -    ["sakatakanahalfwidth"]=65403, -    ["sallallahoualayhewasallamarabic"]=65018, -    ["samekhdageshhebrew"]=64321, -    ["samekhhebrew"]=1505, -    ["saraaathai"]=3634, -    ["saraaethai"]=3649, -    ["saraaimaimalaithai"]=3652, -    ["saraaimaimuanthai"]=3651, -    ["saraamthai"]=3635, -    ["saraathai"]=3632, -    ["saraethai"]=3648, -    ["saraiithai"]=3637, -    ["saraithai"]=3636, -    ["saraothai"]=3650, -    ["saraueethai"]=3639, -    ["sarauethai"]=3638, -    ["sarauthai"]=3640, -    ["sarauuthai"]=3641, -    ["sbopomofo"]=12569, -    ["scaron"]=353, -    ["scarondotaccent"]=7783, -    ["scedilla"]=351, -    ["schwa"]=601, -    ["schwacyrillic"]=1241, -    ["schwadieresiscyrillic"]=1243, -    ["schwahook"]=602, -    ["scircle"]=9442, -    ["scircumflex"]=349, -    ["scommaaccent"]=537, -    ["sdotaccent"]=7777, -    ["sdotbelow"]=7779, -    ["sdotbelowdotaccent"]=7785, -    ["seagullbelowcmb"]=828, -    ["second"]=8243, -    ["secondtonechinese"]=714, -    ["section"]=167, -    ["seenarabic"]=1587, -    ["seenfinalarabic"]=65202, -    ["seeninitialarabic"]=65203, -    ["seenmedialarabic"]=65204, -    ["segoltahebrew"]=1426, -    ["segolwidehebrew"]=1462, -    ["seharmenian"]=1405, -    ["sehiragana"]=12379, -    ["sekatakana"]=12475, -    ["sekatakanahalfwidth"]=65406, -    ["semicolon"]=59, -    ["semicolonarabic"]=1563, -    ["semicolonmonospace"]=65307, -    ["semicolonsmall"]=65108, -    ["semivoicedmarkkana"]=12444, -    ["semivoicedmarkkanahalfwidth"]=65439, -    ["sentisquare"]=13090, -    ["sentosquare"]=13091, -    ["seven"]=55, -    ["sevenbengali"]=2541, -    ["sevencircle"]=9318, -    ["sevencircleinversesansserif"]=10128, -    ["sevendeva"]=2413, -    ["seveneighths"]=8542, -    ["sevengujarati"]=2797, -    ["sevengurmukhi"]=2669, -    ["sevenhackarabic"]=1639, -    ["sevenhangzhou"]=12327, -    ["sevenideographicparen"]=12838, -    ["seveninferior"]=8327, -    ["sevenmonospace"]=65303, -    ["sevenparen"]=9338, -    ["sevenperiod"]=9358, -    ["sevenpersian"]=1783, -    ["sevenroman"]=8566, -    ["sevensuperior"]=8311, -    ["seventeencircle"]=9328, -    ["seventeenparen"]=9348, -    ["seventeenperiod"]=9368, -    ["seventhai"]=3671, -    ["shaarmenian"]=1399, -    ["shabengali"]=2486, -    ["shacyrillic"]=1096, -    ["shaddadammaarabic"]=64609, -    ["shaddadammatanarabic"]=64606, -    ["shaddafathaarabic"]=64608, -    ["shaddafathatanarabic"]=1617, -    ["shaddakasraarabic"]=64610, -    ["shaddakasratanarabic"]=64607, -    ["shadedark"]=9619, -    ["shadelight"]=9617, -    ["shademedium"]=9618, -    ["shadeva"]=2358, -    ["shagujarati"]=2742, -    ["shagurmukhi"]=2614, -    ["shalshelethebrew"]=1427, -    ["shbopomofo"]=12565, -    ["shchacyrillic"]=1097, -    ["sheenarabic"]=1588, -    ["sheenfinalarabic"]=65206, -    ["sheeninitialarabic"]=65207, -    ["sheenmedialarabic"]=65208, -    ["sheicoptic"]=995, -    ["sheqelhebrew"]=8362, -    ["shevawidehebrew"]=1456, -    ["shhacyrillic"]=1211, -    ["shimacoptic"]=1005, -    ["shindageshhebrew"]=64329, -    ["shindageshshindothebrew"]=64300, -    ["shindageshsindothebrew"]=64301, -    ["shindothebrew"]=1473, -    ["shinhebrew"]=1513, -    ["shinshindothebrew"]=64298, -    ["shinsindothebrew"]=64299, -    ["shook"]=642, -    ["sigma"]=963, -    ["sigmafinal"]=962, -    ["sigmalunatesymbolgreek"]=1010, -    ["sihiragana"]=12375, -    ["sikatakana"]=12471, -    ["sikatakanahalfwidth"]=65404, -    ["siluqlefthebrew"]=1469, -    ["sindothebrew"]=1474, -    ["siosacirclekorean"]=12916, -    ["siosaparenkorean"]=12820, -    ["sioscieuckorean"]=12670, -    ["sioscirclekorean"]=12902, -    ["sioskiyeokkorean"]=12666, -    ["sioskorean"]=12613, -    ["siosnieunkorean"]=12667, -    ["siosparenkorean"]=12806, -    ["siospieupkorean"]=12669, -    ["siostikeutkorean"]=12668, -    ["six"]=54, -    ["sixbengali"]=2540, -    ["sixcircle"]=9317, -    ["sixcircleinversesansserif"]=10127, -    ["sixdeva"]=2412, -    ["sixgujarati"]=2796, -    ["sixgurmukhi"]=2668, -    ["sixhackarabic"]=1638, -    ["sixhangzhou"]=12326, -    ["sixideographicparen"]=12837, -    ["sixinferior"]=8326, -    ["sixmonospace"]=65302, -    ["sixparen"]=9337, -    ["sixperiod"]=9357, -    ["sixpersian"]=1782, -    ["sixroman"]=8565, -    ["sixsuperior"]=8310, -    ["sixteencircle"]=9327, -    ["sixteencurrencydenominatorbengali"]=2553, -    ["sixteenparen"]=9347, -    ["sixteenperiod"]=9367, -    ["sixthai"]=3670, -    ["slash"]=47, -    ["slashmonospace"]=65295, -    ["slong"]=383, -    ["slongdotaccent"]=7835, -    ["smonospace"]=65363, -    ["sofpasuqhebrew"]=1475, -    ["softhyphen"]=173, -    ["softsigncyrillic"]=1100, -    ["sohiragana"]=12381, -    ["sokatakana"]=12477, -    ["sokatakanahalfwidth"]=65407, -    ["soliduslongoverlaycmb"]=824, -    ["solidusshortoverlaycmb"]=823, -    ["sorusithai"]=3625, -    ["sosalathai"]=3624, -    ["sosothai"]=3595, -    ["sosuathai"]=3626, -    ["space"]=32, -    ["spadesuitblack"]=9824, -    ["spadesuitwhite"]=9828, -    ["sparen"]=9390, -    ["squarebelowcmb"]=827, -    ["squarecc"]=13252, -    ["squarecm"]=13213, -    ["squarediagonalcrosshatchfill"]=9641, -    ["squarehorizontalfill"]=9636, -    ["squarekg"]=13199, -    ["squarekm"]=13214, -    ["squarekmcapital"]=13262, -    ["squareln"]=13265, -    ["squarelog"]=13266, -    ["squaremg"]=13198, -    ["squaremil"]=13269, -    ["squaremm"]=13212, -    ["squaremsquared"]=13217, -    ["squareorthogonalcrosshatchfill"]=9638, -    ["squareupperlefttolowerrightfill"]=9639, -    ["squareupperrighttolowerleftfill"]=9640, -    ["squareverticalfill"]=9637, -    ["squarewhitewithsmallblack"]=9635, -    ["srsquare"]=13275, -    ["ssabengali"]=2487, -    ["ssadeva"]=2359, -    ["ssagujarati"]=2743, -    ["ssangcieuckorean"]=12617, -    ["ssanghieuhkorean"]=12677, -    ["ssangieungkorean"]=12672, -    ["ssangkiyeokkorean"]=12594, -    ["ssangnieunkorean"]=12645, -    ["ssangpieupkorean"]=12611, -    ["ssangsioskorean"]=12614, -    ["ssangtikeutkorean"]=12600, -    ["sterling"]=163, -    ["sterlingmonospace"]=65505, -    ["strokelongoverlaycmb"]=822, -    ["strokeshortoverlaycmb"]=821, -    ["subset"]=8834, -    ["subsetnotequal"]=8842, -    ["subsetorequal"]=8838, -    ["succeeds"]=8827, -    ["suchthat"]=8715, -    ["suhiragana"]=12377, -    ["sukatakana"]=12473, -    ["sukatakanahalfwidth"]=65405, -    ["sukunarabic"]=1618, -    ["summation"]=8721, -    ["sun"]=9788, -    ["superset"]=8835, -    ["supersetnotequal"]=8843, -    ["supersetorequal"]=8839, -    ["svsquare"]=13276, -    ["syouwaerasquare"]=13180, -    ["t"]=116, -    ["tabengali"]=2468, -    ["tackdown"]=8868, -    ["tackleft"]=8867, -    ["tadeva"]=2340, -    ["tagujarati"]=2724, -    ["tagurmukhi"]=2596, -    ["taharabic"]=1591, -    ["tahfinalarabic"]=65218, -    ["tahinitialarabic"]=65219, -    ["tahiragana"]=12383, -    ["tahmedialarabic"]=65220, -    ["taisyouerasquare"]=13181, -    ["takatakana"]=12479, -    ["takatakanahalfwidth"]=65408, -    ["tatweelarabic"]=1600, -    ["tau"]=964, -    ["tavdageshhebrew"]=64330, -    ["tavhebrew"]=1514, -    ["tbar"]=359, -    ["tbopomofo"]=12554, -    ["tcaron"]=357, -    ["tccurl"]=680, -    ["tcheharabic"]=1670, -    ["tchehfinalarabic"]=64379, -    ["tchehmedialarabic"]=64381, -    ["tchehmeeminitialarabic"]=64380, -    ["tcircle"]=9443, -    ["tcircumflexbelow"]=7793, -    ["tcommaaccent"]=355, -    ["tdieresis"]=7831, -    ["tdotaccent"]=7787, -    ["tdotbelow"]=7789, -    ["tecyrillic"]=1090, -    ["tedescendercyrillic"]=1197, -    ["teharabic"]=1578, -    ["tehfinalarabic"]=65174, -    ["tehhahinitialarabic"]=64674, -    ["tehhahisolatedarabic"]=64524, -    ["tehinitialarabic"]=65175, -    ["tehiragana"]=12390, -    ["tehjeeminitialarabic"]=64673, -    ["tehjeemisolatedarabic"]=64523, -    ["tehmarbutaarabic"]=1577, -    ["tehmarbutafinalarabic"]=65172, -    ["tehmedialarabic"]=65176, -    ["tehmeeminitialarabic"]=64676, -    ["tehmeemisolatedarabic"]=64526, -    ["tehnoonfinalarabic"]=64627, -    ["tekatakana"]=12486, -    ["tekatakanahalfwidth"]=65411, -    ["telephone"]=8481, -    ["telephoneblack"]=9742, -    ["telishagedolahebrew"]=1440, -    ["telishaqetanahebrew"]=1449, -    ["tencircle"]=9321, -    ["tenideographicparen"]=12841, -    ["tenparen"]=9341, -    ["tenperiod"]=9361, -    ["tenroman"]=8569, -    ["tesh"]=679, -    ["tetdageshhebrew"]=64312, -    ["tethebrew"]=1496, -    ["tetsecyrillic"]=1205, -    ["tevirlefthebrew"]=1435, -    ["thabengali"]=2469, -    ["thadeva"]=2341, -    ["thagujarati"]=2725, -    ["thagurmukhi"]=2597, -    ["thalarabic"]=1584, -    ["thalfinalarabic"]=65196, -    ["thanthakhatthai"]=3660, -    ["theharabic"]=1579, -    ["thehfinalarabic"]=65178, -    ["thehinitialarabic"]=65179, -    ["thehmedialarabic"]=65180, -    ["thereexists"]=8707, -    ["therefore"]=8756, -    ["theta"]=952, -    ["thetasymbolgreek"]=977, -    ["thieuthacirclekorean"]=12921, -    ["thieuthaparenkorean"]=12825, -    ["thieuthcirclekorean"]=12907, -    ["thieuthkorean"]=12620, -    ["thieuthparenkorean"]=12811, -    ["thirteencircle"]=9324, -    ["thirteenparen"]=9344, -    ["thirteenperiod"]=9364, -    ["thonangmonthothai"]=3601, -    ["thook"]=429, -    ["thophuthaothai"]=3602, -    ["thorn"]=254, -    ["thothahanthai"]=3607, -    ["thothanthai"]=3600, -    ["thothongthai"]=3608, -    ["thothungthai"]=3606, -    ["thousandcyrillic"]=1154, -    ["thousandsseparatorpersian"]=1644, -    ["three"]=51, -    ["threebengali"]=2537, -    ["threecircle"]=9314, -    ["threecircleinversesansserif"]=10124, -    ["threedeva"]=2409, -    ["threeeighths"]=8540, -    ["threegujarati"]=2793, -    ["threegurmukhi"]=2665, -    ["threehackarabic"]=1635, -    ["threehangzhou"]=12323, -    ["threeideographicparen"]=12834, -    ["threeinferior"]=8323, -    ["threemonospace"]=65299, -    ["threenumeratorbengali"]=2550, -    ["threeparen"]=9334, -    ["threeperiod"]=9354, -    ["threepersian"]=1779, -    ["threequarters"]=190, -    ["threeroman"]=8562, -    ["threesuperior"]=179, -    ["threethai"]=3667, -    ["thzsquare"]=13204, -    ["tihiragana"]=12385, -    ["tikatakana"]=12481, -    ["tikatakanahalfwidth"]=65409, -    ["tikeutacirclekorean"]=12912, -    ["tikeutaparenkorean"]=12816, -    ["tikeutcirclekorean"]=12898, -    ["tikeutkorean"]=12599, -    ["tikeutparenkorean"]=12802, -    ["tilde"]=732, -    ["tildebelowcmb"]=816, -    ["tildecomb"]=771, -    ["tildedoublecmb"]=864, -    ["tildeoperator"]=8764, -    ["tildeoverlaycmb"]=820, -    ["tildeverticalcmb"]=830, -    ["timescircle"]=8855, -    ["tipehalefthebrew"]=1430, -    ["tippigurmukhi"]=2672, -    ["titlocyrilliccmb"]=1155, -    ["tiwnarmenian"]=1407, -    ["tlinebelow"]=7791, -    ["tmonospace"]=65364, -    ["toarmenian"]=1385, -    ["tohiragana"]=12392, -    ["tokatakana"]=12488, -    ["tokatakanahalfwidth"]=65412, -    ["tonebarextrahighmod"]=741, -    ["tonebarextralowmod"]=745, -    ["tonebarhighmod"]=742, -    ["tonebarlowmod"]=744, -    ["tonebarmidmod"]=743, -    ["tonefive"]=445, -    ["tonesix"]=389, -    ["tonetwo"]=424, -    ["tonos"]=900, -    ["tonsquare"]=13095, -    ["topatakthai"]=3599, -    ["tortoiseshellbracketleft"]=12308, -    ["tortoiseshellbracketleftsmall"]=65117, -    ["tortoiseshellbracketleftvertical"]=65081, -    ["tortoiseshellbracketright"]=12309, -    ["tortoiseshellbracketrightsmall"]=65118, -    ["tortoiseshellbracketrightvertical"]=65082, -    ["totaothai"]=3605, -    ["tpalatalhook"]=427, -    ["tparen"]=9391, -    ["trademark"]=8482, -    ["tretroflexhook"]=648, -    ["triagdn"]=9660, -    ["triaglf"]=9668, -    ["triagrt"]=9658, -    ["triagup"]=9650, -    ["ts"]=678, -    ["tsadidageshhebrew"]=64326, -    ["tsadihebrew"]=1510, -    ["tsecyrillic"]=1094, -    ["tserewidehebrew"]=1461, -    ["tshecyrillic"]=1115, -    ["ttabengali"]=2463, -    ["ttadeva"]=2335, -    ["ttagujarati"]=2719, -    ["ttagurmukhi"]=2591, -    ["tteharabic"]=1657, -    ["ttehfinalarabic"]=64359, -    ["ttehinitialarabic"]=64360, -    ["ttehmedialarabic"]=64361, -    ["tthabengali"]=2464, -    ["tthadeva"]=2336, -    ["tthagujarati"]=2720, -    ["tthagurmukhi"]=2592, -    ["tturned"]=647, -    ["tuhiragana"]=12388, -    ["tukatakana"]=12484, -    ["tukatakanahalfwidth"]=65410, -    ["tusmallhiragana"]=12387, -    ["tusmallkatakana"]=12483, -    ["tusmallkatakanahalfwidth"]=65391, -    ["twelvecircle"]=9323, -    ["twelveparen"]=9343, -    ["twelveperiod"]=9363, -    ["twelveroman"]=8571, -    ["twentycircle"]=9331, -    ["twentyparen"]=9351, -    ["twentyperiod"]=9371, -    ["two"]=50, -    ["twobengali"]=2536, -    ["twocircle"]=9313, -    ["twocircleinversesansserif"]=10123, -    ["twodeva"]=2408, -    ["twodotleader"]=8229, -    ["twodotleadervertical"]=65072, -    ["twogujarati"]=2792, -    ["twogurmukhi"]=2664, -    ["twohackarabic"]=1634, -    ["twohangzhou"]=12322, -    ["twoideographicparen"]=12833, -    ["twoinferior"]=8322, -    ["twomonospace"]=65298, -    ["twonumeratorbengali"]=2549, -    ["twoparen"]=9333, -    ["twoperiod"]=9353, -    ["twopersian"]=1778, -    ["tworoman"]=8561, -    ["twostroke"]=443, -    ["twosuperior"]=178, -    ["twothai"]=3666, -    ["twothirds"]=8532, -    ["u"]=117, -    ["uacute"]=250, -    ["ubar"]=649, -    ["ubengali"]=2441, -    ["ubopomofo"]=12584, -    ["ubreve"]=365, -    ["ucaron"]=468, -    ["ucircle"]=9444, -    ["ucircumflex"]=251, -    ["ucircumflexbelow"]=7799, -    ["ucyrillic"]=1091, -    ["udattadeva"]=2385, -    ["udblgrave"]=533, -    ["udeva"]=2313, -    ["udieresis"]=252, -    ["udieresisacute"]=472, -    ["udieresisbelow"]=7795, -    ["udieresiscaron"]=474, -    ["udieresiscyrillic"]=1265, -    ["udieresisgrave"]=476, -    ["udieresismacron"]=470, -    ["udotbelow"]=7909, -    ["ugrave"]=249, -    ["ugujarati"]=2697, -    ["ugurmukhi"]=2569, -    ["uhiragana"]=12358, -    ["uhookabove"]=7911, -    ["uhorn"]=432, -    ["uhornacute"]=7913, -    ["uhorndotbelow"]=7921, -    ["uhorngrave"]=7915, -    ["uhornhookabove"]=7917, -    ["uhorntilde"]=7919, -    ["uhungarumlaut"]=369, -    ["uhungarumlautcyrillic"]=1267, -    ["uinvertedbreve"]=535, -    ["ukatakana"]=12454, -    ["ukatakanahalfwidth"]=65395, -    ["ukcyrillic"]=1145, -    ["ukorean"]=12636, -    ["umacron"]=363, -    ["umacroncyrillic"]=1263, -    ["umacrondieresis"]=7803, -    ["umatragurmukhi"]=2625, -    ["umonospace"]=65365, -    ["underscore"]=95, -    ["underscoredbl"]=8215, -    ["underscoremonospace"]=65343, -    ["underscorevertical"]=65075, -    ["underscorewavy"]=65103, -    ["union"]=8746, -    ["universal"]=8704, -    ["uogonek"]=371, -    ["uparen"]=9392, -    ["upblock"]=9600, -    ["upperdothebrew"]=1476, -    ["upsilon"]=965, -    ["upsilondieresis"]=971, -    ["upsilondieresistonos"]=944, -    ["upsilonlatin"]=650, -    ["upsilontonos"]=973, -    ["uptackbelowcmb"]=797, -    ["uptackmod"]=724, -    ["uragurmukhi"]=2675, -    ["uring"]=367, -    ["ushortcyrillic"]=1118, -    ["usmallhiragana"]=12357, -    ["usmallkatakana"]=12453, -    ["usmallkatakanahalfwidth"]=65385, -    ["ustraightcyrillic"]=1199, -    ["ustraightstrokecyrillic"]=1201, -    ["utilde"]=361, -    ["utildeacute"]=7801, -    ["utildebelow"]=7797, -    ["uubengali"]=2442, -    ["uudeva"]=2314, -    ["uugujarati"]=2698, -    ["uugurmukhi"]=2570, -    ["uumatragurmukhi"]=2626, -    ["uuvowelsignbengali"]=2498, -    ["uuvowelsigndeva"]=2370, -    ["uuvowelsigngujarati"]=2754, -    ["uvowelsignbengali"]=2497, -    ["uvowelsigndeva"]=2369, -    ["uvowelsigngujarati"]=2753, -    ["v"]=118, -    ["vadeva"]=2357, -    ["vagujarati"]=2741, -    ["vagurmukhi"]=2613, -    ["vakatakana"]=12535, -    ["vavdageshhebrew"]=64309, -    ["vavhebrew"]=1493, -    ["vavholamhebrew"]=64331, -    ["vavvavhebrew"]=1520, -    ["vavyodhebrew"]=1521, -    ["vcircle"]=9445, -    ["vdotbelow"]=7807, -    ["vecyrillic"]=1074, -    ["veharabic"]=1700, -    ["vehfinalarabic"]=64363, -    ["vehinitialarabic"]=64364, -    ["vehmedialarabic"]=64365, -    ["vekatakana"]=12537, -    ["venus"]=9792, -    ["verticalbar"]=124, -    ["verticallineabovecmb"]=781, -    ["verticallinebelowcmb"]=809, -    ["verticallinelowmod"]=716, -    ["verticallinemod"]=712, -    ["vewarmenian"]=1406, -    ["vhook"]=651, -    ["vikatakana"]=12536, -    ["viramabengali"]=2509, -    ["viramadeva"]=2381, -    ["viramagujarati"]=2765, -    ["visargabengali"]=2435, -    ["visargadeva"]=2307, -    ["visargagujarati"]=2691, -    ["vmonospace"]=65366, -    ["voarmenian"]=1400, -    ["voicediterationhiragana"]=12446, -    ["voicediterationkatakana"]=12542, -    ["voicedmarkkana"]=12443, -    ["voicedmarkkanahalfwidth"]=65438, -    ["vokatakana"]=12538, -    ["vparen"]=9393, -    ["vtilde"]=7805, -    ["vturned"]=652, -    ["vuhiragana"]=12436, -    ["vukatakana"]=12532, -    ["w"]=119, -    ["wacute"]=7811, -    ["waekorean"]=12633, -    ["wahiragana"]=12431, -    ["wakatakana"]=12527, -    ["wakatakanahalfwidth"]=65436, -    ["wakorean"]=12632, -    ["wasmallhiragana"]=12430, -    ["wasmallkatakana"]=12526, -    ["wattosquare"]=13143, -    ["wavedash"]=12316, -    ["wavyunderscorevertical"]=65076, -    ["wawarabic"]=1608, -    ["wawfinalarabic"]=65262, -    ["wawhamzaabovearabic"]=1572, -    ["wawhamzaabovefinalarabic"]=65158, -    ["wbsquare"]=13277, -    ["wcircle"]=9446, -    ["wcircumflex"]=373, -    ["wdieresis"]=7813, -    ["wdotaccent"]=7815, -    ["wdotbelow"]=7817, -    ["wehiragana"]=12433, -    ["weierstrass"]=8472, -    ["wekatakana"]=12529, -    ["wekorean"]=12638, -    ["weokorean"]=12637, -    ["wgrave"]=7809, -    ["whitebullet"]=9702, -    ["whitecircle"]=9675, -    ["whitecircleinverse"]=9689, -    ["whitecornerbracketleft"]=12302, -    ["whitecornerbracketleftvertical"]=65091, -    ["whitecornerbracketright"]=12303, -    ["whitecornerbracketrightvertical"]=65092, -    ["whitediamond"]=9671, -    ["whitediamondcontainingblacksmalldiamond"]=9672, -    ["whitedownpointingsmalltriangle"]=9663, -    ["whitedownpointingtriangle"]=9661, -    ["whiteleftpointingsmalltriangle"]=9667, -    ["whiteleftpointingtriangle"]=9665, -    ["whitelenticularbracketleft"]=12310, -    ["whitelenticularbracketright"]=12311, -    ["whiterightpointingsmalltriangle"]=9657, -    ["whiterightpointingtriangle"]=9655, -    ["whitesmallsquare"]=9643, -    ["whitesmilingface"]=9786, -    ["whitesquare"]=9633, -    ["whitestar"]=9734, -    ["whitetelephone"]=9743, -    ["whitetortoiseshellbracketleft"]=12312, -    ["whitetortoiseshellbracketright"]=12313, -    ["whiteuppointingsmalltriangle"]=9653, -    ["whiteuppointingtriangle"]=9651, -    ["wihiragana"]=12432, -    ["wikatakana"]=12528, -    ["wikorean"]=12639, -    ["wmonospace"]=65367, -    ["wohiragana"]=12434, -    ["wokatakana"]=12530, -    ["wokatakanahalfwidth"]=65382, -    ["won"]=8361, -    ["wonmonospace"]=65510, -    ["wowaenthai"]=3623, -    ["wparen"]=9394, -    ["wring"]=7832, -    ["wsuperior"]=695, -    ["wturned"]=653, -    ["wynn"]=447, -    ["x"]=120, -    ["xabovecmb"]=829, -    ["xbopomofo"]=12562, -    ["xcircle"]=9447, -    ["xdieresis"]=7821, -    ["xdotaccent"]=7819, -    ["xeharmenian"]=1389, -    ["xi"]=958, -    ["xmonospace"]=65368, -    ["xparen"]=9395, -    ["xsuperior"]=739, -    ["y"]=121, -    ["yaadosquare"]=13134, -    ["yabengali"]=2479, -    ["yacute"]=253, -    ["yadeva"]=2351, -    ["yaekorean"]=12626, -    ["yagujarati"]=2735, -    ["yagurmukhi"]=2607, -    ["yahiragana"]=12420, -    ["yakatakana"]=12516, -    ["yakatakanahalfwidth"]=65428, -    ["yakorean"]=12625, -    ["yamakkanthai"]=3662, -    ["yasmallhiragana"]=12419, -    ["yasmallkatakana"]=12515, -    ["yasmallkatakanahalfwidth"]=65388, -    ["yatcyrillic"]=1123, -    ["ycircle"]=9448, -    ["ycircumflex"]=375, -    ["ydieresis"]=255, -    ["ydotaccent"]=7823, -    ["ydotbelow"]=7925, -    ["yeharabic"]=1610, -    ["yehbarreearabic"]=1746, -    ["yehbarreefinalarabic"]=64431, -    ["yehfinalarabic"]=65266, -    ["yehhamzaabovearabic"]=1574, -    ["yehhamzaabovefinalarabic"]=65162, -    ["yehhamzaaboveinitialarabic"]=65163, -    ["yehhamzaabovemedialarabic"]=65164, -    ["yehinitialarabic"]=65267, -    ["yehmedialarabic"]=65268, -    ["yehmeeminitialarabic"]=64733, -    ["yehmeemisolatedarabic"]=64600, -    ["yehnoonfinalarabic"]=64660, -    ["yehthreedotsbelowarabic"]=1745, -    ["yekorean"]=12630, -    ["yen"]=165, -    ["yenmonospace"]=65509, -    ["yeokorean"]=12629, -    ["yeorinhieuhkorean"]=12678, -    ["yerahbenyomolefthebrew"]=1450, -    ["yericyrillic"]=1099, -    ["yerudieresiscyrillic"]=1273, -    ["yesieungkorean"]=12673, -    ["yesieungpansioskorean"]=12675, -    ["yesieungsioskorean"]=12674, -    ["yetivhebrew"]=1434, -    ["ygrave"]=7923, -    ["yhook"]=436, -    ["yhookabove"]=7927, -    ["yiarmenian"]=1397, -    ["yicyrillic"]=1111, -    ["yikorean"]=12642, -    ["yinyang"]=9775, -    ["yiwnarmenian"]=1410, -    ["ymonospace"]=65369, -    ["yoddageshhebrew"]=64313, -    ["yodhebrew"]=1497, -    ["yodyodhebrew"]=1522, -    ["yodyodpatahhebrew"]=64287, -    ["yohiragana"]=12424, -    ["yoikorean"]=12681, -    ["yokatakana"]=12520, -    ["yokatakanahalfwidth"]=65430, -    ["yokorean"]=12635, -    ["yosmallhiragana"]=12423, -    ["yosmallkatakana"]=12519, -    ["yosmallkatakanahalfwidth"]=65390, -    ["yotgreek"]=1011, -    ["yoyaekorean"]=12680, -    ["yoyakorean"]=12679, -    ["yoyakthai"]=3618, -    ["yoyingthai"]=3597, -    ["yparen"]=9396, -    ["ypogegrammeni"]=890, -    ["ypogegrammenigreekcmb"]=837, -    ["yr"]=422, -    ["yring"]=7833, -    ["ysuperior"]=696, -    ["ytilde"]=7929, -    ["yturned"]=654, -    ["yuhiragana"]=12422, -    ["yuikorean"]=12684, -    ["yukatakana"]=12518, -    ["yukatakanahalfwidth"]=65429, -    ["yukorean"]=12640, -    ["yusbigcyrillic"]=1131, -    ["yusbigiotifiedcyrillic"]=1133, -    ["yuslittlecyrillic"]=1127, -    ["yuslittleiotifiedcyrillic"]=1129, -    ["yusmallhiragana"]=12421, -    ["yusmallkatakana"]=12517, -    ["yusmallkatakanahalfwidth"]=65389, -    ["yuyekorean"]=12683, -    ["yuyeokorean"]=12682, -    ["yyabengali"]=2527, -    ["yyadeva"]=2399, -    ["z"]=122, -    ["zaarmenian"]=1382, -    ["zacute"]=378, -    ["zadeva"]=2395, -    ["zagurmukhi"]=2651, -    ["zaharabic"]=1592, -    ["zahfinalarabic"]=65222, -    ["zahinitialarabic"]=65223, -    ["zahiragana"]=12374, -    ["zahmedialarabic"]=65224, -    ["zainarabic"]=1586, -    ["zainfinalarabic"]=65200, -    ["zakatakana"]=12470, -    ["zaqefgadolhebrew"]=1429, -    ["zaqefqatanhebrew"]=1428, -    ["zarqahebrew"]=1432, -    ["zayindageshhebrew"]=64310, -    ["zayinhebrew"]=1494, -    ["zbopomofo"]=12567, -    ["zcaron"]=382, -    ["zcircle"]=9449, -    ["zcircumflex"]=7825, -    ["zcurl"]=657, -    ["zdotaccent"]=380, -    ["zdotbelow"]=7827, -    ["zecyrillic"]=1079, -    ["zedescendercyrillic"]=1177, -    ["zedieresiscyrillic"]=1247, -    ["zehiragana"]=12380, -    ["zekatakana"]=12476, -    ["zero"]=48, -    ["zerobengali"]=2534, -    ["zerodeva"]=2406, -    ["zerogujarati"]=2790, -    ["zerogurmukhi"]=2662, -    ["zerohackarabic"]=1632, -    ["zeroinferior"]=8320, -    ["zeromonospace"]=65296, -    ["zeropersian"]=1776, -    ["zerosuperior"]=8304, -    ["zerothai"]=3664, -    ["zerowidthjoiner"]=65279, -    ["zerowidthnonjoiner"]=8204, -    ["zerowidthspace"]=8203, -    ["zeta"]=950, -    ["zhbopomofo"]=12563, -    ["zhearmenian"]=1386, -    ["zhebrevecyrillic"]=1218, -    ["zhecyrillic"]=1078, -    ["zhedescendercyrillic"]=1175, -    ["zhedieresiscyrillic"]=1245, -    ["zihiragana"]=12376, -    ["zikatakana"]=12472, -    ["zinorhebrew"]=1454, -    ["zlinebelow"]=7829, -    ["zmonospace"]=65370, -    ["zohiragana"]=12382, -    ["zokatakana"]=12478, -    ["zparen"]=9397, -    ["zretroflexhook"]=656, -    ["zstroke"]=438, -    ["zuhiragana"]=12378, -    ["zukatakana"]=12474, - -    -- extras - -    ["Dcroat"]=272, -    ["Delta"]=8710, -    ["Euro"]=8364, -    ["H18533"]=9679, -    ["H18543"]=9642, -    ["H18551"]=9643, -    ["H22073"]=9633, -    ["Ldot"]=319, -    ["Oslashacute"]=510, -    ["SF10000"]=9484, -    ["SF20000"]=9492, -    ["SF30000"]=9488, -    ["SF40000"]=9496, -    ["SF50000"]=9532, -    ["SF60000"]=9516, -    ["SF70000"]=9524, -    ["SF80000"]=9500, -    ["SF90000"]=9508, -    ["Upsilon1"]=978, -    ["afii10066"]=1073, -    ["afii10067"]=1074, -    ["afii10068"]=1075, -    ["afii10069"]=1076, -    ["afii10070"]=1077, -    ["afii10071"]=1105, -    ["afii10072"]=1078, -    ["afii10073"]=1079, -    ["afii10074"]=1080, -    ["afii10075"]=1081, -    ["afii10076"]=1082, -    ["afii10077"]=1083, -    ["afii10078"]=1084, -    ["afii10079"]=1085, -    ["afii10080"]=1086, -    ["afii10081"]=1087, -    ["afii10082"]=1088, -    ["afii10083"]=1089, -    ["afii10084"]=1090, -    ["afii10085"]=1091, -    ["afii10086"]=1092, -    ["afii10087"]=1093, -    ["afii10088"]=1094, -    ["afii10089"]=1095, -    ["afii10090"]=1096, -    ["afii10091"]=1097, -    ["afii10092"]=1098, -    ["afii10093"]=1099, -    ["afii10094"]=1100, -    ["afii10095"]=1101, -    ["afii10096"]=1102, -    ["afii10097"]=1103, -    ["afii10098"]=1169, -    ["afii10099"]=1106, -    ["afii10100"]=1107, -    ["afii10101"]=1108, -    ["afii10102"]=1109, -    ["afii10103"]=1110, -    ["afii10104"]=1111, -    ["afii10105"]=1112, -    ["afii10106"]=1113, -    ["afii10107"]=1114, -    ["afii10108"]=1115, -    ["afii10109"]=1116, -    ["afii10110"]=1118, -    ["afii10193"]=1119, -    ["afii10194"]=1123, -    ["afii10195"]=1139, -    ["afii10196"]=1141, -    ["afii10846"]=1241, -    ["afii208"]=8213, -    ["afii57381"]=1642, -    ["afii57388"]=1548, -    ["afii57392"]=1632, -    ["afii57393"]=1633, -    ["afii57394"]=1634, -    ["afii57395"]=1635, -    ["afii57396"]=1636, -    ["afii57397"]=1637, -    ["afii57398"]=1638, -    ["afii57399"]=1639, -    ["afii57400"]=1640, -    ["afii57401"]=1641, -    ["afii57403"]=1563, -    ["afii57407"]=1567, -    ["afii57409"]=1569, -    ["afii57410"]=1570, -    ["afii57411"]=1571, -    ["afii57412"]=1572, -    ["afii57413"]=1573, -    ["afii57414"]=1574, -    ["afii57415"]=1575, -    ["afii57416"]=1576, -    ["afii57417"]=1577, -    ["afii57418"]=1578, -    ["afii57419"]=1579, -    ["afii57420"]=1580, -    ["afii57421"]=1581, -    ["afii57422"]=1582, -    ["afii57423"]=1583, -    ["afii57424"]=1584, -    ["afii57425"]=1585, -    ["afii57426"]=1586, -    ["afii57427"]=1587, -    ["afii57428"]=1588, -    ["afii57429"]=1589, -    ["afii57430"]=1590, -    ["afii57431"]=1591, -    ["afii57432"]=1592, -    ["afii57433"]=1593, -    ["afii57434"]=1594, -    ["afii57440"]=1600, -    ["afii57441"]=1601, -    ["afii57442"]=1602, -    ["afii57443"]=1603, -    ["afii57444"]=1604, -    ["afii57445"]=1605, -    ["afii57446"]=1606, -    ["afii57448"]=1608, -    ["afii57449"]=1609, -    ["afii57450"]=1610, -    ["afii57451"]=1611, -    ["afii57452"]=1612, -    ["afii57453"]=1613, -    ["afii57454"]=1614, -    ["afii57455"]=1615, -    ["afii57456"]=1616, -    ["afii57457"]=1617, -    ["afii57458"]=1618, -    ["afii57470"]=1607, -    ["afii57505"]=1700, -    ["afii57506"]=1662, -    ["afii57507"]=1670, -    ["afii57508"]=1688, -    ["afii57509"]=1711, -    ["afii57511"]=1657, -    ["afii57512"]=1672, -    ["afii57513"]=1681, -    ["afii57514"]=1722, -    ["afii57519"]=1746, -    ["afii57636"]=8362, -    ["afii57645"]=1470, -    ["afii57658"]=1475, -    ["afii57664"]=1488, -    ["afii57665"]=1489, -    ["afii57666"]=1490, -    ["afii57667"]=1491, -    ["afii57668"]=1492, -    ["afii57669"]=1493, -    ["afii57670"]=1494, -    ["afii57671"]=1495, -    ["afii57672"]=1496, -    ["afii57673"]=1497, -    ["afii57674"]=1498, -    ["afii57675"]=1499, -    ["afii57676"]=1500, -    ["afii57677"]=1501, -    ["afii57678"]=1502, -    ["afii57679"]=1503, -    ["afii57680"]=1504, -    ["afii57681"]=1505, -    ["afii57682"]=1506, -    ["afii57683"]=1507, -    ["afii57684"]=1508, -    ["afii57685"]=1509, -    ["afii57686"]=1510, -    ["afii57687"]=1511, -    ["afii57688"]=1512, -    ["afii57689"]=1513, -    ["afii57690"]=1514, -    ["afii57716"]=1520, -    ["afii57717"]=1521, -    ["afii57718"]=1522, -    ["afii57793"]=1460, -    ["afii57794"]=1461, -    ["afii57795"]=1462, -    ["afii57796"]=1467, -    ["afii57797"]=1464, -    ["afii57798"]=1463, -    ["afii57799"]=1456, -    ["afii57800"]=1458, -    ["afii57801"]=1457, -    ["afii57802"]=1459, -    ["afii57803"]=1474, -    ["afii57804"]=1473, -    ["afii57806"]=1465, -    ["afii57807"]=1468, -    ["afii57839"]=1469, -    ["afii57841"]=1471, -    ["afii57842"]=1472, -    ["afii57929"]=700, -    ["afii61248"]=8453, -    ["afii61289"]=8467, -    ["afii61352"]=8470, -    ["afii61664"]=8204, -    ["afii63167"]=1645, -    ["afii64937"]=701, -    ["arrowdblboth"]=8660, -    ["arrowdblleft"]=8656, -    ["arrowdblright"]=8658, -    ["arrowupdnbse"]=8616, -    ["bar"]=124, -    ["circle"]=9675, -    ["circlemultiply"]=8855, -    ["circleplus"]=8853, -    ["club"]=9827, -    ["colonmonetary"]=8353, -    ["dcroat"]=273, -    ["dkshade"]=9619, -    ["existential"]=8707, -    ["female"]=9792, -    ["gradient"]=8711, -    ["heart"]=9829, -    ["hookabovecomb"]=777, -    ["invcircle"]=9689, -    ["ldot"]=320, -    ["longs"]=383, -    ["ltshade"]=9617, -    ["male"]=9794, -    ["mu"]=181, -    ["napostrophe"]=329, -    ["notelement"]=8713, -    ["omega1"]=982, -    ["openbullet"]=9702, -    ["orthogonal"]=8735, -    ["oslashacute"]=511, -    ["phi1"]=981, -    ["propersubset"]=8834, -    ["propersuperset"]=8835, -    ["reflexsubset"]=8838, -    ["reflexsuperset"]=8839, -    ["shade"]=9618, -    ["sigma1"]=962, -    ["similar"]=8764, -    ["smileface"]=9786, -    ["spacehackarabic"]=32, -    ["spade"]=9824, -    ["theta1"]=977, -    ["twodotenleader"]=8229, -} diff --git a/fontdbutil.lua b/fontdbutil.lua index 31c7dfa..d76678f 100755 --- a/fontdbutil.lua +++ b/fontdbutil.lua @@ -1,11 +1,15 @@  #!/usr/bin/env texlua ---[[ + +--[[doc--  This file was originally written by Elie Roux and Khaled Hosny and is under CC0  license (see http://creativecommons.org/publicdomain/zero/1.0/legalcode). -This file is a wrapper for the luaotfload's font names module. It is part of the -luaotfload bundle, please see the luaotfload documentation for more info. ---]] +This file is a wrapper for the luaotfload font names module +(luaotfload-database.lua). It is part of the luaotfload bundle, please +see the luaotfload documentation for more info. Report bugs to +\url{https://github.com/lualatex/luaotfload/issues}. + +--doc]]--  kpse.set_program_name"luatex" @@ -14,18 +18,17 @@ local texiowrite_nl   = texio.write_nl  local stringfind      = string.find  local stringlower     = string.lower --- First we need to be able to load module (code copied from --- luatexbase-loader.sty): +  local loader_file = "luatexbase.loader.lua"  local loader_path = assert(kpse.find_file(loader_file, "lua"),                             "File '"..loader_file.."' not found") +  string.quoted = string.quoted or function (str)    return string.format("%q",str)   end ---texiowrite_nl("("..loader_path..")") -dofile(loader_path) -- FIXME this pollutes stdout with filenames +dofile(loader_path)  --[[doc--  Depending on how the script is called we change its behavior. @@ -73,7 +76,20 @@ config.lualibs.prefer_merged    = true  config.lualibs.load_extended    = false  require"lualibs" + +--[[doc-- +\fileent{luatex-basics-gen.lua} calls functions from the +\luafunction{texio.*} library; too much for our taste. +We intercept them with dummies. +--doc]]-- + +local dummy_function = function ( ) end +local backup_write, backup_write_nl  = texio.write, texio.write_nl + +texio.write, texio.write_nl          = dummy_function, dummy_function  require"luaotfload-basics-gen.lua" +texio.write, texio.write_nl          = backup_write, backup_write_nl +  require"luaotfload-override.lua"  --- this populates the logs.* namespace  require"luaotfload-database"  require"alt_getopt" @@ -103,6 +119,8 @@ This tool is part of the luaotfload package. Valid options are:    -V --version                 print version and exit    -h --help                    print this message +  --alias=<name>               force behavior of “fontdbutil” or legacy +                               “mkluatexfontdb”  -------------------------------------------------------------------------------                                     DATABASE @@ -136,6 +154,8 @@ Valid options:    -vvv                         print all steps of directory searching    -V --version                 print version and exit    -h --help                    print this message +  --alias=<name>               force behavior of “fontdbutil” or legacy +                               “mkluatexfontdb”  The font database will be saved to     %s @@ -171,10 +191,10 @@ local show_font_info = function (filename)          local fontinfo = fontloader.info(fullname)          local nfonts   = #fontinfo          if nfonts > 0 then -- true type collection -            logs.names_report(true, 0, "resolve", +            logs.names_report(true, 1, "resolve",                  [[%s is a font collection]], filename)              for n = 1, nfonts do -                logs.names_report(true, 0, "resolve", +                logs.names_report(true, 1, "resolve",                      [[showing info for font no. %d]], n)                  show_info_items(fontinfo[n])              end @@ -182,7 +202,7 @@ local show_font_info = function (filename)              show_info_items(fontinfo)          end      else -        logs.names_report(true, 0, "resolve", +        logs.names_report(true, 1, "resolve",              "font %s not found", filename)      end  end @@ -205,7 +225,7 @@ local actions = { } --- (jobspec -> (bool * bool)) list  actions.loglevel = function (job)      logs.set_loglevel(job.log_level) -    logs.names_report("log", 2, "util", +    logs.names_report("info", 3, "util",                        "setting log level", "%d", job.log_level)      return true, true  end @@ -223,8 +243,8 @@ end  actions.generate = function (job)      local fontnames, savedname      fontnames = names.update(fontnames, job.force_reload) -    logs.names_report("log", 0, "db", -        "fonts in the database", "%i", #fontnames.mappings) +    logs.names_report("info", 2, "db", +        "Fonts in the database: %i", #fontnames.mappings)      savedname = names.save(fontnames)      if savedname then --- FIXME have names.save return bool          return true, true @@ -246,18 +266,18 @@ actions.query = function (job)          fonts.names.resolve(nil, nil, tmpspec)      if success then -        logs.names_report(false, 0, +        logs.names_report(false, 1,              "resolve", "Font “%s” found!", query) -        logs.names_report(false, 0, +        logs.names_report(false, 1,              "resolve", "Resolved file name “%s”:", foundname)          if job.show_info then              show_font_info(foundname)          end      else -        logs.names_report(false, 0, +        logs.names_report(false, 1,              "resolve", "Cannot find “%s”.", query)          if job.fuzzy == true then -            logs.names_report(false, 2, +            logs.names_report(false, 1,                  "resolve", "Looking for close matches, this may take a while ...")              local success = fonts.names.find_closest(query, job.fuzzy_limit)          end @@ -279,14 +299,11 @@ local process_cmdline = function ( ) -- unit -> jobspec      local result = { -- jobspec          force_reload = nil,          query        = "", -        log_level    = 1, +        log_level    = 1, --- 2 is approx. the old behavior      } -    if config.luaotfload.self == "mkluatexfontdb" then -        action_pending["generate"] = true -    end -      local long_options = { +        alias            = 1,          find             = 1,          force            = "f",          fuzzy            = "F", @@ -347,8 +364,17 @@ local process_cmdline = function ( ) -- unit -> jobspec              end          elseif v == "i" then              result.show_info = true +        elseif v == "alias" then +            config.luaotfload.self = optarg[n]          end      end + +    if config.luaotfload.self == "mkluatexfontdb" then +        action_pending["generate"] = true +        print(result.log_level) +        result.log_level = math.max(2, result.log_level) +        print(result.log_level) +    end      return result  end diff --git a/luaotfload-basics-gen.lua b/luaotfload-basics-gen.lua index 727086e..61f3910 100644 --- a/luaotfload-basics-gen.lua +++ b/luaotfload-basics-gen.lua @@ -130,7 +130,9 @@ end  caches = { } -local writable, readables = nil, { } +local writable  = nil +local readables = { } +local usingjit  = jit  if not caches.namespace or caches.namespace == "" or caches.namespace == "context" then      caches.namespace = 'generic' @@ -204,7 +206,7 @@ end  local function makefullname(path,name)      if path and path ~= "" then          name = "temp-" .. name -- clash prevention -        return file.addsuffix(file.join(path,name),"lua"), file.addsuffix(file.join(path,name),"luc") +        return file.addsuffix(file.join(path,name),"lua"), file.addsuffix(file.join(path,name),usingjit and "lub" or "luc")      end  end @@ -265,26 +267,36 @@ end  -- this) in which case one should limit the method to luac and enable support  -- for execution. -caches.compilemethod = "both" +-- function caches.compile(data,luaname,lucname) +--     local d = io.loaddata(luaname) +--     if not d or d == "" then +--         d = table.serialize(data,true) -- slow +--     end +--     if d and d ~= "" then +--         local f = io.open(lucname,'w') +--         if f then +--             local s = loadstring(d) +--             if s then +--                 f:write(string.dump(s,true)) +--             end +--             f:close() +--         end +--     end +-- end  function caches.compile(data,luaname,lucname) -    local done = false -    if caches.compilemethod == "luac" or caches.compilemethod == "both" then -        done = os.spawn("texluac -o " .. string.quoted(lucname) .. " -s " .. string.quoted(luaname)) == 0 +    local d = io.loaddata(luaname) +    if not d or d == "" then +        d = table.serialize(data,true) -- slow      end -    if not done and (caches.compilemethod == "dump" or caches.compilemethod == "both") then -        local d = io.loaddata(luaname) -        if not d or d == "" then -            d = table.serialize(data,true) -- slow -        end -        if d and d ~= "" then -            local f = io.open(lucname,'w') -            if f then -                local s -                if _G["loadstring"] then s=loadstring(d) else s=load(d) end -                f:write(string.dump(s)) -                f:close() +    if d and d ~= "" then +        local f = io.open(lucname,'w') +        if f then +            local s = loadstring(d) +            if s then +                f:write(string.dump(s,true))              end +            f:close()          end      end  end diff --git a/luaotfload-database.lua b/luaotfload-database.lua index 19b04db..e8f3d1d 100644 --- a/luaotfload-database.lua +++ b/luaotfload-database.lua @@ -18,6 +18,7 @@ local pcall                   = pcall  local require                 = require  local tonumber                = tonumber +local fontloaderinfo          = fontloader.info  local iolines                 = io.lines  local ioopen                  = io.open  local kpseexpand_path         = kpse.expand_path @@ -45,6 +46,8 @@ local utf8lower               = unicode.utf8.lower  local dirglob                 = dir.glob  local dirmkdirs               = dir.mkdirs  local filebasename            = file.basename +local filenameonly            = file.nameonly +local filedirname             = file.dirname  local filecollapsepath        = file.collapsepath or file.collapse_path  local fileextname             = file.extname  local fileiswritable          = file.iswritable @@ -81,32 +84,6 @@ end  names.path.dir = writable_path  names.path.path = filejoin(writable_path, names.path.basename) - ----- <FIXME> ---- ---- these lines load some binary module called “lualatex-platform” ---- that doesn’t appear to build with Lua 5.2. I’m going ahead and ---- disable it for the time being until someone clarifies what it ---- is supposed to do and whether we should care to fix it. ---- ---local success = pcall(require, "luatexbase.modutils") ---if success then ---   success = pcall(luatexbase.require_module, ---                   "lualatex-platform", "2011/03/30") ---    print(success) ---end - ---local get_installed_fonts ---if success then ---   get_installed_fonts = lualatex.platform.get_installed_fonts ---else ---   function get_installed_fonts() ---   end ---end ----- </FIXME> - -local get_installed_fonts = nil -  --[[doc--  Auxiliary functions  --doc]]-- @@ -121,10 +98,46 @@ local sanitize_string = function (str)      return nil  end +--[[doc-- +This is a sketch of the db: + +    type dbobj = { +        mappings : fontentry list; +        status   : filestatus; +        version  : float; +    } +    and fontentry = { +        familyname  : string; +        filename    : (string * bool); +        fontname    : string; +        fullname    : string; +        names       : { +            family     : string; +            fullname   : string; +            psname     : string; +            subfamily  : string; +        } +        size        : int list; +        slant       : int; +        weight      : int; +        width       : int; +    } +    and filestatus = (fullname, { index : int list; timestamp : int }) dict + +beware that this is a reconstruction and may be incomplete. + +--doc]]-- +  local fontnames_init = function ( )      return {          mappings  = { },          status    = { }, +        --- adding filename mapping increases the +        --- size of the serialized db on my system +        --- (5840 font files) by a factor of ... +        barenames = { },--- incr. by 1.11 +        basenames = { },--- incr. by 1.22 +--      fullnames = { },--- incr. by 1.48          version   = names.version,      }  end @@ -180,14 +193,18 @@ local save_names  local scan_external_dir  local update_names +--- unit -> dbobj  load_names = function ( ) +    local starttime = os.gettimeofday()      local foundname, data = load_lua_file(names.path.path)      if data then          report("info", 1, "db",              "Font names database loaded", "%s", foundname) +        report("info", 3, "db", "Loading took %0.f ms", +                                1000*(os.gettimeofday()-starttime))      else -        report("info", 0, "db", +        report("info", 1, "db",              [[Font names database not found, generating new one.               This can take several minutes; please be patient.]])          data = update_names(fontnames_init()) @@ -204,10 +221,6 @@ do          regular    = { "normal",        "roman",                         "plain",         "book",                         "medium", }, -        --- TODO note from Élie Roux -        --- boldregular was for old versions of Linux Libertine, is it still useful? -        --- semibold is in new versions of Linux Libertine, but there is also a bold, -        --- not sure it's useful here...          bold       = { "demi",           "demibold",                         "semibold",       "boldregular",},          italic     = { "regularitalic",  "normalitalic", @@ -227,6 +240,55 @@ end  local fonts_loaded   = false  local fonts_reloaded = false +local crude_file_lookup_verbose = function (data, filename) +    local found = data.barenames[filename] +    if found then +        report("info", 0, "db", +            "crude file lookup: req=%s; hit=bare; ret=%s", +            filename, found[1]) +        return found +    end +--  found = data.fullnames[filename] +--  if found then +--      report("info", 0, "db", +--          "crude file lookup: req=%s; hit=bare; ret=%s", +--          filename, found[1]) +--      return found +--  end +    found = data.basenames[filename] +    if found then +        report("info", 0, "db", +            "crude file lookup: req=%s; hit=bare; ret=%s", +            filename, found[1]) +        return found +    end +    found = resolvers.findfile(filename, "tfm") +    if found then +        report("info", 0, "db", +            "crude file lookup: req=tfm; hit=bare; ret=%s", found) +        return { found, false } +    end +    found = resolvers.findfile(filename, "ofm") +    if found then +        report("info", 0, "db", +            "crude file lookup: req=ofm; hit=bare; ret=%s", found) +        return { found, false } +    end +    return false +end + +local crude_file_lookup = function (data, filename) +    local found = data.barenames[filename] +--             or data.fullnames[filename] +               or data.basenames[filename] +    if found then return found end +    found = resolvers.findfile(filename, "tfm") +    if found then return { found, false } end +    found = resolvers.findfile(filename, "ofm") +    if found then return { found, false } end +    return false +end +  --[[doc--  Luatex-fonts, the font-loader package luaotfload imports, comes with @@ -253,8 +315,10 @@ font database created by the mkluatexfontdb script.  ---   · specification: string (== <lookup> ":" <name>)  ---   · sub:      string  --- ---- the return value of “resolve” is the file name of the requested ---- font +--- the first return value of “resolve” is the file name of the +--- requested font (string) +--- the second is of type bool or string and indicates the subfont of a +--- ttc  ---  --- 'a -> 'a -> table -> (string * string | bool * bool)  --- @@ -264,6 +328,18 @@ font database created by the mkluatexfontdb script.  ---  ---   resolve = function (_,_,specification) -- the 1st two parameters are used by ConTeXt +    if not fonts_loaded then +        names.data   = load_names() +        fonts_loaded = true +    end +    local data = names.data + +    if specification.lookup == "file" then +        local found = crude_file_lookup(data, specification.name) +        --local found = crude_file_lookup_verbose(data, specification.name) +        if found then return found[1], found[2], true end +    end +      local name  = sanitize_string(specification.name)      local style = sanitize_string(specification.style) or "regular" @@ -274,152 +350,170 @@ resolve = function (_,_,specification) -- the 1st two parameters are used by Con          size = specification.size / 65536      end -    if not fonts_loaded then -        names.data   = load_names() -        fonts_loaded = true +    if type(data) ~= "table" then +         --- this catches a case where load_names() doesn’t +         --- return a database object, which can happen only +         --- in case there is valid Lua code in the database, +         --- but it’s not a table, e.g. it contains an integer. +        if not fonts_reloaded then +            return reload_db("invalid database; not a table", +                             resolve, nil, nil, specification +                   ) +        end +        --- unsucessfully reloaded; bail +        return specification.name, false, false      end -    local data = names.data -    if type(data) == "table" then -        local db_version, nms_version = data.version, names.version -        if data.version ~= names.version then -            report("log", 0, "db", -                [[version mismatch; expected %4.3f, got %4.3f]], -                nms_version, db_version -            ) -            return reload_db(resolve, nil, nil, specification) +    local db_version, nms_version = data.version, names.version +    if db_version ~= nms_version then +        report("log", 0, "db", +            [[version mismatch; expected %4.3f, got %4.3f]], +            nms_version, db_version +        ) +        return reload_db("version mismatch", resolve, nil, nil, specification) +    end + +    if not data.mappings then +        return reload_db("invalid database; missing font mapping", +                         resolve, nil, nil, specification +               ) +    end + +    local found = { } +    local synonym_set = style_synonyms.set +    for _,face in next, data.mappings do +        --- TODO we really should store those in dedicated +        --- .sanitized field +        local family    = sanitize_string(face.names and face.names.family) +        local subfamily = sanitize_string(face.names and face.names.subfamily) +        local fullname  = sanitize_string(face.names and face.names.fullname) +        local psname    = sanitize_string(face.names and face.names.psname) +        local fontname  = sanitize_string(face.fontname) +        local pfullname = sanitize_string(face.fullname) +        local optsize, dsnsize, maxsize, minsize +        if #face.size > 0 then +            optsize = face.size +            dsnsize = optsize[1] and optsize[1] / 10 +            -- can be nil +            maxsize = optsize[2] and optsize[2] / 10 or dsnsize +            minsize = optsize[3] and optsize[3] / 10 or dsnsize          end -        if data.mappings then -            local found = { } -            local synonym_set = style_synonyms.set -            for _,face in next, data.mappings do -                --- TODO we really should store those in dedicated -                --- .sanitized field -                local family    = sanitize_string(face.names and face.names.family) -                local subfamily = sanitize_string(face.names and face.names.subfamily) -                local fullname  = sanitize_string(face.names and face.names.fullname) -                local psname    = sanitize_string(face.names and face.names.psname) -                local fontname  = sanitize_string(face.fontname) -                local pfullname = sanitize_string(face.fullname) -                local optsize, dsnsize, maxsize, minsize -                if #face.size > 0 then -                    optsize = face.size -                    dsnsize = optsize[1] and optsize[1] / 10 -                    -- can be nil -                    maxsize = optsize[2] and optsize[2] / 10 or dsnsize -                    minsize = optsize[3] and optsize[3] / 10 or dsnsize -                end -                if name == family then -                    if subfamily == style then -                        if optsize then -                            if dsnsize == size -                            or (size > minsize and size <= maxsize) then -                                found[1] = face -                                break -                            else -                                found[#found+1] = face -                            end -                        else -                            found[1] = face -                            break -                        end -                    elseif synonym_set[style] and -                           synonym_set[style][subfamily] then -                        if optsize then -                            if dsnsize == size -                            or (size > minsize and size <= maxsize) then -                                found[1] = face -                                break -                            else -                                found[#found+1] = face -                            end -                        else -                            found[1] = face -                            break -                        end -                    elseif subfamily == "regular" or -                           synonym_set.regular[subfamily] then -                        found.fallback = face + +        if name == family then +            if subfamily == style then +                if optsize then +                    if dsnsize == size +                    or (size > minsize and size <= maxsize) then +                        found[1] = face +                        break +                    else +                        found[#found+1] = face                      end                  else -                    if name == fullname -                    or name == pfullname -                    or name == fontname -                    or name == psname then -                        if optsize then -                            if dsnsize == size -                            or (size > minsize and size <= maxsize) then -                                found[1] = face -                                break -                            else -                                found[#found+1] = face -                            end -                        else -                            found[1] = face -                            break -                        end +                    found[1] = face +                    break +                end +            elseif synonym_set[style] and +                   synonym_set[style][subfamily] +            then +                if optsize then +                    if dsnsize == size +                    or (size > minsize and size <= maxsize) then +                        found[1] = face +                        break +                    else +                        found[#found+1] = face                      end +                else +                    found[1] = face +                    break                  end +            elseif subfamily == "regular" or +                    synonym_set.regular[subfamily] then +                found.fallback = face +            elseif name == fullname then +                --- happens with Libertine Mono which has +                --- “mono” as subfamily +                found[1] = face +                break              end -            if #found == 1 then -                if kpselookup(found[1].filename[1]) then -                    report("log", 0, "resolve", -                        "font family='%s', subfamily='%s' found: %s", -                        name, style, found[1].filename[1] -                    ) -                    return found[1].filename[1], found[1].filename[2], true -                end -            elseif #found > 1 then -                -- we found matching font(s) but not in the requested optical -                -- sizes, so we loop through the matches to find the one with -                -- least difference from the requested size. -                local closest -                local least = math.huge -- initial value is infinity -                for i,face in next, found do -                    local dsnsize    = face.size[1]/10 -                    local difference = mathabs(dsnsize-size) -                    if difference < least then -                        closest = face -                        least   = difference + +        else +            if name == fullname +            or name == pfullname +            or name == fontname +            or name == psname then +                if optsize then +                    if dsnsize == size +                    or (size > minsize and size <= maxsize) then +                        found[1] = face +                        break +                    else +                        found[#found+1] = face                      end +                else +                    found[1] = face +                    break                  end -                if kpselookup(closest.filename[1]) then -                    report("log", 0, "resolve", -                        "font family='%s', subfamily='%s' found: %s", -                        name, style, closest.filename[1] -                    ) -                    return closest.filename[1], closest.filename[2], true -                end -            elseif found.fallback then -                return found.fallback.filename[1], found.fallback.filename[2], true              end -            --- no font found so far -            if not fonts_reloaded then -                --- last straw: try reloading the database -                return reload_db(resolve, nil, nil, specification) -            else -                --- else, fallback to requested name -                --- specification.name is empty with absolute paths, looks -                --- like a bug in the specification parser <TODO< is it still -                --- relevant? looks not... -                return specification.name, false, false +        end +    end + +    if #found == 1 then +        if kpselookup(found[1].filename[1]) then +            report("log", 0, "resolve", +                "font family='%s', subfamily='%s' found: %s", +                name, style, found[1].filename[1] +            ) +            return found[1].filename[1], found[1].filename[2], true +        end +    elseif #found > 1 then +        -- we found matching font(s) but not in the requested optical +        -- sizes, so we loop through the matches to find the one with +        -- least difference from the requested size. +        local closest +        local least = math.huge -- initial value is infinity +        for i,face in next, found do +            local dsnsize    = face.size[1]/10 +            local difference = mathabs(dsnsize-size) +            if difference < least then +                closest = face +                least   = difference              end          end -    else --- no db or outdated; reload names and retry -        if not fonts_reloaded then -            return reload_db(resolve, nil, nil, specification) -        else --- unsucessfully reloaded; bail -            return specification.name, false, false +        if kpselookup(closest.filename[1]) then +            report("log", 0, "resolve", +                "font family='%s', subfamily='%s' found: %s", +                name, style, closest.filename[1] +            ) +            return closest.filename[1], closest.filename[2], true          end +    elseif found.fallback then +        return found.fallback.filename[1], found.fallback.filename[2], true +    end + +    --- no font found so far +    if not fonts_reloaded then +        --- last straw: try reloading the database +        return reload_db( +            "unresoled font name: “" .. name .. "”", +            resolve, nil, nil, specification +        )      end + +    --- else, fallback to requested name +    --- specification.name is empty with absolute paths, looks +    --- like a bug in the specification parser <TODO< is it still +    --- relevant? looks not... +    return specification.name, false, false  end --- resolve()  --- when reload is triggered we update the database  --- and then re-run the caller with the arg list ---- ('a -> 'a) -> 'a list -> 'a -reload_db = function (caller, ...) -    report("log", 1, "db", "reload initiated") +--- string -> ('a -> 'a) -> 'a list -> 'a +reload_db = function (why, caller, ...) +    report("log", 1, "db", "reload initiated; reason: “%s”", why)      names.data = update_names()      save_names(names.data)      fonts_reloaded = true @@ -466,67 +560,65 @@ find_closest = function (name, limit)      local data = names.data -    if type(data) == "table" then -        local by_distance   = { } --- (int, string list) dict -        local distances     = { } --- int list -        local cached        = { } --- (string, int) dict -        local mappings      = data.mappings -        local n_fonts       = #mappings - -        for n = 1, n_fonts do -            local current    = mappings[n] -            local cnames     = current.names -            --[[ -                This is simplistic but surpisingly fast. -                Matching is performed against the “family” name -                of a db record. We then store its “fullname” at -                it edit distance. -                We should probably do some weighting over all the -                font name categories as well as whatever agrep -                does. -            --]] -            if cnames then -                local fullname, family = cnames.fullname, cnames.family -                family = sanitize_string(family) - -                local dist = cached[family]--- maybe already calculated -                if not dist then -                    dist = iterative_levenshtein(name, family) -                    cached[family] = dist -                end -                local namelst = by_distance[dist] -                if not namelst then --- first entry -                    namelst = { fullname } -                    distances[#distances+1] = dist -                else --- append -                    namelst[#namelst+1] = fullname -                end -                by_distance[dist] = namelst +    if type(data) ~= "table" then +        return reload_db("no database", find_closest, name) +    end +    local by_distance   = { } --- (int, string list) dict +    local distances     = { } --- int list +    local cached        = { } --- (string, int) dict +    local mappings      = data.mappings +    local n_fonts       = #mappings + +    for n = 1, n_fonts do +        local current    = mappings[n] +        local cnames     = current.names +        --[[ +            This is simplistic but surpisingly fast. +            Matching is performed against the “family” name +            of a db record. We then store its “fullname” at +            it edit distance. +            We should probably do some weighting over all the +            font name categories as well as whatever agrep +            does. +        --]] +        if cnames then +            local fullname, family = cnames.fullname, cnames.family +            family = sanitize_string(family) + +            local dist = cached[family]--- maybe already calculated +            if not dist then +                dist = iterative_levenshtein(name, family) +                cached[family] = dist              end -        end - -        --- print the matches according to their distance -        local n_distances = #distances -        if n_distances > 0 then --- got some data -            tablesort(distances) -            limit = mathmin(n_distances, limit) -            report(false, 1, "query", -                    "displaying %d distance levels", limit) - -            for i = 1, limit do -                local dist     = distances[i] -                local namelst  = by_distance[dist] -                report(false, 0, "query", -                    "distance from “" .. name .. "”: " .. dist -                 .. "\n    " .. tableconcat(namelst, "\n    ") -                ) +            local namelst = by_distance[dist] +            if not namelst then --- first entry +                namelst = { fullname } +                distances[#distances+1] = dist +            else --- append +                namelst[#namelst+1] = fullname              end +            by_distance[dist] = namelst +        end +    end -            return true +    --- print the matches according to their distance +    local n_distances = #distances +    if n_distances > 0 then --- got some data +        tablesort(distances) +        limit = mathmin(n_distances, limit) +        report(false, 1, "query", +                "displaying %d distance levels", limit) + +        for i = 1, limit do +            local dist     = distances[i] +            local namelst  = by_distance[dist] +            report(false, 0, "query", +                "distance from “" .. name .. "”: " .. dist +                .. "\n    " .. tableconcat(namelst, "\n    ") +            )          end -        return false -    else --- need reload -        return reload_db(find_closest, name) + +        return true      end      return false  end --- find_closest() @@ -595,107 +687,173 @@ font_fullinfo = function (filename, subfont, texmf)      return tfmdata  end -local load_font = function (filename, fontnames, newfontnames, texmf) -    local newmappings = newfontnames.mappings -    local newstatus   = newfontnames.status -    local mappings    = fontnames.mappings -    local status      = fontnames.status -    local basename    = filebasename(filename) -    local basefile    = texmf and basename or filename -    if filename then -        if names.blacklist[filename] or -           names.blacklist[basename] then -            report("log", 2, "db", "ignoring font", "%s", filename) -            return -        end -        local timestamp, db_timestamp -        db_timestamp        = status[basefile] and status[basefile].timestamp -        timestamp           = lfs.attributes(filename, "modification") - -        local index_status = newstatus[basefile] or (not texmf and newstatus[basename]) -        if index_status and index_status.timestamp == timestamp then -            -- already indexed this run -            return -        end +--- we return true if the fond is new or re-indexed +--- string -> dbobj -> dbobj -> bool -> bool +local load_font = function (fullname, fontnames, newfontnames, texmf) +    local newmappings   = newfontnames.mappings +    local newstatus     = newfontnames.status -        newstatus[basefile] = newstatus[basefile] or { } -        newstatus[basefile].timestamp = timestamp -        newstatus[basefile].index     = newstatus[basefile].index or { } +--  local newfullnames  = newfontnames.fullnames +    local newbasenames  = newfontnames.basenames +    local newbarenames  = newfontnames.barenames -        if db_timestamp == timestamp and not newstatus[basefile].index[1] then -            for _,v in next, status[basefile].index do -                local index = #newstatus[basefile].index -                newmappings[#newmappings+1]        = mappings[v] -                newstatus[basefile].index[index+1] = #newmappings -            end -            report("log", 1, "db", "font already indexed", "%s", basefile) -            return +    local mappings      = fontnames.mappings +    local status        = fontnames.status +--  local fullnames     = fontnames.fullnames +    local basenames     = fontnames.basenames +    local barenames     = fontnames.barenames + +    local basename      = filebasename(fullname) +    local barename      = filenameonly(fullname) + +    --- entryname is apparently the identifier a font is +    --- loaded by; it is different for files in the texmf +    --- (due to kpse? idk.) +    --- entryname = texmf : true -> basename | false -> fullname +    local entryname     = texmf and basename or fullname + +    if not fullname then return false end + +    if names.blacklist[fullname] +    or names.blacklist[basename] +    then +        report("log", 2, "db", +            "ignoring blacklisted font “%s”", fullname) +        return false +    end +    local timestamp, db_timestamp +    db_timestamp        = status[entryname] +                        and status[entryname].timestamp +    timestamp           = lfs.attributes(fullname, "modification") + +    local index_status = newstatus[entryname] +                        or (not texmf and newstatus[basename]) +    local teststat = newstatus[entryname] +    --- index_status: nil | false | table +    if index_status and index_status.timestamp == timestamp then +        -- already indexed this run +        return false +    end + +    newstatus[entryname]           = newstatus[entryname] or { } +    newstatus[entryname].timestamp = timestamp +    newstatus[entryname].index     = newstatus[entryname].index or { } + +    if  db_timestamp == timestamp +    and not newstatus[entryname].index[1] then +        for _,v in next, status[entryname].index do +            local index    = #newstatus[entryname].index +            local fullinfo = mappings[v] +            newmappings[#newmappings+1]         = fullinfo --- keep +            newstatus[entryname].index[index+1] = #newmappings +--          newfullnames[fullname] = fullinfo.filename +            newbasenames[basename] = fullinfo.filename +            newbarenames[barename] = fullinfo.filename          end -        local info = fontloader.info(filename) -        if info then -            if type(info) == "table" and #info > 1 then -                for i in next, info do -                    local fullinfo = font_fullinfo(filename, i-1, texmf) -                    if not fullinfo then -                        return -                    end -                    local index = newstatus[basefile].index[i] -                    if newstatus[basefile].index[i] then -                        index = newstatus[basefile].index[i] -                    else -                        index = #newmappings+1 -                    end -                    newmappings[index]           = fullinfo -                    newstatus[basefile].index[i] = index -                end -            else -                local fullinfo = font_fullinfo(filename, false, texmf) +        report("log", 2, "db", "font “%s” already indexed", entryname) +        return false +    end + +    local info = fontloaderinfo(fullname) +    if info then +        if type(info) == "table" and #info > 1 then --- ttc +            for i in next, info do +                local fullinfo = font_fullinfo(fullname, i-1, texmf)                  if not fullinfo then -                    return +                    return false                  end -                local index -                if newstatus[basefile].index[1] then -                    index = newstatus[basefile].index[1] +                local index = newstatus[entryname].index[i] +                if newstatus[entryname].index[i] then +                    index = newstatus[entryname].index[i]                  else                      index = #newmappings+1                  end -                newmappings[index]           = fullinfo -                newstatus[basefile].index[1] = index +                newmappings[index]            = fullinfo +--              newfullnames[fullname]        = fullinfo.filename +                newbasenames[basename]        = fullinfo.filename +                newbarenames[barename]        = fullinfo.filename +                newstatus[entryname].index[i] = index              end          else -            report("log", 1, "db", "failed to load", "%s", basefile) +            local fullinfo = font_fullinfo(fullname, false, texmf) +            if not fullinfo then +                return false +            end +            local index +            if newstatus[entryname].index[1] then +                index = newstatus[entryname].index[1] +            else +                index = #newmappings+1 +            end +            newmappings[index]            = fullinfo +--          newfullnames[fullname]        = { fullinfo.filename[1], fullinfo.filename[2] } +            newbasenames[basename]        = { fullinfo.filename[1], fullinfo.filename[2] } +            newbarenames[barename]        = { fullinfo.filename[1], fullinfo.filename[2] } +            newstatus[entryname].index[1] = index          end + +    else --- missing info +        report("log", 1, "db", "failed to load “%s”", entryname) +        return false      end +    return true  end -local function path_normalize(path) -    --[[ -        path normalization: -        - a\b\c  -> a/b/c -        - a/../b -> b -        - /cygdrive/a/b -> a:/b -        - reading symlinks under non-Win32 -        - using kpse.readable_file on Win32 -    ]] -    if os.type == "windows" or os.type == "msdos" or os.name == "cygwin" then -        path = stringgsub(path, '\\', '/') -        path = stringlower(path) -        path = stringgsub(path, '^/cygdrive/(%a)/', '%1:/') -    end -    if os.type ~= "windows" and os.type ~= "msdos" then -        local dest = lfs.readlink(path) -        if dest then -            if kpsereadable_file(dest) then -                path = dest -            elseif kpsereadable_file(filejoin(file.dirname(path), dest)) then -                path = filejoin(file.dirname(path), dest) -            else -                -- broken symlink? +local path_normalize +do +    --- os.type and os.name are constants so we +    --- choose a normalization function in advance +    --- instead of testing with every call +    local os_type, os_name = os.type, os.name +    local filecollapsepath = filecollapsepath +    local lfsreadlink      = lfs.readlink + +    --- windows and dos +    if os_type == "windows" or os_type == "msdos" then +        --- ms platfom specific stuff +        path_normalize = function (path) +            path = stringgsub(path, '\\', '/') +            path = stringlower(path) +            path = stringgsub(path, '^/cygdrive/(%a)/', '%1:/') +            path = filecollapsepath(path) +            return path +        end + +    elseif os_name == "cygwin" then -- union of ms + unix +        path_normalize = function (path) +            path = stringgsub(path, '\\', '/') +            path = stringlower(path) +            path = stringgsub(path, '^/cygdrive/(%a)/', '%1:/') +            local dest = lfsreadlink(path) +            if dest then +                if kpsereadable_file(dest) then +                    path = dest +                elseif kpsereadable_file(filejoin(filedirname(path), dest)) then +                    path = filejoin(file.dirname(path), dest) +                else +                    -- broken symlink? +                end +            end +            path = filecollapsepath(path) +            return path +        end + +    else -- posix +        path_normalize = function (path) +            local dest = lfsreadlink(path) +            if dest then +                if kpsereadable_file(dest) then +                    path = dest +                elseif kpsereadable_file(filejoin(filedirname(path), dest)) then +                    path = filejoin(file.dirname(path), dest) +                else +                    -- broken symlink? +                end              end +            path = filecollapsepath(path) +            return path          end      end -    path = filecollapsepath(path) -    return path  end  fonts.path_normalize = path_normalize @@ -723,7 +881,7 @@ local function read_blacklist()                      if stringsub(line, 1, 1) == "-" then                          whitelist[stringsub(line, 2, -1)] = true                      else -                        report("log", 2, "db", "blacklisted file", "%s", line) +                        report("log", 2, "db", "blacklisted file “%s”", line)                          blacklist[line] = true                      end                  end @@ -741,85 +899,59 @@ for key, value in next, font_extensions do     font_extensions_set[value] = true  end ---local installed_fonts_scanned = false --- ugh - ---- we already have scan_os_fonts don’t we? - ---local function scan_installed_fonts(fontnames, newfontnames) ---    --- Try to query and add font list from operating system. ---    --- This uses the lualatex-platform module. ---    --- <phg>what for? why can’t we do this in Lua?</phg> ---    report("info", 0, "Scanning fonts known to operating system...") ---    local fonts = get_installed_fonts() ---    if fonts and #fonts > 0 then ---        installed_fonts_scanned = true ---        report("log", 2, "operating system fonts found", "%d", #fonts) ---        for key, value in next, fonts do ---            local file = value.path ---            if file then ---                local ext = fileextname(file) ---                if ext and font_extensions_set[ext] then ---                file = path_normalize(file) ---                    report("log", 1, "loading font", "%s", file) ---                load_font(file, fontnames, newfontnames, false) ---                end ---            end ---        end ---    else ---        report("log", 2, "Could not retrieve list of installed fonts") ---    end ---end - -local function scan_dir(dirname, fontnames, newfontnames, texmf) +--- string -> dbobj -> dbobj -> bool -> (int * int) +local scan_dir = function (dirname, fontnames, newfontnames, texmf)      --[[      This function scans a directory and populates the list of fonts      with all the fonts it finds.      - dirname is the name of the directory to scan -    - names is the font database to fill +    - names is the font database to fill -> no such term!!!      - texmf is a boolean saying if we are scanning a texmf directory      ]] -    local list, found = { }, { } -    local nbfound = 0 +    local n_scanned, n_new = 0, 0   --- total of fonts collected      report("log", 2, "db", "scanning", "%s", dirname)      for _,i in next, font_extensions do          for _,ext in next, { i, stringupper(i) } do -            found = dirglob(stringformat("%s/**.%s$", dirname, ext)) -            -- note that glob fails silently on broken symlinks, which happens -            -- sometimes in TeX Live. -            report("log", 2, "db", -                "fonts found", "%s '%s' fonts found", #found, ext) -            nbfound = nbfound + #found -            tableappend(list, found) +            local found = dirglob(stringformat("%s/**.%s$", dirname, ext)) +            local n_found = #found +            --- note that glob fails silently on broken symlinks, which +            --- happens sometimes in TeX Live. +            report("log", 2, "db", "%s '%s' fonts found", n_found, ext) +            n_scanned = n_scanned + n_found +            for j=1, n_found do +                local fullname = found[j] +                fullname = path_normalize(fullname) +                report("log", 2, "db", "loading font “%s”", fullname) +                local new = load_font(fullname, fontnames, newfontnames, texmf) +                if new then n_new = n_new + 1 end +            end          end      end -    report("log", 2, "db", -        "fonts found", "%d fonts found in '%s'", nbfound, dirname) - -    for _,file in next, list do -        file = path_normalize(file) -        report("log", 1, "db", -            "loading font", "%s", file) -        load_font(file, fontnames, newfontnames, texmf) -    end +    report("log", 2, "db", "%d fonts found in '%s'", n_scanned, dirname) +    return n_scanned, n_new  end  local function scan_texmf_fonts(fontnames, newfontnames) +    local n_scanned, n_new = 0, 0      --[[      This function scans all fonts in the texmf tree, through kpathsea      variables OPENTYPEFONTS and TTFONTS of texmf.cnf      ]]      if stringis_empty(kpseexpand_path("$OSFONTDIR")) then -        report("info", 1, "db", "Scanning TEXMF fonts...") +        report("info", 2, "db", "Scanning TEXMF fonts...")      else -        report("info", 1, "db", "Scanning TEXMF and OS fonts...") +        report("info", 2, "db", "Scanning TEXMF and OS fonts...")      end      local fontdirs = stringgsub(kpseexpand_path("$OPENTYPEFONTS"), "^%.", "")      fontdirs       = fontdirs .. stringgsub(kpseexpand_path("$TTFONTS"), "^%.", "")      if not stringis_empty(fontdirs) then          for _,d in next, filesplitpath(fontdirs) do -            scan_dir(d, fontnames, newfontnames, true) +            local found, new = scan_dir(d, fontnames, newfontnames, true) +            n_scanned = n_scanned + found +            n_new     = n_new     + new          end      end +    return n_scanned, n_new  end  --[[ @@ -851,7 +983,7 @@ read_fonts_conf = function (path, results, passed_paths)      passed_paths[#passed_paths+1] = path      passed_paths_set = tabletohash(passed_paths, true)      if not fh then -        report("log", 2, "db", "cannot open file", "%s", path) +        report("log", 2, "db", "cannot open file %s", path)          return results      end      local incomments = false @@ -942,8 +1074,6 @@ local function get_os_dirs()      else           local passed_paths = {}          local os_dirs = {} -        -- what about ~/config/fontconfig/fonts.conf etc?  -        -- Answer: they should be included by the others, please report if it's not          for _,p in next, {"/usr/local/etc/fonts/fonts.conf", "/etc/fonts/fonts.conf"} do              if lfs.isfile(p) then                  read_fonts_conf(p, os_dirs, passed_paths) @@ -955,25 +1085,33 @@ local function get_os_dirs()  end  local function scan_os_fonts(fontnames, newfontnames) +    local n_scanned, n_new = 0, 0      --[[      This function scans the OS fonts through        - fontcache for Unix (reads the fonts.conf file and scans the directories)        - a static set of directories for Windows and MacOSX      ]] -    report("info", 1, "db", "Scanning OS fonts...") -    report("info", 2, "db", "Searching in static system directories...") +    report("info", 2, "db", "Scanning OS fonts...") +    report("info", 3, "db", "Searching in static system directories...")      for _,d in next, get_os_dirs() do -        scan_dir(d, fontnames, newfontnames, false) +        local found, new = scan_dir(d, fontnames, newfontnames, false) +        n_scanned = n_scanned + found +        n_new     = n_new     + new      end +    return n_scanned, n_new  end +--- dbobj -> bool -> dbobj  update_names = function (fontnames, force) +    local starttime = os.gettimeofday() +    local n_scanned, n_new = 0, 0      --[[      The main function, scans everything -    - fontnames is the final table to return +    - “newfontnames” is the final table to return      - force is whether we rebuild it from scratch or not      ]] -    report("info", 1, "db", "Updating the font names database") +    report("info", 2, "db", "Updating the font names database" +                         .. (force and " forcefully" or ""))      if force then          fontnames = fontnames_init() @@ -991,16 +1129,29 @@ update_names = function (fontnames, force)      read_blacklist()      --installed_fonts_scanned = false      --scan_installed_fonts(fontnames, newfontnames) --- see fixme above -    scan_texmf_fonts(fontnames, newfontnames) +    local scanned, new = scan_texmf_fonts(fontnames, newfontnames) +    n_scanned = n_scanned + scanned +    n_new     = n_new     + new      --if  not installed_fonts_scanned      --and stringis_empty(kpseexpand_path("$OSFONTDIR"))      if stringis_empty(kpseexpand_path("$OSFONTDIR"))      then -        scan_os_fonts(fontnames, newfontnames) +        local scanned, new = scan_os_fonts(fontnames, newfontnames) +        n_scanned = n_scanned + scanned +        n_new     = n_new     + new      end +    --- stats: +    ---            before rewrite   | after rewrite +    ---   partial:         804 ms   |   701 ms +    ---   forced:        45384 ms   | 44714 ms +    report("info", 3, "db", +           "Scanned %d font files; %d new entries.", n_scanned, n_new) +    report("info", 3, "db", +           "Rebuilt in %0.f ms", 1000*(os.gettimeofday()-starttime))      return newfontnames  end +--- dbobj -> unit  save_names = function (fontnames)      local path  = names.path.dir      if not lfs.isdir(path) then @@ -1028,8 +1179,9 @@ scan_external_dir = function (dir)          fonts_loaded    = true      end      new_names = tablecopy(old_names) -    scan_dir(dir, old_names, new_names) +    local n_scanned, n_new = scan_dir(dir, old_names, new_names)      names.data = new_names +    return n_scanned, n_new  end  --- export functionality to the namespace “fonts.names” diff --git a/luaotfload-features.lua b/luaotfload-features.lua index 0121ede..78f8256 100644 --- a/luaotfload-features.lua +++ b/luaotfload-features.lua @@ -37,6 +37,12 @@ local stringfind       = string.find  local stringexplode    = string.explode  local stringis_empty   = string.is_empty +--[[doc-- +Apparently, these “modifiers” are another measure of emulating \XETEX, +cf. “About \XETEX”, by Jonathan Kew, 2005; and +    “The \XETEX Reference Guide”, by Will Robertson, 2011. +--doc]]-- +  local supported = {      b    = "bold",      i    = "italic", @@ -105,6 +111,8 @@ local defaults = {      },  } +local global_defaults = { mode = "node" } +  defaults.beng = defaults.deva  defaults.guru = defaults.deva  defaults.gujr = defaults.deva @@ -123,22 +131,36 @@ defaults.tibt = defaults.khmr  defaults.lao  = defaults.thai -local function set_default_features(script) -    local features -    local script = script or "dflt" +--- (string, string) dict -> (string, string) dict +local set_default_features = function (speclist) +    local script = speclist.script or "dflt" +      report("log", 0, "load font",          "auto-selecting default features for script: %s",          script) -    if defaults[script] then -        features = defaults[script] -    else -        features = defaults["dflt"] + +    local requested = defaults[script] +    if not requested then +        report("log", 0, "load font", +            "no defaults for script “%s”, falling back to “dflt”", +            script) +        requested = defaults.dflt      end -    for _,v in next, features do -        if feature_list[v] ~= false then -            feature_list[v] = true + +    for i=1, #requested do +        local feat = requested[i] +        if speclist[feat] ~= false then +            speclist[feat] = true          end      end + +    for feat, state in next, global_defaults do +        --- This is primarily intended for setting node +        --- mode unless “base” is requested, as stated +        --- in the manual. +        if not speclist[feat] then speclist[feat] = state end +    end +    return speclist  end  local function issome ()    feature_list.lookup = 'name' end @@ -173,7 +195,7 @@ local pattern    = (filename + fontname) * subvalue^0 * stylespec^0 * options^0  local function colonized(specification) -- xetex mode      feature_list = { }      lpeg.match(pattern,specification.specification) -    set_default_features(feature_list.script) +    feature_list = set_default_features(feature_list)      if feature_list.style then          specification.style = feature_list.style          feature_list.style = nil @@ -213,20 +235,22 @@ end  fonts.definers.registersplit(":",colonized,"cryptic")  fonts.definers.registersplit("", colonized,"more cryptic") -- catches \font\text=[names] -function fonts.definers.applypostprocessors(tfmdata) -    local postprocessors = tfmdata.postprocessors -    if postprocessors then -        for i=1,#postprocessors do -            local extrahash = postprocessors[i](tfmdata) -- after scaling etc -            if type(extrahash) == "string" and extrahash ~= "" then -                -- e.g. a reencoding needs this -                extrahash = string.gsub(lower(extrahash),"[^a-z]","-") -                tfmdata.properties.fullname = format("%s-%s",tfmdata.properties.fullname,extrahash) -            end -        end -    end -    return tfmdata -end +--- TODO below section is literally the same in luatex-fonts-def +---      why is it here? +--function fonts.definers.applypostprocessors(tfmdata) +--    local postprocessors = tfmdata.postprocessors +--    if postprocessors then +--        for i=1,#postprocessors do +--            local extrahash = postprocessors[i](tfmdata) -- after scaling etc +--            if type(extrahash) == "string" and extrahash ~= "" then +--                -- e.g. a reencoding needs this +--                extrahash = string.gsub(lower(extrahash),"[^a-z]","-") +--                tfmdata.properties.fullname = format("%s-%s",tfmdata.properties.fullname,extrahash) +--            end +--        end +--    end +--    return tfmdata +--end  ---[[ end included font-ltx.lua ]]  --[[doc-- diff --git a/luaotfload-merged.lua b/luaotfload-merged.lua index 314305a..da5e35a 100644 --- a/luaotfload-merged.lua +++ b/luaotfload-merged.lua @@ -1,6 +1,6 @@  -- merged file : luatex-fonts-merged.lua  -- parent file : luatex-fonts.lua --- merge date  : 04/20/13 13:33:53 +-- merge date  : 04/24/13 13:39:43  do -- begin closure to overcome local limits and interference @@ -2978,7 +2978,9 @@ function resolvers.unresolve(s)    return s  end  caches={} -local writable,readables=nil,{} +local writable=nil +local readables={} +local usingjit=jit  if not caches.namespace or caches.namespace=="" or caches.namespace=="context" then    caches.namespace='generic'  end @@ -3038,7 +3040,7 @@ end  local function makefullname(path,name)    if path and path~="" then      name="temp-"..name  -    return file.addsuffix(file.join(path,name),"lua"),file.addsuffix(file.join(path,name),"luc") +    return file.addsuffix(file.join(path,name),"lua"),file.addsuffix(file.join(path,name),usingjit and "lub" or "luc")    end  end  function caches.is_writable(path,name) @@ -3085,26 +3087,19 @@ function caches.savedata(path,name,data)      end    end  end -caches.compilemethod="both"  function caches.compile(data,luaname,lucname) -  local done=false -  if caches.compilemethod=="luac" or caches.compilemethod=="both" then -    done=os.spawn("texluac -o "..string.quoted(lucname).." -s "..string.quoted(luaname))==0 +  local d=io.loaddata(luaname) +  if not d or d=="" then +    d=table.serialize(data,true)     end -  if not done and (caches.compilemethod=="dump" or caches.compilemethod=="both") then -    local d=io.loaddata(luaname) -    if not d or d=="" then -      d=table.serialize(data,true)  -    end -    if d and d~="" then -      local f=io.open(lucname,'w') -      if f then -        local s=loadstring(d) -        if s then -          f:write(string.dump(s,true)) -        end -        f:close() +  if d and d~="" then +    local f=io.open(lucname,'w') +    if f then +      local s=loadstring(d) +      if s then +        f:write(string.dump(s,true))        end +      f:close()      end    end  end @@ -6103,6 +6098,14 @@ actions["reorganize lookups"]=function(data,filename,raw)                local current=coverage.current                if current then                  current=t_uncover(splitter,t_u_cache,current) +                local lookups=rule.lookups +                if lookups then +                  for i=1,#current do +                    if not lookups[i] then +                      lookups[i]=""  +                    end +                  end +                end                  rule.current=t_hashed(current,t_h_cache)                end                local after=coverage.after @@ -10313,6 +10316,819 @@ end -- closure  do -- begin closure to overcome local limits and interference +if not modules then modules={} end modules ['font-otp']={ +  version=1.001, +  comment="companion to font-otf.lua (packing)", +  author="Hans Hagen, PRAGMA-ADE, Hasselt NL", +  copyright="PRAGMA ADE / ConTeXt Development Team", +  license="see context related readme files" +} +local next,type=next,type +local sort,concat=table.sort,table.concat +local sortedhash=table.sortedhash +local trace_packing=false trackers.register("otf.packing",function(v) trace_packing=v end) +local trace_loading=false trackers.register("otf.loading",function(v) trace_loading=v end) +local report_otf=logs.reporter("fonts","otf loading") +fonts=fonts or {} +local handlers=fonts.handlers or {} +fonts.handlers=handlers +local otf=handlers.otf or {} +handlers.otf=otf +local enhancers=otf.enhancers or {} +otf.enhancers=enhancers +local glists=otf.glists or { "gsub","gpos" } +otf.glists=glists +local criterium=1 +local threshold=0 +local function tabstr_normal(t) +  local s={} +  local n=0 +  for k,v in next,t do +    n=n+1 +    if type(v)=="table" then +      s[n]=k..">"..tabstr_normal(v) +    elseif v==true then +      s[n]=k.."+"  +    elseif v then +      s[n]=k.."="..v +    else +      s[n]=k.."-"  +    end +  end +  if n==0 then +    return "" +  elseif n==1 then +    return s[1] +  else +    sort(s)  +    return concat(s,",") +  end +end +local function tabstr_flat(t) +  local s={} +  local n=0 +  for k,v in next,t do +    n=n+1 +    s[n]=k.."="..v +  end +  if n==0 then +    return "" +  elseif n==1 then +    return s[1] +  else +    sort(s)  +    return concat(s,",") +  end +end +local function tabstr_mixed(t)  +  local s={} +  local n=#t +  if n==0 then +    return "" +  elseif n==1 then +    local k=t[1] +    if k==true then +      return "++"  +    elseif k==false then +      return "--"  +    else +      return tostring(k)  +    end +  else +    for i=1,n do +      local k=t[i] +      if k==true then +        s[i]="++"  +      elseif k==false then +        s[i]="--"  +      else +        s[i]=k  +      end +    end +    return concat(s,",") +  end +end +local function tabstr_boolean(t) +  local s={} +  local n=0 +  for k,v in next,t do +    n=n+1 +    if v then +      s[n]=k.."+" +    else +      s[n]=k.."-" +    end +  end +  if n==0 then +    return "" +  elseif n==1 then +    return s[1] +  else +    sort(s)  +    return concat(s,",") +  end +end +local function packdata(data) +  if data then +    local h,t,c={},{},{} +    local hh,tt,cc={},{},{} +    local nt,ntt=0,0 +    local function pack_normal(v) +      local tag=tabstr_normal(v) +      local ht=h[tag] +      if ht then +        c[ht]=c[ht]+1 +        return ht +      else +        nt=nt+1 +        t[nt]=v +        h[tag]=nt +        c[nt]=1 +        return nt +      end +    end +    local function pack_flat(v) +      local tag=tabstr_flat(v) +      local ht=h[tag] +      if ht then +        c[ht]=c[ht]+1 +        return ht +      else +        nt=nt+1 +        t[nt]=v +        h[tag]=nt +        c[nt]=1 +        return nt +      end +    end +    local function pack_boolean(v) +      local tag=tabstr_boolean(v) +      local ht=h[tag] +      if ht then +        c[ht]=c[ht]+1 +        return ht +      else +        nt=nt+1 +        t[nt]=v +        h[tag]=nt +        c[nt]=1 +        return nt +      end +    end +    local function pack_indexed(v) +      local tag=concat(v," ") +      local ht=h[tag] +      if ht then +        c[ht]=c[ht]+1 +        return ht +      else +        nt=nt+1 +        t[nt]=v +        h[tag]=nt +        c[nt]=1 +        return nt +      end +    end +    local function pack_mixed(v) +      local tag=tabstr_mixed(v) +      local ht=h[tag] +      if ht then +        c[ht]=c[ht]+1 +        return ht +      else +        nt=nt+1 +        t[nt]=v +        h[tag]=nt +        c[nt]=1 +        return nt +      end +    end +    local function pack_final(v) +      if c[v]<=criterium then +        return t[v] +      else +        local hv=hh[v] +        if hv then +          return hv +        else +          ntt=ntt+1 +          tt[ntt]=t[v] +          hh[v]=ntt +          cc[ntt]=c[v] +          return ntt +        end +      end +    end +    local function success(stage,pass) +      if nt==0 then +        if trace_loading or trace_packing then +          report_otf("pack quality: nothing to pack") +        end +        return false +      elseif nt>=threshold then +        local one,two,rest=0,0,0 +        if pass==1 then +          for k,v in next,c do +            if v==1 then +              one=one+1 +            elseif v==2 then +              two=two+1 +            else +              rest=rest+1 +            end +          end +        else +          for k,v in next,cc do +            if v>20 then +              rest=rest+1 +            elseif v>10 then +              two=two+1 +            else +              one=one+1 +            end +          end +          data.tables=tt +        end +        if trace_loading or trace_packing then +          report_otf("pack quality: stage %s, pass %s, %s packed, 1-10:%s, 11-20:%s, rest:%s (criterium: %s)",stage,pass,one+two+rest,one,two,rest,criterium) +        end +        return true +      else +        if trace_loading or trace_packing then +          report_otf("pack quality: stage %s, pass %s, %s packed, aborting pack (threshold: %s)",stage,pass,nt,threshold) +        end +        return false +      end +    end +    local function packers(pass) +      if pass==1 then +        return pack_normal,pack_indexed,pack_flat,pack_boolean,pack_mixed +      else +        return pack_final,pack_final,pack_final,pack_final,pack_final +      end +    end +    local resources=data.resources +    local lookuptypes=resources.lookuptypes +    for pass=1,2 do +      if trace_packing then +        report_otf("start packing: stage 1, pass %s",pass) +      end +      local pack_normal,pack_indexed,pack_flat,pack_boolean,pack_mixed=packers(pass) +      for unicode,description in next,data.descriptions do +        local boundingbox=description.boundingbox +        if boundingbox then +          description.boundingbox=pack_indexed(boundingbox) +        end +        local slookups=description.slookups +        if slookups then +          for tag,slookup in next,slookups do +            local what=lookuptypes[tag] +            if what=="pair" then +              local t=slookup[2] if t then slookup[2]=pack_indexed(t) end +              local t=slookup[3] if t then slookup[3]=pack_indexed(t) end +            elseif what~="substitution" then +              slookups[tag]=pack_indexed(slookup)  +            end +          end +        end +        local mlookups=description.mlookups +        if mlookups then +          for tag,mlookup in next,mlookups do +            local what=lookuptypes[tag] +            if what=="pair" then +              for i=1,#mlookup do +                local lookup=mlookup[i] +                local t=lookup[2] if t then lookup[2]=pack_indexed(t) end +                local t=lookup[3] if t then lookup[3]=pack_indexed(t) end +              end +            elseif what~="substitution" then +              for i=1,#mlookup do +                mlookup[i]=pack_indexed(mlookup[i])  +              end +            end +          end +        end +        local kerns=description.kerns +        if kerns then +          for tag,kern in next,kerns do +            kerns[tag]=pack_flat(kern) +          end +        end +        local math=description.math +        if math then +          local kerns=math.kerns +          if kerns then +            for tag,kern in next,kerns do +              kerns[tag]=pack_normal(kern) +            end +          end +        end +        local anchors=description.anchors +        if anchors then +          for what,anchor in next,anchors do +            if what=="baselig" then +              for _,a in next,anchor do +                for k=1,#a do +                  a[k]=pack_indexed(a[k]) +                end +              end +            else +              for k,v in next,anchor do +                anchor[k]=pack_indexed(v) +              end +            end +          end +        end +      end +      local lookups=data.lookups +      if lookups then +        for _,lookup in next,lookups do +          local rules=lookup.rules +          if rules then +            for i=1,#rules do +              local rule=rules[i] +              local r=rule.before    if r then for i=1,#r do r[i]=pack_boolean(r[i]) end end +              local r=rule.after    if r then for i=1,#r do r[i]=pack_boolean(r[i]) end end +              local r=rule.current   if r then for i=1,#r do r[i]=pack_boolean(r[i]) end end +              local r=rule.replacements if r then rule.replacements=pack_flat  (r)  end  +              local r=rule.lookups   if r then rule.lookups=pack_indexed(r)  end +            end +          end +        end +      end +      local anchor_to_lookup=resources.anchor_to_lookup +      if anchor_to_lookup then +        for anchor,lookup in next,anchor_to_lookup do +          anchor_to_lookup[anchor]=pack_normal(lookup) +        end +      end +      local lookup_to_anchor=resources.lookup_to_anchor +      if lookup_to_anchor then +        for lookup,anchor in next,lookup_to_anchor do +          lookup_to_anchor[lookup]=pack_normal(anchor) +        end +      end +      local sequences=resources.sequences +      if sequences then +        for feature,sequence in next,sequences do +          local flags=sequence.flags +          if flags then +            sequence.flags=pack_normal(flags) +          end +          local subtables=sequence.subtables +          if subtables then +            sequence.subtables=pack_normal(subtables) +          end +          local features=sequence.features +          if features then +            for script,feature in next,features do +              features[script]=pack_normal(feature) +            end +          end +        end +      end +      local lookups=resources.lookups +      if lookups then +        for name,lookup in next,lookups do +          local flags=lookup.flags +          if flags then +            lookup.flags=pack_normal(flags) +          end +          local subtables=lookup.subtables +          if subtables then +            lookup.subtables=pack_normal(subtables) +          end +        end +      end +      local features=resources.features +      if features then +        for _,what in next,glists do +          local list=features[what] +          if list then +            for feature,spec in next,list do +              list[feature]=pack_normal(spec) +            end +          end +        end +      end +      if not success(1,pass) then +        return +      end +    end +    if nt>0 then +      for pass=1,2 do +        if trace_packing then +          report_otf("start packing: stage 2, pass %s",pass) +        end +        local pack_normal,pack_indexed,pack_flat,pack_boolean,pack_mixed=packers(pass) +        for unicode,description in next,data.descriptions do +          local kerns=description.kerns +          if kerns then +            description.kerns=pack_normal(kerns) +          end +          local math=description.math +          if math then +            local kerns=math.kerns +            if kerns then +              math.kerns=pack_normal(kerns) +            end +          end +          local anchors=description.anchors +          if anchors then +            description.anchors=pack_normal(anchors) +          end +          local mlookups=description.mlookups +          if mlookups then +            for tag,mlookup in next,mlookups do +              mlookups[tag]=pack_normal(mlookup) +            end +          end +        end +        local lookups=data.lookups +        if lookups then +          for _,lookup in next,lookups do +            local rules=lookup.rules +            if rules then +              for i=1,#rules do  +                local rule=rules[i] +                local r=rule.before if r then rule.before=pack_normal(r) end +                local r=rule.after  if r then rule.after=pack_normal(r) end +                local r=rule.current if r then rule.current=pack_normal(r) end +              end +            end +          end +        end +        local sequences=resources.sequences +        if sequences then +          for feature,sequence in next,sequences do +            sequence.features=pack_normal(sequence.features) +          end +        end +        if not success(2,pass) then +        end +      end +      for pass=1,2 do +        local pack_normal,pack_indexed,pack_flat,pack_boolean,pack_mixed=packers(pass) +        for unicode,description in next,data.descriptions do +          local slookups=description.slookups +          if slookups then +            description.slookups=pack_normal(slookups) +          end +          local mlookups=description.mlookups +          if mlookups then +            description.mlookups=pack_normal(mlookups) +          end +        end +      end +    end +  end +end +local unpacked_mt={ +  __index=function(t,k) +      t[k]=false +      return k  +    end +} +local function unpackdata(data) +  if data then +    local tables=data.tables +    if tables then +      local resources=data.resources +      local lookuptypes=resources.lookuptypes +      local unpacked={} +      setmetatable(unpacked,unpacked_mt) +      for unicode,description in next,data.descriptions do +        local tv=tables[description.boundingbox] +        if tv then +          description.boundingbox=tv +        end +        local slookups=description.slookups +        if slookups then +          local tv=tables[slookups] +          if tv then +            description.slookups=tv +            slookups=unpacked[tv] +          end +          if slookups then +            for tag,lookup in next,slookups do +              local what=lookuptypes[tag] +              if what=="pair" then +                local tv=tables[lookup[2]] +                if tv then +                  lookup[2]=tv +                end +                local tv=tables[lookup[3]] +                if tv then +                  lookup[3]=tv +                end +              elseif what~="substitution" then +                local tv=tables[lookup] +                if tv then +                  slookups[tag]=tv +                end +              end +            end +          end +        end +        local mlookups=description.mlookups +        if mlookups then +          local tv=tables[mlookups] +          if tv then +            description.mlookups=tv +            mlookups=unpacked[tv] +          end +          if mlookups then +            for tag,list in next,mlookups do +              local tv=tables[list] +              if tv then +                mlookups[tag]=tv +                list=unpacked[tv] +              end +              if list then +                local what=lookuptypes[tag] +                if what=="pair" then +                  for i=1,#list do +                    local lookup=list[i] +                    local tv=tables[lookup[2]] +                    if tv then +                      lookup[2]=tv +                    end +                    local tv=tables[lookup[3]] +                    if tv then +                      lookup[3]=tv +                    end +                  end +                elseif what~="substitution" then +                  for i=1,#list do +                    local tv=tables[list[i]] +                    if tv then +                      list[i]=tv +                    end +                  end +                end +              end +            end +          end +        end +        local kerns=description.kerns +        if kerns then +          local tm=tables[kerns] +          if tm then +            description.kerns=tm +            kerns=unpacked[tm] +          end +          if kerns then +            for k,kern in next,kerns do +              local tv=tables[kern] +              if tv then +                kerns[k]=tv +              end +            end +          end +        end +        local math=description.math +        if math then +          local kerns=math.kerns +          if kerns then +            local tm=tables[kerns] +            if tm then +              math.kerns=tm +              kerns=unpacked[tm] +            end +            if kerns then +              for k,kern in next,kerns do +                local tv=tables[kern] +                if tv then +                  kerns[k]=tv +                end +              end +            end +          end +        end +        local anchors=description.anchors +        if anchors then +          local ta=tables[anchors] +          if ta then +            description.anchors=ta +            anchors=unpacked[ta] +          end +          if anchors then +            for tag,anchor in next,anchors do +              if tag=="baselig" then +                for _,list in next,anchor do +                  for i=1,#list do +                    local tv=tables[list[i]] +                    if tv then +                      list[i]=tv +                    end +                  end +                end +              else +                for a,data in next,anchor do +                  local tv=tables[data] +                  if tv then +                    anchor[a]=tv +                  end +                end +              end +            end +          end +        end +      end +      local lookups=data.lookups +      if lookups then +        for _,lookup in next,lookups do +          local rules=lookup.rules +          if rules then +            for i=1,#rules do  +              local rule=rules[i] +              local before=rule.before +              if before then +                local tv=tables[before] +                if tv then +                  rule.before=tv +                  before=unpacked[tv] +                end +                if before then +                  for i=1,#before do +                    local tv=tables[before[i]] +                    if tv then +                      before[i]=tv +                    end +                  end +                end +              end +              local after=rule.after +              if after then +                local tv=tables[after] +                if tv then +                  rule.after=tv +                  after=unpacked[tv] +                end +                if after then +                  for i=1,#after do +                    local tv=tables[after[i]] +                    if tv then +                      after[i]=tv +                    end +                  end +                end +              end +              local current=rule.current +              if current then +                local tv=tables[current] +                if tv then +                  rule.current=tv +                  current=unpacked[tv] +                end +                if current then +                  for i=1,#current do +                    local tv=tables[current[i]] +                    if tv then +                      current[i]=tv +                    end +                  end +                end +              end +              local replacements=rule.replacements +              if replacements then +                local tv=tables[replacements] +                if tv then +                  rule.replacements=tv +                end +              end +              local fore=rule.fore +              if fore then +                local tv=tables[fore] +                if tv then +                  rule.fore=tv +                end +              end +              local back=rule.back +              if back then +                local tv=tables[back] +                if tv then +                  rule.back=tv +                end +              end +              local names=rule.names +              if names then +                local tv=tables[names] +                if tv then +                  rule.names=tv +                end +              end +              local lookups=rule.lookups +              if lookups then +                local tv=tables[lookups] +                if tv then +                  rule.lookups=tv +                end +              end +            end +          end +        end +      end +      local anchor_to_lookup=resources.anchor_to_lookup +      if anchor_to_lookup then +        for anchor,lookup in next,anchor_to_lookup do +          local tv=tables[lookup] +          if tv then +            anchor_to_lookup[anchor]=tv +          end +        end +      end +      local lookup_to_anchor=resources.lookup_to_anchor +      if lookup_to_anchor then +        for lookup,anchor in next,lookup_to_anchor do +          local tv=tables[anchor] +          if tv then +            lookup_to_anchor[lookup]=tv +          end +        end +      end +      local ls=resources.sequences +      if ls then +        for _,feature in next,ls do +          local flags=feature.flags +          if flags then +            local tv=tables[flags] +            if tv then +              feature.flags=tv +            end +          end +          local subtables=feature.subtables +          if subtables then +            local tv=tables[subtables] +            if tv then +              feature.subtables=tv +            end +          end +          local features=feature.features +          if features then +            local tv=tables[features] +            if tv then +              feature.features=tv +              features=unpacked[tv] +            end +            if features then +              for script,data in next,features do +                local tv=tables[data] +                if tv then +                  features[script]=tv +                end +              end +            end +          end +        end +      end +      local lookups=resources.lookups +      if lookups then +        for _,lookup in next,lookups do +          local flags=lookup.flags +          if flags then +            local tv=tables[flags] +            if tv then +              lookup.flags=tv +            end +          end +          local subtables=lookup.subtables +          if subtables then +            local tv=tables[subtables] +            if tv then +              lookup.subtables=tv +            end +          end +        end +      end +      local features=resources.features +      if features then +        for _,what in next,glists do +          local feature=features[what] +          if feature then +            for tag,spec in next,feature do +              local tv=tables[spec] +              if tv then +                feature[tag]=tv +              end +            end +          end +        end +      end +      data.tables=nil +    end +  end +end +if otf.enhancers.register then +  otf.enhancers.register("pack",packdata) +  otf.enhancers.register("unpack",unpackdata) +end +otf.enhancers.unpack=unpackdata  + +end -- closure + +do -- begin closure to overcome local limits and interference +  if not modules then modules={} end modules ['luatex-fonts-lua']={    version=1.001,    comment="companion to luatex-*.tex", diff --git a/luaotfload-override.lua b/luaotfload-override.lua index 94f2376..726000d 100644 --- a/luaotfload-override.lua +++ b/luaotfload-override.lua @@ -69,9 +69,12 @@ logs.names_report = function (mode, lvl, ...)      end      if not lvl then lvl = 0 end -    if loglevel > lvl then +    if loglevel >= lvl then          if mode == "log" then              log (...) +        elseif mode == "both" then +            log (...) +            stdout (...)          else              stdout (...)          end diff --git a/luaotfload.dtx b/luaotfload.dtx index 7c74a37..18e01d8 100644 --- a/luaotfload.dtx +++ b/luaotfload.dtx @@ -158,6 +158,8 @@ and the derived files  \newcommand*\email[1]{\href{mailto:#1}{#1}} +\renewcommand\partname{Part}%% gets rid of the stupid “file” heading +  \VerbatimFootnotes  \begin{document}    \DocInput{luaotfload.dtx}% @@ -868,6 +870,7 @@ and the derived files  %                     \incitem{font-otf.lua} \incitem{font-otb.lua}  %                     \incitem{node-inj.lua} \incitem{font-ota.lua}  %                     \incitem{font-otn.lua} \incitem{font-def.lua} +%                     \incitem{font-otp.lua}  %                   \end{itemize}  %                 \end{multicols}  %   \end{itemize} @@ -882,6 +885,18 @@ and the derived files  % \CONTEXT beta, all you have to do is remove  % \fileent{luaotfload-merged.lua} from the search path.  % +% Also, the merged file at some point +% loads the Adobe Glyph List from a \LUA table that is contained in +% \fileent{font-age.lua}, which is automatically generated by the +% script \fileent{mkglyphlist}.\footnote{% +%   See \fileent{luaotfload-font-enc.lua}. +%   The hard-coded file name is why the file lacks the \fileent{luaotfload-} +%   prefix. +% } +% There is a make target \identifier{glyphs} that will create a fresh +% \fileent{font-age.lua} so we don’t need to import it from \CONTEXT +% any longer. +%  % In addition to these, \identifier{luaotfload} requires a number of  % files not contained in the merge. Some of these have no equivalent in  % \LUATEX-Fonts or \CONTEXT, some were taken unmodified from the @@ -893,21 +908,20 @@ and the derived files  %       \normalitem{\fileent{#1}}%  %       \space--\hskip1em  %     } -%     \ouritem {luaotfload-font-otc.lua} \fileent{font-otc} from \CONTEXT; -%                                  font feature handling. -%     \ouritem {luaotfload-lib-dir.lua}  \fileent{l-dir} from \CONTEXT; -%                                  contains functionality required -%                                  by \fileent{luaotfload-font-nms.lua}. -%     \ouritem {luaotfload-luat-ovr.lua} overrides the \CONTEXT logging -%                                  functionality. -%     \ouritem {luaotfload-font-pfb.lua} registers the \OpenType -%                                  font reader as handler for -%                                  Postscript fonts. -%     \ouritem {luaotfload-font-nms.lua} font database. -%     \ouritem {luaotfload-font-clr.lua} color handling. -%     \ouritem {luaotfload-font-ltx.lua} font feature handling. -%     \ouritem {luaotfload-features.lua} definitions of the \verb|anum| and -%                                  \verb|tlig| features. +%     \ouritem {luaotfload-features.lua}   font feature handling; +%                                          incorporates some of the code from +%                                          \fileent{font-otc} from \CONTEXT; +%     \ouritem {luaotfload-lib-dir.lua}    \fileent{l-dir} from \CONTEXT; +%                                          contains functionality required +%                                          by \fileent{luaotfload-font-nms.lua}. +%     \ouritem {luaotfload-override.lua}   overrides the \CONTEXT logging +%                                          functionality. +%     \ouritem {luaotfload-loaders.lua}    registers the \OpenType +%                                          font reader as handler for +%                                          Postscript fonts +%                                          (\abbrev{pfa}, \abbrev{pfb}). +%     \ouritem {luaotfload-database.lua}   font names database. +%     \ouritem {luaotfload-colors.lua}     color handling.  % \end{itemize}  %  % \begin{figure}[b] @@ -922,6 +936,10 @@ and the derived files  % version of this package before reporting a bug, as  % \identifier{luaotfload} is under active development and still a  % moving target. +% The development takes place on \identifier{github} at +% \url{https://github.com/lualatex/luaotfload} where there is an issue +% tracker for submitting bug reports, feature requests and the likes +% requests and the likes.  %  % Errors during database generation can be traced by increasing  % verbosity levels and redirecting log output to \fileent{stdout}: @@ -1024,13 +1042,19 @@ local error, warning, info, log =      luatexbase.provides_module(luaotfload.module)  %    \end{macrocode} -% -%    We set the minimum version requirement for \LUATEX to v0.74, as it was -%    the first version to include version 5.2 of the \LUA interpreter. +%    We set the minimum version requirement for \LUATEX to v0.76, +%    because the font loader requires recent features like direct +%    attribute indexing and \luafunction{node.end_of_math()} that aren’t +%    available in earlier versions.\footnote{% +%     See Taco’s announcement of v0.76: +%     \url{http://comments.gmane.org/gmane.comp.tex.luatex.user/4042} +%     and this commit by Hans that introduced those features. +%     \url{http://repo.or.cz/w/context.git/commitdiff/a51f6cf6ee087046a2ae5927ed4edff0a1acec1b}. +%   }  %  %    \begin{macrocode} -local luatex_version = 74 +local luatex_version = 76  if tex.luatexversion < luatex_version then      warning("LuaTeX v%.2f is old, v%.2f is recommended.", @@ -1093,7 +1117,6 @@ end  % \fileent{luaotfload-merged.lua}.  % If this file cannot be found, the original libraries from \CONTEXT of  % which the merged code was composed are loaded instead. -%  % The imported font loader will call \luafunction{callback.register} once  % while reading \fileent{font-def.lua}.  % This is unavoidable unless we modify the imported files, but harmless @@ -1251,6 +1274,7 @@ else--- the loading sequence is known to change, so this might have to      loadmodule('node-inj.lua')      loadmodule('font-ota.lua')      loadmodule('font-otn.lua') +    loadmodule('font-otp.lua')--- since 2013-04-23      loadmodule('luatex-fonts-lua.lua')      loadmodule('font-def.lua')      loadmodule('luatex-fonts-def.lua') @@ -1304,6 +1328,8 @@ add_to_callback("find_vf_file",  loadmodule"lib-dir.lua"   --- required by luaofload-database.lua  loadmodule"override.lua"  --- “luat-ovr” +logs.set_loglevel(0) +  %    \end{macrocode}  % \CONTEXT does not support ofm, these lines were added in order to make it  % work. However they do not seem necessary so they are commented for now. @@ -1325,9 +1351,17 @@ loadmodule"colors.lua"     --- “font-clr”  %    \end{macrocode}  % This hack makes fonts called with file method found by fonts.names.resolve -% instead of just trying to find them with kpse. It is necessary in case -% of fonts that are not accessible by kpse but present in the database, a -% quite common case under Linux. +% instead of just trying to find them with \identifier{kpse}. +% It is necessary in cases when font files are not reachable by +% \identifier{kpse} but present in the database, a quite common case +% under Linux. +% +% As of 2013-04-24 we have a workaround in the resolver that handles +% \verb|file:| lookups diverted this way. +% It requires some overhead due to additional extra data saved in the +% names database, and might vanish entirely once the font request syntax +% is understood. +% Until then it is considered a kludge, like the hack below.  %  %    \begin{macrocode} @@ -1375,7 +1409,7 @@ local define_font_wrapper = function (...)                  --- definers.read                  if stringfind(k, "Percent") then                      -- keep percent values as is -                    print(k,v) +                    --print(k,v)                      mathconstants[k] = v                  else                      mathconstants[k] = v / units_per_em * size @@ -1401,8 +1435,10 @@ end  %    \begin{macrocode}  local read_font_file = fonts.definers.read -local patch_defined_font = function (...) -    local tfmdata = read_font_file(...)-- spec -> size -> id -> tmfdata + +--- spec -> size -> id -> tmfdata +local patch_defined_font = function (specification, size, id) +    local tfmdata = read_font_file(specification, size, id)      if type(tfmdata) == "table" then          call_callback("luaotfload.patch_font", tfmdata)      end @@ -1472,7 +1508,6 @@ loadmodule"features.lua" --- contains what was “font-ltx” and “font-otc”  -- vim:tw=71:sw=4:ts=4:expandtab -  %    \end{macrocode}  %  % \iffalse diff --git a/mkglyphlist b/mkglyphlist new file mode 100755 index 0000000..9ee1528 --- /dev/null +++ b/mkglyphlist @@ -0,0 +1,143 @@ +#!/usr/bin/env texlua +----------------------------------------------------------------------- +--         FILE:  mkglyphlist.lua +--        USAGE:  ./mkglyphlist.lua  +--  DESCRIPTION:  part of the luaotfload package +-- REQUIREMENTS:  lua, lpeg, luasocket, the lualibs package +--       AUTHOR:  Philipp Gesang (Phg), <phg42.2a@gmail.com> +--      VERSION:  1.0 +--      CREATED:  04/23/2013 12:42:17 PM CEST +----------------------------------------------------------------------- +--                              config +----------------------------------------------------------------------- +local glyphfile     = "./glyphlist.txt" +local font_age      = "./font-age.lua" +local glyph_source  = "http://partners.adobe.com/public/developer/en/opentype/glyphlist.txt" + +----------------------------------------------------------------------- +--                             includes +----------------------------------------------------------------------- +require"lpeg" +require"socket" + +kpse.set_program_name"luatex" +dofile(kpse.find_file("lualibs-lua.lua",   "lua")) +dofile(kpse.find_file("lualibs-lpeg.lua",  "lua")) +dofile(kpse.find_file("lualibs-table.lua", "lua")) --- for serialization + +local C, Cf, Cg, Ct, P, R = +  lpeg.C, lpeg.Cf, lpeg.Cg, lpeg.Ct, lpeg.P, lpeg.R + +local http = socket.http + +----------------------------------------------------------------------- +--                           functionality +----------------------------------------------------------------------- + +local dec_of_hex = function (hex) return tonumber(hex, 16) end + +local separator    = P";" +local gartenzaun   = P"#" +local eol          = P"\n\r" + P"\r\n" + P"\r" + P"\n" +local space        = P" " +local alphanum     = R("az", "AZ", "09") +local hexdigit     = R("af", "AF", "09") +local eof_tag      = gartenzaun * P"--end" +local header_line  = gartenzaun * (1-eol)^0 * eol +local codepoint    = hexdigit^1 +local glyphname    = alphanum^1 + +local definition   = Cg(C(glyphname) * separator * (C(codepoint)/ dec_of_hex)) +                   --- With combined glyphs we take only the first +                   --- value as char-def and font-age do, and skip +                   --- the rest. +                   * (space * codepoint)^0 +                   * eol +local definitions  = Cf(Ct"" * definition^1, rawset) + +local p_glyphs     = header_line^0 * definitions * eof_tag + +local get_glyphs = function (data) +  local res = lpeg.match(p_glyphs, data) +  if not res then +    print("error: could not parse glyph list") +    os.exit(-1) +  end +  return res +end + +local file_header = [==[ +if not modules then modules = { } end modules ["font-age"] = { +  version     = 2.200, +  comment     = "part of the luaotfload package", +  author      = "luaotfload team / mkglyphlist", +  copyright   = "derived from %s", +  original    = "Adobe Glyph List, version 2.0, September 20, 2002", +  dataonly    = true, +} + +if context then +  logs.report("fatal error","this module is not for context") +  os.exit(-1) +end + +--[[doc-- +Everything below has been autogenerated. Run mkglyphlist to rebuild +font-age.lua. +--doc]]-- + +]==] + +local writedata = function (data) +  data = table.serialize(data, true) +  data = string.format(file_header, glyph_source) .. data +  local fh = io.open(font_age, "wb") +  if not fh then +    print(string.format("error: %s not writable", font_age)) +    os.exit(-1) +  end +  print(string.format("saving %d bytes to %s", #data, font_age)) +  fh:write(data) +  fh:close() +end + + +local get_raw get_raw = function (retry) +  local fh = io.open(glyphfile, "rb") +  if fh then +    local data = fh:read"*all" +    fh:close() +    if data then return data end +  elseif not retry then --- attempt download +    print"info: retrieving glyph list from" +    print(glyph_source) +    local glyphdata = http.request(glyph_source) +    if glyphdata then +      local fh = io.open(glyphfile, "wb") +      if not fh then +        print"error: glyph file not writable" +        os.exit(-1) +      end +      fh:write(glyphdata) +      fh:close() +      return get_raw(true) +    end +    print"error: download failed" +    os.exit(-1) +  end +  print("error: could not obtain glyph data from "..glyphfile) +  os.exit(-1) +end + +local main = function () +  if arg[1] then glyphfile = arg[1] end +  if arg[2] then font_age  = arg[2] end + +  local data    = get_raw() +  local parsed  = get_glyphs(data) +  writedata(parsed) +  return 0 +end + + +return main() diff --git a/tests/lookups.tex b/tests/lookups.tex index db26312..8b03d8e 100644 --- a/tests/lookups.tex +++ b/tests/lookups.tex @@ -5,10 +5,16 @@  \font\second=file:antpoltltsemiexpd-bolditalic.otf at 42pt  %% lookup font by name, with style in slash notation  \font\third={name:Antykwa torunska/I} at 42pt +%% unspecified lookup; in definers.read: +%%  - first it falls back to “file” +%%  - empty “method” field triggers fallback to “name” +%%  - names.resolve -> kpse.lookup -> hit! +\font\fourth=iwona at 42pt  {\first   foo \endgraf}  {\second  bar \endgraf}  {\third   baz \endgraf} +{\fourth  xyzzy \endgraf}  \bye | 
