diff --git a/tex/compat/ltluatex/ltluatex.lua b/tex/compat/ltluatex/ltluatex.lua deleted file mode 100644 index cbd933531ebf37632334da415957975053cc69fb..0000000000000000000000000000000000000000 --- a/tex/compat/ltluatex/ltluatex.lua +++ /dev/null @@ -1,521 +0,0 @@ --- --- This is file `ltluatex.lua', --- generated with the docstrip utility. --- --- The original source files were: --- --- ltluatex.dtx (with options: `lua') --- --- This is a generated file. --- --- The source is maintained by the LaTeX Project team and bug --- reports for it can be opened at http://latex-project.org/bugs.html --- (but please observe conditions on bug reports sent to that address!) --- --- --- Copyright 2015 --- The LaTeX3 Project and any individual authors listed elsewhere --- in this file. --- --- This file was generated from file(s) of the LaTeX base system. --- -------------------------------------------------------------- --- --- It may be distributed and/or modified under the --- conditions of the LaTeX Project Public License, either version 1.3c --- of this license or (at your option) any later version. --- The latest version of this license is in --- http://www.latex-project.org/lppl.txt --- and version 1.3c or later is part of all distributions of LaTeX --- version 2005/12/01 or later. --- --- This file has the LPPL maintenance status "maintained". --- --- This file may only be distributed together with a copy of the LaTeX --- base system. You may however distribute the LaTeX base system without --- such generated files. --- --- The list of all files belonging to the LaTeX base distribution is --- given in the file `manifest.txt'. See also `legal.txt' for additional --- information. --- --- The list of derived (unpacked) files belonging to the distribution --- and covered by LPPL is defined by the unpacking scripts (with --- extension .ins) which are part of the distribution. -luatexbase = luatexbase or { } -local luatexbase = luatexbase -local string_gsub = string.gsub -local tex_count = tex.count -local tex_setattribute = tex.setattribute -local tex_setcount = tex.setcount -local texio_write_nl = texio.write_nl -local luatexbase_warning -local luatexbase_error -local modules = modules or { } -local function luatexbase_log(text) - texio_write_nl("log", text) -end -local function provides_module(info) - if not (info and info.name) then - luatexbase_error("Missing module name for provides_module") - end - local function spaced(text) - return text and (" " .. text) or "" - end - luatexbase_log( - "Lua module: " .. info.name - .. spaced(info.date) - .. spaced(info.version) - .. spaced(info.description) - ) - modules[info.name] = info -end -luatexbase.provides_module = provides_module -local function msg_format(mod, msg_type, text) - local leader = "" - local cont - local first_head - if mod == "LaTeX" then - cont = string_gsub(leader, ".", " ") - first_head = leader .. "LaTeX: " - else - first_head = leader .. "Module " .. msg_type - cont = "(" .. mod .. ")" - .. string_gsub(first_head, ".", " ") - first_head = leader .. "Module " .. mod .. " " .. msg_type .. ":" - end - if msg_type == "Error" then - first_head = "\n" .. first_head - end - if string.sub(text,-1) ~= "\n" then - text = text .. " " - end - return first_head .. " " - .. string_gsub( - text - .. "on input line " - .. tex.inputlineno, "\n", "\n" .. cont .. " " - ) - .. "\n" -end -local function module_info(mod, text) - texio_write_nl("log", msg_format(mod, "Info", text)) -end -luatexbase.module_info = module_info -local function module_warning(mod, text) - texio_write_nl("term and log",msg_format(mod, "Warning", text)) -end -luatexbase.module_warning = module_warning -local function module_error(mod, text) - error(msg_format(mod, "Error", text)) -end -luatexbase.module_error = module_error -function luatexbase_warning(text) - module_warning("luatexbase", text) -end -function luatexbase_error(text) - module_error("luatexbase", text) -end -local luaregisterbasetable = { } -local registermap = { - attributezero = "assign_attr" , - charzero = "char_given" , - CountZero = "assign_int" , - dimenzero = "assign_dimen" , - mathcharzero = "math_given" , - muskipzero = "assign_mu_skip" , - skipzero = "assign_skip" , - tokszero = "assign_toks" , -} -local createtoken -if tex.luatexversion > 81 then - createtoken = token.create -elseif tex.luatexversion > 79 then - createtoken = newtoken.create -end -local hashtokens = tex.hashtokens() -local luatexversion = tex.luatexversion -for i,j in pairs (registermap) do - if luatexversion < 80 then - luaregisterbasetable[hashtokens[i][1]] = - hashtokens[i][2] - else - luaregisterbasetable[j] = createtoken(i).mode - end -end -local registernumber -if luatexversion < 80 then - function registernumber(name) - local nt = hashtokens[name] - if(nt and luaregisterbasetable[nt[1]]) then - return nt[2] - luaregisterbasetable[nt[1]] - else - return false - end - end -else - function registernumber(name) - local nt = createtoken(name) - if(luaregisterbasetable[nt.cmdname]) then - return nt.mode - luaregisterbasetable[nt.cmdname] - else - return false - end - end -end -luatexbase.registernumber = registernumber -local attributes=setmetatable( -{}, -{ -__index = function(t,key) -return registernumber(key) or nil -end} -) -luatexbase.attributes=attributes -local function new_attribute(name) - tex_setcount("global", "e@alloc@attribute@count", - tex_count["e@alloc@attribute@count"] + 1) - if tex_count["e@alloc@attribute@count"] > 65534 then - luatexbase_error("No room for a new \\attribute") - end - attributes[name]= tex_count["e@alloc@attribute@count"] - luatexbase_log("Lua-only attribute " .. name .. " = " .. - tex_count["e@alloc@attribute@count"]) - return tex_count["e@alloc@attribute@count"] -end -luatexbase.new_attribute = new_attribute -local function new_whatsit(name) - tex_setcount("global", "e@alloc@whatsit@count", - tex_count["e@alloc@whatsit@count"] + 1) - if tex_count["e@alloc@whatsit@count"] > 65534 then - luatexbase_error("No room for a new custom whatsit") - end - luatexbase_log("Custom whatsit " .. (name or "") .. " = " .. - tex_count["e@alloc@whatsit@count"]) - return tex_count["e@alloc@whatsit@count"] -end -luatexbase.new_whatsit = new_whatsit -local function new_bytecode(name) - tex_setcount("global", "e@alloc@bytecode@count", - tex_count["e@alloc@bytecode@count"] + 1) - if tex_count["e@alloc@bytecode@count"] > 65534 then - luatexbase_error("No room for a new bytecode register") - end - luatexbase_log("Lua bytecode " .. (name or "") .. " = " .. - tex_count["e@alloc@bytecode@count"]) - return tex_count["e@alloc@bytecode@count"] -end -luatexbase.new_bytecode = new_bytecode -local function new_chunkname(name) - tex_setcount("global", "e@alloc@luachunk@count", - tex_count["e@alloc@luachunk@count"] + 1) - local chunkname_count = tex_count["e@alloc@luachunk@count"] - chunkname_count = chunkname_count + 1 - if chunkname_count > 65534 then - luatexbase_error("No room for a new chunkname") - end - lua.name[chunkname_count]=name - luatexbase_log("Lua chunkname " .. (name or "") .. " = " .. - chunkname_count .. "\n") - return chunkname_count -end -luatexbase.new_chunkname = new_chunkname -local callbacklist = callbacklist or { } -local list, data, exclusive, simple = 1, 2, 3, 4 -local types = { - list = list, - data = data, - exclusive = exclusive, - simple = simple, -} -local callbacktypes = callbacktypes or { - find_read_file = exclusive, - find_write_file = exclusive, - find_font_file = data, - find_output_file = data, - find_format_file = data, - find_vf_file = data, - find_map_file = data, - find_enc_file = data, - find_sfd_file = data, - find_pk_file = data, - find_data_file = data, - find_opentype_file = data, - find_truetype_file = data, - find_type1_file = data, - find_image_file = data, - open_read_file = exclusive, - read_font_file = exclusive, - read_vf_file = exclusive, - read_map_file = exclusive, - read_enc_file = exclusive, - read_sfd_file = exclusive, - read_pk_file = exclusive, - read_data_file = exclusive, - read_truetype_file = exclusive, - read_type1_file = exclusive, - read_opentype_file = exclusive, - find_cidmap_file = data, - read_cidmap_file = exclusive, - process_input_buffer = data, - process_output_buffer = data, - process_jobname = data, - contribute_filter = simple, - buildpage_filter = simple, - pre_linebreak_filter = list, - linebreak_filter = list, - append_to_vlist_filter = list, - post_linebreak_filter = list, - hpack_filter = list, - vpack_filter = list, - hpack_quality = list, - vpack_quality = list, - pre_output_filter = list, - process_rule = list, - hyphenate = simple, - ligaturing = simple, - kerning = simple, - insert_local_par = simple, - mlist_to_hlist = list, - pre_dump = simple, - start_run = simple, - stop_run = simple, - start_page_number = simple, - stop_page_number = simple, - show_error_hook = simple, - show_warning_message = simple, - show_error_message = simple, - show_lua_error_hook = simple, - start_file = simple, - stop_file = simple, - finish_pdffile = data, - finish_pdfpage = data, - define_font = exclusive, -} -luatexbase.callbacktypes=callbacktypes -local callback_register = callback_register or callback.register -function callback.register() - luatexbase_error("Attempt to use callback.register() directly\n") -end -local function data_handler(name) - return function(data, ...) - for _,i in ipairs(callbacklist[name]) do - data = i.func(data,...) - end - return data - end -end -local function exclusive_handler(name) - return function(...) - return callbacklist[name][1].func(...) - end -end -local function list_handler(name) - return function(head, ...) - local ret - local alltrue = true - for _,i in ipairs(callbacklist[name]) do - ret = i.func(head, ...) - if ret == false then - luatexbase_warning( - "Function `" .. i.description .. "' returned false\n" - .. "in callback `" .. name .."'" - ) - break - end - if ret ~= true then - alltrue = false - head = ret - end - end - return alltrue and true or head - end -end -local function simple_handler(name) - return function(...) - for _,i in ipairs(callbacklist[name]) do - i.func(...) - end - end -end -local handlers = { - [data] = data_handler, - [exclusive] = exclusive_handler, - [list] = list_handler, - [simple] = simple_handler, -} -local user_callbacks_defaults = { } -local function create_callback(name, ctype, default) - if not name or name == "" - or not ctype or ctype == "" - then - luatexbase_error("Unable to create callback:\n" .. - "valid callback name and type required") - end - if callbacktypes[name] then - luatexbase_error("Unable to create callback `" .. name .. - "':\ncallback type disallowed as name") - end - if default ~= false and type (default) ~= "function" then - luatexbase_error("Unable to create callback `" .. name .. - ":\ndefault is not a function") - end - user_callbacks_defaults[name] = default - callbacktypes[name] = types[ctype] -end -luatexbase.create_callback = create_callback -local function call_callback(name,...) - if not name or name == "" then - luatexbase_error("Unable to create callback:\n" .. - "valid callback name required") - end - if user_callbacks_defaults[name] == nil then - luatexbase_error("Unable to call callback `" .. name - .. "':\nunknown or empty") - end - local l = callbacklist[name] - local f - if not l then - f = user_callbacks_defaults[name] - if l == false then - return nil - end - else - f = handlers[callbacktypes[name]](name) - end - return f(...) -end -luatexbase.call_callback=call_callback -local function add_to_callback(name, func, description) - if not name or name == "" then - luatexbase_error("Unable to register callback:\n" .. - "valid callback name required") - end - if not callbacktypes[name] or - type(func) ~= "function" or - not description or - description == "" then - luatexbase_error( - "Unable to register callback.\n\n" - .. "Correct usage:\n" - .. "add_to_callback(<callback>, <function>, <description>)" - ) - end - local l = callbacklist[name] - if l == nil then - l = { } - callbacklist[name] = l - if user_callbacks_defaults[name] == nil then - callback_register(name, handlers[callbacktypes[name]](name)) - end - end - local f = { - func = func, - description = description, - } - local priority = #l + 1 - if callbacktypes[name] == exclusive then - if #l == 1 then - luatexbase_error( - "Cannot add second callback to exclusive function\n`" .. - name .. "'") - end - end - table.insert(l, priority, f) - luatexbase_log( - "Inserting `" .. description .. "' at position " - .. priority .. " in `" .. name .. "'." - ) -end -luatexbase.add_to_callback = add_to_callback -local function remove_from_callback(name, description) - if not name or name == "" then - luatexbase_error("Unable to remove function from callback:\n" .. - "valid callback name required") - end - if not callbacktypes[name] or - not description or - description == "" then - luatexbase_error( - "Unable to remove function from callback.\n\n" - .. "Correct usage:\n" - .. "remove_from_callback(<callback>, <description>)" - ) - end - local l = callbacklist[name] - if not l then - luatexbase_error( - "No callback list for `" .. name .. "'\n") - end - local index = false - for i,j in ipairs(l) do - if j.description == description then - index = i - break - end - end - if not index then - luatexbase_error( - "No callback `" .. description .. "' registered for `" .. - name .. "'\n") - end - local cb = l[index] - table.remove(l, index) - luatexbase_log( - "Removing `" .. description .. "' from `" .. name .. "'." - ) - if #l == 0 then - callbacklist[name] = nil - callback_register(name, nil) - end - return cb.func,cb.description -end -luatexbase.remove_from_callback = remove_from_callback -local function in_callback(name, description) - if not name - or name == "" - or not callbacklist[name] - or not callbacktypes[name] - or not description then - return false - end - for _, i in pairs(callbacklist[name]) do - if i.description == description then - return true - end - end - return false -end -luatexbase.in_callback = in_callback -local function disable_callback(name) - if(callbacklist[name] == nil) then - callback_register(name, false) - else - luatexbase_error("Callback list for " .. name .. " not empty") - end -end -luatexbase.disable_callback = disable_callback -local function callback_descriptions (name) - local d = {} - if not name - or name == "" - or not callbacklist[name] - or not callbacktypes[name] - then - return d - else - for k, i in pairs(callbacklist[name]) do - d[k]= i.description - end - end - return d -end -luatexbase.callback_descriptions =callback_descriptions -local function uninstall() - module_info( - "luatexbase", - "Uninstalling kernel luatexbase code" - ) - callback.register = callback_register - luatexbase = nil -end -luatexbase.uninstall = uninstall diff --git a/tex/compat/ltluatex/ltluatex.tex b/tex/compat/ltluatex/ltluatex.tex deleted file mode 100644 index fd748d582d3410a4b76178f7930e52bc58773902..0000000000000000000000000000000000000000 --- a/tex/compat/ltluatex/ltluatex.tex +++ /dev/null @@ -1,269 +0,0 @@ -%% -%% This is file `ltluatex.tex', -%% generated with the docstrip utility. -%% -%% The original source files were: -%% -%% ltluatex.dtx (with options: `tex,plain') -%% -%% This is a generated file. -%% -%% The source is maintained by the LaTeX Project team and bug -%% reports for it can be opened at http://latex-project.org/bugs.html -%% (but please observe conditions on bug reports sent to that address!) -%% -%% -%% Copyright 1993-2016 -%% The LaTeX3 Project and any individual authors listed elsewhere -%% in this file. -%% -%% This file was generated from file(s) of the LaTeX base system. -%% -------------------------------------------------------------- -%% -%% It may be distributed and/or modified under the -%% conditions of the LaTeX Project Public License, either version 1.3c -%% of this license or (at your option) any later version. -%% The latest version of this license is in -%% http://www.latex-project.org/lppl.txt -%% and version 1.3c or later is part of all distributions of LaTeX -%% version 2005/12/01 or later. -%% -%% This file has the LPPL maintenance status "maintained". -%% -%% This file may only be distributed together with a copy of the LaTeX -%% base system. You may however distribute the LaTeX base system without -%% such generated files. -%% -%% The list of all files belonging to the LaTeX base distribution is -%% given in the file `manifest.txt'. See also `legal.txt' for additional -%% information. -%% -%% The list of derived (unpacked) files belonging to the distribution -%% and covered by LPPL is defined by the unpacking scripts (with -%% extension .ins) which are part of the distribution. -\ifx\newluafunction\undefined\else\expandafter\endinput\fi -\ifx - \ProvidesFile\undefined\begingroup\def\ProvidesFile - #1#2[#3]{\endgroup\immediate\write-1{File: #1 #3}} -\fi -\ProvidesFile{ltluatex.tex} -[2016/03/13 v1.0n - LuaTeX support for plain TeX (core) -] -\edef\etatcatcode{\the\catcode`\@} -\catcode`\@=11 -\ifnum\luatexversion<60 % - \wlog{***************************************************} - \wlog{* LuaTeX version too old for ltluatex support *} - \wlog{***************************************************} - \expandafter\endinput -\fi -\directlua{tex.enableprimitives("",tex.extraprimitives("luatex"))} -\ifx\e@alloc\@undefined - \ifx\documentclass\@undefined - \ifx\loccount\@undefined - \input{etex.src}% - \fi - \catcode`\@=11 % - \outer\expandafter\def\csname newfam\endcsname - {\alloc@8\fam\chardef\et@xmaxfam} - \else - \RequirePackage{etex} - \expandafter\def\csname newfam\endcsname - {\alloc@8\fam\chardef\et@xmaxfam} - \expandafter\let\expandafter\new@mathgroup\csname newfam\endcsname - \fi -\edef \et@xmaxregs {\ifx\directlua\@undefined 32768\else 65536\fi} -\edef \et@xmaxfam {\ifx\Umathchar\@undefined\sixt@@n\else\@cclvi\fi} -\count 270=\et@xmaxregs % locally allocates \count registers -\count 271=\et@xmaxregs % ditto for \dimen registers -\count 272=\et@xmaxregs % ditto for \skip registers -\count 273=\et@xmaxregs % ditto for \muskip registers -\count 274=\et@xmaxregs % ditto for \box registers -\count 275=\et@xmaxregs % ditto for \toks registers -\count 276=\et@xmaxregs % ditto for \marks classes -\expandafter\let\csname newcount\expandafter\expandafter\endcsname - \csname globcount\endcsname -\expandafter\let\csname newdimen\expandafter\expandafter\endcsname - \csname globdimen\endcsname -\expandafter\let\csname newskip\expandafter\expandafter\endcsname - \csname globskip\endcsname -\expandafter\let\csname newbox\expandafter\expandafter\endcsname - \csname globbox\endcsname -\chardef\e@alloc@top=65535 -\let\e@alloc@chardef\chardef -\def\e@alloc#1#2#3#4#5#6{% - \global\advance#3\@ne - \e@ch@ck{#3}{#4}{#5}#1% - \allocationnumber#3\relax - \global#2#6\allocationnumber - \wlog{\string#6=\string#1\the\allocationnumber}}% -\gdef\e@ch@ck#1#2#3#4{% - \ifnum#1<#2\else - \ifnum#1=#2\relax - #1\@cclvi - \ifx\count#4\advance#1 10 \fi - \fi - \ifnum#1<#3\relax - \else - \errmessage{No room for a new \string#4}% - \fi - \fi}% -\long\def\@gobble#1{} -\long\def\@firstofone#1{#1} -\expandafter\csname newcount\endcsname\e@alloc@attribute@count -\expandafter\csname newcount\endcsname\e@alloc@ccodetable@count -\expandafter\csname newcount\endcsname\e@alloc@luafunction@count -\expandafter\csname newcount\endcsname\e@alloc@whatsit@count -\expandafter\csname newcount\endcsname\e@alloc@bytecode@count -\expandafter\csname newcount\endcsname\e@alloc@luachunk@count -\fi -\ifx\e@alloc@attribute@count\@undefined - \countdef\e@alloc@attribute@count=258 -\fi -\def\newattribute#1{% - \e@alloc\attribute\attributedef - \e@alloc@attribute@count\m@ne\e@alloc@top#1% -} -\e@alloc@attribute@count=\z@ -\def\setattribute#1#2{#1=\numexpr#2\relax} -\def\unsetattribute#1{#1=-"7FFFFFFF\relax} -\ifx\e@alloc@ccodetable@count\@undefined - \countdef\e@alloc@ccodetable@count=259 -\fi -\def\newcatcodetable#1{% - \e@alloc\catcodetable\chardef - \e@alloc@ccodetable@count\m@ne{"8000}#1% - \initcatcodetable\allocationnumber -} -\e@alloc@ccodetable@count=\z@ -\newcatcodetable\catcodetable@initex -\newcatcodetable\catcodetable@string -\begingroup - \def\setrangecatcode#1#2#3{% - \ifnum#1>#2 % - \expandafter\@gobble - \else - \expandafter\@firstofone - \fi - {% - \catcode#1=#3 % - \expandafter\setrangecatcode\expandafter - {\number\numexpr#1 + 1\relax}{#2}{#3} - }% - } - \@firstofone{% - \catcodetable\catcodetable@initex - \catcode0=12 % - \catcode13=12 % - \catcode37=12 % - \setrangecatcode{65}{90}{12}% - \setrangecatcode{97}{122}{12}% - \catcode92=12 % - \catcode127=12 % - \savecatcodetable\catcodetable@string - \endgroup - }% -\newcatcodetable\catcodetable@latex -\newcatcodetable\catcodetable@atletter -\begingroup - \def\parseunicodedataI#1;#2;#3;#4\relax{% - \parseunicodedataII#1;#3;#2 First>\relax - }% - \def\parseunicodedataII#1;#2;#3 First>#4\relax{% - \ifx\relax#4\relax - \expandafter\parseunicodedataIII - \else - \expandafter\parseunicodedataIV - \fi - {#1}#2\relax% - }% - \def\parseunicodedataIII#1#2#3\relax{% - \ifnum 0% - \if L#21\fi - \if M#21\fi - >0 % - \catcode"#1=11 % - \fi - }% - \def\parseunicodedataIV#1#2#3\relax{% - \read\unicoderead to \unicodedataline - \if L#2% - \count0="#1 % - \expandafter\parseunicodedataV\unicodedataline\relax - \fi - }% - \def\parseunicodedataV#1;#2\relax{% - \loop - \unless\ifnum\count0>"#1 % - \catcode\count0=11 % - \advance\count0 by 1 % - \repeat - }% - \def\storedpar{\par}% - \chardef\unicoderead=\numexpr\count16 + 1\relax - \openin\unicoderead=UnicodeData.txt % - \loop\unless\ifeof\unicoderead % - \read\unicoderead to \unicodedataline - \unless\ifx\unicodedataline\storedpar - \expandafter\parseunicodedataI\unicodedataline\relax - \fi - \repeat - \closein\unicoderead - \@firstofone{% - \catcode64=12 % - \savecatcodetable\catcodetable@latex - \catcode64=11 % - \savecatcodetable\catcodetable@atletter - } -\endgroup -\ifx\e@alloc@luafunction@count\@undefined - \countdef\e@alloc@luafunction@count=260 -\fi -\def\newluafunction{% - \e@alloc\luafunction\e@alloc@chardef - \e@alloc@luafunction@count\m@ne\e@alloc@top -} -\e@alloc@luafunction@count=\z@ -\ifx\e@alloc@whatsit@count\@undefined - \countdef\e@alloc@whatsit@count=261 -\fi -\def\newwhatsit#1{% - \e@alloc\whatsit\e@alloc@chardef - \e@alloc@whatsit@count\m@ne\e@alloc@top#1% -} -\e@alloc@whatsit@count=\z@ -\ifx\e@alloc@bytecode@count\@undefined - \countdef\e@alloc@bytecode@count=262 -\fi -\def\newluabytecode#1{% - \e@alloc\luabytecode\e@alloc@chardef - \e@alloc@bytecode@count\m@ne\e@alloc@top#1% -} -\e@alloc@bytecode@count=\z@ - -\ifx\e@alloc@luachunk@count\@undefined - \countdef\e@alloc@luachunk@count=263 -\fi -\def\newluachunkname#1{% - \e@alloc\luachunk\e@alloc@chardef - \e@alloc@luachunk@count\m@ne\e@alloc@top#1% - {\escapechar\m@ne - \directlua{lua.name[\the\allocationnumber]="\string#1"}}% -} -\e@alloc@luachunk@count=\z@ - \begingroup - \attributedef\attributezero=0 % - \chardef \charzero =0 % - \countdef \CountZero =0 % - \dimendef \dimenzero =0 % - \mathchardef \mathcharzero =0 % - \muskipdef \muskipzero =0 % - \skipdef \skipzero =0 % - \toksdef \tokszero =0 % - \directlua{require("ltluatex")} - \endgroup -\catcode`\@=\etatcatcode\relax -\endinput -%% -%% End of file `ltluatex.tex'. diff --git a/tex/compat/lualibs/lualibs-basic-merged.lua b/tex/compat/lualibs/lualibs-basic-merged.lua deleted file mode 100644 index ec56b75dc70327cb3da39cff0168bb1652168f27..0000000000000000000000000000000000000000 --- a/tex/compat/lualibs/lualibs-basic-merged.lua +++ /dev/null @@ -1,5072 +0,0 @@ --- merged file : lualibs-basic-merged.lua --- parent file : lualibs-basic.lua --- merge date : Wed Apr 6 23:53:30 2016 - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['l-lua']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -_MAJORVERSION,_MINORVERSION=string.match(_VERSION,"^[^%d]+(%d+)%.(%d+).*$") -_MAJORVERSION=tonumber(_MAJORVERSION) or 5 -_MINORVERSION=tonumber(_MINORVERSION) or 1 -_LUAVERSION=_MAJORVERSION+_MINORVERSION/10 -if _LUAVERSION<5.2 and jit then - _MINORVERSION=2 - _LUAVERSION=5.2 -end -if not lpeg then - lpeg=require("lpeg") -end -if loadstring then - local loadnormal=load - function load(first,...) - if type(first)=="string" then - return loadstring(first,...) - else - return loadnormal(first,...) - end - end -else - loadstring=load -end -if not ipairs then - local function iterate(a,i) - i=i+1 - local v=a[i] - if v~=nil then - return i,v - end - end - function ipairs(a) - return iterate,a,0 - end -end -if not pairs then - function pairs(t) - return next,t - end -end -if not table.unpack then - table.unpack=_G.unpack -elseif not unpack then - _G.unpack=table.unpack -end -if not package.loaders then - package.loaders=package.searchers -end -local print,select,tostring=print,select,tostring -local inspectors={} -function setinspector(kind,inspector) - inspectors[kind]=inspector -end -function inspect(...) - for s=1,select("#",...) do - local value=select(s,...) - if value==nil then - print("nil") - else - local done=false - local kind=type(value) - local inspector=inspectors[kind] - if inspector then - done=inspector(value) - if done then - break - end - end - for kind,inspector in next,inspectors do - done=inspector(value) - if done then - break - end - end - if not done then - print(tostring(value)) - end - end - end -end -local dummy=function() end -function optionalrequire(...) - local ok,result=xpcall(require,dummy,...) - if ok then - return result - end -end -if lua then - lua.mask=load([[τεχ = 1]]) and "utf" or "ascii" -end -local flush=io.flush -if flush then - local execute=os.execute if execute then function os.execute(...) flush() return execute(...) end end - local exec=os.exec if exec then function os.exec (...) flush() return exec (...) end end - local spawn=os.spawn if spawn then function os.spawn (...) flush() return spawn (...) end end - local popen=io.popen if popen then function io.popen (...) flush() return popen (...) end end -end - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['l-package']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local type=type -local gsub,format,find=string.gsub,string.format,string.find -local P,S,Cs,lpegmatch=lpeg.P,lpeg.S,lpeg.Cs,lpeg.match -local package=package -local searchers=package.searchers or package.loaders -local filejoin=file and file.join or function(path,name) return path.."/"..name end -local isreadable=file and file.is_readable or function(name) local f=io.open(name) if f then f:close() return true end end -local addsuffix=file and file.addsuffix or function(name,suffix) return name.."."..suffix end -local function cleanpath(path) - return path -end -local pattern=Cs((((1-S("\\/"))^0*(S("\\/")^1/"/"))^0*(P(".")^1/"/"+P(1))^1)*-1) -local function lualibfile(name) - return lpegmatch(pattern,name) or name -end -local offset=luarocks and 1 or 0 -local helpers=package.helpers or { - cleanpath=cleanpath, - lualibfile=lualibfile, - trace=false, - report=function(...) print(format(...)) end, - builtin={ - ["preload table"]=searchers[1+offset], - ["path specification"]=searchers[2+offset], - ["cpath specification"]=searchers[3+offset], - ["all in one fallback"]=searchers[4+offset], - }, - methods={}, - sequence={ - "already loaded", - "preload table", - "qualified path", - "lua extra list", - "lib extra list", - "path specification", - "cpath specification", - "all in one fallback", - "not loaded", - } -} -package.helpers=helpers -local methods=helpers.methods -local builtin=helpers.builtin -local extraluapaths={} -local extralibpaths={} -local luapaths=nil -local libpaths=nil -local oldluapath=nil -local oldlibpath=nil -local nofextralua=-1 -local nofextralib=-1 -local nofpathlua=-1 -local nofpathlib=-1 -local function listpaths(what,paths) - local nofpaths=#paths - if nofpaths>0 then - for i=1,nofpaths do - helpers.report("using %s path %i: %s",what,i,paths[i]) - end - else - helpers.report("no %s paths defined",what) - end - return nofpaths -end -local function getextraluapaths() - if helpers.trace and #extraluapaths~=nofextralua then - nofextralua=listpaths("extra lua",extraluapaths) - end - return extraluapaths -end -local function getextralibpaths() - if helpers.trace and #extralibpaths~=nofextralib then - nofextralib=listpaths("extra lib",extralibpaths) - end - return extralibpaths -end -local function getluapaths() - local luapath=package.path or "" - if oldluapath~=luapath then - luapaths=file.splitpath(luapath,";") - oldluapath=luapath - nofpathlua=-1 - end - if helpers.trace and #luapaths~=nofpathlua then - nofpathlua=listpaths("builtin lua",luapaths) - end - return luapaths -end -local function getlibpaths() - local libpath=package.cpath or "" - if oldlibpath~=libpath then - libpaths=file.splitpath(libpath,";") - oldlibpath=libpath - nofpathlib=-1 - end - if helpers.trace and #libpaths~=nofpathlib then - nofpathlib=listpaths("builtin lib",libpaths) - end - return libpaths -end -package.luapaths=getluapaths -package.libpaths=getlibpaths -package.extraluapaths=getextraluapaths -package.extralibpaths=getextralibpaths -local hashes={ - lua={}, - lib={}, -} -local function registerpath(tag,what,target,...) - local pathlist={... } - local cleanpath=helpers.cleanpath - local trace=helpers.trace - local report=helpers.report - local hash=hashes[what] - local function add(path) - local path=cleanpath(path) - if not hash[path] then - target[#target+1]=path - hash[path]=true - if trace then - report("registered %s path %s: %s",tag,#target,path) - end - else - if trace then - report("duplicate %s path: %s",tag,path) - end - end - end - for p=1,#pathlist do - local path=pathlist[p] - if type(path)=="table" then - for i=1,#path do - add(path[i]) - end - else - add(path) - end - end - return paths -end -helpers.registerpath=registerpath -function package.extraluapath(...) - registerpath("extra lua","lua",extraluapaths,...) -end -function package.extralibpath(...) - registerpath("extra lib","lib",extralibpaths,...) -end -local function loadedaslib(resolved,rawname) - local base=gsub(rawname,"%.","_") - local init="luaopen_"..gsub(base,"%.","_") - if helpers.trace then - helpers.report("calling loadlib with '%s' with init '%s'",resolved,init) - end - return package.loadlib(resolved,init) -end -helpers.loadedaslib=loadedaslib -local function loadedbypath(name,rawname,paths,islib,what) - local trace=helpers.trace - for p=1,#paths do - local path=paths[p] - local resolved=filejoin(path,name) - if trace then - helpers.report("%s path, identifying '%s' on '%s'",what,name,path) - end - if isreadable(resolved) then - if trace then - helpers.report("%s path, '%s' found on '%s'",what,name,resolved) - end - if islib then - return loadedaslib(resolved,rawname) - else - return loadfile(resolved) - end - end - end -end -helpers.loadedbypath=loadedbypath -local function loadedbyname(name,rawname) - if find(name,"^/") or find(name,"^[a-zA-Z]:/") then - local trace=helpers.trace - if trace then - helpers.report("qualified name, identifying '%s'",what,name) - end - if isreadable(name) then - if trace then - helpers.report("qualified name, '%s' found",what,name) - end - return loadfile(name) - end - end -end -helpers.loadedbyname=loadedbyname -methods["already loaded"]=function(name) - return package.loaded[name] -end -methods["preload table"]=function(name) - return builtin["preload table"](name) -end -methods["qualified path"]=function(name) - return loadedbyname(addsuffix(lualibfile(name),"lua"),name) -end -methods["lua extra list"]=function(name) - return loadedbypath(addsuffix(lualibfile(name),"lua"),name,getextraluapaths(),false,"lua") -end -methods["lib extra list"]=function(name) - return loadedbypath(addsuffix(lualibfile(name),os.libsuffix),name,getextralibpaths(),true,"lib") -end -methods["path specification"]=function(name) - getluapaths() - return builtin["path specification"](name) -end -methods["cpath specification"]=function(name) - getlibpaths() - return builtin["cpath specification"](name) -end -methods["all in one fallback"]=function(name) - return builtin["all in one fallback"](name) -end -methods["not loaded"]=function(name) - if helpers.trace then - helpers.report("unable to locate '%s'",name or "?") - end - return nil -end -local level=0 -local used={} -helpers.traceused=false -function helpers.loaded(name) - local sequence=helpers.sequence - level=level+1 - for i=1,#sequence do - local method=sequence[i] - if helpers.trace then - helpers.report("%s, level '%s', method '%s', name '%s'","locating",level,method,name) - end - local result,rest=methods[method](name) - if type(result)=="function" then - if helpers.trace then - helpers.report("%s, level '%s', method '%s', name '%s'","found",level,method,name) - end - if helpers.traceused then - used[#used+1]={ level=level,name=name } - end - level=level-1 - return result,rest - end - end - level=level-1 - return nil -end -function helpers.showused() - local n=#used - if n>0 then - helpers.report("%s libraries loaded:",n) - helpers.report() - for i=1,n do - local u=used[i] - helpers.report("%i %a",u.level,u.name) - end - helpers.report() - end -end -function helpers.unload(name) - if helpers.trace then - if package.loaded[name] then - helpers.report("unloading, name '%s', %s",name,"done") - else - helpers.report("unloading, name '%s', %s",name,"not loaded") - end - end - package.loaded[name]=nil -end -table.insert(searchers,1,helpers.loaded) - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['l-lpeg']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -lpeg=require("lpeg") -if not lpeg.print then function lpeg.print(...) print(lpeg.pcode(...)) end end -local type,next,tostring=type,next,tostring -local byte,char,gmatch,format=string.byte,string.char,string.gmatch,string.format -local floor=math.floor -local P,R,S,V,Ct,C,Cs,Cc,Cp,Cmt=lpeg.P,lpeg.R,lpeg.S,lpeg.V,lpeg.Ct,lpeg.C,lpeg.Cs,lpeg.Cc,lpeg.Cp,lpeg.Cmt -local lpegtype,lpegmatch,lpegprint=lpeg.type,lpeg.match,lpeg.print -if setinspector then - setinspector("lpeg",function(v) if lpegtype(v) then lpegprint(v) return true end end) -end -lpeg.patterns=lpeg.patterns or {} -local patterns=lpeg.patterns -local anything=P(1) -local endofstring=P(-1) -local alwaysmatched=P(true) -patterns.anything=anything -patterns.endofstring=endofstring -patterns.beginofstring=alwaysmatched -patterns.alwaysmatched=alwaysmatched -local sign=S('+-') -local zero=P('0') -local digit=R('09') -local octdigit=R("07") -local lowercase=R("az") -local uppercase=R("AZ") -local underscore=P("_") -local hexdigit=digit+lowercase+uppercase -local cr,lf,crlf=P("\r"),P("\n"),P("\r\n") -local newline=P("\r")*(P("\n")+P(true))+P("\n") -local escaped=P("\\")*anything -local squote=P("'") -local dquote=P('"') -local space=P(" ") -local period=P(".") -local comma=P(",") -local utfbom_32_be=P('\000\000\254\255') -local utfbom_32_le=P('\255\254\000\000') -local utfbom_16_be=P('\254\255') -local utfbom_16_le=P('\255\254') -local utfbom_8=P('\239\187\191') -local utfbom=utfbom_32_be+utfbom_32_le+utfbom_16_be+utfbom_16_le+utfbom_8 -local utftype=utfbom_32_be*Cc("utf-32-be")+utfbom_32_le*Cc("utf-32-le")+utfbom_16_be*Cc("utf-16-be")+utfbom_16_le*Cc("utf-16-le")+utfbom_8*Cc("utf-8")+alwaysmatched*Cc("utf-8") -local utfstricttype=utfbom_32_be*Cc("utf-32-be")+utfbom_32_le*Cc("utf-32-le")+utfbom_16_be*Cc("utf-16-be")+utfbom_16_le*Cc("utf-16-le")+utfbom_8*Cc("utf-8") -local utfoffset=utfbom_32_be*Cc(4)+utfbom_32_le*Cc(4)+utfbom_16_be*Cc(2)+utfbom_16_le*Cc(2)+utfbom_8*Cc(3)+Cc(0) -local utf8next=R("\128\191") -patterns.utfbom_32_be=utfbom_32_be -patterns.utfbom_32_le=utfbom_32_le -patterns.utfbom_16_be=utfbom_16_be -patterns.utfbom_16_le=utfbom_16_le -patterns.utfbom_8=utfbom_8 -patterns.utf_16_be_nl=P("\000\r\000\n")+P("\000\r")+P("\000\n") -patterns.utf_16_le_nl=P("\r\000\n\000")+P("\r\000")+P("\n\000") -patterns.utf_32_be_nl=P("\000\000\000\r\000\000\000\n")+P("\000\000\000\r")+P("\000\000\000\n") -patterns.utf_32_le_nl=P("\r\000\000\000\n\000\000\000")+P("\r\000\000\000")+P("\n\000\000\000") -patterns.utf8one=R("\000\127") -patterns.utf8two=R("\194\223")*utf8next -patterns.utf8three=R("\224\239")*utf8next*utf8next -patterns.utf8four=R("\240\244")*utf8next*utf8next*utf8next -patterns.utfbom=utfbom -patterns.utftype=utftype -patterns.utfstricttype=utfstricttype -patterns.utfoffset=utfoffset -local utf8char=patterns.utf8one+patterns.utf8two+patterns.utf8three+patterns.utf8four -local validutf8char=utf8char^0*endofstring*Cc(true)+Cc(false) -local utf8character=P(1)*R("\128\191")^0 -patterns.utf8=utf8char -patterns.utf8char=utf8char -patterns.utf8character=utf8character -patterns.validutf8=validutf8char -patterns.validutf8char=validutf8char -local eol=S("\n\r") -local spacer=S(" \t\f\v") -local whitespace=eol+spacer -local nonspacer=1-spacer -local nonwhitespace=1-whitespace -patterns.eol=eol -patterns.spacer=spacer -patterns.whitespace=whitespace -patterns.nonspacer=nonspacer -patterns.nonwhitespace=nonwhitespace -local stripper=spacer^0*C((spacer^0*nonspacer^1)^0) -local fullstripper=whitespace^0*C((whitespace^0*nonwhitespace^1)^0) -local collapser=Cs(spacer^0/""*nonspacer^0*((spacer^0/" "*nonspacer^1)^0)) -local b_collapser=Cs(whitespace^0/""*(nonwhitespace^1+whitespace^1/" ")^0) -local e_collapser=Cs((whitespace^1*P(-1)/""+nonwhitespace^1+whitespace^1/" ")^0) -local m_collapser=Cs((nonwhitespace^1+whitespace^1/" ")^0) -local b_stripper=Cs(spacer^0/""*(nonspacer^1+spacer^1/" ")^0) -local e_stripper=Cs((spacer^1*P(-1)/""+nonspacer^1+spacer^1/" ")^0) -local m_stripper=Cs((nonspacer^1+spacer^1/" ")^0) -patterns.stripper=stripper -patterns.fullstripper=fullstripper -patterns.collapser=collapser -patterns.b_collapser=b_collapser -patterns.m_collapser=m_collapser -patterns.e_collapser=e_collapser -patterns.b_stripper=b_stripper -patterns.m_stripper=m_stripper -patterns.e_stripper=e_stripper -patterns.lowercase=lowercase -patterns.uppercase=uppercase -patterns.letter=patterns.lowercase+patterns.uppercase -patterns.space=space -patterns.tab=P("\t") -patterns.spaceortab=patterns.space+patterns.tab -patterns.newline=newline -patterns.emptyline=newline^1 -patterns.equal=P("=") -patterns.comma=comma -patterns.commaspacer=comma*spacer^0 -patterns.period=period -patterns.colon=P(":") -patterns.semicolon=P(";") -patterns.underscore=underscore -patterns.escaped=escaped -patterns.squote=squote -patterns.dquote=dquote -patterns.nosquote=(escaped+(1-squote))^0 -patterns.nodquote=(escaped+(1-dquote))^0 -patterns.unsingle=(squote/"")*patterns.nosquote*(squote/"") -patterns.undouble=(dquote/"")*patterns.nodquote*(dquote/"") -patterns.unquoted=patterns.undouble+patterns.unsingle -patterns.unspacer=((patterns.spacer^1)/"")^0 -patterns.singlequoted=squote*patterns.nosquote*squote -patterns.doublequoted=dquote*patterns.nodquote*dquote -patterns.quoted=patterns.doublequoted+patterns.singlequoted -patterns.digit=digit -patterns.octdigit=octdigit -patterns.hexdigit=hexdigit -patterns.sign=sign -patterns.cardinal=digit^1 -patterns.integer=sign^-1*digit^1 -patterns.unsigned=digit^0*period*digit^1 -patterns.float=sign^-1*patterns.unsigned -patterns.cunsigned=digit^0*comma*digit^1 -patterns.cpunsigned=digit^0*(period+comma)*digit^1 -patterns.cfloat=sign^-1*patterns.cunsigned -patterns.cpfloat=sign^-1*patterns.cpunsigned -patterns.number=patterns.float+patterns.integer -patterns.cnumber=patterns.cfloat+patterns.integer -patterns.cpnumber=patterns.cpfloat+patterns.integer -patterns.oct=zero*octdigit^1 -patterns.octal=patterns.oct -patterns.HEX=zero*P("X")*(digit+uppercase)^1 -patterns.hex=zero*P("x")*(digit+lowercase)^1 -patterns.hexadecimal=zero*S("xX")*hexdigit^1 -patterns.hexafloat=sign^-1*zero*S("xX")*(hexdigit^0*period*hexdigit^1+hexdigit^1*period*hexdigit^0+hexdigit^1)*(S("pP")*sign^-1*hexdigit^1)^-1 -patterns.decafloat=sign^-1*(digit^0*period*digit^1+digit^1*period*digit^0+digit^1)*S("eE")*sign^-1*digit^1 -patterns.propername=(uppercase+lowercase+underscore)*(uppercase+lowercase+underscore+digit)^0*endofstring -patterns.somecontent=(anything-newline-space)^1 -patterns.beginline=#(1-newline) -patterns.longtostring=Cs(whitespace^0/""*((patterns.quoted+nonwhitespace^1+whitespace^1/""*(P(-1)+Cc(" ")))^0)) -local function anywhere(pattern) - return P { P(pattern)+1*V(1) } -end -lpeg.anywhere=anywhere -function lpeg.instringchecker(p) - p=anywhere(p) - return function(str) - return lpegmatch(p,str) and true or false - end -end -function lpeg.splitter(pattern,action) - return (((1-P(pattern))^1)/action+1)^0 -end -function lpeg.tsplitter(pattern,action) - return Ct((((1-P(pattern))^1)/action+1)^0) -end -local splitters_s,splitters_m,splitters_t={},{},{} -local function splitat(separator,single) - local splitter=(single and splitters_s[separator]) or splitters_m[separator] - if not splitter then - separator=P(separator) - local other=C((1-separator)^0) - if single then - local any=anything - splitter=other*(separator*C(any^0)+"") - splitters_s[separator]=splitter - else - splitter=other*(separator*other)^0 - splitters_m[separator]=splitter - end - end - return splitter -end -local function tsplitat(separator) - local splitter=splitters_t[separator] - if not splitter then - splitter=Ct(splitat(separator)) - splitters_t[separator]=splitter - end - return splitter -end -lpeg.splitat=splitat -lpeg.tsplitat=tsplitat -function string.splitup(str,separator) - if not separator then - separator="," - end - return lpegmatch(splitters_m[separator] or splitat(separator),str) -end -local cache={} -function lpeg.split(separator,str) - local c=cache[separator] - if not c then - c=tsplitat(separator) - cache[separator]=c - end - return lpegmatch(c,str) -end -function string.split(str,separator) - if separator then - local c=cache[separator] - if not c then - c=tsplitat(separator) - cache[separator]=c - end - return lpegmatch(c,str) - else - return { str } - end -end -local spacing=patterns.spacer^0*newline -local empty=spacing*Cc("") -local nonempty=Cs((1-spacing)^1)*spacing^-1 -local content=(empty+nonempty)^1 -patterns.textline=content -local linesplitter=tsplitat(newline) -patterns.linesplitter=linesplitter -function string.splitlines(str) - return lpegmatch(linesplitter,str) -end -local cache={} -function lpeg.checkedsplit(separator,str) - local c=cache[separator] - if not c then - separator=P(separator) - local other=C((1-separator)^1) - c=Ct(separator^0*other*(separator^1*other)^0) - cache[separator]=c - end - return lpegmatch(c,str) -end -function string.checkedsplit(str,separator) - local c=cache[separator] - if not c then - separator=P(separator) - local other=C((1-separator)^1) - c=Ct(separator^0*other*(separator^1*other)^0) - cache[separator]=c - end - return lpegmatch(c,str) -end -local function f2(s) local c1,c2=byte(s,1,2) return c1*64+c2-12416 end -local function f3(s) local c1,c2,c3=byte(s,1,3) return (c1*64+c2)*64+c3-925824 end -local function f4(s) local c1,c2,c3,c4=byte(s,1,4) return ((c1*64+c2)*64+c3)*64+c4-63447168 end -local utf8byte=patterns.utf8one/byte+patterns.utf8two/f2+patterns.utf8three/f3+patterns.utf8four/f4 -patterns.utf8byte=utf8byte -local cache={} -function lpeg.stripper(str) - if type(str)=="string" then - local s=cache[str] - if not s then - s=Cs(((S(str)^1)/""+1)^0) - cache[str]=s - end - return s - else - return Cs(((str^1)/""+1)^0) - end -end -local cache={} -function lpeg.keeper(str) - if type(str)=="string" then - local s=cache[str] - if not s then - s=Cs((((1-S(str))^1)/""+1)^0) - cache[str]=s - end - return s - else - return Cs((((1-str)^1)/""+1)^0) - end -end -function lpeg.frontstripper(str) - return (P(str)+P(true))*Cs(anything^0) -end -function lpeg.endstripper(str) - return Cs((1-P(str)*endofstring)^0) -end -function lpeg.replacer(one,two,makefunction,isutf) - local pattern - local u=isutf and utf8char or 1 - if type(one)=="table" then - local no=#one - local p=P(false) - if no==0 then - for k,v in next,one do - p=p+P(k)/v - end - pattern=Cs((p+u)^0) - elseif no==1 then - local o=one[1] - one,two=P(o[1]),o[2] - pattern=Cs((one/two+u)^0) - else - for i=1,no do - local o=one[i] - p=p+P(o[1])/o[2] - end - pattern=Cs((p+u)^0) - end - else - pattern=Cs((P(one)/(two or "")+u)^0) - end - if makefunction then - return function(str) - return lpegmatch(pattern,str) - end - else - return pattern - end -end -function lpeg.finder(lst,makefunction,isutf) - local pattern - if type(lst)=="table" then - pattern=P(false) - if #lst==0 then - for k,v in next,lst do - pattern=pattern+P(k) - end - else - for i=1,#lst do - pattern=pattern+P(lst[i]) - end - end - else - pattern=P(lst) - end - if isutf then - pattern=((utf8char or 1)-pattern)^0*pattern - else - pattern=(1-pattern)^0*pattern - end - if makefunction then - return function(str) - return lpegmatch(pattern,str) - end - else - return pattern - end -end -local splitters_f,splitters_s={},{} -function lpeg.firstofsplit(separator) - local splitter=splitters_f[separator] - if not splitter then - local pattern=P(separator) - splitter=C((1-pattern)^0) - splitters_f[separator]=splitter - end - return splitter -end -function lpeg.secondofsplit(separator) - local splitter=splitters_s[separator] - if not splitter then - local pattern=P(separator) - splitter=(1-pattern)^0*pattern*C(anything^0) - splitters_s[separator]=splitter - end - return splitter -end -local splitters_s,splitters_p={},{} -function lpeg.beforesuffix(separator) - local splitter=splitters_s[separator] - if not splitter then - local pattern=P(separator) - splitter=C((1-pattern)^0)*pattern*endofstring - splitters_s[separator]=splitter - end - return splitter -end -function lpeg.afterprefix(separator) - local splitter=splitters_p[separator] - if not splitter then - local pattern=P(separator) - splitter=pattern*C(anything^0) - splitters_p[separator]=splitter - end - return splitter -end -function lpeg.balancer(left,right) - left,right=P(left),P(right) - return P { left*((1-left-right)+V(1))^0*right } -end -local nany=utf8char/"" -function lpeg.counter(pattern) - pattern=Cs((P(pattern)/" "+nany)^0) - return function(str) - return #lpegmatch(pattern,str) - end -end -utf=utf or (unicode and unicode.utf8) or {} -local utfcharacters=utf and utf.characters or string.utfcharacters -local utfgmatch=utf and utf.gmatch -local utfchar=utf and utf.char -lpeg.UP=lpeg.P -if utfcharacters then - function lpeg.US(str) - local p=P(false) - for uc in utfcharacters(str) do - p=p+P(uc) - end - return p - end -elseif utfgmatch then - function lpeg.US(str) - local p=P(false) - for uc in utfgmatch(str,".") do - p=p+P(uc) - end - return p - end -else - function lpeg.US(str) - local p=P(false) - local f=function(uc) - p=p+P(uc) - end - lpegmatch((utf8char/f)^0,str) - return p - end -end -local range=utf8byte*utf8byte+Cc(false) -function lpeg.UR(str,more) - local first,last - if type(str)=="number" then - first=str - last=more or first - else - first,last=lpegmatch(range,str) - if not last then - return P(str) - end - end - if first==last then - return P(str) - elseif utfchar and (last-first<8) then - local p=P(false) - for i=first,last do - p=p+P(utfchar(i)) - end - return p - else - local f=function(b) - return b>=first and b<=last - end - return utf8byte/f - end -end -function lpeg.is_lpeg(p) - return p and lpegtype(p)=="pattern" -end -function lpeg.oneof(list,...) - if type(list)~="table" then - list={ list,... } - end - local p=P(list[1]) - for l=2,#list do - p=p+P(list[l]) - end - return p -end -local sort=table.sort -local function copyindexed(old) - local new={} - for i=1,#old do - new[i]=old - end - return new -end -local function sortedkeys(tab) - local keys,s={},0 - for key,_ in next,tab do - s=s+1 - keys[s]=key - end - sort(keys) - return keys -end -function lpeg.append(list,pp,delayed,checked) - local p=pp - if #list>0 then - local keys=copyindexed(list) - sort(keys) - for i=#keys,1,-1 do - local k=keys[i] - if p then - p=P(k)+p - else - p=P(k) - end - end - elseif delayed then - local keys=sortedkeys(list) - if p then - for i=1,#keys,1 do - local k=keys[i] - local v=list[k] - p=P(k)/list+p - end - else - for i=1,#keys do - local k=keys[i] - local v=list[k] - if p then - p=P(k)+p - else - p=P(k) - end - end - if p then - p=p/list - end - end - elseif checked then - local keys=sortedkeys(list) - for i=1,#keys do - local k=keys[i] - local v=list[k] - if p then - if k==v then - p=P(k)+p - else - p=P(k)/v+p - end - else - if k==v then - p=P(k) - else - p=P(k)/v - end - end - end - else - local keys=sortedkeys(list) - for i=1,#keys do - local k=keys[i] - local v=list[k] - if p then - p=P(k)/v+p - else - p=P(k)/v - end - end - end - return p -end -local p_false=P(false) -local p_true=P(true) -local function make(t) - local function making(t) - local p=p_false - local keys=sortedkeys(t) - for i=1,#keys do - local k=keys[i] - if k~="" then - local v=t[k] - if v==true then - p=p+P(k)*p_true - elseif v==false then - else - p=p+P(k)*making(v) - end - end - end - if t[""] then - p=p+p_true - end - return p - end - local p=p_false - local keys=sortedkeys(t) - for i=1,#keys do - local k=keys[i] - if k~="" then - local v=t[k] - if v==true then - p=p+P(k)*p_true - elseif v==false then - else - p=p+P(k)*making(v) - end - end - end - return p -end -local function collapse(t,x) - if type(t)~="table" then - return t,x - else - local n=next(t) - if n==nil then - return t,x - elseif next(t,n)==nil then - local k=n - local v=t[k] - if type(v)=="table" then - return collapse(v,x..k) - else - return v,x..k - end - else - local tt={} - for k,v in next,t do - local vv,kk=collapse(v,k) - tt[kk]=vv - end - return tt,x - end - end -end -function lpeg.utfchartabletopattern(list) - local tree={} - local n=#list - if n==0 then - for s in next,list do - local t=tree - local p,pk - for c in gmatch(s,".") do - if t==true then - t={ [c]=true,[""]=true } - p[pk]=t - p=t - t=false - elseif t==false then - t={ [c]=false } - p[pk]=t - p=t - t=false - else - local tc=t[c] - if not tc then - tc=false - t[c]=false - end - p=t - t=tc - end - pk=c - end - if t==false then - p[pk]=true - elseif t==true then - else - t[""]=true - end - end - else - for i=1,n do - local s=list[i] - local t=tree - local p,pk - for c in gmatch(s,".") do - if t==true then - t={ [c]=true,[""]=true } - p[pk]=t - p=t - t=false - elseif t==false then - t={ [c]=false } - p[pk]=t - p=t - t=false - else - local tc=t[c] - if not tc then - tc=false - t[c]=false - end - p=t - t=tc - end - pk=c - end - if t==false then - p[pk]=true - elseif t==true then - else - t[""]=true - end - end - end - return make(tree) -end -patterns.containseol=lpeg.finder(eol) -local function nextstep(n,step,result) - local m=n%step - local d=floor(n/step) - if d>0 then - local v=V(tostring(step)) - local s=result.start - for i=1,d do - if s then - s=v*s - else - s=v - end - end - result.start=s - end - if step>1 and result.start then - local v=V(tostring(step/2)) - result[tostring(step)]=v*v - end - if step>0 then - return nextstep(m,step/2,result) - else - return result - end -end -function lpeg.times(pattern,n) - return P(nextstep(n,2^16,{ "start",["1"]=pattern })) -end -local trailingzeros=zero^0*-digit -local case_1=period*trailingzeros/"" -local case_2=period*(digit-trailingzeros)^1*(trailingzeros/"") -local number=digit^1*(case_1+case_2) -local stripper=Cs((number+1)^0) -lpeg.patterns.stripzeros=stripper -local byte_to_HEX={} -local byte_to_hex={} -local byte_to_dec={} -local hex_to_byte={} -for i=0,255 do - local H=format("%02X",i) - local h=format("%02x",i) - local d=format("%03i",i) - local c=char(i) - byte_to_HEX[c]=H - byte_to_hex[c]=h - byte_to_dec[c]=d - hex_to_byte[h]=c - hex_to_byte[H]=c -end -local hextobyte=P(2)/hex_to_byte -local bytetoHEX=P(1)/byte_to_HEX -local bytetohex=P(1)/byte_to_hex -local bytetodec=P(1)/byte_to_dec -local hextobytes=Cs(hextobyte^0) -local bytestoHEX=Cs(bytetoHEX^0) -local bytestohex=Cs(bytetohex^0) -local bytestodec=Cs(bytetodec^0) -patterns.hextobyte=hextobyte -patterns.bytetoHEX=bytetoHEX -patterns.bytetohex=bytetohex -patterns.bytetodec=bytetodec -patterns.hextobytes=hextobytes -patterns.bytestoHEX=bytestoHEX -patterns.bytestohex=bytestohex -patterns.bytestodec=bytestodec -function string.toHEX(s) - if not s or s=="" then - return s - else - return lpegmatch(bytestoHEX,s) - end -end -function string.tohex(s) - if not s or s=="" then - return s - else - return lpegmatch(bytestohex,s) - end -end -function string.todec(s) - if not s or s=="" then - return s - else - return lpegmatch(bytestodec,s) - end -end -function string.tobytes(s) - if not s or s=="" then - return s - else - return lpegmatch(hextobytes,s) - end -end - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['l-functions']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -functions=functions or {} -function functions.dummy() end - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['l-string']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local string=string -local sub,gmatch,format,char,byte,rep,lower=string.sub,string.gmatch,string.format,string.char,string.byte,string.rep,string.lower -local lpegmatch,patterns=lpeg.match,lpeg.patterns -local P,S,C,Ct,Cc,Cs=lpeg.P,lpeg.S,lpeg.C,lpeg.Ct,lpeg.Cc,lpeg.Cs -local unquoted=patterns.squote*C(patterns.nosquote)*patterns.squote+patterns.dquote*C(patterns.nodquote)*patterns.dquote -function string.unquoted(str) - return lpegmatch(unquoted,str) or str -end -function string.quoted(str) - return format("%q",str) -end -function string.count(str,pattern) - local n=0 - for _ in gmatch(str,pattern) do - n=n+1 - end - return n -end -function string.limit(str,n,sentinel) - if #str>n then - sentinel=sentinel or "..." - return sub(str,1,(n-#sentinel))..sentinel - else - return str - end -end -local stripper=patterns.stripper -local fullstripper=patterns.fullstripper -local collapser=patterns.collapser -local longtostring=patterns.longtostring -function string.strip(str) - return lpegmatch(stripper,str) or "" -end -function string.fullstrip(str) - return lpegmatch(fullstripper,str) or "" -end -function string.collapsespaces(str) - return lpegmatch(collapser,str) or "" -end -function string.longtostring(str) - return lpegmatch(longtostring,str) or "" -end -local pattern=P(" ")^0*P(-1) -function string.is_empty(str) - if str=="" then - return true - else - return lpegmatch(pattern,str) and true or false - end -end -local anything=patterns.anything -local allescapes=Cc("%")*S(".-+%?()[]*") -local someescapes=Cc("%")*S(".-+%()[]") -local matchescapes=Cc(".")*S("*?") -local pattern_a=Cs ((allescapes+anything )^0 ) -local pattern_b=Cs ((someescapes+matchescapes+anything )^0 ) -local pattern_c=Cs (Cc("^")*(someescapes+matchescapes+anything )^0*Cc("$") ) -function string.escapedpattern(str,simple) - return lpegmatch(simple and pattern_b or pattern_a,str) -end -function string.topattern(str,lowercase,strict) - if str=="" or type(str)~="string" then - return ".*" - elseif strict then - str=lpegmatch(pattern_c,str) - else - str=lpegmatch(pattern_b,str) - end - if lowercase then - return lower(str) - else - return str - end -end -function string.valid(str,default) - return (type(str)=="string" and str~="" and str) or default or nil -end -string.itself=function(s) return s end -local pattern_c=Ct(C(1)^0) -local pattern_b=Ct((C(1)/byte)^0) -function string.totable(str,bytes) - return lpegmatch(bytes and pattern_b or pattern_c,str) -end -local replacer=lpeg.replacer("@","%%") -function string.tformat(fmt,...) - return format(lpegmatch(replacer,fmt),...) -end -string.quote=string.quoted -string.unquote=string.unquoted - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['l-table']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local type,next,tostring,tonumber,ipairs,select=type,next,tostring,tonumber,ipairs,select -local table,string=table,string -local concat,sort,insert,remove=table.concat,table.sort,table.insert,table.remove -local format,lower,dump=string.format,string.lower,string.dump -local getmetatable,setmetatable=getmetatable,setmetatable -local getinfo=debug.getinfo -local lpegmatch,patterns=lpeg.match,lpeg.patterns -local floor=math.floor -local stripper=patterns.stripper -function table.strip(tab) - local lst,l={},0 - for i=1,#tab do - local s=lpegmatch(stripper,tab[i]) or "" - if s=="" then - else - l=l+1 - lst[l]=s - end - end - return lst -end -function table.keys(t) - if t then - local keys,k={},0 - for key in next,t do - k=k+1 - keys[k]=key - end - return keys - else - return {} - end -end -local function compare(a,b) - local ta=type(a) - if ta=="number" then - local tb=type(b) - if ta==tb then - return a<b - elseif tb=="string" then - return tostring(a)<b - end - elseif ta=="string" then - local tb=type(b) - if ta==tb then - return a<b - else - return a<tostring(b) - end - end - return tostring(a)<tostring(b) -end -local function sortedkeys(tab) - if tab then - local srt,category,s={},0,0 - for key in next,tab do - s=s+1 - srt[s]=key - if category==3 then - elseif category==1 then - if type(key)~="string" then - category=3 - end - elseif category==2 then - if type(key)~="number" then - category=3 - end - else - local tkey=type(key) - if tkey=="string" then - category=1 - elseif tkey=="number" then - category=2 - else - category=3 - end - end - end - if s<2 then - elseif category==3 then - sort(srt,compare) - else - sort(srt) - end - return srt - else - return {} - end -end -local function sortedhashonly(tab) - if tab then - local srt,s={},0 - for key in next,tab do - if type(key)=="string" then - s=s+1 - srt[s]=key - end - end - if s>1 then - sort(srt) - end - return srt - else - return {} - end -end -local function sortedindexonly(tab) - if tab then - local srt,s={},0 - for key in next,tab do - if type(key)=="number" then - s=s+1 - srt[s]=key - end - end - if s>1 then - sort(srt) - end - return srt - else - return {} - end -end -local function sortedhashkeys(tab,cmp) - if tab then - local srt,s={},0 - for key in next,tab do - if key then - s=s+1 - srt[s]=key - end - end - if s>1 then - sort(srt,cmp) - end - return srt - else - return {} - end -end -function table.allkeys(t) - local keys={} - for k,v in next,t do - for k in next,v do - keys[k]=true - end - end - return sortedkeys(keys) -end -table.sortedkeys=sortedkeys -table.sortedhashonly=sortedhashonly -table.sortedindexonly=sortedindexonly -table.sortedhashkeys=sortedhashkeys -local function nothing() end -local function sortedhash(t,cmp) - if t then - local s - if cmp then - s=sortedhashkeys(t,function(a,b) return cmp(t,a,b) end) - else - s=sortedkeys(t) - end - local m=#s - if m==1 then - return next,t - elseif m>0 then - local n=0 - return function() - if n<m then - n=n+1 - local k=s[n] - return k,t[k] - end - end - end - end - return nothing -end -table.sortedhash=sortedhash -table.sortedpairs=sortedhash -function table.append(t,list) - local n=#t - for i=1,#list do - n=n+1 - t[n]=list[i] - end - return t -end -function table.prepend(t,list) - local nl=#list - local nt=nl+#t - for i=#t,1,-1 do - t[nt]=t[i] - nt=nt-1 - end - for i=1,#list do - t[i]=list[i] - end - return t -end -function table.merge(t,...) - t=t or {} - for i=1,select("#",...) do - for k,v in next,(select(i,...)) do - t[k]=v - end - end - return t -end -function table.merged(...) - local t={} - for i=1,select("#",...) do - for k,v in next,(select(i,...)) do - t[k]=v - end - end - return t -end -function table.imerge(t,...) - local nt=#t - for i=1,select("#",...) do - local nst=select(i,...) - for j=1,#nst do - nt=nt+1 - t[nt]=nst[j] - end - end - return t -end -function table.imerged(...) - local tmp,ntmp={},0 - for i=1,select("#",...) do - local nst=select(i,...) - for j=1,#nst do - ntmp=ntmp+1 - tmp[ntmp]=nst[j] - end - end - return tmp -end -local function fastcopy(old,metatabletoo) - if old then - local new={} - for k,v in next,old do - if type(v)=="table" then - new[k]=fastcopy(v,metatabletoo) - else - new[k]=v - end - end - if metatabletoo then - local mt=getmetatable(old) - if mt then - setmetatable(new,mt) - end - end - return new - else - return {} - end -end -local function copy(t,tables) - tables=tables or {} - local tcopy={} - if not tables[t] then - tables[t]=tcopy - end - for i,v in next,t do - if type(i)=="table" then - if tables[i] then - i=tables[i] - else - i=copy(i,tables) - end - end - if type(v)~="table" then - tcopy[i]=v - elseif tables[v] then - tcopy[i]=tables[v] - else - tcopy[i]=copy(v,tables) - end - end - local mt=getmetatable(t) - if mt then - setmetatable(tcopy,mt) - end - return tcopy -end -table.fastcopy=fastcopy -table.copy=copy -function table.derive(parent) - local child={} - if parent then - setmetatable(child,{ __index=parent }) - end - return child -end -function table.tohash(t,value) - local h={} - if t then - if value==nil then value=true end - for _,v in next,t do - h[v]=value - end - end - return h -end -function table.fromhash(t) - local hsh,h={},0 - for k,v in next,t do - if v then - h=h+1 - hsh[h]=k - end - end - return hsh -end -local noquotes,hexify,handle,compact,inline,functions -local reserved=table.tohash { - 'and','break','do','else','elseif','end','false','for','function','if', - 'in','local','nil','not','or','repeat','return','then','true','until','while', - 'NaN','goto', -} -local function simple_table(t) - local nt=#t - if nt>0 then - local n=0 - for _,v in next,t do - n=n+1 - end - if n==nt then - local tt={} - for i=1,nt do - local v=t[i] - local tv=type(v) - if tv=="number" then - if hexify then - tt[i]=format("0x%X",v) - else - tt[i]=tostring(v) - end - elseif tv=="string" then - tt[i]=format("%q",v) - elseif tv=="boolean" then - tt[i]=v and "true" or "false" - else - return nil - end - end - return tt - end - end - return nil -end -local propername=patterns.propername -local function dummy() end -local function do_serialize(root,name,depth,level,indexed) - if level>0 then - depth=depth.." " - if indexed then - handle(format("%s{",depth)) - else - local tn=type(name) - if tn=="number" then - if hexify then - handle(format("%s[0x%X]={",depth,name)) - else - handle(format("%s[%s]={",depth,name)) - end - elseif tn=="string" then - if noquotes and not reserved[name] and lpegmatch(propername,name) then - handle(format("%s%s={",depth,name)) - else - handle(format("%s[%q]={",depth,name)) - end - elseif tn=="boolean" then - handle(format("%s[%s]={",depth,name and "true" or "false")) - else - handle(format("%s{",depth)) - end - end - end - if root and next(root)~=nil then - local first,last=nil,0 - if compact then - last=#root - for k=1,last do - if root[k]==nil then - last=k-1 - break - end - end - if last>0 then - first=1 - end - end - local sk=sortedkeys(root) - for i=1,#sk do - local k=sk[i] - local v=root[k] - local tv=type(v) - local tk=type(k) - if compact and first and tk=="number" and k>=first and k<=last then - if tv=="number" then - if hexify then - handle(format("%s 0x%X,",depth,v)) - else - handle(format("%s %s,",depth,v)) - end - elseif tv=="string" then - handle(format("%s %q,",depth,v)) - elseif tv=="table" then - if next(v)==nil then - handle(format("%s {},",depth)) - elseif inline then - local st=simple_table(v) - if st then - handle(format("%s { %s },",depth,concat(st,", "))) - else - do_serialize(v,k,depth,level+1,true) - end - else - do_serialize(v,k,depth,level+1,true) - end - elseif tv=="boolean" then - handle(format("%s %s,",depth,v and "true" or "false")) - elseif tv=="function" then - if functions then - handle(format('%s load(%q),',depth,dump(v))) - else - handle(format('%s "function",',depth)) - end - else - handle(format("%s %q,",depth,tostring(v))) - end - elseif k=="__p__" then - if false then - handle(format("%s __p__=nil,",depth)) - end - elseif tv=="number" then - if tk=="number" then - if hexify then - handle(format("%s [0x%X]=0x%X,",depth,k,v)) - else - handle(format("%s [%s]=%s,",depth,k,v)) - end - elseif tk=="boolean" then - if hexify then - handle(format("%s [%s]=0x%X,",depth,k and "true" or "false",v)) - else - handle(format("%s [%s]=%s,",depth,k and "true" or "false",v)) - end - elseif noquotes and not reserved[k] and lpegmatch(propername,k) then - if hexify then - handle(format("%s %s=0x%X,",depth,k,v)) - else - handle(format("%s %s=%s,",depth,k,v)) - end - else - if hexify then - handle(format("%s [%q]=0x%X,",depth,k,v)) - else - handle(format("%s [%q]=%s,",depth,k,v)) - end - end - elseif tv=="string" then - if tk=="number" then - if hexify then - handle(format("%s [0x%X]=%q,",depth,k,v)) - else - handle(format("%s [%s]=%q,",depth,k,v)) - end - elseif tk=="boolean" then - handle(format("%s [%s]=%q,",depth,k and "true" or "false",v)) - elseif noquotes and not reserved[k] and lpegmatch(propername,k) then - handle(format("%s %s=%q,",depth,k,v)) - else - handle(format("%s [%q]=%q,",depth,k,v)) - end - elseif tv=="table" then - if next(v)==nil then - if tk=="number" then - if hexify then - handle(format("%s [0x%X]={},",depth,k)) - else - handle(format("%s [%s]={},",depth,k)) - end - elseif tk=="boolean" then - handle(format("%s [%s]={},",depth,k and "true" or "false")) - elseif noquotes and not reserved[k] and lpegmatch(propername,k) then - handle(format("%s %s={},",depth,k)) - else - handle(format("%s [%q]={},",depth,k)) - end - elseif inline then - local st=simple_table(v) - if st then - if tk=="number" then - if hexify then - handle(format("%s [0x%X]={ %s },",depth,k,concat(st,", "))) - else - handle(format("%s [%s]={ %s },",depth,k,concat(st,", "))) - end - elseif tk=="boolean" then - handle(format("%s [%s]={ %s },",depth,k and "true" or "false",concat(st,", "))) - elseif noquotes and not reserved[k] and lpegmatch(propername,k) then - handle(format("%s %s={ %s },",depth,k,concat(st,", "))) - else - handle(format("%s [%q]={ %s },",depth,k,concat(st,", "))) - end - else - do_serialize(v,k,depth,level+1) - end - else - do_serialize(v,k,depth,level+1) - end - elseif tv=="boolean" then - if tk=="number" then - if hexify then - handle(format("%s [0x%X]=%s,",depth,k,v and "true" or "false")) - else - handle(format("%s [%s]=%s,",depth,k,v and "true" or "false")) - end - elseif tk=="boolean" then - handle(format("%s [%s]=%s,",depth,tostring(k),v and "true" or "false")) - elseif noquotes and not reserved[k] and lpegmatch(propername,k) then - handle(format("%s %s=%s,",depth,k,v and "true" or "false")) - else - handle(format("%s [%q]=%s,",depth,k,v and "true" or "false")) - end - elseif tv=="function" then - if functions then - local f=getinfo(v).what=="C" and dump(dummy) or dump(v) - if tk=="number" then - if hexify then - handle(format("%s [0x%X]=load(%q),",depth,k,f)) - else - handle(format("%s [%s]=load(%q),",depth,k,f)) - end - elseif tk=="boolean" then - handle(format("%s [%s]=load(%q),",depth,k and "true" or "false",f)) - elseif noquotes and not reserved[k] and lpegmatch(propername,k) then - handle(format("%s %s=load(%q),",depth,k,f)) - else - handle(format("%s [%q]=load(%q),",depth,k,f)) - end - end - else - if tk=="number" then - if hexify then - handle(format("%s [0x%X]=%q,",depth,k,tostring(v))) - else - handle(format("%s [%s]=%q,",depth,k,tostring(v))) - end - elseif tk=="boolean" then - handle(format("%s [%s]=%q,",depth,k and "true" or "false",tostring(v))) - elseif noquotes and not reserved[k] and lpegmatch(propername,k) then - handle(format("%s %s=%q,",depth,k,tostring(v))) - else - handle(format("%s [%q]=%q,",depth,k,tostring(v))) - end - end - end - end - if level>0 then - handle(format("%s},",depth)) - end -end -local function serialize(_handle,root,name,specification) - local tname=type(name) - if type(specification)=="table" then - noquotes=specification.noquotes - hexify=specification.hexify - handle=_handle or specification.handle or print - functions=specification.functions - compact=specification.compact - inline=specification.inline and compact - if functions==nil then - functions=true - end - if compact==nil then - compact=true - end - if inline==nil then - inline=compact - end - else - noquotes=false - hexify=false - handle=_handle or print - compact=true - inline=true - functions=true - end - if tname=="string" then - if name=="return" then - handle("return {") - else - handle(name.."={") - end - elseif tname=="number" then - if hexify then - handle(format("[0x%X]={",name)) - else - handle("["..name.."]={") - end - elseif tname=="boolean" then - if name then - handle("return {") - else - handle("{") - end - else - handle("t={") - end - if root then - if getmetatable(root) then - local dummy=root._w_h_a_t_e_v_e_r_ - root._w_h_a_t_e_v_e_r_=nil - end - if next(root)~=nil then - do_serialize(root,name,"",0) - end - end - handle("}") -end -function table.serialize(root,name,specification) - local t,n={},0 - local function flush(s) - n=n+1 - t[n]=s - end - serialize(flush,root,name,specification) - return concat(t,"\n") -end -table.tohandle=serialize -local maxtab=2*1024 -function table.tofile(filename,root,name,specification) - local f=io.open(filename,'w') - if f then - if maxtab>1 then - local t,n={},0 - local function flush(s) - n=n+1 - t[n]=s - if n>maxtab then - f:write(concat(t,"\n"),"\n") - t,n={},0 - end - end - serialize(flush,root,name,specification) - f:write(concat(t,"\n"),"\n") - else - local function flush(s) - f:write(s,"\n") - end - serialize(flush,root,name,specification) - end - f:close() - io.flush() - end -end -local function flattened(t,f,depth) - if f==nil then - f={} - depth=0xFFFF - elseif tonumber(f) then - depth=f - f={} - elseif not depth then - depth=0xFFFF - end - for k,v in next,t do - if type(k)~="number" then - if depth>0 and type(v)=="table" then - flattened(v,f,depth-1) - else - f[#f+1]=v - end - end - end - for k=1,#t do - local v=t[k] - if depth>0 and type(v)=="table" then - flattened(v,f,depth-1) - else - f[#f+1]=v - end - end - return f -end -table.flattened=flattened -local function unnest(t,f) - if not f then - f={} - end - for i=1,#t do - local v=t[i] - if type(v)=="table" then - if type(v[1])=="table" then - unnest(v,f) - else - f[#f+1]=v - end - else - f[#f+1]=v - end - end - return f -end -function table.unnest(t) - return unnest(t) -end -local function are_equal(a,b,n,m) - if a and b and #a==#b then - n=n or 1 - m=m or #a - for i=n,m do - local ai,bi=a[i],b[i] - if ai==bi then - elseif type(ai)=="table" and type(bi)=="table" then - if not are_equal(ai,bi) then - return false - end - else - return false - end - end - return true - else - return false - end -end -local function identical(a,b) - for ka,va in next,a do - local vb=b[ka] - if va==vb then - elseif type(va)=="table" and type(vb)=="table" then - if not identical(va,vb) then - return false - end - else - return false - end - end - return true -end -table.identical=identical -table.are_equal=are_equal -local function sparse(old,nest,keeptables) - local new={} - for k,v in next,old do - if not (v=="" or v==false) then - if nest and type(v)=="table" then - v=sparse(v,nest) - if keeptables or next(v)~=nil then - new[k]=v - end - else - new[k]=v - end - end - end - return new -end -table.sparse=sparse -function table.compact(t) - return sparse(t,true,true) -end -function table.contains(t,v) - if t then - for i=1,#t do - if t[i]==v then - return i - end - end - end - return false -end -function table.count(t) - local n=0 - for k,v in next,t do - n=n+1 - end - return n -end -function table.swapped(t,s) - local n={} - if s then - for k,v in next,s do - n[k]=v - end - end - for k,v in next,t do - n[v]=k - end - return n -end -function table.mirrored(t) - local n={} - for k,v in next,t do - n[v]=k - n[k]=v - end - return n -end -function table.reversed(t) - if t then - local tt,tn={},#t - if tn>0 then - local ttn=0 - for i=tn,1,-1 do - ttn=ttn+1 - tt[ttn]=t[i] - end - end - return tt - end -end -function table.reverse(t) - if t then - local n=#t - for i=1,floor(n/2) do - local j=n-i+1 - t[i],t[j]=t[j],t[i] - end - return t - end -end -function table.sequenced(t,sep,simple) - if not t then - return "" - end - local n=#t - local s={} - if n>0 then - for i=1,n do - s[i]=tostring(t[i]) - end - else - n=0 - for k,v in sortedhash(t) do - if simple then - if v==true then - n=n+1 - s[n]=k - elseif v and v~="" then - n=n+1 - s[n]=k.."="..tostring(v) - end - else - n=n+1 - s[n]=k.."="..tostring(v) - end - end - end - return concat(s,sep or " | ") -end -function table.print(t,...) - if type(t)~="table" then - print(tostring(t)) - else - serialize(print,t,...) - end -end -if setinspector then - setinspector("table",function(v) if type(v)=="table" then serialize(print,v,"table") return true end end) -end -function table.sub(t,i,j) - return { unpack(t,i,j) } -end -function table.is_empty(t) - return not t or next(t)==nil -end -function table.has_one_entry(t) - return t and next(t,next(t))==nil -end -function table.loweredkeys(t) - local l={} - for k,v in next,t do - l[lower(k)]=v - end - return l -end -function table.unique(old) - local hash={} - local new={} - local n=0 - for i=1,#old do - local oi=old[i] - if not hash[oi] then - n=n+1 - new[n]=oi - hash[oi]=true - end - end - return new -end -function table.sorted(t,...) - sort(t,...) - return t -end -function table.values(t,s) - if t then - local values,keys,v={},{},0 - for key,value in next,t do - if not keys[value] then - v=v+1 - values[v]=value - keys[k]=key - end - end - if s then - sort(values) - end - return values - else - return {} - end -end -function table.filtered(t,pattern,sort,cmp) - if t and type(pattern)=="string" then - if sort then - local s - if cmp then - s=sortedhashkeys(t,function(a,b) return cmp(t,a,b) end) - else - s=sortedkeys(t) - end - local n=0 - local m=#s - local function kv(s) - while n<m do - n=n+1 - local k=s[n] - if find(k,pattern) then - return k,t[k] - end - end - end - return kv,s - else - local n=next(t) - local function iterator() - while n~=nil do - local k=n - n=next(t,k) - if find(k,pattern) then - return k,t[k] - end - end - end - return iterator,t - end - else - return nothing - end -end - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['l-boolean']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local type,tonumber=type,tonumber -boolean=boolean or {} -local boolean=boolean -function boolean.tonumber(b) - if b then return 1 else return 0 end -end -function toboolean(str,tolerant) - if str==nil then - return false - elseif str==false then - return false - elseif str==true then - return true - elseif str=="true" then - return true - elseif str=="false" then - return false - elseif not tolerant then - return false - elseif str==0 then - return false - elseif (tonumber(str) or 0)>0 then - return true - else - return str=="yes" or str=="on" or str=="t" - end -end -string.toboolean=toboolean -function string.booleanstring(str) - if str=="0" then - return false - elseif str=="1" then - return true - elseif str=="" then - return false - elseif str=="false" then - return false - elseif str=="true" then - return true - elseif (tonumber(str) or 0)>0 then - return true - else - return str=="yes" or str=="on" or str=="t" - end -end -function string.is_boolean(str,default,strict) - if type(str)=="string" then - if str=="true" or str=="yes" or str=="on" or str=="t" or (not strict and str=="1") then - return true - elseif str=="false" or str=="no" or str=="off" or str=="f" or (not strict and str=="0") then - return false - end - end - return default -end - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['l-number']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local tostring,tonumber=tostring,tonumber -local format,floor,match,rep=string.format,math.floor,string.match,string.rep -local concat,insert=table.concat,table.insert -local lpegmatch=lpeg.match -number=number or {} -local number=number -if bit32 then - local btest,bor=bit32.btest,bit32.bor - function number.bit(p) - return 2^(p-1) - end - number.hasbit=btest - number.setbit=bor - function number.setbit(x,p) - return btest(x,p) and x or x+p - end - function number.clearbit(x,p) - return btest(x,p) and x-p or x - end -else - function number.bit(p) - return 2^(p-1) - end - function number.hasbit(x,p) - return x%(p+p)>=p - end - function number.setbit(x,p) - return (x%(p+p)>=p) and x or x+p - end - function number.clearbit(x,p) - return (x%(p+p)>=p) and x-p or x - end -end -if bit32 then - local bextract=bit32.extract - local t={ - "0","0","0","0","0","0","0","0", - "0","0","0","0","0","0","0","0", - "0","0","0","0","0","0","0","0", - "0","0","0","0","0","0","0","0", - } - function number.tobitstring(b,m) - local n=32 - for i=0,31 do - local v=bextract(b,i) - local k=32-i - if v==1 then - n=k - t[k]="1" - else - t[k]="0" - end - end - if m then - m=33-m*8 - if m<1 then - m=1 - end - return concat(t,"",m) - elseif n<8 then - return concat(t) - elseif n<16 then - return concat(t,"",9) - elseif n<24 then - return concat(t,"",17) - else - return concat(t,"",25) - end - end -else - function number.tobitstring(n,m) - if n>0 then - local t={} - while n>0 do - insert(t,1,n%2>0 and 1 or 0) - n=floor(n/2) - end - local nn=8-#t%8 - if nn>0 and nn<8 then - for i=1,nn do - insert(t,1,0) - end - end - if m then - m=m*8-#t - if m>0 then - insert(t,1,rep("0",m)) - end - end - return concat(t) - elseif m then - rep("00000000",m) - else - return "00000000" - end - end -end -function number.valid(str,default) - return tonumber(str) or default or nil -end -function number.toevenhex(n) - local s=format("%X",n) - if #s%2==0 then - return s - else - return "0"..s - end -end -local one=lpeg.C(1-lpeg.S('')/tonumber)^1 -function number.toset(n) - return lpegmatch(one,tostring(n)) -end -local function bits(n,i,...) - if n>0 then - local m=n%2 - local n=floor(n/2) - if m>0 then - return bits(n,i+1,i,...) - else - return bits(n,i+1,...) - end - else - return... - end -end -function number.bits(n) - return { bits(n,1) } -end - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['l-math']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local floor,sin,cos,tan=math.floor,math.sin,math.cos,math.tan -if not math.ceiling then - math.ceiling=math.ceil -end -if not math.round then - function math.round(x) return floor(x+0.5) end -end -if not math.div then - function math.div(n,m) return floor(n/m) end -end -if not math.mod then - function math.mod(n,m) return n%m end -end -local pipi=2*math.pi/360 -if not math.sind then - function math.sind(d) return sin(d*pipi) end - function math.cosd(d) return cos(d*pipi) end - function math.tand(d) return tan(d*pipi) end -end -if not math.odd then - function math.odd (n) return n%2~=0 end - function math.even(n) return n%2==0 end -end - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['l-io']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local io=io -local byte,find,gsub,format=string.byte,string.find,string.gsub,string.format -local concat=table.concat -local floor=math.floor -local type=type -if string.find(os.getenv("PATH"),";",1,true) then - io.fileseparator,io.pathseparator="\\",";" -else - io.fileseparator,io.pathseparator="/",":" -end -local function readall(f) - return f:read("*all") -end -local function readall(f) - local size=f:seek("end") - if size==0 then - return "" - elseif size<1024*1024 then - f:seek("set",0) - return f:read('*all') - else - local done=f:seek("set",0) - local step - if size<1024*1024 then - step=1024*1024 - elseif size>16*1024*1024 then - step=16*1024*1024 - else - step=floor(size/(1024*1024))*1024*1024/8 - end - local data={} - while true do - local r=f:read(step) - if not r then - return concat(data) - else - data[#data+1]=r - end - end - end -end -io.readall=readall -function io.loaddata(filename,textmode) - local f=io.open(filename,(textmode and 'r') or 'rb') - if f then - local data=readall(f) - f:close() - if #data>0 then - return data - end - end -end -function io.savedata(filename,data,joiner) - local f=io.open(filename,"wb") - if f then - if type(data)=="table" then - f:write(concat(data,joiner or "")) - elseif type(data)=="function" then - data(f) - else - f:write(data or "") - end - f:close() - io.flush() - return true - else - return false - end -end -function io.loadlines(filename,n) - local f=io.open(filename,'r') - if not f then - elseif n then - local lines={} - for i=1,n do - local line=f:read("*lines") - if line then - lines[#lines+1]=line - else - break - end - end - f:close() - lines=concat(lines,"\n") - if #lines>0 then - return lines - end - else - local line=f:read("*line") or "" - f:close() - if #line>0 then - return line - end - end -end -function io.loadchunk(filename,n) - local f=io.open(filename,'rb') - if f then - local data=f:read(n or 1024) - f:close() - if #data>0 then - return data - end - end -end -function io.exists(filename) - local f=io.open(filename) - if f==nil then - return false - else - f:close() - return true - end -end -function io.size(filename) - local f=io.open(filename) - if f==nil then - return 0 - else - local s=f:seek("end") - f:close() - return s - end -end -function io.noflines(f) - if type(f)=="string" then - local f=io.open(filename) - if f then - local n=f and io.noflines(f) or 0 - f:close() - return n - else - return 0 - end - else - local n=0 - for _ in f:lines() do - n=n+1 - end - f:seek('set',0) - return n - end -end -local nextchar={ - [ 4]=function(f) - return f:read(1,1,1,1) - end, - [ 2]=function(f) - return f:read(1,1) - end, - [ 1]=function(f) - return f:read(1) - end, - [-2]=function(f) - local a,b=f:read(1,1) - return b,a - end, - [-4]=function(f) - local a,b,c,d=f:read(1,1,1,1) - return d,c,b,a - end -} -function io.characters(f,n) - if f then - return nextchar[n or 1],f - end -end -local nextbyte={ - [4]=function(f) - local a,b,c,d=f:read(1,1,1,1) - if d then - return byte(a),byte(b),byte(c),byte(d) - end - end, - [3]=function(f) - local a,b,c=f:read(1,1,1) - if b then - return byte(a),byte(b),byte(c) - end - end, - [2]=function(f) - local a,b=f:read(1,1) - if b then - return byte(a),byte(b) - end - end, - [1]=function (f) - local a=f:read(1) - if a then - return byte(a) - end - end, - [-2]=function (f) - local a,b=f:read(1,1) - if b then - return byte(b),byte(a) - end - end, - [-3]=function(f) - local a,b,c=f:read(1,1,1) - if b then - return byte(c),byte(b),byte(a) - end - end, - [-4]=function(f) - local a,b,c,d=f:read(1,1,1,1) - if d then - return byte(d),byte(c),byte(b),byte(a) - end - end -} -function io.bytes(f,n) - if f then - return nextbyte[n or 1],f - else - return nil,nil - end -end -function io.ask(question,default,options) - while true do - io.write(question) - if options then - io.write(format(" [%s]",concat(options,"|"))) - end - if default then - io.write(format(" [%s]",default)) - end - io.write(format(" ")) - io.flush() - local answer=io.read() - answer=gsub(answer,"^%s*(.*)%s*$","%1") - if answer=="" and default then - return default - elseif not options then - return answer - else - for k=1,#options do - if options[k]==answer then - return answer - end - end - local pattern="^"..answer - for k=1,#options do - local v=options[k] - if find(v,pattern) then - return v - end - end - end - end -end -local function readnumber(f,n,m) - if m then - f:seek("set",n) - n=m - end - if n==1 then - return byte(f:read(1)) - elseif n==2 then - local a,b=byte(f:read(2),1,2) - return 256*a+b - elseif n==3 then - local a,b,c=byte(f:read(3),1,3) - return 256*256*a+256*b+c - elseif n==4 then - local a,b,c,d=byte(f:read(4),1,4) - return 256*256*256*a+256*256*b+256*c+d - elseif n==8 then - local a,b=readnumber(f,4),readnumber(f,4) - return 256*a+b - elseif n==12 then - local a,b,c=readnumber(f,4),readnumber(f,4),readnumber(f,4) - return 256*256*a+256*b+c - elseif n==-2 then - local b,a=byte(f:read(2),1,2) - return 256*a+b - elseif n==-3 then - local c,b,a=byte(f:read(3),1,3) - return 256*256*a+256*b+c - elseif n==-4 then - local d,c,b,a=byte(f:read(4),1,4) - return 256*256*256*a+256*256*b+256*c+d - elseif n==-8 then - local h,g,f,e,d,c,b,a=byte(f:read(8),1,8) - return 256*256*256*256*256*256*256*a+256*256*256*256*256*256*b+256*256*256*256*256*c+256*256*256*256*d+256*256*256*e+256*256*f+256*g+h - else - return 0 - end -end -io.readnumber=readnumber -function io.readstring(f,n,m) - if m then - f:seek("set",n) - n=m - end - local str=gsub(f:read(n),"\000","") - return str -end - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['l-os']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local os=os -local date,time=os.date,os.time -local find,format,gsub,upper,gmatch=string.find,string.format,string.gsub,string.upper,string.gmatch -local concat=table.concat -local random,ceil,randomseed=math.random,math.ceil,math.randomseed -local rawget,rawset,type,getmetatable,setmetatable,tonumber,tostring=rawget,rawset,type,getmetatable,setmetatable,tonumber,tostring -math.initialseed=tonumber(string.sub(string.reverse(tostring(ceil(socket and socket.gettime()*10000 or time()))),1,6)) -randomseed(math.initialseed) -if not os.__getenv__ then - os.__getenv__=os.getenv - os.__setenv__=os.setenv - if os.env then - local osgetenv=os.getenv - local ossetenv=os.setenv - local osenv=os.env local _=osenv.PATH - function os.setenv(k,v) - if v==nil then - v="" - end - local K=upper(k) - osenv[K]=v - if type(v)=="table" then - v=concat(v,";") - end - ossetenv(K,v) - end - function os.getenv(k) - local K=upper(k) - local v=osenv[K] or osenv[k] or osgetenv(K) or osgetenv(k) - if v=="" then - return nil - else - return v - end - end - else - local ossetenv=os.setenv - local osgetenv=os.getenv - local osenv={} - function os.setenv(k,v) - if v==nil then - v="" - end - local K=upper(k) - osenv[K]=v - end - function os.getenv(k) - local K=upper(k) - local v=osenv[K] or osgetenv(K) or osgetenv(k) - if v=="" then - return nil - else - return v - end - end - local function __index(t,k) - return os.getenv(k) - end - local function __newindex(t,k,v) - os.setenv(k,v) - end - os.env={} - setmetatable(os.env,{ __index=__index,__newindex=__newindex } ) - end -end -local execute=os.execute -local iopopen=io.popen -function os.resultof(command) - local handle=iopopen(command,"r") - if handle then - local result=handle:read("*all") or "" - handle:close() - return result - else - return "" - end -end -if not io.fileseparator then - if find(os.getenv("PATH"),";",1,true) then - io.fileseparator,io.pathseparator,os.type="\\",";",os.type or "mswin" - else - io.fileseparator,io.pathseparator,os.type="/",":",os.type or "unix" - end -end -os.type=os.type or (io.pathseparator==";" and "windows") or "unix" -os.name=os.name or (os.type=="windows" and "mswin" ) or "linux" -if os.type=="windows" then - os.libsuffix,os.binsuffix,os.binsuffixes='dll','exe',{ 'exe','cmd','bat' } -else - os.libsuffix,os.binsuffix,os.binsuffixes='so','',{ '' } -end -local launchers={ - windows="start %s", - macosx="open %s", - unix="$BROWSER %s &> /dev/null &", -} -function os.launch(str) - execute(format(launchers[os.name] or launchers.unix,str)) -end -if not os.times then - function os.times() - return { - utime=os.gettimeofday(), - stime=0, - cutime=0, - cstime=0, - } - end -end -local gettimeofday=os.gettimeofday or os.clock -os.gettimeofday=gettimeofday -local startuptime=gettimeofday() -function os.runtime() - return gettimeofday()-startuptime -end -local resolvers=os.resolvers or {} -os.resolvers=resolvers -setmetatable(os,{ __index=function(t,k) - local r=resolvers[k] - return r and r(t,k) or nil -end }) -local name,platform=os.name or "linux",os.getenv("MTX_PLATFORM") or "" -local function guess() - local architecture=os.resultof("uname -m") or "" - if architecture~="" then - return architecture - end - architecture=os.getenv("HOSTTYPE") or "" - if architecture~="" then - return architecture - end - return os.resultof("echo $HOSTTYPE") or "" -end -if platform~="" then - os.platform=platform -elseif os.type=="windows" then - function resolvers.platform(t,k) - local platform,architecture="",os.getenv("PROCESSOR_ARCHITECTURE") or "" - if find(architecture,"AMD64",1,true) then - platform="win64" - else - platform="mswin" - end - os.setenv("MTX_PLATFORM",platform) - os.platform=platform - return platform - end -elseif name=="linux" then - function resolvers.platform(t,k) - local platform,architecture="",os.getenv("HOSTTYPE") or os.resultof("uname -m") or "" - if find(architecture,"x86_64",1,true) then - platform="linux-64" - elseif find(architecture,"ppc",1,true) then - platform="linux-ppc" - else - platform="linux" - end - os.setenv("MTX_PLATFORM",platform) - os.platform=platform - return platform - end -elseif name=="macosx" then - function resolvers.platform(t,k) - local platform,architecture="",os.resultof("echo $HOSTTYPE") or "" - if architecture=="" then - platform="osx-intel" - elseif find(architecture,"i386",1,true) then - platform="osx-intel" - elseif find(architecture,"x86_64",1,true) then - platform="osx-64" - else - platform="osx-ppc" - end - os.setenv("MTX_PLATFORM",platform) - os.platform=platform - return platform - end -elseif name=="sunos" then - function resolvers.platform(t,k) - local platform,architecture="",os.resultof("uname -m") or "" - if find(architecture,"sparc",1,true) then - platform="solaris-sparc" - else - platform="solaris-intel" - end - os.setenv("MTX_PLATFORM",platform) - os.platform=platform - return platform - end -elseif name=="freebsd" then - function resolvers.platform(t,k) - local platform,architecture="",os.resultof("uname -m") or "" - if find(architecture,"amd64",1,true) then - platform="freebsd-amd64" - else - platform="freebsd" - end - os.setenv("MTX_PLATFORM",platform) - os.platform=platform - return platform - end -elseif name=="kfreebsd" then - function resolvers.platform(t,k) - local platform,architecture="",os.getenv("HOSTTYPE") or os.resultof("uname -m") or "" - if find(architecture,"x86_64",1,true) then - platform="kfreebsd-amd64" - else - platform="kfreebsd-i386" - end - os.setenv("MTX_PLATFORM",platform) - os.platform=platform - return platform - end -else - function resolvers.platform(t,k) - local platform="linux" - os.setenv("MTX_PLATFORM",platform) - os.platform=platform - return platform - end -end -os.newline=name=="windows" and "\013\010" or "\010" -function resolvers.bits(t,k) - local bits=find(os.platform,"64",1,true) and 64 or 32 - os.bits=bits - return bits -end -local t={ 8,9,"a","b" } -function os.uuid() - return format("%04x%04x-4%03x-%s%03x-%04x-%04x%04x%04x", - random(0xFFFF),random(0xFFFF), - random(0x0FFF), - t[ceil(random(4))] or 8,random(0x0FFF), - random(0xFFFF), - random(0xFFFF),random(0xFFFF),random(0xFFFF) - ) -end -local d -function os.timezone(delta) - d=d or tonumber(tonumber(date("%H")-date("!%H"))) - if delta then - if d>0 then - return format("+%02i:00",d) - else - return format("-%02i:00",-d) - end - else - return 1 - end -end -local timeformat=format("%%s%s",os.timezone(true)) -local dateformat="!%Y-%m-%d %H:%M:%S" -local lasttime=nil -local lastdate=nil -function os.fulltime(t,default) - t=t and tonumber(t) or 0 - if t>0 then - elseif default then - return default - else - t=time() - end - if t~=lasttime then - lasttime=t - lastdate=format(timeformat,date(dateformat)) - end - return lastdate -end -local dateformat="%Y-%m-%d %H:%M:%S" -local lasttime=nil -local lastdate=nil -function os.localtime(t,default) - t=t and tonumber(t) or 0 - if t>0 then - elseif default then - return default - else - t=time() - end - if t~=lasttime then - lasttime=t - lastdate=date(dateformat,t) - end - return lastdate -end -function os.converttime(t,default) - local t=tonumber(t) - if t and t>0 then - return date(dateformat,t) - else - return default or "-" - end -end -local memory={} -local function which(filename) - local fullname=memory[filename] - if fullname==nil then - local suffix=file.suffix(filename) - local suffixes=suffix=="" and os.binsuffixes or { suffix } - for directory in gmatch(os.getenv("PATH"),"[^"..io.pathseparator.."]+") do - local df=file.join(directory,filename) - for i=1,#suffixes do - local dfs=file.addsuffix(df,suffixes[i]) - if io.exists(dfs) then - fullname=dfs - break - end - end - end - if not fullname then - fullname=false - end - memory[filename]=fullname - end - return fullname -end -os.which=which -os.where=which -function os.today() - return date("!*t") -end -function os.now() - return date("!%Y-%m-%d %H:%M:%S") -end -if not os.sleep then - local socket=socket - function os.sleep(n) - if not socket then - socket=require("socket") - end - socket.sleep(n) - end -end -local function isleapyear(year) - return (year%400==0) or ((year%100~=0) and (year%4==0)) -end -os.isleapyear=isleapyear -local days={ 31,28,31,30,31,30,31,31,30,31,30,31 } -local function nofdays(year,month) - if not month then - return isleapyear(year) and 365 or 364 - else - return month==2 and isleapyear(year) and 29 or days[month] - end -end -os.nofdays=nofdays -function os.weekday(day,month,year) - return date("%w",time { year=year,month=month,day=day })+1 -end -function os.validdate(year,month,day) - if month<1 then - month=1 - elseif month>12 then - month=12 - end - if day<1 then - day=1 - else - local max=nofdays(year,month) - if day>max then - day=max - end - end - return year,month,day -end - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['l-file']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -file=file or {} -local file=file -if not lfs then - lfs=optionalrequire("lfs") -end -local insert,concat=table.insert,table.concat -local match,find,gmatch=string.match,string.find,string.gmatch -local lpegmatch=lpeg.match -local getcurrentdir,attributes=lfs.currentdir,lfs.attributes -local checkedsplit=string.checkedsplit -local P,R,S,C,Cs,Cp,Cc,Ct=lpeg.P,lpeg.R,lpeg.S,lpeg.C,lpeg.Cs,lpeg.Cp,lpeg.Cc,lpeg.Ct -local tricky=S("/\\")*P(-1) -local attributes=lfs.attributes -if sandbox then - sandbox.redefine(lfs.isfile,"lfs.isfile") - sandbox.redefine(lfs.isdir,"lfs.isdir") -end -function lfs.isdir(name) - if lpegmatch(tricky,name) then - return attributes(name,"mode")=="directory" - else - return attributes(name.."/.","mode")=="directory" - end -end -function lfs.isfile(name) - return attributes(name,"mode")=="file" -end -local colon=P(":") -local period=P(".") -local periods=P("..") -local fwslash=P("/") -local bwslash=P("\\") -local slashes=S("\\/") -local noperiod=1-period -local noslashes=1-slashes -local name=noperiod^1 -local suffix=period/""*(1-period-slashes)^1*-1 -local pattern=C((1-(slashes^1*noslashes^1*-1))^1)*P(1) -local function pathpart(name,default) - return name and lpegmatch(pattern,name) or default or "" -end -local pattern=(noslashes^0*slashes)^1*C(noslashes^1)*-1 -local function basename(name) - return name and lpegmatch(pattern,name) or name -end -local pattern=(noslashes^0*slashes^1)^0*Cs((1-suffix)^1)*suffix^0 -local function nameonly(name) - return name and lpegmatch(pattern,name) or name -end -local pattern=(noslashes^0*slashes)^0*(noperiod^1*period)^1*C(noperiod^1)*-1 -local function suffixonly(name) - return name and lpegmatch(pattern,name) or "" -end -local pattern=(noslashes^0*slashes)^0*noperiod^1*((period*C(noperiod^1))^1)*-1+Cc("") -local function suffixesonly(name) - if name then - return lpegmatch(pattern,name) - else - return "" - end -end -file.pathpart=pathpart -file.basename=basename -file.nameonly=nameonly -file.suffixonly=suffixonly -file.suffix=suffixonly -file.suffixesonly=suffixesonly -file.suffixes=suffixesonly -file.dirname=pathpart -file.extname=suffixonly -local drive=C(R("az","AZ"))*colon -local path=C((noslashes^0*slashes)^0) -local suffix=period*C(P(1-period)^0*P(-1)) -local base=C((1-suffix)^0) -local rest=C(P(1)^0) -drive=drive+Cc("") -path=path+Cc("") -base=base+Cc("") -suffix=suffix+Cc("") -local pattern_a=drive*path*base*suffix -local pattern_b=path*base*suffix -local pattern_c=C(drive*path)*C(base*suffix) -local pattern_d=path*rest -function file.splitname(str,splitdrive) - if not str then - elseif splitdrive then - return lpegmatch(pattern_a,str) - else - return lpegmatch(pattern_b,str) - end -end -function file.splitbase(str) - if str then - return lpegmatch(pattern_d,str) - else - return "",str - end -end -function file.nametotable(str,splitdrive) - if str then - local path,drive,subpath,name,base,suffix=lpegmatch(pattern_c,str) - if splitdrive then - return { - path=path, - drive=drive, - subpath=subpath, - name=name, - base=base, - suffix=suffix, - } - else - return { - path=path, - name=name, - base=base, - suffix=suffix, - } - end - end -end -local pattern=Cs(((period*(1-period-slashes)^1*-1)/""+1)^1) -function file.removesuffix(name) - return name and lpegmatch(pattern,name) -end -local suffix=period/""*(1-period-slashes)^1*-1 -local pattern=Cs((noslashes^0*slashes^1)^0*((1-suffix)^1))*Cs(suffix) -function file.addsuffix(filename,suffix,criterium) - if not filename or not suffix or suffix=="" then - return filename - elseif criterium==true then - return filename.."."..suffix - elseif not criterium then - local n,s=lpegmatch(pattern,filename) - if not s or s=="" then - return filename.."."..suffix - else - return filename - end - else - local n,s=lpegmatch(pattern,filename) - if s and s~="" then - local t=type(criterium) - if t=="table" then - for i=1,#criterium do - if s==criterium[i] then - return filename - end - end - elseif t=="string" then - if s==criterium then - return filename - end - end - end - return (n or filename).."."..suffix - end -end -local suffix=period*(1-period-slashes)^1*-1 -local pattern=Cs((1-suffix)^0) -function file.replacesuffix(name,suffix) - if name and suffix and suffix~="" then - return lpegmatch(pattern,name).."."..suffix - else - return name - end -end -local reslasher=lpeg.replacer(P("\\"),"/") -function file.reslash(str) - return str and lpegmatch(reslasher,str) -end -function file.is_writable(name) - if not name then - elseif lfs.isdir(name) then - name=name.."/m_t_x_t_e_s_t.tmp" - local f=io.open(name,"wb") - if f then - f:close() - os.remove(name) - return true - end - elseif lfs.isfile(name) then - local f=io.open(name,"ab") - if f then - f:close() - return true - end - else - local f=io.open(name,"ab") - if f then - f:close() - os.remove(name) - return true - end - end - return false -end -local readable=P("r")*Cc(true) -function file.is_readable(name) - if name then - local a=attributes(name) - return a and lpegmatch(readable,a.permissions) or false - else - return false - end -end -file.isreadable=file.is_readable -file.iswritable=file.is_writable -function file.size(name) - if name then - local a=attributes(name) - return a and a.size or 0 - else - return 0 - end -end -function file.splitpath(str,separator) - return str and checkedsplit(lpegmatch(reslasher,str),separator or io.pathseparator) -end -function file.joinpath(tab,separator) - return tab and concat(tab,separator or io.pathseparator) -end -local someslash=S("\\/") -local stripper=Cs(P(fwslash)^0/""*reslasher) -local isnetwork=someslash*someslash*(1-someslash)+(1-fwslash-colon)^1*colon -local isroot=fwslash^1*-1 -local hasroot=fwslash^1 -local reslasher=lpeg.replacer(S("\\/"),"/") -local deslasher=lpeg.replacer(S("\\/")^1,"/") -function file.join(one,two,three,...) - if not two then - return one=="" and one or lpegmatch(stripper,one) - end - if one=="" then - return lpegmatch(stripper,three and concat({ two,three,... },"/") or two) - end - if lpegmatch(isnetwork,one) then - local one=lpegmatch(reslasher,one) - local two=lpegmatch(deslasher,three and concat({ two,three,... },"/") or two) - if lpegmatch(hasroot,two) then - return one..two - else - return one.."/"..two - end - elseif lpegmatch(isroot,one) then - local two=lpegmatch(deslasher,three and concat({ two,three,... },"/") or two) - if lpegmatch(hasroot,two) then - return two - else - return "/"..two - end - else - return lpegmatch(deslasher,concat({ one,two,three,... },"/")) - end -end -local drivespec=R("az","AZ")^1*colon -local anchors=fwslash+drivespec -local untouched=periods+(1-period)^1*P(-1) -local mswindrive=Cs(drivespec*(bwslash/"/"+fwslash)^0) -local mswinuncpath=(bwslash+fwslash)*(bwslash+fwslash)*Cc("//") -local splitstarter=(mswindrive+mswinuncpath+Cc(false))*Ct(lpeg.splitat(S("/\\")^1)) -local absolute=fwslash -function file.collapsepath(str,anchor) - if not str then - return - end - if anchor==true and not lpegmatch(anchors,str) then - str=getcurrentdir().."/"..str - end - if str=="" or str=="." then - return "." - elseif lpegmatch(untouched,str) then - return lpegmatch(reslasher,str) - end - local starter,oldelements=lpegmatch(splitstarter,str) - local newelements={} - local i=#oldelements - while i>0 do - local element=oldelements[i] - if element=='.' then - elseif element=='..' then - local n=i-1 - while n>0 do - local element=oldelements[n] - if element~='..' and element~='.' then - oldelements[n]='.' - break - else - n=n-1 - end - end - if n<1 then - insert(newelements,1,'..') - end - elseif element~="" then - insert(newelements,1,element) - end - i=i-1 - end - if #newelements==0 then - return starter or "." - elseif starter then - return starter..concat(newelements,'/') - elseif lpegmatch(absolute,str) then - return "/"..concat(newelements,'/') - else - newelements=concat(newelements,'/') - if anchor=="." and find(str,"^%./") then - return "./"..newelements - else - return newelements - end - end -end -local validchars=R("az","09","AZ","--","..") -local pattern_a=lpeg.replacer(1-validchars) -local pattern_a=Cs((validchars+P(1)/"-")^1) -local whatever=P("-")^0/"" -local pattern_b=Cs(whatever*(1-whatever*-1)^1) -function file.robustname(str,strict) - if str then - str=lpegmatch(pattern_a,str) or str - if strict then - return lpegmatch(pattern_b,str) or str - else - return str - end - end -end -file.readdata=io.loaddata -file.savedata=io.savedata -function file.copy(oldname,newname) - if oldname and newname then - local data=io.loaddata(oldname) - if data and data~="" then - file.savedata(newname,data) - end - end -end -local letter=R("az","AZ")+S("_-+") -local separator=P("://") -local qualified=period^0*fwslash+letter*colon+letter^1*separator+letter^1*fwslash -local rootbased=fwslash+letter*colon -lpeg.patterns.qualified=qualified -lpeg.patterns.rootbased=rootbased -function file.is_qualified_path(filename) - return filename and lpegmatch(qualified,filename)~=nil -end -function file.is_rootbased_path(filename) - return filename and lpegmatch(rootbased,filename)~=nil -end -function file.strip(name,dir) - if name then - local b,a=match(name,"^(.-)"..dir.."(.*)$") - return a~="" and a or name - end -end -function lfs.mkdirs(path) - local full="" - for sub in gmatch(path,"(/*[^\\/]+)") do - full=full..sub - lfs.mkdir(full) - end -end - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['l-gzip']={ - version=1.001, - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -if not gzip then - return -end -local suffix,suffixes=file.suffix,file.suffixes -function gzip.load(filename) - local f=io.open(filename,"rb") - if not f then - elseif suffix(filename)=="gz" then - f:close() - local g=gzip.open(filename,"rb") - if g then - local str=g:read("*all") - g:close() - return str - end - else - local str=f:read("*all") - f:close() - return str - end -end -function gzip.save(filename,data) - if suffix(filename)~="gz" then - filename=filename..".gz" - end - local f=io.open(filename,"wb") - if f then - local s=zlib.compress(data or "",9,nil,15+16) - f:write(s) - f:close() - return #s - end -end -function gzip.suffix(filename) - local suffix,extra=suffixes(filename) - local gzipped=extra=="gz" - return suffix,gzipped -end - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['l-md5']={ - version=1.001, - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -if not md5 then - md5=optionalrequire("md5") -end -if not md5 then - md5={ - sum=function(str) print("error: md5 is not loaded (sum ignored)") return str end, - sumhexa=function(str) print("error: md5 is not loaded (sumhexa ignored)") return str end, - } -end -local md5,file=md5,file -local gsub=string.gsub -do - local patterns=lpeg and lpeg.patterns - if patterns then - local bytestoHEX=patterns.bytestoHEX - local bytestohex=patterns.bytestohex - local bytestodec=patterns.bytestodec - local lpegmatch=lpeg.match - local md5sum=md5.sum - if not md5.HEX then function md5.HEX(str) if str then return lpegmatch(bytestoHEX,md5sum(str)) end end end - if not md5.hex then function md5.hex(str) if str then return lpegmatch(bytestohex,md5sum(str)) end end end - if not md5.dec then function md5.dec(str) if str then return lpegmatch(bytestodec,md5sum(str)) end end end - end -end -function file.needsupdating(oldname,newname,threshold) - local oldtime=lfs.attributes(oldname,"modification") - if oldtime then - local newtime=lfs.attributes(newname,"modification") - if not newtime then - return true - elseif newtime>=oldtime then - return false - elseif oldtime-newtime<(threshold or 1) then - return false - else - return true - end - else - return false - end -end -file.needs_updating=file.needsupdating -function file.syncmtimes(oldname,newname) - local oldtime=lfs.attributes(oldname,"modification") - if oldtime and lfs.isfile(newname) then - lfs.touch(newname,oldtime,oldtime) - end -end -function file.checksum(name) - if md5 then - local data=io.loaddata(name) - if data then - return md5.HEX(data) - end - end - return nil -end -function file.loadchecksum(name) - if md5 then - local data=io.loaddata(name..".md5") - return data and (gsub(data,"%s","")) - end - return nil -end -function file.savechecksum(name,checksum) - if not checksum then checksum=file.checksum(name) end - if checksum then - io.savedata(name..".md5",checksum) - return checksum - end - return nil -end - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['l-dir']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local type,select=type,select -local find,gmatch,match,gsub,sub=string.find,string.gmatch,string.match,string.gsub,string.sub -local concat,insert,remove,unpack=table.concat,table.insert,table.remove,table.unpack -local lpegmatch=lpeg.match -local P,S,R,C,Cc,Cs,Ct,Cv,V=lpeg.P,lpeg.S,lpeg.R,lpeg.C,lpeg.Cc,lpeg.Cs,lpeg.Ct,lpeg.Cv,lpeg.V -dir=dir or {} -local dir=dir -local lfs=lfs -local attributes=lfs.attributes -local walkdir=lfs.dir -local isdir=lfs.isdir -local isfile=lfs.isfile -local currentdir=lfs.currentdir -local chdir=lfs.chdir -local mkdir=lfs.mkdir -local onwindows=os.type=="windows" or find(os.getenv("PATH"),";",1,true) -if onwindows then - local tricky=S("/\\")*P(-1) - isdir=function(name) - if lpegmatch(tricky,name) then - return attributes(name,"mode")=="directory" - else - return attributes(name.."/.","mode")=="directory" - end - end - isfile=function(name) - return attributes(name,"mode")=="file" - end - lfs.isdir=isdir - lfs.isfile=isfile -else - isdir=function(name) - return attributes(name,"mode")=="directory" - end - isfile=function(name) - return attributes(name,"mode")=="file" - end - lfs.isdir=isdir - lfs.isfile=isfile -end -function dir.current() - return (gsub(currentdir(),"\\","/")) -end -local function glob_pattern_function(path,patt,recurse,action) - if isdir(path) then - local usedpath - if path=="/" then - usedpath="/." - elseif not find(path,"/$") then - usedpath=path.."/." - path=path.."/" - else - usedpath=path - end - local dirs - for name in walkdir(usedpath) do - if name~="." and name~=".." then - local full=path..name - local mode=attributes(full,'mode') - if mode=='file' then - if not patt or find(full,patt) then - action(full) - end - elseif recurse and mode=="directory" then - if not dirs then - dirs={ full } - else - dirs[#dirs+1]=full - end - end - end - end - if dirs then - for i=1,#dirs do - glob_pattern_function(dirs[i],patt,recurse,action) - end - end - end -end -local function glob_pattern_table(path,patt,recurse,result) - if not result then - result={} - end - if isdir(path) then - local usedpath - if path=="/" then - usedpath="/." - elseif not find(path,"/$") then - usedpath=path.."/." - path=path.."/" - else - usedpath=path - end - local dirs - for name in walkdir(usedpath) do - if name~="." and name~=".." then - local full=path..name - local mode=attributes(full,'mode') - if mode=='file' then - if not patt or find(full,patt) then - result[#result+1]=full - end - elseif recurse and mode=="directory" then - if not dirs then - dirs={ full } - else - dirs[#dirs+1]=full - end - end - end - end - if dirs then - for i=1,#dirs do - glob_pattern_table(dirs[i],patt,recurse,result) - end - end - end - return result -end -local function globpattern(path,patt,recurse,method) - local kind=type(method) - if patt and sub(patt,1,-3)==path then - patt=false - end - if kind=="function" then - return glob_pattern_function(path,patt,recurse,method) - elseif kind=="table" then - return glob_pattern_table(path,patt,recurse,method) - else - return glob_pattern_table(path,patt,recurse,{}) - end -end -dir.globpattern=globpattern -local function collectpattern(path,patt,recurse,result) - local ok,scanner - result=result or {} - if path=="/" then - ok,scanner,first=xpcall(function() return walkdir(path..".") end,function() end) - else - ok,scanner,first=xpcall(function() return walkdir(path) end,function() end) - end - if ok and type(scanner)=="function" then - if not find(path,"/$") then - path=path..'/' - end - for name in scanner,first do - if name=="." then - elseif name==".." then - else - local full=path..name - local attr=attributes(full) - local mode=attr.mode - if mode=='file' then - if find(full,patt) then - result[name]=attr - end - elseif recurse and mode=="directory" then - attr.list=collectpattern(full,patt,recurse) - result[name]=attr - end - end - end - end - return result -end -dir.collectpattern=collectpattern -local separator,pattern -if onwindows then - local slash=S("/\\")/"/" - pattern={ - [1]=(Cs(P(".")+slash^1)+Cs(R("az","AZ")*P(":")*slash^0)+Cc("./"))*V(2)*V(3), - [2]=Cs(((1-S("*?/\\"))^0*slash)^0), - [3]=Cs(P(1)^0) - } -else - pattern={ - [1]=(C(P(".")+P("/")^1)+Cc("./"))*V(2)*V(3), - [2]=C(((1-S("*?/"))^0*P("/"))^0), - [3]=C(P(1)^0) - } -end -local filter=Cs (( - P("**")/".*"+P("*")/"[^/]*"+P("?")/"[^/]"+P(".")/"%%."+P("+")/"%%+"+P("-")/"%%-"+P(1) -)^0 ) -local function glob(str,t) - if type(t)=="function" then - if type(str)=="table" then - for s=1,#str do - glob(str[s],t) - end - elseif isfile(str) then - t(str) - else - local root,path,base=lpegmatch(pattern,str) - if root and path and base then - local recurse=find(base,"**",1,true) - local start=root..path - local result=lpegmatch(filter,start..base) - globpattern(start,result,recurse,t) - end - end - else - if type(str)=="table" then - local t=t or {} - for s=1,#str do - glob(str[s],t) - end - return t - elseif isfile(str) then - if t then - t[#t+1]=str - return t - else - return { str } - end - else - local root,path,base=lpegmatch(pattern,str) - if root and path and base then - local recurse=find(base,"**",1,true) - local start=root..path - local result=lpegmatch(filter,start..base) - return globpattern(start,result,recurse,t) - else - return {} - end - end - end -end -dir.glob=glob -local function globfiles(path,recurse,func,files) - if type(func)=="string" then - local s=func - func=function(name) return find(name,s) end - end - files=files or {} - local noffiles=#files - for name in walkdir(path) do - if find(name,"^%.") then - else - local mode=attributes(name,'mode') - if mode=="directory" then - if recurse then - globfiles(path.."/"..name,recurse,func,files) - end - elseif mode=="file" then - if not func or func(name) then - noffiles=noffiles+1 - files[noffiles]=path.."/"..name - end - end - end - end - return files -end -dir.globfiles=globfiles -function dir.ls(pattern) - return concat(glob(pattern),"\n") -end -local make_indeed=true -if onwindows then - function dir.mkdirs(...) - local n=select("#",...) - local str - if n==1 then - str=select(1,...) - if isdir(str) then - return str,true - end - else - str="" - for i=1,n do - local s=select(i,...) - if s=="" then - elseif str=="" then - str=s - else - str=str.."/"..s - end - end - end - local pth="" - local drive=false - local first,middle,last=match(str,"^(//)(//*)(.*)$") - if first then - else - first,last=match(str,"^(//)/*(.-)$") - if first then - middle,last=match(str,"([^/]+)/+(.-)$") - if middle then - pth="//"..middle - else - pth="//"..last - last="" - end - else - first,middle,last=match(str,"^([a-zA-Z]:)(/*)(.-)$") - if first then - pth,drive=first..middle,true - else - middle,last=match(str,"^(/*)(.-)$") - if not middle then - last=str - end - end - end - end - for s in gmatch(last,"[^/]+") do - if pth=="" then - pth=s - elseif drive then - pth,drive=pth..s,false - else - pth=pth.."/"..s - end - if make_indeed and not isdir(pth) then - mkdir(pth) - end - end - return pth,(isdir(pth)==true) - end -else - function dir.mkdirs(...) - local n=select("#",...) - local str,pth - if n==1 then - str=select(1,...) - if isdir(str) then - return str,true - end - else - str="" - for i=1,n do - local s=select(i,...) - if s and s~="" then - if str~="" then - str=str.."/"..s - else - str=s - end - end - end - end - str=gsub(str,"/+","/") - if find(str,"^/") then - pth="/" - for s in gmatch(str,"[^/]+") do - local first=(pth=="/") - if first then - pth=pth..s - else - pth=pth.."/"..s - end - if make_indeed and not first and not isdir(pth) then - mkdir(pth) - end - end - else - pth="." - for s in gmatch(str,"[^/]+") do - pth=pth.."/"..s - if make_indeed and not isdir(pth) then - mkdir(pth) - end - end - end - return pth,(isdir(pth)==true) - end -end -dir.makedirs=dir.mkdirs -do - local chdir=sandbox and sandbox.original(chdir) or chdir - if onwindows then - local xcurrentdir=dir.current - function dir.expandname(str) - local first,nothing,last=match(str,"^(//)(//*)(.*)$") - if first then - first=xcurrentdir().."/" - end - if not first then - first,last=match(str,"^(//)/*(.*)$") - end - if not first then - first,last=match(str,"^([a-zA-Z]:)(.*)$") - if first and not find(last,"^/") then - local d=currentdir() - if chdir(first) then - first=xcurrentdir() - end - chdir(d) - end - end - if not first then - first,last=xcurrentdir(),str - end - last=gsub(last,"//","/") - last=gsub(last,"/%./","/") - last=gsub(last,"^/*","") - first=gsub(first,"/*$","") - if last=="" or last=="." then - return first - else - return first.."/"..last - end - end - else - function dir.expandname(str) - if not find(str,"^/") then - str=currentdir().."/"..str - end - str=gsub(str,"//","/") - str=gsub(str,"/%./","/") - str=gsub(str,"(.)/%.$","%1") - return str - end - end -end -file.expandname=dir.expandname -local stack={} -function dir.push(newdir) - insert(stack,currentdir()) - if newdir and newdir~="" then - chdir(newdir) - end -end -function dir.pop() - local d=remove(stack) - if d then - chdir(d) - end - return d -end -local function found(...) - for i=1,select("#",...) do - local path=select(i,...) - local kind=type(path) - if kind=="string" then - if isdir(path) then - return path - end - elseif kind=="table" then - local path=found(unpack(path)) - if path then - return path - end - end - end -end -dir.found=found - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['l-unicode']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -utf=utf or (unicode and unicode.utf8) or {} -utf.characters=utf.characters or string.utfcharacters -utf.values=utf.values or string.utfvalues -local type=type -local char,byte,format,sub,gmatch=string.char,string.byte,string.format,string.sub,string.gmatch -local concat=table.concat -local P,C,R,Cs,Ct,Cmt,Cc,Carg,Cp=lpeg.P,lpeg.C,lpeg.R,lpeg.Cs,lpeg.Ct,lpeg.Cmt,lpeg.Cc,lpeg.Carg,lpeg.Cp -local lpegmatch=lpeg.match -local patterns=lpeg.patterns -local tabletopattern=lpeg.utfchartabletopattern -local bytepairs=string.bytepairs -local finder=lpeg.finder -local replacer=lpeg.replacer -local utfvalues=utf.values -local utfgmatch=utf.gmatch -local p_utftype=patterns.utftype -local p_utfstricttype=patterns.utfstricttype -local p_utfoffset=patterns.utfoffset -local p_utf8char=patterns.utf8character -local p_utf8byte=patterns.utf8byte -local p_utfbom=patterns.utfbom -local p_newline=patterns.newline -local p_whitespace=patterns.whitespace -if not unicode then - unicode={ utf=utf } -end -if not utf.char then - local floor,char=math.floor,string.char - function utf.char(n) - if n<0x80 then - return char(n) - elseif n<0x800 then - return char( - 0xC0+floor(n/0x40), - 0x80+(n%0x40) - ) - elseif n<0x10000 then - return char( - 0xE0+floor(n/0x1000), - 0x80+(floor(n/0x40)%0x40), - 0x80+(n%0x40) - ) - elseif n<0x200000 then - return char( - 0xF0+floor(n/0x40000), - 0x80+(floor(n/0x1000)%0x40), - 0x80+(floor(n/0x40)%0x40), - 0x80+(n%0x40) - ) - else - return "" - end - end -end -if not utf.byte then - local utf8byte=patterns.utf8byte - function utf.byte(c) - return lpegmatch(utf8byte,c) - end -end -local utfchar,utfbyte=utf.char,utf.byte -function utf.filetype(data) - return data and lpegmatch(p_utftype,data) or "unknown" -end -local toentities=Cs ( - ( - patterns.utf8one+( - patterns.utf8two+patterns.utf8three+patterns.utf8four - )/function(s) local b=utfbyte(s) if b<127 then return s else return format("&#%X;",b) end end - )^0 -) -patterns.toentities=toentities -function utf.toentities(str) - return lpegmatch(toentities,str) -end -local one=P(1) -local two=C(1)*C(1) -local four=C(R(utfchar(0xD8),utfchar(0xFF)))*C(1)*C(1)*C(1) -local pattern=P("\254\255")*Cs(( - four/function(a,b,c,d) - local ab=0xFF*byte(a)+byte(b) - local cd=0xFF*byte(c)+byte(d) - return utfchar((ab-0xD800)*0x400+(cd-0xDC00)+0x10000) - end+two/function(a,b) - return utfchar(byte(a)*256+byte(b)) - end+one - )^1 )+P("\255\254")*Cs(( - four/function(b,a,d,c) - local ab=0xFF*byte(a)+byte(b) - local cd=0xFF*byte(c)+byte(d) - return utfchar((ab-0xD800)*0x400+(cd-0xDC00)+0x10000) - end+two/function(b,a) - return utfchar(byte(a)*256+byte(b)) - end+one - )^1 ) -function string.toutf(s) - return lpegmatch(pattern,s) or s -end -local validatedutf=Cs ( - ( - patterns.utf8one+patterns.utf8two+patterns.utf8three+patterns.utf8four+P(1)/"�" - )^0 -) -patterns.validatedutf=validatedutf -function utf.is_valid(str) - return type(str)=="string" and lpegmatch(validatedutf,str) or false -end -if not utf.len then - local n,f=0,1 - local utfcharcounter=patterns.utfbom^-1*Cmt ( - Cc(1)*patterns.utf8one^1+Cc(2)*patterns.utf8two^1+Cc(3)*patterns.utf8three^1+Cc(4)*patterns.utf8four^1, - function(_,t,d) - n=n+(t-f)/d - f=t - return true - end - )^0 - function utf.len(str) - n,f=0,1 - lpegmatch(utfcharcounter,str or "") - return n - end -end -utf.length=utf.len -if not utf.sub then - local utflength=utf.length - local b,e,n,first,last=0,0,0,0,0 - local function slide_zero(s,p) - n=n+1 - if n>=last then - e=p-1 - else - return p - end - end - local function slide_one(s,p) - n=n+1 - if n==first then - b=p - end - if n>=last then - e=p-1 - else - return p - end - end - local function slide_two(s,p) - n=n+1 - if n==first then - b=p - else - return true - end - end - local pattern_zero=Cmt(p_utf8char,slide_zero)^0 - local pattern_one=Cmt(p_utf8char,slide_one )^0 - local pattern_two=Cmt(p_utf8char,slide_two )^0 - local pattern_first=C(patterns.utf8character) - function utf.sub(str,start,stop) - if not start then - return str - end - if start==0 then - start=1 - end - if not stop then - if start<0 then - local l=utflength(str) - start=l+start - else - start=start-1 - end - b,n,first=0,0,start - lpegmatch(pattern_two,str) - if n>=first then - return sub(str,b) - else - return "" - end - end - if start<0 or stop<0 then - local l=utf.length(str) - if start<0 then - start=l+start - if start<=0 then - start=1 - else - start=start+1 - end - end - if stop<0 then - stop=l+stop - if stop==0 then - stop=1 - else - stop=stop+1 - end - end - end - if start==1 and stop==1 then - return lpegmatch(pattern_first,str) or "" - elseif start>stop then - return "" - elseif start>1 then - b,e,n,first,last=0,0,0,start-1,stop - lpegmatch(pattern_one,str) - if n>=first and e==0 then - e=#str - end - return sub(str,b,e) - else - b,e,n,last=1,0,0,stop - lpegmatch(pattern_zero,str) - if e==0 then - e=#str - end - return sub(str,b,e) - end - end -end -function utf.remapper(mapping,option,action) - local variant=type(mapping) - if variant=="table" then - action=action or mapping - if option=="dynamic" then - local pattern=false - table.setmetatablenewindex(mapping,function(t,k,v) rawset(t,k,v) pattern=false end) - return function(str) - if not str or str=="" then - return "" - else - if not pattern then - pattern=Cs((tabletopattern(mapping)/action+p_utf8char)^0) - end - return lpegmatch(pattern,str) - end - end - elseif option=="pattern" then - return Cs((tabletopattern(mapping)/action+p_utf8char)^0) - else - local pattern=Cs((tabletopattern(mapping)/action+p_utf8char)^0) - return function(str) - if not str or str=="" then - return "" - else - return lpegmatch(pattern,str) - end - end,pattern - end - elseif variant=="function" then - if option=="pattern" then - return Cs((p_utf8char/mapping+p_utf8char)^0) - else - local pattern=Cs((p_utf8char/mapping+p_utf8char)^0) - return function(str) - if not str or str=="" then - return "" - else - return lpegmatch(pattern,str) - end - end,pattern - end - else - return function(str) - return str or "" - end - end -end -function utf.replacer(t) - local r=replacer(t,false,false,true) - return function(str) - return lpegmatch(r,str) - end -end -function utf.subtituter(t) - local f=finder (t) - local r=replacer(t,false,false,true) - return function(str) - local i=lpegmatch(f,str) - if not i then - return str - elseif i>#str then - return str - else - return lpegmatch(r,str) - end - end -end -local utflinesplitter=p_utfbom^-1*lpeg.tsplitat(p_newline) -local utfcharsplitter_ows=p_utfbom^-1*Ct(C(p_utf8char)^0) -local utfcharsplitter_iws=p_utfbom^-1*Ct((p_whitespace^1+C(p_utf8char))^0) -local utfcharsplitter_raw=Ct(C(p_utf8char)^0) -patterns.utflinesplitter=utflinesplitter -function utf.splitlines(str) - return lpegmatch(utflinesplitter,str or "") -end -function utf.split(str,ignorewhitespace) - if ignorewhitespace then - return lpegmatch(utfcharsplitter_iws,str or "") - else - return lpegmatch(utfcharsplitter_ows,str or "") - end -end -function utf.totable(str) - return lpegmatch(utfcharsplitter_raw,str) -end -function utf.magic(f) - local str=f:read(4) or "" - local off=lpegmatch(p_utfoffset,str) - if off<4 then - f:seek('set',off) - end - return lpegmatch(p_utftype,str) -end -local utf16_to_utf8_be,utf16_to_utf8_le -local utf32_to_utf8_be,utf32_to_utf8_le -local utf_16_be_getbom=patterns.utfbom_16_be^-1 -local utf_16_le_getbom=patterns.utfbom_16_le^-1 -local utf_32_be_getbom=patterns.utfbom_32_be^-1 -local utf_32_le_getbom=patterns.utfbom_32_le^-1 -local utf_16_be_linesplitter=utf_16_be_getbom*lpeg.tsplitat(patterns.utf_16_be_nl) -local utf_16_le_linesplitter=utf_16_le_getbom*lpeg.tsplitat(patterns.utf_16_le_nl) -local utf_32_be_linesplitter=utf_32_be_getbom*lpeg.tsplitat(patterns.utf_32_be_nl) -local utf_32_le_linesplitter=utf_32_le_getbom*lpeg.tsplitat(patterns.utf_32_le_nl) -local more=0 -local p_utf16_to_utf8_be=C(1)*C(1)/function(left,right) - local now=256*byte(left)+byte(right) - if more>0 then - now=(more-0xD800)*0x400+(now-0xDC00)+0x10000 - more=0 - return utfchar(now) - elseif now>=0xD800 and now<=0xDBFF then - more=now - return "" - else - return utfchar(now) - end -end -local p_utf16_to_utf8_le=C(1)*C(1)/function(right,left) - local now=256*byte(left)+byte(right) - if more>0 then - now=(more-0xD800)*0x400+(now-0xDC00)+0x10000 - more=0 - return utfchar(now) - elseif now>=0xD800 and now<=0xDBFF then - more=now - return "" - else - return utfchar(now) - end -end -local p_utf32_to_utf8_be=C(1)*C(1)*C(1)*C(1)/function(a,b,c,d) - return utfchar(256*256*256*byte(a)+256*256*byte(b)+256*byte(c)+byte(d)) -end -local p_utf32_to_utf8_le=C(1)*C(1)*C(1)*C(1)/function(a,b,c,d) - return utfchar(256*256*256*byte(d)+256*256*byte(c)+256*byte(b)+byte(a)) -end -p_utf16_to_utf8_be=P(true)/function() more=0 end*utf_16_be_getbom*Cs(p_utf16_to_utf8_be^0) -p_utf16_to_utf8_le=P(true)/function() more=0 end*utf_16_le_getbom*Cs(p_utf16_to_utf8_le^0) -p_utf32_to_utf8_be=P(true)/function() more=0 end*utf_32_be_getbom*Cs(p_utf32_to_utf8_be^0) -p_utf32_to_utf8_le=P(true)/function() more=0 end*utf_32_le_getbom*Cs(p_utf32_to_utf8_le^0) -patterns.utf16_to_utf8_be=p_utf16_to_utf8_be -patterns.utf16_to_utf8_le=p_utf16_to_utf8_le -patterns.utf32_to_utf8_be=p_utf32_to_utf8_be -patterns.utf32_to_utf8_le=p_utf32_to_utf8_le -utf16_to_utf8_be=function(s) - if s and s~="" then - return lpegmatch(p_utf16_to_utf8_be,s) - else - return s - end -end -local utf16_to_utf8_be_t=function(t) - if not t then - return nil - elseif type(t)=="string" then - t=lpegmatch(utf_16_be_linesplitter,t) - end - for i=1,#t do - local s=t[i] - if s~="" then - t[i]=lpegmatch(p_utf16_to_utf8_be,s) - end - end - return t -end -utf16_to_utf8_le=function(s) - if s and s~="" then - return lpegmatch(p_utf16_to_utf8_le,s) - else - return s - end -end -local utf16_to_utf8_le_t=function(t) - if not t then - return nil - elseif type(t)=="string" then - t=lpegmatch(utf_16_le_linesplitter,t) - end - for i=1,#t do - local s=t[i] - if s~="" then - t[i]=lpegmatch(p_utf16_to_utf8_le,s) - end - end - return t -end -utf32_to_utf8_be=function(s) - if s and s~="" then - return lpegmatch(p_utf32_to_utf8_be,s) - else - return s - end -end -local utf32_to_utf8_be_t=function(t) - if not t then - return nil - elseif type(t)=="string" then - t=lpegmatch(utf_32_be_linesplitter,t) - end - for i=1,#t do - local s=t[i] - if s~="" then - t[i]=lpegmatch(p_utf32_to_utf8_be,s) - end - end - return t -end -utf32_to_utf8_le=function(s) - if s and s~="" then - return lpegmatch(p_utf32_to_utf8_le,s) - else - return s - end -end -local utf32_to_utf8_le_t=function(t) - if not t then - return nil - elseif type(t)=="string" then - t=lpegmatch(utf_32_le_linesplitter,t) - end - for i=1,#t do - local s=t[i] - if s~="" then - t[i]=lpegmatch(p_utf32_to_utf8_le,s) - end - end - return t -end -utf.utf16_to_utf8_le_t=utf16_to_utf8_le_t -utf.utf16_to_utf8_be_t=utf16_to_utf8_be_t -utf.utf32_to_utf8_le_t=utf32_to_utf8_le_t -utf.utf32_to_utf8_be_t=utf32_to_utf8_be_t -utf.utf16_to_utf8_le=utf16_to_utf8_le -utf.utf16_to_utf8_be=utf16_to_utf8_be -utf.utf32_to_utf8_le=utf32_to_utf8_le -utf.utf32_to_utf8_be=utf32_to_utf8_be -function utf.utf8_to_utf8_t(t) - return type(t)=="string" and lpegmatch(utflinesplitter,t) or t -end -function utf.utf16_to_utf8_t(t,endian) - return endian and utf16_to_utf8_be_t(t) or utf16_to_utf8_le_t(t) or t -end -function utf.utf32_to_utf8_t(t,endian) - return endian and utf32_to_utf8_be_t(t) or utf32_to_utf8_le_t(t) or t -end -local function little(b) - if b<0x10000 then - return char(b%256,b/256) - else - b=b-0x10000 - local b1,b2=b/1024+0xD800,b%1024+0xDC00 - return char(b1%256,b1/256,b2%256,b2/256) - end -end -local function big(b) - if b<0x10000 then - return char(b/256,b%256) - else - b=b-0x10000 - local b1,b2=b/1024+0xD800,b%1024+0xDC00 - return char(b1/256,b1%256,b2/256,b2%256) - end -end -local l_remap=Cs((p_utf8byte/little+P(1)/"")^0) -local b_remap=Cs((p_utf8byte/big+P(1)/"")^0) -local function utf8_to_utf16_be(str,nobom) - if nobom then - return lpegmatch(b_remap,str) - else - return char(254,255)..lpegmatch(b_remap,str) - end -end -local function utf8_to_utf16_le(str,nobom) - if nobom then - return lpegmatch(l_remap,str) - else - return char(255,254)..lpegmatch(l_remap,str) - end -end -utf.utf8_to_utf16_be=utf8_to_utf16_be -utf.utf8_to_utf16_le=utf8_to_utf16_le -function utf.utf8_to_utf16(str,littleendian,nobom) - if littleendian then - return utf8_to_utf16_le(str,nobom) - else - return utf8_to_utf16_be(str,nobom) - end -end -local pattern=Cs ( - (p_utf8byte/function(unicode ) return format("0x%04X",unicode) end)*(p_utf8byte*Carg(1)/function(unicode,separator) return format("%s0x%04X",separator,unicode) end)^0 -) -function utf.tocodes(str,separator) - return lpegmatch(pattern,str,1,separator or " ") -end -function utf.ustring(s) - return format("U+%05X",type(s)=="number" and s or utfbyte(s)) -end -function utf.xstring(s) - return format("0x%05X",type(s)=="number" and s or utfbyte(s)) -end -function utf.toeight(str) - if not str or str=="" then - return nil - end - local utftype=lpegmatch(p_utfstricttype,str) - if utftype=="utf-8" then - return sub(str,4) - elseif utftype=="utf-16-be" then - return utf16_to_utf8_be(str) - elseif utftype=="utf-16-le" then - return utf16_to_utf8_le(str) - else - return str - end -end -local p_nany=p_utf8char/"" -if utfgmatch then - function utf.count(str,what) - if type(what)=="string" then - local n=0 - for _ in utfgmatch(str,what) do - n=n+1 - end - return n - else - return #lpegmatch(Cs((P(what)/" "+p_nany)^0),str) - end - end -else - local cache={} - function utf.count(str,what) - if type(what)=="string" then - local p=cache[what] - if not p then - p=Cs((P(what)/" "+p_nany)^0) - cache[p]=p - end - return #lpegmatch(p,str) - else - return #lpegmatch(Cs((P(what)/" "+p_nany)^0),str) - end - end -end -if not utf.characters then - function utf.characters(str) - return gmatch(str,".[\128-\191]*") - end - string.utfcharacters=utf.characters -end -if not utf.values then - local find=string.find - local dummy=function() - end - function utf.values(str) - local n=#str - if n==0 then - return dummy - elseif n==1 then - return function() return utfbyte(str) end - else - local p=1 - return function() - local b,e=find(str,".[\128-\191]*",p) - if b then - p=e+1 - return utfbyte(sub(str,b,e)) - end - end - end - end - string.utfvalues=utf.values -end -function utf.chrlen(u) - return - (u<0x80 and 1) or - (u<0xE0 and 2) or - (u<0xF0 and 3) or - (u<0xF8 and 4) or - (u<0xFC and 5) or - (u<0xFE and 6) or 0 -end - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['l-url']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local char,format,byte=string.char,string.format,string.byte -local concat=table.concat -local tonumber,type=tonumber,type -local P,C,R,S,Cs,Cc,Ct,Cf,Cg,V=lpeg.P,lpeg.C,lpeg.R,lpeg.S,lpeg.Cs,lpeg.Cc,lpeg.Ct,lpeg.Cf,lpeg.Cg,lpeg.V -local lpegmatch,lpegpatterns,replacer=lpeg.match,lpeg.patterns,lpeg.replacer -url=url or {} -local url=url -local tochar=function(s) return char(tonumber(s,16)) end -local colon=P(":") -local qmark=P("?") -local hash=P("#") -local slash=P("/") -local percent=P("%") -local endofstring=P(-1) -local hexdigit=R("09","AF","af") -local plus=P("+") -local nothing=Cc("") -local escapedchar=(percent*C(hexdigit*hexdigit))/tochar -local escaped=(plus/" ")+escapedchar -local noslash=P("/")/"" -local schemestr=Cs((escaped+(1-colon-slash-qmark-hash))^2) -local authoritystr=Cs((escaped+(1- slash-qmark-hash))^0) -local pathstr=Cs((escaped+(1- qmark-hash))^0) -local querystr=Cs(((1- hash))^0) -local fragmentstr=Cs((escaped+(1- endofstring))^0) -local scheme=schemestr*colon+nothing -local authority=slash*slash*authoritystr+nothing -local path=slash*pathstr+nothing -local query=qmark*querystr+nothing -local fragment=hash*fragmentstr+nothing -local validurl=scheme*authority*path*query*fragment -local parser=Ct(validurl) -lpegpatterns.url=validurl -lpegpatterns.urlsplitter=parser -local escapes={} -setmetatable(escapes,{ __index=function(t,k) - local v=format("%%%02X",byte(k)) - t[k]=v - return v -end }) -local escaper=Cs((R("09","AZ","az")^1+P(" ")/"%%20"+S("-./_")^1+P(1)/escapes)^0) -local unescaper=Cs((escapedchar+1)^0) -local getcleaner=Cs((P("+++")/"%%2B"+P("+")/"%%20"+P(1))^1) -lpegpatterns.urlunescaped=escapedchar -lpegpatterns.urlescaper=escaper -lpegpatterns.urlunescaper=unescaper -lpegpatterns.urlgetcleaner=getcleaner -function url.unescapeget(str) - return lpegmatch(getcleaner,str) -end -local function split(str) - return (type(str)=="string" and lpegmatch(parser,str)) or str -end -local isscheme=schemestr*colon*slash*slash -local function hasscheme(str) - if str then - local scheme=lpegmatch(isscheme,str) - return scheme~="" and scheme or false - else - return false - end -end -local rootletter=R("az","AZ")+S("_-+") -local separator=P("://") -local qualified=P(".")^0*P("/")+rootletter*P(":")+rootletter^1*separator+rootletter^1*P("/") -local rootbased=P("/")+rootletter*P(":") -local barswapper=replacer("|",":") -local backslashswapper=replacer("\\","/") -local equal=P("=") -local amp=P("&") -local key=Cs(((escapedchar+1)-equal )^0) -local value=Cs(((escapedchar+1)-amp -endofstring)^0) -local splitquery=Cf (Ct("")*P { "sequence", - sequence=V("pair")*(amp*V("pair"))^0, - pair=Cg(key*equal*value), -},rawset) -local function hashed(str) - if not str or str=="" then - return { - scheme="invalid", - original=str, - } - end - local detailed=split(str) - local rawscheme="" - local rawquery="" - local somescheme=false - local somequery=false - if detailed then - rawscheme=detailed[1] - rawquery=detailed[4] - somescheme=rawscheme~="" - somequery=rawquery~="" - end - if not somescheme and not somequery then - return { - scheme="file", - authority="", - path=str, - query="", - fragment="", - original=str, - noscheme=true, - filename=str, - } - end - local authority=detailed[2] - local path=detailed[3] - local filename=nil - if authority=="" then - filename=path - elseif path=="" then - filename="" - else - filename=authority.."/"..path - end - return { - scheme=rawscheme, - authority=authority, - path=path, - query=lpegmatch(unescaper,rawquery), - queries=lpegmatch(splitquery,rawquery), - fragment=detailed[5], - original=str, - noscheme=false, - filename=filename, - } -end -url.split=split -url.hasscheme=hasscheme -url.hashed=hashed -function url.addscheme(str,scheme) - if hasscheme(str) then - return str - elseif not scheme then - return "file:///"..str - else - return scheme..":///"..str - end -end -function url.construct(hash) - local fullurl,f={},0 - local scheme,authority,path,query,fragment=hash.scheme,hash.authority,hash.path,hash.query,hash.fragment - if scheme and scheme~="" then - f=f+1;fullurl[f]=scheme.."://" - end - if authority and authority~="" then - f=f+1;fullurl[f]=authority - end - if path and path~="" then - f=f+1;fullurl[f]="/"..path - end - if query and query~="" then - f=f+1;fullurl[f]="?"..query - end - if fragment and fragment~="" then - f=f+1;fullurl[f]="#"..fragment - end - return lpegmatch(escaper,concat(fullurl)) -end -local pattern=Cs(slash^-1/""*R("az","AZ")*((S(":|")/":")+P(":"))*slash*P(1)^0) -function url.filename(filename) - local spec=hashed(filename) - local path=spec.path - return (spec.scheme=="file" and path and lpegmatch(pattern,path)) or filename -end -local function escapestring(str) - return lpegmatch(escaper,str) -end -url.escape=escapestring -function url.query(str) - if type(str)=="string" then - return lpegmatch(splitquery,str) or "" - else - return str - end -end -function url.toquery(data) - local td=type(data) - if td=="string" then - return #str and escape(data) or nil - elseif td=="table" then - if next(data) then - local t={} - for k,v in next,data do - t[#t+1]=format("%s=%s",k,escapestring(v)) - end - return concat(t,"&") - end - else - end -end -local pattern=Cs(noslash^0*(1-noslash*P(-1))^0) -function url.barepath(path) - if not path or path=="" then - return "" - else - return lpegmatch(pattern,path) - end -end - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['l-set']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -set=set or {} -local nums={} -local tabs={} -local concat=table.concat -local next,type=next,type -set.create=table.tohash -function set.tonumber(t) - if next(t) then - local s="" - for k,v in next,t do - if v then - s=s.." "..k - end - end - local n=nums[s] - if not n then - n=#tabs+1 - tabs[n]=t - nums[s]=n - end - return n - else - return 0 - end -end -function set.totable(n) - if n==0 then - return {} - else - return tabs[n] or {} - end -end -function set.tolist(n) - if n==0 or not tabs[n] then - return "" - else - local t,n={},0 - for k,v in next,tabs[n] do - if v then - n=n+1 - t[n]=k - end - end - return concat(t," ") - end -end -function set.contains(n,s) - if type(n)=="table" then - return n[s] - elseif n==0 then - return false - else - local t=tabs[n] - return t and t[s] - end -end - -end -- closure diff --git a/tex/compat/lualibs/lualibs-basic.lua b/tex/compat/lualibs/lualibs-basic.lua deleted file mode 100644 index 1cd0c280c6e12decee5fb47c4a5cf3120654291c..0000000000000000000000000000000000000000 --- a/tex/compat/lualibs/lualibs-basic.lua +++ /dev/null @@ -1,78 +0,0 @@ --- --- This is file `lualibs-basic.lua', --- generated with the docstrip utility. --- --- The original source files were: --- --- lualibs.dtx (with options: `basic') --- This is a generated file. --- --- Copyright (C) 2009--2016 by --- PRAGMA ADE / ConTeXt Development Team --- The LuaLaTeX Dev Team --- --- See ConTeXt's mreadme.pdf for the license. --- --- This work consists of the main source file lualibs.dtx --- and the derived files lualibs.lua, lualibs-basic.lua, --- and lualibs-extended.lua. --- --- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -lualibs = lualibs or { } -local info = lualibs.info -local loadmodule = lualibs.loadmodule - -local lualibs_basic_module = { - name = "lualibs-basic", - version = 2.4, - date = "2016-04-06", - description = "ConTeXt Lua libraries -- basic collection.", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL & Elie Roux & Philipp Gesang", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "See ConTeXt's mreadme.pdf for the license", -} - -local loaded = false --- track success of package loading - -if lualibs.prefer_merged then - info"Loading merged package for collection “basic”." - loaded = loadmodule('lualibs-basic-merged.lua') -else - info"Ignoring merged packages." - info"Falling back to individual libraries from collection “basic”." -end - - -if loaded == false then - loadmodule("lualibs-lua.lua") - loadmodule("lualibs-package.lua") - loadmodule("lualibs-lpeg.lua") - loadmodule("lualibs-function.lua") - loadmodule("lualibs-string.lua") - loadmodule("lualibs-table.lua") - loadmodule("lualibs-boolean.lua") - loadmodule("lualibs-number.lua") - loadmodule("lualibs-math.lua") - loadmodule("lualibs-io.lua") - loadmodule("lualibs-os.lua") - loadmodule("lualibs-file.lua") - loadmodule("lualibs-gzip.lua") - loadmodule("lualibs-md5.lua") - loadmodule("lualibs-dir.lua") - loadmodule("lualibs-unicode.lua") - loadmodule("lualibs-url.lua") - loadmodule("lualibs-set.lua") -end - -lualibs.basic_loaded = true --- vim:tw=71:sw=2:ts=2:expandtab - --- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --- --- End of File `lualibs-basic.lua'. diff --git a/tex/compat/lualibs/lualibs-boolean.lua b/tex/compat/lualibs/lualibs-boolean.lua deleted file mode 100644 index 8f18d4c003df76648cb8870d8d46127c3edd942c..0000000000000000000000000000000000000000 --- a/tex/compat/lualibs/lualibs-boolean.lua +++ /dev/null @@ -1,69 +0,0 @@ -if not modules then modules = { } end modules ['l-boolean'] = { - version = 1.001, - comment = "companion to luat-lib.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -local type, tonumber = type, tonumber - -boolean = boolean or { } -local boolean = boolean - -function boolean.tonumber(b) - if b then return 1 else return 0 end -- test and return or return -end - -function toboolean(str,tolerant) -- global - if str == nil then - return false - elseif str == false then - return false - elseif str == true then - return true - elseif str == "true" then - return true - elseif str == "false" then - return false - elseif not tolerant then - return false - elseif str == 0 then - return false - elseif (tonumber(str) or 0) > 0 then - return true - else - return str == "yes" or str == "on" or str == "t" - end -end - -string.toboolean = toboolean - -function string.booleanstring(str) - if str == "0" then - return false - elseif str == "1" then - return true - elseif str == "" then - return false - elseif str == "false" then - return false - elseif str == "true" then - return true - elseif (tonumber(str) or 0) > 0 then - return true - else - return str == "yes" or str == "on" or str == "t" - end -end - -function string.is_boolean(str,default,strict) - if type(str) == "string" then - if str == "true" or str == "yes" or str == "on" or str == "t" or (not strict and str == "1") then - return true - elseif str == "false" or str == "no" or str == "off" or str == "f" or (not strict and str == "0") then - return false - end - end - return default -end diff --git a/tex/compat/lualibs/lualibs-compat.lua b/tex/compat/lualibs/lualibs-compat.lua deleted file mode 100644 index 707f26b8b66f165a9ab0a0b3fefdbf5eb9e21db4..0000000000000000000000000000000000000000 --- a/tex/compat/lualibs/lualibs-compat.lua +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env texlua - -lualibs = lualibs or { } - -local stringgsub = string.gsub -local stringlower = string.lower -local next = next -local Ct, splitat = lpeg.Ct, lpeg.splitat - ---[[doc -Needed by legacy luat-dum.lua. ---doc]]-- -table.reverse_hash = function (h) - local r = { } - for k,v in next, h do - r[v] = stringlower(stringgsub(k," ","")) - end - return r -end - ---[[doc -Needed by legacy font-otn.lua. ---doc]]-- -lpeg.splitters = { [" "] = Ct(splitat" ") } - ---[[doc -Needed by legacy font-nms.lua. ---doc]]-- - -file.split_path = file.splitpath -file.collapse_path = file.collapsepath diff --git a/tex/compat/lualibs/lualibs-dir.lua b/tex/compat/lualibs/lualibs-dir.lua deleted file mode 100644 index 81ac65e506d7182da2814f64a1837cbf456b337b..0000000000000000000000000000000000000000 --- a/tex/compat/lualibs/lualibs-dir.lua +++ /dev/null @@ -1,593 +0,0 @@ -if not modules then modules = { } end modules ['l-dir'] = { - version = 1.001, - comment = "companion to luat-lib.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- todo: dir.expandname will be sped up and merged with cleanpath and collapsepath --- todo: keep track of currentdir (chdir, pushdir, popdir) - -local type, select = type, select -local find, gmatch, match, gsub, sub = string.find, string.gmatch, string.match, string.gsub, string.sub -local concat, insert, remove, unpack = table.concat, table.insert, table.remove, table.unpack -local lpegmatch = lpeg.match - -local P, S, R, C, Cc, Cs, Ct, Cv, V = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.Cc, lpeg.Cs, lpeg.Ct, lpeg.Cv, lpeg.V - -dir = dir or { } -local dir = dir -local lfs = lfs - -local attributes = lfs.attributes -local walkdir = lfs.dir -local isdir = lfs.isdir -- not robust, will be overloaded anyway -local isfile = lfs.isfile -- not robust, will be overloaded anyway -local currentdir = lfs.currentdir -local chdir = lfs.chdir -local mkdir = lfs.mkdir - -local onwindows = os.type == "windows" or find(os.getenv("PATH"),";",1,true) - --- in case we load outside luatex - -if onwindows then - - -- lfs.isdir does not like trailing / - -- lfs.dir accepts trailing / - - local tricky = S("/\\") * P(-1) - - isdir = function(name) - if lpegmatch(tricky,name) then - return attributes(name,"mode") == "directory" - else - return attributes(name.."/.","mode") == "directory" - end - end - - isfile = function(name) - return attributes(name,"mode") == "file" - end - - lfs.isdir = isdir - lfs.isfile = isfile - -else - - isdir = function(name) - return attributes(name,"mode") == "directory" - end - - isfile = function(name) - return attributes(name,"mode") == "file" - end - - lfs.isdir = isdir - lfs.isfile = isfile - -end - --- handy - -function dir.current() - return (gsub(currentdir(),"\\","/")) -end - --- somewhat optimized - -local function glob_pattern_function(path,patt,recurse,action) - if isdir(path) then - local usedpath - if path == "/" then - usedpath = "/." - elseif not find(path,"/$") then - usedpath = path .. "/." - path = path .. "/" - else - usedpath = path - end - local dirs - for name in walkdir(usedpath) do - if name ~= "." and name ~= ".." then - local full = path .. name - local mode = attributes(full,'mode') - if mode == 'file' then - if not patt or find(full,patt) then - action(full) - end - elseif recurse and mode == "directory" then - if not dirs then - dirs = { full } - else - dirs[#dirs+1] = full - end - end - end - end - if dirs then - for i=1,#dirs do - glob_pattern_function(dirs[i],patt,recurse,action) - end - end - end -end - -local function glob_pattern_table(path,patt,recurse,result) - if not result then - result = { } - end - if isdir(path) then - local usedpath - if path == "/" then - usedpath = "/." - elseif not find(path,"/$") then - usedpath = path .. "/." - path = path .. "/" - else - usedpath = path - end - local dirs - for name in walkdir(usedpath) do - if name ~= "." and name ~= ".." then - local full = path .. name - local mode = attributes(full,'mode') - if mode == 'file' then - if not patt or find(full,patt) then - result[#result+1] = full - end - elseif recurse and mode == "directory" then - if not dirs then - dirs = { full } - else - dirs[#dirs+1] = full - end - end - end - end - if dirs then - for i=1,#dirs do - glob_pattern_table(dirs[i],patt,recurse,result) - end - end - end - return result -end - -local function globpattern(path,patt,recurse,method) - local kind = type(method) - if patt and sub(patt,1,-3) == path then - patt = false - end - if kind == "function" then - return glob_pattern_function(path,patt,recurse,method) - elseif kind == "table" then - return glob_pattern_table(path,patt,recurse,method) - else - return glob_pattern_table(path,patt,recurse,{ }) - end -end - -dir.globpattern = globpattern - --- never or seldom used so far: - -local function collectpattern(path,patt,recurse,result) - local ok, scanner - result = result or { } - if path == "/" then - ok, scanner, first = xpcall(function() return walkdir(path..".") end, function() end) -- kepler safe - else - ok, scanner, first = xpcall(function() return walkdir(path) end, function() end) -- kepler safe - end - if ok and type(scanner) == "function" then - if not find(path,"/$") then - path = path .. '/' - end - for name in scanner, first do - if name == "." then - -- skip - elseif name == ".." then - -- skip - else - local full = path .. name - local attr = attributes(full) - local mode = attr.mode - if mode == 'file' then - if find(full,patt) then - result[name] = attr - end - elseif recurse and mode == "directory" then - attr.list = collectpattern(full,patt,recurse) - result[name] = attr - end - end - end - end - return result -end - -dir.collectpattern = collectpattern - -local separator, pattern - -if onwindows then -- we could sanitize here - - local slash = S("/\\") / "/" - --- pattern = Ct { - pattern = { - [1] = (Cs(P(".") + slash^1) + Cs(R("az","AZ") * P(":") * slash^0) + Cc("./")) * V(2) * V(3), - [2] = Cs(((1-S("*?/\\"))^0 * slash)^0), - [3] = Cs(P(1)^0) - } - -else -- assume unix - --- pattern = Ct { - pattern = { - [1] = (C(P(".") + P("/")^1) + Cc("./")) * V(2) * V(3), - [2] = C(((1-S("*?/"))^0 * P("/"))^0), - [3] = C(P(1)^0) - } - -end - -local filter = Cs ( ( - P("**") / ".*" + - P("*") / "[^/]*" + - P("?") / "[^/]" + - P(".") / "%%." + - P("+") / "%%+" + - P("-") / "%%-" + - P(1) -)^0 ) - -local function glob(str,t) - if type(t) == "function" then - if type(str) == "table" then - for s=1,#str do - glob(str[s],t) - end - elseif isfile(str) then - t(str) - else - local root, path, base = lpegmatch(pattern,str) -- we could use the file splitter - if root and path and base then - local recurse = find(base,"**",1,true) -- find(base,"%*%*") - local start = root .. path - local result = lpegmatch(filter,start .. base) - globpattern(start,result,recurse,t) - end - end - else - if type(str) == "table" then - local t = t or { } - for s=1,#str do - glob(str[s],t) - end - return t - elseif isfile(str) then - if t then - t[#t+1] = str - return t - else - return { str } - end - else - local root, path, base = lpegmatch(pattern,str) -- we could use the file splitter - if root and path and base then - local recurse = find(base,"**",1,true) -- find(base,"%*%*") - local start = root .. path - local result = lpegmatch(filter,start .. base) - return globpattern(start,result,recurse,t) - else - return { } - end - end - end -end - -dir.glob = glob - --- local c = os.clock() --- local t = dir.glob("e:/**") --- local t = dir.glob("t:/sources/**") --- local t = dir.glob("t:/**") --- print(os.clock()-c,#t) - --- for i=1,3000 do print(t[i]) end --- for i=1,10 do print(t[i]) end - --- list = dir.glob("**/*.tif") --- list = dir.glob("/**/*.tif") --- list = dir.glob("./**/*.tif") --- list = dir.glob("oeps/**/*.tif") --- list = dir.glob("/oeps/**/*.tif") - -local function globfiles(path,recurse,func,files) -- func == pattern or function - if type(func) == "string" then - local s = func - func = function(name) return find(name,s) end - end - files = files or { } - local noffiles = #files - for name in walkdir(path) do - if find(name,"^%.") then - --- skip - else - local mode = attributes(name,'mode') - if mode == "directory" then - if recurse then - globfiles(path .. "/" .. name,recurse,func,files) - end - elseif mode == "file" then - if not func or func(name) then - noffiles = noffiles + 1 - files[noffiles] = path .. "/" .. name - end - end - end - end - return files -end - -dir.globfiles = globfiles - --- t = dir.glob("c:/data/develop/context/sources/**/????-*.tex") --- t = dir.glob("c:/data/develop/tex/texmf/**/*.tex") --- t = dir.glob("c:/data/develop/context/texmf/**/*.tex") --- t = dir.glob("f:/minimal/tex/**/*") --- print(dir.ls("f:/minimal/tex/**/*")) --- print(dir.ls("*.tex")) - -function dir.ls(pattern) - return concat(glob(pattern),"\n") -end - --- mkdirs("temp") --- mkdirs("a/b/c") --- mkdirs(".","/a/b/c") --- mkdirs("a","b","c") - -local make_indeed = true -- false - -if onwindows then - - function dir.mkdirs(...) - local n = select("#",...) - local str - if n == 1 then - str = select(1,...) - if isdir(str) then - return str, true - end - else - str = "" - for i=1,n do - local s = select(i,...) - if s == "" then - -- skip - elseif str == "" then - str = s - else - str = str .. "/" .. s - end - end - end - local pth = "" - local drive = false - local first, middle, last = match(str,"^(//)(//*)(.*)$") - if first then - -- empty network path == local path - else - first, last = match(str,"^(//)/*(.-)$") - if first then - middle, last = match(str,"([^/]+)/+(.-)$") - if middle then - pth = "//" .. middle - else - pth = "//" .. last - last = "" - end - else - first, middle, last = match(str,"^([a-zA-Z]:)(/*)(.-)$") - if first then - pth, drive = first .. middle, true - else - middle, last = match(str,"^(/*)(.-)$") - if not middle then - last = str - end - end - end - end - for s in gmatch(last,"[^/]+") do - if pth == "" then - pth = s - elseif drive then - pth, drive = pth .. s, false - else - pth = pth .. "/" .. s - end - if make_indeed and not isdir(pth) then - mkdir(pth) - end - end - return pth, (isdir(pth) == true) - end - - -- print(dir.mkdirs("","","a","c")) - -- print(dir.mkdirs("a")) - -- print(dir.mkdirs("a:")) - -- print(dir.mkdirs("a:/b/c")) - -- print(dir.mkdirs("a:b/c")) - -- print(dir.mkdirs("a:/bbb/c")) - -- print(dir.mkdirs("/a/b/c")) - -- print(dir.mkdirs("/aaa/b/c")) - -- print(dir.mkdirs("//a/b/c")) - -- print(dir.mkdirs("///a/b/c")) - -- print(dir.mkdirs("a/bbb//ccc/")) - -else - - function dir.mkdirs(...) - local n = select("#",...) - local str, pth - if n == 1 then - str = select(1,...) - if isdir(str) then - return str, true - end - else - str = "" - for i=1,n do - local s = select(i,...) - if s and s ~= "" then -- we catch nil and false - if str ~= "" then - str = str .. "/" .. s - else - str = s - end - end - end - end - str = gsub(str,"/+","/") - if find(str,"^/") then - pth = "/" - for s in gmatch(str,"[^/]+") do - local first = (pth == "/") - if first then - pth = pth .. s - else - pth = pth .. "/" .. s - end - if make_indeed and not first and not isdir(pth) then - mkdir(pth) - end - end - else - pth = "." - for s in gmatch(str,"[^/]+") do - pth = pth .. "/" .. s - if make_indeed and not isdir(pth) then - mkdir(pth) - end - end - end - return pth, (isdir(pth) == true) - end - - -- print(dir.mkdirs("","","a","c")) - -- print(dir.mkdirs("a")) - -- print(dir.mkdirs("/a/b/c")) - -- print(dir.mkdirs("/aaa/b/c")) - -- print(dir.mkdirs("//a/b/c")) - -- print(dir.mkdirs("///a/b/c")) - -- print(dir.mkdirs("a/bbb//ccc/")) - -end - -dir.makedirs = dir.mkdirs - - -do - - -- we can only define it here as it uses dir.chdir and we also need to - -- make sure we use the non sandboxed variant because otherwise we get - -- into a recursive loop due to usage of expandname in the file resolver - - local chdir = sandbox and sandbox.original(chdir) or chdir - - if onwindows then - - local xcurrentdir = dir.current - - function dir.expandname(str) -- will be merged with cleanpath and collapsepath\ - local first, nothing, last = match(str,"^(//)(//*)(.*)$") - if first then - first = xcurrentdir() .. "/" -- xcurrentdir sanitizes - end - if not first then - first, last = match(str,"^(//)/*(.*)$") - end - if not first then - first, last = match(str,"^([a-zA-Z]:)(.*)$") - if first and not find(last,"^/") then - local d = currentdir() -- push / pop - if chdir(first) then - first = xcurrentdir() -- xcurrentdir sanitizes - end - chdir(d) - end - end - if not first then - first, last = xcurrentdir(), str - end - last = gsub(last,"//","/") - last = gsub(last,"/%./","/") - last = gsub(last,"^/*","") - first = gsub(first,"/*$","") - if last == "" or last == "." then - return first - else - return first .. "/" .. last - end - end - - else - - function dir.expandname(str) -- will be merged with cleanpath and collapsepath - if not find(str,"^/") then - str = currentdir() .. "/" .. str - end - str = gsub(str,"//","/") - str = gsub(str,"/%./","/") - str = gsub(str,"(.)/%.$","%1") - return str - end - - end - -end - -file.expandname = dir.expandname -- for convenience - -local stack = { } - -function dir.push(newdir) - insert(stack,currentdir()) - if newdir and newdir ~= "" then - chdir(newdir) - end -end - -function dir.pop() - local d = remove(stack) - if d then - chdir(d) - end - return d -end - -local function found(...) -- can have nil entries - for i=1,select("#",...) do - local path = select(i,...) - local kind = type(path) - if kind == "string" then - if isdir(path) then - return path - end - elseif kind == "table" then - -- here we asume no holes, i.e. an indexed table - local path = found(unpack(path)) - if path then - return path - end - end - end - -- return nil -- if we want print("crappath") to show something -end - -dir.found = found diff --git a/tex/compat/lualibs/lualibs-extended-merged.lua b/tex/compat/lualibs/lualibs-extended-merged.lua deleted file mode 100644 index db833a05eb0cb0bd28364c4292d9882739f39b0a..0000000000000000000000000000000000000000 --- a/tex/compat/lualibs/lualibs-extended-merged.lua +++ /dev/null @@ -1,3233 +0,0 @@ --- merged file : lualibs-extended-merged.lua --- parent file : lualibs-extended.lua --- merge date : Wed Apr 6 23:53:30 2016 - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['util-str']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -utilities=utilities or {} -utilities.strings=utilities.strings or {} -local strings=utilities.strings -local format,gsub,rep,sub=string.format,string.gsub,string.rep,string.sub -local load,dump=load,string.dump -local tonumber,type,tostring=tonumber,type,tostring -local unpack,concat=table.unpack,table.concat -local P,V,C,S,R,Ct,Cs,Cp,Carg,Cc=lpeg.P,lpeg.V,lpeg.C,lpeg.S,lpeg.R,lpeg.Ct,lpeg.Cs,lpeg.Cp,lpeg.Carg,lpeg.Cc -local patterns,lpegmatch=lpeg.patterns,lpeg.match -local utfchar,utfbyte=utf.char,utf.byte -local loadstripped=nil -if _LUAVERSION<5.2 then - loadstripped=function(str,shortcuts) - return load(str) - end -else - loadstripped=function(str,shortcuts) - if shortcuts then - return load(dump(load(str),true),nil,nil,shortcuts) - else - return load(dump(load(str),true)) - end - end -end -if not number then number={} end -local stripper=patterns.stripzeros -local newline=patterns.newline -local endofstring=patterns.endofstring -local whitespace=patterns.whitespace -local spacer=patterns.spacer -local spaceortab=patterns.spaceortab -local function points(n) - n=tonumber(n) - return (not n or n==0) and "0pt" or lpegmatch(stripper,format("%.5fpt",n/65536)) -end -local function basepoints(n) - n=tonumber(n) - return (not n or n==0) and "0bp" or lpegmatch(stripper,format("%.5fbp",n*(7200/7227)/65536)) -end -number.points=points -number.basepoints=basepoints -local rubish=spaceortab^0*newline -local anyrubish=spaceortab+newline -local anything=patterns.anything -local stripped=(spaceortab^1/"")*newline -local leading=rubish^0/"" -local trailing=(anyrubish^1*endofstring)/"" -local redundant=rubish^3/"\n" -local pattern=Cs(leading*(trailing+redundant+stripped+anything)^0) -function strings.collapsecrlf(str) - return lpegmatch(pattern,str) -end -local repeaters={} -function strings.newrepeater(str,offset) - offset=offset or 0 - local s=repeaters[str] - if not s then - s={} - repeaters[str]=s - end - local t=s[offset] - if t then - return t - end - t={} - setmetatable(t,{ __index=function(t,k) - if not k then - return "" - end - local n=k+offset - local s=n>0 and rep(str,n) or "" - t[k]=s - return s - end }) - s[offset]=t - return t -end -local extra,tab,start=0,0,4,0 -local nspaces=strings.newrepeater(" ") -string.nspaces=nspaces -local pattern=Carg(1)/function(t) - extra,tab,start=0,t or 7,1 - end*Cs(( - Cp()*patterns.tab/function(position) - local current=(position-start+1)+extra - local spaces=tab-(current-1)%tab - if spaces>0 then - extra=extra+spaces-1 - return nspaces[spaces] - else - return "" - end - end+newline*Cp()/function(position) - extra,start=0,position - end+patterns.anything - )^1) -function strings.tabtospace(str,tab) - return lpegmatch(pattern,str,1,tab or 7) -end -local space=spacer^0 -local nospace=space/"" -local endofline=nospace*newline -local stripend=(whitespace^1*endofstring)/"" -local normalline=(nospace*((1-space*(newline+endofstring))^1)*nospace) -local stripempty=endofline^1/"" -local normalempty=endofline^1 -local singleempty=endofline*(endofline^0/"") -local doubleempty=endofline*endofline^-1*(endofline^0/"") -local stripstart=stripempty^0 -local p_prune_normal=Cs (stripstart*(stripend+normalline+normalempty )^0 ) -local p_prune_collapse=Cs (stripstart*(stripend+normalline+doubleempty )^0 ) -local p_prune_noempty=Cs (stripstart*(stripend+normalline+singleempty )^0 ) -local p_retain_normal=Cs ((normalline+normalempty )^0 ) -local p_retain_collapse=Cs ((normalline+doubleempty )^0 ) -local p_retain_noempty=Cs ((normalline+singleempty )^0 ) -local striplinepatterns={ - ["prune"]=p_prune_normal, - ["prune and collapse"]=p_prune_collapse, - ["prune and no empty"]=p_prune_noempty, - ["retain"]=p_retain_normal, - ["retain and collapse"]=p_retain_collapse, - ["retain and no empty"]=p_retain_noempty, - ["collapse"]=patterns.collapser, -} -setmetatable(striplinepatterns,{ __index=function(t,k) return p_prune_collapse end }) -strings.striplinepatterns=striplinepatterns -function strings.striplines(str,how) - return str and lpegmatch(striplinepatterns[how],str) or str -end -strings.striplong=strings.striplines -function strings.nice(str) - str=gsub(str,"[:%-+_]+"," ") - return str -end -local n=0 -local sequenced=table.sequenced -function string.autodouble(s,sep) - if s==nil then - return '""' - end - local t=type(s) - if t=="number" then - return tostring(s) - end - if t=="table" then - return ('"'..sequenced(s,sep or ",")..'"') - end - return ('"'..tostring(s)..'"') -end -function string.autosingle(s,sep) - if s==nil then - return "''" - end - local t=type(s) - if t=="number" then - return tostring(s) - end - if t=="table" then - return ("'"..sequenced(s,sep or ",").."'") - end - return ("'"..tostring(s).."'") -end -local tracedchars={ [0]= - "[null]","[soh]","[stx]","[etx]","[eot]","[enq]","[ack]","[bel]", - "[bs]","[ht]","[lf]","[vt]","[ff]","[cr]","[so]","[si]", - "[dle]","[dc1]","[dc2]","[dc3]","[dc4]","[nak]","[syn]","[etb]", - "[can]","[em]","[sub]","[esc]","[fs]","[gs]","[rs]","[us]", - "[space]", -} -string.tracedchars=tracedchars -strings.tracers=tracedchars -function string.tracedchar(b) - if type(b)=="number" then - return tracedchars[b] or (utfchar(b).." (U+"..format("%05X",b)..")") - else - local c=utfbyte(b) - return tracedchars[c] or (b.." (U+"..(c and format("%05X",c) or "?????")..")") - end -end -function number.signed(i) - if i>0 then - return "+",i - else - return "-",-i - end -end -local zero=P("0")^1/"" -local plus=P("+")/"" -local minus=P("-") -local separator=S(".") -local digit=R("09") -local trailing=zero^1*#S("eE") -local exponent=(S("eE")*(plus+Cs((minus*zero^0*P(-1))/"")+minus)*zero^0*(P(-1)*Cc("0")+P(1)^1)) -local pattern_a=Cs(minus^0*digit^1*(separator/""*trailing+separator*(trailing+digit)^0)*exponent) -local pattern_b=Cs((exponent+P(1))^0) -function number.sparseexponent(f,n) - if not n then - n=f - f="%e" - end - local tn=type(n) - if tn=="string" then - local m=tonumber(n) - if m then - return lpegmatch((f=="%e" or f=="%E") and pattern_a or pattern_b,format(f,m)) - end - elseif tn=="number" then - return lpegmatch((f=="%e" or f=="%E") and pattern_a or pattern_b,format(f,n)) - end - return tostring(n) -end -local template=[[ -%s -%s -return function(%s) return %s end -]] -local preamble,environment="",{} -if _LUAVERSION<5.2 then - preamble=[[ -local lpeg=lpeg -local type=type -local tostring=tostring -local tonumber=tonumber -local format=string.format -local concat=table.concat -local signed=number.signed -local points=number.points -local basepoints= number.basepoints -local utfchar=utf.char -local utfbyte=utf.byte -local lpegmatch=lpeg.match -local nspaces=string.nspaces -local tracedchar=string.tracedchar -local autosingle=string.autosingle -local autodouble=string.autodouble -local sequenced=table.sequenced -local formattednumber=number.formatted -local sparseexponent=number.sparseexponent - ]] -else - environment={ - global=global or _G, - lpeg=lpeg, - type=type, - tostring=tostring, - tonumber=tonumber, - format=string.format, - concat=table.concat, - signed=number.signed, - points=number.points, - basepoints=number.basepoints, - utfchar=utf.char, - utfbyte=utf.byte, - lpegmatch=lpeg.match, - nspaces=string.nspaces, - tracedchar=string.tracedchar, - autosingle=string.autosingle, - autodouble=string.autodouble, - sequenced=table.sequenced, - formattednumber=number.formatted, - sparseexponent=number.sparseexponent, - } -end -local arguments={ "a1" } -setmetatable(arguments,{ __index=function(t,k) - local v=t[k-1]..",a"..k - t[k]=v - return v - end -}) -local prefix_any=C((S("+- .")+R("09"))^0) -local prefix_tab=P("{")*C((1-P("}"))^0)*P("}")+C((1-R("az","AZ","09","%%"))^0) -local format_s=function(f) - n=n+1 - if f and f~="" then - return format("format('%%%ss',a%s)",f,n) - else - return format("(a%s or '')",n) - end -end -local format_S=function(f) - n=n+1 - if f and f~="" then - return format("format('%%%ss',tostring(a%s))",f,n) - else - return format("tostring(a%s)",n) - end -end -local format_q=function() - n=n+1 - return format("(a%s and format('%%q',a%s) or '')",n,n) -end -local format_Q=function() - n=n+1 - return format("format('%%q',tostring(a%s))",n) -end -local format_i=function(f) - n=n+1 - if f and f~="" then - return format("format('%%%si',a%s)",f,n) - else - return format("format('%%i',a%s)",n) - end -end -local format_d=format_i -local format_I=function(f) - n=n+1 - return format("format('%%s%%%si',signed(a%s))",f,n) -end -local format_f=function(f) - n=n+1 - return format("format('%%%sf',a%s)",f,n) -end -local format_F=function(f) - n=n+1 - if not f or f=="" then - return format("(((a%s > -0.0000000005 and a%s < 0.0000000005) and '0') or format((a%s %% 1 == 0) and '%%i' or '%%.9f',a%s))",n,n,n,n) - else - return format("format((a%s %% 1 == 0) and '%%i' or '%%%sf',a%s)",n,f,n) - end -end -local format_g=function(f) - n=n+1 - return format("format('%%%sg',a%s)",f,n) -end -local format_G=function(f) - n=n+1 - return format("format('%%%sG',a%s)",f,n) -end -local format_e=function(f) - n=n+1 - return format("format('%%%se',a%s)",f,n) -end -local format_E=function(f) - n=n+1 - return format("format('%%%sE',a%s)",f,n) -end -local format_j=function(f) - n=n+1 - return format("sparseexponent('%%%se',a%s)",f,n) -end -local format_J=function(f) - n=n+1 - return format("sparseexponent('%%%sE',a%s)",f,n) -end -local format_x=function(f) - n=n+1 - return format("format('%%%sx',a%s)",f,n) -end -local format_X=function(f) - n=n+1 - return format("format('%%%sX',a%s)",f,n) -end -local format_o=function(f) - n=n+1 - return format("format('%%%so',a%s)",f,n) -end -local format_c=function() - n=n+1 - return format("utfchar(a%s)",n) -end -local format_C=function() - n=n+1 - return format("tracedchar(a%s)",n) -end -local format_r=function(f) - n=n+1 - return format("format('%%%s.0f',a%s)",f,n) -end -local format_h=function(f) - n=n+1 - if f=="-" then - f=sub(f,2) - return format("format('%%%sx',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n) - else - return format("format('0x%%%sx',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n) - end -end -local format_H=function(f) - n=n+1 - if f=="-" then - f=sub(f,2) - return format("format('%%%sX',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n) - else - return format("format('0x%%%sX',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n) - end -end -local format_u=function(f) - n=n+1 - if f=="-" then - f=sub(f,2) - return format("format('%%%sx',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n) - else - return format("format('u+%%%sx',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n) - end -end -local format_U=function(f) - n=n+1 - if f=="-" then - f=sub(f,2) - return format("format('%%%sX',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n) - else - return format("format('U+%%%sX',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n) - end -end -local format_p=function() - n=n+1 - return format("points(a%s)",n) -end -local format_b=function() - n=n+1 - return format("basepoints(a%s)",n) -end -local format_t=function(f) - n=n+1 - if f and f~="" then - return format("concat(a%s,%q)",n,f) - else - return format("concat(a%s)",n) - end -end -local format_T=function(f) - n=n+1 - if f and f~="" then - return format("sequenced(a%s,%q)",n,f) - else - return format("sequenced(a%s)",n) - end -end -local format_l=function() - n=n+1 - return format("(a%s and 'true' or 'false')",n) -end -local format_L=function() - n=n+1 - return format("(a%s and 'TRUE' or 'FALSE')",n) -end -local format_N=function() - n=n+1 - return format("tostring(tonumber(a%s) or a%s)",n,n) -end -local format_a=function(f) - n=n+1 - if f and f~="" then - return format("autosingle(a%s,%q)",n,f) - else - return format("autosingle(a%s)",n) - end -end -local format_A=function(f) - n=n+1 - if f and f~="" then - return format("autodouble(a%s,%q)",n,f) - else - return format("autodouble(a%s)",n) - end -end -local format_w=function(f) - n=n+1 - f=tonumber(f) - if f then - return format("nspaces[%s+a%s]",f,n) - else - return format("nspaces[a%s]",n) - end -end -local format_W=function(f) - return format("nspaces[%s]",tonumber(f) or 0) -end -local digit=patterns.digit -local period=patterns.period -local three=digit*digit*digit -local splitter=Cs ( - (((1-(three^1*period))^1+C(three))*(Carg(1)*three)^1+C((1-period)^1))*(P(1)/""*Carg(2))*C(2) -) -patterns.formattednumber=splitter -function number.formatted(n,sep1,sep2) - local s=type(s)=="string" and n or format("%0.2f",n) - if sep1==true then - return lpegmatch(splitter,s,1,".",",") - elseif sep1=="." then - return lpegmatch(splitter,s,1,sep1,sep2 or ",") - elseif sep1=="," then - return lpegmatch(splitter,s,1,sep1,sep2 or ".") - else - return lpegmatch(splitter,s,1,sep1 or ",",sep2 or ".") - end -end -local format_m=function(f) - n=n+1 - if not f or f=="" then - f="," - end - return format([[formattednumber(a%s,%q,".")]],n,f) -end -local format_M=function(f) - n=n+1 - if not f or f=="" then - f="." - end - return format([[formattednumber(a%s,%q,",")]],n,f) -end -local format_z=function(f) - n=n+(tonumber(f) or 1) - return "''" -end -local format_rest=function(s) - return format("%q",s) -end -local format_extension=function(extensions,f,name) - local extension=extensions[name] or "tostring(%s)" - local f=tonumber(f) or 1 - if f==0 then - return extension - elseif f==1 then - n=n+1 - local a="a"..n - return format(extension,a,a) - elseif f<0 then - local a="a"..(n+f+1) - return format(extension,a,a) - else - local t={} - for i=1,f do - n=n+1 - t[#t+1]="a"..n - end - return format(extension,unpack(t)) - end -end -local builder=Cs { "start", - start=( - ( - P("%")/""*( - V("!") -+V("s")+V("q")+V("i")+V("d")+V("f")+V("F")+V("g")+V("G")+V("e")+V("E")+V("x")+V("X")+V("o") -+V("c")+V("C")+V("S") -+V("Q") -+V("N") -+V("r")+V("h")+V("H")+V("u")+V("U")+V("p")+V("b")+V("t")+V("T")+V("l")+V("L")+V("I")+V("w") -+V("W") -+V("a") -+V("A") -+V("j")+V("J") -+V("m")+V("M") -+V("z") - )+V("*") - )*(P(-1)+Carg(1)) - )^0, - ["s"]=(prefix_any*P("s"))/format_s, - ["q"]=(prefix_any*P("q"))/format_q, - ["i"]=(prefix_any*P("i"))/format_i, - ["d"]=(prefix_any*P("d"))/format_d, - ["f"]=(prefix_any*P("f"))/format_f, - ["F"]=(prefix_any*P("F"))/format_F, - ["g"]=(prefix_any*P("g"))/format_g, - ["G"]=(prefix_any*P("G"))/format_G, - ["e"]=(prefix_any*P("e"))/format_e, - ["E"]=(prefix_any*P("E"))/format_E, - ["x"]=(prefix_any*P("x"))/format_x, - ["X"]=(prefix_any*P("X"))/format_X, - ["o"]=(prefix_any*P("o"))/format_o, - ["S"]=(prefix_any*P("S"))/format_S, - ["Q"]=(prefix_any*P("Q"))/format_S, - ["N"]=(prefix_any*P("N"))/format_N, - ["c"]=(prefix_any*P("c"))/format_c, - ["C"]=(prefix_any*P("C"))/format_C, - ["r"]=(prefix_any*P("r"))/format_r, - ["h"]=(prefix_any*P("h"))/format_h, - ["H"]=(prefix_any*P("H"))/format_H, - ["u"]=(prefix_any*P("u"))/format_u, - ["U"]=(prefix_any*P("U"))/format_U, - ["p"]=(prefix_any*P("p"))/format_p, - ["b"]=(prefix_any*P("b"))/format_b, - ["t"]=(prefix_tab*P("t"))/format_t, - ["T"]=(prefix_tab*P("T"))/format_T, - ["l"]=(prefix_any*P("l"))/format_l, - ["L"]=(prefix_any*P("L"))/format_L, - ["I"]=(prefix_any*P("I"))/format_I, - ["w"]=(prefix_any*P("w"))/format_w, - ["W"]=(prefix_any*P("W"))/format_W, - ["j"]=(prefix_any*P("j"))/format_j, - ["J"]=(prefix_any*P("J"))/format_J, - ["m"]=(prefix_tab*P("m"))/format_m, - ["M"]=(prefix_tab*P("M"))/format_M, - ["z"]=(prefix_any*P("z"))/format_z, - ["a"]=(prefix_any*P("a"))/format_a, - ["A"]=(prefix_any*P("A"))/format_A, - ["*"]=Cs(((1-P("%"))^1+P("%%")/"%%")^1)/format_rest, - ["?"]=Cs(((1-P("%"))^1 )^1)/format_rest, - ["!"]=Carg(2)*prefix_any*P("!")*C((1-P("!"))^1)*P("!")/format_extension, -} -local direct=Cs ( - P("%")*(S("+- .")+R("09"))^0*S("sqidfgGeExXo")*P(-1)/[[local format = string.format return function(str) return format("%0",str) end]] -) -local function make(t,str) - local f - local p - local p=lpegmatch(direct,str) - if p then - f=loadstripped(p)() - else - n=0 - p=lpegmatch(builder,str,1,t._connector_,t._extensions_) - if n>0 then - p=format(template,preamble,t._preamble_,arguments[n],p) - f=loadstripped(p,t._environment_)() - else - f=function() return str end - end - end - t[str]=f - return f -end -local function use(t,fmt,...) - return t[fmt](...) -end -strings.formatters={} -if _LUAVERSION<5.2 then - function strings.formatters.new(noconcat) - local t={ _type_="formatter",_connector_=noconcat and "," or "..",_extensions_={},_preamble_=preamble,_environment_={} } - setmetatable(t,{ __index=make,__call=use }) - return t - end -else - function strings.formatters.new(noconcat) - local e={} - for k,v in next,environment do - e[k]=v - end - local t={ _type_="formatter",_connector_=noconcat and "," or "..",_extensions_={},_preamble_="",_environment_=e } - setmetatable(t,{ __index=make,__call=use }) - return t - end -end -local formatters=strings.formatters.new() -string.formatters=formatters -string.formatter=function(str,...) return formatters[str](...) end -local function add(t,name,template,preamble) - if type(t)=="table" and t._type_=="formatter" then - t._extensions_[name]=template or "%s" - if type(preamble)=="string" then - t._preamble_=preamble.."\n"..t._preamble_ - elseif type(preamble)=="table" then - for k,v in next,preamble do - t._environment_[k]=v - end - end - end -end -strings.formatters.add=add -patterns.xmlescape=Cs((P("<")/"<"+P(">")/">"+P("&")/"&"+P('"')/"""+P(1))^0) -patterns.texescape=Cs((C(S("#$%\\{}"))/"\\%1"+P(1))^0) -patterns.luaescape=Cs(((1-S('"\n'))^1+P('"')/'\\"'+P('\n')/'\\n"')^0) -patterns.luaquoted=Cs(Cc('"')*((1-S('"\n'))^1+P('"')/'\\"'+P('\n')/'\\n"')^0*Cc('"')) -if _LUAVERSION<5.2 then - add(formatters,"xml",[[lpegmatch(xmlescape,%s)]],"local xmlescape = lpeg.patterns.xmlescape") - add(formatters,"tex",[[lpegmatch(texescape,%s)]],"local texescape = lpeg.patterns.texescape") - add(formatters,"lua",[[lpegmatch(luaescape,%s)]],"local luaescape = lpeg.patterns.luaescape") -else - add(formatters,"xml",[[lpegmatch(xmlescape,%s)]],{ xmlescape=lpeg.patterns.xmlescape }) - add(formatters,"tex",[[lpegmatch(texescape,%s)]],{ texescape=lpeg.patterns.texescape }) - add(formatters,"lua",[[lpegmatch(luaescape,%s)]],{ luaescape=lpeg.patterns.luaescape }) -end -local dquote=patterns.dquote -local equote=patterns.escaped+dquote/'\\"'+1 -local space=patterns.space -local cquote=Cc('"') -local pattern=Cs(dquote*(equote-P(-2))^0*dquote) -+Cs(cquote*(equote-space)^0*space*equote^0*cquote) -function string.optionalquoted(str) - return lpegmatch(pattern,str) or str -end -local pattern=Cs((newline/(os.newline or "\r")+1)^0) -function string.replacenewlines(str) - return lpegmatch(pattern,str) -end - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['util-fil']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local byte=string.byte -local extract=bit32.extract -utilities=utilities or {} -local files={} -utilities.files=files -local zerobased={} -function files.open(filename,zb) - local f=io.open(filename,"rb") - if f then - zerobased[f]=zb or false - end - return f -end -function files.close(f) - zerobased[f]=nil - f:close() -end -function files.size(f) - return f:seek("end") -end -function files.setposition(f,n) - if zerobased[f] then - f:seek("set",n) - else - f:seek("set",n-1) - end -end -function files.getposition(f) - if zerobased[f] then - return f:seek() - else - return f:seek()+1 - end -end -function files.look(f,n,chars) - local p=f:seek() - local s=f:read(n) - f:seek("set",p) - if chars then - return s - else - return byte(s,1,#s) - end -end -function files.skip(f,n) - if n==1 then - f:read(n) - else - f:seek("set",f:seek()+n) - end -end -function files.readbyte(f) - return byte(f:read(1)) -end -function files.readbytes(f,n) - return byte(f:read(n),1,n) -end -function files.readchar(f) - return f:read(1) -end -function files.readstring(f,n) - return f:read(n or 1) -end -function files.readinteger1(f) - local n=byte(f:read(1)) - if n>=0x80 then - return n-0xFF-1 - else - return n - end -end -files.readcardinal1=files.readbyte -files.readcardinal=files.readcardinal1 -files.readinteger=files.readinteger1 -function files.readcardinal2(f) - local a,b=byte(f:read(2),1,2) - return 0x100*a+b -end -function files.readinteger2(f) - local a,b=byte(f:read(2),1,2) - local n=0x100*a+b - if n>=0x8000 then - return n-0xFFFF-1 - else - return n - end -end -function files.readcardinal3(f) - local a,b,c=byte(f:read(3),1,3) - return 0x10000*a+0x100*b+c -end -function files.readcardinal4(f) - local a,b,c,d=byte(f:read(4),1,4) - return 0x1000000*a+0x10000*b+0x100*c+d -end -function files.readinteger4(f) - local a,b,c,d=byte(f:read(4),1,4) - local n=0x1000000*a+0x10000*b+0x100*c+d - if n>=0x8000000 then - return n-0xFFFFFFFF-1 - else - return n - end -end -function files.readfixed4(f) - local a,b,c,d=byte(f:read(4),1,4) - local n=0x100*a+b - if n>=0x8000 then - return n-0xFFFF-1+(0x100*c+d)/0xFFFF - else - return n+(0x100*c+d)/0xFFFF - end -end -function files.read2dot14(f) - local a,b=byte(f:read(2),1,2) - local n=0x100*a+b - local m=extract(n,0,30) - if n>0x7FFF then - n=extract(n,30,2) - return m/0x4000-4 - else - n=extract(n,30,2) - return n+m/0x4000 - end -end -function files.skipshort(f,n) - f:read(2*(n or 1)) -end -function files.skiplong(f,n) - f:read(4*(n or 1)) -end - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['util-tab']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -utilities=utilities or {} -utilities.tables=utilities.tables or {} -local tables=utilities.tables -local format,gmatch,gsub,sub=string.format,string.gmatch,string.gsub,string.sub -local concat,insert,remove,sort=table.concat,table.insert,table.remove,table.sort -local setmetatable,getmetatable,tonumber,tostring=setmetatable,getmetatable,tonumber,tostring -local type,next,rawset,tonumber,tostring,load,select=type,next,rawset,tonumber,tostring,load,select -local lpegmatch,P,Cs,Cc=lpeg.match,lpeg.P,lpeg.Cs,lpeg.Cc -local sortedkeys,sortedpairs=table.sortedkeys,table.sortedpairs -local formatters=string.formatters -local utftoeight=utf.toeight -local splitter=lpeg.tsplitat(".") -function utilities.tables.definetable(target,nofirst,nolast) - local composed,t=nil,{} - local snippets=lpegmatch(splitter,target) - for i=1,#snippets-(nolast and 1 or 0) do - local name=snippets[i] - if composed then - composed=composed.."."..name - t[#t+1]=formatters["if not %s then %s = { } end"](composed,composed) - else - composed=name - if not nofirst then - t[#t+1]=formatters["%s = %s or { }"](composed,composed) - end - end - end - if composed then - if nolast then - composed=composed.."."..snippets[#snippets] - end - return concat(t,"\n"),composed - else - return "",target - end -end -function tables.definedtable(...) - local t=_G - for i=1,select("#",...) do - local li=select(i,...) - local tl=t[li] - if not tl then - tl={} - t[li]=tl - end - t=tl - end - return t -end -function tables.accesstable(target,root) - local t=root or _G - for name in gmatch(target,"([^%.]+)") do - t=t[name] - if not t then - return - end - end - return t -end -function tables.migratetable(target,v,root) - local t=root or _G - local names=lpegmatch(splitter,target) - for i=1,#names-1 do - local name=names[i] - t[name]=t[name] or {} - t=t[name] - if not t then - return - end - end - t[names[#names]]=v -end -function tables.removevalue(t,value) - if value then - for i=1,#t do - if t[i]==value then - remove(t,i) - end - end - end -end -function tables.replacevalue(t,oldvalue,newvalue) - if oldvalue and newvalue then - for i=1,#t do - if t[i]==oldvalue then - t[i]=newvalue - end - end - end -end -function tables.insertbeforevalue(t,value,extra) - for i=1,#t do - if t[i]==extra then - remove(t,i) - end - end - for i=1,#t do - if t[i]==value then - insert(t,i,extra) - return - end - end - insert(t,1,extra) -end -function tables.insertaftervalue(t,value,extra) - for i=1,#t do - if t[i]==extra then - remove(t,i) - end - end - for i=1,#t do - if t[i]==value then - insert(t,i+1,extra) - return - end - end - insert(t,#t+1,extra) -end -local escape=Cs(Cc('"')*((P('"')/'""'+P(1))^0)*Cc('"')) -function table.tocsv(t,specification) - if t and #t>0 then - local result={} - local r={} - specification=specification or {} - local fields=specification.fields - if type(fields)~="string" then - fields=sortedkeys(t[1]) - end - local separator=specification.separator or "," - if specification.preamble==true then - for f=1,#fields do - r[f]=lpegmatch(escape,tostring(fields[f])) - end - result[1]=concat(r,separator) - end - for i=1,#t do - local ti=t[i] - for f=1,#fields do - local field=ti[fields[f]] - if type(field)=="string" then - r[f]=lpegmatch(escape,field) - else - r[f]=tostring(field) - end - end - result[#result+1]=concat(r,separator) - end - return concat(result,"\n") - else - return "" - end -end -local nspaces=utilities.strings.newrepeater(" ") -local function toxml(t,d,result,step) - for k,v in sortedpairs(t) do - local s=nspaces[d] - local tk=type(k) - local tv=type(v) - if tv=="table" then - if tk=="number" then - result[#result+1]=formatters["%s<entry n='%s'>"](s,k) - toxml(v,d+step,result,step) - result[#result+1]=formatters["%s</entry>"](s,k) - else - result[#result+1]=formatters["%s<%s>"](s,k) - toxml(v,d+step,result,step) - result[#result+1]=formatters["%s</%s>"](s,k) - end - elseif tv=="string" then - if tk=="number" then - result[#result+1]=formatters["%s<entry n='%s'>%!xml!</entry>"](s,k,v,k) - else - result[#result+1]=formatters["%s<%s>%!xml!</%s>"](s,k,v,k) - end - elseif tk=="number" then - result[#result+1]=formatters["%s<entry n='%s'>%S</entry>"](s,k,v,k) - else - result[#result+1]=formatters["%s<%s>%S</%s>"](s,k,v,k) - end - end -end -function table.toxml(t,specification) - specification=specification or {} - local name=specification.name - local noroot=name==false - local result=(specification.nobanner or noroot) and {} or { "<?xml version='1.0' standalone='yes' ?>" } - local indent=specification.indent or 0 - local spaces=specification.spaces or 1 - if noroot then - toxml(t,indent,result,spaces) - else - toxml({ [name or "data"]=t },indent,result,spaces) - end - return concat(result,"\n") -end -function tables.encapsulate(core,capsule,protect) - if type(capsule)~="table" then - protect=true - capsule={} - end - for key,value in next,core do - if capsule[key] then - print(formatters["\ninvalid %s %a in %a"]("inheritance",key,core)) - os.exit() - else - capsule[key]=value - end - end - if protect then - for key,value in next,core do - core[key]=nil - end - setmetatable(core,{ - __index=capsule, - __newindex=function(t,key,value) - if capsule[key] then - print(formatters["\ninvalid %s %a' in %a"]("overload",key,core)) - os.exit() - else - rawset(t,key,value) - end - end - } ) - end -end -local f_hashed_string=formatters["[%q]=%q,"] -local f_hashed_number=formatters["[%q]=%s,"] -local f_hashed_boolean=formatters["[%q]=%l,"] -local f_hashed_table=formatters["[%q]="] -local f_indexed_string=formatters["[%s]=%q,"] -local f_indexed_number=formatters["[%s]=%s,"] -local f_indexed_boolean=formatters["[%s]=%l,"] -local f_indexed_table=formatters["[%s]="] -local f_ordered_string=formatters["%q,"] -local f_ordered_number=formatters["%s,"] -local f_ordered_boolean=formatters["%l,"] -function table.fastserialize(t,prefix) - local r={ type(prefix)=="string" and prefix or "return" } - local m=1 - local function fastserialize(t,outer) - local n=#t - m=m+1 - r[m]="{" - if n>0 then - for i=0,n do - local v=t[i] - local tv=type(v) - if tv=="string" then - m=m+1 r[m]=f_ordered_string(v) - elseif tv=="number" then - m=m+1 r[m]=f_ordered_number(v) - elseif tv=="table" then - fastserialize(v) - elseif tv=="boolean" then - m=m+1 r[m]=f_ordered_boolean(v) - end - end - end - for k,v in next,t do - local tk=type(k) - if tk=="number" then - if k>n or k<0 then - local tv=type(v) - if tv=="string" then - m=m+1 r[m]=f_indexed_string(k,v) - elseif tv=="number" then - m=m+1 r[m]=f_indexed_number(k,v) - elseif tv=="table" then - m=m+1 r[m]=f_indexed_table(k) - fastserialize(v) - elseif tv=="boolean" then - m=m+1 r[m]=f_indexed_boolean(k,v) - end - end - else - local tv=type(v) - if tv=="string" then - m=m+1 r[m]=f_hashed_string(k,v) - elseif tv=="number" then - m=m+1 r[m]=f_hashed_number(k,v) - elseif tv=="table" then - m=m+1 r[m]=f_hashed_table(k) - fastserialize(v) - elseif tv=="boolean" then - m=m+1 r[m]=f_hashed_boolean(k,v) - end - end - end - m=m+1 - if outer then - r[m]="}" - else - r[m]="}," - end - return r - end - return concat(fastserialize(t,true)) -end -function table.deserialize(str) - if not str or str=="" then - return - end - local code=load(str) - if not code then - return - end - code=code() - if not code then - return - end - return code -end -function table.load(filename,loader) - if filename then - local t=(loader or io.loaddata)(filename) - if t and t~="" then - local t=utftoeight(t) - t=load(t) - if type(t)=="function" then - t=t() - if type(t)=="table" then - return t - end - end - end - end -end -function table.save(filename,t,n,...) - io.savedata(filename,table.serialize(t,n==nil and true or n,...)) -end -local f_key_value=formatters["%s=%q"] -local f_add_table=formatters[" {%t},\n"] -local f_return_table=formatters["return {\n%t}"] -local function slowdrop(t) - local r={} - local l={} - for i=1,#t do - local ti=t[i] - local j=0 - for k,v in next,ti do - j=j+1 - l[j]=f_key_value(k,v) - end - r[i]=f_add_table(l) - end - return f_return_table(r) -end -local function fastdrop(t) - local r={ "return {\n" } - local m=1 - for i=1,#t do - local ti=t[i] - m=m+1 r[m]=" {" - for k,v in next,ti do - m=m+1 r[m]=f_key_value(k,v) - end - m=m+1 r[m]="},\n" - end - m=m+1 - r[m]="}" - return concat(r) -end -function table.drop(t,slow) - if #t==0 then - return "return { }" - elseif slow==true then - return slowdrop(t) - else - return fastdrop(t) - end -end -function table.autokey(t,k) - local v={} - t[k]=v - return v -end -local selfmapper={ __index=function(t,k) t[k]=k return k end } -function table.twowaymapper(t) - if not t then - t={} - else - for i=0,#t do - local ti=t[i] - if ti then - local i=tostring(i) - t[i]=ti - t[ti]=i - end - end - t[""]=t[0] or "" - end - setmetatable(t,selfmapper) - return t -end -local f_start_key_idx=formatters["%w{"] -local f_start_key_num=formatters["%w[%s]={"] -local f_start_key_str=formatters["%w[%q]={"] -local f_start_key_boo=formatters["%w[%l]={"] -local f_start_key_nop=formatters["%w{"] -local f_stop=formatters["%w},"] -local f_key_num_value_num=formatters["%w[%s]=%s,"] -local f_key_str_value_num=formatters["%w[%q]=%s,"] -local f_key_boo_value_num=formatters["%w[%l]=%s,"] -local f_key_num_value_str=formatters["%w[%s]=%q,"] -local f_key_str_value_str=formatters["%w[%q]=%q,"] -local f_key_boo_value_str=formatters["%w[%l]=%q,"] -local f_key_num_value_boo=formatters["%w[%s]=%l,"] -local f_key_str_value_boo=formatters["%w[%q]=%l,"] -local f_key_boo_value_boo=formatters["%w[%l]=%l,"] -local f_key_num_value_not=formatters["%w[%s]={},"] -local f_key_str_value_not=formatters["%w[%q]={},"] -local f_key_boo_value_not=formatters["%w[%l]={},"] -local f_key_num_value_seq=formatters["%w[%s]={ %, t },"] -local f_key_str_value_seq=formatters["%w[%q]={ %, t },"] -local f_key_boo_value_seq=formatters["%w[%l]={ %, t },"] -local f_val_num=formatters["%w%s,"] -local f_val_str=formatters["%w%q,"] -local f_val_boo=formatters["%w%l,"] -local f_val_not=formatters["%w{},"] -local f_val_seq=formatters["%w{ %, t },"] -local f_fin_seq=formatters[" %, t }"] -local f_table_return=formatters["return {"] -local f_table_name=formatters["%s={"] -local f_table_direct=formatters["{"] -local f_table_entry=formatters["[%q]={"] -local f_table_finish=formatters["}"] -local spaces=utilities.strings.newrepeater(" ") -local original_serialize=table.serialize -local function serialize(root,name,specification) - if type(specification)=="table" then - return original_serialize(root,name,specification) - end - local t - local n=1 - local unknown=false - local function simple_table(t) - local nt=#t - if nt>0 then - local n=0 - for _,v in next,t do - n=n+1 - if type(v)=="table" then - return nil - end - end - local haszero=t[0] - if n==nt then - local tt={} - for i=1,nt do - local v=t[i] - local tv=type(v) - if tv=="number" then - tt[i]=v - elseif tv=="string" then - tt[i]=format("%q",v) - elseif tv=="boolean" then - tt[i]=v and "true" or "false" - else - return nil - end - end - return tt - elseif haszero and (n==nt+1) then - local tt={} - for i=0,nt do - local v=t[i] - local tv=type(v) - if tv=="number" then - tt[i+1]=v - elseif tv=="string" then - tt[i+1]=format("%q",v) - elseif tv=="boolean" then - tt[i+1]=v and "true" or "false" - else - return nil - end - end - tt[1]="[0] = "..tt[1] - return tt - end - end - return nil - end - local function do_serialize(root,name,depth,level,indexed) - if level>0 then - n=n+1 - if indexed then - t[n]=f_start_key_idx(depth) - else - local tn=type(name) - if tn=="number" then - t[n]=f_start_key_num(depth,name) - elseif tn=="string" then - t[n]=f_start_key_str(depth,name) - elseif tn=="boolean" then - t[n]=f_start_key_boo(depth,name) - else - t[n]=f_start_key_nop(depth) - end - end - depth=depth+1 - end - if root and next(root)~=nil then - local first=nil - local last=0 - last=#root - for k=1,last do - if root[k]==nil then - last=k-1 - break - end - end - if last>0 then - first=1 - end - local sk=sortedkeys(root) - for i=1,#sk do - local k=sk[i] - local v=root[k] - local tv=type(v) - local tk=type(k) - if first and tk=="number" and k<=last and k>=first then - if tv=="number" then - n=n+1 t[n]=f_val_num(depth,v) - elseif tv=="string" then - n=n+1 t[n]=f_val_str(depth,v) - elseif tv=="table" then - if next(v)==nil then - n=n+1 t[n]=f_val_not(depth) - else - local st=simple_table(v) - if st then - n=n+1 t[n]=f_val_seq(depth,st) - else - do_serialize(v,k,depth,level+1,true) - end - end - elseif tv=="boolean" then - n=n+1 t[n]=f_val_boo(depth,v) - elseif unknown then - n=n+1 t[n]=f_val_str(depth,tostring(v)) - end - elseif tv=="number" then - if tk=="number" then - n=n+1 t[n]=f_key_num_value_num(depth,k,v) - elseif tk=="string" then - n=n+1 t[n]=f_key_str_value_num(depth,k,v) - elseif tk=="boolean" then - n=n+1 t[n]=f_key_boo_value_num(depth,k,v) - elseif unknown then - n=n+1 t[n]=f_key_str_value_num(depth,tostring(k),v) - end - elseif tv=="string" then - if tk=="number" then - n=n+1 t[n]=f_key_num_value_str(depth,k,v) - elseif tk=="string" then - n=n+1 t[n]=f_key_str_value_str(depth,k,v) - elseif tk=="boolean" then - n=n+1 t[n]=f_key_boo_value_str(depth,k,v) - elseif unknown then - n=n+1 t[n]=f_key_str_value_str(depth,tostring(k),v) - end - elseif tv=="table" then - if next(v)==nil then - if tk=="number" then - n=n+1 t[n]=f_key_num_value_not(depth,k) - elseif tk=="string" then - n=n+1 t[n]=f_key_str_value_not(depth,k) - elseif tk=="boolean" then - n=n+1 t[n]=f_key_boo_value_not(depth,k) - elseif unknown then - n=n+1 t[n]=f_key_str_value_not(depth,tostring(k)) - end - else - local st=simple_table(v) - if not st then - do_serialize(v,k,depth,level+1) - elseif tk=="number" then - n=n+1 t[n]=f_key_num_value_seq(depth,k,st) - elseif tk=="string" then - n=n+1 t[n]=f_key_str_value_seq(depth,k,st) - elseif tk=="boolean" then - n=n+1 t[n]=f_key_boo_value_seq(depth,k,st) - elseif unknown then - n=n+1 t[n]=f_key_str_value_seq(depth,tostring(k),st) - end - end - elseif tv=="boolean" then - if tk=="number" then - n=n+1 t[n]=f_key_num_value_boo(depth,k,v) - elseif tk=="string" then - n=n+1 t[n]=f_key_str_value_boo(depth,k,v) - elseif tk=="boolean" then - n=n+1 t[n]=f_key_boo_value_boo(depth,k,v) - elseif unknown then - n=n+1 t[n]=f_key_str_value_boo(depth,tostring(k),v) - end - else - if tk=="number" then - n=n+1 t[n]=f_key_num_value_str(depth,k,tostring(v)) - elseif tk=="string" then - n=n+1 t[n]=f_key_str_value_str(depth,k,tostring(v)) - elseif tk=="boolean" then - n=n+1 t[n]=f_key_boo_value_str(depth,k,tostring(v)) - elseif unknown then - n=n+1 t[n]=f_key_str_value_str(depth,tostring(k),tostring(v)) - end - end - end - end - if level>0 then - n=n+1 t[n]=f_stop(depth-1) - end - end - local tname=type(name) - if tname=="string" then - if name=="return" then - t={ f_table_return() } - else - t={ f_table_name(name) } - end - elseif tname=="number" then - t={ f_table_entry(name) } - elseif tname=="boolean" then - if name then - t={ f_table_return() } - else - t={ f_table_direct() } - end - else - t={ f_table_name("t") } - end - if root then - if getmetatable(root) then - local dummy=root._w_h_a_t_e_v_e_r_ - root._w_h_a_t_e_v_e_r_=nil - end - if next(root)~=nil then - local st=simple_table(root) - if st then - return t[1]..f_fin_seq(st) - else - do_serialize(root,name,1,0) - end - end - end - n=n+1 - t[n]=f_table_finish() - return concat(t,"\n") -end -table.serialize=serialize -if setinspector then - setinspector("table",function(v) if type(v)=="table" then print(serialize(v,"table",{})) return true end end) -end - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['util-sto']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local setmetatable,getmetatable,type=setmetatable,getmetatable,type -utilities=utilities or {} -utilities.storage=utilities.storage or {} -local storage=utilities.storage -function storage.mark(t) - if not t then - print("\nfatal error: storage cannot be marked\n") - os.exit() - return - end - local m=getmetatable(t) - if not m then - m={} - setmetatable(t,m) - end - m.__storage__=true - return t -end -function storage.allocate(t) - t=t or {} - local m=getmetatable(t) - if not m then - m={} - setmetatable(t,m) - end - m.__storage__=true - return t -end -function storage.marked(t) - local m=getmetatable(t) - return m and m.__storage__ -end -function storage.checked(t) - if not t then - report("\nfatal error: storage has not been allocated\n") - os.exit() - return - end - return t -end -function storage.setinitializer(data,initialize) - local m=getmetatable(data) or {} - m.__index=function(data,k) - m.__index=nil - initialize() - return data[k] - end - setmetatable(data,m) -end -local keyisvalue={ __index=function(t,k) - t[k]=k - return k -end } -function storage.sparse(t) - t=t or {} - setmetatable(t,keyisvalue) - return t -end -local function f_empty () return "" end -local function f_self (t,k) t[k]=k return k end -local function f_table (t,k) local v={} t[k]=v return v end -local function f_number(t,k) t[k]=0 return 0 end -local function f_ignore() end -local f_index={ - ["empty"]=f_empty, - ["self"]=f_self, - ["table"]=f_table, - ["number"]=f_number, -} -function table.setmetatableindex(t,f) - if type(t)~="table" then - f,t=t,{} - end - local m=getmetatable(t) - local i=f_index[f] or f - if m then - m.__index=i - else - setmetatable(t,{ __index=i }) - end - return t -end -local f_index={ - ["ignore"]=f_ignore, -} -function table.setmetatablenewindex(t,f) - if type(t)~="table" then - f,t=t,{} - end - local m=getmetatable(t) - local i=f_index[f] or f - if m then - m.__newindex=i - else - setmetatable(t,{ __newindex=i }) - end - return t -end -function table.setmetatablecall(t,f) - if type(t)~="table" then - f,t=t,{} - end - local m=getmetatable(t) - if m then - m.__call=f - else - setmetatable(t,{ __call=f }) - end - return t -end -function table.setmetatablekey(t,key,value) - local m=getmetatable(t) - if not m then - m={} - setmetatable(t,m) - end - m[key]=value - return t -end -function table.getmetatablekey(t,key,value) - local m=getmetatable(t) - return m and m[key] -end - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['util-prs']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local lpeg,table,string=lpeg,table,string -local P,R,V,S,C,Ct,Cs,Carg,Cc,Cg,Cf,Cp=lpeg.P,lpeg.R,lpeg.V,lpeg.S,lpeg.C,lpeg.Ct,lpeg.Cs,lpeg.Carg,lpeg.Cc,lpeg.Cg,lpeg.Cf,lpeg.Cp -local lpegmatch,lpegpatterns=lpeg.match,lpeg.patterns -local concat,gmatch,find=table.concat,string.gmatch,string.find -local tostring,type,next,rawset=tostring,type,next,rawset -local mod,div=math.mod,math.div -utilities=utilities or {} -local parsers=utilities.parsers or {} -utilities.parsers=parsers -local patterns=parsers.patterns or {} -parsers.patterns=patterns -local setmetatableindex=table.setmetatableindex -local sortedhash=table.sortedhash -local sortedkeys=table.sortedkeys -local tohash=table.tohash -local hashes={} -utilities.parsers.hashes=hashes -local digit=R("09") -local space=P(' ') -local equal=P("=") -local comma=P(",") -local lbrace=P("{") -local rbrace=P("}") -local lparent=P("(") -local rparent=P(")") -local period=S(".") -local punctuation=S(".,:;") -local spacer=lpegpatterns.spacer -local whitespace=lpegpatterns.whitespace -local newline=lpegpatterns.newline -local anything=lpegpatterns.anything -local endofstring=lpegpatterns.endofstring -local nobrace=1-(lbrace+rbrace ) -local noparent=1-(lparent+rparent) -local escape,left,right=P("\\"),P('{'),P('}') -lpegpatterns.balanced=P { - [1]=((escape*(left+right))+(1-(left+right))+V(2))^0, - [2]=left*V(1)*right -} -local nestedbraces=P { lbrace*(nobrace+V(1))^0*rbrace } -local nestedparents=P { lparent*(noparent+V(1))^0*rparent } -local spaces=space^0 -local argument=Cs((lbrace/"")*((nobrace+nestedbraces)^0)*(rbrace/"")) -local content=(1-endofstring)^0 -lpegpatterns.nestedbraces=nestedbraces -lpegpatterns.nestedparents=nestedparents -lpegpatterns.nested=nestedbraces -lpegpatterns.argument=argument -lpegpatterns.content=content -local value=P(lbrace*C((nobrace+nestedbraces)^0)*rbrace)+C((nestedbraces+(1-comma))^0) -local key=C((1-equal-comma)^1) -local pattern_a=(space+comma)^0*(key*equal*value+key*C("")) -local pattern_c=(space+comma)^0*(key*equal*value) -local key=C((1-space-equal-comma)^1) -local pattern_b=spaces*comma^0*spaces*(key*((spaces*equal*spaces*value)+C(""))) -local hash={} -local function set(key,value) - hash[key]=value -end -local pattern_a_s=(pattern_a/set)^1 -local pattern_b_s=(pattern_b/set)^1 -local pattern_c_s=(pattern_c/set)^1 -patterns.settings_to_hash_a=pattern_a_s -patterns.settings_to_hash_b=pattern_b_s -patterns.settings_to_hash_c=pattern_c_s -function parsers.make_settings_to_hash_pattern(set,how) - if how=="strict" then - return (pattern_c/set)^1 - elseif how=="tolerant" then - return (pattern_b/set)^1 - else - return (pattern_a/set)^1 - end -end -function parsers.settings_to_hash(str,existing) - if not str or str=="" then - return {} - elseif type(str)=="table" then - if existing then - for k,v in next,str do - existing[k]=v - end - return exiting - else - return str - end - else - hash=existing or {} - lpegmatch(pattern_a_s,str) - return hash - end -end -function parsers.settings_to_hash_tolerant(str,existing) - if not str or str=="" then - return {} - elseif type(str)=="table" then - if existing then - for k,v in next,str do - existing[k]=v - end - return exiting - else - return str - end - else - hash=existing or {} - lpegmatch(pattern_b_s,str) - return hash - end -end -function parsers.settings_to_hash_strict(str,existing) - if not str or str=="" then - return nil - elseif type(str)=="table" then - if existing then - for k,v in next,str do - existing[k]=v - end - return exiting - else - return str - end - elseif str and str~="" then - hash=existing or {} - lpegmatch(pattern_c_s,str) - return next(hash) and hash - end -end -local separator=comma*space^0 -local value=P(lbrace*C((nobrace+nestedbraces)^0)*rbrace)+C((nestedbraces+(1-comma))^0) -local pattern=spaces*Ct(value*(separator*value)^0) -patterns.settings_to_array=pattern -function parsers.settings_to_array(str,strict) - if not str or str=="" then - return {} - elseif type(str)=="table" then - return str - elseif strict then - if find(str,"{",1,true) then - return lpegmatch(pattern,str) - else - return { str } - end - elseif find(str,",",1,true) then - return lpegmatch(pattern,str) - else - return { str } - end -end -local cache_a={} -local cache_b={} -function parsers.groupedsplitat(symbol,withaction) - if not symbol then - symbol="," - end - local pattern=(withaction and cache_b or cache_a)[symbol] - if not pattern then - local symbols=S(symbol) - local separator=space^0*symbols*space^0 - local value=P(lbrace*C((nobrace+nestedbraces)^0)*rbrace)+C((nestedbraces+(1-(space^0*(symbols+P(-1)))))^0) - if withaction then - local withvalue=Carg(1)*value/function(f,s) return f(s) end - pattern=spaces*withvalue*(separator*withvalue)^0 - cache_b[symbol]=pattern - else - pattern=spaces*Ct(value*(separator*value)^0) - cache_a[symbol]=pattern - end - end - return pattern -end -local pattern_a=parsers.groupedsplitat(",",false) -local pattern_b=parsers.groupedsplitat(",",true) -function parsers.stripped_settings_to_array(str) - if not str or str=="" then - return {} - else - return lpegmatch(pattern_a,str) - end -end -function parsers.process_stripped_settings(str,action) - if not str or str=="" then - return {} - else - return lpegmatch(pattern_b,str,1,action) - end -end -local function set(t,v) - t[#t+1]=v -end -local value=P(Carg(1)*value)/set -local pattern=value*(separator*value)^0*Carg(1) -function parsers.add_settings_to_array(t,str) - return lpegmatch(pattern,str,nil,t) -end -function parsers.hash_to_string(h,separator,yes,no,strict,omit) - if h then - local t,tn,s={},0,sortedkeys(h) - omit=omit and tohash(omit) - for i=1,#s do - local key=s[i] - if not omit or not omit[key] then - local value=h[key] - if type(value)=="boolean" then - if yes and no then - if value then - tn=tn+1 - t[tn]=key..'='..yes - elseif not strict then - tn=tn+1 - t[tn]=key..'='..no - end - elseif value or not strict then - tn=tn+1 - t[tn]=key..'='..tostring(value) - end - else - tn=tn+1 - t[tn]=key..'='..value - end - end - end - return concat(t,separator or ",") - else - return "" - end -end -function parsers.array_to_string(a,separator) - if a then - return concat(a,separator or ",") - else - return "" - end -end -local pattern=Cf(Ct("")*Cg(C((1-S(", "))^1)*S(", ")^0*Cc(true))^1,rawset) -function utilities.parsers.settings_to_set(str) - return str and lpegmatch(pattern,str) or {} -end -hashes.settings_to_set=table.setmetatableindex(function(t,k) - local v=k and lpegmatch(pattern,k) or {} - t[k]=v - return v -end) -getmetatable(hashes.settings_to_set).__mode="kv" -function parsers.simple_hash_to_string(h,separator) - local t,tn={},0 - for k,v in sortedhash(h) do - if v then - tn=tn+1 - t[tn]=k - end - end - return concat(t,separator or ",") -end -local str=Cs(lpegpatterns.unquoted)+C((1-whitespace-equal)^1) -local setting=Cf(Carg(1)*(whitespace^0*Cg(str*whitespace^0*(equal*whitespace^0*str+Cc(""))))^1,rawset) -local splitter=setting^1 -function utilities.parsers.options_to_hash(str,target) - return str and lpegmatch(splitter,str,1,target or {}) or {} -end -local splitter=lpeg.tsplitat(" ") -function utilities.parsers.options_to_array(str) - return str and lpegmatch(splitter,str) or {} -end -local value=P(lbrace*C((nobrace+nestedbraces)^0)*rbrace)+C(digit^1*lparent*(noparent+nestedparents)^1*rparent)+C((nestedbraces+(1-comma))^1) -local pattern_a=spaces*Ct(value*(separator*value)^0) -local function repeater(n,str) - if not n then - return str - else - local s=lpegmatch(pattern_a,str) - if n==1 then - return unpack(s) - else - local t,tn={},0 - for i=1,n do - for j=1,#s do - tn=tn+1 - t[tn]=s[j] - end - end - return unpack(t) - end - end -end -local value=P(lbrace*C((nobrace+nestedbraces)^0)*rbrace)+(C(digit^1)/tonumber*lparent*Cs((noparent+nestedparents)^1)*rparent)/repeater+C((nestedbraces+(1-comma))^1) -local pattern_b=spaces*Ct(value*(separator*value)^0) -function parsers.settings_to_array_with_repeat(str,expand) - if expand then - return lpegmatch(pattern_b,str) or {} - else - return lpegmatch(pattern_a,str) or {} - end -end -local value=lbrace*C((nobrace+nestedbraces)^0)*rbrace -local pattern=Ct((space+value)^0) -function parsers.arguments_to_table(str) - return lpegmatch(pattern,str) -end -function parsers.getparameters(self,class,parentclass,settings) - local sc=self[class] - if not sc then - sc={} - self[class]=sc - if parentclass then - local sp=self[parentclass] - if not sp then - sp={} - self[parentclass]=sp - end - setmetatableindex(sc,sp) - end - end - parsers.settings_to_hash(settings,sc) -end -function parsers.listitem(str) - return gmatch(str,"[^, ]+") -end -local pattern=Cs { "start", - start=V("one")+V("two")+V("three"), - rest=(Cc(",")*V("thousand"))^0*(P(".")+endofstring)*anything^0, - thousand=digit*digit*digit, - one=digit*V("rest"), - two=digit*digit*V("rest"), - three=V("thousand")*V("rest"), -} -lpegpatterns.splitthousands=pattern -function parsers.splitthousands(str) - return lpegmatch(pattern,str) or str -end -local optionalwhitespace=whitespace^0 -lpegpatterns.words=Ct((Cs((1-punctuation-whitespace)^1)+anything)^1) -lpegpatterns.sentences=Ct((optionalwhitespace*Cs((1-period)^0*period))^1) -lpegpatterns.paragraphs=Ct((optionalwhitespace*Cs((whitespace^1*endofstring/""+1-(spacer^0*newline*newline))^1))^1) -local dquote=P('"') -local equal=P('=') -local escape=P('\\') -local separator=S(' ,') -local key=C((1-equal)^1) -local value=dquote*C((1-dquote-escape*dquote)^0)*dquote -local pattern=Cf(Ct("")*(Cg(key*equal*value)*separator^0)^1,rawset)^0*P(-1) -function parsers.keq_to_hash(str) - if str and str~="" then - return lpegmatch(pattern,str) - else - return {} - end -end -local defaultspecification={ separator=",",quote='"' } -function parsers.csvsplitter(specification) - specification=specification and setmetatableindex(specification,defaultspecification) or defaultspecification - local separator=specification.separator - local quotechar=specification.quote - local separator=S(separator~="" and separator or ",") - local whatever=C((1-separator-newline)^0) - if quotechar and quotechar~="" then - local quotedata=nil - for chr in gmatch(quotechar,".") do - local quotechar=P(chr) - local quoteword=quotechar*C((1-quotechar)^0)*quotechar - if quotedata then - quotedata=quotedata+quoteword - else - quotedata=quoteword - end - end - whatever=quotedata+whatever - end - local parser=Ct((Ct(whatever*(separator*whatever)^0)*S("\n\r")^1)^0 ) - return function(data) - return lpegmatch(parser,data) - end -end -function parsers.rfc4180splitter(specification) - specification=specification and setmetatableindex(specification,defaultspecification) or defaultspecification - local separator=specification.separator - local quotechar=P(specification.quote) - local dquotechar=quotechar*quotechar -/specification.quote - local separator=S(separator~="" and separator or ",") - local escaped=quotechar*Cs((dquotechar+(1-quotechar))^0)*quotechar - local non_escaped=C((1-quotechar-newline-separator)^1) - local field=escaped+non_escaped+Cc("") - local record=Ct(field*(separator*field)^1) - local headerline=record*Cp() - local wholeblob=Ct((newline^(specification.strict and -1 or 1)*record)^0) - return function(data,getheader) - if getheader then - local header,position=lpegmatch(headerline,data) - local data=lpegmatch(wholeblob,data,position) - return data,header - else - return lpegmatch(wholeblob,data) - end - end -end -local function ranger(first,last,n,action) - if not first then - elseif last==true then - for i=first,n or first do - action(i) - end - elseif last then - for i=first,last do - action(i) - end - else - action(first) - end -end -local cardinal=lpegpatterns.cardinal/tonumber -local spacers=lpegpatterns.spacer^0 -local endofstring=lpegpatterns.endofstring -local stepper=spacers*(C(cardinal)*(spacers*S(":-")*spacers*(C(cardinal)+Cc(true) )+Cc(false) )*Carg(1)*Carg(2)/ranger*S(", ")^0 )^1 -local stepper=spacers*(C(cardinal)*(spacers*S(":-")*spacers*(C(cardinal)+(P("*")+endofstring)*Cc(true) )+Cc(false) )*Carg(1)*Carg(2)/ranger*S(", ")^0 )^1*endofstring -function parsers.stepper(str,n,action) - if type(n)=="function" then - lpegmatch(stepper,str,1,false,n or print) - else - lpegmatch(stepper,str,1,n,action or print) - end -end -local pattern_math=Cs((P("%")/"\\percent "+P("^")*Cc("{")*lpegpatterns.integer*Cc("}")+anything)^0) -local pattern_text=Cs((P("%")/"\\percent "+(P("^")/"\\high")*Cc("{")*lpegpatterns.integer*Cc("}")+anything)^0) -patterns.unittotex=pattern -function parsers.unittotex(str,textmode) - return lpegmatch(textmode and pattern_text or pattern_math,str) -end -local pattern=Cs((P("^")/"<sup>"*lpegpatterns.integer*Cc("</sup>")+anything)^0) -function parsers.unittoxml(str) - return lpegmatch(pattern,str) -end -local cache={} -local spaces=lpegpatterns.space^0 -local dummy=function() end -setmetatableindex(cache,function(t,k) - local separator=P(k) - local value=(1-separator)^0 - local pattern=spaces*C(value)*separator^0*Cp() - t[k]=pattern - return pattern -end) -local commalistiterator=cache[","] -function utilities.parsers.iterator(str,separator) - local n=#str - if n==0 then - return dummy - else - local pattern=separator and cache[separator] or commalistiterator - local p=1 - return function() - if p<=n then - local s,e=lpegmatch(pattern,str,p) - if e then - p=e - return s - end - end - end - end -end -local function initialize(t,name) - local source=t[name] - if source then - local result={} - for k,v in next,t[name] do - result[k]=v - end - return result - else - return {} - end -end -local function fetch(t,name) - return t[name] or {} -end -local function process(result,more) - for k,v in next,more do - result[k]=v - end - return result -end -local name=C((1-S(", "))^1) -local parser=(Carg(1)*name/initialize)*(S(", ")^1*(Carg(1)*name/fetch))^0 -local merge=Cf(parser,process) -function utilities.parsers.mergehashes(hash,list) - return lpegmatch(merge,list,1,hash) -end -function utilities.parsers.runtime(time) - if not time then - time=os.runtime() - end - local days=div(time,24*60*60) - time=mod(time,24*60*60) - local hours=div(time,60*60) - time=mod(time,60*60) - local minutes=div(time,60) - local seconds=mod(time,60) - return days,hours,minutes,seconds -end -local spacing=whitespace^0 -local apply=P("->") -local method=C((1-apply)^1) -local token=lbrace*C((1-rbrace)^1)*rbrace+C(anything^1) -local pattern=spacing*(method*spacing*apply+Carg(1))*spacing*token -function utilities.parsers.splitmethod(str,default) - if str then - return lpegmatch(pattern,str,1,default or false) - else - return default or false,"" - end -end - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['util-dim']={ - version=1.001, - comment="support for dimensions", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local format,match,gsub,type,setmetatable=string.format,string.match,string.gsub,type,setmetatable -local P,S,R,Cc,C,lpegmatch=lpeg.P,lpeg.S,lpeg.R,lpeg.Cc,lpeg.C,lpeg.match -local allocate=utilities.storage.allocate -local setmetatableindex=table.setmetatableindex -local formatters=string.formatters -local texget=tex and tex.get or function() return 65536*10*100 end -local p_stripzeros=lpeg.patterns.stripzeros -number=number or {} -local number=number -number.tonumberf=function(n) return lpegmatch(p_stripzeros,format("%.20f",n)) end -number.tonumberg=function(n) return format("%.20g",n) end -local dimenfactors=allocate { - ["pt"]=1/65536, - ["in"]=(100/7227)/65536, - ["cm"]=(254/7227)/65536, - ["mm"]=(2540/7227)/65536, - ["sp"]=1, - ["bp"]=(7200/7227)/65536, - ["pc"]=(1/12)/65536, - ["dd"]=(1157/1238)/65536, - ["cc"]=(1157/14856)/65536, - ["nd"]=(20320/21681)/65536, - ["nc"]=(5080/65043)/65536 -} -local f_none=formatters["%s%s"] -local f_true=formatters["%0.5F%s"] -local function numbertodimen(n,unit,fmt) - if type(n)=='string' then - return n - else - unit=unit or 'pt' - n=n*dimenfactors[unit] - if not fmt then - fmt=f_none(n,unit) - elseif fmt==true then - fmt=f_true(n,unit) - else - return formatters[fmt](n,unit) - end - end -end -number.maxdimen=1073741823 -number.todimen=numbertodimen -number.dimenfactors=dimenfactors -function number.topoints (n,fmt) return numbertodimen(n,"pt",fmt) end -function number.toinches (n,fmt) return numbertodimen(n,"in",fmt) end -function number.tocentimeters (n,fmt) return numbertodimen(n,"cm",fmt) end -function number.tomillimeters (n,fmt) return numbertodimen(n,"mm",fmt) end -function number.toscaledpoints(n,fmt) return numbertodimen(n,"sp",fmt) end -function number.toscaledpoints(n) return n.."sp" end -function number.tobasepoints (n,fmt) return numbertodimen(n,"bp",fmt) end -function number.topicas (n,fmt) return numbertodimen(n "pc",fmt) end -function number.todidots (n,fmt) return numbertodimen(n,"dd",fmt) end -function number.tociceros (n,fmt) return numbertodimen(n,"cc",fmt) end -function number.tonewdidots (n,fmt) return numbertodimen(n,"nd",fmt) end -function number.tonewciceros (n,fmt) return numbertodimen(n,"nc",fmt) end -local amount=(S("+-")^0*R("09")^0*P(".")^0*R("09")^0)+Cc("0") -local unit=R("az")^1+P("%") -local dimenpair=amount/tonumber*(unit^1/dimenfactors+Cc(1)) -lpeg.patterns.dimenpair=dimenpair -local splitter=amount/tonumber*C(unit^1) -function number.splitdimen(str) - return lpegmatch(splitter,str) -end -setmetatableindex(dimenfactors,function(t,s) - return false -end) -local stringtodimen -local amount=S("+-")^0*R("09")^0*S(".,")^0*R("09")^0 -local unit=P("pt")+P("cm")+P("mm")+P("sp")+P("bp")+P("in")+P("pc")+P("dd")+P("cc")+P("nd")+P("nc") -local validdimen=amount*unit -lpeg.patterns.validdimen=validdimen -local dimensions={} -function dimensions.__add(a,b) - local ta,tb=type(a),type(b) - if ta=="string" then a=stringtodimen(a) elseif ta=="table" then a=a[1] end - if tb=="string" then b=stringtodimen(b) elseif tb=="table" then b=b[1] end - return setmetatable({ a+b },dimensions) -end -function dimensions.__sub(a,b) - local ta,tb=type(a),type(b) - if ta=="string" then a=stringtodimen(a) elseif ta=="table" then a=a[1] end - if tb=="string" then b=stringtodimen(b) elseif tb=="table" then b=b[1] end - return setmetatable({ a-b },dimensions) -end -function dimensions.__mul(a,b) - local ta,tb=type(a),type(b) - if ta=="string" then a=stringtodimen(a) elseif ta=="table" then a=a[1] end - if tb=="string" then b=stringtodimen(b) elseif tb=="table" then b=b[1] end - return setmetatable({ a*b },dimensions) -end -function dimensions.__div(a,b) - local ta,tb=type(a),type(b) - if ta=="string" then a=stringtodimen(a) elseif ta=="table" then a=a[1] end - if tb=="string" then b=stringtodimen(b) elseif tb=="table" then b=b[1] end - return setmetatable({ a/b },dimensions) -end -function dimensions.__unm(a) - local ta=type(a) - if ta=="string" then a=stringtodimen(a) elseif ta=="table" then a=a[1] end - return setmetatable({-a },dimensions) -end -function dimensions.__lt(a,b) - return a[1]<b[1] -end -function dimensions.__eq(a,b) - return a[1]==b[1] -end -function dimensions.__tostring(a) - return a[1]/65536 .."pt" -end -function dimensions.__index(tab,key) - local d=dimenfactors[key] - if not d then - error("illegal property of dimen: "..key) - d=1 - end - return 1/d -end - dimenfactors["ex"]=4*1/65536 - dimenfactors["em"]=10*1/65536 -local known={} setmetatable(known,{ __mode="v" }) -function dimen(a) - if a then - local ta=type(a) - if ta=="string" then - local k=known[a] - if k then - a=k - else - local value,unit=lpegmatch(dimenpair,a) - if value and unit then - k=value/unit - else - k=0 - end - known[a]=k - a=k - end - elseif ta=="table" then - a=a[1] - end - return setmetatable({ a },dimensions) - else - return setmetatable({ 0 },dimensions) - end -end -function string.todimen(str) - if type(str)=="number" then - return str - else - local k=known[str] - if not k then - local value,unit=lpegmatch(dimenpair,str) - if value and unit then - k=value/unit - else - k=0 - end - known[str]=k - end - return k - end -end -stringtodimen=string.todimen -function number.toscaled(d) - return format("%0.5f",d/2^16) -end -function number.percent(n,d) - d=d or texget("hsize") - if type(d)=="string" then - d=stringtodimen(d) - end - return (n/100)*d -end -number["%"]=number.percent - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['util-jsn']={ - version=1.001, - comment="companion to m-json.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local P,V,R,S,C,Cc,Cs,Ct,Cf,Cg=lpeg.P,lpeg.V,lpeg.R,lpeg.S,lpeg.C,lpeg.Cc,lpeg.Cs,lpeg.Ct,lpeg.Cf,lpeg.Cg -local lpegmatch=lpeg.match -local format=string.format -local utfchar=utf.char -local concat=table.concat -local tonumber,tostring,rawset,type=tonumber,tostring,rawset,type -local json=utilities.json or {} -utilities.json=json -local lbrace=P("{") -local rbrace=P("}") -local lparent=P("[") -local rparent=P("]") -local comma=P(",") -local colon=P(":") -local dquote=P('"') -local whitespace=lpeg.patterns.whitespace -local optionalws=whitespace^0 -local escapes={ - ["b"]="\010", - ["f"]="\014", - ["n"]="\n", - ["r"]="\r", - ["t"]="\t", -} -local escape_un=C(P("\\u")/"0x"*S("09","AF","af"))/function(s) return utfchar(tonumber(s)) end -local escape_bs=P([[\]])/""*(P(1)/escapes) -local jstring=dquote*Cs((escape_un+escape_bs+(1-dquote))^0)*dquote -local jtrue=P("true")*Cc(true) -local jfalse=P("false")*Cc(false) -local jnull=P("null")*Cc(nil) -local jnumber=(1-whitespace-rparent-rbrace-comma)^1/tonumber -local key=jstring -local jsonconverter={ "value", - object=lbrace*Cf(Ct("")*V("pair")*(comma*V("pair"))^0,rawset)*rbrace, - pair=Cg(optionalws*key*optionalws*colon*V("value")), - array=Ct(lparent*V("value")*(comma*V("value"))^0*rparent), - value=optionalws*(jstring+V("object")+V("array")+jtrue+jfalse+jnull+jnumber+#rparent)*optionalws, -} -function json.tolua(str) - return lpegmatch(jsonconverter,str) -end -local function tojson(value,t) - local kind=type(value) - if kind=="table" then - local done=false - local size=#value - if size==0 then - for k,v in next,value do - if done then - t[#t+1]="," - else - t[#t+1]="{" - done=true - end - t[#t+1]=format("%q:",k) - tojson(v,t) - end - if done then - t[#t+1]="}" - else - t[#t+1]="{}" - end - elseif size==1 then - t[#t+1]="[" - tojson(value[1],t) - t[#t+1]="]" - else - for i=1,size do - if done then - t[#t+1]="," - else - t[#t+1]="[" - done=true - end - tojson(value[i],t) - end - t[#t+1]="]" - end - elseif kind=="string" then - t[#t+1]=format("%q",value) - elseif kind=="number" then - t[#t+1]=value - elseif kind=="boolean" then - t[#t+1]=tostring(value) - end - return t -end -function json.tostring(value) - local kind=type(value) - if kind=="table" then - return concat(tojson(value,{}),"") - elseif kind=="string" or kind=="number" then - return value - else - return tostring(value) - end -end - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['trac-inf']={ - version=1.001, - comment="companion to trac-inf.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local type,tonumber,select=type,tonumber,select -local format,lower,find=string.format,string.lower,string.find -local concat=table.concat -local clock=os.gettimeofday or os.clock -local setmetatableindex=table.setmetatableindex -local serialize=table.serialize -local formatters=string.formatters -statistics=statistics or {} -local statistics=statistics -statistics.enable=true -statistics.threshold=0.01 -local statusinfo,n,registered,timers={},0,{},{} -setmetatableindex(timers,function(t,k) - local v={ timing=0,loadtime=0 } - t[k]=v - return v -end) -local function hastiming(instance) - return instance and timers[instance] -end -local function resettiming(instance) - timers[instance or "notimer"]={ timing=0,loadtime=0 } -end -local function starttiming(instance) - local timer=timers[instance or "notimer"] - local it=timer.timing or 0 - if it==0 then - timer.starttime=clock() - if not timer.loadtime then - timer.loadtime=0 - end - end - timer.timing=it+1 -end -local function stoptiming(instance) - local timer=timers[instance or "notimer"] - local it=timer.timing - if it>1 then - timer.timing=it-1 - else - local starttime=timer.starttime - if starttime then - local stoptime=clock() - local loadtime=stoptime-starttime - timer.stoptime=stoptime - timer.loadtime=timer.loadtime+loadtime - timer.timing=0 - return loadtime - end - end - return 0 -end -local function elapsed(instance) - if type(instance)=="number" then - return instance or 0 - else - local timer=timers[instance or "notimer"] - return timer and timer.loadtime or 0 - end -end -local function elapsedtime(instance) - return format("%0.3f",elapsed(instance)) -end -local function elapsedindeed(instance) - return elapsed(instance)>statistics.threshold -end -local function elapsedseconds(instance,rest) - if elapsedindeed(instance) then - return format("%0.3f seconds %s",elapsed(instance),rest or "") - end -end -statistics.hastiming=hastiming -statistics.resettiming=resettiming -statistics.starttiming=starttiming -statistics.stoptiming=stoptiming -statistics.elapsed=elapsed -statistics.elapsedtime=elapsedtime -statistics.elapsedindeed=elapsedindeed -statistics.elapsedseconds=elapsedseconds -function statistics.register(tag,fnc) - if statistics.enable and type(fnc)=="function" then - local rt=registered[tag] or (#statusinfo+1) - statusinfo[rt]={ tag,fnc } - registered[tag]=rt - if #tag>n then n=#tag end - end -end -local report=logs.reporter("mkiv lua stats") -function statistics.show() - if statistics.enable then - local register=statistics.register - register("used platform",function() - return format("%s, type: %s, binary subtree: %s", - os.platform or "unknown",os.type or "unknown",environment.texos or "unknown") - end) - register("luatex banner",function() - return lower(status.banner) - end) - register("control sequences",function() - return format("%s of %s + %s",status.cs_count,status.hash_size,status.hash_extra) - end) - register("callbacks",function() - local total,indirect=status.callbacks or 0,status.indirect_callbacks or 0 - return format("%s direct, %s indirect, %s total",total-indirect,indirect,total) - end) - if jit then - local jitstatus={ jit.status() } - if jitstatus[1] then - register("luajit options",concat(jitstatus," ",2)) - end - end - register("lua properties",function() - local hashchar=tonumber(status.luatex_hashchars) - local hashtype=status.luatex_hashtype - local mask=lua.mask or "ascii" - return format("engine: %s, used memory: %s, hash type: %s, hash chars: min(%s,40), symbol mask: %s (%s)", - jit and "luajit" or "lua", - statistics.memused(), - hashtype or "default", - hashchar and 2^hashchar or "unknown", - mask, - mask=="utf" and "τεχ" or "tex") - end) - register("runtime",statistics.runtime) - logs.newline() - for i=1,#statusinfo do - local s=statusinfo[i] - local r=s[2]() - if r then - report("%s: %s",s[1],r) - end - end - statistics.enable=false - end -end -function statistics.memused() - local round=math.round or math.floor - return format("%s MB (ctx: %s MB)",round(collectgarbage("count")/1000),round(status.luastate_bytes/1000000)) -end -starttiming(statistics) -function statistics.formatruntime(runtime) - return format("%s seconds",runtime) -end -function statistics.runtime() - stoptiming(statistics) - return statistics.formatruntime(elapsedtime(statistics)) -end -local report=logs.reporter("system") -function statistics.timed(action) - starttiming("run") - action() - stoptiming("run") - report("total runtime: %s seconds",elapsedtime("run")) -end -function statistics.tracefunction(base,tag,...) - for i=1,select("#",...) do - local name=select(i,...) - local stat={} - local func=base[name] - setmetatableindex(stat,function(t,k) t[k]=0 return 0 end) - base[name]=function(n,k,v) stat[k]=stat[k]+1 return func(n,k,v) end - statistics.register(formatters["%s.%s"](tag,name),function() return serialize(stat,"calls") end) - end -end - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['util-lua']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - comment="the strip code is written by Peter Cawley", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local rep,sub,byte,dump,format=string.rep,string.sub,string.byte,string.dump,string.format -local load,loadfile,type=load,loadfile,type -utilities=utilities or {} -utilities.lua=utilities.lua or {} -local luautilities=utilities.lua -local report_lua=logs.reporter("system","lua") -local tracestripping=false -local forcestupidcompile=true -luautilities.stripcode=true -luautilities.alwaysstripcode=false -luautilities.nofstrippedchunks=0 -luautilities.nofstrippedbytes=0 -local strippedchunks={} -luautilities.strippedchunks=strippedchunks -luautilities.suffixes={ - tma="tma", - tmc=jit and "tmb" or "tmc", - lua="lua", - luc=jit and "lub" or "luc", - lui="lui", - luv="luv", - luj="luj", - tua="tua", - tuc="tuc", -} -local function register(name) - if tracestripping then - report_lua("stripped bytecode from %a",name or "unknown") - end - strippedchunks[#strippedchunks+1]=name - luautilities.nofstrippedchunks=luautilities.nofstrippedchunks+1 -end -local function stupidcompile(luafile,lucfile,strip) - local code=io.loaddata(luafile) - if code and code~="" then - code=load(code) - if code then - code=dump(code,strip and luautilities.stripcode or luautilities.alwaysstripcode) - if code and code~="" then - register(name) - io.savedata(lucfile,code) - return true,0 - end - else - report_lua("fatal error %a in file %a",1,luafile) - end - else - report_lua("fatal error %a in file %a",2,luafile) - end - return false,0 -end -function luautilities.loadedluacode(fullname,forcestrip,name) - name=name or fullname - local code,message - if environment.loadpreprocessedfile then - code,message=environment.loadpreprocessedfile(fullname) - else - code,message=loadfile(fullname) - end - if code then - code() - else - report_lua("loading of file %a failed:\n\t%s",fullname,message or "no message") - end - if forcestrip and luautilities.stripcode then - if type(forcestrip)=="function" then - forcestrip=forcestrip(fullname) - end - if forcestrip or luautilities.alwaysstripcode then - register(name) - return load(dump(code,true)),0 - else - return code,0 - end - elseif luautilities.alwaysstripcode then - register(name) - return load(dump(code,true)),0 - else - return code,0 - end -end -function luautilities.strippedloadstring(code,forcestrip,name) - local code,message=load(code) - if not code then - report_lua("loading of file %a failed:\n\t%s",name,message or "no message") - end - if forcestrip and luautilities.stripcode or luautilities.alwaysstripcode then - register(name) - return load(dump(code,true)),0 - else - return code,0 - end -end -function luautilities.compile(luafile,lucfile,cleanup,strip,fallback) - report_lua("compiling %a into %a",luafile,lucfile) - os.remove(lucfile) - local done=stupidcompile(luafile,lucfile,strip~=false) - if done then - report_lua("dumping %a into %a stripped",luafile,lucfile) - if cleanup==true and lfs.isfile(lucfile) and lfs.isfile(luafile) then - report_lua("removing %a",luafile) - os.remove(luafile) - end - end - return done -end -function luautilities.loadstripped(...) - local l=load(...) - if l then - return load(dump(l,true)) - end -end - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['util-deb']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local debug=require "debug" -local getinfo=debug.getinfo -local type,next,tostring=type,next,tostring -local format,find=string.format,string.find -local is_boolean=string.is_boolean -utilities=utilities or {} -local debugger=utilities.debugger or {} -utilities.debugger=debugger -local counters={} -local names={} -local report=logs.reporter("debugger") -local function hook() - local f=getinfo(2) - if f then - local n="unknown" - if f.what=="C" then - n=f.name or '<anonymous>' - if not names[n] then - names[n]=format("%42s",n) - end - else - n=f.name or f.namewhat or f.what - if not n or n=="" then - n="?" - end - if not names[n] then - names[n]=format("%42s : % 5i : %s",n,f.linedefined or 0,f.short_src or "unknown source") - end - end - counters[n]=(counters[n] or 0)+1 - end -end -function debugger.showstats(printer,threshold) - printer=printer or report - threshold=threshold or 0 - local total,grandtotal,functions=0,0,0 - local dataset={} - for name,count in next,counters do - dataset[#dataset+1]={ name,count } - end - table.sort(dataset,function(a,b) return a[2]==b[2] and b[1]>a[1] or a[2]>b[2] end) - for i=1,#dataset do - local d=dataset[i] - local name=d[1] - local count=d[2] - if count>threshold and not find(name,"for generator") then - printer(format("%8i %s\n",count,names[name])) - total=total+count - end - grandtotal=grandtotal+count - functions=functions+1 - end - printer("\n") - printer(format("functions : % 10i\n",functions)) - printer(format("total : % 10i\n",total)) - printer(format("grand total: % 10i\n",grandtotal)) - printer(format("threshold : % 10i\n",threshold)) -end -function debugger.savestats(filename,threshold) - local f=io.open(filename,'w') - if f then - debugger.showstats(function(str) f:write(str) end,threshold) - f:close() - end -end -function debugger.enable() - debug.sethook(hook,"c") -end -function debugger.disable() - debug.sethook() -end -local function showtraceback(rep) - local level=2 - local reporter=rep or report - while true do - local info=getinfo(level,"Sl") - if not info then - break - elseif info.what=="C" then - reporter("%2i : %s",level-1,"C function") - else - reporter("%2i : %s : %s",level-1,info.short_src,info.currentline) - end - level=level+1 - end -end -debugger.showtraceback=showtraceback - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['util-tpl']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -utilities.templates=utilities.templates or {} -local templates=utilities.templates -local trace_template=false trackers.register("templates.trace",function(v) trace_template=v end) -local report_template=logs.reporter("template") -local tostring=tostring -local format,sub,byte=string.format,string.sub,string.byte -local P,C,R,Cs,Cc,Carg,lpegmatch,lpegpatterns=lpeg.P,lpeg.C,lpeg.R,lpeg.Cs,lpeg.Cc,lpeg.Carg,lpeg.match,lpeg.patterns -local replacer -local function replacekey(k,t,how,recursive) - local v=t[k] - if not v then - if trace_template then - report_template("unknown key %a",k) - end - return "" - else - v=tostring(v) - if trace_template then - report_template("setting key %a to value %a",k,v) - end - if recursive then - return lpegmatch(replacer,v,1,t,how,recursive) - else - return v - end - end -end -local sqlescape=lpeg.replacer { - { "'","''" }, - { "\\","\\\\" }, - { "\r\n","\\n" }, - { "\r","\\n" }, -} -local sqlquoted=Cs(Cc("'")*sqlescape*Cc("'")) -lpegpatterns.sqlescape=sqlescape -lpegpatterns.sqlquoted=sqlquoted -local luaescape=lpegpatterns.luaescape -local escapers={ - lua=function(s) - return lpegmatch(luaescape,s) - end, - sql=function(s) - return lpegmatch(sqlescape,s) - end, -} -local quotedescapers={ - lua=function(s) - return format("%q",s) - end, - sql=function(s) - return lpegmatch(sqlquoted,s) - end, -} -local luaescaper=escapers.lua -local quotedluaescaper=quotedescapers.lua -local function replacekeyunquoted(s,t,how,recurse) - if how==false then - return replacekey(s,t,how,recurse) - else - local escaper=how and escapers[how] or luaescaper - return escaper(replacekey(s,t,how,recurse)) - end -end -local function replacekeyquoted(s,t,how,recurse) - if how==false then - return replacekey(s,t,how,recurse) - else - local escaper=how and quotedescapers[how] or quotedluaescaper - return escaper(replacekey(s,t,how,recurse)) - end -end -local function replaceoptional(l,m,r,t,how,recurse) - local v=t[l] - return v and v~="" and lpegmatch(replacer,r,1,t,how or "lua",recurse or false) or "" -end -local single=P("%") -local double=P("%%") -local lquoted=P("%[") -local rquoted=P("]%") -local lquotedq=P("%(") -local rquotedq=P(")%") -local escape=double/'%%' -local nosingle=single/'' -local nodouble=double/'' -local nolquoted=lquoted/'' -local norquoted=rquoted/'' -local nolquotedq=lquotedq/'' -local norquotedq=rquotedq/'' -local noloptional=P("%?")/'' -local noroptional=P("?%")/'' -local nomoptional=P(":")/'' -local args=Carg(1)*Carg(2)*Carg(3) -local key=nosingle*((C((1-nosingle )^1)*args)/replacekey )*nosingle -local quoted=nolquotedq*((C((1-norquotedq )^1)*args)/replacekeyquoted )*norquotedq -local unquoted=nolquoted*((C((1-norquoted )^1)*args)/replacekeyunquoted)*norquoted -local optional=noloptional*((C((1-nomoptional)^1)*nomoptional*C((1-noroptional)^1)*args)/replaceoptional)*noroptional -local any=P(1) - replacer=Cs((unquoted+quoted+escape+optional+key+any)^0) -local function replace(str,mapping,how,recurse) - if mapping and str then - return lpegmatch(replacer,str,1,mapping,how or "lua",recurse or false) or str - else - return str - end -end -templates.replace=replace -function templates.replacer(str,how,recurse) - return function(mapping) - return lpegmatch(replacer,str,1,mapping,how or "lua",recurse or false) or str - end -end -function templates.load(filename,mapping,how,recurse) - local data=io.loaddata(filename) or "" - if mapping and next(mapping) then - return replace(data,mapping,how,recurse) - else - return data - end -end -function templates.resolve(t,mapping,how,recurse) - if not mapping then - mapping=t - end - for k,v in next,t do - t[k]=replace(v,mapping,how,recurse) - end - return t -end - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['util-sta']={ - version=1.001, - comment="companion to util-ini.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local insert,remove,fastcopy,concat=table.insert,table.remove,table.fastcopy,table.concat -local format=string.format -local select,tostring=select,tostring -local trace_stacker=false trackers.register("stacker.resolve",function(v) trace_stacker=v end) -local stacker=stacker or {} -utilities.stacker=stacker -local function start(s,t,first,last) - if s.mode=="switch" then - local n=tostring(t[last]) - if trace_stacker then - s.report("start: %s",n) - end - return n - else - local r={} - for i=first,last do - r[#r+1]=tostring(t[i]) - end - local n=concat(r," ") - if trace_stacker then - s.report("start: %s",n) - end - return n - end -end -local function stop(s,t,first,last) - if s.mode=="switch" then - local n=tostring(false) - if trace_stacker then - s.report("stop: %s",n) - end - return n - else - local r={} - for i=last,first,-1 do - r[#r+1]=tostring(false) - end - local n=concat(r," ") - if trace_stacker then - s.report("stop: %s",n) - end - return n - end -end -local function change(s,t1,first1,last1,t2,first2,last2) - if s.mode=="switch" then - local n=tostring(t2[last2]) - if trace_stacker then - s.report("change: %s",n) - end - return n - else - local r={} - for i=last1,first1,-1 do - r[#r+1]=tostring(false) - end - local n=concat(r," ") - for i=first2,last2 do - r[#r+1]=tostring(t2[i]) - end - if trace_stacker then - s.report("change: %s",n) - end - return n - end -end -function stacker.new(name) - local report=logs.reporter("stacker",name or nil) - local s - local stack={} - local list={} - local ids={} - local hash={} - local hashing=true - local function push(...) - for i=1,select("#",...) do - insert(stack,(select(i,...))) - end - if hashing then - local c=concat(stack,"|") - local n=hash[c] - if not n then - n=#list+1 - hash[c]=n - list[n]=fastcopy(stack) - end - insert(ids,n) - return n - else - local n=#list+1 - list[n]=fastcopy(stack) - insert(ids,n) - return n - end - end - local function pop() - remove(stack) - remove(ids) - return ids[#ids] or s.unset or -1 - end - local function clean() - if #stack==0 then - if trace_stacker then - s.report("%s list entries, %s stack entries",#list,#stack) - end - end - end - local tops={} - local top=nil - local switch=nil - local function resolve_reset(mode) - if #tops>0 then - report("resetting %s left-over states of %a",#tops,name) - end - tops={} - top=nil - switch=nil - end - local function resolve_begin(mode) - if mode then - switch=mode=="switch" - else - switch=s.mode=="switch" - end - top={ switch=switch } - insert(tops,top) - end - local function resolve_step(ti) - local result=nil - local noftop=#top - if ti>0 then - local current=list[ti] - if current then - local noflist=#current - local nofsame=0 - if noflist>noftop then - for i=1,noflist do - if current[i]==top[i] then - nofsame=i - else - break - end - end - else - for i=1,noflist do - if current[i]==top[i] then - nofsame=i - else - break - end - end - end - local plus=nofsame+1 - if plus<=noftop then - if plus<=noflist then - if switch then - result=s.change(s,top,plus,noftop,current,nofsame,noflist) - else - result=s.change(s,top,plus,noftop,current,plus,noflist) - end - else - if switch then - result=s.change(s,top,plus,noftop,current,nofsame,noflist) - else - result=s.stop(s,top,plus,noftop) - end - end - elseif plus<=noflist then - if switch then - result=s.start(s,current,nofsame,noflist) - else - result=s.start(s,current,plus,noflist) - end - end - top=current - else - if 1<=noftop then - result=s.stop(s,top,1,noftop) - end - top={} - end - return result - else - if 1<=noftop then - result=s.stop(s,top,1,noftop) - end - top={} - return result - end - end - local function resolve_end() - if #tops>0 then - local result=s.stop(s,top,1,#top) - remove(tops) - top=tops[#tops] - switch=top and top.switch - return result - end - end - local function resolve(t) - resolve_begin() - for i=1,#t do - resolve_step(t[i]) - end - resolve_end() - end - s={ - name=name or "unknown", - unset=-1, - report=report, - start=start, - stop=stop, - change=change, - push=push, - pop=pop, - clean=clean, - resolve=resolve, - resolve_begin=resolve_begin, - resolve_step=resolve_step, - resolve_end=resolve_end, - resolve_reset=resolve_reset, - } - return s -end - -end -- closure diff --git a/tex/compat/lualibs/lualibs-extended.lua b/tex/compat/lualibs/lualibs-extended.lua deleted file mode 100644 index fdd50b80ba3112d8813a0d000124d0bfe1cc46e3..0000000000000000000000000000000000000000 --- a/tex/compat/lualibs/lualibs-extended.lua +++ /dev/null @@ -1,149 +0,0 @@ --- --- This is file `lualibs-extended.lua', --- generated with the docstrip utility. --- --- The original source files were: --- --- lualibs.dtx (with options: `extended') --- This is a generated file. --- --- Copyright (C) 2009--2016 by --- PRAGMA ADE / ConTeXt Development Team --- The LuaLaTeX Dev Team --- --- See ConTeXt's mreadme.pdf for the license. --- --- This work consists of the main source file lualibs.dtx --- and the derived files lualibs.lua, lualibs-basic.lua, --- and lualibs-extended.lua. --- --- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -lualibs = lualibs or { } - - -local lualibs_extended_module = { - name = "lualibs-extended", - version = 2.4, - date = "2016-04-06", - description = "ConTeXt Lua libraries -- extended collection.", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL & Elie Roux & Philipp Gesang", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "See ConTeXt's mreadme.pdf for the license", -} - -local stringformat = string.format -local loadmodule = lualibs.loadmodule -local texiowrite = texio.write -local texiowrite_nl = texio.write_nl - - -local error, logger, mklog -if luatexbase and luatexbase.provides_module then - --- TODO test how those work out when running tex - local __error,_,_,__logger = - luatexbase.provides_module(lualibs_extended_module) - error = __error - logger = __logger - mklog = function ( ) return logger end -else - mklog = function (t) - local prefix = stringformat("[%s] ", t) - return function (...) - texiowrite_nl(prefix) - texiowrite (stringformat(...)) - end - end - error = mklog"ERROR" - logger = mklog"INFO" -end - -local info = lualibs.info - - -local dummy_function = function ( ) end -local newline = function ( ) texiowrite_nl"" end - -local fake_logs = function (name) - return { - name = name, - enable = dummy_function, - disable = dummy_function, - reporter = mklog, - newline = newline - } -end - -local fake_trackers = function (name) - return { - name = name, - enable = dummy_function, - disable = dummy_function, - register = mklog, - newline = newline, - } -end - -local backup_store = { } - -local fake_context = function ( ) - if logs then backup_store.logs = logs end - if trackers then backup_store.trackers = trackers end - logs = fake_logs"logs" - trackers = fake_trackers"trackers" -end - -local unfake_context = function ( ) - if backup_store then - local bl, bt = backup_store.logs, backup_store.trackers - if bl then logs = bl end - if bt then trackers = bt end - end -end - -fake_context() - -local loaded = false -if lualibs.prefer_merged then - info"Loading merged package for collection “extended”." - loaded = loadmodule('lualibs-extended-merged.lua') -else - info"Ignoring merged packages." - info"Falling back to individual libraries from collection “extended”." -end - -if loaded == false then - loadmodule("lualibs-util-str.lua")--- string formatters (fast) - loadmodule("lualibs-util-fil.lua")--- extra file helpers - loadmodule("lualibs-util-tab.lua")--- extended table operations - loadmodule("lualibs-util-sto.lua")--- storage (hash allocation) - ----------("lualibs-util-pck.lua")---!packers; necessary? - ----------("lualibs-util-seq.lua")---!sequencers (function chaining) - ----------("lualibs-util-mrg.lua")---!only relevant in mtx-package - loadmodule("lualibs-util-prs.lua")--- miscellaneous parsers; cool. cool cool cool - ----------("lualibs-util-fmt.lua")---!column formatter (rarely used) - loadmodule("lualibs-util-dim.lua")--- conversions between dimensions - loadmodule("lualibs-util-jsn.lua")--- JSON parser - - ----------("lualibs-trac-set.lua")---!generalization of trackers - ----------("lualibs-trac-log.lua")---!logging - loadmodule("lualibs-trac-inf.lua")--- timing/statistics - loadmodule("lualibs-util-lua.lua")--- operations on lua bytecode - loadmodule("lualibs-util-deb.lua")--- extra debugging - loadmodule("lualibs-util-tpl.lua")--- templating - loadmodule("lualibs-util-sta.lua")--- stacker (for writing pdf) -end - -unfake_context() --- TODO check if this works at runtime - -lualibs.extended_loaded = true --- vim:tw=71:sw=2:ts=2:expandtab - --- --- End of File `lualibs-extended.lua'. diff --git a/tex/compat/lualibs/lualibs-file.lua b/tex/compat/lualibs/lualibs-file.lua deleted file mode 100644 index 7ed6370f2605609f03b96dbef0ce91be346e8df1..0000000000000000000000000000000000000000 --- a/tex/compat/lualibs/lualibs-file.lua +++ /dev/null @@ -1,698 +0,0 @@ -if not modules then modules = { } end modules ['l-file'] = { - version = 1.001, - comment = "companion to luat-lib.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- needs a cleanup - -file = file or { } -local file = file - -if not lfs then - lfs = optionalrequire("lfs") -end - --- -- see later --- --- if not lfs then --- --- lfs = { --- getcurrentdir = function() --- return "." --- end, --- attributes = function() --- return nil --- end, --- isfile = function(name) --- local f = io.open(name,'rb') --- if f then --- f:close() --- return true --- end --- end, --- isdir = function(name) --- print("you need to load lfs") --- return false --- end --- } --- --- elseif not lfs.isfile then --- --- local attributes = lfs.attributes --- --- function lfs.isdir(name) --- return attributes(name,"mode") == "directory" --- end --- --- function lfs.isfile(name) --- return attributes(name,"mode") == "file" --- end --- --- -- function lfs.isdir(name) --- -- local a = attributes(name) --- -- return a and a.mode == "directory" --- -- end --- --- -- function lfs.isfile(name) --- -- local a = attributes(name) --- -- return a and a.mode == "file" --- -- end --- --- end - -local insert, concat = table.insert, table.concat -local match, find, gmatch = string.match, string.find, string.gmatch -local lpegmatch = lpeg.match -local getcurrentdir, attributes = lfs.currentdir, lfs.attributes -local checkedsplit = string.checkedsplit - --- local patterns = file.patterns or { } --- file.patterns = patterns - -local P, R, S, C, Cs, Cp, Cc, Ct = lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.Cs, lpeg.Cp, lpeg.Cc, lpeg.Ct - --- better this way: - -local tricky = S("/\\") * P(-1) -local attributes = lfs.attributes - -if sandbox then - sandbox.redefine(lfs.isfile,"lfs.isfile") - sandbox.redefine(lfs.isdir, "lfs.isdir") -end - -function lfs.isdir(name) - if lpegmatch(tricky,name) then - return attributes(name,"mode") == "directory" - else - return attributes(name.."/.","mode") == "directory" - end -end - -function lfs.isfile(name) - return attributes(name,"mode") == "file" -end - -local colon = P(":") -local period = P(".") -local periods = P("..") -local fwslash = P("/") -local bwslash = P("\\") -local slashes = S("\\/") -local noperiod = 1-period -local noslashes = 1-slashes -local name = noperiod^1 -local suffix = period/"" * (1-period-slashes)^1 * -1 - ------ pattern = C((noslashes^0 * slashes^1)^1) -local pattern = C((1 - (slashes^1 * noslashes^1 * -1))^1) * P(1) -- there must be a more efficient way - -local function pathpart(name,default) - return name and lpegmatch(pattern,name) or default or "" -end - -local pattern = (noslashes^0 * slashes)^1 * C(noslashes^1) * -1 - -local function basename(name) - return name and lpegmatch(pattern,name) or name -end - --- print(pathpart("file")) --- print(pathpart("dir/file")) --- print(pathpart("/dir/file")) --- print(basename("file")) --- print(basename("dir/file")) --- print(basename("/dir/file")) - -local pattern = (noslashes^0 * slashes^1)^0 * Cs((1-suffix)^1) * suffix^0 - -local function nameonly(name) - return name and lpegmatch(pattern,name) or name -end - -local pattern = (noslashes^0 * slashes)^0 * (noperiod^1 * period)^1 * C(noperiod^1) * -1 - -local function suffixonly(name) - return name and lpegmatch(pattern,name) or "" -end - -local pattern = (noslashes^0 * slashes)^0 * noperiod^1 * ((period * C(noperiod^1))^1) * -1 + Cc("") - -local function suffixesonly(name) - if name then - return lpegmatch(pattern,name) - else - return "" - end -end - -file.pathpart = pathpart -file.basename = basename -file.nameonly = nameonly -file.suffixonly = suffixonly -file.suffix = suffixonly -file.suffixesonly = suffixesonly -file.suffixes = suffixesonly - -file.dirname = pathpart -- obsolete -file.extname = suffixonly -- obsolete - --- actually these are schemes - -local drive = C(R("az","AZ")) * colon -local path = C((noslashes^0 * slashes)^0) -local suffix = period * C(P(1-period)^0 * P(-1)) -local base = C((1-suffix)^0) -local rest = C(P(1)^0) - -drive = drive + Cc("") -path = path + Cc("") -base = base + Cc("") -suffix = suffix + Cc("") - -local pattern_a = drive * path * base * suffix -local pattern_b = path * base * suffix -local pattern_c = C(drive * path) * C(base * suffix) -- trick: two extra captures -local pattern_d = path * rest - -function file.splitname(str,splitdrive) - if not str then - -- error - elseif splitdrive then - return lpegmatch(pattern_a,str) -- returns drive, path, base, suffix - else - return lpegmatch(pattern_b,str) -- returns path, base, suffix - end -end - -function file.splitbase(str) - if str then - return lpegmatch(pattern_d,str) -- returns path, base+suffix (path has / appended, might change at some point) - else - return "", str -- assume no path - end -end - ----- stripslash = C((1 - P("/")^1*P(-1))^0) - -function file.nametotable(str,splitdrive) - if str then - local path, drive, subpath, name, base, suffix = lpegmatch(pattern_c,str) - -- if path ~= "" then - -- path = lpegmatch(stripslash,path) -- unfortunate hack, maybe this becomes default - -- end - if splitdrive then - return { - path = path, - drive = drive, - subpath = subpath, - name = name, - base = base, - suffix = suffix, - } - else - return { - path = path, - name = name, - base = base, - suffix = suffix, - } - end - end -end - --- print(file.splitname("file")) --- print(file.splitname("dir/file")) --- print(file.splitname("/dir/file")) --- print(file.splitname("file")) --- print(file.splitname("dir/file")) --- print(file.splitname("/dir/file")) - --- inspect(file.nametotable("file.ext")) --- inspect(file.nametotable("dir/file.ext")) --- inspect(file.nametotable("/dir/file.ext")) --- inspect(file.nametotable("file.ext")) --- inspect(file.nametotable("dir/file.ext")) --- inspect(file.nametotable("/dir/file.ext")) - ------ pattern = Cs(((period * noperiod^1 * -1) / "" + 1)^1) -local pattern = Cs(((period * (1-period-slashes)^1 * -1) / "" + 1)^1) - -function file.removesuffix(name) - return name and lpegmatch(pattern,name) -end - --- local pattern = (noslashes^0 * slashes)^0 * (noperiod^1 * period)^1 * Cp() * noperiod^1 * -1 --- --- function file.addsuffix(name, suffix) --- local p = lpegmatch(pattern,name) --- if p then --- return name --- else --- return name .. "." .. suffix --- end --- end - -local suffix = period/"" * (1-period-slashes)^1 * -1 -local pattern = Cs((noslashes^0 * slashes^1)^0 * ((1-suffix)^1)) * Cs(suffix) - -function file.addsuffix(filename,suffix,criterium) - if not filename or not suffix or suffix == "" then - return filename - elseif criterium == true then - return filename .. "." .. suffix - elseif not criterium then - local n, s = lpegmatch(pattern,filename) - if not s or s == "" then - return filename .. "." .. suffix - else - return filename - end - else - local n, s = lpegmatch(pattern,filename) - if s and s ~= "" then - local t = type(criterium) - if t == "table" then - -- keep if in criterium - for i=1,#criterium do - if s == criterium[i] then - return filename - end - end - elseif t == "string" then - -- keep if criterium - if s == criterium then - return filename - end - end - end - return (n or filename) .. "." .. suffix - end -end - --- print("1 " .. file.addsuffix("name","new") .. " -> name.new") --- print("2 " .. file.addsuffix("name.old","new") .. " -> name.old") --- print("3 " .. file.addsuffix("name.old","new",true) .. " -> name.old.new") --- print("4 " .. file.addsuffix("name.old","new","new") .. " -> name.new") --- print("5 " .. file.addsuffix("name.old","new","old") .. " -> name.old") --- print("6 " .. file.addsuffix("name.old","new","foo") .. " -> name.new") --- print("7 " .. file.addsuffix("name.old","new",{"foo","bar"}) .. " -> name.new") --- print("8 " .. file.addsuffix("name.old","new",{"old","bar"}) .. " -> name.old") - -local suffix = period * (1-period-slashes)^1 * -1 -local pattern = Cs((1-suffix)^0) - -function file.replacesuffix(name,suffix) - if name and suffix and suffix ~= "" then - return lpegmatch(pattern,name) .. "." .. suffix - else - return name - end -end - --- - -local reslasher = lpeg.replacer(P("\\"),"/") - -function file.reslash(str) - return str and lpegmatch(reslasher,str) -end - --- We should be able to use: --- --- local writable = P(1) * P("w") * Cc(true) --- --- function file.is_writable(name) --- local a = attributes(name) or attributes(pathpart(name,".")) --- return a and lpegmatch(writable,a.permissions) or false --- end --- --- But after some testing Taco and I came up with the more robust --- variant: - -function file.is_writable(name) - if not name then - -- error - elseif lfs.isdir(name) then - name = name .. "/m_t_x_t_e_s_t.tmp" - local f = io.open(name,"wb") - if f then - f:close() - os.remove(name) - return true - end - elseif lfs.isfile(name) then - local f = io.open(name,"ab") - if f then - f:close() - return true - end - else - local f = io.open(name,"ab") - if f then - f:close() - os.remove(name) - return true - end - end - return false -end - -local readable = P("r") * Cc(true) - -function file.is_readable(name) - if name then - local a = attributes(name) - return a and lpegmatch(readable,a.permissions) or false - else - return false - end -end - -file.isreadable = file.is_readable -- depricated -file.iswritable = file.is_writable -- depricated - -function file.size(name) - if name then - local a = attributes(name) - return a and a.size or 0 - else - return 0 - end -end - -function file.splitpath(str,separator) -- string .. reslash is a bonus (we could do a direct split) - return str and checkedsplit(lpegmatch(reslasher,str),separator or io.pathseparator) -end - -function file.joinpath(tab,separator) -- table - return tab and concat(tab,separator or io.pathseparator) -- can have trailing // -end - -local someslash = S("\\/") -local stripper = Cs(P(fwslash)^0/"" * reslasher) -local isnetwork = someslash * someslash * (1-someslash) - + (1-fwslash-colon)^1 * colon -local isroot = fwslash^1 * -1 -local hasroot = fwslash^1 - -local reslasher = lpeg.replacer(S("\\/"),"/") -local deslasher = lpeg.replacer(S("\\/")^1,"/") - --- If we have a network or prefix then there is a change that we end up with two --- // in the middle ... we could prevent this if we (1) expand prefixes: and (2) --- split and rebuild as url. Of course we could assume no network paths (which --- makes sense) adn assume either mapped drives (windows) or mounts (unix) but --- then we still have to deal with urls ... anyhow, multiple // are never a real --- problem but just ugly. - --- function file.join(...) --- local lst = { ... } --- local one = lst[1] --- if lpegmatch(isnetwork,one) then --- local one = lpegmatch(reslasher,one) --- local two = lpegmatch(deslasher,concat(lst,"/",2)) --- if lpegmatch(hasroot,two) then --- return one .. two --- else --- return one .. "/" .. two --- end --- elseif lpegmatch(isroot,one) then --- local two = lpegmatch(deslasher,concat(lst,"/",2)) --- if lpegmatch(hasroot,two) then --- return two --- else --- return "/" .. two --- end --- elseif one == "" then --- return lpegmatch(stripper,concat(lst,"/",2)) --- else --- return lpegmatch(deslasher,concat(lst,"/")) --- end --- end - -function file.join(one, two, three, ...) - if not two then - return one == "" and one or lpegmatch(stripper,one) - end - if one == "" then - return lpegmatch(stripper,three and concat({ two, three, ... },"/") or two) - end - if lpegmatch(isnetwork,one) then - local one = lpegmatch(reslasher,one) - local two = lpegmatch(deslasher,three and concat({ two, three, ... },"/") or two) - if lpegmatch(hasroot,two) then - return one .. two - else - return one .. "/" .. two - end - elseif lpegmatch(isroot,one) then - local two = lpegmatch(deslasher,three and concat({ two, three, ... },"/") or two) - if lpegmatch(hasroot,two) then - return two - else - return "/" .. two - end - else - return lpegmatch(deslasher,concat({ one, two, three, ... },"/")) - end -end - --- or we can use this: --- --- function file.join(...) --- local n = select("#",...) --- local one = select(1,...) --- if n == 1 then --- return one == "" and one or lpegmatch(stripper,one) --- end --- if one == "" then --- return lpegmatch(stripper,n > 2 and concat({ ... },"/",2) or select(2,...)) --- end --- if lpegmatch(isnetwork,one) then --- local one = lpegmatch(reslasher,one) --- local two = lpegmatch(deslasher,n > 2 and concat({ ... },"/",2) or select(2,...)) --- if lpegmatch(hasroot,two) then --- return one .. two --- else --- return one .. "/" .. two --- end --- elseif lpegmatch(isroot,one) then --- local two = lpegmatch(deslasher,n > 2 and concat({ ... },"/",2) or select(2,...)) --- if lpegmatch(hasroot,two) then --- return two --- else --- return "/" .. two --- end --- else --- return lpegmatch(deslasher,concat({ ... },"/")) --- end --- end - --- print(file.join("c:/whatever")) --- print(file.join("c:/whatever","name")) --- print(file.join("//","/y")) --- print(file.join("/","/y")) --- print(file.join("","/y")) --- print(file.join("/x/","/y")) --- print(file.join("x/","/y")) --- print(file.join("http://","/y")) --- print(file.join("http://a","/y")) --- print(file.join("http:///a","/y")) --- print(file.join("//nas-1","/y")) --- print(file.join("//nas-1/a/b/c","/y")) --- print(file.join("\\\\nas-1\\a\\b\\c","\\y")) - --- The previous one fails on "a.b/c" so Taco came up with a split based --- variant. After some skyping we got it sort of compatible with the old --- one. After that the anchoring to currentdir was added in a better way. --- Of course there are some optimizations too. Finally we had to deal with --- windows drive prefixes and things like sys://. Eventually gsubs and --- finds were replaced by lpegs. - -local drivespec = R("az","AZ")^1 * colon -local anchors = fwslash - + drivespec -local untouched = periods - + (1-period)^1 * P(-1) -local mswindrive = Cs(drivespec * (bwslash/"/" + fwslash)^0) -local mswinuncpath = (bwslash + fwslash) * (bwslash + fwslash) * Cc("//") -local splitstarter = (mswindrive + mswinuncpath + Cc(false)) - * Ct(lpeg.splitat(S("/\\")^1)) -local absolute = fwslash - -function file.collapsepath(str,anchor) -- anchor: false|nil, true, "." - if not str then - return - end - if anchor == true and not lpegmatch(anchors,str) then - str = getcurrentdir() .. "/" .. str - end - if str == "" or str =="." then - return "." - elseif lpegmatch(untouched,str) then - return lpegmatch(reslasher,str) - end - local starter, oldelements = lpegmatch(splitstarter,str) - local newelements = { } - local i = #oldelements - while i > 0 do - local element = oldelements[i] - if element == '.' then - -- do nothing - elseif element == '..' then - local n = i - 1 - while n > 0 do - local element = oldelements[n] - if element ~= '..' and element ~= '.' then - oldelements[n] = '.' - break - else - n = n - 1 - end - end - if n < 1 then - insert(newelements,1,'..') - end - elseif element ~= "" then - insert(newelements,1,element) - end - i = i - 1 - end - if #newelements == 0 then - return starter or "." - elseif starter then - return starter .. concat(newelements, '/') - elseif lpegmatch(absolute,str) then - return "/" .. concat(newelements,'/') - else - newelements = concat(newelements, '/') - if anchor == "." and find(str,"^%./") then - return "./" .. newelements - else - return newelements - end - end -end - --- local function test(str,...) --- print(string.format("%-20s %-15s %-30s %-20s",str,file.collapsepath(str),file.collapsepath(str,true),file.collapsepath(str,"."))) --- end --- test("a/b.c/d") test("b.c/d") test("b.c/..") --- test("/") test("c:/..") test("sys://..") --- test("") test("./") test(".") test("..") test("./..") test("../..") --- test("a") test("./a") test("/a") test("a/../..") --- test("a/./b/..") test("a/aa/../b/bb") test("a/.././././b/..") test("a/./././b/..") --- test("a/b/c/../..") test("./a/b/c/../..") test("a/b/c/../..") --- test("./a") --- test([[\\a.b.c\d\e]]) - -local validchars = R("az","09","AZ","--","..") -local pattern_a = lpeg.replacer(1-validchars) -local pattern_a = Cs((validchars + P(1)/"-")^1) -local whatever = P("-")^0 / "" -local pattern_b = Cs(whatever * (1 - whatever * -1)^1) - -function file.robustname(str,strict) - if str then - str = lpegmatch(pattern_a,str) or str - if strict then - return lpegmatch(pattern_b,str) or str -- two step is cleaner (less backtracking) - else - return str - end - end -end - -file.readdata = io.loaddata -file.savedata = io.savedata - -function file.copy(oldname,newname) - if oldname and newname then - local data = io.loaddata(oldname) - if data and data ~= "" then - file.savedata(newname,data) - end - end -end - --- also rewrite previous - -local letter = R("az","AZ") + S("_-+") -local separator = P("://") - -local qualified = period^0 * fwslash - + letter * colon - + letter^1 * separator - + letter^1 * fwslash -local rootbased = fwslash - + letter * colon - -lpeg.patterns.qualified = qualified -lpeg.patterns.rootbased = rootbased - --- ./name ../name /name c: :// name/name - -function file.is_qualified_path(filename) - return filename and lpegmatch(qualified,filename) ~= nil -end - -function file.is_rootbased_path(filename) - return filename and lpegmatch(rootbased,filename) ~= nil -end - --- function test(t) for k, v in next, t do print(v, "=>", file.splitname(v)) end end --- --- test { "c:", "c:/aa", "c:/aa/bb", "c:/aa/bb/cc", "c:/aa/bb/cc.dd", "c:/aa/bb/cc.dd.ee" } --- test { "c:", "c:aa", "c:aa/bb", "c:aa/bb/cc", "c:aa/bb/cc.dd", "c:aa/bb/cc.dd.ee" } --- test { "/aa", "/aa/bb", "/aa/bb/cc", "/aa/bb/cc.dd", "/aa/bb/cc.dd.ee" } --- test { "aa", "aa/bb", "aa/bb/cc", "aa/bb/cc.dd", "aa/bb/cc.dd.ee" } - --- -- maybe: --- --- if os.type == "windows" then --- local currentdir = getcurrentdir --- function getcurrentdir() --- return lpegmatch(reslasher,currentdir()) --- end --- end - --- for myself: - -function file.strip(name,dir) - if name then - local b, a = match(name,"^(.-)" .. dir .. "(.*)$") - return a ~= "" and a or name - end -end - --- local debuglist = { --- "pathpart", "basename", "nameonly", "suffixonly", "suffix", "dirname", "extname", --- "addsuffix", "removesuffix", "replacesuffix", "join", --- "strip","collapsepath", "joinpath", "splitpath", --- } - --- for i=1,#debuglist do --- local name = debuglist[i] --- local f = file[name] --- file[name] = function(...) --- print(name,f(...)) --- return f(...) --- end --- end - --- a goodie: a dumb version of mkdirs (not used in context itself, only --- in generic usage) - -function lfs.mkdirs(path) - local full = "" - for sub in gmatch(path,"(/*[^\\/]+)") do -- accepts leading c: and / - full = full .. sub - -- lfs.isdir("/foo") mistakenly returns true on windows so - -- so we don't test and just make as that one is not too picky - lfs.mkdir(full) - end -end diff --git a/tex/compat/lualibs/lualibs-function.lua b/tex/compat/lualibs/lualibs-function.lua deleted file mode 100644 index 7ded8ceecd5c61e66e7beca0474a17a2781666ad..0000000000000000000000000000000000000000 --- a/tex/compat/lualibs/lualibs-function.lua +++ /dev/null @@ -1,11 +0,0 @@ -if not modules then modules = { } end modules ['l-functions'] = { - version = 1.001, - comment = "companion to luat-lib.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -functions = functions or { } - -function functions.dummy() end diff --git a/tex/compat/lualibs/lualibs-gzip.lua b/tex/compat/lualibs/lualibs-gzip.lua deleted file mode 100644 index 5100e47222ca85f79455bd1814377f0fef7aea6f..0000000000000000000000000000000000000000 --- a/tex/compat/lualibs/lualibs-gzip.lua +++ /dev/null @@ -1,54 +0,0 @@ -if not modules then modules = { } end modules ['l-gzip'] = { - version = 1.001, - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -if not gzip then - - -- no fallback yet - - return - -end - -local suffix, suffixes = file.suffix, file.suffixes - -function gzip.load(filename) - local f = io.open(filename,"rb") - if not f then - -- invalid file - elseif suffix(filename) == "gz" then - f:close() - local g = gzip.open(filename,"rb") - if g then - local str = g:read("*all") - g:close() - return str - end - else - local str = f:read("*all") - f:close() - return str - end -end - -function gzip.save(filename,data) - if suffix(filename) ~= "gz" then - filename = filename .. ".gz" - end - local f = io.open(filename,"wb") - if f then - local s = zlib.compress(data or "",9,nil,15+16) - f:write(s) - f:close() - return #s - end -end - -function gzip.suffix(filename) - local suffix, extra = suffixes(filename) - local gzipped = extra == "gz" - return suffix, gzipped -end diff --git a/tex/compat/lualibs/lualibs-io.lua b/tex/compat/lualibs/lualibs-io.lua deleted file mode 100644 index a91d44d8776692cb2dee1eca4bab4d72edb6603b..0000000000000000000000000000000000000000 --- a/tex/compat/lualibs/lualibs-io.lua +++ /dev/null @@ -1,358 +0,0 @@ -if not modules then modules = { } end modules ['l-io'] = { - version = 1.001, - comment = "companion to luat-lib.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -local io = io -local byte, find, gsub, format = string.byte, string.find, string.gsub, string.format -local concat = table.concat -local floor = math.floor -local type = type - -if string.find(os.getenv("PATH"),";",1,true) then - io.fileseparator, io.pathseparator = "\\", ";" -else - io.fileseparator, io.pathseparator = "/" , ":" -end - -local function readall(f) - return f:read("*all") -end - --- The next one is upto 50% faster on large files and less memory consumption due --- to less intermediate large allocations. This phenomena was discussed on the --- luatex dev list. - -local function readall(f) - local size = f:seek("end") - if size == 0 then - return "" - elseif size < 1024*1024 then - f:seek("set",0) - return f:read('*all') - else - local done = f:seek("set",0) - local step - if size < 1024*1024 then - step = 1024 * 1024 - elseif size > 16*1024*1024 then - step = 16*1024*1024 - else - step = floor(size/(1024*1024)) * 1024 * 1024 / 8 - end - local data = { } - while true do - local r = f:read(step) - if not r then - return concat(data) - else - data[#data+1] = r - end - end - end -end - -io.readall = readall - -function io.loaddata(filename,textmode) -- return nil if empty - local f = io.open(filename,(textmode and 'r') or 'rb') - if f then - -- local data = f:read('*all') - local data = readall(f) - f:close() - if #data > 0 then - return data - end - end -end - -function io.savedata(filename,data,joiner) - local f = io.open(filename,"wb") - if f then - if type(data) == "table" then - f:write(concat(data,joiner or "")) - elseif type(data) == "function" then - data(f) - else - f:write(data or "") - end - f:close() - io.flush() - return true - else - return false - end -end - --- we can also chunk this one if needed: io.lines(filename,chunksize,"*l") - -function io.loadlines(filename,n) -- return nil if empty - local f = io.open(filename,'r') - if not f then - -- no file - elseif n then - local lines = { } - for i=1,n do - local line = f:read("*lines") - if line then - lines[#lines+1] = line - else - break - end - end - f:close() - lines = concat(lines,"\n") - if #lines > 0 then - return lines - end - else - local line = f:read("*line") or "" - f:close() - if #line > 0 then - return line - end - end -end - -function io.loadchunk(filename,n) - local f = io.open(filename,'rb') - if f then - local data = f:read(n or 1024) - f:close() - if #data > 0 then - return data - end - end -end - -function io.exists(filename) - local f = io.open(filename) - if f == nil then - return false - else - f:close() - return true - end -end - -function io.size(filename) - local f = io.open(filename) - if f == nil then - return 0 - else - local s = f:seek("end") - f:close() - return s - end -end - -function io.noflines(f) - if type(f) == "string" then - local f = io.open(filename) - if f then - local n = f and io.noflines(f) or 0 - f:close() - return n - else - return 0 - end - else - local n = 0 - for _ in f:lines() do - n = n + 1 - end - f:seek('set',0) - return n - end -end - -local nextchar = { - [ 4] = function(f) - return f:read(1,1,1,1) - end, - [ 2] = function(f) - return f:read(1,1) - end, - [ 1] = function(f) - return f:read(1) - end, - [-2] = function(f) - local a, b = f:read(1,1) - return b, a - end, - [-4] = function(f) - local a, b, c, d = f:read(1,1,1,1) - return d, c, b, a - end -} - -function io.characters(f,n) - if f then - return nextchar[n or 1], f - end -end - -local nextbyte = { - [4] = function(f) - local a, b, c, d = f:read(1,1,1,1) - if d then - return byte(a), byte(b), byte(c), byte(d) - end - end, - [3] = function(f) - local a, b, c = f:read(1,1,1) - if b then - return byte(a), byte(b), byte(c) - end - end, - [2] = function(f) - local a, b = f:read(1,1) - if b then - return byte(a), byte(b) - end - end, - [1] = function (f) - local a = f:read(1) - if a then - return byte(a) - end - end, - [-2] = function (f) - local a, b = f:read(1,1) - if b then - return byte(b), byte(a) - end - end, - [-3] = function(f) - local a, b, c = f:read(1,1,1) - if b then - return byte(c), byte(b), byte(a) - end - end, - [-4] = function(f) - local a, b, c, d = f:read(1,1,1,1) - if d then - return byte(d), byte(c), byte(b), byte(a) - end - end -} - -function io.bytes(f,n) - if f then - return nextbyte[n or 1], f - else - return nil, nil - end -end - -function io.ask(question,default,options) - while true do - io.write(question) - if options then - io.write(format(" [%s]",concat(options,"|"))) - end - if default then - io.write(format(" [%s]",default)) - end - io.write(format(" ")) - io.flush() - local answer = io.read() - answer = gsub(answer,"^%s*(.*)%s*$","%1") - if answer == "" and default then - return default - elseif not options then - return answer - else - for k=1,#options do - if options[k] == answer then - return answer - end - end - local pattern = "^" .. answer - for k=1,#options do - local v = options[k] - if find(v,pattern) then - return v - end - end - end - end -end - -local function readnumber(f,n,m) - if m then - f:seek("set",n) - n = m - end - if n == 1 then - return byte(f:read(1)) - elseif n == 2 then - local a, b = byte(f:read(2),1,2) - return 256 * a + b - elseif n == 3 then - local a, b, c = byte(f:read(3),1,3) - return 256*256 * a + 256 * b + c - elseif n == 4 then - local a, b, c, d = byte(f:read(4),1,4) - return 256*256*256 * a + 256*256 * b + 256 * c + d - elseif n == 8 then - local a, b = readnumber(f,4), readnumber(f,4) - return 256 * a + b - elseif n == 12 then - local a, b, c = readnumber(f,4), readnumber(f,4), readnumber(f,4) - return 256*256 * a + 256 * b + c - elseif n == -2 then - local b, a = byte(f:read(2),1,2) - return 256*a + b - elseif n == -3 then - local c, b, a = byte(f:read(3),1,3) - return 256*256 * a + 256 * b + c - elseif n == -4 then - local d, c, b, a = byte(f:read(4),1,4) - return 256*256*256 * a + 256*256 * b + 256*c + d - elseif n == -8 then - local h, g, f, e, d, c, b, a = byte(f:read(8),1,8) - return 256*256*256*256*256*256*256 * a + - 256*256*256*256*256*256 * b + - 256*256*256*256*256 * c + - 256*256*256*256 * d + - 256*256*256 * e + - 256*256 * f + - 256 * g + - h - else - return 0 - end -end - -io.readnumber = readnumber - -function io.readstring(f,n,m) - if m then - f:seek("set",n) - n = m - end - local str = gsub(f:read(n),"\000","") - return str -end - --- This works quite ok: --- --- function io.piped(command,writer) --- local pipe = io.popen(command) --- -- for line in pipe:lines() do --- -- print(line) --- -- end --- while true do --- local line = pipe:read(1) --- if not line then --- break --- elseif line ~= "\n" then --- writer(line) --- end --- end --- return pipe:close() -- ok, status, (error)code --- end diff --git a/tex/compat/lualibs/lualibs-lpeg.lua b/tex/compat/lualibs/lualibs-lpeg.lua deleted file mode 100644 index 959ca553eb8d2c7c0a54e72c06a8eb8df471f802..0000000000000000000000000000000000000000 --- a/tex/compat/lualibs/lualibs-lpeg.lua +++ /dev/null @@ -1,1173 +0,0 @@ -if not modules then modules = { } end modules ['l-lpeg'] = { - version = 1.001, - comment = "companion to luat-lib.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- lpeg 12 vs lpeg 10: slower compilation, similar parsing speed (i need to check --- if i can use new features like capture / 2 and .B (at first sight the xml --- parser is some 5% slower) - --- lpeg.P("abc") is faster than lpeg.P("a") * lpeg.P("b") * lpeg.P("c") - --- a new lpeg fails on a #(1-P(":")) test and really needs a + P(-1) - --- move utf -> l-unicode --- move string -> l-string or keep it here - -lpeg = require("lpeg") - --- The latest lpeg doesn't have print any more, and even the new ones are not --- available by default (only when debug mode is enabled), which is a pitty as --- as it helps nailing down bottlenecks. Performance seems comparable: some 10% --- slower pattern compilation, same parsing speed, although, --- --- local p = lpeg.C(lpeg.P(1)^0 * lpeg.P(-1)) --- local a = string.rep("123",100) --- lpeg.match(p,a) --- --- seems slower and is also still suboptimal (i.e. a match that runs from begin --- to end, one of the cases where string matchers win). - -if not lpeg.print then function lpeg.print(...) print(lpeg.pcode(...)) end end - --- tracing (only used when we encounter a problem in integration of lpeg in luatex) - --- some code will move to unicode and string - --- local lpmatch = lpeg.match --- local lpprint = lpeg.print --- local lpp = lpeg.P --- local lpr = lpeg.R --- local lps = lpeg.S --- local lpc = lpeg.C --- local lpb = lpeg.B --- local lpv = lpeg.V --- local lpcf = lpeg.Cf --- local lpcb = lpeg.Cb --- local lpcg = lpeg.Cg --- local lpct = lpeg.Ct --- local lpcs = lpeg.Cs --- local lpcc = lpeg.Cc --- local lpcmt = lpeg.Cmt --- local lpcarg = lpeg.Carg - --- function lpeg.match(l,...) print("LPEG MATCH") lpprint(l) return lpmatch(l,...) end - --- function lpeg.P (l) local p = lpp (l) print("LPEG P =") lpprint(l) return p end --- function lpeg.R (l) local p = lpr (l) print("LPEG R =") lpprint(l) return p end --- function lpeg.S (l) local p = lps (l) print("LPEG S =") lpprint(l) return p end --- function lpeg.C (l) local p = lpc (l) print("LPEG C =") lpprint(l) return p end --- function lpeg.B (l) local p = lpb (l) print("LPEG B =") lpprint(l) return p end --- function lpeg.V (l) local p = lpv (l) print("LPEG V =") lpprint(l) return p end --- function lpeg.Cf (l) local p = lpcf (l) print("LPEG Cf =") lpprint(l) return p end --- function lpeg.Cb (l) local p = lpcb (l) print("LPEG Cb =") lpprint(l) return p end --- function lpeg.Cg (l) local p = lpcg (l) print("LPEG Cg =") lpprint(l) return p end --- function lpeg.Ct (l) local p = lpct (l) print("LPEG Ct =") lpprint(l) return p end --- function lpeg.Cs (l) local p = lpcs (l) print("LPEG Cs =") lpprint(l) return p end --- function lpeg.Cc (l) local p = lpcc (l) print("LPEG Cc =") lpprint(l) return p end --- function lpeg.Cmt (l) local p = lpcmt (l) print("LPEG Cmt =") lpprint(l) return p end --- function lpeg.Carg (l) local p = lpcarg(l) print("LPEG Carg =") lpprint(l) return p end - -local type, next, tostring = type, next, tostring -local byte, char, gmatch, format = string.byte, string.char, string.gmatch, string.format ------ mod, div = math.mod, math.div -local floor = math.floor - -local P, R, S, V, Ct, C, Cs, Cc, Cp, Cmt = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc, lpeg.Cp, lpeg.Cmt -local lpegtype, lpegmatch, lpegprint = lpeg.type, lpeg.match, lpeg.print - --- let's start with an inspector: - -if setinspector then - setinspector("lpeg",function(v) if lpegtype(v) then lpegprint(v) return true end end) -end - --- Beware, we predefine a bunch of patterns here and one reason for doing so --- is that we get consistent behaviour in some of the visualizers. - -lpeg.patterns = lpeg.patterns or { } -- so that we can share -local patterns = lpeg.patterns - -local anything = P(1) -local endofstring = P(-1) -local alwaysmatched = P(true) - -patterns.anything = anything -patterns.endofstring = endofstring -patterns.beginofstring = alwaysmatched -patterns.alwaysmatched = alwaysmatched - -local sign = S('+-') -local zero = P('0') -local digit = R('09') -local octdigit = R("07") -local lowercase = R("az") -local uppercase = R("AZ") -local underscore = P("_") -local hexdigit = digit + lowercase + uppercase -local cr, lf, crlf = P("\r"), P("\n"), P("\r\n") ------ newline = crlf + S("\r\n") -- cr + lf -local newline = P("\r") * (P("\n") + P(true)) + P("\n") -- P("\r")^-1 * P("\n")^-1 -local escaped = P("\\") * anything -local squote = P("'") -local dquote = P('"') -local space = P(" ") -local period = P(".") -local comma = P(",") - -local utfbom_32_be = P('\000\000\254\255') -- 00 00 FE FF -local utfbom_32_le = P('\255\254\000\000') -- FF FE 00 00 -local utfbom_16_be = P('\254\255') -- FE FF -local utfbom_16_le = P('\255\254') -- FF FE -local utfbom_8 = P('\239\187\191') -- EF BB BF -local utfbom = utfbom_32_be + utfbom_32_le - + utfbom_16_be + utfbom_16_le - + utfbom_8 -local utftype = utfbom_32_be * Cc("utf-32-be") + utfbom_32_le * Cc("utf-32-le") - + utfbom_16_be * Cc("utf-16-be") + utfbom_16_le * Cc("utf-16-le") - + utfbom_8 * Cc("utf-8") + alwaysmatched * Cc("utf-8") -- assume utf8 -local utfstricttype = utfbom_32_be * Cc("utf-32-be") + utfbom_32_le * Cc("utf-32-le") - + utfbom_16_be * Cc("utf-16-be") + utfbom_16_le * Cc("utf-16-le") - + utfbom_8 * Cc("utf-8") -local utfoffset = utfbom_32_be * Cc(4) + utfbom_32_le * Cc(4) - + utfbom_16_be * Cc(2) + utfbom_16_le * Cc(2) - + utfbom_8 * Cc(3) + Cc(0) - -local utf8next = R("\128\191") - -patterns.utfbom_32_be = utfbom_32_be -patterns.utfbom_32_le = utfbom_32_le -patterns.utfbom_16_be = utfbom_16_be -patterns.utfbom_16_le = utfbom_16_le -patterns.utfbom_8 = utfbom_8 - -patterns.utf_16_be_nl = P("\000\r\000\n") + P("\000\r") + P("\000\n") -- P("\000\r") * (P("\000\n") + P(true)) + P("\000\n") -patterns.utf_16_le_nl = P("\r\000\n\000") + P("\r\000") + P("\n\000") -- P("\r\000") * (P("\n\000") + P(true)) + P("\n\000") - -patterns.utf_32_be_nl = P("\000\000\000\r\000\000\000\n") + P("\000\000\000\r") + P("\000\000\000\n") -patterns.utf_32_le_nl = P("\r\000\000\000\n\000\000\000") + P("\r\000\000\000") + P("\n\000\000\000") - -patterns.utf8one = R("\000\127") -patterns.utf8two = R("\194\223") * utf8next -patterns.utf8three = R("\224\239") * utf8next * utf8next -patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next -patterns.utfbom = utfbom -patterns.utftype = utftype -patterns.utfstricttype = utfstricttype -patterns.utfoffset = utfoffset - -local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four -local validutf8char = utf8char^0 * endofstring * Cc(true) + Cc(false) - -local utf8character = P(1) * R("\128\191")^0 -- unchecked but fast - -patterns.utf8 = utf8char -patterns.utf8char = utf8char -patterns.utf8character = utf8character -- this one can be used in most cases so we might use that one -patterns.validutf8 = validutf8char -patterns.validutf8char = validutf8char - -local eol = S("\n\r") -local spacer = S(" \t\f\v") -- + char(0xc2, 0xa0) if we want utf (cf mail roberto) -local whitespace = eol + spacer -local nonspacer = 1 - spacer -local nonwhitespace = 1 - whitespace - -patterns.eol = eol -patterns.spacer = spacer -patterns.whitespace = whitespace -patterns.nonspacer = nonspacer -patterns.nonwhitespace = nonwhitespace - -local stripper = spacer ^0 * C((spacer ^0 * nonspacer ^1)^0) -- from example by roberto -local fullstripper = whitespace^0 * C((whitespace^0 * nonwhitespace^1)^0) - ------ collapser = Cs(spacer^0/"" * ((spacer^1 * endofstring / "") + (spacer^1/" ") + P(1))^0) -local collapser = Cs(spacer^0/"" * nonspacer^0 * ((spacer^0/" " * nonspacer^1)^0)) - -local b_collapser = Cs( whitespace^0 /"" * (nonwhitespace^1 + whitespace^1/" ")^0) -local e_collapser = Cs((whitespace^1 * P(-1)/"" + nonwhitespace^1 + whitespace^1/" ")^0) -local m_collapser = Cs( (nonwhitespace^1 + whitespace^1/" ")^0) - -local b_stripper = Cs( spacer^0 /"" * (nonspacer^1 + spacer^1/" ")^0) -local e_stripper = Cs((spacer^1 * P(-1)/"" + nonspacer^1 + spacer^1/" ")^0) -local m_stripper = Cs( (nonspacer^1 + spacer^1/" ")^0) - -patterns.stripper = stripper -patterns.fullstripper = fullstripper -patterns.collapser = collapser - -patterns.b_collapser = b_collapser -patterns.m_collapser = m_collapser -patterns.e_collapser = e_collapser - -patterns.b_stripper = b_stripper -patterns.m_stripper = m_stripper -patterns.e_stripper = e_stripper - -patterns.lowercase = lowercase -patterns.uppercase = uppercase -patterns.letter = patterns.lowercase + patterns.uppercase -patterns.space = space -patterns.tab = P("\t") -patterns.spaceortab = patterns.space + patterns.tab -patterns.newline = newline -patterns.emptyline = newline^1 -patterns.equal = P("=") -patterns.comma = comma -patterns.commaspacer = comma * spacer^0 -patterns.period = period -patterns.colon = P(":") -patterns.semicolon = P(";") -patterns.underscore = underscore -patterns.escaped = escaped -patterns.squote = squote -patterns.dquote = dquote -patterns.nosquote = (escaped + (1-squote))^0 -patterns.nodquote = (escaped + (1-dquote))^0 -patterns.unsingle = (squote/"") * patterns.nosquote * (squote/"") -- will change to C in the middle -patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"") -- will change to C in the middle -patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble -patterns.unspacer = ((patterns.spacer^1)/"")^0 - -patterns.singlequoted = squote * patterns.nosquote * squote -patterns.doublequoted = dquote * patterns.nodquote * dquote -patterns.quoted = patterns.doublequoted + patterns.singlequoted - -patterns.digit = digit -patterns.octdigit = octdigit -patterns.hexdigit = hexdigit -patterns.sign = sign -patterns.cardinal = digit^1 -patterns.integer = sign^-1 * digit^1 -patterns.unsigned = digit^0 * period * digit^1 -patterns.float = sign^-1 * patterns.unsigned -patterns.cunsigned = digit^0 * comma * digit^1 -patterns.cpunsigned = digit^0 * (period + comma) * digit^1 -patterns.cfloat = sign^-1 * patterns.cunsigned -patterns.cpfloat = sign^-1 * patterns.cpunsigned -patterns.number = patterns.float + patterns.integer -patterns.cnumber = patterns.cfloat + patterns.integer -patterns.cpnumber = patterns.cpfloat + patterns.integer -patterns.oct = zero * octdigit^1 -patterns.octal = patterns.oct -patterns.HEX = zero * P("X") * (digit+uppercase)^1 -patterns.hex = zero * P("x") * (digit+lowercase)^1 -patterns.hexadecimal = zero * S("xX") * hexdigit^1 - -patterns.hexafloat = sign^-1 - * zero * S("xX") - * (hexdigit^0 * period * hexdigit^1 + hexdigit^1 * period * hexdigit^0 + hexdigit^1) - * (S("pP") * sign^-1 * hexdigit^1)^-1 -patterns.decafloat = sign^-1 - * (digit^0 * period * digit^1 + digit^1 * period * digit^0 + digit^1) - * S("eE") * sign^-1 * digit^1 - -patterns.propername = (uppercase + lowercase + underscore) * (uppercase + lowercase + underscore + digit)^0 * endofstring - -patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1 -patterns.beginline = #(1-newline) - -patterns.longtostring = Cs(whitespace^0/"" * ((patterns.quoted + nonwhitespace^1 + whitespace^1/"" * (P(-1) + Cc(" ")))^0)) - -local function anywhere(pattern) --slightly adapted from website - return P { P(pattern) + 1 * V(1) } -end - -lpeg.anywhere = anywhere - -function lpeg.instringchecker(p) - p = anywhere(p) - return function(str) - return lpegmatch(p,str) and true or false - end -end - -function lpeg.splitter(pattern, action) - return (((1-P(pattern))^1)/action+1)^0 -end - -function lpeg.tsplitter(pattern, action) - return Ct((((1-P(pattern))^1)/action+1)^0) -end - --- probleem: separator can be lpeg and that does not hash too well, but --- it's quite okay as the key is then not garbage collected - -local splitters_s, splitters_m, splitters_t = { }, { }, { } - -local function splitat(separator,single) - local splitter = (single and splitters_s[separator]) or splitters_m[separator] - if not splitter then - separator = P(separator) - local other = C((1 - separator)^0) - if single then - local any = anything - splitter = other * (separator * C(any^0) + "") -- ? - splitters_s[separator] = splitter - else - splitter = other * (separator * other)^0 - splitters_m[separator] = splitter - end - end - return splitter -end - -local function tsplitat(separator) - local splitter = splitters_t[separator] - if not splitter then - splitter = Ct(splitat(separator)) - splitters_t[separator] = splitter - end - return splitter -end - -lpeg.splitat = splitat -lpeg.tsplitat = tsplitat - -function string.splitup(str,separator) - if not separator then - separator = "," - end - return lpegmatch(splitters_m[separator] or splitat(separator),str) -end - --- local p = splitat("->",false) print(lpegmatch(p,"oeps->what->more")) -- oeps what more --- local p = splitat("->",true) print(lpegmatch(p,"oeps->what->more")) -- oeps what->more --- local p = splitat("->",false) print(lpegmatch(p,"oeps")) -- oeps --- local p = splitat("->",true) print(lpegmatch(p,"oeps")) -- oeps - -local cache = { } - -function lpeg.split(separator,str) - local c = cache[separator] - if not c then - c = tsplitat(separator) - cache[separator] = c - end - return lpegmatch(c,str) -end - -function string.split(str,separator) - if separator then - local c = cache[separator] - if not c then - c = tsplitat(separator) - cache[separator] = c - end - return lpegmatch(c,str) - else - return { str } - end -end - -local spacing = patterns.spacer^0 * newline -- sort of strip -local empty = spacing * Cc("") -local nonempty = Cs((1-spacing)^1) * spacing^-1 -local content = (empty + nonempty)^1 - -patterns.textline = content - -local linesplitter = tsplitat(newline) - -patterns.linesplitter = linesplitter - -function string.splitlines(str) - return lpegmatch(linesplitter,str) -end - --- lpeg.splitters = cache -- no longer public - -local cache = { } - -function lpeg.checkedsplit(separator,str) - local c = cache[separator] - if not c then - separator = P(separator) - local other = C((1 - separator)^1) - c = Ct(separator^0 * other * (separator^1 * other)^0) - cache[separator] = c - end - return lpegmatch(c,str) -end - -function string.checkedsplit(str,separator) - local c = cache[separator] - if not c then - separator = P(separator) - local other = C((1 - separator)^1) - c = Ct(separator^0 * other * (separator^1 * other)^0) - cache[separator] = c - end - return lpegmatch(c,str) -end - --- from roberto's site: - -local function f2(s) local c1, c2 = byte(s,1,2) return c1 * 64 + c2 - 12416 end -local function f3(s) local c1, c2, c3 = byte(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end -local function f4(s) local c1, c2, c3, c4 = byte(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end - -local utf8byte = patterns.utf8one/byte + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4 - -patterns.utf8byte = utf8byte - ---~ local str = " a b c d " - ---~ local s = lpeg.stripper(lpeg.R("az")) print("["..lpegmatch(s,str).."]") ---~ local s = lpeg.keeper(lpeg.R("az")) print("["..lpegmatch(s,str).."]") ---~ local s = lpeg.stripper("ab") print("["..lpegmatch(s,str).."]") ---~ local s = lpeg.keeper("ab") print("["..lpegmatch(s,str).."]") - -local cache = { } - -function lpeg.stripper(str) - if type(str) == "string" then - local s = cache[str] - if not s then - s = Cs(((S(str)^1)/"" + 1)^0) - cache[str] = s - end - return s - else - return Cs(((str^1)/"" + 1)^0) - end -end - -local cache = { } - -function lpeg.keeper(str) - if type(str) == "string" then - local s = cache[str] - if not s then - s = Cs((((1-S(str))^1)/"" + 1)^0) - cache[str] = s - end - return s - else - return Cs((((1-str)^1)/"" + 1)^0) - end -end - -function lpeg.frontstripper(str) -- or pattern (yet undocumented) - return (P(str) + P(true)) * Cs(anything^0) -end - -function lpeg.endstripper(str) -- or pattern (yet undocumented) - return Cs((1 - P(str) * endofstring)^0) -end - --- Just for fun I looked at the used bytecode and --- p = (p and p + pp) or pp gets one more (testset). - --- todo: cache when string - -function lpeg.replacer(one,two,makefunction,isutf) -- in principle we should sort the keys - local pattern - local u = isutf and utf8char or 1 - if type(one) == "table" then - local no = #one - local p = P(false) - if no == 0 then - for k, v in next, one do - p = p + P(k) / v - end - pattern = Cs((p + u)^0) - elseif no == 1 then - local o = one[1] - one, two = P(o[1]), o[2] - -- pattern = Cs(((1-one)^1 + one/two)^0) - pattern = Cs((one/two + u)^0) - else - for i=1,no do - local o = one[i] - p = p + P(o[1]) / o[2] - end - pattern = Cs((p + u)^0) - end - else - pattern = Cs((P(one)/(two or "") + u)^0) - end - if makefunction then - return function(str) - return lpegmatch(pattern,str) - end - else - return pattern - end -end - --- local pattern1 = P(1-P(pattern))^0 * P(pattern) : test for not nil --- local pattern2 = (P(pattern) * Cc(true) + P(1))^0 : test for true (could be faster, but not much) - -function lpeg.finder(lst,makefunction,isutf) -- beware: slower than find with 'patternless finds' - local pattern - if type(lst) == "table" then - pattern = P(false) - if #lst == 0 then - for k, v in next, lst do - pattern = pattern + P(k) -- ignore key, so we can use a replacer table - end - else - for i=1,#lst do - pattern = pattern + P(lst[i]) - end - end - else - pattern = P(lst) - end - if isutf then - pattern = ((utf8char or 1)-pattern)^0 * pattern - else - pattern = (1-pattern)^0 * pattern - end - if makefunction then - return function(str) - return lpegmatch(pattern,str) - end - else - return pattern - end -end - --- print(lpeg.match(lpeg.replacer("e","a"),"test test")) --- print(lpeg.match(lpeg.replacer{{"e","a"}},"test test")) --- print(lpeg.match(lpeg.replacer({ e = "a", t = "x" }),"test test")) - -local splitters_f, splitters_s = { }, { } - -function lpeg.firstofsplit(separator) -- always return value - local splitter = splitters_f[separator] - if not splitter then - local pattern = P(separator) - splitter = C((1 - pattern)^0) - splitters_f[separator] = splitter - end - return splitter -end - -function lpeg.secondofsplit(separator) -- nil if not split - local splitter = splitters_s[separator] - if not splitter then - local pattern = P(separator) - splitter = (1 - pattern)^0 * pattern * C(anything^0) - splitters_s[separator] = splitter - end - return splitter -end - -local splitters_s, splitters_p = { }, { } - -function lpeg.beforesuffix(separator) -- nil if nothing but empty is ok - local splitter = splitters_s[separator] - if not splitter then - local pattern = P(separator) - splitter = C((1 - pattern)^0) * pattern * endofstring - splitters_s[separator] = splitter - end - return splitter -end - -function lpeg.afterprefix(separator) -- nil if nothing but empty is ok - local splitter = splitters_p[separator] - if not splitter then - local pattern = P(separator) - splitter = pattern * C(anything^0) - splitters_p[separator] = splitter - end - return splitter -end - -function lpeg.balancer(left,right) - left, right = P(left), P(right) - return P { left * ((1 - left - right) + V(1))^0 * right } -end - --- print(1,lpegmatch(lpeg.firstofsplit(":"),"bc:de")) --- print(2,lpegmatch(lpeg.firstofsplit(":"),":de")) -- empty --- print(3,lpegmatch(lpeg.firstofsplit(":"),"bc")) --- print(4,lpegmatch(lpeg.secondofsplit(":"),"bc:de")) --- print(5,lpegmatch(lpeg.secondofsplit(":"),"bc:")) -- empty --- print(6,lpegmatch(lpeg.secondofsplit(":",""),"bc")) --- print(7,lpegmatch(lpeg.secondofsplit(":"),"bc")) --- print(9,lpegmatch(lpeg.secondofsplit(":","123"),"bc")) - --- -- slower: --- --- function lpeg.counter(pattern) --- local n, pattern = 0, (lpeg.P(pattern)/function() n = n + 1 end + lpeg.anything)^0 --- return function(str) n = 0 ; lpegmatch(pattern,str) ; return n end --- end - -local nany = utf8char/"" - -function lpeg.counter(pattern) - pattern = Cs((P(pattern)/" " + nany)^0) - return function(str) - return #lpegmatch(pattern,str) - end -end - --- utf extensies - -utf = utf or (unicode and unicode.utf8) or { } - -local utfcharacters = utf and utf.characters or string.utfcharacters -local utfgmatch = utf and utf.gmatch -local utfchar = utf and utf.char - -lpeg.UP = lpeg.P - -if utfcharacters then - - function lpeg.US(str) - local p = P(false) - for uc in utfcharacters(str) do - p = p + P(uc) - end - return p - end - - -elseif utfgmatch then - - function lpeg.US(str) - local p = P(false) - for uc in utfgmatch(str,".") do - p = p + P(uc) - end - return p - end - -else - - function lpeg.US(str) - local p = P(false) - local f = function(uc) - p = p + P(uc) - end - lpegmatch((utf8char/f)^0,str) - return p - end - -end - -local range = utf8byte * utf8byte + Cc(false) -- utf8byte is already a capture - -function lpeg.UR(str,more) - local first, last - if type(str) == "number" then - first = str - last = more or first - else - first, last = lpegmatch(range,str) - if not last then - return P(str) - end - end - if first == last then - return P(str) - elseif utfchar and (last - first < 8) then -- a somewhat arbitrary criterium - local p = P(false) - for i=first,last do - p = p + P(utfchar(i)) - end - return p -- nil when invalid range - else - local f = function(b) - return b >= first and b <= last - end - -- tricky, these nested captures - return utf8byte / f -- nil when invalid range - end -end - --- print(lpeg.match(lpeg.Cs((C(lpeg.UR("αω"))/{ ["χ"] = "OEPS" })^0),"αωχαω")) - --- lpeg.print(lpeg.R("ab","cd","gh")) --- lpeg.print(lpeg.P("a","b","c")) --- lpeg.print(lpeg.S("a","b","c")) - --- print(lpeg.count("äáàa",lpeg.P("á") + lpeg.P("à"))) --- print(lpeg.count("äáàa",lpeg.UP("áà"))) --- print(lpeg.count("äáàa",lpeg.US("àá"))) --- print(lpeg.count("äáàa",lpeg.UR("aá"))) --- print(lpeg.count("äáàa",lpeg.UR("àá"))) --- print(lpeg.count("äáàa",lpeg.UR(0x0000,0xFFFF))) - -function lpeg.is_lpeg(p) - return p and lpegtype(p) == "pattern" -end - -function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then") -- assume proper order - if type(list) ~= "table" then - list = { list, ... } - end - -- table.sort(list) -- longest match first - local p = P(list[1]) - for l=2,#list do - p = p + P(list[l]) - end - return p -end - --- For the moment here, but it might move to utilities. Beware, we need to --- have the longest keyword first, so 'aaa' comes beforte 'aa' which is why we --- loop back from the end cq. prepend. - -local sort = table.sort - -local function copyindexed(old) - local new = { } - for i=1,#old do - new[i] = old - end - return new -end - -local function sortedkeys(tab) - local keys, s = { }, 0 - for key,_ in next, tab do - s = s + 1 - keys[s] = key - end - sort(keys) - return keys -end - -function lpeg.append(list,pp,delayed,checked) - local p = pp - if #list > 0 then - local keys = copyindexed(list) - sort(keys) - for i=#keys,1,-1 do - local k = keys[i] - if p then - p = P(k) + p - else - p = P(k) - end - end - elseif delayed then -- hm, it looks like the lpeg parser resolves anyway - local keys = sortedkeys(list) - if p then - for i=1,#keys,1 do - local k = keys[i] - local v = list[k] - p = P(k)/list + p - end - else - for i=1,#keys do - local k = keys[i] - local v = list[k] - if p then - p = P(k) + p - else - p = P(k) - end - end - if p then - p = p / list - end - end - elseif checked then - -- problem: substitution gives a capture - local keys = sortedkeys(list) - for i=1,#keys do - local k = keys[i] - local v = list[k] - if p then - if k == v then - p = P(k) + p - else - p = P(k)/v + p - end - else - if k == v then - p = P(k) - else - p = P(k)/v - end - end - end - else - local keys = sortedkeys(list) - for i=1,#keys do - local k = keys[i] - local v = list[k] - if p then - p = P(k)/v + p - else - p = P(k)/v - end - end - end - return p -end - --- inspect(lpeg.append({ a = "1", aa = "1", aaa = "1" } ,nil,true)) --- inspect(lpeg.append({ ["degree celsius"] = "1", celsius = "1", degree = "1" } ,nil,true)) - --- function lpeg.exact_match(words,case_insensitive) --- local pattern = concat(words) --- if case_insensitive then --- local pattern = S(upper(characters)) + S(lower(characters)) --- local list = { } --- for i=1,#words do --- list[lower(words[i])] = true --- end --- return Cmt(pattern^1, function(_,i,s) --- return list[lower(s)] and i --- end) --- else --- local pattern = S(concat(words)) --- local list = { } --- for i=1,#words do --- list[words[i]] = true --- end --- return Cmt(pattern^1, function(_,i,s) --- return list[s] and i --- end) --- end --- end - --- experiment: - -local p_false = P(false) -local p_true = P(true) - -local function make(t) - local function making(t) - local p = p_false - local keys = sortedkeys(t) - for i=1,#keys do - local k = keys[i] - if k ~= "" then - local v = t[k] - if v == true then - p = p + P(k) * p_true - elseif v == false then - -- can't happen - else - p = p + P(k) * making(v) - end - end - end - if t[""] then - p = p + p_true - end - return p - end - local p = p_false - local keys = sortedkeys(t) - for i=1,#keys do - local k = keys[i] - if k ~= "" then - local v = t[k] - if v == true then - p = p + P(k) * p_true - elseif v == false then - -- can't happen - else - p = p + P(k) * making(v) - end - end - end - return p -end - -local function collapse(t,x) - if type(t) ~= "table" then - return t, x - else - local n = next(t) - if n == nil then - return t, x - elseif next(t,n) == nil then - -- one entry - local k = n - local v = t[k] - if type(v) == "table" then - return collapse(v,x..k) - else - return v, x .. k - end - else - local tt = { } - for k, v in next, t do - local vv, kk = collapse(v,k) - tt[kk] = vv - end - return tt, x - end - end -end - -function lpeg.utfchartabletopattern(list) -- goes to util-lpg - local tree = { } - local n = #list - if n == 0 then - for s in next, list do - local t = tree - local p, pk - for c in gmatch(s,".") do - if t == true then - t = { [c] = true, [""] = true } - p[pk] = t - p = t - t = false - elseif t == false then - t = { [c] = false } - p[pk] = t - p = t - t = false - else - local tc = t[c] - if not tc then - tc = false - t[c] = false - end - p = t - t = tc - end - pk = c - end - if t == false then - p[pk] = true - elseif t == true then - -- okay - else - t[""] = true - end - end - else - for i=1,n do - local s = list[i] - local t = tree - local p, pk - for c in gmatch(s,".") do - if t == true then - t = { [c] = true, [""] = true } - p[pk] = t - p = t - t = false - elseif t == false then - t = { [c] = false } - p[pk] = t - p = t - t = false - else - local tc = t[c] - if not tc then - tc = false - t[c] = false - end - p = t - t = tc - end - pk = c - end - if t == false then - p[pk] = true - elseif t == true then - -- okay - else - t[""] = true - end - end - end --- collapse(tree,"") -- needs testing, maybe optional, slightly faster because P("x")*P("X") seems slower than P"(xX") (why) --- inspect(tree) - return make(tree) -end - --- local t = { "start", "stoep", "staart", "paard" } --- local p = lpeg.Cs((lpeg.utfchartabletopattern(t)/string.upper + 1)^1) - --- local t = { "a", "abc", "ac", "abe", "abxyz", "xy", "bef","aa" } --- local p = lpeg.Cs((lpeg.utfchartabletopattern(t)/string.upper + 1)^1) - --- inspect(lpegmatch(p,"a")) --- inspect(lpegmatch(p,"aa")) --- inspect(lpegmatch(p,"aaaa")) --- inspect(lpegmatch(p,"ac")) --- inspect(lpegmatch(p,"bc")) --- inspect(lpegmatch(p,"zzbczz")) --- inspect(lpegmatch(p,"zzabezz")) --- inspect(lpegmatch(p,"ab")) --- inspect(lpegmatch(p,"abc")) --- inspect(lpegmatch(p,"abe")) --- inspect(lpegmatch(p,"xa")) --- inspect(lpegmatch(p,"bx")) --- inspect(lpegmatch(p,"bax")) --- inspect(lpegmatch(p,"abxyz")) --- inspect(lpegmatch(p,"foobarbefcrap")) - --- local t = { ["^"] = 1, ["^^"] = 2, ["^^^"] = 3, ["^^^^"] = 4 } --- local p = lpeg.Cs((lpeg.utfchartabletopattern(t)/t + 1)^1) --- inspect(lpegmatch(p," ^ ^^ ^^^ ^^^^ ^^^^^ ^^^^^^ ^^^^^^^ ")) - --- local t = { ["^^"] = 2, ["^^^"] = 3, ["^^^^"] = 4 } --- local p = lpeg.Cs((lpeg.utfchartabletopattern(t)/t + 1)^1) --- inspect(lpegmatch(p," ^ ^^ ^^^ ^^^^ ^^^^^ ^^^^^^ ^^^^^^^ ")) - --- lpeg.utfchartabletopattern { --- utfchar(0x00A0), -- nbsp --- utfchar(0x2000), -- enquad --- utfchar(0x2001), -- emquad --- utfchar(0x2002), -- enspace --- utfchar(0x2003), -- emspace --- utfchar(0x2004), -- threeperemspace --- utfchar(0x2005), -- fourperemspace --- utfchar(0x2006), -- sixperemspace --- utfchar(0x2007), -- figurespace --- utfchar(0x2008), -- punctuationspace --- utfchar(0x2009), -- breakablethinspace --- utfchar(0x200A), -- hairspace --- utfchar(0x200B), -- zerowidthspace --- utfchar(0x202F), -- narrownobreakspace --- utfchar(0x205F), -- math thinspace --- } - --- a few handy ones: --- --- faster than find(str,"[\n\r]") when match and # > 7 and always faster when # > 3 - -patterns.containseol = lpeg.finder(eol) -- (1-eol)^0 * eol - --- The next pattern^n variant is based on an approach suggested --- by Roberto: constructing a big repetition in chunks. --- --- Being sparse is not needed, and only complicate matters and --- the number of redundant entries is not that large. - -local function nextstep(n,step,result) - local m = n % step -- mod(n,step) - local d = floor(n/step) -- div(n,step) - if d > 0 then - local v = V(tostring(step)) - local s = result.start - for i=1,d do - if s then - s = v * s - else - s = v - end - end - result.start = s - end - if step > 1 and result.start then - local v = V(tostring(step/2)) - result[tostring(step)] = v * v - end - if step > 0 then - return nextstep(m,step/2,result) - else - return result - end -end - -function lpeg.times(pattern,n) - return P(nextstep(n,2^16,{ "start", ["1"] = pattern })) -end - --- local p = lpeg.Cs((1 - lpeg.times(lpeg.P("AB"),25))^1) --- local s = "12" .. string.rep("AB",20) .. "34" .. string.rep("AB",30) .. "56" --- inspect(p) --- print(lpeg.match(p,s)) - --- moved here (before util-str) - ------ digit = R("09") ------ period = P(".") ------ zero = P("0") -local trailingzeros = zero^0 * -digit -- suggested by Roberto R -local case_1 = period * trailingzeros / "" -local case_2 = period * (digit - trailingzeros)^1 * (trailingzeros / "") -local number = digit^1 * (case_1 + case_2) -local stripper = Cs((number + 1)^0) - -lpeg.patterns.stripzeros = stripper - --- local sample = "bla 11.00 bla 11 bla 0.1100 bla 1.00100 bla 0.00 bla 0.001 bla 1.1100 bla 0.100100100 bla 0.00100100100" --- collectgarbage("collect") --- str = string.rep(sample,10000) --- local ts = os.clock() --- lpegmatch(stripper,str) --- print(#str, os.clock()-ts, lpegmatch(stripper,sample)) - --- for practical reasone we keep this here: - -local byte_to_HEX = { } -local byte_to_hex = { } -local byte_to_dec = { } -- for md5 -local hex_to_byte = { } - -for i=0,255 do - local H = format("%02X",i) - local h = format("%02x",i) - local d = format("%03i",i) - local c = char(i) - byte_to_HEX[c] = H - byte_to_hex[c] = h - byte_to_dec[c] = d - hex_to_byte[h] = c - hex_to_byte[H] = c -end - -local hextobyte = P(2)/hex_to_byte -local bytetoHEX = P(1)/byte_to_HEX -local bytetohex = P(1)/byte_to_hex -local bytetodec = P(1)/byte_to_dec -local hextobytes = Cs(hextobyte^0) -local bytestoHEX = Cs(bytetoHEX^0) -local bytestohex = Cs(bytetohex^0) -local bytestodec = Cs(bytetodec^0) - -patterns.hextobyte = hextobyte -patterns.bytetoHEX = bytetoHEX -patterns.bytetohex = bytetohex -patterns.bytetodec = bytetodec -patterns.hextobytes = hextobytes -patterns.bytestoHEX = bytestoHEX -patterns.bytestohex = bytestohex -patterns.bytestodec = bytestodec - -function string.toHEX(s) - if not s or s == "" then - return s - else - return lpegmatch(bytestoHEX,s) - end -end - -function string.tohex(s) - if not s or s == "" then - return s - else - return lpegmatch(bytestohex,s) - end -end - -function string.todec(s) - if not s or s == "" then - return s - else - return lpegmatch(bytestodec,s) - end -end - -function string.tobytes(s) - if not s or s == "" then - return s - else - return lpegmatch(hextobytes,s) - end -end - --- local h = "ADFE0345" --- local b = lpegmatch(patterns.hextobytes,h) --- print(h,b,string.tohex(b),string.toHEX(b)) diff --git a/tex/compat/lualibs/lualibs-lua.lua b/tex/compat/lualibs/lualibs-lua.lua deleted file mode 100644 index b90f37e3db36e67251e2a3297223748f50fd5ad1..0000000000000000000000000000000000000000 --- a/tex/compat/lualibs/lualibs-lua.lua +++ /dev/null @@ -1,200 +0,0 @@ -if not modules then modules = { } end modules ['l-lua'] = { - version = 1.001, - comment = "companion to luat-lib.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- potential issues with 5.3: - --- i'm not sure yet if the int/float change is good for luatex - --- math.min --- math.max --- tostring --- tonumber --- utf.* --- bit32 - --- compatibility hacksand helpers - -_MAJORVERSION, _MINORVERSION = string.match(_VERSION,"^[^%d]+(%d+)%.(%d+).*$") - -_MAJORVERSION = tonumber(_MAJORVERSION) or 5 -_MINORVERSION = tonumber(_MINORVERSION) or 1 -_LUAVERSION = _MAJORVERSION + _MINORVERSION/10 - -if _LUAVERSION < 5.2 and jit then - -- - -- we want loadstring cum suis to behave like 5.2 - -- - _MINORVERSION = 2 - _LUAVERSION = 5.2 -end - --- lpeg - -if not lpeg then - lpeg = require("lpeg") -end - --- basics: - -if loadstring then - - local loadnormal = load - - function load(first,...) - if type(first) == "string" then - return loadstring(first,...) - else - return loadnormal(first,...) - end - end - -else - - loadstring = load - -end - --- table: - --- At some point it was announced that i[pairs would be dropped, which makes --- sense. As we already used the for loop and # in most places the impact on --- ConTeXt was not that large; the remaining ipairs already have been replaced. --- Hm, actually ipairs was retained, but we no longer use it anyway (nor --- pairs). --- --- Just in case, we provide the fallbacks as discussed in Programming --- in Lua (http://www.lua.org/pil/7.3.html): - -if not ipairs then - - -- for k, v in ipairs(t) do ... end - -- for k=1,#t do local v = t[k] ... end - - local function iterate(a,i) - i = i + 1 - local v = a[i] - if v ~= nil then - return i, v --, nil - end - end - - function ipairs(a) - return iterate, a, 0 - end - -end - -if not pairs then - - -- for k, v in pairs(t) do ... end - -- for k, v in next, t do ... end - - function pairs(t) - return next, t -- , nil - end - -end - --- The unpack function has been moved to the table table, and for compatiility --- reasons we provide both now. - -if not table.unpack then - - table.unpack = _G.unpack - -elseif not unpack then - - _G.unpack = table.unpack - -end - --- package: - --- if not package.seachers then --- --- package.searchers = package.loaders -- 5.2 --- --- elseif not package.loaders then --- --- package.loaders = package.searchers --- --- end - -if not package.loaders then -- brr, searchers is a special "loadlib function" userdata type - - package.loaders = package.searchers - -end - --- moved from util-deb to here: - -local print, select, tostring = print, select, tostring - -local inspectors = { } - -function setinspector(kind,inspector) -- global function - inspectors[kind] = inspector -end - -function inspect(...) -- global function - for s=1,select("#",...) do - local value = select(s,...) - if value == nil then - print("nil") - else - local done = false - -- type driven (table) - local kind = type(value) - local inspector = inspectors[kind] - if inspector then - done = inspector(value) - if done then - break - end - end - -- whatever driven (token, node, ...) - for kind, inspector in next, inspectors do - done = inspector(value) - if done then - break - end - end - if not done then - print(tostring(value)) - end - end - end -end - --- - -local dummy = function() end - -function optionalrequire(...) - local ok, result = xpcall(require,dummy,...) - if ok then - return result - end -end - --- nice for non ascii scripts (this might move): - -if lua then - lua.mask = load([[τεχ = 1]]) and "utf" or "ascii" -end - -local flush = io.flush - -if flush then - - local execute = os.execute if execute then function os.execute(...) flush() return execute(...) end end - local exec = os.exec if exec then function os.exec (...) flush() return exec (...) end end - local spawn = os.spawn if spawn then function os.spawn (...) flush() return spawn (...) end end - local popen = io.popen if popen then function io.popen (...) flush() return popen (...) end end - -end diff --git a/tex/compat/lualibs/lualibs-math.lua b/tex/compat/lualibs/lualibs-math.lua deleted file mode 100644 index ec62919b46ac50acc93ceeeef4394dd1474e5569..0000000000000000000000000000000000000000 --- a/tex/compat/lualibs/lualibs-math.lua +++ /dev/null @@ -1,38 +0,0 @@ -if not modules then modules = { } end modules ['l-math'] = { - version = 1.001, - comment = "companion to luat-lib.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -local floor, sin, cos, tan = math.floor, math.sin, math.cos, math.tan - -if not math.ceiling then - math.ceiling = math.ceil -end - -if not math.round then - function math.round(x) return floor(x + 0.5) end -end - -if not math.div then - function math.div(n,m) return floor(n/m) end -end - -if not math.mod then - function math.mod(n,m) return n % m end -end - -local pipi = 2*math.pi/360 - -if not math.sind then - function math.sind(d) return sin(d*pipi) end - function math.cosd(d) return cos(d*pipi) end - function math.tand(d) return tan(d*pipi) end -end - -if not math.odd then - function math.odd (n) return n % 2 ~= 0 end - function math.even(n) return n % 2 == 0 end -end diff --git a/tex/compat/lualibs/lualibs-md5.lua b/tex/compat/lualibs/lualibs-md5.lua deleted file mode 100644 index 00272c873f1a65152b4e7dc437d389d007098916..0000000000000000000000000000000000000000 --- a/tex/compat/lualibs/lualibs-md5.lua +++ /dev/null @@ -1,107 +0,0 @@ -if not modules then modules = { } end modules ['l-md5'] = { - version = 1.001, - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- This also provides file checksums and checkers. - -if not md5 then - md5 = optionalrequire("md5") -end - -if not md5 then - md5 = { - sum = function(str) print("error: md5 is not loaded (sum ignored)") return str end, - sumhexa = function(str) print("error: md5 is not loaded (sumhexa ignored)") return str end, - } -end - -local md5, file = md5, file -local gsub = string.gsub - --- local gsub, format, byte = string.gsub, string.format, string.byte --- --- local function convert(str,fmt) --- return (gsub(md5sum(str),".",function(chr) return format(fmt,byte(chr)) end)) --- end --- --- if not md5.HEX then function md5.HEX(str) return convert(str,"%02X") end end --- if not md5.hex then function md5.hex(str) return convert(str,"%02x") end end --- if not md5.dec then function md5.dec(str) return convert(str,"%03i") end end - -do - - local patterns = lpeg and lpeg.patterns - - if patterns then - - local bytestoHEX = patterns.bytestoHEX - local bytestohex = patterns.bytestohex - local bytestodec = patterns.bytestodec - - local lpegmatch = lpeg.match - local md5sum = md5.sum - - if not md5.HEX then function md5.HEX(str) if str then return lpegmatch(bytestoHEX,md5sum(str)) end end end - if not md5.hex then function md5.hex(str) if str then return lpegmatch(bytestohex,md5sum(str)) end end end - if not md5.dec then function md5.dec(str) if str then return lpegmatch(bytestodec,md5sum(str)) end end end - - end - -end - -function file.needsupdating(oldname,newname,threshold) -- size modification access change - local oldtime = lfs.attributes(oldname,"modification") - if oldtime then - local newtime = lfs.attributes(newname,"modification") - if not newtime then - return true -- no new file, so no updating needed - elseif newtime >= oldtime then - return false -- new file definitely needs updating - elseif oldtime - newtime < (threshold or 1) then - return false -- new file is probably still okay - else - return true -- new file has to be updated - end - else - return false -- no old file, so no updating needed - end -end - -file.needs_updating = file.needsupdating - -function file.syncmtimes(oldname,newname) - local oldtime = lfs.attributes(oldname,"modification") - if oldtime and lfs.isfile(newname) then - lfs.touch(newname,oldtime,oldtime) - end -end - -function file.checksum(name) - if md5 then - local data = io.loaddata(name) - if data then - return md5.HEX(data) - end - end - return nil -end - -function file.loadchecksum(name) - if md5 then - local data = io.loaddata(name .. ".md5") - return data and (gsub(data,"%s","")) - end - return nil -end - -function file.savechecksum(name,checksum) - if not checksum then checksum = file.checksum(name) end - if checksum then - io.savedata(name .. ".md5",checksum) - return checksum - end - return nil -end diff --git a/tex/compat/lualibs/lualibs-number.lua b/tex/compat/lualibs/lualibs-number.lua deleted file mode 100644 index 001ca31f773dfcf016388216da990a30a177d222..0000000000000000000000000000000000000000 --- a/tex/compat/lualibs/lualibs-number.lua +++ /dev/null @@ -1,207 +0,0 @@ -if not modules then modules = { } end modules ['l-number'] = { - version = 1.001, - comment = "companion to luat-lib.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- this module will be replaced when we have the bit library .. the number based sets --- might go away - -local tostring, tonumber = tostring, tonumber -local format, floor, match, rep = string.format, math.floor, string.match, string.rep -local concat, insert = table.concat, table.insert -local lpegmatch = lpeg.match - -number = number or { } -local number = number - -if bit32 then -- I wonder if this is faster - - local btest, bor = bit32.btest, bit32.bor - - function number.bit(p) - return 2 ^ (p - 1) -- 1-based indexing - end - - number.hasbit = btest - number.setbit = bor - - function number.setbit(x,p) -- why not bor? - return btest(x,p) and x or x + p - end - - function number.clearbit(x,p) - return btest(x,p) and x - p or x - end - -else - - -- http://ricilake.blogspot.com/2007/10/iterating-bits-in-lua.html - - function number.bit(p) - return 2 ^ (p - 1) -- 1-based indexing - end - - function number.hasbit(x, p) -- typical call: if hasbit(x, bit(3)) then ... - return x % (p + p) >= p - end - - function number.setbit(x, p) - return (x % (p + p) >= p) and x or x + p - end - - function number.clearbit(x, p) - return (x % (p + p) >= p) and x - p or x - end - -end - --- print(number.tobitstring(8)) --- print(number.tobitstring(14)) --- print(number.tobitstring(66)) --- print(number.tobitstring(0x00)) --- print(number.tobitstring(0xFF)) --- print(number.tobitstring(46260767936,4)) - -if bit32 then - - local bextract = bit32.extract - - local t = { - "0", "0", "0", "0", "0", "0", "0", "0", - "0", "0", "0", "0", "0", "0", "0", "0", - "0", "0", "0", "0", "0", "0", "0", "0", - "0", "0", "0", "0", "0", "0", "0", "0", - } - - function number.tobitstring(b,m) - -- if really needed we can speed this one up - -- because small numbers need less extraction - local n = 32 - for i=0,31 do - local v = bextract(b,i) - local k = 32 - i - if v == 1 then - n = k - t[k] = "1" - else - t[k] = "0" - end - end - if m then - m = 33 - m * 8 - if m < 1 then - m = 1 - end - return concat(t,"",m) - elseif n < 8 then - return concat(t) - elseif n < 16 then - return concat(t,"",9) - elseif n < 24 then - return concat(t,"",17) - else - return concat(t,"",25) - end - end - -else - - function number.tobitstring(n,m) - if n > 0 then - local t = { } - while n > 0 do - insert(t,1,n % 2 > 0 and 1 or 0) - n = floor(n/2) - end - local nn = 8 - #t % 8 - if nn > 0 and nn < 8 then - for i=1,nn do - insert(t,1,0) - end - end - if m then - m = m * 8 - #t - if m > 0 then - insert(t,1,rep("0",m)) - end - end - return concat(t) - elseif m then - rep("00000000",m) - else - return "00000000" - end - end - -end - -function number.valid(str,default) - return tonumber(str) or default or nil -end - -function number.toevenhex(n) - local s = format("%X",n) - if #s % 2 == 0 then - return s - else - return "0" .. s - end -end - --- a,b,c,d,e,f = number.toset(100101) --- --- function number.toset(n) --- return match(tostring(n),"(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.?)") --- end --- --- -- the lpeg way is slower on 8 digits, but faster on 4 digits, some 7.5% --- -- on --- --- for i=1,1000000 do --- local a,b,c,d,e,f,g,h = number.toset(12345678) --- local a,b,c,d = number.toset(1234) --- local a,b,c = number.toset(123) --- local a,b,c = number.toset("123") --- end - -local one = lpeg.C(1-lpeg.S('')/tonumber)^1 - -function number.toset(n) - return lpegmatch(one,tostring(n)) -end - --- function number.bits(n,zero) --- local t, i = { }, (zero and 0) or 1 --- while n > 0 do --- local m = n % 2 --- if m > 0 then --- insert(t,1,i) --- end --- n = floor(n/2) --- i = i + 1 --- end --- return t --- end --- --- -- a bit faster - -local function bits(n,i,...) - if n > 0 then - local m = n % 2 - local n = floor(n/2) - if m > 0 then - return bits(n, i+1, i, ...) - else - return bits(n, i+1, ...) - end - else - return ... - end -end - -function number.bits(n) - return { bits(n,1) } -end diff --git a/tex/compat/lualibs/lualibs-os.lua b/tex/compat/lualibs/lualibs-os.lua deleted file mode 100644 index 0a86ea6d69778ca501d22a4dedbb6dc47d85f91b..0000000000000000000000000000000000000000 --- a/tex/compat/lualibs/lualibs-os.lua +++ /dev/null @@ -1,558 +0,0 @@ -if not modules then modules = { } end modules ['l-os'] = { - version = 1.001, - comment = "companion to luat-lib.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- This file deals with some operating system issues. Please don't bother me --- with the pros and cons of operating systems as they all have their flaws --- and benefits. Bashing one of them won't help solving problems and fixing --- bugs faster and is a waste of time and energy. --- --- path separators: / or \ ... we can use / everywhere --- suffixes : dll so exe <none> ... no big deal --- quotes : we can use "" in most cases --- expansion : unless "" are used * might give side effects --- piping/threads : somewhat different for each os --- locations : specific user file locations and settings can change over time --- --- os.type : windows | unix (new, we already guessed os.platform) --- os.name : windows | msdos | linux | macosx | solaris | .. | generic (new) --- os.platform : extended os.name with architecture - --- os.sleep() => socket.sleep() --- math.randomseed(tonumber(string.sub(string.reverse(tostring(math.floor(socket.gettime()*10000))),1,6))) - -local os = os -local date, time = os.date, os.time -local find, format, gsub, upper, gmatch = string.find, string.format, string.gsub, string.upper, string.gmatch -local concat = table.concat -local random, ceil, randomseed = math.random, math.ceil, math.randomseed -local rawget, rawset, type, getmetatable, setmetatable, tonumber, tostring = rawget, rawset, type, getmetatable, setmetatable, tonumber, tostring - --- The following code permits traversing the environment table, at least --- in luatex. Internally all environment names are uppercase. - --- The randomseed in Lua is not that random, although this depends on the operating system as well --- as the binary (Luatex is normally okay). But to be sure we set the seed anyway. - -math.initialseed = tonumber(string.sub(string.reverse(tostring(ceil(socket and socket.gettime()*10000 or time()))),1,6)) - -randomseed(math.initialseed) - -if not os.__getenv__ then - - os.__getenv__ = os.getenv - os.__setenv__ = os.setenv - - if os.env then - - local osgetenv = os.getenv - local ossetenv = os.setenv - local osenv = os.env local _ = osenv.PATH -- initialize the table - - function os.setenv(k,v) - if v == nil then - v = "" - end - local K = upper(k) - osenv[K] = v - if type(v) == "table" then - v = concat(v,";") -- path - end - ossetenv(K,v) - end - - function os.getenv(k) - local K = upper(k) - local v = osenv[K] or osenv[k] or osgetenv(K) or osgetenv(k) - if v == "" then - return nil - else - return v - end - end - - else - - local ossetenv = os.setenv - local osgetenv = os.getenv - local osenv = { } - - function os.setenv(k,v) - if v == nil then - v = "" - end - local K = upper(k) - osenv[K] = v - end - - function os.getenv(k) - local K = upper(k) - local v = osenv[K] or osgetenv(K) or osgetenv(k) - if v == "" then - return nil - else - return v - end - end - - local function __index(t,k) - return os.getenv(k) - end - local function __newindex(t,k,v) - os.setenv(k,v) - end - - os.env = { } - - setmetatable(os.env, { __index = __index, __newindex = __newindex } ) - - end - -end - --- end of environment hack - -local execute = os.execute -local iopopen = io.popen - -function os.resultof(command) - local handle = iopopen(command,"r") -- already has flush - if handle then - local result = handle:read("*all") or "" - handle:close() - return result - else - return "" - end -end - -if not io.fileseparator then - if find(os.getenv("PATH"),";",1,true) then - io.fileseparator, io.pathseparator, os.type = "\\", ";", os.type or "mswin" - else - io.fileseparator, io.pathseparator, os.type = "/" , ":", os.type or "unix" - end -end - -os.type = os.type or (io.pathseparator == ";" and "windows") or "unix" -os.name = os.name or (os.type == "windows" and "mswin" ) or "linux" - -if os.type == "windows" then - os.libsuffix, os.binsuffix, os.binsuffixes = 'dll', 'exe', { 'exe', 'cmd', 'bat' } -else - os.libsuffix, os.binsuffix, os.binsuffixes = 'so', '', { '' } -end - -local launchers = { - windows = "start %s", - macosx = "open %s", - unix = "$BROWSER %s &> /dev/null &", -} - -function os.launch(str) - execute(format(launchers[os.name] or launchers.unix,str)) -end - -if not os.times then -- ? - -- utime = user time - -- stime = system time - -- cutime = children user time - -- cstime = children system time - function os.times() - return { - utime = os.gettimeofday(), -- user - stime = 0, -- system - cutime = 0, -- children user - cstime = 0, -- children system - } - end -end - - -local gettimeofday = os.gettimeofday or os.clock -os.gettimeofday = gettimeofday - -local startuptime = gettimeofday() - -function os.runtime() - return gettimeofday() - startuptime -end - --- print(os.gettimeofday()-os.time()) --- os.sleep(1.234) --- print (">>",os.runtime()) --- print(os.date("%H:%M:%S",os.gettimeofday())) --- print(os.date("%H:%M:%S",os.time())) - --- no need for function anymore as we have more clever code and helpers now --- this metatable trickery might as well disappear - -local resolvers = os.resolvers or { } -os.resolvers = resolvers - -setmetatable(os, { __index = function(t,k) - local r = resolvers[k] - return r and r(t,k) or nil -- no memoize -end }) - --- we can use HOSTTYPE on some platforms - -local name, platform = os.name or "linux", os.getenv("MTX_PLATFORM") or "" - -local function guess() - local architecture = os.resultof("uname -m") or "" - if architecture ~= "" then - return architecture - end - architecture = os.getenv("HOSTTYPE") or "" - if architecture ~= "" then - return architecture - end - return os.resultof("echo $HOSTTYPE") or "" -end - --- os.bits = 32 | 64 - -if platform ~= "" then - - os.platform = platform - -elseif os.type == "windows" then - - -- we could set the variable directly, no function needed here - - -- PROCESSOR_ARCHITECTURE : binary platform - -- PROCESSOR_ARCHITEW6432 : OS platform - - function resolvers.platform(t,k) - local platform, architecture = "", os.getenv("PROCESSOR_ARCHITECTURE") or "" - if find(architecture,"AMD64",1,true) then - -- platform = "mswin-64" - platform = "win64" - else - platform = "mswin" - end - os.setenv("MTX_PLATFORM",platform) - os.platform = platform - return platform - end - -elseif name == "linux" then - - function resolvers.platform(t,k) - -- we sometimes have HOSTTYPE set so let's check that first - local platform, architecture = "", os.getenv("HOSTTYPE") or os.resultof("uname -m") or "" - if find(architecture,"x86_64",1,true) then - platform = "linux-64" - elseif find(architecture,"ppc",1,true) then - platform = "linux-ppc" - else - platform = "linux" - end - os.setenv("MTX_PLATFORM",platform) - os.platform = platform - return platform - end - -elseif name == "macosx" then - - --[[ - Identifying the architecture of OSX is quite a mess and this - is the best we can come up with. For some reason $HOSTTYPE is - a kind of pseudo environment variable, not known to the current - environment. And yes, uname cannot be trusted either, so there - is a change that you end up with a 32 bit run on a 64 bit system. - Also, some proper 64 bit intel macs are too cheap (low-end) and - therefore not permitted to run the 64 bit kernel. - ]]-- - - function resolvers.platform(t,k) - -- local platform, architecture = "", os.getenv("HOSTTYPE") or "" - -- if architecture == "" then - -- architecture = os.resultof("echo $HOSTTYPE") or "" - -- end - local platform, architecture = "", os.resultof("echo $HOSTTYPE") or "" - if architecture == "" then - -- print("\nI have no clue what kind of OSX you're running so let's assume an 32 bit intel.\n") - platform = "osx-intel" - elseif find(architecture,"i386",1,true) then - platform = "osx-intel" - elseif find(architecture,"x86_64",1,true) then - platform = "osx-64" - else - platform = "osx-ppc" - end - os.setenv("MTX_PLATFORM",platform) - os.platform = platform - return platform - end - -elseif name == "sunos" then - - function resolvers.platform(t,k) - local platform, architecture = "", os.resultof("uname -m") or "" - if find(architecture,"sparc",1,true) then - platform = "solaris-sparc" - else -- if architecture == 'i86pc' - platform = "solaris-intel" - end - os.setenv("MTX_PLATFORM",platform) - os.platform = platform - return platform - end - -elseif name == "freebsd" then - - function resolvers.platform(t,k) - local platform, architecture = "", os.resultof("uname -m") or "" - if find(architecture,"amd64",1,true) then - platform = "freebsd-amd64" - else - platform = "freebsd" - end - os.setenv("MTX_PLATFORM",platform) - os.platform = platform - return platform - end - -elseif name == "kfreebsd" then - - function resolvers.platform(t,k) - -- we sometimes have HOSTTYPE set so let's check that first - local platform, architecture = "", os.getenv("HOSTTYPE") or os.resultof("uname -m") or "" - if find(architecture,"x86_64",1,true) then - platform = "kfreebsd-amd64" - else - platform = "kfreebsd-i386" - end - os.setenv("MTX_PLATFORM",platform) - os.platform = platform - return platform - end - -else - - -- platform = "linux" - -- os.setenv("MTX_PLATFORM",platform) - -- os.platform = platform - - function resolvers.platform(t,k) - local platform = "linux" - os.setenv("MTX_PLATFORM",platform) - os.platform = platform - return platform - end - -end - -os.newline = name == "windows" and "\013\010" or "\010" -- crlf or lf - -function resolvers.bits(t,k) - local bits = find(os.platform,"64",1,true) and 64 or 32 - os.bits = bits - return bits -end - --- beware, we set the randomseed - --- from wikipedia: Version 4 UUIDs use a scheme relying only on random numbers. This algorithm sets the --- version number as well as two reserved bits. All other bits are set using a random or pseudorandom --- data source. Version 4 UUIDs have the form xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx with hexadecimal --- digits x and hexadecimal digits 8, 9, A, or B for y. e.g. f47ac10b-58cc-4372-a567-0e02b2c3d479. --- --- as we don't call this function too often there is not so much risk on repetition - -local t = { 8, 9, "a", "b" } - -function os.uuid() - return format("%04x%04x-4%03x-%s%03x-%04x-%04x%04x%04x", - random(0xFFFF),random(0xFFFF), - random(0x0FFF), - t[ceil(random(4))] or 8,random(0x0FFF), - random(0xFFFF), - random(0xFFFF),random(0xFFFF),random(0xFFFF) - ) -end - -local d - -function os.timezone(delta) - d = d or tonumber(tonumber(date("%H")-date("!%H"))) - if delta then - if d > 0 then - return format("+%02i:00",d) - else - return format("-%02i:00",-d) - end - else - return 1 - end -end - -local timeformat = format("%%s%s",os.timezone(true)) -local dateformat = "!%Y-%m-%d %H:%M:%S" -local lasttime = nil -local lastdate = nil - -function os.fulltime(t,default) - t = t and tonumber(t) or 0 - if t > 0 then - -- valid time - elseif default then - return default - else - t = time() - end - if t ~= lasttime then - lasttime = t - lastdate = format(timeformat,date(dateformat)) - end - return lastdate -end - -local dateformat = "%Y-%m-%d %H:%M:%S" -local lasttime = nil -local lastdate = nil - -function os.localtime(t,default) - t = t and tonumber(t) or 0 - if t > 0 then - -- valid time - elseif default then - return default - else - t = time() - end - if t ~= lasttime then - lasttime = t - lastdate = date(dateformat,t) - end - return lastdate -end - -function os.converttime(t,default) - local t = tonumber(t) - if t and t > 0 then - return date(dateformat,t) - else - return default or "-" - end -end - -local memory = { } - -local function which(filename) - local fullname = memory[filename] - if fullname == nil then - local suffix = file.suffix(filename) - local suffixes = suffix == "" and os.binsuffixes or { suffix } - for directory in gmatch(os.getenv("PATH"),"[^" .. io.pathseparator .."]+") do - local df = file.join(directory,filename) - for i=1,#suffixes do - local dfs = file.addsuffix(df,suffixes[i]) - if io.exists(dfs) then - fullname = dfs - break - end - end - end - if not fullname then - fullname = false - end - memory[filename] = fullname - end - return fullname -end - -os.which = which -os.where = which - -function os.today() - return date("!*t") -- table with values -end - -function os.now() - return date("!%Y-%m-%d %H:%M:%S") -- 2011-12-04 14:59:12 -end - --- if not os.sleep and socket then --- os.sleep = socket.sleep --- end - -if not os.sleep then - local socket = socket - function os.sleep(n) - if not socket then - -- so we delay ... if os.sleep is really needed then one should also - -- be sure that socket can be found - socket = require("socket") - end - socket.sleep(n) - end -end - --- print(os.which("inkscape.exe")) --- print(os.which("inkscape")) --- print(os.which("gs.exe")) --- print(os.which("ps2pdf")) - --- These are moved from core-con.lua (as I needed them elsewhere). - -local function isleapyear(year) - return (year % 400 == 0) or ((year % 100 ~= 0) and (year % 4 == 0)) -end - -os.isleapyear = isleapyear - --- nicer: --- --- local days = { --- [false] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, --- [true] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } --- } --- --- local function nofdays(year,month) --- return days[isleapyear(year)][month] --- return month == 2 and isleapyear(year) and 29 or days[month] --- end --- --- more efficient: - -local days = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } - -local function nofdays(year,month) - if not month then - return isleapyear(year) and 365 or 364 - else - return month == 2 and isleapyear(year) and 29 or days[month] - end -end - -os.nofdays = nofdays - -function os.weekday(day,month,year) - return date("%w",time { year = year, month = month, day = day }) + 1 -end - -function os.validdate(year,month,day) - -- we assume that all three values are set - -- year is always ok, even if lua has a 1970 time limit - if month < 1 then - month = 1 - elseif month > 12 then - month = 12 - end - if day < 1 then - day = 1 - else - local max = nofdays(year,month) - if day > max then - day = max - end - end - return year, month, day -end diff --git a/tex/compat/lualibs/lualibs-package.lua b/tex/compat/lualibs/lualibs-package.lua deleted file mode 100644 index 075fcde25aed2ba381a4532c3a12ceb1ce5d615e..0000000000000000000000000000000000000000 --- a/tex/compat/lualibs/lualibs-package.lua +++ /dev/null @@ -1,362 +0,0 @@ -if not modules then modules = { } end modules ['l-package'] = { - version = 1.001, - comment = "companion to luat-lib.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- Code moved from data-lua and changed into a plug-in. - --- We overload the regular loader. We do so because we operate mostly in --- tds and use our own loader code. Alternatively we could use a more --- extensive definition of package.path and package.cpath but even then --- we're not done. Also, we now have better tracing. --- --- -- local mylib = require("libtest") --- -- local mysql = require("luasql.mysql") - -local type = type -local gsub, format, find = string.gsub, string.format, string.find - -local P, S, Cs, lpegmatch = lpeg.P, lpeg.S, lpeg.Cs, lpeg.match - -local package = package -local searchers = package.searchers or package.loaders - --- dummies - -local filejoin = file and file.join or function(path,name) return path .. "/" .. name end -local isreadable = file and file.is_readable or function(name) local f = io.open(name) if f then f:close() return true end end -local addsuffix = file and file.addsuffix or function(name,suffix) return name .. "." .. suffix end - --- local separator, concatinator, placeholder, pathofexecutable, ignorebefore = string.match(package.config,"(.-)\n(.-)\n(.-)\n(.-)\n(.-)\n") --- --- local config = { --- separator = separator, -- \ or / --- concatinator = concatinator, -- ; --- placeholder = placeholder, -- ? becomes name --- pathofexecutable = pathofexecutable, -- ! becomes executables dir (on windows) --- ignorebefore = ignorebefore, -- - remove all before this when making lua_open --- } - -local function cleanpath(path) -- hm, don't we have a helper for this? - return path -end - -local pattern = Cs((((1-S("\\/"))^0 * (S("\\/")^1/"/"))^0 * (P(".")^1/"/"+P(1))^1) * -1) - -local function lualibfile(name) - return lpegmatch(pattern,name) or name -end - -local offset = luarocks and 1 or 0 -- todo: also check other extras - -local helpers = package.helpers or { - cleanpath = cleanpath, - lualibfile = lualibfile, - trace = false, - report = function(...) print(format(...)) end, - builtin = { - ["preload table"] = searchers[1+offset], -- special case, built-in libs - ["path specification"] = searchers[2+offset], - ["cpath specification"] = searchers[3+offset], - ["all in one fallback"] = searchers[4+offset], -- special case, combined libs - }, - methods = { - }, - sequence = { - "already loaded", - "preload table", - "qualified path", -- beware, lua itself doesn't handle qualified paths (prepends ./) - "lua extra list", - "lib extra list", - "path specification", - "cpath specification", - "all in one fallback", - "not loaded", - } -} - -package.helpers = helpers - -local methods = helpers.methods -local builtin = helpers.builtin - --- extra tds/ctx paths ... a bit of overhead for efficient tracing - -local extraluapaths = { } -local extralibpaths = { } -local luapaths = nil -- delayed -local libpaths = nil -- delayed -local oldluapath = nil -local oldlibpath = nil - -local nofextralua = -1 -local nofextralib = -1 -local nofpathlua = -1 -local nofpathlib = -1 - -local function listpaths(what,paths) - local nofpaths = #paths - if nofpaths > 0 then - for i=1,nofpaths do - helpers.report("using %s path %i: %s",what,i,paths[i]) - end - else - helpers.report("no %s paths defined",what) - end - return nofpaths -end - -local function getextraluapaths() - if helpers.trace and #extraluapaths ~= nofextralua then - nofextralua = listpaths("extra lua",extraluapaths) - end - return extraluapaths -end - -local function getextralibpaths() - if helpers.trace and #extralibpaths ~= nofextralib then - nofextralib = listpaths("extra lib",extralibpaths) - end - return extralibpaths -end - -local function getluapaths() - local luapath = package.path or "" - if oldluapath ~= luapath then - luapaths = file.splitpath(luapath,";") - oldluapath = luapath - nofpathlua = -1 - end - if helpers.trace and #luapaths ~= nofpathlua then - nofpathlua = listpaths("builtin lua",luapaths) - end - return luapaths -end - -local function getlibpaths() - local libpath = package.cpath or "" - if oldlibpath ~= libpath then - libpaths = file.splitpath(libpath,";") - oldlibpath = libpath - nofpathlib = -1 - end - if helpers.trace and #libpaths ~= nofpathlib then - nofpathlib = listpaths("builtin lib",libpaths) - end - return libpaths -end - -package.luapaths = getluapaths -package.libpaths = getlibpaths -package.extraluapaths = getextraluapaths -package.extralibpaths = getextralibpaths - -local hashes = { - lua = { }, - lib = { }, -} - -local function registerpath(tag,what,target,...) - local pathlist = { ... } - local cleanpath = helpers.cleanpath - local trace = helpers.trace - local report = helpers.report - local hash = hashes[what] - -- - local function add(path) - local path = cleanpath(path) - if not hash[path] then - target[#target+1] = path - hash[path] = true - if trace then - report("registered %s path %s: %s",tag,#target,path) - end - else - if trace then - report("duplicate %s path: %s",tag,path) - end - end - end - -- - for p=1,#pathlist do - local path = pathlist[p] - if type(path) == "table" then - for i=1,#path do - add(path[i]) - end - else - add(path) - end - end - return paths -end - -helpers.registerpath = registerpath - -function package.extraluapath(...) - registerpath("extra lua","lua",extraluapaths,...) -end - -function package.extralibpath(...) - registerpath("extra lib","lib",extralibpaths,...) -end - --- lib loader (used elsewhere) - -local function loadedaslib(resolved,rawname) -- todo: strip all before first - - local base = gsub(rawname,"%.","_") - -- so, we can do a require("foo/bar") and initialize bar - -- local base = gsub(file.basename(rawname),"%.","_") - local init = "luaopen_" .. gsub(base,"%.","_") - if helpers.trace then - helpers.report("calling loadlib with '%s' with init '%s'",resolved,init) - end - return package.loadlib(resolved,init) -end - -helpers.loadedaslib = loadedaslib - --- wrapped and new loaders - -local function loadedbypath(name,rawname,paths,islib,what) - local trace = helpers.trace - for p=1,#paths do - local path = paths[p] - local resolved = filejoin(path,name) - if trace then - helpers.report("%s path, identifying '%s' on '%s'",what,name,path) - end - if isreadable(resolved) then - if trace then - helpers.report("%s path, '%s' found on '%s'",what,name,resolved) - end - if islib then - return loadedaslib(resolved,rawname) - else - return loadfile(resolved) - end - end - end -end - -helpers.loadedbypath = loadedbypath - -local function loadedbyname(name,rawname) - if find(name,"^/") or find(name,"^[a-zA-Z]:/") then - local trace=helpers.trace - if trace then - helpers.report("qualified name, identifying '%s'",what,name) - end - if isreadable(name) then - if trace then - helpers.report("qualified name, '%s' found",what,name) - end - return loadfile(name) - end - end -end - -helpers.loadedbyname = loadedbyname - -methods["already loaded"] = function(name) - return package.loaded[name] -end - -methods["preload table"] = function(name) - return builtin["preload table"](name) -end - -methods["qualified path"]=function(name) - return loadedbyname(addsuffix(lualibfile(name),"lua"),name) -end - -methods["lua extra list"] = function(name) - return loadedbypath(addsuffix(lualibfile(name),"lua"),name,getextraluapaths(),false,"lua") -end - -methods["lib extra list"] = function(name) - return loadedbypath(addsuffix(lualibfile(name),os.libsuffix),name,getextralibpaths(),true, "lib") -end - -methods["path specification"] = function(name) - getluapaths() -- triggers list building and tracing - return builtin["path specification"](name) -end - -methods["cpath specification"] = function(name) - getlibpaths() -- triggers list building and tracing - return builtin["cpath specification"](name) -end - -methods["all in one fallback"] = function(name) - return builtin["all in one fallback"](name) -end - -methods["not loaded"] = function(name) - if helpers.trace then - helpers.report("unable to locate '%s'",name or "?") - end - return nil -end - -local level = 0 -local used = { } - -helpers.traceused = false - -function helpers.loaded(name) - local sequence = helpers.sequence - level = level + 1 - for i=1,#sequence do - local method = sequence[i] - if helpers.trace then - helpers.report("%s, level '%s', method '%s', name '%s'","locating",level,method,name) - end - local result, rest = methods[method](name) - if type(result) == "function" then - if helpers.trace then - helpers.report("%s, level '%s', method '%s', name '%s'","found",level,method,name) - end - if helpers.traceused then - used[#used+1] = { level = level, name = name } - end - level = level - 1 - return result, rest - end - end - -- safeguard, we never come here - level = level - 1 - return nil -end - -function helpers.showused() - local n = #used - if n > 0 then - helpers.report("%s libraries loaded:",n) - helpers.report() - for i=1,n do - local u = used[i] - helpers.report("%i %a",u.level,u.name) - end - helpers.report() - end -end - -function helpers.unload(name) - if helpers.trace then - if package.loaded[name] then - helpers.report("unloading, name '%s', %s",name,"done") - else - helpers.report("unloading, name '%s', %s",name,"not loaded") - end - end - package.loaded[name] = nil -end - --- overloading require does not work out well so we need to push it in --- front .. - -table.insert(searchers,1,helpers.loaded) diff --git a/tex/compat/lualibs/lualibs-set.lua b/tex/compat/lualibs/lualibs-set.lua deleted file mode 100644 index 2370f0139ff7285529a8a2bf8651e08186dee4a6..0000000000000000000000000000000000000000 --- a/tex/compat/lualibs/lualibs-set.lua +++ /dev/null @@ -1,87 +0,0 @@ -if not modules then modules = { } end modules ['l-set'] = { - version = 1.001, - comment = "companion to luat-lib.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- This will become obsolete when we have the bitset library embedded. - -set = set or { } - -local nums = { } -local tabs = { } -local concat = table.concat -local next, type = next, type - -set.create = table.tohash - -function set.tonumber(t) - if next(t) then - local s = "" - -- we could save mem by sorting, but it slows down - for k, v in next, t do - if v then - -- why bother about the leading space - s = s .. " " .. k - end - end - local n = nums[s] - if not n then - n = #tabs + 1 - tabs[n] = t - nums[s] = n - end - return n - else - return 0 - end -end - -function set.totable(n) - if n == 0 then - return { } - else - return tabs[n] or { } - end -end - -function set.tolist(n) - if n == 0 or not tabs[n] then - return "" - else - local t, n = { }, 0 - for k, v in next, tabs[n] do - if v then - n = n + 1 - t[n] = k - end - end - return concat(t," ") - end -end - -function set.contains(n,s) - if type(n) == "table" then - return n[s] - elseif n == 0 then - return false - else - local t = tabs[n] - return t and t[s] - end -end - ---~ local c = set.create{'aap','noot','mies'} ---~ local s = set.tonumber(c) ---~ local t = set.totable(s) ---~ print(t['aap']) ---~ local c = set.create{'zus','wim','jet'} ---~ local s = set.tonumber(c) ---~ local t = set.totable(s) ---~ print(t['aap']) ---~ print(t['jet']) ---~ print(set.contains(t,'jet')) ---~ print(set.contains(t,'aap')) - diff --git a/tex/compat/lualibs/lualibs-string.lua b/tex/compat/lualibs/lualibs-string.lua deleted file mode 100644 index e9dc2bbbcff8dca1daa96705b8b0ff216f66e0af..0000000000000000000000000000000000000000 --- a/tex/compat/lualibs/lualibs-string.lua +++ /dev/null @@ -1,213 +0,0 @@ -if not modules then modules = { } end modules ['l-string'] = { - version = 1.001, - comment = "companion to luat-lib.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -local string = string -local sub, gmatch, format, char, byte, rep, lower = string.sub, string.gmatch, string.format, string.char, string.byte, string.rep, string.lower -local lpegmatch, patterns = lpeg.match, lpeg.patterns -local P, S, C, Ct, Cc, Cs = lpeg.P, lpeg.S, lpeg.C, lpeg.Ct, lpeg.Cc, lpeg.Cs - --- Some functions are already defined in l-lpeg and maybe some from here will --- move there (unless we also expose caches). - --- if not string.split then --- --- function string.split(str,pattern) --- local t = { } --- if #str > 0 then --- local n = 1 --- for s in gmatch(str..pattern,"(.-)"..pattern) do --- t[n] = s --- n = n + 1 --- end --- end --- return t --- end --- --- end - --- function string.unquoted(str) --- return (gsub(str,"^([\"\'])(.*)%1$","%2")) -- interesting pattern --- end - -local unquoted = patterns.squote * C(patterns.nosquote) * patterns.squote - + patterns.dquote * C(patterns.nodquote) * patterns.dquote - -function string.unquoted(str) - return lpegmatch(unquoted,str) or str -end - --- print(string.unquoted("test")) --- print(string.unquoted([["t\"est"]])) --- print(string.unquoted([["t\"est"x]])) --- print(string.unquoted("\'test\'")) --- print(string.unquoted('"test"')) --- print(string.unquoted('"test"')) - -function string.quoted(str) - return format("%q",str) -- always double quote -end - -function string.count(str,pattern) -- variant 3 - local n = 0 - for _ in gmatch(str,pattern) do -- not for utf - n = n + 1 - end - return n -end - -function string.limit(str,n,sentinel) -- not utf proof - if #str > n then - sentinel = sentinel or "..." - return sub(str,1,(n-#sentinel)) .. sentinel - else - return str - end -end - -local stripper = patterns.stripper -local fullstripper = patterns.fullstripper -local collapser = patterns.collapser -local longtostring = patterns.longtostring - -function string.strip(str) - return lpegmatch(stripper,str) or "" -end - -function string.fullstrip(str) - return lpegmatch(fullstripper,str) or "" -end - -function string.collapsespaces(str) - return lpegmatch(collapser,str) or "" -end - -function string.longtostring(str) - return lpegmatch(longtostring,str) or "" -end - --- function string.is_empty(str) --- return not find(str,"%S") --- end - -local pattern = P(" ")^0 * P(-1) -- maybe also newlines - --- patterns.onlyspaces = pattern - -function string.is_empty(str) - if str == "" then - return true - else - return lpegmatch(pattern,str) and true or false - end -end - --- if not string.escapedpattern then --- --- local patterns_escapes = { --- ["%"] = "%%", --- ["."] = "%.", --- ["+"] = "%+", ["-"] = "%-", ["*"] = "%*", --- ["["] = "%[", ["]"] = "%]", --- ["("] = "%(", [")"] = "%)", --- -- ["{"] = "%{", ["}"] = "%}" --- -- ["^"] = "%^", ["$"] = "%$", --- } --- --- local simple_escapes = { --- ["-"] = "%-", --- ["."] = "%.", --- ["?"] = ".", --- ["*"] = ".*", --- } --- --- function string.escapedpattern(str,simple) --- return (gsub(str,".",simple and simple_escapes or patterns_escapes)) --- end --- --- function string.topattern(str,lowercase,strict) --- if str == "" then --- return ".*" --- else --- str = gsub(str,".",simple_escapes) --- if lowercase then --- str = lower(str) --- end --- if strict then --- return "^" .. str .. "$" --- else --- return str --- end --- end --- end --- --- end - ---- needs checking - -local anything = patterns.anything -local allescapes = Cc("%") * S(".-+%?()[]*") -- also {} and ^$ ? -local someescapes = Cc("%") * S(".-+%()[]") -- also {} and ^$ ? -local matchescapes = Cc(".") * S("*?") -- wildcard and single match - -local pattern_a = Cs ( ( allescapes + anything )^0 ) -local pattern_b = Cs ( ( someescapes + matchescapes + anything )^0 ) -local pattern_c = Cs ( Cc("^") * ( someescapes + matchescapes + anything )^0 * Cc("$") ) - -function string.escapedpattern(str,simple) - return lpegmatch(simple and pattern_b or pattern_a,str) -end - -function string.topattern(str,lowercase,strict) - if str=="" or type(str) ~= "string" then - return ".*" - elseif strict then - str = lpegmatch(pattern_c,str) - else - str = lpegmatch(pattern_b,str) - end - if lowercase then - return lower(str) - else - return str - end -end - --- print(string.escapedpattern("12+34*.tex",false)) --- print(string.escapedpattern("12+34*.tex",true)) --- print(string.topattern ("12+34*.tex",false,false)) --- print(string.topattern ("12+34*.tex",false,true)) - -function string.valid(str,default) - return (type(str) == "string" and str ~= "" and str) or default or nil -end - --- handy fallback - -string.itself = function(s) return s end - --- also handy (see utf variant) - -local pattern_c = Ct( C(1) ^0) -- string and not utf ! -local pattern_b = Ct((C(1)/byte)^0) - -function string.totable(str,bytes) - return lpegmatch(bytes and pattern_b or pattern_c,str) -end - --- handy from within tex: - -local replacer = lpeg.replacer("@","%%") -- Watch the escaped % in lpeg! - -function string.tformat(fmt,...) - return format(lpegmatch(replacer,fmt),...) -end - --- obsolete names: - -string.quote = string.quoted -string.unquote = string.unquoted diff --git a/tex/compat/lualibs/lualibs-table.lua b/tex/compat/lualibs/lualibs-table.lua deleted file mode 100644 index 552097e1c10d70d4f5806886ed3495f9622c72a0..0000000000000000000000000000000000000000 --- a/tex/compat/lualibs/lualibs-table.lua +++ /dev/null @@ -1,1265 +0,0 @@ -if not modules then modules = { } end modules ['l-table'] = { - version = 1.001, - comment = "companion to luat-lib.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -local type, next, tostring, tonumber, ipairs, select = type, next, tostring, tonumber, ipairs, select -local table, string = table, string -local concat, sort, insert, remove = table.concat, table.sort, table.insert, table.remove -local format, lower, dump = string.format, string.lower, string.dump -local getmetatable, setmetatable = getmetatable, setmetatable -local getinfo = debug.getinfo -local lpegmatch, patterns = lpeg.match, lpeg.patterns -local floor = math.floor - --- extra functions, some might go (when not used) --- --- we could serialize using %a but that won't work well is in the code we mostly use --- floats and as such we get unequality e.g. in version comparisons - -local stripper = patterns.stripper - -function table.strip(tab) - local lst, l = { }, 0 - for i=1,#tab do - local s = lpegmatch(stripper,tab[i]) or "" - if s == "" then - -- skip this one - else - l = l + 1 - lst[l] = s - end - end - return lst -end - -function table.keys(t) - if t then - local keys, k = { }, 0 - for key in next, t do - k = k + 1 - keys[k] = key - end - return keys - else - return { } - end -end - --- local function compare(a,b) --- local ta = type(a) -- needed, else 11 < 2 --- local tb = type(b) -- needed, else 11 < 2 --- if ta == tb and ta == "number" then --- return a < b --- else --- return tostring(a) < tostring(b) -- not that efficient --- end --- end - --- local function compare(a,b) --- local ta = type(a) -- needed, else 11 < 2 --- local tb = type(b) -- needed, else 11 < 2 --- if ta == tb and (ta == "number" or ta == "string") then --- return a < b --- else --- return tostring(a) < tostring(b) -- not that efficient --- end --- end - --- local function sortedkeys(tab) --- if tab then --- local srt, category, s = { }, 0, 0 -- 0=unknown 1=string, 2=number 3=mixed --- for key in next, tab do --- s = s + 1 --- srt[s] = key --- if category == 3 then --- -- no further check --- else --- local tkey = type(key) --- if tkey == "string" then --- category = (category == 2 and 3) or 1 --- elseif tkey == "number" then --- category = (category == 1 and 3) or 2 --- else --- category = 3 --- end --- end --- end --- if category == 0 or category == 3 then --- sort(srt,compare) --- else --- sort(srt) --- end --- return srt --- else --- return { } --- end --- end - --- local function compare(a,b) --- local ta = type(a) -- needed, else 11 < 2 --- local tb = type(b) -- needed, else 11 < 2 --- if ta == tb and (ta == "number" or ta == "string") then --- return a < b --- else --- return tostring(a) < tostring(b) -- not that efficient --- end --- end - --- local function compare(a,b) --- local ta = type(a) -- needed, else 11 < 2 --- if ta == "number" or ta == "string" then --- local tb = type(b) -- needed, else 11 < 2 --- if ta == tb then --- return a < b --- end --- end --- return tostring(a) < tostring(b) -- not that efficient --- end - -local function compare(a,b) - local ta = type(a) -- needed, else 11 < 2 - if ta == "number" then - local tb = type(b) -- needed, else 11 < 2 - if ta == tb then - return a < b - elseif tb == "string" then - return tostring(a) < b - end - elseif ta == "string" then - local tb = type(b) -- needed, else 11 < 2 - if ta == tb then - return a < b - else - return a < tostring(b) - end - end - return tostring(a) < tostring(b) -- not that efficient -end - -local function sortedkeys(tab) - if tab then - local srt, category, s = { }, 0, 0 -- 0=unknown 1=string, 2=number 3=mixed - for key in next, tab do - s = s + 1 - srt[s] = key - if category == 3 then - -- no further check - elseif category == 1 then - if type(key) ~= "string" then - category = 3 - end - elseif category == 2 then - if type(key) ~= "number" then - category = 3 - end - else - local tkey = type(key) - if tkey == "string" then - category = 1 - elseif tkey == "number" then - category = 2 - else - category = 3 - end - end - end - if s < 2 then - -- nothing to sort - elseif category == 3 then - sort(srt,compare) - else - sort(srt) - end - return srt - else - return { } - end -end - -local function sortedhashonly(tab) - if tab then - local srt, s = { }, 0 - for key in next, tab do - if type(key) == "string" then - s = s + 1 - srt[s] = key - end - end - if s > 1 then - sort(srt) - end - return srt - else - return { } - end -end - -local function sortedindexonly(tab) - if tab then - local srt, s = { }, 0 - for key in next, tab do - if type(key) == "number" then - s = s + 1 - srt[s] = key - end - end - if s > 1 then - sort(srt) - end - return srt - else - return { } - end -end - -local function sortedhashkeys(tab,cmp) -- fast one - if tab then - local srt, s = { }, 0 - for key in next, tab do - if key then - s= s + 1 - srt[s] = key - end - end - if s > 1 then - sort(srt,cmp) - end - return srt - else - return { } - end -end - -function table.allkeys(t) - local keys = { } - for k, v in next, t do - for k in next, v do - keys[k] = true - end - end - return sortedkeys(keys) -end - -table.sortedkeys = sortedkeys -table.sortedhashonly = sortedhashonly -table.sortedindexonly = sortedindexonly -table.sortedhashkeys = sortedhashkeys - -local function nothing() end - -local function sortedhash(t,cmp) - if t then - local s - if cmp then - -- it would be nice if the sort function would accept a third argument (or nicer, an optional first) - s = sortedhashkeys(t,function(a,b) return cmp(t,a,b) end) - else - s = sortedkeys(t) -- the robust one - end - local m = #s - if m == 1 then - return next, t - elseif m > 0 then - local n = 0 - return function() - if n < m then - n = n + 1 - local k = s[n] - return k, t[k] - end - end - end - end - return nothing -end - -table.sortedhash = sortedhash -table.sortedpairs = sortedhash -- obsolete - -function table.append(t,list) - local n = #t - for i=1,#list do - n = n + 1 - t[n] = list[i] - end - return t -end - -function table.prepend(t, list) - local nl = #list - local nt = nl + #t - for i=#t,1,-1 do - t[nt] = t[i] - nt = nt - 1 - end - for i=1,#list do - t[i] = list[i] - end - return t -end - --- function table.merge(t, ...) -- first one is target --- t = t or { } --- local lst = { ... } --- for i=1,#lst do --- for k, v in next, lst[i] do --- t[k] = v --- end --- end --- return t --- end - -function table.merge(t, ...) -- first one is target - t = t or { } - for i=1,select("#",...) do - for k, v in next, (select(i,...)) do - t[k] = v - end - end - return t -end - --- function table.merged(...) --- local tmp, lst = { }, { ... } --- for i=1,#lst do --- for k, v in next, lst[i] do --- tmp[k] = v --- end --- end --- return tmp --- end - -function table.merged(...) - local t = { } - for i=1,select("#",...) do - for k, v in next, (select(i,...)) do - t[k] = v - end - end - return t -end - --- function table.imerge(t, ...) --- local lst, nt = { ... }, #t --- for i=1,#lst do --- local nst = lst[i] --- for j=1,#nst do --- nt = nt + 1 --- t[nt] = nst[j] --- end --- end --- return t --- end - -function table.imerge(t, ...) - local nt = #t - for i=1,select("#",...) do - local nst = select(i,...) - for j=1,#nst do - nt = nt + 1 - t[nt] = nst[j] - end - end - return t -end - --- function table.imerged(...) --- local tmp, ntmp, lst = { }, 0, {...} --- for i=1,#lst do --- local nst = lst[i] --- for j=1,#nst do --- ntmp = ntmp + 1 --- tmp[ntmp] = nst[j] --- end --- end --- return tmp --- end - -function table.imerged(...) - local tmp, ntmp = { }, 0 - for i=1,select("#",...) do - local nst = select(i,...) - for j=1,#nst do - ntmp = ntmp + 1 - tmp[ntmp] = nst[j] - end - end - return tmp -end - -local function fastcopy(old,metatabletoo) -- fast one - if old then - local new = { } - for k, v in next, old do - if type(v) == "table" then - new[k] = fastcopy(v,metatabletoo) -- was just table.copy - else - new[k] = v - end - end - if metatabletoo then - -- optional second arg - local mt = getmetatable(old) - if mt then - setmetatable(new,mt) - end - end - return new - else - return { } - end -end - --- todo : copy without metatable - -local function copy(t, tables) -- taken from lua wiki, slightly adapted - tables = tables or { } - local tcopy = { } - if not tables[t] then - tables[t] = tcopy - end - for i,v in next, t do -- brrr, what happens with sparse indexed - if type(i) == "table" then - if tables[i] then - i = tables[i] - else - i = copy(i, tables) - end - end - if type(v) ~= "table" then - tcopy[i] = v - elseif tables[v] then - tcopy[i] = tables[v] - else - tcopy[i] = copy(v, tables) - end - end - local mt = getmetatable(t) - if mt then - setmetatable(tcopy,mt) - end - return tcopy -end - -table.fastcopy = fastcopy -table.copy = copy - -function table.derive(parent) -- for the moment not public - local child = { } - if parent then - setmetatable(child,{ __index = parent }) - end - return child -end - -function table.tohash(t,value) - local h = { } - if t then - if value == nil then value = true end - for _, v in next, t do -- no ipairs here - h[v] = value - end - end - return h -end - -function table.fromhash(t) - local hsh, h = { }, 0 - for k, v in next, t do -- no ipairs here - if v then - h = h + 1 - hsh[h] = k - end - end - return hsh -end - -local noquotes, hexify, handle, compact, inline, functions - -local reserved = table.tohash { -- intercept a language inconvenience: no reserved words as key - 'and', 'break', 'do', 'else', 'elseif', 'end', 'false', 'for', 'function', 'if', - 'in', 'local', 'nil', 'not', 'or', 'repeat', 'return', 'then', 'true', 'until', 'while', - 'NaN', 'goto', -} - --- local function simple_table(t) --- if #t > 0 then --- local n = 0 --- for _,v in next, t do --- n = n + 1 --- end --- if n == #t then --- local tt, nt = { }, 0 --- for i=1,#t do --- local v = t[i] --- local tv = type(v) --- if tv == "number" then --- nt = nt + 1 --- if hexify then --- tt[nt] = format("0x%X",v) --- else --- tt[nt] = tostring(v) -- tostring not needed --- end --- elseif tv == "string" then --- nt = nt + 1 --- tt[nt] = format("%q",v) --- elseif tv == "boolean" then --- nt = nt + 1 --- tt[nt] = v and "true" or "false" --- else --- return nil --- end --- end --- return tt --- end --- end --- return nil --- end - -local function simple_table(t) - local nt = #t - if nt > 0 then - local n = 0 - for _,v in next, t do - n = n + 1 - -- if type(v) == "table" then - -- return nil - -- end - end - if n == nt then - local tt = { } - for i=1,nt do - local v = t[i] - local tv = type(v) - if tv == "number" then - if hexify then - tt[i] = format("0x%X",v) - else - tt[i] = tostring(v) -- tostring not needed - end - elseif tv == "string" then - tt[i] = format("%q",v) - elseif tv == "boolean" then - tt[i] = v and "true" or "false" - else - return nil - end - end - return tt - end - end - return nil -end - --- Because this is a core function of mkiv I moved some function calls --- inline. --- --- twice as fast in a test: --- --- local propername = lpeg.P(lpeg.R("AZ","az","__") * lpeg.R("09","AZ","az", "__")^0 * lpeg.P(-1) ) - --- problem: there no good number_to_string converter with the best resolution - --- probably using .. is faster than format --- maybe split in a few cases (yes/no hexify) - --- todo: %g faster on numbers than %s - --- we can speed this up with repeaters and formatters but we haven't defined them --- yet - -local propername = patterns.propername -- was find(name,"^%a[%w%_]*$") - -local function dummy() end - -local function do_serialize(root,name,depth,level,indexed) - if level > 0 then - depth = depth .. " " - if indexed then - handle(format("%s{",depth)) - else - local tn = type(name) - if tn == "number" then - if hexify then - handle(format("%s[0x%X]={",depth,name)) - else - handle(format("%s[%s]={",depth,name)) - end - elseif tn == "string" then - if noquotes and not reserved[name] and lpegmatch(propername,name) then - handle(format("%s%s={",depth,name)) - else - handle(format("%s[%q]={",depth,name)) - end - elseif tn == "boolean" then - handle(format("%s[%s]={",depth,name and "true" or "false")) - else - handle(format("%s{",depth)) - end - end - end - -- we could check for k (index) being number (cardinal) - if root and next(root) ~= nil then - local first, last = nil, 0 - if compact then - last = #root - for k=1,last do - if root[k] == nil then - last = k - 1 - break - end - end - if last > 0 then - first = 1 - end - end - local sk = sortedkeys(root) - for i=1,#sk do - local k = sk[i] - local v = root[k] - local tv = type(v) - local tk = type(k) - if compact and first and tk == "number" and k >= first and k <= last then - if tv == "number" then - if hexify then - handle(format("%s 0x%X,",depth,v)) - else - handle(format("%s %s,",depth,v)) -- %.99g - end - elseif tv == "string" then - handle(format("%s %q,",depth,v)) - elseif tv == "table" then - if next(v) == nil then - handle(format("%s {},",depth)) - elseif inline then -- and #t > 0 - local st = simple_table(v) - if st then - handle(format("%s { %s },",depth,concat(st,", "))) - else - do_serialize(v,k,depth,level+1,true) - end - else - do_serialize(v,k,depth,level+1,true) - end - elseif tv == "boolean" then - handle(format("%s %s,",depth,v and "true" or "false")) - elseif tv == "function" then - if functions then - handle(format('%s load(%q),',depth,dump(v))) -- maybe strip - else - handle(format('%s "function",',depth)) - end - else - handle(format("%s %q,",depth,tostring(v))) - end - elseif k == "__p__" then -- parent - if false then - handle(format("%s __p__=nil,",depth)) - end - elseif tv == "number" then - if tk == "number" then - if hexify then - handle(format("%s [0x%X]=0x%X,",depth,k,v)) - else - handle(format("%s [%s]=%s,",depth,k,v)) -- %.99g - end - elseif tk == "boolean" then - if hexify then - handle(format("%s [%s]=0x%X,",depth,k and "true" or "false",v)) - else - handle(format("%s [%s]=%s,",depth,k and "true" or "false",v)) -- %.99g - end - elseif noquotes and not reserved[k] and lpegmatch(propername,k) then - if hexify then - handle(format("%s %s=0x%X,",depth,k,v)) - else - handle(format("%s %s=%s,",depth,k,v)) -- %.99g - end - else - if hexify then - handle(format("%s [%q]=0x%X,",depth,k,v)) - else - handle(format("%s [%q]=%s,",depth,k,v)) -- %.99g - end - end - elseif tv == "string" then - if tk == "number" then - if hexify then - handle(format("%s [0x%X]=%q,",depth,k,v)) - else - handle(format("%s [%s]=%q,",depth,k,v)) - end - elseif tk == "boolean" then - handle(format("%s [%s]=%q,",depth,k and "true" or "false",v)) - elseif noquotes and not reserved[k] and lpegmatch(propername,k) then - handle(format("%s %s=%q,",depth,k,v)) - else - handle(format("%s [%q]=%q,",depth,k,v)) - end - elseif tv == "table" then - if next(v) == nil then - if tk == "number" then - if hexify then - handle(format("%s [0x%X]={},",depth,k)) - else - handle(format("%s [%s]={},",depth,k)) - end - elseif tk == "boolean" then - handle(format("%s [%s]={},",depth,k and "true" or "false")) - elseif noquotes and not reserved[k] and lpegmatch(propername,k) then - handle(format("%s %s={},",depth,k)) - else - handle(format("%s [%q]={},",depth,k)) - end - elseif inline then - local st = simple_table(v) - if st then - if tk == "number" then - if hexify then - handle(format("%s [0x%X]={ %s },",depth,k,concat(st,", "))) - else - handle(format("%s [%s]={ %s },",depth,k,concat(st,", "))) - end - elseif tk == "boolean" then - handle(format("%s [%s]={ %s },",depth,k and "true" or "false",concat(st,", "))) - elseif noquotes and not reserved[k] and lpegmatch(propername,k) then - handle(format("%s %s={ %s },",depth,k,concat(st,", "))) - else - handle(format("%s [%q]={ %s },",depth,k,concat(st,", "))) - end - else - do_serialize(v,k,depth,level+1) - end - else - do_serialize(v,k,depth,level+1) - end - elseif tv == "boolean" then - if tk == "number" then - if hexify then - handle(format("%s [0x%X]=%s,",depth,k,v and "true" or "false")) - else - handle(format("%s [%s]=%s,",depth,k,v and "true" or "false")) - end - elseif tk == "boolean" then - handle(format("%s [%s]=%s,",depth,tostring(k),v and "true" or "false")) - elseif noquotes and not reserved[k] and lpegmatch(propername,k) then - handle(format("%s %s=%s,",depth,k,v and "true" or "false")) - else - handle(format("%s [%q]=%s,",depth,k,v and "true" or "false")) - end - elseif tv == "function" then - if functions then - local f = getinfo(v).what == "C" and dump(dummy) or dump(v) -- maybe strip - -- local f = getinfo(v).what == "C" and dump(function(...) return v(...) end) or dump(v) -- maybe strip - if tk == "number" then - if hexify then - handle(format("%s [0x%X]=load(%q),",depth,k,f)) - else - handle(format("%s [%s]=load(%q),",depth,k,f)) - end - elseif tk == "boolean" then - handle(format("%s [%s]=load(%q),",depth,k and "true" or "false",f)) - elseif noquotes and not reserved[k] and lpegmatch(propername,k) then - handle(format("%s %s=load(%q),",depth,k,f)) - else - handle(format("%s [%q]=load(%q),",depth,k,f)) - end - end - else - if tk == "number" then - if hexify then - handle(format("%s [0x%X]=%q,",depth,k,tostring(v))) - else - handle(format("%s [%s]=%q,",depth,k,tostring(v))) - end - elseif tk == "boolean" then - handle(format("%s [%s]=%q,",depth,k and "true" or "false",tostring(v))) - elseif noquotes and not reserved[k] and lpegmatch(propername,k) then - handle(format("%s %s=%q,",depth,k,tostring(v))) - else - handle(format("%s [%q]=%q,",depth,k,tostring(v))) - end - end - end - end - if level > 0 then - handle(format("%s},",depth)) - end -end - --- replacing handle by a direct t[#t+1] = ... (plus test) is not much --- faster (0.03 on 1.00 for zapfino.tma) - -local function serialize(_handle,root,name,specification) -- handle wins - local tname = type(name) - if type(specification) == "table" then - noquotes = specification.noquotes - hexify = specification.hexify - handle = _handle or specification.handle or print - functions = specification.functions - compact = specification.compact - inline = specification.inline and compact - if functions == nil then - functions = true - end - if compact == nil then - compact = true - end - if inline == nil then - inline = compact - end - else - noquotes = false - hexify = false - handle = _handle or print - compact = true - inline = true - functions = true - end - if tname == "string" then - if name == "return" then - handle("return {") - else - handle(name .. "={") - end - elseif tname == "number" then - if hexify then - handle(format("[0x%X]={",name)) - else - handle("[" .. name .. "]={") - end - elseif tname == "boolean" then - if name then - handle("return {") - else - handle("{") - end - else - handle("t={") - end - if root then - -- The dummy access will initialize a table that has a delayed initialization - -- using a metatable. (maybe explicitly test for metatable) - if getmetatable(root) then -- todo: make this an option, maybe even per subtable - local dummy = root._w_h_a_t_e_v_e_r_ - root._w_h_a_t_e_v_e_r_ = nil - end - -- Let's forget about empty tables. - if next(root) ~= nil then - do_serialize(root,name,"",0) - end - end - handle("}") -end - --- A version with formatters is some 20% faster than using format (because formatters are --- much faster) but of course, inlining the format using .. is then again faster .. anyway, --- as we do some pretty printing as well there is not that much to gain unless we make a --- 'fast' ugly variant as well. But, we would have to move the formatter to l-string then. - --- name: --- --- true : return { } --- false : { } --- nil : t = { } --- string : string = { } --- "return" : return { } --- number : [number] = { } - -function table.serialize(root,name,specification) - local t, n = { }, 0 - local function flush(s) - n = n + 1 - t[n] = s - end - serialize(flush,root,name,specification) - return concat(t,"\n") -end - --- local a = { e = { 1,2,3,4,5,6}, a = 1, b = 2, c = "ccc", d = { a = 1, b = 2, c = "ccc", d = { a = 1, b = 2, c = "ccc" } } } --- local t = os.clock() --- for i=1,10000 do --- table.serialize(a) --- end --- print(os.clock()-t,table.serialize(a)) - -table.tohandle = serialize - -local maxtab = 2*1024 - -function table.tofile(filename,root,name,specification) - local f = io.open(filename,'w') - if f then - if maxtab > 1 then - local t, n = { }, 0 - local function flush(s) - n = n + 1 - t[n] = s - if n > maxtab then - f:write(concat(t,"\n"),"\n") -- hm, write(sometable) should be nice - t, n = { }, 0 -- we could recycle t if needed - end - end - serialize(flush,root,name,specification) - f:write(concat(t,"\n"),"\n") - else - local function flush(s) - f:write(s,"\n") - end - serialize(flush,root,name,specification) - end - f:close() - io.flush() - end -end - -local function flattened(t,f,depth) -- also handles { nil, 1, nil, 2 } - if f == nil then - f = { } - depth = 0xFFFF - elseif tonumber(f) then - -- assume that only two arguments are given - depth = f - f = { } - elseif not depth then - depth = 0xFFFF - end - for k, v in next, t do - if type(k) ~= "number" then - if depth > 0 and type(v) == "table" then - flattened(v,f,depth-1) - else - f[#f+1] = v - end - end - end - for k=1,#t do - local v = t[k] - if depth > 0 and type(v) == "table" then - flattened(v,f,depth-1) - else - f[#f+1] = v - end - end - return f -end - -table.flattened = flattened - -local function unnest(t,f) -- only used in mk, for old times sake - if not f then -- and only relevant for token lists - f = { } -- this one can become obsolete - end - for i=1,#t do - local v = t[i] - if type(v) == "table" then - if type(v[1]) == "table" then - unnest(v,f) - else - f[#f+1] = v - end - else - f[#f+1] = v - end - end - return f -end - -function table.unnest(t) -- bad name - return unnest(t) -end - -local function are_equal(a,b,n,m) -- indexed - if a and b and #a == #b then - n = n or 1 - m = m or #a - for i=n,m do - local ai, bi = a[i], b[i] - if ai==bi then - -- same - elseif type(ai) == "table" and type(bi) == "table" then - if not are_equal(ai,bi) then - return false - end - else - return false - end - end - return true - else - return false - end -end - -local function identical(a,b) -- assumes same structure - for ka, va in next, a do - local vb = b[ka] - if va == vb then - -- same - elseif type(va) == "table" and type(vb) == "table" then - if not identical(va,vb) then - return false - end - else - return false - end - end - return true -end - -table.identical = identical -table.are_equal = are_equal - -local function sparse(old,nest,keeptables) - local new = { } - for k, v in next, old do - if not (v == "" or v == false) then - if nest and type(v) == "table" then - v = sparse(v,nest) - if keeptables or next(v) ~= nil then - new[k] = v - end - else - new[k] = v - end - end - end - return new -end - -table.sparse = sparse - -function table.compact(t) - return sparse(t,true,true) -end - -function table.contains(t, v) - if t then - for i=1, #t do - if t[i] == v then - return i - end - end - end - return false -end - -function table.count(t) - local n = 0 - for k, v in next, t do - n = n + 1 - end - return n -end - -function table.swapped(t,s) -- hash - local n = { } - if s then - for k, v in next, s do - n[k] = v - end - end - for k, v in next, t do - n[v] = k - end - return n -end - -function table.mirrored(t) -- hash - local n = { } - for k, v in next, t do - n[v] = k - n[k] = v - end - return n -end - -function table.reversed(t) - if t then - local tt, tn = { }, #t - if tn > 0 then - local ttn = 0 - for i=tn,1,-1 do - ttn = ttn + 1 - tt[ttn] = t[i] - end - end - return tt - end -end - -function table.reverse(t) - if t then - local n = #t - for i=1,floor(n/2) do - local j = n - i + 1 - t[i], t[j] = t[j], t[i] - end - return t - end -end - -function table.sequenced(t,sep,simple) -- hash only - if not t then - return "" - end - local n = #t - local s = { } - if n > 0 then - -- indexed - for i=1,n do - s[i] = tostring(t[i]) - end - else - -- hashed - n = 0 - for k, v in sortedhash(t) do - if simple then - if v == true then - n = n + 1 - s[n] = k - elseif v and v~= "" then - n = n + 1 - s[n] = k .. "=" .. tostring(v) - end - else - n = n + 1 - s[n] = k .. "=" .. tostring(v) - end - end - end - return concat(s,sep or " | ") -end - -function table.print(t,...) - if type(t) ~= "table" then - print(tostring(t)) - else - serialize(print,t,...) - end -end - -if setinspector then - setinspector("table",function(v) if type(v) == "table" then serialize(print,v,"table") return true end end) -end - --- -- -- obsolete but we keep them for a while and might comment them later -- -- -- - --- roughly: copy-loop : unpack : sub == 0.9 : 0.4 : 0.45 (so in critical apps, use unpack) - -function table.sub(t,i,j) - return { unpack(t,i,j) } -end - --- slower than #t on indexed tables (#t only returns the size of the numerically indexed slice) - -function table.is_empty(t) - return not t or next(t) == nil -end - -function table.has_one_entry(t) - return t and next(t,next(t)) == nil -end - --- new - -function table.loweredkeys(t) -- maybe utf - local l = { } - for k, v in next, t do - l[lower(k)] = v - end - return l -end - --- new, might move (maybe duplicate) - -function table.unique(old) - local hash = { } - local new = { } - local n = 0 - for i=1,#old do - local oi = old[i] - if not hash[oi] then - n = n + 1 - new[n] = oi - hash[oi] = true - end - end - return new -end - -function table.sorted(t,...) - sort(t,...) - return t -- still sorts in-place -end - --- - -function table.values(t,s) -- optional sort flag - if t then - local values, keys, v = { }, { }, 0 - for key, value in next, t do - if not keys[value] then - v = v + 1 - values[v] = value - keys[k] = key - end - end - if s then - sort(values) - end - return values - else - return { } - end -end - --- maybe this will move to util-tab.lua - --- for k, v in table.filtered(t,pattern) do ... end --- for k, v in table.filtered(t,pattern,true) do ... end --- for k, v in table.filtered(t,pattern,true,cmp) do ... end - -function table.filtered(t,pattern,sort,cmp) - if t and type(pattern) == "string" then - if sort then - local s - if cmp then - -- it would be nice if the sort function would accept a third argument (or nicer, an optional first) - s = sortedhashkeys(t,function(a,b) return cmp(t,a,b) end) - else - s = sortedkeys(t) -- the robust one - end - local n = 0 - local m = #s - local function kv(s) - while n < m do - n = n + 1 - local k = s[n] - if find(k,pattern) then - return k, t[k] - end - end - end - return kv, s - else - local n = next(t) - local function iterator() - while n ~= nil do - local k = n - n = next(t,k) - if find(k,pattern) then - return k, t[k] - end - end - end - return iterator, t - end - else - return nothing - end -end diff --git a/tex/compat/lualibs/lualibs-trac-inf.lua b/tex/compat/lualibs/lualibs-trac-inf.lua deleted file mode 100644 index f4c4e5557879f2d9479dee948f7ca48fc0516aa0..0000000000000000000000000000000000000000 --- a/tex/compat/lualibs/lualibs-trac-inf.lua +++ /dev/null @@ -1,209 +0,0 @@ -if not modules then modules = { } end modules ['trac-inf'] = { - version = 1.001, - comment = "companion to trac-inf.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- As we want to protect the global tables, we no longer store the timing --- in the tables themselves but in a hidden timers table so that we don't --- get warnings about assignments. This is more efficient than using rawset --- and rawget. - -local type, tonumber, select = type, tonumber, select -local format, lower, find = string.format, string.lower, string.find -local concat = table.concat -local clock = os.gettimeofday or os.clock -- should go in environment - -local setmetatableindex = table.setmetatableindex -local serialize = table.serialize -local formatters = string.formatters - -statistics = statistics or { } -local statistics = statistics - -statistics.enable = true -statistics.threshold = 0.01 - -local statusinfo, n, registered, timers = { }, 0, { }, { } - -setmetatableindex(timers,function(t,k) - local v = { timing = 0, loadtime = 0 } - t[k] = v - return v -end) - -local function hastiming(instance) - return instance and timers[instance] -end - -local function resettiming(instance) - timers[instance or "notimer"] = { timing = 0, loadtime = 0 } -end - -local function starttiming(instance) - local timer = timers[instance or "notimer"] - local it = timer.timing or 0 - if it == 0 then - timer.starttime = clock() - if not timer.loadtime then - timer.loadtime = 0 - end - end - timer.timing = it + 1 -end - -local function stoptiming(instance) - local timer = timers[instance or "notimer"] - local it = timer.timing - if it > 1 then - timer.timing = it - 1 - else - local starttime = timer.starttime - if starttime then - local stoptime = clock() - local loadtime = stoptime - starttime - timer.stoptime = stoptime - timer.loadtime = timer.loadtime + loadtime - timer.timing = 0 - return loadtime - end - end - return 0 -end - -local function elapsed(instance) - if type(instance) == "number" then - return instance or 0 - else - local timer = timers[instance or "notimer"] - return timer and timer.loadtime or 0 - end -end - -local function elapsedtime(instance) - return format("%0.3f",elapsed(instance)) -end - -local function elapsedindeed(instance) - return elapsed(instance) > statistics.threshold -end - -local function elapsedseconds(instance,rest) -- returns nil if 0 seconds - if elapsedindeed(instance) then - return format("%0.3f seconds %s", elapsed(instance),rest or "") - end -end - -statistics.hastiming = hastiming -statistics.resettiming = resettiming -statistics.starttiming = starttiming -statistics.stoptiming = stoptiming -statistics.elapsed = elapsed -statistics.elapsedtime = elapsedtime -statistics.elapsedindeed = elapsedindeed -statistics.elapsedseconds = elapsedseconds - --- general function .. we might split this module - -function statistics.register(tag,fnc) - if statistics.enable and type(fnc) == "function" then - local rt = registered[tag] or (#statusinfo + 1) - statusinfo[rt] = { tag, fnc } - registered[tag] = rt - if #tag > n then n = #tag end - end -end - -local report = logs.reporter("mkiv lua stats") - -function statistics.show() - if statistics.enable then - -- this code will move - local register = statistics.register - register("used platform", function() - return format("%s, type: %s, binary subtree: %s", - os.platform or "unknown",os.type or "unknown", environment.texos or "unknown") - end) - register("luatex banner", function() - return lower(status.banner) - end) - register("control sequences", function() - return format("%s of %s + %s", status.cs_count, status.hash_size,status.hash_extra) - end) - register("callbacks", function() - local total, indirect = status.callbacks or 0, status.indirect_callbacks or 0 - return format("%s direct, %s indirect, %s total", total-indirect, indirect, total) - end) - if jit then - local jitstatus = { jit.status() } - if jitstatus[1] then - register("luajit options", concat(jitstatus," ",2)) - end - end - -- so far - -- collectgarbage("collect") - register("lua properties",function() - local hashchar = tonumber(status.luatex_hashchars) - local hashtype = status.luatex_hashtype - local mask = lua.mask or "ascii" - return format("engine: %s, used memory: %s, hash type: %s, hash chars: min(%s,40), symbol mask: %s (%s)", - jit and "luajit" or "lua", - statistics.memused(), - hashtype or "default", - hashchar and 2^hashchar or "unknown", - mask, - mask == "utf" and "τεχ" or "tex") - end) - register("runtime",statistics.runtime) - logs.newline() -- initial newline - for i=1,#statusinfo do - local s = statusinfo[i] - local r = s[2]() - if r then - report("%s: %s",s[1],r) - end - end - -- logs.newline() -- final newline - statistics.enable = false - end -end - -function statistics.memused() -- no math.round yet -) - local round = math.round or math.floor - return format("%s MB (ctx: %s MB)",round(collectgarbage("count")/1000), round(status.luastate_bytes/1000000)) -end - -starttiming(statistics) - -function statistics.formatruntime(runtime) -- indirect so it can be overloaded and - return format("%s seconds", runtime) -- indeed that happens in cure-uti.lua -end - -function statistics.runtime() - stoptiming(statistics) - return statistics.formatruntime(elapsedtime(statistics)) -end - -local report = logs.reporter("system") - -function statistics.timed(action) - starttiming("run") - action() - stoptiming("run") - report("total runtime: %s seconds",elapsedtime("run")) -end - --- goodie - -function statistics.tracefunction(base,tag,...) - for i=1,select("#",...) do - local name = select(i,...) - local stat = { } - local func = base[name] - setmetatableindex(stat,function(t,k) t[k] = 0 return 0 end) - base[name] = function(n,k,v) stat[k] = stat[k] + 1 return func(n,k,v) end - statistics.register(formatters["%s.%s"](tag,name),function() return serialize(stat,"calls") end) - end -end diff --git a/tex/compat/lualibs/lualibs-unicode.lua b/tex/compat/lualibs/lualibs-unicode.lua deleted file mode 100644 index 3dec8001345a16adcff34b04955593f8b0254c24..0000000000000000000000000000000000000000 --- a/tex/compat/lualibs/lualibs-unicode.lua +++ /dev/null @@ -1,1272 +0,0 @@ -if not modules then modules = { } end modules ['l-unicode'] = { - version = 1.001, - comment = "companion to luat-lib.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- in lua 5.3: - --- utf8.char(···) : concatinated --- utf8.charpatt : "[\0-\x7F\xC2-\xF4][\x80-\xBF]*" --- utf8.codes(s) : for p, c in utf8.codes(s) do body end --- utf8.codepoint(s [, i [, j]]) --- utf8.len(s [, i]) --- utf8.offset(s, n [, i]) - --- todo: utf.sub replacement (used in syst-aux) --- we put these in the utf namespace: - -utf = utf or (unicode and unicode.utf8) or { } - -utf.characters = utf.characters or string.utfcharacters -utf.values = utf.values or string.utfvalues - --- string.utfvalues --- string.utfcharacters --- string.characters --- string.characterpairs --- string.bytes --- string.bytepairs - -local type = type -local char, byte, format, sub, gmatch = string.char, string.byte, string.format, string.sub, string.gmatch -local concat = table.concat -local P, C, R, Cs, Ct, Cmt, Cc, Carg, Cp = lpeg.P, lpeg.C, lpeg.R, lpeg.Cs, lpeg.Ct, lpeg.Cmt, lpeg.Cc, lpeg.Carg, lpeg.Cp - -local lpegmatch = lpeg.match -local patterns = lpeg.patterns -local tabletopattern = lpeg.utfchartabletopattern - -local bytepairs = string.bytepairs - -local finder = lpeg.finder -local replacer = lpeg.replacer - -local utfvalues = utf.values -local utfgmatch = utf.gmatch -- not always present - -local p_utftype = patterns.utftype -local p_utfstricttype = patterns.utfstricttype -local p_utfoffset = patterns.utfoffset -local p_utf8char = patterns.utf8character -local p_utf8byte = patterns.utf8byte -local p_utfbom = patterns.utfbom -local p_newline = patterns.newline -local p_whitespace = patterns.whitespace - -if not unicode then - - unicode = { utf = utf } -- for a while - -end - -if not utf.char then - - local floor, char = math.floor, string.char - - function utf.char(n) - if n < 0x80 then - -- 0aaaaaaa : 0x80 - return char(n) - elseif n < 0x800 then - -- 110bbbaa : 0xC0 : n >> 6 - -- 10aaaaaa : 0x80 : n & 0x3F - return char( - 0xC0 + floor(n/0x40), - 0x80 + (n % 0x40) - ) - elseif n < 0x10000 then - -- 1110bbbb : 0xE0 : n >> 12 - -- 10bbbbaa : 0x80 : (n >> 6) & 0x3F - -- 10aaaaaa : 0x80 : n & 0x3F - return char( - 0xE0 + floor(n/0x1000), - 0x80 + (floor(n/0x40) % 0x40), - 0x80 + (n % 0x40) - ) - elseif n < 0x200000 then - -- 11110ccc : 0xF0 : n >> 18 - -- 10ccbbbb : 0x80 : (n >> 12) & 0x3F - -- 10bbbbaa : 0x80 : (n >> 6) & 0x3F - -- 10aaaaaa : 0x80 : n & 0x3F - -- dddd : ccccc - 1 - return char( - 0xF0 + floor(n/0x40000), - 0x80 + (floor(n/0x1000) % 0x40), - 0x80 + (floor(n/0x40) % 0x40), - 0x80 + (n % 0x40) - ) - else - return "" - end - end - -end - -if not utf.byte then - - local utf8byte = patterns.utf8byte - - function utf.byte(c) - return lpegmatch(utf8byte,c) - end - -end - -local utfchar, utfbyte = utf.char, utf.byte - --- As we want to get rid of the (unmaintained) utf library we implement our own --- variants (in due time an independent module): - -function utf.filetype(data) - return data and lpegmatch(p_utftype,data) or "unknown" -end - -local toentities = Cs ( - ( - patterns.utf8one - + ( - patterns.utf8two - + patterns.utf8three - + patterns.utf8four - ) / function(s) local b = utfbyte(s) if b < 127 then return s else return format("&#%X;",b) end end - )^0 -) - -patterns.toentities = toentities - -function utf.toentities(str) - return lpegmatch(toentities,str) -end - --- local utfchr = { } -- 60K -> 2.638 M extra mem but currently not called that often (on latin) --- --- setmetatable(utfchr, { __index = function(t,k) local v = utfchar(k) t[k] = v return v end } ) --- --- collectgarbage("collect") --- local u = collectgarbage("count")*1024 --- local t = os.clock() --- for i=1,1000 do --- for i=1,600 do --- local a = utfchr[i] --- end --- end --- print(os.clock()-t,collectgarbage("count")*1024-u) - --- collectgarbage("collect") --- local t = os.clock() --- for i=1,1000 do --- for i=1,600 do --- local a = utfchar(i) --- end --- end --- print(os.clock()-t,collectgarbage("count")*1024-u) - --- local byte = string.byte --- local utfchar = utf.char - -local one = P(1) -local two = C(1) * C(1) -local four = C(R(utfchar(0xD8),utfchar(0xFF))) * C(1) * C(1) * C(1) - --- actually one of them is already utf ... sort of useless this one - --- function utf.char(n) --- if n < 0x80 then --- return char(n) --- elseif n < 0x800 then --- return char( --- 0xC0 + floor(n/0x40), --- 0x80 + (n % 0x40) --- ) --- elseif n < 0x10000 then --- return char( --- 0xE0 + floor(n/0x1000), --- 0x80 + (floor(n/0x40) % 0x40), --- 0x80 + (n % 0x40) --- ) --- elseif n < 0x40000 then --- return char( --- 0xF0 + floor(n/0x40000), --- 0x80 + floor(n/0x1000), --- 0x80 + (floor(n/0x40) % 0x40), --- 0x80 + (n % 0x40) --- ) --- else --- -- return char( --- -- 0xF1 + floor(n/0x1000000), --- -- 0x80 + floor(n/0x40000), --- -- 0x80 + floor(n/0x1000), --- -- 0x80 + (floor(n/0x40) % 0x40), --- -- 0x80 + (n % 0x40) --- -- ) --- return "?" --- end --- end --- --- merge into: - -local pattern = P("\254\255") * Cs( ( - four / function(a,b,c,d) - local ab = 0xFF * byte(a) + byte(b) - local cd = 0xFF * byte(c) + byte(d) - return utfchar((ab-0xD800)*0x400 + (cd-0xDC00) + 0x10000) - end - + two / function(a,b) - return utfchar(byte(a)*256 + byte(b)) - end - + one - )^1 ) - + P("\255\254") * Cs( ( - four / function(b,a,d,c) - local ab = 0xFF * byte(a) + byte(b) - local cd = 0xFF * byte(c) + byte(d) - return utfchar((ab-0xD800)*0x400 + (cd-0xDC00) + 0x10000) - end - + two / function(b,a) - return utfchar(byte(a)*256 + byte(b)) - end - + one - )^1 ) - -function string.toutf(s) -- in string namespace - return lpegmatch(pattern,s) or s -- todo: utf32 -end - -local validatedutf = Cs ( - ( - patterns.utf8one - + patterns.utf8two - + patterns.utf8three - + patterns.utf8four - + P(1) / "�" - )^0 -) - -patterns.validatedutf = validatedutf - -function utf.is_valid(str) - return type(str) == "string" and lpegmatch(validatedutf,str) or false -end - -if not utf.len then - - -- -- alternative 1: 0.77 - -- - -- local utfcharcounter = utfbom^-1 * Cs((p_utf8char/'!')^0) - -- - -- function utf.len(str) - -- return #lpegmatch(utfcharcounter,str or "") - -- end - -- - -- -- alternative 2: 1.70 - -- - -- local n = 0 - -- - -- local utfcharcounter = utfbom^-1 * (p_utf8char/function() n = n + 1 end)^0 -- slow - -- - -- function utf.length(str) - -- n = 0 - -- lpegmatch(utfcharcounter,str or "") - -- return n - -- end - -- - -- -- alternative 3: 0.24 (native unicode.utf8.len: 0.047) - - -- local n = 0 - -- - -- -- local utfcharcounter = lpeg.patterns.utfbom^-1 * P ( ( Cp() * ( - -- -- patterns.utf8one ^1 * Cc(1) - -- -- + patterns.utf8two ^1 * Cc(2) - -- -- + patterns.utf8three^1 * Cc(3) - -- -- + patterns.utf8four ^1 * Cc(4) ) * Cp() / function(f,d,t) n = n + (t - f)/d end - -- -- )^0 ) -- just as many captures as below - -- - -- -- local utfcharcounter = lpeg.patterns.utfbom^-1 * P ( ( - -- -- (Cmt(patterns.utf8one ^1,function(_,_,s) n = n + #s return true end)) - -- -- + (Cmt(patterns.utf8two ^1,function(_,_,s) n = n + #s/2 return true end)) - -- -- + (Cmt(patterns.utf8three^1,function(_,_,s) n = n + #s/3 return true end)) - -- -- + (Cmt(patterns.utf8four ^1,function(_,_,s) n = n + #s/4 return true end)) - -- -- )^0 ) -- not interesting as it creates strings but sometimes faster - -- - -- -- The best so far: - -- - -- local utfcharcounter = utfbom^-1 * P ( ( - -- Cp() * (patterns.utf8one )^1 * Cp() / function(f,t) n = n + t - f end - -- + Cp() * (patterns.utf8two )^1 * Cp() / function(f,t) n = n + (t - f)/2 end - -- + Cp() * (patterns.utf8three)^1 * Cp() / function(f,t) n = n + (t - f)/3 end - -- + Cp() * (patterns.utf8four )^1 * Cp() / function(f,t) n = n + (t - f)/4 end - -- )^0 ) - - -- function utf.len(str) - -- n = 0 - -- lpegmatch(utfcharcounter,str or "") - -- return n - -- end - - local n, f = 0, 1 - - local utfcharcounter = patterns.utfbom^-1 * Cmt ( - Cc(1) * patterns.utf8one ^1 - + Cc(2) * patterns.utf8two ^1 - + Cc(3) * patterns.utf8three^1 - + Cc(4) * patterns.utf8four ^1, - function(_,t,d) -- due to Cc no string captures, so faster - n = n + (t - f)/d - f = t - return true - end - )^0 - - function utf.len(str) - n, f = 0, 1 - lpegmatch(utfcharcounter,str or "") - return n - end - - -- -- these are quite a bit slower: - - -- utfcharcounter = utfbom^-1 * (Cmt(P(1) * R("\128\191")^0, function() n = n + 1 return true end))^0 -- 50+ times slower - -- utfcharcounter = utfbom^-1 * (Cmt(P(1), function() n = n + 1 return true end) * R("\128\191")^0)^0 -- 50- times slower - -end - -utf.length = utf.len - -if not utf.sub then - - -- inefficient as lpeg just copies ^n - - -- local function sub(str,start,stop) - -- local pattern = p_utf8char^-(start-1) * C(p_utf8char^-(stop-start+1)) - -- inspect(pattern) - -- return lpegmatch(pattern,str) or "" - -- end - - -- local b, e, n, first, last = 0, 0, 0, 0, 0 - -- - -- local function slide(s,p) - -- n = n + 1 - -- if n == first then - -- b = p - -- if not last then - -- return nil - -- end - -- end - -- if n == last then - -- e = p - -- return nil - -- else - -- return p - -- end - -- end - -- - -- local pattern = Cmt(p_utf8char,slide)^0 - -- - -- function utf.sub(str,start,stop) -- todo: from the end - -- if not start then - -- return str - -- end - -- b, e, n, first, last = 0, 0, 0, start, stop - -- lpegmatch(pattern,str) - -- if not stop then - -- return sub(str,b) - -- else - -- return sub(str,b,e-1) - -- end - -- end - - -- print(utf.sub("Hans Hagen is my name")) - -- print(utf.sub("Hans Hagen is my name",5)) - -- print(utf.sub("Hans Hagen is my name",5,10)) - - local utflength = utf.length - - -- also negative indices, upto 10 times slower than a c variant - - local b, e, n, first, last = 0, 0, 0, 0, 0 - - local function slide_zero(s,p) - n = n + 1 - if n >= last then - e = p - 1 - else - return p - end - end - - local function slide_one(s,p) - n = n + 1 - if n == first then - b = p - end - if n >= last then - e = p - 1 - else - return p - end - end - - local function slide_two(s,p) - n = n + 1 - if n == first then - b = p - else - return true - end - end - - local pattern_zero = Cmt(p_utf8char,slide_zero)^0 - local pattern_one = Cmt(p_utf8char,slide_one )^0 - local pattern_two = Cmt(p_utf8char,slide_two )^0 - - local pattern_first = C(patterns.utf8character) - - function utf.sub(str,start,stop) - if not start then - return str - end - if start == 0 then - start = 1 - end - if not stop then - if start < 0 then - local l = utflength(str) -- we can inline this function if needed - start = l + start - else - start = start - 1 - end - b, n, first = 0, 0, start - lpegmatch(pattern_two,str) - if n >= first then - return sub(str,b) - else - return "" - end - end - if start < 0 or stop < 0 then - local l = utf.length(str) - if start < 0 then - start = l + start - if start <= 0 then - start = 1 - else - start = start + 1 - end - end - if stop < 0 then - stop = l + stop - if stop == 0 then - stop = 1 - else - stop = stop + 1 - end - end - end - if start == 1 and stop == 1 then - return lpegmatch(pattern_first,str) or "" - elseif start > stop then - return "" - elseif start > 1 then - b, e, n, first, last = 0, 0, 0, start - 1, stop - lpegmatch(pattern_one,str) - if n >= first and e == 0 then - e = #str - end - return sub(str,b,e) - else - b, e, n, last = 1, 0, 0, stop - lpegmatch(pattern_zero,str) - if e == 0 then - e = #str - end - return sub(str,b,e) - end - end - - -- local n = 100000 - -- local str = string.rep("123456àáâãäå",100) - -- - -- for i=-15,15,1 do - -- for j=-15,15,1 do - -- if utf.xsub(str,i,j) ~= utf.sub(str,i,j) then - -- print("error",i,j,"l>"..utf.xsub(str,i,j),"s>"..utf.sub(str,i,j)) - -- end - -- end - -- if utf.xsub(str,i) ~= utf.sub(str,i) then - -- print("error",i,"l>"..utf.xsub(str,i),"s>"..utf.sub(str,i)) - -- end - -- end - - -- print(" 1, 7",utf.xsub(str, 1, 7),utf.sub(str, 1, 7)) - -- print(" 0, 7",utf.xsub(str, 0, 7),utf.sub(str, 0, 7)) - -- print(" 0, 9",utf.xsub(str, 0, 9),utf.sub(str, 0, 9)) - -- print(" 4 ",utf.xsub(str, 4 ),utf.sub(str, 4 )) - -- print(" 0 ",utf.xsub(str, 0 ),utf.sub(str, 0 )) - -- print(" 0, 0",utf.xsub(str, 0, 0),utf.sub(str, 0, 0)) - -- print(" 4, 4",utf.xsub(str, 4, 4),utf.sub(str, 4, 4)) - -- print(" 4, 0",utf.xsub(str, 4, 0),utf.sub(str, 4, 0)) - -- print("-3, 0",utf.xsub(str,-3, 0),utf.sub(str,-3, 0)) - -- print(" 0,-3",utf.xsub(str, 0,-3),utf.sub(str, 0,-3)) - -- print(" 5,-3",utf.xsub(str,-5,-3),utf.sub(str,-5,-3)) - -- print("-3 ",utf.xsub(str,-3 ),utf.sub(str,-3 )) - -end - --- a replacement for simple gsubs: - --- function utf.remapper(mapping) --- local pattern = Cs((p_utf8char/mapping)^0) --- return function(str) --- if not str or str == "" then --- return "" --- else --- return lpegmatch(pattern,str) --- end --- end, pattern --- end - -function utf.remapper(mapping,option,action) -- static also returns a pattern - local variant = type(mapping) - if variant == "table" then - action = action or mapping - if option == "dynamic" then - local pattern = false - table.setmetatablenewindex(mapping,function(t,k,v) rawset(t,k,v) pattern = false end) - return function(str) - if not str or str == "" then - return "" - else - if not pattern then - pattern = Cs((tabletopattern(mapping)/action + p_utf8char)^0) - end - return lpegmatch(pattern,str) - end - end - elseif option == "pattern" then - return Cs((tabletopattern(mapping)/action + p_utf8char)^0) - -- elseif option == "static" then - else - local pattern = Cs((tabletopattern(mapping)/action + p_utf8char)^0) - return function(str) - if not str or str == "" then - return "" - else - return lpegmatch(pattern,str) - end - end, pattern - end - elseif variant == "function" then - if option == "pattern" then - return Cs((p_utf8char/mapping + p_utf8char)^0) - else - local pattern = Cs((p_utf8char/mapping + p_utf8char)^0) - return function(str) - if not str or str == "" then - return "" - else - return lpegmatch(pattern,str) - end - end, pattern - end - else - -- is actually an error - return function(str) - return str or "" - end - end -end - --- local remap = utf.remapper { a = 'd', b = "c", c = "b", d = "a" } --- print(remap("abcd 1234 abcd")) - -function utf.replacer(t) -- no precheck, always string builder - local r = replacer(t,false,false,true) - return function(str) - return lpegmatch(r,str) - end -end - -function utf.subtituter(t) -- with precheck and no building if no match - local f = finder (t) - local r = replacer(t,false,false,true) - return function(str) - local i = lpegmatch(f,str) - if not i then - return str - elseif i > #str then - return str - else - -- return sub(str,1,i-2) .. lpegmatch(r,str,i-1) -- slower - return lpegmatch(r,str) - end - end -end - --- inspect(utf.split("a b c d")) --- inspect(utf.split("a b c d",true)) - -local utflinesplitter = p_utfbom^-1 * lpeg.tsplitat(p_newline) -local utfcharsplitter_ows = p_utfbom^-1 * Ct(C(p_utf8char)^0) -local utfcharsplitter_iws = p_utfbom^-1 * Ct((p_whitespace^1 + C(p_utf8char))^0) -local utfcharsplitter_raw = Ct(C(p_utf8char)^0) - -patterns.utflinesplitter = utflinesplitter - -function utf.splitlines(str) - return lpegmatch(utflinesplitter,str or "") -end - -function utf.split(str,ignorewhitespace) -- new - if ignorewhitespace then - return lpegmatch(utfcharsplitter_iws,str or "") - else - return lpegmatch(utfcharsplitter_ows,str or "") - end -end - -function utf.totable(str) -- keeps bom - return lpegmatch(utfcharsplitter_raw,str) -end - --- 0 EF BB BF UTF-8 --- 1 FF FE UTF-16-little-endian --- 2 FE FF UTF-16-big-endian --- 3 FF FE 00 00 UTF-32-little-endian --- 4 00 00 FE FF UTF-32-big-endian --- --- \000 fails in <= 5.0 but is valid in >=5.1 where %z is depricated - --- utf.name = { --- [0] = 'utf-8', --- [1] = 'utf-16-le', --- [2] = 'utf-16-be', --- [3] = 'utf-32-le', --- [4] = 'utf-32-be' --- } --- --- function utf.magic(f) --- local str = f:read(4) --- if not str then --- f:seek('set') --- return 0 --- -- elseif find(str,"^%z%z\254\255") then -- depricated --- -- elseif find(str,"^\000\000\254\255") then -- not permitted and bugged --- elseif find(str,"\000\000\254\255",1,true) then -- seems to work okay (TH) --- return 4 --- -- elseif find(str,"^\255\254%z%z") then -- depricated --- -- elseif find(str,"^\255\254\000\000") then -- not permitted and bugged --- elseif find(str,"\255\254\000\000",1,true) then -- seems to work okay (TH) --- return 3 --- elseif find(str,"^\254\255") then --- f:seek('set',2) --- return 2 --- elseif find(str,"^\255\254") then --- f:seek('set',2) --- return 1 --- elseif find(str,"^\239\187\191") then --- f:seek('set',3) --- return 0 --- else --- f:seek('set') --- return 0 --- end --- end - -function utf.magic(f) -- not used - local str = f:read(4) or "" - local off = lpegmatch(p_utfoffset,str) - if off < 4 then - f:seek('set',off) - end - return lpegmatch(p_utftype,str) -end - -local utf16_to_utf8_be, utf16_to_utf8_le -local utf32_to_utf8_be, utf32_to_utf8_le - -local utf_16_be_getbom = patterns.utfbom_16_be^-1 -local utf_16_le_getbom = patterns.utfbom_16_le^-1 -local utf_32_be_getbom = patterns.utfbom_32_be^-1 -local utf_32_le_getbom = patterns.utfbom_32_le^-1 - -local utf_16_be_linesplitter = utf_16_be_getbom * lpeg.tsplitat(patterns.utf_16_be_nl) -local utf_16_le_linesplitter = utf_16_le_getbom * lpeg.tsplitat(patterns.utf_16_le_nl) -local utf_32_be_linesplitter = utf_32_be_getbom * lpeg.tsplitat(patterns.utf_32_be_nl) -local utf_32_le_linesplitter = utf_32_le_getbom * lpeg.tsplitat(patterns.utf_32_le_nl) - --- we have three possibilities: bytepairs (using tables), gmatch (using tables), gsub and --- lpeg. Bytepairs are the fastert but as soon as we need to remove bombs and so the gain --- is less due to more testing. Also, we seldom have to convert utf16 so we don't care to --- much about a few milliseconds more runtime. The lpeg variant is upto 20% slower but --- still pretty fast. --- --- for historic resone we keep the bytepairs variants around .. beware they don't grab the --- bom like the lpegs do so they're not dropins in the functions that follow --- --- utf16_to_utf8_be = function(s) --- if not s then --- return nil --- elseif s == "" then --- return "" --- end --- local result, r, more = { }, 0, 0 --- for left, right in bytepairs(s) do --- if right then --- local now = 256*left + right --- if more > 0 then --- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong --- more = 0 --- r = r + 1 --- result[r] = utfchar(now) --- elseif now >= 0xD800 and now <= 0xDBFF then --- more = now --- else --- r = r + 1 --- result[r] = utfchar(now) --- end --- end --- end --- return concat(result) --- end --- --- local utf16_to_utf8_be_t = function(t) --- if not t then --- return nil --- elseif type(t) == "string" then --- t = lpegmatch(utf_16_be_linesplitter,t) --- end --- local result = { } -- we reuse result --- for i=1,#t do --- local s = t[i] --- if s ~= "" then --- local r, more = 0, 0 --- for left, right in bytepairs(s) do --- if right then --- local now = 256*left + right --- if more > 0 then --- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong --- more = 0 --- r = r + 1 --- result[r] = utfchar(now) --- elseif now >= 0xD800 and now <= 0xDBFF then --- more = now --- else --- r = r + 1 --- result[r] = utfchar(now) --- end --- end --- end --- t[i] = concat(result,"",1,r) -- we reused tmp, hence t --- end --- end --- return t --- end --- --- utf16_to_utf8_le = function(s) --- if not s then --- return nil --- elseif s == "" then --- return "" --- end --- local result, r, more = { }, 0, 0 --- for left, right in bytepairs(s) do --- if right then --- local now = 256*right + left --- if more > 0 then --- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong --- more = 0 --- r = r + 1 --- result[r] = utfchar(now) --- elseif now >= 0xD800 and now <= 0xDBFF then --- more = now --- else --- r = r + 1 --- result[r] = utfchar(now) --- end --- end --- end --- return concat(result) --- end --- --- local utf16_to_utf8_le_t = function(t) --- if not t then --- return nil --- elseif type(t) == "string" then --- t = lpegmatch(utf_16_le_linesplitter,t) --- end --- local result = { } -- we reuse result --- for i=1,#t do --- local s = t[i] --- if s ~= "" then --- local r, more = 0, 0 --- for left, right in bytepairs(s) do --- if right then --- local now = 256*right + left --- if more > 0 then --- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong --- more = 0 --- r = r + 1 --- result[r] = utfchar(now) --- elseif now >= 0xD800 and now <= 0xDBFF then --- more = now --- else --- r = r + 1 --- result[r] = utfchar(now) --- end --- end --- end --- t[i] = concat(result,"",1,r) -- we reused tmp, hence t --- end --- end --- return t --- end --- --- local utf32_to_utf8_be_t = function(t) --- if not t then --- return nil --- elseif type(t) == "string" then --- t = lpegmatch(utflinesplitter,t) --- end --- local result = { } -- we reuse result --- for i=1,#t do --- local r, more = 0, -1 --- for a,b in bytepairs(t[i]) do --- if a and b then --- if more < 0 then --- more = 256*256*256*a + 256*256*b --- else --- r = r + 1 --- result[t] = utfchar(more + 256*a + b) --- more = -1 --- end --- else --- break --- end --- end --- t[i] = concat(result,"",1,r) --- end --- return t --- end --- --- local utf32_to_utf8_le_t = function(t) --- if not t then --- return nil --- elseif type(t) == "string" then --- t = lpegmatch(utflinesplitter,t) --- end --- local result = { } -- we reuse result --- for i=1,#t do --- local r, more = 0, -1 --- for a,b in bytepairs(t[i]) do --- if a and b then --- if more < 0 then --- more = 256*b + a --- else --- r = r + 1 --- result[t] = utfchar(more + 256*256*256*b + 256*256*a) --- more = -1 --- end --- else --- break --- end --- end --- t[i] = concat(result,"",1,r) --- end --- return t --- end - -local more = 0 - -local p_utf16_to_utf8_be = C(1) * C(1) /function(left,right) - local now = 256*byte(left) + byte(right) - if more > 0 then - now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong - more = 0 - return utfchar(now) - elseif now >= 0xD800 and now <= 0xDBFF then - more = now - return "" -- else the c's end up in the stream - else - return utfchar(now) - end -end - -local p_utf16_to_utf8_le = C(1) * C(1) /function(right,left) - local now = 256*byte(left) + byte(right) - if more > 0 then - now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong - more = 0 - return utfchar(now) - elseif now >= 0xD800 and now <= 0xDBFF then - more = now - return "" -- else the c's end up in the stream - else - return utfchar(now) - end -end -local p_utf32_to_utf8_be = C(1) * C(1) * C(1) * C(1) /function(a,b,c,d) - return utfchar(256*256*256*byte(a) + 256*256*byte(b) + 256*byte(c) + byte(d)) -end - -local p_utf32_to_utf8_le = C(1) * C(1) * C(1) * C(1) /function(a,b,c,d) - return utfchar(256*256*256*byte(d) + 256*256*byte(c) + 256*byte(b) + byte(a)) -end - -p_utf16_to_utf8_be = P(true) / function() more = 0 end * utf_16_be_getbom * Cs(p_utf16_to_utf8_be^0) -p_utf16_to_utf8_le = P(true) / function() more = 0 end * utf_16_le_getbom * Cs(p_utf16_to_utf8_le^0) -p_utf32_to_utf8_be = P(true) / function() more = 0 end * utf_32_be_getbom * Cs(p_utf32_to_utf8_be^0) -p_utf32_to_utf8_le = P(true) / function() more = 0 end * utf_32_le_getbom * Cs(p_utf32_to_utf8_le^0) - -patterns.utf16_to_utf8_be = p_utf16_to_utf8_be -patterns.utf16_to_utf8_le = p_utf16_to_utf8_le -patterns.utf32_to_utf8_be = p_utf32_to_utf8_be -patterns.utf32_to_utf8_le = p_utf32_to_utf8_le - -utf16_to_utf8_be = function(s) - if s and s ~= "" then - return lpegmatch(p_utf16_to_utf8_be,s) - else - return s - end -end - -local utf16_to_utf8_be_t = function(t) - if not t then - return nil - elseif type(t) == "string" then - t = lpegmatch(utf_16_be_linesplitter,t) - end - for i=1,#t do - local s = t[i] - if s ~= "" then - t[i] = lpegmatch(p_utf16_to_utf8_be,s) - end - end - return t -end - -utf16_to_utf8_le = function(s) - if s and s ~= "" then - return lpegmatch(p_utf16_to_utf8_le,s) - else - return s - end -end - -local utf16_to_utf8_le_t = function(t) - if not t then - return nil - elseif type(t) == "string" then - t = lpegmatch(utf_16_le_linesplitter,t) - end - for i=1,#t do - local s = t[i] - if s ~= "" then - t[i] = lpegmatch(p_utf16_to_utf8_le,s) - end - end - return t -end - -utf32_to_utf8_be = function(s) - if s and s ~= "" then - return lpegmatch(p_utf32_to_utf8_be,s) - else - return s - end -end - -local utf32_to_utf8_be_t = function(t) - if not t then - return nil - elseif type(t) == "string" then - t = lpegmatch(utf_32_be_linesplitter,t) - end - for i=1,#t do - local s = t[i] - if s ~= "" then - t[i] = lpegmatch(p_utf32_to_utf8_be,s) - end - end - return t -end - -utf32_to_utf8_le = function(s) - if s and s ~= "" then - return lpegmatch(p_utf32_to_utf8_le,s) - else - return s - end -end - -local utf32_to_utf8_le_t = function(t) - if not t then - return nil - elseif type(t) == "string" then - t = lpegmatch(utf_32_le_linesplitter,t) - end - for i=1,#t do - local s = t[i] - if s ~= "" then - t[i] = lpegmatch(p_utf32_to_utf8_le,s) - end - end - return t -end - -utf.utf16_to_utf8_le_t = utf16_to_utf8_le_t -utf.utf16_to_utf8_be_t = utf16_to_utf8_be_t -utf.utf32_to_utf8_le_t = utf32_to_utf8_le_t -utf.utf32_to_utf8_be_t = utf32_to_utf8_be_t - -utf.utf16_to_utf8_le = utf16_to_utf8_le -utf.utf16_to_utf8_be = utf16_to_utf8_be -utf.utf32_to_utf8_le = utf32_to_utf8_le -utf.utf32_to_utf8_be = utf32_to_utf8_be - -function utf.utf8_to_utf8_t(t) - return type(t) == "string" and lpegmatch(utflinesplitter,t) or t -end - -function utf.utf16_to_utf8_t(t,endian) - return endian and utf16_to_utf8_be_t(t) or utf16_to_utf8_le_t(t) or t -end - -function utf.utf32_to_utf8_t(t,endian) - return endian and utf32_to_utf8_be_t(t) or utf32_to_utf8_le_t(t) or t -end - -local function little(b) - if b < 0x10000 then - return char(b%256,b/256) - else - b = b - 0x10000 - local b1, b2 = b/1024 + 0xD800, b%1024 + 0xDC00 - return char(b1%256,b1/256,b2%256,b2/256) - end -end - -local function big(b) - if b < 0x10000 then - return char(b/256,b%256) - else - b = b - 0x10000 - local b1, b2 = b/1024 + 0xD800, b%1024 + 0xDC00 - return char(b1/256,b1%256,b2/256,b2%256) - end -end - -local l_remap = Cs((p_utf8byte/little+P(1)/"")^0) -local b_remap = Cs((p_utf8byte/big +P(1)/"")^0) - -local function utf8_to_utf16_be(str,nobom) - if nobom then - return lpegmatch(b_remap,str) - else - return char(254,255) .. lpegmatch(b_remap,str) - end -end - -local function utf8_to_utf16_le(str,nobom) - if nobom then - return lpegmatch(l_remap,str) - else - return char(255,254) .. lpegmatch(l_remap,str) - end -end - -utf.utf8_to_utf16_be = utf8_to_utf16_be -utf.utf8_to_utf16_le = utf8_to_utf16_le - -function utf.utf8_to_utf16(str,littleendian,nobom) - if littleendian then - return utf8_to_utf16_le(str,nobom) - else - return utf8_to_utf16_be(str,nobom) - end -end - --- function utf.tocodes(str,separator) -- can be sped up with an lpeg --- local t, n = { }, 0 --- for u in utfvalues(str) do --- n = n + 1 --- t[n] = format("0x%04X",u) --- end --- return concat(t,separator or " ") --- end - -local pattern = Cs ( - (p_utf8byte / function(unicode ) return format( "0x%04X", unicode) end) * - (p_utf8byte * Carg(1) / function(unicode,separator) return format("%s0x%04X",separator,unicode) end)^0 -) - -function utf.tocodes(str,separator) - return lpegmatch(pattern,str,1,separator or " ") -end - -function utf.ustring(s) - return format("U+%05X",type(s) == "number" and s or utfbyte(s)) -end - -function utf.xstring(s) - return format("0x%05X",type(s) == "number" and s or utfbyte(s)) -end - -function utf.toeight(str) - if not str or str == "" then - return nil - end - local utftype = lpegmatch(p_utfstricttype,str) - if utftype == "utf-8" then - return sub(str,4) -- remove the bom - elseif utftype == "utf-16-be" then - return utf16_to_utf8_be(str) -- bom gets removed - elseif utftype == "utf-16-le" then - return utf16_to_utf8_le(str) -- bom gets removed - else - return str - end -end - --- - -local p_nany = p_utf8char / "" - -if utfgmatch then - - function utf.count(str,what) - if type(what) == "string" then - local n = 0 - for _ in utfgmatch(str,what) do - n = n + 1 - end - return n - else -- 4 times slower but still faster than / function - return #lpegmatch(Cs((P(what)/" " + p_nany)^0),str) - end - end - -else - - local cache = { } - - function utf.count(str,what) - if type(what) == "string" then - local p = cache[what] - if not p then - p = Cs((P(what)/" " + p_nany)^0) - cache[p] = p - end - return #lpegmatch(p,str) - else -- 4 times slower but still faster than / function - return #lpegmatch(Cs((P(what)/" " + p_nany)^0),str) - end - end - -end - --- maybe also register as string.utf* - - -if not utf.characters then - - -- New: this gmatch hack is taken from the Lua 5.2 book. It's about two times slower - -- than the built-in string.utfcharacters. - - function utf.characters(str) - return gmatch(str,".[\128-\191]*") - end - - string.utfcharacters = utf.characters - -end - -if not utf.values then - - -- So, a logical next step is to check for the values variant. It over five times - -- slower than the built-in string.utfvalues. I optimized it a bit for n=0,1. - - ----- wrap, yield, gmatch = coroutine.wrap, coroutine.yield, string.gmatch - local find = string.find - - local dummy = function() - -- we share this one - end - - -- function utf.values(str) - -- local n = #str - -- if n == 0 then - -- return wrap(dummy) - -- elseif n == 1 then - -- return wrap(function() yield(utfbyte(str)) end) - -- else - -- return wrap(function() for s in gmatch(str,".[\128-\191]*") do - -- yield(utfbyte(s)) - -- end end) - -- end - -- end - -- - -- faster: - - function utf.values(str) - local n = #str - if n == 0 then - return dummy - elseif n == 1 then - return function() return utfbyte(str) end - else - local p = 1 - -- local n = #str - return function() - -- if p <= n then -- slower than the last find - local b, e = find(str,".[\128-\191]*",p) - if b then - p = e + 1 - return utfbyte(sub(str,b,e)) - end - -- end - end - end - end - - -- slower: - -- - -- local pattern = C(patterns.utf8character) * Cp() - -- ----- pattern = patterns.utf8character/utfbyte * Cp() - -- ----- pattern = patterns.utf8byte * Cp() - -- - -- function utf.values(str) -- one of the cases where a find is faster than an lpeg - -- local n = #str - -- if n == 0 then - -- return dummy - -- elseif n == 1 then - -- return function() return utfbyte(str) end - -- else - -- local p = 1 - -- return function() - -- local s, e = lpegmatch(pattern,str,p) - -- if e then - -- p = e - -- return utfbyte(s) - -- -- return s - -- end - -- end - -- end - -- end - - string.utfvalues = utf.values - -end - -function utf.chrlen(u) -- u is number - return - (u < 0x80 and 1) or - (u < 0xE0 and 2) or - (u < 0xF0 and 3) or - (u < 0xF8 and 4) or - (u < 0xFC and 5) or - (u < 0xFE and 6) or 0 -end diff --git a/tex/compat/lualibs/lualibs-url.lua b/tex/compat/lualibs/lualibs-url.lua deleted file mode 100644 index b189ec5bba8383d264a46a8d128001203977c762..0000000000000000000000000000000000000000 --- a/tex/compat/lualibs/lualibs-url.lua +++ /dev/null @@ -1,366 +0,0 @@ -if not modules then modules = { } end modules ['l-url'] = { - version = 1.001, - comment = "companion to luat-lib.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -local char, format, byte = string.char, string.format, string.byte -local concat = table.concat -local tonumber, type = tonumber, type -local P, C, R, S, Cs, Cc, Ct, Cf, Cg, V = lpeg.P, lpeg.C, lpeg.R, lpeg.S, lpeg.Cs, lpeg.Cc, lpeg.Ct, lpeg.Cf, lpeg.Cg, lpeg.V -local lpegmatch, lpegpatterns, replacer = lpeg.match, lpeg.patterns, lpeg.replacer - --- from wikipedia: --- --- foo://username:password@example.com:8042/over/there/index.dtb?type=animal;name=narwhal#nose --- \_/ \_______________/ \_________/ \__/ \___/ \_/ \______________________/ \__/ --- | | | | | | | | --- | userinfo hostname port | | query fragment --- | \________________________________/\_____________|____|/ --- scheme | | | | --- | authority path | | --- | | | --- | path interpretable as filename --- | ___________|____________ | --- / \ / \ | --- urn:example:animal:ferret:nose interpretable as extension --- --- also nice: http://url.spec.whatwg.org/ (maybe some day ...) - -url = url or { } -local url = url - -local tochar = function(s) return char(tonumber(s,16)) end - -local colon = P(":") -local qmark = P("?") -local hash = P("#") -local slash = P("/") -local percent = P("%") -local endofstring = P(-1) - -local hexdigit = R("09","AF","af") -local plus = P("+") -local nothing = Cc("") -local escapedchar = (percent * C(hexdigit * hexdigit)) / tochar -local escaped = (plus / " ") + escapedchar -- so no loc://foo++.tex - -local noslash = P("/") / "" - --- we assume schemes with more than 1 character (in order to avoid problems with windows disks) --- we also assume that when we have a scheme, we also have an authority --- --- maybe we should already split the query (better for unescaping as = & can be part of a value - -local schemestr = Cs((escaped+(1-colon-slash-qmark-hash))^2) -local authoritystr = Cs((escaped+(1- slash-qmark-hash))^0) -local pathstr = Cs((escaped+(1- qmark-hash))^0) ------ querystr = Cs((escaped+(1- hash))^0) -local querystr = Cs(( (1- hash))^0) -local fragmentstr = Cs((escaped+(1- endofstring))^0) - -local scheme = schemestr * colon + nothing -local authority = slash * slash * authoritystr + nothing -local path = slash * pathstr + nothing -local query = qmark * querystr + nothing -local fragment = hash * fragmentstr + nothing - -local validurl = scheme * authority * path * query * fragment -local parser = Ct(validurl) - -lpegpatterns.url = validurl -lpegpatterns.urlsplitter = parser - -local escapes = { } - -setmetatable(escapes, { __index = function(t,k) - local v = format("%%%02X",byte(k)) - t[k] = v - return v -end }) - -local escaper = Cs((R("09","AZ","az")^1 + P(" ")/"%%20" + S("-./_")^1 + P(1) / escapes)^0) -- space happens most -local unescaper = Cs((escapedchar + 1)^0) -local getcleaner = Cs((P("+++") / "%%2B" + P("+") / "%%20" + P(1))^1) - -lpegpatterns.urlunescaped = escapedchar -lpegpatterns.urlescaper = escaper -lpegpatterns.urlunescaper = unescaper -lpegpatterns.urlgetcleaner = getcleaner - -function url.unescapeget(str) - return lpegmatch(getcleaner,str) -end - --- todo: reconsider Ct as we can as well have five return values (saves a table) --- so we can have two parsers, one with and one without - -local function split(str) - return (type(str) == "string" and lpegmatch(parser,str)) or str -end - -local isscheme = schemestr * colon * slash * slash -- this test also assumes authority - -local function hasscheme(str) - if str then - local scheme = lpegmatch(isscheme,str) -- at least one character - return scheme ~= "" and scheme or false - else - return false - end -end - ---~ print(hasscheme("home:")) ---~ print(hasscheme("home://")) - --- todo: cache them - -local rootletter = R("az","AZ") - + S("_-+") -local separator = P("://") -local qualified = P(".")^0 * P("/") - + rootletter * P(":") - + rootletter^1 * separator - + rootletter^1 * P("/") -local rootbased = P("/") - + rootletter * P(":") - -local barswapper = replacer("|",":") -local backslashswapper = replacer("\\","/") - --- queries: - -local equal = P("=") -local amp = P("&") -local key = Cs(((escapedchar+1)-equal )^0) -local value = Cs(((escapedchar+1)-amp -endofstring)^0) - -local splitquery = Cf ( Ct("") * P { "sequence", - sequence = V("pair") * (amp * V("pair"))^0, - pair = Cg(key * equal * value), -}, rawset) - --- hasher - -local function hashed(str) -- not yet ok (/test?test) - if not str or str == "" then - return { - scheme = "invalid", - original = str, - } - end - local detailed = split(str) - local rawscheme = "" - local rawquery = "" - local somescheme = false - local somequery = false - if detailed then - rawscheme = detailed[1] - rawquery = detailed[4] - somescheme = rawscheme ~= "" - somequery = rawquery ~= "" - end - if not somescheme and not somequery then - return { - scheme = "file", - authority = "", - path = str, - query = "", - fragment = "", - original = str, - noscheme = true, - filename = str, - } - end - -- not always a filename but handy anyway - local authority = detailed[2] - local path = detailed[3] - local filename = nil - if authority == "" then - filename = path - elseif path == "" then - filename = "" - else - filename = authority .. "/" .. path - end - return { - scheme = rawscheme, - authority = authority, - path = path, - query = lpegmatch(unescaper,rawquery), -- unescaped, but possible conflict with & and = - queries = lpegmatch(splitquery,rawquery), -- split first and then unescaped - fragment = detailed[5], - original = str, - noscheme = false, - filename = filename, - } -end - --- inspect(hashed()) --- inspect(hashed("")) --- inspect(hashed("template:///test")) --- inspect(hashed("template:///test++.whatever")) --- inspect(hashed("template:///test%2B%2B.whatever")) --- inspect(hashed("template:///test%x.whatever")) --- inspect(hashed("tem%2Bplate:///test%x.whatever")) - --- Here we assume: --- --- files: /// = relative --- files: //// = absolute (!) - ---~ table.print(hashed("file://c:/opt/tex/texmf-local")) -- c:/opt/tex/texmf-local ---~ table.print(hashed("file://opt/tex/texmf-local" )) -- opt/tex/texmf-local ---~ table.print(hashed("file:///opt/tex/texmf-local" )) -- opt/tex/texmf-local ---~ table.print(hashed("file:////opt/tex/texmf-local" )) -- /opt/tex/texmf-local ---~ table.print(hashed("file:///./opt/tex/texmf-local" )) -- ./opt/tex/texmf-local - ---~ table.print(hashed("c:/opt/tex/texmf-local" )) -- c:/opt/tex/texmf-local ---~ table.print(hashed("opt/tex/texmf-local" )) -- opt/tex/texmf-local ---~ table.print(hashed("/opt/tex/texmf-local" )) -- /opt/tex/texmf-local - -url.split = split -url.hasscheme = hasscheme -url.hashed = hashed - -function url.addscheme(str,scheme) -- no authority - if hasscheme(str) then - return str - elseif not scheme then - return "file:///" .. str - else - return scheme .. ":///" .. str - end -end - -function url.construct(hash) -- dodo: we need to escape ! - local fullurl, f = { }, 0 - local scheme, authority, path, query, fragment = hash.scheme, hash.authority, hash.path, hash.query, hash.fragment - if scheme and scheme ~= "" then - f = f + 1 ; fullurl[f] = scheme .. "://" - end - if authority and authority ~= "" then - f = f + 1 ; fullurl[f] = authority - end - if path and path ~= "" then - f = f + 1 ; fullurl[f] = "/" .. path - end - if query and query ~= "" then - f = f + 1 ; fullurl[f] = "?".. query - end - if fragment and fragment ~= "" then - f = f + 1 ; fullurl[f] = "#".. fragment - end - return lpegmatch(escaper,concat(fullurl)) -end - -local pattern = Cs(slash^-1/"" * R("az","AZ") * ((S(":|")/":") + P(":")) * slash * P(1)^0) - -function url.filename(filename) - local spec = hashed(filename) - local path = spec.path - return (spec.scheme == "file" and path and lpegmatch(pattern,path)) or filename -end - --- print(url.filename("/c|/test")) --- print(url.filename("/c/test")) --- print(url.filename("file:///t:/sources/cow.svg")) - -local function escapestring(str) - return lpegmatch(escaper,str) -end - -url.escape = escapestring - -function url.query(str) - if type(str) == "string" then - return lpegmatch(splitquery,str) or "" - else - return str - end -end - -function url.toquery(data) - local td = type(data) - if td == "string" then - return #str and escape(data) or nil -- beware of double escaping - elseif td == "table" then - if next(data) then - local t = { } - for k, v in next, data do - t[#t+1] = format("%s=%s",k,escapestring(v)) - end - return concat(t,"&") - end - else - -- nil is a signal that no query - end -end - --- /test/ | /test | test/ | test => test - -local pattern = Cs(noslash^0 * (1 - noslash * P(-1))^0) - -function url.barepath(path) - if not path or path == "" then - return "" - else - return lpegmatch(pattern,path) - end -end - --- print(url.barepath("/test"),url.barepath("test/"),url.barepath("/test/"),url.barepath("test")) --- print(url.barepath("/x/yz"),url.barepath("x/yz/"),url.barepath("/x/yz/"),url.barepath("x/yz")) - ---~ print(url.filename("file:///c:/oeps.txt")) ---~ print(url.filename("c:/oeps.txt")) ---~ print(url.filename("file:///oeps.txt")) ---~ print(url.filename("file:///etc/test.txt")) ---~ print(url.filename("/oeps.txt")) - ---~ from the spec on the web (sort of): - ---~ local function test(str) ---~ local t = url.hashed(str) ---~ t.constructed = url.construct(t) ---~ print(table.serialize(t)) ---~ end - ---~ inspect(url.hashed("http://www.pragma-ade.com/test%20test?test=test%20test&x=123%3d45")) ---~ inspect(url.hashed("http://www.pragma-ade.com/test%20test?test=test%20test&x=123%3d45")) - ---~ test("sys:///./colo-rgb") - ---~ test("/data/site/output/q2p-develop/resources/ecaboperception4_res/topicresources/58313733/figuur-cow.jpg") ---~ test("file:///M:/q2p/develop/output/q2p-develop/resources/ecaboperception4_res/topicresources/58313733") ---~ test("M:/q2p/develop/output/q2p-develop/resources/ecaboperception4_res/topicresources/58313733") ---~ test("file:///q2p/develop/output/q2p-develop/resources/ecaboperception4_res/topicresources/58313733") ---~ test("/q2p/develop/output/q2p-develop/resources/ecaboperception4_res/topicresources/58313733") - ---~ test("file:///cow%20with%20spaces") ---~ test("file:///cow%20with%20spaces.pdf") ---~ test("cow%20with%20spaces.pdf") ---~ test("some%20file") ---~ test("/etc/passwords") ---~ test("http://www.myself.com/some%20words.html") ---~ test("file:///c:/oeps.txt") ---~ test("file:///c|/oeps.txt") ---~ test("file:///etc/oeps.txt") ---~ test("file://./etc/oeps.txt") ---~ test("file:////etc/oeps.txt") ---~ test("ftp://ftp.is.co.za/rfc/rfc1808.txt") ---~ test("http://www.ietf.org/rfc/rfc2396.txt") ---~ test("ldap://[2001:db8::7]/c=GB?objectClass?one#what") ---~ test("mailto:John.Doe@example.com") ---~ test("news:comp.infosystems.www.servers.unix") ---~ test("tel:+1-816-555-1212") ---~ test("telnet://192.0.2.16:80/") ---~ test("urn:oasis:names:specification:docbook:dtd:xml:4.1.2") ---~ test("http://www.pragma-ade.com/spaced%20name") - ---~ test("zip:///oeps/oeps.zip#bla/bla.tex") ---~ test("zip:///oeps/oeps.zip?bla/bla.tex") - ---~ table.print(url.hashed("/test?test")) diff --git a/tex/compat/lualibs/lualibs-util-deb.lua b/tex/compat/lualibs/lualibs-util-deb.lua deleted file mode 100644 index ee732b3b54c277367d1022a81e3c8c94b1427f10..0000000000000000000000000000000000000000 --- a/tex/compat/lualibs/lualibs-util-deb.lua +++ /dev/null @@ -1,132 +0,0 @@ -if not modules then modules = { } end modules ['util-deb'] = { - version = 1.001, - comment = "companion to luat-lib.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- the <anonymous> tag is kind of generic and used for functions that are not --- bound to a variable, like node.new, node.copy etc (contrary to for instance --- node.has_attribute which is bound to a has_attribute local variable in mkiv) - -local debug = require "debug" - -local getinfo = debug.getinfo -local type, next, tostring = type, next, tostring -local format, find = string.format, string.find -local is_boolean = string.is_boolean - -utilities = utilities or { } -local debugger = utilities.debugger or { } -utilities.debugger = debugger - -local counters = { } -local names = { } - -local report = logs.reporter("debugger") - --- one - -local function hook() - local f = getinfo(2) -- "nS" - if f then - local n = "unknown" - if f.what == "C" then - n = f.name or '<anonymous>' - if not names[n] then - names[n] = format("%42s",n) - end - else - -- source short_src linedefined what name namewhat nups func - n = f.name or f.namewhat or f.what - if not n or n == "" then - n = "?" - end - if not names[n] then - names[n] = format("%42s : % 5i : %s",n,f.linedefined or 0,f.short_src or "unknown source") - end - end - counters[n] = (counters[n] or 0) + 1 - end -end - -function debugger.showstats(printer,threshold) -- hm, something has changed, rubish now - printer = printer or report - threshold = threshold or 0 - local total, grandtotal, functions = 0, 0, 0 - local dataset = { } - for name, count in next, counters do - dataset[#dataset+1] = { name, count } - end - table.sort(dataset,function(a,b) return a[2] == b[2] and b[1] > a[1] or a[2] > b[2] end) - for i=1,#dataset do - local d = dataset[i] - local name = d[1] - local count = d[2] - if count > threshold and not find(name,"for generator") then -- move up - printer(format("%8i %s\n", count, names[name])) - total = total + count - end - grandtotal = grandtotal + count - functions = functions + 1 - end - printer("\n") - printer(format("functions : % 10i\n", functions)) - printer(format("total : % 10i\n", total)) - printer(format("grand total: % 10i\n", grandtotal)) - printer(format("threshold : % 10i\n", threshold)) -end - -function debugger.savestats(filename,threshold) - local f = io.open(filename,'w') - if f then - debugger.showstats(function(str) f:write(str) end,threshold) - f:close() - end -end - -function debugger.enable() - debug.sethook(hook,"c") -end - -function debugger.disable() - debug.sethook() - -- counters[debug.getinfo(2,"f").func] = nil -end - --- debugger.enable() --- --- print(math.sin(1*.5)) --- print(math.sin(1*.5)) --- print(math.sin(1*.5)) --- print(math.sin(1*.5)) --- print(math.sin(1*.5)) --- --- debugger.disable() --- --- print("") --- debugger.showstats() --- print("") --- debugger.showstats(print,3) --- --- from the lua book: - -local function showtraceback(rep) -- from lua site / adapted - local level = 2 -- we don't want this function to be reported - local reporter = rep or report - while true do - local info = getinfo(level, "Sl") - if not info then - break - elseif info.what == "C" then - reporter("%2i : %s",level-1,"C function") - else - reporter("%2i : %s : %s",level-1,info.short_src,info.currentline) - end - level = level + 1 - end -end - -debugger.showtraceback = showtraceback --- debug.showtraceback = showtraceback diff --git a/tex/compat/lualibs/lualibs-util-dim.lua b/tex/compat/lualibs/lualibs-util-dim.lua deleted file mode 100644 index 2bdb870e7a4d3a65c71bcb11791ba2a10a9bb44f..0000000000000000000000000000000000000000 --- a/tex/compat/lualibs/lualibs-util-dim.lua +++ /dev/null @@ -1,452 +0,0 @@ -if not modules then modules = { } end modules ['util-dim'] = { - version = 1.001, - comment = "support for dimensions", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - ---[[ldx-- -<p>Internally <l n='luatex'/> work with scaled point, which are -represented by integers. However, in practice, at east at the -<l n='tex'/> end we work with more generic units like points (pt). Going -from scaled points (numbers) to one of those units can be -done by using the conversion factors collected in the following -table.</p> ---ldx]]-- - -local format, match, gsub, type, setmetatable = string.format, string.match, string.gsub, type, setmetatable -local P, S, R, Cc, C, lpegmatch = lpeg.P, lpeg.S, lpeg.R, lpeg.Cc, lpeg.C, lpeg.match - -local allocate = utilities.storage.allocate -local setmetatableindex = table.setmetatableindex -local formatters = string.formatters - -local texget = tex and tex.get or function() return 65536*10*100 end - -local p_stripzeros = lpeg.patterns.stripzeros - ---this might become another namespace - -number = number or { } -local number = number - -number.tonumberf = function(n) return lpegmatch(p_stripzeros,format("%.20f",n)) end -number.tonumberg = function(n) return format("%.20g",n) end - -local dimenfactors = allocate { - ["pt"] = 1/65536, - ["in"] = ( 100/ 7227)/65536, - ["cm"] = ( 254/ 7227)/65536, - ["mm"] = ( 2540/ 7227)/65536, - ["sp"] = 1, -- 65536 sp in 1pt - ["bp"] = ( 7200/ 7227)/65536, - ["pc"] = ( 1/ 12)/65536, - ["dd"] = ( 1157/ 1238)/65536, - ["cc"] = ( 1157/14856)/65536, - ["nd"] = (20320/21681)/65536, - ["nc"] = ( 5080/65043)/65536 -} - --- print(table.serialize(dimenfactors)) --- --- %.99g: --- --- t={ --- ["bp"]=1.5201782378580324e-005, --- ["cc"]=1.1883696112892098e-006, --- ["cm"]=5.3628510057769479e-007, --- ["dd"]=1.4260435335470516e-005, --- ["em"]=0.000152587890625, --- ["ex"]=6.103515625e-005, --- ["in"]=2.1113586636917117e-007, --- ["mm"]=5.3628510057769473e-008, --- ["nc"]=1.1917446679504327e-006, --- ["nd"]=1.4300936015405194e-005, --- ["pc"]=1.2715657552083333e-006, --- ["pt"]=1.52587890625e-005, --- ["sp"]=1, --- } --- --- patched %s and tonumber --- --- t={ --- ["bp"]=0.00001520178238, --- ["cc"]=0.00000118836961, --- ["cm"]=0.0000005362851, --- ["dd"]=0.00001426043534, --- ["em"]=0.00015258789063, --- ["ex"]=0.00006103515625, --- ["in"]=0.00000021113587, --- ["mm"]=0.00000005362851, --- ["nc"]=0.00000119174467, --- ["nd"]=0.00001430093602, --- ["pc"]=0.00000127156576, --- ["pt"]=0.00001525878906, --- ["sp"]=1, --- } - ---[[ldx-- -<p>A conversion function that takes a number, unit (string) and optional -format (string) is implemented using this table.</p> ---ldx]]-- - -local f_none = formatters["%s%s"] -local f_true = formatters["%0.5F%s"] - -local function numbertodimen(n,unit,fmt) -- will be redefined later ! - if type(n) == 'string' then - return n - else - unit = unit or 'pt' - n = n * dimenfactors[unit] - if not fmt then - fmt = f_none(n,unit) - elseif fmt == true then - fmt = f_true(n,unit) - else - return formatters[fmt](n,unit) - end - end -end - ---[[ldx-- -<p>We collect a bunch of converters in the <type>number</type> namespace.</p> ---ldx]]-- - -number.maxdimen = 1073741823 -number.todimen = numbertodimen -number.dimenfactors = dimenfactors - -function number.topoints (n,fmt) return numbertodimen(n,"pt",fmt) end -function number.toinches (n,fmt) return numbertodimen(n,"in",fmt) end -function number.tocentimeters (n,fmt) return numbertodimen(n,"cm",fmt) end -function number.tomillimeters (n,fmt) return numbertodimen(n,"mm",fmt) end -function number.toscaledpoints(n,fmt) return numbertodimen(n,"sp",fmt) end -function number.toscaledpoints(n) return n .. "sp" end -function number.tobasepoints (n,fmt) return numbertodimen(n,"bp",fmt) end -function number.topicas (n,fmt) return numbertodimen(n "pc",fmt) end -function number.todidots (n,fmt) return numbertodimen(n,"dd",fmt) end -function number.tociceros (n,fmt) return numbertodimen(n,"cc",fmt) end -function number.tonewdidots (n,fmt) return numbertodimen(n,"nd",fmt) end -function number.tonewciceros (n,fmt) return numbertodimen(n,"nc",fmt) end - ---[[ldx-- -<p>More interesting it to implement a (sort of) dimen datatype, one -that permits calculations too. First we define a function that -converts a string to scaledpoints. We use <l n='lpeg'/>. We capture -a number and optionally a unit. When no unit is given a constant -capture takes place.</p> ---ldx]]-- - -local amount = (S("+-")^0 * R("09")^0 * P(".")^0 * R("09")^0) + Cc("0") -local unit = R("az")^1 + P("%") - -local dimenpair = amount/tonumber * (unit^1/dimenfactors + Cc(1)) -- tonumber is new - -lpeg.patterns.dimenpair = dimenpair - -local splitter = amount/tonumber * C(unit^1) - -function number.splitdimen(str) - return lpegmatch(splitter,str) -end - ---[[ldx-- -<p>We use a metatable to intercept errors. When no key is found in -the table with factors, the metatable will be consulted for an -alternative index function.</p> ---ldx]]-- - -setmetatableindex(dimenfactors, function(t,s) - -- error("wrong dimension: " .. (s or "?")) -- better a message - return false -end) - ---[[ldx-- -<p>We redefine the following function later on, so we comment it -here (which saves us bytecodes.</p> ---ldx]]-- - --- function string.todimen(str) --- if type(str) == "number" then --- return str --- else --- local value, unit = lpegmatch(dimenpair,str) --- return value/unit --- end --- end --- --- local stringtodimen = string.todimen - -local stringtodimen -- assigned later (commenting saves bytecode) - -local amount = S("+-")^0 * R("09")^0 * S(".,")^0 * R("09")^0 -local unit = P("pt") + P("cm") + P("mm") + P("sp") + P("bp") + P("in") + - P("pc") + P("dd") + P("cc") + P("nd") + P("nc") - -local validdimen = amount * unit - -lpeg.patterns.validdimen = validdimen - ---[[ldx-- -<p>This converter accepts calls like:</p> - -<typing> -string.todimen("10") -string.todimen(".10") -string.todimen("10.0") -string.todimen("10.0pt") -string.todimen("10pt") -string.todimen("10.0pt") -</typing> - -<p>With this in place, we can now implement a proper datatype for dimensions, one -that permits us to do this:</p> - -<typing> -s = dimen "10pt" + dimen "20pt" + dimen "200pt" - - dimen "100sp" / 10 + "20pt" + "0pt" -</typing> - -<p>We create a local metatable for this new type:</p> ---ldx]]-- - -local dimensions = { } - ---[[ldx-- -<p>The main (and globally) visible representation of a dimen is defined next: it is -a one-element table. The unit that is returned from the match is normally a number -(one of the previously defined factors) but we also accept functions. Later we will -see why. This function is redefined later.</p> ---ldx]]-- - --- function dimen(a) --- if a then --- local ta= type(a) --- if ta == "string" then --- local value, unit = lpegmatch(pattern,a) --- if type(unit) == "function" then --- k = value/unit() --- else --- k = value/unit --- end --- a = k --- elseif ta == "table" then --- a = a[1] --- end --- return setmetatable({ a }, dimensions) --- else --- return setmetatable({ 0 }, dimensions) --- end --- end - ---[[ldx-- -<p>This function return a small hash with a metatable attached. It is -through this metatable that we can do the calculations. We could have -shared some of the code but for reasons of speed we don't.</p> ---ldx]]-- - -function dimensions.__add(a, b) - local ta, tb = type(a), type(b) - if ta == "string" then a = stringtodimen(a) elseif ta == "table" then a = a[1] end - if tb == "string" then b = stringtodimen(b) elseif tb == "table" then b = b[1] end - return setmetatable({ a + b }, dimensions) -end - -function dimensions.__sub(a, b) - local ta, tb = type(a), type(b) - if ta == "string" then a = stringtodimen(a) elseif ta == "table" then a = a[1] end - if tb == "string" then b = stringtodimen(b) elseif tb == "table" then b = b[1] end - return setmetatable({ a - b }, dimensions) -end - -function dimensions.__mul(a, b) - local ta, tb = type(a), type(b) - if ta == "string" then a = stringtodimen(a) elseif ta == "table" then a = a[1] end - if tb == "string" then b = stringtodimen(b) elseif tb == "table" then b = b[1] end - return setmetatable({ a * b }, dimensions) -end - -function dimensions.__div(a, b) - local ta, tb = type(a), type(b) - if ta == "string" then a = stringtodimen(a) elseif ta == "table" then a = a[1] end - if tb == "string" then b = stringtodimen(b) elseif tb == "table" then b = b[1] end - return setmetatable({ a / b }, dimensions) -end - -function dimensions.__unm(a) - local ta = type(a) - if ta == "string" then a = stringtodimen(a) elseif ta == "table" then a = a[1] end - return setmetatable({ - a }, dimensions) -end - ---[[ldx-- -<p>It makes no sense to implement the power and modulo function but -the next two do make sense because they permits is code like:</p> - -<typing> -local a, b = dimen "10pt", dimen "11pt" -... -if a > b then - ... -end -</typing> ---ldx]]-- - --- makes no sense: dimensions.__pow and dimensions.__mod - -function dimensions.__lt(a, b) - return a[1] < b[1] -end - -function dimensions.__eq(a, b) - return a[1] == b[1] -end - ---[[ldx-- -<p>We also need to provide a function for conversion to string (so that -we can print dimensions). We print them as points, just like <l n='tex'/>.</p> ---ldx]]-- - -function dimensions.__tostring(a) - return a[1]/65536 .. "pt" -- instead of todimen(a[1]) -end - ---[[ldx-- -<p>Since it does not take much code, we also provide a way to access -a few accessors</p> - -<typing> -print(dimen().pt) -print(dimen().sp) -</typing> ---ldx]]-- - -function dimensions.__index(tab,key) - local d = dimenfactors[key] - if not d then - error("illegal property of dimen: " .. key) - d = 1 - end - return 1/d -end - ---[[ldx-- -<p>In the converter from string to dimension we support functions as -factors. This is because in <l n='tex'/> we have a few more units: -<type>ex</type> and <type>em</type>. These are not constant factors but -depend on the current font. They are not defined by default, but need -an explicit function call. This is because at the moment that this code -is loaded, the relevant tables that hold the functions needed may not -yet be available.</p> ---ldx]]-- - - dimenfactors["ex"] = 4 * 1/65536 -- 4pt - dimenfactors["em"] = 10 * 1/65536 -- 10pt --- dimenfactors["%"] = 4 * 1/65536 -- 400pt/100 - ---[[ldx-- -<p>The previous code is rather efficient (also thanks to <l n='lpeg'/>) but we -can speed it up by caching converted dimensions. On my machine (2008) the following -loop takes about 25.5 seconds.</p> - -<typing> -for i=1,1000000 do - local s = dimen "10pt" + dimen "20pt" + dimen "200pt" - - dimen "100sp" / 10 + "20pt" + "0pt" -end -</typing> - -<p>When we cache converted strings this becomes 16.3 seconds. In order not -to waste too much memory on it, we tag the values of the cache as being -week which mean that the garbage collector will collect them in a next -sweep. This means that in most cases the speed up is mostly affecting the -current couple of calculations and as such the speed penalty is small.</p> - -<p>We redefine two previous defined functions that can benefit from -this:</p> ---ldx]]-- - -local known = { } setmetatable(known, { __mode = "v" }) - -function dimen(a) - if a then - local ta= type(a) - if ta == "string" then - local k = known[a] - if k then - a = k - else - local value, unit = lpegmatch(dimenpair,a) - if value and unit then - k = value/unit -- to be considered: round - else - k = 0 - end - known[a] = k - a = k - end - elseif ta == "table" then - a = a[1] - end - return setmetatable({ a }, dimensions) - else - return setmetatable({ 0 }, dimensions) - end -end - -function string.todimen(str) -- maybe use tex.sp when available - if type(str) == "number" then - return str - else - local k = known[str] - if not k then - local value, unit = lpegmatch(dimenpair,str) - if value and unit then - k = value/unit -- to be considered: round - else - k = 0 - end - -- print(str,value,unit) - known[str] = k - end - return k - end -end - --- local known = { } --- --- function string.todimen(str) -- maybe use tex.sp --- local k = known[str] --- if not k then --- k = tex.sp(str) --- known[str] = k --- end --- return k --- end - -stringtodimen = string.todimen -- local variable defined earlier - -function number.toscaled(d) - return format("%0.5f",d/2^16) -end - ---[[ldx-- -<p>In a similar fashion we can define a glue datatype. In that case we -probably use a hash instead of a one-element table.</p> ---ldx]]-- - ---[[ldx-- -<p>Goodie:s</p> ---ldx]]-- - -function number.percent(n,d) -- will be cleaned up once luatex 0.30 is out - d = d or texget("hsize") - if type(d) == "string" then - d = stringtodimen(d) - end - return (n/100) * d -end - -number["%"] = number.percent diff --git a/tex/compat/lualibs/lualibs-util-fil.lua b/tex/compat/lualibs/lualibs-util-fil.lua deleted file mode 100644 index 28c92c7c3c3fa04ec242100b6b6c554096c095b3..0000000000000000000000000000000000000000 --- a/tex/compat/lualibs/lualibs-util-fil.lua +++ /dev/null @@ -1,167 +0,0 @@ -if not modules then modules = { } end modules ['util-fil'] = { - version = 1.001, - comment = "companion to luat-lib.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -local byte = string.byte -local extract = bit32.extract - --- Here are a few helpers (the starting point were old ones I used for parsing --- flac files). In Lua 5.3 we can probably do this better. Some code will move --- here. - -utilities = utilities or { } -local files = { } -utilities.files = files - -local zerobased = { } - -function files.open(filename,zb) - local f = io.open(filename,"rb") - if f then - zerobased[f] = zb or false - end - return f -end - -function files.close(f) - zerobased[f] = nil - f:close() -end - -function files.size(f) - return f:seek("end") -end - -function files.setposition(f,n) - if zerobased[f] then - f:seek("set",n) - else - f:seek("set",n - 1) - end -end - -function files.getposition(f) - if zerobased[f] then - return f:seek() - else - return f:seek() + 1 - end -end - -function files.look(f,n,chars) - local p = f:seek() - local s = f:read(n) - f:seek("set",p) - if chars then - return s - else - return byte(s,1,#s) - end -end - -function files.skip(f,n) - if n == 1 then - f:read(n) - else - f:seek("set",f:seek()+n) - end -end - -function files.readbyte(f) - return byte(f:read(1)) -end - -function files.readbytes(f,n) - return byte(f:read(n),1,n) -end - -function files.readchar(f) - return f:read(1) -end - -function files.readstring(f,n) - return f:read(n or 1) -end - -function files.readinteger1(f) -- one byte - local n = byte(f:read(1)) - if n >= 0x80 then - return n - 0xFF - 1 - else - return n - end -end - -files.readcardinal1 = files.readbyte -- one byte -files.readcardinal = files.readcardinal1 -files.readinteger = files.readinteger1 - -function files.readcardinal2(f) - local a, b = byte(f:read(2),1,2) - return 0x100 * a + b -end - -function files.readinteger2(f) - local a, b = byte(f:read(2),1,2) - local n = 0x100 * a + b - if n >= 0x8000 then - return n - 0xFFFF - 1 - else - return n - end -end - -function files.readcardinal3(f) - local a, b, c = byte(f:read(3),1,3) - return 0x10000 * a + 0x100 * b + c -end - -function files.readcardinal4(f) - local a, b, c, d = byte(f:read(4),1,4) - return 0x1000000 * a + 0x10000 * b + 0x100 * c + d -end - -function files.readinteger4(f) - local a, b, c, d = byte(f:read(4),1,4) - local n = 0x1000000 * a + 0x10000 * b + 0x100 * c + d - if n >= 0x8000000 then - return n - 0xFFFFFFFF - 1 - else - return n - end -end - -function files.readfixed4(f) - local a, b, c, d = byte(f:read(4),1,4) - local n = 0x100 * a + b - if n >= 0x8000 then - return n - 0xFFFF - 1 + (0x100 * c + d)/0xFFFF - else - return n + (0x100 * c + d)/0xFFFF - end -end - -function files.read2dot14(f) - local a, b = byte(f:read(2),1,2) - local n = 0x100 * a + b - local m = extract(n,0,30) - if n > 0x7FFF then - n = extract(n,30,2) - return m/0x4000 - 4 - else - n = extract(n,30,2) - return n + m/0x4000 - end -end - -function files.skipshort(f,n) - f:read(2*(n or 1)) -end - -function files.skiplong(f,n) - f:read(4*(n or 1)) -end diff --git a/tex/compat/lualibs/lualibs-util-jsn.lua b/tex/compat/lualibs/lualibs-util-jsn.lua deleted file mode 100644 index bbe25d89df89c2df30685b93d86e0968e3272ed4..0000000000000000000000000000000000000000 --- a/tex/compat/lualibs/lualibs-util-jsn.lua +++ /dev/null @@ -1,158 +0,0 @@ -if not modules then modules = { } end modules ['util-jsn'] = { - version = 1.001, - comment = "companion to m-json.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- Of course we could make a nice complete parser with proper error messages but --- as json is generated programmatically errors are systematic and we can assume --- a correct stream. If not, we have some fatal error anyway. So, we can just rely --- on strings being strings (apart from the unicode escape which is not in 5.1) and --- as we first catch known types we just assume that anything else is a number. --- --- Reminder for me: check usage in framework and extend when needed. Also document --- it in the cld lib documentation. - -local P, V, R, S, C, Cc, Cs, Ct, Cf, Cg = lpeg.P, lpeg.V, lpeg.R, lpeg.S, lpeg.C, lpeg.Cc, lpeg.Cs, lpeg.Ct, lpeg.Cf, lpeg.Cg -local lpegmatch = lpeg.match -local format = string.format -local utfchar = utf.char -local concat = table.concat - -local tonumber, tostring, rawset, type = tonumber, tostring, rawset, type - -local json = utilities.json or { } -utilities.json = json - --- moduledata = moduledata or { } --- moduledata.json = json - --- \\ \/ \b \f \n \r \t \uHHHH - -local lbrace = P("{") -local rbrace = P("}") -local lparent = P("[") -local rparent = P("]") -local comma = P(",") -local colon = P(":") -local dquote = P('"') - -local whitespace = lpeg.patterns.whitespace -local optionalws = whitespace^0 - -local escapes = { - -- ["\\"] = "\\", -- lua will escape these - -- ["/"] = "/", -- no need to escape this one - ["b"] = "\010", - ["f"] = "\014", - ["n"] = "\n", - ["r"] = "\r", - ["t"] = "\t", -} - -local escape_un = C(P("\\u") / "0x" * S("09","AF","af")) / function(s) return utfchar(tonumber(s)) end -local escape_bs = P([[\]]) / "" * (P(1) / escapes) -- if not found then P(1) is returned i.e. the to be escaped char - -local jstring = dquote * Cs((escape_un + escape_bs + (1-dquote))^0) * dquote -local jtrue = P("true") * Cc(true) -local jfalse = P("false") * Cc(false) -local jnull = P("null") * Cc(nil) -local jnumber = (1-whitespace-rparent-rbrace-comma)^1 / tonumber - -local key = jstring - -local jsonconverter = { "value", - object = lbrace * Cf(Ct("") * V("pair") * (comma * V("pair"))^0,rawset) * rbrace, - pair = Cg(optionalws * key * optionalws * colon * V("value")), - array = Ct(lparent * V("value") * (comma * V("value"))^0 * rparent), - value = optionalws * (jstring + V("object") + V("array") + jtrue + jfalse + jnull + jnumber + #rparent) * optionalws, -} - --- local jsonconverter = { "value", --- object = lbrace * Cf(Ct("") * V("pair") * (comma * V("pair"))^0,rawset) * rbrace, --- pair = Cg(optionalws * V("string") * optionalws * colon * V("value")), --- array = Ct(lparent * V("value") * (comma * V("value"))^0 * rparent), --- string = jstring, --- value = optionalws * (V("string") + V("object") + V("array") + jtrue + jfalse + jnull + jnumber) * optionalws, --- } - --- lpeg.print(jsonconverter) -- size 181 - -function json.tolua(str) - return lpegmatch(jsonconverter,str) -end - -local function tojson(value,t) -- we could optimize #t - local kind = type(value) - if kind == "table" then - local done = false - local size = #value - if size == 0 then - for k, v in next, value do - if done then - t[#t+1] = "," - else - t[#t+1] = "{" - done = true - end - t[#t+1] = format("%q:",k) - tojson(v,t) - end - if done then - t[#t+1] = "}" - else - t[#t+1] = "{}" - end - elseif size == 1 then - -- we can optimize for non tables - t[#t+1] = "[" - tojson(value[1],t) - t[#t+1] = "]" - else - for i=1,size do - if done then - t[#t+1] = "," - else - t[#t+1] = "[" - done = true - end - tojson(value[i],t) - end - t[#t+1] = "]" - end - elseif kind == "string" then - t[#t+1] = format("%q",value) - elseif kind == "number" then - t[#t+1] = value - elseif kind == "boolean" then - t[#t+1] = tostring(value) - end - return t -end - -function json.tostring(value) - -- todo optimize for non table - local kind = type(value) - if kind == "table" then - return concat(tojson(value,{}),"") - elseif kind == "string" or kind == "number" then - return value - else - return tostring(value) - end -end - --- local tmp = [[ { "a" : true, "b" : [ 123 , 456E-10, { "a" : true, "b" : [ 123 , 456 ] } ] } ]] - --- tmp = json.tolua(tmp) --- inspect(tmp) --- tmp = json.tostring(tmp) --- inspect(tmp) --- tmp = json.tolua(tmp) --- inspect(tmp) --- tmp = json.tostring(tmp) --- inspect(tmp) - --- inspect(json.tostring(true)) diff --git a/tex/compat/lualibs/lualibs-util-lua.lua b/tex/compat/lualibs/lualibs-util-lua.lua deleted file mode 100644 index e1dcdc94d5707acb95f044df7bdf4d6179028998..0000000000000000000000000000000000000000 --- a/tex/compat/lualibs/lualibs-util-lua.lua +++ /dev/null @@ -1,160 +0,0 @@ -if not modules then modules = { } end modules ['util-lua'] = { - version = 1.001, - comment = "companion to luat-lib.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - comment = "the strip code is written by Peter Cawley", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- we will remove the 5.1 code some day soon - -local rep, sub, byte, dump, format = string.rep, string.sub, string.byte, string.dump, string.format -local load, loadfile, type = load, loadfile, type - -utilities = utilities or {} -utilities.lua = utilities.lua or { } -local luautilities = utilities.lua - -local report_lua = logs.reporter("system","lua") - -local tracestripping = false -local forcestupidcompile = true -- use internal bytecode compiler -luautilities.stripcode = true -- support stripping when asked for -luautilities.alwaysstripcode = false -- saves 1 meg on 7 meg compressed format file (2012.08.12) -luautilities.nofstrippedchunks = 0 -luautilities.nofstrippedbytes = 0 -local strippedchunks = { } -- allocate() -luautilities.strippedchunks = strippedchunks - -luautilities.suffixes = { - tma = "tma", - tmc = jit and "tmb" or "tmc", - lua = "lua", - luc = jit and "lub" or "luc", - lui = "lui", - luv = "luv", - luj = "luj", - tua = "tua", - tuc = "tuc", -} - --- environment.loadpreprocessedfile can be set to a preprocessor - -local function register(name) - if tracestripping then - report_lua("stripped bytecode from %a",name or "unknown") - end - strippedchunks[#strippedchunks+1] = name - luautilities.nofstrippedchunks = luautilities.nofstrippedchunks + 1 -end - -local function stupidcompile(luafile,lucfile,strip) - local code = io.loaddata(luafile) - if code and code ~= "" then - code = load(code) - if code then - code = dump(code,strip and luautilities.stripcode or luautilities.alwaysstripcode) - if code and code ~= "" then - register(name) - io.savedata(lucfile,code) - return true, 0 - end - else - report_lua("fatal error %a in file %a",1,luafile) - end - else - report_lua("fatal error %a in file %a",2,luafile) - end - return false, 0 -end - --- quite subtle ... doing this wrong incidentally can give more bytes - -function luautilities.loadedluacode(fullname,forcestrip,name) - -- quite subtle ... doing this wrong incidentally can give more bytes - name = name or fullname - local code, message - if environment.loadpreprocessedfile then - code, message = environment.loadpreprocessedfile(fullname) - else - code, message = loadfile(fullname) - end - if code then - code() - else - report_lua("loading of file %a failed:\n\t%s",fullname,message or "no message") - end - if forcestrip and luautilities.stripcode then - if type(forcestrip) == "function" then - forcestrip = forcestrip(fullname) - end - if forcestrip or luautilities.alwaysstripcode then - register(name) - return load(dump(code,true)), 0 - else - return code, 0 - end - elseif luautilities.alwaysstripcode then - register(name) - return load(dump(code,true)), 0 - else - return code, 0 - end -end - -function luautilities.strippedloadstring(code,forcestrip,name) -- not executed - local code, message = load(code) - if not code then - report_lua("loading of file %a failed:\n\t%s",name,message or "no message") - end - if forcestrip and luautilities.stripcode or luautilities.alwaysstripcode then - register(name) - return load(dump(code,true)), 0 -- not yet executes - else - return code, 0 - end -end - -function luautilities.compile(luafile,lucfile,cleanup,strip,fallback) -- defaults: cleanup=false strip=true - report_lua("compiling %a into %a",luafile,lucfile) - os.remove(lucfile) - local done = stupidcompile(luafile,lucfile,strip ~= false) - if done then - report_lua("dumping %a into %a stripped",luafile,lucfile) - if cleanup == true and lfs.isfile(lucfile) and lfs.isfile(luafile) then - report_lua("removing %a",luafile) - os.remove(luafile) - end - end - return done -end - -function luautilities.loadstripped(...) - local l = load(...) - if l then - return load(dump(l,true)) - end -end - --- local getmetatable, type = getmetatable, type --- --- local types = { } --- --- function luautilities.registerdatatype(d,name) --- types[getmetatable(d)] = name --- end --- --- function luautilities.datatype(d) --- local t = type(d) --- if t == "userdata" then --- local m = getmetatable(d) --- return m and types[m] or "userdata" --- else --- return t --- end --- end --- --- luautilities.registerdatatype(lpeg.P("!"),"lpeg") --- --- print(luautilities.datatype(lpeg.P("oeps"))) diff --git a/tex/compat/lualibs/lualibs-util-prs.lua b/tex/compat/lualibs/lualibs-util-prs.lua deleted file mode 100644 index 01138f1bbb3dd85ef85e8931ed260183dbe63b0d..0000000000000000000000000000000000000000 --- a/tex/compat/lualibs/lualibs-util-prs.lua +++ /dev/null @@ -1,725 +0,0 @@ -if not modules then modules = { } end modules ['util-prs'] = { - version = 1.001, - comment = "companion to luat-lib.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -local lpeg, table, string = lpeg, table, string -local P, R, V, S, C, Ct, Cs, Carg, Cc, Cg, Cf, Cp = lpeg.P, lpeg.R, lpeg.V, lpeg.S, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Carg, lpeg.Cc, lpeg.Cg, lpeg.Cf, lpeg.Cp -local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns -local concat, gmatch, find = table.concat, string.gmatch, string.find -local tostring, type, next, rawset = tostring, type, next, rawset -local mod, div = math.mod, math.div - -utilities = utilities or {} -local parsers = utilities.parsers or { } -utilities.parsers = parsers -local patterns = parsers.patterns or { } -parsers.patterns = patterns - -local setmetatableindex = table.setmetatableindex -local sortedhash = table.sortedhash -local sortedkeys = table.sortedkeys -local tohash = table.tohash - -local hashes = { } -utilities.parsers.hashes = hashes --- we share some patterns - -local digit = R("09") -local space = P(' ') -local equal = P("=") -local comma = P(",") -local lbrace = P("{") -local rbrace = P("}") -local lparent = P("(") -local rparent = P(")") -local period = S(".") -local punctuation = S(".,:;") -local spacer = lpegpatterns.spacer -local whitespace = lpegpatterns.whitespace -local newline = lpegpatterns.newline -local anything = lpegpatterns.anything -local endofstring = lpegpatterns.endofstring - -local nobrace = 1 - (lbrace + rbrace ) -local noparent = 1 - (lparent + rparent) - --- we could use a Cf Cg construct - -local escape, left, right = P("\\"), P('{'), P('}') - -lpegpatterns.balanced = P { - [1] = ((escape * (left+right)) + (1 - (left+right)) + V(2))^0, - [2] = left * V(1) * right -} - -local nestedbraces = P { lbrace * (nobrace + V(1))^0 * rbrace } -local nestedparents = P { lparent * (noparent + V(1))^0 * rparent } -local spaces = space^0 -local argument = Cs((lbrace/"") * ((nobrace + nestedbraces)^0) * (rbrace/"")) -local content = (1-endofstring)^0 - -lpegpatterns.nestedbraces = nestedbraces -- no capture -lpegpatterns.nestedparents = nestedparents -- no capture -lpegpatterns.nested = nestedbraces -- no capture -lpegpatterns.argument = argument -- argument after e.g. = -lpegpatterns.content = content -- rest after e.g = - -local value = P(lbrace * C((nobrace + nestedbraces)^0) * rbrace) + C((nestedbraces + (1-comma))^0) - -local key = C((1-equal-comma)^1) -local pattern_a = (space+comma)^0 * (key * equal * value + key * C("")) -local pattern_c = (space+comma)^0 * (key * equal * value) - -local key = C((1-space-equal-comma)^1) -local pattern_b = spaces * comma^0 * spaces * (key * ((spaces * equal * spaces * value) + C(""))) - --- "a=1, b=2, c=3, d={a{b,c}d}, e=12345, f=xx{a{b,c}d}xx, g={}" : outer {} removes, leading spaces ignored - --- todo: rewrite to fold etc --- --- parse = lpeg.Cf(lpeg.Carg(1) * lpeg.Cg(key * equal * value) * separator^0,rawset)^0 -- lpeg.match(parse,"...",1,hash) - -local hash = { } - -local function set(key,value) - hash[key] = value -end - -local pattern_a_s = (pattern_a/set)^1 -local pattern_b_s = (pattern_b/set)^1 -local pattern_c_s = (pattern_c/set)^1 - -patterns.settings_to_hash_a = pattern_a_s -patterns.settings_to_hash_b = pattern_b_s -patterns.settings_to_hash_c = pattern_c_s - -function parsers.make_settings_to_hash_pattern(set,how) - if how == "strict" then - return (pattern_c/set)^1 - elseif how == "tolerant" then - return (pattern_b/set)^1 - else - return (pattern_a/set)^1 - end -end - -function parsers.settings_to_hash(str,existing) - if not str or str == "" then - return { } - elseif type(str) == "table" then - if existing then - for k, v in next, str do - existing[k] = v - end - return exiting - else - return str - end - else - hash = existing or { } - lpegmatch(pattern_a_s,str) - return hash - end -end - -function parsers.settings_to_hash_tolerant(str,existing) - if not str or str == "" then - return { } - elseif type(str) == "table" then - if existing then - for k, v in next, str do - existing[k] = v - end - return exiting - else - return str - end - else - hash = existing or { } - lpegmatch(pattern_b_s,str) - return hash - end -end - -function parsers.settings_to_hash_strict(str,existing) - if not str or str == "" then - return nil - elseif type(str) == "table" then - if existing then - for k, v in next, str do - existing[k] = v - end - return exiting - else - return str - end - elseif str and str ~= "" then - hash = existing or { } - lpegmatch(pattern_c_s,str) - return next(hash) and hash - end -end - -local separator = comma * space^0 -local value = P(lbrace * C((nobrace + nestedbraces)^0) * rbrace) - + C((nestedbraces + (1-comma))^0) -local pattern = spaces * Ct(value*(separator*value)^0) - --- "aap, {noot}, mies" : outer {} removed, leading spaces ignored - -patterns.settings_to_array = pattern - --- we could use a weak table as cache - -function parsers.settings_to_array(str,strict) - if not str or str == "" then - return { } - elseif type(str) == "table" then - return str - elseif strict then - if find(str,"{",1,true) then - return lpegmatch(pattern,str) - else - return { str } - end - elseif find(str,",",1,true) then - return lpegmatch(pattern,str) - else - return { str } - end -end - --- this one also strips end spaces before separators --- --- "{123} , 456 " -> "123" "456" - --- local separator = space^0 * comma * space^0 --- local value = P(lbrace * C((nobrace + nestedbraces)^0) * rbrace) --- + C((nestedbraces + (1-(space^0*(comma+P(-1)))))^0) --- local withvalue = Carg(1) * value / function(f,s) return f(s) end --- local pattern_a = spaces * Ct(value*(separator*value)^0) --- local pattern_b = spaces * withvalue * (separator*withvalue)^0 - -local cache_a = { } -local cache_b = { } - -function parsers.groupedsplitat(symbol,withaction) - if not symbol then - symbol = "," - end - local pattern = (withaction and cache_b or cache_a)[symbol] - if not pattern then - local symbols = S(symbol) - local separator = space^0 * symbols * space^0 - local value = P(lbrace * C((nobrace + nestedbraces)^0) * rbrace) - + C((nestedbraces + (1-(space^0*(symbols+P(-1)))))^0) - if withaction then - local withvalue = Carg(1) * value / function(f,s) return f(s) end - pattern = spaces * withvalue * (separator*withvalue)^0 - cache_b[symbol] = pattern - else - pattern = spaces * Ct(value*(separator*value)^0) - cache_a[symbol] = pattern - end - end - return pattern -end - -local pattern_a = parsers.groupedsplitat(",",false) -local pattern_b = parsers.groupedsplitat(",",true) - -function parsers.stripped_settings_to_array(str) - if not str or str == "" then - return { } - else - return lpegmatch(pattern_a,str) - end -end - -function parsers.process_stripped_settings(str,action) - if not str or str == "" then - return { } - else - return lpegmatch(pattern_b,str,1,action) - end -end - --- parsers.process_stripped_settings("{123} , 456 ",function(s) print("["..s.."]") end) --- parsers.process_stripped_settings("123 , 456 ",function(s) print("["..s.."]") end) - -local function set(t,v) - t[#t+1] = v -end - -local value = P(Carg(1)*value) / set -local pattern = value*(separator*value)^0 * Carg(1) - -function parsers.add_settings_to_array(t,str) - return lpegmatch(pattern,str,nil,t) -end - -function parsers.hash_to_string(h,separator,yes,no,strict,omit) - if h then - local t, tn, s = { }, 0, sortedkeys(h) - omit = omit and tohash(omit) - for i=1,#s do - local key = s[i] - if not omit or not omit[key] then - local value = h[key] - if type(value) == "boolean" then - if yes and no then - if value then - tn = tn + 1 - t[tn] = key .. '=' .. yes - elseif not strict then - tn = tn + 1 - t[tn] = key .. '=' .. no - end - elseif value or not strict then - tn = tn + 1 - t[tn] = key .. '=' .. tostring(value) - end - else - tn = tn + 1 - t[tn] = key .. '=' .. value - end - end - end - return concat(t,separator or ",") - else - return "" - end -end - -function parsers.array_to_string(a,separator) - if a then - return concat(a,separator or ",") - else - return "" - end -end - --- function parsers.settings_to_set(str,t) -- tohash? -- todo: lpeg -- duplicate anyway --- if str then --- t = t or { } --- for s in gmatch(str,"[^, ]+") do -- space added --- t[s] = true --- end --- return t --- else --- return { } --- end --- end - -local pattern = Cf(Ct("") * Cg(C((1-S(", "))^1) * S(", ")^0 * Cc(true))^1,rawset) - -function utilities.parsers.settings_to_set(str) - return str and lpegmatch(pattern,str) or { } -end - -hashes.settings_to_set = table.setmetatableindex(function(t,k) -- experiment, not public - local v = k and lpegmatch(pattern,k) or { } - t[k] = v - return v -end) - -getmetatable(hashes.settings_to_set).__mode = "kv" -- could be an option (maybe sharing makes sense) - -function parsers.simple_hash_to_string(h, separator) - local t, tn = { }, 0 - for k, v in sortedhash(h) do - if v then - tn = tn + 1 - t[tn] = k - end - end - return concat(t,separator or ",") -end - --- for mtx-context etc: aaaa bbbb cccc=dddd eeee=ffff - -local str = Cs(lpegpatterns.unquoted) + C((1-whitespace-equal)^1) -local setting = Cf( Carg(1) * (whitespace^0 * Cg(str * whitespace^0 * (equal * whitespace^0 * str + Cc(""))))^1,rawset) -local splitter = setting^1 - -function utilities.parsers.options_to_hash(str,target) - return str and lpegmatch(splitter,str,1,target or { }) or { } -end - -local splitter = lpeg.tsplitat(" ") - -function utilities.parsers.options_to_array(str) - return str and lpegmatch(splitter,str) or { } -end - --- for chem (currently one level) - -local value = P(lbrace * C((nobrace + nestedbraces)^0) * rbrace) - + C(digit^1 * lparent * (noparent + nestedparents)^1 * rparent) - + C((nestedbraces + (1-comma))^1) -local pattern_a = spaces * Ct(value*(separator*value)^0) - -local function repeater(n,str) - if not n then - return str - else - local s = lpegmatch(pattern_a,str) - if n == 1 then - return unpack(s) - else - local t, tn = { }, 0 - for i=1,n do - for j=1,#s do - tn = tn + 1 - t[tn] = s[j] - end - end - return unpack(t) - end - end -end - -local value = P(lbrace * C((nobrace + nestedbraces)^0) * rbrace) - + (C(digit^1)/tonumber * lparent * Cs((noparent + nestedparents)^1) * rparent) / repeater - + C((nestedbraces + (1-comma))^1) -local pattern_b = spaces * Ct(value*(separator*value)^0) - -function parsers.settings_to_array_with_repeat(str,expand) -- beware: "" => { } - if expand then - return lpegmatch(pattern_b,str) or { } - else - return lpegmatch(pattern_a,str) or { } - end -end - --- - -local value = lbrace * C((nobrace + nestedbraces)^0) * rbrace -local pattern = Ct((space + value)^0) - -function parsers.arguments_to_table(str) - return lpegmatch(pattern,str) -end - --- temporary here (unoptimized) - -function parsers.getparameters(self,class,parentclass,settings) - local sc = self[class] - if not sc then - sc = { } - self[class] = sc - if parentclass then - local sp = self[parentclass] - if not sp then - sp = { } - self[parentclass] = sp - end - setmetatableindex(sc,sp) - end - end - parsers.settings_to_hash(settings,sc) -end - -function parsers.listitem(str) - return gmatch(str,"[^, ]+") -end - --- - -local pattern = Cs { "start", - start = V("one") + V("two") + V("three"), - rest = (Cc(",") * V("thousand"))^0 * (P(".") + endofstring) * anything^0, - thousand = digit * digit * digit, - one = digit * V("rest"), - two = digit * digit * V("rest"), - three = V("thousand") * V("rest"), -} - -lpegpatterns.splitthousands = pattern -- maybe better in the parsers namespace ? - -function parsers.splitthousands(str) - return lpegmatch(pattern,str) or str -end - --- print(parsers.splitthousands("11111111111.11")) - -local optionalwhitespace = whitespace^0 - -lpegpatterns.words = Ct((Cs((1-punctuation-whitespace)^1) + anything)^1) -lpegpatterns.sentences = Ct((optionalwhitespace * Cs((1-period)^0 * period))^1) -lpegpatterns.paragraphs = Ct((optionalwhitespace * Cs((whitespace^1*endofstring/"" + 1 - (spacer^0*newline*newline))^1))^1) - --- local str = " Word1 word2. \n Word3 word4. \n\n Word5 word6.\n " --- inspect(lpegmatch(lpegpatterns.paragraphs,str)) --- inspect(lpegmatch(lpegpatterns.sentences,str)) --- inspect(lpegmatch(lpegpatterns.words,str)) - --- handy for k="v" [, ] k="v" - -local dquote = P('"') -local equal = P('=') -local escape = P('\\') -local separator = S(' ,') - -local key = C((1-equal)^1) -local value = dquote * C((1-dquote-escape*dquote)^0) * dquote - ------ pattern = Cf(Ct("") * Cg(key * equal * value) * separator^0,rawset)^0 * P(-1) -- was wrong -local pattern = Cf(Ct("") * (Cg(key * equal * value) * separator^0)^1,rawset)^0 * P(-1) - -function parsers.keq_to_hash(str) - if str and str ~= "" then - return lpegmatch(pattern,str) - else - return { } - end -end - --- inspect(lpeg.match(pattern,[[key="value" foo="bar"]])) - -local defaultspecification = { separator = ",", quote = '"' } - --- this version accepts multiple separators and quotes as used in the --- database module - -function parsers.csvsplitter(specification) - specification = specification and setmetatableindex(specification,defaultspecification) or defaultspecification - local separator = specification.separator - local quotechar = specification.quote - local separator = S(separator ~= "" and separator or ",") - local whatever = C((1 - separator - newline)^0) - if quotechar and quotechar ~= "" then - local quotedata = nil - for chr in gmatch(quotechar,".") do - local quotechar = P(chr) - local quoteword = quotechar * C((1 - quotechar)^0) * quotechar - if quotedata then - quotedata = quotedata + quoteword - else - quotedata = quoteword - end - end - whatever = quotedata + whatever - end - local parser = Ct((Ct(whatever * (separator * whatever)^0) * S("\n\r")^1)^0 ) - return function(data) - return lpegmatch(parser,data) - end -end - --- and this is a slightly patched version of a version posted by Philipp Gesang - --- local mycsvsplitter = utilities.parsers.rfc4180splitter() - --- local crap = [[ --- first,second,third,fourth --- "1","2","3","4" --- "a","b","c","d" --- "foo","bar""baz","boogie","xyzzy" --- ]] - --- local list, names = mycsvsplitter(crap,true) inspect(list) inspect(names) --- local list, names = mycsvsplitter(crap) inspect(list) inspect(names) - -function parsers.rfc4180splitter(specification) - specification = specification and setmetatableindex(specification,defaultspecification) or defaultspecification - local separator = specification.separator --> rfc: COMMA - local quotechar = P(specification.quote) --> DQUOTE - local dquotechar = quotechar * quotechar --> 2DQUOTE - / specification.quote - local separator = S(separator ~= "" and separator or ",") - local escaped = quotechar - * Cs((dquotechar + (1 - quotechar))^0) - * quotechar - local non_escaped = C((1 - quotechar - newline - separator)^1) - local field = escaped + non_escaped + Cc("") - local record = Ct(field * (separator * field)^1) - local headerline = record * Cp() - local wholeblob = Ct((newline^(specification.strict and -1 or 1) * record)^0) - return function(data,getheader) - if getheader then - local header, position = lpegmatch(headerline,data) - local data = lpegmatch(wholeblob,data,position) - return data, header - else - return lpegmatch(wholeblob,data) - end - end -end - --- utilities.parsers.stepper("1,7-",9,function(i) print(">>>",i) end) --- utilities.parsers.stepper("1-3,7,8,9") --- utilities.parsers.stepper("1-3,6,7",function(i) print(">>>",i) end) --- utilities.parsers.stepper(" 1 : 3, ,7 ") --- utilities.parsers.stepper("1:4,9:13,24:*",30) - -local function ranger(first,last,n,action) - if not first then - -- forget about it - elseif last == true then - for i=first,n or first do - action(i) - end - elseif last then - for i=first,last do - action(i) - end - else - action(first) - end -end - -local cardinal = lpegpatterns.cardinal / tonumber -local spacers = lpegpatterns.spacer^0 -local endofstring = lpegpatterns.endofstring - -local stepper = spacers * ( C(cardinal) * ( spacers * S(":-") * spacers * ( C(cardinal) + Cc(true) ) + Cc(false) ) - * Carg(1) * Carg(2) / ranger * S(", ")^0 )^1 - -local stepper = spacers * ( C(cardinal) * ( spacers * S(":-") * spacers * ( C(cardinal) + (P("*") + endofstring) * Cc(true) ) + Cc(false) ) - * Carg(1) * Carg(2) / ranger * S(", ")^0 )^1 * endofstring -- we're sort of strict (could do without endofstring) - -function parsers.stepper(str,n,action) - if type(n) == "function" then - lpegmatch(stepper,str,1,false,n or print) - else - lpegmatch(stepper,str,1,n,action or print) - end -end - --- - -local pattern_math = Cs((P("%")/"\\percent " + P("^") * Cc("{") * lpegpatterns.integer * Cc("}") + anything)^0) -local pattern_text = Cs((P("%")/"\\percent " + (P("^")/"\\high") * Cc("{") * lpegpatterns.integer * Cc("}") + anything)^0) - -patterns.unittotex = pattern - -function parsers.unittotex(str,textmode) - return lpegmatch(textmode and pattern_text or pattern_math,str) -end - -local pattern = Cs((P("^") / "<sup>" * lpegpatterns.integer * Cc("</sup>") + anything)^0) - -function parsers.unittoxml(str) - return lpegmatch(pattern,str) -end - --- print(utilities.parsers.unittotex("10^-32 %"),utilities.parsers.unittoxml("10^32 %")) - -local cache = { } -local spaces = lpegpatterns.space^0 -local dummy = function() end - -setmetatableindex(cache,function(t,k) - local separator = P(k) - local value = (1-separator)^0 - local pattern = spaces * C(value) * separator^0 * Cp() - t[k] = pattern - return pattern -end) - -local commalistiterator = cache[","] - -function utilities.parsers.iterator(str,separator) - local n = #str - if n == 0 then - return dummy - else - local pattern = separator and cache[separator] or commalistiterator - local p = 1 - return function() - if p <= n then - local s, e = lpegmatch(pattern,str,p) - if e then - p = e - return s - end - end - end - end -end - --- for s in utilities.parsers.iterator("a b c,b,c") do --- print(s) --- end - -local function initialize(t,name) - local source = t[name] - if source then - local result = { } - for k, v in next, t[name] do - result[k] = v - end - return result - else - return { } - end -end - -local function fetch(t,name) - return t[name] or { } -end - -local function process(result,more) - for k, v in next, more do - result[k] = v - end - return result -end - -local name = C((1-S(", "))^1) -local parser = (Carg(1) * name / initialize) * (S(", ")^1 * (Carg(1) * name / fetch))^0 -local merge = Cf(parser,process) - -function utilities.parsers.mergehashes(hash,list) - return lpegmatch(merge,list,1,hash) -end - --- local t = { --- aa = { alpha = 1, beta = 2, gamma = 3, }, --- bb = { alpha = 4, beta = 5, delta = 6, }, --- cc = { epsilon = 3 }, --- } --- --- inspect(utilities.parsers.mergehashes(t,"aa, bb, cc")) - -function utilities.parsers.runtime(time) - if not time then - time = os.runtime() - end - local days = div(time,24*60*60) - time = mod(time,24*60*60) - local hours = div(time,60*60) - time = mod(time,60*60) - local minutes = div(time,60) - local seconds = mod(time,60) - return days, hours, minutes, seconds -end - --- - -local spacing = whitespace^0 -local apply = P("->") -local method = C((1-apply)^1) -local token = lbrace * C((1-rbrace)^1) * rbrace + C(anything^1) - -local pattern = spacing * (method * spacing * apply + Carg(1)) * spacing * token - -function utilities.parsers.splitmethod(str,default) - if str then - return lpegmatch(pattern,str,1,default or false) - else - return default or false, "" - end -end - --- print(utilities.parsers.splitmethod(" foo -> {bar} ")) --- print(utilities.parsers.splitmethod("foo->{bar}")) --- print(utilities.parsers.splitmethod("foo->bar")) --- print(utilities.parsers.splitmethod("foo")) --- print(utilities.parsers.splitmethod("{foo}")) --- print(utilities.parsers.splitmethod()) diff --git a/tex/compat/lualibs/lualibs-util-sta.lua b/tex/compat/lualibs/lualibs-util-sta.lua deleted file mode 100644 index 27ab5a624b658cea522d66fc58f28de928008e02..0000000000000000000000000000000000000000 --- a/tex/compat/lualibs/lualibs-util-sta.lua +++ /dev/null @@ -1,352 +0,0 @@ -if not modules then modules = { } end modules ['util-sta'] = { - version = 1.001, - comment = "companion to util-ini.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -local insert, remove, fastcopy, concat = table.insert, table.remove, table.fastcopy, table.concat -local format = string.format -local select, tostring = select, tostring - -local trace_stacker = false trackers.register("stacker.resolve", function(v) trace_stacker = v end) - -local stacker = stacker or { } - -utilities.stacker = stacker - -local function start(s,t,first,last) - if s.mode == "switch" then - local n = tostring(t[last]) - if trace_stacker then - s.report("start: %s",n) - end - return n - else - local r = { } - for i=first,last do - r[#r+1] = tostring(t[i]) - end - local n = concat(r," ") - if trace_stacker then - s.report("start: %s",n) - end - return n - end -end - -local function stop(s,t,first,last) - if s.mode == "switch" then - local n = tostring(false) - if trace_stacker then - s.report("stop: %s",n) - end - return n - else - local r = { } - for i=last,first,-1 do - r[#r+1] = tostring(false) - end - local n = concat(r," ") - if trace_stacker then - s.report("stop: %s",n) - end - return n - end -end - -local function change(s,t1,first1,last1,t2,first2,last2) - if s.mode == "switch" then - local n = tostring(t2[last2]) - if trace_stacker then - s.report("change: %s",n) - end - return n - else - local r = { } - for i=last1,first1,-1 do - r[#r+1] = tostring(false) - end - local n = concat(r," ") - for i=first2,last2 do - r[#r+1] = tostring(t2[i]) - end - if trace_stacker then - s.report("change: %s",n) - end - return n - end -end - -function stacker.new(name) - - local report = logs.reporter("stacker",name or nil) - - local s - - local stack = { } - local list = { } - local ids = { } - local hash = { } - - local hashing = true - - local function push(...) - for i=1,select("#",...) do - insert(stack,(select(i,...))) -- watch the () - end - if hashing then - local c = concat(stack,"|") - local n = hash[c] - if not n then - n = #list+1 - hash[c] = n - list[n] = fastcopy(stack) - end - insert(ids,n) - return n - else - local n = #list+1 - list[n] = fastcopy(stack) - insert(ids,n) - return n - end - end - - local function pop() - remove(stack) - remove(ids) - return ids[#ids] or s.unset or -1 - end - - local function clean() - if #stack == 0 then - if trace_stacker then - s.report("%s list entries, %s stack entries",#list,#stack) - end - end - end - - local tops = { } - local top = nil - local switch = nil - - local function resolve_reset(mode) - if #tops > 0 then - report("resetting %s left-over states of %a",#tops,name) - end - tops = { } - top = nil - switch = nil - end - - local function resolve_begin(mode) - if mode then - switch = mode == "switch" - else - switch = s.mode == "switch" - end - top = { switch = switch } - insert(tops,top) - end - - local function resolve_step(ti) -- keep track of changes outside function ! - -- todo: optimize for n=1 etc - local result = nil - local noftop = #top - if ti > 0 then - local current = list[ti] - if current then - local noflist = #current - local nofsame = 0 - if noflist > noftop then - for i=1,noflist do - if current[i] == top[i] then - nofsame = i - else - break - end - end - else - for i=1,noflist do - if current[i] == top[i] then - nofsame = i - else - break - end - end - end - local plus = nofsame + 1 - if plus <= noftop then - if plus <= noflist then - if switch then - result = s.change(s,top,plus,noftop,current,nofsame,noflist) - else - result = s.change(s,top,plus,noftop,current,plus,noflist) - end - else - if switch then - result = s.change(s,top,plus,noftop,current,nofsame,noflist) - else - result = s.stop(s,top,plus,noftop) - end - end - elseif plus <= noflist then - if switch then - result = s.start(s,current,nofsame,noflist) - else - result = s.start(s,current,plus,noflist) - end - end - top = current - else - if 1 <= noftop then - result = s.stop(s,top,1,noftop) - end - top = { } - end - return result - else - if 1 <= noftop then - result = s.stop(s,top,1,noftop) - end - top = { } - return result - end - end - - local function resolve_end() - -- resolve_step(s.unset) - if #tops > 0 then -- was #top brrr - local result = s.stop(s,top,1,#top) - remove(tops) - top = tops[#tops] - switch = top and top.switch - return result - end - end - - local function resolve(t) - resolve_begin() - for i=1,#t do - resolve_step(t[i]) - end - resolve_end() - end - - s = { - name = name or "unknown", - unset = -1, - report = report, - start = start, - stop = stop, - change = change, - push = push, - pop = pop, - clean = clean, - resolve = resolve, - resolve_begin = resolve_begin, - resolve_step = resolve_step, - resolve_end = resolve_end, - resolve_reset = resolve_reset, - } - - return s -- we can overload functions - -end - --- local s = utilities.stacker.new("demo") --- --- local unset = s.unset --- local push = s.push --- local pop = s.pop --- --- local t = { --- unset, --- unset, --- push("a"), -- a --- push("b","c"), -- a b c --- pop(), -- a b --- push("d"), -- a b d --- pop(), -- a b --- unset, --- pop(), -- a --- pop(), -- b --- unset, --- unset, --- } --- --- s.resolve(t) - --- demostacker = utilities.stacker.new("demos") --- --- local whatever = { --- one = "1 0 0 RG 1 0 0 rg", --- two = "1 1 0 RG 1 1 0 rg", --- [false] = "0 G 0 g", --- } --- --- local concat = table.concat --- --- local pdfliteral = nodes.pool.pdfliteral --- --- function demostacker.start(s,t,first,last) --- local n = whatever[t[last]] --- -- s.report("start: %s",n) --- return pdfliteral(n) --- end --- --- function demostacker.stop(s,t,first,last) --- local n = whatever[false] --- -- s.report("stop: %s",n) --- return pdfliteral(n) --- end --- --- function demostacker.change(s,t1,first1,last1,t2,first2,last2) --- local n = whatever[t2[last2]] --- -- s.report("change: %s",n) --- return pdfliteral(n) --- end --- --- demostacker.mode = "switch" --- --- local whatever = { --- one = "/OC /test1 BDC", --- two = "/OC /test2 BDC", --- [false] = "EMC", --- } --- --- demostacker = utilities.stacker.new("demos") --- --- function demostacker.start(s,t,first,last) --- local r = { } --- for i=first,last do --- r[#r+1] = whatever[t[i]] --- end --- -- s.report("start: %s",concat(r," ")) --- return pdfliteral(concat(r," ")) --- end --- --- function demostacker.stop(s,t,first,last) --- local r = { } --- for i=last,first,-1 do --- r[#r+1] = whatever[false] --- end --- -- s.report("stop: %s",concat(r," ")) --- return pdfliteral(concat(r," ")) --- end --- --- function demostacker.change(s,t1,first1,last1,t2,first2,last2) --- local r = { } --- for i=last1,first1,-1 do --- r[#r+1] = whatever[false] --- end --- for i=first2,last2 do --- r[#r+1] = whatever[t2[i]] --- end --- -- s.report("change: %s",concat(r," ")) --- return pdfliteral(concat(r," ")) --- end --- --- demostacker.mode = "stack" diff --git a/tex/compat/lualibs/lualibs-util-sto.lua b/tex/compat/lualibs/lualibs-util-sto.lua deleted file mode 100644 index d21267d7a8c996f03fadab34b04d3b9c4aac7611..0000000000000000000000000000000000000000 --- a/tex/compat/lualibs/lualibs-util-sto.lua +++ /dev/null @@ -1,174 +0,0 @@ -if not modules then modules = { } end modules ['util-sto'] = { - version = 1.001, - comment = "companion to luat-lib.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -local setmetatable, getmetatable, type = setmetatable, getmetatable, type - -utilities = utilities or { } -utilities.storage = utilities.storage or { } -local storage = utilities.storage - -function storage.mark(t) - if not t then - print("\nfatal error: storage cannot be marked\n") - os.exit() - return - end - local m = getmetatable(t) - if not m then - m = { } - setmetatable(t,m) - end - m.__storage__ = true - return t -end - -function storage.allocate(t) - t = t or { } - local m = getmetatable(t) - if not m then - m = { } - setmetatable(t,m) - end - m.__storage__ = true - return t -end - -function storage.marked(t) - local m = getmetatable(t) - return m and m.__storage__ -end - -function storage.checked(t) - if not t then - report("\nfatal error: storage has not been allocated\n") - os.exit() - return - end - return t -end - --- function utilities.storage.delay(parent,name,filename) --- local m = getmetatable(parent) --- m.__list[name] = filename --- end --- --- function utilities.storage.predefine(parent) --- local list = { } --- local m = getmetatable(parent) or { --- __list = list, --- __index = function(t,k) --- local l = require(list[k]) --- t[k] = l --- return l --- end --- } --- setmetatable(parent,m) --- end --- --- bla = { } --- utilities.storage.predefine(bla) --- utilities.storage.delay(bla,"test","oepsoeps") --- local t = bla.test --- table.print(t) --- print(t.a) - -function storage.setinitializer(data,initialize) - local m = getmetatable(data) or { } - m.__index = function(data,k) - m.__index = nil -- so that we can access the entries during initializing - initialize() - return data[k] - end - setmetatable(data, m) -end - -local keyisvalue = { __index = function(t,k) - t[k] = k - return k -end } - -function storage.sparse(t) - t = t or { } - setmetatable(t,keyisvalue) - return t -end - --- table namespace ? - -local function f_empty () return "" end -- t,k -local function f_self (t,k) t[k] = k return k end -local function f_table (t,k) local v = { } t[k] = v return v end -local function f_number(t,k) t[k] = 0 return 0 end -- t,k,v -local function f_ignore() end -- t,k,v - -local f_index = { - ["empty"] = f_empty, - ["self"] = f_self, - ["table"] = f_table, - ["number"] = f_number, -} - -function table.setmetatableindex(t,f) - if type(t) ~= "table" then - f, t = t, { } - end - local m = getmetatable(t) - local i = f_index[f] or f - if m then - m.__index = i - else - setmetatable(t,{ __index = i }) - end - return t -end - -local f_index = { - ["ignore"] = f_ignore, -} - -function table.setmetatablenewindex(t,f) - if type(t) ~= "table" then - f, t = t, { } - end - local m = getmetatable(t) - local i = f_index[f] or f - if m then - m.__newindex = i - else - setmetatable(t,{ __newindex = i }) - end - return t -end - -function table.setmetatablecall(t,f) - if type(t) ~= "table" then - f, t = t, { } - end - local m = getmetatable(t) - if m then - m.__call = f - else - setmetatable(t,{ __call = f }) - end - return t -end - -function table.setmetatablekey(t,key,value) - local m = getmetatable(t) - if not m then - m = { } - setmetatable(t,m) - end - m[key] = value - return t -end - -function table.getmetatablekey(t,key,value) - local m = getmetatable(t) - return m and m[key] -end diff --git a/tex/compat/lualibs/lualibs-util-str.lua b/tex/compat/lualibs/lualibs-util-str.lua deleted file mode 100644 index 95534c8d87f3f11eb63a76419ee81845aec93d2c..0000000000000000000000000000000000000000 --- a/tex/compat/lualibs/lualibs-util-str.lua +++ /dev/null @@ -1,1134 +0,0 @@ -if not modules then modules = { } end modules ['util-str'] = { - version = 1.001, - comment = "companion to luat-lib.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -utilities = utilities or { } -utilities.strings = utilities.strings or { } -local strings = utilities.strings - -local format, gsub, rep, sub = string.format, string.gsub, string.rep, string.sub -local load, dump = load, string.dump -local tonumber, type, tostring = tonumber, type, tostring -local unpack, concat = table.unpack, table.concat -local P, V, C, S, R, Ct, Cs, Cp, Carg, Cc = lpeg.P, lpeg.V, lpeg.C, lpeg.S, lpeg.R, lpeg.Ct, lpeg.Cs, lpeg.Cp, lpeg.Carg, lpeg.Cc -local patterns, lpegmatch = lpeg.patterns, lpeg.match -local utfchar, utfbyte = utf.char, utf.byte ------ loadstripped = utilities.lua.loadstripped ------ setmetatableindex = table.setmetatableindex - -local loadstripped = nil - -if _LUAVERSION < 5.2 then - - loadstripped = function(str,shortcuts) - return load(str) - end - -else - - loadstripped = function(str,shortcuts) - if shortcuts then - return load(dump(load(str),true),nil,nil,shortcuts) - else - return load(dump(load(str),true)) - end - end - -end - --- todo: make a special namespace for the formatter - -if not number then number = { } end -- temp hack for luatex-fonts - -local stripper = patterns.stripzeros -local newline = patterns.newline -local endofstring = patterns.endofstring -local whitespace = patterns.whitespace -local spacer = patterns.spacer -local spaceortab = patterns.spaceortab - -local function points(n) - n = tonumber(n) - return (not n or n == 0) and "0pt" or lpegmatch(stripper,format("%.5fpt",n/65536)) -end - -local function basepoints(n) - n = tonumber(n) - return (not n or n == 0) and "0bp" or lpegmatch(stripper,format("%.5fbp", n*(7200/7227)/65536)) -end - -number.points = points -number.basepoints = basepoints - --- str = " \n \ntest \n test\ntest " --- print("["..string.gsub(string.collapsecrlf(str),"\n","+").."]") - -local rubish = spaceortab^0 * newline -local anyrubish = spaceortab + newline -local anything = patterns.anything -local stripped = (spaceortab^1 / "") * newline -local leading = rubish^0 / "" -local trailing = (anyrubish^1 * endofstring) / "" -local redundant = rubish^3 / "\n" - -local pattern = Cs(leading * (trailing + redundant + stripped + anything)^0) - -function strings.collapsecrlf(str) - return lpegmatch(pattern,str) -end - --- The following functions might end up in another namespace. - -local repeaters = { } -- watch how we also moved the -1 in depth-1 to the creator - -function strings.newrepeater(str,offset) - offset = offset or 0 - local s = repeaters[str] - if not s then - s = { } - repeaters[str] = s - end - local t = s[offset] - if t then - return t - end - t = { } - setmetatable(t, { __index = function(t,k) - if not k then - return "" - end - local n = k + offset - local s = n > 0 and rep(str,n) or "" - t[k] = s - return s - end }) - s[offset] = t - return t -end - --- local dashes = strings.newrepeater("--",-1) --- print(dashes[2],dashes[3],dashes[1]) - -local extra, tab, start = 0, 0, 4, 0 - -local nspaces = strings.newrepeater(" ") - -string.nspaces = nspaces - -local pattern = - Carg(1) / function(t) - extra, tab, start = 0, t or 7, 1 - end - * Cs(( - Cp() * patterns.tab / function(position) - local current = (position - start + 1) + extra - local spaces = tab-(current-1) % tab - if spaces > 0 then - extra = extra + spaces - 1 - return nspaces[spaces] -- rep(" ",spaces) - else - return "" - end - end - + newline * Cp() / function(position) - extra, start = 0, position - end - + patterns.anything - )^1) - -function strings.tabtospace(str,tab) - return lpegmatch(pattern,str,1,tab or 7) -end - --- local t = { --- "1234567123456712345671234567", --- "\tb\tc", --- "a\tb\tc", --- "aa\tbb\tcc", --- "aaa\tbbb\tccc", --- "aaaa\tbbbb\tcccc", --- "aaaaa\tbbbbb\tccccc", --- "aaaaaa\tbbbbbb\tcccccc\n aaaaaa\tbbbbbb\tcccccc", --- "one\n two\nxxx three\nxx four\nx five\nsix", --- } --- for k=1,#t do --- print(strings.tabtospace(t[k])) --- end - --- todo: lpeg - --- function strings.striplong(str) -- strips all leading spaces --- str = gsub(str,"^%s*","") --- str = gsub(str,"[\n\r]+ *","\n") --- return str --- end - -local space = spacer^0 -local nospace = space/"" -local endofline = nospace * newline - -local stripend = (whitespace^1 * endofstring)/"" - -local normalline = (nospace * ((1-space*(newline+endofstring))^1) * nospace) - -local stripempty = endofline^1/"" -local normalempty = endofline^1 -local singleempty = endofline * (endofline^0/"") -local doubleempty = endofline * endofline^-1 * (endofline^0/"") - -local stripstart = stripempty^0 - -local p_prune_normal = Cs ( stripstart * ( stripend + normalline + normalempty )^0 ) -local p_prune_collapse = Cs ( stripstart * ( stripend + normalline + doubleempty )^0 ) -local p_prune_noempty = Cs ( stripstart * ( stripend + normalline + singleempty )^0 ) -local p_retain_normal = Cs ( ( normalline + normalempty )^0 ) -local p_retain_collapse = Cs ( ( normalline + doubleempty )^0 ) -local p_retain_noempty = Cs ( ( normalline + singleempty )^0 ) - --- function striplines(str,prune,collapse,noempty) --- if prune then --- if noempty then --- return lpegmatch(p_prune_noempty,str) or str --- elseif collapse then --- return lpegmatch(p_prune_collapse,str) or str --- else --- return lpegmatch(p_prune_normal,str) or str --- end --- else --- if noempty then --- return lpegmatch(p_retain_noempty,str) or str --- elseif collapse then --- return lpegmatch(p_retain_collapse,str) or str --- else --- return lpegmatch(p_retain_normal,str) or str --- end --- end --- end - -local striplinepatterns = { - ["prune"] = p_prune_normal, - ["prune and collapse"] = p_prune_collapse, -- default - ["prune and no empty"] = p_prune_noempty, - ["retain"] = p_retain_normal, - ["retain and collapse"] = p_retain_collapse, - ["retain and no empty"] = p_retain_noempty, - ["collapse"] = patterns.collapser, -- how about: stripper fullstripper -} - -setmetatable(striplinepatterns,{ __index = function(t,k) return p_prune_collapse end }) - -strings.striplinepatterns = striplinepatterns - -function strings.striplines(str,how) - return str and lpegmatch(striplinepatterns[how],str) or str -end - --- also see: string.collapsespaces - -strings.striplong = strings.striplines -- for old times sake - --- local str = table.concat( { --- " ", --- " aap", --- " noot mies", --- " ", --- " ", --- " zus wim jet", --- "zus wim jet", --- " zus wim jet", --- " ", --- }, "\n") - --- local str = table.concat( { --- " aaaa", --- " bb", --- " cccccc", --- }, "\n") - --- for k, v in table.sortedhash(utilities.strings.striplinepatterns) do --- logs.report("stripper","method: %s, result: [[%s]]",k,utilities.strings.striplines(str,k)) --- end - --- inspect(strings.striplong([[ --- aaaa --- bb --- cccccc --- ]])) - -function strings.nice(str) - str = gsub(str,"[:%-+_]+"," ") -- maybe more - return str -end - --- Work in progress. Interesting is that compared to the built-in this is faster in --- luatex than in luajittex where we have a comparable speed. It only makes sense --- to use the formatter when a (somewhat) complex format is used a lot. Each formatter --- is a function so there is some overhead and not all formatted output is worth that --- overhead. Keep in mind that there is an extra function call involved. In principle --- we end up with a string concatination so one could inline such a sequence but often --- at the cost of less readabinity. So, it's a sort of (visual) compromise. Of course --- there is the benefit of more variants. (Concerning the speed: a simple format like --- %05fpt is better off with format than with a formatter, but as soon as you put --- something in front formatters become faster. Passing the pt as extra argument makes --- formatters behave better. Of course this is rather implementation dependent. Also, --- when a specific format is only used a few times the overhead in creating it is not --- compensated by speed.) --- --- More info can be found in cld-mkiv.pdf so here I stick to a simple list. --- --- integer %...i number --- integer %...d number --- unsigned %...u number --- character %...c number --- hexadecimal %...x number --- HEXADECIMAL %...X number --- octal %...o number --- string %...s string number --- float %...f number --- checked float %...F number --- exponential %...e number --- exponential %...E number --- autofloat %...g number --- autofloat %...G number --- utf character %...c number --- force tostring %...S any --- force tostring %Q any --- force tonumber %N number (strip leading zeros) --- signed number %I number --- rounded number %r number --- 0xhexadecimal %...h character number --- 0xHEXADECIMAL %...H character number --- U+hexadecimal %...u character number --- U+HEXADECIMAL %...U character number --- points %p number (scaled points) --- basepoints %b number (scaled points) --- table concat %...t table --- table concat %{.}t table --- serialize %...T sequenced (no nested tables) --- serialize %{.}T sequenced (no nested tables) --- boolean (logic) %l boolean --- BOOLEAN %L boolean --- whitespace %...w --- automatic %...a 'whatever' (string, table, ...) --- automatic %...A "whatever" (string, table, ...) - -local n = 0 - --- we are somewhat sloppy in parsing prefixes as it's not that critical - --- hard to avoid but we can collect them in a private namespace if needed - --- inline the next two makes no sense as we only use this in logging - -local sequenced = table.sequenced - -function string.autodouble(s,sep) - if s == nil then - return '""' - end - local t = type(s) - if t == "number" then - return tostring(s) -- tostring not really needed - end - if t == "table" then - return ('"' .. sequenced(s,sep or ",") .. '"') - end - return ('"' .. tostring(s) .. '"') -end - -function string.autosingle(s,sep) - if s == nil then - return "''" - end - local t = type(s) - if t == "number" then - return tostring(s) -- tostring not really needed - end - if t == "table" then - return ("'" .. sequenced(s,sep or ",") .. "'") - end - return ("'" .. tostring(s) .. "'") -end - -local tracedchars = { [0] = - -- the regular bunch - "[null]", "[soh]", "[stx]", "[etx]", "[eot]", "[enq]", "[ack]", "[bel]", - "[bs]", "[ht]", "[lf]", "[vt]", "[ff]", "[cr]", "[so]", "[si]", - "[dle]", "[dc1]", "[dc2]", "[dc3]", "[dc4]", "[nak]", "[syn]", "[etb]", - "[can]", "[em]", "[sub]", "[esc]", "[fs]", "[gs]", "[rs]", "[us]", - -- plus space - "[space]", -- 0x20 -} - -string.tracedchars = tracedchars -strings.tracers = tracedchars - -function string.tracedchar(b) - -- todo: table - if type(b) == "number" then - return tracedchars[b] or (utfchar(b) .. " (U+" .. format("%05X",b) .. ")") - else - local c = utfbyte(b) - return tracedchars[c] or (b .. " (U+" .. (c and format("%05X",c) or "?????") .. ")") - end -end - -function number.signed(i) - if i > 0 then - return "+", i - else - return "-", -i - end -end - -local zero = P("0")^1 / "" -local plus = P("+") / "" -local minus = P("-") -local separator = S(".") -local digit = R("09") -local trailing = zero^1 * #S("eE") -local exponent = (S("eE") * (plus + Cs((minus * zero^0 * P(-1))/"") + minus) * zero^0 * (P(-1) * Cc("0") + P(1)^1)) -local pattern_a = Cs(minus^0 * digit^1 * (separator/"" * trailing + separator * (trailing + digit)^0) * exponent) -local pattern_b = Cs((exponent + P(1))^0) - -function number.sparseexponent(f,n) - if not n then - n = f - f = "%e" - end - local tn = type(n) - if tn == "string" then -- cast to number - local m = tonumber(n) - if m then - return lpegmatch((f == "%e" or f == "%E") and pattern_a or pattern_b,format(f,m)) - end - elseif tn == "number" then - return lpegmatch((f == "%e" or f == "%E") and pattern_a or pattern_b,format(f,n)) - end - return tostring(n) -end - -local template = [[ -%s -%s -return function(%s) return %s end -]] - -local preamble, environment = "", { } - -if _LUAVERSION < 5.2 then - - preamble = [[ -local lpeg=lpeg -local type=type -local tostring=tostring -local tonumber=tonumber -local format=string.format -local concat=table.concat -local signed=number.signed -local points=number.points -local basepoints= number.basepoints -local utfchar=utf.char -local utfbyte=utf.byte -local lpegmatch=lpeg.match -local nspaces=string.nspaces -local tracedchar=string.tracedchar -local autosingle=string.autosingle -local autodouble=string.autodouble -local sequenced=table.sequenced -local formattednumber=number.formatted -local sparseexponent=number.sparseexponent - ]] - -else - - environment = { - global = global or _G, - lpeg = lpeg, - type = type, - tostring = tostring, - tonumber = tonumber, - format = string.format, - concat = table.concat, - signed = number.signed, - points = number.points, - basepoints = number.basepoints, - utfchar = utf.char, - utfbyte = utf.byte, - lpegmatch = lpeg.match, - nspaces = string.nspaces, - tracedchar = string.tracedchar, - autosingle = string.autosingle, - autodouble = string.autodouble, - sequenced = table.sequenced, - formattednumber = number.formatted, - sparseexponent = number.sparseexponent, - } - -end - --- -- -- - -local arguments = { "a1" } -- faster than previously used (select(n,...)) - -setmetatable(arguments, { __index = - function(t,k) - local v = t[k-1] .. ",a" .. k - t[k] = v - return v - end -}) - -local prefix_any = C((S("+- .") + R("09"))^0) -local prefix_tab = P("{") * C((1-P("}"))^0) * P("}") + C((1-R("az","AZ","09","%%"))^0) - --- we've split all cases as then we can optimize them (let's omit the fuzzy u) - --- todo: replace outer formats in next by .. - -local format_s = function(f) - n = n + 1 - if f and f ~= "" then - return format("format('%%%ss',a%s)",f,n) - else -- best no tostring in order to stay compatible (.. does a selective tostring too) - return format("(a%s or '')",n) -- goodie: nil check - end -end - -local format_S = function(f) -- can be optimized - n = n + 1 - if f and f ~= "" then - return format("format('%%%ss',tostring(a%s))",f,n) - else - return format("tostring(a%s)",n) - end -end - -local format_q = function() - n = n + 1 - return format("(a%s and format('%%q',a%s) or '')",n,n) -- goodie: nil check (maybe separate lpeg, not faster) -end - -local format_Q = function() -- can be optimized - n = n + 1 - return format("format('%%q',tostring(a%s))",n) -end - -local format_i = function(f) - n = n + 1 - if f and f ~= "" then - return format("format('%%%si',a%s)",f,n) - else - return format("format('%%i',a%s)",n) -- why not just tostring() - end -end - -local format_d = format_i - -local format_I = function(f) - n = n + 1 - return format("format('%%s%%%si',signed(a%s))",f,n) -end - -local format_f = function(f) - n = n + 1 - return format("format('%%%sf',a%s)",f,n) -end - --- The next one formats an integer as integer and very small values as zero. This is needed --- for pdf backend code. --- --- 1.23 % 1 : 0.23 --- - 1.23 % 1 : 0.77 --- --- We could probably use just %s with integers but who knows what Lua 5.3 will do? So let's --- for the moment use %i. - -local format_F = function(f) -- beware, no cast to number - n = n + 1 - if not f or f == "" then - return format("(((a%s > -0.0000000005 and a%s < 0.0000000005) and '0') or format((a%s %% 1 == 0) and '%%i' or '%%.9f',a%s))",n,n,n,n) - else - return format("format((a%s %% 1 == 0) and '%%i' or '%%%sf',a%s)",n,f,n) - end -end - -local format_g = function(f) - n = n + 1 - return format("format('%%%sg',a%s)",f,n) -end - -local format_G = function(f) - n = n + 1 - return format("format('%%%sG',a%s)",f,n) -end - -local format_e = function(f) - n = n + 1 - return format("format('%%%se',a%s)",f,n) -end - -local format_E = function(f) - n = n + 1 - return format("format('%%%sE',a%s)",f,n) -end - -local format_j = function(f) - n = n + 1 - return format("sparseexponent('%%%se',a%s)",f,n) -end - -local format_J = function(f) - n = n + 1 - return format("sparseexponent('%%%sE',a%s)",f,n) -end - -local format_x = function(f) - n = n + 1 - return format("format('%%%sx',a%s)",f,n) -end - -local format_X = function(f) - n = n + 1 - return format("format('%%%sX',a%s)",f,n) -end - -local format_o = function(f) - n = n + 1 - return format("format('%%%so',a%s)",f,n) -end - -local format_c = function() - n = n + 1 - return format("utfchar(a%s)",n) -end - -local format_C = function() - n = n + 1 - return format("tracedchar(a%s)",n) -end - -local format_r = function(f) - n = n + 1 - return format("format('%%%s.0f',a%s)",f,n) -end - -local format_h = function(f) - n = n + 1 - if f == "-" then - f = sub(f,2) - return format("format('%%%sx',type(a%s) == 'number' and a%s or utfbyte(a%s))",f == "" and "05" or f,n,n,n) - else - return format("format('0x%%%sx',type(a%s) == 'number' and a%s or utfbyte(a%s))",f == "" and "05" or f,n,n,n) - end -end - -local format_H = function(f) - n = n + 1 - if f == "-" then - f = sub(f,2) - return format("format('%%%sX',type(a%s) == 'number' and a%s or utfbyte(a%s))",f == "" and "05" or f,n,n,n) - else - return format("format('0x%%%sX',type(a%s) == 'number' and a%s or utfbyte(a%s))",f == "" and "05" or f,n,n,n) - end -end - -local format_u = function(f) - n = n + 1 - if f == "-" then - f = sub(f,2) - return format("format('%%%sx',type(a%s) == 'number' and a%s or utfbyte(a%s))",f == "" and "05" or f,n,n,n) - else - return format("format('u+%%%sx',type(a%s) == 'number' and a%s or utfbyte(a%s))",f == "" and "05" or f,n,n,n) - end -end - -local format_U = function(f) - n = n + 1 - if f == "-" then - f = sub(f,2) - return format("format('%%%sX',type(a%s) == 'number' and a%s or utfbyte(a%s))",f == "" and "05" or f,n,n,n) - else - return format("format('U+%%%sX',type(a%s) == 'number' and a%s or utfbyte(a%s))",f == "" and "05" or f,n,n,n) - end -end - -local format_p = function() - n = n + 1 - return format("points(a%s)",n) -end - -local format_b = function() - n = n + 1 - return format("basepoints(a%s)",n) -end - -local format_t = function(f) - n = n + 1 - if f and f ~= "" then - return format("concat(a%s,%q)",n,f) - else - return format("concat(a%s)",n) - end -end - -local format_T = function(f) - n = n + 1 - if f and f ~= "" then - return format("sequenced(a%s,%q)",n,f) - else - return format("sequenced(a%s)",n) - end -end - -local format_l = function() - n = n + 1 - return format("(a%s and 'true' or 'false')",n) -end - -local format_L = function() - n = n + 1 - return format("(a%s and 'TRUE' or 'FALSE')",n) -end - -local format_N = function() -- strips leading zeros - n = n + 1 - return format("tostring(tonumber(a%s) or a%s)",n,n) -end - -local format_a = function(f) - n = n + 1 - if f and f ~= "" then - return format("autosingle(a%s,%q)",n,f) - else - return format("autosingle(a%s)",n) - end -end - -local format_A = function(f) - n = n + 1 - if f and f ~= "" then - return format("autodouble(a%s,%q)",n,f) - else - return format("autodouble(a%s)",n) - end -end - -local format_w = function(f) -- handy when doing depth related indent - n = n + 1 - f = tonumber(f) - if f then -- not that useful - return format("nspaces[%s+a%s]",f,n) -- no real need for tonumber - else - return format("nspaces[a%s]",n) -- no real need for tonumber - end -end - -local format_W = function(f) -- handy when doing depth related indent - return format("nspaces[%s]",tonumber(f) or 0) -end - --- maybe to util-num - -local digit = patterns.digit -local period = patterns.period -local three = digit * digit * digit - -local splitter = Cs ( - (((1 - (three^1 * period))^1 + C(three)) * (Carg(1) * three)^1 + C((1-period)^1)) - * (P(1)/"" * Carg(2)) * C(2) -) - -patterns.formattednumber = splitter - -function number.formatted(n,sep1,sep2) - local s = type(s) == "string" and n or format("%0.2f",n) - if sep1 == true then - return lpegmatch(splitter,s,1,".",",") - elseif sep1 == "." then - return lpegmatch(splitter,s,1,sep1,sep2 or ",") - elseif sep1 == "," then - return lpegmatch(splitter,s,1,sep1,sep2 or ".") - else - return lpegmatch(splitter,s,1,sep1 or ",",sep2 or ".") - end -end - --- print(number.formatted(1)) --- print(number.formatted(12)) --- print(number.formatted(123)) --- print(number.formatted(1234)) --- print(number.formatted(12345)) --- print(number.formatted(123456)) --- print(number.formatted(1234567)) --- print(number.formatted(12345678)) --- print(number.formatted(12345678,true)) --- print(number.formatted(1234.56,"!","?")) - -local format_m = function(f) - n = n + 1 - if not f or f == "" then - f = "," - end - return format([[formattednumber(a%s,%q,".")]],n,f) -end - -local format_M = function(f) - n = n + 1 - if not f or f == "" then - f = "." - end - return format([[formattednumber(a%s,%q,",")]],n,f) -end - --- - -local format_z = function(f) - n = n + (tonumber(f) or 1) - return "''" -- okay, not that efficient to append '' but a special case anyway -end - --- - -local format_rest = function(s) - return format("%q",s) -- catches " and \n and such -end - -local format_extension = function(extensions,f,name) - local extension = extensions[name] or "tostring(%s)" - local f = tonumber(f) or 1 - if f == 0 then - return extension - elseif f == 1 then - n = n + 1 - local a = "a" .. n - return format(extension,a,a) -- maybe more times? - elseif f < 0 then - local a = "a" .. (n + f + 1) - return format(extension,a,a) - else - local t = { } - for i=1,f do - n = n + 1 - t[#t+1] = "a" .. n - end - return format(extension,unpack(t)) - end -end - --- aA b cC d eE f gG hH iI jJ lL mM N o p qQ r sS tT uU wW xX z - -local builder = Cs { "start", - start = ( - ( - P("%") / "" - * ( - V("!") -- new - + V("s") + V("q") - + V("i") + V("d") - + V("f") + V("F") + V("g") + V("G") + V("e") + V("E") - + V("x") + V("X") + V("o") - -- - + V("c") - + V("C") - + V("S") -- new - + V("Q") -- new - + V("N") -- new - -- - + V("r") - + V("h") + V("H") + V("u") + V("U") - + V("p") + V("b") - + V("t") + V("T") - + V("l") + V("L") - + V("I") - + V("w") -- new - + V("W") -- new - + V("a") -- new - + V("A") -- new - + V("j") + V("J") -- stripped e E - + V("m") + V("M") -- new - + V("z") -- new - -- - -- + V("?") -- ignores probably messed up % - ) - + V("*") - ) - * (P(-1) + Carg(1)) - )^0, - -- - ["s"] = (prefix_any * P("s")) / format_s, -- %s => regular %s (string) - ["q"] = (prefix_any * P("q")) / format_q, -- %q => regular %q (quoted string) - ["i"] = (prefix_any * P("i")) / format_i, -- %i => regular %i (integer) - ["d"] = (prefix_any * P("d")) / format_d, -- %d => regular %d (integer) - ["f"] = (prefix_any * P("f")) / format_f, -- %f => regular %f (float) - ["F"] = (prefix_any * P("F")) / format_F, -- %F => regular %f (float) but 0/1 check - ["g"] = (prefix_any * P("g")) / format_g, -- %g => regular %g (float) - ["G"] = (prefix_any * P("G")) / format_G, -- %G => regular %G (float) - ["e"] = (prefix_any * P("e")) / format_e, -- %e => regular %e (float) - ["E"] = (prefix_any * P("E")) / format_E, -- %E => regular %E (float) - ["x"] = (prefix_any * P("x")) / format_x, -- %x => regular %x (hexadecimal) - ["X"] = (prefix_any * P("X")) / format_X, -- %X => regular %X (HEXADECIMAL) - ["o"] = (prefix_any * P("o")) / format_o, -- %o => regular %o (octal) - -- - ["S"] = (prefix_any * P("S")) / format_S, -- %S => %s (tostring) - ["Q"] = (prefix_any * P("Q")) / format_S, -- %Q => %q (tostring) - ["N"] = (prefix_any * P("N")) / format_N, -- %N => tonumber (strips leading zeros) - ["c"] = (prefix_any * P("c")) / format_c, -- %c => utf character (extension to regular) - ["C"] = (prefix_any * P("C")) / format_C, -- %c => U+.... utf character - -- - ["r"] = (prefix_any * P("r")) / format_r, -- %r => round - ["h"] = (prefix_any * P("h")) / format_h, -- %h => 0x0a1b2 (when - no 0x) was v - ["H"] = (prefix_any * P("H")) / format_H, -- %H => 0x0A1B2 (when - no 0x) was V - ["u"] = (prefix_any * P("u")) / format_u, -- %u => u+0a1b2 (when - no u+) - ["U"] = (prefix_any * P("U")) / format_U, -- %U => U+0A1B2 (when - no U+) - ["p"] = (prefix_any * P("p")) / format_p, -- %p => 12.345pt / maybe: P (and more units) - ["b"] = (prefix_any * P("b")) / format_b, -- %b => 12.342bp / maybe: B (and more units) - ["t"] = (prefix_tab * P("t")) / format_t, -- %t => concat - ["T"] = (prefix_tab * P("T")) / format_T, -- %t => sequenced - ["l"] = (prefix_any * P("l")) / format_l, -- %l => boolean - ["L"] = (prefix_any * P("L")) / format_L, -- %L => BOOLEAN - ["I"] = (prefix_any * P("I")) / format_I, -- %I => signed integer - -- - ["w"] = (prefix_any * P("w")) / format_w, -- %w => n spaces (optional prefix is added) - ["W"] = (prefix_any * P("W")) / format_W, -- %W => mandate prefix, no specifier - -- - ["j"] = (prefix_any * P("j")) / format_j, -- %j => %e (float) stripped exponent (irrational) - ["J"] = (prefix_any * P("J")) / format_J, -- %J => %E (float) stripped exponent (irrational) - -- - ["m"] = (prefix_tab * P("m")) / format_m, -- %m => xxx.xxx.xxx,xx (optional prefix instead of .) - ["M"] = (prefix_tab * P("M")) / format_M, -- %M => xxx,xxx,xxx.xx (optional prefix instead of ,) - -- - ["z"] = (prefix_any * P("z")) / format_z, -- %M => xxx,xxx,xxx.xx (optional prefix instead of ,) - -- - ["a"] = (prefix_any * P("a")) / format_a, -- %a => '...' (forces tostring) - ["A"] = (prefix_any * P("A")) / format_A, -- %A => "..." (forces tostring) - -- - ["*"] = Cs(((1-P("%"))^1 + P("%%")/"%%")^1) / format_rest, -- rest (including %%) - ["?"] = Cs(((1-P("%"))^1 )^1) / format_rest, -- rest (including %%) - -- - ["!"] = Carg(2) * prefix_any * P("!") * C((1-P("!"))^1) * P("!") / format_extension, -} - --- we can be clever and only alias what is needed - --- local direct = Cs ( --- P("%")/"" --- * Cc([[local format = string.format return function(str) return format("%]]) --- * (S("+- .") + R("09"))^0 --- * S("sqidfgGeExXo") --- * Cc([[",str) end]]) --- * P(-1) --- ) - -local direct = Cs ( - P("%") - * (S("+- .") + R("09"))^0 - * S("sqidfgGeExXo") - * P(-1) / [[local format = string.format return function(str) return format("%0",str) end]] -) - -local function make(t,str) - local f - local p - local p = lpegmatch(direct,str) - if p then - -- f = loadstripped(p)() - -- print("builder 1 >",p) - f = loadstripped(p)() - else - n = 0 - -- p = lpegmatch(builder,str,1,"..",t._extensions_) -- after this we know n - p = lpegmatch(builder,str,1,t._connector_,t._extensions_) -- after this we know n - if n > 0 then - p = format(template,preamble,t._preamble_,arguments[n],p) - -- print("builder 2 >",p) - f = loadstripped(p,t._environment_)() -- t._environment is not populated (was experiment) - else - f = function() return str end - end - end - t[str] = f - return f -end - --- -- collect periodically --- --- local threshold = 1000 -- max nof cached formats --- --- local function make(t,str) --- local f = rawget(t,str) --- if f then --- return f --- end --- local parent = t._t_ --- if parent._n_ > threshold then --- local m = { _t_ = parent } --- getmetatable(parent).__index = m --- setmetatable(m, { __index = make }) --- else --- parent._n_ = parent._n_ + 1 --- end --- local f --- local p = lpegmatch(direct,str) --- if p then --- f = loadstripped(p)() --- else --- n = 0 --- p = lpegmatch(builder,str,1,"..",parent._extensions_) -- after this we know n --- if n > 0 then --- p = format(template,preamble,parent._preamble_,arguments[n],p) --- -- print("builder>",p) --- f = loadstripped(p)() --- else --- f = function() return str end --- end --- end --- t[str] = f --- return f --- end - -local function use(t,fmt,...) - return t[fmt](...) -end - -strings.formatters = { } - --- we cannot make these tables weak, unless we start using an indirect --- table (metatable) in which case we could better keep a count and --- clear that table when a threshold is reached - --- _connector_ is an experiment - -if _LUAVERSION < 5.2 then - - function strings.formatters.new(noconcat) - local t = { _type_ = "formatter", _connector_ = noconcat and "," or "..", _extensions_ = { }, _preamble_ = preamble, _environment_ = { } } - setmetatable(t, { __index = make, __call = use }) - return t - end - -else - - function strings.formatters.new(noconcat) - local e = { } -- better make a copy as we can overload - for k, v in next, environment do - e[k] = v - end - local t = { _type_ = "formatter", _connector_ = noconcat and "," or "..", _extensions_ = { }, _preamble_ = "", _environment_ = e } - setmetatable(t, { __index = make, __call = use }) - return t - end - -end - --- function strings.formatters.new() --- local t = { _extensions_ = { }, _preamble_ = "", _type_ = "formatter", _n_ = 0 } --- local m = { _t_ = t } --- setmetatable(t, { __index = m, __call = use }) --- setmetatable(m, { __index = make }) --- return t --- end - -local formatters = strings.formatters.new() -- the default instance - -string.formatters = formatters -- in the main string namespace -string.formatter = function(str,...) return formatters[str](...) end -- sometimes nicer name - -local function add(t,name,template,preamble) - if type(t) == "table" and t._type_ == "formatter" then - t._extensions_[name] = template or "%s" - if type(preamble) == "string" then - t._preamble_ = preamble .. "\n" .. t._preamble_ -- so no overload ! - elseif type(preamble) == "table" then - for k, v in next, preamble do - t._environment_[k] = v - end - end - end -end - -strings.formatters.add = add - --- registered in the default instance (should we fall back on this one?) - -patterns.xmlescape = Cs((P("<")/"<" + P(">")/">" + P("&")/"&" + P('"')/""" + P(1))^0) -patterns.texescape = Cs((C(S("#$%\\{}"))/"\\%1" + P(1))^0) -patterns.luaescape = Cs(((1-S('"\n'))^1 + P('"')/'\\"' + P('\n')/'\\n"')^0) -- maybe also \0 -patterns.luaquoted = Cs(Cc('"') * ((1-S('"\n'))^1 + P('"')/'\\"' + P('\n')/'\\n"')^0 * Cc('"')) - --- escaping by lpeg is faster for strings without quotes, slower on a string with quotes, but --- faster again when other q-escapables are found (the ones we don't need to escape) - --- add(formatters,"xml", [[lpegmatch(xmlescape,%s)]],[[local xmlescape = lpeg.patterns.xmlescape]]) --- add(formatters,"tex", [[lpegmatch(texescape,%s)]],[[local texescape = lpeg.patterns.texescape]]) --- add(formatters,"lua", [[lpegmatch(luaescape,%s)]],[[local luaescape = lpeg.patterns.luaescape]]) - -if _LUAVERSION < 5.2 then - - add(formatters,"xml",[[lpegmatch(xmlescape,%s)]],"local xmlescape = lpeg.patterns.xmlescape") - add(formatters,"tex",[[lpegmatch(texescape,%s)]],"local texescape = lpeg.patterns.texescape") - add(formatters,"lua",[[lpegmatch(luaescape,%s)]],"local luaescape = lpeg.patterns.luaescape") - -else - - add(formatters,"xml",[[lpegmatch(xmlescape,%s)]],{ xmlescape = lpeg.patterns.xmlescape }) - add(formatters,"tex",[[lpegmatch(texescape,%s)]],{ texescape = lpeg.patterns.texescape }) - add(formatters,"lua",[[lpegmatch(luaescape,%s)]],{ luaescape = lpeg.patterns.luaescape }) - -end - --- -- yes or no: --- --- local function make(t,str) --- local f --- local p = lpegmatch(direct,str) --- if p then --- f = loadstripped(p)() --- else --- n = 0 --- p = lpegmatch(builder,str,1,",") -- after this we know n --- if n > 0 then --- p = format(template,template_shortcuts,arguments[n],p) --- f = loadstripped(p)() --- else --- f = function() return str end --- end --- end --- t[str] = f --- return f --- end --- --- local formatteds = string.formatteds or { } --- string.formatteds = formatteds --- --- setmetatable(formatteds, { __index = make, __call = use }) - --- This is a somewhat silly one used in commandline reconstruction but the older --- method, using a combination of fine, gsub, quoted and unquoted was not that --- reliable. --- --- '"foo"bar \"and " whatever"' => "foo\"bar \"and \" whatever" --- 'foo"bar \"and " whatever' => "foo\"bar \"and \" whatever" - -local dquote = patterns.dquote -- P('"') -local equote = patterns.escaped + dquote / '\\"' + 1 -local space = patterns.space -local cquote = Cc('"') - -local pattern = - Cs(dquote * (equote - P(-2))^0 * dquote) -- we keep the outer but escape unescaped ones - + Cs(cquote * (equote - space)^0 * space * equote^0 * cquote) -- we escape unescaped ones - -function string.optionalquoted(str) - return lpegmatch(pattern,str) or str -end - -local pattern = Cs((newline / (os.newline or "\r") + 1)^0) - -function string.replacenewlines(str) - return lpegmatch(pattern,str) -end diff --git a/tex/compat/lualibs/lualibs-util-tab.lua b/tex/compat/lualibs/lualibs-util-tab.lua deleted file mode 100644 index a6239adf4091fd3f71c2e8a0d582275ca88cbf51..0000000000000000000000000000000000000000 --- a/tex/compat/lualibs/lualibs-util-tab.lua +++ /dev/null @@ -1,837 +0,0 @@ -if not modules then modules = { } end modules ['util-tab'] = { - version = 1.001, - comment = "companion to luat-lib.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -utilities = utilities or {} -utilities.tables = utilities.tables or { } -local tables = utilities.tables - -local format, gmatch, gsub, sub = string.format, string.gmatch, string.gsub, string.sub -local concat, insert, remove, sort = table.concat, table.insert, table.remove, table.sort -local setmetatable, getmetatable, tonumber, tostring = setmetatable, getmetatable, tonumber, tostring -local type, next, rawset, tonumber, tostring, load, select = type, next, rawset, tonumber, tostring, load, select -local lpegmatch, P, Cs, Cc = lpeg.match, lpeg.P, lpeg.Cs, lpeg.Cc -local sortedkeys, sortedpairs = table.sortedkeys, table.sortedpairs -local formatters = string.formatters -local utftoeight = utf.toeight - -local splitter = lpeg.tsplitat(".") - -function utilities.tables.definetable(target,nofirst,nolast) -- defines undefined tables - local composed, t = nil, { } - local snippets = lpegmatch(splitter,target) - for i=1,#snippets - (nolast and 1 or 0) do - local name = snippets[i] - if composed then - composed = composed .. "." .. name - t[#t+1] = formatters["if not %s then %s = { } end"](composed,composed) - else - composed = name - if not nofirst then - t[#t+1] = formatters["%s = %s or { }"](composed,composed) - end - end - end - if composed then - if nolast then - composed = composed .. "." .. snippets[#snippets] - end - return concat(t,"\n"), composed -- could be shortcut - else - return "", target - end -end - --- local t = tables.definedtable("a","b","c","d") - -function tables.definedtable(...) - local t = _G - for i=1,select("#",...) do - local li = select(i,...) - local tl = t[li] - if not tl then - tl = { } - t[li] = tl - end - t = tl - end - return t -end - -function tables.accesstable(target,root) - local t = root or _G - for name in gmatch(target,"([^%.]+)") do - t = t[name] - if not t then - return - end - end - return t -end - -function tables.migratetable(target,v,root) - local t = root or _G - local names = lpegmatch(splitter,target) - for i=1,#names-1 do - local name = names[i] - t[name] = t[name] or { } - t = t[name] - if not t then - return - end - end - t[names[#names]] = v -end - -function tables.removevalue(t,value) -- todo: n - if value then - for i=1,#t do - if t[i] == value then - remove(t,i) - -- remove all, so no: return - end - end - end -end - -function tables.replacevalue(t,oldvalue,newvalue) - if oldvalue and newvalue then - for i=1,#t do - if t[i] == oldvalue then - t[i] = newvalue - -- replace all, so no: return - end - end - end -end - -function tables.insertbeforevalue(t,value,extra) - for i=1,#t do - if t[i] == extra then - remove(t,i) - end - end - for i=1,#t do - if t[i] == value then - insert(t,i,extra) - return - end - end - insert(t,1,extra) -end - -function tables.insertaftervalue(t,value,extra) - for i=1,#t do - if t[i] == extra then - remove(t,i) - end - end - for i=1,#t do - if t[i] == value then - insert(t,i+1,extra) - return - end - end - insert(t,#t+1,extra) -end - --- experimental - -local escape = Cs(Cc('"') * ((P('"')/'""' + P(1))^0) * Cc('"')) - -function table.tocsv(t,specification) - if t and #t > 0 then - local result = { } - local r = { } - specification = specification or { } - local fields = specification.fields - if type(fields) ~= "string" then - fields = sortedkeys(t[1]) - end - local separator = specification.separator or "," - if specification.preamble == true then - for f=1,#fields do - r[f] = lpegmatch(escape,tostring(fields[f])) - end - result[1] = concat(r,separator) - end - for i=1,#t do - local ti = t[i] - for f=1,#fields do - local field = ti[fields[f]] - if type(field) == "string" then - r[f] = lpegmatch(escape,field) - else - r[f] = tostring(field) - end - end - result[#result+1] = concat(r,separator) - end - return concat(result,"\n") - else - return "" - end -end - --- local nspaces = utilities.strings.newrepeater(" ") --- local escape = Cs((P("<")/"<" + P(">")/">" + P("&")/"&" + P(1))^0) --- --- local function toxml(t,d,result,step) --- for k, v in sortedpairs(t) do --- local s = nspaces[d] --- local tk = type(k) --- local tv = type(v) --- if tv == "table" then --- if tk == "number" then --- result[#result+1] = format("%s<entry n='%s'>",s,k) --- toxml(v,d+step,result,step) --- result[#result+1] = format("%s</entry>",s,k) --- else --- result[#result+1] = format("%s<%s>",s,k) --- toxml(v,d+step,result,step) --- result[#result+1] = format("%s</%s>",s,k) --- end --- elseif tv == "string" then --- if tk == "number" then --- result[#result+1] = format("%s<entry n='%s'>%s</entry>",s,k,lpegmatch(escape,v),k) --- else --- result[#result+1] = format("%s<%s>%s</%s>",s,k,lpegmatch(escape,v),k) --- end --- elseif tk == "number" then --- result[#result+1] = format("%s<entry n='%s'>%s</entry>",s,k,tostring(v),k) --- else --- result[#result+1] = format("%s<%s>%s</%s>",s,k,tostring(v),k) --- end --- end --- end --- --- much faster - -local nspaces = utilities.strings.newrepeater(" ") - -local function toxml(t,d,result,step) - for k, v in sortedpairs(t) do - local s = nspaces[d] -- inlining this is somewhat faster but gives more formatters - local tk = type(k) - local tv = type(v) - if tv == "table" then - if tk == "number" then - result[#result+1] = formatters["%s<entry n='%s'>"](s,k) - toxml(v,d+step,result,step) - result[#result+1] = formatters["%s</entry>"](s,k) - else - result[#result+1] = formatters["%s<%s>"](s,k) - toxml(v,d+step,result,step) - result[#result+1] = formatters["%s</%s>"](s,k) - end - elseif tv == "string" then - if tk == "number" then - result[#result+1] = formatters["%s<entry n='%s'>%!xml!</entry>"](s,k,v,k) - else - result[#result+1] = formatters["%s<%s>%!xml!</%s>"](s,k,v,k) - end - elseif tk == "number" then - result[#result+1] = formatters["%s<entry n='%s'>%S</entry>"](s,k,v,k) - else - result[#result+1] = formatters["%s<%s>%S</%s>"](s,k,v,k) - end - end -end - --- function table.toxml(t,name,nobanner,indent,spaces) --- local noroot = name == false --- local result = (nobanner or noroot) and { } or { "<?xml version='1.0' standalone='yes' ?>" } --- local indent = rep(" ",indent or 0) --- local spaces = rep(" ",spaces or 1) --- if noroot then --- toxml( t, inndent, result, spaces) --- else --- toxml( { [name or "root"] = t }, indent, result, spaces) --- end --- return concat(result,"\n") --- end - -function table.toxml(t,specification) - specification = specification or { } - local name = specification.name - local noroot = name == false - local result = (specification.nobanner or noroot) and { } or { "<?xml version='1.0' standalone='yes' ?>" } - local indent = specification.indent or 0 - local spaces = specification.spaces or 1 - if noroot then - toxml( t, indent, result, spaces) - else - toxml( { [name or "data"] = t }, indent, result, spaces) - end - return concat(result,"\n") -end - --- also experimental - --- encapsulate(table,utilities.tables) --- encapsulate(table,utilities.tables,true) --- encapsulate(table,true) - -function tables.encapsulate(core,capsule,protect) - if type(capsule) ~= "table" then - protect = true - capsule = { } - end - for key, value in next, core do - if capsule[key] then - print(formatters["\ninvalid %s %a in %a"]("inheritance",key,core)) - os.exit() - else - capsule[key] = value - end - end - if protect then - for key, value in next, core do - core[key] = nil - end - setmetatable(core, { - __index = capsule, - __newindex = function(t,key,value) - if capsule[key] then - print(formatters["\ninvalid %s %a' in %a"]("overload",key,core)) - os.exit() - else - rawset(t,key,value) - end - end - } ) - end -end - --- best keep [%q] keys (as we have some in older applications i.e. saving user data - -local f_hashed_string = formatters["[%q]=%q,"] -local f_hashed_number = formatters["[%q]=%s,"] -local f_hashed_boolean = formatters["[%q]=%l,"] -local f_hashed_table = formatters["[%q]="] - -local f_indexed_string = formatters["[%s]=%q,"] -local f_indexed_number = formatters["[%s]=%s,"] -local f_indexed_boolean = formatters["[%s]=%l,"] -local f_indexed_table = formatters["[%s]="] - -local f_ordered_string = formatters["%q,"] -local f_ordered_number = formatters["%s,"] -local f_ordered_boolean = formatters["%l,"] - -function table.fastserialize(t,prefix) - - -- prefix should contain the = - -- not sorted - -- only number and string indices (currently) - - local r = { type(prefix) == "string" and prefix or "return" } - local m = 1 - - local function fastserialize(t,outer) -- no mixes - local n = #t - m = m + 1 - r[m] = "{" - if n > 0 then - for i=0,n do - local v = t[i] - local tv = type(v) - if tv == "string" then - m = m + 1 r[m] = f_ordered_string(v) - elseif tv == "number" then - m = m + 1 r[m] = f_ordered_number(v) - elseif tv == "table" then - fastserialize(v) - elseif tv == "boolean" then - m = m + 1 r[m] = f_ordered_boolean(v) - end - end - end - for k, v in next, t do - local tk = type(k) - if tk == "number" then - if k > n or k < 0 then - local tv = type(v) - if tv == "string" then - m = m + 1 r[m] = f_indexed_string(k,v) - elseif tv == "number" then - m = m + 1 r[m] = f_indexed_number(k,v) - elseif tv == "table" then - m = m + 1 r[m] = f_indexed_table(k) - fastserialize(v) - elseif tv == "boolean" then - m = m + 1 r[m] = f_indexed_boolean(k,v) - end - end - else - local tv = type(v) - if tv == "string" then - m = m + 1 r[m] = f_hashed_string(k,v) - elseif tv == "number" then - m = m + 1 r[m] = f_hashed_number(k,v) - elseif tv == "table" then - m = m + 1 r[m] = f_hashed_table(k) - fastserialize(v) - elseif tv == "boolean" then - m = m + 1 r[m] = f_hashed_boolean(k,v) - end - end - end - m = m + 1 - if outer then - r[m] = "}" - else - r[m] = "}," - end - return r - end - return concat(fastserialize(t,true)) -end - -function table.deserialize(str) - if not str or str == "" then - return - end - local code = load(str) - if not code then - return - end - code = code() - if not code then - return - end - return code -end - --- inspect(table.fastserialize { a = 1, b = { 4, { 5, 6 } }, c = { d = 7, e = 'f"g\nh' } }) - -function table.load(filename,loader) - if filename then - local t = (loader or io.loaddata)(filename) - if t and t ~= "" then - local t = utftoeight(t) - t = load(t) - if type(t) == "function" then - t = t() - if type(t) == "table" then - return t - end - end - end - end -end - -function table.save(filename,t,n,...) - io.savedata(filename,table.serialize(t,n == nil and true or n,...)) -- no frozen table.serialize -end - -local f_key_value = formatters["%s=%q"] -local f_add_table = formatters[" {%t},\n"] -local f_return_table = formatters["return {\n%t}"] - -local function slowdrop(t) -- maybe less memory (intermediate concat) - local r = { } - local l = { } - for i=1,#t do - local ti = t[i] - local j = 0 - for k, v in next, ti do - j = j + 1 - l[j] = f_key_value(k,v) - end - r[i] = f_add_table(l) - end - return f_return_table(r) -end - -local function fastdrop(t) - local r = { "return {\n" } - local m = 1 - for i=1,#t do - local ti = t[i] - m = m + 1 r[m] = " {" - for k, v in next, ti do - m = m + 1 r[m] = f_key_value(k,v) - end - m = m + 1 r[m] = "},\n" - end - m = m + 1 - r[m] = "}" - return concat(r) -end - -function table.drop(t,slow) -- only { { a=2 }, {a=3} } -- for special cases - if #t == 0 then - return "return { }" - elseif slow == true then - return slowdrop(t) -- less memory - else - return fastdrop(t) -- some 15% faster - end -end - --- inspect(table.drop({ { a=2 }, {a=3} })) --- inspect(table.drop({ { a=2 }, {a=3} },true)) - -function table.autokey(t,k) - local v = { } - t[k] = v - return v -end - -local selfmapper = { __index = function(t,k) t[k] = k return k end } - -function table.twowaymapper(t) - if not t then - t = { } - else - for i=0,#t do - local ti = t[i] -- t[1] = "one" - if ti then - local i = tostring(i) - t[i] = ti -- t["1"] = "one" - t[ti] = i -- t["one"] = "1" - end - end - t[""] = t[0] or "" - end - -- setmetatableindex(t,"key") - setmetatable(t,selfmapper) - return t -end - --- The next version is somewhat faster, although in practice one will seldom --- serialize a lot using this one. Often the above variants are more efficient. --- If we would really need this a lot, we could hash q keys, or just not used --- indented code. - --- char-def.lua : 0.53 -> 0.38 --- husayni.tma : 0.28 -> 0.19 - -local f_start_key_idx = formatters["%w{"] -local f_start_key_num = formatters["%w[%s]={"] -local f_start_key_str = formatters["%w[%q]={"] -local f_start_key_boo = formatters["%w[%l]={"] -local f_start_key_nop = formatters["%w{"] - -local f_stop = formatters["%w},"] - -local f_key_num_value_num = formatters["%w[%s]=%s,"] -local f_key_str_value_num = formatters["%w[%q]=%s,"] -local f_key_boo_value_num = formatters["%w[%l]=%s,"] - -local f_key_num_value_str = formatters["%w[%s]=%q,"] -local f_key_str_value_str = formatters["%w[%q]=%q,"] -local f_key_boo_value_str = formatters["%w[%l]=%q,"] - -local f_key_num_value_boo = formatters["%w[%s]=%l,"] -local f_key_str_value_boo = formatters["%w[%q]=%l,"] -local f_key_boo_value_boo = formatters["%w[%l]=%l,"] - -local f_key_num_value_not = formatters["%w[%s]={},"] -local f_key_str_value_not = formatters["%w[%q]={},"] -local f_key_boo_value_not = formatters["%w[%l]={},"] - -local f_key_num_value_seq = formatters["%w[%s]={ %, t },"] -local f_key_str_value_seq = formatters["%w[%q]={ %, t },"] -local f_key_boo_value_seq = formatters["%w[%l]={ %, t },"] - -local f_val_num = formatters["%w%s,"] -local f_val_str = formatters["%w%q,"] -local f_val_boo = formatters["%w%l,"] -local f_val_not = formatters["%w{},"] -local f_val_seq = formatters["%w{ %, t },"] -local f_fin_seq = formatters[" %, t }"] - -local f_table_return = formatters["return {"] -local f_table_name = formatters["%s={"] -local f_table_direct = formatters["{"] -local f_table_entry = formatters["[%q]={"] -local f_table_finish = formatters["}"] - ------ f_string = formatters["%q"] - -local spaces = utilities.strings.newrepeater(" ") - -local original_serialize = table.serialize -- the extensive one, the one we started with - --- there is still room for optimization: index run, key run, but i need to check with the --- latest lua for the value of #n (with holes) .. anyway for tracing purposes we want --- indices / keys being sorted, so it will never be real fast - -local function serialize(root,name,specification) - - if type(specification) == "table" then - return original_serialize(root,name,specification) -- the original one - end - - local t -- = { } - local n = 1 - local unknown = false - --- local function simple_table(t) --- local ts = #t --- if ts > 0 then --- local n = 0 --- for _, v in next, t do --- n = n + 1 --- if type(v) == "table" then --- return nil --- end --- end --- if n == ts then --- local tt = { } --- local nt = 0 --- for i=1,ts do --- local v = t[i] --- local tv = type(v) --- nt = nt + 1 --- if tv == "number" then --- tt[nt] = v --- elseif tv == "string" then --- tt[nt] = format("%q",v) -- f_string(v) --- elseif tv == "boolean" then --- tt[nt] = v and "true" or "false" --- else --- return nil --- end --- end --- return tt --- end --- end --- return nil --- end - - local function simple_table(t) - local nt = #t - if nt > 0 then - local n = 0 - for _, v in next, t do - n = n + 1 - if type(v) == "table" then - return nil - end - end - local haszero = t[0] - if n == nt then - local tt = { } - for i=1,nt do - local v = t[i] - local tv = type(v) - if tv == "number" then - tt[i] = v -- not needed tostring(v) - elseif tv == "string" then - tt[i] = format("%q",v) -- f_string(v) - elseif tv == "boolean" then - tt[i] = v and "true" or "false" - else - return nil - end - end - return tt - elseif haszero and (n == nt + 1) then - local tt = { } - for i=0,nt do - local v = t[i] - local tv = type(v) - if tv == "number" then - tt[i+1] = v -- not needed tostring(v) - elseif tv == "string" then - tt[i+1] = format("%q",v) -- f_string(v) - elseif tv == "boolean" then - tt[i+1] = v and "true" or "false" - else - return nil - end - end - tt[1] = "[0] = " .. tt[1] - return tt - end - end - return nil - end - - local function do_serialize(root,name,depth,level,indexed) - if level > 0 then - n = n + 1 - if indexed then - t[n] = f_start_key_idx(depth) - else - local tn = type(name) - if tn == "number" then - t[n] = f_start_key_num(depth,name) - elseif tn == "string" then - t[n] = f_start_key_str(depth,name) - elseif tn == "boolean" then - t[n] = f_start_key_boo(depth,name) - else - t[n] = f_start_key_nop(depth) - end - end - depth = depth + 1 - end - -- we could check for k (index) being number (cardinal) - if root and next(root) ~= nil then - local first = nil - local last = 0 - last = #root - for k=1,last do - if root[k] == nil then - last = k - 1 - break - end - end - if last > 0 then - first = 1 - end - local sk = sortedkeys(root) -- inline fast version?\ - for i=1,#sk do - local k = sk[i] - local v = root[k] - local tv = type(v) - local tk = type(k) - if first and tk == "number" and k <= last and k >= first then - if tv == "number" then - n = n + 1 t[n] = f_val_num(depth,v) - elseif tv == "string" then - n = n + 1 t[n] = f_val_str(depth,v) - elseif tv == "table" then - if next(v) == nil then -- tricky as next is unpredictable in a hash - n = n + 1 t[n] = f_val_not(depth) - else - local st = simple_table(v) - if st then - n = n + 1 t[n] = f_val_seq(depth,st) - else - do_serialize(v,k,depth,level+1,true) - end - end - elseif tv == "boolean" then - n = n + 1 t[n] = f_val_boo(depth,v) - elseif unknown then - n = n + 1 t[n] = f_val_str(depth,tostring(v)) - end - elseif tv == "number" then - if tk == "number" then - n = n + 1 t[n] = f_key_num_value_num(depth,k,v) - elseif tk == "string" then - n = n + 1 t[n] = f_key_str_value_num(depth,k,v) - elseif tk == "boolean" then - n = n + 1 t[n] = f_key_boo_value_num(depth,k,v) - elseif unknown then - n = n + 1 t[n] = f_key_str_value_num(depth,tostring(k),v) - end - elseif tv == "string" then - if tk == "number" then - n = n + 1 t[n] = f_key_num_value_str(depth,k,v) - elseif tk == "string" then - n = n + 1 t[n] = f_key_str_value_str(depth,k,v) - elseif tk == "boolean" then - n = n + 1 t[n] = f_key_boo_value_str(depth,k,v) - elseif unknown then - n = n + 1 t[n] = f_key_str_value_str(depth,tostring(k),v) - end - elseif tv == "table" then - if next(v) == nil then - if tk == "number" then - n = n + 1 t[n] = f_key_num_value_not(depth,k) - elseif tk == "string" then - n = n + 1 t[n] = f_key_str_value_not(depth,k) - elseif tk == "boolean" then - n = n + 1 t[n] = f_key_boo_value_not(depth,k) - elseif unknown then - n = n + 1 t[n] = f_key_str_value_not(depth,tostring(k)) - end - else - local st = simple_table(v) - if not st then - do_serialize(v,k,depth,level+1) - elseif tk == "number" then - n = n + 1 t[n] = f_key_num_value_seq(depth,k,st) - elseif tk == "string" then - n = n + 1 t[n] = f_key_str_value_seq(depth,k,st) - elseif tk == "boolean" then - n = n + 1 t[n] = f_key_boo_value_seq(depth,k,st) - elseif unknown then - n = n + 1 t[n] = f_key_str_value_seq(depth,tostring(k),st) - end - end - elseif tv == "boolean" then - if tk == "number" then - n = n + 1 t[n] = f_key_num_value_boo(depth,k,v) - elseif tk == "string" then - n = n + 1 t[n] = f_key_str_value_boo(depth,k,v) - elseif tk == "boolean" then - n = n + 1 t[n] = f_key_boo_value_boo(depth,k,v) - elseif unknown then - n = n + 1 t[n] = f_key_str_value_boo(depth,tostring(k),v) - end - else - if tk == "number" then - n = n + 1 t[n] = f_key_num_value_str(depth,k,tostring(v)) - elseif tk == "string" then - n = n + 1 t[n] = f_key_str_value_str(depth,k,tostring(v)) - elseif tk == "boolean" then - n = n + 1 t[n] = f_key_boo_value_str(depth,k,tostring(v)) - elseif unknown then - n = n + 1 t[n] = f_key_str_value_str(depth,tostring(k),tostring(v)) - end - end - end - end - if level > 0 then - n = n + 1 t[n] = f_stop(depth-1) - end - end - - local tname = type(name) - - if tname == "string" then - if name == "return" then - t = { f_table_return() } - else - t = { f_table_name(name) } - end - elseif tname == "number" then - t = { f_table_entry(name) } - elseif tname == "boolean" then - if name then - t = { f_table_return() } - else - t = { f_table_direct() } - end - else - t = { f_table_name("t") } - end - - if root then - -- The dummy access will initialize a table that has a delayed initialization - -- using a metatable. (maybe explicitly test for metatable) - if getmetatable(root) then -- todo: make this an option, maybe even per subtable - local dummy = root._w_h_a_t_e_v_e_r_ - root._w_h_a_t_e_v_e_r_ = nil - end - -- Let's forget about empty tables. - if next(root) ~= nil then - local st = simple_table(root) - if st then - return t[1] .. f_fin_seq(st) -- todo: move up and in one go - else - do_serialize(root,name,1,0) - end - end - end - n = n + 1 - t[n] = f_table_finish() - return concat(t,"\n") -end - -table.serialize = serialize - -if setinspector then - setinspector("table",function(v) if type(v) == "table" then print(serialize(v,"table",{})) return true end end) -end diff --git a/tex/compat/lualibs/lualibs-util-tpl.lua b/tex/compat/lualibs/lualibs-util-tpl.lua deleted file mode 100644 index 468dd429c9856d1855e6dae01654e5f4314e074b..0000000000000000000000000000000000000000 --- a/tex/compat/lualibs/lualibs-util-tpl.lua +++ /dev/null @@ -1,213 +0,0 @@ -if not modules then modules = { } end modules ['util-tpl'] = { - version = 1.001, - comment = "companion to luat-lib.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- This is experimental code. Coming from dos and windows, I've always used %whatever% --- as template variables so let's stick to it. After all, it's easy to parse and stands --- out well. A double %% is turned into a regular %. - -utilities.templates = utilities.templates or { } -local templates = utilities.templates - -local trace_template = false trackers.register("templates.trace",function(v) trace_template = v end) -local report_template = logs.reporter("template") - -local tostring = tostring -local format, sub, byte = string.format, string.sub, string.byte -local P, C, R, Cs, Cc, Carg, lpegmatch, lpegpatterns = lpeg.P, lpeg.C, lpeg.R, lpeg.Cs, lpeg.Cc, lpeg.Carg, lpeg.match, lpeg.patterns - --- todo: make installable template.new - -local replacer - -local function replacekey(k,t,how,recursive) - local v = t[k] - if not v then - if trace_template then - report_template("unknown key %a",k) - end - return "" - else - v = tostring(v) - if trace_template then - report_template("setting key %a to value %a",k,v) - end - if recursive then - return lpegmatch(replacer,v,1,t,how,recursive) - else - return v - end - end -end - -local sqlescape = lpeg.replacer { - { "'", "''" }, - { "\\", "\\\\" }, - { "\r\n", "\\n" }, - { "\r", "\\n" }, - -- { "\t", "\\t" }, -} - -local sqlquoted = Cs(Cc("'") * sqlescape * Cc("'")) - -lpegpatterns.sqlescape = sqlescape -lpegpatterns.sqlquoted = sqlquoted - --- escapeset : \0\1\2\3\4\5\6\7\8\9\10\11\12\13\14\15\16\17\18\19\20\21\22\23\24\25\26\27\28\29\30\31\"\\\127 --- test string: [[1\0\31test23"\\]] .. string.char(19) .. "23" --- --- slow: --- --- local luaescape = lpeg.replacer { --- { '"', [[\"]] }, --- { '\\', [[\\]] }, --- { R("\0\9") * #R("09"), function(s) return "\\00" .. byte(s) end }, --- { R("\10\31") * #R("09"), function(s) return "\\0" .. byte(s) end }, --- { R("\0\31") , function(s) return "\\" .. byte(s) end }, --- } --- --- slightly faster: - --- local luaescape = Cs (( --- P('"' ) / [[\"]] + --- P('\\') / [[\\]] + --- Cc("\\00") * (R("\0\9") / byte) * #R("09") + --- Cc("\\0") * (R("\10\31") / byte) * #R("09") + --- Cc("\\") * (R("\0\31") / byte) + --- P(1) --- )^0) - ------ xmlescape = lpegpatterns.xmlescape ------ texescape = lpegpatterns.texescape -local luaescape = lpegpatterns.luaescape ------ sqlquoted = lpegpatterns.sqlquoted ------ luaquoted = lpegpatterns.luaquoted - -local escapers = { - lua = function(s) - -- return sub(format("%q",s),2,-2) - return lpegmatch(luaescape,s) - end, - sql = function(s) - return lpegmatch(sqlescape,s) - end, -} - -local quotedescapers = { - lua = function(s) - -- return lpegmatch(luaquoted,s) - return format("%q",s) - end, - sql = function(s) - return lpegmatch(sqlquoted,s) - end, -} - -local luaescaper = escapers.lua -local quotedluaescaper = quotedescapers.lua - -local function replacekeyunquoted(s,t,how,recurse) -- ".. \" " - if how == false then - return replacekey(s,t,how,recurse) - else - local escaper = how and escapers[how] or luaescaper - return escaper(replacekey(s,t,how,recurse)) - end -end - -local function replacekeyquoted(s,t,how,recurse) -- ".. \" " - if how == false then - return replacekey(s,t,how,recurse) - else - local escaper = how and quotedescapers[how] or quotedluaescaper - return escaper(replacekey(s,t,how,recurse)) - end -end - -local function replaceoptional(l,m,r,t,how,recurse) - local v = t[l] - return v and v ~= "" and lpegmatch(replacer,r,1,t,how or "lua",recurse or false) or "" -end - -local single = P("%") -- test %test% test : resolves test -local double = P("%%") -- test 10%% test : %% becomes % -local lquoted = P("%[") -- test '%[test]%' test : resolves to test with escaped "'s -local rquoted = P("]%") -- -local lquotedq = P("%(") -- test %(test)% test : resolves to 'test' with escaped "'s -local rquotedq = P(")%") -- - -local escape = double / '%%' -local nosingle = single / '' -local nodouble = double / '' -local nolquoted = lquoted / '' -local norquoted = rquoted / '' -local nolquotedq = lquotedq / '' -local norquotedq = rquotedq / '' - -local noloptional = P("%?") / '' -local noroptional = P("?%") / '' -local nomoptional = P(":") / '' - - -local args = Carg(1) * Carg(2) * Carg(3) -local key = nosingle * ((C((1-nosingle )^1) * args) / replacekey ) * nosingle -local quoted = nolquotedq * ((C((1-norquotedq )^1) * args) / replacekeyquoted ) * norquotedq -local unquoted = nolquoted * ((C((1-norquoted )^1) * args) / replacekeyunquoted) * norquoted -local optional = noloptional * ((C((1-nomoptional)^1) * nomoptional * C((1-noroptional)^1) * args) / replaceoptional) * noroptional -local any = P(1) - - replacer = Cs((unquoted + quoted + escape + optional + key + any)^0) - -local function replace(str,mapping,how,recurse) - if mapping and str then - return lpegmatch(replacer,str,1,mapping,how or "lua",recurse or false) or str - else - return str - end -end - --- print(replace("test '%[x]%' test",{ x = [[a 'x' a]] })) --- print(replace("test '%[x]%' test",{ x = true })) --- print(replace("test '%[x]%' test",{ x = [[a 'x' a]], y = "oeps" },'sql')) --- print(replace("test '%[x]%' test",{ x = [[a '%y%' a]], y = "oeps" },'sql',true)) --- print(replace([[test %[x]% test]],{ x = [[a "x" a]]})) --- print(replace([[test %(x)% test]],{ x = [[a "x" a]]})) --- print(replace([[convert %?x: -x "%x%" ?% %?y: -y "%y%" ?%]],{ x = "yes" })) - -templates.replace = replace - -function templates.replacer(str,how,recurse) -- reads nicer - return function(mapping) - return lpegmatch(replacer,str,1,mapping,how or "lua",recurse or false) or str - end -end - --- local cmd = templates.replacer([[foo %bar%]]) print(cmd { bar = "foo" }) - -function templates.load(filename,mapping,how,recurse) - local data = io.loaddata(filename) or "" - if mapping and next(mapping) then - return replace(data,mapping,how,recurse) - else - return data - end -end - -function templates.resolve(t,mapping,how,recurse) - if not mapping then - mapping = t - end - for k, v in next, t do - t[k] = replace(v,mapping,how,recurse) - end - return t -end - --- inspect(utilities.templates.replace("test %one% test", { one = "%two%", two = "two" })) --- inspect(utilities.templates.resolve({ one = "%two%", two = "two", three = "%three%" })) --- inspect(utilities.templates.replace("test %one% test", { one = "%two%", two = "two" },false,true)) --- inspect(utilities.templates.replace("test %one% test", { one = "%two%", two = "two" },false)) diff --git a/tex/compat/lualibs/lualibs.lua b/tex/compat/lualibs/lualibs.lua deleted file mode 100644 index 9810fd7b46ab4460845a1984ae1b9f3d0a6f8d70..0000000000000000000000000000000000000000 --- a/tex/compat/lualibs/lualibs.lua +++ /dev/null @@ -1,130 +0,0 @@ --- --- This is file `lualibs.lua', --- generated with the docstrip utility. --- --- The original source files were: --- --- lualibs.dtx (with options: `lualibs') --- This is a generated file. --- --- Copyright (C) 2009--2016 by --- PRAGMA ADE / ConTeXt Development Team --- The LuaLaTeX Dev Team --- --- See ConTeXt's mreadme.pdf for the license. --- --- This work consists of the main source file lualibs.dtx --- and the derived files lualibs.lua, lualibs-basic.lua, --- and lualibs-extended.lua. --- --- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -lualibs = lualibs or { } - -lualibs.module_info = { - name = "lualibs", - version = 2.4, - date = "2016-04-06", - description = "ConTeXt Lua standard libraries.", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL & Elie Roux & Philipp Gesang", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "See ConTeXt's mreadme.pdf for the license", -} - - -config = config or { } -config.lualibs = config.lualibs or { } - -if config.lualibs.prefer_merged ~= nil then - lualibs.prefer_merged = config.lualibs.prefer_merged -else - lualibs.prefer_merged = true -end - -if config.lualibs.load_extended ~= nil then - lualibs.load_extended = config.lualibs.load_extended -else - lualibs.load_extended = true -end - -if config.lualibs.verbose ~= nil then - config.lualibs.verbose = config.lualibs.verbose -else - config.lualibs.verbose = false -end - - -local dofile = dofile -local kpsefind_file = kpse.find_file -local stringformat = string.format -local texiowrite_nl = texio.write_nl - -local find_file, error, warn, info -do - local _error, _warn, _info - if luatexbase and luatexbase.provides_module then - _error, _warn, _info = luatexbase.provides_module(lualibs.module_info) - else - _error, _warn, _info = texiowrite_nl, texiowrite_nl, texiowrite_nl - end - - if lualibs.verbose then - error, warn, info = _error, _warn, _info - else - local dummylogger = function ( ) end - error, warn, info = _error, dummylogger, dummylogger - end - lualibs.error, lualibs.warn, lualibs.info = error, warn, info -end - -if luatexbase and luatexbase.find_file then - find_file = luatexbase.find_file -else - kpse.set_program_name"luatex" - find_file = kpsefind_file -end - - -local loadmodule = loadmodule or function (name, t) - if not t then t = "library" end - local filepath = find_file(name, "lua") - if not filepath or filepath == "" then - warn(stringformat("Could not locate %s “%s”.", t, name)) - return false - end - dofile(filepath) - return true -end - -lualibs.loadmodule = loadmodule - - -if lualibs.basic_loaded ~= true -or config.lualibs.force_reload == true -then - loadmodule"lualibs-basic.lua" - loadmodule"lualibs-compat.lua" --- restore stuff gone since v1.* -end - -if lualibs.load_extended == true -and lualibs.extended_loaded ~= true -or config.lualibs.force_reload == true -then - loadmodule"lualibs-extended.lua" -end - ---- This restores the default of loading everything should a package ---- have requested otherwise. Will be gone once there is a canonical ---- interface for parameterized loading of libraries. -config.lualibs.load_extended = true - --- vim:tw=71:sw=2:ts=2:expandtab - --- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --- --- End of File `lualibs.lua'. diff --git a/tex/compat/luaotfload/fontloader-2017-02-11.lua b/tex/compat/luaotfload/fontloader-2017-02-11.lua deleted file mode 100644 index f8f6f0658a24c5b900c70df03a5855ffcd57a80c..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/fontloader-2017-02-11.lua +++ /dev/null @@ -1,21726 +0,0 @@ ---[[info----------------------------------------------------------------------- - Luaotfload fontloader package - build 2017-02-11 18:16:05 by phg@phlegethon -------------------------------------------------------------------------------- - - © 2017 PRAGMA ADE / ConTeXt Development Team - - The code in this file is provided under the GPL v2.0 license. See the - file COPYING in the Luaotfload repository for details. - - Report bugs to github.com/lualatex/luaotfload - - This file has been assembled from components taken from Context. See - the Luaotfload documentation for details: - - $ texdoc luaotfload - $ man 1 luaotfload-tool - $ man 5 luaotfload.conf - - Included files: - - · fontloader-data-con.lua - · fontloader-basics-nod.lua - · fontloader-font-ini.lua - · fontloader-font-con.lua - · fontloader-fonts-enc.lua - · fontloader-font-cid.lua - · fontloader-font-map.lua - · fontloader-font-oti.lua - · fontloader-font-otr.lua - · fontloader-font-cff.lua - · fontloader-font-ttf.lua - · fontloader-font-dsp.lua - · fontloader-font-oup.lua - · fontloader-font-otl.lua - · fontloader-font-oto.lua - · fontloader-font-otj.lua - · fontloader-font-ota.lua - · fontloader-font-ots.lua - · fontloader-font-osd.lua - · fontloader-font-ocl.lua - · fontloader-font-otc.lua - · fontloader-font-onr.lua - · fontloader-font-one.lua - · fontloader-font-afk.lua - · fontloader-font-tfm.lua - · fontloader-font-lua.lua - · fontloader-font-def.lua - · fontloader-fonts-ext.lua - · fontloader-font-gbn.lua - ---info]]----------------------------------------------------------------------- - - -do --- [luaotfload, fontloader-2017-02-11.lua scope for “data-con” d8982c834ed9acc6193eee23067b9d5d] --- - -if not modules then modules={} end modules ['data-con']={ - version=1.100, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local format,lower,gsub=string.format,string.lower,string.gsub -local trace_cache=false trackers.register("resolvers.cache",function(v) trace_cache=v end) -local trace_containers=false trackers.register("resolvers.containers",function(v) trace_containers=v end) -local trace_storage=false trackers.register("resolvers.storage",function(v) trace_storage=v end) -containers=containers or {} -local containers=containers -containers.usecache=true -local report_containers=logs.reporter("resolvers","containers") -local allocated={} -local mt={ - __index=function(t,k) - if k=="writable" then - local writable=caches.getwritablepath(t.category,t.subcategory) or { "." } - t.writable=writable - return writable - elseif k=="readables" then - local readables=caches.getreadablepaths(t.category,t.subcategory) or { "." } - t.readables=readables - return readables - end - end, - __storage__=true -} -function containers.define(category,subcategory,version,enabled) - if category and subcategory then - local c=allocated[category] - if not c then - c={} - allocated[category]=c - end - local s=c[subcategory] - if not s then - s={ - category=category, - subcategory=subcategory, - storage={}, - enabled=enabled, - version=version or math.pi, - trace=false, - } - setmetatable(s,mt) - c[subcategory]=s - end - return s - end -end -function containers.is_usable(container,name) - return container.enabled and caches and caches.is_writable(container.writable,name) -end -function containers.is_valid(container,name) - if name and name~="" then - local storage=container.storage[name] - return storage and storage.cache_version==container.version - else - return false - end -end -function containers.read(container,name) - local storage=container.storage - local stored=storage[name] - if not stored and container.enabled and caches and containers.usecache then - stored=caches.loaddata(container.readables,name,container.writable) - if stored and stored.cache_version==container.version then - if trace_cache or trace_containers then - report_containers("action %a, category %a, name %a","load",container.subcategory,name) - end - else - stored=nil - end - storage[name]=stored - elseif stored then - if trace_cache or trace_containers then - report_containers("action %a, category %a, name %a","reuse",container.subcategory,name) - end - end - return stored -end -function containers.write(container,name,data) - if data then - data.cache_version=container.version - if container.enabled and caches then - local unique,shared=data.unique,data.shared - data.unique,data.shared=nil,nil - caches.savedata(container.writable,name,data) - if trace_cache or trace_containers then - report_containers("action %a, category %a, name %a","save",container.subcategory,name) - end - data.unique,data.shared=unique,shared - end - if trace_cache or trace_containers then - report_containers("action %a, category %a, name %a","store",container.subcategory,name) - end - container.storage[name]=data - end - return data -end -function containers.content(container,name) - return container.storage[name] -end -function containers.cleanname(name) - return (gsub(lower(name),"[^%w\128-\255]+","-")) -end - -end --- [luaotfload, fontloader-2017-02-11.lua scope for “data-con”] --- - - -do --- [luaotfload, fontloader-2017-02-11.lua scope for “basics-nod” 9288471b8395bfb683aba0ff3964d950] --- - -if not modules then modules={} end modules ['luatex-fonts-nod']={ - version=1.001, - comment="companion to luatex-fonts.lua", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -if context then - texio.write_nl("fatal error: this module is not for context") - os.exit() -end -if tex.attribute[0]~=0 then - texio.write_nl("log","!") - texio.write_nl("log","! Attribute 0 is reserved for ConTeXt's font feature management and has to be") - texio.write_nl("log","! set to zero. Also, some attributes in the range 1-255 are used for special") - texio.write_nl("log","! purposes so setting them at the TeX end might break the font handler.") - texio.write_nl("log","!") - tex.attribute[0]=0 -end -attributes=attributes or {} -attributes.unsetvalue=-0x7FFFFFFF -local numbers,last={},127 -attributes.private=attributes.private or function(name) - local number=numbers[name] - if not number then - if last<255 then - last=last+1 - end - number=last - numbers[name]=number - end - return number -end -nodes={} -nodes.pool={} -nodes.handlers={} -local nodecodes={} -local glyphcodes=node.subtypes("glyph") -local disccodes=node.subtypes("disc") -for k,v in next,node.types() do - v=string.gsub(v,"_","") - nodecodes[k]=v - nodecodes[v]=k -end -for i=0,#glyphcodes do - glyphcodes[glyphcodes[i]]=i -end -for i=0,#disccodes do - disccodes[disccodes[i]]=i -end -nodes.nodecodes=nodecodes -nodes.glyphcodes=glyphcodes -nodes.disccodes=disccodes -local flush_node=node.flush_node -local remove_node=node.remove -local new_node=node.new -local traverse_id=node.traverse_id -nodes.handlers.protectglyphs=node.protect_glyphs -nodes.handlers.unprotectglyphs=node.unprotect_glyphs -local math_code=nodecodes.math -local end_of_math=node.end_of_math -function node.end_of_math(n) - if n.id==math_code and n.subtype==1 then - return n - else - return end_of_math(n) - end -end -function nodes.remove(head,current,free_too) - local t=current - head,current=remove_node(head,current) - if t then - if free_too then - flush_node(t) - t=nil - else - t.next,t.prev=nil,nil - end - end - return head,current,t -end -function nodes.delete(head,current) - return nodes.remove(head,current,true) -end -function nodes.pool.kern(k) - local n=new_node("kern",1) - n.kern=k - return n -end -local getfield=node.getfield -local setfield=node.setfield -nodes.getfield=getfield -nodes.setfield=setfield -nodes.getattr=getfield -nodes.setattr=setfield -nodes.tostring=node.tostring or tostring -nodes.copy=node.copy -nodes.copy_node=node.copy -nodes.copy_list=node.copy_list -nodes.delete=node.delete -nodes.dimensions=node.dimensions -nodes.end_of_math=node.end_of_math -nodes.flush_list=node.flush_list -nodes.flush_node=node.flush_node -nodes.flush=node.flush_node -nodes.free=node.free -nodes.insert_after=node.insert_after -nodes.insert_before=node.insert_before -nodes.hpack=node.hpack -nodes.new=node.new -nodes.tail=node.tail -nodes.traverse=node.traverse -nodes.traverse_id=node.traverse_id -nodes.slide=node.slide -nodes.vpack=node.vpack -nodes.first_glyph=node.first_glyph -nodes.has_glyph=node.has_glyph or node.first_glyph -nodes.current_attr=node.current_attr -nodes.has_field=node.has_field -nodes.last_node=node.last_node -nodes.usedlist=node.usedlist -nodes.protrusion_skippable=node.protrusion_skippable -nodes.write=node.write -nodes.has_attribute=node.has_attribute -nodes.set_attribute=node.set_attribute -nodes.unset_attribute=node.unset_attribute -nodes.protect_glyphs=node.protect_glyphs -nodes.unprotect_glyphs=node.unprotect_glyphs -nodes.mlist_to_hlist=node.mlist_to_hlist -local direct=node.direct -local nuts={} -nodes.nuts=nuts -local tonode=direct.tonode -local tonut=direct.todirect -nodes.tonode=tonode -nodes.tonut=tonut -nuts.tonode=tonode -nuts.tonut=tonut -local getfield=direct.getfield -local setfield=direct.setfield -nuts.getfield=getfield -nuts.setfield=setfield -nuts.getnext=direct.getnext -nuts.setnext=direct.setnext -nuts.getprev=direct.getprev -nuts.setprev=direct.setprev -nuts.getboth=direct.getboth -nuts.setboth=direct.setboth -nuts.getid=direct.getid -nuts.getattr=direct.get_attribute or direct.has_attribute or getfield -nuts.setattr=setfield -nuts.getfont=direct.getfont -nuts.setfont=direct.setfont -nuts.getsubtype=direct.getsubtype -nuts.setsubtype=direct.setsubtype or function(n,s) setfield(n,"subtype",s) end -nuts.getchar=direct.getchar -nuts.setchar=direct.setchar -nuts.getdisc=direct.getdisc -nuts.setdisc=direct.setdisc -nuts.setlink=direct.setlink -nuts.getlist=direct.getlist -nuts.setlist=direct.setlist or function(n,l) setfield(n,"list",l) end -nuts.getleader=direct.getleader -nuts.setleader=direct.setleader or function(n,l) setfield(n,"leader",l) end -if not direct.is_glyph then - local getchar=direct.getchar - local getid=direct.getid - local getfont=direct.getfont - local glyph_code=nodes.nodecodes.glyph - function direct.is_glyph(n,f) - local id=getid(n) - if id==glyph_code then - if f and getfont(n)==f then - return getchar(n) - else - return false - end - else - return nil,id - end - end - function direct.is_char(n,f) - local id=getid(n) - if id==glyph_code then - if getsubtype(n)>=256 then - return false - elseif f and getfont(n)==f then - return getchar(n) - else - return false - end - else - return nil,id - end - end -end -nuts.ischar=direct.is_char -nuts.is_char=direct.is_char -nuts.isglyph=direct.is_glyph -nuts.is_glyph=direct.is_glyph -nuts.insert_before=direct.insert_before -nuts.insert_after=direct.insert_after -nuts.delete=direct.delete -nuts.copy=direct.copy -nuts.copy_node=direct.copy -nuts.copy_list=direct.copy_list -nuts.tail=direct.tail -nuts.flush_list=direct.flush_list -nuts.flush_node=direct.flush_node -nuts.flush=direct.flush -nuts.free=direct.free -nuts.remove=direct.remove -nuts.is_node=direct.is_node -nuts.end_of_math=direct.end_of_math -nuts.traverse=direct.traverse -nuts.traverse_id=direct.traverse_id -nuts.traverse_char=direct.traverse_char -nuts.ligaturing=direct.ligaturing -nuts.kerning=direct.kerning -nuts.getprop=nuts.getattr -nuts.setprop=nuts.setattr -local new_nut=direct.new -nuts.new=new_nut -nuts.pool={} -function nuts.pool.kern(k) - local n=new_nut("kern",1) - setfield(n,"kern",k) - return n -end -local propertydata=direct.get_properties_table() -nodes.properties={ data=propertydata } -direct.set_properties_mode(true,true) -function direct.set_properties_mode() end -nuts.getprop=function(n,k) - local p=propertydata[n] - if p then - return p[k] - end -end -nuts.setprop=function(n,k,v) - if v then - local p=propertydata[n] - if p then - p[k]=v - else - propertydata[n]={ [k]=v } - end - end -end -nodes.setprop=nodes.setproperty -nodes.getprop=nodes.getproperty - -end --- [luaotfload, fontloader-2017-02-11.lua scope for “basics-nod”] --- - - -do --- [luaotfload, fontloader-2017-02-11.lua scope for “font-ini” 10cb9a563a98e06ff79c35a8751e13dc] --- - -if not modules then modules={} end modules ['font-ini']={ - version=1.001, - comment="companion to font-ini.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local allocate=utilities.storage.allocate -fonts=fonts or {} -local fonts=fonts -fonts.hashes={ identifiers=allocate() } -fonts.tables=fonts.tables or {} -fonts.helpers=fonts.helpers or {} -fonts.tracers=fonts.tracers or {} -fonts.specifiers=fonts.specifiers or {} -fonts.analyzers={} -fonts.readers={} -fonts.definers={ methods={} } -fonts.loggers={ register=function() end } -fontloader.totable=fontloader.to_table - -end --- [luaotfload, fontloader-2017-02-11.lua scope for “font-ini”] --- - - -do --- [luaotfload, fontloader-2017-02-11.lua scope for “font-con” 7575a7b4e6d04816072945e27d7d0b33] --- - -if not modules then modules={} end modules ['font-con']={ - version=1.001, - comment="companion to font-ini.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local next,tostring,rawget=next,tostring,rawget -local format,match,lower,gsub,find=string.format,string.match,string.lower,string.gsub,string.find -local sort,insert,concat,sortedkeys,serialize,fastcopy=table.sort,table.insert,table.concat,table.sortedkeys,table.serialize,table.fastcopy -local derivetable=table.derive -local ioflush=io.flush -local trace_defining=false trackers.register("fonts.defining",function(v) trace_defining=v end) -local trace_scaling=false trackers.register("fonts.scaling",function(v) trace_scaling=v end) -local report_defining=logs.reporter("fonts","defining") -local fonts=fonts -local constructors=fonts.constructors or {} -fonts.constructors=constructors -local handlers=fonts.handlers or {} -fonts.handlers=handlers -local allocate=utilities.storage.allocate -local setmetatableindex=table.setmetatableindex -constructors.dontembed=allocate() -constructors.autocleanup=true -constructors.namemode="fullpath" -constructors.version=1.01 -constructors.cache=containers.define("fonts","constructors",constructors.version,false) -constructors.privateoffset=0xF0000 -constructors.cacheintex=true -local designsizes=allocate() -constructors.designsizes=designsizes -local loadedfonts=allocate() -constructors.loadedfonts=loadedfonts -local factors={ - pt=65536.0, - bp=65781.8, -} -function constructors.setfactor(f) - constructors.factor=factors[f or 'pt'] or factors.pt -end -constructors.setfactor() -function constructors.scaled(scaledpoints,designsize) - if scaledpoints<0 then - local factor=constructors.factor - if designsize then - if designsize>factor then - return (- scaledpoints/1000)*designsize - else - return (- scaledpoints/1000)*designsize*factor - end - else - return (- scaledpoints/1000)*10*factor - end - else - return scaledpoints - end -end -function constructors.cleanuptable(tfmdata) - if constructors.autocleanup and tfmdata.properties.virtualized then - for k,v in next,tfmdata.characters do - if v.commands then v.commands=nil end - end - end -end -function constructors.calculatescale(tfmdata,scaledpoints) - local parameters=tfmdata.parameters - if scaledpoints<0 then - scaledpoints=(- scaledpoints/1000)*(tfmdata.designsize or parameters.designsize) - end - return scaledpoints,scaledpoints/(parameters.units or 1000) -end -local unscaled={ - ScriptPercentScaleDown=true, - ScriptScriptPercentScaleDown=true, - RadicalDegreeBottomRaisePercent=true, - NoLimitSupFactor=true, - NoLimitSubFactor=true, -} -function constructors.assignmathparameters(target,original) - local mathparameters=original.mathparameters - if mathparameters and next(mathparameters) then - local targetparameters=target.parameters - local targetproperties=target.properties - local targetmathparameters={} - local factor=targetproperties.math_is_scaled and 1 or targetparameters.factor - for name,value in next,mathparameters do - if unscaled[name] then - targetmathparameters[name]=value - else - targetmathparameters[name]=value*factor - end - end - if not targetmathparameters.FractionDelimiterSize then - targetmathparameters.FractionDelimiterSize=1.01*targetparameters.size - end - if not mathparameters.FractionDelimiterDisplayStyleSize then - targetmathparameters.FractionDelimiterDisplayStyleSize=2.40*targetparameters.size - end - target.mathparameters=targetmathparameters - end -end -function constructors.beforecopyingcharacters(target,original) -end -function constructors.aftercopyingcharacters(target,original) -end -constructors.sharefonts=false -constructors.nofsharedfonts=0 -local sharednames={} -function constructors.trytosharefont(target,tfmdata) - if constructors.sharefonts then - local characters=target.characters - local n=1 - local t={ target.psname } - local u=sortedkeys(characters) - for i=1,#u do - local k=u[i] - n=n+1;t[n]=k - n=n+1;t[n]=characters[k].index or k - end - local h=md5.HEX(concat(t," ")) - local s=sharednames[h] - if s then - if trace_defining then - report_defining("font %a uses backend resources of font %a",target.fullname,s) - end - target.fullname=s - constructors.nofsharedfonts=constructors.nofsharedfonts+1 - target.properties.sharedwith=s - else - sharednames[h]=target.fullname - end - end -end -function constructors.enhanceparameters(parameters) - local xheight=parameters.x_height - local quad=parameters.quad - local space=parameters.space - local stretch=parameters.space_stretch - local shrink=parameters.space_shrink - local extra=parameters.extra_space - local slant=parameters.slant - parameters.xheight=xheight - parameters.spacestretch=stretch - parameters.spaceshrink=shrink - parameters.extraspace=extra - parameters.em=quad - parameters.ex=xheight - parameters.slantperpoint=slant - parameters.spacing={ - width=space, - stretch=stretch, - shrink=shrink, - extra=extra, - } -end -local function mathkerns(v,vdelta) - local k={} - for i=1,#v do - local entry=v[i] - local height=entry.height - local kern=entry.kern - k[i]={ - height=height and vdelta*height or 0, - kern=kern and vdelta*kern or 0, - } - end - return k -end -local psfake=0 -local function fixedpsname(psname,fallback) - local usedname=psname - if psname and psname~="" then - if find(psname," ") then - usedname=gsub(psname,"[%s]+","-") - else - end - elseif not fallback or fallback=="" then - psfake=psfake+1 - psname="fakename-"..psfake - else - psname=fallback - usedname=gsub(psname,"[^a-zA-Z0-9]+","-") - end - return usedname,psname~=usedname -end -function constructors.scale(tfmdata,specification) - local target={} - if tonumber(specification) then - specification={ size=specification } - end - target.specification=specification - local scaledpoints=specification.size - local relativeid=specification.relativeid - local properties=tfmdata.properties or {} - local goodies=tfmdata.goodies or {} - local resources=tfmdata.resources or {} - local descriptions=tfmdata.descriptions or {} - local characters=tfmdata.characters or {} - local changed=tfmdata.changed or {} - local shared=tfmdata.shared or {} - local parameters=tfmdata.parameters or {} - local mathparameters=tfmdata.mathparameters or {} - local targetcharacters={} - local targetdescriptions=derivetable(descriptions) - local targetparameters=derivetable(parameters) - local targetproperties=derivetable(properties) - local targetgoodies=goodies - target.characters=targetcharacters - target.descriptions=targetdescriptions - target.parameters=targetparameters - target.properties=targetproperties - target.goodies=targetgoodies - target.shared=shared - target.resources=resources - target.unscaled=tfmdata - local mathsize=tonumber(specification.mathsize) or 0 - local textsize=tonumber(specification.textsize) or scaledpoints - local forcedsize=tonumber(parameters.mathsize ) or 0 - local extrafactor=tonumber(specification.factor ) or 1 - if (mathsize==2 or forcedsize==2) and parameters.scriptpercentage then - scaledpoints=parameters.scriptpercentage*textsize/100 - elseif (mathsize==3 or forcedsize==3) and parameters.scriptscriptpercentage then - scaledpoints=parameters.scriptscriptpercentage*textsize/100 - elseif forcedsize>1000 then - scaledpoints=forcedsize - end - targetparameters.mathsize=mathsize - targetparameters.textsize=textsize - targetparameters.forcedsize=forcedsize - targetparameters.extrafactor=extrafactor - local tounicode=fonts.mappings.tounicode - local defaultwidth=resources.defaultwidth or 0 - local defaultheight=resources.defaultheight or 0 - local defaultdepth=resources.defaultdepth or 0 - local units=parameters.units or 1000 - if target.fonts then - target.fonts=fastcopy(target.fonts) - end - targetproperties.language=properties.language or "dflt" - targetproperties.script=properties.script or "dflt" - targetproperties.mode=properties.mode or "base" - local askedscaledpoints=scaledpoints - local scaledpoints,delta=constructors.calculatescale(tfmdata,scaledpoints,nil,specification) - local hdelta=delta - local vdelta=delta - target.designsize=parameters.designsize - target.units=units - target.units_per_em=units - local direction=properties.direction or tfmdata.direction or 0 - target.direction=direction - properties.direction=direction - target.size=scaledpoints - target.encodingbytes=properties.encodingbytes or 1 - target.embedding=properties.embedding or "subset" - target.tounicode=1 - target.cidinfo=properties.cidinfo - target.format=properties.format - target.cache=constructors.cacheintex and "yes" or "renew" - local fontname=properties.fontname or tfmdata.fontname - local fullname=properties.fullname or tfmdata.fullname - local filename=properties.filename or tfmdata.filename - local psname=properties.psname or tfmdata.psname - local name=properties.name or tfmdata.name - local psname,psfixed=fixedpsname(psname,fontname or fullname or file.nameonly(filename)) - target.fontname=fontname - target.fullname=fullname - target.filename=filename - target.psname=psname - target.name=name - properties.fontname=fontname - properties.fullname=fullname - properties.filename=filename - properties.psname=psname - properties.name=name - local expansion=parameters.expansion - if expansion then - target.stretch=expansion.stretch - target.shrink=expansion.shrink - target.step=expansion.step - target.auto_expand=expansion.auto - end - local protrusion=parameters.protrusion - if protrusion then - target.auto_protrude=protrusion.auto - end - local extendfactor=parameters.extendfactor or 0 - if extendfactor~=0 and extendfactor~=1 then - hdelta=hdelta*extendfactor - target.extend=extendfactor*1000 - else - target.extend=1000 - end - local slantfactor=parameters.slantfactor or 0 - if slantfactor~=0 then - target.slant=slantfactor*1000 - else - target.slant=0 - end - targetparameters.factor=delta - targetparameters.hfactor=hdelta - targetparameters.vfactor=vdelta - targetparameters.size=scaledpoints - targetparameters.units=units - targetparameters.scaledpoints=askedscaledpoints - local isvirtual=properties.virtualized or tfmdata.type=="virtual" - local hasquality=target.auto_expand or target.auto_protrude - local hasitalics=properties.hasitalics - local autoitalicamount=properties.autoitalicamount - local stackmath=not properties.nostackmath - local nonames=properties.noglyphnames - local haskerns=properties.haskerns or properties.mode=="base" - local hasligatures=properties.hasligatures or properties.mode=="base" - local realdimensions=properties.realdimensions - local writingmode=properties.writingmode or "horizontal" - local identity=properties.identity or "horizontal" - if changed and not next(changed) then - changed=false - end - target.type=isvirtual and "virtual" or "real" - target.writingmode=writingmode=="vertical" and "vertical" or "horizontal" - target.identity=identity=="vertical" and "vertical" or "horizontal" - target.postprocessors=tfmdata.postprocessors - local targetslant=(parameters.slant or parameters[1] or 0)*factors.pt - local targetspace=(parameters.space or parameters[2] or 0)*hdelta - local targetspace_stretch=(parameters.space_stretch or parameters[3] or 0)*hdelta - local targetspace_shrink=(parameters.space_shrink or parameters[4] or 0)*hdelta - local targetx_height=(parameters.x_height or parameters[5] or 0)*vdelta - local targetquad=(parameters.quad or parameters[6] or 0)*hdelta - local targetextra_space=(parameters.extra_space or parameters[7] or 0)*hdelta - targetparameters.slant=targetslant - targetparameters.space=targetspace - targetparameters.space_stretch=targetspace_stretch - targetparameters.space_shrink=targetspace_shrink - targetparameters.x_height=targetx_height - targetparameters.quad=targetquad - targetparameters.extra_space=targetextra_space - local ascender=parameters.ascender - if ascender then - targetparameters.ascender=delta*ascender - end - local descender=parameters.descender - if descender then - targetparameters.descender=delta*descender - end - constructors.enhanceparameters(targetparameters) - local protrusionfactor=(targetquad~=0 and 1000/targetquad) or 0 - local scaledwidth=defaultwidth*hdelta - local scaledheight=defaultheight*vdelta - local scaleddepth=defaultdepth*vdelta - local hasmath=(properties.hasmath or next(mathparameters)) and true - if hasmath then - constructors.assignmathparameters(target,tfmdata) - properties.hasmath=true - target.nomath=false - target.MathConstants=target.mathparameters - else - properties.hasmath=false - target.nomath=true - target.mathparameters=nil - end - if hasmath then - local mathitalics=properties.mathitalics - if mathitalics==false then - if trace_defining then - report_defining("%s italics %s for font %a, fullname %a, filename %a","math",hasitalics and "ignored" or "disabled",name,fullname,filename) - end - hasitalics=false - autoitalicamount=false - end - else - local textitalics=properties.textitalics - if textitalics==false then - if trace_defining then - report_defining("%s italics %s for font %a, fullname %a, filename %a","text",hasitalics and "ignored" or "disabled",name,fullname,filename) - end - hasitalics=false - autoitalicamount=false - end - end - if trace_defining then - report_defining("defining tfm, name %a, fullname %a, filename %a, %spsname %a, hscale %a, vscale %a, math %a, italics %a", - name,fullname,filename,psfixed and "(fixed) " or "",psname,hdelta,vdelta, - hasmath and "enabled" or "disabled",hasitalics and "enabled" or "disabled") - end - constructors.beforecopyingcharacters(target,tfmdata) - local sharedkerns={} - for unicode,character in next,characters do - local chr,description,index - if changed then - local c=changed[unicode] - if c then - description=descriptions[c] or descriptions[unicode] or character - character=characters[c] or character - index=description.index or c - else - description=descriptions[unicode] or character - index=description.index or unicode - end - else - description=descriptions[unicode] or character - index=description.index or unicode - end - local width=description.width - local height=description.height - local depth=description.depth - if realdimensions then - if not height or height==0 then - local bb=description.boundingbox - local ht=bb[4] - if ht~=0 then - height=ht - end - if not depth or depth==0 then - local dp=-bb[2] - if dp~=0 then - depth=dp - end - end - elseif not depth or depth==0 then - local dp=-description.boundingbox[2] - if dp~=0 then - depth=dp - end - end - end - if width then width=hdelta*width else width=scaledwidth end - if height then height=vdelta*height else height=scaledheight end - if depth and depth~=0 then - depth=delta*depth - if nonames then - chr={ - index=index, - height=height, - depth=depth, - width=width, - } - else - chr={ - name=description.name, - index=index, - height=height, - depth=depth, - width=width, - } - end - else - if nonames then - chr={ - index=index, - height=height, - width=width, - } - else - chr={ - name=description.name, - index=index, - height=height, - width=width, - } - end - end - local isunicode=description.unicode - if isunicode then - chr.unicode=isunicode - chr.tounicode=tounicode(isunicode) - end - if hasquality then - local ve=character.expansion_factor - if ve then - chr.expansion_factor=ve*1000 - end - local vl=character.left_protruding - if vl then - chr.left_protruding=protrusionfactor*width*vl - end - local vr=character.right_protruding - if vr then - chr.right_protruding=protrusionfactor*width*vr - end - end - if hasmath then - local vn=character.next - if vn then - chr.next=vn - else - local vv=character.vert_variants - if vv then - local t={} - for i=1,#vv do - local vvi=vv[i] - t[i]={ - ["start"]=(vvi["start"] or 0)*vdelta, - ["end"]=(vvi["end"] or 0)*vdelta, - ["advance"]=(vvi["advance"] or 0)*vdelta, - ["extender"]=vvi["extender"], - ["glyph"]=vvi["glyph"], - } - end - chr.vert_variants=t - else - local hv=character.horiz_variants - if hv then - local t={} - for i=1,#hv do - local hvi=hv[i] - t[i]={ - ["start"]=(hvi["start"] or 0)*hdelta, - ["end"]=(hvi["end"] or 0)*hdelta, - ["advance"]=(hvi["advance"] or 0)*hdelta, - ["extender"]=hvi["extender"], - ["glyph"]=hvi["glyph"], - } - end - chr.horiz_variants=t - end - end - end - local vi=character.vert_italic - if vi and vi~=0 then - chr.vert_italic=vi*hdelta - end - local va=character.accent - if va then - chr.top_accent=vdelta*va - end - if stackmath then - local mk=character.mathkerns - if mk then - local tr,tl,br,bl=mk.topright,mk.topleft,mk.bottomright,mk.bottomleft - chr.mathkern={ - top_right=tr and mathkerns(tr,vdelta) or nil, - top_left=tl and mathkerns(tl,vdelta) or nil, - bottom_right=br and mathkerns(br,vdelta) or nil, - bottom_left=bl and mathkerns(bl,vdelta) or nil, - } - end - end - if hasitalics then - local vi=character.italic - if vi and vi~=0 then - chr.italic=vi*hdelta - end - end - elseif autoitalicamount then - local vi=description.italic - if not vi then - local bb=description.boundingbox - if bb then - local vi=bb[3]-description.width+autoitalicamount - if vi>0 then - chr.italic=vi*hdelta - end - else - end - elseif vi~=0 then - chr.italic=vi*hdelta - end - elseif hasitalics then - local vi=character.italic - if vi and vi~=0 then - chr.italic=vi*hdelta - end - end - if haskerns then - local vk=character.kerns - if vk then - local s=sharedkerns[vk] - if not s then - s={} - for k,v in next,vk do s[k]=v*hdelta end - sharedkerns[vk]=s - end - chr.kerns=s - end - end - if hasligatures then - local vl=character.ligatures - if vl then - if true then - chr.ligatures=vl - else - local tt={} - for i,l in next,vl do - tt[i]=l - end - chr.ligatures=tt - end - end - end - if isvirtual then - local vc=character.commands - if vc then - local ok=false - for i=1,#vc do - local key=vc[i][1] - if key=="right" or key=="down" then - ok=true - break - end - end - if ok then - local tt={} - for i=1,#vc do - local ivc=vc[i] - local key=ivc[1] - if key=="right" then - tt[i]={ key,ivc[2]*hdelta } - elseif key=="down" then - tt[i]={ key,ivc[2]*vdelta } - elseif key=="rule" then - tt[i]={ key,ivc[2]*vdelta,ivc[3]*hdelta } - else - tt[i]=ivc - end - end - chr.commands=tt - else - chr.commands=vc - end - chr.index=nil - end - end - targetcharacters[unicode]=chr - end - properties.setitalics=hasitalics - constructors.aftercopyingcharacters(target,tfmdata) - constructors.trytosharefont(target,tfmdata) - return target -end -function constructors.finalize(tfmdata) - if tfmdata.properties and tfmdata.properties.finalized then - return - end - if not tfmdata.characters then - return nil - end - if not tfmdata.goodies then - tfmdata.goodies={} - end - local parameters=tfmdata.parameters - if not parameters then - return nil - end - if not parameters.expansion then - parameters.expansion={ - stretch=tfmdata.stretch or 0, - shrink=tfmdata.shrink or 0, - step=tfmdata.step or 0, - auto=tfmdata.auto_expand or false, - } - end - if not parameters.protrusion then - parameters.protrusion={ - auto=auto_protrude - } - end - if not parameters.size then - parameters.size=tfmdata.size - end - if not parameters.extendfactor then - parameters.extendfactor=tfmdata.extend or 0 - end - if not parameters.slantfactor then - parameters.slantfactor=tfmdata.slant or 0 - end - local designsize=parameters.designsize - if designsize then - parameters.minsize=tfmdata.minsize or designsize - parameters.maxsize=tfmdata.maxsize or designsize - else - designsize=factors.pt*10 - parameters.designsize=designsize - parameters.minsize=designsize - parameters.maxsize=designsize - end - parameters.minsize=tfmdata.minsize or parameters.designsize - parameters.maxsize=tfmdata.maxsize or parameters.designsize - if not parameters.units then - parameters.units=tfmdata.units or tfmdata.units_per_em or 1000 - end - if not tfmdata.descriptions then - local descriptions={} - setmetatableindex(descriptions,function(t,k) local v={} t[k]=v return v end) - tfmdata.descriptions=descriptions - end - local properties=tfmdata.properties - if not properties then - properties={} - tfmdata.properties=properties - end - if not properties.virtualized then - properties.virtualized=tfmdata.type=="virtual" - end - if not tfmdata.properties then - tfmdata.properties={ - fontname=tfmdata.fontname, - filename=tfmdata.filename, - fullname=tfmdata.fullname, - name=tfmdata.name, - psname=tfmdata.psname, - encodingbytes=tfmdata.encodingbytes or 1, - embedding=tfmdata.embedding or "subset", - tounicode=tfmdata.tounicode or 1, - cidinfo=tfmdata.cidinfo or nil, - format=tfmdata.format or "type1", - direction=tfmdata.direction or 0, - writingmode=tfmdata.writingmode or "horizontal", - identity=tfmdata.identity or "horizontal", - } - end - if not tfmdata.resources then - tfmdata.resources={} - end - if not tfmdata.shared then - tfmdata.shared={} - end - if not properties.hasmath then - properties.hasmath=not tfmdata.nomath - end - tfmdata.MathConstants=nil - tfmdata.postprocessors=nil - tfmdata.fontname=nil - tfmdata.filename=nil - tfmdata.fullname=nil - tfmdata.name=nil - tfmdata.psname=nil - tfmdata.encodingbytes=nil - tfmdata.embedding=nil - tfmdata.tounicode=nil - tfmdata.cidinfo=nil - tfmdata.format=nil - tfmdata.direction=nil - tfmdata.type=nil - tfmdata.nomath=nil - tfmdata.designsize=nil - tfmdata.size=nil - tfmdata.stretch=nil - tfmdata.shrink=nil - tfmdata.step=nil - tfmdata.auto_expand=nil - tfmdata.auto_protrude=nil - tfmdata.extend=nil - tfmdata.slant=nil - tfmdata.units=nil - tfmdata.units_per_em=nil - tfmdata.cache=nil - properties.finalized=true - return tfmdata -end -local hashmethods={} -constructors.hashmethods=hashmethods -function constructors.hashfeatures(specification) - local features=specification.features - if features then - local t,tn={},0 - for category,list in next,features do - if next(list) then - local hasher=hashmethods[category] - if hasher then - local hash=hasher(list) - if hash then - tn=tn+1 - t[tn]=category..":"..hash - end - end - end - end - if tn>0 then - return concat(t," & ") - end - end - return "unknown" -end -hashmethods.normal=function(list) - local s={} - local n=0 - for k,v in next,list do - if not k then - elseif k=="number" or k=="features" then - else - n=n+1 - s[n]=k..'='..tostring(v) - end - end - if n>0 then - sort(s) - return concat(s,"+") - end -end -function constructors.hashinstance(specification,force) - local hash,size,fallbacks=specification.hash,specification.size,specification.fallbacks - if force or not hash then - hash=constructors.hashfeatures(specification) - specification.hash=hash - end - if size<1000 and designsizes[hash] then - size=math.round(constructors.scaled(size,designsizes[hash])) - specification.size=size - end - if fallbacks then - return hash..' @ '..tostring(size)..' @ '..fallbacks - else - return hash..' @ '..tostring(size) - end -end -function constructors.setname(tfmdata,specification) - if constructors.namemode=="specification" then - local specname=specification.specification - if specname then - tfmdata.properties.name=specname - if trace_defining then - report_otf("overloaded fontname %a",specname) - end - end - end -end -function constructors.checkedfilename(data) - local foundfilename=data.foundfilename - if not foundfilename then - local askedfilename=data.filename or "" - if askedfilename~="" then - askedfilename=resolvers.resolve(askedfilename) - foundfilename=resolvers.findbinfile(askedfilename,"") or "" - if foundfilename=="" then - report_defining("source file %a is not found",askedfilename) - foundfilename=resolvers.findbinfile(file.basename(askedfilename),"") or "" - if foundfilename~="" then - report_defining("using source file %a due to cache mismatch",foundfilename) - end - end - end - data.foundfilename=foundfilename - end - return foundfilename -end -local formats=allocate() -fonts.formats=formats -setmetatableindex(formats,function(t,k) - local l=lower(k) - if rawget(t,k) then - t[k]=l - return l - end - return rawget(t,file.suffix(l)) -end) -do - local function setindeed(mode,source,target,group,name,position) - local action=source[mode] - if not action then - return - end - local t=target[mode] - if not t then - report_defining("fatal error in setting feature %a, group %a, mode %a",name,group,mode) - os.exit() - elseif position then - insert(t,position,{ name=name,action=action }) - else - for i=1,#t do - local ti=t[i] - if ti.name==name then - ti.action=action - return - end - end - insert(t,{ name=name,action=action }) - end - end - local function set(group,name,target,source) - target=target[group] - if not target then - report_defining("fatal target error in setting feature %a, group %a",name,group) - os.exit() - end - local source=source[group] - if not source then - report_defining("fatal source error in setting feature %a, group %a",name,group) - os.exit() - end - local position=source.position - setindeed("node",source,target,group,name,position) - setindeed("base",source,target,group,name,position) - setindeed("plug",source,target,group,name,position) - end - local function register(where,specification) - local name=specification.name - if name and name~="" then - local default=specification.default - local description=specification.description - local initializers=specification.initializers - local processors=specification.processors - local manipulators=specification.manipulators - local modechecker=specification.modechecker - if default then - where.defaults[name]=default - end - if description and description~="" then - where.descriptions[name]=description - end - if initializers then - set('initializers',name,where,specification) - end - if processors then - set('processors',name,where,specification) - end - if manipulators then - set('manipulators',name,where,specification) - end - if modechecker then - where.modechecker=modechecker - end - end - end - constructors.registerfeature=register - function constructors.getfeatureaction(what,where,mode,name) - what=handlers[what].features - if what then - where=what[where] - if where then - mode=where[mode] - if mode then - for i=1,#mode do - local m=mode[i] - if m.name==name then - return m.action - end - end - end - end - end - end - local newfeatures={} - constructors.newfeatures=newfeatures - constructors.features=newfeatures - local function setnewfeatures(what) - local handler=handlers[what] - local features=handler.features - if not features then - local tables=handler.tables - local statistics=handler.statistics - features=allocate { - defaults={}, - descriptions=tables and tables.features or {}, - used=statistics and statistics.usedfeatures or {}, - initializers={ base={},node={},plug={} }, - processors={ base={},node={},plug={} }, - manipulators={ base={},node={},plug={} }, - } - features.register=function(specification) return register(features,specification) end - handler.features=features - end - return features - end - setmetatable(newfeatures,{ - __call=function(t,k) local v=t[k] return v end, - __index=function(t,k) local v=setnewfeatures(k) t[k]=v return v end, - }) -end -do - local newhandler={} - constructors.handlers=newhandler - constructors.newhandler=newhandler - local function setnewhandler(what) - local handler=handlers[what] - if not handler then - handler={} - handlers[what]=handler - end - return handler - end - setmetatable(newhandler,{ - __call=function(t,k) local v=t[k] return v end, - __index=function(t,k) local v=setnewhandler(k) t[k]=v return v end, - }) -end -do - local newenhancer={} - constructors.enhancers=newenhancer - constructors.newenhancer=newenhancer - local function setnewenhancer(format) - local handler=handlers[format] - local enhancers=handler.enhancers - if not enhancers then - local actions=allocate() - local before=allocate() - local after=allocate() - local order=allocate() - local patches={ before=before,after=after } - local trace=false - local report=logs.reporter("fonts",format.." enhancing") - trackers.register(format..".loading",function(v) trace=v end) - local function enhance(name,data,filename,raw) - local enhancer=actions[name] - if enhancer then - if trace then - report("apply enhancement %a to file %a",name,filename) - ioflush() - end - enhancer(data,filename,raw) - else - end - end - local function apply(data,filename,raw) - local basename=file.basename(lower(filename)) - if trace then - report("%s enhancing file %a","start",filename) - end - ioflush() - for e=1,#order do - local enhancer=order[e] - local b=before[enhancer] - if b then - for pattern,action in next,b do - if find(basename,pattern) then - action(data,filename,raw) - end - end - end - enhance(enhancer,data,filename,raw) - local a=after[enhancer] - if a then - for pattern,action in next,a do - if find(basename,pattern) then - action(data,filename,raw) - end - end - end - ioflush() - end - if trace then - report("%s enhancing file %a","stop",filename) - end - ioflush() - end - local function register(what,action) - if action then - if actions[what] then - else - order[#order+1]=what - end - actions[what]=action - else - report("bad enhancer %a",what) - end - end - local function patch(what,where,pattern,action) - local pw=patches[what] - if pw then - local ww=pw[where] - if ww then - ww[pattern]=action - else - pw[where]={ [pattern]=action} - end - end - end - enhancers={ - register=register, - apply=apply, - patch=patch, - patches={ register=patch }, - } - handler.enhancers=enhancers - end - return enhancers - end - setmetatable(newenhancer,{ - __call=function(t,k) local v=t[k] return v end, - __index=function(t,k) local v=setnewenhancer(k) t[k]=v return v end, - }) -end -function constructors.checkedfeatures(what,features) - local defaults=handlers[what].features.defaults - if features and next(features) then - features=fastcopy(features) - for key,value in next,defaults do - if features[key]==nil then - features[key]=value - end - end - return features - else - return fastcopy(defaults) - end -end -function constructors.initializefeatures(what,tfmdata,features,trace,report) - if features and next(features) then - local properties=tfmdata.properties or {} - local whathandler=handlers[what] - local whatfeatures=whathandler.features - local whatmodechecker=whatfeatures.modechecker - local mode=properties.mode or (whatmodechecker and whatmodechecker(tfmdata,features,features.mode)) or features.mode or "base" - properties.mode=mode - features.mode=mode - local done={} - while true do - local redo=false - local initializers=whatfeatures.initializers[mode] - if initializers then - for i=1,#initializers do - local step=initializers[i] - local feature=step.name - local value=features[feature] - if not value then - elseif done[feature] then - else - local action=step.action - if trace then - report("initializing feature %a to %a for mode %a for font %a",feature, - value,mode,tfmdata.properties.fullname) - end - action(tfmdata,value,features) - if mode~=properties.mode or mode~=features.mode then - if whatmodechecker then - properties.mode=whatmodechecker(tfmdata,features,properties.mode) - features.mode=properties.mode - end - if mode~=properties.mode then - mode=properties.mode - redo=true - end - end - done[feature]=true - end - if redo then - break - end - end - if not redo then - break - end - else - break - end - end - properties.mode=mode - return true - else - return false - end -end -function constructors.collectprocessors(what,tfmdata,features,trace,report) - local processes,nofprocesses={},0 - if features and next(features) then - local properties=tfmdata.properties - local whathandler=handlers[what] - local whatfeatures=whathandler.features - local whatprocessors=whatfeatures.processors - local mode=properties.mode - local processors=whatprocessors[mode] - if processors then - for i=1,#processors do - local step=processors[i] - local feature=step.name - if features[feature] then - local action=step.action - if trace then - report("installing feature processor %a for mode %a for font %a",feature,mode,tfmdata.properties.fullname) - end - if action then - nofprocesses=nofprocesses+1 - processes[nofprocesses]=action - end - end - end - elseif trace then - report("no feature processors for mode %a for font %a",mode,properties.fullname) - end - end - return processes -end -function constructors.applymanipulators(what,tfmdata,features,trace,report) - if features and next(features) then - local properties=tfmdata.properties - local whathandler=handlers[what] - local whatfeatures=whathandler.features - local whatmanipulators=whatfeatures.manipulators - local mode=properties.mode - local manipulators=whatmanipulators[mode] - if manipulators then - for i=1,#manipulators do - local step=manipulators[i] - local feature=step.name - local value=features[feature] - if value then - local action=step.action - if trace then - report("applying feature manipulator %a for mode %a for font %a",feature,mode,properties.fullname) - end - if action then - action(tfmdata,feature,value) - end - end - end - end - end -end -function constructors.addcoreunicodes(unicodes) - if not unicodes then - unicodes={} - end - unicodes.space=0x0020 - unicodes.hyphen=0x002D - unicodes.zwj=0x200D - unicodes.zwnj=0x200C - return unicodes -end - -end --- [luaotfload, fontloader-2017-02-11.lua scope for “font-con”] --- - - -do --- [luaotfload, fontloader-2017-02-11.lua scope for “fonts-enc” a7ace7c1969cd64a5ca9888838f3edb6] --- - -if not modules then modules={} end modules ['luatex-font-enc']={ - version=1.001, - comment="companion to luatex-*.tex", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -if context then - texio.write_nl("fatal error: this module is not for context") - os.exit() -end -local fonts=fonts -local encodings={} -fonts.encodings=encodings -encodings.agl={} -encodings.known={} -setmetatable(encodings.agl,{ __index=function(t,k) - if k=="unicodes" then - texio.write(" <loading (extended) adobe glyph list>") - local unicodes=dofile(resolvers.findfile("font-age.lua")) - encodings.agl={ unicodes=unicodes } - return unicodes - else - return nil - end -end }) -encodings.cache=containers.define("fonts","enc",encodings.version,true) -function encodings.load(filename) - local name=file.removesuffix(filename) - local data=containers.read(encodings.cache,name) - if data then - return data - end - local vector,tag,hash,unicodes={},"",{},{} - local foundname=resolvers.findfile(filename,'enc') - if foundname and foundname~="" then - local ok,encoding,size=resolvers.loadbinfile(foundname) - if ok and encoding then - encoding=string.gsub(encoding,"%%(.-)\n","") - local unicoding=encodings.agl.unicodes - local tag,vec=string.match(encoding,"/(%w+)%s*%[(.*)%]%s*def") - local i=0 - for ch in string.gmatch(vec,"/([%a%d%.]+)") do - if ch~=".notdef" then - vector[i]=ch - if not hash[ch] then - hash[ch]=i - else - end - local u=unicoding[ch] - if u then - unicodes[u]=i - end - end - i=i+1 - end - end - end - local data={ - name=name, - tag=tag, - vector=vector, - hash=hash, - unicodes=unicodes - } - return containers.write(encodings.cache,name,data) -end - -end --- [luaotfload, fontloader-2017-02-11.lua scope for “fonts-enc”] --- - - -do --- [luaotfload, fontloader-2017-02-11.lua scope for “font-cid” 52421d1fdaa07ec4b1d936c6ff5079be] --- - -if not modules then modules={} end modules ['font-cid']={ - version=1.001, - comment="companion to font-otf.lua (cidmaps)", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local format,match,lower=string.format,string.match,string.lower -local tonumber=tonumber -local P,S,R,C,V,lpegmatch=lpeg.P,lpeg.S,lpeg.R,lpeg.C,lpeg.V,lpeg.match -local fonts,logs,trackers=fonts,logs,trackers -local trace_loading=false trackers.register("otf.loading",function(v) trace_loading=v end) -local report_otf=logs.reporter("fonts","otf loading") -local cid={} -fonts.cid=cid -local cidmap={} -local cidmax=10 -local number=C(R("09","af","AF")^1) -local space=S(" \n\r\t") -local spaces=space^0 -local period=P(".") -local periods=period*period -local name=P("/")*C((1-space)^1) -local unicodes,names={},{} -local function do_one(a,b) - unicodes[tonumber(a)]=tonumber(b,16) -end -local function do_range(a,b,c) - c=tonumber(c,16) - for i=tonumber(a),tonumber(b) do - unicodes[i]=c - c=c+1 - end -end -local function do_name(a,b) - names[tonumber(a)]=b -end -local grammar=P { "start", - start=number*spaces*number*V("series"), - series=(spaces*(V("one")+V("range")+V("named")))^1, - one=(number*spaces*number)/do_one, - range=(number*periods*number*spaces*number)/do_range, - named=(number*spaces*name)/do_name -} -local function loadcidfile(filename) - local data=io.loaddata(filename) - if data then - unicodes,names={},{} - lpegmatch(grammar,data) - local supplement,registry,ordering=match(filename,"^(.-)%-(.-)%-()%.(.-)$") - return { - supplement=supplement, - registry=registry, - ordering=ordering, - filename=filename, - unicodes=unicodes, - names=names, - } - end -end -cid.loadfile=loadcidfile -local template="%s-%s-%s.cidmap" -local function locate(registry,ordering,supplement) - local filename=format(template,registry,ordering,supplement) - local hashname=lower(filename) - local found=cidmap[hashname] - if not found then - if trace_loading then - report_otf("checking cidmap, registry %a, ordering %a, supplement %a, filename %a",registry,ordering,supplement,filename) - end - local fullname=resolvers.findfile(filename,'cid') or "" - if fullname~="" then - found=loadcidfile(fullname) - if found then - if trace_loading then - report_otf("using cidmap file %a",filename) - end - cidmap[hashname]=found - found.usedname=file.basename(filename) - end - end - end - return found -end -function cid.getmap(specification) - if not specification then - report_otf("invalid cidinfo specification, table expected") - return - end - local registry=specification.registry - local ordering=specification.ordering - local supplement=specification.supplement - local filename=format(registry,ordering,supplement) - local lowername=lower(filename) - local found=cidmap[lowername] - if found then - return found - end - if ordering=="Identity" then - local found={ - supplement=supplement, - registry=registry, - ordering=ordering, - filename=filename, - unicodes={}, - names={}, - } - cidmap[lowername]=found - return found - end - if trace_loading then - report_otf("cidmap needed, registry %a, ordering %a, supplement %a",registry,ordering,supplement) - end - found=locate(registry,ordering,supplement) - if not found then - local supnum=tonumber(supplement) - local cidnum=nil - if supnum<cidmax then - for s=supnum+1,cidmax do - local c=locate(registry,ordering,s) - if c then - found,cidnum=c,s - break - end - end - end - if not found and supnum>0 then - for s=supnum-1,0,-1 do - local c=locate(registry,ordering,s) - if c then - found,cidnum=c,s - break - end - end - end - registry=lower(registry) - ordering=lower(ordering) - if found and cidnum>0 then - for s=0,cidnum-1 do - local filename=format(template,registry,ordering,s) - if not cidmap[filename] then - cidmap[filename]=found - end - end - end - end - return found -end - -end --- [luaotfload, fontloader-2017-02-11.lua scope for “font-cid”] --- - - -do --- [luaotfload, fontloader-2017-02-11.lua scope for “font-map” 8708bde7467785c4d3b7afdaf2f9333a] --- - -if not modules then modules={} end modules ['font-map']={ - version=1.001, - comment="companion to font-ini.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local tonumber,next,type=tonumber,next,type -local match,format,find,concat,gsub,lower=string.match,string.format,string.find,table.concat,string.gsub,string.lower -local P,R,S,C,Ct,Cc,lpegmatch=lpeg.P,lpeg.R,lpeg.S,lpeg.C,lpeg.Ct,lpeg.Cc,lpeg.match -local floor=math.floor -local formatters=string.formatters -local sortedhash,sortedkeys=table.sortedhash,table.sortedkeys -local trace_loading=false trackers.register("fonts.loading",function(v) trace_loading=v end) -local trace_mapping=false trackers.register("fonts.mapping",function(v) trace_mapping=v end) -local report_fonts=logs.reporter("fonts","loading") -local force_ligatures=false directives.register("fonts.mapping.forceligatures",function(v) force_ligatures=v end) -local fonts=fonts or {} -local mappings=fonts.mappings or {} -fonts.mappings=mappings -local allocate=utilities.storage.allocate -local hex=R("AF","af","09") -local hexfour=(hex*hex*hex^-2)/function(s) return tonumber(s,16) end -local hexsix=(hex*hex*hex^-4)/function(s) return tonumber(s,16) end -local dec=(R("09")^1)/tonumber -local period=P(".") -local unicode=(P("uni")+P("UNI"))*(hexfour*(period+P(-1))*Cc(false)+Ct(hexfour^1)*Cc(true)) -local ucode=(P("u")+P("U") )*(hexsix*(period+P(-1))*Cc(false)+Ct(hexsix^1)*Cc(true)) -local index=P("index")*dec*Cc(false) -local parser=unicode+ucode+index -local parsers={} -local function makenameparser(str) - if not str or str=="" then - return parser - else - local p=parsers[str] - if not p then - p=P(str)*period*dec*Cc(false) - parsers[str]=p - end - return p - end -end -local f_single=formatters["%04X"] -local f_double=formatters["%04X%04X"] -local function tounicode16(unicode) - if unicode<0xD7FF or (unicode>0xDFFF and unicode<=0xFFFF) then - return f_single(unicode) - else - unicode=unicode-0x10000 - return f_double(floor(unicode/1024)+0xD800,unicode%1024+0xDC00) - end -end -local function tounicode16sequence(unicodes) - local t={} - for l=1,#unicodes do - local u=unicodes[l] - if u<0xD7FF or (u>0xDFFF and u<=0xFFFF) then - t[l]=f_single(u) - else - u=u-0x10000 - t[l]=f_double(floor(u/1024)+0xD800,u%1024+0xDC00) - end - end - return concat(t) -end -local function tounicode(unicode,name) - if type(unicode)=="table" then - local t={} - for l=1,#unicode do - local u=unicode[l] - if u<0xD7FF or (u>0xDFFF and u<=0xFFFF) then - t[l]=f_single(u) - else - u=u-0x10000 - t[l]=f_double(floor(u/1024)+0xD800,u%1024+0xDC00) - end - end - return concat(t) - else - if unicode<0xD7FF or (unicode>0xDFFF and unicode<=0xFFFF) then - return f_single(unicode) - else - unicode=unicode-0x10000 - return f_double(floor(unicode/1024)+0xD800,unicode%1024+0xDC00) - end - end -end -local function fromunicode16(str) - if #str==4 then - return tonumber(str,16) - else - local l,r=match(str,"(....)(....)") - return 0x10000+(tonumber(l,16)-0xD800)*0x400+tonumber(r,16)-0xDC00 - end -end -mappings.makenameparser=makenameparser -mappings.tounicode=tounicode -mappings.tounicode16=tounicode16 -mappings.tounicode16sequence=tounicode16sequence -mappings.fromunicode16=fromunicode16 -local ligseparator=P("_") -local varseparator=P(".") -local namesplitter=Ct(C((1-ligseparator-varseparator)^1)*(ligseparator*C((1-ligseparator-varseparator)^1))^0) -do - local overloads=allocate { - IJ={ name="I_J",unicode={ 0x49,0x4A },mess=0x0132 }, - ij={ name="i_j",unicode={ 0x69,0x6A },mess=0x0133 }, - ff={ name="f_f",unicode={ 0x66,0x66 },mess=0xFB00 }, - fi={ name="f_i",unicode={ 0x66,0x69 },mess=0xFB01 }, - fl={ name="f_l",unicode={ 0x66,0x6C },mess=0xFB02 }, - ffi={ name="f_f_i",unicode={ 0x66,0x66,0x69 },mess=0xFB03 }, - ffl={ name="f_f_l",unicode={ 0x66,0x66,0x6C },mess=0xFB04 }, - fj={ name="f_j",unicode={ 0x66,0x6A } }, - fk={ name="f_k",unicode={ 0x66,0x6B } }, - } - local o={} - for k,v in next,overloads do - local name=v.name - local mess=v.mess - if name then - o[name]=v - end - if mess then - o[mess]=v - end - o[k]=v - end - mappings.overloads=o -end -function mappings.addtounicode(data,filename,checklookups) - local resources=data.resources - local unicodes=resources.unicodes - if not unicodes then - if trace_mapping then - report_fonts("no unicode list, quitting tounicode for %a",filename) - end - return - end - local properties=data.properties - local descriptions=data.descriptions - local overloads=mappings.overloads - unicodes['space']=unicodes['space'] or 32 - unicodes['hyphen']=unicodes['hyphen'] or 45 - unicodes['zwj']=unicodes['zwj'] or 0x200D - unicodes['zwnj']=unicodes['zwnj'] or 0x200C - local private=fonts.constructors and fonts.constructors.privateoffset or 0xF0000 - local unicodevector=fonts.encodings.agl.unicodes or {} - local contextvector=fonts.encodings.agl.ctxcodes or {} - local missing={} - local nofmissing=0 - local oparser=nil - local cidnames=nil - local cidcodes=nil - local cidinfo=properties.cidinfo - local usedmap=cidinfo and fonts.cid.getmap(cidinfo) - local uparser=makenameparser() - if usedmap then - oparser=usedmap and makenameparser(cidinfo.ordering) - cidnames=usedmap.names - cidcodes=usedmap.unicodes - end - local ns=0 - local nl=0 - local dlist=sortedkeys(descriptions) - for i=1,#dlist do - local du=dlist[i] - local glyph=descriptions[du] - local name=glyph.name - if name then - local overload=overloads[name] or overloads[du] - if overload then - glyph.unicode=overload.unicode - else - local gu=glyph.unicode - if not gu or gu==-1 or du>=private or (du>=0xE000 and du<=0xF8FF) or du==0xFFFE or du==0xFFFF then - local unicode=unicodevector[name] or contextvector[name] - if unicode then - glyph.unicode=unicode - ns=ns+1 - end - if (not unicode) and usedmap then - local foundindex=lpegmatch(oparser,name) - if foundindex then - unicode=cidcodes[foundindex] - if unicode then - glyph.unicode=unicode - ns=ns+1 - else - local reference=cidnames[foundindex] - if reference then - local foundindex=lpegmatch(oparser,reference) - if foundindex then - unicode=cidcodes[foundindex] - if unicode then - glyph.unicode=unicode - ns=ns+1 - end - end - if not unicode or unicode=="" then - local foundcodes,multiple=lpegmatch(uparser,reference) - if foundcodes then - glyph.unicode=foundcodes - if multiple then - nl=nl+1 - unicode=true - else - ns=ns+1 - unicode=foundcodes - end - end - end - end - end - end - end - if not unicode or unicode=="" then - local split=lpegmatch(namesplitter,name) - local nsplit=split and #split or 0 - if nsplit==0 then - elseif nsplit==1 then - local base=split[1] - local u=unicodes[base] or unicodevector[base] or contextvector[name] - if not u then - elseif type(u)=="table" then - if u[1]<private then - unicode=u - glyph.unicode=unicode - end - elseif u<private then - unicode=u - glyph.unicode=unicode - end - else - local t,n={},0 - for l=1,nsplit do - local base=split[l] - local u=unicodes[base] or unicodevector[base] or contextvector[name] - if not u then - break - elseif type(u)=="table" then - if u[1]>=private then - break - end - n=n+1 - t[n]=u[1] - else - if u>=private then - break - end - n=n+1 - t[n]=u - end - end - if n>0 then - if n==1 then - unicode=t[1] - else - unicode=t - end - glyph.unicode=unicode - end - end - nl=nl+1 - end - if not unicode or unicode=="" then - local foundcodes,multiple=lpegmatch(uparser,name) - if foundcodes then - glyph.unicode=foundcodes - if multiple then - nl=nl+1 - unicode=true - else - ns=ns+1 - unicode=foundcodes - end - end - end - local r=overloads[unicode] - if r then - unicode=r.unicode - glyph.unicode=unicode - end - if not unicode then - missing[du]=true - nofmissing=nofmissing+1 - end - end - end - else - local overload=overloads[du] - if overload then - glyph.unicode=overload.unicode - end - end - end - if type(checklookups)=="function" then - checklookups(data,missing,nofmissing) - end - local collected=false - local unicoded=0 - for i=1,#dlist do - local du=dlist[i] - local glyph=descriptions[du] - if glyph.class=="ligature" and (force_ligatures or not glyph.unicode) then - if not collected then - collected=fonts.handlers.otf.readers.getcomponents(data) - if not collected then - break - end - end - local u=collected[du] - if u then - local n=#u - for i=1,n do - if u[i]>private then - n=0 - break - end - end - if n>0 then - if n>1 then - glyph.unicode=u - else - glyph.unicode=u[1] - end - unicoded=unicoded+1 - end - end - end - end - if trace_mapping and unicoded>0 then - report_fonts("%n ligature tounicode mappings deduced from gsub ligature features",unicoded) - end - if trace_mapping then - for i=1,#dlist do - local du=dlist[i] - local glyph=descriptions[du] - local name=glyph.name or "-" - local index=glyph.index or 0 - local unicode=glyph.unicode - if unicode then - if type(unicode)=="table" then - local unicodes={} - for i=1,#unicode do - unicodes[i]=formatters("%U",unicode[i]) - end - report_fonts("internal slot %U, name %a, unicode %U, tounicode % t",index,name,du,unicodes) - else - report_fonts("internal slot %U, name %a, unicode %U, tounicode %U",index,name,du,unicode) - end - else - report_fonts("internal slot %U, name %a, unicode %U",index,name,du) - end - end - end - if trace_loading and (ns>0 or nl>0) then - report_fonts("%s tounicode entries added, ligatures %s",nl+ns,ns) - end -end - -end --- [luaotfload, fontloader-2017-02-11.lua scope for “font-map”] --- - - -do --- [luaotfload, fontloader-2017-02-11.lua scope for “font-oti” 8f48c06a1d632febd7231ad5dfadfc53] --- - -if not modules then modules={} end modules ['font-oti']={ - version=1.001, - comment="companion to font-ini.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local lower=string.lower -local fonts=fonts -local constructors=fonts.constructors -local otf=constructors.handlers.otf -local otffeatures=constructors.features.otf -local registerotffeature=otffeatures.register -local otftables=otf.tables or {} -otf.tables=otftables -local allocate=utilities.storage.allocate -registerotffeature { - name="features", - description="initialization of feature handler", - default=true, -} -local function setmode(tfmdata,value) - if value then - tfmdata.properties.mode=lower(value) - end -end -otf.modeinitializer=setmode -local function setlanguage(tfmdata,value) - if value then - local cleanvalue=lower(value) - local languages=otftables and otftables.languages - local properties=tfmdata.properties - if not languages then - properties.language=cleanvalue - elseif languages[value] then - properties.language=cleanvalue - else - properties.language="dflt" - end - end -end -local function setscript(tfmdata,value) - if value then - local cleanvalue=lower(value) - local scripts=otftables and otftables.scripts - local properties=tfmdata.properties - if not scripts then - properties.script=cleanvalue - elseif scripts[value] then - properties.script=cleanvalue - else - properties.script="dflt" - end - end -end -registerotffeature { - name="mode", - description="mode", - initializers={ - base=setmode, - node=setmode, - plug=setmode, - } -} -registerotffeature { - name="language", - description="language", - initializers={ - base=setlanguage, - node=setlanguage, - plug=setlanguage, - } -} -registerotffeature { - name="script", - description="script", - initializers={ - base=setscript, - node=setscript, - plug=setscript, - } -} -otftables.featuretypes=allocate { - gpos_single="position", - gpos_pair="position", - gpos_cursive="position", - gpos_mark2base="position", - gpos_mark2ligature="position", - gpos_mark2mark="position", - gpos_context="position", - gpos_contextchain="position", - gsub_single="substitution", - gsub_multiple="substitution", - gsub_alternate="substitution", - gsub_ligature="substitution", - gsub_context="substitution", - gsub_contextchain="substitution", - gsub_reversecontextchain="substitution", - gsub_reversesub="substitution", -} -function otffeatures.checkeddefaultscript(featuretype,autoscript,scripts) - if featuretype=="position" then - local default=scripts.dflt - if default then - if autoscript=="position" or autoscript==true then - return default - else - report_otf("script feature %s not applied, enable default positioning") - end - else - end - elseif featuretype=="substitution" then - local default=scripts.dflt - if default then - if autoscript=="substitution" or autoscript==true then - return default - end - end - end -end -function otffeatures.checkeddefaultlanguage(featuretype,autolanguage,languages) - if featuretype=="position" then - local default=languages.dflt - if default then - if autolanguage=="position" or autolanguage==true then - return default - else - report_otf("language feature %s not applied, enable default positioning") - end - else - end - elseif featuretype=="substitution" then - local default=languages.dflt - if default then - if autolanguage=="substitution" or autolanguage==true then - return default - end - end - end -end - -end --- [luaotfload, fontloader-2017-02-11.lua scope for “font-oti”] --- - - -do --- [luaotfload, fontloader-2017-02-11.lua scope for “font-otr” 2bd0085b78027f261218d63034f43474] --- - -if not modules then modules={} end modules ['font-otr']={ - version=1.001, - comment="companion to font-ini.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local next,type,unpack=next,type,unpack -local byte,lower,char,strip,gsub=string.byte,string.lower,string.char,string.strip,string.gsub -local bittest=bit32.btest -local concat,remove,unpack,fastcopy=table.concat,table.remov,table.unpack,table.fastcopy -local floor,abs,sqrt,round=math.floor,math.abs,math.sqrt,math.round -local P,R,S,C,Cs,Cc,Ct,Carg,Cmt=lpeg.P,lpeg.R,lpeg.S,lpeg.C,lpeg.Cs,lpeg.Cc,lpeg.Ct,lpeg.Carg,lpeg.Cmt -local lpegmatch=lpeg.match -local setmetatableindex=table.setmetatableindex -local formatters=string.formatters -local sortedkeys=table.sortedkeys -local sortedhash=table.sortedhash -local stripstring=string.strip -local utf16_to_utf8_be=utf.utf16_to_utf8_be -local report=logs.reporter("otf reader") -local trace_cmap=false -fonts=fonts or {} -local handlers=fonts.handlers or {} -fonts.handlers=handlers -local otf=handlers.otf or {} -handlers.otf=otf -local readers=otf.readers or {} -otf.readers=readers -local streamreader=utilities.files -local streamwriter=utilities.files -readers.streamreader=streamreader -readers.streamwriter=streamwriter -local openfile=streamreader.open -local closefile=streamreader.close -local setposition=streamreader.setposition -local skipshort=streamreader.skipshort -local readbytes=streamreader.readbytes -local readstring=streamreader.readstring -local readbyte=streamreader.readcardinal1 -local readushort=streamreader.readcardinal2 -local readuint=streamreader.readcardinal3 -local readulong=streamreader.readcardinal4 -local readshort=streamreader.readinteger2 -local readlong=streamreader.readinteger4 -local readfixed=streamreader.readfixed4 -local readfword=readshort -local readufword=readushort -local readoffset=readushort -local read2dot14=streamreader.read2dot14 -function streamreader.readtag(f) - return lower(strip(readstring(f,4))) -end -local function readlongdatetime(f) - local a,b,c,d,e,f,g,h=readbytes(f,8) - return 0x100000000*d+0x1000000*e+0x10000*f+0x100*g+h -end -local tableversion=0.004 -readers.tableversion=tableversion -local privateoffset=fonts.constructors and fonts.constructors.privateoffset or 0xF0000 -local reportedskipped={} -local function reportskippedtable(tag) - if not reportedskipped[tag] then - report("loading of table %a skipped (reported once only)",tag) - reportedskipped[tag]=true - end -end -local reservednames={ [0]="copyright", - "family", - "subfamily", - "uniqueid", - "fullname", - "version", - "postscriptname", - "trademark", - "manufacturer", - "designer", - "description", - "vendorurl", - "designerurl", - "license", - "licenseurl", - "reserved", - "typographicfamily", - "typographicsubfamily", - "compatiblefullname", - "sampletext", - "cidfindfontname", - "wwsfamily", - "wwssubfamily", - "lightbackgroundpalette", - "darkbackgroundpalette", -} -local platforms={ [0]="unicode", - "macintosh", - "iso", - "windows", - "custom", -} -local encodings={ - unicode={ [0]="unicode 1.0 semantics", - "unicode 1.1 semantics", - "iso/iec 10646", - "unicode 2.0 bmp", - "unicode 2.0 full", - "unicode variation sequences", - "unicode full repertoire", - }, - macintosh={ [0]="roman","japanese","chinese (traditional)","korean","arabic","hebrew","greek","russian", - "rsymbol","devanagari","gurmukhi","gujarati","oriya","bengali","tamil","telugu","kannada", - "malayalam","sinhalese","burmese","khmer","thai","laotian","georgian","armenian", - "chinese (simplified)","tibetan","mongolian","geez","slavic","vietnamese","sindhi", - "uninterpreted", - }, - iso={ [0]="7-bit ascii", - "iso 10646", - "iso 8859-1", - }, - windows={ [0]="symbol", - "unicode bmp", - "shiftjis", - "prc", - "big5", - "wansung", - "johab", - "reserved 7", - "reserved 8", - "reserved 9", - "unicode ucs-4", - }, - custom={ - } -} -local decoders={ - unicode={}, - macintosh={}, - iso={}, - windows={ - ["unicode semantics"]=utf16_to_utf8_be, - ["unicode bmp"]=utf16_to_utf8_be, - ["unicode full"]=utf16_to_utf8_be, - ["unicode 1.0 semantics"]=utf16_to_utf8_be, - ["unicode 1.1 semantics"]=utf16_to_utf8_be, - ["unicode 2.0 bmp"]=utf16_to_utf8_be, - ["unicode 2.0 full"]=utf16_to_utf8_be, - ["unicode variation sequences"]=utf16_to_utf8_be, - ["unicode full repertoire"]=utf16_to_utf8_be, - }, - custom={}, -} -local languages={ - unicode={ - [ 0]="english", - }, - macintosh={ - [ 0]="english", - }, - iso={}, - windows={ - [0x0409]="english - united states", - }, - custom={}, -} -local standardromanencoding={ [0]= - "notdef",".null","nonmarkingreturn","space","exclam","quotedbl", - "numbersign","dollar","percent","ampersand","quotesingle","parenleft", - "parenright","asterisk","plus","comma","hyphen","period","slash", - "zero","one","two","three","four","five","six","seven","eight", - "nine","colon","semicolon","less","equal","greater","question","at", - "A","B","C","D","E","F","G","H","I","J","K","L","M","N","O", - "P","Q","R","S","T","U","V","W","X","Y","Z","bracketleft", - "backslash","bracketright","asciicircum","underscore","grave","a","b", - "c","d","e","f","g","h","i","j","k","l","m","n","o","p","q", - "r","s","t","u","v","w","x","y","z","braceleft","bar", - "braceright","asciitilde","Adieresis","Aring","Ccedilla","Eacute", - "Ntilde","Odieresis","Udieresis","aacute","agrave","acircumflex", - "adieresis","atilde","aring","ccedilla","eacute","egrave", - "ecircumflex","edieresis","iacute","igrave","icircumflex","idieresis", - "ntilde","oacute","ograve","ocircumflex","odieresis","otilde","uacute", - "ugrave","ucircumflex","udieresis","dagger","degree","cent","sterling", - "section","bullet","paragraph","germandbls","registered","copyright", - "trademark","acute","dieresis","notequal","AE","Oslash","infinity", - "plusminus","lessequal","greaterequal","yen","mu","partialdiff", - "summation","product","pi","integral","ordfeminine","ordmasculine", - "Omega","ae","oslash","questiondown","exclamdown","logicalnot", - "radical","florin","approxequal","Delta","guillemotleft", - "guillemotright","ellipsis","nonbreakingspace","Agrave","Atilde", - "Otilde","OE","oe","endash","emdash","quotedblleft","quotedblright", - "quoteleft","quoteright","divide","lozenge","ydieresis","Ydieresis", - "fraction","currency","guilsinglleft","guilsinglright","fi","fl", - "daggerdbl","periodcentered","quotesinglbase","quotedblbase", - "perthousand","Acircumflex","Ecircumflex","Aacute","Edieresis","Egrave", - "Iacute","Icircumflex","Idieresis","Igrave","Oacute","Ocircumflex", - "apple","Ograve","Uacute","Ucircumflex","Ugrave","dotlessi", - "circumflex","tilde","macron","breve","dotaccent","ring","cedilla", - "hungarumlaut","ogonek","caron","Lslash","lslash","Scaron","scaron", - "Zcaron","zcaron","brokenbar","Eth","eth","Yacute","yacute","Thorn", - "thorn","minus","multiply","onesuperior","twosuperior","threesuperior", - "onehalf","onequarter","threequarters","franc","Gbreve","gbreve", - "Idotaccent","Scedilla","scedilla","Cacute","cacute","Ccaron","ccaron", - "dcroat", -} -local weights={ - [100]="thin", - [200]="extralight", - [300]="light", - [400]="normal", - [500]="medium", - [600]="semibold", - [700]="bold", - [800]="extrabold", - [900]="black", -} -local widths={ - [1]="ultracondensed", - [2]="extracondensed", - [3]="condensed", - [4]="semicondensed", - [5]="normal", - [6]="semiexpanded", - [7]="expanded", - [8]="extraexpanded", - [9]="ultraexpanded", -} -setmetatableindex(weights,function(t,k) - local r=floor((k+50)/100)*100 - local v=(r>900 and "black") or rawget(t,r) or "normal" - return v -end) -setmetatableindex(widths,function(t,k) - return "normal" -end) -local panoseweights={ - [ 0]="normal", - [ 1]="normal", - [ 2]="verylight", - [ 3]="light", - [ 4]="thin", - [ 5]="book", - [ 6]="medium", - [ 7]="demi", - [ 8]="bold", - [ 9]="heavy", - [10]="black", -} -local panosewidths={ - [ 0]="normal", - [ 1]="normal", - [ 2]="normal", - [ 3]="normal", - [ 4]="normal", - [ 5]="expanded", - [ 6]="condensed", - [ 7]="veryexpanded", - [ 8]="verycondensed", - [ 9]="monospaced", -} -local platformnames={ - postscriptname=true, - fullname=true, - family=true, - subfamily=true, - typographicfamily=true, - typographicsubfamily=true, - compatiblefullname=true, -} -function readers.name(f,fontdata,specification) - local datatable=fontdata.tables.name - if datatable then - setposition(f,datatable.offset) - local format=readushort(f) - local nofnames=readushort(f) - local offset=readushort(f) - local start=datatable.offset+offset - local namelists={ - unicode={}, - windows={}, - macintosh={}, - } - for i=1,nofnames do - local platform=platforms[readushort(f)] - if platform then - local namelist=namelists[platform] - if namelist then - local encoding=readushort(f) - local language=readushort(f) - local encodings=encodings[platform] - local languages=languages[platform] - if encodings and languages then - local encoding=encodings[encoding] - local language=languages[language] - if encoding and language then - local name=reservednames[readushort(f)] - if name then - namelist[#namelist+1]={ - platform=platform, - encoding=encoding, - language=language, - name=name, - length=readushort(f), - offset=start+readushort(f), - } - else - skipshort(f,2) - end - else - skipshort(f,3) - end - else - skipshort(f,3) - end - else - skipshort(f,5) - end - else - skipshort(f,5) - end - end - local names={} - local done={} - local function filter(platform,e,l) - local namelist=namelists[platform] - for i=1,#namelist do - local name=namelist[i] - local nametag=name.name - if not done[nametag] then - local encoding=name.encoding - local language=name.language - if (not e or encoding==e) and (not l or language==l) then - setposition(f,name.offset) - local content=readstring(f,name.length) - local decoder=decoders[platform] - if decoder then - decoder=decoder[encoding] - end - if decoder then - content=decoder(content) - end - names[nametag]={ - content=content, - platform=platform, - encoding=encoding, - language=language, - } - done[nametag]=true - end - end - end - end - filter("windows","unicode bmp","english - united states") - filter("macintosh","roman","english") - filter("windows") - filter("macintosh") - filter("unicode") - fontdata.names=names - if specification.platformnames then - local collected={} - for platform,namelist in next,namelists do - local filtered=false - for i=1,#namelist do - local entry=namelist[i] - local name=entry.name - if platformnames[name] then - setposition(f,entry.offset) - local content=readstring(f,entry.length) - local encoding=entry.encoding - local decoder=decoders[platform] - if decoder then - decoder=decoder[encoding] - end - if decoder then - content=decoder(content) - end - if filtered then - filtered[name]=content - else - filtered={ [name]=content } - end - end - end - if filtered then - collected[platform]=filtered - end - end - fontdata.platformnames=collected - end - else - fontdata.names={} - end -end -local validutf=lpeg.patterns.validutf8 -local function getname(fontdata,key) - local names=fontdata.names - if names then - local value=names[key] - if value then - local content=value.content - return lpegmatch(validutf,content) and content or nil - end - end -end -readers["os/2"]=function(f,fontdata) - local datatable=fontdata.tables["os/2"] - if datatable then - setposition(f,datatable.offset) - local version=readushort(f) - local windowsmetrics={ - version=version, - averagewidth=readshort(f), - weightclass=readushort(f), - widthclass=readushort(f), - fstype=readushort(f), - subscriptxsize=readshort(f), - subscriptysize=readshort(f), - subscriptxoffset=readshort(f), - subscriptyoffset=readshort(f), - superscriptxsize=readshort(f), - superscriptysize=readshort(f), - superscriptxoffset=readshort(f), - superscriptyoffset=readshort(f), - strikeoutsize=readshort(f), - strikeoutpos=readshort(f), - familyclass=readshort(f), - panose={ readbytes(f,10) }, - unicoderanges={ readulong(f),readulong(f),readulong(f),readulong(f) }, - vendor=readstring(f,4), - fsselection=readushort(f), - firstcharindex=readushort(f), - lastcharindex=readushort(f), - typoascender=readshort(f), - typodescender=readshort(f), - typolinegap=readshort(f), - winascent=readushort(f), - windescent=readushort(f), - } - if version>=1 then - windowsmetrics.codepageranges={ readulong(f),readulong(f) } - end - if version>=3 then - windowsmetrics.xheight=readshort(f) - windowsmetrics.capheight=readshort(f) - windowsmetrics.defaultchar=readushort(f) - windowsmetrics.breakchar=readushort(f) - end - windowsmetrics.weight=windowsmetrics.weightclass and weights[windowsmetrics.weightclass] - windowsmetrics.width=windowsmetrics.widthclass and widths [windowsmetrics.widthclass] - windowsmetrics.panoseweight=panoseweights[windowsmetrics.panose[3]] - windowsmetrics.panosewidth=panosewidths [windowsmetrics.panose[4]] - fontdata.windowsmetrics=windowsmetrics - else - fontdata.windowsmetrics={} - end -end -readers.head=function(f,fontdata) - local datatable=fontdata.tables.head - if datatable then - setposition(f,datatable.offset) - local fontheader={ - version=readfixed(f), - revision=readfixed(f), - checksum=readulong(f), - magic=readulong(f), - flags=readushort(f), - units=readushort(f), - created=readlongdatetime(f), - modified=readlongdatetime(f), - xmin=readshort(f), - ymin=readshort(f), - xmax=readshort(f), - ymax=readshort(f), - macstyle=readushort(f), - smallpixels=readushort(f), - directionhint=readshort(f), - indextolocformat=readshort(f), - glyphformat=readshort(f), - } - fontdata.fontheader=fontheader - else - fontdata.fontheader={} - end - fontdata.nofglyphs=0 -end -readers.hhea=function(f,fontdata,specification) - if specification.details then - local datatable=fontdata.tables.hhea - if datatable then - setposition(f,datatable.offset) - fontdata.horizontalheader={ - version=readfixed(f), - ascender=readfword(f), - descender=readfword(f), - linegap=readfword(f), - maxadvancewidth=readufword(f), - minleftsidebearing=readfword(f), - minrightsidebearing=readfword(f), - maxextent=readfword(f), - caretsloperise=readshort(f), - caretsloperun=readshort(f), - caretoffset=readshort(f), - reserved_1=readshort(f), - reserved_2=readshort(f), - reserved_3=readshort(f), - reserved_4=readshort(f), - metricdataformat=readshort(f), - nofmetrics=readushort(f), - } - else - fontdata.horizontalheader={ - nofmetrics=0, - } - end - end -end -readers.vhea=function(f,fontdata,specification) - if specification.details then - local datatable=fontdata.tables.vhea - if datatable then - setposition(f,datatable.offset) - local version=readfixed(f) - fontdata.verticalheader={ - version=version, - ascender=readfword(f), - descender=readfword(f), - linegap=readfword(f), - maxadvanceheight=readufword(f), - mintopsidebearing=readfword(f), - minbottomsidebearing=readfword(f), - maxextent=readfword(f), - caretsloperise=readshort(f), - caretsloperun=readshort(f), - caretoffset=readshort(f), - reserved_1=readshort(f), - reserved_2=readshort(f), - reserved_3=readshort(f), - reserved_4=readshort(f), - metricdataformat=readshort(f), - nofmetrics=readushort(f), - } - else - fontdata.verticalheader={ - nofmetrics=0, - } - end - end -end -readers.maxp=function(f,fontdata,specification) - if specification.details then - local datatable=fontdata.tables.maxp - if datatable then - setposition(f,datatable.offset) - local version=readfixed(f) - local nofglyphs=readushort(f) - fontdata.nofglyphs=nofglyphs - if version==0.5 then - fontdata.maximumprofile={ - version=version, - nofglyphs=nofglyphs, - } - return - elseif version==1.0 then - fontdata.maximumprofile={ - version=version, - nofglyphs=nofglyphs, - points=readushort(f), - contours=readushort(f), - compositepoints=readushort(f), - compositecontours=readushort(f), - zones=readushort(f), - twilightpoints=readushort(f), - storage=readushort(f), - functiondefs=readushort(f), - instructiondefs=readushort(f), - stackelements=readushort(f), - sizeofinstructions=readushort(f), - componentelements=readushort(f), - componentdepth=readushort(f), - } - return - end - end - fontdata.maximumprofile={ - version=version, - nofglyphs=0, - } - end -end -readers.hmtx=function(f,fontdata,specification) - if specification.glyphs then - local datatable=fontdata.tables.hmtx - if datatable then - setposition(f,datatable.offset) - local horizontalheader=fontdata.horizontalheader - local nofmetrics=horizontalheader.nofmetrics - local glyphs=fontdata.glyphs - local nofglyphs=fontdata.nofglyphs - local width=0 - local leftsidebearing=0 - for i=0,nofmetrics-1 do - local glyph=glyphs[i] - width=readshort(f) - leftsidebearing=readshort(f) - if width~=0 then - glyph.width=width - end - end - for i=nofmetrics,nofglyphs-1 do - local glyph=glyphs[i] - if width~=0 then - glyph.width=width - end - end - end - end -end -readers.vmtx=function(f,fontdata,specification) - if specification.glyphs then - local datatable=fontdata.tables.vmtx - if datatable then - setposition(f,datatable.offset) - local verticalheader=fontdata.verticalheader - local nofmetrics=verticalheader.nofmetrics - local glyphs=fontdata.glyphs - local nofglyphs=fontdata.nofglyphs - local vheight=0 - local vdefault=verticalheader.ascender+verticalheader.descender - local topsidebearing=0 - for i=0,nofmetrics-1 do - local glyph=glyphs[i] - vheight=readshort(f) - topsidebearing=readshort(f) - if vheight~=0 and vheight~=vdefault then - glyph.vheight=vheight - end - end - for i=nofmetrics,nofglyphs-1 do - local glyph=glyphs[i] - if vheight~=0 and vheight~=vdefault then - glyph.vheight=vheight - end - end - end - end -end -readers.vorg=function(f,fontdata,specification) - if specification.glyphs then - local datatable=fontdata.tables.vorg - if datatable then - report("todo: %s","vorg") - end - end -end -readers.post=function(f,fontdata,specification) - local datatable=fontdata.tables.post - if datatable then - setposition(f,datatable.offset) - local version=readfixed(f) - fontdata.postscript={ - version=version, - italicangle=round(1000*readfixed(f))/1000, - underlineposition=readfword(f), - underlinethickness=readfword(f), - monospaced=readulong(f), - minmemtype42=readulong(f), - maxmemtype42=readulong(f), - minmemtype1=readulong(f), - maxmemtype1=readulong(f), - } - if not specification.glyphs then - elseif version==1.0 then - for index=0,#standardromanencoding do - glyphs[index].name=standardromanencoding[index] - end - elseif version==2.0 then - local glyphs=fontdata.glyphs - local nofglyphs=readushort(f) - local indices={} - local names={} - local maxnames=0 - for i=0,nofglyphs-1 do - local nameindex=readushort(f) - if nameindex>=258 then - maxnames=maxnames+1 - nameindex=nameindex-257 - indices[nameindex]=i - else - glyphs[i].name=standardromanencoding[nameindex] - end - end - for i=1,maxnames do - local mapping=indices[i] - if not mapping then - report("quit post name fetching at %a of %a: %s",i,maxnames,"no index") - break - else - local length=readbyte(f) - if length>0 then - glyphs[mapping].name=readstring(f,length) - else - report("quit post name fetching at %a of %a: %s",i,maxnames,"overflow") - break - end - end - end - elseif version==2.5 then - elseif version==3.0 then - end - else - fontdata.postscript={} - end -end -readers.cff=function(f,fontdata,specification) - if specification.glyphs then - reportskippedtable("cff") - end -end -local formatreaders={} -local duplicatestoo=true -local sequence={ - { 3,1,4 }, - { 3,10,12 }, - { 0,3,4 }, - { 0,1,4 }, - { 0,0,6 }, - { 3,0,6 }, - { 0,5,14 }, - { 3,10,13 }, -} -local supported={} -for i=1,#sequence do - local sp,se,sf=unpack(sequence[i]) - local p=supported[sp] - if not p then - p={} - supported[sp]=p - end - local e=p[se] - if not e then - e={} - p[se]=e - end - e[sf]=true -end -formatreaders[4]=function(f,fontdata,offset) - setposition(f,offset+2) - local length=readushort(f) - local language=readushort(f) - local nofsegments=readushort(f)/2 - skipshort(f,3) - local endchars={} - local startchars={} - local deltas={} - local offsets={} - local indices={} - local mapping=fontdata.mapping - local glyphs=fontdata.glyphs - local duplicates=fontdata.duplicates - local nofdone=0 - for i=1,nofsegments do - endchars[i]=readushort(f) - end - local reserved=readushort(f) - for i=1,nofsegments do - startchars[i]=readushort(f) - end - for i=1,nofsegments do - deltas[i]=readshort(f) - end - for i=1,nofsegments do - offsets[i]=readushort(f) - end - local size=(length-2*2-5*2-4*nofsegments*2)/2 - for i=1,size-1 do - indices[i]=readushort(f) - end - for segment=1,nofsegments do - local startchar=startchars[segment] - local endchar=endchars[segment] - local offset=offsets[segment] - local delta=deltas[segment] - if startchar==0xFFFF and endchar==0xFFFF then - elseif startchar==0xFFFF and offset==0 then - elseif offset==0xFFFF then - elseif offset==0 then - if trace_cmap then - report("format 4.%i segment %2i from %C upto %C at index %H",1,segment,startchar,endchar,(startchar+delta)%65536) - end - for unicode=startchar,endchar do - local index=(unicode+delta)%65536 - if index and index>0 then - local glyph=glyphs[index] - if glyph then - local gu=glyph.unicode - if not gu then - glyph.unicode=unicode - nofdone=nofdone+1 - elseif gu~=unicode then - if duplicatestoo then - local d=duplicates[gu] - if d then - d[unicode]=true - else - duplicates[gu]={ [unicode]=true } - end - else - report("duplicate case 1: %C %04i %s",unicode,index,glyphs[index].name) - end - end - if not mapping[index] then - mapping[index]=unicode - end - end - end - end - else - local shift=(segment-nofsegments+offset/2)-startchar - if trace_cmap then - report("format 4.%i segment %2i from %C upto %C at index %H",0,segment,startchar,endchar,(startchar+delta)%65536) - end - for unicode=startchar,endchar do - local slot=shift+unicode - local index=indices[slot] - if index and index>0 then - index=(index+delta)%65536 - local glyph=glyphs[index] - if glyph then - local gu=glyph.unicode - if not gu then - glyph.unicode=unicode - nofdone=nofdone+1 - elseif gu~=unicode then - if duplicatestoo then - local d=duplicates[gu] - if d then - d[unicode]=true - else - duplicates[gu]={ [unicode]=true } - end - else - report("duplicate case 2: %C %04i %s",unicode,index,glyphs[index].name) - end - end - if not mapping[index] then - mapping[index]=unicode - end - end - end - end - end - end - return nofdone -end -formatreaders[6]=function(f,fontdata,offset) - setposition(f,offset) - local format=readushort(f) - local length=readushort(f) - local language=readushort(f) - local mapping=fontdata.mapping - local glyphs=fontdata.glyphs - local duplicates=fontdata.duplicates - local start=readushort(f) - local count=readushort(f) - local stop=start+count-1 - local nofdone=0 - if trace_cmap then - report("format 6 from %C to %C",2,start,stop) - end - for unicode=start,stop do - local index=readushort(f) - if index>0 then - local glyph=glyphs[index] - if glyph then - local gu=glyph.unicode - if not gu then - glyph.unicode=unicode - nofdone=nofdone+1 - elseif gu~=unicode then - end - if not mapping[index] then - mapping[index]=unicode - end - end - end - end - return nofdone -end -formatreaders[12]=function(f,fontdata,offset) - setposition(f,offset+2+2+4+4) - local mapping=fontdata.mapping - local glyphs=fontdata.glyphs - local duplicates=fontdata.duplicates - local nofgroups=readulong(f) - local nofdone=0 - for i=1,nofgroups do - local first=readulong(f) - local last=readulong(f) - local index=readulong(f) - if trace_cmap then - report("format 12 from %C to %C starts at index %i",first,last,index) - end - for unicode=first,last do - local glyph=glyphs[index] - if glyph then - local gu=glyph.unicode - if not gu then - glyph.unicode=unicode - nofdone=nofdone+1 - elseif gu~=unicode then - local d=duplicates[gu] - if d then - d[unicode]=true - else - duplicates[gu]={ [unicode]=true } - end - end - if not mapping[index] then - mapping[index]=unicode - end - end - index=index+1 - end - end - return nofdone -end -formatreaders[13]=function(f,fontdata,offset) - setposition(f,offset+2+2+4+4) - local mapping=fontdata.mapping - local glyphs=fontdata.glyphs - local duplicates=fontdata.duplicates - local nofgroups=readulong(f) - local nofdone=0 - for i=1,nofgroups do - local first=readulong(f) - local last=readulong(f) - local index=readulong(f) - if first<privateoffset then - if trace_cmap then - report("format 13 from %C to %C get index %i",first,last,index) - end - local glyph=glyphs[index] - local unicode=glyph.unicode - if not unicode then - unicode=first - glyph.unicode=unicode - first=first+1 - end - local list=duplicates[unicode] - mapping[index]=unicode - if not list then - list={} - duplicates[unicode]=list - end - if last>=privateoffset then - local limit=privateoffset-1 - report("format 13 from %C to %C pruned to %C",first,last,limit) - last=limit - end - for unicode=first,last do - list[unicode]=true - end - nofdone=nofdone+last-first+1 - else - report("format 13 from %C to %C ignored",first,last) - end - end - return nofdone -end -formatreaders[14]=function(f,fontdata,offset) - if offset and offset~=0 then - setposition(f,offset) - local format=readushort(f) - local length=readulong(f) - local nofrecords=readulong(f) - local records={} - local variants={} - local nofdone=0 - fontdata.variants=variants - for i=1,nofrecords do - records[i]={ - selector=readuint(f), - default=readulong(f), - other=readulong(f), - } - end - for i=1,nofrecords do - local record=records[i] - local selector=record.selector - local default=record.default - local other=record.other - local other=record.other - if other~=0 then - setposition(f,offset+other) - local mapping={} - local count=readulong(f) - for i=1,count do - mapping[readuint(f)]=readushort(f) - end - nofdone=nofdone+count - variants[selector]=mapping - end - end - return nofdone - else - return 0 - end -end -local function checkcmap(f,fontdata,records,platform,encoding,format) - local data=records[platform] - if not data then - return 0 - end - data=data[encoding] - if not data then - return 0 - end - data=data[format] - if not data then - return 0 - end - local reader=formatreaders[format] - if not reader then - return 0 - end - local p=platforms[platform] - local e=encodings[p] - local n=reader(f,fontdata,data) or 0 - report("cmap checked: platform %i (%s), encoding %i (%s), format %i, new unicodes %i",platform,p,encoding,e and e[encoding] or "?",format,n) - return n -end -function readers.cmap(f,fontdata,specification) - if specification.glyphs then - local datatable=fontdata.tables.cmap - if datatable then - local tableoffset=datatable.offset - setposition(f,tableoffset) - local version=readushort(f) - local noftables=readushort(f) - local records={} - local unicodecid=false - local variantcid=false - local variants={} - local duplicates=fontdata.duplicates or {} - fontdata.duplicates=duplicates - for i=1,noftables do - local platform=readushort(f) - local encoding=readushort(f) - local offset=readulong(f) - local record=records[platform] - if not record then - records[platform]={ - [encoding]={ - offsets={ offset }, - formats={}, - } - } - else - local subtables=record[encoding] - if not subtables then - record[encoding]={ - offsets={ offset }, - formats={}, - } - else - local offsets=subtables.offsets - offsets[#offsets+1]=offset - end - end - end - report("found cmaps:") - for platform,record in sortedhash(records) do - local p=platforms[platform] - local e=encodings[p] - local sp=supported[platform] - local ps=p or "?" - if sp then - report(" platform %i: %s",platform,ps) - else - report(" platform %i: %s (unsupported)",platform,ps) - end - for encoding,subtables in sortedhash(record) do - local se=sp and sp[encoding] - local es=e and e[encoding] or "?" - if se then - report(" encoding %i: %s",encoding,es) - else - report(" encoding %i: %s (unsupported)",encoding,es) - end - local offsets=subtables.offsets - local formats=subtables.formats - for i=1,#offsets do - local offset=tableoffset+offsets[i] - setposition(f,offset) - formats[readushort(f)]=offset - end - record[encoding]=formats - local list=sortedkeys(formats) - for i=1,#list do - if not (se and se[list[i]]) then - list[i]=list[i].." (unsupported)" - end - end - report(" formats: % t",list) - end - end - local ok=false - for i=1,#sequence do - local sp,se,sf=unpack(sequence[i]) - if checkcmap(f,fontdata,records,sp,se,sf)>0 then - ok=true - end - end - if not ok then - report("no useable unicode cmap found") - end - fontdata.cidmaps={ - version=version, - noftables=noftables, - records=records, - } - else - fontdata.cidmaps={} - end - end -end -function readers.loca(f,fontdata,specification) - if specification.glyphs then - reportskippedtable("loca") - end -end -function readers.glyf(f,fontdata,specification) - if specification.glyphs then - reportskippedtable("glyf") - end -end -function readers.colr(f,fontdata,specification) - if specification.glyphs then - reportskippedtable("colr") - end -end -function readers.cpal(f,fontdata,specification) - if specification.glyphs then - reportskippedtable("cpal") - end -end -function readers.svg(f,fontdata,specification) - if specification.glyphs then - reportskippedtable("svg") - end -end -function readers.kern(f,fontdata,specification) - if specification.kerns then - local datatable=fontdata.tables.kern - if datatable then - setposition(f,datatable.offset) - local version=readushort(f) - local noftables=readushort(f) - for i=1,noftables do - local version=readushort(f) - local length=readushort(f) - local coverage=readushort(f) - local format=bit32.rshift(coverage,8) - if format==0 then - local nofpairs=readushort(f) - local searchrange=readushort(f) - local entryselector=readushort(f) - local rangeshift=readushort(f) - local kerns={} - local glyphs=fontdata.glyphs - for i=1,nofpairs do - local left=readushort(f) - local right=readushort(f) - local kern=readfword(f) - local glyph=glyphs[left] - local kerns=glyph.kerns - if kerns then - kerns[right]=kern - else - glyph.kerns={ [right]=kern } - end - end - elseif format==2 then - report("todo: kern classes") - else - report("todo: kerns") - end - end - end - end -end -function readers.gdef(f,fontdata,specification) - if specification.details then - reportskippedtable("gdef") - end -end -function readers.gsub(f,fontdata,specification) - if specification.details then - reportskippedtable("gsub") - end -end -function readers.gpos(f,fontdata,specification) - if specification.details then - reportskippedtable("gpos") - end -end -function readers.math(f,fontdata,specification) - if specification.glyphs then - reportskippedtable("math") - end -end -local function getinfo(maindata,sub,platformnames,rawfamilynames,metricstoo) - local fontdata=sub and maindata.subfonts and maindata.subfonts[sub] or maindata - local names=fontdata.names - local info=nil - if names then - local metrics=fontdata.windowsmetrics or {} - local postscript=fontdata.postscript or {} - local fontheader=fontdata.fontheader or {} - local cffinfo=fontdata.cffinfo or {} - local filename=fontdata.filename - local weight=getname(fontdata,"weight") or (cffinfo and cffinfo.weight) or (metrics and metrics.weight) - local width=getname(fontdata,"width") or (cffinfo and cffinfo.width ) or (metrics and metrics.width ) - local fontname=getname(fontdata,"postscriptname") - local fullname=getname(fontdata,"fullname") - local family=getname(fontdata,"family") - local subfamily=getname(fontdata,"subfamily") - local familyname=getname(fontdata,"typographicfamily") - local subfamilyname=getname(fontdata,"typographicsubfamily") - local compatiblename=getname(fontdata,"compatiblefullname") - if rawfamilynames then - else - if not familyname then familyname=family end - if not subfamilyname then subfamilyname=subfamily end - end - info={ - subfontindex=fontdata.subfontindex or sub or 0, - version=getname(fontdata,"version"), - fontname=fontname, - fullname=fullname, - family=family, - subfamily=subfamily, - familyname=familyname, - subfamilyname=subfamilyname, - compatiblename=compatiblename, - weight=weight and lower(weight), - width=width and lower(width), - pfmweight=metrics.weightclass or 400, - pfmwidth=metrics.widthclass or 5, - panosewidth=metrics.panosewidth, - panoseweight=metrics.panoseweight, - italicangle=postscript.italicangle or 0, - units=fontheader.units or 0, - designsize=fontdata.designsize, - minsize=fontdata.minsize, - maxsize=fontdata.maxsize, - monospaced=(tonumber(postscript.monospaced or 0)>0) or metrics.panosewidth=="monospaced", - averagewidth=metrics.averagewidth, - xheight=metrics.xheight, - capheight=metrics.capheight, - ascender=metrics.typoascender, - descender=metrics.typodescender, - platformnames=platformnames and fontdata.platformnames or nil, - } - if metricstoo then - local keys={ - "version", - "ascender","descender","linegap", - "maxadvancewidth","maxadvanceheight","maxextent", - "minbottomsidebearing","mintopsidebearing", - } - local h=fontdata.horizontalheader or {} - local v=fontdata.verticalheader or {} - if h then - local th={} - local tv={} - for i=1,#keys do - local key=keys[i] - th[key]=h[key] or 0 - tv[key]=v[key] or 0 - end - info.horizontalmetrics=th - info.verticalmetrics=tv - end - end - elseif n then - info={ - filename=fontdata.filename, - comment="there is no info for subfont "..n, - } - else - info={ - filename=fontdata.filename, - comment="there is no info", - } - end - return info -end -local function loadtables(f,specification,offset) - if offset then - setposition(f,offset) - end - local tables={} - local basename=file.basename(specification.filename) - local filesize=specification.filesize - local filetime=specification.filetime - local fontdata={ - filename=basename, - filesize=filesize, - filetime=filetime, - version=readstring(f,4), - noftables=readushort(f), - searchrange=readushort(f), - entryselector=readushort(f), - rangeshift=readushort(f), - tables=tables, - } - for i=1,fontdata.noftables do - local tag=lower(stripstring(readstring(f,4))) - local checksum=readulong(f) - local offset=readulong(f) - local length=readulong(f) - if offset+length>filesize then - report("bad %a table in file %a",tag,basename) - end - tables[tag]={ - checksum=checksum, - offset=offset, - length=length, - } - end - if tables.cff then - fontdata.format="opentype" - else - fontdata.format="truetype" - end - return fontdata -end -local function prepareglyps(fontdata) - local glyphs=setmetatableindex(function(t,k) - local v={ - index=k, - } - t[k]=v - return v - end) - fontdata.glyphs=glyphs - fontdata.mapping={} -end -local function readdata(f,offset,specification) - local fontdata=loadtables(f,specification,offset) - if specification.glyphs then - prepareglyps(fontdata) - end - readers["name"](f,fontdata,specification) - local askedname=specification.askedname - if askedname then - local fullname=getname(fontdata,"fullname") or "" - local cleanname=gsub(askedname,"[^a-zA-Z0-9]","") - local foundname=gsub(fullname,"[^a-zA-Z0-9]","") - if lower(cleanname)~=lower(foundname) then - return - end - end - readers["os/2"](f,fontdata,specification) - readers["head"](f,fontdata,specification) - readers["maxp"](f,fontdata,specification) - readers["hhea"](f,fontdata,specification) - readers["vhea"](f,fontdata,specification) - readers["hmtx"](f,fontdata,specification) - readers["vmtx"](f,fontdata,specification) - readers["vorg"](f,fontdata,specification) - readers["post"](f,fontdata,specification) - readers["cff" ](f,fontdata,specification) - readers["cmap"](f,fontdata,specification) - readers["loca"](f,fontdata,specification) - readers["glyf"](f,fontdata,specification) - readers["colr"](f,fontdata,specification) - readers["cpal"](f,fontdata,specification) - readers["svg" ](f,fontdata,specification) - readers["kern"](f,fontdata,specification) - readers["gdef"](f,fontdata,specification) - readers["gsub"](f,fontdata,specification) - readers["gpos"](f,fontdata,specification) - readers["math"](f,fontdata,specification) - fontdata.locations=nil - fontdata.tables=nil - fontdata.cidmaps=nil - fontdata.dictionaries=nil - return fontdata -end -local function loadfontdata(specification) - local filename=specification.filename - local fileattr=lfs.attributes(filename) - local filesize=fileattr and fileattr.size or 0 - local filetime=fileattr and fileattr.modification or 0 - local f=openfile(filename,true) - if not f then - report("unable to open %a",filename) - elseif filesize==0 then - report("empty file %a",filename) - closefile(f) - else - specification.filesize=filesize - specification.filetime=filetime - local version=readstring(f,4) - local fontdata=nil - if version=="OTTO" or version=="true" or version=="\0\1\0\0" then - fontdata=readdata(f,0,specification) - elseif version=="ttcf" then - local subfont=tonumber(specification.subfont) - local offsets={} - local ttcversion=readulong(f) - local nofsubfonts=readulong(f) - for i=1,nofsubfonts do - offsets[i]=readulong(f) - end - if subfont then - if subfont>=1 and subfont<=nofsubfonts then - fontdata=readdata(f,offsets[subfont],specification) - else - report("no subfont %a in file %a",subfont,filename) - end - else - subfont=specification.subfont - if type(subfont)=="string" and subfont~="" then - specification.askedname=subfont - for i=1,nofsubfonts do - fontdata=readdata(f,offsets[i],specification) - if fontdata then - fontdata.subfontindex=i - report("subfont named %a has index %a",subfont,i) - break - end - end - if not fontdata then - report("no subfont named %a",subfont) - end - else - local subfonts={} - fontdata={ - filename=filename, - filesize=filesize, - filetime=filetime, - version=version, - subfonts=subfonts, - ttcversion=ttcversion, - nofsubfonts=nofsubfonts, - } - for i=1,nofsubfonts do - subfonts[i]=readdata(f,offsets[i],specification) - end - end - end - else - report("unknown version %a in file %a",version,filename) - end - closefile(f) - return fontdata or {} - end -end -local function loadfont(specification,n) - if type(specification)=="string" then - specification={ - filename=specification, - info=true, - details=true, - glyphs=true, - shapes=true, - kerns=true, - globalkerns=true, - lookups=true, - subfont=n or true, - tounicode=false, - } - end - if specification.shapes or specification.lookups or specification.kerns then - specification.glyphs=true - end - if specification.glyphs then - specification.details=true - end - if specification.details then - specification.info=true - end - if specification.platformnames then - specification.platformnames=true - end - local function message(str) - report("fatal error in file %a: %s\n%s",specification.filename,str,debug.traceback()) - end - local ok,result=xpcall(loadfontdata,message,specification) - if ok then - return result - end -end -function readers.loadshapes(filename,n) - local fontdata=loadfont { - filename=filename, - shapes=true, - subfont=n, - } - if fontdata then - for k,v in next,fontdata.glyphs do - v.class=nil - v.index=nil - v.math=nil - end - end - return fontdata and { - filename=filename, - format=fontdata.format, - glyphs=fontdata.glyphs, - units=fontdata.fontheader.units, - } or { - filename=filename, - format="unknown", - glyphs={}, - units=0, - } -end -function readers.loadfont(filename,n) - local fontdata=loadfont { - filename=filename, - glyphs=true, - shapes=false, - lookups=true, - subfont=n, - } - if fontdata then - return { - tableversion=tableversion, - creator="context mkiv", - size=fontdata.filesize, - time=fontdata.filetime, - glyphs=fontdata.glyphs, - descriptions=fontdata.descriptions, - format=fontdata.format, - goodies={}, - metadata=getinfo(fontdata,n,false,false,true), - properties={ - hasitalics=fontdata.hasitalics or false, - maxcolorclass=fontdata.maxcolorclass, - hascolor=fontdata.hascolor or false, - }, - resources={ - filename=filename, - private=privateoffset, - duplicates=fontdata.duplicates or {}, - features=fontdata.features or {}, - sublookups=fontdata.sublookups or {}, - marks=fontdata.marks or {}, - markclasses=fontdata.markclasses or {}, - marksets=fontdata.marksets or {}, - sequences=fontdata.sequences or {}, - variants=fontdata.variants, - version=getname(fontdata,"version"), - cidinfo=fontdata.cidinfo, - mathconstants=fontdata.mathconstants, - colorpalettes=fontdata.colorpalettes, - svgshapes=fontdata.svgshapes, - }, - } - end -end -function readers.getinfo(filename,specification) - local subfont=nil - local platformnames=false - local rawfamilynames=false - if type(specification)=="table" then - subfont=tonumber(specification.subfont) - platformnames=specification.platformnames - rawfamilynames=specification.rawfamilynames - else - subfont=tonumber(specification) - end - local fontdata=loadfont { - filename=filename, - details=true, - platformnames=platformnames, - } - if fontdata then - local subfonts=fontdata.subfonts - if not subfonts then - return getinfo(fontdata,nil,platformnames,rawfamilynames) - elseif not subfont then - local info={} - for i=1,#subfonts do - info[i]=getinfo(fontdata,i,platformnames,rawfamilynames) - end - return info - elseif subfont>=1 and subfont<=#subfonts then - return getinfo(fontdata,subfont,platformnames,rawfamilynames) - else - return { - filename=filename, - comment="there is no subfont "..subfont.." in this file" - } - end - else - return { - filename=filename, - comment="the file cannot be opened for reading", - } - end -end -function readers.rehash(fontdata,hashmethod) - report("the %a helper is not yet implemented","rehash") -end -function readers.checkhash(fontdata) - report("the %a helper is not yet implemented","checkhash") -end -function readers.pack(fontdata,hashmethod) - report("the %a helper is not yet implemented","pack") -end -function readers.unpack(fontdata) - report("the %a helper is not yet implemented","unpack") -end -function readers.expand(fontdata) - report("the %a helper is not yet implemented","unpack") -end -function readers.compact(fontdata) - report("the %a helper is not yet implemented","compact") -end -local extenders={} -function readers.registerextender(extender) - extenders[#extenders+1]=extender -end -function readers.extend(fontdata) - for i=1,#extenders do - local extender=extenders[i] - local name=extender.name or "unknown" - local action=extender.action - if action then - action(fontdata) - end - end -end - -end --- [luaotfload, fontloader-2017-02-11.lua scope for “font-otr”] --- - - -do --- [luaotfload, fontloader-2017-02-11.lua scope for “font-cff” f3fc74e8629f7a2825c34a34550c790d] --- - -if not modules then modules={} end modules ['font-cff']={ - version=1.001, - comment="companion to font-ini.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local next,type,tonumber=next,type,tonumber -local byte=string.byte -local concat,remove=table.concat,table.remove -local floor,abs,round,ceil=math.floor,math.abs,math.round,math.ceil -local P,C,R,S,C,Cs,Ct=lpeg.P,lpeg.C,lpeg.R,lpeg.S,lpeg.C,lpeg.Cs,lpeg.Ct -local lpegmatch=lpeg.match -local formatters=string.formatters -local readers=fonts.handlers.otf.readers -local streamreader=readers.streamreader -local readbytes=streamreader.readbytes -local readstring=streamreader.readstring -local readbyte=streamreader.readcardinal1 -local readushort=streamreader.readcardinal2 -local readuint=streamreader.readcardinal3 -local readulong=streamreader.readcardinal4 -local setposition=streamreader.setposition -local getposition=streamreader.getposition -local setmetatableindex=table.setmetatableindex -local trace_charstrings=false trackers.register("fonts.cff.charstrings",function(v) trace_charstrings=v end) -local report=logs.reporter("otf reader","cff") -local parsedictionaries -local parsecharstring -local parsecharstrings -local resetcharstrings -local parseprivates -local defaultstrings={ [0]= - ".notdef","space","exclam","quotedbl","numbersign","dollar","percent", - "ampersand","quoteright","parenleft","parenright","asterisk","plus", - "comma","hyphen","period","slash","zero","one","two","three","four", - "five","six","seven","eight","nine","colon","semicolon","less", - "equal","greater","question","at","A","B","C","D","E","F","G","H", - "I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W", - "X","Y","Z","bracketleft","backslash","bracketright","asciicircum", - "underscore","quoteleft","a","b","c","d","e","f","g","h","i","j", - "k","l","m","n","o","p","q","r","s","t","u","v","w","x","y", - "z","braceleft","bar","braceright","asciitilde","exclamdown","cent", - "sterling","fraction","yen","florin","section","currency", - "quotesingle","quotedblleft","guillemotleft","guilsinglleft", - "guilsinglright","fi","fl","endash","dagger","daggerdbl", - "periodcentered","paragraph","bullet","quotesinglbase","quotedblbase", - "quotedblright","guillemotright","ellipsis","perthousand","questiondown", - "grave","acute","circumflex","tilde","macron","breve","dotaccent", - "dieresis","ring","cedilla","hungarumlaut","ogonek","caron","emdash", - "AE","ordfeminine","Lslash","Oslash","OE","ordmasculine","ae", - "dotlessi","lslash","oslash","oe","germandbls","onesuperior", - "logicalnot","mu","trademark","Eth","onehalf","plusminus","Thorn", - "onequarter","divide","brokenbar","degree","thorn","threequarters", - "twosuperior","registered","minus","eth","multiply","threesuperior", - "copyright","Aacute","Acircumflex","Adieresis","Agrave","Aring", - "Atilde","Ccedilla","Eacute","Ecircumflex","Edieresis","Egrave", - "Iacute","Icircumflex","Idieresis","Igrave","Ntilde","Oacute", - "Ocircumflex","Odieresis","Ograve","Otilde","Scaron","Uacute", - "Ucircumflex","Udieresis","Ugrave","Yacute","Ydieresis","Zcaron", - "aacute","acircumflex","adieresis","agrave","aring","atilde", - "ccedilla","eacute","ecircumflex","edieresis","egrave","iacute", - "icircumflex","idieresis","igrave","ntilde","oacute","ocircumflex", - "odieresis","ograve","otilde","scaron","uacute","ucircumflex", - "udieresis","ugrave","yacute","ydieresis","zcaron","exclamsmall", - "Hungarumlautsmall","dollaroldstyle","dollarsuperior","ampersandsmall", - "Acutesmall","parenleftsuperior","parenrightsuperior","twodotenleader", - "onedotenleader","zerooldstyle","oneoldstyle","twooldstyle", - "threeoldstyle","fouroldstyle","fiveoldstyle","sixoldstyle", - "sevenoldstyle","eightoldstyle","nineoldstyle","commasuperior", - "threequartersemdash","periodsuperior","questionsmall","asuperior", - "bsuperior","centsuperior","dsuperior","esuperior","isuperior", - "lsuperior","msuperior","nsuperior","osuperior","rsuperior","ssuperior", - "tsuperior","ff","ffi","ffl","parenleftinferior","parenrightinferior", - "Circumflexsmall","hyphensuperior","Gravesmall","Asmall","Bsmall", - "Csmall","Dsmall","Esmall","Fsmall","Gsmall","Hsmall","Ismall", - "Jsmall","Ksmall","Lsmall","Msmall","Nsmall","Osmall","Psmall", - "Qsmall","Rsmall","Ssmall","Tsmall","Usmall","Vsmall","Wsmall", - "Xsmall","Ysmall","Zsmall","colonmonetary","onefitted","rupiah", - "Tildesmall","exclamdownsmall","centoldstyle","Lslashsmall", - "Scaronsmall","Zcaronsmall","Dieresissmall","Brevesmall","Caronsmall", - "Dotaccentsmall","Macronsmall","figuredash","hypheninferior", - "Ogoneksmall","Ringsmall","Cedillasmall","questiondownsmall","oneeighth", - "threeeighths","fiveeighths","seveneighths","onethird","twothirds", - "zerosuperior","foursuperior","fivesuperior","sixsuperior", - "sevensuperior","eightsuperior","ninesuperior","zeroinferior", - "oneinferior","twoinferior","threeinferior","fourinferior", - "fiveinferior","sixinferior","seveninferior","eightinferior", - "nineinferior","centinferior","dollarinferior","periodinferior", - "commainferior","Agravesmall","Aacutesmall","Acircumflexsmall", - "Atildesmall","Adieresissmall","Aringsmall","AEsmall","Ccedillasmall", - "Egravesmall","Eacutesmall","Ecircumflexsmall","Edieresissmall", - "Igravesmall","Iacutesmall","Icircumflexsmall","Idieresissmall", - "Ethsmall","Ntildesmall","Ogravesmall","Oacutesmall","Ocircumflexsmall", - "Otildesmall","Odieresissmall","OEsmall","Oslashsmall","Ugravesmall", - "Uacutesmall","Ucircumflexsmall","Udieresissmall","Yacutesmall", - "Thornsmall","Ydieresissmall","001.000","001.001","001.002","001.003", - "Black","Bold","Book","Light","Medium","Regular","Roman","Semibold", -} -local cffreaders={ - readbyte, - readushort, - readuint, - readulong, -} -local function readheader(f) - local offset=getposition(f) - local header={ - offset=offset, - major=readbyte(f), - minor=readbyte(f), - size=readbyte(f), - osize=readbyte(f), - } - setposition(f,offset+header.size) - return header -end -local function readlengths(f) - local count=readushort(f) - if count==0 then - return {} - end - local osize=readbyte(f) - local read=cffreaders[osize] - if not read then - report("bad offset size: %i",osize) - return {} - end - local lengths={} - local previous=read(f) - for i=1,count do - local offset=read(f) - lengths[i]=offset-previous - previous=offset - end - return lengths -end -local function readfontnames(f) - local names=readlengths(f) - for i=1,#names do - names[i]=readstring(f,names[i]) - end - return names -end -local function readtopdictionaries(f) - local dictionaries=readlengths(f) - for i=1,#dictionaries do - dictionaries[i]=readstring(f,dictionaries[i]) - end - return dictionaries -end -local function readstrings(f) - local lengths=readlengths(f) - local strings=setmetatableindex({},defaultstrings) - local index=#defaultstrings - for i=1,#lengths do - index=index+1 - strings[index]=readstring(f,lengths[i]) - end - return strings -end -do - local stack={} - local top=0 - local result={} - local strings={} - local p_single=P("\00")/function() - result.version=strings[stack[top]] or "unset" - top=0 - end+P("\01")/function() - result.notice=strings[stack[top]] or "unset" - top=0 - end+P("\02")/function() - result.fullname=strings[stack[top]] or "unset" - top=0 - end+P("\03")/function() - result.familyname=strings[stack[top]] or "unset" - top=0 - end+P("\04")/function() - result.weight=strings[stack[top]] or "unset" - top=0 - end+P("\05")/function() - result.fontbbox={ unpack(stack,1,4) } - top=0 - end -+P("\13")/function() - result.uniqueid=stack[top] - top=0 - end+P("\14")/function() - result.xuid=concat(stack,"",1,top) - top=0 - end+P("\15")/function() - result.charset=stack[top] - top=0 - end+P("\16")/function() - result.encoding=stack[top] - top=0 - end+P("\17")/function() - result.charstrings=stack[top] - top=0 - end+P("\18")/function() - result.private={ - size=stack[top-1], - offset=stack[top], - } - top=0 - end+P("\19")/function() - result.subroutines=stack[top] - end+P("\20")/function() - result.defaultwidthx=stack[top] - end+P("\21")/function() - result.nominalwidthx=stack[top] - end - local p_double=P("\12")*( - P("\00")/function() - result.copyright=stack[top] - top=0 - end+P("\01")/function() - result.monospaced=stack[top]==1 and true or false - top=0 - end+P("\02")/function() - result.italicangle=stack[top] - top=0 - end+P("\03")/function() - result.underlineposition=stack[top] - top=0 - end+P("\04")/function() - result.underlinethickness=stack[top] - top=0 - end+P("\05")/function() - result.painttype=stack[top] - top=0 - end+P("\06")/function() - result.charstringtype=stack[top] - top=0 - end+P("\07")/function() - result.fontmatrix={ unpack(stack,1,6) } - top=0 - end+P("\08")/function() - result.strokewidth=stack[top] - top=0 - end+P("\20")/function() - result.syntheticbase=stack[top] - top=0 - end+P("\21")/function() - result.postscript=strings[stack[top]] or "unset" - top=0 - end+P("\22")/function() - result.basefontname=strings[stack[top]] or "unset" - top=0 - end+P("\21")/function() - result.basefontblend=stack[top] - top=0 - end+P("\30")/function() - result.cid.registry=strings[stack[top-2]] or "unset" - result.cid.ordering=strings[stack[top-1]] or "unset" - result.cid.supplement=stack[top] - top=0 - end+P("\31")/function() - result.cid.fontversion=stack[top] - top=0 - end+P("\32")/function() - result.cid.fontrevision=stack[top] - top=0 - end+P("\33")/function() - result.cid.fonttype=stack[top] - top=0 - end+P("\34")/function() - result.cid.count=stack[top] - top=0 - end+P("\35")/function() - result.cid.uidbase=stack[top] - top=0 - end+P("\36")/function() - result.cid.fdarray=stack[top] - top=0 - end+P("\37")/function() - result.cid.fdselect=stack[top] - top=0 - end+P("\38")/function() - result.cid.fontname=strings[stack[top]] or "unset" - top=0 - end - ) - local p_last=P("\x0F")/"0"+P("\x1F")/"1"+P("\x2F")/"2"+P("\x3F")/"3"+P("\x4F")/"4"+P("\x5F")/"5"+P("\x6F")/"6"+P("\x7F")/"7"+P("\x8F")/"8"+P("\x9F")/"9"+P("\xAF")/""+P("\xBF")/""+P("\xCF")/""+P("\xDF")/""+P("\xEF")/""+R("\xF0\xFF")/"" - local remap={ - ["\x00"]="00",["\x01"]="01",["\x02"]="02",["\x03"]="03",["\x04"]="04",["\x05"]="05",["\x06"]="06",["\x07"]="07",["\x08"]="08",["\x09"]="09",["\x0A"]="0.",["\x0B"]="0E",["\x0C"]="0E-",["\x0D"]="0",["\x0E"]="0-",["\x0F"]="0", - ["\x10"]="10",["\x11"]="11",["\x12"]="12",["\x13"]="13",["\x14"]="14",["\x15"]="15",["\x16"]="16",["\x17"]="17",["\x18"]="18",["\x19"]="19",["\x1A"]="0.",["\x1B"]="0E",["\x1C"]="0E-",["\x1D"]="0",["\x1E"]="0-",["\x1F"]="0", - ["\x20"]="20",["\x21"]="21",["\x22"]="22",["\x23"]="23",["\x24"]="24",["\x25"]="25",["\x26"]="26",["\x27"]="27",["\x28"]="28",["\x29"]="29",["\x2A"]="0.",["\x2B"]="0E",["\x2C"]="0E-",["\x2D"]="0",["\x2E"]="0-",["\x2F"]="0", - ["\x30"]="30",["\x31"]="31",["\x32"]="32",["\x33"]="33",["\x34"]="34",["\x35"]="35",["\x36"]="36",["\x37"]="37",["\x38"]="38",["\x39"]="39",["\x3A"]="0.",["\x3B"]="0E",["\x3C"]="0E-",["\x3D"]="0",["\x3E"]="0-",["\x3F"]="0", - ["\x40"]="40",["\x41"]="41",["\x42"]="42",["\x43"]="43",["\x44"]="44",["\x45"]="45",["\x46"]="46",["\x47"]="47",["\x48"]="48",["\x49"]="49",["\x4A"]="0.",["\x4B"]="0E",["\x4C"]="0E-",["\x4D"]="0",["\x4E"]="0-",["\x4F"]="0", - ["\x50"]="50",["\x51"]="51",["\x52"]="52",["\x53"]="53",["\x54"]="54",["\x55"]="55",["\x56"]="56",["\x57"]="57",["\x58"]="58",["\x59"]="59",["\x5A"]="0.",["\x5B"]="0E",["\x5C"]="0E-",["\x5D"]="0",["\x5E"]="0-",["\x5F"]="0", - ["\x60"]="60",["\x61"]="61",["\x62"]="62",["\x63"]="63",["\x64"]="64",["\x65"]="65",["\x66"]="66",["\x67"]="67",["\x68"]="68",["\x69"]="69",["\x6A"]="0.",["\x6B"]="0E",["\x6C"]="0E-",["\x6D"]="0",["\x6E"]="0-",["\x6F"]="0", - ["\x70"]="70",["\x71"]="71",["\x72"]="72",["\x73"]="73",["\x74"]="74",["\x75"]="75",["\x76"]="76",["\x77"]="77",["\x78"]="78",["\x79"]="79",["\x7A"]="0.",["\x7B"]="0E",["\x7C"]="0E-",["\x7D"]="0",["\x7E"]="0-",["\x7F"]="0", - ["\x80"]="80",["\x81"]="81",["\x82"]="82",["\x83"]="83",["\x84"]="84",["\x85"]="85",["\x86"]="86",["\x87"]="87",["\x88"]="88",["\x89"]="89",["\x8A"]="0.",["\x8B"]="0E",["\x8C"]="0E-",["\x8D"]="0",["\x8E"]="0-",["\x8F"]="0", - ["\x90"]="90",["\x91"]="91",["\x92"]="92",["\x93"]="93",["\x94"]="94",["\x95"]="95",["\x96"]="96",["\x97"]="97",["\x98"]="98",["\x99"]="99",["\x9A"]="0.",["\x9B"]="0E",["\x9C"]="0E-",["\x9D"]="0",["\x9E"]="0-",["\x9F"]="0", - ["\xA0"]=".0",["\xA1"]=".1",["\xA2"]=".2",["\xA3"]=".3",["\xA4"]=".4",["\xA5"]=".5",["\xA6"]=".6",["\xA7"]=".7",["\xA8"]=".8",["\xA9"]=".9",["\xAA"]="..",["\xAB"]=".E",["\xAC"]=".E-",["\xAD"]=".",["\xAE"]=".-",["\xAF"]=".", - ["\xB0"]="E0",["\xB1"]="E1",["\xB2"]="E2",["\xB3"]="E3",["\xB4"]="E4",["\xB5"]="E5",["\xB6"]="E6",["\xB7"]="E7",["\xB8"]="E8",["\xB9"]="E9",["\xBA"]="E.",["\xBB"]="EE",["\xBC"]="EE-",["\xBD"]="E",["\xBE"]="E-",["\xBF"]="E", - ["\xC0"]="E-0",["\xC1"]="E-1",["\xC2"]="E-2",["\xC3"]="E-3",["\xC4"]="E-4",["\xC5"]="E-5",["\xC6"]="E-6",["\xC7"]="E-7",["\xC8"]="E-8",["\xC9"]="E-9",["\xCA"]="E-.",["\xCB"]="E-E",["\xCC"]="E-E-",["\xCD"]="E-",["\xCE"]="E--",["\xCF"]="E-", - ["\xD0"]="-0",["\xD1"]="-1",["\xD2"]="-2",["\xD3"]="-3",["\xD4"]="-4",["\xD5"]="-5",["\xD6"]="-6",["\xD7"]="-7",["\xD8"]="-8",["\xD9"]="-9",["\xDA"]="-.",["\xDB"]="-E",["\xDC"]="-E-",["\xDD"]="-",["\xDE"]="--",["\xDF"]="-", - } - local p_nibbles=P("\30")*Cs(((1-p_last)/remap)^0+p_last)/function(n) - top=top+1 - stack[top]=tonumber(n) or 0 - end - local p_byte=C(R("\32\246"))/function(b0) - top=top+1 - stack[top]=byte(b0)-139 - end - local p_positive=C(R("\247\250"))*C(1)/function(b0,b1) - top=top+1 - stack[top]=(byte(b0)-247)*256+byte(b1)+108 - end - local p_negative=C(R("\251\254"))*C(1)/function(b0,b1) - top=top+1 - stack[top]=-(byte(b0)-251)*256-byte(b1)-108 - end - local p_short=P("\28")*C(1)*C(1)/function(b1,b2) - top=top+1 - local n=0x100*byte(b1)+byte(b2) - if n>=0x8000 then - stack[top]=n-0xFFFF-1 - else - stack[top]=n - end - end - local p_long=P("\29")*C(1)*C(1)*C(1)*C(1)/function(b1,b2,b3,b4) - top=top+1 - local n=0x1000000*byte(b1)+0x10000*byte(b2)+0x100*byte(b3)+byte(b4) - if n>=0x8000000 then - stack[top]=n-0xFFFFFFFF-1 - else - stack[top]=n - end - end - local p_unsupported=P(1)/function(detail) - top=0 - end - local p_dictionary=( - p_byte+p_positive+p_negative+p_short+p_long+p_nibbles+p_single+p_double+p_unsupported - )^1 - parsedictionaries=function(data,dictionaries) - stack={} - strings=data.strings - for i=1,#dictionaries do - top=0 - result={ - monospaced=false, - italicangle=0, - underlineposition=-100, - underlinethickness=50, - painttype=0, - charstringtype=2, - fontmatrix={ 0.001,0,0,0.001,0,0 }, - fontbbox={ 0,0,0,0 }, - strokewidth=0, - charset=0, - encoding=0, - cid={ - fontversion=0, - fontrevision=0, - fonttype=0, - count=8720, - } - } - lpegmatch(p_dictionary,dictionaries[i]) - dictionaries[i]=result - end - result={} - top=0 - stack={} - end - parseprivates=function(data,dictionaries) - stack={} - strings=data.strings - for i=1,#dictionaries do - local private=dictionaries[i].private - if private and private.data then - top=0 - result={ - forcebold=false, - languagegroup=0, - expansionfactor=0.06, - initialrandomseed=0, - subroutines=0, - defaultwidthx=0, - nominalwidthx=0, - cid={ - }, - } - lpegmatch(p_dictionary,private.data) - private.data=result - end - end - result={} - top=0 - stack={} - end - local x=0 - local y=0 - local width=false - local r=0 - local stems=0 - local globalbias=0 - local localbias=0 - local globals=false - local locals=false - local depth=1 - local xmin=0 - local xmax=0 - local ymin=0 - local ymax=0 - local checked=false - local keepcurve=false - local version=2 - local function showstate(where) - report("%w%-10s : [%s] n=%i",depth*2,where,concat(stack," ",1,top),top) - end - local function showvalue(where,value,showstack) - if showstack then - report("%w%-10s : %s : [%s] n=%i",depth*2,where,tostring(value),concat(stack," ",1,top),top) - else - report("%w%-10s : %s",depth*2,where,tostring(value)) - end - end - local function moveto(x,y) - if keepcurve then - r=r+1 - result[r]={ x,y,"m" } - end - if checked then - if x<xmin then xmin=x elseif x>xmax then xmax=x end - if y<ymin then ymin=y elseif y>ymax then ymax=y end - else - xmin=x - ymin=y - xmax=x - ymax=y - checked=true - end - end - local function lineto(x,y) - if keepcurve then - r=r+1 - result[r]={ x,y,"l" } - end - if checked then - if x<xmin then xmin=x elseif x>xmax then xmax=x end - if y<ymin then ymin=y elseif y>ymax then ymax=y end - else - xmin=x - ymin=y - xmax=x - ymax=y - checked=true - end - end - local function curveto(x1,y1,x2,y2,x3,y3) - if keepcurve then - r=r+1 - result[r]={ x1,y1,x2,y2,x3,y3,"c" } - end - if checked then - if x1<xmin then xmin=x1 elseif x1>xmax then xmax=x1 end - if y1<ymin then ymin=y1 elseif y1>ymax then ymax=y1 end - else - xmin=x1 - ymin=y1 - xmax=x1 - ymax=y1 - checked=true - end - if x2<xmin then xmin=x2 elseif x2>xmax then xmax=x2 end - if y2<ymin then ymin=y2 elseif y2>ymax then ymax=y2 end - if x3<xmin then xmin=x3 elseif x3>xmax then xmax=x3 end - if y3<ymin then ymin=y3 elseif y3>ymax then ymax=y3 end - end - local function rmoveto() - if top>2 then - if not width then - width=stack[1] - if trace_charstrings then - showvalue("width",width) - end - end - elseif not width then - width=true - end - if trace_charstrings then - showstate("rmoveto") - end - x=x+stack[top-1] - y=y+stack[top] - top=0 - moveto(x,y) - end - local function hmoveto() - if top>1 then - if not width then - width=stack[1] - if trace_charstrings then - showvalue("width",width) - end - end - elseif not width then - width=true - end - if trace_charstrings then - showstate("hmoveto") - end - x=x+stack[top] - top=0 - moveto(x,y) - end - local function vmoveto() - if top>1 then - if not width then - width=stack[1] - if trace_charstrings then - showvalue("width",width) - end - end - elseif not width then - width=true - end - if trace_charstrings then - showstate("vmoveto") - end - y=y+stack[top] - top=0 - moveto(x,y) - end - local function rlineto() - if trace_charstrings then - showstate("rlineto") - end - for i=1,top,2 do - x=x+stack[i] - y=y+stack[i+1] - lineto(x,y) - end - top=0 - end - local function xlineto(swap) - for i=1,top do - if swap then - x=x+stack[i] - swap=false - else - y=y+stack[i] - swap=true - end - lineto(x,y) - end - top=0 - end - local function hlineto() - if trace_charstrings then - showstate("hlineto") - end - xlineto(true) - end - local function vlineto() - if trace_charstrings then - showstate("vlineto") - end - xlineto(false) - end - local function rrcurveto() - if trace_charstrings then - showstate("rrcurveto") - end - for i=1,top,6 do - local ax=x+stack[i] - local ay=y+stack[i+1] - local bx=ax+stack[i+2] - local by=ay+stack[i+3] - x=bx+stack[i+4] - y=by+stack[i+5] - curveto(ax,ay,bx,by,x,y) - end - top=0 - end - local function hhcurveto() - if trace_charstrings then - showstate("hhcurveto") - end - local s=1 - if top%2~=0 then - y=y+stack[1] - s=2 - end - for i=s,top,4 do - local ax=x+stack[i] - local ay=y - local bx=ax+stack[i+1] - local by=ay+stack[i+2] - x=bx+stack[i+3] - y=by - curveto(ax,ay,bx,by,x,y) - end - top=0 - end - local function vvcurveto() - if trace_charstrings then - showstate("vvcurveto") - end - local s=1 - local d=0 - if top%2~=0 then - d=stack[1] - s=2 - end - for i=s,top,4 do - local ax=x+d - local ay=y+stack[i] - local bx=ax+stack[i+1] - local by=ay+stack[i+2] - x=bx - y=by+stack[i+3] - curveto(ax,ay,bx,by,x,y) - d=0 - end - top=0 - end - local function xxcurveto(swap) - local last=top%4~=0 and stack[top] - if last then - top=top-1 - end - local sw=swap - for i=1,top,4 do - local ax,ay,bx,by - if swap then - ax=x+stack[i] - ay=y - bx=ax+stack[i+1] - by=ay+stack[i+2] - y=by+stack[i+3] - if last and i+3==top then - x=bx+last - else - x=bx - end - swap=false - else - ax=x - ay=y+stack[i] - bx=ax+stack[i+1] - by=ay+stack[i+2] - x=bx+stack[i+3] - if last and i+3==top then - y=by+last - else - y=by - end - swap=true - end - curveto(ax,ay,bx,by,x,y) - end - top=0 - end - local function hvcurveto() - if trace_charstrings then - showstate("hvcurveto") - end - xxcurveto(true) - end - local function vhcurveto() - if trace_charstrings then - showstate("vhcurveto") - end - xxcurveto(false) - end - local function rcurveline() - if trace_charstrings then - showstate("rcurveline") - end - for i=1,top-2,6 do - local ax=x+stack[i] - local ay=y+stack[i+1] - local bx=ax+stack[i+2] - local by=ay+stack[i+3] - x=bx+stack[i+4] - y=by+stack[i+5] - curveto(ax,ay,bx,by,x,y) - end - x=x+stack[top-1] - y=y+stack[top] - lineto(x,y) - top=0 - end - local function rlinecurve() - if trace_charstrings then - showstate("rlinecurve") - end - if top>6 then - for i=1,top-6,2 do - x=x+stack[i] - y=y+stack[i+1] - lineto(x,y) - end - end - local ax=x+stack[top-5] - local ay=y+stack[top-4] - local bx=ax+stack[top-3] - local by=ay+stack[top-2] - x=bx+stack[top-1] - y=by+stack[top] - curveto(ax,ay,bx,by,x,y) - top=0 - end - local function flex() - if trace_charstrings then - showstate("flex") - end - local ax=x+stack[1] - local ay=y+stack[2] - local bx=ax+stack[3] - local by=ay+stack[4] - local cx=bx+stack[5] - local cy=by+stack[6] - curveto(ax,ay,bx,by,cx,cy) - local dx=cx+stack[7] - local dy=cy+stack[8] - local ex=dx+stack[9] - local ey=dy+stack[10] - x=ex+stack[11] - y=ey+stack[12] - curveto(dx,dy,ex,ey,x,y) - top=0 - end - local function hflex() - if trace_charstrings then - showstate("hflex") - end - local ax=x+stack[1] - local ay=y - local bx=ax+stack[2] - local by=ay+stack[3] - local cx=bx+stack[4] - local cy=by - curveto(ax,ay,bx,by,cx,cy) - local dx=cx+stack[5] - local dy=by - local ex=dx+stack[6] - local ey=y - x=ex+stack[7] - curveto(dx,dy,ex,ey,x,y) - top=0 - end - local function hflex1() - if trace_charstrings then - showstate("hflex1") - end - local ax=x+stack[1] - local ay=y+stack[2] - local bx=ax+stack[3] - local by=ay+stack[4] - local cx=bx+stack[5] - local cy=by - curveto(ax,ay,bx,by,cx,cy) - local dx=cx+stack[6] - local dy=by - local ex=dx+stack[7] - local ey=dy+stack[8] - x=ex+stack[9] - curveto(dx,dy,ex,ey,x,y) - top=0 - end - local function flex1() - if trace_charstrings then - showstate("flex1") - end - local ax=x+stack[1] - local ay=y+stack[2] - local bx=ax+stack[3] - local by=ay+stack[4] - local cx=bx+stack[5] - local cy=by+stack[6] - curveto(ax,ay,bx,by,cx,cy) - local dx=cx+stack[7] - local dy=cy+stack[8] - local ex=dx+stack[9] - local ey=dy+stack[10] - if abs(ex-x)>abs(ey-y) then - x=ex+stack[11] - else - y=ey+stack[11] - end - curveto(dx,dy,ex,ey,x,y) - top=0 - end - local function getstem() - if top==0 then - elseif top%2~=0 then - if width then - remove(stack,1) - else - width=remove(stack,1) - if trace_charstrings then - showvalue("width",width) - end - end - top=top-1 - end - if trace_charstrings then - showstate("stem") - end - stems=stems+top/2 - top=0 - end - local function getmask() - if top==0 then - elseif top%2~=0 then - if width then - remove(stack,1) - else - width=remove(stack,1) - if trace_charstrings then - showvalue("width",width) - end - end - top=top-1 - end - if trace_charstrings then - showstate(operator==19 and "hintmark" or "cntrmask") - end - stems=stems+top/2 - top=0 - if stems==0 then - elseif stems<=8 then - return 1 - else - return floor((stems+7)/8) - end - end - local function unsupported(t) - if trace_charstrings then - showstate("unsupported "..t) - end - top=0 - end - local function unsupportedsub(t) - if trace_charstrings then - showstate("unsupported sub "..t) - end - top=0 - end - local function getstem3() - if trace_charstrings then - showstate("stem3") - end - top=0 - end - local function divide() - if version==1 then - local d=stack[top] - top=top-1 - stack[top]=stack[top]/d - end - end - local function closepath() - if version==1 then - if trace_charstrings then - showstate("closepath") - end - end - top=0 - end - local function hsbw() - if version==1 then - if trace_charstrings then - showstate("dotsection") - end - width=stack[top] - end - top=0 - end - local function seac() - if version==1 then - if trace_charstrings then - showstate("seac") - end - end - top=0 - end - local function sbw() - if version==1 then - if trace_charstrings then - showstate("sbw") - end - width=stack[top-1] - end - top=0 - end - local function callothersubr() - if version==1 then - if trace_charstrings then - showstate("callothersubr (unsupported)") - end - end - top=0 - end - local function pop() - if version==1 then - if trace_charstrings then - showstate("pop (unsupported)") - end - top=top+1 - stack[top]=0 - else - top=0 - end - end - local function setcurrentpoint() - if version==1 then - if trace_charstrings then - showstate("pop (unsupported)") - end - x=x+stack[top-1] - y=y+stack[top] - end - top=0 - end - local actions={ [0]=unsupported, - getstem, - unsupported, - getstem, - vmoveto, - rlineto, - hlineto, - vlineto, - rrcurveto, - unsupported, - unsupported, - unsupported, - unsupported, - hsbw, - unsupported, - unsupported, - unsupported, - unsupported, - getstem, - getmask, - getmask, - rmoveto, - hmoveto, - getstem, - rcurveline, - rlinecurve, - vvcurveto, - hhcurveto, - unsupported, - unsupported, - vhcurveto, - hvcurveto, - } - local subactions={ - [000]=dotsection, - [001]=getstem3, - [002]=getstem3, - [006]=seac, - [007]=sbw, - [012]=divide, - [016]=callothersubr, - [017]=pop, - [033]=setcurrentpoint, - [034]=hflex, - [035]=flex, - [036]=hflex1, - [037]=flex1, - } - local p_bytes=Ct((P(1)/byte)^0) - local function call(scope,list,bias,process) - depth=depth+1 - if top==0 then - showstate(formatters["unknown %s call"](scope)) - top=0 - else - local index=stack[top]+bias - top=top-1 - if trace_charstrings then - showvalue(scope,index,true) - end - local tab=list[index] - if tab then - if type(tab)=="string" then - tab=lpegmatch(p_bytes,tab) - list[index]=tab - end - process(tab) - else - showstate(formatters["unknown %s call %i"](scope,index)) - top=0 - end - end - depth=depth-1 - end - local function process(tab) - local i=1 - local n=#tab - while i<=n do - local t=tab[i] - if t>=32 and t<=246 then - top=top+1 - stack[top]=t-139 - i=i+1 - elseif t>=247 and t<=250 then - top=top+1 - stack[top]=(t-247)*256+tab[i+1]+108 - i=i+2 - elseif t>=251 and t<=254 then - top=top+1 - stack[top]=-(t-251)*256-tab[i+1]-108 - i=i+2 - elseif t==28 then - top=top+1 - local n=0x100*tab[i+1]+tab[i+2] - if n>=0x8000 then - stack[top]=n-0xFFFF-1 - else - stack[top]=n - end - i=i+3 - elseif t==255 then - local n=0x100*tab[i+1]+tab[i+2] - top=top+1 - if n>=0x8000 then - stack[top]=n-0xFFFF-1+(0x100*tab[i+3]+tab[i+4])/0xFFFF - else - stack[top]=n+(0x100*tab[i+3]+tab[i+4])/0xFFFF - end - i=i+5 - elseif t==11 then - if trace_charstrings then - showstate("return") - end - return - elseif t==10 then - call("local",locals,localbias,process) - i=i+1 - elseif t==14 then - if width then - elseif top>0 then - width=stack[1] - if trace_charstrings then - showvalue("width",width) - end - else - width=true - end - if trace_charstrings then - showstate("endchar") - end - return - elseif t==29 then - call("global",globals,globalbias,process) - i=i+1 - elseif t==12 then - i=i+1 - local t=tab[i] - local a=subactions[t] - if a then - a(t) - else - if trace_charstrings then - showvalue("<subaction>",t) - end - top=0 - end - i=i+1 - else - local a=actions[t] - if a then - local s=a(t) - if s then - i=i+s - end - else - if trace_charstrings then - showvalue("<action>",t) - end - top=0 - end - i=i+1 - end - end - end - local function setbias(globals,locals) - if version==1 then - return - false, - false - else - local g,l=#globals,#locals - return - ((g<1240 and 107) or (g<33900 and 1131) or 32768)+1, - ((l<1240 and 107) or (l<33900 and 1131) or 32768)+1 - end - end - parsecharstrings=function(data,glyphs,doshapes,tversion) - local dictionary=data.dictionaries[1] - local charstrings=dictionary.charstrings - local charset=dictionary.charset - local private=dictionary.private or { data={} } - keepcurve=doshapes - version=tversion - stack={} - glyphs=glyphs or {} - strings=data.strings - globals=data.routines or {} - locals=dictionary.subroutines or {} - globalbias,localbias=setbias(globals,locals) - local nominalwidth=private.data.nominalwidthx or 0 - local defaultwidth=private.data.defaultwidthx or 0 - for i=1,#charstrings do - local tab=charstrings[i] - if type(tab)=="string" then - tab=lpegmatch(p_bytes,tab) - end - local index=i-1 - x=0 - y=0 - width=false - r=0 - top=0 - stems=0 - result={} - xmin=0 - xmax=0 - ymin=0 - ymax=0 - checked=false - if trace_charstrings then - report("glyph: %i",index) - report("data: % t",tab) - end - process(tab) - local boundingbox={ round(xmin),round(ymin),round(xmax),round(ymax) } - if width==true or width==false then - width=defaultwidth - else - width=nominalwidth+width - end - local glyph=glyphs[index] - if not glyph then - glyphs[index]={ - segments=doshapes~=false and result or nil, - boundingbox=boundingbox, - width=width, - name=charset[index], - } - else - glyph.segments=doshapes~=false and result or nil - glyph.boundingbox=boundingbox - if not glyph.width then - glyph.width=width - end - if charset and not glyph.name then - glyph.name=charset[index] - end - end - if trace_charstrings then - report("width: %s",tostring(width)) - report("boundingbox: % t",boundingbox) - end - charstrings[i]=nil - end - return glyphs - end - parsecharstring=function(data,dictionary,tab,glyphs,index,doshapes,tversion) - local private=dictionary.private - keepcurve=doshapes - version=tversion - strings=data.strings - locals=dictionary.subroutines or {} - globals=data.routines or {} - globalbias,localbias=setbias(globals,locals) - local nominalwidth=private and private.data.nominalwidthx or 0 - local defaultwidth=private and private.data.defaultwidthx or 0 - if type(tab)=="string" then - tab=lpegmatch(p_bytes,tab) - end - x=0 - y=0 - width=false - r=0 - top=0 - stems=0 - result={} - xmin=0 - xmax=0 - ymin=0 - ymax=0 - checked=false - if trace_charstrings then - report("glyph: %i",index) - report("data: % t",tab) - end - process(tab) - local boundingbox={ xmin,ymin,xmax,ymax } - if width==true or width==false then - width=defaultwidth - else - width=nominalwidth+width - end - index=index-1 - local glyph=glyphs[index] - if not glyph then - glyphs[index]={ - segments=doshapes~=false and result or nil, - boundingbox=boundingbox, - width=width, - name=charset[index], - } - else - glyph.segments=doshapes~=false and result or nil - glyph.boundingbox=boundingbox - if not glyph.width then - glyph.width=width - end - if charset and not glyph.name then - glyph.name=charset[index] - end - end - if trace_charstrings then - report("width: %s",tostring(width)) - report("boundingbox: % t",boundingbox) - end - end - resetcharstrings=function() - result={} - top=0 - stack={} - end -end -local function readglobals(f,data) - local routines=readlengths(f) - for i=1,#routines do - routines[i]=readstring(f,routines[i]) - end - data.routines=routines -end -local function readencodings(f,data) - data.encodings={} -end -local function readcharsets(f,data,dictionary) - local header=data.header - local strings=data.strings - local nofglyphs=data.nofglyphs - local charsetoffset=dictionary.charset - if charsetoffset~=0 then - setposition(f,header.offset+charsetoffset) - local format=readbyte(f) - local charset={ [0]=".notdef" } - dictionary.charset=charset - if format==0 then - for i=1,nofglyphs do - charset[i]=strings[readushort(f)] - end - elseif format==1 or format==2 then - local readcount=format==1 and readbyte or readushort - local i=1 - while i<=nofglyphs do - local sid=readushort(f) - local n=readcount(f) - for s=sid,sid+n do - charset[i]=strings[s] - i=i+1 - if i>nofglyphs then - break - end - end - end - else - report("cff parser: unsupported charset format %a",format) - end - end -end -local function readprivates(f,data) - local header=data.header - local dictionaries=data.dictionaries - local private=dictionaries[1].private - if private then - setposition(f,header.offset+private.offset) - private.data=readstring(f,private.size) - end -end -local function readlocals(f,data,dictionary) - local header=data.header - local private=dictionary.private - if private then - local subroutineoffset=private.data.subroutines - if subroutineoffset~=0 then - setposition(f,header.offset+private.offset+subroutineoffset) - local subroutines=readlengths(f) - for i=1,#subroutines do - subroutines[i]=readstring(f,subroutines[i]) - end - dictionary.subroutines=subroutines - private.data.subroutines=nil - else - dictionary.subroutines={} - end - else - dictionary.subroutines={} - end -end -local function readcharstrings(f,data) - local header=data.header - local dictionaries=data.dictionaries - local dictionary=dictionaries[1] - local type=dictionary.charstringtype - local offset=dictionary.charstrings - if type==2 then - setposition(f,header.offset+offset) - local charstrings=readlengths(f) - local nofglyphs=#charstrings - for i=1,nofglyphs do - charstrings[i]=readstring(f,charstrings[i]) - end - data.nofglyphs=nofglyphs - dictionary.charstrings=charstrings - else - report("unsupported charstr type %i",type) - data.nofglyphs=0 - dictionary.charstrings={} - end -end -local function readcidprivates(f,data) - local header=data.header - local dictionaries=data.dictionaries[1].cid.dictionaries - for i=1,#dictionaries do - local dictionary=dictionaries[i] - local private=dictionary.private - if private then - setposition(f,header.offset+private.offset) - private.data=readstring(f,private.size) - end - end - parseprivates(data,dictionaries) -end -local function readnoselect(f,data,glyphs,doshapes,version) - local dictionaries=data.dictionaries - local dictionary=dictionaries[1] - readglobals(f,data) - readcharstrings(f,data) - readencodings(f,data) - readcharsets(f,data,dictionary) - readprivates(f,data) - parseprivates(data,data.dictionaries) - readlocals(f,data,dictionary) - parsecharstrings(data,glyphs,doshapes,version) - resetcharstrings() -end -readers.parsecharstrings=parsecharstrings -local function readfdselect(f,data,glyphs,doshapes,version) - local header=data.header - local dictionaries=data.dictionaries - local dictionary=dictionaries[1] - local cid=dictionary.cid - local cidselect=cid and cid.fdselect - readglobals(f,data) - readcharstrings(f,data) - readencodings(f,data) - local charstrings=dictionary.charstrings - local fdindex={} - local nofglyphs=data.nofglyphs - local maxindex=-1 - setposition(f,header.offset+cidselect) - local format=readbyte(f) - if format==1 then - for i=0,nofglyphs do - local index=readbyte(i) - fdindex[i]=index - if index>maxindex then - maxindex=index - end - end - elseif format==3 then - local nofranges=readushort(f) - local first=readushort(f) - local index=readbyte(f) - while true do - local last=readushort(f) - if index>maxindex then - maxindex=index - end - for i=first,last do - fdindex[i]=index - end - if last>=nofglyphs then - break - else - first=last+1 - index=readbyte(f) - end - end - else - end - if maxindex>=0 then - local cidarray=cid.fdarray - setposition(f,header.offset+cidarray) - local dictionaries=readlengths(f) - for i=1,#dictionaries do - dictionaries[i]=readstring(f,dictionaries[i]) - end - parsedictionaries(data,dictionaries) - cid.dictionaries=dictionaries - readcidprivates(f,data) - for i=1,#dictionaries do - readlocals(f,data,dictionaries[i]) - end - for i=1,#charstrings do - parsecharstring(data,dictionaries[fdindex[i]+1],charstrings[i],glyphs,i,doshapes,version) - end - resetcharstrings() - end -end -function readers.cff(f,fontdata,specification) - if specification.details then - local datatable=fontdata.tables.cff - if datatable then - local offset=datatable.offset - local glyphs=fontdata.glyphs - if not f then - report("invalid filehandle") - return - end - if offset then - setposition(f,offset) - end - local header=readheader(f) - if header.major>1 then - report("version mismatch") - return - end - local names=readfontnames(f) - local dictionaries=readtopdictionaries(f) - local strings=readstrings(f) - local data={ - header=header, - names=names, - dictionaries=dictionaries, - strings=strings, - nofglyphs=fontdata.nofglyphs, - } - parsedictionaries(data,data.dictionaries) - local d=dictionaries[1] - local c=d.cid - fontdata.cffinfo={ - familynamename=d.familyname, - fullname=d.fullname, - boundingbox=d.boundingbox, - weight=d.weight, - italicangle=d.italicangle, - underlineposition=d.underlineposition, - underlinethickness=d.underlinethickness, - monospaced=d.monospaced, - } - fontdata.cidinfo=c and { - registry=c.registry, - ordering=c.ordering, - supplement=c.supplement, - } - if not specification.glyphs then - else - local cid=d.cid - if cid and cid.fdselect then - readfdselect(f,data,glyphs,specification.shapes or false) - else - readnoselect(f,data,glyphs,specification.shapes or false) - end - end - end - end -end - -end --- [luaotfload, fontloader-2017-02-11.lua scope for “font-cff”] --- - - -do --- [luaotfload, fontloader-2017-02-11.lua scope for “font-ttf” e0893de6d0f3f421ee4386fa90429db8] --- - -if not modules then modules={} end modules ['font-ttf']={ - version=1.001, - comment="companion to font-ini.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local next,type,unpack=next,type,unpack -local bittest=bit32.btest -local sqrt=math.sqrt -local report=logs.reporter("otf reader","ttf") -local readers=fonts.handlers.otf.readers -local streamreader=readers.streamreader -local setposition=streamreader.setposition -local getposition=streamreader.getposition -local skipbytes=streamreader.skip -local readbyte=streamreader.readcardinal1 -local readushort=streamreader.readcardinal2 -local readulong=streamreader.readcardinal4 -local readchar=streamreader.readinteger1 -local readshort=streamreader.readinteger2 -local read2dot14=streamreader.read2dot14 -local function mergecomposites(glyphs,shapes) - local function merge(index,shape,components) - local contours={} - local nofcontours=0 - for i=1,#components do - local component=components[i] - local subindex=component.index - local subshape=shapes[subindex] - local subcontours=subshape.contours - if not subcontours then - local subcomponents=subshape.components - if subcomponents then - subcontours=merge(subindex,subshape,subcomponents) - end - end - if subcontours then - local matrix=component.matrix - local xscale=matrix[1] - local xrotate=matrix[2] - local yrotate=matrix[3] - local yscale=matrix[4] - local xoffset=matrix[5] - local yoffset=matrix[6] - for i=1,#subcontours do - local points=subcontours[i] - local result={} - for i=1,#points do - local p=points[i] - local x=p[1] - local y=p[2] - result[i]={ - xscale*x+xrotate*y+xoffset, - yscale*y+yrotate*x+yoffset, - p[3] - } - end - nofcontours=nofcontours+1 - contours[nofcontours]=result - end - else - report("missing contours composite %s, component %s of %s, glyph %s",index,i,#components,subindex) - end - end - shape.contours=contours - shape.components=nil - return contours - end - for index=1,#glyphs do - local shape=shapes[index] - local components=shape.components - if components then - merge(index,shape,components) - end - end -end -local function readnothing(f,nofcontours) - return { - type="nothing", - } -end -local function curveto(m_x,m_y,l_x,l_y,r_x,r_y) - return { - l_x+2/3*(m_x-l_x),l_y+2/3*(m_y-l_y), - r_x+2/3*(m_x-r_x),r_y+2/3*(m_y-r_y), - r_x,r_y,"c" - } -end -local function contours2outlines(glyphs,shapes) - local quadratic=true - for index=1,#glyphs do - local glyph=glyphs[index] - local shape=shapes[index] - local contours=shape.contours - if contours then - local nofcontours=#contours - local segments={} - local nofsegments=0 - glyph.segments=segments - if nofcontours>0 then - for i=1,nofcontours do - local contour=contours[i] - local nofcontour=#contour - if nofcontour>0 then - local first_pt=contour[1] - local first_on=first_pt[3] - if nofcontour==1 then - first_pt[3]="m" - nofsegments=nofsegments+1 - segments[nofsegments]=first_pt - else - local first_on=first_pt[3] - local last_pt=contour[nofcontour] - local last_on=last_pt[3] - local start=1 - local control_pt=false - if first_on then - start=2 - else - if last_on then - first_pt=last_pt - else - first_pt={ (first_pt[1]+last_pt[1])/2,(first_pt[2]+last_pt[2])/2,false } - end - control_pt=first_pt - end - nofsegments=nofsegments+1 - segments[nofsegments]={ first_pt[1],first_pt[2],"m" } - local previous_pt=first_pt - for i=start,nofcontour do - local current_pt=contour[i] - local current_on=current_pt[3] - local previous_on=previous_pt[3] - if previous_on then - if current_on then - nofsegments=nofsegments+1 - segments[nofsegments]={ current_pt[1],current_pt[2],"l" } - else - control_pt=current_pt - end - elseif current_on then - local ps=segments[nofsegments] - nofsegments=nofsegments+1 - if quadratic then - segments[nofsegments]={ control_pt[1],control_pt[2],current_pt[1],current_pt[2],"q" } - else - local p=segments[nofsegments-1] local n=#p - segments[nofsegments]=curveto(control_pt[1],control_pt[2],p[n-2],p[n-1],current_pt[1],current_pt[2]) - end - control_pt=false - else - nofsegments=nofsegments+1 - local halfway_x=(previous_pt[1]+current_pt[1])/2 - local halfway_y=(previous_pt[2]+current_pt[2])/2 - if quadratic then - segments[nofsegments]={ control_pt[1],control_pt[2],halfway_x,halfway_y,"q" } - else - local p=segments[nofsegments-1] local n=#p - segments[nofsegments]=curveto(control_pt[1],control_pt[2],p[n-2],p[n-1],halfway_x,halfway_y) - end - control_pt=current_pt - end - previous_pt=current_pt - end - if first_pt==last_pt then - else - nofsegments=nofsegments+1 - if not control_pt then - segments[nofsegments]={ first_pt[1],first_pt[2],"l" } - elseif quadratic then - segments[nofsegments]={ control_pt[1],control_pt[2],first_pt[1],first_pt[2],"q" } - else - local p=last_pt local n=#p - segments[nofsegments]=curveto(control_pt[1],control_pt[2],p[n-2],p[n-1],first_pt[1],first_pt[2]) - end - end - end - end - end - end - end - end -end -local function readglyph(f,nofcontours) - local points={} - local endpoints={} - local instructions={} - local flags={} - for i=1,nofcontours do - endpoints[i]=readshort(f)+1 - end - local nofpoints=endpoints[nofcontours] - local nofinstructions=readushort(f) - skipbytes(f,nofinstructions) - local i=1 - while i<=nofpoints do - local flag=readbyte(f) - flags[i]=flag - if bittest(flag,0x0008) then - for j=1,readbyte(f) do - i=i+1 - flags[i]=flag - end - end - i=i+1 - end - local x=0 - for i=1,nofpoints do - local flag=flags[i] - local short=bittest(flag,0x0002) - local same=bittest(flag,0x0010) - if short then - if same then - x=x+readbyte(f) - else - x=x-readbyte(f) - end - elseif same then - else - x=x+readshort(f) - end - points[i]={ x,y,bittest(flag,0x0001) } - end - local y=0 - for i=1,nofpoints do - local flag=flags[i] - local short=bittest(flag,0x0004) - local same=bittest(flag,0x0020) - if short then - if same then - y=y+readbyte(f) - else - y=y-readbyte(f) - end - elseif same then - else - y=y+readshort(f) - end - points[i][2]=y - end - local first=1 - for i=1,#endpoints do - local last=endpoints[i] - endpoints[i]={ unpack(points,first,last) } - first=last+1 - end - return { - type="glyph", - contours=endpoints, - } -end -local function readcomposite(f) - local components={} - local nofcomponents=0 - local instructions=false - while true do - local flags=readushort(f) - local index=readushort(f) - local f_xyarg=bittest(flags,0x0002) - local f_offset=bittest(flags,0x0800) - local xscale=1 - local xrotate=0 - local yrotate=0 - local yscale=1 - local xoffset=0 - local yoffset=0 - local base=false - local reference=false - if f_xyarg then - if bittest(flags,0x0001) then - xoffset=readshort(f) - yoffset=readshort(f) - else - xoffset=readchar(f) - yoffset=readchar(f) - end - else - if bittest(flags,0x0001) then - base=readshort(f) - reference=readshort(f) - else - base=readchar(f) - reference=readchar(f) - end - end - if bittest(flags,0x0008) then - xscale=read2dot14(f) - yscale=xscale - if f_xyarg and f_offset then - xoffset=xoffset*xscale - yoffset=yoffset*yscale - end - elseif bittest(flags,0x0040) then - xscale=read2dot14(f) - yscale=read2dot14(f) - if f_xyarg and f_offset then - xoffset=xoffset*xscale - yoffset=yoffset*yscale - end - elseif bittest(flags,0x0080) then - xscale=read2dot14(f) - xrotate=read2dot14(f) - yrotate=read2dot14(f) - yscale=read2dot14(f) - if f_xyarg and f_offset then - xoffset=xoffset*sqrt(xscale^2+xrotate^2) - yoffset=yoffset*sqrt(yrotate^2+yscale^2) - end - end - nofcomponents=nofcomponents+1 - components[nofcomponents]={ - index=index, - usemine=bittest(flags,0x0200), - round=bittest(flags,0x0006), - base=base, - reference=reference, - matrix={ xscale,xrotate,yrotate,yscale,xoffset,yoffset }, - } - if bittest(flags,0x0100) then - instructions=true - end - if not bittest(flags,0x0020) then - break - end - end - return { - type="composite", - components=components, - } -end -function readers.loca(f,fontdata,specification) - if specification.glyphs then - local datatable=fontdata.tables.loca - if datatable then - local offset=fontdata.tables.glyf.offset - local format=fontdata.fontheader.indextolocformat - local locations={} - setposition(f,datatable.offset) - if format==1 then - local nofglyphs=datatable.length/4-1 - -1 - for i=0,nofglyphs do - locations[i]=offset+readulong(f) - end - fontdata.nofglyphs=nofglyphs - else - local nofglyphs=datatable.length/2-1 - -1 - for i=0,nofglyphs do - locations[i]=offset+readushort(f)*2 - end - fontdata.nofglyphs=nofglyphs - end - fontdata.locations=locations - end - end -end -function readers.glyf(f,fontdata,specification) - if specification.glyphs then - local datatable=fontdata.tables.glyf - if datatable then - local locations=fontdata.locations - if locations then - local glyphs=fontdata.glyphs - local nofglyphs=fontdata.nofglyphs - local filesize=fontdata.filesize - local nothing={ 0,0,0,0 } - local shapes={} - local loadshapes=specification.shapes - for index=0,nofglyphs do - local location=locations[index] - if location>=filesize then - report("discarding %s glyphs due to glyph location bug",nofglyphs-index+1) - fontdata.nofglyphs=index-1 - fontdata.badfont=true - break - elseif location>0 then - setposition(f,location) - local nofcontours=readshort(f) - glyphs[index].boundingbox={ - readshort(f), - readshort(f), - readshort(f), - readshort(f), - } - if not loadshapes then - elseif nofcontours==0 then - shapes[index]=readnothing(f,nofcontours) - elseif nofcontours>0 then - shapes[index]=readglyph(f,nofcontours) - else - shapes[index]=readcomposite(f,nofcontours) - end - else - if loadshapes then - shapes[index]={} - end - glyphs[index].boundingbox=nothing - end - end - if loadshapes then - mergecomposites(glyphs,shapes) - contours2outlines(glyphs,shapes) - end - end - end - end -end - -end --- [luaotfload, fontloader-2017-02-11.lua scope for “font-ttf”] --- - - -do --- [luaotfload, fontloader-2017-02-11.lua scope for “font-dsp” 4a5266ada979d5c2d48867dc3ffaefea] --- - -if not modules then modules={} end modules ['font-dsp']={ - version=1.001, - comment="companion to font-ini.mkiv", - 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 bittest=bit32.btest -local rshift=bit32.rshift -local concat=table.concat -local lower=string.lower -local copy=table.copy -local sub=string.sub -local strip=string.strip -local tohash=table.tohash -local reversed=table.reversed -local setmetatableindex=table.setmetatableindex -local formatters=string.formatters -local sortedkeys=table.sortedkeys -local sortedhash=table.sortedhash -local report=logs.reporter("otf reader") -local readers=fonts.handlers.otf.readers -local streamreader=readers.streamreader -local setposition=streamreader.setposition -local getposition=streamreader.getposition -local skipshort=streamreader.skipshort -local readushort=streamreader.readcardinal2 -local readulong=streamreader.readcardinal4 -local readshort=streamreader.readinteger2 -local readfword=readshort -local readstring=streamreader.readstring -local readtag=streamreader.readtag -local readbytes=streamreader.readbytes -local gsubhandlers={} -local gposhandlers={} -local lookupidoffset=-1 -local classes={ - "base", - "ligature", - "mark", - "component", -} -local gsubtypes={ - "single", - "multiple", - "alternate", - "ligature", - "context", - "chainedcontext", - "extension", - "reversechainedcontextsingle", -} -local gpostypes={ - "single", - "pair", - "cursive", - "marktobase", - "marktoligature", - "marktomark", - "context", - "chainedcontext", - "extension", -} -local chaindirections={ - context=0, - chainedcontext=1, - reversechainedcontextsingle=-1, -} -local lookupnames={ - gsub={ - single="gsub_single", - multiple="gsub_multiple", - alternate="gsub_alternate", - ligature="gsub_ligature", - context="gsub_context", - chainedcontext="gsub_contextchain", - reversechainedcontextsingle="gsub_reversecontextchain", - }, - gpos={ - single="gpos_single", - pair="gpos_pair", - cursive="gpos_cursive", - marktobase="gpos_mark2base", - marktoligature="gpos_mark2ligature", - marktomark="gpos_mark2mark", - context="gpos_context", - chainedcontext="gpos_contextchain", - } -} -local lookupflags=setmetatableindex(function(t,k) - local v={ - bittest(k,0x0008) and true or false, - bittest(k,0x0004) and true or false, - bittest(k,0x0002) and true or false, - bittest(k,0x0001) and true or false, - } - t[k]=v - return v -end) -local function readcoverage(f,offset,simple) - setposition(f,offset) - local coverageformat=readushort(f) - local coverage={} - if coverageformat==1 then - local nofcoverage=readushort(f) - if simple then - for i=1,nofcoverage do - coverage[i]=readushort(f) - end - else - for i=0,nofcoverage-1 do - coverage[readushort(f)]=i - end - end - elseif coverageformat==2 then - local nofranges=readushort(f) - local n=simple and 1 or 0 - for i=1,nofranges do - local firstindex=readushort(f) - local lastindex=readushort(f) - local coverindex=readushort(f) - if simple then - for i=firstindex,lastindex do - coverage[n]=i - n=n+1 - end - else - for i=firstindex,lastindex do - coverage[i]=n - n=n+1 - end - end - end - else - report("unknown coverage format %a ",coverageformat) - end - return coverage -end -local function readclassdef(f,offset,preset) - setposition(f,offset) - local classdefformat=readushort(f) - local classdef={} - if type(preset)=="number" then - for k=0,preset-1 do - classdef[k]=1 - end - end - if classdefformat==1 then - local index=readushort(f) - local nofclassdef=readushort(f) - for i=1,nofclassdef do - classdef[index]=readushort(f)+1 - index=index+1 - end - elseif classdefformat==2 then - local nofranges=readushort(f) - local n=0 - for i=1,nofranges do - local firstindex=readushort(f) - local lastindex=readushort(f) - local class=readushort(f)+1 - for i=firstindex,lastindex do - classdef[i]=class - end - end - else - report("unknown classdef format %a ",classdefformat) - end - if type(preset)=="table" then - for k in next,preset do - if not classdef[k] then - classdef[k]=1 - end - end - end - return classdef -end -local function classtocoverage(defs) - if defs then - local list={} - for index,class in next,defs do - local c=list[class] - if c then - c[#c+1]=index - else - list[class]={ index } - end - end - return list - end -end -local function readposition(f,format) - if format==0 then - return nil - end - local x=bittest(format,0x0001) and readshort(f) or 0 - local y=bittest(format,0x0002) and readshort(f) or 0 - local h=bittest(format,0x0004) and readshort(f) or 0 - local v=bittest(format,0x0008) and readshort(f) or 0 - if x==0 and y==0 and h==0 and v==0 then - return nil - else - return { x,y,h,v } - end -end -local function readanchor(f,offset) - if not offset or offset==0 then - return nil - end - setposition(f,offset) - local format=readshort(f) - if format==0 then - report("invalid anchor format %i @ position %i",format,offset) - return false - elseif format>3 then - report("unsupported anchor format %i @ position %i",format,offset) - return false - end - return { readshort(f),readshort(f) } -end -local function readfirst(f,offset) - if offset then - setposition(f,offset) - end - return { readushort(f) } -end -local function readarray(f,offset,first) - if offset then - setposition(f,offset) - end - local n=readushort(f) - if first then - local t={ first } - for i=2,n do - t[i]=readushort(f) - end - return t,n - elseif n>0 then - local t={} - for i=1,n do - t[i]=readushort(f) - end - return t,n - end -end -local function readcoveragearray(f,offset,t,simple) - if not t then - return nil - end - local n=#t - if n==0 then - return nil - end - for i=1,n do - t[i]=readcoverage(f,offset+t[i],simple) - end - return t -end -local function covered(subset,all) - local used,u - for i=1,#subset do - local s=subset[i] - if all[s] then - if used then - u=u+1 - used[u]=s - else - u=1 - used={ s } - end - end - end - return used -end -local function readlookuparray(f,noflookups,nofcurrent) - local lookups={} - if noflookups>0 then - local length=0 - for i=1,noflookups do - local index=readushort(f)+1 - if index>length then - length=index - end - lookups[index]=readushort(f)+1 - end - for index=1,length do - if not lookups[index] then - lookups[index]=false - end - end - end - return lookups -end -local function unchainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,what) - local tableoffset=lookupoffset+offset - setposition(f,tableoffset) - local subtype=readushort(f) - if subtype==1 then - local coverage=readushort(f) - local subclasssets=readarray(f) - local rules={} - if subclasssets then - coverage=readcoverage(f,tableoffset+coverage,true) - for i=1,#subclasssets do - local offset=subclasssets[i] - if offset>0 then - local firstcoverage=coverage[i] - local rulesoffset=tableoffset+offset - local subclassrules=readarray(f,rulesoffset) - for rule=1,#subclassrules do - setposition(f,rulesoffset+subclassrules[rule]) - local nofcurrent=readushort(f) - local noflookups=readushort(f) - local current={ { firstcoverage } } - for i=2,nofcurrent do - current[i]={ readushort(f) } - end - local lookups=readlookuparray(f,noflookups,nofcurrent) - rules[#rules+1]={ - current=current, - lookups=lookups - } - end - end - end - else - report("empty subclassset in %a subtype %i","unchainedcontext",subtype) - end - return { - format="glyphs", - rules=rules, - } - elseif subtype==2 then - local coverage=readushort(f) - local currentclassdef=readushort(f) - local subclasssets=readarray(f) - local rules={} - if subclasssets then - coverage=readcoverage(f,tableoffset+coverage) - currentclassdef=readclassdef(f,tableoffset+currentclassdef,coverage) - local currentclasses=classtocoverage(currentclassdef,fontdata.glyphs) - for class=1,#subclasssets do - local offset=subclasssets[class] - if offset>0 then - local firstcoverage=currentclasses[class] - if firstcoverage then - firstcoverage=covered(firstcoverage,coverage) - if firstcoverage then - local rulesoffset=tableoffset+offset - local subclassrules=readarray(f,rulesoffset) - for rule=1,#subclassrules do - setposition(f,rulesoffset+subclassrules[rule]) - local nofcurrent=readushort(f) - local noflookups=readushort(f) - local current={ firstcoverage } - for i=2,nofcurrent do - current[i]=currentclasses[readushort(f)+1] - end - local lookups=readlookuparray(f,noflookups,nofcurrent) - rules[#rules+1]={ - current=current, - lookups=lookups - } - end - else - report("no coverage") - end - else - report("no coverage class") - end - end - end - else - report("empty subclassset in %a subtype %i","unchainedcontext",subtype) - end - return { - format="class", - rules=rules, - } - elseif subtype==3 then - local current=readarray(f) - local noflookups=readushort(f) - local lookups=readlookuparray(f,noflookups,#current) - current=readcoveragearray(f,tableoffset,current,true) - return { - format="coverage", - rules={ - { - current=current, - lookups=lookups, - } - } - } - else - report("unsupported subtype %a in %a %s",subtype,"unchainedcontext",what) - end -end -local function chainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,what) - local tableoffset=lookupoffset+offset - setposition(f,tableoffset) - local subtype=readushort(f) - if subtype==1 then - local coverage=readushort(f) - local subclasssets=readarray(f) - local rules={} - if subclasssets then - coverage=readcoverage(f,tableoffset+coverage,true) - for i=1,#subclasssets do - local offset=subclasssets[i] - if offset>0 then - local firstcoverage=coverage[i] - local rulesoffset=tableoffset+offset - local subclassrules=readarray(f,rulesoffset) - for rule=1,#subclassrules do - setposition(f,rulesoffset+subclassrules[rule]) - local nofbefore=readushort(f) - local before - if nofbefore>0 then - before={} - for i=1,nofbefore do - before[i]={ readushort(f) } - end - end - local nofcurrent=readushort(f) - local current={ { firstcoverage } } - for i=2,nofcurrent do - current[i]={ readushort(f) } - end - local nofafter=readushort(f) - local after - if nofafter>0 then - after={} - for i=1,nofafter do - after[i]={ readushort(f) } - end - end - local noflookups=readushort(f) - local lookups=readlookuparray(f,noflookups,nofcurrent) - rules[#rules+1]={ - before=before, - current=current, - after=after, - lookups=lookups, - } - end - end - end - else - report("empty subclassset in %a subtype %i","chainedcontext",subtype) - end - return { - format="glyphs", - rules=rules, - } - elseif subtype==2 then - local coverage=readushort(f) - local beforeclassdef=readushort(f) - local currentclassdef=readushort(f) - local afterclassdef=readushort(f) - local subclasssets=readarray(f) - local rules={} - if subclasssets then - local coverage=readcoverage(f,tableoffset+coverage) - local beforeclassdef=readclassdef(f,tableoffset+beforeclassdef,nofglyphs) - local currentclassdef=readclassdef(f,tableoffset+currentclassdef,coverage) - local afterclassdef=readclassdef(f,tableoffset+afterclassdef,nofglyphs) - local beforeclasses=classtocoverage(beforeclassdef,fontdata.glyphs) - local currentclasses=classtocoverage(currentclassdef,fontdata.glyphs) - local afterclasses=classtocoverage(afterclassdef,fontdata.glyphs) - for class=1,#subclasssets do - local offset=subclasssets[class] - if offset>0 then - local firstcoverage=currentclasses[class] - if firstcoverage then - firstcoverage=covered(firstcoverage,coverage) - if firstcoverage then - local rulesoffset=tableoffset+offset - local subclassrules=readarray(f,rulesoffset) - for rule=1,#subclassrules do - setposition(f,rulesoffset+subclassrules[rule]) - local nofbefore=readushort(f) - local before - if nofbefore>0 then - before={} - for i=1,nofbefore do - before[i]=beforeclasses[readushort(f)+1] - end - end - local nofcurrent=readushort(f) - local current={ firstcoverage } - for i=2,nofcurrent do - current[i]=currentclasses[readushort(f)+1] - end - local nofafter=readushort(f) - local after - if nofafter>0 then - after={} - for i=1,nofafter do - after[i]=afterclasses[readushort(f)+1] - end - end - local noflookups=readushort(f) - local lookups=readlookuparray(f,noflookups,nofcurrent) - rules[#rules+1]={ - before=before, - current=current, - after=after, - lookups=lookups, - } - end - else - report("no coverage") - end - else - report("class is not covered") - end - end - end - else - report("empty subclassset in %a subtype %i","chainedcontext",subtype) - end - return { - format="class", - rules=rules, - } - elseif subtype==3 then - local before=readarray(f) - local current=readarray(f) - local after=readarray(f) - local noflookups=readushort(f) - local lookups=readlookuparray(f,noflookups,#current) - before=readcoveragearray(f,tableoffset,before,true) - current=readcoveragearray(f,tableoffset,current,true) - after=readcoveragearray(f,tableoffset,after,true) - return { - format="coverage", - rules={ - { - before=before, - current=current, - after=after, - lookups=lookups, - } - } - } - else - report("unsupported subtype %a in %a %s",subtype,"chainedcontext",what) - end -end -local function extension(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,types,handlers,what) - local tableoffset=lookupoffset+offset - setposition(f,tableoffset) - local subtype=readushort(f) - if subtype==1 then - local lookuptype=types[readushort(f)] - local faroffset=readulong(f) - local handler=handlers[lookuptype] - if handler then - return handler(f,fontdata,lookupid,tableoffset+faroffset,0,glyphs,nofglyphs),lookuptype - else - report("no handler for lookuptype %a subtype %a in %s %s",lookuptype,subtype,what,"extension") - end - else - report("unsupported subtype %a in %s %s",subtype,what,"extension") - end -end -function gsubhandlers.single(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs) - local tableoffset=lookupoffset+offset - setposition(f,tableoffset) - local subtype=readushort(f) - if subtype==1 then - local coverage=readushort(f) - local delta=readshort(f) - local coverage=readcoverage(f,tableoffset+coverage) - for index in next,coverage do - local newindex=index+delta - if index>nofglyphs or newindex>nofglyphs then - report("invalid index in %s format %i: %i -> %i (max %i)","single",subtype,index,newindex,nofglyphs) - coverage[index]=nil - else - coverage[index]=newindex - end - end - return { - coverage=coverage - } - elseif subtype==2 then - local coverage=readushort(f) - local nofreplacements=readushort(f) - local replacements={} - for i=1,nofreplacements do - replacements[i]=readushort(f) - end - local coverage=readcoverage(f,tableoffset+coverage) - for index,newindex in next,coverage do - newindex=newindex+1 - if index>nofglyphs or newindex>nofglyphs then - report("invalid index in %s format %i: %i -> %i (max %i)","single",subtype,index,newindex,nofglyphs) - coverage[index]=nil - else - coverage[index]=replacements[newindex] - end - end - return { - coverage=coverage - } - else - report("unsupported subtype %a in %a substitution",subtype,"single") - end -end -local function sethandler(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,what) - local tableoffset=lookupoffset+offset - setposition(f,tableoffset) - local subtype=readushort(f) - if subtype==1 then - local coverage=readushort(f) - local nofsequence=readushort(f) - local sequences={} - for i=1,nofsequence do - sequences[i]=readushort(f) - end - for i=1,nofsequence do - setposition(f,tableoffset+sequences[i]) - local n=readushort(f) - local s={} - for i=1,n do - s[i]=readushort(f) - end - sequences[i]=s - end - local coverage=readcoverage(f,tableoffset+coverage) - for index,newindex in next,coverage do - newindex=newindex+1 - if index>nofglyphs or newindex>nofglyphs then - report("invalid index in %s format %i: %i -> %i (max %i)",what,subtype,index,newindex,nofglyphs) - coverage[index]=nil - else - coverage[index]=sequences[newindex] - end - end - return { - coverage=coverage - } - else - report("unsupported subtype %a in %a substitution",subtype,what) - end -end -function gsubhandlers.multiple(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs) - return sethandler(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,"multiple") -end -function gsubhandlers.alternate(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs) - return sethandler(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,"alternate") -end -function gsubhandlers.ligature(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs) - local tableoffset=lookupoffset+offset - setposition(f,tableoffset) - local subtype=readushort(f) - if subtype==1 then - local coverage=readushort(f) - local nofsets=readushort(f) - local ligatures={} - for i=1,nofsets do - ligatures[i]=readushort(f) - end - for i=1,nofsets do - local offset=lookupoffset+offset+ligatures[i] - setposition(f,offset) - local n=readushort(f) - local l={} - for i=1,n do - l[i]=offset+readushort(f) - end - ligatures[i]=l - end - local coverage=readcoverage(f,tableoffset+coverage) - for index,newindex in next,coverage do - local hash={} - local ligatures=ligatures[newindex+1] - for i=1,#ligatures do - local offset=ligatures[i] - setposition(f,offset) - local lig=readushort(f) - local cnt=readushort(f) - local hsh=hash - for i=2,cnt do - local c=readushort(f) - local h=hsh[c] - if not h then - h={} - hsh[c]=h - end - hsh=h - end - hsh.ligature=lig - end - coverage[index]=hash - end - return { - coverage=coverage - } - else - report("unsupported subtype %a in %a substitution",subtype,"ligature") - end -end -function gsubhandlers.context(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs) - return unchainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,"substitution"),"context" -end -function gsubhandlers.chainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs) - return chainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,"substitution"),"chainedcontext" -end -function gsubhandlers.extension(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs) - return extension(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,gsubtypes,gsubhandlers,"substitution") -end -function gsubhandlers.reversechainedcontextsingle(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs) - local tableoffset=lookupoffset+offset - setposition(f,tableoffset) - local subtype=readushort(f) - if subtype==1 then - local current=readfirst(f) - local before=readarray(f) - local after=readarray(f) - local replacements=readarray(f) - current=readcoveragearray(f,tableoffset,current,true) - before=readcoveragearray(f,tableoffset,before,true) - after=readcoveragearray(f,tableoffset,after,true) - return { - coverage={ - format="reversecoverage", - before=before, - current=current, - after=after, - replacements=replacements, - } - },"reversechainedcontextsingle" - else - report("unsupported subtype %a in %a substitution",subtype,"reversechainedcontextsingle") - end -end -local function readpairsets(f,tableoffset,sets,format1,format2) - local done={} - for i=1,#sets do - local offset=sets[i] - local reused=done[offset] - if not reused then - setposition(f,tableoffset+offset) - local n=readushort(f) - reused={} - for i=1,n do - reused[i]={ - readushort(f), - readposition(f,format1), - readposition(f,format2) - } - end - done[offset]=reused - end - sets[i]=reused - end - return sets -end -local function readpairclasssets(f,nofclasses1,nofclasses2,format1,format2) - local classlist1={} - for i=1,nofclasses1 do - local classlist2={} - classlist1[i]=classlist2 - for j=1,nofclasses2 do - local one=readposition(f,format1) - local two=readposition(f,format2) - if one or two then - classlist2[j]={ one,two } - else - classlist2[j]=false - end - end - end - return classlist1 -end -function gposhandlers.single(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs) - local tableoffset=lookupoffset+offset - setposition(f,tableoffset) - local subtype=readushort(f) - if subtype==1 then - local coverage=readushort(f) - local format=readushort(f) - local value=readposition(f,format) - local coverage=readcoverage(f,tableoffset+coverage) - for index,newindex in next,coverage do - coverage[index]=value - end - return { - format="pair", - coverage=coverage - } - elseif subtype==2 then - local coverage=readushort(f) - local format=readushort(f) - local values={} - local nofvalues=readushort(f) - for i=1,nofvalues do - values[i]=readposition(f,format) - end - local coverage=readcoverage(f,tableoffset+coverage) - for index,newindex in next,coverage do - coverage[index]=values[newindex+1] - end - return { - format="pair", - coverage=coverage - } - else - report("unsupported subtype %a in %a positioning",subtype,"single") - end -end -function gposhandlers.pair(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs) - local tableoffset=lookupoffset+offset - setposition(f,tableoffset) - local subtype=readushort(f) - if subtype==1 then - local coverage=readushort(f) - local format1=readushort(f) - local format2=readushort(f) - local sets=readarray(f) - sets=readpairsets(f,tableoffset,sets,format1,format2) - coverage=readcoverage(f,tableoffset+coverage) - for index,newindex in next,coverage do - local set=sets[newindex+1] - local hash={} - for i=1,#set do - local value=set[i] - if value then - local other=value[1] - local first=value[2] - local second=value[3] - if first or second then - hash[other]={ first,second } - else - hash[other]=nil - end - end - end - coverage[index]=hash - end - return { - format="pair", - coverage=coverage - } - elseif subtype==2 then - local coverage=readushort(f) - local format1=readushort(f) - local format2=readushort(f) - local classdef1=readushort(f) - local classdef2=readushort(f) - local nofclasses1=readushort(f) - local nofclasses2=readushort(f) - local classlist=readpairclasssets(f,nofclasses1,nofclasses2,format1,format2) - coverage=readcoverage(f,tableoffset+coverage) - classdef1=readclassdef(f,tableoffset+classdef1,coverage) - classdef2=readclassdef(f,tableoffset+classdef2,nofglyphs) - local usedcoverage={} - for g1,c1 in next,classdef1 do - if coverage[g1] then - local l1=classlist[c1] - if l1 then - local hash={} - for paired,class in next,classdef2 do - local offsets=l1[class] - if offsets then - local first=offsets[1] - local second=offsets[2] - if first or second then - hash[paired]={ first,second } - else - end - end - end - usedcoverage[g1]=hash - end - end - end - return { - format="pair", - coverage=usedcoverage - } - elseif subtype==3 then - report("yet unsupported subtype %a in %a positioning",subtype,"pair") - else - report("unsupported subtype %a in %a positioning",subtype,"pair") - end -end -function gposhandlers.cursive(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs) - local tableoffset=lookupoffset+offset - setposition(f,tableoffset) - local subtype=readushort(f) - if subtype==1 then - local coverage=tableoffset+readushort(f) - local nofrecords=readushort(f) - local records={} - for i=1,nofrecords do - local entry=readushort(f) - local exit=readushort(f) - records[i]={ - entry=entry~=0 and (tableoffset+entry) or false, - exit=exit~=0 and (tableoffset+exit ) or false, - } - end - coverage=readcoverage(f,coverage) - for i=1,nofrecords do - local r=records[i] - records[i]={ - 1, - readanchor(f,r.entry) or nil, - readanchor(f,r.exit ) or nil, - } - end - for index,newindex in next,coverage do - coverage[index]=records[newindex+1] - end - return { - coverage=coverage - } - else - report("unsupported subtype %a in %a positioning",subtype,"cursive") - end -end -local function handlemark(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,ligature) - local tableoffset=lookupoffset+offset - setposition(f,tableoffset) - local subtype=readushort(f) - if subtype==1 then - local markcoverage=tableoffset+readushort(f) - local basecoverage=tableoffset+readushort(f) - local nofclasses=readushort(f) - local markoffset=tableoffset+readushort(f) - local baseoffset=tableoffset+readushort(f) - local markcoverage=readcoverage(f,markcoverage) - local basecoverage=readcoverage(f,basecoverage,true) - setposition(f,markoffset) - local markclasses={} - local nofmarkclasses=readushort(f) - local lastanchor=fontdata.lastanchor or 0 - local usedanchors={} - for i=1,nofmarkclasses do - local class=readushort(f)+1 - local offset=readushort(f) - if offset==0 then - markclasses[i]=false - else - markclasses[i]={ class,markoffset+offset } - end - usedanchors[class]=true - end - for i=1,nofmarkclasses do - local mc=markclasses[i] - if mc then - mc[2]=readanchor(f,mc[2]) - end - end - setposition(f,baseoffset) - local nofbaserecords=readushort(f) - local baserecords={} - if ligature then - for i=1,nofbaserecords do - local offset=readushort(f) - if offset==0 then - baserecords[i]=false - else - baserecords[i]=baseoffset+offset - end - end - for i=1,nofbaserecords do - local recordoffset=baserecords[i] - if recordoffset then - setposition(f,recordoffset) - local nofcomponents=readushort(f) - local components={} - for i=1,nofcomponents do - local classes={} - for i=1,nofclasses do - local offset=readushort(f) - if offset~=0 then - classes[i]=recordoffset+offset - else - classes[i]=false - end - end - components[i]=classes - end - baserecords[i]=components - end - end - local baseclasses={} - for i=1,nofclasses do - baseclasses[i]={} - end - for i=1,nofbaserecords do - local components=baserecords[i] - if components then - local b=basecoverage[i] - for c=1,#components do - local classes=components[c] - if classes then - for i=1,nofclasses do - local anchor=readanchor(f,classes[i]) - local bclass=baseclasses[i] - local bentry=bclass[b] - if bentry then - bentry[c]=anchor - else - bclass[b]={ [c]=anchor } - end - end - end - end - end - end - for index,newindex in next,markcoverage do - markcoverage[index]=markclasses[newindex+1] or nil - end - return { - format="ligature", - baseclasses=baseclasses, - coverage=markcoverage, - } - else - for i=1,nofbaserecords do - local r={} - for j=1,nofclasses do - local offset=readushort(f) - if offset==0 then - r[j]=false - else - r[j]=baseoffset+offset - end - end - baserecords[i]=r - end - local baseclasses={} - for i=1,nofclasses do - baseclasses[i]={} - end - for i=1,nofbaserecords do - local r=baserecords[i] - local b=basecoverage[i] - for j=1,nofclasses do - baseclasses[j][b]=readanchor(f,r[j]) - end - end - for index,newindex in next,markcoverage do - markcoverage[index]=markclasses[newindex+1] or nil - end - return { - format="base", - baseclasses=baseclasses, - coverage=markcoverage, - } - end - else - report("unsupported subtype %a in",subtype) - end -end -function gposhandlers.marktobase(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs) - return handlemark(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs) -end -function gposhandlers.marktoligature(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs) - return handlemark(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,true) -end -function gposhandlers.marktomark(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs) - return handlemark(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs) -end -function gposhandlers.context(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs) - return unchainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,"positioning"),"context" -end -function gposhandlers.chainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs) - return chainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,"positioning"),"chainedcontext" -end -function gposhandlers.extension(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs) - return extension(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,gpostypes,gposhandlers,"positioning") -end -do - local plugins={} - function plugins.size(f,fontdata,tableoffset,feature) - if fontdata.designsize then - else - local function check(offset) - setposition(f,offset) - local designsize=readushort(f) - if designsize>0 then - local fontstyle=readushort(f) - local guimenuid=readushort(f) - local minsize=readushort(f) - local maxsize=readushort(f) - if minsize==0 and maxsize==0 and fontstyleid==0 and guimenuid==0 then - minsize=designsize - maxsize=designsize - end - if designsize>=minsize and designsize<=maxsize then - return minsize,maxsize,designsize - end - end - end - local minsize,maxsize,designsize=check(tableoffset+feature.offset+feature.parameters) - if not designsize then - minsize,maxsize,designsize=check(tableoffset+feature.parameters) - if designsize then - report("bad size feature in %a, falling back to wrong offset",fontdata.filename or "?") - else - report("bad size feature in %a,",fontdata.filename or "?") - end - end - if designsize then - fontdata.minsize=minsize - fontdata.maxsize=maxsize - fontdata.designsize=designsize - end - end - end - local function reorderfeatures(fontdata,scripts,features) - local scriptlangs={} - local featurehash={} - local featureorder={} - for script,languages in next,scripts do - for language,record in next,languages do - local hash={} - local list=record.featureindices - for k=1,#list do - local index=list[k] - local feature=features[index] - local lookups=feature.lookups - local tag=feature.tag - if tag then - hash[tag]=true - end - if lookups then - for i=1,#lookups do - local lookup=lookups[i] - local o=featureorder[lookup] - if o then - local okay=true - for i=1,#o do - if o[i]==tag then - okay=false - break - end - end - if okay then - o[#o+1]=tag - end - else - featureorder[lookup]={ tag } - end - local f=featurehash[lookup] - if f then - local h=f[tag] - if h then - local s=h[script] - if s then - s[language]=true - else - h[script]={ [language]=true } - end - else - f[tag]={ [script]={ [language]=true } } - end - else - featurehash[lookup]={ [tag]={ [script]={ [language]=true } } } - end - local h=scriptlangs[tag] - if h then - local s=h[script] - if s then - s[language]=true - else - h[script]={ [language]=true } - end - else - scriptlangs[tag]={ [script]={ [language]=true } } - end - end - end - end - end - end - return scriptlangs,featurehash,featureorder - end - local function readscriplan(f,fontdata,scriptoffset) - setposition(f,scriptoffset) - local nofscripts=readushort(f) - local scripts={} - for i=1,nofscripts do - scripts[readtag(f)]=scriptoffset+readushort(f) - end - local languagesystems=setmetatableindex("table") - for script,offset in next,scripts do - setposition(f,offset) - local defaultoffset=readushort(f) - local noflanguages=readushort(f) - local languages={} - if defaultoffset>0 then - languages.dflt=languagesystems[offset+defaultoffset] - end - for i=1,noflanguages do - local language=readtag(f) - local offset=offset+readushort(f) - languages[language]=languagesystems[offset] - end - scripts[script]=languages - end - for offset,usedfeatures in next,languagesystems do - if offset>0 then - setposition(f,offset) - local featureindices={} - usedfeatures.featureindices=featureindices - usedfeatures.lookuporder=readushort(f) - usedfeatures.requiredindex=readushort(f) - local noffeatures=readushort(f) - for i=1,noffeatures do - featureindices[i]=readushort(f)+1 - end - end - end - return scripts - end - local function readfeatures(f,fontdata,featureoffset) - setposition(f,featureoffset) - local features={} - local noffeatures=readushort(f) - for i=1,noffeatures do - features[i]={ - tag=readtag(f), - offset=readushort(f) - } - end - for i=1,noffeatures do - local feature=features[i] - local offset=featureoffset+feature.offset - setposition(f,offset) - local parameters=readushort(f) - local noflookups=readushort(f) - if noflookups>0 then - local lookups={} - feature.lookups=lookups - for j=1,noflookups do - lookups[j]=readushort(f)+1 - end - end - if parameters>0 then - feature.parameters=parameters - local plugin=plugins[feature.tag] - if plugin then - plugin(f,fontdata,featureoffset,feature) - end - end - end - return features - end - local function readlookups(f,lookupoffset,lookuptypes,featurehash,featureorder) - setposition(f,lookupoffset) - local lookups={} - local noflookups=readushort(f) - for i=1,noflookups do - lookups[i]=readushort(f) - end - for lookupid=1,noflookups do - local index=lookups[lookupid] - setposition(f,lookupoffset+index) - local subtables={} - local typebits=readushort(f) - local flagbits=readushort(f) - local lookuptype=lookuptypes[typebits] - local lookupflags=lookupflags[flagbits] - local nofsubtables=readushort(f) - for j=1,nofsubtables do - local offset=readushort(f) - subtables[j]=offset+index - end - local markclass=bittest(flagbits,0x0010) - if markclass then - markclass=readushort(f) - end - local markset=rshift(flagbits,8) - if markset>0 then - markclass=markset - end - lookups[lookupid]={ - type=lookuptype, - flags=lookupflags, - name=lookupid, - subtables=subtables, - markclass=markclass, - features=featurehash[lookupid], - order=featureorder[lookupid], - } - end - return lookups - end - local function readscriptoffsets(f,fontdata,tableoffset) - if not tableoffset then - return - end - setposition(f,tableoffset) - local version=readulong(f) - if version~=0x00010000 then - report("table version %a of %a is not supported (yet), maybe font %s is bad",version,what,fontdata.filename) - return - end - return tableoffset+readushort(f),tableoffset+readushort(f),tableoffset+readushort(f) - end - local f_lookupname=formatters["%s_%s_%s"] - local function resolvelookups(f,lookupoffset,fontdata,lookups,lookuptypes,lookuphandlers,what) - local sequences=fontdata.sequences or {} - local sublookuplist=fontdata.sublookups or {} - fontdata.sequences=sequences - fontdata.sublookups=sublookuplist - local nofsublookups=#sublookuplist - local nofsequences=#sequences - local lastsublookup=nofsublookups - local lastsequence=nofsequences - local lookupnames=lookupnames[what] - local sublookuphash={} - local sublookupcheck={} - local glyphs=fontdata.glyphs - local nofglyphs=fontdata.nofglyphs or #glyphs - local noflookups=#lookups - local lookupprefix=sub(what,2,2) - for lookupid=1,noflookups do - local lookup=lookups[lookupid] - local lookuptype=lookup.type - local subtables=lookup.subtables - local features=lookup.features - local handler=lookuphandlers[lookuptype] - if handler then - local nofsubtables=#subtables - local order=lookup.order - local flags=lookup.flags - if flags[1] then flags[1]="mark" end - if flags[2] then flags[2]="ligature" end - if flags[3] then flags[3]="base" end - local markclass=lookup.markclass - if nofsubtables>0 then - local steps={} - local nofsteps=0 - local oldtype=nil - for s=1,nofsubtables do - local step,lt=handler(f,fontdata,lookupid,lookupoffset,subtables[s],glyphs,nofglyphs) - if lt then - lookuptype=lt - if oldtype and lt~=oldtype then - report("messy %s lookup type %a and %a",what,lookuptype,oldtype) - end - oldtype=lookuptype - end - if not step then - report("unsupported %s lookup type %a",what,lookuptype) - else - nofsteps=nofsteps+1 - steps[nofsteps]=step - local rules=step.rules - if rules then - for i=1,#rules do - local rule=rules[i] - local before=rule.before - local current=rule.current - local after=rule.after - if before then - for i=1,#before do - before[i]=tohash(before[i]) - end - rule.before=reversed(before) - end - if current then - for i=1,#current do - current[i]=tohash(current[i]) - end - end - if after then - for i=1,#after do - after[i]=tohash(after[i]) - end - end - end - end - end - end - if nofsteps~=nofsubtables then - report("bogus subtables removed in %s lookup type %a",what,lookuptype) - end - lookuptype=lookupnames[lookuptype] or lookuptype - if features then - nofsequences=nofsequences+1 - local l={ - index=nofsequences, - name=f_lookupname(lookupprefix,"s",lookupid+lookupidoffset), - steps=steps, - nofsteps=nofsteps, - type=lookuptype, - markclass=markclass or nil, - flags=flags, - order=order, - features=features, - } - sequences[nofsequences]=l - lookup.done=l - else - nofsublookups=nofsublookups+1 - local l={ - index=nofsublookups, - name=f_lookupname(lookupprefix,"l",lookupid+lookupidoffset), - steps=steps, - nofsteps=nofsteps, - type=lookuptype, - markclass=markclass or nil, - flags=flags, - } - sublookuplist[nofsublookups]=l - sublookuphash[lookupid]=nofsublookups - sublookupcheck[lookupid]=0 - lookup.done=l - end - else - report("no subtables for lookup %a",lookupid) - end - else - report("no handler for lookup %a with type %a",lookupid,lookuptype) - end - end - local reported={} - local function report_issue(i,what,sequence,kind) - local name=sequence.name - if not reported[name] then - report("rule %i in %s lookup %a has %s lookups",i,what,name,kind) - reported[name]=true - end - end - for i=lastsequence+1,nofsequences do - local sequence=sequences[i] - local steps=sequence.steps - for i=1,#steps do - local step=steps[i] - local rules=step.rules - if rules then - for i=1,#rules do - local rule=rules[i] - local rlookups=rule.lookups - if not rlookups then - report_issue(i,what,sequence,"no") - elseif not next(rlookups) then - report_issue(i,what,sequence,"empty") - rule.lookups=nil - else - local length=#rlookups - for index=1,length do - local lookupid=rlookups[index] - if lookupid then - local h=sublookuphash[lookupid] - if not h then - local lookup=lookups[lookupid] - if lookup then - local d=lookup.done - if d then - nofsublookups=nofsublookups+1 - h={ - index=nofsublookups, - name=f_lookupname(lookupprefix,"d",lookupid+lookupidoffset), - derived=true, - steps=d.steps, - nofsteps=d.nofsteps, - type=d.lookuptype, - markclass=d.markclass or nil, - flags=d.flags, - } - sublookuplist[nofsublookups]=copy(h) - sublookuphash[lookupid]=nofsublookups - sublookupcheck[lookupid]=1 - h=nofsublookups - else - report_issue(i,what,sequence,"missing") - rule.lookups=nil - break - end - else - report_issue(i,what,sequence,"bad") - rule.lookups=nil - break - end - else - sublookupcheck[lookupid]=sublookupcheck[lookupid]+1 - end - rlookups[index]=h or false - else - rlookups[index]=false - end - end - end - end - end - end - end - for i,n in sortedhash(sublookupcheck) do - local l=lookups[i] - local t=l.type - if n==0 and t~="extension" then - local d=l.done - report("%s lookup %s of type %a is not used",what,d and d.name or l.name,t) - end - end - end - local function readscripts(f,fontdata,what,lookuptypes,lookuphandlers,lookupstoo) - local datatable=fontdata.tables[what] - if not datatable then - return - end - local tableoffset=datatable.offset - if not tableoffset then - return - end - local scriptoffset,featureoffset,lookupoffset=readscriptoffsets(f,fontdata,tableoffset) - if not scriptoffset then - return - end - local scripts=readscriplan(f,fontdata,scriptoffset) - local features=readfeatures(f,fontdata,featureoffset) - local scriptlangs,featurehash,featureorder=reorderfeatures(fontdata,scripts,features) - if fontdata.features then - fontdata.features[what]=scriptlangs - else - fontdata.features={ [what]=scriptlangs } - end - if not lookupstoo then - return - end - local lookups=readlookups(f,lookupoffset,lookuptypes,featurehash,featureorder) - if lookups then - resolvelookups(f,lookupoffset,fontdata,lookups,lookuptypes,lookuphandlers,what) - end - end - local function checkkerns(f,fontdata,specification) - local datatable=fontdata.tables.kern - if not datatable then - return - end - local features=fontdata.features - local gposfeatures=features and features.gpos - local name - if not gposfeatures or not gposfeatures.kern then - name="kern" - elseif specification.globalkerns then - name="globalkern" - else - report("ignoring global kern table using gpos kern feature") - return - end - report("adding global kern table as gpos feature %a",name) - setposition(f,datatable.offset) - local version=readushort(f) - local noftables=readushort(f) - local kerns=setmetatableindex("table") - for i=1,noftables do - local version=readushort(f) - local length=readushort(f) - local coverage=readushort(f) - local format=bit32.rshift(coverage,8) - if format==0 then - local nofpairs=readushort(f) - local searchrange=readushort(f) - local entryselector=readushort(f) - local rangeshift=readushort(f) - for i=1,nofpairs do - kerns[readushort(f)][readushort(f)]=readfword(f) - end - elseif format==2 then - else - end - end - local feature={ dflt={ dflt=true } } - if not features then - fontdata.features={ gpos={ [name]=feature } } - elseif not gposfeatures then - fontdata.features.gpos={ [name]=feature } - else - gposfeatures[name]=feature - end - local sequences=fontdata.sequences - if not sequences then - sequences={} - fontdata.sequences=sequences - end - local nofsequences=#sequences+1 - sequences[nofsequences]={ - index=nofsequences, - name=name, - steps={ - { - coverage=kerns, - format="kern", - }, - }, - nofsteps=1, - type="gpos_pair", - flags={ false,false,false,false }, - order={ name }, - features={ [name]=feature }, - } - end - function readers.gsub(f,fontdata,specification) - if specification.details then - readscripts(f,fontdata,"gsub",gsubtypes,gsubhandlers,specification.lookups) - end - end - function readers.gpos(f,fontdata,specification) - if specification.details then - readscripts(f,fontdata,"gpos",gpostypes,gposhandlers,specification.lookups) - if specification.lookups then - checkkerns(f,fontdata,specification) - end - end - end -end -function readers.gdef(f,fontdata,specification) - if specification.glyphs then - local datatable=fontdata.tables.gdef - if datatable then - local tableoffset=datatable.offset - setposition(f,tableoffset) - local version=readulong(f) - local classoffset=tableoffset+readushort(f) - local attachmentoffset=tableoffset+readushort(f) - local ligaturecarets=tableoffset+readushort(f) - local markclassoffset=tableoffset+readushort(f) - local marksetsoffset=version==0x00010002 and (tableoffset+readushort(f)) - local glyphs=fontdata.glyphs - local marks={} - local markclasses=setmetatableindex("table") - local marksets=setmetatableindex("table") - fontdata.marks=marks - fontdata.markclasses=markclasses - fontdata.marksets=marksets - setposition(f,classoffset) - local classformat=readushort(f) - if classformat==1 then - local firstindex=readushort(f) - local lastindex=firstindex+readushort(f)-1 - for index=firstindex,lastindex do - local class=classes[readushort(f)] - if class=="mark" then - marks[index]=true - end - glyphs[index].class=class - end - elseif classformat==2 then - local nofranges=readushort(f) - for i=1,nofranges do - local firstindex=readushort(f) - local lastindex=readushort(f) - local class=classes[readushort(f)] - if class then - for index=firstindex,lastindex do - glyphs[index].class=class - if class=="mark" then - marks[index]=true - end - end - end - end - end - setposition(f,markclassoffset) - local classformat=readushort(f) - if classformat==1 then - local firstindex=readushort(f) - local lastindex=firstindex+readushort(f)-1 - for index=firstindex,lastindex do - markclasses[readushort(f)][index]=true - end - elseif classformat==2 then - local nofranges=readushort(f) - for i=1,nofranges do - local firstindex=readushort(f) - local lastindex=readushort(f) - local class=markclasses[readushort(f)] - for index=firstindex,lastindex do - class[index]=true - end - end - end - if marksetsoffset and marksetsoffset>tableoffset then - setposition(f,marksetsoffset) - local format=readushort(f) - if format==1 then - local nofsets=readushort(f) - local sets={} - for i=1,nofsets do - sets[i]=readulong(f) - end - for i=1,nofsets do - local offset=sets[i] - if offset~=0 then - marksets[i]=readcoverage(f,marksetsoffset+offset) - end - end - end - end - end - end -end -local function readmathvalue(f) - local v=readshort(f) - skipshort(f,1) - return v -end -local function readmathconstants(f,fontdata,offset) - setposition(f,offset) - fontdata.mathconstants={ - ScriptPercentScaleDown=readshort(f), - ScriptScriptPercentScaleDown=readshort(f), - DelimitedSubFormulaMinHeight=readushort(f), - DisplayOperatorMinHeight=readushort(f), - MathLeading=readmathvalue(f), - AxisHeight=readmathvalue(f), - AccentBaseHeight=readmathvalue(f), - FlattenedAccentBaseHeight=readmathvalue(f), - SubscriptShiftDown=readmathvalue(f), - SubscriptTopMax=readmathvalue(f), - SubscriptBaselineDropMin=readmathvalue(f), - SuperscriptShiftUp=readmathvalue(f), - SuperscriptShiftUpCramped=readmathvalue(f), - SuperscriptBottomMin=readmathvalue(f), - SuperscriptBaselineDropMax=readmathvalue(f), - SubSuperscriptGapMin=readmathvalue(f), - SuperscriptBottomMaxWithSubscript=readmathvalue(f), - SpaceAfterScript=readmathvalue(f), - UpperLimitGapMin=readmathvalue(f), - UpperLimitBaselineRiseMin=readmathvalue(f), - LowerLimitGapMin=readmathvalue(f), - LowerLimitBaselineDropMin=readmathvalue(f), - StackTopShiftUp=readmathvalue(f), - StackTopDisplayStyleShiftUp=readmathvalue(f), - StackBottomShiftDown=readmathvalue(f), - StackBottomDisplayStyleShiftDown=readmathvalue(f), - StackGapMin=readmathvalue(f), - StackDisplayStyleGapMin=readmathvalue(f), - StretchStackTopShiftUp=readmathvalue(f), - StretchStackBottomShiftDown=readmathvalue(f), - StretchStackGapAboveMin=readmathvalue(f), - StretchStackGapBelowMin=readmathvalue(f), - FractionNumeratorShiftUp=readmathvalue(f), - FractionNumeratorDisplayStyleShiftUp=readmathvalue(f), - FractionDenominatorShiftDown=readmathvalue(f), - FractionDenominatorDisplayStyleShiftDown=readmathvalue(f), - FractionNumeratorGapMin=readmathvalue(f), - FractionNumeratorDisplayStyleGapMin=readmathvalue(f), - FractionRuleThickness=readmathvalue(f), - FractionDenominatorGapMin=readmathvalue(f), - FractionDenominatorDisplayStyleGapMin=readmathvalue(f), - SkewedFractionHorizontalGap=readmathvalue(f), - SkewedFractionVerticalGap=readmathvalue(f), - OverbarVerticalGap=readmathvalue(f), - OverbarRuleThickness=readmathvalue(f), - OverbarExtraAscender=readmathvalue(f), - UnderbarVerticalGap=readmathvalue(f), - UnderbarRuleThickness=readmathvalue(f), - UnderbarExtraDescender=readmathvalue(f), - RadicalVerticalGap=readmathvalue(f), - RadicalDisplayStyleVerticalGap=readmathvalue(f), - RadicalRuleThickness=readmathvalue(f), - RadicalExtraAscender=readmathvalue(f), - RadicalKernBeforeDegree=readmathvalue(f), - RadicalKernAfterDegree=readmathvalue(f), - RadicalDegreeBottomRaisePercent=readshort(f), - } -end -local function readmathglyphinfo(f,fontdata,offset) - setposition(f,offset) - local italics=readushort(f) - local accents=readushort(f) - local extensions=readushort(f) - local kerns=readushort(f) - local glyphs=fontdata.glyphs - if italics~=0 then - setposition(f,offset+italics) - local coverage=readushort(f) - local nofglyphs=readushort(f) - coverage=readcoverage(f,offset+italics+coverage,true) - setposition(f,offset+italics+4) - for i=1,nofglyphs do - local italic=readmathvalue(f) - if italic~=0 then - local glyph=glyphs[coverage[i]] - local math=glyph.math - if not math then - glyph.math={ italic=italic } - else - math.italic=italic - end - end - end - fontdata.hasitalics=true - end - if accents~=0 then - setposition(f,offset+accents) - local coverage=readushort(f) - local nofglyphs=readushort(f) - coverage=readcoverage(f,offset+accents+coverage,true) - setposition(f,offset+accents+4) - for i=1,nofglyphs do - local accent=readmathvalue(f) - if accent~=0 then - local glyph=glyphs[coverage[i]] - local math=glyph.math - if not math then - glyph.math={ accent=accent } - else - math.accent=accent - end - end - end - end - if extensions~=0 then - setposition(f,offset+extensions) - end - if kerns~=0 then - local kernoffset=offset+kerns - setposition(f,kernoffset) - local coverage=readushort(f) - local nofglyphs=readushort(f) - if nofglyphs>0 then - local function get(offset) - setposition(f,kernoffset+offset) - local n=readushort(f) - if n==0 then - local k=readmathvalue(f) - if k==0 then - else - return { { kern=k } } - end - else - local l={} - for i=1,n do - l[i]={ height=readmathvalue(f) } - end - for i=1,n do - l[i].kern=readmathvalue(f) - end - l[n+1]={ kern=readmathvalue(f) } - return l - end - end - local kernsets={} - for i=1,nofglyphs do - local topright=readushort(f) - local topleft=readushort(f) - local bottomright=readushort(f) - local bottomleft=readushort(f) - kernsets[i]={ - topright=topright~=0 and topright or nil, - topleft=topleft~=0 and topleft or nil, - bottomright=bottomright~=0 and bottomright or nil, - bottomleft=bottomleft~=0 and bottomleft or nil, - } - end - coverage=readcoverage(f,kernoffset+coverage,true) - for i=1,nofglyphs do - local kernset=kernsets[i] - if next(kernset) then - local k=kernset.topright if k then kernset.topright=get(k) end - local k=kernset.topleft if k then kernset.topleft=get(k) end - local k=kernset.bottomright if k then kernset.bottomright=get(k) end - local k=kernset.bottomleft if k then kernset.bottomleft=get(k) end - if next(kernset) then - local glyph=glyphs[coverage[i]] - local math=glyph.math - if math then - math.kerns=kernset - else - glyph.math={ kerns=kernset } - end - end - end - end - end - end -end -local function readmathvariants(f,fontdata,offset) - setposition(f,offset) - local glyphs=fontdata.glyphs - local minoverlap=readushort(f) - local vcoverage=readushort(f) - local hcoverage=readushort(f) - local vnofglyphs=readushort(f) - local hnofglyphs=readushort(f) - local vconstruction={} - local hconstruction={} - for i=1,vnofglyphs do - vconstruction[i]=readushort(f) - end - for i=1,hnofglyphs do - hconstruction[i]=readushort(f) - end - fontdata.mathconstants.MinConnectorOverlap=minoverlap - local function get(offset,coverage,nofglyphs,construction,kvariants,kparts,kitalic) - if coverage~=0 and nofglyphs>0 then - local coverage=readcoverage(f,offset+coverage,true) - for i=1,nofglyphs do - local c=construction[i] - if c~=0 then - local index=coverage[i] - local glyph=glyphs[index] - local math=glyph.math - setposition(f,offset+c) - local assembly=readushort(f) - local nofvariants=readushort(f) - if nofvariants>0 then - local variants,v=nil,0 - for i=1,nofvariants do - local variant=readushort(f) - if variant==index then - elseif variants then - v=v+1 - variants[v]=variant - else - v=1 - variants={ variant } - end - skipshort(f) - end - if not variants then - elseif not math then - math={ [kvariants]=variants } - glyph.math=math - else - math[kvariants]=variants - end - end - if assembly~=0 then - setposition(f,offset+c+assembly) - local italic=readmathvalue(f) - local nofparts=readushort(f) - local parts={} - for i=1,nofparts do - local p={ - glyph=readushort(f), - start=readushort(f), - ["end"]=readushort(f), - advance=readushort(f), - } - local flags=readushort(f) - if bittest(flags,0x0001) then - p.extender=1 - end - parts[i]=p - end - if not math then - math={ - [kparts]=parts - } - glyph.math=math - else - math[kparts]=parts - end - if italic and italic~=0 then - math[kitalic]=italic - end - end - end - end - end - end - get(offset,vcoverage,vnofglyphs,vconstruction,"vvariants","vparts","vitalic") - get(offset,hcoverage,hnofglyphs,hconstruction,"hvariants","hparts","hitalic") -end -function readers.math(f,fontdata,specification) - if specification.glyphs then - local datatable=fontdata.tables.math - if datatable then - local tableoffset=datatable.offset - setposition(f,tableoffset) - local version=readulong(f) - if version~=0x00010000 then - report("table version %a of %a is not supported (yet), maybe font %s is bad",version,"math",fontdata.filename) - return - end - local constants=readushort(f) - local glyphinfo=readushort(f) - local variants=readushort(f) - if constants==0 then - report("the math table of %a has no constants",fontdata.filename) - else - readmathconstants(f,fontdata,tableoffset+constants) - end - if glyphinfo~=0 then - readmathglyphinfo(f,fontdata,tableoffset+glyphinfo) - end - if variants~=0 then - readmathvariants(f,fontdata,tableoffset+variants) - end - end - end -end -function readers.colr(f,fontdata,specification) - local datatable=fontdata.tables.colr - if datatable then - if specification.glyphs then - local tableoffset=datatable.offset - setposition(f,tableoffset) - local version=readushort(f) - if version~=0 then - report("table version %a of %a is not supported (yet), maybe font %s is bad",version,"colr",fontdata.filename) - return - end - if not fontdata.tables.cpal then - report("color table %a in font %a has no mandate %a table","colr",fontdata.filename,"cpal") - fontdata.colorpalettes={} - end - local glyphs=fontdata.glyphs - local nofglyphs=readushort(f) - local baseoffset=readulong(f) - local layeroffset=readulong(f) - local noflayers=readushort(f) - local layerrecords={} - local maxclass=0 - setposition(f,tableoffset+layeroffset) - for i=1,noflayers do - local slot=readushort(f) - local class=readushort(f) - if class<0xFFFF then - class=class+1 - if class>maxclass then - maxclass=class - end - end - layerrecords[i]={ - slot=slot, - class=class, - } - end - fontdata.maxcolorclass=maxclass - setposition(f,tableoffset+baseoffset) - for i=0,nofglyphs-1 do - local glyphindex=readushort(f) - local firstlayer=readushort(f) - local noflayers=readushort(f) - local t={} - for i=1,noflayers do - t[i]=layerrecords[firstlayer+i] - end - glyphs[glyphindex].colors=t - end - end - fontdata.hascolor=true - end -end -function readers.cpal(f,fontdata,specification) - if specification.glyphs then - local datatable=fontdata.tables.cpal - if datatable then - local tableoffset=datatable.offset - setposition(f,tableoffset) - local version=readushort(f) - if version>1 then - report("table version %a of %a is not supported (yet), maybe font %s is bad",version,"cpal",fontdata.filename) - return - end - local nofpaletteentries=readushort(f) - local nofpalettes=readushort(f) - local nofcolorrecords=readushort(f) - local firstcoloroffset=readulong(f) - local colorrecords={} - local palettes={} - for i=1,nofpalettes do - palettes[i]=readushort(f) - end - if version==1 then - local palettettypesoffset=readulong(f) - local palettelabelsoffset=readulong(f) - local paletteentryoffset=readulong(f) - end - setposition(f,tableoffset+firstcoloroffset) - for i=1,nofcolorrecords do - local b,g,r,a=readbytes(f,4) - colorrecords[i]={ - r,g,b,a~=255 and a or nil, - } - end - for i=1,nofpalettes do - local p={} - local o=palettes[i] - for j=1,nofpaletteentries do - p[j]=colorrecords[o+j] - end - palettes[i]=p - end - fontdata.colorpalettes=palettes - end - end -end -function readers.svg(f,fontdata,specification) - local datatable=fontdata.tables.svg - if datatable then - if specification.glyphs then - local tableoffset=datatable.offset - setposition(f,tableoffset) - local version=readushort(f) - if version~=0 then - report("table version %a of %a is not supported (yet), maybe font %s is bad",version,"svg",fontdata.filename) - return - end - local glyphs=fontdata.glyphs - local indexoffset=tableoffset+readulong(f) - local reserved=readulong(f) - setposition(f,indexoffset) - local nofentries=readushort(f) - local entries={} - for i=1,nofentries do - entries[i]={ - first=readushort(f), - last=readushort(f), - offset=indexoffset+readulong(f), - length=readulong(f), - } - end - for i=1,nofentries do - local entry=entries[i] - setposition(f,entry.offset) - entries[i]={ - first=entry.first, - last=entry.last, - data=readstring(f,entry.length) - } - end - fontdata.svgshapes=entries - end - fontdata.hascolor=true - end -end - -end --- [luaotfload, fontloader-2017-02-11.lua scope for “font-dsp”] --- - - -do --- [luaotfload, fontloader-2017-02-11.lua scope for “font-oup” f7237130b648a4c2b477dabedc7f90e8] --- - -if not modules then modules={} end modules ['font-oup']={ - version=1.001, - comment="companion to font-ini.mkiv", - 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 P,R,S=lpeg.P,lpeg.R,lpeg.S -local lpegmatch=lpeg.match -local insert,remove,copy,unpack=table.insert,table.remove,table.copy,table.unpack -local formatters=string.formatters -local sortedkeys=table.sortedkeys -local sortedhash=table.sortedhash -local tohash=table.tohash -local report=logs.reporter("otf reader") -local trace_markwidth=false trackers.register("otf.markwidth",function(v) trace_markwidth=v end) -local readers=fonts.handlers.otf.readers -local privateoffset=fonts.constructors and fonts.constructors.privateoffset or 0xF0000 -local f_private=formatters["P%05X"] -local f_unicode=formatters["U%05X"] -local f_index=formatters["I%05X"] -local f_character_y=formatters["%C"] -local f_character_n=formatters["[ %C ]"] -local check_duplicates=true -local check_soft_hyphen=false -directives.register("otf.checksofthyphen",function(v) - check_soft_hyphen=v -end) -local function replaced(list,index,replacement) - if type(list)=="number" then - return replacement - elseif type(replacement)=="table" then - local t={} - local n=index-1 - for i=1,n do - t[i]=list[i] - end - for i=1,#replacement do - n=n+1 - t[n]=replacement[i] - end - for i=index+1,#list do - n=n+1 - t[n]=list[i] - end - else - list[index]=replacement - return list - end -end -local function unifyresources(fontdata,indices) - local descriptions=fontdata.descriptions - local resources=fontdata.resources - if not descriptions or not resources then - return - end - local variants=fontdata.resources.variants - if variants then - for selector,unicodes in next,variants do - for unicode,index in next,unicodes do - unicodes[unicode]=indices[index] - end - end - end - local function remark(marks) - if marks then - local newmarks={} - for k,v in next,marks do - local u=indices[k] - if u then - newmarks[u]=v - else - report("discarding mark %i",k) - end - end - return newmarks - end - end - local marks=resources.marks - if marks then - resources.marks=remark(marks) - end - local markclasses=resources.markclasses - if markclasses then - for class,marks in next,markclasses do - markclasses[class]=remark(marks) - end - end - local marksets=resources.marksets - if marksets then - for class,marks in next,marksets do - marksets[class]=remark(marks) - end - end - local done={} - local duplicates=check_duplicates and resources.duplicates - if duplicates and not next(duplicates) then - duplicates=false - end - local function recover(cover) - for i=1,#cover do - local c=cover[i] - if not done[c] then - local t={} - for k,v in next,c do - t[indices[k]]=v - end - cover[i]=t - done[c]=d - end - end - end - local function recursed(c) - local t={} - for g,d in next,c do - if type(d)=="table" then - t[indices[g]]=recursed(d) - else - t[g]=indices[d] - end - end - return t - end - local function unifythem(sequences) - if not sequences then - return - end - for i=1,#sequences do - local sequence=sequences[i] - local kind=sequence.type - local steps=sequence.steps - local features=sequence.features - if steps then - for i=1,#steps do - local step=steps[i] - if kind=="gsub_single" then - local c=step.coverage - if c then - local t1=done[c] - if not t1 then - t1={} - if duplicates then - for g1,d1 in next,c do - local ug1=indices[g1] - local ud1=indices[d1] - t1[ug1]=ud1 - local dg1=duplicates[ug1] - if dg1 then - for u in next,dg1 do - t1[u]=ud1 - end - end - end - else - for g1,d1 in next,c do - t1[indices[g1]]=indices[d1] - end - end - done[c]=t1 - end - step.coverage=t1 - end - elseif kind=="gpos_pair" then - local c=step.coverage - if c then - local t1=done[c] - if not t1 then - t1={} - for g1,d1 in next,c do - local t2=done[d1] - if not t2 then - t2={} - for g2,d2 in next,d1 do - t2[indices[g2]]=d2 - end - done[d1]=t2 - end - t1[indices[g1]]=t2 - end - done[c]=t1 - end - step.coverage=t1 - end - elseif kind=="gsub_ligature" then - local c=step.coverage - if c then - step.coverage=recursed(c) - end - elseif kind=="gsub_alternate" or kind=="gsub_multiple" then - local c=step.coverage - if c then - local t1=done[c] - if not t1 then - t1={} - if duplicates then - for g1,d1 in next,c do - for i=1,#d1 do - d1[i]=indices[d1[i]] - end - local ug1=indices[g1] - t1[ug1]=d1 - local dg1=duplicates[ug1] - if dg1 then - for u in next,dg1 do - t1[u]=copy(d1) - end - end - end - else - for g1,d1 in next,c do - for i=1,#d1 do - d1[i]=indices[d1[i]] - end - t1[indices[g1]]=d1 - end - end - done[c]=t1 - end - step.coverage=t1 - end - elseif kind=="gpos_mark2base" or kind=="gpos_mark2mark" or kind=="gpos_mark2ligature" then - local c=step.coverage - if c then - local t1=done[c] - if not t1 then - t1={} - for g1,d1 in next,c do - t1[indices[g1]]=d1 - end - done[c]=t1 - end - step.coverage=t1 - end - local c=step.baseclasses - if c then - local t1=done[c] - if not t1 then - for g1,d1 in next,c do - local t2=done[d1] - if not t2 then - t2={} - for g2,d2 in next,d1 do - t2[indices[g2]]=d2 - end - done[d1]=t2 - end - c[g1]=t2 - end - done[c]=c - end - end - elseif kind=="gpos_single" then - local c=step.coverage - if c then - local t1=done[c] - if not t1 then - t1={} - if duplicates then - for g1,d1 in next,c do - local ug1=indices[g1] - t1[ug1]=d1 - local dg1=duplicates[ug1] - if dg1 then - for u in next,dg1 do - t1[u]=d1 - end - end - end - else - for g1,d1 in next,c do - t1[indices[g1]]=d1 - end - end - done[c]=t1 - end - step.coverage=t1 - end - elseif kind=="gpos_cursive" then - local c=step.coverage - if c then - local t1=done[c] - if not t1 then - t1={} - if duplicates then - for g1,d1 in next,c do - local ug1=indices[g1] - t1[ug1]=d1 - local dg1=duplicates[ug1] - if dg1 then - for u in next,dg1 do - t1[u]=copy(d1) - end - end - end - else - for g1,d1 in next,c do - t1[indices[g1]]=d1 - end - end - done[c]=t1 - end - step.coverage=t1 - end - end - local rules=step.rules - if rules then - for i=1,#rules do - local rule=rules[i] - local before=rule.before if before then recover(before) end - local after=rule.after if after then recover(after) end - local current=rule.current if current then recover(current) end - local replacements=rule.replacements - if replacements then - if not done[replacements] then - local r={} - for k,v in next,replacements do - r[indices[k]]=indices[v] - end - rule.replacements=r - done[replacements]=r - end - end - end - end - end - end - end - end - unifythem(resources.sequences) - unifythem(resources.sublookups) -end -local function copyduplicates(fontdata) - if check_duplicates then - local descriptions=fontdata.descriptions - local resources=fontdata.resources - local duplicates=resources.duplicates - if check_soft_hyphen then - local ds=descriptions[0xAD] - if not ds or ds.width==0 then - if ds then - descriptions[0xAD]=nil - report("patching soft hyphen") - else - report("adding soft hyphen") - end - if not duplicates then - duplicates={} - resources.duplicates=duplicates - end - local dh=duplicates[0x2D] - if dh then - dh[#dh+1]={ [0xAD]=true } - else - duplicates[0x2D]={ [0xAD]=true } - end - end - end - if duplicates then - for u,d in next,duplicates do - local du=descriptions[u] - if du then - local t={ f_character_y(u),"@",f_index(du.index),"->" } - local n=0 - local m=25 - for u in next,d do - if descriptions[u] then - if n<m then - t[n+4]=f_character_n(u) - end - else - local c=copy(du) - c.unicode=u - descriptions[u]=c - if n<m then - t[n+4]=f_character_y(u) - end - end - n=n+1 - end - if n<=m then - report("duplicates: %i : % t",n,t) - else - report("duplicates: %i : % t ...",n,t) - end - else - end - end - end - end -end -local ignore={ - ["notdef"]=true, - [".notdef"]=true, - ["null"]=true, - [".null"]=true, - ["nonmarkingreturn"]=true, -} -local function checklookups(fontdata,missing,nofmissing) - local descriptions=fontdata.descriptions - local resources=fontdata.resources - if missing and nofmissing and nofmissing<=0 then - return - end - local singles={} - local alternates={} - local ligatures={} - if not missing then - missing={} - nofmissing=0 - for u,d in next,descriptions do - if not d.unicode then - nofmissing=nofmissing+1 - missing[u]=true - end - end - end - local function collectthem(sequences) - if not sequences then - return - end - for i=1,#sequences do - local sequence=sequences[i] - local kind=sequence.type - local steps=sequence.steps - if steps then - for i=1,#steps do - local step=steps[i] - if kind=="gsub_single" then - local c=step.coverage - if c then - singles[#singles+1]=c - end - elseif kind=="gsub_alternate" then - local c=step.coverage - if c then - alternates[#alternates+1]=c - end - elseif kind=="gsub_ligature" then - local c=step.coverage - if c then - ligatures[#ligatures+1]=c - end - end - end - end - end - end - collectthem(resources.sequences) - collectthem(resources.sublookups) - local loops=0 - while true do - loops=loops+1 - local old=nofmissing - for i=1,#singles do - local c=singles[i] - for g1,g2 in next,c do - if missing[g1] then - local u2=descriptions[g2].unicode - if u2 then - missing[g1]=false - descriptions[g1].unicode=u2 - nofmissing=nofmissing-1 - end - end - if missing[g2] then - local u1=descriptions[g1].unicode - if u1 then - missing[g2]=false - descriptions[g2].unicode=u1 - nofmissing=nofmissing-1 - end - end - end - end - for i=1,#alternates do - local c=alternates[i] - for g1,d1 in next,c do - if missing[g1] then - for i=1,#d1 do - local g2=d1[i] - local u2=descriptions[g2].unicode - if u2 then - missing[g1]=false - descriptions[g1].unicode=u2 - nofmissing=nofmissing-1 - end - end - end - if not missing[g1] then - for i=1,#d1 do - local g2=d1[i] - if missing[g2] then - local u1=descriptions[g1].unicode - if u1 then - missing[g2]=false - descriptions[g2].unicode=u1 - nofmissing=nofmissing-1 - end - end - end - end - end - end - if nofmissing<=0 then - report("all done in %s loops",loops) - return - elseif old==nofmissing then - break - end - end - local t,n - local function recursed(c) - for g,d in next,c do - if g~="ligature" then - local u=descriptions[g].unicode - if u then - n=n+1 - t[n]=u - recursed(d) - n=n-1 - end - elseif missing[d] then - local l={} - local m=0 - for i=1,n do - local u=t[i] - if type(u)=="table" then - for i=1,#u do - m=m+1 - l[m]=u[i] - end - else - m=m+1 - l[m]=u - end - end - missing[d]=false - descriptions[d].unicode=l - nofmissing=nofmissing-1 - end - end - end - if nofmissing>0 then - t={} - n=0 - local loops=0 - while true do - loops=loops+1 - local old=nofmissing - for i=1,#ligatures do - recursed(ligatures[i]) - end - if nofmissing<=0 then - report("all done in %s loops",loops) - return - elseif old==nofmissing then - break - end - end - t=nil - n=0 - end - if nofmissing>0 then - local done={} - for i,r in next,missing do - if r then - local data=descriptions[i] - local name=data and data.name or f_index(i) - if not ignore[name] then - done[name]=true - end - end - end - if next(done) then - report("not unicoded: % t",table.sortedkeys(done)) - end - end -end -local function unifymissing(fontdata) - if not fonts.mappings then - require("font-map") - require("font-agl") - end - local unicodes={} - local private=fontdata.private - local resources=fontdata.resources - resources.unicodes=unicodes - for unicode,d in next,fontdata.descriptions do - if unicode<privateoffset then - local name=d.name - if name then - unicodes[name]=unicode - end - end - end - fonts.mappings.addtounicode(fontdata,fontdata.filename,checklookups) - resources.unicodes=nil -end -local function unifyglyphs(fontdata,usenames) - local private=fontdata.private or privateoffset - local glyphs=fontdata.glyphs - local indices={} - local descriptions={} - local names=usenames and {} - local resources=fontdata.resources - local zero=glyphs[0] - local zerocode=zero.unicode - if not zerocode then - zerocode=private - zero.unicode=zerocode - private=private+1 - end - descriptions[zerocode]=zero - if names then - local name=glyphs[0].name or f_private(zerocode) - indices[0]=name - names[name]=zerocode - else - indices[0]=zerocode - end - for index=1,#glyphs do - local glyph=glyphs[index] - local unicode=glyph.unicode - if not unicode then - unicode=private - if names then - local name=glyph.name or f_private(unicode) - indices[index]=name - names[name]=unicode - else - indices[index]=unicode - end - private=private+1 - elseif descriptions[unicode] then - report("assigning private unicode %U to glyph indexed %05X (%C)",private,index,unicode) - unicode=private - if names then - local name=glyph.name or f_private(unicode) - indices[index]=name - names[name]=unicode - else - indices[index]=unicode - end - private=private+1 - else - if names then - local name=glyph.name or f_unicode(unicode) - indices[index]=name - names[name]=unicode - else - indices[index]=unicode - end - end - descriptions[unicode]=glyph - end - for index=1,#glyphs do - local math=glyphs[index].math - if math then - local list=math.vparts - if list then - for i=1,#list do local l=list[i] l.glyph=indices[l.glyph] end - end - local list=math.hparts - if list then - for i=1,#list do local l=list[i] l.glyph=indices[l.glyph] end - end - local list=math.vvariants - if list then - for i=1,#list do list[i]=indices[list[i]] end - end - local list=math.hvariants - if list then - for i=1,#list do list[i]=indices[list[i]] end - end - end - end - local colorpalettes=resources.colorpalettes - if colorpalettes then - for index=1,#glyphs do - local colors=glyphs[index].colors - if colors then - for i=1,#colors do - local c=colors[i] - c.slot=indices[c.slot] - end - end - end - end - fontdata.private=private - fontdata.glyphs=nil - fontdata.names=names - fontdata.descriptions=descriptions - fontdata.hashmethod=hashmethod - return indices,names -end -local p_bogusname=( - (P("uni")+P("UNI")+P("Uni")+P("U")+P("u"))*S("Xx")^0*R("09","AF")^1+(P("identity")+P("Identity")+P("IDENTITY"))*R("09","AF")^1+(P("index")+P("Index")+P("INDEX"))*R("09")^1 -)*P(-1) -local function stripredundant(fontdata) - local descriptions=fontdata.descriptions - if descriptions then - local n=0 - local c=0 - for unicode,d in next,descriptions do - local name=d.name - if name and lpegmatch(p_bogusname,name) then - d.name=nil - n=n+1 - end - if d.class=="base" then - d.class=nil - c=c+1 - end - end - if n>0 then - report("%s bogus names removed (verbose unicode)",n) - end - if c>0 then - report("%s base class tags removed (default is base)",c) - end - end -end -function readers.getcomponents(fontdata) - local resources=fontdata.resources - if resources then - local sequences=resources.sequences - if sequences then - local collected={} - for i=1,#sequences do - local sequence=sequences[i] - if sequence.type=="gsub_ligature" then - local steps=sequence.steps - if steps then - local l={} - local function traverse(p,k,v) - if k=="ligature" then - collected[v]={ unpack(l) } - else - insert(l,k) - for k,vv in next,v do - traverse(p,k,vv) - end - remove(l) - end - end - for i=1,#steps do - local coverage=steps[i].coverage - if coverage then - for k,v in next,coverage do - traverse(k,k,v) - end - end - end - end - end - end - if next(collected) then - while true do - local done=false - for k,v in next,collected do - for i=1,#v do - local vi=v[i] - if vi==k then - collected[k]=nil - break - else - local c=collected[vi] - if c then - done=true - local t={} - local n=i-1 - for j=1,n do - t[j]=v[j] - end - for j=1,#c do - n=n+1 - t[n]=c[j] - end - for j=i+1,#v do - n=n+1 - t[n]=v[j] - end - collected[k]=t - break - end - end - end - end - if not done then - break - end - end - return collected - end - end - end -end -readers.unifymissing=unifymissing -function readers.rehash(fontdata,hashmethod) - if not (fontdata and fontdata.glyphs) then - return - end - if hashmethod=="indices" then - fontdata.hashmethod="indices" - elseif hashmethod=="names" then - fontdata.hashmethod="names" - local indices=unifyglyphs(fontdata,true) - unifyresources(fontdata,indices) - copyduplicates(fontdata) - unifymissing(fontdata) - else - fontdata.hashmethod="unicode" - local indices=unifyglyphs(fontdata) - unifyresources(fontdata,indices) - copyduplicates(fontdata) - unifymissing(fontdata) - stripredundant(fontdata) - end -end -function readers.checkhash(fontdata) - local hashmethod=fontdata.hashmethod - if hashmethod=="unicodes" then - fontdata.names=nil - elseif hashmethod=="names" and fontdata.names then - unifyresources(fontdata,fontdata.names) - copyduplicates(fontdata) - fontdata.hashmethod="unicode" - fontdata.names=nil - else - readers.rehash(fontdata,"unicode") - end -end -function readers.addunicodetable(fontdata) - local resources=fontdata.resources - local unicodes=resources.unicodes - if not unicodes then - local descriptions=fontdata.descriptions - if descriptions then - unicodes={} - resources.unicodes=unicodes - for u,d in next,descriptions do - local n=d.name - if n then - unicodes[n]=u - end - end - end - end -end -local concat,sort=table.concat,table.sort -local next,type,tostring=next,type,tostring -local criterium=1 -local threshold=0 -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") -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 -function readers.pack(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 sequences=resources.sequences - local sublookups=resources.sublookups - local features=resources.features - local palettes=resources.colorpalettes - local chardata=characters and characters.data - local descriptions=data.descriptions or data.glyphs - if not descriptions then - return - end - 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,descriptions do - local boundingbox=description.boundingbox - if boundingbox then - description.boundingbox=pack_indexed(boundingbox) - 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 - end - local function packthem(sequences) - for i=1,#sequences do - local sequence=sequences[i] - local kind=sequence.type - local steps=sequence.steps - local order=sequence.order - local features=sequence.features - local flags=sequence.flags - if steps then - for i=1,#steps do - local step=steps[i] - if kind=="gpos_pair" then - local c=step.coverage - if c then - if step.format=="kern" then - for g1,d1 in next,c do - c[g1]=pack_normal(d1) - end - else - for g1,d1 in next,c do - for g2,d2 in next,d1 do - local f=d2[1] if f then d2[1]=pack_indexed(f) end - local s=d2[2] if s then d2[2]=pack_indexed(s) end - end - end - end - end - elseif kind=="gpos_single" then - local c=step.coverage - if c then - if step.format=="kern" then - step.coverage=pack_normal(c) - else - for g1,d1 in next,c do - c[g1]=pack_indexed(d1) - end - end - end - elseif kind=="gpos_cursive" then - local c=step.coverage - if c then - for g1,d1 in next,c do - local f=d1[2] if f then d1[2]=pack_indexed(f) end - local s=d1[3] if s then d1[3]=pack_indexed(s) end - end - end - elseif kind=="gpos_mark2base" or kind=="gpos_mark2mark" then - local c=step.baseclasses - if c then - for g1,d1 in next,c do - for g2,d2 in next,d1 do - d1[g2]=pack_indexed(d2) - end - end - end - local c=step.coverage - if c then - for g1,d1 in next,c do - d1[2]=pack_indexed(d1[2]) - end - end - elseif kind=="gpos_mark2ligature" then - local c=step.baseclasses - if c then - for g1,d1 in next,c do - for g2,d2 in next,d1 do - for g3,d3 in next,d2 do - d2[g3]=pack_indexed(d3) - end - end - end - end - local c=step.coverage - if c then - for g1,d1 in next,c do - d1[2]=pack_indexed(d1[2]) - end - end - end - local rules=step.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.lookups if r then rule.lookups=pack_mixed (r) end - local r=rule.replacements if r then rule.replacements=pack_flat (r) end - end - end - end - end - if order then - sequence.order=pack_indexed(order) - end - if features then - for script,feature in next,features do - features[script]=pack_normal(feature) - end - end - if flags then - sequence.flags=pack_normal(flags) - end - end - end - if sequences then - packthem(sequences) - end - if sublookups then - packthem(sublookups) - end - if features then - for k,list in next,features do - for feature,spec in next,list do - list[feature]=pack_normal(spec) - end - end - end - if palettes then - for i=1,#palettes do - local p=palettes[i] - for j=1,#p do - p[j]=pack_indexed(p[j]) - 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,descriptions do - local math=description.math - if math then - local kerns=math.kerns - if kerns then - math.kerns=pack_normal(kerns) - end - end - end - local function packthem(sequences) - for i=1,#sequences do - local sequence=sequences[i] - local kind=sequence.type - local steps=sequence.steps - local features=sequence.features - if steps then - for i=1,#steps do - local step=steps[i] - if kind=="gpos_pair" then - local c=step.coverage - if c then - if step.format=="kern" then - else - for g1,d1 in next,c do - for g2,d2 in next,d1 do - d1[g2]=pack_normal(d2) - end - end - end - end - end - local rules=step.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 - if features then - sequence.features=pack_normal(features) - end - end - end - if sequences then - packthem(sequences) - end - if sublookups then - packthem(sublookups) - end - if not success(2,pass) then - end - end - for pass=1,2 do - if trace_packing then - report_otf("start packing: stage 3, pass %s",pass) - end - local pack_normal,pack_indexed,pack_flat,pack_boolean,pack_mixed=packers(pass) - local function packthem(sequences) - for i=1,#sequences do - local sequence=sequences[i] - local kind=sequence.type - local steps=sequence.steps - local features=sequence.features - if steps then - for i=1,#steps do - local step=steps[i] - if kind=="gpos_pair" then - local c=step.coverage - if c then - if step.format=="kern" then - else - for g1,d1 in next,c do - c[g1]=pack_normal(d1) - end - end - end - end - end - end - end - end - if sequences then - packthem(sequences) - end - if sublookups then - packthem(sublookups) - end - end - end - end -end -local unpacked_mt={ - __index=function(t,k) - t[k]=false - return k - end -} -function readers.unpack(data) - if data then - local tables=data.tables - if tables then - local resources=data.resources - local descriptions=data.descriptions or data.glyphs - local sequences=resources.sequences - local sublookups=resources.sublookups - local features=resources.features - local palettes=resources.colorpalettes - local unpacked={} - setmetatable(unpacked,unpacked_mt) - for unicode,description in next,descriptions do - local tv=tables[description.boundingbox] - if tv then - description.boundingbox=tv - 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 - end - local function unpackthem(sequences) - for i=1,#sequences do - local sequence=sequences[i] - local kind=sequence.type - local steps=sequence.steps - local order=sequence.order - local features=sequence.features - local flags=sequence.flags - local markclass=sequence.markclass - if steps then - for i=1,#steps do - local step=steps[i] - if kind=="gpos_pair" then - local c=step.coverage - if c then - if step.format=="kern" then - for g1,d1 in next,c do - local tv=tables[d1] - if tv then - c[g1]=tv - end - end - else - for g1,d1 in next,c do - local tv=tables[d1] - if tv then - c[g1]=tv - d1=tv - end - for g2,d2 in next,d1 do - local tv=tables[d2] - if tv then - d1[g2]=tv - d2=tv - end - local f=tables[d2[1]] if f then d2[1]=f end - local s=tables[d2[2]] if s then d2[2]=s end - end - end - end - end - elseif kind=="gpos_single" then - local c=step.coverage - if c then - if step.format=="kern" then - local tv=tables[c] - if tv then - step.coverage=tv - end - else - for g1,d1 in next,c do - local tv=tables[d1] - if tv then - c[g1]=tv - end - end - end - end - elseif kind=="gpos_cursive" then - local c=step.coverage - if c then - for g1,d1 in next,c do - local f=tables[d1[2]] if f then d1[2]=f end - local s=tables[d1[3]] if s then d1[3]=s end - end - end - elseif kind=="gpos_mark2base" or kind=="gpos_mark2mark" then - local c=step.baseclasses - if c then - for g1,d1 in next,c do - for g2,d2 in next,d1 do - local tv=tables[d2] - if tv then - d1[g2]=tv - end - end - end - end - local c=step.coverage - if c then - for g1,d1 in next,c do - local tv=tables[d1[2]] - if tv then - d1[2]=tv - end - end - end - elseif kind=="gpos_mark2ligature" then - local c=step.baseclasses - if c then - for g1,d1 in next,c do - for g2,d2 in next,d1 do - for g3,d3 in next,d2 do - local tv=tables[d2[g3]] - if tv then - d2[g3]=tv - end - end - end - end - end - local c=step.coverage - if c then - for g1,d1 in next,c do - local tv=tables[d1[2]] - if tv then - d1[2]=tv - end - end - end - end - local rules=step.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=tv - end - for i=1,#before do - local tv=tables[before[i]] - if tv then - before[i]=tv - end - end - end - local after=rule.after - if after then - local tv=tables[after] - if tv then - rule.after=tv - after=tv - end - for i=1,#after do - local tv=tables[after[i]] - if tv then - after[i]=tv - end - end - end - local current=rule.current - if current then - local tv=tables[current] - if tv then - rule.current=tv - current=tv - end - for i=1,#current do - local tv=tables[current[i]] - if tv then - current[i]=tv - end - end - end - local lookups=rule.lookups - if lookups then - local tv=tables[lookups] - if tv then - rule.lookups=tv - end - end - local replacements=rule.replacements - if replacements then - local tv=tables[replacements] - if tv then - rule.replacements=tv - end - end - end - end - end - end - if features then - local tv=tables[features] - if tv then - sequence.features=tv - features=tv - end - for script,feature in next,features do - local tv=tables[feature] - if tv then - features[script]=tv - end - end - end - if order then - local tv=tables[order] - if tv then - sequence.order=tv - end - end - if flags then - local tv=tables[flags] - if tv then - sequence.flags=tv - end - end - end - end - if sequences then - unpackthem(sequences) - end - if sublookups then - unpackthem(sublookups) - end - if features then - for k,list in next,features do - for feature,spec in next,list do - local tv=tables[spec] - if tv then - list[feature]=tv - end - end - end - end - if palettes then - for i=1,#palettes do - local p=palettes[i] - for j=1,#p do - local tv=tables[p[j]] - if tv then - p[j]=tv - end - end - end - end - data.tables=nil - end - end -end -local mt={ - __index=function(t,k) - if k=="height" then - local ht=t.boundingbox[4] - return ht<0 and 0 or ht - elseif k=="depth" then - local dp=-t.boundingbox[2] - return dp<0 and 0 or dp - elseif k=="width" then - return 0 - elseif k=="name" then - return forcenotdef and ".notdef" - end - end -} -local function sameformat(sequence,steps,first,nofsteps,kind) - return true -end -local function mergesteps_1(lookup,strict) - local steps=lookup.steps - local nofsteps=lookup.nofsteps - local first=steps[1] - if strict then - local f=first.format - for i=2,nofsteps do - if steps[i].format~=f then - report("not merging %a steps of %a lookup %a, different formats",nofsteps,lookup.type,lookup.name) - return 0 - end - end - end - report("merging %a steps of %a lookup %a",nofsteps,lookup.type,lookup.name) - local target=first.coverage - for i=2,nofsteps do - for k,v in next,steps[i].coverage do - if not target[k] then - target[k]=v - end - end - end - lookup.nofsteps=1 - lookup.merged=true - lookup.steps={ first } - return nofsteps-1 -end -local function mergesteps_2(lookup,strict) - local steps=lookup.steps - local nofsteps=lookup.nofsteps - local first=steps[1] - if strict then - local f=first.format - for i=2,nofsteps do - if steps[i].format~=f then - report("not merging %a steps of %a lookup %a, different formats",nofsteps,lookup.type,lookup.name) - return 0 - end - end - end - report("merging %a steps of %a lookup %a",nofsteps,lookup.type,lookup.name) - local target=first.coverage - for i=2,nofsteps do - for k,v in next,steps[i].coverage do - local tk=target[k] - if tk then - for k,v in next,v do - if not tk[k] then - tk[k]=v - end - end - else - target[k]=v - end - end - end - lookup.nofsteps=1 - lookup.steps={ first } - return nofsteps-1 -end -local function mergesteps_3(lookup,strict) - local steps=lookup.steps - local nofsteps=lookup.nofsteps - local first=steps[1] - report("merging %a steps of %a lookup %a",nofsteps,lookup.type,lookup.name) - local baseclasses={} - local coverage={} - local used={} - for i=1,nofsteps do - local offset=i*10 - local step=steps[i] - for k,v in sortedhash(step.baseclasses) do - baseclasses[offset+k]=v - end - for k,v in next,step.coverage do - local tk=coverage[k] - if tk then - for k,v in next,v do - if not tk[k] then - tk[k]=v - local c=offset+v[1] - v[1]=c - if not used[c] then - used[c]=true - end - end - end - else - coverage[k]=v - local c=offset+v[1] - v[1]=c - if not used[c] then - used[c]=true - end - end - end - end - for k,v in next,baseclasses do - if not used[k] then - baseclasses[k]=nil - report("discarding not used baseclass %i",k) - end - end - first.baseclasses=baseclasses - first.coverage=coverage - lookup.nofsteps=1 - lookup.steps={ first } - return nofsteps-1 -end -local function nested(old,new) - for k,v in next,old do - if k=="ligature" then - if not new.ligature then - new.ligature=v - end - else - local n=new[k] - if n then - nested(v,n) - else - new[k]=v - end - end - end -end -local function mergesteps_4(lookup) - local steps=lookup.steps - local nofsteps=lookup.nofsteps - local first=steps[1] - report("merging %a steps of %a lookup %a",nofsteps,lookup.type,lookup.name) - local target=first.coverage - for i=2,nofsteps do - for k,v in next,steps[i].coverage do - local tk=target[k] - if tk then - nested(v,tk) - else - target[k]=v - end - end - end - lookup.nofsteps=1 - lookup.steps={ first } - return nofsteps-1 -end -local function checkkerns(lookup) - local steps=lookup.steps - local nofsteps=lookup.nofsteps - for i=1,nofsteps do - local step=steps[i] - if step.format=="pair" then - local coverage=step.coverage - local kerns=true - for g1,d1 in next,coverage do - if d1[1]~=0 or d1[2]~=0 or d1[4]~=0 then - kerns=false - break - end - end - if kerns then - report("turning pairs of step %a of %a lookup %a into kerns",i,lookup.type,lookup.name) - for g1,d1 in next,coverage do - coverage[g1]=d1[3] - end - step.format="kern" - end - end - end -end -local function checkpairs(lookup) - local steps=lookup.steps - local nofsteps=lookup.nofsteps - local kerned=0 - for i=1,nofsteps do - local step=steps[i] - if step.format=="pair" then - local coverage=step.coverage - local kerns=true - for g1,d1 in next,coverage do - for g2,d2 in next,d1 do - if d2[2] then - kerns=false - break - else - local v=d2[1] - if v[1]~=0 or v[2]~=0 or v[4]~=0 then - kerns=false - break - end - end - end - end - if kerns then - report("turning pairs of step %a of %a lookup %a into kerns",i,lookup.type,lookup.name) - for g1,d1 in next,coverage do - for g2,d2 in next,d1 do - d1[g2]=d2[1][3] - end - end - step.format="kern" - kerned=kerned+1 - end - end - end - return kerned -end -function readers.compact(data) - if not data or data.compacted then - return - else - data.compacted=true - end - local resources=data.resources - local merged=0 - local kerned=0 - local allsteps=0 - local function compact(what) - local lookups=resources[what] - if lookups then - for i=1,#lookups do - local lookup=lookups[i] - local nofsteps=lookup.nofsteps - allsteps=allsteps+nofsteps - if nofsteps>1 then - local kind=lookup.type - if kind=="gsub_single" or kind=="gsub_alternate" or kind=="gsub_multiple" then - merged=merged+mergesteps_1(lookup) - elseif kind=="gsub_ligature" then - merged=merged+mergesteps_4(lookup) - elseif kind=="gpos_single" then - merged=merged+mergesteps_1(lookup,true) - checkkerns(lookup) - elseif kind=="gpos_pair" then - merged=merged+mergesteps_2(lookup,true) - kerned=kerned+checkpairs(lookup) - elseif kind=="gpos_cursive" then - merged=merged+mergesteps_2(lookup) - elseif kind=="gpos_mark2mark" or kind=="gpos_mark2base" or kind=="gpos_mark2ligature" then - merged=merged+mergesteps_3(lookup) - end - end - end - else - report("no lookups in %a",what) - end - end - compact("sequences") - compact("sublookups") - if merged>0 then - report("%i steps of %i removed due to merging",merged,allsteps) - end - if kerned>0 then - report("%i steps of %i steps turned from pairs into kerns",kerned,allsteps) - end -end -function readers.expand(data) - if not data or data.expanded then - return - else - data.expanded=true - end - local resources=data.resources - local sublookups=resources.sublookups - local sequences=resources.sequences - local markclasses=resources.markclasses - local descriptions=data.descriptions - if descriptions then - local defaultwidth=resources.defaultwidth or 0 - local defaultheight=resources.defaultheight or 0 - local defaultdepth=resources.defaultdepth or 0 - local basename=trace_markwidth and file.basename(resources.filename) - for u,d in next,descriptions do - local bb=d.boundingbox - local wd=d.width - if not wd then - d.width=defaultwidth - elseif trace_markwidth and wd~=0 and d.class=="mark" then - report("mark %a with width %b found in %a",d.name or "<noname>",wd,basename) - end - if bb then - local ht=bb[4] - local dp=-bb[2] - if ht==0 or ht<0 then - else - d.height=ht - end - if dp==0 or dp<0 then - else - d.depth=dp - end - end - end - end - local function expandlookups(sequences) - if sequences then - for i=1,#sequences do - local sequence=sequences[i] - local steps=sequence.steps - if steps then - local kind=sequence.type - local markclass=sequence.markclass - if markclass then - if not markclasses then - report_warning("missing markclasses") - sequence.markclass=false - else - sequence.markclass=markclasses[markclass] - end - end - for i=1,sequence.nofsteps do - local step=steps[i] - local baseclasses=step.baseclasses - if baseclasses then - local coverage=step.coverage - for k,v in next,coverage do - v[1]=baseclasses[v[1]] - end - elseif kind=="gpos_cursive" then - local coverage=step.coverage - for k,v in next,coverage do - v[1]=coverage - end - end - local rules=step.rules - if rules then - local rulehash={} - local rulesize=0 - local coverage={} - local lookuptype=sequence.type - step.coverage=coverage - for nofrules=1,#rules do - local rule=rules[nofrules] - local current=rule.current - local before=rule.before - local after=rule.after - local replacements=rule.replacements or false - local sequence={} - local nofsequences=0 - if before then - for n=1,#before do - nofsequences=nofsequences+1 - sequence[nofsequences]=before[n] - end - end - local start=nofsequences+1 - for n=1,#current do - nofsequences=nofsequences+1 - sequence[nofsequences]=current[n] - end - local stop=nofsequences - if after then - for n=1,#after do - nofsequences=nofsequences+1 - sequence[nofsequences]=after[n] - end - end - local lookups=rule.lookups or false - local subtype=nil - if lookups then - for k,v in next,lookups do - local lookup=sublookups[v] - if lookup then - lookups[k]=lookup - if not subtype then - subtype=lookup.type - end - else - end - end - end - if sequence[1] then - rulesize=rulesize+1 - rulehash[rulesize]={ - nofrules, - lookuptype, - sequence, - start, - stop, - lookups, - replacements, - subtype, - } - for unic in next,sequence[start] do - local cu=coverage[unic] - if not cu then - coverage[unic]=rulehash - end - end - end - end - end - end - end - end - end - end - expandlookups(sequences) - expandlookups(sublookups) -end - -end --- [luaotfload, fontloader-2017-02-11.lua scope for “font-oup”] --- - - -do --- [luaotfload, fontloader-2017-02-11.lua scope for “font-otl” 2e7c8d9a331c46826211bd507f8e488a] --- - -if not modules then modules={} end modules ['font-otl']={ - version=1.001, - comment="companion to font-ini.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files", -} -local gmatch,find,match,lower,strip=string.gmatch,string.find,string.match,string.lower,string.strip -local type,next,tonumber,tostring,unpack=type,next,tonumber,tostring,unpack -local abs=math.abs -local derivetable=table.derive -local formatters=string.formatters -local setmetatableindex=table.setmetatableindex -local allocate=utilities.storage.allocate -local registertracker=trackers.register -local registerdirective=directives.register -local starttiming=statistics.starttiming -local stoptiming=statistics.stoptiming -local elapsedtime=statistics.elapsedtime -local findbinfile=resolvers.findbinfile -local trace_loading=false registertracker("otf.loading",function(v) trace_loading=v end) -local trace_features=false registertracker("otf.features",function(v) trace_features=v end) -local trace_defining=false registertracker("fonts.defining",function(v) trace_defining=v end) -local report_otf=logs.reporter("fonts","otf loading") -local fonts=fonts -local otf=fonts.handlers.otf -otf.version=3.027 -otf.cache=containers.define("fonts","otl",otf.version,true) -otf.svgcache=containers.define("fonts","svg",otf.version,true) -otf.pdfcache=containers.define("fonts","pdf",otf.version,true) -otf.svgenabled=false -local otfreaders=otf.readers -local hashes=fonts.hashes -local definers=fonts.definers -local readers=fonts.readers -local constructors=fonts.constructors -local otffeatures=constructors.features.otf -local registerotffeature=otffeatures.register -local otfenhancers=constructors.enhancers.otf -local registerotfenhancer=otfenhancers.register -local forceload=false -local cleanup=0 -local syncspace=true -local forcenotdef=false -local applyruntimefixes=fonts.treatments and fonts.treatments.applyfixes -local wildcard="*" -local default="dflt" -local formats=fonts.formats -formats.otf="opentype" -formats.ttf="truetype" -formats.ttc="truetype" -registerdirective("fonts.otf.loader.cleanup",function(v) cleanup=tonumber(v) or (v and 1) or 0 end) -registerdirective("fonts.otf.loader.force",function(v) forceload=v end) -registerdirective("fonts.otf.loader.syncspace",function(v) syncspace=v end) -registerdirective("fonts.otf.loader.forcenotdef",function(v) forcenotdef=v end) -registerotfenhancer("check extra features",function() end) -function otf.load(filename,sub,featurefile) - local featurefile=nil - local base=file.basename(file.removesuffix(filename)) - local name=file.removesuffix(base) - local attr=lfs.attributes(filename) - local size=attr and attr.size or 0 - local time=attr and attr.modification or 0 - if featurefile then - name=name.."@"..file.removesuffix(file.basename(featurefile)) - end - if sub=="" then - sub=false - end - local hash=name - if sub then - hash=hash.."-"..sub - end - hash=containers.cleanname(hash) - local featurefiles - if featurefile then - featurefiles={} - for s in gmatch(featurefile,"[^,]+") do - local name=resolvers.findfile(file.addsuffix(s,'fea'),'fea') or "" - if name=="" then - report_otf("loading error, no featurefile %a",s) - else - local attr=lfs.attributes(name) - featurefiles[#featurefiles+1]={ - name=name, - size=attr and attr.size or 0, - time=attr and attr.modification or 0, - } - end - end - if #featurefiles==0 then - featurefiles=nil - end - end - local data=containers.read(otf.cache,hash) - local reload=not data or data.size~=size or data.time~=time or data.tableversion~=otfreaders.tableversion - if forceload then - report_otf("forced reload of %a due to hard coded flag",filename) - reload=true - end - if reload then - report_otf("loading %a, hash %a",filename,hash) - starttiming(otfreaders) - data=otfreaders.loadfont(filename,sub or 1) - if data then - local resources=data.resources - local svgshapes=resources.svgshapes - if svgshapes then - resources.svgshapes=nil - if otf.svgenabled then - local timestamp=os.date() - containers.write(otf.svgcache,hash,{ - svgshapes=svgshapes, - timestamp=timestamp, - }) - data.properties.svg={ - hash=hash, - timestamp=timestamp, - } - end - end - otfreaders.compact(data) - otfreaders.rehash(data,"unicodes") - otfreaders.addunicodetable(data) - otfreaders.extend(data) - otfreaders.pack(data) - report_otf("loading done") - report_otf("saving %a in cache",filename) - data=containers.write(otf.cache,hash,data) - if cleanup>1 then - collectgarbage("collect") - end - stoptiming(otfreaders) - if elapsedtime then - report_otf("loading, optimizing, packing and caching time %s",elapsedtime(otfreaders)) - end - if cleanup>3 then - collectgarbage("collect") - end - data=containers.read(otf.cache,hash) - if cleanup>2 then - collectgarbage("collect") - end - else - data=nil - report_otf("loading failed due to read error") - end - end - if data then - if trace_defining then - report_otf("loading from cache using hash %a",hash) - end - otfreaders.unpack(data) - otfreaders.expand(data) - otfreaders.addunicodetable(data) - otfenhancers.apply(data,filename,data) - if applyruntimefixes then - applyruntimefixes(filename,data) - end - data.metadata.math=data.resources.mathconstants - end - return data -end -function otf.setfeatures(tfmdata,features) - local okay=constructors.initializefeatures("otf",tfmdata,features,trace_features,report_otf) - if okay then - return constructors.collectprocessors("otf",tfmdata,features,trace_features,report_otf) - else - return {} - end -end -local function copytotfm(data,cache_id) - if data then - local metadata=data.metadata - local properties=derivetable(data.properties) - local descriptions=derivetable(data.descriptions) - local goodies=derivetable(data.goodies) - local characters={} - local parameters={} - local mathparameters={} - local resources=data.resources - local unicodes=resources.unicodes - local spaceunits=500 - local spacer="space" - local designsize=metadata.designsize or 100 - local minsize=metadata.minsize or designsize - local maxsize=metadata.maxsize or designsize - local mathspecs=metadata.math - if designsize==0 then - designsize=100 - minsize=100 - maxsize=100 - end - if mathspecs then - for name,value in next,mathspecs do - mathparameters[name]=value - end - end - for unicode in next,data.descriptions do - characters[unicode]={} - end - if mathspecs then - for unicode,character in next,characters do - local d=descriptions[unicode] - local m=d.math - if m then - local italic=m.italic - local vitalic=m.vitalic - local variants=m.hvariants - local parts=m.hparts - if variants then - local c=character - for i=1,#variants do - local un=variants[i] - c.next=un - c=characters[un] - end - c.horiz_variants=parts - elseif parts then - character.horiz_variants=parts - italic=m.hitalic - end - local variants=m.vvariants - local parts=m.vparts - if variants then - local c=character - for i=1,#variants do - local un=variants[i] - c.next=un - c=characters[un] - end - c.vert_variants=parts - elseif parts then - character.vert_variants=parts - end - if italic and italic~=0 then - character.italic=italic - end - if vitalic and vitalic~=0 then - character.vert_italic=vitalic - end - local accent=m.accent - if accent then - character.accent=accent - end - local kerns=m.kerns - if kerns then - character.mathkerns=kerns - end - end - end - end - local filename=constructors.checkedfilename(resources) - local fontname=metadata.fontname - local fullname=metadata.fullname or fontname - local psname=fontname or fullname - local units=metadata.units or 1000 - if units==0 then - units=1000 - metadata.units=1000 - report_otf("changing %a units to %a",0,units) - end - local monospaced=metadata.monospaced - local charwidth=metadata.averagewidth - local charxheight=metadata.xheight - local italicangle=metadata.italicangle - local hasitalics=metadata.hasitalics - properties.monospaced=monospaced - properties.hasitalics=hasitalics - parameters.italicangle=italicangle - parameters.charwidth=charwidth - parameters.charxheight=charxheight - local space=0x0020 - local emdash=0x2014 - if monospaced then - if descriptions[space] then - spaceunits,spacer=descriptions[space].width,"space" - end - if not spaceunits and descriptions[emdash] then - spaceunits,spacer=descriptions[emdash].width,"emdash" - end - if not spaceunits and charwidth then - spaceunits,spacer=charwidth,"charwidth" - end - else - if descriptions[space] then - spaceunits,spacer=descriptions[space].width,"space" - end - if not spaceunits and descriptions[emdash] then - spaceunits,spacer=descriptions[emdash].width/2,"emdash/2" - end - if not spaceunits and charwidth then - spaceunits,spacer=charwidth,"charwidth" - end - end - spaceunits=tonumber(spaceunits) or units/2 - parameters.slant=0 - parameters.space=spaceunits - parameters.space_stretch=1*units/2 - parameters.space_shrink=1*units/3 - parameters.x_height=2*units/5 - parameters.quad=units - if spaceunits<2*units/5 then - end - if italicangle and italicangle~=0 then - parameters.italicangle=italicangle - parameters.italicfactor=math.cos(math.rad(90+italicangle)) - parameters.slant=- math.tan(italicangle*math.pi/180) - end - if monospaced then - parameters.space_stretch=0 - parameters.space_shrink=0 - elseif syncspace then - parameters.space_stretch=spaceunits/2 - parameters.space_shrink=spaceunits/3 - end - parameters.extra_space=parameters.space_shrink - if charxheight then - parameters.x_height=charxheight - else - local x=0x0078 - if x then - local x=descriptions[x] - if x then - parameters.x_height=x.height - end - end - end - parameters.designsize=(designsize/10)*65536 - parameters.minsize=(minsize/10)*65536 - parameters.maxsize=(maxsize/10)*65536 - parameters.ascender=abs(metadata.ascender or 0) - parameters.descender=abs(metadata.descender or 0) - parameters.units=units - properties.space=spacer - properties.encodingbytes=2 - properties.format=data.format or formats.otf - properties.noglyphnames=true - properties.filename=filename - properties.fontname=fontname - properties.fullname=fullname - properties.psname=psname - properties.name=filename or fullname - return { - characters=characters, - descriptions=descriptions, - parameters=parameters, - mathparameters=mathparameters, - resources=resources, - properties=properties, - goodies=goodies, - } - end -end -local converters={ - woff={ - cachename="webfonts", - action=otf.readers.woff2otf, - } -} -local function checkconversion(specification) - local filename=specification.filename - local converter=converters[lower(file.suffix(filename))] - if converter then - local base=file.basename(filename) - local name=file.removesuffix(base) - local attr=lfs.attributes(filename) - local size=attr and attr.size or 0 - local time=attr and attr.modification or 0 - if size>0 then - local cleanname=containers.cleanname(name) - local cachename=caches.setfirstwritablefile(cleanname,converter.cachename) - if not io.exists(cachename) or (time~=lfs.attributes(cachename).modification) then - report_otf("caching font %a in %a",filename,cachename) - converter.action(filename,cachename) - lfs.touch(cachename,time,time) - end - specification.filename=cachename - end - end -end -local function otftotfm(specification) - local cache_id=specification.hash - local tfmdata=containers.read(constructors.cache,cache_id) - if not tfmdata then - checkconversion(specification) - local name=specification.name - local sub=specification.sub - local subindex=specification.subindex - local filename=specification.filename - local features=specification.features.normal - local rawdata=otf.load(filename,sub,features and features.featurefile) - if rawdata and next(rawdata) then - local descriptions=rawdata.descriptions - rawdata.lookuphash={} - tfmdata=copytotfm(rawdata,cache_id) - if tfmdata and next(tfmdata) then - local features=constructors.checkedfeatures("otf",features) - local shared=tfmdata.shared - if not shared then - shared={} - tfmdata.shared=shared - end - shared.rawdata=rawdata - shared.dynamics={} - tfmdata.changed={} - shared.features=features - shared.processes=otf.setfeatures(tfmdata,features) - end - end - containers.write(constructors.cache,cache_id,tfmdata) - end - return tfmdata -end -local function read_from_otf(specification) - local tfmdata=otftotfm(specification) - if tfmdata then - tfmdata.properties.name=specification.name - tfmdata.properties.sub=specification.sub - tfmdata=constructors.scale(tfmdata,specification) - local allfeatures=tfmdata.shared.features or specification.features.normal - constructors.applymanipulators("otf",tfmdata,allfeatures,trace_features,report_otf) - constructors.setname(tfmdata,specification) - fonts.loggers.register(tfmdata,file.suffix(specification.filename),specification) - end - return tfmdata -end -local function checkmathsize(tfmdata,mathsize) - local mathdata=tfmdata.shared.rawdata.metadata.math - local mathsize=tonumber(mathsize) - if mathdata then - local parameters=tfmdata.parameters - parameters.scriptpercentage=mathdata.ScriptPercentScaleDown - parameters.scriptscriptpercentage=mathdata.ScriptScriptPercentScaleDown - parameters.mathsize=mathsize - end -end -registerotffeature { - name="mathsize", - description="apply mathsize specified in the font", - initializers={ - base=checkmathsize, - node=checkmathsize, - } -} -function otf.collectlookups(rawdata,kind,script,language) - if not kind then - return - end - if not script then - script=default - end - if not language then - language=default - end - local lookupcache=rawdata.lookupcache - if not lookupcache then - lookupcache={} - rawdata.lookupcache=lookupcache - end - local kindlookup=lookupcache[kind] - if not kindlookup then - kindlookup={} - lookupcache[kind]=kindlookup - end - local scriptlookup=kindlookup[script] - if not scriptlookup then - scriptlookup={} - kindlookup[script]=scriptlookup - end - local languagelookup=scriptlookup[language] - if not languagelookup then - local sequences=rawdata.resources.sequences - local featuremap={} - local featurelist={} - if sequences then - for s=1,#sequences do - local sequence=sequences[s] - local features=sequence.features - if features then - features=features[kind] - if features then - features=features[script] or features[wildcard] - if features then - features=features[language] or features[wildcard] - if features then - if not featuremap[sequence] then - featuremap[sequence]=true - featurelist[#featurelist+1]=sequence - end - end - end - end - end - end - if #featurelist==0 then - featuremap,featurelist=false,false - end - else - featuremap,featurelist=false,false - end - languagelookup={ featuremap,featurelist } - scriptlookup[language]=languagelookup - end - return unpack(languagelookup) -end -local function getgsub(tfmdata,k,kind,value) - local shared=tfmdata.shared - local rawdata=shared and shared.rawdata - if rawdata then - local sequences=rawdata.resources.sequences - if sequences then - local properties=tfmdata.properties - local validlookups,lookuplist=otf.collectlookups(rawdata,kind,properties.script,properties.language) - if validlookups then - for i=1,#lookuplist do - local lookup=lookuplist[i] - local steps=lookup.steps - local nofsteps=lookup.nofsteps - for i=1,nofsteps do - local coverage=steps[i].coverage - if coverage then - local found=coverage[k] - if found then - return found,lookup.type - end - end - end - end - end - end - end -end -otf.getgsub=getgsub -function otf.getsubstitution(tfmdata,k,kind,value) - local found,kind=getgsub(tfmdata,k,kind,value) - if not found then - elseif kind=="gsub_single" then - return found - elseif kind=="gsub_alternate" then - local choice=tonumber(value) or 1 - return found[choice] or found[1] or k - end - return k -end -otf.getalternate=otf.getsubstitution -function otf.getmultiple(tfmdata,k,kind) - local found,kind=getgsub(tfmdata,k,kind) - if found and kind=="gsub_multiple" then - return found - end - return { k } -end -function otf.getkern(tfmdata,left,right,kind) - local kerns=getgsub(tfmdata,left,kind or "kern",true) - if kerns then - local found=kerns[right] - local kind=type(found) - if kind=="table" then - found=found[1][3] - elseif kind~="number" then - found=false - end - if found then - return found*tfmdata.parameters.factor - end - end - return 0 -end -local function check_otf(forced,specification,suffix) - local name=specification.name - if forced then - name=specification.forcedname - end - local fullname=findbinfile(name,suffix) or "" - if fullname=="" then - fullname=fonts.names.getfilename(name,suffix) or "" - end - if fullname~="" and not fonts.names.ignoredfile(fullname) then - specification.filename=fullname - return read_from_otf(specification) - end -end -local function opentypereader(specification,suffix) - local forced=specification.forced or "" - if formats[forced] then - return check_otf(true,specification,forced) - else - return check_otf(false,specification,suffix) - end -end -readers.opentype=opentypereader -function readers.otf(specification) return opentypereader(specification,"otf") end -function readers.ttf(specification) return opentypereader(specification,"ttf") end -function readers.ttc(specification) return opentypereader(specification,"ttf") end -function readers.woff(specification) - checkconversion(specification) - opentypereader(specification,"") -end -function otf.scriptandlanguage(tfmdata,attr) - local properties=tfmdata.properties - return properties.script or "dflt",properties.language or "dflt" -end -local function justset(coverage,unicode,replacement) - coverage[unicode]=replacement -end -otf.coverup={ - stepkey="steps", - actions={ - chainsubstitution=justset, - chainposition=justset, - substitution=justset, - alternate=justset, - multiple=justset, - kern=justset, - pair=justset, - ligature=function(coverage,unicode,ligature) - local first=ligature[1] - local tree=coverage[first] - if not tree then - tree={} - coverage[first]=tree - end - for i=2,#ligature do - local l=ligature[i] - local t=tree[l] - if not t then - t={} - tree[l]=t - end - tree=t - end - tree.ligature=unicode - end, - }, - register=function(coverage,featuretype,format) - return { - format=format, - coverage=coverage, - } - end -} - -end --- [luaotfload, fontloader-2017-02-11.lua scope for “font-otl”] --- - - -do --- [luaotfload, fontloader-2017-02-11.lua scope for “font-oto” 5fbdd899624d4eef639f81b580afe9aa] --- - -if not modules then modules={} end modules ['font-oto']={ - version=1.001, - comment="companion to font-ini.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local concat,unpack=table.concat,table.unpack -local insert,remove=table.insert,table.remove -local format,gmatch,gsub,find,match,lower,strip=string.format,string.gmatch,string.gsub,string.find,string.match,string.lower,string.strip -local type,next,tonumber,tostring,rawget=type,next,tonumber,tostring,rawget -local trace_baseinit=false trackers.register("otf.baseinit",function(v) trace_baseinit=v end) -local trace_singles=false trackers.register("otf.singles",function(v) trace_singles=v end) -local trace_multiples=false trackers.register("otf.multiples",function(v) trace_multiples=v end) -local trace_alternatives=false trackers.register("otf.alternatives",function(v) trace_alternatives=v end) -local trace_ligatures=false trackers.register("otf.ligatures",function(v) trace_ligatures=v end) -local trace_kerns=false trackers.register("otf.kerns",function(v) trace_kerns=v end) -local trace_preparing=false trackers.register("otf.preparing",function(v) trace_preparing=v end) -local report_prepare=logs.reporter("fonts","otf prepare") -local fonts=fonts -local otf=fonts.handlers.otf -local otffeatures=otf.features -local registerotffeature=otffeatures.register -otf.defaultbasealternate="none" -local wildcard="*" -local default="dflt" -local formatters=string.formatters -local f_unicode=formatters["%U"] -local f_uniname=formatters["%U (%s)"] -local f_unilist=formatters["% t (% t)"] -local function gref(descriptions,n) - if type(n)=="number" then - local name=descriptions[n].name - if name then - return f_uniname(n,name) - else - return f_unicode(n) - end - elseif n then - local num,nam,j={},{},0 - for i=1,#n do - local ni=n[i] - if tonumber(ni) then - j=j+1 - local di=descriptions[ni] - num[j]=f_unicode(ni) - nam[j]=di and di.name or "-" - end - end - return f_unilist(num,nam) - else - return "<error in base mode tracing>" - end -end -local function cref(feature,sequence) - return formatters["feature %a, type %a, chain lookup %a"](feature,sequence.type,sequence.name) -end -local function report_alternate(feature,sequence,descriptions,unicode,replacement,value,comment) - report_prepare("%s: base alternate %s => %s (%S => %S)", - cref(feature,sequence), - gref(descriptions,unicode), - replacement and gref(descriptions,replacement), - value, - comment) -end -local function report_substitution(feature,sequence,descriptions,unicode,substitution) - report_prepare("%s: base substitution %s => %S", - cref(feature,sequence), - gref(descriptions,unicode), - gref(descriptions,substitution)) -end -local function report_ligature(feature,sequence,descriptions,unicode,ligature) - report_prepare("%s: base ligature %s => %S", - cref(feature,sequence), - gref(descriptions,ligature), - gref(descriptions,unicode)) -end -local function report_kern(feature,sequence,descriptions,unicode,otherunicode,value) - report_prepare("%s: base kern %s + %s => %S", - cref(feature,sequence), - gref(descriptions,unicode), - gref(descriptions,otherunicode), - value) -end -local basehash,basehashes,applied={},1,{} -local function registerbasehash(tfmdata) - local properties=tfmdata.properties - local hash=concat(applied," ") - local base=basehash[hash] - if not base then - basehashes=basehashes+1 - base=basehashes - basehash[hash]=base - end - properties.basehash=base - properties.fullname=(properties.fullname or properties.name).."-"..base - applied={} -end -local function registerbasefeature(feature,value) - applied[#applied+1]=feature.."="..tostring(value) -end -local function makefake(tfmdata,name,present) - local resources=tfmdata.resources - local private=resources.private - local character={ intermediate=true,ligatures={} } - resources.unicodes[name]=private - tfmdata.characters[private]=character - tfmdata.descriptions[private]={ name=name } - resources.private=private+1 - present[name]=private - return character -end -local function make_1(present,tree,name) - for k,v in next,tree do - if k=="ligature" then - present[name]=v - else - make_1(present,v,name.."_"..k) - end - end -end -local function make_2(present,tfmdata,characters,tree,name,preceding,unicode,done) - for k,v in next,tree do - if k=="ligature" then - local character=characters[preceding] - if not character then - if trace_baseinit then - report_prepare("weird ligature in lookup %a, current %C, preceding %C",sequence.name,v,preceding) - end - character=makefake(tfmdata,name,present) - end - local ligatures=character.ligatures - if ligatures then - ligatures[unicode]={ char=v } - else - character.ligatures={ [unicode]={ char=v } } - end - if done then - local d=done[name] - if not d then - done[name]={ "dummy",v } - else - d[#d+1]=v - end - end - else - local code=present[name] or unicode - local name=name.."_"..k - make_2(present,tfmdata,characters,v,name,code,k,done) - end - end -end -local function preparesubstitutions(tfmdata,feature,value,validlookups,lookuplist) - local characters=tfmdata.characters - local descriptions=tfmdata.descriptions - local resources=tfmdata.resources - local changed=tfmdata.changed - local ligatures={} - local alternate=tonumber(value) or true and 1 - local defaultalt=otf.defaultbasealternate - local trace_singles=trace_baseinit and trace_singles - local trace_alternatives=trace_baseinit and trace_alternatives - local trace_ligatures=trace_baseinit and trace_ligatures - if not changed then - changed={} - tfmdata.changed=changed - end - for i=1,#lookuplist do - local sequence=lookuplist[i] - local steps=sequence.steps - local kind=sequence.type - if kind=="gsub_single" then - for i=1,#steps do - for unicode,data in next,steps[i].coverage do - if trace_singles then - report_substitution(feature,sequence,descriptions,unicode,data) - end - changed[unicode]=data - end - end - elseif kind=="gsub_alternate" then - for i=1,#steps do - for unicode,data in next,steps[i].coverage do - if not changed[unicode] then - local replacement=data[alternate] - if replacement then - changed[unicode]=replacement - if trace_alternatives then - report_alternate(feature,sequence,descriptions,unicode,replacement,value,"normal") - end - elseif defaultalt=="first" then - replacement=data[1] - changed[unicode]=replacement - if trace_alternatives then - report_alternate(feature,sequence,descriptions,unicode,replacement,value,defaultalt) - end - elseif defaultalt=="last" then - replacement=data[#data] - if trace_alternatives then - report_alternate(feature,sequence,descriptions,unicode,replacement,value,defaultalt) - end - else - if trace_alternatives then - report_alternate(feature,sequence,descriptions,unicode,replacement,value,"unknown") - end - end - end - end - end - elseif kind=="gsub_ligature" then - for i=1,#steps do - for unicode,data in next,steps[i].coverage do - ligatures[#ligatures+1]={ unicode,data,"" } - if trace_ligatures then - report_ligature(feature,sequence,descriptions,unicode,data) - end - end - end - end - end - local nofligatures=#ligatures - if nofligatures>0 then - local characters=tfmdata.characters - local present={} - local done=trace_baseinit and trace_ligatures and {} - for i=1,nofligatures do - local ligature=ligatures[i] - local unicode,tree=ligature[1],ligature[2] - make_1(present,tree,"ctx_"..unicode) - end - for i=1,nofligatures do - local ligature=ligatures[i] - local unicode,tree,lookupname=ligature[1],ligature[2],ligature[3] - make_2(present,tfmdata,characters,tree,"ctx_"..unicode,unicode,unicode,done,sequence) - end - end -end -local function preparepositionings(tfmdata,feature,value,validlookups,lookuplist) - local characters=tfmdata.characters - local descriptions=tfmdata.descriptions - local resources=tfmdata.resources - local properties=tfmdata.properties - local traceindeed=trace_baseinit and trace_kerns - for i=1,#lookuplist do - local sequence=lookuplist[i] - local steps=sequence.steps - local kind=sequence.type - local format=sequence.format - if kind=="gpos_pair" then - for i=1,#steps do - local step=steps[i] - if step.format=="kern" then - for unicode,data in next,steps[i].coverage do - local character=characters[unicode] - local kerns=character.kerns - if not kerns then - kerns={} - character.kerns=kerns - end - if traceindeed then - for otherunicode,kern in next,data do - if not kerns[otherunicode] and kern~=0 then - kerns[otherunicode]=kern - report_kern(feature,sequence,descriptions,unicode,otherunicode,kern) - end - end - else - for otherunicode,kern in next,data do - if not kerns[otherunicode] and kern~=0 then - kerns[otherunicode]=kern - end - end - end - end - else - for unicode,data in next,steps[i].coverage do - local character=characters[unicode] - local kerns=character.kerns - for otherunicode,kern in next,data do - if not kern[2] and not (kerns and kerns[otherunicode]) then - local kern=kern[1] - if kern[1]~=0 or kern[2]~=0 or kern[4]~=0 then - else - kern=kern[3] - if kern~=0 then - if kerns then - kerns[otherunicode]=kern - else - kerns={ [otherunicode]=kern } - character.kerns=kerns - end - if traceindeed then - report_kern(feature,sequence,descriptions,unicode,otherunicode,kern) - end - end - end - end - end - end - end - end - end - end -end -local function initializehashes(tfmdata) -end -local function featuresinitializer(tfmdata,value) - if true then - local starttime=trace_preparing and os.clock() - local features=tfmdata.shared.features - local fullname=tfmdata.properties.fullname or "?" - if features then - initializehashes(tfmdata) - local collectlookups=otf.collectlookups - local rawdata=tfmdata.shared.rawdata - local properties=tfmdata.properties - local script=properties.script - local language=properties.language - local rawresources=rawdata.resources - local rawfeatures=rawresources and rawresources.features - local basesubstitutions=rawfeatures and rawfeatures.gsub - local basepositionings=rawfeatures and rawfeatures.gpos - if basesubstitutions or basepositionings then - local sequences=tfmdata.resources.sequences - for s=1,#sequences do - local sequence=sequences[s] - local sfeatures=sequence.features - if sfeatures then - local order=sequence.order - if order then - for i=1,#order do - local feature=order[i] - local value=features[feature] - if value then - local validlookups,lookuplist=collectlookups(rawdata,feature,script,language) - if not validlookups then - elseif basesubstitutions and basesubstitutions[feature] then - if trace_preparing then - report_prepare("filtering base %s feature %a for %a with value %a","sub",feature,fullname,value) - end - preparesubstitutions(tfmdata,feature,value,validlookups,lookuplist) - registerbasefeature(feature,value) - elseif basepositionings and basepositionings[feature] then - if trace_preparing then - report_prepare("filtering base %a feature %a for %a with value %a","pos",feature,fullname,value) - end - preparepositionings(tfmdata,feature,value,validlookups,lookuplist) - registerbasefeature(feature,value) - end - end - end - end - end - end - end - registerbasehash(tfmdata) - end - if trace_preparing then - report_prepare("preparation time is %0.3f seconds for %a",os.clock()-starttime,fullname) - end - end -end -registerotffeature { - name="features", - description="features", - default=true, - initializers={ - base=featuresinitializer, - } -} -otf.basemodeinitializer=featuresinitializer - -end --- [luaotfload, fontloader-2017-02-11.lua scope for “font-oto”] --- - - -do --- [luaotfload, fontloader-2017-02-11.lua scope for “font-otj” 5ea70db9f1990dc1459425853c79f663] --- - -if not modules then modules={} end modules ['font-otj']={ - version=1.001, - comment="companion to font-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files", -} -if not nodes.properties then return end -local next,rawget=next,rawget -local fastcopy=table.fastcopy -local registertracker=trackers.register -local trace_injections=false registertracker("fonts.injections",function(v) trace_injections=v end) -local trace_marks=false registertracker("fonts.injections.marks",function(v) trace_marks=v end) -local trace_cursive=false registertracker("fonts.injections.cursive",function(v) trace_cursive=v end) -local trace_spaces=false registertracker("fonts.injections.spaces",function(v) trace_spaces=v end) -local use_advance=false directives.register("fonts.injections.advance",function(v) use_advance=v end) -local report_injections=logs.reporter("fonts","injections") -local report_spaces=logs.reporter("fonts","spaces") -local attributes,nodes,node=attributes,nodes,node -fonts=fonts -local hashes=fonts.hashes -local fontdata=hashes.identifiers -nodes.injections=nodes.injections or {} -local injections=nodes.injections -local tracers=nodes.tracers -local setcolor=tracers and tracers.colors.set -local resetcolor=tracers and tracers.colors.reset -local nodecodes=nodes.nodecodes -local glyph_code=nodecodes.glyph -local disc_code=nodecodes.disc -local kern_code=nodecodes.kern -local glue_code=nodecodes.glue -local nuts=nodes.nuts -local nodepool=nuts.pool -local newkern=nodepool.kern -local tonode=nuts.tonode -local tonut=nuts.tonut -local getfield=nuts.getfield -local setfield=nuts.setfield -local getnext=nuts.getnext -local getprev=nuts.getprev -local getid=nuts.getid -local getfont=nuts.getfont -local getsubtype=nuts.getsubtype -local getchar=nuts.getchar -local getboth=nuts.getboth -local ischar=nuts.is_char -local getdisc=nuts.getdisc -local setdisc=nuts.setdisc -local traverse_id=nuts.traverse_id -local traverse_char=nuts.traverse_char -local insert_node_before=nuts.insert_before -local insert_node_after=nuts.insert_after -local properties=nodes.properties.data -function injections.installnewkern(nk) - newkern=nk or newkern -end -local nofregisteredkerns=0 -local nofregisteredpairs=0 -local nofregisteredmarks=0 -local nofregisteredcursives=0 -local keepregisteredcounts=false -function injections.keepcounts() - keepregisteredcounts=true -end -function injections.resetcounts() - nofregisteredkerns=0 - nofregisteredpairs=0 - nofregisteredmarks=0 - nofregisteredcursives=0 - keepregisteredcounts=false -end -function injections.reset(n) - local p=rawget(properties,n) - if p then - p.injections=false - else - properties[n]=false - end -end -function injections.copy(target,source) - local sp=rawget(properties,source) - if sp then - local tp=rawget(properties,target) - local si=sp.injections - if si then - si=fastcopy(si) - if tp then - tp.injections=si - else - propertydata[target]={ - injections=si, - } - end - elseif tp then - tp.injections=false - else - properties[target]={ injections={} } - end - else - local tp=rawget(properties,target) - if tp then - tp.injections=false - else - properties[target]=false - end - end -end -function injections.setligaindex(n,index) - local p=rawget(properties,n) - if p then - local i=p.injections - if i then - i.ligaindex=index - else - p.injections={ - ligaindex=index - } - end - else - properties[n]={ - injections={ - ligaindex=index - } - } - end -end -function injections.getligaindex(n,default) - local p=rawget(properties,n) - if p then - local i=p.injections - if i then - return i.ligaindex or default - end - end - return default -end -function injections.setcursive(start,nxt,factor,rlmode,exit,entry,tfmstart,tfmnext) - local dx=factor*(exit[1]-entry[1]) - local dy=-factor*(exit[2]-entry[2]) - local ws=tfmstart.width - local wn=tfmnext.width - nofregisteredcursives=nofregisteredcursives+1 - if rlmode<0 then - dx=-(dx+wn) - else - dx=dx-ws - end - if dx==0 then - dx=0 - end - local p=rawget(properties,start) - if p then - local i=p.injections - if i then - i.cursiveanchor=true - else - p.injections={ - cursiveanchor=true, - } - end - else - properties[start]={ - injections={ - cursiveanchor=true, - }, - } - end - local p=rawget(properties,nxt) - if p then - local i=p.injections - if i then - i.cursivex=dx - i.cursivey=dy - else - p.injections={ - cursivex=dx, - cursivey=dy, - } - end - else - properties[nxt]={ - injections={ - cursivex=dx, - cursivey=dy, - }, - } - end - return dx,dy,nofregisteredcursives -end -function injections.setpair(current,factor,rlmode,r2lflag,spec,injection) - local x=factor*spec[1] - local y=factor*spec[2] - local w=factor*spec[3] - local h=factor*spec[4] - if x~=0 or w~=0 or y~=0 or h~=0 then - local yoffset=y-h - local leftkern=x - local rightkern=w-x - if leftkern~=0 or rightkern~=0 or yoffset~=0 then - nofregisteredpairs=nofregisteredpairs+1 - if rlmode and rlmode<0 then - leftkern,rightkern=rightkern,leftkern - end - if not injection then - injection="injections" - end - local p=rawget(properties,current) - if p then - local i=rawget(p,injection) - if i then - if leftkern~=0 then - i.leftkern=(i.leftkern or 0)+leftkern - end - if rightkern~=0 then - i.rightkern=(i.rightkern or 0)+rightkern - end - if yoffset~=0 then - i.yoffset=(i.yoffset or 0)+yoffset - end - elseif leftkern~=0 or rightkern~=0 then - p[injection]={ - leftkern=leftkern, - rightkern=rightkern, - yoffset=yoffset, - } - else - p[injection]={ - yoffset=yoffset, - } - end - elseif leftkern~=0 or rightkern~=0 then - properties[current]={ - [injection]={ - leftkern=leftkern, - rightkern=rightkern, - yoffset=yoffset, - }, - } - else - properties[current]={ - [injection]={ - yoffset=yoffset, - }, - } - end - return x,y,w,h,nofregisteredpairs - end - end - return x,y,w,h -end -function injections.setkern(current,factor,rlmode,x,injection) - local dx=factor*x - if dx~=0 then - nofregisteredkerns=nofregisteredkerns+1 - local p=rawget(properties,current) - if not injection then - injection="injections" - end - if p then - local i=rawget(p,injection) - if i then - i.leftkern=dx+(i.leftkern or 0) - else - p[injection]={ - leftkern=dx, - } - end - else - properties[current]={ - [injection]={ - leftkern=dx, - }, - } - end - return dx,nofregisteredkerns - else - return 0,0 - end -end -function injections.setmark(start,base,factor,rlmode,ba,ma,tfmbase,mkmk,checkmark) - local dx,dy=factor*(ba[1]-ma[1]),factor*(ba[2]-ma[2]) - nofregisteredmarks=nofregisteredmarks+1 - if rlmode>=0 then - dx=tfmbase.width-dx - end - local p=rawget(properties,start) - if p then - local i=p.injections - if i then - if i.markmark then - else - i.markx=dx - i.marky=dy - i.markdir=rlmode or 0 - i.markbase=nofregisteredmarks - i.markbasenode=base - i.markmark=mkmk - i.checkmark=checkmark - end - else - p.injections={ - markx=dx, - marky=dy, - markdir=rlmode or 0, - markbase=nofregisteredmarks, - markbasenode=base, - markmark=mkmk, - checkmark=checkmark, - } - end - else - properties[start]={ - injections={ - markx=dx, - marky=dy, - markdir=rlmode or 0, - markbase=nofregisteredmarks, - markbasenode=base, - markmark=mkmk, - checkmark=checkmark, - }, - } - end - return dx,dy,nofregisteredmarks -end -local function dir(n) - return (n and n<0 and "r-to-l") or (n and n>0 and "l-to-r") or "unset" -end -local function showchar(n,nested) - local char=getchar(n) - report_injections("%wfont %s, char %U, glyph %c",nested and 2 or 0,getfont(n),char,char) -end -local function show(n,what,nested,symbol) - if n then - local p=rawget(properties,n) - if p then - local i=rawget(p,what) - if i then - local leftkern=i.leftkern or 0 - local rightkern=i.rightkern or 0 - local yoffset=i.yoffset or 0 - local markx=i.markx or 0 - local marky=i.marky or 0 - local markdir=i.markdir or 0 - local markbase=i.markbase or 0 - local cursivex=i.cursivex or 0 - local cursivey=i.cursivey or 0 - local ligaindex=i.ligaindex or 0 - local cursbase=i.cursiveanchor - local margin=nested and 4 or 2 - if rightkern~=0 or yoffset~=0 then - report_injections("%w%s pair: lx %p, rx %p, dy %p",margin,symbol,leftkern,rightkern,yoffset) - elseif leftkern~=0 then - report_injections("%w%s kern: dx %p",margin,symbol,leftkern) - end - if markx~=0 or marky~=0 or markbase~=0 then - report_injections("%w%s mark: dx %p, dy %p, dir %s, base %s",margin,symbol,markx,marky,markdir,markbase~=0 and "yes" or "no") - end - if cursivex~=0 or cursivey~=0 then - if cursbase then - report_injections("%w%s curs: base dx %p, dy %p",margin,symbol,cursivex,cursivey) - else - report_injections("%w%s curs: dx %p, dy %p",margin,symbol,cursivex,cursivey) - end - elseif cursbase then - report_injections("%w%s curs: base",margin,symbol) - end - if ligaindex~=0 then - report_injections("%w%s liga: index %i",margin,symbol,ligaindex) - end - end - end - end -end -local function showsub(n,what,where) - report_injections("begin subrun: %s",where) - for n in traverse_id(glyph_code,n) do - showchar(n,where) - show(n,what,where," ") - end - report_injections("end subrun") -end -local function trace(head,where) - report_injections("begin run %s: %s kerns, %s pairs, %s marks and %s cursives registered", - where or "",nofregisteredkerns,nofregisteredpairs,nofregisteredmarks,nofregisteredcursives) - local n=head - while n do - local id=getid(n) - if id==glyph_code then - showchar(n) - show(n,"injections",false," ") - show(n,"preinjections",false,"<") - show(n,"postinjections",false,">") - show(n,"replaceinjections",false,"=") - show(n,"emptyinjections",false,"*") - elseif id==disc_code then - local pre,post,replace=getdisc(n) - if pre then - showsub(pre,"preinjections","pre") - end - if post then - showsub(post,"postinjections","post") - end - if replace then - showsub(replace,"replaceinjections","replace") - end - show(n,"emptyinjections",false,"*") - end - n=getnext(n) - end - report_injections("end run") -end -local function show_result(head) - local current=head - local skipping=false - while current do - local id=getid(current) - if id==glyph_code then - report_injections("char: %C, width %p, xoffset %p, yoffset %p", - getchar(current),getfield(current,"width"),getfield(current,"xoffset"),getfield(current,"yoffset")) - skipping=false - elseif id==kern_code then - report_injections("kern: %p",getfield(current,"kern")) - skipping=false - elseif not skipping then - report_injections() - skipping=true - end - current=getnext(current) - end -end -local function inject_kerns_only(head,where) - head=tonut(head) - if trace_injections then - trace(head,"kerns") - end - local current=head - local prev=nil - local next=nil - local prevdisc=nil - local prevglyph=nil - local pre=nil - local post=nil - local replace=nil - local pretail=nil - local posttail=nil - local replacetail=nil - while current do - local id=getid(current) - local next=getnext(current) - if id==glyph_code then - if getsubtype(current)<256 then - local p=rawget(properties,current) - if p then - local i=p.injections - if i then - local leftkern=i.leftkern - if leftkern and leftkern~=0 then - if use_advance then - setfield(current,"xoffset",leftkern) - setfield(current,"xadvance",leftkern) - else - insert_node_before(head,current,newkern(leftkern)) - end - end - end - if prevdisc then - local done=false - if post then - local i=p.postinjections - if i then - local leftkern=i.leftkern - if leftkern and leftkern~=0 then - if use_advance then - setfield(post,"xadvance",leftkern) - else - insert_node_after(post,posttail,newkern(leftkern)) - done=true - end - end - end - end - if replace then - local i=p.replaceinjections - if i then - local leftkern=i.leftkern - if leftkern and leftkern~=0 then - if use_advance then - setfield(replace,"xadvance",leftkern) - else - insert_node_after(replace,replacetail,newkern(leftkern)) - done=true - end - end - end - else - local i=p.emptyinjections - if i then - local leftkern=i.leftkern - if leftkern and leftkern~=0 then - setfield(prev,"replace",newkern(leftkern)) - end - end - end - if done then - setdisc(prevdisc,pre,post,replace) - end - end - end - end - prevdisc=nil - prevglyph=current - elseif id==disc_code then - pre,post,replace,pretail,posttail,replacetail=getdisc(current,true) - local done=false - if pre then - for n in traverse_char(pre) do - local p=rawget(properties,n) - if p then - local i=p.injections or p.preinjections - if i then - local leftkern=i.leftkern - if leftkern and leftkern~=0 then - if use_advance then - setfield(pre,"xoffset",leftkern) - setfield(pre,"xadvance",leftkern) - else - pre=insert_node_before(pre,n,newkern(leftkern)) - done=true - end - end - end - end - end - end - if post then - for n in traverse_char(post) do - local p=rawget(properties,n) - if p then - local i=p.injections or p.postinjections - if i then - local leftkern=i.leftkern - if leftkern and leftkern~=0 then - if use_advance then - setfield(post,"xoffset",leftkern) - setfield(post,"xadvance",leftkern) - else - post=insert_node_before(post,n,newkern(leftkern)) - done=true - end - end - end - end - end - end - if replace then - for n in traverse_char(replace) do - local p=rawget(properties,n) - if p then - local i=p.injections or p.replaceinjections - if i then - local leftkern=i.leftkern - if leftkern and leftkern~=0 then - if use_advance then - setfield(replace,"xoffset",leftkern) - setfield(replace,"xadvance",leftkern) - else - replace=insert_node_before(replace,n,newkern(leftkern)) - done=true - end - end - end - end - end - end - if done then - setdisc(current,pre,post,replace) - end - prevglyph=nil - prevdisc=current - else - prevglyph=nil - prevdisc=nil - end - prev=current - current=next - end - if keepregisteredcounts then - keepregisteredcounts=false - else - nofregisteredkerns=0 - end - return tonode(head),true -end -local function inject_pairs_only(head,where) - head=tonut(head) - if trace_injections then - trace(head,"pairs") - end - local current=head - local prev=nil - local next=nil - local prevdisc=nil - local prevglyph=nil - local pre=nil - local post=nil - local replace=nil - local pretail=nil - local posttail=nil - local replacetail=nil - while current do - local id=getid(current) - local next=getnext(current) - if id==glyph_code then - if getsubtype(current)<256 then - local p=rawget(properties,current) - if p then - local i=p.injections - if i then - local yoffset=i.yoffset - if yoffset and yoffset~=0 then - setfield(current,"yoffset",yoffset) - end - local leftkern=i.leftkern - if leftkern and leftkern~=0 then - head=insert_node_before(head,current,newkern(leftkern)) - end - local rightkern=i.rightkern - if rightkern and rightkern~=0 then - insert_node_after(head,current,newkern(rightkern)) - end - else - local i=p.emptyinjections - if i then - local rightkern=i.rightkern - if rightkern and rightkern~=0 then - if next and getid(next)==disc_code then - if replace then - else - setfield(next,"replace",newkern(rightkern)) - end - end - end - end - end - if prevdisc then - local done=false - if post then - local i=p.postinjections - if i then - local leftkern=i.leftkern - if leftkern and leftkern~=0 then - insert_node_after(post,posttail,newkern(leftkern)) - done=true - end - end - end - if replace then - local i=p.replaceinjections - if i then - local leftkern=i.leftkern - if leftkern and leftkern~=0 then - insert_node_after(replace,replacetail,newkern(leftkern)) - done=true - end - end - else - local i=p.emptyinjections - if i then - local leftkern=i.leftkern - if leftkern and leftkern~=0 then - setfield(prev,"replace",newkern(leftkern)) - end - end - end - if done then - setdisc(prevdisc,pre,post,replace) - end - end - end - end - prevdisc=nil - prevglyph=current - elseif id==disc_code then - pre,post,replace,pretail,posttail,replacetail=getdisc(current,true) - local done=false - if pre then - for n in traverse_char(pre) do - local p=rawget(properties,n) - if p then - local i=p.injections or p.preinjections - if i then - local yoffset=i.yoffset - if yoffset and yoffset~=0 then - setfield(n,"yoffset",yoffset) - end - local leftkern=i.leftkern - if leftkern and leftkern~=0 then - pre=insert_node_before(pre,n,newkern(leftkern)) - done=true - end - local rightkern=i.rightkern - if rightkern and rightkern~=0 then - insert_node_after(pre,n,newkern(rightkern)) - done=true - end - end - end - end - end - if post then - for n in traverse_char(post) do - local p=rawget(properties,n) - if p then - local i=p.injections or p.postinjections - if i then - local yoffset=i.yoffset - if yoffset and yoffset~=0 then - setfield(n,"yoffset",yoffset) - end - local leftkern=i.leftkern - if leftkern and leftkern~=0 then - post=insert_node_before(post,n,newkern(leftkern)) - done=true - end - local rightkern=i.rightkern - if rightkern and rightkern~=0 then - insert_node_after(post,n,newkern(rightkern)) - done=true - end - end - end - end - end - if replace then - for n in traverse_char(replace) do - local p=rawget(properties,n) - if p then - local i=p.injections or p.replaceinjections - if i then - local yoffset=i.yoffset - if yoffset and yoffset~=0 then - setfield(n,"yoffset",yoffset) - end - local leftkern=i.leftkern - if leftkern and leftkern~=0 then - replace=insert_node_before(replace,n,newkern(leftkern)) - done=true - end - local rightkern=i.rightkern - if rightkern and rightkern~=0 then - insert_node_after(replace,n,newkern(rightkern)) - done=true - end - end - end - end - end - if prevglyph then - if pre then - local p=rawget(properties,prevglyph) - if p then - local i=p.preinjections - if i then - local rightkern=i.rightkern - if rightkern and rightkern~=0 then - pre=insert_node_before(pre,pre,newkern(rightkern)) - done=true - end - end - end - end - if replace then - local p=rawget(properties,prevglyph) - if p then - local i=p.replaceinjections - if i then - local rightkern=i.rightkern - if rightkern and rightkern~=0 then - replace=insert_node_before(replace,replace,newkern(rightkern)) - done=true - end - end - end - end - end - if done then - setdisc(current,pre,post,replace) - end - prevglyph=nil - prevdisc=current - else - prevglyph=nil - prevdisc=nil - end - prev=current - current=next - end - if keepregisteredcounts then - keepregisteredcounts=false - else - nofregisteredkerns=0 - end - return tonode(head),true -end -local function showoffset(n,flag) - local o=getfield(n,"xoffset") - if o==0 then - o=getfield(n,"yoffset") - end - if o~=0 then - setcolor(n,flag and "darkred" or "darkgreen") - else - resetcolor(n) - end -end -local function inject_everything(head,where) - head=tonut(head) - if trace_injections then - trace(head,"everything") - end - local hascursives=nofregisteredcursives>0 - local hasmarks=nofregisteredmarks>0 - local current=head - local last=nil - local font=font - local markdata=nil - local prev=nil - local next=nil - local prevdisc=nil - local prevglyph=nil - local pre=nil - local post=nil - local replace=nil - local pretail=nil - local posttail=nil - local replacetail=nil - local cursiveanchor=nil - local minc=0 - local maxc=0 - local glyphs={} - local marks={} - local nofmarks=0 - local function processmark(p,n,pn) - local px=getfield(p,"xoffset") - local ox=0 - local rightkern=nil - local pp=rawget(properties,p) - if pp then - pp=pp.injections - if pp then - rightkern=pp.rightkern - end - end - if rightkern then - if pn.markdir<0 then - ox=px-pn.markx-rightkern - else - if false then - local leftkern=pp.leftkern - if leftkern then - ox=px-pn.markx-leftkern - else - ox=px-pn.markx - end - else - ox=px-pn.markx - end - end - else - ox=px-pn.markx - if pn.checkmark then - local wn=getfield(n,"width") - if wn~=0 then - wn=wn/2 - if trace_injections then - report_injections("correcting non zero width mark %C",getchar(n)) - end - insert_node_before(n,n,newkern(-wn)) - insert_node_after(n,n,newkern(-wn)) - end - end - end - local oy=getfield(n,"yoffset")+getfield(p,"yoffset")+pn.marky - setfield(n,"xoffset",ox) - setfield(n,"yoffset",oy) - if trace_marks then - showoffset(n,true) - end - end - while current do - local id=getid(current) - local next=getnext(current) - if id==glyph_code then - if getsubtype(current)<256 then - local p=rawget(properties,current) - if p then - local i=p.injections - if i then - local pm=i.markbasenode - if pm then - nofmarks=nofmarks+1 - marks[nofmarks]=current - else - local yoffset=i.yoffset - if yoffset and yoffset~=0 then - setfield(current,"yoffset",yoffset) - end - if hascursives then - local cursivex=i.cursivex - if cursivex then - if cursiveanchor then - if cursivex~=0 then - i.leftkern=(i.leftkern or 0)+cursivex - end - if maxc==0 then - minc=1 - maxc=1 - glyphs[1]=cursiveanchor - else - maxc=maxc+1 - glyphs[maxc]=cursiveanchor - end - properties[cursiveanchor].cursivedy=i.cursivey - last=current - else - maxc=0 - end - elseif maxc>0 then - local ny=getfield(current,"yoffset") - for i=maxc,minc,-1 do - local ti=glyphs[i] - ny=ny+properties[ti].cursivedy - setfield(ti,"yoffset",ny) - if trace_cursive then - showoffset(ti) - end - end - maxc=0 - cursiveanchor=nil - end - if i.cursiveanchor then - cursiveanchor=current - else - if maxc>0 then - local ny=getfield(current,"yoffset") - for i=maxc,minc,-1 do - local ti=glyphs[i] - ny=ny+properties[ti].cursivedy - setfield(ti,"yoffset",ny) - if trace_cursive then - showoffset(ti) - end - end - maxc=0 - end - cursiveanchor=nil - end - end - local leftkern=i.leftkern - if leftkern and leftkern~=0 then - insert_node_before(head,current,newkern(leftkern)) - end - local rightkern=i.rightkern - if rightkern and rightkern~=0 then - insert_node_after(head,current,newkern(rightkern)) - end - end - else - local i=p.emptyinjections - if i then - local rightkern=i.rightkern - if rightkern and rightkern~=0 then - if next and getid(next)==disc_code then - if replace then - else - setfield(next,"replace",newkern(rightkern)) - end - end - end - end - end - if prevdisc then - if p then - local done=false - if post then - local i=p.postinjections - if i then - local leftkern=i.leftkern - if leftkern and leftkern~=0 then - insert_node_after(post,posttail,newkern(leftkern)) - done=true - end - end - end - if replace then - local i=p.replaceinjections - if i then - local leftkern=i.leftkern - if leftkern and leftkern~=0 then - insert_node_after(replace,replacetail,newkern(leftkern)) - done=true - end - end - else - local i=p.emptyinjections - if i then - local leftkern=i.leftkern - if leftkern and leftkern~=0 then - setfield(prev,"replace",newkern(leftkern)) - end - end - end - if done then - setdisc(prevdisc,pre,post,replace) - end - end - end - else - if hascursives and maxc>0 then - local ny=getfield(current,"yoffset") - for i=maxc,minc,-1 do - local ti=glyphs[i] - ny=ny+properties[ti].cursivedy - setfield(ti,"yoffset",getfield(ti,"yoffset")+ny) - end - maxc=0 - cursiveanchor=nil - end - end - end - prevdisc=nil - prevglyph=current - elseif id==disc_code then - pre,post,replace,pretail,posttail,replacetail=getdisc(current,true) - local done=false - if pre then - for n in traverse_char(pre) do - local p=rawget(properties,n) - if p then - local i=p.injections or p.preinjections - if i then - local yoffset=i.yoffset - if yoffset and yoffset~=0 then - setfield(n,"yoffset",yoffset) - end - local leftkern=i.leftkern - if leftkern and leftkern~=0 then - pre=insert_node_before(pre,n,newkern(leftkern)) - done=true - end - local rightkern=i.rightkern - if rightkern and rightkern~=0 then - insert_node_after(pre,n,newkern(rightkern)) - done=true - end - if hasmarks then - local pm=i.markbasenode - if pm then - processmark(pm,current,i) - end - end - end - end - end - end - if post then - for n in traverse_char(post) do - local p=rawget(properties,n) - if p then - local i=p.injections or p.postinjections - if i then - local yoffset=i.yoffset - if yoffset and yoffset~=0 then - setfield(n,"yoffset",yoffset) - end - local leftkern=i.leftkern - if leftkern and leftkern~=0 then - post=insert_node_before(post,n,newkern(leftkern)) - done=true - end - local rightkern=i.rightkern - if rightkern and rightkern~=0 then - insert_node_after(post,n,newkern(rightkern)) - done=true - end - if hasmarks then - local pm=i.markbasenode - if pm then - processmark(pm,current,i) - end - end - end - end - end - end - if replace then - for n in traverse_char(replace) do - local p=rawget(properties,n) - if p then - local i=p.injections or p.replaceinjections - if i then - local yoffset=i.yoffset - if yoffset and yoffset~=0 then - setfield(n,"yoffset",yoffset) - end - local leftkern=i.leftkern - if leftkern and leftkern~=0 then - replace=insert_node_before(replace,n,newkern(leftkern)) - done=true - end - local rightkern=i.rightkern - if rightkern and rightkern~=0 then - insert_node_after(replace,n,newkern(rightkern)) - done=true - end - if hasmarks then - local pm=i.markbasenode - if pm then - processmark(pm,current,i) - end - end - end - end - end - end - if prevglyph then - if pre then - local p=rawget(properties,prevglyph) - if p then - local i=p.preinjections - if i then - local rightkern=i.rightkern - if rightkern and rightkern~=0 then - pre=insert_node_before(pre,pre,newkern(rightkern)) - done=true - end - end - end - end - if replace then - local p=rawget(properties,prevglyph) - if p then - local i=p.replaceinjections - if i then - local rightkern=i.rightkern - if rightkern and rightkern~=0 then - replace=insert_node_before(replace,replace,newkern(rightkern)) - done=true - end - end - end - end - end - if done then - setdisc(current,pre,post,replace) - end - prevglyph=nil - prevdisc=current - else - prevglyph=nil - prevdisc=nil - end - prev=current - current=next - end - if hascursives and maxc>0 then - local ny=getfield(last,"yoffset") - for i=maxc,minc,-1 do - local ti=glyphs[i] - ny=ny+properties[ti].cursivedy - setfield(ti,"yoffset",ny) - if trace_cursive then - showoffset(ti) - end - end - end - if nofmarks>0 then - for i=1,nofmarks do - local m=marks[i] - local p=rawget(properties,m) - local i=p.injections - local b=i.markbasenode - processmark(b,m,i) - end - elseif hasmarks then - end - if keepregisteredcounts then - keepregisteredcounts=false - else - nofregisteredkerns=0 - nofregisteredpairs=0 - nofregisteredmarks=0 - nofregisteredcursives=0 - end - return tonode(head),true -end -local triggers=false -function nodes.injections.setspacekerns(font,sequence) - if triggers then - triggers[font]=sequence - else - triggers={ [font]=sequence } - end -end -local getthreshold -if context then - local threshold=1 - local parameters=fonts.hashes.parameters - directives.register("otf.threshold",function(v) threshold=tonumber(v) or 1 end) - getthreshold=function(font) - local p=parameters[font] - local f=p.factor - local s=p.spacing - local t=threshold*(s and s.width or p.space or 0)-2 - return t>0 and t or 0,f - end -else - injections.threshold=0 - getthreshold=function(font) - local p=fontdata[font].parameters - local f=p.factor - local s=p.spacing - local t=injections.threshold*(s and s.width or p.space or 0)-2 - return t>0 and t or 0,f - end -end -injections.getthreshold=getthreshold -function injections.isspace(n,threshold) - if getid(n)==glue_code then - local w=getfield(n,"width") - if threshold and w>threshold then - return 32 - end - end -end -local function injectspaces(head) - if not triggers then - return head,false - end - local lastfont=nil - local spacekerns=nil - local leftkerns=nil - local rightkerns=nil - local factor=0 - local threshold=0 - local leftkern=false - local rightkern=false - local function updatefont(font,trig) - leftkerns=trig.left - rightkerns=trig.right - lastfont=font - threshold, - factor=getthreshold(font) - end - for n in traverse_id(glue_code,tonut(head)) do - local prev,next=getboth(n) - local prevchar=ischar(prev) - local nextchar=ischar(next) - if nextchar then - local font=getfont(next) - local trig=triggers[font] - if trig then - if lastfont~=font then - updatefont(font,trig) - end - if rightkerns then - rightkern=rightkerns[nextchar] - end - end - end - if prevchar then - local font=getfont(prev) - local trig=triggers[font] - if trig then - if lastfont~=font then - updatefont(font,trig) - end - if leftkerns then - leftkern=leftkerns[prevchar] - end - end - end - if leftkern then - local old=getfield(n,"width") - if old>threshold then - if rightkern then - local new=old+(leftkern+rightkern)*factor - if trace_spaces then - report_spaces("%C [%p -> %p] %C",prevchar,old,new,nextchar) - end - setfield(n,"width",new) - leftkern=false - else - local new=old+leftkern*factor - if trace_spaces then - report_spaces("%C [%p -> %p]",prevchar,old,new) - end - setfield(n,"width",new) - end - end - leftkern=false - elseif rightkern then - local old=getfield(n,"width") - if old>threshold then - local new=old+rightkern*factor - if trace_spaces then - report_spaces("[%p -> %p] %C",nextchar,old,new) - end - setfield(n,"width",new) - end - rightkern=false - end - end - triggers=false - return head,true -end -function injections.handler(head,where) - if triggers then - head=injectspaces(head) - end - if nofregisteredmarks>0 or nofregisteredcursives>0 then - if trace_injections then - report_injections("injection variant %a","everything") - end - return inject_everything(head,where) - elseif nofregisteredpairs>0 then - if trace_injections then - report_injections("injection variant %a","pairs") - end - return inject_pairs_only(head,where) - elseif nofregisteredkerns>0 then - if trace_injections then - report_injections("injection variant %a","kerns") - end - return inject_kerns_only(head,where) - else - return head,false - end -end - -end --- [luaotfload, fontloader-2017-02-11.lua scope for “font-otj”] --- - - -do --- [luaotfload, fontloader-2017-02-11.lua scope for “font-ota” c281d18dfc89a8ca18af64f55e9fa92b] --- - -if not modules then modules={} end modules ['font-ota']={ - version=1.001, - comment="companion to font-otf.lua (analysing)", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local type=type -if not trackers then trackers={ register=function() end } end -local fonts,nodes,node=fonts,nodes,node -local allocate=utilities.storage.allocate -local otf=fonts.handlers.otf -local analyzers=fonts.analyzers -local initializers=allocate() -local methods=allocate() -analyzers.initializers=initializers -analyzers.methods=methods -local a_state=attributes.private('state') -local nuts=nodes.nuts -local tonut=nuts.tonut -local getfield=nuts.getfield -local getnext=nuts.getnext -local getprev=nuts.getprev -local getprev=nuts.getprev -local getprop=nuts.getprop -local setprop=nuts.setprop -local getfont=nuts.getfont -local getsubtype=nuts.getsubtype -local getchar=nuts.getchar -local ischar=nuts.is_char -local traverse_id=nuts.traverse_id -local end_of_math=nuts.end_of_math -local nodecodes=nodes.nodecodes -local disc_code=nodecodes.disc -local math_code=nodecodes.math -local fontdata=fonts.hashes.identifiers -local categories=characters and characters.categories or {} -local chardata=characters and characters.data -local otffeatures=fonts.constructors.features.otf -local registerotffeature=otffeatures.register -local s_init=1 local s_rphf=7 -local s_medi=2 local s_half=8 -local s_fina=3 local s_pref=9 -local s_isol=4 local s_blwf=10 -local s_mark=5 local s_pstf=11 -local s_rest=6 -local states={ - init=s_init, - medi=s_medi, - med2=s_medi, - fina=s_fina, - fin2=s_fina, - fin3=s_fina, - isol=s_isol, - mark=s_mark, - rest=s_rest, - rphf=s_rphf, - half=s_half, - pref=s_pref, - blwf=s_blwf, - pstf=s_pstf, -} -local features={ - init=s_init, - medi=s_medi, - med2=s_medi, - fina=s_fina, - fin2=s_fina, - fin3=s_fina, - isol=s_isol, - rphf=s_rphf, - half=s_half, - pref=s_pref, - blwf=s_blwf, - pstf=s_pstf, -} -analyzers.states=states -analyzers.features=features -analyzers.useunicodemarks=false -function analyzers.setstate(head,font) - local useunicodemarks=analyzers.useunicodemarks - local tfmdata=fontdata[font] - local descriptions=tfmdata.descriptions - local first,last,current,n,done=nil,nil,head,0,false - current=tonut(current) - while current do - local char,id=ischar(current,font) - if char and not getprop(current,a_state) then - done=true - local d=descriptions[char] - if d then - if d.class=="mark" then - done=true - setprop(current,a_state,s_mark) - elseif useunicodemarks and categories[char]=="mn" then - done=true - setprop(current,a_state,s_mark) - elseif n==0 then - first,last,n=current,current,1 - setprop(current,a_state,s_init) - else - last,n=current,n+1 - setprop(current,a_state,s_medi) - end - else - if first and first==last then - setprop(last,a_state,s_isol) - elseif last then - setprop(last,a_state,s_fina) - end - first,last,n=nil,nil,0 - end - elseif char==false then - if first and first==last then - setprop(last,a_state,s_isol) - elseif last then - setprop(last,a_state,s_fina) - end - first,last,n=nil,nil,0 - if id==math_code then - current=end_of_math(current) - end - elseif id==disc_code then - setprop(current,a_state,s_medi) - last=current - else - if first and first==last then - setprop(last,a_state,s_isol) - elseif last then - setprop(last,a_state,s_fina) - end - first,last,n=nil,nil,0 - if id==math_code then - current=end_of_math(current) - end - end - current=getnext(current) - end - if first and first==last then - setprop(last,a_state,s_isol) - elseif last then - setprop(last,a_state,s_fina) - end - return head,done -end -local function analyzeinitializer(tfmdata,value) - local script,language=otf.scriptandlanguage(tfmdata) - local action=initializers[script] - if not action then - elseif type(action)=="function" then - return action(tfmdata,value) - else - local action=action[language] - if action then - return action(tfmdata,value) - end - end -end -local function analyzeprocessor(head,font,attr) - local tfmdata=fontdata[font] - local script,language=otf.scriptandlanguage(tfmdata,attr) - local action=methods[script] - if not action then - elseif type(action)=="function" then - return action(head,font,attr) - else - action=action[language] - if action then - return action(head,font,attr) - end - end - return head,false -end -registerotffeature { - name="analyze", - description="analysis of character classes", - default=true, - initializers={ - node=analyzeinitializer, - }, - processors={ - position=1, - node=analyzeprocessor, - } -} -methods.latn=analyzers.setstate -local arab_warned={} -local function warning(current,what) - local char=getchar(current) - if not arab_warned[char] then - log.report("analyze","arab: character %C has no %a class",char,what) - arab_warned[char]=true - end -end -local mappers={ - l=s_init, - d=s_medi, - c=s_medi, - r=s_fina, - u=s_isol, -} -local classifiers=characters.classifiers -if not classifiers then - local f_arabic,l_arabic=characters.blockrange("arabic") - local f_syriac,l_syriac=characters.blockrange("syriac") - local f_mandiac,l_mandiac=characters.blockrange("mandiac") - local f_nko,l_nko=characters.blockrange("nko") - local f_ext_a,l_ext_a=characters.blockrange("arabicextendeda") - classifiers=table.setmetatableindex(function(t,k) - if type(k)=="number" then - local c=chardata[k] - local v=false - if c then - local arabic=c.arabic - if arabic then - v=mappers[arabic] - if not v then - log.report("analyze","error in mapping arabic %C",k) - v=false - end - elseif (k>=f_arabic and k<=l_arabic) or - (k>=f_syriac and k<=l_syriac) or - (k>=f_mandiac and k<=l_mandiac) or - (k>=f_nko and k<=l_nko) or - (k>=f_ext_a and k<=l_ext_a) then - if categories[k]=="mn" then - v=s_mark - else - v=s_rest - end - end - end - t[k]=v - return v - end - end) - characters.classifiers=classifiers -end -function methods.arab(head,font,attr) - local first,last=nil,nil - local c_first,c_last=nil,nil - local current,done=head,false - current=tonut(current) - while current do - local char,id=ischar(current,font) - if char and not getprop(current,a_state) then - done=true - local classifier=classifiers[char] - if not classifier then - if last then - if c_last==s_medi or c_last==s_fina then - setprop(last,a_state,s_fina) - else - warning(last,"fina") - setprop(last,a_state,s_error) - end - first,last=nil,nil - elseif first then - if c_first==s_medi or c_first==s_fina then - setprop(first,a_state,s_isol) - else - warning(first,"isol") - setprop(first,a_state,s_error) - end - first=nil - end - elseif classifier==s_mark then - setprop(current,a_state,s_mark) - elseif classifier==s_isol then - if last then - if c_last==s_medi or c_last==s_fina then - setprop(last,a_state,s_fina) - else - warning(last,"fina") - setprop(last,a_state,s_error) - end - first,last=nil,nil - elseif first then - if c_first==s_medi or c_first==s_fina then - setprop(first,a_state,s_isol) - else - warning(first,"isol") - setprop(first,a_state,s_error) - end - first=nil - end - setprop(current,a_state,s_isol) - elseif classifier==s_medi then - if first then - last=current - c_last=classifier - setprop(current,a_state,s_medi) - else - setprop(current,a_state,s_init) - first=current - c_first=classifier - end - elseif classifier==s_fina then - if last then - if getprop(last,a_state)~=s_init then - setprop(last,a_state,s_medi) - end - setprop(current,a_state,s_fina) - first,last=nil,nil - elseif first then - setprop(current,a_state,s_fina) - first=nil - else - setprop(current,a_state,s_isol) - end - else - setprop(current,a_state,s_rest) - if last then - if c_last==s_medi or c_last==s_fina then - setprop(last,a_state,s_fina) - else - warning(last,"fina") - setprop(last,a_state,s_error) - end - first,last=nil,nil - elseif first then - if c_first==s_medi or c_first==s_fina then - setprop(first,a_state,s_isol) - else - warning(first,"isol") - setprop(first,a_state,s_error) - end - first=nil - end - end - else - if last then - if c_last==s_medi or c_last==s_fina then - setprop(last,a_state,s_fina) - else - warning(last,"fina") - setprop(last,a_state,s_error) - end - first,last=nil,nil - elseif first then - if c_first==s_medi or c_first==s_fina then - setprop(first,a_state,s_isol) - else - warning(first,"isol") - setprop(first,a_state,s_error) - end - first=nil - end - if id==math_code then - current=end_of_math(current) - end - end - current=getnext(current) - end - if last then - if c_last==s_medi or c_last==s_fina then - setprop(last,a_state,s_fina) - else - warning(last,"fina") - setprop(last,a_state,s_error) - end - elseif first then - if c_first==s_medi or c_first==s_fina then - setprop(first,a_state,s_isol) - else - warning(first,"isol") - setprop(first,a_state,s_error) - end - end - return head,done -end -methods.syrc=methods.arab -methods.mand=methods.arab -methods.nko=methods.arab -directives.register("otf.analyze.useunicodemarks",function(v) - analyzers.useunicodemarks=v -end) - -end --- [luaotfload, fontloader-2017-02-11.lua scope for “font-ota”] --- - - -do --- [luaotfload, fontloader-2017-02-11.lua scope for “font-ots” 7e1e55f9f728474372665e4a64a43f5a] --- - -if not modules then modules={} end modules ['font-ots']={ - version=1.001, - comment="companion to font-ini.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files", -} -local type,next,tonumber=type,next,tonumber -local random=math.random -local formatters=string.formatters -local insert=table.insert -local logs,trackers,nodes,attributes=logs,trackers,nodes,attributes -local registertracker=trackers.register -local registerdirective=directives.register -local fonts=fonts -local otf=fonts.handlers.otf -local trace_lookups=false registertracker("otf.lookups",function(v) trace_lookups=v end) -local trace_singles=false registertracker("otf.singles",function(v) trace_singles=v end) -local trace_multiples=false registertracker("otf.multiples",function(v) trace_multiples=v end) -local trace_alternatives=false registertracker("otf.alternatives",function(v) trace_alternatives=v end) -local trace_ligatures=false registertracker("otf.ligatures",function(v) trace_ligatures=v end) -local trace_contexts=false registertracker("otf.contexts",function(v) trace_contexts=v end) -local trace_marks=false registertracker("otf.marks",function(v) trace_marks=v end) -local trace_kerns=false registertracker("otf.kerns",function(v) trace_kerns=v end) -local trace_cursive=false registertracker("otf.cursive",function(v) trace_cursive=v end) -local trace_preparing=false registertracker("otf.preparing",function(v) trace_preparing=v end) -local trace_bugs=false registertracker("otf.bugs",function(v) trace_bugs=v end) -local trace_details=false registertracker("otf.details",function(v) trace_details=v end) -local trace_steps=false registertracker("otf.steps",function(v) trace_steps=v end) -local trace_skips=false registertracker("otf.skips",function(v) trace_skips=v end) -local trace_directions=false registertracker("otf.directions",function(v) trace_directions=v end) -local trace_plugins=false registertracker("otf.plugins",function(v) trace_plugins=v end) -local trace_kernruns=false registertracker("otf.kernruns",function(v) trace_kernruns=v end) -local trace_discruns=false registertracker("otf.discruns",function(v) trace_discruns=v end) -local trace_compruns=false registertracker("otf.compruns",function(v) trace_compruns=v end) -local trace_testruns=false registertracker("otf.testruns",function(v) trace_testruns=v end) -local optimizekerns=true -local alwaysdisc=true registerdirective("otf.alwaysdisc",function(v) alwaysdisc=v end) -local report_direct=logs.reporter("fonts","otf direct") -local report_subchain=logs.reporter("fonts","otf subchain") -local report_chain=logs.reporter("fonts","otf chain") -local report_process=logs.reporter("fonts","otf process") -local report_warning=logs.reporter("fonts","otf warning") -local report_run=logs.reporter("fonts","otf run") -registertracker("otf.replacements","otf.singles,otf.multiples,otf.alternatives,otf.ligatures") -registertracker("otf.positions","otf.marks,otf.kerns,otf.cursive") -registertracker("otf.actions","otf.replacements,otf.positions") -registertracker("otf.injections","nodes.injections") -registertracker("*otf.sample","otf.steps,otf.actions,otf.analyzing") -local nuts=nodes.nuts -local tonode=nuts.tonode -local tonut=nuts.tonut -local getfield=nuts.getfield -local setfield=nuts.setfield -local getnext=nuts.getnext -local setnext=nuts.setnext -local getprev=nuts.getprev -local setprev=nuts.setprev -local getboth=nuts.getboth -local setboth=nuts.setboth -local getid=nuts.getid -local getattr=nuts.getattr -local setattr=nuts.setattr -local getprop=nuts.getprop -local setprop=nuts.setprop -local getfont=nuts.getfont -local getsubtype=nuts.getsubtype -local setsubtype=nuts.setsubtype -local getchar=nuts.getchar -local setchar=nuts.setchar -local getdisc=nuts.getdisc -local setdisc=nuts.setdisc -local setlink=nuts.setlink -local ischar=nuts.is_char -local insert_node_after=nuts.insert_after -local copy_node=nuts.copy -local copy_node_list=nuts.copy_list -local find_node_tail=nuts.tail -local flush_node_list=nuts.flush_list -local flush_node=nuts.flush_node -local end_of_math=nuts.end_of_math -local traverse_nodes=nuts.traverse -local traverse_id=nuts.traverse_id -local remove_node=nuts.remove -local setmetatableindex=table.setmetatableindex -local zwnj=0x200C -local zwj=0x200D -local wildcard="*" -local default="dflt" -local nodecodes=nodes.nodecodes -local glyphcodes=nodes.glyphcodes -local disccodes=nodes.disccodes -local glyph_code=nodecodes.glyph -local glue_code=nodecodes.glue -local disc_code=nodecodes.disc -local math_code=nodecodes.math -local dir_code=nodecodes.dir -local localpar_code=nodecodes.localpar -local discretionary_code=disccodes.discretionary -local ligature_code=glyphcodes.ligature -local privateattribute=attributes.private -local a_state=privateattribute('state') -local injections=nodes.injections -local setmark=injections.setmark -local setcursive=injections.setcursive -local setkern=injections.setkern -local setpair=injections.setpair -local resetinjection=injections.reset -local copyinjection=injections.copy -local setligaindex=injections.setligaindex -local getligaindex=injections.getligaindex -local cursonce=true -local fonthashes=fonts.hashes -local fontdata=fonthashes.identifiers -local fontfeatures=fonthashes.features -local otffeatures=fonts.constructors.features.otf -local registerotffeature=otffeatures.register -local onetimemessage=fonts.loggers.onetimemessage or function() end -local getrandom=utilities and utilities.randomizer and utilities.randomizer.get -otf.defaultnodealternate="none" -local tfmdata=false -local characters=false -local descriptions=false -local marks=false -local currentfont=false -local factor=0 -local threshold=0 -local checkmarks=false -local sweepnode=nil -local sweepprev=nil -local sweepnext=nil -local sweephead={} -local notmatchpre={} -local notmatchpost={} -local notmatchreplace={} -local handlers={} -local isspace=injections.isspace -local getthreshold=injections.getthreshold -local checkstep=(nodes and nodes.tracers and nodes.tracers.steppers.check) or function() end -local registerstep=(nodes and nodes.tracers and nodes.tracers.steppers.register) or function() end -local registermessage=(nodes and nodes.tracers and nodes.tracers.steppers.message) or function() end -local function checkdisccontent(d) - local pre,post,replace=getdisc(d) - if pre then for n in traverse_id(glue_code,pre) do print("pre",nodes.idstostring(pre)) break end end - if post then for n in traverse_id(glue_code,post) do print("pos",nodes.idstostring(post)) break end end - if replace then for n in traverse_id(glue_code,replace) do print("rep",nodes.idstostring(replace)) break end end -end -local function logprocess(...) - if trace_steps then - registermessage(...) - end - report_direct(...) -end -local function logwarning(...) - report_direct(...) -end -local f_unicode=formatters["%U"] -local f_uniname=formatters["%U (%s)"] -local f_unilist=formatters["% t (% t)"] -local function gref(n) - if type(n)=="number" then - local description=descriptions[n] - local name=description and description.name - if name then - return f_uniname(n,name) - else - return f_unicode(n) - end - elseif n then - local num,nam={},{} - for i=1,#n do - local ni=n[i] - if tonumber(ni) then - local di=descriptions[ni] - num[i]=f_unicode(ni) - nam[i]=di and di.name or "-" - end - end - return f_unilist(num,nam) - else - return "<error in node mode tracing>" - end -end -local function cref(dataset,sequence,index) - if not dataset then - return "no valid dataset" - elseif index then - return formatters["feature %a, type %a, chain lookup %a, index %a"](dataset[4],sequence.type,sequence.name,index) - else - return formatters["feature %a, type %a, chain lookup %a"](dataset[4],sequence.type,sequence.name) - end -end -local function pref(dataset,sequence) - return formatters["feature %a, type %a, lookup %a"](dataset[4],sequence.type,sequence.name) -end -local function mref(rlmode) - if not rlmode or rlmode==0 then - return "---" - elseif rlmode==-1 or rlmode=="+TRT" then - return "r2l" - else - return "l2r" - end -end -local function copy_glyph(g) - local components=getfield(g,"components") - if components then - setfield(g,"components") - local n=copy_node(g) - copyinjection(n,g) - setfield(g,"components",components) - return n - else - local n=copy_node(g) - copyinjection(n,g) - return n - end -end -local function flattendisk(head,disc) - local pre,post,replace,pretail,posttail,replacetail=getdisc(disc,true) - local prev,next=getboth(disc) - local ishead=head==disc - setdisc(disc) - flush_node(disc) - if pre then - flush_node_list(pre) - end - if post then - flush_node_list(post) - end - if ishead then - if replace then - if next then - setlink(replacetail,next) - end - return replace,replace - elseif next then - return next,next - else - return - end - else - if replace then - if next then - setlink(replacetail,next) - end - setlink(prev,replace) - return head,replace - else - setlink(prev,next) - return head,next - end - end -end -local function appenddisc(disc,list) - local pre,post,replace,pretail,posttail,replacetail=getdisc(disc,true) - local posthead=list - local replacehead=copy_node_list(list) - if post then - setlink(posttail,posthead) - else - post=phead - end - if replace then - setlink(replacetail,replacehead) - else - replace=rhead - end - setdisc(disc,pre,post,replace) -end -local function markstoligature(head,start,stop,char) - if start==stop and getchar(start)==char then - return head,start - else - local prev=getprev(start) - local next=getnext(stop) - setprev(start) - setnext(stop) - local base=copy_glyph(start) - if head==start then - head=base - end - resetinjection(base) - setchar(base,char) - setsubtype(base,ligature_code) - setfield(base,"components",start) - setlink(prev,base) - setlink(base,next) - return head,base - end -end -local function getcomponentindex(start) - if getid(start)~=glyph_code then - return 0 - elseif getsubtype(start)==ligature_code then - local i=0 - local components=getfield(start,"components") - while components do - i=i+getcomponentindex(components) - components=getnext(components) - end - return i - elseif not marks[getchar(start)] then - return 1 - else - return 0 - end -end -local a_noligature=attributes.private("noligature") -local function toligature(head,start,stop,char,dataset,sequence,markflag,discfound) - if getattr(start,a_noligature)==1 then - return head,start - end - if start==stop and getchar(start)==char then - resetinjection(start) - setchar(start,char) - return head,start - end - local components=getfield(start,"components") - if components then - end - local prev=getprev(start) - local next=getnext(stop) - local comp=start - setprev(start) - setnext(stop) - local base=copy_glyph(start) - if start==head then - head=base - end - resetinjection(base) - setchar(base,char) - setsubtype(base,ligature_code) - setfield(base,"components",comp) - if prev then - setnext(prev,base) - end - if next then - setprev(next,base) - end - setboth(base,prev,next) - if not discfound then - local deletemarks=markflag~="mark" - local components=start - local baseindex=0 - local componentindex=0 - local head=base - local current=base - while start do - local char=getchar(start) - if not marks[char] then - baseindex=baseindex+componentindex - componentindex=getcomponentindex(start) - elseif not deletemarks then - setligaindex(start,baseindex+getligaindex(start,componentindex)) - if trace_marks then - logwarning("%s: keep mark %s, gets index %s",pref(dataset,sequence),gref(char),getligaindex(start)) - end - local n=copy_node(start) - copyinjection(n,start) - head,current=insert_node_after(head,current,n) - elseif trace_marks then - logwarning("%s: delete mark %s",pref(dataset,sequence),gref(char)) - end - start=getnext(start) - end - local start=getnext(current) - while start do - local char=ischar(start) - if char then - if marks[char] then - setligaindex(start,baseindex+getligaindex(start,componentindex)) - if trace_marks then - logwarning("%s: set mark %s, gets index %s",pref(dataset,sequence),gref(char),getligaindex(start)) - end - start=getnext(start) - else - break - end - else - break - end - end - else - local discprev,discnext=getboth(discfound) - if discprev and discnext then - local pre,post,replace,pretail,posttail,replacetail=getdisc(discfound,true) - if not replace then - local prev=getprev(base) - local current=comp - local previous=nil - local copied=nil - while current do - if getid(current)==glyph_code then - local n=copy_node(current) - if copied then - setlink(previous,n) - else - copied=n - end - previous=n - end - current=getnext(current) - end - setprev(discnext) - setnext(discprev) - if pre then - setlink(discprev,pre) - end - pre=comp - if post then - setlink(posttail,discnext) - setprev(post) - else - post=discnext - end - setlink(prev,discfound) - setlink(discfound,next) - setboth(base) - setfield(base,"components",copied) - setdisc(discfound,pre,post,base) - base=prev - end - end - end - return head,base -end -local function multiple_glyphs(head,start,multiple,ignoremarks,what) - local nofmultiples=#multiple - if nofmultiples>0 then - resetinjection(start) - setchar(start,multiple[1]) - if nofmultiples>1 then - local sn=getnext(start) - for k=2,nofmultiples do - local n=copy_node(start) - resetinjection(n) - setchar(n,multiple[k]) - insert_node_after(head,start,n) - start=n - end - if what==true then - elseif what>1 then - local m=multiple[nofmultiples] - for i=2,what do - local n=copy_node(start) - resetinjection(n) - setchar(n,m) - insert_node_after(head,start,n) - start=n - end - end - end - return head,start,true - else - if trace_multiples then - logprocess("no multiple for %s",gref(getchar(start))) - end - return head,start,false - end -end -local function get_alternative_glyph(start,alternatives,value) - local n=#alternatives - if value=="random" then - local r=getrandom and getrandom("glyph",1,n) or random(1,n) - return alternatives[r],trace_alternatives and formatters["value %a, taking %a"](value,r) - elseif value=="first" then - return alternatives[1],trace_alternatives and formatters["value %a, taking %a"](value,1) - elseif value=="last" then - return alternatives[n],trace_alternatives and formatters["value %a, taking %a"](value,n) - end - value=value==true and 1 or tonumber(value) - if type(value)~="number" then - return alternatives[1],trace_alternatives and formatters["invalid value %s, taking %a"](value,1) - end - if value>n then - local defaultalt=otf.defaultnodealternate - if defaultalt=="first" then - return alternatives[n],trace_alternatives and formatters["invalid value %s, taking %a"](value,1) - elseif defaultalt=="last" then - return alternatives[1],trace_alternatives and formatters["invalid value %s, taking %a"](value,n) - else - return false,trace_alternatives and formatters["invalid value %a, %s"](value,"out of range") - end - elseif value==0 then - return getchar(start),trace_alternatives and formatters["invalid value %a, %s"](value,"no change") - elseif value<1 then - return alternatives[1],trace_alternatives and formatters["invalid value %a, taking %a"](value,1) - else - return alternatives[value],trace_alternatives and formatters["value %a, taking %a"](value,value) - end -end -function handlers.gsub_single(head,start,dataset,sequence,replacement) - if trace_singles then - logprocess("%s: replacing %s by single %s",pref(dataset,sequence),gref(getchar(start)),gref(replacement)) - end - resetinjection(start) - setchar(start,replacement) - return head,start,true -end -function handlers.gsub_alternate(head,start,dataset,sequence,alternative) - local kind=dataset[4] - local what=dataset[1] - local value=what==true and tfmdata.shared.features[kind] or what - local choice,comment=get_alternative_glyph(start,alternative,value) - if choice then - if trace_alternatives then - logprocess("%s: replacing %s by alternative %a to %s, %s",pref(dataset,sequence),gref(getchar(start)),gref(choice),comment) - end - resetinjection(start) - setchar(start,choice) - else - if trace_alternatives then - logwarning("%s: no variant %a for %s, %s",pref(dataset,sequence),value,gref(getchar(start)),comment) - end - end - return head,start,true -end -function handlers.gsub_multiple(head,start,dataset,sequence,multiple) - if trace_multiples then - logprocess("%s: replacing %s by multiple %s",pref(dataset,sequence),gref(getchar(start)),gref(multiple)) - end - return multiple_glyphs(head,start,multiple,sequence.flags[1],dataset[1]) -end -function handlers.gsub_ligature(head,start,dataset,sequence,ligature) - local current=getnext(start) - if not current then - return head,start,false,nil - end - local stop=nil - local startchar=getchar(start) - if marks[startchar] then - while current do - local char=ischar(current,currentfont) - if char then - local lg=ligature[char] - if lg then - stop=current - ligature=lg - current=getnext(current) - else - break - end - else - break - end - end - if stop then - local lig=ligature.ligature - if lig then - if trace_ligatures then - local stopchar=getchar(stop) - head,start=markstoligature(head,start,stop,lig) - logprocess("%s: replacing %s upto %s by ligature %s case 1",pref(dataset,sequence),gref(startchar),gref(stopchar),gref(getchar(start))) - else - head,start=markstoligature(head,start,stop,lig) - end - return head,start,true,false - else - end - end - else - local skipmark=sequence.flags[1] - local discfound=false - local lastdisc=nil - while current do - local char,id=ischar(current,currentfont) - if char then - if skipmark and marks[char] then - current=getnext(current) - else - local lg=ligature[char] - if lg then - if not discfound and lastdisc then - discfound=lastdisc - lastdisc=nil - end - stop=current - ligature=lg - current=getnext(current) - else - break - end - end - elseif char==false then - break - elseif id==disc_code then - local replace=getfield(current,"replace") - if replace then - while replace do - local char,id=ischar(replace,currentfont) - if char then - local lg=ligature[char] - if lg then - ligature=lg - replace=getnext(replace) - else - return head,start,false,false - end - else - return head,start,false,false - end - end - stop=current - end - lastdisc=current - current=getnext(current) - else - break - end - end - local lig=ligature.ligature - if lig then - if stop then - if trace_ligatures then - local stopchar=getchar(stop) - head,start=toligature(head,start,stop,lig,dataset,sequence,skipmark,discfound) - logprocess("%s: replacing %s upto %s by ligature %s case 2",pref(dataset,sequence),gref(startchar),gref(stopchar),gref(lig)) - else - head,start=toligature(head,start,stop,lig,dataset,sequence,skipmark,discfound) - end - else - resetinjection(start) - setchar(start,lig) - if trace_ligatures then - logprocess("%s: replacing %s by (no real) ligature %s case 3",pref(dataset,sequence),gref(startchar),gref(lig)) - end - end - return head,start,true,discfound - else - end - end - return head,start,false,discfound -end -function handlers.gpos_single(head,start,dataset,sequence,kerns,rlmode,step,i,injection) - local startchar=getchar(start) - if step.format=="pair" then - local dx,dy,w,h=setpair(start,factor,rlmode,sequence.flags[4],kerns,injection) - if trace_kerns then - logprocess("%s: shifting single %s by (%p,%p) and correction (%p,%p)",pref(dataset,sequence),gref(startchar),dx,dy,w,h) - end - else - local k=setkern(start,factor,rlmode,kerns,injection) - if trace_kerns then - logprocess("%s: shifting single %s by %p",pref(dataset,sequence),gref(startchar),k) - end - end - return head,start,false -end -function handlers.gpos_pair(head,start,dataset,sequence,kerns,rlmode,step,i,injection) - local snext=getnext(start) - if not snext then - return head,start,false - else - local prev=start - local done=false - while snext do - local nextchar=ischar(snext,currentfont) - if nextchar then - local krn=kerns[nextchar] - if not krn and marks[nextchar] then - prev=snext - snext=getnext(snext) - elseif not krn then - break - elseif step.format=="pair" then - local a,b=krn[1],krn[2] - if optimizekerns then - if not b and a[1]==0 and a[2]==0 and a[4]==0 then - local k=setkern(snext,factor,rlmode,a[3],injection) - if trace_kerns then - logprocess("%s: shifting single %s by %p",pref(dataset,sequence),gref(nextchar),k) - end - done=true - break - end - end - if a and #a>0 then - local x,y,w,h=setpair(start,factor,rlmode,sequence.flags[4],a,injection) - if trace_kerns then - local startchar=getchar(start) - logprocess("%s: shifting first of pair %s and %s by (%p,%p) and correction (%p,%p) as %s",pref(dataset,sequence),gref(startchar),gref(nextchar),x,y,w,h,injection or "injections") - end - end - if b and #b>0 then - local x,y,w,h=setpair(snext,factor,rlmode,sequence.flags[4],b,injection) - if trace_kerns then - local startchar=getchar(snext) - logprocess("%s: shifting second of pair %s and %s by (%p,%p) and correction (%p,%p) as %s",pref(dataset,sequence),gref(startchar),gref(nextchar),x,y,w,h,injection or "injections") - end - end - done=true - break - elseif krn~=0 then - local k=setkern(snext,factor,rlmode,krn,injection) - if trace_kerns then - logprocess("%s: inserting kern %p between %s and %s as %s",pref(dataset,sequence),k,gref(getchar(prev)),gref(nextchar),injection or "injections") - end - done=true - break - else - break - end - else - break - end - end - return head,start,done - end -end -function handlers.gpos_mark2base(head,start,dataset,sequence,markanchors,rlmode) - local markchar=getchar(start) - if marks[markchar] then - local base=getprev(start) - if base then - local basechar=ischar(base,currentfont) - if basechar then - if marks[basechar] then - while base do - base=getprev(base) - if base then - basechar=ischar(base,currentfont) - if basechar then - if not marks[basechar] then - break - end - else - if trace_bugs then - logwarning("%s: no base for mark %s, case %i",pref(dataset,sequence),gref(markchar),1) - end - return head,start,false - end - else - if trace_bugs then - logwarning("%s: no base for mark %s, case %i",pref(dataset,sequence),gref(markchar),2) - end - return head,start,false - end - end - end - local ba=markanchors[1][basechar] - if ba then - local ma=markanchors[2] - local dx,dy,bound=setmark(start,base,factor,rlmode,ba,ma,characters[basechar],false,checkmarks) - if trace_marks then - logprocess("%s, anchor %s, bound %s: anchoring mark %s to basechar %s => (%p,%p)", - pref(dataset,sequence),anchor,bound,gref(markchar),gref(basechar),dx,dy) - end - return head,start,true - end - elseif trace_bugs then - logwarning("%s: nothing preceding, case %i",pref(dataset,sequence),1) - end - elseif trace_bugs then - logwarning("%s: nothing preceding, case %i",pref(dataset,sequence),2) - end - elseif trace_bugs then - logwarning("%s: mark %s is no mark",pref(dataset,sequence),gref(markchar)) - end - return head,start,false -end -function handlers.gpos_mark2ligature(head,start,dataset,sequence,markanchors,rlmode) - local markchar=getchar(start) - if marks[markchar] then - local base=getprev(start) - if base then - local basechar=ischar(base,currentfont) - if basechar then - if marks[basechar] then - while base do - base=getprev(base) - if base then - basechar=ischar(base,currentfont) - if basechar then - if not marks[basechar] then - break - end - else - if trace_bugs then - logwarning("%s: no base for mark %s, case %i",pref(dataset,sequence),gref(markchar),1) - end - return head,start,false - end - else - if trace_bugs then - logwarning("%s: no base for mark %s, case %i",pref(dataset,sequence),gref(markchar),2) - end - return head,start,false - end - end - end - local ba=markanchors[1][basechar] - if ba then - local ma=markanchors[2] - if ma then - local index=getligaindex(start) - ba=ba[index] - if ba then - local dx,dy,bound=setmark(start,base,factor,rlmode,ba,ma,characters[basechar],false,checkmarks) - if trace_marks then - logprocess("%s, anchor %s, index %s, bound %s: anchoring mark %s to baselig %s at index %s => (%p,%p)", - pref(dataset,sequence),anchor,index,bound,gref(markchar),gref(basechar),index,dx,dy) - end - return head,start,true - else - if trace_bugs then - logwarning("%s: no matching anchors for mark %s and baselig %s with index %a",pref(dataset,sequence),gref(markchar),gref(basechar),index) - end - end - end - elseif trace_bugs then - onetimemessage(currentfont,basechar,"no base anchors",report_fonts) - end - elseif trace_bugs then - logwarning("%s: prev node is no char, case %i",pref(dataset,sequence),1) - end - elseif trace_bugs then - logwarning("%s: prev node is no char, case %i",pref(dataset,sequence),2) - end - elseif trace_bugs then - logwarning("%s: mark %s is no mark",pref(dataset,sequence),gref(markchar)) - end - return head,start,false -end -function handlers.gpos_mark2mark(head,start,dataset,sequence,markanchors,rlmode) - local markchar=getchar(start) - if marks[markchar] then - local base=getprev(start) - local slc=getligaindex(start) - if slc then - while base do - local blc=getligaindex(base) - if blc and blc~=slc then - base=getprev(base) - else - break - end - end - end - if base then - local basechar=ischar(base,currentfont) - if basechar then - local ba=markanchors[1][basechar] - if ba then - local ma=markanchors[2] - local dx,dy,bound=setmark(start,base,factor,rlmode,ba,ma,characters[basechar],true,checkmarks) - if trace_marks then - logprocess("%s, anchor %s, bound %s: anchoring mark %s to basemark %s => (%p,%p)", - pref(dataset,sequence),anchor,bound,gref(markchar),gref(basechar),dx,dy) - end - return head,start,true - end - end - end - elseif trace_bugs then - logwarning("%s: mark %s is no mark",pref(dataset,sequence),gref(markchar)) - end - return head,start,false -end -function handlers.gpos_cursive(head,start,dataset,sequence,exitanchors,rlmode,step,i) - local done=false - local startchar=getchar(start) - if marks[startchar] then - if trace_cursive then - logprocess("%s: ignoring cursive for mark %s",pref(dataset,sequence),gref(startchar)) - end - else - local nxt=getnext(start) - while not done and nxt do - local nextchar=ischar(nxt,currentfont) - if not nextchar then - break - elseif marks[nextchar] then - nxt=getnext(nxt) - else - local exit=exitanchors[3] - if exit then - local entry=exitanchors[1][nextchar] - if entry then - entry=entry[2] - if entry then - local dx,dy,bound=setcursive(start,nxt,factor,rlmode,exit,entry,characters[startchar],characters[nextchar]) - if trace_cursive then - logprocess("%s: moving %s to %s cursive (%p,%p) using anchor %s and bound %s in %s mode",pref(dataset,sequence),gref(startchar),gref(nextchar),dx,dy,anchor,bound,mref(rlmode)) - end - done=true - end - end - end - break - end - end - end - return head,start,done -end -local chainprocs={} -local function logprocess(...) - if trace_steps then - registermessage(...) - end - report_subchain(...) -end -local logwarning=report_subchain -local function logprocess(...) - if trace_steps then - registermessage(...) - end - report_chain(...) -end -local logwarning=report_chain -local function reversesub(head,start,stop,dataset,sequence,replacements,rlmode) - local char=getchar(start) - local replacement=replacements[char] - if replacement then - if trace_singles then - logprocess("%s: single reverse replacement of %s by %s",cref(dataset,sequence),gref(char),gref(replacement)) - end - resetinjection(start) - setchar(start,replacement) - return head,start,true - else - return head,start,false - end -end -chainprocs.reversesub=reversesub -local function reportmoresteps(dataset,sequence) - logwarning("%s: more than 1 step",cref(dataset,sequence)) -end -function chainprocs.gsub_single(head,start,stop,dataset,sequence,currentlookup,chainindex) - local steps=currentlookup.steps - local nofsteps=currentlookup.nofsteps - if nofsteps>1 then - reportmoresteps(dataset,sequence) - end - local current=start - while current do - local currentchar=ischar(current) - if currentchar then - local replacement=steps[1].coverage[currentchar] - if not replacement or replacement=="" then - if trace_bugs then - logwarning("%s: no single for %s",cref(dataset,sequence,chainindex),gref(currentchar)) - end - else - if trace_singles then - logprocess("%s: replacing single %s by %s",cref(dataset,sequence,chainindex),gref(currentchar),gref(replacement)) - end - resetinjection(current) - setchar(current,replacement) - end - return head,start,true - elseif currentchar==false then - break - elseif current==stop then - break - else - current=getnext(current) - end - end - return head,start,false -end -function chainprocs.gsub_multiple(head,start,stop,dataset,sequence,currentlookup) - local steps=currentlookup.steps - local nofsteps=currentlookup.nofsteps - if nofsteps>1 then - reportmoresteps(dataset,sequence) - end - local startchar=getchar(start) - local replacement=steps[1].coverage[startchar] - if not replacement or replacement=="" then - if trace_bugs then - logwarning("%s: no multiple for %s",cref(dataset,sequence),gref(startchar)) - end - else - if trace_multiples then - logprocess("%s: replacing %s by multiple characters %s",cref(dataset,sequence),gref(startchar),gref(replacement)) - end - return multiple_glyphs(head,start,replacement,sequence.flags[1],dataset[1]) - end - return head,start,false -end -function chainprocs.gsub_alternate(head,start,stop,dataset,sequence,currentlookup) - local steps=currentlookup.steps - local nofsteps=currentlookup.nofsteps - if nofsteps>1 then - reportmoresteps(dataset,sequence) - end - local kind=dataset[4] - local what=dataset[1] - local value=what==true and tfmdata.shared.features[kind] or what - local current=start - while current do - local currentchar=ischar(current) - if currentchar then - local alternatives=steps[1].coverage[currentchar] - if alternatives then - local choice,comment=get_alternative_glyph(current,alternatives,value) - if choice then - if trace_alternatives then - logprocess("%s: replacing %s by alternative %a to %s, %s",cref(dataset,sequence),gref(char),choice,gref(choice),comment) - end - resetinjection(start) - setchar(start,choice) - else - if trace_alternatives then - logwarning("%s: no variant %a for %s, %s",cref(dataset,sequence),value,gref(char),comment) - end - end - end - return head,start,true - elseif currentchar==false then - break - elseif current==stop then - break - else - current=getnext(current) - end - end - return head,start,false -end -function chainprocs.gsub_ligature(head,start,stop,dataset,sequence,currentlookup,chainindex) - local steps=currentlookup.steps - local nofsteps=currentlookup.nofsteps - if nofsteps>1 then - reportmoresteps(dataset,sequence) - end - local startchar=getchar(start) - local ligatures=steps[1].coverage[startchar] - if not ligatures then - if trace_bugs then - logwarning("%s: no ligatures starting with %s",cref(dataset,sequence,chainindex),gref(startchar)) - end - else - local current=getnext(start) - local discfound=false - local last=stop - local nofreplacements=1 - local skipmark=currentlookup.flags[1] - while current do - local id=getid(current) - if id==disc_code then - if not discfound then - discfound=current - end - if current==stop then - break - else - current=getnext(current) - end - else - local schar=getchar(current) - if skipmark and marks[schar] then - current=getnext(current) - else - local lg=ligatures[schar] - if lg then - ligatures=lg - last=current - nofreplacements=nofreplacements+1 - if current==stop then - break - else - current=getnext(current) - end - else - break - end - end - end - end - local ligature=ligatures.ligature - if ligature then - if chainindex then - stop=last - end - if trace_ligatures then - if start==stop then - logprocess("%s: replacing character %s by ligature %s case 3",cref(dataset,sequence,chainindex),gref(startchar),gref(ligature)) - else - logprocess("%s: replacing character %s upto %s by ligature %s case 4",cref(dataset,sequence,chainindex),gref(startchar),gref(getchar(stop)),gref(ligature)) - end - end - head,start=toligature(head,start,stop,ligature,dataset,sequence,skipmark,discfound) - return head,start,true,nofreplacements,discfound - elseif trace_bugs then - if start==stop then - logwarning("%s: replacing character %s by ligature fails",cref(dataset,sequence,chainindex),gref(startchar)) - else - logwarning("%s: replacing character %s upto %s by ligature fails",cref(dataset,sequence,chainindex),gref(startchar),gref(getchar(stop))) - end - end - end - return head,start,false,0,false -end -function chainprocs.gpos_single(head,start,stop,dataset,sequence,currentlookup,rlmode,chainindex) - local steps=currentlookup.steps - local nofsteps=currentlookup.nofsteps - if nofsteps>1 then - reportmoresteps(dataset,sequence) - end - local startchar=getchar(start) - local step=steps[1] - local kerns=step.coverage[startchar] - if not kerns then - elseif step.format=="pair" then - local dx,dy,w,h=setpair(start,factor,rlmode,sequence.flags[4],kerns) - if trace_kerns then - logprocess("%s: shifting single %s by (%p,%p) and correction (%p,%p)",cref(dataset,sequence),gref(startchar),dx,dy,w,h) - end - else - local k=setkern(start,factor,rlmode,kerns,injection) - if trace_kerns then - logprocess("%s: shifting single %s by %p",cref(dataset,sequence),gref(startchar),k) - end - end - return head,start,false -end -function chainprocs.gpos_pair(head,start,stop,dataset,sequence,currentlookup,rlmode,chainindex) - local steps=currentlookup.steps - local nofsteps=currentlookup.nofsteps - if nofsteps>1 then - reportmoresteps(dataset,sequence) - end - local snext=getnext(start) - if snext then - local startchar=getchar(start) - local step=steps[1] - local kerns=step.coverage[startchar] - if kerns then - local prev=start - local done=false - while snext do - local nextchar=ischar(snext,currentfont) - if not nextchar then - break - end - local krn=kerns[nextchar] - if not krn and marks[nextchar] then - prev=snext - snext=getnext(snext) - elseif not krn then - break - elseif step.format=="pair" then - local a,b=krn[1],krn[2] - if optimizekerns then - if not b and a[1]==0 and a[2]==0 and a[4]==0 then - local k=setkern(snext,factor,rlmode,a[3],"injections") - if trace_kerns then - logprocess("%s: shifting single %s by %p",cref(dataset,sequence),gref(startchar),k) - end - done=true - break - end - end - if a and #a>0 then - local startchar=getchar(start) - local x,y,w,h=setpair(start,factor,rlmode,sequence.flags[4],a,"injections") - if trace_kerns then - logprocess("%s: shifting first of pair %s and %s by (%p,%p) and correction (%p,%p)",cref(dataset,sequence),gref(startchar),gref(nextchar),x,y,w,h) - end - end - if b and #b>0 then - local startchar=getchar(start) - local x,y,w,h=setpair(snext,factor,rlmode,sequence.flags[4],b,"injections") - if trace_kerns then - logprocess("%s: shifting second of pair %s and %s by (%p,%p) and correction (%p,%p)",cref(dataset,sequence),gref(startchar),gref(nextchar),x,y,w,h) - end - end - done=true - break - elseif krn~=0 then - local k=setkern(snext,factor,rlmode,krn) - if trace_kerns then - logprocess("%s: inserting kern %s between %s and %s",cref(dataset,sequence),k,gref(getchar(prev)),gref(nextchar)) - end - done=true - break - else - break - end - end - return head,start,done - end - end - return head,start,false -end -function chainprocs.gpos_mark2base(head,start,stop,dataset,sequence,currentlookup,rlmode) - local steps=currentlookup.steps - local nofsteps=currentlookup.nofsteps - if nofsteps>1 then - reportmoresteps(dataset,sequence) - end - local markchar=getchar(start) - if marks[markchar] then - local markanchors=steps[1].coverage[markchar] - if markanchors then - local base=getprev(start) - if base then - local basechar=ischar(base,currentfont) - if basechar then - if marks[basechar] then - while base do - base=getprev(base) - if base then - local basechar=ischar(base,currentfont) - if basechar then - if not marks[basechar] then - break - end - else - if trace_bugs then - logwarning("%s: no base for mark %s, case %i",pref(dataset,sequence),gref(markchar),1) - end - return head,start,false - end - else - if trace_bugs then - logwarning("%s: no base for mark %s, case %i",pref(dataset,sequence),gref(markchar),2) - end - return head,start,false - end - end - end - local ba=markanchors[1][basechar] - if ba then - local ma=markanchors[2] - if ma then - local dx,dy,bound=setmark(start,base,factor,rlmode,ba,ma,characters[basechar],false,checkmarks) - if trace_marks then - logprocess("%s, anchor %s, bound %s: anchoring mark %s to basechar %s => (%p,%p)", - cref(dataset,sequence),anchor,bound,gref(markchar),gref(basechar),dx,dy) - end - return head,start,true - end - end - elseif trace_bugs then - logwarning("%s: prev node is no char, case %i",cref(dataset,sequence),1) - end - elseif trace_bugs then - logwarning("%s: prev node is no char, case %i",cref(dataset,sequence),2) - end - elseif trace_bugs then - logwarning("%s: mark %s has no anchors",cref(dataset,sequence),gref(markchar)) - end - elseif trace_bugs then - logwarning("%s: mark %s is no mark",cref(dataset,sequence),gref(markchar)) - end - return head,start,false -end -function chainprocs.gpos_mark2ligature(head,start,stop,dataset,sequence,currentlookup,rlmode) - local steps=currentlookup.steps - local nofsteps=currentlookup.nofsteps - if nofsteps>1 then - reportmoresteps(dataset,sequence) - end - local markchar=getchar(start) - if marks[markchar] then - local markanchors=steps[1].coverage[markchar] - if markanchors then - local base=getprev(start) - if base then - local basechar=ischar(base,currentfont) - if basechar then - if marks[basechar] then - while base do - base=getprev(base) - if base then - local basechar=ischar(base,currentfont) - if basechar then - if not marks[basechar] then - break - end - else - if trace_bugs then - logwarning("%s: no base for mark %s, case %i",cref(dataset,sequence),markchar,1) - end - return head,start,false - end - else - if trace_bugs then - logwarning("%s: no base for mark %s, case %i",cref(dataset,sequence),markchar,2) - end - return head,start,false - end - end - end - local ba=markanchors[1][basechar] - if ba then - local ma=markanchors[2] - if ma then - local index=getligaindex(start) - ba=ba[index] - if ba then - local dx,dy,bound=setmark(start,base,factor,rlmode,ba,ma,characters[basechar],false,checkmarks) - if trace_marks then - logprocess("%s, anchor %s, bound %s: anchoring mark %s to baselig %s at index %s => (%p,%p)", - cref(dataset,sequence),anchor,a or bound,gref(markchar),gref(basechar),index,dx,dy) - end - return head,start,true - end - end - end - elseif trace_bugs then - logwarning("%s, prev node is no char, case %i",cref(dataset,sequence),1) - end - elseif trace_bugs then - logwarning("%s, prev node is no char, case %i",cref(dataset,sequence),2) - end - elseif trace_bugs then - logwarning("%s, mark %s has no anchors",cref(dataset,sequence),gref(markchar)) - end - elseif trace_bugs then - logwarning("%s, mark %s is no mark",cref(dataset,sequence),gref(markchar)) - end - return head,start,false -end -function chainprocs.gpos_mark2mark(head,start,stop,dataset,sequence,currentlookup,rlmode) - local steps=currentlookup.steps - local nofsteps=currentlookup.nofsteps - if nofsteps>1 then - reportmoresteps(dataset,sequence) - end - local markchar=getchar(start) - if marks[markchar] then - local markanchors=steps[1].coverage[markchar] - if markanchors then - local base=getprev(start) - local slc=getligaindex(start) - if slc then - while base do - local blc=getligaindex(base) - if blc and blc~=slc then - base=getprev(base) - else - break - end - end - end - if base then - local basechar=ischar(base,currentfont) - if basechar then - local ba=markanchors[1][basechar] - if ba then - local ma=markanchors[2] - if ma then - local dx,dy,bound=setmark(start,base,factor,rlmode,ba,ma,characters[basechar],true,checkmarks) - if trace_marks then - logprocess("%s, anchor %s, bound %s: anchoring mark %s to basemark %s => (%p,%p)", - cref(dataset,sequence),anchor,bound,gref(markchar),gref(basechar),dx,dy) - end - return head,start,true - end - end - elseif trace_bugs then - logwarning("%s: prev node is no mark, case %i",cref(dataset,sequence),1) - end - elseif trace_bugs then - logwarning("%s: prev node is no mark, case %i",cref(dataset,sequence),2) - end - elseif trace_bugs then - logwarning("%s: mark %s has no anchors",cref(dataset,sequence),gref(markchar)) - end - elseif trace_bugs then - logwarning("%s: mark %s is no mark",cref(dataset,sequence),gref(markchar)) - end - return head,start,false -end -function chainprocs.gpos_cursive(head,start,stop,dataset,sequence,currentlookup,rlmode) - local steps=currentlookup.steps - local nofsteps=currentlookup.nofsteps - if nofsteps>1 then - reportmoresteps(dataset,sequence) - end - local startchar=getchar(start) - local exitanchors=steps[1].coverage[startchar] - if exitanchors then - local done=false - if marks[startchar] then - if trace_cursive then - logprocess("%s: ignoring cursive for mark %s",pref(dataset,sequence),gref(startchar)) - end - else - local nxt=getnext(start) - while not done and nxt do - local nextchar=ischar(nxt,currentfont) - if not nextchar then - break - elseif marks[nextchar] then - nxt=getnext(nxt) - else - local exit=exitanchors[3] - if exit then - local entry=exitanchors[1][nextchar] - if entry then - entry=entry[2] - if entry then - local dx,dy,bound=setcursive(start,nxt,factor,rlmode,exit,entry,characters[startchar],characters[nextchar]) - if trace_cursive then - logprocess("%s: moving %s to %s cursive (%p,%p) using anchor %s and bound %s in %s mode",pref(dataset,sequence),gref(startchar),gref(nextchar),dx,dy,anchor,bound,mref(rlmode)) - end - done=true - break - end - end - elseif trace_bugs then - onetimemessage(currentfont,startchar,"no entry anchors",report_fonts) - end - break - end - end - end - return head,start,done - else - if trace_cursive and trace_details then - logprocess("%s, cursive %s is already done",pref(dataset,sequence),gref(getchar(start)),alreadydone) - end - return head,start,false - end -end -local function show_skip(dataset,sequence,char,ck,class) - logwarning("%s: skipping char %s, class %a, rule %a, lookuptype %a",cref(dataset,sequence),gref(char),class,ck[1],ck[8] or ck[2]) -end -local new_kern=nuts.pool.kern -local function checked(head) - local current=head - while current do - if getid(current)==glue_code then - local kern=new_kern(getfield(current,"width")) - if head==current then - local next=getnext(current) - if next then - setlink(kern,next) - end - flush_node(current) - head=kern - current=next - else - local prev,next=getboth(current) - setlink(prev,kern) - setlink(kern,next) - flush_node(current) - current=next - end - else - current=getnext(current) - end - end - return head -end -local function setdiscchecked(d,pre,post,replace) - if pre then pre=checked(pre) end - if post then post=checked(post) end - if replace then replace=checked(replace) end - setdisc(d,pre,post,replace) -end -local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,ck,chainproc) - if not start then - return head,start,false - end - local startishead=start==head - local seq=ck[3] - local f=ck[4] - local l=ck[5] - local s=#seq - local done=false - local sweepnode=sweepnode - local sweeptype=sweeptype - local sweepoverflow=false - local checkdisc=getprev(head) - local keepdisc=not sweepnode - local lookaheaddisc=nil - local backtrackdisc=nil - local current=start - local last=start - local prev=getprev(start) - local hasglue=false - local i=f - while i<=l do - local id=getid(current) - if id==glyph_code then - i=i+1 - last=current - current=getnext(current) - elseif id==glue_code then - i=i+1 - last=current - current=getnext(current) - hasglue=true - elseif id==disc_code then - if keepdisc then - keepdisc=false - if notmatchpre[current]~=notmatchreplace[current] then - lookaheaddisc=current - end - local replace=getfield(current,"replace") - while replace and i<=l do - if getid(replace)==glyph_code then - i=i+1 - end - replace=getnext(replace) - end - last=current - current=getnext(c) - else - head,current=flattendisk(head,current) - end - else - last=current - current=getnext(current) - end - if current then - elseif sweepoverflow then - break - elseif sweeptype=="post" or sweeptype=="replace" then - current=getnext(sweepnode) - if current then - sweeptype=nil - sweepoverflow=true - else - break - end - else - break - end - end - if sweepoverflow then - local prev=current and getprev(current) - if not current or prev~=sweepnode then - local head=getnext(sweepnode) - local tail=nil - if prev then - tail=prev - setprev(current,sweepnode) - else - tail=find_node_tail(head) - end - setnext(sweepnode,current) - setprev(head) - setnext(tail) - appenddisc(sweepnode,head) - end - end - if l<s then - local i=l - local t=sweeptype=="post" or sweeptype=="replace" - while current and i<s do - local id=getid(current) - if id==glyph_code then - i=i+1 - current=getnext(current) - elseif id==glue_code then - i=i+1 - current=getnext(current) - hasglue=true - elseif id==disc_code then - if keepdisc then - keepdisc=false - if notmatchpre[current]~=notmatchreplace[current] then - lookaheaddisc=current - end - local replace=getfield(c,"replace") - while replace and i<s do - if getid(replace)==glyph_code then - i=i+1 - end - replace=getnext(replace) - end - current=getnext(current) - elseif notmatchpre[current]~=notmatchreplace[current] then - head,current=flattendisk(head,current) - else - current=getnext(current) - end - else - current=getnext(current) - end - if not current and t then - current=getnext(sweepnode) - if current then - sweeptype=nil - end - end - end - end - if f>1 then - local current=prev - local i=f - local t=sweeptype=="pre" or sweeptype=="replace" - if not current and t and current==checkdisk then - current=getprev(sweepnode) - end - while current and i>1 do - local id=getid(current) - if id==glyph_code then - i=i-1 - elseif id==glue_code then - i=i-1 - hasglue=true - elseif id==disc_code then - if keepdisc then - keepdisc=false - if notmatchpost[current]~=notmatchreplace[current] then - backtrackdisc=current - end - local replace=getfield(current,"replace") - while replace and i>1 do - if getid(replace)==glyph_code then - i=i-1 - end - replace=getnext(replace) - end - elseif notmatchpost[current]~=notmatchreplace[current] then - head,current=flattendisk(head,current) - end - end - current=getprev(current) - if t and current==checkdisk then - current=getprev(sweepnode) - end - end - end - local ok=false - if lookaheaddisc then - local cf=start - local cl=getprev(lookaheaddisc) - local cprev=getprev(start) - local insertedmarks=0 - while cprev do - local char=ischar(cf,currentfont) - if char and marks[char] then - insertedmarks=insertedmarks+1 - cf=cprev - startishead=cf==head - cprev=getprev(cprev) - else - break - end - end - setprev(lookaheaddisc,cprev) - if cprev then - setnext(cprev,lookaheaddisc) - end - setprev(cf) - setnext(cl) - if startishead then - head=lookaheaddisc - end - local pre,post,replace=getdisc(lookaheaddisc) - local new=copy_node_list(cf) - local cnew=new - for i=1,insertedmarks do - cnew=getnext(cnew) - end - local clast=cnew - for i=f,l do - clast=getnext(clast) - end - if not notmatchpre[lookaheaddisc] then - cf,start,ok=chainproc(cf,start,last,dataset,sequence,chainlookup,rlmode,k) - end - if not notmatchreplace[lookaheaddisc] then - new,cnew,ok=chainproc(new,cnew,clast,dataset,sequence,chainlookup,rlmode,k) - end - if pre then - setlink(cl,pre) - end - if replace then - local tail=find_node_tail(new) - setlink(tail,replace) - end - if hasglue then - setdiscchecked(lookaheaddisc,cf,post,new) - else - setdisc(lookaheaddisc,cf,post,new) - end - start=getprev(lookaheaddisc) - sweephead[cf]=getnext(clast) - sweephead[new]=getnext(last) - elseif backtrackdisc then - local cf=getnext(backtrackdisc) - local cl=start - local cnext=getnext(start) - local insertedmarks=0 - while cnext do - local char=ischar(cnext,currentfont) - if char and marks[char] then - insertedmarks=insertedmarks+1 - cl=cnext - cnext=getnext(cnext) - else - break - end - end - if cnext then - setprev(cnext,backtrackdisc) - end - setnext(backtrackdisc,cnext) - setprev(cf) - setnext(cl) - local pre,post,replace,pretail,posttail,replacetail=getdisc(backtrackdisc,true) - local new=copy_node_list(cf) - local cnew=find_node_tail(new) - for i=1,insertedmarks do - cnew=getprev(cnew) - end - local clast=cnew - for i=f,l do - clast=getnext(clast) - end - if not notmatchpost[backtrackdisc] then - cf,start,ok=chainproc(cf,start,last,dataset,sequence,chainlookup,rlmode,k) - end - if not notmatchreplace[backtrackdisc] then - new,cnew,ok=chainproc(new,cnew,clast,dataset,sequence,chainlookup,rlmode,k) - end - if post then - setlink(posttail,cf) - else - post=cf - end - if replace then - setlink(replacetail,new) - else - replace=new - end - if hasglue then - setdiscchecked(backtrackdisc,pre,post,replace) - else - setdisc(backtrackdisc,pre,post,replace) - end - start=getprev(backtrackdisc) - sweephead[post]=getnext(clast) - sweephead[replace]=getnext(last) - else - head,start,ok=chainproc(head,start,last,dataset,sequence,chainlookup,rlmode,k) - end - return head,start,ok -end -local noflags={ false,false,false,false } -local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode) - local sweepnode=sweepnode - local sweeptype=sweeptype - local currentfont=currentfont - local diskseen=false - local checkdisc=getprev(head) - local flags=sequence.flags or noflags - local done=false - local skipmark=flags[1] - local skipligature=flags[2] - local skipbase=flags[3] - local markclass=sequence.markclass - local skipped=false - for k=1,#contexts do - local match=true - local current=start - local last=start - local ck=contexts[k] - local seq=ck[3] - local s=#seq - local size=1 - if s==1 then - local char=ischar(current,currentfont) - if char then - match=seq[1][char] - end - else - local f=ck[4] - local l=ck[5] - size=l-f+1 - if size>1 then - local discfound=nil - local n=f+1 - last=getnext(last) - while n<=l do - if not last and (sweeptype=="post" or sweeptype=="replace") then - last=getnext(sweepnode) - sweeptype=nil - end - if last then - local char,id=ischar(last,currentfont) - if char then - local ccd=descriptions[char] - if ccd then - local class=ccd.class or "base" - if class==skipmark or class==skipligature or class==skipbase or (markclass and class=="mark" and not markclass[char]) then - skipped=true - if trace_skips then - show_skip(dataset,sequence,char,ck,class) - end - last=getnext(last) - elseif seq[n][char] then - if n<l then - last=getnext(last) - end - n=n+1 - else - if discfound then - notmatchreplace[discfound]=true - match=not notmatchpre[discfound] - else - match=false - end - break - end - else - if discfound then - notmatchreplace[discfound]=true - match=not notmatchpre[discfound] - else - match=false - end - break - end - elseif char==false then - if discfound then - notmatchreplace[discfound]=true - match=not notmatchpre[discfound] - else - match=false - end - break - elseif id==disc_code then - diskseen=true - discfound=last - notmatchpre[last]=nil - notmatchpost[last]=true - notmatchreplace[last]=nil - local pre,post,replace=getdisc(last) - if pre then - local n=n - while pre do - if seq[n][getchar(pre)] then - n=n+1 - pre=getnext(pre) - if n>l then - break - end - else - notmatchpre[last]=true - break - end - end - if n<=l then - notmatchpre[last]=true - end - else - notmatchpre[last]=true - end - if replace then - while replace do - if seq[n][getchar(replace)] then - n=n+1 - replace=getnext(replace) - if n>l then - break - end - else - notmatchreplace[last]=true - match=not notmatchpre[last] - break - end - end - match=not notmatchpre[last] - end - last=getnext(last) - else - match=false - break - end - else - match=false - break - end - end - end - if match and f>1 then - local prev=getprev(start) - if prev then - if prev==checkdisc and (sweeptype=="pre" or sweeptype=="replace") then - prev=getprev(sweepnode) - end - if prev then - local discfound=nil - local n=f-1 - while n>=1 do - if prev then - local char,id=ischar(prev,currentfont) - if char then - local ccd=descriptions[char] - if ccd then - local class=ccd.class - if class==skipmark or class==skipligature or class==skipbase or (markclass and class=="mark" and not markclass[char]) then - skipped=true - if trace_skips then - show_skip(dataset,sequence,char,ck,class) - end - prev=getprev(prev) - elseif seq[n][char] then - if n>1 then - prev=getprev(prev) - end - n=n-1 - else - if discfound then - notmatchreplace[discfound]=true - match=not notmatchpost[discfound] - else - match=false - end - break - end - else - if discfound then - notmatchreplace[discfound]=true - match=not notmatchpost[discfound] - else - match=false - end - break - end - elseif char==false then - if discfound then - notmatchreplace[discfound]=true - match=not notmatchpost[discfound] - else - match=false - end - break - elseif id==disc_code then - diskseen=true - discfound=prev - notmatchpre[prev]=true - notmatchpost[prev]=nil - notmatchreplace[prev]=nil - local pre,post,replace,pretail,posttail,replacetail=getdisc(prev,true) - if pre~=start and post~=start and replace~=start then - if post then - local n=n - while posttail do - if seq[n][getchar(posttail)] then - n=n-1 - if posttail==post then - break - else - posttail=getprev(posttail) - if n<1 then - break - end - end - else - notmatchpost[prev]=true - break - end - end - if n>=1 then - notmatchpost[prev]=true - end - else - notmatchpost[prev]=true - end - if replace then - while replacetail do - if seq[n][getchar(replacetail)] then - n=n-1 - if replacetail==replace then - break - else - replacetail=getprev(replacetail) - if n<1 then - break - end - end - else - notmatchreplace[prev]=true - match=not notmatchpost[prev] - break - end - end - if not match then - break - end - end - end - prev=getprev(prev) - elseif seq[n][32] and isspace(prev,threshold) then - n=n-1 - prev=getprev(prev) - else - match=false - break - end - else - match=false - break - end - end - else - match=false - end - else - match=false - end - end - if match and s>l then - local current=last and getnext(last) - if not current then - if sweeptype=="post" or sweeptype=="replace" then - current=getnext(sweepnode) - end - end - if current then - local discfound=nil - local n=l+1 - while n<=s do - if current then - local char,id=ischar(current,currentfont) - if char then - local ccd=descriptions[char] - if ccd then - local class=ccd.class - if class==skipmark or class==skipligature or class==skipbase or (markclass and class=="mark" and not markclass[char]) then - skipped=true - if trace_skips then - show_skip(dataset,sequence,char,ck,class) - end - current=getnext(current) - elseif seq[n][char] then - if n<s then - current=getnext(current) - end - n=n+1 - else - if discfound then - notmatchreplace[discfound]=true - match=not notmatchpre[discfound] - else - match=false - end - break - end - else - if discfound then - notmatchreplace[discfound]=true - match=not notmatchpre[discfound] - else - match=false - end - break - end - elseif char==false then - if discfound then - notmatchreplace[discfound]=true - match=not notmatchpre[discfound] - else - match=false - end - break - elseif id==disc_code then - diskseen=true - discfound=current - notmatchpre[current]=nil - notmatchpost[current]=true - notmatchreplace[current]=nil - local pre,post,replace=getdisc(current) - if pre then - local n=n - while pre do - if seq[n][getchar(pre)] then - n=n+1 - pre=getnext(pre) - if n>s then - break - end - else - notmatchpre[current]=true - break - end - end - if n<=s then - notmatchpre[current]=true - end - else - notmatchpre[current]=true - end - if replace then - while replace do - if seq[n][getchar(replace)] then - n=n+1 - replace=getnext(replace) - if n>s then - break - end - else - notmatchreplace[current]=true - match=notmatchpre[current] - break - end - end - if not match then - break - end - else - end - current=getnext(current) - elseif seq[n][32] and isspace(current,threshold) then - n=n+1 - current=getnext(current) - else - match=false - break - end - else - match=false - break - end - end - else - match=false - end - end - end - if match then - local diskchain=diskseen or sweepnode - if trace_contexts then - local rule=ck[1] - local lookuptype=ck[8] or ck[2] - local first=ck[4] - local last=ck[5] - local char=getchar(start) - logwarning("%s: rule %s matches at char %s for (%s,%s,%s) chars, lookuptype %a", - cref(dataset,sequence),rule,gref(char),first-1,last-first+1,s-last,lookuptype) - end - local chainlookups=ck[6] - if chainlookups then - local nofchainlookups=#chainlookups - if size==1 then - local chainlookup=chainlookups[1] - local chainkind=chainlookup.type - local chainproc=chainprocs[chainkind] - if chainproc then - local ok - if diskchain then - head,start,ok=chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,1,ck,chainproc) - else - head,start,ok=chainproc(head,start,last,dataset,sequence,chainlookup,rlmode,1) - end - if ok then - done=true - end - else - logprocess("%s: %s is not yet supported (1)",cref(dataset,sequence),chainkind) - end - else - local i=1 - while start do - if skipped then - while start do - local char=getchar(start) - local ccd=descriptions[char] - if ccd then - local class=ccd.class or "base" - if class==skipmark or class==skipligature or class==skipbase or (markclass and class=="mark" and not markclass[char]) then - start=getnext(start) - else - break - end - else - break - end - end - end - local chainlookup=chainlookups[i] - if chainlookup then - local chainkind=chainlookup.type - local chainproc=chainprocs[chainkind] - if chainproc then - local ok,n - if diskchain then - head,start,ok=chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,i,ck,chainproc) - else - head,start,ok,n=chainproc(head,start,last,dataset,sequence,chainlookup,rlmode,i) - end - if ok then - done=true - if n and n>1 and i+n>nofchainlookups then - break - end - end - else - logprocess("%s: %s is not yet supported (2)",cref(dataset,sequence),chainkind) - end - end - i=i+1 - if i>size or not start then - break - elseif start then - start=getnext(start) - end - end - end - else - local replacements=ck[7] - if replacements then - head,start,done=reversesub(head,start,last,dataset,sequence,replacements,rlmode) - else - done=true - if trace_contexts then - logprocess("%s: skipping match",cref(dataset,sequence)) - end - end - end - if done then - break - end - end - end - if diskseen then - notmatchpre={} - notmatchpost={} - notmatchreplace={} - end - return head,start,done -end -handlers.gsub_context=handle_contextchain -handlers.gsub_contextchain=handle_contextchain -handlers.gsub_reversecontextchain=handle_contextchain -handlers.gpos_contextchain=handle_contextchain -handlers.gpos_context=handle_contextchain -local function chained_contextchain(head,start,stop,dataset,sequence,currentlookup,rlmode) - local steps=currentlookup.steps - local nofsteps=currentlookup.nofsteps - if nofsteps>1 then - reportmoresteps(dataset,sequence) - end - return handle_contextchain(head,start,dataset,sequence,currentlookup,rlmode) -end -chainprocs.gsub_context=chained_contextchain -chainprocs.gsub_contextchain=chained_contextchain -chainprocs.gsub_reversecontextchain=chained_contextchain -chainprocs.gpos_contextchain=chained_contextchain -chainprocs.gpos_context=chained_contextchain -local missing=setmetatableindex("table") -local function logprocess(...) - if trace_steps then - registermessage(...) - end - report_process(...) -end -local logwarning=report_process -local function report_missing_coverage(dataset,sequence) - local t=missing[currentfont] - if not t[sequence] then - t[sequence]=true - logwarning("missing coverage for feature %a, lookup %a, type %a, font %a, name %a", - dataset[4],sequence.name,sequence.type,currentfont,tfmdata.properties.fullname) - end -end -local resolved={} -local sequencelists=setmetatableindex(function(t,font) - local sequences=fontdata[font].resources.sequences - if not sequences or not next(sequences) then - sequences=false - end - t[font]=sequences - return sequences -end) -local autofeatures=fonts.analyzers.features -local featuretypes=otf.tables.featuretypes -local defaultscript=otf.features.checkeddefaultscript -local defaultlanguage=otf.features.checkeddefaultlanguage -local function initialize(sequence,script,language,enabled,autoscript,autolanguage) - local features=sequence.features - if features then - local order=sequence.order - if order then - local featuretype=featuretypes[sequence.type or "unknown"] - for i=1,#order do - local kind=order[i] - local valid=enabled[kind] - if valid then - local scripts=features[kind] - local languages=scripts and ( - scripts[script] or - scripts[wildcard] or - (autoscript and defaultscript(featuretype,autoscript,scripts)) - ) - local enabled=languages and ( - languages[language] or - languages[wildcard] or - (autolanguage and defaultlanguage(featuretype,autolanguage,languages)) - ) - if enabled then - return { valid,autofeatures[kind] or false,sequence,kind } - end - end - end - else - end - end - return false -end -function otf.dataset(tfmdata,font) - local shared=tfmdata.shared - local properties=tfmdata.properties - local language=properties.language or "dflt" - local script=properties.script or "dflt" - local enabled=shared.features - local autoscript=enabled and enabled.autoscript - local autolanguage=enabled and enabled.autolanguage - local res=resolved[font] - if not res then - res={} - resolved[font]=res - end - local rs=res[script] - if not rs then - rs={} - res[script]=rs - end - local rl=rs[language] - if not rl then - rl={ - } - rs[language]=rl - local sequences=tfmdata.resources.sequences - if sequences then - for s=1,#sequences do - local v=enabled and initialize(sequences[s],script,language,enabled,autoscript,autolanguage) - if v then - rl[#rl+1]=v - end - end - end - end - return rl -end -local function report_disc(what,n) - report_run("%s: %s > %s",what,n,languages.serializediscretionary(n)) -end -local function kernrun(disc,k_run,font,attr,...) - if trace_kernruns then - report_disc("kern",disc) - end - local prev,next=getboth(disc) - local nextstart=next - local done=false - local pre,post,replace,pretail,posttail,replacetail=getdisc(disc,true) - local prevmarks=prev - while prevmarks do - local char=ischar(prevmarks,font) - if char and marks[char] then - prevmarks=getprev(prevmarks) - else - break - end - end - if prev and not ischar(prev,font) then - prev=false - end - if next and not ischar(next,font) then - next=false - end - if pre then - if k_run(pre,"injections",nil,font,attr,...) then - done=true - end - if prev then - local nest=getprev(pre) - setlink(prev,pre) - if k_run(prevmarks,"preinjections",pre,font,attr,...) then - done=true - end - setprev(pre,nest) - setnext(prev,disc) - end - end - if post then - if k_run(post,"injections",nil,font,attr,...) then - done=true - end - if next then - setlink(posttail,next) - if k_run(posttail,"postinjections",next,font,attr,...) then - done=true - end - setnext(posttail) - setprev(next,disc) - end - end - if replace then - if k_run(replace,"injections",nil,font,attr,...) then - done=true - end - if prev then - local nest=getprev(replace) - setlink(prev,replace) - if k_run(prevmarks,"replaceinjections",replace,font,attr,...) then - done=true - end - setprev(replace,nest) - setnext(prev,disc) - end - if next then - setlink(replacetail,next) - if k_run(replacetail,"replaceinjections",next,font,attr,...) then - done=true - end - setnext(replacetail) - setprev(next,disc) - end - elseif prev and next then - setlink(prev,next) - if k_run(prevmarks,"emptyinjections",next,font,attr,...) then - done=true - end - setlink(prev,disc) - setlink(disc,next) - end - return nextstart,done -end -local function comprun(disc,c_run,...) - if trace_compruns then - report_disc("comp",disc) - end - local pre,post,replace=getdisc(disc) - local renewed=false - if pre then - sweepnode=disc - sweeptype="pre" - local new,done=c_run(pre,...) - if done then - pre=new - renewed=true - end - end - if post then - sweepnode=disc - sweeptype="post" - local new,done=c_run(post,...) - if done then - post=new - renewed=true - end - end - if replace then - sweepnode=disc - sweeptype="replace" - local new,done=c_run(replace,...) - if done then - replace=new - renewed=true - end - end - sweepnode=nil - sweeptype=nil - if renewed then - setdisc(disc,pre,post,replace) - end - return getnext(disc),renewed -end -local function testrun(disc,t_run,c_run,...) - if trace_testruns then - report_disc("test",disc) - end - local prev,next=getboth(disc) - if not next then - return - end - local pre,post,replace,pretail,posttail,replacetail=getdisc(disc,true) - local done=false - if replace and prev then - setlink(replacetail,next) - local ok,overflow=t_run(replace,next,...) - if ok and overflow then - setfield(disc,"replace") - setlink(prev,replace) - setboth(disc) - flush_node_list(disc) - return replace,true - else - setnext(replacetail) - setprev(next,disc) - end - end - local renewed=false - if pre then - sweepnode=disc - sweeptype="pre" - local new,ok=c_run(pre,...) - if ok then - pre=new - renewed=true - end - end - if post then - sweepnode=disc - sweeptype="post" - local new,ok=c_run(post,...) - if ok then - post=new - renewed=true - end - end - if replace then - sweepnode=disc - sweeptype="replace" - local new,ok=c_run(replace,...) - if ok then - replace=new - renewed=true - end - end - sweepnode=nil - sweeptype=nil - if renewed then - setdisc(disc,pre,post,replace) - return next,true - else - return next,done - end -end -local nesting=0 -local function c_run_single(head,font,attr,lookupcache,step,dataset,sequence,rlmode,handler) - local done=false - local sweep=sweephead[head] - if sweep then - start=sweep - sweephead[head]=nil - else - start=head - end - while start do - local char=ischar(start,font) - if char then - local a=attr and getattr(start,0) - if not a or (a==attr) then - local lookupmatch=lookupcache[char] - if lookupmatch then - local ok - head,start,ok=handler(head,start,dataset,sequence,lookupmatch,rlmode,step,1) - if ok then - done=true - end - end - if start then - start=getnext(start) - end - else - start=getnext(start) - end - elseif char==false then - return head,done - elseif sweep then - return head,done - else - start=getnext(start) - end - end - return head,done -end -local function t_run_single(start,stop,font,attr,lookupcache) - while start~=stop do - local char=ischar(start,font) - if char then - local a=attr and getattr(start,0) - if not a or (a==attr) then - local lookupmatch=lookupcache[char] - if lookupmatch then - local s=getnext(start) - local l=nil - local d=0 - while s do - if s==stop then - d=1 - elseif d>0 then - d=d+1 - end - local lg=lookupmatch[getchar(s)] - if lg then - l=lg - s=getnext(s) - else - break - end - end - if l and l.ligature then - return true,d>1 - end - end - else - end - start=getnext(start) - else - break - end - end -end -local function k_run_single(sub,injection,last,font,attr,lookupcache,step,dataset,sequence,rlmode,handler) - local a=attr and getattr(sub,0) - if not a or (a==attr) then - for n in traverse_nodes(sub) do - if n==last then - break - end - local char=ischar(n) - if char then - local lookupmatch=lookupcache[char] - if lookupmatch then - local h,d,ok=handler(sub,n,dataset,sequence,lookupmatch,rlmode,step,1,injection) - if ok then - return true - end - end - end - end - end -end -local function c_run_multiple(head,font,attr,steps,nofsteps,dataset,sequence,rlmode,handler) - local done=false - local sweep=sweephead[head] - if sweep then - start=sweep - sweephead[head]=nil - else - start=head - end - while start do - local char=ischar(start,font) - if char then - local a=attr and getattr(start,0) - if not a or (a==attr) then - for i=1,nofsteps do - local step=steps[i] - local lookupcache=step.coverage - if lookupcache then - local lookupmatch=lookupcache[char] - if lookupmatch then - local ok - head,start,ok=handler(head,start,dataset,sequence,lookupmatch,rlmode,step,i) - if ok then - done=true - break - elseif not start then - break - end - end - else - report_missing_coverage(dataset,sequence) - end - end - if start then - start=getnext(start) - end - else - start=getnext(start) - end - elseif char==false then - return head,done - elseif sweep then - return head,done - else - start=getnext(start) - end - end - return head,done -end -local function t_run_multiple(start,stop,font,attr,steps,nofsteps) - while start~=stop do - local char=ischar(start,font) - if char then - local a=attr and getattr(start,0) - if not a or (a==attr) then - for i=1,nofsteps do - local step=steps[i] - local lookupcache=step.coverage - if lookupcache then - local lookupmatch=lookupcache[char] - if lookupmatch then - local s=getnext(start) - local l=nil - local d=0 - while s do - if s==stop then - d=1 - elseif d>0 then - d=d+1 - end - local lg=lookupmatch[getchar(s)] - if lg then - l=lg - s=getnext(s) - else - break - end - end - if l and l.ligature then - return true,d>1 - end - end - else - report_missing_coverage(dataset,sequence) - end - end - else - end - start=getnext(start) - else - break - end - end -end -local function k_run_multiple(sub,injection,last,font,attr,steps,nofsteps,dataset,sequence,rlmode,handler) - local a=attr and getattr(sub,0) - if not a or (a==attr) then - for n in traverse_nodes(sub) do - if n==last then - break - end - local char=ischar(n) - if char then - for i=1,nofsteps do - local step=steps[i] - local lookupcache=step.coverage - if lookupcache then - local lookupmatch=lookupcache[char] - if lookupmatch then - local h,d,ok=handler(head,n,dataset,sequence,lookupmatch,step,rlmode,i,injection) - if ok then - return true - end - end - else - report_missing_coverage(dataset,sequence) - end - end - end - end - end -end -local function txtdirstate(start,stack,top,rlparmode) - local dir=getfield(start,"dir") - local new=1 - if dir=="+TRT" then - top=top+1 - stack[top]=dir - new=-1 - elseif dir=="+TLT" then - top=top+1 - stack[top]=dir - elseif dir=="-TRT" or dir=="-TLT" then - top=top-1 - if stack[top]=="+TRT" then - new=-1 - end - else - new=rlparmode - end - if trace_directions then - report_process("directions after txtdir %a: parmode %a, txtmode %a, level %a",dir,mref(rlparmode),mref(new),top) - end - return getnext(start),top,new -end -local function pardirstate(start) - local dir=getfield(start,"dir") - local new=0 - if dir=="TLT" then - new=1 - elseif dir=="TRT" then - new=-1 - end - if trace_directions then - report_process("directions after pardir %a: parmode %a",dir,mref(new)) - end - return getnext(start),new,new -end -otf.helpers=otf.helpers or {} -otf.helpers.txtdirstate=txtdirstate -otf.helpers.pardirstate=pardirstate -local function featuresprocessor(head,font,attr) - local sequences=sequencelists[font] - if not sequencelists then - return head,false - end - nesting=nesting+1 - if nesting==1 then - currentfont=font - tfmdata=fontdata[font] - descriptions=tfmdata.descriptions - characters=tfmdata.characters - marks=tfmdata.resources.marks - threshold, - factor=getthreshold(font) - checkmarks=tfmdata.properties.checkmarks - elseif currentfont~=font then - report_warning("nested call with a different font, level %s, quitting",nesting) - nesting=nesting-1 - return head,false - end - head=tonut(head) - if trace_steps then - checkstep(head) - end - local rlmode=0 - local done=false - local datasets=otf.dataset(tfmdata,font,attr) - local forcedisc=alwaysdisc or not attr - local dirstack={} - sweephead={} - for s=1,#datasets do - local dataset=datasets[s] - local attribute=dataset[2] - local sequence=dataset[3] - local rlparmode=0 - local topstack=0 - local success=false - local typ=sequence.type - local gpossing=typ=="gpos_single" or typ=="gpos_pair" - local handler=handlers[typ] - local steps=sequence.steps - local nofsteps=sequence.nofsteps - if not steps then - local h,d,ok=handler(head,head,dataset,sequence,nil,nil,nil,0,font,attr) - if ok then - success=true - if h then - head=h - end - end - elseif typ=="gsub_reversecontextchain" then - local start=find_node_tail(head) - while start do - local char=ischar(start,font) - if char then - local a=attr and getattr(start,0) - if not a or (a==attr) then - for i=1,nofsteps do - local step=steps[i] - local lookupcache=step.coverage - if lookupcache then - local lookupmatch=lookupcache[char] - if lookupmatch then - local ok - head,start,ok=handler(head,start,dataset,sequence,lookupmatch,rlmode,step,i) - if ok then - success=true - break - end - end - else - report_missing_coverage(dataset,sequence) - end - end - if start then - start=getprev(start) - end - else - start=getprev(start) - end - else - start=getprev(start) - end - end - else - local start=head - rlmode=0 - if nofsteps==1 then - local step=steps[1] - local lookupcache=step.coverage - if not lookupcache then - report_missing_coverage(dataset,sequence) - else - while start do - local char,id=ischar(start,font) - if char then - local a=attr and getattr(start,0) - if a then - a=(a==attr) and (not attribute or getprop(start,a_state)==attribute) - else - a=not attribute or getprop(start,a_state)==attribute - end - if a then - local lookupmatch=lookupcache[char] - if lookupmatch then - local ok - head,start,ok=handler(head,start,dataset,sequence,lookupmatch,rlmode,step,1) - if ok then - success=true - end - end - if start then - start=getnext(start) - end - else - start=getnext(start) - end - elseif char==false then - start=getnext(start) - elseif id==disc_code then - local a=forcedisc or getsubtype(start)==discretionary_code or getattr(start,0)==attr - if a then - local ok - if gpossing then - start,ok=kernrun(start,k_run_single,font,attr,lookupcache,step,dataset,sequence,rlmode,handler) - elseif typ=="gsub_ligature" then - start,ok=testrun(start,t_run_single,c_run_single,font,attr,lookupcache,step,dataset,sequence,rlmode,handler) - else - start,ok=comprun(start,c_run_single,font,attr,lookupcache,step,dataset,sequence,rlmode,handler) - end - if ok then - success=true - end - else - start=getnext(start) - end - elseif id==math_code then - start=getnext(end_of_math(start)) - elseif id==dir_code then - start,topstack,rlmode=txtdirstate(start,dirstack,topstack,rlparmode) - elseif id==localpar_code then - start,rlparmode,rlmode=pardirstate(start) - else - start=getnext(start) - end - end - end - else - while start do - local char,id=ischar(start,font) - if char then - local a=attr and getattr(start,0) - if a then - a=(a==attr) and (not attribute or getprop(start,a_state)==attribute) - else - a=not attribute or getprop(start,a_state)==attribute - end - if a then - for i=1,nofsteps do - local step=steps[i] - local lookupcache=step.coverage - if lookupcache then - local lookupmatch=lookupcache[char] - if lookupmatch then - local ok - head,start,ok=handler(head,start,dataset,sequence,lookupmatch,rlmode,step,i) - if ok then - success=true - break - elseif not start then - break - end - end - else - report_missing_coverage(dataset,sequence) - end - end - if start then - start=getnext(start) - end - else - start=getnext(start) - end - elseif char==false then - start=getnext(start) - elseif id==disc_code then - local a=forcedisc or getsubtype(start)==discretionary_code or getattr(start,0)==attr - if a then - local ok - if gpossing then - start,ok=kernrun(start,k_run_multiple,font,attr,steps,nofsteps,dataset,sequence,rlmode,handler) - elseif typ=="gsub_ligature" then - start,ok=testrun(start,t_run_multiple,c_run_multiple,font,attr,steps,nofsteps,dataset,sequence,rlmode,handler) - else - start,ok=comprun(start,c_run_multiple,font,attr,steps,nofsteps,dataset,sequence,rlmode,handler) - end - if ok then - success=true - end - else - start=getnext(start) - end - elseif id==math_code then - start=getnext(end_of_math(start)) - elseif id==dir_code then - start,topstack,rlmode=txtdirstate(start,dirstack,topstack,rlparmode) - elseif id==localpar_code then - start,rlparmode,rlmode=pardirstate(start) - else - start=getnext(start) - end - end - end - end - if success then - done=true - end - if trace_steps then - registerstep(head) - end - end - nesting=nesting-1 - head=tonode(head) - return head,done -end -local plugins={} -otf.plugins=plugins -function otf.registerplugin(name,f) - if type(name)=="string" and type(f)=="function" then - plugins[name]={ name,f } - end -end -local function plugininitializer(tfmdata,value) - if type(value)=="string" then - tfmdata.shared.plugin=plugins[value] - end -end -local function pluginprocessor(head,font) - local s=fontdata[font].shared - local p=s and s.plugin - if p then - if trace_plugins then - report_process("applying plugin %a",p[1]) - end - return p[2](head,font) - else - return head,false - end -end -local function featuresinitializer(tfmdata,value) -end -registerotffeature { - name="features", - description="features", - default=true, - initializers={ - position=1, - node=featuresinitializer, - plug=plugininitializer, - }, - processors={ - node=featuresprocessor, - plug=pluginprocessor, - } -} -otf.nodemodeinitializer=featuresinitializer -otf.featuresprocessor=featuresprocessor -otf.handlers=handlers -local setspacekerns=nodes.injections.setspacekerns if not setspacekerns then os.exit() end -if fontfeatures then - function otf.handlers.trigger_space_kerns(head,start,dataset,sequence,_,_,_,_,font,attr) - local features=fontfeatures[font] - local enabled=features and features.spacekern and features.kern - if enabled then - setspacekerns(font,sequence) - end - return head,start,enabled - end -else - function otf.handlers.trigger_space_kerns(head,start,dataset,sequence,_,_,_,_,font,attr) - local shared=fontdata[font].shared - local features=shared and shared.features - local enabled=features and features.spacekern and features.kern - if enabled then - setspacekerns(font,sequence) - end - return head,start,enabled - end -end -local function hasspacekerns(data) - local sequences=data.resources.sequences - for i=1,#sequences do - local sequence=sequences[i] - local steps=sequence.steps - if steps and sequence.features.kern then - for i=1,#steps do - local coverage=steps[i].coverage - if not coverage then - elseif coverage[32] then - return true - else - for k,v in next,coverage do - if v[32] then - return true - end - end - end - end - end - end - return false -end -otf.readers.registerextender { - name="spacekerns", - action=function(data) - data.properties.hasspacekerns=hasspacekerns(data) - end -} -local function spaceinitializer(tfmdata,value) - local resources=tfmdata.resources - local spacekerns=resources and resources.spacekerns - local properties=tfmdata.properties - if value and spacekerns==nil then - if properties and properties.hasspacekerns then - local sequences=resources.sequences - local left={} - local right={} - local last=0 - local feat=nil - for i=1,#sequences do - local sequence=sequences[i] - local steps=sequence.steps - if steps then - local kern=sequence.features.kern - if kern then - if feat then - for script,languages in next,kern do - local f=feat[script] - if f then - for l in next,languages do - f[l]=true - end - else - feat[script]=languages - end - end - else - feat=kern - end - for i=1,#steps do - local step=steps[i] - local coverage=step.coverage - local rules=step.rules - local format=step.format - if rules then - elseif coverage then - local single=format==gpos_single - local kerns=coverage[32] - if kerns then - for k,v in next,kerns do - if type(v)~="table" then - right[k]=v - elseif single then - right[k]=v[3] - else - local one=v[1] - if one then - right[k]=one[3] - end - end - end - end - for k,v in next,coverage do - local kern=v[32] - if kern then - if type(kern)~="table" then - left[k]=kern - elseif single then - left[k]=v[3] - else - local one=v[1] - if one then - left[k]=one[3] - end - end - end - end - end - end - last=i - end - else - end - end - left=next(left) and left or false - right=next(right) and right or false - if left or right then - spacekerns={ - left=left, - right=right, - } - if last>0 then - local triggersequence={ - features={ kern=feat or { dflt={ dflt=true,} } }, - flags=noflags, - name="trigger_space_kerns", - order={ "kern" }, - type="trigger_space_kerns", - left=left, - right=right, - } - insert(sequences,last,triggersequence) - end - else - spacekerns=false - end - else - spacekerns=false - end - resources.spacekerns=spacekerns - end - return spacekerns -end -registerotffeature { - name="spacekern", - description="space kern injection", - default=true, - initializers={ - node=spaceinitializer, - }, -} -local function markinitializer(tfmdata,value) - local properties=tfmdata.properties - properties.checkmarks=value -end -registerotffeature { - name="checkmarks", - description="check mark widths", - default=true, - initializers={ - node=markinitializer, - }, -} - -end --- [luaotfload, fontloader-2017-02-11.lua scope for “font-ots”] --- - - -do --- [luaotfload, fontloader-2017-02-11.lua scope for “font-osd” 10ecd4b375680b011e7c6a25e5ad74f7] --- - -if not modules then modules={} end modules ['font-osd']={ - version=1.001, - comment="companion to font-ini.mkiv", - author="Kai Eigner, TAT Zetwerk / Hans Hagen, PRAGMA ADE", - copyright="TAT Zetwerk / PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local insert,imerge,copy=table.insert,table.imerge,table.copy -local next,type=next,type -local report_devanagari=logs.reporter("otf","devanagari") -fonts=fonts or {} -fonts.analyzers=fonts.analyzers or {} -fonts.analyzers.methods=fonts.analyzers.methods or { node={ otf={} } } -local otf=fonts.handlers.otf -local handlers=otf.handlers -local methods=fonts.analyzers.methods -local otffeatures=fonts.constructors.features.otf -local registerotffeature=otffeatures.register -local nuts=nodes.nuts -local tonode=nuts.tonode -local tonut=nuts.tonut -local getnext=nuts.getnext -local getprev=nuts.getprev -local getboth=nuts.getboth -local getid=nuts.getid -local getchar=nuts.getchar -local getfont=nuts.getfont -local getsubtype=nuts.getsubtype -local setlink=nuts.setlink -local setnext=nuts.setnext -local setprev=nuts.setprev -local setchar=nuts.setchar -local getprop=nuts.getprop -local setprop=nuts.setprop -local ischar=nuts.is_char -local insert_node_after=nuts.insert_after -local copy_node=nuts.copy -local remove_node=nuts.remove -local flush_list=nuts.flush_list -local flush_node=nuts.flush_node -local copyinjection=nodes.injections.copy -local unsetvalue=attributes.unsetvalue -local fontdata=fonts.hashes.identifiers -local a_state=attributes.private('state') -local a_syllabe=attributes.private('syllabe') -local dotted_circle=0x25CC -local states=fonts.analyzers.states -local s_rphf=states.rphf -local s_half=states.half -local s_pref=states.pref -local s_blwf=states.blwf -local s_pstf=states.pstf -local replace_all_nbsp=nil -replace_all_nbsp=function(head) - replace_all_nbsp=typesetters and typesetters.characters and typesetters.characters.replacenbspaces or function(head) - return head - end - return replace_all_nbsp(head) -end -local xprocesscharacters=nil -if context then - xprocesscharacters=function(head,font) - xprocesscharacters=nodes.handlers.characters - return xprocesscharacters(head,font) - end -else - xprocesscharacters=function(head,font) - xprocesscharacters=nodes.handlers.nodepass - return xprocesscharacters(head,font) - end -end -local function processcharacters(head,font) - return tonut(xprocesscharacters(tonode(head))) -end -local consonant={ - [0x0915]=true,[0x0916]=true,[0x0917]=true,[0x0918]=true, - [0x0919]=true,[0x091A]=true,[0x091B]=true,[0x091C]=true, - [0x091D]=true,[0x091E]=true,[0x091F]=true,[0x0920]=true, - [0x0921]=true,[0x0922]=true,[0x0923]=true,[0x0924]=true, - [0x0925]=true,[0x0926]=true,[0x0927]=true,[0x0928]=true, - [0x0929]=true,[0x092A]=true,[0x092B]=true,[0x092C]=true, - [0x092D]=true,[0x092E]=true,[0x092F]=true,[0x0930]=true, - [0x0931]=true,[0x0932]=true,[0x0933]=true,[0x0934]=true, - [0x0935]=true,[0x0936]=true,[0x0937]=true,[0x0938]=true, - [0x0939]=true,[0x0958]=true,[0x0959]=true,[0x095A]=true, - [0x095B]=true,[0x095C]=true,[0x095D]=true,[0x095E]=true, - [0x095F]=true,[0x0979]=true,[0x097A]=true, - [0x0C95]=true,[0x0C96]=true,[0x0C97]=true,[0x0C98]=true, - [0x0C99]=true,[0x0C9A]=true,[0x0C9B]=true,[0x0C9C]=true, - [0x0C9D]=true,[0x0C9E]=true,[0x0C9F]=true,[0x0CA0]=true, - [0x0CA1]=true,[0x0CA2]=true,[0x0CA3]=true,[0x0CA4]=true, - [0x0CA5]=true,[0x0CA6]=true,[0x0CA7]=true,[0x0CA8]=true, - [0x0CA9]=true,[0x0CAA]=true,[0x0CAB]=true,[0x0CAC]=true, - [0x0CAD]=true,[0x0CAE]=true,[0x0CAF]=true,[0x0CB0]=true, - [0x0CB1]=true,[0x0CB2]=true,[0x0CB3]=true,[0x0CB4]=true, - [0x0CB5]=true,[0x0CB6]=true,[0x0CB7]=true,[0x0CB8]=true, - [0x0CB9]=true, - [0x0CDE]=true, - [0x0D15]=true,[0x0D16]=true,[0x0D17]=true,[0x0D18]=true, - [0x0D19]=true,[0x0D1A]=true,[0x0D1B]=true,[0x0D1C]=true, - [0x0D1D]=true,[0x0D1E]=true,[0x0D1F]=true,[0x0D20]=true, - [0x0D21]=true,[0x0D22]=true,[0x0D23]=true,[0x0D24]=true, - [0x0D25]=true,[0x0D26]=true,[0x0D27]=true,[0x0D28]=true, - [0x0D29]=true,[0x0D2A]=true,[0x0D2B]=true,[0x0D2C]=true, - [0x0D2D]=true,[0x0D2E]=true,[0x0D2F]=true,[0x0D30]=true, - [0x0D31]=true,[0x0D32]=true,[0x0D33]=true,[0x0D34]=true, - [0x0D35]=true,[0x0D36]=true,[0x0D37]=true,[0x0D38]=true, - [0x0D39]=true,[0x0D3A]=true, -} -local independent_vowel={ - [0x0904]=true,[0x0905]=true,[0x0906]=true,[0x0907]=true, - [0x0908]=true,[0x0909]=true,[0x090A]=true,[0x090B]=true, - [0x090C]=true,[0x090D]=true,[0x090E]=true,[0x090F]=true, - [0x0910]=true,[0x0911]=true,[0x0912]=true,[0x0913]=true, - [0x0914]=true,[0x0960]=true,[0x0961]=true,[0x0972]=true, - [0x0973]=true,[0x0974]=true,[0x0975]=true,[0x0976]=true, - [0x0977]=true, - [0x0C85]=true,[0x0C86]=true,[0x0C87]=true,[0x0C88]=true, - [0x0C89]=true,[0x0C8A]=true,[0x0C8B]=true,[0x0C8C]=true, - [0x0C8D]=true,[0x0C8E]=true,[0x0C8F]=true,[0x0C90]=true, - [0x0C91]=true,[0x0C92]=true,[0x0C93]=true,[0x0C94]=true, - [0x0D05]=true,[0x0D06]=true,[0x0D07]=true,[0x0D08]=true, - [0x0D09]=true,[0x0D0A]=true,[0x0D0B]=true,[0x0D0C]=true, - [0x0D0E]=true,[0x0D0F]=true,[0x0D10]=true,[0x0D12]=true, - [0x0D13]=true,[0x0D14]=true, -} -local dependent_vowel={ - [0x093A]=true,[0x093B]=true,[0x093E]=true,[0x093F]=true, - [0x0940]=true,[0x0941]=true,[0x0942]=true,[0x0943]=true, - [0x0944]=true,[0x0945]=true,[0x0946]=true,[0x0947]=true, - [0x0948]=true,[0x0949]=true,[0x094A]=true,[0x094B]=true, - [0x094C]=true,[0x094E]=true,[0x094F]=true,[0x0955]=true, - [0x0956]=true,[0x0957]=true,[0x0962]=true,[0x0963]=true, - [0x0CBE]=true,[0x0CBF]=true,[0x0CC0]=true,[0x0CC1]=true, - [0x0CC2]=true,[0x0CC3]=true,[0x0CC4]=true,[0x0CC5]=true, - [0x0CC6]=true,[0x0CC7]=true,[0x0CC8]=true,[0x0CC9]=true, - [0x0CCA]=true,[0x0CCB]=true,[0x0CCC]=true, - [0x0D3E]=true,[0x0D3F]=true,[0x0D40]=true,[0x0D41]=true, - [0x0D42]=true,[0x0D43]=true,[0x0D44]=true,[0x0D46]=true, - [0x0D47]=true,[0x0D48]=true,[0x0D4A]=true,[0x0D4B]=true, - [0x0D4C]=true,[0x0D57]=true, -} -local vowel_modifier={ - [0x0900]=true,[0x0901]=true,[0x0902]=true,[0x0903]=true, - [0xA8E0]=true,[0xA8E1]=true,[0xA8E2]=true,[0xA8E3]=true, - [0xA8E4]=true,[0xA8E5]=true,[0xA8E6]=true,[0xA8E7]=true, - [0xA8E8]=true,[0xA8E9]=true,[0xA8EA]=true,[0xA8EB]=true, - [0xA8EC]=true,[0xA8ED]=true,[0xA8EE]=true,[0xA8EF]=true, - [0xA8F0]=true,[0xA8F1]=true, - [0x0D02]=true,[0x0D03]=true, -} -local stress_tone_mark={ - [0x0951]=true,[0x0952]=true,[0x0953]=true,[0x0954]=true, - [0x0CCD]=true, - [0x0D4D]=true, -} -local nukta={ - [0x093C]=true, - [0x0CBC]=true, -} -local halant={ - [0x094D]=true, - [0x0CCD]=true, - [0x0D4D]=true, -} -local ra={ - [0x0930]=true, - [0x0CB0]=true, - [0x0D30]=true, -} -local c_anudatta=0x0952 -local c_nbsp=0x00A0 -local c_zwnj=0x200C -local c_zwj=0x200D -local zw_char={ - [0x200C]=true, - [0x200D]=true, -} -local pre_mark={ - [0x093F]=true,[0x094E]=true, - [0x0D46]=true,[0x0D47]=true,[0x0D48]=true, -} -local above_mark={ - [0x0900]=true,[0x0901]=true,[0x0902]=true,[0x093A]=true, - [0x0945]=true,[0x0946]=true,[0x0947]=true,[0x0948]=true, - [0x0951]=true,[0x0953]=true,[0x0954]=true,[0x0955]=true, - [0xA8E0]=true,[0xA8E1]=true,[0xA8E2]=true,[0xA8E3]=true, - [0xA8E4]=true,[0xA8E5]=true,[0xA8E6]=true,[0xA8E7]=true, - [0xA8E8]=true,[0xA8E9]=true,[0xA8EA]=true,[0xA8EB]=true, - [0xA8EC]=true,[0xA8ED]=true,[0xA8EE]=true,[0xA8EF]=true, - [0xA8F0]=true,[0xA8F1]=true, - [0x0D4E]=true, -} -local below_mark={ - [0x093C]=true,[0x0941]=true,[0x0942]=true,[0x0943]=true, - [0x0944]=true,[0x094D]=true,[0x0952]=true,[0x0956]=true, - [0x0957]=true,[0x0962]=true,[0x0963]=true, -} -local post_mark={ - [0x0903]=true,[0x093B]=true,[0x093E]=true,[0x0940]=true, - [0x0949]=true,[0x094A]=true,[0x094B]=true,[0x094C]=true, - [0x094F]=true, -} -local twopart_mark={ - [0x0D4A]={ 0x0D46,0x0D3E,}, - [0x0D4B]={ 0x0D47,0x0D3E,}, - [0x0D4C]={ 0x0D46,0x0D57,}, -} -local mark_four={} -for k,v in next,pre_mark do mark_four[k]=pre_mark end -for k,v in next,above_mark do mark_four[k]=above_mark end -for k,v in next,below_mark do mark_four[k]=below_mark end -for k,v in next,post_mark do mark_four[k]=post_mark end -local mark_above_below_post={} -for k,v in next,above_mark do mark_above_below_post[k]=above_mark end -for k,v in next,below_mark do mark_above_below_post[k]=below_mark end -for k,v in next,post_mark do mark_above_below_post[k]=post_mark end -local reorder_class={ - [0x0930]="before postscript", - [0x093F]="before half", - [0x0940]="after subscript", - [0x0941]="after subscript", - [0x0942]="after subscript", - [0x0943]="after subscript", - [0x0944]="after subscript", - [0x0945]="after subscript", - [0x0946]="after subscript", - [0x0947]="after subscript", - [0x0948]="after subscript", - [0x0949]="after subscript", - [0x094A]="after subscript", - [0x094B]="after subscript", - [0x094C]="after subscript", - [0x0962]="after subscript", - [0x0963]="after subscript", - [0x093E]="after subscript", - [0x0CB0]="after postscript", - [0x0CBF]="before subscript", - [0x0CC6]="before subscript", - [0x0CCC]="before subscript", - [0x0CBE]="before subscript", - [0x0CE2]="before subscript", - [0x0CE3]="before subscript", - [0x0CC1]="before subscript", - [0x0CC2]="before subscript", - [0x0CC3]="after subscript", - [0x0CC4]="after subscript", - [0x0CD5]="after subscript", - [0x0CD6]="after subscript", -} -local dflt_true={ - dflt=true -} -local dev2_defaults={ - dev2=dflt_true, -} -local deva_defaults={ - dev2=dflt_true, - deva=dflt_true, -} -local false_flags={ false,false,false,false } -local both_joiners_true={ - [0x200C]=true, - [0x200D]=true, -} -local sequence_reorder_matras={ - features={ dv01=dev2_defaults }, - flags=false_flags, - name="dv01_reorder_matras", - order={ "dv01" }, - type="devanagari_reorder_matras", - nofsteps=1, - steps={ - { - osdstep=true, - coverage=pre_mark, - } - } -} -local sequence_reorder_reph={ - features={ dv02=dev2_defaults }, - flags=false_flags, - name="dv02_reorder_reph", - order={ "dv02" }, - type="devanagari_reorder_reph", - nofsteps=1, - steps={ - { - osdstep=true, - coverage={}, - } - } -} -local sequence_reorder_pre_base_reordering_consonants={ - features={ dv03=dev2_defaults }, - flags=false_flags, - name="dv03_reorder_pre_base_reordering_consonants", - order={ "dv03" }, - type="devanagari_reorder_pre_base_reordering_consonants", - nofsteps=1, - steps={ - { - osdstep=true, - coverage={}, - } - } -} -local sequence_remove_joiners={ - features={ dv04=deva_defaults }, - flags=false_flags, - name="dv04_remove_joiners", - order={ "dv04" }, - type="devanagari_remove_joiners", - nofsteps=1, - steps={ - { osdstep=true, - coverage=both_joiners_true, - }, - } -} -local basic_shaping_forms={ - nukt=true, - akhn=true, - rphf=true, - pref=true, - rkrf=true, - blwf=true, - half=true, - pstf=true, - vatu=true, - cjct=true, -} -local valid={ - akhn=true, - rphf=true, - pref=true, - half=true, - blwf=true, - pstf=true, - pres=true, - blws=true, - psts=true, -} -local function initializedevanagi(tfmdata) - local script,language=otf.scriptandlanguage(tfmdata,attr) - if script=="deva" or script=="dev2" or script=="mlym" or script=="mlm2" then - local resources=tfmdata.resources - local devanagari=resources.devanagari - if not devanagari then - report_devanagari("adding devanagari features to font") - local gsubfeatures=resources.features.gsub - local sequences=resources.sequences - local sharedfeatures=tfmdata.shared.features - local lastmatch=0 - for s=1,#sequences do - local features=sequences[s].features - if features then - for k,v in next,features do - if basic_shaping_forms[k] then - lastmatch=s - end - end - end - end - local insertindex=lastmatch+1 - gsubfeatures["dv01"]=dev2_defaults - gsubfeatures["dv02"]=dev2_defaults - gsubfeatures["dv03"]=dev2_defaults - gsubfeatures["dv04"]=deva_defaults - local reorder_pre_base_reordering_consonants=copy(sequence_reorder_pre_base_reordering_consonants) - local reorder_reph=copy(sequence_reorder_reph) - local reorder_matras=copy(sequence_reorder_matras) - local remove_joiners=copy(sequence_remove_joiners) - insert(sequences,insertindex,reorder_pre_base_reordering_consonants) - insert(sequences,insertindex,reorder_reph) - insert(sequences,insertindex,reorder_matras) - insert(sequences,insertindex,remove_joiners) - local blwfcache={} - local seqsubset={} - local rephstep={ - coverage={} - } - local devanagari={ - reph=false, - vattu=false, - blwfcache=blwfcache, - seqsubset=seqsubset, - reorderreph=rephstep, - } - reorder_reph.steps={ rephstep } - local pre_base_reordering_consonants={} - reorder_pre_base_reordering_consonants.steps[1].coverage=pre_base_reordering_consonants - resources.devanagari=devanagari - for s=1,#sequences do - local sequence=sequences[s] - local steps=sequence.steps - local nofsteps=sequence.nofsteps - local features=sequence.features - local has_rphf=features.rphf - local has_blwf=features.blwf - if has_rphf and has_rphf.deva then - devanagari.reph=true - elseif has_blwf and has_blwf.deva then - devanagari.vattu=true - for i=1,nofsteps do - local step=steps[i] - local coverage=step.coverage - if coverage then - for k,v in next,coverage do - if not blwfcache[k] then - blwfcache[k]=v - end - end - end - end - end - for kind,spec in next,features do - if spec.dev2 and valid[kind] then - for i=1,nofsteps do - local step=steps[i] - local coverage=step.coverage - if coverage then - local reph=false - if kind=="rphf" then - if true then - for k,v in next,ra do - local r=coverage[k] - if r then - local h=false - for k,v in next,halant do - local h=r[k] - if h then - reph=h.ligature or false - break - end - end - if reph then - break - end - end - end - else - end - end - seqsubset[#seqsubset+1]={ kind,coverage,reph } - end - end - end - if kind=="pref" then - local steps=sequence.steps - local nofsteps=sequence.nofsteps - for i=1,nofsteps do - local step=steps[i] - local coverage=step.coverage - if coverage then - for k,v in next,halant do - local h=coverage[k] - if h then - local found=false - for k,v in next,h do - found=v and v.ligature - if found then - pre_base_reordering_consonants[k]=found - break - end - end - if found then - break - end - end - end - end - end - end - end - end - if script=="deva" then - sharedfeatures["dv04"]=true - elseif script=="dev2" then - sharedfeatures["dv01"]=true - sharedfeatures["dv02"]=true - sharedfeatures["dv03"]=true - sharedfeatures["dv04"]=true - elseif script=="mlym" then - sharedfeatures["pstf"]=true - elseif script=="mlm2" then - sharedfeatures["pstf"]=true - sharedfeatures["pref"]=true - sharedfeatures["dv03"]=true - gsubfeatures ["dv03"]=dev2_defaults - insert(sequences,insertindex,sequence_reorder_pre_base_reordering_consonants) - end - end - end -end -registerotffeature { - name="devanagari", - description="inject additional features", - default=true, - initializers={ - node=initializedevanagi, - }, -} -local function deva_initialize(font,attr) - local tfmdata=fontdata[font] - local datasets=otf.dataset(tfmdata,font,attr) - local devanagaridata=datasets.devanagari - if not devanagaridata then - devanagaridata={ - reph=false, - vattu=false, - blwfcache={}, - } - datasets.devanagari=devanagaridata - local resources=tfmdata.resources - local devanagari=resources.devanagari - for s=1,#datasets do - local dataset=datasets[s] - if dataset and dataset[1] then - local kind=dataset[4] - if kind=="rphf" then - devanagaridata.reph=true - elseif kind=="blwf" then - devanagaridata.vattu=true - devanagaridata.blwfcache=devanagari.blwfcache - end - end - end - end - return devanagaridata.reph,devanagaridata.vattu,devanagaridata.blwfcache -end -local function deva_reorder(head,start,stop,font,attr,nbspaces) - local reph,vattu,blwfcache=deva_initialize(font,attr) - local current=start - local n=getnext(start) - local base=nil - local firstcons=nil - local lastcons=nil - local basefound=false - if reph and ra[getchar(start)] and halant[getchar(n)] then - if n==stop then - return head,stop,nbspaces - end - if getchar(getnext(n))==c_zwj then - current=start - else - current=getnext(n) - setprop(start,a_state,s_rphf) - end - end - if getchar(current)==c_nbsp then - if current==stop then - stop=getprev(stop) - head=remove_node(head,current) - flush_node(current) - return head,stop,nbspaces - else - nbspaces=nbspaces+1 - base=current - firstcons=current - lastcons=current - current=getnext(current) - if current~=stop then - if nukta[getchar(current)] then - current=getnext(current) - end - if getchar(current)==c_zwj then - if current~=stop then - local next=getnext(current) - if next~=stop and halant[getchar(next)] then - current=next - next=getnext(current) - local tmp=next and getnext(next) or nil - local changestop=next==stop - local tempcurrent=copy_node(next) - copyinjection(tempcurrent,next) - local nextcurrent=copy_node(current) - copyinjection(nextcurrent,current) - setlink(tempcurrent,nextcurrent) - setprop(tempcurrent,a_state,s_blwf) - tempcurrent=processcharacters(tempcurrent,font) - setprop(tempcurrent,a_state,unsetvalue) - if getchar(next)==getchar(tempcurrent) then - flush_list(tempcurrent) - local n=copy_node(current) - copyinjection(n,current) - setchar(current,dotted_circle) - head=insert_node_after(head,current,n) - else - setchar(current,getchar(tempcurrent)) - local freenode=getnext(current) - setlink(current,tmp) - flush_node(freenode) - flush_list(tempcurrent) - if changestop then - stop=current - end - end - end - end - end - end - end - end - while not basefound do - local char=getchar(current) - if consonant[char] then - setprop(current,a_state,s_half) - if not firstcons then - firstcons=current - end - lastcons=current - if not base then - base=current - elseif blwfcache[char] then - setprop(current,a_state,s_blwf) - else - base=current - end - end - basefound=current==stop - current=getnext(current) - end - if base~=lastcons then - local np=base - local n=getnext(base) - local ch=getchar(n) - if nukta[ch] then - np=n - n=getnext(n) - ch=getchar(n) - end - if halant[ch] then - if lastcons~=stop then - local ln=getnext(lastcons) - if nukta[getchar(ln)] then - lastcons=ln - end - end - local nn=getnext(n) - local ln=getnext(lastcons) - setlink(np,nn) - setnext(lastcons,n) - if ln then - setprev(ln,n) - end - setnext(n,ln) - setprev(n,lastcons) - if lastcons==stop then - stop=n - end - end - end - n=getnext(start) - if n~=stop and ra[getchar(start)] and halant[getchar(n)] and not zw_char[getchar(getnext(n))] then - local matra=base - if base~=stop then - local next=getnext(base) - if dependent_vowel[getchar(next)] then - matra=next - end - end - local sp=getprev(start) - local nn=getnext(n) - local mn=getnext(matra) - setlink(sp,nn) - setlink(matra,start) - setlink(n,mn) - if head==start then - head=nn - end - start=nn - if matra==stop then - stop=n - end - end - local current=start - while current~=stop do - local next=getnext(current) - if next~=stop and halant[getchar(next)] and getchar(getnext(next))==c_zwnj then - setprop(current,a_state,unsetvalue) - end - current=next - end - if base~=stop and getprop(base,a_state) then - local next=getnext(base) - if halant[getchar(next)] and not (next~=stop and getchar(getnext(next))==c_zwj) then - setprop(base,a_state,unsetvalue) - end - end - local current,allreordered,moved=start,false,{ [base]=true } - local a,b,p,bn=base,base,base,getnext(base) - if base~=stop and nukta[getchar(bn)] then - a,b,p=bn,bn,bn - end - while not allreordered do - local c=current - local n=getnext(current) - local l=nil - if c~=stop then - local ch=getchar(n) - if nukta[ch] then - c=n - n=getnext(n) - ch=getchar(n) - end - if c~=stop then - if halant[ch] then - c=n - n=getnext(n) - ch=getchar(n) - end - while c~=stop and dependent_vowel[ch] do - c=n - n=getnext(n) - ch=getchar(n) - end - if c~=stop then - if vowel_modifier[ch] then - c=n - n=getnext(n) - ch=getchar(n) - end - if c~=stop and stress_tone_mark[ch] then - c=n - n=getnext(n) - end - end - end - end - local bp=getprev(firstcons) - local cn=getnext(current) - local last=getnext(c) - while cn~=last do - if pre_mark[getchar(cn)] then - if bp then - setnext(bp,cn) - end - local prev,next=getboth(cn) - if next then - setprev(next,prev) - end - setnext(prev,next) - if cn==stop then - stop=prev - end - setprev(cn,bp) - setlink(cn,firstcons) - if firstcons==start then - if head==start then - head=cn - end - start=cn - end - break - end - cn=getnext(cn) - end - allreordered=c==stop - current=getnext(c) - end - if reph or vattu then - local current,cns=start,nil - while current~=stop do - local c=current - local n=getnext(current) - if ra[getchar(current)] and halant[getchar(n)] then - c=n - n=getnext(n) - local b,bn=base,base - while bn~=stop do - local next=getnext(bn) - if dependent_vowel[getchar(next)] then - b=next - end - bn=next - end - if getprop(current,a_state)==s_rphf then - if b~=current then - if current==start then - if head==start then - head=n - end - start=n - end - if b==stop then - stop=c - end - local prev=getprev(current) - setlink(prev,n) - local next=getnext(b) - setlink(c,next) - setlink(b,current) - end - elseif cns and getnext(cns)~=current then - local cp=getprev(current) - local cnsn=getnext(cns) - setlink(cp,n) - setlink(cns,current) - setlink(c,cnsn) - if c==stop then - stop=cp - break - end - current=getprev(n) - end - else - local char=getchar(current) - if consonant[char] then - cns=current - local next=getnext(cns) - if halant[getchar(next)] then - cns=next - end - elseif char==c_nbsp then - nbspaces=nbspaces+1 - cns=current - local next=getnext(cns) - if halant[getchar(next)] then - cns=next - end - end - end - current=getnext(current) - end - end - if getchar(base)==c_nbsp then - nbspaces=nbspaces-1 - head=remove_node(head,base) - flush_node(base) - end - return head,stop,nbspaces -end -function handlers.devanagari_reorder_matras(head,start) - local current=start - local startfont=getfont(start) - local startattr=getprop(start,a_syllabe) - while current do - local char=ischar(current,startfont) - local next=getnext(current) - if char and getprop(current,a_syllabe)==startattr then - if halant[char] and not getprop(current,a_state) then - if next then - local char=ischar(next,startfont) - if char and zw_char[char] and getprop(next,a_syllabe)==startattr then - current=next - next=getnext(current) - end - end - local startnext=getnext(start) - head=remove_node(head,start) - setlink(start,next) - setlink(current,start) - start=startnext - break - end - else - break - end - current=next - end - return head,start,true -end -function handlers.devanagari_reorder_reph(head,start) - local current=getnext(start) - local startnext=nil - local startprev=nil - local startfont=getfont(start) - local startattr=getprop(start,a_syllabe) - while current do - local char=ischar(current,startfont) - if char and getprop(current,a_syllabe)==startattr then - if halant[char] and not getprop(current,a_state) then - local next=getnext(current) - if next then - local nextchar=ischar(next,startfont) - if nextchar and zw_char[nextchar] and getprop(next,a_syllabe)==startattr then - current=next - next=getnext(current) - end - end - startnext=getnext(start) - head=remove_node(head,start) - setlink(start,next) - setlink(current,start) - start=startnext - startattr=getprop(start,a_syllabe) - break - end - current=getnext(current) - else - break - end - end - if not startnext then - current=getnext(start) - while current do - local char=ischar(current,startfont) - if char and getprop(current,a_syllabe)==startattr then - if getprop(current,a_state)==s_pstf then - startnext=getnext(start) - head=remove_node(head,start) - local prev=getprev(current) - setlink(prev,start) - setlink(start,current) - start=startnext - startattr=getprop(start,a_syllabe) - break - end - current=getnext(current) - else - break - end - end - end - if not startnext then - current=getnext(start) - local c=nil - while current do - local char=ischar(current,startfont) - if char and getprop(current,a_syllabe)==startattr then - if not c and mark_above_below_post[char] and reorder_class[char]~="after subscript" then - c=current - end - current=getnext(current) - else - break - end - end - if c then - startnext=getnext(start) - head=remove_node(head,start) - local prev=getprev(c) - setlink(prev,start) - setlink(start,c) - start=startnext - startattr=getprop(start,a_syllabe) - end - end - if not startnext then - current=start - local next=getnext(current) - while next do - local nextchar=ischar(next,startfont) - if nextchar and getprop(next,a_syllabe)==startattr then - current=next - next=getnext(current) - else - break - end - end - if start~=current then - startnext=getnext(start) - head=remove_node(head,start) - local next=getnext(current) - setlink(start,next) - setlink(current,start) - start=startnext - end - end - return head,start,true -end -function handlers.devanagari_reorder_pre_base_reordering_consonants(head,start) - local current=start - local startnext=nil - local startprev=nil - local startfont=getfont(start) - local startattr=getprop(start,a_syllabe) - while current do - local char=ischar(current,startfont) - if char and getprop(current,a_syllabe)==startattr then - local next=getnext(current) - if halant[char] and not getprop(current,a_state) then - if next then - local nextchar=ischar(next,startfont) - if nextchar and getprop(next,a_syllabe)==startattr then - if nextchar==c_zwnj or nextchar==c_zwj then - current=next - next=getnext(current) - end - end - end - startnext=getnext(start) - removenode(start,start) - setlink(start,next) - setlink(current,start) - start=startnext - break - end - current=next - else - break - end - end - if not startnext then - current=getnext(start) - startattr=getprop(start,a_syllabe) - while current do - local char=ischar(current,startfont) - if char and getprop(current,a_syllabe)==startattr then - if not consonant[char] and getprop(current,a_state) then - startnext=getnext(start) - removenode(start,start) - local prev=getprev(current) - setlink(prev,start) - setlink(start,current) - start=startnext - break - end - current=getnext(current) - else - break - end - end - end - return head,start,true -end -function handlers.devanagari_remove_joiners(head,start,kind,lookupname,replacement) - local stop=getnext(start) - local font=getfont(start) - local last=start - while stop do - local char=ischar(stop,font) - if char and (char==c_zwnj or char==c_zwj) then - last=stop - stop=getnext(stop) - else - break - end - end - local prev=getprev(start) - if stop then - setnext(last) - setlink(prev,stop) - elseif prev then - setnext(prev) - end - if head==start then - head=stop - end - flush_list(start) - return head,stop,true -end -local function dev2_initialize(font,attr) - local devanagari=fontdata[font].resources.devanagari - if devanagari then - return devanagari.seqsubset or {},devanagari.reorderreph or {} - else - return {},{} - end -end -local function dev2_reorder(head,start,stop,font,attr,nbspaces) - local seqsubset,reorderreph=dev2_initialize(font,attr) - local reph=false - local halfpos=nil - local basepos=nil - local subpos=nil - local postpos=nil - local locl={} - for i=1,#seqsubset do - local subset=seqsubset[i] - local kind=subset[1] - local lookupcache=subset[2] - if kind=="rphf" then - reph=subset[3] - local current=start - local last=getnext(stop) - while current~=last do - if current~=stop then - local c=locl[current] or getchar(current) - local found=lookupcache[c] - if found then - local next=getnext(current) - local n=locl[next] or getchar(next) - if found[n] then - local afternext=next~=stop and getnext(next) - if afternext and zw_char[getchar(afternext)] then - current=next - current=getnext(current) - elseif current==start then - setprop(current,a_state,s_rphf) - current=next - else - current=next - end - end - end - end - current=getnext(current) - end - elseif kind=="pref" then - local current=start - local last=getnext(stop) - while current~=last do - if current~=stop then - local c=locl[current] or getchar(current) - local found=lookupcache[c] - if found then - local next=getnext(current) - local n=locl[next] or getchar(next) - if found[n] then - setprop(current,a_state,s_pref) - setprop(next,a_state,s_pref) - current=next - end - end - end - current=getnext(current) - end - elseif kind=="half" then - local current=start - local last=getnext(stop) - while current~=last do - if current~=stop then - local c=locl[current] or getchar(current) - local found=lookupcache[c] - if found then - local next=getnext(current) - local n=locl[next] or getchar(next) - if found[n] then - if next~=stop and getchar(getnext(next))==c_zwnj then - current=next - else - setprop(current,a_state,s_half) - if not halfpos then - halfpos=current - end - end - current=getnext(current) - end - end - end - current=getnext(current) - end - elseif kind=="blwf" then - local current=start - local last=getnext(stop) - while current~=last do - if current~=stop then - local c=locl[current] or getchar(current) - local found=lookupcache[c] - if found then - local next=getnext(current) - local n=locl[next] or getchar(next) - if found[n] then - setprop(current,a_state,s_blwf) - setprop(next,a_state,s_blwf) - current=next - subpos=current - end - end - end - current=getnext(current) - end - elseif kind=="pstf" then - local current=start - local last=getnext(stop) - while current~=last do - if current~=stop then - local c=locl[current] or getchar(current) - local found=lookupcache[c] - if found then - local next=getnext(current) - local n=locl[next] or getchar(next) - if found[n] then - setprop(current,a_state,s_pstf) - setprop(next,a_state,s_pstf) - current=next - postpos=current - end - end - end - current=getnext(current) - end - end - end - reorderreph.coverage={ [reph]=true } - local current,base,firstcons=start,nil,nil - if getprop(start,a_state)==s_rphf then - current=getnext(getnext(start)) - end - if current~=getnext(stop) and getchar(current)==c_nbsp then - if current==stop then - stop=getprev(stop) - head=remove_node(head,current) - flush_node(current) - return head,stop,nbspaces - else - nbspaces=nbspaces+1 - base=current - current=getnext(current) - if current~=stop then - local char=getchar(current) - if nukta[char] then - current=getnext(current) - char=getchar(current) - end - if char==c_zwj then - local next=getnext(current) - if current~=stop and next~=stop and halant[getchar(next)] then - current=next - next=getnext(current) - local tmp=getnext(next) - local changestop=next==stop - setnext(next,nil) - setprop(current,a_state,s_pref) - current=processcharacters(current,font) - setprop(current,a_state,s_blwf) - current=processcharacters(current,font) - setprop(current,a_state,s_pstf) - current=processcharacters(current,font) - setprop(current,a_state,unsetvalue) - if halant[getchar(current)] then - setnext(getnext(current),tmp) - local nc=copy_node(current) - copyinjection(nc,current) - setchar(current,dotted_circle) - head=insert_node_after(head,current,nc) - else - setnext(current,tmp) - if changestop then - stop=current - end - end - end - end - end - end - else - local last=getnext(stop) - while current~=last do - local next=getnext(current) - if consonant[getchar(current)] then - if not (current~=stop and next~=stop and halant[getchar(next)] and getchar(getnext(next))==c_zwj) then - if not firstcons then - firstcons=current - end - local a=getprop(current,a_state) - if not (a==s_pref or a==s_blwf or a==s_pstf) then - base=current - end - end - end - current=next - end - if not base then - base=firstcons - end - end - if not base then - if getprop(start,a_state)==s_rphf then - setprop(start,a_state,unsetvalue) - end - return head,stop,nbspaces - else - if getprop(base,a_state) then - setprop(base,a_state,unsetvalue) - end - basepos=base - end - if not halfpos then - halfpos=base - end - if not subpos then - subpos=base - end - if not postpos then - postpos=subpos or base - end - local moved={} - local current=start - local last=getnext(stop) - while current~=last do - local char,target,cn=locl[current] or getchar(current),nil,getnext(current) - local tpm=twopart_mark[char] - if tpm then - local extra=copy_node(current) - copyinjection(extra,current) - char=tpm[1] - setchar(current,char) - setchar(extra,tpm[2]) - head=insert_node_after(head,current,extra) - end - if not moved[current] and dependent_vowel[char] then - if pre_mark[char] then - moved[current]=true - local prev,next=getboth(current) - setlink(prev,next) - if current==stop then - stop=getprev(current) - end - if halfpos==start then - if head==start then - head=current - end - start=current - end - local prev=getprev(halfpos) - setlink(prev,current) - setlink(current,halfpos) - halfpos=current - elseif above_mark[char] then - target=basepos - if subpos==basepos then - subpos=current - end - if postpos==basepos then - postpos=current - end - basepos=current - elseif below_mark[char] then - target=subpos - if postpos==subpos then - postpos=current - end - subpos=current - elseif post_mark[char] then - target=postpos - postpos=current - end - if mark_above_below_post[char] then - local prev=getprev(current) - if prev~=target then - local next=getnext(current) - setlink(prev,next) - if current==stop then - stop=prev - end - local next=getnext(target) - setlink(current,next) - setlink(target,current) - end - end - end - current=cn - end - local current,c=start,nil - while current~=stop do - local char=getchar(current) - if halant[char] or stress_tone_mark[char] then - if not c then - c=current - end - else - c=nil - end - local next=getnext(current) - if c and nukta[getchar(next)] then - if head==c then - head=next - end - if stop==next then - stop=current - end - local prev=getprev(c) - setlink(prev,next) - local nextnext=getnext(next) - setnext(current,nextnext) - local nextnextnext=getnext(nextnext) - if nextnextnext then - setprev(nextnextnext,current) - end - setlink(nextnext,c) - end - if stop==current then break end - current=getnext(current) - end - if getchar(base)==c_nbsp then - if base==stop then - stop=getprev(stop) - end - nbspaces=nbspaces-1 - head=remove_node(head,base) - flush_node(base) - end - return head,stop,nbspaces -end -local separator={} -imerge(separator,consonant) -imerge(separator,independent_vowel) -imerge(separator,dependent_vowel) -imerge(separator,vowel_modifier) -imerge(separator,stress_tone_mark) -for k,v in next,nukta do separator[k]=true end -for k,v in next,halant do separator[k]=true end -local function analyze_next_chars_one(c,font,variant) - local n=getnext(c) - if not n then - return c - end - if variant==1 then - local v=ischar(n,font) - if v and nukta[v] then - n=getnext(n) - if n then - v=ischar(n,font) - end - end - if n and v then - local nn=getnext(n) - if nn then - local vv=ischar(nn,font) - if vv then - local nnn=getnext(nn) - if nnn then - local vvv=ischar(nnn,font) - if vvv then - if vv==c_zwj and consonant[vvv] then - c=nnn - elseif (vv==c_zwnj or vv==c_zwj) and halant[vvv] then - local nnnn=getnext(nnn) - if nnnn then - local vvvv=ischar(nnnn,font) - if vvvv and consonant[vvvv] then - c=nnnn - end - end - end - end - end - end - end - end - elseif variant==2 then - local v=ischar(n,font) - if v and nukta[v] then - c=n - end - n=getnext(c) - if n then - v=ischar(n,font) - if v then - local nn=getnext(n) - if nn then - local vv=ischar(nn,font) - if vv and zw_char[v] then - n=nn - v=vv - nn=getnext(nn) - vv=nn and ischar(nn,font) - end - if vv and halant[v] and consonant[vv] then - c=nn - end - end - end - end - end - local n=getnext(c) - if not n then - return c - end - local v=ischar(n,font) - if not v then - return c - end - if dependent_vowel[v] then - c=getnext(c) - n=getnext(c) - if not n then - return c - end - v=ischar(n,font) - if not v then - return c - end - end - if nukta[v] then - c=getnext(c) - n=getnext(c) - if not n then - return c - end - v=ischar(n,font) - if not v then - return c - end - end - if halant[v] then - c=getnext(c) - n=getnext(c) - if not n then - return c - end - v=ischar(n,font) - if not v then - return c - end - end - if vowel_modifier[v] then - c=getnext(c) - n=getnext(c) - if not n then - return c - end - v=ischar(n,font) - if not v then - return c - end - end - if stress_tone_mark[v] then - c=getnext(c) - n=getnext(c) - if not n then - return c - end - v=ischar(n,font) - if not v then - return c - end - end - if stress_tone_mark[v] then - return n - else - return c - end -end -local function analyze_next_chars_two(c,font) - local n=getnext(c) - if not n then - return c - end - local v=ischar(n,font) - if v and nukta[v] then - c=n - end - n=c - while true do - local nn=getnext(n) - if nn then - local vv=ischar(nn,font) - if vv then - if halant[vv] then - n=nn - local nnn=getnext(nn) - if nnn then - local vvv=ischar(nnn,font) - if vvv and zw_char[vvv] then - n=nnn - end - end - elseif vv==c_zwnj or vv==c_zwj then - local nnn=getnext(nn) - if nnn then - local vvv=ischar(nnn,font) - if vvv and halant[vvv] then - n=nnn - end - end - else - break - end - local nn=getnext(n) - if nn then - local vv=ischar(nn,font) - if vv and consonant[vv] then - n=nn - local nnn=getnext(nn) - if nnn then - local vvv=ischar(nnn,font) - if vvv and nukta[vvv] then - n=nnn - end - end - c=n - else - break - end - else - break - end - else - break - end - else - break - end - end - if not c then - return - end - local n=getnext(c) - if not n then - return c - end - local v=ischar(n,font) - if not v then - return c - end - if v==c_anudatta then - c=n - n=getnext(c) - if not n then - return c - end - v=ischar(n,font) - if not v then - return c - end - end - if halant[v] then - c=n - n=getnext(c) - if not n then - return c - end - v=ischar(n,font) - if not v then - return c - end - if v==c_zwnj or v==c_zwj then - c=n - n=getnext(c) - if not n then - return c - end - v=ischar(n,font) - if not v then - return c - end - end - else - if dependent_vowel[v] then - c=n - n=getnext(c) - if not n then - return c - end - v=ischar(n,font) - if not v then - return c - end - end - if nukta[v] then - c=n - n=getnext(c) - if not n then - return c - end - v=ischar(n,font) - if not v then - return c - end - end - if halant[v] then - c=n - n=getnext(c) - if not n then - return c - end - v=ischar(n,font) - if not v then - return c - end - end - end - if vowel_modifier[v] then - c=n - n=getnext(c) - if not n then - return c - end - v=ischar(n,font) - if not v then - return c - end - end - if stress_tone_mark[v] then - c=n - n=getnext(c) - if not n then - return c - end - v=ischar(n,font) - if not v then - return c - end - end - if stress_tone_mark[v] then - return n - else - return c - end -end -local function inject_syntax_error(head,current,mark) - local signal=copy_node(current) - copyinjection(signal,current) - if mark==pre_mark then - setchar(signal,dotted_circle) - else - setchar(current,dotted_circle) - end - return insert_node_after(head,current,signal) -end -function methods.deva(head,font,attr) - head=tonut(head) - local current=head - local start=true - local done=false - local nbspaces=0 - while current do - local char=ischar(current,font) - if char then - done=true - local syllablestart=current - local syllableend=nil - local c=current - local n=getnext(c) - local first=char - if n and ra[first] then - local second=ischar(n,font) - if second and halant[second] then - local n=getnext(n) - if n then - local third=ischar(n,font) - if third then - c=n - first=third - end - end - end - end - local standalone=first==c_nbsp - if standalone then - local prev=getprev(current) - if prev then - local prevchar=ischar(prev,font) - if not prevchar then - elseif not separator[prevchar] then - else - standalone=false - end - else - end - end - if standalone then - local syllableend=analyze_next_chars_one(c,font,2) - current=getnext(syllableend) - if syllablestart~=syllableend then - head,current,nbspaces=deva_reorder(head,syllablestart,syllableend,font,attr,nbspaces) - current=getnext(current) - end - else - if consonant[char] then - local prevc=true - while prevc do - prevc=false - local n=getnext(current) - if not n then - break - end - local v=ischar(n,font) - if not v then - break - end - if nukta[v] then - n=getnext(n) - if not n then - break - end - v=ischar(n,font) - if not v then - break - end - end - if halant[v] then - n=getnext(n) - if not n then - break - end - v=ischar(n,font) - if not v then - break - end - if v==c_zwnj or v==c_zwj then - n=getnext(n) - if not n then - break - end - v=ischar(n,font) - if not v then - break - end - end - if consonant[v] then - prevc=true - current=n - end - end - end - local n=getnext(current) - if n then - local v=ischar(n,font) - if v and nukta[v] then - current=n - n=getnext(current) - end - end - syllableend=current - current=n - if current then - local v=ischar(current,font) - if not v then - elseif halant[v] then - local n=getnext(current) - if n then - local v=ischar(n,font) - if v and zw_char[v] then - syllableend=n - current=getnext(n) - else - syllableend=current - current=n - end - else - syllableend=current - current=n - end - else - if dependent_vowel[v] then - syllableend=current - current=getnext(current) - v=ischar(current,font) - end - if v and vowel_modifier[v] then - syllableend=current - current=getnext(current) - v=ischar(current,font) - end - if v and stress_tone_mark[v] then - syllableend=current - current=getnext(current) - end - end - end - if syllablestart~=syllableend then - head,current,nbspaces=deva_reorder(head,syllablestart,syllableend,font,attr,nbspaces) - current=getnext(current) - end - elseif independent_vowel[char] then - syllableend=current - current=getnext(current) - if current then - local v=ischar(current,font) - if v then - if vowel_modifier[v] then - syllableend=current - current=getnext(current) - v=ischar(current,font) - end - if v and stress_tone_mark[v] then - syllableend=current - current=getnext(current) - end - end - end - else - local mark=mark_four[char] - if mark then - head,current=inject_syntax_error(head,current,mark) - end - current=getnext(current) - end - end - else - current=getnext(current) - end - start=false - end - if nbspaces>0 then - head=replace_all_nbsp(head) - end - head=tonode(head) - return head,done -end -function methods.dev2(head,font,attr) - head=tonut(head) - local current=head - local start=true - local done=false - local syllabe=0 - local nbspaces=0 - while current do - local syllablestart=nil - local syllableend=nil - local char=ischar(current,font) - if char then - done=true - syllablestart=current - local c=current - local n=getnext(current) - if n and ra[char] then - local nextchar=ischar(n,font) - if nextchar and halant[nextchar] then - local n=getnext(n) - if n then - local nextnextchar=ischar(n,font) - if nextnextchar then - c=n - char=nextnextchar - end - end - end - end - if independent_vowel[char] then - current=analyze_next_chars_one(c,font,1) - syllableend=current - else - local standalone=char==c_nbsp - if standalone then - nbspaces=nbspaces+1 - local p=getprev(current) - if not p then - elseif ischar(p,font) then - elseif not separator[getchar(p)] then - else - standalone=false - end - end - if standalone then - current=analyze_next_chars_one(c,font,2) - syllableend=current - elseif consonant[getchar(current)] then - current=analyze_next_chars_two(current,font) - syllableend=current - end - end - end - if syllableend then - syllabe=syllabe+1 - local c=syllablestart - local n=getnext(syllableend) - while c~=n do - setprop(c,a_syllabe,syllabe) - c=getnext(c) - end - end - if syllableend and syllablestart~=syllableend then - head,current,nbspaces=dev2_reorder(head,syllablestart,syllableend,font,attr,nbspaces) - end - if not syllableend then - local char=ischar(current,font) - if char and not getprop(current,a_state) then - local mark=mark_four[char] - if mark then - head,current=inject_syntax_error(head,current,mark) - end - end - end - start=false - current=getnext(current) - end - if nbspaces>0 then - head=replace_all_nbsp(head) - end - head=tonode(head) - return head,done -end -methods.mlym=methods.deva -methods.mlm2=methods.dev2 - -end --- [luaotfload, fontloader-2017-02-11.lua scope for “font-osd”] --- - - -do --- [luaotfload, fontloader-2017-02-11.lua scope for “font-ocl” fbc00782e4efb24a7569f99cd1574ffb] --- - -if not modules then modules={} end modules ['font-ocl']={ - version=1.001, - comment="companion to font-otf.lua (context)", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local tostring,next,format=tostring,next,string.format -local round,max=math.round,math.round -local formatters=string.formatters -local tounicode=fonts.mappings.tounicode -local otf=fonts.handlers.otf -local f_color=formatters["pdf:direct:%f %f %f rg"] -local f_gray=formatters["pdf:direct:%f g"] -local s_black="pdf:direct:0 g" -if context then - local startactualtext=nil - local stopactualtext=nil - function otf.getactualtext(s) - if not startactualtext then - startactualtext=backends.codeinjections.startunicodetoactualtextdirect - stopactualtext=backends.codeinjections.stopunicodetoactualtextdirect - end - return startactualtext(s),stopactualtext() - end -else - local tounicode=fonts.mappings.tounicode16 - function otf.getactualtext(s) - return - "/Span << /ActualText <feff"..n.."> >> BDC", - "EMC" - end -end -local sharedpalettes={} -if context then - local graytorgb=attributes.colors.graytorgb - local cmyktorgb=attributes.colors.cmyktorgb - function otf.registerpalette(name,values) - sharedpalettes[name]=values - for i=1,#values do - local v=values[i] - local r,g,b - local s=v.s - if s then - r,g,b=graytorgb(s) - else - local c,m,y,k=v.c,v.m,v.y,v.k - if c or m or y or k then - r,g,b=cmyktorgb(c or 0,m or 0,y or 0,k or 0) - else - r,g,b=v.r,v.g,v.b - end - end - values[i]={ - max(r and round(r*255) or 0,255), - max(g and round(g*255) or 0,255), - max(b and round(b*255) or 0,255) - } - end - end -else - function otf.registerpalette(name,values) - sharedpalettes[name]=values - for i=1,#values do - local v=values[i] - values[i]={ - max(round((v.r or 0)*255),255), - max(round((v.g or 0)*255),255), - max(round((v.b or 0)*255),255) - } - end - end -end -local function initializecolr(tfmdata,kind,value) - if value then - local palettes=tfmdata.resources.colorpalettes - if palettes then - local palette=sharedpalettes[value] or palettes[tonumber(value) or 1] or palettes[1] or {} - local classes=#palette - if classes==0 then - return - end - local characters=tfmdata.characters - local descriptions=tfmdata.descriptions - local properties=tfmdata.properties - local colorvalues={} - properties.virtualized=true - tfmdata.fonts={ - { id=0 } - } - for i=1,classes do - local p=palette[i] - local r,g,b=p[1],p[2],p[3] - if r==g and g==b then - colorvalues[i]={ "special",f_gray(r/255) } - else - colorvalues[i]={ "special",f_color(r/255,g/255,b/255) } - end - end - local getactualtext=otf.getactualtext - for unicode,character in next,characters do - local description=descriptions[unicode] - if description then - local colorlist=description.colors - if colorlist then - local b,e=getactualtext(tounicode(characters[unicode].unicode or 0xFFFD)) - local w=character.width or 0 - local s=#colorlist - local t={ - { "special","pdf:page:q" }, - { "special","pdf:raw:"..b } - } - local n=#t - for i=1,s do - local entry=colorlist[i] - n=n+1 t[n]=colorvalues[entry.class] or s_black - n=n+1 t[n]={ "char",entry.slot } - if s>1 and i<s and w~=0 then - n=n+1 t[n]={ "right",-w } - end - end - n=n+1 t[n]={ "special","pdf:page:"..e } - n=n+1 t[n]={ "special","pdf:raw:Q" } - character.commands=t - end - end - end - end - end -end -fonts.handlers.otf.features.register { - name="colr", - description="color glyphs", - manipulators={ - base=initializecolr, - node=initializecolr, - } -} -local otfsvg=otf.svg or {} -otf.svg=otfsvg -otf.svgenabled=true -do - local nofstreams=0 - local f_name=formatters[ [[svg-glyph-%05i]] ] - local f_used=context and formatters[ [[original:///%s]] ] or formatters[ [[%s]] ] - local cache={} - function otfsvg.storepdfdata(pdf) - nofstreams=nofstreams+1 - local o,n=epdf.openMemStream(pdf,#pdf,f_name(nofstreams)) - cache[n]=o - return nil,f_used(n),nil - end - if context then - local storepdfdata=otfsvg.storepdfdata - local initialized=false - function otfsvg.storepdfdata(pdf) - if not initialized then - if resolvers.setmemstream then - local f_setstream=formatters[ [[resolvers.setmemstream("svg-glyph-%05i",%q,true)]] ] - local f_getstream=formatters[ [[memstream:///svg-glyph-%05i]] ] - local f_nilstream=formatters[ [[resolvers.resetmemstream("svg-glyph-%05i",true)]] ] - storepdfdata=function(pdf) - nofstreams=nofstreams+1 - return - f_setstream(nofstreams,pdf), - f_getstream(nofstreams), - f_nilstream(nofstreams) - end - otfsvg.storepdfdata=storepdfdata - end - initialized=true - end - return storepdfdata(pdf) - end - end -end -do - local report_svg=logs.reporter("fonts","svg conversion") - local loaddata=io.loaddata - local savedata=io.savedata - local remove=os.remove - if context and xml.convert then - local xmlconvert=xml.convert - local xmlfirst=xml.first - function otfsvg.filterglyph(entry,index) - local svg=xmlconvert(entry.data) - local root=svg and xmlfirst(svg,"/svg[@id='glyph"..index.."']") - local data=root and tostring(root) - return data - end - else - function otfsvg.filterglyph(entry,index) - return entry.data - end - end - function otfsvg.topdf(svgshapes) - local inkscape=io.popen("inkscape --shell > temp-otf-svg-shape.log","w") - local pdfshapes={} - local nofshapes=#svgshapes - local f_svgfile=formatters["temp-otf-svg-shape-%i.svg"] - local f_pdffile=formatters["temp-otf-svg-shape-%i.pdf"] - local f_convert=formatters["%s --export-pdf=%s\n"] - local filterglyph=otfsvg.filterglyph - report_svg("processing %i svg containers",nofshapes) - statistics.starttiming() - for i=1,nofshapes do - local entry=svgshapes[i] - for index=entry.first,entry.last do - local data=filterglyph(entry,index) - if data and data~="" then - local svgfile=f_svgfile(index) - local pdffile=f_pdffile(index) - savedata(svgfile,data) - inkscape:write(f_convert(svgfile,pdffile)) - pdfshapes[index]=true - end - end - end - inkscape:write("quit\n") - inkscape:close() - report_svg("processing %i pdf results",nofshapes) - for index in next,pdfshapes do - local svgfile=f_svgfile(index) - local pdffile=f_pdffile(index) - pdfshapes[index]=loaddata(pdffile) - remove(svgfile) - remove(pdffile) - end - statistics.stoptiming() - if statistics.elapsedseconds then - report_svg("svg conversion time %s",statistics.elapsedseconds()) - end - return pdfshapes - end -end -local function initializesvg(tfmdata,kind,value) - if value and otf.svgenabled then - local characters=tfmdata.characters - local descriptions=tfmdata.descriptions - local properties=tfmdata.properties - local svg=properties.svg - local hash=svg and svg.hash - local timestamp=svg and svg.timestamp - if not hash then - return - end - local pdffile=containers.read(otf.pdfcache,hash) - local pdfshapes=pdffile and pdffile.pdfshapes - if not pdfshapes or pdffile.timestamp~=timestamp then - local svgfile=containers.read(otf.svgcache,hash) - local svgshapes=svgfile and svgfile.svgshapes - pdfshapes=svgshapes and otfsvg.topdf(svgshapes) or {} - containers.write(otf.pdfcache,hash,{ - pdfshapes=pdfshapes, - timestamp=timestamp, - }) - end - if not pdfshapes or not next(pdfshapes) then - return - end - properties.virtualized=true - tfmdata.fonts={ - { id=0 } - } - local getactualtext=otf.getactualtext - local storepdfdata=otfsvg.storepdfdata - local nop={ "nop" } - for unicode,character in next,characters do - local index=character.index - if index then - local pdf=pdfshapes[index] - if pdf then - local setcode,name,nilcode=storepdfdata(pdf) - if name then - local bt,et=getactualtext(unicode) - local wd=character.width or 0 - local ht=character.height or 0 - local dp=character.depth or 0 - character.commands={ - { "special","pdf:direct:"..bt }, - { "down",dp }, - setcode and { "lua",setcode } or nop, - { "image",{ filename=name,width=wd,height=ht,depth=dp } }, - nilcode and { "lua",nilcode } or nop, - { "special","pdf:direct:"..et }, - } - character.svg=true - end - end - end - end - end -end -fonts.handlers.otf.features.register { - name="svg", - description="svg glyphs", - manipulators={ - base=initializesvg, - node=initializesvg, - } -} - -end --- [luaotfload, fontloader-2017-02-11.lua scope for “font-ocl”] --- - - -do --- [luaotfload, fontloader-2017-02-11.lua scope for “font-otc” 85d63e257c748c624768aa7c8ec7f0bc] --- - -if not modules then modules={} end modules ['font-otc']={ - version=1.001, - comment="companion to font-otf.lua (context)", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local format,insert,sortedkeys,tohash=string.format,table.insert,table.sortedkeys,table.tohash -local type,next=type,next -local lpegmatch=lpeg.match -local utfbyte,utflen=utf.byte,utf.len -local trace_loading=false trackers.register("otf.loading",function(v) trace_loading=v end) -local report_otf=logs.reporter("fonts","otf loading") -local fonts=fonts -local otf=fonts.handlers.otf -local registerotffeature=otf.features.register -local setmetatableindex=table.setmetatableindex -local normalized={ - substitution="substitution", - single="substitution", - ligature="ligature", - alternate="alternate", - multiple="multiple", - kern="kern", - pair="pair", - chainsubstitution="chainsubstitution", - chainposition="chainposition", -} -local types={ - substitution="gsub_single", - ligature="gsub_ligature", - alternate="gsub_alternate", - multiple="gsub_multiple", - kern="gpos_pair", - pair="gpos_pair", - chainsubstitution="gsub_contextchain", - chainposition="gpos_contextchain", -} -local names={ - gsub_single="gsub", - gsub_multiple="gsub", - gsub_alternate="gsub", - gsub_ligature="gsub", - gsub_context="gsub", - gsub_contextchain="gsub", - gsub_reversecontextchain="gsub", - gpos_single="gpos", - gpos_pair="gpos", - gpos_cursive="gpos", - gpos_mark2base="gpos", - gpos_mark2ligature="gpos", - gpos_mark2mark="gpos", - gpos_context="gpos", - gpos_contextchain="gpos", -} -setmetatableindex(types,function(t,k) t[k]=k return k end) -local everywhere={ ["*"]={ ["*"]=true } } -local noflags={ false,false,false,false } -local function getrange(sequences,category) - local count=#sequences - local first=nil - local last=nil - for i=1,count do - local t=sequences[i].type - if t and names[t]==category then - if not first then - first=i - end - last=i - end - end - return first or 1,last or count -end -local function validspecification(specification,name) - local dataset=specification.dataset - if dataset then - elseif specification[1] then - dataset=specification - specification={ dataset=dataset } - else - dataset={ { data=specification.data } } - specification.data=nil - specification.dataset=dataset - end - local first=dataset[1] - if first then - first=first.data - end - if not first then - report_otf("invalid feature specification, no dataset") - return - end - if type(name)~="string" then - name=specification.name or first.name - end - if type(name)~="string" then - report_otf("invalid feature specification, no name") - return - end - local n=#dataset - if n>0 then - for i=1,n do - setmetatableindex(dataset[i],specification) - end - return specification,name - end -end -local function addfeature(data,feature,specifications) - if not specifications then - report_otf("missing specification") - return - end - local descriptions=data.descriptions - local resources=data.resources - local features=resources.features - local sequences=resources.sequences - if not features or not sequences then - report_otf("missing specification") - return - end - local alreadydone=resources.alreadydone - if not alreadydone then - alreadydone={} - resources.alreadydone=alreadydone - end - if alreadydone[specifications] then - return - else - alreadydone[specifications]=true - end - local fontfeatures=resources.features or everywhere - local unicodes=resources.unicodes - local splitter=lpeg.splitter(" ",unicodes) - local done=0 - local skip=0 - local aglunicodes=false - local specifications=validspecification(specifications,feature) - if not specifications then - return - end - local function tounicode(code) - if not code then - return - end - if type(code)=="number" then - return code - end - local u=unicodes[code] - if u then - return u - end - if utflen(code)==1 then - u=utfbyte(code) - if u then - return u - end - end - if not aglunicodes then - aglunicodes=fonts.encodings.agl.unicodes - end - return aglunicodes[code] - end - local coverup=otf.coverup - local coveractions=coverup.actions - local stepkey=coverup.stepkey - local register=coverup.register - local function prepare_substitution(list,featuretype) - local coverage={} - local cover=coveractions[featuretype] - for code,replacement in next,list do - local unicode=tounicode(code) - local description=descriptions[unicode] - if description then - if type(replacement)=="table" then - replacement=replacement[1] - end - replacement=tounicode(replacement) - if replacement and descriptions[replacement] then - cover(coverage,unicode,replacement) - done=done+1 - else - skip=skip+1 - end - else - skip=skip+1 - end - end - return coverage - end - local function prepare_alternate(list,featuretype) - local coverage={} - local cover=coveractions[featuretype] - for code,replacement in next,list do - local unicode=tounicode(code) - local description=descriptions[unicode] - if not description then - skip=skip+1 - elseif type(replacement)=="table" then - local r={} - for i=1,#replacement do - local u=tounicode(replacement[i]) - r[i]=descriptions[u] and u or unicode - end - cover(coverage,unicode,r) - done=done+1 - else - local u=tounicode(replacement) - if u then - cover(coverage,unicode,{ u }) - done=done+1 - else - skip=skip+1 - end - end - end - return coverage - end - local function prepare_multiple(list,featuretype) - local coverage={} - local cover=coveractions[featuretype] - for code,replacement in next,list do - local unicode=tounicode(code) - local description=descriptions[unicode] - if not description then - skip=skip+1 - elseif type(replacement)=="table" then - local r,n={},0 - for i=1,#replacement do - local u=tounicode(replacement[i]) - if descriptions[u] then - n=n+1 - r[n]=u - end - end - if n>0 then - cover(coverage,unicode,r) - done=done+1 - else - skip=skip+1 - end - else - local u=tounicode(replacement) - if u then - cover(coverage,unicode,{ u }) - done=done+1 - else - skip=skip+1 - end - end - end - return coverage - end - local function prepare_ligature(list,featuretype) - local coverage={} - local cover=coveractions[featuretype] - for code,ligature in next,list do - local unicode=tounicode(code) - local description=descriptions[unicode] - if description then - if type(ligature)=="string" then - ligature={ lpegmatch(splitter,ligature) } - end - local present=true - for i=1,#ligature do - local l=ligature[i] - local u=tounicode(l) - if descriptions[u] then - ligature[i]=u - else - present=false - break - end - end - if present then - cover(coverage,unicode,ligature) - done=done+1 - else - skip=skip+1 - end - else - skip=skip+1 - end - end - return coverage - end - local function prepare_kern(list,featuretype) - local coverage={} - local cover=coveractions[featuretype] - for code,replacement in next,list do - local unicode=tounicode(code) - local description=descriptions[unicode] - if description and type(replacement)=="table" then - local r={} - for k,v in next,replacement do - local u=tounicode(k) - if u then - r[u]=v - end - end - if next(r) then - cover(coverage,unicode,r) - done=done+1 - else - skip=skip+1 - end - else - skip=skip+1 - end - end - return coverage - end - local function prepare_pair(list,featuretype) - local coverage={} - local cover=coveractions[featuretype] - if cover then - for code,replacement in next,list do - local unicode=tounicode(code) - local description=descriptions[unicode] - if description and type(replacement)=="table" then - local r={} - for k,v in next,replacement do - local u=tounicode(k) - if u then - r[u]=v - end - end - if next(r) then - cover(coverage,unicode,r) - done=done+1 - else - skip=skip+1 - end - else - skip=skip+1 - end - end - else - report_otf("unknown cover type %a",featuretype) - end - return coverage - end - local function prepare_chain(list,featuretype,sublookups) - local rules=list.rules - local coverage={} - if rules then - local rulehash={} - local rulesize=0 - local sequence={} - local nofsequences=0 - local lookuptype=types[featuretype] - for nofrules=1,#rules do - local rule=rules[nofrules] - local current=rule.current - local before=rule.before - local after=rule.after - local replacements=rule.replacements or false - local sequence={} - local nofsequences=0 - if before then - for n=1,#before do - nofsequences=nofsequences+1 - sequence[nofsequences]=before[n] - end - end - local start=nofsequences+1 - for n=1,#current do - nofsequences=nofsequences+1 - sequence[nofsequences]=current[n] - end - local stop=nofsequences - if after then - for n=1,#after do - nofsequences=nofsequences+1 - sequence[nofsequences]=after[n] - end - end - local lookups=rule.lookups or false - local subtype=nil - if lookups and sublookups then - for k,v in next,lookups do - local lookup=sublookups[v] - if lookup then - lookups[k]=lookup - if not subtype then - subtype=lookup.type - end - else - end - end - end - if nofsequences>0 then - local hashed={} - for i=1,nofsequences do - local t={} - local s=sequence[i] - for i=1,#s do - local u=tounicode(s[i]) - if u then - t[u]=true - end - end - hashed[i]=t - end - sequence=hashed - rulesize=rulesize+1 - rulehash[rulesize]={ - nofrules, - lookuptype, - sequence, - start, - stop, - lookups, - replacements, - subtype, - } - for unic in next,sequence[start] do - local cu=coverage[unic] - if not cu then - coverage[unic]=rulehash - end - end - end - end - end - return coverage - end - local dataset=specifications.dataset - local function report(name,category,position,first,last,sequences) - report_otf("injecting name %a of category %a at position %i in [%i,%i] of [%i,%i]", - name,category,position,first,last,1,#sequences) - end - local function inject(specification,sequences,sequence,first,last,category,name) - local position=specification.position or false - if not position then - position=specification.prepend - if position==true then - if trace_loading then - report(name,category,first,first,last,sequences) - end - insert(sequences,first,sequence) - return - end - end - if not position then - position=specification.append - if position==true then - if trace_loading then - report(name,category,last+1,first,last,sequences) - end - insert(sequences,last+1,sequence) - return - end - end - local kind=type(position) - if kind=="string" then - local index=false - for i=first,last do - local s=sequences[i] - local f=s.features - if f then - for k in next,f do - if k==position then - index=i - break - end - end - if index then - break - end - end - end - if index then - position=index - else - position=last+1 - end - elseif kind=="number" then - if position<0 then - position=last-position+1 - end - if position>last then - position=last+1 - elseif position<first then - position=first - end - else - position=last+1 - end - if trace_loading then - report(name,category,position,first,last,sequences) - end - insert(sequences,position,sequence) - end - for s=1,#dataset do - local specification=dataset[s] - local valid=specification.valid - local feature=specification.name or feature - if not feature or feature=="" then - report_otf("no valid name given for extra feature") - elseif not valid or valid(data,specification,feature) then - local initialize=specification.initialize - if initialize then - specification.initialize=initialize(specification,data) and initialize or nil - end - local askedfeatures=specification.features or everywhere - local askedsteps=specification.steps or specification.subtables or { specification.data } or {} - local featuretype=normalized[specification.type or "substitution"] or "substitution" - local featureflags=specification.flags or noflags - local featureorder=specification.order or { feature } - local featurechain=(featuretype=="chainsubstitution" or featuretype=="chainposition") and 1 or 0 - local nofsteps=0 - local steps={} - local sublookups=specification.lookups - local category=nil - if sublookups then - local s={} - for i=1,#sublookups do - local specification=sublookups[i] - local askedsteps=specification.steps or specification.subtables or { specification.data } or {} - local featuretype=normalized[specification.type or "substitution"] or "substitution" - local featureflags=specification.flags or noflags - local nofsteps=0 - local steps={} - for i=1,#askedsteps do - local list=askedsteps[i] - local coverage=nil - local format=nil - if featuretype=="substitution" then - coverage=prepare_substitution(list,featuretype) - elseif featuretype=="ligature" then - coverage=prepare_ligature(list,featuretype) - elseif featuretype=="alternate" then - coverage=prepare_alternate(list,featuretype) - elseif featuretype=="multiple" then - coverage=prepare_multiple(list,featuretype) - elseif featuretype=="kern" then - format="kern" - coverage=prepare_kern(list,featuretype) - elseif featuretype=="pair" then - format="pair" - coverage=prepare_pair(list,featuretype) - end - if coverage and next(coverage) then - nofsteps=nofsteps+1 - steps[nofsteps]=register(coverage,featuretype,format,feature,nofsteps,descriptions,resources) - end - end - s[i]={ - [stepkey]=steps, - nofsteps=nofsteps, - type=types[featuretype], - } - end - sublookups=s - end - for i=1,#askedsteps do - local list=askedsteps[i] - local coverage=nil - local format=nil - if featuretype=="substitution" then - category="gsub" - coverage=prepare_substitution(list,featuretype) - elseif featuretype=="ligature" then - category="gsub" - coverage=prepare_ligature(list,featuretype) - elseif featuretype=="alternate" then - category="gsub" - coverage=prepare_alternate(list,featuretype) - elseif featuretype=="multiple" then - category="gsub" - coverage=prepare_multiple(list,featuretype) - elseif featuretype=="kern" then - category="gpos" - format="kern" - coverage=prepare_kern(list,featuretype) - elseif featuretype=="pair" then - category="gpos" - format="pair" - coverage=prepare_pair(list,featuretype) - elseif featuretype=="chainsubstitution" then - category="gsub" - coverage=prepare_chain(list,featuretype,sublookups) - elseif featuretype=="chainposition" then - category="gpos" - coverage=prepare_chain(list,featuretype,sublookups) - else - report_otf("not registering feature %a, unknown category",feature) - return - end - if coverage and next(coverage) then - nofsteps=nofsteps+1 - steps[nofsteps]=register(coverage,featuretype,format,feature,nofsteps,descriptions,resources) - end - end - if nofsteps>0 then - for k,v in next,askedfeatures do - if v[1] then - askedfeatures[k]=tohash(v) - end - end - if featureflags[1] then featureflags[1]="mark" end - if featureflags[2] then featureflags[2]="ligature" end - if featureflags[3] then featureflags[3]="base" end - local steptype=types[featuretype] - local sequence={ - chain=featurechain, - features={ [feature]=askedfeatures }, - flags=featureflags, - name=feature, - order=featureorder, - [stepkey]=steps, - nofsteps=nofsteps, - type=steptype, - } - local first,last=getrange(sequences,category) - inject(specification,sequences,sequence,first,last,category,feature) - local features=fontfeatures[category] - if not features then - features={} - fontfeatures[category]=features - end - local k=features[feature] - if not k then - k={} - features[feature]=k - end - for script,languages in next,askedfeatures do - local kk=k[script] - if not kk then - kk={} - k[script]=kk - end - for language,value in next,languages do - kk[language]=value - end - end - end - end - end - if trace_loading then - report_otf("registering feature %a, affected glyphs %a, skipped glyphs %a",feature,done,skip) - end -end -otf.enhancers.addfeature=addfeature -local extrafeatures={} -local knownfeatures={} -function otf.addfeature(name,specification) - if type(name)=="table" then - specification=name - end - if type(specification)~="table" then - report_otf("invalid feature specification, no valid table") - return - end - specification,name=validspecification(specification,name) - if name and specification then - local slot=knownfeatures[name] - if slot then - else - slot=#extrafeatures+1 - knownfeatures[name]=slot - end - specification.name=name - extrafeatures[slot]=specification - end -end -local function enhance(data,filename,raw) - for slot=1,#extrafeatures do - local specification=extrafeatures[slot] - addfeature(data,specification.name,specification) - end -end -otf.enhancers.enhance=enhance -otf.enhancers.register("check extra features",enhance) -local tlig={ - [0x2013]={ 0x002D,0x002D }, - [0x2014]={ 0x002D,0x002D,0x002D }, -} -local tlig_specification={ - type="ligature", - features=everywhere, - data=tlig, - order={ "tlig" }, - flags=noflags, - prepend=true, -} -otf.addfeature("tlig",tlig_specification) -registerotffeature { - name='tlig', - description='tex ligatures', -} -local trep={ - [0x0027]=0x2019, -} -local trep_specification={ - type="substitution", - features=everywhere, - data=trep, - order={ "trep" }, - flags=noflags, - prepend=true, -} -otf.addfeature("trep",trep_specification) -registerotffeature { - name='trep', - description='tex replacements', -} -local anum_arabic={ - [0x0030]=0x0660, - [0x0031]=0x0661, - [0x0032]=0x0662, - [0x0033]=0x0663, - [0x0034]=0x0664, - [0x0035]=0x0665, - [0x0036]=0x0666, - [0x0037]=0x0667, - [0x0038]=0x0668, - [0x0039]=0x0669, -} -local anum_persian={ - [0x0030]=0x06F0, - [0x0031]=0x06F1, - [0x0032]=0x06F2, - [0x0033]=0x06F3, - [0x0034]=0x06F4, - [0x0035]=0x06F5, - [0x0036]=0x06F6, - [0x0037]=0x06F7, - [0x0038]=0x06F8, - [0x0039]=0x06F9, -} -local function valid(data) - local features=data.resources.features - if features then - for k,v in next,features do - for k,v in next,v do - if v.arab then - return true - end - end - end - end -end -local anum_specification={ - { - type="substitution", - features={ arab={ urd=true,dflt=true } }, - order={ "anum" }, - data=anum_arabic, - flags=noflags, - valid=valid, - }, - { - type="substitution", - features={ arab={ urd=true } }, - order={ "anum" }, - data=anum_persian, - flags=noflags, - valid=valid, - }, -} -otf.addfeature("anum",anum_specification) -registerotffeature { - name='anum', - description='arabic digits', -} - -end --- [luaotfload, fontloader-2017-02-11.lua scope for “font-otc”] --- - - -do --- [luaotfload, fontloader-2017-02-11.lua scope for “font-onr” 205c8bc640715aecf3538a33b842f450] --- - -if not modules then modules={} end modules ['font-onr']={ - version=1.001, - comment="companion to font-ini.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local fonts,logs,trackers,resolvers=fonts,logs,trackers,resolvers -local next,type,tonumber,rawget,rawset=next,type,tonumber,rawget,rawset -local match,lower,gsub,strip,find=string.match,string.lower,string.gsub,string.strip,string.find -local char,byte,sub=string.char,string.byte,string.sub -local abs=math.abs -local bxor,rshift=bit32.bxor,bit32.rshift -local P,S,R,Cmt,C,Ct,Cs,Carg,Cf,Cg=lpeg.P,lpeg.S,lpeg.R,lpeg.Cmt,lpeg.C,lpeg.Ct,lpeg.Cs,lpeg.Carg,lpeg.Cf,lpeg.Cg -local lpegmatch,patterns=lpeg.match,lpeg.patterns -local trace_indexing=false trackers.register("afm.indexing",function(v) trace_indexing=v end) -local trace_loading=false trackers.register("afm.loading",function(v) trace_loading=v end) -local report_afm=logs.reporter("fonts","afm loading") -local report_pfb=logs.reporter("fonts","pfb loading") -local handlers=fonts.handlers -local afm=handlers.afm or {} -handlers.afm=afm -local readers=afm.readers or {} -afm.readers=readers -afm.version=1.512 -local get_indexes,get_shapes -do - local decrypt - do - local r,c1,c2,n=0,0,0,0 - local function step(c) - local cipher=byte(c) - local plain=bxor(cipher,rshift(r,8)) - r=((cipher+r)*c1+c2)%65536 - return char(plain) - end - decrypt=function(binary,initial,seed) - r,c1,c2,n=initial,52845,22719,seed - binary=gsub(binary,".",step) - return sub(binary,n+1) - end - end - local charstrings=P("/CharStrings") - local subroutines=P("/Subrs") - local encoding=P("/Encoding") - local dup=P("dup") - local put=P("put") - local array=P("array") - local name=P("/")*C((R("az")+R("AZ")+R("09")+S("-_."))^1) - local digits=R("09")^1 - local cardinal=digits/tonumber - local spaces=P(" ")^1 - local spacing=patterns.whitespace^0 - local routines,vector,chars,n,m - local initialize=function(str,position,size) - n=0 - m=size - return position+1 - end - local setroutine=function(str,position,index,size) - local forward=position+tonumber(size) - local stream=sub(str,position+1,forward) - routines[index]=decrypt(stream,4330,4) - return forward - end - local setvector=function(str,position,name,size) - local forward=position+tonumber(size) - if n>=m then - return #str - elseif forward<#str then - vector[n]=name - n=n+1 - return forward - else - return #str - end - end - local setshapes=function(str,position,name,size) - local forward=position+tonumber(size) - local stream=sub(str,position+1,forward) - if n>m then - return #str - elseif forward<#str then - vector[n]=name - n=n+1 - chars [n]=decrypt(stream,4330,4) - return forward - else - return #str - end - end - local p_rd=spacing*(P("RD")+P("-|")) - local p_np=spacing*(P("NP")+P("|")) - local p_nd=spacing*(P("ND")+P("|")) - local p_filterroutines= - (1-subroutines)^0*subroutines*spaces*Cmt(cardinal,initialize)*(Cmt(cardinal*spaces*cardinal*p_rd,setroutine)*p_np+P(1))^1 - local p_filtershapes= - (1-charstrings)^0*charstrings*spaces*Cmt(cardinal,initialize)*(Cmt(name*spaces*cardinal*p_rd,setshapes)*p_nd+P(1))^1 - local p_filternames=Ct ( - (1-charstrings)^0*charstrings*spaces*Cmt(cardinal,initialize)*(Cmt(name*spaces*cardinal,setvector)+P(1))^1 - ) - local p_filterencoding=(1-encoding)^0*encoding*spaces*digits*spaces*array*(1-dup)^0*Cf( - Ct("")*Cg(spacing*dup*spaces*cardinal*spaces*name*spaces*put)^1 -,rawset) - local function loadpfbvector(filename,shapestoo) - local data=io.loaddata(resolvers.findfile(filename)) - if not data then - report_pfb("no data in %a",filename) - return - end - if not (find(data,"!PS%-AdobeFont%-") or find(data,"%%!FontType1")) then - report_pfb("no font in %a",filename) - return - end - local ascii,binary=match(data,"(.*)eexec%s+......(.*)") - if not binary then - report_pfb("no binary data in %a",filename) - return - end - binary=decrypt(binary,55665,4) - local names={} - local encoding=lpegmatch(p_filterencoding,ascii) - local glyphs={} - routines,vector,chars={},{},{} - if shapestoo then - lpegmatch(p_filterroutines,binary) - lpegmatch(p_filtershapes,binary) - local data={ - dictionaries={ - { - charstrings=chars, - charset=vector, - subroutines=routines, - } - }, - } - fonts.handlers.otf.readers.parsecharstrings(data,glyphs,true,true) - else - lpegmatch(p_filternames,binary) - end - names=vector - routines,vector,chars=nil,nil,nil - return names,encoding,glyphs - end - local pfb=handlers.pfb or {} - handlers.pfb=pfb - pfb.loadvector=loadpfbvector - get_indexes=function(data,pfbname) - local vector=loadpfbvector(pfbname) - if vector then - local characters=data.characters - if trace_loading then - report_afm("getting index data from %a",pfbname) - end - for index=1,#vector do - local name=vector[index] - local char=characters[name] - if char then - if trace_indexing then - report_afm("glyph %a has index %a",name,index) - end - char.index=index - end - end - end - end - get_shapes=function(pfbname) - local vector,encoding,glyphs=loadpfbvector(pfbname,true) - return glyphs - end -end -local spacer=patterns.spacer -local whitespace=patterns.whitespace -local lineend=patterns.newline -local spacing=spacer^0 -local number=spacing*S("+-")^-1*(R("09")+S("."))^1/tonumber -local name=spacing*C((1-whitespace)^1) -local words=spacing*((1-lineend)^1/strip) -local rest=(1-lineend)^0 -local fontdata=Carg(1) -local semicolon=spacing*P(";") -local plus=spacing*P("plus")*number -local minus=spacing*P("minus")*number -local function addkernpair(data,one,two,value) - local chr=data.characters[one] - if chr then - local kerns=chr.kerns - if kerns then - kerns[two]=tonumber(value) - else - chr.kerns={ [two]=tonumber(value) } - end - end -end -local p_kernpair=(fontdata*P("KPX")*name*name*number)/addkernpair -local chr=false -local ind=0 -local function start(data,version) - data.metadata.afmversion=version - ind=0 - chr={} -end -local function stop() - ind=0 - chr=false -end -local function setindex(i) - if i<0 then - ind=ind+1 - else - ind=i - end - chr={ - index=ind - } -end -local function setwidth(width) - chr.width=width -end -local function setname(data,name) - data.characters[name]=chr -end -local function setboundingbox(boundingbox) - chr.boundingbox=boundingbox -end -local function setligature(plus,becomes) - local ligatures=chr.ligatures - if ligatures then - ligatures[plus]=becomes - else - chr.ligatures={ [plus]=becomes } - end -end -local p_charmetric=(( - P("C")*number/setindex+P("WX")*number/setwidth+P("N")*fontdata*name/setname+P("B")*Ct((number)^4)/setboundingbox+P("L")*(name)^2/setligature - )*semicolon )^1 -local p_charmetrics=P("StartCharMetrics")*number*(p_charmetric+(1-P("EndCharMetrics")))^0*P("EndCharMetrics") -local p_kernpairs=P("StartKernPairs")*number*(p_kernpair+(1-P("EndKernPairs" )))^0*P("EndKernPairs" ) -local function set_1(data,key,a) data.metadata[lower(key)]=a end -local function set_2(data,key,a,b) data.metadata[lower(key)]={ a,b } end -local function set_3(data,key,a,b,c) data.metadata[lower(key)]={ a,b,c } end -local p_parameters=P(false)+fontdata*((P("FontName")+P("FullName")+P("FamilyName"))/lower)*words/function(data,key,value) - data.metadata[key]=value - end+fontdata*((P("Weight")+P("Version"))/lower)*name/function(data,key,value) - data.metadata[key]=value - end+fontdata*P("IsFixedPitch")*name/function(data,pitch) - data.metadata.monospaced=toboolean(pitch,true) - end+fontdata*P("FontBBox")*Ct(number^4)/function(data,boundingbox) - data.metadata.boundingbox=boundingbox - end+fontdata*((P("CharWidth")+P("CapHeight")+P("XHeight")+P("Descender")+P("Ascender")+P("ItalicAngle"))/lower)*number/function(data,key,value) - data.metadata[key]=value - end+P("Comment")*spacing*(P(false)+(fontdata*C("DESIGNSIZE")*number*rest)/set_1 -+(fontdata*C("TFM designsize")*number*rest)/set_1+(fontdata*C("DesignSize")*number*rest)/set_1+(fontdata*C("CODINGSCHEME")*words*rest)/set_1 -+(fontdata*C("CHECKSUM")*number*words*rest)/set_1 -+(fontdata*C("SPACE")*number*plus*minus*rest)/set_3 -+(fontdata*C("QUAD")*number*rest)/set_1 -+(fontdata*C("EXTRASPACE")*number*rest)/set_1 -+(fontdata*C("NUM")*number*number*number*rest)/set_3 -+(fontdata*C("DENOM")*number*number*rest)/set_2 -+(fontdata*C("SUP")*number*number*number*rest)/set_3 -+(fontdata*C("SUB")*number*number*rest)/set_2 -+(fontdata*C("SUPDROP")*number*rest)/set_1 -+(fontdata*C("SUBDROP")*number*rest)/set_1 -+(fontdata*C("DELIM")*number*number*rest)/set_2 -+(fontdata*C("AXISHEIGHT")*number*rest)/set_1 - ) -local fullparser=(P("StartFontMetrics")*fontdata*name/start )*(p_charmetrics+p_kernpairs+p_parameters+(1-P("EndFontMetrics")) )^0*(P("EndFontMetrics")/stop ) -local fullparser=(P("StartFontMetrics")*fontdata*name/start )*(p_charmetrics+p_kernpairs+p_parameters+(1-P("EndFontMetrics")) )^0*(P("EndFontMetrics")/stop ) -local infoparser=(P("StartFontMetrics")*fontdata*name/start )*(p_parameters+(1-P("EndFontMetrics")) )^0*(P("EndFontMetrics")/stop ) -local function read(filename,parser) - local afmblob=io.loaddata(filename) - if afmblob then - local data={ - resources={ - filename=resolvers.unresolve(filename), - version=afm.version, - creator="context mkiv", - }, - properties={ - hasitalics=false, - }, - goodies={}, - metadata={ - filename=file.removesuffix(file.basename(filename)) - }, - characters={ - }, - descriptions={ - }, - } - if trace_loading then - report_afm("parsing afm file %a",filename) - end - lpegmatch(parser,afmblob,1,data) - return data - else - if trace_loading then - report_afm("no valid afm file %a",filename) - end - return nil - end -end -function readers.loadfont(afmname,pfbname) - local data=read(resolvers.findfile(afmname),fullparser) - if data then - if not pfbname or pfbname=="" then - pfbname=file.replacesuffix(file.nameonly(afmname),"pfb") - pfbname=resolvers.findfile(pfbname) - end - if pfbname and pfbname~="" then - data.resources.filename=resolvers.unresolve(pfbname) - get_indexes(data,pfbname) - elseif trace_loading then - report_afm("no pfb file for %a",afmname) - end - return data - end -end -function readers.loadshapes(filename) - local fullname=resolvers.findfile(filename) or "" - if fullname=="" then - return { - filename="not found: "..filename, - glyphs={} - } - else - return { - filename=fullname, - format="opentype", - glyphs=get_shapes(fullname) or {}, - units=1000, - } - end -end -function readers.getinfo(filename) - local data=read(resolvers.findfile(filename),infoparser) - if data then - return data.metadata - end -end - -end --- [luaotfload, fontloader-2017-02-11.lua scope for “font-onr”] --- - - -do --- [luaotfload, fontloader-2017-02-11.lua scope for “font-one” 6fbf6b9e219a944cd1ad5933d77cc488] --- - -if not modules then modules={} end modules ['font-one']={ - version=1.001, - comment="companion to font-ini.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local fonts,logs,trackers,containers,resolvers=fonts,logs,trackers,containers,resolvers -local next,type,tonumber,rawget=next,type,tonumber,rawget -local match,gmatch,lower,gsub,strip,find=string.match,string.gmatch,string.lower,string.gsub,string.strip,string.find -local char,byte,sub=string.char,string.byte,string.sub -local abs=math.abs -local bxor,rshift=bit32.bxor,bit32.rshift -local P,S,R,Cmt,C,Ct,Cs,Carg=lpeg.P,lpeg.S,lpeg.R,lpeg.Cmt,lpeg.C,lpeg.Ct,lpeg.Cs,lpeg.Carg -local lpegmatch,patterns=lpeg.match,lpeg.patterns -local trace_features=false trackers.register("afm.features",function(v) trace_features=v end) -local trace_indexing=false trackers.register("afm.indexing",function(v) trace_indexing=v end) -local trace_loading=false trackers.register("afm.loading",function(v) trace_loading=v end) -local trace_defining=false trackers.register("fonts.defining",function(v) trace_defining=v end) -local report_afm=logs.reporter("fonts","afm loading") -local setmetatableindex=table.setmetatableindex -local derivetable=table.derive -local findbinfile=resolvers.findbinfile -local definers=fonts.definers -local readers=fonts.readers -local constructors=fonts.constructors -local afm=constructors.handlers.afm -local pfb=constructors.handlers.pfb -local otf=fonts.handlers.otf -local otfreaders=otf.readers -local otfenhancers=otf.enhancers -local afmfeatures=constructors.features.afm -local registerafmfeature=afmfeatures.register -local afmenhancers=constructors.enhancers.afm -local registerafmenhancer=afmenhancers.register -afm.version=1.512 -afm.cache=containers.define("fonts","one",afm.version,true) -afm.autoprefixed=true -afm.helpdata={} -afm.syncspace=true -local overloads=fonts.mappings.overloads -local applyruntimefixes=fonts.treatments and fonts.treatments.applyfixes -function afm.load(filename) - filename=resolvers.findfile(filename,'afm') or "" - if filename~="" and not fonts.names.ignoredfile(filename) then - local name=file.removesuffix(file.basename(filename)) - local data=containers.read(afm.cache,name) - local attr=lfs.attributes(filename) - local size,time=attr.size or 0,attr.modification or 0 - local pfbfile=file.replacesuffix(name,"pfb") - local pfbname=resolvers.findfile(pfbfile,"pfb") or "" - if pfbname=="" then - pfbname=resolvers.findfile(file.basename(pfbfile),"pfb") or "" - end - local pfbsize,pfbtime=0,0 - if pfbname~="" then - local attr=lfs.attributes(pfbname) - pfbsize=attr.size or 0 - pfbtime=attr.modification or 0 - end - if not data or data.size~=size or data.time~=time or data.pfbsize~=pfbsize or data.pfbtime~=pfbtime then - report_afm("reading %a",filename) - data=afm.readers.loadfont(filename,pfbname) - if data then - afmenhancers.apply(data,filename) - fonts.mappings.addtounicode(data,filename) - otfreaders.pack(data) - data.size=size - data.time=time - data.pfbsize=pfbsize - data.pfbtime=pfbtime - report_afm("saving %a in cache",name) - data=containers.write(afm.cache,name,data) - data=containers.read(afm.cache,name) - end - end - if data then - otfreaders.unpack(data) - otfreaders.expand(data) - otfreaders.addunicodetable(data) - otfenhancers.apply(data,filename,data) - if applyruntimefixes then - applyruntimefixes(filename,data) - end - end - return data - end -end -local uparser=fonts.mappings.makenameparser() -local function enhance_unify_names(data,filename) - local unicodevector=fonts.encodings.agl.unicodes - local unicodes={} - local names={} - local private=constructors.privateoffset - local descriptions=data.descriptions - for name,blob in next,data.characters do - local code=unicodevector[name] - if not code then - code=lpegmatch(uparser,name) - if type(code)~="number" then - code=private - private=private+1 - report_afm("assigning private slot %U for unknown glyph name %a",code,name) - end - end - local index=blob.index - unicodes[name]=code - names[name]=index - blob.name=name - descriptions[code]={ - boundingbox=blob.boundingbox, - width=blob.width, - kerns=blob.kerns, - index=index, - name=name, - } - end - for unicode,description in next,descriptions do - local kerns=description.kerns - if kerns then - local krn={} - for name,kern in next,kerns do - local unicode=unicodes[name] - if unicode then - krn[unicode]=kern - else - end - end - description.kerns=krn - end - end - data.characters=nil - local resources=data.resources - local filename=resources.filename or file.removesuffix(file.basename(filename)) - resources.filename=resolvers.unresolve(filename) - resources.unicodes=unicodes - resources.marks={} - resources.private=private -end -local everywhere={ ["*"]={ ["*"]=true } } -local noflags={ false,false,false,false } -local function enhance_normalize_features(data) - local ligatures=setmetatableindex("table") - local kerns=setmetatableindex("table") - local extrakerns=setmetatableindex("table") - for u,c in next,data.descriptions do - local l=c.ligatures - local k=c.kerns - local e=c.extrakerns - if l then - ligatures[u]=l - for u,v in next,l do - l[u]={ ligature=v } - end - c.ligatures=nil - end - if k then - kerns[u]=k - for u,v in next,k do - k[u]=v - end - c.kerns=nil - end - if e then - extrakerns[u]=e - for u,v in next,e do - e[u]=v - end - c.extrakerns=nil - end - end - local features={ - gpos={}, - gsub={}, - } - local sequences={ - } - if next(ligatures) then - features.gsub.liga=everywhere - data.properties.hasligatures=true - sequences[#sequences+1]={ - features={ - liga=everywhere, - }, - flags=noflags, - name="s_s_0", - nofsteps=1, - order={ "liga" }, - type="gsub_ligature", - steps={ - { - coverage=ligatures, - }, - }, - } - end - if next(kerns) then - features.gpos.kern=everywhere - data.properties.haskerns=true - sequences[#sequences+1]={ - features={ - kern=everywhere, - }, - flags=noflags, - name="p_s_0", - nofsteps=1, - order={ "kern" }, - type="gpos_pair", - steps={ - { - format="kern", - coverage=kerns, - }, - }, - } - end - if next(extrakerns) then - features.gpos.extrakerns=everywhere - data.properties.haskerns=true - sequences[#sequences+1]={ - features={ - extrakerns=everywhere, - }, - flags=noflags, - name="p_s_1", - nofsteps=1, - order={ "extrakerns" }, - type="gpos_pair", - steps={ - { - format="kern", - coverage=extrakerns, - }, - }, - } - end - data.resources.features=features - data.resources.sequences=sequences -end -local function enhance_fix_names(data) - for k,v in next,data.descriptions do - local n=v.name - local r=overloads[n] - if r then - local name=r.name - if trace_indexing then - report_afm("renaming characters %a to %a",n,name) - end - v.name=name - v.unicode=r.unicode - end - end -end -local addthem=function(rawdata,ligatures) - if ligatures then - local descriptions=rawdata.descriptions - local resources=rawdata.resources - local unicodes=resources.unicodes - for ligname,ligdata in next,ligatures do - local one=descriptions[unicodes[ligname]] - if one then - for _,pair in next,ligdata do - local two,three=unicodes[pair[1]],unicodes[pair[2]] - if two and three then - local ol=one.ligatures - if ol then - if not ol[two] then - ol[two]=three - end - else - one.ligatures={ [two]=three } - end - end - end - end - end - end -end -local function enhance_add_ligatures(rawdata) - addthem(rawdata,afm.helpdata.ligatures) -end -local function enhance_add_extra_kerns(rawdata) - local descriptions=rawdata.descriptions - local resources=rawdata.resources - local unicodes=resources.unicodes - local function do_it_left(what) - if what then - for unicode,description in next,descriptions do - local kerns=description.kerns - if kerns then - local extrakerns - for complex,simple in next,what do - complex=unicodes[complex] - simple=unicodes[simple] - if complex and simple then - local ks=kerns[simple] - if ks and not kerns[complex] then - if extrakerns then - extrakerns[complex]=ks - else - extrakerns={ [complex]=ks } - end - end - end - end - if extrakerns then - description.extrakerns=extrakerns - end - end - end - end - end - local function do_it_copy(what) - if what then - for complex,simple in next,what do - complex=unicodes[complex] - simple=unicodes[simple] - if complex and simple then - local complexdescription=descriptions[complex] - if complexdescription then - local simpledescription=descriptions[complex] - if simpledescription then - local extrakerns - local kerns=simpledescription.kerns - if kerns then - for unicode,kern in next,kerns do - if extrakerns then - extrakerns[unicode]=kern - else - extrakerns={ [unicode]=kern } - end - end - end - local extrakerns=simpledescription.extrakerns - if extrakerns then - for unicode,kern in next,extrakerns do - if extrakerns then - extrakerns[unicode]=kern - else - extrakerns={ [unicode]=kern } - end - end - end - if extrakerns then - complexdescription.extrakerns=extrakerns - end - end - end - end - end - end - end - do_it_left(afm.helpdata.leftkerned) - do_it_left(afm.helpdata.bothkerned) - do_it_copy(afm.helpdata.bothkerned) - do_it_copy(afm.helpdata.rightkerned) -end -local function adddimensions(data) - if data then - for unicode,description in next,data.descriptions do - local bb=description.boundingbox - if bb then - local ht,dp=bb[4],-bb[2] - if ht==0 or ht<0 then - else - description.height=ht - end - if dp==0 or dp<0 then - else - description.depth=dp - end - end - end - end -end -local function copytotfm(data) - if data and data.descriptions then - local metadata=data.metadata - local resources=data.resources - local properties=derivetable(data.properties) - local descriptions=derivetable(data.descriptions) - local goodies=derivetable(data.goodies) - local characters={} - local parameters={} - local unicodes=resources.unicodes - for unicode,description in next,data.descriptions do - characters[unicode]={} - end - local filename=constructors.checkedfilename(resources) - local fontname=metadata.fontname or metadata.fullname - local fullname=metadata.fullname or metadata.fontname - local endash=0x0020 - local emdash=0x2014 - local spacer="space" - local spaceunits=500 - local monospaced=metadata.monospaced - local charwidth=metadata.charwidth - local italicangle=metadata.italicangle - local charxheight=metadata.xheight and metadata.xheight>0 and metadata.xheight - properties.monospaced=monospaced - parameters.italicangle=italicangle - parameters.charwidth=charwidth - parameters.charxheight=charxheight - if properties.monospaced then - if descriptions[endash] then - spaceunits,spacer=descriptions[endash].width,"space" - end - if not spaceunits and descriptions[emdash] then - spaceunits,spacer=descriptions[emdash].width,"emdash" - end - if not spaceunits and charwidth then - spaceunits,spacer=charwidth,"charwidth" - end - else - if descriptions[endash] then - spaceunits,spacer=descriptions[endash].width,"space" - end - if not spaceunits and charwidth then - spaceunits,spacer=charwidth,"charwidth" - end - end - spaceunits=tonumber(spaceunits) - if spaceunits<200 then - end - parameters.slant=0 - parameters.space=spaceunits - parameters.space_stretch=500 - parameters.space_shrink=333 - parameters.x_height=400 - parameters.quad=1000 - if italicangle and italicangle~=0 then - parameters.italicangle=italicangle - parameters.italicfactor=math.cos(math.rad(90+italicangle)) - parameters.slant=- math.tan(italicangle*math.pi/180) - end - if monospaced then - parameters.space_stretch=0 - parameters.space_shrink=0 - elseif afm.syncspace then - parameters.space_stretch=spaceunits/2 - parameters.space_shrink=spaceunits/3 - end - parameters.extra_space=parameters.space_shrink - if charxheight then - parameters.x_height=charxheight - else - local x=0x0078 - if x then - local x=descriptions[x] - if x then - parameters.x_height=x.height - end - end - end - if metadata.sup then - local dummy={ 0,0,0 } - parameters[ 1]=metadata.designsize or 0 - parameters[ 2]=metadata.checksum or 0 - parameters[ 3], - parameters[ 4], - parameters[ 5]=unpack(metadata.space or dummy) - parameters[ 6]=metadata.quad or 0 - parameters[ 7]=metadata.extraspace or 0 - parameters[ 8], - parameters[ 9], - parameters[10]=unpack(metadata.num or dummy) - parameters[11], - parameters[12]=unpack(metadata.denom or dummy) - parameters[13], - parameters[14], - parameters[15]=unpack(metadata.sup or dummy) - parameters[16], - parameters[17]=unpack(metadata.sub or dummy) - parameters[18]=metadata.supdrop or 0 - parameters[19]=metadata.subdrop or 0 - parameters[20], - parameters[21]=unpack(metadata.delim or dummy) - parameters[22]=metadata.axisheight or 0 - end - parameters.designsize=(metadata.designsize or 10)*65536 - parameters.ascender=abs(metadata.ascender or 0) - parameters.descender=abs(metadata.descender or 0) - parameters.units=1000 - properties.spacer=spacer - properties.encodingbytes=2 - properties.format=fonts.formats[filename] or "type1" - properties.filename=filename - properties.fontname=fontname - properties.fullname=fullname - properties.psname=fullname - properties.name=filename or fullname or fontname - if next(characters) then - return { - characters=characters, - descriptions=descriptions, - parameters=parameters, - resources=resources, - properties=properties, - goodies=goodies, - } - end - end - return nil -end -function afm.setfeatures(tfmdata,features) - local okay=constructors.initializefeatures("afm",tfmdata,features,trace_features,report_afm) - if okay then - return constructors.collectprocessors("afm",tfmdata,features,trace_features,report_afm) - else - return {} - end -end -local function addtables(data) - local resources=data.resources - local lookuptags=resources.lookuptags - local unicodes=resources.unicodes - if not lookuptags then - lookuptags={} - resources.lookuptags=lookuptags - end - setmetatableindex(lookuptags,function(t,k) - local v=type(k)=="number" and ("lookup "..k) or k - t[k]=v - return v - end) - if not unicodes then - unicodes={} - resources.unicodes=unicodes - setmetatableindex(unicodes,function(t,k) - setmetatableindex(unicodes,nil) - for u,d in next,data.descriptions do - local n=d.name - if n then - t[n]=u - end - end - return rawget(t,k) - end) - end - constructors.addcoreunicodes(unicodes) -end -local function afmtotfm(specification) - local afmname=specification.filename or specification.name - if specification.forced=="afm" or specification.format=="afm" then - if trace_loading then - report_afm("forcing afm format for %a",afmname) - end - else - local tfmname=findbinfile(afmname,"ofm") or "" - if tfmname~="" then - if trace_loading then - report_afm("fallback from afm to tfm for %a",afmname) - end - return - end - end - if afmname~="" then - local features=constructors.checkedfeatures("afm",specification.features.normal) - specification.features.normal=features - constructors.hashinstance(specification,true) - specification=definers.resolve(specification) - local cache_id=specification.hash - local tfmdata=containers.read(constructors.cache,cache_id) - if not tfmdata then - local rawdata=afm.load(afmname) - if rawdata and next(rawdata) then - addtables(rawdata) - adddimensions(rawdata) - tfmdata=copytotfm(rawdata) - if tfmdata and next(tfmdata) then - local shared=tfmdata.shared - if not shared then - shared={} - tfmdata.shared=shared - end - shared.rawdata=rawdata - shared.dynamics={} - tfmdata.changed={} - shared.features=features - shared.processes=afm.setfeatures(tfmdata,features) - end - elseif trace_loading then - report_afm("no (valid) afm file found with name %a",afmname) - end - tfmdata=containers.write(constructors.cache,cache_id,tfmdata) - end - return tfmdata - end -end -local function read_from_afm(specification) - local tfmdata=afmtotfm(specification) - if tfmdata then - tfmdata.properties.name=specification.name - tfmdata=constructors.scale(tfmdata,specification) - local allfeatures=tfmdata.shared.features or specification.features.normal - constructors.applymanipulators("afm",tfmdata,allfeatures,trace_features,report_afm) - fonts.loggers.register(tfmdata,'afm',specification) - end - return tfmdata -end -registerafmfeature { - name="mode", - description="mode", - initializers={ - base=otf.modeinitializer, - node=otf.modeinitializer, - } -} -registerafmfeature { - name="features", - description="features", - default=true, - initializers={ - node=otf.nodemodeinitializer, - base=otf.basemodeinitializer, - }, - processors={ - node=otf.featuresprocessor, - } -} -fonts.formats.afm="type1" -fonts.formats.pfb="type1" -local function check_afm(specification,fullname) - local foundname=findbinfile(fullname,'afm') or "" - if foundname=="" then - foundname=fonts.names.getfilename(fullname,"afm") or "" - end - if foundname=="" and afm.autoprefixed then - local encoding,shortname=match(fullname,"^(.-)%-(.*)$") - if encoding and shortname and fonts.encodings.known[encoding] then - shortname=findbinfile(shortname,'afm') or "" - if shortname~="" then - foundname=shortname - if trace_defining then - report_afm("stripping encoding prefix from filename %a",afmname) - end - end - end - end - if foundname~="" then - specification.filename=foundname - specification.format="afm" - return read_from_afm(specification) - end -end -function readers.afm(specification,method) - local fullname=specification.filename or "" - local tfmdata=nil - if fullname=="" then - local forced=specification.forced or "" - if forced~="" then - tfmdata=check_afm(specification,specification.name.."."..forced) - end - if not tfmdata then - local check_tfm=readers.check_tfm - method=(check_tfm and (method or definers.method or "afm or tfm")) or "afm" - if method=="tfm" then - tfmdata=check_tfm(specification,specification.name) - elseif method=="afm" then - tfmdata=check_afm(specification,specification.name) - elseif method=="tfm or afm" then - tfmdata=check_tfm(specification,specification.name) or check_afm(specification,specification.name) - else - tfmdata=check_afm(specification,specification.name) or check_tfm(specification,specification.name) - end - end - else - tfmdata=check_afm(specification,fullname) - end - return tfmdata -end -function readers.pfb(specification,method) - local original=specification.specification - if trace_defining then - report_afm("using afm reader for %a",original) - end - specification.forced="afm" - local function swap(name) - local value=specification[swap] - if value then - specification[swap]=gsub("%.pfb",".afm",1) - end - end - swap("filename") - swap("fullname") - swap("forcedname") - swap("specification") - return readers.afm(specification,method) -end -registerafmenhancer("unify names",enhance_unify_names) -registerafmenhancer("add ligatures",enhance_add_ligatures) -registerafmenhancer("add extra kerns",enhance_add_extra_kerns) -registerafmenhancer("normalize features",enhance_normalize_features) -registerafmenhancer("check extra features",otfenhancers.enhance) -registerafmenhancer("fix names",enhance_fix_names) - -end --- [luaotfload, fontloader-2017-02-11.lua scope for “font-one”] --- - - -do --- [luaotfload, fontloader-2017-02-11.lua scope for “font-afk” b36a76ceb835f41f8c05b471000ddc14] --- - -if not modules then modules={} end modules ['font-afk']={ - version=1.001, - comment="companion to font-afm.lua", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files", - dataonly=true, -} -local allocate=utilities.storage.allocate -fonts.handlers.afm.helpdata={ - ligatures=allocate { - ['f']={ - { 'f','ff' }, - { 'i','fi' }, - { 'l','fl' }, - }, - ['ff']={ - { 'i','ffi' } - }, - ['fi']={ - { 'i','fii' } - }, - ['fl']={ - { 'i','fli' } - }, - ['s']={ - { 't','st' } - }, - ['i']={ - { 'j','ij' } - }, - }, - texligatures=allocate { - ['quoteleft']={ - { 'quoteleft','quotedblleft' } - }, - ['quoteright']={ - { 'quoteright','quotedblright' } - }, - ['hyphen']={ - { 'hyphen','endash' } - }, - ['endash']={ - { 'hyphen','emdash' } - } - }, - leftkerned=allocate { - AEligature="A",aeligature="a", - OEligature="O",oeligature="o", - IJligature="I",ijligature="i", - AE="A",ae="a", - OE="O",oe="o", - IJ="I",ij="i", - Ssharp="S",ssharp="s", - }, - rightkerned=allocate { - AEligature="E",aeligature="e", - OEligature="E",oeligature="e", - IJligature="J",ijligature="j", - AE="E",ae="e", - OE="E",oe="e", - IJ="J",ij="j", - Ssharp="S",ssharp="s", - }, - bothkerned=allocate { - Acircumflex="A",acircumflex="a", - Ccircumflex="C",ccircumflex="c", - Ecircumflex="E",ecircumflex="e", - Gcircumflex="G",gcircumflex="g", - Hcircumflex="H",hcircumflex="h", - Icircumflex="I",icircumflex="i", - Jcircumflex="J",jcircumflex="j", - Ocircumflex="O",ocircumflex="o", - Scircumflex="S",scircumflex="s", - Ucircumflex="U",ucircumflex="u", - Wcircumflex="W",wcircumflex="w", - Ycircumflex="Y",ycircumflex="y", - Agrave="A",agrave="a", - Egrave="E",egrave="e", - Igrave="I",igrave="i", - Ograve="O",ograve="o", - Ugrave="U",ugrave="u", - Ygrave="Y",ygrave="y", - Atilde="A",atilde="a", - Itilde="I",itilde="i", - Otilde="O",otilde="o", - Utilde="U",utilde="u", - Ntilde="N",ntilde="n", - Adiaeresis="A",adiaeresis="a",Adieresis="A",adieresis="a", - Ediaeresis="E",ediaeresis="e",Edieresis="E",edieresis="e", - Idiaeresis="I",idiaeresis="i",Idieresis="I",idieresis="i", - Odiaeresis="O",odiaeresis="o",Odieresis="O",odieresis="o", - Udiaeresis="U",udiaeresis="u",Udieresis="U",udieresis="u", - Ydiaeresis="Y",ydiaeresis="y",Ydieresis="Y",ydieresis="y", - Aacute="A",aacute="a", - Cacute="C",cacute="c", - Eacute="E",eacute="e", - Iacute="I",iacute="i", - Lacute="L",lacute="l", - Nacute="N",nacute="n", - Oacute="O",oacute="o", - Racute="R",racute="r", - Sacute="S",sacute="s", - Uacute="U",uacute="u", - Yacute="Y",yacute="y", - Zacute="Z",zacute="z", - Dstroke="D",dstroke="d", - Hstroke="H",hstroke="h", - Tstroke="T",tstroke="t", - Cdotaccent="C",cdotaccent="c", - Edotaccent="E",edotaccent="e", - Gdotaccent="G",gdotaccent="g", - Idotaccent="I",idotaccent="i", - Zdotaccent="Z",zdotaccent="z", - Amacron="A",amacron="a", - Emacron="E",emacron="e", - Imacron="I",imacron="i", - Omacron="O",omacron="o", - Umacron="U",umacron="u", - Ccedilla="C",ccedilla="c", - Kcedilla="K",kcedilla="k", - Lcedilla="L",lcedilla="l", - Ncedilla="N",ncedilla="n", - Rcedilla="R",rcedilla="r", - Scedilla="S",scedilla="s", - Tcedilla="T",tcedilla="t", - Ohungarumlaut="O",ohungarumlaut="o", - Uhungarumlaut="U",uhungarumlaut="u", - Aogonek="A",aogonek="a", - Eogonek="E",eogonek="e", - Iogonek="I",iogonek="i", - Uogonek="U",uogonek="u", - Aring="A",aring="a", - Uring="U",uring="u", - Abreve="A",abreve="a", - Ebreve="E",ebreve="e", - Gbreve="G",gbreve="g", - Ibreve="I",ibreve="i", - Obreve="O",obreve="o", - Ubreve="U",ubreve="u", - Ccaron="C",ccaron="c", - Dcaron="D",dcaron="d", - Ecaron="E",ecaron="e", - Lcaron="L",lcaron="l", - Ncaron="N",ncaron="n", - Rcaron="R",rcaron="r", - Scaron="S",scaron="s", - Tcaron="T",tcaron="t", - Zcaron="Z",zcaron="z", - dotlessI="I",dotlessi="i", - dotlessJ="J",dotlessj="j", - AEligature="AE",aeligature="ae",AE="AE",ae="ae", - OEligature="OE",oeligature="oe",OE="OE",oe="oe", - IJligature="IJ",ijligature="ij",IJ="IJ",ij="ij", - Lstroke="L",lstroke="l",Lslash="L",lslash="l", - Ostroke="O",ostroke="o",Oslash="O",oslash="o", - Ssharp="SS",ssharp="ss", - Aumlaut="A",aumlaut="a", - Eumlaut="E",eumlaut="e", - Iumlaut="I",iumlaut="i", - Oumlaut="O",oumlaut="o", - Uumlaut="U",uumlaut="u", - } -} - -end --- [luaotfload, fontloader-2017-02-11.lua scope for “font-afk”] --- - - -do --- [luaotfload, fontloader-2017-02-11.lua scope for “font-tfm” 3d813578dbf6c447e4b859c2bf0618f7] --- - -if not modules then modules={} end modules ['font-tfm']={ - version=1.001, - comment="companion to font-ini.mkiv", - 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 match,format=string.match,string.format -local concat,sortedhash=table.concat,table.sortedhash -local trace_defining=false trackers.register("fonts.defining",function(v) trace_defining=v end) -local trace_features=false trackers.register("tfm.features",function(v) trace_features=v end) -local report_defining=logs.reporter("fonts","defining") -local report_tfm=logs.reporter("fonts","tfm loading") -local findbinfile=resolvers.findbinfile -local setmetatableindex=table.setmetatableindex -local fonts=fonts -local handlers=fonts.handlers -local readers=fonts.readers -local constructors=fonts.constructors -local encodings=fonts.encodings -local tfm=constructors.handlers.tfm -tfm.version=1.000 -tfm.maxnestingdepth=5 -tfm.maxnestingsize=65536*1024 -local otf=fonts.handlers.otf -local otfenhancers=otf.enhancers -local tfmfeatures=constructors.features.tfm -local registertfmfeature=tfmfeatures.register -local tfmenhancers=constructors.enhancers.tfm -local registertfmenhancer=tfmenhancers.register -constructors.resolvevirtualtoo=false -fonts.formats.tfm="type1" -fonts.formats.ofm="type1" -function tfm.setfeatures(tfmdata,features) - local okay=constructors.initializefeatures("tfm",tfmdata,features,trace_features,report_tfm) - if okay then - return constructors.collectprocessors("tfm",tfmdata,features,trace_features,report_tfm) - else - return {} - end -end -local depth={} -local function read_from_tfm(specification) - local filename=specification.filename - local size=specification.size - depth[filename]=(depth[filename] or 0)+1 - if trace_defining then - report_defining("loading tfm file %a at size %s",filename,size) - end - local tfmdata=font.read_tfm(filename,size) - if tfmdata then - local features=specification.features and specification.features.normal or {} - local features=constructors.checkedfeatures("tfm",features) - specification.features.normal=features - local newtfmdata=(depth[filename]==1) and tfm.reencode(tfmdata,specification) - if newtfmdata then - tfmdata=newtfmdata - end - local resources=tfmdata.resources or {} - local properties=tfmdata.properties or {} - local parameters=tfmdata.parameters or {} - local shared=tfmdata.shared or {} - shared.features=features - shared.resources=resources - properties.name=tfmdata.name - properties.fontname=tfmdata.fontname - properties.psname=tfmdata.psname - properties.fullname=tfmdata.fullname - properties.filename=specification.filename - properties.format=fonts.formats.tfm - tfmdata.properties=properties - tfmdata.resources=resources - tfmdata.parameters=parameters - tfmdata.shared=shared - shared.rawdata={ resources=resources } - shared.features=features - if newtfmdata then - if not resources.marks then - resources.marks={} - end - if not resources.sequences then - resources.sequences={} - end - if not resources.features then - resources.features={ - gsub={}, - gpos={}, - } - end - if not tfmdata.changed then - tfmdata.changed={} - end - if not tfmdata.descriptions then - tfmdata.descriptions=tfmdata.characters - end - otf.readers.addunicodetable(tfmdata) - tfmenhancers.apply(tfmdata,filename) - constructors.applymanipulators("tfm",tfmdata,features,trace_features,report_tfm) - otf.readers.unifymissing(tfmdata) - fonts.mappings.addtounicode(tfmdata,filename) - tfmdata.tounicode=1 - local tounicode=fonts.mappings.tounicode - for unicode,v in next,tfmdata.characters do - local u=v.unicode - if u then - v.tounicode=tounicode(u) - end - end - if tfmdata.usedbitmap then - tfm.addtounicode(tfmdata) - end - end - shared.processes=next(features) and tfm.setfeatures(tfmdata,features) or nil - parameters.factor=1 - parameters.size=size - parameters.slant=parameters.slant or parameters[1] or 0 - parameters.space=parameters.space or parameters[2] or 0 - parameters.space_stretch=parameters.space_stretch or parameters[3] or 0 - parameters.space_shrink=parameters.space_shrink or parameters[4] or 0 - parameters.x_height=parameters.x_height or parameters[5] or 0 - parameters.quad=parameters.quad or parameters[6] or 0 - parameters.extra_space=parameters.extra_space or parameters[7] or 0 - constructors.enhanceparameters(parameters) - if newtfmdata then - elseif constructors.resolvevirtualtoo then - fonts.loggers.register(tfmdata,file.suffix(filename),specification) - local vfname=findbinfile(specification.name,'ovf') - if vfname and vfname~="" then - local vfdata=font.read_vf(vfname,size) - if vfdata then - local chars=tfmdata.characters - for k,v in next,vfdata.characters do - chars[k].commands=v.commands - end - properties.virtualized=true - tfmdata.fonts=vfdata.fonts - tfmdata.type="virtual" - local fontlist=vfdata.fonts - local name=file.nameonly(filename) - for i=1,#fontlist do - local n=fontlist[i].name - local s=fontlist[i].size - local d=depth[filename] - s=constructors.scaled(s,vfdata.designsize) - if d>tfm.maxnestingdepth then - report_defining("too deeply nested virtual font %a with size %a, max nesting depth %s",n,s,tfm.maxnestingdepth) - fontlist[i]={ id=0 } - elseif (d>1) and (s>tfm.maxnestingsize) then - report_defining("virtual font %a exceeds size %s",n,s) - fontlist[i]={ id=0 } - else - local t,id=fonts.constructors.readanddefine(n,s) - fontlist[i]={ id=id } - end - end - end - end - end - properties.haskerns=true - properties.hasligatures=true - resources.unicodes={} - resources.lookuptags={} - depth[filename]=depth[filename]-1 - return tfmdata - else - depth[filename]=depth[filename]-1 - end -end -local function check_tfm(specification,fullname) - local foundname=findbinfile(fullname,'tfm') or "" - if foundname=="" then - foundname=findbinfile(fullname,'ofm') or "" - end - if foundname=="" then - foundname=fonts.names.getfilename(fullname,"tfm") or "" - end - if foundname~="" then - specification.filename=foundname - specification.format="ofm" - return read_from_tfm(specification) - elseif trace_defining then - report_defining("loading tfm with name %a fails",specification.name) - end -end -readers.check_tfm=check_tfm -function readers.tfm(specification) - local fullname=specification.filename or "" - if fullname=="" then - local forced=specification.forced or "" - if forced~="" then - fullname=specification.name.."."..forced - else - fullname=specification.name - end - end - return check_tfm(specification,fullname) -end -readers.ofm=readers.tfm -do - local outfiles={} - local tfmcache=table.setmetatableindex(function(t,tfmdata) - local id=font.define(tfmdata) - t[tfmdata]=id - return id - end) - local encdone=table.setmetatableindex("table") - function tfm.reencode(tfmdata,specification) - local features=specification.features - if not features then - return - end - local features=features.normal - if not features then - return - end - local tfmfile=file.basename(tfmdata.name) - local encfile=features.reencode - local pfbfile=features.pfbfile - local bitmap=features.bitmap - if not encfile then - return - end - local pfbfile=outfiles[tfmfile] - if pfbfile==nil then - if bitmap then - pfbfile=false - elseif type(pfbfile)~="string" then - pfbfile=tfmfile - end - if type(pfbfile)=="string" then - pfbfile=file.addsuffix(pfbfile,"pfb") - report_tfm("using type1 shapes from %a for %a",pfbfile,tfmfile) - else - report_tfm("using bitmap shapes for %a",tfmfile) - pfbfile=false - end - outfiles[tfmfile]=pfbfile - end - local encoding=false - local vector=false - if type(pfbfile)=="string" then - local pfb=fonts.constructors.handlers.pfb - if pfb and pfb.loadvector then - local v,e=pfb.loadvector(pfbfile) - if v then - vector=v - end - if e then - encoding=e - end - end - end - if type(encfile)=="string" and encfile~="auto" then - encoding=fonts.encodings.load(file.addsuffix(encfile,"enc")) - if encoding then - encoding=encoding.vector - end - end - if not encoding then - report_tfm("bad encoding for %a, quitting",tfmfile) - return - end - local unicoding=fonts.encodings.agl and fonts.encodings.agl.unicodes - local virtualid=tfmcache[tfmdata] - local tfmdata=table.copy(tfmdata) - local characters={} - local originals=tfmdata.characters - local indices={} - local parentfont={ "font",1 } - local private=fonts.constructors.privateoffset - local reported=encdone[tfmfile][encfile] - local backmap=vector and table.swapped(vector) - local done={} - for index,name in sortedhash(encoding) do - local unicode=unicoding[name] - local original=originals[index] - if original then - if unicode then - original.unicode=unicode - else - unicode=private - private=private+1 - if not reported then - report_tfm("glyph %a in font %a with encoding %a gets unicode %U",name,tfmfile,encfile,unicode) - end - end - characters[unicode]=original - indices[index]=unicode - original.name=name - if backmap then - original.index=backmap[name] - else - original.commands={ parentfont,{ "char",index } } - original.oindex=index - end - done[name]=true - elseif not done[name] then - report_tfm("bad index %a in font %a with name %a",index,tfmfile,name) - end - end - encdone[tfmfile][encfile]=true - for k,v in next,characters do - local kerns=v.kerns - if kerns then - local t={} - for k,v in next,kerns do - local i=indices[k] - if i then - t[i]=v - end - end - v.kerns=next(t) and t or nil - end - local ligatures=v.ligatures - if ligatures then - local t={} - for k,v in next,ligatures do - local i=indices[k] - if i then - t[i]=v - v.char=indices[v.char] - end - end - v.ligatures=next(t) and t or nil - end - end - tfmdata.fonts={ { id=virtualid } } - tfmdata.characters=characters - tfmdata.fullname=tfmdata.fullname or tfmdata.name - tfmdata.psname=file.nameonly(pfbfile or tfmdata.name) - tfmdata.filename=pfbfile - tfmdata.encodingbytes=2 - tfmdata.format="type1" - tfmdata.tounicode=1 - tfmdata.embedding="subset" - tfmdata.usedbitmap=bitmap and virtualid - return tfmdata - end -end -do - local template=[[ -/CIDInit /ProcSet findresource begin - 12 dict begin - begincmap - /CIDSystemInfo << /Registry (TeX) /Ordering (bitmap-%s) /Supplement 0 >> def - /CMapName /TeX-bitmap-%s def - /CMapType 2 def - 1 begincodespacerange - <00> <FF> - endcodespacerange - %s beginbfchar -%s - endbfchar - endcmap -CMapName currentdict /CMap defineresource pop end -end -end -]] - local flushstreamobject=lpdf and lpdf.flushstreamobject - local setfontattributes=pdf.setfontattributes - if not flushstreamobject then - flushstreamobject=function(data) - return pdf.obj { - immediate=true, - type="stream", - string=data, - } - end - end - if not setfontattributes then - setfontattributes=function(id,data) - print(format("your luatex is too old so no tounicode bitmap font%i",id)) - end - end - function tfm.addtounicode(tfmdata) - local id=tfmdata.usedbitmap - local map={} - local char={} - for k,v in next,tfmdata.characters do - local index=v.oindex - local tounicode=v.tounicode - if index and tounicode then - map[index]=tounicode - end - end - for k,v in sortedhash(map) do - char[#char+1]=format("<%02X> <%s>",k,v) - end - char=concat(char,"\n") - local stream=format(template,id,id,#char,char) - local reference=flushstreamobject(stream,nil,true) - setfontattributes(id,format("/ToUnicode %i 0 R",reference)) - end -end -do - local everywhere={ ["*"]={ ["*"]=true } } - local noflags={ false,false,false,false } - local function enhance_normalize_features(data) - local ligatures=setmetatableindex("table") - local kerns=setmetatableindex("table") - local characters=data.characters - for u,c in next,characters do - local l=c.ligatures - local k=c.kerns - if l then - ligatures[u]=l - for u,v in next,l do - l[u]={ ligature=v.char } - end - c.ligatures=nil - end - if k then - kerns[u]=k - for u,v in next,k do - k[u]=v - end - c.kerns=nil - end - end - for u,l in next,ligatures do - for k,v in next,l do - local vl=v.ligature - local dl=ligatures[vl] - if dl then - for kk,vv in next,dl do - v[kk]=vv - end - end - end - end - local features={ - gpos={}, - gsub={}, - } - local sequences={ - } - if next(ligatures) then - features.gsub.liga=everywhere - data.properties.hasligatures=true - sequences[#sequences+1]={ - features={ - liga=everywhere, - }, - flags=noflags, - name="s_s_0", - nofsteps=1, - order={ "liga" }, - type="gsub_ligature", - steps={ - { - coverage=ligatures, - }, - }, - } - end - if next(kerns) then - features.gpos.kern=everywhere - data.properties.haskerns=true - sequences[#sequences+1]={ - features={ - kern=everywhere, - }, - flags=noflags, - name="p_s_0", - nofsteps=1, - order={ "kern" }, - type="gpos_pair", - steps={ - { - format="kern", - coverage=kerns, - }, - }, - } - end - data.resources.features=features - data.resources.sequences=sequences - data.shared.resources=data.shared.resources or resources - end - registertfmenhancer("normalize features",enhance_normalize_features) - registertfmenhancer("check extra features",otfenhancers.enhance) -end -registertfmfeature { - name="mode", - description="mode", - initializers={ - base=otf.modeinitializer, - node=otf.modeinitializer, - } -} -registertfmfeature { - name="features", - description="features", - default=true, - initializers={ - base=otf.basemodeinitializer, - node=otf.nodemodeinitializer, - }, - processors={ - node=otf.featuresprocessor, - } -} - -end --- [luaotfload, fontloader-2017-02-11.lua scope for “font-tfm”] --- - - -do --- [luaotfload, fontloader-2017-02-11.lua scope for “font-lua” 1fbfdf7b689b2bdfd0e3bb9bf74ce136] --- - -if not modules then modules={} end modules ['font-lua']={ - version=1.001, - comment="companion to font-ini.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local trace_defining=false trackers.register("fonts.defining",function(v) trace_defining=v end) -local report_lua=logs.reporter("fonts","lua loading") -local fonts=fonts -local readers=fonts.readers -fonts.formats.lua="lua" -local function check_lua(specification,fullname) - local fullname=resolvers.findfile(fullname) or "" - if fullname~="" then - local loader=loadfile(fullname) - loader=loader and loader() - return loader and loader(specification) - end -end -readers.check_lua=check_lua -function readers.lua(specification) - local original=specification.specification - if trace_defining then - report_lua("using lua reader for %a",original) - end - local fullname=specification.filename or "" - if fullname=="" then - local forced=specification.forced or "" - if forced~="" then - fullname=specification.name.."."..forced - else - fullname=specification.name - end - end - return check_lua(specification,fullname) -end - -end --- [luaotfload, fontloader-2017-02-11.lua scope for “font-lua”] --- - - -do --- [luaotfload, fontloader-2017-02-11.lua scope for “font-def” 49fa2b50d8d2a1bb70b08b72f858ecd0] --- - -if not modules then modules={} end modules ['font-def']={ - version=1.001, - comment="companion to font-ini.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local lower,gsub=string.lower,string.gsub -local tostring,next=tostring,next -local lpegmatch=lpeg.match -local suffixonly,removesuffix=file.suffix,file.removesuffix -local formatters=string.formatters -local allocate=utilities.storage.allocate -local trace_defining=false trackers .register("fonts.defining",function(v) trace_defining=v end) -local directive_embedall=false directives.register("fonts.embedall",function(v) directive_embedall=v end) -trackers.register("fonts.loading","fonts.defining","otf.loading","afm.loading","tfm.loading") -trackers.register("fonts.all","fonts.*","otf.*","afm.*","tfm.*") -local report_defining=logs.reporter("fonts","defining") -local fonts=fonts -local fontdata=fonts.hashes.identifiers -local readers=fonts.readers -local definers=fonts.definers -local specifiers=fonts.specifiers -local constructors=fonts.constructors -local fontgoodies=fonts.goodies -readers.sequence=allocate { 'otf','ttf','afm','tfm','lua' } -local variants=allocate() -specifiers.variants=variants -definers.methods=definers.methods or {} -local internalized=allocate() -local lastdefined=nil -local loadedfonts=constructors.loadedfonts -local designsizes=constructors.designsizes -local resolvefile=fontgoodies and fontgoodies.filenames and fontgoodies.filenames.resolve or function(s) return s end -local splitter,splitspecifiers=nil,"" -local P,C,S,Cc=lpeg.P,lpeg.C,lpeg.S,lpeg.Cc -local left=P("(") -local right=P(")") -local colon=P(":") -local space=P(" ") -definers.defaultlookup="file" -local prefixpattern=P(false) -local function addspecifier(symbol) - splitspecifiers=splitspecifiers..symbol - local method=S(splitspecifiers) - local lookup=C(prefixpattern)*colon - local sub=left*C(P(1-left-right-method)^1)*right - local specification=C(method)*C(P(1)^1) - local name=C((1-sub-specification)^1) - splitter=P((lookup+Cc(""))*name*(sub+Cc(""))*(specification+Cc(""))) -end -local function addlookup(str,default) - prefixpattern=prefixpattern+P(str) -end -definers.addlookup=addlookup -addlookup("file") -addlookup("name") -addlookup("spec") -local function getspecification(str) - return lpegmatch(splitter,str or "") -end -definers.getspecification=getspecification -function definers.registersplit(symbol,action,verbosename) - addspecifier(symbol) - variants[symbol]=action - if verbosename then - variants[verbosename]=action - end -end -local function makespecification(specification,lookup,name,sub,method,detail,size) - size=size or 655360 - if not lookup or lookup=="" then - lookup=definers.defaultlookup - end - if trace_defining then - report_defining("specification %a, lookup %a, name %a, sub %a, method %a, detail %a", - specification,lookup,name,sub,method,detail) - end - local t={ - lookup=lookup, - specification=specification, - size=size, - name=name, - sub=sub, - method=method, - detail=detail, - resolved="", - forced="", - features={}, - } - return t -end -definers.makespecification=makespecification -function definers.analyze(specification,size) - local lookup,name,sub,method,detail=getspecification(specification or "") - return makespecification(specification,lookup,name,sub,method,detail,size) -end -definers.resolvers=definers.resolvers or {} -local resolvers=definers.resolvers -function resolvers.file(specification) - local name=resolvefile(specification.name) - local suffix=lower(suffixonly(name)) - if fonts.formats[suffix] then - specification.forced=suffix - specification.forcedname=name - specification.name=removesuffix(name) - else - specification.name=name - end -end -function resolvers.name(specification) - local resolve=fonts.names.resolve - if resolve then - local resolved,sub,subindex=resolve(specification.name,specification.sub,specification) - if resolved then - specification.resolved=resolved - specification.sub=sub - specification.subindex=subindex - local suffix=lower(suffixonly(resolved)) - if fonts.formats[suffix] then - specification.forced=suffix - specification.forcedname=resolved - specification.name=removesuffix(resolved) - else - specification.name=resolved - end - end - else - resolvers.file(specification) - end -end -function resolvers.spec(specification) - local resolvespec=fonts.names.resolvespec - if resolvespec then - local resolved,sub,subindex=resolvespec(specification.name,specification.sub,specification) - if resolved then - specification.resolved=resolved - specification.sub=sub - specification.subindex=subindex - specification.forced=lower(suffixonly(resolved)) - specification.forcedname=resolved - specification.name=removesuffix(resolved) - end - else - resolvers.name(specification) - end -end -function definers.resolve(specification) - if not specification.resolved or specification.resolved=="" then - local r=resolvers[specification.lookup] - if r then - r(specification) - end - end - if specification.forced=="" then - specification.forced=nil - specification.forcedname=nil - end - specification.hash=lower(specification.name..' @ '..constructors.hashfeatures(specification)) - if specification.sub and specification.sub~="" then - specification.hash=specification.sub..' @ '..specification.hash - end - return specification -end -function definers.applypostprocessors(tfmdata) - local postprocessors=tfmdata.postprocessors - if postprocessors then - local properties=tfmdata.properties - for i=1,#postprocessors do - local extrahash=postprocessors[i](tfmdata) - if type(extrahash)=="string" and extrahash~="" then - extrahash=gsub(lower(extrahash),"[^a-z]","-") - properties.fullname=formatters["%s-%s"](properties.fullname,extrahash) - end - end - end - return tfmdata -end -local function checkembedding(tfmdata) - local properties=tfmdata.properties - local embedding - if directive_embedall then - embedding="full" - elseif properties and properties.filename and constructors.dontembed[properties.filename] then - embedding="no" - else - embedding="subset" - end - if properties then - properties.embedding=embedding - else - tfmdata.properties={ embedding=embedding } - end - tfmdata.embedding=embedding -end -function definers.loadfont(specification) - local hash=constructors.hashinstance(specification) - local tfmdata=loadedfonts[hash] - if not tfmdata then - local forced=specification.forced or "" - if forced~="" then - local reader=readers[lower(forced)] - tfmdata=reader and reader(specification) - if not tfmdata then - report_defining("forced type %a of %a not found",forced,specification.name) - end - else - local sequence=readers.sequence - for s=1,#sequence do - local reader=sequence[s] - if readers[reader] then - if trace_defining then - report_defining("trying (reader sequence driven) type %a for %a with file %a",reader,specification.name,specification.filename) - end - tfmdata=readers[reader](specification) - if tfmdata then - break - else - specification.filename=nil - end - end - end - end - if tfmdata then - tfmdata=definers.applypostprocessors(tfmdata) - checkembedding(tfmdata) - loadedfonts[hash]=tfmdata - designsizes[specification.hash]=tfmdata.parameters.designsize - end - end - if not tfmdata then - report_defining("font with asked name %a is not found using lookup %a",specification.name,specification.lookup) - end - return tfmdata -end -function constructors.checkvirtualids() -end -function constructors.readanddefine(name,size) - local specification=definers.analyze(name,size) - local method=specification.method - if method and variants[method] then - specification=variants[method](specification) - end - specification=definers.resolve(specification) - local hash=constructors.hashinstance(specification) - local id=definers.registered(hash) - if not id then - local tfmdata=definers.loadfont(specification) - if tfmdata then - tfmdata.properties.hash=hash - constructors.checkvirtualids(tfmdata) - id=font.define(tfmdata) - definers.register(tfmdata,id) - else - id=0 - end - end - return fontdata[id],id -end -function definers.current() - return lastdefined -end -function definers.registered(hash) - local id=internalized[hash] - return id,id and fontdata[id] -end -function definers.register(tfmdata,id) - if tfmdata and id then - local hash=tfmdata.properties.hash - if not hash then - report_defining("registering font, id %a, name %a, invalid hash",id,tfmdata.properties.filename or "?") - elseif not internalized[hash] then - internalized[hash]=id - if trace_defining then - report_defining("registering font, id %s, hash %a",id,hash) - end - fontdata[id]=tfmdata - end - end -end -function definers.read(specification,size,id) - statistics.starttiming(fonts) - if type(specification)=="string" then - specification=definers.analyze(specification,size) - end - local method=specification.method - if method and variants[method] then - specification=variants[method](specification) - end - specification=definers.resolve(specification) - local hash=constructors.hashinstance(specification) - local tfmdata=definers.registered(hash) - if tfmdata then - if trace_defining then - report_defining("already hashed: %s",hash) - end - else - tfmdata=definers.loadfont(specification) - if tfmdata then - if trace_defining then - report_defining("loaded and hashed: %s",hash) - end - tfmdata.properties.hash=hash - if id then - definers.register(tfmdata,id) - end - else - if trace_defining then - report_defining("not loaded and hashed: %s",hash) - end - end - end - lastdefined=tfmdata or id - if not tfmdata then - report_defining("unknown font %a, loading aborted",specification.name) - elseif trace_defining and type(tfmdata)=="table" then - local properties=tfmdata.properties or {} - local parameters=tfmdata.parameters or {} - report_defining("using %a font with id %a, name %a, size %a, bytes %a, encoding %a, fullname %a, filename %a", - properties.format or "unknown",id,properties.name,parameters.size,properties.encodingbytes, - properties.encodingname,properties.fullname,file.basename(properties.filename)) - end - statistics.stoptiming(fonts) - return tfmdata -end -function font.getfont(id) - return fontdata[id] -end -callbacks.register('define_font',definers.read,"definition of fonts (tfmdata preparation)") - -end --- [luaotfload, fontloader-2017-02-11.lua scope for “font-def”] --- - - -do --- [luaotfload, fontloader-2017-02-11.lua scope for “fonts-ext” aff3846f4c1f15de0a9f4fd7081e0c68] --- - -if not modules then modules={} end modules ['luatex-fonts-ext']={ - version=1.001, - comment="companion to luatex-*.tex", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -if context then - texio.write_nl("fatal error: this module is not for context") - os.exit() -end -local fonts=fonts -local otffeatures=fonts.constructors.features.otf -local function initializeitlc(tfmdata,value) - if value then - local parameters=tfmdata.parameters - local italicangle=parameters.italicangle - if italicangle and italicangle~=0 then - local properties=tfmdata.properties - local factor=tonumber(value) or 1 - properties.hasitalics=true - properties.autoitalicamount=factor*(parameters.uwidth or 40)/2 - end - end -end -otffeatures.register { - name="itlc", - description="italic correction", - initializers={ - base=initializeitlc, - node=initializeitlc, - } -} -local function initializeslant(tfmdata,value) - value=tonumber(value) - if not value then - value=0 - elseif value>1 then - value=1 - elseif value<-1 then - value=-1 - end - tfmdata.parameters.slantfactor=value -end -otffeatures.register { - name="slant", - description="slant glyphs", - initializers={ - base=initializeslant, - node=initializeslant, - } -} -local function initializeextend(tfmdata,value) - value=tonumber(value) - if not value then - value=0 - elseif value>10 then - value=10 - elseif value<-10 then - value=-10 - end - tfmdata.parameters.extendfactor=value -end -otffeatures.register { - name="extend", - description="scale glyphs horizontally", - initializers={ - base=initializeextend, - node=initializeextend, - } -} -fonts.protrusions=fonts.protrusions or {} -fonts.protrusions.setups=fonts.protrusions.setups or {} -local setups=fonts.protrusions.setups -local function initializeprotrusion(tfmdata,value) - if value then - local setup=setups[value] - if setup then - local factor,left,right=setup.factor or 1,setup.left or 1,setup.right or 1 - local emwidth=tfmdata.parameters.quad - tfmdata.parameters.protrusion={ - auto=true, - } - for i,chr in next,tfmdata.characters do - local v,pl,pr=setup[i],nil,nil - if v then - pl,pr=v[1],v[2] - end - if pl and pl~=0 then chr.left_protruding=left*pl*factor end - if pr and pr~=0 then chr.right_protruding=right*pr*factor end - end - end - end -end -otffeatures.register { - name="protrusion", - description="shift characters into the left and or right margin", - initializers={ - base=initializeprotrusion, - node=initializeprotrusion, - } -} -fonts.expansions=fonts.expansions or {} -fonts.expansions.setups=fonts.expansions.setups or {} -local setups=fonts.expansions.setups -local function initializeexpansion(tfmdata,value) - if value then - local setup=setups[value] - if setup then - local factor=setup.factor or 1 - tfmdata.parameters.expansion={ - stretch=10*(setup.stretch or 0), - shrink=10*(setup.shrink or 0), - step=10*(setup.step or 0), - auto=true, - } - for i,chr in next,tfmdata.characters do - local v=setup[i] - if v and v~=0 then - chr.expansion_factor=v*factor - else - chr.expansion_factor=factor - end - end - end - end -end -otffeatures.register { - name="expansion", - description="apply hz optimization", - initializers={ - base=initializeexpansion, - node=initializeexpansion, - } -} -function fonts.loggers.onetimemessage() end -local byte=string.byte -fonts.expansions.setups['default']={ - stretch=2,shrink=2,step=.5,factor=1, - [byte('A')]=0.5,[byte('B')]=0.7,[byte('C')]=0.7,[byte('D')]=0.5,[byte('E')]=0.7, - [byte('F')]=0.7,[byte('G')]=0.5,[byte('H')]=0.7,[byte('K')]=0.7,[byte('M')]=0.7, - [byte('N')]=0.7,[byte('O')]=0.5,[byte('P')]=0.7,[byte('Q')]=0.5,[byte('R')]=0.7, - [byte('S')]=0.7,[byte('U')]=0.7,[byte('W')]=0.7,[byte('Z')]=0.7, - [byte('a')]=0.7,[byte('b')]=0.7,[byte('c')]=0.7,[byte('d')]=0.7,[byte('e')]=0.7, - [byte('g')]=0.7,[byte('h')]=0.7,[byte('k')]=0.7,[byte('m')]=0.7,[byte('n')]=0.7, - [byte('o')]=0.7,[byte('p')]=0.7,[byte('q')]=0.7,[byte('s')]=0.7,[byte('u')]=0.7, - [byte('w')]=0.7,[byte('z')]=0.7, - [byte('2')]=0.7,[byte('3')]=0.7,[byte('6')]=0.7,[byte('8')]=0.7,[byte('9')]=0.7, -} -fonts.protrusions.setups['default']={ - factor=1,left=1,right=1, - [0x002C]={ 0,1 }, - [0x002E]={ 0,1 }, - [0x003A]={ 0,1 }, - [0x003B]={ 0,1 }, - [0x002D]={ 0,1 }, - [0x2013]={ 0,0.50 }, - [0x2014]={ 0,0.33 }, - [0x3001]={ 0,1 }, - [0x3002]={ 0,1 }, - [0x060C]={ 0,1 }, - [0x061B]={ 0,1 }, - [0x06D4]={ 0,1 }, -} -fonts.handlers.otf.features.normalize=function(t) - if t.rand then - t.rand="random" - end - return t -end -function fonts.helpers.nametoslot(name) - local t=type(name) - if t=="string" then - local tfmdata=fonts.hashes.identifiers[currentfont()] - local shared=tfmdata and tfmdata.shared - local fntdata=shared and shared.rawdata - return fntdata and fntdata.resources.unicodes[name] - elseif t=="number" then - return n - end -end -fonts.encodings=fonts.encodings or {} -local reencodings={} -fonts.encodings.reencodings=reencodings -local function specialreencode(tfmdata,value) - local encoding=value and reencodings[value] - if encoding then - local temp={} - local char=tfmdata.characters - for k,v in next,encoding do - temp[k]=char[v] - end - for k,v in next,temp do - char[k]=temp[k] - end - return string.format("reencoded:%s",value) - end -end -local function reencode(tfmdata,value) - tfmdata.postprocessors=tfmdata.postprocessors or {} - table.insert(tfmdata.postprocessors, - function(tfmdata) - return specialreencode(tfmdata,value) - end - ) -end -otffeatures.register { - name="reencode", - description="reencode characters", - manipulators={ - base=reencode, - node=reencode, - } -} -local function ignore(tfmdata,key,value) - if value then - tfmdata.mathparameters=nil - end -end -otffeatures.register { - name="ignoremathconstants", - description="ignore math constants table", - initializers={ - base=ignore, - node=ignore, - } -} - -end --- [luaotfload, fontloader-2017-02-11.lua scope for “fonts-ext”] --- - - -do --- [luaotfload, fontloader-2017-02-11.lua scope for “font-gbn” 850f31ba73ff8de96371d0aed2b2b4cb] --- - -if not modules then modules={} end modules ['font-gbn']={ - version=1.001, - comment="companion to luatex-*.tex", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -if context then - texio.write_nl("fatal error: this module is not for context") - os.exit() -end -local fonts=fonts -local nodes=nodes -local nuts=nodes.nuts -local traverse_id=nuts.traverse_id -local flush_node=nuts.flush_node -local glyph_code=nodes.nodecodes.glyph -local disc_code=nodes.nodecodes.disc -local tonode=nuts.tonode -local tonut=nuts.tonut -local getfont=nuts.getfont -local getchar=nuts.getchar -local getid=nuts.getid -local getboth=nuts.getboth -local getprev=nuts.getprev -local getnext=nuts.getnext -local getdisc=nuts.getdisc -local setchar=nuts.setchar -local setlink=nuts.setlink -local setprev=nuts.setprev -local nodetail=nuts.tail -local n_ligaturing=node.ligaturing -local n_kerning=node.kerning -local ligaturing=nuts.ligaturing -local kerning=nuts.kerning -local basemodepass=true -local function l_warning() texio.write_nl("warning: node.ligaturing called directly") l_warning=nil end -local function k_warning() texio.write_nl("warning: node.kerning called directly") k_warning=nil end -function node.ligaturing(...) - if basemodepass and l_warning then - l_warning() - end - return n_ligaturing(...) -end -function node.kerning(...) - if basemodepass and k_warning then - k_warning() - end - return n_kerning(...) -end -function nodes.handlers.setbasemodepass(v) - basemodepass=v -end -function nodes.handlers.nodepass(head) - local fontdata=fonts.hashes.identifiers - if fontdata then - local nuthead=tonut(head) - local usedfonts={} - local basefonts={} - local prevfont=nil - local basefont=nil - local variants=nil - local redundant=nil - for n in traverse_id(glyph_code,nuthead) do - local font=getfont(n) - if font~=prevfont then - if basefont then - basefont[2]=getprev(n) - end - prevfont=font - local used=usedfonts[font] - if not used then - local tfmdata=fontdata[font] - if tfmdata then - local shared=tfmdata.shared - if shared then - local processors=shared.processes - if processors and #processors>0 then - usedfonts[font]=processors - elseif basemodepass then - basefont={ n,nil } - basefonts[#basefonts+1]=basefont - end - end - local resources=tfmdata.resources - variants=resources and resources.variants - variants=variants and next(variants) and variants or false - end - else - local tfmdata=fontdata[prevfont] - if tfmdata then - local resources=tfmdata.resources - variants=resources and resources.variants - variants=variants and next(variants) and variants or false - end - end - end - if variants then - local char=getchar(n) - if char>=0xFE00 and (char<=0xFE0F or (char>=0xE0100 and char<=0xE01EF)) then - local hash=variants[char] - if hash then - local p=getprev(n) - if p and getid(p)==glyph_code then - local variant=hash[getchar(p)] - if variant then - setchar(p,variant) - end - end - end - if not redundant then - redundant={ n } - else - redundant[#redundant+1]=n - end - end - end - end - local nofbasefonts=#basefonts - if redundant then - for i=1,#redundant do - local r=redundant[i] - local p,n=getboth(r) - if r==nuthead then - nuthead=n - setprev(n) - else - setlink(p,n) - end - if nofbasefonts>0 then - for i=1,nofbasefonts do - local bi=basefonts[i] - if r==bi[1] then - bi[1]=n - end - if r==bi[2] then - bi[2]=n - end - end - end - flush_node(r) - end - end - for d in traverse_id(disc_code,nuthead) do - local _,_,r=getdisc(d) - if r then - for n in traverse_id(glyph_code,r) do - local font=getfont(n) - if font~=prevfont then - prevfont=font - local used=usedfonts[font] - if not used then - local tfmdata=fontdata[font] - if tfmdata then - local shared=tfmdata.shared - if shared then - local processors=shared.processes - if processors and #processors>0 then - usedfonts[font]=processors - end - end - end - end - end - end - end - end - if next(usedfonts) then - for font,processors in next,usedfonts do - for i=1,#processors do - head=processors[i](head,font,0) or head - end - end - end - if basemodepass and nofbasefonts>0 then - for i=1,nofbasefonts do - local range=basefonts[i] - local start=range[1] - local stop=range[2] - if start then - local front=nuthead==start - if not stop then - stop=nodetail(start) - end - if stop then - start,stop=ligaturing(start,stop) - start,stop=kerning(start,stop) - elseif start then - start,stop=ligaturing(start,stop) - start,stop=kerning(start,stop) - end - if front and nuthead~=start then - head=tonode(start) - end - end - end - end - return head,true - else - return head,false - end -end -function nodes.handlers.basepass(head) - if not basemodepass then - head=n_ligaturing(head) - head=n_kerning(head) - end - return head,true -end -local nodepass=nodes.handlers.nodepass -local basepass=nodes.handlers.basepass -local injectpass=nodes.injections.handler -local protectpass=nodes.handlers.protectglyphs -function nodes.simple_font_handler(head) - if head then - head=nodepass(head) - head=injectpass(head) - if not basemodepass then - head=basepass(head) - end - protectpass(head) - return head,true - else - return head,false - end -end - -end --- [luaotfload, fontloader-2017-02-11.lua scope for “font-gbn”] --- - - ---- vim:ft=lua:sw=2:ts=8:et:tw=79 diff --git a/tex/compat/luaotfload/fontloader-basics-gen.lua b/tex/compat/luaotfload/fontloader-basics-gen.lua deleted file mode 100644 index 2be55cceabca2aff1c51c6803ad5f96dc4b96a55..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/fontloader-basics-gen.lua +++ /dev/null @@ -1,436 +0,0 @@ -if not modules then modules = { } end modules ['luat-basics-gen'] = { - version = 1.100, - comment = "companion to luatex-*.tex", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -if context then - texio.write_nl("fatal error: this module is not for context") - os.exit() -end - -local dummyfunction = function() -end - -local dummyreporter = function(c) - return function(f,...) - local r = texio.reporter or texio.write_nl - if f then - r(c .. " : " .. string.formatters(f,...)) - else - r("") - end - end -end - -statistics = { - register = dummyfunction, - starttiming = dummyfunction, - stoptiming = dummyfunction, - elapsedtime = nil, -} - -directives = { - register = dummyfunction, - enable = dummyfunction, - disable = dummyfunction, -} - -trackers = { - register = dummyfunction, - enable = dummyfunction, - disable = dummyfunction, -} - -experiments = { - register = dummyfunction, - enable = dummyfunction, - disable = dummyfunction, -} - -storage = { -- probably no longer needed - register = dummyfunction, - shared = { }, -} - -logs = { - new = dummyreporter, - reporter = dummyreporter, - messenger = dummyreporter, - report = dummyfunction, -} - -callbacks = { - register = function(n,f) - return callback.register(n,f) - end, - -} - -utilities = utilities or { } utilities.storage = { - allocate = function(t) - return t or { } - end, - mark = function(t) - return t or { } - end, -} - -characters = characters or { - data = { } -} - --- we need to cheat a bit here - -texconfig.kpse_init = true - -resolvers = resolvers or { } -- no fancy file helpers used - -local remapper = { - otf = "opentype fonts", - ttf = "truetype fonts", - ttc = "truetype fonts", - cid = "cid maps", - cidmap = "cid maps", - -- fea = "font feature files", -- no longer supported - pfb = "type1 fonts", -- needed for vector loading - afm = "afm", - enc = "enc files", -} - -function resolvers.findfile(name,fileformat) - name = string.gsub(name,"\\","/") - if not fileformat or fileformat == "" then - fileformat = file.suffix(name) - if fileformat == "" then - fileformat = "tex" - end - end - fileformat = string.lower(fileformat) - fileformat = remapper[fileformat] or fileformat - local found = kpse.find_file(name,fileformat) - if not found or found == "" then - found = kpse.find_file(name,"other text files") - end - return found -end - --- function resolvers.findbinfile(name,fileformat) --- if not fileformat or fileformat == "" then --- fileformat = file.suffix(name) --- end --- return resolvers.findfile(name,(fileformat and remapper[fileformat]) or fileformat) --- end - -resolvers.findbinfile = resolvers.findfile - -function resolvers.loadbinfile(filename,filetype) - local data = io.loaddata(filename) - return true, data, #data -end - -function resolvers.resolve(s) - return s -end - -function resolvers.unresolve(s) - return s -end - --- Caches ... I will make a real stupid version some day when I'm in the --- mood. After all, the generic code does not need the more advanced --- ConTeXt features. Cached data is not shared between ConTeXt and other --- usage as I don't want any dependency at all. Also, ConTeXt might have --- different needs and tricks added. - ---~ containers.usecache = true - -caches = { } - -local writable = nil -local readables = { } -local usingjit = jit - -if not caches.namespace or caches.namespace == "" or caches.namespace == "context" then - caches.namespace = 'generic' -end - -do - - -- standard context tree setup - - local cachepaths = kpse.expand_var('$TEXMFCACHE') or "" - - -- quite like tex live or so (the weird $TEXMFCACHE test seems to be needed on miktex) - - if cachepaths == "" or cachepaths == "$TEXMFCACHE" then - cachepaths = kpse.expand_var('$TEXMFVAR') or "" - end - - -- this also happened to be used (the weird $TEXMFVAR test seems to be needed on miktex) - - if cachepaths == "" or cachepaths == "$TEXMFVAR" then - cachepaths = kpse.expand_var('$VARTEXMF') or "" - end - - -- and this is a last resort (hm, we could use TEMP or TEMPDIR) - - if cachepaths == "" then - local fallbacks = { "TMPDIR", "TEMPDIR", "TMP", "TEMP", "HOME", "HOMEPATH" } - for i=1,#fallbacks do - cachepaths = os.getenv(fallbacks[i]) or "" - if cachepath ~= "" and lfs.isdir(cachepath) then - break - end - end - end - - if cachepaths == "" then - cachepaths = "." - end - - cachepaths = string.split(cachepaths,os.type == "windows" and ";" or ":") - - for i=1,#cachepaths do - local cachepath = cachepaths[i] - if not lfs.isdir(cachepath) then - lfs.mkdirs(cachepath) -- needed for texlive and latex - if lfs.isdir(cachepath) then - texio.write(string.format("(created cache path: %s)",cachepath)) - end - end - if file.is_writable(cachepath) then - writable = file.join(cachepath,"luatex-cache") - lfs.mkdir(writable) - writable = file.join(writable,caches.namespace) - lfs.mkdir(writable) - break - end - end - - for i=1,#cachepaths do - if file.is_readable(cachepaths[i]) then - readables[#readables+1] = file.join(cachepaths[i],"luatex-cache",caches.namespace) - end - end - - if not writable then - texio.write_nl("quiting: fix your writable cache path") - os.exit() - elseif #readables == 0 then - texio.write_nl("quiting: fix your readable cache path") - os.exit() - elseif #readables == 1 and readables[1] == writable then - texio.write(string.format("(using cache: %s)",writable)) - else - texio.write(string.format("(using write cache: %s)",writable)) - texio.write(string.format("(using read cache: %s)",table.concat(readables, " "))) - end - -end - -function caches.getwritablepath(category,subcategory) - local path = file.join(writable,category) - lfs.mkdir(path) - path = file.join(path,subcategory) - lfs.mkdir(path) - return path -end - -function caches.getreadablepaths(category,subcategory) - local t = { } - for i=1,#readables do - t[i] = file.join(readables[i],category,subcategory) - end - return t -end - -local function makefullname(path,name) - if path and path ~= "" then - 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) - local fullname = makefullname(path,name) - return fullname and file.is_writable(fullname) -end - --- function caches.loaddata(paths,name) --- for i=1,#paths do --- local data = false --- local luaname, lucname = makefullname(paths[i],name) --- if lucname and not lfs.isfile(lucname) and type(caches.compile) == "function" then --- -- in case we used luatex and luajittex mixed ... lub or luc file --- texio.write(string.format("(compiling luc: %s)",lucname)) --- data = loadfile(luaname) --- if data then --- data = data() --- end --- if data then --- caches.compile(data,luaname,lucname) --- return data --- end --- end --- if lucname and lfs.isfile(lucname) then -- maybe also check for size --- texio.write(string.format("(load luc: %s)",lucname)) --- data = loadfile(lucname) --- if data then --- data = data() --- end --- if data then --- return data --- else --- texio.write(string.format("(loading failed: %s)",lucname)) --- end --- end --- if luaname and lfs.isfile(luaname) then --- texio.write(string.format("(load lua: %s)",luaname)) --- data = loadfile(luaname) --- if data then --- data = data() --- end --- if data then --- return data --- end --- end --- end --- end - -function caches.loaddata(readables,name,writable) - for i=1,#readables do - local path = readables[i] - local loader = false - local luaname, lucname = makefullname(path,name) - if lfs.isfile(lucname) then - texio.write(string.format("(load luc: %s)",lucname)) - loader = loadfile(lucname) - end - if not loader and lfs.isfile(luaname) then - -- can be different paths when we read a file database from disk - local luacrap, lucname = makefullname(writable,name) - texio.write(string.format("(compiling luc: %s)",lucname)) - if lfs.isfile(lucname) then - loader = loadfile(lucname) - end - caches.compile(data,luaname,lucname) - if lfs.isfile(lucname) then - texio.write(string.format("(load luc: %s)",lucname)) - loader = loadfile(lucname) - else - texio.write(string.format("(loading failed: %s)",lucname)) - end - if not loader then - texio.write(string.format("(load lua: %s)",luaname)) - loader = loadfile(luaname) - else - texio.write(string.format("(loading failed: %s)",luaname)) - end - end - if loader then - loader = loader() - collectgarbage("step") - return loader - end - end - return false -end - -function caches.savedata(path,name,data) - local luaname, lucname = makefullname(path,name) - if luaname then - texio.write(string.format("(save: %s)",luaname)) - table.tofile(luaname,data,true) - if lucname and type(caches.compile) == "function" then - os.remove(lucname) -- better be safe - texio.write(string.format("(save: %s)",lucname)) - caches.compile(data,luaname,lucname) - end - end -end - --- According to KH os.execute is not permitted in plain/latex so there is --- no reason to use the normal context way. So the method here is slightly --- different from the one we have in context. We also use different suffixes --- as we don't want any clashes (sharing cache files is not that handy as --- context moves on faster.) --- --- Beware: serialization might fail on large files (so maybe we should pcall --- this) in which case one should limit the method to luac and enable support --- for execution. - --- 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 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,'wb') - if f then - local s = loadstring(d) - if s then - f:write(string.dump(s,true)) - end - f:close() - end - end -end - --- - --- function table.setmetatableindex(t,f) --- if type(t) ~= "table" then --- f = f or t --- t = { } --- end --- setmetatable(t,{ __index = f }) --- return t --- end - -function table.setmetatableindex(t,f) - if type(t) ~= "table" then - f, t = t, { } - end - local m = getmetatable(t) - if f == "table" then - f = function(t,k) local v = { } t[k] = v return v end - end - if m then - m.__index = f - else - setmetatable(t,{ __index = f }) - end - return t -end - --- helper for plain: - -arguments = { } - -if arg then - for i=1,#arg do - local k, v = string.match(arg[i],"^%-%-([^=]+)=?(.-)$") - if k and v then - arguments[k] = v - end - end -end diff --git a/tex/compat/luaotfload/fontloader-basics-nod.lua b/tex/compat/luaotfload/fontloader-basics-nod.lua deleted file mode 100644 index 42a7a2e29eba14ddbf08cb97dbf845315d3a2900..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/fontloader-basics-nod.lua +++ /dev/null @@ -1,314 +0,0 @@ -if not modules then modules = { } end modules ['luatex-fonts-nod'] = { - version = 1.001, - comment = "companion to luatex-fonts.lua", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -if context then - texio.write_nl("fatal error: this module is not for context") - os.exit() -end - --- Don't depend on code here as it is only needed to complement the --- font handler code. - --- Attributes: - -if tex.attribute[0] ~= 0 then - - texio.write_nl("log","!") - texio.write_nl("log","! Attribute 0 is reserved for ConTeXt's font feature management and has to be") - texio.write_nl("log","! set to zero. Also, some attributes in the range 1-255 are used for special") - texio.write_nl("log","! purposes so setting them at the TeX end might break the font handler.") - texio.write_nl("log","!") - - tex.attribute[0] = 0 -- else no features - -end - -attributes = attributes or { } -attributes.unsetvalue = -0x7FFFFFFF - -local numbers, last = { }, 127 - -attributes.private = attributes.private or function(name) - local number = numbers[name] - if not number then - if last < 255 then - last = last + 1 - end - number = last - numbers[name] = number - end - return number -end - --- Nodes (a subset of context so that we don't get too much unused code): - -nodes = { } -nodes.pool = { } -nodes.handlers = { } - -local nodecodes = { } -local glyphcodes = node.subtypes("glyph") -local disccodes = node.subtypes("disc") - -for k, v in next, node.types() do - v = string.gsub(v,"_","") - nodecodes[k] = v - nodecodes[v] = k -end -for i=0,#glyphcodes do - glyphcodes[glyphcodes[i]] = i -end -for i=0,#disccodes do - disccodes[disccodes[i]] = i -end - -nodes.nodecodes = nodecodes -nodes.glyphcodes = glyphcodes -nodes.disccodes = disccodes - -local flush_node = node.flush_node -local remove_node = node.remove -local new_node = node.new -local traverse_id = node.traverse_id - -nodes.handlers.protectglyphs = node.protect_glyphs -nodes.handlers.unprotectglyphs = node.unprotect_glyphs - -local math_code = nodecodes.math -local end_of_math = node.end_of_math - -function node.end_of_math(n) - if n.id == math_code and n.subtype == 1 then - return n - else - return end_of_math(n) - end -end - -function nodes.remove(head, current, free_too) - local t = current - head, current = remove_node(head,current) - if t then - if free_too then - flush_node(t) - t = nil - else - t.next, t.prev = nil, nil - end - end - return head, current, t -end - -function nodes.delete(head,current) - return nodes.remove(head,current,true) -end - -function nodes.pool.kern(k) - local n = new_node("kern",1) - n.kern = k - return n -end - -local getfield = node.getfield -local setfield = node.setfield - -nodes.getfield = getfield -nodes.setfield = setfield - -nodes.getattr = getfield -nodes.setattr = setfield - --- being lazy ... just copy a bunch ... not all needed in generic but we assume --- nodes to be kind of private anyway - -nodes.tostring = node.tostring or tostring -nodes.copy = node.copy -nodes.copy_node = node.copy -nodes.copy_list = node.copy_list -nodes.delete = node.delete -nodes.dimensions = node.dimensions -nodes.end_of_math = node.end_of_math -nodes.flush_list = node.flush_list -nodes.flush_node = node.flush_node -nodes.flush = node.flush_node -nodes.free = node.free -nodes.insert_after = node.insert_after -nodes.insert_before = node.insert_before -nodes.hpack = node.hpack -nodes.new = node.new -nodes.tail = node.tail -nodes.traverse = node.traverse -nodes.traverse_id = node.traverse_id -nodes.slide = node.slide -nodes.vpack = node.vpack - -nodes.first_glyph = node.first_glyph -nodes.has_glyph = node.has_glyph or node.first_glyph - -nodes.current_attr = node.current_attr -nodes.has_field = node.has_field -nodes.last_node = node.last_node -nodes.usedlist = node.usedlist -nodes.protrusion_skippable = node.protrusion_skippable -nodes.write = node.write - -nodes.has_attribute = node.has_attribute -nodes.set_attribute = node.set_attribute -nodes.unset_attribute = node.unset_attribute - -nodes.protect_glyphs = node.protect_glyphs -nodes.unprotect_glyphs = node.unprotect_glyphs ------.kerning = node.kerning ------.ligaturing = node.ligaturing -nodes.mlist_to_hlist = node.mlist_to_hlist - --- in generic code, at least for some time, we stay nodes, while in context --- we can go nuts (e.g. experimental); this split permits us us keep code --- used elsewhere stable but at the same time play around in context - -local direct = node.direct -local nuts = { } -nodes.nuts = nuts - -local tonode = direct.tonode -local tonut = direct.todirect - -nodes.tonode = tonode -nodes.tonut = tonut - -nuts.tonode = tonode -nuts.tonut = tonut - -local getfield = direct.getfield -local setfield = direct.setfield - -nuts.getfield = getfield -nuts.setfield = setfield -nuts.getnext = direct.getnext -nuts.setnext = direct.setnext -nuts.getprev = direct.getprev -nuts.setprev = direct.setprev -nuts.getboth = direct.getboth -nuts.setboth = direct.setboth -nuts.getid = direct.getid -nuts.getattr = direct.get_attribute or direct.has_attribute or getfield -nuts.setattr = setfield -nuts.getfont = direct.getfont -nuts.setfont = direct.setfont -nuts.getsubtype = direct.getsubtype -nuts.setsubtype = direct.setsubtype or function(n,s) setfield(n,"subtype",s) end -nuts.getchar = direct.getchar -nuts.setchar = direct.setchar -nuts.getdisc = direct.getdisc -nuts.setdisc = direct.setdisc -nuts.setlink = direct.setlink -nuts.getlist = direct.getlist -nuts.setlist = direct.setlist or function(n,l) setfield(n,"list",l) end -nuts.getleader = direct.getleader -nuts.setleader = direct.setleader or function(n,l) setfield(n,"leader",l) end - -if not direct.is_glyph then - local getchar = direct.getchar - local getid = direct.getid - local getfont = direct.getfont - local glyph_code = nodes.nodecodes.glyph - function direct.is_glyph(n,f) - local id = getid(n) - if id == glyph_code then - if f and getfont(n) == f then - return getchar(n) - else - return false - end - else - return nil, id - end - end - function direct.is_char(n,f) - local id = getid(n) - if id == glyph_code then - if getsubtype(n) >= 256 then - return false - elseif f and getfont(n) == f then - return getchar(n) - else - return false - end - else - return nil, id - end - end -end - -nuts.ischar = direct.is_char -nuts.is_char = direct.is_char -nuts.isglyph = direct.is_glyph -nuts.is_glyph = direct.is_glyph - -nuts.insert_before = direct.insert_before -nuts.insert_after = direct.insert_after -nuts.delete = direct.delete -nuts.copy = direct.copy -nuts.copy_node = direct.copy -nuts.copy_list = direct.copy_list -nuts.tail = direct.tail -nuts.flush_list = direct.flush_list -nuts.flush_node = direct.flush_node -nuts.flush = direct.flush -nuts.free = direct.free -nuts.remove = direct.remove -nuts.is_node = direct.is_node -nuts.end_of_math = direct.end_of_math -nuts.traverse = direct.traverse -nuts.traverse_id = direct.traverse_id -nuts.traverse_char = direct.traverse_char -nuts.ligaturing = direct.ligaturing -nuts.kerning = direct.kerning - -nuts.getprop = nuts.getattr -nuts.setprop = nuts.setattr - -local new_nut = direct.new -nuts.new = new_nut -nuts.pool = { } - -function nuts.pool.kern(k) - local n = new_nut("kern",1) - setfield(n,"kern",k) - return n -end - --- properties as used in the (new) injector: - -local propertydata = direct.get_properties_table() -nodes.properties = { data = propertydata } - -direct.set_properties_mode(true,true) -- needed for injection - -function direct.set_properties_mode() end -- we really need the set modes - -nuts.getprop = function(n,k) - local p = propertydata[n] - if p then - return p[k] - end -end - -nuts.setprop = function(n,k,v) - if v then - local p = propertydata[n] - if p then - p[k] = v - else - propertydata[n] = { [k] = v } - end - end -end - -nodes.setprop = nodes.setproperty -nodes.getprop = nodes.getproperty diff --git a/tex/compat/luaotfload/fontloader-basics.tex b/tex/compat/luaotfload/fontloader-basics.tex deleted file mode 100644 index 1180c68e6c5e2f3157d795934b8d1960e5ba3897..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/fontloader-basics.tex +++ /dev/null @@ -1,93 +0,0 @@ -%D \module -%D [ file=luatex-basics, -%D version=2009.12.01, -%D title=\LUATEX\ Support Macros, -%D subtitle=Attribute Allocation, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] - -%D As soon as we feel the need this file will file will contain an extension -%D to the standard plain register allocation. For the moment we stick to a -%D rather dumb attribute allocator. We start at 256 because we don't want -%D any interference with the attributes used in the font handler. - -\ifx\newattribute\undefined \else \endinput \fi - -\newcount \lastallocatedattribute \lastallocatedattribute=255 - -\def\newattribute#1% - {\global\advance\lastallocatedattribute 1 - \attributedef#1\lastallocatedattribute} - -% maybe we will have luatex-basics.lua some day for instance when more -% (pdf) primitives have moved to macros) - -\directlua { - - gadgets = gadgets or { } % reserved namespace - - gadgets.functions = { } - local registered = {} - - function gadgets.functions.reverve() - local numb = newtoken.scan_int() - local name = newtoken.scan_string() - local okay = string.gsub(name,"[\string\\ ]","") - registered[okay] = numb - texio.write_nl("reserving lua function '"..okay.."' with number "..numb) - end - - function gadgets.functions.register(name,f) - local okay = string.gsub(name,"[\string\\ ]","") - local numb = registered[okay] - if numb then - texio.write_nl("registering lua function '"..okay.."' with number "..numb) - lua.get_functions_table()[numb] = f - else - texio.write_nl("lua function '"..okay.."' is not reserved") - end - end - -} - -\newcount\lastallocatedluafunction - -\def\newluafunction#1% - {\ifdefined#1\else - \global\advance\lastallocatedluafunction 1 - \global\chardef#1\lastallocatedluafunction - \directlua{gadgets.functions.reserve()}#1{\detokenize{#1}}% - \fi} - -% an example of usage (if we ever support it it will go to the plain gadgets module): -% -% \directlua { -% -% local cct = nil -% local chr = nil -% -% gadgets.functions.register("UcharcatLuaOne",function() -% chr = newtoken.scan_int() -% cct = tex.getcatcode(chr) -% tex.setcatcode(chr,newtoken.scan_int()) -% tex.sprint(unicode.utf8.char(chr)) -% end) -% -% gadgets.functions.register("UcharcatLuaTwo",function() -% tex.setcatcode(chr,cct) -% end) -% -% } -% -% \def\Ucharcat -% {\expandafter\expandafter\expandafter\luafunction -% \expandafter\expandafter\expandafter\UcharcatLuaTwo -% \luafunction\UcharcatLuaOne} -% -% A:\the\catcode65:\Ucharcat 65 11:A:\the\catcode65\par -% A:\the\catcode65:\Ucharcat 65 5:A:\the\catcode65\par -% A:\the\catcode65:\Ucharcat 65 11:A:\the\catcode65\par - - -\endinput diff --git a/tex/compat/luaotfload/fontloader-data-con.lua b/tex/compat/luaotfload/fontloader-data-con.lua deleted file mode 100644 index c79fca7c5c1357419a4a4d9dac0e9e1534894154..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/fontloader-data-con.lua +++ /dev/null @@ -1,138 +0,0 @@ -if not modules then modules = { } end modules ['data-con'] = { - version = 1.100, - comment = "companion to luat-lib.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -local format, lower, gsub = string.format, string.lower, string.gsub - -local trace_cache = false trackers.register("resolvers.cache", function(v) trace_cache = v end) -local trace_containers = false trackers.register("resolvers.containers", function(v) trace_containers = v end) -local trace_storage = false trackers.register("resolvers.storage", function(v) trace_storage = v end) - ---[[ldx-- -<p>Once we found ourselves defining similar cache constructs -several times, containers were introduced. Containers are used -to collect tables in memory and reuse them when possible based -on (unique) hashes (to be provided by the calling function).</p> - -<p>Caching to disk is disabled by default. Version numbers are -stored in the saved table which makes it possible to change the -table structures without bothering about the disk cache.</p> - -<p>Examples of usage can be found in the font related code.</p> ---ldx]]-- - -containers = containers or { } -local containers = containers -containers.usecache = true - -local report_containers = logs.reporter("resolvers","containers") - -local allocated = { } - -local mt = { - __index = function(t,k) - if k == "writable" then - local writable = caches.getwritablepath(t.category,t.subcategory) or { "." } - t.writable = writable - return writable - elseif k == "readables" then - local readables = caches.getreadablepaths(t.category,t.subcategory) or { "." } - t.readables = readables - return readables - end - end, - __storage__ = true -} - -function containers.define(category, subcategory, version, enabled) - if category and subcategory then - local c = allocated[category] - if not c then - c = { } - allocated[category] = c - end - local s = c[subcategory] - if not s then - s = { - category = category, - subcategory = subcategory, - storage = { }, - enabled = enabled, - version = version or math.pi, -- after all, this is TeX - trace = false, - -- writable = caches.getwritablepath and caches.getwritablepath (category,subcategory) or { "." }, - -- readables = caches.getreadablepaths and caches.getreadablepaths(category,subcategory) or { "." }, - } - setmetatable(s,mt) - c[subcategory] = s - end - return s - end -end - -function containers.is_usable(container,name) - return container.enabled and caches and caches.is_writable(container.writable, name) -end - -function containers.is_valid(container,name) - if name and name ~= "" then - local storage = container.storage[name] - return storage and storage.cache_version == container.version - else - return false - end -end - -function containers.read(container,name) - local storage = container.storage - local stored = storage[name] - if not stored and container.enabled and caches and containers.usecache then - stored = caches.loaddata(container.readables,name,container.writable) - if stored and stored.cache_version == container.version then - if trace_cache or trace_containers then - report_containers("action %a, category %a, name %a","load",container.subcategory,name) - end - else - stored = nil - end - storage[name] = stored - elseif stored then - if trace_cache or trace_containers then - report_containers("action %a, category %a, name %a","reuse",container.subcategory,name) - end - end - return stored -end - -function containers.write(container, name, data) - if data then - data.cache_version = container.version - if container.enabled and caches then - local unique, shared = data.unique, data.shared - data.unique, data.shared = nil, nil - caches.savedata(container.writable, name, data) - if trace_cache or trace_containers then - report_containers("action %a, category %a, name %a","save",container.subcategory,name) - end - data.unique, data.shared = unique, shared - end - if trace_cache or trace_containers then - report_containers("action %a, category %a, name %a","store",container.subcategory,name) - end - container.storage[name] = data - end - return data -end - -function containers.content(container,name) - return container.storage[name] -end - -function containers.cleanname(name) - -- return (gsub(lower(name),"[^%w]+","-")) - return (gsub(lower(name),"[^%w\128-\255]+","-")) -- more utf friendly -end diff --git a/tex/compat/luaotfload/fontloader-font-afk.lua b/tex/compat/luaotfload/fontloader-font-afk.lua deleted file mode 100644 index 8b65b0631845e0ca78b41304a1d0c3f3a28c492d..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/fontloader-font-afk.lua +++ /dev/null @@ -1,200 +0,0 @@ -if not modules then modules = { } end modules ['font-afk'] = { - version = 1.001, - comment = "companion to font-afm.lua", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files", - dataonly = true, -} - ---[[ldx-- -<p>For ligatures, only characters with a code smaller than 128 make sense, -anything larger is encoding dependent. An interesting complication is that a -character can be in an encoding twice but is hashed once.</p> ---ldx]]-- - -local allocate = utilities.storage.allocate - -fonts.handlers.afm.helpdata = { - ligatures = allocate { -- okay, nowadays we could parse the name but type 1 fonts - ['f'] = { -- don't have that many ligatures anyway - { 'f', 'ff' }, - { 'i', 'fi' }, - { 'l', 'fl' }, - }, - ['ff'] = { - { 'i', 'ffi' } - }, - ['fi'] = { - { 'i', 'fii' } - }, - ['fl'] = { - { 'i', 'fli' } - }, - ['s'] = { - { 't', 'st' } - }, - ['i'] = { - { 'j', 'ij' } - }, - }, - texligatures = allocate { - -- ['space'] = { - -- { 'L', 'Lslash' }, - -- { 'l', 'lslash' } - -- }, - -- ['question'] = { - -- { 'quoteleft', 'questiondown' } - -- }, - -- ['exclam'] = { - -- { 'quoteleft', 'exclamdown' } - -- }, - ['quoteleft'] = { - { 'quoteleft', 'quotedblleft' } - }, - ['quoteright'] = { - { 'quoteright', 'quotedblright' } - }, - ['hyphen'] = { - { 'hyphen', 'endash' } - }, - ['endash'] = { - { 'hyphen', 'emdash' } - } - }, - leftkerned = allocate { - AEligature = "A", aeligature = "a", - OEligature = "O", oeligature = "o", - IJligature = "I", ijligature = "i", - AE = "A", ae = "a", - OE = "O", oe = "o", - IJ = "I", ij = "i", - Ssharp = "S", ssharp = "s", - }, - rightkerned = allocate { - AEligature = "E", aeligature = "e", - OEligature = "E", oeligature = "e", - IJligature = "J", ijligature = "j", - AE = "E", ae = "e", - OE = "E", oe = "e", - IJ = "J", ij = "j", - Ssharp = "S", ssharp = "s", - }, - bothkerned = allocate { - Acircumflex = "A", acircumflex = "a", - Ccircumflex = "C", ccircumflex = "c", - Ecircumflex = "E", ecircumflex = "e", - Gcircumflex = "G", gcircumflex = "g", - Hcircumflex = "H", hcircumflex = "h", - Icircumflex = "I", icircumflex = "i", - Jcircumflex = "J", jcircumflex = "j", - Ocircumflex = "O", ocircumflex = "o", - Scircumflex = "S", scircumflex = "s", - Ucircumflex = "U", ucircumflex = "u", - Wcircumflex = "W", wcircumflex = "w", - Ycircumflex = "Y", ycircumflex = "y", - - Agrave = "A", agrave = "a", - Egrave = "E", egrave = "e", - Igrave = "I", igrave = "i", - Ograve = "O", ograve = "o", - Ugrave = "U", ugrave = "u", - Ygrave = "Y", ygrave = "y", - - Atilde = "A", atilde = "a", - Itilde = "I", itilde = "i", - Otilde = "O", otilde = "o", - Utilde = "U", utilde = "u", - Ntilde = "N", ntilde = "n", - - Adiaeresis = "A", adiaeresis = "a", Adieresis = "A", adieresis = "a", - Ediaeresis = "E", ediaeresis = "e", Edieresis = "E", edieresis = "e", - Idiaeresis = "I", idiaeresis = "i", Idieresis = "I", idieresis = "i", - Odiaeresis = "O", odiaeresis = "o", Odieresis = "O", odieresis = "o", - Udiaeresis = "U", udiaeresis = "u", Udieresis = "U", udieresis = "u", - Ydiaeresis = "Y", ydiaeresis = "y", Ydieresis = "Y", ydieresis = "y", - - Aacute = "A", aacute = "a", - Cacute = "C", cacute = "c", - Eacute = "E", eacute = "e", - Iacute = "I", iacute = "i", - Lacute = "L", lacute = "l", - Nacute = "N", nacute = "n", - Oacute = "O", oacute = "o", - Racute = "R", racute = "r", - Sacute = "S", sacute = "s", - Uacute = "U", uacute = "u", - Yacute = "Y", yacute = "y", - Zacute = "Z", zacute = "z", - - Dstroke = "D", dstroke = "d", - Hstroke = "H", hstroke = "h", - Tstroke = "T", tstroke = "t", - - Cdotaccent = "C", cdotaccent = "c", - Edotaccent = "E", edotaccent = "e", - Gdotaccent = "G", gdotaccent = "g", - Idotaccent = "I", idotaccent = "i", - Zdotaccent = "Z", zdotaccent = "z", - - Amacron = "A", amacron = "a", - Emacron = "E", emacron = "e", - Imacron = "I", imacron = "i", - Omacron = "O", omacron = "o", - Umacron = "U", umacron = "u", - - Ccedilla = "C", ccedilla = "c", - Kcedilla = "K", kcedilla = "k", - Lcedilla = "L", lcedilla = "l", - Ncedilla = "N", ncedilla = "n", - Rcedilla = "R", rcedilla = "r", - Scedilla = "S", scedilla = "s", - Tcedilla = "T", tcedilla = "t", - - Ohungarumlaut = "O", ohungarumlaut = "o", - Uhungarumlaut = "U", uhungarumlaut = "u", - - Aogonek = "A", aogonek = "a", - Eogonek = "E", eogonek = "e", - Iogonek = "I", iogonek = "i", - Uogonek = "U", uogonek = "u", - - Aring = "A", aring = "a", - Uring = "U", uring = "u", - - Abreve = "A", abreve = "a", - Ebreve = "E", ebreve = "e", - Gbreve = "G", gbreve = "g", - Ibreve = "I", ibreve = "i", - Obreve = "O", obreve = "o", - Ubreve = "U", ubreve = "u", - - Ccaron = "C", ccaron = "c", - Dcaron = "D", dcaron = "d", - Ecaron = "E", ecaron = "e", - Lcaron = "L", lcaron = "l", - Ncaron = "N", ncaron = "n", - Rcaron = "R", rcaron = "r", - Scaron = "S", scaron = "s", - Tcaron = "T", tcaron = "t", - Zcaron = "Z", zcaron = "z", - - dotlessI = "I", dotlessi = "i", - dotlessJ = "J", dotlessj = "j", - - AEligature = "AE", aeligature = "ae", AE = "AE", ae = "ae", - OEligature = "OE", oeligature = "oe", OE = "OE", oe = "oe", - IJligature = "IJ", ijligature = "ij", IJ = "IJ", ij = "ij", - - Lstroke = "L", lstroke = "l", Lslash = "L", lslash = "l", - Ostroke = "O", ostroke = "o", Oslash = "O", oslash = "o", - - Ssharp = "SS", ssharp = "ss", - - Aumlaut = "A", aumlaut = "a", - Eumlaut = "E", eumlaut = "e", - Iumlaut = "I", iumlaut = "i", - Oumlaut = "O", oumlaut = "o", - Uumlaut = "U", uumlaut = "u", - } -} diff --git a/tex/compat/luaotfload/fontloader-font-cff.lua b/tex/compat/luaotfload/fontloader-font-cff.lua deleted file mode 100644 index 1c6bd56fd3d0d959715f7017eaa94baf30c677f5..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/fontloader-font-cff.lua +++ /dev/null @@ -1,1839 +0,0 @@ -if not modules then modules = { } end modules ['font-cff'] = { - version = 1.001, - comment = "companion to font-ini.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- todo: option.outlines --- todo: option.boundingbox --- per charstring (less memory) - --- This is a heavy one as it is a rather packed format. We don't need al the information --- now but we might need it later (who know what magic we can do with metapost). So at --- some point this might become a module. We just follow Adobe Technical Notes #5176 and --- #5177. In case of doubt I looked in the fontforge code that comes with LuaTeX. - --- For now we save the segments in a list of segments with the operator last in an entry --- because that reflects the original. But it might make more sense to use a single array --- per segment. For pdf a simple concat works ok, but for other purposes a operator first --- flush is nicer. - -local next, type, tonumber = next, type, tonumber -local byte = string.byte -local concat, remove = table.concat, table.remove -local floor, abs, round, ceil = math.floor, math.abs, math.round, math.ceil -local P, C, R, S, C, Cs, Ct = lpeg.P, lpeg.C, lpeg.R, lpeg.S, lpeg.C, lpeg.Cs, lpeg.Ct -local lpegmatch = lpeg.match -local formatters = string.formatters - -local readers = fonts.handlers.otf.readers -local streamreader = readers.streamreader - -local readbytes = streamreader.readbytes -local readstring = streamreader.readstring -local readbyte = streamreader.readcardinal1 -- 8-bit unsigned integer -local readushort = streamreader.readcardinal2 -- 16-bit unsigned integer -local readuint = streamreader.readcardinal3 -- 24-bit unsigned integer -local readulong = streamreader.readcardinal4 -- 24-bit unsigned integer -local setposition = streamreader.setposition -local getposition = streamreader.getposition - -local setmetatableindex = table.setmetatableindex - -local trace_charstrings = false trackers.register("fonts.cff.charstrings",function(v) trace_charstrings = v end) -local report = logs.reporter("otf reader","cff") - -local parsedictionaries -local parsecharstring -local parsecharstrings -local resetcharstrings -local parseprivates - -local defaultstrings = { [0] = -- taken from ff - ".notdef", "space", "exclam", "quotedbl", "numbersign", "dollar", "percent", - "ampersand", "quoteright", "parenleft", "parenright", "asterisk", "plus", - "comma", "hyphen", "period", "slash", "zero", "one", "two", "three", "four", - "five", "six", "seven", "eight", "nine", "colon", "semicolon", "less", - "equal", "greater", "question", "at", "A", "B", "C", "D", "E", "F", "G", "H", - "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", - "X", "Y", "Z", "bracketleft", "backslash", "bracketright", "asciicircum", - "underscore", "quoteleft", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", - "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", - "z", "braceleft", "bar", "braceright", "asciitilde", "exclamdown", "cent", - "sterling", "fraction", "yen", "florin", "section", "currency", - "quotesingle", "quotedblleft", "guillemotleft", "guilsinglleft", - "guilsinglright", "fi", "fl", "endash", "dagger", "daggerdbl", - "periodcentered", "paragraph", "bullet", "quotesinglbase", "quotedblbase", - "quotedblright", "guillemotright", "ellipsis", "perthousand", "questiondown", - "grave", "acute", "circumflex", "tilde", "macron", "breve", "dotaccent", - "dieresis", "ring", "cedilla", "hungarumlaut", "ogonek", "caron", "emdash", - "AE", "ordfeminine", "Lslash", "Oslash", "OE", "ordmasculine", "ae", - "dotlessi", "lslash", "oslash", "oe", "germandbls", "onesuperior", - "logicalnot", "mu", "trademark", "Eth", "onehalf", "plusminus", "Thorn", - "onequarter", "divide", "brokenbar", "degree", "thorn", "threequarters", - "twosuperior", "registered", "minus", "eth", "multiply", "threesuperior", - "copyright", "Aacute", "Acircumflex", "Adieresis", "Agrave", "Aring", - "Atilde", "Ccedilla", "Eacute", "Ecircumflex", "Edieresis", "Egrave", - "Iacute", "Icircumflex", "Idieresis", "Igrave", "Ntilde", "Oacute", - "Ocircumflex", "Odieresis", "Ograve", "Otilde", "Scaron", "Uacute", - "Ucircumflex", "Udieresis", "Ugrave", "Yacute", "Ydieresis", "Zcaron", - "aacute", "acircumflex", "adieresis", "agrave", "aring", "atilde", - "ccedilla", "eacute", "ecircumflex", "edieresis", "egrave", "iacute", - "icircumflex", "idieresis", "igrave", "ntilde", "oacute", "ocircumflex", - "odieresis", "ograve", "otilde", "scaron", "uacute", "ucircumflex", - "udieresis", "ugrave", "yacute", "ydieresis", "zcaron", "exclamsmall", - "Hungarumlautsmall", "dollaroldstyle", "dollarsuperior", "ampersandsmall", - "Acutesmall", "parenleftsuperior", "parenrightsuperior", "twodotenleader", - "onedotenleader", "zerooldstyle", "oneoldstyle", "twooldstyle", - "threeoldstyle", "fouroldstyle", "fiveoldstyle", "sixoldstyle", - "sevenoldstyle", "eightoldstyle", "nineoldstyle", "commasuperior", - "threequartersemdash", "periodsuperior", "questionsmall", "asuperior", - "bsuperior", "centsuperior", "dsuperior", "esuperior", "isuperior", - "lsuperior", "msuperior", "nsuperior", "osuperior", "rsuperior", "ssuperior", - "tsuperior", "ff", "ffi", "ffl", "parenleftinferior", "parenrightinferior", - "Circumflexsmall", "hyphensuperior", "Gravesmall", "Asmall", "Bsmall", - "Csmall", "Dsmall", "Esmall", "Fsmall", "Gsmall", "Hsmall", "Ismall", - "Jsmall", "Ksmall", "Lsmall", "Msmall", "Nsmall", "Osmall", "Psmall", - "Qsmall", "Rsmall", "Ssmall", "Tsmall", "Usmall", "Vsmall", "Wsmall", - "Xsmall", "Ysmall", "Zsmall", "colonmonetary", "onefitted", "rupiah", - "Tildesmall", "exclamdownsmall", "centoldstyle", "Lslashsmall", - "Scaronsmall", "Zcaronsmall", "Dieresissmall", "Brevesmall", "Caronsmall", - "Dotaccentsmall", "Macronsmall", "figuredash", "hypheninferior", - "Ogoneksmall", "Ringsmall", "Cedillasmall", "questiondownsmall", "oneeighth", - "threeeighths", "fiveeighths", "seveneighths", "onethird", "twothirds", - "zerosuperior", "foursuperior", "fivesuperior", "sixsuperior", - "sevensuperior", "eightsuperior", "ninesuperior", "zeroinferior", - "oneinferior", "twoinferior", "threeinferior", "fourinferior", - "fiveinferior", "sixinferior", "seveninferior", "eightinferior", - "nineinferior", "centinferior", "dollarinferior", "periodinferior", - "commainferior", "Agravesmall", "Aacutesmall", "Acircumflexsmall", - "Atildesmall", "Adieresissmall", "Aringsmall", "AEsmall", "Ccedillasmall", - "Egravesmall", "Eacutesmall", "Ecircumflexsmall", "Edieresissmall", - "Igravesmall", "Iacutesmall", "Icircumflexsmall", "Idieresissmall", - "Ethsmall", "Ntildesmall", "Ogravesmall", "Oacutesmall", "Ocircumflexsmall", - "Otildesmall", "Odieresissmall", "OEsmall", "Oslashsmall", "Ugravesmall", - "Uacutesmall", "Ucircumflexsmall", "Udieresissmall", "Yacutesmall", - "Thornsmall", "Ydieresissmall", "001.000", "001.001", "001.002", "001.003", - "Black", "Bold", "Book", "Light", "Medium", "Regular", "Roman", "Semibold", -} - -local cffreaders = { - readbyte, - readushort, - readuint, - readulong, -} - --- The header contains information about its own size. - -local function readheader(f) - local offset = getposition(f) - local header = { - offset = offset, - major = readbyte(f), - minor = readbyte(f), - size = readbyte(f), -- headersize - osize = readbyte(f), -- for offsets to start - } - setposition(f,offset+header.size) - return header -end - --- The indexes all look the same, so we share a loader. We could pass a handler --- and run over the array but why bother, we only have a few uses. - -local function readlengths(f) - local count = readushort(f) - if count == 0 then - return { } - end - local osize = readbyte(f) - local read = cffreaders[osize] - if not read then - report("bad offset size: %i",osize) - return { } - end - local lengths = { } - local previous = read(f) - for i=1,count do - local offset = read(f) - lengths[i] = offset - previous - previous = offset - end - return lengths -end - --- There can be subfonts so names is an array. However, in our case it's always --- one font. The same is true for the top dictionaries. Watch how we only load --- the dictionary string as for interpretation we need to have the strings loaded --- as well. - -local function readfontnames(f) - local names = readlengths(f) - for i=1,#names do - names[i] = readstring(f,names[i]) - end - return names -end - -local function readtopdictionaries(f) - local dictionaries = readlengths(f) - for i=1,#dictionaries do - dictionaries[i] = readstring(f,dictionaries[i]) - end - return dictionaries -end - --- Strings are added to a list of standard strings so we start the font specific --- one with an offset. Strings are shared so we have one table. - -local function readstrings(f) - local lengths = readlengths(f) - local strings = setmetatableindex({ }, defaultstrings) - local index = #defaultstrings - for i=1,#lengths do - index = index + 1 - strings[index] = readstring(f,lengths[i]) - end - return strings -end - --- Parsing the dictionaries is delayed till we have the strings loaded. The parser --- is stack based so the operands come before the operator (like in postscript). - --- local function delta(t) --- local n = #t --- if n > 1 then --- local p = t[1] --- for i=2,n do --- local c = t[i] --- t[i] = c + p --- p = c --- end --- end --- end - -do - - -- We use a closure so that we don't need to pass too much around. - - local stack = { } - local top = 0 - local result = { } - local strings = { } - - local p_single = - P("\00") / function() - result.version = strings[stack[top]] or "unset" - top = 0 - end - + P("\01") / function() - result.notice = strings[stack[top]] or "unset" - top = 0 - end - + P("\02") / function() - result.fullname = strings[stack[top]] or "unset" - top = 0 - end - + P("\03") / function() - result.familyname = strings[stack[top]] or "unset" - top = 0 - end - + P("\04") / function() - result.weight = strings[stack[top]] or "unset" - top = 0 - end - + P("\05") / function() - result.fontbbox = { unpack(stack,1,4) } - top = 0 - end - -- + P("\06") / function() end -- bluevalues - -- + P("\07") / function() end -- otherblues - -- + P("\08") / function() end -- familyblues - -- + P("\09") / function() end -- familyotherblues - -- + P("\10") / function() end -- strhw - -- + P("\11") / function() end -- stdvw - + P("\13") / function() - result.uniqueid = stack[top] - top = 0 - end - + P("\14") / function() - result.xuid = concat(stack,"",1,top) - top = 0 - end - + P("\15") / function() - result.charset = stack[top] - top = 0 - end - + P("\16") / function() - result.encoding = stack[top] - top = 0 - end - + P("\17") / function() - result.charstrings = stack[top] - top = 0 - end - + P("\18") / function() - result.private = { - size = stack[top-1], - offset = stack[top], - } - top = 0 - end - + P("\19") / function() - result.subroutines = stack[top] - end - + P("\20") / function() - result.defaultwidthx = stack[top] - end - + P("\21") / function() - result.nominalwidthx = stack[top] - end - -- + P("\22") / function() end -- reserved - -- + P("\23") / function() end -- reserved - -- + P("\24") / function() end -- reserved - -- + P("\25") / function() end -- reserved - -- + P("\26") / function() end -- reserved - -- + P("\27") / function() end -- reserved - - local p_double = P("\12") * ( - P("\00") / function() - result.copyright = stack[top] - top = 0 - end - + P("\01") / function() - result.monospaced = stack[top] == 1 and true or false -- isfixedpitch - top = 0 - end - + P("\02") / function() - result.italicangle = stack[top] - top = 0 - end - + P("\03") / function() - result.underlineposition = stack[top] - top = 0 - end - + P("\04") / function() - result.underlinethickness = stack[top] - top = 0 - end - + P("\05") / function() - result.painttype = stack[top] - top = 0 - end - + P("\06") / function() - result.charstringtype = stack[top] - top = 0 - end - + P("\07") / function() - result.fontmatrix = { unpack(stack,1,6) } - top = 0 - end - + P("\08") / function() - result.strokewidth = stack[top] - top = 0 - end - + P("\20") / function() - result.syntheticbase = stack[top] - top = 0 - end - + P("\21") / function() - result.postscript = strings[stack[top]] or "unset" - top = 0 - end - + P("\22") / function() - result.basefontname = strings[stack[top]] or "unset" - top = 0 - end - + P("\21") / function() - result.basefontblend = stack[top] - top = 0 - end - + P("\30") / function() - result.cid.registry = strings[stack[top-2]] or "unset" - result.cid.ordering = strings[stack[top-1]] or "unset" - result.cid.supplement = stack[top] - top = 0 - end - + P("\31") / function() - result.cid.fontversion = stack[top] - top = 0 - end - + P("\32") / function() - result.cid.fontrevision= stack[top] - top = 0 - end - + P("\33") / function() - result.cid.fonttype = stack[top] - top = 0 - end - + P("\34") / function() - result.cid.count = stack[top] - top = 0 - end - + P("\35") / function() - result.cid.uidbase = stack[top] - top = 0 - end - + P("\36") / function() - result.cid.fdarray = stack[top] - top = 0 - end - + P("\37") / function() - result.cid.fdselect = stack[top] - top = 0 - end - + P("\38") / function() - result.cid.fontname = strings[stack[top]] or "unset" - top = 0 - end - ) - - -- Some lpeg fun ... a first variant split the byte and made a new string but - -- the second variant is much faster. Not that it matters much as we don't see - -- such numbers often. - - local p_last = P("\x0F") / "0" + P("\x1F") / "1" + P("\x2F") / "2" + P("\x3F") / "3" - + P("\x4F") / "4" + P("\x5F") / "5" + P("\x6F") / "6" + P("\x7F") / "7" - + P("\x8F") / "8" + P("\x9F") / "9" + P("\xAF") / "" + P("\xBF") / "" - + P("\xCF") / "" + P("\xDF") / "" + P("\xEF") / "" + R("\xF0\xFF") / "" - - -- local remap = { [0] = - -- "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0.", "0E", "0E-", "0", "0-", "0", - -- "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "0.", "0E", "0E-", "0", "0-", "0", - -- "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "0.", "0E", "0E-", "0", "0-", "0", - -- "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "0.", "0E", "0E-", "0", "0-", "0", - -- "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "0.", "0E", "0E-", "0", "0-", "0", - -- "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "0.", "0E", "0E-", "0", "0-", "0", - -- "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "0.", "0E", "0E-", "0", "0-", "0", - -- "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "0.", "0E", "0E-", "0", "0-", "0", - -- "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "0.", "0E", "0E-", "0", "0-", "0", - -- "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "0.", "0E", "0E-", "0", "0-", "0", - -- ".0", ".1", ".2", ".3", ".4", ".5", ".6", ".7", ".8", ".9", "..", ".E", ".E-", ".", ".-", ".", - -- "E0", "E1", "E2", "E3", "E4", "E5", "E6", "E7", "E8", "E9", "E.", "EE", "EE-", "E", "E-", "E", - -- "E-0", "E-1", "E-2", "E-3", "E-4", "E-5", "E-6", "E-7", "E-8", "E-9", "E-.", "E-E", "E-E-", "E-", "E--", "E-", - -- "-0", "-1", "-2", "-3", "-4", "-5", "-6", "-7", "-8", "-9", "-.", "-E", "-E-", "-", "--", "-", - -- } - - -- local p_nibbles = Cs(((1-p_last)/byte/remap)^0+p_last) - - -- local p = P("\30") * p_nibbles / function(t) - -- print(tonumber(t)) - -- end - - local remap = { - ["\x00"] = "00", ["\x01"] = "01", ["\x02"] = "02", ["\x03"] = "03", ["\x04"] = "04", ["\x05"] = "05", ["\x06"] = "06", ["\x07"] = "07", ["\x08"] = "08", ["\x09"] = "09", ["\x0A"] = "0.", ["\x0B"] = "0E", ["\x0C"] = "0E-", ["\x0D"] = "0", ["\x0E"] = "0-", ["\x0F"] = "0", - ["\x10"] = "10", ["\x11"] = "11", ["\x12"] = "12", ["\x13"] = "13", ["\x14"] = "14", ["\x15"] = "15", ["\x16"] = "16", ["\x17"] = "17", ["\x18"] = "18", ["\x19"] = "19", ["\x1A"] = "0.", ["\x1B"] = "0E", ["\x1C"] = "0E-", ["\x1D"] = "0", ["\x1E"] = "0-", ["\x1F"] = "0", - ["\x20"] = "20", ["\x21"] = "21", ["\x22"] = "22", ["\x23"] = "23", ["\x24"] = "24", ["\x25"] = "25", ["\x26"] = "26", ["\x27"] = "27", ["\x28"] = "28", ["\x29"] = "29", ["\x2A"] = "0.", ["\x2B"] = "0E", ["\x2C"] = "0E-", ["\x2D"] = "0", ["\x2E"] = "0-", ["\x2F"] = "0", - ["\x30"] = "30", ["\x31"] = "31", ["\x32"] = "32", ["\x33"] = "33", ["\x34"] = "34", ["\x35"] = "35", ["\x36"] = "36", ["\x37"] = "37", ["\x38"] = "38", ["\x39"] = "39", ["\x3A"] = "0.", ["\x3B"] = "0E", ["\x3C"] = "0E-", ["\x3D"] = "0", ["\x3E"] = "0-", ["\x3F"] = "0", - ["\x40"] = "40", ["\x41"] = "41", ["\x42"] = "42", ["\x43"] = "43", ["\x44"] = "44", ["\x45"] = "45", ["\x46"] = "46", ["\x47"] = "47", ["\x48"] = "48", ["\x49"] = "49", ["\x4A"] = "0.", ["\x4B"] = "0E", ["\x4C"] = "0E-", ["\x4D"] = "0", ["\x4E"] = "0-", ["\x4F"] = "0", - ["\x50"] = "50", ["\x51"] = "51", ["\x52"] = "52", ["\x53"] = "53", ["\x54"] = "54", ["\x55"] = "55", ["\x56"] = "56", ["\x57"] = "57", ["\x58"] = "58", ["\x59"] = "59", ["\x5A"] = "0.", ["\x5B"] = "0E", ["\x5C"] = "0E-", ["\x5D"] = "0", ["\x5E"] = "0-", ["\x5F"] = "0", - ["\x60"] = "60", ["\x61"] = "61", ["\x62"] = "62", ["\x63"] = "63", ["\x64"] = "64", ["\x65"] = "65", ["\x66"] = "66", ["\x67"] = "67", ["\x68"] = "68", ["\x69"] = "69", ["\x6A"] = "0.", ["\x6B"] = "0E", ["\x6C"] = "0E-", ["\x6D"] = "0", ["\x6E"] = "0-", ["\x6F"] = "0", - ["\x70"] = "70", ["\x71"] = "71", ["\x72"] = "72", ["\x73"] = "73", ["\x74"] = "74", ["\x75"] = "75", ["\x76"] = "76", ["\x77"] = "77", ["\x78"] = "78", ["\x79"] = "79", ["\x7A"] = "0.", ["\x7B"] = "0E", ["\x7C"] = "0E-", ["\x7D"] = "0", ["\x7E"] = "0-", ["\x7F"] = "0", - ["\x80"] = "80", ["\x81"] = "81", ["\x82"] = "82", ["\x83"] = "83", ["\x84"] = "84", ["\x85"] = "85", ["\x86"] = "86", ["\x87"] = "87", ["\x88"] = "88", ["\x89"] = "89", ["\x8A"] = "0.", ["\x8B"] = "0E", ["\x8C"] = "0E-", ["\x8D"] = "0", ["\x8E"] = "0-", ["\x8F"] = "0", - ["\x90"] = "90", ["\x91"] = "91", ["\x92"] = "92", ["\x93"] = "93", ["\x94"] = "94", ["\x95"] = "95", ["\x96"] = "96", ["\x97"] = "97", ["\x98"] = "98", ["\x99"] = "99", ["\x9A"] = "0.", ["\x9B"] = "0E", ["\x9C"] = "0E-", ["\x9D"] = "0", ["\x9E"] = "0-", ["\x9F"] = "0", - ["\xA0"] = ".0", ["\xA1"] = ".1", ["\xA2"] = ".2", ["\xA3"] = ".3", ["\xA4"] = ".4", ["\xA5"] = ".5", ["\xA6"] = ".6", ["\xA7"] = ".7", ["\xA8"] = ".8", ["\xA9"] = ".9", ["\xAA"] = "..", ["\xAB"] = ".E", ["\xAC"] = ".E-", ["\xAD"] = ".", ["\xAE"] = ".-", ["\xAF"] = ".", - ["\xB0"] = "E0", ["\xB1"] = "E1", ["\xB2"] = "E2", ["\xB3"] = "E3", ["\xB4"] = "E4", ["\xB5"] = "E5", ["\xB6"] = "E6", ["\xB7"] = "E7", ["\xB8"] = "E8", ["\xB9"] = "E9", ["\xBA"] = "E.", ["\xBB"] = "EE", ["\xBC"] = "EE-", ["\xBD"] = "E", ["\xBE"] = "E-", ["\xBF"] = "E", - ["\xC0"] = "E-0", ["\xC1"] = "E-1", ["\xC2"] = "E-2", ["\xC3"] = "E-3", ["\xC4"] = "E-4", ["\xC5"] = "E-5", ["\xC6"] = "E-6", ["\xC7"] = "E-7", ["\xC8"] = "E-8", ["\xC9"] = "E-9", ["\xCA"] = "E-.", ["\xCB"] = "E-E", ["\xCC"] = "E-E-", ["\xCD"] = "E-", ["\xCE"] = "E--", ["\xCF"] = "E-", - ["\xD0"] = "-0", ["\xD1"] = "-1", ["\xD2"] = "-2", ["\xD3"] = "-3", ["\xD4"] = "-4", ["\xD5"] = "-5", ["\xD6"] = "-6", ["\xD7"] = "-7", ["\xD8"] = "-8", ["\xD9"] = "-9", ["\xDA"] = "-.", ["\xDB"] = "-E", ["\xDC"] = "-E-", ["\xDD"] = "-", ["\xDE"] = "--", ["\xDF"] = "-", - } - - local p_nibbles = P("\30") * Cs(((1-p_last)/remap)^0+p_last) / function(n) - -- 0-9=digit a=. b=E c=E- d=reserved e=- f=finish - top = top + 1 - stack[top] = tonumber(n) or 0 - end - - local p_byte = C(R("\32\246")) / function(b0) - -- -107 .. +107 - top = top + 1 - stack[top] = byte(b0) - 139 - end - - local p_positive = C(R("\247\250")) * C(1) / function(b0,b1) - -- +108 .. +1131 - top = top + 1 - stack[top] = (byte(b0)-247)*256 + byte(b1) + 108 - end - - local p_negative = C(R("\251\254")) * C(1) / function(b0,b1) - -- -1131 .. -108 - top = top + 1 - stack[top] = -(byte(b0)-251)*256 - byte(b1) - 108 - end - - local p_short = P("\28") * C(1) * C(1) / function(b1,b2) - -- -32768 .. +32767 : b1<<8 | b2 - top = top + 1 - local n = 0x100 * byte(b1) + byte(b2) - if n >= 0x8000 then - stack[top] = n - 0xFFFF - 1 - else - stack[top] = n - end - end - - local p_long = P("\29") * C(1) * C(1) * C(1) * C(1) / function(b1,b2,b3,b4) - -- -2^31 .. +2^31-1 : b1<<24 | b2<<16 | b3<<8 | b4 - top = top + 1 - local n = 0x1000000 * byte(b1) + 0x10000 * byte(b2) + 0x100 * byte(b3) + byte(b4) - if n >= 0x8000000 then - stack[top] = n - 0xFFFFFFFF - 1 - else - stack[top] = n - end - end - - local p_unsupported = P(1) / function(detail) - top = 0 - end - - local p_dictionary = ( - p_byte - + p_positive - + p_negative - + p_short - + p_long - + p_nibbles - + p_single - + p_double - + p_unsupported - )^1 - - parsedictionaries = function(data,dictionaries) - stack = { } - strings = data.strings - for i=1,#dictionaries do - top = 0 - result = { - monospaced = false, - italicangle = 0, - underlineposition = -100, - underlinethickness = 50, - painttype = 0, - charstringtype = 2, - fontmatrix = { 0.001, 0, 0, 0.001, 0, 0 }, - fontbbox = { 0, 0, 0, 0 }, - strokewidth = 0, - charset = 0, - encoding = 0, - cid = { - fontversion = 0, - fontrevision = 0, - fonttype = 0, - count = 8720, - } - } - lpegmatch(p_dictionary,dictionaries[i]) - dictionaries[i] = result - end - -- - result = { } - top = 0 - stack = { } - end - - parseprivates = function(data,dictionaries) - stack = { } - strings = data.strings - for i=1,#dictionaries do - local private = dictionaries[i].private - if private and private.data then - top = 0 - result = { - forcebold = false, - languagegroup = 0, - expansionfactor = 0.06, - initialrandomseed = 0, - subroutines = 0, - defaultwidthx = 0, - nominalwidthx = 0, - cid = { - -- actually an error - }, - } - lpegmatch(p_dictionary,private.data) - private.data = result - end - end - result = { } - top = 0 - stack = { } - end - - -- All bezier curves have 6 points with successive pairs relative to - -- the previous pair. Some can be left out and are then copied or zero - -- (optimization). - -- - -- We are not really interested in all the details of a glyph because we - -- only need to calculate the boundingbox. So, todo: a quick no result but - -- calculate only variant. - -- - -- The conversion is straightforward and the specification os clear once - -- you understand that the x and y needs to be updates each step. It's also - -- quite easy to test because in mp a shape will look bad when a few variables - -- are swapped. But still there might be bugs down here because not all - -- variants are seen in a font so far. We are less compact that the ff code - -- because there quite some variants are done in one helper with a lot of - -- testing for states. - - local x = 0 - local y = 0 - local width = false - local r = 0 - local stems = 0 - local globalbias = 0 - local localbias = 0 - local globals = false - local locals = false - local depth = 1 - local xmin = 0 - local xmax = 0 - local ymin = 0 - local ymax = 0 - local checked = false - local keepcurve = false - local version = 2 - - local function showstate(where) - report("%w%-10s : [%s] n=%i",depth*2,where,concat(stack," ",1,top),top) - end - - local function showvalue(where,value,showstack) - if showstack then - report("%w%-10s : %s : [%s] n=%i",depth*2,where,tostring(value),concat(stack," ",1,top),top) - else - report("%w%-10s : %s",depth*2,where,tostring(value)) - end - end - - -- All these indirect calls make this run slower but it's cleaner this way - -- and we cache the result. As we moved the boundingbox code inline we gain - -- some back. - - local function moveto(x,y) - if keepcurve then - r = r + 1 - result[r] = { x, y, "m" } - end - if checked then - if x < xmin then xmin = x elseif x > xmax then xmax = x end - if y < ymin then ymin = y elseif y > ymax then ymax = y end - else - xmin = x - ymin = y - xmax = x - ymax = y - checked = true - end - end - - local function lineto(x,y) - if keepcurve then - r = r + 1 - result[r] = { x, y, "l" } - end - if checked then - if x < xmin then xmin = x elseif x > xmax then xmax = x end - if y < ymin then ymin = y elseif y > ymax then ymax = y end - else - xmin = x - ymin = y - xmax = x - ymax = y - checked = true - end - end - - local function curveto(x1,y1,x2,y2,x3,y3) - if keepcurve then - r = r + 1 - result[r] = { x1, y1, x2, y2, x3, y3, "c" } - end - if checked then - if x1 < xmin then xmin = x1 elseif x1 > xmax then xmax = x1 end - if y1 < ymin then ymin = y1 elseif y1 > ymax then ymax = y1 end - else - xmin = x1 - ymin = y1 - xmax = x1 - ymax = y1 - checked = true - end - if x2 < xmin then xmin = x2 elseif x2 > xmax then xmax = x2 end - if y2 < ymin then ymin = y2 elseif y2 > ymax then ymax = y2 end - if x3 < xmin then xmin = x3 elseif x3 > xmax then xmax = x3 end - if y3 < ymin then ymin = y3 elseif y3 > ymax then ymax = y3 end - end - - local function rmoveto() - if top > 2 then - if not width then - width = stack[1] - if trace_charstrings then - showvalue("width",width) - end - end - elseif not width then - width = true - end - if trace_charstrings then - showstate("rmoveto") - end - x = x + stack[top-1] -- dx1 - y = y + stack[top] -- dy1 - top = 0 - moveto(x,y) - end - - local function hmoveto() - if top > 1 then - if not width then - width = stack[1] - if trace_charstrings then - showvalue("width",width) - end - end - elseif not width then - width = true - end - if trace_charstrings then - showstate("hmoveto") - end - x = x + stack[top] -- dx1 - top = 0 - moveto(x,y) - end - - local function vmoveto() - if top > 1 then - if not width then - width = stack[1] - if trace_charstrings then - showvalue("width",width) - end - end - elseif not width then - width = true - end - if trace_charstrings then - showstate("vmoveto") - end - y = y + stack[top] -- dy1 - top = 0 - moveto(x,y) - end - - local function rlineto() - if trace_charstrings then - showstate("rlineto") - end - for i=1,top,2 do - x = x + stack[i] -- dxa - y = y + stack[i+1] -- dya - lineto(x,y) - end - top = 0 - end - - local function xlineto(swap) -- x (y,x)+ | (x,y)+ - for i=1,top do - if swap then - x = x + stack[i] - swap = false - else - y = y + stack[i] - swap = true - end - lineto(x,y) - end - top = 0 - end - - local function hlineto() -- x (y,x)+ | (x,y)+ - if trace_charstrings then - showstate("hlineto") - end - xlineto(true) - end - - local function vlineto() -- y (x,y)+ | (y,x)+ - if trace_charstrings then - showstate("vlineto") - end - xlineto(false) - end - - local function rrcurveto() - if trace_charstrings then - showstate("rrcurveto") - end - for i=1,top,6 do - local ax = x + stack[i] -- dxa - local ay = y + stack[i+1] -- dya - local bx = ax + stack[i+2] -- dxb - local by = ay + stack[i+3] -- dyb - x = bx + stack[i+4] -- dxc - y = by + stack[i+5] -- dyc - curveto(ax,ay,bx,by,x,y) - end - top = 0 - end - - local function hhcurveto() - if trace_charstrings then - showstate("hhcurveto") - end - local s = 1 - if top % 2 ~= 0 then - y = y + stack[1] -- dy1 - s = 2 - end - for i=s,top,4 do - local ax = x + stack[i] -- dxa - local ay = y - local bx = ax + stack[i+1] -- dxb - local by = ay + stack[i+2] -- dyb - x = bx + stack[i+3] -- dxc - y = by - curveto(ax,ay,bx,by,x,y) - end - top = 0 - end - - local function vvcurveto() - if trace_charstrings then - showstate("vvcurveto") - end - local s = 1 - local d = 0 - if top % 2 ~= 0 then - d = stack[1] -- dx1 - s = 2 - end - for i=s,top,4 do - local ax = x + d - local ay = y + stack[i] -- dya - local bx = ax + stack[i+1] -- dxb - local by = ay + stack[i+2] -- dyb - x = bx - y = by + stack[i+3] -- dyc - curveto(ax,ay,bx,by,x,y) - d = 0 - end - top = 0 - end - - local function xxcurveto(swap) - local last = top % 4 ~= 0 and stack[top] - if last then - top = top - 1 - end - local sw = swap - for i=1,top,4 do - local ax, ay, bx, by - if swap then - ax = x + stack[i] - ay = y - bx = ax + stack[i+1] - by = ay + stack[i+2] - y = by + stack[i+3] - if last and i+3 == top then - x = bx + last - else - x = bx - end - swap = false - else - ax = x - ay = y + stack[i] - bx = ax + stack[i+1] - by = ay + stack[i+2] - x = bx + stack[i+3] - if last and i+3 == top then - y = by + last - else - y = by - end - swap = true - end - curveto(ax,ay,bx,by,x,y) - end - top = 0 - end - - local function hvcurveto() - if trace_charstrings then - showstate("hvcurveto") - end - xxcurveto(true) - end - - local function vhcurveto() - if trace_charstrings then - showstate("vhcurveto") - end - xxcurveto(false) - end - - local function rcurveline() - if trace_charstrings then - showstate("rcurveline") - end - for i=1,top-2,6 do - local ax = x + stack[i] -- dxa - local ay = y + stack[i+1] -- dya - local bx = ax + stack[i+2] -- dxb - local by = ay + stack[i+3] -- dyb - x = bx + stack[i+4] -- dxc - y = by + stack[i+5] -- dyc - curveto(ax,ay,bx,by,x,y) - end - x = x + stack[top-1] -- dxc - y = y + stack[top] -- dyc - lineto(x,y) - top = 0 - end - - local function rlinecurve() - if trace_charstrings then - showstate("rlinecurve") - end - if top > 6 then - for i=1,top-6,2 do - x = x + stack[i] - y = y + stack[i+1] - lineto(x,y) - end - end - local ax = x + stack[top-5] - local ay = y + stack[top-4] - local bx = ax + stack[top-3] - local by = ay + stack[top-2] - x = bx + stack[top-1] - y = by + stack[top] - curveto(ax,ay,bx,by,x,y) - top = 0 - end - - -- flex is not yet tested! no loop - - local function flex() -- fd not used - if trace_charstrings then - showstate("flex") - end - local ax = x + stack[1] -- dx1 - local ay = y + stack[2] -- dy1 - local bx = ax + stack[3] -- dx2 - local by = ay + stack[4] -- dy2 - local cx = bx + stack[5] -- dx3 - local cy = by + stack[6] -- dy3 - curveto(ax,ay,bx,by,cx,cy) - local dx = cx + stack[7] -- dx4 - local dy = cy + stack[8] -- dy4 - local ex = dx + stack[9] -- dx5 - local ey = dy + stack[10] -- dy5 - x = ex + stack[11] -- dx6 - y = ey + stack[12] -- dy6 - curveto(dx,dy,ex,ey,x,y) - top = 0 - end - - local function hflex() - if trace_charstrings then - showstate("hflex") - end - local ax = x + stack[1] -- dx1 - local ay = y - local bx = ax + stack[2] -- dx2 - local by = ay + stack[3] -- dy2 - local cx = bx + stack[4] -- dx3 - local cy = by - curveto(ax,ay,bx,by,cx,cy) - local dx = cx + stack[5] -- dx4 - local dy = by - local ex = dx + stack[6] -- dx5 - local ey = y - x = ex + stack[7] -- dx6 - curveto(dx,dy,ex,ey,x,y) - top = 0 - end - - local function hflex1() - if trace_charstrings then - showstate("hflex1") - end - local ax = x + stack[1] -- dx1 - local ay = y + stack[2] -- dy1 - local bx = ax + stack[3] -- dx2 - local by = ay + stack[4] -- dy2 - local cx = bx + stack[5] -- dx3 - local cy = by - curveto(ax,ay,bx,by,cx,cy) - local dx = cx + stack[6] -- dx4 - local dy = by - local ex = dx + stack[7] -- dx5 - local ey = dy + stack[8] -- dy5 - x = ex + stack[9] -- dx6 - curveto(dx,dy,ex,ey,x,y) - top = 0 - end - - local function flex1() - if trace_charstrings then - showstate("flex1") - end - local ax = x + stack[1] --dx1 - local ay = y + stack[2] --dy1 - local bx = ax + stack[3] --dx2 - local by = ay + stack[4] --dy2 - local cx = bx + stack[5] --dx3 - local cy = by + stack[6] --dy3 - curveto(ax,ay,bx,by,cx,cy) - local dx = cx + stack[7] --dx4 - local dy = cy + stack[8] --dy4 - local ex = dx + stack[9] --dx5 - local ey = dy + stack[10] --dy5 - if abs(ex - x) > abs(ey - y) then -- spec: abs(dx) > abs(dy) - x = ex + stack[11] - else - y = ey + stack[11] - end - curveto(dx,dy,ex,ey,x,y) - top = 0 - end - - local function getstem() - if top == 0 then - -- bad - elseif top % 2 ~= 0 then - if width then - remove(stack,1) - else - width = remove(stack,1) - if trace_charstrings then - showvalue("width",width) - end - end - top = top - 1 - end - if trace_charstrings then - showstate("stem") - end - stems = stems + top/2 - top = 0 - end - - local function getmask() - if top == 0 then - -- bad - elseif top % 2 ~= 0 then - if width then - remove(stack,1) - else - width = remove(stack,1) - if trace_charstrings then - showvalue("width",width) - end - end - top = top - 1 - end - if trace_charstrings then - showstate(operator == 19 and "hintmark" or "cntrmask") - end - stems = stems + top/2 - top = 0 - if stems == 0 then - -- forget about it - elseif stems <= 8 then - return 1 - else - return floor((stems+7)/8) - end - end - - local function unsupported(t) - if trace_charstrings then - showstate("unsupported " .. t) - end - top = 0 - end - - local function unsupportedsub(t) - if trace_charstrings then - showstate("unsupported sub " .. t) - end - top = 0 - end - - -- type 1 (not used in type 2) - - local function getstem3() - if trace_charstrings then - showstate("stem3") - end - top = 0 - end - - local function divide() - if version == 1 then - local d = stack[top] - top = top - 1 - stack[top] = stack[top] / d - end - end - - local function closepath() - if version == 1 then - if trace_charstrings then - showstate("closepath") - end - end - top = 0 - end - - local function hsbw() - if version == 1 then - if trace_charstrings then - showstate("dotsection") - end - width = stack[top] - end - top = 0 - end - - local function seac() - if version == 1 then - if trace_charstrings then - showstate("seac") - end - end - top = 0 - end - - local function sbw() - if version == 1 then - if trace_charstrings then - showstate("sbw") - end - width = stack[top-1] - end - top = 0 - end - - -- these are probably used for special cases i.e. call out to postscript - - local function callothersubr() - if version == 1 then - -- we don't support this (ok, we could mimick these othersubs) - if trace_charstrings then - showstate("callothersubr (unsupported)") - end - end - top = 0 - end - - local function pop() - if version == 1 then - -- we don't support this - if trace_charstrings then - showstate("pop (unsupported)") - end - top = top + 1 - stack[top] = 0 -- a dummy - else - top = 0 - end - end - - local function setcurrentpoint() - if version == 1 then - -- we don't support this - if trace_charstrings then - showstate("pop (unsupported)") - end - x = x + stack[top-1] - y = y + stack[top] - end - top = 0 - end - - -- so far for unsupported postscript - - -- Bah, we cannot use a fast lpeg because a hint has an unknown size and a - -- runtime capture cannot handle that well. - - local actions = { [0] = - unsupported, -- 0 - getstem, -- 1 -- hstem - unsupported, -- 2 - getstem, -- 3 -- vstem - vmoveto, -- 4 - rlineto, -- 5 - hlineto, -- 6 - vlineto, -- 7 - rrcurveto, -- 8 - unsupported, -- 9 -- closepath - unsupported, -- 10 -- calllocal, - unsupported, -- 11 -- callreturn, - unsupported, -- 12 -- elsewhere - hsbw, -- 13 -- hsbw (type 1 cff) - unsupported, -- 14 -- endchar, - unsupported, -- 15 - unsupported, -- 16 - unsupported, -- 17 - getstem, -- 18 -- hstemhm - getmask, -- 19 -- hintmask - getmask, -- 20 -- cntrmask - rmoveto, -- 21 - hmoveto, -- 22 - getstem, -- 23 -- vstemhm - rcurveline, -- 24 - rlinecurve, -- 25 - vvcurveto, -- 26 - hhcurveto, -- 27 - unsupported, -- 28 -- elsewhere - unsupported, -- 29 -- elsewhere - vhcurveto, -- 30 - hvcurveto, -- 31 - } - - local subactions = { - -- cff 1 - [000] = dotsection, - [001] = getstem3, - [002] = getstem3, - [006] = seac, - [007] = sbw, - [012] = divide, - [016] = callothersubr, - [017] = pop, - [033] = setcurrentpoint, - -- cff 2 - [034] = hflex, - [035] = flex, - [036] = hflex1, - [037] = flex1, - } - - local p_bytes = Ct((P(1)/byte)^0) - - local function call(scope,list,bias,process) - depth = depth + 1 - if top == 0 then - showstate(formatters["unknown %s call"](scope)) - top = 0 - else - local index = stack[top] + bias - top = top - 1 - if trace_charstrings then - showvalue(scope,index,true) - end - local tab = list[index] - if tab then - if type(tab) == "string" then - tab = lpegmatch(p_bytes,tab) - list[index] = tab - end - process(tab) - else - showstate(formatters["unknown %s call %i"](scope,index)) - top = 0 - end - end - depth = depth - 1 - end - - local function process(tab) - local i = 1 - local n = #tab - while i <= n do - local t = tab[i] - if t >= 32 and t <= 246 then - -- -107 .. +107 - top = top + 1 - stack[top] = t - 139 - i = i + 1 - elseif t >= 247 and t <= 250 then - -- +108 .. +1131 - top = top + 1 - stack[top] = (t-247)*256 + tab[i+1] + 108 - i = i + 2 - elseif t >= 251 and t <= 254 then - -- -1131 .. -108 - top = top + 1 - stack[top] = -(t-251)*256 - tab[i+1] - 108 - i = i + 2 - elseif t == 28 then - -- -32768 .. +32767 : b1<<8 | b2 - top = top + 1 - local n = 0x100 * tab[i+1] + tab[i+2] - if n >= 0x8000 then - stack[top] = n - 0xFFFF - 1 - else - stack[top] = n - end - i = i + 3 - elseif t == 255 then - local n = 0x100 * tab[i+1] + tab[i+2] - top = top + 1 - if n >= 0x8000 then - stack[top] = n - 0xFFFF - 1 + (0x100 * tab[i+3] + tab[i+4])/0xFFFF - else - stack[top] = n + (0x100 * tab[i+3] + tab[i+4])/0xFFFF - end - i = i + 5 - elseif t == 11 then - if trace_charstrings then - showstate("return") - end - return - elseif t == 10 then - call("local",locals,localbias,process) - i = i + 1 - elseif t == 14 then -- endchar - if width then - -- okay - elseif top > 0 then - width = stack[1] - if trace_charstrings then - showvalue("width",width) - end - else - width = true - end - if trace_charstrings then - showstate("endchar") - end - return - elseif t == 29 then - call("global",globals,globalbias,process) - i = i + 1 - elseif t == 12 then - i = i + 1 - local t = tab[i] - local a = subactions[t] - if a then - a(t) - else - if trace_charstrings then - showvalue("<subaction>",t) - end - top = 0 - end - i = i + 1 - else - local a = actions[t] - if a then - local s = a(t) - if s then - i = i + s - end - else - if trace_charstrings then - showvalue("<action>",t) - end - top = 0 - end - i = i + 1 - end - end - end - - -- local function calculatebounds(segments,x,y) - -- local nofsegments = #segments - -- if nofsegments == 0 then - -- return { x, y, x, y } - -- else - -- local xmin = 10000 - -- local xmax = -10000 - -- local ymin = 10000 - -- local ymax = -10000 - -- if x < xmin then xmin = x end - -- if x > xmax then xmax = x end - -- if y < ymin then ymin = y end - -- if y > ymax then ymax = y end - -- -- we now have a reasonable start so we could - -- -- simplyfy the next checks - -- for i=1,nofsegments do - -- local s = segments[i] - -- local x = s[1] - -- local y = s[2] - -- if x < xmin then xmin = x end - -- if x > xmax then xmax = x end - -- if y < ymin then ymin = y end - -- if y > ymax then ymax = y end - -- if s[#s] == "c" then -- "curveto" - -- local x = s[3] - -- local y = s[4] - -- if x < xmin then xmin = x elseif x > xmax then xmax = x end - -- if y < ymin then ymin = y elseif y > ymax then ymax = y end - -- local x = s[5] - -- local y = s[6] - -- if x < xmin then xmin = x elseif x > xmax then xmax = x end - -- if y < ymin then ymin = y elseif y > ymax then ymax = y end - -- end - -- end - -- return { round(xmin), round(ymin), round(xmax), round(ymax) } -- doesn't make ceil more sense - -- end - -- end - - local function setbias(globals,locals) - if version == 1 then - return - false, - false - else - local g, l = #globals, #locals - return - ((g < 1240 and 107) or (g < 33900 and 1131) or 32768) + 1, - ((l < 1240 and 107) or (l < 33900 and 1131) or 32768) + 1 - end - end - - parsecharstrings = function(data,glyphs,doshapes,tversion) - -- for all charstrings - local dictionary = data.dictionaries[1] - local charstrings = dictionary.charstrings - local charset = dictionary.charset - local private = dictionary.private or { data = { } } - - keepcurve = doshapes - version = tversion - stack = { } - glyphs = glyphs or { } - strings = data.strings - globals = data.routines or { } - locals = dictionary.subroutines or { } - - globalbias, localbias = setbias(globals,locals) - - local nominalwidth = private.data.nominalwidthx or 0 - local defaultwidth = private.data.defaultwidthx or 0 - - for i=1,#charstrings do - local tab = charstrings[i] - if type(tab) == "string" then - tab = lpegmatch(p_bytes,tab) - end - local index = i - 1 - x = 0 - y = 0 - width = false - r = 0 - top = 0 - stems = 0 - result = { } - -- - xmin = 0 - xmax = 0 - ymin = 0 - ymax = 0 - checked = false - -- - if trace_charstrings then - report("glyph: %i",index) - report("data: % t",tab) - end - -- - process(tab) - -- - local boundingbox = { round(xmin), round(ymin), round(xmax), round(ymax) } - -- - if width == true or width == false then - width = defaultwidth - else - width = nominalwidth + width - end - -- - -- trace_charstrings = index == 3078 -- todo: make tracker - local glyph = glyphs[index] -- can be autodefined in otr - if not glyph then - glyphs[index] = { - segments = doshapes ~= false and result or nil, -- optional - boundingbox = boundingbox, - width = width, - name = charset[index], - -- sidebearing = 0, - } - else - glyph.segments = doshapes ~= false and result or nil - glyph.boundingbox = boundingbox - if not glyph.width then - glyph.width = width - end - if charset and not glyph.name then - glyph.name = charset[index] - end - -- glyph.sidebearing = 0 -- todo - end - if trace_charstrings then - report("width: %s",tostring(width)) - report("boundingbox: % t",boundingbox) - end - charstrings[i] = nil -- free memory - end - return glyphs - end - - parsecharstring = function(data,dictionary,tab,glyphs,index,doshapes,tversion) - local private = dictionary.private - keepcurve = doshapes - version = tversion - strings = data.strings -- or in dict? - locals = dictionary.subroutines or { } - globals = data.routines or { } - - globalbias, localbias = setbias(globals,locals) - - local nominalwidth = private and private.data.nominalwidthx or 0 - local defaultwidth = private and private.data.defaultwidthx or 0 - -- - if type(tab) == "string" then - tab = lpegmatch(p_bytes,tab) - end - -- - x = 0 - y = 0 - width = false - r = 0 - top = 0 - stems = 0 - result = { } - -- - xmin = 0 - xmax = 0 - ymin = 0 - ymax = 0 - checked = false - -- - if trace_charstrings then - report("glyph: %i",index) - report("data: % t",tab) - end - -- - process(tab) - -- - local boundingbox = { xmin, ymin, xmax, ymax } - -- - if width == true or width == false then - width = defaultwidth - else - width = nominalwidth + width - end - -- - index = index - 1 - -- - local glyph = glyphs[index] -- can be autodefined in otr - if not glyph then - glyphs[index] = { - segments = doshapes ~= false and result or nil, -- optional - boundingbox = boundingbox, - width = width, - name = charset[index], - -- sidebearing = 0, - } - else - glyph.segments = doshapes ~= false and result or nil - glyph.boundingbox = boundingbox - if not glyph.width then - glyph.width = width - end - if charset and not glyph.name then - glyph.name = charset[index] - end - -- glyph.sidebearing = 0 -- todo - end - -- - if trace_charstrings then - report("width: %s",tostring(width)) - report("boundingbox: % t",boundingbox) - end - end - - resetcharstrings = function() - result = { } - top = 0 - stack = { } - end - -end - -local function readglobals(f,data) - local routines = readlengths(f) - for i=1,#routines do - routines[i] = readstring(f,routines[i]) - end - data.routines = routines -end - -local function readencodings(f,data) - data.encodings = { } -end - -local function readcharsets(f,data,dictionary) - local header = data.header - local strings = data.strings - local nofglyphs = data.nofglyphs - local charsetoffset = dictionary.charset - - if charsetoffset ~= 0 then - setposition(f,header.offset+charsetoffset) - local format = readbyte(f) - local charset = { [0] = ".notdef" } - dictionary.charset = charset - if format == 0 then - for i=1,nofglyphs do - charset[i] = strings[readushort(f)] - end - elseif format == 1 or format == 2 then - local readcount = format == 1 and readbyte or readushort - local i = 1 - while i <= nofglyphs do - local sid = readushort(f) - local n = readcount(f) - for s=sid,sid+n do - charset[i] = strings[s] - i = i + 1 - if i > nofglyphs then - break - end - end - end - else - report("cff parser: unsupported charset format %a",format) - end - end -end - -local function readprivates(f,data) - local header = data.header - local dictionaries = data.dictionaries - local private = dictionaries[1].private - if private then - setposition(f,header.offset+private.offset) - private.data = readstring(f,private.size) - end -end - -local function readlocals(f,data,dictionary) - local header = data.header - local private = dictionary.private - if private then - local subroutineoffset = private.data.subroutines - if subroutineoffset ~= 0 then - setposition(f,header.offset+private.offset+subroutineoffset) - local subroutines = readlengths(f) - for i=1,#subroutines do - subroutines[i] = readstring(f,subroutines[i]) - end - dictionary.subroutines = subroutines - private.data.subroutines = nil - else - dictionary.subroutines = { } - end - else - dictionary.subroutines = { } - end -end - --- These charstrings are little programs and described in: Technical Note #5177. A truetype --- font has only one dictionary. - -local function readcharstrings(f,data) - local header = data.header - local dictionaries = data.dictionaries - local dictionary = dictionaries[1] - local type = dictionary.charstringtype - local offset = dictionary.charstrings - if type == 2 then - setposition(f,header.offset+offset) - -- could be a metatable .. delayed loading - local charstrings = readlengths(f) - local nofglyphs = #charstrings - for i=1,nofglyphs do - charstrings[i] = readstring(f,charstrings[i]) - end - data.nofglyphs = nofglyphs - dictionary.charstrings = charstrings - else - report("unsupported charstr type %i",type) - data.nofglyphs = 0 - dictionary.charstrings = { } - end -end - --- cid (maybe do this stepwise so less mem) -- share with above - -local function readcidprivates(f,data) - local header = data.header - local dictionaries = data.dictionaries[1].cid.dictionaries - for i=1,#dictionaries do - local dictionary = dictionaries[i] - local private = dictionary.private - if private then - setposition(f,header.offset+private.offset) - private.data = readstring(f,private.size) - end - end - parseprivates(data,dictionaries) -end - -local function readnoselect(f,data,glyphs,doshapes,version) - local dictionaries = data.dictionaries - local dictionary = dictionaries[1] - readglobals(f,data) - readcharstrings(f,data) - readencodings(f,data) - readcharsets(f,data,dictionary) - readprivates(f,data) - parseprivates(data,data.dictionaries) - readlocals(f,data,dictionary) - parsecharstrings(data,glyphs,doshapes,version) - resetcharstrings() -end - -readers.parsecharstrings = parsecharstrings - -local function readfdselect(f,data,glyphs,doshapes,version) - local header = data.header - local dictionaries = data.dictionaries - local dictionary = dictionaries[1] - local cid = dictionary.cid - local cidselect = cid and cid.fdselect - readglobals(f,data) - readcharstrings(f,data) - readencodings(f,data) - local charstrings = dictionary.charstrings - local fdindex = { } - local nofglyphs = data.nofglyphs - local maxindex = -1 - setposition(f,header.offset+cidselect) - local format = readbyte(f) - if format == 1 then - for i=0,nofglyphs do -- notdef included (needs checking) - local index = readbyte(i) - fdindex[i] = index - if index > maxindex then - maxindex = index - end - end - elseif format == 3 then - local nofranges = readushort(f) - local first = readushort(f) - local index = readbyte(f) - while true do - local last = readushort(f) - if index > maxindex then - maxindex = index - end - for i=first,last do - fdindex[i] = index - end - if last >= nofglyphs then - break - else - first = last + 1 - index = readbyte(f) - end - end - else - -- unsupported format - end - if maxindex >= 0 then - local cidarray = cid.fdarray - setposition(f,header.offset+cidarray) - local dictionaries = readlengths(f) - for i=1,#dictionaries do - dictionaries[i] = readstring(f,dictionaries[i]) - end - parsedictionaries(data,dictionaries) - cid.dictionaries = dictionaries - readcidprivates(f,data) - for i=1,#dictionaries do - readlocals(f,data,dictionaries[i]) - end - for i=1,#charstrings do - parsecharstring(data,dictionaries[fdindex[i]+1],charstrings[i],glyphs,i,doshapes,version) - end - resetcharstrings() - end -end - -function readers.cff(f,fontdata,specification) --- if specification.glyphs then - if specification.details then - local datatable = fontdata.tables.cff - if datatable then - local offset = datatable.offset - local glyphs = fontdata.glyphs - if not f then - report("invalid filehandle") - return - end - if offset then - setposition(f,offset) - end - local header = readheader(f) - if header.major > 1 then - report("version mismatch") - return - end - local names = readfontnames(f) - local dictionaries = readtopdictionaries(f) - local strings = readstrings(f) - local data = { - header = header, - names = names, - dictionaries = dictionaries, - strings = strings, - nofglyphs = fontdata.nofglyphs, - } - -- - parsedictionaries(data,data.dictionaries) - -- - local d = dictionaries[1] - local c = d.cid - fontdata.cffinfo = { - familynamename = d.familyname, - fullname = d.fullname, - boundingbox = d.boundingbox, - weight = d.weight, - italicangle = d.italicangle, - underlineposition = d.underlineposition, - underlinethickness = d.underlinethickness, - monospaced = d.monospaced, - } - fontdata.cidinfo = c and { - registry = c.registry, - ordering = c.ordering, - supplement = c.supplement, - } - -- - if not specification.glyphs then - -- we only want some metadata - else - local cid = d.cid - if cid and cid.fdselect then - readfdselect(f,data,glyphs,specification.shapes or false) - else - readnoselect(f,data,glyphs,specification.shapes or false) - end - end - -- - -- cleanup (probably more can go) - -- - -- for i=1,#dictionaries do - -- local d = dictionaries[i] - -- d.subroutines = nil - -- end - -- data.strings = nil - -- if data then - -- data.charstrings = nil - -- data.routines = nil - -- end - end - end -end diff --git a/tex/compat/luaotfload/fontloader-font-cid.lua b/tex/compat/luaotfload/fontloader-font-cid.lua deleted file mode 100644 index 0eaacdfbd549941ad09e436aabc951b99dee1dc5..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/fontloader-font-cid.lua +++ /dev/null @@ -1,177 +0,0 @@ -if not modules then modules = { } end modules ['font-cid'] = { - version = 1.001, - comment = "companion to font-otf.lua (cidmaps)", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -local format, match, lower = string.format, string.match, string.lower -local tonumber = tonumber -local P, S, R, C, V, lpegmatch = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.V, lpeg.match - -local fonts, logs, trackers = fonts, logs, trackers - -local trace_loading = false trackers.register("otf.loading", function(v) trace_loading = v end) - -local report_otf = logs.reporter("fonts","otf loading") - -local cid = { } -fonts.cid = cid - -local cidmap = { } -local cidmax = 10 - --- original string parser: 0.109, lpeg parser: 0.036 seconds for Adobe-CNS1-4.cidmap --- --- 18964 18964 (leader) --- 0 /.notdef --- 1..95 0020 --- 99 3000 - -local number = C(R("09","af","AF")^1) -local space = S(" \n\r\t") -local spaces = space^0 -local period = P(".") -local periods = period * period -local name = P("/") * C((1-space)^1) - -local unicodes, names = { }, { } -- we could use Carg now - -local function do_one(a,b) - unicodes[tonumber(a)] = tonumber(b,16) -end - -local function do_range(a,b,c) - c = tonumber(c,16) - for i=tonumber(a),tonumber(b) do - unicodes[i] = c - c = c + 1 - end -end - -local function do_name(a,b) - names[tonumber(a)] = b -end - -local grammar = P { "start", - start = number * spaces * number * V("series"), - series = (spaces * (V("one") + V("range") + V("named")))^1, - one = (number * spaces * number) / do_one, - range = (number * periods * number * spaces * number) / do_range, - named = (number * spaces * name) / do_name -} - -local function loadcidfile(filename) - local data = io.loaddata(filename) - if data then - unicodes, names = { }, { } - lpegmatch(grammar,data) - local supplement, registry, ordering = match(filename,"^(.-)%-(.-)%-()%.(.-)$") - return { - supplement = supplement, - registry = registry, - ordering = ordering, - filename = filename, - unicodes = unicodes, - names = names, - } - end -end - -cid.loadfile = loadcidfile -- we use the frozen variant -local template = "%s-%s-%s.cidmap" - -local function locate(registry,ordering,supplement) - local filename = format(template,registry,ordering,supplement) - local hashname = lower(filename) - local found = cidmap[hashname] - if not found then - if trace_loading then - report_otf("checking cidmap, registry %a, ordering %a, supplement %a, filename %a",registry,ordering,supplement,filename) - end - local fullname = resolvers.findfile(filename,'cid') or "" - if fullname ~= "" then - found = loadcidfile(fullname) - if found then - if trace_loading then - report_otf("using cidmap file %a",filename) - end - cidmap[hashname] = found - found.usedname = file.basename(filename) - end - end - end - return found -end - --- cf Arthur R. we can safely scan upwards since cids are downward compatible - -function cid.getmap(specification) - if not specification then - report_otf("invalid cidinfo specification, table expected") - return - end - local registry = specification.registry - local ordering = specification.ordering - local supplement = specification.supplement - local filename = format(registry,ordering,supplement) - local lowername = lower(filename) - local found = cidmap[lowername] - if found then - return found - end - if ordering == "Identity" then - local found = { - supplement = supplement, - registry = registry, - ordering = ordering, - filename = filename, - unicodes = { }, - names = { }, - } - cidmap[lowername] = found - return found - end - -- check for already loaded file - if trace_loading then - report_otf("cidmap needed, registry %a, ordering %a, supplement %a",registry,ordering,supplement) - end - found = locate(registry,ordering,supplement) - if not found then - local supnum = tonumber(supplement) - local cidnum = nil - -- next highest (alternatively we could start high) - if supnum < cidmax then - for s=supnum+1,cidmax do - local c = locate(registry,ordering,s) - if c then - found, cidnum = c, s - break - end - end - end - -- next lowest (least worse fit) - if not found and supnum > 0 then - for s=supnum-1,0,-1 do - local c = locate(registry,ordering,s) - if c then - found, cidnum = c, s - break - end - end - end - -- prevent further lookups -- somewhat tricky - registry = lower(registry) - ordering = lower(ordering) - if found and cidnum > 0 then - for s=0,cidnum-1 do - local filename = format(template,registry,ordering,s) - if not cidmap[filename] then - cidmap[filename] = found - end - end - end - end - return found -end diff --git a/tex/compat/luaotfload/fontloader-font-con.lua b/tex/compat/luaotfload/fontloader-font-con.lua deleted file mode 100644 index 18f2217108af0443e63e5d4e1a57353f303734c6..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/fontloader-font-con.lua +++ /dev/null @@ -1,1552 +0,0 @@ -if not modules then modules = { } end modules ['font-con'] = { - version = 1.001, - comment = "companion to font-ini.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- some names of table entries will be changed (no _) - -local next, tostring, rawget = next, tostring, rawget -local format, match, lower, gsub, find = string.format, string.match, string.lower, string.gsub, string.find -local sort, insert, concat, sortedkeys, serialize, fastcopy = table.sort, table.insert, table.concat, table.sortedkeys, table.serialize, table.fastcopy -local derivetable = table.derive -local ioflush = io.flush - -local trace_defining = false trackers.register("fonts.defining", function(v) trace_defining = v end) -local trace_scaling = false trackers.register("fonts.scaling", function(v) trace_scaling = v end) - -local report_defining = logs.reporter("fonts","defining") - --- watch out: no negative depths and negative eights permitted in regular fonts - ---[[ldx-- -<p>Here we only implement a few helper functions.</p> ---ldx]]-- - -local fonts = fonts -local constructors = fonts.constructors or { } -fonts.constructors = constructors -local handlers = fonts.handlers or { } -- can have preloaded tables -fonts.handlers = handlers - -local allocate = utilities.storage.allocate -local setmetatableindex = table.setmetatableindex - --- will be directives - -constructors.dontembed = allocate() -constructors.autocleanup = true -constructors.namemode = "fullpath" -- will be a function - -constructors.version = 1.01 -constructors.cache = containers.define("fonts", "constructors", constructors.version, false) - -constructors.privateoffset = 0xF0000 -- 0x10FFFF - -constructors.cacheintex = true -- so we see the original table in fonts.font - --- This might become an interface: - -local designsizes = allocate() -constructors.designsizes = designsizes -local loadedfonts = allocate() -constructors.loadedfonts = loadedfonts - ---[[ldx-- -<p>We need to normalize the scale factor (in scaled points). This has to -do with the fact that <l n='tex'/> uses a negative multiple of 1000 as -a signal for a font scaled based on the design size.</p> ---ldx]]-- - -local factors = { - pt = 65536.0, - bp = 65781.8, -} - -function constructors.setfactor(f) - constructors.factor = factors[f or 'pt'] or factors.pt -end - -constructors.setfactor() - -function constructors.scaled(scaledpoints, designsize) -- handles designsize in sp as well - if scaledpoints < 0 then - local factor = constructors.factor - if designsize then - if designsize > factor then -- or just 1000 / when? mp? - return (- scaledpoints/1000) * designsize -- sp's - else - return (- scaledpoints/1000) * designsize * factor - end - else - return (- scaledpoints/1000) * 10 * factor - end - else - return scaledpoints - end -end - ---[[ldx-- -<p>Beware, the boundingbox is passed as reference so we may not overwrite it -in the process; numbers are of course copies. Here 65536 equals 1pt. (Due to -excessive memory usage in CJK fonts, we no longer pass the boundingbox.)</p> ---ldx]]-- - --- The scaler is only used for otf and afm and virtual fonts. If a virtual font has italic --- correction make sure to set the hasitalics flag. Some more flags will be added in the --- future. - ---[[ldx-- -<p>The reason why the scaler was originally split, is that for a while we experimented -with a helper function. However, in practice the <l n='api'/> calls are too slow to -make this profitable and the <l n='lua'/> based variant was just faster. A days -wasted day but an experience richer.</p> ---ldx]]-- - --- we can get rid of the tfm instance when we have fast access to the --- scaled character dimensions at the tex end, e.g. a fontobject.width --- actually we already have some of that now as virtual keys in glyphs --- --- flushing the kern and ligature tables from memory saves a lot (only --- base mode) but it complicates vf building where the new characters --- demand this data .. solution: functions that access them - -function constructors.cleanuptable(tfmdata) - if constructors.autocleanup and tfmdata.properties.virtualized then - for k, v in next, tfmdata.characters do - if v.commands then v.commands = nil end - -- if v.kerns then v.kerns = nil end - end - end -end - --- experimental, sharing kerns (unscaled and scaled) saves memory --- local sharedkerns, basekerns = constructors.check_base_kerns(tfmdata) --- loop over descriptions (afm and otf have descriptions, tfm not) --- there is no need (yet) to assign a value to chr.tonunicode - --- constructors.prepare_base_kerns(tfmdata) -- optimalization - --- we have target.name=metricfile and target.fullname=RealName and target.filename=diskfilename --- when collapsing fonts, luatex looks as both target.name and target.fullname as ttc files --- can have multiple subfonts - -function constructors.calculatescale(tfmdata,scaledpoints) - local parameters = tfmdata.parameters - if scaledpoints < 0 then - scaledpoints = (- scaledpoints/1000) * (tfmdata.designsize or parameters.designsize) -- already in sp - end - return scaledpoints, scaledpoints / (parameters.units or 1000) -- delta -end - -local unscaled = { - ScriptPercentScaleDown = true, - ScriptScriptPercentScaleDown = true, - RadicalDegreeBottomRaisePercent = true, - NoLimitSupFactor = true, - NoLimitSubFactor = true, -} - -function constructors.assignmathparameters(target,original) -- simple variant, not used in context - -- when a tfm file is loaded, it has already been scaled - -- and it never enters the scaled so this is otf only and - -- even then we do some extra in the context math plugins - local mathparameters = original.mathparameters - if mathparameters and next(mathparameters) then - local targetparameters = target.parameters - local targetproperties = target.properties - local targetmathparameters = { } - local factor = targetproperties.math_is_scaled and 1 or targetparameters.factor - for name, value in next, mathparameters do - if unscaled[name] then - targetmathparameters[name] = value - else - targetmathparameters[name] = value * factor - end - end - if not targetmathparameters.FractionDelimiterSize then - targetmathparameters.FractionDelimiterSize = 1.01 * targetparameters.size - end - if not mathparameters.FractionDelimiterDisplayStyleSize then - targetmathparameters.FractionDelimiterDisplayStyleSize = 2.40 * targetparameters.size - end - target.mathparameters = targetmathparameters - end -end - -function constructors.beforecopyingcharacters(target,original) - -- can be used for additional tweaking -end - -function constructors.aftercopyingcharacters(target,original) - -- can be used for additional tweaking -end - --- It's probably ok to hash just the indices because there is not that much --- chance that one will shift slots and leave the others unset then. Anyway, --- there is of course some overhead here, but it might as well get compensated --- by less time spent on including the font resource twice. For the moment --- we default to false, so a macro package has to enable it explicitly. In --- LuaTeX the fullname is used to identify a font as being unique. - -constructors.sharefonts = false -constructors.nofsharedfonts = 0 -local sharednames = { } - -function constructors.trytosharefont(target,tfmdata) - if constructors.sharefonts then -- not robust ! - local characters = target.characters - local n = 1 - local t = { target.psname } - local u = sortedkeys(characters) - for i=1,#u do - local k = u[i] - n = n + 1 ; t[n] = k - n = n + 1 ; t[n] = characters[k].index or k - end - local h = md5.HEX(concat(t," ")) - local s = sharednames[h] - if s then - if trace_defining then - report_defining("font %a uses backend resources of font %a",target.fullname,s) - end - target.fullname = s - constructors.nofsharedfonts = constructors.nofsharedfonts + 1 - target.properties.sharedwith = s - else - sharednames[h] = target.fullname - end - end -end - -function constructors.enhanceparameters(parameters) - local xheight = parameters.x_height - local quad = parameters.quad - local space = parameters.space - local stretch = parameters.space_stretch - local shrink = parameters.space_shrink - local extra = parameters.extra_space - local slant = parameters.slant - parameters.xheight = xheight - parameters.spacestretch = stretch - parameters.spaceshrink = shrink - parameters.extraspace = extra - parameters.em = quad - parameters.ex = xheight - parameters.slantperpoint = slant - parameters.spacing = { - width = space, - stretch = stretch, - shrink = shrink, - extra = extra, - } -end - -local function mathkerns(v,vdelta) - local k = { } - for i=1,#v do - local entry = v[i] - local height = entry.height - local kern = entry.kern - k[i] = { - height = height and vdelta*height or 0, - kern = kern and vdelta*kern or 0, - } - end - return k -end - -local psfake = 0 - -local function fixedpsname(psname,fallback) - local usedname = psname - if psname and psname ~= "" then - if find(psname," ") then - usedname = gsub(psname,"[%s]+","-") - else - -- we assume that the name is sane enough (we might sanitize completely some day) - end - elseif not fallback or fallback == "" then - psfake = psfake + 1 - psname = "fakename-" .. psfake - else - -- filenames can be a mess so we do a drastic cleanup - psname = fallback - usedname = gsub(psname,"[^a-zA-Z0-9]+","-") - end - return usedname, psname ~= usedname -end - -function constructors.scale(tfmdata,specification) - local target = { } -- the new table - -- - if tonumber(specification) then - specification = { size = specification } - end - target.specification = specification - -- - local scaledpoints = specification.size - local relativeid = specification.relativeid - -- - local properties = tfmdata.properties or { } - local goodies = tfmdata.goodies or { } - local resources = tfmdata.resources or { } - local descriptions = tfmdata.descriptions or { } -- bad news if empty - local characters = tfmdata.characters or { } -- bad news if empty - local changed = tfmdata.changed or { } -- for base mode - local shared = tfmdata.shared or { } - local parameters = tfmdata.parameters or { } - local mathparameters = tfmdata.mathparameters or { } - -- - local targetcharacters = { } - local targetdescriptions = derivetable(descriptions) - local targetparameters = derivetable(parameters) - local targetproperties = derivetable(properties) - local targetgoodies = goodies -- we need to loop so no metatable - target.characters = targetcharacters - target.descriptions = targetdescriptions - target.parameters = targetparameters - -- target.mathparameters = targetmathparameters -- happens elsewhere - target.properties = targetproperties - target.goodies = targetgoodies - target.shared = shared - target.resources = resources - target.unscaled = tfmdata -- the original unscaled one - -- - -- specification.mathsize : 1=text 2=script 3=scriptscript - -- specification.textsize : natural (text)size - -- parameters.mathsize : 1=text 2=script 3=scriptscript >1000 enforced size (feature value other than yes) - -- - local mathsize = tonumber(specification.mathsize) or 0 - local textsize = tonumber(specification.textsize) or scaledpoints - local forcedsize = tonumber(parameters.mathsize ) or 0 - local extrafactor = tonumber(specification.factor ) or 1 - if (mathsize == 2 or forcedsize == 2) and parameters.scriptpercentage then - scaledpoints = parameters.scriptpercentage * textsize / 100 - elseif (mathsize == 3 or forcedsize == 3) and parameters.scriptscriptpercentage then - scaledpoints = parameters.scriptscriptpercentage * textsize / 100 - elseif forcedsize > 1000 then -- safeguard - scaledpoints = forcedsize - end - targetparameters.mathsize = mathsize -- context specific - targetparameters.textsize = textsize -- context specific - targetparameters.forcedsize = forcedsize -- context specific - targetparameters.extrafactor = extrafactor -- context specific - -- - local tounicode = fonts.mappings.tounicode - -- - local defaultwidth = resources.defaultwidth or 0 - local defaultheight = resources.defaultheight or 0 - local defaultdepth = resources.defaultdepth or 0 - local units = parameters.units or 1000 - -- - if target.fonts then - target.fonts = fastcopy(target.fonts) -- maybe we virtualize more afterwards - end - -- - -- boundary keys are no longer needed as we now have a string 'right_boundary' - -- that can be used in relevant tables (kerns and ligatures) ... not that I ever - -- used them - -- - -- boundarychar_label = 0, -- not needed - -- boundarychar = 65536, -- there is now a string 'right_boundary' - -- false_boundarychar = 65536, -- produces invalid tfm in luatex - -- - targetproperties.language = properties.language or "dflt" -- inherited - targetproperties.script = properties.script or "dflt" -- inherited - targetproperties.mode = properties.mode or "base" -- inherited - -- - local askedscaledpoints = scaledpoints - local scaledpoints, delta = constructors.calculatescale(tfmdata,scaledpoints,nil,specification) -- no shortcut, dan be redefined - -- - local hdelta = delta - local vdelta = delta - -- - target.designsize = parameters.designsize -- not really needed so it might become obsolete - target.units = units - target.units_per_em = units -- just a trigger for the backend - -- - local direction = properties.direction or tfmdata.direction or 0 -- pointless, as we don't use omf fonts at all - target.direction = direction - properties.direction = direction - -- - target.size = scaledpoints - -- - target.encodingbytes = properties.encodingbytes or 1 - target.embedding = properties.embedding or "subset" - target.tounicode = 1 - target.cidinfo = properties.cidinfo - target.format = properties.format - target.cache = constructors.cacheintex and "yes" or "renew" - -- - local fontname = properties.fontname or tfmdata.fontname - local fullname = properties.fullname or tfmdata.fullname - local filename = properties.filename or tfmdata.filename - local psname = properties.psname or tfmdata.psname - local name = properties.name or tfmdata.name - -- - -- the psname used in pdf file as well as for selecting subfont in ttc - -- - local psname, psfixed = fixedpsname(psname,fontname or fullname or file.nameonly(filename)) - -- - target.fontname = fontname - target.fullname = fullname - target.filename = filename - target.psname = psname - target.name = name - -- - properties.fontname = fontname - properties.fullname = fullname - properties.filename = filename - properties.psname = psname - properties.name = name - -- expansion (hz) - local expansion = parameters.expansion - if expansion then - target.stretch = expansion.stretch - target.shrink = expansion.shrink - target.step = expansion.step - target.auto_expand = expansion.auto - end - -- protrusion - local protrusion = parameters.protrusion - if protrusion then - target.auto_protrude = protrusion.auto - end - -- widening - local extendfactor = parameters.extendfactor or 0 - if extendfactor ~= 0 and extendfactor ~= 1 then - hdelta = hdelta * extendfactor - target.extend = extendfactor * 1000 -- extent ? - else - target.extend = 1000 -- extent ? - end - -- slanting - local slantfactor = parameters.slantfactor or 0 - if slantfactor ~= 0 then - target.slant = slantfactor * 1000 - else - target.slant = 0 - end - -- - targetparameters.factor = delta - targetparameters.hfactor = hdelta - targetparameters.vfactor = vdelta - targetparameters.size = scaledpoints - targetparameters.units = units - targetparameters.scaledpoints = askedscaledpoints - -- - local isvirtual = properties.virtualized or tfmdata.type == "virtual" - local hasquality = target.auto_expand or target.auto_protrude - local hasitalics = properties.hasitalics - local autoitalicamount = properties.autoitalicamount - local stackmath = not properties.nostackmath - local nonames = properties.noglyphnames - local haskerns = properties.haskerns or properties.mode == "base" -- we can have afm in node mode - local hasligatures = properties.hasligatures or properties.mode == "base" -- we can have afm in node mode - local realdimensions = properties.realdimensions - local writingmode = properties.writingmode or "horizontal" - local identity = properties.identity or "horizontal" - -- - if changed and not next(changed) then - changed = false - end - -- - target.type = isvirtual and "virtual" or "real" - target.writingmode = writingmode == "vertical" and "vertical" or "horizontal" - target.identity = identity == "vertical" and "vertical" or "horizontal" - -- - target.postprocessors = tfmdata.postprocessors - -- - local targetslant = (parameters.slant or parameters[1] or 0) * factors.pt -- per point - local targetspace = (parameters.space or parameters[2] or 0) * hdelta - local targetspace_stretch = (parameters.space_stretch or parameters[3] or 0) * hdelta - local targetspace_shrink = (parameters.space_shrink or parameters[4] or 0) * hdelta - local targetx_height = (parameters.x_height or parameters[5] or 0) * vdelta - local targetquad = (parameters.quad or parameters[6] or 0) * hdelta - local targetextra_space = (parameters.extra_space or parameters[7] or 0) * hdelta - -- - targetparameters.slant = targetslant -- slantperpoint - targetparameters.space = targetspace - targetparameters.space_stretch = targetspace_stretch - targetparameters.space_shrink = targetspace_shrink - targetparameters.x_height = targetx_height - targetparameters.quad = targetquad - targetparameters.extra_space = targetextra_space - -- - local ascender = parameters.ascender - if ascender then - targetparameters.ascender = delta * ascender - end - local descender = parameters.descender - if descender then - targetparameters.descender = delta * descender - end - -- - constructors.enhanceparameters(targetparameters) -- official copies for us - -- - local protrusionfactor = (targetquad ~= 0 and 1000/targetquad) or 0 - local scaledwidth = defaultwidth * hdelta - local scaledheight = defaultheight * vdelta - local scaleddepth = defaultdepth * vdelta - -- - local hasmath = (properties.hasmath or next(mathparameters)) and true - -- - if hasmath then - constructors.assignmathparameters(target,tfmdata) -- does scaling and whatever is needed - properties.hasmath = true - target.nomath = false - target.MathConstants = target.mathparameters - else - properties.hasmath = false - target.nomath = true - target.mathparameters = nil -- nop - end - -- - -- Here we support some context specific trickery (this might move to a plugin). During the - -- transition to opentype the engine had troubles with italics so we had some additional code - -- for fixing that. In node mode (text) we don't care much if italics gets passed because - -- the engine does nothign with them then. - -- - if hasmath then - local mathitalics = properties.mathitalics - if mathitalics == false then - if trace_defining then - report_defining("%s italics %s for font %a, fullname %a, filename %a","math",hasitalics and "ignored" or "disabled",name,fullname,filename) - end - hasitalics = false - autoitalicamount = false - end - else - local textitalics = properties.textitalics - if textitalics == false then - if trace_defining then - report_defining("%s italics %s for font %a, fullname %a, filename %a","text",hasitalics and "ignored" or "disabled",name,fullname,filename) - end - hasitalics = false - autoitalicamount = false - end - end - -- - -- end of context specific trickery - -- - if trace_defining then - report_defining("defining tfm, name %a, fullname %a, filename %a, %spsname %a, hscale %a, vscale %a, math %a, italics %a", - name,fullname,filename,psfixed and "(fixed) " or "",psname,hdelta,vdelta, - hasmath and "enabled" or "disabled",hasitalics and "enabled" or "disabled") - end - -- - constructors.beforecopyingcharacters(target,tfmdata) - -- - local sharedkerns = { } - -- - -- we can have a dumb mode (basemode without math etc) that skips most - -- - for unicode, character in next, characters do - local chr, description, index - if changed then - local c = changed[unicode] - if c then - description = descriptions[c] or descriptions[unicode] or character - character = characters[c] or character - index = description.index or c - else - description = descriptions[unicode] or character - index = description.index or unicode - end - else - description = descriptions[unicode] or character - index = description.index or unicode - end - local width = description.width - local height = description.height - local depth = description.depth - if realdimensions then - -- this is mostly for checking issues - if not height or height == 0 then - local bb = description.boundingbox - local ht = bb[4] - if ht ~= 0 then - height = ht - end - if not depth or depth == 0 then - local dp = -bb[2] - if dp ~= 0 then - depth = dp - end - end - elseif not depth or depth == 0 then - local dp = -description.boundingbox[2] - if dp ~= 0 then - depth = dp - end - end - end - if width then width = hdelta*width else width = scaledwidth end - if height then height = vdelta*height else height = scaledheight end - -- if depth then depth = vdelta*depth else depth = scaleddepth end - if depth and depth ~= 0 then - depth = delta*depth - if nonames then - chr = { - index = index, - height = height, - depth = depth, - width = width, - } - else - chr = { - name = description.name, - index = index, - height = height, - depth = depth, - width = width, - } - end - else - -- this saves a little bit of memory time and memory, esp for big cjk fonts - if nonames then - chr = { - index = index, - height = height, - width = width, - } - else - chr = { - name = description.name, - index = index, - height = height, - width = width, - } - end - end - local isunicode = description.unicode - if isunicode then - chr.unicode = isunicode - chr.tounicode = tounicode(isunicode) - -- in luatex > 0.85 we can do this: - -- chr.tounicode = isunicode - end - if hasquality then - -- we could move these calculations elsewhere (saves calculations) - local ve = character.expansion_factor - if ve then - chr.expansion_factor = ve*1000 -- expansionfactor, hm, can happen elsewhere - end - local vl = character.left_protruding - if vl then - chr.left_protruding = protrusionfactor*width*vl - end - local vr = character.right_protruding - if vr then - chr.right_protruding = protrusionfactor*width*vr - end - end - -- - if hasmath then - -- - -- todo, just operate on descriptions.math - local vn = character.next - if vn then - chr.next = vn - else - local vv = character.vert_variants - if vv then - local t = { } - for i=1,#vv do - local vvi = vv[i] - t[i] = { - ["start"] = (vvi["start"] or 0)*vdelta, - ["end"] = (vvi["end"] or 0)*vdelta, - ["advance"] = (vvi["advance"] or 0)*vdelta, - ["extender"] = vvi["extender"], - ["glyph"] = vvi["glyph"], - } - end - chr.vert_variants = t - else - local hv = character.horiz_variants - if hv then - local t = { } - for i=1,#hv do - local hvi = hv[i] - t[i] = { - ["start"] = (hvi["start"] or 0)*hdelta, - ["end"] = (hvi["end"] or 0)*hdelta, - ["advance"] = (hvi["advance"] or 0)*hdelta, - ["extender"] = hvi["extender"], - ["glyph"] = hvi["glyph"], - } - end - chr.horiz_variants = t - end - end - -- todo also check mathitalics (or that one can go away) - end - local vi = character.vert_italic - if vi and vi ~= 0 then - chr.vert_italic = vi*hdelta - end - local va = character.accent - if va then - chr.top_accent = vdelta*va - end - if stackmath then - local mk = character.mathkerns - if mk then - local tr, tl, br, bl = mk.topright, mk.topleft, mk.bottomright, mk.bottomleft - chr.mathkern = { -- singular -> should be patched in luatex ! - top_right = tr and mathkerns(tr,vdelta) or nil, - top_left = tl and mathkerns(tl,vdelta) or nil, - bottom_right = br and mathkerns(br,vdelta) or nil, - bottom_left = bl and mathkerns(bl,vdelta) or nil, - } - end - end - if hasitalics then - local vi = character.italic - if vi and vi ~= 0 then - chr.italic = vi*hdelta - end - end - elseif autoitalicamount then -- itlc feature - local vi = description.italic - if not vi then - local bb = description.boundingbox - if bb then - local vi = bb[3] - description.width + autoitalicamount - if vi > 0 then -- < 0 indicates no overshoot or a very small auto italic - chr.italic = vi*hdelta - end - else - -- report_defining("no boundingbox for character %C in font %a, fullname %a, filename %a",unicode,name,fullname,filename) - end - elseif vi ~= 0 then - chr.italic = vi*hdelta - end - elseif hasitalics then -- unlikely - local vi = character.italic - if vi and vi ~= 0 then - chr.italic = vi*hdelta - end - end - if haskerns then - local vk = character.kerns - if vk then - local s = sharedkerns[vk] - if not s then - s = { } - for k,v in next, vk do s[k] = v*hdelta end - sharedkerns[vk] = s - end - chr.kerns = s - end - end - if hasligatures then - local vl = character.ligatures - if vl then - if true then - chr.ligatures = vl -- shared - else - local tt = { } - for i, l in next, vl do - tt[i] = l - end - chr.ligatures = tt - end - end - end - if isvirtual then - local vc = character.commands - if vc then - -- we assume non scaled commands here - -- tricky .. we need to scale pseudo math glyphs too - -- which is why we deal with rules too - local ok = false - for i=1,#vc do - local key = vc[i][1] - if key == "right" or key == "down" then - ok = true - break - end - end - if ok then - local tt = { } - for i=1,#vc do - local ivc = vc[i] - local key = ivc[1] - if key == "right" then - tt[i] = { key, ivc[2]*hdelta } - elseif key == "down" then - tt[i] = { key, ivc[2]*vdelta } - elseif key == "rule" then - tt[i] = { key, ivc[2]*vdelta, ivc[3]*hdelta } - else -- not comment - tt[i] = ivc -- shared since in cache and untouched - end - end - chr.commands = tt - else - chr.commands = vc - end - chr.index = nil - end - end - targetcharacters[unicode] = chr - end - -- - properties.setitalics = hasitalics -- for postprocessing - -- - constructors.aftercopyingcharacters(target,tfmdata) - -- - constructors.trytosharefont(target,tfmdata) - -- - return target -end - -function constructors.finalize(tfmdata) - if tfmdata.properties and tfmdata.properties.finalized then - return - end - -- - if not tfmdata.characters then - return nil - end - -- - if not tfmdata.goodies then - tfmdata.goodies = { } -- context specific - end - -- - local parameters = tfmdata.parameters - if not parameters then - return nil - end - -- - if not parameters.expansion then - parameters.expansion = { - stretch = tfmdata.stretch or 0, - shrink = tfmdata.shrink or 0, - step = tfmdata.step or 0, - auto = tfmdata.auto_expand or false, - } - end - -- - if not parameters.protrusion then - parameters.protrusion = { - auto = auto_protrude - } - end - -- - if not parameters.size then - parameters.size = tfmdata.size - end - -- - if not parameters.extendfactor then - parameters.extendfactor = tfmdata.extend or 0 - end - -- - if not parameters.slantfactor then - parameters.slantfactor = tfmdata.slant or 0 - end - -- - local designsize = parameters.designsize - if designsize then - parameters.minsize = tfmdata.minsize or designsize - parameters.maxsize = tfmdata.maxsize or designsize - else - designsize = factors.pt * 10 - parameters.designsize = designsize - parameters.minsize = designsize - parameters.maxsize = designsize - end - parameters.minsize = tfmdata.minsize or parameters.designsize - parameters.maxsize = tfmdata.maxsize or parameters.designsize - -- - if not parameters.units then - parameters.units = tfmdata.units or tfmdata.units_per_em or 1000 - end - -- - if not tfmdata.descriptions then - local descriptions = { } -- yes or no - setmetatableindex(descriptions, function(t,k) local v = { } t[k] = v return v end) - tfmdata.descriptions = descriptions - end - -- - local properties = tfmdata.properties - if not properties then - properties = { } - tfmdata.properties = properties - end - -- - if not properties.virtualized then - properties.virtualized = tfmdata.type == "virtual" - end - -- - if not tfmdata.properties then - tfmdata.properties = { - fontname = tfmdata.fontname, - filename = tfmdata.filename, - fullname = tfmdata.fullname, - name = tfmdata.name, - psname = tfmdata.psname, - -- - encodingbytes = tfmdata.encodingbytes or 1, - embedding = tfmdata.embedding or "subset", - tounicode = tfmdata.tounicode or 1, - cidinfo = tfmdata.cidinfo or nil, - format = tfmdata.format or "type1", - direction = tfmdata.direction or 0, - writingmode = tfmdata.writingmode or "horizontal", - identity = tfmdata.identity or "horizontal", - } - end - if not tfmdata.resources then - tfmdata.resources = { } - end - if not tfmdata.shared then - tfmdata.shared = { } - end - -- - -- tfmdata.fonts - -- tfmdata.unscaled - -- - if not properties.hasmath then - properties.hasmath = not tfmdata.nomath - end - -- - tfmdata.MathConstants = nil - tfmdata.postprocessors = nil - -- - tfmdata.fontname = nil - tfmdata.filename = nil - tfmdata.fullname = nil - tfmdata.name = nil -- most tricky part - tfmdata.psname = nil - -- - tfmdata.encodingbytes = nil - tfmdata.embedding = nil - tfmdata.tounicode = nil - tfmdata.cidinfo = nil - tfmdata.format = nil - tfmdata.direction = nil - tfmdata.type = nil - tfmdata.nomath = nil - tfmdata.designsize = nil - -- - tfmdata.size = nil - tfmdata.stretch = nil - tfmdata.shrink = nil - tfmdata.step = nil - tfmdata.auto_expand = nil - tfmdata.auto_protrude = nil - tfmdata.extend = nil - tfmdata.slant = nil - tfmdata.units = nil - tfmdata.units_per_em = nil - -- - tfmdata.cache = nil - -- - properties.finalized = true - -- - return tfmdata -end - ---[[ldx-- -<p>A unique hash value is generated by:</p> ---ldx]]-- - -local hashmethods = { } -constructors.hashmethods = hashmethods - -function constructors.hashfeatures(specification) -- will be overloaded - local features = specification.features - if features then - local t, tn = { }, 0 - for category, list in next, features do - if next(list) then - local hasher = hashmethods[category] - if hasher then - local hash = hasher(list) - if hash then - tn = tn + 1 - t[tn] = category .. ":" .. hash - end - end - end - end - if tn > 0 then - return concat(t," & ") - end - end - return "unknown" -end - --- hashmethods.normal = function(list) --- local s = { } --- local n = 0 --- for k, v in next, list do --- if not k then --- -- no need to add to hash --- elseif k == "number" or k == "features" then --- -- no need to add to hash (maybe we need a skip list) --- else --- n = n + 1 --- s[n] = k --- end --- end --- if n > 0 then --- sort(s) --- for i=1,n do --- local k = s[i] --- s[i] = k .. '=' .. tostring(list[k]) --- end --- return concat(s,"+") --- end --- end - -hashmethods.normal = function(list) - local s = { } - local n = 0 - for k, v in next, list do - if not k then - -- no need to add to hash - elseif k == "number" or k == "features" then - -- no need to add to hash (maybe we need a skip list) - else - n = n + 1 - s[n] = k .. '=' .. tostring(v) - end - end - if n > 0 then - sort(s) - return concat(s,"+") - end -end - ---[[ldx-- -<p>In principle we can share tfm tables when we are in node for a font, but then -we need to define a font switch as an id/attr switch which is no fun, so in that -case users can best use dynamic features ... so, we will not use that speedup. Okay, -when we get rid of base mode we can optimize even further by sharing, but then we -loose our testcases for <l n='luatex'/>.</p> ---ldx]]-- - -function constructors.hashinstance(specification,force) - local hash, size, fallbacks = specification.hash, specification.size, specification.fallbacks - if force or not hash then - hash = constructors.hashfeatures(specification) - specification.hash = hash - end - if size < 1000 and designsizes[hash] then - size = math.round(constructors.scaled(size,designsizes[hash])) - specification.size = size - end - if fallbacks then - return hash .. ' @ ' .. tostring(size) .. ' @ ' .. fallbacks - else - return hash .. ' @ ' .. tostring(size) - end -end - -function constructors.setname(tfmdata,specification) -- todo: get specification from tfmdata - if constructors.namemode == "specification" then - -- not to be used in context ! - local specname = specification.specification - if specname then - tfmdata.properties.name = specname - if trace_defining then - report_otf("overloaded fontname %a",specname) - end - end - end -end - -function constructors.checkedfilename(data) - local foundfilename = data.foundfilename - if not foundfilename then - local askedfilename = data.filename or "" - if askedfilename ~= "" then - askedfilename = resolvers.resolve(askedfilename) -- no shortcut - foundfilename = resolvers.findbinfile(askedfilename,"") or "" - if foundfilename == "" then - report_defining("source file %a is not found",askedfilename) - foundfilename = resolvers.findbinfile(file.basename(askedfilename),"") or "" - if foundfilename ~= "" then - report_defining("using source file %a due to cache mismatch",foundfilename) - end - end - end - data.foundfilename = foundfilename - end - return foundfilename -end - -local formats = allocate() -fonts.formats = formats - -setmetatableindex(formats, function(t,k) - local l = lower(k) - if rawget(t,k) then - t[k] = l - return l - end - return rawget(t,file.suffix(l)) -end) - -do - - local function setindeed(mode,source,target,group,name,position) - local action = source[mode] - if not action then - return - end - local t = target[mode] - if not t then - report_defining("fatal error in setting feature %a, group %a, mode %a",name,group,mode) - os.exit() - elseif position then - -- todo: remove existing - insert(t, position, { name = name, action = action }) - else - for i=1,#t do - local ti = t[i] - if ti.name == name then - ti.action = action - return - end - end - insert(t, { name = name, action = action }) - end - end - - local function set(group,name,target,source) - target = target[group] - if not target then - report_defining("fatal target error in setting feature %a, group %a",name,group) - os.exit() - end - local source = source[group] - if not source then - report_defining("fatal source error in setting feature %a, group %a",name,group) - os.exit() - end - local position = source.position - setindeed("node",source,target,group,name,position) - setindeed("base",source,target,group,name,position) - setindeed("plug",source,target,group,name,position) - end - - local function register(where,specification) - local name = specification.name - if name and name ~= "" then - local default = specification.default - local description = specification.description - local initializers = specification.initializers - local processors = specification.processors - local manipulators = specification.manipulators - local modechecker = specification.modechecker - if default then - where.defaults[name] = default - end - if description and description ~= "" then - where.descriptions[name] = description - end - if initializers then - set('initializers',name,where,specification) - end - if processors then - set('processors', name,where,specification) - end - if manipulators then - set('manipulators',name,where,specification) - end - if modechecker then - where.modechecker = modechecker - end - end - end - - constructors.registerfeature = register - - function constructors.getfeatureaction(what,where,mode,name) - what = handlers[what].features - if what then - where = what[where] - if where then - mode = where[mode] - if mode then - for i=1,#mode do - local m = mode[i] - if m.name == name then - return m.action - end - end - end - end - end - end - - local newfeatures = { } - constructors.newfeatures = newfeatures -- downward compatible - constructors.features = newfeatures - - local function setnewfeatures(what) - local handler = handlers[what] - local features = handler.features - if not features then - local tables = handler.tables -- can be preloaded - local statistics = handler.statistics -- can be preloaded - features = allocate { - defaults = { }, - descriptions = tables and tables.features or { }, - used = statistics and statistics.usedfeatures or { }, - initializers = { base = { }, node = { }, plug = { } }, - processors = { base = { }, node = { }, plug = { } }, - manipulators = { base = { }, node = { }, plug = { } }, - } - features.register = function(specification) return register(features,specification) end - handler.features = features -- will also become hidden - end - return features - end - - setmetatable(newfeatures, { - __call = function(t,k) local v = t[k] return v end, - __index = function(t,k) local v = setnewfeatures(k) t[k] = v return v end, - }) - -end - -do - - local newhandler = { } - constructors.handlers = newhandler -- downward compatible - constructors.newhandler = newhandler - - local function setnewhandler(what) -- could be a metatable newindex - local handler = handlers[what] - if not handler then - handler = { } - handlers[what] = handler - end - return handler - end - - setmetatable(newhandler, { - __call = function(t,k) local v = t[k] return v end, - __index = function(t,k) local v = setnewhandler(k) t[k] = v return v end, - }) - -end - -do - -- a pitty that we need to be generic as we have nicer mechanisms for this ... - - local newenhancer = { } - constructors.enhancers = newenhancer - constructors.newenhancer = newenhancer - - local function setnewenhancer(format) - - local handler = handlers[format] - local enhancers = handler.enhancers - - if not enhancers then - - local actions = allocate() - local before = allocate() - local after = allocate() - local order = allocate() - local patches = { before = before, after = after } - - local trace = false - local report = logs.reporter("fonts",format .. " enhancing") - - trackers.register(format .. ".loading", function(v) trace = v end) - - local function enhance(name,data,filename,raw) - local enhancer = actions[name] - if enhancer then - if trace then - report("apply enhancement %a to file %a",name,filename) - ioflush() - end - enhancer(data,filename,raw) - else - -- no message as we can have private ones - end - end - - local function apply(data,filename,raw) - local basename = file.basename(lower(filename)) - if trace then - report("%s enhancing file %a","start",filename) - end - ioflush() -- we want instant messages - for e=1,#order do - local enhancer = order[e] - local b = before[enhancer] - if b then - for pattern, action in next, b do - if find(basename,pattern) then - action(data,filename,raw) - end - end - end - enhance(enhancer,data,filename,raw) - local a = after[enhancer] - if a then - for pattern, action in next, a do - if find(basename,pattern) then - action(data,filename,raw) - end - end - end - ioflush() -- we want instant messages - end - if trace then - report("%s enhancing file %a","stop",filename) - end - ioflush() -- we want instant messages - end - - local function register(what,action) - if action then - if actions[what] then - -- overloading, e.g."check extra features" - else - order[#order+1] = what - end - actions[what] = action - else - report("bad enhancer %a",what) - end - end - - -- fonts.constructors.otf.enhancers.patch("before","migrate metadata","cambria",function() end) - - local function patch(what,where,pattern,action) - local pw = patches[what] - if pw then - local ww = pw[where] - if ww then - ww[pattern] = action - else - pw[where] = { [pattern] = action} - end - end - end - - enhancers = { - register = register, - apply = apply, - patch = patch, - patches = { register = patch }, -- for old times sake - } - - handler.enhancers = enhancers - end - return enhancers - end - - setmetatable(newenhancer, { - __call = function(t,k) local v = t[k] return v end, - __index = function(t,k) local v = setnewenhancer(k) t[k] = v return v end, - }) - -end - ---[[ldx-- -<p>We need to check for default features. For this we provide -a helper function.</p> ---ldx]]-- - -function constructors.checkedfeatures(what,features) - local defaults = handlers[what].features.defaults - if features and next(features) then - features = fastcopy(features) -- can be inherited (mt) but then no loops possible - for key, value in next, defaults do - if features[key] == nil then - features[key] = value - end - end - return features - else - return fastcopy(defaults) -- we can change features in place - end -end - --- before scaling - -function constructors.initializefeatures(what,tfmdata,features,trace,report) - if features and next(features) then - local properties = tfmdata.properties or { } -- brrr - local whathandler = handlers[what] - local whatfeatures = whathandler.features - local whatmodechecker = whatfeatures.modechecker - -- properties.mode can be enforces (for instance in font-otd) - local mode = properties.mode or (whatmodechecker and whatmodechecker(tfmdata,features,features.mode)) or features.mode or "base" - properties.mode = mode -- also status - features.mode = mode -- both properties.mode or features.mode can be changed - -- - local done = { } - while true do - local redo = false - local initializers = whatfeatures.initializers[mode] - if initializers then - for i=1,#initializers do - local step = initializers[i] - local feature = step.name --- we could intercept mode here .. needs a rewrite of this whole loop then but it's cleaner that way - local value = features[feature] - if not value then - -- disabled - elseif done[feature] then - -- already done - else - local action = step.action - if trace then - report("initializing feature %a to %a for mode %a for font %a",feature, - value,mode,tfmdata.properties.fullname) - end - action(tfmdata,value,features) -- can set mode (e.g. goodies) so it can trigger a restart - if mode ~= properties.mode or mode ~= features.mode then - if whatmodechecker then - properties.mode = whatmodechecker(tfmdata,features,properties.mode) -- force checking - features.mode = properties.mode - end - if mode ~= properties.mode then - mode = properties.mode - redo = true - end - end - done[feature] = true - end - if redo then - break - end - end - if not redo then - break - end - else - break - end - end - properties.mode = mode -- to be sure - return true - else - return false - end -end - --- while typesetting - -function constructors.collectprocessors(what,tfmdata,features,trace,report) - local processes, nofprocesses = { }, 0 - if features and next(features) then - local properties = tfmdata.properties - local whathandler = handlers[what] - local whatfeatures = whathandler.features - local whatprocessors = whatfeatures.processors - local mode = properties.mode - local processors = whatprocessors[mode] - if processors then - for i=1,#processors do - local step = processors[i] - local feature = step.name - if features[feature] then - local action = step.action - if trace then - report("installing feature processor %a for mode %a for font %a",feature,mode,tfmdata.properties.fullname) - end - if action then - nofprocesses = nofprocesses + 1 - processes[nofprocesses] = action - end - end - end - elseif trace then - report("no feature processors for mode %a for font %a",mode,properties.fullname) - end - end - return processes -end - --- after scaling - -function constructors.applymanipulators(what,tfmdata,features,trace,report) - if features and next(features) then - local properties = tfmdata.properties - local whathandler = handlers[what] - local whatfeatures = whathandler.features - local whatmanipulators = whatfeatures.manipulators - local mode = properties.mode - local manipulators = whatmanipulators[mode] - if manipulators then - for i=1,#manipulators do - local step = manipulators[i] - local feature = step.name - local value = features[feature] - if value then - local action = step.action - if trace then - report("applying feature manipulator %a for mode %a for font %a",feature,mode,properties.fullname) - end - if action then - action(tfmdata,feature,value) - end - end - end - end - end -end - -function constructors.addcoreunicodes(unicodes) -- maybe make this a metatable if used at all - if not unicodes then - unicodes = { } - end - unicodes.space = 0x0020 - unicodes.hyphen = 0x002D - unicodes.zwj = 0x200D - unicodes.zwnj = 0x200C - return unicodes -end - --- -- keep for a while: old tounicode code --- --- if changed then --- -- basemode hack (we try to catch missing tounicodes, e.g. needed for ssty in math cambria) --- local c = changed[unicode] --- if c then --- -- local ligatures = character.ligatures -- the original ligatures (as we cannot rely on remapping) --- description = descriptions[c] or descriptions[unicode] or character --- character = characters[c] or character --- index = description.index or c --- if tounicode then --- touni = tounicode[index] -- nb: index! --- if not touni then -- goodie --- local d = descriptions[unicode] or characters[unicode] --- local i = d.index or unicode --- touni = tounicode[i] -- nb: index! --- end --- end --- -- if ligatures and not character.ligatures then --- -- character.ligatures = ligatures -- the original targets (for now at least.. see libertine smallcaps) --- -- end --- else --- description = descriptions[unicode] or character --- index = description.index or unicode --- if tounicode then --- touni = tounicode[index] -- nb: index! --- end --- end --- else --- description = descriptions[unicode] or character --- index = description.index or unicode --- if tounicode then --- touni = tounicode[index] -- nb: index! --- end --- end diff --git a/tex/compat/luaotfload/fontloader-font-def.lua b/tex/compat/luaotfload/fontloader-font-def.lua deleted file mode 100644 index 88d6145665bf66b1cc41904cf8abe2a834d6860f..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/fontloader-font-def.lua +++ /dev/null @@ -1,455 +0,0 @@ -if not modules then modules = { } end modules ['font-def'] = { - version = 1.001, - comment = "companion to font-ini.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- We can overload some of the definers.functions so we don't local them. - -local lower, gsub = string.lower, string.gsub -local tostring, next = tostring, next -local lpegmatch = lpeg.match -local suffixonly, removesuffix = file.suffix, file.removesuffix -local formatters = string.formatters - -local allocate = utilities.storage.allocate - -local trace_defining = false trackers .register("fonts.defining", function(v) trace_defining = v end) -local directive_embedall = false directives.register("fonts.embedall", function(v) directive_embedall = v end) - -trackers.register("fonts.loading", "fonts.defining", "otf.loading", "afm.loading", "tfm.loading") -trackers.register("fonts.all", "fonts.*", "otf.*", "afm.*", "tfm.*") - -local report_defining = logs.reporter("fonts","defining") - ---[[ldx-- -<p>Here we deal with defining fonts. We do so by intercepting the -default loader that only handles <l n='tfm'/>.</p> ---ldx]]-- - -local fonts = fonts -local fontdata = fonts.hashes.identifiers -local readers = fonts.readers -local definers = fonts.definers -local specifiers = fonts.specifiers -local constructors = fonts.constructors -local fontgoodies = fonts.goodies - -readers.sequence = allocate { 'otf', 'ttf', 'afm', 'tfm', 'lua' } -- dfont ttc - -local variants = allocate() -specifiers.variants = variants - -definers.methods = definers.methods or { } - -local internalized = allocate() -- internal tex numbers (private) -local lastdefined = nil -- we don't want this one to end up in s-tra-02 - -local loadedfonts = constructors.loadedfonts -local designsizes = constructors.designsizes - --- not in generic (some day I'll make two defs, one for context, one for generic) - -local resolvefile = fontgoodies and fontgoodies.filenames and fontgoodies.filenames.resolve or function(s) return s end - ---[[ldx-- -<p>We hardly gain anything when we cache the final (pre scaled) -<l n='tfm'/> table. But it can be handy for debugging, so we no -longer carry this code along. Also, we now have quite some reference -to other tables so we would end up with lots of catches.</p> ---ldx]]-- - ---[[ldx-- -<p>We can prefix a font specification by <type>name:</type> or -<type>file:</type>. The first case will result in a lookup in the -synonym table.</p> - -<typing> -[ name: | file: ] identifier [ separator [ specification ] ] -</typing> - -<p>The following function split the font specification into components -and prepares a table that will move along as we proceed.</p> ---ldx]]-- - --- beware, we discard additional specs --- --- method:name method:name(sub) method:name(sub)*spec method:name*spec --- name name(sub) name(sub)*spec name*spec --- name@spec*oeps - -local splitter, splitspecifiers = nil, "" -- not so nice - -local P, C, S, Cc = lpeg.P, lpeg.C, lpeg.S, lpeg.Cc - -local left = P("(") -local right = P(")") -local colon = P(":") -local space = P(" ") - -definers.defaultlookup = "file" - -local prefixpattern = P(false) - -local function addspecifier(symbol) - splitspecifiers = splitspecifiers .. symbol - local method = S(splitspecifiers) - local lookup = C(prefixpattern) * colon - local sub = left * C(P(1-left-right-method)^1) * right - local specification = C(method) * C(P(1)^1) - local name = C((1-sub-specification)^1) - splitter = P((lookup + Cc("")) * name * (sub + Cc("")) * (specification + Cc(""))) -end - -local function addlookup(str,default) - prefixpattern = prefixpattern + P(str) -end - -definers.addlookup = addlookup - -addlookup("file") -addlookup("name") -addlookup("spec") - -local function getspecification(str) - return lpegmatch(splitter,str or "") -- weird catch -end - -definers.getspecification = getspecification - -function definers.registersplit(symbol,action,verbosename) - addspecifier(symbol) - variants[symbol] = action - if verbosename then - variants[verbosename] = action - end -end - -local function makespecification(specification,lookup,name,sub,method,detail,size) - size = size or 655360 - if not lookup or lookup == "" then - lookup = definers.defaultlookup - end - if trace_defining then - report_defining("specification %a, lookup %a, name %a, sub %a, method %a, detail %a", - specification, lookup, name, sub, method, detail) - end - local t = { - lookup = lookup, -- forced type - specification = specification, -- full specification - size = size, -- size in scaled points or -1000*n - name = name, -- font or filename - sub = sub, -- subfont (eg in ttc) - method = method, -- specification method - detail = detail, -- specification - resolved = "", -- resolved font name - forced = "", -- forced loader - features = { }, -- preprocessed features - } - return t -end - - -definers.makespecification = makespecification - -function definers.analyze(specification, size) - -- can be optimized with locals - local lookup, name, sub, method, detail = getspecification(specification or "") - return makespecification(specification, lookup, name, sub, method, detail, size) -end - ---[[ldx-- -<p>We can resolve the filename using the next function:</p> ---ldx]]-- - -definers.resolvers = definers.resolvers or { } -local resolvers = definers.resolvers - --- todo: reporter - -function resolvers.file(specification) - local name = resolvefile(specification.name) -- catch for renames - local suffix = lower(suffixonly(name)) - if fonts.formats[suffix] then - specification.forced = suffix - specification.forcedname = name - specification.name = removesuffix(name) - else - specification.name = name -- can be resolved - end -end - -function resolvers.name(specification) - local resolve = fonts.names.resolve - if resolve then - local resolved, sub, subindex = resolve(specification.name,specification.sub,specification) -- we pass specification for overloaded versions - if resolved then - specification.resolved = resolved - specification.sub = sub - specification.subindex = subindex - local suffix = lower(suffixonly(resolved)) - if fonts.formats[suffix] then - specification.forced = suffix - specification.forcedname = resolved - specification.name = removesuffix(resolved) - else - specification.name = resolved - end - end - else - resolvers.file(specification) - end -end - -function resolvers.spec(specification) - local resolvespec = fonts.names.resolvespec - if resolvespec then - local resolved, sub, subindex = resolvespec(specification.name,specification.sub,specification) -- we pass specification for overloaded versions - if resolved then - specification.resolved = resolved - specification.sub = sub - specification.subindex = subindex - specification.forced = lower(suffixonly(resolved)) - specification.forcedname = resolved - specification.name = removesuffix(resolved) - end - else - resolvers.name(specification) - end -end - -function definers.resolve(specification) - if not specification.resolved or specification.resolved == "" then -- resolved itself not per se in mapping hash - local r = resolvers[specification.lookup] - if r then - r(specification) - end - end - if specification.forced == "" then - specification.forced = nil - specification.forcedname = nil - end - specification.hash = lower(specification.name .. ' @ ' .. constructors.hashfeatures(specification)) - if specification.sub and specification.sub ~= "" then - specification.hash = specification.sub .. ' @ ' .. specification.hash - end - return specification -end - ---[[ldx-- -<p>The main read function either uses a forced reader (as determined by -a lookup) or tries to resolve the name using the list of readers.</p> - -<p>We need to cache when possible. We do cache raw tfm data (from <l -n='tfm'/>, <l n='afm'/> or <l n='otf'/>). After that we can cache based -on specificstion (name) and size, that is, <l n='tex'/> only needs a number -for an already loaded fonts. However, it may make sense to cache fonts -before they're scaled as well (store <l n='tfm'/>'s with applied methods -and features). However, there may be a relation between the size and -features (esp in virtual fonts) so let's not do that now.</p> - -<p>Watch out, here we do load a font, but we don't prepare the -specification yet.</p> ---ldx]]-- - --- very experimental: - -function definers.applypostprocessors(tfmdata) - local postprocessors = tfmdata.postprocessors - if postprocessors then - local properties = tfmdata.properties - 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 = gsub(lower(extrahash),"[^a-z]","-") - properties.fullname = formatters["%s-%s"](properties.fullname,extrahash) - end - end - end - return tfmdata -end - --- function definers.applypostprocessors(tfmdata) --- return tfmdata --- end - -local function checkembedding(tfmdata) - local properties = tfmdata.properties - local embedding - if directive_embedall then - embedding = "full" - elseif properties and properties.filename and constructors.dontembed[properties.filename] then - embedding = "no" - else - embedding = "subset" - end - if properties then - properties.embedding = embedding - else - tfmdata.properties = { embedding = embedding } - end - tfmdata.embedding = embedding -end - -function definers.loadfont(specification) - local hash = constructors.hashinstance(specification) - local tfmdata = loadedfonts[hash] -- hashes by size ! - if not tfmdata then - local forced = specification.forced or "" - if forced ~= "" then - local reader = readers[lower(forced)] -- normally forced is already lowered - tfmdata = reader and reader(specification) - if not tfmdata then - report_defining("forced type %a of %a not found",forced,specification.name) - end - else - local sequence = readers.sequence -- can be overloaded so only a shortcut here - for s=1,#sequence do - local reader = sequence[s] - if readers[reader] then -- we skip not loaded readers - if trace_defining then - report_defining("trying (reader sequence driven) type %a for %a with file %a",reader,specification.name,specification.filename) - end - tfmdata = readers[reader](specification) - if tfmdata then - break - else - specification.filename = nil - end - end - end - end - if tfmdata then - tfmdata = definers.applypostprocessors(tfmdata) - checkembedding(tfmdata) -- todo: general postprocessor - loadedfonts[hash] = tfmdata - designsizes[specification.hash] = tfmdata.parameters.designsize - end - end - if not tfmdata then - report_defining("font with asked name %a is not found using lookup %a",specification.name,specification.lookup) - end - return tfmdata -end - -function constructors.checkvirtualids() - -- dummy in plain version -end - -function constructors.readanddefine(name,size) -- no id -- maybe a dummy first - local specification = definers.analyze(name,size) - local method = specification.method - if method and variants[method] then - specification = variants[method](specification) - end - specification = definers.resolve(specification) - local hash = constructors.hashinstance(specification) - local id = definers.registered(hash) - if not id then - local tfmdata = definers.loadfont(specification) - if tfmdata then - tfmdata.properties.hash = hash - constructors.checkvirtualids(tfmdata) -- experiment, will become obsolete when slots can selfreference - id = font.define(tfmdata) - definers.register(tfmdata,id) - else - id = 0 -- signal - end - end - return fontdata[id], id -end - ---[[ldx-- -<p>So far the specifiers. Now comes the real definer. Here we cache -based on id's. Here we also intercept the virtual font handler. Since -it evolved stepwise I may rewrite this bit (combine code).</p> - -In the previously defined reader (the one resulting in a <l n='tfm'/> -table) we cached the (scaled) instances. Here we cache them again, but -this time based on id. We could combine this in one cache but this does -not gain much. By the way, passing id's back to in the callback was -introduced later in the development.</p> ---ldx]]-- - -function definers.current() -- or maybe current - return lastdefined -end - -function definers.registered(hash) - local id = internalized[hash] - return id, id and fontdata[id] -end - -function definers.register(tfmdata,id) - if tfmdata and id then - local hash = tfmdata.properties.hash - if not hash then - report_defining("registering font, id %a, name %a, invalid hash",id,tfmdata.properties.filename or "?") - elseif not internalized[hash] then - internalized[hash] = id - if trace_defining then - report_defining("registering font, id %s, hash %a",id,hash) - end - fontdata[id] = tfmdata - end - end -end - -function definers.read(specification,size,id) -- id can be optional, name can already be table - statistics.starttiming(fonts) - if type(specification) == "string" then - specification = definers.analyze(specification,size) - end - local method = specification.method - if method and variants[method] then - specification = variants[method](specification) - end - specification = definers.resolve(specification) - local hash = constructors.hashinstance(specification) - local tfmdata = definers.registered(hash) -- id - if tfmdata then - if trace_defining then - report_defining("already hashed: %s",hash) - end - else - tfmdata = definers.loadfont(specification) -- can be overloaded - if tfmdata then - if trace_defining then - report_defining("loaded and hashed: %s",hash) - end - tfmdata.properties.hash = hash - if id then - definers.register(tfmdata,id) - end - else - if trace_defining then - report_defining("not loaded and hashed: %s",hash) - end - end - end - lastdefined = tfmdata or id -- todo ! ! ! ! ! - if not tfmdata then -- or id? - report_defining( "unknown font %a, loading aborted",specification.name) - elseif trace_defining and type(tfmdata) == "table" then - local properties = tfmdata.properties or { } - local parameters = tfmdata.parameters or { } - report_defining("using %a font with id %a, name %a, size %a, bytes %a, encoding %a, fullname %a, filename %a", - properties.format or "unknown", id, properties.name, parameters.size, properties.encodingbytes, - properties.encodingname, properties.fullname, file.basename(properties.filename)) - end - statistics.stoptiming(fonts) - return tfmdata -end - -function font.getfont(id) - return fontdata[id] -- otherwise issues -end - ---[[ldx-- -<p>We overload the <l n='tfm'/> reader.</p> ---ldx]]-- - -callbacks.register('define_font', definers.read, "definition of fonts (tfmdata preparation)") diff --git a/tex/compat/luaotfload/fontloader-font-dsp.lua b/tex/compat/luaotfload/fontloader-font-dsp.lua deleted file mode 100644 index 13095f7e699d1ea2f426f4de2cdf79bee85ab066..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/fontloader-font-dsp.lua +++ /dev/null @@ -1,2442 +0,0 @@ -if not modules then modules = { } end modules ['font-dsp'] = { - version = 1.001, - comment = "companion to font-ini.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- many 0,0 entry/exit - --- This loader went through a few iterations. First I made a ff compatible one so --- that we could do some basic checking. Also some verbosity was added (named --- glyphs). Eventually all that was dropped for a context friendly format, simply --- because keeping the different table models in sync too to much time. I have the --- old file somewhere. A positive side effect is that we get an (upto) much smaller --- smaller tma/tmc file. In the end the loader will be not much slower than the --- c based ff one. - --- Being binary encoded, an opentype is rather compact. When expanded into a Lua table --- quite some memory can be used. This is very noticeable in the ff loader, which for --- a good reason uses a verbose format. However, when we use that data we create a couple --- of hashes. In the Lua loader we create these hashes directly, which save quite some --- memory. --- --- We convert a font file only once and then cache it. Before creating the cached instance --- packing takes place: common tables get shared. After (re)loading and unpacking we then --- get a rather efficient internal representation of the font. In the new loader there is a --- pitfall. Because we use some common coverage magic we put a bit more information in --- the mark and cursive coverage tables than strickly needed: a reference to the coverage --- itself. This permits a fast lookup of the second glyph involved. In the marks we --- expand the class indicator to a class hash, in the cursive we use a placeholder that gets --- a self reference. This means that we cannot pack these subtables unless we add a unique --- id per entry (the same one per coverage) and that makes the tables larger. Because only a --- few fonts benefit from this, I decided to not do this. Experiments demonstrated that it --- only gives a few percent gain (on for instance husayni we can go from 845K to 828K --- bytecode). Better stay conceptually clean than messy compact. - --- When we can reduce all basic lookups to one step we might safe a bit in the processing --- so then only chains are multiple. - --- I used to flatten kerns here but that has been moved elsewhere because it polutes the code --- here and can be done fast afterwards. One can even wonder if it makes sense to do it as we --- pack anyway. In a similar fashion the unique placeholders in anchors in marks have been --- removed because packing doesn't save much there anyway. - --- Although we have a bit more efficient tables in the cached files, the internals are still --- pretty similar. And although we have a slightly more direct coverage access the processing --- of node lists is not noticeable faster for latin texts, but for arabic we gain some 10% --- (and could probably gain a bit more). - -local next, type = next, type -local bittest = bit32.btest -local rshift = bit32.rshift -local concat = table.concat -local lower = string.lower -local copy = table.copy -local sub = string.sub -local strip = string.strip -local tohash = table.tohash -local reversed = table.reversed - -local setmetatableindex = table.setmetatableindex -local formatters = string.formatters -local sortedkeys = table.sortedkeys -local sortedhash = table.sortedhash - -local report = logs.reporter("otf reader") - -local readers = fonts.handlers.otf.readers -local streamreader = readers.streamreader - -local setposition = streamreader.setposition -local getposition = streamreader.getposition -local skipshort = streamreader.skipshort -local readushort = streamreader.readcardinal2 -- 16-bit unsigned integer -local readulong = streamreader.readcardinal4 -- 24-bit unsigned integer -local readshort = streamreader.readinteger2 -- 16-bit signed integer -local readfword = readshort -local readstring = streamreader.readstring -local readtag = streamreader.readtag -local readbytes = streamreader.readbytes - -local gsubhandlers = { } -local gposhandlers = { } - -local lookupidoffset = -1 -- will become 1 when we migrate (only -1 for comparign with old) - -local classes = { - "base", - "ligature", - "mark", - "component", -} - -local gsubtypes = { - "single", - "multiple", - "alternate", - "ligature", - "context", - "chainedcontext", - "extension", - "reversechainedcontextsingle", -} - -local gpostypes = { - "single", - "pair", - "cursive", - "marktobase", - "marktoligature", - "marktomark", - "context", - "chainedcontext", - "extension", -} - -local chaindirections = { - context = 0, - chainedcontext = 1, - reversechainedcontextsingle = -1, -} - --- Traditionally we use these unique names (so that we can flatten the lookup list --- (we create subsets runtime) but I will adapt the old code to newer names. - --- chainsub --- reversesub - -local lookupnames = { - gsub = { - single = "gsub_single", - multiple = "gsub_multiple", - alternate = "gsub_alternate", - ligature = "gsub_ligature", - context = "gsub_context", - chainedcontext = "gsub_contextchain", - reversechainedcontextsingle = "gsub_reversecontextchain", -- reversesub - }, - gpos = { - single = "gpos_single", - pair = "gpos_pair", - cursive = "gpos_cursive", - marktobase = "gpos_mark2base", - marktoligature = "gpos_mark2ligature", - marktomark = "gpos_mark2mark", - context = "gpos_context", - chainedcontext = "gpos_contextchain", - } -} - --- keep this as reference: --- --- local lookupbits = { --- [0x0001] = "righttoleft", --- [0x0002] = "ignorebaseglyphs", --- [0x0004] = "ignoreligatures", --- [0x0008] = "ignoremarks", --- [0x0010] = "usemarkfilteringset", --- [0x00E0] = "reserved", --- [0xFF00] = "markattachmenttype", --- } --- --- local lookupstate = setmetatableindex(function(t,k) --- local v = { } --- for kk, vv in next, lookupbits do --- if bittest(k,kk) then --- v[vv] = true --- end --- end --- t[k] = v --- return v --- end) - -local lookupflags = setmetatableindex(function(t,k) - local v = { - bittest(k,0x0008) and true or false, -- ignoremarks - bittest(k,0x0004) and true or false, -- ignoreligatures - bittest(k,0x0002) and true or false, -- ignorebaseglyphs - bittest(k,0x0001) and true or false, -- r2l - } - t[k] = v - return v -end) - --- Beware: only use the simple variant if we don't set keys/values (otherwise too many entries). We --- could also have a variant that applies a function but there is no real benefit in this. - -local function readcoverage(f,offset,simple) - setposition(f,offset) - local coverageformat = readushort(f) - local coverage = { } - if coverageformat == 1 then - local nofcoverage = readushort(f) - if simple then - for i=1,nofcoverage do - coverage[i] = readushort(f) - end - else - for i=0,nofcoverage-1 do - coverage[readushort(f)] = i -- index in record - end - end - elseif coverageformat == 2 then - local nofranges = readushort(f) - local n = simple and 1 or 0 -- needs checking - for i=1,nofranges do - local firstindex = readushort(f) - local lastindex = readushort(f) - local coverindex = readushort(f) - if simple then - for i=firstindex,lastindex do - coverage[n] = i - n = n + 1 - end - else - for i=firstindex,lastindex do - coverage[i] = n - n = n + 1 - end - end - end - else - report("unknown coverage format %a ",coverageformat) - end - return coverage -end - -local function readclassdef(f,offset,preset) - setposition(f,offset) - local classdefformat = readushort(f) - local classdef = { } - if type(preset) == "number" then - for k=0,preset-1 do - classdef[k] = 1 - end - end - if classdefformat == 1 then - local index = readushort(f) - local nofclassdef = readushort(f) - for i=1,nofclassdef do - classdef[index] = readushort(f) + 1 - index = index + 1 - end - elseif classdefformat == 2 then - local nofranges = readushort(f) - local n = 0 - for i=1,nofranges do - local firstindex = readushort(f) - local lastindex = readushort(f) - local class = readushort(f) + 1 - for i=firstindex,lastindex do - classdef[i] = class - end - end - else - report("unknown classdef format %a ",classdefformat) - end - if type(preset) == "table" then - for k in next, preset do - if not classdef[k] then - classdef[k] = 1 - end - end - end - return classdef -end - -local function classtocoverage(defs) - if defs then - local list = { } - for index, class in next, defs do - local c = list[class] - if c then - c[#c+1] = index - else - list[class] = { index } - end - end - return list - end -end - --- extra readers - -local function readposition(f,format) - if format == 0 then - return nil - end - -- maybe fast test on 0x0001 + 0x0002 + 0x0004 + 0x0008 (profile first) - local x = bittest(format,0x0001) and readshort(f) or 0 -- placement - local y = bittest(format,0x0002) and readshort(f) or 0 -- placement - local h = bittest(format,0x0004) and readshort(f) or 0 -- advance - local v = bittest(format,0x0008) and readshort(f) or 0 -- advance - if x == 0 and y == 0 and h == 0 and v == 0 then - return nil - else - return { x, y, h, v } - end -end - -local function readanchor(f,offset) - if not offset or offset == 0 then - return nil -- false - end - setposition(f,offset) - local format = readshort(f) - if format == 0 then - report("invalid anchor format %i @ position %i",format,offset) - return false - elseif format > 3 then - report("unsupported anchor format %i @ position %i",format,offset) - return false - end - return { readshort(f), readshort(f) } -end - --- common handlers: inlining can be faster but we cache anyway --- so we don't bother too much about speed here - -local function readfirst(f,offset) - if offset then - setposition(f,offset) - end - return { readushort(f) } -end - -local function readarray(f,offset,first) - if offset then - setposition(f,offset) - end - local n = readushort(f) - if first then - local t = { first } - for i=2,n do - t[i] = readushort(f) - end - return t, n - elseif n > 0 then - local t = { } - for i=1,n do - t[i] = readushort(f) - end - return t, n - end -end - -local function readcoveragearray(f,offset,t,simple) - if not t then - return nil - end - local n = #t - if n == 0 then - return nil - end - for i=1,n do - t[i] = readcoverage(f,offset+t[i],simple) - end - return t -end - -local function covered(subset,all) - local used, u - for i=1,#subset do - local s = subset[i] - if all[s] then - if used then - u = u + 1 - used[u] = s - else - u = 1 - used = { s } - end - end - end - return used -end - --- We generalize the chained lookups so that we can do with only one handler --- when processing them. - --- pruned - -local function readlookuparray(f,noflookups,nofcurrent) - local lookups = { } - if noflookups > 0 then - local length = 0 - for i=1,noflookups do - local index = readushort(f) + 1 - if index > length then - length = index - end - lookups[index] = readushort(f) + 1 - end - for index=1,length do - if not lookups[index] then - lookups[index] = false - end - end - -- if length > nofcurrent then - -- report("more lookups than currently matched characters") - -- end - end - return lookups -end - --- not pruned --- --- local function readlookuparray(f,noflookups,nofcurrent) --- local lookups = { } --- for i=1,nofcurrent do --- lookups[i] = false --- end --- for i=1,noflookups do --- local index = readushort(f) + 1 --- if index > nofcurrent then --- report("more lookups than currently matched characters") --- for i=nofcurrent+1,index-1 do --- lookups[i] = false --- end --- nofcurrent = index --- end --- lookups[index] = readushort(f) + 1 --- end --- return lookups --- end - -local function unchainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,what) - local tableoffset = lookupoffset + offset - setposition(f,tableoffset) - local subtype = readushort(f) - if subtype == 1 then - local coverage = readushort(f) - local subclasssets = readarray(f) - local rules = { } - if subclasssets then - coverage = readcoverage(f,tableoffset+coverage,true) - for i=1,#subclasssets do - local offset = subclasssets[i] - if offset > 0 then - local firstcoverage = coverage[i] - local rulesoffset = tableoffset + offset - local subclassrules = readarray(f,rulesoffset) - for rule=1,#subclassrules do - setposition(f,rulesoffset + subclassrules[rule]) - local nofcurrent = readushort(f) - local noflookups = readushort(f) - local current = { { firstcoverage } } - for i=2,nofcurrent do - current[i] = { readushort(f) } - end - local lookups = readlookuparray(f,noflookups,nofcurrent) - rules[#rules+1] = { - current = current, - lookups = lookups - } - end - end - end - else - report("empty subclassset in %a subtype %i","unchainedcontext",subtype) - end - return { - format = "glyphs", - rules = rules, - } - elseif subtype == 2 then - -- We expand the classes as later on we do a pack over the whole table so then we get - -- back efficiency. This way we can also apply the coverage to the first current. - local coverage = readushort(f) - local currentclassdef = readushort(f) - local subclasssets = readarray(f) - local rules = { } - if subclasssets then - coverage = readcoverage(f,tableoffset + coverage) - currentclassdef = readclassdef(f,tableoffset + currentclassdef,coverage) - local currentclasses = classtocoverage(currentclassdef,fontdata.glyphs) - for class=1,#subclasssets do - local offset = subclasssets[class] - if offset > 0 then - local firstcoverage = currentclasses[class] - if firstcoverage then - firstcoverage = covered(firstcoverage,coverage) -- bonus - if firstcoverage then - local rulesoffset = tableoffset + offset - local subclassrules = readarray(f,rulesoffset) - for rule=1,#subclassrules do - setposition(f,rulesoffset + subclassrules[rule]) - local nofcurrent = readushort(f) - local noflookups = readushort(f) - local current = { firstcoverage } - for i=2,nofcurrent do - current[i] = currentclasses[readushort(f) + 1] - end - local lookups = readlookuparray(f,noflookups,nofcurrent) - rules[#rules+1] = { - current = current, - lookups = lookups - } - end - else - report("no coverage") - end - else - report("no coverage class") - end - end - end - else - report("empty subclassset in %a subtype %i","unchainedcontext",subtype) - end - return { - format = "class", - rules = rules, - } - elseif subtype == 3 then - local current = readarray(f) - local noflookups = readushort(f) - local lookups = readlookuparray(f,noflookups,#current) - current = readcoveragearray(f,tableoffset,current,true) - return { - format = "coverage", - rules = { - { - current = current, - lookups = lookups, - } - } - } - else - report("unsupported subtype %a in %a %s",subtype,"unchainedcontext",what) - end -end - --- todo: optimize for n=1 ? - --- class index needs checking, probably no need for +1 - -local function chainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,what) - local tableoffset = lookupoffset + offset - setposition(f,tableoffset) - local subtype = readushort(f) - if subtype == 1 then - local coverage = readushort(f) - local subclasssets = readarray(f) - local rules = { } - if subclasssets then - coverage = readcoverage(f,tableoffset+coverage,true) - for i=1,#subclasssets do - local offset = subclasssets[i] - if offset > 0 then - local firstcoverage = coverage[i] - local rulesoffset = tableoffset + offset - local subclassrules = readarray(f,rulesoffset) - for rule=1,#subclassrules do - setposition(f,rulesoffset + subclassrules[rule]) - local nofbefore = readushort(f) - local before - if nofbefore > 0 then - before = { } - for i=1,nofbefore do - before[i] = { readushort(f) } - end - end - local nofcurrent = readushort(f) - local current = { { firstcoverage } } - for i=2,nofcurrent do - current[i] = { readushort(f) } - end - local nofafter = readushort(f) - local after - if nofafter > 0 then - after = { } - for i=1,nofafter do - after[i] = { readushort(f) } - end - end - local noflookups = readushort(f) - local lookups = readlookuparray(f,noflookups,nofcurrent) - rules[#rules+1] = { - before = before, - current = current, - after = after, - lookups = lookups, - } - end - end - end - else - report("empty subclassset in %a subtype %i","chainedcontext",subtype) - end - return { - format = "glyphs", - rules = rules, - } - elseif subtype == 2 then - local coverage = readushort(f) - local beforeclassdef = readushort(f) - local currentclassdef = readushort(f) - local afterclassdef = readushort(f) - local subclasssets = readarray(f) - local rules = { } - if subclasssets then - local coverage = readcoverage(f,tableoffset + coverage) - local beforeclassdef = readclassdef(f,tableoffset + beforeclassdef,nofglyphs) - local currentclassdef = readclassdef(f,tableoffset + currentclassdef,coverage) - local afterclassdef = readclassdef(f,tableoffset + afterclassdef,nofglyphs) - local beforeclasses = classtocoverage(beforeclassdef,fontdata.glyphs) - local currentclasses = classtocoverage(currentclassdef,fontdata.glyphs) - local afterclasses = classtocoverage(afterclassdef,fontdata.glyphs) - for class=1,#subclasssets do - local offset = subclasssets[class] - if offset > 0 then - local firstcoverage = currentclasses[class] - if firstcoverage then - firstcoverage = covered(firstcoverage,coverage) -- bonus - if firstcoverage then - local rulesoffset = tableoffset + offset - local subclassrules = readarray(f,rulesoffset) - for rule=1,#subclassrules do - -- watch out, in context we first get the counts and then the arrays while - -- here we get them mixed - setposition(f,rulesoffset + subclassrules[rule]) - local nofbefore = readushort(f) - local before - if nofbefore > 0 then - before = { } - for i=1,nofbefore do - before[i] = beforeclasses[readushort(f) + 1] - end - end - local nofcurrent = readushort(f) - local current = { firstcoverage } - for i=2,nofcurrent do - current[i] = currentclasses[readushort(f)+ 1] - end - local nofafter = readushort(f) - local after - if nofafter > 0 then - after = { } - for i=1,nofafter do - after[i] = afterclasses[readushort(f) + 1] - end - end - -- no sequence index here (so why in context as it saves nothing) - local noflookups = readushort(f) - local lookups = readlookuparray(f,noflookups,nofcurrent) - rules[#rules+1] = { - before = before, - current = current, - after = after, - lookups = lookups, - } - end - else - report("no coverage") - end - else - report("class is not covered") - end - end - end - else - report("empty subclassset in %a subtype %i","chainedcontext",subtype) - end - return { - format = "class", - rules = rules, - } - elseif subtype == 3 then - local before = readarray(f) - local current = readarray(f) - local after = readarray(f) - local noflookups = readushort(f) - local lookups = readlookuparray(f,noflookups,#current) - before = readcoveragearray(f,tableoffset,before,true) - current = readcoveragearray(f,tableoffset,current,true) - after = readcoveragearray(f,tableoffset,after,true) - return { - format = "coverage", - rules = { - { - before = before, - current = current, - after = after, - lookups = lookups, - } - } - } - else - report("unsupported subtype %a in %a %s",subtype,"chainedcontext",what) - end -end - -local function extension(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,types,handlers,what) - local tableoffset = lookupoffset + offset - setposition(f,tableoffset) - local subtype = readushort(f) - if subtype == 1 then - local lookuptype = types[readushort(f)] - local faroffset = readulong(f) - local handler = handlers[lookuptype] - if handler then - -- maybe we can just pass one offset (or tableoffset first) - return handler(f,fontdata,lookupid,tableoffset + faroffset,0,glyphs,nofglyphs), lookuptype - else - report("no handler for lookuptype %a subtype %a in %s %s",lookuptype,subtype,what,"extension") - end - else - report("unsupported subtype %a in %s %s",subtype,what,"extension") - end -end - --- gsub handlers - -function gsubhandlers.single(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs) - local tableoffset = lookupoffset + offset - setposition(f,tableoffset) - local subtype = readushort(f) - if subtype == 1 then - local coverage = readushort(f) - local delta = readshort(f) -- can be negative - local coverage = readcoverage(f,tableoffset+coverage) -- not simple as we need to set key/value anyway - for index in next, coverage do - local newindex = index + delta - if index > nofglyphs or newindex > nofglyphs then - report("invalid index in %s format %i: %i -> %i (max %i)","single",subtype,index,newindex,nofglyphs) - coverage[index] = nil - else - coverage[index] = newindex - end - end - return { - coverage = coverage - } - elseif subtype == 2 then -- in streamreader a seek and fetch is faster than a temp table - local coverage = readushort(f) - local nofreplacements = readushort(f) - local replacements = { } - for i=1,nofreplacements do - replacements[i] = readushort(f) - end - local coverage = readcoverage(f,tableoffset + coverage) -- not simple as we need to set key/value anyway - for index, newindex in next, coverage do - newindex = newindex + 1 - if index > nofglyphs or newindex > nofglyphs then - report("invalid index in %s format %i: %i -> %i (max %i)","single",subtype,index,newindex,nofglyphs) - coverage[index] = nil - else - coverage[index] = replacements[newindex] - end - end - return { - coverage = coverage - } - else - report("unsupported subtype %a in %a substitution",subtype,"single") - end -end - --- we see coverage format 0x300 in some old ms fonts - -local function sethandler(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,what) - local tableoffset = lookupoffset + offset - setposition(f,tableoffset) - local subtype = readushort(f) - if subtype == 1 then - local coverage = readushort(f) - local nofsequence = readushort(f) - local sequences = { } - for i=1,nofsequence do - sequences[i] = readushort(f) - end - for i=1,nofsequence do - setposition(f,tableoffset + sequences[i]) - local n = readushort(f) - local s = { } - for i=1,n do - s[i] = readushort(f) - end - sequences[i] = s - end - local coverage = readcoverage(f,tableoffset + coverage) - for index, newindex in next, coverage do - newindex = newindex + 1 - if index > nofglyphs or newindex > nofglyphs then - report("invalid index in %s format %i: %i -> %i (max %i)",what,subtype,index,newindex,nofglyphs) - coverage[index] = nil - else - coverage[index] = sequences[newindex] - end - end - return { - coverage = coverage - } - else - report("unsupported subtype %a in %a substitution",subtype,what) - end -end - -function gsubhandlers.multiple(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs) - return sethandler(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,"multiple") -end - -function gsubhandlers.alternate(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs) - return sethandler(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,"alternate") -end - -function gsubhandlers.ligature(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs) - local tableoffset = lookupoffset + offset - setposition(f,tableoffset) - local subtype = readushort(f) - if subtype == 1 then - local coverage = readushort(f) - local nofsets = readushort(f) - local ligatures = { } - for i=1,nofsets do - ligatures[i] = readushort(f) - end - for i=1,nofsets do - local offset = lookupoffset + offset + ligatures[i] - setposition(f,offset) - local n = readushort(f) - local l = { } - for i=1,n do - l[i] = offset + readushort(f) - end - ligatures[i] = l - end - local coverage = readcoverage(f,tableoffset + coverage) - for index, newindex in next, coverage do - local hash = { } - local ligatures = ligatures[newindex+1] - for i=1,#ligatures do - local offset = ligatures[i] - setposition(f,offset) - local lig = readushort(f) - local cnt = readushort(f) - local hsh = hash - for i=2,cnt do - local c = readushort(f) - local h = hsh[c] - if not h then - h = { } - hsh[c] = h - end - hsh = h - end - hsh.ligature = lig - end - coverage[index] = hash - end - return { - coverage = coverage - } - else - report("unsupported subtype %a in %a substitution",subtype,"ligature") - end -end - -function gsubhandlers.context(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs) - return unchainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,"substitution"), "context" -end - -function gsubhandlers.chainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs) - return chainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,"substitution"), "chainedcontext" -end - -function gsubhandlers.extension(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs) - return extension(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,gsubtypes,gsubhandlers,"substitution") -end - -function gsubhandlers.reversechainedcontextsingle(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs) - local tableoffset = lookupoffset + offset - setposition(f,tableoffset) - local subtype = readushort(f) - if subtype == 1 then -- NEEDS CHECKING - local current = readfirst(f) - local before = readarray(f) - local after = readarray(f) - local replacements = readarray(f) - current = readcoveragearray(f,tableoffset,current,true) - before = readcoveragearray(f,tableoffset,before,true) - after = readcoveragearray(f,tableoffset,after,true) - return { - coverage = { - format = "reversecoverage", -- reversesub - before = before, - current = current, - after = after, - replacements = replacements, - } - }, "reversechainedcontextsingle" - else - report("unsupported subtype %a in %a substitution",subtype,"reversechainedcontextsingle") - end -end - --- gpos handlers - -local function readpairsets(f,tableoffset,sets,format1,format2) - local done = { } - for i=1,#sets do - local offset = sets[i] - local reused = done[offset] - if not reused then - setposition(f,tableoffset + offset) - local n = readushort(f) - reused = { } - for i=1,n do - reused[i] = { - readushort(f), -- second glyph id - readposition(f,format1), - readposition(f,format2) - } - end - done[offset] = reused - end - sets[i] = reused - end - return sets -end - -local function readpairclasssets(f,nofclasses1,nofclasses2,format1,format2) - local classlist1 = { } - for i=1,nofclasses1 do - local classlist2 = { } - classlist1[i] = classlist2 - for j=1,nofclasses2 do - local one = readposition(f,format1) - local two = readposition(f,format2) - if one or two then - classlist2[j] = { one, two } - else - classlist2[j] = false - end - end - end - return classlist1 -end - --- no real gain in kerns as we pack - -function gposhandlers.single(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs) - local tableoffset = lookupoffset + offset - setposition(f,tableoffset) - local subtype = readushort(f) - if subtype == 1 then - local coverage = readushort(f) - local format = readushort(f) - local value = readposition(f,format) - local coverage = readcoverage(f,tableoffset+coverage) - for index, newindex in next, coverage do - coverage[index] = value - end - return { - format = "pair", - coverage = coverage - } - elseif subtype == 2 then - local coverage = readushort(f) - local format = readushort(f) - local values = { } - local nofvalues = readushort(f) - for i=1,nofvalues do - values[i] = readposition(f,format) - end - local coverage = readcoverage(f,tableoffset+coverage) - for index, newindex in next, coverage do - coverage[index] = values[newindex+1] - end - return { - format = "pair", - coverage = coverage - } - else - report("unsupported subtype %a in %a positioning",subtype,"single") - end -end - --- this needs checking! if no second pair then another advance over the list - --- ValueFormat1 applies to the ValueRecord of the first glyph in each pair. ValueRecords for all first glyphs must use ValueFormat1. If ValueFormat1 is set to zero (0), the corresponding glyph has no ValueRecord and, therefore, should not be repositioned. --- ValueFormat2 applies to the ValueRecord of the second glyph in each pair. ValueRecords for all second glyphs must use ValueFormat2. If ValueFormat2 is set to null, then the second glyph of the pair is the “next” glyph for which a lookup should be performed. - --- !!!!! this needs checking: when both false, we have no hit so then we might need to fall through - -function gposhandlers.pair(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs) - local tableoffset = lookupoffset + offset - setposition(f,tableoffset) - local subtype = readushort(f) - if subtype == 1 then - local coverage = readushort(f) - local format1 = readushort(f) - local format2 = readushort(f) - local sets = readarray(f) - sets = readpairsets(f,tableoffset,sets,format1,format2) - coverage = readcoverage(f,tableoffset + coverage) - for index, newindex in next, coverage do - local set = sets[newindex+1] - local hash = { } - for i=1,#set do - local value = set[i] - if value then - local other = value[1] - local first = value[2] - local second = value[3] - if first or second then - hash[other] = { first, second } -- needs checking - else - hash[other] = nil - end - end - end - coverage[index] = hash - end - return { - format = "pair", - coverage = coverage - } - elseif subtype == 2 then - local coverage = readushort(f) - local format1 = readushort(f) - local format2 = readushort(f) - local classdef1 = readushort(f) - local classdef2 = readushort(f) - local nofclasses1 = readushort(f) -- incl class 0 - local nofclasses2 = readushort(f) -- incl class 0 - local classlist = readpairclasssets(f,nofclasses1,nofclasses2,format1,format2) - coverage = readcoverage(f,tableoffset+coverage) - classdef1 = readclassdef(f,tableoffset+classdef1,coverage) - classdef2 = readclassdef(f,tableoffset+classdef2,nofglyphs) - local usedcoverage = { } - for g1, c1 in next, classdef1 do - if coverage[g1] then - local l1 = classlist[c1] - if l1 then - local hash = { } - for paired, class in next, classdef2 do - local offsets = l1[class] - if offsets then - local first = offsets[1] - local second = offsets[2] - if first or second then - hash[paired] = { first, second } - else - -- upto the next lookup for this combination - end - end - end - usedcoverage[g1] = hash - end - end - end - return { - format = "pair", - coverage = usedcoverage - } - elseif subtype == 3 then - report("yet unsupported subtype %a in %a positioning",subtype,"pair") - else - report("unsupported subtype %a in %a positioning",subtype,"pair") - end -end - -function gposhandlers.cursive(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs) - local tableoffset = lookupoffset + offset - setposition(f,tableoffset) - local subtype = readushort(f) - if subtype == 1 then - local coverage = tableoffset + readushort(f) - local nofrecords = readushort(f) - local records = { } - for i=1,nofrecords do - local entry = readushort(f) - local exit = readushort(f) - records[i] = { - entry = entry ~= 0 and (tableoffset + entry) or false, - exit = exit ~= 0 and (tableoffset + exit ) or false, - } - end - coverage = readcoverage(f,coverage) - for i=1,nofrecords do - local r = records[i] - records[i] = { - 1, -- will become hash after loading (must be unique per lookup when packed) - readanchor(f,r.entry) or nil, - readanchor(f,r.exit ) or nil, - } - end - for index, newindex in next, coverage do - coverage[index] = records[newindex+1] - end - return { - coverage = coverage - } - else - report("unsupported subtype %a in %a positioning",subtype,"cursive") - end -end - -local function handlemark(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,ligature) - local tableoffset = lookupoffset + offset - setposition(f,tableoffset) - local subtype = readushort(f) - if subtype == 1 then - -- we are one based, not zero - local markcoverage = tableoffset + readushort(f) - local basecoverage = tableoffset + readushort(f) - local nofclasses = readushort(f) - local markoffset = tableoffset + readushort(f) - local baseoffset = tableoffset + readushort(f) - -- - local markcoverage = readcoverage(f,markcoverage) - local basecoverage = readcoverage(f,basecoverage,true) -- TO BE CHECKED: true - -- - setposition(f,markoffset) - local markclasses = { } - local nofmarkclasses = readushort(f) - -- - local lastanchor = fontdata.lastanchor or 0 - local usedanchors = { } - -- --- local placeholder = (fontdata.markcount or 0) + 1 --- fontdata.markcount = placeholder --- placeholder = "m" .. placeholder - -- - for i=1,nofmarkclasses do - local class = readushort(f) + 1 - local offset = readushort(f) - if offset == 0 then - markclasses[i] = false - else --- markclasses[i] = { placeholder, class, markoffset + offset } - markclasses[i] = { class, markoffset + offset } - end - usedanchors[class] = true - end - for i=1,nofmarkclasses do - local mc = markclasses[i] - if mc then --- mc[3] = readanchor(f,mc[3]) - mc[2] = readanchor(f,mc[2]) - end - end - -- - setposition(f,baseoffset) - local nofbaserecords = readushort(f) - local baserecords = { } - -- - if ligature then - -- 3 components - -- 1 : class .. nofclasses -- NULL when empty - -- 2 : class .. nofclasses -- NULL when empty - -- 3 : class .. nofclasses -- NULL when empty - for i=1,nofbaserecords do -- here i is the class - local offset = readushort(f) - if offset == 0 then - baserecords[i] = false - else - baserecords[i] = baseoffset + offset - end - end - for i=1,nofbaserecords do - local recordoffset = baserecords[i] - if recordoffset then - setposition(f,recordoffset) - local nofcomponents = readushort(f) - local components = { } - for i=1,nofcomponents do - local classes = { } - for i=1,nofclasses do - local offset = readushort(f) - if offset ~= 0 then - classes[i] = recordoffset + offset - else - classes[i] = false - end - end - components[i] = classes - end - baserecords[i] = components - end - end - local baseclasses = { } -- setmetatableindex("table") - for i=1,nofclasses do - baseclasses[i] = { } - end - for i=1,nofbaserecords do - local components = baserecords[i] - if components then - local b = basecoverage[i] - for c=1,#components do - local classes = components[c] - if classes then - for i=1,nofclasses do - local anchor = readanchor(f,classes[i]) - local bclass = baseclasses[i] - local bentry = bclass[b] - if bentry then - bentry[c] = anchor - else - bclass[b]= { [c] = anchor } - end - end - end --- components[i] = classes - end - end - end - for index, newindex in next, markcoverage do - markcoverage[index] = markclasses[newindex+1] or nil - end - return { - format = "ligature", - baseclasses = baseclasses, - coverage = markcoverage, - } - else - for i=1,nofbaserecords do - local r = { } - for j=1,nofclasses do - local offset = readushort(f) - if offset == 0 then - r[j] = false - else - r[j] = baseoffset + offset - end - end - baserecords[i] = r - end - local baseclasses = { } -- setmetatableindex("table") - for i=1,nofclasses do - baseclasses[i] = { } - end - for i=1,nofbaserecords do - local r = baserecords[i] - local b = basecoverage[i] - for j=1,nofclasses do - baseclasses[j][b] = readanchor(f,r[j]) - end - end - for index, newindex in next, markcoverage do - markcoverage[index] = markclasses[newindex+1] or nil - end - -- we could actually already calculate the displacement if we want - return { - format = "base", - baseclasses = baseclasses, - coverage = markcoverage, - } - end - else - report("unsupported subtype %a in",subtype) - end - -end - -function gposhandlers.marktobase(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs) - return handlemark(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs) -end - -function gposhandlers.marktoligature(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs) - return handlemark(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,true) -end - -function gposhandlers.marktomark(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs) - return handlemark(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs) -end - -function gposhandlers.context(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs) - return unchainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,"positioning"), "context" -end - -function gposhandlers.chainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs) - return chainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,"positioning"), "chainedcontext" -end - -function gposhandlers.extension(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs) - return extension(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,gpostypes,gposhandlers,"positioning") -end - --- main loader - -do - - local plugins = { } - - function plugins.size(f,fontdata,tableoffset,feature) - if fontdata.designsize then - -- yes, there are fonts with multiple size entries ... it probably relates - -- to the other two fields (menu entries in some language) - else - local function check(offset) - setposition(f,offset) - local designsize = readushort(f) - if designsize > 0 then -- we could also have a threshold - local fontstyle = readushort(f) - local guimenuid = readushort(f) - local minsize = readushort(f) - local maxsize = readushort(f) - if minsize == 0 and maxsize == 0 and fontstyleid == 0 and guimenuid == 0 then - minsize = designsize - maxsize = designsize - end - if designsize >= minsize and designsize <= maxsize then - return minsize, maxsize, designsize - end - end - end - local minsize, maxsize, designsize = check(tableoffset+feature.offset+feature.parameters) - if not designsize then - -- some old adobe fonts have: tableoffset+feature.parameters and we could - -- use some heuristic but why bother ... this extra check will be removed - -- some day and/or when we run into an issue - minsize, maxsize, designsize = check(tableoffset+feature.parameters) - if designsize then - report("bad size feature in %a, falling back to wrong offset",fontdata.filename or "?") - else - report("bad size feature in %a,",fontdata.filename or "?") - end - end - if designsize then - fontdata.minsize = minsize - fontdata.maxsize = maxsize - fontdata.designsize = designsize - end - end - end - - -- feature order needs checking ... as we loop over a hash ... however, in the file - -- they are sorted so order is not that relevant - - local function reorderfeatures(fontdata,scripts,features) - local scriptlangs = { } - local featurehash = { } - local featureorder = { } - for script, languages in next, scripts do - for language, record in next, languages do - local hash = { } - local list = record.featureindices - for k=1,#list do - local index = list[k] - local feature = features[index] - local lookups = feature.lookups - local tag = feature.tag - if tag then - hash[tag] = true - end - if lookups then - for i=1,#lookups do - local lookup = lookups[i] - local o = featureorder[lookup] - if o then - local okay = true - for i=1,#o do - if o[i] == tag then - okay = false - break - end - end - if okay then - o[#o+1] = tag - end - else - featureorder[lookup] = { tag } - end - local f = featurehash[lookup] - if f then - local h = f[tag] - if h then - local s = h[script] - if s then - s[language] = true - else - h[script] = { [language] = true } - end - else - f[tag] = { [script] = { [language] = true } } - end - else - featurehash[lookup] = { [tag] = { [script] = { [language] = true } } } - end - -- - local h = scriptlangs[tag] - if h then - local s = h[script] - if s then - s[language] = true - else - h[script] = { [language] = true } - end - else - scriptlangs[tag] = { [script] = { [language] = true } } - end - end - end - end - end - end - return scriptlangs, featurehash, featureorder - end - - local function readscriplan(f,fontdata,scriptoffset) - setposition(f,scriptoffset) - local nofscripts = readushort(f) - local scripts = { } - for i=1,nofscripts do - scripts[readtag(f)] = scriptoffset + readushort(f) - end - -- script list -> language system info - local languagesystems = setmetatableindex("table") - for script, offset in next, scripts do - setposition(f,offset) - local defaultoffset = readushort(f) - local noflanguages = readushort(f) - local languages = { } - if defaultoffset > 0 then - languages.dflt = languagesystems[offset + defaultoffset] - end - for i=1,noflanguages do - local language = readtag(f) - local offset = offset + readushort(f) - languages[language] = languagesystems[offset] - end - scripts[script] = languages - end - -- script list -> language system info -> feature list - for offset, usedfeatures in next, languagesystems do - if offset > 0 then - setposition(f,offset) - local featureindices = { } - usedfeatures.featureindices = featureindices - usedfeatures.lookuporder = readushort(f) -- reserved, not used (yet) - usedfeatures.requiredindex = readushort(f) -- relates to required (can be 0xFFFF) - local noffeatures = readushort(f) - for i=1,noffeatures do - featureindices[i] = readushort(f) + 1 - end - end - end - return scripts - end - - local function readfeatures(f,fontdata,featureoffset) - setposition(f,featureoffset) - local features = { } - local noffeatures = readushort(f) - for i=1,noffeatures do - -- also shared? - features[i] = { - tag = readtag(f), - offset = readushort(f) - } - end - -- - for i=1,noffeatures do - local feature = features[i] - local offset = featureoffset+feature.offset - setposition(f,offset) - local parameters = readushort(f) -- feature.parameters - local noflookups = readushort(f) - if noflookups > 0 then - local lookups = { } - feature.lookups = lookups - for j=1,noflookups do - lookups[j] = readushort(f) + 1 - end - end - if parameters > 0 then - feature.parameters = parameters - local plugin = plugins[feature.tag] - if plugin then - plugin(f,fontdata,featureoffset,feature) - end - end - end - return features - end - - local function readlookups(f,lookupoffset,lookuptypes,featurehash,featureorder) - setposition(f,lookupoffset) - local lookups = { } - local noflookups = readushort(f) - for i=1,noflookups do - lookups[i] = readushort(f) - end - for lookupid=1,noflookups do - local index = lookups[lookupid] - setposition(f,lookupoffset+index) - local subtables = { } - local typebits = readushort(f) - local flagbits = readushort(f) - local lookuptype = lookuptypes[typebits] - local lookupflags = lookupflags[flagbits] - local nofsubtables = readushort(f) - for j=1,nofsubtables do - local offset = readushort(f) - subtables[j] = offset + index -- we can probably put lookupoffset here - end - -- which one wins? - local markclass = bittest(flagbits,0x0010) -- usemarkfilteringset - if markclass then - markclass = readushort(f) -- + 1 - end - local markset = rshift(flagbits,8) - if markset > 0 then - markclass = markset -- + 1 - end - lookups[lookupid] = { - type = lookuptype, - -- chain = chaindirections[lookuptype] or nil, - flags = lookupflags, - name = lookupid, - subtables = subtables, - markclass = markclass, - features = featurehash[lookupid], -- not if extension - order = featureorder[lookupid], - } - end - return lookups - end - - local function readscriptoffsets(f,fontdata,tableoffset) - if not tableoffset then - return - end - setposition(f,tableoffset) - local version = readulong(f) - if version ~= 0x00010000 then - report("table version %a of %a is not supported (yet), maybe font %s is bad",version,what,fontdata.filename) - return - end - -- - return tableoffset + readushort(f), tableoffset + readushort(f), tableoffset + readushort(f) - end - - local f_lookupname = formatters["%s_%s_%s"] - - local function resolvelookups(f,lookupoffset,fontdata,lookups,lookuptypes,lookuphandlers,what) - - local sequences = fontdata.sequences or { } - local sublookuplist = fontdata.sublookups or { } - fontdata.sequences = sequences - fontdata.sublookups = sublookuplist - local nofsublookups = #sublookuplist - local nofsequences = #sequences -- 0 - local lastsublookup = nofsublookups - local lastsequence = nofsequences - local lookupnames = lookupnames[what] - local sublookuphash = { } - local sublookupcheck = { } - local glyphs = fontdata.glyphs - local nofglyphs = fontdata.nofglyphs or #glyphs - local noflookups = #lookups - local lookupprefix = sub(what,2,2) -- g[s|p][ub|os] - -- - for lookupid=1,noflookups do - local lookup = lookups[lookupid] - local lookuptype = lookup.type - local subtables = lookup.subtables - local features = lookup.features - local handler = lookuphandlers[lookuptype] - if handler then - local nofsubtables = #subtables - local order = lookup.order - local flags = lookup.flags - -- this is expected in th efont handler (faster checking) - if flags[1] then flags[1] = "mark" end - if flags[2] then flags[2] = "ligature" end - if flags[3] then flags[3] = "base" end - -- - local markclass = lookup.markclass - -- local chain = lookup.chain - if nofsubtables > 0 then - local steps = { } - local nofsteps = 0 - local oldtype = nil - for s=1,nofsubtables do - local step, lt = handler(f,fontdata,lookupid,lookupoffset,subtables[s],glyphs,nofglyphs) - if lt then - lookuptype = lt - if oldtype and lt ~= oldtype then - report("messy %s lookup type %a and %a",what,lookuptype,oldtype) - end - oldtype = lookuptype - end - if not step then - report("unsupported %s lookup type %a",what,lookuptype) - else - nofsteps = nofsteps + 1 - steps[nofsteps] = step - local rules = step.rules - if rules then - for i=1,#rules do - local rule = rules[i] - local before = rule.before - local current = rule.current - local after = rule.after - if before then - for i=1,#before do - before[i] = tohash(before[i]) - end - -- as with original ctx ff loader - rule.before = reversed(before) - end - if current then - for i=1,#current do - current[i] = tohash(current[i]) - end - end - if after then - for i=1,#after do - after[i] = tohash(after[i]) - end - end - end - end - end - end - if nofsteps ~= nofsubtables then - report("bogus subtables removed in %s lookup type %a",what,lookuptype) - end - lookuptype = lookupnames[lookuptype] or lookuptype - if features then - nofsequences = nofsequences + 1 - -- report("registering %i as sequence step %i",lookupid,nofsequences) - local l = { - index = nofsequences, - name = f_lookupname(lookupprefix,"s",lookupid+lookupidoffset), - steps = steps, - nofsteps = nofsteps, - type = lookuptype, - markclass = markclass or nil, - flags = flags, - -- chain = chain, - order = order, - features = features, - } - sequences[nofsequences] = l - lookup.done = l - else - nofsublookups = nofsublookups + 1 - -- report("registering %i as sublookup %i",lookupid,nofsublookups) - local l = { - index = nofsublookups, - name = f_lookupname(lookupprefix,"l",lookupid+lookupidoffset), - steps = steps, - nofsteps = nofsteps, - type = lookuptype, - markclass = markclass or nil, - flags = flags, - -- chain = chain, - } - sublookuplist[nofsublookups] = l - sublookuphash[lookupid] = nofsublookups - sublookupcheck[lookupid] = 0 - lookup.done = l - end - else - report("no subtables for lookup %a",lookupid) - end - else - report("no handler for lookup %a with type %a",lookupid,lookuptype) - end - end - - -- When we have a context, we have sublookups that resolve into lookups for which we need to - -- know the type. We split the main lookuptable in two parts: sequences (the main lookups) - -- and subtable lookups (simple specs with no features). We could keep them merged and might do - -- that once we only use this loader. Then we can also move the simple specs into the sequence. - -- After all, we pack afterwards. - - local reported = { } - - local function report_issue(i,what,sequence,kind) - local name = sequence.name - if not reported[name] then - report("rule %i in %s lookup %a has %s lookups",i,what,name,kind) - reported[name] = true - end - end - - for i=lastsequence+1,nofsequences do - local sequence = sequences[i] - local steps = sequence.steps - for i=1,#steps do - local step = steps[i] - local rules = step.rules - if rules then - for i=1,#rules do - local rule = rules[i] - local rlookups = rule.lookups - if not rlookups then - report_issue(i,what,sequence,"no") - elseif not next(rlookups) then - -- can be ok as it aborts a chain sequence - report_issue(i,what,sequence,"empty") - rule.lookups = nil - else - -- we can have holes in rlookups - -- for index, lookupid in sortedhash(rlookups) do - local length = #rlookups --- for index in next, rlookups do --- if index > length then --- length = index --- end --- end - for index=1,length do - local lookupid = rlookups[index] - if lookupid then - local h = sublookuphash[lookupid] - if not h then - -- here we have a lookup that is used independent as well - -- as in another one - local lookup = lookups[lookupid] - if lookup then - local d = lookup.done - if d then - nofsublookups = nofsublookups + 1 - -- report("registering %i as sublookup %i",lookupid,nofsublookups) - h = { - index = nofsublookups, -- handy for tracing - name = f_lookupname(lookupprefix,"d",lookupid+lookupidoffset), - derived = true, -- handy for tracing - steps = d.steps, - nofsteps = d.nofsteps, - type = d.lookuptype, - markclass = d.markclass or nil, - flags = d.flags, - -- chain = d.chain, - } - sublookuplist[nofsublookups] = copy(h) -- we repack later - sublookuphash[lookupid] = nofsublookups - sublookupcheck[lookupid] = 1 - h = nofsublookups --- patch by Hans - else - report_issue(i,what,sequence,"missing") - rule.lookups = nil - break - end - else - report_issue(i,what,sequence,"bad") - rule.lookups = nil - break - end - else - sublookupcheck[lookupid] = sublookupcheck[lookupid] + 1 - end - rlookups[index] = h or false - else - rlookups[index] = false - end - end - end - end - end - end - end - - for i, n in sortedhash(sublookupcheck) do - local l = lookups[i] - local t = l.type - if n == 0 and t ~= "extension" then - local d = l.done - report("%s lookup %s of type %a is not used",what,d and d.name or l.name,t) - -- inspect(l) - end - end - - end - - local function readscripts(f,fontdata,what,lookuptypes,lookuphandlers,lookupstoo) - local datatable = fontdata.tables[what] - if not datatable then - return - end - local tableoffset = datatable.offset - if not tableoffset then - return - end - local scriptoffset, featureoffset, lookupoffset = readscriptoffsets(f,fontdata,tableoffset) - if not scriptoffset then - return - end - -- - local scripts = readscriplan(f,fontdata,scriptoffset) - local features = readfeatures(f,fontdata,featureoffset) - -- - local scriptlangs, featurehash, featureorder = reorderfeatures(fontdata,scripts,features) - -- - if fontdata.features then - fontdata.features[what] = scriptlangs - else - fontdata.features = { [what] = scriptlangs } - end - -- - if not lookupstoo then - return - end - -- - local lookups = readlookups(f,lookupoffset,lookuptypes,featurehash,featureorder) - -- - if lookups then - resolvelookups(f,lookupoffset,fontdata,lookups,lookuptypes,lookuphandlers,what) - end - end - - local function checkkerns(f,fontdata,specification) - local datatable = fontdata.tables.kern - if not datatable then - return -- no kerns - end - local features = fontdata.features - local gposfeatures = features and features.gpos - local name - if not gposfeatures or not gposfeatures.kern then - name = "kern" - elseif specification.globalkerns then - name = "globalkern" - else - report("ignoring global kern table using gpos kern feature") - return - end - report("adding global kern table as gpos feature %a",name) - setposition(f,datatable.offset) - local version = readushort(f) - local noftables = readushort(f) - local kerns = setmetatableindex("table") - for i=1,noftables do - local version = readushort(f) - local length = readushort(f) - local coverage = readushort(f) - -- bit 8-15 of coverage: format 0 or 2 - local format = bit32.rshift(coverage,8) -- is this ok? - if format == 0 then - local nofpairs = readushort(f) - local searchrange = readushort(f) - local entryselector = readushort(f) - local rangeshift = readushort(f) - for i=1,nofpairs do - kerns[readushort(f)][readushort(f)] = readfword(f) - end - elseif format == 2 then - -- apple specific so let's ignore it - else - -- not supported by ms - end - end - local feature = { dflt = { dflt = true } } - if not features then - fontdata.features = { gpos = { [name] = feature } } - elseif not gposfeatures then - fontdata.features.gpos = { [name] = feature } - else - gposfeatures[name] = feature - end - local sequences = fontdata.sequences - if not sequences then - sequences = { } - fontdata.sequences = sequences - end - local nofsequences = #sequences + 1 - sequences[nofsequences] = { - index = nofsequences, - name = name, - steps = { - { - coverage = kerns, - format = "kern", - }, - }, - nofsteps = 1, - type = "gpos_pair", - -- type = "gpos_single", -- maybe better - flags = { false, false, false, false }, - order = { name }, - features = { [name] = feature }, - } - end - - function readers.gsub(f,fontdata,specification) - if specification.details then - readscripts(f,fontdata,"gsub",gsubtypes,gsubhandlers,specification.lookups) - end - end - - function readers.gpos(f,fontdata,specification) - if specification.details then - readscripts(f,fontdata,"gpos",gpostypes,gposhandlers,specification.lookups) - if specification.lookups then - checkkerns(f,fontdata,specification) - end - end - end - -end - -function readers.gdef(f,fontdata,specification) - if specification.glyphs then - local datatable = fontdata.tables.gdef - if datatable then - local tableoffset = datatable.offset - setposition(f,tableoffset) - local version = readulong(f) - local classoffset = tableoffset + readushort(f) - local attachmentoffset = tableoffset + readushort(f) -- used for bitmaps - local ligaturecarets = tableoffset + readushort(f) -- used in editors (maybe nice for tracing) - local markclassoffset = tableoffset + readushort(f) - local marksetsoffset = version == 0x00010002 and (tableoffset + readushort(f)) - local glyphs = fontdata.glyphs - local marks = { } - local markclasses = setmetatableindex("table") - local marksets = setmetatableindex("table") - fontdata.marks = marks - fontdata.markclasses = markclasses - fontdata.marksets = marksets - -- class definitions - setposition(f,classoffset) - local classformat = readushort(f) - if classformat == 1 then - local firstindex = readushort(f) - local lastindex = firstindex + readushort(f) - 1 - for index=firstindex,lastindex do - local class = classes[readushort(f)] - if class == "mark" then - marks[index] = true - end - glyphs[index].class = class - end - elseif classformat == 2 then - local nofranges = readushort(f) - for i=1,nofranges do - local firstindex = readushort(f) - local lastindex = readushort(f) - local class = classes[readushort(f)] - if class then - for index=firstindex,lastindex do - glyphs[index].class = class - if class == "mark" then - marks[index] = true - end - end - end - end - end - -- mark classes - setposition(f,markclassoffset) - local classformat = readushort(f) - if classformat == 1 then - local firstindex = readushort(f) - local lastindex = firstindex + readushort(f) - 1 - for index=firstindex,lastindex do - markclasses[readushort(f)][index] = true - end - elseif classformat == 2 then - local nofranges = readushort(f) - for i=1,nofranges do - local firstindex = readushort(f) - local lastindex = readushort(f) - local class = markclasses[readushort(f)] - for index=firstindex,lastindex do - class[index] = true - end - end - end - -- mark sets : todo: just make the same as class sets above - if marksetsoffset and marksetsoffset > tableoffset then -- zero offset means no table - setposition(f,marksetsoffset) - local format = readushort(f) - if format == 1 then - local nofsets = readushort(f) - local sets = { } - for i=1,nofsets do - sets[i] = readulong(f) - end - for i=1,nofsets do - local offset = sets[i] - if offset ~= 0 then - marksets[i] = readcoverage(f,marksetsoffset+offset) - end - end - end - end - end - end -end - --- We keep this code here instead of font-otm.lua because we need coverage --- helpers. Okay, these helpers could go to the main reader file some day. - -local function readmathvalue(f) - local v = readshort(f) - skipshort(f,1) -- offset to device table - return v -end - -local function readmathconstants(f,fontdata,offset) - setposition(f,offset) - fontdata.mathconstants = { - ScriptPercentScaleDown = readshort(f), - ScriptScriptPercentScaleDown = readshort(f), - DelimitedSubFormulaMinHeight = readushort(f), - DisplayOperatorMinHeight = readushort(f), - MathLeading = readmathvalue(f), - AxisHeight = readmathvalue(f), - AccentBaseHeight = readmathvalue(f), - FlattenedAccentBaseHeight = readmathvalue(f), - SubscriptShiftDown = readmathvalue(f), - SubscriptTopMax = readmathvalue(f), - SubscriptBaselineDropMin = readmathvalue(f), - SuperscriptShiftUp = readmathvalue(f), - SuperscriptShiftUpCramped = readmathvalue(f), - SuperscriptBottomMin = readmathvalue(f), - SuperscriptBaselineDropMax = readmathvalue(f), - SubSuperscriptGapMin = readmathvalue(f), - SuperscriptBottomMaxWithSubscript = readmathvalue(f), - SpaceAfterScript = readmathvalue(f), - UpperLimitGapMin = readmathvalue(f), - UpperLimitBaselineRiseMin = readmathvalue(f), - LowerLimitGapMin = readmathvalue(f), - LowerLimitBaselineDropMin = readmathvalue(f), - StackTopShiftUp = readmathvalue(f), - StackTopDisplayStyleShiftUp = readmathvalue(f), - StackBottomShiftDown = readmathvalue(f), - StackBottomDisplayStyleShiftDown = readmathvalue(f), - StackGapMin = readmathvalue(f), - StackDisplayStyleGapMin = readmathvalue(f), - StretchStackTopShiftUp = readmathvalue(f), - StretchStackBottomShiftDown = readmathvalue(f), - StretchStackGapAboveMin = readmathvalue(f), - StretchStackGapBelowMin = readmathvalue(f), - FractionNumeratorShiftUp = readmathvalue(f), - FractionNumeratorDisplayStyleShiftUp = readmathvalue(f), - FractionDenominatorShiftDown = readmathvalue(f), - FractionDenominatorDisplayStyleShiftDown = readmathvalue(f), - FractionNumeratorGapMin = readmathvalue(f), - FractionNumeratorDisplayStyleGapMin = readmathvalue(f), - FractionRuleThickness = readmathvalue(f), - FractionDenominatorGapMin = readmathvalue(f), - FractionDenominatorDisplayStyleGapMin = readmathvalue(f), - SkewedFractionHorizontalGap = readmathvalue(f), - SkewedFractionVerticalGap = readmathvalue(f), - OverbarVerticalGap = readmathvalue(f), - OverbarRuleThickness = readmathvalue(f), - OverbarExtraAscender = readmathvalue(f), - UnderbarVerticalGap = readmathvalue(f), - UnderbarRuleThickness = readmathvalue(f), - UnderbarExtraDescender = readmathvalue(f), - RadicalVerticalGap = readmathvalue(f), - RadicalDisplayStyleVerticalGap = readmathvalue(f), - RadicalRuleThickness = readmathvalue(f), - RadicalExtraAscender = readmathvalue(f), - RadicalKernBeforeDegree = readmathvalue(f), - RadicalKernAfterDegree = readmathvalue(f), - RadicalDegreeBottomRaisePercent = readshort(f), - } -end - -local function readmathglyphinfo(f,fontdata,offset) - setposition(f,offset) - local italics = readushort(f) - local accents = readushort(f) - local extensions = readushort(f) - local kerns = readushort(f) - local glyphs = fontdata.glyphs - if italics ~= 0 then - setposition(f,offset+italics) - local coverage = readushort(f) - local nofglyphs = readushort(f) - coverage = readcoverage(f,offset+italics+coverage,true) - setposition(f,offset+italics+4) - for i=1,nofglyphs do - local italic = readmathvalue(f) - if italic ~= 0 then - local glyph = glyphs[coverage[i]] - local math = glyph.math - if not math then - glyph.math = { italic = italic } - else - math.italic = italic - end - end - end - fontdata.hasitalics = true - end - if accents ~= 0 then - setposition(f,offset+accents) - local coverage = readushort(f) - local nofglyphs = readushort(f) - coverage = readcoverage(f,offset+accents+coverage,true) - setposition(f,offset+accents+4) - for i=1,nofglyphs do - local accent = readmathvalue(f) - if accent ~= 0 then - local glyph = glyphs[coverage[i]] - local math = glyph.math - if not math then - glyph.math = { accent = accent } - else - math.accent = accent - end - end - end - end - if extensions ~= 0 then - setposition(f,offset+extensions) - end - if kerns ~= 0 then - local kernoffset = offset + kerns - setposition(f,kernoffset) - local coverage = readushort(f) - local nofglyphs = readushort(f) - if nofglyphs > 0 then - local function get(offset) - setposition(f,kernoffset+offset) - local n = readushort(f) - if n == 0 then - local k = readmathvalue(f) - if k == 0 then - -- no need for it (happens sometimes) - else - return { { kern = k } } - end - else - local l = { } - for i=1,n do - l[i] = { height = readmathvalue(f) } - end - for i=1,n do - l[i].kern = readmathvalue(f) - end - l[n+1] = { kern = readmathvalue(f) } - return l - end - end - local kernsets = { } - for i=1,nofglyphs do - local topright = readushort(f) - local topleft = readushort(f) - local bottomright = readushort(f) - local bottomleft = readushort(f) - kernsets[i] = { - topright = topright ~= 0 and topright or nil, - topleft = topleft ~= 0 and topleft or nil, - bottomright = bottomright ~= 0 and bottomright or nil, - bottomleft = bottomleft ~= 0 and bottomleft or nil, - } - end - coverage = readcoverage(f,kernoffset+coverage,true) - for i=1,nofglyphs do - local kernset = kernsets[i] - if next(kernset) then - local k = kernset.topright if k then kernset.topright = get(k) end - local k = kernset.topleft if k then kernset.topleft = get(k) end - local k = kernset.bottomright if k then kernset.bottomright = get(k) end - local k = kernset.bottomleft if k then kernset.bottomleft = get(k) end - if next(kernset) then - local glyph = glyphs[coverage[i]] - local math = glyph.math - if math then - math.kerns = kernset - else - glyph.math = { kerns = kernset } - end - end - end - end - end - end -end - -local function readmathvariants(f,fontdata,offset) - setposition(f,offset) - local glyphs = fontdata.glyphs - local minoverlap = readushort(f) - local vcoverage = readushort(f) - local hcoverage = readushort(f) - local vnofglyphs = readushort(f) - local hnofglyphs = readushort(f) - local vconstruction = { } - local hconstruction = { } - for i=1,vnofglyphs do - vconstruction[i] = readushort(f) - end - for i=1,hnofglyphs do - hconstruction[i] = readushort(f) - end - - fontdata.mathconstants.MinConnectorOverlap = minoverlap - - -- variants[i] = { - -- glyph = readushort(f), - -- advance = readushort(f), - -- } - - local function get(offset,coverage,nofglyphs,construction,kvariants,kparts,kitalic) - if coverage ~= 0 and nofglyphs > 0 then - local coverage = readcoverage(f,offset+coverage,true) - for i=1,nofglyphs do - local c = construction[i] - if c ~= 0 then - local index = coverage[i] - local glyph = glyphs[index] - local math = glyph.math - setposition(f,offset+c) - local assembly = readushort(f) - local nofvariants = readushort(f) - if nofvariants > 0 then - local variants, v = nil, 0 - for i=1,nofvariants do - local variant = readushort(f) - if variant == index then - -- ignore - elseif variants then - v = v + 1 - variants[v] = variant - else - v = 1 - variants = { variant } - end - skipshort(f) - end - if not variants then - -- only self - elseif not math then - math = { [kvariants] = variants } - glyph.math = math - else - math[kvariants] = variants - end - end - if assembly ~= 0 then - setposition(f,offset + c + assembly) - local italic = readmathvalue(f) - local nofparts = readushort(f) - local parts = { } - for i=1,nofparts do - local p = { - glyph = readushort(f), - start = readushort(f), - ["end"] = readushort(f), - advance = readushort(f), - } - local flags = readushort(f) - if bittest(flags,0x0001) then - p.extender = 1 -- true - end - parts[i] = p - end - if not math then - math = { - [kparts] = parts - } - glyph.math = math - else - math[kparts] = parts - end - if italic and italic ~= 0 then - math[kitalic] = italic - end - end - end - end - end - end - - get(offset,vcoverage,vnofglyphs,vconstruction,"vvariants","vparts","vitalic") - get(offset,hcoverage,hnofglyphs,hconstruction,"hvariants","hparts","hitalic") -end - -function readers.math(f,fontdata,specification) - if specification.glyphs then - local datatable = fontdata.tables.math - if datatable then - local tableoffset = datatable.offset - setposition(f,tableoffset) - local version = readulong(f) - if version ~= 0x00010000 then - report("table version %a of %a is not supported (yet), maybe font %s is bad",version,"math",fontdata.filename) - return - end - local constants = readushort(f) - local glyphinfo = readushort(f) - local variants = readushort(f) - if constants == 0 then - report("the math table of %a has no constants",fontdata.filename) - else - readmathconstants(f,fontdata,tableoffset+constants) - end - if glyphinfo ~= 0 then - readmathglyphinfo(f,fontdata,tableoffset+glyphinfo) - end - if variants ~= 0 then - readmathvariants(f,fontdata,tableoffset+variants) - end - end - end -end - -function readers.colr(f,fontdata,specification) - local datatable = fontdata.tables.colr - if datatable then - if specification.glyphs then - local tableoffset = datatable.offset - setposition(f,tableoffset) - local version = readushort(f) - if version ~= 0 then - report("table version %a of %a is not supported (yet), maybe font %s is bad",version,"colr",fontdata.filename) - return - end - if not fontdata.tables.cpal then - report("color table %a in font %a has no mandate %a table","colr",fontdata.filename,"cpal") - fontdata.colorpalettes = { } - end - local glyphs = fontdata.glyphs - local nofglyphs = readushort(f) - local baseoffset = readulong(f) - local layeroffset = readulong(f) - local noflayers = readushort(f) - local layerrecords = { } - local maxclass = 0 - -- The special value 0xFFFF is foreground (but we index from 1). It - -- more looks like indices into a palette so 'class' is a better name - -- than 'palette'. - setposition(f,tableoffset + layeroffset) - for i=1,noflayers do - local slot = readushort(f) - local class = readushort(f) - if class < 0xFFFF then - class = class + 1 - if class > maxclass then - maxclass = class - end - end - layerrecords[i] = { - slot = slot, - class = class, - } - end - fontdata.maxcolorclass = maxclass - setposition(f,tableoffset + baseoffset) - for i=0,nofglyphs-1 do - local glyphindex = readushort(f) - local firstlayer = readushort(f) - local noflayers = readushort(f) - local t = { } - for i=1,noflayers do - t[i] = layerrecords[firstlayer+i] - end - glyphs[glyphindex].colors = t - end - end - fontdata.hascolor = true - end -end - -function readers.cpal(f,fontdata,specification) - if specification.glyphs then - local datatable = fontdata.tables.cpal - if datatable then - local tableoffset = datatable.offset - setposition(f,tableoffset) - local version = readushort(f) - if version > 1 then - report("table version %a of %a is not supported (yet), maybe font %s is bad",version,"cpal",fontdata.filename) - return - end - local nofpaletteentries = readushort(f) - local nofpalettes = readushort(f) - local nofcolorrecords = readushort(f) - local firstcoloroffset = readulong(f) - local colorrecords = { } - local palettes = { } - for i=1,nofpalettes do - palettes[i] = readushort(f) - end - if version == 1 then - -- used for guis - local palettettypesoffset = readulong(f) - local palettelabelsoffset = readulong(f) - local paletteentryoffset = readulong(f) - end - setposition(f,tableoffset+firstcoloroffset) - for i=1,nofcolorrecords do - local b, g, r, a = readbytes(f,4) - colorrecords[i] = { - r, g, b, a ~= 255 and a or nil, - } - end - for i=1,nofpalettes do - local p = { } - local o = palettes[i] - for j=1,nofpaletteentries do - p[j] = colorrecords[o+j] - end - palettes[i] = p - end - fontdata.colorpalettes = palettes - end - end -end - -function readers.svg(f,fontdata,specification) - local datatable = fontdata.tables.svg - if datatable then - if specification.glyphs then - local tableoffset = datatable.offset - setposition(f,tableoffset) - local version = readushort(f) - if version ~= 0 then - report("table version %a of %a is not supported (yet), maybe font %s is bad",version,"svg",fontdata.filename) - return - end - local glyphs = fontdata.glyphs - local indexoffset = tableoffset + readulong(f) - local reserved = readulong(f) - setposition(f,indexoffset) - local nofentries = readushort(f) - local entries = { } - for i=1,nofentries do - entries[i] = { - first = readushort(f), - last = readushort(f), - offset = indexoffset + readulong(f), - length = readulong(f), - } - end - for i=1,nofentries do - local entry = entries[i] - setposition(f,entry.offset) - entries[i] = { - first = entry.first, - last = entry.last, - data = readstring(f,entry.length) - } - end - fontdata.svgshapes = entries - end - fontdata.hascolor = true - end -end diff --git a/tex/compat/luaotfload/fontloader-font-gbn.lua b/tex/compat/luaotfload/fontloader-font-gbn.lua deleted file mode 100644 index 21c6061542d691d259aa878656c68158d8768503..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/fontloader-font-gbn.lua +++ /dev/null @@ -1,251 +0,0 @@ -if not modules then modules = { } end modules ['font-gbn'] = { - version = 1.001, - comment = "companion to luatex-*.tex", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- generic [base|node] mode handler - -if context then - texio.write_nl("fatal error: this module is not for context") - os.exit() -end - -local fonts = fonts -local nodes = nodes - -local nuts = nodes.nuts -- context abstraction of direct nodes - -local traverse_id = nuts.traverse_id -local flush_node = nuts.flush_node - -local glyph_code = nodes.nodecodes.glyph -local disc_code = nodes.nodecodes.disc - -local tonode = nuts.tonode -local tonut = nuts.tonut - -local getfont = nuts.getfont -local getchar = nuts.getchar -local getid = nuts.getid -local getboth = nuts.getboth -local getprev = nuts.getprev -local getnext = nuts.getnext -local getdisc = nuts.getdisc -local setchar = nuts.setchar -local setlink = nuts.setlink -local setprev = nuts.setprev -local nodetail = nuts.tail - --- from now on we apply ligaturing and kerning here because it might interfere with complex --- opentype discretionary handling where the base ligature pass expect some weird extra --- pointers (which then confuse the tail slider that has some checking built in) - -local n_ligaturing = node.ligaturing -local n_kerning = node.kerning - -local ligaturing = nuts.ligaturing -local kerning = nuts.kerning - -local basemodepass = true - -local function l_warning() texio.write_nl("warning: node.ligaturing called directly") l_warning = nil end -local function k_warning() texio.write_nl("warning: node.kerning called directly") k_warning = nil end - -function node.ligaturing(...) - if basemodepass and l_warning then - l_warning() - end - return n_ligaturing(...) -end - -function node.kerning(...) - if basemodepass and k_warning then - k_warning() - end - return n_kerning(...) -end - -function nodes.handlers.setbasemodepass(v) - basemodepass = v -end - -function nodes.handlers.nodepass(head) - local fontdata = fonts.hashes.identifiers - if fontdata then - local nuthead = tonut(head) - local usedfonts = { } - local basefonts = { } - local prevfont = nil - local basefont = nil - local variants = nil - local redundant = nil - for n in traverse_id(glyph_code,nuthead) do - local font = getfont(n) - if font ~= prevfont then - if basefont then - basefont[2] = getprev(n) - end - prevfont = font - local used = usedfonts[font] - if not used then - local tfmdata = fontdata[font] -- - if tfmdata then - local shared = tfmdata.shared -- we need to check shared, only when same features - if shared then - local processors = shared.processes - if processors and #processors > 0 then - usedfonts[font] = processors - elseif basemodepass then - basefont = { n, nil } - basefonts[#basefonts+1] = basefont - end - end - local resources = tfmdata.resources - variants = resources and resources.variants - variants = variants and next(variants) and variants or false - end - else - local tfmdata = fontdata[prevfont] - if tfmdata then - local resources = tfmdata.resources - variants = resources and resources.variants - variants = variants and next(variants) and variants or false - end - end - end - if variants then - local char = getchar(n) - if char >= 0xFE00 and (char <= 0xFE0F or (char >= 0xE0100 and char <= 0xE01EF)) then - local hash = variants[char] - if hash then - local p = getprev(n) - if p and getid(p) == glyph_code then - local variant = hash[getchar(p)] - if variant then - setchar(p,variant) - end - end - end - -- per generic user request we always remove selectors - if not redundant then - redundant = { n } - else - redundant[#redundant+1] = n - end - end - end - end - local nofbasefonts = #basefonts - if redundant then - for i=1,#redundant do - local r = redundant[i] - local p, n = getboth(r) - if r == nuthead then - nuthead = n - setprev(n) - else - setlink(p,n) - end - if nofbasefonts > 0 then - for i=1,nofbasefonts do - local bi = basefonts[i] - if r == bi[1] then - bi[1] = n - end - if r == bi[2] then - bi[2] = n - end - end - end - flush_node(r) - end - end - for d in traverse_id(disc_code,nuthead) do - local _, _, r = getdisc(d) - if r then - for n in traverse_id(glyph_code,r) do - local font = getfont(n) - if font ~= prevfont then - prevfont = font - local used = usedfonts[font] - if not used then - local tfmdata = fontdata[font] -- - if tfmdata then - local shared = tfmdata.shared -- we need to check shared, only when same features - if shared then - local processors = shared.processes - if processors and #processors > 0 then - usedfonts[font] = processors - end - end - end - end - end - end - end - end - if next(usedfonts) then - for font, processors in next, usedfonts do - for i=1,#processors do - head = processors[i](head,font,0) or head - end - end - end - if basemodepass and nofbasefonts > 0 then - for i=1,nofbasefonts do - local range = basefonts[i] - local start = range[1] - local stop = range[2] - if start then - local front = nuthead == start - if not stop then - stop = nodetail(start) - end - if stop then - start, stop = ligaturing(start,stop) - start, stop = kerning(start,stop) - elseif start then -- safeguard - start, stop = ligaturing(start,stop) - start, stop = kerning(start,stop) - end - if front and nuthead ~= start then - head = tonode(start) - end - end - end - end - return head, true - else - return head, false - end -end - -function nodes.handlers.basepass(head) - if not basemodepass then - head = n_ligaturing(head) - head = n_kerning(head) - end - return head, true -end - -local nodepass = nodes.handlers.nodepass -local basepass = nodes.handlers.basepass -local injectpass = nodes.injections.handler -local protectpass = nodes.handlers.protectglyphs - -function nodes.simple_font_handler(head) - if head then - head = nodepass(head) - head = injectpass(head) - if not basemodepass then - head = basepass(head) - end - protectpass(head) - return head, true - else - return head, false - end -end diff --git a/tex/compat/luaotfload/fontloader-font-ini.lua b/tex/compat/luaotfload/fontloader-font-ini.lua deleted file mode 100644 index abc319484d231e2f2807a0ac6e2149e0a654bf68..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/fontloader-font-ini.lua +++ /dev/null @@ -1,30 +0,0 @@ -if not modules then modules = { } end modules ['font-ini'] = { - version = 1.001, - comment = "companion to font-ini.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - ---[[ldx-- -<p>Not much is happening here.</p> ---ldx]]-- - -local allocate = utilities.storage.allocate - -fonts = fonts or { } -local fonts = fonts - -fonts.hashes = { identifiers = allocate() } - -fonts.tables = fonts.tables or { } -fonts.helpers = fonts.helpers or { } -fonts.tracers = fonts.tracers or { } -- for the moment till we have move to moduledata -fonts.specifiers = fonts.specifiers or { } -- in format ! - -fonts.analyzers = { } -- not needed here -fonts.readers = { } -fonts.definers = { methods = { } } -fonts.loggers = { register = function() end } - -fontloader.totable = fontloader.to_table -- not used diff --git a/tex/compat/luaotfload/fontloader-font-lua.lua b/tex/compat/luaotfload/fontloader-font-lua.lua deleted file mode 100644 index 6fbbcf17e4e5bc725ff26b3bc62b3366382f2699..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/fontloader-font-lua.lua +++ /dev/null @@ -1,46 +0,0 @@ -if not modules then modules = { } end modules ['font-lua'] = { - version = 1.001, - comment = "companion to font-ini.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -local trace_defining = false trackers.register("fonts.defining", function(v) trace_defining = v end) - -local report_lua = logs.reporter("fonts","lua loading") - -local fonts = fonts -local readers = fonts.readers -fonts.formats.lua = "lua" - --- we could add support for features here - -local function check_lua(specification,fullname) - -- standard tex file lookup - local fullname = resolvers.findfile(fullname) or "" - if fullname ~= "" then - local loader = loadfile(fullname) - loader = loader and loader() - return loader and loader(specification) - end -end - -readers.check_lua = check_lua - -function readers.lua(specification) - local original = specification.specification - if trace_defining then - report_lua("using lua reader for %a",original) - end - local fullname = specification.filename or "" - if fullname == "" then - local forced = specification.forced or "" - if forced ~= "" then - fullname = specification.name .. "." .. forced - else - fullname = specification.name - end - end - return check_lua(specification,fullname) -end diff --git a/tex/compat/luaotfload/fontloader-font-map.lua b/tex/compat/luaotfload/fontloader-font-map.lua deleted file mode 100644 index e2254f8ca0edb44dfe36445cdca69cf07e310f24..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/fontloader-font-map.lua +++ /dev/null @@ -1,546 +0,0 @@ -if not modules then modules = { } end modules ['font-map'] = { - version = 1.001, - comment = "companion to font-ini.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -local tonumber, next, type = tonumber, next, type - -local match, format, find, concat, gsub, lower = string.match, string.format, string.find, table.concat, string.gsub, string.lower -local P, R, S, C, Ct, Cc, lpegmatch = lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.Ct, lpeg.Cc, lpeg.match -local floor = math.floor -local formatters = string.formatters -local sortedhash, sortedkeys = table.sortedhash, table.sortedkeys - -local trace_loading = false trackers.register("fonts.loading", function(v) trace_loading = v end) -local trace_mapping = false trackers.register("fonts.mapping", function(v) trace_mapping = v end) - -local report_fonts = logs.reporter("fonts","loading") -- not otf only - -local force_ligatures = false directives.register("fonts.mapping.forceligatures",function(v) force_ligatures = v end) - -local fonts = fonts or { } -local mappings = fonts.mappings or { } -fonts.mappings = mappings - -local allocate = utilities.storage.allocate - ---[[ldx-- -<p>Eventually this code will disappear because map files are kind -of obsolete. Some code may move to runtime or auxiliary modules.</p> -<p>The name to unciode related code will stay of course.</p> ---ldx]]-- - --- local function loadlumtable(filename) -- will move to font goodies --- local lumname = file.replacesuffix(file.basename(filename),"lum") --- local lumfile = resolvers.findfile(lumname,"map") or "" --- if lumfile ~= "" and lfs.isfile(lumfile) then --- if trace_loading or trace_mapping then --- report_fonts("loading map table %a",lumfile) --- end --- lumunic = dofile(lumfile) --- return lumunic, lumfile --- end --- end - -local hex = R("AF","af","09") ------ hexfour = (hex*hex*hex*hex) / function(s) return tonumber(s,16) end ------ hexsix = (hex*hex*hex*hex*hex*hex) / function(s) return tonumber(s,16) end -local hexfour = (hex*hex*hex^-2) / function(s) return tonumber(s,16) end -local hexsix = (hex*hex*hex^-4) / function(s) return tonumber(s,16) end -local dec = (R("09")^1) / tonumber -local period = P(".") -local unicode = (P("uni") + P("UNI")) * (hexfour * (period + P(-1)) * Cc(false) + Ct(hexfour^1) * Cc(true)) -- base planes -local ucode = (P("u") + P("U") ) * (hexsix * (period + P(-1)) * Cc(false) + Ct(hexsix ^1) * Cc(true)) -- extended -local index = P("index") * dec * Cc(false) - -local parser = unicode + ucode + index - -local parsers = { } - -local function makenameparser(str) - if not str or str == "" then - return parser - else - local p = parsers[str] - if not p then - p = P(str) * period * dec * Cc(false) - parsers[str] = p - end - return p - end -end - -local f_single = formatters["%04X"] -local f_double = formatters["%04X%04X"] - --- 0.684 0.661 0,672 0.650 : cache at lua end (more mem) --- 0.682 0,672 0.698 0.657 : no cache (moderate mem i.e. lua strings) --- 0.644 0.647 0.655 0.645 : convert in c (less mem in theory) - --- local tounicodes = table.setmetatableindex(function(t,unicode) --- local s --- if unicode < 0xD7FF or (unicode > 0xDFFF and unicode <= 0xFFFF) then --- s = f_single(unicode) --- else --- unicode = unicode - 0x10000 --- s = f_double(floor(unicode/1024)+0xD800,unicode%1024+0xDC00) --- end --- t[unicode] = s --- return s --- end) --- --- local function tounicode16(unicode,name) --- local s = tounicodes[unicode] --- if s then --- return s --- else --- report_fonts("can't convert %a in %a into tounicode",unicode,name) --- end --- end --- --- local function tounicode16sequence(unicodes,name) --- local t = { } --- for l=1,#unicodes do --- local u = unicodes[l] --- local s = tounicodes[u] --- if s then --- t[l] = s --- else --- report_fonts ("can't convert %a in %a into tounicode",u,name) --- return --- end --- end --- return concat(t) --- end --- --- local function tounicode(unicode,name) --- if type(unicode) == "table" then --- local t = { } --- for l=1,#unicode do --- local u = unicode[l] --- local s = tounicodes[u] --- if s then --- t[l] = s --- else --- report_fonts ("can't convert %a in %a into tounicode",u,name) --- return --- end --- end --- return concat(t) --- else --- local s = tounicodes[unicode] --- if s then --- return s --- else --- report_fonts("can't convert %a in %a into tounicode",unicode,name) --- end --- end --- end - -local function tounicode16(unicode) - if unicode < 0xD7FF or (unicode > 0xDFFF and unicode <= 0xFFFF) then - return f_single(unicode) - else - unicode = unicode - 0x10000 - return f_double(floor(unicode/1024)+0xD800,unicode%1024+0xDC00) - end -end - -local function tounicode16sequence(unicodes) - local t = { } - for l=1,#unicodes do - local u = unicodes[l] - if u < 0xD7FF or (u > 0xDFFF and u <= 0xFFFF) then - t[l] = f_single(u) - else - u = u - 0x10000 - t[l] = f_double(floor(u/1024)+0xD800,u%1024+0xDC00) - end - end - return concat(t) -end - -local function tounicode(unicode,name) - if type(unicode) == "table" then - local t = { } - for l=1,#unicode do - local u = unicode[l] - if u < 0xD7FF or (u > 0xDFFF and u <= 0xFFFF) then - t[l] = f_single(u) - else - u = u - 0x10000 - t[l] = f_double(floor(u/1024)+0xD800,u%1024+0xDC00) - end - end - return concat(t) - else - if unicode < 0xD7FF or (unicode > 0xDFFF and unicode <= 0xFFFF) then - return f_single(unicode) - else - unicode = unicode - 0x10000 - return f_double(floor(unicode/1024)+0xD800,unicode%1024+0xDC00) - end - end -end - -local function fromunicode16(str) - if #str == 4 then - return tonumber(str,16) - else - local l, r = match(str,"(....)(....)") - -- return (tonumber(l,16))*0x400 + tonumber(r,16) - 0xDC00 - return 0x10000 + (tonumber(l,16)-0xD800)*0x400 + tonumber(r,16) - 0xDC00 - end -end - --- Slightly slower: --- --- local p = C(4) * (C(4)^-1) / function(l,r) --- if r then --- return (tonumber(l,16))*0x400 + tonumber(r,16) - 0xDC00 --- else --- return tonumber(l,16) --- end --- end --- --- local function fromunicode16(str) --- return lpegmatch(p,str) --- end - -mappings.makenameparser = makenameparser -mappings.tounicode = tounicode -mappings.tounicode16 = tounicode16 -mappings.tounicode16sequence = tounicode16sequence -mappings.fromunicode16 = fromunicode16 - -local ligseparator = P("_") -local varseparator = P(".") -local namesplitter = Ct(C((1 - ligseparator - varseparator)^1) * (ligseparator * C((1 - ligseparator - varseparator)^1))^0) - --- maybe: ff fi fl ffi ffl => f_f f_i f_l f_f_i f_f_l - --- local function test(name) --- local split = lpegmatch(namesplitter,name) --- print(string.formatters["%s: [% t]"](name,split)) --- end - --- test("i.f_") --- test("this") --- test("this.that") --- test("japan1.123") --- test("such_so_more") --- test("such_so_more.that") - --- to be completed .. for fonts that use unicodes for ligatures which --- is a actually a bad thing and should be avoided in the first place - -do - - local overloads = allocate { - IJ = { name = "I_J", unicode = { 0x49, 0x4A }, mess = 0x0132 }, - ij = { name = "i_j", unicode = { 0x69, 0x6A }, mess = 0x0133 }, - ff = { name = "f_f", unicode = { 0x66, 0x66 }, mess = 0xFB00 }, - fi = { name = "f_i", unicode = { 0x66, 0x69 }, mess = 0xFB01 }, - fl = { name = "f_l", unicode = { 0x66, 0x6C }, mess = 0xFB02 }, - ffi = { name = "f_f_i", unicode = { 0x66, 0x66, 0x69 }, mess = 0xFB03 }, - ffl = { name = "f_f_l", unicode = { 0x66, 0x66, 0x6C }, mess = 0xFB04 }, - fj = { name = "f_j", unicode = { 0x66, 0x6A } }, - fk = { name = "f_k", unicode = { 0x66, 0x6B } }, - } - - local o = { } - - for k, v in next, overloads do - local name = v.name - local mess = v.mess - if name then - o[name] = v - end - if mess then - o[mess] = v - end - o[k] = v - end - - mappings.overloads = o - -end - -function mappings.addtounicode(data,filename,checklookups) - local resources = data.resources - local unicodes = resources.unicodes - if not unicodes then - if trace_mapping then - report_fonts("no unicode list, quitting tounicode for %a",filename) - end - return - end - local properties = data.properties - local descriptions = data.descriptions - local overloads = mappings.overloads - -- we need to move this code - unicodes['space'] = unicodes['space'] or 32 - unicodes['hyphen'] = unicodes['hyphen'] or 45 - unicodes['zwj'] = unicodes['zwj'] or 0x200D - unicodes['zwnj'] = unicodes['zwnj'] or 0x200C - -- - local private = fonts.constructors and fonts.constructors.privateoffset or 0xF0000 -- 0x10FFFF - local unicodevector = fonts.encodings.agl.unicodes or { } -- loaded runtime in context - local contextvector = fonts.encodings.agl.ctxcodes or { } -- loaded runtime in context - local missing = { } - local nofmissing = 0 - local oparser = nil - local cidnames = nil - local cidcodes = nil - local cidinfo = properties.cidinfo - local usedmap = cidinfo and fonts.cid.getmap(cidinfo) - local uparser = makenameparser() -- hm, every time? - if usedmap then - oparser = usedmap and makenameparser(cidinfo.ordering) - cidnames = usedmap.names - cidcodes = usedmap.unicodes - end - local ns = 0 - local nl = 0 - -- - -- in order to avoid differences between runs due to hash randomization we - -- run over a sorted list - -- - local dlist = sortedkeys(descriptions) - -- - -- for du, glyph in next, descriptions do - for i=1,#dlist do - local du = dlist[i] - local glyph = descriptions[du] - local name = glyph.name - if name then - local overload = overloads[name] or overloads[du] - if overload then - -- get rid of weird ligatures - -- glyph.name = overload.name - glyph.unicode = overload.unicode - else - local gu = glyph.unicode -- can already be set (number or table) - if not gu or gu == -1 or du >= private or (du >= 0xE000 and du <= 0xF8FF) or du == 0xFFFE or du == 0xFFFF then - local unicode = unicodevector[name] or contextvector[name] - if unicode then - glyph.unicode = unicode - ns = ns + 1 - end - -- cidmap heuristics, beware, there is no guarantee for a match unless - -- the chain resolves - if (not unicode) and usedmap then - local foundindex = lpegmatch(oparser,name) - if foundindex then - unicode = cidcodes[foundindex] -- name to number - if unicode then - glyph.unicode = unicode - ns = ns + 1 - else - local reference = cidnames[foundindex] -- number to name - if reference then - local foundindex = lpegmatch(oparser,reference) - if foundindex then - unicode = cidcodes[foundindex] - if unicode then - glyph.unicode = unicode - ns = ns + 1 - end - end - if not unicode or unicode == "" then - local foundcodes, multiple = lpegmatch(uparser,reference) - if foundcodes then - glyph.unicode = foundcodes - if multiple then - nl = nl + 1 - unicode = true - else - ns = ns + 1 - unicode = foundcodes - end - end - end - end - end - end - end - -- a.whatever or a_b_c.whatever or a_b_c (no numbers) a.b_ - -- - -- It is not trivial to find a solution that suits all fonts. We tried several alternatives - -- and this one seems to work reasonable also with fonts that use less standardized naming - -- schemes. The extra private test is tested by KE and seems to work okay with non-typical - -- fonts as well. - -- - if not unicode or unicode == "" then - local split = lpegmatch(namesplitter,name) - local nsplit = split and #split or 0 -- add if - if nsplit == 0 then - -- skip - elseif nsplit == 1 then - local base = split[1] - local u = unicodes[base] or unicodevector[base] or contextvector[name] - if not u then - -- skip - elseif type(u) == "table" then - -- unlikely - if u[1] < private then - unicode = u - glyph.unicode = unicode - end - elseif u < private then - unicode = u - glyph.unicode = unicode - end - else - local t, n = { }, 0 - for l=1,nsplit do - local base = split[l] - local u = unicodes[base] or unicodevector[base] or contextvector[name] - if not u then - break - elseif type(u) == "table" then - if u[1] >= private then - break - end - n = n + 1 - t[n] = u[1] - else - if u >= private then - break - end - n = n + 1 - t[n] = u - end - end - if n > 0 then - if n == 1 then - unicode = t[1] - else - unicode = t - end - glyph.unicode = unicode - end - end - nl = nl + 1 - end - -- last resort (we might need to catch private here as well) - if not unicode or unicode == "" then - local foundcodes, multiple = lpegmatch(uparser,name) - if foundcodes then - glyph.unicode = foundcodes - if multiple then - nl = nl + 1 - unicode = true - else - ns = ns + 1 - unicode = foundcodes - end - end - end - -- check using substitutes and alternates - local r = overloads[unicode] - if r then - unicode = r.unicode - glyph.unicode = unicode - end - -- - if not unicode then - missing[du] = true - nofmissing = nofmissing + 1 - end - end - end - else - local overload = overloads[du] - if overload then - glyph.unicode = overload.unicode - end - end - end - if type(checklookups) == "function" then - checklookups(data,missing,nofmissing) - end - - -- todo: go lowercase - - local collected = false - local unicoded = 0 - -- for du, glyph in next, descriptions do - for i=1,#dlist do - local du = dlist[i] - local glyph = descriptions[du] - if glyph.class == "ligature" and (force_ligatures or not glyph.unicode) then - if not collected then - collected = fonts.handlers.otf.readers.getcomponents(data) - if not collected then - break - end - end - local u = collected[du] -- always tables - if u then - local n = #u - for i=1,n do - if u[i] > private then - n = 0 - break - end - end - if n > 0 then - if n > 1 then - glyph.unicode = u - else - glyph.unicode = u[1] - end - unicoded = unicoded + 1 - end - end - end - end - if trace_mapping and unicoded > 0 then - report_fonts("%n ligature tounicode mappings deduced from gsub ligature features",unicoded) - end - if trace_mapping then - -- for unic, glyph in sortedhash(descriptions) do - for i=1,#dlist do - local du = dlist[i] - local glyph = descriptions[du] - local name = glyph.name or "-" - local index = glyph.index or 0 - local unicode = glyph.unicode - if unicode then - if type(unicode) == "table" then - local unicodes = { } - for i=1,#unicode do - unicodes[i] = formatters("%U",unicode[i]) - end - report_fonts("internal slot %U, name %a, unicode %U, tounicode % t",index,name,du,unicodes) - else - report_fonts("internal slot %U, name %a, unicode %U, tounicode %U",index,name,du,unicode) - end - else - report_fonts("internal slot %U, name %a, unicode %U",index,name,du) - end - end - end - if trace_loading and (ns > 0 or nl > 0) then - report_fonts("%s tounicode entries added, ligatures %s",nl+ns,ns) - end -end - --- local parser = makenameparser("Japan1") --- local parser = makenameparser() --- local function test(str) --- local b, a = lpegmatch(parser,str) --- print((a and table.serialize(b)) or b) --- end --- test("a.sc") --- test("a") --- test("uni1234") --- test("uni1234.xx") --- test("uni12349876") --- test("u123400987600") --- test("index1234") --- test("Japan1.123") diff --git a/tex/compat/luaotfload/fontloader-font-ocl.lua b/tex/compat/luaotfload/fontloader-font-ocl.lua deleted file mode 100644 index 65a1c63427c6e241540a6bacffcc6e381c2af58a..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/fontloader-font-ocl.lua +++ /dev/null @@ -1,413 +0,0 @@ -if not modules then modules = { } end modules ['font-ocl'] = { - version = 1.001, - comment = "companion to font-otf.lua (context)", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- todo : user list of colors - -local tostring, next, format = tostring, next, string.format -local round, max = math.round, math.round - -local formatters = string.formatters -local tounicode = fonts.mappings.tounicode - -local otf = fonts.handlers.otf - -local f_color = formatters["pdf:direct:%f %f %f rg"] -local f_gray = formatters["pdf:direct:%f g"] -local s_black = "pdf:direct:0 g" - -if context then - - local startactualtext = nil - local stopactualtext = nil - - function otf.getactualtext(s) - if not startactualtext then - startactualtext = backends.codeinjections.startunicodetoactualtextdirect - stopactualtext = backends.codeinjections.stopunicodetoactualtextdirect - end - return startactualtext(s), stopactualtext() - end - -else - - local tounicode = fonts.mappings.tounicode16 - - function otf.getactualtext(s) - return - "/Span << /ActualText <feff" .. n .. "> >> BDC", - "EMC" - end - -end - -local sharedpalettes = { } - -if context then - - local graytorgb = attributes.colors.graytorgb - local cmyktorgb = attributes.colors.cmyktorgb - - function otf.registerpalette(name,values) - sharedpalettes[name] = values - for i=1,#values do - local v = values[i] - local r, g, b - local s = v.s - if s then - r, g, b = graytorgb(s) - else - local c, m, y, k = v.c, v.m, v.y, v.k - if c or m or y or k then - r, g, b = cmyktorgb(c or 0,m or 0,y or 0,k or 0) - else - r, g, b = v.r, v.g, v.b - end - end - values[i] = { - max(r and round(r*255) or 0,255), - max(g and round(g*255) or 0,255), - max(b and round(b*255) or 0,255) - } - end - end - -else -- for generic - - function otf.registerpalette(name,values) - sharedpalettes[name] = values - for i=1,#values do - local v = values[i] - values[i] = { - max(round((v.r or 0)*255),255), - max(round((v.g or 0)*255),255), - max(round((v.b or 0)*255),255) - } - end - end - -end - -local function initializecolr(tfmdata,kind,value) -- hm, always value - if value then - local palettes = tfmdata.resources.colorpalettes - if palettes then - -- - local palette = sharedpalettes[value] or palettes[tonumber(value) or 1] or palettes[1] or { } - local classes = #palette - if classes == 0 then - return - end - -- - local characters = tfmdata.characters - local descriptions = tfmdata.descriptions - local properties = tfmdata.properties - local colorvalues = { } - -- - properties.virtualized = true - tfmdata.fonts = { - { id = 0 } - } - -- - for i=1,classes do - local p = palette[i] - local r, g, b = p[1], p[2], p[3] - if r == g and g == b then - colorvalues[i] = { "special", f_gray(r/255) } - else - colorvalues[i] = { "special", f_color(r/255,g/255,b/255) } - end - end - -- - local getactualtext = otf.getactualtext - -- - for unicode, character in next, characters do - local description = descriptions[unicode] - if description then - local colorlist = description.colors - if colorlist then - local b, e = getactualtext(tounicode(characters[unicode].unicode or 0xFFFD)) - local w = character.width or 0 - local s = #colorlist - local t = { - -- We need to force page first because otherwise the q's get outside - -- the font switch and as a consequence the next character has no font - -- set (well, it has: the preceding one). As a consequence these fonts - -- are somewhat inefficient as each glyph gets the font set. It's a - -- side effect of the fact that a font is handled when a character gets - -- flushed. - { "special", "pdf:page:q" }, - { "special", "pdf:raw:" .. b } - } - local n = #t - for i=1,s do - local entry = colorlist[i] - n = n + 1 t[n] = colorvalues[entry.class] or s_black - n = n + 1 t[n] = { "char", entry.slot } - if s > 1 and i < s and w ~= 0 then - n = n + 1 t[n] = { "right", -w } - end - end - n = n + 1 t[n] = { "special", "pdf:page:" .. e } - n = n + 1 t[n] = { "special", "pdf:raw:Q" } - character.commands = t - end - end - end - end - end -end - -fonts.handlers.otf.features.register { - name = "colr", - description = "color glyphs", - manipulators = { - base = initializecolr, - node = initializecolr, - } -} - -local otfsvg = otf.svg or { } -otf.svg = otfsvg -otf.svgenabled = true - -do - - local nofstreams = 0 - - -- local f_setstream = formatters[ [[io.savedata("svg-glyph-%05i",%q)]] ] - -- local f_getstream = formatters[ [[svg-glyph-%05i]] ] - - -- function otfsvg.storepdfdata(pdf) - -- nofstreams = nofstreams + 1 - -- storepdfdata = function(pdf) - -- nofstreams = nofstreams + 1 - -- return f_setstream(nofstreams,pdf), f_getstream(nofstreams) - -- end - -- end - - local f_name = formatters[ [[svg-glyph-%05i]] ] - local f_used = context and formatters[ [[original:///%s]] ] or formatters[ [[%s]] ] - - local cache = { } - - function otfsvg.storepdfdata(pdf) - nofstreams = nofstreams + 1 - local o, n = epdf.openMemStream(pdf,#pdf,f_name(nofstreams)) - cache[n] = o -- we need to keep in mem - return nil, f_used(n), nil - end - - if context then - - local storepdfdata = otfsvg.storepdfdata - local initialized = false - - function otfsvg.storepdfdata(pdf) - if not initialized then - if resolvers.setmemstream then - local f_setstream = formatters[ [[resolvers.setmemstream("svg-glyph-%05i",%q,true)]] ] - local f_getstream = formatters[ [[memstream:///svg-glyph-%05i]] ] - local f_nilstream = formatters[ [[resolvers.resetmemstream("svg-glyph-%05i",true)]] ] - storepdfdata = function(pdf) - nofstreams = nofstreams + 1 - return - f_setstream(nofstreams,pdf), - f_getstream(nofstreams), - f_nilstream(nofstreams) - end - otfsvg.storepdfdata = storepdfdata - end - initialized = true - end - return storepdfdata(pdf) - end - - end - -end - - -do - - local report_svg = logs.reporter("fonts","svg conversion") - - local loaddata = io.loaddata - local savedata = io.savedata - local remove = os.remove - - if context and xml.convert then - - local xmlconvert = xml.convert - local xmlfirst = xml.first - - function otfsvg.filterglyph(entry,index) - local svg = xmlconvert(entry.data) - local root = svg and xmlfirst(svg,"/svg[@id='glyph"..index.."']") - local data = root and tostring(root) - -- report_svg("data for glyph %04X: %s",index,data) - return data - end - - else - - function otfsvg.filterglyph(entry,index) -- can be overloaded - return entry.data - end - - end - - -- function otfsvg.topdf(svgshapes) - -- local svgfile = "temp-otf-svg-shape.svg" - -- local pdffile = "temp-otf-svg-shape.pdf" - -- local command = "inkscape " .. svgfile .. " --export-pdf=" .. pdffile - -- local testrun = false - -- local pdfshapes = { } - -- local nofshapes = #svgshapes - -- local filterglyph = otfsvg.filterglyph - -- report_svg("processing %i svg containers",nofshapes) - -- statistics.starttiming() - -- for i=1,nofshapes do - -- local entry = svgshapes[i] - -- for index=entry.first,entry.last do - -- local data = filterglyph(entry,index) - -- savedata(svgfile,tostring(data)) - -- if data and data ~= "" then - -- report_svg("processing svg shape of glyph %i in container %i",index,i) - -- os.execute(command) - -- pdfshapes[index] = loaddata(pdffile) - -- end - -- end - -- if testrun and i > testrun then - -- report_svg("quiting test run") - -- break - -- end - -- end - -- remove(svgfile) - -- statistics.stoptiming() - -- report_svg("conversion time: %0.3f",statistics.elapsedtime()) - -- return pdfshapes - -- end - - function otfsvg.topdf(svgshapes) - local inkscape = io.popen("inkscape --shell > temp-otf-svg-shape.log","w") - local pdfshapes = { } - local nofshapes = #svgshapes - local f_svgfile = formatters["temp-otf-svg-shape-%i.svg"] - local f_pdffile = formatters["temp-otf-svg-shape-%i.pdf"] - local f_convert = formatters["%s --export-pdf=%s\n"] - local filterglyph = otfsvg.filterglyph - report_svg("processing %i svg containers",nofshapes) - statistics.starttiming() - for i=1,nofshapes do - local entry = svgshapes[i] - for index=entry.first,entry.last do - local data = filterglyph(entry,index) - if data and data ~= "" then - local svgfile = f_svgfile(index) - local pdffile = f_pdffile(index) - savedata(svgfile,data) - inkscape:write(f_convert(svgfile,pdffile)) - pdfshapes[index] = true - end - end - end - inkscape:write("quit\n") - -- while inkscape:read("*a") do - -- os.sleep(0.1) - -- end - inkscape:close() - report_svg("processing %i pdf results",nofshapes) - for index in next, pdfshapes do - local svgfile = f_svgfile(index) - local pdffile = f_pdffile(index) - pdfshapes[index] = loaddata(pdffile) - remove(svgfile) - remove(pdffile) - end - statistics.stoptiming() - if statistics.elapsedseconds then - report_svg("svg conversion time %s",statistics.elapsedseconds()) - end - return pdfshapes - end - -end - -local function initializesvg(tfmdata,kind,value) -- hm, always value - if value and otf.svgenabled then - local characters = tfmdata.characters - local descriptions = tfmdata.descriptions - local properties = tfmdata.properties - -- - local svg = properties.svg - local hash = svg and svg.hash - local timestamp = svg and svg.timestamp - if not hash then - return - end - -- - local pdffile = containers.read(otf.pdfcache,hash) - local pdfshapes = pdffile and pdffile.pdfshapes - if not pdfshapes or pdffile.timestamp ~= timestamp then - local svgfile = containers.read(otf.svgcache,hash) - local svgshapes = svgfile and svgfile.svgshapes - pdfshapes = svgshapes and otfsvg.topdf(svgshapes) or { } - containers.write(otf.pdfcache, hash, { - pdfshapes = pdfshapes, - timestamp = timestamp, - }) - end - if not pdfshapes or not next(pdfshapes) then - return - end - -- - properties.virtualized = true - tfmdata.fonts = { - { id = 0 } - } - -- - local getactualtext = otf.getactualtext - local storepdfdata = otfsvg.storepdfdata - -- - local nop = { "nop" } - -- - for unicode, character in next, characters do - local index = character.index - if index then - local pdf = pdfshapes[index] - if pdf then - local setcode, name, nilcode = storepdfdata(pdf) - if name then - local bt, et = getactualtext(unicode) - local wd = character.width or 0 - local ht = character.height or 0 - local dp = character.depth or 0 - character.commands = { - { "special", "pdf:direct:" .. bt }, - { "down", dp }, - setcode and { "lua", setcode } or nop, - { "image", { filename = name, width = wd, height = ht, depth = dp } }, - nilcode and { "lua", nilcode } or nop, - { "special", "pdf:direct:" .. et }, - } - character.svg = true - end - end - end - end - end -end - -fonts.handlers.otf.features.register { - name = "svg", - description = "svg glyphs", - manipulators = { - base = initializesvg, - node = initializesvg, - } -} diff --git a/tex/compat/luaotfload/fontloader-font-one.lua b/tex/compat/luaotfload/fontloader-font-one.lua deleted file mode 100644 index d9b9c65dff4da00fc36607328946322de90c88e0..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/fontloader-font-one.lua +++ /dev/null @@ -1,829 +0,0 @@ -if not modules then modules = { } end modules ['font-one'] = { - version = 1.001, - comment = "companion to font-ini.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - ---[[ldx-- -<p>Some code may look a bit obscure but this has to do with the fact that we also use -this code for testing and much code evolved in the transition from <l n='tfm'/> to -<l n='afm'/> to <l n='otf'/>.</p> - -<p>The following code still has traces of intermediate font support where we handles -font encodings. Eventually font encoding went away but we kept some code around in -other modules.</p> - -<p>This version implements a node mode approach so that users can also more easily -add features.</p> ---ldx]]-- - -local fonts, logs, trackers, containers, resolvers = fonts, logs, trackers, containers, resolvers - -local next, type, tonumber, rawget = next, type, tonumber, rawget -local match, gmatch, lower, gsub, strip, find = string.match, string.gmatch, string.lower, string.gsub, string.strip, string.find -local char, byte, sub = string.char, string.byte, string.sub -local abs = math.abs -local bxor, rshift = bit32.bxor, bit32.rshift -local P, S, R, Cmt, C, Ct, Cs, Carg = lpeg.P, lpeg.S, lpeg.R, lpeg.Cmt, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Carg -local lpegmatch, patterns = lpeg.match, lpeg.patterns - -local trace_features = false trackers.register("afm.features", function(v) trace_features = v end) -local trace_indexing = false trackers.register("afm.indexing", function(v) trace_indexing = v end) -local trace_loading = false trackers.register("afm.loading", function(v) trace_loading = v end) -local trace_defining = false trackers.register("fonts.defining", function(v) trace_defining = v end) - -local report_afm = logs.reporter("fonts","afm loading") - -local setmetatableindex = table.setmetatableindex -local derivetable = table.derive - -local findbinfile = resolvers.findbinfile - -local definers = fonts.definers -local readers = fonts.readers -local constructors = fonts.constructors - -local afm = constructors.handlers.afm -local pfb = constructors.handlers.pfb -local otf = fonts.handlers.otf - -local otfreaders = otf.readers -local otfenhancers = otf.enhancers - -local afmfeatures = constructors.features.afm -local registerafmfeature = afmfeatures.register - -local afmenhancers = constructors.enhancers.afm -local registerafmenhancer = afmenhancers.register - -afm.version = 1.512 -- incrementing this number one up will force a re-cache -afm.cache = containers.define("fonts", "one", afm.version, true) -afm.autoprefixed = true -- this will become false some day (catches texnansi-blabla.*) - -afm.helpdata = { } -- set later on so no local for this -afm.syncspace = true -- when true, nicer stretch values - -local overloads = fonts.mappings.overloads - -local applyruntimefixes = fonts.treatments and fonts.treatments.applyfixes - ---[[ldx-- -<p>We cache files. Caching is taken care of in the loader. We cheat a bit by adding -ligatures and kern information to the afm derived data. That way we can set them faster -when defining a font.</p> - -<p>We still keep the loading two phased: first we load the data in a traditional -fashion and later we transform it to sequences. Then we apply some methods also -used in opentype fonts (like <t>tlig</t>).</p> ---ldx]]-- - -function afm.load(filename) - filename = resolvers.findfile(filename,'afm') or "" - if filename ~= "" and not fonts.names.ignoredfile(filename) then - local name = file.removesuffix(file.basename(filename)) - local data = containers.read(afm.cache,name) - local attr = lfs.attributes(filename) - local size, time = attr.size or 0, attr.modification or 0 - -- - local pfbfile = file.replacesuffix(name,"pfb") - local pfbname = resolvers.findfile(pfbfile,"pfb") or "" - if pfbname == "" then - pfbname = resolvers.findfile(file.basename(pfbfile),"pfb") or "" - end - local pfbsize, pfbtime = 0, 0 - if pfbname ~= "" then - local attr = lfs.attributes(pfbname) - pfbsize = attr.size or 0 - pfbtime = attr.modification or 0 - end - if not data or data.size ~= size or data.time ~= time or data.pfbsize ~= pfbsize or data.pfbtime ~= pfbtime then - report_afm("reading %a",filename) - data = afm.readers.loadfont(filename,pfbname) - if data then - afmenhancers.apply(data,filename) - -- otfreaders.addunicodetable(data) -- only when not done yet - fonts.mappings.addtounicode(data,filename) - -- otfreaders.extend(data) - otfreaders.pack(data) - data.size = size - data.time = time - data.pfbsize = pfbsize - data.pfbtime = pfbtime - report_afm("saving %a in cache",name) - -- data.resources.unicodes = nil -- consistent with otf but here we save not much - data = containers.write(afm.cache, name, data) - data = containers.read(afm.cache,name) - end - end - if data then - -- constructors.addcoreunicodes(unicodes) - otfreaders.unpack(data) - otfreaders.expand(data) -- inline tables - otfreaders.addunicodetable(data) -- only when not done yet - otfenhancers.apply(data,filename,data) - if applyruntimefixes then - applyruntimefixes(filename,data) - end - end - return data - end -end - --- we run a more advanced analyzer later on anyway - -local uparser = fonts.mappings.makenameparser() -- each time - -local function enhance_unify_names(data, filename) - local unicodevector = fonts.encodings.agl.unicodes -- loaded runtime in context - local unicodes = { } - local names = { } - local private = constructors.privateoffset - local descriptions = data.descriptions - for name, blob in next, data.characters do - local code = unicodevector[name] -- or characters.name_to_unicode[name] - if not code then - code = lpegmatch(uparser,name) - if type(code) ~= "number" then - code = private - private = private + 1 - report_afm("assigning private slot %U for unknown glyph name %a",code,name) - end - end - local index = blob.index - unicodes[name] = code - names[name] = index - blob.name = name - descriptions[code] = { - boundingbox = blob.boundingbox, - width = blob.width, - kerns = blob.kerns, - index = index, - name = name, - } - end - for unicode, description in next, descriptions do - local kerns = description.kerns - if kerns then - local krn = { } - for name, kern in next, kerns do - local unicode = unicodes[name] - if unicode then - krn[unicode] = kern - else - -- print(unicode,name) - end - end - description.kerns = krn - end - end - data.characters = nil - local resources = data.resources - local filename = resources.filename or file.removesuffix(file.basename(filename)) - resources.filename = resolvers.unresolve(filename) -- no shortcut - resources.unicodes = unicodes -- name to unicode - resources.marks = { } -- todo - -- resources.names = names -- name to index - resources.private = private -end - -local everywhere = { ["*"] = { ["*"] = true } } -- or: { ["*"] = { "*" } } -local noflags = { false, false, false, false } - -local function enhance_normalize_features(data) - local ligatures = setmetatableindex("table") - local kerns = setmetatableindex("table") - local extrakerns = setmetatableindex("table") - for u, c in next, data.descriptions do - local l = c.ligatures - local k = c.kerns - local e = c.extrakerns - if l then - ligatures[u] = l - for u, v in next, l do - l[u] = { ligature = v } - end - c.ligatures = nil - end - if k then - kerns[u] = k - for u, v in next, k do - k[u] = v -- { v, 0 } - end - c.kerns = nil - end - if e then - extrakerns[u] = e - for u, v in next, e do - e[u] = v -- { v, 0 } - end - c.extrakerns = nil - end - end - local features = { - gpos = { }, - gsub = { }, - } - local sequences = { - -- only filled ones - } - if next(ligatures) then - features.gsub.liga = everywhere - data.properties.hasligatures = true - sequences[#sequences+1] = { - features = { - liga = everywhere, - }, - flags = noflags, - name = "s_s_0", - nofsteps = 1, - order = { "liga" }, - type = "gsub_ligature", - steps = { - { - coverage = ligatures, - }, - }, - } - end - if next(kerns) then - features.gpos.kern = everywhere - data.properties.haskerns = true - sequences[#sequences+1] = { - features = { - kern = everywhere, - }, - flags = noflags, - name = "p_s_0", - nofsteps = 1, - order = { "kern" }, - type = "gpos_pair", - steps = { - { - format = "kern", - coverage = kerns, - }, - }, - } - end - if next(extrakerns) then - features.gpos.extrakerns = everywhere - data.properties.haskerns = true - sequences[#sequences+1] = { - features = { - extrakerns = everywhere, - }, - flags = noflags, - name = "p_s_1", - nofsteps = 1, - order = { "extrakerns" }, - type = "gpos_pair", - steps = { - { - format = "kern", - coverage = extrakerns, - }, - }, - } - end - -- todo: compress kerns - data.resources.features = features - data.resources.sequences = sequences -end - -local function enhance_fix_names(data) - for k, v in next, data.descriptions do - local n = v.name - local r = overloads[n] - if r then - local name = r.name - if trace_indexing then - report_afm("renaming characters %a to %a",n,name) - end - v.name = name - v.unicode = r.unicode - end - end -end - ---[[ldx-- -<p>These helpers extend the basic table with extra ligatures, texligatures -and extra kerns. This saves quite some lookups later.</p> ---ldx]]-- - -local addthem = function(rawdata,ligatures) - if ligatures then - local descriptions = rawdata.descriptions - local resources = rawdata.resources - local unicodes = resources.unicodes - -- local names = resources.names - for ligname, ligdata in next, ligatures do - local one = descriptions[unicodes[ligname]] - if one then - for _, pair in next, ligdata do - local two, three = unicodes[pair[1]], unicodes[pair[2]] - if two and three then - local ol = one.ligatures - if ol then - if not ol[two] then - ol[two] = three - end - else - one.ligatures = { [two] = three } - end - end - end - end - end - end -end - -local function enhance_add_ligatures(rawdata) - addthem(rawdata,afm.helpdata.ligatures) -end - ---[[ldx-- -<p>We keep the extra kerns in separate kerning tables so that we can use -them selectively.</p> ---ldx]]-- - --- This is rather old code (from the beginning when we had only tfm). If --- we unify the afm data (now we have names all over the place) then --- we can use shcodes but there will be many more looping then. But we --- could get rid of the tables in char-cmp then. Als, in the generic version --- we don't use the character database. (Ok, we can have a context specific --- variant). - -local function enhance_add_extra_kerns(rawdata) -- using shcodes is not robust here - local descriptions = rawdata.descriptions - local resources = rawdata.resources - local unicodes = resources.unicodes - local function do_it_left(what) - if what then - for unicode, description in next, descriptions do - local kerns = description.kerns - if kerns then - local extrakerns - for complex, simple in next, what do - complex = unicodes[complex] - simple = unicodes[simple] - if complex and simple then - local ks = kerns[simple] - if ks and not kerns[complex] then - if extrakerns then - extrakerns[complex] = ks - else - extrakerns = { [complex] = ks } - end - end - end - end - if extrakerns then - description.extrakerns = extrakerns - end - end - end - end - end - local function do_it_copy(what) - if what then - for complex, simple in next, what do - complex = unicodes[complex] - simple = unicodes[simple] - if complex and simple then - local complexdescription = descriptions[complex] - if complexdescription then -- optional - local simpledescription = descriptions[complex] - if simpledescription then - local extrakerns - local kerns = simpledescription.kerns - if kerns then - for unicode, kern in next, kerns do - if extrakerns then - extrakerns[unicode] = kern - else - extrakerns = { [unicode] = kern } - end - end - end - local extrakerns = simpledescription.extrakerns - if extrakerns then - for unicode, kern in next, extrakerns do - if extrakerns then - extrakerns[unicode] = kern - else - extrakerns = { [unicode] = kern } - end - end - end - if extrakerns then - complexdescription.extrakerns = extrakerns - end - end - end - end - end - end - end - -- add complex with values of simplified when present - do_it_left(afm.helpdata.leftkerned) - do_it_left(afm.helpdata.bothkerned) - -- copy kerns from simple char to complex char unless set - do_it_copy(afm.helpdata.bothkerned) - do_it_copy(afm.helpdata.rightkerned) -end - ---[[ldx-- -<p>The copying routine looks messy (and is indeed a bit messy).</p> ---ldx]]-- - -local function adddimensions(data) -- we need to normalize afm to otf i.e. indexed table instead of name - if data then - for unicode, description in next, data.descriptions do - local bb = description.boundingbox - if bb then - local ht, dp = bb[4], -bb[2] - if ht == 0 or ht < 0 then - -- no need to set it and no negative heights, nil == 0 - else - description.height = ht - end - if dp == 0 or dp < 0 then - -- no negative depths and no negative depths, nil == 0 - else - description.depth = dp - end - end - end - end -end - -local function copytotfm(data) - if data and data.descriptions then - local metadata = data.metadata - local resources = data.resources - local properties = derivetable(data.properties) - local descriptions = derivetable(data.descriptions) - local goodies = derivetable(data.goodies) - local characters = { } - local parameters = { } - local unicodes = resources.unicodes - -- - for unicode, description in next, data.descriptions do -- use parent table - characters[unicode] = { } - end - -- - local filename = constructors.checkedfilename(resources) - local fontname = metadata.fontname or metadata.fullname - local fullname = metadata.fullname or metadata.fontname - local endash = 0x0020 -- space - local emdash = 0x2014 - local spacer = "space" - local spaceunits = 500 - -- - local monospaced = metadata.monospaced - local charwidth = metadata.charwidth - local italicangle = metadata.italicangle - local charxheight = metadata.xheight and metadata.xheight > 0 and metadata.xheight - properties.monospaced = monospaced - parameters.italicangle = italicangle - parameters.charwidth = charwidth - parameters.charxheight = charxheight - -- same as otf - if properties.monospaced then - if descriptions[endash] then - spaceunits, spacer = descriptions[endash].width, "space" - end - if not spaceunits and descriptions[emdash] then - spaceunits, spacer = descriptions[emdash].width, "emdash" - end - if not spaceunits and charwidth then - spaceunits, spacer = charwidth, "charwidth" - end - else - if descriptions[endash] then - spaceunits, spacer = descriptions[endash].width, "space" - end - if not spaceunits and charwidth then - spaceunits, spacer = charwidth, "charwidth" - end - end - spaceunits = tonumber(spaceunits) - if spaceunits < 200 then - -- todo: warning - end - -- - parameters.slant = 0 - parameters.space = spaceunits - parameters.space_stretch = 500 - parameters.space_shrink = 333 - parameters.x_height = 400 - parameters.quad = 1000 - -- - if italicangle and italicangle ~= 0 then - parameters.italicangle = italicangle - parameters.italicfactor = math.cos(math.rad(90+italicangle)) - parameters.slant = - math.tan(italicangle*math.pi/180) - end - if monospaced then - parameters.space_stretch = 0 - parameters.space_shrink = 0 - elseif afm.syncspace then - parameters.space_stretch = spaceunits/2 - parameters.space_shrink = spaceunits/3 - end - parameters.extra_space = parameters.space_shrink - if charxheight then - parameters.x_height = charxheight - else - -- same as otf - local x = 0x0078 -- x - if x then - local x = descriptions[x] - if x then - parameters.x_height = x.height - end - end - -- - end - -- - if metadata.sup then - local dummy = { 0, 0, 0 } - parameters[ 1] = metadata.designsize or 0 - parameters[ 2] = metadata.checksum or 0 - parameters[ 3], - parameters[ 4], - parameters[ 5] = unpack(metadata.space or dummy) - parameters[ 6] = metadata.quad or 0 - parameters[ 7] = metadata.extraspace or 0 - parameters[ 8], - parameters[ 9], - parameters[10] = unpack(metadata.num or dummy) - parameters[11], - parameters[12] = unpack(metadata.denom or dummy) - parameters[13], - parameters[14], - parameters[15] = unpack(metadata.sup or dummy) - parameters[16], - parameters[17] = unpack(metadata.sub or dummy) - parameters[18] = metadata.supdrop or 0 - parameters[19] = metadata.subdrop or 0 - parameters[20], - parameters[21] = unpack(metadata.delim or dummy) - parameters[22] = metadata.axisheight or 0 - end - -- - parameters.designsize = (metadata.designsize or 10)*65536 - parameters.ascender = abs(metadata.ascender or 0) - parameters.descender = abs(metadata.descender or 0) - parameters.units = 1000 - -- - properties.spacer = spacer - properties.encodingbytes = 2 - properties.format = fonts.formats[filename] or "type1" - properties.filename = filename - properties.fontname = fontname - properties.fullname = fullname - properties.psname = fullname - properties.name = filename or fullname or fontname - -- - if next(characters) then - return { - characters = characters, - descriptions = descriptions, - parameters = parameters, - resources = resources, - properties = properties, - goodies = goodies, - } - end - end - return nil -end - ---[[ldx-- -<p>Originally we had features kind of hard coded for <l n='afm'/> files but since I -expect to support more font formats, I decided to treat this fontformat like any -other and handle features in a more configurable way.</p> ---ldx]]-- - -function afm.setfeatures(tfmdata,features) - local okay = constructors.initializefeatures("afm",tfmdata,features,trace_features,report_afm) - if okay then - return constructors.collectprocessors("afm",tfmdata,features,trace_features,report_afm) - else - return { } -- will become false - end -end - -local function addtables(data) - local resources = data.resources - local lookuptags = resources.lookuptags - local unicodes = resources.unicodes - if not lookuptags then - lookuptags = { } - resources.lookuptags = lookuptags - end - setmetatableindex(lookuptags,function(t,k) - local v = type(k) == "number" and ("lookup " .. k) or k - t[k] = v - return v - end) - if not unicodes then - unicodes = { } - resources.unicodes = unicodes - setmetatableindex(unicodes,function(t,k) - setmetatableindex(unicodes,nil) - for u, d in next, data.descriptions do - local n = d.name - if n then - t[n] = u - end - end - return rawget(t,k) - end) - end - constructors.addcoreunicodes(unicodes) -- do we really need this? -end - -local function afmtotfm(specification) - local afmname = specification.filename or specification.name - if specification.forced == "afm" or specification.format == "afm" then -- move this one up - if trace_loading then - report_afm("forcing afm format for %a",afmname) - end - else - local tfmname = findbinfile(afmname,"ofm") or "" - if tfmname ~= "" then - if trace_loading then - report_afm("fallback from afm to tfm for %a",afmname) - end - return -- just that - end - end - if afmname ~= "" then - -- weird, isn't this already done then? - local features = constructors.checkedfeatures("afm",specification.features.normal) - specification.features.normal = features - constructors.hashinstance(specification,true) -- also weird here - -- - specification = definers.resolve(specification) -- new, was forgotten - local cache_id = specification.hash - local tfmdata = containers.read(constructors.cache, cache_id) -- cache with features applied - if not tfmdata then - local rawdata = afm.load(afmname) - if rawdata and next(rawdata) then - addtables(rawdata) - adddimensions(rawdata) - tfmdata = copytotfm(rawdata) - if tfmdata and next(tfmdata) then - local shared = tfmdata.shared - if not shared then - shared = { } - tfmdata.shared = shared - end - shared.rawdata = rawdata - shared.dynamics = { } - tfmdata.changed = { } - shared.features = features - shared.processes = afm.setfeatures(tfmdata,features) - end - elseif trace_loading then - report_afm("no (valid) afm file found with name %a",afmname) - end - tfmdata = containers.write(constructors.cache,cache_id,tfmdata) - end - return tfmdata - end -end - ---[[ldx-- -<p>As soon as we could intercept the <l n='tfm'/> reader, I implemented an -<l n='afm'/> reader. Since traditional <l n='pdftex'/> could use <l n='opentype'/> -fonts with <l n='afm'/> companions, the following method also could handle -those cases, but now that we can handle <l n='opentype'/> directly we no longer -need this features.</p> ---ldx]]-- - -local function read_from_afm(specification) - local tfmdata = afmtotfm(specification) - if tfmdata then - tfmdata.properties.name = specification.name - tfmdata = constructors.scale(tfmdata, specification) - local allfeatures = tfmdata.shared.features or specification.features.normal - constructors.applymanipulators("afm",tfmdata,allfeatures,trace_features,report_afm) - fonts.loggers.register(tfmdata,'afm',specification) - end - return tfmdata -end - ---[[ldx-- -<p>We have the usual two modes and related features initializers and processors.</p> ---ldx]]-- - -registerafmfeature { - name = "mode", - description = "mode", - initializers = { - base = otf.modeinitializer, - node = otf.modeinitializer, - } -} - -registerafmfeature { - name = "features", - description = "features", - default = true, - initializers = { - node = otf.nodemodeinitializer, - base = otf.basemodeinitializer, - }, - processors = { - node = otf.featuresprocessor, - } -} - --- readers - -fonts.formats.afm = "type1" -fonts.formats.pfb = "type1" - -local function check_afm(specification,fullname) - local foundname = findbinfile(fullname, 'afm') or "" -- just to be sure - if foundname == "" then - foundname = fonts.names.getfilename(fullname,"afm") or "" - end - if foundname == "" and afm.autoprefixed then - local encoding, shortname = match(fullname,"^(.-)%-(.*)$") -- context: encoding-name.* - if encoding and shortname and fonts.encodings.known[encoding] then - shortname = findbinfile(shortname,'afm') or "" -- just to be sure - if shortname ~= "" then - foundname = shortname - if trace_defining then - report_afm("stripping encoding prefix from filename %a",afmname) - end - end - end - end - if foundname ~= "" then - specification.filename = foundname - specification.format = "afm" - return read_from_afm(specification) - end -end - -function readers.afm(specification,method) - local fullname = specification.filename or "" - local tfmdata = nil - if fullname == "" then - local forced = specification.forced or "" - if forced ~= "" then - tfmdata = check_afm(specification,specification.name .. "." .. forced) - end - if not tfmdata then - local check_tfm = readers.check_tfm - method = (check_tfm and (method or definers.method or "afm or tfm")) or "afm" - if method == "tfm" then - tfmdata = check_tfm(specification,specification.name) - elseif method == "afm" then - tfmdata = check_afm(specification,specification.name) - elseif method == "tfm or afm" then - tfmdata = check_tfm(specification,specification.name) or check_afm(specification,specification.name) - else -- method == "afm or tfm" or method == "" then - tfmdata = check_afm(specification,specification.name) or check_tfm(specification,specification.name) - end - end - else - tfmdata = check_afm(specification,fullname) - end - return tfmdata -end - -function readers.pfb(specification,method) -- only called when forced - local original = specification.specification - if trace_defining then - report_afm("using afm reader for %a",original) - end - specification.forced = "afm" - local function swap(name) - local value = specification[swap] - if value then - specification[swap] = gsub("%.pfb",".afm",1) - end - end - swap("filename") - swap("fullname") - swap("forcedname") - swap("specification") - return readers.afm(specification,method) -end - --- now we register them - -registerafmenhancer("unify names", enhance_unify_names) -registerafmenhancer("add ligatures", enhance_add_ligatures) -registerafmenhancer("add extra kerns", enhance_add_extra_kerns) -registerafmenhancer("normalize features", enhance_normalize_features) -registerafmenhancer("check extra features", otfenhancers.enhance) -registerafmenhancer("fix names", enhance_fix_names) diff --git a/tex/compat/luaotfload/fontloader-font-onr.lua b/tex/compat/luaotfload/fontloader-font-onr.lua deleted file mode 100644 index 6c33b24c64463bb8571bf1c99b7dc402aa7feb32..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/fontloader-font-onr.lua +++ /dev/null @@ -1,505 +0,0 @@ -if not modules then modules = { } end modules ['font-onr'] = { - version = 1.001, - comment = "companion to font-ini.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - ---[[ldx-- -<p>Some code may look a bit obscure but this has to do with the fact that we also use -this code for testing and much code evolved in the transition from <l n='tfm'/> to -<l n='afm'/> to <l n='otf'/>.</p> - -<p>The following code still has traces of intermediate font support where we handles -font encodings. Eventually font encoding went away but we kept some code around in -other modules.</p> - -<p>This version implements a node mode approach so that users can also more easily -add features.</p> ---ldx]]-- - -local fonts, logs, trackers, resolvers = fonts, logs, trackers, resolvers - -local next, type, tonumber, rawget, rawset = next, type, tonumber, rawget, rawset -local match, lower, gsub, strip, find = string.match, string.lower, string.gsub, string.strip, string.find -local char, byte, sub = string.char, string.byte, string.sub -local abs = math.abs -local bxor, rshift = bit32.bxor, bit32.rshift -local P, S, R, Cmt, C, Ct, Cs, Carg, Cf, Cg = lpeg.P, lpeg.S, lpeg.R, lpeg.Cmt, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Carg, lpeg.Cf, lpeg.Cg -local lpegmatch, patterns = lpeg.match, lpeg.patterns - -local trace_indexing = false trackers.register("afm.indexing", function(v) trace_indexing = v end) -local trace_loading = false trackers.register("afm.loading", function(v) trace_loading = v end) - -local report_afm = logs.reporter("fonts","afm loading") -local report_pfb = logs.reporter("fonts","pfb loading") - -local handlers = fonts.handlers -local afm = handlers.afm or { } -handlers.afm = afm -local readers = afm.readers or { } -afm.readers = readers - -afm.version = 1.512 -- incrementing this number one up will force a re-cache - ---[[ldx-- -<p>We start with the basic reader which we give a name similar to the built in <l n='tfm'/> -and <l n='otf'/> reader.</p> -<p>We use a new (unfinished) pfb loader but I see no differences between the old -and new vectors (we actually had one bad vector with the old loader).</p> ---ldx]]-- - -local get_indexes, get_shapes - -do - - local decrypt - - do - - local r, c1, c2, n = 0, 0, 0, 0 - - local function step(c) - local cipher = byte(c) - local plain = bxor(cipher,rshift(r,8)) - r = ((cipher + r) * c1 + c2) % 65536 - return char(plain) - end - - decrypt = function(binary,initial,seed) - r, c1, c2, n = initial, 52845, 22719, seed - binary = gsub(binary,".",step) - return sub(binary,n+1) - end - - -- local pattern = Cs((P(1) / step)^1) - -- - -- decrypt = function(binary,initial,seed) - -- r, c1, c2, n = initial, 52845, 22719, seed - -- binary = lpegmatch(pattern,binary) - -- return sub(binary,n+1) - -- end - - end - - local charstrings = P("/CharStrings") - local subroutines = P("/Subrs") - local encoding = P("/Encoding") - local dup = P("dup") - local put = P("put") - local array = P("array") - local name = P("/") * C((R("az")+R("AZ")+R("09")+S("-_."))^1) - local digits = R("09")^1 - local cardinal = digits / tonumber - local spaces = P(" ")^1 - local spacing = patterns.whitespace^0 - - local routines, vector, chars, n, m - - local initialize = function(str,position,size) - n = 0 - m = size -- % tonumber(size) - return position + 1 - end - - local setroutine = function(str,position,index,size) - local forward = position + tonumber(size) - local stream = sub(str,position+1,forward) - routines[index] = decrypt(stream,4330,4) - return forward - end - - local setvector = function(str,position,name,size) - local forward = position + tonumber(size) - if n >= m then - return #str - elseif forward < #str then - vector[n] = name - n = n + 1 -- we compensate for notdef at the cff loader end - return forward - else - return #str - end - end - - local setshapes = function(str,position,name,size) - local forward = position + tonumber(size) - local stream = sub(str,position+1,forward) - if n > m then - return #str - elseif forward < #str then - vector[n] = name - n = n + 1 - chars [n] = decrypt(stream,4330,4) - return forward - else - return #str - end - end - - local p_rd = spacing * (P("RD") + P("-|")) - local p_np = spacing * (P("NP") + P( "|")) - local p_nd = spacing * (P("ND") + P( "|")) - - local p_filterroutines = -- dup <i> <n> RD or -| <n encrypted bytes> NP or | - (1-subroutines)^0 * subroutines * spaces * Cmt(cardinal,initialize) - * (Cmt(cardinal * spaces * cardinal * p_rd, setroutine) * p_np + P(1))^1 - - local p_filtershapes = -- /foo <n> RD <n encrypted bytes> ND - (1-charstrings)^0 * charstrings * spaces * Cmt(cardinal,initialize) - * (Cmt(name * spaces * cardinal * p_rd, setshapes) * p_nd + P(1))^1 - - local p_filternames = Ct ( - (1-charstrings)^0 * charstrings * spaces * Cmt(cardinal,initialize) - * (Cmt(name * spaces * cardinal, setvector) + P(1))^1 - ) - - -- /Encoding 256 array - -- 0 1 255 {1 index exch /.notdef put} for - -- dup 0 /Foo put - - local p_filterencoding = - (1-encoding)^0 * encoding * spaces * digits * spaces * array * (1-dup)^0 - * Cf( - Ct("") * Cg(spacing * dup * spaces * cardinal * spaces * name * spaces * put)^1 - ,rawset) - - -- if one of first 4 not 0-9A-F then binary else hex - - local function loadpfbvector(filename,shapestoo) - -- for the moment limited to encoding only - - local data = io.loaddata(resolvers.findfile(filename)) - - if not data then - report_pfb("no data in %a",filename) - return - end - - if not (find(data,"!PS%-AdobeFont%-") or find(data,"%%!FontType1")) then - report_pfb("no font in %a",filename) - return - end - - local ascii, binary = match(data,"(.*)eexec%s+......(.*)") - - if not binary then - report_pfb("no binary data in %a",filename) - return - end - - binary = decrypt(binary,55665,4) - - local names = { } - local encoding = lpegmatch(p_filterencoding,ascii) - local glyphs = { } - - routines, vector, chars = { }, { }, { } - - if shapestoo then - lpegmatch(p_filterroutines,binary) - lpegmatch(p_filtershapes,binary) - local data = { - dictionaries = { - { - charstrings = chars, - charset = vector, - subroutines = routines, - } - }, - } - fonts.handlers.otf.readers.parsecharstrings(data,glyphs,true,true) - else - lpegmatch(p_filternames,binary) - end - - names = vector - - routines, vector, chars = nil, nil, nil - - return names, encoding, glyphs - - end - - local pfb = handlers.pfb or { } - handlers.pfb = pfb - pfb.loadvector = loadpfbvector - - get_indexes = function(data,pfbname) - local vector = loadpfbvector(pfbname) - if vector then - local characters = data.characters - if trace_loading then - report_afm("getting index data from %a",pfbname) - end - for index=1,#vector do - local name = vector[index] - local char = characters[name] - if char then - if trace_indexing then - report_afm("glyph %a has index %a",name,index) - end - char.index = index - end - end - end - end - - get_shapes = function(pfbname) - local vector, encoding, glyphs = loadpfbvector(pfbname,true) - return glyphs - end - -end - ---[[ldx-- -<p>We start with the basic reader which we give a name similar to the built in <l n='tfm'/> -and <l n='otf'/> reader. We only need data that is relevant for our use. We don't support -more complex arrangements like multiple master (obsolete), direction specific kerning, etc.</p> ---ldx]]-- - -local spacer = patterns.spacer -local whitespace = patterns.whitespace -local lineend = patterns.newline -local spacing = spacer^0 -local number = spacing * S("+-")^-1 * (R("09") + S("."))^1 / tonumber -local name = spacing * C((1 - whitespace)^1) -local words = spacing * ((1 - lineend)^1 / strip) -local rest = (1 - lineend)^0 -local fontdata = Carg(1) -local semicolon = spacing * P(";") -local plus = spacing * P("plus") * number -local minus = spacing * P("minus") * number - --- kern pairs - -local function addkernpair(data,one,two,value) - local chr = data.characters[one] - if chr then - local kerns = chr.kerns - if kerns then - kerns[two] = tonumber(value) - else - chr.kerns = { [two] = tonumber(value) } - end - end -end - -local p_kernpair = (fontdata * P("KPX") * name * name * number) / addkernpair - --- char metrics - -local chr = false -local ind = 0 - -local function start(data,version) - data.metadata.afmversion = version - ind = 0 - chr = { } -end - -local function stop() - ind = 0 - chr = false -end - -local function setindex(i) - if i < 0 then - ind = ind + 1 -- ? - else - ind = i - end - chr = { - index = ind - } -end - -local function setwidth(width) - chr.width = width -end - -local function setname(data,name) - data.characters[name] = chr -end - -local function setboundingbox(boundingbox) - chr.boundingbox = boundingbox -end - -local function setligature(plus,becomes) - local ligatures = chr.ligatures - if ligatures then - ligatures[plus] = becomes - else - chr.ligatures = { [plus] = becomes } - end -end - -local p_charmetric = ( ( - P("C") * number / setindex - + P("WX") * number / setwidth - + P("N") * fontdata * name / setname - + P("B") * Ct((number)^4) / setboundingbox - + P("L") * (name)^2 / setligature - ) * semicolon )^1 - -local p_charmetrics = P("StartCharMetrics") * number * (p_charmetric + (1-P("EndCharMetrics")))^0 * P("EndCharMetrics") -local p_kernpairs = P("StartKernPairs") * number * (p_kernpair + (1-P("EndKernPairs" )))^0 * P("EndKernPairs" ) - -local function set_1(data,key,a) data.metadata[lower(key)] = a end -local function set_2(data,key,a,b) data.metadata[lower(key)] = { a, b } end -local function set_3(data,key,a,b,c) data.metadata[lower(key)] = { a, b, c } end - --- Notice string --- EncodingScheme string --- MappingScheme integer --- EscChar integer --- CharacterSet string --- Characters integer --- IsBaseFont boolean --- VVector number number --- IsFixedV boolean - -local p_parameters = P(false) - + fontdata - * ((P("FontName") + P("FullName") + P("FamilyName"))/lower) - * words / function(data,key,value) - data.metadata[key] = value - end - + fontdata - * ((P("Weight") + P("Version"))/lower) - * name / function(data,key,value) - data.metadata[key] = value - end - + fontdata - * P("IsFixedPitch") - * name / function(data,pitch) - data.metadata.monospaced = toboolean(pitch,true) - end - + fontdata - * P("FontBBox") - * Ct(number^4) / function(data,boundingbox) - data.metadata.boundingbox = boundingbox - end - + fontdata - * ((P("CharWidth") + P("CapHeight") + P("XHeight") + P("Descender") + P("Ascender") + P("ItalicAngle"))/lower) - * number / function(data,key,value) - data.metadata[key] = value - end - + P("Comment") * spacing * ( P(false) - + (fontdata * C("DESIGNSIZE") * number * rest) / set_1 -- 1 - + (fontdata * C("TFM designsize") * number * rest) / set_1 - + (fontdata * C("DesignSize") * number * rest) / set_1 - + (fontdata * C("CODINGSCHEME") * words * rest) / set_1 -- - + (fontdata * C("CHECKSUM") * number * words * rest) / set_1 -- 2 - + (fontdata * C("SPACE") * number * plus * minus * rest) / set_3 -- 3 4 5 - + (fontdata * C("QUAD") * number * rest) / set_1 -- 6 - + (fontdata * C("EXTRASPACE") * number * rest) / set_1 -- 7 - + (fontdata * C("NUM") * number * number * number * rest) / set_3 -- 8 9 10 - + (fontdata * C("DENOM") * number * number * rest) / set_2 -- 11 12 - + (fontdata * C("SUP") * number * number * number * rest) / set_3 -- 13 14 15 - + (fontdata * C("SUB") * number * number * rest) / set_2 -- 16 17 - + (fontdata * C("SUPDROP") * number * rest) / set_1 -- 18 - + (fontdata * C("SUBDROP") * number * rest) / set_1 -- 19 - + (fontdata * C("DELIM") * number * number * rest) / set_2 -- 20 21 - + (fontdata * C("AXISHEIGHT") * number * rest) / set_1 -- 22 - ) - -local fullparser = ( P("StartFontMetrics") * fontdata * name / start ) - * ( p_charmetrics + p_kernpairs + p_parameters + (1-P("EndFontMetrics")) )^0 - * ( P("EndFontMetrics") / stop ) - -local fullparser = ( P("StartFontMetrics") * fontdata * name / start ) - * ( p_charmetrics + p_kernpairs + p_parameters + (1-P("EndFontMetrics")) )^0 - * ( P("EndFontMetrics") / stop ) - -local infoparser = ( P("StartFontMetrics") * fontdata * name / start ) - * ( p_parameters + (1-P("EndFontMetrics")) )^0 - * ( P("EndFontMetrics") / stop ) - --- infoparser = ( P("StartFontMetrics") * fontdata * name / start ) --- * ( p_parameters + (1-P("EndFontMetrics") - P("StartCharMetrics")) )^0 --- * ( (P("EndFontMetrics") + P("StartCharMetrics")) / stop ) - -local function read(filename,parser) - local afmblob = io.loaddata(filename) - if afmblob then - local data = { - resources = { - filename = resolvers.unresolve(filename), - version = afm.version, - creator = "context mkiv", - }, - properties = { - hasitalics = false, - }, - goodies = { - }, - metadata = { - filename = file.removesuffix(file.basename(filename)) - }, - characters = { - -- a temporary store - }, - descriptions = { - -- the final store - }, - } - if trace_loading then - report_afm("parsing afm file %a",filename) - end - lpegmatch(parser,afmblob,1,data) - return data - else - if trace_loading then - report_afm("no valid afm file %a",filename) - end - return nil - end -end - -function readers.loadfont(afmname,pfbname) - local data = read(resolvers.findfile(afmname),fullparser) - if data then - if not pfbname or pfbname == "" then - pfbname = file.replacesuffix(file.nameonly(afmname),"pfb") - pfbname = resolvers.findfile(pfbname) - end - if pfbname and pfbname ~= "" then - data.resources.filename = resolvers.unresolve(pfbname) - get_indexes(data,pfbname) - elseif trace_loading then - report_afm("no pfb file for %a",afmname) - -- data.resources.filename = "unset" -- better than loading the afm file - end - return data - end -end - --- for now, todo: n and check with otf (no afm needed here) - -function readers.loadshapes(filename) - local fullname = resolvers.findfile(filename) or "" - if fullname == "" then - return { - filename = "not found: " .. filename, - glyphs = { } - } - else - return { - filename = fullname, - format = "opentype", - glyphs = get_shapes(fullname) or { }, - units = 1000, - } - end -end - - -function readers.getinfo(filename) - local data = read(resolvers.findfile(filename),infoparser) - if data then - return data.metadata - end -end diff --git a/tex/compat/luaotfload/fontloader-font-osd.lua b/tex/compat/luaotfload/fontloader-font-osd.lua deleted file mode 100644 index b67cc9241138715bd2acc7927355859589f1858f..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/fontloader-font-osd.lua +++ /dev/null @@ -1,2413 +0,0 @@ -if not modules then modules = { } end modules ['font-osd'] = { -- script devanagari - version = 1.001, - comment = "companion to font-ini.mkiv", - author = "Kai Eigner, TAT Zetwerk / Hans Hagen, PRAGMA ADE", - copyright = "TAT Zetwerk / PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- I'll optimize this one with ischar (much faster) when I see a reason (read: I need a --- proper test case first). - --- This is a version of font-odv.lua adapted to the new font loader and more --- direct hashing. The initialization code has been adapted (more efficient). One day --- I'll speed this up ... char swapping and properties. - --- A few remarks: --- --- This code is a partial rewrite of the code that deals with devanagari. The data and logic --- is by Kai Eigner and based based on Microsoft's OpenType specifications for specific --- scripts, but with a few improvements. More information can be found at: --- --- deva: http://www.microsoft.com/typography/OpenType%20Dev/devanagari/introO.mspx --- dev2: http://www.microsoft.com/typography/OpenType%20Dev/devanagari/intro.mspx --- --- Rajeesh Nambiar provided patches for the malayalam variant. Thanks to feedback from --- the mailing list some aspects could be improved. --- --- As I touched nearly all code, reshuffled it, optimized a lot, etc. etc. (imagine how --- much can get messed up in over a week work) it could be that I introduced bugs. There --- is more to gain (esp in the functions applied to a range) but I'll do that when --- everything works as expected. Kai's original code is kept in font-odk.lua as a reference --- so blame me (HH) for bugs. --- --- Interesting is that Kai managed to write this on top of the existing otf handler. Only a --- few extensions were needed, like a few more analyzing states and dealing with changed --- head nodes in the core scanner as that only happens here. There's a lot going on here --- and it's only because I touched nearly all code that I got a bit of a picture of what --- happens. For in-depth knowledge one needs to consult Kai. --- --- The rewrite mostly deals with efficiency, both in terms of speed and code. We also made --- sure that it suits generic use as well as use in ConTeXt. I removed some buglets but can --- as well have messed up the logic by doing this. For this we keep the original around --- as that serves as reference. Due to the lots of reshuffling glyphs quite some leaks --- occur(red) but once I'm satisfied with the rewrite I'll weed them. I also integrated --- initialization etc into the regular mechanisms. --- --- In the meantime, we're down from 25.5-3.5=22 seconds to 17.7-3.5=14.2 seconds for a 100 --- page sample (mid 2012) with both variants so it's worth the effort. Some more speedup is --- to be expected. Due to the method chosen it will never be real fast. If I ever become a --- power user I'll have a go at some further speed up. I will rename some functions (and --- features) once we don't need to check the original code. We now use a special subset --- sequence for use inside the analyzer (after all we could can store this in the dataset --- and save redundant analysis). --- --- I might go for an array approach with respect to attributes (and reshuffling). Easier. --- --- Some data will move to char-def.lua (some day). --- --- By now we have yet another incremental improved version. In the end I might rewrite the --- code. - --- Hans Hagen, PRAGMA-ADE, Hasselt NL --- --- We could have c_nukta, c_halant, c_ra is we know that they are never used mixed within --- one script .. yes or no? --- --- Matras: according to Microsoft typography specifications "up to one of each type: --- pre-, above-, below- or post- base", but that does not seem to be right. It could --- become an option. - -local insert, imerge, copy = table.insert, table.imerge, table.copy -local next, type = next, type - -local report_devanagari = logs.reporter("otf","devanagari") - -fonts = fonts or { } -fonts.analyzers = fonts.analyzers or { } -fonts.analyzers.methods = fonts.analyzers.methods or { node = { otf = { } } } - -local otf = fonts.handlers.otf - -local handlers = otf.handlers -local methods = fonts.analyzers.methods - -local otffeatures = fonts.constructors.features.otf -local registerotffeature = otffeatures.register - -local nuts = nodes.nuts -local tonode = nuts.tonode -local tonut = nuts.tonut - -local getnext = nuts.getnext -local getprev = nuts.getprev -local getboth = nuts.getboth -local getid = nuts.getid -local getchar = nuts.getchar -local getfont = nuts.getfont -local getsubtype = nuts.getsubtype -local setlink = nuts.setlink -local setnext = nuts.setnext -local setprev = nuts.setprev -local setchar = nuts.setchar -local getprop = nuts.getprop -local setprop = nuts.setprop - -local ischar = nuts.is_char - -local insert_node_after = nuts.insert_after -local copy_node = nuts.copy -local remove_node = nuts.remove -local flush_list = nuts.flush_list -local flush_node = nuts.flush_node - -local copyinjection = nodes.injections.copy -- KE: is this necessary? HH: probably not as positioning comes later and we rawget/set - -local unsetvalue = attributes.unsetvalue - -local fontdata = fonts.hashes.identifiers - -local a_state = attributes.private('state') -local a_syllabe = attributes.private('syllabe') - -local dotted_circle = 0x25CC - -local states = fonts.analyzers.states -- not features - -local s_rphf = states.rphf -local s_half = states.half -local s_pref = states.pref -local s_blwf = states.blwf -local s_pstf = states.pstf - -local replace_all_nbsp = nil - -replace_all_nbsp = function(head) -- delayed definition - replace_all_nbsp = typesetters and typesetters.characters and typesetters.characters.replacenbspaces or function(head) - return head - end - return replace_all_nbsp(head) -end - -local xprocesscharacters = nil - -if context then - xprocesscharacters = function(head,font) - xprocesscharacters = nodes.handlers.characters - return xprocesscharacters(head,font) - end -else - xprocesscharacters = function(head,font) - xprocesscharacters = nodes.handlers.nodepass -- generic - return xprocesscharacters(head,font) - end -end - -local function processcharacters(head,font) - return tonut(xprocesscharacters(tonode(head))) -- can be more efficient in context, just direct call -end - --- local fontprocesses = fonts.hashes.processes --- --- function processcharacters(head,font) --- local processors = fontprocesses[font] --- for i=1,#processors do --- head = processors[i](head,font,0) --- end --- return head, true --- end - --- In due time there will be entries here for scripts like Bengali, Gujarati, --- Gurmukhi, Kannada, Malayalam, Oriya, Tamil, Telugu. Feel free to provide the --- code points. - --- We can assume that script are not mixed in the source but if that is the case --- we might need to have consonants etc per script and initialize a local table --- pointing to the right one. - --- new, to be checked: --- --- U+00978 : DEVANAGARI LETTER MARWARI DDA --- U+00980 : BENGALI ANJI --- U+00C00 : TELUGU SIGN COMBINING CANDRABINDU ABOVE --- U+00C34 : TELUGU LETTER LLLA --- U+00C81 : KANNADA SIGN CANDRABINDU --- U+00D01 : MALAYALAM SIGN CANDRABINDU --- U+00DE6 : SINHALA LITH DIGIT ZERO --- U+00DE7 : SINHALA LITH DIGIT ONE --- U+00DE8 : SINHALA LITH DIGIT TWO --- U+00DE9 : SINHALA LITH DIGIT THREE --- U+00DEA : SINHALA LITH DIGIT FOUR --- U+00DEB : SINHALA LITH DIGIT FIVE --- U+00DEC : SINHALA LITH DIGIT SIX --- U+00DED : SINHALA LITH DIGIT SEVEN --- U+00DEE : SINHALA LITH DIGIT EIGHT --- U+00DEF : SINHALA LITH DIGIT NINE - -local consonant = { - -- devanagari - [0x0915] = true, [0x0916] = true, [0x0917] = true, [0x0918] = true, - [0x0919] = true, [0x091A] = true, [0x091B] = true, [0x091C] = true, - [0x091D] = true, [0x091E] = true, [0x091F] = true, [0x0920] = true, - [0x0921] = true, [0x0922] = true, [0x0923] = true, [0x0924] = true, - [0x0925] = true, [0x0926] = true, [0x0927] = true, [0x0928] = true, - [0x0929] = true, [0x092A] = true, [0x092B] = true, [0x092C] = true, - [0x092D] = true, [0x092E] = true, [0x092F] = true, [0x0930] = true, - [0x0931] = true, [0x0932] = true, [0x0933] = true, [0x0934] = true, - [0x0935] = true, [0x0936] = true, [0x0937] = true, [0x0938] = true, - [0x0939] = true, [0x0958] = true, [0x0959] = true, [0x095A] = true, - [0x095B] = true, [0x095C] = true, [0x095D] = true, [0x095E] = true, - [0x095F] = true, [0x0979] = true, [0x097A] = true, - -- kannada - [0x0C95] = true, [0x0C96] = true, [0x0C97] = true, [0x0C98] = true, - [0x0C99] = true, [0x0C9A] = true, [0x0C9B] = true, [0x0C9C] = true, - [0x0C9D] = true, [0x0C9E] = true, [0x0C9F] = true, [0x0CA0] = true, - [0x0CA1] = true, [0x0CA2] = true, [0x0CA3] = true, [0x0CA4] = true, - [0x0CA5] = true, [0x0CA6] = true, [0x0CA7] = true, [0x0CA8] = true, - [0x0CA9] = true, [0x0CAA] = true, [0x0CAB] = true, [0x0CAC] = true, - [0x0CAD] = true, [0x0CAE] = true, [0x0CAF] = true, [0x0CB0] = true, - [0x0CB1] = true, [0x0CB2] = true, [0x0CB3] = true, [0x0CB4] = true, - [0x0CB5] = true, [0x0CB6] = true, [0x0CB7] = true, [0x0CB8] = true, - [0x0CB9] = true, - [0x0CDE] = true, -- obsolete - -- malayalam - [0x0D15] = true, [0x0D16] = true, [0x0D17] = true, [0x0D18] = true, - [0x0D19] = true, [0x0D1A] = true, [0x0D1B] = true, [0x0D1C] = true, - [0x0D1D] = true, [0x0D1E] = true, [0x0D1F] = true, [0x0D20] = true, - [0x0D21] = true, [0x0D22] = true, [0x0D23] = true, [0x0D24] = true, - [0x0D25] = true, [0x0D26] = true, [0x0D27] = true, [0x0D28] = true, - [0x0D29] = true, [0x0D2A] = true, [0x0D2B] = true, [0x0D2C] = true, - [0x0D2D] = true, [0x0D2E] = true, [0x0D2F] = true, [0x0D30] = true, - [0x0D31] = true, [0x0D32] = true, [0x0D33] = true, [0x0D34] = true, - [0x0D35] = true, [0x0D36] = true, [0x0D37] = true, [0x0D38] = true, - [0x0D39] = true, [0x0D3A] = true, -} - -local independent_vowel = { - -- devanagari - [0x0904] = true, [0x0905] = true, [0x0906] = true, [0x0907] = true, - [0x0908] = true, [0x0909] = true, [0x090A] = true, [0x090B] = true, - [0x090C] = true, [0x090D] = true, [0x090E] = true, [0x090F] = true, - [0x0910] = true, [0x0911] = true, [0x0912] = true, [0x0913] = true, - [0x0914] = true, [0x0960] = true, [0x0961] = true, [0x0972] = true, - [0x0973] = true, [0x0974] = true, [0x0975] = true, [0x0976] = true, - [0x0977] = true, - -- kannada - [0x0C85] = true, [0x0C86] = true, [0x0C87] = true, [0x0C88] = true, - [0x0C89] = true, [0x0C8A] = true, [0x0C8B] = true, [0x0C8C] = true, - [0x0C8D] = true, [0x0C8E] = true, [0x0C8F] = true, [0x0C90] = true, - [0x0C91] = true, [0x0C92] = true, [0x0C93] = true, [0x0C94] = true, - -- malayalam - [0x0D05] = true, [0x0D06] = true, [0x0D07] = true, [0x0D08] = true, - [0x0D09] = true, [0x0D0A] = true, [0x0D0B] = true, [0x0D0C] = true, - [0x0D0E] = true, [0x0D0F] = true, [0x0D10] = true, [0x0D12] = true, - [0x0D13] = true, [0x0D14] = true, -} - -local dependent_vowel = { -- matra - -- devanagari - [0x093A] = true, [0x093B] = true, [0x093E] = true, [0x093F] = true, - [0x0940] = true, [0x0941] = true, [0x0942] = true, [0x0943] = true, - [0x0944] = true, [0x0945] = true, [0x0946] = true, [0x0947] = true, - [0x0948] = true, [0x0949] = true, [0x094A] = true, [0x094B] = true, - [0x094C] = true, [0x094E] = true, [0x094F] = true, [0x0955] = true, - [0x0956] = true, [0x0957] = true, [0x0962] = true, [0x0963] = true, - -- kannada - [0x0CBE] = true, [0x0CBF] = true, [0x0CC0] = true, [0x0CC1] = true, - [0x0CC2] = true, [0x0CC3] = true, [0x0CC4] = true, [0x0CC5] = true, - [0x0CC6] = true, [0x0CC7] = true, [0x0CC8] = true, [0x0CC9] = true, - [0x0CCA] = true, [0x0CCB] = true, [0x0CCC] = true, - -- malayalam - [0x0D3E] = true, [0x0D3F] = true, [0x0D40] = true, [0x0D41] = true, - [0x0D42] = true, [0x0D43] = true, [0x0D44] = true, [0x0D46] = true, - [0x0D47] = true, [0x0D48] = true, [0x0D4A] = true, [0x0D4B] = true, - [0x0D4C] = true, [0x0D57] = true, -} - -local vowel_modifier = { - -- devanagari - [0x0900] = true, [0x0901] = true, [0x0902] = true, [0x0903] = true, - -- A8E0 - A8F1 are cantillation marks for the Samaveda and may not belong here. - [0xA8E0] = true, [0xA8E1] = true, [0xA8E2] = true, [0xA8E3] = true, - [0xA8E4] = true, [0xA8E5] = true, [0xA8E6] = true, [0xA8E7] = true, - [0xA8E8] = true, [0xA8E9] = true, [0xA8EA] = true, [0xA8EB] = true, - [0xA8EC] = true, [0xA8ED] = true, [0xA8EE] = true, [0xA8EF] = true, - [0xA8F0] = true, [0xA8F1] = true, - -- malayalam - [0x0D02] = true, [0x0D03] = true, -} - -local stress_tone_mark = { - [0x0951] = true, [0x0952] = true, [0x0953] = true, [0x0954] = true, - -- kannada - [0x0CCD] = true, - -- malayalam - [0x0D4D] = true, -} - -local nukta = { - -- devanagari - [0x093C] = true, - -- kannada: - [0x0CBC] = true, -} - -local halant = { - -- devanagari - [0x094D] = true, - -- kannada - [0x0CCD] = true, - -- malayalam - [0x0D4D] = true, -} - -local ra = { - -- devanagari - [0x0930] = true, - -- kannada - [0x0CB0] = true, - -- malayalam - [0x0D30] = true, -} - -local c_anudatta = 0x0952 -- used to be tables -local c_nbsp = 0x00A0 -- used to be tables -local c_zwnj = 0x200C -- used to be tables -local c_zwj = 0x200D -- used to be tables - -local zw_char = { -- could also be inlined - [0x200C] = true, - [0x200D] = true, -} - --- 0C82 anusvara --- 0C83 visarga --- 0CBD avagraha --- 0CD5 length mark --- 0CD6 ai length mark --- 0CE0 letter ll --- 0CE1 letter rr --- 0CE2 vowel sign l --- 0CE2 vowel sign ll --- 0CF1 sign --- 0CF2 sign --- OCE6 - OCEF digits - -local pre_mark = { - [0x093F] = true, [0x094E] = true, - -- malayalam - [0x0D46] = true, [0x0D47] = true, [0x0D48] = true, -} - -local above_mark = { - [0x0900] = true, [0x0901] = true, [0x0902] = true, [0x093A] = true, - [0x0945] = true, [0x0946] = true, [0x0947] = true, [0x0948] = true, - [0x0951] = true, [0x0953] = true, [0x0954] = true, [0x0955] = true, - [0xA8E0] = true, [0xA8E1] = true, [0xA8E2] = true, [0xA8E3] = true, - [0xA8E4] = true, [0xA8E5] = true, [0xA8E6] = true, [0xA8E7] = true, - [0xA8E8] = true, [0xA8E9] = true, [0xA8EA] = true, [0xA8EB] = true, - [0xA8EC] = true, [0xA8ED] = true, [0xA8EE] = true, [0xA8EF] = true, - [0xA8F0] = true, [0xA8F1] = true, - -- malayalam - [0x0D4E] = true, -} - -local below_mark = { - [0x093C] = true, [0x0941] = true, [0x0942] = true, [0x0943] = true, - [0x0944] = true, [0x094D] = true, [0x0952] = true, [0x0956] = true, - [0x0957] = true, [0x0962] = true, [0x0963] = true, -} - -local post_mark = { - [0x0903] = true, [0x093B] = true, [0x093E] = true, [0x0940] = true, - [0x0949] = true, [0x094A] = true, [0x094B] = true, [0x094C] = true, - [0x094F] = true, -} - -local twopart_mark = { - -- malayalam - [0x0D4A] = { 0x0D46, 0x0D3E, }, -- ൊ - [0x0D4B] = { 0x0D47, 0x0D3E, }, -- ോ - [0x0D4C] = { 0x0D46, 0x0D57, }, -- ൌ -} - -local mark_four = { } -- As we access these frequently an extra hash is used. - -for k, v in next, pre_mark do mark_four[k] = pre_mark end -for k, v in next, above_mark do mark_four[k] = above_mark end -for k, v in next, below_mark do mark_four[k] = below_mark end -for k, v in next, post_mark do mark_four[k] = post_mark end - -local mark_above_below_post = { } - -for k, v in next, above_mark do mark_above_below_post[k] = above_mark end -for k, v in next, below_mark do mark_above_below_post[k] = below_mark end -for k, v in next, post_mark do mark_above_below_post[k] = post_mark end - --- Again, this table can be extended for other scripts than devanagari. Actually, --- for ConTeXt this kind of data is kept elsewhere so eventually we might move --- tables to someplace else. - -local reorder_class = { - -- devanagari - [0x0930] = "before postscript", - [0x093F] = "before half", - [0x0940] = "after subscript", - [0x0941] = "after subscript", - [0x0942] = "after subscript", - [0x0943] = "after subscript", - [0x0944] = "after subscript", - [0x0945] = "after subscript", - [0x0946] = "after subscript", - [0x0947] = "after subscript", - [0x0948] = "after subscript", - [0x0949] = "after subscript", - [0x094A] = "after subscript", - [0x094B] = "after subscript", - [0x094C] = "after subscript", - [0x0962] = "after subscript", - [0x0963] = "after subscript", - [0x093E] = "after subscript", - -- kannada: - [0x0CB0] = "after postscript", -- todo in code below - [0x0CBF] = "before subscript", -- todo in code below - [0x0CC6] = "before subscript", -- todo in code below - [0x0CCC] = "before subscript", -- todo in code below - [0x0CBE] = "before subscript", -- todo in code below - [0x0CE2] = "before subscript", -- todo in code below - [0x0CE3] = "before subscript", -- todo in code below - [0x0CC1] = "before subscript", -- todo in code below - [0x0CC2] = "before subscript", -- todo in code below - [0x0CC3] = "after subscript", - [0x0CC4] = "after subscript", - [0x0CD5] = "after subscript", - [0x0CD6] = "after subscript", - -- malayalam -} - --- We use some pseudo features as we need to manipulate the nodelist based --- on information in the font as well as already applied features. - -local dflt_true = { - dflt = true -} - -local dev2_defaults = { - dev2 = dflt_true, -} - -local deva_defaults = { - dev2 = dflt_true, - deva = dflt_true, -} - -local false_flags = { false, false, false, false } - -local both_joiners_true = { - [0x200C] = true, - [0x200D] = true, -} - -local sequence_reorder_matras = { - features = { dv01 = dev2_defaults }, - flags = false_flags, - name = "dv01_reorder_matras", - order = { "dv01" }, - type = "devanagari_reorder_matras", - nofsteps = 1, - steps = { - { - osdstep = true, - coverage = pre_mark, - } - } -} - -local sequence_reorder_reph = { - features = { dv02 = dev2_defaults }, - flags = false_flags, - name = "dv02_reorder_reph", - order = { "dv02" }, - type = "devanagari_reorder_reph", - nofsteps = 1, - steps = { - { - osdstep = true, - coverage = { }, - } - } -} - -local sequence_reorder_pre_base_reordering_consonants = { - features = { dv03 = dev2_defaults }, - flags = false_flags, - name = "dv03_reorder_pre_base_reordering_consonants", - order = { "dv03" }, - type = "devanagari_reorder_pre_base_reordering_consonants", - nofsteps = 1, - steps = { - { - osdstep = true, - coverage = { }, - } - } -} - -local sequence_remove_joiners = { - features = { dv04 = deva_defaults }, - flags = false_flags, - name = "dv04_remove_joiners", - order = { "dv04" }, - type = "devanagari_remove_joiners", - nofsteps = 1, - steps = { - { osdstep = true, - coverage = both_joiners_true, - }, - } -} - --- Looping over feature twice as efficient as looping over basic forms (some --- 350 checks instead of 750 for one font). This is something to keep an eye on --- as it might depends on the font. Not that it's a bottleneck. - -local basic_shaping_forms = { - nukt = true, - akhn = true, - rphf = true, - pref = true, - rkrf = true, - blwf = true, - half = true, - pstf = true, - vatu = true, - cjct = true, -} - -local valid = { - akhn = true, -- malayalam - rphf = true, - pref = true, - half = true, - blwf = true, - pstf = true, - pres = true, -- malayalam - blws = true, -- malayalam - psts = true, -- malayalam -} - -local function initializedevanagi(tfmdata) - local script, language = otf.scriptandlanguage(tfmdata,attr) -- todo: take fast variant - if script == "deva" or script == "dev2" or script =="mlym" or script == "mlm2" then - local resources = tfmdata.resources - local devanagari = resources.devanagari - if not devanagari then - -- - report_devanagari("adding devanagari features to font") - -- - local gsubfeatures = resources.features.gsub - local sequences = resources.sequences - local sharedfeatures = tfmdata.shared.features - -- - local lastmatch = 0 - for s=1,#sequences do -- classify chars - local features = sequences[s].features - if features then - for k, v in next, features do - if basic_shaping_forms[k] then - lastmatch = s - end - end - end - end - local insertindex = lastmatch + 1 - -- - gsubfeatures["dv01"] = dev2_defaults -- reorder matras - gsubfeatures["dv02"] = dev2_defaults -- reorder reph - gsubfeatures["dv03"] = dev2_defaults -- reorder pre base reordering consonants - gsubfeatures["dv04"] = deva_defaults -- remove joiners - -- - local reorder_pre_base_reordering_consonants = copy(sequence_reorder_pre_base_reordering_consonants) - local reorder_reph = copy(sequence_reorder_reph) - local reorder_matras = copy(sequence_reorder_matras) - local remove_joiners = copy(sequence_remove_joiners) - -- - insert(sequences,insertindex,reorder_pre_base_reordering_consonants) - insert(sequences,insertindex,reorder_reph) - insert(sequences,insertindex,reorder_matras) - insert(sequences,insertindex,remove_joiners) - -- - local blwfcache = { } - local seqsubset = { } - local rephstep = { - coverage = { } -- will be adapted each work - } - local devanagari = { - reph = false, - vattu = false, - blwfcache = blwfcache, - seqsubset = seqsubset, - reorderreph = rephstep, - - } - -- - reorder_reph.steps = { rephstep } - -- - local pre_base_reordering_consonants = { } - reorder_pre_base_reordering_consonants.steps[1].coverage = pre_base_reordering_consonants - -- - resources.devanagari = devanagari - -- - for s=1,#sequences do - local sequence = sequences[s] - local steps = sequence.steps - local nofsteps = sequence.nofsteps - local features = sequence.features - local has_rphf = features.rphf - local has_blwf = features.blwf - if has_rphf and has_rphf.deva then - devanagari.reph = true - elseif has_blwf and has_blwf.deva then - devanagari.vattu = true - for i=1,nofsteps do - local step = steps[i] - local coverage = step.coverage - if coverage then - for k, v in next, coverage do - if not blwfcache[k] then - blwfcache[k] = v - end - end - end - end - end - for kind, spec in next, features do -- beware, this is - if spec.dev2 and valid[kind] then - for i=1,nofsteps do - local step = steps[i] - local coverage = step.coverage - if coverage then - local reph = false - if kind == "rphf" then - -- - -- KE: I don't understand the rationale behind osdstep. The original if - -- statement checked whether coverage is contextual chaining. - -- - -- HH: The osdstep signals that we deal with our own feature here, not - -- one in the font itself so it was just a safeguard against us overloading - -- something driven by the font. - -- - -- if step.osdstep then -- selective - if true then -- always - -- rphf acts on consonant + halant - for k, v in next, ra do - local r = coverage[k] - if r then - local h = false - for k, v in next, halant do - local h = r[k] - if h then - reph = h.ligature or false - break - end - end - if reph then - break - end - end - end - else - -- rphf might be result of other handler/chainproc - end - end - seqsubset[#seqsubset+1] = { kind, coverage, reph } - end - end - end - if kind == "pref" then - local steps = sequence.steps - local nofsteps = sequence.nofsteps - for i=1,nofsteps do - local step = steps[i] - local coverage = step.coverage - if coverage then - for k, v in next, halant do - local h = coverage[k] - if h then - local found = false - for k, v in next, h do - found = v and v.ligature - if found then - pre_base_reordering_consonants[k] = found - break - end - end - if found then - break - end - end - end - end - end - end - end - end - -- - if script == "deva" then - sharedfeatures["dv04"] = true -- dv04_remove_joiners - elseif script == "dev2" then - sharedfeatures["dv01"] = true -- dv01_reorder_matras - sharedfeatures["dv02"] = true -- dv02_reorder_reph - sharedfeatures["dv03"] = true -- dv03_reorder_pre_base_reordering_consonants - sharedfeatures["dv04"] = true -- dv04_remove_joiners - elseif script == "mlym" then - sharedfeatures["pstf"] = true - elseif script == "mlm2" then - sharedfeatures["pstf"] = true - sharedfeatures["pref"] = true - sharedfeatures["dv03"] = true -- dv03_reorder_pre_base_reordering_consonants - gsubfeatures ["dv03"] = dev2_defaults -- reorder pre base reordering consonants - insert(sequences,insertindex,sequence_reorder_pre_base_reordering_consonants) - end - end - end -end - -registerotffeature { - name = "devanagari", - description = "inject additional features", - default = true, - initializers = { - node = initializedevanagi, - }, -} - --- hm, this is applied to one character: - -local function deva_initialize(font,attr) -- we need a proper hook into the dataset initializer - - local tfmdata = fontdata[font] - local datasets = otf.dataset(tfmdata,font,attr) -- don't we know this one? - local devanagaridata = datasets.devanagari - - if not devanagaridata then - - devanagaridata = { - reph = false, - vattu = false, - blwfcache = { }, - } - datasets.devanagari = devanagaridata - local resources = tfmdata.resources - local devanagari = resources.devanagari - - for s=1,#datasets do - local dataset = datasets[s] - if dataset and dataset[1] then -- value - local kind = dataset[4] - if kind == "rphf" then - -- deva - devanagaridata.reph = true - elseif kind == "blwf" then - -- deva - devanagaridata.vattu = true - -- dev2 - devanagaridata.blwfcache = devanagari.blwfcache - end - end - end - - end - - return devanagaridata.reph, devanagaridata.vattu, devanagaridata.blwfcache - -end - -local function deva_reorder(head,start,stop,font,attr,nbspaces) - - local reph, vattu, blwfcache = deva_initialize(font,attr) -- todo: a hash[font] - - local current = start - local n = getnext(start) - local base = nil - local firstcons = nil - local lastcons = nil - local basefound = false - - if reph and ra[getchar(start)] and halant[getchar(n)] then - -- if syllable starts with Ra + H and script has 'Reph' then exclude Reph - -- from candidates for base consonants - if n == stop then - return head, stop, nbspaces - end - if getchar(getnext(n)) == c_zwj then - current = start - else - current = getnext(n) - setprop(start,a_state,s_rphf) - end - end - - if getchar(current) == c_nbsp then - -- Stand Alone cluster - if current == stop then - stop = getprev(stop) - head = remove_node(head,current) - flush_node(current) - return head, stop, nbspaces - else - nbspaces = nbspaces + 1 - base = current - firstcons = current - lastcons = current - current = getnext(current) - if current ~= stop then - if nukta[getchar(current)] then - current = getnext(current) - end - if getchar(current) == c_zwj then - if current ~= stop then - local next = getnext(current) - if next ~= stop and halant[getchar(next)] then - current = next - next = getnext(current) - local tmp = next and getnext(next) or nil -- needs checking - local changestop = next == stop - local tempcurrent = copy_node(next) - copyinjection(tempcurrent,next) - local nextcurrent = copy_node(current) - copyinjection(nextcurrent,current) -- KE: necessary? HH: probably not as positioning comes later and we rawget/set - setlink(tempcurrent,nextcurrent) - setprop(tempcurrent,a_state,s_blwf) - tempcurrent = processcharacters(tempcurrent,font) - setprop(tempcurrent,a_state,unsetvalue) - if getchar(next) == getchar(tempcurrent) then - flush_list(tempcurrent) - local n = copy_node(current) - copyinjection(n,current) -- KE: necessary? HH: probably not as positioning comes later and we rawget/set - setchar(current,dotted_circle) - head = insert_node_after(head, current, n) - else - setchar(current,getchar(tempcurrent)) -- we assumes that the result of blwf consists of one node - local freenode = getnext(current) - setlink(current,tmp) - flush_node(freenode) - flush_list(tempcurrent) - if changestop then - stop = current - end - end - end - end - end - end - end - end - - while not basefound do - -- find base consonant - local char = getchar(current) - if consonant[char] then - setprop(current,a_state,s_half) - if not firstcons then - firstcons = current - end - lastcons = current - if not base then - base = current - elseif blwfcache[char] then - -- consonant has below-base (or post-base) form - setprop(current,a_state,s_blwf) - else - base = current - end - end - basefound = current == stop - current = getnext(current) - end - - if base ~= lastcons then - -- if base consonant is not last one then move halant from base consonant to last one - local np = base - local n = getnext(base) - local ch = getchar(n) - if nukta[ch] then - np = n - n = getnext(n) - ch = getchar(n) - end - if halant[ch] then - if lastcons ~= stop then - local ln = getnext(lastcons) - if nukta[getchar(ln)] then - lastcons = ln - end - end - -- local np = getprev(n) - local nn = getnext(n) - local ln = getnext(lastcons) -- what if lastcons is nn ? - setlink(np,nn) - setnext(lastcons,n) - if ln then - setprev(ln,n) - end - setnext(n,ln) - setprev(n,lastcons) - if lastcons == stop then - stop = n - end - end - end - - n = getnext(start) - if n ~= stop and ra[getchar(start)] and halant[getchar(n)] and not zw_char[getchar(getnext(n))] then - -- if syllable starts with Ra + H then move this combination so that it follows either: - -- the post-base 'matra' (if any) or the base consonant - local matra = base - if base ~= stop then - local next = getnext(base) - if dependent_vowel[getchar(next)] then - matra = next - end - end - -- [sp][start][n][nn] [matra|base][?] - -- [matra|base][start] [n][?] [sp][nn] - local sp = getprev(start) - local nn = getnext(n) - local mn = getnext(matra) - setlink(sp,nn) - setlink(matra,start) - setlink(n,mn) - if head == start then - head = nn - end - start = nn - if matra == stop then - stop = n - end - end - - local current = start - while current ~= stop do - local next = getnext(current) - if next ~= stop and halant[getchar(next)] and getchar(getnext(next)) == c_zwnj then - setprop(current,a_state,unsetvalue) - end - current = next - end - - if base ~= stop and getprop(base,a_state) then - local next = getnext(base) - if halant[getchar(next)] and not (next ~= stop and getchar(getnext(next)) == c_zwj) then - setprop(base,a_state,unsetvalue) - end - end - - -- ToDo: split two- or three-part matras into their parts. Then, move the left 'matra' part to the beginning of the syllable. - -- Not necessary for Devanagari. However it is necessay for other scripts, such as Tamil (e.g. TAMIL VOWEL SIGN O - 0BCA) - - -- classify consonants and 'matra' parts as pre-base, above-base (Reph), below-base or post-base, and group elements of the syllable (consonants and 'matras') according to this classification - - local current, allreordered, moved = start, false, { [base] = true } - local a, b, p, bn = base, base, base, getnext(base) - if base ~= stop and nukta[getchar(bn)] then - a, b, p = bn, bn, bn - end - while not allreordered do - -- current is always consonant - local c = current - local n = getnext(current) - local l = nil -- used ? - if c ~= stop then - local ch = getchar(n) - if nukta[ch] then - c = n - n = getnext(n) - ch = getchar(n) - end - if c ~= stop then - if halant[ch] then - c = n - n = getnext(n) - ch = getchar(n) - end - while c ~= stop and dependent_vowel[ch] do - c = n - n = getnext(n) - ch = getchar(n) - end - if c ~= stop then - if vowel_modifier[ch] then - c = n - n = getnext(n) - ch = getchar(n) - end - if c ~= stop and stress_tone_mark[ch] then - c = n - n = getnext(n) - end - end - end - end - local bp = getprev(firstcons) - local cn = getnext(current) - local last = getnext(c) - while cn ~= last do - -- move pre-base matras... - if pre_mark[getchar(cn)] then - if bp then - setnext(bp,cn) - end - local prev, next = getboth(cn) - if next then - setprev(next,prev) - end - setnext(prev,next) - if cn == stop then - stop = prev - end - setprev(cn,bp) - setlink(cn,firstcons) - if firstcons == start then - if head == start then - head = cn - end - start = cn - end - break - end - cn = getnext(cn) - end - allreordered = c == stop - current = getnext(c) - end - - if reph or vattu then - local current, cns = start, nil - while current ~= stop do - local c = current - local n = getnext(current) - if ra[getchar(current)] and halant[getchar(n)] then - c = n - n = getnext(n) - local b, bn = base, base - while bn ~= stop do - local next = getnext(bn) - if dependent_vowel[getchar(next)] then - b = next - end - bn = next - end - if getprop(current,a_state) == s_rphf then - -- position Reph (Ra + H) after post-base 'matra' (if any) since these - -- become marks on the 'matra', not on the base glyph - if b ~= current then - if current == start then - if head == start then - head = n - end - start = n - end - if b == stop then - stop = c - end - local prev = getprev(current) - setlink(prev,n) - local next = getnext(b) - setlink(c,next) - setlink(b,current) - end - elseif cns and getnext(cns) ~= current then -- todo: optimize next - -- position below-base Ra (vattu) following the consonants on which it is placed (either the base consonant or one of the pre-base consonants) - local cp = getprev(current) - local cnsn = getnext(cns) - setlink(cp,n) - setlink(cns,current) - setlink(c,cnsn) - if c == stop then - stop = cp - break - end - current = getprev(n) - end - else - local char = getchar(current) - if consonant[char] then - cns = current - local next = getnext(cns) - if halant[getchar(next)] then - cns = next - end - elseif char == c_nbsp then - nbspaces = nbspaces + 1 - cns = current - local next = getnext(cns) - if halant[getchar(next)] then - cns = next - end - end - end - current = getnext(current) - end - end - - if getchar(base) == c_nbsp then - nbspaces = nbspaces - 1 - head = remove_node(head,base) - flush_node(base) - end - - return head, stop, nbspaces -end - --- If a pre-base matra character had been reordered before applying basic features, --- the glyph can be moved closer to the main consonant based on whether half-forms had been formed. --- Actual position for the matra is defined as “after last standalone halant glyph, --- after initial matra position and before the main consonant”. --- If ZWJ or ZWNJ follow this halant, position is moved after it. - --- so we break out ... this is only done for the first 'word' (if we feed words we can as --- well test for non glyph. - -function handlers.devanagari_reorder_matras(head,start) -- no leak - local current = start -- we could cache attributes here - local startfont = getfont(start) - local startattr = getprop(start,a_syllabe) - while current do - local char = ischar(current,startfont) - local next = getnext(current) - if char and getprop(current,a_syllabe) == startattr then - if halant[char] and not getprop(current,a_state) then - if next then - local char = ischar(next,startfont) - if char and zw_char[char] and getprop(next,a_syllabe) == startattr then - current = next - next = getnext(current) - end - end - -- can be optimzied - local startnext = getnext(start) - head = remove_node(head,start) - setlink(start,next) - setlink(current,start) - start = startnext - break - end - else - break - end - current = next - end - return head, start, true -end - --- todo: way more caching of attributes and font - --- Reph’s original position is always at the beginning of the syllable, (i.e. it is not reordered at the character reordering stage). --- However, it will be reordered according to the basic-forms shaping results. --- Possible positions for reph, depending on the script, are; after main, before post-base consonant forms, --- and after post-base consonant forms. - --- 1 If reph should be positioned after post-base consonant forms, proceed to step 5. --- 2 If the reph repositioning class is not after post-base: target position is after the first explicit halant glyph between --- the first post-reph consonant and last main consonant. If ZWJ or ZWNJ are following this halant, position is moved after it. --- If such position is found, this is the target position. Otherwise, proceed to the next step. --- Note: in old-implementation fonts, where classifications were fixed in shaping engine, --- there was no case where reph position will be found on this step. --- 3 If reph should be repositioned after the main consonant: from the first consonant not ligated with main, --- or find the first consonant that is not a potential pre-base reordering Ra. --- 4 If reph should be positioned before post-base consonant, find first post-base classified consonant not ligated with main. --- If no consonant is found, the target position should be before the first matra, syllable modifier sign or vedic sign. --- 5 If no consonant is found in steps 3 or 4, move reph to a position immediately before the first post-base matra, --- syllable modifier sign or vedic sign that has a reordering class after the intended reph position. --- For example, if the reordering position for reph is post-main, it will skip above-base matras that also have a post-main position. --- 6 Otherwise, reorder reph to the end of the syllable. - --- hm, this only looks at the start of a nodelist ... is this supposed to be line based? - -function handlers.devanagari_reorder_reph(head,start) - -- since in Devanagari reph has reordering position 'before postscript' dev2 only follows step 2, 4, and 6, - -- the other steps are still ToDo (required for scripts other than dev2) - local current = getnext(start) - local startnext = nil - local startprev = nil - local startfont = getfont(start) - local startattr = getprop(start,a_syllabe) - while current do - local char = ischar(current,startfont) - if char and getprop(current,a_syllabe) == startattr then -- step 2 - if halant[char] and not getprop(current,a_state) then - local next = getnext(current) - if next then - local nextchar = ischar(next,startfont) - if nextchar and zw_char[nextchar] and getprop(next,a_syllabe) == startattr then - current = next - next = getnext(current) - end - end - startnext = getnext(start) - head = remove_node(head,start) - setlink(start,next) - setlink(current,start) - start = startnext - startattr = getprop(start,a_syllabe) - break - end - current = getnext(current) - else - break - end - end - if not startnext then - current = getnext(start) - while current do - local char = ischar(current,startfont) - if char and getprop(current,a_syllabe) == startattr then -- step 4 - if getprop(current,a_state) == s_pstf then -- post-base - startnext = getnext(start) - head = remove_node(head,start) - local prev = getprev(current) - setlink(prev,start) - setlink(start,current) - start = startnext - startattr = getprop(start,a_syllabe) - break - end - current = getnext(current) - else - break - end - end - end - -- todo: determine position for reph with reordering position other than 'before postscript' - -- (required for scripts other than dev2) - -- leaks - if not startnext then - current = getnext(start) - local c = nil - while current do - local char = ischar(current,startfont) - if char and getprop(current,a_syllabe) == startattr then -- step 5 - if not c and mark_above_below_post[char] and reorder_class[char] ~= "after subscript" then - c = current - end - current = getnext(current) - else - break - end - end - -- here we can loose the old start node: maybe best split cases - if c then - startnext = getnext(start) - head = remove_node(head,start) - local prev = getprev(c) - setlink(prev,start) - setlink(start,c) - -- end - start = startnext - startattr = getprop(start,a_syllabe) - end - end - -- leaks - if not startnext then - current = start - local next = getnext(current) - while next do - local nextchar = ischar(next,startfont) - if nextchar and getprop(next,a_syllabe) == startattr then --step 6 - current = next - next = getnext(current) - else - break - end - end - if start ~= current then - startnext = getnext(start) - head = remove_node(head,start) - local next = getnext(current) - setlink(start,next) - setlink(current,start) - start = startnext - end - end - -- - return head, start, true -end - --- we can cache some checking (v) - --- If a pre-base reordering consonant is found, reorder it according to the following rules: --- --- 1 Only reorder a glyph produced by substitution during application of the feature. --- (Note that a font may shape a Ra consonant with the feature generally but block it in certain contexts.) --- 2 Try to find a target position the same way as for pre-base matra. If it is found, reorder pre-base consonant glyph. --- 3 If position is not found, reorder immediately before main consonant. - --- UNTESTED: NOT CALLED IN EXAMPLE - -function handlers.devanagari_reorder_pre_base_reordering_consonants(head,start) - local current = start - local startnext = nil - local startprev = nil - local startfont = getfont(start) - local startattr = getprop(start,a_syllabe) - -- can be fast for loop + caching state - while current do - local char = ischar(current,startfont) - if char and getprop(current,a_syllabe) == startattr then - local next = getnext(current) - if halant[char] and not getprop(current,a_state) then - if next then - local nextchar = ischar(next,startfont) - if nextchar and getprop(next,a_syllabe) == startattr then - if nextchar == c_zwnj or nextchar == c_zwj then - current = next - next = getnext(current) - end - end - end - startnext = getnext(start) - removenode(start,start) - setlink(start,next) - setlink(current,start) - start = startnext - break - end - current = next - else - break - end - end - if not startnext then - current = getnext(start) - startattr = getprop(start,a_syllabe) - while current do - local char = ischar(current,startfont) - if char and getprop(current,a_syllabe) == startattr then - if not consonant[char] and getprop(current,a_state) then -- main - startnext = getnext(start) - removenode(start,start) - local prev = getprev(current) - setlink(prev,start) - setlink(start,current) - start = startnext - break - end - current = getnext(current) - else - break - end - end - end - return head, start, true -end - --- function handlers.devanagari_remove_joiners(head,start,kind,lookupname,replacement) --- local stop = getnext(start) --- local font = getfont(start) --- while stop do --- local char = ischar(stop) --- if char and (char == c_zwnj or char == c_zwj) then --- stop = getnext(stop) --- else --- break --- end --- end --- if stop then --- setnext(getprev(stop)) --- setprev(stop,getprev(start)) --- end --- local prev = getprev(start) --- if prev then --- setnext(prev,stop) --- end --- if head == start then --- head = stop --- end --- flush_list(start) --- return head, stop, true --- end - -function handlers.devanagari_remove_joiners(head,start,kind,lookupname,replacement) - local stop = getnext(start) - local font = getfont(start) - local last = start - while stop do - local char = ischar(stop,font) - if char and (char == c_zwnj or char == c_zwj) then - last = stop - stop = getnext(stop) - else - break - end - end - local prev = getprev(start) - if stop then - setnext(last) - setlink(prev,stop) - elseif prev then - setnext(prev) - end - if head == start then - head = stop - end - flush_list(start) - return head, stop, true -end - -local function dev2_initialize(font,attr) - - local devanagari = fontdata[font].resources.devanagari - - if devanagari then - return devanagari.seqsubset or { }, devanagari.reorderreph or { } - else - return { }, { } - end - -end - --- this one will be merged into the caller: it saves a call, but we will then make function --- of the actions - -local function dev2_reorder(head,start,stop,font,attr,nbspaces) -- maybe do a pass over (determine stop in sweep) - - local seqsubset, reorderreph = dev2_initialize(font,attr) - - local reph = false -- was nil ... probably went unnoticed because never assigned - local halfpos = nil - local basepos = nil - local subpos = nil - local postpos = nil - local locl = { } - - for i=1,#seqsubset do - - -- maybe quit if start == stop - - local subset = seqsubset[i] - local kind = subset[1] - local lookupcache = subset[2] - if kind == "rphf" then - reph = subset[3] - local current = start - local last = getnext(stop) - while current ~= last do - if current ~= stop then - local c = locl[current] or getchar(current) - local found = lookupcache[c] - if found then - local next = getnext(current) - local n = locl[next] or getchar(next) - if found[n] then --above-base: rphf Consonant + Halant - local afternext = next ~= stop and getnext(next) - if afternext and zw_char[getchar(afternext)] then -- ZWJ and ZWNJ prevent creation of reph - current = next - current = getnext(current) - elseif current == start then - setprop(current,a_state,s_rphf) - current = next - else - current = next - end - end - end - end - current = getnext(current) - end - elseif kind == "pref" then - local current = start - local last = getnext(stop) - while current ~= last do - if current ~= stop then - local c = locl[current] or getchar(current) - local found = lookupcache[c] - if found then -- pre-base: pref Halant + Consonant - local next = getnext(current) - local n = locl[next] or getchar(next) - if found[n] then - setprop(current,a_state,s_pref) - setprop(next,a_state,s_pref) - current = next - end - end - end - current = getnext(current) - end - elseif kind == "half" then -- half forms: half / Consonant + Halant - local current = start - local last = getnext(stop) - while current ~= last do - if current ~= stop then - local c = locl[current] or getchar(current) - local found = lookupcache[c] - if found then - local next = getnext(current) - local n = locl[next] or getchar(next) - if found[n] then - if next ~= stop and getchar(getnext(next)) == c_zwnj then -- zwnj prevent creation of half - current = next - else - setprop(current,a_state,s_half) - if not halfpos then - halfpos = current - end - end - current = getnext(current) - end - end - end - current = getnext(current) - end - elseif kind == "blwf" then -- below-base: blwf / Halant + Consonant - local current = start - local last = getnext(stop) - while current ~= last do - if current ~= stop then - local c = locl[current] or getchar(current) - local found = lookupcache[c] - if found then - local next = getnext(current) - local n = locl[next] or getchar(next) - if found[n] then - setprop(current,a_state,s_blwf) - setprop(next,a_state,s_blwf) - current = next - subpos = current - end - end - end - current = getnext(current) - end - elseif kind == "pstf" then -- post-base: pstf / Halant + Consonant - local current = start - local last = getnext(stop) - while current ~= last do - if current ~= stop then - local c = locl[current] or getchar(current) - local found = lookupcache[c] - if found then - local next = getnext(current) - local n = locl[next] or getchar(next) - if found[n] then - setprop(current,a_state,s_pstf) - setprop(next,a_state,s_pstf) - current = next - postpos = current - end - end - end - current = getnext(current) - end - end - end - - -- this one changes per word ... - - reorderreph.coverage = { [reph] = true } -- neat - - -- end of weird - - local current, base, firstcons = start, nil, nil - - if getprop(start,a_state) == s_rphf then - -- if syllable starts with Ra + H and script has 'Reph' then exclude Reph from candidates for base consonants - current = getnext(getnext(start)) - end - - if current ~= getnext(stop) and getchar(current) == c_nbsp then - -- Stand Alone cluster - if current == stop then - stop = getprev(stop) - head = remove_node(head,current) - flush_node(current) - return head, stop, nbspaces - else - nbspaces = nbspaces + 1 - base = current - current = getnext(current) - if current ~= stop then - local char = getchar(current) - if nukta[char] then - current = getnext(current) - char = getchar(current) - end - if char == c_zwj then - local next = getnext(current) - if current ~= stop and next ~= stop and halant[getchar(next)] then - current = next - next = getnext(current) - local tmp = getnext(next) - local changestop = next == stop - setnext(next,nil) - setprop(current,a_state,s_pref) - current = processcharacters(current,font) - setprop(current,a_state,s_blwf) - current = processcharacters(current,font) - setprop(current,a_state,s_pstf) - current = processcharacters(current,font) - setprop(current,a_state,unsetvalue) - if halant[getchar(current)] then - setnext(getnext(current),tmp) - local nc = copy_node(current) - copyinjection(nc,current) - setchar(current,dotted_circle) - head = insert_node_after(head,current,nc) - else - setnext(current,tmp) -- assumes that result of pref, blwf, or pstf consists of one node - if changestop then - stop = current - end - end - end - end - end - end - else -- not Stand Alone cluster - local last = getnext(stop) - while current ~= last do -- find base consonant - local next = getnext(current) - if consonant[getchar(current)] then - if not (current ~= stop and next ~= stop and halant[getchar(next)] and getchar(getnext(next)) == c_zwj) then - if not firstcons then - firstcons = current - end - -- check whether consonant has below-base or post-base form or is pre-base reordering Ra - local a = getprop(current,a_state) - if not (a == s_pref or a == s_blwf or a == s_pstf) then - base = current - end - end - end - current = next - end - if not base then - base = firstcons - end - end - - if not base then - if getprop(start,a_state) == s_rphf then - setprop(start,a_state,unsetvalue) - end - return head, stop, nbspaces - else - if getprop(base,a_state) then - setprop(base,a_state,unsetvalue) - end - basepos = base - end - if not halfpos then - halfpos = base - end - if not subpos then - subpos = base - end - if not postpos then - postpos = subpos or base - end - - -- Matra characters are classified and reordered by which consonant in a conjunct they have affinity for - - local moved = { } - local current = start - local last = getnext(stop) - while current ~= last do - local char, target, cn = locl[current] or getchar(current), nil, getnext(current) - -- not so efficient (needed for malayalam) - local tpm = twopart_mark[char] - if tpm then - local extra = copy_node(current) - copyinjection(extra,current) - char = tpm[1] - setchar(current,char) - setchar(extra,tpm[2]) - head = insert_node_after(head,current,extra) - end - -- - if not moved[current] and dependent_vowel[char] then - if pre_mark[char] then -- Before first half form in the syllable - moved[current] = true - -- can be helper to remove one node - local prev, next = getboth(current) - setlink(prev,next) - if current == stop then - stop = getprev(current) - end - if halfpos == start then - if head == start then - head = current - end - start = current - end - local prev = getprev(halfpos) - setlink(prev,current) - setlink(current,halfpos) - halfpos = current - elseif above_mark[char] then -- After main consonant - target = basepos - if subpos == basepos then - subpos = current - end - if postpos == basepos then - postpos = current - end - basepos = current - elseif below_mark[char] then -- After subjoined consonants - target = subpos - if postpos == subpos then - postpos = current - end - subpos = current - elseif post_mark[char] then -- After post-form consonant - target = postpos - postpos = current - end - if mark_above_below_post[char] then - local prev = getprev(current) - if prev ~= target then - local next = getnext(current) - setlink(prev,next) - if current == stop then - stop = prev - end - local next = getnext(target) - setlink(current,next) - setlink(target,current) - end - end - end - current = cn - end - - -- Reorder marks to canonical order: Adjacent nukta and halant or nukta and vedic sign are always repositioned if necessary, so that the nukta is first. - - local current, c = start, nil - while current ~= stop do - local char = getchar(current) - if halant[char] or stress_tone_mark[char] then - if not c then - c = current - end - else - c = nil - end - local next = getnext(current) - if c and nukta[getchar(next)] then - if head == c then - head = next - end - if stop == next then - stop = current - end - local prev = getprev(c) - setlink(prev,next) - local nextnext = getnext(next) - setnext(current,nextnext) - local nextnextnext = getnext(nextnext) - if nextnextnext then - setprev(nextnextnext,current) - end - setlink(nextnext,c) - end - if stop == current then break end - current = getnext(current) - end - - if getchar(base) == c_nbsp then - if base == stop then - stop = getprev(stop) - end - nbspaces = nbspaces - 1 - head = remove_node(head, base) - flush_node(base) - end - - return head, stop, nbspaces -end - --- cleaned up and optimized ... needs checking (local, check order, fixes, extra hash, etc) - -local separator = { } - -imerge(separator,consonant) -imerge(separator,independent_vowel) -imerge(separator,dependent_vowel) -imerge(separator,vowel_modifier) -imerge(separator,stress_tone_mark) - -for k, v in next, nukta do separator[k] = true end -for k, v in next, halant do separator[k] = true end - -local function analyze_next_chars_one(c,font,variant) -- skip one dependent vowel - -- why two variants ... the comment suggests that it's the same ruleset - local n = getnext(c) - if not n then - return c - end - if variant == 1 then - local v = ischar(n,font) - if v and nukta[v] then - n = getnext(n) - if n then - v = ischar(n,font) - end - end - if n and v then - local nn = getnext(n) - if nn then - local vv = ischar(nn,font) - if vv then - local nnn = getnext(nn) - if nnn then - local vvv = ischar(nnn,font) - if vvv then - if vv == c_zwj and consonant[vvv] then - c = nnn - elseif (vv == c_zwnj or vv == c_zwj) and halant[vvv] then - local nnnn = getnext(nnn) - if nnnn then - local vvvv = ischar(nnnn,font) - if vvvv and consonant[vvvv] then - c = nnnn - end - end - end - end - end - end - end - end - elseif variant == 2 then - local v = ischar(n,font) - if v and nukta[v] then - c = n - end - n = getnext(c) - if n then - v = ischar(n,font) - if v then - local nn = getnext(n) - if nn then - local vv = ischar(nn,font) - if vv and zw_char[v] then - n = nn - v = vv - nn = getnext(nn) - vv = nn and ischar(nn,font) - end - if vv and halant[v] and consonant[vv] then - c = nn - end - end - end - end - end - -- c = ms_matra(c) - local n = getnext(c) - if not n then - return c - end - local v = ischar(n,font) - if not v then - return c - end - if dependent_vowel[v] then - c = getnext(c) - n = getnext(c) - if not n then - return c - end - v = ischar(n,font) - if not v then - return c - end - end - if nukta[v] then - c = getnext(c) - n = getnext(c) - if not n then - return c - end - v = ischar(n,font) - if not v then - return c - end - end - if halant[v] then - c = getnext(c) - n = getnext(c) - if not n then - return c - end - v = ischar(n,font) - if not v then - return c - end - end - if vowel_modifier[v] then - c = getnext(c) - n = getnext(c) - if not n then - return c - end - v = ischar(n,font) - if not v then - return c - end - end - if stress_tone_mark[v] then - c = getnext(c) - n = getnext(c) - if not n then - return c - end - v = ischar(n,font) - if not v then - return c - end - end - if stress_tone_mark[v] then - return n - else - return c - end -end - -local function analyze_next_chars_two(c,font) - local n = getnext(c) - if not n then - return c - end - local v = ischar(n,font) - if v and nukta[v] then - c = n - end - n = c - while true do - local nn = getnext(n) - if nn then - local vv = ischar(nn,font) - if vv then - if halant[vv] then - n = nn - local nnn = getnext(nn) - if nnn then - local vvv = ischar(nnn,font) - if vvv and zw_char[vvv] then - n = nnn - end - end - elseif vv == c_zwnj or vv == c_zwj then - -- n = nn -- not here (?) - local nnn = getnext(nn) - if nnn then - local vvv = ischar(nnn,font) - if vvv and halant[vvv] then - n = nnn - end - end - else - break - end - local nn = getnext(n) - if nn then - local vv = ischar(nn,font) - if vv and consonant[vv] then - n = nn - local nnn = getnext(nn) - if nnn then - local vvv = ischar(nnn,font) - if vvv and nukta[vvv] then - n = nnn - end - end - c = n - else - break - end - else - break - end - else - break - end - else - break - end - end - -- - if not c then - -- This shouldn't happen I guess. - return - end - local n = getnext(c) - if not n then - return c - end - local v = ischar(n,font) - if not v then - return c - end - if v == c_anudatta then - c = n - n = getnext(c) - if not n then - return c - end - v = ischar(n,font) - if not v then - return c - end - end - if halant[v] then - c = n - n = getnext(c) - if not n then - return c - end - v = ischar(n,font) - if not v then - return c - end - if v == c_zwnj or v == c_zwj then - c = n - n = getnext(c) - if not n then - return c - end - v = ischar(n,font) - if not v then - return c - end - end - else - -- c = ms_matra(c) - -- same as one - if dependent_vowel[v] then - c = n - n = getnext(c) - if not n then - return c - end - v = ischar(n,font) - if not v then - return c - end - end - if nukta[v] then - c = n - n = getnext(c) - if not n then - return c - end - v = ischar(n,font) - if not v then - return c - end - end - if halant[v] then - c = n - n = getnext(c) - if not n then - return c - end - v = ischar(n,font) - if not v then - return c - end - end - end - -- same as one - if vowel_modifier[v] then - c = n - n = getnext(c) - if not n then - return c - end - v = ischar(n,font) - if not v then - return c - end - end - if stress_tone_mark[v] then - c = n - n = getnext(c) - if not n then - return c - end - v = ischar(n,font) - if not v then - return c - end - end - if stress_tone_mark[v] then - return n - else - return c - end -end - -local function inject_syntax_error(head,current,mark) - local signal = copy_node(current) - copyinjection(signal,current) - if mark == pre_mark then -- THIS IS WRONG: pre_mark is a table - setchar(signal,dotted_circle) - else - setchar(current,dotted_circle) - end - return insert_node_after(head,current,signal) -end - --- It looks like these two analyzers were written independently but they share --- a lot. Common code has been synced. - -function methods.deva(head,font,attr) - head = tonut(head) - local current = head - local start = true - local done = false - local nbspaces = 0 - while current do - local char = ischar(current,font) - if char then - done = true - local syllablestart = current - local syllableend = nil - local c = current - local n = getnext(c) - local first = char - if n and ra[first] then - local second = ischar(n,font) - if second and halant[second] then - local n = getnext(n) - if n then - local third = ischar(n,font) - if third then - c = n - first = third - end - end - end - end - local standalone = first == c_nbsp - if standalone then - local prev = getprev(current) - if prev then - local prevchar = ischar(prev,font) - if not prevchar then - -- different font or language so quite certainly a different word - elseif not separator[prevchar] then - -- something that separates words - else - standalone = false - end - else - -- begin of paragraph or box - end - end - if standalone then - -- stand alone cluster (at the start of the word only): #[Ra+H]+NBSP+[N]+[<[<ZWJ|ZWNJ>]+H+C>]+[{M}+[N]+[H]]+[SM]+[(VD)] - local syllableend = analyze_next_chars_one(c,font,2) - current = getnext(syllableend) - if syllablestart ~= syllableend then - head, current, nbspaces = deva_reorder(head,syllablestart,syllableend,font,attr,nbspaces) - current = getnext(current) - end - else - -- we can delay the getsubtype(n) and getfont(n) and test for say halant first - -- as an table access is faster than two function calls (subtype and font are - -- pseudo fields) but the code becomes messy (unless we make it a function) - if consonant[char] then - -- syllable containing consonant - local prevc = true - while prevc do - prevc = false - local n = getnext(current) - if not n then - break - end - local v = ischar(n,font) - if not v then - break - end - if nukta[v] then - n = getnext(n) - if not n then - break - end - v = ischar(n,font) - if not v then - break - end - end - if halant[v] then - n = getnext(n) - if not n then - break - end - v = ischar(n,font) - if not v then - break - end - if v == c_zwnj or v == c_zwj then - n = getnext(n) - if not n then - break - end - v = ischar(n,font) - if not v then - break - end - end - if consonant[v] then - prevc = true - current = n - end - end - end - local n = getnext(current) - if n then - local v = ischar(n,font) - if v and nukta[v] then - -- nukta (not specified in Microsft Devanagari OpenType specification) - current = n - n = getnext(current) - end - end - syllableend = current - current = n - if current then - local v = ischar(current,font) - if not v then - -- skip - elseif halant[v] then - -- syllable containing consonant without vowels: {C + [Nukta] + H} + C + H - local n = getnext(current) - if n then - local v = ischar(n,font) - if v and zw_char[v] then - -- code collapsed, probably needs checking with intention - syllableend = n - current = getnext(n) - else - syllableend = current - current = n - end - else - syllableend = current - current = n - end - else - -- syllable containing consonant with vowels: {C + [Nukta] + H} + C + [M] + [VM] + [SM] - if dependent_vowel[v] then - syllableend = current - current = getnext(current) - v = ischar(current,font) - end - if v and vowel_modifier[v] then - syllableend = current - current = getnext(current) - v = ischar(current,font) - end - if v and stress_tone_mark[v] then - syllableend = current - current = getnext(current) - end - end - end - if syllablestart ~= syllableend then - head, current, nbspaces = deva_reorder(head,syllablestart,syllableend,font,attr,nbspaces) - current = getnext(current) - end - elseif independent_vowel[char] then - -- syllable without consonants: VO + [VM] + [SM] - syllableend = current - current = getnext(current) - if current then - local v = ischar(current,font) - if v then - if vowel_modifier[v] then - syllableend = current - current = getnext(current) - v = ischar(current,font) - end - if v and stress_tone_mark[v] then - syllableend = current - current = getnext(current) - end - end - end - else - local mark = mark_four[char] - if mark then - head, current = inject_syntax_error(head,current,mark) - end - current = getnext(current) - end - end - else - current = getnext(current) - end - start = false - end - - if nbspaces > 0 then - head = replace_all_nbsp(head) - end - - head = tonode(head) - - return head, done -end - --- there is a good change that when we run into one with subtype < 256 that the rest is also done --- so maybe we can omit this check (it's pretty hard to get glyphs in the stream out of the blue) - -function methods.dev2(head,font,attr) - head = tonut(head) - local current = head - local start = true - local done = false - local syllabe = 0 - local nbspaces = 0 - while current do - local syllablestart = nil - local syllableend = nil - local char = ischar(current,font) - if char then - done = true - syllablestart = current - local c = current - local n = getnext(current) - if n and ra[char] then - local nextchar = ischar(n,font) - if nextchar and halant[nextchar] then - local n = getnext(n) - if n then - local nextnextchar = ischar(n,font) - if nextnextchar then - c = n - char = nextnextchar - end - end - end - end - if independent_vowel[char] then - -- vowel-based syllable: [Ra+H]+V+[N]+[<[<ZWJ|ZWNJ>]+H+C|ZWJ+C>]+[{M}+[N]+[H]]+[SM]+[(VD)] - current = analyze_next_chars_one(c,font,1) - syllableend = current - else - local standalone = char == c_nbsp - if standalone then - nbspaces = nbspaces + 1 - local p = getprev(current) - if not p then - -- begin of paragraph or box - elseif ischar(p,font) then - -- different font or language so quite certainly a different word - elseif not separator[getchar(p)] then - -- something that separates words - else - standalone = false - end - end - if standalone then - -- Stand Alone cluster (at the start of the word only): #[Ra+H]+NBSP+[N]+[<[<ZWJ|ZWNJ>]+H+C>]+[{M}+[N]+[H]]+[SM]+[(VD)] - current = analyze_next_chars_one(c,font,2) - syllableend = current - elseif consonant[getchar(current)] then - -- WHY current INSTEAD OF c ? - - -- Consonant syllable: {C+[N]+<H+[<ZWNJ|ZWJ>]|<ZWNJ|ZWJ>+H>} + C+[N]+[A] + [< H+[<ZWNJ|ZWJ>] | {M}+[N]+[H]>]+[SM]+[(VD)] - current = analyze_next_chars_two(current,font) -- not c ! - syllableend = current - end - end - end - if syllableend then - syllabe = syllabe + 1 - local c = syllablestart - local n = getnext(syllableend) - while c ~= n do - setprop(c,a_syllabe,syllabe) - c = getnext(c) - end - end - if syllableend and syllablestart ~= syllableend then - head, current, nbspaces = dev2_reorder(head,syllablestart,syllableend,font,attr,nbspaces) - end - if not syllableend then - local char = ischar(current,font) - if char and not getprop(current,a_state) then - local mark = mark_four[char] - if mark then - head, current = inject_syntax_error(head,current,mark) - end - end - end - start = false - current = getnext(current) - end - - if nbspaces > 0 then - head = replace_all_nbsp(head) - end - - head = tonode(head) - - return head, done -end - -methods.mlym = methods.deva -methods.mlm2 = methods.dev2 diff --git a/tex/compat/luaotfload/fontloader-font-ota.lua b/tex/compat/luaotfload/fontloader-font-ota.lua deleted file mode 100644 index b8944e0c0c9b647c8ffc424958bbbbfe3bfccd65..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/fontloader-font-ota.lua +++ /dev/null @@ -1,449 +0,0 @@ -if not modules then modules = { } end modules ['font-ota'] = { - version = 1.001, - comment = "companion to font-otf.lua (analysing)", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- context only - -local type = type - -if not trackers then trackers = { register = function() end } end - ------ trace_analyzing = false trackers.register("otf.analyzing", function(v) trace_analyzing = v end) - -local fonts, nodes, node = fonts, nodes, node - -local allocate = utilities.storage.allocate - -local otf = fonts.handlers.otf - -local analyzers = fonts.analyzers -local initializers = allocate() -local methods = allocate() - -analyzers.initializers = initializers -analyzers.methods = methods - -local a_state = attributes.private('state') - -local nuts = nodes.nuts -local tonut = nuts.tonut - -local getfield = nuts.getfield -local getnext = nuts.getnext -local getprev = nuts.getprev -local getprev = nuts.getprev -local getprop = nuts.getprop -local setprop = nuts.setprop -local getfont = nuts.getfont -local getsubtype = nuts.getsubtype -local getchar = nuts.getchar -local ischar = nuts.is_char - -local traverse_id = nuts.traverse_id -local end_of_math = nuts.end_of_math - -local nodecodes = nodes.nodecodes ------ glyph_code = nodecodes.glyph -local disc_code = nodecodes.disc -local math_code = nodecodes.math - -local fontdata = fonts.hashes.identifiers -local categories = characters and characters.categories or { } -- sorry, only in context -local chardata = characters and characters.data - -local otffeatures = fonts.constructors.features.otf -local registerotffeature = otffeatures.register - ---[[ldx-- -<p>Analyzers run per script and/or language and are needed in order to -process features right.</p> ---ldx]]-- - --- never use these numbers directly - -local s_init = 1 local s_rphf = 7 -local s_medi = 2 local s_half = 8 -local s_fina = 3 local s_pref = 9 -local s_isol = 4 local s_blwf = 10 -local s_mark = 5 local s_pstf = 11 -local s_rest = 6 - -local states = { - init = s_init, - medi = s_medi, - med2 = s_medi, - fina = s_fina, - fin2 = s_fina, - fin3 = s_fina, - isol = s_isol, - mark = s_mark, - rest = s_rest, - rphf = s_rphf, - half = s_half, - pref = s_pref, - blwf = s_blwf, - pstf = s_pstf, -} - -local features = { - init = s_init, - medi = s_medi, - med2 = s_medi, - fina = s_fina, - fin2 = s_fina, - fin3 = s_fina, - isol = s_isol, - -- mark = s_mark, - -- rest = s_rest, - rphf = s_rphf, - half = s_half, - pref = s_pref, - blwf = s_blwf, - pstf = s_pstf, -} - -analyzers.states = states -analyzers.features = features -analyzers.useunicodemarks = false - --- todo: analyzers per script/lang, cross font, so we need an font id hash -> script --- e.g. latin -> hyphenate, arab -> 1/2/3 analyze -- its own namespace - -function analyzers.setstate(head,font) - local useunicodemarks = analyzers.useunicodemarks - local tfmdata = fontdata[font] - local descriptions = tfmdata.descriptions - local first, last, current, n, done = nil, nil, head, 0, false -- maybe make n boolean - current = tonut(current) - while current do - local char, id = ischar(current,font) - if char and not getprop(current,a_state) then - done = true - local d = descriptions[char] - if d then - if d.class == "mark" then - done = true - setprop(current,a_state,s_mark) - elseif useunicodemarks and categories[char] == "mn" then - done = true - setprop(current,a_state,s_mark) - elseif n == 0 then - first, last, n = current, current, 1 - setprop(current,a_state,s_init) - else - last, n = current, n+1 - setprop(current,a_state,s_medi) - end - else -- finish - if first and first == last then - setprop(last,a_state,s_isol) - elseif last then - setprop(last,a_state,s_fina) - end - first, last, n = nil, nil, 0 - end - elseif char == false then - -- other font - if first and first == last then - setprop(last,a_state,s_isol) - elseif last then - setprop(last,a_state,s_fina) - end - first, last, n = nil, nil, 0 - if id == math_code then - current = end_of_math(current) - end - elseif id == disc_code then - -- always in the middle .. it doesn't make much sense to assign a property - -- here ... we might at some point decide to flag the components when present - -- but even then it's kind of bogus - setprop(current,a_state,s_medi) - last = current - else -- finish - if first and first == last then - setprop(last,a_state,s_isol) - elseif last then - setprop(last,a_state,s_fina) - end - first, last, n = nil, nil, 0 - if id == math_code then - current = end_of_math(current) - end - end - current = getnext(current) - end - if first and first == last then - setprop(last,a_state,s_isol) - elseif last then - setprop(last,a_state,s_fina) - end - return head, done -end - --- in the future we will use language/script attributes instead of the --- font related value, but then we also need dynamic features which is --- somewhat slower; and .. we need a chain of them - -local function analyzeinitializer(tfmdata,value) -- attr - local script, language = otf.scriptandlanguage(tfmdata) -- attr - local action = initializers[script] - if not action then - -- skip - elseif type(action) == "function" then - return action(tfmdata,value) - else - local action = action[language] - if action then - return action(tfmdata,value) - end - end -end - -local function analyzeprocessor(head,font,attr) - local tfmdata = fontdata[font] - local script, language = otf.scriptandlanguage(tfmdata,attr) - local action = methods[script] - if not action then - -- skip - elseif type(action) == "function" then - return action(head,font,attr) - else - action = action[language] - if action then - return action(head,font,attr) - end - end - return head, false -end - -registerotffeature { - name = "analyze", - description = "analysis of character classes", - default = true, - initializers = { - node = analyzeinitializer, - }, - processors = { - position = 1, - node = analyzeprocessor, - } -} - --- latin - -methods.latn = analyzers.setstate --------.dflt = analyzers.setstate % can be an option or just the default - -local arab_warned = { } - -local function warning(current,what) - local char = getchar(current) - if not arab_warned[char] then - log.report("analyze","arab: character %C has no %a class",char,what) - arab_warned[char] = true - end -end - -local mappers = { - l = s_init, -- left - d = s_medi, -- double - c = s_medi, -- joiner - r = s_fina, -- right - u = s_isol, -- nonjoiner -} - --- we can also use this trick for devanagari - -local classifiers = characters.classifiers - -if not classifiers then - - local f_arabic, l_arabic = characters.blockrange("arabic") - local f_syriac, l_syriac = characters.blockrange("syriac") - local f_mandiac, l_mandiac = characters.blockrange("mandiac") - local f_nko, l_nko = characters.blockrange("nko") - local f_ext_a, l_ext_a = characters.blockrange("arabicextendeda") - - classifiers = table.setmetatableindex(function(t,k) - if type(k) == "number" then - local c = chardata[k] - local v = false - if c then - local arabic = c.arabic - if arabic then - v = mappers[arabic] - if not v then - log.report("analyze","error in mapping arabic %C",k) - -- error - v = false - end - elseif (k >= f_arabic and k <= l_arabic) or - (k >= f_syriac and k <= l_syriac) or - (k >= f_mandiac and k <= l_mandiac) or - (k >= f_nko and k <= l_nko) or - (k >= f_ext_a and k <= l_ext_a) then - if categories[k] == "mn" then - v = s_mark - else - v = s_rest - end - end - end - t[k] = v - return v - end - end) - - characters.classifiers = classifiers - -end - -function methods.arab(head,font,attr) - local first, last = nil, nil - local c_first, c_last = nil, nil - local current, done = head, false - current = tonut(current) - while current do - local char, id = ischar(current,font) - if char and not getprop(current,a_state) then - done = true - local classifier = classifiers[char] - if not classifier then - if last then - if c_last == s_medi or c_last == s_fina then - setprop(last,a_state,s_fina) - else - warning(last,"fina") - setprop(last,a_state,s_error) - end - first, last = nil, nil - elseif first then - if c_first == s_medi or c_first == s_fina then - setprop(first,a_state,s_isol) - else - warning(first,"isol") - setprop(first,a_state,s_error) - end - first = nil - end - elseif classifier == s_mark then - setprop(current,a_state,s_mark) - elseif classifier == s_isol then - if last then - if c_last == s_medi or c_last == s_fina then - setprop(last,a_state,s_fina) - else - warning(last,"fina") - setprop(last,a_state,s_error) - end - first, last = nil, nil - elseif first then - if c_first == s_medi or c_first == s_fina then - setprop(first,a_state,s_isol) - else - warning(first,"isol") - setprop(first,a_state,s_error) - end - first = nil - end - setprop(current,a_state,s_isol) - elseif classifier == s_medi then - if first then - last = current - c_last = classifier - setprop(current,a_state,s_medi) - else - setprop(current,a_state,s_init) - first = current - c_first = classifier - end - elseif classifier == s_fina then - if last then - if getprop(last,a_state) ~= s_init then - setprop(last,a_state,s_medi) - end - setprop(current,a_state,s_fina) - first, last = nil, nil - elseif first then - -- if getprop(first,a_state) ~= s_init then - -- -- needs checking - -- setprop(first,a_state,s_medi) - -- end - setprop(current,a_state,s_fina) - first = nil - else - setprop(current,a_state,s_isol) - end - else -- classifier == s_rest - setprop(current,a_state,s_rest) - if last then - if c_last == s_medi or c_last == s_fina then - setprop(last,a_state,s_fina) - else - warning(last,"fina") - setprop(last,a_state,s_error) - end - first, last = nil, nil - elseif first then - if c_first == s_medi or c_first == s_fina then - setprop(first,a_state,s_isol) - else - warning(first,"isol") - setprop(first,a_state,s_error) - end - first = nil - end - end - else - if last then - if c_last == s_medi or c_last == s_fina then - setprop(last,a_state,s_fina) - else - warning(last,"fina") - setprop(last,a_state,s_error) - end - first, last = nil, nil - elseif first then - if c_first == s_medi or c_first == s_fina then - setprop(first,a_state,s_isol) - else - warning(first,"isol") - setprop(first,a_state,s_error) - end - first = nil - end - if id == math_code then -- a bit duplicate as we test for glyphs twice - current = end_of_math(current) - end - end - current = getnext(current) - end - if last then - if c_last == s_medi or c_last == s_fina then - setprop(last,a_state,s_fina) - else - warning(last,"fina") - setprop(last,a_state,s_error) - end - elseif first then - if c_first == s_medi or c_first == s_fina then - setprop(first,a_state,s_isol) - else - warning(first,"isol") - setprop(first,a_state,s_error) - end - end - return head, done -end - -methods.syrc = methods.arab -methods.mand = methods.arab -methods.nko = methods.arab - -directives.register("otf.analyze.useunicodemarks",function(v) - analyzers.useunicodemarks = v -end) diff --git a/tex/compat/luaotfload/fontloader-font-otc.lua b/tex/compat/luaotfload/fontloader-font-otc.lua deleted file mode 100644 index a55320903fba5773361fe6991a39139ce6bad852..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/fontloader-font-otc.lua +++ /dev/null @@ -1,952 +0,0 @@ -if not modules then modules = { } end modules ['font-otc'] = { - version = 1.001, - comment = "companion to font-otf.lua (context)", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -local format, insert, sortedkeys, tohash = string.format, table.insert, table.sortedkeys, table.tohash -local type, next = type, next -local lpegmatch = lpeg.match -local utfbyte, utflen = utf.byte, utf.len - --- we assume that the other otf stuff is loaded already - -local trace_loading = false trackers.register("otf.loading", function(v) trace_loading = v end) -local report_otf = logs.reporter("fonts","otf loading") - -local fonts = fonts -local otf = fonts.handlers.otf -local registerotffeature = otf.features.register -local setmetatableindex = table.setmetatableindex - -local normalized = { - substitution = "substitution", - single = "substitution", - ligature = "ligature", - alternate = "alternate", - multiple = "multiple", - kern = "kern", - pair = "pair", - chainsubstitution = "chainsubstitution", - chainposition = "chainposition", -} - -local types = { - substitution = "gsub_single", - ligature = "gsub_ligature", - alternate = "gsub_alternate", - multiple = "gsub_multiple", - kern = "gpos_pair", - pair = "gpos_pair", - chainsubstitution = "gsub_contextchain", - chainposition = "gpos_contextchain", -} - -local names = { - gsub_single = "gsub", - gsub_multiple = "gsub", - gsub_alternate = "gsub", - gsub_ligature = "gsub", - gsub_context = "gsub", - gsub_contextchain = "gsub", - gsub_reversecontextchain = "gsub", - gpos_single = "gpos", - gpos_pair = "gpos", - gpos_cursive = "gpos", - gpos_mark2base = "gpos", - gpos_mark2ligature = "gpos", - gpos_mark2mark = "gpos", - gpos_context = "gpos", - gpos_contextchain = "gpos", -} - -setmetatableindex(types, function(t,k) t[k] = k return k end) -- "key" - -local everywhere = { ["*"] = { ["*"] = true } } -- or: { ["*"] = { "*" } } -local noflags = { false, false, false, false } - --- beware: shared, maybe we should copy the sequence - -local function getrange(sequences,category) - local count = #sequences - local first = nil - local last = nil - for i=1,count do - local t = sequences[i].type - if t and names[t] == category then - if not first then - first = i - end - last = i - end - end - return first or 1, last or count -end - -local function validspecification(specification,name) - local dataset = specification.dataset - if dataset then - -- okay - elseif specification[1] then - dataset = specification - specification = { dataset = dataset } - else - dataset = { { data = specification.data } } - specification.data = nil - specification.dataset = dataset - end - local first = dataset[1] - if first then - first = first.data - end - if not first then - report_otf("invalid feature specification, no dataset") - return - end - if type(name) ~= "string" then - name = specification.name or first.name - end - if type(name) ~= "string" then - report_otf("invalid feature specification, no name") - return - end - local n = #dataset - if n > 0 then - for i=1,n do - setmetatableindex(dataset[i],specification) - end - return specification, name - end -end - -local function addfeature(data,feature,specifications) - - -- todo: add some validator / check code so that we're more tolerant to - -- user errors - - if not specifications then - report_otf("missing specification") - return - end - - local descriptions = data.descriptions - local resources = data.resources - local features = resources.features - local sequences = resources.sequences - - if not features or not sequences then - report_otf("missing specification") - return - end - - local alreadydone = resources.alreadydone - if not alreadydone then - alreadydone = { } - resources.alreadydone = alreadydone - end - if alreadydone[specifications] then - return - else - alreadydone[specifications] = true - end - - -- feature has to be unique but the name entry wins eventually - - local fontfeatures = resources.features or everywhere - local unicodes = resources.unicodes - local splitter = lpeg.splitter(" ",unicodes) - local done = 0 - local skip = 0 - local aglunicodes = false - - local specifications = validspecification(specifications,feature) - if not specifications then - -- report_otf("invalid specification") - return - end - - local function tounicode(code) - if not code then - return - end - if type(code) == "number" then - return code - end - local u = unicodes[code] - if u then - return u - end - if utflen(code) == 1 then - u = utfbyte(code) - if u then - return u - end - end - if not aglunicodes then - aglunicodes = fonts.encodings.agl.unicodes -- delayed - end - return aglunicodes[code] - end - - local coverup = otf.coverup - local coveractions = coverup.actions - local stepkey = coverup.stepkey - local register = coverup.register - - local function prepare_substitution(list,featuretype) - local coverage = { } - local cover = coveractions[featuretype] - for code, replacement in next, list do - local unicode = tounicode(code) - local description = descriptions[unicode] - if description then - if type(replacement) == "table" then - replacement = replacement[1] - end - replacement = tounicode(replacement) - if replacement and descriptions[replacement] then - cover(coverage,unicode,replacement) - done = done + 1 - else - skip = skip + 1 - end - else - skip = skip + 1 - end - end - return coverage - end - - local function prepare_alternate(list,featuretype) - local coverage = { } - local cover = coveractions[featuretype] - for code, replacement in next, list do - local unicode = tounicode(code) - local description = descriptions[unicode] - if not description then - skip = skip + 1 - elseif type(replacement) == "table" then - local r = { } - for i=1,#replacement do - local u = tounicode(replacement[i]) - r[i] = descriptions[u] and u or unicode - end - cover(coverage,unicode,r) - done = done + 1 - else - local u = tounicode(replacement) - if u then - cover(coverage,unicode,{ u }) - done = done + 1 - else - skip = skip + 1 - end - end - end - return coverage - end - - local function prepare_multiple(list,featuretype) - local coverage = { } - local cover = coveractions[featuretype] - for code, replacement in next, list do - local unicode = tounicode(code) - local description = descriptions[unicode] - if not description then - skip = skip + 1 - elseif type(replacement) == "table" then - local r, n = { }, 0 - for i=1,#replacement do - local u = tounicode(replacement[i]) - if descriptions[u] then - n = n + 1 - r[n] = u - end - end - if n > 0 then - cover(coverage,unicode,r) - done = done + 1 - else - skip = skip + 1 - end - else - local u = tounicode(replacement) - if u then - cover(coverage,unicode,{ u }) - done = done + 1 - else - skip = skip + 1 - end - end - end - return coverage - end - - local function prepare_ligature(list,featuretype) - local coverage = { } - local cover = coveractions[featuretype] - for code, ligature in next, list do - local unicode = tounicode(code) - local description = descriptions[unicode] - if description then - if type(ligature) == "string" then - ligature = { lpegmatch(splitter,ligature) } - end - local present = true - for i=1,#ligature do - local l = ligature[i] - local u = tounicode(l) - if descriptions[u] then - ligature[i] = u - else - present = false - break - end - end - if present then - cover(coverage,unicode,ligature) - done = done + 1 - else - skip = skip + 1 - end - else - skip = skip + 1 - end - end - return coverage - end - - local function prepare_kern(list,featuretype) - local coverage = { } - local cover = coveractions[featuretype] - for code, replacement in next, list do - local unicode = tounicode(code) - local description = descriptions[unicode] - if description and type(replacement) == "table" then - local r = { } - for k, v in next, replacement do - local u = tounicode(k) - if u then - r[u] = v - end - end - if next(r) then - cover(coverage,unicode,r) - done = done + 1 - else - skip = skip + 1 - end - else - skip = skip + 1 - end - end - return coverage - end - - local function prepare_pair(list,featuretype) - local coverage = { } - local cover = coveractions[featuretype] - if cover then - for code, replacement in next, list do - local unicode = tounicode(code) - local description = descriptions[unicode] - if description and type(replacement) == "table" then - local r = { } - for k, v in next, replacement do - local u = tounicode(k) - if u then - r[u] = v - end - end - if next(r) then - cover(coverage,unicode,r) - done = done + 1 - else - skip = skip + 1 - end - else - skip = skip + 1 - end - end - else - report_otf("unknown cover type %a",featuretype) - end - return coverage - end - - local function prepare_chain(list,featuretype,sublookups) - -- todo: coveractions - local rules = list.rules - local coverage = { } - if rules then - local rulehash = { } - local rulesize = 0 - local sequence = { } - local nofsequences = 0 - local lookuptype = types[featuretype] - for nofrules=1,#rules do - local rule = rules[nofrules] - local current = rule.current - local before = rule.before - local after = rule.after - local replacements = rule.replacements or false - local sequence = { } - local nofsequences = 0 - if before then - for n=1,#before do - nofsequences = nofsequences + 1 - sequence[nofsequences] = before[n] - end - end - local start = nofsequences + 1 - for n=1,#current do - nofsequences = nofsequences + 1 - sequence[nofsequences] = current[n] - end - local stop = nofsequences - if after then - for n=1,#after do - nofsequences = nofsequences + 1 - sequence[nofsequences] = after[n] - end - end - local lookups = rule.lookups or false - local subtype = nil - if lookups and sublookups then - for k, v in next, lookups do - local lookup = sublookups[v] - if lookup then - lookups[k] = lookup - if not subtype then - subtype = lookup.type - end - else - -- already expanded - end - end - end - if nofsequences > 0 then -- we merge coverage into one - -- we copy as we can have different fonts - local hashed = { } - for i=1,nofsequences do - local t = { } - local s = sequence[i] - for i=1,#s do - local u = tounicode(s[i]) - if u then - t[u] = true - end - end - hashed[i] = t - end - sequence = hashed - -- now we create the rule - rulesize = rulesize + 1 - rulehash[rulesize] = { - nofrules, -- 1 - lookuptype, -- 2 - sequence, -- 3 - start, -- 4 - stop, -- 5 - lookups, -- 6 (6/7 also signal of what to do) - replacements, -- 7 - subtype, -- 8 - } - for unic in next, sequence[start] do - local cu = coverage[unic] - if not cu then - coverage[unic] = rulehash -- can now be done cleaner i think - end - end - end - end - end - return coverage - end - - local dataset = specifications.dataset - - local function report(name,category,position,first,last,sequences) - report_otf("injecting name %a of category %a at position %i in [%i,%i] of [%i,%i]", - name,category,position,first,last,1,#sequences) - end - - local function inject(specification,sequences,sequence,first,last,category,name) - local position = specification.position or false - if not position then - position = specification.prepend - if position == true then - if trace_loading then - report(name,category,first,first,last,sequences) - end - insert(sequences,first,sequence) - return - end - end - if not position then - position = specification.append - if position == true then - if trace_loading then - report(name,category,last+1,first,last,sequences) - end - insert(sequences,last+1,sequence) - return - end - end - local kind = type(position) - if kind == "string" then - local index = false - for i=first,last do - local s = sequences[i] - local f = s.features - if f then - for k in next, f do - if k == position then - index = i - break - end - end - if index then - break - end - end - end - if index then - position = index - else - position = last + 1 - end - elseif kind == "number" then - if position < 0 then - position = last - position + 1 - end - if position > last then - position = last + 1 - elseif position < first then - position = first - end - else - position = last + 1 - end - if trace_loading then - report(name,category,position,first,last,sequences) - end - insert(sequences,position,sequence) - end - - for s=1,#dataset do - local specification = dataset[s] - local valid = specification.valid -- nowhere used - local feature = specification.name or feature - if not feature or feature == "" then - report_otf("no valid name given for extra feature") - elseif not valid or valid(data,specification,feature) then -- anum uses this - local initialize = specification.initialize - if initialize then - -- when false is returned we initialize only once - specification.initialize = initialize(specification,data) and initialize or nil - end - local askedfeatures = specification.features or everywhere - local askedsteps = specification.steps or specification.subtables or { specification.data } or { } - local featuretype = normalized[specification.type or "substitution"] or "substitution" - local featureflags = specification.flags or noflags - local featureorder = specification.order or { feature } - local featurechain = (featuretype == "chainsubstitution" or featuretype == "chainposition") and 1 or 0 - local nofsteps = 0 - local steps = { } - local sublookups = specification.lookups - local category = nil - if sublookups then - local s = { } - for i=1,#sublookups do - local specification = sublookups[i] - local askedsteps = specification.steps or specification.subtables or { specification.data } or { } - local featuretype = normalized[specification.type or "substitution"] or "substitution" - local featureflags = specification.flags or noflags - local nofsteps = 0 - local steps = { } - for i=1,#askedsteps do - local list = askedsteps[i] - local coverage = nil - local format = nil - if featuretype == "substitution" then - coverage = prepare_substitution(list,featuretype) - elseif featuretype == "ligature" then - coverage = prepare_ligature(list,featuretype) - elseif featuretype == "alternate" then - coverage = prepare_alternate(list,featuretype) - elseif featuretype == "multiple" then - coverage = prepare_multiple(list,featuretype) - elseif featuretype == "kern" then - format = "kern" - coverage = prepare_kern(list,featuretype) - elseif featuretype == "pair" then - format = "pair" - coverage = prepare_pair(list,featuretype) - end - if coverage and next(coverage) then - nofsteps = nofsteps + 1 - steps[nofsteps] = register(coverage,featuretype,format,feature,nofsteps,descriptions,resources) - end - end - s[i] = { - [stepkey] = steps, - nofsteps = nofsteps, - type = types[featuretype], - } - end - sublookups = s - end - for i=1,#askedsteps do - local list = askedsteps[i] - local coverage = nil - local format = nil - if featuretype == "substitution" then - category = "gsub" - coverage = prepare_substitution(list,featuretype) - elseif featuretype == "ligature" then - category = "gsub" - coverage = prepare_ligature(list,featuretype) - elseif featuretype == "alternate" then - category = "gsub" - coverage = prepare_alternate(list,featuretype) - elseif featuretype == "multiple" then - category = "gsub" - coverage = prepare_multiple(list,featuretype) - elseif featuretype == "kern" then - category = "gpos" - format = "kern" - coverage = prepare_kern(list,featuretype) - elseif featuretype == "pair" then - category = "gpos" - format = "pair" - coverage = prepare_pair(list,featuretype) - elseif featuretype == "chainsubstitution" then - category = "gsub" - coverage = prepare_chain(list,featuretype,sublookups) - elseif featuretype == "chainposition" then - category = "gpos" - coverage = prepare_chain(list,featuretype,sublookups) - else - report_otf("not registering feature %a, unknown category",feature) - return - end - if coverage and next(coverage) then - nofsteps = nofsteps + 1 - steps[nofsteps] = register(coverage,featuretype,format,feature,nofsteps,descriptions,resources) - end - end - if nofsteps > 0 then - -- script = { lang1, lang2, lang3 } or script = { lang1 = true, ... } - for k, v in next, askedfeatures do - if v[1] then - askedfeatures[k] = tohash(v) - end - end - if featureflags[1] then featureflags[1] = "mark" end - if featureflags[2] then featureflags[2] = "ligature" end - if featureflags[3] then featureflags[3] = "base" end - local steptype = types[featuretype] - local sequence = { - chain = featurechain, - features = { [feature] = askedfeatures }, - flags = featureflags, - name = feature, -- redundant - order = featureorder, - [stepkey] = steps, - nofsteps = nofsteps, - type = steptype, - } - -- position | prepend | append - local first, last = getrange(sequences,category) - inject(specification,sequences,sequence,first,last,category,feature) - -- register in metadata (merge as there can be a few) - local features = fontfeatures[category] - if not features then - features = { } - fontfeatures[category] = features - end - local k = features[feature] - if not k then - k = { } - features[feature] = k - end - -- - for script, languages in next, askedfeatures do - local kk = k[script] - if not kk then - kk = { } - k[script] = kk - end - for language, value in next, languages do - kk[language] = value - end - end - end - end - end - if trace_loading then - report_otf("registering feature %a, affected glyphs %a, skipped glyphs %a",feature,done,skip) - end -end - -otf.enhancers.addfeature = addfeature - -local extrafeatures = { } -local knownfeatures = { } - -function otf.addfeature(name,specification) - if type(name) == "table" then - specification = name - end - if type(specification) ~= "table" then - report_otf("invalid feature specification, no valid table") - return - end - specification, name = validspecification(specification,name) - if name and specification then - local slot = knownfeatures[name] - if slot then - -- we overload one .. should be option - else - slot = #extrafeatures + 1 - knownfeatures[name] = slot - end - specification.name = name -- to be sure - extrafeatures[slot] = specification - -- report_otf("adding feature %a @ %i",name,slot) - end -end - --- for feature, specification in next, extrafeatures do --- addfeature(data,feature,specification) --- end - -local function enhance(data,filename,raw) - for slot=1,#extrafeatures do - local specification = extrafeatures[slot] - addfeature(data,specification.name,specification) - end -end - -otf.enhancers.enhance = enhance - -otf.enhancers.register("check extra features",enhance) - --- tlig -- - -local tlig = { -- we need numbers for some fonts so ... - -- endash = "hyphen hyphen", - -- emdash = "hyphen hyphen hyphen", - [0x2013] = { 0x002D, 0x002D }, - [0x2014] = { 0x002D, 0x002D, 0x002D }, - -- quotedblleft = "quoteleft quoteleft", - -- quotedblright = "quoteright quoteright", - -- quotedblleft = "grave grave", - -- quotedblright = "quotesingle quotesingle", - -- quotedblbase = "comma comma", -} - -local tlig_specification = { - type = "ligature", - features = everywhere, - data = tlig, - order = { "tlig" }, - flags = noflags, - prepend = true, -} - -otf.addfeature("tlig",tlig_specification) - -registerotffeature { - -- this makes it a known feature (in tables) - name = 'tlig', - description = 'tex ligatures', -} - --- trep - -local trep = { - -- [0x0022] = 0x201D, - [0x0027] = 0x2019, - -- [0x0060] = 0x2018, -} - -local trep_specification = { - type = "substitution", - features = everywhere, - data = trep, - order = { "trep" }, - flags = noflags, - prepend = true, -} - -otf.addfeature("trep",trep_specification) - -registerotffeature { - -- this makes it a known feature (in tables) - name = 'trep', - description = 'tex replacements', -} - --- -- tcom (obsolete, was already not set for a while) - --- if characters.combined then --- --- local tcom = { } --- --- local function initialize() --- characters.initialize() --- for first, seconds in next, characters.combined do --- for second, combination in next, seconds do --- tcom[combination] = { first, second } --- end --- end --- -- return false --- end --- --- local tcom_specification = { --- type = "ligature", --- features = everywhere, --- data = tcom, --- order = { "tcom" }, --- flags = noflags, --- initialize = initialize, --- } --- --- otf.addfeature("tcom",tcom_specification) --- --- registerotffeature { --- name = 'tcom', --- description = 'tex combinations', --- } --- --- end - --- anum - -local anum_arabic = { - [0x0030] = 0x0660, - [0x0031] = 0x0661, - [0x0032] = 0x0662, - [0x0033] = 0x0663, - [0x0034] = 0x0664, - [0x0035] = 0x0665, - [0x0036] = 0x0666, - [0x0037] = 0x0667, - [0x0038] = 0x0668, - [0x0039] = 0x0669, -} - -local anum_persian = { - [0x0030] = 0x06F0, - [0x0031] = 0x06F1, - [0x0032] = 0x06F2, - [0x0033] = 0x06F3, - [0x0034] = 0x06F4, - [0x0035] = 0x06F5, - [0x0036] = 0x06F6, - [0x0037] = 0x06F7, - [0x0038] = 0x06F8, - [0x0039] = 0x06F9, -} - -local function valid(data) - local features = data.resources.features - if features then - for k, v in next, features do - for k, v in next, v do - if v.arab then - return true - end - end - end - end -end - -local anum_specification = { - { - type = "substitution", - features = { arab = { urd = true, dflt = true } }, - order = { "anum" }, - data = anum_arabic, - flags = noflags, -- { }, - valid = valid, - }, - { - type = "substitution", - features = { arab = { urd = true } }, - order = { "anum" }, - data = anum_persian, - flags = noflags, -- { }, - valid = valid, - }, -} - -otf.addfeature("anum",anum_specification) -- todo: only when there is already an arab script feature - -registerotffeature { - -- this makes it a known feature (in tables) - name = 'anum', - description = 'arabic digits', -} - --- maybe: - --- fonts.handlers.otf.addfeature("hangulfix",{ --- type = "substitution", --- features = { ["hang"] = { ["*"] = true } }, --- data = { --- [0x1160] = 0x119E, --- }, --- order = { "hangulfix" }, --- flags = { }, --- prepend = true, --- }) - --- fonts.handlers.otf.features.register { --- name = 'hangulfix', --- description = 'fixes for hangul', --- } - --- fonts.handlers.otf.addfeature { --- name = "stest", --- type = "substitution", --- data = { --- a = "X", --- b = "P", --- } --- } --- fonts.handlers.otf.addfeature { --- name = "atest", --- type = "alternate", --- data = { --- a = { "X", "Y" }, --- b = { "P", "Q" }, --- } --- } --- fonts.handlers.otf.addfeature { --- name = "mtest", --- type = "multiple", --- data = { --- a = { "X", "Y" }, --- b = { "P", "Q" }, --- } --- } --- fonts.handlers.otf.addfeature { --- name = "ltest", --- type = "ligature", --- data = { --- X = { "a", "b" }, --- Y = { "d", "a" }, --- } --- } --- fonts.handlers.otf.addfeature { --- name = "ktest", --- type = "kern", --- data = { --- a = { b = -500 }, --- } --- } diff --git a/tex/compat/luaotfload/fontloader-font-oti.lua b/tex/compat/luaotfload/fontloader-font-oti.lua deleted file mode 100644 index e10a261cd2baee0e6610c8aadec013320bb27d0e..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/fontloader-font-oti.lua +++ /dev/null @@ -1,162 +0,0 @@ -if not modules then modules = { } end modules ['font-oti'] = { - version = 1.001, - comment = "companion to font-ini.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -local lower = string.lower - -local fonts = fonts -local constructors = fonts.constructors - -local otf = constructors.handlers.otf -local otffeatures = constructors.features.otf -local registerotffeature = otffeatures.register - -local otftables = otf.tables or { } -otf.tables = otftables - -local allocate = utilities.storage.allocate - -registerotffeature { - name = "features", - description = "initialization of feature handler", - default = true, -} - --- these are later hooked into node and base initializaters - -local function setmode(tfmdata,value) - if value then - tfmdata.properties.mode = lower(value) - end -end - -otf.modeinitializer = setmode - -local function setlanguage(tfmdata,value) - if value then - local cleanvalue = lower(value) - local languages = otftables and otftables.languages - local properties = tfmdata.properties - if not languages then - properties.language = cleanvalue - elseif languages[value] then - properties.language = cleanvalue - else - properties.language = "dflt" - end - end -end - -local function setscript(tfmdata,value) - if value then - local cleanvalue = lower(value) - local scripts = otftables and otftables.scripts - local properties = tfmdata.properties - if not scripts then - properties.script = cleanvalue - elseif scripts[value] then - properties.script = cleanvalue - else - properties.script = "dflt" - end - end -end - -registerotffeature { - name = "mode", - description = "mode", - initializers = { - base = setmode, - node = setmode, - plug = setmode, - } -} - -registerotffeature { - name = "language", - description = "language", - initializers = { - base = setlanguage, - node = setlanguage, - plug = setlanguage, - } -} - -registerotffeature { - name = "script", - description = "script", - initializers = { - base = setscript, - node = setscript, - plug = setscript, - } -} - --- here (as also in generic - -otftables.featuretypes = allocate { - gpos_single = "position", - gpos_pair = "position", - gpos_cursive = "position", - gpos_mark2base = "position", - gpos_mark2ligature = "position", - gpos_mark2mark = "position", - gpos_context = "position", - gpos_contextchain = "position", - gsub_single = "substitution", - gsub_multiple = "substitution", - gsub_alternate = "substitution", - gsub_ligature = "substitution", - gsub_context = "substitution", - gsub_contextchain = "substitution", - gsub_reversecontextchain = "substitution", - gsub_reversesub = "substitution", -} - -function otffeatures.checkeddefaultscript(featuretype,autoscript,scripts) - if featuretype == "position" then - local default = scripts.dflt - if default then - if autoscript == "position" or autoscript == true then - return default - else - report_otf("script feature %s not applied, enable default positioning") - end - else - -- no positioning at all - end - elseif featuretype == "substitution" then - local default = scripts.dflt - if default then - if autoscript == "substitution" or autoscript == true then - return default - end - end - end -end - -function otffeatures.checkeddefaultlanguage(featuretype,autolanguage,languages) - if featuretype == "position" then - local default = languages.dflt - if default then - if autolanguage == "position" or autolanguage == true then - return default - else - report_otf("language feature %s not applied, enable default positioning") - end - else - -- no positioning at all - end - elseif featuretype == "substitution" then - local default = languages.dflt - if default then - if autolanguage == "substitution" or autolanguage == true then - return default - end - end - end -end diff --git a/tex/compat/luaotfload/fontloader-font-otj.lua b/tex/compat/luaotfload/fontloader-font-otj.lua deleted file mode 100644 index 68cf608ec942b0e75e7c7c159cb7d61863a46dc0..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/fontloader-font-otj.lua +++ /dev/null @@ -1,1594 +0,0 @@ -if not modules then modules = { } end modules ['font-otj'] = { - version = 1.001, - comment = "companion to font-lib.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files", -} - --- This property based variant is not faster but looks nicer than the attribute one. We --- need to use rawget (which is apbout 4 times slower than a direct access but we cannot --- get/set that one for our purpose! This version does a bit more with discretionaries --- (and Kai has tested it with his collection of weird fonts.) - --- There is some duplicate code here (especially in the the pre/post/replace branches) but --- we go for speed. We could store a list of glyph and mark nodes when registering but it's --- cleaner to have an identification pass here. Also, I need to keep tracing in mind so --- being too clever here is dangerous. - --- The subtype test is not needed as there will be no (new) properties set, given that we --- reset the properties. - --- As we have a rawget on properties we don't need one on injections. - --- The use_advance code is just a test and is meant for testing and manuals. There is no --- performance (or whatever) gain and using kerns is somewhat cleaner (at least for now). - --- Maybe: subtype fontkern when pure kerns. - -if not nodes.properties then return end - -local next, rawget = next, rawget -local fastcopy = table.fastcopy - -local registertracker = trackers.register - -local trace_injections = false registertracker("fonts.injections", function(v) trace_injections = v end) -local trace_marks = false registertracker("fonts.injections.marks", function(v) trace_marks = v end) -local trace_cursive = false registertracker("fonts.injections.cursive", function(v) trace_cursive = v end) -local trace_spaces = false registertracker("fonts.injections.spaces", function(v) trace_spaces = v end) - --- use_advance is just an experiment: it makes copying glyphs (instead of new_glyph) dangerous - -local use_advance = false directives.register("fonts.injections.advance", function(v) use_advance = v end) - -local report_injections = logs.reporter("fonts","injections") -local report_spaces = logs.reporter("fonts","spaces") - -local attributes, nodes, node = attributes, nodes, node - -fonts = fonts -local hashes = fonts.hashes -local fontdata = hashes.identifiers ------ parameters = fonts.hashes.parameters -- not in generic ------ resources = fonts.hashes.resources -- not in generic - -nodes.injections = nodes.injections or { } -local injections = nodes.injections - -local tracers = nodes.tracers -local setcolor = tracers and tracers.colors.set -local resetcolor = tracers and tracers.colors.reset - -local nodecodes = nodes.nodecodes -local glyph_code = nodecodes.glyph -local disc_code = nodecodes.disc -local kern_code = nodecodes.kern -local glue_code = nodecodes.glue - -local nuts = nodes.nuts -local nodepool = nuts.pool - -local newkern = nodepool.kern - -local tonode = nuts.tonode -local tonut = nuts.tonut - -local getfield = nuts.getfield -local setfield = nuts.setfield -local getnext = nuts.getnext -local getprev = nuts.getprev -local getid = nuts.getid -local getfont = nuts.getfont -local getsubtype = nuts.getsubtype -local getchar = nuts.getchar -local getboth = nuts.getboth - -local ischar = nuts.is_char - -local getdisc = nuts.getdisc -local setdisc = nuts.setdisc - -local traverse_id = nuts.traverse_id -local traverse_char = nuts.traverse_char -local insert_node_before = nuts.insert_before -local insert_node_after = nuts.insert_after - -local properties = nodes.properties.data - -function injections.installnewkern(nk) - newkern = nk or newkern -end - -local nofregisteredkerns = 0 -local nofregisteredpairs = 0 -local nofregisteredmarks = 0 -local nofregisteredcursives = 0 -local keepregisteredcounts = false - -function injections.keepcounts() - keepregisteredcounts = true -end - -function injections.resetcounts() - nofregisteredkerns = 0 - nofregisteredpairs = 0 - nofregisteredmarks = 0 - nofregisteredcursives = 0 - keepregisteredcounts = false -end - --- We need to make sure that a possible metatable will not kick in unexpectedly. - --- function injections.reset(n) --- local p = rawget(properties,n) --- if p and rawget(p,"injections") then --- p.injections = nil --- end --- end - --- function injections.copy(target,source) --- local sp = rawget(properties,source) --- if sp then --- local tp = rawget(properties,target) --- local si = rawget(sp,"injections") --- if si then --- si = fastcopy(si) --- if tp then --- tp.injections = si --- else --- propertydata[target] = { --- injections = si, --- } --- end --- else --- if tp then --- tp.injections = nil --- end --- end --- end --- end - -function injections.reset(n) - local p = rawget(properties,n) - if p then - p.injections = false -- { } - else - properties[n] = false -- { injections = { } } - end -end - -function injections.copy(target,source) - local sp = rawget(properties,source) - if sp then - local tp = rawget(properties,target) - -- local si = rawget(sp,"injections") - local si = sp.injections - if si then - si = fastcopy(si) - if tp then - tp.injections = si - else - propertydata[target] = { - injections = si, - } - end - elseif tp then - tp.injections = false -- { } - else - properties[target] = { injections = { } } - end - else - local tp = rawget(properties,target) - if tp then - tp.injections = false -- { } - else - properties[target] = false -- { injections = { } } - end - end -end - -function injections.setligaindex(n,index) - local p = rawget(properties,n) - if p then - -- local i = rawget(p,"injections") - local i = p.injections - if i then - i.ligaindex = index - else - p.injections = { - ligaindex = index - } - end - else - properties[n] = { - injections = { - ligaindex = index - } - } - end -end - -function injections.getligaindex(n,default) - local p = rawget(properties,n) - if p then - -- local i = rawget(p,"injections") - local i = p.injections - if i then - return i.ligaindex or default - end - end - return default -end - -function injections.setcursive(start,nxt,factor,rlmode,exit,entry,tfmstart,tfmnext) -- hm: nuts or nodes - local dx = factor*(exit[1]-entry[1]) - local dy = -factor*(exit[2]-entry[2]) - local ws = tfmstart.width - local wn = tfmnext.width - nofregisteredcursives = nofregisteredcursives + 1 - if rlmode < 0 then - dx = -(dx + wn) - else - dx = dx - ws - end - if dx == 0 then - -- get rid of funny -0 - dx = 0 - end - -- - local p = rawget(properties,start) - if p then - -- local i = rawget(p,"injections") - local i = p.injections - if i then - i.cursiveanchor = true - else - p.injections = { - cursiveanchor = true, - } - end - else - properties[start] = { - injections = { - cursiveanchor = true, - }, - } - end - local p = rawget(properties,nxt) - if p then - -- local i = rawget(p,"injections") - local i = p.injections - if i then - i.cursivex = dx - i.cursivey = dy - else - p.injections = { - cursivex = dx, - cursivey = dy, - } - end - else - properties[nxt] = { - injections = { - cursivex = dx, - cursivey = dy, - }, - } - end - return dx, dy, nofregisteredcursives -end - -function injections.setpair(current,factor,rlmode,r2lflag,spec,injection) -- r2lflag & tfmchr not used - local x = factor*spec[1] - local y = factor*spec[2] - local w = factor*spec[3] - local h = factor*spec[4] - if x ~= 0 or w ~= 0 or y ~= 0 or h ~= 0 then -- okay? - local yoffset = y - h - local leftkern = x -- both kerns are set in a pair kern compared - local rightkern = w - x -- to normal kerns where we set only leftkern - if leftkern ~= 0 or rightkern ~= 0 or yoffset ~= 0 then - nofregisteredpairs = nofregisteredpairs + 1 - if rlmode and rlmode < 0 then - leftkern, rightkern = rightkern, leftkern - end - if not injection then - injection = "injections" - end - local p = rawget(properties,current) - if p then - -- local i = p[injection] - local i = rawget(p,injection) - if i then - if leftkern ~= 0 then - i.leftkern = (i.leftkern or 0) + leftkern - end - if rightkern ~= 0 then - i.rightkern = (i.rightkern or 0) + rightkern - end - if yoffset ~= 0 then - i.yoffset = (i.yoffset or 0) + yoffset - end - elseif leftkern ~= 0 or rightkern ~= 0 then - p[injection] = { - leftkern = leftkern, - rightkern = rightkern, - yoffset = yoffset, - } - else - p[injection] = { - yoffset = yoffset, - } - end - elseif leftkern ~= 0 or rightkern ~= 0 then - properties[current] = { - [injection] = { - leftkern = leftkern, - rightkern = rightkern, - yoffset = yoffset, - }, - } - else - properties[current] = { - [injection] = { - yoffset = yoffset, - }, - } - end - return x, y, w, h, nofregisteredpairs - end - end - return x, y, w, h -- no bound -end - --- This needs checking for rl < 0 but it is unlikely that a r2l script uses kernclasses between --- glyphs so we're probably safe (KE has a problematic font where marks interfere with rl < 0 in --- the previous case) - -function injections.setkern(current,factor,rlmode,x,injection) - local dx = factor * x - if dx ~= 0 then - nofregisteredkerns = nofregisteredkerns + 1 - local p = rawget(properties,current) - if not injection then - injection = "injections" - end - if p then - -- local i = rawget(p,injection) - local i = rawget(p,injection) - if i then - i.leftkern = dx + (i.leftkern or 0) - else - p[injection] = { - leftkern = dx, - } - end - else - properties[current] = { - [injection] = { - leftkern = dx, - }, - } - end - return dx, nofregisteredkerns - else - return 0, 0 - end -end - -function injections.setmark(start,base,factor,rlmode,ba,ma,tfmbase,mkmk,checkmark) -- ba=baseanchor, ma=markanchor - - local dx, dy = factor*(ba[1]-ma[1]), factor*(ba[2]-ma[2]) - nofregisteredmarks = nofregisteredmarks + 1 - if rlmode >= 0 then - dx = tfmbase.width - dx -- see later commented ox - end - local p = rawget(properties,start) - -- hm, dejavu serif does a sloppy mark2mark before mark2base - if p then - -- local i = rawget(p,"injections") - local i = p.injections - if i then - if i.markmark then - -- out of order mkmk: yes or no or option - else - i.markx = dx - i.marky = dy - i.markdir = rlmode or 0 - i.markbase = nofregisteredmarks - i.markbasenode = base - i.markmark = mkmk - i.checkmark = checkmark - end - else - p.injections = { - markx = dx, - marky = dy, - markdir = rlmode or 0, - markbase = nofregisteredmarks, - markbasenode = base, - markmark = mkmk, - checkmark = checkmark, - } - end - else - properties[start] = { - injections = { - markx = dx, - marky = dy, - markdir = rlmode or 0, - markbase = nofregisteredmarks, - markbasenode = base, - markmark = mkmk, - checkmark = checkmark, - }, - } - end - return dx, dy, nofregisteredmarks -end - -local function dir(n) - return (n and n<0 and "r-to-l") or (n and n>0 and "l-to-r") or "unset" -end - -local function showchar(n,nested) - local char = getchar(n) - report_injections("%wfont %s, char %U, glyph %c",nested and 2 or 0,getfont(n),char,char) -end - -local function show(n,what,nested,symbol) - if n then - local p = rawget(properties,n) - if p then - local i = rawget(p,what) - if i then - local leftkern = i.leftkern or 0 - local rightkern = i.rightkern or 0 - local yoffset = i.yoffset or 0 - local markx = i.markx or 0 - local marky = i.marky or 0 - local markdir = i.markdir or 0 - local markbase = i.markbase or 0 - local cursivex = i.cursivex or 0 - local cursivey = i.cursivey or 0 - local ligaindex = i.ligaindex or 0 - local cursbase = i.cursiveanchor - local margin = nested and 4 or 2 - -- - if rightkern ~= 0 or yoffset ~= 0 then - report_injections("%w%s pair: lx %p, rx %p, dy %p",margin,symbol,leftkern,rightkern,yoffset) - elseif leftkern ~= 0 then - report_injections("%w%s kern: dx %p",margin,symbol,leftkern) - end - if markx ~= 0 or marky ~= 0 or markbase ~= 0 then - report_injections("%w%s mark: dx %p, dy %p, dir %s, base %s",margin,symbol,markx,marky,markdir,markbase ~= 0 and "yes" or "no") - end - if cursivex ~= 0 or cursivey ~= 0 then - if cursbase then - report_injections("%w%s curs: base dx %p, dy %p",margin,symbol,cursivex,cursivey) - else - report_injections("%w%s curs: dx %p, dy %p",margin,symbol,cursivex,cursivey) - end - elseif cursbase then - report_injections("%w%s curs: base",margin,symbol) - end - if ligaindex ~= 0 then - report_injections("%w%s liga: index %i",margin,symbol,ligaindex) - end - end - end - end -end - -local function showsub(n,what,where) - report_injections("begin subrun: %s",where) - for n in traverse_id(glyph_code,n) do - showchar(n,where) - show(n,what,where," ") - end - report_injections("end subrun") -end - -local function trace(head,where) - report_injections("begin run %s: %s kerns, %s pairs, %s marks and %s cursives registered", - where or "",nofregisteredkerns,nofregisteredpairs,nofregisteredmarks,nofregisteredcursives) - local n = head - while n do - local id = getid(n) - if id == glyph_code then - showchar(n) - show(n,"injections",false," ") - show(n,"preinjections",false,"<") - show(n,"postinjections",false,">") - show(n,"replaceinjections",false,"=") - show(n,"emptyinjections",false,"*") - elseif id == disc_code then - local pre, post, replace = getdisc(n) - if pre then - showsub(pre,"preinjections","pre") - end - if post then - showsub(post,"postinjections","post") - end - if replace then - showsub(replace,"replaceinjections","replace") - end - show(n,"emptyinjections",false,"*") - end - n = getnext(n) - end - report_injections("end run") -end - -local function show_result(head) - local current = head - local skipping = false - while current do - local id = getid(current) - if id == glyph_code then - report_injections("char: %C, width %p, xoffset %p, yoffset %p", - getchar(current),getfield(current,"width"),getfield(current,"xoffset"),getfield(current,"yoffset")) - skipping = false - elseif id == kern_code then - report_injections("kern: %p",getfield(current,"kern")) - skipping = false - elseif not skipping then - report_injections() - skipping = true - end - current = getnext(current) - end -end - --- G +D-pre G --- D-post+ --- +D-replace+ --- --- G +D-pre +D-pre --- D-post +D-post --- +D-replace +D-replace - -local function inject_kerns_only(head,where) - head = tonut(head) - if trace_injections then - trace(head,"kerns") - end - local current = head - local prev = nil - local next = nil - local prevdisc = nil - local prevglyph = nil - local pre = nil -- saves a lookup - local post = nil -- saves a lookup - local replace = nil -- saves a lookup - local pretail = nil -- saves a lookup - local posttail = nil -- saves a lookup - local replacetail = nil -- saves a lookup - while current do - local id = getid(current) - local next = getnext(current) - if id == glyph_code then - if getsubtype(current) < 256 then - local p = rawget(properties,current) - if p then - -- local i = rawget(p,"injections") - local i = p.injections - if i then - -- left|glyph|right - local leftkern = i.leftkern - if leftkern and leftkern ~= 0 then - if use_advance then - setfield(current,"xoffset",leftkern) - setfield(current,"xadvance",leftkern) - else - insert_node_before(head,current,newkern(leftkern)) - end - end - end - if prevdisc then - local done = false - if post then - -- local i = rawget(p,"postinjections") - local i = p.postinjections - if i then - local leftkern = i.leftkern - if leftkern and leftkern ~= 0 then - if use_advance then - setfield(post,"xadvance",leftkern) - else - insert_node_after(post,posttail,newkern(leftkern)) - done = true - end - end - end - end - if replace then - -- local i = rawget(p,"replaceinjections") - local i = p.replaceinjections - if i then - local leftkern = i.leftkern - if leftkern and leftkern ~= 0 then - if use_advance then - setfield(replace,"xadvance",leftkern) - else - insert_node_after(replace,replacetail,newkern(leftkern)) - done = true - end - end - end - else - -- local i = rawget(p,"emptyinjections") - local i = p.emptyinjections - if i then - -- glyph|disc|glyph (special case) - local leftkern = i.leftkern - if leftkern and leftkern ~= 0 then - setfield(prev,"replace",newkern(leftkern)) -- maybe also leftkern - end - end - end - if done then - setdisc(prevdisc,pre,post,replace) - end - end - end - end - prevdisc = nil - prevglyph = current - elseif id == disc_code then - pre, post, replace, pretail, posttail, replacetail = getdisc(current,true) - local done = false - if pre then - -- left|pre glyphs|right - for n in traverse_char(pre) do - local p = rawget(properties,n) - if p then - -- local i = rawget(p,"injections") or rawget(p,"preinjections") - local i = p.injections or p.preinjections - if i then - local leftkern = i.leftkern - if leftkern and leftkern ~= 0 then - if use_advance then - setfield(pre,"xoffset",leftkern) - setfield(pre,"xadvance",leftkern) - else - pre = insert_node_before(pre,n,newkern(leftkern)) - done = true - end - end - end - end - end - end - if post then - -- left|post glyphs|right - for n in traverse_char(post) do - local p = rawget(properties,n) - if p then - -- local i = rawget(p,"injections") or rawget(p,"postinjections") - local i = p.injections or p.postinjections - if i then - local leftkern = i.leftkern - if leftkern and leftkern ~= 0 then - if use_advance then - setfield(post,"xoffset",leftkern) - setfield(post,"xadvance",leftkern) - else - post = insert_node_before(post,n,newkern(leftkern)) - done = true - end - end - end - end - end - end - if replace then - -- left|replace glyphs|right - for n in traverse_char(replace) do - local p = rawget(properties,n) - if p then - -- local i = rawget(p,"injections") or rawget(p,"replaceinjections") - local i = p.injections or p.replaceinjections - if i then - local leftkern = i.leftkern - if leftkern and leftkern ~= 0 then - if use_advance then - setfield(replace,"xoffset",leftkern) - setfield(replace,"xadvance",leftkern) - else - replace = insert_node_before(replace,n,newkern(leftkern)) - done = true - end - end - end - end - end - end - if done then - setdisc(current,pre,post,replace) - end - prevglyph = nil - prevdisc = current - else - prevglyph = nil - prevdisc = nil - end - prev = current - current = next - end - -- - if keepregisteredcounts then - keepregisteredcounts = false - else - nofregisteredkerns = 0 - end - return tonode(head), true -end - -local function inject_pairs_only(head,where) - head = tonut(head) - if trace_injections then - trace(head,"pairs") - end - local current = head - local prev = nil - local next = nil - local prevdisc = nil - local prevglyph = nil - local pre = nil -- saves a lookup - local post = nil -- saves a lookup - local replace = nil -- saves a lookup - local pretail = nil -- saves a lookup - local posttail = nil -- saves a lookup - local replacetail = nil -- saves a lookup - while current do - local id = getid(current) - local next = getnext(current) - if id == glyph_code then - if getsubtype(current) < 256 then - local p = rawget(properties,current) - if p then - -- local i = rawget(p,"injections") - local i = p.injections - if i then - -- left|glyph|right - local yoffset = i.yoffset - if yoffset and yoffset ~= 0 then - setfield(current,"yoffset",yoffset) - end - local leftkern = i.leftkern - if leftkern and leftkern ~= 0 then - head = insert_node_before(head,current,newkern(leftkern)) - end - local rightkern = i.rightkern - if rightkern and rightkern ~= 0 then - insert_node_after(head,current,newkern(rightkern)) - end - else - -- local i = rawget(p,"emptyinjections") - local i = p.emptyinjections - if i then - -- glyph|disc|glyph (special case) --- is this okay? - local rightkern = i.rightkern - if rightkern and rightkern ~= 0 then - if next and getid(next) == disc_code then - if replace then - -- error, we expect an empty one - else - setfield(next,"replace",newkern(rightkern)) -- maybe also leftkern - end - end - end - end - end - if prevdisc then - local done = false - if post then - -- local i = rawget(p,"postinjections") - local i = p.postinjections - if i then - local leftkern = i.leftkern - if leftkern and leftkern ~= 0 then - insert_node_after(post,posttail,newkern(leftkern)) - done = true - end - end - end - if replace then - -- local i = rawget(p,"replaceinjections") - local i = p.replaceinjections - if i then - local leftkern = i.leftkern - if leftkern and leftkern ~= 0 then - insert_node_after(replace,replacetail,newkern(leftkern)) - done = true - end - end - else - local i = p.emptyinjections - if i then --- new .. okay? - local leftkern = i.leftkern - if leftkern and leftkern ~= 0 then - setfield(prev,"replace",newkern(leftkern)) -- maybe also leftkern - end - end - end - if done then - setdisc(prevdisc,pre,post,replace) - end - end - end - end - prevdisc = nil - prevglyph = current - elseif id == disc_code then - pre, post, replace, pretail, posttail, replacetail = getdisc(current,true) - local done = false - if pre then - -- left|pre glyphs|right - for n in traverse_char(pre) do - local p = rawget(properties,n) - if p then - -- local i = rawget(p,"injections") or rawget(p,"preinjections") - local i = p.injections or p.preinjections - if i then - local yoffset = i.yoffset - if yoffset and yoffset ~= 0 then - setfield(n,"yoffset",yoffset) - end - local leftkern = i.leftkern - if leftkern and leftkern ~= 0 then - pre = insert_node_before(pre,n,newkern(leftkern)) - done = true - end - local rightkern = i.rightkern - if rightkern and rightkern ~= 0 then - insert_node_after(pre,n,newkern(rightkern)) - done = true - end - end - end - end - end - if post then - -- left|post glyphs|right - for n in traverse_char(post) do - local p = rawget(properties,n) - if p then - -- local i = rawget(p,"injections") or rawget(p,"postinjections") - local i = p.injections or p.postinjections - if i then - local yoffset = i.yoffset - if yoffset and yoffset ~= 0 then - setfield(n,"yoffset",yoffset) - end - local leftkern = i.leftkern - if leftkern and leftkern ~= 0 then - post = insert_node_before(post,n,newkern(leftkern)) - done = true - end - local rightkern = i.rightkern - if rightkern and rightkern ~= 0 then - insert_node_after(post,n,newkern(rightkern)) - done = true - end - end - end - end - end - if replace then - -- left|replace glyphs|right - for n in traverse_char(replace) do - local p = rawget(properties,n) - if p then - -- local i = rawget(p,"injections") or rawget(p,"replaceinjections") - local i = p.injections or p.replaceinjections - if i then - local yoffset = i.yoffset - if yoffset and yoffset ~= 0 then - setfield(n,"yoffset",yoffset) - end - local leftkern = i.leftkern - if leftkern and leftkern ~= 0 then - replace = insert_node_before(replace,n,newkern(leftkern)) - done = true - end - local rightkern = i.rightkern - if rightkern and rightkern ~= 0 then - insert_node_after(replace,n,newkern(rightkern)) - done = true - end - end - end - end - end - if prevglyph then - if pre then - local p = rawget(properties,prevglyph) - if p then - -- local i = rawget(p,"preinjections") - local i = p.preinjections - if i then - -- glyph|pre glyphs - local rightkern = i.rightkern - if rightkern and rightkern ~= 0 then - pre = insert_node_before(pre,pre,newkern(rightkern)) - done = true - end - end - end - end - if replace then - local p = rawget(properties,prevglyph) - if p then - -- local i = rawget(p,"replaceinjections") - local i = p.replaceinjections - if i then - -- glyph|replace glyphs - local rightkern = i.rightkern - if rightkern and rightkern ~= 0 then - replace = insert_node_before(replace,replace,newkern(rightkern)) - done = true - end - end - end - end - end - if done then - setdisc(current,pre,post,replace) - end - prevglyph = nil - prevdisc = current - else - prevglyph = nil - prevdisc = nil - end - prev = current - current = next - end - -- - if keepregisteredcounts then - keepregisteredcounts = false - else - nofregisteredkerns = 0 - end - return tonode(head), true -end - --- local function showoffset(n,flag) --- local ox = getfield(n,"xoffset") --- local oy = getfield(n,"yoffset") --- if flag then --- if ox == 0 then --- setcolor(n,oy == 0 and "darkgray" or "darkgreen") --- else --- setcolor(n,oy == 0 and "darkblue" or "darkred") --- end --- else --- if ox == 0 then --- setcolor(n,oy == 0 and "gray" or "green") --- else --- setcolor(n,oy == 0 and "blue" or "red") --- end --- end --- end - -local function showoffset(n,flag) - local o = getfield(n,"xoffset") - if o == 0 then - o = getfield(n,"yoffset") - end - if o ~= 0 then - setcolor(n,flag and "darkred" or "darkgreen") - else - resetcolor(n) - end -end - -local function inject_everything(head,where) - head = tonut(head) - if trace_injections then - trace(head,"everything") - end - local hascursives = nofregisteredcursives > 0 - local hasmarks = nofregisteredmarks > 0 - -- - local current = head - local last = nil - local font = font - local markdata = nil - local prev = nil - local next = nil - local prevdisc = nil - local prevglyph = nil - local pre = nil -- saves a lookup - local post = nil -- saves a lookup - local replace = nil -- saves a lookup - local pretail = nil -- saves a lookup - local posttail = nil -- saves a lookup - local replacetail = nil -- saves a lookup - -- - local cursiveanchor = nil - local minc = 0 - local maxc = 0 - local glyphs = { } - local marks = { } - local nofmarks = 0 - -- - -- move out - -- - local function processmark(p,n,pn) -- p = basenode - local px = getfield(p,"xoffset") - local ox = 0 - local rightkern = nil - local pp = rawget(properties,p) - if pp then - -- pp = rawget(pp,"injections") - pp = pp.injections - if pp then - rightkern = pp.rightkern - end - end - if rightkern then -- x and w ~= 0 - if pn.markdir < 0 then - -- kern(w-x) glyph(p) kern(x) mark(n) - ox = px - pn.markx - rightkern - -- report_injections("r2l case 1: %p",ox) - else - -- kern(x) glyph(p) kern(w-x) mark(n) - -- ox = px - getfield(p,"width") + pn.markx - pp.leftkern - -- - -- According to Kai we don't need to handle leftkern here but I'm - -- pretty sure I've run into a case where it was needed so maybe - -- some day we need something more clever here. - -- - if false then - -- a mark with kerning - local leftkern = pp.leftkern - if leftkern then - ox = px - pn.markx - leftkern - else - ox = px - pn.markx - end - else - ox = px - pn.markx - end - end - else - -- if pn.markdir < 0 then - -- ox = px - pn.markx - -- -- report_injections("r2l case 3: %p",ox) - -- else - -- -- ox = px - getfield(p,"width") + pn.markx - ox = px - pn.markx - -- report_injections("l2r case 3: %p",ox) - -- end - if pn.checkmark then - local wn = getfield(n,"width") -- in arial marks have widths - if wn ~= 0 then - wn = wn/2 - if trace_injections then - report_injections("correcting non zero width mark %C",getchar(n)) - end - -- -- bad: we should center - -- pn.leftkern = -wn - -- pn.rightkern = -wn - -- -- we're too late anyway as kerns are already injected so - -- -- we do it the ugly way (no checking if the previous is - -- -- already a kern) .. maybe we should fix the font instead - insert_node_before(n,n,newkern(-wn)) - insert_node_after(n,n,newkern(-wn)) - end - end - end - local oy = getfield(n,"yoffset") + getfield(p,"yoffset") + pn.marky - setfield(n,"xoffset",ox) - setfield(n,"yoffset",oy) - if trace_marks then - showoffset(n,true) - end - end - -- todo: marks in disc - while current do - local id = getid(current) - local next = getnext(current) - if id == glyph_code then - if getsubtype(current) < 256 then - local p = rawget(properties,current) - if p then - -- local i = rawget(p,"injections") - local i = p.injections - if i then - local pm = i.markbasenode - if pm then - nofmarks = nofmarks + 1 - marks[nofmarks] = current - else - local yoffset = i.yoffset - if yoffset and yoffset ~= 0 then - setfield(current,"yoffset",yoffset) - end - if hascursives then - local cursivex = i.cursivex - if cursivex then - if cursiveanchor then - if cursivex ~= 0 then - i.leftkern = (i.leftkern or 0) + cursivex - end - if maxc == 0 then - minc = 1 - maxc = 1 - glyphs[1] = cursiveanchor - else - maxc = maxc + 1 - glyphs[maxc] = cursiveanchor - end - properties[cursiveanchor].cursivedy = i.cursivey -- cursiveprops - last = current - else - maxc = 0 - end - elseif maxc > 0 then - local ny = getfield(current,"yoffset") - for i=maxc,minc,-1 do - local ti = glyphs[i] - ny = ny + properties[ti].cursivedy - setfield(ti,"yoffset",ny) -- why not add ? - if trace_cursive then - showoffset(ti) - end - end - maxc = 0 - cursiveanchor = nil - end - if i.cursiveanchor then - cursiveanchor = current -- no need for both now - else - if maxc > 0 then - local ny = getfield(current,"yoffset") - for i=maxc,minc,-1 do - local ti = glyphs[i] - ny = ny + properties[ti].cursivedy - setfield(ti,"yoffset",ny) -- why not add ? - if trace_cursive then - showoffset(ti) - end - end - maxc = 0 - end - cursiveanchor = nil - end - end - -- left|glyph|right - local leftkern = i.leftkern - if leftkern and leftkern ~= 0 then - insert_node_before(head,current,newkern(leftkern)) - end - local rightkern = i.rightkern - if rightkern and rightkern ~= 0 then - insert_node_after(head,current,newkern(rightkern)) - end - end - else - -- local i = rawget(p,"emptyinjections") - local i = p.emptyinjections - if i then - -- glyph|disc|glyph (special case) - -- okay? - local rightkern = i.rightkern - if rightkern and rightkern ~= 0 then - if next and getid(next) == disc_code then - if replace then - -- error, we expect an empty one - else - setfield(next,"replace",newkern(rightkern)) -- maybe also leftkern - end - end - end - end - end - if prevdisc then - if p then - local done = false - if post then - -- local i = rawget(p,"postinjections") - local i = p.postinjections - if i then - local leftkern = i.leftkern - if leftkern and leftkern ~= 0 then - insert_node_after(post,posttail,newkern(leftkern)) - done = true - end - end - end - if replace then - -- local i = rawget(p,"replaceinjections") - local i = p.replaceinjections - if i then - local leftkern = i.leftkern - if leftkern and leftkern ~= 0 then - insert_node_after(replace,replacetail,newkern(leftkern)) - done = true - end - end - else - -- local i = rawget(p,"emptyinjections") - local i = p.emptyinjections - if i then - local leftkern = i.leftkern - if leftkern and leftkern ~= 0 then - setfield(prev,"replace",newkern(leftkern)) -- maybe also leftkern - end - end - end - if done then - setdisc(prevdisc,pre,post,replace) - end - end - end - else - -- cursive - if hascursives and maxc > 0 then - local ny = getfield(current,"yoffset") - for i=maxc,minc,-1 do - local ti = glyphs[i] - ny = ny + properties[ti].cursivedy - setfield(ti,"yoffset",getfield(ti,"yoffset") + ny) -- can be mark - end - maxc = 0 - cursiveanchor = nil - end - end - end - prevdisc = nil - prevglyph = current - elseif id == disc_code then - pre, post, replace, pretail, posttail, replacetail = getdisc(current,true) - local done = false - if pre then - -- left|pre glyphs|right - for n in traverse_char(pre) do - local p = rawget(properties,n) - if p then - -- local i = rawget(p,"injections") or rawget(p,"preinjections") - local i = p.injections or p.preinjections - if i then - local yoffset = i.yoffset - if yoffset and yoffset ~= 0 then - setfield(n,"yoffset",yoffset) - end - local leftkern = i.leftkern - if leftkern and leftkern ~= 0 then - pre = insert_node_before(pre,n,newkern(leftkern)) - done = true - end - local rightkern = i.rightkern - if rightkern and rightkern ~= 0 then - insert_node_after(pre,n,newkern(rightkern)) - done = true - end - if hasmarks then - local pm = i.markbasenode - if pm then - processmark(pm,current,i) - end - end - end - end - end - end - if post then - -- left|post glyphs|right - for n in traverse_char(post) do - local p = rawget(properties,n) - if p then - -- local i = rawget(p,"injections") or rawget(p,"postinjections") - local i = p.injections or p.postinjections - if i then - local yoffset = i.yoffset - if yoffset and yoffset ~= 0 then - setfield(n,"yoffset",yoffset) - end - local leftkern = i.leftkern - if leftkern and leftkern ~= 0 then - post = insert_node_before(post,n,newkern(leftkern)) - done = true - end - local rightkern = i.rightkern - if rightkern and rightkern ~= 0 then - insert_node_after(post,n,newkern(rightkern)) - done = true - end - if hasmarks then - local pm = i.markbasenode - if pm then - processmark(pm,current,i) - end - end - end - end - end - end - if replace then - -- left|replace glyphs|right - for n in traverse_char(replace) do - local p = rawget(properties,n) - if p then - -- local i = rawget(p,"injections") or rawget(p,"replaceinjections") - local i = p.injections or p.replaceinjections - if i then - local yoffset = i.yoffset - if yoffset and yoffset ~= 0 then - setfield(n,"yoffset",yoffset) - end - local leftkern = i.leftkern - if leftkern and leftkern ~= 0 then - replace = insert_node_before(replace,n,newkern(leftkern)) - done = true - end - local rightkern = i.rightkern - if rightkern and rightkern ~= 0 then - insert_node_after(replace,n,newkern(rightkern)) - done = true - end - if hasmarks then - local pm = i.markbasenode - if pm then - processmark(pm,current,i) - end - end - end - end - end - end - if prevglyph then - if pre then - local p = rawget(properties,prevglyph) - if p then - -- local i = rawget(p,"preinjections") - local i = p.preinjections - if i then - -- glyph|pre glyphs - local rightkern = i.rightkern - if rightkern and rightkern ~= 0 then - pre = insert_node_before(pre,pre,newkern(rightkern)) - done = true - end - end - end - end - if replace then - local p = rawget(properties,prevglyph) - if p then - -- local i = rawget(p,"replaceinjections") - local i = p.replaceinjections - if i then - -- glyph|replace glyphs - local rightkern = i.rightkern - if rightkern and rightkern ~= 0 then - replace = insert_node_before(replace,replace,newkern(rightkern)) - done = true - end - end - end - end - end - if done then - setdisc(current,pre,post,replace) - end - prevglyph = nil - prevdisc = current - else - prevglyph = nil - prevdisc = nil - end - prev = current - current = next - end - -- cursive - if hascursives and maxc > 0 then - local ny = getfield(last,"yoffset") - for i=maxc,minc,-1 do - local ti = glyphs[i] - ny = ny + properties[ti].cursivedy - setfield(ti,"yoffset",ny) -- why not add ? - if trace_cursive then - showoffset(ti) - end - end - end - -- - if nofmarks > 0 then - for i=1,nofmarks do - local m = marks[i] - local p = rawget(properties,m) - -- local i = rawget(p,"injections") - local i = p.injections - local b = i.markbasenode - processmark(b,m,i) - end - elseif hasmarks then - -- sometyhing bad happened - end - -- - if keepregisteredcounts then - keepregisteredcounts = false - else - nofregisteredkerns = 0 - nofregisteredpairs = 0 - nofregisteredmarks = 0 - nofregisteredcursives = 0 - end - return tonode(head), true -end - --- space triggers - -local triggers = false - -function nodes.injections.setspacekerns(font,sequence) - if triggers then - triggers[font] = sequence - else - triggers = { [font] = sequence } - end -end - -local getthreshold - -if context then - - local threshold = 1 -- todo: add a few methods for context - local parameters = fonts.hashes.parameters - - directives.register("otf.threshold", function(v) threshold = tonumber(v) or 1 end) - - getthreshold = function(font) - local p = parameters[font] - local f = p.factor - local s = p.spacing - local t = threshold * (s and s.width or p.space or 0) - 2 - return t > 0 and t or 0, f - end - -else - - injections.threshold = 0 - - getthreshold = function(font) - local p = fontdata[font].parameters - local f = p.factor - local s = p.spacing - local t = injections.threshold * (s and s.width or p.space or 0) - 2 - return t > 0 and t or 0, f - end - -end - -injections.getthreshold = getthreshold - -function injections.isspace(n,threshold) - if getid(n) == glue_code then - local w = getfield(n,"width") - if threshold and w > threshold then -- was >= - return 32 - end - end -end - -local function injectspaces(head) - - if not triggers then - return head, false - end - - local lastfont = nil - local spacekerns = nil - local leftkerns = nil - local rightkerns = nil - local factor = 0 - local threshold = 0 - local leftkern = false - local rightkern = false - - local function updatefont(font,trig) - leftkerns = trig.left - rightkerns = trig.right - lastfont = font - threshold, - factor = getthreshold(font) - end - - for n in traverse_id(glue_code,tonut(head)) do - local prev, next = getboth(n) - local prevchar = ischar(prev) - local nextchar = ischar(next) - if nextchar then - local font = getfont(next) - local trig = triggers[font] - if trig then - if lastfont ~= font then - updatefont(font,trig) - end - if rightkerns then - rightkern = rightkerns[nextchar] - end - end - end - if prevchar then - local font = getfont(prev) - local trig = triggers[font] - if trig then - if lastfont ~= font then - updatefont(font,trig) - end - if leftkerns then - leftkern = leftkerns[prevchar] - end - end - end - if leftkern then - local old = getfield(n,"width") - if old > threshold then - if rightkern then - local new = old + (leftkern + rightkern) * factor - if trace_spaces then - report_spaces("%C [%p -> %p] %C",prevchar,old,new,nextchar) - end - setfield(n,"width",new) - leftkern = false - else - local new = old + leftkern * factor - if trace_spaces then - report_spaces("%C [%p -> %p]",prevchar,old,new) - end - setfield(n,"width",new) - end - end - leftkern = false - elseif rightkern then - local old = getfield(n,"width") - if old > threshold then - local new = old + rightkern * factor - if trace_spaces then - report_spaces("[%p -> %p] %C",nextchar,old,new) - end - setfield(n,"width",new) - end - rightkern = false - end - end - - triggers = false - return head, true -end - --- - -function injections.handler(head,where) - if triggers then - head = injectspaces(head) - end - -- todo: marks only run too - if nofregisteredmarks > 0 or nofregisteredcursives > 0 then - if trace_injections then - report_injections("injection variant %a","everything") - end - return inject_everything(head,where) - elseif nofregisteredpairs > 0 then - if trace_injections then - report_injections("injection variant %a","pairs") - end - return inject_pairs_only(head,where) - elseif nofregisteredkerns > 0 then - if trace_injections then - report_injections("injection variant %a","kerns") - end - return inject_kerns_only(head,where) - else - return head, false - end -end diff --git a/tex/compat/luaotfload/fontloader-font-otl.lua b/tex/compat/luaotfload/fontloader-font-otl.lua deleted file mode 100644 index d4eaed763ba888eefec9015bf7e7162327b6274b..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/fontloader-font-otl.lua +++ /dev/null @@ -1,823 +0,0 @@ -if not modules then modules = { } end modules ['font-otl'] = { - version = 1.001, - comment = "companion to font-ini.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files", -} - --- After some experimenting with an alternative loader (one that is needed for --- getting outlines in mp) I decided not to be compatible with the old (built-in) --- one. The approach used in font-otn is as follows: we load the font in a compact --- format but still very compatible with the ff data structures. From there we --- create hashes to access the data efficiently. The implementation of feature --- processing is mostly based on looking at the data as organized in the glyphs and --- lookups as well as the specification. Keeping the lookup data in the glyphs is --- very instructive and handy for tracing. On the other hand hashing is what brings --- speed. So, the in the new approach (the old one will stay around too) we no --- longer keep data in the glyphs which saves us a (what in retrospect looks a bit --- like) a reconstruction step. It also means that the data format of the cached --- files changes. What method is used depends on that format. There is no fundamental --- change in processing, and not even in data organation. Most has to do with --- loading and storage. - --- todo: less tounicodes - -local gmatch, find, match, lower, strip = string.gmatch, string.find, string.match, string.lower, string.strip -local type, next, tonumber, tostring, unpack = type, next, tonumber, tostring, unpack -local abs = math.abs -local derivetable = table.derive -local formatters = string.formatters - -local setmetatableindex = table.setmetatableindex -local allocate = utilities.storage.allocate -local registertracker = trackers.register -local registerdirective = directives.register -local starttiming = statistics.starttiming -local stoptiming = statistics.stoptiming -local elapsedtime = statistics.elapsedtime -local findbinfile = resolvers.findbinfile - ------ trace_private = false registertracker("otf.private", function(v) trace_private = v end) ------ trace_subfonts = false registertracker("otf.subfonts", function(v) trace_subfonts = v end) -local trace_loading = false registertracker("otf.loading", function(v) trace_loading = v end) -local trace_features = false registertracker("otf.features", function(v) trace_features = v end) ------ trace_dynamics = false registertracker("otf.dynamics", function(v) trace_dynamics = v end) ------ trace_sequences = false registertracker("otf.sequences", function(v) trace_sequences = v end) ------ trace_markwidth = false registertracker("otf.markwidth", function(v) trace_markwidth = v end) -local trace_defining = false registertracker("fonts.defining", function(v) trace_defining = v end) - -local report_otf = logs.reporter("fonts","otf loading") - -local fonts = fonts -local otf = fonts.handlers.otf - -otf.version = 3.027 -- beware: also sync font-mis.lua and in mtx-fonts -otf.cache = containers.define("fonts", "otl", otf.version, true) -otf.svgcache = containers.define("fonts", "svg", otf.version, true) -otf.pdfcache = containers.define("fonts", "pdf", otf.version, true) - -otf.svgenabled = false - -local otfreaders = otf.readers - -local hashes = fonts.hashes -local definers = fonts.definers -local readers = fonts.readers -local constructors = fonts.constructors - -local otffeatures = constructors.features.otf -local registerotffeature = otffeatures.register - -local otfenhancers = constructors.enhancers.otf -local registerotfenhancer = otfenhancers.register - -local forceload = false -local cleanup = 0 -- mk: 0=885M 1=765M 2=735M (regular run 730M) -local syncspace = true -local forcenotdef = false - -local applyruntimefixes = fonts.treatments and fonts.treatments.applyfixes - -local wildcard = "*" -local default = "dflt" - -local formats = fonts.formats - -formats.otf = "opentype" -formats.ttf = "truetype" -formats.ttc = "truetype" - -registerdirective("fonts.otf.loader.cleanup", function(v) cleanup = tonumber(v) or (v and 1) or 0 end) -registerdirective("fonts.otf.loader.force", function(v) forceload = v end) -registerdirective("fonts.otf.loader.syncspace", function(v) syncspace = v end) -registerdirective("fonts.otf.loader.forcenotdef", function(v) forcenotdef = v end) - --- local function load_featurefile(raw,featurefile) --- if featurefile and featurefile ~= "" then --- if trace_loading then --- report_otf("using featurefile %a", featurefile) --- end --- -- TODO: apply_featurefile(raw, featurefile) --- end --- end - --- otfenhancers.patch("before","migrate metadata","cambria",function() end) - -registerotfenhancer("check extra features", function() end) -- placeholder - -function otf.load(filename,sub,featurefile) -- second argument (format) is gone ! - -- - local featurefile = nil -- not supported (yet) - -- - local base = file.basename(file.removesuffix(filename)) - local name = file.removesuffix(base) - local attr = lfs.attributes(filename) - local size = attr and attr.size or 0 - local time = attr and attr.modification or 0 - if featurefile then - name = name .. "@" .. file.removesuffix(file.basename(featurefile)) - end - -- sub can be number of string - if sub == "" then - sub = false - end - local hash = name - if sub then - hash = hash .. "-" .. sub - end - hash = containers.cleanname(hash) - local featurefiles - if featurefile then - featurefiles = { } - for s in gmatch(featurefile,"[^,]+") do - local name = resolvers.findfile(file.addsuffix(s,'fea'),'fea') or "" - if name == "" then - report_otf("loading error, no featurefile %a",s) - else - local attr = lfs.attributes(name) - featurefiles[#featurefiles+1] = { - name = name, - size = attr and attr.size or 0, - time = attr and attr.modification or 0, - } - end - end - if #featurefiles == 0 then - featurefiles = nil - end - end - local data = containers.read(otf.cache,hash) - local reload = not data or data.size ~= size or data.time ~= time or data.tableversion ~= otfreaders.tableversion - if forceload then - report_otf("forced reload of %a due to hard coded flag",filename) - reload = true - end - -- if not reload then - -- local featuredata = data.featuredata - -- if featurefiles then - -- if not featuredata or #featuredata ~= #featurefiles then - -- reload = true - -- else - -- for i=1,#featurefiles do - -- local fi, fd = featurefiles[i], featuredata[i] - -- if fi.name ~= fd.name or fi.size ~= fd.size or fi.time ~= fd.time then - -- reload = true - -- break - -- end - -- end - -- end - -- elseif featuredata then - -- reload = true - -- end - -- if reload then - -- report_otf("loading: forced reload due to changed featurefile specification %a",featurefile) - -- end - -- end - if reload then - report_otf("loading %a, hash %a",filename,hash) - -- - starttiming(otfreaders) - data = otfreaders.loadfont(filename,sub or 1) -- we can pass the number instead (if it comes from a name search) - -- - -- if featurefiles then - -- for i=1,#featurefiles do - -- load_featurefile(data,featurefiles[i].name) - -- end - -- end - -- - -- - if data then - -- - local resources = data.resources - local svgshapes = resources.svgshapes - if svgshapes then - resources.svgshapes = nil - if otf.svgenabled then - local timestamp = os.date() - -- work in progress ... a bit boring to do - containers.write(otf.svgcache,hash, { - svgshapes = svgshapes, - timestamp = timestamp, - }) - data.properties.svg = { - hash = hash, - timestamp = timestamp, - } - end - end - -- - otfreaders.compact(data) - otfreaders.rehash(data,"unicodes") - otfreaders.addunicodetable(data) - otfreaders.extend(data) - otfreaders.pack(data) - report_otf("loading done") - report_otf("saving %a in cache",filename) - data = containers.write(otf.cache, hash, data) - if cleanup > 1 then - collectgarbage("collect") - end - stoptiming(otfreaders) - if elapsedtime then - report_otf("loading, optimizing, packing and caching time %s", elapsedtime(otfreaders)) - end - if cleanup > 3 then - collectgarbage("collect") - end - data = containers.read(otf.cache,hash) -- this frees the old table and load the sparse one - if cleanup > 2 then - collectgarbage("collect") - end - else - data = nil - report_otf("loading failed due to read error") - end - end - if data then - if trace_defining then - report_otf("loading from cache using hash %a",hash) - end - -- - otfreaders.unpack(data) - otfreaders.expand(data) -- inline tables - otfreaders.addunicodetable(data) -- only when not done yet - -- - otfenhancers.apply(data,filename,data) - -- - -- constructors.addcoreunicodes(data.resources.unicodes) -- still needed ? - -- - if applyruntimefixes then - applyruntimefixes(filename,data) - end - -- - data.metadata.math = data.resources.mathconstants - end - - return data -end - --- modes: node, base, none - -function otf.setfeatures(tfmdata,features) - local okay = constructors.initializefeatures("otf",tfmdata,features,trace_features,report_otf) - if okay then - return constructors.collectprocessors("otf",tfmdata,features,trace_features,report_otf) - else - return { } -- will become false - end -end - --- the first version made a top/mid/not extensible table, now we just --- pass on the variants data and deal with it in the tfm scaler (there --- is no longer an extensible table anyway) --- --- we cannot share descriptions as virtual fonts might extend them (ok, --- we could use a cache with a hash --- --- we already assign an empty table to characters as we can add for --- instance protruding info and loop over characters; one is not supposed --- to change descriptions and if one does so one should make a copy! - -local function copytotfm(data,cache_id) - if data then - local metadata = data.metadata - local properties = derivetable(data.properties) - local descriptions = derivetable(data.descriptions) - local goodies = derivetable(data.goodies) - local characters = { } - local parameters = { } - local mathparameters = { } - -- - local resources = data.resources - local unicodes = resources.unicodes - local spaceunits = 500 - local spacer = "space" - local designsize = metadata.designsize or 100 - local minsize = metadata.minsize or designsize - local maxsize = metadata.maxsize or designsize - local mathspecs = metadata.math - -- - if designsize == 0 then - designsize = 100 - minsize = 100 - maxsize = 100 - end - if mathspecs then - for name, value in next, mathspecs do - mathparameters[name] = value - end - end - for unicode in next, data.descriptions do -- use parent table - characters[unicode] = { } - end - if mathspecs then - for unicode, character in next, characters do - local d = descriptions[unicode] - local m = d.math - if m then - -- watch out: luatex uses horiz_variants for the parts - -- - local italic = m.italic - local vitalic = m.vitalic - -- - local variants = m.hvariants - local parts = m.hparts - if variants then - local c = character - for i=1,#variants do - -- local un = variants[i].glyph - local un = variants[i] - c.next = un - c = characters[un] - end -- c is now last in chain - c.horiz_variants = parts - elseif parts then - character.horiz_variants = parts - italic = m.hitalic - end - -- - local variants = m.vvariants - local parts = m.vparts - if variants then - local c = character - for i=1,#variants do - -- local un = variants[i].glyph - local un = variants[i] - c.next = un - c = characters[un] - end -- c is now last in chain - c.vert_variants = parts - elseif parts then - character.vert_variants = parts - end - -- - if italic and italic ~= 0 then - character.italic = italic - end - -- - if vitalic and vitalic ~= 0 then - character.vert_italic = vitalic - end - -- - local accent = m.accent -- taccent? - if accent then - character.accent = accent - end - -- - local kerns = m.kerns - if kerns then - character.mathkerns = kerns - end - end - end - end - -- we need a runtime lookup because of running from cdrom or zip, brrr (shouldn't - -- we use the basename then?) - local filename = constructors.checkedfilename(resources) - local fontname = metadata.fontname - local fullname = metadata.fullname or fontname - local psname = fontname or fullname - local units = metadata.units or 1000 - -- - if units == 0 then -- catch bugs in fonts - units = 1000 -- maybe 2000 when ttf - metadata.units = 1000 - report_otf("changing %a units to %a",0,units) - end - -- - local monospaced = metadata.monospaced - local charwidth = metadata.averagewidth -- or unset - local charxheight = metadata.xheight -- or unset - local italicangle = metadata.italicangle - local hasitalics = metadata.hasitalics - properties.monospaced = monospaced - properties.hasitalics = hasitalics - parameters.italicangle = italicangle - parameters.charwidth = charwidth - parameters.charxheight = charxheight - -- - local space = 0x0020 - local emdash = 0x2014 - if monospaced then - if descriptions[space] then - spaceunits, spacer = descriptions[space].width, "space" - end - if not spaceunits and descriptions[emdash] then - spaceunits, spacer = descriptions[emdash].width, "emdash" - end - if not spaceunits and charwidth then - spaceunits, spacer = charwidth, "charwidth" - end - else - if descriptions[space] then - spaceunits, spacer = descriptions[space].width, "space" - end - if not spaceunits and descriptions[emdash] then - spaceunits, spacer = descriptions[emdash].width/2, "emdash/2" - end - if not spaceunits and charwidth then - spaceunits, spacer = charwidth, "charwidth" - end - end - spaceunits = tonumber(spaceunits) or units/2 - -- - parameters.slant = 0 - parameters.space = spaceunits -- 3.333 (cmr10) - parameters.space_stretch = 1*units/2 -- 500 -- 1.666 (cmr10) - parameters.space_shrink = 1*units/3 -- 333 -- 1.111 (cmr10) - parameters.x_height = 2*units/5 -- 400 - parameters.quad = units -- 1000 - if spaceunits < 2*units/5 then - -- todo: warning - end - if italicangle and italicangle ~= 0 then - parameters.italicangle = italicangle - parameters.italicfactor = math.cos(math.rad(90+italicangle)) - parameters.slant = - math.tan(italicangle*math.pi/180) - end - if monospaced then - parameters.space_stretch = 0 - parameters.space_shrink = 0 - elseif syncspace then -- - parameters.space_stretch = spaceunits/2 - parameters.space_shrink = spaceunits/3 - end - parameters.extra_space = parameters.space_shrink -- 1.111 (cmr10) - if charxheight then - parameters.x_height = charxheight - else - local x = 0x0078 - if x then - local x = descriptions[x] - if x then - parameters.x_height = x.height - end - end - end - -- - parameters.designsize = (designsize/10)*65536 - parameters.minsize = (minsize /10)*65536 - parameters.maxsize = (maxsize /10)*65536 - parameters.ascender = abs(metadata.ascender or 0) - parameters.descender = abs(metadata.descender or 0) - parameters.units = units - -- - properties.space = spacer - properties.encodingbytes = 2 - properties.format = data.format or formats.otf - properties.noglyphnames = true - properties.filename = filename - properties.fontname = fontname - properties.fullname = fullname - properties.psname = psname - properties.name = filename or fullname - -- - -- properties.name = specification.name - -- properties.sub = specification.sub - -- - return { - characters = characters, - descriptions = descriptions, - parameters = parameters, - mathparameters = mathparameters, - resources = resources, - properties = properties, - goodies = goodies, - } - end -end - --- These woff files are a kind of joke in a tex environment because one can simply convert --- them to ttf/otf and use them as such (after all, we cache them too). The successor format --- woff2 is more complex so there we can as well call an external converter which in the end --- makes this code kind of obsolete before it's even used. Although ... it might become a --- more general conversion plug in. - -local converters = { - woff = { - cachename = "webfonts", - action = otf.readers.woff2otf, - } -} - -local function checkconversion(specification) - local filename = specification.filename - local converter = converters[lower(file.suffix(filename))] - if converter then - local base = file.basename(filename) - local name = file.removesuffix(base) - local attr = lfs.attributes(filename) - local size = attr and attr.size or 0 - local time = attr and attr.modification or 0 - if size > 0 then - local cleanname = containers.cleanname(name) - local cachename = caches.setfirstwritablefile(cleanname,converter.cachename) - if not io.exists(cachename) or (time ~= lfs.attributes(cachename).modification) then - report_otf("caching font %a in %a",filename,cachename) - converter.action(filename,cachename) -- todo infoonly - lfs.touch(cachename,time,time) - end - specification.filename = cachename - end - end -end - -local function otftotfm(specification) - local cache_id = specification.hash - local tfmdata = containers.read(constructors.cache,cache_id) - if not tfmdata then - - checkconversion(specification) -- for the moment here - - local name = specification.name - local sub = specification.sub - local subindex = specification.subindex - local filename = specification.filename - local features = specification.features.normal - local rawdata = otf.load(filename,sub,features and features.featurefile) - if rawdata and next(rawdata) then - local descriptions = rawdata.descriptions - rawdata.lookuphash = { } -- to be done - tfmdata = copytotfm(rawdata,cache_id) - if tfmdata and next(tfmdata) then - -- at this moment no characters are assigned yet, only empty slots - local features = constructors.checkedfeatures("otf",features) - local shared = tfmdata.shared - if not shared then - shared = { } - tfmdata.shared = shared - end - shared.rawdata = rawdata - -- shared.features = features -- default - shared.dynamics = { } - -- shared.processes = { } - tfmdata.changed = { } - shared.features = features - shared.processes = otf.setfeatures(tfmdata,features) - end - end - containers.write(constructors.cache,cache_id,tfmdata) - end - return tfmdata -end - -local function read_from_otf(specification) - local tfmdata = otftotfm(specification) - if tfmdata then - -- this late ? .. needs checking - tfmdata.properties.name = specification.name - tfmdata.properties.sub = specification.sub - -- - tfmdata = constructors.scale(tfmdata,specification) - local allfeatures = tfmdata.shared.features or specification.features.normal - constructors.applymanipulators("otf",tfmdata,allfeatures,trace_features,report_otf) - constructors.setname(tfmdata,specification) -- only otf? - fonts.loggers.register(tfmdata,file.suffix(specification.filename),specification) - end - return tfmdata -end - -local function checkmathsize(tfmdata,mathsize) - local mathdata = tfmdata.shared.rawdata.metadata.math - local mathsize = tonumber(mathsize) - if mathdata then -- we cannot use mathparameters as luatex will complain - local parameters = tfmdata.parameters - parameters.scriptpercentage = mathdata.ScriptPercentScaleDown - parameters.scriptscriptpercentage = mathdata.ScriptScriptPercentScaleDown - parameters.mathsize = mathsize - end -end - -registerotffeature { - name = "mathsize", - description = "apply mathsize specified in the font", - initializers = { - base = checkmathsize, - node = checkmathsize, - } -} - --- readers - -function otf.collectlookups(rawdata,kind,script,language) - if not kind then - return - end - if not script then - script = default - end - if not language then - language = default - end - local lookupcache = rawdata.lookupcache - if not lookupcache then - lookupcache = { } - rawdata.lookupcache = lookupcache - end - local kindlookup = lookupcache[kind] - if not kindlookup then - kindlookup = { } - lookupcache[kind] = kindlookup - end - local scriptlookup = kindlookup[script] - if not scriptlookup then - scriptlookup = { } - kindlookup[script] = scriptlookup - end - local languagelookup = scriptlookup[language] - if not languagelookup then - local sequences = rawdata.resources.sequences - local featuremap = { } - local featurelist = { } - if sequences then - for s=1,#sequences do - local sequence = sequences[s] - local features = sequence.features - if features then - features = features[kind] - if features then - -- features = features[script] or features[default] or features[wildcard] - features = features[script] or features[wildcard] - if features then - -- features = features[language] or features[default] or features[wildcard] - features = features[language] or features[wildcard] - if features then - if not featuremap[sequence] then - featuremap[sequence] = true - featurelist[#featurelist+1] = sequence - end - end - end - end - end - end - if #featurelist == 0 then - featuremap, featurelist = false, false - end - else - featuremap, featurelist = false, false - end - languagelookup = { featuremap, featurelist } - scriptlookup[language] = languagelookup - end - return unpack(languagelookup) -end - --- moved from font-oth.lua, todo: also afm - -local function getgsub(tfmdata,k,kind,value) - local shared = tfmdata.shared - local rawdata = shared and shared.rawdata - if rawdata then - local sequences = rawdata.resources.sequences - if sequences then - local properties = tfmdata.properties - local validlookups, lookuplist = otf.collectlookups(rawdata,kind,properties.script,properties.language) - if validlookups then - -- local choice = tonumber(value) or 1 -- no random here (yet) - for i=1,#lookuplist do - local lookup = lookuplist[i] - local steps = lookup.steps - local nofsteps = lookup.nofsteps - for i=1,nofsteps do - local coverage = steps[i].coverage - if coverage then - local found = coverage[k] - if found then - return found, lookup.type - end - end - end - end - end - end - end -end - -otf.getgsub = getgsub -- returns value, gsub_kind - -function otf.getsubstitution(tfmdata,k,kind,value) - local found, kind = getgsub(tfmdata,k,kind,value) - if not found then - -- - elseif kind == "gsub_single" then - return found - elseif kind == "gsub_alternate" then - local choice = tonumber(value) or 1 -- no random here (yet) - return found[choice] or found[1] or k - end - return k -end - -otf.getalternate = otf.getsubstitution - -function otf.getmultiple(tfmdata,k,kind) - local found, kind = getgsub(tfmdata,k,kind) - if found and kind == "gsub_multiple" then - return found - end - return { k } -end - -function otf.getkern(tfmdata,left,right,kind) - local kerns = getgsub(tfmdata,left,kind or "kern",true) -- for now we use getsub - if kerns then - local found = kerns[right] - local kind = type(found) - if kind == "table" then - found = found[1][3] -- can be more clever - elseif kind ~= "number" then - found = false - end - if found then - return found * tfmdata.parameters.factor - end - end - return 0 -end - -local function check_otf(forced,specification,suffix) - local name = specification.name - if forced then - name = specification.forcedname -- messy - end - local fullname = findbinfile(name,suffix) or "" - if fullname == "" then - fullname = fonts.names.getfilename(name,suffix) or "" - end - if fullname ~= "" and not fonts.names.ignoredfile(fullname) then - specification.filename = fullname - return read_from_otf(specification) - end -end - -local function opentypereader(specification,suffix) - local forced = specification.forced or "" - if formats[forced] then - return check_otf(true,specification,forced) - else - return check_otf(false,specification,suffix) - end -end - -readers.opentype = opentypereader -- kind of useless and obsolete - -function readers.otf(specification) return opentypereader(specification,"otf") end -function readers.ttf(specification) return opentypereader(specification,"ttf") end -function readers.ttc(specification) return opentypereader(specification,"ttf") end - -function readers.woff(specification) - checkconversion(specification) - opentypereader(specification,"") -end - --- this will be overloaded - -function otf.scriptandlanguage(tfmdata,attr) - local properties = tfmdata.properties - return properties.script or "dflt", properties.language or "dflt" -end - --- a little bit of abstraction - -local function justset(coverage,unicode,replacement) - coverage[unicode] = replacement -end - -otf.coverup = { - stepkey = "steps", - actions = { - chainsubstitution = justset, - chainposition = justset, - substitution = justset, - alternate = justset, - multiple = justset, - kern = justset, - pair = justset, - ligature = function(coverage,unicode,ligature) - local first = ligature[1] - local tree = coverage[first] - if not tree then - tree = { } - coverage[first] = tree - end - for i=2,#ligature do - local l = ligature[i] - local t = tree[l] - if not t then - t = { } - tree[l] = t - end - tree = t - end - tree.ligature = unicode - end, - }, - register = function(coverage,featuretype,format) - return { - format = format, - coverage = coverage, - } - end -} diff --git a/tex/compat/luaotfload/fontloader-font-oto.lua b/tex/compat/luaotfload/fontloader-font-oto.lua deleted file mode 100644 index 13568799b756e5e1d975ee31a502fd6b8a26b7bf..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/fontloader-font-oto.lua +++ /dev/null @@ -1,458 +0,0 @@ -if not modules then modules = { } end modules ['font-oto'] = { -- original tex - version = 1.001, - comment = "companion to font-ini.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- This is a version of font-otb adapted to the new fontloader code. We used to have two --- base initialization methods but now we have only one. This means that instead of the --- old default (independent) we now use the one more similar to node node (shared). - -local concat, unpack = table.concat, table.unpack -local insert, remove = table.insert, table.remove -local format, gmatch, gsub, find, match, lower, strip = string.format, string.gmatch, string.gsub, string.find, string.match, string.lower, string.strip -local type, next, tonumber, tostring, rawget = type, next, tonumber, tostring, rawget - -local trace_baseinit = false trackers.register("otf.baseinit", function(v) trace_baseinit = v end) -local trace_singles = false trackers.register("otf.singles", function(v) trace_singles = v end) -local trace_multiples = false trackers.register("otf.multiples", function(v) trace_multiples = v end) -local trace_alternatives = false trackers.register("otf.alternatives", function(v) trace_alternatives = v end) -local trace_ligatures = false trackers.register("otf.ligatures", function(v) trace_ligatures = v end) ------ trace_ligatures_detail = false trackers.register("otf.ligatures.detail", function(v) trace_ligatures_detail = v end) -local trace_kerns = false trackers.register("otf.kerns", function(v) trace_kerns = v end) -local trace_preparing = false trackers.register("otf.preparing", function(v) trace_preparing = v end) - -local report_prepare = logs.reporter("fonts","otf prepare") - -local fonts = fonts -local otf = fonts.handlers.otf - -local otffeatures = otf.features -local registerotffeature = otffeatures.register - -otf.defaultbasealternate = "none" -- first last - -local wildcard = "*" -local default = "dflt" - -local formatters = string.formatters -local f_unicode = formatters["%U"] -local f_uniname = formatters["%U (%s)"] -local f_unilist = formatters["% t (% t)"] - -local function gref(descriptions,n) - if type(n) == "number" then - local name = descriptions[n].name - if name then - return f_uniname(n,name) - else - return f_unicode(n) - end - elseif n then - local num, nam, j = { }, { }, 0 - for i=1,#n do - local ni = n[i] - if tonumber(ni) then -- first is likely a key - j = j + 1 - local di = descriptions[ni] - num[j] = f_unicode(ni) - nam[j] = di and di.name or "-" - end - end - return f_unilist(num,nam) - else - return "<error in base mode tracing>" - end -end - -local function cref(feature,sequence) - return formatters["feature %a, type %a, chain lookup %a"](feature,sequence.type,sequence.name) -end - - -local function report_alternate(feature,sequence,descriptions,unicode,replacement,value,comment) - report_prepare("%s: base alternate %s => %s (%S => %S)", - cref(feature,sequence), - gref(descriptions,unicode), - replacement and gref(descriptions,replacement), - value, - comment) -end - -local function report_substitution(feature,sequence,descriptions,unicode,substitution) - report_prepare("%s: base substitution %s => %S", - cref(feature,sequence), - gref(descriptions,unicode), - gref(descriptions,substitution)) -end - -local function report_ligature(feature,sequence,descriptions,unicode,ligature) - report_prepare("%s: base ligature %s => %S", - cref(feature,sequence), - gref(descriptions,ligature), - gref(descriptions,unicode)) -end - -local function report_kern(feature,sequence,descriptions,unicode,otherunicode,value) - report_prepare("%s: base kern %s + %s => %S", - cref(feature,sequence), - gref(descriptions,unicode), - gref(descriptions,otherunicode), - value) -end - --- We need to make sure that luatex sees the difference between base fonts that have --- different glyphs in the same slots in fonts that have the same fullname (or filename). --- LuaTeX will merge fonts eventually (and subset later on). If needed we can use a more --- verbose name as long as we don't use <()<>[]{}/%> and the length is < 128. - -local basehash, basehashes, applied = { }, 1, { } - -local function registerbasehash(tfmdata) - local properties = tfmdata.properties - local hash = concat(applied," ") - local base = basehash[hash] - if not base then - basehashes = basehashes + 1 - base = basehashes - basehash[hash] = base - end - properties.basehash = base - properties.fullname = (properties.fullname or properties.name) .. "-" .. base - -- report_prepare("fullname base hash '%a, featureset %a",tfmdata.properties.fullname,hash) - applied = { } -end - -local function registerbasefeature(feature,value) - applied[#applied+1] = feature .. "=" .. tostring(value) -end - --- The original basemode ligature builder used the names of components and did some expression --- juggling to get the chain right. The current variant starts with unicodes but still uses --- names to make the chain. This is needed because we have to create intermediates when needed --- but use predefined snippets when available. To some extend the current builder is more stupid --- but I don't worry that much about it as ligatures are rather predicatable. --- --- Personally I think that an ff + i == ffi rule as used in for instance latin modern is pretty --- weird as no sane person will key that in and expect a glyph for that ligature plus the following --- character. Anyhow, as we need to deal with this, we do, but no guarantes are given. --- --- latin modern dejavu --- --- f+f 102 102 102 102 --- f+i 102 105 102 105 --- f+l 102 108 102 108 --- f+f+i 102 102 105 --- f+f+l 102 102 108 102 102 108 --- ff+i 64256 105 64256 105 --- ff+l 64256 108 --- --- As you can see here, latin modern is less complete than dejavu but --- in practice one will not notice it. --- --- The while loop is needed because we need to resolve for instance pseudo names like --- hyphen_hyphen to endash so in practice we end up with a bit too many definitions but the --- overhead is neglectable. We can have changed[first] or changed[second] but it quickly becomes --- messy if we need to take that into account. - -local function makefake(tfmdata,name,present) - local resources = tfmdata.resources - local private = resources.private - local character = { intermediate = true, ligatures = { } } - resources.unicodes[name] = private - tfmdata.characters[private] = character - tfmdata.descriptions[private] = { name = name } - resources.private = private + 1 - present[name] = private - return character -end - -local function make_1(present,tree,name) - for k, v in next, tree do - if k == "ligature" then - present[name] = v - else - make_1(present,v,name .. "_" .. k) - end - end -end - -local function make_2(present,tfmdata,characters,tree,name,preceding,unicode,done) - for k, v in next, tree do - if k == "ligature" then - local character = characters[preceding] - if not character then - if trace_baseinit then - report_prepare("weird ligature in lookup %a, current %C, preceding %C",sequence.name,v,preceding) - end - character = makefake(tfmdata,name,present) - end - local ligatures = character.ligatures - if ligatures then - ligatures[unicode] = { char = v } - else - character.ligatures = { [unicode] = { char = v } } - end - if done then - local d = done[name] - if not d then - done[name] = { "dummy", v } - else - d[#d+1] = v - end - end - else - local code = present[name] or unicode - local name = name .. "_" .. k - make_2(present,tfmdata,characters,v,name,code,k,done) - end - end -end - -local function preparesubstitutions(tfmdata,feature,value,validlookups,lookuplist) - local characters = tfmdata.characters - local descriptions = tfmdata.descriptions - local resources = tfmdata.resources - local changed = tfmdata.changed - - local ligatures = { } - local alternate = tonumber(value) or true and 1 - local defaultalt = otf.defaultbasealternate - - local trace_singles = trace_baseinit and trace_singles - local trace_alternatives = trace_baseinit and trace_alternatives - local trace_ligatures = trace_baseinit and trace_ligatures - - if not changed then - changed = { } - tfmdata.changed = changed - end - - for i=1,#lookuplist do - local sequence = lookuplist[i] - local steps = sequence.steps - local kind = sequence.type - if kind == "gsub_single" then - for i=1,#steps do - for unicode, data in next, steps[i].coverage do - -- if not changed[unicode] then -- fails for multiple subs in some math fonts - if trace_singles then - report_substitution(feature,sequence,descriptions,unicode,data) - end - changed[unicode] = data - -- end - end - end - elseif kind == "gsub_alternate" then - for i=1,#steps do - for unicode, data in next, steps[i].coverage do - if not changed[unicode] then - local replacement = data[alternate] - if replacement then - changed[unicode] = replacement - if trace_alternatives then - report_alternate(feature,sequence,descriptions,unicode,replacement,value,"normal") - end - elseif defaultalt == "first" then - replacement = data[1] - changed[unicode] = replacement - if trace_alternatives then - report_alternate(feature,sequence,descriptions,unicode,replacement,value,defaultalt) - end - elseif defaultalt == "last" then - replacement = data[#data] - if trace_alternatives then - report_alternate(feature,sequence,descriptions,unicode,replacement,value,defaultalt) - end - else - if trace_alternatives then - report_alternate(feature,sequence,descriptions,unicode,replacement,value,"unknown") - end - end - end - end - end - elseif kind == "gsub_ligature" then - for i=1,#steps do - for unicode, data in next, steps[i].coverage do - ligatures[#ligatures+1] = { unicode, data, "" } -- lookupname } - if trace_ligatures then - report_ligature(feature,sequence,descriptions,unicode,data) - end - end - end - end - end - - local nofligatures = #ligatures - - if nofligatures > 0 then - - local characters = tfmdata.characters - local present = { } - local done = trace_baseinit and trace_ligatures and { } - - for i=1,nofligatures do - local ligature = ligatures[i] - local unicode, tree = ligature[1], ligature[2] - make_1(present,tree,"ctx_"..unicode) - end - - for i=1,nofligatures do - local ligature = ligatures[i] - local unicode, tree, lookupname = ligature[1], ligature[2], ligature[3] - make_2(present,tfmdata,characters,tree,"ctx_"..unicode,unicode,unicode,done,sequence) - end - - end - -end - -local function preparepositionings(tfmdata,feature,value,validlookups,lookuplist) - local characters = tfmdata.characters - local descriptions = tfmdata.descriptions - local resources = tfmdata.resources - local properties = tfmdata.properties - local traceindeed = trace_baseinit and trace_kerns - -- check out this sharedkerns trickery - for i=1,#lookuplist do - local sequence = lookuplist[i] - local steps = sequence.steps - local kind = sequence.type - local format = sequence.format - if kind == "gpos_pair" then - for i=1,#steps do - local step = steps[i] - if step.format == "kern" then - for unicode, data in next, steps[i].coverage do - local character = characters[unicode] - local kerns = character.kerns - if not kerns then - kerns = { } - character.kerns = kerns - end - if traceindeed then - for otherunicode, kern in next, data do - if not kerns[otherunicode] and kern ~= 0 then - kerns[otherunicode] = kern - report_kern(feature,sequence,descriptions,unicode,otherunicode,kern) - end - end - else - for otherunicode, kern in next, data do - if not kerns[otherunicode] and kern ~= 0 then - kerns[otherunicode] = kern - end - end - end - end - else - for unicode, data in next, steps[i].coverage do - local character = characters[unicode] - local kerns = character.kerns - for otherunicode, kern in next, data do - if not kern[2] and not (kerns and kerns[otherunicode]) then - local kern = kern[1] - if kern[1] ~= 0 or kern[2] ~= 0 or kern[4] ~= 0 then - -- a complex pair not suitable for basemode - else - kern = kern[3] - if kern ~= 0 then - if kerns then - kerns[otherunicode] = kern - else - kerns = { [otherunicode] = kern } - character.kerns = kerns - end - if traceindeed then - report_kern(feature,sequence,descriptions,unicode,otherunicode,kern) - end - end - end - end - end - end - end - end - end - end - -end - -local function initializehashes(tfmdata) - -- already done -end - -local function featuresinitializer(tfmdata,value) - if true then -- value then - local starttime = trace_preparing and os.clock() - local features = tfmdata.shared.features - local fullname = tfmdata.properties.fullname or "?" - if features then - initializehashes(tfmdata) - local collectlookups = otf.collectlookups - local rawdata = tfmdata.shared.rawdata - local properties = tfmdata.properties - local script = properties.script - local language = properties.language - local rawresources = rawdata.resources - local rawfeatures = rawresources and rawresources.features - local basesubstitutions = rawfeatures and rawfeatures.gsub - local basepositionings = rawfeatures and rawfeatures.gpos - -- - if basesubstitutions or basepositionings then - local sequences = tfmdata.resources.sequences - for s=1,#sequences do - local sequence = sequences[s] - local sfeatures = sequence.features - if sfeatures then - local order = sequence.order - if order then - for i=1,#order do -- - local feature = order[i] - local value = features[feature] - if value then - local validlookups, lookuplist = collectlookups(rawdata,feature,script,language) - if not validlookups then - -- skip - elseif basesubstitutions and basesubstitutions[feature] then - if trace_preparing then - report_prepare("filtering base %s feature %a for %a with value %a","sub",feature,fullname,value) - end - preparesubstitutions(tfmdata,feature,value,validlookups,lookuplist) - registerbasefeature(feature,value) - elseif basepositionings and basepositionings[feature] then - if trace_preparing then - report_prepare("filtering base %a feature %a for %a with value %a","pos",feature,fullname,value) - end - preparepositionings(tfmdata,feature,value,validlookups,lookuplist) - registerbasefeature(feature,value) - end - end - end - end - end - end - end - -- - registerbasehash(tfmdata) - end - if trace_preparing then - report_prepare("preparation time is %0.3f seconds for %a",os.clock()-starttime,fullname) - end - end -end - -registerotffeature { - name = "features", - description = "features", - default = true, - initializers = { - -- position = 1, -- after setscript (temp hack ... we need to force script / language to 1 - base = featuresinitializer, - } -} - -otf.basemodeinitializer = featuresinitializer diff --git a/tex/compat/luaotfload/fontloader-font-otr.lua b/tex/compat/luaotfload/fontloader-font-otr.lua deleted file mode 100644 index a9d3a8b29318f1416595316fd7fb55d20384c0b3..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/fontloader-font-otr.lua +++ /dev/null @@ -1,2309 +0,0 @@ -if not modules then modules = { } end modules ['font-otr'] = { - version = 1.001, - comment = "companion to font-ini.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- When looking into a cid font relates issue in the ff library I wondered if --- it made sense to use Lua to filter the information from the otf and ttf --- files. Quite some ff code relates to special fonts and in practice we only --- use rather normal opentype fonts. --- --- The code here is based on the documentation (and examples) at the microsoft --- website. The code will be extended and improved stepwise. After some experiments --- I decided to convert to a format more suitable for the context font handler --- because it makes no sense to rehash all those lookups again. --- --- Currently we can use this code for getting basic info about the font, loading --- shapes and loading the extensive table. I'm not sure if I will provide a ff --- compatible output as well (We're not that far from it as currently I can load --- all data reasonable fast.) - --- We can omit redundant glyphs names i.e. ones that match the agl or --- are just a unicode string but it doesn't save that much. It will be an option --- some day. - --- Optimizing the widths wil be done anyway as it save quite some on a cjk font --- and the existing (old) code if okay. - --- todo: more messages (only if really needed) --- --- considered, in math: --- --- start -> first (so we can skip the first same-size one) --- end -> last --- --- Widths and weights are kind of messy: for instance lmmonolt has a pfmweight of --- 400 while it should be 300. So, for now we mostly stick to the old compromis. - --- We don't really need all those language tables so they might be dropped some --- day. - --- The new reader is faster on some aspects and slower on other. The memory footprint --- is lower. The string reader is a bit faster than the file reader. The new reader --- gives more efficient tables and has bit more analysis. In practice these times are --- not that relevant because we cache. The otf files take a it more time because we --- need to calculate the boundingboxes. In theory the processing of text should be --- somewhat faster especially for complex fonts with many lookups. --- --- old new str reader --- lmroman12-regular.otf 0.103 0.203 0.195 --- latinmodern-math.otf 0.454 0.768 0.712 --- husayni.ttf 1.142 1.526 1.259 --- --- If there is demand I will consider making a ff compatible table dumper but it's --- probably more fun to provide a way to show features applied. - --- I experimented a bit with f:readbyte(n) and f:readshort() and so and it is indeed --- faster but it might not be the real bottleneck as we still need to juggle data. It --- is probably more memory efficient as no intermediate strings are involved. - --- if not characters then --- require("char-def") --- require("char-ini") --- end - -local next, type, unpack = next, type, unpack -local byte, lower, char, strip, gsub = string.byte, string.lower, string.char, string.strip, string.gsub -local bittest = bit32.btest -local concat, remove, unpack, fastcopy = table.concat, table.remov, table.unpack, table.fastcopy -local floor, abs, sqrt, round = math.floor, math.abs, math.sqrt, math.round -local P, R, S, C, Cs, Cc, Ct, Carg, Cmt = lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.Cs, lpeg.Cc, lpeg.Ct, lpeg.Carg, lpeg.Cmt -local lpegmatch = lpeg.match - -local setmetatableindex = table.setmetatableindex -local formatters = string.formatters -local sortedkeys = table.sortedkeys -local sortedhash = table.sortedhash -local stripstring = string.strip -local utf16_to_utf8_be = utf.utf16_to_utf8_be - -local report = logs.reporter("otf reader") - -local trace_cmap = false -- only for checking issues - -fonts = fonts or { } -local handlers = fonts.handlers or { } -fonts.handlers = handlers -local otf = handlers.otf or { } -handlers.otf = otf -local readers = otf.readers or { } -otf.readers = readers - ------ streamreader = utilities.streams -- faster on big files -local streamreader = utilities.files -- faster on identify -local streamwriter = utilities.files - -readers.streamreader = streamreader -readers.streamwriter = streamwriter - -local openfile = streamreader.open -local closefile = streamreader.close ------ skipbytes = streamreader.skip -local setposition = streamreader.setposition -local skipshort = streamreader.skipshort -local readbytes = streamreader.readbytes -local readstring = streamreader.readstring -local readbyte = streamreader.readcardinal1 -- 8-bit unsigned integer -local readushort = streamreader.readcardinal2 -- 16-bit unsigned integer -local readuint = streamreader.readcardinal3 -- 24-bit unsigned integer -local readulong = streamreader.readcardinal4 -- 24-bit unsigned integer ------ readchar = streamreader.readinteger1 -- 8-bit signed integer -local readshort = streamreader.readinteger2 -- 16-bit signed integer -local readlong = streamreader.readinteger4 -- 24-bit unsigned integer -local readfixed = streamreader.readfixed4 -local readfword = readshort -- 16-bit signed integer that describes a quantity in FUnits -local readufword = readushort -- 16-bit unsigned integer that describes a quantity in FUnits -local readoffset = readushort -local read2dot14 = streamreader.read2dot14 -- 16-bit signed fixed number with the low 14 bits of fraction (2.14) (F2DOT14) - -function streamreader.readtag(f) - return lower(strip(readstring(f,4))) -end - --- date represented in number of seconds since 12:00 midnight, January 1, 1904. The value is represented as a --- signed 64-bit integer - -local function readlongdatetime(f) - local a, b, c, d, e, f, g, h = readbytes(f,8) - return 0x100000000 * d + 0x1000000 * e + 0x10000 * f + 0x100 * g + h -end - -local tableversion = 0.004 -readers.tableversion = tableversion -local privateoffset = fonts.constructors and fonts.constructors.privateoffset or 0xF0000 -- 0x10FFFF -local reportedskipped = { } - - -local function reportskippedtable(tag) - if not reportedskipped[tag] then - report("loading of table %a skipped (reported once only)",tag) - reportedskipped[tag] = true - end -end - --- We have quite some data tables. We are somewhat ff compatible with names but as I used --- the information from the microsoft site there can be differences. Eventually I might end --- up with a different ordering and naming. - -local reservednames = { [0] = - "copyright", - "family", - "subfamily", - "uniqueid", - "fullname", - "version", - "postscriptname", - "trademark", - "manufacturer", - "designer", - "description", -- descriptor in ff - "vendorurl", - "designerurl", - "license", - "licenseurl", - "reserved", - "typographicfamily", -- preffamilyname - "typographicsubfamily", -- prefmodifiers - "compatiblefullname", -- for mac - "sampletext", - "cidfindfontname", - "wwsfamily", - "wwssubfamily", - "lightbackgroundpalette", - "darkbackgroundpalette", -} - --- more at: https://www.microsoft.com/typography/otspec/name.htm - --- setmetatableindex(reservednames,function(t,k) --- local v = "name_" .. k --- t[k] = v --- return v --- end) - -local platforms = { [0] = - "unicode", - "macintosh", - "iso", - "windows", - "custom", -} - -local encodings = { - -- these stay: - unicode = { [0] = - "unicode 1.0 semantics", - "unicode 1.1 semantics", - "iso/iec 10646", - "unicode 2.0 bmp", -- cmap subtable formats 0, 4, 6 - "unicode 2.0 full", -- cmap subtable formats 0, 4, 6, 10, 12 - "unicode variation sequences", -- cmap subtable format 14). - "unicode full repertoire", -- cmap subtable formats 0, 4, 6, 10, 12, 13 - }, - -- these can go: - macintosh = { [0] = - "roman", "japanese", "chinese (traditional)", "korean", "arabic", "hebrew", "greek", "russian", - "rsymbol", "devanagari", "gurmukhi", "gujarati", "oriya", "bengali", "tamil", "telugu", "kannada", - "malayalam", "sinhalese", "burmese", "khmer", "thai", "laotian", "georgian", "armenian", - "chinese (simplified)", "tibetan", "mongolian", "geez", "slavic", "vietnamese", "sindhi", - "uninterpreted", - }, - -- these stay: - iso = { [0] = - "7-bit ascii", - "iso 10646", - "iso 8859-1", - }, - -- these stay: - windows = { [0] = - "symbol", - "unicode bmp", -- this is utf16 - "shiftjis", - "prc", - "big5", - "wansung", - "johab", - "reserved 7", - "reserved 8", - "reserved 9", - "unicode ucs-4", - }, - custom = { - --custom: 0-255 : otf windows nt compatibility mapping - } -} - -local decoders = { - unicode = { }, - macintosh = { }, - iso = { }, - windows = { - -- maybe always utf16 - ["unicode semantics"] = utf16_to_utf8_be, - ["unicode bmp"] = utf16_to_utf8_be, - ["unicode full"] = utf16_to_utf8_be, - ["unicode 1.0 semantics"] = utf16_to_utf8_be, - ["unicode 1.1 semantics"] = utf16_to_utf8_be, - ["unicode 2.0 bmp"] = utf16_to_utf8_be, - ["unicode 2.0 full"] = utf16_to_utf8_be, - ["unicode variation sequences"] = utf16_to_utf8_be, - ["unicode full repertoire"] = utf16_to_utf8_be, - }, - custom = { }, -} - --- This is bit over the top as we can just look for either windows, unicode or macintosh --- names (in that order). A font with no english name is probably a weird one anyway. - -local languages = { - -- these stay: - unicode = { - [ 0] = "english", - }, - -- english can stay: - macintosh = { - [ 0] = "english", - -- [ 1] = "french", - -- [ 2] = "german", - -- [ 3] = "italian", - -- [ 4] = "dutch", - -- [ 5] = "swedish", - -- [ 6] = "spanish", - -- [ 7] = "danish", - -- [ 8] = "portuguese", - -- [ 9] = "norwegian", - -- [ 10] = "hebrew", - -- [ 11] = "japanese", - -- [ 12] = "arabic", - -- [ 13] = "finnish", - -- [ 14] = "greek", - -- [ 15] = "icelandic", - -- [ 16] = "maltese", - -- [ 17] = "turkish", - -- [ 18] = "croatian", - -- [ 19] = "chinese (traditional)", - -- [ 20] = "urdu", - -- [ 21] = "hindi", - -- [ 22] = "thai", - -- [ 23] = "korean", - -- [ 24] = "lithuanian", - -- [ 25] = "polish", - -- [ 26] = "hungarian", - -- [ 27] = "estonian", - -- [ 28] = "latvian", - -- [ 29] = "sami", - -- [ 30] = "faroese", - -- [ 31] = "farsi/persian", - -- [ 32] = "russian", - -- [ 33] = "chinese (simplified)", - -- [ 34] = "flemish", - -- [ 35] = "irish gaelic", - -- [ 36] = "albanian", - -- [ 37] = "romanian", - -- [ 38] = "czech", - -- [ 39] = "slovak", - -- [ 40] = "slovenian", - -- [ 41] = "yiddish", - -- [ 42] = "serbian", - -- [ 43] = "macedonian", - -- [ 44] = "bulgarian", - -- [ 45] = "ukrainian", - -- [ 46] = "byelorussian", - -- [ 47] = "uzbek", - -- [ 48] = "kazakh", - -- [ 49] = "azerbaijani (cyrillic script)", - -- [ 50] = "azerbaijani (arabic script)", - -- [ 51] = "armenian", - -- [ 52] = "georgian", - -- [ 53] = "moldavian", - -- [ 54] = "kirghiz", - -- [ 55] = "tajiki", - -- [ 56] = "turkmen", - -- [ 57] = "mongolian (mongolian script)", - -- [ 58] = "mongolian (cyrillic script)", - -- [ 59] = "pashto", - -- [ 60] = "kurdish", - -- [ 61] = "kashmiri", - -- [ 62] = "sindhi", - -- [ 63] = "tibetan", - -- [ 64] = "nepali", - -- [ 65] = "sanskrit", - -- [ 66] = "marathi", - -- [ 67] = "bengali", - -- [ 68] = "assamese", - -- [ 69] = "gujarati", - -- [ 70] = "punjabi", - -- [ 71] = "oriya", - -- [ 72] = "malayalam", - -- [ 73] = "kannada", - -- [ 74] = "tamil", - -- [ 75] = "telugu", - -- [ 76] = "sinhalese", - -- [ 77] = "burmese", - -- [ 78] = "khmer", - -- [ 79] = "lao", - -- [ 80] = "vietnamese", - -- [ 81] = "indonesian", - -- [ 82] = "tagalong", - -- [ 83] = "malay (roman script)", - -- [ 84] = "malay (arabic script)", - -- [ 85] = "amharic", - -- [ 86] = "tigrinya", - -- [ 87] = "galla", - -- [ 88] = "somali", - -- [ 89] = "swahili", - -- [ 90] = "kinyarwanda/ruanda", - -- [ 91] = "rundi", - -- [ 92] = "nyanja/chewa", - -- [ 93] = "malagasy", - -- [ 94] = "esperanto", - -- [128] = "welsh", - -- [129] = "basque", - -- [130] = "catalan", - -- [131] = "latin", - -- [132] = "quenchua", - -- [133] = "guarani", - -- [134] = "aymara", - -- [135] = "tatar", - -- [136] = "uighur", - -- [137] = "dzongkha", - -- [138] = "javanese (roman script)", - -- [139] = "sundanese (roman script)", - -- [140] = "galician", - -- [141] = "afrikaans", - -- [142] = "breton", - -- [143] = "inuktitut", - -- [144] = "scottish gaelic", - -- [145] = "manx gaelic", - -- [146] = "irish gaelic (with dot above)", - -- [147] = "tongan", - -- [148] = "greek (polytonic)", - -- [149] = "greenlandic", - -- [150] = "azerbaijani (roman script)", - }, - -- these can stay: - iso = { - }, - -- english can stay: - windows = { - -- [0x0436] = "afrikaans - south africa", - -- [0x041c] = "albanian - albania", - -- [0x0484] = "alsatian - france", - -- [0x045e] = "amharic - ethiopia", - -- [0x1401] = "arabic - algeria", - -- [0x3c01] = "arabic - bahrain", - -- [0x0c01] = "arabic - egypt", - -- [0x0801] = "arabic - iraq", - -- [0x2c01] = "arabic - jordan", - -- [0x3401] = "arabic - kuwait", - -- [0x3001] = "arabic - lebanon", - -- [0x1001] = "arabic - libya", - -- [0x1801] = "arabic - morocco", - -- [0x2001] = "arabic - oman", - -- [0x4001] = "arabic - qatar", - -- [0x0401] = "arabic - saudi arabia", - -- [0x2801] = "arabic - syria", - -- [0x1c01] = "arabic - tunisia", - -- [0x3801] = "arabic - u.a.e.", - -- [0x2401] = "arabic - yemen", - -- [0x042b] = "armenian - armenia", - -- [0x044d] = "assamese - india", - -- [0x082c] = "azeri (cyrillic) - azerbaijan", - -- [0x042c] = "azeri (latin) - azerbaijan", - -- [0x046d] = "bashkir - russia", - -- [0x042d] = "basque - basque", - -- [0x0423] = "belarusian - belarus", - -- [0x0845] = "bengali - bangladesh", - -- [0x0445] = "bengali - india", - -- [0x201a] = "bosnian (cyrillic) - bosnia and herzegovina", - -- [0x141a] = "bosnian (latin) - bosnia and herzegovina", - -- [0x047e] = "breton - france", - -- [0x0402] = "bulgarian - bulgaria", - -- [0x0403] = "catalan - catalan", - -- [0x0c04] = "chinese - hong kong s.a.r.", - -- [0x1404] = "chinese - macao s.a.r.", - -- [0x0804] = "chinese - people's republic of china", - -- [0x1004] = "chinese - singapore", - -- [0x0404] = "chinese - taiwan", - -- [0x0483] = "corsican - france", - -- [0x041a] = "croatian - croatia", - -- [0x101a] = "croatian (latin) - bosnia and herzegovina", - -- [0x0405] = "czech - czech republic", - -- [0x0406] = "danish - denmark", - -- [0x048c] = "dari - afghanistan", - -- [0x0465] = "divehi - maldives", - -- [0x0813] = "dutch - belgium", - -- [0x0413] = "dutch - netherlands", - -- [0x0c09] = "english - australia", - -- [0x2809] = "english - belize", - -- [0x1009] = "english - canada", - -- [0x2409] = "english - caribbean", - -- [0x4009] = "english - india", - -- [0x1809] = "english - ireland", - -- [0x2009] = "english - jamaica", - -- [0x4409] = "english - malaysia", - -- [0x1409] = "english - new zealand", - -- [0x3409] = "english - republic of the philippines", - -- [0x4809] = "english - singapore", - -- [0x1c09] = "english - south africa", - -- [0x2c09] = "english - trinidad and tobago", - -- [0x0809] = "english - united kingdom", - [0x0409] = "english - united states", - -- [0x3009] = "english - zimbabwe", - -- [0x0425] = "estonian - estonia", - -- [0x0438] = "faroese - faroe islands", - -- [0x0464] = "filipino - philippines", - -- [0x040b] = "finnish - finland", - -- [0x080c] = "french - belgium", - -- [0x0c0c] = "french - canada", - -- [0x040c] = "french - france", - -- [0x140c] = "french - luxembourg", - -- [0x180c] = "french - principality of monoco", - -- [0x100c] = "french - switzerland", - -- [0x0462] = "frisian - netherlands", - -- [0x0456] = "galician - galician", - -- [0x0437] = "georgian -georgia", - -- [0x0c07] = "german - austria", - -- [0x0407] = "german - germany", - -- [0x1407] = "german - liechtenstein", - -- [0x1007] = "german - luxembourg", - -- [0x0807] = "german - switzerland", - -- [0x0408] = "greek - greece", - -- [0x046f] = "greenlandic - greenland", - -- [0x0447] = "gujarati - india", - -- [0x0468] = "hausa (latin) - nigeria", - -- [0x040d] = "hebrew - israel", - -- [0x0439] = "hindi - india", - -- [0x040e] = "hungarian - hungary", - -- [0x040f] = "icelandic - iceland", - -- [0x0470] = "igbo - nigeria", - -- [0x0421] = "indonesian - indonesia", - -- [0x045d] = "inuktitut - canada", - -- [0x085d] = "inuktitut (latin) - canada", - -- [0x083c] = "irish - ireland", - -- [0x0434] = "isixhosa - south africa", - -- [0x0435] = "isizulu - south africa", - -- [0x0410] = "italian - italy", - -- [0x0810] = "italian - switzerland", - -- [0x0411] = "japanese - japan", - -- [0x044b] = "kannada - india", - -- [0x043f] = "kazakh - kazakhstan", - -- [0x0453] = "khmer - cambodia", - -- [0x0486] = "k'iche - guatemala", - -- [0x0487] = "kinyarwanda - rwanda", - -- [0x0441] = "kiswahili - kenya", - -- [0x0457] = "konkani - india", - -- [0x0412] = "korean - korea", - -- [0x0440] = "kyrgyz - kyrgyzstan", - -- [0x0454] = "lao - lao p.d.r.", - -- [0x0426] = "latvian - latvia", - -- [0x0427] = "lithuanian - lithuania", - -- [0x082e] = "lower sorbian - germany", - -- [0x046e] = "luxembourgish - luxembourg", - -- [0x042f] = "macedonian (fyrom) - former yugoslav republic of macedonia", - -- [0x083e] = "malay - brunei darussalam", - -- [0x043e] = "malay - malaysia", - -- [0x044c] = "malayalam - india", - -- [0x043a] = "maltese - malta", - -- [0x0481] = "maori - new zealand", - -- [0x047a] = "mapudungun - chile", - -- [0x044e] = "marathi - india", - -- [0x047c] = "mohawk - mohawk", - -- [0x0450] = "mongolian (cyrillic) - mongolia", - -- [0x0850] = "mongolian (traditional) - people's republic of china", - -- [0x0461] = "nepali - nepal", - -- [0x0414] = "norwegian (bokmal) - norway", - -- [0x0814] = "norwegian (nynorsk) - norway", - -- [0x0482] = "occitan - france", - -- [0x0448] = "odia (formerly oriya) - india", - -- [0x0463] = "pashto - afghanistan", - -- [0x0415] = "polish - poland", - -- [0x0416] = "portuguese - brazil", - -- [0x0816] = "portuguese - portugal", - -- [0x0446] = "punjabi - india", - -- [0x046b] = "quechua - bolivia", - -- [0x086b] = "quechua - ecuador", - -- [0x0c6b] = "quechua - peru", - -- [0x0418] = "romanian - romania", - -- [0x0417] = "romansh - switzerland", - -- [0x0419] = "russian - russia", - -- [0x243b] = "sami (inari) - finland", - -- [0x103b] = "sami (lule) - norway", - -- [0x143b] = "sami (lule) - sweden", - -- [0x0c3b] = "sami (northern) - finland", - -- [0x043b] = "sami (northern) - norway", - -- [0x083b] = "sami (northern) - sweden", - -- [0x203b] = "sami (skolt) - finland", - -- [0x183b] = "sami (southern) - norway", - -- [0x1c3b] = "sami (southern) - sweden", - -- [0x044f] = "sanskrit - india", - -- [0x1c1a] = "serbian (cyrillic) - bosnia and herzegovina", - -- [0x0c1a] = "serbian (cyrillic) - serbia", - -- [0x181a] = "serbian (latin) - bosnia and herzegovina", - -- [0x081a] = "serbian (latin) - serbia", - -- [0x046c] = "sesotho sa leboa - south africa", - -- [0x0432] = "setswana - south africa", - -- [0x045b] = "sinhala - sri lanka", - -- [0x041b] = "slovak - slovakia", - -- [0x0424] = "slovenian - slovenia", - -- [0x2c0a] = "spanish - argentina", - -- [0x400a] = "spanish - bolivia", - -- [0x340a] = "spanish - chile", - -- [0x240a] = "spanish - colombia", - -- [0x140a] = "spanish - costa rica", - -- [0x1c0a] = "spanish - dominican republic", - -- [0x300a] = "spanish - ecuador", - -- [0x440a] = "spanish - el salvador", - -- [0x100a] = "spanish - guatemala", - -- [0x480a] = "spanish - honduras", - -- [0x080a] = "spanish - mexico", - -- [0x4c0a] = "spanish - nicaragua", - -- [0x180a] = "spanish - panama", - -- [0x3c0a] = "spanish - paraguay", - -- [0x280a] = "spanish - peru", - -- [0x500a] = "spanish - puerto rico", - -- [0x0c0a] = "spanish (modern sort) - spain", - -- [0x040a] = "spanish (traditional sort) - spain", - -- [0x540a] = "spanish - united states", - -- [0x380a] = "spanish - uruguay", - -- [0x200a] = "spanish - venezuela", - -- [0x081d] = "sweden - finland", - -- [0x041d] = "swedish - sweden", - -- [0x045a] = "syriac - syria", - -- [0x0428] = "tajik (cyrillic) - tajikistan", - -- [0x085f] = "tamazight (latin) - algeria", - -- [0x0449] = "tamil - india", - -- [0x0444] = "tatar - russia", - -- [0x044a] = "telugu - india", - -- [0x041e] = "thai - thailand", - -- [0x0451] = "tibetan - prc", - -- [0x041f] = "turkish - turkey", - -- [0x0442] = "turkmen - turkmenistan", - -- [0x0480] = "uighur - prc", - -- [0x0422] = "ukrainian - ukraine", - -- [0x042e] = "upper sorbian - germany", - -- [0x0420] = "urdu - islamic republic of pakistan", - -- [0x0843] = "uzbek (cyrillic) - uzbekistan", - -- [0x0443] = "uzbek (latin) - uzbekistan", - -- [0x042a] = "vietnamese - vietnam", - -- [0x0452] = "welsh - united kingdom", - -- [0x0488] = "wolof - senegal", - -- [0x0485] = "yakut - russia", - -- [0x0478] = "yi - prc", - -- [0x046a] = "yoruba - nigeria", - }, - custom = { - }, -} - -local standardromanencoding = { [0] = -- taken from wikipedia - "notdef", ".null", "nonmarkingreturn", "space", "exclam", "quotedbl", - "numbersign", "dollar", "percent", "ampersand", "quotesingle", "parenleft", - "parenright", "asterisk", "plus", "comma", "hyphen", "period", "slash", - "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", - "nine", "colon", "semicolon", "less", "equal", "greater", "question", "at", - "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", - "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "bracketleft", - "backslash", "bracketright", "asciicircum", "underscore", "grave", "a", "b", - "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", - "r", "s", "t", "u", "v", "w", "x", "y", "z", "braceleft", "bar", - "braceright", "asciitilde", "Adieresis", "Aring", "Ccedilla", "Eacute", - "Ntilde", "Odieresis", "Udieresis", "aacute", "agrave", "acircumflex", - "adieresis", "atilde", "aring", "ccedilla", "eacute", "egrave", - "ecircumflex", "edieresis", "iacute", "igrave", "icircumflex", "idieresis", - "ntilde", "oacute", "ograve", "ocircumflex", "odieresis", "otilde", "uacute", - "ugrave", "ucircumflex", "udieresis", "dagger", "degree", "cent", "sterling", - "section", "bullet", "paragraph", "germandbls", "registered", "copyright", - "trademark", "acute", "dieresis", "notequal", "AE", "Oslash", "infinity", - "plusminus", "lessequal", "greaterequal", "yen", "mu", "partialdiff", - "summation", "product", "pi", "integral", "ordfeminine", "ordmasculine", - "Omega", "ae", "oslash", "questiondown", "exclamdown", "logicalnot", - "radical", "florin", "approxequal", "Delta", "guillemotleft", - "guillemotright", "ellipsis", "nonbreakingspace", "Agrave", "Atilde", - "Otilde", "OE", "oe", "endash", "emdash", "quotedblleft", "quotedblright", - "quoteleft", "quoteright", "divide", "lozenge", "ydieresis", "Ydieresis", - "fraction", "currency", "guilsinglleft", "guilsinglright", "fi", "fl", - "daggerdbl", "periodcentered", "quotesinglbase", "quotedblbase", - "perthousand", "Acircumflex", "Ecircumflex", "Aacute", "Edieresis", "Egrave", - "Iacute", "Icircumflex", "Idieresis", "Igrave", "Oacute", "Ocircumflex", - "apple", "Ograve", "Uacute", "Ucircumflex", "Ugrave", "dotlessi", - "circumflex", "tilde", "macron", "breve", "dotaccent", "ring", "cedilla", - "hungarumlaut", "ogonek", "caron", "Lslash", "lslash", "Scaron", "scaron", - "Zcaron", "zcaron", "brokenbar", "Eth", "eth", "Yacute", "yacute", "Thorn", - "thorn", "minus", "multiply", "onesuperior", "twosuperior", "threesuperior", - "onehalf", "onequarter", "threequarters", "franc", "Gbreve", "gbreve", - "Idotaccent", "Scedilla", "scedilla", "Cacute", "cacute", "Ccaron", "ccaron", - "dcroat", -} - -local weights = { - [100] = "thin", - [200] = "extralight", - [300] = "light", - [400] = "normal", - [500] = "medium", - [600] = "semibold", -- demi demibold - [700] = "bold", - [800] = "extrabold", - [900] = "black", -} - -local widths = { - [1] = "ultracondensed", - [2] = "extracondensed", - [3] = "condensed", - [4] = "semicondensed", - [5] = "normal", - [6] = "semiexpanded", - [7] = "expanded", - [8] = "extraexpanded", - [9] = "ultraexpanded", -} - -setmetatableindex(weights, function(t,k) - local r = floor((k + 50) / 100) * 100 - local v = (r > 900 and "black") or rawget(t,r) or "normal" --- print("weight:",k,r,v) - return v -end) - -setmetatableindex(widths,function(t,k) --- print("width:",k) - return "normal" -end) - -local panoseweights = { - [ 0] = "normal", - [ 1] = "normal", - [ 2] = "verylight", - [ 3] = "light", - [ 4] = "thin", - [ 5] = "book", - [ 6] = "medium", - [ 7] = "demi", - [ 8] = "bold", - [ 9] = "heavy", - [10] = "black", -} - -local panosewidths = { - [ 0] = "normal", - [ 1] = "normal", - [ 2] = "normal", - [ 3] = "normal", - [ 4] = "normal", - [ 5] = "expanded", - [ 6] = "condensed", - [ 7] = "veryexpanded", - [ 8] = "verycondensed", - [ 9] = "monospaced", -} - --- We implement a reader per table. - --- The name table is probably the first one to load. After all this one provides --- useful information about what we deal with. The complication is that we need --- to filter the best one available. - -local platformnames = { - postscriptname = true, - fullname = true, - family = true, - subfamily = true, - typographicfamily = true, - typographicsubfamily = true, - compatiblefullname = true, -} - -function readers.name(f,fontdata,specification) - local datatable = fontdata.tables.name - if datatable then - setposition(f,datatable.offset) - local format = readushort(f) - local nofnames = readushort(f) - local offset = readushort(f) - -- we can also provide a raw list as extra, todo as option - local start = datatable.offset + offset - local namelists = { - unicode = { }, - windows = { }, - macintosh = { }, - -- iso = { }, - -- windows = { }, - } - for i=1,nofnames do - local platform = platforms[readushort(f)] - if platform then - local namelist = namelists[platform] - if namelist then - local encoding = readushort(f) - local language = readushort(f) - local encodings = encodings[platform] - local languages = languages[platform] - if encodings and languages then - local encoding = encodings[encoding] - local language = languages[language] - if encoding and language then - local name = reservednames[readushort(f)] - if name then - namelist[#namelist+1] = { - platform = platform, - encoding = encoding, - language = language, - name = name, - length = readushort(f), - offset = start + readushort(f), - } - else - skipshort(f,2) - end - else - skipshort(f,3) - end - else - skipshort(f,3) - end - else - skipshort(f,5) - end - else - skipshort(f,5) - end - end - -- if format == 1 then - -- local noftags = readushort(f) - -- for i=1,noftags do - -- local length = readushort(f) - -- local offset = readushort(f) - -- end - -- end - -- - -- we need to choose one we like, for instance an unicode one - -- - local names = { } - local done = { } - -- - -- there is quite some logic in ff ... hard to follow so we start simple - -- and extend when we run into it (todo: proper reverse hash) .. we're only - -- interested in english anyway - -- - local function filter(platform,e,l) - local namelist = namelists[platform] - for i=1,#namelist do - local name = namelist[i] - local nametag = name.name - if not done[nametag] then - local encoding = name.encoding - local language = name.language - if (not e or encoding == e) and (not l or language == l) then - setposition(f,name.offset) - local content = readstring(f,name.length) - local decoder = decoders[platform] - if decoder then - decoder = decoder[encoding] - end - if decoder then - content = decoder(content) - end - names[nametag] = { - content = content, - platform = platform, - encoding = encoding, - language = language, - } - done[nametag] = true - end - end - end - end - -- - filter("windows","unicode bmp","english - united states") - -- filter("unicode") -- which one ? - filter("macintosh","roman","english") - filter("windows") - filter("macintosh") - filter("unicode") - -- - fontdata.names = names - -- - if specification.platformnames then - local collected = { } - for platform, namelist in next, namelists do - local filtered = false - for i=1,#namelist do - local entry = namelist[i] - local name = entry.name - if platformnames[name] then - setposition(f,entry.offset) - local content = readstring(f,entry.length) - local encoding = entry.encoding - local decoder = decoders[platform] - if decoder then - decoder = decoder[encoding] - end - if decoder then - content = decoder(content) - end - if filtered then - filtered[name] = content - else - filtered = { [name] = content } - end - end - end - if filtered then - collected[platform] = filtered - end - end - fontdata.platformnames = collected - end - else - fontdata.names = { } - end -end - ------ validutf = lpeg.patterns.utf8character^0 * P(-1) -local validutf = lpeg.patterns.validutf8 - -local function getname(fontdata,key) - local names = fontdata.names - if names then - local value = names[key] - if value then - local content = value.content - return lpegmatch(validutf,content) and content or nil - end - end -end - --- This table is an original windows (with its precursor os/2) table. In ff this one is --- part of the pfminfo table but here we keep it separate (for now). We will create a --- properties table afterwards. - -readers["os/2"] = function(f,fontdata) - local datatable = fontdata.tables["os/2"] - if datatable then - setposition(f,datatable.offset) - local version = readushort(f) - local windowsmetrics = { - version = version, - averagewidth = readshort(f), - weightclass = readushort(f), - widthclass = readushort(f), - fstype = readushort(f), - subscriptxsize = readshort(f), - subscriptysize = readshort(f), - subscriptxoffset = readshort(f), - subscriptyoffset = readshort(f), - superscriptxsize = readshort(f), - superscriptysize = readshort(f), - superscriptxoffset = readshort(f), - superscriptyoffset = readshort(f), - strikeoutsize = readshort(f), - strikeoutpos = readshort(f), - familyclass = readshort(f), - panose = { readbytes(f,10) }, - unicoderanges = { readulong(f), readulong(f), readulong(f), readulong(f) }, - vendor = readstring(f,4), - fsselection = readushort(f), - firstcharindex = readushort(f), - lastcharindex = readushort(f), - typoascender = readshort(f), - typodescender = readshort(f), - typolinegap = readshort(f), - winascent = readushort(f), - windescent = readushort(f), - } - if version >= 1 then - windowsmetrics.codepageranges = { readulong(f), readulong(f) } - end - if version >= 3 then - windowsmetrics.xheight = readshort(f) - windowsmetrics.capheight = readshort(f) - windowsmetrics.defaultchar = readushort(f) - windowsmetrics.breakchar = readushort(f) - -- windowsmetrics.maxcontexts = readushort(f) - -- windowsmetrics.loweropticalpointsize = readushort(f) - -- windowsmetrics.upperopticalpointsize = readushort(f) - end - -- - -- todo: unicoderanges - -- - windowsmetrics.weight = windowsmetrics.weightclass and weights[windowsmetrics.weightclass] - windowsmetrics.width = windowsmetrics.widthclass and widths [windowsmetrics.widthclass] - -- - windowsmetrics.panoseweight = panoseweights[windowsmetrics.panose[3]] - windowsmetrics.panosewidth = panosewidths [windowsmetrics.panose[4]] - -- - fontdata.windowsmetrics = windowsmetrics - else - fontdata.windowsmetrics = { } - end -end - -readers.head = function(f,fontdata) - local datatable = fontdata.tables.head - if datatable then - setposition(f,datatable.offset) - local fontheader = { - version = readfixed(f), - revision = readfixed(f), - checksum = readulong(f), - magic = readulong(f), - flags = readushort(f), - units = readushort(f), - created = readlongdatetime(f), - modified = readlongdatetime(f), - xmin = readshort(f), - ymin = readshort(f), - xmax = readshort(f), - ymax = readshort(f), - macstyle = readushort(f), - smallpixels = readushort(f), - directionhint = readshort(f), - indextolocformat = readshort(f), - glyphformat = readshort(f), - } - fontdata.fontheader = fontheader - else - fontdata.fontheader = { } - end - fontdata.nofglyphs = 0 -end - --- This table is a rather simple one. No treatment of values is needed here. Most --- variables are not used but nofmetrics is quite important. - -readers.hhea = function(f,fontdata,specification) - if specification.details then - local datatable = fontdata.tables.hhea - if datatable then - setposition(f,datatable.offset) - fontdata.horizontalheader = { - version = readfixed(f), -- two ushorts: major minor - ascender = readfword(f), - descender = readfword(f), - linegap = readfword(f), - maxadvancewidth = readufword(f), - minleftsidebearing = readfword(f), - minrightsidebearing = readfword(f), - maxextent = readfword(f), - caretsloperise = readshort(f), - caretsloperun = readshort(f), - caretoffset = readshort(f), - reserved_1 = readshort(f), - reserved_2 = readshort(f), - reserved_3 = readshort(f), - reserved_4 = readshort(f), - metricdataformat = readshort(f), - nofmetrics = readushort(f), - } - else - fontdata.horizontalheader = { - nofmetrics = 0, - } - end - end -end - -readers.vhea = function(f,fontdata,specification) - if specification.details then - local datatable = fontdata.tables.vhea - if datatable then - setposition(f,datatable.offset) - local version = readfixed(f) - fontdata.verticalheader = { - version = version, - ascender = readfword(f), - descender = readfword(f), - linegap = readfword(f), - maxadvanceheight = readufword(f), - mintopsidebearing = readfword(f), - minbottomsidebearing = readfword(f), - maxextent = readfword(f), - caretsloperise = readshort(f), - caretsloperun = readshort(f), - caretoffset = readshort(f), - reserved_1 = readshort(f), - reserved_2 = readshort(f), - reserved_3 = readshort(f), - reserved_4 = readshort(f), - metricdataformat = readshort(f), - nofmetrics = readushort(f), - } --- inspect(fontdata.verticalheader) - else - fontdata.verticalheader = { - nofmetrics = 0, - } - end - end -end - --- We probably never need all these variables, but we do need the nofglyphs when loading other --- tables. Again we use the microsoft names but see no reason to have "max" in each name. - --- fontdata.maximumprofile can be bad - -readers.maxp = function(f,fontdata,specification) - if specification.details then - local datatable = fontdata.tables.maxp - if datatable then - setposition(f,datatable.offset) - local version = readfixed(f) - local nofglyphs = readushort(f) - fontdata.nofglyphs = nofglyphs - if version == 0.5 then - fontdata.maximumprofile = { - version = version, - nofglyphs = nofglyphs, - } - return - elseif version == 1.0 then - fontdata.maximumprofile = { - version = version, - nofglyphs = nofglyphs, - points = readushort(f), - contours = readushort(f), - compositepoints = readushort(f), - compositecontours = readushort(f), - zones = readushort(f), - twilightpoints = readushort(f), - storage = readushort(f), - functiondefs = readushort(f), - instructiondefs = readushort(f), - stackelements = readushort(f), - sizeofinstructions = readushort(f), - componentelements = readushort(f), - componentdepth = readushort(f), - } - return - end - end - fontdata.maximumprofile = { - version = version, - nofglyphs = 0, - } - end -end - --- Here we filter the (advance) widths (that can be different from the boundingbox width of --- course). - -readers.hmtx = function(f,fontdata,specification) - if specification.glyphs then - local datatable = fontdata.tables.hmtx - if datatable then - setposition(f,datatable.offset) - local horizontalheader = fontdata.horizontalheader - local nofmetrics = horizontalheader.nofmetrics - local glyphs = fontdata.glyphs - local nofglyphs = fontdata.nofglyphs - local width = 0 -- advance - local leftsidebearing = 0 - for i=0,nofmetrics-1 do - local glyph = glyphs[i] - width = readshort(f) - leftsidebearing = readshort(f) - if width ~= 0 then - glyph.width = width - end - -- if leftsidebearing ~= 0 then - -- glyph.lsb = leftsidebearing - -- end - end - -- The next can happen in for instance a monospace font or in a cjk font - -- with fixed widths. - for i=nofmetrics,nofglyphs-1 do - local glyph = glyphs[i] - if width ~= 0 then - glyph.width = width - end - -- if leftsidebearing ~= 0 then - -- glyph.lsb = leftsidebearing - -- end - end - end - end -end - -readers.vmtx = function(f,fontdata,specification) - if specification.glyphs then - local datatable = fontdata.tables.vmtx - if datatable then - setposition(f,datatable.offset) - local verticalheader = fontdata.verticalheader - local nofmetrics = verticalheader.nofmetrics - local glyphs = fontdata.glyphs - local nofglyphs = fontdata.nofglyphs - local vheight = 0 - local vdefault = verticalheader.ascender + verticalheader.descender - local topsidebearing = 0 - for i=0,nofmetrics-1 do - local glyph = glyphs[i] - vheight = readshort(f) - topsidebearing = readshort(f) - if vheight ~= 0 and vheight ~= vdefault then - glyph.vheight = vheight - end - -- if topsidebearing ~= 0 then - -- glyph.tsb = topsidebearing - -- end - end - -- The next can happen in for instance a monospace font or in a cjk font - -- with fixed heights. - for i=nofmetrics,nofglyphs-1 do - local glyph = glyphs[i] - if vheight ~= 0 and vheight ~= vdefault then - glyph.vheight = vheight - end - -- if topsidebearing ~= 0 then - -- glyph.tsb = topsidebearing - -- end - end - end - end -end - -readers.vorg = function(f,fontdata,specification) - if specification.glyphs then - local datatable = fontdata.tables.vorg - if datatable then - report("todo: %s","vorg") - end - end -end - --- The post table relates to postscript (printing) but has some relevant properties for other --- usage as well. We just use the names from the microsoft specification. The version 2.0 --- description is somewhat fuzzy but it is a hybrid with overloads. - -readers.post = function(f,fontdata,specification) - local datatable = fontdata.tables.post - if datatable then - setposition(f,datatable.offset) - local version = readfixed(f) - fontdata.postscript = { - version = version, - italicangle = round(1000*readfixed(f))/1000, - underlineposition = readfword(f), - underlinethickness = readfword(f), - monospaced = readulong(f), - minmemtype42 = readulong(f), - maxmemtype42 = readulong(f), - minmemtype1 = readulong(f), - maxmemtype1 = readulong(f), - } - if not specification.glyphs then - -- enough done - elseif version == 1.0 then - -- mac encoding (258 glyphs) - for index=0,#standardromanencoding do - glyphs[index].name = standardromanencoding[index] - end - elseif version == 2.0 then - local glyphs = fontdata.glyphs - local nofglyphs = readushort(f) - local indices = { } - local names = { } - local maxnames = 0 - for i=0,nofglyphs-1 do - local nameindex = readushort(f) - if nameindex >= 258 then - maxnames = maxnames + 1 - nameindex = nameindex - 257 - indices[nameindex] = i - else - glyphs[i].name = standardromanencoding[nameindex] - end - end - for i=1,maxnames do - local mapping = indices[i] - if not mapping then - report("quit post name fetching at %a of %a: %s",i,maxnames,"no index") - break - else - local length = readbyte(f) - if length > 0 then - glyphs[mapping].name = readstring(f,length) - else - report("quit post name fetching at %a of %a: %s",i,maxnames,"overflow") - break - end - end - end - elseif version == 2.5 then - -- depricated, will be done when needed - elseif version == 3.0 then - -- no ps name information - end - else - fontdata.postscript = { } - end -end - -readers.cff = function(f,fontdata,specification) - if specification.glyphs then - reportskippedtable("cff") - end -end - --- Not all cmaps make sense .. e.g. dfont is obsolete and probably more are not relevant. Let's see --- what we run into. There is some weird calculation going on here because we offset in a table --- being a blob of memory or file. Anyway, I can't stand lunatic formats like this esp when there --- is no real gain. - -local formatreaders = { } -local duplicatestoo = true - -local sequence = { - { 3, 1, 4 }, - { 3, 10, 12 }, - { 0, 3, 4 }, - { 0, 1, 4 }, - -- { 0, 4, 12 }, - { 0, 0, 6 }, - { 3, 0, 6 }, - -- variants - { 0, 5, 14 }, - -- last resort ranges - { 3, 10, 13 }, -} - --- local sequence = { --- { 0, 1, 4 }, --- { 0, 4, 12 }, --- { 0, 3, 4 }, --- { 3, 1, 4 }, --- { 3, 10, 12 }, --- { 0, 0, 6 }, --- { 3, 0, 6 }, --- -- variants --- { 0, 5, 14 }, --- } - -local supported = { } - -for i=1,#sequence do - local sp, se, sf = unpack(sequence[i]) - local p = supported[sp] - if not p then - p = { } - supported[sp] = p - end - local e = p[se] - if not e then - e = { } - p[se] = e - end - e[sf] = true -end - -formatreaders[4] = function(f,fontdata,offset) - setposition(f,offset+2) -- skip format - -- - local length = readushort(f) -- in bytes of subtable - local language = readushort(f) - local nofsegments = readushort(f) / 2 - -- - skipshort(f,3) -- searchrange entryselector rangeshift - -- - local endchars = { } - local startchars = { } - local deltas = { } - local offsets = { } - local indices = { } - local mapping = fontdata.mapping - local glyphs = fontdata.glyphs - local duplicates = fontdata.duplicates - local nofdone = 0 - -- - for i=1,nofsegments do - endchars[i] = readushort(f) - end - local reserved = readushort(f) -- 0 - for i=1,nofsegments do - startchars[i] = readushort(f) - end - for i=1,nofsegments do - deltas[i] = readshort(f) - end - for i=1,nofsegments do - offsets[i] = readushort(f) - end - -- format length language nofsegments searchrange entryselector rangeshift 4-tables - local size = (length - 2 * 2 - 5 * 2 - 4 * nofsegments * 2) / 2 - for i=1,size-1 do - indices[i] = readushort(f) - end - -- - for segment=1,nofsegments do - local startchar = startchars[segment] - local endchar = endchars[segment] - local offset = offsets[segment] - local delta = deltas[segment] - if startchar == 0xFFFF and endchar == 0xFFFF then - -- break - elseif startchar == 0xFFFF and offset == 0 then - -- break - elseif offset == 0xFFFF then - -- bad encoding - elseif offset == 0 then - if trace_cmap then - report("format 4.%i segment %2i from %C upto %C at index %H",1,segment,startchar,endchar,(startchar + delta) % 65536) - end - for unicode=startchar,endchar do - local index = (unicode + delta) % 65536 - if index and index > 0 then - local glyph = glyphs[index] - if glyph then - local gu = glyph.unicode - if not gu then - glyph.unicode = unicode - nofdone = nofdone + 1 - elseif gu ~= unicode then - if duplicatestoo then - local d = duplicates[gu] - if d then - d[unicode] = true - else - duplicates[gu] = { [unicode] = true } - end - else - -- no duplicates ... weird side effects in lm - report("duplicate case 1: %C %04i %s",unicode,index,glyphs[index].name) - end - end - if not mapping[index] then - mapping[index] = unicode - end - end - end - end - else - local shift = (segment-nofsegments+offset/2) - startchar - if trace_cmap then - report("format 4.%i segment %2i from %C upto %C at index %H",0,segment,startchar,endchar,(startchar + delta) % 65536) - end - for unicode=startchar,endchar do - local slot = shift + unicode - local index = indices[slot] - if index and index > 0 then - index = (index + delta) % 65536 - local glyph = glyphs[index] - if glyph then - local gu = glyph.unicode - if not gu then - glyph.unicode = unicode - nofdone = nofdone + 1 - elseif gu ~= unicode then - if duplicatestoo then - local d = duplicates[gu] - if d then - d[unicode] = true - else - duplicates[gu] = { [unicode] = true } - end - else - -- no duplicates ... weird side effects in lm - report("duplicate case 2: %C %04i %s",unicode,index,glyphs[index].name) - end - end - if not mapping[index] then - mapping[index] = unicode - end - end - end - end - end - end - return nofdone -end - -formatreaders[6] = function(f,fontdata,offset) - setposition(f,offset) -- + 2 + 2 + 2 -- skip format length language - local format = readushort(f) - local length = readushort(f) - local language = readushort(f) - local mapping = fontdata.mapping - local glyphs = fontdata.glyphs - local duplicates = fontdata.duplicates - local start = readushort(f) - local count = readushort(f) - local stop = start+count-1 - local nofdone = 0 - if trace_cmap then - report("format 6 from %C to %C",2,start,stop) - end - for unicode=start,stop do - local index = readushort(f) - if index > 0 then - local glyph = glyphs[index] - if glyph then - local gu = glyph.unicode - if not gu then - glyph.unicode = unicode - nofdone = nofdone + 1 - elseif gu ~= unicode then - -- report("format 6 overloading %C to %C",gu,unicode) - -- glyph.unicode = unicode - -- no duplicates ... weird side effects in lm - end - if not mapping[index] then - mapping[index] = unicode - end - end - end - end - return nofdone -end - -formatreaders[12] = function(f,fontdata,offset) - setposition(f,offset+2+2+4+4) -- skip format reserved length language - local mapping = fontdata.mapping - local glyphs = fontdata.glyphs - local duplicates = fontdata.duplicates - local nofgroups = readulong(f) - local nofdone = 0 - for i=1,nofgroups do - local first = readulong(f) - local last = readulong(f) - local index = readulong(f) - if trace_cmap then - report("format 12 from %C to %C starts at index %i",first,last,index) - end - for unicode=first,last do - local glyph = glyphs[index] - if glyph then - local gu = glyph.unicode - if not gu then - glyph.unicode = unicode - nofdone = nofdone + 1 - elseif gu ~= unicode then - -- e.g. sourcehan fonts need this - local d = duplicates[gu] - if d then - d[unicode] = true - else - duplicates[gu] = { [unicode] = true } - end - end - if not mapping[index] then - mapping[index] = unicode - end - end - index = index + 1 - end - end - return nofdone -end - -formatreaders[13] = function(f,fontdata,offset) - -- - -- this fector is only used for simple fallback fonts - -- - setposition(f,offset+2+2+4+4) -- skip format reserved length language - local mapping = fontdata.mapping - local glyphs = fontdata.glyphs - local duplicates = fontdata.duplicates - local nofgroups = readulong(f) - local nofdone = 0 - for i=1,nofgroups do - local first = readulong(f) - local last = readulong(f) - local index = readulong(f) - if first < privateoffset then - if trace_cmap then - report("format 13 from %C to %C get index %i",first,last,index) - end - local glyph = glyphs[index] - local unicode = glyph.unicode - if not unicode then - unicode = first - glyph.unicode = unicode - first = first + 1 - end - local list = duplicates[unicode] - mapping[index] = unicode - if not list then - list = { } - duplicates[unicode] = list - end - if last >= privateoffset then - local limit = privateoffset - 1 - report("format 13 from %C to %C pruned to %C",first,last,limit) - last = limit - end - for unicode=first,last do - list[unicode] = true - end - nofdone = nofdone + last - first + 1 - else - report("format 13 from %C to %C ignored",first,last) - end - end - return nofdone -end - -formatreaders[14] = function(f,fontdata,offset) - if offset and offset ~= 0 then - setposition(f,offset) - local format = readushort(f) - local length = readulong(f) - local nofrecords = readulong(f) - local records = { } - local variants = { } - local nofdone = 0 - fontdata.variants = variants - for i=1,nofrecords do - records[i] = { - selector = readuint(f), - default = readulong(f), -- default offset - other = readulong(f), -- non-default offset - } - end - for i=1,nofrecords do - local record = records[i] - local selector = record.selector - local default = record.default - local other = record.other - -- - -- there is no need to map the defaults to themselves - -- - -- if default ~= 0 then - -- setposition(f,offset+default) - -- local nofranges = readulong(f) - -- for i=1,nofranges do - -- local start = readuint(f) - -- local extra = readbyte(f) - -- for i=start,start+extra do - -- mapping[i] = i - -- end - -- end - -- end - local other = record.other - if other ~= 0 then - setposition(f,offset+other) - local mapping = { } - local count = readulong(f) - for i=1,count do - mapping[readuint(f)] = readushort(f) - end - nofdone = nofdone + count - variants[selector] = mapping - end - end - return nofdone - else - return 0 - end -end - -local function checkcmap(f,fontdata,records,platform,encoding,format) - local data = records[platform] - if not data then - return 0 - end - data = data[encoding] - if not data then - return 0 - end - data = data[format] - if not data then - return 0 - end - local reader = formatreaders[format] - if not reader then - return 0 - end - local p = platforms[platform] - local e = encodings[p] - local n = reader(f,fontdata,data) or 0 - report("cmap checked: platform %i (%s), encoding %i (%s), format %i, new unicodes %i",platform,p,encoding,e and e[encoding] or "?",format,n) - return n -end - -function readers.cmap(f,fontdata,specification) - if specification.glyphs then - local datatable = fontdata.tables.cmap - if datatable then - local tableoffset = datatable.offset - setposition(f,tableoffset) - local version = readushort(f) - local noftables = readushort(f) - local records = { } - local unicodecid = false - local variantcid = false - local variants = { } - local duplicates = fontdata.duplicates or { } - fontdata.duplicates = duplicates - for i=1,noftables do - local platform = readushort(f) - local encoding = readushort(f) - local offset = readulong(f) - local record = records[platform] - if not record then - records[platform] = { - [encoding] = { - offsets = { offset }, - formats = { }, - } - } - else - local subtables = record[encoding] - if not subtables then - record[encoding] = { - offsets = { offset }, - formats = { }, - } - else - local offsets = subtables.offsets - offsets[#offsets+1] = offset - end - end - end - report("found cmaps:") - for platform, record in sortedhash(records) do - local p = platforms[platform] - local e = encodings[p] - local sp = supported[platform] - local ps = p or "?" - if sp then - report(" platform %i: %s",platform,ps) - else - report(" platform %i: %s (unsupported)",platform,ps) - end - for encoding, subtables in sortedhash(record) do - local se = sp and sp[encoding] - local es = e and e[encoding] or "?" - if se then - report(" encoding %i: %s",encoding,es) - else - report(" encoding %i: %s (unsupported)",encoding,es) - end - local offsets = subtables.offsets - local formats = subtables.formats - for i=1,#offsets do - local offset = tableoffset + offsets[i] - setposition(f,offset) - formats[readushort(f)] = offset - end - record[encoding] = formats - local list = sortedkeys(formats) - for i=1,#list do - if not (se and se[list[i]]) then - list[i] = list[i] .. " (unsupported)" - end - end - report(" formats: % t",list) - end - end - -- - local ok = false - for i=1,#sequence do - local sp, se, sf = unpack(sequence[i]) - if checkcmap(f,fontdata,records,sp,se,sf) > 0 then - ok = true - end - end - if not ok then - report("no useable unicode cmap found") - end - -- - fontdata.cidmaps = { - version = version, - noftables = noftables, - records = records, - } - else - fontdata.cidmaps = { } - end - end -end - --- The glyf table depends on the loca table. We have one entry to much in the locations table (the --- last one is a dummy) because we need to calculate the size of a glyph blob from the delta, --- although we not need it in our usage (yet). We can remove the locations table when we're done. - -function readers.loca(f,fontdata,specification) - if specification.glyphs then - reportskippedtable("loca") - end -end - -function readers.glyf(f,fontdata,specification) -- part goes to cff module - if specification.glyphs then - reportskippedtable("glyf") - end -end - --- Experimental (we need fonts). - -function readers.colr(f,fontdata,specification) - if specification.glyphs then - reportskippedtable("colr") - end -end - -function readers.cpal(f,fontdata,specification) - if specification.glyphs then - reportskippedtable("cpal") - end -end - -function readers.svg(f,fontdata,specification) - if specification.glyphs then - reportskippedtable("svg") - end -end - --- Here we have a table that we really need for later processing although a more advanced gpos table --- can also be available. Todo: we need a 'fake' lookup for this (analogue to ff). - -function readers.kern(f,fontdata,specification) - if specification.kerns then - local datatable = fontdata.tables.kern - if datatable then - setposition(f,datatable.offset) - local version = readushort(f) - local noftables = readushort(f) - for i=1,noftables do - local version = readushort(f) - local length = readushort(f) - local coverage = readushort(f) - -- bit 8-15 of coverage: format 0 or 2 - local format = bit32.rshift(coverage,8) -- is this ok? - if format == 0 then - local nofpairs = readushort(f) - local searchrange = readushort(f) - local entryselector = readushort(f) - local rangeshift = readushort(f) - local kerns = { } - local glyphs = fontdata.glyphs - for i=1,nofpairs do - local left = readushort(f) - local right = readushort(f) - local kern = readfword(f) - local glyph = glyphs[left] - local kerns = glyph.kerns - if kerns then - kerns[right] = kern - else - glyph.kerns = { [right] = kern } - end - end - elseif format == 2 then - report("todo: kern classes") - else - report("todo: kerns") - end - end - end - end -end - -function readers.gdef(f,fontdata,specification) - if specification.details then - reportskippedtable("gdef") - end -end - -function readers.gsub(f,fontdata,specification) - if specification.details then - reportskippedtable("gsub") - end -end - -function readers.gpos(f,fontdata,specification) - if specification.details then - reportskippedtable("gpos") - end -end - -function readers.math(f,fontdata,specification) - if specification.glyphs then - reportskippedtable("math") - end -end - --- Now comes the loader. The order of reading these matters as we need to know --- some properties in order to read following tables. When details is true we also --- initialize the glyphs data. - -local function getinfo(maindata,sub,platformnames,rawfamilynames,metricstoo) - local fontdata = sub and maindata.subfonts and maindata.subfonts[sub] or maindata - local names = fontdata.names - local info = nil - if names then - local metrics = fontdata.windowsmetrics or { } - local postscript = fontdata.postscript or { } - local fontheader = fontdata.fontheader or { } - local cffinfo = fontdata.cffinfo or { } - local filename = fontdata.filename - local weight = getname(fontdata,"weight") or (cffinfo and cffinfo.weight) or (metrics and metrics.weight) - local width = getname(fontdata,"width") or (cffinfo and cffinfo.width ) or (metrics and metrics.width ) - local fontname = getname(fontdata,"postscriptname") - local fullname = getname(fontdata,"fullname") - local family = getname(fontdata,"family") - local subfamily = getname(fontdata,"subfamily") - local familyname = getname(fontdata,"typographicfamily") - local subfamilyname = getname(fontdata,"typographicsubfamily") - local compatiblename = getname(fontdata,"compatiblefullname") -- kind of useless - if rawfamilynames then - -- for PG (for now, as i need to check / adapt context to catch a no-fallback case) - else - if not familyname then familyname = family end - if not subfamilyname then subfamilyname = subfamily end - end - info = { -- we inherit some inconsistencies/choices from ff - subfontindex = fontdata.subfontindex or sub or 0, - -- filename = filename, - version = getname(fontdata,"version"), - -- format = fontdata.format, - fontname = fontname, - fullname = fullname, - -- cfffullname = cff.fullname, - family = family, - subfamily = subfamily, - familyname = familyname, - subfamilyname = subfamilyname, - compatiblename = compatiblename, - weight = weight and lower(weight), - width = width and lower(width), - pfmweight = metrics.weightclass or 400, -- will become weightclass - pfmwidth = metrics.widthclass or 5, -- will become widthclass - panosewidth = metrics.panosewidth, - panoseweight = metrics.panoseweight, - italicangle = postscript.italicangle or 0, - units = fontheader.units or 0, - designsize = fontdata.designsize, - minsize = fontdata.minsize, - maxsize = fontdata.maxsize, - monospaced = (tonumber(postscript.monospaced or 0) > 0) or metrics.panosewidth == "monospaced", - averagewidth = metrics.averagewidth, - xheight = metrics.xheight, - capheight = metrics.capheight, -- not always present and probably crap - ascender = metrics.typoascender, - descender = metrics.typodescender, - platformnames = platformnames and fontdata.platformnames or nil, - } - if metricstoo then - local keys = { - "version", - "ascender", "descender", "linegap", - -- "caretoffset", "caretsloperise", "caretsloperun", - "maxadvancewidth", "maxadvanceheight", "maxextent", - -- "metricdataformat", - "minbottomsidebearing", "mintopsidebearing", - } - local h = fontdata.horizontalheader or { } - local v = fontdata.verticalheader or { } - if h then - local th = { } - local tv = { } - for i=1,#keys do - local key = keys[i] - th[key] = h[key] or 0 - tv[key] = v[key] or 0 - end - info.horizontalmetrics = th - info.verticalmetrics = tv - end - end - elseif n then - info = { - filename = fontdata.filename, - comment = "there is no info for subfont " .. n, - } - else - info = { - filename = fontdata.filename, - comment = "there is no info", - } - end - -- inspect(info) - return info -end - -local function loadtables(f,specification,offset) - if offset then - setposition(f,offset) - end - local tables = { } - local basename = file.basename(specification.filename) - local filesize = specification.filesize - local filetime = specification.filetime - local fontdata = { -- some can/will go - filename = basename, - filesize = filesize, - filetime = filetime, - version = readstring(f,4), - noftables = readushort(f), - searchrange = readushort(f), -- not needed - entryselector = readushort(f), -- not needed - rangeshift = readushort(f), -- not needed - tables = tables, - } - for i=1,fontdata.noftables do - local tag = lower(stripstring(readstring(f,4))) - local checksum = readulong(f) -- not used - local offset = readulong(f) - local length = readulong(f) - if offset + length > filesize then - report("bad %a table in file %a",tag,basename) - end - tables[tag] = { - checksum = checksum, - offset = offset, - length = length, - } - end - if tables.cff then - fontdata.format = "opentype" - else - fontdata.format = "truetype" - end - return fontdata -end - -local function prepareglyps(fontdata) - local glyphs = setmetatableindex(function(t,k) - local v = { - -- maybe more defaults - index = k, - } - t[k] = v - return v - end) - fontdata.glyphs = glyphs - fontdata.mapping = { } -end - -local function readdata(f,offset,specification) - local fontdata = loadtables(f,specification,offset) - if specification.glyphs then - prepareglyps(fontdata) - end - -- - readers["name"](f,fontdata,specification) - -- - local askedname = specification.askedname - if askedname then - local fullname = getname(fontdata,"fullname") or "" - local cleanname = gsub(askedname,"[^a-zA-Z0-9]","") - local foundname = gsub(fullname,"[^a-zA-Z0-9]","") - if lower(cleanname) ~= lower(foundname) then - return -- keep searching - end - end - -- - -- - readers["os/2"](f,fontdata,specification) - readers["head"](f,fontdata,specification) - readers["maxp"](f,fontdata,specification) - readers["hhea"](f,fontdata,specification) - readers["vhea"](f,fontdata,specification) - readers["hmtx"](f,fontdata,specification) - readers["vmtx"](f,fontdata,specification) - readers["vorg"](f,fontdata,specification) - readers["post"](f,fontdata,specification) - readers["cff" ](f,fontdata,specification) - readers["cmap"](f,fontdata,specification) - readers["loca"](f,fontdata,specification) - readers["glyf"](f,fontdata,specification) - readers["colr"](f,fontdata,specification) - readers["cpal"](f,fontdata,specification) - readers["svg" ](f,fontdata,specification) - readers["kern"](f,fontdata,specification) - readers["gdef"](f,fontdata,specification) - readers["gsub"](f,fontdata,specification) - readers["gpos"](f,fontdata,specification) - readers["math"](f,fontdata,specification) - -- - fontdata.locations = nil - fontdata.tables = nil - fontdata.cidmaps = nil - fontdata.dictionaries = nil - -- fontdata.cff = nil - return fontdata -end - -local function loadfontdata(specification) - local filename = specification.filename - local fileattr = lfs.attributes(filename) - local filesize = fileattr and fileattr.size or 0 - local filetime = fileattr and fileattr.modification or 0 - local f = openfile(filename,true) -- zero based - if not f then - report("unable to open %a",filename) - elseif filesize == 0 then - report("empty file %a",filename) - closefile(f) - else - specification.filesize = filesize - specification.filetime = filetime - local version = readstring(f,4) - local fontdata = nil - if version == "OTTO" or version == "true" or version == "\0\1\0\0" then - fontdata = readdata(f,0,specification) - elseif version == "ttcf" then - local subfont = tonumber(specification.subfont) - local offsets = { } - local ttcversion = readulong(f) - local nofsubfonts = readulong(f) - for i=1,nofsubfonts do - offsets[i] = readulong(f) - end - if subfont then -- a number of not - if subfont >= 1 and subfont <= nofsubfonts then - fontdata = readdata(f,offsets[subfont],specification) - else - report("no subfont %a in file %a",subfont,filename) - end - else - subfont = specification.subfont - if type(subfont) == "string" and subfont ~= "" then - specification.askedname = subfont - for i=1,nofsubfonts do - fontdata = readdata(f,offsets[i],specification) - if fontdata then - fontdata.subfontindex = i - report("subfont named %a has index %a",subfont,i) - break - end - end - if not fontdata then - report("no subfont named %a",subfont) - end - else - local subfonts = { } - fontdata = { - filename = filename, - filesize = filesize, - filetime = filetime, - version = version, - subfonts = subfonts, - ttcversion = ttcversion, - nofsubfonts = nofsubfonts, - } - for i=1,nofsubfonts do - subfonts[i] = readdata(f,offsets[i],specification) - end - end - end - else - report("unknown version %a in file %a",version,filename) - end - closefile(f) - return fontdata or { } - end -end - -local function loadfont(specification,n) - if type(specification) == "string" then - specification = { - filename = specification, - info = true, -- always true (for now) - details = true, - glyphs = true, - shapes = true, - kerns = true, - globalkerns = true, - lookups = true, - -- true or number: - subfont = n or true, - tounicode = false, - } - end - -- if shapes only then - if specification.shapes or specification.lookups or specification.kerns then - specification.glyphs = true - end - if specification.glyphs then - specification.details = true - end - if specification.details then - specification.info = true -- not really used any more - end - if specification.platformnames then - specification.platformnames = true -- not really used any more - end - local function message(str) - report("fatal error in file %a: %s\n%s",specification.filename,str,debug.traceback()) - end - local ok, result = xpcall(loadfontdata,message,specification) - if ok then - return result - end -end - --- we need even less, but we can have a 'detail' variant - -function readers.loadshapes(filename,n) - local fontdata = loadfont { - filename = filename, - shapes = true, - subfont = n, - } - if fontdata then - -- easier on luajit but still we can hit the 64 K stack constants issue - for k, v in next, fontdata.glyphs do - v.class = nil - v.index = nil - v.math = nil - -- v.name = nil - end - end - return fontdata and { - -- version = 0.123 -- todo - filename = filename, - format = fontdata.format, - glyphs = fontdata.glyphs, - units = fontdata.fontheader.units, - } or { - filename = filename, - format = "unknown", - glyphs = { }, - units = 0, - } -end - -function readers.loadfont(filename,n) - local fontdata = loadfont { - filename = filename, - glyphs = true, - shapes = false, - lookups = true, - -- kerns = true, - -- globalkerns = true, -- only for testing, e.g. cambria has different gpos and kern - subfont = n, - } - if fontdata then - -- - return { - tableversion = tableversion, - creator = "context mkiv", - size = fontdata.filesize, - time = fontdata.filetime, - glyphs = fontdata.glyphs, - descriptions = fontdata.descriptions, - format = fontdata.format, - goodies = { }, - metadata = getinfo(fontdata,n,false,false,true), -- no platformnames here ! - properties = { - hasitalics = fontdata.hasitalics or false, - maxcolorclass = fontdata.maxcolorclass, - hascolor = fontdata.hascolor or false, - }, - resources = { - -- filename = fontdata.filename, - filename = filename, - private = privateoffset, - duplicates = fontdata.duplicates or { }, - features = fontdata.features or { }, -- we need to add these in the loader - sublookups = fontdata.sublookups or { }, -- we need to add these in the loader - marks = fontdata.marks or { }, -- we need to add these in the loader - markclasses = fontdata.markclasses or { }, -- we need to add these in the loader - marksets = fontdata.marksets or { }, -- we need to add these in the loader - sequences = fontdata.sequences or { }, -- we need to add these in the loader - variants = fontdata.variants, -- variant -> unicode -> glyph - version = getname(fontdata,"version"), - cidinfo = fontdata.cidinfo, - mathconstants = fontdata.mathconstants, - colorpalettes = fontdata.colorpalettes, - svgshapes = fontdata.svgshapes, - }, - } - end -end - -function readers.getinfo(filename,specification) -- string, nil|number|table - -- platformnames is optional and not used by context (a too unpredictable mess - -- that only add to the confusion) .. so it's only for checking things - local subfont = nil - local platformnames = false - local rawfamilynames = false - if type(specification) == "table" then - subfont = tonumber(specification.subfont) - platformnames = specification.platformnames - rawfamilynames = specification.rawfamilynames - else - subfont = tonumber(specification) - end - local fontdata = loadfont { - filename = filename, - details = true, - platformnames = platformnames, - -- rawfamilynames = rawfamilynames, - } - if fontdata then - local subfonts = fontdata.subfonts - if not subfonts then - return getinfo(fontdata,nil,platformnames,rawfamilynames) - elseif not subfont then - local info = { } - for i=1,#subfonts do - info[i] = getinfo(fontdata,i,platformnames,rawfamilynames) - end - return info - elseif subfont >= 1 and subfont <= #subfonts then - return getinfo(fontdata,subfont,platformnames,rawfamilynames) - else - return { - filename = filename, - comment = "there is no subfont " .. subfont .. " in this file" - } - end - else - return { - filename = filename, - comment = "the file cannot be opened for reading", - } - end -end - -function readers.rehash(fontdata,hashmethod) - report("the %a helper is not yet implemented","rehash") -end - -function readers.checkhash(fontdata) - report("the %a helper is not yet implemented","checkhash") -end - -function readers.pack(fontdata,hashmethod) - report("the %a helper is not yet implemented","pack") -end - -function readers.unpack(fontdata) - report("the %a helper is not yet implemented","unpack") -end - -function readers.expand(fontdata) - report("the %a helper is not yet implemented","unpack") -end - -function readers.compact(fontdata) - report("the %a helper is not yet implemented","compact") -end - --- plug in - -local extenders = { } - -function readers.registerextender(extender) - extenders[#extenders+1] = extender -end - -function readers.extend(fontdata) - for i=1,#extenders do - local extender = extenders[i] - local name = extender.name or "unknown" - local action = extender.action - if action then - action(fontdata) - end - end -end diff --git a/tex/compat/luaotfload/fontloader-font-ots.lua b/tex/compat/luaotfload/fontloader-font-ots.lua deleted file mode 100644 index 1f84214812f55e7c0b762a6ab36058ea64845c57..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/fontloader-font-ots.lua +++ /dev/null @@ -1,3924 +0,0 @@ -if not modules then modules = { } end modules ['font-ots'] = { -- sequences - version = 1.001, - comment = "companion to font-ini.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files", -} - --- to be checked: discrun doesn't seem to do something useful now (except run the --- check again) so if we need it again we'll do a zwnjrun or so - --- components will go away and be replaced by a property table which simplifies --- code (also more efficient) - --- beware, on my development machine we test a slightly a more optimized version - --- assumptions: --- --- cursives don't cross discretionaries --- marks precede bases --- --- pitfalls: --- --- when we append to a dics field we need to set the field in order to update tail --- --- This is a version of font-otn.lua adapted to the new font loader code. It --- is a context version which can contain experimental code, but when we --- have serious patches we will backport to the font-otn files. The plain --- loader that ships with context also uses this now. --- --- todo: looks like we have a leak somewhere (probably in ligatures) --- todo: copy attributes to disc --- todo: get rid of components, better use the tounicode entry if needed (at all) --- --- we do some disc juggling where we need to keep in mind that the --- pre, post and replace fields can have prev pointers to a nesting --- node ... i wonder if that is still needed --- --- not possible: --- --- \discretionary {alpha-} {betagammadelta} --- {\discretionary {alphabeta-} {gammadelta} --- {\discretionary {alphabetagamma-} {delta} --- {alphabetagammadelta}}} - ---[[ldx-- -<p>This module is a bit more split up that I'd like but since we also want to test -with plain <l n='tex'/> it has to be so. This module is part of <l n='context'/> -and discussion about improvements and functionality mostly happens on the -<l n='context'/> mailing list.</p> - -<p>The specification of OpenType is kind of vague. Apart from a lack of a proper -free specifications there's also the problem that Microsoft and Adobe -may have their own interpretation of how and in what order to apply features. -In general the Microsoft website has more detailed specifications and is a -better reference. There is also some information in the FontForge help files.</p> - -<p>Because there is so much possible, fonts might contain bugs and/or be made to -work with certain rederers. These may evolve over time which may have the side -effect that suddenly fonts behave differently.</p> - -<p>After a lot of experiments (mostly by Taco, me and Idris) we're now at yet another -implementation. Of course all errors are mine and of course the code can be -improved. There are quite some optimizations going on here and processing speed -is currently acceptable. Not all functions are implemented yet, often because I -lack the fonts for testing. Many scripts are not yet supported either, but I will -look into them as soon as <l n='context'/> users ask for it.</p> - -<p>The specification leaves room for interpretation. In case of doubt the microsoft -implementation is the reference as it is the most complete one. As they deal with -lots of scripts and fonts, Kai and Ivo did a lot of testing of the generic code and -their suggestions help improve the code. I'm aware that not all border cases can be -taken care of, unless we accept excessive runtime, and even then the interference -with other mechanisms (like hyphenation) are not trivial.</p> - -<p>Glyphs are indexed not by unicode but in their own way. This is because there is no -relationship with unicode at all, apart from the fact that a font might cover certain -ranges of characters. One character can have multiple shapes. However, at the -<l n='tex'/> end we use unicode so and all extra glyphs are mapped into a private -space. This is needed because we need to access them and <l n='tex'/> has to include -then in the output eventually.</p> - -<p>The initial data table is rather close to the open type specification and also not -that different from the one produced by <l n='fontforge'/> but we uses hashes instead. -In <l n='context'/> that table is packed (similar tables are shared) and cached on disk -so that successive runs can use the optimized table (after loading the table is -unpacked). The flattening code used later is a prelude to an even more compact table -format (and as such it keeps evolving).</p> - -<p>This module is sparsely documented because it is a moving target. The table format -of the reader changes and we experiment a lot with different methods for supporting -features.</p> - -<p>As with the <l n='afm'/> code, we may decide to store more information in the -<l n='otf'/> table.</p> - -<p>Incrementing the version number will force a re-cache. We jump the number by one -when there's a fix in the <l n='fontforge'/> library or <l n='lua'/> code that -results in different tables.</p> ---ldx]]-- - -local type, next, tonumber = type, next, tonumber -local random = math.random -local formatters = string.formatters -local insert = table.insert - -local logs, trackers, nodes, attributes = logs, trackers, nodes, attributes - -local registertracker = trackers.register -local registerdirective = directives.register - -local fonts = fonts -local otf = fonts.handlers.otf - -local trace_lookups = false registertracker("otf.lookups", function(v) trace_lookups = v end) -local trace_singles = false registertracker("otf.singles", function(v) trace_singles = v end) -local trace_multiples = false registertracker("otf.multiples", function(v) trace_multiples = v end) -local trace_alternatives = false registertracker("otf.alternatives", function(v) trace_alternatives = v end) -local trace_ligatures = false registertracker("otf.ligatures", function(v) trace_ligatures = v end) -local trace_contexts = false registertracker("otf.contexts", function(v) trace_contexts = v end) -local trace_marks = false registertracker("otf.marks", function(v) trace_marks = v end) -local trace_kerns = false registertracker("otf.kerns", function(v) trace_kerns = v end) -local trace_cursive = false registertracker("otf.cursive", function(v) trace_cursive = v end) -local trace_preparing = false registertracker("otf.preparing", function(v) trace_preparing = v end) -local trace_bugs = false registertracker("otf.bugs", function(v) trace_bugs = v end) -local trace_details = false registertracker("otf.details", function(v) trace_details = v end) ------ trace_applied = false registertracker("otf.applied", function(v) trace_applied = v end) -local trace_steps = false registertracker("otf.steps", function(v) trace_steps = v end) -local trace_skips = false registertracker("otf.skips", function(v) trace_skips = v end) -local trace_directions = false registertracker("otf.directions", function(v) trace_directions = v end) -local trace_plugins = false registertracker("otf.plugins", function(v) trace_plugins = v end) - -local trace_kernruns = false registertracker("otf.kernruns", function(v) trace_kernruns = v end) -local trace_discruns = false registertracker("otf.discruns", function(v) trace_discruns = v end) -local trace_compruns = false registertracker("otf.compruns", function(v) trace_compruns = v end) -local trace_testruns = false registertracker("otf.testruns", function(v) trace_testruns = v end) - ------ zwnjruns = true registerdirective("otf.zwnjruns", function(v) zwnjruns = v end) -local optimizekerns = true -local alwaysdisc = true registerdirective("otf.alwaysdisc", function(v) alwaysdisc = v end) - -local report_direct = logs.reporter("fonts","otf direct") -local report_subchain = logs.reporter("fonts","otf subchain") -local report_chain = logs.reporter("fonts","otf chain") -local report_process = logs.reporter("fonts","otf process") -local report_warning = logs.reporter("fonts","otf warning") -local report_run = logs.reporter("fonts","otf run") - -registertracker("otf.replacements", "otf.singles,otf.multiples,otf.alternatives,otf.ligatures") -registertracker("otf.positions","otf.marks,otf.kerns,otf.cursive") -registertracker("otf.actions","otf.replacements,otf.positions") -registertracker("otf.injections","nodes.injections") - -registertracker("*otf.sample","otf.steps,otf.actions,otf.analyzing") - -local nuts = nodes.nuts -local tonode = nuts.tonode -local tonut = nuts.tonut - -local getfield = nuts.getfield -local setfield = nuts.setfield -local getnext = nuts.getnext -local setnext = nuts.setnext -local getprev = nuts.getprev -local setprev = nuts.setprev -local getboth = nuts.getboth -local setboth = nuts.setboth -local getid = nuts.getid -local getattr = nuts.getattr -local setattr = nuts.setattr -local getprop = nuts.getprop -local setprop = nuts.setprop -local getfont = nuts.getfont -local getsubtype = nuts.getsubtype -local setsubtype = nuts.setsubtype -local getchar = nuts.getchar -local setchar = nuts.setchar -local getdisc = nuts.getdisc -local setdisc = nuts.setdisc -local setlink = nuts.setlink - -local ischar = nuts.is_char - -local insert_node_after = nuts.insert_after -local copy_node = nuts.copy -local copy_node_list = nuts.copy_list -local find_node_tail = nuts.tail -local flush_node_list = nuts.flush_list -local flush_node = nuts.flush_node -local end_of_math = nuts.end_of_math -local traverse_nodes = nuts.traverse -local traverse_id = nuts.traverse_id -local remove_node = nuts.remove - -local setmetatableindex = table.setmetatableindex - -local zwnj = 0x200C -local zwj = 0x200D -local wildcard = "*" -local default = "dflt" - -local nodecodes = nodes.nodecodes -local glyphcodes = nodes.glyphcodes -local disccodes = nodes.disccodes - -local glyph_code = nodecodes.glyph -local glue_code = nodecodes.glue -local disc_code = nodecodes.disc -local math_code = nodecodes.math -local dir_code = nodecodes.dir -local localpar_code = nodecodes.localpar - -local discretionary_code = disccodes.discretionary -local ligature_code = glyphcodes.ligature - -local privateattribute = attributes.private - --- Something is messed up: we have two mark / ligature indices, one at the injection --- end and one here ... this is based on KE's patches but there is something fishy --- there as I'm pretty sure that for husayni we need some connection (as it's much --- more complex than an average font) but I need proper examples of all cases, not --- of only some. - -local a_state = privateattribute('state') - -local injections = nodes.injections -local setmark = injections.setmark -local setcursive = injections.setcursive -local setkern = injections.setkern -local setpair = injections.setpair -local resetinjection = injections.reset -local copyinjection = injections.copy -local setligaindex = injections.setligaindex -local getligaindex = injections.getligaindex - -local cursonce = true - -local fonthashes = fonts.hashes -local fontdata = fonthashes.identifiers -local fontfeatures = fonthashes.features - -local otffeatures = fonts.constructors.features.otf -local registerotffeature = otffeatures.register - -local onetimemessage = fonts.loggers.onetimemessage or function() end - -local getrandom = utilities and utilities.randomizer and utilities.randomizer.get - -otf.defaultnodealternate = "none" -- first last - --- We use a few global variables. The handler can be called nested but this assumes that the --- same font is used. Nested calls are normally not needed (only for devanagari). - -local tfmdata = false -local characters = false -local descriptions = false -local marks = false -local currentfont = false -local factor = 0 -local threshold = 0 -local checkmarks = false - -local sweepnode = nil -local sweepprev = nil -local sweepnext = nil -local sweephead = { } - -local notmatchpre = { } -local notmatchpost = { } -local notmatchreplace = { } - -local handlers = { } - -local isspace = injections.isspace -local getthreshold = injections.getthreshold - --- we use this for special testing and documentation - -local checkstep = (nodes and nodes.tracers and nodes.tracers.steppers.check) or function() end -local registerstep = (nodes and nodes.tracers and nodes.tracers.steppers.register) or function() end -local registermessage = (nodes and nodes.tracers and nodes.tracers.steppers.message) or function() end - -local function checkdisccontent(d) - local pre, post, replace = getdisc(d) - if pre then for n in traverse_id(glue_code,pre) do print("pre",nodes.idstostring(pre)) break end end - if post then for n in traverse_id(glue_code,post) do print("pos",nodes.idstostring(post)) break end end - if replace then for n in traverse_id(glue_code,replace) do print("rep",nodes.idstostring(replace)) break end end -end - -local function logprocess(...) - if trace_steps then - registermessage(...) - end - report_direct(...) -end - -local function logwarning(...) - report_direct(...) -end - -local f_unicode = formatters["%U"] -local f_uniname = formatters["%U (%s)"] -local f_unilist = formatters["% t (% t)"] - -local function gref(n) -- currently the same as in font-otb - if type(n) == "number" then - local description = descriptions[n] - local name = description and description.name - if name then - return f_uniname(n,name) - else - return f_unicode(n) - end - elseif n then - local num, nam = { }, { } - for i=1,#n do - local ni = n[i] - if tonumber(ni) then -- later we will start at 2 - local di = descriptions[ni] - num[i] = f_unicode(ni) - nam[i] = di and di.name or "-" - end - end - return f_unilist(num,nam) - else - return "<error in node mode tracing>" - end -end - -local function cref(dataset,sequence,index) - if not dataset then - return "no valid dataset" - elseif index then - return formatters["feature %a, type %a, chain lookup %a, index %a"](dataset[4],sequence.type,sequence.name,index) - else - return formatters["feature %a, type %a, chain lookup %a"](dataset[4],sequence.type,sequence.name) - end -end - -local function pref(dataset,sequence) - return formatters["feature %a, type %a, lookup %a"](dataset[4],sequence.type,sequence.name) -end - -local function mref(rlmode) - if not rlmode or rlmode == 0 then - return "---" - elseif rlmode == -1 or rlmode == "+TRT" then - return "r2l" - else - return "l2r" - end -end - --- We can assume that languages that use marks are not hyphenated. We can also assume --- that at most one discretionary is present. - --- We do need components in funny kerning mode but maybe I can better reconstruct then --- as we do have the font components info available; removing components makes the --- previous code much simpler. Also, later on copying and freeing becomes easier. --- However, for arabic we need to keep them around for the sake of mark placement --- and indices. - -local function copy_glyph(g) -- next and prev are untouched ! - local components = getfield(g,"components") - if components then - setfield(g,"components") - local n = copy_node(g) - copyinjection(n,g) -- we need to preserve the lig indices - setfield(g,"components",components) - return n - else - local n = copy_node(g) - copyinjection(n,g) -- we need to preserve the lig indices - return n - end -end - -local function flattendisk(head,disc) - local pre, post, replace, pretail, posttail, replacetail = getdisc(disc,true) - local prev, next = getboth(disc) - local ishead = head == disc - setdisc(disc) - flush_node(disc) - if pre then - flush_node_list(pre) - end - if post then - flush_node_list(post) - end - if ishead then - if replace then - if next then - setlink(replacetail,next) - end - return replace, replace - elseif next then - return next, next - else - return -- maybe warning - end - else - if replace then - if next then - setlink(replacetail,next) - end - setlink(prev,replace) - return head, replace - else - setlink(prev,next) -- checks for next anyway - return head, next - end - end -end - -local function appenddisc(disc,list) - local pre, post, replace, pretail, posttail, replacetail = getdisc(disc,true) - local posthead = list - local replacehead = copy_node_list(list) - if post then - setlink(posttail,posthead) - else - post = phead - end - if replace then - setlink(replacetail,replacehead) - else - replace = rhead - end - setdisc(disc,pre,post,replace) -end - --- start is a mark and we need to keep that one - -local function markstoligature(head,start,stop,char) - if start == stop and getchar(start) == char then - return head, start - else - local prev = getprev(start) - local next = getnext(stop) - setprev(start) - setnext(stop) - local base = copy_glyph(start) - if head == start then - head = base - end - resetinjection(base) - setchar(base,char) - setsubtype(base,ligature_code) - setfield(base,"components",start) - setlink(prev,base) - setlink(base,next) - return head, base - end -end - --- The next code is somewhat complicated by the fact that some fonts can have ligatures made --- from ligatures that themselves have marks. This was identified by Kai in for instance --- arabtype: KAF LAM SHADDA ALEF FATHA (0x0643 0x0644 0x0651 0x0627 0x064E). This becomes --- KAF LAM-ALEF with a SHADDA on the first and a FATHA op de second component. In a next --- iteration this becomes a KAF-LAM-ALEF with a SHADDA on the second and a FATHA on the --- third component. - -local function getcomponentindex(start) -- we could store this offset in the glyph (nofcomponents) - if getid(start) ~= glyph_code then -- and then get rid of all components - return 0 - elseif getsubtype(start) == ligature_code then - local i = 0 - local components = getfield(start,"components") - while components do - i = i + getcomponentindex(components) - components = getnext(components) - end - return i - elseif not marks[getchar(start)] then - return 1 - else - return 0 - end -end - -local a_noligature = attributes.private("noligature") - -local function toligature(head,start,stop,char,dataset,sequence,markflag,discfound) -- brr head - if getattr(start,a_noligature) == 1 then - -- so we can do: e\noligature{ff}e e\noligature{f}fie (we only look at the first) - return head, start - end - if start == stop and getchar(start) == char then - resetinjection(start) - setchar(start,char) - return head, start - end - -- needs testing (side effects): - local components = getfield(start,"components") - if components then - -- we get a double free .. needs checking - -- flush_node_list(components) - end - -- - local prev = getprev(start) - local next = getnext(stop) - local comp = start - setprev(start) - setnext(stop) - local base = copy_glyph(start) - if start == head then - head = base - end - resetinjection(base) - setchar(base,char) - setsubtype(base,ligature_code) - setfield(base,"components",comp) -- start can have components ... do we need to flush? - if prev then - setnext(prev,base) - end - if next then - setprev(next,base) - end - setboth(base,prev,next) - if not discfound then - local deletemarks = markflag ~= "mark" - local components = start - local baseindex = 0 - local componentindex = 0 - local head = base - local current = base - -- first we loop over the glyphs in start .. stop - while start do - local char = getchar(start) - if not marks[char] then - baseindex = baseindex + componentindex - componentindex = getcomponentindex(start) - elseif not deletemarks then -- quite fishy - setligaindex(start,baseindex + getligaindex(start,componentindex)) - if trace_marks then - logwarning("%s: keep mark %s, gets index %s",pref(dataset,sequence),gref(char),getligaindex(start)) - end - local n = copy_node(start) - copyinjection(n,start) - head, current = insert_node_after(head,current,n) -- unlikely that mark has components - elseif trace_marks then - logwarning("%s: delete mark %s",pref(dataset,sequence),gref(char)) - end - start = getnext(start) - end - -- we can have one accent as part of a lookup and another following - -- local start = components -- was wrong (component scanning was introduced when more complex ligs in devanagari was added) - local start = getnext(current) - while start do - local char = ischar(start) - if char then - if marks[char] then - setligaindex(start,baseindex + getligaindex(start,componentindex)) - if trace_marks then - logwarning("%s: set mark %s, gets index %s",pref(dataset,sequence),gref(char),getligaindex(start)) - end - start = getnext(start) - else - break - end - else - break - end - end - else - -- discfound ... forget about marks .. probably no scripts that hyphenate and have marks - local discprev, discnext = getboth(discfound) - if discprev and discnext then - -- we assume normalization in context, and don't care about generic ... especially - -- \- can give problems as there we can have a negative char but that won't match - -- anyway - local pre, post, replace, pretail, posttail, replacetail = getdisc(discfound,true) - if not replace then -- todo: signal simple hyphen - local prev = getprev(base) - local current = comp - local previous = nil - local copied = nil - while current do - if getid(current) == glyph_code then - local n = copy_node(current) - if copied then - setlink(previous,n) - else - copied = n - end - previous = n - end - current = getnext(current) - end - setprev(discnext) -- also blocks funny assignments - setnext(discprev) -- also blocks funny assignments - if pre then - setlink(discprev,pre) - end - pre = comp - if post then - setlink(posttail,discnext) - setprev(post) - else - post = discnext - end - setlink(prev,discfound) - setlink(discfound,next) - setboth(base) - setfield(base,"components",copied) - setdisc(discfound,pre,post,base) -- was discretionary_code - base = prev -- restart - end - end - end - return head, base -end - -local function multiple_glyphs(head,start,multiple,ignoremarks,what) - local nofmultiples = #multiple - if nofmultiples > 0 then - resetinjection(start) - setchar(start,multiple[1]) - if nofmultiples > 1 then - local sn = getnext(start) - for k=2,nofmultiples do - -- untested: - -- - -- while ignoremarks and marks[getchar(sn)] then - -- local sn = getnext(sn) - -- end - local n = copy_node(start) -- ignore components - resetinjection(n) - setchar(n,multiple[k]) - insert_node_after(head,start,n) - start = n - end - if what == true then - -- we're ok - elseif what > 1 then - local m = multiple[nofmultiples] - for i=2,what do - local n = copy_node(start) -- ignore components - resetinjection(n) - setchar(n,m) - insert_node_after(head,start,n) - start = n - end - end - end - return head, start, true - else - if trace_multiples then - logprocess("no multiple for %s",gref(getchar(start))) - end - return head, start, false - end -end - -local function get_alternative_glyph(start,alternatives,value) - local n = #alternatives - if value == "random" then - local r = getrandom and getrandom("glyph",1,n) or random(1,n) - return alternatives[r], trace_alternatives and formatters["value %a, taking %a"](value,r) - elseif value == "first" then - return alternatives[1], trace_alternatives and formatters["value %a, taking %a"](value,1) - elseif value == "last" then - return alternatives[n], trace_alternatives and formatters["value %a, taking %a"](value,n) - end - value = value == true and 1 or tonumber(value) - if type(value) ~= "number" then - return alternatives[1], trace_alternatives and formatters["invalid value %s, taking %a"](value,1) - end - -- local a = alternatives[value] - -- if a then - -- -- some kind of hash - -- return a, trace_alternatives and formatters["value %a, taking %a"](value,a) - -- end - if value > n then - local defaultalt = otf.defaultnodealternate - if defaultalt == "first" then - return alternatives[n], trace_alternatives and formatters["invalid value %s, taking %a"](value,1) - elseif defaultalt == "last" then - return alternatives[1], trace_alternatives and formatters["invalid value %s, taking %a"](value,n) - else - return false, trace_alternatives and formatters["invalid value %a, %s"](value,"out of range") - end - elseif value == 0 then - return getchar(start), trace_alternatives and formatters["invalid value %a, %s"](value,"no change") - elseif value < 1 then - return alternatives[1], trace_alternatives and formatters["invalid value %a, taking %a"](value,1) - else - return alternatives[value], trace_alternatives and formatters["value %a, taking %a"](value,value) - end -end - --- handlers - -function handlers.gsub_single(head,start,dataset,sequence,replacement) - if trace_singles then - logprocess("%s: replacing %s by single %s",pref(dataset,sequence),gref(getchar(start)),gref(replacement)) - end - resetinjection(start) - setchar(start,replacement) - return head, start, true -end - -function handlers.gsub_alternate(head,start,dataset,sequence,alternative) - local kind = dataset[4] - local what = dataset[1] - local value = what == true and tfmdata.shared.features[kind] or what - local choice, comment = get_alternative_glyph(start,alternative,value) - if choice then - if trace_alternatives then - logprocess("%s: replacing %s by alternative %a to %s, %s",pref(dataset,sequence),gref(getchar(start)),gref(choice),comment) - end - resetinjection(start) - setchar(start,choice) - else - if trace_alternatives then - logwarning("%s: no variant %a for %s, %s",pref(dataset,sequence),value,gref(getchar(start)),comment) - end - end - return head, start, true -end - -function handlers.gsub_multiple(head,start,dataset,sequence,multiple) - if trace_multiples then - logprocess("%s: replacing %s by multiple %s",pref(dataset,sequence),gref(getchar(start)),gref(multiple)) - end - return multiple_glyphs(head,start,multiple,sequence.flags[1],dataset[1]) -end - -function handlers.gsub_ligature(head,start,dataset,sequence,ligature) - local current = getnext(start) - if not current then - return head, start, false, nil - end - local stop = nil - local startchar = getchar(start) - if marks[startchar] then - while current do - local char = ischar(current,currentfont) - if char then - local lg = ligature[char] - if lg then - stop = current - ligature = lg - current = getnext(current) - else - break - end - else - break - end - end - if stop then - local lig = ligature.ligature - if lig then - if trace_ligatures then - local stopchar = getchar(stop) - head, start = markstoligature(head,start,stop,lig) - logprocess("%s: replacing %s upto %s by ligature %s case 1",pref(dataset,sequence),gref(startchar),gref(stopchar),gref(getchar(start))) - else - head, start = markstoligature(head,start,stop,lig) - end - return head, start, true, false - else - -- ok, goto next lookup - end - end - else - local skipmark = sequence.flags[1] - local discfound = false - local lastdisc = nil - while current do - local char, id = ischar(current,currentfont) - if char then - if skipmark and marks[char] then - current = getnext(current) - else -- ligature is a tree - local lg = ligature[char] -- can there be multiple in a row? maybe in a bad font - if lg then - if not discfound and lastdisc then - discfound = lastdisc - lastdisc = nil - end - stop = current -- needed for fake so outside then - ligature = lg - current = getnext(current) - else - break - end - end - elseif char == false then - -- kind of weird - break - elseif id == disc_code then - -- tricky .. we also need to do pre here - local replace = getfield(current,"replace") - if replace then - -- of{f-}{}{f}e o{f-}{}{f}fe o{-}{}{ff}e (oe and ff ligature) - -- we can end up here when we have a start run .. testruns start at a disc but - -- so here we have the other case: char + disc - while replace do - local char, id = ischar(replace,currentfont) - if char then - local lg = ligature[char] -- can there be multiple in a row? maybe in a bad font - if lg then - ligature = lg - replace = getnext(replace) - else - return head, start, false, false - end - else - return head, start, false, false - end - end - stop = current - end - lastdisc = current - current = getnext(current) - else - break - end - end - local lig = ligature.ligature - if lig then - if stop then - if trace_ligatures then - local stopchar = getchar(stop) - head, start = toligature(head,start,stop,lig,dataset,sequence,skipmark,discfound) - logprocess("%s: replacing %s upto %s by ligature %s case 2",pref(dataset,sequence),gref(startchar),gref(stopchar),gref(lig)) - else - head, start = toligature(head,start,stop,lig,dataset,sequence,skipmark,discfound) - end - else - -- weird but happens (in some arabic font) - resetinjection(start) - setchar(start,lig) - if trace_ligatures then - logprocess("%s: replacing %s by (no real) ligature %s case 3",pref(dataset,sequence),gref(startchar),gref(lig)) - end - end - return head, start, true, discfound - else - -- weird but happens, pseudo ligatures ... just the components - end - end - return head, start, false, discfound -end - -function handlers.gpos_single(head,start,dataset,sequence,kerns,rlmode,step,i,injection) - local startchar = getchar(start) - if step.format == "pair" then - local dx, dy, w, h = setpair(start,factor,rlmode,sequence.flags[4],kerns,injection) - if trace_kerns then - logprocess("%s: shifting single %s by (%p,%p) and correction (%p,%p)",pref(dataset,sequence),gref(startchar),dx,dy,w,h) - end - else - -- needs checking .. maybe no kerns format for single - local k = setkern(start,factor,rlmode,kerns,injection) - if trace_kerns then - logprocess("%s: shifting single %s by %p",pref(dataset,sequence),gref(startchar),k) - end - end - return head, start, false -end - -function handlers.gpos_pair(head,start,dataset,sequence,kerns,rlmode,step,i,injection) - local snext = getnext(start) - if not snext then - return head, start, false - else - local prev = start - local done = false - while snext do - local nextchar = ischar(snext,currentfont) - if nextchar then - local krn = kerns[nextchar] - if not krn and marks[nextchar] then - prev = snext - snext = getnext(snext) - elseif not krn then - break - elseif step.format == "pair" then - local a, b = krn[1], krn[2] - if optimizekerns then - -- this permits a mixed table, but we could also decide to optimize this - -- in the loader and use format 'kern' - if not b and a[1] == 0 and a[2] == 0 and a[4] == 0 then - local k = setkern(snext,factor,rlmode,a[3],injection) - if trace_kerns then - logprocess("%s: shifting single %s by %p",pref(dataset,sequence),gref(nextchar),k) - end - done = true - break - end - end - if a and #a > 0 then - local x, y, w, h = setpair(start,factor,rlmode,sequence.flags[4],a,injection) - if trace_kerns then - local startchar = getchar(start) - logprocess("%s: shifting first of pair %s and %s by (%p,%p) and correction (%p,%p) as %s",pref(dataset,sequence),gref(startchar),gref(nextchar),x,y,w,h,injection or "injections") - end - end - if b and #b > 0 then - local x, y, w, h = setpair(snext,factor,rlmode,sequence.flags[4],b,injection) - if trace_kerns then - local startchar = getchar(snext) - logprocess("%s: shifting second of pair %s and %s by (%p,%p) and correction (%p,%p) as %s",pref(dataset,sequence),gref(startchar),gref(nextchar),x,y,w,h,injection or "injections") - end - end - done = true - break - elseif krn ~= 0 then - local k = setkern(snext,factor,rlmode,krn,injection) - if trace_kerns then - logprocess("%s: inserting kern %p between %s and %s as %s",pref(dataset,sequence),k,gref(getchar(prev)),gref(nextchar),injection or "injections") - end - done = true - break - else -- can't happen - break - end - else - break - end - end - return head, start, done - end -end - ---[[ldx-- -<p>We get hits on a mark, but we're not sure if the it has to be applied so -we need to explicitly test for basechar, baselig and basemark entries.</p> ---ldx]]-- - -function handlers.gpos_mark2base(head,start,dataset,sequence,markanchors,rlmode) - local markchar = getchar(start) - if marks[markchar] then - local base = getprev(start) -- [glyph] [start=mark] - if base then - local basechar = ischar(base,currentfont) - if basechar then - if marks[basechar] then - while base do - base = getprev(base) - if base then - basechar = ischar(base,currentfont) - if basechar then - if not marks[basechar] then - break - end - else - if trace_bugs then - logwarning("%s: no base for mark %s, case %i",pref(dataset,sequence),gref(markchar),1) - end - return head, start, false - end - else - if trace_bugs then - logwarning("%s: no base for mark %s, case %i",pref(dataset,sequence),gref(markchar),2) - end - return head, start, false - end - end - end - local ba = markanchors[1][basechar] - if ba then - local ma = markanchors[2] - local dx, dy, bound = setmark(start,base,factor,rlmode,ba,ma,characters[basechar],false,checkmarks) - if trace_marks then - logprocess("%s, anchor %s, bound %s: anchoring mark %s to basechar %s => (%p,%p)", - pref(dataset,sequence),anchor,bound,gref(markchar),gref(basechar),dx,dy) - end - return head, start, true - end - elseif trace_bugs then - logwarning("%s: nothing preceding, case %i",pref(dataset,sequence),1) - end - elseif trace_bugs then - logwarning("%s: nothing preceding, case %i",pref(dataset,sequence),2) - end - elseif trace_bugs then - logwarning("%s: mark %s is no mark",pref(dataset,sequence),gref(markchar)) - end - return head, start, false -end - -function handlers.gpos_mark2ligature(head,start,dataset,sequence,markanchors,rlmode) - local markchar = getchar(start) - if marks[markchar] then - local base = getprev(start) -- [glyph] [optional marks] [start=mark] - if base then - local basechar = ischar(base,currentfont) - if basechar then - if marks[basechar] then - while base do - base = getprev(base) - if base then - basechar = ischar(base,currentfont) - if basechar then - if not marks[basechar] then - break - end - else - if trace_bugs then - logwarning("%s: no base for mark %s, case %i",pref(dataset,sequence),gref(markchar),1) - end - return head, start, false - end - else - if trace_bugs then - logwarning("%s: no base for mark %s, case %i",pref(dataset,sequence),gref(markchar),2) - end - return head, start, false - end - end - end - local ba = markanchors[1][basechar] - if ba then - local ma = markanchors[2] - if ma then - local index = getligaindex(start) - ba = ba[index] - if ba then - local dx, dy, bound = setmark(start,base,factor,rlmode,ba,ma,characters[basechar],false,checkmarks) - if trace_marks then - logprocess("%s, anchor %s, index %s, bound %s: anchoring mark %s to baselig %s at index %s => (%p,%p)", - pref(dataset,sequence),anchor,index,bound,gref(markchar),gref(basechar),index,dx,dy) - end - return head, start, true - else - if trace_bugs then - logwarning("%s: no matching anchors for mark %s and baselig %s with index %a",pref(dataset,sequence),gref(markchar),gref(basechar),index) - end - end - end - elseif trace_bugs then - -- logwarning("%s: char %s is missing in font",pref(dataset,sequence),gref(basechar)) - onetimemessage(currentfont,basechar,"no base anchors",report_fonts) - end - elseif trace_bugs then - logwarning("%s: prev node is no char, case %i",pref(dataset,sequence),1) - end - elseif trace_bugs then - logwarning("%s: prev node is no char, case %i",pref(dataset,sequence),2) - end - elseif trace_bugs then - logwarning("%s: mark %s is no mark",pref(dataset,sequence),gref(markchar)) - end - return head, start, false -end - -function handlers.gpos_mark2mark(head,start,dataset,sequence,markanchors,rlmode) - local markchar = getchar(start) - if marks[markchar] then - local base = getprev(start) -- [glyph] [basemark] [start=mark] - local slc = getligaindex(start) - if slc then -- a rather messy loop ... needs checking with husayni - while base do - local blc = getligaindex(base) - if blc and blc ~= slc then - base = getprev(base) - else - break - end - end - end - if base then - local basechar = ischar(base,currentfont) - if basechar then -- subtype test can go - local ba = markanchors[1][basechar] -- slot 1 has been made copy of the class hash - if ba then - local ma = markanchors[2] - local dx, dy, bound = setmark(start,base,factor,rlmode,ba,ma,characters[basechar],true,checkmarks) - if trace_marks then - logprocess("%s, anchor %s, bound %s: anchoring mark %s to basemark %s => (%p,%p)", - pref(dataset,sequence),anchor,bound,gref(markchar),gref(basechar),dx,dy) - end - return head, start, true - end - end - end - elseif trace_bugs then - logwarning("%s: mark %s is no mark",pref(dataset,sequence),gref(markchar)) - end - return head, start, false -end - -function handlers.gpos_cursive(head,start,dataset,sequence,exitanchors,rlmode,step,i) -- to be checked - local done = false - local startchar = getchar(start) - if marks[startchar] then - if trace_cursive then - logprocess("%s: ignoring cursive for mark %s",pref(dataset,sequence),gref(startchar)) - end - else - local nxt = getnext(start) - while not done and nxt do - local nextchar = ischar(nxt,currentfont) - if not nextchar then - break - elseif marks[nextchar] then - -- should not happen (maybe warning) - nxt = getnext(nxt) - else - local exit = exitanchors[3] - if exit then - local entry = exitanchors[1][nextchar] - if entry then - entry = entry[2] - if entry then - local dx, dy, bound = setcursive(start,nxt,factor,rlmode,exit,entry,characters[startchar],characters[nextchar]) - if trace_cursive then - logprocess("%s: moving %s to %s cursive (%p,%p) using anchor %s and bound %s in %s mode",pref(dataset,sequence),gref(startchar),gref(nextchar),dx,dy,anchor,bound,mref(rlmode)) - end - done = true - end - end - end - break - end - end - end - return head, start, done -end - ---[[ldx-- -<p>I will implement multiple chain replacements once I run into a font that uses -it. It's not that complex to handle.</p> ---ldx]]-- - -local chainprocs = { } - -local function logprocess(...) - if trace_steps then - registermessage(...) - end - report_subchain(...) -end - -local logwarning = report_subchain - -local function logprocess(...) - if trace_steps then - registermessage(...) - end - report_chain(...) -end - -local logwarning = report_chain - --- We could share functions but that would lead to extra function calls with many --- arguments, redundant tests and confusing messages. - --- The reversesub is a special case, which is why we need to store the replacements --- in a bit weird way. There is no lookup and the replacement comes from the lookup --- itself. It is meant mostly for dealing with Urdu. - -local function reversesub(head,start,stop,dataset,sequence,replacements,rlmode) - local char = getchar(start) - local replacement = replacements[char] - if replacement then - if trace_singles then - logprocess("%s: single reverse replacement of %s by %s",cref(dataset,sequence),gref(char),gref(replacement)) - end - resetinjection(start) - setchar(start,replacement) - return head, start, true - else - return head, start, false - end -end - - -chainprocs.reversesub = reversesub - ---[[ldx-- -<p>This chain stuff is somewhat tricky since we can have a sequence of actions to be -applied: single, alternate, multiple or ligature where ligature can be an invalid -one in the sense that it will replace multiple by one but not neccessary one that -looks like the combination (i.e. it is the counterpart of multiple then). For -example, the following is valid:</p> - -<typing> -<line>xxxabcdexxx [single a->A][multiple b->BCD][ligature cde->E] xxxABCDExxx</line> -</typing> - -<p>Therefore we we don't really do the replacement here already unless we have the -single lookup case. The efficiency of the replacements can be improved by deleting -as less as needed but that would also make the code even more messy.</p> ---ldx]]-- - ---[[ldx-- -<p>Here we replace start by a single variant.</p> ---ldx]]-- - --- To be done (example needed): what if > 1 steps - --- this is messy: do we need this disc checking also in alternaties? - -local function reportmoresteps(dataset,sequence) - logwarning("%s: more than 1 step",cref(dataset,sequence)) -end - -function chainprocs.gsub_single(head,start,stop,dataset,sequence,currentlookup,chainindex) - local steps = currentlookup.steps - local nofsteps = currentlookup.nofsteps - if nofsteps > 1 then - reportmoresteps(dataset,sequence) - end - local current = start - while current do - local currentchar = ischar(current) - if currentchar then - local replacement = steps[1].coverage[currentchar] - if not replacement or replacement == "" then - if trace_bugs then - logwarning("%s: no single for %s",cref(dataset,sequence,chainindex),gref(currentchar)) - end - else - if trace_singles then - logprocess("%s: replacing single %s by %s",cref(dataset,sequence,chainindex),gref(currentchar),gref(replacement)) - end - resetinjection(current) - setchar(current,replacement) - end - return head, start, true - elseif currentchar == false then - -- can't happen - break - elseif current == stop then - break - else - current = getnext(current) - end - end - return head, start, false -end - ---[[ldx-- -<p>Here we replace start by a sequence of new glyphs.</p> ---ldx]]-- - -function chainprocs.gsub_multiple(head,start,stop,dataset,sequence,currentlookup) - local steps = currentlookup.steps - local nofsteps = currentlookup.nofsteps - if nofsteps > 1 then - reportmoresteps(dataset,sequence) - end - local startchar = getchar(start) - local replacement = steps[1].coverage[startchar] - if not replacement or replacement == "" then - if trace_bugs then - logwarning("%s: no multiple for %s",cref(dataset,sequence),gref(startchar)) - end - else - if trace_multiples then - logprocess("%s: replacing %s by multiple characters %s",cref(dataset,sequence),gref(startchar),gref(replacement)) - end - return multiple_glyphs(head,start,replacement,sequence.flags[1],dataset[1]) - end - return head, start, false -end - ---[[ldx-- -<p>Here we replace start by new glyph. First we delete the rest of the match.</p> ---ldx]]-- - --- char_1 mark_1 -> char_x mark_1 (ignore marks) --- char_1 mark_1 -> char_x - --- to be checked: do we always have just one glyph? --- we can also have alternates for marks --- marks come last anyway --- are there cases where we need to delete the mark - -function chainprocs.gsub_alternate(head,start,stop,dataset,sequence,currentlookup) - local steps = currentlookup.steps - local nofsteps = currentlookup.nofsteps - if nofsteps > 1 then - reportmoresteps(dataset,sequence) - end - local kind = dataset[4] - local what = dataset[1] - local value = what == true and tfmdata.shared.features[kind] or what -- todo: optimize in ctx - local current = start - while current do - local currentchar = ischar(current) - if currentchar then - local alternatives = steps[1].coverage[currentchar] - if alternatives then - local choice, comment = get_alternative_glyph(current,alternatives,value) - if choice then - if trace_alternatives then - logprocess("%s: replacing %s by alternative %a to %s, %s",cref(dataset,sequence),gref(char),choice,gref(choice),comment) - end - resetinjection(start) - setchar(start,choice) - else - if trace_alternatives then - logwarning("%s: no variant %a for %s, %s",cref(dataset,sequence),value,gref(char),comment) - end - end - end - return head, start, true - elseif currentchar == false then - -- can't happen - break - elseif current == stop then - break - else - current = getnext(current) - end - end - return head, start, false -end - ---[[ldx-- -<p>When we replace ligatures we use a helper that handles the marks. I might change -this function (move code inline and handle the marks by a separate function). We -assume rather stupid ligatures (no complex disc nodes).</p> ---ldx]]-- - -function chainprocs.gsub_ligature(head,start,stop,dataset,sequence,currentlookup,chainindex) - local steps = currentlookup.steps - local nofsteps = currentlookup.nofsteps - if nofsteps > 1 then - reportmoresteps(dataset,sequence) - end - local startchar = getchar(start) - local ligatures = steps[1].coverage[startchar] - if not ligatures then - if trace_bugs then - logwarning("%s: no ligatures starting with %s",cref(dataset,sequence,chainindex),gref(startchar)) - end - else - local current = getnext(start) - local discfound = false - local last = stop - local nofreplacements = 1 - local skipmark = currentlookup.flags[1] -- sequence.flags? - while current do - -- todo: ischar ... can there really be disc nodes here? - local id = getid(current) - if id == disc_code then - if not discfound then - discfound = current - end - if current == stop then - break -- okay? or before the disc - else - current = getnext(current) - end - else - local schar = getchar(current) - if skipmark and marks[schar] then -- marks - -- if current == stop then -- maybe add this - -- break - -- else - current = getnext(current) - -- end - else - local lg = ligatures[schar] - if lg then - ligatures = lg - last = current - nofreplacements = nofreplacements + 1 - if current == stop then - break - else - current = getnext(current) - end - else - break - end - end - end - end - local ligature = ligatures.ligature - if ligature then - if chainindex then - stop = last - end - if trace_ligatures then - if start == stop then - logprocess("%s: replacing character %s by ligature %s case 3",cref(dataset,sequence,chainindex),gref(startchar),gref(ligature)) - else - logprocess("%s: replacing character %s upto %s by ligature %s case 4",cref(dataset,sequence,chainindex),gref(startchar),gref(getchar(stop)),gref(ligature)) - end - end - head, start = toligature(head,start,stop,ligature,dataset,sequence,skipmark,discfound) - return head, start, true, nofreplacements, discfound - elseif trace_bugs then - if start == stop then - logwarning("%s: replacing character %s by ligature fails",cref(dataset,sequence,chainindex),gref(startchar)) - else - logwarning("%s: replacing character %s upto %s by ligature fails",cref(dataset,sequence,chainindex),gref(startchar),gref(getchar(stop))) - end - end - end - return head, start, false, 0, false -end - -function chainprocs.gpos_single(head,start,stop,dataset,sequence,currentlookup,rlmode,chainindex) - local steps = currentlookup.steps - local nofsteps = currentlookup.nofsteps - if nofsteps > 1 then - reportmoresteps(dataset,sequence) - end - local startchar = getchar(start) - local step = steps[1] - local kerns = step.coverage[startchar] - if not kerns then - -- skip - elseif step.format == "pair" then - local dx, dy, w, h = setpair(start,factor,rlmode,sequence.flags[4],kerns) -- currentlookup.flags ? - if trace_kerns then - logprocess("%s: shifting single %s by (%p,%p) and correction (%p,%p)",cref(dataset,sequence),gref(startchar),dx,dy,w,h) - end - else -- needs checking .. maybe no kerns format for single - local k = setkern(start,factor,rlmode,kerns,injection) - if trace_kerns then - logprocess("%s: shifting single %s by %p",cref(dataset,sequence),gref(startchar),k) - end - end - return head, start, false -end - -function chainprocs.gpos_pair(head,start,stop,dataset,sequence,currentlookup,rlmode,chainindex) -- todo: injections ? - local steps = currentlookup.steps - local nofsteps = currentlookup.nofsteps - if nofsteps > 1 then - reportmoresteps(dataset,sequence) - end - local snext = getnext(start) - if snext then - local startchar = getchar(start) - local step = steps[1] - local kerns = step.coverage[startchar] -- always 1 step - if kerns then - local prev = start - local done = false - while snext do - local nextchar = ischar(snext,currentfont) - if not nextchar then - break - end - local krn = kerns[nextchar] - if not krn and marks[nextchar] then - prev = snext - snext = getnext(snext) - elseif not krn then - break - elseif step.format == "pair" then - local a, b = krn[1], krn[2] - if optimizekerns then - -- this permits a mixed table, but we could also decide to optimize this - -- in the loader and use format 'kern' - if not b and a[1] == 0 and a[2] == 0 and a[4] == 0 then - local k = setkern(snext,factor,rlmode,a[3],"injections") - if trace_kerns then - logprocess("%s: shifting single %s by %p",cref(dataset,sequence),gref(startchar),k) - end - done = true - break - end - end - if a and #a > 0 then - local startchar = getchar(start) - local x, y, w, h = setpair(start,factor,rlmode,sequence.flags[4],a,"injections") -- currentlookups flags? - if trace_kerns then - logprocess("%s: shifting first of pair %s and %s by (%p,%p) and correction (%p,%p)",cref(dataset,sequence),gref(startchar),gref(nextchar),x,y,w,h) - end - end - if b and #b > 0 then - local startchar = getchar(start) - local x, y, w, h = setpair(snext,factor,rlmode,sequence.flags[4],b,"injections") - if trace_kerns then - logprocess("%s: shifting second of pair %s and %s by (%p,%p) and correction (%p,%p)",cref(dataset,sequence),gref(startchar),gref(nextchar),x,y,w,h) - end - end - done = true - break - elseif krn ~= 0 then - local k = setkern(snext,factor,rlmode,krn) - if trace_kerns then - logprocess("%s: inserting kern %s between %s and %s",cref(dataset,sequence),k,gref(getchar(prev)),gref(nextchar)) - end - done = true - break - else - break - end - end - return head, start, done - end - end - return head, start, false -end - -function chainprocs.gpos_mark2base(head,start,stop,dataset,sequence,currentlookup,rlmode) - local steps = currentlookup.steps - local nofsteps = currentlookup.nofsteps - if nofsteps > 1 then - reportmoresteps(dataset,sequence) - end - local markchar = getchar(start) - if marks[markchar] then - local markanchors = steps[1].coverage[markchar] -- always 1 step - if markanchors then - local base = getprev(start) -- [glyph] [start=mark] - if base then - local basechar = ischar(base,currentfont) - if basechar then - if marks[basechar] then - while base do - base = getprev(base) - if base then - local basechar = ischar(base,currentfont) - if basechar then - if not marks[basechar] then - break - end - else - if trace_bugs then - logwarning("%s: no base for mark %s, case %i",pref(dataset,sequence),gref(markchar),1) - end - return head, start, false - end - else - if trace_bugs then - logwarning("%s: no base for mark %s, case %i",pref(dataset,sequence),gref(markchar),2) - end - return head, start, false - end - end - end - local ba = markanchors[1][basechar] - if ba then - local ma = markanchors[2] - if ma then - local dx, dy, bound = setmark(start,base,factor,rlmode,ba,ma,characters[basechar],false,checkmarks) - if trace_marks then - logprocess("%s, anchor %s, bound %s: anchoring mark %s to basechar %s => (%p,%p)", - cref(dataset,sequence),anchor,bound,gref(markchar),gref(basechar),dx,dy) - end - return head, start, true - end - end - elseif trace_bugs then - logwarning("%s: prev node is no char, case %i",cref(dataset,sequence),1) - end - elseif trace_bugs then - logwarning("%s: prev node is no char, case %i",cref(dataset,sequence),2) - end - elseif trace_bugs then - logwarning("%s: mark %s has no anchors",cref(dataset,sequence),gref(markchar)) - end - elseif trace_bugs then - logwarning("%s: mark %s is no mark",cref(dataset,sequence),gref(markchar)) - end - return head, start, false -end - -function chainprocs.gpos_mark2ligature(head,start,stop,dataset,sequence,currentlookup,rlmode) - local steps = currentlookup.steps - local nofsteps = currentlookup.nofsteps - if nofsteps > 1 then - reportmoresteps(dataset,sequence) - end - local markchar = getchar(start) - if marks[markchar] then - local markanchors = steps[1].coverage[markchar] -- always 1 step - if markanchors then - local base = getprev(start) -- [glyph] [optional marks] [start=mark] - if base then - local basechar = ischar(base,currentfont) - if basechar then - if marks[basechar] then - while base do - base = getprev(base) - if base then - local basechar = ischar(base,currentfont) - if basechar then - if not marks[basechar] then - break - end - else - if trace_bugs then - logwarning("%s: no base for mark %s, case %i",cref(dataset,sequence),markchar,1) - end - return head, start, false - end - else - if trace_bugs then - logwarning("%s: no base for mark %s, case %i",cref(dataset,sequence),markchar,2) - end - return head, start, false - end - end - end - local ba = markanchors[1][basechar] - if ba then - local ma = markanchors[2] - if ma then - local index = getligaindex(start) - ba = ba[index] - if ba then - local dx, dy, bound = setmark(start,base,factor,rlmode,ba,ma,characters[basechar],false,checkmarks) - if trace_marks then - logprocess("%s, anchor %s, bound %s: anchoring mark %s to baselig %s at index %s => (%p,%p)", - cref(dataset,sequence),anchor,a or bound,gref(markchar),gref(basechar),index,dx,dy) - end - return head, start, true - end - end - end - elseif trace_bugs then - logwarning("%s, prev node is no char, case %i",cref(dataset,sequence),1) - end - elseif trace_bugs then - logwarning("%s, prev node is no char, case %i",cref(dataset,sequence),2) - end - elseif trace_bugs then - logwarning("%s, mark %s has no anchors",cref(dataset,sequence),gref(markchar)) - end - elseif trace_bugs then - logwarning("%s, mark %s is no mark",cref(dataset,sequence),gref(markchar)) - end - return head, start, false -end - -function chainprocs.gpos_mark2mark(head,start,stop,dataset,sequence,currentlookup,rlmode) - local steps = currentlookup.steps - local nofsteps = currentlookup.nofsteps - if nofsteps > 1 then - reportmoresteps(dataset,sequence) - end - local markchar = getchar(start) - if marks[markchar] then - local markanchors = steps[1].coverage[markchar] -- always 1 step - if markanchors then - local base = getprev(start) -- [glyph] [basemark] [start=mark] - local slc = getligaindex(start) - if slc then -- a rather messy loop ... needs checking with husayni - while base do - local blc = getligaindex(base) - if blc and blc ~= slc then - base = getprev(base) - else - break - end - end - end - if base then -- subtype test can go - local basechar = ischar(base,currentfont) - if basechar then - local ba = markanchors[1][basechar] - if ba then - local ma = markanchors[2] - if ma then - local dx, dy, bound = setmark(start,base,factor,rlmode,ba,ma,characters[basechar],true,checkmarks) - if trace_marks then - logprocess("%s, anchor %s, bound %s: anchoring mark %s to basemark %s => (%p,%p)", - cref(dataset,sequence),anchor,bound,gref(markchar),gref(basechar),dx,dy) - end - return head, start, true - end - end - elseif trace_bugs then - logwarning("%s: prev node is no mark, case %i",cref(dataset,sequence),1) - end - elseif trace_bugs then - logwarning("%s: prev node is no mark, case %i",cref(dataset,sequence),2) - end - elseif trace_bugs then - logwarning("%s: mark %s has no anchors",cref(dataset,sequence),gref(markchar)) - end - elseif trace_bugs then - logwarning("%s: mark %s is no mark",cref(dataset,sequence),gref(markchar)) - end - return head, start, false -end - -function chainprocs.gpos_cursive(head,start,stop,dataset,sequence,currentlookup,rlmode) - local steps = currentlookup.steps - local nofsteps = currentlookup.nofsteps - if nofsteps > 1 then - reportmoresteps(dataset,sequence) - end - local startchar = getchar(start) - local exitanchors = steps[1].coverage[startchar] -- always 1 step - if exitanchors then - local done = false - if marks[startchar] then - if trace_cursive then - logprocess("%s: ignoring cursive for mark %s",pref(dataset,sequence),gref(startchar)) - end - else - local nxt = getnext(start) - while not done and nxt do - local nextchar = ischar(nxt,currentfont) - if not nextchar then - break - elseif marks[nextchar] then - -- should not happen (maybe warning) - nxt = getnext(nxt) - else - local exit = exitanchors[3] - if exit then - local entry = exitanchors[1][nextchar] - if entry then - entry = entry[2] - if entry then - local dx, dy, bound = setcursive(start,nxt,factor,rlmode,exit,entry,characters[startchar],characters[nextchar]) - if trace_cursive then - logprocess("%s: moving %s to %s cursive (%p,%p) using anchor %s and bound %s in %s mode",pref(dataset,sequence),gref(startchar),gref(nextchar),dx,dy,anchor,bound,mref(rlmode)) - end - done = true - break - end - end - elseif trace_bugs then - onetimemessage(currentfont,startchar,"no entry anchors",report_fonts) - end - break - end - end - end - return head, start, done - else - if trace_cursive and trace_details then - logprocess("%s, cursive %s is already done",pref(dataset,sequence),gref(getchar(start)),alreadydone) - end - return head, start, false - end -end - --- what pointer to return, spec says stop --- to be discussed ... is bidi changer a space? --- elseif char == zwnj and sequence[n][32] then -- brrr - -local function show_skip(dataset,sequence,char,ck,class) - logwarning("%s: skipping char %s, class %a, rule %a, lookuptype %a",cref(dataset,sequence),gref(char),class,ck[1],ck[8] or ck[2]) -end - --- A previous version had disc collapsing code in the (single sub) handler plus some --- checking in the main loop, but that left the pre/post sequences undone. The best --- solution is to add some checking there and backtrack when a replace/post matches --- but it takes a bit of work to figure out an efficient way (this is what the sweep* --- names refer to). I might look into that variant one day again as it can replace --- some other code too. In that approach we can have a special version for gub and pos --- which gains some speed. This method does the test and passes info to the handlers --- (sweepnode, sweepmode, sweepprev, sweepnext, etc). Here collapsing is handled in the --- main loop which also makes code elsewhere simpler (i.e. no need for the other special --- runners and disc code in ligature building). I also experimented with pushing preceding --- glyphs sequences in the replace/pre fields beforehand which saves checking afterwards --- but at the cost of duplicate glyphs (memory) but it's too much overhead (runtime). --- --- In the meantime Kai had moved the code from the single chain into a more general handler --- and this one (renamed to chaindisk) is used now. I optimized the code a bit and brought --- it in sycn with the other code. Hopefully I didn't introduce errors. Note: this somewhat --- complex approach is meant for fonts that implement (for instance) ligatures by character --- replacement which to some extend is not that suitable for hyphenation. I also use some --- helpers. This method passes some states but reparses the list. There is room for a bit of --- speed up but that will be done in the context version. (In fact a partial rewrite of all --- code can bring some more efficientry.) --- --- I didn't test it with extremes but successive disc nodes still can give issues but in --- order to handle that we need more complex code which also slows down even more. The main --- loop variant could deal with that: test, collapse, backtrack. - -local new_kern = nuts.pool.kern - -local function checked(head) - local current = head - while current do - if getid(current) == glue_code then - local kern = new_kern(getfield(current,"width")) - if head == current then - local next = getnext(current) - if next then - setlink(kern,next) - end - flush_node(current) - head = kern - current = next - else - local prev, next = getboth(current) - setlink(prev,kern) - setlink(kern,next) - flush_node(current) - current = next - end - else - current = getnext(current) - end - end - return head -end - -local function setdiscchecked(d,pre,post,replace) - if pre then pre = checked(pre) end - if post then post = checked(post) end - if replace then replace = checked(replace) end - setdisc(d,pre,post,replace) -end - -local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,ck,chainproc) - - if not start then - return head, start, false - end - - local startishead = start == head - local seq = ck[3] - local f = ck[4] - local l = ck[5] - local s = #seq - local done = false - local sweepnode = sweepnode - local sweeptype = sweeptype - local sweepoverflow = false - local checkdisc = getprev(head) -- hm bad name head - local keepdisc = not sweepnode - local lookaheaddisc = nil - local backtrackdisc = nil - local current = start - local last = start - local prev = getprev(start) - local hasglue = false - - -- fishy: so we can overflow and then go on in the sweep? - -- todo : id can also be glue_code as we checked spaces - - local i = f - while i <= l do - local id = getid(current) - if id == glyph_code then - i = i + 1 - last = current - current = getnext(current) - elseif id == glue_code then - i = i + 1 - last = current - current = getnext(current) - hasglue = true - elseif id == disc_code then - if keepdisc then - keepdisc = false - if notmatchpre[current] ~= notmatchreplace[current] then - lookaheaddisc = current - end - local replace = getfield(current,"replace") - while replace and i <= l do - if getid(replace) == glyph_code then - i = i + 1 - end - replace = getnext(replace) - end - last = current - current = getnext(c) - else - head, current = flattendisk(head,current) - end - else - last = current - current = getnext(current) - end - if current then - -- go on - elseif sweepoverflow then - -- we already are folling up on sweepnode - break - elseif sweeptype == "post" or sweeptype == "replace" then - current = getnext(sweepnode) - if current then - sweeptype = nil - sweepoverflow = true - else - break - end - else - break -- added - end - end - - if sweepoverflow then - local prev = current and getprev(current) - if not current or prev ~= sweepnode then - local head = getnext(sweepnode) - local tail = nil - if prev then - tail = prev - setprev(current,sweepnode) - else - tail = find_node_tail(head) - end - setnext(sweepnode,current) - setprev(head) - setnext(tail) - appenddisc(sweepnode,head) - end - end - - if l < s then - local i = l - local t = sweeptype == "post" or sweeptype == "replace" - while current and i < s do - local id = getid(current) - if id == glyph_code then - i = i + 1 - current = getnext(current) - elseif id == glue_code then - i = i + 1 - current = getnext(current) - hasglue = true - elseif id == disc_code then - if keepdisc then - keepdisc = false - if notmatchpre[current] ~= notmatchreplace[current] then - lookaheaddisc = current - end - local replace = getfield(c,"replace") - while replace and i < s do - if getid(replace) == glyph_code then - i = i + 1 - end - replace = getnext(replace) - end - current = getnext(current) - elseif notmatchpre[current] ~= notmatchreplace[current] then - head, current = flattendisk(head,current) - else - current = getnext(current) -- HH - end - else - current = getnext(current) - end - if not current and t then - current = getnext(sweepnode) - if current then - sweeptype = nil - end - end - end - end - - if f > 1 then - local current = prev - local i = f - local t = sweeptype == "pre" or sweeptype == "replace" - if not current and t and current == checkdisk then - current = getprev(sweepnode) - end - while current and i > 1 do -- missing getprev added / moved outside - local id = getid(current) - if id == glyph_code then - i = i - 1 - elseif id == glue_code then - i = i - 1 - hasglue = true - elseif id == disc_code then - if keepdisc then - keepdisc = false - if notmatchpost[current] ~= notmatchreplace[current] then - backtrackdisc = current - end - local replace = getfield(current,"replace") - while replace and i > 1 do - if getid(replace) == glyph_code then - i = i - 1 - end - replace = getnext(replace) - end - elseif notmatchpost[current] ~= notmatchreplace[current] then - head, current = flattendisk(head,current) - end - end - current = getprev(current) - if t and current == checkdisk then - current = getprev(sweepnode) - end - end - end - - local ok = false - if lookaheaddisc then - - local cf = start - local cl = getprev(lookaheaddisc) - local cprev = getprev(start) - local insertedmarks = 0 - - while cprev do - local char = ischar(cf,currentfont) - if char and marks[char] then - insertedmarks = insertedmarks + 1 - cf = cprev - startishead = cf == head - cprev = getprev(cprev) - else - break - end - end - - setprev(lookaheaddisc,cprev) - if cprev then - setnext(cprev,lookaheaddisc) - end - setprev(cf) - setnext(cl) - if startishead then - head = lookaheaddisc - end - local pre, post, replace = getdisc(lookaheaddisc) - local new = copy_node_list(cf) - local cnew = new - for i=1,insertedmarks do - cnew = getnext(cnew) - end - local clast = cnew - for i=f,l do - clast = getnext(clast) - end - if not notmatchpre[lookaheaddisc] then - cf, start, ok = chainproc(cf,start,last,dataset,sequence,chainlookup,rlmode,k) - end - if not notmatchreplace[lookaheaddisc] then - new, cnew, ok = chainproc(new,cnew,clast,dataset,sequence,chainlookup,rlmode,k) - end - if pre then - setlink(cl,pre) - end - if replace then - local tail = find_node_tail(new) - setlink(tail,replace) - end - if hasglue then - setdiscchecked(lookaheaddisc,cf,post,new) - else - setdisc(lookaheaddisc,cf,post,new) - end - start = getprev(lookaheaddisc) - sweephead[cf] = getnext(clast) - sweephead[new] = getnext(last) - - elseif backtrackdisc then - - local cf = getnext(backtrackdisc) - local cl = start - local cnext = getnext(start) - local insertedmarks = 0 - - while cnext do - local char = ischar(cnext,currentfont) - if char and marks[char] then - insertedmarks = insertedmarks + 1 - cl = cnext - cnext = getnext(cnext) - else - break - end - end - if cnext then - setprev(cnext,backtrackdisc) - end - setnext(backtrackdisc,cnext) - setprev(cf) - setnext(cl) - local pre, post, replace, pretail, posttail, replacetail = getdisc(backtrackdisc,true) - local new = copy_node_list(cf) - local cnew = find_node_tail(new) - for i=1,insertedmarks do - cnew = getprev(cnew) - end - local clast = cnew - for i=f,l do - clast = getnext(clast) - end - if not notmatchpost[backtrackdisc] then - cf, start, ok = chainproc(cf,start,last,dataset,sequence,chainlookup,rlmode,k) - end - if not notmatchreplace[backtrackdisc] then - new, cnew, ok = chainproc(new,cnew,clast,dataset,sequence,chainlookup,rlmode,k) - end - if post then - setlink(posttail,cf) - else - post = cf - end - if replace then - setlink(replacetail,new) - else - replace = new - end - if hasglue then - setdiscchecked(backtrackdisc,pre,post,replace) - else - setdisc(backtrackdisc,pre,post,replace) - end - start = getprev(backtrackdisc) - sweephead[post] = getnext(clast) - sweephead[replace] = getnext(last) - - else - - head, start, ok = chainproc(head,start,last,dataset,sequence,chainlookup,rlmode,k) - - end - - return head, start, ok -end - -local noflags = { false, false, false, false } - -local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode) - local sweepnode = sweepnode - local sweeptype = sweeptype - local currentfont = currentfont - local diskseen = false - local checkdisc = getprev(head) - local flags = sequence.flags or noflags - local done = false - local skipmark = flags[1] - local skipligature = flags[2] - local skipbase = flags[3] - local markclass = sequence.markclass - local skipped = false - for k=1,#contexts do -- i've only seen ccmp having > 1 (e.g. dejavu) - local match = true - local current = start - local last = start - local ck = contexts[k] - local seq = ck[3] - local s = #seq - local size = 1 - -- f..l = mid string - if s == 1 then - -- this seldom happens as it makes no sense (bril, ebgaramond, husayni, minion) - local char = ischar(current,currentfont) - if char then - match = seq[1][char] - end - else - -- maybe we need a better space check (maybe check for glue or category or combination) - -- we cannot optimize for n=2 because there can be disc nodes - local f = ck[4] - local l = ck[5] - -- current match - size = l - f + 1 - if size > 1 then - -- before/current/after | before/current | current/after - local discfound = nil - local n = f + 1 - last = getnext(last) -- the second in current (first already matched) - while n <= l do - if not last and (sweeptype == "post" or sweeptype == "replace") then - last = getnext(sweepnode) - sweeptype = nil - end - if last then - local char, id = ischar(last,currentfont) - if char then - local ccd = descriptions[char] - if ccd then - local class = ccd.class or "base" - if class == skipmark or class == skipligature or class == skipbase or (markclass and class == "mark" and not markclass[char]) then - skipped = true - if trace_skips then - show_skip(dataset,sequence,char,ck,class) - end - last = getnext(last) - elseif seq[n][char] then - if n < l then - last = getnext(last) - end - n = n + 1 - else - if discfound then - notmatchreplace[discfound] = true - match = not notmatchpre[discfound] - else - match = false - end - break - end - else - if discfound then - notmatchreplace[discfound] = true - match = not notmatchpre[discfound] - else - match = false - end - break - end - elseif char == false then - if discfound then - notmatchreplace[discfound] = true - match = not notmatchpre[discfound] - else - match = false - end - break - elseif id == disc_code then - diskseen = true - discfound = last - notmatchpre[last] = nil - notmatchpost[last] = true - notmatchreplace[last] = nil - local pre, post, replace = getdisc(last) - if pre then - local n = n - while pre do - if seq[n][getchar(pre)] then - n = n + 1 - pre = getnext(pre) - if n > l then - break - end - else - notmatchpre[last] = true - break - end - end - if n <= l then - notmatchpre[last] = true - end - else - notmatchpre[last] = true - end - if replace then - -- so far we never entered this branch - while replace do - if seq[n][getchar(replace)] then - n = n + 1 - replace = getnext(replace) - if n > l then - break - end - else - notmatchreplace[last] = true - match = not notmatchpre[last] - break - end - end - match = not notmatchpre[last] - end - -- maybe only if match - last = getnext(last) - else - match = false - break - end - else - match = false - break - end - end - end - -- before - if match and f > 1 then - local prev = getprev(start) - if prev then - if prev == checkdisc and (sweeptype == "pre" or sweeptype == "replace") then - prev = getprev(sweepnode) - -- sweeptype = nil - end - if prev then - local discfound = nil - local n = f - 1 - while n >= 1 do - if prev then - local char, id = ischar(prev,currentfont) - if char then - local ccd = descriptions[char] - if ccd then - local class = ccd.class - if class == skipmark or class == skipligature or class == skipbase or (markclass and class == "mark" and not markclass[char]) then - skipped = true - if trace_skips then - show_skip(dataset,sequence,char,ck,class) - end - prev = getprev(prev) -- moved here - elseif seq[n][char] then - if n > 1 then -- new test - prev = getprev(prev) -- moved here - end - n = n - 1 - else - if discfound then - notmatchreplace[discfound] = true - match = not notmatchpost[discfound] - else - match = false - end - break - end - else - if discfound then - notmatchreplace[discfound] = true - match = not notmatchpost[discfound] - else - match = false - end - break - end - -- prev = getprev(prev) -- moved up - elseif char == false then - if discfound then - notmatchreplace[discfound] = true - match = not notmatchpost[discfound] - else - match = false - end - break - elseif id == disc_code then - -- the special case: f i where i becomes dottless i .. - diskseen = true - discfound = prev - notmatchpre[prev] = true - notmatchpost[prev] = nil - notmatchreplace[prev] = nil - local pre, post, replace, pretail, posttail, replacetail = getdisc(prev,true) - if pre ~= start and post ~= start and replace ~= start then - if post then - local n = n - while posttail do - if seq[n][getchar(posttail)] then - n = n - 1 - if posttail == post then - break - else - posttail = getprev(posttail) - if n < 1 then - break - end - end - else - notmatchpost[prev] = true - break - end - end - if n >= 1 then - notmatchpost[prev] = true - end - else - notmatchpost[prev] = true - end - if replace then - -- we seldom enter this branch (e.g. on brill efficient) - while replacetail do - if seq[n][getchar(replacetail)] then - n = n - 1 - if replacetail == replace then - break - else - replacetail = getprev(replacetail) - if n < 1 then - break - end - end - else - notmatchreplace[prev] = true - match = not notmatchpost[prev] - break - end - end - if not match then - break - end - end - end - -- maybe only if match - prev = getprev(prev) - elseif seq[n][32] and isspace(prev,threshold) then - n = n - 1 - prev = getprev(prev) - else - match = false - break - end - else - match = false - break - end - end - else - match = false - end - else - match = false - end - end - -- after - if match and s > l then - local current = last and getnext(last) - if not current then - if sweeptype == "post" or sweeptype == "replace" then - current = getnext(sweepnode) - -- sweeptype = nil - end - end - if current then - local discfound = nil - -- removed optimization for s-l == 1, we have to deal with marks anyway - local n = l + 1 - while n <= s do - if current then - local char, id = ischar(current,currentfont) - if char then - local ccd = descriptions[char] - if ccd then - local class = ccd.class - if class == skipmark or class == skipligature or class == skipbase or (markclass and class == "mark" and not markclass[char]) then - skipped = true - if trace_skips then - show_skip(dataset,sequence,char,ck,class) - end - current = getnext(current) -- was absent - elseif seq[n][char] then - if n < s then -- new test - current = getnext(current) -- was absent - end - n = n + 1 - else - if discfound then - notmatchreplace[discfound] = true - match = not notmatchpre[discfound] - else - match = false - end - break - end - else - if discfound then - notmatchreplace[discfound] = true - match = not notmatchpre[discfound] - else - match = false - end - break - end - elseif char == false then - if discfound then - notmatchreplace[discfound] = true - match = not notmatchpre[discfound] - else - match = false - end - break - elseif id == disc_code then - diskseen = true - discfound = current - notmatchpre[current] = nil - notmatchpost[current] = true - notmatchreplace[current] = nil - local pre, post, replace = getdisc(current) - if pre then - local n = n - while pre do - if seq[n][getchar(pre)] then - n = n + 1 - pre = getnext(pre) - if n > s then - break - end - else - notmatchpre[current] = true - break - end - end - if n <= s then - notmatchpre[current] = true - end - else - notmatchpre[current] = true - end - if replace then - -- so far we never entered this branch - while replace do - if seq[n][getchar(replace)] then - n = n + 1 - replace = getnext(replace) - if n > s then - break - end - else - notmatchreplace[current] = true - match = notmatchpre[current] - break - end - end - if not match then - break - end - else - -- skip 'm - end - -- maybe only if match - current = getnext(current) - elseif seq[n][32] and isspace(current,threshold) then - n = n + 1 - current = getnext(current) - else - match = false - break - end - else - match = false - break - end - end - else - match = false - end - end - end - if match then - -- Can lookups be of a different type? - local diskchain = diskseen or sweepnode - if trace_contexts then - local rule = ck[1] - local lookuptype = ck[8] or ck[2] - local first = ck[4] - local last = ck[5] - local char = getchar(start) - logwarning("%s: rule %s matches at char %s for (%s,%s,%s) chars, lookuptype %a", - cref(dataset,sequence),rule,gref(char),first-1,last-first+1,s-last,lookuptype) - end - local chainlookups = ck[6] - if chainlookups then - local nofchainlookups = #chainlookups - -- Lookups can be like { 1, false, 3 } or { false, 2 } or basically anything and - -- #lookups can be less than #current - if size == 1 then - -- if nofchainlookups > size then - -- -- bad rules - -- end - local chainlookup = chainlookups[1] - local chainkind = chainlookup.type - local chainproc = chainprocs[chainkind] - if chainproc then - local ok - if diskchain then - head, start, ok = chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,1,ck,chainproc) - else - head, start, ok = chainproc(head,start,last,dataset,sequence,chainlookup,rlmode,1) - end - if ok then - done = true - end - else - logprocess("%s: %s is not yet supported (1)",cref(dataset,sequence),chainkind) - end - else - -- See LookupType 5: Contextual Substitution Subtable. Now it becomes messy. The - -- easiest case is where #current maps on #lookups i.e. one-to-one. But what if - -- we have a ligature. Cf the spec we then need to advance one character but we - -- really need to test it as there are fonts out there that are fuzzy and have - -- too many lookups: - -- - -- U+1105 U+119E U+1105 U+119E : sourcehansansklight: script=hang ccmp=yes - -- - local i = 1 - while start do - if skipped then - while start do -- todo: use properties - local char = getchar(start) - local ccd = descriptions[char] - if ccd then - local class = ccd.class or "base" - if class == skipmark or class == skipligature or class == skipbase or (markclass and class == "mark" and not markclass[char]) then - start = getnext(start) - else - break - end - else - break - end - end - end - local chainlookup = chainlookups[i] - if chainlookup then - local chainkind = chainlookup.type - local chainproc = chainprocs[chainkind] - if chainproc then - local ok, n - if diskchain then - head, start, ok = chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,i,ck,chainproc) - else - head, start, ok, n = chainproc(head,start,last,dataset,sequence,chainlookup,rlmode,i) - end - -- messy since last can be changed ! - if ok then - done = true - if n and n > 1 and i + n > nofchainlookups then - -- this is a safeguard, we just ignore the rest of the lookups - break - end - end - else - -- actually an error - logprocess("%s: %s is not yet supported (2)",cref(dataset,sequence),chainkind) - end - end - i = i + 1 - if i > size or not start then - break - elseif start then - start = getnext(start) - end - end - end - else - -- todo: needs checking for holes in the replacements - local replacements = ck[7] - if replacements then - head, start, done = reversesub(head,start,last,dataset,sequence,replacements,rlmode) - else - done = true - if trace_contexts then - logprocess("%s: skipping match",cref(dataset,sequence)) - end - end - end - if done then - break -- out of contexts (new, needs checking) - end - end - end - if diskseen then - notmatchpre = { } - notmatchpost = { } - notmatchreplace = { } - end - return head, start, done -end - -handlers.gsub_context = handle_contextchain -handlers.gsub_contextchain = handle_contextchain -handlers.gsub_reversecontextchain = handle_contextchain -handlers.gpos_contextchain = handle_contextchain -handlers.gpos_context = handle_contextchain - --- this needs testing - -local function chained_contextchain(head,start,stop,dataset,sequence,currentlookup,rlmode) - local steps = currentlookup.steps - local nofsteps = currentlookup.nofsteps - if nofsteps > 1 then - reportmoresteps(dataset,sequence) - end - return handle_contextchain(head,start,dataset,sequence,currentlookup,rlmode) -end - -chainprocs.gsub_context = chained_contextchain -chainprocs.gsub_contextchain = chained_contextchain -chainprocs.gsub_reversecontextchain = chained_contextchain -chainprocs.gpos_contextchain = chained_contextchain -chainprocs.gpos_context = chained_contextchain - -local missing = setmetatableindex("table") - -local function logprocess(...) - if trace_steps then - registermessage(...) - end - report_process(...) -end - -local logwarning = report_process - -local function report_missing_coverage(dataset,sequence) - local t = missing[currentfont] - if not t[sequence] then - t[sequence] = true - logwarning("missing coverage for feature %a, lookup %a, type %a, font %a, name %a", - dataset[4],sequence.name,sequence.type,currentfont,tfmdata.properties.fullname) - end -end - -local resolved = { } -- we only resolve a font,script,language pair once - --- todo: pass all these 'locals' in a table - -local sequencelists = setmetatableindex(function(t,font) - local sequences = fontdata[font].resources.sequences - if not sequences or not next(sequences) then - sequences = false - end - t[font] = sequences - return sequences -end) - --- fonts.hashes.sequences = sequencelists - -local autofeatures = fonts.analyzers.features -local featuretypes = otf.tables.featuretypes -local defaultscript = otf.features.checkeddefaultscript -local defaultlanguage = otf.features.checkeddefaultlanguage - -local function initialize(sequence,script,language,enabled,autoscript,autolanguage) - local features = sequence.features - if features then - local order = sequence.order - if order then - local featuretype = featuretypes[sequence.type or "unknown"] - for i=1,#order do - local kind = order[i] - local valid = enabled[kind] - if valid then - local scripts = features[kind] - local languages = scripts and ( - scripts[script] or - scripts[wildcard] or - (autoscript and defaultscript(featuretype,autoscript,scripts)) - ) - local enabled = languages and ( - languages[language] or - languages[wildcard] or - (autolanguage and defaultlanguage(featuretype,autolanguage,languages)) - ) - if enabled then - return { valid, autofeatures[kind] or false, sequence, kind } - end - end - end - else - -- can't happen - end - end - return false -end - -function otf.dataset(tfmdata,font) -- generic variant, overloaded in context - local shared = tfmdata.shared - local properties = tfmdata.properties - local language = properties.language or "dflt" - local script = properties.script or "dflt" - local enabled = shared.features - local autoscript = enabled and enabled.autoscript - local autolanguage = enabled and enabled.autolanguage - local res = resolved[font] - if not res then - res = { } - resolved[font] = res - end - local rs = res[script] - if not rs then - rs = { } - res[script] = rs - end - local rl = rs[language] - if not rl then - rl = { - -- indexed but we can also add specific data by key - } - rs[language] = rl - local sequences = tfmdata.resources.sequences - if sequences then - for s=1,#sequences do - local v = enabled and initialize(sequences[s],script,language,enabled,autoscript,autolanguage) - if v then - rl[#rl+1] = v - end - end - end - end - return rl -end - -local function report_disc(what,n) - report_run("%s: %s > %s",what,n,languages.serializediscretionary(n)) -end - -local function kernrun(disc,k_run,font,attr,...) - -- - -- we catch <font 1><disc font 2> - -- - if trace_kernruns then - report_disc("kern",disc) - end - -- - local prev, next = getboth(disc) - -- - local nextstart = next - local done = false - -- - local pre, post, replace, pretail, posttail, replacetail = getdisc(disc,true) - -- - local prevmarks = prev - -- - -- can be optional, because why on earth do we get a disc after a mark (okay, maybe when a ccmp - -- has happened but then it should be in the disc so basically this test indicates an error) - -- - while prevmarks do - local char = ischar(prevmarks,font) - if char and marks[char] then - prevmarks = getprev(prevmarks) - else - break - end - end - -- - if prev and not ischar(prev,font) then -- and (pre or replace) - prev = false - end - if next and not ischar(next,font) then -- and (post or replace) - next = false - end - -- - -- we need to get rid of this nest mess some day .. has to be done otherwise - -- - if pre then - if k_run(pre,"injections",nil,font,attr,...) then - done = true - end - if prev then - local nest = getprev(pre) - setlink(prev,pre) - if k_run(prevmarks,"preinjections",pre,font,attr,...) then -- or prev? - done = true - end - setprev(pre,nest) --- setprev(pre) - setnext(prev,disc) - end - end - -- - if post then - if k_run(post,"injections",nil,font,attr,...) then - done = true - end - if next then - setlink(posttail,next) - if k_run(posttail,"postinjections",next,font,attr,...) then - done = true - end - setnext(posttail) - setprev(next,disc) - end - end - -- - if replace then - if k_run(replace,"injections",nil,font,attr,...) then - done = true - end - if prev then - local nest = getprev(replace) - setlink(prev,replace) - if k_run(prevmarks,"replaceinjections",replace,font,attr,...) then -- getnext(replace)) - done = true - end - setprev(replace,nest) --- setprev(replace) - setnext(prev,disc) - end - if next then - setlink(replacetail,next) - if k_run(replacetail,"replaceinjections",next,font,attr,...) then - done = true - end - setnext(replacetail) - setprev(next,disc) - end - elseif prev and next then - setlink(prev,next) - if k_run(prevmarks,"emptyinjections",next,font,attr,...) then - done = true - end - setlink(prev,disc) - setlink(disc,next) - end - return nextstart, done -end - -local function comprun(disc,c_run,...) - if trace_compruns then - report_disc("comp",disc) - end - -- - local pre, post, replace = getdisc(disc) - local renewed = false - -- - if pre then - sweepnode = disc - sweeptype = "pre" -- in alternative code preinjections is uc_c_sed (also used then for proeprties, saves a variable) - local new, done = c_run(pre,...) - if done then - pre = new - renewed = true - end - end - -- - if post then - sweepnode = disc - sweeptype = "post" - local new, done = c_run(post,...) - if done then - post = new - renewed = true - end - end - -- - if replace then - sweepnode = disc - sweeptype = "replace" - local new, done = c_run(replace,...) - if done then - replace = new - renewed = true - end - end - -- - sweepnode = nil - sweeptype = nil - if renewed then - setdisc(disc,pre,post,replace) - end - -- - return getnext(disc), renewed -end - -local function testrun(disc,t_run,c_run,...) - if trace_testruns then - report_disc("test",disc) - end - local prev, next = getboth(disc) - if not next then - -- weird discretionary - return - end - local pre, post, replace, pretail, posttail, replacetail = getdisc(disc,true) - local done = false - if replace and prev then - -- this is a bit strange as we only do replace here and not post - -- anyway, we only look ahead ... the idea is that we discard a - -- disc when there is a ligature crossing the replace boundary - setlink(replacetail,next) - local ok, overflow = t_run(replace,next,...) - if ok and overflow then - -- so, we can have crossed the boundary - setfield(disc,"replace") - setlink(prev,replace) - -- setlink(replacetail,next) - setboth(disc) - flush_node_list(disc) - return replace, true -- restart .. tricky ! - else - -- we stay inside the disc - setnext(replacetail) - setprev(next,disc) - end - -- pre, post, replace, pretail, posttail, replacetail = getdisc(disc,true) - end - -- - -- like comprun - -- - local renewed = false - -- - if pre then - sweepnode = disc - sweeptype = "pre" - local new, ok = c_run(pre,...) - if ok then - pre = new - renewed = true - end - end - -- - if post then - sweepnode = disc - sweeptype = "post" - local new, ok = c_run(post,...) - if ok then - post = new - renewed = true - end - end - -- - if replace then - sweepnode = disc - sweeptype = "replace" - local new, ok = c_run(replace,...) - if ok then - replace = new - renewed = true - end - end - -- - sweepnode = nil - sweeptype = nil - if renewed then - setdisc(disc,pre,post,replace) - return next, true - else - return next, done - end -end - --- A discrun happens when we have a zwnj. We're gpossing so it is unlikely that --- there has been a match changing the character. Now, as we check again here --- the question is: why do we do this ... needs checking as drun seems useless --- ... maybe that code can go away - --- local function discrun(disc,drun,krun) --- local prev, next = getboth(disc) --- if trace_discruns then --- report_disc("disc",disc) --- end --- if next and prev then --- setnext(prev,next) --- -- setprev(next,prev) --- drun(prev) --- setnext(prev,disc) --- -- setprev(next,disc) --- end --- -- --- if krun then -- currently always false --- local pre = getfield(disc,"pre") --- if not pre then --- -- go on --- elseif prev then --- local nest = getprev(pre) --- setlink(prev,pre) --- krun(prev,"preinjections") --- setprev(pre,nest) --- setnext(prev,disc) --- else --- krun(pre,"preinjections") --- end --- end --- return next --- end - --- We can make some assumptions with respect to discretionaries. First of all it is very --- unlikely that some of the analysis related attributes applies. Then we can also assume --- that the ConTeXt specific dynamic attribute is different, although we do use explicit --- discretionaries (maybe we need to tag those some day). So, at least for now, we don't --- have the following test in the sub runs: --- --- -- local a = getattr(start,0) --- -- if a then --- -- a = (a == attr) and (not attribute or getprop(start,a_state) == attribute) --- -- else --- -- a = not attribute or getprop(start,a_state) == attribute --- -- end --- -- if a then --- --- but use this instead: --- --- -- local a = getattr(start,0) --- -- if not a or (a == attr) then --- --- and even that one is probably not needed. However, we can handle interesting --- cases now: --- --- 1{2{\oldstyle\discretionary{3}{4}{5}}6}7\par --- 1{2\discretionary{3{\oldstyle3}}{{\oldstyle4}4}{5{\oldstyle5}5}6}7\par - -local nesting = 0 - -local function c_run_single(head,font,attr,lookupcache,step,dataset,sequence,rlmode,handler) - local done = false - local sweep = sweephead[head] - if sweep then - start = sweep - sweephead[head] = nil - else - start = head - end - while start do - local char = ischar(start,font) - if char then - local a = attr and getattr(start,0) - if not a or (a == attr) then - local lookupmatch = lookupcache[char] - if lookupmatch then - local ok - head, start, ok = handler(head,start,dataset,sequence,lookupmatch,rlmode,step,1) - if ok then - done = true - end - end - if start then - start = getnext(start) - end - else - -- go on can be a mixed one - start = getnext(start) - end - elseif char == false then - return head, done - elseif sweep then - -- else we loose the rest - return head, done - else - -- in disc component - start = getnext(start) - end - end - return head, done -end - -local function t_run_single(start,stop,font,attr,lookupcache) - while start ~= stop do - local char = ischar(start,font) - if char then - local a = attr and getattr(start,0) - if not a or (a == attr) then - local lookupmatch = lookupcache[char] - if lookupmatch then -- hm, hyphens can match (tlig) so we need to really check - -- if we need more than ligatures we can outline the code and use functions - local s = getnext(start) - local l = nil - local d = 0 - while s do - if s == stop then - d = 1 - elseif d > 0 then - d = d + 1 - end - local lg = lookupmatch[getchar(s)] - if lg then - l = lg - s = getnext(s) - else - break - end - end - if l and l.ligature then - return true, d > 1 - end - end - else - -- go on can be a mixed one - end - start = getnext(start) - else - break - end - end -end - --- local function d_run_single(prev,font,attr,lookupcache,step,dataset,sequence,rlmode,handler) --- local a = attr and getattr(prev,0) --- if not a or (a == attr) then --- local char = ischar(prev) -- can be disc --- if char then --- local lookupmatch = lookupcache[char] --- if lookupmatch then --- local h, d, ok = handler(head,start,dataset,sequence,lookupmatch,rlmode,step,1) --- if ok then --- done = true --- success = true --- end --- end --- end --- end --- end - -local function k_run_single(sub,injection,last,font,attr,lookupcache,step,dataset,sequence,rlmode,handler) - local a = attr and getattr(sub,0) - if not a or (a == attr) then - for n in traverse_nodes(sub) do -- only gpos - if n == last then - break - end - local char = ischar(n) - if char then - local lookupmatch = lookupcache[char] - if lookupmatch then - local h, d, ok = handler(sub,n,dataset,sequence,lookupmatch,rlmode,step,1,injection) - if ok then - return true - end - end - end - end - end -end - -local function c_run_multiple(head,font,attr,steps,nofsteps,dataset,sequence,rlmode,handler) - local done = false - local sweep = sweephead[head] - if sweep then - start = sweep - sweephead[head] = nil - else - start = head - end - while start do - local char = ischar(start,font) - if char then - local a = attr and getattr(start,0) - if not a or (a == attr) then - for i=1,nofsteps do - local step = steps[i] - local lookupcache = step.coverage - if lookupcache then - local lookupmatch = lookupcache[char] - if lookupmatch then - -- we could move all code inline but that makes things even more unreadable - local ok - head, start, ok = handler(head,start,dataset,sequence,lookupmatch,rlmode,step,i) - if ok then - done = true - break - elseif not start then - -- don't ask why ... shouldn't happen - break - end - end - else - report_missing_coverage(dataset,sequence) - end - end - if start then - start = getnext(start) - end - else - -- go on can be a mixed one - start = getnext(start) - end - elseif char == false then - -- whatever glyph - return head, done - elseif sweep then - -- else we loose the rest - return head, done - else - -- in disc component - start = getnext(start) - end - end - return head, done -end - -local function t_run_multiple(start,stop,font,attr,steps,nofsteps) - while start ~= stop do - local char = ischar(start,font) - if char then - local a = attr and getattr(start,0) - if not a or (a == attr) then - for i=1,nofsteps do - local step = steps[i] - local lookupcache = step.coverage - if lookupcache then - local lookupmatch = lookupcache[char] - if lookupmatch then - -- if we need more than ligatures we can outline the code and use functions - local s = getnext(start) - local l = nil - local d = 0 - while s do - if s == stop then - d = 1 - elseif d > 0 then - d = d + 1 - end - local lg = lookupmatch[getchar(s)] - if lg then - l = lg - s = getnext(s) - else - break - end - end - if l and l.ligature then - return true, d > 1 - end - end - else - report_missing_coverage(dataset,sequence) - end - end - else - -- go on can be a mixed one - end - start = getnext(start) - else - break - end - end -end - --- local function d_run_multiple(prev,attr,steps,nofsteps,dataset,sequence,rlmode,handler) --- local a = attr and getattr(prev,0) --- if not a or (a == attr) then --- local char = ischar(prev) -- can be disc --- if char then --- for i=1,nofsteps do --- local step = steps[i] --- local lookupcache = step.coverage --- if lookupcache then --- local lookupmatch = lookupcache[char] --- if lookupmatch then --- -- we could move all code inline but that makes things even more unreadable --- local h, d, ok = handler(head,prev,dataset,sequence,lookupmatch,rlmode,step,i) --- if ok then --- done = true --- break --- end --- end --- else --- report_missing_coverage(dataset,sequence) --- end --- end --- end --- end --- end - -local function k_run_multiple(sub,injection,last,font,attr,steps,nofsteps,dataset,sequence,rlmode,handler) - local a = attr and getattr(sub,0) - if not a or (a == attr) then - for n in traverse_nodes(sub) do -- only gpos - if n == last then - break - end - local char = ischar(n) - if char then - for i=1,nofsteps do - local step = steps[i] - local lookupcache = step.coverage - if lookupcache then - local lookupmatch = lookupcache[char] - if lookupmatch then - local h, d, ok = handler(head,n,dataset,sequence,lookupmatch,step,rlmode,i,injection) - if ok then - return true - end - end - else - report_missing_coverage(dataset,sequence) - end - end - end - end - end -end - --- to be checked, nowadays we probably can assume properly matched directions --- so maybe we no longer need a stack - -local function txtdirstate(start,stack,top,rlparmode) - local dir = getfield(start,"dir") - local new = 1 - if dir == "+TRT" then - top = top + 1 - stack[top] = dir - new = -1 - elseif dir == "+TLT" then - top = top + 1 - stack[top] = dir - elseif dir == "-TRT" or dir == "-TLT" then - top = top - 1 - if stack[top] == "+TRT" then - new = -1 - end - else - new = rlparmode - end - if trace_directions then - report_process("directions after txtdir %a: parmode %a, txtmode %a, level %a",dir,mref(rlparmode),mref(new),top) - end - return getnext(start), top, new -end - -local function pardirstate(start) - local dir = getfield(start,"dir") - local new = 0 - if dir == "TLT" then - new = 1 - elseif dir == "TRT" then - new = -1 - end - if trace_directions then - report_process("directions after pardir %a: parmode %a",dir,mref(new)) - end - return getnext(start), new, new -end - -otf.helpers = otf.helpers or { } -otf.helpers.txtdirstate = txtdirstate -otf.helpers.pardirstate = pardirstate - -local function featuresprocessor(head,font,attr) - - local sequences = sequencelists[font] -- temp hack - - if not sequencelists then - return head, false - end - - nesting = nesting + 1 - - if nesting == 1 then - - currentfont = font - tfmdata = fontdata[font] - descriptions = tfmdata.descriptions - characters = tfmdata.characters - marks = tfmdata.resources.marks - threshold, - factor = getthreshold(font) - checkmarks = tfmdata.properties.checkmarks - - elseif currentfont ~= font then - - report_warning("nested call with a different font, level %s, quitting",nesting) - nesting = nesting - 1 - return head, false - - end - - -- some 10% faster when no dynamics but hardly measureable on real runs .. but: it only - -- works when we have no other dynamics as otherwise the zero run will be applied to the - -- whole stream for which we then need to pass another variable which we won't - - -- if attr == 0 then - -- attr = false - -- end - - head = tonut(head) - - if trace_steps then - checkstep(head) - end - - local rlmode = 0 - - local done = false - local datasets = otf.dataset(tfmdata,font,attr) - - local forcedisc = alwaysdisc or not attr - - local dirstack = { } -- could move outside function but we can have local runs - - sweephead = { } - - -- We could work on sub start-stop ranges instead but I wonder if there is that - -- much speed gain (experiments showed that it made not much sense) and we need - -- to keep track of directions anyway. Also at some point I want to play with - -- font interactions and then we do need the full sweeps. - - -- Keeping track of the headnode is needed for devanagari (I generalized it a bit - -- so that multiple cases are also covered.) - - -- We don't goto the next node when a disc node is created so that we can then treat - -- the pre, post and replace. It's a bit of a hack but works out ok for most cases. - - for s=1,#datasets do - local dataset = datasets[s] - ----- featurevalue = dataset[1] -- todo: pass to function instead of using a global - local attribute = dataset[2] - local sequence = dataset[3] -- sequences[s] -- also dataset[5] - local rlparmode = 0 - local topstack = 0 - local success = false - local typ = sequence.type - local gpossing = typ == "gpos_single" or typ == "gpos_pair" -- store in dataset - local handler = handlers[typ] - local steps = sequence.steps - local nofsteps = sequence.nofsteps - if not steps then - -- this permits injection, watch the different arguments - local h, d, ok = handler(head,head,dataset,sequence,nil,nil,nil,0,font,attr) - if ok then - success = true - if h then - head = h - end - end - elseif typ == "gsub_reversecontextchain" then - -- this is a limited case, no special treatments like 'init' etc - local start = find_node_tail(head) - while start do - local char = ischar(start,font) - if char then - local a = attr and getattr(start,0) - if not a or (a == attr) then - for i=1,nofsteps do - local step = steps[i] - local lookupcache = step.coverage - if lookupcache then - local lookupmatch = lookupcache[char] - if lookupmatch then - -- todo: disc? - local ok - head, start, ok = handler(head,start,dataset,sequence,lookupmatch,rlmode,step,i) - if ok then - success = true - break - end - end - else - report_missing_coverage(dataset,sequence) - end - end - if start then - start = getprev(start) - end - else - start = getprev(start) - end - else - start = getprev(start) - end - end - else - local start = head -- local ? - rlmode = 0 -- to be checked ? - if nofsteps == 1 then -- happens often - local step = steps[1] - local lookupcache = step.coverage - if not lookupcache then - report_missing_coverage(dataset,sequence) - else - while start do - local char, id = ischar(start,font) - if char then - local a = attr and getattr(start,0) - if a then - a = (a == attr) and (not attribute or getprop(start,a_state) == attribute) - else - a = not attribute or getprop(start,a_state) == attribute - end - if a then - local lookupmatch = lookupcache[char] - if lookupmatch then - local ok - head, start, ok = handler(head,start,dataset,sequence,lookupmatch,rlmode,step,1) - if ok then - success = true - -- elseif gpossing and zwnjruns and char == zwnj then - -- discrun(start,d_run,font,attr,lookupcache) - end - -- elseif gpossing and zwnjruns and char == zwnj then - -- discrun(start,d_run,font,attr,lookupcache) - end - if start then - start = getnext(start) - end - else - start = getnext(start) - end - elseif char == false then - -- whatever glyph - start = getnext(start) - elseif id == disc_code then - -- ctx: we could assume the same attr as the surrounding glyphs but then we loose - -- the option to have interesting disc nodes (we gain upto 10% on extreme tests); - -- if a disc would have a font field we could even be more strict (see oldstyle test - -- case) - local a = forcedisc or getsubtype(start) == discretionary_code or getattr(start,0) == attr - if a then - -- local attr = false - local ok - if gpossing then - start, ok = kernrun(start,k_run_single, font,attr,lookupcache,step,dataset,sequence,rlmode,handler) - elseif typ == "gsub_ligature" then - start, ok = testrun(start,t_run_single,c_run_single,font,attr,lookupcache,step,dataset,sequence,rlmode,handler) - else - start, ok = comprun(start,c_run_single, font,attr,lookupcache,step,dataset,sequence,rlmode,handler) - end - if ok then - success = true - end - else - start = getnext(start) - end - elseif id == math_code then - start = getnext(end_of_math(start)) - elseif id == dir_code then - start, topstack, rlmode = txtdirstate(start,dirstack,topstack,rlparmode) - elseif id == localpar_code then - start, rlparmode, rlmode = pardirstate(start) - else - start = getnext(start) - end - end - end - - else - - while start do - local char, id = ischar(start,font) - if char then - local a = attr and getattr(start,0) - if a then - a = (a == attr) and (not attribute or getprop(start,a_state) == attribute) - else - a = not attribute or getprop(start,a_state) == attribute - end - if a then - for i=1,nofsteps do - local step = steps[i] - local lookupcache = step.coverage - if lookupcache then - local lookupmatch = lookupcache[char] - if lookupmatch then - -- we could move all code inline but that makes things even more unreadable - local ok - head, start, ok = handler(head,start,dataset,sequence,lookupmatch,rlmode,step,i) - if ok then - success = true - break - elseif not start then - -- don't ask why ... shouldn't happen - break - -- elseif gpossing and zwnjruns and char == zwnj then - -- discrun(start,d_run,font,attr,steps,nofsteps) - end - -- elseif gpossing and zwnjruns and char == zwnj then - -- discrun(start,d_run,font,attr,steps,nofsteps) - end - else - report_missing_coverage(dataset,sequence) - end - end - if start then - start = getnext(start) - end - else - start = getnext(start) - end - elseif char == false then - start = getnext(start) - elseif id == disc_code then - -- see comment above - local a = forcedisc or getsubtype(start) == discretionary_code or getattr(start,0) == attr - if a then - local ok - if gpossing then - start, ok = kernrun(start,k_run_multiple, font,attr,steps,nofsteps,dataset,sequence,rlmode,handler) - elseif typ == "gsub_ligature" then - start, ok = testrun(start,t_run_multiple,c_run_multiple,font,attr,steps,nofsteps,dataset,sequence,rlmode,handler) - else - start, ok = comprun(start,c_run_multiple, font,attr,steps,nofsteps,dataset,sequence,rlmode,handler) - end - if ok then - success = true - end - else - start = getnext(start) - end - elseif id == math_code then - start = getnext(end_of_math(start)) - elseif id == dir_code then - start, topstack, rlmode = txtdirstate(start,dirstack,topstack,rlparmode) - elseif id == localpar_code then - start, rlparmode, rlmode = pardirstate(start) - else - start = getnext(start) - end - end - end - end - - if success then - done = true - end - if trace_steps then -- ? - registerstep(head) - end - - end - - nesting = nesting - 1 - head = tonode(head) - - return head, done -end - --- so far - -local plugins = { } -otf.plugins = plugins - -function otf.registerplugin(name,f) - if type(name) == "string" and type(f) == "function" then - plugins[name] = { name, f } - end -end - -local function plugininitializer(tfmdata,value) - if type(value) == "string" then - tfmdata.shared.plugin = plugins[value] - end -end - -local function pluginprocessor(head,font) - local s = fontdata[font].shared - local p = s and s.plugin - if p then - if trace_plugins then - report_process("applying plugin %a",p[1]) - end - return p[2](head,font) - else - return head, false - end -end - -local function featuresinitializer(tfmdata,value) - -- nothing done here any more -end - -registerotffeature { - name = "features", - description = "features", - default = true, - initializers = { - position = 1, - node = featuresinitializer, - plug = plugininitializer, - }, - processors = { - node = featuresprocessor, - plug = pluginprocessor, - } -} - -otf.nodemodeinitializer = featuresinitializer -otf.featuresprocessor = featuresprocessor - --- This can be used for extra handlers, but should be used with care! - -otf.handlers = handlers -- used in devanagari - --- We implement one here: - -local setspacekerns = nodes.injections.setspacekerns if not setspacekerns then os.exit() end - -if fontfeatures then - - function otf.handlers.trigger_space_kerns(head,start,dataset,sequence,_,_,_,_,font,attr) - local features = fontfeatures[font] - local enabled = features and features.spacekern and features.kern - if enabled then - setspacekerns(font,sequence) - end - return head, start, enabled - end - -else -- generic (no hashes) - - function otf.handlers.trigger_space_kerns(head,start,dataset,sequence,_,_,_,_,font,attr) - local shared = fontdata[font].shared - local features = shared and shared.features - local enabled = features and features.spacekern and features.kern - if enabled then - setspacekerns(font,sequence) - end - return head, start, enabled - end - -end - -local function hasspacekerns(data) - local sequences = data.resources.sequences - for i=1,#sequences do - local sequence = sequences[i] - local steps = sequence.steps - if steps and sequence.features.kern then - for i=1,#steps do - local coverage = steps[i].coverage - if not coverage then - -- maybe an issue - elseif coverage[32] then - return true - else - for k, v in next, coverage do - if v[32] then - return true - end - end - end - end - end - end - return false -end - -otf.readers.registerextender { - name = "spacekerns", - action = function(data) - data.properties.hasspacekerns = hasspacekerns(data) - end -} - --- we merge the lookups but we still honor the language / script - -local function spaceinitializer(tfmdata,value) -- attr - local resources = tfmdata.resources - local spacekerns = resources and resources.spacekerns - local properties = tfmdata.properties - if value and spacekerns == nil then - if properties and properties.hasspacekerns then - local sequences = resources.sequences - local left = { } - local right = { } - local last = 0 - local feat = nil - for i=1,#sequences do - local sequence = sequences[i] - local steps = sequence.steps - if steps then - local kern = sequence.features.kern - if kern then - if feat then - for script, languages in next, kern do - local f = feat[script] - if f then - for l in next, languages do - f[l] = true - end - else - feat[script] = languages - end - end - else - feat = kern - end - for i=1,#steps do - local step = steps[i] - local coverage = step.coverage - local rules = step.rules - local format = step.format - if rules then - -- not now: analyze (simple) rules - elseif coverage then - -- what to do if we have no [1] but only [2] - local single = format == gpos_single - local kerns = coverage[32] - if kerns then - for k, v in next, kerns do - if type(v) ~= "table" then - right[k] = v - elseif single then - right[k] = v[3] - else - local one = v[1] - if one then - right[k] = one[3] - end - end - end - end - for k, v in next, coverage do - local kern = v[32] - if kern then - if type(kern) ~= "table" then - left[k] = kern - elseif single then - left[k] = v[3] - else - local one = v[1] - if one then - left[k] = one[3] - end - end - end - end - end - end - last = i - end - else - -- no steps ... needed for old one ... we could use the basekerns - -- instead - end - end - left = next(left) and left or false - right = next(right) and right or false - if left or right then - spacekerns = { - left = left, - right = right, - } - if last > 0 then - local triggersequence = { - features = { kern = feat or { dflt = { dflt = true, } } }, - flags = noflags, - name = "trigger_space_kerns", - order = { "kern" }, - type = "trigger_space_kerns", - left = left, - right = right, - } - insert(sequences,last,triggersequence) - end - else - spacekerns = false - end - else - spacekerns = false - end - resources.spacekerns = spacekerns - end - return spacekerns -end - -registerotffeature { - name = "spacekern", - description = "space kern injection", - default = true, - initializers = { - node = spaceinitializer, - }, -} - -local function markinitializer(tfmdata,value) - local properties = tfmdata.properties - properties.checkmarks = value -end - -registerotffeature { - name = "checkmarks", - description = "check mark widths", - default = true, - initializers = { - node = markinitializer, - }, -} diff --git a/tex/compat/luaotfload/fontloader-font-oup.lua b/tex/compat/luaotfload/fontloader-font-oup.lua deleted file mode 100644 index cfa90c7944a86068d0520e20091d1afb4edccfaf..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/fontloader-font-oup.lua +++ /dev/null @@ -1,2252 +0,0 @@ -if not modules then modules = { } end modules ['font-oup'] = { - version = 1.001, - comment = "companion to font-ini.mkiv", - 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 P, R, S = lpeg.P, lpeg.R, lpeg.S -local lpegmatch = lpeg.match -local insert, remove, copy, unpack = table.insert, table.remove, table.copy, table.unpack - -local formatters = string.formatters -local sortedkeys = table.sortedkeys -local sortedhash = table.sortedhash -local tohash = table.tohash - -local report = logs.reporter("otf reader") - -local trace_markwidth = false trackers.register("otf.markwidth",function(v) trace_markwidth = v end) - -local readers = fonts.handlers.otf.readers -local privateoffset = fonts.constructors and fonts.constructors.privateoffset or 0xF0000 -- 0x10FFFF - -local f_private = formatters["P%05X"] -local f_unicode = formatters["U%05X"] -local f_index = formatters["I%05X"] -local f_character_y = formatters["%C"] -local f_character_n = formatters["[ %C ]"] - -local check_duplicates = true -- can become an option (pseudo feature) / aways needed anyway -local check_soft_hyphen = false -- can become an option (pseudo feature) / needed for tagging - -directives.register("otf.checksofthyphen",function(v) - check_soft_hyphen = v -end) - -local function replaced(list,index,replacement) - if type(list) == "number" then - return replacement - elseif type(replacement) == "table" then - local t = { } - local n = index-1 - for i=1,n do - t[i] = list[i] - end - for i=1,#replacement do - n = n + 1 - t[n] = replacement[i] - end - for i=index+1,#list do - n = n + 1 - t[n] = list[i] - end - else - list[index] = replacement - return list - end -end - -local function unifyresources(fontdata,indices) - local descriptions = fontdata.descriptions - local resources = fontdata.resources - if not descriptions or not resources then - return - end - -- - local variants = fontdata.resources.variants - if variants then - for selector, unicodes in next, variants do - for unicode, index in next, unicodes do - unicodes[unicode] = indices[index] - end - end - end - -- - local function remark(marks) - if marks then - local newmarks = { } - for k, v in next, marks do - local u = indices[k] - if u then - newmarks[u] = v - else - report("discarding mark %i",k) - end - end - return newmarks - end - end - -- - local marks = resources.marks - if marks then - resources.marks = remark(marks) - end - -- - local markclasses = resources.markclasses - if markclasses then - for class, marks in next, markclasses do - markclasses[class] = remark(marks) - end - end - -- - local marksets = resources.marksets - if marksets then - for class, marks in next, marksets do - marksets[class] = remark(marks) - end - end - -- - local done = { } -- we need to deal with shared ! - -- - local duplicates = check_duplicates and resources.duplicates - if duplicates and not next(duplicates) then - duplicates = false - end - -- - local function recover(cover) -- can be packed - for i=1,#cover do - local c = cover[i] - if not done[c] then - local t = { } - for k, v in next, c do - t[indices[k]] = v - end - cover[i] = t - done[c] = d - end - end - end - -- - local function recursed(c) -- ligs are not packed - local t = { } - for g, d in next, c do - if type(d) == "table" then - t[indices[g]] = recursed(d) - else - t[g] = indices[d] -- ligature - end - end - return t - end - -- - -- the duplicates need checking (probably only in cjk fonts): currently we only check - -- gsub_single, gsub_alternate, gsub_multiple, gpos_single and gpos_cursive - -- - local function unifythem(sequences) - if not sequences then - return - end - for i=1,#sequences do - local sequence = sequences[i] - local kind = sequence.type - local steps = sequence.steps - local features = sequence.features - if steps then - for i=1,#steps do - local step = steps[i] - if kind == "gsub_single" then - local c = step.coverage - if c then - local t1 = done[c] - if not t1 then - t1 = { } - if duplicates then - for g1, d1 in next, c do - local ug1 = indices[g1] - local ud1 = indices[d1] - t1[ug1] = ud1 - -- - local dg1 = duplicates[ug1] - if dg1 then - for u in next, dg1 do - t1[u] = ud1 - end - end - end - else - for g1, d1 in next, c do - t1[indices[g1]] = indices[d1] - end - end - done[c] = t1 - end - step.coverage = t1 - end - elseif kind == "gpos_pair" then - local c = step.coverage - if c then - local t1 = done[c] - if not t1 then - t1 = { } - for g1, d1 in next, c do - local t2 = done[d1] - if not t2 then - t2 = { } - for g2, d2 in next, d1 do - t2[indices[g2]] = d2 - end - done[d1] = t2 - end - t1[indices[g1]] = t2 - end - done[c] = t1 - end - step.coverage = t1 - end - elseif kind == "gsub_ligature" then - local c = step.coverage - if c then - step.coverage = recursed(c) - end - elseif kind == "gsub_alternate" or kind == "gsub_multiple" then - local c = step.coverage - if c then - local t1 = done[c] - if not t1 then - t1 = { } - if duplicates then - for g1, d1 in next, c do - for i=1,#d1 do - d1[i] = indices[d1[i]] - end - local ug1 = indices[g1] - t1[ug1] = d1 - -- - local dg1 = duplicates[ug1] - if dg1 then - for u in next, dg1 do - t1[u] = copy(d1) - end - end - end - else - for g1, d1 in next, c do - for i=1,#d1 do - d1[i] = indices[d1[i]] - end - t1[indices[g1]] = d1 - end - end - done[c] = t1 - end - step.coverage = t1 - end - elseif kind == "gpos_mark2base" or kind == "gpos_mark2mark" or kind == "gpos_mark2ligature" then - local c = step.coverage - if c then - local t1 = done[c] - if not t1 then - t1 = { } - for g1, d1 in next, c do - t1[indices[g1]] = d1 - end - done[c] = t1 - end - step.coverage = t1 - end - local c = step.baseclasses - if c then - local t1 = done[c] - if not t1 then - for g1, d1 in next, c do - local t2 = done[d1] - if not t2 then - t2 = { } - for g2, d2 in next, d1 do - t2[indices[g2]] = d2 - end - done[d1] = t2 - end - c[g1] = t2 - end - done[c] = c - end - end - elseif kind == "gpos_single" then - local c = step.coverage - if c then - local t1 = done[c] - if not t1 then - t1 = { } - if duplicates then - for g1, d1 in next, c do - local ug1 = indices[g1] - t1[ug1] = d1 - -- - local dg1 = duplicates[ug1] - if dg1 then - for u in next, dg1 do - t1[u] = d1 - end - end - end - else - for g1, d1 in next, c do - t1[indices[g1]] = d1 - end - end - done[c] = t1 - end - step.coverage = t1 - end - elseif kind == "gpos_cursive" then - local c = step.coverage - if c then - local t1 = done[c] - if not t1 then - t1 = { } - if duplicates then - for g1, d1 in next, c do - local ug1 = indices[g1] - t1[ug1] = d1 - -- - local dg1 = duplicates[ug1] - if dg1 then - -- probably needs a bit more - for u in next, dg1 do - t1[u] = copy(d1) - end - end - end - else - for g1, d1 in next, c do - t1[indices[g1]] = d1 - end - end - done[c] = t1 - end - step.coverage = t1 - end - end - -- - local rules = step.rules - if rules then - for i=1,#rules do - local rule = rules[i] - -- - local before = rule.before if before then recover(before) end - local after = rule.after if after then recover(after) end - local current = rule.current if current then recover(current) end - -- - local replacements = rule.replacements - if replacements then - if not done[replacements] then - local r = { } - for k, v in next, replacements do - r[indices[k]] = indices[v] - end - rule.replacements = r - done[replacements] = r - end - end - end - end - end - end - end - end - -- - unifythem(resources.sequences) - unifythem(resources.sublookups) -end - -local function copyduplicates(fontdata) - if check_duplicates then - local descriptions = fontdata.descriptions - local resources = fontdata.resources - local duplicates = resources.duplicates - if check_soft_hyphen then - -- ebgaramond has a zero width empty soft hyphen - local ds = descriptions[0xAD] - if not ds or ds.width == 0 then - if ds then - descriptions[0xAD] = nil - report("patching soft hyphen") - else - report("adding soft hyphen") - end - if not duplicates then - duplicates = { } - resources.duplicates = duplicates - end - local dh = duplicates[0x2D] - if dh then - dh[#dh+1] = { [0xAD] = true } - else - duplicates[0x2D] = { [0xAD] = true } - end - end - end - if duplicates then - for u, d in next, duplicates do - local du = descriptions[u] - if du then - local t = { f_character_y(u), "@", f_index(du.index), "->" } - local n = 0 - local m = 25 - for u in next, d do - if descriptions[u] then - if n < m then - t[n+4] = f_character_n(u) - end - else - local c = copy(du) - c.unicode = u -- better this way - descriptions[u] = c - if n < m then - t[n+4] = f_character_y(u) - end - end - n = n + 1 - end - if n <= m then - report("duplicates: %i : % t",n,t) - else - report("duplicates: %i : % t ...",n,t) - end - else - -- what a mess - end - end - end - end -end - -local ignore = { -- should we fix them? - ["notdef"] = true, - [".notdef"] = true, - ["null"] = true, - [".null"] = true, - ["nonmarkingreturn"] = true, -} - - -local function checklookups(fontdata,missing,nofmissing) - local descriptions = fontdata.descriptions - local resources = fontdata.resources - if missing and nofmissing and nofmissing <= 0 then - return - end - -- - local singles = { } - local alternates = { } - local ligatures = { } - - if not missing then - missing = { } - nofmissing = 0 - for u, d in next, descriptions do - if not d.unicode then - nofmissing = nofmissing + 1 - missing[u] = true - end - end - end - - local function collectthem(sequences) - if not sequences then - return - end - for i=1,#sequences do - local sequence = sequences[i] - local kind = sequence.type - local steps = sequence.steps - if steps then - for i=1,#steps do - local step = steps[i] - if kind == "gsub_single" then - local c = step.coverage - if c then - singles[#singles+1] = c - end - elseif kind == "gsub_alternate" then - local c = step.coverage - if c then - alternates[#alternates+1] = c - end - elseif kind == "gsub_ligature" then - local c = step.coverage - if c then - ligatures[#ligatures+1] = c - end - end - end - end - end - end - - collectthem(resources.sequences) - collectthem(resources.sublookups) - - local loops = 0 - while true do - loops = loops + 1 - local old = nofmissing - for i=1,#singles do - local c = singles[i] - for g1, g2 in next, c do - if missing[g1] then - local u2 = descriptions[g2].unicode - if u2 then - missing[g1] = false - descriptions[g1].unicode = u2 - nofmissing = nofmissing - 1 - end - end - if missing[g2] then - local u1 = descriptions[g1].unicode - if u1 then - missing[g2] = false - descriptions[g2].unicode = u1 - nofmissing = nofmissing - 1 - end - end - end - end - for i=1,#alternates do - local c = alternates[i] - -- maybe first a g1 loop and then a g2 - for g1, d1 in next, c do - if missing[g1] then - for i=1,#d1 do - local g2 = d1[i] - local u2 = descriptions[g2].unicode - if u2 then - missing[g1] = false - descriptions[g1].unicode = u2 - nofmissing = nofmissing - 1 - end - end - end - if not missing[g1] then - for i=1,#d1 do - local g2 = d1[i] - if missing[g2] then - local u1 = descriptions[g1].unicode - if u1 then - missing[g2] = false - descriptions[g2].unicode = u1 - nofmissing = nofmissing - 1 - end - end - end - end - end - end - if nofmissing <= 0 then - report("all done in %s loops",loops) - return - elseif old == nofmissing then - break - end - end - - local t, n -- no need to insert/remove and allocate many times - - local function recursed(c) - for g, d in next, c do - if g ~= "ligature" then - local u = descriptions[g].unicode - if u then - n = n + 1 - t[n] = u - recursed(d) - n = n - 1 - end - elseif missing[d] then - local l = { } - local m = 0 - for i=1,n do - local u = t[i] - if type(u) == "table" then - for i=1,#u do - m = m + 1 - l[m] = u[i] - end - else - m = m + 1 - l[m] = u - end - end - missing[d] = false - descriptions[d].unicode = l - nofmissing = nofmissing - 1 - end - end - end - - if nofmissing > 0 then - t = { } - n = 0 - local loops = 0 - while true do - loops = loops + 1 - local old = nofmissing - for i=1,#ligatures do - recursed(ligatures[i]) - end - if nofmissing <= 0 then - report("all done in %s loops",loops) - return - elseif old == nofmissing then - break - end - end - t = nil - n = 0 - end - - if nofmissing > 0 then - local done = { } - for i, r in next, missing do - if r then - local data = descriptions[i] - local name = data and data.name or f_index(i) - if not ignore[name] then - done[name] = true - end - end - end - if next(done) then - report("not unicoded: % t",table.sortedkeys(done)) - end - end -end - -local function unifymissing(fontdata) - if not fonts.mappings then - require("font-map") - require("font-agl") - end - local unicodes = { } - local private = fontdata.private - local resources = fontdata.resources - resources.unicodes = unicodes - for unicode, d in next, fontdata.descriptions do - if unicode < privateoffset then - local name = d.name - if name then - unicodes[name] = unicode - end - end - end - fonts.mappings.addtounicode(fontdata,fontdata.filename,checklookups) - resources.unicodes = nil -end - -local function unifyglyphs(fontdata,usenames) - local private = fontdata.private or privateoffset - local glyphs = fontdata.glyphs - local indices = { } - local descriptions = { } - local names = usenames and { } - local resources = fontdata.resources - local zero = glyphs[0] - local zerocode = zero.unicode - if not zerocode then - zerocode = private - zero.unicode = zerocode - private = private + 1 - end - descriptions[zerocode] = zero - if names then - local name = glyphs[0].name or f_private(zerocode) - indices[0] = name - names[name] = zerocode - else - indices[0] = zerocode - end - -- - for index=1,#glyphs do - local glyph = glyphs[index] - local unicode = glyph.unicode -- this is the primary one - if not unicode then - -- report("assigning private unicode %U to glyph indexed %05X (%s)",private,index,"unset") - unicode = private - -- glyph.unicode = -1 - if names then - local name = glyph.name or f_private(unicode) - indices[index] = name - names[name] = unicode - else - indices[index] = unicode - end - private = private + 1 - elseif descriptions[unicode] then - -- real weird - report("assigning private unicode %U to glyph indexed %05X (%C)",private,index,unicode) - unicode = private - -- glyph.unicode = -1 - if names then - local name = glyph.name or f_private(unicode) - indices[index] = name - names[name] = unicode - else - indices[index] = unicode - end - private = private + 1 - else - if names then - local name = glyph.name or f_unicode(unicode) - indices[index] = name - names[name] = unicode - else - indices[index] = unicode - end - end - descriptions[unicode] = glyph - end - -- - for index=1,#glyphs do - local math = glyphs[index].math - if math then - local list = math.vparts - if list then - for i=1,#list do local l = list[i] l.glyph = indices[l.glyph] end - end - local list = math.hparts - if list then - for i=1,#list do local l = list[i] l.glyph = indices[l.glyph] end - end - local list = math.vvariants - if list then - -- for i=1,#list do local l = list[i] l.glyph = indices[l.glyph] end - for i=1,#list do list[i] = indices[list[i]] end - end - local list = math.hvariants - if list then - -- for i=1,#list do local l = list[i] l.glyph = indices[l.glyph] end - for i=1,#list do list[i] = indices[list[i]] end - end - end - end - -- - local colorpalettes = resources.colorpalettes - if colorpalettes then - for index=1,#glyphs do - local colors = glyphs[index].colors - if colors then - for i=1,#colors do - local c = colors[i] - c.slot = indices[c.slot] - end - end - end - end - -- - fontdata.private = private - fontdata.glyphs = nil - fontdata.names = names - fontdata.descriptions = descriptions - fontdata.hashmethod = hashmethod - -- - return indices, names -end - -local p_bogusname = ( - (P("uni") + P("UNI") + P("Uni") + P("U") + P("u")) * S("Xx")^0 * R("09","AF")^1 - + (P("identity") + P("Identity") + P("IDENTITY")) * R("09","AF")^1 - + (P("index") + P("Index") + P("INDEX")) * R("09")^1 -) * P(-1) - -local function stripredundant(fontdata) - local descriptions = fontdata.descriptions - if descriptions then - local n = 0 - local c = 0 - for unicode, d in next, descriptions do - local name = d.name - if name and lpegmatch(p_bogusname,name) then - d.name = nil - n = n + 1 - end - if d.class == "base" then - d.class = nil - c = c + 1 - end - end - if n > 0 then - report("%s bogus names removed (verbose unicode)",n) - end - if c > 0 then - report("%s base class tags removed (default is base)",c) - end - end -end - -function readers.getcomponents(fontdata) -- handy for resolving ligatures when names are missing - local resources = fontdata.resources - if resources then - local sequences = resources.sequences - if sequences then - local collected = { } - for i=1,#sequences do - local sequence = sequences[i] - if sequence.type == "gsub_ligature" then - local steps = sequence.steps - if steps then - local l = { } - local function traverse(p,k,v) - if k == "ligature" then - collected[v] = { unpack(l) } - else - insert(l,k) - for k, vv in next, v do - traverse(p,k,vv) - end - remove(l) - end - end - for i=1,#steps do - -- we actually had/have this in base mode - local coverage = steps[i].coverage - if coverage then - for k, v in next, coverage do - traverse(k,k,v) - end - end - end - end - end - end - if next(collected) then - -- remove self referring - -- for k, v in next, collected do - -- for i=1,#v do - -- local vi = v[i] - -- if vi == k then - -- -- report("removing self referring ligature @ slot %5X from collected (1)",k) - -- collected[k] = nil - -- end - -- end - -- end - while true do - local done = false - for k, v in next, collected do - for i=1,#v do - local vi = v[i] - if vi == k then - -- report("removing self referring ligature @ slot %5X from collected (2)",k) - collected[k] = nil - break - else - local c = collected[vi] - if c then - done = true - local t = { } - local n = i - 1 - for j=1,n do - t[j] = v[j] - end - for j=1,#c do - n = n + 1 - t[n] = c[j] - end - for j=i+1,#v do - n = n + 1 - t[n] = v[j] - end - collected[k] = t - break - end - end - end - end - if not done then - break - end - end - return collected - end - end - end -end - -readers.unifymissing = unifymissing - -function readers.rehash(fontdata,hashmethod) -- TODO: combine loops in one - if not (fontdata and fontdata.glyphs) then - return - end - if hashmethod == "indices" then - fontdata.hashmethod = "indices" - elseif hashmethod == "names" then - fontdata.hashmethod = "names" - local indices = unifyglyphs(fontdata,true) - unifyresources(fontdata,indices) - copyduplicates(fontdata) - unifymissing(fontdata) - -- stripredundant(fontdata) - else - fontdata.hashmethod = "unicode" - local indices = unifyglyphs(fontdata) - unifyresources(fontdata,indices) - copyduplicates(fontdata) - unifymissing(fontdata) - stripredundant(fontdata) - end - -- maybe here components -end - -function readers.checkhash(fontdata) - local hashmethod = fontdata.hashmethod - if hashmethod == "unicodes" then - fontdata.names = nil -- just to be sure - elseif hashmethod == "names" and fontdata.names then - unifyresources(fontdata,fontdata.names) - copyduplicates(fontdata) - fontdata.hashmethod = "unicode" - fontdata.names = nil -- no need for it - else - readers.rehash(fontdata,"unicode") - end -end - -function readers.addunicodetable(fontdata) - local resources = fontdata.resources - local unicodes = resources.unicodes - if not unicodes then - local descriptions = fontdata.descriptions - if descriptions then - unicodes = { } - resources.unicodes = unicodes - for u, d in next, descriptions do - local n = d.name - if n then - unicodes[n] = u - end - end - end - end -end - --- for the moment here: - -local concat, sort = table.concat, table.sort -local next, type, tostring = next, type, tostring - -local criterium = 1 -local threshold = 0 - -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") - -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 .. "+" -- "=true" - elseif v then - s[n] = k .. "=" .. v - else - s[n] = k .. "-" -- "=false" - end - end - if n == 0 then - return "" - elseif n == 1 then - return s[1] - else - sort(s) -- costly but needed (occasional wrong hit otherwise) - 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) -- costly but needed (occasional wrong hit otherwise) - return concat(s,",") - end -end - -local function tabstr_mixed(t) -- indexed - local s = { } - local n = #t - if n == 0 then - return "" - elseif n == 1 then - local k = t[1] - if k == true then - return "++" -- we need to distinguish from "true" - elseif k == false then - return "--" -- we need to distinguish from "false" - else - return tostring(k) -- number or string - end - else - for i=1,n do - local k = t[i] - if k == true then - s[i] = "++" -- we need to distinguish from "true" - elseif k == false then - s[i] = "--" -- we need to distinguish from "false" - else - s[i] = k -- number or string - 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) -- costly but needed (occasional wrong hit otherwise) - return concat(s,",") - end -end - --- beware: we cannot unpack and repack the same table because then sharing --- interferes (we could catch this if needed) .. so for now: save, reload --- and repack in such cases (never needed anyway) .. a tricky aspect is that --- we then need to sort more thanks to random hashing - -function readers.pack(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) - -- v == number - if c[v] <= criterium then - return t[v] - else - -- compact hash - 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 sequences = resources.sequences - local sublookups = resources.sublookups - local features = resources.features - local palettes = resources.colorpalettes - - local chardata = characters and characters.data - local descriptions = data.descriptions or data.glyphs - - if not descriptions then - return - end - - -- - - 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, descriptions do - local boundingbox = description.boundingbox - if boundingbox then - description.boundingbox = pack_indexed(boundingbox) - 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 - -- if palettes then - -- local color = description.color - -- if color then - -- for i=1,#color do - -- color[i] = pack_normal(color[i]) - -- end - -- end - -- end - end - - local function packthem(sequences) - for i=1,#sequences do - local sequence = sequences[i] - local kind = sequence.type - local steps = sequence.steps - local order = sequence.order - local features = sequence.features - local flags = sequence.flags - if steps then - for i=1,#steps do - local step = steps[i] - if kind == "gpos_pair" then - local c = step.coverage - if c then - if step.format == "kern" then - for g1, d1 in next, c do - c[g1] = pack_normal(d1) - end - else - for g1, d1 in next, c do - for g2, d2 in next, d1 do - local f = d2[1] if f then d2[1] = pack_indexed(f) end - local s = d2[2] if s then d2[2] = pack_indexed(s) end - end - end - end - end - elseif kind == "gpos_single" then - local c = step.coverage - if c then - if step.format == "kern" then - step.coverage = pack_normal(c) - else - for g1, d1 in next, c do - c[g1] = pack_indexed(d1) - end - end - end - elseif kind == "gpos_cursive" then - local c = step.coverage - if c then - for g1, d1 in next, c do - local f = d1[2] if f then d1[2] = pack_indexed(f) end - local s = d1[3] if s then d1[3] = pack_indexed(s) end - end - end - elseif kind == "gpos_mark2base" or kind == "gpos_mark2mark" then - local c = step.baseclasses - if c then - for g1, d1 in next, c do - for g2, d2 in next, d1 do - d1[g2] = pack_indexed(d2) - end - end - end - local c = step.coverage - if c then - for g1, d1 in next, c do - d1[2] = pack_indexed(d1[2]) - end - end - elseif kind == "gpos_mark2ligature" then - local c = step.baseclasses - if c then - for g1, d1 in next, c do - for g2, d2 in next, d1 do - for g3, d3 in next, d2 do - d2[g3] = pack_indexed(d3) - end - end - end - end - local c = step.coverage - if c then - for g1, d1 in next, c do - d1[2] = pack_indexed(d1[2]) - end - end - end - -- if ... chain ... - local rules = step.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.lookups if r then rule.lookups = pack_mixed (r) end - local r = rule.replacements if r then rule.replacements = pack_flat (r) end - end - end - end - end - if order then - sequence.order = pack_indexed(order) - end - if features then - for script, feature in next, features do - features[script] = pack_normal(feature) - end - end - if flags then - sequence.flags = pack_normal(flags) - end - end - end - - if sequences then - packthem(sequences) - end - - if sublookups then - packthem(sublookups) - end - - if features then - for k, list in next, features do - for feature, spec in next, list do - list[feature] = pack_normal(spec) - end - end - end - - if palettes then - for i=1,#palettes do - local p = palettes[i] - for j=1,#p do - p[j] = pack_indexed(p[j]) - 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, descriptions do - local math = description.math - if math then - local kerns = math.kerns - if kerns then - math.kerns = pack_normal(kerns) - end - end - end - - local function packthem(sequences) - for i=1,#sequences do - local sequence = sequences[i] - local kind = sequence.type - local steps = sequence.steps - local features = sequence.features - if steps then - for i=1,#steps do - local step = steps[i] - if kind == "gpos_pair" then - local c = step.coverage - if c then - if step.format == "kern" then - -- todo ! - else - for g1, d1 in next, c do - for g2, d2 in next, d1 do - d1[g2] = pack_normal(d2) - end - end - end - end --- elseif kind == "gpos_mark2base" or kind == "gpos_mark2mark" or kind == "gpos_mark2ligature" then --- local c = step.baseclasses --- for k, v in next, c do --- c[k] = pack_normal(v) --- end - end - local rules = step.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 - if features then - sequence.features = pack_normal(features) - end - end - end - if sequences then - packthem(sequences) - end - if sublookups then - packthem(sublookups) - end - -- features - if not success(2,pass) then - -- return - end - end - - for pass=1,2 do - if trace_packing then - report_otf("start packing: stage 3, pass %s",pass) - end - - local pack_normal, pack_indexed, pack_flat, pack_boolean, pack_mixed = packers(pass) - - local function packthem(sequences) - for i=1,#sequences do - local sequence = sequences[i] - local kind = sequence.type - local steps = sequence.steps - local features = sequence.features - if steps then - for i=1,#steps do - local step = steps[i] - if kind == "gpos_pair" then - local c = step.coverage - if c then - if step.format == "kern" then - -- todo ! - else - for g1, d1 in next, c do - c[g1] = pack_normal(d1) - end - end - end - end - end - end - end - end - - if sequences then - packthem(sequences) - end - if sublookups then - packthem(sublookups) - end - - end - - end - - end -end - -local unpacked_mt = { - __index = - function(t,k) - t[k] = false - return k -- next time true - end -} - -function readers.unpack(data) - - if data then - local tables = data.tables - if tables then - local resources = data.resources - local descriptions = data.descriptions or data.glyphs - local sequences = resources.sequences - local sublookups = resources.sublookups - local features = resources.features - local palettes = resources.colorpalettes - local unpacked = { } - setmetatable(unpacked,unpacked_mt) - for unicode, description in next, descriptions do - local tv = tables[description.boundingbox] - if tv then - description.boundingbox = tv - 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 - -- if palettes then - -- local color = description.color - -- if color then - -- for i=1,#color do - -- local tv = tables[color[i]] - -- if tv then - -- color[i] = tv - -- end - -- end - -- end - -- end - end - - local function unpackthem(sequences) - for i=1,#sequences do - local sequence = sequences[i] - local kind = sequence.type - local steps = sequence.steps - local order = sequence.order - local features = sequence.features - local flags = sequence.flags - local markclass = sequence.markclass - if steps then - for i=1,#steps do - local step = steps[i] - if kind == "gpos_pair" then - local c = step.coverage - if c then - if step.format == "kern" then - for g1, d1 in next, c do - local tv = tables[d1] - if tv then - c[g1] = tv - end - end - else - for g1, d1 in next, c do - local tv = tables[d1] - if tv then - c[g1] = tv - d1 = tv - end - for g2, d2 in next, d1 do - local tv = tables[d2] - if tv then - d1[g2] = tv - d2 = tv - end - local f = tables[d2[1]] if f then d2[1] = f end - local s = tables[d2[2]] if s then d2[2] = s end - end - end - end - end - elseif kind == "gpos_single" then - local c = step.coverage - if c then - if step.format == "kern" then - local tv = tables[c] - if tv then - step.coverage = tv - end - else - for g1, d1 in next, c do - local tv = tables[d1] - if tv then - c[g1] = tv - end - end - end - end - elseif kind == "gpos_cursive" then - local c = step.coverage - if c then - for g1, d1 in next, c do - local f = tables[d1[2]] if f then d1[2] = f end - local s = tables[d1[3]] if s then d1[3] = s end - end - end - elseif kind == "gpos_mark2base" or kind == "gpos_mark2mark" then - local c = step.baseclasses - if c then --- for k, v in next, c do --- local tv = tables[v] --- if tv then --- c[k] = tv --- end --- end - for g1, d1 in next, c do - for g2, d2 in next, d1 do - local tv = tables[d2] - if tv then - d1[g2] = tv - end - end - end - end - local c = step.coverage - if c then - for g1, d1 in next, c do - local tv = tables[d1[2]] - if tv then - d1[2] = tv - end - end - end - elseif kind == "gpos_mark2ligature" then - local c = step.baseclasses - if c then --- for k, v in next, c do --- local tv = tables[v] --- if tv then --- c[k] = tv --- end --- end - for g1, d1 in next, c do - for g2, d2 in next, d1 do - for g3, d3 in next, d2 do - local tv = tables[d2[g3]] - if tv then - d2[g3] = tv - end - end - end - end - end - local c = step.coverage - if c then - for g1, d1 in next, c do - local tv = tables[d1[2]] - if tv then - d1[2] = tv - end - end - end - end - local rules = step.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 = tv - end - for i=1,#before do - local tv = tables[before[i]] - if tv then - before[i] = tv - end - end - end - local after = rule.after - if after then - local tv = tables[after] - if tv then - rule.after = tv - after = tv - end - for i=1,#after do - local tv = tables[after[i]] - if tv then - after[i] = tv - end - end - end - local current = rule.current - if current then - local tv = tables[current] - if tv then - rule.current = tv - current = tv - end - for i=1,#current do - local tv = tables[current[i]] - if tv then - current[i] = tv - end - end - end - local lookups = rule.lookups - if lookups then - local tv = tables[lookups] - if tv then - rule.lookups = tv - end - end - local replacements = rule.replacements - if replacements then - local tv = tables[replacements] - if tv then - rule.replacements = tv - end - end - end - end - end - end - if features then - local tv = tables[features] - if tv then - sequence.features = tv - features = tv - end - for script, feature in next, features do - local tv = tables[feature] - if tv then - features[script] = tv - end - end - end - if order then - local tv = tables[order] - if tv then - sequence.order = tv - end - end - if flags then - local tv = tables[flags] - if tv then - sequence.flags = tv - end - end - end - end - - if sequences then - unpackthem(sequences) - end - - if sublookups then - unpackthem(sublookups) - end - - if features then - for k, list in next, features do - for feature, spec in next, list do - local tv = tables[spec] - if tv then - list[feature] = tv - end - end - end - end - - if palettes then - for i=1,#palettes do - local p = palettes[i] - for j=1,#p do - local tv = tables[p[j]] - if tv then - p[j] = tv - end - end - end - end - - data.tables = nil - end - end -end - -local mt = { - __index = function(t,k) -- maybe set it - if k == "height" then - local ht = t.boundingbox[4] - return ht < 0 and 0 or ht - elseif k == "depth" then - local dp = -t.boundingbox[2] - return dp < 0 and 0 or dp - elseif k == "width" then - return 0 - elseif k == "name" then -- or maybe uni* - return forcenotdef and ".notdef" - end - end -} - -local function sameformat(sequence,steps,first,nofsteps,kind) - return true -end - -local function mergesteps_1(lookup,strict) - local steps = lookup.steps - local nofsteps = lookup.nofsteps - local first = steps[1] - if strict then - local f = first.format - for i=2,nofsteps do - if steps[i].format ~= f then - report("not merging %a steps of %a lookup %a, different formats",nofsteps,lookup.type,lookup.name) - return 0 - end - end - end - report("merging %a steps of %a lookup %a",nofsteps,lookup.type,lookup.name) - local target = first.coverage - for i=2,nofsteps do - for k, v in next, steps[i].coverage do - if not target[k] then - target[k] = v - end - end - end - lookup.nofsteps = 1 - lookup.merged = true - lookup.steps = { first } - return nofsteps - 1 -end - - -local function mergesteps_2(lookup,strict) -- pairs - local steps = lookup.steps - local nofsteps = lookup.nofsteps - local first = steps[1] - if strict then - local f = first.format - for i=2,nofsteps do - if steps[i].format ~= f then - report("not merging %a steps of %a lookup %a, different formats",nofsteps,lookup.type,lookup.name) - return 0 - end - end - end - report("merging %a steps of %a lookup %a",nofsteps,lookup.type,lookup.name) - local target = first.coverage - for i=2,nofsteps do - for k, v in next, steps[i].coverage do - local tk = target[k] - if tk then - for k, v in next, v do - if not tk[k] then - tk[k] = v - end - end - else - target[k] = v - end - end - end - lookup.nofsteps = 1 - lookup.steps = { first } - return nofsteps - 1 -end - - -local function mergesteps_3(lookup,strict) -- marks - local steps = lookup.steps - local nofsteps = lookup.nofsteps - local first = steps[1] - report("merging %a steps of %a lookup %a",nofsteps,lookup.type,lookup.name) - local baseclasses = { } - local coverage = { } - local used = { } - for i=1,nofsteps do - local offset = i*10 - local step = steps[i] - for k, v in sortedhash(step.baseclasses) do - baseclasses[offset+k] = v - end - for k, v in next, step.coverage do - local tk = coverage[k] - if tk then - for k, v in next, v do - if not tk[k] then - tk[k] = v - local c = offset + v[1] - v[1] = c - if not used[c] then - used[c] = true - end - end - end - else - coverage[k] = v - local c = offset + v[1] - v[1] = c - if not used[c] then - used[c] = true - end - end - end - end - for k, v in next, baseclasses do - if not used[k] then - baseclasses[k] = nil - report("discarding not used baseclass %i",k) - end - end - first.baseclasses = baseclasses - first.coverage = coverage - lookup.nofsteps = 1 - lookup.steps = { first } - return nofsteps - 1 -end - -local function nested(old,new) - for k, v in next, old do - if k == "ligature" then - if not new.ligature then - new.ligature = v - end - else - local n = new[k] - if n then - nested(v,n) - else - new[k] = v - end - end - end -end - -local function mergesteps_4(lookup) -- ligatures - local steps = lookup.steps - local nofsteps = lookup.nofsteps - local first = steps[1] - report("merging %a steps of %a lookup %a",nofsteps,lookup.type,lookup.name) - local target = first.coverage - for i=2,nofsteps do - for k, v in next, steps[i].coverage do - local tk = target[k] - if tk then - nested(v,tk) - else - target[k] = v - end - end - end - lookup.nofsteps = 1 - lookup.steps = { first } - return nofsteps - 1 -end - -local function checkkerns(lookup) - local steps = lookup.steps - local nofsteps = lookup.nofsteps - for i=1,nofsteps do - local step = steps[i] - if step.format == "pair" then - local coverage = step.coverage - local kerns = true - for g1, d1 in next, coverage do - if d1[1] ~= 0 or d1[2] ~= 0 or d1[4] ~= 0 then - kerns = false - break - end - end - if kerns then - report("turning pairs of step %a of %a lookup %a into kerns",i,lookup.type,lookup.name) - for g1, d1 in next, coverage do - coverage[g1] = d1[3] - end - step.format = "kern" - end - end - end -end - -local function checkpairs(lookup) - local steps = lookup.steps - local nofsteps = lookup.nofsteps - local kerned = 0 - for i=1,nofsteps do - local step = steps[i] - if step.format == "pair" then - local coverage = step.coverage - local kerns = true - for g1, d1 in next, coverage do - for g2, d2 in next, d1 do - if d2[2] then - kerns = false - break - else - local v = d2[1] - if v[1] ~= 0 or v[2] ~= 0 or v[4] ~= 0 then - kerns = false - break - end - end - end - end - if kerns then - report("turning pairs of step %a of %a lookup %a into kerns",i,lookup.type,lookup.name) - for g1, d1 in next, coverage do - for g2, d2 in next, d1 do - d1[g2] = d2[1][3] - end - end - step.format = "kern" - kerned = kerned + 1 - end - end - end - return kerned -end - -function readers.compact(data) - if not data or data.compacted then - return - else - data.compacted = true - end - local resources = data.resources - local merged = 0 - local kerned = 0 - local allsteps = 0 - local function compact(what) - local lookups = resources[what] - if lookups then - for i=1,#lookups do - local lookup = lookups[i] - local nofsteps = lookup.nofsteps - allsteps = allsteps + nofsteps - if nofsteps > 1 then - local kind = lookup.type - if kind == "gsub_single" or kind == "gsub_alternate" or kind == "gsub_multiple" then - merged = merged + mergesteps_1(lookup) - elseif kind == "gsub_ligature" then - merged = merged + mergesteps_4(lookup) - elseif kind == "gpos_single" then - merged = merged + mergesteps_1(lookup,true) - checkkerns(lookup) - elseif kind == "gpos_pair" then - merged = merged + mergesteps_2(lookup,true) - kerned = kerned + checkpairs(lookup) - elseif kind == "gpos_cursive" then - merged = merged + mergesteps_2(lookup) - elseif kind == "gpos_mark2mark" or kind == "gpos_mark2base" or kind == "gpos_mark2ligature" then - merged = merged + mergesteps_3(lookup) - end - end - end - else - report("no lookups in %a",what) - end - end - compact("sequences") - compact("sublookups") - if merged > 0 then - report("%i steps of %i removed due to merging",merged,allsteps) - end - if kerned > 0 then - report("%i steps of %i steps turned from pairs into kerns",kerned,allsteps) - end -end - -function readers.expand(data) - if not data or data.expanded then - return - else - data.expanded = true - end - local resources = data.resources - local sublookups = resources.sublookups - local sequences = resources.sequences -- were one level up - local markclasses = resources.markclasses - local descriptions = data.descriptions - if descriptions then - local defaultwidth = resources.defaultwidth or 0 - local defaultheight = resources.defaultheight or 0 - local defaultdepth = resources.defaultdepth or 0 - local basename = trace_markwidth and file.basename(resources.filename) - for u, d in next, descriptions do - local bb = d.boundingbox - local wd = d.width - if not wd then - -- or bb? - d.width = defaultwidth - elseif trace_markwidth and wd ~= 0 and d.class == "mark" then - report("mark %a with width %b found in %a",d.name or "<noname>",wd,basename) - end - if bb then - local ht = bb[4] - local dp = -bb[2] - if ht == 0 or ht < 0 then - -- not set - else - d.height = ht - end - if dp == 0 or dp < 0 then - -- not set - else - d.depth = dp - end - end - end - end - local function expandlookups(sequences) - if sequences then - -- we also need to do sublookups - for i=1,#sequences do - local sequence = sequences[i] - local steps = sequence.steps - if steps then - local kind = sequence.type - local markclass = sequence.markclass - if markclass then - if not markclasses then - report_warning("missing markclasses") - sequence.markclass = false - else - sequence.markclass = markclasses[markclass] - end - end - for i=1,sequence.nofsteps do - local step = steps[i] - local baseclasses = step.baseclasses - if baseclasses then - local coverage = step.coverage - for k, v in next, coverage do - v[1] = baseclasses[v[1]] -- slot 1 is a placeholder - end - elseif kind == "gpos_cursive" then - local coverage = step.coverage - for k, v in next, coverage do - v[1] = coverage -- slot 1 is a placeholder - end - end - local rules = step.rules - if rules then - local rulehash = { } - local rulesize = 0 - local coverage = { } - local lookuptype = sequence.type - step.coverage = coverage -- combined hits - for nofrules=1,#rules do - local rule = rules[nofrules] - local current = rule.current - local before = rule.before - local after = rule.after - local replacements = rule.replacements or false - local sequence = { } - local nofsequences = 0 - if before then - for n=1,#before do - nofsequences = nofsequences + 1 - sequence[nofsequences] = before[n] - end - end - local start = nofsequences + 1 - for n=1,#current do - nofsequences = nofsequences + 1 - sequence[nofsequences] = current[n] - end - local stop = nofsequences - if after then - for n=1,#after do - nofsequences = nofsequences + 1 - sequence[nofsequences] = after[n] - end - end - local lookups = rule.lookups or false - local subtype = nil - if lookups then - -- is now indexed - for k, v in next, lookups do - local lookup = sublookups[v] - if lookup then - lookups[k] = lookup - if not subtype then - subtype = lookup.type - end - else - -- already expanded - end - end - end - if sequence[1] then -- we merge coverage into one - rulesize = rulesize + 1 - rulehash[rulesize] = { - nofrules, -- 1 - lookuptype, -- 2 - sequence, -- 3 - start, -- 4 - stop, -- 5 - lookups, -- 6 (6/7 also signal of what to do) - replacements, -- 7 - subtype, -- 8 - } - for unic in next, sequence[start] do - local cu = coverage[unic] - if not cu then - coverage[unic] = rulehash -- can now be done cleaner i think - end - end - end - end - end - end - end - end - end - end - expandlookups(sequences) - expandlookups(sublookups) -end diff --git a/tex/compat/luaotfload/fontloader-font-tfm.lua b/tex/compat/luaotfload/fontloader-font-tfm.lua deleted file mode 100644 index 6584190ce380d31e04305f3e9ca2a3c9b500df81..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/fontloader-font-tfm.lua +++ /dev/null @@ -1,711 +0,0 @@ -if not modules then modules = { } end modules ['font-tfm'] = { - version = 1.001, - comment = "companion to font-ini.mkiv", - 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 match, format = string.match, string.format -local concat, sortedhash = table.concat, table.sortedhash - -local trace_defining = false trackers.register("fonts.defining", function(v) trace_defining = v end) -local trace_features = false trackers.register("tfm.features", function(v) trace_features = v end) - -local report_defining = logs.reporter("fonts","defining") -local report_tfm = logs.reporter("fonts","tfm loading") - -local findbinfile = resolvers.findbinfile -local setmetatableindex = table.setmetatableindex - -local fonts = fonts -local handlers = fonts.handlers -local readers = fonts.readers -local constructors = fonts.constructors -local encodings = fonts.encodings - -local tfm = constructors.handlers.tfm -tfm.version = 1.000 -tfm.maxnestingdepth = 5 -tfm.maxnestingsize = 65536*1024 - -local otf = fonts.handlers.otf -local otfenhancers = otf.enhancers - -local tfmfeatures = constructors.features.tfm -local registertfmfeature = tfmfeatures.register - -local tfmenhancers = constructors.enhancers.tfm -local registertfmenhancer = tfmenhancers.register - -constructors.resolvevirtualtoo = false -- wil be set in font-ctx.lua - -fonts.formats.tfm = "type1" -- we need to have at least a value here -fonts.formats.ofm = "type1" -- we need to have at least a value here - ---[[ldx-- -<p>The next function encapsulates the standard <l n='tfm'/> loader as -supplied by <l n='luatex'/>.</p> ---ldx]]-- - --- this might change: not scaling and then apply features and do scaling in the --- usual way with dummy descriptions but on the other hand .. we no longer use --- tfm so why bother - --- ofm directive blocks local path search unless set; btw, in context we --- don't support ofm files anyway as this format is obsolete - --- we need to deal with nested virtual fonts, but because we load in the --- frontend we also need to make sure we don't nest too deep (esp when sizes --- get large) --- --- (VTITLE Example of a recursion) --- (MAPFONT D 0 (FONTNAME recurse)(FONTAT D 2)) --- (CHARACTER C A (CHARWD D 1)(CHARHT D 1)(MAP (SETRULE D 1 D 1))) --- (CHARACTER C B (CHARWD D 2)(CHARHT D 2)(MAP (SETCHAR C A))) --- (CHARACTER C C (CHARWD D 4)(CHARHT D 4)(MAP (SETCHAR C B))) --- --- we added the same checks as below to the luatex engine - -function tfm.setfeatures(tfmdata,features) - local okay = constructors.initializefeatures("tfm",tfmdata,features,trace_features,report_tfm) - if okay then - return constructors.collectprocessors("tfm",tfmdata,features,trace_features,report_tfm) - else - return { } -- will become false - end -end - -local depth = { } -- table.setmetatableindex("number") - --- Normally we just load the tfm data and go on. However there was some demand for --- loading good old tfm /pfb files where afm files were lacking and even enc files --- of dubious quality so we now support loading such (often messy) setups too. --- --- Because such fonts also use (ugly) tweaks achieve some purpose (like swapping --- accents) we need to delay the unicoding actions till after the features have been --- applied. --- --- It must be noted that in ConTeXt we don't expect this to be used at all. Here is --- example: --- --- tfm metrics + pfb vector for index + pfb file for shapes --- --- \font\foo=file:csr10.tfm:reencode=auto;mode=node;liga=yes;kern=yes --- --- tfm metrics + pfb vector for index + enc file for tfm mapping + pfb file for shapes --- --- \font\foo=file:csr10.tfm:reencode=csr.enc;mode=node;liga=yes;kern=yes --- --- tfm metrics + enc file for mapping to tfm + bitmaps shapes --- --- \font\foo=file:csr10.tfm:reencode=csr.enc;bitmap=yes;mode=node;liga=yes;kern=yes --- --- One can add features: --- --- fonts.handlers.otf.addfeature { --- name = "czechdqcheat", --- type = "substitution", --- data = { --- quotedblright = "csquotedblright", --- }, --- } --- --- So "czechdqcheat=yes" is then a valid feature. And yes, it's a cheat. - - -local function read_from_tfm(specification) - local filename = specification.filename - local size = specification.size - depth[filename] = (depth[filename] or 0) + 1 - if trace_defining then - report_defining("loading tfm file %a at size %s",filename,size) - end - local tfmdata = font.read_tfm(filename,size) -- not cached, fast enough - if tfmdata then - - local features = specification.features and specification.features.normal or { } - local features = constructors.checkedfeatures("tfm",features) - specification.features.normal = features - - -- If reencode returns a new table, we assume that we're doing something - -- special. An 'auto' reencode pickt up its vector from the pfb file. - - local newtfmdata = (depth[filename] == 1) and tfm.reencode(tfmdata,specification) - if newtfmdata then - tfmdata = newtfmdata - end - - local resources = tfmdata.resources or { } - local properties = tfmdata.properties or { } - local parameters = tfmdata.parameters or { } - local shared = tfmdata.shared or { } - -- - shared.features = features - shared.resources = resources - -- - properties.name = tfmdata.name -- todo: fallback - properties.fontname = tfmdata.fontname -- todo: fallback - properties.psname = tfmdata.psname -- todo: fallback - properties.fullname = tfmdata.fullname -- todo: fallback - properties.filename = specification.filename -- todo: fallback - properties.format = fonts.formats.tfm -- better than nothing - -- - tfmdata.properties = properties - tfmdata.resources = resources - tfmdata.parameters = parameters - tfmdata.shared = shared - -- - shared.rawdata = { resources = resources } - shared.features = features - -- - -- The next branch is only entered when we have a proper encoded file i.e. - -- unicodes and such. It really nakes no sense to do feature juggling when - -- we have no names and unicodes. - -- - if newtfmdata then - -- - -- Some opentype processing assumes these to be present: - -- - if not resources.marks then - resources.marks = { } - end - if not resources.sequences then - resources.sequences = { } - end - if not resources.features then - resources.features = { - gsub = { }, - gpos = { }, - } - end - if not tfmdata.changed then - tfmdata.changed = { } - end - if not tfmdata.descriptions then - tfmdata.descriptions = tfmdata.characters - end - -- - -- It might be handy to have this: - -- - otf.readers.addunicodetable(tfmdata) - -- - -- We make a pseudo opentype font, e.g. kerns and ligatures etc: - -- - tfmenhancers.apply(tfmdata,filename) - -- - -- Now user stuff can kick in. - -- - constructors.applymanipulators("tfm",tfmdata,features,trace_features,report_tfm) - -- - -- As that can also mess with names and such, we are now ready for finalizing - -- the unicode information. This is a different order that for instance type one - -- (afm) files. First we try to deduce unicodes from already present information. - -- - otf.readers.unifymissing(tfmdata) - -- - -- Next we fill in the gaps, based on names from teh agl. Probably not much will - -- happen here. - -- - fonts.mappings.addtounicode(tfmdata,filename) - -- - -- The tounicode data is passed to the backend that constructs the vectors for us. - -- - tfmdata.tounicode = 1 - local tounicode = fonts.mappings.tounicode - for unicode, v in next, tfmdata.characters do - local u = v.unicode - if u then - v.tounicode = tounicode(u) - end - end - -- - -- However, when we use a bitmap font those vectors can't be constructed because - -- that information is not carried with those fonts (there is no name info, nor - -- proper index info, nor unicodes at that end). So, we provide it ourselves. - -- - if tfmdata.usedbitmap then - tfm.addtounicode(tfmdata) - end - end - -- - shared.processes = next(features) and tfm.setfeatures(tfmdata,features) or nil - -- - parameters.factor = 1 -- already scaled - parameters.size = size - parameters.slant = parameters.slant or parameters[1] or 0 - parameters.space = parameters.space or parameters[2] or 0 - parameters.space_stretch = parameters.space_stretch or parameters[3] or 0 - parameters.space_shrink = parameters.space_shrink or parameters[4] or 0 - parameters.x_height = parameters.x_height or parameters[5] or 0 - parameters.quad = parameters.quad or parameters[6] or 0 - parameters.extra_space = parameters.extra_space or parameters[7] or 0 - -- - constructors.enhanceparameters(parameters) -- official copies for us - -- - if newtfmdata then - -- - -- We do nothing as we assume flat tfm files. It would become real messy - -- otherwise and I don't have something for testing on my system anyway. - -- - elseif constructors.resolvevirtualtoo then - fonts.loggers.register(tfmdata,file.suffix(filename),specification) -- strange, why here - local vfname = findbinfile(specification.name, 'ovf') - if vfname and vfname ~= "" then - local vfdata = font.read_vf(vfname,size) -- not cached, fast enough - if vfdata then - local chars = tfmdata.characters - for k,v in next, vfdata.characters do - chars[k].commands = v.commands - end - properties.virtualized = true - tfmdata.fonts = vfdata.fonts - tfmdata.type = "virtual" -- else nested calls with cummulative scaling - local fontlist = vfdata.fonts - local name = file.nameonly(filename) - for i=1,#fontlist do - local n = fontlist[i].name - local s = fontlist[i].size - local d = depth[filename] - s = constructors.scaled(s,vfdata.designsize) - if d > tfm.maxnestingdepth then - report_defining("too deeply nested virtual font %a with size %a, max nesting depth %s",n,s,tfm.maxnestingdepth) - fontlist[i] = { id = 0 } - elseif (d > 1) and (s > tfm.maxnestingsize) then - report_defining("virtual font %a exceeds size %s",n,s) - fontlist[i] = { id = 0 } - else - local t, id = fonts.constructors.readanddefine(n,s) - fontlist[i] = { id = id } - end - end - end - end - end - -- - -- This is for old times sake (and context specific) so we comment it. It has - -- to do with encoding prefixes (a context naming that was later adopted by - -- the lm/gyre project) - -- - -- if not features.encoding then - -- local encoding, filename = match(properties.filename,"^(.-)%-(.*)$") - -- if filename and encoding and encodings.known and encodings.known[encoding] then - -- features.encoding = encoding - -- end - -- end - -- - -- Some afterthoughts: - -- - properties.haskerns = true - properties.hasligatures = true - resources.unicodes = { } - resources.lookuptags = { } - -- - depth[filename] = depth[filename] - 1 - -- - return tfmdata - else - depth[filename] = depth[filename] - 1 - end -end - -local function check_tfm(specification,fullname) -- we could split up like afm/otf - local foundname = findbinfile(fullname, 'tfm') or "" - if foundname == "" then - foundname = findbinfile(fullname, 'ofm') or "" -- not needed in context - end - if foundname == "" then - foundname = fonts.names.getfilename(fullname,"tfm") or "" - end - if foundname ~= "" then - specification.filename = foundname - specification.format = "ofm" - return read_from_tfm(specification) - elseif trace_defining then - report_defining("loading tfm with name %a fails",specification.name) - end -end - -readers.check_tfm = check_tfm - -function readers.tfm(specification) - local fullname = specification.filename or "" - if fullname == "" then - local forced = specification.forced or "" - if forced ~= "" then - fullname = specification.name .. "." .. forced - else - fullname = specification.name - end - end - return check_tfm(specification,fullname) -end - -readers.ofm = readers.tfm - --- The reencoding acts upon the 'reencode' feature which can have values 'auto' or --- an enc file. You can also specify a 'pfbfile' feature (but it defaults to the --- tfm filename) and a 'bitmap' feature. When no enc file is givven (auto) we will --- get the vectors from the pfb file. - -do - - local outfiles = { } - - local tfmcache = table.setmetatableindex(function(t,tfmdata) - local id = font.define(tfmdata) - t[tfmdata] = id - return id - end) - - local encdone = table.setmetatableindex("table") - - function tfm.reencode(tfmdata,specification) - - local features = specification.features - - if not features then - return - end - - local features = features.normal - - if not features then - return - end - - local tfmfile = file.basename(tfmdata.name) - local encfile = features.reencode -- or features.enc - local pfbfile = features.pfbfile -- or features.pfb - local bitmap = features.bitmap -- or features.pk - - if not encfile then - return - end - - local pfbfile = outfiles[tfmfile] - - if pfbfile == nil then - if bitmap then - pfbfile = false - elseif type(pfbfile) ~= "string" then - pfbfile = tfmfile - end - if type(pfbfile) == "string" then - pfbfile = file.addsuffix(pfbfile,"pfb") - -- pdf.mapline(tfmfile .. "<" .. pfbfile) - report_tfm("using type1 shapes from %a for %a",pfbfile,tfmfile) - else - report_tfm("using bitmap shapes for %a",tfmfile) - pfbfile = false -- use bitmap - end - outfiles[tfmfile] = pfbfile - end - - local encoding = false - local vector = false - - if type(pfbfile) == "string" then - local pfb = fonts.constructors.handlers.pfb - if pfb and pfb.loadvector then - local v, e = pfb.loadvector(pfbfile) - if v then - vector = v - end - if e then - encoding = e - end - end - end - if type(encfile) == "string" and encfile ~= "auto" then - encoding = fonts.encodings.load(file.addsuffix(encfile,"enc")) - if encoding then - encoding = encoding.vector - end - end - if not encoding then - report_tfm("bad encoding for %a, quitting",tfmfile) - return - end - - local unicoding = fonts.encodings.agl and fonts.encodings.agl.unicodes - local virtualid = tfmcache[tfmdata] - local tfmdata = table.copy(tfmdata) -- good enough for small fonts - local characters = { } - local originals = tfmdata.characters - local indices = { } - local parentfont = { "font", 1 } - local private = fonts.constructors.privateoffset - local reported = encdone[tfmfile][encfile] - - -- create characters table - - local backmap = vector and table.swapped(vector) - local done = { } -- prevent duplicate - - for index, name in sortedhash(encoding) do -- predictable order - local unicode = unicoding[name] - local original = originals[index] - if original then - if unicode then - original.unicode = unicode - else - unicode = private - private = private + 1 - if not reported then - report_tfm("glyph %a in font %a with encoding %a gets unicode %U",name,tfmfile,encfile,unicode) - end - end - characters[unicode] = original - indices[index] = unicode - original.name = name -- so one can lookup weird names - if backmap then - original.index = backmap[name] - else -- probably bitmap - original.commands = { parentfont, { "char", index } } - original.oindex = index - end - done[name] = true - elseif not done[name] then - report_tfm("bad index %a in font %a with name %a",index,tfmfile,name) - end - end - - encdone[tfmfile][encfile] = true - - -- redo kerns and ligatures - - for k, v in next, characters do - local kerns = v.kerns - if kerns then - local t = { } - for k, v in next, kerns do - local i = indices[k] - if i then - t[i] = v - end - end - v.kerns = next(t) and t or nil - end - local ligatures = v.ligatures - if ligatures then - local t = { } - for k, v in next, ligatures do - local i = indices[k] - if i then - t[i] = v - v.char = indices[v.char] - end - end - v.ligatures = next(t) and t or nil - end - end - - -- wrap up - - tfmdata.fonts = { { id = virtualid } } - tfmdata.characters = characters - tfmdata.fullname = tfmdata.fullname or tfmdata.name - tfmdata.psname = file.nameonly(pfbfile or tfmdata.name) - tfmdata.filename = pfbfile - tfmdata.encodingbytes = 2 - tfmdata.format = "type1" - tfmdata.tounicode = 1 - tfmdata.embedding = "subset" - tfmdata.usedbitmap = bitmap and virtualid - - return tfmdata - end - -end - --- This code adds a ToUnicode vector for bitmap fonts. We don't bother about --- ranges because we have small fonts. it works ok with acrobat but fails with --- the other viewers (they get confused by the bitmaps I guess). - -do - - local template = [[ -/CIDInit /ProcSet findresource begin - 12 dict begin - begincmap - /CIDSystemInfo << /Registry (TeX) /Ordering (bitmap-%s) /Supplement 0 >> def - /CMapName /TeX-bitmap-%s def - /CMapType 2 def - 1 begincodespacerange - <00> <FF> - endcodespacerange - %s beginbfchar -%s - endbfchar - endcmap -CMapName currentdict /CMap defineresource pop end -end -end -]] - - local flushstreamobject = lpdf and lpdf.flushstreamobject - local setfontattributes = pdf.setfontattributes - - if not flushstreamobject then - flushstreamobject = function(data) - return pdf.obj { - immediate = true, - type = "stream", - string = data, - } - end - end - - if not setfontattributes then - setfontattributes = function(id,data) - print(format("your luatex is too old so no tounicode bitmap font%i",id)) - end - end - - function tfm.addtounicode(tfmdata) - local id = tfmdata.usedbitmap - local map = { } - local char = { } -- no need for range, hardly used - for k, v in next, tfmdata.characters do - local index = v.oindex - local tounicode = v.tounicode - if index and tounicode then - map[index] = tounicode - end - end - for k, v in sortedhash(map) do - char[#char+1] = format("<%02X> <%s>",k,v) - end - char = concat(char,"\n") - local stream = format(template,id,id,#char,char) - local reference = flushstreamobject(stream,nil,true) - setfontattributes(id,format("/ToUnicode %i 0 R",reference)) - end - -end - --- Now we implement the regular features handlers. We need to convert the --- tfm specific structures to opentype structures. In basemode they are --- converted back so that is a bti of a waste but it's fast enough. - -do - - local everywhere = { ["*"] = { ["*"] = true } } -- or: { ["*"] = { "*" } } - local noflags = { false, false, false, false } - - local function enhance_normalize_features(data) - local ligatures = setmetatableindex("table") - local kerns = setmetatableindex("table") - local characters = data.characters - for u, c in next, characters do - local l = c.ligatures - local k = c.kerns - if l then - ligatures[u] = l - for u, v in next, l do - l[u] = { ligature = v.char } - end - c.ligatures = nil - end - if k then - kerns[u] = k - for u, v in next, k do - k[u] = v -- { v, 0 } - end - c.kerns = nil - end - end - - for u, l in next, ligatures do - for k, v in next, l do - local vl = v.ligature - local dl = ligatures[vl] - if dl then - for kk, vv in next, dl do - v[kk] = vv -- table.copy(vv) - end - end - end - end - - local features = { - gpos = { }, - gsub = { }, - } - local sequences = { - -- only filled ones - } - if next(ligatures) then - features.gsub.liga = everywhere - data.properties.hasligatures = true - sequences[#sequences+1] = { - features = { - liga = everywhere, - }, - flags = noflags, - name = "s_s_0", - nofsteps = 1, - order = { "liga" }, - type = "gsub_ligature", - steps = { - { - coverage = ligatures, - }, - }, - } - end - if next(kerns) then - features.gpos.kern = everywhere - data.properties.haskerns = true - sequences[#sequences+1] = { - features = { - kern = everywhere, - }, - flags = noflags, - name = "p_s_0", - nofsteps = 1, - order = { "kern" }, - type = "gpos_pair", - steps = { - { - format = "kern", - coverage = kerns, - }, - }, - } - end - data.resources.features = features - data.resources.sequences = sequences - data.shared.resources = data.shared.resources or resources - end - - registertfmenhancer("normalize features", enhance_normalize_features) - registertfmenhancer("check extra features", otfenhancers.enhance) - -end - --- As with type one (afm) loading, we just use the opentype ones: - -registertfmfeature { - name = "mode", - description = "mode", - initializers = { - base = otf.modeinitializer, - node = otf.modeinitializer, - } -} - -registertfmfeature { - name = "features", - description = "features", - default = true, - initializers = { - base = otf.basemodeinitializer, - node = otf.nodemodeinitializer, - }, - processors = { - node = otf.featuresprocessor, - } -} diff --git a/tex/compat/luaotfload/fontloader-font-ttf.lua b/tex/compat/luaotfload/fontloader-font-ttf.lua deleted file mode 100644 index 6df339214b2d0a2ee9c6edf3faa0439f1255dec7..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/fontloader-font-ttf.lua +++ /dev/null @@ -1,480 +0,0 @@ -if not modules then modules = { } end modules ['font-ttf'] = { - version = 1.001, - comment = "companion to font-ini.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -local next, type, unpack = next, type, unpack -local bittest = bit32.btest -local sqrt = math.sqrt - -local report = logs.reporter("otf reader","ttf") - -local readers = fonts.handlers.otf.readers -local streamreader = readers.streamreader - -local setposition = streamreader.setposition -local getposition = streamreader.getposition -local skipbytes = streamreader.skip -local readbyte = streamreader.readcardinal1 -- 8-bit unsigned integer -local readushort = streamreader.readcardinal2 -- 16-bit unsigned integer -local readulong = streamreader.readcardinal4 -- 24-bit unsigned integer -local readchar = streamreader.readinteger1 -- 8-bit signed integer -local readshort = streamreader.readinteger2 -- 16-bit signed integer -local read2dot14 = streamreader.read2dot14 -- 16-bit signed fixed number with the low 14 bits of fraction (2.14) (F2DOT14) - -local function mergecomposites(glyphs,shapes) - - local function merge(index,shape,components) - local contours = { } - local nofcontours = 0 - for i=1,#components do - local component = components[i] - local subindex = component.index - local subshape = shapes[subindex] - local subcontours = subshape.contours - if not subcontours then - local subcomponents = subshape.components - if subcomponents then - subcontours = merge(subindex,subshape,subcomponents) - end - end - if subcontours then - local matrix = component.matrix - local xscale = matrix[1] - local xrotate = matrix[2] - local yrotate = matrix[3] - local yscale = matrix[4] - local xoffset = matrix[5] - local yoffset = matrix[6] - for i=1,#subcontours do - local points = subcontours[i] - local result = { } - for i=1,#points do - local p = points[i] - local x = p[1] - local y = p[2] - result[i] = { - xscale * x + xrotate * y + xoffset, - yscale * y + yrotate * x + yoffset, - p[3] - } - end - nofcontours = nofcontours + 1 - contours[nofcontours] = result - end - else - report("missing contours composite %s, component %s of %s, glyph %s",index,i,#components,subindex) - end - end - shape.contours = contours - shape.components = nil - return contours - end - - for index=1,#glyphs do - local shape = shapes[index] - local components = shape.components - if components then - merge(index,shape,components) - end - end - -end - -local function readnothing(f,nofcontours) - return { - type = "nothing", - } -end - --- begin of converter - --- make paths: the ff code is quite complex but it looks like we need to deal --- with all kind of on curve border cases - -local function curveto(m_x,m_y,l_x,l_y,r_x,r_y) -- todo: inline this - return { - l_x + 2/3 *(m_x-l_x), l_y + 2/3 *(m_y-l_y), - r_x + 2/3 *(m_x-r_x), r_y + 2/3 *(m_y-r_y), - r_x, r_y, "c" -- "curveto" - } -end - --- We could omit the operator which saves some 10%: --- --- #2=lineto #4=quadratic #6=cubic #3=moveto (with "m") --- --- For the moment we keep the original outlines but that default might change --- in the future. In any case, a backend should support both. --- --- The code is a bit messy. I looked at the ff code but it's messy too. It has --- to do with the fact that we need to look at points on the curve and control --- points in between. This also means that we start at point 2 and have to look at --- point 1 when we're at the end. We still use a ps like storage with the operator --- last in an entry. It's typical code that evolves stepwise till a point of no --- comprehension. - -local function contours2outlines(glyphs,shapes) - local quadratic = true - -- local quadratic = false - for index=1,#glyphs do - local glyph = glyphs[index] - local shape = shapes[index] - local contours = shape.contours - if contours then - local nofcontours = #contours - local segments = { } - local nofsegments = 0 - glyph.segments = segments - if nofcontours > 0 then - for i=1,nofcontours do - local contour = contours[i] - local nofcontour = #contour - if nofcontour > 0 then - local first_pt = contour[1] - local first_on = first_pt[3] - -- todo no new tables but reuse lineto and quadratic - if nofcontour == 1 then - -- this can influence the boundingbox - first_pt[3] = "m" -- "moveto" - nofsegments = nofsegments + 1 - segments[nofsegments] = first_pt - else -- maybe also treat n == 2 special - local first_on = first_pt[3] - local last_pt = contour[nofcontour] - local last_on = last_pt[3] - local start = 1 - local control_pt = false - if first_on then - start = 2 - else - if last_on then - first_pt = last_pt - else - first_pt = { (first_pt[1]+last_pt[1])/2, (first_pt[2]+last_pt[2])/2, false } - end - control_pt = first_pt - end - nofsegments = nofsegments + 1 - segments[nofsegments] = { first_pt[1], first_pt[2], "m" } -- "moveto" - local previous_pt = first_pt - for i=start,nofcontour do - local current_pt = contour[i] - local current_on = current_pt[3] - local previous_on = previous_pt[3] - if previous_on then - if current_on then - -- both normal points - nofsegments = nofsegments + 1 - segments[nofsegments] = { current_pt[1], current_pt[2], "l" } -- "lineto" - else - control_pt = current_pt - end - elseif current_on then - local ps = segments[nofsegments] - nofsegments = nofsegments + 1 - if quadratic then - segments[nofsegments] = { control_pt[1], control_pt[2], current_pt[1], current_pt[2], "q" } -- "quadraticto" - else - local p = segments[nofsegments-1] local n = #p - segments[nofsegments] = curveto(control_pt[1],control_pt[2],p[n-2],p[n-1],current_pt[1],current_pt[2]) - end - control_pt = false - else - nofsegments = nofsegments + 1 - local halfway_x = (previous_pt[1]+current_pt[1])/2 - local halfway_y = (previous_pt[2]+current_pt[2])/2 - if quadratic then - segments[nofsegments] = { control_pt[1], control_pt[2], halfway_x, halfway_y, "q" } -- "quadraticto" - else - local p = segments[nofsegments-1] local n = #p - segments[nofsegments] = curveto(control_pt[1],control_pt[2],p[n-2],p[n-1],halfway_x,halfway_y) - end - control_pt = current_pt - end - previous_pt = current_pt - end - if first_pt == last_pt then - -- we're already done, probably a simple curve - else - nofsegments = nofsegments + 1 - if not control_pt then - segments[nofsegments] = { first_pt[1], first_pt[2], "l" } -- "lineto" - elseif quadratic then - segments[nofsegments] = { control_pt[1], control_pt[2], first_pt[1], first_pt[2], "q" } -- "quadraticto" - else - local p = last_pt local n = #p - segments[nofsegments] = curveto(control_pt[1],control_pt[2],p[n-2],p[n-1],first_pt[1],first_pt[2]) - end - end - end - end - end - end - end - end -end - --- end of converter - -local function readglyph(f,nofcontours) - local points = { } - local endpoints = { } - local instructions = { } - local flags = { } - for i=1,nofcontours do - endpoints[i] = readshort(f) + 1 - end - local nofpoints = endpoints[nofcontours] - local nofinstructions = readushort(f) --- f:seek("set",f:seek()+nofinstructions) - skipbytes(f,nofinstructions) - -- because flags can repeat we don't know the amount ... in fact this is - -- not that efficient (small files but more mem) - local i = 1 - while i <= nofpoints do - local flag = readbyte(f) - flags[i] = flag - if bittest(flag,0x0008) then - for j=1,readbyte(f) do - i = i + 1 - flags[i] = flag - end - end - i = i + 1 - end - -- first come the x coordinates, and next the y coordinates and they - -- can be repeated - local x = 0 - for i=1,nofpoints do - local flag = flags[i] - local short = bittest(flag,0x0002) - local same = bittest(flag,0x0010) - if short then - if same then - x = x + readbyte(f) - else - x = x - readbyte(f) - end - elseif same then - -- copy - else - x = x + readshort(f) - end - points[i] = { x, y, bittest(flag,0x0001) } - end - local y = 0 - for i=1,nofpoints do - local flag = flags[i] - local short = bittest(flag,0x0004) - local same = bittest(flag,0x0020) - if short then - if same then - y = y + readbyte(f) - else - y = y - readbyte(f) - end - elseif same then - -- copy - else - y = y + readshort(f) - end - points[i][2] = y - end - -- we could integrate this if needed - local first = 1 - for i=1,#endpoints do - local last = endpoints[i] - endpoints[i] = { unpack(points,first,last) } - first = last + 1 - end - return { - type = "glyph", - -- points = points, - contours = endpoints, - } -end - -local function readcomposite(f) - local components = { } - local nofcomponents = 0 - local instructions = false - while true do - local flags = readushort(f) - local index = readushort(f) - ----- f_words = bittest(flags,0x0001) - local f_xyarg = bittest(flags,0x0002) - ----- f_round = bittest(flags,0x0004+0x0002) - ----- f_scale = bittest(flags,0x0008) - ----- f_reserved = bittest(flags,0x0010) - ----- f_more = bittest(flags,0x0020) - ----- f_xyscale = bittest(flags,0x0040) - ----- f_matrix = bittest(flags,0x0080) - ----- f_instruct = bittest(flags,0x0100) - ----- f_usemine = bittest(flags,0x0200) - ----- f_overlap = bittest(flags,0x0400) - local f_offset = bittest(flags,0x0800) - ----- f_uoffset = bittest(flags,0x1000) - local xscale = 1 - local xrotate = 0 - local yrotate = 0 - local yscale = 1 - local xoffset = 0 - local yoffset = 0 - local base = false - local reference = false - if f_xyarg then - if bittest(flags,0x0001) then -- f_words - xoffset = readshort(f) - yoffset = readshort(f) - else - xoffset = readchar(f) -- signed byte, stupid name - yoffset = readchar(f) -- signed byte, stupid name - end - else - if bittest(flags,0x0001) then -- f_words - base = readshort(f) - reference = readshort(f) - else - base = readchar(f) -- signed byte, stupid name - reference = readchar(f) -- signed byte, stupid name - end - end - if bittest(flags,0x0008) then -- f_scale - xscale = read2dot14(f) - yscale = xscale - if f_xyarg and f_offset then - xoffset = xoffset * xscale - yoffset = yoffset * yscale - end - elseif bittest(flags,0x0040) then -- f_xyscale - xscale = read2dot14(f) - yscale = read2dot14(f) - if f_xyarg and f_offset then - xoffset = xoffset * xscale - yoffset = yoffset * yscale - end - elseif bittest(flags,0x0080) then -- f_matrix - xscale = read2dot14(f) - xrotate = read2dot14(f) - yrotate = read2dot14(f) - yscale = read2dot14(f) - if f_xyarg and f_offset then - xoffset = xoffset * sqrt(xscale ^2 + xrotate^2) - yoffset = yoffset * sqrt(yrotate^2 + yscale ^2) - end - end - nofcomponents = nofcomponents + 1 - components[nofcomponents] = { - index = index, - usemine = bittest(flags,0x0200), -- f_usemine - round = bittest(flags,0x0006), -- f_round, - base = base, - reference = reference, - matrix = { xscale, xrotate, yrotate, yscale, xoffset, yoffset }, - } - if bittest(flags,0x0100) then - instructions = true - end - if not bittest(flags,0x0020) then -- f_more - break - end - end - return { - type = "composite", - components = components, - } -end - --- function readers.cff(f,offset,glyphs,doshapes) -- false == no shapes (nil or true otherwise) - --- The glyf table depends on the loca table. We have one entry to much --- in the locations table (the last one is a dummy) because we need to --- calculate the size of a glyph blob from the delta, although we not --- need it in our usage (yet). We can remove the locations table when --- we're done (todo: cleanup finalizer). - -function readers.loca(f,fontdata,specification) - if specification.glyphs then - local datatable = fontdata.tables.loca - if datatable then - -- locations are relative to the glypdata table (glyf) - local offset = fontdata.tables.glyf.offset - local format = fontdata.fontheader.indextolocformat - local locations = { } - setposition(f,datatable.offset) - if format == 1 then - local nofglyphs = datatable.length/4 - 1 - -1 - for i=0,nofglyphs do - locations[i] = offset + readulong(f) - end - fontdata.nofglyphs = nofglyphs - else - local nofglyphs = datatable.length/2 - 1 - -1 - for i=0,nofglyphs do - locations[i] = offset + readushort(f) * 2 - end - fontdata.nofglyphs = nofglyphs - end - fontdata.locations = locations - end - end -end - -function readers.glyf(f,fontdata,specification) -- part goes to cff module - if specification.glyphs then - local datatable = fontdata.tables.glyf - if datatable then - local locations = fontdata.locations - if locations then - local glyphs = fontdata.glyphs - local nofglyphs = fontdata.nofglyphs - local filesize = fontdata.filesize - local nothing = { 0, 0, 0, 0 } - local shapes = { } - local loadshapes = specification.shapes - for index=0,nofglyphs do - local location = locations[index] - if location >= filesize then - report("discarding %s glyphs due to glyph location bug",nofglyphs-index+1) - fontdata.nofglyphs = index - 1 - fontdata.badfont = true - break - elseif location > 0 then - setposition(f,location) - local nofcontours = readshort(f) - glyphs[index].boundingbox = { - readshort(f), -- xmin - readshort(f), -- ymin - readshort(f), -- xmax - readshort(f), -- ymax - } - if not loadshapes then - -- save space - elseif nofcontours == 0 then - shapes[index] = readnothing(f,nofcontours) - elseif nofcontours > 0 then - shapes[index] = readglyph(f,nofcontours) - else - shapes[index] = readcomposite(f,nofcontours) - end - else - if loadshapes then - shapes[index] = { } - end - glyphs[index].boundingbox = nothing - end - end - if loadshapes then - mergecomposites(glyphs,shapes) - contours2outlines(glyphs,shapes) - end - end - end - end -end diff --git a/tex/compat/luaotfload/fontloader-fonts-demo-vf-1.lua b/tex/compat/luaotfload/fontloader-fonts-demo-vf-1.lua deleted file mode 100644 index 793526f7be385b92b5c3076ae3cc042b11436b47..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/fontloader-fonts-demo-vf-1.lua +++ /dev/null @@ -1,52 +0,0 @@ -if not modules then modules = { } end modules ['luatex-fonts-demo-vf-1'] = { - version = 1.001, - comment = "companion to luatex-*.tex", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -local identifiers = fonts.hashes.identifiers - -return function(specification) - local f1, id1 = fonts.constructors.readanddefine('lmroman10-regular', specification.size) - local f2, id2 = fonts.constructors.readanddefine('lmsans10-regular', specification.size) - local f3, id3 = fonts.constructors.readanddefine('lmtypewriter10-regular',specification.size) - if f1 and f2 and f3 then - f1.properties.name = specification.name - f1.properties.virtualized = true - f1.fonts = { - { id = id1 }, - { id = id2 }, - { id = id3 }, - } - local color = { [0] = - { "special", "pdf:0 g" }, - { "special", "pdf:1 0 0 rg" }, - { "special", "pdf:0 1 0 rg" }, - { "special", "pdf:0 0 1 rg" }, - { "special", "pdf:0 0 1 rg" }, - } - local chars = { - identifiers[id1].characters, - identifiers[id2].characters, - identifiers[id3].characters, - } - for u, v in next, f1.characters do - local n = math.floor(math.random(1,3)+0.5) - local c = chars[n][u] or v - v.commands = { - color[n], - { 'slot', n, u }, - color[0], - { 'nop' } - } - v.kerns = nil - v.width = c.width - v.height = c.height - v.depth = c.depth - v.italic = nil - end - end - return f1 -end diff --git a/tex/compat/luaotfload/fontloader-fonts-enc.lua b/tex/compat/luaotfload/fontloader-fonts-enc.lua deleted file mode 100644 index c076d59477d89dc44d7d788a7c93bbc8ed486037..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/fontloader-fonts-enc.lua +++ /dev/null @@ -1,76 +0,0 @@ -if not modules then modules = { } end modules ['luatex-font-enc'] = { - version = 1.001, - comment = "companion to luatex-*.tex", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -if context then - texio.write_nl("fatal error: this module is not for context") - os.exit() -end - -local fonts = fonts -local encodings = { } -fonts.encodings = encodings -encodings.agl = { } -encodings.known = { } - -setmetatable(encodings.agl, { __index = function(t,k) - if k == "unicodes" then - texio.write(" <loading (extended) adobe glyph list>") - local unicodes = dofile(resolvers.findfile("font-age.lua")) - encodings.agl = { unicodes = unicodes } - return unicodes - else - return nil - end -end }) - --- adapted for generic - -encodings.cache = containers.define("fonts", "enc", encodings.version, true) - -function encodings.load(filename) - local name = file.removesuffix(filename) - local data = containers.read(encodings.cache,name) - if data then - return data - end - local vector, tag, hash, unicodes = { }, "", { }, { } - local foundname = resolvers.findfile(filename,'enc') - if foundname and foundname ~= "" then - local ok, encoding, size = resolvers.loadbinfile(foundname) - if ok and encoding then - encoding = string.gsub(encoding,"%%(.-)\n","") - local unicoding = encodings.agl.unicodes - local tag, vec = string.match(encoding,"/(%w+)%s*%[(.*)%]%s*def") - local i = 0 - for ch in string.gmatch(vec,"/([%a%d%.]+)") do - if ch ~= ".notdef" then - vector[i] = ch - if not hash[ch] then - hash[ch] = i - else - -- duplicate, play safe for tex ligs and take first - end - local u = unicoding[ch] - if u then - unicodes[u] = i - end - end - i = i + 1 - end - end - end - local data = { - name = name, - tag = tag, - vector = vector, - hash = hash, - unicodes = unicodes - } - return containers.write(encodings.cache, name, data) -end - diff --git a/tex/compat/luaotfload/fontloader-fonts-ext.lua b/tex/compat/luaotfload/fontloader-fonts-ext.lua deleted file mode 100644 index 0b61e27fd67140ec5fe0387a69cf421afd3d932f..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/fontloader-fonts-ext.lua +++ /dev/null @@ -1,287 +0,0 @@ -if not modules then modules = { } end modules ['luatex-fonts-ext'] = { - version = 1.001, - comment = "companion to luatex-*.tex", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -if context then - texio.write_nl("fatal error: this module is not for context") - os.exit() -end - -local fonts = fonts -local otffeatures = fonts.constructors.features.otf - --- A few generic extensions. - -local function initializeitlc(tfmdata,value) - if value then - -- the magic 40 and it formula come from Dohyun Kim but we might need another guess - local parameters = tfmdata.parameters - local italicangle = parameters.italicangle - if italicangle and italicangle ~= 0 then - local properties = tfmdata.properties - local factor = tonumber(value) or 1 - properties.hasitalics = true - properties.autoitalicamount = factor * (parameters.uwidth or 40)/2 - end - end -end - -otffeatures.register { - name = "itlc", - description = "italic correction", - initializers = { - base = initializeitlc, - node = initializeitlc, - } -} - --- slant and extend - -local function initializeslant(tfmdata,value) - value = tonumber(value) - if not value then - value = 0 - elseif value > 1 then - value = 1 - elseif value < -1 then - value = -1 - end - tfmdata.parameters.slantfactor = value -end - -otffeatures.register { - name = "slant", - description = "slant glyphs", - initializers = { - base = initializeslant, - node = initializeslant, - } -} - -local function initializeextend(tfmdata,value) - value = tonumber(value) - if not value then - value = 0 - elseif value > 10 then - value = 10 - elseif value < -10 then - value = -10 - end - tfmdata.parameters.extendfactor = value -end - -otffeatures.register { - name = "extend", - description = "scale glyphs horizontally", - initializers = { - base = initializeextend, - node = initializeextend, - } -} - --- expansion and protrusion - -fonts.protrusions = fonts.protrusions or { } -fonts.protrusions.setups = fonts.protrusions.setups or { } - -local setups = fonts.protrusions.setups - -local function initializeprotrusion(tfmdata,value) - if value then - local setup = setups[value] - if setup then - local factor, left, right = setup.factor or 1, setup.left or 1, setup.right or 1 - local emwidth = tfmdata.parameters.quad - tfmdata.parameters.protrusion = { - auto = true, - } - for i, chr in next, tfmdata.characters do - local v, pl, pr = setup[i], nil, nil - if v then - pl, pr = v[1], v[2] - end - if pl and pl ~= 0 then chr.left_protruding = left *pl*factor end - if pr and pr ~= 0 then chr.right_protruding = right*pr*factor end - end - end - end -end - -otffeatures.register { - name = "protrusion", - description = "shift characters into the left and or right margin", - initializers = { - base = initializeprotrusion, - node = initializeprotrusion, - } -} - -fonts.expansions = fonts.expansions or { } -fonts.expansions.setups = fonts.expansions.setups or { } - -local setups = fonts.expansions.setups - -local function initializeexpansion(tfmdata,value) - if value then - local setup = setups[value] - if setup then - local factor = setup.factor or 1 - tfmdata.parameters.expansion = { - stretch = 10 * (setup.stretch or 0), - shrink = 10 * (setup.shrink or 0), - step = 10 * (setup.step or 0), - auto = true, - } - for i, chr in next, tfmdata.characters do - local v = setup[i] - if v and v ~= 0 then - chr.expansion_factor = v*factor - else -- can be option - chr.expansion_factor = factor - end - end - end - end -end - -otffeatures.register { - name = "expansion", - description = "apply hz optimization", - initializers = { - base = initializeexpansion, - node = initializeexpansion, - } -} - --- left over - -function fonts.loggers.onetimemessage() end - --- example vectors - -local byte = string.byte - -fonts.expansions.setups['default'] = { - - stretch = 2, shrink = 2, step = .5, factor = 1, - - [byte('A')] = 0.5, [byte('B')] = 0.7, [byte('C')] = 0.7, [byte('D')] = 0.5, [byte('E')] = 0.7, - [byte('F')] = 0.7, [byte('G')] = 0.5, [byte('H')] = 0.7, [byte('K')] = 0.7, [byte('M')] = 0.7, - [byte('N')] = 0.7, [byte('O')] = 0.5, [byte('P')] = 0.7, [byte('Q')] = 0.5, [byte('R')] = 0.7, - [byte('S')] = 0.7, [byte('U')] = 0.7, [byte('W')] = 0.7, [byte('Z')] = 0.7, - [byte('a')] = 0.7, [byte('b')] = 0.7, [byte('c')] = 0.7, [byte('d')] = 0.7, [byte('e')] = 0.7, - [byte('g')] = 0.7, [byte('h')] = 0.7, [byte('k')] = 0.7, [byte('m')] = 0.7, [byte('n')] = 0.7, - [byte('o')] = 0.7, [byte('p')] = 0.7, [byte('q')] = 0.7, [byte('s')] = 0.7, [byte('u')] = 0.7, - [byte('w')] = 0.7, [byte('z')] = 0.7, - [byte('2')] = 0.7, [byte('3')] = 0.7, [byte('6')] = 0.7, [byte('8')] = 0.7, [byte('9')] = 0.7, -} - -fonts.protrusions.setups['default'] = { - - factor = 1, left = 1, right = 1, - - [0x002C] = { 0, 1 }, -- comma - [0x002E] = { 0, 1 }, -- period - [0x003A] = { 0, 1 }, -- colon - [0x003B] = { 0, 1 }, -- semicolon - [0x002D] = { 0, 1 }, -- hyphen - [0x2013] = { 0, 0.50 }, -- endash - [0x2014] = { 0, 0.33 }, -- emdash - [0x3001] = { 0, 1 }, -- ideographic comma 、 - [0x3002] = { 0, 1 }, -- ideographic full stop 。 - [0x060C] = { 0, 1 }, -- arabic comma ، - [0x061B] = { 0, 1 }, -- arabic semicolon ؛ - [0x06D4] = { 0, 1 }, -- arabic full stop ۔ - -} - --- normalizer - -fonts.handlers.otf.features.normalize = function(t) - if t.rand then - t.rand = "random" - end - return t -end - --- bonus - -function fonts.helpers.nametoslot(name) - local t = type(name) - if t == "string" then - local tfmdata = fonts.hashes.identifiers[currentfont()] - local shared = tfmdata and tfmdata.shared - local fntdata = shared and shared.rawdata - return fntdata and fntdata.resources.unicodes[name] - elseif t == "number" then - return n - end -end - --- \font\test=file:somefont:reencode=mymessup --- --- fonts.encodings.reencodings.mymessup = { --- [109] = 110, -- m --- [110] = 109, -- n --- } - -fonts.encodings = fonts.encodings or { } -local reencodings = { } -fonts.encodings.reencodings = reencodings - -local function specialreencode(tfmdata,value) - -- we forget about kerns as we assume symbols and we - -- could issue a message if ther are kerns but it's - -- a hack anyway so we odn't care too much here - local encoding = value and reencodings[value] - if encoding then - local temp = { } - local char = tfmdata.characters - for k, v in next, encoding do - temp[k] = char[v] - end - for k, v in next, temp do - char[k] = temp[k] - end - -- if we use the font otherwise luatex gets confused so - -- we return an additional hash component for fullname - return string.format("reencoded:%s",value) - end -end - -local function reencode(tfmdata,value) - tfmdata.postprocessors = tfmdata.postprocessors or { } - table.insert(tfmdata.postprocessors, - function(tfmdata) - return specialreencode(tfmdata,value) - end - ) -end - -otffeatures.register { - name = "reencode", - description = "reencode characters", - manipulators = { - base = reencode, - node = reencode, - } -} - -local function ignore(tfmdata,key,value) - if value then - tfmdata.mathparameters = nil - end -end - -otffeatures.register { - name = "ignoremathconstants", - description = "ignore math constants table", - initializers = { - base = ignore, - node = ignore, - } -} diff --git a/tex/compat/luaotfload/fontloader-fonts-syn.lua b/tex/compat/luaotfload/fontloader-fonts-syn.lua deleted file mode 100644 index 376fd05fbf5678a96e4c0d4dcd092253aeee705d..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/fontloader-fonts-syn.lua +++ /dev/null @@ -1,105 +0,0 @@ -if not modules then modules = { } end modules ['luatex-fonts-syn'] = { - version = 1.001, - comment = "companion to luatex-*.tex", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -if context then - texio.write_nl("fatal error: this module is not for context") - os.exit() -end - --- Generic font names support. --- --- Watch out, the version number is the same as the one used in --- the mtx-fonts.lua function scripts.fonts.names as we use a --- simplified font database in the plain solution and by using --- a different number we're less dependent on context. --- --- mtxrun --script font --reload --simple --- --- The format of the file is as follows: --- --- return { --- ["version"] = 1.001, --- ["cache_version"] = 1.001, --- ["mappings"] = { --- ["somettcfontone"] = { "Some TTC Font One", "SomeFontA.ttc", 1 }, --- ["somettcfonttwo"] = { "Some TTC Font Two", "SomeFontA.ttc", 2 }, --- ["somettffont"] = { "Some TTF Font", "SomeFontB.ttf" }, --- ["someotffont"] = { "Some OTF Font", "SomeFontC.otf" }, --- }, --- } - -local fonts = fonts -fonts.names = fonts.names or { } - -fonts.names.version = 1.001 -- not the same as in context but matches mtx-fonts --simple -fonts.names.basename = "luatex-fonts-names" -fonts.names.cache = containers.define("fonts","data",fonts.names.version,true) - -local data = nil -local loaded = false - -local fileformats = { "lua", "tex", "other text files" } - -function fonts.names.reportmissingbase() - texio.write("<missing font database, run: mtxrun --script fonts --reload --simple>") - fonts.names.reportmissingbase = nil -end - -function fonts.names.reportmissingname() - texio.write("<unknown font in database, run: mtxrun --script fonts --reload --simple>") - fonts.names.reportmissingname = nil -end - -function fonts.names.resolve(name,sub) - if not loaded then - local basename = fonts.names.basename - if basename and basename ~= "" then - data = containers.read(fonts.names.cache,basename) - if not data then - basename = file.addsuffix(basename,"lua") - for i=1,#fileformats do - local format = fileformats[i] - local foundname = resolvers.findfile(basename,format) or "" - if foundname ~= "" then - data = dofile(foundname) - texio.write("<font database loaded: ",foundname,">") - break - end - end - end - end - loaded = true - end - if type(data) == "table" and data.version == fonts.names.version then - local condensed = string.gsub(string.lower(name),"[^%a%d]","") - local found = data.mappings and data.mappings[condensed] - if found then - local fontname, filename, subfont = found[1], found[2], found[3] - if subfont then - return filename, fontname - else - return filename, false - end - elseif fonts.names.reportmissingname then - fonts.names.reportmissingname() - return name, false -- fallback to filename - end - elseif fonts.names.reportmissingbase then - fonts.names.reportmissingbase() - end -end - -fonts.names.resolvespec = fonts.names.resolve -- only supported in mkiv - -function fonts.names.getfilename(askedname,suffix) -- only supported in mkiv - return "" -end - -function fonts.names.ignoredfile(filename) -- only supported in mkiv - return false -- will be overloaded -end diff --git a/tex/compat/luaotfload/fontloader-fonts.lua b/tex/compat/luaotfload/fontloader-fonts.lua deleted file mode 100644 index c21389c71de508b0c3b15d8d2b5fa1a66894436f..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/fontloader-fonts.lua +++ /dev/null @@ -1,324 +0,0 @@ -if not modules then modules = { } end modules ['luatex-fonts'] = { - version = 1.001, - comment = "companion to luatex-fonts.tex", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- A merged file is generated with: --- --- mtxrun --script package --merge ./luatex-fonts.lua --- --- A needed resource file is made by: --- --- mtxrun --script context luatex-basics-prepare.tex --- --- A font (generic) database is created with: --- --- mtxrun --script font --reload --simple - --- The following code isolates the generic context code from already defined or to be defined --- namespaces. This is the reference loader for plain tex. This generic code is also used in --- luaotfload which is a low level lualatex opentype font loader but somehow has gotten a bit --- too generic name / prefix, originally set up and maintained by Khaled Hosny. Currently that --- set of derived files is maintained by a larger team lead by Philipp Gesang so when there are --- issues with this code in latex, you can best contact him. It might make sense then to first --- check if context has the same issue. We do our best to keep the interface as clean as possible. --- --- The code base is rather stable now, especially if you stay away from the non generic code. All --- relevant data is organized in tables within the main table of a font instance. There are a few --- places where in context other code is plugged in, but this does not affect the core code. Users --- can (given that their macro package provides this option) access the font data (characters, --- descriptions, properties, parameters, etc) of this main table. The documentation is part of --- context. There is also a manual for the helper libraries (maintained as part of the cld manuals). --- --- Future versions will probably have some more specific context code removed, like tracing and --- obscure hooks, so that we have a more efficient version (and less files too). So, don't depend --- too much on low level code that is meant for context as it can change without notice. We might --- also add more helper code here, but that depends to what extend metatex (sidetrack of context) --- evolves into a low level layer (depends on time, as usual). - --- The code here is the same as in context version 2015.09.11 but the rendering in context can be --- different from generic. This can be a side effect of additional callbacks, additional features --- and interferences between mechanisms between macro packages. We use the rendering in context --- and luatex-plain as reference for issues. - -utf = utf or unicode.utf8 - --- We have some (global) hooks (for latex): - -if not non_generic_context then - non_generic_context = { } -end - -if not non_generic_context.luatex_fonts then - non_generic_context.luatex_fonts = { - -- load_before = nil, - -- load_after = nil, - -- skip_loading = nil, - } -end - -if not generic_context then - generic_context = { } -end - -if not generic_context.push_namespaces then - - function generic_context.push_namespaces() - texio.write(" <push namespace>") - local normalglobal = { } - for k, v in next, _G do - normalglobal[k] = v - end - return normalglobal - end - - function generic_context.pop_namespaces(normalglobal,isolate) - if normalglobal then - texio.write(" <pop namespace>") - for k, v in next, _G do - if not normalglobal[k] then - generic_context[k] = v - if isolate then - _G[k] = nil - end - end - end - for k, v in next, normalglobal do - _G[k] = v - end - -- just to be sure: - setmetatable(generic_context,_G) - else - texio.write(" <fatal error: invalid pop of generic_context>") - os.exit() - end - end - -end - -local whatever = generic_context.push_namespaces() - --- We keep track of load time by storing the current time. That way we cannot be accused --- of slowing down loading too much. Anyhow, there is no reason for this library to perform --- slower in any other package as it does in context. --- --- Please don't update to this version without proper testing. It might be that this version --- lags behind stock context and the only formal release takes place around tex live code --- freeze. - -local starttime = os.gettimeofday() - --- As we don't use the context file searching, we need to initialize the kpse library. As the --- progname can be anything we will temporary switch to the context namespace if needed. Just --- adding the context paths to the path specification is somewhat faster. --- --- Now, with lua 5.2 being used we might create a special ENV for this. - --- kpse.set_program_name("luatex") - -local ctxkpse = nil -local verbose = true - -local function loadmodule(name,continue) - local foundname = kpse.find_file(name,"tex") or "" - if not foundname then - if not ctxkpse then - ctxkpse = kpse.new("luatex","context") - end - foundname = ctxkpse:find_file(name,"tex") or "" - end - if foundname == "" then - if not continue then - texio.write_nl(string.format(" <luatex-fonts: unable to locate %s>",name)) - os.exit() - end - else - if verbose then - texio.write(string.format(" <%s>",foundname)) -- no file.basename yet - end - dofile(foundname) - end -end - -if non_generic_context.luatex_fonts.load_before then - loadmodule(non_generic_context.luatex_fonts.load_before,true) -end - -if non_generic_context.luatex_fonts.skip_loading ~= true then - - loadmodule('luatex-fonts-merged.lua',true) - - if fonts then - - if not fonts._merge_loaded_message_done_ then - texio.write_nl("log", "!") - texio.write_nl("log", "! I am using the merged version of 'luatex-fonts.lua' here. If") - texio.write_nl("log", "! you run into problems or experience unexpected behaviour, and") - texio.write_nl("log", "! if you have ConTeXt installed you can try to delete the file") - texio.write_nl("log", "! 'luatex-font-merged.lua' as I might then use the possibly") - texio.write_nl("log", "! updated libraries. The merged version is not supported as it") - texio.write_nl("log", "! is a frozen instance. Problems can be reported to the ConTeXt") - texio.write_nl("log", "! mailing list.") - texio.write_nl("log", "!") - end - - fonts._merge_loaded_message_done_ = true - - else - - -- The following helpers are a bit overkill but I don't want to mess up context code for the - -- sake of general generality. Around version 1.0 there will be an official api defined. - -- - -- So, I will strip these libraries and see what is really needed so that we don't have this - -- overhead in the generic modules. The next section is only there for the packager, so stick - -- to using luatex-fonts with luatex-fonts-merged.lua and forget about the rest. The following - -- list might change without prior notice (for instance because we shuffled code around). - - loadmodule("l-lua.lua") - loadmodule("l-lpeg.lua") - loadmodule("l-function.lua") - loadmodule("l-string.lua") - loadmodule("l-table.lua") - loadmodule("l-io.lua") - loadmodule("l-file.lua") - loadmodule("l-boolean.lua") - loadmodule("l-math.lua") - loadmodule("l-unicode.lua") - - -- A few slightly higher level support modules: - - loadmodule("util-str.lua") - loadmodule("util-fil.lua") - - -- The following modules contain code that is either not used at all outside context or will - -- fail when enabled due to lack of other modules. - - -- First we load a few helper modules. This is about the miminum needed to let the font modules - -- do their work. Don't depend on their functions as we might strip them in future versions of - -- this generic variant. - - loadmodule('luatex-basics-gen.lua') - loadmodule('data-con.lua') - - -- We do need some basic node support. The code in there is not for general use as it might - -- change. - - loadmodule('luatex-basics-nod.lua') - - -- We ship a resources needed for font handling (more might end up here). - - loadmodule('luatex-basics-chr.lua') - - -- Now come the font modules that deal with traditional tex fonts as well as open type fonts. - -- - -- The font database file (if used at all) must be put someplace visible for kpse and is not - -- shared with context. The mtx-fonts script can be used to generate this file (using the - -- --reload --force --simple option). - - loadmodule('font-ini.lua') - loadmodule('font-con.lua') - loadmodule('luatex-fonts-enc.lua') -- will load font-age on demand - loadmodule('font-cid.lua') - loadmodule('font-map.lua') -- for loading lum file (will be stripped) - - -- We use a bit simpler database because using the context one demands loading more helper - -- code and although it is more flexible (more wauys to resolve and so) it will never be - -- uses in plain/latex anyway, so let's stick to a simple approach. - - loadmodule('luatex-fonts-syn.lua') - - loadmodule('font-oti.lua') - - -- These are the old loader and processing modules. These use the built-in font loader and - -- will stay around (but not be extended), only fixed. - - -- font-otf.lua - -- font-otb.lua - -- font-inj.lua - -- font-ota.lua - -- font-otn.lua - -- font-otp.lua - - -- Here come the new loader and processing modules. The loader is written in Lua and although - -- initial loading is somewhat slower, identifying is faster, cached files can be slightly - -- more efficient, and processing is somewhat faster (only measureable on complex fonts). - - loadmodule('font-otr.lua') - loadmodule('font-cff.lua') - loadmodule('font-ttf.lua') - loadmodule('font-dsp.lua') - loadmodule('font-oup.lua') - loadmodule('font-otl.lua') - loadmodule('font-oto.lua') - loadmodule('font-otj.lua') - loadmodule('font-ota.lua') - loadmodule('font-ots.lua') - loadmodule('font-osd.lua') - loadmodule('font-ocl.lua') -- svg needs 0.97 (for fix in memstreams) - - loadmodule('font-otc.lua') - - -- type one code - - loadmodule('font-onr.lua') -- was font-afm.lua - loadmodule('font-one.lua') -- was font-afm.lua - loadmodule('font-afk.lua') - - -- traditional code - - loadmodule('font-tfm.lua') - - -- common code - - loadmodule('font-lua.lua') - loadmodule('font-def.lua') - loadmodule('font-xtx.lua') -- xetex compatible specifiers (plain/latex only) - loadmodule('luatex-fonts-ext.lua') -- some extensions - - -- We need to plug into a callback and the following module implements the handlers. Actual - -- plugging in happens later. - - loadmodule('font-gbn.lua') - - end - -end - -if non_generic_context.luatex_fonts.load_after then - loadmodule(non_generic_context.luatex_fonts.load_after,true) -end - -resolvers.loadmodule = loadmodule - --- In order to deal with the fonts we need to initialize some callbacks. One can overload them later --- on if needed. First a bit of abstraction. - -generic_context.callback_ligaturing = false -generic_context.callback_kerning = false -generic_context.callback_pre_linebreak_filter = nodes.simple_font_handler -generic_context.callback_hpack_filter = nodes.simple_font_handler -generic_context.callback_define_font = fonts.definers.read - --- The next ones can be done at a different moment if needed. You can create a generic_context namespace --- and set no_callbacks_yet to true, load this module, and enable the callbacks later. So, there is really --- *no* need to create a alternative for luatex-fonts.lua and luatex-fonts-merged.lua: just load this one --- and overload if needed. - -if not generic_context.no_callbacks_yet then - - callback.register('ligaturing', generic_context.callback_ligaturing) - callback.register('kerning', generic_context.callback_kerning) - callback.register('pre_linebreak_filter', generic_context.callback_pre_linebreak_filter) - callback.register('hpack_filter', generic_context.callback_hpack_filter) - callback.register('define_font' , generic_context.callback_define_font) - -end - --- We're done. - -texio.write(string.format(" <luatex-fonts.lua loaded in %0.3f seconds>", os.gettimeofday()-starttime)) - -generic_context.pop_namespaces(whatever) diff --git a/tex/compat/luaotfload/fontloader-fonts.tex b/tex/compat/luaotfload/fontloader-fonts.tex deleted file mode 100644 index 7b457e9b4fcdf087cb1219b7ab42e05e923ff9c0..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/fontloader-fonts.tex +++ /dev/null @@ -1,140 +0,0 @@ -%D \module -%D [ file=luatex-fonts, -%D version=2009.12.01, -%D title=\LUATEX\ Support Macros, -%D subtitle=Generic \OPENTYPE\ Font Handler, -%D author=Hans Hagen, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] - -%D \subject{Welcome} -%D -%D This file is one of a set of basic functionality enhancements -%D for \LUATEX\ derived from the \CONTEXT\ \MKIV\ code base. Please -%D don't polute the \type {luatex-*} namespace with code not coming -%D from the \CONTEXT\ development team as we may add more files. -%D -%D As this is an experimental setup, it might not always work out as -%D expected. Around \LUATEX\ version 0.50 we expect the code to be -%D more or less okay. -%D -%D This file implements a basic font system for a bare \LUATEX\ -%D system. By default \LUATEX\ only knows about the classic \TFM\ -%D fonts but it can read other font formats and pass them to \LUA. -%D With some glue code one can then construct a suitable \TFM\ -%D representation that \LUATEX\ can work with. For more advanced font -%D support a bit more code is needed that needs to be hooked -%D into the callback mechanism. -%D -%D This file is currently rather simple: it just loads the \LUA\ file -%D with the same name. An example of a \type {luatex.tex} file that is -%D just plain \TEX: -%D -%D \starttyping -%D \catcode`\{=1 % left brace is begin-group character -%D \catcode`\}=2 % right brace is end-group character -%D -%D \input plain -%D -%D \everyjob\expandafter{\the\everyjob\input luatex-fonts\relax} -%D -%D \dump -%D \stoptyping -%D -%D We could load the \LUA\ file in \type {\everyjob} but maybe some -%D day we need more here. -%D -%D When defining a font you can use two prefixes. A \type {file:} -%D prefix forced a file search, while a \type {name:} prefix will -%D result in consulting the names database. Such a database can be -%D generated with: -%D -%D \starttyping -%D mtxrun --usekpse --script fonts --names -%D \stoptyping -%D -%D This will generate a file \type {luatex-fonts-names.lua} that has -%D to be placed in a location where it can be found by \KPSE. Beware: -%D the \type {--kpseonly} flag is only used outside \CONTEXT\ and -%D provides very limited functionality, just enough for this task. -%D -%D The code loaded here does not come out of thin air, but is mostly -%D shared with \CONTEXT, however, in that macropackage we go beyond -%D what is provided here. When you use the code packaged here you -%D need to keep a few things in mind: -%D -%D \startitemize -%D -%D \item This subsystem will be extended, improved etc. in about the -%D same pace as \CONTEXT\ \MKIV. However, because \CONTEXT\ provides a -%D rather high level of integration not all features will be supported -%D in the same quality. Use \CONTEXT\ if you want more goodies. -%D -%D \item There is no official \API\ yet, which means that using -%D functions implemented here is at your own risk, in the sense that -%D names and namespaces might change. There will be a minimal \API\ -%D defined once \LUATEX\ version 1.0 is out. Instead of patching the -%D files it's better to overload functions if needed. -%D -%D \item The modules are not stripped too much, which makes it -%D possible to benefit from improvements in the code that take place -%D in the perspective of \CONTEXT\ development. They might be split a -%D bit more in due time so the baseline might become smaller. -%D -%D \item The code is maintained and tested by the \CONTEXT\ -%D development team. As such it might be better suited for this macro -%D package and integration in other systems might demand some -%D additional wrapping. Problems can be reported to the team but as we -%D use \CONTEXT\ \MKIV\ as baseline, you'd better check if the problem -%D is a general \CONTEXT\ problem too. -%D -%D \item The more high level support for features that is provided in -%D \CONTEXT\ is not part of the code loaded here as it makes no sense -%D elsewhere. Some experimental features are not part of this code -%D either but some might show up later. -%D -%D \item Math font support will be added but only in its basic form -%D once that the Latin Modern and \TEX\ Gyre math fonts are -%D available. -%D -%D \item At this moment the more nifty speed-ups are not enabled -%D because they work in tandem with the alternative file handling -%D that \CONTEXT\ uses. Maybe around \LUATEX\ 1.0 we will bring some -%D speedup into this code too (if it pays off at all). -%D -%D \item The code defines a few global tables. If this code is used -%D in a larger perspective then you can best make sure that no -%D conflicts occur. The \CONTEXT\ package expects users to work in -%D their own namespace (\type {userdata}, \type {thirddata}, \type -%D {moduledata} or \type {document}. The team takes all freedom to -%D use any table at the global level but will not use tables that are -%D named after macro packages. Later the \CONTEXT\ might operate in -%D a more controlled namespace but it has a low priority. -%D -%D \item There is some tracing code present but this is not enabled -%D and not supported outside \CONTEXT\ either as it integrates quite -%D tightly into \CONTEXT. In case of problems you can use \CONTEXT\ -%D for tracking down problems. -%D -%D \item Patching the code in distributions is dangerous as it might -%D fix your problem but introduce new ones for \CONTEXT. So, best keep -%D the original code as it is. -%D -%D \item Attributes are (automatically) taken from the range 127-255 so -%D you'd best not use these yourself. -%D -%D \stopitemize -%D -%D If this all sounds a bit tricky, keep in mind that it makes no sense -%D for us to maintain multiple code bases and we happen to use \CONTEXT. -%D -%D For more details about how the font subsystem works we refer to -%D publications in \TEX\ related journals, the \CONTEXT\ documentation, -%D and the \CONTEXT\ wiki. - -\directlua { - if not fonts then - dofile(kpse.find_file("luatex-fonts.lua","tex")) - end -} - -\endinput diff --git a/tex/compat/luaotfload/fontloader-l-boolean.lua b/tex/compat/luaotfload/fontloader-l-boolean.lua deleted file mode 100644 index 8f18d4c003df76648cb8870d8d46127c3edd942c..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/fontloader-l-boolean.lua +++ /dev/null @@ -1,69 +0,0 @@ -if not modules then modules = { } end modules ['l-boolean'] = { - version = 1.001, - comment = "companion to luat-lib.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -local type, tonumber = type, tonumber - -boolean = boolean or { } -local boolean = boolean - -function boolean.tonumber(b) - if b then return 1 else return 0 end -- test and return or return -end - -function toboolean(str,tolerant) -- global - if str == nil then - return false - elseif str == false then - return false - elseif str == true then - return true - elseif str == "true" then - return true - elseif str == "false" then - return false - elseif not tolerant then - return false - elseif str == 0 then - return false - elseif (tonumber(str) or 0) > 0 then - return true - else - return str == "yes" or str == "on" or str == "t" - end -end - -string.toboolean = toboolean - -function string.booleanstring(str) - if str == "0" then - return false - elseif str == "1" then - return true - elseif str == "" then - return false - elseif str == "false" then - return false - elseif str == "true" then - return true - elseif (tonumber(str) or 0) > 0 then - return true - else - return str == "yes" or str == "on" or str == "t" - end -end - -function string.is_boolean(str,default,strict) - if type(str) == "string" then - if str == "true" or str == "yes" or str == "on" or str == "t" or (not strict and str == "1") then - return true - elseif str == "false" or str == "no" or str == "off" or str == "f" or (not strict and str == "0") then - return false - end - end - return default -end diff --git a/tex/compat/luaotfload/fontloader-l-file.lua b/tex/compat/luaotfload/fontloader-l-file.lua deleted file mode 100644 index f2a27ad1832d4ce16c60882ca8ef42d86364e7c7..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/fontloader-l-file.lua +++ /dev/null @@ -1,701 +0,0 @@ -if not modules then modules = { } end modules ['l-file'] = { - version = 1.001, - comment = "companion to luat-lib.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- needs a cleanup - -file = file or { } -local file = file - -if not lfs then - lfs = optionalrequire("lfs") -end - --- -- see later --- --- if not lfs then --- --- lfs = { --- getcurrentdir = function() --- return "." --- end, --- attributes = function() --- return nil --- end, --- isfile = function(name) --- local f = io.open(name,'rb') --- if f then --- f:close() --- return true --- end --- end, --- isdir = function(name) --- print("you need to load lfs") --- return false --- end --- } --- --- elseif not lfs.isfile then --- --- local attributes = lfs.attributes --- --- function lfs.isdir(name) --- return attributes(name,"mode") == "directory" --- end --- --- function lfs.isfile(name) --- return attributes(name,"mode") == "file" --- end --- --- -- function lfs.isdir(name) --- -- local a = attributes(name) --- -- return a and a.mode == "directory" --- -- end --- --- -- function lfs.isfile(name) --- -- local a = attributes(name) --- -- return a and a.mode == "file" --- -- end --- --- end - -local insert, concat = table.insert, table.concat -local match, find, gmatch = string.match, string.find, string.gmatch -local lpegmatch = lpeg.match -local getcurrentdir, attributes = lfs.currentdir, lfs.attributes -local checkedsplit = string.checkedsplit - --- local patterns = file.patterns or { } --- file.patterns = patterns - -local P, R, S, C, Cs, Cp, Cc, Ct = lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.Cs, lpeg.Cp, lpeg.Cc, lpeg.Ct - --- better this way: - -local tricky = S("/\\") * P(-1) -local attributes = lfs.attributes - -if sandbox then - sandbox.redefine(lfs.isfile,"lfs.isfile") - sandbox.redefine(lfs.isdir, "lfs.isdir") -end - -function lfs.isdir(name) - if lpegmatch(tricky,name) then - return attributes(name,"mode") == "directory" - else - return attributes(name.."/.","mode") == "directory" - end -end - -function lfs.isfile(name) - return attributes(name,"mode") == "file" -end - -local colon = P(":") -local period = P(".") -local periods = P("..") -local fwslash = P("/") -local bwslash = P("\\") -local slashes = S("\\/") -local noperiod = 1-period -local noslashes = 1-slashes -local name = noperiod^1 -local suffix = period/"" * (1-period-slashes)^1 * -1 - ------ pattern = C((noslashes^0 * slashes^1)^1) -local pattern = C((1 - (slashes^1 * noslashes^1 * -1))^1) * P(1) -- there must be a more efficient way - -local function pathpart(name,default) - return name and lpegmatch(pattern,name) or default or "" -end - -local pattern = (noslashes^0 * slashes)^1 * C(noslashes^1) * -1 - -local function basename(name) - return name and lpegmatch(pattern,name) or name -end - --- print(pathpart("file")) --- print(pathpart("dir/file")) --- print(pathpart("/dir/file")) --- print(basename("file")) --- print(basename("dir/file")) --- print(basename("/dir/file")) - -local pattern = (noslashes^0 * slashes^1)^0 * Cs((1-suffix)^1) * suffix^0 - -local function nameonly(name) - return name and lpegmatch(pattern,name) or name -end - -local pattern = (noslashes^0 * slashes)^0 * (noperiod^1 * period)^1 * C(noperiod^1) * -1 - -local function suffixonly(name) - return name and lpegmatch(pattern,name) or "" -end - -local pattern = (noslashes^0 * slashes)^0 * noperiod^1 * ((period * C(noperiod^1))^1) * -1 + Cc("") - -local function suffixesonly(name) - if name then - return lpegmatch(pattern,name) - else - return "" - end -end - -file.pathpart = pathpart -file.basename = basename -file.nameonly = nameonly -file.suffixonly = suffixonly -file.suffix = suffixonly -file.suffixesonly = suffixesonly -file.suffixes = suffixesonly - -file.dirname = pathpart -- obsolete -file.extname = suffixonly -- obsolete - --- actually these are schemes - -local drive = C(R("az","AZ")) * colon -local path = C((noslashes^0 * slashes)^0) -local suffix = period * C(P(1-period)^0 * P(-1)) -local base = C((1-suffix)^0) -local rest = C(P(1)^0) - -drive = drive + Cc("") -path = path + Cc("") -base = base + Cc("") -suffix = suffix + Cc("") - -local pattern_a = drive * path * base * suffix -local pattern_b = path * base * suffix -local pattern_c = C(drive * path) * C(base * suffix) -- trick: two extra captures -local pattern_d = path * rest - -function file.splitname(str,splitdrive) - if not str then - -- error - elseif splitdrive then - return lpegmatch(pattern_a,str) -- returns drive, path, base, suffix - else - return lpegmatch(pattern_b,str) -- returns path, base, suffix - end -end - -function file.splitbase(str) - if str then - return lpegmatch(pattern_d,str) -- returns path, base+suffix (path has / appended, might change at some point) - else - return "", str -- assume no path - end -end - ----- stripslash = C((1 - P("/")^1*P(-1))^0) - -function file.nametotable(str,splitdrive) - if str then - local path, drive, subpath, name, base, suffix = lpegmatch(pattern_c,str) - -- if path ~= "" then - -- path = lpegmatch(stripslash,path) -- unfortunate hack, maybe this becomes default - -- end - if splitdrive then - return { - path = path, - drive = drive, - subpath = subpath, - name = name, - base = base, - suffix = suffix, - } - else - return { - path = path, - name = name, - base = base, - suffix = suffix, - } - end - end -end - --- print(file.splitname("file")) --- print(file.splitname("dir/file")) --- print(file.splitname("/dir/file")) --- print(file.splitname("file")) --- print(file.splitname("dir/file")) --- print(file.splitname("/dir/file")) - --- inspect(file.nametotable("file.ext")) --- inspect(file.nametotable("dir/file.ext")) --- inspect(file.nametotable("/dir/file.ext")) --- inspect(file.nametotable("file.ext")) --- inspect(file.nametotable("dir/file.ext")) --- inspect(file.nametotable("/dir/file.ext")) - ------ pattern = Cs(((period * noperiod^1 * -1) / "" + 1)^1) -local pattern = Cs(((period * (1-period-slashes)^1 * -1) / "" + 1)^1) - -function file.removesuffix(name) - return name and lpegmatch(pattern,name) -end - --- local pattern = (noslashes^0 * slashes)^0 * (noperiod^1 * period)^1 * Cp() * noperiod^1 * -1 --- --- function file.addsuffix(name, suffix) --- local p = lpegmatch(pattern,name) --- if p then --- return name --- else --- return name .. "." .. suffix --- end --- end - -local suffix = period/"" * (1-period-slashes)^1 * -1 -local pattern = Cs((noslashes^0 * slashes^1)^0 * ((1-suffix)^1)) * Cs(suffix) - -function file.addsuffix(filename,suffix,criterium) - if not filename or not suffix or suffix == "" then - return filename - elseif criterium == true then - return filename .. "." .. suffix - elseif not criterium then - local n, s = lpegmatch(pattern,filename) - if not s or s == "" then - return filename .. "." .. suffix - else - return filename - end - else - local n, s = lpegmatch(pattern,filename) - if s and s ~= "" then - local t = type(criterium) - if t == "table" then - -- keep if in criterium - for i=1,#criterium do - if s == criterium[i] then - return filename - end - end - elseif t == "string" then - -- keep if criterium - if s == criterium then - return filename - end - end - end - return (n or filename) .. "." .. suffix - end -end - --- print("1 " .. file.addsuffix("name","new") .. " -> name.new") --- print("2 " .. file.addsuffix("name.old","new") .. " -> name.old") --- print("3 " .. file.addsuffix("name.old","new",true) .. " -> name.old.new") --- print("4 " .. file.addsuffix("name.old","new","new") .. " -> name.new") --- print("5 " .. file.addsuffix("name.old","new","old") .. " -> name.old") --- print("6 " .. file.addsuffix("name.old","new","foo") .. " -> name.new") --- print("7 " .. file.addsuffix("name.old","new",{"foo","bar"}) .. " -> name.new") --- print("8 " .. file.addsuffix("name.old","new",{"old","bar"}) .. " -> name.old") - -local suffix = period * (1-period-slashes)^1 * -1 -local pattern = Cs((1-suffix)^0) - -function file.replacesuffix(name,suffix) - if name and suffix and suffix ~= "" then - return lpegmatch(pattern,name) .. "." .. suffix - else - return name - end -end - --- - -local reslasher = lpeg.replacer(P("\\"),"/") - -function file.reslash(str) - return str and lpegmatch(reslasher,str) -end - --- We should be able to use: --- --- local writable = P(1) * P("w") * Cc(true) --- --- function file.is_writable(name) --- local a = attributes(name) or attributes(pathpart(name,".")) --- return a and lpegmatch(writable,a.permissions) or false --- end --- --- But after some testing Taco and I came up with the more robust --- variant: - -function file.is_writable(name) - if not name then - -- error - elseif lfs.isdir(name) then - name = name .. "/m_t_x_t_e_s_t.tmp" - local f = io.open(name,"wb") - if f then - f:close() - os.remove(name) - return true - end - elseif lfs.isfile(name) then - local f = io.open(name,"ab") - if f then - f:close() - return true - end - else - local f = io.open(name,"ab") - if f then - f:close() - os.remove(name) - return true - end - end - return false -end - -local readable = P("r") * Cc(true) - -function file.is_readable(name) - if name then - local a = attributes(name) - return a and lpegmatch(readable,a.permissions) or false - else - return false - end -end - -file.isreadable = file.is_readable -- depricated -file.iswritable = file.is_writable -- depricated - -function file.size(name) - if name then - local a = attributes(name) - return a and a.size or 0 - else - return 0 - end -end - -function file.splitpath(str,separator) -- string .. reslash is a bonus (we could do a direct split) - return str and checkedsplit(lpegmatch(reslasher,str),separator or io.pathseparator) -end - -function file.joinpath(tab,separator) -- table - return tab and concat(tab,separator or io.pathseparator) -- can have trailing // -end - -local someslash = S("\\/") -local stripper = Cs(P(fwslash)^0/"" * reslasher) -local isnetwork = someslash * someslash * (1-someslash) - + (1-fwslash-colon)^1 * colon -local isroot = fwslash^1 * -1 -local hasroot = fwslash^1 - -local reslasher = lpeg.replacer(S("\\/"),"/") -local deslasher = lpeg.replacer(S("\\/")^1,"/") - --- If we have a network or prefix then there is a change that we end up with two --- // in the middle ... we could prevent this if we (1) expand prefixes: and (2) --- split and rebuild as url. Of course we could assume no network paths (which --- makes sense) adn assume either mapped drives (windows) or mounts (unix) but --- then we still have to deal with urls ... anyhow, multiple // are never a real --- problem but just ugly. - --- function file.join(...) --- local lst = { ... } --- local one = lst[1] --- if lpegmatch(isnetwork,one) then --- local one = lpegmatch(reslasher,one) --- local two = lpegmatch(deslasher,concat(lst,"/",2)) --- if lpegmatch(hasroot,two) then --- return one .. two --- else --- return one .. "/" .. two --- end --- elseif lpegmatch(isroot,one) then --- local two = lpegmatch(deslasher,concat(lst,"/",2)) --- if lpegmatch(hasroot,two) then --- return two --- else --- return "/" .. two --- end --- elseif one == "" then --- return lpegmatch(stripper,concat(lst,"/",2)) --- else --- return lpegmatch(deslasher,concat(lst,"/")) --- end --- end - -function file.join(one, two, three, ...) - if not two then - return one == "" and one or lpegmatch(reslasher,one) - end - if one == "" then - return lpegmatch(stripper,three and concat({ two, three, ... },"/") or two) - end - if lpegmatch(isnetwork,one) then - local one = lpegmatch(reslasher,one) - local two = lpegmatch(deslasher,three and concat({ two, three, ... },"/") or two) - if lpegmatch(hasroot,two) then - return one .. two - else - return one .. "/" .. two - end - elseif lpegmatch(isroot,one) then - local two = lpegmatch(deslasher,three and concat({ two, three, ... },"/") or two) - if lpegmatch(hasroot,two) then - return two - else - return "/" .. two - end - else - return lpegmatch(deslasher,concat({ one, two, three, ... },"/")) - end -end - --- or we can use this: --- --- function file.join(...) --- local n = select("#",...) --- local one = select(1,...) --- if n == 1 then --- return one == "" and one or lpegmatch(stripper,one) --- end --- if one == "" then --- return lpegmatch(stripper,n > 2 and concat({ ... },"/",2) or select(2,...)) --- end --- if lpegmatch(isnetwork,one) then --- local one = lpegmatch(reslasher,one) --- local two = lpegmatch(deslasher,n > 2 and concat({ ... },"/",2) or select(2,...)) --- if lpegmatch(hasroot,two) then --- return one .. two --- else --- return one .. "/" .. two --- end --- elseif lpegmatch(isroot,one) then --- local two = lpegmatch(deslasher,n > 2 and concat({ ... },"/",2) or select(2,...)) --- if lpegmatch(hasroot,two) then --- return two --- else --- return "/" .. two --- end --- else --- return lpegmatch(deslasher,concat({ ... },"/")) --- end --- end - --- print(file.join("c:/whatever")) --- print(file.join("c:/whatever","name")) --- print(file.join("//","/y")) --- print(file.join("/","/y")) --- print(file.join("","/y")) --- print(file.join("/x/","/y")) --- print(file.join("x/","/y")) --- print(file.join("http://","/y")) --- print(file.join("http://a","/y")) --- print(file.join("http:///a","/y")) --- print(file.join("//nas-1","/y")) --- print(file.join("//nas-1/a/b/c","/y")) --- print(file.join("\\\\nas-1\\a\\b\\c","\\y")) - --- The previous one fails on "a.b/c" so Taco came up with a split based --- variant. After some skyping we got it sort of compatible with the old --- one. After that the anchoring to currentdir was added in a better way. --- Of course there are some optimizations too. Finally we had to deal with --- windows drive prefixes and things like sys://. Eventually gsubs and --- finds were replaced by lpegs. - -local drivespec = R("az","AZ")^1 * colon -local anchors = fwslash - + drivespec -local untouched = periods - + (1-period)^1 * P(-1) -local mswindrive = Cs(drivespec * (bwslash/"/" + fwslash)^0) -local mswinuncpath = (bwslash + fwslash) * (bwslash + fwslash) * Cc("//") -local splitstarter = (mswindrive + mswinuncpath + Cc(false)) - * Ct(lpeg.splitat(S("/\\")^1)) -local absolute = fwslash - -function file.collapsepath(str,anchor) -- anchor: false|nil, true, "." - if not str then - return - end - if anchor == true and not lpegmatch(anchors,str) then - str = getcurrentdir() .. "/" .. str - end - if str == "" or str =="." then - return "." - elseif lpegmatch(untouched,str) then - return lpegmatch(reslasher,str) - end - local starter, oldelements = lpegmatch(splitstarter,str) - local newelements = { } - local i = #oldelements - while i > 0 do - local element = oldelements[i] - if element == '.' then - -- do nothing - elseif element == '..' then - local n = i - 1 - while n > 0 do - local element = oldelements[n] - if element ~= '..' and element ~= '.' then - oldelements[n] = '.' - break - else - n = n - 1 - end - end - if n < 1 then - insert(newelements,1,'..') - end - elseif element ~= "" then - insert(newelements,1,element) - end - i = i - 1 - end - if #newelements == 0 then - return starter or "." - elseif starter then - return starter .. concat(newelements, '/') - elseif lpegmatch(absolute,str) then - return "/" .. concat(newelements,'/') - else - newelements = concat(newelements, '/') - if anchor == "." and find(str,"^%./") then - return "./" .. newelements - else - return newelements - end - end -end - --- local function test(str,...) --- print(string.format("%-20s %-15s %-30s %-20s",str,file.collapsepath(str),file.collapsepath(str,true),file.collapsepath(str,"."))) --- end --- test("a/b.c/d") test("b.c/d") test("b.c/..") --- test("/") test("c:/..") test("sys://..") --- test("") test("./") test(".") test("..") test("./..") test("../..") --- test("a") test("./a") test("/a") test("a/../..") --- test("a/./b/..") test("a/aa/../b/bb") test("a/.././././b/..") test("a/./././b/..") --- test("a/b/c/../..") test("./a/b/c/../..") test("a/b/c/../..") --- test("./a") --- test([[\\a.b.c\d\e]]) - -local validchars = R("az","09","AZ","--","..") -local pattern_a = lpeg.replacer(1-validchars) -local pattern_a = Cs((validchars + P(1)/"-")^1) -local whatever = P("-")^0 / "" -local pattern_b = Cs(whatever * (1 - whatever * -1)^1) - -function file.robustname(str,strict) - if str then - str = lpegmatch(pattern_a,str) or str - if strict then - return lpegmatch(pattern_b,str) or str -- two step is cleaner (less backtracking) - else - return str - end - end -end - -local loaddata = io.loaddata -local savedata = io.savedata - -file.readdata = loaddata -file.savedata = savedata - -function file.copy(oldname,newname) - if oldname and newname then - local data = loaddata(oldname) - if data and data ~= "" then - savedata(newname,data) - end - end -end - --- also rewrite previous - -local letter = R("az","AZ") + S("_-+") -local separator = P("://") - -local qualified = period^0 * fwslash - + letter * colon - + letter^1 * separator - + letter^1 * fwslash -local rootbased = fwslash - + letter * colon - -lpeg.patterns.qualified = qualified -lpeg.patterns.rootbased = rootbased - --- ./name ../name /name c: :// name/name - -function file.is_qualified_path(filename) - return filename and lpegmatch(qualified,filename) ~= nil -end - -function file.is_rootbased_path(filename) - return filename and lpegmatch(rootbased,filename) ~= nil -end - --- function test(t) for k, v in next, t do print(v, "=>", file.splitname(v)) end end --- --- test { "c:", "c:/aa", "c:/aa/bb", "c:/aa/bb/cc", "c:/aa/bb/cc.dd", "c:/aa/bb/cc.dd.ee" } --- test { "c:", "c:aa", "c:aa/bb", "c:aa/bb/cc", "c:aa/bb/cc.dd", "c:aa/bb/cc.dd.ee" } --- test { "/aa", "/aa/bb", "/aa/bb/cc", "/aa/bb/cc.dd", "/aa/bb/cc.dd.ee" } --- test { "aa", "aa/bb", "aa/bb/cc", "aa/bb/cc.dd", "aa/bb/cc.dd.ee" } - --- -- maybe: --- --- if os.type == "windows" then --- local currentdir = getcurrentdir --- function getcurrentdir() --- return lpegmatch(reslasher,currentdir()) --- end --- end - --- for myself: - -function file.strip(name,dir) - if name then - local b, a = match(name,"^(.-)" .. dir .. "(.*)$") - return a ~= "" and a or name - end -end - --- local debuglist = { --- "pathpart", "basename", "nameonly", "suffixonly", "suffix", "dirname", "extname", --- "addsuffix", "removesuffix", "replacesuffix", "join", --- "strip","collapsepath", "joinpath", "splitpath", --- } - --- for i=1,#debuglist do --- local name = debuglist[i] --- local f = file[name] --- file[name] = function(...) --- print(name,f(...)) --- return f(...) --- end --- end - --- a goodie: a dumb version of mkdirs (not used in context itself, only --- in generic usage) - -function lfs.mkdirs(path) - local full = "" - for sub in gmatch(path,"(/*[^\\/]+)") do -- accepts leading c: and / - full = full .. sub - -- lfs.isdir("/foo") mistakenly returns true on windows so - -- so we don't test and just make as that one is not too picky - lfs.mkdir(full) - end -end diff --git a/tex/compat/luaotfload/fontloader-l-function.lua b/tex/compat/luaotfload/fontloader-l-function.lua deleted file mode 100644 index 7ded8ceecd5c61e66e7beca0474a17a2781666ad..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/fontloader-l-function.lua +++ /dev/null @@ -1,11 +0,0 @@ -if not modules then modules = { } end modules ['l-functions'] = { - version = 1.001, - comment = "companion to luat-lib.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -functions = functions or { } - -function functions.dummy() end diff --git a/tex/compat/luaotfload/fontloader-l-io.lua b/tex/compat/luaotfload/fontloader-l-io.lua deleted file mode 100644 index 2039017b25da5f62d02c26349a555bcff0019d6c..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/fontloader-l-io.lua +++ /dev/null @@ -1,407 +0,0 @@ -if not modules then modules = { } end modules ['l-io'] = { - version = 1.001, - comment = "companion to luat-lib.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -local io = io -local open, flush, write, read = io.open, io.flush, io.write, io.read -local byte, find, gsub, format = string.byte, string.find, string.gsub, string.format -local concat = table.concat -local floor = math.floor -local type = type - -if string.find(os.getenv("PATH"),";",1,true) then - io.fileseparator, io.pathseparator = "\\", ";" -else - io.fileseparator, io.pathseparator = "/" , ":" -end - -local function readall(f) - return f:read("*all") -end - --- The next one is upto 50% faster on large files and less memory consumption due --- to less intermediate large allocations. This phenomena was discussed on the --- luatex dev list. - -local function readall(f) - local size = f:seek("end") - if size == 0 then - return "" - end - f:seek("set",0) - if size < 1024*1024 then - return f:read('*all') - else - local step - if size > 16*1024*1024 then - step = 16*1024*1024 - else - step = floor(size/(1024*1024)) * 1024 * 1024 / 8 - end - local data = { } - while true do - local r = f:read(step) - if not r then - return concat(data) - else - data[#data+1] = r - end - end - end -end - -io.readall = readall - -function io.loaddata(filename,textmode) -- return nil if empty - local f = open(filename,(textmode and 'r') or 'rb') - if f then - local data = readall(f) - f:close() - if #data > 0 then - return data - end - end -end - -function io.copydata(source,target,action) - local f = open(source,"rb") - if f then - local g = open(target,"wb") - if g then - local size = f:seek("end") - if size == 0 then - -- empty - else - f:seek("set",0) - if size < 1024*1024 then - local data = f:read('*all') - if action then - data = action(data) - end - if data then - g:write(data) - end - else - local step - if size > 16*1024*1024 then - step = 16*1024*1024 - else - step = floor(size/(1024*1024)) * 1024 * 1024 / 8 - end - while true do - local data = f:read(step) - if data then - if action then - data = action(data) - end - if data then - g:write(data) - end - else - break - end - end - end - end - g:close() - end - f:close() - flush() - end -end - -function io.savedata(filename,data,joiner) - local f = open(filename,"wb") - if f then - if type(data) == "table" then - f:write(concat(data,joiner or "")) - elseif type(data) == "function" then - data(f) - else - f:write(data or "") - end - f:close() - flush() - return true - else - return false - end -end - --- we can also chunk this one if needed: io.lines(filename,chunksize,"*l") - -function io.loadlines(filename,n) -- return nil if empty - local f = open(filename,'r') - if not f then - -- no file - elseif n then - local lines = { } - for i=1,n do - local line = f:read("*lines") - if line then - lines[#lines+1] = line - else - break - end - end - f:close() - lines = concat(lines,"\n") - if #lines > 0 then - return lines - end - else - local line = f:read("*line") or "" - f:close() - if #line > 0 then - return line - end - end -end - -function io.loadchunk(filename,n) - local f = open(filename,'rb') - if f then - local data = f:read(n or 1024) - f:close() - if #data > 0 then - return data - end - end -end - -function io.exists(filename) - local f = open(filename) - if f == nil then - return false - else - f:close() - return true - end -end - -function io.size(filename) - local f = open(filename) - if f == nil then - return 0 - else - local s = f:seek("end") - f:close() - return s - end -end - -local function noflines(f) - if type(f) == "string" then - local f = open(filename) - if f then - local n = f and noflines(f) or 0 - f:close() - return n - else - return 0 - end - else - local n = 0 - for _ in f:lines() do - n = n + 1 - end - f:seek('set',0) - return n - end -end - -io.noflines = noflines - --- inlined is faster - -local nextchar = { - [ 4] = function(f) - return f:read(1,1,1,1) - end, - [ 2] = function(f) - return f:read(1,1) - end, - [ 1] = function(f) - return f:read(1) - end, - [-2] = function(f) - local a, b = f:read(1,1) - return b, a - end, - [-4] = function(f) - local a, b, c, d = f:read(1,1,1,1) - return d, c, b, a - end -} - -function io.characters(f,n) - if f then - return nextchar[n or 1], f - end -end - -local nextbyte = { - [4] = function(f) - local a, b, c, d = f:read(1,1,1,1) - if d then - return byte(a), byte(b), byte(c), byte(d) - end - end, - [3] = function(f) - local a, b, c = f:read(1,1,1) - if b then - return byte(a), byte(b), byte(c) - end - end, - [2] = function(f) - local a, b = f:read(1,1) - if b then - return byte(a), byte(b) - end - end, - [1] = function (f) - local a = f:read(1) - if a then - return byte(a) - end - end, - [-2] = function (f) - local a, b = f:read(1,1) - if b then - return byte(b), byte(a) - end - end, - [-3] = function(f) - local a, b, c = f:read(1,1,1) - if b then - return byte(c), byte(b), byte(a) - end - end, - [-4] = function(f) - local a, b, c, d = f:read(1,1,1,1) - if d then - return byte(d), byte(c), byte(b), byte(a) - end - end -} - -function io.bytes(f,n) - if f then - return nextbyte[n or 1], f - else - return nil, nil - end -end - -function io.ask(question,default,options) - while true do - write(question) - if options then - write(format(" [%s]",concat(options,"|"))) - end - if default then - write(format(" [%s]",default)) - end - write(format(" ")) - flush() - local answer = read() - answer = gsub(answer,"^%s*(.*)%s*$","%1") - if answer == "" and default then - return default - elseif not options then - return answer - else - for k=1,#options do - if options[k] == answer then - return answer - end - end - local pattern = "^" .. answer - for k=1,#options do - local v = options[k] - if find(v,pattern) then - return v - end - end - end - end -end - -local function readnumber(f,n,m) - if m then - f:seek("set",n) - n = m - end - if n == 1 then - return byte(f:read(1)) - elseif n == 2 then - local a, b = byte(f:read(2),1,2) - return 256 * a + b - elseif n == 3 then - local a, b, c = byte(f:read(3),1,3) - return 256*256 * a + 256 * b + c - elseif n == 4 then - local a, b, c, d = byte(f:read(4),1,4) - return 256*256*256 * a + 256*256 * b + 256 * c + d - elseif n == 8 then - local a, b = readnumber(f,4), readnumber(f,4) - return 256 * a + b - elseif n == 12 then - local a, b, c = readnumber(f,4), readnumber(f,4), readnumber(f,4) - return 256*256 * a + 256 * b + c - elseif n == -2 then - local b, a = byte(f:read(2),1,2) - return 256*a + b - elseif n == -3 then - local c, b, a = byte(f:read(3),1,3) - return 256*256 * a + 256 * b + c - elseif n == -4 then - local d, c, b, a = byte(f:read(4),1,4) - return 256*256*256 * a + 256*256 * b + 256*c + d - elseif n == -8 then - local h, g, f, e, d, c, b, a = byte(f:read(8),1,8) - return 256*256*256*256*256*256*256 * a + - 256*256*256*256*256*256 * b + - 256*256*256*256*256 * c + - 256*256*256*256 * d + - 256*256*256 * e + - 256*256 * f + - 256 * g + - h - else - return 0 - end -end - -io.readnumber = readnumber - -function io.readstring(f,n,m) - if m then - f:seek("set",n) - n = m - end - local str = gsub(f:read(n),"\000","") - return str -end - --- This works quite ok: --- --- function io.piped(command,writer) --- local pipe = io.popen(command) --- -- for line in pipe:lines() do --- -- print(line) --- -- end --- while true do --- local line = pipe:read(1) --- if not line then --- break --- elseif line ~= "\n" then --- writer(line) --- end --- end --- return pipe:close() -- ok, status, (error)code --- end diff --git a/tex/compat/luaotfload/fontloader-l-lpeg.lua b/tex/compat/luaotfload/fontloader-l-lpeg.lua deleted file mode 100644 index 959ca553eb8d2c7c0a54e72c06a8eb8df471f802..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/fontloader-l-lpeg.lua +++ /dev/null @@ -1,1173 +0,0 @@ -if not modules then modules = { } end modules ['l-lpeg'] = { - version = 1.001, - comment = "companion to luat-lib.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- lpeg 12 vs lpeg 10: slower compilation, similar parsing speed (i need to check --- if i can use new features like capture / 2 and .B (at first sight the xml --- parser is some 5% slower) - --- lpeg.P("abc") is faster than lpeg.P("a") * lpeg.P("b") * lpeg.P("c") - --- a new lpeg fails on a #(1-P(":")) test and really needs a + P(-1) - --- move utf -> l-unicode --- move string -> l-string or keep it here - -lpeg = require("lpeg") - --- The latest lpeg doesn't have print any more, and even the new ones are not --- available by default (only when debug mode is enabled), which is a pitty as --- as it helps nailing down bottlenecks. Performance seems comparable: some 10% --- slower pattern compilation, same parsing speed, although, --- --- local p = lpeg.C(lpeg.P(1)^0 * lpeg.P(-1)) --- local a = string.rep("123",100) --- lpeg.match(p,a) --- --- seems slower and is also still suboptimal (i.e. a match that runs from begin --- to end, one of the cases where string matchers win). - -if not lpeg.print then function lpeg.print(...) print(lpeg.pcode(...)) end end - --- tracing (only used when we encounter a problem in integration of lpeg in luatex) - --- some code will move to unicode and string - --- local lpmatch = lpeg.match --- local lpprint = lpeg.print --- local lpp = lpeg.P --- local lpr = lpeg.R --- local lps = lpeg.S --- local lpc = lpeg.C --- local lpb = lpeg.B --- local lpv = lpeg.V --- local lpcf = lpeg.Cf --- local lpcb = lpeg.Cb --- local lpcg = lpeg.Cg --- local lpct = lpeg.Ct --- local lpcs = lpeg.Cs --- local lpcc = lpeg.Cc --- local lpcmt = lpeg.Cmt --- local lpcarg = lpeg.Carg - --- function lpeg.match(l,...) print("LPEG MATCH") lpprint(l) return lpmatch(l,...) end - --- function lpeg.P (l) local p = lpp (l) print("LPEG P =") lpprint(l) return p end --- function lpeg.R (l) local p = lpr (l) print("LPEG R =") lpprint(l) return p end --- function lpeg.S (l) local p = lps (l) print("LPEG S =") lpprint(l) return p end --- function lpeg.C (l) local p = lpc (l) print("LPEG C =") lpprint(l) return p end --- function lpeg.B (l) local p = lpb (l) print("LPEG B =") lpprint(l) return p end --- function lpeg.V (l) local p = lpv (l) print("LPEG V =") lpprint(l) return p end --- function lpeg.Cf (l) local p = lpcf (l) print("LPEG Cf =") lpprint(l) return p end --- function lpeg.Cb (l) local p = lpcb (l) print("LPEG Cb =") lpprint(l) return p end --- function lpeg.Cg (l) local p = lpcg (l) print("LPEG Cg =") lpprint(l) return p end --- function lpeg.Ct (l) local p = lpct (l) print("LPEG Ct =") lpprint(l) return p end --- function lpeg.Cs (l) local p = lpcs (l) print("LPEG Cs =") lpprint(l) return p end --- function lpeg.Cc (l) local p = lpcc (l) print("LPEG Cc =") lpprint(l) return p end --- function lpeg.Cmt (l) local p = lpcmt (l) print("LPEG Cmt =") lpprint(l) return p end --- function lpeg.Carg (l) local p = lpcarg(l) print("LPEG Carg =") lpprint(l) return p end - -local type, next, tostring = type, next, tostring -local byte, char, gmatch, format = string.byte, string.char, string.gmatch, string.format ------ mod, div = math.mod, math.div -local floor = math.floor - -local P, R, S, V, Ct, C, Cs, Cc, Cp, Cmt = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc, lpeg.Cp, lpeg.Cmt -local lpegtype, lpegmatch, lpegprint = lpeg.type, lpeg.match, lpeg.print - --- let's start with an inspector: - -if setinspector then - setinspector("lpeg",function(v) if lpegtype(v) then lpegprint(v) return true end end) -end - --- Beware, we predefine a bunch of patterns here and one reason for doing so --- is that we get consistent behaviour in some of the visualizers. - -lpeg.patterns = lpeg.patterns or { } -- so that we can share -local patterns = lpeg.patterns - -local anything = P(1) -local endofstring = P(-1) -local alwaysmatched = P(true) - -patterns.anything = anything -patterns.endofstring = endofstring -patterns.beginofstring = alwaysmatched -patterns.alwaysmatched = alwaysmatched - -local sign = S('+-') -local zero = P('0') -local digit = R('09') -local octdigit = R("07") -local lowercase = R("az") -local uppercase = R("AZ") -local underscore = P("_") -local hexdigit = digit + lowercase + uppercase -local cr, lf, crlf = P("\r"), P("\n"), P("\r\n") ------ newline = crlf + S("\r\n") -- cr + lf -local newline = P("\r") * (P("\n") + P(true)) + P("\n") -- P("\r")^-1 * P("\n")^-1 -local escaped = P("\\") * anything -local squote = P("'") -local dquote = P('"') -local space = P(" ") -local period = P(".") -local comma = P(",") - -local utfbom_32_be = P('\000\000\254\255') -- 00 00 FE FF -local utfbom_32_le = P('\255\254\000\000') -- FF FE 00 00 -local utfbom_16_be = P('\254\255') -- FE FF -local utfbom_16_le = P('\255\254') -- FF FE -local utfbom_8 = P('\239\187\191') -- EF BB BF -local utfbom = utfbom_32_be + utfbom_32_le - + utfbom_16_be + utfbom_16_le - + utfbom_8 -local utftype = utfbom_32_be * Cc("utf-32-be") + utfbom_32_le * Cc("utf-32-le") - + utfbom_16_be * Cc("utf-16-be") + utfbom_16_le * Cc("utf-16-le") - + utfbom_8 * Cc("utf-8") + alwaysmatched * Cc("utf-8") -- assume utf8 -local utfstricttype = utfbom_32_be * Cc("utf-32-be") + utfbom_32_le * Cc("utf-32-le") - + utfbom_16_be * Cc("utf-16-be") + utfbom_16_le * Cc("utf-16-le") - + utfbom_8 * Cc("utf-8") -local utfoffset = utfbom_32_be * Cc(4) + utfbom_32_le * Cc(4) - + utfbom_16_be * Cc(2) + utfbom_16_le * Cc(2) - + utfbom_8 * Cc(3) + Cc(0) - -local utf8next = R("\128\191") - -patterns.utfbom_32_be = utfbom_32_be -patterns.utfbom_32_le = utfbom_32_le -patterns.utfbom_16_be = utfbom_16_be -patterns.utfbom_16_le = utfbom_16_le -patterns.utfbom_8 = utfbom_8 - -patterns.utf_16_be_nl = P("\000\r\000\n") + P("\000\r") + P("\000\n") -- P("\000\r") * (P("\000\n") + P(true)) + P("\000\n") -patterns.utf_16_le_nl = P("\r\000\n\000") + P("\r\000") + P("\n\000") -- P("\r\000") * (P("\n\000") + P(true)) + P("\n\000") - -patterns.utf_32_be_nl = P("\000\000\000\r\000\000\000\n") + P("\000\000\000\r") + P("\000\000\000\n") -patterns.utf_32_le_nl = P("\r\000\000\000\n\000\000\000") + P("\r\000\000\000") + P("\n\000\000\000") - -patterns.utf8one = R("\000\127") -patterns.utf8two = R("\194\223") * utf8next -patterns.utf8three = R("\224\239") * utf8next * utf8next -patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next -patterns.utfbom = utfbom -patterns.utftype = utftype -patterns.utfstricttype = utfstricttype -patterns.utfoffset = utfoffset - -local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four -local validutf8char = utf8char^0 * endofstring * Cc(true) + Cc(false) - -local utf8character = P(1) * R("\128\191")^0 -- unchecked but fast - -patterns.utf8 = utf8char -patterns.utf8char = utf8char -patterns.utf8character = utf8character -- this one can be used in most cases so we might use that one -patterns.validutf8 = validutf8char -patterns.validutf8char = validutf8char - -local eol = S("\n\r") -local spacer = S(" \t\f\v") -- + char(0xc2, 0xa0) if we want utf (cf mail roberto) -local whitespace = eol + spacer -local nonspacer = 1 - spacer -local nonwhitespace = 1 - whitespace - -patterns.eol = eol -patterns.spacer = spacer -patterns.whitespace = whitespace -patterns.nonspacer = nonspacer -patterns.nonwhitespace = nonwhitespace - -local stripper = spacer ^0 * C((spacer ^0 * nonspacer ^1)^0) -- from example by roberto -local fullstripper = whitespace^0 * C((whitespace^0 * nonwhitespace^1)^0) - ------ collapser = Cs(spacer^0/"" * ((spacer^1 * endofstring / "") + (spacer^1/" ") + P(1))^0) -local collapser = Cs(spacer^0/"" * nonspacer^0 * ((spacer^0/" " * nonspacer^1)^0)) - -local b_collapser = Cs( whitespace^0 /"" * (nonwhitespace^1 + whitespace^1/" ")^0) -local e_collapser = Cs((whitespace^1 * P(-1)/"" + nonwhitespace^1 + whitespace^1/" ")^0) -local m_collapser = Cs( (nonwhitespace^1 + whitespace^1/" ")^0) - -local b_stripper = Cs( spacer^0 /"" * (nonspacer^1 + spacer^1/" ")^0) -local e_stripper = Cs((spacer^1 * P(-1)/"" + nonspacer^1 + spacer^1/" ")^0) -local m_stripper = Cs( (nonspacer^1 + spacer^1/" ")^0) - -patterns.stripper = stripper -patterns.fullstripper = fullstripper -patterns.collapser = collapser - -patterns.b_collapser = b_collapser -patterns.m_collapser = m_collapser -patterns.e_collapser = e_collapser - -patterns.b_stripper = b_stripper -patterns.m_stripper = m_stripper -patterns.e_stripper = e_stripper - -patterns.lowercase = lowercase -patterns.uppercase = uppercase -patterns.letter = patterns.lowercase + patterns.uppercase -patterns.space = space -patterns.tab = P("\t") -patterns.spaceortab = patterns.space + patterns.tab -patterns.newline = newline -patterns.emptyline = newline^1 -patterns.equal = P("=") -patterns.comma = comma -patterns.commaspacer = comma * spacer^0 -patterns.period = period -patterns.colon = P(":") -patterns.semicolon = P(";") -patterns.underscore = underscore -patterns.escaped = escaped -patterns.squote = squote -patterns.dquote = dquote -patterns.nosquote = (escaped + (1-squote))^0 -patterns.nodquote = (escaped + (1-dquote))^0 -patterns.unsingle = (squote/"") * patterns.nosquote * (squote/"") -- will change to C in the middle -patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"") -- will change to C in the middle -patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble -patterns.unspacer = ((patterns.spacer^1)/"")^0 - -patterns.singlequoted = squote * patterns.nosquote * squote -patterns.doublequoted = dquote * patterns.nodquote * dquote -patterns.quoted = patterns.doublequoted + patterns.singlequoted - -patterns.digit = digit -patterns.octdigit = octdigit -patterns.hexdigit = hexdigit -patterns.sign = sign -patterns.cardinal = digit^1 -patterns.integer = sign^-1 * digit^1 -patterns.unsigned = digit^0 * period * digit^1 -patterns.float = sign^-1 * patterns.unsigned -patterns.cunsigned = digit^0 * comma * digit^1 -patterns.cpunsigned = digit^0 * (period + comma) * digit^1 -patterns.cfloat = sign^-1 * patterns.cunsigned -patterns.cpfloat = sign^-1 * patterns.cpunsigned -patterns.number = patterns.float + patterns.integer -patterns.cnumber = patterns.cfloat + patterns.integer -patterns.cpnumber = patterns.cpfloat + patterns.integer -patterns.oct = zero * octdigit^1 -patterns.octal = patterns.oct -patterns.HEX = zero * P("X") * (digit+uppercase)^1 -patterns.hex = zero * P("x") * (digit+lowercase)^1 -patterns.hexadecimal = zero * S("xX") * hexdigit^1 - -patterns.hexafloat = sign^-1 - * zero * S("xX") - * (hexdigit^0 * period * hexdigit^1 + hexdigit^1 * period * hexdigit^0 + hexdigit^1) - * (S("pP") * sign^-1 * hexdigit^1)^-1 -patterns.decafloat = sign^-1 - * (digit^0 * period * digit^1 + digit^1 * period * digit^0 + digit^1) - * S("eE") * sign^-1 * digit^1 - -patterns.propername = (uppercase + lowercase + underscore) * (uppercase + lowercase + underscore + digit)^0 * endofstring - -patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1 -patterns.beginline = #(1-newline) - -patterns.longtostring = Cs(whitespace^0/"" * ((patterns.quoted + nonwhitespace^1 + whitespace^1/"" * (P(-1) + Cc(" ")))^0)) - -local function anywhere(pattern) --slightly adapted from website - return P { P(pattern) + 1 * V(1) } -end - -lpeg.anywhere = anywhere - -function lpeg.instringchecker(p) - p = anywhere(p) - return function(str) - return lpegmatch(p,str) and true or false - end -end - -function lpeg.splitter(pattern, action) - return (((1-P(pattern))^1)/action+1)^0 -end - -function lpeg.tsplitter(pattern, action) - return Ct((((1-P(pattern))^1)/action+1)^0) -end - --- probleem: separator can be lpeg and that does not hash too well, but --- it's quite okay as the key is then not garbage collected - -local splitters_s, splitters_m, splitters_t = { }, { }, { } - -local function splitat(separator,single) - local splitter = (single and splitters_s[separator]) or splitters_m[separator] - if not splitter then - separator = P(separator) - local other = C((1 - separator)^0) - if single then - local any = anything - splitter = other * (separator * C(any^0) + "") -- ? - splitters_s[separator] = splitter - else - splitter = other * (separator * other)^0 - splitters_m[separator] = splitter - end - end - return splitter -end - -local function tsplitat(separator) - local splitter = splitters_t[separator] - if not splitter then - splitter = Ct(splitat(separator)) - splitters_t[separator] = splitter - end - return splitter -end - -lpeg.splitat = splitat -lpeg.tsplitat = tsplitat - -function string.splitup(str,separator) - if not separator then - separator = "," - end - return lpegmatch(splitters_m[separator] or splitat(separator),str) -end - --- local p = splitat("->",false) print(lpegmatch(p,"oeps->what->more")) -- oeps what more --- local p = splitat("->",true) print(lpegmatch(p,"oeps->what->more")) -- oeps what->more --- local p = splitat("->",false) print(lpegmatch(p,"oeps")) -- oeps --- local p = splitat("->",true) print(lpegmatch(p,"oeps")) -- oeps - -local cache = { } - -function lpeg.split(separator,str) - local c = cache[separator] - if not c then - c = tsplitat(separator) - cache[separator] = c - end - return lpegmatch(c,str) -end - -function string.split(str,separator) - if separator then - local c = cache[separator] - if not c then - c = tsplitat(separator) - cache[separator] = c - end - return lpegmatch(c,str) - else - return { str } - end -end - -local spacing = patterns.spacer^0 * newline -- sort of strip -local empty = spacing * Cc("") -local nonempty = Cs((1-spacing)^1) * spacing^-1 -local content = (empty + nonempty)^1 - -patterns.textline = content - -local linesplitter = tsplitat(newline) - -patterns.linesplitter = linesplitter - -function string.splitlines(str) - return lpegmatch(linesplitter,str) -end - --- lpeg.splitters = cache -- no longer public - -local cache = { } - -function lpeg.checkedsplit(separator,str) - local c = cache[separator] - if not c then - separator = P(separator) - local other = C((1 - separator)^1) - c = Ct(separator^0 * other * (separator^1 * other)^0) - cache[separator] = c - end - return lpegmatch(c,str) -end - -function string.checkedsplit(str,separator) - local c = cache[separator] - if not c then - separator = P(separator) - local other = C((1 - separator)^1) - c = Ct(separator^0 * other * (separator^1 * other)^0) - cache[separator] = c - end - return lpegmatch(c,str) -end - --- from roberto's site: - -local function f2(s) local c1, c2 = byte(s,1,2) return c1 * 64 + c2 - 12416 end -local function f3(s) local c1, c2, c3 = byte(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end -local function f4(s) local c1, c2, c3, c4 = byte(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end - -local utf8byte = patterns.utf8one/byte + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4 - -patterns.utf8byte = utf8byte - ---~ local str = " a b c d " - ---~ local s = lpeg.stripper(lpeg.R("az")) print("["..lpegmatch(s,str).."]") ---~ local s = lpeg.keeper(lpeg.R("az")) print("["..lpegmatch(s,str).."]") ---~ local s = lpeg.stripper("ab") print("["..lpegmatch(s,str).."]") ---~ local s = lpeg.keeper("ab") print("["..lpegmatch(s,str).."]") - -local cache = { } - -function lpeg.stripper(str) - if type(str) == "string" then - local s = cache[str] - if not s then - s = Cs(((S(str)^1)/"" + 1)^0) - cache[str] = s - end - return s - else - return Cs(((str^1)/"" + 1)^0) - end -end - -local cache = { } - -function lpeg.keeper(str) - if type(str) == "string" then - local s = cache[str] - if not s then - s = Cs((((1-S(str))^1)/"" + 1)^0) - cache[str] = s - end - return s - else - return Cs((((1-str)^1)/"" + 1)^0) - end -end - -function lpeg.frontstripper(str) -- or pattern (yet undocumented) - return (P(str) + P(true)) * Cs(anything^0) -end - -function lpeg.endstripper(str) -- or pattern (yet undocumented) - return Cs((1 - P(str) * endofstring)^0) -end - --- Just for fun I looked at the used bytecode and --- p = (p and p + pp) or pp gets one more (testset). - --- todo: cache when string - -function lpeg.replacer(one,two,makefunction,isutf) -- in principle we should sort the keys - local pattern - local u = isutf and utf8char or 1 - if type(one) == "table" then - local no = #one - local p = P(false) - if no == 0 then - for k, v in next, one do - p = p + P(k) / v - end - pattern = Cs((p + u)^0) - elseif no == 1 then - local o = one[1] - one, two = P(o[1]), o[2] - -- pattern = Cs(((1-one)^1 + one/two)^0) - pattern = Cs((one/two + u)^0) - else - for i=1,no do - local o = one[i] - p = p + P(o[1]) / o[2] - end - pattern = Cs((p + u)^0) - end - else - pattern = Cs((P(one)/(two or "") + u)^0) - end - if makefunction then - return function(str) - return lpegmatch(pattern,str) - end - else - return pattern - end -end - --- local pattern1 = P(1-P(pattern))^0 * P(pattern) : test for not nil --- local pattern2 = (P(pattern) * Cc(true) + P(1))^0 : test for true (could be faster, but not much) - -function lpeg.finder(lst,makefunction,isutf) -- beware: slower than find with 'patternless finds' - local pattern - if type(lst) == "table" then - pattern = P(false) - if #lst == 0 then - for k, v in next, lst do - pattern = pattern + P(k) -- ignore key, so we can use a replacer table - end - else - for i=1,#lst do - pattern = pattern + P(lst[i]) - end - end - else - pattern = P(lst) - end - if isutf then - pattern = ((utf8char or 1)-pattern)^0 * pattern - else - pattern = (1-pattern)^0 * pattern - end - if makefunction then - return function(str) - return lpegmatch(pattern,str) - end - else - return pattern - end -end - --- print(lpeg.match(lpeg.replacer("e","a"),"test test")) --- print(lpeg.match(lpeg.replacer{{"e","a"}},"test test")) --- print(lpeg.match(lpeg.replacer({ e = "a", t = "x" }),"test test")) - -local splitters_f, splitters_s = { }, { } - -function lpeg.firstofsplit(separator) -- always return value - local splitter = splitters_f[separator] - if not splitter then - local pattern = P(separator) - splitter = C((1 - pattern)^0) - splitters_f[separator] = splitter - end - return splitter -end - -function lpeg.secondofsplit(separator) -- nil if not split - local splitter = splitters_s[separator] - if not splitter then - local pattern = P(separator) - splitter = (1 - pattern)^0 * pattern * C(anything^0) - splitters_s[separator] = splitter - end - return splitter -end - -local splitters_s, splitters_p = { }, { } - -function lpeg.beforesuffix(separator) -- nil if nothing but empty is ok - local splitter = splitters_s[separator] - if not splitter then - local pattern = P(separator) - splitter = C((1 - pattern)^0) * pattern * endofstring - splitters_s[separator] = splitter - end - return splitter -end - -function lpeg.afterprefix(separator) -- nil if nothing but empty is ok - local splitter = splitters_p[separator] - if not splitter then - local pattern = P(separator) - splitter = pattern * C(anything^0) - splitters_p[separator] = splitter - end - return splitter -end - -function lpeg.balancer(left,right) - left, right = P(left), P(right) - return P { left * ((1 - left - right) + V(1))^0 * right } -end - --- print(1,lpegmatch(lpeg.firstofsplit(":"),"bc:de")) --- print(2,lpegmatch(lpeg.firstofsplit(":"),":de")) -- empty --- print(3,lpegmatch(lpeg.firstofsplit(":"),"bc")) --- print(4,lpegmatch(lpeg.secondofsplit(":"),"bc:de")) --- print(5,lpegmatch(lpeg.secondofsplit(":"),"bc:")) -- empty --- print(6,lpegmatch(lpeg.secondofsplit(":",""),"bc")) --- print(7,lpegmatch(lpeg.secondofsplit(":"),"bc")) --- print(9,lpegmatch(lpeg.secondofsplit(":","123"),"bc")) - --- -- slower: --- --- function lpeg.counter(pattern) --- local n, pattern = 0, (lpeg.P(pattern)/function() n = n + 1 end + lpeg.anything)^0 --- return function(str) n = 0 ; lpegmatch(pattern,str) ; return n end --- end - -local nany = utf8char/"" - -function lpeg.counter(pattern) - pattern = Cs((P(pattern)/" " + nany)^0) - return function(str) - return #lpegmatch(pattern,str) - end -end - --- utf extensies - -utf = utf or (unicode and unicode.utf8) or { } - -local utfcharacters = utf and utf.characters or string.utfcharacters -local utfgmatch = utf and utf.gmatch -local utfchar = utf and utf.char - -lpeg.UP = lpeg.P - -if utfcharacters then - - function lpeg.US(str) - local p = P(false) - for uc in utfcharacters(str) do - p = p + P(uc) - end - return p - end - - -elseif utfgmatch then - - function lpeg.US(str) - local p = P(false) - for uc in utfgmatch(str,".") do - p = p + P(uc) - end - return p - end - -else - - function lpeg.US(str) - local p = P(false) - local f = function(uc) - p = p + P(uc) - end - lpegmatch((utf8char/f)^0,str) - return p - end - -end - -local range = utf8byte * utf8byte + Cc(false) -- utf8byte is already a capture - -function lpeg.UR(str,more) - local first, last - if type(str) == "number" then - first = str - last = more or first - else - first, last = lpegmatch(range,str) - if not last then - return P(str) - end - end - if first == last then - return P(str) - elseif utfchar and (last - first < 8) then -- a somewhat arbitrary criterium - local p = P(false) - for i=first,last do - p = p + P(utfchar(i)) - end - return p -- nil when invalid range - else - local f = function(b) - return b >= first and b <= last - end - -- tricky, these nested captures - return utf8byte / f -- nil when invalid range - end -end - --- print(lpeg.match(lpeg.Cs((C(lpeg.UR("αω"))/{ ["χ"] = "OEPS" })^0),"αωχαω")) - --- lpeg.print(lpeg.R("ab","cd","gh")) --- lpeg.print(lpeg.P("a","b","c")) --- lpeg.print(lpeg.S("a","b","c")) - --- print(lpeg.count("äáàa",lpeg.P("á") + lpeg.P("à"))) --- print(lpeg.count("äáàa",lpeg.UP("áà"))) --- print(lpeg.count("äáàa",lpeg.US("àá"))) --- print(lpeg.count("äáàa",lpeg.UR("aá"))) --- print(lpeg.count("äáàa",lpeg.UR("àá"))) --- print(lpeg.count("äáàa",lpeg.UR(0x0000,0xFFFF))) - -function lpeg.is_lpeg(p) - return p and lpegtype(p) == "pattern" -end - -function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then") -- assume proper order - if type(list) ~= "table" then - list = { list, ... } - end - -- table.sort(list) -- longest match first - local p = P(list[1]) - for l=2,#list do - p = p + P(list[l]) - end - return p -end - --- For the moment here, but it might move to utilities. Beware, we need to --- have the longest keyword first, so 'aaa' comes beforte 'aa' which is why we --- loop back from the end cq. prepend. - -local sort = table.sort - -local function copyindexed(old) - local new = { } - for i=1,#old do - new[i] = old - end - return new -end - -local function sortedkeys(tab) - local keys, s = { }, 0 - for key,_ in next, tab do - s = s + 1 - keys[s] = key - end - sort(keys) - return keys -end - -function lpeg.append(list,pp,delayed,checked) - local p = pp - if #list > 0 then - local keys = copyindexed(list) - sort(keys) - for i=#keys,1,-1 do - local k = keys[i] - if p then - p = P(k) + p - else - p = P(k) - end - end - elseif delayed then -- hm, it looks like the lpeg parser resolves anyway - local keys = sortedkeys(list) - if p then - for i=1,#keys,1 do - local k = keys[i] - local v = list[k] - p = P(k)/list + p - end - else - for i=1,#keys do - local k = keys[i] - local v = list[k] - if p then - p = P(k) + p - else - p = P(k) - end - end - if p then - p = p / list - end - end - elseif checked then - -- problem: substitution gives a capture - local keys = sortedkeys(list) - for i=1,#keys do - local k = keys[i] - local v = list[k] - if p then - if k == v then - p = P(k) + p - else - p = P(k)/v + p - end - else - if k == v then - p = P(k) - else - p = P(k)/v - end - end - end - else - local keys = sortedkeys(list) - for i=1,#keys do - local k = keys[i] - local v = list[k] - if p then - p = P(k)/v + p - else - p = P(k)/v - end - end - end - return p -end - --- inspect(lpeg.append({ a = "1", aa = "1", aaa = "1" } ,nil,true)) --- inspect(lpeg.append({ ["degree celsius"] = "1", celsius = "1", degree = "1" } ,nil,true)) - --- function lpeg.exact_match(words,case_insensitive) --- local pattern = concat(words) --- if case_insensitive then --- local pattern = S(upper(characters)) + S(lower(characters)) --- local list = { } --- for i=1,#words do --- list[lower(words[i])] = true --- end --- return Cmt(pattern^1, function(_,i,s) --- return list[lower(s)] and i --- end) --- else --- local pattern = S(concat(words)) --- local list = { } --- for i=1,#words do --- list[words[i]] = true --- end --- return Cmt(pattern^1, function(_,i,s) --- return list[s] and i --- end) --- end --- end - --- experiment: - -local p_false = P(false) -local p_true = P(true) - -local function make(t) - local function making(t) - local p = p_false - local keys = sortedkeys(t) - for i=1,#keys do - local k = keys[i] - if k ~= "" then - local v = t[k] - if v == true then - p = p + P(k) * p_true - elseif v == false then - -- can't happen - else - p = p + P(k) * making(v) - end - end - end - if t[""] then - p = p + p_true - end - return p - end - local p = p_false - local keys = sortedkeys(t) - for i=1,#keys do - local k = keys[i] - if k ~= "" then - local v = t[k] - if v == true then - p = p + P(k) * p_true - elseif v == false then - -- can't happen - else - p = p + P(k) * making(v) - end - end - end - return p -end - -local function collapse(t,x) - if type(t) ~= "table" then - return t, x - else - local n = next(t) - if n == nil then - return t, x - elseif next(t,n) == nil then - -- one entry - local k = n - local v = t[k] - if type(v) == "table" then - return collapse(v,x..k) - else - return v, x .. k - end - else - local tt = { } - for k, v in next, t do - local vv, kk = collapse(v,k) - tt[kk] = vv - end - return tt, x - end - end -end - -function lpeg.utfchartabletopattern(list) -- goes to util-lpg - local tree = { } - local n = #list - if n == 0 then - for s in next, list do - local t = tree - local p, pk - for c in gmatch(s,".") do - if t == true then - t = { [c] = true, [""] = true } - p[pk] = t - p = t - t = false - elseif t == false then - t = { [c] = false } - p[pk] = t - p = t - t = false - else - local tc = t[c] - if not tc then - tc = false - t[c] = false - end - p = t - t = tc - end - pk = c - end - if t == false then - p[pk] = true - elseif t == true then - -- okay - else - t[""] = true - end - end - else - for i=1,n do - local s = list[i] - local t = tree - local p, pk - for c in gmatch(s,".") do - if t == true then - t = { [c] = true, [""] = true } - p[pk] = t - p = t - t = false - elseif t == false then - t = { [c] = false } - p[pk] = t - p = t - t = false - else - local tc = t[c] - if not tc then - tc = false - t[c] = false - end - p = t - t = tc - end - pk = c - end - if t == false then - p[pk] = true - elseif t == true then - -- okay - else - t[""] = true - end - end - end --- collapse(tree,"") -- needs testing, maybe optional, slightly faster because P("x")*P("X") seems slower than P"(xX") (why) --- inspect(tree) - return make(tree) -end - --- local t = { "start", "stoep", "staart", "paard" } --- local p = lpeg.Cs((lpeg.utfchartabletopattern(t)/string.upper + 1)^1) - --- local t = { "a", "abc", "ac", "abe", "abxyz", "xy", "bef","aa" } --- local p = lpeg.Cs((lpeg.utfchartabletopattern(t)/string.upper + 1)^1) - --- inspect(lpegmatch(p,"a")) --- inspect(lpegmatch(p,"aa")) --- inspect(lpegmatch(p,"aaaa")) --- inspect(lpegmatch(p,"ac")) --- inspect(lpegmatch(p,"bc")) --- inspect(lpegmatch(p,"zzbczz")) --- inspect(lpegmatch(p,"zzabezz")) --- inspect(lpegmatch(p,"ab")) --- inspect(lpegmatch(p,"abc")) --- inspect(lpegmatch(p,"abe")) --- inspect(lpegmatch(p,"xa")) --- inspect(lpegmatch(p,"bx")) --- inspect(lpegmatch(p,"bax")) --- inspect(lpegmatch(p,"abxyz")) --- inspect(lpegmatch(p,"foobarbefcrap")) - --- local t = { ["^"] = 1, ["^^"] = 2, ["^^^"] = 3, ["^^^^"] = 4 } --- local p = lpeg.Cs((lpeg.utfchartabletopattern(t)/t + 1)^1) --- inspect(lpegmatch(p," ^ ^^ ^^^ ^^^^ ^^^^^ ^^^^^^ ^^^^^^^ ")) - --- local t = { ["^^"] = 2, ["^^^"] = 3, ["^^^^"] = 4 } --- local p = lpeg.Cs((lpeg.utfchartabletopattern(t)/t + 1)^1) --- inspect(lpegmatch(p," ^ ^^ ^^^ ^^^^ ^^^^^ ^^^^^^ ^^^^^^^ ")) - --- lpeg.utfchartabletopattern { --- utfchar(0x00A0), -- nbsp --- utfchar(0x2000), -- enquad --- utfchar(0x2001), -- emquad --- utfchar(0x2002), -- enspace --- utfchar(0x2003), -- emspace --- utfchar(0x2004), -- threeperemspace --- utfchar(0x2005), -- fourperemspace --- utfchar(0x2006), -- sixperemspace --- utfchar(0x2007), -- figurespace --- utfchar(0x2008), -- punctuationspace --- utfchar(0x2009), -- breakablethinspace --- utfchar(0x200A), -- hairspace --- utfchar(0x200B), -- zerowidthspace --- utfchar(0x202F), -- narrownobreakspace --- utfchar(0x205F), -- math thinspace --- } - --- a few handy ones: --- --- faster than find(str,"[\n\r]") when match and # > 7 and always faster when # > 3 - -patterns.containseol = lpeg.finder(eol) -- (1-eol)^0 * eol - --- The next pattern^n variant is based on an approach suggested --- by Roberto: constructing a big repetition in chunks. --- --- Being sparse is not needed, and only complicate matters and --- the number of redundant entries is not that large. - -local function nextstep(n,step,result) - local m = n % step -- mod(n,step) - local d = floor(n/step) -- div(n,step) - if d > 0 then - local v = V(tostring(step)) - local s = result.start - for i=1,d do - if s then - s = v * s - else - s = v - end - end - result.start = s - end - if step > 1 and result.start then - local v = V(tostring(step/2)) - result[tostring(step)] = v * v - end - if step > 0 then - return nextstep(m,step/2,result) - else - return result - end -end - -function lpeg.times(pattern,n) - return P(nextstep(n,2^16,{ "start", ["1"] = pattern })) -end - --- local p = lpeg.Cs((1 - lpeg.times(lpeg.P("AB"),25))^1) --- local s = "12" .. string.rep("AB",20) .. "34" .. string.rep("AB",30) .. "56" --- inspect(p) --- print(lpeg.match(p,s)) - --- moved here (before util-str) - ------ digit = R("09") ------ period = P(".") ------ zero = P("0") -local trailingzeros = zero^0 * -digit -- suggested by Roberto R -local case_1 = period * trailingzeros / "" -local case_2 = period * (digit - trailingzeros)^1 * (trailingzeros / "") -local number = digit^1 * (case_1 + case_2) -local stripper = Cs((number + 1)^0) - -lpeg.patterns.stripzeros = stripper - --- local sample = "bla 11.00 bla 11 bla 0.1100 bla 1.00100 bla 0.00 bla 0.001 bla 1.1100 bla 0.100100100 bla 0.00100100100" --- collectgarbage("collect") --- str = string.rep(sample,10000) --- local ts = os.clock() --- lpegmatch(stripper,str) --- print(#str, os.clock()-ts, lpegmatch(stripper,sample)) - --- for practical reasone we keep this here: - -local byte_to_HEX = { } -local byte_to_hex = { } -local byte_to_dec = { } -- for md5 -local hex_to_byte = { } - -for i=0,255 do - local H = format("%02X",i) - local h = format("%02x",i) - local d = format("%03i",i) - local c = char(i) - byte_to_HEX[c] = H - byte_to_hex[c] = h - byte_to_dec[c] = d - hex_to_byte[h] = c - hex_to_byte[H] = c -end - -local hextobyte = P(2)/hex_to_byte -local bytetoHEX = P(1)/byte_to_HEX -local bytetohex = P(1)/byte_to_hex -local bytetodec = P(1)/byte_to_dec -local hextobytes = Cs(hextobyte^0) -local bytestoHEX = Cs(bytetoHEX^0) -local bytestohex = Cs(bytetohex^0) -local bytestodec = Cs(bytetodec^0) - -patterns.hextobyte = hextobyte -patterns.bytetoHEX = bytetoHEX -patterns.bytetohex = bytetohex -patterns.bytetodec = bytetodec -patterns.hextobytes = hextobytes -patterns.bytestoHEX = bytestoHEX -patterns.bytestohex = bytestohex -patterns.bytestodec = bytestodec - -function string.toHEX(s) - if not s or s == "" then - return s - else - return lpegmatch(bytestoHEX,s) - end -end - -function string.tohex(s) - if not s or s == "" then - return s - else - return lpegmatch(bytestohex,s) - end -end - -function string.todec(s) - if not s or s == "" then - return s - else - return lpegmatch(bytestodec,s) - end -end - -function string.tobytes(s) - if not s or s == "" then - return s - else - return lpegmatch(hextobytes,s) - end -end - --- local h = "ADFE0345" --- local b = lpegmatch(patterns.hextobytes,h) --- print(h,b,string.tohex(b),string.toHEX(b)) diff --git a/tex/compat/luaotfload/fontloader-l-lua.lua b/tex/compat/luaotfload/fontloader-l-lua.lua deleted file mode 100644 index 35715383635420c2d1cc32dedcb7c1bb967635a4..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/fontloader-l-lua.lua +++ /dev/null @@ -1,201 +0,0 @@ -if not modules then modules = { } end modules ['l-lua'] = { - version = 1.001, - comment = "companion to luat-lib.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- potential issues with 5.3: - --- i'm not sure yet if the int/float change is good for luatex - --- math.min --- math.max --- tostring --- tonumber --- utf.* --- bit32 - --- compatibility hacksand helpers - -_MAJORVERSION, _MINORVERSION = string.match(_VERSION,"^[^%d]+(%d+)%.(%d+).*$") - -_MAJORVERSION = tonumber(_MAJORVERSION) or 5 -_MINORVERSION = tonumber(_MINORVERSION) or 1 -_LUAVERSION = _MAJORVERSION + _MINORVERSION/10 - -if _LUAVERSION < 5.2 and jit then - -- - -- we want loadstring cum suis to behave like 5.2 - -- - _MINORVERSION = 2 - _LUAVERSION = 5.2 -end - --- lpeg - -if not lpeg then - lpeg = require("lpeg") -end - --- basics: - -if loadstring then - - local loadnormal = load - - function load(first,...) - if type(first) == "string" then - return loadstring(first,...) - else - return loadnormal(first,...) - end - end - -else - - loadstring = load - -end - --- table: - --- At some point it was announced that i[pairs would be dropped, which makes --- sense. As we already used the for loop and # in most places the impact on --- ConTeXt was not that large; the remaining ipairs already have been replaced. --- Hm, actually ipairs was retained, but we no longer use it anyway (nor --- pairs). --- --- Just in case, we provide the fallbacks as discussed in Programming --- in Lua (http://www.lua.org/pil/7.3.html): - -if not ipairs then - - -- for k, v in ipairs(t) do ... end - -- for k=1,#t do local v = t[k] ... end - - local function iterate(a,i) - i = i + 1 - local v = a[i] - if v ~= nil then - return i, v --, nil - end - end - - function ipairs(a) - return iterate, a, 0 - end - -end - -if not pairs then - - -- for k, v in pairs(t) do ... end - -- for k, v in next, t do ... end - - function pairs(t) - return next, t -- , nil - end - -end - --- The unpack function has been moved to the table table, and for compatiility --- reasons we provide both now. - -if not table.unpack then - - table.unpack = _G.unpack - -elseif not unpack then - - _G.unpack = table.unpack - -end - --- package: - --- if not package.seachers then --- --- package.searchers = package.loaders -- 5.2 --- --- elseif not package.loaders then --- --- package.loaders = package.searchers --- --- end - -if not package.loaders then -- brr, searchers is a special "loadlib function" userdata type - - package.loaders = package.searchers - -end - --- moved from util-deb to here: - -local print, select, tostring = print, select, tostring - -local inspectors = { } - -function setinspector(kind,inspector) -- global function - inspectors[kind] = inspector -end - -function inspect(...) -- global function - for s=1,select("#",...) do - local value = select(s,...) - if value == nil then - print("nil") - else - local done = false - -- type driven (table) - local kind = type(value) - local inspector = inspectors[kind] - if inspector then - done = inspector(value) - if done then - break - end - end - -- whatever driven (token, node, ...) - for kind, inspector in next, inspectors do - done = inspector(value) - if done then - break - end - end - if not done then - print(tostring(value)) - end - end - end -end - --- - -local dummy = function() end - -function optionalrequire(...) - local ok, result = xpcall(require,dummy,...) - if ok then - return result - end -end - --- nice for non ascii scripts (this might move): - -if lua then - lua.mask = load([[τεχ = 1]]) and "utf" or "ascii" -end - -local flush = io.flush - -if flush then - - local execute = os.execute if execute then function os.execute(...) flush() return execute(...) end end - local exec = os.exec if exec then function os.exec (...) flush() return exec (...) end end - local spawn = os.spawn if spawn then function os.spawn (...) flush() return spawn (...) end end - local popen = io.popen if popen then function io.popen (...) flush() return popen (...) end end - -end - diff --git a/tex/compat/luaotfload/fontloader-l-math.lua b/tex/compat/luaotfload/fontloader-l-math.lua deleted file mode 100644 index ec62919b46ac50acc93ceeeef4394dd1474e5569..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/fontloader-l-math.lua +++ /dev/null @@ -1,38 +0,0 @@ -if not modules then modules = { } end modules ['l-math'] = { - version = 1.001, - comment = "companion to luat-lib.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -local floor, sin, cos, tan = math.floor, math.sin, math.cos, math.tan - -if not math.ceiling then - math.ceiling = math.ceil -end - -if not math.round then - function math.round(x) return floor(x + 0.5) end -end - -if not math.div then - function math.div(n,m) return floor(n/m) end -end - -if not math.mod then - function math.mod(n,m) return n % m end -end - -local pipi = 2*math.pi/360 - -if not math.sind then - function math.sind(d) return sin(d*pipi) end - function math.cosd(d) return cos(d*pipi) end - function math.tand(d) return tan(d*pipi) end -end - -if not math.odd then - function math.odd (n) return n % 2 ~= 0 end - function math.even(n) return n % 2 == 0 end -end diff --git a/tex/compat/luaotfload/fontloader-l-string.lua b/tex/compat/luaotfload/fontloader-l-string.lua deleted file mode 100644 index be8f397aee36d6d4a3f219eec7b2e69d6975acea..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/fontloader-l-string.lua +++ /dev/null @@ -1,214 +0,0 @@ -if not modules then modules = { } end modules ['l-string'] = { - version = 1.001, - comment = "companion to luat-lib.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -local string = string -local sub, gmatch, format, char, byte, rep, lower = string.sub, string.gmatch, string.format, string.char, string.byte, string.rep, string.lower -local lpegmatch, patterns = lpeg.match, lpeg.patterns -local P, S, C, Ct, Cc, Cs = lpeg.P, lpeg.S, lpeg.C, lpeg.Ct, lpeg.Cc, lpeg.Cs - --- Some functions are already defined in l-lpeg and maybe some from here will --- move there (unless we also expose caches). - --- if not string.split then --- --- function string.split(str,pattern) --- local t = { } --- if #str > 0 then --- local n = 1 --- for s in gmatch(str..pattern,"(.-)"..pattern) do --- t[n] = s --- n = n + 1 --- end --- end --- return t --- end --- --- end - --- function string.unquoted(str) --- return (gsub(str,"^([\"\'])(.*)%1$","%2")) -- interesting pattern --- end - -local unquoted = patterns.squote * C(patterns.nosquote) * patterns.squote - + patterns.dquote * C(patterns.nodquote) * patterns.dquote - -function string.unquoted(str) - return lpegmatch(unquoted,str) or str -end - --- print(string.unquoted("test")) --- print(string.unquoted([["t\"est"]])) --- print(string.unquoted([["t\"est"x]])) --- print(string.unquoted("\'test\'")) --- print(string.unquoted('"test"')) --- print(string.unquoted('"test"')) - -function string.quoted(str) - return format("%q",str) -- always double quote -end - -function string.count(str,pattern) -- variant 3 - local n = 0 - for _ in gmatch(str,pattern) do -- not for utf - n = n + 1 - end - return n -end - -function string.limit(str,n,sentinel) -- not utf proof - if #str > n then - sentinel = sentinel or "..." - return sub(str,1,(n-#sentinel)) .. sentinel - else - return str - end -end - -local stripper = patterns.stripper -local fullstripper = patterns.fullstripper -local collapser = patterns.collapser -local longtostring = patterns.longtostring - -function string.strip(str) - return str and lpegmatch(stripper,str) or "" -end - -function string.fullstrip(str) - return str and lpegmatch(fullstripper,str) or "" -end - -function string.collapsespaces(str) - return str and lpegmatch(collapser,str) or "" -end - -function string.longtostring(str) - return str and lpegmatch(longtostring,str) or "" -end - --- function string.is_empty(str) --- return not find(str,"%S") --- end - -local pattern = P(" ")^0 * P(-1) -- maybe also newlines - --- patterns.onlyspaces = pattern - -function string.is_empty(str) - if not str or str == "" then - return true - else - return lpegmatch(pattern,str) and true or false - end -end - --- if not string.escapedpattern then --- --- local patterns_escapes = { --- ["%"] = "%%", --- ["."] = "%.", --- ["+"] = "%+", ["-"] = "%-", ["*"] = "%*", --- ["["] = "%[", ["]"] = "%]", --- ["("] = "%(", [")"] = "%)", --- -- ["{"] = "%{", ["}"] = "%}" --- -- ["^"] = "%^", ["$"] = "%$", --- } --- --- local simple_escapes = { --- ["-"] = "%-", --- ["."] = "%.", --- ["?"] = ".", --- ["*"] = ".*", --- } --- --- function string.escapedpattern(str,simple) --- return (gsub(str,".",simple and simple_escapes or patterns_escapes)) --- end --- --- function string.topattern(str,lowercase,strict) --- if str == "" then --- return ".*" --- else --- str = gsub(str,".",simple_escapes) --- if lowercase then --- str = lower(str) --- end --- if strict then --- return "^" .. str .. "$" --- else --- return str --- end --- end --- end --- --- end - ---- needs checking - -local anything = patterns.anything -local allescapes = Cc("%") * S(".-+%?()[]*") -- also {} and ^$ ? -local someescapes = Cc("%") * S(".-+%()[]") -- also {} and ^$ ? -local matchescapes = Cc(".") * S("*?") -- wildcard and single match - -local pattern_a = Cs ( ( allescapes + anything )^0 ) -local pattern_b = Cs ( ( someescapes + matchescapes + anything )^0 ) -local pattern_c = Cs ( Cc("^") * ( someescapes + matchescapes + anything )^0 * Cc("$") ) - -function string.escapedpattern(str,simple) - return lpegmatch(simple and pattern_b or pattern_a,str) -end - -function string.topattern(str,lowercase,strict) - if str == "" or type(str) ~= "string" then - return ".*" - elseif strict then - str = lpegmatch(pattern_c,str) - else - str = lpegmatch(pattern_b,str) - end - if lowercase then - return lower(str) - else - return str - end -end - --- print(string.escapedpattern("abc*234",true)) --- print(string.escapedpattern("12+34*.tex",false)) --- print(string.escapedpattern("12+34*.tex",true)) --- print(string.topattern ("12+34*.tex",false,false)) --- print(string.topattern ("12+34*.tex",false,true)) - -function string.valid(str,default) - return (type(str) == "string" and str ~= "" and str) or default or nil -end - --- handy fallback - -string.itself = function(s) return s end - --- also handy (see utf variant) - -local pattern_c = Ct( C(1) ^0) -- string and not utf ! -local pattern_b = Ct((C(1)/byte)^0) - -function string.totable(str,bytes) - return lpegmatch(bytes and pattern_b or pattern_c,str) -end - --- handy from within tex: - -local replacer = lpeg.replacer("@","%%") -- Watch the escaped % in lpeg! - -function string.tformat(fmt,...) - return format(lpegmatch(replacer,fmt),...) -end - --- obsolete names: - -string.quote = string.quoted -string.unquote = string.unquoted diff --git a/tex/compat/luaotfload/fontloader-l-table.lua b/tex/compat/luaotfload/fontloader-l-table.lua deleted file mode 100644 index 39357bd25e6da2283e106830e45ec1ffaf5c0bbd..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/fontloader-l-table.lua +++ /dev/null @@ -1,1328 +0,0 @@ -if not modules then modules = { } end modules ['l-table'] = { - version = 1.001, - comment = "companion to luat-lib.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -local type, next, tostring, tonumber, ipairs, select = type, next, tostring, tonumber, ipairs, select -local table, string = table, string -local concat, sort, insert, remove = table.concat, table.sort, table.insert, table.remove -local format, lower, dump = string.format, string.lower, string.dump -local getmetatable, setmetatable = getmetatable, setmetatable -local getinfo = debug.getinfo -local lpegmatch, patterns = lpeg.match, lpeg.patterns -local floor = math.floor - --- extra functions, some might go (when not used) --- --- we could serialize using %a but that won't work well is in the code we mostly use --- floats and as such we get unequality e.g. in version comparisons - -local stripper = patterns.stripper - -function table.strip(tab) - local lst, l = { }, 0 - for i=1,#tab do - local s = lpegmatch(stripper,tab[i]) or "" - if s == "" then - -- skip this one - else - l = l + 1 - lst[l] = s - end - end - return lst -end - -function table.keys(t) - if t then - local keys, k = { }, 0 - for key in next, t do - k = k + 1 - keys[k] = key - end - return keys - else - return { } - end -end - --- local function compare(a,b) --- local ta = type(a) -- needed, else 11 < 2 --- local tb = type(b) -- needed, else 11 < 2 --- if ta == tb and ta == "number" then --- return a < b --- else --- return tostring(a) < tostring(b) -- not that efficient --- end --- end - --- local function compare(a,b) --- local ta = type(a) -- needed, else 11 < 2 --- local tb = type(b) -- needed, else 11 < 2 --- if ta == tb and (ta == "number" or ta == "string") then --- return a < b --- else --- return tostring(a) < tostring(b) -- not that efficient --- end --- end - --- local function sortedkeys(tab) --- if tab then --- local srt, category, s = { }, 0, 0 -- 0=unknown 1=string, 2=number 3=mixed --- for key in next, tab do --- s = s + 1 --- srt[s] = key --- if category == 3 then --- -- no further check --- else --- local tkey = type(key) --- if tkey == "string" then --- category = (category == 2 and 3) or 1 --- elseif tkey == "number" then --- category = (category == 1 and 3) or 2 --- else --- category = 3 --- end --- end --- end --- if category == 0 or category == 3 then --- sort(srt,compare) --- else --- sort(srt) --- end --- return srt --- else --- return { } --- end --- end - --- local function compare(a,b) --- local ta = type(a) -- needed, else 11 < 2 --- local tb = type(b) -- needed, else 11 < 2 --- if ta == tb and (ta == "number" or ta == "string") then --- return a < b --- else --- return tostring(a) < tostring(b) -- not that efficient --- end --- end - --- local function compare(a,b) --- local ta = type(a) -- needed, else 11 < 2 --- if ta == "number" or ta == "string" then --- local tb = type(b) -- needed, else 11 < 2 --- if ta == tb then --- return a < b --- end --- end --- return tostring(a) < tostring(b) -- not that efficient --- end - -local function compare(a,b) - local ta = type(a) -- needed, else 11 < 2 - if ta == "number" then - local tb = type(b) -- needed, else 11 < 2 - if ta == tb then - return a < b - elseif tb == "string" then - return tostring(a) < b - end - elseif ta == "string" then - local tb = type(b) -- needed, else 11 < 2 - if ta == tb then - return a < b - else - return a < tostring(b) - end - end - return tostring(a) < tostring(b) -- not that efficient -end - -local function sortedkeys(tab) - if tab then - local srt, category, s = { }, 0, 0 -- 0=unknown 1=string, 2=number 3=mixed - for key in next, tab do - s = s + 1 - srt[s] = key - if category == 3 then - -- no further check - elseif category == 1 then - if type(key) ~= "string" then - category = 3 - end - elseif category == 2 then - if type(key) ~= "number" then - category = 3 - end - else - local tkey = type(key) - if tkey == "string" then - category = 1 - elseif tkey == "number" then - category = 2 - else - category = 3 - end - end - end - if s < 2 then - -- nothing to sort - elseif category == 3 then - sort(srt,compare) - else - sort(srt) - end - return srt - else - return { } - end -end - -local function sortedhashonly(tab) - if tab then - local srt, s = { }, 0 - for key in next, tab do - if type(key) == "string" then - s = s + 1 - srt[s] = key - end - end - if s > 1 then - sort(srt) - end - return srt - else - return { } - end -end - -local function sortedindexonly(tab) - if tab then - local srt, s = { }, 0 - for key in next, tab do - if type(key) == "number" then - s = s + 1 - srt[s] = key - end - end - if s > 1 then - sort(srt) - end - return srt - else - return { } - end -end - -local function sortedhashkeys(tab,cmp) -- fast one - if tab then - local srt, s = { }, 0 - for key in next, tab do - if key then - s= s + 1 - srt[s] = key - end - end - if s > 1 then - sort(srt,cmp) - end - return srt - else - return { } - end -end - -function table.allkeys(t) - local keys = { } - for k, v in next, t do - for k in next, v do - keys[k] = true - end - end - return sortedkeys(keys) -end - -table.sortedkeys = sortedkeys -table.sortedhashonly = sortedhashonly -table.sortedindexonly = sortedindexonly -table.sortedhashkeys = sortedhashkeys - -local function nothing() end - -local function sortedhash(t,cmp) - if t then - local s - if cmp then - -- it would be nice if the sort function would accept a third argument (or nicer, an optional first) - s = sortedhashkeys(t,function(a,b) return cmp(t,a,b) end) - else - s = sortedkeys(t) -- the robust one - end - local m = #s - if m == 1 then - return next, t - elseif m > 0 then - local n = 0 - return function() - if n < m then - n = n + 1 - local k = s[n] - return k, t[k] - end - end - end - end - return nothing -end - -table.sortedhash = sortedhash -table.sortedpairs = sortedhash -- obsolete - -function table.append(t,list) - local n = #t - for i=1,#list do - n = n + 1 - t[n] = list[i] - end - return t -end - -function table.prepend(t, list) - local nl = #list - local nt = nl + #t - for i=#t,1,-1 do - t[nt] = t[i] - nt = nt - 1 - end - for i=1,#list do - t[i] = list[i] - end - return t -end - --- function table.merge(t, ...) -- first one is target --- t = t or { } --- local lst = { ... } --- for i=1,#lst do --- for k, v in next, lst[i] do --- t[k] = v --- end --- end --- return t --- end - -function table.merge(t, ...) -- first one is target - t = t or { } - for i=1,select("#",...) do - for k, v in next, (select(i,...)) do - t[k] = v - end - end - return t -end - --- function table.merged(...) --- local tmp, lst = { }, { ... } --- for i=1,#lst do --- for k, v in next, lst[i] do --- tmp[k] = v --- end --- end --- return tmp --- end - -function table.merged(...) - local t = { } - for i=1,select("#",...) do - for k, v in next, (select(i,...)) do - t[k] = v - end - end - return t -end - --- function table.imerge(t, ...) --- local lst, nt = { ... }, #t --- for i=1,#lst do --- local nst = lst[i] --- for j=1,#nst do --- nt = nt + 1 --- t[nt] = nst[j] --- end --- end --- return t --- end - -function table.imerge(t, ...) - local nt = #t - for i=1,select("#",...) do - local nst = select(i,...) - for j=1,#nst do - nt = nt + 1 - t[nt] = nst[j] - end - end - return t -end - --- function table.imerged(...) --- local tmp, ntmp, lst = { }, 0, {...} --- for i=1,#lst do --- local nst = lst[i] --- for j=1,#nst do --- ntmp = ntmp + 1 --- tmp[ntmp] = nst[j] --- end --- end --- return tmp --- end - -function table.imerged(...) - local tmp, ntmp = { }, 0 - for i=1,select("#",...) do - local nst = select(i,...) - for j=1,#nst do - ntmp = ntmp + 1 - tmp[ntmp] = nst[j] - end - end - return tmp -end - -local function fastcopy(old,metatabletoo) -- fast one - if old then - local new = { } - for k, v in next, old do - if type(v) == "table" then - new[k] = fastcopy(v,metatabletoo) -- was just table.copy - else - new[k] = v - end - end - if metatabletoo then - -- optional second arg - local mt = getmetatable(old) - if mt then - setmetatable(new,mt) - end - end - return new - else - return { } - end -end - --- todo : copy without metatable - -local function copy(t, tables) -- taken from lua wiki, slightly adapted - tables = tables or { } - local tcopy = { } - if not tables[t] then - tables[t] = tcopy - end - for i,v in next, t do -- brrr, what happens with sparse indexed - if type(i) == "table" then - if tables[i] then - i = tables[i] - else - i = copy(i, tables) - end - end - if type(v) ~= "table" then - tcopy[i] = v - elseif tables[v] then - tcopy[i] = tables[v] - else - tcopy[i] = copy(v, tables) - end - end - local mt = getmetatable(t) - if mt then - setmetatable(tcopy,mt) - end - return tcopy -end - -table.fastcopy = fastcopy -table.copy = copy - -function table.derive(parent) -- for the moment not public - local child = { } - if parent then - setmetatable(child,{ __index = parent }) - end - return child -end - -function table.tohash(t,value) - local h = { } - if t then - if value == nil then value = true end - for _, v in next, t do -- no ipairs here - h[v] = value - end - end - return h -end - -function table.fromhash(t) - local hsh, h = { }, 0 - for k, v in next, t do -- no ipairs here - if v then - h = h + 1 - hsh[h] = k - end - end - return hsh -end - -local noquotes, hexify, handle, compact, inline, functions, metacheck - -local reserved = table.tohash { -- intercept a language inconvenience: no reserved words as key - 'and', 'break', 'do', 'else', 'elseif', 'end', 'false', 'for', 'function', 'if', - 'in', 'local', 'nil', 'not', 'or', 'repeat', 'return', 'then', 'true', 'until', 'while', - 'NaN', 'goto', -} - --- local function simple_table(t) --- if #t > 0 then --- local n = 0 --- for _,v in next, t do --- n = n + 1 --- end --- if n == #t then --- local tt, nt = { }, 0 --- for i=1,#t do --- local v = t[i] --- local tv = type(v) --- if tv == "number" then --- nt = nt + 1 --- if hexify then --- tt[nt] = format("0x%X",v) --- else --- tt[nt] = tostring(v) -- tostring not needed --- end --- elseif tv == "string" then --- nt = nt + 1 --- tt[nt] = format("%q",v) --- elseif tv == "boolean" then --- nt = nt + 1 --- tt[nt] = v and "true" or "false" --- else --- return nil --- end --- end --- return tt --- end --- end --- return nil --- end - -local function simple_table(t) - local nt = #t - if nt > 0 then - local n = 0 - for _,v in next, t do - n = n + 1 - -- if type(v) == "table" then - -- return nil - -- end - end - if n == nt then - local tt = { } - for i=1,nt do - local v = t[i] - local tv = type(v) - if tv == "number" then - if hexify then - tt[i] = format("0x%X",v) - else - tt[i] = tostring(v) -- tostring not needed - end - elseif tv == "string" then - tt[i] = format("%q",v) - elseif tv == "boolean" then - tt[i] = v and "true" or "false" - else - return nil - end - end - return tt - end - end - return nil -end - --- Because this is a core function of mkiv I moved some function calls --- inline. --- --- twice as fast in a test: --- --- local propername = lpeg.P(lpeg.R("AZ","az","__") * lpeg.R("09","AZ","az", "__")^0 * lpeg.P(-1) ) - --- problem: there no good number_to_string converter with the best resolution - --- probably using .. is faster than format --- maybe split in a few cases (yes/no hexify) - --- todo: %g faster on numbers than %s - --- we can speed this up with repeaters and formatters but we haven't defined them --- yet - -local propername = patterns.propername -- was find(name,"^%a[%w%_]*$") - -local function dummy() end - -local function do_serialize(root,name,depth,level,indexed) - if level > 0 then - depth = depth .. " " - if indexed then - handle(format("%s{",depth)) - else - local tn = type(name) - if tn == "number" then - if hexify then - handle(format("%s[0x%X]={",depth,name)) - else - handle(format("%s[%s]={",depth,name)) - end - elseif tn == "string" then - if noquotes and not reserved[name] and lpegmatch(propername,name) then - handle(format("%s%s={",depth,name)) - else - handle(format("%s[%q]={",depth,name)) - end - elseif tn == "boolean" then - handle(format("%s[%s]={",depth,name and "true" or "false")) - else - handle(format("%s{",depth)) - end - end - end - -- we could check for k (index) being number (cardinal) - if root and next(root) ~= nil then - local first, last = nil, 0 - if compact then - last = #root - for k=1,last do - -- if root[k] == nil then - if rawget(root,k) == nil then - last = k - 1 - break - end - end - if last > 0 then - first = 1 - end - end - local sk = sortedkeys(root) - for i=1,#sk do - local k = sk[i] - local v = root[k] - local tv = type(v) - local tk = type(k) - if compact and first and tk == "number" and k >= first and k <= last then - if tv == "number" then - if hexify then - handle(format("%s 0x%X,",depth,v)) - else - handle(format("%s %s,",depth,v)) -- %.99g - end - elseif tv == "string" then - handle(format("%s %q,",depth,v)) - elseif tv == "table" then - if next(v) == nil then - handle(format("%s {},",depth)) - elseif inline then -- and #t > 0 - local st = simple_table(v) - if st then - handle(format("%s { %s },",depth,concat(st,", "))) - else - do_serialize(v,k,depth,level+1,true) - end - else - do_serialize(v,k,depth,level+1,true) - end - elseif tv == "boolean" then - handle(format("%s %s,",depth,v and "true" or "false")) - elseif tv == "function" then - if functions then - handle(format('%s load(%q),',depth,dump(v))) -- maybe strip - else - handle(format('%s "function",',depth)) - end - else - handle(format("%s %q,",depth,tostring(v))) - end - elseif k == "__p__" then -- parent - if false then - handle(format("%s __p__=nil,",depth)) - end - elseif tv == "number" then - if tk == "number" then - if hexify then - handle(format("%s [0x%X]=0x%X,",depth,k,v)) - else - handle(format("%s [%s]=%s,",depth,k,v)) -- %.99g - end - elseif tk == "boolean" then - if hexify then - handle(format("%s [%s]=0x%X,",depth,k and "true" or "false",v)) - else - handle(format("%s [%s]=%s,",depth,k and "true" or "false",v)) -- %.99g - end - elseif tk ~= "string" then - -- ignore - elseif noquotes and not reserved[k] and lpegmatch(propername,k) then - if hexify then - handle(format("%s %s=0x%X,",depth,k,v)) - else - handle(format("%s %s=%s,",depth,k,v)) -- %.99g - end - else - if hexify then - handle(format("%s [%q]=0x%X,",depth,k,v)) - else - handle(format("%s [%q]=%s,",depth,k,v)) -- %.99g - end - end - elseif tv == "string" then - if tk == "number" then - if hexify then - handle(format("%s [0x%X]=%q,",depth,k,v)) - else - handle(format("%s [%s]=%q,",depth,k,v)) - end - elseif tk == "boolean" then - handle(format("%s [%s]=%q,",depth,k and "true" or "false",v)) - elseif tk ~= "string" then - -- ignore - elseif noquotes and not reserved[k] and lpegmatch(propername,k) then - handle(format("%s %s=%q,",depth,k,v)) - else - handle(format("%s [%q]=%q,",depth,k,v)) - end - elseif tv == "table" then - if next(v) == nil then - if tk == "number" then - if hexify then - handle(format("%s [0x%X]={},",depth,k)) - else - handle(format("%s [%s]={},",depth,k)) - end - elseif tk == "boolean" then - handle(format("%s [%s]={},",depth,k and "true" or "false")) - elseif tk ~= "string" then - -- ignore - elseif noquotes and not reserved[k] and lpegmatch(propername,k) then - handle(format("%s %s={},",depth,k)) - else - handle(format("%s [%q]={},",depth,k)) - end - elseif inline then - local st = simple_table(v) - if st then - if tk == "number" then - if hexify then - handle(format("%s [0x%X]={ %s },",depth,k,concat(st,", "))) - else - handle(format("%s [%s]={ %s },",depth,k,concat(st,", "))) - end - elseif tk == "boolean" then - handle(format("%s [%s]={ %s },",depth,k and "true" or "false",concat(st,", "))) - elseif tk ~= "string" then - -- ignore - elseif noquotes and not reserved[k] and lpegmatch(propername,k) then - handle(format("%s %s={ %s },",depth,k,concat(st,", "))) - else - handle(format("%s [%q]={ %s },",depth,k,concat(st,", "))) - end - else - do_serialize(v,k,depth,level+1) - end - else - do_serialize(v,k,depth,level+1) - end - elseif tv == "boolean" then - if tk == "number" then - if hexify then - handle(format("%s [0x%X]=%s,",depth,k,v and "true" or "false")) - else - handle(format("%s [%s]=%s,",depth,k,v and "true" or "false")) - end - elseif tk == "boolean" then - handle(format("%s [%s]=%s,",depth,tostring(k),v and "true" or "false")) - elseif tk ~= "string" then - -- ignore - elseif noquotes and not reserved[k] and lpegmatch(propername,k) then - handle(format("%s %s=%s,",depth,k,v and "true" or "false")) - else - handle(format("%s [%q]=%s,",depth,k,v and "true" or "false")) - end - elseif tv == "function" then - if functions then - local f = getinfo(v).what == "C" and dump(dummy) or dump(v) -- maybe strip - -- local f = getinfo(v).what == "C" and dump(function(...) return v(...) end) or dump(v) -- maybe strip - if tk == "number" then - if hexify then - handle(format("%s [0x%X]=load(%q),",depth,k,f)) - else - handle(format("%s [%s]=load(%q),",depth,k,f)) - end - elseif tk == "boolean" then - handle(format("%s [%s]=load(%q),",depth,k and "true" or "false",f)) - elseif tk ~= "string" then - -- ignore - elseif noquotes and not reserved[k] and lpegmatch(propername,k) then - handle(format("%s %s=load(%q),",depth,k,f)) - else - handle(format("%s [%q]=load(%q),",depth,k,f)) - end - end - else - if tk == "number" then - if hexify then - handle(format("%s [0x%X]=%q,",depth,k,tostring(v))) - else - handle(format("%s [%s]=%q,",depth,k,tostring(v))) - end - elseif tk == "boolean" then - handle(format("%s [%s]=%q,",depth,k and "true" or "false",tostring(v))) - elseif tk ~= "string" then - -- ignore - elseif noquotes and not reserved[k] and lpegmatch(propername,k) then - handle(format("%s %s=%q,",depth,k,tostring(v))) - else - handle(format("%s [%q]=%q,",depth,k,tostring(v))) - end - end - end - end - if level > 0 then - handle(format("%s},",depth)) - end -end - --- replacing handle by a direct t[#t+1] = ... (plus test) is not much --- faster (0.03 on 1.00 for zapfino.tma) - -local function serialize(_handle,root,name,specification) -- handle wins - local tname = type(name) - if type(specification) == "table" then - noquotes = specification.noquotes - hexify = specification.hexify - handle = _handle or specification.handle or print - functions = specification.functions - compact = specification.compact - inline = specification.inline and compact - metacheck = specification.metacheck - if functions == nil then - functions = true - end - if compact == nil then - compact = true - end - if inline == nil then - inline = compact - end - if metacheck == nil then - metacheck = true - end - else - noquotes = false - hexify = false - handle = _handle or print - compact = true - inline = true - functions = true - metacheck = true - end - if tname == "string" then - if name == "return" then - handle("return {") - else - handle(name .. "={") - end - elseif tname == "number" then - if hexify then - handle(format("[0x%X]={",name)) - else - handle("[" .. name .. "]={") - end - elseif tname == "boolean" then - if name then - handle("return {") - else - handle("{") - end - else - handle("t={") - end - if root then - -- The dummy access will initialize a table that has a delayed initialization - -- using a metatable. (maybe explicitly test for metatable). This can crash on - -- metatables that check the index against a number. - if metacheck and getmetatable(root) then - local dummy = root._w_h_a_t_e_v_e_r_ - root._w_h_a_t_e_v_e_r_ = nil - end - -- Let's forget about empty tables. - if next(root) ~= nil then - do_serialize(root,name,"",0) - end - end - handle("}") -end - --- A version with formatters is some 20% faster than using format (because formatters are --- much faster) but of course, inlining the format using .. is then again faster .. anyway, --- as we do some pretty printing as well there is not that much to gain unless we make a --- 'fast' ugly variant as well. But, we would have to move the formatter to l-string then. - --- name: --- --- true : return { } --- false : { } --- nil : t = { } --- string : string = { } --- "return" : return { } --- number : [number] = { } - -function table.serialize(root,name,specification) - local t, n = { }, 0 - local function flush(s) - n = n + 1 - t[n] = s - end - serialize(flush,root,name,specification) - return concat(t,"\n") -end - --- local a = { e = { 1,2,3,4,5,6}, a = 1, b = 2, c = "ccc", d = { a = 1, b = 2, c = "ccc", d = { a = 1, b = 2, c = "ccc" } } } --- local t = os.clock() --- for i=1,10000 do --- table.serialize(a) --- end --- print(os.clock()-t,table.serialize(a)) - -table.tohandle = serialize - -local maxtab = 2*1024 - -function table.tofile(filename,root,name,specification) - local f = io.open(filename,'w') - if f then - if maxtab > 1 then - local t, n = { }, 0 - local function flush(s) - n = n + 1 - t[n] = s - if n > maxtab then - f:write(concat(t,"\n"),"\n") -- hm, write(sometable) should be nice - t, n = { }, 0 -- we could recycle t if needed - end - end - serialize(flush,root,name,specification) - f:write(concat(t,"\n"),"\n") - else - local function flush(s) - f:write(s,"\n") - end - serialize(flush,root,name,specification) - end - f:close() - io.flush() - end -end - -local function flattened(t,f,depth) -- also handles { nil, 1, nil, 2 } - if f == nil then - f = { } - depth = 0xFFFF - elseif tonumber(f) then - -- assume that only two arguments are given - depth = f - f = { } - elseif not depth then - depth = 0xFFFF - end - for k, v in next, t do - if type(k) ~= "number" then - if depth > 0 and type(v) == "table" then - flattened(v,f,depth-1) - else - f[#f+1] = v - end - end - end - for k=1,#t do - local v = t[k] - if depth > 0 and type(v) == "table" then - flattened(v,f,depth-1) - else - f[#f+1] = v - end - end - return f -end - -table.flattened = flattened - -local function collapsed(t,f,h) - if f == nil then - f = { } - h = { } - end - for k=1,#t do - local v = t[k] - if type(v) == "table" then - collapsed(v,f,h) - elseif not h[v] then - f[#f+1] = v - h[v] = true - end - end - return f -end - -local function collapsedhash(t,h) - if h == nil then - h = { } - end - for k=1,#t do - local v = t[k] - if type(v) == "table" then - collapsedhash(v,h) - else - h[v] = true - end - end - return h -end - -table.collapsed = collapsed -- 20% faster than unique(collapsed(t)) -table.collapsedhash = collapsedhash - -local function unnest(t,f) -- only used in mk, for old times sake - if not f then -- and only relevant for token lists - f = { } -- this one can become obsolete - end - for i=1,#t do - local v = t[i] - if type(v) == "table" then - if type(v[1]) == "table" then - unnest(v,f) - else - f[#f+1] = v - end - else - f[#f+1] = v - end - end - return f -end - -function table.unnest(t) -- bad name - return unnest(t) -end - -local function are_equal(a,b,n,m) -- indexed - if a and b and #a == #b then - n = n or 1 - m = m or #a - for i=n,m do - local ai, bi = a[i], b[i] - if ai==bi then - -- same - elseif type(ai) == "table" and type(bi) == "table" then - if not are_equal(ai,bi) then - return false - end - else - return false - end - end - return true - else - return false - end -end - -local function identical(a,b) -- assumes same structure - for ka, va in next, a do - local vb = b[ka] - if va == vb then - -- same - elseif type(va) == "table" and type(vb) == "table" then - if not identical(va,vb) then - return false - end - else - return false - end - end - return true -end - -table.identical = identical -table.are_equal = are_equal - -local function sparse(old,nest,keeptables) - local new = { } - for k, v in next, old do - if not (v == "" or v == false) then - if nest and type(v) == "table" then - v = sparse(v,nest) - if keeptables or next(v) ~= nil then - new[k] = v - end - else - new[k] = v - end - end - end - return new -end - -table.sparse = sparse - -function table.compact(t) - return sparse(t,true,true) -end - -function table.contains(t, v) - if t then - for i=1, #t do - if t[i] == v then - return i - end - end - end - return false -end - -function table.count(t) - local n = 0 - for k, v in next, t do - n = n + 1 - end - return n -end - -function table.swapped(t,s) -- hash, we need to make sure we don't mess up next - local n = { } - if s then - for k, v in next, s do - n[k] = v - end - end - for k, v in next, t do - n[v] = k - end - return n -end - -function table.hashed(t) -- list, add hash to index (save because we are not yet mixed - for i=1,#t do - t[t[i]] = i - end - return t -end - -function table.mirrored(t) -- hash, we need to make sure we don't mess up next - local n = { } - for k, v in next, t do - n[v] = k - n[k] = v - end - return n -end - -function table.reversed(t) - if t then - local tt, tn = { }, #t - if tn > 0 then - local ttn = 0 - for i=tn,1,-1 do - ttn = ttn + 1 - tt[ttn] = t[i] - end - end - return tt - end -end - -function table.reverse(t) - if t then - local n = #t - for i=1,floor(n/2) do - local j = n - i + 1 - t[i], t[j] = t[j], t[i] - end - return t - end -end - -function table.sequenced(t,sep,simple) -- hash only - if not t then - return "" - end - local n = #t - local s = { } - if n > 0 then - -- indexed - for i=1,n do - s[i] = tostring(t[i]) - end - else - -- hashed - n = 0 - for k, v in sortedhash(t) do - if simple then - if v == true then - n = n + 1 - s[n] = k - elseif v and v~= "" then - n = n + 1 - s[n] = k .. "=" .. tostring(v) - end - else - n = n + 1 - s[n] = k .. "=" .. tostring(v) - end - end - end - return concat(s,sep or " | ") -end - -function table.print(t,...) - if type(t) ~= "table" then - print(tostring(t)) - else - serialize(print,t,...) - end -end - -if setinspector then - setinspector("table",function(v) if type(v) == "table" then serialize(print,v,"table") return true end end) -end - --- -- -- obsolete but we keep them for a while and might comment them later -- -- -- - --- roughly: copy-loop : unpack : sub == 0.9 : 0.4 : 0.45 (so in critical apps, use unpack) - -function table.sub(t,i,j) - return { unpack(t,i,j) } -end - --- slower than #t on indexed tables (#t only returns the size of the numerically indexed slice) - -function table.is_empty(t) - return not t or next(t) == nil -end - -function table.has_one_entry(t) - return t and next(t,next(t)) == nil -end - --- new (rather basic, not indexed and nested) - -function table.loweredkeys(t) -- maybe utf - local l = { } - for k, v in next, t do - l[lower(k)] = v - end - return l -end - --- new, might move (maybe duplicate) - -function table.unique(old) - local hash = { } - local new = { } - local n = 0 - for i=1,#old do - local oi = old[i] - if not hash[oi] then - n = n + 1 - new[n] = oi - hash[oi] = true - end - end - return new -end - -function table.sorted(t,...) - sort(t,...) - return t -- still sorts in-place -end - --- - -function table.values(t,s) -- optional sort flag - if t then - local values, keys, v = { }, { }, 0 - for key, value in next, t do - if not keys[value] then - v = v + 1 - values[v] = value - keys[k] = key - end - end - if s then - sort(values) - end - return values - else - return { } - end -end - --- maybe this will move to util-tab.lua - --- for k, v in table.filtered(t,pattern) do ... end --- for k, v in table.filtered(t,pattern,true) do ... end --- for k, v in table.filtered(t,pattern,true,cmp) do ... end - -function table.filtered(t,pattern,sort,cmp) - if t and type(pattern) == "string" then - if sort then - local s - if cmp then - -- it would be nice if the sort function would accept a third argument (or nicer, an optional first) - s = sortedhashkeys(t,function(a,b) return cmp(t,a,b) end) - else - s = sortedkeys(t) -- the robust one - end - local n = 0 - local m = #s - local function kv(s) - while n < m do - n = n + 1 - local k = s[n] - if find(k,pattern) then - return k, t[k] - end - end - end - return kv, s - else - local n = next(t) - local function iterator() - while n ~= nil do - local k = n - n = next(t,k) - if find(k,pattern) then - return k, t[k] - end - end - end - return iterator, t - end - else - return nothing - end -end diff --git a/tex/compat/luaotfload/fontloader-languages.lua b/tex/compat/luaotfload/fontloader-languages.lua deleted file mode 100644 index cecd60c1331694de57ce584ccc2ba1ebf317d12e..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/fontloader-languages.lua +++ /dev/null @@ -1,50 +0,0 @@ -if not modules then modules = { } end modules ['luatex-languages'] = { - version = 1.001, - comment = "companion to luatex-languages.tex", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- We borrow from ConTeXt. - -languages = languages or { } - -local loaded = { } - -function languages.loadpatterns(tag) - if not loaded[tag] then - loaded[tag] = 0 - local filename = kpse.find_file("lang-" .. tag .. ".lua") - if not filename or filename == "" then - texio.write("<unknown language file for: " .. tag .. ">") - else - local whatever = loadfile(filename) - if type(whatever) == "function" then - whatever = whatever() - if type(whatever) == "table" then - texio.write("<language file: " .. tag .. ">") - local characters = whatever.patterns.characters or "" - local patterns = whatever.patterns.data or "" - local exceptions = whatever.exceptions.data or "" - for b in string.utfvalues(characters) do - -- what about uppercase --- lang.sethjcode(b,b) - tex.setlccode(b,b) - end - local language = lang.new() - lang.patterns(language, patterns) - lang.hyphenation(language, exceptions) - loaded[tag] = lang.id(language) - else - texio.write("<invalid language table: " .. tag .. ">") - os.exit() - end - else - texio.write("<invalid language file: " .. tag .. ">") - os.exit() - end - end - end - return loaded[tag] -end diff --git a/tex/compat/luaotfload/fontloader-languages.tex b/tex/compat/luaotfload/fontloader-languages.tex deleted file mode 100644 index a087b30939a867b8a19285cbc141a65d4579b31a..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/fontloader-languages.tex +++ /dev/null @@ -1,19 +0,0 @@ -%D \module -%D [ file=luatex-fonts, -%D version=2009.12.01, -%D title=\LUATEX\ Support Macros, -%D subtitle=Generic \OPENTYPE\ Font Handler, -%D author=Hans Hagen, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] - -%D Cf. discussion on \CONTEXT\ list: - -% \savinghyphcodes1 - -\directlua { - dofile(kpse.find_file("luatex-languages.lua","tex")) -} - -\def\loadpatterns#1{\directlua{tex.language = languages.loadpatterns("#1")}} - -\endinput diff --git a/tex/compat/luaotfload/fontloader-math.lua b/tex/compat/luaotfload/fontloader-math.lua deleted file mode 100644 index c316182ba3215afd6c95519dfe0ebccedefa98a6..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/fontloader-math.lua +++ /dev/null @@ -1,53 +0,0 @@ -if not modules then modules = { } end modules ['luatex-math'] = { - version = 1.001, - comment = "companion to luatex-math.tex", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -local gaps = { - [0x1D455] = 0x0210E, - [0x1D49D] = 0x0212C, - [0x1D4A0] = 0x02130, - [0x1D4A1] = 0x02131, - [0x1D4A3] = 0x0210B, - [0x1D4A4] = 0x02110, - [0x1D4A7] = 0x02112, - [0x1D4A8] = 0x02133, - [0x1D4AD] = 0x0211B, - [0x1D4BA] = 0x0212F, - [0x1D4BC] = 0x0210A, - [0x1D4C4] = 0x02134, - [0x1D506] = 0x0212D, - [0x1D50B] = 0x0210C, - [0x1D50C] = 0x02111, - [0x1D515] = 0x0211C, - [0x1D51D] = 0x02128, - [0x1D53A] = 0x02102, - [0x1D53F] = 0x0210D, - [0x1D545] = 0x02115, - [0x1D547] = 0x02119, - [0x1D548] = 0x0211A, - [0x1D549] = 0x0211D, - [0x1D551] = 0x02124, -} - - -local function fixmath(tfmdata,key,value) - if value then - local characters = tfmdata.characters - for gap, mess in pairs(gaps) do - characters[gap] = characters[mess] - end - end -end - -fonts.handlers.otf.features.register { - name = "fixmath", - description = "math font fixing", - manipulators = { - base = fixmath, - node = fixmath, - } -} diff --git a/tex/compat/luaotfload/fontloader-math.tex b/tex/compat/luaotfload/fontloader-math.tex deleted file mode 100644 index b24902100a1f9c12f56364e2d06ca60ef9e034b8..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/fontloader-math.tex +++ /dev/null @@ -1,1874 +0,0 @@ -%D \module -%D [ file=luatex-math, -%D version=2013.04.29, -%D title=\LUATEX\ Support Macros, -%D subtitle=An exmaple of math, -%D author=Hans Hagen, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] - -%D This module is in no way a complete plain math implementation. I made this file -%D because I needed it for a tutorial for (mostly) plain \TEX\ users. There are -%D several ways to support math in \LUATEX, and this is just one of them. It was the -%D quickest hack I could come up with and it stays somewhat close to the traditional -%D approach (and thereby far from the \CONTEXT\ way). This file is mainly meant for -%D Boguslaw Jackowski. - -% we provide a remap feature - -\directlua{dofile(kpse.find_file('luatex-math.lua'))} - -% a bunch of fonts: - -\let \teni = \relax -\let \seveni = \relax -\let \fivei = \relax -\let \tensy = \relax -\let \sevensy = \relax -\let \fivesy = \relax -\let \tenex = \relax -\let \sevenbf = \relax -\let \fivebf = \relax - -\def\latinmodern - {\font\tenrm = file:lmroman10-regular.otf:+liga;+kern;+tlig;+trep at 10pt - \font\sevenrm = file:lmroman7-regular.otf:+liga;+kern;+tlig;+trep at 7pt - \font\fiverm = file:lmroman5-regular.otf:+liga;+kern;+tlig;+trep at 5pt - % - \font\tentt = file:lmmono10-regular.otf at 10pt - \font\tensl = file:lmromanslant10-regular.otf:+liga;+kern;+tlig;+trep at 10pt - \font\tenit = file:lmroman10-italic.otf:+liga;+kern;+tlig;+trep at 10pt - \font\tenbf = file:lmroman10-bold.otf:+liga;+kern;+tlig;+trep at 10pt - \font\tenbi = file:lmroman10-bolditalic.otf:+liga;+kern;+tlig;+trep at 10pt - % - \font\mathfonttextupright = file:latinmodern-math.otf:script=math;ssty=0;mathsize=yes at 10pt - \font\mathfontscriptupright = file:latinmodern-math.otf:script=math;ssty=1;mathsize=yes at 7pt - \font\mathfontscriptscriptupright = file:latinmodern-math.otf:script=math;ssty=2;mathsize=yes at 5pt - % - \textfont 0 = \mathfonttextupright - \scriptfont 0 = \mathfontscriptupright - \scriptscriptfont 0 = \mathfontscriptscriptupright - % - \tenrm} - -\def\lucidabright - {\font\tenrm = file:lucidabrightot.otf:+liga;+kern;+tlig;+trep at 10pt - \font\sevenrm = file:lucidabrightot.otf:+liga;+kern;+tlig;+trep at 7pt - \font\fiverm = file:lucidabrightot.otf:+liga;+kern;+tlig;+trep at 5pt - % - \font\tentt = file:lucidabrightot.otf at 10pt - \font\tenit = file:lucidabrightot.otf:+liga;+kern;+tlig;+trep at 10pt - \font\tenit = file:lucidabrightot-italic.otf:+liga;+kern;+tlig;+trep at 10pt - \font\tenbf = file:lucidabrightot-demi.otf:+liga;+kern;+tlig;+trep at 10pt - \font\tenbi = file:lucidabrightot-demiitalic.otf:+liga;+kern;+tlig;+trep at 10pt - % - \font\mathfonttextupright = file:lucidabrightmathot.otf:script=math;ssty=0;mathsize=yes at 10pt - \font\mathfontscriptupright = file:lucidabrightmathot.otf:script=math;ssty=1;mathsize=yes at 7pt - \font\mathfontscriptscriptupright = file:lucidabrightmathot.otf:script=math;ssty=2;mathsize=yes at 5pt - % - \textfont 0 = \mathfonttextupright - \scriptfont 0 = \mathfontscriptupright - \scriptscriptfont 0 = \mathfontscriptscriptupright - % - \tenrm} - -\directlua { - if arguments["mtx:lucidabright"] then - tex.print("\string\\lucidabright") - else - tex.print("\string\\latinmodern") - end -} - -\newtoks\everymathrm -\newtoks\everymathmit -\newtoks\everymathcal -\newtoks\everymathit -\newtoks\everymathsl -\newtoks\everymathbf -\newtoks\everymathbi -\newtoks\everymathtt - -\def\rm{\fam0\relax\the\everymathrm\relax\tenrm\relax} -\def\it{\fam0\relax\the\everymathit\relax\tenit\relax} -\def\sl{\fam0\relax\the\everymathsl\relax\tensl\relax} -\def\bf{\fam0\relax\the\everymathbf\relax\tenbf\relax} -\def\bi{\fam0\relax\the\everymathbi\relax\tenbi\relax} -\def\tt{\fam0\relax\the\everymathtt\relax\tentt\relax} - -\let\mit \relax % use names or \Uchar or define a vector -\let\cal \relax % idem, i'm not in the mood for this now -\let\oldstyle\relax % no longer misuse of math mode - -% tex is fast enough for this kind of assignments: - -\everymathrm {% - \Umathcode"0041="0"0"0041% - \Umathcode"0042="0"0"0042% - \Umathcode"0043="0"0"0043% - \Umathcode"0044="0"0"0044% - \Umathcode"0045="0"0"0045% - \Umathcode"0046="0"0"0046% - \Umathcode"0047="0"0"0047% - \Umathcode"0048="0"0"0048% - \Umathcode"0049="0"0"0049% - \Umathcode"004A="0"0"004A% - \Umathcode"004B="0"0"004B% - \Umathcode"004C="0"0"004C% - \Umathcode"004D="0"0"004D% - \Umathcode"004E="0"0"004E% - \Umathcode"004F="0"0"004F% - \Umathcode"0050="0"0"0050% - \Umathcode"0051="0"0"0051% - \Umathcode"0052="0"0"0052% - \Umathcode"0053="0"0"0053% - \Umathcode"0054="0"0"0054% - \Umathcode"0055="0"0"0055% - \Umathcode"0056="0"0"0056% - \Umathcode"0057="0"0"0057% - \Umathcode"0058="0"0"0058% - \Umathcode"0059="0"0"0059% - \Umathcode"005A="0"0"005A% - \Umathcode"0061="0"0"0061% - \Umathcode"0062="0"0"0062% - \Umathcode"0063="0"0"0063% - \Umathcode"0064="0"0"0064% - \Umathcode"0065="0"0"0065% - \Umathcode"0066="0"0"0066% - \Umathcode"0067="0"0"0067% - \Umathcode"0068="0"0"0068% - \Umathcode"0069="0"0"0069% - \Umathcode"006A="0"0"006A% - \Umathcode"006B="0"0"006B% - \Umathcode"006C="0"0"006C% - \Umathcode"006D="0"0"006D% - \Umathcode"006E="0"0"006E% - \Umathcode"006F="0"0"006F% - \Umathcode"0070="0"0"0070% - \Umathcode"0071="0"0"0071% - \Umathcode"0072="0"0"0072% - \Umathcode"0073="0"0"0073% - \Umathcode"0074="0"0"0074% - \Umathcode"0075="0"0"0075% - \Umathcode"0076="0"0"0076% - \Umathcode"0077="0"0"0077% - \Umathcode"0078="0"0"0078% - \Umathcode"0079="0"0"0079% - \Umathcode"007A="0"0"007A% - \Umathcode"0391="0"0"0391% - \Umathcode"0392="0"0"0392% - \Umathcode"0393="0"0"0393% - \Umathcode"0394="0"0"0394% - \Umathcode"0395="0"0"0395% - \Umathcode"0396="0"0"0396% - \Umathcode"0397="0"0"0397% - \Umathcode"0398="0"0"0398% - \Umathcode"0399="0"0"0399% - \Umathcode"039A="0"0"039A% - \Umathcode"039B="0"0"039B% - \Umathcode"039C="0"0"039C% - \Umathcode"039D="0"0"039D% - \Umathcode"039E="0"0"039E% - \Umathcode"039F="0"0"039F% - \Umathcode"03A0="0"0"03A0% - \Umathcode"03A1="0"0"03A1% - \Umathcode"03A3="0"0"03A3% - \Umathcode"03A4="0"0"03A4% - \Umathcode"03A5="0"0"03A5% - \Umathcode"03A6="0"0"03A6% - \Umathcode"03A7="0"0"03A7% - \Umathcode"03A8="0"0"03A8% - \Umathcode"03A9="0"0"03A9% - \Umathcode"03B1="0"0"03B1% - \Umathcode"03B2="0"0"03B2% - \Umathcode"03B3="0"0"03B3% - \Umathcode"03B4="0"0"03B4% - \Umathcode"03B5="0"0"03B5% - \Umathcode"03B6="0"0"03B6% - \Umathcode"03B7="0"0"03B7% - \Umathcode"03B8="0"0"03B8% - \Umathcode"03B9="0"0"03B9% - \Umathcode"03BA="0"0"03BA% - \Umathcode"03BB="0"0"03BB% - \Umathcode"03BC="0"0"03BC% - \Umathcode"03BD="0"0"03BD% - \Umathcode"03BE="0"0"03BE% - \Umathcode"03BF="0"0"03BF% - \Umathcode"03C0="0"0"03C0% - \Umathcode"03C1="0"0"03C1% - \Umathcode"03C2="0"0"03C2% - \Umathcode"03C3="0"0"03C3% - \Umathcode"03C4="0"0"03C4% - \Umathcode"03C5="0"0"03C5% - \Umathcode"03C6="0"0"03C6% - \Umathcode"03C7="0"0"03C7% - \Umathcode"03C8="0"0"03C8% - \Umathcode"03C9="0"0"03C9% - \Umathcode"03D1="0"0"03D1% - \Umathcode"03D5="0"0"03D5% - \Umathcode"03D6="0"0"03D6% - \Umathcode"03F0="0"0"03F0% - \Umathcode"03F1="0"0"03F1% - \Umathcode"03F4="0"0"03F4% - \Umathcode"03F5="0"0"03F5% - \Umathcode"2202="0"0"2202% - \Umathcode"2207="0"0"2207% - \relax -} - -\everymathmit {% - % not done -} - -\everymathcal {% - % not done -} - -\everymathit {% - \Umathcode"0041="0"0"1D434% - \Umathcode"0042="0"0"1D435% - \Umathcode"0043="0"0"1D436% - \Umathcode"0044="0"0"1D437% - \Umathcode"0045="0"0"1D438% - \Umathcode"0046="0"0"1D439% - \Umathcode"0047="0"0"1D43A% - \Umathcode"0048="0"0"1D43B% - \Umathcode"0049="0"0"1D43C% - \Umathcode"004A="0"0"1D43D% - \Umathcode"004B="0"0"1D43E% - \Umathcode"004C="0"0"1D43F% - \Umathcode"004D="0"0"1D440% - \Umathcode"004E="0"0"1D441% - \Umathcode"004F="0"0"1D442% - \Umathcode"0050="0"0"1D443% - \Umathcode"0051="0"0"1D444% - \Umathcode"0052="0"0"1D445% - \Umathcode"0053="0"0"1D446% - \Umathcode"0054="0"0"1D447% - \Umathcode"0055="0"0"1D448% - \Umathcode"0056="0"0"1D449% - \Umathcode"0057="0"0"1D44A% - \Umathcode"0058="0"0"1D44B% - \Umathcode"0059="0"0"1D44C% - \Umathcode"005A="0"0"1D44D% - \Umathcode"0061="0"0"1D44E% - \Umathcode"0062="0"0"1D44F% - \Umathcode"0063="0"0"1D450% - \Umathcode"0064="0"0"1D451% - \Umathcode"0065="0"0"1D452% - \Umathcode"0066="0"0"1D453% - \Umathcode"0067="0"0"1D454% - \Umathcode"0068="0"0"0210E% - \Umathcode"0069="0"0"1D456% - \Umathcode"006A="0"0"1D457% - \Umathcode"006B="0"0"1D458% - \Umathcode"006C="0"0"1D459% - \Umathcode"006D="0"0"1D45A% - \Umathcode"006E="0"0"1D45B% - \Umathcode"006F="0"0"1D45C% - \Umathcode"0070="0"0"1D45D% - \Umathcode"0071="0"0"1D45E% - \Umathcode"0072="0"0"1D45F% - \Umathcode"0073="0"0"1D460% - \Umathcode"0074="0"0"1D461% - \Umathcode"0075="0"0"1D462% - \Umathcode"0076="0"0"1D463% - \Umathcode"0077="0"0"1D464% - \Umathcode"0078="0"0"1D465% - \Umathcode"0079="0"0"1D466% - \Umathcode"007A="0"0"1D467% - \Umathcode"0391="0"0"1D6E2% - \Umathcode"0392="0"0"1D6E3% - \Umathcode"0393="0"0"1D6E4% - \Umathcode"0394="0"0"1D6E5% - \Umathcode"0395="0"0"1D6E6% - \Umathcode"0396="0"0"1D6E7% - \Umathcode"0397="0"0"1D6E8% - \Umathcode"0398="0"0"1D6E9% - \Umathcode"0399="0"0"1D6EA% - \Umathcode"039A="0"0"1D6EB% - \Umathcode"039B="0"0"1D6EC% - \Umathcode"039C="0"0"1D6ED% - \Umathcode"039D="0"0"1D6EE% - \Umathcode"039E="0"0"1D6EF% - \Umathcode"039F="0"0"1D6F0% - \Umathcode"03A0="0"0"1D6F1% - \Umathcode"03A1="0"0"1D6F2% - \Umathcode"03A3="0"0"1D6F4% - \Umathcode"03A4="0"0"1D6F5% - \Umathcode"03A5="0"0"1D6F6% - \Umathcode"03A6="0"0"1D6F7% - \Umathcode"03A7="0"0"1D6F8% - \Umathcode"03A8="0"0"1D6F9% - \Umathcode"03A9="0"0"1D6FA% - \Umathcode"03B1="0"0"1D6FC% - \Umathcode"03B2="0"0"1D6FD% - \Umathcode"03B3="0"0"1D6FE% - \Umathcode"03B4="0"0"1D6FF% - \Umathcode"03B5="0"0"1D700% - \Umathcode"03B6="0"0"1D701% - \Umathcode"03B7="0"0"1D702% - \Umathcode"03B8="0"0"1D703% - \Umathcode"03B9="0"0"1D704% - \Umathcode"03BA="0"0"1D705% - \Umathcode"03BB="0"0"1D706% - \Umathcode"03BC="0"0"1D707% - \Umathcode"03BD="0"0"1D708% - \Umathcode"03BE="0"0"1D709% - \Umathcode"03BF="0"0"1D70A% - \Umathcode"03C0="0"0"1D70B% - \Umathcode"03C1="0"0"1D70C% - \Umathcode"03C2="0"0"1D70D% - \Umathcode"03C3="0"0"1D70E% - \Umathcode"03C4="0"0"1D70F% - \Umathcode"03C5="0"0"1D710% - \Umathcode"03C6="0"0"1D711% - \Umathcode"03C7="0"0"1D712% - \Umathcode"03C8="0"0"1D713% - \Umathcode"03C9="0"0"1D714% - \Umathcode"03D1="0"0"1D717% - \Umathcode"03D5="0"0"1D719% - \Umathcode"03D6="0"0"1D71B% - \Umathcode"03F0="0"0"1D718% - \Umathcode"03F1="0"0"1D71A% - \Umathcode"03F4="0"0"1D6F3% - \Umathcode"03F5="0"0"1D716% - \Umathcode"2202="0"0"1D715% - \Umathcode"2207="0"0"1D6FB% - \relax -} - -\everymathsl {% - \the\everymathit -} - -\everymathbf {% - \Umathcode"0030="0"0"1D7CE% - \Umathcode"0031="0"0"1D7CF% - \Umathcode"0032="0"0"1D7D0% - \Umathcode"0033="0"0"1D7D1% - \Umathcode"0034="0"0"1D7D2% - \Umathcode"0035="0"0"1D7D3% - \Umathcode"0036="0"0"1D7D4% - \Umathcode"0037="0"0"1D7D5% - \Umathcode"0038="0"0"1D7D6% - \Umathcode"0039="0"0"1D7D7% - \Umathcode"0041="0"0"1D400% - \Umathcode"0042="0"0"1D401% - \Umathcode"0043="0"0"1D402% - \Umathcode"0044="0"0"1D403% - \Umathcode"0045="0"0"1D404% - \Umathcode"0046="0"0"1D405% - \Umathcode"0047="0"0"1D406% - \Umathcode"0048="0"0"1D407% - \Umathcode"0049="0"0"1D408% - \Umathcode"004A="0"0"1D409% - \Umathcode"004B="0"0"1D40A% - \Umathcode"004C="0"0"1D40B% - \Umathcode"004D="0"0"1D40C% - \Umathcode"004E="0"0"1D40D% - \Umathcode"004F="0"0"1D40E% - \Umathcode"0050="0"0"1D40F% - \Umathcode"0051="0"0"1D410% - \Umathcode"0052="0"0"1D411% - \Umathcode"0053="0"0"1D412% - \Umathcode"0054="0"0"1D413% - \Umathcode"0055="0"0"1D414% - \Umathcode"0056="0"0"1D415% - \Umathcode"0057="0"0"1D416% - \Umathcode"0058="0"0"1D417% - \Umathcode"0059="0"0"1D418% - \Umathcode"005A="0"0"1D419% - \Umathcode"0061="0"0"1D41A% - \Umathcode"0062="0"0"1D41B% - \Umathcode"0063="0"0"1D41C% - \Umathcode"0064="0"0"1D41D% - \Umathcode"0065="0"0"1D41E% - \Umathcode"0066="0"0"1D41F% - \Umathcode"0067="0"0"1D420% - \Umathcode"0068="0"0"1D421% - \Umathcode"0069="0"0"1D422% - \Umathcode"006A="0"0"1D423% - \Umathcode"006B="0"0"1D424% - \Umathcode"006C="0"0"1D425% - \Umathcode"006D="0"0"1D426% - \Umathcode"006E="0"0"1D427% - \Umathcode"006F="0"0"1D428% - \Umathcode"0070="0"0"1D429% - \Umathcode"0071="0"0"1D42A% - \Umathcode"0072="0"0"1D42B% - \Umathcode"0073="0"0"1D42C% - \Umathcode"0074="0"0"1D42D% - \Umathcode"0075="0"0"1D42E% - \Umathcode"0076="0"0"1D42F% - \Umathcode"0077="0"0"1D430% - \Umathcode"0078="0"0"1D431% - \Umathcode"0079="0"0"1D432% - \Umathcode"007A="0"0"1D433% - \Umathcode"0391="0"0"1D6A8% - \Umathcode"0392="0"0"1D6A9% - \Umathcode"0393="0"0"1D6AA% - \Umathcode"0394="0"0"1D6AB% - \Umathcode"0395="0"0"1D6AC% - \Umathcode"0396="0"0"1D6AD% - \Umathcode"0397="0"0"1D6AE% - \Umathcode"0398="0"0"1D6AF% - \Umathcode"0399="0"0"1D6B0% - \Umathcode"039A="0"0"1D6B1% - \Umathcode"039B="0"0"1D6B2% - \Umathcode"039C="0"0"1D6B3% - \Umathcode"039D="0"0"1D6B4% - \Umathcode"039E="0"0"1D6B5% - \Umathcode"039F="0"0"1D6B6% - \Umathcode"03A0="0"0"1D6B7% - \Umathcode"03A1="0"0"1D6B8% - \Umathcode"03A3="0"0"1D6BA% - \Umathcode"03A4="0"0"1D6BB% - \Umathcode"03A5="0"0"1D6BC% - \Umathcode"03A6="0"0"1D6BD% - \Umathcode"03A7="0"0"1D6BE% - \Umathcode"03A8="0"0"1D6BF% - \Umathcode"03A9="0"0"1D6C0% - \Umathcode"03B1="0"0"1D6C2% - \Umathcode"03B2="0"0"1D6C3% - \Umathcode"03B3="0"0"1D6C4% - \Umathcode"03B4="0"0"1D6C5% - \Umathcode"03B5="0"0"1D6C6% - \Umathcode"03B6="0"0"1D6C7% - \Umathcode"03B7="0"0"1D6C8% - \Umathcode"03B8="0"0"1D6C9% - \Umathcode"03B9="0"0"1D6CA% - \Umathcode"03BA="0"0"1D6CB% - \Umathcode"03BB="0"0"1D6CC% - \Umathcode"03BC="0"0"1D6CD% - \Umathcode"03BD="0"0"1D6CE% - \Umathcode"03BE="0"0"1D6CF% - \Umathcode"03BF="0"0"1D6D0% - \Umathcode"03C0="0"0"1D6D1% - \Umathcode"03C1="0"0"1D6D2% - \Umathcode"03C2="0"0"1D6D3% - \Umathcode"03C3="0"0"1D6D4% - \Umathcode"03C4="0"0"1D6D5% - \Umathcode"03C5="0"0"1D6D6% - \Umathcode"03C6="0"0"1D6D7% - \Umathcode"03C7="0"0"1D6D8% - \Umathcode"03C8="0"0"1D6D9% - \Umathcode"03C9="0"0"1D6DA% - \Umathcode"03D1="0"0"1D6DD% - \Umathcode"03D5="0"0"1D6DF% - \Umathcode"03D6="0"0"1D6E1% - \Umathcode"03F0="0"0"1D6DE% - \Umathcode"03F1="0"0"1D6E0% - \Umathcode"03F4="0"0"1D6B9% - \Umathcode"03F5="0"0"1D6DC% - \Umathcode"2202="0"0"1D6DB% - \Umathcode"2207="0"0"1D6C1% - \relax -} - -\everymathbi {% - \Umathcode"0030="0"0"1D7CE% - \Umathcode"0031="0"0"1D7CF% - \Umathcode"0032="0"0"1D7D0% - \Umathcode"0033="0"0"1D7D1% - \Umathcode"0034="0"0"1D7D2% - \Umathcode"0035="0"0"1D7D3% - \Umathcode"0036="0"0"1D7D4% - \Umathcode"0037="0"0"1D7D5% - \Umathcode"0038="0"0"1D7D6% - \Umathcode"0039="0"0"1D7D7% - \Umathcode"0041="0"0"1D468% - \Umathcode"0042="0"0"1D469% - \Umathcode"0043="0"0"1D46A% - \Umathcode"0044="0"0"1D46B% - \Umathcode"0045="0"0"1D46C% - \Umathcode"0046="0"0"1D46D% - \Umathcode"0047="0"0"1D46E% - \Umathcode"0048="0"0"1D46F% - \Umathcode"0049="0"0"1D470% - \Umathcode"004A="0"0"1D471% - \Umathcode"004B="0"0"1D472% - \Umathcode"004C="0"0"1D473% - \Umathcode"004D="0"0"1D474% - \Umathcode"004E="0"0"1D475% - \Umathcode"004F="0"0"1D476% - \Umathcode"0050="0"0"1D477% - \Umathcode"0051="0"0"1D478% - \Umathcode"0052="0"0"1D479% - \Umathcode"0053="0"0"1D47A% - \Umathcode"0054="0"0"1D47B% - \Umathcode"0055="0"0"1D47C% - \Umathcode"0056="0"0"1D47D% - \Umathcode"0057="0"0"1D47E% - \Umathcode"0058="0"0"1D47F% - \Umathcode"0059="0"0"1D480% - \Umathcode"005A="0"0"1D481% - \Umathcode"0061="0"0"1D482% - \Umathcode"0062="0"0"1D483% - \Umathcode"0063="0"0"1D484% - \Umathcode"0064="0"0"1D485% - \Umathcode"0065="0"0"1D486% - \Umathcode"0066="0"0"1D487% - \Umathcode"0067="0"0"1D488% - \Umathcode"0068="0"0"1D489% - \Umathcode"0069="0"0"1D48A% - \Umathcode"006A="0"0"1D48B% - \Umathcode"006B="0"0"1D48C% - \Umathcode"006C="0"0"1D48D% - \Umathcode"006D="0"0"1D48E% - \Umathcode"006E="0"0"1D48F% - \Umathcode"006F="0"0"1D490% - \Umathcode"0070="0"0"1D491% - \Umathcode"0071="0"0"1D492% - \Umathcode"0072="0"0"1D493% - \Umathcode"0073="0"0"1D494% - \Umathcode"0074="0"0"1D495% - \Umathcode"0075="0"0"1D496% - \Umathcode"0076="0"0"1D497% - \Umathcode"0077="0"0"1D498% - \Umathcode"0078="0"0"1D499% - \Umathcode"0079="0"0"1D49A% - \Umathcode"007A="0"0"1D49B% - \Umathcode"0391="0"0"1D71C% - \Umathcode"0392="0"0"1D71D% - \Umathcode"0393="0"0"1D71E% - \Umathcode"0394="0"0"1D71F% - \Umathcode"0395="0"0"1D720% - \Umathcode"0396="0"0"1D721% - \Umathcode"0397="0"0"1D722% - \Umathcode"0398="0"0"1D723% - \Umathcode"0399="0"0"1D724% - \Umathcode"039A="0"0"1D725% - \Umathcode"039B="0"0"1D726% - \Umathcode"039C="0"0"1D727% - \Umathcode"039D="0"0"1D728% - \Umathcode"039E="0"0"1D729% - \Umathcode"039F="0"0"1D72A% - \Umathcode"03A0="0"0"1D72B% - \Umathcode"03A1="0"0"1D72C% - \Umathcode"03A3="0"0"1D72E% - \Umathcode"03A4="0"0"1D72F% - \Umathcode"03A5="0"0"1D730% - \Umathcode"03A6="0"0"1D731% - \Umathcode"03A7="0"0"1D732% - \Umathcode"03A8="0"0"1D733% - \Umathcode"03A9="0"0"1D734% - \Umathcode"03B1="0"0"1D736% - \Umathcode"03B2="0"0"1D737% - \Umathcode"03B3="0"0"1D738% - \Umathcode"03B4="0"0"1D739% - \Umathcode"03B5="0"0"1D73A% - \Umathcode"03B6="0"0"1D73B% - \Umathcode"03B7="0"0"1D73C% - \Umathcode"03B8="0"0"1D73D% - \Umathcode"03B9="0"0"1D73E% - \Umathcode"03BA="0"0"1D73F% - \Umathcode"03BB="0"0"1D740% - \Umathcode"03BC="0"0"1D741% - \Umathcode"03BD="0"0"1D742% - \Umathcode"03BE="0"0"1D743% - \Umathcode"03BF="0"0"1D744% - \Umathcode"03C0="0"0"1D745% - \Umathcode"03C1="0"0"1D746% - \Umathcode"03C2="0"0"1D747% - \Umathcode"03C3="0"0"1D748% - \Umathcode"03C4="0"0"1D749% - \Umathcode"03C5="0"0"1D74A% - \Umathcode"03C6="0"0"1D74B% - \Umathcode"03C7="0"0"1D74C% - \Umathcode"03C8="0"0"1D74D% - \Umathcode"03C9="0"0"1D74E% - \Umathcode"03D1="0"0"1D751% - \Umathcode"03D5="0"0"1D753% - \Umathcode"03D6="0"0"1D755% - \Umathcode"03F0="0"0"1D752% - \Umathcode"03F1="0"0"1D754% - \Umathcode"03F4="0"0"1D72D% - \Umathcode"03F5="0"0"1D750% - \Umathcode"2202="0"0"1D74F% - \Umathcode"2207="0"0"1D735% - \relax -} - -\everymathtt {% - % not done -} - -\Udelcode "00021 = "0 "00021 -\Udelcode "00028 = "0 "00028 -\Udelcode "00028 = "0 "00028 -\Udelcode "00029 = "0 "00029 -\Udelcode "00029 = "0 "00029 -\Udelcode "0002F = "0 "0002F -\Udelcode "0002F = "0 "0002F -\Udelcode "0002F = "0 "02044 -\Udelcode "0003F = "0 "0003F -\Udelcode "0005B = "0 "0005B -\Udelcode "0005B = "0 "0005B -\Udelcode "0005D = "0 "0005D -\Udelcode "0005D = "0 "0005D -\Udelcode "0007B = "0 "0007B -\Udelcode "0007B = "0 "0007B -\Udelcode "0007C = "0 "0007C -\Udelcode "0007C = "0 "0007C -\Udelcode "0007C = "0 "0007C -\Udelcode "0007C = "0 "0007C -\Udelcode "0007C = "0 "0007C -\Udelcode "0007D = "0 "0007D -\Udelcode "0007D = "0 "0007D -\Udelcode "02016 = "0 "02016 -\Udelcode "02016 = "0 "02016 -\Udelcode "02016 = "0 "02016 -\Udelcode "02016 = "0 "02016 -\Udelcode "02016 = "0 "02016 -\Udelcode "02044 = "0 "02044 -\Udelcode "02044 = "0 "02044 -\Udelcode "02308 = "0 "02308 -\Udelcode "02308 = "0 "02308 -\Udelcode "02308 = "0 "02308 -\Udelcode "02308 = "0 "02308 -\Udelcode "02308 = "0 "02308 -\Udelcode "02309 = "0 "02309 -\Udelcode "02309 = "0 "02309 -\Udelcode "02309 = "0 "02309 -\Udelcode "02309 = "0 "02309 -\Udelcode "02309 = "0 "02309 -\Udelcode "0230A = "0 "0230A -\Udelcode "0230A = "0 "0230A -\Udelcode "0230B = "0 "0230B -\Udelcode "0230B = "0 "0230B -\Udelcode "0231C = "0 "0231C -\Udelcode "0231C = "0 "0231C -\Udelcode "0231D = "0 "0231D -\Udelcode "0231D = "0 "0231D -\Udelcode "0231E = "0 "0231E -\Udelcode "0231E = "0 "0231E -\Udelcode "0231F = "0 "0231F -\Udelcode "0231F = "0 "0231F -\Udelcode "023B0 = "0 "023B0 -\Udelcode "023B0 = "0 "023B0 -\Udelcode "023B1 = "0 "023B1 -\Udelcode "023B1 = "0 "023B1 -\Udelcode "027E6 = "0 "027E6 -\Udelcode "027E6 = "0 "027E6 -\Udelcode "027E7 = "0 "027E7 -\Udelcode "027E7 = "0 "027E7 -\Udelcode "027E8 = "0 "027E8 -\Udelcode "027E8 = "0 "027E8 -\Udelcode "027E9 = "0 "027E9 -\Udelcode "027E9 = "0 "027E9 -\Udelcode "027EA = "0 "027EA -\Udelcode "027EA = "0 "027EA -\Udelcode "027EB = "0 "027EB -\Udelcode "027EB = "0 "027EB -\Udelcode "027EE = "0 "027EE -\Udelcode "027EE = "0 "027EE -\Udelcode "027EF = "0 "027EF -\Udelcode "027EF = "0 "027EF - -\Umathcode "00021 = "5 "0 "00021 -\Umathcode "00022 = "0 "0 "00022 -\Umathcode "00027 = "0 "0 "00027 -\Umathcode "00028 = "4 "0 "00028 -\Umathcode "00029 = "5 "0 "00029 -\Umathcode "0002A = "2 "0 "02217 -\Umathcode "0002B = "2 "0 "0002B -\Umathcode "0002C = "6 "0 "0002C -\Umathcode "0002D = "2 "0 "02212 -\Umathcode "0002E = "6 "0 "0002E -\Umathcode "0002F = "4 "0 "02044 -\Umathcode "0003A = "3 "0 "0003A -\Umathcode "0003B = "6 "0 "0003B -\Umathcode "0003C = "3 "0 "0003C -\Umathcode "0003D = "3 "0 "0003D -\Umathcode "0003E = "3 "0 "0003E -\Umathcode "0003F = "5 "0 "0003F -\Umathcode "0005B = "4 "0 "0005B -\Umathcode "0005C = "0 "0 "0005C -\Umathcode "0005D = "5 "0 "0005D -\Umathcode "0007B = "4 "0 "0007B -\Umathcode "0007C = "0 "0 "0007C -\Umathcode "0007D = "5 "0 "0007D -\Umathcode "000A5 = "0 "0 "000A5 -\Umathcode "000A7 = "0 "0 "000A7 -\Umathcode "000AC = "0 "0 "000AC -\Umathcode "000B1 = "2 "0 "000B1 -\Umathcode "000B6 = "0 "0 "000B6 -\Umathcode "000B7 = "2 "0 "000B7 -\Umathcode "000D7 = "2 "0 "000D7 -\Umathcode "000F0 = "0 "0 "000F0 -\Umathcode "000F7 = "2 "0 "000F7 -\Umathcode "00338 = "3 "0 "00338 -\Umathcode "003F0 = "0 "0 "003F0 -\Umathcode "02016 = "0 "0 "02016 -\Umathcode "02020 = "2 "0 "02020 -\Umathcode "02021 = "2 "0 "02021 -\Umathcode "02022 = "2 "0 "02022 -\Umathcode "02026 = "0 "0 "02026 -\Umathcode "02032 = "0 "0 "02032 -\Umathcode "02033 = "0 "0 "02033 -\Umathcode "02034 = "0 "0 "02034 -\Umathcode "02044 = "0 "0 "02044 -\Umathcode "0207A = "2 "0 "0207A -\Umathcode "0207B = "2 "0 "0207B -\Umathcode "020DD = "0 "0 "020DD -\Umathcode "020DE = "0 "0 "020DE -\Umathcode "020DF = "0 "0 "020DF -\Umathcode "02111 = "0 "0 "02111 -\Umathcode "02113 = "0 "0 "02113 -\Umathcode "02118 = "0 "0 "02118 -\Umathcode "0211C = "0 "0 "0211C -\Umathcode "02132 = "0 "0 "02132 -\Umathcode "02135 = "0 "0 "02135 -\Umathcode "02136 = "0 "0 "02136 -\Umathcode "02137 = "0 "0 "02137 -\Umathcode "02138 = "0 "0 "02138 -\Umathcode "02141 = "0 "0 "02141 -\Umathcode "02142 = "0 "0 "02142 -\Umathcode "02143 = "0 "0 "02143 -\Umathcode "02144 = "0 "0 "02144 -\Umathcode "02145 = "0 "0 "02145 -\Umathcode "02146 = "0 "0 "02146 -\Umathcode "02147 = "0 "0 "02147 -\Umathcode "02148 = "0 "0 "02148 -\Umathcode "02149 = "0 "0 "02149 -\Umathcode "0214A = "0 "0 "0214A -\Umathcode "0214B = "2 "0 "0214B -\Umathcode "02190 = "3 "0 "02190 -\Umathcode "02191 = "3 "0 "02191 -\Umathcode "02192 = "3 "0 "02192 -\Umathcode "02193 = "3 "0 "02193 -\Umathcode "02194 = "3 "0 "02194 -\Umathcode "02195 = "3 "0 "02195 -\Umathcode "02196 = "3 "0 "02196 -\Umathcode "02197 = "3 "0 "02197 -\Umathcode "02198 = "3 "0 "02198 -\Umathcode "02199 = "3 "0 "02199 -\Umathcode "0219A = "3 "0 "0219A -\Umathcode "0219B = "3 "0 "0219B -\Umathcode "0219C = "3 "0 "0219C -\Umathcode "0219D = "3 "0 "0219D -\Umathcode "0219E = "3 "0 "0219E -\Umathcode "0219F = "3 "0 "0219F -\Umathcode "021A0 = "3 "0 "021A0 -\Umathcode "021A1 = "3 "0 "021A1 -\Umathcode "021A2 = "3 "0 "021A2 -\Umathcode "021A3 = "3 "0 "021A3 -\Umathcode "021A4 = "3 "0 "021A4 -\Umathcode "021A5 = "3 "0 "021A5 -\Umathcode "021A6 = "3 "0 "021A6 -\Umathcode "021A7 = "3 "0 "021A7 -\Umathcode "021A8 = "0 "0 "021A8 -\Umathcode "021A9 = "3 "0 "021A9 -\Umathcode "021AA = "3 "0 "021AA -\Umathcode "021AB = "3 "0 "021AB -\Umathcode "021AC = "3 "0 "021AC -\Umathcode "021AD = "3 "0 "021AD -\Umathcode "021AE = "3 "0 "021AE -\Umathcode "021AF = "3 "0 "021AF -\Umathcode "021B0 = "3 "0 "021B0 -\Umathcode "021B1 = "3 "0 "021B1 -\Umathcode "021B2 = "3 "0 "021B2 -\Umathcode "021B3 = "3 "0 "021B3 -\Umathcode "021B4 = "0 "0 "021B4 -\Umathcode "021B5 = "0 "0 "021B5 -\Umathcode "021B6 = "3 "0 "021B6 -\Umathcode "021B7 = "3 "0 "021B7 -\Umathcode "021B8 = "3 "0 "021B8 -\Umathcode "021B9 = "3 "0 "021B9 -\Umathcode "021BA = "3 "0 "021BA -\Umathcode "021BB = "3 "0 "021BB -\Umathcode "021BC = "3 "0 "021BC -\Umathcode "021BD = "3 "0 "021BD -\Umathcode "021BE = "3 "0 "021BE -\Umathcode "021BF = "3 "0 "021BF -\Umathcode "021C0 = "3 "0 "021C0 -\Umathcode "021C1 = "3 "0 "021C1 -\Umathcode "021C2 = "3 "0 "021C2 -\Umathcode "021C3 = "3 "0 "021C3 -\Umathcode "021C4 = "3 "0 "021C4 -\Umathcode "021C5 = "3 "0 "021C5 -\Umathcode "021C6 = "3 "0 "021C6 -\Umathcode "021C7 = "3 "0 "021C7 -\Umathcode "021C8 = "3 "0 "021C8 -\Umathcode "021C9 = "3 "0 "021C9 -\Umathcode "021CA = "3 "0 "021CA -\Umathcode "021CB = "3 "0 "021CB -\Umathcode "021CC = "3 "0 "021CC -\Umathcode "021CD = "3 "0 "021CD -\Umathcode "021CE = "3 "0 "021CE -\Umathcode "021CF = "3 "0 "021CF -\Umathcode "021D0 = "3 "0 "021D0 -\Umathcode "021D1 = "3 "0 "021D1 -\Umathcode "021D2 = "3 "0 "021D2 -\Umathcode "021D3 = "3 "0 "021D3 -\Umathcode "021D4 = "3 "0 "021D4 -\Umathcode "021D5 = "3 "0 "021D5 -\Umathcode "021D6 = "3 "0 "021D6 -\Umathcode "021D7 = "3 "0 "021D7 -\Umathcode "021D8 = "3 "0 "021D8 -\Umathcode "021D9 = "3 "0 "021D9 -\Umathcode "021DA = "3 "0 "021DA -\Umathcode "021DB = "3 "0 "021DB -\Umathcode "021DC = "3 "0 "021DC -\Umathcode "021DD = "3 "0 "021DD -\Umathcode "021DE = "3 "0 "021DE -\Umathcode "021DF = "3 "0 "021DF -\Umathcode "021E0 = "3 "0 "021E0 -\Umathcode "021E1 = "3 "0 "021E1 -\Umathcode "021E2 = "3 "0 "021E2 -\Umathcode "021E3 = "3 "0 "021E3 -\Umathcode "021E4 = "3 "0 "021E4 -\Umathcode "021E5 = "3 "0 "021E5 -\Umathcode "021E6 = "0 "0 "021E6 -\Umathcode "021E7 = "0 "0 "021E7 -\Umathcode "021E8 = "0 "0 "021E8 -\Umathcode "021E9 = "0 "0 "021E9 -\Umathcode "021EB = "0 "0 "021EB -\Umathcode "021F4 = "3 "0 "021F4 -\Umathcode "021F5 = "3 "0 "021F5 -\Umathcode "021F6 = "3 "0 "021F6 -\Umathcode "021F7 = "3 "0 "021F7 -\Umathcode "021F8 = "3 "0 "021F8 -\Umathcode "021F9 = "3 "0 "021F9 -\Umathcode "021FA = "3 "0 "021FA -\Umathcode "021FB = "3 "0 "021FB -\Umathcode "021FC = "3 "0 "021FC -\Umathcode "021FD = "3 "0 "021FD -\Umathcode "021FE = "3 "0 "021FE -\Umathcode "021FF = "3 "0 "021FF -\Umathcode "02200 = "0 "0 "02200 -\Umathcode "02201 = "0 "0 "02201 -\Umathcode "02202 = "0 "0 "02202 -\Umathcode "02203 = "0 "0 "02203 -\Umathcode "02204 = "0 "0 "02204 -\Umathcode "02205 = "0 "0 "02205 -\Umathcode "02208 = "3 "0 "02208 -\Umathcode "02209 = "3 "0 "02209 -\Umathcode "0220B = "3 "0 "0220B -\Umathcode "0220C = "3 "0 "0220C -\Umathcode "0220F = "1 "0 "0220F -\Umathcode "02210 = "1 "0 "02210 -\Umathcode "02211 = "1 "0 "02211 -\Umathcode "02212 = "2 "0 "02212 -\Umathcode "02213 = "2 "0 "02213 -\Umathcode "02214 = "2 "0 "02214 -\Umathcode "02216 = "2 "0 "02216 -\Umathcode "02217 = "2 "0 "02217 -\Umathcode "02218 = "2 "0 "02218 -\Umathcode "02219 = "2 "0 "02219 -\Umathcode "0221D = "3 "0 "0221D -\Umathcode "0221E = "0 "0 "0221E -\Umathcode "0221F = "0 "0 "0221F -\Umathcode "02220 = "0 "0 "02220 -\Umathcode "02221 = "0 "0 "02221 -\Umathcode "02222 = "0 "0 "02222 -\Umathcode "02223 = "2 "0 "02223 -\Umathcode "02224 = "2 "0 "02224 -\Umathcode "02225 = "3 "0 "02225 -\Umathcode "02226 = "3 "0 "02226 -\Umathcode "02227 = "2 "0 "02227 -\Umathcode "02228 = "2 "0 "02228 -\Umathcode "02229 = "2 "0 "02229 -\Umathcode "0222A = "2 "0 "0222A -\Umathcode "0222B = "1 "0 "0222B -\Umathcode "0222C = "1 "0 "0222C -\Umathcode "0222D = "1 "0 "0222D -\Umathcode "0222E = "1 "0 "0222E -\Umathcode "0222F = "1 "0 "0222F -\Umathcode "02230 = "1 "0 "02230 -\Umathcode "02231 = "1 "0 "02231 -\Umathcode "02232 = "1 "0 "02232 -\Umathcode "02233 = "1 "0 "02233 -\Umathcode "02234 = "3 "0 "02234 -\Umathcode "02235 = "3 "0 "02235 -\Umathcode "02236 = "6 "0 "02236 -\Umathcode "02237 = "3 "0 "02237 -\Umathcode "02238 = "2 "0 "02238 -\Umathcode "02239 = "3 "0 "02239 -\Umathcode "0223C = "3 "0 "0223C -\Umathcode "0223D = "3 "0 "0223D -\Umathcode "02240 = "2 "0 "02240 -\Umathcode "02241 = "3 "0 "02241 -\Umathcode "02242 = "3 "0 "02242 -\Umathcode "02243 = "3 "0 "02243 -\Umathcode "02244 = "3 "0 "02244 -\Umathcode "02245 = "3 "0 "02245 -\Umathcode "02246 = "3 "0 "02246 -\Umathcode "02247 = "3 "0 "02247 -\Umathcode "02248 = "3 "0 "02248 -\Umathcode "02249 = "3 "0 "02249 -\Umathcode "0224A = "3 "0 "0224A -\Umathcode "0224C = "3 "0 "0224C -\Umathcode "0224D = "3 "0 "0224D -\Umathcode "0224E = "3 "0 "0224E -\Umathcode "02250 = "3 "0 "02250 -\Umathcode "02251 = "3 "0 "02251 -\Umathcode "02252 = "3 "0 "02252 -\Umathcode "02253 = "3 "0 "02253 -\Umathcode "02254 = "3 "0 "02254 -\Umathcode "02255 = "3 "0 "02255 -\Umathcode "02256 = "3 "0 "02256 -\Umathcode "02257 = "3 "0 "02257 -\Umathcode "02259 = "3 "0 "02259 -\Umathcode "0225A = "3 "0 "0225A -\Umathcode "0225B = "3 "0 "0225B -\Umathcode "0225C = "3 "0 "0225C -\Umathcode "0225D = "3 "0 "0225D -\Umathcode "0225E = "3 "0 "0225E -\Umathcode "0225F = "3 "0 "0225F -\Umathcode "02260 = "3 "0 "02260 -\Umathcode "02261 = "3 "0 "02261 -\Umathcode "02262 = "3 "0 "02262 -\Umathcode "02263 = "3 "0 "02263 -\Umathcode "02264 = "3 "0 "02264 -\Umathcode "02265 = "3 "0 "02265 -\Umathcode "02266 = "3 "0 "02266 -\Umathcode "02267 = "3 "0 "02267 -\Umathcode "02268 = "3 "0 "02268 -\Umathcode "02269 = "3 "0 "02269 -\Umathcode "0226A = "3 "0 "0226A -\Umathcode "0226B = "3 "0 "0226B -\Umathcode "0226C = "3 "0 "0226C -\Umathcode "0226D = "3 "0 "0226D -\Umathcode "0226E = "3 "0 "0226E -\Umathcode "0226F = "3 "0 "0226F -\Umathcode "02270 = "3 "0 "02270 -\Umathcode "02271 = "3 "0 "02271 -\Umathcode "02272 = "3 "0 "02272 -\Umathcode "02273 = "3 "0 "02273 -\Umathcode "02274 = "3 "0 "02274 -\Umathcode "02275 = "3 "0 "02275 -\Umathcode "02276 = "3 "0 "02276 -\Umathcode "02277 = "3 "0 "02277 -\Umathcode "02278 = "3 "0 "02278 -\Umathcode "02279 = "3 "0 "02279 -\Umathcode "0227A = "3 "0 "0227A -\Umathcode "0227B = "3 "0 "0227B -\Umathcode "0227C = "3 "0 "0227C -\Umathcode "0227D = "3 "0 "0227D -\Umathcode "0227E = "3 "0 "0227E -\Umathcode "0227F = "3 "0 "0227F -\Umathcode "02280 = "3 "0 "02280 -\Umathcode "02281 = "3 "0 "02281 -\Umathcode "02282 = "3 "0 "02282 -\Umathcode "02283 = "3 "0 "02283 -\Umathcode "02284 = "3 "0 "02284 -\Umathcode "02285 = "3 "0 "02285 -\Umathcode "02286 = "3 "0 "02286 -\Umathcode "02287 = "3 "0 "02287 -\Umathcode "02288 = "3 "0 "02288 -\Umathcode "02289 = "3 "0 "02289 -\Umathcode "0228A = "3 "0 "0228A -\Umathcode "0228B = "3 "0 "0228B -\Umathcode "0228E = "2 "0 "0228E -\Umathcode "0228F = "3 "0 "0228F -\Umathcode "02290 = "3 "0 "02290 -\Umathcode "02291 = "2 "0 "02291 -\Umathcode "02292 = "2 "0 "02292 -\Umathcode "02293 = "2 "0 "02293 -\Umathcode "02294 = "2 "0 "02294 -\Umathcode "02295 = "2 "0 "02295 -\Umathcode "02296 = "2 "0 "02296 -\Umathcode "02297 = "2 "0 "02297 -\Umathcode "02298 = "2 "0 "02298 -\Umathcode "02299 = "2 "0 "02299 -\Umathcode "0229A = "2 "0 "0229A -\Umathcode "0229B = "2 "0 "0229B -\Umathcode "0229C = "2 "0 "0229C -\Umathcode "0229D = "2 "0 "0229D -\Umathcode "0229E = "2 "0 "0229E -\Umathcode "0229F = "2 "0 "0229F -\Umathcode "022A0 = "2 "0 "022A0 -\Umathcode "022A1 = "2 "0 "022A1 -\Umathcode "022A2 = "3 "0 "022A2 -\Umathcode "022A3 = "3 "0 "022A3 -\Umathcode "022A4 = "0 "0 "022A4 -\Umathcode "022A5 = "0 "0 "022A5 -\Umathcode "022A7 = "3 "0 "022A7 -\Umathcode "022A8 = "3 "0 "022A8 -\Umathcode "022A9 = "3 "0 "022A9 -\Umathcode "022AA = "3 "0 "022AA -\Umathcode "022AB = "3 "0 "022AB -\Umathcode "022AC = "3 "0 "022AC -\Umathcode "022AD = "3 "0 "022AD -\Umathcode "022AE = "3 "0 "022AE -\Umathcode "022AF = "3 "0 "022AF -\Umathcode "022B2 = "2 "0 "022B2 -\Umathcode "022B3 = "2 "0 "022B3 -\Umathcode "022B8 = "3 "0 "022B8 -\Umathcode "022BA = "2 "0 "022BA -\Umathcode "022BB = "2 "0 "022BB -\Umathcode "022BC = "2 "0 "022BC -\Umathcode "022C0 = "1 "0 "022C0 -\Umathcode "022C1 = "1 "0 "022C1 -\Umathcode "022C2 = "1 "0 "022C2 -\Umathcode "022C3 = "1 "0 "022C3 -\Umathcode "022C4 = "2 "0 "022C4 -\Umathcode "022C5 = "2 "0 "022C5 -\Umathcode "022C6 = "2 "0 "022C6 -\Umathcode "022C7 = "2 "0 "022C7 -\Umathcode "022C8 = "3 "0 "022C8 -\Umathcode "022C9 = "2 "0 "022C9 -\Umathcode "022CA = "2 "0 "022CA -\Umathcode "022CB = "2 "0 "022CB -\Umathcode "022CC = "2 "0 "022CC -\Umathcode "022CE = "2 "0 "022CE -\Umathcode "022CF = "2 "0 "022CF -\Umathcode "022D0 = "3 "0 "022D0 -\Umathcode "022D1 = "3 "0 "022D1 -\Umathcode "022D2 = "2 "0 "022D2 -\Umathcode "022D3 = "2 "0 "022D3 -\Umathcode "022D4 = "3 "0 "022D4 -\Umathcode "022D6 = "2 "0 "022D6 -\Umathcode "022D7 = "2 "0 "022D7 -\Umathcode "022D8 = "3 "0 "022D8 -\Umathcode "022D9 = "3 "0 "022D9 -\Umathcode "022DA = "3 "0 "022DA -\Umathcode "022DB = "3 "0 "022DB -\Umathcode "022DC = "3 "0 "022DC -\Umathcode "022DD = "3 "0 "022DD -\Umathcode "022DE = "3 "0 "022DE -\Umathcode "022DF = "3 "0 "022DF -\Umathcode "022E0 = "3 "0 "022E0 -\Umathcode "022E1 = "3 "0 "022E1 -\Umathcode "022E2 = "3 "0 "022E2 -\Umathcode "022E3 = "3 "0 "022E3 -\Umathcode "022E4 = "3 "0 "022E4 -\Umathcode "022E5 = "3 "0 "022E5 -\Umathcode "022E6 = "3 "0 "022E6 -\Umathcode "022E7 = "3 "0 "022E7 -\Umathcode "022E8 = "3 "0 "022E8 -\Umathcode "022E9 = "3 "0 "022E9 -\Umathcode "022EA = "3 "0 "022EA -\Umathcode "022EB = "3 "0 "022EB -\Umathcode "022EC = "3 "0 "022EC -\Umathcode "022ED = "3 "0 "022ED -\Umathcode "022EE = "0 "0 "022EE -\Umathcode "022EF = "0 "0 "022EF -\Umathcode "022F0 = "0 "0 "022F0 -\Umathcode "022F1 = "0 "0 "022F1 -\Umathcode "02300 = "0 "0 "02300 -\Umathcode "02308 = "4 "0 "02308 -\Umathcode "02309 = "5 "0 "02309 -\Umathcode "0230A = "4 "0 "0230A -\Umathcode "0230B = "5 "0 "0230B -\Umathcode "0231C = "4 "0 "0231C -\Umathcode "0231D = "5 "0 "0231D -\Umathcode "0231E = "4 "0 "0231E -\Umathcode "0231F = "5 "0 "0231F -\Umathcode "02322 = "3 "0 "02322 -\Umathcode "02323 = "3 "0 "02323 -\Umathcode "023B0 = "4 "0 "023B0 -\Umathcode "023B1 = "5 "0 "023B1 -\Umathcode "024C7 = "0 "0 "024C7 -\Umathcode "024C8 = "0 "0 "024C8 -\Umathcode "025A0 = "0 "0 "025A0 -\Umathcode "025A1 = "0 "0 "025A1 -\Umathcode "025A2 = "0 "0 "025A2 -\Umathcode "025B2 = "2 "0 "025B2 -\Umathcode "025B3 = "0 "0 "025B3 -\Umathcode "025B6 = "2 "0 "025B6 -\Umathcode "025B7 = "2 "0 "025B7 -\Umathcode "025BC = "2 "0 "025BC -\Umathcode "025BD = "2 "0 "025BD -\Umathcode "025C0 = "2 "0 "025C0 -\Umathcode "025C1 = "2 "0 "025C1 -\Umathcode "025CA = "0 "0 "025CA -\Umathcode "025EF = "2 "0 "025EF -\Umathcode "02605 = "0 "0 "02605 -\Umathcode "02660 = "0 "0 "02660 -\Umathcode "02661 = "0 "0 "02661 -\Umathcode "02662 = "0 "0 "02662 -\Umathcode "02663 = "0 "0 "02663 -\Umathcode "02666 = "0 "0 "02666 -\Umathcode "0266D = "0 "0 "0266D -\Umathcode "0266E = "0 "0 "0266E -\Umathcode "0266F = "0 "0 "0266F -\Umathcode "02713 = "0 "0 "02713 -\Umathcode "02720 = "0 "0 "02720 -\Umathcode "027E6 = "4 "0 "027E6 -\Umathcode "027E7 = "5 "0 "027E7 -\Umathcode "027E8 = "4 "0 "027E8 -\Umathcode "027E9 = "5 "0 "027E9 -\Umathcode "027EA = "4 "0 "027EA -\Umathcode "027EB = "5 "0 "027EB -\Umathcode "027EE = "4 "0 "027EE -\Umathcode "027EF = "5 "0 "027EF -\Umathcode "027F5 = "3 "0 "027F5 -\Umathcode "027F6 = "3 "0 "027F6 -\Umathcode "027F7 = "3 "0 "027F7 -\Umathcode "027F8 = "3 "0 "027F8 -\Umathcode "027F9 = "3 "0 "027F9 -\Umathcode "027FA = "3 "0 "027FA -\Umathcode "027FB = "3 "0 "027FB -\Umathcode "027FC = "3 "0 "027FC -\Umathcode "027FD = "3 "0 "027FD -\Umathcode "027FE = "3 "0 "027FE -\Umathcode "027FF = "3 "0 "027FF -\Umathcode "02906 = "3 "0 "02906 -\Umathcode "02907 = "3 "0 "02907 -\Umathcode "0290A = "3 "0 "0290A -\Umathcode "0290B = "3 "0 "0290B -\Umathcode "0290C = "3 "0 "0290C -\Umathcode "0290D = "3 "0 "0290D -\Umathcode "02911 = "3 "0 "02911 -\Umathcode "02916 = "3 "0 "02916 -\Umathcode "02917 = "3 "0 "02917 -\Umathcode "02921 = "3 "0 "02921 -\Umathcode "02922 = "3 "0 "02922 -\Umathcode "02923 = "3 "0 "02923 -\Umathcode "02924 = "3 "0 "02924 -\Umathcode "02925 = "3 "0 "02925 -\Umathcode "02926 = "3 "0 "02926 -\Umathcode "02A00 = "1 "0 "02A00 -\Umathcode "02A01 = "1 "0 "02A01 -\Umathcode "02A02 = "1 "0 "02A02 -\Umathcode "02A03 = "1 "0 "02A03 -\Umathcode "02A04 = "1 "0 "02A04 -\Umathcode "02A05 = "1 "0 "02A05 -\Umathcode "02A06 = "1 "0 "02A06 -\Umathcode "02A09 = "1 "0 "02A09 -\Umathcode "02A3F = "2 "0 "02A3F -\Umathcode "02A7D = "3 "0 "02A7D -\Umathcode "02A7E = "3 "0 "02A7E -\Umathcode "02A85 = "3 "0 "02A85 -\Umathcode "02A86 = "3 "0 "02A86 -\Umathcode "02A87 = "3 "0 "02A87 -\Umathcode "02A88 = "3 "0 "02A88 -\Umathcode "02A89 = "3 "0 "02A89 -\Umathcode "02A8A = "3 "0 "02A8A -\Umathcode "02A8B = "3 "0 "02A8B -\Umathcode "02A8C = "3 "0 "02A8C -\Umathcode "02A95 = "3 "0 "02A95 -\Umathcode "02A96 = "3 "0 "02A96 -\Umathcode "02AAF = "3 "0 "02AAF -\Umathcode "02AB0 = "3 "0 "02AB0 -\Umathcode "02AB1 = "3 "0 "02AB1 -\Umathcode "02AB2 = "3 "0 "02AB2 -\Umathcode "02AB3 = "3 "0 "02AB3 -\Umathcode "02AB4 = "3 "0 "02AB4 -\Umathcode "02AB5 = "3 "0 "02AB5 -\Umathcode "02AB6 = "3 "0 "02AB6 -\Umathcode "02AB7 = "3 "0 "02AB7 -\Umathcode "02AB8 = "3 "0 "02AB8 -\Umathcode "02AB9 = "3 "0 "02AB9 -\Umathcode "02ABA = "3 "0 "02ABA -\Umathcode "02AC5 = "3 "0 "02AC5 -\Umathcode "02AC6 = "3 "0 "02AC6 -\Umathcode "02ACB = "3 "0 "02ACB -\Umathcode "02ACC = "3 "0 "02ACC -\Umathcode "12035 = "0 "0 "12035 -\Umathcode "1D6A4 = "0 "0 "1D6A4 -\Umathcode "1D6A5 = "0 "0 "1D6A5 -\Umathcode "1D6FB = "0 "0 "1D6FB -\Umathcode "1D717 = "0 "0 "1D717 -\Umathcode "1D718 = "0 "0 "1D718 - -% gaps .. done in lua (as example) - -% \Umathcode "1D455 = "0 "0 "0210E -% \Umathcode "1D49D = "0 "0 "0212C -% \Umathcode "1D4A0 = "0 "0 "02130 -% \Umathcode "1D4A1 = "0 "0 "02131 -% \Umathcode "1D4A3 = "0 "0 "0210B -% \Umathcode "1D4A4 = "0 "0 "02110 -% \Umathcode "1D4A7 = "0 "0 "02112 -% \Umathcode "1D4A8 = "0 "0 "02133 -% \Umathcode "1D4AD = "0 "0 "0211B -% \Umathcode "1D4BA = "0 "0 "0212F -% \Umathcode "1D4BC = "0 "0 "0210A -% \Umathcode "1D4C4 = "0 "0 "02134 -% \Umathcode "1D506 = "0 "0 "0212D -% \Umathcode "1D50B = "0 "0 "0210C -% \Umathcode "1D50C = "0 "0 "02111 -% \Umathcode "1D515 = "0 "0 "0211C -% \Umathcode "1D51D = "0 "0 "02128 -% \Umathcode "1D53A = "0 "0 "02102 -% \Umathcode "1D53F = "0 "0 "0210D -% \Umathcode "1D545 = "0 "0 "02115 -% \Umathcode "1D547 = "0 "0 "02119 -% \Umathcode "1D548 = "0 "0 "0211A -% \Umathcode "1D549 = "0 "0 "0211D -% \Umathcode "1D551 = "0 "0 "02124 - -% initialization - -\the\everymathit - -% a couple of definitions (we could also use \mathchardef): - -\def\acute {\Umathaccent"0"0"0000B4 } -\def\acwopencirclearrow {\Umathchar "3"0"0021BA } -\def\aleph {\Umathchar "0"0"002135 } -\def\Alpha {\Umathchar "0"0"000391 } -\def\alpha {\Umathchar "0"0"0003B1 } -\def\amalg {\Umathchar "2"0"002A3F } -\def\angle {\Umathchar "0"0"002220 } -\def\Angstrom {\Umathchar "0"0"00212B } -\def\approx {\Umathchar "3"0"002248 } -\def\approxEq {\Umathchar "3"0"002245 } -\def\approxeq {\Umathchar "3"0"00224A } -\def\approxnEq {\Umathchar "3"0"002247 } -\def\arrowvert {\Umathchar "0"0"00007C } -\def\Arrowvert {\Umathchar "0"0"002016 } -\def\ast {\Umathchar "2"0"002217 } -\def\ast {\Umathchar "2"0"002217 } -\def\asymp {\Umathchar "3"0"00224D } -\def\backepsilon {\Umathchar "0"0"0003F6 } -\def\backprime {\Umathchar "0"0"012035 } -\def\backsim {\Umathchar "3"0"00223D } -\def\backslash {\Umathchar "0"0"00005C } -\def\bar {\Umathaccent"0"0"0000AF } -\def\barleftarrow {\Umathchar "3"0"0021E4 } -\def\barleftarrowrightarrowbar {\Umathchar "3"0"0021B9 } -\def\barovernorthwestarrow {\Umathchar "3"0"0021B8 } -\def\barwedge {\Umathchar "2"0"0022BC } -\def\because {\Umathchar "3"0"002235 } -\def\Beta {\Umathchar "0"0"000392 } -\def\beta {\Umathchar "0"0"0003B2 } -\def\beth {\Umathchar "0"0"002136 } -\def\between {\Umathchar "3"0"00226C } -\def\bigcap {\Umathchar "1"0"0022C2 } -\def\bigcirc {\Umathchar "2"0"0025EF } -\def\bigcircle {\Umathchar "2"0"0020DD } -\def\bigcircle {\Umathchar "2"0"0020DD } -\def\bigcup {\Umathchar "1"0"0022C3 } -\def\bigdiamond {\Umathchar "0"0"0020DF } -\def\bigodot {\Umathchar "1"0"002A00 } -\def\bigoplus {\Umathchar "1"0"002A01 } -\def\bigotimes {\Umathchar "1"0"002A02 } -\def\bigsqcap {\Umathchar "1"0"002A05 } -\def\bigsqcup {\Umathchar "1"0"002A06 } -\def\bigsquare {\Umathchar "0"0"0020DE } -\def\bigstar {\Umathchar "0"0"002605 } -\def\bigtimes {\Umathchar "1"0"002A09 } -\def\bigtriangledown {\Umathchar "2"0"0025BD } -\def\bigtriangleup {\Umathchar "2"0"0025B3 } -\def\bigudot {\Umathchar "1"0"002A03 } -\def\biguplus {\Umathchar "1"0"002A04 } -\def\bigvee {\Umathchar "1"0"0022C1 } -\def\bigwedge {\Umathchar "1"0"0022C0 } -\def\blacklozenge {\Umathchar "0"0"002666 } -\def\blacksquare {\Umathchar "0"0"0025A0 } -\def\blacktriangle {\Umathchar "2"0"0025B2 } -\def\blacktriangledown {\Umathchar "2"0"0025BC } -\def\blacktriangleleft {\Umathchar "2"0"0025C0 } -\def\blacktriangleright {\Umathchar "2"0"0025B6 } -\def\bot {\Umathchar "0"0"0022A5 } -\def\bowtie {\Umathchar "3"0"0022C8 } -\def\Box {\Umathchar "0"0"0025A1 } -\def\boxdot {\Umathchar "2"0"0022A1 } -\def\boxminus {\Umathchar "2"0"00229F } -\def\boxplus {\Umathchar "2"0"00229E } -\def\boxtimes {\Umathchar "2"0"0022A0 } -%def\braceld {\Umathchar "0"0"000000 } -%def\bracerd {\Umathchar "0"0"000000 } -%def\bracelu {\Umathchar "0"0"000000 } -%def\braceru {\Umathchar "0"0"000000 } -\def\breve {\Umathaccent"0"0"0002D8 } -\def\bullet {\Umathchar "2"0"002022 } -\def\bullet {\Umathchar "2"0"002022 } -\def\Bumpeq {\Umathchar "3"0"00224E } -\def\cap {\Umathchar "2"0"002229 } -\def\Cap {\Umathchar "2"0"0022D2 } -\def\carriagereturn {\Umathchar "0"0"0021B5 } -\def\cdot {\Umathchar "2"0"0022C5 } -\def\cdotp {\Umathchar "6"0"0022C5 } -\def\cdots {\Umathchar "0"0"0022EF } -\def\centerdot {\Umathchar "2"0"0000B7 } -\def\check {\Umathaccent"0"0"0002C7 } -\def\checkmark {\Umathchar "0"0"002713 } -\def\Chi {\Umathchar "0"0"0003A7 } -\def\chi {\Umathchar "0"0"0003C7 } -\def\circ {\Umathchar "2"0"002218 } -\def\circeq {\Umathchar "3"0"002257 } -\def\circlearrowleft {\Umathchar "3"0"0021BB } -\def\circlearrowright {\Umathchar "3"0"0021BA } -\def\circledast {\Umathchar "2"0"00229B } -\def\circledcirc {\Umathchar "2"0"00229A } -\def\circleddash {\Umathchar "2"0"00229D } -\def\circledequals {\Umathchar "2"0"00229C } -\def\circledR {\Umathchar "0"0"0024C7 } -\def\circledS {\Umathchar "0"0"0024C8 } -\def\circleonrightarrow {\Umathchar "3"0"0021F4 } -\def\clubsuit {\Umathchar "0"0"002663 } -\def\colon {\Umathchar "6"0"002236 } -\def\colonequals {\Umathchar "3"0"002254 } -\def\complement {\Umathchar "0"0"002201 } -\def\complexes {\Umathchar "0"0"002102 } -\def\cong {\Umathchar "3"0"002245 } -\def\coprod {\Umathchar "1"0"002210 } -\def\cup {\Umathchar "2"0"00222A } -\def\Cup {\Umathchar "2"0"0022D3 } -\def\curlyeqprec {\Umathchar "3"0"0022DE } -\def\curlyeqsucc {\Umathchar "3"0"0022DF } -\def\curlyvee {\Umathchar "2"0"0022CE } -\def\curlywedge {\Umathchar "2"0"0022CF } -\def\curvearrowleft {\Umathchar "3"0"0021B6 } -\def\curvearrowright {\Umathchar "3"0"0021B7 } -\def\cwopencirclearrow {\Umathchar "3"0"0021BB } -\def\dag {\Umathchar "0"0"002020 } -\def\dagger {\Umathchar "2"0"002020 } -\def\daleth {\Umathchar "0"0"002138 } -\def\dasharrow {\Umathchar "3"0"0021E2 } -\def\dashedleftarrow {\Umathchar "3"0"00290C } -\def\dashedrightarrow {\Umathchar "3"0"00290D } -\def\dashv {\Umathchar "3"0"0022A3 } -\def\ddag {\Umathchar "0"0"002021 } -\def\ddagger {\Umathchar "2"0"002021 } -\def\dddot {\Umathaccent"0"0"0020DB } -\def\ddot {\Umathaccent"0"0"0000A8 } -\def\ddots {\Umathchar "0"0"0022F1 } -\def\Ddownarrow {\Umathchar "3"0"00290B } -\def\definedeq {\Umathchar "3"0"00225D } -\def\Delta {\Umathchar "0"0"000394 } -\def\delta {\Umathchar "0"0"0003B4 } -\def\diamond {\Umathchar "2"0"0022C4 } -\def\diamondsuit {\Umathchar "0"0"002662 } -\def\differentialD {\Umathchar "0"0"002145 } -\def\differentiald {\Umathchar "0"0"002146 } -\def\digamma {\Umathchar "0"0"0003DC } -\def\div {\Umathchar "2"0"0000F7 } -\def\divideontimes {\Umathchar "2"0"0022C7 } -\def\divides {\Umathchar "2"0"002223 } -\def\dot {\Umathaccent"0"0"0002D9 } -\def\doteq {\Umathchar "3"0"002250 } -\def\Doteq {\Umathchar "3"0"002251 } -\def\doteqdot {\Umathchar "3"0"002251 } -\def\dotminus {\Umathchar "2"0"002238 } -\def\dotplus {\Umathchar "2"0"002214 } -\def\dots {\Umathchar "0"0"002026 } -\def\dottedrightarrow {\Umathchar "3"0"002911 } -\def\doublecap {\Umathchar "2"0"0022D2 } -\def\doublecup {\Umathchar "2"0"0022D3 } -\def\doubleprime {\Umathchar "0"0"002033 } -\def\downarrow {\Umathchar "3"0"002193 } -\def\Downarrow {\Umathchar "3"0"0021D3 } -\def\downdasharrow {\Umathchar "3"0"0021E3 } -\def\downdownarrows {\Umathchar "3"0"0021CA } -\def\downharpoonleft {\Umathchar "3"0"0021C3 } -\def\downharpoonright {\Umathchar "3"0"0021C2 } -\def\downuparrows {\Umathchar "3"0"0021F5 } -\def\downwhitearrow {\Umathchar "0"0"0021E9 } -\def\downzigzagarrow {\Umathchar "3"0"0021AF } -\def\ell {\Umathchar "0"0"002113 } -\def\emptyset {\Umathchar "0"0"002205 } -\def\Epsilon {\Umathchar "0"0"000395 } -\def\epsilon {\Umathchar "0"0"0003F5 } -\def\eq {\Umathchar "3"0"00003D } -\def\eqcirc {\Umathchar "3"0"002256 } -\def\eqgtr {\Umathchar "3"0"0022DD } -\def\eqless {\Umathchar "3"0"0022DC } -\def\eqsim {\Umathchar "3"0"002242 } -\def\eqslantgtr {\Umathchar "3"0"002A96 } -\def\eqslantless {\Umathchar "3"0"002A95 } -\def\equalscolon {\Umathchar "3"0"002255 } -\def\equiv {\Umathchar "3"0"002261 } -\def\Eta {\Umathchar "0"0"000397 } -\def\eta {\Umathchar "0"0"0003B7 } -\def\eth {\Umathchar "0"0"0000F0 } -\def\Eulerconst {\Umathchar "0"0"002107 } -\def\exists {\Umathchar "0"0"002203 } -\def\exponentiale {\Umathchar "0"0"002147 } -\def\fallingdotseq {\Umathchar "3"0"002252 } -\def\Finv {\Umathchar "0"0"002132 } -\def\flat {\Umathchar "0"0"00266D } -\def\forall {\Umathchar "0"0"002200 } -\def\frown {\Umathchar "3"0"002322 } -\def\Game {\Umathchar "0"0"002141 } -\def\Gamma {\Umathchar "0"0"000393 } -\def\gamma {\Umathchar "0"0"0003B3 } -\def\ge {\Umathchar "3"0"002265 } -\def\geq {\Umathchar "3"0"002265 } -\def\geqq {\Umathchar "3"0"002267 } -\def\geqslant {\Umathchar "3"0"002A7E } -\def\gets {\Umathchar "3"0"002190 } -\def\gg {\Umathchar "3"0"00226B } -\def\ggg {\Umathchar "3"0"0022D9 } -\def\gggtr {\Umathchar "3"0"0022D9 } -\def\gimel {\Umathchar "0"0"002137 } -\def\gnapprox {\Umathchar "3"0"002A8A } -\def\gneqq {\Umathchar "3"0"002269 } -\def\gnsim {\Umathchar "3"0"0022E7 } -\def\grave {\Umathaccent"0"0"000060 } -\def\gt {\Umathchar "3"0"00003E } -\def\gtrapprox {\Umathchar "3"0"002A86 } -\def\gtrdot {\Umathchar "2"0"0022D7 } -\def\gtreqless {\Umathchar "3"0"0022DB } -\def\gtreqqless {\Umathchar "3"0"002A8C } -\def\gtrless {\Umathchar "3"0"002277 } -\def\gtrsim {\Umathchar "3"0"002273 } -\def\hat {\Umathaccent"0"0"0002C6 } -\def\hbar {\Umathchar "0"0"00210F } -\def\heartsuit {\Umathchar "0"0"002661 } -\def\hookleftarrow {\Umathchar "3"0"0021A9 } -\def\hookrightarrow {\Umathchar "3"0"0021AA } -\def\hslash {\Umathchar "0"0"00210F } -\def\iiint {\Umathchar "1"0"00222D } -\def\iiintop {\Umathchar "0"0"00222D } -\def\iint {\Umathchar "1"0"00222C } -\def\iintop {\Umathchar "0"0"00222C } -\def\Im {\Umathchar "0"0"002111 } -\def\imaginaryi {\Umathchar "0"0"002148 } -\def\imaginaryj {\Umathchar "0"0"002149 } -\def\imath {\Umathchar "0"0"01D6A4 } -\def\imply {\Umathchar "3"0"0021D2 } -\def\in {\Umathchar "0"0"002208 } -\def\infty {\Umathchar "0"0"00221E } -\def\int {\Umathchar "1"0"00222B } -\def\intclockwise {\Umathchar "1"0"002231 } -\def\integers {\Umathchar "0"0"002124 } -\def\intercal {\Umathchar "2"0"0022BA } -\def\intop {\Umathchar "0"0"00222B } -\def\Iota {\Umathchar "0"0"000399 } -\def\iota {\Umathchar "0"0"0003B9 } -\def\jmath {\Umathchar "0"0"01D6A5 } -\def\Join {\Umathchar "3"0"0022C8 } -\def\Kappa {\Umathchar "0"0"00039A } -\def\kappa {\Umathchar "0"0"0003BA } -\def\Lambda {\Umathchar "0"0"00039B } -\def\lambda {\Umathchar "0"0"0003BB } -\def\land {\Umathchar "2"0"002227 } -\def\langle {\Udelimiter "4"0"0027E8 } -\def\lbrace {\Udelimiter "4"0"00007B } -\def\lbrack {\Udelimiter "4"0"00005B } -\def\lceil {\Udelimiter "4"0"002308 } -\def\lceiling {\Udelimiter "4"0"002308 } -\def\ldotp {\Umathchar "6"0"00002E } -\def\ldots {\Umathchar "0"0"002026 } -\def\Ldsh {\Umathchar "3"0"0021B2 } -\def\le {\Umathchar "3"0"002264 } -\def\leadsto {\Umathchar "3"0"0021DD } -\def\leftarrow {\Umathchar "3"0"002190 } -\def\Leftarrow {\Umathchar "3"0"0021D0 } -\def\leftarrowtail {\Umathchar "3"0"0021A2 } -\def\leftarrowtriangle {\Umathchar "3"0"0021FD } -\def\leftdasharrow {\Umathchar "3"0"0021E0 } -\def\leftharpoondown {\Umathchar "3"0"0021BD } -\def\leftharpoonup {\Umathchar "3"0"0021BC } -\def\leftleftarrows {\Umathchar "3"0"0021C7 } -\def\leftrightarrow {\Umathchar "3"0"002194 } -\def\Leftrightarrow {\Umathchar "3"0"0021D4 } -\def\leftrightarrows {\Umathchar "3"0"0021C6 } -\def\leftrightarrowtriangle {\Umathchar "3"0"0021FF } -\def\leftrightharpoons {\Umathchar "3"0"0021CB } -\def\leftrightsquigarrow {\Umathchar "3"0"0021AD } -\def\leftsquigarrow {\Umathchar "3"0"0021DC } -\def\leftthreetimes {\Umathchar "2"0"0022CB } -\def\leftwavearrow {\Umathchar "3"0"00219C } -\def\leftwhitearrow {\Umathchar "0"0"0021E6 } -\def\leq {\Umathchar "3"0"002264 } -\def\leqq {\Umathchar "3"0"002266 } -\def\leqslant {\Umathchar "3"0"002A7D } -\def\lessapprox {\Umathchar "3"0"002A85 } -\def\lessdot {\Umathchar "2"0"0022D6 } -\def\lesseqgtr {\Umathchar "3"0"0022DA } -\def\lesseqqgtr {\Umathchar "3"0"002A8B } -\def\lessgtr {\Umathchar "3"0"002276 } -\def\lesssim {\Umathchar "3"0"002272 } -\def\lfloor {\Udelimiter "4"0"00230A } -\def\lgroup {\Udelimiter "4"0"0027EE } -\def\lhook {\Umathchar "3"0"0FE322 } -\def\lhooknwarrow {\Umathchar "3"0"002923 } -\def\lhooksearrow {\Umathchar "3"0"002925 } -\def\linefeed {\Umathchar "0"0"0021B4 } -\def\ll {\Umathchar "3"0"00226A } -\def\llangle {\Udelimiter "4"0"0027EA } -\def\llbracket {\Udelimiter "4"0"0027E6 } -\def\llcorner {\Udelimiter "4"0"00231E } -\def\Lleftarrow {\Umathchar "3"0"0021DA } -\def\lll {\Umathchar "3"0"0022D8 } -\def\llless {\Umathchar "3"0"0022D8 } -\def\lmoustache {\Udelimiter "4"0"0023B0 } -\def\lnapprox {\Umathchar "3"0"002A89 } -\def\lneq {\Umathchar "3"0"002A87 } -\def\lneqq {\Umathchar "3"0"002268 } -\def\lnot {\Umathchar "0"0"0000AC } -\def\lnsim {\Umathchar "3"0"0022E6 } -\def\longleftarrow {\Umathchar "3"0"0027F5 } -\def\Longleftarrow {\Umathchar "3"0"0027F8 } -\def\longleftrightarrow {\Umathchar "3"0"0027F7 } -\def\Longleftrightarrow {\Umathchar "3"0"0027FA } -\def\longmapsfrom {\Umathchar "3"0"0027FB } -\def\Longmapsfrom {\Umathchar "3"0"0027FD } -\def\longmapsto {\Umathchar "3"0"0027FC } -\def\Longmapsto {\Umathchar "3"0"0027FE } -\def\longrightarrow {\Umathchar "3"0"0027F6 } -\def\Longrightarrow {\Umathchar "3"0"0027F9 } -\def\longrightsquigarrow {\Umathchar "3"0"0027FF } -\def\looparrowleft {\Umathchar "3"0"0021AB } -\def\looparrowright {\Umathchar "3"0"0021AC } -\def\lor {\Umathchar "2"0"002228 } -\def\lozenge {\Umathchar "0"0"0025CA } -\def\lparent {\Udelimiter "4"0"000028 } -\def\lrcorner {\Udelimiter "5"0"00231F } -\def\Lsh {\Umathchar "3"0"0021B0 } -\def\lt {\Umathchar "3"0"00003C } -\def\ltimes {\Umathchar "2"0"0022C9 } -\def\lvert {\Udelimiter "4"0"00007C } -\def\lVert {\Udelimiter "4"0"002016 } -\def\maltese {\Umathchar "0"0"002720 } -\def\mapsdown {\Umathchar "3"0"0021A7 } -\def\mapsfrom {\Umathchar "3"0"0021A4 } -\def\Mapsfrom {\Umathchar "3"0"002906 } -\def\mapsfromchar {\Umathchar "3"0"0FE324 } -\def\mapsto {\Umathchar "3"0"0021A6 } -\def\Mapsto {\Umathchar "3"0"002907 } -\def\mapstochar {\Umathchar "3"0"0FE321 } -\def\mapsup {\Umathchar "3"0"0021A5 } -\def\mathring {\Umathaccent"0"0"0002DA } -\def\measuredangle {\Umathchar "0"0"002221 } -\def\measuredeq {\Umathchar "3"0"00225E } -\def\mho {\Umathchar "0"0"002127 } -\def\mid {\Umathchar "3"0"00007C } -\def\minus {\Umathchar "2"0"002212 } -\def\minuscolon {\Umathchar "2"0"002239 } -\def\models {\Umathchar "3"0"0022A7 } -\def\mp {\Umathchar "2"0"002213 } -\def\Mu {\Umathchar "0"0"00039C } -\def\mu {\Umathchar "0"0"0003BC } -\def\multimap {\Umathchar "3"0"0022B8 } -\def\napprox {\Umathchar "3"0"002249 } -\def\napproxEq {\Umathchar "3"0"002246 } -\def\nasymp {\Umathchar "3"0"00226D } -\def\natural {\Umathchar "0"0"00266E } -\def\naturalnumbers {\Umathchar "0"0"002115 } -\def\ncong {\Umathchar "3"0"002246 } -\def\ndivides {\Umathchar "2"0"002224 } -\def\ne {\Umathchar "3"0"002260 } -\def\nearrow {\Umathchar "3"0"002197 } -\def\Nearrow {\Umathchar "3"0"0021D7 } -\def\neg {\Umathchar "0"0"0000AC } -\def\negativesign {\Umathchar "2"0"00207B } -\def\neq {\Umathchar "3"0"002260 } -\def\nequiv {\Umathchar "3"0"002262 } -\def\neswarrow {\Umathchar "3"0"002922 } -\def\nexists {\Umathchar "0"0"002204 } -\def\ngeq {\Umathchar "3"0"002271 } -\def\ngtr {\Umathchar "3"0"00226F } -\def\ngtrless {\Umathchar "3"0"002279 } -\def\ngtrsim {\Umathchar "3"0"002275 } -\def\nHdownarrow {\Umathchar "3"0"0021DF } -\def\nHuparrow {\Umathchar "3"0"0021DE } -\def\ni {\Umathchar "3"0"00220B } -\def\nin {\Umathchar "3"0"002209 } -\def\nleftarrow {\Umathchar "3"0"00219A } -\def\nLeftarrow {\Umathchar "3"0"0021CD } -\def\nleftrightarrow {\Umathchar "3"0"0021AE } -\def\nLeftrightarrow {\Umathchar "3"0"0021CE } -\def\nleq {\Umathchar "3"0"002270 } -\def\nless {\Umathchar "3"0"00226E } -\def\nlessgtr {\Umathchar "3"0"002278 } -\def\nlesssim {\Umathchar "3"0"002274 } -\def\nmid {\Umathchar "3"0"002224 } -\def\nni {\Umathchar "3"0"00220C } -\def\not {\Umathchar "3"0"000338 } -\def\notin {\Umathchar "3"0"002209 } -\def\nowns {\Umathchar "3"0"00220C } -\def\nparallel {\Umathchar "3"0"002226 } -\def\nprec {\Umathchar "3"0"002280 } -\def\npreccurlyeq {\Umathchar "3"0"0022E0 } -\def\nrightarrow {\Umathchar "3"0"00219B } -\def\nRightarrow {\Umathchar "3"0"0021CF } -\def\nsim {\Umathchar "3"0"002241 } -\def\nsimeq {\Umathchar "3"0"002244 } -\def\nsqsubseteq {\Umathchar "3"0"0022E2 } -\def\nsqsupseteq {\Umathchar "3"0"0022E3 } -\def\nsubset {\Umathchar "3"0"002284 } -\def\nsubseteq {\Umathchar "3"0"002288 } -\def\nsucc {\Umathchar "3"0"002281 } -\def\nsucccurlyeq {\Umathchar "3"0"0022E1 } -\def\nsupset {\Umathchar "3"0"002285 } -\def\nsupseteq {\Umathchar "3"0"002289 } -\def\ntriangleleft {\Umathchar "3"0"0022EB } -\def\ntrianglelefteq {\Umathchar "3"0"0022EC } -\def\ntriangleright {\Umathchar "3"0"0022EA } -\def\ntrianglerighteq {\Umathchar "3"0"0022ED } -\def\Nu {\Umathchar "0"0"00039D } -\def\nu {\Umathchar "0"0"0003BD } -\def\nvdash {\Umathchar "3"0"0022AC } -\def\nvDash {\Umathchar "3"0"0022AD } -\def\nVdash {\Umathchar "3"0"0022AE } -\def\nVDash {\Umathchar "3"0"0022AF } -\def\nvleftarrow {\Umathchar "3"0"0021F7 } -\def\nVleftarrow {\Umathchar "3"0"0021FA } -\def\nvleftrightarrow {\Umathchar "3"0"0021F9 } -\def\nVleftrightarrow {\Umathchar "3"0"0021FC } -\def\nvrightarrow {\Umathchar "3"0"0021F8 } -\def\nVrightarrow {\Umathchar "3"0"0021FB } -\def\nwarrow {\Umathchar "3"0"002196 } -\def\Nwarrow {\Umathchar "3"0"0021D6 } -\def\nwsearrow {\Umathchar "3"0"002921 } -\def\odot {\Umathchar "2"0"002299 } -\def\ohm {\Umathchar "0"0"002126 } -\def\oiiint {\Umathchar "1"0"002230 } -\def\oiint {\Umathchar "1"0"00222F } -\def\oint {\Umathchar "1"0"00222E } -\def\ointclockwise {\Umathchar "1"0"002232 } -\def\ointctrclockwise {\Umathchar "1"0"002233 } -\def\Omega {\Umathchar "0"0"0003A9 } -\def\omega {\Umathchar "0"0"0003C9 } -\def\Omicron {\Umathchar "0"0"00039F } -\def\omicron {\Umathchar "0"0"0003BF } -\def\ominus {\Umathchar "2"0"002296 } -\def\oplus {\Umathchar "2"0"002295 } -\def\oslash {\Umathchar "2"0"002298 } -\def\otimes {\Umathchar "2"0"002297 } -\def\overbar {\Umathaccent"0"0"00203E } -\def\overbrace {\Umathaccent"0"0"0023DE } -\def\overbracket {\Umathaccent"0"0"0023B4 } -\def\overparent {\Umathaccent"0"0"0023DC } -\def\owns {\Umathchar "3"0"00220B } -\def\P {\Umathchar "0"0"0000B6 } -\def\parallel {\Umathchar "3"0"002225 } -\def\partial {\Umathchar "0"0"002202 } -\def\perp {\Umathchar "3"0"0022A5 } -\def\Phi {\Umathchar "0"0"0003A6 } -\def\phi {\Umathchar "0"0"0003D5 } -\def\Pi {\Umathchar "0"0"0003A0 } -\def\pi {\Umathchar "0"0"0003C0 } -\def\pitchfork {\Umathchar "3"0"0022D4 } -\def\Plankconst {\Umathchar "0"0"00210E } -\def\pm {\Umathchar "2"0"0000B1 } -\def\positivesign {\Umathchar "2"0"00207A } -\def\prec {\Umathchar "3"0"00227A } -\def\precapprox {\Umathchar "3"0"002AB7 } -\def\preccurlyeq {\Umathchar "3"0"00227C } -\def\preceq {\Umathchar "3"0"002AAF } -\def\preceqq {\Umathchar "3"0"002AB3 } -\def\precnapprox {\Umathchar "3"0"002AB9 } -\def\precneq {\Umathchar "3"0"002AB1 } -\def\precneqq {\Umathchar "3"0"002AB5 } -\def\precnsim {\Umathchar "3"0"0022E8 } -\def\precsim {\Umathchar "3"0"00227E } -\def\prime {\Umathchar "0"0"002032 } -\def\primes {\Umathchar "0"0"002119 } -\def\prod {\Umathchar "1"0"00220F } -\def\PropertyLine {\Umathchar "0"0"00214A } -\def\propto {\Umathchar "3"0"00221D } -\def\Psi {\Umathchar "0"0"0003A8 } -\def\psi {\Umathchar "0"0"0003C8 } -\def\questionedeq {\Umathchar "3"0"00225F } -\def\rangle {\Udelimiter "5"0"0027E9 } -\def\rationals {\Umathchar "0"0"00211A } -\def\rbrace {\Udelimiter "5"0"00007D } -\def\rbrack {\Udelimiter "5"0"00005D } -\def\rceil {\Udelimiter "5"0"002309 } -\def\rceiling {\Udelimiter "5"0"002309 } -\def\Rdsh {\Umathchar "3"0"0021B3 } -\def\Re {\Umathchar "0"0"00211C } -\def\reals {\Umathchar "0"0"00211D } -\def\Relbar {\Umathchar "3"0"00003D } -\def\relbar {\Umathchar "3"0"002212 } -\def\restriction {\Umathchar "3"0"0021BE } -\def\rfloor {\Udelimiter "5"0"00230B } -\def\rgroup {\Udelimiter "5"0"0027EF } -\def\Rho {\Umathchar "0"0"0003A1 } -\def\rho {\Umathchar "0"0"0003C1 } -\def\rhook {\Umathchar "3"0"0FE323 } -\def\rhooknearrow {\Umathchar "3"0"002924 } -\def\rhookswarrow {\Umathchar "3"0"002926 } -\def\rightangle {\Umathchar "0"0"00221F } -\def\rightarrow {\Umathchar "3"0"002192 } -\def\Rightarrow {\Umathchar "3"0"0021D2 } -\def\rightarrowbar {\Umathchar "3"0"0021E5 } -\def\rightarrowtail {\Umathchar "3"0"0021A3 } -\def\rightarrowtriangle {\Umathchar "3"0"0021FE } -\def\rightdasharrow {\Umathchar "3"0"0021E2 } -\def\rightharpoondown {\Umathchar "3"0"0021C1 } -\def\rightharpoonup {\Umathchar "3"0"0021C0 } -\def\rightleftarrows {\Umathchar "3"0"0021C4 } -\def\rightleftharpoons {\Umathchar "3"0"0021CC } -\def\rightrightarrows {\Umathchar "3"0"0021C9 } -\def\rightsquigarrow {\Umathchar "3"0"0021DD } -\def\rightthreearrows {\Umathchar "3"0"0021F6 } -\def\rightthreetimes {\Umathchar "2"0"0022CC } -\def\rightwavearrow {\Umathchar "3"0"00219D } -\def\rightwhitearrow {\Umathchar "0"0"0021E8 } -\def\risingdotseq {\Umathchar "3"0"002253 } -\def\rmoustache {\Udelimiter "5"0"0023B1 } -\def\rneq {\Umathchar "3"0"002A88 } -\def\rparent {\Udelimiter "5"0"000029 } -\def\rrangle {\Udelimiter "5"0"0027EB } -\def\rrbracket {\Udelimiter "5"0"0027E7 } -\def\Rrightarrow {\Umathchar "3"0"0021DB } -\def\Rsh {\Umathchar "3"0"0021B1 } -\def\rtimes {\Umathchar "2"0"0022CA } -\def\rvert {\Udelimiter "5"0"00007C } -\def\rVert {\Udelimiter "5"0"002016 } -\def\S {\Umathchar "0"0"0000A7 } -\def\searrow {\Umathchar "3"0"002198 } -\def\Searrow {\Umathchar "3"0"0021D8 } -\def\setminus {\Umathchar "2"0"002216 } -\def\sharp {\Umathchar "0"0"00266F } -\def\Sigma {\Umathchar "0"0"0003A3 } -\def\sigma {\Umathchar "0"0"0003C3 } -\def\sim {\Umathchar "3"0"00223C } -\def\simeq {\Umathchar "3"0"002243 } -\def\slash {\Umathchar "0"0"002044 } -\def\smile {\Umathchar "3"0"002323 } -\def\solidus {\Udelimiter "5"0"002044 } -\def\spadesuit {\Umathchar "0"0"002660 } -\def\sphericalangle {\Umathchar "0"0"002222 } -\def\sqcap {\Umathchar "2"0"002293 } -\def\sqcup {\Umathchar "2"0"002294 } -\def\sqsubset {\Umathchar "3"0"00228F } -\def\sqsubseteq {\Umathchar "2"0"002291 } -\def\sqsubsetneq {\Umathchar "3"0"0022E4 } -\def\sqsupset {\Umathchar "3"0"002290 } -\def\sqsupseteq {\Umathchar "2"0"002292 } -\def\sqsupsetneq {\Umathchar "3"0"0022E5 } -\def\square {\Umathchar "0"0"0025A1 } -\def\squaredots {\Umathchar "3"0"002237 } -\def\star {\Umathchar "2"0"0022C6 } -\def\stareq {\Umathchar "3"0"00225B } -\def\subset {\Umathchar "3"0"002282 } -\def\Subset {\Umathchar "3"0"0022D0 } -\def\subseteq {\Umathchar "3"0"002286 } -\def\subseteqq {\Umathchar "3"0"002AC5 } -\def\subsetneq {\Umathchar "3"0"00228A } -\def\subsetneqq {\Umathchar "3"0"002ACB } -\def\succ {\Umathchar "3"0"00227B } -\def\succapprox {\Umathchar "3"0"002AB8 } -\def\succcurlyeq {\Umathchar "3"0"00227D } -\def\succeq {\Umathchar "3"0"002AB0 } -\def\succeqq {\Umathchar "3"0"002AB4 } -\def\succnapprox {\Umathchar "3"0"002ABA } -\def\succneq {\Umathchar "3"0"002AB2 } -\def\succneqq {\Umathchar "3"0"002AB6 } -\def\succnsim {\Umathchar "3"0"0022E9 } -\def\succsim {\Umathchar "3"0"00227F } -\def\sum {\Umathchar "1"0"002211 } -\def\supset {\Umathchar "3"0"002283 } -\def\Supset {\Umathchar "3"0"0022D1 } -\def\supseteq {\Umathchar "3"0"002287 } -\def\supseteqq {\Umathchar "3"0"002AC6 } -\def\supsetneq {\Umathchar "3"0"00228B } -\def\supsetneqq {\Umathchar "3"0"002ACC } -\def\surd {\Umathchar "2"0"00221A } -\def\swarrow {\Umathchar "3"0"002199 } -\def\Swarrow {\Umathchar "3"0"0021D9 } -\def\Tau {\Umathchar "0"0"0003A4 } -\def\tau {\Umathchar "0"0"0003C4 } -\def\therefore {\Umathchar "3"0"002234 } -\def\Theta {\Umathchar "0"0"000398 } -\def\theta {\Umathchar "0"0"0003B8 } -\def\tilde {\Umathaccent"0"0"0002DC } -\def\times {\Umathchar "2"0"0000D7 } -\def\to {\Umathchar "3"0"002192 } -\def\top {\Umathchar "0"0"0022A4 } -\def\triangle {\Umathchar "0"0"0025B3 } -\def\triangledown {\Umathchar "2"0"0025BD } -\def\triangleleft {\Umathchar "2"0"0025C1 } -\def\triangleq {\Umathchar "3"0"00225C } -\def\triangleright {\Umathchar "2"0"0025B7 } -\def\tripleprime {\Umathchar "0"0"002034 } -\def\turnediota {\Umathchar "0"0"002129 } -\def\twoheaddownarrow {\Umathchar "3"0"0021A1 } -\def\twoheadleftarrow {\Umathchar "3"0"00219E } -\def\twoheadrightarrow {\Umathchar "3"0"0021A0 } -\def\twoheadrightarrowtail {\Umathchar "3"0"002916 } -\def\twoheaduparrow {\Umathchar "3"0"00219F } -\def\udots {\Umathchar "0"0"0022F0 } -\def\ulcorner {\Udelimiter "4"0"00231C } -\def\underbar {\Umathaccent bottom "0"0"00203E } -\def\underbrace {\Umathaccent bottom "0"0"0023DF } -\def\underbracket {\Umathaccent bottom "0"0"0023B5 } -\def\underparent {\Umathaccent bottom "0"0"0023DD } -\def\upand {\Umathchar "2"0"00214B } -\def\uparrow {\Umathchar "3"0"002191 } -\def\Uparrow {\Umathchar "3"0"0021D1 } -\def\updasharrow {\Umathchar "3"0"0021E1 } -\def\updownarrow {\Umathchar "3"0"002195 } -\def\Updownarrow {\Umathchar "3"0"0021D5 } -\def\updownarrowbar {\Umathchar "0"0"0021A8 } -\def\updownarrows {\Umathchar "3"0"0021C5 } -\def\upharpoonleft {\Umathchar "3"0"0021BF } -\def\upharpoonright {\Umathchar "3"0"0021BE } -\def\uplus {\Umathchar "2"0"00228E } -\def\Upsilon {\Umathchar "0"0"0003A5 } -\def\upsilon {\Umathchar "0"0"0003C5 } -\def\upuparrows {\Umathchar "3"0"0021C8 } -\def\upwhitearrow {\Umathchar "0"0"0021E7 } -\def\urcorner {\Udelimiter "5"0"00231D } -\def\Uuparrow {\Umathchar "3"0"00290A } -\def\varepsilon {\Umathchar "0"0"0003B5 } -\def\varkappa {\Umathchar "0"0"0003F0 } -\def\varkappa {\Umathchar "0"0"0003F0 } -\def\varnothing {\Umathchar "0"0"002300 } -\def\varphi {\Umathchar "0"0"0003C6 } -\def\varpi {\Umathchar "0"0"0003D6 } -\def\varrho {\Umathchar "0"0"01D71A } -\def\varsigma {\Umathchar "0"0"0003C2 } -\def\vartheta {\Umathchar "0"0"01D717 } -\def\varTheta {\Umathchar "0"0"0003D1 } -\def\vdash {\Umathchar "3"0"0022A2 } -\def\vDash {\Umathchar "3"0"0022A8 } -\def\Vdash {\Umathchar "3"0"0022A9 } -\def\VDash {\Umathchar "3"0"0022AB } -\def\vdots {\Umathchar "0"0"0022EE } -\def\vec {\Umathaccent"0"0"0020D7 } -\def\vee {\Umathchar "2"0"002228 } -\def\veebar {\Umathchar "2"0"0022BB } -\def\veeeq {\Umathchar "3"0"00225A } -\def\vert {\Udelimiter "0"0"00007C } -\def\Vert {\Udelimiter "0"0"002016 } -\def\Vvdash {\Umathchar "3"0"0022AA } -\def\wedge {\Umathchar "2"0"002227 } -\def\wedgeeq {\Umathchar "3"0"002259 } -\def\whitearrowupfrombar {\Umathchar "0"0"0021EB } -\def\widehat {\Umathaccent"0"0"000302 } -\def\widetilde {\Umathaccent"0"0"000303 } -\def\wp {\Umathchar "0"0"002118 } -\def\wr {\Umathchar "2"0"002240 } -\def\Xi {\Umathchar "0"0"00039E } -\def\xi {\Umathchar "0"0"0003BE } -\def\yen {\Umathchar "0"0"0000A5 } -\def\Zeta {\Umathchar "0"0"000396 } -\def\zeta {\Umathchar "0"0"0003B6 } - -% a few definitions: - -\def\sqrt {\Uroot "0 "221A{}} -\def\root#1\of{\Uroot "0 "221A{#1}} - -% \skewchar\teni='177 \skewchar\seveni='177 \skewchar\fivei='177 -% \skewchar\tensy='60 \skewchar\sevensy='60 \skewchar\fivesy='60 - -\chardef\% = "25 -\chardef\& = "26 -\chardef\# = "23 -\chardef\$ = "24 -\chardef\_ = "5F - -\let\ss ß -\let\ae æ -\let\oe œ -\let\o ø -\let\AE Æ -\let\OE Œ -\let\O Ø -\let\i ı -\let\aa å -\let\l ł -\let\L Ł -\let\AA Å -\let\copyright © - -% just use utf - -\def\`#1{\string\`\string{#1\string}} -\def\'#1{\string\'\string{#1\string}} -\def\v#1{\string\v\string{#1\string}} -\def\u#1{\string\u\string{#1\string}} -\def\=#1{\string\=\string{#1\string}} -\def\^#1{\string\^\string{#1\string}} -\def\.#1{\string\.\string{#1\string}} -\def\H#1{\string\H\string{#1\string}} -\def\~#1{\string\~\string{#1\string}} -\def\"#1{\string\"\string{#1\string}} -\def\d#1{\string\d\string{#1\string}} -\def\b#1{\string\b\string{#1\string}} -\def\c#1{\string\c\string{#1\string}} - -\endinput diff --git a/tex/compat/luaotfload/fontloader-mplib.lua b/tex/compat/luaotfload/fontloader-mplib.lua deleted file mode 100644 index 976bb59f91bbcd0d32cb9c843e92b4bbe599a333..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/fontloader-mplib.lua +++ /dev/null @@ -1,591 +0,0 @@ -if not modules then modules = { } end modules ['luatex-mplib'] = { - version = 1.001, - comment = "companion to luatex-mplib.tex", - author = "Hans Hagen & Taco Hoekwater", - copyright = "ConTeXt Development Team", - license = "public domain", -} - ---[[ldx-- -<p>This module is a stripped down version of libraries that are used -by <l n='context'/>. It can be used in other macro packages and/or -serve as an example. Embedding in a macro package is upto others and -normally boils down to inputting <t>supp-mpl.tex</t>.</p> ---ldx]]-- - -if metapost and metapost.version then - - --[[ldx-- - <p>Let's silently quit and make sure that no one loads it - manually in <l n='context'/>.</p> - --ldx]]-- - -else - - local format, match, gsub = string.format, string.match, string.gsub - local concat = table.concat - local abs = math.abs - - local mplib = require ('mplib') - local kpse = require ('kpse') - - --[[ldx-- - <p>We create a namespace and some variables to it. If a namespace is - already defined it wil not be initialized. This permits hooking - in code beforehand.</p> - - <p>We don't make a format automatically. After all, distributions - might have their own preferences and normally a format (mem) file will - have some special place in the <l n='tex'/> tree. Also, there can already - be format files, different memort settings and other nasty pitfalls that - we don't want to interfere with. If you want, you can define a function - <t>metapost.make(name,mem_name) that does the job.</t></p> - --ldx]]-- - - metapost = metapost or { } - metapost.version = 1.00 - metapost.showlog = metapost.showlog or false - metapost.lastlog = "" - - --[[ldx-- - <p>A few helpers, taken from <t>l-file.lua</t>.</p> - --ldx]]-- - - local file = file or { } - - function file.replacesuffix(filename, suffix) - return (string.gsub(filename,"%.[%a%d]+$","")) .. "." .. suffix - end - - function file.stripsuffix(filename) - return (string.gsub(filename,"%.[%a%d]+$","")) - end - - --[[ldx-- - <p>We use the <l n='kpse'/> library unless a finder is already - defined.</p> - --ldx]]-- - - local mpkpse = kpse.new("luatex","mpost") - - metapost.finder = metapost.finder or function(name, mode, ftype) - if mode == "w" then - return name - else - return mpkpse:find_file(name,ftype) - end - end - - --[[ldx-- - <p>You can use your own reported if needed, as long as it handles multiple - arguments and formatted strings.</p> - --ldx]]-- - - metapost.report = metapost.report or function(...) - texio.write(format("<mplib: %s>",format(...))) - end - - --[[ldx-- - <p>The rest of this module is not documented. More info can be found in the - <l n='luatex'/> manual, articles in user group journals and the files that - ship with <l n='context'/>.</p> - --ldx]]-- - - function metapost.resetlastlog() - metapost.lastlog = "" - end - - local mplibone = tonumber(mplib.version()) <= 1.50 - - if mplibone then - - metapost.make = metapost.make or function(name,mem_name,dump) - local t = os.clock() - local mpx = mplib.new { - ini_version = true, - find_file = metapost.finder, - job_name = file.stripsuffix(name) - } - mpx:execute(string.format("input %s ;",name)) - if dump then - mpx:execute("dump ;") - metapost.report("format %s made and dumped for %s in %0.3f seconds",mem_name,name,os.clock()-t) - else - metapost.report("%s read in %0.3f seconds",name,os.clock()-t) - end - return mpx - end - - function metapost.load(name) - local mem_name = file.replacesuffix(name,"mem") - local mpx = mplib.new { - ini_version = false, - mem_name = mem_name, - find_file = metapost.finder - } - if not mpx and type(metapost.make) == "function" then - -- when i have time i'll locate the format and dump - mpx = metapost.make(name,mem_name) - end - if mpx then - metapost.report("using format %s",mem_name,false) - return mpx, nil - else - return nil, { status = 99, error = "out of memory or invalid format" } - end - end - - else - - local preamble = [[ - boolean mplib ; mplib := true ; - let dump = endinput ; - input %s ; - ]] - - metapost.make = metapost.make or function() - end - - local template = [[ - \pdfoutput=1 - \pdfpkresolution600 - \pdfcompresslevel=9 - %s\relax - \hsize=100in - \vsize=\hsize - \hoffset=-1in - \voffset=\hoffset - \topskip=0pt - \setbox0=\hbox{%s}\relax - \pageheight=\ht0 - \pagewidth=\wd0 - \box0 - \bye - ]] - - metapost.texrunner = "mtxrun --script plain" - - local texruns = 0 -- per document - local texhash = { } -- per document - - function metapost.maketext(mpd,str,what) - -- inefficient but one can always use metafun .. it's more a test - -- feature - local verbatimtex = mpd.verbatimtex - if not verbatimtex then - verbatimtex = { } - mpd.verbatimtex = verbatimtex - end - if what == 1 then - table.insert(verbatimtex,str) - else - local texcode = format(template,concat(verbatimtex,"\n"),str) - local texdone = texhash[texcode] - local jobname = tex.jobname - if not texdone then - texruns = texruns + 1 - texdone = texruns - texhash[texcode] = texdone - local texname = format("%s-mplib-%s.tmp",jobname,texdone) - local logname = format("%s-mplib-%s.log",jobname,texdone) - local pdfname = format("%s-mplib-%s.pdf",jobname,texdone) - io.savedata(texname,texcode) - os.execute(format("%s %s",metapost.texrunner,texname)) - os.remove(texname) - os.remove(logname) - end - return format('"image::%s-mplib-%s.pdf" infont defaultfont',jobname,texdone) - end - end - - local function mpprint(buffer,...) - for i=1,select("#",...) do - local value = select(i,...) - if value ~= nil then - local t = type(value) - if t == "number" then - buffer[#buffer+1] = format("%.16f",value) - elseif t == "string" then - buffer[#buffer+1] = value - elseif t == "table" then - buffer[#buffer+1] = "(" .. concat(value,",") .. ")" - else -- boolean or whatever - buffer[#buffer+1] = tostring(value) - end - end - end - end - - function metapost.runscript(mpd,code) - local code = loadstring(code) - if type(code) == "function" then - local buffer = { } - function metapost.print(...) - mpprint(buffer,...) - end - code() - -- mpd.buffer = buffer -- for tracing - return concat(buffer,"") - end - return "" - end - - function metapost.load(name) - local mpd = { - buffer = { }, - verbatim = { } - } - local mpx = mplib.new { - ini_version = true, - find_file = metapost.finder, - make_text = function(...) return metapost.maketext (mpd,...) end, - run_script = function(...) return metapost.runscript(mpd,...) end, - extensions = 1, - } - local result - if not mpx then - result = { status = 99, error = "out of memory"} - else - result = mpx:execute(format(preamble, file.replacesuffix(name,"mp"))) - end - metapost.reporterror(result) - return mpx, result - end - - end - - function metapost.unload(mpx) - if mpx then - mpx:finish() - end - end - - function metapost.reporterror(result) - if not result then - metapost.report("mp error: no result object returned") - elseif result.status > 0 then - local t, e, l = result.term, result.error, result.log - if t then - metapost.report("mp terminal: %s",t) - end - if e then - metapost.report("mp error: %s", e) - end - if not t and not e and l then - metapost.lastlog = metapost.lastlog .. "\n " .. l - metapost.report("mp log: %s",l) - else - metapost.report("mp error: unknown, no error, terminal or log messages") - end - else - return false - end - return true - end - - function metapost.process(mpx, data) - local converted, result = false, {} - mpx = metapost.load(mpx) - if mpx and data then - local result = mpx:execute(data) - if not result then - metapost.report("mp error: no result object returned") - elseif result.status > 0 then - metapost.report("mp error: %s",(result.term or "no-term") .. "\n" .. (result.error or "no-error")) - elseif metapost.showlog then - metapost.lastlog = metapost.lastlog .. "\n" .. result.term - metapost.report("mp info: %s",result.term or "no-term") - elseif result.fig then - converted = metapost.convert(result) - else - metapost.report("mp error: unknown error, maybe no beginfig/endfig") - end - else - metapost.report("mp error: mem file not found") - end - return converted, result - end - - local function getobjects(result,figure,f) - return figure:objects() - end - - function metapost.convert(result,flusher) - metapost.flush(result,flusher) - return true -- done - end - - --[[ldx-- - <p>We removed some message and tracing code. We might even remove the flusher</p> - --ldx]]-- - - local function pdf_startfigure(n,llx,lly,urx,ury) - tex.sprint(format("\\startMPLIBtoPDF{%s}{%s}{%s}{%s}",llx,lly,urx,ury)) - end - - local function pdf_stopfigure() - tex.sprint("\\stopMPLIBtoPDF") - end - - function pdf_literalcode(fmt,...) -- table - tex.sprint(format("\\MPLIBtoPDF{%s}",format(fmt,...))) - end - - function pdf_textfigure(font,size,text,width,height,depth) - local how, what = match(text,"^(.-)::(.+)$") - if how == "image" then - tex.sprint(format("\\MPLIBpdftext{%s}{%s}",what,depth)) - else - text = gsub(text,".","\\hbox{%1}") -- kerning happens in metapost - tex.sprint(format("\\MPLIBtextext{%s}{%s}{%s}{%s}",font,size,text,depth)) - end - end - - local bend_tolerance = 131/65536 - - local rx, sx, sy, ry, tx, ty, divider = 1, 0, 0, 1, 0, 0, 1 - - local function pen_characteristics(object) - local t = mplib.pen_info(object) - rx, ry, sx, sy, tx, ty = t.rx, t.ry, t.sx, t.sy, t.tx, t.ty - divider = sx*sy - rx*ry - return not (sx==1 and rx==0 and ry==0 and sy==1 and tx==0 and ty==0), t.width - end - - local function concatinated(px, py) -- no tx, ty here - return (sy*px-ry*py)/divider,(sx*py-rx*px)/divider - end - - local function curved(ith,pth) - local d = pth.left_x - ith.right_x - if abs(ith.right_x - ith.x_coord - d) <= bend_tolerance and abs(pth.x_coord - pth.left_x - d) <= bend_tolerance then - d = pth.left_y - ith.right_y - if abs(ith.right_y - ith.y_coord - d) <= bend_tolerance and abs(pth.y_coord - pth.left_y - d) <= bend_tolerance then - return false - end - end - return true - end - - local function flushnormalpath(path,open) - local pth, ith - for i=1,#path do - pth = path[i] - if not ith then - pdf_literalcode("%f %f m",pth.x_coord,pth.y_coord) - elseif curved(ith,pth) then - pdf_literalcode("%f %f %f %f %f %f c",ith.right_x,ith.right_y,pth.left_x,pth.left_y,pth.x_coord,pth.y_coord) - else - pdf_literalcode("%f %f l",pth.x_coord,pth.y_coord) - end - ith = pth - end - if not open then - local one = path[1] - if curved(pth,one) then - pdf_literalcode("%f %f %f %f %f %f c",pth.right_x,pth.right_y,one.left_x,one.left_y,one.x_coord,one.y_coord ) - else - pdf_literalcode("%f %f l",one.x_coord,one.y_coord) - end - elseif #path == 1 then - -- special case .. draw point - local one = path[1] - pdf_literalcode("%f %f l",one.x_coord,one.y_coord) - end - return t - end - - local function flushconcatpath(path,open) - pdf_literalcode("%f %f %f %f %f %f cm", sx, rx, ry, sy, tx ,ty) - local pth, ith - for i=1,#path do - pth = path[i] - if not ith then - pdf_literalcode("%f %f m",concatinated(pth.x_coord,pth.y_coord)) - elseif curved(ith,pth) then - local a, b = concatinated(ith.right_x,ith.right_y) - local c, d = concatinated(pth.left_x,pth.left_y) - pdf_literalcode("%f %f %f %f %f %f c",a,b,c,d,concatinated(pth.x_coord, pth.y_coord)) - else - pdf_literalcode("%f %f l",concatinated(pth.x_coord, pth.y_coord)) - end - ith = pth - end - if not open then - local one = path[1] - if curved(pth,one) then - local a, b = concatinated(pth.right_x,pth.right_y) - local c, d = concatinated(one.left_x,one.left_y) - pdf_literalcode("%f %f %f %f %f %f c",a,b,c,d,concatinated(one.x_coord, one.y_coord)) - else - pdf_literalcode("%f %f l",concatinated(one.x_coord,one.y_coord)) - end - elseif #path == 1 then - -- special case .. draw point - local one = path[1] - pdf_literalcode("%f %f l",concatinated(one.x_coord,one.y_coord)) - end - return t - end - - --[[ldx-- - <p>Support for specials has been removed.</p> - --ldx]]-- - - function metapost.flush(result,flusher) - if result then - local figures = result.fig - if figures then - for f=1, #figures do - metapost.report("flushing figure %s",f) - local figure = figures[f] - local objects = getobjects(result,figure,f) - local fignum = tonumber(match(figure:filename(),"([%d]+)$") or figure:charcode() or 0) - local miterlimit, linecap, linejoin, dashed = -1, -1, -1, false - local bbox = figure:boundingbox() - local llx, lly, urx, ury = bbox[1], bbox[2], bbox[3], bbox[4] -- faster than unpack - if urx < llx then - -- invalid - pdf_startfigure(fignum,0,0,0,0) - pdf_stopfigure() - else - pdf_startfigure(fignum,llx,lly,urx,ury) - pdf_literalcode("q") - if objects then - for o=1,#objects do - local object = objects[o] - local objecttype = object.type - if objecttype == "start_bounds" or objecttype == "stop_bounds" then - -- skip - elseif objecttype == "start_clip" then - pdf_literalcode("q") - flushnormalpath(object.path,t,false) - pdf_literalcode("W n") - elseif objecttype == "stop_clip" then - pdf_literalcode("Q") - miterlimit, linecap, linejoin, dashed = -1, -1, -1, false - elseif objecttype == "special" then - -- not supported - elseif objecttype == "text" then - local ot = object.transform -- 3,4,5,6,1,2 - pdf_literalcode("q %f %f %f %f %f %f cm",ot[3],ot[4],ot[5],ot[6],ot[1],ot[2]) - pdf_textfigure(object.font,object.dsize,object.text,object.width,object.height,object.depth) - pdf_literalcode("Q") - else - local cs = object.color - local cr = false - if cs and #cs > 0 then - cs, cr = metapost.colorconverter(cs) - pdf_literalcode(cs) - end - local ml = object.miterlimit - if ml and ml ~= miterlimit then - miterlimit = ml - pdf_literalcode("%f M",ml) - end - local lj = object.linejoin - if lj and lj ~= linejoin then - linejoin = lj - pdf_literalcode("%i j",lj) - end - local lc = object.linecap - if lc and lc ~= linecap then - linecap = lc - pdf_literalcode("%i J",lc) - end - local dl = object.dash - if dl then - local d = format("[%s] %i d",concat(dl.dashes or {}," "),dl.offset) - if d ~= dashed then - dashed = d - pdf_literalcode(dashed) - end - elseif dashed then - pdf_literalcode("[] 0 d") - dashed = false - end - local path = object.path - local transformed, penwidth = false, 1 - local open = path and path[1].left_type and path[#path].right_type - local pen = object.pen - if pen then - if pen.type == 'elliptical' then - transformed, penwidth = pen_characteristics(object) -- boolean, value - pdf_literalcode("%f w",penwidth) - if objecttype == 'fill' then - objecttype = 'both' - end - else -- calculated by mplib itself - objecttype = 'fill' - end - end - if transformed then - pdf_literalcode("q") - end - if path then - if transformed then - flushconcatpath(path,open) - else - flushnormalpath(path,open) - end - if objecttype == "fill" then - pdf_literalcode("h f") - elseif objecttype == "outline" then - pdf_literalcode((open and "S") or "h S") - elseif objecttype == "both" then - pdf_literalcode("h B") - end - end - if transformed then - pdf_literalcode("Q") - end - local path = object.htap - if path then - if transformed then - pdf_literalcode("q") - end - if transformed then - flushconcatpath(path,open) - else - flushnormalpath(path,open) - end - if objecttype == "fill" then - pdf_literalcode("h f") - elseif objecttype == "outline" then - pdf_literalcode((open and "S") or "h S") - elseif objecttype == "both" then - pdf_literalcode("h B") - end - if transformed then - pdf_literalcode("Q") - end - end - if cr then - pdf_literalcode(cr) - end - end - end - end - pdf_literalcode("Q") - pdf_stopfigure() - end - end - end - end - end - - function metapost.colorconverter(cr) - local n = #cr - if n == 4 then - local c, m, y, k = cr[1], cr[2], cr[3], cr[4] - return format("%.3f %.3f %.3f %.3f k %.3f %.3f %.3f %.3f K",c,m,y,k,c,m,y,k), "0 g 0 G" - elseif n == 3 then - local r, g, b = cr[1], cr[2], cr[3] - return format("%.3f %.3f %.3f rg %.3f %.3f %.3f RG",r,g,b,r,g,b), "0 g 0 G" - else - local s = cr[1] - return format("%.3f g %.3f G",s,s), "0 g 0 G" - end - end - -end diff --git a/tex/compat/luaotfload/fontloader-mplib.tex b/tex/compat/luaotfload/fontloader-mplib.tex deleted file mode 100644 index f9de4b223f4c9543ca977f51ce09dbda9e21712c..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/fontloader-mplib.tex +++ /dev/null @@ -1,140 +0,0 @@ -%D \module -%D [ file=luatex-mplib, -%D version=2009.12.01, -%D title=\LUATEX\ Support Macros, -%D subtitle=\METAPOST\ to \PDF\ conversion, -%D author=Taco Hoekwater \& Hans Hagen, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] - -%D This is the companion to the \LUA\ module \type {supp-mpl.lua}. Further -%D embedding is up to others. A simple example of usage in plain \TEX\ is: -%D -%D \starttyping -%D \pdfoutput=1 -%D -%D \input luatex-mplib.tex -%D -%D \setmplibformat{plain} -%D -%D \mplibcode -%D beginfig(1); -%D draw fullcircle -%D scaled 10cm -%D withcolor red -%D withpen pencircle xscaled 4mm yscaled 2mm rotated 30 ; -%D endfig; -%D \endmplibcode -%D -%D \end -%D \stoptyping - -\def\setmplibformat#1{\def\mplibformat{#1}} - -\def\setupmplibcatcodes - {\catcode`\{=12 % could be optional .. not really needed - \catcode`\}=12 % could be optional .. not really needed - \catcode`\#=12 - \catcode`\^=12 - \catcode`\~=12 - \catcode`\_=12 - \catcode`\%=12 - \catcode`\&=12 - \catcode`\$=12 } - -\def\mplibcode - {\bgroup - \setupmplibcatcodes - \domplibcode} - -\long\def\domplibcode#1\endmplibcode - {\egroup - \directlua{metapost.process('\mplibformat',[[#1]])}} - -%D We default to \type {plain} \METAPOST: - -\def\mplibformat{plain} - -%D We use a dedicated scratchbox: - -\ifx\mplibscratchbox\undefined \newbox\mplibscratchbox \fi - -%D Now load the needed \LUA\ code. - -\directlua{dofile(kpse.find_file('luatex-mplib.lua'))} -% \directlua{dofile(resolvers.findfile('luatex-mplib.lua'))} - -%D The following code takes care of encapsulating the literals: - -\def\startMPLIBtoPDF#1#2#3#4% - {\hbox\bgroup - \xdef\MPllx{#1}\xdef\MPlly{#2}% - \xdef\MPurx{#3}\xdef\MPury{#4}% - \xdef\MPwidth{\the\dimexpr#3bp-#1bp\relax}% - \xdef\MPheight{\the\dimexpr#4bp-#2bp\relax}% - \parskip0pt% - \leftskip0pt% - \parindent0pt% - \everypar{}% - \setbox\mplibscratchbox\vbox\bgroup - \noindent} - -\def\stopMPLIBtoPDF - {\egroup - \setbox\mplibscratchbox\hbox - {\hskip-\MPllx bp% - \raise-\MPlly bp% - \box\mplibscratchbox}% - \setbox\mplibscratchbox\vbox to \MPheight - {\vfill - \hsize\MPwidth - \wd\mplibscratchbox0pt% - \ht\mplibscratchbox0pt% - \dp\mplibscratchbox0pt% - \box\mplibscratchbox}% - \wd\mplibscratchbox\MPwidth - \ht\mplibscratchbox\MPheight - \box\mplibscratchbox - \egroup} - -%D The body of picture, except for text items, is taken care of by: - -\ifnum\pdfoutput>0 - \let\MPLIBtoPDF\pdfliteral -\else - \def\MPLIBtoPDF#1{\special{pdf:literal direct #1}} % not ok yet -\fi - -%D Text items have a special handler: - -\def\MPLIBtextext#1#2#3#4% - {\begingroup - \setbox\mplibscratchbox\hbox - {\font\temp=#1 at #2bp% - \temp - #3}% - \setbox\mplibscratchbox\hbox - {\raise#4sp% - \box\mplibscratchbox}% - \wd\mplibscratchbox0pt% - \ht\mplibscratchbox0pt% - \dp\mplibscratchbox0pt% - \box\mplibscratchbox - \endgroup} - -\def\MPLIBpdftext#1#2% - {\ifcsname mplib::#1\endcsname - % already done, forgotten outside convert group - \message{<reusing mplib: #1>}% - \else - \message{<embedding mplib: #1>}% - \immediate\pdfximage{#1}% we cannot remove the file as it is included last - \expandafter\edef\csname mplib::#1\endcsname{\the\pdflastximage}% - \fi - \setbox\mplibscratchbox\hbox - {\raise#2sp\hbox{\pdfrefximage\csname mplib::#1\endcsname}}% - \wd\mplibscratchbox0pt% - \ht\mplibscratchbox0pt% - \dp\mplibscratchbox0pt% - \box\mplibscratchbox} - -\endinput diff --git a/tex/compat/luaotfload/fontloader-plain.tex b/tex/compat/luaotfload/fontloader-plain.tex deleted file mode 100644 index 0a806c76ff13cdab5618f83ba852d07907e95718..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/fontloader-plain.tex +++ /dev/null @@ -1,55 +0,0 @@ -%D \module -%D [ file=luatex-plain, -%D version=2009.12.01, -%D title=\LUATEX\ Macros, -%D subtitle=Plain Format, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] - -\input plain - -\directlua {tex.enableprimitives('', tex.extraprimitives())} - -% We assume that pdf is used. - -\ifdefined\pdfextension - \input luatex-pdf \relax -\fi - -\outputmode 1 - -% \outputmode 0 \magnification\magstep5 - -% We set the page dimensions because otherwise the backend does weird things -% when we have for instance this on a line of its own: -% -% \hbox to 100cm {\hss wide indeed\hss} -% -% The page dimension calculation is a fuzzy one as there are some compensations -% for the \hoffset and \voffset and such. I remember long discussions and much -% trial and error in figuring this out during pdftex development times. Where -% a dvi driver will project on a papersize (and thereby clip) the pdf backend -% has to deal with the lack of a page concept on tex by some guessing. Normally -% a macro package will set the dimensions to something reasonable anyway. - -\pagewidth 8.5truein -\pageheight 11.0truein - -% We load some code at runtime: - -\everyjob \expandafter {% - \the\everyjob - \input {luatex-basics}% - \input {luatex-fonts}% - \input {luatex-math}% - \input {luatex-languages}% - \input {luatex-mplib}% - \input {luatex-gadgets}% -} - -% We also patch the version number: - -\edef\fmtversion{\fmtversion+luatex} - -\dump diff --git a/tex/compat/luaotfload/fontloader-preprocessor-test.tex b/tex/compat/luaotfload/fontloader-preprocessor-test.tex deleted file mode 100644 index 857b28f831bc532fb8446abd406c5bf847a832e6..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/fontloader-preprocessor-test.tex +++ /dev/null @@ -1,30 +0,0 @@ -\ifdefined\inputpreprocessed - - \def\TestOne[#1]% - {test one: [#1]\par} - - \def\TestTwo#some% - {test two: #some\par} - - \def\TestThree[#whatever][#more]% - {test three: [#more] and [#whatever]\par} - - \def\TestFour[#one]#two% - {\def\TestFive[#alpha][#one]% - {test four and five: [#one], [#two] and [#alpha]}\par} - - \def\TestSix[#{one}]#{two}% - {test six: [#{one}] and #{two}\par} - - \TestOne [one] - \TestTwo {one} - \TestThree[one][two] - \TestFour [one]{two} - \TestFive [one][two] - \TestSix [one]{two} - -\else - \input{luatex-preprocessor.tex} - \inputpreprocessed{luatex-preprocessor-test.tex} - \expandafter \end -\fi diff --git a/tex/compat/luaotfload/fontloader-preprocessor.lua b/tex/compat/luaotfload/fontloader-preprocessor.lua deleted file mode 100644 index 8faa0b47e693bd2af063363d9240d26248b8d640..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/fontloader-preprocessor.lua +++ /dev/null @@ -1,163 +0,0 @@ -if not modules then modules = { } end modules ['luatex-preprocessor'] = { - version = 1.001, - comment = "companion to luatex-preprocessor.tex", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - ---[[ldx -<p>This is a stripped down version of the preprocessor. In -<l n='context'/> we have a bit more, use a different logger, and -use a few optimizations. A few examples are shown at the end.</p> ---ldx]] - -local rep, sub, gmatch = string.rep, string.sub, string.gmatch -local insert, remove = table.insert, table.remove -local setmetatable = setmetatable - -local stack, top, n, hashes = { }, nil, 0, { } - -local function set(s) - if top then - n = n + 1 - if n > 9 then - texio.write_nl("number of arguments > 9, ignoring: " .. s) - else - local ns = #stack - local h = hashes[ns] - if not h then - h = rep("#",ns) - hashes[ns] = h - end - m = h .. n - top[s] = m - return m - end - end -end - -local function get(s) - local m = top and top[s] or s - return m -end - -local function push() - top = { } - n = 0 - local s = stack[#stack] - if s then - setmetatable(top,{ __index = s }) - end - insert(stack,top) -end - -local function pop() - top = remove(stack) -end - -local leftbrace = lpeg.P("{") -local rightbrace = lpeg.P("}") -local escape = lpeg.P("\\") - -local space = lpeg.P(" ") -local spaces = space^1 -local newline = lpeg.S("\r\n") -local nobrace = 1 - leftbrace - rightbrace - -local name = lpeg.R("AZ","az")^1 -local longname = (leftbrace/"") * (nobrace^1) * (rightbrace/"") -local variable = lpeg.P("#") * lpeg.Cs(name + longname) -local escapedname = escape * name -local definer = escape * (lpeg.P("def") + lpeg.P("egdx") * lpeg.P("def")) -local anything = lpeg.P(1) -local always = lpeg.P(true) - -local pushlocal = always / push -local poplocal = always / pop -local declaration = variable / set -local identifier = variable / get - -local function matcherror(str,pos) - texio.write_nl("runaway definition at: " .. sub(str,pos-30,pos)) -end - -local parser = lpeg.Cs { "converter", - definition = pushlocal - * definer - * escapedname - * (declaration + (1-leftbrace))^0 - * lpeg.V("braced") - * poplocal, - braced = leftbrace - * ( lpeg.V("definition") - + identifier - + lpeg.V("braced") - + nobrace - )^0 - * (rightbrace + lpeg.Cmt(always,matcherror)), - converter = (lpeg.V("definition") + anything)^1, -} - ---[[ldx -<p>We provide a few commands.</p> ---ldx]] - --- local texkpse - -local function find_file(...) - -- texkpse = texkpse or kpse.new("luatex","tex") - -- return texkpse:find_file(...) or "" - return kpse.find_file(...) or "" -end - -commands = commands or { } - -function commands.preprocessed(str) - return lpeg.match(parser,str) -end - -function commands.inputpreprocessed(name) - local name = find_file(name) or "" - if name ~= "" then - -- we could use io.loaddata as it's loaded in luatex-plain - local f = io.open(name,'rb') - if f then - texio.write("("..name) - local d = commands.preprocessed(f:read("*a")) - if d and d ~= "" then - texio.write("processed: " .. name) - for s in gmatch(d,"[^\n\r]+") do - tex.print(s) -- we do a dumb feedback - end - end - f:close() - texio.write(")") - else - tex.error("preprocessor error, invalid file: " .. name) - end - else - tex.error("preprocessor error, unknown file: " .. name) - end -end - -function commands.preprocessfile(oldfile,newfile) -- no checking - if oldfile and oldfile ~= newfile then - local f = io.open(oldfile,'rb') - if f then - local g = io.open(newfile,'wb') - if g then - g:write(lpeg.match(parser,f:read("*a") or "")) - g:close() - end - f:close() - end - end -end - ---~ print(preprocessed([[\def\test#oeps{test:#oeps}]])) ---~ print(preprocessed([[\def\test#oeps{test:#{oeps}}]])) ---~ print(preprocessed([[\def\test#{oeps:1}{test:#{oeps:1}}]])) ---~ print(preprocessed([[\def\test#{oeps}{test:#oeps}]])) ---~ preprocessed([[\def\test#{oeps}{test:#oeps \halign{##\cr #oeps\cr}]]) ---~ print(preprocessed([[\def\test#{oeps}{test:#oeps \halign{##\cr #oeps\cr}}]])) diff --git a/tex/compat/luaotfload/fontloader-preprocessor.tex b/tex/compat/luaotfload/fontloader-preprocessor.tex deleted file mode 100644 index 03b483f41850dd0a68b3f37c6b493dcf0e9dd53f..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/fontloader-preprocessor.tex +++ /dev/null @@ -1,14 +0,0 @@ -%D \module -%D [ file=luatex-preprocessor, -%D version=2010.12.02, -%D title=\LUATEX\ Support Macros, -%D subtitle=Generic Preprocessor, -%D author=Hans Hagen, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] - -\directlua{dofile(kpse.find_file('luatex-preprocessor.lua'))} - -\def\inputpreprocessed#1% - {\directlua{commands.inputpreprocessed("#1")}} - -\endinput diff --git a/tex/compat/luaotfload/fontloader-reference.lua b/tex/compat/luaotfload/fontloader-reference.lua deleted file mode 100644 index 3a4a70c626113b8fb49702a8359500f5c09535ea..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/fontloader-reference.lua +++ /dev/null @@ -1,27259 +0,0 @@ --- merged file : c:/data/develop/context/sources/luatex-fonts-merged.lua --- parent file : c:/data/develop/context/sources/luatex-fonts.lua --- merge date : 01/27/17 14:39:39 - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['l-lua']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -_MAJORVERSION,_MINORVERSION=string.match(_VERSION,"^[^%d]+(%d+)%.(%d+).*$") -_MAJORVERSION=tonumber(_MAJORVERSION) or 5 -_MINORVERSION=tonumber(_MINORVERSION) or 1 -_LUAVERSION=_MAJORVERSION+_MINORVERSION/10 -if _LUAVERSION<5.2 and jit then - _MINORVERSION=2 - _LUAVERSION=5.2 -end -if not lpeg then - lpeg=require("lpeg") -end -if loadstring then - local loadnormal=load - function load(first,...) - if type(first)=="string" then - return loadstring(first,...) - else - return loadnormal(first,...) - end - end -else - loadstring=load -end -if not ipairs then - local function iterate(a,i) - i=i+1 - local v=a[i] - if v~=nil then - return i,v - end - end - function ipairs(a) - return iterate,a,0 - end -end -if not pairs then - function pairs(t) - return next,t - end -end -if not table.unpack then - table.unpack=_G.unpack -elseif not unpack then - _G.unpack=table.unpack -end -if not package.loaders then - package.loaders=package.searchers -end -local print,select,tostring=print,select,tostring -local inspectors={} -function setinspector(kind,inspector) - inspectors[kind]=inspector -end -function inspect(...) - for s=1,select("#",...) do - local value=select(s,...) - if value==nil then - print("nil") - else - local done=false - local kind=type(value) - local inspector=inspectors[kind] - if inspector then - done=inspector(value) - if done then - break - end - end - for kind,inspector in next,inspectors do - done=inspector(value) - if done then - break - end - end - if not done then - print(tostring(value)) - end - end - end -end -local dummy=function() end -function optionalrequire(...) - local ok,result=xpcall(require,dummy,...) - if ok then - return result - end -end -if lua then - lua.mask=load([[τεχ = 1]]) and "utf" or "ascii" -end -local flush=io.flush -if flush then - local execute=os.execute if execute then function os.execute(...) flush() return execute(...) end end - local exec=os.exec if exec then function os.exec (...) flush() return exec (...) end end - local spawn=os.spawn if spawn then function os.spawn (...) flush() return spawn (...) end end - local popen=io.popen if popen then function io.popen (...) flush() return popen (...) end end -end - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['l-lpeg']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -lpeg=require("lpeg") -if not lpeg.print then function lpeg.print(...) print(lpeg.pcode(...)) end end -local type,next,tostring=type,next,tostring -local byte,char,gmatch,format=string.byte,string.char,string.gmatch,string.format -local floor=math.floor -local P,R,S,V,Ct,C,Cs,Cc,Cp,Cmt=lpeg.P,lpeg.R,lpeg.S,lpeg.V,lpeg.Ct,lpeg.C,lpeg.Cs,lpeg.Cc,lpeg.Cp,lpeg.Cmt -local lpegtype,lpegmatch,lpegprint=lpeg.type,lpeg.match,lpeg.print -if setinspector then - setinspector("lpeg",function(v) if lpegtype(v) then lpegprint(v) return true end end) -end -lpeg.patterns=lpeg.patterns or {} -local patterns=lpeg.patterns -local anything=P(1) -local endofstring=P(-1) -local alwaysmatched=P(true) -patterns.anything=anything -patterns.endofstring=endofstring -patterns.beginofstring=alwaysmatched -patterns.alwaysmatched=alwaysmatched -local sign=S('+-') -local zero=P('0') -local digit=R('09') -local octdigit=R("07") -local lowercase=R("az") -local uppercase=R("AZ") -local underscore=P("_") -local hexdigit=digit+lowercase+uppercase -local cr,lf,crlf=P("\r"),P("\n"),P("\r\n") -local newline=P("\r")*(P("\n")+P(true))+P("\n") -local escaped=P("\\")*anything -local squote=P("'") -local dquote=P('"') -local space=P(" ") -local period=P(".") -local comma=P(",") -local utfbom_32_be=P('\000\000\254\255') -local utfbom_32_le=P('\255\254\000\000') -local utfbom_16_be=P('\254\255') -local utfbom_16_le=P('\255\254') -local utfbom_8=P('\239\187\191') -local utfbom=utfbom_32_be+utfbom_32_le+utfbom_16_be+utfbom_16_le+utfbom_8 -local utftype=utfbom_32_be*Cc("utf-32-be")+utfbom_32_le*Cc("utf-32-le")+utfbom_16_be*Cc("utf-16-be")+utfbom_16_le*Cc("utf-16-le")+utfbom_8*Cc("utf-8")+alwaysmatched*Cc("utf-8") -local utfstricttype=utfbom_32_be*Cc("utf-32-be")+utfbom_32_le*Cc("utf-32-le")+utfbom_16_be*Cc("utf-16-be")+utfbom_16_le*Cc("utf-16-le")+utfbom_8*Cc("utf-8") -local utfoffset=utfbom_32_be*Cc(4)+utfbom_32_le*Cc(4)+utfbom_16_be*Cc(2)+utfbom_16_le*Cc(2)+utfbom_8*Cc(3)+Cc(0) -local utf8next=R("\128\191") -patterns.utfbom_32_be=utfbom_32_be -patterns.utfbom_32_le=utfbom_32_le -patterns.utfbom_16_be=utfbom_16_be -patterns.utfbom_16_le=utfbom_16_le -patterns.utfbom_8=utfbom_8 -patterns.utf_16_be_nl=P("\000\r\000\n")+P("\000\r")+P("\000\n") -patterns.utf_16_le_nl=P("\r\000\n\000")+P("\r\000")+P("\n\000") -patterns.utf_32_be_nl=P("\000\000\000\r\000\000\000\n")+P("\000\000\000\r")+P("\000\000\000\n") -patterns.utf_32_le_nl=P("\r\000\000\000\n\000\000\000")+P("\r\000\000\000")+P("\n\000\000\000") -patterns.utf8one=R("\000\127") -patterns.utf8two=R("\194\223")*utf8next -patterns.utf8three=R("\224\239")*utf8next*utf8next -patterns.utf8four=R("\240\244")*utf8next*utf8next*utf8next -patterns.utfbom=utfbom -patterns.utftype=utftype -patterns.utfstricttype=utfstricttype -patterns.utfoffset=utfoffset -local utf8char=patterns.utf8one+patterns.utf8two+patterns.utf8three+patterns.utf8four -local validutf8char=utf8char^0*endofstring*Cc(true)+Cc(false) -local utf8character=P(1)*R("\128\191")^0 -patterns.utf8=utf8char -patterns.utf8char=utf8char -patterns.utf8character=utf8character -patterns.validutf8=validutf8char -patterns.validutf8char=validutf8char -local eol=S("\n\r") -local spacer=S(" \t\f\v") -local whitespace=eol+spacer -local nonspacer=1-spacer -local nonwhitespace=1-whitespace -patterns.eol=eol -patterns.spacer=spacer -patterns.whitespace=whitespace -patterns.nonspacer=nonspacer -patterns.nonwhitespace=nonwhitespace -local stripper=spacer^0*C((spacer^0*nonspacer^1)^0) -local fullstripper=whitespace^0*C((whitespace^0*nonwhitespace^1)^0) -local collapser=Cs(spacer^0/""*nonspacer^0*((spacer^0/" "*nonspacer^1)^0)) -local b_collapser=Cs(whitespace^0/""*(nonwhitespace^1+whitespace^1/" ")^0) -local e_collapser=Cs((whitespace^1*P(-1)/""+nonwhitespace^1+whitespace^1/" ")^0) -local m_collapser=Cs((nonwhitespace^1+whitespace^1/" ")^0) -local b_stripper=Cs(spacer^0/""*(nonspacer^1+spacer^1/" ")^0) -local e_stripper=Cs((spacer^1*P(-1)/""+nonspacer^1+spacer^1/" ")^0) -local m_stripper=Cs((nonspacer^1+spacer^1/" ")^0) -patterns.stripper=stripper -patterns.fullstripper=fullstripper -patterns.collapser=collapser -patterns.b_collapser=b_collapser -patterns.m_collapser=m_collapser -patterns.e_collapser=e_collapser -patterns.b_stripper=b_stripper -patterns.m_stripper=m_stripper -patterns.e_stripper=e_stripper -patterns.lowercase=lowercase -patterns.uppercase=uppercase -patterns.letter=patterns.lowercase+patterns.uppercase -patterns.space=space -patterns.tab=P("\t") -patterns.spaceortab=patterns.space+patterns.tab -patterns.newline=newline -patterns.emptyline=newline^1 -patterns.equal=P("=") -patterns.comma=comma -patterns.commaspacer=comma*spacer^0 -patterns.period=period -patterns.colon=P(":") -patterns.semicolon=P(";") -patterns.underscore=underscore -patterns.escaped=escaped -patterns.squote=squote -patterns.dquote=dquote -patterns.nosquote=(escaped+(1-squote))^0 -patterns.nodquote=(escaped+(1-dquote))^0 -patterns.unsingle=(squote/"")*patterns.nosquote*(squote/"") -patterns.undouble=(dquote/"")*patterns.nodquote*(dquote/"") -patterns.unquoted=patterns.undouble+patterns.unsingle -patterns.unspacer=((patterns.spacer^1)/"")^0 -patterns.singlequoted=squote*patterns.nosquote*squote -patterns.doublequoted=dquote*patterns.nodquote*dquote -patterns.quoted=patterns.doublequoted+patterns.singlequoted -patterns.digit=digit -patterns.octdigit=octdigit -patterns.hexdigit=hexdigit -patterns.sign=sign -patterns.cardinal=digit^1 -patterns.integer=sign^-1*digit^1 -patterns.unsigned=digit^0*period*digit^1 -patterns.float=sign^-1*patterns.unsigned -patterns.cunsigned=digit^0*comma*digit^1 -patterns.cpunsigned=digit^0*(period+comma)*digit^1 -patterns.cfloat=sign^-1*patterns.cunsigned -patterns.cpfloat=sign^-1*patterns.cpunsigned -patterns.number=patterns.float+patterns.integer -patterns.cnumber=patterns.cfloat+patterns.integer -patterns.cpnumber=patterns.cpfloat+patterns.integer -patterns.oct=zero*octdigit^1 -patterns.octal=patterns.oct -patterns.HEX=zero*P("X")*(digit+uppercase)^1 -patterns.hex=zero*P("x")*(digit+lowercase)^1 -patterns.hexadecimal=zero*S("xX")*hexdigit^1 -patterns.hexafloat=sign^-1*zero*S("xX")*(hexdigit^0*period*hexdigit^1+hexdigit^1*period*hexdigit^0+hexdigit^1)*(S("pP")*sign^-1*hexdigit^1)^-1 -patterns.decafloat=sign^-1*(digit^0*period*digit^1+digit^1*period*digit^0+digit^1)*S("eE")*sign^-1*digit^1 -patterns.propername=(uppercase+lowercase+underscore)*(uppercase+lowercase+underscore+digit)^0*endofstring -patterns.somecontent=(anything-newline-space)^1 -patterns.beginline=#(1-newline) -patterns.longtostring=Cs(whitespace^0/""*((patterns.quoted+nonwhitespace^1+whitespace^1/""*(P(-1)+Cc(" ")))^0)) -local function anywhere(pattern) - return P { P(pattern)+1*V(1) } -end -lpeg.anywhere=anywhere -function lpeg.instringchecker(p) - p=anywhere(p) - return function(str) - return lpegmatch(p,str) and true or false - end -end -function lpeg.splitter(pattern,action) - return (((1-P(pattern))^1)/action+1)^0 -end -function lpeg.tsplitter(pattern,action) - return Ct((((1-P(pattern))^1)/action+1)^0) -end -local splitters_s,splitters_m,splitters_t={},{},{} -local function splitat(separator,single) - local splitter=(single and splitters_s[separator]) or splitters_m[separator] - if not splitter then - separator=P(separator) - local other=C((1-separator)^0) - if single then - local any=anything - splitter=other*(separator*C(any^0)+"") - splitters_s[separator]=splitter - else - splitter=other*(separator*other)^0 - splitters_m[separator]=splitter - end - end - return splitter -end -local function tsplitat(separator) - local splitter=splitters_t[separator] - if not splitter then - splitter=Ct(splitat(separator)) - splitters_t[separator]=splitter - end - return splitter -end -lpeg.splitat=splitat -lpeg.tsplitat=tsplitat -function string.splitup(str,separator) - if not separator then - separator="," - end - return lpegmatch(splitters_m[separator] or splitat(separator),str) -end -local cache={} -function lpeg.split(separator,str) - local c=cache[separator] - if not c then - c=tsplitat(separator) - cache[separator]=c - end - return lpegmatch(c,str) -end -function string.split(str,separator) - if separator then - local c=cache[separator] - if not c then - c=tsplitat(separator) - cache[separator]=c - end - return lpegmatch(c,str) - else - return { str } - end -end -local spacing=patterns.spacer^0*newline -local empty=spacing*Cc("") -local nonempty=Cs((1-spacing)^1)*spacing^-1 -local content=(empty+nonempty)^1 -patterns.textline=content -local linesplitter=tsplitat(newline) -patterns.linesplitter=linesplitter -function string.splitlines(str) - return lpegmatch(linesplitter,str) -end -local cache={} -function lpeg.checkedsplit(separator,str) - local c=cache[separator] - if not c then - separator=P(separator) - local other=C((1-separator)^1) - c=Ct(separator^0*other*(separator^1*other)^0) - cache[separator]=c - end - return lpegmatch(c,str) -end -function string.checkedsplit(str,separator) - local c=cache[separator] - if not c then - separator=P(separator) - local other=C((1-separator)^1) - c=Ct(separator^0*other*(separator^1*other)^0) - cache[separator]=c - end - return lpegmatch(c,str) -end -local function f2(s) local c1,c2=byte(s,1,2) return c1*64+c2-12416 end -local function f3(s) local c1,c2,c3=byte(s,1,3) return (c1*64+c2)*64+c3-925824 end -local function f4(s) local c1,c2,c3,c4=byte(s,1,4) return ((c1*64+c2)*64+c3)*64+c4-63447168 end -local utf8byte=patterns.utf8one/byte+patterns.utf8two/f2+patterns.utf8three/f3+patterns.utf8four/f4 -patterns.utf8byte=utf8byte -local cache={} -function lpeg.stripper(str) - if type(str)=="string" then - local s=cache[str] - if not s then - s=Cs(((S(str)^1)/""+1)^0) - cache[str]=s - end - return s - else - return Cs(((str^1)/""+1)^0) - end -end -local cache={} -function lpeg.keeper(str) - if type(str)=="string" then - local s=cache[str] - if not s then - s=Cs((((1-S(str))^1)/""+1)^0) - cache[str]=s - end - return s - else - return Cs((((1-str)^1)/""+1)^0) - end -end -function lpeg.frontstripper(str) - return (P(str)+P(true))*Cs(anything^0) -end -function lpeg.endstripper(str) - return Cs((1-P(str)*endofstring)^0) -end -function lpeg.replacer(one,two,makefunction,isutf) - local pattern - local u=isutf and utf8char or 1 - if type(one)=="table" then - local no=#one - local p=P(false) - if no==0 then - for k,v in next,one do - p=p+P(k)/v - end - pattern=Cs((p+u)^0) - elseif no==1 then - local o=one[1] - one,two=P(o[1]),o[2] - pattern=Cs((one/two+u)^0) - else - for i=1,no do - local o=one[i] - p=p+P(o[1])/o[2] - end - pattern=Cs((p+u)^0) - end - else - pattern=Cs((P(one)/(two or "")+u)^0) - end - if makefunction then - return function(str) - return lpegmatch(pattern,str) - end - else - return pattern - end -end -function lpeg.finder(lst,makefunction,isutf) - local pattern - if type(lst)=="table" then - pattern=P(false) - if #lst==0 then - for k,v in next,lst do - pattern=pattern+P(k) - end - else - for i=1,#lst do - pattern=pattern+P(lst[i]) - end - end - else - pattern=P(lst) - end - if isutf then - pattern=((utf8char or 1)-pattern)^0*pattern - else - pattern=(1-pattern)^0*pattern - end - if makefunction then - return function(str) - return lpegmatch(pattern,str) - end - else - return pattern - end -end -local splitters_f,splitters_s={},{} -function lpeg.firstofsplit(separator) - local splitter=splitters_f[separator] - if not splitter then - local pattern=P(separator) - splitter=C((1-pattern)^0) - splitters_f[separator]=splitter - end - return splitter -end -function lpeg.secondofsplit(separator) - local splitter=splitters_s[separator] - if not splitter then - local pattern=P(separator) - splitter=(1-pattern)^0*pattern*C(anything^0) - splitters_s[separator]=splitter - end - return splitter -end -local splitters_s,splitters_p={},{} -function lpeg.beforesuffix(separator) - local splitter=splitters_s[separator] - if not splitter then - local pattern=P(separator) - splitter=C((1-pattern)^0)*pattern*endofstring - splitters_s[separator]=splitter - end - return splitter -end -function lpeg.afterprefix(separator) - local splitter=splitters_p[separator] - if not splitter then - local pattern=P(separator) - splitter=pattern*C(anything^0) - splitters_p[separator]=splitter - end - return splitter -end -function lpeg.balancer(left,right) - left,right=P(left),P(right) - return P { left*((1-left-right)+V(1))^0*right } -end -local nany=utf8char/"" -function lpeg.counter(pattern) - pattern=Cs((P(pattern)/" "+nany)^0) - return function(str) - return #lpegmatch(pattern,str) - end -end -utf=utf or (unicode and unicode.utf8) or {} -local utfcharacters=utf and utf.characters or string.utfcharacters -local utfgmatch=utf and utf.gmatch -local utfchar=utf and utf.char -lpeg.UP=lpeg.P -if utfcharacters then - function lpeg.US(str) - local p=P(false) - for uc in utfcharacters(str) do - p=p+P(uc) - end - return p - end -elseif utfgmatch then - function lpeg.US(str) - local p=P(false) - for uc in utfgmatch(str,".") do - p=p+P(uc) - end - return p - end -else - function lpeg.US(str) - local p=P(false) - local f=function(uc) - p=p+P(uc) - end - lpegmatch((utf8char/f)^0,str) - return p - end -end -local range=utf8byte*utf8byte+Cc(false) -function lpeg.UR(str,more) - local first,last - if type(str)=="number" then - first=str - last=more or first - else - first,last=lpegmatch(range,str) - if not last then - return P(str) - end - end - if first==last then - return P(str) - elseif utfchar and (last-first<8) then - local p=P(false) - for i=first,last do - p=p+P(utfchar(i)) - end - return p - else - local f=function(b) - return b>=first and b<=last - end - return utf8byte/f - end -end -function lpeg.is_lpeg(p) - return p and lpegtype(p)=="pattern" -end -function lpeg.oneof(list,...) - if type(list)~="table" then - list={ list,... } - end - local p=P(list[1]) - for l=2,#list do - p=p+P(list[l]) - end - return p -end -local sort=table.sort -local function copyindexed(old) - local new={} - for i=1,#old do - new[i]=old - end - return new -end -local function sortedkeys(tab) - local keys,s={},0 - for key,_ in next,tab do - s=s+1 - keys[s]=key - end - sort(keys) - return keys -end -function lpeg.append(list,pp,delayed,checked) - local p=pp - if #list>0 then - local keys=copyindexed(list) - sort(keys) - for i=#keys,1,-1 do - local k=keys[i] - if p then - p=P(k)+p - else - p=P(k) - end - end - elseif delayed then - local keys=sortedkeys(list) - if p then - for i=1,#keys,1 do - local k=keys[i] - local v=list[k] - p=P(k)/list+p - end - else - for i=1,#keys do - local k=keys[i] - local v=list[k] - if p then - p=P(k)+p - else - p=P(k) - end - end - if p then - p=p/list - end - end - elseif checked then - local keys=sortedkeys(list) - for i=1,#keys do - local k=keys[i] - local v=list[k] - if p then - if k==v then - p=P(k)+p - else - p=P(k)/v+p - end - else - if k==v then - p=P(k) - else - p=P(k)/v - end - end - end - else - local keys=sortedkeys(list) - for i=1,#keys do - local k=keys[i] - local v=list[k] - if p then - p=P(k)/v+p - else - p=P(k)/v - end - end - end - return p -end -local p_false=P(false) -local p_true=P(true) -local function make(t) - local function making(t) - local p=p_false - local keys=sortedkeys(t) - for i=1,#keys do - local k=keys[i] - if k~="" then - local v=t[k] - if v==true then - p=p+P(k)*p_true - elseif v==false then - else - p=p+P(k)*making(v) - end - end - end - if t[""] then - p=p+p_true - end - return p - end - local p=p_false - local keys=sortedkeys(t) - for i=1,#keys do - local k=keys[i] - if k~="" then - local v=t[k] - if v==true then - p=p+P(k)*p_true - elseif v==false then - else - p=p+P(k)*making(v) - end - end - end - return p -end -local function collapse(t,x) - if type(t)~="table" then - return t,x - else - local n=next(t) - if n==nil then - return t,x - elseif next(t,n)==nil then - local k=n - local v=t[k] - if type(v)=="table" then - return collapse(v,x..k) - else - return v,x..k - end - else - local tt={} - for k,v in next,t do - local vv,kk=collapse(v,k) - tt[kk]=vv - end - return tt,x - end - end -end -function lpeg.utfchartabletopattern(list) - local tree={} - local n=#list - if n==0 then - for s in next,list do - local t=tree - local p,pk - for c in gmatch(s,".") do - if t==true then - t={ [c]=true,[""]=true } - p[pk]=t - p=t - t=false - elseif t==false then - t={ [c]=false } - p[pk]=t - p=t - t=false - else - local tc=t[c] - if not tc then - tc=false - t[c]=false - end - p=t - t=tc - end - pk=c - end - if t==false then - p[pk]=true - elseif t==true then - else - t[""]=true - end - end - else - for i=1,n do - local s=list[i] - local t=tree - local p,pk - for c in gmatch(s,".") do - if t==true then - t={ [c]=true,[""]=true } - p[pk]=t - p=t - t=false - elseif t==false then - t={ [c]=false } - p[pk]=t - p=t - t=false - else - local tc=t[c] - if not tc then - tc=false - t[c]=false - end - p=t - t=tc - end - pk=c - end - if t==false then - p[pk]=true - elseif t==true then - else - t[""]=true - end - end - end - return make(tree) -end -patterns.containseol=lpeg.finder(eol) -local function nextstep(n,step,result) - local m=n%step - local d=floor(n/step) - if d>0 then - local v=V(tostring(step)) - local s=result.start - for i=1,d do - if s then - s=v*s - else - s=v - end - end - result.start=s - end - if step>1 and result.start then - local v=V(tostring(step/2)) - result[tostring(step)]=v*v - end - if step>0 then - return nextstep(m,step/2,result) - else - return result - end -end -function lpeg.times(pattern,n) - return P(nextstep(n,2^16,{ "start",["1"]=pattern })) -end -local trailingzeros=zero^0*-digit -local case_1=period*trailingzeros/"" -local case_2=period*(digit-trailingzeros)^1*(trailingzeros/"") -local number=digit^1*(case_1+case_2) -local stripper=Cs((number+1)^0) -lpeg.patterns.stripzeros=stripper -local byte_to_HEX={} -local byte_to_hex={} -local byte_to_dec={} -local hex_to_byte={} -for i=0,255 do - local H=format("%02X",i) - local h=format("%02x",i) - local d=format("%03i",i) - local c=char(i) - byte_to_HEX[c]=H - byte_to_hex[c]=h - byte_to_dec[c]=d - hex_to_byte[h]=c - hex_to_byte[H]=c -end -local hextobyte=P(2)/hex_to_byte -local bytetoHEX=P(1)/byte_to_HEX -local bytetohex=P(1)/byte_to_hex -local bytetodec=P(1)/byte_to_dec -local hextobytes=Cs(hextobyte^0) -local bytestoHEX=Cs(bytetoHEX^0) -local bytestohex=Cs(bytetohex^0) -local bytestodec=Cs(bytetodec^0) -patterns.hextobyte=hextobyte -patterns.bytetoHEX=bytetoHEX -patterns.bytetohex=bytetohex -patterns.bytetodec=bytetodec -patterns.hextobytes=hextobytes -patterns.bytestoHEX=bytestoHEX -patterns.bytestohex=bytestohex -patterns.bytestodec=bytestodec -function string.toHEX(s) - if not s or s=="" then - return s - else - return lpegmatch(bytestoHEX,s) - end -end -function string.tohex(s) - if not s or s=="" then - return s - else - return lpegmatch(bytestohex,s) - end -end -function string.todec(s) - if not s or s=="" then - return s - else - return lpegmatch(bytestodec,s) - end -end -function string.tobytes(s) - if not s or s=="" then - return s - else - return lpegmatch(hextobytes,s) - end -end - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['l-functions']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -functions=functions or {} -function functions.dummy() end - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['l-string']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local string=string -local sub,gmatch,format,char,byte,rep,lower=string.sub,string.gmatch,string.format,string.char,string.byte,string.rep,string.lower -local lpegmatch,patterns=lpeg.match,lpeg.patterns -local P,S,C,Ct,Cc,Cs=lpeg.P,lpeg.S,lpeg.C,lpeg.Ct,lpeg.Cc,lpeg.Cs -local unquoted=patterns.squote*C(patterns.nosquote)*patterns.squote+patterns.dquote*C(patterns.nodquote)*patterns.dquote -function string.unquoted(str) - return lpegmatch(unquoted,str) or str -end -function string.quoted(str) - return format("%q",str) -end -function string.count(str,pattern) - local n=0 - for _ in gmatch(str,pattern) do - n=n+1 - end - return n -end -function string.limit(str,n,sentinel) - if #str>n then - sentinel=sentinel or "..." - return sub(str,1,(n-#sentinel))..sentinel - else - return str - end -end -local stripper=patterns.stripper -local fullstripper=patterns.fullstripper -local collapser=patterns.collapser -local longtostring=patterns.longtostring -function string.strip(str) - return str and lpegmatch(stripper,str) or "" -end -function string.fullstrip(str) - return str and lpegmatch(fullstripper,str) or "" -end -function string.collapsespaces(str) - return str and lpegmatch(collapser,str) or "" -end -function string.longtostring(str) - return str and lpegmatch(longtostring,str) or "" -end -local pattern=P(" ")^0*P(-1) -function string.is_empty(str) - if not str or str=="" then - return true - else - return lpegmatch(pattern,str) and true or false - end -end -local anything=patterns.anything -local allescapes=Cc("%")*S(".-+%?()[]*") -local someescapes=Cc("%")*S(".-+%()[]") -local matchescapes=Cc(".")*S("*?") -local pattern_a=Cs ((allescapes+anything )^0 ) -local pattern_b=Cs ((someescapes+matchescapes+anything )^0 ) -local pattern_c=Cs (Cc("^")*(someescapes+matchescapes+anything )^0*Cc("$") ) -function string.escapedpattern(str,simple) - return lpegmatch(simple and pattern_b or pattern_a,str) -end -function string.topattern(str,lowercase,strict) - if str=="" or type(str)~="string" then - return ".*" - elseif strict then - str=lpegmatch(pattern_c,str) - else - str=lpegmatch(pattern_b,str) - end - if lowercase then - return lower(str) - else - return str - end -end -function string.valid(str,default) - return (type(str)=="string" and str~="" and str) or default or nil -end -string.itself=function(s) return s end -local pattern_c=Ct(C(1)^0) -local pattern_b=Ct((C(1)/byte)^0) -function string.totable(str,bytes) - return lpegmatch(bytes and pattern_b or pattern_c,str) -end -local replacer=lpeg.replacer("@","%%") -function string.tformat(fmt,...) - return format(lpegmatch(replacer,fmt),...) -end -string.quote=string.quoted -string.unquote=string.unquoted - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['l-table']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local type,next,tostring,tonumber,ipairs,select=type,next,tostring,tonumber,ipairs,select -local table,string=table,string -local concat,sort,insert,remove=table.concat,table.sort,table.insert,table.remove -local format,lower,dump=string.format,string.lower,string.dump -local getmetatable,setmetatable=getmetatable,setmetatable -local getinfo=debug.getinfo -local lpegmatch,patterns=lpeg.match,lpeg.patterns -local floor=math.floor -local stripper=patterns.stripper -function table.strip(tab) - local lst,l={},0 - for i=1,#tab do - local s=lpegmatch(stripper,tab[i]) or "" - if s=="" then - else - l=l+1 - lst[l]=s - end - end - return lst -end -function table.keys(t) - if t then - local keys,k={},0 - for key in next,t do - k=k+1 - keys[k]=key - end - return keys - else - return {} - end -end -local function compare(a,b) - local ta=type(a) - if ta=="number" then - local tb=type(b) - if ta==tb then - return a<b - elseif tb=="string" then - return tostring(a)<b - end - elseif ta=="string" then - local tb=type(b) - if ta==tb then - return a<b - else - return a<tostring(b) - end - end - return tostring(a)<tostring(b) -end -local function sortedkeys(tab) - if tab then - local srt,category,s={},0,0 - for key in next,tab do - s=s+1 - srt[s]=key - if category==3 then - elseif category==1 then - if type(key)~="string" then - category=3 - end - elseif category==2 then - if type(key)~="number" then - category=3 - end - else - local tkey=type(key) - if tkey=="string" then - category=1 - elseif tkey=="number" then - category=2 - else - category=3 - end - end - end - if s<2 then - elseif category==3 then - sort(srt,compare) - else - sort(srt) - end - return srt - else - return {} - end -end -local function sortedhashonly(tab) - if tab then - local srt,s={},0 - for key in next,tab do - if type(key)=="string" then - s=s+1 - srt[s]=key - end - end - if s>1 then - sort(srt) - end - return srt - else - return {} - end -end -local function sortedindexonly(tab) - if tab then - local srt,s={},0 - for key in next,tab do - if type(key)=="number" then - s=s+1 - srt[s]=key - end - end - if s>1 then - sort(srt) - end - return srt - else - return {} - end -end -local function sortedhashkeys(tab,cmp) - if tab then - local srt,s={},0 - for key in next,tab do - if key then - s=s+1 - srt[s]=key - end - end - if s>1 then - sort(srt,cmp) - end - return srt - else - return {} - end -end -function table.allkeys(t) - local keys={} - for k,v in next,t do - for k in next,v do - keys[k]=true - end - end - return sortedkeys(keys) -end -table.sortedkeys=sortedkeys -table.sortedhashonly=sortedhashonly -table.sortedindexonly=sortedindexonly -table.sortedhashkeys=sortedhashkeys -local function nothing() end -local function sortedhash(t,cmp) - if t then - local s - if cmp then - s=sortedhashkeys(t,function(a,b) return cmp(t,a,b) end) - else - s=sortedkeys(t) - end - local m=#s - if m==1 then - return next,t - elseif m>0 then - local n=0 - return function() - if n<m then - n=n+1 - local k=s[n] - return k,t[k] - end - end - end - end - return nothing -end -table.sortedhash=sortedhash -table.sortedpairs=sortedhash -function table.append(t,list) - local n=#t - for i=1,#list do - n=n+1 - t[n]=list[i] - end - return t -end -function table.prepend(t,list) - local nl=#list - local nt=nl+#t - for i=#t,1,-1 do - t[nt]=t[i] - nt=nt-1 - end - for i=1,#list do - t[i]=list[i] - end - return t -end -function table.merge(t,...) - t=t or {} - for i=1,select("#",...) do - for k,v in next,(select(i,...)) do - t[k]=v - end - end - return t -end -function table.merged(...) - local t={} - for i=1,select("#",...) do - for k,v in next,(select(i,...)) do - t[k]=v - end - end - return t -end -function table.imerge(t,...) - local nt=#t - for i=1,select("#",...) do - local nst=select(i,...) - for j=1,#nst do - nt=nt+1 - t[nt]=nst[j] - end - end - return t -end -function table.imerged(...) - local tmp,ntmp={},0 - for i=1,select("#",...) do - local nst=select(i,...) - for j=1,#nst do - ntmp=ntmp+1 - tmp[ntmp]=nst[j] - end - end - return tmp -end -local function fastcopy(old,metatabletoo) - if old then - local new={} - for k,v in next,old do - if type(v)=="table" then - new[k]=fastcopy(v,metatabletoo) - else - new[k]=v - end - end - if metatabletoo then - local mt=getmetatable(old) - if mt then - setmetatable(new,mt) - end - end - return new - else - return {} - end -end -local function copy(t,tables) - tables=tables or {} - local tcopy={} - if not tables[t] then - tables[t]=tcopy - end - for i,v in next,t do - if type(i)=="table" then - if tables[i] then - i=tables[i] - else - i=copy(i,tables) - end - end - if type(v)~="table" then - tcopy[i]=v - elseif tables[v] then - tcopy[i]=tables[v] - else - tcopy[i]=copy(v,tables) - end - end - local mt=getmetatable(t) - if mt then - setmetatable(tcopy,mt) - end - return tcopy -end -table.fastcopy=fastcopy -table.copy=copy -function table.derive(parent) - local child={} - if parent then - setmetatable(child,{ __index=parent }) - end - return child -end -function table.tohash(t,value) - local h={} - if t then - if value==nil then value=true end - for _,v in next,t do - h[v]=value - end - end - return h -end -function table.fromhash(t) - local hsh,h={},0 - for k,v in next,t do - if v then - h=h+1 - hsh[h]=k - end - end - return hsh -end -local noquotes,hexify,handle,compact,inline,functions,metacheck -local reserved=table.tohash { - 'and','break','do','else','elseif','end','false','for','function','if', - 'in','local','nil','not','or','repeat','return','then','true','until','while', - 'NaN','goto', -} -local function simple_table(t) - local nt=#t - if nt>0 then - local n=0 - for _,v in next,t do - n=n+1 - end - if n==nt then - local tt={} - for i=1,nt do - local v=t[i] - local tv=type(v) - if tv=="number" then - if hexify then - tt[i]=format("0x%X",v) - else - tt[i]=tostring(v) - end - elseif tv=="string" then - tt[i]=format("%q",v) - elseif tv=="boolean" then - tt[i]=v and "true" or "false" - else - return nil - end - end - return tt - end - end - return nil -end -local propername=patterns.propername -local function dummy() end -local function do_serialize(root,name,depth,level,indexed) - if level>0 then - depth=depth.." " - if indexed then - handle(format("%s{",depth)) - else - local tn=type(name) - if tn=="number" then - if hexify then - handle(format("%s[0x%X]={",depth,name)) - else - handle(format("%s[%s]={",depth,name)) - end - elseif tn=="string" then - if noquotes and not reserved[name] and lpegmatch(propername,name) then - handle(format("%s%s={",depth,name)) - else - handle(format("%s[%q]={",depth,name)) - end - elseif tn=="boolean" then - handle(format("%s[%s]={",depth,name and "true" or "false")) - else - handle(format("%s{",depth)) - end - end - end - if root and next(root)~=nil then - local first,last=nil,0 - if compact then - last=#root - for k=1,last do - if rawget(root,k)==nil then - last=k-1 - break - end - end - if last>0 then - first=1 - end - end - local sk=sortedkeys(root) - for i=1,#sk do - local k=sk[i] - local v=root[k] - local tv=type(v) - local tk=type(k) - if compact and first and tk=="number" and k>=first and k<=last then - if tv=="number" then - if hexify then - handle(format("%s 0x%X,",depth,v)) - else - handle(format("%s %s,",depth,v)) - end - elseif tv=="string" then - handle(format("%s %q,",depth,v)) - elseif tv=="table" then - if next(v)==nil then - handle(format("%s {},",depth)) - elseif inline then - local st=simple_table(v) - if st then - handle(format("%s { %s },",depth,concat(st,", "))) - else - do_serialize(v,k,depth,level+1,true) - end - else - do_serialize(v,k,depth,level+1,true) - end - elseif tv=="boolean" then - handle(format("%s %s,",depth,v and "true" or "false")) - elseif tv=="function" then - if functions then - handle(format('%s load(%q),',depth,dump(v))) - else - handle(format('%s "function",',depth)) - end - else - handle(format("%s %q,",depth,tostring(v))) - end - elseif k=="__p__" then - if false then - handle(format("%s __p__=nil,",depth)) - end - elseif tv=="number" then - if tk=="number" then - if hexify then - handle(format("%s [0x%X]=0x%X,",depth,k,v)) - else - handle(format("%s [%s]=%s,",depth,k,v)) - end - elseif tk=="boolean" then - if hexify then - handle(format("%s [%s]=0x%X,",depth,k and "true" or "false",v)) - else - handle(format("%s [%s]=%s,",depth,k and "true" or "false",v)) - end - elseif tk~="string" then - elseif noquotes and not reserved[k] and lpegmatch(propername,k) then - if hexify then - handle(format("%s %s=0x%X,",depth,k,v)) - else - handle(format("%s %s=%s,",depth,k,v)) - end - else - if hexify then - handle(format("%s [%q]=0x%X,",depth,k,v)) - else - handle(format("%s [%q]=%s,",depth,k,v)) - end - end - elseif tv=="string" then - if tk=="number" then - if hexify then - handle(format("%s [0x%X]=%q,",depth,k,v)) - else - handle(format("%s [%s]=%q,",depth,k,v)) - end - elseif tk=="boolean" then - handle(format("%s [%s]=%q,",depth,k and "true" or "false",v)) - elseif tk~="string" then - elseif noquotes and not reserved[k] and lpegmatch(propername,k) then - handle(format("%s %s=%q,",depth,k,v)) - else - handle(format("%s [%q]=%q,",depth,k,v)) - end - elseif tv=="table" then - if next(v)==nil then - if tk=="number" then - if hexify then - handle(format("%s [0x%X]={},",depth,k)) - else - handle(format("%s [%s]={},",depth,k)) - end - elseif tk=="boolean" then - handle(format("%s [%s]={},",depth,k and "true" or "false")) - elseif tk~="string" then - elseif noquotes and not reserved[k] and lpegmatch(propername,k) then - handle(format("%s %s={},",depth,k)) - else - handle(format("%s [%q]={},",depth,k)) - end - elseif inline then - local st=simple_table(v) - if st then - if tk=="number" then - if hexify then - handle(format("%s [0x%X]={ %s },",depth,k,concat(st,", "))) - else - handle(format("%s [%s]={ %s },",depth,k,concat(st,", "))) - end - elseif tk=="boolean" then - handle(format("%s [%s]={ %s },",depth,k and "true" or "false",concat(st,", "))) - elseif tk~="string" then - elseif noquotes and not reserved[k] and lpegmatch(propername,k) then - handle(format("%s %s={ %s },",depth,k,concat(st,", "))) - else - handle(format("%s [%q]={ %s },",depth,k,concat(st,", "))) - end - else - do_serialize(v,k,depth,level+1) - end - else - do_serialize(v,k,depth,level+1) - end - elseif tv=="boolean" then - if tk=="number" then - if hexify then - handle(format("%s [0x%X]=%s,",depth,k,v and "true" or "false")) - else - handle(format("%s [%s]=%s,",depth,k,v and "true" or "false")) - end - elseif tk=="boolean" then - handle(format("%s [%s]=%s,",depth,tostring(k),v and "true" or "false")) - elseif tk~="string" then - elseif noquotes and not reserved[k] and lpegmatch(propername,k) then - handle(format("%s %s=%s,",depth,k,v and "true" or "false")) - else - handle(format("%s [%q]=%s,",depth,k,v and "true" or "false")) - end - elseif tv=="function" then - if functions then - local f=getinfo(v).what=="C" and dump(dummy) or dump(v) - if tk=="number" then - if hexify then - handle(format("%s [0x%X]=load(%q),",depth,k,f)) - else - handle(format("%s [%s]=load(%q),",depth,k,f)) - end - elseif tk=="boolean" then - handle(format("%s [%s]=load(%q),",depth,k and "true" or "false",f)) - elseif tk~="string" then - elseif noquotes and not reserved[k] and lpegmatch(propername,k) then - handle(format("%s %s=load(%q),",depth,k,f)) - else - handle(format("%s [%q]=load(%q),",depth,k,f)) - end - end - else - if tk=="number" then - if hexify then - handle(format("%s [0x%X]=%q,",depth,k,tostring(v))) - else - handle(format("%s [%s]=%q,",depth,k,tostring(v))) - end - elseif tk=="boolean" then - handle(format("%s [%s]=%q,",depth,k and "true" or "false",tostring(v))) - elseif tk~="string" then - elseif noquotes and not reserved[k] and lpegmatch(propername,k) then - handle(format("%s %s=%q,",depth,k,tostring(v))) - else - handle(format("%s [%q]=%q,",depth,k,tostring(v))) - end - end - end - end - if level>0 then - handle(format("%s},",depth)) - end -end -local function serialize(_handle,root,name,specification) - local tname=type(name) - if type(specification)=="table" then - noquotes=specification.noquotes - hexify=specification.hexify - handle=_handle or specification.handle or print - functions=specification.functions - compact=specification.compact - inline=specification.inline and compact - metacheck=specification.metacheck - if functions==nil then - functions=true - end - if compact==nil then - compact=true - end - if inline==nil then - inline=compact - end - if metacheck==nil then - metacheck=true - end - else - noquotes=false - hexify=false - handle=_handle or print - compact=true - inline=true - functions=true - metacheck=true - end - if tname=="string" then - if name=="return" then - handle("return {") - else - handle(name.."={") - end - elseif tname=="number" then - if hexify then - handle(format("[0x%X]={",name)) - else - handle("["..name.."]={") - end - elseif tname=="boolean" then - if name then - handle("return {") - else - handle("{") - end - else - handle("t={") - end - if root then - if metacheck and getmetatable(root) then - local dummy=root._w_h_a_t_e_v_e_r_ - root._w_h_a_t_e_v_e_r_=nil - end - if next(root)~=nil then - do_serialize(root,name,"",0) - end - end - handle("}") -end -function table.serialize(root,name,specification) - local t,n={},0 - local function flush(s) - n=n+1 - t[n]=s - end - serialize(flush,root,name,specification) - return concat(t,"\n") -end -table.tohandle=serialize -local maxtab=2*1024 -function table.tofile(filename,root,name,specification) - local f=io.open(filename,'w') - if f then - if maxtab>1 then - local t,n={},0 - local function flush(s) - n=n+1 - t[n]=s - if n>maxtab then - f:write(concat(t,"\n"),"\n") - t,n={},0 - end - end - serialize(flush,root,name,specification) - f:write(concat(t,"\n"),"\n") - else - local function flush(s) - f:write(s,"\n") - end - serialize(flush,root,name,specification) - end - f:close() - io.flush() - end -end -local function flattened(t,f,depth) - if f==nil then - f={} - depth=0xFFFF - elseif tonumber(f) then - depth=f - f={} - elseif not depth then - depth=0xFFFF - end - for k,v in next,t do - if type(k)~="number" then - if depth>0 and type(v)=="table" then - flattened(v,f,depth-1) - else - f[#f+1]=v - end - end - end - for k=1,#t do - local v=t[k] - if depth>0 and type(v)=="table" then - flattened(v,f,depth-1) - else - f[#f+1]=v - end - end - return f -end -table.flattened=flattened -local function collapsed(t,f,h) - if f==nil then - f={} - h={} - end - for k=1,#t do - local v=t[k] - if type(v)=="table" then - collapsed(v,f,h) - elseif not h[v] then - f[#f+1]=v - h[v]=true - end - end - return f -end -local function collapsedhash(t,h) - if h==nil then - h={} - end - for k=1,#t do - local v=t[k] - if type(v)=="table" then - collapsedhash(v,h) - else - h[v]=true - end - end - return h -end -table.collapsed=collapsed -table.collapsedhash=collapsedhash -local function unnest(t,f) - if not f then - f={} - end - for i=1,#t do - local v=t[i] - if type(v)=="table" then - if type(v[1])=="table" then - unnest(v,f) - else - f[#f+1]=v - end - else - f[#f+1]=v - end - end - return f -end -function table.unnest(t) - return unnest(t) -end -local function are_equal(a,b,n,m) - if a and b and #a==#b then - n=n or 1 - m=m or #a - for i=n,m do - local ai,bi=a[i],b[i] - if ai==bi then - elseif type(ai)=="table" and type(bi)=="table" then - if not are_equal(ai,bi) then - return false - end - else - return false - end - end - return true - else - return false - end -end -local function identical(a,b) - for ka,va in next,a do - local vb=b[ka] - if va==vb then - elseif type(va)=="table" and type(vb)=="table" then - if not identical(va,vb) then - return false - end - else - return false - end - end - return true -end -table.identical=identical -table.are_equal=are_equal -local function sparse(old,nest,keeptables) - local new={} - for k,v in next,old do - if not (v=="" or v==false) then - if nest and type(v)=="table" then - v=sparse(v,nest) - if keeptables or next(v)~=nil then - new[k]=v - end - else - new[k]=v - end - end - end - return new -end -table.sparse=sparse -function table.compact(t) - return sparse(t,true,true) -end -function table.contains(t,v) - if t then - for i=1,#t do - if t[i]==v then - return i - end - end - end - return false -end -function table.count(t) - local n=0 - for k,v in next,t do - n=n+1 - end - return n -end -function table.swapped(t,s) - local n={} - if s then - for k,v in next,s do - n[k]=v - end - end - for k,v in next,t do - n[v]=k - end - return n -end -function table.hashed(t) - for i=1,#t do - t[t[i]]=i - end - return t -end -function table.mirrored(t) - local n={} - for k,v in next,t do - n[v]=k - n[k]=v - end - return n -end -function table.reversed(t) - if t then - local tt,tn={},#t - if tn>0 then - local ttn=0 - for i=tn,1,-1 do - ttn=ttn+1 - tt[ttn]=t[i] - end - end - return tt - end -end -function table.reverse(t) - if t then - local n=#t - for i=1,floor(n/2) do - local j=n-i+1 - t[i],t[j]=t[j],t[i] - end - return t - end -end -function table.sequenced(t,sep,simple) - if not t then - return "" - end - local n=#t - local s={} - if n>0 then - for i=1,n do - s[i]=tostring(t[i]) - end - else - n=0 - for k,v in sortedhash(t) do - if simple then - if v==true then - n=n+1 - s[n]=k - elseif v and v~="" then - n=n+1 - s[n]=k.."="..tostring(v) - end - else - n=n+1 - s[n]=k.."="..tostring(v) - end - end - end - return concat(s,sep or " | ") -end -function table.print(t,...) - if type(t)~="table" then - print(tostring(t)) - else - serialize(print,t,...) - end -end -if setinspector then - setinspector("table",function(v) if type(v)=="table" then serialize(print,v,"table") return true end end) -end -function table.sub(t,i,j) - return { unpack(t,i,j) } -end -function table.is_empty(t) - return not t or next(t)==nil -end -function table.has_one_entry(t) - return t and next(t,next(t))==nil -end -function table.loweredkeys(t) - local l={} - for k,v in next,t do - l[lower(k)]=v - end - return l -end -function table.unique(old) - local hash={} - local new={} - local n=0 - for i=1,#old do - local oi=old[i] - if not hash[oi] then - n=n+1 - new[n]=oi - hash[oi]=true - end - end - return new -end -function table.sorted(t,...) - sort(t,...) - return t -end -function table.values(t,s) - if t then - local values,keys,v={},{},0 - for key,value in next,t do - if not keys[value] then - v=v+1 - values[v]=value - keys[k]=key - end - end - if s then - sort(values) - end - return values - else - return {} - end -end -function table.filtered(t,pattern,sort,cmp) - if t and type(pattern)=="string" then - if sort then - local s - if cmp then - s=sortedhashkeys(t,function(a,b) return cmp(t,a,b) end) - else - s=sortedkeys(t) - end - local n=0 - local m=#s - local function kv(s) - while n<m do - n=n+1 - local k=s[n] - if find(k,pattern) then - return k,t[k] - end - end - end - return kv,s - else - local n=next(t) - local function iterator() - while n~=nil do - local k=n - n=next(t,k) - if find(k,pattern) then - return k,t[k] - end - end - end - return iterator,t - end - else - return nothing - end -end - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['l-io']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local io=io -local open,flush,write,read=io.open,io.flush,io.write,io.read -local byte,find,gsub,format=string.byte,string.find,string.gsub,string.format -local concat=table.concat -local floor=math.floor -local type=type -if string.find(os.getenv("PATH"),";",1,true) then - io.fileseparator,io.pathseparator="\\",";" -else - io.fileseparator,io.pathseparator="/",":" -end -local function readall(f) - return f:read("*all") -end -local function readall(f) - local size=f:seek("end") - if size==0 then - return "" - end - f:seek("set",0) - if size<1024*1024 then - return f:read('*all') - else - local step - if size>16*1024*1024 then - step=16*1024*1024 - else - step=floor(size/(1024*1024))*1024*1024/8 - end - local data={} - while true do - local r=f:read(step) - if not r then - return concat(data) - else - data[#data+1]=r - end - end - end -end -io.readall=readall -function io.loaddata(filename,textmode) - local f=open(filename,(textmode and 'r') or 'rb') - if f then - local data=readall(f) - f:close() - if #data>0 then - return data - end - end -end -function io.copydata(source,target,action) - local f=open(source,"rb") - if f then - local g=open(target,"wb") - if g then - local size=f:seek("end") - if size==0 then - else - f:seek("set",0) - if size<1024*1024 then - local data=f:read('*all') - if action then - data=action(data) - end - if data then - g:write(data) - end - else - local step - if size>16*1024*1024 then - step=16*1024*1024 - else - step=floor(size/(1024*1024))*1024*1024/8 - end - while true do - local data=f:read(step) - if data then - if action then - data=action(data) - end - if data then - g:write(data) - end - else - break - end - end - end - end - g:close() - end - f:close() - flush() - end -end -function io.savedata(filename,data,joiner) - local f=open(filename,"wb") - if f then - if type(data)=="table" then - f:write(concat(data,joiner or "")) - elseif type(data)=="function" then - data(f) - else - f:write(data or "") - end - f:close() - flush() - return true - else - return false - end -end -function io.loadlines(filename,n) - local f=open(filename,'r') - if not f then - elseif n then - local lines={} - for i=1,n do - local line=f:read("*lines") - if line then - lines[#lines+1]=line - else - break - end - end - f:close() - lines=concat(lines,"\n") - if #lines>0 then - return lines - end - else - local line=f:read("*line") or "" - f:close() - if #line>0 then - return line - end - end -end -function io.loadchunk(filename,n) - local f=open(filename,'rb') - if f then - local data=f:read(n or 1024) - f:close() - if #data>0 then - return data - end - end -end -function io.exists(filename) - local f=open(filename) - if f==nil then - return false - else - f:close() - return true - end -end -function io.size(filename) - local f=open(filename) - if f==nil then - return 0 - else - local s=f:seek("end") - f:close() - return s - end -end -local function noflines(f) - if type(f)=="string" then - local f=open(filename) - if f then - local n=f and noflines(f) or 0 - f:close() - return n - else - return 0 - end - else - local n=0 - for _ in f:lines() do - n=n+1 - end - f:seek('set',0) - return n - end -end -io.noflines=noflines -local nextchar={ - [ 4]=function(f) - return f:read(1,1,1,1) - end, - [ 2]=function(f) - return f:read(1,1) - end, - [ 1]=function(f) - return f:read(1) - end, - [-2]=function(f) - local a,b=f:read(1,1) - return b,a - end, - [-4]=function(f) - local a,b,c,d=f:read(1,1,1,1) - return d,c,b,a - end -} -function io.characters(f,n) - if f then - return nextchar[n or 1],f - end -end -local nextbyte={ - [4]=function(f) - local a,b,c,d=f:read(1,1,1,1) - if d then - return byte(a),byte(b),byte(c),byte(d) - end - end, - [3]=function(f) - local a,b,c=f:read(1,1,1) - if b then - return byte(a),byte(b),byte(c) - end - end, - [2]=function(f) - local a,b=f:read(1,1) - if b then - return byte(a),byte(b) - end - end, - [1]=function (f) - local a=f:read(1) - if a then - return byte(a) - end - end, - [-2]=function (f) - local a,b=f:read(1,1) - if b then - return byte(b),byte(a) - end - end, - [-3]=function(f) - local a,b,c=f:read(1,1,1) - if b then - return byte(c),byte(b),byte(a) - end - end, - [-4]=function(f) - local a,b,c,d=f:read(1,1,1,1) - if d then - return byte(d),byte(c),byte(b),byte(a) - end - end -} -function io.bytes(f,n) - if f then - return nextbyte[n or 1],f - else - return nil,nil - end -end -function io.ask(question,default,options) - while true do - write(question) - if options then - write(format(" [%s]",concat(options,"|"))) - end - if default then - write(format(" [%s]",default)) - end - write(format(" ")) - flush() - local answer=read() - answer=gsub(answer,"^%s*(.*)%s*$","%1") - if answer=="" and default then - return default - elseif not options then - return answer - else - for k=1,#options do - if options[k]==answer then - return answer - end - end - local pattern="^"..answer - for k=1,#options do - local v=options[k] - if find(v,pattern) then - return v - end - end - end - end -end -local function readnumber(f,n,m) - if m then - f:seek("set",n) - n=m - end - if n==1 then - return byte(f:read(1)) - elseif n==2 then - local a,b=byte(f:read(2),1,2) - return 256*a+b - elseif n==3 then - local a,b,c=byte(f:read(3),1,3) - return 256*256*a+256*b+c - elseif n==4 then - local a,b,c,d=byte(f:read(4),1,4) - return 256*256*256*a+256*256*b+256*c+d - elseif n==8 then - local a,b=readnumber(f,4),readnumber(f,4) - return 256*a+b - elseif n==12 then - local a,b,c=readnumber(f,4),readnumber(f,4),readnumber(f,4) - return 256*256*a+256*b+c - elseif n==-2 then - local b,a=byte(f:read(2),1,2) - return 256*a+b - elseif n==-3 then - local c,b,a=byte(f:read(3),1,3) - return 256*256*a+256*b+c - elseif n==-4 then - local d,c,b,a=byte(f:read(4),1,4) - return 256*256*256*a+256*256*b+256*c+d - elseif n==-8 then - local h,g,f,e,d,c,b,a=byte(f:read(8),1,8) - return 256*256*256*256*256*256*256*a+256*256*256*256*256*256*b+256*256*256*256*256*c+256*256*256*256*d+256*256*256*e+256*256*f+256*g+h - else - return 0 - end -end -io.readnumber=readnumber -function io.readstring(f,n,m) - if m then - f:seek("set",n) - n=m - end - local str=gsub(f:read(n),"\000","") - return str -end - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['l-file']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -file=file or {} -local file=file -if not lfs then - lfs=optionalrequire("lfs") -end -local insert,concat=table.insert,table.concat -local match,find,gmatch=string.match,string.find,string.gmatch -local lpegmatch=lpeg.match -local getcurrentdir,attributes=lfs.currentdir,lfs.attributes -local checkedsplit=string.checkedsplit -local P,R,S,C,Cs,Cp,Cc,Ct=lpeg.P,lpeg.R,lpeg.S,lpeg.C,lpeg.Cs,lpeg.Cp,lpeg.Cc,lpeg.Ct -local tricky=S("/\\")*P(-1) -local attributes=lfs.attributes -if sandbox then - sandbox.redefine(lfs.isfile,"lfs.isfile") - sandbox.redefine(lfs.isdir,"lfs.isdir") -end -function lfs.isdir(name) - if lpegmatch(tricky,name) then - return attributes(name,"mode")=="directory" - else - return attributes(name.."/.","mode")=="directory" - end -end -function lfs.isfile(name) - return attributes(name,"mode")=="file" -end -local colon=P(":") -local period=P(".") -local periods=P("..") -local fwslash=P("/") -local bwslash=P("\\") -local slashes=S("\\/") -local noperiod=1-period -local noslashes=1-slashes -local name=noperiod^1 -local suffix=period/""*(1-period-slashes)^1*-1 -local pattern=C((1-(slashes^1*noslashes^1*-1))^1)*P(1) -local function pathpart(name,default) - return name and lpegmatch(pattern,name) or default or "" -end -local pattern=(noslashes^0*slashes)^1*C(noslashes^1)*-1 -local function basename(name) - return name and lpegmatch(pattern,name) or name -end -local pattern=(noslashes^0*slashes^1)^0*Cs((1-suffix)^1)*suffix^0 -local function nameonly(name) - return name and lpegmatch(pattern,name) or name -end -local pattern=(noslashes^0*slashes)^0*(noperiod^1*period)^1*C(noperiod^1)*-1 -local function suffixonly(name) - return name and lpegmatch(pattern,name) or "" -end -local pattern=(noslashes^0*slashes)^0*noperiod^1*((period*C(noperiod^1))^1)*-1+Cc("") -local function suffixesonly(name) - if name then - return lpegmatch(pattern,name) - else - return "" - end -end -file.pathpart=pathpart -file.basename=basename -file.nameonly=nameonly -file.suffixonly=suffixonly -file.suffix=suffixonly -file.suffixesonly=suffixesonly -file.suffixes=suffixesonly -file.dirname=pathpart -file.extname=suffixonly -local drive=C(R("az","AZ"))*colon -local path=C((noslashes^0*slashes)^0) -local suffix=period*C(P(1-period)^0*P(-1)) -local base=C((1-suffix)^0) -local rest=C(P(1)^0) -drive=drive+Cc("") -path=path+Cc("") -base=base+Cc("") -suffix=suffix+Cc("") -local pattern_a=drive*path*base*suffix -local pattern_b=path*base*suffix -local pattern_c=C(drive*path)*C(base*suffix) -local pattern_d=path*rest -function file.splitname(str,splitdrive) - if not str then - elseif splitdrive then - return lpegmatch(pattern_a,str) - else - return lpegmatch(pattern_b,str) - end -end -function file.splitbase(str) - if str then - return lpegmatch(pattern_d,str) - else - return "",str - end -end -function file.nametotable(str,splitdrive) - if str then - local path,drive,subpath,name,base,suffix=lpegmatch(pattern_c,str) - if splitdrive then - return { - path=path, - drive=drive, - subpath=subpath, - name=name, - base=base, - suffix=suffix, - } - else - return { - path=path, - name=name, - base=base, - suffix=suffix, - } - end - end -end -local pattern=Cs(((period*(1-period-slashes)^1*-1)/""+1)^1) -function file.removesuffix(name) - return name and lpegmatch(pattern,name) -end -local suffix=period/""*(1-period-slashes)^1*-1 -local pattern=Cs((noslashes^0*slashes^1)^0*((1-suffix)^1))*Cs(suffix) -function file.addsuffix(filename,suffix,criterium) - if not filename or not suffix or suffix=="" then - return filename - elseif criterium==true then - return filename.."."..suffix - elseif not criterium then - local n,s=lpegmatch(pattern,filename) - if not s or s=="" then - return filename.."."..suffix - else - return filename - end - else - local n,s=lpegmatch(pattern,filename) - if s and s~="" then - local t=type(criterium) - if t=="table" then - for i=1,#criterium do - if s==criterium[i] then - return filename - end - end - elseif t=="string" then - if s==criterium then - return filename - end - end - end - return (n or filename).."."..suffix - end -end -local suffix=period*(1-period-slashes)^1*-1 -local pattern=Cs((1-suffix)^0) -function file.replacesuffix(name,suffix) - if name and suffix and suffix~="" then - return lpegmatch(pattern,name).."."..suffix - else - return name - end -end -local reslasher=lpeg.replacer(P("\\"),"/") -function file.reslash(str) - return str and lpegmatch(reslasher,str) -end -function file.is_writable(name) - if not name then - elseif lfs.isdir(name) then - name=name.."/m_t_x_t_e_s_t.tmp" - local f=io.open(name,"wb") - if f then - f:close() - os.remove(name) - return true - end - elseif lfs.isfile(name) then - local f=io.open(name,"ab") - if f then - f:close() - return true - end - else - local f=io.open(name,"ab") - if f then - f:close() - os.remove(name) - return true - end - end - return false -end -local readable=P("r")*Cc(true) -function file.is_readable(name) - if name then - local a=attributes(name) - return a and lpegmatch(readable,a.permissions) or false - else - return false - end -end -file.isreadable=file.is_readable -file.iswritable=file.is_writable -function file.size(name) - if name then - local a=attributes(name) - return a and a.size or 0 - else - return 0 - end -end -function file.splitpath(str,separator) - return str and checkedsplit(lpegmatch(reslasher,str),separator or io.pathseparator) -end -function file.joinpath(tab,separator) - return tab and concat(tab,separator or io.pathseparator) -end -local someslash=S("\\/") -local stripper=Cs(P(fwslash)^0/""*reslasher) -local isnetwork=someslash*someslash*(1-someslash)+(1-fwslash-colon)^1*colon -local isroot=fwslash^1*-1 -local hasroot=fwslash^1 -local reslasher=lpeg.replacer(S("\\/"),"/") -local deslasher=lpeg.replacer(S("\\/")^1,"/") -function file.join(one,two,three,...) - if not two then - return one=="" and one or lpegmatch(reslasher,one) - end - if one=="" then - return lpegmatch(stripper,three and concat({ two,three,... },"/") or two) - end - if lpegmatch(isnetwork,one) then - local one=lpegmatch(reslasher,one) - local two=lpegmatch(deslasher,three and concat({ two,three,... },"/") or two) - if lpegmatch(hasroot,two) then - return one..two - else - return one.."/"..two - end - elseif lpegmatch(isroot,one) then - local two=lpegmatch(deslasher,three and concat({ two,three,... },"/") or two) - if lpegmatch(hasroot,two) then - return two - else - return "/"..two - end - else - return lpegmatch(deslasher,concat({ one,two,three,... },"/")) - end -end -local drivespec=R("az","AZ")^1*colon -local anchors=fwslash+drivespec -local untouched=periods+(1-period)^1*P(-1) -local mswindrive=Cs(drivespec*(bwslash/"/"+fwslash)^0) -local mswinuncpath=(bwslash+fwslash)*(bwslash+fwslash)*Cc("//") -local splitstarter=(mswindrive+mswinuncpath+Cc(false))*Ct(lpeg.splitat(S("/\\")^1)) -local absolute=fwslash -function file.collapsepath(str,anchor) - if not str then - return - end - if anchor==true and not lpegmatch(anchors,str) then - str=getcurrentdir().."/"..str - end - if str=="" or str=="." then - return "." - elseif lpegmatch(untouched,str) then - return lpegmatch(reslasher,str) - end - local starter,oldelements=lpegmatch(splitstarter,str) - local newelements={} - local i=#oldelements - while i>0 do - local element=oldelements[i] - if element=='.' then - elseif element=='..' then - local n=i-1 - while n>0 do - local element=oldelements[n] - if element~='..' and element~='.' then - oldelements[n]='.' - break - else - n=n-1 - end - end - if n<1 then - insert(newelements,1,'..') - end - elseif element~="" then - insert(newelements,1,element) - end - i=i-1 - end - if #newelements==0 then - return starter or "." - elseif starter then - return starter..concat(newelements,'/') - elseif lpegmatch(absolute,str) then - return "/"..concat(newelements,'/') - else - newelements=concat(newelements,'/') - if anchor=="." and find(str,"^%./") then - return "./"..newelements - else - return newelements - end - end -end -local validchars=R("az","09","AZ","--","..") -local pattern_a=lpeg.replacer(1-validchars) -local pattern_a=Cs((validchars+P(1)/"-")^1) -local whatever=P("-")^0/"" -local pattern_b=Cs(whatever*(1-whatever*-1)^1) -function file.robustname(str,strict) - if str then - str=lpegmatch(pattern_a,str) or str - if strict then - return lpegmatch(pattern_b,str) or str - else - return str - end - end -end -local loaddata=io.loaddata -local savedata=io.savedata -file.readdata=loaddata -file.savedata=savedata -function file.copy(oldname,newname) - if oldname and newname then - local data=loaddata(oldname) - if data and data~="" then - savedata(newname,data) - end - end -end -local letter=R("az","AZ")+S("_-+") -local separator=P("://") -local qualified=period^0*fwslash+letter*colon+letter^1*separator+letter^1*fwslash -local rootbased=fwslash+letter*colon -lpeg.patterns.qualified=qualified -lpeg.patterns.rootbased=rootbased -function file.is_qualified_path(filename) - return filename and lpegmatch(qualified,filename)~=nil -end -function file.is_rootbased_path(filename) - return filename and lpegmatch(rootbased,filename)~=nil -end -function file.strip(name,dir) - if name then - local b,a=match(name,"^(.-)"..dir.."(.*)$") - return a~="" and a or name - end -end -function lfs.mkdirs(path) - local full="" - for sub in gmatch(path,"(/*[^\\/]+)") do - full=full..sub - lfs.mkdir(full) - end -end - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['l-boolean']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local type,tonumber=type,tonumber -boolean=boolean or {} -local boolean=boolean -function boolean.tonumber(b) - if b then return 1 else return 0 end -end -function toboolean(str,tolerant) - if str==nil then - return false - elseif str==false then - return false - elseif str==true then - return true - elseif str=="true" then - return true - elseif str=="false" then - return false - elseif not tolerant then - return false - elseif str==0 then - return false - elseif (tonumber(str) or 0)>0 then - return true - else - return str=="yes" or str=="on" or str=="t" - end -end -string.toboolean=toboolean -function string.booleanstring(str) - if str=="0" then - return false - elseif str=="1" then - return true - elseif str=="" then - return false - elseif str=="false" then - return false - elseif str=="true" then - return true - elseif (tonumber(str) or 0)>0 then - return true - else - return str=="yes" or str=="on" or str=="t" - end -end -function string.is_boolean(str,default,strict) - if type(str)=="string" then - if str=="true" or str=="yes" or str=="on" or str=="t" or (not strict and str=="1") then - return true - elseif str=="false" or str=="no" or str=="off" or str=="f" or (not strict and str=="0") then - return false - end - end - return default -end - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['l-math']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local floor,sin,cos,tan=math.floor,math.sin,math.cos,math.tan -if not math.ceiling then - math.ceiling=math.ceil -end -if not math.round then - function math.round(x) return floor(x+0.5) end -end -if not math.div then - function math.div(n,m) return floor(n/m) end -end -if not math.mod then - function math.mod(n,m) return n%m end -end -local pipi=2*math.pi/360 -if not math.sind then - function math.sind(d) return sin(d*pipi) end - function math.cosd(d) return cos(d*pipi) end - function math.tand(d) return tan(d*pipi) end -end -if not math.odd then - function math.odd (n) return n%2~=0 end - function math.even(n) return n%2==0 end -end - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['l-unicode']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -utf=utf or (unicode and unicode.utf8) or {} -utf.characters=utf.characters or string.utfcharacters -utf.values=utf.values or string.utfvalues -local type=type -local char,byte,format,sub,gmatch=string.char,string.byte,string.format,string.sub,string.gmatch -local concat=table.concat -local P,C,R,Cs,Ct,Cmt,Cc,Carg,Cp=lpeg.P,lpeg.C,lpeg.R,lpeg.Cs,lpeg.Ct,lpeg.Cmt,lpeg.Cc,lpeg.Carg,lpeg.Cp -local lpegmatch=lpeg.match -local patterns=lpeg.patterns -local tabletopattern=lpeg.utfchartabletopattern -local bytepairs=string.bytepairs -local finder=lpeg.finder -local replacer=lpeg.replacer -local utfvalues=utf.values -local utfgmatch=utf.gmatch -local p_utftype=patterns.utftype -local p_utfstricttype=patterns.utfstricttype -local p_utfoffset=patterns.utfoffset -local p_utf8char=patterns.utf8character -local p_utf8byte=patterns.utf8byte -local p_utfbom=patterns.utfbom -local p_newline=patterns.newline -local p_whitespace=patterns.whitespace -if not unicode then - unicode={ utf=utf } -end -if not utf.char then - local floor,char=math.floor,string.char - function utf.char(n) - if n<0x80 then - return char(n) - elseif n<0x800 then - return char( - 0xC0+floor(n/0x40), - 0x80+(n%0x40) - ) - elseif n<0x10000 then - return char( - 0xE0+floor(n/0x1000), - 0x80+(floor(n/0x40)%0x40), - 0x80+(n%0x40) - ) - elseif n<0x200000 then - return char( - 0xF0+floor(n/0x40000), - 0x80+(floor(n/0x1000)%0x40), - 0x80+(floor(n/0x40)%0x40), - 0x80+(n%0x40) - ) - else - return "" - end - end -end -if not utf.byte then - local utf8byte=patterns.utf8byte - function utf.byte(c) - return lpegmatch(utf8byte,c) - end -end -local utfchar,utfbyte=utf.char,utf.byte -function utf.filetype(data) - return data and lpegmatch(p_utftype,data) or "unknown" -end -local toentities=Cs ( - ( - patterns.utf8one+( - patterns.utf8two+patterns.utf8three+patterns.utf8four - )/function(s) local b=utfbyte(s) if b<127 then return s else return format("&#%X;",b) end end - )^0 -) -patterns.toentities=toentities -function utf.toentities(str) - return lpegmatch(toentities,str) -end -local one=P(1) -local two=C(1)*C(1) -local four=C(R(utfchar(0xD8),utfchar(0xFF)))*C(1)*C(1)*C(1) -local pattern=P("\254\255")*Cs(( - four/function(a,b,c,d) - local ab=0xFF*byte(a)+byte(b) - local cd=0xFF*byte(c)+byte(d) - return utfchar((ab-0xD800)*0x400+(cd-0xDC00)+0x10000) - end+two/function(a,b) - return utfchar(byte(a)*256+byte(b)) - end+one - )^1 )+P("\255\254")*Cs(( - four/function(b,a,d,c) - local ab=0xFF*byte(a)+byte(b) - local cd=0xFF*byte(c)+byte(d) - return utfchar((ab-0xD800)*0x400+(cd-0xDC00)+0x10000) - end+two/function(b,a) - return utfchar(byte(a)*256+byte(b)) - end+one - )^1 ) -function string.toutf(s) - return lpegmatch(pattern,s) or s -end -local validatedutf=Cs ( - ( - patterns.utf8one+patterns.utf8two+patterns.utf8three+patterns.utf8four+P(1)/"�" - )^0 -) -patterns.validatedutf=validatedutf -function utf.is_valid(str) - return type(str)=="string" and lpegmatch(validatedutf,str) or false -end -if not utf.len then - local n,f=0,1 - local utfcharcounter=patterns.utfbom^-1*Cmt ( - Cc(1)*patterns.utf8one^1+Cc(2)*patterns.utf8two^1+Cc(3)*patterns.utf8three^1+Cc(4)*patterns.utf8four^1, - function(_,t,d) - n=n+(t-f)/d - f=t - return true - end - )^0 - function utf.len(str) - n,f=0,1 - lpegmatch(utfcharcounter,str or "") - return n - end -end -utf.length=utf.len -if not utf.sub then - local utflength=utf.length - local b,e,n,first,last=0,0,0,0,0 - local function slide_zero(s,p) - n=n+1 - if n>=last then - e=p-1 - else - return p - end - end - local function slide_one(s,p) - n=n+1 - if n==first then - b=p - end - if n>=last then - e=p-1 - else - return p - end - end - local function slide_two(s,p) - n=n+1 - if n==first then - b=p - else - return true - end - end - local pattern_zero=Cmt(p_utf8char,slide_zero)^0 - local pattern_one=Cmt(p_utf8char,slide_one )^0 - local pattern_two=Cmt(p_utf8char,slide_two )^0 - local pattern_first=C(patterns.utf8character) - function utf.sub(str,start,stop) - if not start then - return str - end - if start==0 then - start=1 - end - if not stop then - if start<0 then - local l=utflength(str) - start=l+start - else - start=start-1 - end - b,n,first=0,0,start - lpegmatch(pattern_two,str) - if n>=first then - return sub(str,b) - else - return "" - end - end - if start<0 or stop<0 then - local l=utf.length(str) - if start<0 then - start=l+start - if start<=0 then - start=1 - else - start=start+1 - end - end - if stop<0 then - stop=l+stop - if stop==0 then - stop=1 - else - stop=stop+1 - end - end - end - if start==1 and stop==1 then - return lpegmatch(pattern_first,str) or "" - elseif start>stop then - return "" - elseif start>1 then - b,e,n,first,last=0,0,0,start-1,stop - lpegmatch(pattern_one,str) - if n>=first and e==0 then - e=#str - end - return sub(str,b,e) - else - b,e,n,last=1,0,0,stop - lpegmatch(pattern_zero,str) - if e==0 then - e=#str - end - return sub(str,b,e) - end - end -end -function utf.remapper(mapping,option,action) - local variant=type(mapping) - if variant=="table" then - action=action or mapping - if option=="dynamic" then - local pattern=false - table.setmetatablenewindex(mapping,function(t,k,v) rawset(t,k,v) pattern=false end) - return function(str) - if not str or str=="" then - return "" - else - if not pattern then - pattern=Cs((tabletopattern(mapping)/action+p_utf8char)^0) - end - return lpegmatch(pattern,str) - end - end - elseif option=="pattern" then - return Cs((tabletopattern(mapping)/action+p_utf8char)^0) - else - local pattern=Cs((tabletopattern(mapping)/action+p_utf8char)^0) - return function(str) - if not str or str=="" then - return "" - else - return lpegmatch(pattern,str) - end - end,pattern - end - elseif variant=="function" then - if option=="pattern" then - return Cs((p_utf8char/mapping+p_utf8char)^0) - else - local pattern=Cs((p_utf8char/mapping+p_utf8char)^0) - return function(str) - if not str or str=="" then - return "" - else - return lpegmatch(pattern,str) - end - end,pattern - end - else - return function(str) - return str or "" - end - end -end -function utf.replacer(t) - local r=replacer(t,false,false,true) - return function(str) - return lpegmatch(r,str) - end -end -function utf.subtituter(t) - local f=finder (t) - local r=replacer(t,false,false,true) - return function(str) - local i=lpegmatch(f,str) - if not i then - return str - elseif i>#str then - return str - else - return lpegmatch(r,str) - end - end -end -local utflinesplitter=p_utfbom^-1*lpeg.tsplitat(p_newline) -local utfcharsplitter_ows=p_utfbom^-1*Ct(C(p_utf8char)^0) -local utfcharsplitter_iws=p_utfbom^-1*Ct((p_whitespace^1+C(p_utf8char))^0) -local utfcharsplitter_raw=Ct(C(p_utf8char)^0) -patterns.utflinesplitter=utflinesplitter -function utf.splitlines(str) - return lpegmatch(utflinesplitter,str or "") -end -function utf.split(str,ignorewhitespace) - if ignorewhitespace then - return lpegmatch(utfcharsplitter_iws,str or "") - else - return lpegmatch(utfcharsplitter_ows,str or "") - end -end -function utf.totable(str) - return lpegmatch(utfcharsplitter_raw,str) -end -function utf.magic(f) - local str=f:read(4) or "" - local off=lpegmatch(p_utfoffset,str) - if off<4 then - f:seek('set',off) - end - return lpegmatch(p_utftype,str) -end -local utf16_to_utf8_be,utf16_to_utf8_le -local utf32_to_utf8_be,utf32_to_utf8_le -local utf_16_be_getbom=patterns.utfbom_16_be^-1 -local utf_16_le_getbom=patterns.utfbom_16_le^-1 -local utf_32_be_getbom=patterns.utfbom_32_be^-1 -local utf_32_le_getbom=patterns.utfbom_32_le^-1 -local utf_16_be_linesplitter=utf_16_be_getbom*lpeg.tsplitat(patterns.utf_16_be_nl) -local utf_16_le_linesplitter=utf_16_le_getbom*lpeg.tsplitat(patterns.utf_16_le_nl) -local utf_32_be_linesplitter=utf_32_be_getbom*lpeg.tsplitat(patterns.utf_32_be_nl) -local utf_32_le_linesplitter=utf_32_le_getbom*lpeg.tsplitat(patterns.utf_32_le_nl) -local more=0 -local p_utf16_to_utf8_be=C(1)*C(1)/function(left,right) - local now=256*byte(left)+byte(right) - if more>0 then - now=(more-0xD800)*0x400+(now-0xDC00)+0x10000 - more=0 - return utfchar(now) - elseif now>=0xD800 and now<=0xDBFF then - more=now - return "" - else - return utfchar(now) - end -end -local p_utf16_to_utf8_le=C(1)*C(1)/function(right,left) - local now=256*byte(left)+byte(right) - if more>0 then - now=(more-0xD800)*0x400+(now-0xDC00)+0x10000 - more=0 - return utfchar(now) - elseif now>=0xD800 and now<=0xDBFF then - more=now - return "" - else - return utfchar(now) - end -end -local p_utf32_to_utf8_be=C(1)*C(1)*C(1)*C(1)/function(a,b,c,d) - return utfchar(256*256*256*byte(a)+256*256*byte(b)+256*byte(c)+byte(d)) -end -local p_utf32_to_utf8_le=C(1)*C(1)*C(1)*C(1)/function(a,b,c,d) - return utfchar(256*256*256*byte(d)+256*256*byte(c)+256*byte(b)+byte(a)) -end -p_utf16_to_utf8_be=P(true)/function() more=0 end*utf_16_be_getbom*Cs(p_utf16_to_utf8_be^0) -p_utf16_to_utf8_le=P(true)/function() more=0 end*utf_16_le_getbom*Cs(p_utf16_to_utf8_le^0) -p_utf32_to_utf8_be=P(true)/function() more=0 end*utf_32_be_getbom*Cs(p_utf32_to_utf8_be^0) -p_utf32_to_utf8_le=P(true)/function() more=0 end*utf_32_le_getbom*Cs(p_utf32_to_utf8_le^0) -patterns.utf16_to_utf8_be=p_utf16_to_utf8_be -patterns.utf16_to_utf8_le=p_utf16_to_utf8_le -patterns.utf32_to_utf8_be=p_utf32_to_utf8_be -patterns.utf32_to_utf8_le=p_utf32_to_utf8_le -utf16_to_utf8_be=function(s) - if s and s~="" then - return lpegmatch(p_utf16_to_utf8_be,s) - else - return s - end -end -local utf16_to_utf8_be_t=function(t) - if not t then - return nil - elseif type(t)=="string" then - t=lpegmatch(utf_16_be_linesplitter,t) - end - for i=1,#t do - local s=t[i] - if s~="" then - t[i]=lpegmatch(p_utf16_to_utf8_be,s) - end - end - return t -end -utf16_to_utf8_le=function(s) - if s and s~="" then - return lpegmatch(p_utf16_to_utf8_le,s) - else - return s - end -end -local utf16_to_utf8_le_t=function(t) - if not t then - return nil - elseif type(t)=="string" then - t=lpegmatch(utf_16_le_linesplitter,t) - end - for i=1,#t do - local s=t[i] - if s~="" then - t[i]=lpegmatch(p_utf16_to_utf8_le,s) - end - end - return t -end -utf32_to_utf8_be=function(s) - if s and s~="" then - return lpegmatch(p_utf32_to_utf8_be,s) - else - return s - end -end -local utf32_to_utf8_be_t=function(t) - if not t then - return nil - elseif type(t)=="string" then - t=lpegmatch(utf_32_be_linesplitter,t) - end - for i=1,#t do - local s=t[i] - if s~="" then - t[i]=lpegmatch(p_utf32_to_utf8_be,s) - end - end - return t -end -utf32_to_utf8_le=function(s) - if s and s~="" then - return lpegmatch(p_utf32_to_utf8_le,s) - else - return s - end -end -local utf32_to_utf8_le_t=function(t) - if not t then - return nil - elseif type(t)=="string" then - t=lpegmatch(utf_32_le_linesplitter,t) - end - for i=1,#t do - local s=t[i] - if s~="" then - t[i]=lpegmatch(p_utf32_to_utf8_le,s) - end - end - return t -end -utf.utf16_to_utf8_le_t=utf16_to_utf8_le_t -utf.utf16_to_utf8_be_t=utf16_to_utf8_be_t -utf.utf32_to_utf8_le_t=utf32_to_utf8_le_t -utf.utf32_to_utf8_be_t=utf32_to_utf8_be_t -utf.utf16_to_utf8_le=utf16_to_utf8_le -utf.utf16_to_utf8_be=utf16_to_utf8_be -utf.utf32_to_utf8_le=utf32_to_utf8_le -utf.utf32_to_utf8_be=utf32_to_utf8_be -function utf.utf8_to_utf8_t(t) - return type(t)=="string" and lpegmatch(utflinesplitter,t) or t -end -function utf.utf16_to_utf8_t(t,endian) - return endian and utf16_to_utf8_be_t(t) or utf16_to_utf8_le_t(t) or t -end -function utf.utf32_to_utf8_t(t,endian) - return endian and utf32_to_utf8_be_t(t) or utf32_to_utf8_le_t(t) or t -end -local function little(b) - if b<0x10000 then - return char(b%256,b/256) - else - b=b-0x10000 - local b1,b2=b/1024+0xD800,b%1024+0xDC00 - return char(b1%256,b1/256,b2%256,b2/256) - end -end -local function big(b) - if b<0x10000 then - return char(b/256,b%256) - else - b=b-0x10000 - local b1,b2=b/1024+0xD800,b%1024+0xDC00 - return char(b1/256,b1%256,b2/256,b2%256) - end -end -local l_remap=Cs((p_utf8byte/little+P(1)/"")^0) -local b_remap=Cs((p_utf8byte/big+P(1)/"")^0) -local function utf8_to_utf16_be(str,nobom) - if nobom then - return lpegmatch(b_remap,str) - else - return char(254,255)..lpegmatch(b_remap,str) - end -end -local function utf8_to_utf16_le(str,nobom) - if nobom then - return lpegmatch(l_remap,str) - else - return char(255,254)..lpegmatch(l_remap,str) - end -end -utf.utf8_to_utf16_be=utf8_to_utf16_be -utf.utf8_to_utf16_le=utf8_to_utf16_le -function utf.utf8_to_utf16(str,littleendian,nobom) - if littleendian then - return utf8_to_utf16_le(str,nobom) - else - return utf8_to_utf16_be(str,nobom) - end -end -local pattern=Cs ( - (p_utf8byte/function(unicode ) return format("0x%04X",unicode) end)*(p_utf8byte*Carg(1)/function(unicode,separator) return format("%s0x%04X",separator,unicode) end)^0 -) -function utf.tocodes(str,separator) - return lpegmatch(pattern,str,1,separator or " ") -end -function utf.ustring(s) - return format("U+%05X",type(s)=="number" and s or utfbyte(s)) -end -function utf.xstring(s) - return format("0x%05X",type(s)=="number" and s or utfbyte(s)) -end -function utf.toeight(str) - if not str or str=="" then - return nil - end - local utftype=lpegmatch(p_utfstricttype,str) - if utftype=="utf-8" then - return sub(str,4) - elseif utftype=="utf-16-be" then - return utf16_to_utf8_be(str) - elseif utftype=="utf-16-le" then - return utf16_to_utf8_le(str) - else - return str - end -end -local p_nany=p_utf8char/"" -if utfgmatch then - function utf.count(str,what) - if type(what)=="string" then - local n=0 - for _ in utfgmatch(str,what) do - n=n+1 - end - return n - else - return #lpegmatch(Cs((P(what)/" "+p_nany)^0),str) - end - end -else - local cache={} - function utf.count(str,what) - if type(what)=="string" then - local p=cache[what] - if not p then - p=Cs((P(what)/" "+p_nany)^0) - cache[p]=p - end - return #lpegmatch(p,str) - else - return #lpegmatch(Cs((P(what)/" "+p_nany)^0),str) - end - end -end -if not utf.characters then - function utf.characters(str) - return gmatch(str,".[\128-\191]*") - end - string.utfcharacters=utf.characters -end -if not utf.values then - local find=string.find - local dummy=function() - end - function utf.values(str) - local n=#str - if n==0 then - return dummy - elseif n==1 then - return function() return utfbyte(str) end - else - local p=1 - return function() - local b,e=find(str,".[\128-\191]*",p) - if b then - p=e+1 - return utfbyte(sub(str,b,e)) - end - end - end - end - string.utfvalues=utf.values -end -function utf.chrlen(u) - return - (u<0x80 and 1) or - (u<0xE0 and 2) or - (u<0xF0 and 3) or - (u<0xF8 and 4) or - (u<0xFC and 5) or - (u<0xFE and 6) or 0 -end - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['util-str']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -utilities=utilities or {} -utilities.strings=utilities.strings or {} -local strings=utilities.strings -local format,gsub,rep,sub,find=string.format,string.gsub,string.rep,string.sub,string.find -local load,dump=load,string.dump -local tonumber,type,tostring=tonumber,type,tostring -local unpack,concat=table.unpack,table.concat -local P,V,C,S,R,Ct,Cs,Cp,Carg,Cc=lpeg.P,lpeg.V,lpeg.C,lpeg.S,lpeg.R,lpeg.Ct,lpeg.Cs,lpeg.Cp,lpeg.Carg,lpeg.Cc -local patterns,lpegmatch=lpeg.patterns,lpeg.match -local utfchar,utfbyte=utf.char,utf.byte -local loadstripped=nil -if _LUAVERSION<5.2 then - loadstripped=function(str,shortcuts) - return load(str) - end -else - loadstripped=function(str,shortcuts) - if shortcuts then - return load(dump(load(str),true),nil,nil,shortcuts) - else - return load(dump(load(str),true)) - end - end -end -if not number then number={} end -local stripper=patterns.stripzeros -local newline=patterns.newline -local endofstring=patterns.endofstring -local whitespace=patterns.whitespace -local spacer=patterns.spacer -local spaceortab=patterns.spaceortab -local function points(n) - n=tonumber(n) - return (not n or n==0) and "0pt" or lpegmatch(stripper,format("%.5fpt",n/65536)) -end -local function basepoints(n) - n=tonumber(n) - return (not n or n==0) and "0bp" or lpegmatch(stripper,format("%.5fbp",n*(7200/7227)/65536)) -end -number.points=points -number.basepoints=basepoints -local rubish=spaceortab^0*newline -local anyrubish=spaceortab+newline -local anything=patterns.anything -local stripped=(spaceortab^1/"")*newline -local leading=rubish^0/"" -local trailing=(anyrubish^1*endofstring)/"" -local redundant=rubish^3/"\n" -local pattern=Cs(leading*(trailing+redundant+stripped+anything)^0) -function strings.collapsecrlf(str) - return lpegmatch(pattern,str) -end -local repeaters={} -function strings.newrepeater(str,offset) - offset=offset or 0 - local s=repeaters[str] - if not s then - s={} - repeaters[str]=s - end - local t=s[offset] - if t then - return t - end - t={} - setmetatable(t,{ __index=function(t,k) - if not k then - return "" - end - local n=k+offset - local s=n>0 and rep(str,n) or "" - t[k]=s - return s - end }) - s[offset]=t - return t -end -local extra,tab,start=0,0,4,0 -local nspaces=strings.newrepeater(" ") -string.nspaces=nspaces -local pattern=Carg(1)/function(t) - extra,tab,start=0,t or 7,1 - end*Cs(( - Cp()*patterns.tab/function(position) - local current=(position-start+1)+extra - local spaces=tab-(current-1)%tab - if spaces>0 then - extra=extra+spaces-1 - return nspaces[spaces] - else - return "" - end - end+newline*Cp()/function(position) - extra,start=0,position - end+patterns.anything - )^1) -function strings.tabtospace(str,tab) - return lpegmatch(pattern,str,1,tab or 7) -end -local space=spacer^0 -local nospace=space/"" -local endofline=nospace*newline -local stripend=(whitespace^1*endofstring)/"" -local normalline=(nospace*((1-space*(newline+endofstring))^1)*nospace) -local stripempty=endofline^1/"" -local normalempty=endofline^1 -local singleempty=endofline*(endofline^0/"") -local doubleempty=endofline*endofline^-1*(endofline^0/"") -local stripstart=stripempty^0 -local p_prune_normal=Cs (stripstart*(stripend+normalline+normalempty )^0 ) -local p_prune_collapse=Cs (stripstart*(stripend+normalline+doubleempty )^0 ) -local p_prune_noempty=Cs (stripstart*(stripend+normalline+singleempty )^0 ) -local p_retain_normal=Cs ((normalline+normalempty )^0 ) -local p_retain_collapse=Cs ((normalline+doubleempty )^0 ) -local p_retain_noempty=Cs ((normalline+singleempty )^0 ) -local striplinepatterns={ - ["prune"]=p_prune_normal, - ["prune and collapse"]=p_prune_collapse, - ["prune and no empty"]=p_prune_noempty, - ["retain"]=p_retain_normal, - ["retain and collapse"]=p_retain_collapse, - ["retain and no empty"]=p_retain_noempty, - ["collapse"]=patterns.collapser, -} -setmetatable(striplinepatterns,{ __index=function(t,k) return p_prune_collapse end }) -strings.striplinepatterns=striplinepatterns -function strings.striplines(str,how) - return str and lpegmatch(striplinepatterns[how],str) or str -end -strings.striplong=strings.striplines -function strings.nice(str) - str=gsub(str,"[:%-+_]+"," ") - return str -end -local n=0 -local sequenced=table.sequenced -function string.autodouble(s,sep) - if s==nil then - return '""' - end - local t=type(s) - if t=="number" then - return tostring(s) - end - if t=="table" then - return ('"'..sequenced(s,sep or ",")..'"') - end - return ('"'..tostring(s)..'"') -end -function string.autosingle(s,sep) - if s==nil then - return "''" - end - local t=type(s) - if t=="number" then - return tostring(s) - end - if t=="table" then - return ("'"..sequenced(s,sep or ",").."'") - end - return ("'"..tostring(s).."'") -end -local tracedchars={ [0]= - "[null]","[soh]","[stx]","[etx]","[eot]","[enq]","[ack]","[bel]", - "[bs]","[ht]","[lf]","[vt]","[ff]","[cr]","[so]","[si]", - "[dle]","[dc1]","[dc2]","[dc3]","[dc4]","[nak]","[syn]","[etb]", - "[can]","[em]","[sub]","[esc]","[fs]","[gs]","[rs]","[us]", - "[space]", -} -string.tracedchars=tracedchars -strings.tracers=tracedchars -function string.tracedchar(b) - if type(b)=="number" then - return tracedchars[b] or (utfchar(b).." (U+"..format("%05X",b)..")") - else - local c=utfbyte(b) - return tracedchars[c] or (b.." (U+"..(c and format("%05X",c) or "?????")..")") - end -end -function number.signed(i) - if i>0 then - return "+",i - else - return "-",-i - end -end -local digit=patterns.digit -local period=patterns.period -local three=digit*digit*digit -local splitter=Cs ( - (((1-(three^1*period))^1+C(three))*(Carg(1)*three)^1+C((1-period)^1))*(P(1)/""*Carg(2))*C(2) -) -patterns.formattednumber=splitter -function number.formatted(n,sep1,sep2) - local s=type(s)=="string" and n or format("%0.2f",n) - if sep1==true then - return lpegmatch(splitter,s,1,".",",") - elseif sep1=="." then - return lpegmatch(splitter,s,1,sep1,sep2 or ",") - elseif sep1=="," then - return lpegmatch(splitter,s,1,sep1,sep2 or ".") - else - return lpegmatch(splitter,s,1,sep1 or ",",sep2 or ".") - end -end -local zero=P("0")^1/"" -local plus=P("+")/"" -local minus=P("-") -local separator=S(".") -local digit=R("09") -local trailing=zero^1*#S("eE") -local exponent=(S("eE")*(plus+Cs((minus*zero^0*P(-1))/"")+minus)*zero^0*(P(-1)*Cc("0")+P(1)^1)) -local pattern_a=Cs(minus^0*digit^1*(separator/""*trailing+separator*(trailing+digit)^0)*exponent) -local pattern_b=Cs((exponent+P(1))^0) -function number.sparseexponent(f,n) - if not n then - n=f - f="%e" - end - local tn=type(n) - if tn=="string" then - local m=tonumber(n) - if m then - return lpegmatch((f=="%e" or f=="%E") and pattern_a or pattern_b,format(f,m)) - end - elseif tn=="number" then - return lpegmatch((f=="%e" or f=="%E") and pattern_a or pattern_b,format(f,n)) - end - return tostring(n) -end -local template=[[ -%s -%s -return function(%s) return %s end -]] -local preamble,environment="",{} -if _LUAVERSION<5.2 then - preamble=[[ -local lpeg=lpeg -local type=type -local tostring=tostring -local tonumber=tonumber -local format=string.format -local concat=table.concat -local signed=number.signed -local points=number.points -local basepoints= number.basepoints -local utfchar=utf.char -local utfbyte=utf.byte -local lpegmatch=lpeg.match -local nspaces=string.nspaces -local tracedchar=string.tracedchar -local autosingle=string.autosingle -local autodouble=string.autodouble -local sequenced=table.sequenced -local formattednumber=number.formatted -local sparseexponent=number.sparseexponent - ]] -else - environment={ - global=global or _G, - lpeg=lpeg, - type=type, - tostring=tostring, - tonumber=tonumber, - format=string.format, - concat=table.concat, - signed=number.signed, - points=number.points, - basepoints=number.basepoints, - utfchar=utf.char, - utfbyte=utf.byte, - lpegmatch=lpeg.match, - nspaces=string.nspaces, - tracedchar=string.tracedchar, - autosingle=string.autosingle, - autodouble=string.autodouble, - sequenced=table.sequenced, - formattednumber=number.formatted, - sparseexponent=number.sparseexponent, - } -end -local arguments={ "a1" } -setmetatable(arguments,{ __index=function(t,k) - local v=t[k-1]..",a"..k - t[k]=v - return v - end -}) -local prefix_any=C((S("+- .")+R("09"))^0) -local prefix_tab=P("{")*C((1-P("}"))^0)*P("}")+C((1-R("az","AZ","09","%%"))^0) -local format_s=function(f) - n=n+1 - if f and f~="" then - return format("format('%%%ss',a%s)",f,n) - else - return format("(a%s or '')",n) - end -end -local format_S=function(f) - n=n+1 - if f and f~="" then - return format("format('%%%ss',tostring(a%s))",f,n) - else - return format("tostring(a%s)",n) - end -end -local format_q=function() - n=n+1 - return format("(a%s and format('%%q',a%s) or '')",n,n) -end -local format_Q=function() - n=n+1 - return format("format('%%q',tostring(a%s))",n) -end -local format_i=function(f) - n=n+1 - if f and f~="" then - return format("format('%%%si',a%s)",f,n) - else - return format("format('%%i',a%s)",n) - end -end -local format_d=format_i -local format_I=function(f) - n=n+1 - return format("format('%%s%%%si',signed(a%s))",f,n) -end -local format_f=function(f) - n=n+1 - return format("format('%%%sf',a%s)",f,n) -end -local format_F=function(f) - n=n+1 - if not f or f=="" then - return format("(((a%s > -0.0000000005 and a%s < 0.0000000005) and '0') or format((a%s %% 1 == 0) and '%%i' or '%%.9f',a%s))",n,n,n,n) - else - return format("format((a%s %% 1 == 0) and '%%i' or '%%%sf',a%s)",n,f,n) - end -end -local format_g=function(f) - n=n+1 - return format("format('%%%sg',a%s)",f,n) -end -local format_G=function(f) - n=n+1 - return format("format('%%%sG',a%s)",f,n) -end -local format_e=function(f) - n=n+1 - return format("format('%%%se',a%s)",f,n) -end -local format_E=function(f) - n=n+1 - return format("format('%%%sE',a%s)",f,n) -end -local format_j=function(f) - n=n+1 - return format("sparseexponent('%%%se',a%s)",f,n) -end -local format_J=function(f) - n=n+1 - return format("sparseexponent('%%%sE',a%s)",f,n) -end -local format_x=function(f) - n=n+1 - return format("format('%%%sx',a%s)",f,n) -end -local format_X=function(f) - n=n+1 - return format("format('%%%sX',a%s)",f,n) -end -local format_o=function(f) - n=n+1 - return format("format('%%%so',a%s)",f,n) -end -local format_c=function() - n=n+1 - return format("utfchar(a%s)",n) -end -local format_C=function() - n=n+1 - return format("tracedchar(a%s)",n) -end -local format_r=function(f) - n=n+1 - return format("format('%%%s.0f',a%s)",f,n) -end -local format_h=function(f) - n=n+1 - if f=="-" then - f=sub(f,2) - return format("format('%%%sx',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n) - else - return format("format('0x%%%sx',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n) - end -end -local format_H=function(f) - n=n+1 - if f=="-" then - f=sub(f,2) - return format("format('%%%sX',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n) - else - return format("format('0x%%%sX',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n) - end -end -local format_u=function(f) - n=n+1 - if f=="-" then - f=sub(f,2) - return format("format('%%%sx',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n) - else - return format("format('u+%%%sx',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n) - end -end -local format_U=function(f) - n=n+1 - if f=="-" then - f=sub(f,2) - return format("format('%%%sX',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n) - else - return format("format('U+%%%sX',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n) - end -end -local format_p=function() - n=n+1 - return format("points(a%s)",n) -end -local format_b=function() - n=n+1 - return format("basepoints(a%s)",n) -end -local format_t=function(f) - n=n+1 - if f and f~="" then - return format("concat(a%s,%q)",n,f) - else - return format("concat(a%s)",n) - end -end -local format_T=function(f) - n=n+1 - if f and f~="" then - return format("sequenced(a%s,%q)",n,f) - else - return format("sequenced(a%s)",n) - end -end -local format_l=function() - n=n+1 - return format("(a%s and 'true' or 'false')",n) -end -local format_L=function() - n=n+1 - return format("(a%s and 'TRUE' or 'FALSE')",n) -end -local format_N=function() - n=n+1 - return format("tostring(tonumber(a%s) or a%s)",n,n) -end -local format_a=function(f) - n=n+1 - if f and f~="" then - return format("autosingle(a%s,%q)",n,f) - else - return format("autosingle(a%s)",n) - end -end -local format_A=function(f) - n=n+1 - if f and f~="" then - return format("autodouble(a%s,%q)",n,f) - else - return format("autodouble(a%s)",n) - end -end -local format_w=function(f) - n=n+1 - f=tonumber(f) - if f then - return format("nspaces[%s+a%s]",f,n) - else - return format("nspaces[a%s]",n) - end -end -local format_W=function(f) - return format("nspaces[%s]",tonumber(f) or 0) -end -local format_m=function(f) - n=n+1 - if not f or f=="" then - f="," - end - return format([[formattednumber(a%s,%q,".")]],n,f) -end -local format_M=function(f) - n=n+1 - if not f or f=="" then - f="." - end - return format([[formattednumber(a%s,%q,",")]],n,f) -end -local format_z=function(f) - n=n+(tonumber(f) or 1) - return "''" -end -local format_rest=function(s) - return format("%q",s) -end -local format_extension=function(extensions,f,name) - local extension=extensions[name] or "tostring(%s)" - local f=tonumber(f) or 1 - local w=find(extension,"%.%.%.") - if f==0 then - if w then - extension=gsub(extension,"%.%.%.","") - end - return extension - elseif f==1 then - if w then - extension=gsub(extension,"%.%.%.","%%s") - end - n=n+1 - local a="a"..n - return format(extension,a,a) - elseif f<0 then - local a="a"..(n+f+1) - return format(extension,a,a) - else - if w then - extension=gsub(extension,"%.%.%.",rep("%%s,",f-1).."%%s") - end - local t={} - for i=1,f do - n=n+1 - t[i]="a"..n - end - return format(extension,unpack(t)) - end -end -local builder=Cs { "start", - start=( - ( - P("%")/""*( - V("!") -+V("s")+V("q")+V("i")+V("d")+V("f")+V("F")+V("g")+V("G")+V("e")+V("E")+V("x")+V("X")+V("o") -+V("c")+V("C")+V("S") -+V("Q") -+V("N") -+V("r")+V("h")+V("H")+V("u")+V("U")+V("p")+V("b")+V("t")+V("T")+V("l")+V("L")+V("I")+V("w") -+V("W") -+V("a") -+V("A") -+V("j")+V("J") -+V("m")+V("M") -+V("z") - )+V("*") - )*(P(-1)+Carg(1)) - )^0, - ["s"]=(prefix_any*P("s"))/format_s, - ["q"]=(prefix_any*P("q"))/format_q, - ["i"]=(prefix_any*P("i"))/format_i, - ["d"]=(prefix_any*P("d"))/format_d, - ["f"]=(prefix_any*P("f"))/format_f, - ["F"]=(prefix_any*P("F"))/format_F, - ["g"]=(prefix_any*P("g"))/format_g, - ["G"]=(prefix_any*P("G"))/format_G, - ["e"]=(prefix_any*P("e"))/format_e, - ["E"]=(prefix_any*P("E"))/format_E, - ["x"]=(prefix_any*P("x"))/format_x, - ["X"]=(prefix_any*P("X"))/format_X, - ["o"]=(prefix_any*P("o"))/format_o, - ["S"]=(prefix_any*P("S"))/format_S, - ["Q"]=(prefix_any*P("Q"))/format_S, - ["N"]=(prefix_any*P("N"))/format_N, - ["c"]=(prefix_any*P("c"))/format_c, - ["C"]=(prefix_any*P("C"))/format_C, - ["r"]=(prefix_any*P("r"))/format_r, - ["h"]=(prefix_any*P("h"))/format_h, - ["H"]=(prefix_any*P("H"))/format_H, - ["u"]=(prefix_any*P("u"))/format_u, - ["U"]=(prefix_any*P("U"))/format_U, - ["p"]=(prefix_any*P("p"))/format_p, - ["b"]=(prefix_any*P("b"))/format_b, - ["t"]=(prefix_tab*P("t"))/format_t, - ["T"]=(prefix_tab*P("T"))/format_T, - ["l"]=(prefix_any*P("l"))/format_l, - ["L"]=(prefix_any*P("L"))/format_L, - ["I"]=(prefix_any*P("I"))/format_I, - ["w"]=(prefix_any*P("w"))/format_w, - ["W"]=(prefix_any*P("W"))/format_W, - ["j"]=(prefix_any*P("j"))/format_j, - ["J"]=(prefix_any*P("J"))/format_J, - ["m"]=(prefix_tab*P("m"))/format_m, - ["M"]=(prefix_tab*P("M"))/format_M, - ["z"]=(prefix_any*P("z"))/format_z, - ["a"]=(prefix_any*P("a"))/format_a, - ["A"]=(prefix_any*P("A"))/format_A, - ["*"]=Cs(((1-P("%"))^1+P("%%")/"%%")^1)/format_rest, - ["?"]=Cs(((1-P("%"))^1 )^1)/format_rest, - ["!"]=Carg(2)*prefix_any*P("!")*C((1-P("!"))^1)*P("!")/format_extension, -} -local direct=Cs ( - P("%")*(S("+- .")+R("09"))^0*S("sqidfgGeExXo")*P(-1)/[[local format = string.format return function(str) return format("%0",str) end]] -) -local function make(t,str) - local f - local p - local p=lpegmatch(direct,str) - if p then - f=loadstripped(p)() - else - n=0 - p=lpegmatch(builder,str,1,t._connector_,t._extensions_) - if n>0 then - p=format(template,preamble,t._preamble_,arguments[n],p) - f=loadstripped(p,t._environment_)() - else - f=function() return str end - end - end - t[str]=f - return f -end -local function use(t,fmt,...) - return t[fmt](...) -end -strings.formatters={} -if _LUAVERSION<5.2 then - function strings.formatters.new(noconcat) - local t={ _type_="formatter",_connector_=noconcat and "," or "..",_extensions_={},_preamble_=preamble,_environment_={} } - setmetatable(t,{ __index=make,__call=use }) - return t - end -else - function strings.formatters.new(noconcat) - local e={} - for k,v in next,environment do - e[k]=v - end - local t={ _type_="formatter",_connector_=noconcat and "," or "..",_extensions_={},_preamble_="",_environment_=e } - setmetatable(t,{ __index=make,__call=use }) - return t - end -end -local formatters=strings.formatters.new() -string.formatters=formatters -string.formatter=function(str,...) return formatters[str](...) end -local function add(t,name,template,preamble) - if type(t)=="table" and t._type_=="formatter" then - t._extensions_[name]=template or "%s" - if type(preamble)=="string" then - t._preamble_=preamble.."\n"..t._preamble_ - elseif type(preamble)=="table" then - for k,v in next,preamble do - t._environment_[k]=v - end - end - end -end -strings.formatters.add=add -patterns.xmlescape=Cs((P("<")/"<"+P(">")/">"+P("&")/"&"+P('"')/"""+P(1))^0) -patterns.texescape=Cs((C(S("#$%\\{}"))/"\\%1"+P(1))^0) -patterns.luaescape=Cs(((1-S('"\n'))^1+P('"')/'\\"'+P('\n')/'\\n"')^0) -patterns.luaquoted=Cs(Cc('"')*((1-S('"\n'))^1+P('"')/'\\"'+P('\n')/'\\n"')^0*Cc('"')) -if _LUAVERSION<5.2 then - add(formatters,"xml",[[lpegmatch(xmlescape,%s)]],"local xmlescape = lpeg.patterns.xmlescape") - add(formatters,"tex",[[lpegmatch(texescape,%s)]],"local texescape = lpeg.patterns.texescape") - add(formatters,"lua",[[lpegmatch(luaescape,%s)]],"local luaescape = lpeg.patterns.luaescape") -else - add(formatters,"xml",[[lpegmatch(xmlescape,%s)]],{ xmlescape=lpeg.patterns.xmlescape }) - add(formatters,"tex",[[lpegmatch(texescape,%s)]],{ texescape=lpeg.patterns.texescape }) - add(formatters,"lua",[[lpegmatch(luaescape,%s)]],{ luaescape=lpeg.patterns.luaescape }) -end -local dquote=patterns.dquote -local equote=patterns.escaped+dquote/'\\"'+1 -local space=patterns.space -local cquote=Cc('"') -local pattern=Cs(dquote*(equote-P(-2))^0*dquote) -+Cs(cquote*(equote-space)^0*space*equote^0*cquote) -function string.optionalquoted(str) - return lpegmatch(pattern,str) or str -end -local pattern=Cs((newline/(os.newline or "\r")+1)^0) -function string.replacenewlines(str) - return lpegmatch(pattern,str) -end - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['util-fil']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local byte=string.byte -local char=string.char -local extract=bit32 and bit32.extract -local floor=math.floor -utilities=utilities or {} -local files={} -utilities.files=files -local zerobased={} -function files.open(filename,zb) - local f=io.open(filename,"rb") - if f then - zerobased[f]=zb or false - end - return f -end -function files.close(f) - zerobased[f]=nil - f:close() -end -function files.size(f) - return f:seek("end") -end -files.getsize=files.size -function files.setposition(f,n) - if zerobased[f] then - f:seek("set",n) - else - f:seek("set",n-1) - end -end -function files.getposition(f) - if zerobased[f] then - return f:seek() - else - return f:seek()+1 - end -end -function files.look(f,n,chars) - local p=f:seek() - local s=f:read(n) - f:seek("set",p) - if chars then - return s - else - return byte(s,1,#s) - end -end -function files.skip(f,n) - if n==1 then - f:read(n) - else - f:seek("set",f:seek()+n) - end -end -function files.readbyte(f) - return byte(f:read(1)) -end -function files.readbytes(f,n) - return byte(f:read(n),1,n) -end -function files.readchar(f) - return f:read(1) -end -function files.readstring(f,n) - return f:read(n or 1) -end -function files.readinteger1(f) - local n=byte(f:read(1)) - if n>=0x80 then - return n-0x100 - else - return n - end -end -files.readcardinal1=files.readbyte -files.readcardinal=files.readcardinal1 -files.readinteger=files.readinteger1 -function files.readcardinal2(f) - local a,b=byte(f:read(2),1,2) - return 0x100*a+b -end -function files.readcardinal2le(f) - local b,a=byte(f:read(2),1,2) - return 0x100*a+b -end -function files.readinteger2(f) - local a,b=byte(f:read(2),1,2) - local n=0x100*a+b - if n>=0x8000 then - return n-0x10000 - else - return n - end -end -function files.readinteger2le(f) - local b,a=byte(f:read(2),1,2) - local n=0x100*a+b - if n>=0x8000 then - return n-0x10000 - else - return n - end -end -function files.readcardinal3(f) - local a,b,c=byte(f:read(3),1,3) - return 0x10000*a+0x100*b+c -end -function files.readcardinal3le(f) - local c,b,a=byte(f:read(3),1,3) - return 0x10000*a+0x100*b+c -end -function files.readinteger3(f) - local a,b,c=byte(f:read(3),1,3) - local n=0x10000*a+0x100*b+c - if n>=0x80000 then - return n-0x1000000 - else - return n - end -end -function files.readinteger3le(f) - local c,b,a=byte(f:read(3),1,3) - local n=0x10000*a+0x100*b+c - if n>=0x80000 then - return n-0x1000000 - else - return n - end -end -function files.readcardinal4(f) - local a,b,c,d=byte(f:read(4),1,4) - return 0x1000000*a+0x10000*b+0x100*c+d -end -function files.readcardinal4le(f) - local d,c,b,a=byte(f:read(4),1,4) - return 0x1000000*a+0x10000*b+0x100*c+d -end -function files.readinteger4(f) - local a,b,c,d=byte(f:read(4),1,4) - local n=0x1000000*a+0x10000*b+0x100*c+d - if n>=0x8000000 then - return n-0x100000000 - else - return n - end -end -function files.readinteger4le(f) - local d,c,b,a=byte(f:read(4),1,4) - local n=0x1000000*a+0x10000*b+0x100*c+d - if n>=0x8000000 then - return n-0x100000000 - else - return n - end -end -function files.readfixed4(f) - local a,b,c,d=byte(f:read(4),1,4) - local n=0x100*a+b - if n>=0x8000 then - return n-0x10000+(0x100*c+d)/0xFFFF - else - return n+(0x100*c+d)/0xFFFF - end -end -if extract then - function files.read2dot14(f) - local a,b=byte(f:read(2),1,2) - local n=0x100*a+b - local m=extract(n,0,30) - if n>0x7FFF then - n=extract(n,30,2) - return m/0x4000-4 - else - n=extract(n,30,2) - return n+m/0x4000 - end - end -end -function files.skipshort(f,n) - f:read(2*(n or 1)) -end -function files.skiplong(f,n) - f:read(4*(n or 1)) -end -function files.writecardinal2(f,n) - local a=char(n%256) - n=floor(n/256) - local b=char(n%256) - f:write(b,a) -end -function files.writecardinal4(f,n) - local a=char(n%256) - n=floor(n/256) - local b=char(n%256) - n=floor(n/256) - local c=char(n%256) - n=floor(n/256) - local d=char(n%256) - f:write(d,c,b,a) -end -function files.writestring(f,s) - f:write(char(byte(s,1,#s))) -end -function files.writebyte(f,b) - f:write(char(b)) -end - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['luat-basics-gen']={ - version=1.100, - comment="companion to luatex-*.tex", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -if context then - texio.write_nl("fatal error: this module is not for context") - os.exit() -end -local dummyfunction=function() -end -local dummyreporter=function(c) - return function(f,...) - local r=texio.reporter or texio.write_nl - if f then - r(c.." : "..string.formatters(f,...)) - else - r("") - end - end -end -statistics={ - register=dummyfunction, - starttiming=dummyfunction, - stoptiming=dummyfunction, - elapsedtime=nil, -} -directives={ - register=dummyfunction, - enable=dummyfunction, - disable=dummyfunction, -} -trackers={ - register=dummyfunction, - enable=dummyfunction, - disable=dummyfunction, -} -experiments={ - register=dummyfunction, - enable=dummyfunction, - disable=dummyfunction, -} -storage={ - register=dummyfunction, - shared={}, -} -logs={ - new=dummyreporter, - reporter=dummyreporter, - messenger=dummyreporter, - report=dummyfunction, -} -callbacks={ - register=function(n,f) - return callback.register(n,f) - end, -} -utilities=utilities or {} utilities.storage={ - allocate=function(t) - return t or {} - end, - mark=function(t) - return t or {} - end, -} -characters=characters or { - data={} -} -texconfig.kpse_init=true -resolvers=resolvers or {} -local remapper={ - otf="opentype fonts", - ttf="truetype fonts", - ttc="truetype fonts", - cid="cid maps", - cidmap="cid maps", - pfb="type1 fonts", - afm="afm", - enc="enc files", -} -function resolvers.findfile(name,fileformat) - name=string.gsub(name,"\\","/") - if not fileformat or fileformat=="" then - fileformat=file.suffix(name) - if fileformat=="" then - fileformat="tex" - end - end - fileformat=string.lower(fileformat) - fileformat=remapper[fileformat] or fileformat - local found=kpse.find_file(name,fileformat) - if not found or found=="" then - found=kpse.find_file(name,"other text files") - end - return found -end -resolvers.findbinfile=resolvers.findfile -function resolvers.loadbinfile(filename,filetype) - local data=io.loaddata(filename) - return true,data,#data -end -function resolvers.resolve(s) - return s -end -function resolvers.unresolve(s) - return s -end -caches={} -local writable=nil -local readables={} -local usingjit=jit -if not caches.namespace or caches.namespace=="" or caches.namespace=="context" then - caches.namespace='generic' -end -do - local cachepaths=kpse.expand_var('$TEXMFCACHE') or "" - if cachepaths=="" or cachepaths=="$TEXMFCACHE" then - cachepaths=kpse.expand_var('$TEXMFVAR') or "" - end - if cachepaths=="" or cachepaths=="$TEXMFVAR" then - cachepaths=kpse.expand_var('$VARTEXMF') or "" - end - if cachepaths=="" then - local fallbacks={ "TMPDIR","TEMPDIR","TMP","TEMP","HOME","HOMEPATH" } - for i=1,#fallbacks do - cachepaths=os.getenv(fallbacks[i]) or "" - if cachepath~="" and lfs.isdir(cachepath) then - break - end - end - end - if cachepaths=="" then - cachepaths="." - end - cachepaths=string.split(cachepaths,os.type=="windows" and ";" or ":") - for i=1,#cachepaths do - local cachepath=cachepaths[i] - if not lfs.isdir(cachepath) then - lfs.mkdirs(cachepath) - if lfs.isdir(cachepath) then - texio.write(string.format("(created cache path: %s)",cachepath)) - end - end - if file.is_writable(cachepath) then - writable=file.join(cachepath,"luatex-cache") - lfs.mkdir(writable) - writable=file.join(writable,caches.namespace) - lfs.mkdir(writable) - break - end - end - for i=1,#cachepaths do - if file.is_readable(cachepaths[i]) then - readables[#readables+1]=file.join(cachepaths[i],"luatex-cache",caches.namespace) - end - end - if not writable then - texio.write_nl("quiting: fix your writable cache path") - os.exit() - elseif #readables==0 then - texio.write_nl("quiting: fix your readable cache path") - os.exit() - elseif #readables==1 and readables[1]==writable then - texio.write(string.format("(using cache: %s)",writable)) - else - texio.write(string.format("(using write cache: %s)",writable)) - texio.write(string.format("(using read cache: %s)",table.concat(readables," "))) - end -end -function caches.getwritablepath(category,subcategory) - local path=file.join(writable,category) - lfs.mkdir(path) - path=file.join(path,subcategory) - lfs.mkdir(path) - return path -end -function caches.getreadablepaths(category,subcategory) - local t={} - for i=1,#readables do - t[i]=file.join(readables[i],category,subcategory) - end - return t -end -local function makefullname(path,name) - if path and path~="" then - 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) - local fullname=makefullname(path,name) - return fullname and file.is_writable(fullname) -end -function caches.loaddata(readables,name,writable) - for i=1,#readables do - local path=readables[i] - local loader=false - local luaname,lucname=makefullname(path,name) - if lfs.isfile(lucname) then - texio.write(string.format("(load luc: %s)",lucname)) - loader=loadfile(lucname) - end - if not loader and lfs.isfile(luaname) then - local luacrap,lucname=makefullname(writable,name) - texio.write(string.format("(compiling luc: %s)",lucname)) - if lfs.isfile(lucname) then - loader=loadfile(lucname) - end - caches.compile(data,luaname,lucname) - if lfs.isfile(lucname) then - texio.write(string.format("(load luc: %s)",lucname)) - loader=loadfile(lucname) - else - texio.write(string.format("(loading failed: %s)",lucname)) - end - if not loader then - texio.write(string.format("(load lua: %s)",luaname)) - loader=loadfile(luaname) - else - texio.write(string.format("(loading failed: %s)",luaname)) - end - end - if loader then - loader=loader() - collectgarbage("step") - return loader - end - end - return false -end -function caches.savedata(path,name,data) - local luaname,lucname=makefullname(path,name) - if luaname then - texio.write(string.format("(save: %s)",luaname)) - table.tofile(luaname,data,true) - if lucname and type(caches.compile)=="function" then - os.remove(lucname) - texio.write(string.format("(save: %s)",lucname)) - caches.compile(data,luaname,lucname) - end - end -end -function caches.compile(data,luaname,lucname) - 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,'wb') - if f then - local s=loadstring(d) - if s then - f:write(string.dump(s,true)) - end - f:close() - end - end -end -function table.setmetatableindex(t,f) - if type(t)~="table" then - f,t=t,{} - end - local m=getmetatable(t) - if f=="table" then - f=function(t,k) local v={} t[k]=v return v end - end - if m then - m.__index=f - else - setmetatable(t,{ __index=f }) - end - return t -end -arguments={} -if arg then - for i=1,#arg do - local k,v=string.match(arg[i],"^%-%-([^=]+)=?(.-)$") - if k and v then - arguments[k]=v - end - end -end - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['data-con']={ - version=1.100, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local format,lower,gsub=string.format,string.lower,string.gsub -local trace_cache=false trackers.register("resolvers.cache",function(v) trace_cache=v end) -local trace_containers=false trackers.register("resolvers.containers",function(v) trace_containers=v end) -local trace_storage=false trackers.register("resolvers.storage",function(v) trace_storage=v end) -containers=containers or {} -local containers=containers -containers.usecache=true -local report_containers=logs.reporter("resolvers","containers") -local allocated={} -local mt={ - __index=function(t,k) - if k=="writable" then - local writable=caches.getwritablepath(t.category,t.subcategory) or { "." } - t.writable=writable - return writable - elseif k=="readables" then - local readables=caches.getreadablepaths(t.category,t.subcategory) or { "." } - t.readables=readables - return readables - end - end, - __storage__=true -} -function containers.define(category,subcategory,version,enabled) - if category and subcategory then - local c=allocated[category] - if not c then - c={} - allocated[category]=c - end - local s=c[subcategory] - if not s then - s={ - category=category, - subcategory=subcategory, - storage={}, - enabled=enabled, - version=version or math.pi, - trace=false, - } - setmetatable(s,mt) - c[subcategory]=s - end - return s - end -end -function containers.is_usable(container,name) - return container.enabled and caches and caches.is_writable(container.writable,name) -end -function containers.is_valid(container,name) - if name and name~="" then - local storage=container.storage[name] - return storage and storage.cache_version==container.version - else - return false - end -end -function containers.read(container,name) - local storage=container.storage - local stored=storage[name] - if not stored and container.enabled and caches and containers.usecache then - stored=caches.loaddata(container.readables,name,container.writable) - if stored and stored.cache_version==container.version then - if trace_cache or trace_containers then - report_containers("action %a, category %a, name %a","load",container.subcategory,name) - end - else - stored=nil - end - storage[name]=stored - elseif stored then - if trace_cache or trace_containers then - report_containers("action %a, category %a, name %a","reuse",container.subcategory,name) - end - end - return stored -end -function containers.write(container,name,data) - if data then - data.cache_version=container.version - if container.enabled and caches then - local unique,shared=data.unique,data.shared - data.unique,data.shared=nil,nil - caches.savedata(container.writable,name,data) - if trace_cache or trace_containers then - report_containers("action %a, category %a, name %a","save",container.subcategory,name) - end - data.unique,data.shared=unique,shared - end - if trace_cache or trace_containers then - report_containers("action %a, category %a, name %a","store",container.subcategory,name) - end - container.storage[name]=data - end - return data -end -function containers.content(container,name) - return container.storage[name] -end -function containers.cleanname(name) - return (gsub(lower(name),"[^%w\128-\255]+","-")) -end - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['luatex-fonts-nod']={ - version=1.001, - comment="companion to luatex-fonts.lua", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -if context then - texio.write_nl("fatal error: this module is not for context") - os.exit() -end -if tex.attribute[0]~=0 then - texio.write_nl("log","!") - texio.write_nl("log","! Attribute 0 is reserved for ConTeXt's font feature management and has to be") - texio.write_nl("log","! set to zero. Also, some attributes in the range 1-255 are used for special") - texio.write_nl("log","! purposes so setting them at the TeX end might break the font handler.") - texio.write_nl("log","!") - tex.attribute[0]=0 -end -attributes=attributes or {} -attributes.unsetvalue=-0x7FFFFFFF -local numbers,last={},127 -attributes.private=attributes.private or function(name) - local number=numbers[name] - if not number then - if last<255 then - last=last+1 - end - number=last - numbers[name]=number - end - return number -end -nodes={} -nodes.pool={} -nodes.handlers={} -local nodecodes={} -local glyphcodes=node.subtypes("glyph") -local disccodes=node.subtypes("disc") -for k,v in next,node.types() do - v=string.gsub(v,"_","") - nodecodes[k]=v - nodecodes[v]=k -end -for i=0,#glyphcodes do - glyphcodes[glyphcodes[i]]=i -end -for i=0,#disccodes do - disccodes[disccodes[i]]=i -end -nodes.nodecodes=nodecodes -nodes.glyphcodes=glyphcodes -nodes.disccodes=disccodes -local flush_node=node.flush_node -local remove_node=node.remove -local new_node=node.new -local traverse_id=node.traverse_id -nodes.handlers.protectglyphs=node.protect_glyphs -nodes.handlers.unprotectglyphs=node.unprotect_glyphs -local math_code=nodecodes.math -local end_of_math=node.end_of_math -function node.end_of_math(n) - if n.id==math_code and n.subtype==1 then - return n - else - return end_of_math(n) - end -end -function nodes.remove(head,current,free_too) - local t=current - head,current=remove_node(head,current) - if t then - if free_too then - flush_node(t) - t=nil - else - t.next,t.prev=nil,nil - end - end - return head,current,t -end -function nodes.delete(head,current) - return nodes.remove(head,current,true) -end -function nodes.pool.kern(k) - local n=new_node("kern",1) - n.kern=k - return n -end -local getfield=node.getfield -local setfield=node.setfield -nodes.getfield=getfield -nodes.setfield=setfield -nodes.getattr=getfield -nodes.setattr=setfield -nodes.tostring=node.tostring or tostring -nodes.copy=node.copy -nodes.copy_node=node.copy -nodes.copy_list=node.copy_list -nodes.delete=node.delete -nodes.dimensions=node.dimensions -nodes.end_of_math=node.end_of_math -nodes.flush_list=node.flush_list -nodes.flush_node=node.flush_node -nodes.flush=node.flush_node -nodes.free=node.free -nodes.insert_after=node.insert_after -nodes.insert_before=node.insert_before -nodes.hpack=node.hpack -nodes.new=node.new -nodes.tail=node.tail -nodes.traverse=node.traverse -nodes.traverse_id=node.traverse_id -nodes.slide=node.slide -nodes.vpack=node.vpack -nodes.first_glyph=node.first_glyph -nodes.has_glyph=node.has_glyph or node.first_glyph -nodes.current_attr=node.current_attr -nodes.has_field=node.has_field -nodes.last_node=node.last_node -nodes.usedlist=node.usedlist -nodes.protrusion_skippable=node.protrusion_skippable -nodes.write=node.write -nodes.has_attribute=node.has_attribute -nodes.set_attribute=node.set_attribute -nodes.unset_attribute=node.unset_attribute -nodes.protect_glyphs=node.protect_glyphs -nodes.unprotect_glyphs=node.unprotect_glyphs -nodes.mlist_to_hlist=node.mlist_to_hlist -local direct=node.direct -local nuts={} -nodes.nuts=nuts -local tonode=direct.tonode -local tonut=direct.todirect -nodes.tonode=tonode -nodes.tonut=tonut -nuts.tonode=tonode -nuts.tonut=tonut -local getfield=direct.getfield -local setfield=direct.setfield -nuts.getfield=getfield -nuts.setfield=setfield -nuts.getnext=direct.getnext -nuts.setnext=direct.setnext -nuts.getprev=direct.getprev -nuts.setprev=direct.setprev -nuts.getboth=direct.getboth -nuts.setboth=direct.setboth -nuts.getid=direct.getid -nuts.getattr=direct.get_attribute or direct.has_attribute or getfield -nuts.setattr=setfield -nuts.getfont=direct.getfont -nuts.setfont=direct.setfont -nuts.getsubtype=direct.getsubtype -nuts.setsubtype=direct.setsubtype or function(n,s) setfield(n,"subtype",s) end -nuts.getchar=direct.getchar -nuts.setchar=direct.setchar -nuts.getdisc=direct.getdisc -nuts.setdisc=direct.setdisc -nuts.setlink=direct.setlink -nuts.getlist=direct.getlist -nuts.setlist=direct.setlist or function(n,l) setfield(n,"list",l) end -nuts.getleader=direct.getleader -nuts.setleader=direct.setleader or function(n,l) setfield(n,"leader",l) end -if not direct.is_glyph then - local getchar=direct.getchar - local getid=direct.getid - local getfont=direct.getfont - local glyph_code=nodes.nodecodes.glyph - function direct.is_glyph(n,f) - local id=getid(n) - if id==glyph_code then - if f and getfont(n)==f then - return getchar(n) - else - return false - end - else - return nil,id - end - end - function direct.is_char(n,f) - local id=getid(n) - if id==glyph_code then - if getsubtype(n)>=256 then - return false - elseif f and getfont(n)==f then - return getchar(n) - else - return false - end - else - return nil,id - end - end -end -nuts.ischar=direct.is_char -nuts.is_char=direct.is_char -nuts.isglyph=direct.is_glyph -nuts.is_glyph=direct.is_glyph -nuts.insert_before=direct.insert_before -nuts.insert_after=direct.insert_after -nuts.delete=direct.delete -nuts.copy=direct.copy -nuts.copy_node=direct.copy -nuts.copy_list=direct.copy_list -nuts.tail=direct.tail -nuts.flush_list=direct.flush_list -nuts.flush_node=direct.flush_node -nuts.flush=direct.flush -nuts.free=direct.free -nuts.remove=direct.remove -nuts.is_node=direct.is_node -nuts.end_of_math=direct.end_of_math -nuts.traverse=direct.traverse -nuts.traverse_id=direct.traverse_id -nuts.traverse_char=direct.traverse_char -nuts.ligaturing=direct.ligaturing -nuts.kerning=direct.kerning -nuts.getprop=nuts.getattr -nuts.setprop=nuts.setattr -local new_nut=direct.new -nuts.new=new_nut -nuts.pool={} -function nuts.pool.kern(k) - local n=new_nut("kern",1) - setfield(n,"kern",k) - return n -end -local propertydata=direct.get_properties_table() -nodes.properties={ data=propertydata } -direct.set_properties_mode(true,true) -function direct.set_properties_mode() end -nuts.getprop=function(n,k) - local p=propertydata[n] - if p then - return p[k] - end -end -nuts.setprop=function(n,k,v) - if v then - local p=propertydata[n] - if p then - p[k]=v - else - propertydata[n]={ [k]=v } - end - end -end -nodes.setprop=nodes.setproperty -nodes.getprop=nodes.getproperty - -end -- closure - -do -- begin closure to overcome local limits and interference - - -characters=characters or {} -characters.blockrange={} -characters.classifiers={ - [1536]=4, - [1537]=4, - [1538]=4, - [1539]=4, - [1540]=4, - [1541]=4, - [1542]=6, - [1543]=6, - [1544]=4, - [1545]=6, - [1546]=6, - [1547]=4, - [1548]=6, - [1549]=6, - [1550]=6, - [1551]=6, - [1552]=5, - [1553]=5, - [1554]=5, - [1555]=5, - [1556]=5, - [1557]=5, - [1558]=5, - [1559]=5, - [1560]=5, - [1561]=5, - [1562]=5, - [1563]=6, - [1564]=6, - [1566]=6, - [1567]=6, - [1568]=2, - [1569]=4, - [1570]=3, - [1571]=3, - [1572]=3, - [1573]=3, - [1574]=2, - [1575]=3, - [1576]=2, - [1577]=3, - [1578]=2, - [1579]=2, - [1580]=2, - [1581]=2, - [1582]=2, - [1583]=3, - [1584]=3, - [1585]=3, - [1586]=3, - [1587]=2, - [1588]=2, - [1589]=2, - [1590]=2, - [1591]=2, - [1592]=2, - [1593]=2, - [1594]=2, - [1595]=2, - [1596]=2, - [1597]=2, - [1598]=2, - [1599]=2, - [1600]=2, - [1601]=2, - [1602]=2, - [1603]=2, - [1604]=2, - [1605]=2, - [1606]=2, - [1607]=2, - [1608]=3, - [1609]=2, - [1610]=2, - [1611]=5, - [1612]=5, - [1613]=5, - [1614]=5, - [1615]=5, - [1616]=5, - [1617]=5, - [1618]=5, - [1619]=5, - [1620]=5, - [1621]=5, - [1622]=5, - [1623]=5, - [1624]=5, - [1625]=5, - [1626]=5, - [1627]=5, - [1628]=5, - [1629]=5, - [1630]=5, - [1631]=5, - [1632]=6, - [1633]=6, - [1634]=6, - [1635]=6, - [1636]=6, - [1637]=6, - [1638]=6, - [1639]=6, - [1640]=6, - [1641]=6, - [1642]=6, - [1643]=6, - [1644]=6, - [1645]=6, - [1646]=2, - [1647]=2, - [1648]=5, - [1649]=3, - [1650]=3, - [1651]=3, - [1652]=4, - [1653]=3, - [1654]=3, - [1655]=3, - [1656]=2, - [1657]=2, - [1658]=2, - [1659]=2, - [1660]=2, - [1661]=2, - [1662]=2, - [1663]=2, - [1664]=2, - [1665]=2, - [1666]=2, - [1667]=2, - [1668]=2, - [1669]=2, - [1670]=2, - [1671]=2, - [1672]=3, - [1673]=3, - [1674]=3, - [1675]=3, - [1676]=3, - [1677]=3, - [1678]=3, - [1679]=3, - [1680]=3, - [1681]=3, - [1682]=3, - [1683]=3, - [1684]=3, - [1685]=3, - [1686]=3, - [1687]=3, - [1688]=3, - [1689]=3, - [1690]=2, - [1691]=2, - [1692]=2, - [1693]=2, - [1694]=2, - [1695]=2, - [1696]=2, - [1697]=2, - [1698]=2, - [1699]=2, - [1700]=2, - [1701]=2, - [1702]=2, - [1703]=2, - [1704]=2, - [1705]=2, - [1706]=2, - [1707]=2, - [1708]=2, - [1709]=2, - [1710]=2, - [1711]=2, - [1712]=2, - [1713]=2, - [1714]=2, - [1715]=2, - [1716]=2, - [1717]=2, - [1718]=2, - [1719]=2, - [1720]=2, - [1721]=2, - [1722]=2, - [1723]=2, - [1724]=2, - [1725]=2, - [1726]=2, - [1727]=2, - [1728]=3, - [1729]=2, - [1730]=2, - [1731]=3, - [1732]=3, - [1733]=3, - [1734]=3, - [1735]=3, - [1736]=3, - [1737]=3, - [1738]=3, - [1739]=3, - [1740]=2, - [1741]=3, - [1742]=2, - [1743]=3, - [1744]=2, - [1745]=2, - [1746]=3, - [1747]=3, - [1748]=6, - [1749]=3, - [1750]=5, - [1751]=5, - [1752]=5, - [1753]=5, - [1754]=5, - [1755]=5, - [1756]=5, - [1757]=4, - [1758]=6, - [1759]=5, - [1760]=5, - [1761]=5, - [1762]=5, - [1763]=5, - [1764]=5, - [1765]=6, - [1766]=6, - [1767]=5, - [1768]=5, - [1769]=6, - [1770]=5, - [1771]=5, - [1772]=5, - [1773]=5, - [1774]=3, - [1775]=3, - [1776]=6, - [1777]=6, - [1778]=6, - [1779]=6, - [1780]=6, - [1781]=6, - [1782]=6, - [1783]=6, - [1784]=6, - [1785]=6, - [1786]=2, - [1787]=2, - [1788]=2, - [1789]=6, - [1790]=6, - [1791]=2, - [1792]=6, - [1793]=6, - [1794]=6, - [1795]=6, - [1796]=6, - [1797]=6, - [1798]=6, - [1799]=6, - [1800]=6, - [1801]=6, - [1802]=6, - [1803]=6, - [1804]=6, - [1805]=6, - [1807]=6, - [1808]=3, - [1809]=5, - [1810]=2, - [1811]=2, - [1812]=2, - [1813]=3, - [1814]=3, - [1815]=3, - [1816]=3, - [1817]=3, - [1818]=2, - [1819]=2, - [1820]=2, - [1821]=2, - [1822]=3, - [1823]=2, - [1824]=2, - [1825]=2, - [1826]=2, - [1827]=2, - [1828]=2, - [1829]=2, - [1830]=2, - [1831]=2, - [1832]=3, - [1833]=2, - [1834]=3, - [1835]=2, - [1836]=3, - [1837]=2, - [1838]=2, - [1839]=3, - [1840]=5, - [1841]=5, - [1842]=5, - [1843]=5, - [1844]=5, - [1845]=5, - [1846]=5, - [1847]=5, - [1848]=5, - [1849]=5, - [1850]=5, - [1851]=5, - [1852]=5, - [1853]=5, - [1854]=5, - [1855]=5, - [1856]=5, - [1857]=5, - [1858]=5, - [1859]=5, - [1860]=5, - [1861]=5, - [1862]=5, - [1863]=5, - [1864]=5, - [1865]=5, - [1866]=5, - [1869]=3, - [1870]=2, - [1871]=2, - [1872]=2, - [1873]=2, - [1874]=2, - [1875]=2, - [1876]=2, - [1877]=2, - [1878]=2, - [1879]=2, - [1880]=2, - [1881]=3, - [1882]=3, - [1883]=3, - [1884]=2, - [1885]=2, - [1886]=2, - [1887]=2, - [1888]=2, - [1889]=2, - [1890]=2, - [1891]=2, - [1892]=2, - [1893]=2, - [1894]=2, - [1895]=2, - [1896]=2, - [1897]=2, - [1898]=2, - [1899]=3, - [1900]=3, - [1901]=2, - [1902]=2, - [1903]=2, - [1904]=2, - [1905]=3, - [1906]=2, - [1907]=3, - [1908]=3, - [1909]=2, - [1910]=2, - [1911]=2, - [1912]=3, - [1913]=3, - [1914]=2, - [1915]=2, - [1916]=2, - [1917]=2, - [1918]=2, - [1919]=2, - [1984]=6, - [1985]=6, - [1986]=6, - [1987]=6, - [1988]=6, - [1989]=6, - [1990]=6, - [1991]=6, - [1992]=6, - [1993]=6, - [1994]=2, - [1995]=2, - [1996]=2, - [1997]=2, - [1998]=2, - [1999]=2, - [2000]=2, - [2001]=2, - [2002]=2, - [2003]=2, - [2004]=2, - [2005]=2, - [2006]=2, - [2007]=2, - [2008]=2, - [2009]=2, - [2010]=2, - [2011]=2, - [2012]=2, - [2013]=2, - [2014]=2, - [2015]=2, - [2016]=2, - [2017]=2, - [2018]=2, - [2019]=2, - [2020]=2, - [2021]=2, - [2022]=2, - [2023]=2, - [2024]=2, - [2025]=2, - [2026]=2, - [2027]=5, - [2028]=5, - [2029]=5, - [2030]=5, - [2031]=5, - [2032]=5, - [2033]=5, - [2034]=5, - [2035]=5, - [2036]=6, - [2037]=6, - [2038]=6, - [2039]=6, - [2040]=6, - [2041]=6, - [2042]=2, - [2112]=3, - [2113]=2, - [2114]=2, - [2115]=2, - [2116]=2, - [2117]=2, - [2118]=3, - [2119]=3, - [2120]=2, - [2121]=3, - [2122]=2, - [2123]=2, - [2124]=2, - [2125]=2, - [2126]=2, - [2127]=2, - [2128]=2, - [2129]=2, - [2130]=2, - [2131]=2, - [2132]=3, - [2133]=2, - [2134]=4, - [2135]=4, - [2136]=4, - [2208]=2, - [2209]=2, - [2210]=2, - [2211]=2, - [2212]=2, - [2213]=2, - [2214]=2, - [2215]=2, - [2216]=2, - [2217]=2, - [2218]=3, - [2219]=3, - [2220]=3, - [2221]=4, - [2222]=3, - [2223]=2, - [2224]=2, - [2225]=3, - [2226]=3, - [2227]=2, - [2228]=2, - [6150]=4, - [6151]=2, - [6154]=2, - [6158]=4, - [6176]=2, - [6177]=2, - [6178]=2, - [6179]=2, - [6180]=2, - [6181]=2, - [6182]=2, - [6183]=2, - [6184]=2, - [6185]=2, - [6186]=2, - [6187]=2, - [6188]=2, - [6189]=2, - [6190]=2, - [6191]=2, - [6192]=2, - [6193]=2, - [6194]=2, - [6195]=2, - [6196]=2, - [6197]=2, - [6198]=2, - [6199]=2, - [6200]=2, - [6201]=2, - [6202]=2, - [6203]=2, - [6204]=2, - [6205]=2, - [6206]=2, - [6207]=2, - [6208]=2, - [6209]=2, - [6210]=2, - [6211]=2, - [6212]=2, - [6213]=2, - [6214]=2, - [6215]=2, - [6216]=2, - [6217]=2, - [6218]=2, - [6219]=2, - [6220]=2, - [6221]=2, - [6222]=2, - [6223]=2, - [6224]=2, - [6225]=2, - [6226]=2, - [6227]=2, - [6228]=2, - [6229]=2, - [6230]=2, - [6231]=2, - [6232]=2, - [6233]=2, - [6234]=2, - [6235]=2, - [6236]=2, - [6237]=2, - [6238]=2, - [6239]=2, - [6240]=2, - [6241]=2, - [6242]=2, - [6243]=2, - [6244]=2, - [6245]=2, - [6246]=2, - [6247]=2, - [6248]=2, - [6249]=2, - [6250]=2, - [6251]=2, - [6252]=2, - [6253]=2, - [6254]=2, - [6255]=2, - [6256]=2, - [6257]=2, - [6258]=2, - [6259]=2, - [6260]=2, - [6261]=2, - [6262]=2, - [6263]=2, - [6272]=4, - [6273]=4, - [6274]=4, - [6275]=4, - [6276]=4, - [6277]=4, - [6278]=4, - [6279]=2, - [6280]=2, - [6281]=2, - [6282]=2, - [6283]=2, - [6284]=2, - [6285]=2, - [6286]=2, - [6287]=2, - [6288]=2, - [6289]=2, - [6290]=2, - [6291]=2, - [6292]=2, - [6293]=2, - [6294]=2, - [6295]=2, - [6296]=2, - [6297]=2, - [6298]=2, - [6299]=2, - [6300]=2, - [6301]=2, - [6302]=2, - [6303]=2, - [6304]=2, - [6305]=2, - [6306]=2, - [6307]=2, - [6308]=2, - [6309]=2, - [6310]=2, - [6311]=2, - [6312]=2, - [6314]=2, - [8204]=4, - [8205]=2, - [8294]=4, - [8295]=4, - [8296]=4, - [8297]=4, - [43072]=2, - [43073]=2, - [43074]=2, - [43075]=2, - [43076]=2, - [43077]=2, - [43078]=2, - [43079]=2, - [43080]=2, - [43081]=2, - [43082]=2, - [43083]=2, - [43084]=2, - [43085]=2, - [43086]=2, - [43087]=2, - [43088]=2, - [43089]=2, - [43090]=2, - [43091]=2, - [43092]=2, - [43093]=2, - [43094]=2, - [43095]=2, - [43096]=2, - [43097]=2, - [43098]=2, - [43099]=2, - [43100]=2, - [43101]=2, - [43102]=2, - [43103]=2, - [43104]=2, - [43105]=2, - [43106]=2, - [43107]=2, - [43108]=2, - [43109]=2, - [43110]=2, - [43111]=2, - [43112]=2, - [43113]=2, - [43114]=2, - [43115]=2, - [43116]=2, - [43117]=2, - [43118]=2, - [43119]=2, - [43120]=2, - [43121]=2, - [43122]=1, - [43123]=4, - [68288]=2, - [68289]=2, - [68290]=2, - [68291]=2, - [68292]=2, - [68293]=3, - [68294]=4, - [68295]=3, - [68296]=4, - [68297]=3, - [68298]=3, - [68299]=4, - [68300]=4, - [68301]=1, - [68302]=3, - [68303]=3, - [68304]=3, - [68305]=3, - [68306]=3, - [68307]=2, - [68308]=2, - [68309]=2, - [68310]=2, - [68311]=1, - [68312]=2, - [68313]=2, - [68314]=2, - [68315]=2, - [68316]=2, - [68317]=3, - [68318]=2, - [68319]=2, - [68320]=2, - [68321]=3, - [68322]=4, - [68323]=4, - [68324]=3, - [68331]=2, - [68332]=2, - [68333]=2, - [68334]=2, - [68335]=3, - [68480]=2, - [68481]=3, - [68482]=2, - [68483]=3, - [68484]=3, - [68485]=3, - [68486]=2, - [68487]=2, - [68488]=2, - [68489]=3, - [68490]=2, - [68491]=2, - [68492]=3, - [68493]=2, - [68494]=3, - [68495]=3, - [68496]=2, - [68497]=3, - [68521]=3, - [68522]=3, - [68523]=3, - [68524]=3, - [68525]=2, - [68526]=2, - [68527]=4, -} - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['font-ini']={ - version=1.001, - comment="companion to font-ini.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local allocate=utilities.storage.allocate -fonts=fonts or {} -local fonts=fonts -fonts.hashes={ identifiers=allocate() } -fonts.tables=fonts.tables or {} -fonts.helpers=fonts.helpers or {} -fonts.tracers=fonts.tracers or {} -fonts.specifiers=fonts.specifiers or {} -fonts.analyzers={} -fonts.readers={} -fonts.definers={ methods={} } -fonts.loggers={ register=function() end } -fontloader.totable=fontloader.to_table - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['font-con']={ - version=1.001, - comment="companion to font-ini.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local next,tostring,rawget=next,tostring,rawget -local format,match,lower,gsub,find=string.format,string.match,string.lower,string.gsub,string.find -local sort,insert,concat,sortedkeys,serialize,fastcopy=table.sort,table.insert,table.concat,table.sortedkeys,table.serialize,table.fastcopy -local derivetable=table.derive -local ioflush=io.flush -local trace_defining=false trackers.register("fonts.defining",function(v) trace_defining=v end) -local trace_scaling=false trackers.register("fonts.scaling",function(v) trace_scaling=v end) -local report_defining=logs.reporter("fonts","defining") -local fonts=fonts -local constructors=fonts.constructors or {} -fonts.constructors=constructors -local handlers=fonts.handlers or {} -fonts.handlers=handlers -local allocate=utilities.storage.allocate -local setmetatableindex=table.setmetatableindex -constructors.dontembed=allocate() -constructors.autocleanup=true -constructors.namemode="fullpath" -constructors.version=1.01 -constructors.cache=containers.define("fonts","constructors",constructors.version,false) -constructors.privateoffset=0xF0000 -constructors.cacheintex=true -local designsizes=allocate() -constructors.designsizes=designsizes -local loadedfonts=allocate() -constructors.loadedfonts=loadedfonts -local factors={ - pt=65536.0, - bp=65781.8, -} -function constructors.setfactor(f) - constructors.factor=factors[f or 'pt'] or factors.pt -end -constructors.setfactor() -function constructors.scaled(scaledpoints,designsize) - if scaledpoints<0 then - local factor=constructors.factor - if designsize then - if designsize>factor then - return (- scaledpoints/1000)*designsize - else - return (- scaledpoints/1000)*designsize*factor - end - else - return (- scaledpoints/1000)*10*factor - end - else - return scaledpoints - end -end -function constructors.cleanuptable(tfmdata) - if constructors.autocleanup and tfmdata.properties.virtualized then - for k,v in next,tfmdata.characters do - if v.commands then v.commands=nil end - end - end -end -function constructors.calculatescale(tfmdata,scaledpoints) - local parameters=tfmdata.parameters - if scaledpoints<0 then - scaledpoints=(- scaledpoints/1000)*(tfmdata.designsize or parameters.designsize) - end - return scaledpoints,scaledpoints/(parameters.units or 1000) -end -local unscaled={ - ScriptPercentScaleDown=true, - ScriptScriptPercentScaleDown=true, - RadicalDegreeBottomRaisePercent=true, - NoLimitSupFactor=true, - NoLimitSubFactor=true, -} -function constructors.assignmathparameters(target,original) - local mathparameters=original.mathparameters - if mathparameters and next(mathparameters) then - local targetparameters=target.parameters - local targetproperties=target.properties - local targetmathparameters={} - local factor=targetproperties.math_is_scaled and 1 or targetparameters.factor - for name,value in next,mathparameters do - if unscaled[name] then - targetmathparameters[name]=value - else - targetmathparameters[name]=value*factor - end - end - if not targetmathparameters.FractionDelimiterSize then - targetmathparameters.FractionDelimiterSize=1.01*targetparameters.size - end - if not mathparameters.FractionDelimiterDisplayStyleSize then - targetmathparameters.FractionDelimiterDisplayStyleSize=2.40*targetparameters.size - end - target.mathparameters=targetmathparameters - end -end -function constructors.beforecopyingcharacters(target,original) -end -function constructors.aftercopyingcharacters(target,original) -end -constructors.sharefonts=false -constructors.nofsharedfonts=0 -local sharednames={} -function constructors.trytosharefont(target,tfmdata) - if constructors.sharefonts then - local characters=target.characters - local n=1 - local t={ target.psname } - local u=sortedkeys(characters) - for i=1,#u do - local k=u[i] - n=n+1;t[n]=k - n=n+1;t[n]=characters[k].index or k - end - local h=md5.HEX(concat(t," ")) - local s=sharednames[h] - if s then - if trace_defining then - report_defining("font %a uses backend resources of font %a",target.fullname,s) - end - target.fullname=s - constructors.nofsharedfonts=constructors.nofsharedfonts+1 - target.properties.sharedwith=s - else - sharednames[h]=target.fullname - end - end -end -function constructors.enhanceparameters(parameters) - local xheight=parameters.x_height - local quad=parameters.quad - local space=parameters.space - local stretch=parameters.space_stretch - local shrink=parameters.space_shrink - local extra=parameters.extra_space - local slant=parameters.slant - parameters.xheight=xheight - parameters.spacestretch=stretch - parameters.spaceshrink=shrink - parameters.extraspace=extra - parameters.em=quad - parameters.ex=xheight - parameters.slantperpoint=slant - parameters.spacing={ - width=space, - stretch=stretch, - shrink=shrink, - extra=extra, - } -end -local function mathkerns(v,vdelta) - local k={} - for i=1,#v do - local entry=v[i] - local height=entry.height - local kern=entry.kern - k[i]={ - height=height and vdelta*height or 0, - kern=kern and vdelta*kern or 0, - } - end - return k -end -local psfake=0 -local function fixedpsname(psname,fallback) - local usedname=psname - if psname and psname~="" then - if find(psname," ") then - usedname=gsub(psname,"[%s]+","-") - else - end - elseif not fallback or fallback=="" then - psfake=psfake+1 - psname="fakename-"..psfake - else - psname=fallback - usedname=gsub(psname,"[^a-zA-Z0-9]+","-") - end - return usedname,psname~=usedname -end -function constructors.scale(tfmdata,specification) - local target={} - if tonumber(specification) then - specification={ size=specification } - end - target.specification=specification - local scaledpoints=specification.size - local relativeid=specification.relativeid - local properties=tfmdata.properties or {} - local goodies=tfmdata.goodies or {} - local resources=tfmdata.resources or {} - local descriptions=tfmdata.descriptions or {} - local characters=tfmdata.characters or {} - local changed=tfmdata.changed or {} - local shared=tfmdata.shared or {} - local parameters=tfmdata.parameters or {} - local mathparameters=tfmdata.mathparameters or {} - local targetcharacters={} - local targetdescriptions=derivetable(descriptions) - local targetparameters=derivetable(parameters) - local targetproperties=derivetable(properties) - local targetgoodies=goodies - target.characters=targetcharacters - target.descriptions=targetdescriptions - target.parameters=targetparameters - target.properties=targetproperties - target.goodies=targetgoodies - target.shared=shared - target.resources=resources - target.unscaled=tfmdata - local mathsize=tonumber(specification.mathsize) or 0 - local textsize=tonumber(specification.textsize) or scaledpoints - local forcedsize=tonumber(parameters.mathsize ) or 0 - local extrafactor=tonumber(specification.factor ) or 1 - if (mathsize==2 or forcedsize==2) and parameters.scriptpercentage then - scaledpoints=parameters.scriptpercentage*textsize/100 - elseif (mathsize==3 or forcedsize==3) and parameters.scriptscriptpercentage then - scaledpoints=parameters.scriptscriptpercentage*textsize/100 - elseif forcedsize>1000 then - scaledpoints=forcedsize - end - targetparameters.mathsize=mathsize - targetparameters.textsize=textsize - targetparameters.forcedsize=forcedsize - targetparameters.extrafactor=extrafactor - local tounicode=fonts.mappings.tounicode - local defaultwidth=resources.defaultwidth or 0 - local defaultheight=resources.defaultheight or 0 - local defaultdepth=resources.defaultdepth or 0 - local units=parameters.units or 1000 - if target.fonts then - target.fonts=fastcopy(target.fonts) - end - targetproperties.language=properties.language or "dflt" - targetproperties.script=properties.script or "dflt" - targetproperties.mode=properties.mode or "base" - local askedscaledpoints=scaledpoints - local scaledpoints,delta=constructors.calculatescale(tfmdata,scaledpoints,nil,specification) - local hdelta=delta - local vdelta=delta - target.designsize=parameters.designsize - target.units=units - target.units_per_em=units - local direction=properties.direction or tfmdata.direction or 0 - target.direction=direction - properties.direction=direction - target.size=scaledpoints - target.encodingbytes=properties.encodingbytes or 1 - target.embedding=properties.embedding or "subset" - target.tounicode=1 - target.cidinfo=properties.cidinfo - target.format=properties.format - target.cache=constructors.cacheintex and "yes" or "renew" - local fontname=properties.fontname or tfmdata.fontname - local fullname=properties.fullname or tfmdata.fullname - local filename=properties.filename or tfmdata.filename - local psname=properties.psname or tfmdata.psname - local name=properties.name or tfmdata.name - local psname,psfixed=fixedpsname(psname,fontname or fullname or file.nameonly(filename)) - target.fontname=fontname - target.fullname=fullname - target.filename=filename - target.psname=psname - target.name=name - properties.fontname=fontname - properties.fullname=fullname - properties.filename=filename - properties.psname=psname - properties.name=name - local expansion=parameters.expansion - if expansion then - target.stretch=expansion.stretch - target.shrink=expansion.shrink - target.step=expansion.step - target.auto_expand=expansion.auto - end - local protrusion=parameters.protrusion - if protrusion then - target.auto_protrude=protrusion.auto - end - local extendfactor=parameters.extendfactor or 0 - if extendfactor~=0 and extendfactor~=1 then - hdelta=hdelta*extendfactor - target.extend=extendfactor*1000 - else - target.extend=1000 - end - local slantfactor=parameters.slantfactor or 0 - if slantfactor~=0 then - target.slant=slantfactor*1000 - else - target.slant=0 - end - targetparameters.factor=delta - targetparameters.hfactor=hdelta - targetparameters.vfactor=vdelta - targetparameters.size=scaledpoints - targetparameters.units=units - targetparameters.scaledpoints=askedscaledpoints - local isvirtual=properties.virtualized or tfmdata.type=="virtual" - local hasquality=target.auto_expand or target.auto_protrude - local hasitalics=properties.hasitalics - local autoitalicamount=properties.autoitalicamount - local stackmath=not properties.nostackmath - local nonames=properties.noglyphnames - local haskerns=properties.haskerns or properties.mode=="base" - local hasligatures=properties.hasligatures or properties.mode=="base" - local realdimensions=properties.realdimensions - local writingmode=properties.writingmode or "horizontal" - local identity=properties.identity or "horizontal" - if changed and not next(changed) then - changed=false - end - target.type=isvirtual and "virtual" or "real" - target.writingmode=writingmode=="vertical" and "vertical" or "horizontal" - target.identity=identity=="vertical" and "vertical" or "horizontal" - target.postprocessors=tfmdata.postprocessors - local targetslant=(parameters.slant or parameters[1] or 0)*factors.pt - local targetspace=(parameters.space or parameters[2] or 0)*hdelta - local targetspace_stretch=(parameters.space_stretch or parameters[3] or 0)*hdelta - local targetspace_shrink=(parameters.space_shrink or parameters[4] or 0)*hdelta - local targetx_height=(parameters.x_height or parameters[5] or 0)*vdelta - local targetquad=(parameters.quad or parameters[6] or 0)*hdelta - local targetextra_space=(parameters.extra_space or parameters[7] or 0)*hdelta - targetparameters.slant=targetslant - targetparameters.space=targetspace - targetparameters.space_stretch=targetspace_stretch - targetparameters.space_shrink=targetspace_shrink - targetparameters.x_height=targetx_height - targetparameters.quad=targetquad - targetparameters.extra_space=targetextra_space - local ascender=parameters.ascender - if ascender then - targetparameters.ascender=delta*ascender - end - local descender=parameters.descender - if descender then - targetparameters.descender=delta*descender - end - constructors.enhanceparameters(targetparameters) - local protrusionfactor=(targetquad~=0 and 1000/targetquad) or 0 - local scaledwidth=defaultwidth*hdelta - local scaledheight=defaultheight*vdelta - local scaleddepth=defaultdepth*vdelta - local hasmath=(properties.hasmath or next(mathparameters)) and true - if hasmath then - constructors.assignmathparameters(target,tfmdata) - properties.hasmath=true - target.nomath=false - target.MathConstants=target.mathparameters - else - properties.hasmath=false - target.nomath=true - target.mathparameters=nil - end - if hasmath then - local mathitalics=properties.mathitalics - if mathitalics==false then - if trace_defining then - report_defining("%s italics %s for font %a, fullname %a, filename %a","math",hasitalics and "ignored" or "disabled",name,fullname,filename) - end - hasitalics=false - autoitalicamount=false - end - else - local textitalics=properties.textitalics - if textitalics==false then - if trace_defining then - report_defining("%s italics %s for font %a, fullname %a, filename %a","text",hasitalics and "ignored" or "disabled",name,fullname,filename) - end - hasitalics=false - autoitalicamount=false - end - end - if trace_defining then - report_defining("defining tfm, name %a, fullname %a, filename %a, %spsname %a, hscale %a, vscale %a, math %a, italics %a", - name,fullname,filename,psfixed and "(fixed) " or "",psname,hdelta,vdelta, - hasmath and "enabled" or "disabled",hasitalics and "enabled" or "disabled") - end - constructors.beforecopyingcharacters(target,tfmdata) - local sharedkerns={} - for unicode,character in next,characters do - local chr,description,index - if changed then - local c=changed[unicode] - if c then - description=descriptions[c] or descriptions[unicode] or character - character=characters[c] or character - index=description.index or c - else - description=descriptions[unicode] or character - index=description.index or unicode - end - else - description=descriptions[unicode] or character - index=description.index or unicode - end - local width=description.width - local height=description.height - local depth=description.depth - if realdimensions then - if not height or height==0 then - local bb=description.boundingbox - local ht=bb[4] - if ht~=0 then - height=ht - end - if not depth or depth==0 then - local dp=-bb[2] - if dp~=0 then - depth=dp - end - end - elseif not depth or depth==0 then - local dp=-description.boundingbox[2] - if dp~=0 then - depth=dp - end - end - end - if width then width=hdelta*width else width=scaledwidth end - if height then height=vdelta*height else height=scaledheight end - if depth and depth~=0 then - depth=delta*depth - if nonames then - chr={ - index=index, - height=height, - depth=depth, - width=width, - } - else - chr={ - name=description.name, - index=index, - height=height, - depth=depth, - width=width, - } - end - else - if nonames then - chr={ - index=index, - height=height, - width=width, - } - else - chr={ - name=description.name, - index=index, - height=height, - width=width, - } - end - end - local isunicode=description.unicode - if isunicode then - chr.unicode=isunicode - chr.tounicode=tounicode(isunicode) - end - if hasquality then - local ve=character.expansion_factor - if ve then - chr.expansion_factor=ve*1000 - end - local vl=character.left_protruding - if vl then - chr.left_protruding=protrusionfactor*width*vl - end - local vr=character.right_protruding - if vr then - chr.right_protruding=protrusionfactor*width*vr - end - end - if hasmath then - local vn=character.next - if vn then - chr.next=vn - else - local vv=character.vert_variants - if vv then - local t={} - for i=1,#vv do - local vvi=vv[i] - t[i]={ - ["start"]=(vvi["start"] or 0)*vdelta, - ["end"]=(vvi["end"] or 0)*vdelta, - ["advance"]=(vvi["advance"] or 0)*vdelta, - ["extender"]=vvi["extender"], - ["glyph"]=vvi["glyph"], - } - end - chr.vert_variants=t - else - local hv=character.horiz_variants - if hv then - local t={} - for i=1,#hv do - local hvi=hv[i] - t[i]={ - ["start"]=(hvi["start"] or 0)*hdelta, - ["end"]=(hvi["end"] or 0)*hdelta, - ["advance"]=(hvi["advance"] or 0)*hdelta, - ["extender"]=hvi["extender"], - ["glyph"]=hvi["glyph"], - } - end - chr.horiz_variants=t - end - end - end - local vi=character.vert_italic - if vi and vi~=0 then - chr.vert_italic=vi*hdelta - end - local va=character.accent - if va then - chr.top_accent=vdelta*va - end - if stackmath then - local mk=character.mathkerns - if mk then - local tr,tl,br,bl=mk.topright,mk.topleft,mk.bottomright,mk.bottomleft - chr.mathkern={ - top_right=tr and mathkerns(tr,vdelta) or nil, - top_left=tl and mathkerns(tl,vdelta) or nil, - bottom_right=br and mathkerns(br,vdelta) or nil, - bottom_left=bl and mathkerns(bl,vdelta) or nil, - } - end - end - if hasitalics then - local vi=character.italic - if vi and vi~=0 then - chr.italic=vi*hdelta - end - end - elseif autoitalicamount then - local vi=description.italic - if not vi then - local bb=description.boundingbox - if bb then - local vi=bb[3]-description.width+autoitalicamount - if vi>0 then - chr.italic=vi*hdelta - end - else - end - elseif vi~=0 then - chr.italic=vi*hdelta - end - elseif hasitalics then - local vi=character.italic - if vi and vi~=0 then - chr.italic=vi*hdelta - end - end - if haskerns then - local vk=character.kerns - if vk then - local s=sharedkerns[vk] - if not s then - s={} - for k,v in next,vk do s[k]=v*hdelta end - sharedkerns[vk]=s - end - chr.kerns=s - end - end - if hasligatures then - local vl=character.ligatures - if vl then - if true then - chr.ligatures=vl - else - local tt={} - for i,l in next,vl do - tt[i]=l - end - chr.ligatures=tt - end - end - end - if isvirtual then - local vc=character.commands - if vc then - local ok=false - for i=1,#vc do - local key=vc[i][1] - if key=="right" or key=="down" then - ok=true - break - end - end - if ok then - local tt={} - for i=1,#vc do - local ivc=vc[i] - local key=ivc[1] - if key=="right" then - tt[i]={ key,ivc[2]*hdelta } - elseif key=="down" then - tt[i]={ key,ivc[2]*vdelta } - elseif key=="rule" then - tt[i]={ key,ivc[2]*vdelta,ivc[3]*hdelta } - else - tt[i]=ivc - end - end - chr.commands=tt - else - chr.commands=vc - end - chr.index=nil - end - end - targetcharacters[unicode]=chr - end - properties.setitalics=hasitalics - constructors.aftercopyingcharacters(target,tfmdata) - constructors.trytosharefont(target,tfmdata) - return target -end -function constructors.finalize(tfmdata) - if tfmdata.properties and tfmdata.properties.finalized then - return - end - if not tfmdata.characters then - return nil - end - if not tfmdata.goodies then - tfmdata.goodies={} - end - local parameters=tfmdata.parameters - if not parameters then - return nil - end - if not parameters.expansion then - parameters.expansion={ - stretch=tfmdata.stretch or 0, - shrink=tfmdata.shrink or 0, - step=tfmdata.step or 0, - auto=tfmdata.auto_expand or false, - } - end - if not parameters.protrusion then - parameters.protrusion={ - auto=auto_protrude - } - end - if not parameters.size then - parameters.size=tfmdata.size - end - if not parameters.extendfactor then - parameters.extendfactor=tfmdata.extend or 0 - end - if not parameters.slantfactor then - parameters.slantfactor=tfmdata.slant or 0 - end - local designsize=parameters.designsize - if designsize then - parameters.minsize=tfmdata.minsize or designsize - parameters.maxsize=tfmdata.maxsize or designsize - else - designsize=factors.pt*10 - parameters.designsize=designsize - parameters.minsize=designsize - parameters.maxsize=designsize - end - parameters.minsize=tfmdata.minsize or parameters.designsize - parameters.maxsize=tfmdata.maxsize or parameters.designsize - if not parameters.units then - parameters.units=tfmdata.units or tfmdata.units_per_em or 1000 - end - if not tfmdata.descriptions then - local descriptions={} - setmetatableindex(descriptions,function(t,k) local v={} t[k]=v return v end) - tfmdata.descriptions=descriptions - end - local properties=tfmdata.properties - if not properties then - properties={} - tfmdata.properties=properties - end - if not properties.virtualized then - properties.virtualized=tfmdata.type=="virtual" - end - if not tfmdata.properties then - tfmdata.properties={ - fontname=tfmdata.fontname, - filename=tfmdata.filename, - fullname=tfmdata.fullname, - name=tfmdata.name, - psname=tfmdata.psname, - encodingbytes=tfmdata.encodingbytes or 1, - embedding=tfmdata.embedding or "subset", - tounicode=tfmdata.tounicode or 1, - cidinfo=tfmdata.cidinfo or nil, - format=tfmdata.format or "type1", - direction=tfmdata.direction or 0, - writingmode=tfmdata.writingmode or "horizontal", - identity=tfmdata.identity or "horizontal", - } - end - if not tfmdata.resources then - tfmdata.resources={} - end - if not tfmdata.shared then - tfmdata.shared={} - end - if not properties.hasmath then - properties.hasmath=not tfmdata.nomath - end - tfmdata.MathConstants=nil - tfmdata.postprocessors=nil - tfmdata.fontname=nil - tfmdata.filename=nil - tfmdata.fullname=nil - tfmdata.name=nil - tfmdata.psname=nil - tfmdata.encodingbytes=nil - tfmdata.embedding=nil - tfmdata.tounicode=nil - tfmdata.cidinfo=nil - tfmdata.format=nil - tfmdata.direction=nil - tfmdata.type=nil - tfmdata.nomath=nil - tfmdata.designsize=nil - tfmdata.size=nil - tfmdata.stretch=nil - tfmdata.shrink=nil - tfmdata.step=nil - tfmdata.auto_expand=nil - tfmdata.auto_protrude=nil - tfmdata.extend=nil - tfmdata.slant=nil - tfmdata.units=nil - tfmdata.units_per_em=nil - tfmdata.cache=nil - properties.finalized=true - return tfmdata -end -local hashmethods={} -constructors.hashmethods=hashmethods -function constructors.hashfeatures(specification) - local features=specification.features - if features then - local t,tn={},0 - for category,list in next,features do - if next(list) then - local hasher=hashmethods[category] - if hasher then - local hash=hasher(list) - if hash then - tn=tn+1 - t[tn]=category..":"..hash - end - end - end - end - if tn>0 then - return concat(t," & ") - end - end - return "unknown" -end -hashmethods.normal=function(list) - local s={} - local n=0 - for k,v in next,list do - if not k then - elseif k=="number" or k=="features" then - else - n=n+1 - s[n]=k..'='..tostring(v) - end - end - if n>0 then - sort(s) - return concat(s,"+") - end -end -function constructors.hashinstance(specification,force) - local hash,size,fallbacks=specification.hash,specification.size,specification.fallbacks - if force or not hash then - hash=constructors.hashfeatures(specification) - specification.hash=hash - end - if size<1000 and designsizes[hash] then - size=math.round(constructors.scaled(size,designsizes[hash])) - specification.size=size - end - if fallbacks then - return hash..' @ '..tostring(size)..' @ '..fallbacks - else - return hash..' @ '..tostring(size) - end -end -function constructors.setname(tfmdata,specification) - if constructors.namemode=="specification" then - local specname=specification.specification - if specname then - tfmdata.properties.name=specname - if trace_defining then - report_otf("overloaded fontname %a",specname) - end - end - end -end -function constructors.checkedfilename(data) - local foundfilename=data.foundfilename - if not foundfilename then - local askedfilename=data.filename or "" - if askedfilename~="" then - askedfilename=resolvers.resolve(askedfilename) - foundfilename=resolvers.findbinfile(askedfilename,"") or "" - if foundfilename=="" then - report_defining("source file %a is not found",askedfilename) - foundfilename=resolvers.findbinfile(file.basename(askedfilename),"") or "" - if foundfilename~="" then - report_defining("using source file %a due to cache mismatch",foundfilename) - end - end - end - data.foundfilename=foundfilename - end - return foundfilename -end -local formats=allocate() -fonts.formats=formats -setmetatableindex(formats,function(t,k) - local l=lower(k) - if rawget(t,k) then - t[k]=l - return l - end - return rawget(t,file.suffix(l)) -end) -do - local function setindeed(mode,source,target,group,name,position) - local action=source[mode] - if not action then - return - end - local t=target[mode] - if not t then - report_defining("fatal error in setting feature %a, group %a, mode %a",name,group,mode) - os.exit() - elseif position then - insert(t,position,{ name=name,action=action }) - else - for i=1,#t do - local ti=t[i] - if ti.name==name then - ti.action=action - return - end - end - insert(t,{ name=name,action=action }) - end - end - local function set(group,name,target,source) - target=target[group] - if not target then - report_defining("fatal target error in setting feature %a, group %a",name,group) - os.exit() - end - local source=source[group] - if not source then - report_defining("fatal source error in setting feature %a, group %a",name,group) - os.exit() - end - local position=source.position - setindeed("node",source,target,group,name,position) - setindeed("base",source,target,group,name,position) - setindeed("plug",source,target,group,name,position) - end - local function register(where,specification) - local name=specification.name - if name and name~="" then - local default=specification.default - local description=specification.description - local initializers=specification.initializers - local processors=specification.processors - local manipulators=specification.manipulators - local modechecker=specification.modechecker - if default then - where.defaults[name]=default - end - if description and description~="" then - where.descriptions[name]=description - end - if initializers then - set('initializers',name,where,specification) - end - if processors then - set('processors',name,where,specification) - end - if manipulators then - set('manipulators',name,where,specification) - end - if modechecker then - where.modechecker=modechecker - end - end - end - constructors.registerfeature=register - function constructors.getfeatureaction(what,where,mode,name) - what=handlers[what].features - if what then - where=what[where] - if where then - mode=where[mode] - if mode then - for i=1,#mode do - local m=mode[i] - if m.name==name then - return m.action - end - end - end - end - end - end - local newfeatures={} - constructors.newfeatures=newfeatures - constructors.features=newfeatures - local function setnewfeatures(what) - local handler=handlers[what] - local features=handler.features - if not features then - local tables=handler.tables - local statistics=handler.statistics - features=allocate { - defaults={}, - descriptions=tables and tables.features or {}, - used=statistics and statistics.usedfeatures or {}, - initializers={ base={},node={},plug={} }, - processors={ base={},node={},plug={} }, - manipulators={ base={},node={},plug={} }, - } - features.register=function(specification) return register(features,specification) end - handler.features=features - end - return features - end - setmetatable(newfeatures,{ - __call=function(t,k) local v=t[k] return v end, - __index=function(t,k) local v=setnewfeatures(k) t[k]=v return v end, - }) -end -do - local newhandler={} - constructors.handlers=newhandler - constructors.newhandler=newhandler - local function setnewhandler(what) - local handler=handlers[what] - if not handler then - handler={} - handlers[what]=handler - end - return handler - end - setmetatable(newhandler,{ - __call=function(t,k) local v=t[k] return v end, - __index=function(t,k) local v=setnewhandler(k) t[k]=v return v end, - }) -end -do - local newenhancer={} - constructors.enhancers=newenhancer - constructors.newenhancer=newenhancer - local function setnewenhancer(format) - local handler=handlers[format] - local enhancers=handler.enhancers - if not enhancers then - local actions=allocate() - local before=allocate() - local after=allocate() - local order=allocate() - local patches={ before=before,after=after } - local trace=false - local report=logs.reporter("fonts",format.." enhancing") - trackers.register(format..".loading",function(v) trace=v end) - local function enhance(name,data,filename,raw) - local enhancer=actions[name] - if enhancer then - if trace then - report("apply enhancement %a to file %a",name,filename) - ioflush() - end - enhancer(data,filename,raw) - else - end - end - local function apply(data,filename,raw) - local basename=file.basename(lower(filename)) - if trace then - report("%s enhancing file %a","start",filename) - end - ioflush() - for e=1,#order do - local enhancer=order[e] - local b=before[enhancer] - if b then - for pattern,action in next,b do - if find(basename,pattern) then - action(data,filename,raw) - end - end - end - enhance(enhancer,data,filename,raw) - local a=after[enhancer] - if a then - for pattern,action in next,a do - if find(basename,pattern) then - action(data,filename,raw) - end - end - end - ioflush() - end - if trace then - report("%s enhancing file %a","stop",filename) - end - ioflush() - end - local function register(what,action) - if action then - if actions[what] then - else - order[#order+1]=what - end - actions[what]=action - else - report("bad enhancer %a",what) - end - end - local function patch(what,where,pattern,action) - local pw=patches[what] - if pw then - local ww=pw[where] - if ww then - ww[pattern]=action - else - pw[where]={ [pattern]=action} - end - end - end - enhancers={ - register=register, - apply=apply, - patch=patch, - patches={ register=patch }, - } - handler.enhancers=enhancers - end - return enhancers - end - setmetatable(newenhancer,{ - __call=function(t,k) local v=t[k] return v end, - __index=function(t,k) local v=setnewenhancer(k) t[k]=v return v end, - }) -end -function constructors.checkedfeatures(what,features) - local defaults=handlers[what].features.defaults - if features and next(features) then - features=fastcopy(features) - for key,value in next,defaults do - if features[key]==nil then - features[key]=value - end - end - return features - else - return fastcopy(defaults) - end -end -function constructors.initializefeatures(what,tfmdata,features,trace,report) - if features and next(features) then - local properties=tfmdata.properties or {} - local whathandler=handlers[what] - local whatfeatures=whathandler.features - local whatmodechecker=whatfeatures.modechecker - local mode=properties.mode or (whatmodechecker and whatmodechecker(tfmdata,features,features.mode)) or features.mode or "base" - properties.mode=mode - features.mode=mode - local done={} - while true do - local redo=false - local initializers=whatfeatures.initializers[mode] - if initializers then - for i=1,#initializers do - local step=initializers[i] - local feature=step.name - local value=features[feature] - if not value then - elseif done[feature] then - else - local action=step.action - if trace then - report("initializing feature %a to %a for mode %a for font %a",feature, - value,mode,tfmdata.properties.fullname) - end - action(tfmdata,value,features) - if mode~=properties.mode or mode~=features.mode then - if whatmodechecker then - properties.mode=whatmodechecker(tfmdata,features,properties.mode) - features.mode=properties.mode - end - if mode~=properties.mode then - mode=properties.mode - redo=true - end - end - done[feature]=true - end - if redo then - break - end - end - if not redo then - break - end - else - break - end - end - properties.mode=mode - return true - else - return false - end -end -function constructors.collectprocessors(what,tfmdata,features,trace,report) - local processes,nofprocesses={},0 - if features and next(features) then - local properties=tfmdata.properties - local whathandler=handlers[what] - local whatfeatures=whathandler.features - local whatprocessors=whatfeatures.processors - local mode=properties.mode - local processors=whatprocessors[mode] - if processors then - for i=1,#processors do - local step=processors[i] - local feature=step.name - if features[feature] then - local action=step.action - if trace then - report("installing feature processor %a for mode %a for font %a",feature,mode,tfmdata.properties.fullname) - end - if action then - nofprocesses=nofprocesses+1 - processes[nofprocesses]=action - end - end - end - elseif trace then - report("no feature processors for mode %a for font %a",mode,properties.fullname) - end - end - return processes -end -function constructors.applymanipulators(what,tfmdata,features,trace,report) - if features and next(features) then - local properties=tfmdata.properties - local whathandler=handlers[what] - local whatfeatures=whathandler.features - local whatmanipulators=whatfeatures.manipulators - local mode=properties.mode - local manipulators=whatmanipulators[mode] - if manipulators then - for i=1,#manipulators do - local step=manipulators[i] - local feature=step.name - local value=features[feature] - if value then - local action=step.action - if trace then - report("applying feature manipulator %a for mode %a for font %a",feature,mode,properties.fullname) - end - if action then - action(tfmdata,feature,value) - end - end - end - end - end -end -function constructors.addcoreunicodes(unicodes) - if not unicodes then - unicodes={} - end - unicodes.space=0x0020 - unicodes.hyphen=0x002D - unicodes.zwj=0x200D - unicodes.zwnj=0x200C - return unicodes -end - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['luatex-font-enc']={ - version=1.001, - comment="companion to luatex-*.tex", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -if context then - texio.write_nl("fatal error: this module is not for context") - os.exit() -end -local fonts=fonts -local encodings={} -fonts.encodings=encodings -encodings.agl={} -encodings.known={} -setmetatable(encodings.agl,{ __index=function(t,k) - if k=="unicodes" then - texio.write(" <loading (extended) adobe glyph list>") - local unicodes=dofile(resolvers.findfile("font-age.lua")) - encodings.agl={ unicodes=unicodes } - return unicodes - else - return nil - end -end }) -encodings.cache=containers.define("fonts","enc",encodings.version,true) -function encodings.load(filename) - local name=file.removesuffix(filename) - local data=containers.read(encodings.cache,name) - if data then - return data - end - local vector,tag,hash,unicodes={},"",{},{} - local foundname=resolvers.findfile(filename,'enc') - if foundname and foundname~="" then - local ok,encoding,size=resolvers.loadbinfile(foundname) - if ok and encoding then - encoding=string.gsub(encoding,"%%(.-)\n","") - local unicoding=encodings.agl.unicodes - local tag,vec=string.match(encoding,"/(%w+)%s*%[(.*)%]%s*def") - local i=0 - for ch in string.gmatch(vec,"/([%a%d%.]+)") do - if ch~=".notdef" then - vector[i]=ch - if not hash[ch] then - hash[ch]=i - else - end - local u=unicoding[ch] - if u then - unicodes[u]=i - end - end - i=i+1 - end - end - end - local data={ - name=name, - tag=tag, - vector=vector, - hash=hash, - unicodes=unicodes - } - return containers.write(encodings.cache,name,data) -end - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['font-cid']={ - version=1.001, - comment="companion to font-otf.lua (cidmaps)", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local format,match,lower=string.format,string.match,string.lower -local tonumber=tonumber -local P,S,R,C,V,lpegmatch=lpeg.P,lpeg.S,lpeg.R,lpeg.C,lpeg.V,lpeg.match -local fonts,logs,trackers=fonts,logs,trackers -local trace_loading=false trackers.register("otf.loading",function(v) trace_loading=v end) -local report_otf=logs.reporter("fonts","otf loading") -local cid={} -fonts.cid=cid -local cidmap={} -local cidmax=10 -local number=C(R("09","af","AF")^1) -local space=S(" \n\r\t") -local spaces=space^0 -local period=P(".") -local periods=period*period -local name=P("/")*C((1-space)^1) -local unicodes,names={},{} -local function do_one(a,b) - unicodes[tonumber(a)]=tonumber(b,16) -end -local function do_range(a,b,c) - c=tonumber(c,16) - for i=tonumber(a),tonumber(b) do - unicodes[i]=c - c=c+1 - end -end -local function do_name(a,b) - names[tonumber(a)]=b -end -local grammar=P { "start", - start=number*spaces*number*V("series"), - series=(spaces*(V("one")+V("range")+V("named")))^1, - one=(number*spaces*number)/do_one, - range=(number*periods*number*spaces*number)/do_range, - named=(number*spaces*name)/do_name -} -local function loadcidfile(filename) - local data=io.loaddata(filename) - if data then - unicodes,names={},{} - lpegmatch(grammar,data) - local supplement,registry,ordering=match(filename,"^(.-)%-(.-)%-()%.(.-)$") - return { - supplement=supplement, - registry=registry, - ordering=ordering, - filename=filename, - unicodes=unicodes, - names=names, - } - end -end -cid.loadfile=loadcidfile -local template="%s-%s-%s.cidmap" -local function locate(registry,ordering,supplement) - local filename=format(template,registry,ordering,supplement) - local hashname=lower(filename) - local found=cidmap[hashname] - if not found then - if trace_loading then - report_otf("checking cidmap, registry %a, ordering %a, supplement %a, filename %a",registry,ordering,supplement,filename) - end - local fullname=resolvers.findfile(filename,'cid') or "" - if fullname~="" then - found=loadcidfile(fullname) - if found then - if trace_loading then - report_otf("using cidmap file %a",filename) - end - cidmap[hashname]=found - found.usedname=file.basename(filename) - end - end - end - return found -end -function cid.getmap(specification) - if not specification then - report_otf("invalid cidinfo specification, table expected") - return - end - local registry=specification.registry - local ordering=specification.ordering - local supplement=specification.supplement - local filename=format(registry,ordering,supplement) - local lowername=lower(filename) - local found=cidmap[lowername] - if found then - return found - end - if ordering=="Identity" then - local found={ - supplement=supplement, - registry=registry, - ordering=ordering, - filename=filename, - unicodes={}, - names={}, - } - cidmap[lowername]=found - return found - end - if trace_loading then - report_otf("cidmap needed, registry %a, ordering %a, supplement %a",registry,ordering,supplement) - end - found=locate(registry,ordering,supplement) - if not found then - local supnum=tonumber(supplement) - local cidnum=nil - if supnum<cidmax then - for s=supnum+1,cidmax do - local c=locate(registry,ordering,s) - if c then - found,cidnum=c,s - break - end - end - end - if not found and supnum>0 then - for s=supnum-1,0,-1 do - local c=locate(registry,ordering,s) - if c then - found,cidnum=c,s - break - end - end - end - registry=lower(registry) - ordering=lower(ordering) - if found and cidnum>0 then - for s=0,cidnum-1 do - local filename=format(template,registry,ordering,s) - if not cidmap[filename] then - cidmap[filename]=found - end - end - end - end - return found -end - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['font-map']={ - version=1.001, - comment="companion to font-ini.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local tonumber,next,type=tonumber,next,type -local match,format,find,concat,gsub,lower=string.match,string.format,string.find,table.concat,string.gsub,string.lower -local P,R,S,C,Ct,Cc,lpegmatch=lpeg.P,lpeg.R,lpeg.S,lpeg.C,lpeg.Ct,lpeg.Cc,lpeg.match -local floor=math.floor -local formatters=string.formatters -local sortedhash,sortedkeys=table.sortedhash,table.sortedkeys -local trace_loading=false trackers.register("fonts.loading",function(v) trace_loading=v end) -local trace_mapping=false trackers.register("fonts.mapping",function(v) trace_mapping=v end) -local report_fonts=logs.reporter("fonts","loading") -local force_ligatures=false directives.register("fonts.mapping.forceligatures",function(v) force_ligatures=v end) -local fonts=fonts or {} -local mappings=fonts.mappings or {} -fonts.mappings=mappings -local allocate=utilities.storage.allocate -local hex=R("AF","af","09") -local hexfour=(hex*hex*hex^-2)/function(s) return tonumber(s,16) end -local hexsix=(hex*hex*hex^-4)/function(s) return tonumber(s,16) end -local dec=(R("09")^1)/tonumber -local period=P(".") -local unicode=(P("uni")+P("UNI"))*(hexfour*(period+P(-1))*Cc(false)+Ct(hexfour^1)*Cc(true)) -local ucode=(P("u")+P("U") )*(hexsix*(period+P(-1))*Cc(false)+Ct(hexsix^1)*Cc(true)) -local index=P("index")*dec*Cc(false) -local parser=unicode+ucode+index -local parsers={} -local function makenameparser(str) - if not str or str=="" then - return parser - else - local p=parsers[str] - if not p then - p=P(str)*period*dec*Cc(false) - parsers[str]=p - end - return p - end -end -local f_single=formatters["%04X"] -local f_double=formatters["%04X%04X"] -local function tounicode16(unicode) - if unicode<0xD7FF or (unicode>0xDFFF and unicode<=0xFFFF) then - return f_single(unicode) - else - unicode=unicode-0x10000 - return f_double(floor(unicode/1024)+0xD800,unicode%1024+0xDC00) - end -end -local function tounicode16sequence(unicodes) - local t={} - for l=1,#unicodes do - local u=unicodes[l] - if u<0xD7FF or (u>0xDFFF and u<=0xFFFF) then - t[l]=f_single(u) - else - u=u-0x10000 - t[l]=f_double(floor(u/1024)+0xD800,u%1024+0xDC00) - end - end - return concat(t) -end -local function tounicode(unicode,name) - if type(unicode)=="table" then - local t={} - for l=1,#unicode do - local u=unicode[l] - if u<0xD7FF or (u>0xDFFF and u<=0xFFFF) then - t[l]=f_single(u) - else - u=u-0x10000 - t[l]=f_double(floor(u/1024)+0xD800,u%1024+0xDC00) - end - end - return concat(t) - else - if unicode<0xD7FF or (unicode>0xDFFF and unicode<=0xFFFF) then - return f_single(unicode) - else - unicode=unicode-0x10000 - return f_double(floor(unicode/1024)+0xD800,unicode%1024+0xDC00) - end - end -end -local function fromunicode16(str) - if #str==4 then - return tonumber(str,16) - else - local l,r=match(str,"(....)(....)") - return 0x10000+(tonumber(l,16)-0xD800)*0x400+tonumber(r,16)-0xDC00 - end -end -mappings.makenameparser=makenameparser -mappings.tounicode=tounicode -mappings.tounicode16=tounicode16 -mappings.tounicode16sequence=tounicode16sequence -mappings.fromunicode16=fromunicode16 -local ligseparator=P("_") -local varseparator=P(".") -local namesplitter=Ct(C((1-ligseparator-varseparator)^1)*(ligseparator*C((1-ligseparator-varseparator)^1))^0) -do - local overloads=allocate { - IJ={ name="I_J",unicode={ 0x49,0x4A },mess=0x0132 }, - ij={ name="i_j",unicode={ 0x69,0x6A },mess=0x0133 }, - ff={ name="f_f",unicode={ 0x66,0x66 },mess=0xFB00 }, - fi={ name="f_i",unicode={ 0x66,0x69 },mess=0xFB01 }, - fl={ name="f_l",unicode={ 0x66,0x6C },mess=0xFB02 }, - ffi={ name="f_f_i",unicode={ 0x66,0x66,0x69 },mess=0xFB03 }, - ffl={ name="f_f_l",unicode={ 0x66,0x66,0x6C },mess=0xFB04 }, - fj={ name="f_j",unicode={ 0x66,0x6A } }, - fk={ name="f_k",unicode={ 0x66,0x6B } }, - } - local o={} - for k,v in next,overloads do - local name=v.name - local mess=v.mess - if name then - o[name]=v - end - if mess then - o[mess]=v - end - o[k]=v - end - mappings.overloads=o -end -function mappings.addtounicode(data,filename,checklookups) - local resources=data.resources - local unicodes=resources.unicodes - if not unicodes then - if trace_mapping then - report_fonts("no unicode list, quitting tounicode for %a",filename) - end - return - end - local properties=data.properties - local descriptions=data.descriptions - local overloads=mappings.overloads - unicodes['space']=unicodes['space'] or 32 - unicodes['hyphen']=unicodes['hyphen'] or 45 - unicodes['zwj']=unicodes['zwj'] or 0x200D - unicodes['zwnj']=unicodes['zwnj'] or 0x200C - local private=fonts.constructors and fonts.constructors.privateoffset or 0xF0000 - local unicodevector=fonts.encodings.agl.unicodes or {} - local contextvector=fonts.encodings.agl.ctxcodes or {} - local missing={} - local nofmissing=0 - local oparser=nil - local cidnames=nil - local cidcodes=nil - local cidinfo=properties.cidinfo - local usedmap=cidinfo and fonts.cid.getmap(cidinfo) - local uparser=makenameparser() - if usedmap then - oparser=usedmap and makenameparser(cidinfo.ordering) - cidnames=usedmap.names - cidcodes=usedmap.unicodes - end - local ns=0 - local nl=0 - local dlist=sortedkeys(descriptions) - for i=1,#dlist do - local du=dlist[i] - local glyph=descriptions[du] - local name=glyph.name - if name then - local overload=overloads[name] or overloads[du] - if overload then - glyph.unicode=overload.unicode - else - local gu=glyph.unicode - if not gu or gu==-1 or du>=private or (du>=0xE000 and du<=0xF8FF) or du==0xFFFE or du==0xFFFF then - local unicode=unicodevector[name] or contextvector[name] - if unicode then - glyph.unicode=unicode - ns=ns+1 - end - if (not unicode) and usedmap then - local foundindex=lpegmatch(oparser,name) - if foundindex then - unicode=cidcodes[foundindex] - if unicode then - glyph.unicode=unicode - ns=ns+1 - else - local reference=cidnames[foundindex] - if reference then - local foundindex=lpegmatch(oparser,reference) - if foundindex then - unicode=cidcodes[foundindex] - if unicode then - glyph.unicode=unicode - ns=ns+1 - end - end - if not unicode or unicode=="" then - local foundcodes,multiple=lpegmatch(uparser,reference) - if foundcodes then - glyph.unicode=foundcodes - if multiple then - nl=nl+1 - unicode=true - else - ns=ns+1 - unicode=foundcodes - end - end - end - end - end - end - end - if not unicode or unicode=="" then - local split=lpegmatch(namesplitter,name) - local nsplit=split and #split or 0 - if nsplit==0 then - elseif nsplit==1 then - local base=split[1] - local u=unicodes[base] or unicodevector[base] or contextvector[name] - if not u then - elseif type(u)=="table" then - if u[1]<private then - unicode=u - glyph.unicode=unicode - end - elseif u<private then - unicode=u - glyph.unicode=unicode - end - else - local t,n={},0 - for l=1,nsplit do - local base=split[l] - local u=unicodes[base] or unicodevector[base] or contextvector[name] - if not u then - break - elseif type(u)=="table" then - if u[1]>=private then - break - end - n=n+1 - t[n]=u[1] - else - if u>=private then - break - end - n=n+1 - t[n]=u - end - end - if n>0 then - if n==1 then - unicode=t[1] - else - unicode=t - end - glyph.unicode=unicode - end - end - nl=nl+1 - end - if not unicode or unicode=="" then - local foundcodes,multiple=lpegmatch(uparser,name) - if foundcodes then - glyph.unicode=foundcodes - if multiple then - nl=nl+1 - unicode=true - else - ns=ns+1 - unicode=foundcodes - end - end - end - local r=overloads[unicode] - if r then - unicode=r.unicode - glyph.unicode=unicode - end - if not unicode then - missing[du]=true - nofmissing=nofmissing+1 - end - end - end - else - local overload=overloads[du] - if overload then - glyph.unicode=overload.unicode - end - end - end - if type(checklookups)=="function" then - checklookups(data,missing,nofmissing) - end - local collected=false - local unicoded=0 - for i=1,#dlist do - local du=dlist[i] - local glyph=descriptions[du] - if glyph.class=="ligature" and (force_ligatures or not glyph.unicode) then - if not collected then - collected=fonts.handlers.otf.readers.getcomponents(data) - if not collected then - break - end - end - local u=collected[du] - if u then - local n=#u - for i=1,n do - if u[i]>private then - n=0 - break - end - end - if n>0 then - if n>1 then - glyph.unicode=u - else - glyph.unicode=u[1] - end - unicoded=unicoded+1 - end - end - end - end - if trace_mapping and unicoded>0 then - report_fonts("%n ligature tounicode mappings deduced from gsub ligature features",unicoded) - end - if trace_mapping then - for i=1,#dlist do - local du=dlist[i] - local glyph=descriptions[du] - local name=glyph.name or "-" - local index=glyph.index or 0 - local unicode=glyph.unicode - if unicode then - if type(unicode)=="table" then - local unicodes={} - for i=1,#unicode do - unicodes[i]=formatters("%U",unicode[i]) - end - report_fonts("internal slot %U, name %a, unicode %U, tounicode % t",index,name,du,unicodes) - else - report_fonts("internal slot %U, name %a, unicode %U, tounicode %U",index,name,du,unicode) - end - else - report_fonts("internal slot %U, name %a, unicode %U",index,name,du) - end - end - end - if trace_loading and (ns>0 or nl>0) then - report_fonts("%s tounicode entries added, ligatures %s",nl+ns,ns) - end -end - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['luatex-fonts-syn']={ - version=1.001, - comment="companion to luatex-*.tex", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -if context then - texio.write_nl("fatal error: this module is not for context") - os.exit() -end -local fonts=fonts -fonts.names=fonts.names or {} -fonts.names.version=1.001 -fonts.names.basename="luatex-fonts-names" -fonts.names.cache=containers.define("fonts","data",fonts.names.version,true) -local data=nil -local loaded=false -local fileformats={ "lua","tex","other text files" } -function fonts.names.reportmissingbase() - texio.write("<missing font database, run: mtxrun --script fonts --reload --simple>") - fonts.names.reportmissingbase=nil -end -function fonts.names.reportmissingname() - texio.write("<unknown font in database, run: mtxrun --script fonts --reload --simple>") - fonts.names.reportmissingname=nil -end -function fonts.names.resolve(name,sub) - if not loaded then - local basename=fonts.names.basename - if basename and basename~="" then - data=containers.read(fonts.names.cache,basename) - if not data then - basename=file.addsuffix(basename,"lua") - for i=1,#fileformats do - local format=fileformats[i] - local foundname=resolvers.findfile(basename,format) or "" - if foundname~="" then - data=dofile(foundname) - texio.write("<font database loaded: ",foundname,">") - break - end - end - end - end - loaded=true - end - if type(data)=="table" and data.version==fonts.names.version then - local condensed=string.gsub(string.lower(name),"[^%a%d]","") - local found=data.mappings and data.mappings[condensed] - if found then - local fontname,filename,subfont=found[1],found[2],found[3] - if subfont then - return filename,fontname - else - return filename,false - end - elseif fonts.names.reportmissingname then - fonts.names.reportmissingname() - return name,false - end - elseif fonts.names.reportmissingbase then - fonts.names.reportmissingbase() - end -end -fonts.names.resolvespec=fonts.names.resolve -function fonts.names.getfilename(askedname,suffix) - return "" -end -function fonts.names.ignoredfile(filename) - return false -end - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['font-oti']={ - version=1.001, - comment="companion to font-ini.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local lower=string.lower -local fonts=fonts -local constructors=fonts.constructors -local otf=constructors.handlers.otf -local otffeatures=constructors.features.otf -local registerotffeature=otffeatures.register -local otftables=otf.tables or {} -otf.tables=otftables -local allocate=utilities.storage.allocate -registerotffeature { - name="features", - description="initialization of feature handler", - default=true, -} -local function setmode(tfmdata,value) - if value then - tfmdata.properties.mode=lower(value) - end -end -otf.modeinitializer=setmode -local function setlanguage(tfmdata,value) - if value then - local cleanvalue=lower(value) - local languages=otftables and otftables.languages - local properties=tfmdata.properties - if not languages then - properties.language=cleanvalue - elseif languages[value] then - properties.language=cleanvalue - else - properties.language="dflt" - end - end -end -local function setscript(tfmdata,value) - if value then - local cleanvalue=lower(value) - local scripts=otftables and otftables.scripts - local properties=tfmdata.properties - if not scripts then - properties.script=cleanvalue - elseif scripts[value] then - properties.script=cleanvalue - else - properties.script="dflt" - end - end -end -registerotffeature { - name="mode", - description="mode", - initializers={ - base=setmode, - node=setmode, - plug=setmode, - } -} -registerotffeature { - name="language", - description="language", - initializers={ - base=setlanguage, - node=setlanguage, - plug=setlanguage, - } -} -registerotffeature { - name="script", - description="script", - initializers={ - base=setscript, - node=setscript, - plug=setscript, - } -} -otftables.featuretypes=allocate { - gpos_single="position", - gpos_pair="position", - gpos_cursive="position", - gpos_mark2base="position", - gpos_mark2ligature="position", - gpos_mark2mark="position", - gpos_context="position", - gpos_contextchain="position", - gsub_single="substitution", - gsub_multiple="substitution", - gsub_alternate="substitution", - gsub_ligature="substitution", - gsub_context="substitution", - gsub_contextchain="substitution", - gsub_reversecontextchain="substitution", - gsub_reversesub="substitution", -} -function otffeatures.checkeddefaultscript(featuretype,autoscript,scripts) - if featuretype=="position" then - local default=scripts.dflt - if default then - if autoscript=="position" or autoscript==true then - return default - else - report_otf("script feature %s not applied, enable default positioning") - end - else - end - elseif featuretype=="substitution" then - local default=scripts.dflt - if default then - if autoscript=="substitution" or autoscript==true then - return default - end - end - end -end -function otffeatures.checkeddefaultlanguage(featuretype,autolanguage,languages) - if featuretype=="position" then - local default=languages.dflt - if default then - if autolanguage=="position" or autolanguage==true then - return default - else - report_otf("language feature %s not applied, enable default positioning") - end - else - end - elseif featuretype=="substitution" then - local default=languages.dflt - if default then - if autolanguage=="substitution" or autolanguage==true then - return default - end - end - end -end - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['font-otr']={ - version=1.001, - comment="companion to font-ini.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local next,type,unpack=next,type,unpack -local byte,lower,char,strip,gsub=string.byte,string.lower,string.char,string.strip,string.gsub -local bittest=bit32.btest -local concat,remove,unpack,fastcopy=table.concat,table.remov,table.unpack,table.fastcopy -local floor,abs,sqrt,round=math.floor,math.abs,math.sqrt,math.round -local P,R,S,C,Cs,Cc,Ct,Carg,Cmt=lpeg.P,lpeg.R,lpeg.S,lpeg.C,lpeg.Cs,lpeg.Cc,lpeg.Ct,lpeg.Carg,lpeg.Cmt -local lpegmatch=lpeg.match -local setmetatableindex=table.setmetatableindex -local formatters=string.formatters -local sortedkeys=table.sortedkeys -local sortedhash=table.sortedhash -local stripstring=string.strip -local utf16_to_utf8_be=utf.utf16_to_utf8_be -local report=logs.reporter("otf reader") -local trace_cmap=false -fonts=fonts or {} -local handlers=fonts.handlers or {} -fonts.handlers=handlers -local otf=handlers.otf or {} -handlers.otf=otf -local readers=otf.readers or {} -otf.readers=readers -local streamreader=utilities.files -local streamwriter=utilities.files -readers.streamreader=streamreader -readers.streamwriter=streamwriter -local openfile=streamreader.open -local closefile=streamreader.close -local setposition=streamreader.setposition -local skipshort=streamreader.skipshort -local readbytes=streamreader.readbytes -local readstring=streamreader.readstring -local readbyte=streamreader.readcardinal1 -local readushort=streamreader.readcardinal2 -local readuint=streamreader.readcardinal3 -local readulong=streamreader.readcardinal4 -local readshort=streamreader.readinteger2 -local readlong=streamreader.readinteger4 -local readfixed=streamreader.readfixed4 -local readfword=readshort -local readufword=readushort -local readoffset=readushort -local read2dot14=streamreader.read2dot14 -function streamreader.readtag(f) - return lower(strip(readstring(f,4))) -end -local function readlongdatetime(f) - local a,b,c,d,e,f,g,h=readbytes(f,8) - return 0x100000000*d+0x1000000*e+0x10000*f+0x100*g+h -end -local tableversion=0.004 -readers.tableversion=tableversion -local privateoffset=fonts.constructors and fonts.constructors.privateoffset or 0xF0000 -local reportedskipped={} -local function reportskippedtable(tag) - if not reportedskipped[tag] then - report("loading of table %a skipped (reported once only)",tag) - reportedskipped[tag]=true - end -end -local reservednames={ [0]="copyright", - "family", - "subfamily", - "uniqueid", - "fullname", - "version", - "postscriptname", - "trademark", - "manufacturer", - "designer", - "description", - "vendorurl", - "designerurl", - "license", - "licenseurl", - "reserved", - "typographicfamily", - "typographicsubfamily", - "compatiblefullname", - "sampletext", - "cidfindfontname", - "wwsfamily", - "wwssubfamily", - "lightbackgroundpalette", - "darkbackgroundpalette", -} -local platforms={ [0]="unicode", - "macintosh", - "iso", - "windows", - "custom", -} -local encodings={ - unicode={ [0]="unicode 1.0 semantics", - "unicode 1.1 semantics", - "iso/iec 10646", - "unicode 2.0 bmp", - "unicode 2.0 full", - "unicode variation sequences", - "unicode full repertoire", - }, - macintosh={ [0]="roman","japanese","chinese (traditional)","korean","arabic","hebrew","greek","russian", - "rsymbol","devanagari","gurmukhi","gujarati","oriya","bengali","tamil","telugu","kannada", - "malayalam","sinhalese","burmese","khmer","thai","laotian","georgian","armenian", - "chinese (simplified)","tibetan","mongolian","geez","slavic","vietnamese","sindhi", - "uninterpreted", - }, - iso={ [0]="7-bit ascii", - "iso 10646", - "iso 8859-1", - }, - windows={ [0]="symbol", - "unicode bmp", - "shiftjis", - "prc", - "big5", - "wansung", - "johab", - "reserved 7", - "reserved 8", - "reserved 9", - "unicode ucs-4", - }, - custom={ - } -} -local decoders={ - unicode={}, - macintosh={}, - iso={}, - windows={ - ["unicode semantics"]=utf16_to_utf8_be, - ["unicode bmp"]=utf16_to_utf8_be, - ["unicode full"]=utf16_to_utf8_be, - ["unicode 1.0 semantics"]=utf16_to_utf8_be, - ["unicode 1.1 semantics"]=utf16_to_utf8_be, - ["unicode 2.0 bmp"]=utf16_to_utf8_be, - ["unicode 2.0 full"]=utf16_to_utf8_be, - ["unicode variation sequences"]=utf16_to_utf8_be, - ["unicode full repertoire"]=utf16_to_utf8_be, - }, - custom={}, -} -local languages={ - unicode={ - [ 0]="english", - }, - macintosh={ - [ 0]="english", - }, - iso={}, - windows={ - [0x0409]="english - united states", - }, - custom={}, -} -local standardromanencoding={ [0]= - "notdef",".null","nonmarkingreturn","space","exclam","quotedbl", - "numbersign","dollar","percent","ampersand","quotesingle","parenleft", - "parenright","asterisk","plus","comma","hyphen","period","slash", - "zero","one","two","three","four","five","six","seven","eight", - "nine","colon","semicolon","less","equal","greater","question","at", - "A","B","C","D","E","F","G","H","I","J","K","L","M","N","O", - "P","Q","R","S","T","U","V","W","X","Y","Z","bracketleft", - "backslash","bracketright","asciicircum","underscore","grave","a","b", - "c","d","e","f","g","h","i","j","k","l","m","n","o","p","q", - "r","s","t","u","v","w","x","y","z","braceleft","bar", - "braceright","asciitilde","Adieresis","Aring","Ccedilla","Eacute", - "Ntilde","Odieresis","Udieresis","aacute","agrave","acircumflex", - "adieresis","atilde","aring","ccedilla","eacute","egrave", - "ecircumflex","edieresis","iacute","igrave","icircumflex","idieresis", - "ntilde","oacute","ograve","ocircumflex","odieresis","otilde","uacute", - "ugrave","ucircumflex","udieresis","dagger","degree","cent","sterling", - "section","bullet","paragraph","germandbls","registered","copyright", - "trademark","acute","dieresis","notequal","AE","Oslash","infinity", - "plusminus","lessequal","greaterequal","yen","mu","partialdiff", - "summation","product","pi","integral","ordfeminine","ordmasculine", - "Omega","ae","oslash","questiondown","exclamdown","logicalnot", - "radical","florin","approxequal","Delta","guillemotleft", - "guillemotright","ellipsis","nonbreakingspace","Agrave","Atilde", - "Otilde","OE","oe","endash","emdash","quotedblleft","quotedblright", - "quoteleft","quoteright","divide","lozenge","ydieresis","Ydieresis", - "fraction","currency","guilsinglleft","guilsinglright","fi","fl", - "daggerdbl","periodcentered","quotesinglbase","quotedblbase", - "perthousand","Acircumflex","Ecircumflex","Aacute","Edieresis","Egrave", - "Iacute","Icircumflex","Idieresis","Igrave","Oacute","Ocircumflex", - "apple","Ograve","Uacute","Ucircumflex","Ugrave","dotlessi", - "circumflex","tilde","macron","breve","dotaccent","ring","cedilla", - "hungarumlaut","ogonek","caron","Lslash","lslash","Scaron","scaron", - "Zcaron","zcaron","brokenbar","Eth","eth","Yacute","yacute","Thorn", - "thorn","minus","multiply","onesuperior","twosuperior","threesuperior", - "onehalf","onequarter","threequarters","franc","Gbreve","gbreve", - "Idotaccent","Scedilla","scedilla","Cacute","cacute","Ccaron","ccaron", - "dcroat", -} -local weights={ - [100]="thin", - [200]="extralight", - [300]="light", - [400]="normal", - [500]="medium", - [600]="semibold", - [700]="bold", - [800]="extrabold", - [900]="black", -} -local widths={ - [1]="ultracondensed", - [2]="extracondensed", - [3]="condensed", - [4]="semicondensed", - [5]="normal", - [6]="semiexpanded", - [7]="expanded", - [8]="extraexpanded", - [9]="ultraexpanded", -} -setmetatableindex(weights,function(t,k) - local r=floor((k+50)/100)*100 - local v=(r>900 and "black") or rawget(t,r) or "normal" - return v -end) -setmetatableindex(widths,function(t,k) - return "normal" -end) -local panoseweights={ - [ 0]="normal", - [ 1]="normal", - [ 2]="verylight", - [ 3]="light", - [ 4]="thin", - [ 5]="book", - [ 6]="medium", - [ 7]="demi", - [ 8]="bold", - [ 9]="heavy", - [10]="black", -} -local panosewidths={ - [ 0]="normal", - [ 1]="normal", - [ 2]="normal", - [ 3]="normal", - [ 4]="normal", - [ 5]="expanded", - [ 6]="condensed", - [ 7]="veryexpanded", - [ 8]="verycondensed", - [ 9]="monospaced", -} -local platformnames={ - postscriptname=true, - fullname=true, - family=true, - subfamily=true, - typographicfamily=true, - typographicsubfamily=true, - compatiblefullname=true, -} -function readers.name(f,fontdata,specification) - local datatable=fontdata.tables.name - if datatable then - setposition(f,datatable.offset) - local format=readushort(f) - local nofnames=readushort(f) - local offset=readushort(f) - local start=datatable.offset+offset - local namelists={ - unicode={}, - windows={}, - macintosh={}, - } - for i=1,nofnames do - local platform=platforms[readushort(f)] - if platform then - local namelist=namelists[platform] - if namelist then - local encoding=readushort(f) - local language=readushort(f) - local encodings=encodings[platform] - local languages=languages[platform] - if encodings and languages then - local encoding=encodings[encoding] - local language=languages[language] - if encoding and language then - local name=reservednames[readushort(f)] - if name then - namelist[#namelist+1]={ - platform=platform, - encoding=encoding, - language=language, - name=name, - length=readushort(f), - offset=start+readushort(f), - } - else - skipshort(f,2) - end - else - skipshort(f,3) - end - else - skipshort(f,3) - end - else - skipshort(f,5) - end - else - skipshort(f,5) - end - end - local names={} - local done={} - local function filter(platform,e,l) - local namelist=namelists[platform] - for i=1,#namelist do - local name=namelist[i] - local nametag=name.name - if not done[nametag] then - local encoding=name.encoding - local language=name.language - if (not e or encoding==e) and (not l or language==l) then - setposition(f,name.offset) - local content=readstring(f,name.length) - local decoder=decoders[platform] - if decoder then - decoder=decoder[encoding] - end - if decoder then - content=decoder(content) - end - names[nametag]={ - content=content, - platform=platform, - encoding=encoding, - language=language, - } - done[nametag]=true - end - end - end - end - filter("windows","unicode bmp","english - united states") - filter("macintosh","roman","english") - filter("windows") - filter("macintosh") - filter("unicode") - fontdata.names=names - if specification.platformnames then - local collected={} - for platform,namelist in next,namelists do - local filtered=false - for i=1,#namelist do - local entry=namelist[i] - local name=entry.name - if platformnames[name] then - setposition(f,entry.offset) - local content=readstring(f,entry.length) - local encoding=entry.encoding - local decoder=decoders[platform] - if decoder then - decoder=decoder[encoding] - end - if decoder then - content=decoder(content) - end - if filtered then - filtered[name]=content - else - filtered={ [name]=content } - end - end - end - if filtered then - collected[platform]=filtered - end - end - fontdata.platformnames=collected - end - else - fontdata.names={} - end -end -local validutf=lpeg.patterns.validutf8 -local function getname(fontdata,key) - local names=fontdata.names - if names then - local value=names[key] - if value then - local content=value.content - return lpegmatch(validutf,content) and content or nil - end - end -end -readers["os/2"]=function(f,fontdata) - local datatable=fontdata.tables["os/2"] - if datatable then - setposition(f,datatable.offset) - local version=readushort(f) - local windowsmetrics={ - version=version, - averagewidth=readshort(f), - weightclass=readushort(f), - widthclass=readushort(f), - fstype=readushort(f), - subscriptxsize=readshort(f), - subscriptysize=readshort(f), - subscriptxoffset=readshort(f), - subscriptyoffset=readshort(f), - superscriptxsize=readshort(f), - superscriptysize=readshort(f), - superscriptxoffset=readshort(f), - superscriptyoffset=readshort(f), - strikeoutsize=readshort(f), - strikeoutpos=readshort(f), - familyclass=readshort(f), - panose={ readbytes(f,10) }, - unicoderanges={ readulong(f),readulong(f),readulong(f),readulong(f) }, - vendor=readstring(f,4), - fsselection=readushort(f), - firstcharindex=readushort(f), - lastcharindex=readushort(f), - typoascender=readshort(f), - typodescender=readshort(f), - typolinegap=readshort(f), - winascent=readushort(f), - windescent=readushort(f), - } - if version>=1 then - windowsmetrics.codepageranges={ readulong(f),readulong(f) } - end - if version>=3 then - windowsmetrics.xheight=readshort(f) - windowsmetrics.capheight=readshort(f) - windowsmetrics.defaultchar=readushort(f) - windowsmetrics.breakchar=readushort(f) - end - windowsmetrics.weight=windowsmetrics.weightclass and weights[windowsmetrics.weightclass] - windowsmetrics.width=windowsmetrics.widthclass and widths [windowsmetrics.widthclass] - windowsmetrics.panoseweight=panoseweights[windowsmetrics.panose[3]] - windowsmetrics.panosewidth=panosewidths [windowsmetrics.panose[4]] - fontdata.windowsmetrics=windowsmetrics - else - fontdata.windowsmetrics={} - end -end -readers.head=function(f,fontdata) - local datatable=fontdata.tables.head - if datatable then - setposition(f,datatable.offset) - local fontheader={ - version=readfixed(f), - revision=readfixed(f), - checksum=readulong(f), - magic=readulong(f), - flags=readushort(f), - units=readushort(f), - created=readlongdatetime(f), - modified=readlongdatetime(f), - xmin=readshort(f), - ymin=readshort(f), - xmax=readshort(f), - ymax=readshort(f), - macstyle=readushort(f), - smallpixels=readushort(f), - directionhint=readshort(f), - indextolocformat=readshort(f), - glyphformat=readshort(f), - } - fontdata.fontheader=fontheader - else - fontdata.fontheader={} - end - fontdata.nofglyphs=0 -end -readers.hhea=function(f,fontdata,specification) - if specification.details then - local datatable=fontdata.tables.hhea - if datatable then - setposition(f,datatable.offset) - fontdata.horizontalheader={ - version=readfixed(f), - ascender=readfword(f), - descender=readfword(f), - linegap=readfword(f), - maxadvancewidth=readufword(f), - minleftsidebearing=readfword(f), - minrightsidebearing=readfword(f), - maxextent=readfword(f), - caretsloperise=readshort(f), - caretsloperun=readshort(f), - caretoffset=readshort(f), - reserved_1=readshort(f), - reserved_2=readshort(f), - reserved_3=readshort(f), - reserved_4=readshort(f), - metricdataformat=readshort(f), - nofmetrics=readushort(f), - } - else - fontdata.horizontalheader={ - nofmetrics=0, - } - end - end -end -readers.vhea=function(f,fontdata,specification) - if specification.details then - local datatable=fontdata.tables.vhea - if datatable then - setposition(f,datatable.offset) - local version=readfixed(f) - fontdata.verticalheader={ - version=version, - ascender=readfword(f), - descender=readfword(f), - linegap=readfword(f), - maxadvanceheight=readufword(f), - mintopsidebearing=readfword(f), - minbottomsidebearing=readfword(f), - maxextent=readfword(f), - caretsloperise=readshort(f), - caretsloperun=readshort(f), - caretoffset=readshort(f), - reserved_1=readshort(f), - reserved_2=readshort(f), - reserved_3=readshort(f), - reserved_4=readshort(f), - metricdataformat=readshort(f), - nofmetrics=readushort(f), - } - else - fontdata.verticalheader={ - nofmetrics=0, - } - end - end -end -readers.maxp=function(f,fontdata,specification) - if specification.details then - local datatable=fontdata.tables.maxp - if datatable then - setposition(f,datatable.offset) - local version=readfixed(f) - local nofglyphs=readushort(f) - fontdata.nofglyphs=nofglyphs - if version==0.5 then - fontdata.maximumprofile={ - version=version, - nofglyphs=nofglyphs, - } - return - elseif version==1.0 then - fontdata.maximumprofile={ - version=version, - nofglyphs=nofglyphs, - points=readushort(f), - contours=readushort(f), - compositepoints=readushort(f), - compositecontours=readushort(f), - zones=readushort(f), - twilightpoints=readushort(f), - storage=readushort(f), - functiondefs=readushort(f), - instructiondefs=readushort(f), - stackelements=readushort(f), - sizeofinstructions=readushort(f), - componentelements=readushort(f), - componentdepth=readushort(f), - } - return - end - end - fontdata.maximumprofile={ - version=version, - nofglyphs=0, - } - end -end -readers.hmtx=function(f,fontdata,specification) - if specification.glyphs then - local datatable=fontdata.tables.hmtx - if datatable then - setposition(f,datatable.offset) - local horizontalheader=fontdata.horizontalheader - local nofmetrics=horizontalheader.nofmetrics - local glyphs=fontdata.glyphs - local nofglyphs=fontdata.nofglyphs - local width=0 - local leftsidebearing=0 - for i=0,nofmetrics-1 do - local glyph=glyphs[i] - width=readshort(f) - leftsidebearing=readshort(f) - if width~=0 then - glyph.width=width - end - end - for i=nofmetrics,nofglyphs-1 do - local glyph=glyphs[i] - if width~=0 then - glyph.width=width - end - end - end - end -end -readers.vmtx=function(f,fontdata,specification) - if specification.glyphs then - local datatable=fontdata.tables.vmtx - if datatable then - setposition(f,datatable.offset) - local verticalheader=fontdata.verticalheader - local nofmetrics=verticalheader.nofmetrics - local glyphs=fontdata.glyphs - local nofglyphs=fontdata.nofglyphs - local vheight=0 - local vdefault=verticalheader.ascender+verticalheader.descender - local topsidebearing=0 - for i=0,nofmetrics-1 do - local glyph=glyphs[i] - vheight=readshort(f) - topsidebearing=readshort(f) - if vheight~=0 and vheight~=vdefault then - glyph.vheight=vheight - end - end - for i=nofmetrics,nofglyphs-1 do - local glyph=glyphs[i] - if vheight~=0 and vheight~=vdefault then - glyph.vheight=vheight - end - end - end - end -end -readers.vorg=function(f,fontdata,specification) - if specification.glyphs then - local datatable=fontdata.tables.vorg - if datatable then - report("todo: %s","vorg") - end - end -end -readers.post=function(f,fontdata,specification) - local datatable=fontdata.tables.post - if datatable then - setposition(f,datatable.offset) - local version=readfixed(f) - fontdata.postscript={ - version=version, - italicangle=round(1000*readfixed(f))/1000, - underlineposition=readfword(f), - underlinethickness=readfword(f), - monospaced=readulong(f), - minmemtype42=readulong(f), - maxmemtype42=readulong(f), - minmemtype1=readulong(f), - maxmemtype1=readulong(f), - } - if not specification.glyphs then - elseif version==1.0 then - for index=0,#standardromanencoding do - glyphs[index].name=standardromanencoding[index] - end - elseif version==2.0 then - local glyphs=fontdata.glyphs - local nofglyphs=readushort(f) - local indices={} - local names={} - local maxnames=0 - for i=0,nofglyphs-1 do - local nameindex=readushort(f) - if nameindex>=258 then - maxnames=maxnames+1 - nameindex=nameindex-257 - indices[nameindex]=i - else - glyphs[i].name=standardromanencoding[nameindex] - end - end - for i=1,maxnames do - local mapping=indices[i] - if not mapping then - report("quit post name fetching at %a of %a: %s",i,maxnames,"no index") - break - else - local length=readbyte(f) - if length>0 then - glyphs[mapping].name=readstring(f,length) - else - report("quit post name fetching at %a of %a: %s",i,maxnames,"overflow") - break - end - end - end - elseif version==2.5 then - elseif version==3.0 then - end - else - fontdata.postscript={} - end -end -readers.cff=function(f,fontdata,specification) - if specification.glyphs then - reportskippedtable("cff") - end -end -local formatreaders={} -local duplicatestoo=true -local sequence={ - { 3,1,4 }, - { 3,10,12 }, - { 0,3,4 }, - { 0,1,4 }, - { 0,0,6 }, - { 3,0,6 }, - { 0,5,14 }, - { 3,10,13 }, -} -local supported={} -for i=1,#sequence do - local sp,se,sf=unpack(sequence[i]) - local p=supported[sp] - if not p then - p={} - supported[sp]=p - end - local e=p[se] - if not e then - e={} - p[se]=e - end - e[sf]=true -end -formatreaders[4]=function(f,fontdata,offset) - setposition(f,offset+2) - local length=readushort(f) - local language=readushort(f) - local nofsegments=readushort(f)/2 - skipshort(f,3) - local endchars={} - local startchars={} - local deltas={} - local offsets={} - local indices={} - local mapping=fontdata.mapping - local glyphs=fontdata.glyphs - local duplicates=fontdata.duplicates - local nofdone=0 - for i=1,nofsegments do - endchars[i]=readushort(f) - end - local reserved=readushort(f) - for i=1,nofsegments do - startchars[i]=readushort(f) - end - for i=1,nofsegments do - deltas[i]=readshort(f) - end - for i=1,nofsegments do - offsets[i]=readushort(f) - end - local size=(length-2*2-5*2-4*nofsegments*2)/2 - for i=1,size-1 do - indices[i]=readushort(f) - end - for segment=1,nofsegments do - local startchar=startchars[segment] - local endchar=endchars[segment] - local offset=offsets[segment] - local delta=deltas[segment] - if startchar==0xFFFF and endchar==0xFFFF then - elseif startchar==0xFFFF and offset==0 then - elseif offset==0xFFFF then - elseif offset==0 then - if trace_cmap then - report("format 4.%i segment %2i from %C upto %C at index %H",1,segment,startchar,endchar,(startchar+delta)%65536) - end - for unicode=startchar,endchar do - local index=(unicode+delta)%65536 - if index and index>0 then - local glyph=glyphs[index] - if glyph then - local gu=glyph.unicode - if not gu then - glyph.unicode=unicode - nofdone=nofdone+1 - elseif gu~=unicode then - if duplicatestoo then - local d=duplicates[gu] - if d then - d[unicode]=true - else - duplicates[gu]={ [unicode]=true } - end - else - report("duplicate case 1: %C %04i %s",unicode,index,glyphs[index].name) - end - end - if not mapping[index] then - mapping[index]=unicode - end - end - end - end - else - local shift=(segment-nofsegments+offset/2)-startchar - if trace_cmap then - report("format 4.%i segment %2i from %C upto %C at index %H",0,segment,startchar,endchar,(startchar+delta)%65536) - end - for unicode=startchar,endchar do - local slot=shift+unicode - local index=indices[slot] - if index and index>0 then - index=(index+delta)%65536 - local glyph=glyphs[index] - if glyph then - local gu=glyph.unicode - if not gu then - glyph.unicode=unicode - nofdone=nofdone+1 - elseif gu~=unicode then - if duplicatestoo then - local d=duplicates[gu] - if d then - d[unicode]=true - else - duplicates[gu]={ [unicode]=true } - end - else - report("duplicate case 2: %C %04i %s",unicode,index,glyphs[index].name) - end - end - if not mapping[index] then - mapping[index]=unicode - end - end - end - end - end - end - return nofdone -end -formatreaders[6]=function(f,fontdata,offset) - setposition(f,offset) - local format=readushort(f) - local length=readushort(f) - local language=readushort(f) - local mapping=fontdata.mapping - local glyphs=fontdata.glyphs - local duplicates=fontdata.duplicates - local start=readushort(f) - local count=readushort(f) - local stop=start+count-1 - local nofdone=0 - if trace_cmap then - report("format 6 from %C to %C",2,start,stop) - end - for unicode=start,stop do - local index=readushort(f) - if index>0 then - local glyph=glyphs[index] - if glyph then - local gu=glyph.unicode - if not gu then - glyph.unicode=unicode - nofdone=nofdone+1 - elseif gu~=unicode then - end - if not mapping[index] then - mapping[index]=unicode - end - end - end - end - return nofdone -end -formatreaders[12]=function(f,fontdata,offset) - setposition(f,offset+2+2+4+4) - local mapping=fontdata.mapping - local glyphs=fontdata.glyphs - local duplicates=fontdata.duplicates - local nofgroups=readulong(f) - local nofdone=0 - for i=1,nofgroups do - local first=readulong(f) - local last=readulong(f) - local index=readulong(f) - if trace_cmap then - report("format 12 from %C to %C starts at index %i",first,last,index) - end - for unicode=first,last do - local glyph=glyphs[index] - if glyph then - local gu=glyph.unicode - if not gu then - glyph.unicode=unicode - nofdone=nofdone+1 - elseif gu~=unicode then - local d=duplicates[gu] - if d then - d[unicode]=true - else - duplicates[gu]={ [unicode]=true } - end - end - if not mapping[index] then - mapping[index]=unicode - end - end - index=index+1 - end - end - return nofdone -end -formatreaders[13]=function(f,fontdata,offset) - setposition(f,offset+2+2+4+4) - local mapping=fontdata.mapping - local glyphs=fontdata.glyphs - local duplicates=fontdata.duplicates - local nofgroups=readulong(f) - local nofdone=0 - for i=1,nofgroups do - local first=readulong(f) - local last=readulong(f) - local index=readulong(f) - if first<privateoffset then - if trace_cmap then - report("format 13 from %C to %C get index %i",first,last,index) - end - local glyph=glyphs[index] - local unicode=glyph.unicode - if not unicode then - unicode=first - glyph.unicode=unicode - first=first+1 - end - local list=duplicates[unicode] - mapping[index]=unicode - if not list then - list={} - duplicates[unicode]=list - end - if last>=privateoffset then - local limit=privateoffset-1 - report("format 13 from %C to %C pruned to %C",first,last,limit) - last=limit - end - for unicode=first,last do - list[unicode]=true - end - nofdone=nofdone+last-first+1 - else - report("format 13 from %C to %C ignored",first,last) - end - end - return nofdone -end -formatreaders[14]=function(f,fontdata,offset) - if offset and offset~=0 then - setposition(f,offset) - local format=readushort(f) - local length=readulong(f) - local nofrecords=readulong(f) - local records={} - local variants={} - local nofdone=0 - fontdata.variants=variants - for i=1,nofrecords do - records[i]={ - selector=readuint(f), - default=readulong(f), - other=readulong(f), - } - end - for i=1,nofrecords do - local record=records[i] - local selector=record.selector - local default=record.default - local other=record.other - local other=record.other - if other~=0 then - setposition(f,offset+other) - local mapping={} - local count=readulong(f) - for i=1,count do - mapping[readuint(f)]=readushort(f) - end - nofdone=nofdone+count - variants[selector]=mapping - end - end - return nofdone - else - return 0 - end -end -local function checkcmap(f,fontdata,records,platform,encoding,format) - local data=records[platform] - if not data then - return 0 - end - data=data[encoding] - if not data then - return 0 - end - data=data[format] - if not data then - return 0 - end - local reader=formatreaders[format] - if not reader then - return 0 - end - local p=platforms[platform] - local e=encodings[p] - local n=reader(f,fontdata,data) or 0 - report("cmap checked: platform %i (%s), encoding %i (%s), format %i, new unicodes %i",platform,p,encoding,e and e[encoding] or "?",format,n) - return n -end -function readers.cmap(f,fontdata,specification) - if specification.glyphs then - local datatable=fontdata.tables.cmap - if datatable then - local tableoffset=datatable.offset - setposition(f,tableoffset) - local version=readushort(f) - local noftables=readushort(f) - local records={} - local unicodecid=false - local variantcid=false - local variants={} - local duplicates=fontdata.duplicates or {} - fontdata.duplicates=duplicates - for i=1,noftables do - local platform=readushort(f) - local encoding=readushort(f) - local offset=readulong(f) - local record=records[platform] - if not record then - records[platform]={ - [encoding]={ - offsets={ offset }, - formats={}, - } - } - else - local subtables=record[encoding] - if not subtables then - record[encoding]={ - offsets={ offset }, - formats={}, - } - else - local offsets=subtables.offsets - offsets[#offsets+1]=offset - end - end - end - report("found cmaps:") - for platform,record in sortedhash(records) do - local p=platforms[platform] - local e=encodings[p] - local sp=supported[platform] - local ps=p or "?" - if sp then - report(" platform %i: %s",platform,ps) - else - report(" platform %i: %s (unsupported)",platform,ps) - end - for encoding,subtables in sortedhash(record) do - local se=sp and sp[encoding] - local es=e and e[encoding] or "?" - if se then - report(" encoding %i: %s",encoding,es) - else - report(" encoding %i: %s (unsupported)",encoding,es) - end - local offsets=subtables.offsets - local formats=subtables.formats - for i=1,#offsets do - local offset=tableoffset+offsets[i] - setposition(f,offset) - formats[readushort(f)]=offset - end - record[encoding]=formats - local list=sortedkeys(formats) - for i=1,#list do - if not (se and se[list[i]]) then - list[i]=list[i].." (unsupported)" - end - end - report(" formats: % t",list) - end - end - local ok=false - for i=1,#sequence do - local sp,se,sf=unpack(sequence[i]) - if checkcmap(f,fontdata,records,sp,se,sf)>0 then - ok=true - end - end - if not ok then - report("no useable unicode cmap found") - end - fontdata.cidmaps={ - version=version, - noftables=noftables, - records=records, - } - else - fontdata.cidmaps={} - end - end -end -function readers.loca(f,fontdata,specification) - if specification.glyphs then - reportskippedtable("loca") - end -end -function readers.glyf(f,fontdata,specification) - if specification.glyphs then - reportskippedtable("glyf") - end -end -function readers.colr(f,fontdata,specification) - if specification.glyphs then - reportskippedtable("colr") - end -end -function readers.cpal(f,fontdata,specification) - if specification.glyphs then - reportskippedtable("cpal") - end -end -function readers.svg(f,fontdata,specification) - if specification.glyphs then - reportskippedtable("svg") - end -end -function readers.kern(f,fontdata,specification) - if specification.kerns then - local datatable=fontdata.tables.kern - if datatable then - setposition(f,datatable.offset) - local version=readushort(f) - local noftables=readushort(f) - for i=1,noftables do - local version=readushort(f) - local length=readushort(f) - local coverage=readushort(f) - local format=bit32.rshift(coverage,8) - if format==0 then - local nofpairs=readushort(f) - local searchrange=readushort(f) - local entryselector=readushort(f) - local rangeshift=readushort(f) - local kerns={} - local glyphs=fontdata.glyphs - for i=1,nofpairs do - local left=readushort(f) - local right=readushort(f) - local kern=readfword(f) - local glyph=glyphs[left] - local kerns=glyph.kerns - if kerns then - kerns[right]=kern - else - glyph.kerns={ [right]=kern } - end - end - elseif format==2 then - report("todo: kern classes") - else - report("todo: kerns") - end - end - end - end -end -function readers.gdef(f,fontdata,specification) - if specification.details then - reportskippedtable("gdef") - end -end -function readers.gsub(f,fontdata,specification) - if specification.details then - reportskippedtable("gsub") - end -end -function readers.gpos(f,fontdata,specification) - if specification.details then - reportskippedtable("gpos") - end -end -function readers.math(f,fontdata,specification) - if specification.glyphs then - reportskippedtable("math") - end -end -local function getinfo(maindata,sub,platformnames,rawfamilynames,metricstoo) - local fontdata=sub and maindata.subfonts and maindata.subfonts[sub] or maindata - local names=fontdata.names - local info=nil - if names then - local metrics=fontdata.windowsmetrics or {} - local postscript=fontdata.postscript or {} - local fontheader=fontdata.fontheader or {} - local cffinfo=fontdata.cffinfo or {} - local filename=fontdata.filename - local weight=getname(fontdata,"weight") or (cffinfo and cffinfo.weight) or (metrics and metrics.weight) - local width=getname(fontdata,"width") or (cffinfo and cffinfo.width ) or (metrics and metrics.width ) - local fontname=getname(fontdata,"postscriptname") - local fullname=getname(fontdata,"fullname") - local family=getname(fontdata,"family") - local subfamily=getname(fontdata,"subfamily") - local familyname=getname(fontdata,"typographicfamily") - local subfamilyname=getname(fontdata,"typographicsubfamily") - local compatiblename=getname(fontdata,"compatiblefullname") - if rawfamilynames then - else - if not familyname then familyname=family end - if not subfamilyname then subfamilyname=subfamily end - end - info={ - subfontindex=fontdata.subfontindex or sub or 0, - version=getname(fontdata,"version"), - fontname=fontname, - fullname=fullname, - family=family, - subfamily=subfamily, - familyname=familyname, - subfamilyname=subfamilyname, - compatiblename=compatiblename, - weight=weight and lower(weight), - width=width and lower(width), - pfmweight=metrics.weightclass or 400, - pfmwidth=metrics.widthclass or 5, - panosewidth=metrics.panosewidth, - panoseweight=metrics.panoseweight, - italicangle=postscript.italicangle or 0, - units=fontheader.units or 0, - designsize=fontdata.designsize, - minsize=fontdata.minsize, - maxsize=fontdata.maxsize, - monospaced=(tonumber(postscript.monospaced or 0)>0) or metrics.panosewidth=="monospaced", - averagewidth=metrics.averagewidth, - xheight=metrics.xheight, - capheight=metrics.capheight, - ascender=metrics.typoascender, - descender=metrics.typodescender, - platformnames=platformnames and fontdata.platformnames or nil, - } - if metricstoo then - local keys={ - "version", - "ascender","descender","linegap", - "maxadvancewidth","maxadvanceheight","maxextent", - "minbottomsidebearing","mintopsidebearing", - } - local h=fontdata.horizontalheader or {} - local v=fontdata.verticalheader or {} - if h then - local th={} - local tv={} - for i=1,#keys do - local key=keys[i] - th[key]=h[key] or 0 - tv[key]=v[key] or 0 - end - info.horizontalmetrics=th - info.verticalmetrics=tv - end - end - elseif n then - info={ - filename=fontdata.filename, - comment="there is no info for subfont "..n, - } - else - info={ - filename=fontdata.filename, - comment="there is no info", - } - end - return info -end -local function loadtables(f,specification,offset) - if offset then - setposition(f,offset) - end - local tables={} - local basename=file.basename(specification.filename) - local filesize=specification.filesize - local filetime=specification.filetime - local fontdata={ - filename=basename, - filesize=filesize, - filetime=filetime, - version=readstring(f,4), - noftables=readushort(f), - searchrange=readushort(f), - entryselector=readushort(f), - rangeshift=readushort(f), - tables=tables, - } - for i=1,fontdata.noftables do - local tag=lower(stripstring(readstring(f,4))) - local checksum=readulong(f) - local offset=readulong(f) - local length=readulong(f) - if offset+length>filesize then - report("bad %a table in file %a",tag,basename) - end - tables[tag]={ - checksum=checksum, - offset=offset, - length=length, - } - end - if tables.cff then - fontdata.format="opentype" - else - fontdata.format="truetype" - end - return fontdata -end -local function prepareglyps(fontdata) - local glyphs=setmetatableindex(function(t,k) - local v={ - index=k, - } - t[k]=v - return v - end) - fontdata.glyphs=glyphs - fontdata.mapping={} -end -local function readdata(f,offset,specification) - local fontdata=loadtables(f,specification,offset) - if specification.glyphs then - prepareglyps(fontdata) - end - readers["name"](f,fontdata,specification) - local askedname=specification.askedname - if askedname then - local fullname=getname(fontdata,"fullname") or "" - local cleanname=gsub(askedname,"[^a-zA-Z0-9]","") - local foundname=gsub(fullname,"[^a-zA-Z0-9]","") - if lower(cleanname)~=lower(foundname) then - return - end - end - readers["os/2"](f,fontdata,specification) - readers["head"](f,fontdata,specification) - readers["maxp"](f,fontdata,specification) - readers["hhea"](f,fontdata,specification) - readers["vhea"](f,fontdata,specification) - readers["hmtx"](f,fontdata,specification) - readers["vmtx"](f,fontdata,specification) - readers["vorg"](f,fontdata,specification) - readers["post"](f,fontdata,specification) - readers["cff" ](f,fontdata,specification) - readers["cmap"](f,fontdata,specification) - readers["loca"](f,fontdata,specification) - readers["glyf"](f,fontdata,specification) - readers["colr"](f,fontdata,specification) - readers["cpal"](f,fontdata,specification) - readers["svg" ](f,fontdata,specification) - readers["kern"](f,fontdata,specification) - readers["gdef"](f,fontdata,specification) - readers["gsub"](f,fontdata,specification) - readers["gpos"](f,fontdata,specification) - readers["math"](f,fontdata,specification) - fontdata.locations=nil - fontdata.tables=nil - fontdata.cidmaps=nil - fontdata.dictionaries=nil - return fontdata -end -local function loadfontdata(specification) - local filename=specification.filename - local fileattr=lfs.attributes(filename) - local filesize=fileattr and fileattr.size or 0 - local filetime=fileattr and fileattr.modification or 0 - local f=openfile(filename,true) - if not f then - report("unable to open %a",filename) - elseif filesize==0 then - report("empty file %a",filename) - closefile(f) - else - specification.filesize=filesize - specification.filetime=filetime - local version=readstring(f,4) - local fontdata=nil - if version=="OTTO" or version=="true" or version=="\0\1\0\0" then - fontdata=readdata(f,0,specification) - elseif version=="ttcf" then - local subfont=tonumber(specification.subfont) - local offsets={} - local ttcversion=readulong(f) - local nofsubfonts=readulong(f) - for i=1,nofsubfonts do - offsets[i]=readulong(f) - end - if subfont then - if subfont>=1 and subfont<=nofsubfonts then - fontdata=readdata(f,offsets[subfont],specification) - else - report("no subfont %a in file %a",subfont,filename) - end - else - subfont=specification.subfont - if type(subfont)=="string" and subfont~="" then - specification.askedname=subfont - for i=1,nofsubfonts do - fontdata=readdata(f,offsets[i],specification) - if fontdata then - fontdata.subfontindex=i - report("subfont named %a has index %a",subfont,i) - break - end - end - if not fontdata then - report("no subfont named %a",subfont) - end - else - local subfonts={} - fontdata={ - filename=filename, - filesize=filesize, - filetime=filetime, - version=version, - subfonts=subfonts, - ttcversion=ttcversion, - nofsubfonts=nofsubfonts, - } - for i=1,nofsubfonts do - subfonts[i]=readdata(f,offsets[i],specification) - end - end - end - else - report("unknown version %a in file %a",version,filename) - end - closefile(f) - return fontdata or {} - end -end -local function loadfont(specification,n) - if type(specification)=="string" then - specification={ - filename=specification, - info=true, - details=true, - glyphs=true, - shapes=true, - kerns=true, - globalkerns=true, - lookups=true, - subfont=n or true, - tounicode=false, - } - end - if specification.shapes or specification.lookups or specification.kerns then - specification.glyphs=true - end - if specification.glyphs then - specification.details=true - end - if specification.details then - specification.info=true - end - if specification.platformnames then - specification.platformnames=true - end - local function message(str) - report("fatal error in file %a: %s\n%s",specification.filename,str,debug.traceback()) - end - local ok,result=xpcall(loadfontdata,message,specification) - if ok then - return result - end -end -function readers.loadshapes(filename,n) - local fontdata=loadfont { - filename=filename, - shapes=true, - subfont=n, - } - if fontdata then - for k,v in next,fontdata.glyphs do - v.class=nil - v.index=nil - v.math=nil - end - end - return fontdata and { - filename=filename, - format=fontdata.format, - glyphs=fontdata.glyphs, - units=fontdata.fontheader.units, - } or { - filename=filename, - format="unknown", - glyphs={}, - units=0, - } -end -function readers.loadfont(filename,n) - local fontdata=loadfont { - filename=filename, - glyphs=true, - shapes=false, - lookups=true, - subfont=n, - } - if fontdata then - return { - tableversion=tableversion, - creator="context mkiv", - size=fontdata.filesize, - time=fontdata.filetime, - glyphs=fontdata.glyphs, - descriptions=fontdata.descriptions, - format=fontdata.format, - goodies={}, - metadata=getinfo(fontdata,n,false,false,true), - properties={ - hasitalics=fontdata.hasitalics or false, - maxcolorclass=fontdata.maxcolorclass, - hascolor=fontdata.hascolor or false, - }, - resources={ - filename=filename, - private=privateoffset, - duplicates=fontdata.duplicates or {}, - features=fontdata.features or {}, - sublookups=fontdata.sublookups or {}, - marks=fontdata.marks or {}, - markclasses=fontdata.markclasses or {}, - marksets=fontdata.marksets or {}, - sequences=fontdata.sequences or {}, - variants=fontdata.variants, - version=getname(fontdata,"version"), - cidinfo=fontdata.cidinfo, - mathconstants=fontdata.mathconstants, - colorpalettes=fontdata.colorpalettes, - svgshapes=fontdata.svgshapes, - }, - } - end -end -function readers.getinfo(filename,specification) - local subfont=nil - local platformnames=false - local rawfamilynames=false - if type(specification)=="table" then - subfont=tonumber(specification.subfont) - platformnames=specification.platformnames - rawfamilynames=specification.rawfamilynames - else - subfont=tonumber(specification) - end - local fontdata=loadfont { - filename=filename, - details=true, - platformnames=platformnames, - } - if fontdata then - local subfonts=fontdata.subfonts - if not subfonts then - return getinfo(fontdata,nil,platformnames,rawfamilynames) - elseif not subfont then - local info={} - for i=1,#subfonts do - info[i]=getinfo(fontdata,i,platformnames,rawfamilynames) - end - return info - elseif subfont>=1 and subfont<=#subfonts then - return getinfo(fontdata,subfont,platformnames,rawfamilynames) - else - return { - filename=filename, - comment="there is no subfont "..subfont.." in this file" - } - end - else - return { - filename=filename, - comment="the file cannot be opened for reading", - } - end -end -function readers.rehash(fontdata,hashmethod) - report("the %a helper is not yet implemented","rehash") -end -function readers.checkhash(fontdata) - report("the %a helper is not yet implemented","checkhash") -end -function readers.pack(fontdata,hashmethod) - report("the %a helper is not yet implemented","pack") -end -function readers.unpack(fontdata) - report("the %a helper is not yet implemented","unpack") -end -function readers.expand(fontdata) - report("the %a helper is not yet implemented","unpack") -end -function readers.compact(fontdata) - report("the %a helper is not yet implemented","compact") -end -local extenders={} -function readers.registerextender(extender) - extenders[#extenders+1]=extender -end -function readers.extend(fontdata) - for i=1,#extenders do - local extender=extenders[i] - local name=extender.name or "unknown" - local action=extender.action - if action then - action(fontdata) - end - end -end - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['font-cff']={ - version=1.001, - comment="companion to font-ini.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local next,type,tonumber=next,type,tonumber -local byte=string.byte -local concat,remove=table.concat,table.remove -local floor,abs,round,ceil=math.floor,math.abs,math.round,math.ceil -local P,C,R,S,C,Cs,Ct=lpeg.P,lpeg.C,lpeg.R,lpeg.S,lpeg.C,lpeg.Cs,lpeg.Ct -local lpegmatch=lpeg.match -local formatters=string.formatters -local readers=fonts.handlers.otf.readers -local streamreader=readers.streamreader -local readbytes=streamreader.readbytes -local readstring=streamreader.readstring -local readbyte=streamreader.readcardinal1 -local readushort=streamreader.readcardinal2 -local readuint=streamreader.readcardinal3 -local readulong=streamreader.readcardinal4 -local setposition=streamreader.setposition -local getposition=streamreader.getposition -local setmetatableindex=table.setmetatableindex -local trace_charstrings=false trackers.register("fonts.cff.charstrings",function(v) trace_charstrings=v end) -local report=logs.reporter("otf reader","cff") -local parsedictionaries -local parsecharstring -local parsecharstrings -local resetcharstrings -local parseprivates -local defaultstrings={ [0]= - ".notdef","space","exclam","quotedbl","numbersign","dollar","percent", - "ampersand","quoteright","parenleft","parenright","asterisk","plus", - "comma","hyphen","period","slash","zero","one","two","three","four", - "five","six","seven","eight","nine","colon","semicolon","less", - "equal","greater","question","at","A","B","C","D","E","F","G","H", - "I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W", - "X","Y","Z","bracketleft","backslash","bracketright","asciicircum", - "underscore","quoteleft","a","b","c","d","e","f","g","h","i","j", - "k","l","m","n","o","p","q","r","s","t","u","v","w","x","y", - "z","braceleft","bar","braceright","asciitilde","exclamdown","cent", - "sterling","fraction","yen","florin","section","currency", - "quotesingle","quotedblleft","guillemotleft","guilsinglleft", - "guilsinglright","fi","fl","endash","dagger","daggerdbl", - "periodcentered","paragraph","bullet","quotesinglbase","quotedblbase", - "quotedblright","guillemotright","ellipsis","perthousand","questiondown", - "grave","acute","circumflex","tilde","macron","breve","dotaccent", - "dieresis","ring","cedilla","hungarumlaut","ogonek","caron","emdash", - "AE","ordfeminine","Lslash","Oslash","OE","ordmasculine","ae", - "dotlessi","lslash","oslash","oe","germandbls","onesuperior", - "logicalnot","mu","trademark","Eth","onehalf","plusminus","Thorn", - "onequarter","divide","brokenbar","degree","thorn","threequarters", - "twosuperior","registered","minus","eth","multiply","threesuperior", - "copyright","Aacute","Acircumflex","Adieresis","Agrave","Aring", - "Atilde","Ccedilla","Eacute","Ecircumflex","Edieresis","Egrave", - "Iacute","Icircumflex","Idieresis","Igrave","Ntilde","Oacute", - "Ocircumflex","Odieresis","Ograve","Otilde","Scaron","Uacute", - "Ucircumflex","Udieresis","Ugrave","Yacute","Ydieresis","Zcaron", - "aacute","acircumflex","adieresis","agrave","aring","atilde", - "ccedilla","eacute","ecircumflex","edieresis","egrave","iacute", - "icircumflex","idieresis","igrave","ntilde","oacute","ocircumflex", - "odieresis","ograve","otilde","scaron","uacute","ucircumflex", - "udieresis","ugrave","yacute","ydieresis","zcaron","exclamsmall", - "Hungarumlautsmall","dollaroldstyle","dollarsuperior","ampersandsmall", - "Acutesmall","parenleftsuperior","parenrightsuperior","twodotenleader", - "onedotenleader","zerooldstyle","oneoldstyle","twooldstyle", - "threeoldstyle","fouroldstyle","fiveoldstyle","sixoldstyle", - "sevenoldstyle","eightoldstyle","nineoldstyle","commasuperior", - "threequartersemdash","periodsuperior","questionsmall","asuperior", - "bsuperior","centsuperior","dsuperior","esuperior","isuperior", - "lsuperior","msuperior","nsuperior","osuperior","rsuperior","ssuperior", - "tsuperior","ff","ffi","ffl","parenleftinferior","parenrightinferior", - "Circumflexsmall","hyphensuperior","Gravesmall","Asmall","Bsmall", - "Csmall","Dsmall","Esmall","Fsmall","Gsmall","Hsmall","Ismall", - "Jsmall","Ksmall","Lsmall","Msmall","Nsmall","Osmall","Psmall", - "Qsmall","Rsmall","Ssmall","Tsmall","Usmall","Vsmall","Wsmall", - "Xsmall","Ysmall","Zsmall","colonmonetary","onefitted","rupiah", - "Tildesmall","exclamdownsmall","centoldstyle","Lslashsmall", - "Scaronsmall","Zcaronsmall","Dieresissmall","Brevesmall","Caronsmall", - "Dotaccentsmall","Macronsmall","figuredash","hypheninferior", - "Ogoneksmall","Ringsmall","Cedillasmall","questiondownsmall","oneeighth", - "threeeighths","fiveeighths","seveneighths","onethird","twothirds", - "zerosuperior","foursuperior","fivesuperior","sixsuperior", - "sevensuperior","eightsuperior","ninesuperior","zeroinferior", - "oneinferior","twoinferior","threeinferior","fourinferior", - "fiveinferior","sixinferior","seveninferior","eightinferior", - "nineinferior","centinferior","dollarinferior","periodinferior", - "commainferior","Agravesmall","Aacutesmall","Acircumflexsmall", - "Atildesmall","Adieresissmall","Aringsmall","AEsmall","Ccedillasmall", - "Egravesmall","Eacutesmall","Ecircumflexsmall","Edieresissmall", - "Igravesmall","Iacutesmall","Icircumflexsmall","Idieresissmall", - "Ethsmall","Ntildesmall","Ogravesmall","Oacutesmall","Ocircumflexsmall", - "Otildesmall","Odieresissmall","OEsmall","Oslashsmall","Ugravesmall", - "Uacutesmall","Ucircumflexsmall","Udieresissmall","Yacutesmall", - "Thornsmall","Ydieresissmall","001.000","001.001","001.002","001.003", - "Black","Bold","Book","Light","Medium","Regular","Roman","Semibold", -} -local cffreaders={ - readbyte, - readushort, - readuint, - readulong, -} -local function readheader(f) - local offset=getposition(f) - local header={ - offset=offset, - major=readbyte(f), - minor=readbyte(f), - size=readbyte(f), - osize=readbyte(f), - } - setposition(f,offset+header.size) - return header -end -local function readlengths(f) - local count=readushort(f) - if count==0 then - return {} - end - local osize=readbyte(f) - local read=cffreaders[osize] - if not read then - report("bad offset size: %i",osize) - return {} - end - local lengths={} - local previous=read(f) - for i=1,count do - local offset=read(f) - lengths[i]=offset-previous - previous=offset - end - return lengths -end -local function readfontnames(f) - local names=readlengths(f) - for i=1,#names do - names[i]=readstring(f,names[i]) - end - return names -end -local function readtopdictionaries(f) - local dictionaries=readlengths(f) - for i=1,#dictionaries do - dictionaries[i]=readstring(f,dictionaries[i]) - end - return dictionaries -end -local function readstrings(f) - local lengths=readlengths(f) - local strings=setmetatableindex({},defaultstrings) - local index=#defaultstrings - for i=1,#lengths do - index=index+1 - strings[index]=readstring(f,lengths[i]) - end - return strings -end -do - local stack={} - local top=0 - local result={} - local strings={} - local p_single=P("\00")/function() - result.version=strings[stack[top]] or "unset" - top=0 - end+P("\01")/function() - result.notice=strings[stack[top]] or "unset" - top=0 - end+P("\02")/function() - result.fullname=strings[stack[top]] or "unset" - top=0 - end+P("\03")/function() - result.familyname=strings[stack[top]] or "unset" - top=0 - end+P("\04")/function() - result.weight=strings[stack[top]] or "unset" - top=0 - end+P("\05")/function() - result.fontbbox={ unpack(stack,1,4) } - top=0 - end -+P("\13")/function() - result.uniqueid=stack[top] - top=0 - end+P("\14")/function() - result.xuid=concat(stack,"",1,top) - top=0 - end+P("\15")/function() - result.charset=stack[top] - top=0 - end+P("\16")/function() - result.encoding=stack[top] - top=0 - end+P("\17")/function() - result.charstrings=stack[top] - top=0 - end+P("\18")/function() - result.private={ - size=stack[top-1], - offset=stack[top], - } - top=0 - end+P("\19")/function() - result.subroutines=stack[top] - end+P("\20")/function() - result.defaultwidthx=stack[top] - end+P("\21")/function() - result.nominalwidthx=stack[top] - end - local p_double=P("\12")*( - P("\00")/function() - result.copyright=stack[top] - top=0 - end+P("\01")/function() - result.monospaced=stack[top]==1 and true or false - top=0 - end+P("\02")/function() - result.italicangle=stack[top] - top=0 - end+P("\03")/function() - result.underlineposition=stack[top] - top=0 - end+P("\04")/function() - result.underlinethickness=stack[top] - top=0 - end+P("\05")/function() - result.painttype=stack[top] - top=0 - end+P("\06")/function() - result.charstringtype=stack[top] - top=0 - end+P("\07")/function() - result.fontmatrix={ unpack(stack,1,6) } - top=0 - end+P("\08")/function() - result.strokewidth=stack[top] - top=0 - end+P("\20")/function() - result.syntheticbase=stack[top] - top=0 - end+P("\21")/function() - result.postscript=strings[stack[top]] or "unset" - top=0 - end+P("\22")/function() - result.basefontname=strings[stack[top]] or "unset" - top=0 - end+P("\21")/function() - result.basefontblend=stack[top] - top=0 - end+P("\30")/function() - result.cid.registry=strings[stack[top-2]] or "unset" - result.cid.ordering=strings[stack[top-1]] or "unset" - result.cid.supplement=stack[top] - top=0 - end+P("\31")/function() - result.cid.fontversion=stack[top] - top=0 - end+P("\32")/function() - result.cid.fontrevision=stack[top] - top=0 - end+P("\33")/function() - result.cid.fonttype=stack[top] - top=0 - end+P("\34")/function() - result.cid.count=stack[top] - top=0 - end+P("\35")/function() - result.cid.uidbase=stack[top] - top=0 - end+P("\36")/function() - result.cid.fdarray=stack[top] - top=0 - end+P("\37")/function() - result.cid.fdselect=stack[top] - top=0 - end+P("\38")/function() - result.cid.fontname=strings[stack[top]] or "unset" - top=0 - end - ) - local p_last=P("\x0F")/"0"+P("\x1F")/"1"+P("\x2F")/"2"+P("\x3F")/"3"+P("\x4F")/"4"+P("\x5F")/"5"+P("\x6F")/"6"+P("\x7F")/"7"+P("\x8F")/"8"+P("\x9F")/"9"+P("\xAF")/""+P("\xBF")/""+P("\xCF")/""+P("\xDF")/""+P("\xEF")/""+R("\xF0\xFF")/"" - local remap={ - ["\x00"]="00",["\x01"]="01",["\x02"]="02",["\x03"]="03",["\x04"]="04",["\x05"]="05",["\x06"]="06",["\x07"]="07",["\x08"]="08",["\x09"]="09",["\x0A"]="0.",["\x0B"]="0E",["\x0C"]="0E-",["\x0D"]="0",["\x0E"]="0-",["\x0F"]="0", - ["\x10"]="10",["\x11"]="11",["\x12"]="12",["\x13"]="13",["\x14"]="14",["\x15"]="15",["\x16"]="16",["\x17"]="17",["\x18"]="18",["\x19"]="19",["\x1A"]="0.",["\x1B"]="0E",["\x1C"]="0E-",["\x1D"]="0",["\x1E"]="0-",["\x1F"]="0", - ["\x20"]="20",["\x21"]="21",["\x22"]="22",["\x23"]="23",["\x24"]="24",["\x25"]="25",["\x26"]="26",["\x27"]="27",["\x28"]="28",["\x29"]="29",["\x2A"]="0.",["\x2B"]="0E",["\x2C"]="0E-",["\x2D"]="0",["\x2E"]="0-",["\x2F"]="0", - ["\x30"]="30",["\x31"]="31",["\x32"]="32",["\x33"]="33",["\x34"]="34",["\x35"]="35",["\x36"]="36",["\x37"]="37",["\x38"]="38",["\x39"]="39",["\x3A"]="0.",["\x3B"]="0E",["\x3C"]="0E-",["\x3D"]="0",["\x3E"]="0-",["\x3F"]="0", - ["\x40"]="40",["\x41"]="41",["\x42"]="42",["\x43"]="43",["\x44"]="44",["\x45"]="45",["\x46"]="46",["\x47"]="47",["\x48"]="48",["\x49"]="49",["\x4A"]="0.",["\x4B"]="0E",["\x4C"]="0E-",["\x4D"]="0",["\x4E"]="0-",["\x4F"]="0", - ["\x50"]="50",["\x51"]="51",["\x52"]="52",["\x53"]="53",["\x54"]="54",["\x55"]="55",["\x56"]="56",["\x57"]="57",["\x58"]="58",["\x59"]="59",["\x5A"]="0.",["\x5B"]="0E",["\x5C"]="0E-",["\x5D"]="0",["\x5E"]="0-",["\x5F"]="0", - ["\x60"]="60",["\x61"]="61",["\x62"]="62",["\x63"]="63",["\x64"]="64",["\x65"]="65",["\x66"]="66",["\x67"]="67",["\x68"]="68",["\x69"]="69",["\x6A"]="0.",["\x6B"]="0E",["\x6C"]="0E-",["\x6D"]="0",["\x6E"]="0-",["\x6F"]="0", - ["\x70"]="70",["\x71"]="71",["\x72"]="72",["\x73"]="73",["\x74"]="74",["\x75"]="75",["\x76"]="76",["\x77"]="77",["\x78"]="78",["\x79"]="79",["\x7A"]="0.",["\x7B"]="0E",["\x7C"]="0E-",["\x7D"]="0",["\x7E"]="0-",["\x7F"]="0", - ["\x80"]="80",["\x81"]="81",["\x82"]="82",["\x83"]="83",["\x84"]="84",["\x85"]="85",["\x86"]="86",["\x87"]="87",["\x88"]="88",["\x89"]="89",["\x8A"]="0.",["\x8B"]="0E",["\x8C"]="0E-",["\x8D"]="0",["\x8E"]="0-",["\x8F"]="0", - ["\x90"]="90",["\x91"]="91",["\x92"]="92",["\x93"]="93",["\x94"]="94",["\x95"]="95",["\x96"]="96",["\x97"]="97",["\x98"]="98",["\x99"]="99",["\x9A"]="0.",["\x9B"]="0E",["\x9C"]="0E-",["\x9D"]="0",["\x9E"]="0-",["\x9F"]="0", - ["\xA0"]=".0",["\xA1"]=".1",["\xA2"]=".2",["\xA3"]=".3",["\xA4"]=".4",["\xA5"]=".5",["\xA6"]=".6",["\xA7"]=".7",["\xA8"]=".8",["\xA9"]=".9",["\xAA"]="..",["\xAB"]=".E",["\xAC"]=".E-",["\xAD"]=".",["\xAE"]=".-",["\xAF"]=".", - ["\xB0"]="E0",["\xB1"]="E1",["\xB2"]="E2",["\xB3"]="E3",["\xB4"]="E4",["\xB5"]="E5",["\xB6"]="E6",["\xB7"]="E7",["\xB8"]="E8",["\xB9"]="E9",["\xBA"]="E.",["\xBB"]="EE",["\xBC"]="EE-",["\xBD"]="E",["\xBE"]="E-",["\xBF"]="E", - ["\xC0"]="E-0",["\xC1"]="E-1",["\xC2"]="E-2",["\xC3"]="E-3",["\xC4"]="E-4",["\xC5"]="E-5",["\xC6"]="E-6",["\xC7"]="E-7",["\xC8"]="E-8",["\xC9"]="E-9",["\xCA"]="E-.",["\xCB"]="E-E",["\xCC"]="E-E-",["\xCD"]="E-",["\xCE"]="E--",["\xCF"]="E-", - ["\xD0"]="-0",["\xD1"]="-1",["\xD2"]="-2",["\xD3"]="-3",["\xD4"]="-4",["\xD5"]="-5",["\xD6"]="-6",["\xD7"]="-7",["\xD8"]="-8",["\xD9"]="-9",["\xDA"]="-.",["\xDB"]="-E",["\xDC"]="-E-",["\xDD"]="-",["\xDE"]="--",["\xDF"]="-", - } - local p_nibbles=P("\30")*Cs(((1-p_last)/remap)^0+p_last)/function(n) - top=top+1 - stack[top]=tonumber(n) or 0 - end - local p_byte=C(R("\32\246"))/function(b0) - top=top+1 - stack[top]=byte(b0)-139 - end - local p_positive=C(R("\247\250"))*C(1)/function(b0,b1) - top=top+1 - stack[top]=(byte(b0)-247)*256+byte(b1)+108 - end - local p_negative=C(R("\251\254"))*C(1)/function(b0,b1) - top=top+1 - stack[top]=-(byte(b0)-251)*256-byte(b1)-108 - end - local p_short=P("\28")*C(1)*C(1)/function(b1,b2) - top=top+1 - local n=0x100*byte(b1)+byte(b2) - if n>=0x8000 then - stack[top]=n-0xFFFF-1 - else - stack[top]=n - end - end - local p_long=P("\29")*C(1)*C(1)*C(1)*C(1)/function(b1,b2,b3,b4) - top=top+1 - local n=0x1000000*byte(b1)+0x10000*byte(b2)+0x100*byte(b3)+byte(b4) - if n>=0x8000000 then - stack[top]=n-0xFFFFFFFF-1 - else - stack[top]=n - end - end - local p_unsupported=P(1)/function(detail) - top=0 - end - local p_dictionary=( - p_byte+p_positive+p_negative+p_short+p_long+p_nibbles+p_single+p_double+p_unsupported - )^1 - parsedictionaries=function(data,dictionaries) - stack={} - strings=data.strings - for i=1,#dictionaries do - top=0 - result={ - monospaced=false, - italicangle=0, - underlineposition=-100, - underlinethickness=50, - painttype=0, - charstringtype=2, - fontmatrix={ 0.001,0,0,0.001,0,0 }, - fontbbox={ 0,0,0,0 }, - strokewidth=0, - charset=0, - encoding=0, - cid={ - fontversion=0, - fontrevision=0, - fonttype=0, - count=8720, - } - } - lpegmatch(p_dictionary,dictionaries[i]) - dictionaries[i]=result - end - result={} - top=0 - stack={} - end - parseprivates=function(data,dictionaries) - stack={} - strings=data.strings - for i=1,#dictionaries do - local private=dictionaries[i].private - if private and private.data then - top=0 - result={ - forcebold=false, - languagegroup=0, - expansionfactor=0.06, - initialrandomseed=0, - subroutines=0, - defaultwidthx=0, - nominalwidthx=0, - cid={ - }, - } - lpegmatch(p_dictionary,private.data) - private.data=result - end - end - result={} - top=0 - stack={} - end - local x=0 - local y=0 - local width=false - local r=0 - local stems=0 - local globalbias=0 - local localbias=0 - local globals=false - local locals=false - local depth=1 - local xmin=0 - local xmax=0 - local ymin=0 - local ymax=0 - local checked=false - local keepcurve=false - local version=2 - local function showstate(where) - report("%w%-10s : [%s] n=%i",depth*2,where,concat(stack," ",1,top),top) - end - local function showvalue(where,value,showstack) - if showstack then - report("%w%-10s : %s : [%s] n=%i",depth*2,where,tostring(value),concat(stack," ",1,top),top) - else - report("%w%-10s : %s",depth*2,where,tostring(value)) - end - end - local function moveto(x,y) - if keepcurve then - r=r+1 - result[r]={ x,y,"m" } - end - if checked then - if x<xmin then xmin=x elseif x>xmax then xmax=x end - if y<ymin then ymin=y elseif y>ymax then ymax=y end - else - xmin=x - ymin=y - xmax=x - ymax=y - checked=true - end - end - local function lineto(x,y) - if keepcurve then - r=r+1 - result[r]={ x,y,"l" } - end - if checked then - if x<xmin then xmin=x elseif x>xmax then xmax=x end - if y<ymin then ymin=y elseif y>ymax then ymax=y end - else - xmin=x - ymin=y - xmax=x - ymax=y - checked=true - end - end - local function curveto(x1,y1,x2,y2,x3,y3) - if keepcurve then - r=r+1 - result[r]={ x1,y1,x2,y2,x3,y3,"c" } - end - if checked then - if x1<xmin then xmin=x1 elseif x1>xmax then xmax=x1 end - if y1<ymin then ymin=y1 elseif y1>ymax then ymax=y1 end - else - xmin=x1 - ymin=y1 - xmax=x1 - ymax=y1 - checked=true - end - if x2<xmin then xmin=x2 elseif x2>xmax then xmax=x2 end - if y2<ymin then ymin=y2 elseif y2>ymax then ymax=y2 end - if x3<xmin then xmin=x3 elseif x3>xmax then xmax=x3 end - if y3<ymin then ymin=y3 elseif y3>ymax then ymax=y3 end - end - local function rmoveto() - if top>2 then - if not width then - width=stack[1] - if trace_charstrings then - showvalue("width",width) - end - end - elseif not width then - width=true - end - if trace_charstrings then - showstate("rmoveto") - end - x=x+stack[top-1] - y=y+stack[top] - top=0 - moveto(x,y) - end - local function hmoveto() - if top>1 then - if not width then - width=stack[1] - if trace_charstrings then - showvalue("width",width) - end - end - elseif not width then - width=true - end - if trace_charstrings then - showstate("hmoveto") - end - x=x+stack[top] - top=0 - moveto(x,y) - end - local function vmoveto() - if top>1 then - if not width then - width=stack[1] - if trace_charstrings then - showvalue("width",width) - end - end - elseif not width then - width=true - end - if trace_charstrings then - showstate("vmoveto") - end - y=y+stack[top] - top=0 - moveto(x,y) - end - local function rlineto() - if trace_charstrings then - showstate("rlineto") - end - for i=1,top,2 do - x=x+stack[i] - y=y+stack[i+1] - lineto(x,y) - end - top=0 - end - local function xlineto(swap) - for i=1,top do - if swap then - x=x+stack[i] - swap=false - else - y=y+stack[i] - swap=true - end - lineto(x,y) - end - top=0 - end - local function hlineto() - if trace_charstrings then - showstate("hlineto") - end - xlineto(true) - end - local function vlineto() - if trace_charstrings then - showstate("vlineto") - end - xlineto(false) - end - local function rrcurveto() - if trace_charstrings then - showstate("rrcurveto") - end - for i=1,top,6 do - local ax=x+stack[i] - local ay=y+stack[i+1] - local bx=ax+stack[i+2] - local by=ay+stack[i+3] - x=bx+stack[i+4] - y=by+stack[i+5] - curveto(ax,ay,bx,by,x,y) - end - top=0 - end - local function hhcurveto() - if trace_charstrings then - showstate("hhcurveto") - end - local s=1 - if top%2~=0 then - y=y+stack[1] - s=2 - end - for i=s,top,4 do - local ax=x+stack[i] - local ay=y - local bx=ax+stack[i+1] - local by=ay+stack[i+2] - x=bx+stack[i+3] - y=by - curveto(ax,ay,bx,by,x,y) - end - top=0 - end - local function vvcurveto() - if trace_charstrings then - showstate("vvcurveto") - end - local s=1 - local d=0 - if top%2~=0 then - d=stack[1] - s=2 - end - for i=s,top,4 do - local ax=x+d - local ay=y+stack[i] - local bx=ax+stack[i+1] - local by=ay+stack[i+2] - x=bx - y=by+stack[i+3] - curveto(ax,ay,bx,by,x,y) - d=0 - end - top=0 - end - local function xxcurveto(swap) - local last=top%4~=0 and stack[top] - if last then - top=top-1 - end - local sw=swap - for i=1,top,4 do - local ax,ay,bx,by - if swap then - ax=x+stack[i] - ay=y - bx=ax+stack[i+1] - by=ay+stack[i+2] - y=by+stack[i+3] - if last and i+3==top then - x=bx+last - else - x=bx - end - swap=false - else - ax=x - ay=y+stack[i] - bx=ax+stack[i+1] - by=ay+stack[i+2] - x=bx+stack[i+3] - if last and i+3==top then - y=by+last - else - y=by - end - swap=true - end - curveto(ax,ay,bx,by,x,y) - end - top=0 - end - local function hvcurveto() - if trace_charstrings then - showstate("hvcurveto") - end - xxcurveto(true) - end - local function vhcurveto() - if trace_charstrings then - showstate("vhcurveto") - end - xxcurveto(false) - end - local function rcurveline() - if trace_charstrings then - showstate("rcurveline") - end - for i=1,top-2,6 do - local ax=x+stack[i] - local ay=y+stack[i+1] - local bx=ax+stack[i+2] - local by=ay+stack[i+3] - x=bx+stack[i+4] - y=by+stack[i+5] - curveto(ax,ay,bx,by,x,y) - end - x=x+stack[top-1] - y=y+stack[top] - lineto(x,y) - top=0 - end - local function rlinecurve() - if trace_charstrings then - showstate("rlinecurve") - end - if top>6 then - for i=1,top-6,2 do - x=x+stack[i] - y=y+stack[i+1] - lineto(x,y) - end - end - local ax=x+stack[top-5] - local ay=y+stack[top-4] - local bx=ax+stack[top-3] - local by=ay+stack[top-2] - x=bx+stack[top-1] - y=by+stack[top] - curveto(ax,ay,bx,by,x,y) - top=0 - end - local function flex() - if trace_charstrings then - showstate("flex") - end - local ax=x+stack[1] - local ay=y+stack[2] - local bx=ax+stack[3] - local by=ay+stack[4] - local cx=bx+stack[5] - local cy=by+stack[6] - curveto(ax,ay,bx,by,cx,cy) - local dx=cx+stack[7] - local dy=cy+stack[8] - local ex=dx+stack[9] - local ey=dy+stack[10] - x=ex+stack[11] - y=ey+stack[12] - curveto(dx,dy,ex,ey,x,y) - top=0 - end - local function hflex() - if trace_charstrings then - showstate("hflex") - end - local ax=x+stack[1] - local ay=y - local bx=ax+stack[2] - local by=ay+stack[3] - local cx=bx+stack[4] - local cy=by - curveto(ax,ay,bx,by,cx,cy) - local dx=cx+stack[5] - local dy=by - local ex=dx+stack[6] - local ey=y - x=ex+stack[7] - curveto(dx,dy,ex,ey,x,y) - top=0 - end - local function hflex1() - if trace_charstrings then - showstate("hflex1") - end - local ax=x+stack[1] - local ay=y+stack[2] - local bx=ax+stack[3] - local by=ay+stack[4] - local cx=bx+stack[5] - local cy=by - curveto(ax,ay,bx,by,cx,cy) - local dx=cx+stack[6] - local dy=by - local ex=dx+stack[7] - local ey=dy+stack[8] - x=ex+stack[9] - curveto(dx,dy,ex,ey,x,y) - top=0 - end - local function flex1() - if trace_charstrings then - showstate("flex1") - end - local ax=x+stack[1] - local ay=y+stack[2] - local bx=ax+stack[3] - local by=ay+stack[4] - local cx=bx+stack[5] - local cy=by+stack[6] - curveto(ax,ay,bx,by,cx,cy) - local dx=cx+stack[7] - local dy=cy+stack[8] - local ex=dx+stack[9] - local ey=dy+stack[10] - if abs(ex-x)>abs(ey-y) then - x=ex+stack[11] - else - y=ey+stack[11] - end - curveto(dx,dy,ex,ey,x,y) - top=0 - end - local function getstem() - if top==0 then - elseif top%2~=0 then - if width then - remove(stack,1) - else - width=remove(stack,1) - if trace_charstrings then - showvalue("width",width) - end - end - top=top-1 - end - if trace_charstrings then - showstate("stem") - end - stems=stems+top/2 - top=0 - end - local function getmask() - if top==0 then - elseif top%2~=0 then - if width then - remove(stack,1) - else - width=remove(stack,1) - if trace_charstrings then - showvalue("width",width) - end - end - top=top-1 - end - if trace_charstrings then - showstate(operator==19 and "hintmark" or "cntrmask") - end - stems=stems+top/2 - top=0 - if stems==0 then - elseif stems<=8 then - return 1 - else - return floor((stems+7)/8) - end - end - local function unsupported(t) - if trace_charstrings then - showstate("unsupported "..t) - end - top=0 - end - local function unsupportedsub(t) - if trace_charstrings then - showstate("unsupported sub "..t) - end - top=0 - end - local function getstem3() - if trace_charstrings then - showstate("stem3") - end - top=0 - end - local function divide() - if version==1 then - local d=stack[top] - top=top-1 - stack[top]=stack[top]/d - end - end - local function closepath() - if version==1 then - if trace_charstrings then - showstate("closepath") - end - end - top=0 - end - local function hsbw() - if version==1 then - if trace_charstrings then - showstate("dotsection") - end - width=stack[top] - end - top=0 - end - local function seac() - if version==1 then - if trace_charstrings then - showstate("seac") - end - end - top=0 - end - local function sbw() - if version==1 then - if trace_charstrings then - showstate("sbw") - end - width=stack[top-1] - end - top=0 - end - local function callothersubr() - if version==1 then - if trace_charstrings then - showstate("callothersubr (unsupported)") - end - end - top=0 - end - local function pop() - if version==1 then - if trace_charstrings then - showstate("pop (unsupported)") - end - top=top+1 - stack[top]=0 - else - top=0 - end - end - local function setcurrentpoint() - if version==1 then - if trace_charstrings then - showstate("pop (unsupported)") - end - x=x+stack[top-1] - y=y+stack[top] - end - top=0 - end - local actions={ [0]=unsupported, - getstem, - unsupported, - getstem, - vmoveto, - rlineto, - hlineto, - vlineto, - rrcurveto, - unsupported, - unsupported, - unsupported, - unsupported, - hsbw, - unsupported, - unsupported, - unsupported, - unsupported, - getstem, - getmask, - getmask, - rmoveto, - hmoveto, - getstem, - rcurveline, - rlinecurve, - vvcurveto, - hhcurveto, - unsupported, - unsupported, - vhcurveto, - hvcurveto, - } - local subactions={ - [000]=dotsection, - [001]=getstem3, - [002]=getstem3, - [006]=seac, - [007]=sbw, - [012]=divide, - [016]=callothersubr, - [017]=pop, - [033]=setcurrentpoint, - [034]=hflex, - [035]=flex, - [036]=hflex1, - [037]=flex1, - } - local p_bytes=Ct((P(1)/byte)^0) - local function call(scope,list,bias,process) - depth=depth+1 - if top==0 then - showstate(formatters["unknown %s call"](scope)) - top=0 - else - local index=stack[top]+bias - top=top-1 - if trace_charstrings then - showvalue(scope,index,true) - end - local tab=list[index] - if tab then - if type(tab)=="string" then - tab=lpegmatch(p_bytes,tab) - list[index]=tab - end - process(tab) - else - showstate(formatters["unknown %s call %i"](scope,index)) - top=0 - end - end - depth=depth-1 - end - local function process(tab) - local i=1 - local n=#tab - while i<=n do - local t=tab[i] - if t>=32 and t<=246 then - top=top+1 - stack[top]=t-139 - i=i+1 - elseif t>=247 and t<=250 then - top=top+1 - stack[top]=(t-247)*256+tab[i+1]+108 - i=i+2 - elseif t>=251 and t<=254 then - top=top+1 - stack[top]=-(t-251)*256-tab[i+1]-108 - i=i+2 - elseif t==28 then - top=top+1 - local n=0x100*tab[i+1]+tab[i+2] - if n>=0x8000 then - stack[top]=n-0xFFFF-1 - else - stack[top]=n - end - i=i+3 - elseif t==255 then - local n=0x100*tab[i+1]+tab[i+2] - top=top+1 - if n>=0x8000 then - stack[top]=n-0xFFFF-1+(0x100*tab[i+3]+tab[i+4])/0xFFFF - else - stack[top]=n+(0x100*tab[i+3]+tab[i+4])/0xFFFF - end - i=i+5 - elseif t==11 then - if trace_charstrings then - showstate("return") - end - return - elseif t==10 then - call("local",locals,localbias,process) - i=i+1 - elseif t==14 then - if width then - elseif top>0 then - width=stack[1] - if trace_charstrings then - showvalue("width",width) - end - else - width=true - end - if trace_charstrings then - showstate("endchar") - end - return - elseif t==29 then - call("global",globals,globalbias,process) - i=i+1 - elseif t==12 then - i=i+1 - local t=tab[i] - local a=subactions[t] - if a then - a(t) - else - if trace_charstrings then - showvalue("<subaction>",t) - end - top=0 - end - i=i+1 - else - local a=actions[t] - if a then - local s=a(t) - if s then - i=i+s - end - else - if trace_charstrings then - showvalue("<action>",t) - end - top=0 - end - i=i+1 - end - end - end - local function setbias(globals,locals) - if version==1 then - return - false, - false - else - local g,l=#globals,#locals - return - ((g<1240 and 107) or (g<33900 and 1131) or 32768)+1, - ((l<1240 and 107) or (l<33900 and 1131) or 32768)+1 - end - end - parsecharstrings=function(data,glyphs,doshapes,tversion) - local dictionary=data.dictionaries[1] - local charstrings=dictionary.charstrings - local charset=dictionary.charset - local private=dictionary.private or { data={} } - keepcurve=doshapes - version=tversion - stack={} - glyphs=glyphs or {} - strings=data.strings - globals=data.routines or {} - locals=dictionary.subroutines or {} - globalbias,localbias=setbias(globals,locals) - local nominalwidth=private.data.nominalwidthx or 0 - local defaultwidth=private.data.defaultwidthx or 0 - for i=1,#charstrings do - local tab=charstrings[i] - if type(tab)=="string" then - tab=lpegmatch(p_bytes,tab) - end - local index=i-1 - x=0 - y=0 - width=false - r=0 - top=0 - stems=0 - result={} - xmin=0 - xmax=0 - ymin=0 - ymax=0 - checked=false - if trace_charstrings then - report("glyph: %i",index) - report("data: % t",tab) - end - process(tab) - local boundingbox={ round(xmin),round(ymin),round(xmax),round(ymax) } - if width==true or width==false then - width=defaultwidth - else - width=nominalwidth+width - end - local glyph=glyphs[index] - if not glyph then - glyphs[index]={ - segments=doshapes~=false and result or nil, - boundingbox=boundingbox, - width=width, - name=charset[index], - } - else - glyph.segments=doshapes~=false and result or nil - glyph.boundingbox=boundingbox - if not glyph.width then - glyph.width=width - end - if charset and not glyph.name then - glyph.name=charset[index] - end - end - if trace_charstrings then - report("width: %s",tostring(width)) - report("boundingbox: % t",boundingbox) - end - charstrings[i]=nil - end - return glyphs - end - parsecharstring=function(data,dictionary,tab,glyphs,index,doshapes,tversion) - local private=dictionary.private - keepcurve=doshapes - version=tversion - strings=data.strings - locals=dictionary.subroutines or {} - globals=data.routines or {} - globalbias,localbias=setbias(globals,locals) - local nominalwidth=private and private.data.nominalwidthx or 0 - local defaultwidth=private and private.data.defaultwidthx or 0 - if type(tab)=="string" then - tab=lpegmatch(p_bytes,tab) - end - x=0 - y=0 - width=false - r=0 - top=0 - stems=0 - result={} - xmin=0 - xmax=0 - ymin=0 - ymax=0 - checked=false - if trace_charstrings then - report("glyph: %i",index) - report("data: % t",tab) - end - process(tab) - local boundingbox={ xmin,ymin,xmax,ymax } - if width==true or width==false then - width=defaultwidth - else - width=nominalwidth+width - end - index=index-1 - local glyph=glyphs[index] - if not glyph then - glyphs[index]={ - segments=doshapes~=false and result or nil, - boundingbox=boundingbox, - width=width, - name=charset[index], - } - else - glyph.segments=doshapes~=false and result or nil - glyph.boundingbox=boundingbox - if not glyph.width then - glyph.width=width - end - if charset and not glyph.name then - glyph.name=charset[index] - end - end - if trace_charstrings then - report("width: %s",tostring(width)) - report("boundingbox: % t",boundingbox) - end - end - resetcharstrings=function() - result={} - top=0 - stack={} - end -end -local function readglobals(f,data) - local routines=readlengths(f) - for i=1,#routines do - routines[i]=readstring(f,routines[i]) - end - data.routines=routines -end -local function readencodings(f,data) - data.encodings={} -end -local function readcharsets(f,data,dictionary) - local header=data.header - local strings=data.strings - local nofglyphs=data.nofglyphs - local charsetoffset=dictionary.charset - if charsetoffset~=0 then - setposition(f,header.offset+charsetoffset) - local format=readbyte(f) - local charset={ [0]=".notdef" } - dictionary.charset=charset - if format==0 then - for i=1,nofglyphs do - charset[i]=strings[readushort(f)] - end - elseif format==1 or format==2 then - local readcount=format==1 and readbyte or readushort - local i=1 - while i<=nofglyphs do - local sid=readushort(f) - local n=readcount(f) - for s=sid,sid+n do - charset[i]=strings[s] - i=i+1 - if i>nofglyphs then - break - end - end - end - else - report("cff parser: unsupported charset format %a",format) - end - end -end -local function readprivates(f,data) - local header=data.header - local dictionaries=data.dictionaries - local private=dictionaries[1].private - if private then - setposition(f,header.offset+private.offset) - private.data=readstring(f,private.size) - end -end -local function readlocals(f,data,dictionary) - local header=data.header - local private=dictionary.private - if private then - local subroutineoffset=private.data.subroutines - if subroutineoffset~=0 then - setposition(f,header.offset+private.offset+subroutineoffset) - local subroutines=readlengths(f) - for i=1,#subroutines do - subroutines[i]=readstring(f,subroutines[i]) - end - dictionary.subroutines=subroutines - private.data.subroutines=nil - else - dictionary.subroutines={} - end - else - dictionary.subroutines={} - end -end -local function readcharstrings(f,data) - local header=data.header - local dictionaries=data.dictionaries - local dictionary=dictionaries[1] - local type=dictionary.charstringtype - local offset=dictionary.charstrings - if type==2 then - setposition(f,header.offset+offset) - local charstrings=readlengths(f) - local nofglyphs=#charstrings - for i=1,nofglyphs do - charstrings[i]=readstring(f,charstrings[i]) - end - data.nofglyphs=nofglyphs - dictionary.charstrings=charstrings - else - report("unsupported charstr type %i",type) - data.nofglyphs=0 - dictionary.charstrings={} - end -end -local function readcidprivates(f,data) - local header=data.header - local dictionaries=data.dictionaries[1].cid.dictionaries - for i=1,#dictionaries do - local dictionary=dictionaries[i] - local private=dictionary.private - if private then - setposition(f,header.offset+private.offset) - private.data=readstring(f,private.size) - end - end - parseprivates(data,dictionaries) -end -local function readnoselect(f,data,glyphs,doshapes,version) - local dictionaries=data.dictionaries - local dictionary=dictionaries[1] - readglobals(f,data) - readcharstrings(f,data) - readencodings(f,data) - readcharsets(f,data,dictionary) - readprivates(f,data) - parseprivates(data,data.dictionaries) - readlocals(f,data,dictionary) - parsecharstrings(data,glyphs,doshapes,version) - resetcharstrings() -end -readers.parsecharstrings=parsecharstrings -local function readfdselect(f,data,glyphs,doshapes,version) - local header=data.header - local dictionaries=data.dictionaries - local dictionary=dictionaries[1] - local cid=dictionary.cid - local cidselect=cid and cid.fdselect - readglobals(f,data) - readcharstrings(f,data) - readencodings(f,data) - local charstrings=dictionary.charstrings - local fdindex={} - local nofglyphs=data.nofglyphs - local maxindex=-1 - setposition(f,header.offset+cidselect) - local format=readbyte(f) - if format==1 then - for i=0,nofglyphs do - local index=readbyte(i) - fdindex[i]=index - if index>maxindex then - maxindex=index - end - end - elseif format==3 then - local nofranges=readushort(f) - local first=readushort(f) - local index=readbyte(f) - while true do - local last=readushort(f) - if index>maxindex then - maxindex=index - end - for i=first,last do - fdindex[i]=index - end - if last>=nofglyphs then - break - else - first=last+1 - index=readbyte(f) - end - end - else - end - if maxindex>=0 then - local cidarray=cid.fdarray - setposition(f,header.offset+cidarray) - local dictionaries=readlengths(f) - for i=1,#dictionaries do - dictionaries[i]=readstring(f,dictionaries[i]) - end - parsedictionaries(data,dictionaries) - cid.dictionaries=dictionaries - readcidprivates(f,data) - for i=1,#dictionaries do - readlocals(f,data,dictionaries[i]) - end - for i=1,#charstrings do - parsecharstring(data,dictionaries[fdindex[i]+1],charstrings[i],glyphs,i,doshapes,version) - end - resetcharstrings() - end -end -function readers.cff(f,fontdata,specification) - if specification.details then - local datatable=fontdata.tables.cff - if datatable then - local offset=datatable.offset - local glyphs=fontdata.glyphs - if not f then - report("invalid filehandle") - return - end - if offset then - setposition(f,offset) - end - local header=readheader(f) - if header.major>1 then - report("version mismatch") - return - end - local names=readfontnames(f) - local dictionaries=readtopdictionaries(f) - local strings=readstrings(f) - local data={ - header=header, - names=names, - dictionaries=dictionaries, - strings=strings, - nofglyphs=fontdata.nofglyphs, - } - parsedictionaries(data,data.dictionaries) - local d=dictionaries[1] - local c=d.cid - fontdata.cffinfo={ - familynamename=d.familyname, - fullname=d.fullname, - boundingbox=d.boundingbox, - weight=d.weight, - italicangle=d.italicangle, - underlineposition=d.underlineposition, - underlinethickness=d.underlinethickness, - monospaced=d.monospaced, - } - fontdata.cidinfo=c and { - registry=c.registry, - ordering=c.ordering, - supplement=c.supplement, - } - if not specification.glyphs then - else - local cid=d.cid - if cid and cid.fdselect then - readfdselect(f,data,glyphs,specification.shapes or false) - else - readnoselect(f,data,glyphs,specification.shapes or false) - end - end - end - end -end - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['font-ttf']={ - version=1.001, - comment="companion to font-ini.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local next,type,unpack=next,type,unpack -local bittest=bit32.btest -local sqrt=math.sqrt -local report=logs.reporter("otf reader","ttf") -local readers=fonts.handlers.otf.readers -local streamreader=readers.streamreader -local setposition=streamreader.setposition -local getposition=streamreader.getposition -local skipbytes=streamreader.skip -local readbyte=streamreader.readcardinal1 -local readushort=streamreader.readcardinal2 -local readulong=streamreader.readcardinal4 -local readchar=streamreader.readinteger1 -local readshort=streamreader.readinteger2 -local read2dot14=streamreader.read2dot14 -local function mergecomposites(glyphs,shapes) - local function merge(index,shape,components) - local contours={} - local nofcontours=0 - for i=1,#components do - local component=components[i] - local subindex=component.index - local subshape=shapes[subindex] - local subcontours=subshape.contours - if not subcontours then - local subcomponents=subshape.components - if subcomponents then - subcontours=merge(subindex,subshape,subcomponents) - end - end - if subcontours then - local matrix=component.matrix - local xscale=matrix[1] - local xrotate=matrix[2] - local yrotate=matrix[3] - local yscale=matrix[4] - local xoffset=matrix[5] - local yoffset=matrix[6] - for i=1,#subcontours do - local points=subcontours[i] - local result={} - for i=1,#points do - local p=points[i] - local x=p[1] - local y=p[2] - result[i]={ - xscale*x+xrotate*y+xoffset, - yscale*y+yrotate*x+yoffset, - p[3] - } - end - nofcontours=nofcontours+1 - contours[nofcontours]=result - end - else - report("missing contours composite %s, component %s of %s, glyph %s",index,i,#components,subindex) - end - end - shape.contours=contours - shape.components=nil - return contours - end - for index=1,#glyphs do - local shape=shapes[index] - local components=shape.components - if components then - merge(index,shape,components) - end - end -end -local function readnothing(f,nofcontours) - return { - type="nothing", - } -end -local function curveto(m_x,m_y,l_x,l_y,r_x,r_y) - return { - l_x+2/3*(m_x-l_x),l_y+2/3*(m_y-l_y), - r_x+2/3*(m_x-r_x),r_y+2/3*(m_y-r_y), - r_x,r_y,"c" - } -end -local function contours2outlines(glyphs,shapes) - local quadratic=true - for index=1,#glyphs do - local glyph=glyphs[index] - local shape=shapes[index] - local contours=shape.contours - if contours then - local nofcontours=#contours - local segments={} - local nofsegments=0 - glyph.segments=segments - if nofcontours>0 then - for i=1,nofcontours do - local contour=contours[i] - local nofcontour=#contour - if nofcontour>0 then - local first_pt=contour[1] - local first_on=first_pt[3] - if nofcontour==1 then - first_pt[3]="m" - nofsegments=nofsegments+1 - segments[nofsegments]=first_pt - else - local first_on=first_pt[3] - local last_pt=contour[nofcontour] - local last_on=last_pt[3] - local start=1 - local control_pt=false - if first_on then - start=2 - else - if last_on then - first_pt=last_pt - else - first_pt={ (first_pt[1]+last_pt[1])/2,(first_pt[2]+last_pt[2])/2,false } - end - control_pt=first_pt - end - nofsegments=nofsegments+1 - segments[nofsegments]={ first_pt[1],first_pt[2],"m" } - local previous_pt=first_pt - for i=start,nofcontour do - local current_pt=contour[i] - local current_on=current_pt[3] - local previous_on=previous_pt[3] - if previous_on then - if current_on then - nofsegments=nofsegments+1 - segments[nofsegments]={ current_pt[1],current_pt[2],"l" } - else - control_pt=current_pt - end - elseif current_on then - local ps=segments[nofsegments] - nofsegments=nofsegments+1 - if quadratic then - segments[nofsegments]={ control_pt[1],control_pt[2],current_pt[1],current_pt[2],"q" } - else - local p=segments[nofsegments-1] local n=#p - segments[nofsegments]=curveto(control_pt[1],control_pt[2],p[n-2],p[n-1],current_pt[1],current_pt[2]) - end - control_pt=false - else - nofsegments=nofsegments+1 - local halfway_x=(previous_pt[1]+current_pt[1])/2 - local halfway_y=(previous_pt[2]+current_pt[2])/2 - if quadratic then - segments[nofsegments]={ control_pt[1],control_pt[2],halfway_x,halfway_y,"q" } - else - local p=segments[nofsegments-1] local n=#p - segments[nofsegments]=curveto(control_pt[1],control_pt[2],p[n-2],p[n-1],halfway_x,halfway_y) - end - control_pt=current_pt - end - previous_pt=current_pt - end - if first_pt==last_pt then - else - nofsegments=nofsegments+1 - if not control_pt then - segments[nofsegments]={ first_pt[1],first_pt[2],"l" } - elseif quadratic then - segments[nofsegments]={ control_pt[1],control_pt[2],first_pt[1],first_pt[2],"q" } - else - local p=last_pt local n=#p - segments[nofsegments]=curveto(control_pt[1],control_pt[2],p[n-2],p[n-1],first_pt[1],first_pt[2]) - end - end - end - end - end - end - end - end -end -local function readglyph(f,nofcontours) - local points={} - local endpoints={} - local instructions={} - local flags={} - for i=1,nofcontours do - endpoints[i]=readshort(f)+1 - end - local nofpoints=endpoints[nofcontours] - local nofinstructions=readushort(f) - skipbytes(f,nofinstructions) - local i=1 - while i<=nofpoints do - local flag=readbyte(f) - flags[i]=flag - if bittest(flag,0x0008) then - for j=1,readbyte(f) do - i=i+1 - flags[i]=flag - end - end - i=i+1 - end - local x=0 - for i=1,nofpoints do - local flag=flags[i] - local short=bittest(flag,0x0002) - local same=bittest(flag,0x0010) - if short then - if same then - x=x+readbyte(f) - else - x=x-readbyte(f) - end - elseif same then - else - x=x+readshort(f) - end - points[i]={ x,y,bittest(flag,0x0001) } - end - local y=0 - for i=1,nofpoints do - local flag=flags[i] - local short=bittest(flag,0x0004) - local same=bittest(flag,0x0020) - if short then - if same then - y=y+readbyte(f) - else - y=y-readbyte(f) - end - elseif same then - else - y=y+readshort(f) - end - points[i][2]=y - end - local first=1 - for i=1,#endpoints do - local last=endpoints[i] - endpoints[i]={ unpack(points,first,last) } - first=last+1 - end - return { - type="glyph", - contours=endpoints, - } -end -local function readcomposite(f) - local components={} - local nofcomponents=0 - local instructions=false - while true do - local flags=readushort(f) - local index=readushort(f) - local f_xyarg=bittest(flags,0x0002) - local f_offset=bittest(flags,0x0800) - local xscale=1 - local xrotate=0 - local yrotate=0 - local yscale=1 - local xoffset=0 - local yoffset=0 - local base=false - local reference=false - if f_xyarg then - if bittest(flags,0x0001) then - xoffset=readshort(f) - yoffset=readshort(f) - else - xoffset=readchar(f) - yoffset=readchar(f) - end - else - if bittest(flags,0x0001) then - base=readshort(f) - reference=readshort(f) - else - base=readchar(f) - reference=readchar(f) - end - end - if bittest(flags,0x0008) then - xscale=read2dot14(f) - yscale=xscale - if f_xyarg and f_offset then - xoffset=xoffset*xscale - yoffset=yoffset*yscale - end - elseif bittest(flags,0x0040) then - xscale=read2dot14(f) - yscale=read2dot14(f) - if f_xyarg and f_offset then - xoffset=xoffset*xscale - yoffset=yoffset*yscale - end - elseif bittest(flags,0x0080) then - xscale=read2dot14(f) - xrotate=read2dot14(f) - yrotate=read2dot14(f) - yscale=read2dot14(f) - if f_xyarg and f_offset then - xoffset=xoffset*sqrt(xscale^2+xrotate^2) - yoffset=yoffset*sqrt(yrotate^2+yscale^2) - end - end - nofcomponents=nofcomponents+1 - components[nofcomponents]={ - index=index, - usemine=bittest(flags,0x0200), - round=bittest(flags,0x0006), - base=base, - reference=reference, - matrix={ xscale,xrotate,yrotate,yscale,xoffset,yoffset }, - } - if bittest(flags,0x0100) then - instructions=true - end - if not bittest(flags,0x0020) then - break - end - end - return { - type="composite", - components=components, - } -end -function readers.loca(f,fontdata,specification) - if specification.glyphs then - local datatable=fontdata.tables.loca - if datatable then - local offset=fontdata.tables.glyf.offset - local format=fontdata.fontheader.indextolocformat - local locations={} - setposition(f,datatable.offset) - if format==1 then - local nofglyphs=datatable.length/4-1 - -1 - for i=0,nofglyphs do - locations[i]=offset+readulong(f) - end - fontdata.nofglyphs=nofglyphs - else - local nofglyphs=datatable.length/2-1 - -1 - for i=0,nofglyphs do - locations[i]=offset+readushort(f)*2 - end - fontdata.nofglyphs=nofglyphs - end - fontdata.locations=locations - end - end -end -function readers.glyf(f,fontdata,specification) - if specification.glyphs then - local datatable=fontdata.tables.glyf - if datatable then - local locations=fontdata.locations - if locations then - local glyphs=fontdata.glyphs - local nofglyphs=fontdata.nofglyphs - local filesize=fontdata.filesize - local nothing={ 0,0,0,0 } - local shapes={} - local loadshapes=specification.shapes - for index=0,nofglyphs do - local location=locations[index] - if location>=filesize then - report("discarding %s glyphs due to glyph location bug",nofglyphs-index+1) - fontdata.nofglyphs=index-1 - fontdata.badfont=true - break - elseif location>0 then - setposition(f,location) - local nofcontours=readshort(f) - glyphs[index].boundingbox={ - readshort(f), - readshort(f), - readshort(f), - readshort(f), - } - if not loadshapes then - elseif nofcontours==0 then - shapes[index]=readnothing(f,nofcontours) - elseif nofcontours>0 then - shapes[index]=readglyph(f,nofcontours) - else - shapes[index]=readcomposite(f,nofcontours) - end - else - if loadshapes then - shapes[index]={} - end - glyphs[index].boundingbox=nothing - end - end - if loadshapes then - mergecomposites(glyphs,shapes) - contours2outlines(glyphs,shapes) - end - end - end - end -end - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['font-dsp']={ - version=1.001, - comment="companion to font-ini.mkiv", - 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 bittest=bit32.btest -local rshift=bit32.rshift -local concat=table.concat -local lower=string.lower -local copy=table.copy -local sub=string.sub -local strip=string.strip -local tohash=table.tohash -local reversed=table.reversed -local setmetatableindex=table.setmetatableindex -local formatters=string.formatters -local sortedkeys=table.sortedkeys -local sortedhash=table.sortedhash -local report=logs.reporter("otf reader") -local readers=fonts.handlers.otf.readers -local streamreader=readers.streamreader -local setposition=streamreader.setposition -local getposition=streamreader.getposition -local skipshort=streamreader.skipshort -local readushort=streamreader.readcardinal2 -local readulong=streamreader.readcardinal4 -local readshort=streamreader.readinteger2 -local readfword=readshort -local readstring=streamreader.readstring -local readtag=streamreader.readtag -local readbytes=streamreader.readbytes -local gsubhandlers={} -local gposhandlers={} -local lookupidoffset=-1 -local classes={ - "base", - "ligature", - "mark", - "component", -} -local gsubtypes={ - "single", - "multiple", - "alternate", - "ligature", - "context", - "chainedcontext", - "extension", - "reversechainedcontextsingle", -} -local gpostypes={ - "single", - "pair", - "cursive", - "marktobase", - "marktoligature", - "marktomark", - "context", - "chainedcontext", - "extension", -} -local chaindirections={ - context=0, - chainedcontext=1, - reversechainedcontextsingle=-1, -} -local lookupnames={ - gsub={ - single="gsub_single", - multiple="gsub_multiple", - alternate="gsub_alternate", - ligature="gsub_ligature", - context="gsub_context", - chainedcontext="gsub_contextchain", - reversechainedcontextsingle="gsub_reversecontextchain", - }, - gpos={ - single="gpos_single", - pair="gpos_pair", - cursive="gpos_cursive", - marktobase="gpos_mark2base", - marktoligature="gpos_mark2ligature", - marktomark="gpos_mark2mark", - context="gpos_context", - chainedcontext="gpos_contextchain", - } -} -local lookupflags=setmetatableindex(function(t,k) - local v={ - bittest(k,0x0008) and true or false, - bittest(k,0x0004) and true or false, - bittest(k,0x0002) and true or false, - bittest(k,0x0001) and true or false, - } - t[k]=v - return v -end) -local function readcoverage(f,offset,simple) - setposition(f,offset) - local coverageformat=readushort(f) - local coverage={} - if coverageformat==1 then - local nofcoverage=readushort(f) - if simple then - for i=1,nofcoverage do - coverage[i]=readushort(f) - end - else - for i=0,nofcoverage-1 do - coverage[readushort(f)]=i - end - end - elseif coverageformat==2 then - local nofranges=readushort(f) - local n=simple and 1 or 0 - for i=1,nofranges do - local firstindex=readushort(f) - local lastindex=readushort(f) - local coverindex=readushort(f) - if simple then - for i=firstindex,lastindex do - coverage[n]=i - n=n+1 - end - else - for i=firstindex,lastindex do - coverage[i]=n - n=n+1 - end - end - end - else - report("unknown coverage format %a ",coverageformat) - end - return coverage -end -local function readclassdef(f,offset,preset) - setposition(f,offset) - local classdefformat=readushort(f) - local classdef={} - if type(preset)=="number" then - for k=0,preset-1 do - classdef[k]=1 - end - end - if classdefformat==1 then - local index=readushort(f) - local nofclassdef=readushort(f) - for i=1,nofclassdef do - classdef[index]=readushort(f)+1 - index=index+1 - end - elseif classdefformat==2 then - local nofranges=readushort(f) - local n=0 - for i=1,nofranges do - local firstindex=readushort(f) - local lastindex=readushort(f) - local class=readushort(f)+1 - for i=firstindex,lastindex do - classdef[i]=class - end - end - else - report("unknown classdef format %a ",classdefformat) - end - if type(preset)=="table" then - for k in next,preset do - if not classdef[k] then - classdef[k]=1 - end - end - end - return classdef -end -local function classtocoverage(defs) - if defs then - local list={} - for index,class in next,defs do - local c=list[class] - if c then - c[#c+1]=index - else - list[class]={ index } - end - end - return list - end -end -local function readposition(f,format) - if format==0 then - return nil - end - local x=bittest(format,0x0001) and readshort(f) or 0 - local y=bittest(format,0x0002) and readshort(f) or 0 - local h=bittest(format,0x0004) and readshort(f) or 0 - local v=bittest(format,0x0008) and readshort(f) or 0 - if x==0 and y==0 and h==0 and v==0 then - return nil - else - return { x,y,h,v } - end -end -local function readanchor(f,offset) - if not offset or offset==0 then - return nil - end - setposition(f,offset) - local format=readshort(f) - if format==0 then - report("invalid anchor format %i @ position %i",format,offset) - return false - elseif format>3 then - report("unsupported anchor format %i @ position %i",format,offset) - return false - end - return { readshort(f),readshort(f) } -end -local function readfirst(f,offset) - if offset then - setposition(f,offset) - end - return { readushort(f) } -end -local function readarray(f,offset,first) - if offset then - setposition(f,offset) - end - local n=readushort(f) - if first then - local t={ first } - for i=2,n do - t[i]=readushort(f) - end - return t,n - elseif n>0 then - local t={} - for i=1,n do - t[i]=readushort(f) - end - return t,n - end -end -local function readcoveragearray(f,offset,t,simple) - if not t then - return nil - end - local n=#t - if n==0 then - return nil - end - for i=1,n do - t[i]=readcoverage(f,offset+t[i],simple) - end - return t -end -local function covered(subset,all) - local used,u - for i=1,#subset do - local s=subset[i] - if all[s] then - if used then - u=u+1 - used[u]=s - else - u=1 - used={ s } - end - end - end - return used -end -local function readlookuparray(f,noflookups,nofcurrent) - local lookups={} - if noflookups>0 then - local length=0 - for i=1,noflookups do - local index=readushort(f)+1 - if index>length then - length=index - end - lookups[index]=readushort(f)+1 - end - for index=1,length do - if not lookups[index] then - lookups[index]=false - end - end - end - return lookups -end -local function unchainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,what) - local tableoffset=lookupoffset+offset - setposition(f,tableoffset) - local subtype=readushort(f) - if subtype==1 then - local coverage=readushort(f) - local subclasssets=readarray(f) - local rules={} - if subclasssets then - coverage=readcoverage(f,tableoffset+coverage,true) - for i=1,#subclasssets do - local offset=subclasssets[i] - if offset>0 then - local firstcoverage=coverage[i] - local rulesoffset=tableoffset+offset - local subclassrules=readarray(f,rulesoffset) - for rule=1,#subclassrules do - setposition(f,rulesoffset+subclassrules[rule]) - local nofcurrent=readushort(f) - local noflookups=readushort(f) - local current={ { firstcoverage } } - for i=2,nofcurrent do - current[i]={ readushort(f) } - end - local lookups=readlookuparray(f,noflookups,nofcurrent) - rules[#rules+1]={ - current=current, - lookups=lookups - } - end - end - end - else - report("empty subclassset in %a subtype %i","unchainedcontext",subtype) - end - return { - format="glyphs", - rules=rules, - } - elseif subtype==2 then - local coverage=readushort(f) - local currentclassdef=readushort(f) - local subclasssets=readarray(f) - local rules={} - if subclasssets then - coverage=readcoverage(f,tableoffset+coverage) - currentclassdef=readclassdef(f,tableoffset+currentclassdef,coverage) - local currentclasses=classtocoverage(currentclassdef,fontdata.glyphs) - for class=1,#subclasssets do - local offset=subclasssets[class] - if offset>0 then - local firstcoverage=currentclasses[class] - if firstcoverage then - firstcoverage=covered(firstcoverage,coverage) - if firstcoverage then - local rulesoffset=tableoffset+offset - local subclassrules=readarray(f,rulesoffset) - for rule=1,#subclassrules do - setposition(f,rulesoffset+subclassrules[rule]) - local nofcurrent=readushort(f) - local noflookups=readushort(f) - local current={ firstcoverage } - for i=2,nofcurrent do - current[i]=currentclasses[readushort(f)+1] - end - local lookups=readlookuparray(f,noflookups,nofcurrent) - rules[#rules+1]={ - current=current, - lookups=lookups - } - end - else - report("no coverage") - end - else - report("no coverage class") - end - end - end - else - report("empty subclassset in %a subtype %i","unchainedcontext",subtype) - end - return { - format="class", - rules=rules, - } - elseif subtype==3 then - local current=readarray(f) - local noflookups=readushort(f) - local lookups=readlookuparray(f,noflookups,#current) - current=readcoveragearray(f,tableoffset,current,true) - return { - format="coverage", - rules={ - { - current=current, - lookups=lookups, - } - } - } - else - report("unsupported subtype %a in %a %s",subtype,"unchainedcontext",what) - end -end -local function chainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,what) - local tableoffset=lookupoffset+offset - setposition(f,tableoffset) - local subtype=readushort(f) - if subtype==1 then - local coverage=readushort(f) - local subclasssets=readarray(f) - local rules={} - if subclasssets then - coverage=readcoverage(f,tableoffset+coverage,true) - for i=1,#subclasssets do - local offset=subclasssets[i] - if offset>0 then - local firstcoverage=coverage[i] - local rulesoffset=tableoffset+offset - local subclassrules=readarray(f,rulesoffset) - for rule=1,#subclassrules do - setposition(f,rulesoffset+subclassrules[rule]) - local nofbefore=readushort(f) - local before - if nofbefore>0 then - before={} - for i=1,nofbefore do - before[i]={ readushort(f) } - end - end - local nofcurrent=readushort(f) - local current={ { firstcoverage } } - for i=2,nofcurrent do - current[i]={ readushort(f) } - end - local nofafter=readushort(f) - local after - if nofafter>0 then - after={} - for i=1,nofafter do - after[i]={ readushort(f) } - end - end - local noflookups=readushort(f) - local lookups=readlookuparray(f,noflookups,nofcurrent) - rules[#rules+1]={ - before=before, - current=current, - after=after, - lookups=lookups, - } - end - end - end - else - report("empty subclassset in %a subtype %i","chainedcontext",subtype) - end - return { - format="glyphs", - rules=rules, - } - elseif subtype==2 then - local coverage=readushort(f) - local beforeclassdef=readushort(f) - local currentclassdef=readushort(f) - local afterclassdef=readushort(f) - local subclasssets=readarray(f) - local rules={} - if subclasssets then - local coverage=readcoverage(f,tableoffset+coverage) - local beforeclassdef=readclassdef(f,tableoffset+beforeclassdef,nofglyphs) - local currentclassdef=readclassdef(f,tableoffset+currentclassdef,coverage) - local afterclassdef=readclassdef(f,tableoffset+afterclassdef,nofglyphs) - local beforeclasses=classtocoverage(beforeclassdef,fontdata.glyphs) - local currentclasses=classtocoverage(currentclassdef,fontdata.glyphs) - local afterclasses=classtocoverage(afterclassdef,fontdata.glyphs) - for class=1,#subclasssets do - local offset=subclasssets[class] - if offset>0 then - local firstcoverage=currentclasses[class] - if firstcoverage then - firstcoverage=covered(firstcoverage,coverage) - if firstcoverage then - local rulesoffset=tableoffset+offset - local subclassrules=readarray(f,rulesoffset) - for rule=1,#subclassrules do - setposition(f,rulesoffset+subclassrules[rule]) - local nofbefore=readushort(f) - local before - if nofbefore>0 then - before={} - for i=1,nofbefore do - before[i]=beforeclasses[readushort(f)+1] - end - end - local nofcurrent=readushort(f) - local current={ firstcoverage } - for i=2,nofcurrent do - current[i]=currentclasses[readushort(f)+1] - end - local nofafter=readushort(f) - local after - if nofafter>0 then - after={} - for i=1,nofafter do - after[i]=afterclasses[readushort(f)+1] - end - end - local noflookups=readushort(f) - local lookups=readlookuparray(f,noflookups,nofcurrent) - rules[#rules+1]={ - before=before, - current=current, - after=after, - lookups=lookups, - } - end - else - report("no coverage") - end - else - report("class is not covered") - end - end - end - else - report("empty subclassset in %a subtype %i","chainedcontext",subtype) - end - return { - format="class", - rules=rules, - } - elseif subtype==3 then - local before=readarray(f) - local current=readarray(f) - local after=readarray(f) - local noflookups=readushort(f) - local lookups=readlookuparray(f,noflookups,#current) - before=readcoveragearray(f,tableoffset,before,true) - current=readcoveragearray(f,tableoffset,current,true) - after=readcoveragearray(f,tableoffset,after,true) - return { - format="coverage", - rules={ - { - before=before, - current=current, - after=after, - lookups=lookups, - } - } - } - else - report("unsupported subtype %a in %a %s",subtype,"chainedcontext",what) - end -end -local function extension(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,types,handlers,what) - local tableoffset=lookupoffset+offset - setposition(f,tableoffset) - local subtype=readushort(f) - if subtype==1 then - local lookuptype=types[readushort(f)] - local faroffset=readulong(f) - local handler=handlers[lookuptype] - if handler then - return handler(f,fontdata,lookupid,tableoffset+faroffset,0,glyphs,nofglyphs),lookuptype - else - report("no handler for lookuptype %a subtype %a in %s %s",lookuptype,subtype,what,"extension") - end - else - report("unsupported subtype %a in %s %s",subtype,what,"extension") - end -end -function gsubhandlers.single(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs) - local tableoffset=lookupoffset+offset - setposition(f,tableoffset) - local subtype=readushort(f) - if subtype==1 then - local coverage=readushort(f) - local delta=readshort(f) - local coverage=readcoverage(f,tableoffset+coverage) - for index in next,coverage do - local newindex=index+delta - if index>nofglyphs or newindex>nofglyphs then - report("invalid index in %s format %i: %i -> %i (max %i)","single",subtype,index,newindex,nofglyphs) - coverage[index]=nil - else - coverage[index]=newindex - end - end - return { - coverage=coverage - } - elseif subtype==2 then - local coverage=readushort(f) - local nofreplacements=readushort(f) - local replacements={} - for i=1,nofreplacements do - replacements[i]=readushort(f) - end - local coverage=readcoverage(f,tableoffset+coverage) - for index,newindex in next,coverage do - newindex=newindex+1 - if index>nofglyphs or newindex>nofglyphs then - report("invalid index in %s format %i: %i -> %i (max %i)","single",subtype,index,newindex,nofglyphs) - coverage[index]=nil - else - coverage[index]=replacements[newindex] - end - end - return { - coverage=coverage - } - else - report("unsupported subtype %a in %a substitution",subtype,"single") - end -end -local function sethandler(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,what) - local tableoffset=lookupoffset+offset - setposition(f,tableoffset) - local subtype=readushort(f) - if subtype==1 then - local coverage=readushort(f) - local nofsequence=readushort(f) - local sequences={} - for i=1,nofsequence do - sequences[i]=readushort(f) - end - for i=1,nofsequence do - setposition(f,tableoffset+sequences[i]) - local n=readushort(f) - local s={} - for i=1,n do - s[i]=readushort(f) - end - sequences[i]=s - end - local coverage=readcoverage(f,tableoffset+coverage) - for index,newindex in next,coverage do - newindex=newindex+1 - if index>nofglyphs or newindex>nofglyphs then - report("invalid index in %s format %i: %i -> %i (max %i)",what,subtype,index,newindex,nofglyphs) - coverage[index]=nil - else - coverage[index]=sequences[newindex] - end - end - return { - coverage=coverage - } - else - report("unsupported subtype %a in %a substitution",subtype,what) - end -end -function gsubhandlers.multiple(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs) - return sethandler(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,"multiple") -end -function gsubhandlers.alternate(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs) - return sethandler(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,"alternate") -end -function gsubhandlers.ligature(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs) - local tableoffset=lookupoffset+offset - setposition(f,tableoffset) - local subtype=readushort(f) - if subtype==1 then - local coverage=readushort(f) - local nofsets=readushort(f) - local ligatures={} - for i=1,nofsets do - ligatures[i]=readushort(f) - end - for i=1,nofsets do - local offset=lookupoffset+offset+ligatures[i] - setposition(f,offset) - local n=readushort(f) - local l={} - for i=1,n do - l[i]=offset+readushort(f) - end - ligatures[i]=l - end - local coverage=readcoverage(f,tableoffset+coverage) - for index,newindex in next,coverage do - local hash={} - local ligatures=ligatures[newindex+1] - for i=1,#ligatures do - local offset=ligatures[i] - setposition(f,offset) - local lig=readushort(f) - local cnt=readushort(f) - local hsh=hash - for i=2,cnt do - local c=readushort(f) - local h=hsh[c] - if not h then - h={} - hsh[c]=h - end - hsh=h - end - hsh.ligature=lig - end - coverage[index]=hash - end - return { - coverage=coverage - } - else - report("unsupported subtype %a in %a substitution",subtype,"ligature") - end -end -function gsubhandlers.context(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs) - return unchainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,"substitution"),"context" -end -function gsubhandlers.chainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs) - return chainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,"substitution"),"chainedcontext" -end -function gsubhandlers.extension(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs) - return extension(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,gsubtypes,gsubhandlers,"substitution") -end -function gsubhandlers.reversechainedcontextsingle(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs) - local tableoffset=lookupoffset+offset - setposition(f,tableoffset) - local subtype=readushort(f) - if subtype==1 then - local current=readfirst(f) - local before=readarray(f) - local after=readarray(f) - local replacements=readarray(f) - current=readcoveragearray(f,tableoffset,current,true) - before=readcoveragearray(f,tableoffset,before,true) - after=readcoveragearray(f,tableoffset,after,true) - return { - coverage={ - format="reversecoverage", - before=before, - current=current, - after=after, - replacements=replacements, - } - },"reversechainedcontextsingle" - else - report("unsupported subtype %a in %a substitution",subtype,"reversechainedcontextsingle") - end -end -local function readpairsets(f,tableoffset,sets,format1,format2) - local done={} - for i=1,#sets do - local offset=sets[i] - local reused=done[offset] - if not reused then - setposition(f,tableoffset+offset) - local n=readushort(f) - reused={} - for i=1,n do - reused[i]={ - readushort(f), - readposition(f,format1), - readposition(f,format2) - } - end - done[offset]=reused - end - sets[i]=reused - end - return sets -end -local function readpairclasssets(f,nofclasses1,nofclasses2,format1,format2) - local classlist1={} - for i=1,nofclasses1 do - local classlist2={} - classlist1[i]=classlist2 - for j=1,nofclasses2 do - local one=readposition(f,format1) - local two=readposition(f,format2) - if one or two then - classlist2[j]={ one,two } - else - classlist2[j]=false - end - end - end - return classlist1 -end -function gposhandlers.single(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs) - local tableoffset=lookupoffset+offset - setposition(f,tableoffset) - local subtype=readushort(f) - if subtype==1 then - local coverage=readushort(f) - local format=readushort(f) - local value=readposition(f,format) - local coverage=readcoverage(f,tableoffset+coverage) - for index,newindex in next,coverage do - coverage[index]=value - end - return { - format="pair", - coverage=coverage - } - elseif subtype==2 then - local coverage=readushort(f) - local format=readushort(f) - local values={} - local nofvalues=readushort(f) - for i=1,nofvalues do - values[i]=readposition(f,format) - end - local coverage=readcoverage(f,tableoffset+coverage) - for index,newindex in next,coverage do - coverage[index]=values[newindex+1] - end - return { - format="pair", - coverage=coverage - } - else - report("unsupported subtype %a in %a positioning",subtype,"single") - end -end -function gposhandlers.pair(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs) - local tableoffset=lookupoffset+offset - setposition(f,tableoffset) - local subtype=readushort(f) - if subtype==1 then - local coverage=readushort(f) - local format1=readushort(f) - local format2=readushort(f) - local sets=readarray(f) - sets=readpairsets(f,tableoffset,sets,format1,format2) - coverage=readcoverage(f,tableoffset+coverage) - for index,newindex in next,coverage do - local set=sets[newindex+1] - local hash={} - for i=1,#set do - local value=set[i] - if value then - local other=value[1] - local first=value[2] - local second=value[3] - if first or second then - hash[other]={ first,second } - else - hash[other]=nil - end - end - end - coverage[index]=hash - end - return { - format="pair", - coverage=coverage - } - elseif subtype==2 then - local coverage=readushort(f) - local format1=readushort(f) - local format2=readushort(f) - local classdef1=readushort(f) - local classdef2=readushort(f) - local nofclasses1=readushort(f) - local nofclasses2=readushort(f) - local classlist=readpairclasssets(f,nofclasses1,nofclasses2,format1,format2) - coverage=readcoverage(f,tableoffset+coverage) - classdef1=readclassdef(f,tableoffset+classdef1,coverage) - classdef2=readclassdef(f,tableoffset+classdef2,nofglyphs) - local usedcoverage={} - for g1,c1 in next,classdef1 do - if coverage[g1] then - local l1=classlist[c1] - if l1 then - local hash={} - for paired,class in next,classdef2 do - local offsets=l1[class] - if offsets then - local first=offsets[1] - local second=offsets[2] - if first or second then - hash[paired]={ first,second } - else - end - end - end - usedcoverage[g1]=hash - end - end - end - return { - format="pair", - coverage=usedcoverage - } - elseif subtype==3 then - report("yet unsupported subtype %a in %a positioning",subtype,"pair") - else - report("unsupported subtype %a in %a positioning",subtype,"pair") - end -end -function gposhandlers.cursive(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs) - local tableoffset=lookupoffset+offset - setposition(f,tableoffset) - local subtype=readushort(f) - if subtype==1 then - local coverage=tableoffset+readushort(f) - local nofrecords=readushort(f) - local records={} - for i=1,nofrecords do - local entry=readushort(f) - local exit=readushort(f) - records[i]={ - entry=entry~=0 and (tableoffset+entry) or false, - exit=exit~=0 and (tableoffset+exit ) or false, - } - end - coverage=readcoverage(f,coverage) - for i=1,nofrecords do - local r=records[i] - records[i]={ - 1, - readanchor(f,r.entry) or nil, - readanchor(f,r.exit ) or nil, - } - end - for index,newindex in next,coverage do - coverage[index]=records[newindex+1] - end - return { - coverage=coverage - } - else - report("unsupported subtype %a in %a positioning",subtype,"cursive") - end -end -local function handlemark(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,ligature) - local tableoffset=lookupoffset+offset - setposition(f,tableoffset) - local subtype=readushort(f) - if subtype==1 then - local markcoverage=tableoffset+readushort(f) - local basecoverage=tableoffset+readushort(f) - local nofclasses=readushort(f) - local markoffset=tableoffset+readushort(f) - local baseoffset=tableoffset+readushort(f) - local markcoverage=readcoverage(f,markcoverage) - local basecoverage=readcoverage(f,basecoverage,true) - setposition(f,markoffset) - local markclasses={} - local nofmarkclasses=readushort(f) - local lastanchor=fontdata.lastanchor or 0 - local usedanchors={} - for i=1,nofmarkclasses do - local class=readushort(f)+1 - local offset=readushort(f) - if offset==0 then - markclasses[i]=false - else - markclasses[i]={ class,markoffset+offset } - end - usedanchors[class]=true - end - for i=1,nofmarkclasses do - local mc=markclasses[i] - if mc then - mc[2]=readanchor(f,mc[2]) - end - end - setposition(f,baseoffset) - local nofbaserecords=readushort(f) - local baserecords={} - if ligature then - for i=1,nofbaserecords do - local offset=readushort(f) - if offset==0 then - baserecords[i]=false - else - baserecords[i]=baseoffset+offset - end - end - for i=1,nofbaserecords do - local recordoffset=baserecords[i] - if recordoffset then - setposition(f,recordoffset) - local nofcomponents=readushort(f) - local components={} - for i=1,nofcomponents do - local classes={} - for i=1,nofclasses do - local offset=readushort(f) - if offset~=0 then - classes[i]=recordoffset+offset - else - classes[i]=false - end - end - components[i]=classes - end - baserecords[i]=components - end - end - local baseclasses={} - for i=1,nofclasses do - baseclasses[i]={} - end - for i=1,nofbaserecords do - local components=baserecords[i] - if components then - local b=basecoverage[i] - for c=1,#components do - local classes=components[c] - if classes then - for i=1,nofclasses do - local anchor=readanchor(f,classes[i]) - local bclass=baseclasses[i] - local bentry=bclass[b] - if bentry then - bentry[c]=anchor - else - bclass[b]={ [c]=anchor } - end - end - end - end - end - end - for index,newindex in next,markcoverage do - markcoverage[index]=markclasses[newindex+1] or nil - end - return { - format="ligature", - baseclasses=baseclasses, - coverage=markcoverage, - } - else - for i=1,nofbaserecords do - local r={} - for j=1,nofclasses do - local offset=readushort(f) - if offset==0 then - r[j]=false - else - r[j]=baseoffset+offset - end - end - baserecords[i]=r - end - local baseclasses={} - for i=1,nofclasses do - baseclasses[i]={} - end - for i=1,nofbaserecords do - local r=baserecords[i] - local b=basecoverage[i] - for j=1,nofclasses do - baseclasses[j][b]=readanchor(f,r[j]) - end - end - for index,newindex in next,markcoverage do - markcoverage[index]=markclasses[newindex+1] or nil - end - return { - format="base", - baseclasses=baseclasses, - coverage=markcoverage, - } - end - else - report("unsupported subtype %a in",subtype) - end -end -function gposhandlers.marktobase(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs) - return handlemark(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs) -end -function gposhandlers.marktoligature(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs) - return handlemark(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,true) -end -function gposhandlers.marktomark(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs) - return handlemark(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs) -end -function gposhandlers.context(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs) - return unchainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,"positioning"),"context" -end -function gposhandlers.chainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs) - return chainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,"positioning"),"chainedcontext" -end -function gposhandlers.extension(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs) - return extension(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,gpostypes,gposhandlers,"positioning") -end -do - local plugins={} - function plugins.size(f,fontdata,tableoffset,feature) - if fontdata.designsize then - else - local function check(offset) - setposition(f,offset) - local designsize=readushort(f) - if designsize>0 then - local fontstyle=readushort(f) - local guimenuid=readushort(f) - local minsize=readushort(f) - local maxsize=readushort(f) - if minsize==0 and maxsize==0 and fontstyleid==0 and guimenuid==0 then - minsize=designsize - maxsize=designsize - end - if designsize>=minsize and designsize<=maxsize then - return minsize,maxsize,designsize - end - end - end - local minsize,maxsize,designsize=check(tableoffset+feature.offset+feature.parameters) - if not designsize then - minsize,maxsize,designsize=check(tableoffset+feature.parameters) - if designsize then - report("bad size feature in %a, falling back to wrong offset",fontdata.filename or "?") - else - report("bad size feature in %a,",fontdata.filename or "?") - end - end - if designsize then - fontdata.minsize=minsize - fontdata.maxsize=maxsize - fontdata.designsize=designsize - end - end - end - local function reorderfeatures(fontdata,scripts,features) - local scriptlangs={} - local featurehash={} - local featureorder={} - for script,languages in next,scripts do - for language,record in next,languages do - local hash={} - local list=record.featureindices - for k=1,#list do - local index=list[k] - local feature=features[index] - local lookups=feature.lookups - local tag=feature.tag - if tag then - hash[tag]=true - end - if lookups then - for i=1,#lookups do - local lookup=lookups[i] - local o=featureorder[lookup] - if o then - local okay=true - for i=1,#o do - if o[i]==tag then - okay=false - break - end - end - if okay then - o[#o+1]=tag - end - else - featureorder[lookup]={ tag } - end - local f=featurehash[lookup] - if f then - local h=f[tag] - if h then - local s=h[script] - if s then - s[language]=true - else - h[script]={ [language]=true } - end - else - f[tag]={ [script]={ [language]=true } } - end - else - featurehash[lookup]={ [tag]={ [script]={ [language]=true } } } - end - local h=scriptlangs[tag] - if h then - local s=h[script] - if s then - s[language]=true - else - h[script]={ [language]=true } - end - else - scriptlangs[tag]={ [script]={ [language]=true } } - end - end - end - end - end - end - return scriptlangs,featurehash,featureorder - end - local function readscriplan(f,fontdata,scriptoffset) - setposition(f,scriptoffset) - local nofscripts=readushort(f) - local scripts={} - for i=1,nofscripts do - scripts[readtag(f)]=scriptoffset+readushort(f) - end - local languagesystems=setmetatableindex("table") - for script,offset in next,scripts do - setposition(f,offset) - local defaultoffset=readushort(f) - local noflanguages=readushort(f) - local languages={} - if defaultoffset>0 then - languages.dflt=languagesystems[offset+defaultoffset] - end - for i=1,noflanguages do - local language=readtag(f) - local offset=offset+readushort(f) - languages[language]=languagesystems[offset] - end - scripts[script]=languages - end - for offset,usedfeatures in next,languagesystems do - if offset>0 then - setposition(f,offset) - local featureindices={} - usedfeatures.featureindices=featureindices - usedfeatures.lookuporder=readushort(f) - usedfeatures.requiredindex=readushort(f) - local noffeatures=readushort(f) - for i=1,noffeatures do - featureindices[i]=readushort(f)+1 - end - end - end - return scripts - end - local function readfeatures(f,fontdata,featureoffset) - setposition(f,featureoffset) - local features={} - local noffeatures=readushort(f) - for i=1,noffeatures do - features[i]={ - tag=readtag(f), - offset=readushort(f) - } - end - for i=1,noffeatures do - local feature=features[i] - local offset=featureoffset+feature.offset - setposition(f,offset) - local parameters=readushort(f) - local noflookups=readushort(f) - if noflookups>0 then - local lookups={} - feature.lookups=lookups - for j=1,noflookups do - lookups[j]=readushort(f)+1 - end - end - if parameters>0 then - feature.parameters=parameters - local plugin=plugins[feature.tag] - if plugin then - plugin(f,fontdata,featureoffset,feature) - end - end - end - return features - end - local function readlookups(f,lookupoffset,lookuptypes,featurehash,featureorder) - setposition(f,lookupoffset) - local lookups={} - local noflookups=readushort(f) - for i=1,noflookups do - lookups[i]=readushort(f) - end - for lookupid=1,noflookups do - local index=lookups[lookupid] - setposition(f,lookupoffset+index) - local subtables={} - local typebits=readushort(f) - local flagbits=readushort(f) - local lookuptype=lookuptypes[typebits] - local lookupflags=lookupflags[flagbits] - local nofsubtables=readushort(f) - for j=1,nofsubtables do - local offset=readushort(f) - subtables[j]=offset+index - end - local markclass=bittest(flagbits,0x0010) - if markclass then - markclass=readushort(f) - end - local markset=rshift(flagbits,8) - if markset>0 then - markclass=markset - end - lookups[lookupid]={ - type=lookuptype, - flags=lookupflags, - name=lookupid, - subtables=subtables, - markclass=markclass, - features=featurehash[lookupid], - order=featureorder[lookupid], - } - end - return lookups - end - local function readscriptoffsets(f,fontdata,tableoffset) - if not tableoffset then - return - end - setposition(f,tableoffset) - local version=readulong(f) - if version~=0x00010000 then - report("table version %a of %a is not supported (yet), maybe font %s is bad",version,what,fontdata.filename) - return - end - return tableoffset+readushort(f),tableoffset+readushort(f),tableoffset+readushort(f) - end - local f_lookupname=formatters["%s_%s_%s"] - local function resolvelookups(f,lookupoffset,fontdata,lookups,lookuptypes,lookuphandlers,what) - local sequences=fontdata.sequences or {} - local sublookuplist=fontdata.sublookups or {} - fontdata.sequences=sequences - fontdata.sublookups=sublookuplist - local nofsublookups=#sublookuplist - local nofsequences=#sequences - local lastsublookup=nofsublookups - local lastsequence=nofsequences - local lookupnames=lookupnames[what] - local sublookuphash={} - local sublookupcheck={} - local glyphs=fontdata.glyphs - local nofglyphs=fontdata.nofglyphs or #glyphs - local noflookups=#lookups - local lookupprefix=sub(what,2,2) - for lookupid=1,noflookups do - local lookup=lookups[lookupid] - local lookuptype=lookup.type - local subtables=lookup.subtables - local features=lookup.features - local handler=lookuphandlers[lookuptype] - if handler then - local nofsubtables=#subtables - local order=lookup.order - local flags=lookup.flags - if flags[1] then flags[1]="mark" end - if flags[2] then flags[2]="ligature" end - if flags[3] then flags[3]="base" end - local markclass=lookup.markclass - if nofsubtables>0 then - local steps={} - local nofsteps=0 - local oldtype=nil - for s=1,nofsubtables do - local step,lt=handler(f,fontdata,lookupid,lookupoffset,subtables[s],glyphs,nofglyphs) - if lt then - lookuptype=lt - if oldtype and lt~=oldtype then - report("messy %s lookup type %a and %a",what,lookuptype,oldtype) - end - oldtype=lookuptype - end - if not step then - report("unsupported %s lookup type %a",what,lookuptype) - else - nofsteps=nofsteps+1 - steps[nofsteps]=step - local rules=step.rules - if rules then - for i=1,#rules do - local rule=rules[i] - local before=rule.before - local current=rule.current - local after=rule.after - if before then - for i=1,#before do - before[i]=tohash(before[i]) - end - rule.before=reversed(before) - end - if current then - for i=1,#current do - current[i]=tohash(current[i]) - end - end - if after then - for i=1,#after do - after[i]=tohash(after[i]) - end - end - end - end - end - end - if nofsteps~=nofsubtables then - report("bogus subtables removed in %s lookup type %a",what,lookuptype) - end - lookuptype=lookupnames[lookuptype] or lookuptype - if features then - nofsequences=nofsequences+1 - local l={ - index=nofsequences, - name=f_lookupname(lookupprefix,"s",lookupid+lookupidoffset), - steps=steps, - nofsteps=nofsteps, - type=lookuptype, - markclass=markclass or nil, - flags=flags, - order=order, - features=features, - } - sequences[nofsequences]=l - lookup.done=l - else - nofsublookups=nofsublookups+1 - local l={ - index=nofsublookups, - name=f_lookupname(lookupprefix,"l",lookupid+lookupidoffset), - steps=steps, - nofsteps=nofsteps, - type=lookuptype, - markclass=markclass or nil, - flags=flags, - } - sublookuplist[nofsublookups]=l - sublookuphash[lookupid]=nofsublookups - sublookupcheck[lookupid]=0 - lookup.done=l - end - else - report("no subtables for lookup %a",lookupid) - end - else - report("no handler for lookup %a with type %a",lookupid,lookuptype) - end - end - local reported={} - local function report_issue(i,what,sequence,kind) - local name=sequence.name - if not reported[name] then - report("rule %i in %s lookup %a has %s lookups",i,what,name,kind) - reported[name]=true - end - end - for i=lastsequence+1,nofsequences do - local sequence=sequences[i] - local steps=sequence.steps - for i=1,#steps do - local step=steps[i] - local rules=step.rules - if rules then - for i=1,#rules do - local rule=rules[i] - local rlookups=rule.lookups - if not rlookups then - report_issue(i,what,sequence,"no") - elseif not next(rlookups) then - report_issue(i,what,sequence,"empty") - rule.lookups=nil - else - local length=#rlookups - for index=1,length do - local lookupid=rlookups[index] - if lookupid then - local h=sublookuphash[lookupid] - if not h then - local lookup=lookups[lookupid] - if lookup then - local d=lookup.done - if d then - nofsublookups=nofsublookups+1 - h={ - index=nofsublookups, - name=f_lookupname(lookupprefix,"d",lookupid+lookupidoffset), - derived=true, - steps=d.steps, - nofsteps=d.nofsteps, - type=d.lookuptype, - markclass=d.markclass or nil, - flags=d.flags, - } - sublookuplist[nofsublookups]=copy(h) - sublookuphash[lookupid]=nofsublookups - sublookupcheck[lookupid]=1 - else - report_issue(i,what,sequence,"missing") - rule.lookups=nil - break - end - else - report_issue(i,what,sequence,"bad") - rule.lookups=nil - break - end - else - sublookupcheck[lookupid]=sublookupcheck[lookupid]+1 - end - rlookups[index]=h or false - else - rlookups[index]=false - end - end - end - end - end - end - end - for i,n in sortedhash(sublookupcheck) do - local l=lookups[i] - local t=l.type - if n==0 and t~="extension" then - local d=l.done - report("%s lookup %s of type %a is not used",what,d and d.name or l.name,t) - end - end - end - local function readscripts(f,fontdata,what,lookuptypes,lookuphandlers,lookupstoo) - local datatable=fontdata.tables[what] - if not datatable then - return - end - local tableoffset=datatable.offset - if not tableoffset then - return - end - local scriptoffset,featureoffset,lookupoffset=readscriptoffsets(f,fontdata,tableoffset) - if not scriptoffset then - return - end - local scripts=readscriplan(f,fontdata,scriptoffset) - local features=readfeatures(f,fontdata,featureoffset) - local scriptlangs,featurehash,featureorder=reorderfeatures(fontdata,scripts,features) - if fontdata.features then - fontdata.features[what]=scriptlangs - else - fontdata.features={ [what]=scriptlangs } - end - if not lookupstoo then - return - end - local lookups=readlookups(f,lookupoffset,lookuptypes,featurehash,featureorder) - if lookups then - resolvelookups(f,lookupoffset,fontdata,lookups,lookuptypes,lookuphandlers,what) - end - end - local function checkkerns(f,fontdata,specification) - local datatable=fontdata.tables.kern - if not datatable then - return - end - local features=fontdata.features - local gposfeatures=features and features.gpos - local name - if not gposfeatures or not gposfeatures.kern then - name="kern" - elseif specification.globalkerns then - name="globalkern" - else - report("ignoring global kern table using gpos kern feature") - return - end - report("adding global kern table as gpos feature %a",name) - setposition(f,datatable.offset) - local version=readushort(f) - local noftables=readushort(f) - local kerns=setmetatableindex("table") - for i=1,noftables do - local version=readushort(f) - local length=readushort(f) - local coverage=readushort(f) - local format=bit32.rshift(coverage,8) - if format==0 then - local nofpairs=readushort(f) - local searchrange=readushort(f) - local entryselector=readushort(f) - local rangeshift=readushort(f) - for i=1,nofpairs do - kerns[readushort(f)][readushort(f)]=readfword(f) - end - elseif format==2 then - else - end - end - local feature={ dflt={ dflt=true } } - if not features then - fontdata.features={ gpos={ [name]=feature } } - elseif not gposfeatures then - fontdata.features.gpos={ [name]=feature } - else - gposfeatures[name]=feature - end - local sequences=fontdata.sequences - if not sequences then - sequences={} - fontdata.sequences=sequences - end - local nofsequences=#sequences+1 - sequences[nofsequences]={ - index=nofsequences, - name=name, - steps={ - { - coverage=kerns, - format="kern", - }, - }, - nofsteps=1, - type="gpos_pair", - flags={ false,false,false,false }, - order={ name }, - features={ [name]=feature }, - } - end - function readers.gsub(f,fontdata,specification) - if specification.details then - readscripts(f,fontdata,"gsub",gsubtypes,gsubhandlers,specification.lookups) - end - end - function readers.gpos(f,fontdata,specification) - if specification.details then - readscripts(f,fontdata,"gpos",gpostypes,gposhandlers,specification.lookups) - if specification.lookups then - checkkerns(f,fontdata,specification) - end - end - end -end -function readers.gdef(f,fontdata,specification) - if specification.glyphs then - local datatable=fontdata.tables.gdef - if datatable then - local tableoffset=datatable.offset - setposition(f,tableoffset) - local version=readulong(f) - local classoffset=tableoffset+readushort(f) - local attachmentoffset=tableoffset+readushort(f) - local ligaturecarets=tableoffset+readushort(f) - local markclassoffset=tableoffset+readushort(f) - local marksetsoffset=version==0x00010002 and (tableoffset+readushort(f)) - local glyphs=fontdata.glyphs - local marks={} - local markclasses=setmetatableindex("table") - local marksets=setmetatableindex("table") - fontdata.marks=marks - fontdata.markclasses=markclasses - fontdata.marksets=marksets - setposition(f,classoffset) - local classformat=readushort(f) - if classformat==1 then - local firstindex=readushort(f) - local lastindex=firstindex+readushort(f)-1 - for index=firstindex,lastindex do - local class=classes[readushort(f)] - if class=="mark" then - marks[index]=true - end - glyphs[index].class=class - end - elseif classformat==2 then - local nofranges=readushort(f) - for i=1,nofranges do - local firstindex=readushort(f) - local lastindex=readushort(f) - local class=classes[readushort(f)] - if class then - for index=firstindex,lastindex do - glyphs[index].class=class - if class=="mark" then - marks[index]=true - end - end - end - end - end - setposition(f,markclassoffset) - local classformat=readushort(f) - if classformat==1 then - local firstindex=readushort(f) - local lastindex=firstindex+readushort(f)-1 - for index=firstindex,lastindex do - markclasses[readushort(f)][index]=true - end - elseif classformat==2 then - local nofranges=readushort(f) - for i=1,nofranges do - local firstindex=readushort(f) - local lastindex=readushort(f) - local class=markclasses[readushort(f)] - for index=firstindex,lastindex do - class[index]=true - end - end - end - if marksetsoffset and marksetsoffset>tableoffset then - setposition(f,marksetsoffset) - local format=readushort(f) - if format==1 then - local nofsets=readushort(f) - local sets={} - for i=1,nofsets do - sets[i]=readulong(f) - end - for i=1,nofsets do - local offset=sets[i] - if offset~=0 then - marksets[i]=readcoverage(f,marksetsoffset+offset) - end - end - end - end - end - end -end -local function readmathvalue(f) - local v=readshort(f) - skipshort(f,1) - return v -end -local function readmathconstants(f,fontdata,offset) - setposition(f,offset) - fontdata.mathconstants={ - ScriptPercentScaleDown=readshort(f), - ScriptScriptPercentScaleDown=readshort(f), - DelimitedSubFormulaMinHeight=readushort(f), - DisplayOperatorMinHeight=readushort(f), - MathLeading=readmathvalue(f), - AxisHeight=readmathvalue(f), - AccentBaseHeight=readmathvalue(f), - FlattenedAccentBaseHeight=readmathvalue(f), - SubscriptShiftDown=readmathvalue(f), - SubscriptTopMax=readmathvalue(f), - SubscriptBaselineDropMin=readmathvalue(f), - SuperscriptShiftUp=readmathvalue(f), - SuperscriptShiftUpCramped=readmathvalue(f), - SuperscriptBottomMin=readmathvalue(f), - SuperscriptBaselineDropMax=readmathvalue(f), - SubSuperscriptGapMin=readmathvalue(f), - SuperscriptBottomMaxWithSubscript=readmathvalue(f), - SpaceAfterScript=readmathvalue(f), - UpperLimitGapMin=readmathvalue(f), - UpperLimitBaselineRiseMin=readmathvalue(f), - LowerLimitGapMin=readmathvalue(f), - LowerLimitBaselineDropMin=readmathvalue(f), - StackTopShiftUp=readmathvalue(f), - StackTopDisplayStyleShiftUp=readmathvalue(f), - StackBottomShiftDown=readmathvalue(f), - StackBottomDisplayStyleShiftDown=readmathvalue(f), - StackGapMin=readmathvalue(f), - StackDisplayStyleGapMin=readmathvalue(f), - StretchStackTopShiftUp=readmathvalue(f), - StretchStackBottomShiftDown=readmathvalue(f), - StretchStackGapAboveMin=readmathvalue(f), - StretchStackGapBelowMin=readmathvalue(f), - FractionNumeratorShiftUp=readmathvalue(f), - FractionNumeratorDisplayStyleShiftUp=readmathvalue(f), - FractionDenominatorShiftDown=readmathvalue(f), - FractionDenominatorDisplayStyleShiftDown=readmathvalue(f), - FractionNumeratorGapMin=readmathvalue(f), - FractionNumeratorDisplayStyleGapMin=readmathvalue(f), - FractionRuleThickness=readmathvalue(f), - FractionDenominatorGapMin=readmathvalue(f), - FractionDenominatorDisplayStyleGapMin=readmathvalue(f), - SkewedFractionHorizontalGap=readmathvalue(f), - SkewedFractionVerticalGap=readmathvalue(f), - OverbarVerticalGap=readmathvalue(f), - OverbarRuleThickness=readmathvalue(f), - OverbarExtraAscender=readmathvalue(f), - UnderbarVerticalGap=readmathvalue(f), - UnderbarRuleThickness=readmathvalue(f), - UnderbarExtraDescender=readmathvalue(f), - RadicalVerticalGap=readmathvalue(f), - RadicalDisplayStyleVerticalGap=readmathvalue(f), - RadicalRuleThickness=readmathvalue(f), - RadicalExtraAscender=readmathvalue(f), - RadicalKernBeforeDegree=readmathvalue(f), - RadicalKernAfterDegree=readmathvalue(f), - RadicalDegreeBottomRaisePercent=readshort(f), - } -end -local function readmathglyphinfo(f,fontdata,offset) - setposition(f,offset) - local italics=readushort(f) - local accents=readushort(f) - local extensions=readushort(f) - local kerns=readushort(f) - local glyphs=fontdata.glyphs - if italics~=0 then - setposition(f,offset+italics) - local coverage=readushort(f) - local nofglyphs=readushort(f) - coverage=readcoverage(f,offset+italics+coverage,true) - setposition(f,offset+italics+4) - for i=1,nofglyphs do - local italic=readmathvalue(f) - if italic~=0 then - local glyph=glyphs[coverage[i]] - local math=glyph.math - if not math then - glyph.math={ italic=italic } - else - math.italic=italic - end - end - end - fontdata.hasitalics=true - end - if accents~=0 then - setposition(f,offset+accents) - local coverage=readushort(f) - local nofglyphs=readushort(f) - coverage=readcoverage(f,offset+accents+coverage,true) - setposition(f,offset+accents+4) - for i=1,nofglyphs do - local accent=readmathvalue(f) - if accent~=0 then - local glyph=glyphs[coverage[i]] - local math=glyph.math - if not math then - glyph.math={ accent=accent } - else - math.accent=accent - end - end - end - end - if extensions~=0 then - setposition(f,offset+extensions) - end - if kerns~=0 then - local kernoffset=offset+kerns - setposition(f,kernoffset) - local coverage=readushort(f) - local nofglyphs=readushort(f) - if nofglyphs>0 then - local function get(offset) - setposition(f,kernoffset+offset) - local n=readushort(f) - if n==0 then - local k=readmathvalue(f) - if k==0 then - else - return { { kern=k } } - end - else - local l={} - for i=1,n do - l[i]={ height=readmathvalue(f) } - end - for i=1,n do - l[i].kern=readmathvalue(f) - end - l[n+1]={ kern=readmathvalue(f) } - return l - end - end - local kernsets={} - for i=1,nofglyphs do - local topright=readushort(f) - local topleft=readushort(f) - local bottomright=readushort(f) - local bottomleft=readushort(f) - kernsets[i]={ - topright=topright~=0 and topright or nil, - topleft=topleft~=0 and topleft or nil, - bottomright=bottomright~=0 and bottomright or nil, - bottomleft=bottomleft~=0 and bottomleft or nil, - } - end - coverage=readcoverage(f,kernoffset+coverage,true) - for i=1,nofglyphs do - local kernset=kernsets[i] - if next(kernset) then - local k=kernset.topright if k then kernset.topright=get(k) end - local k=kernset.topleft if k then kernset.topleft=get(k) end - local k=kernset.bottomright if k then kernset.bottomright=get(k) end - local k=kernset.bottomleft if k then kernset.bottomleft=get(k) end - if next(kernset) then - local glyph=glyphs[coverage[i]] - local math=glyph.math - if math then - math.kerns=kernset - else - glyph.math={ kerns=kernset } - end - end - end - end - end - end -end -local function readmathvariants(f,fontdata,offset) - setposition(f,offset) - local glyphs=fontdata.glyphs - local minoverlap=readushort(f) - local vcoverage=readushort(f) - local hcoverage=readushort(f) - local vnofglyphs=readushort(f) - local hnofglyphs=readushort(f) - local vconstruction={} - local hconstruction={} - for i=1,vnofglyphs do - vconstruction[i]=readushort(f) - end - for i=1,hnofglyphs do - hconstruction[i]=readushort(f) - end - fontdata.mathconstants.MinConnectorOverlap=minoverlap - local function get(offset,coverage,nofglyphs,construction,kvariants,kparts,kitalic) - if coverage~=0 and nofglyphs>0 then - local coverage=readcoverage(f,offset+coverage,true) - for i=1,nofglyphs do - local c=construction[i] - if c~=0 then - local index=coverage[i] - local glyph=glyphs[index] - local math=glyph.math - setposition(f,offset+c) - local assembly=readushort(f) - local nofvariants=readushort(f) - if nofvariants>0 then - local variants,v=nil,0 - for i=1,nofvariants do - local variant=readushort(f) - if variant==index then - elseif variants then - v=v+1 - variants[v]=variant - else - v=1 - variants={ variant } - end - skipshort(f) - end - if not variants then - elseif not math then - math={ [kvariants]=variants } - glyph.math=math - else - math[kvariants]=variants - end - end - if assembly~=0 then - setposition(f,offset+c+assembly) - local italic=readmathvalue(f) - local nofparts=readushort(f) - local parts={} - for i=1,nofparts do - local p={ - glyph=readushort(f), - start=readushort(f), - ["end"]=readushort(f), - advance=readushort(f), - } - local flags=readushort(f) - if bittest(flags,0x0001) then - p.extender=1 - end - parts[i]=p - end - if not math then - math={ - [kparts]=parts - } - glyph.math=math - else - math[kparts]=parts - end - if italic and italic~=0 then - math[kitalic]=italic - end - end - end - end - end - end - get(offset,vcoverage,vnofglyphs,vconstruction,"vvariants","vparts","vitalic") - get(offset,hcoverage,hnofglyphs,hconstruction,"hvariants","hparts","hitalic") -end -function readers.math(f,fontdata,specification) - if specification.glyphs then - local datatable=fontdata.tables.math - if datatable then - local tableoffset=datatable.offset - setposition(f,tableoffset) - local version=readulong(f) - if version~=0x00010000 then - report("table version %a of %a is not supported (yet), maybe font %s is bad",version,"math",fontdata.filename) - return - end - local constants=readushort(f) - local glyphinfo=readushort(f) - local variants=readushort(f) - if constants==0 then - report("the math table of %a has no constants",fontdata.filename) - else - readmathconstants(f,fontdata,tableoffset+constants) - end - if glyphinfo~=0 then - readmathglyphinfo(f,fontdata,tableoffset+glyphinfo) - end - if variants~=0 then - readmathvariants(f,fontdata,tableoffset+variants) - end - end - end -end -function readers.colr(f,fontdata,specification) - local datatable=fontdata.tables.colr - if datatable then - if specification.glyphs then - local tableoffset=datatable.offset - setposition(f,tableoffset) - local version=readushort(f) - if version~=0 then - report("table version %a of %a is not supported (yet), maybe font %s is bad",version,"colr",fontdata.filename) - return - end - if not fontdata.tables.cpal then - report("color table %a in font %a has no mandate %a table","colr",fontdata.filename,"cpal") - fontdata.colorpalettes={} - end - local glyphs=fontdata.glyphs - local nofglyphs=readushort(f) - local baseoffset=readulong(f) - local layeroffset=readulong(f) - local noflayers=readushort(f) - local layerrecords={} - local maxclass=0 - setposition(f,tableoffset+layeroffset) - for i=1,noflayers do - local slot=readushort(f) - local class=readushort(f) - if class<0xFFFF then - class=class+1 - if class>maxclass then - maxclass=class - end - end - layerrecords[i]={ - slot=slot, - class=class, - } - end - fontdata.maxcolorclass=maxclass - setposition(f,tableoffset+baseoffset) - for i=0,nofglyphs-1 do - local glyphindex=readushort(f) - local firstlayer=readushort(f) - local noflayers=readushort(f) - local t={} - for i=1,noflayers do - t[i]=layerrecords[firstlayer+i] - end - glyphs[glyphindex].colors=t - end - end - fontdata.hascolor=true - end -end -function readers.cpal(f,fontdata,specification) - if specification.glyphs then - local datatable=fontdata.tables.cpal - if datatable then - local tableoffset=datatable.offset - setposition(f,tableoffset) - local version=readushort(f) - if version>1 then - report("table version %a of %a is not supported (yet), maybe font %s is bad",version,"cpal",fontdata.filename) - return - end - local nofpaletteentries=readushort(f) - local nofpalettes=readushort(f) - local nofcolorrecords=readushort(f) - local firstcoloroffset=readulong(f) - local colorrecords={} - local palettes={} - for i=1,nofpalettes do - palettes[i]=readushort(f) - end - if version==1 then - local palettettypesoffset=readulong(f) - local palettelabelsoffset=readulong(f) - local paletteentryoffset=readulong(f) - end - setposition(f,tableoffset+firstcoloroffset) - for i=1,nofcolorrecords do - local b,g,r,a=readbytes(f,4) - colorrecords[i]={ - r,g,b,a~=255 and a or nil, - } - end - for i=1,nofpalettes do - local p={} - local o=palettes[i] - for j=1,nofpaletteentries do - p[j]=colorrecords[o+j] - end - palettes[i]=p - end - fontdata.colorpalettes=palettes - end - end -end -function readers.svg(f,fontdata,specification) - local datatable=fontdata.tables.svg - if datatable then - if specification.glyphs then - local tableoffset=datatable.offset - setposition(f,tableoffset) - local version=readushort(f) - if version~=0 then - report("table version %a of %a is not supported (yet), maybe font %s is bad",version,"svg",fontdata.filename) - return - end - local glyphs=fontdata.glyphs - local indexoffset=tableoffset+readulong(f) - local reserved=readulong(f) - setposition(f,indexoffset) - local nofentries=readushort(f) - local entries={} - for i=1,nofentries do - entries[i]={ - first=readushort(f), - last=readushort(f), - offset=indexoffset+readulong(f), - length=readulong(f), - } - end - for i=1,nofentries do - local entry=entries[i] - setposition(f,entry.offset) - entries[i]={ - first=entry.first, - last=entry.last, - data=readstring(f,entry.length) - } - end - fontdata.svgshapes=entries - end - fontdata.hascolor=true - end -end - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['font-oup']={ - version=1.001, - comment="companion to font-ini.mkiv", - 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 P,R,S=lpeg.P,lpeg.R,lpeg.S -local lpegmatch=lpeg.match -local insert,remove,copy,unpack=table.insert,table.remove,table.copy,table.unpack -local formatters=string.formatters -local sortedkeys=table.sortedkeys -local sortedhash=table.sortedhash -local tohash=table.tohash -local report=logs.reporter("otf reader") -local trace_markwidth=false trackers.register("otf.markwidth",function(v) trace_markwidth=v end) -local readers=fonts.handlers.otf.readers -local privateoffset=fonts.constructors and fonts.constructors.privateoffset or 0xF0000 -local f_private=formatters["P%05X"] -local f_unicode=formatters["U%05X"] -local f_index=formatters["I%05X"] -local f_character_y=formatters["%C"] -local f_character_n=formatters["[ %C ]"] -local check_duplicates=true -local check_soft_hyphen=false -directives.register("otf.checksofthyphen",function(v) - check_soft_hyphen=v -end) -local function replaced(list,index,replacement) - if type(list)=="number" then - return replacement - elseif type(replacement)=="table" then - local t={} - local n=index-1 - for i=1,n do - t[i]=list[i] - end - for i=1,#replacement do - n=n+1 - t[n]=replacement[i] - end - for i=index+1,#list do - n=n+1 - t[n]=list[i] - end - else - list[index]=replacement - return list - end -end -local function unifyresources(fontdata,indices) - local descriptions=fontdata.descriptions - local resources=fontdata.resources - if not descriptions or not resources then - return - end - local variants=fontdata.resources.variants - if variants then - for selector,unicodes in next,variants do - for unicode,index in next,unicodes do - unicodes[unicode]=indices[index] - end - end - end - local function remark(marks) - if marks then - local newmarks={} - for k,v in next,marks do - local u=indices[k] - if u then - newmarks[u]=v - else - report("discarding mark %i",k) - end - end - return newmarks - end - end - local marks=resources.marks - if marks then - resources.marks=remark(marks) - end - local markclasses=resources.markclasses - if markclasses then - for class,marks in next,markclasses do - markclasses[class]=remark(marks) - end - end - local marksets=resources.marksets - if marksets then - for class,marks in next,marksets do - marksets[class]=remark(marks) - end - end - local done={} - local duplicates=check_duplicates and resources.duplicates - if duplicates and not next(duplicates) then - duplicates=false - end - local function recover(cover) - for i=1,#cover do - local c=cover[i] - if not done[c] then - local t={} - for k,v in next,c do - t[indices[k]]=v - end - cover[i]=t - done[c]=d - end - end - end - local function recursed(c) - local t={} - for g,d in next,c do - if type(d)=="table" then - t[indices[g]]=recursed(d) - else - t[g]=indices[d] - end - end - return t - end - local function unifythem(sequences) - if not sequences then - return - end - for i=1,#sequences do - local sequence=sequences[i] - local kind=sequence.type - local steps=sequence.steps - local features=sequence.features - if steps then - for i=1,#steps do - local step=steps[i] - if kind=="gsub_single" then - local c=step.coverage - if c then - local t1=done[c] - if not t1 then - t1={} - if duplicates then - for g1,d1 in next,c do - local ug1=indices[g1] - local ud1=indices[d1] - t1[ug1]=ud1 - local dg1=duplicates[ug1] - if dg1 then - for u in next,dg1 do - t1[u]=ud1 - end - end - end - else - for g1,d1 in next,c do - t1[indices[g1]]=indices[d1] - end - end - done[c]=t1 - end - step.coverage=t1 - end - elseif kind=="gpos_pair" then - local c=step.coverage - if c then - local t1=done[c] - if not t1 then - t1={} - for g1,d1 in next,c do - local t2=done[d1] - if not t2 then - t2={} - for g2,d2 in next,d1 do - t2[indices[g2]]=d2 - end - done[d1]=t2 - end - t1[indices[g1]]=t2 - end - done[c]=t1 - end - step.coverage=t1 - end - elseif kind=="gsub_ligature" then - local c=step.coverage - if c then - step.coverage=recursed(c) - end - elseif kind=="gsub_alternate" or kind=="gsub_multiple" then - local c=step.coverage - if c then - local t1=done[c] - if not t1 then - t1={} - if duplicates then - for g1,d1 in next,c do - for i=1,#d1 do - d1[i]=indices[d1[i]] - end - local ug1=indices[g1] - t1[ug1]=d1 - local dg1=duplicates[ug1] - if dg1 then - for u in next,dg1 do - t1[u]=copy(d1) - end - end - end - else - for g1,d1 in next,c do - for i=1,#d1 do - d1[i]=indices[d1[i]] - end - t1[indices[g1]]=d1 - end - end - done[c]=t1 - end - step.coverage=t1 - end - elseif kind=="gpos_mark2base" or kind=="gpos_mark2mark" or kind=="gpos_mark2ligature" then - local c=step.coverage - if c then - local t1=done[c] - if not t1 then - t1={} - for g1,d1 in next,c do - t1[indices[g1]]=d1 - end - done[c]=t1 - end - step.coverage=t1 - end - local c=step.baseclasses - if c then - local t1=done[c] - if not t1 then - for g1,d1 in next,c do - local t2=done[d1] - if not t2 then - t2={} - for g2,d2 in next,d1 do - t2[indices[g2]]=d2 - end - done[d1]=t2 - end - c[g1]=t2 - end - done[c]=c - end - end - elseif kind=="gpos_single" then - local c=step.coverage - if c then - local t1=done[c] - if not t1 then - t1={} - if duplicates then - for g1,d1 in next,c do - local ug1=indices[g1] - t1[ug1]=d1 - local dg1=duplicates[ug1] - if dg1 then - for u in next,dg1 do - t1[u]=d1 - end - end - end - else - for g1,d1 in next,c do - t1[indices[g1]]=d1 - end - end - done[c]=t1 - end - step.coverage=t1 - end - elseif kind=="gpos_cursive" then - local c=step.coverage - if c then - local t1=done[c] - if not t1 then - t1={} - if duplicates then - for g1,d1 in next,c do - local ug1=indices[g1] - t1[ug1]=d1 - local dg1=duplicates[ug1] - if dg1 then - for u in next,dg1 do - t1[u]=copy(d1) - end - end - end - else - for g1,d1 in next,c do - t1[indices[g1]]=d1 - end - end - done[c]=t1 - end - step.coverage=t1 - end - end - local rules=step.rules - if rules then - for i=1,#rules do - local rule=rules[i] - local before=rule.before if before then recover(before) end - local after=rule.after if after then recover(after) end - local current=rule.current if current then recover(current) end - local replacements=rule.replacements - if replacements then - if not done[replacements] then - local r={} - for k,v in next,replacements do - r[indices[k]]=indices[v] - end - rule.replacements=r - done[replacements]=r - end - end - end - end - end - end - end - end - unifythem(resources.sequences) - unifythem(resources.sublookups) -end -local function copyduplicates(fontdata) - if check_duplicates then - local descriptions=fontdata.descriptions - local resources=fontdata.resources - local duplicates=resources.duplicates - if check_soft_hyphen then - local ds=descriptions[0xAD] - if not ds or ds.width==0 then - if ds then - descriptions[0xAD]=nil - report("patching soft hyphen") - else - report("adding soft hyphen") - end - if not duplicates then - duplicates={} - resources.duplicates=duplicates - end - local dh=duplicates[0x2D] - if dh then - dh[#dh+1]={ [0xAD]=true } - else - duplicates[0x2D]={ [0xAD]=true } - end - end - end - if duplicates then - for u,d in next,duplicates do - local du=descriptions[u] - if du then - local t={ f_character_y(u),"@",f_index(du.index),"->" } - local n=0 - local m=25 - for u in next,d do - if descriptions[u] then - if n<m then - t[n+4]=f_character_n(u) - end - else - local c=copy(du) - c.unicode=u - descriptions[u]=c - if n<m then - t[n+4]=f_character_y(u) - end - end - n=n+1 - end - if n<=m then - report("duplicates: %i : % t",n,t) - else - report("duplicates: %i : % t ...",n,t) - end - else - end - end - end - end -end -local ignore={ - ["notdef"]=true, - [".notdef"]=true, - ["null"]=true, - [".null"]=true, - ["nonmarkingreturn"]=true, -} -local function checklookups(fontdata,missing,nofmissing) - local descriptions=fontdata.descriptions - local resources=fontdata.resources - if missing and nofmissing and nofmissing<=0 then - return - end - local singles={} - local alternates={} - local ligatures={} - if not missing then - missing={} - nofmissing=0 - for u,d in next,descriptions do - if not d.unicode then - nofmissing=nofmissing+1 - missing[u]=true - end - end - end - local function collectthem(sequences) - if not sequences then - return - end - for i=1,#sequences do - local sequence=sequences[i] - local kind=sequence.type - local steps=sequence.steps - if steps then - for i=1,#steps do - local step=steps[i] - if kind=="gsub_single" then - local c=step.coverage - if c then - singles[#singles+1]=c - end - elseif kind=="gsub_alternate" then - local c=step.coverage - if c then - alternates[#alternates+1]=c - end - elseif kind=="gsub_ligature" then - local c=step.coverage - if c then - ligatures[#ligatures+1]=c - end - end - end - end - end - end - collectthem(resources.sequences) - collectthem(resources.sublookups) - local loops=0 - while true do - loops=loops+1 - local old=nofmissing - for i=1,#singles do - local c=singles[i] - for g1,g2 in next,c do - if missing[g1] then - local u2=descriptions[g2].unicode - if u2 then - missing[g1]=false - descriptions[g1].unicode=u2 - nofmissing=nofmissing-1 - end - end - if missing[g2] then - local u1=descriptions[g1].unicode - if u1 then - missing[g2]=false - descriptions[g2].unicode=u1 - nofmissing=nofmissing-1 - end - end - end - end - for i=1,#alternates do - local c=alternates[i] - for g1,d1 in next,c do - if missing[g1] then - for i=1,#d1 do - local g2=d1[i] - local u2=descriptions[g2].unicode - if u2 then - missing[g1]=false - descriptions[g1].unicode=u2 - nofmissing=nofmissing-1 - end - end - end - if not missing[g1] then - for i=1,#d1 do - local g2=d1[i] - if missing[g2] then - local u1=descriptions[g1].unicode - if u1 then - missing[g2]=false - descriptions[g2].unicode=u1 - nofmissing=nofmissing-1 - end - end - end - end - end - end - if nofmissing<=0 then - report("all done in %s loops",loops) - return - elseif old==nofmissing then - break - end - end - local t,n - local function recursed(c) - for g,d in next,c do - if g~="ligature" then - local u=descriptions[g].unicode - if u then - n=n+1 - t[n]=u - recursed(d) - n=n-1 - end - elseif missing[d] then - local l={} - local m=0 - for i=1,n do - local u=t[i] - if type(u)=="table" then - for i=1,#u do - m=m+1 - l[m]=u[i] - end - else - m=m+1 - l[m]=u - end - end - missing[d]=false - descriptions[d].unicode=l - nofmissing=nofmissing-1 - end - end - end - if nofmissing>0 then - t={} - n=0 - local loops=0 - while true do - loops=loops+1 - local old=nofmissing - for i=1,#ligatures do - recursed(ligatures[i]) - end - if nofmissing<=0 then - report("all done in %s loops",loops) - return - elseif old==nofmissing then - break - end - end - t=nil - n=0 - end - if nofmissing>0 then - local done={} - for i,r in next,missing do - if r then - local data=descriptions[i] - local name=data and data.name or f_index(i) - if not ignore[name] then - done[name]=true - end - end - end - if next(done) then - report("not unicoded: % t",table.sortedkeys(done)) - end - end -end -local function unifymissing(fontdata) - if not fonts.mappings then - require("font-map") - require("font-agl") - end - local unicodes={} - local private=fontdata.private - local resources=fontdata.resources - resources.unicodes=unicodes - for unicode,d in next,fontdata.descriptions do - if unicode<privateoffset then - local name=d.name - if name then - unicodes[name]=unicode - end - end - end - fonts.mappings.addtounicode(fontdata,fontdata.filename,checklookups) - resources.unicodes=nil -end -local function unifyglyphs(fontdata,usenames) - local private=fontdata.private or privateoffset - local glyphs=fontdata.glyphs - local indices={} - local descriptions={} - local names=usenames and {} - local resources=fontdata.resources - local zero=glyphs[0] - local zerocode=zero.unicode - if not zerocode then - zerocode=private - zero.unicode=zerocode - private=private+1 - end - descriptions[zerocode]=zero - if names then - local name=glyphs[0].name or f_private(zerocode) - indices[0]=name - names[name]=zerocode - else - indices[0]=zerocode - end - for index=1,#glyphs do - local glyph=glyphs[index] - local unicode=glyph.unicode - if not unicode then - unicode=private - if names then - local name=glyph.name or f_private(unicode) - indices[index]=name - names[name]=unicode - else - indices[index]=unicode - end - private=private+1 - elseif descriptions[unicode] then - report("assigning private unicode %U to glyph indexed %05X (%C)",private,index,unicode) - unicode=private - if names then - local name=glyph.name or f_private(unicode) - indices[index]=name - names[name]=unicode - else - indices[index]=unicode - end - private=private+1 - else - if names then - local name=glyph.name or f_unicode(unicode) - indices[index]=name - names[name]=unicode - else - indices[index]=unicode - end - end - descriptions[unicode]=glyph - end - for index=1,#glyphs do - local math=glyphs[index].math - if math then - local list=math.vparts - if list then - for i=1,#list do local l=list[i] l.glyph=indices[l.glyph] end - end - local list=math.hparts - if list then - for i=1,#list do local l=list[i] l.glyph=indices[l.glyph] end - end - local list=math.vvariants - if list then - for i=1,#list do list[i]=indices[list[i]] end - end - local list=math.hvariants - if list then - for i=1,#list do list[i]=indices[list[i]] end - end - end - end - local colorpalettes=resources.colorpalettes - if colorpalettes then - for index=1,#glyphs do - local colors=glyphs[index].colors - if colors then - for i=1,#colors do - local c=colors[i] - c.slot=indices[c.slot] - end - end - end - end - fontdata.private=private - fontdata.glyphs=nil - fontdata.names=names - fontdata.descriptions=descriptions - fontdata.hashmethod=hashmethod - return indices,names -end -local p_bogusname=( - (P("uni")+P("UNI")+P("Uni")+P("U")+P("u"))*S("Xx")^0*R("09","AF")^1+(P("identity")+P("Identity")+P("IDENTITY"))*R("09","AF")^1+(P("index")+P("Index")+P("INDEX"))*R("09")^1 -)*P(-1) -local function stripredundant(fontdata) - local descriptions=fontdata.descriptions - if descriptions then - local n=0 - local c=0 - for unicode,d in next,descriptions do - local name=d.name - if name and lpegmatch(p_bogusname,name) then - d.name=nil - n=n+1 - end - if d.class=="base" then - d.class=nil - c=c+1 - end - end - if n>0 then - report("%s bogus names removed (verbose unicode)",n) - end - if c>0 then - report("%s base class tags removed (default is base)",c) - end - end -end -function readers.getcomponents(fontdata) - local resources=fontdata.resources - if resources then - local sequences=resources.sequences - if sequences then - local collected={} - for i=1,#sequences do - local sequence=sequences[i] - if sequence.type=="gsub_ligature" then - local steps=sequence.steps - if steps then - local l={} - local function traverse(p,k,v) - if k=="ligature" then - collected[v]={ unpack(l) } - else - insert(l,k) - for k,vv in next,v do - traverse(p,k,vv) - end - remove(l) - end - end - for i=1,#steps do - local coverage=steps[i].coverage - if coverage then - for k,v in next,coverage do - traverse(k,k,v) - end - end - end - end - end - end - if next(collected) then - while true do - local done=false - for k,v in next,collected do - for i=1,#v do - local vi=v[i] - if vi==k then - collected[k]=nil - break - else - local c=collected[vi] - if c then - done=true - local t={} - local n=i-1 - for j=1,n do - t[j]=v[j] - end - for j=1,#c do - n=n+1 - t[n]=c[j] - end - for j=i+1,#v do - n=n+1 - t[n]=v[j] - end - collected[k]=t - break - end - end - end - end - if not done then - break - end - end - return collected - end - end - end -end -readers.unifymissing=unifymissing -function readers.rehash(fontdata,hashmethod) - if not (fontdata and fontdata.glyphs) then - return - end - if hashmethod=="indices" then - fontdata.hashmethod="indices" - elseif hashmethod=="names" then - fontdata.hashmethod="names" - local indices=unifyglyphs(fontdata,true) - unifyresources(fontdata,indices) - copyduplicates(fontdata) - unifymissing(fontdata) - else - fontdata.hashmethod="unicode" - local indices=unifyglyphs(fontdata) - unifyresources(fontdata,indices) - copyduplicates(fontdata) - unifymissing(fontdata) - stripredundant(fontdata) - end -end -function readers.checkhash(fontdata) - local hashmethod=fontdata.hashmethod - if hashmethod=="unicodes" then - fontdata.names=nil - elseif hashmethod=="names" and fontdata.names then - unifyresources(fontdata,fontdata.names) - copyduplicates(fontdata) - fontdata.hashmethod="unicode" - fontdata.names=nil - else - readers.rehash(fontdata,"unicode") - end -end -function readers.addunicodetable(fontdata) - local resources=fontdata.resources - local unicodes=resources.unicodes - if not unicodes then - local descriptions=fontdata.descriptions - if descriptions then - unicodes={} - resources.unicodes=unicodes - for u,d in next,descriptions do - local n=d.name - if n then - unicodes[n]=u - end - end - end - end -end -local concat,sort=table.concat,table.sort -local next,type,tostring=next,type,tostring -local criterium=1 -local threshold=0 -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") -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 -function readers.pack(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 sequences=resources.sequences - local sublookups=resources.sublookups - local features=resources.features - local palettes=resources.colorpalettes - local chardata=characters and characters.data - local descriptions=data.descriptions or data.glyphs - if not descriptions then - return - end - 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,descriptions do - local boundingbox=description.boundingbox - if boundingbox then - description.boundingbox=pack_indexed(boundingbox) - 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 - end - local function packthem(sequences) - for i=1,#sequences do - local sequence=sequences[i] - local kind=sequence.type - local steps=sequence.steps - local order=sequence.order - local features=sequence.features - local flags=sequence.flags - if steps then - for i=1,#steps do - local step=steps[i] - if kind=="gpos_pair" then - local c=step.coverage - if c then - if step.format=="kern" then - for g1,d1 in next,c do - c[g1]=pack_normal(d1) - end - else - for g1,d1 in next,c do - for g2,d2 in next,d1 do - local f=d2[1] if f then d2[1]=pack_indexed(f) end - local s=d2[2] if s then d2[2]=pack_indexed(s) end - end - end - end - end - elseif kind=="gpos_single" then - local c=step.coverage - if c then - if step.format=="kern" then - step.coverage=pack_normal(c) - else - for g1,d1 in next,c do - c[g1]=pack_indexed(d1) - end - end - end - elseif kind=="gpos_cursive" then - local c=step.coverage - if c then - for g1,d1 in next,c do - local f=d1[2] if f then d1[2]=pack_indexed(f) end - local s=d1[3] if s then d1[3]=pack_indexed(s) end - end - end - elseif kind=="gpos_mark2base" or kind=="gpos_mark2mark" then - local c=step.baseclasses - if c then - for g1,d1 in next,c do - for g2,d2 in next,d1 do - d1[g2]=pack_indexed(d2) - end - end - end - local c=step.coverage - if c then - for g1,d1 in next,c do - d1[2]=pack_indexed(d1[2]) - end - end - elseif kind=="gpos_mark2ligature" then - local c=step.baseclasses - if c then - for g1,d1 in next,c do - for g2,d2 in next,d1 do - for g3,d3 in next,d2 do - d2[g3]=pack_indexed(d3) - end - end - end - end - local c=step.coverage - if c then - for g1,d1 in next,c do - d1[2]=pack_indexed(d1[2]) - end - end - end - local rules=step.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.lookups if r then rule.lookups=pack_mixed (r) end - local r=rule.replacements if r then rule.replacements=pack_flat (r) end - end - end - end - end - if order then - sequence.order=pack_indexed(order) - end - if features then - for script,feature in next,features do - features[script]=pack_normal(feature) - end - end - if flags then - sequence.flags=pack_normal(flags) - end - end - end - if sequences then - packthem(sequences) - end - if sublookups then - packthem(sublookups) - end - if features then - for k,list in next,features do - for feature,spec in next,list do - list[feature]=pack_normal(spec) - end - end - end - if palettes then - for i=1,#palettes do - local p=palettes[i] - for j=1,#p do - p[j]=pack_indexed(p[j]) - 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,descriptions do - local math=description.math - if math then - local kerns=math.kerns - if kerns then - math.kerns=pack_normal(kerns) - end - end - end - local function packthem(sequences) - for i=1,#sequences do - local sequence=sequences[i] - local kind=sequence.type - local steps=sequence.steps - local features=sequence.features - if steps then - for i=1,#steps do - local step=steps[i] - if kind=="gpos_pair" then - local c=step.coverage - if c then - if step.format=="kern" then - else - for g1,d1 in next,c do - for g2,d2 in next,d1 do - d1[g2]=pack_normal(d2) - end - end - end - end - end - local rules=step.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 - if features then - sequence.features=pack_normal(features) - end - end - end - if sequences then - packthem(sequences) - end - if sublookups then - packthem(sublookups) - end - if not success(2,pass) then - end - end - for pass=1,2 do - if trace_packing then - report_otf("start packing: stage 3, pass %s",pass) - end - local pack_normal,pack_indexed,pack_flat,pack_boolean,pack_mixed=packers(pass) - local function packthem(sequences) - for i=1,#sequences do - local sequence=sequences[i] - local kind=sequence.type - local steps=sequence.steps - local features=sequence.features - if steps then - for i=1,#steps do - local step=steps[i] - if kind=="gpos_pair" then - local c=step.coverage - if c then - if step.format=="kern" then - else - for g1,d1 in next,c do - c[g1]=pack_normal(d1) - end - end - end - end - end - end - end - end - if sequences then - packthem(sequences) - end - if sublookups then - packthem(sublookups) - end - end - end - end -end -local unpacked_mt={ - __index=function(t,k) - t[k]=false - return k - end -} -function readers.unpack(data) - if data then - local tables=data.tables - if tables then - local resources=data.resources - local descriptions=data.descriptions or data.glyphs - local sequences=resources.sequences - local sublookups=resources.sublookups - local features=resources.features - local palettes=resources.colorpalettes - local unpacked={} - setmetatable(unpacked,unpacked_mt) - for unicode,description in next,descriptions do - local tv=tables[description.boundingbox] - if tv then - description.boundingbox=tv - 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 - end - local function unpackthem(sequences) - for i=1,#sequences do - local sequence=sequences[i] - local kind=sequence.type - local steps=sequence.steps - local order=sequence.order - local features=sequence.features - local flags=sequence.flags - local markclass=sequence.markclass - if steps then - for i=1,#steps do - local step=steps[i] - if kind=="gpos_pair" then - local c=step.coverage - if c then - if step.format=="kern" then - for g1,d1 in next,c do - local tv=tables[d1] - if tv then - c[g1]=tv - end - end - else - for g1,d1 in next,c do - local tv=tables[d1] - if tv then - c[g1]=tv - d1=tv - end - for g2,d2 in next,d1 do - local tv=tables[d2] - if tv then - d1[g2]=tv - d2=tv - end - local f=tables[d2[1]] if f then d2[1]=f end - local s=tables[d2[2]] if s then d2[2]=s end - end - end - end - end - elseif kind=="gpos_single" then - local c=step.coverage - if c then - if step.format=="kern" then - local tv=tables[c] - if tv then - step.coverage=tv - end - else - for g1,d1 in next,c do - local tv=tables[d1] - if tv then - c[g1]=tv - end - end - end - end - elseif kind=="gpos_cursive" then - local c=step.coverage - if c then - for g1,d1 in next,c do - local f=tables[d1[2]] if f then d1[2]=f end - local s=tables[d1[3]] if s then d1[3]=s end - end - end - elseif kind=="gpos_mark2base" or kind=="gpos_mark2mark" then - local c=step.baseclasses - if c then - for g1,d1 in next,c do - for g2,d2 in next,d1 do - local tv=tables[d2] - if tv then - d1[g2]=tv - end - end - end - end - local c=step.coverage - if c then - for g1,d1 in next,c do - local tv=tables[d1[2]] - if tv then - d1[2]=tv - end - end - end - elseif kind=="gpos_mark2ligature" then - local c=step.baseclasses - if c then - for g1,d1 in next,c do - for g2,d2 in next,d1 do - for g3,d3 in next,d2 do - local tv=tables[d2[g3]] - if tv then - d2[g3]=tv - end - end - end - end - end - local c=step.coverage - if c then - for g1,d1 in next,c do - local tv=tables[d1[2]] - if tv then - d1[2]=tv - end - end - end - end - local rules=step.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=tv - end - for i=1,#before do - local tv=tables[before[i]] - if tv then - before[i]=tv - end - end - end - local after=rule.after - if after then - local tv=tables[after] - if tv then - rule.after=tv - after=tv - end - for i=1,#after do - local tv=tables[after[i]] - if tv then - after[i]=tv - end - end - end - local current=rule.current - if current then - local tv=tables[current] - if tv then - rule.current=tv - current=tv - end - for i=1,#current do - local tv=tables[current[i]] - if tv then - current[i]=tv - end - end - end - local lookups=rule.lookups - if lookups then - local tv=tables[lookups] - if tv then - rule.lookups=tv - end - end - local replacements=rule.replacements - if replacements then - local tv=tables[replacements] - if tv then - rule.replacements=tv - end - end - end - end - end - end - if features then - local tv=tables[features] - if tv then - sequence.features=tv - features=tv - end - for script,feature in next,features do - local tv=tables[feature] - if tv then - features[script]=tv - end - end - end - if order then - local tv=tables[order] - if tv then - sequence.order=tv - end - end - if flags then - local tv=tables[flags] - if tv then - sequence.flags=tv - end - end - end - end - if sequences then - unpackthem(sequences) - end - if sublookups then - unpackthem(sublookups) - end - if features then - for k,list in next,features do - for feature,spec in next,list do - local tv=tables[spec] - if tv then - list[feature]=tv - end - end - end - end - if palettes then - for i=1,#palettes do - local p=palettes[i] - for j=1,#p do - local tv=tables[p[j]] - if tv then - p[j]=tv - end - end - end - end - data.tables=nil - end - end -end -local mt={ - __index=function(t,k) - if k=="height" then - local ht=t.boundingbox[4] - return ht<0 and 0 or ht - elseif k=="depth" then - local dp=-t.boundingbox[2] - return dp<0 and 0 or dp - elseif k=="width" then - return 0 - elseif k=="name" then - return forcenotdef and ".notdef" - end - end -} -local function sameformat(sequence,steps,first,nofsteps,kind) - return true -end -local function mergesteps_1(lookup,strict) - local steps=lookup.steps - local nofsteps=lookup.nofsteps - local first=steps[1] - if strict then - local f=first.format - for i=2,nofsteps do - if steps[i].format~=f then - report("not merging %a steps of %a lookup %a, different formats",nofsteps,lookup.type,lookup.name) - return 0 - end - end - end - report("merging %a steps of %a lookup %a",nofsteps,lookup.type,lookup.name) - local target=first.coverage - for i=2,nofsteps do - for k,v in next,steps[i].coverage do - if not target[k] then - target[k]=v - end - end - end - lookup.nofsteps=1 - lookup.merged=true - lookup.steps={ first } - return nofsteps-1 -end -local function mergesteps_2(lookup,strict) - local steps=lookup.steps - local nofsteps=lookup.nofsteps - local first=steps[1] - if strict then - local f=first.format - for i=2,nofsteps do - if steps[i].format~=f then - report("not merging %a steps of %a lookup %a, different formats",nofsteps,lookup.type,lookup.name) - return 0 - end - end - end - report("merging %a steps of %a lookup %a",nofsteps,lookup.type,lookup.name) - local target=first.coverage - for i=2,nofsteps do - for k,v in next,steps[i].coverage do - local tk=target[k] - if tk then - for k,v in next,v do - if not tk[k] then - tk[k]=v - end - end - else - target[k]=v - end - end - end - lookup.nofsteps=1 - lookup.steps={ first } - return nofsteps-1 -end -local function mergesteps_3(lookup,strict) - local steps=lookup.steps - local nofsteps=lookup.nofsteps - local first=steps[1] - report("merging %a steps of %a lookup %a",nofsteps,lookup.type,lookup.name) - local baseclasses={} - local coverage={} - local used={} - for i=1,nofsteps do - local offset=i*10 - local step=steps[i] - for k,v in sortedhash(step.baseclasses) do - baseclasses[offset+k]=v - end - for k,v in next,step.coverage do - local tk=coverage[k] - if tk then - for k,v in next,v do - if not tk[k] then - tk[k]=v - local c=offset+v[1] - v[1]=c - if not used[c] then - used[c]=true - end - end - end - else - coverage[k]=v - local c=offset+v[1] - v[1]=c - if not used[c] then - used[c]=true - end - end - end - end - for k,v in next,baseclasses do - if not used[k] then - baseclasses[k]=nil - report("discarding not used baseclass %i",k) - end - end - first.baseclasses=baseclasses - first.coverage=coverage - lookup.nofsteps=1 - lookup.steps={ first } - return nofsteps-1 -end -local function nested(old,new) - for k,v in next,old do - if k=="ligature" then - if not new.ligature then - new.ligature=v - end - else - local n=new[k] - if n then - nested(v,n) - else - new[k]=v - end - end - end -end -local function mergesteps_4(lookup) - local steps=lookup.steps - local nofsteps=lookup.nofsteps - local first=steps[1] - report("merging %a steps of %a lookup %a",nofsteps,lookup.type,lookup.name) - local target=first.coverage - for i=2,nofsteps do - for k,v in next,steps[i].coverage do - local tk=target[k] - if tk then - nested(v,tk) - else - target[k]=v - end - end - end - lookup.nofsteps=1 - lookup.steps={ first } - return nofsteps-1 -end -local function checkkerns(lookup) - local steps=lookup.steps - local nofsteps=lookup.nofsteps - for i=1,nofsteps do - local step=steps[i] - if step.format=="pair" then - local coverage=step.coverage - local kerns=true - for g1,d1 in next,coverage do - if d1[1]~=0 or d1[2]~=0 or d1[4]~=0 then - kerns=false - break - end - end - if kerns then - report("turning pairs of step %a of %a lookup %a into kerns",i,lookup.type,lookup.name) - for g1,d1 in next,coverage do - coverage[g1]=d1[3] - end - step.format="kern" - end - end - end -end -local function checkpairs(lookup) - local steps=lookup.steps - local nofsteps=lookup.nofsteps - local kerned=0 - for i=1,nofsteps do - local step=steps[i] - if step.format=="pair" then - local coverage=step.coverage - local kerns=true - for g1,d1 in next,coverage do - for g2,d2 in next,d1 do - if d2[2] then - kerns=false - break - else - local v=d2[1] - if v[1]~=0 or v[2]~=0 or v[4]~=0 then - kerns=false - break - end - end - end - end - if kerns then - report("turning pairs of step %a of %a lookup %a into kerns",i,lookup.type,lookup.name) - for g1,d1 in next,coverage do - for g2,d2 in next,d1 do - d1[g2]=d2[1][3] - end - end - step.format="kern" - kerned=kerned+1 - end - end - end - return kerned -end -function readers.compact(data) - if not data or data.compacted then - return - else - data.compacted=true - end - local resources=data.resources - local merged=0 - local kerned=0 - local allsteps=0 - local function compact(what) - local lookups=resources[what] - if lookups then - for i=1,#lookups do - local lookup=lookups[i] - local nofsteps=lookup.nofsteps - allsteps=allsteps+nofsteps - if nofsteps>1 then - local kind=lookup.type - if kind=="gsub_single" or kind=="gsub_alternate" or kind=="gsub_multiple" then - merged=merged+mergesteps_1(lookup) - elseif kind=="gsub_ligature" then - merged=merged+mergesteps_4(lookup) - elseif kind=="gpos_single" then - merged=merged+mergesteps_1(lookup,true) - checkkerns(lookup) - elseif kind=="gpos_pair" then - merged=merged+mergesteps_2(lookup,true) - kerned=kerned+checkpairs(lookup) - elseif kind=="gpos_cursive" then - merged=merged+mergesteps_2(lookup) - elseif kind=="gpos_mark2mark" or kind=="gpos_mark2base" or kind=="gpos_mark2ligature" then - merged=merged+mergesteps_3(lookup) - end - end - end - else - report("no lookups in %a",what) - end - end - compact("sequences") - compact("sublookups") - if merged>0 then - report("%i steps of %i removed due to merging",merged,allsteps) - end - if kerned>0 then - report("%i steps of %i steps turned from pairs into kerns",kerned,allsteps) - end -end -function readers.expand(data) - if not data or data.expanded then - return - else - data.expanded=true - end - local resources=data.resources - local sublookups=resources.sublookups - local sequences=resources.sequences - local markclasses=resources.markclasses - local descriptions=data.descriptions - if descriptions then - local defaultwidth=resources.defaultwidth or 0 - local defaultheight=resources.defaultheight or 0 - local defaultdepth=resources.defaultdepth or 0 - local basename=trace_markwidth and file.basename(resources.filename) - for u,d in next,descriptions do - local bb=d.boundingbox - local wd=d.width - if not wd then - d.width=defaultwidth - elseif trace_markwidth and wd~=0 and d.class=="mark" then - report("mark %a with width %b found in %a",d.name or "<noname>",wd,basename) - end - if bb then - local ht=bb[4] - local dp=-bb[2] - if ht==0 or ht<0 then - else - d.height=ht - end - if dp==0 or dp<0 then - else - d.depth=dp - end - end - end - end - local function expandlookups(sequences) - if sequences then - for i=1,#sequences do - local sequence=sequences[i] - local steps=sequence.steps - if steps then - local kind=sequence.type - local markclass=sequence.markclass - if markclass then - if not markclasses then - report_warning("missing markclasses") - sequence.markclass=false - else - sequence.markclass=markclasses[markclass] - end - end - for i=1,sequence.nofsteps do - local step=steps[i] - local baseclasses=step.baseclasses - if baseclasses then - local coverage=step.coverage - for k,v in next,coverage do - v[1]=baseclasses[v[1]] - end - elseif kind=="gpos_cursive" then - local coverage=step.coverage - for k,v in next,coverage do - v[1]=coverage - end - end - local rules=step.rules - if rules then - local rulehash={} - local rulesize=0 - local coverage={} - local lookuptype=sequence.type - step.coverage=coverage - for nofrules=1,#rules do - local rule=rules[nofrules] - local current=rule.current - local before=rule.before - local after=rule.after - local replacements=rule.replacements or false - local sequence={} - local nofsequences=0 - if before then - for n=1,#before do - nofsequences=nofsequences+1 - sequence[nofsequences]=before[n] - end - end - local start=nofsequences+1 - for n=1,#current do - nofsequences=nofsequences+1 - sequence[nofsequences]=current[n] - end - local stop=nofsequences - if after then - for n=1,#after do - nofsequences=nofsequences+1 - sequence[nofsequences]=after[n] - end - end - local lookups=rule.lookups or false - local subtype=nil - if lookups then - for k,v in next,lookups do - local lookup=sublookups[v] - if lookup then - lookups[k]=lookup - if not subtype then - subtype=lookup.type - end - else - end - end - end - if sequence[1] then - rulesize=rulesize+1 - rulehash[rulesize]={ - nofrules, - lookuptype, - sequence, - start, - stop, - lookups, - replacements, - subtype, - } - for unic in next,sequence[start] do - local cu=coverage[unic] - if not cu then - coverage[unic]=rulehash - end - end - end - end - end - end - end - end - end - end - expandlookups(sequences) - expandlookups(sublookups) -end - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['font-otl']={ - version=1.001, - comment="companion to font-ini.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files", -} -local gmatch,find,match,lower,strip=string.gmatch,string.find,string.match,string.lower,string.strip -local type,next,tonumber,tostring,unpack=type,next,tonumber,tostring,unpack -local abs=math.abs -local derivetable=table.derive -local formatters=string.formatters -local setmetatableindex=table.setmetatableindex -local allocate=utilities.storage.allocate -local registertracker=trackers.register -local registerdirective=directives.register -local starttiming=statistics.starttiming -local stoptiming=statistics.stoptiming -local elapsedtime=statistics.elapsedtime -local findbinfile=resolvers.findbinfile -local trace_loading=false registertracker("otf.loading",function(v) trace_loading=v end) -local trace_features=false registertracker("otf.features",function(v) trace_features=v end) -local trace_defining=false registertracker("fonts.defining",function(v) trace_defining=v end) -local report_otf=logs.reporter("fonts","otf loading") -local fonts=fonts -local otf=fonts.handlers.otf -otf.version=3.027 -otf.cache=containers.define("fonts","otl",otf.version,true) -otf.svgcache=containers.define("fonts","svg",otf.version,true) -otf.pdfcache=containers.define("fonts","pdf",otf.version,true) -otf.svgenabled=false -local otfreaders=otf.readers -local hashes=fonts.hashes -local definers=fonts.definers -local readers=fonts.readers -local constructors=fonts.constructors -local otffeatures=constructors.features.otf -local registerotffeature=otffeatures.register -local otfenhancers=constructors.enhancers.otf -local registerotfenhancer=otfenhancers.register -local forceload=false -local cleanup=0 -local syncspace=true -local forcenotdef=false -local applyruntimefixes=fonts.treatments and fonts.treatments.applyfixes -local wildcard="*" -local default="dflt" -local formats=fonts.formats -formats.otf="opentype" -formats.ttf="truetype" -formats.ttc="truetype" -registerdirective("fonts.otf.loader.cleanup",function(v) cleanup=tonumber(v) or (v and 1) or 0 end) -registerdirective("fonts.otf.loader.force",function(v) forceload=v end) -registerdirective("fonts.otf.loader.syncspace",function(v) syncspace=v end) -registerdirective("fonts.otf.loader.forcenotdef",function(v) forcenotdef=v end) -registerotfenhancer("check extra features",function() end) -function otf.load(filename,sub,featurefile) - local featurefile=nil - local base=file.basename(file.removesuffix(filename)) - local name=file.removesuffix(base) - local attr=lfs.attributes(filename) - local size=attr and attr.size or 0 - local time=attr and attr.modification or 0 - if featurefile then - name=name.."@"..file.removesuffix(file.basename(featurefile)) - end - if sub=="" then - sub=false - end - local hash=name - if sub then - hash=hash.."-"..sub - end - hash=containers.cleanname(hash) - local featurefiles - if featurefile then - featurefiles={} - for s in gmatch(featurefile,"[^,]+") do - local name=resolvers.findfile(file.addsuffix(s,'fea'),'fea') or "" - if name=="" then - report_otf("loading error, no featurefile %a",s) - else - local attr=lfs.attributes(name) - featurefiles[#featurefiles+1]={ - name=name, - size=attr and attr.size or 0, - time=attr and attr.modification or 0, - } - end - end - if #featurefiles==0 then - featurefiles=nil - end - end - local data=containers.read(otf.cache,hash) - local reload=not data or data.size~=size or data.time~=time or data.tableversion~=otfreaders.tableversion - if forceload then - report_otf("forced reload of %a due to hard coded flag",filename) - reload=true - end - if reload then - report_otf("loading %a, hash %a",filename,hash) - starttiming(otfreaders) - data=otfreaders.loadfont(filename,sub or 1) - if data then - local resources=data.resources - local svgshapes=resources.svgshapes - if svgshapes then - resources.svgshapes=nil - if otf.svgenabled then - local timestamp=os.date() - containers.write(otf.svgcache,hash,{ - svgshapes=svgshapes, - timestamp=timestamp, - }) - data.properties.svg={ - hash=hash, - timestamp=timestamp, - } - end - end - otfreaders.compact(data) - otfreaders.rehash(data,"unicodes") - otfreaders.addunicodetable(data) - otfreaders.extend(data) - otfreaders.pack(data) - report_otf("loading done") - report_otf("saving %a in cache",filename) - data=containers.write(otf.cache,hash,data) - if cleanup>1 then - collectgarbage("collect") - end - stoptiming(otfreaders) - if elapsedtime then - report_otf("loading, optimizing, packing and caching time %s",elapsedtime(otfreaders)) - end - if cleanup>3 then - collectgarbage("collect") - end - data=containers.read(otf.cache,hash) - if cleanup>2 then - collectgarbage("collect") - end - else - data=nil - report_otf("loading failed due to read error") - end - end - if data then - if trace_defining then - report_otf("loading from cache using hash %a",hash) - end - otfreaders.unpack(data) - otfreaders.expand(data) - otfreaders.addunicodetable(data) - otfenhancers.apply(data,filename,data) - if applyruntimefixes then - applyruntimefixes(filename,data) - end - data.metadata.math=data.resources.mathconstants - end - return data -end -function otf.setfeatures(tfmdata,features) - local okay=constructors.initializefeatures("otf",tfmdata,features,trace_features,report_otf) - if okay then - return constructors.collectprocessors("otf",tfmdata,features,trace_features,report_otf) - else - return {} - end -end -local function copytotfm(data,cache_id) - if data then - local metadata=data.metadata - local properties=derivetable(data.properties) - local descriptions=derivetable(data.descriptions) - local goodies=derivetable(data.goodies) - local characters={} - local parameters={} - local mathparameters={} - local resources=data.resources - local unicodes=resources.unicodes - local spaceunits=500 - local spacer="space" - local designsize=metadata.designsize or 100 - local minsize=metadata.minsize or designsize - local maxsize=metadata.maxsize or designsize - local mathspecs=metadata.math - if designsize==0 then - designsize=100 - minsize=100 - maxsize=100 - end - if mathspecs then - for name,value in next,mathspecs do - mathparameters[name]=value - end - end - for unicode in next,data.descriptions do - characters[unicode]={} - end - if mathspecs then - for unicode,character in next,characters do - local d=descriptions[unicode] - local m=d.math - if m then - local italic=m.italic - local vitalic=m.vitalic - local variants=m.hvariants - local parts=m.hparts - if variants then - local c=character - for i=1,#variants do - local un=variants[i] - c.next=un - c=characters[un] - end - c.horiz_variants=parts - elseif parts then - character.horiz_variants=parts - italic=m.hitalic - end - local variants=m.vvariants - local parts=m.vparts - if variants then - local c=character - for i=1,#variants do - local un=variants[i] - c.next=un - c=characters[un] - end - c.vert_variants=parts - elseif parts then - character.vert_variants=parts - end - if italic and italic~=0 then - character.italic=italic - end - if vitalic and vitalic~=0 then - character.vert_italic=vitalic - end - local accent=m.accent - if accent then - character.accent=accent - end - local kerns=m.kerns - if kerns then - character.mathkerns=kerns - end - end - end - end - local filename=constructors.checkedfilename(resources) - local fontname=metadata.fontname - local fullname=metadata.fullname or fontname - local psname=fontname or fullname - local units=metadata.units or 1000 - if units==0 then - units=1000 - metadata.units=1000 - report_otf("changing %a units to %a",0,units) - end - local monospaced=metadata.monospaced - local charwidth=metadata.averagewidth - local charxheight=metadata.xheight - local italicangle=metadata.italicangle - local hasitalics=metadata.hasitalics - properties.monospaced=monospaced - properties.hasitalics=hasitalics - parameters.italicangle=italicangle - parameters.charwidth=charwidth - parameters.charxheight=charxheight - local space=0x0020 - local emdash=0x2014 - if monospaced then - if descriptions[space] then - spaceunits,spacer=descriptions[space].width,"space" - end - if not spaceunits and descriptions[emdash] then - spaceunits,spacer=descriptions[emdash].width,"emdash" - end - if not spaceunits and charwidth then - spaceunits,spacer=charwidth,"charwidth" - end - else - if descriptions[space] then - spaceunits,spacer=descriptions[space].width,"space" - end - if not spaceunits and descriptions[emdash] then - spaceunits,spacer=descriptions[emdash].width/2,"emdash/2" - end - if not spaceunits and charwidth then - spaceunits,spacer=charwidth,"charwidth" - end - end - spaceunits=tonumber(spaceunits) or units/2 - parameters.slant=0 - parameters.space=spaceunits - parameters.space_stretch=1*units/2 - parameters.space_shrink=1*units/3 - parameters.x_height=2*units/5 - parameters.quad=units - if spaceunits<2*units/5 then - end - if italicangle and italicangle~=0 then - parameters.italicangle=italicangle - parameters.italicfactor=math.cos(math.rad(90+italicangle)) - parameters.slant=- math.tan(italicangle*math.pi/180) - end - if monospaced then - parameters.space_stretch=0 - parameters.space_shrink=0 - elseif syncspace then - parameters.space_stretch=spaceunits/2 - parameters.space_shrink=spaceunits/3 - end - parameters.extra_space=parameters.space_shrink - if charxheight then - parameters.x_height=charxheight - else - local x=0x0078 - if x then - local x=descriptions[x] - if x then - parameters.x_height=x.height - end - end - end - parameters.designsize=(designsize/10)*65536 - parameters.minsize=(minsize/10)*65536 - parameters.maxsize=(maxsize/10)*65536 - parameters.ascender=abs(metadata.ascender or 0) - parameters.descender=abs(metadata.descender or 0) - parameters.units=units - properties.space=spacer - properties.encodingbytes=2 - properties.format=data.format or formats.otf - properties.noglyphnames=true - properties.filename=filename - properties.fontname=fontname - properties.fullname=fullname - properties.psname=psname - properties.name=filename or fullname - return { - characters=characters, - descriptions=descriptions, - parameters=parameters, - mathparameters=mathparameters, - resources=resources, - properties=properties, - goodies=goodies, - } - end -end -local converters={ - woff={ - cachename="webfonts", - action=otf.readers.woff2otf, - } -} -local function checkconversion(specification) - local filename=specification.filename - local converter=converters[lower(file.suffix(filename))] - if converter then - local base=file.basename(filename) - local name=file.removesuffix(base) - local attr=lfs.attributes(filename) - local size=attr and attr.size or 0 - local time=attr and attr.modification or 0 - if size>0 then - local cleanname=containers.cleanname(name) - local cachename=caches.setfirstwritablefile(cleanname,converter.cachename) - if not io.exists(cachename) or (time~=lfs.attributes(cachename).modification) then - report_otf("caching font %a in %a",filename,cachename) - converter.action(filename,cachename) - lfs.touch(cachename,time,time) - end - specification.filename=cachename - end - end -end -local function otftotfm(specification) - local cache_id=specification.hash - local tfmdata=containers.read(constructors.cache,cache_id) - if not tfmdata then - checkconversion(specification) - local name=specification.name - local sub=specification.sub - local subindex=specification.subindex - local filename=specification.filename - local features=specification.features.normal - local rawdata=otf.load(filename,sub,features and features.featurefile) - if rawdata and next(rawdata) then - local descriptions=rawdata.descriptions - rawdata.lookuphash={} - tfmdata=copytotfm(rawdata,cache_id) - if tfmdata and next(tfmdata) then - local features=constructors.checkedfeatures("otf",features) - local shared=tfmdata.shared - if not shared then - shared={} - tfmdata.shared=shared - end - shared.rawdata=rawdata - shared.dynamics={} - tfmdata.changed={} - shared.features=features - shared.processes=otf.setfeatures(tfmdata,features) - end - end - containers.write(constructors.cache,cache_id,tfmdata) - end - return tfmdata -end -local function read_from_otf(specification) - local tfmdata=otftotfm(specification) - if tfmdata then - tfmdata.properties.name=specification.name - tfmdata.properties.sub=specification.sub - tfmdata=constructors.scale(tfmdata,specification) - local allfeatures=tfmdata.shared.features or specification.features.normal - constructors.applymanipulators("otf",tfmdata,allfeatures,trace_features,report_otf) - constructors.setname(tfmdata,specification) - fonts.loggers.register(tfmdata,file.suffix(specification.filename),specification) - end - return tfmdata -end -local function checkmathsize(tfmdata,mathsize) - local mathdata=tfmdata.shared.rawdata.metadata.math - local mathsize=tonumber(mathsize) - if mathdata then - local parameters=tfmdata.parameters - parameters.scriptpercentage=mathdata.ScriptPercentScaleDown - parameters.scriptscriptpercentage=mathdata.ScriptScriptPercentScaleDown - parameters.mathsize=mathsize - end -end -registerotffeature { - name="mathsize", - description="apply mathsize specified in the font", - initializers={ - base=checkmathsize, - node=checkmathsize, - } -} -function otf.collectlookups(rawdata,kind,script,language) - if not kind then - return - end - if not script then - script=default - end - if not language then - language=default - end - local lookupcache=rawdata.lookupcache - if not lookupcache then - lookupcache={} - rawdata.lookupcache=lookupcache - end - local kindlookup=lookupcache[kind] - if not kindlookup then - kindlookup={} - lookupcache[kind]=kindlookup - end - local scriptlookup=kindlookup[script] - if not scriptlookup then - scriptlookup={} - kindlookup[script]=scriptlookup - end - local languagelookup=scriptlookup[language] - if not languagelookup then - local sequences=rawdata.resources.sequences - local featuremap={} - local featurelist={} - if sequences then - for s=1,#sequences do - local sequence=sequences[s] - local features=sequence.features - if features then - features=features[kind] - if features then - features=features[script] or features[wildcard] - if features then - features=features[language] or features[wildcard] - if features then - if not featuremap[sequence] then - featuremap[sequence]=true - featurelist[#featurelist+1]=sequence - end - end - end - end - end - end - if #featurelist==0 then - featuremap,featurelist=false,false - end - else - featuremap,featurelist=false,false - end - languagelookup={ featuremap,featurelist } - scriptlookup[language]=languagelookup - end - return unpack(languagelookup) -end -local function getgsub(tfmdata,k,kind,value) - local shared=tfmdata.shared - local rawdata=shared and shared.rawdata - if rawdata then - local sequences=rawdata.resources.sequences - if sequences then - local properties=tfmdata.properties - local validlookups,lookuplist=otf.collectlookups(rawdata,kind,properties.script,properties.language) - if validlookups then - for i=1,#lookuplist do - local lookup=lookuplist[i] - local steps=lookup.steps - local nofsteps=lookup.nofsteps - for i=1,nofsteps do - local coverage=steps[i].coverage - if coverage then - local found=coverage[k] - if found then - return found,lookup.type - end - end - end - end - end - end - end -end -otf.getgsub=getgsub -function otf.getsubstitution(tfmdata,k,kind,value) - local found,kind=getgsub(tfmdata,k,kind,value) - if not found then - elseif kind=="gsub_single" then - return found - elseif kind=="gsub_alternate" then - local choice=tonumber(value) or 1 - return found[choice] or found[1] or k - end - return k -end -otf.getalternate=otf.getsubstitution -function otf.getmultiple(tfmdata,k,kind) - local found,kind=getgsub(tfmdata,k,kind) - if found and kind=="gsub_multiple" then - return found - end - return { k } -end -function otf.getkern(tfmdata,left,right,kind) - local kerns=getgsub(tfmdata,left,kind or "kern",true) - if kerns then - local found=kerns[right] - local kind=type(found) - if kind=="table" then - found=found[1][3] - elseif kind~="number" then - found=false - end - if found then - return found*tfmdata.parameters.factor - end - end - return 0 -end -local function check_otf(forced,specification,suffix) - local name=specification.name - if forced then - name=specification.forcedname - end - local fullname=findbinfile(name,suffix) or "" - if fullname=="" then - fullname=fonts.names.getfilename(name,suffix) or "" - end - if fullname~="" and not fonts.names.ignoredfile(fullname) then - specification.filename=fullname - return read_from_otf(specification) - end -end -local function opentypereader(specification,suffix) - local forced=specification.forced or "" - if formats[forced] then - return check_otf(true,specification,forced) - else - return check_otf(false,specification,suffix) - end -end -readers.opentype=opentypereader -function readers.otf(specification) return opentypereader(specification,"otf") end -function readers.ttf(specification) return opentypereader(specification,"ttf") end -function readers.ttc(specification) return opentypereader(specification,"ttf") end -function readers.woff(specification) - checkconversion(specification) - opentypereader(specification,"") -end -function otf.scriptandlanguage(tfmdata,attr) - local properties=tfmdata.properties - return properties.script or "dflt",properties.language or "dflt" -end -local function justset(coverage,unicode,replacement) - coverage[unicode]=replacement -end -otf.coverup={ - stepkey="steps", - actions={ - chainsubstitution=justset, - chainposition=justset, - substitution=justset, - alternate=justset, - multiple=justset, - kern=justset, - pair=justset, - ligature=function(coverage,unicode,ligature) - local first=ligature[1] - local tree=coverage[first] - if not tree then - tree={} - coverage[first]=tree - end - for i=2,#ligature do - local l=ligature[i] - local t=tree[l] - if not t then - t={} - tree[l]=t - end - tree=t - end - tree.ligature=unicode - end, - }, - register=function(coverage,featuretype,format) - return { - format=format, - coverage=coverage, - } - end -} - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['font-oto']={ - version=1.001, - comment="companion to font-ini.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local concat,unpack=table.concat,table.unpack -local insert,remove=table.insert,table.remove -local format,gmatch,gsub,find,match,lower,strip=string.format,string.gmatch,string.gsub,string.find,string.match,string.lower,string.strip -local type,next,tonumber,tostring,rawget=type,next,tonumber,tostring,rawget -local trace_baseinit=false trackers.register("otf.baseinit",function(v) trace_baseinit=v end) -local trace_singles=false trackers.register("otf.singles",function(v) trace_singles=v end) -local trace_multiples=false trackers.register("otf.multiples",function(v) trace_multiples=v end) -local trace_alternatives=false trackers.register("otf.alternatives",function(v) trace_alternatives=v end) -local trace_ligatures=false trackers.register("otf.ligatures",function(v) trace_ligatures=v end) -local trace_kerns=false trackers.register("otf.kerns",function(v) trace_kerns=v end) -local trace_preparing=false trackers.register("otf.preparing",function(v) trace_preparing=v end) -local report_prepare=logs.reporter("fonts","otf prepare") -local fonts=fonts -local otf=fonts.handlers.otf -local otffeatures=otf.features -local registerotffeature=otffeatures.register -otf.defaultbasealternate="none" -local wildcard="*" -local default="dflt" -local formatters=string.formatters -local f_unicode=formatters["%U"] -local f_uniname=formatters["%U (%s)"] -local f_unilist=formatters["% t (% t)"] -local function gref(descriptions,n) - if type(n)=="number" then - local name=descriptions[n].name - if name then - return f_uniname(n,name) - else - return f_unicode(n) - end - elseif n then - local num,nam,j={},{},0 - for i=1,#n do - local ni=n[i] - if tonumber(ni) then - j=j+1 - local di=descriptions[ni] - num[j]=f_unicode(ni) - nam[j]=di and di.name or "-" - end - end - return f_unilist(num,nam) - else - return "<error in base mode tracing>" - end -end -local function cref(feature,sequence) - return formatters["feature %a, type %a, chain lookup %a"](feature,sequence.type,sequence.name) -end -local function report_alternate(feature,sequence,descriptions,unicode,replacement,value,comment) - report_prepare("%s: base alternate %s => %s (%S => %S)", - cref(feature,sequence), - gref(descriptions,unicode), - replacement and gref(descriptions,replacement), - value, - comment) -end -local function report_substitution(feature,sequence,descriptions,unicode,substitution) - report_prepare("%s: base substitution %s => %S", - cref(feature,sequence), - gref(descriptions,unicode), - gref(descriptions,substitution)) -end -local function report_ligature(feature,sequence,descriptions,unicode,ligature) - report_prepare("%s: base ligature %s => %S", - cref(feature,sequence), - gref(descriptions,ligature), - gref(descriptions,unicode)) -end -local function report_kern(feature,sequence,descriptions,unicode,otherunicode,value) - report_prepare("%s: base kern %s + %s => %S", - cref(feature,sequence), - gref(descriptions,unicode), - gref(descriptions,otherunicode), - value) -end -local basehash,basehashes,applied={},1,{} -local function registerbasehash(tfmdata) - local properties=tfmdata.properties - local hash=concat(applied," ") - local base=basehash[hash] - if not base then - basehashes=basehashes+1 - base=basehashes - basehash[hash]=base - end - properties.basehash=base - properties.fullname=(properties.fullname or properties.name).."-"..base - applied={} -end -local function registerbasefeature(feature,value) - applied[#applied+1]=feature.."="..tostring(value) -end -local function makefake(tfmdata,name,present) - local resources=tfmdata.resources - local private=resources.private - local character={ intermediate=true,ligatures={} } - resources.unicodes[name]=private - tfmdata.characters[private]=character - tfmdata.descriptions[private]={ name=name } - resources.private=private+1 - present[name]=private - return character -end -local function make_1(present,tree,name) - for k,v in next,tree do - if k=="ligature" then - present[name]=v - else - make_1(present,v,name.."_"..k) - end - end -end -local function make_2(present,tfmdata,characters,tree,name,preceding,unicode,done) - for k,v in next,tree do - if k=="ligature" then - local character=characters[preceding] - if not character then - if trace_baseinit then - report_prepare("weird ligature in lookup %a, current %C, preceding %C",sequence.name,v,preceding) - end - character=makefake(tfmdata,name,present) - end - local ligatures=character.ligatures - if ligatures then - ligatures[unicode]={ char=v } - else - character.ligatures={ [unicode]={ char=v } } - end - if done then - local d=done[name] - if not d then - done[name]={ "dummy",v } - else - d[#d+1]=v - end - end - else - local code=present[name] or unicode - local name=name.."_"..k - make_2(present,tfmdata,characters,v,name,code,k,done) - end - end -end -local function preparesubstitutions(tfmdata,feature,value,validlookups,lookuplist) - local characters=tfmdata.characters - local descriptions=tfmdata.descriptions - local resources=tfmdata.resources - local changed=tfmdata.changed - local ligatures={} - local alternate=tonumber(value) or true and 1 - local defaultalt=otf.defaultbasealternate - local trace_singles=trace_baseinit and trace_singles - local trace_alternatives=trace_baseinit and trace_alternatives - local trace_ligatures=trace_baseinit and trace_ligatures - if not changed then - changed={} - tfmdata.changed=changed - end - for i=1,#lookuplist do - local sequence=lookuplist[i] - local steps=sequence.steps - local kind=sequence.type - if kind=="gsub_single" then - for i=1,#steps do - for unicode,data in next,steps[i].coverage do - if trace_singles then - report_substitution(feature,sequence,descriptions,unicode,data) - end - changed[unicode]=data - end - end - elseif kind=="gsub_alternate" then - for i=1,#steps do - for unicode,data in next,steps[i].coverage do - if not changed[unicode] then - local replacement=data[alternate] - if replacement then - changed[unicode]=replacement - if trace_alternatives then - report_alternate(feature,sequence,descriptions,unicode,replacement,value,"normal") - end - elseif defaultalt=="first" then - replacement=data[1] - changed[unicode]=replacement - if trace_alternatives then - report_alternate(feature,sequence,descriptions,unicode,replacement,value,defaultalt) - end - elseif defaultalt=="last" then - replacement=data[#data] - if trace_alternatives then - report_alternate(feature,sequence,descriptions,unicode,replacement,value,defaultalt) - end - else - if trace_alternatives then - report_alternate(feature,sequence,descriptions,unicode,replacement,value,"unknown") - end - end - end - end - end - elseif kind=="gsub_ligature" then - for i=1,#steps do - for unicode,data in next,steps[i].coverage do - ligatures[#ligatures+1]={ unicode,data,"" } - if trace_ligatures then - report_ligature(feature,sequence,descriptions,unicode,data) - end - end - end - end - end - local nofligatures=#ligatures - if nofligatures>0 then - local characters=tfmdata.characters - local present={} - local done=trace_baseinit and trace_ligatures and {} - for i=1,nofligatures do - local ligature=ligatures[i] - local unicode,tree=ligature[1],ligature[2] - make_1(present,tree,"ctx_"..unicode) - end - for i=1,nofligatures do - local ligature=ligatures[i] - local unicode,tree,lookupname=ligature[1],ligature[2],ligature[3] - make_2(present,tfmdata,characters,tree,"ctx_"..unicode,unicode,unicode,done,sequence) - end - end -end -local function preparepositionings(tfmdata,feature,value,validlookups,lookuplist) - local characters=tfmdata.characters - local descriptions=tfmdata.descriptions - local resources=tfmdata.resources - local properties=tfmdata.properties - local traceindeed=trace_baseinit and trace_kerns - for i=1,#lookuplist do - local sequence=lookuplist[i] - local steps=sequence.steps - local kind=sequence.type - local format=sequence.format - if kind=="gpos_pair" then - for i=1,#steps do - local step=steps[i] - if step.format=="kern" then - for unicode,data in next,steps[i].coverage do - local character=characters[unicode] - local kerns=character.kerns - if not kerns then - kerns={} - character.kerns=kerns - end - if traceindeed then - for otherunicode,kern in next,data do - if not kerns[otherunicode] and kern~=0 then - kerns[otherunicode]=kern - report_kern(feature,sequence,descriptions,unicode,otherunicode,kern) - end - end - else - for otherunicode,kern in next,data do - if not kerns[otherunicode] and kern~=0 then - kerns[otherunicode]=kern - end - end - end - end - else - for unicode,data in next,steps[i].coverage do - local character=characters[unicode] - local kerns=character.kerns - for otherunicode,kern in next,data do - if not kern[2] and not (kerns and kerns[otherunicode]) then - local kern=kern[1] - if kern[1]~=0 or kern[2]~=0 or kern[4]~=0 then - else - kern=kern[3] - if kern~=0 then - if kerns then - kerns[otherunicode]=kern - else - kerns={ [otherunicode]=kern } - character.kerns=kerns - end - if traceindeed then - report_kern(feature,sequence,descriptions,unicode,otherunicode,kern) - end - end - end - end - end - end - end - end - end - end -end -local function initializehashes(tfmdata) -end -local function featuresinitializer(tfmdata,value) - if true then - local starttime=trace_preparing and os.clock() - local features=tfmdata.shared.features - local fullname=tfmdata.properties.fullname or "?" - if features then - initializehashes(tfmdata) - local collectlookups=otf.collectlookups - local rawdata=tfmdata.shared.rawdata - local properties=tfmdata.properties - local script=properties.script - local language=properties.language - local rawresources=rawdata.resources - local rawfeatures=rawresources and rawresources.features - local basesubstitutions=rawfeatures and rawfeatures.gsub - local basepositionings=rawfeatures and rawfeatures.gpos - if basesubstitutions or basepositionings then - local sequences=tfmdata.resources.sequences - for s=1,#sequences do - local sequence=sequences[s] - local sfeatures=sequence.features - if sfeatures then - local order=sequence.order - if order then - for i=1,#order do - local feature=order[i] - local value=features[feature] - if value then - local validlookups,lookuplist=collectlookups(rawdata,feature,script,language) - if not validlookups then - elseif basesubstitutions and basesubstitutions[feature] then - if trace_preparing then - report_prepare("filtering base %s feature %a for %a with value %a","sub",feature,fullname,value) - end - preparesubstitutions(tfmdata,feature,value,validlookups,lookuplist) - registerbasefeature(feature,value) - elseif basepositionings and basepositionings[feature] then - if trace_preparing then - report_prepare("filtering base %a feature %a for %a with value %a","pos",feature,fullname,value) - end - preparepositionings(tfmdata,feature,value,validlookups,lookuplist) - registerbasefeature(feature,value) - end - end - end - end - end - end - end - registerbasehash(tfmdata) - end - if trace_preparing then - report_prepare("preparation time is %0.3f seconds for %a",os.clock()-starttime,fullname) - end - end -end -registerotffeature { - name="features", - description="features", - default=true, - initializers={ - base=featuresinitializer, - } -} -otf.basemodeinitializer=featuresinitializer - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['font-otj']={ - version=1.001, - comment="companion to font-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files", -} -if not nodes.properties then return end -local next,rawget=next,rawget -local fastcopy=table.fastcopy -local registertracker=trackers.register -local trace_injections=false registertracker("fonts.injections",function(v) trace_injections=v end) -local trace_marks=false registertracker("fonts.injections.marks",function(v) trace_marks=v end) -local trace_cursive=false registertracker("fonts.injections.cursive",function(v) trace_cursive=v end) -local trace_spaces=false registertracker("fonts.injections.spaces",function(v) trace_spaces=v end) -local use_advance=false directives.register("fonts.injections.advance",function(v) use_advance=v end) -local report_injections=logs.reporter("fonts","injections") -local report_spaces=logs.reporter("fonts","spaces") -local attributes,nodes,node=attributes,nodes,node -fonts=fonts -local hashes=fonts.hashes -local fontdata=hashes.identifiers -nodes.injections=nodes.injections or {} -local injections=nodes.injections -local tracers=nodes.tracers -local setcolor=tracers and tracers.colors.set -local resetcolor=tracers and tracers.colors.reset -local nodecodes=nodes.nodecodes -local glyph_code=nodecodes.glyph -local disc_code=nodecodes.disc -local kern_code=nodecodes.kern -local glue_code=nodecodes.glue -local nuts=nodes.nuts -local nodepool=nuts.pool -local newkern=nodepool.kern -local tonode=nuts.tonode -local tonut=nuts.tonut -local getfield=nuts.getfield -local setfield=nuts.setfield -local getnext=nuts.getnext -local getprev=nuts.getprev -local getid=nuts.getid -local getfont=nuts.getfont -local getsubtype=nuts.getsubtype -local getchar=nuts.getchar -local getboth=nuts.getboth -local ischar=nuts.is_char -local getdisc=nuts.getdisc -local setdisc=nuts.setdisc -local traverse_id=nuts.traverse_id -local traverse_char=nuts.traverse_char -local insert_node_before=nuts.insert_before -local insert_node_after=nuts.insert_after -local properties=nodes.properties.data -function injections.installnewkern(nk) - newkern=nk or newkern -end -local nofregisteredkerns=0 -local nofregisteredpairs=0 -local nofregisteredmarks=0 -local nofregisteredcursives=0 -local keepregisteredcounts=false -function injections.keepcounts() - keepregisteredcounts=true -end -function injections.resetcounts() - nofregisteredkerns=0 - nofregisteredpairs=0 - nofregisteredmarks=0 - nofregisteredcursives=0 - keepregisteredcounts=false -end -function injections.reset(n) - local p=rawget(properties,n) - if p then - p.injections=false - else - properties[n]=false - end -end -function injections.copy(target,source) - local sp=rawget(properties,source) - if sp then - local tp=rawget(properties,target) - local si=sp.injections - if si then - si=fastcopy(si) - if tp then - tp.injections=si - else - propertydata[target]={ - injections=si, - } - end - elseif tp then - tp.injections=false - else - properties[target]={ injections={} } - end - else - local tp=rawget(properties,target) - if tp then - tp.injections=false - else - properties[target]=false - end - end -end -function injections.setligaindex(n,index) - local p=rawget(properties,n) - if p then - local i=p.injections - if i then - i.ligaindex=index - else - p.injections={ - ligaindex=index - } - end - else - properties[n]={ - injections={ - ligaindex=index - } - } - end -end -function injections.getligaindex(n,default) - local p=rawget(properties,n) - if p then - local i=p.injections - if i then - return i.ligaindex or default - end - end - return default -end -function injections.setcursive(start,nxt,factor,rlmode,exit,entry,tfmstart,tfmnext) - local dx=factor*(exit[1]-entry[1]) - local dy=-factor*(exit[2]-entry[2]) - local ws=tfmstart.width - local wn=tfmnext.width - nofregisteredcursives=nofregisteredcursives+1 - if rlmode<0 then - dx=-(dx+wn) - else - dx=dx-ws - end - if dx==0 then - dx=0 - end - local p=rawget(properties,start) - if p then - local i=p.injections - if i then - i.cursiveanchor=true - else - p.injections={ - cursiveanchor=true, - } - end - else - properties[start]={ - injections={ - cursiveanchor=true, - }, - } - end - local p=rawget(properties,nxt) - if p then - local i=p.injections - if i then - i.cursivex=dx - i.cursivey=dy - else - p.injections={ - cursivex=dx, - cursivey=dy, - } - end - else - properties[nxt]={ - injections={ - cursivex=dx, - cursivey=dy, - }, - } - end - return dx,dy,nofregisteredcursives -end -function injections.setpair(current,factor,rlmode,r2lflag,spec,injection) - local x=factor*spec[1] - local y=factor*spec[2] - local w=factor*spec[3] - local h=factor*spec[4] - if x~=0 or w~=0 or y~=0 or h~=0 then - local yoffset=y-h - local leftkern=x - local rightkern=w-x - if leftkern~=0 or rightkern~=0 or yoffset~=0 then - nofregisteredpairs=nofregisteredpairs+1 - if rlmode and rlmode<0 then - leftkern,rightkern=rightkern,leftkern - end - if not injection then - injection="injections" - end - local p=rawget(properties,current) - if p then - local i=rawget(p,injection) - if i then - if leftkern~=0 then - i.leftkern=(i.leftkern or 0)+leftkern - end - if rightkern~=0 then - i.rightkern=(i.rightkern or 0)+rightkern - end - if yoffset~=0 then - i.yoffset=(i.yoffset or 0)+yoffset - end - elseif leftkern~=0 or rightkern~=0 then - p[injection]={ - leftkern=leftkern, - rightkern=rightkern, - yoffset=yoffset, - } - else - p[injection]={ - yoffset=yoffset, - } - end - elseif leftkern~=0 or rightkern~=0 then - properties[current]={ - [injection]={ - leftkern=leftkern, - rightkern=rightkern, - yoffset=yoffset, - }, - } - else - properties[current]={ - [injection]={ - yoffset=yoffset, - }, - } - end - return x,y,w,h,nofregisteredpairs - end - end - return x,y,w,h -end -function injections.setkern(current,factor,rlmode,x,injection) - local dx=factor*x - if dx~=0 then - nofregisteredkerns=nofregisteredkerns+1 - local p=rawget(properties,current) - if not injection then - injection="injections" - end - if p then - local i=rawget(p,injection) - if i then - i.leftkern=dx+(i.leftkern or 0) - else - p[injection]={ - leftkern=dx, - } - end - else - properties[current]={ - [injection]={ - leftkern=dx, - }, - } - end - return dx,nofregisteredkerns - else - return 0,0 - end -end -function injections.setmark(start,base,factor,rlmode,ba,ma,tfmbase,mkmk,checkmark) - local dx,dy=factor*(ba[1]-ma[1]),factor*(ba[2]-ma[2]) - nofregisteredmarks=nofregisteredmarks+1 - if rlmode>=0 then - dx=tfmbase.width-dx - end - local p=rawget(properties,start) - if p then - local i=p.injections - if i then - if i.markmark then - else - i.markx=dx - i.marky=dy - i.markdir=rlmode or 0 - i.markbase=nofregisteredmarks - i.markbasenode=base - i.markmark=mkmk - i.checkmark=checkmark - end - else - p.injections={ - markx=dx, - marky=dy, - markdir=rlmode or 0, - markbase=nofregisteredmarks, - markbasenode=base, - markmark=mkmk, - checkmark=checkmark, - } - end - else - properties[start]={ - injections={ - markx=dx, - marky=dy, - markdir=rlmode or 0, - markbase=nofregisteredmarks, - markbasenode=base, - markmark=mkmk, - checkmark=checkmark, - }, - } - end - return dx,dy,nofregisteredmarks -end -local function dir(n) - return (n and n<0 and "r-to-l") or (n and n>0 and "l-to-r") or "unset" -end -local function showchar(n,nested) - local char=getchar(n) - report_injections("%wfont %s, char %U, glyph %c",nested and 2 or 0,getfont(n),char,char) -end -local function show(n,what,nested,symbol) - if n then - local p=rawget(properties,n) - if p then - local i=rawget(p,what) - if i then - local leftkern=i.leftkern or 0 - local rightkern=i.rightkern or 0 - local yoffset=i.yoffset or 0 - local markx=i.markx or 0 - local marky=i.marky or 0 - local markdir=i.markdir or 0 - local markbase=i.markbase or 0 - local cursivex=i.cursivex or 0 - local cursivey=i.cursivey or 0 - local ligaindex=i.ligaindex or 0 - local cursbase=i.cursiveanchor - local margin=nested and 4 or 2 - if rightkern~=0 or yoffset~=0 then - report_injections("%w%s pair: lx %p, rx %p, dy %p",margin,symbol,leftkern,rightkern,yoffset) - elseif leftkern~=0 then - report_injections("%w%s kern: dx %p",margin,symbol,leftkern) - end - if markx~=0 or marky~=0 or markbase~=0 then - report_injections("%w%s mark: dx %p, dy %p, dir %s, base %s",margin,symbol,markx,marky,markdir,markbase~=0 and "yes" or "no") - end - if cursivex~=0 or cursivey~=0 then - if cursbase then - report_injections("%w%s curs: base dx %p, dy %p",margin,symbol,cursivex,cursivey) - else - report_injections("%w%s curs: dx %p, dy %p",margin,symbol,cursivex,cursivey) - end - elseif cursbase then - report_injections("%w%s curs: base",margin,symbol) - end - if ligaindex~=0 then - report_injections("%w%s liga: index %i",margin,symbol,ligaindex) - end - end - end - end -end -local function showsub(n,what,where) - report_injections("begin subrun: %s",where) - for n in traverse_id(glyph_code,n) do - showchar(n,where) - show(n,what,where," ") - end - report_injections("end subrun") -end -local function trace(head,where) - report_injections("begin run %s: %s kerns, %s pairs, %s marks and %s cursives registered", - where or "",nofregisteredkerns,nofregisteredpairs,nofregisteredmarks,nofregisteredcursives) - local n=head - while n do - local id=getid(n) - if id==glyph_code then - showchar(n) - show(n,"injections",false," ") - show(n,"preinjections",false,"<") - show(n,"postinjections",false,">") - show(n,"replaceinjections",false,"=") - show(n,"emptyinjections",false,"*") - elseif id==disc_code then - local pre,post,replace=getdisc(n) - if pre then - showsub(pre,"preinjections","pre") - end - if post then - showsub(post,"postinjections","post") - end - if replace then - showsub(replace,"replaceinjections","replace") - end - show(n,"emptyinjections",false,"*") - end - n=getnext(n) - end - report_injections("end run") -end -local function show_result(head) - local current=head - local skipping=false - while current do - local id=getid(current) - if id==glyph_code then - report_injections("char: %C, width %p, xoffset %p, yoffset %p", - getchar(current),getfield(current,"width"),getfield(current,"xoffset"),getfield(current,"yoffset")) - skipping=false - elseif id==kern_code then - report_injections("kern: %p",getfield(current,"kern")) - skipping=false - elseif not skipping then - report_injections() - skipping=true - end - current=getnext(current) - end -end -local function inject_kerns_only(head,where) - head=tonut(head) - if trace_injections then - trace(head,"kerns") - end - local current=head - local prev=nil - local next=nil - local prevdisc=nil - local prevglyph=nil - local pre=nil - local post=nil - local replace=nil - local pretail=nil - local posttail=nil - local replacetail=nil - while current do - local id=getid(current) - local next=getnext(current) - if id==glyph_code then - if getsubtype(current)<256 then - local p=rawget(properties,current) - if p then - local i=p.injections - if i then - local leftkern=i.leftkern - if leftkern and leftkern~=0 then - if use_advance then - setfield(current,"xoffset",leftkern) - setfield(current,"xadvance",leftkern) - else - insert_node_before(head,current,newkern(leftkern)) - end - end - end - if prevdisc then - local done=false - if post then - local i=p.postinjections - if i then - local leftkern=i.leftkern - if leftkern and leftkern~=0 then - if use_advance then - setfield(post,"xadvance",leftkern) - else - insert_node_after(post,posttail,newkern(leftkern)) - done=true - end - end - end - end - if replace then - local i=p.replaceinjections - if i then - local leftkern=i.leftkern - if leftkern and leftkern~=0 then - if use_advance then - setfield(replace,"xadvance",leftkern) - else - insert_node_after(replace,replacetail,newkern(leftkern)) - done=true - end - end - end - else - local i=p.emptyinjections - if i then - local leftkern=i.leftkern - if leftkern and leftkern~=0 then - setfield(prev,"replace",newkern(leftkern)) - end - end - end - if done then - setdisc(prevdisc,pre,post,replace) - end - end - end - end - prevdisc=nil - prevglyph=current - elseif id==disc_code then - pre,post,replace,pretail,posttail,replacetail=getdisc(current,true) - local done=false - if pre then - for n in traverse_char(pre) do - local p=rawget(properties,n) - if p then - local i=p.injections or p.preinjections - if i then - local leftkern=i.leftkern - if leftkern and leftkern~=0 then - if use_advance then - setfield(pre,"xoffset",leftkern) - setfield(pre,"xadvance",leftkern) - else - pre=insert_node_before(pre,n,newkern(leftkern)) - done=true - end - end - end - end - end - end - if post then - for n in traverse_char(post) do - local p=rawget(properties,n) - if p then - local i=p.injections or p.postinjections - if i then - local leftkern=i.leftkern - if leftkern and leftkern~=0 then - if use_advance then - setfield(post,"xoffset",leftkern) - setfield(post,"xadvance",leftkern) - else - post=insert_node_before(post,n,newkern(leftkern)) - done=true - end - end - end - end - end - end - if replace then - for n in traverse_char(replace) do - local p=rawget(properties,n) - if p then - local i=p.injections or p.replaceinjections - if i then - local leftkern=i.leftkern - if leftkern and leftkern~=0 then - if use_advance then - setfield(replace,"xoffset",leftkern) - setfield(replace,"xadvance",leftkern) - else - replace=insert_node_before(replace,n,newkern(leftkern)) - done=true - end - end - end - end - end - end - if done then - setdisc(current,pre,post,replace) - end - prevglyph=nil - prevdisc=current - else - prevglyph=nil - prevdisc=nil - end - prev=current - current=next - end - if keepregisteredcounts then - keepregisteredcounts=false - else - nofregisteredkerns=0 - end - return tonode(head),true -end -local function inject_pairs_only(head,where) - head=tonut(head) - if trace_injections then - trace(head,"pairs") - end - local current=head - local prev=nil - local next=nil - local prevdisc=nil - local prevglyph=nil - local pre=nil - local post=nil - local replace=nil - local pretail=nil - local posttail=nil - local replacetail=nil - while current do - local id=getid(current) - local next=getnext(current) - if id==glyph_code then - if getsubtype(current)<256 then - local p=rawget(properties,current) - if p then - local i=p.injections - if i then - local yoffset=i.yoffset - if yoffset and yoffset~=0 then - setfield(current,"yoffset",yoffset) - end - local leftkern=i.leftkern - if leftkern and leftkern~=0 then - head=insert_node_before(head,current,newkern(leftkern)) - end - local rightkern=i.rightkern - if rightkern and rightkern~=0 then - insert_node_after(head,current,newkern(rightkern)) - end - else - local i=p.emptyinjections - if i then - local rightkern=i.rightkern - if rightkern and rightkern~=0 then - if next and getid(next)==disc_code then - if replace then - else - setfield(next,"replace",newkern(rightkern)) - end - end - end - end - end - if prevdisc then - local done=false - if post then - local i=p.postinjections - if i then - local leftkern=i.leftkern - if leftkern and leftkern~=0 then - insert_node_after(post,posttail,newkern(leftkern)) - done=true - end - end - end - if replace then - local i=p.replaceinjections - if i then - local leftkern=i.leftkern - if leftkern and leftkern~=0 then - insert_node_after(replace,replacetail,newkern(leftkern)) - done=true - end - end - else - local i=p.emptyinjections - if i then - local leftkern=i.leftkern - if leftkern and leftkern~=0 then - setfield(prev,"replace",newkern(leftkern)) - end - end - end - if done then - setdisc(prevdisc,pre,post,replace) - end - end - end - end - prevdisc=nil - prevglyph=current - elseif id==disc_code then - pre,post,replace,pretail,posttail,replacetail=getdisc(current,true) - local done=false - if pre then - for n in traverse_char(pre) do - local p=rawget(properties,n) - if p then - local i=p.injections or p.preinjections - if i then - local yoffset=i.yoffset - if yoffset and yoffset~=0 then - setfield(n,"yoffset",yoffset) - end - local leftkern=i.leftkern - if leftkern and leftkern~=0 then - pre=insert_node_before(pre,n,newkern(leftkern)) - done=true - end - local rightkern=i.rightkern - if rightkern and rightkern~=0 then - insert_node_after(pre,n,newkern(rightkern)) - done=true - end - end - end - end - end - if post then - for n in traverse_char(post) do - local p=rawget(properties,n) - if p then - local i=p.injections or p.postinjections - if i then - local yoffset=i.yoffset - if yoffset and yoffset~=0 then - setfield(n,"yoffset",yoffset) - end - local leftkern=i.leftkern - if leftkern and leftkern~=0 then - post=insert_node_before(post,n,newkern(leftkern)) - done=true - end - local rightkern=i.rightkern - if rightkern and rightkern~=0 then - insert_node_after(post,n,newkern(rightkern)) - done=true - end - end - end - end - end - if replace then - for n in traverse_char(replace) do - local p=rawget(properties,n) - if p then - local i=p.injections or p.replaceinjections - if i then - local yoffset=i.yoffset - if yoffset and yoffset~=0 then - setfield(n,"yoffset",yoffset) - end - local leftkern=i.leftkern - if leftkern and leftkern~=0 then - replace=insert_node_before(replace,n,newkern(leftkern)) - done=true - end - local rightkern=i.rightkern - if rightkern and rightkern~=0 then - insert_node_after(replace,n,newkern(rightkern)) - done=true - end - end - end - end - end - if prevglyph then - if pre then - local p=rawget(properties,prevglyph) - if p then - local i=p.preinjections - if i then - local rightkern=i.rightkern - if rightkern and rightkern~=0 then - pre=insert_node_before(pre,pre,newkern(rightkern)) - done=true - end - end - end - end - if replace then - local p=rawget(properties,prevglyph) - if p then - local i=p.replaceinjections - if i then - local rightkern=i.rightkern - if rightkern and rightkern~=0 then - replace=insert_node_before(replace,replace,newkern(rightkern)) - done=true - end - end - end - end - end - if done then - setdisc(current,pre,post,replace) - end - prevglyph=nil - prevdisc=current - else - prevglyph=nil - prevdisc=nil - end - prev=current - current=next - end - if keepregisteredcounts then - keepregisteredcounts=false - else - nofregisteredkerns=0 - end - return tonode(head),true -end -local function showoffset(n,flag) - local o=getfield(n,"xoffset") - if o==0 then - o=getfield(n,"yoffset") - end - if o~=0 then - setcolor(n,flag and "darkred" or "darkgreen") - else - resetcolor(n) - end -end -local function inject_everything(head,where) - head=tonut(head) - if trace_injections then - trace(head,"everything") - end - local hascursives=nofregisteredcursives>0 - local hasmarks=nofregisteredmarks>0 - local current=head - local last=nil - local font=font - local markdata=nil - local prev=nil - local next=nil - local prevdisc=nil - local prevglyph=nil - local pre=nil - local post=nil - local replace=nil - local pretail=nil - local posttail=nil - local replacetail=nil - local cursiveanchor=nil - local minc=0 - local maxc=0 - local glyphs={} - local marks={} - local nofmarks=0 - local function processmark(p,n,pn) - local px=getfield(p,"xoffset") - local ox=0 - local rightkern=nil - local pp=rawget(properties,p) - if pp then - pp=pp.injections - if pp then - rightkern=pp.rightkern - end - end - if rightkern then - if pn.markdir<0 then - ox=px-pn.markx-rightkern - else - if false then - local leftkern=pp.leftkern - if leftkern then - ox=px-pn.markx-leftkern - else - ox=px-pn.markx - end - else - ox=px-pn.markx - end - end - else - ox=px-pn.markx - if pn.checkmark then - local wn=getfield(n,"width") - if wn~=0 then - wn=wn/2 - if trace_injections then - report_injections("correcting non zero width mark %C",getchar(n)) - end - insert_node_before(n,n,newkern(-wn)) - insert_node_after(n,n,newkern(-wn)) - end - end - end - local oy=getfield(n,"yoffset")+getfield(p,"yoffset")+pn.marky - setfield(n,"xoffset",ox) - setfield(n,"yoffset",oy) - if trace_marks then - showoffset(n,true) - end - end - while current do - local id=getid(current) - local next=getnext(current) - if id==glyph_code then - if getsubtype(current)<256 then - local p=rawget(properties,current) - if p then - local i=p.injections - if i then - local pm=i.markbasenode - if pm then - nofmarks=nofmarks+1 - marks[nofmarks]=current - else - local yoffset=i.yoffset - if yoffset and yoffset~=0 then - setfield(current,"yoffset",yoffset) - end - if hascursives then - local cursivex=i.cursivex - if cursivex then - if cursiveanchor then - if cursivex~=0 then - i.leftkern=(i.leftkern or 0)+cursivex - end - if maxc==0 then - minc=1 - maxc=1 - glyphs[1]=cursiveanchor - else - maxc=maxc+1 - glyphs[maxc]=cursiveanchor - end - properties[cursiveanchor].cursivedy=i.cursivey - last=current - else - maxc=0 - end - elseif maxc>0 then - local ny=getfield(current,"yoffset") - for i=maxc,minc,-1 do - local ti=glyphs[i] - ny=ny+properties[ti].cursivedy - setfield(ti,"yoffset",ny) - if trace_cursive then - showoffset(ti) - end - end - maxc=0 - cursiveanchor=nil - end - if i.cursiveanchor then - cursiveanchor=current - else - if maxc>0 then - local ny=getfield(current,"yoffset") - for i=maxc,minc,-1 do - local ti=glyphs[i] - ny=ny+properties[ti].cursivedy - setfield(ti,"yoffset",ny) - if trace_cursive then - showoffset(ti) - end - end - maxc=0 - end - cursiveanchor=nil - end - end - local leftkern=i.leftkern - if leftkern and leftkern~=0 then - insert_node_before(head,current,newkern(leftkern)) - end - local rightkern=i.rightkern - if rightkern and rightkern~=0 then - insert_node_after(head,current,newkern(rightkern)) - end - end - else - local i=p.emptyinjections - if i then - local rightkern=i.rightkern - if rightkern and rightkern~=0 then - if next and getid(next)==disc_code then - if replace then - else - setfield(next,"replace",newkern(rightkern)) - end - end - end - end - end - if prevdisc then - if p then - local done=false - if post then - local i=p.postinjections - if i then - local leftkern=i.leftkern - if leftkern and leftkern~=0 then - insert_node_after(post,posttail,newkern(leftkern)) - done=true - end - end - end - if replace then - local i=p.replaceinjections - if i then - local leftkern=i.leftkern - if leftkern and leftkern~=0 then - insert_node_after(replace,replacetail,newkern(leftkern)) - done=true - end - end - else - local i=p.emptyinjections - if i then - local leftkern=i.leftkern - if leftkern and leftkern~=0 then - setfield(prev,"replace",newkern(leftkern)) - end - end - end - if done then - setdisc(prevdisc,pre,post,replace) - end - end - end - else - if hascursives and maxc>0 then - local ny=getfield(current,"yoffset") - for i=maxc,minc,-1 do - local ti=glyphs[i] - ny=ny+properties[ti].cursivedy - setfield(ti,"yoffset",getfield(ti,"yoffset")+ny) - end - maxc=0 - cursiveanchor=nil - end - end - end - prevdisc=nil - prevglyph=current - elseif id==disc_code then - pre,post,replace,pretail,posttail,replacetail=getdisc(current,true) - local done=false - if pre then - for n in traverse_char(pre) do - local p=rawget(properties,n) - if p then - local i=p.injections or p.preinjections - if i then - local yoffset=i.yoffset - if yoffset and yoffset~=0 then - setfield(n,"yoffset",yoffset) - end - local leftkern=i.leftkern - if leftkern and leftkern~=0 then - pre=insert_node_before(pre,n,newkern(leftkern)) - done=true - end - local rightkern=i.rightkern - if rightkern and rightkern~=0 then - insert_node_after(pre,n,newkern(rightkern)) - done=true - end - if hasmarks then - local pm=i.markbasenode - if pm then - processmark(pm,current,i) - end - end - end - end - end - end - if post then - for n in traverse_char(post) do - local p=rawget(properties,n) - if p then - local i=p.injections or p.postinjections - if i then - local yoffset=i.yoffset - if yoffset and yoffset~=0 then - setfield(n,"yoffset",yoffset) - end - local leftkern=i.leftkern - if leftkern and leftkern~=0 then - post=insert_node_before(post,n,newkern(leftkern)) - done=true - end - local rightkern=i.rightkern - if rightkern and rightkern~=0 then - insert_node_after(post,n,newkern(rightkern)) - done=true - end - if hasmarks then - local pm=i.markbasenode - if pm then - processmark(pm,current,i) - end - end - end - end - end - end - if replace then - for n in traverse_char(replace) do - local p=rawget(properties,n) - if p then - local i=p.injections or p.replaceinjections - if i then - local yoffset=i.yoffset - if yoffset and yoffset~=0 then - setfield(n,"yoffset",yoffset) - end - local leftkern=i.leftkern - if leftkern and leftkern~=0 then - replace=insert_node_before(replace,n,newkern(leftkern)) - done=true - end - local rightkern=i.rightkern - if rightkern and rightkern~=0 then - insert_node_after(replace,n,newkern(rightkern)) - done=true - end - if hasmarks then - local pm=i.markbasenode - if pm then - processmark(pm,current,i) - end - end - end - end - end - end - if prevglyph then - if pre then - local p=rawget(properties,prevglyph) - if p then - local i=p.preinjections - if i then - local rightkern=i.rightkern - if rightkern and rightkern~=0 then - pre=insert_node_before(pre,pre,newkern(rightkern)) - done=true - end - end - end - end - if replace then - local p=rawget(properties,prevglyph) - if p then - local i=p.replaceinjections - if i then - local rightkern=i.rightkern - if rightkern and rightkern~=0 then - replace=insert_node_before(replace,replace,newkern(rightkern)) - done=true - end - end - end - end - end - if done then - setdisc(current,pre,post,replace) - end - prevglyph=nil - prevdisc=current - else - prevglyph=nil - prevdisc=nil - end - prev=current - current=next - end - if hascursives and maxc>0 then - local ny=getfield(last,"yoffset") - for i=maxc,minc,-1 do - local ti=glyphs[i] - ny=ny+properties[ti].cursivedy - setfield(ti,"yoffset",ny) - if trace_cursive then - showoffset(ti) - end - end - end - if nofmarks>0 then - for i=1,nofmarks do - local m=marks[i] - local p=rawget(properties,m) - local i=p.injections - local b=i.markbasenode - processmark(b,m,i) - end - elseif hasmarks then - end - if keepregisteredcounts then - keepregisteredcounts=false - else - nofregisteredkerns=0 - nofregisteredpairs=0 - nofregisteredmarks=0 - nofregisteredcursives=0 - end - return tonode(head),true -end -local triggers=false -function nodes.injections.setspacekerns(font,sequence) - if triggers then - triggers[font]=sequence - else - triggers={ [font]=sequence } - end -end -local getthreshold -if context then - local threshold=1 - local parameters=fonts.hashes.parameters - directives.register("otf.threshold",function(v) threshold=tonumber(v) or 1 end) - getthreshold=function(font) - local p=parameters[font] - local f=p.factor - local s=p.spacing - local t=threshold*(s and s.width or p.space or 0)-2 - return t>0 and t or 0,f - end -else - injections.threshold=0 - getthreshold=function(font) - local p=fontdata[font].parameters - local f=p.factor - local s=p.spacing - local t=injections.threshold*(s and s.width or p.space or 0)-2 - return t>0 and t or 0,f - end -end -injections.getthreshold=getthreshold -function injections.isspace(n,threshold) - if getid(n)==glue_code then - local w=getfield(n,"width") - if threshold and w>threshold then - return 32 - end - end -end -local function injectspaces(head) - if not triggers then - return head,false - end - local lastfont=nil - local spacekerns=nil - local leftkerns=nil - local rightkerns=nil - local factor=0 - local threshold=0 - local leftkern=false - local rightkern=false - local function updatefont(font,trig) - leftkerns=trig.left - rightkerns=trig.right - lastfont=font - threshold, - factor=getthreshold(font) - end - for n in traverse_id(glue_code,tonut(head)) do - local prev,next=getboth(n) - local prevchar=ischar(prev) - local nextchar=ischar(next) - if nextchar then - local font=getfont(next) - local trig=triggers[font] - if trig then - if lastfont~=font then - updatefont(font,trig) - end - if rightkerns then - rightkern=rightkerns[nextchar] - end - end - end - if prevchar then - local font=getfont(prev) - local trig=triggers[font] - if trig then - if lastfont~=font then - updatefont(font,trig) - end - if leftkerns then - leftkern=leftkerns[prevchar] - end - end - end - if leftkern then - local old=getfield(n,"width") - if old>threshold then - if rightkern then - local new=old+(leftkern+rightkern)*factor - if trace_spaces then - report_spaces("%C [%p -> %p] %C",prevchar,old,new,nextchar) - end - setfield(n,"width",new) - leftkern=false - else - local new=old+leftkern*factor - if trace_spaces then - report_spaces("%C [%p -> %p]",prevchar,old,new) - end - setfield(n,"width",new) - end - end - leftkern=false - elseif rightkern then - local old=getfield(n,"width") - if old>threshold then - local new=old+rightkern*factor - if trace_spaces then - report_spaces("[%p -> %p] %C",nextchar,old,new) - end - setfield(n,"width",new) - end - rightkern=false - end - end - triggers=false - return head,true -end -function injections.handler(head,where) - if triggers then - head=injectspaces(head) - end - if nofregisteredmarks>0 or nofregisteredcursives>0 then - if trace_injections then - report_injections("injection variant %a","everything") - end - return inject_everything(head,where) - elseif nofregisteredpairs>0 then - if trace_injections then - report_injections("injection variant %a","pairs") - end - return inject_pairs_only(head,where) - elseif nofregisteredkerns>0 then - if trace_injections then - report_injections("injection variant %a","kerns") - end - return inject_kerns_only(head,where) - else - return head,false - end -end - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['font-ota']={ - version=1.001, - comment="companion to font-otf.lua (analysing)", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local type=type -if not trackers then trackers={ register=function() end } end -local fonts,nodes,node=fonts,nodes,node -local allocate=utilities.storage.allocate -local otf=fonts.handlers.otf -local analyzers=fonts.analyzers -local initializers=allocate() -local methods=allocate() -analyzers.initializers=initializers -analyzers.methods=methods -local a_state=attributes.private('state') -local nuts=nodes.nuts -local tonut=nuts.tonut -local getfield=nuts.getfield -local getnext=nuts.getnext -local getprev=nuts.getprev -local getprev=nuts.getprev -local getprop=nuts.getprop -local setprop=nuts.setprop -local getfont=nuts.getfont -local getsubtype=nuts.getsubtype -local getchar=nuts.getchar -local ischar=nuts.is_char -local traverse_id=nuts.traverse_id -local end_of_math=nuts.end_of_math -local nodecodes=nodes.nodecodes -local disc_code=nodecodes.disc -local math_code=nodecodes.math -local fontdata=fonts.hashes.identifiers -local categories=characters and characters.categories or {} -local chardata=characters and characters.data -local otffeatures=fonts.constructors.features.otf -local registerotffeature=otffeatures.register -local s_init=1 local s_rphf=7 -local s_medi=2 local s_half=8 -local s_fina=3 local s_pref=9 -local s_isol=4 local s_blwf=10 -local s_mark=5 local s_pstf=11 -local s_rest=6 -local states={ - init=s_init, - medi=s_medi, - med2=s_medi, - fina=s_fina, - fin2=s_fina, - fin3=s_fina, - isol=s_isol, - mark=s_mark, - rest=s_rest, - rphf=s_rphf, - half=s_half, - pref=s_pref, - blwf=s_blwf, - pstf=s_pstf, -} -local features={ - init=s_init, - medi=s_medi, - med2=s_medi, - fina=s_fina, - fin2=s_fina, - fin3=s_fina, - isol=s_isol, - rphf=s_rphf, - half=s_half, - pref=s_pref, - blwf=s_blwf, - pstf=s_pstf, -} -analyzers.states=states -analyzers.features=features -analyzers.useunicodemarks=false -function analyzers.setstate(head,font) - local useunicodemarks=analyzers.useunicodemarks - local tfmdata=fontdata[font] - local descriptions=tfmdata.descriptions - local first,last,current,n,done=nil,nil,head,0,false - current=tonut(current) - while current do - local char,id=ischar(current,font) - if char and not getprop(current,a_state) then - done=true - local d=descriptions[char] - if d then - if d.class=="mark" then - done=true - setprop(current,a_state,s_mark) - elseif useunicodemarks and categories[char]=="mn" then - done=true - setprop(current,a_state,s_mark) - elseif n==0 then - first,last,n=current,current,1 - setprop(current,a_state,s_init) - else - last,n=current,n+1 - setprop(current,a_state,s_medi) - end - else - if first and first==last then - setprop(last,a_state,s_isol) - elseif last then - setprop(last,a_state,s_fina) - end - first,last,n=nil,nil,0 - end - elseif char==false then - if first and first==last then - setprop(last,a_state,s_isol) - elseif last then - setprop(last,a_state,s_fina) - end - first,last,n=nil,nil,0 - if id==math_code then - current=end_of_math(current) - end - elseif id==disc_code then - setprop(current,a_state,s_medi) - last=current - else - if first and first==last then - setprop(last,a_state,s_isol) - elseif last then - setprop(last,a_state,s_fina) - end - first,last,n=nil,nil,0 - if id==math_code then - current=end_of_math(current) - end - end - current=getnext(current) - end - if first and first==last then - setprop(last,a_state,s_isol) - elseif last then - setprop(last,a_state,s_fina) - end - return head,done -end -local function analyzeinitializer(tfmdata,value) - local script,language=otf.scriptandlanguage(tfmdata) - local action=initializers[script] - if not action then - elseif type(action)=="function" then - return action(tfmdata,value) - else - local action=action[language] - if action then - return action(tfmdata,value) - end - end -end -local function analyzeprocessor(head,font,attr) - local tfmdata=fontdata[font] - local script,language=otf.scriptandlanguage(tfmdata,attr) - local action=methods[script] - if not action then - elseif type(action)=="function" then - return action(head,font,attr) - else - action=action[language] - if action then - return action(head,font,attr) - end - end - return head,false -end -registerotffeature { - name="analyze", - description="analysis of character classes", - default=true, - initializers={ - node=analyzeinitializer, - }, - processors={ - position=1, - node=analyzeprocessor, - } -} -methods.latn=analyzers.setstate -local arab_warned={} -local function warning(current,what) - local char=getchar(current) - if not arab_warned[char] then - log.report("analyze","arab: character %C has no %a class",char,what) - arab_warned[char]=true - end -end -local mappers={ - l=s_init, - d=s_medi, - c=s_medi, - r=s_fina, - u=s_isol, -} -local classifiers=characters.classifiers -if not classifiers then - local f_arabic,l_arabic=characters.blockrange("arabic") - local f_syriac,l_syriac=characters.blockrange("syriac") - local f_mandiac,l_mandiac=characters.blockrange("mandiac") - local f_nko,l_nko=characters.blockrange("nko") - local f_ext_a,l_ext_a=characters.blockrange("arabicextendeda") - classifiers=table.setmetatableindex(function(t,k) - if type(k)=="number" then - local c=chardata[k] - local v=false - if c then - local arabic=c.arabic - if arabic then - v=mappers[arabic] - if not v then - log.report("analyze","error in mapping arabic %C",k) - v=false - end - elseif (k>=f_arabic and k<=l_arabic) or - (k>=f_syriac and k<=l_syriac) or - (k>=f_mandiac and k<=l_mandiac) or - (k>=f_nko and k<=l_nko) or - (k>=f_ext_a and k<=l_ext_a) then - if categories[k]=="mn" then - v=s_mark - else - v=s_rest - end - end - end - t[k]=v - return v - end - end) - characters.classifiers=classifiers -end -function methods.arab(head,font,attr) - local first,last=nil,nil - local c_first,c_last=nil,nil - local current,done=head,false - current=tonut(current) - while current do - local char,id=ischar(current,font) - if char and not getprop(current,a_state) then - done=true - local classifier=classifiers[char] - if not classifier then - if last then - if c_last==s_medi or c_last==s_fina then - setprop(last,a_state,s_fina) - else - warning(last,"fina") - setprop(last,a_state,s_error) - end - first,last=nil,nil - elseif first then - if c_first==s_medi or c_first==s_fina then - setprop(first,a_state,s_isol) - else - warning(first,"isol") - setprop(first,a_state,s_error) - end - first=nil - end - elseif classifier==s_mark then - setprop(current,a_state,s_mark) - elseif classifier==s_isol then - if last then - if c_last==s_medi or c_last==s_fina then - setprop(last,a_state,s_fina) - else - warning(last,"fina") - setprop(last,a_state,s_error) - end - first,last=nil,nil - elseif first then - if c_first==s_medi or c_first==s_fina then - setprop(first,a_state,s_isol) - else - warning(first,"isol") - setprop(first,a_state,s_error) - end - first=nil - end - setprop(current,a_state,s_isol) - elseif classifier==s_medi then - if first then - last=current - c_last=classifier - setprop(current,a_state,s_medi) - else - setprop(current,a_state,s_init) - first=current - c_first=classifier - end - elseif classifier==s_fina then - if last then - if getprop(last,a_state)~=s_init then - setprop(last,a_state,s_medi) - end - setprop(current,a_state,s_fina) - first,last=nil,nil - elseif first then - setprop(current,a_state,s_fina) - first=nil - else - setprop(current,a_state,s_isol) - end - else - setprop(current,a_state,s_rest) - if last then - if c_last==s_medi or c_last==s_fina then - setprop(last,a_state,s_fina) - else - warning(last,"fina") - setprop(last,a_state,s_error) - end - first,last=nil,nil - elseif first then - if c_first==s_medi or c_first==s_fina then - setprop(first,a_state,s_isol) - else - warning(first,"isol") - setprop(first,a_state,s_error) - end - first=nil - end - end - else - if last then - if c_last==s_medi or c_last==s_fina then - setprop(last,a_state,s_fina) - else - warning(last,"fina") - setprop(last,a_state,s_error) - end - first,last=nil,nil - elseif first then - if c_first==s_medi or c_first==s_fina then - setprop(first,a_state,s_isol) - else - warning(first,"isol") - setprop(first,a_state,s_error) - end - first=nil - end - if id==math_code then - current=end_of_math(current) - end - end - current=getnext(current) - end - if last then - if c_last==s_medi or c_last==s_fina then - setprop(last,a_state,s_fina) - else - warning(last,"fina") - setprop(last,a_state,s_error) - end - elseif first then - if c_first==s_medi or c_first==s_fina then - setprop(first,a_state,s_isol) - else - warning(first,"isol") - setprop(first,a_state,s_error) - end - end - return head,done -end -methods.syrc=methods.arab -methods.mand=methods.arab -methods.nko=methods.arab -directives.register("otf.analyze.useunicodemarks",function(v) - analyzers.useunicodemarks=v -end) - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['font-ots']={ - version=1.001, - comment="companion to font-ini.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files", -} -local type,next,tonumber=type,next,tonumber -local random=math.random -local formatters=string.formatters -local insert=table.insert -local logs,trackers,nodes,attributes=logs,trackers,nodes,attributes -local registertracker=trackers.register -local registerdirective=directives.register -local fonts=fonts -local otf=fonts.handlers.otf -local trace_lookups=false registertracker("otf.lookups",function(v) trace_lookups=v end) -local trace_singles=false registertracker("otf.singles",function(v) trace_singles=v end) -local trace_multiples=false registertracker("otf.multiples",function(v) trace_multiples=v end) -local trace_alternatives=false registertracker("otf.alternatives",function(v) trace_alternatives=v end) -local trace_ligatures=false registertracker("otf.ligatures",function(v) trace_ligatures=v end) -local trace_contexts=false registertracker("otf.contexts",function(v) trace_contexts=v end) -local trace_marks=false registertracker("otf.marks",function(v) trace_marks=v end) -local trace_kerns=false registertracker("otf.kerns",function(v) trace_kerns=v end) -local trace_cursive=false registertracker("otf.cursive",function(v) trace_cursive=v end) -local trace_preparing=false registertracker("otf.preparing",function(v) trace_preparing=v end) -local trace_bugs=false registertracker("otf.bugs",function(v) trace_bugs=v end) -local trace_details=false registertracker("otf.details",function(v) trace_details=v end) -local trace_steps=false registertracker("otf.steps",function(v) trace_steps=v end) -local trace_skips=false registertracker("otf.skips",function(v) trace_skips=v end) -local trace_directions=false registertracker("otf.directions",function(v) trace_directions=v end) -local trace_plugins=false registertracker("otf.plugins",function(v) trace_plugins=v end) -local trace_kernruns=false registertracker("otf.kernruns",function(v) trace_kernruns=v end) -local trace_discruns=false registertracker("otf.discruns",function(v) trace_discruns=v end) -local trace_compruns=false registertracker("otf.compruns",function(v) trace_compruns=v end) -local trace_testruns=false registertracker("otf.testruns",function(v) trace_testruns=v end) -local optimizekerns=true -local alwaysdisc=true registerdirective("otf.alwaysdisc",function(v) alwaysdisc=v end) -local report_direct=logs.reporter("fonts","otf direct") -local report_subchain=logs.reporter("fonts","otf subchain") -local report_chain=logs.reporter("fonts","otf chain") -local report_process=logs.reporter("fonts","otf process") -local report_warning=logs.reporter("fonts","otf warning") -local report_run=logs.reporter("fonts","otf run") -registertracker("otf.replacements","otf.singles,otf.multiples,otf.alternatives,otf.ligatures") -registertracker("otf.positions","otf.marks,otf.kerns,otf.cursive") -registertracker("otf.actions","otf.replacements,otf.positions") -registertracker("otf.injections","nodes.injections") -registertracker("*otf.sample","otf.steps,otf.actions,otf.analyzing") -local nuts=nodes.nuts -local tonode=nuts.tonode -local tonut=nuts.tonut -local getfield=nuts.getfield -local setfield=nuts.setfield -local getnext=nuts.getnext -local setnext=nuts.setnext -local getprev=nuts.getprev -local setprev=nuts.setprev -local getboth=nuts.getboth -local setboth=nuts.setboth -local getid=nuts.getid -local getattr=nuts.getattr -local setattr=nuts.setattr -local getprop=nuts.getprop -local setprop=nuts.setprop -local getfont=nuts.getfont -local getsubtype=nuts.getsubtype -local setsubtype=nuts.setsubtype -local getchar=nuts.getchar -local setchar=nuts.setchar -local getdisc=nuts.getdisc -local setdisc=nuts.setdisc -local setlink=nuts.setlink -local ischar=nuts.is_char -local insert_node_after=nuts.insert_after -local copy_node=nuts.copy -local copy_node_list=nuts.copy_list -local find_node_tail=nuts.tail -local flush_node_list=nuts.flush_list -local flush_node=nuts.flush_node -local end_of_math=nuts.end_of_math -local traverse_nodes=nuts.traverse -local traverse_id=nuts.traverse_id -local remove_node=nuts.remove -local setmetatableindex=table.setmetatableindex -local zwnj=0x200C -local zwj=0x200D -local wildcard="*" -local default="dflt" -local nodecodes=nodes.nodecodes -local glyphcodes=nodes.glyphcodes -local disccodes=nodes.disccodes -local glyph_code=nodecodes.glyph -local glue_code=nodecodes.glue -local disc_code=nodecodes.disc -local math_code=nodecodes.math -local dir_code=nodecodes.dir -local localpar_code=nodecodes.localpar -local discretionary_code=disccodes.discretionary -local ligature_code=glyphcodes.ligature -local privateattribute=attributes.private -local a_state=privateattribute('state') -local injections=nodes.injections -local setmark=injections.setmark -local setcursive=injections.setcursive -local setkern=injections.setkern -local setpair=injections.setpair -local resetinjection=injections.reset -local copyinjection=injections.copy -local setligaindex=injections.setligaindex -local getligaindex=injections.getligaindex -local cursonce=true -local fonthashes=fonts.hashes -local fontdata=fonthashes.identifiers -local fontfeatures=fonthashes.features -local otffeatures=fonts.constructors.features.otf -local registerotffeature=otffeatures.register -local onetimemessage=fonts.loggers.onetimemessage or function() end -local getrandom=utilities and utilities.randomizer and utilities.randomizer.get -otf.defaultnodealternate="none" -local tfmdata=false -local characters=false -local descriptions=false -local marks=false -local currentfont=false -local factor=0 -local threshold=0 -local checkmarks=false -local sweepnode=nil -local sweepprev=nil -local sweepnext=nil -local sweephead={} -local notmatchpre={} -local notmatchpost={} -local notmatchreplace={} -local handlers={} -local isspace=injections.isspace -local getthreshold=injections.getthreshold -local checkstep=(nodes and nodes.tracers and nodes.tracers.steppers.check) or function() end -local registerstep=(nodes and nodes.tracers and nodes.tracers.steppers.register) or function() end -local registermessage=(nodes and nodes.tracers and nodes.tracers.steppers.message) or function() end -local function checkdisccontent(d) - local pre,post,replace=getdisc(d) - if pre then for n in traverse_id(glue_code,pre) do print("pre",nodes.idstostring(pre)) break end end - if post then for n in traverse_id(glue_code,post) do print("pos",nodes.idstostring(post)) break end end - if replace then for n in traverse_id(glue_code,replace) do print("rep",nodes.idstostring(replace)) break end end -end -local function logprocess(...) - if trace_steps then - registermessage(...) - end - report_direct(...) -end -local function logwarning(...) - report_direct(...) -end -local f_unicode=formatters["%U"] -local f_uniname=formatters["%U (%s)"] -local f_unilist=formatters["% t (% t)"] -local function gref(n) - if type(n)=="number" then - local description=descriptions[n] - local name=description and description.name - if name then - return f_uniname(n,name) - else - return f_unicode(n) - end - elseif n then - local num,nam={},{} - for i=1,#n do - local ni=n[i] - if tonumber(ni) then - local di=descriptions[ni] - num[i]=f_unicode(ni) - nam[i]=di and di.name or "-" - end - end - return f_unilist(num,nam) - else - return "<error in node mode tracing>" - end -end -local function cref(dataset,sequence,index) - if not dataset then - return "no valid dataset" - elseif index then - return formatters["feature %a, type %a, chain lookup %a, index %a"](dataset[4],sequence.type,sequence.name,index) - else - return formatters["feature %a, type %a, chain lookup %a"](dataset[4],sequence.type,sequence.name) - end -end -local function pref(dataset,sequence) - return formatters["feature %a, type %a, lookup %a"](dataset[4],sequence.type,sequence.name) -end -local function mref(rlmode) - if not rlmode or rlmode==0 then - return "---" - elseif rlmode==-1 or rlmode=="+TRT" then - return "r2l" - else - return "l2r" - end -end -local function copy_glyph(g) - local components=getfield(g,"components") - if components then - setfield(g,"components") - local n=copy_node(g) - copyinjection(n,g) - setfield(g,"components",components) - return n - else - local n=copy_node(g) - copyinjection(n,g) - return n - end -end -local function flattendisk(head,disc) - local pre,post,replace,pretail,posttail,replacetail=getdisc(disc,true) - local prev,next=getboth(disc) - local ishead=head==disc - setdisc(disc) - flush_node(disc) - if pre then - flush_node_list(pre) - end - if post then - flush_node_list(post) - end - if ishead then - if replace then - if next then - setlink(replacetail,next) - end - return replace,replace - elseif next then - return next,next - else - return - end - else - if replace then - if next then - setlink(replacetail,next) - end - setlink(prev,replace) - return head,replace - else - setlink(prev,next) - return head,next - end - end -end -local function appenddisc(disc,list) - local pre,post,replace,pretail,posttail,replacetail=getdisc(disc,true) - local posthead=list - local replacehead=copy_node_list(list) - if post then - setlink(posttail,posthead) - else - post=phead - end - if replace then - setlink(replacetail,replacehead) - else - replace=rhead - end - setdisc(disc,pre,post,replace) -end -local function markstoligature(head,start,stop,char) - if start==stop and getchar(start)==char then - return head,start - else - local prev=getprev(start) - local next=getnext(stop) - setprev(start) - setnext(stop) - local base=copy_glyph(start) - if head==start then - head=base - end - resetinjection(base) - setchar(base,char) - setsubtype(base,ligature_code) - setfield(base,"components",start) - setlink(prev,base) - setlink(base,next) - return head,base - end -end -local function getcomponentindex(start) - if getid(start)~=glyph_code then - return 0 - elseif getsubtype(start)==ligature_code then - local i=0 - local components=getfield(start,"components") - while components do - i=i+getcomponentindex(components) - components=getnext(components) - end - return i - elseif not marks[getchar(start)] then - return 1 - else - return 0 - end -end -local a_noligature=attributes.private("noligature") -local function toligature(head,start,stop,char,dataset,sequence,markflag,discfound) - if getattr(start,a_noligature)==1 then - return head,start - end - if start==stop and getchar(start)==char then - resetinjection(start) - setchar(start,char) - return head,start - end - local components=getfield(start,"components") - if components then - end - local prev=getprev(start) - local next=getnext(stop) - local comp=start - setprev(start) - setnext(stop) - local base=copy_glyph(start) - if start==head then - head=base - end - resetinjection(base) - setchar(base,char) - setsubtype(base,ligature_code) - setfield(base,"components",comp) - if prev then - setnext(prev,base) - end - if next then - setprev(next,base) - end - setboth(base,prev,next) - if not discfound then - local deletemarks=markflag~="mark" - local components=start - local baseindex=0 - local componentindex=0 - local head=base - local current=base - while start do - local char=getchar(start) - if not marks[char] then - baseindex=baseindex+componentindex - componentindex=getcomponentindex(start) - elseif not deletemarks then - setligaindex(start,baseindex+getligaindex(start,componentindex)) - if trace_marks then - logwarning("%s: keep mark %s, gets index %s",pref(dataset,sequence),gref(char),getligaindex(start)) - end - local n=copy_node(start) - copyinjection(n,start) - head,current=insert_node_after(head,current,n) - elseif trace_marks then - logwarning("%s: delete mark %s",pref(dataset,sequence),gref(char)) - end - start=getnext(start) - end - local start=getnext(current) - while start do - local char=ischar(start) - if char then - if marks[char] then - setligaindex(start,baseindex+getligaindex(start,componentindex)) - if trace_marks then - logwarning("%s: set mark %s, gets index %s",pref(dataset,sequence),gref(char),getligaindex(start)) - end - start=getnext(start) - else - break - end - else - break - end - end - else - local discprev,discnext=getboth(discfound) - if discprev and discnext then - local pre,post,replace,pretail,posttail,replacetail=getdisc(discfound,true) - if not replace then - local prev=getprev(base) - local current=comp - local previous=nil - local copied=nil - while current do - if getid(current)==glyph_code then - local n=copy_node(current) - if copied then - setlink(previous,n) - else - copied=n - end - previous=n - end - current=getnext(current) - end - setprev(discnext) - setnext(discprev) - if pre then - setlink(discprev,pre) - end - pre=comp - if post then - setlink(posttail,discnext) - setprev(post) - else - post=discnext - end - setlink(prev,discfound) - setlink(discfound,next) - setboth(base) - setfield(base,"components",copied) - setdisc(discfound,pre,post,base) - base=prev - end - end - end - return head,base -end -local function multiple_glyphs(head,start,multiple,ignoremarks,what) - local nofmultiples=#multiple - if nofmultiples>0 then - resetinjection(start) - setchar(start,multiple[1]) - if nofmultiples>1 then - local sn=getnext(start) - for k=2,nofmultiples do - local n=copy_node(start) - resetinjection(n) - setchar(n,multiple[k]) - insert_node_after(head,start,n) - start=n - end - if what==true then - elseif what>1 then - local m=multiple[nofmultiples] - for i=2,what do - local n=copy_node(start) - resetinjection(n) - setchar(n,m) - insert_node_after(head,start,n) - start=n - end - end - end - return head,start,true - else - if trace_multiples then - logprocess("no multiple for %s",gref(getchar(start))) - end - return head,start,false - end -end -local function get_alternative_glyph(start,alternatives,value) - local n=#alternatives - if value=="random" then - local r=getrandom and getrandom("glyph",1,n) or random(1,n) - return alternatives[r],trace_alternatives and formatters["value %a, taking %a"](value,r) - elseif value=="first" then - return alternatives[1],trace_alternatives and formatters["value %a, taking %a"](value,1) - elseif value=="last" then - return alternatives[n],trace_alternatives and formatters["value %a, taking %a"](value,n) - end - value=value==true and 1 or tonumber(value) - if type(value)~="number" then - return alternatives[1],trace_alternatives and formatters["invalid value %s, taking %a"](value,1) - end - if value>n then - local defaultalt=otf.defaultnodealternate - if defaultalt=="first" then - return alternatives[n],trace_alternatives and formatters["invalid value %s, taking %a"](value,1) - elseif defaultalt=="last" then - return alternatives[1],trace_alternatives and formatters["invalid value %s, taking %a"](value,n) - else - return false,trace_alternatives and formatters["invalid value %a, %s"](value,"out of range") - end - elseif value==0 then - return getchar(start),trace_alternatives and formatters["invalid value %a, %s"](value,"no change") - elseif value<1 then - return alternatives[1],trace_alternatives and formatters["invalid value %a, taking %a"](value,1) - else - return alternatives[value],trace_alternatives and formatters["value %a, taking %a"](value,value) - end -end -function handlers.gsub_single(head,start,dataset,sequence,replacement) - if trace_singles then - logprocess("%s: replacing %s by single %s",pref(dataset,sequence),gref(getchar(start)),gref(replacement)) - end - resetinjection(start) - setchar(start,replacement) - return head,start,true -end -function handlers.gsub_alternate(head,start,dataset,sequence,alternative) - local kind=dataset[4] - local what=dataset[1] - local value=what==true and tfmdata.shared.features[kind] or what - local choice,comment=get_alternative_glyph(start,alternative,value) - if choice then - if trace_alternatives then - logprocess("%s: replacing %s by alternative %a to %s, %s",pref(dataset,sequence),gref(getchar(start)),gref(choice),comment) - end - resetinjection(start) - setchar(start,choice) - else - if trace_alternatives then - logwarning("%s: no variant %a for %s, %s",pref(dataset,sequence),value,gref(getchar(start)),comment) - end - end - return head,start,true -end -function handlers.gsub_multiple(head,start,dataset,sequence,multiple) - if trace_multiples then - logprocess("%s: replacing %s by multiple %s",pref(dataset,sequence),gref(getchar(start)),gref(multiple)) - end - return multiple_glyphs(head,start,multiple,sequence.flags[1],dataset[1]) -end -function handlers.gsub_ligature(head,start,dataset,sequence,ligature) - local current=getnext(start) - if not current then - return head,start,false,nil - end - local stop=nil - local startchar=getchar(start) - if marks[startchar] then - while current do - local char=ischar(current,currentfont) - if char then - local lg=ligature[char] - if lg then - stop=current - ligature=lg - current=getnext(current) - else - break - end - else - break - end - end - if stop then - local lig=ligature.ligature - if lig then - if trace_ligatures then - local stopchar=getchar(stop) - head,start=markstoligature(head,start,stop,lig) - logprocess("%s: replacing %s upto %s by ligature %s case 1",pref(dataset,sequence),gref(startchar),gref(stopchar),gref(getchar(start))) - else - head,start=markstoligature(head,start,stop,lig) - end - return head,start,true,false - else - end - end - else - local skipmark=sequence.flags[1] - local discfound=false - local lastdisc=nil - while current do - local char,id=ischar(current,currentfont) - if char then - if skipmark and marks[char] then - current=getnext(current) - else - local lg=ligature[char] - if lg then - if not discfound and lastdisc then - discfound=lastdisc - lastdisc=nil - end - stop=current - ligature=lg - current=getnext(current) - else - break - end - end - elseif char==false then - break - elseif id==disc_code then - local replace=getfield(current,"replace") - if replace then - while replace do - local char,id=ischar(replace,currentfont) - if char then - local lg=ligature[char] - if lg then - ligature=lg - replace=getnext(replace) - else - return head,start,false,false - end - else - return head,start,false,false - end - end - stop=current - end - lastdisc=current - current=getnext(current) - else - break - end - end - local lig=ligature.ligature - if lig then - if stop then - if trace_ligatures then - local stopchar=getchar(stop) - head,start=toligature(head,start,stop,lig,dataset,sequence,skipmark,discfound) - logprocess("%s: replacing %s upto %s by ligature %s case 2",pref(dataset,sequence),gref(startchar),gref(stopchar),gref(lig)) - else - head,start=toligature(head,start,stop,lig,dataset,sequence,skipmark,discfound) - end - else - resetinjection(start) - setchar(start,lig) - if trace_ligatures then - logprocess("%s: replacing %s by (no real) ligature %s case 3",pref(dataset,sequence),gref(startchar),gref(lig)) - end - end - return head,start,true,discfound - else - end - end - return head,start,false,discfound -end -function handlers.gpos_single(head,start,dataset,sequence,kerns,rlmode,step,i,injection) - local startchar=getchar(start) - if step.format=="pair" then - local dx,dy,w,h=setpair(start,factor,rlmode,sequence.flags[4],kerns,injection) - if trace_kerns then - logprocess("%s: shifting single %s by (%p,%p) and correction (%p,%p)",pref(dataset,sequence),gref(startchar),dx,dy,w,h) - end - else - local k=setkern(start,factor,rlmode,kerns,injection) - if trace_kerns then - logprocess("%s: shifting single %s by %p",pref(dataset,sequence),gref(startchar),k) - end - end - return head,start,false -end -function handlers.gpos_pair(head,start,dataset,sequence,kerns,rlmode,step,i,injection) - local snext=getnext(start) - if not snext then - return head,start,false - else - local prev=start - local done=false - while snext do - local nextchar=ischar(snext,currentfont) - if nextchar then - local krn=kerns[nextchar] - if not krn and marks[nextchar] then - prev=snext - snext=getnext(snext) - elseif not krn then - break - elseif step.format=="pair" then - local a,b=krn[1],krn[2] - if optimizekerns then - if not b and a[1]==0 and a[2]==0 and a[4]==0 then - local k=setkern(snext,factor,rlmode,a[3],injection) - if trace_kerns then - logprocess("%s: shifting single %s by %p",pref(dataset,sequence),gref(nextchar),k) - end - done=true - break - end - end - if a and #a>0 then - local x,y,w,h=setpair(start,factor,rlmode,sequence.flags[4],a,injection) - if trace_kerns then - local startchar=getchar(start) - logprocess("%s: shifting first of pair %s and %s by (%p,%p) and correction (%p,%p) as %s",pref(dataset,sequence),gref(startchar),gref(nextchar),x,y,w,h,injection or "injections") - end - end - if b and #b>0 then - local x,y,w,h=setpair(snext,factor,rlmode,sequence.flags[4],b,injection) - if trace_kerns then - local startchar=getchar(snext) - logprocess("%s: shifting second of pair %s and %s by (%p,%p) and correction (%p,%p) as %s",pref(dataset,sequence),gref(startchar),gref(nextchar),x,y,w,h,injection or "injections") - end - end - done=true - break - elseif krn~=0 then - local k=setkern(snext,factor,rlmode,krn,injection) - if trace_kerns then - logprocess("%s: inserting kern %p between %s and %s as %s",pref(dataset,sequence),k,gref(getchar(prev)),gref(nextchar),injection or "injections") - end - done=true - break - else - break - end - else - break - end - end - return head,start,done - end -end -function handlers.gpos_mark2base(head,start,dataset,sequence,markanchors,rlmode) - local markchar=getchar(start) - if marks[markchar] then - local base=getprev(start) - if base then - local basechar=ischar(base,currentfont) - if basechar then - if marks[basechar] then - while base do - base=getprev(base) - if base then - basechar=ischar(base,currentfont) - if basechar then - if not marks[basechar] then - break - end - else - if trace_bugs then - logwarning("%s: no base for mark %s, case %i",pref(dataset,sequence),gref(markchar),1) - end - return head,start,false - end - else - if trace_bugs then - logwarning("%s: no base for mark %s, case %i",pref(dataset,sequence),gref(markchar),2) - end - return head,start,false - end - end - end - local ba=markanchors[1][basechar] - if ba then - local ma=markanchors[2] - local dx,dy,bound=setmark(start,base,factor,rlmode,ba,ma,characters[basechar],false,checkmarks) - if trace_marks then - logprocess("%s, anchor %s, bound %s: anchoring mark %s to basechar %s => (%p,%p)", - pref(dataset,sequence),anchor,bound,gref(markchar),gref(basechar),dx,dy) - end - return head,start,true - end - elseif trace_bugs then - logwarning("%s: nothing preceding, case %i",pref(dataset,sequence),1) - end - elseif trace_bugs then - logwarning("%s: nothing preceding, case %i",pref(dataset,sequence),2) - end - elseif trace_bugs then - logwarning("%s: mark %s is no mark",pref(dataset,sequence),gref(markchar)) - end - return head,start,false -end -function handlers.gpos_mark2ligature(head,start,dataset,sequence,markanchors,rlmode) - local markchar=getchar(start) - if marks[markchar] then - local base=getprev(start) - if base then - local basechar=ischar(base,currentfont) - if basechar then - if marks[basechar] then - while base do - base=getprev(base) - if base then - basechar=ischar(base,currentfont) - if basechar then - if not marks[basechar] then - break - end - else - if trace_bugs then - logwarning("%s: no base for mark %s, case %i",pref(dataset,sequence),gref(markchar),1) - end - return head,start,false - end - else - if trace_bugs then - logwarning("%s: no base for mark %s, case %i",pref(dataset,sequence),gref(markchar),2) - end - return head,start,false - end - end - end - local ba=markanchors[1][basechar] - if ba then - local ma=markanchors[2] - if ma then - local index=getligaindex(start) - ba=ba[index] - if ba then - local dx,dy,bound=setmark(start,base,factor,rlmode,ba,ma,characters[basechar],false,checkmarks) - if trace_marks then - logprocess("%s, anchor %s, index %s, bound %s: anchoring mark %s to baselig %s at index %s => (%p,%p)", - pref(dataset,sequence),anchor,index,bound,gref(markchar),gref(basechar),index,dx,dy) - end - return head,start,true - else - if trace_bugs then - logwarning("%s: no matching anchors for mark %s and baselig %s with index %a",pref(dataset,sequence),gref(markchar),gref(basechar),index) - end - end - end - elseif trace_bugs then - onetimemessage(currentfont,basechar,"no base anchors",report_fonts) - end - elseif trace_bugs then - logwarning("%s: prev node is no char, case %i",pref(dataset,sequence),1) - end - elseif trace_bugs then - logwarning("%s: prev node is no char, case %i",pref(dataset,sequence),2) - end - elseif trace_bugs then - logwarning("%s: mark %s is no mark",pref(dataset,sequence),gref(markchar)) - end - return head,start,false -end -function handlers.gpos_mark2mark(head,start,dataset,sequence,markanchors,rlmode) - local markchar=getchar(start) - if marks[markchar] then - local base=getprev(start) - local slc=getligaindex(start) - if slc then - while base do - local blc=getligaindex(base) - if blc and blc~=slc then - base=getprev(base) - else - break - end - end - end - if base then - local basechar=ischar(base,currentfont) - if basechar then - local ba=markanchors[1][basechar] - if ba then - local ma=markanchors[2] - local dx,dy,bound=setmark(start,base,factor,rlmode,ba,ma,characters[basechar],true,checkmarks) - if trace_marks then - logprocess("%s, anchor %s, bound %s: anchoring mark %s to basemark %s => (%p,%p)", - pref(dataset,sequence),anchor,bound,gref(markchar),gref(basechar),dx,dy) - end - return head,start,true - end - end - end - elseif trace_bugs then - logwarning("%s: mark %s is no mark",pref(dataset,sequence),gref(markchar)) - end - return head,start,false -end -function handlers.gpos_cursive(head,start,dataset,sequence,exitanchors,rlmode,step,i) - local done=false - local startchar=getchar(start) - if marks[startchar] then - if trace_cursive then - logprocess("%s: ignoring cursive for mark %s",pref(dataset,sequence),gref(startchar)) - end - else - local nxt=getnext(start) - while not done and nxt do - local nextchar=ischar(nxt,currentfont) - if not nextchar then - break - elseif marks[nextchar] then - nxt=getnext(nxt) - else - local exit=exitanchors[3] - if exit then - local entry=exitanchors[1][nextchar] - if entry then - entry=entry[2] - if entry then - local dx,dy,bound=setcursive(start,nxt,factor,rlmode,exit,entry,characters[startchar],characters[nextchar]) - if trace_cursive then - logprocess("%s: moving %s to %s cursive (%p,%p) using anchor %s and bound %s in %s mode",pref(dataset,sequence),gref(startchar),gref(nextchar),dx,dy,anchor,bound,mref(rlmode)) - end - done=true - end - end - end - break - end - end - end - return head,start,done -end -local chainprocs={} -local function logprocess(...) - if trace_steps then - registermessage(...) - end - report_subchain(...) -end -local logwarning=report_subchain -local function logprocess(...) - if trace_steps then - registermessage(...) - end - report_chain(...) -end -local logwarning=report_chain -local function reversesub(head,start,stop,dataset,sequence,replacements,rlmode) - local char=getchar(start) - local replacement=replacements[char] - if replacement then - if trace_singles then - logprocess("%s: single reverse replacement of %s by %s",cref(dataset,sequence),gref(char),gref(replacement)) - end - resetinjection(start) - setchar(start,replacement) - return head,start,true - else - return head,start,false - end -end -chainprocs.reversesub=reversesub -local function reportmoresteps(dataset,sequence) - logwarning("%s: more than 1 step",cref(dataset,sequence)) -end -function chainprocs.gsub_single(head,start,stop,dataset,sequence,currentlookup,chainindex) - local steps=currentlookup.steps - local nofsteps=currentlookup.nofsteps - if nofsteps>1 then - reportmoresteps(dataset,sequence) - end - local current=start - while current do - local currentchar=ischar(current) - if currentchar then - local replacement=steps[1].coverage[currentchar] - if not replacement or replacement=="" then - if trace_bugs then - logwarning("%s: no single for %s",cref(dataset,sequence,chainindex),gref(currentchar)) - end - else - if trace_singles then - logprocess("%s: replacing single %s by %s",cref(dataset,sequence,chainindex),gref(currentchar),gref(replacement)) - end - resetinjection(current) - setchar(current,replacement) - end - return head,start,true - elseif currentchar==false then - break - elseif current==stop then - break - else - current=getnext(current) - end - end - return head,start,false -end -function chainprocs.gsub_multiple(head,start,stop,dataset,sequence,currentlookup) - local steps=currentlookup.steps - local nofsteps=currentlookup.nofsteps - if nofsteps>1 then - reportmoresteps(dataset,sequence) - end - local startchar=getchar(start) - local replacement=steps[1].coverage[startchar] - if not replacement or replacement=="" then - if trace_bugs then - logwarning("%s: no multiple for %s",cref(dataset,sequence),gref(startchar)) - end - else - if trace_multiples then - logprocess("%s: replacing %s by multiple characters %s",cref(dataset,sequence),gref(startchar),gref(replacement)) - end - return multiple_glyphs(head,start,replacement,sequence.flags[1],dataset[1]) - end - return head,start,false -end -function chainprocs.gsub_alternate(head,start,stop,dataset,sequence,currentlookup) - local steps=currentlookup.steps - local nofsteps=currentlookup.nofsteps - if nofsteps>1 then - reportmoresteps(dataset,sequence) - end - local kind=dataset[4] - local what=dataset[1] - local value=what==true and tfmdata.shared.features[kind] or what - local current=start - while current do - local currentchar=ischar(current) - if currentchar then - local alternatives=steps[1].coverage[currentchar] - if alternatives then - local choice,comment=get_alternative_glyph(current,alternatives,value) - if choice then - if trace_alternatives then - logprocess("%s: replacing %s by alternative %a to %s, %s",cref(dataset,sequence),gref(char),choice,gref(choice),comment) - end - resetinjection(start) - setchar(start,choice) - else - if trace_alternatives then - logwarning("%s: no variant %a for %s, %s",cref(dataset,sequence),value,gref(char),comment) - end - end - end - return head,start,true - elseif currentchar==false then - break - elseif current==stop then - break - else - current=getnext(current) - end - end - return head,start,false -end -function chainprocs.gsub_ligature(head,start,stop,dataset,sequence,currentlookup,chainindex) - local steps=currentlookup.steps - local nofsteps=currentlookup.nofsteps - if nofsteps>1 then - reportmoresteps(dataset,sequence) - end - local startchar=getchar(start) - local ligatures=steps[1].coverage[startchar] - if not ligatures then - if trace_bugs then - logwarning("%s: no ligatures starting with %s",cref(dataset,sequence,chainindex),gref(startchar)) - end - else - local current=getnext(start) - local discfound=false - local last=stop - local nofreplacements=1 - local skipmark=currentlookup.flags[1] - while current do - local id=getid(current) - if id==disc_code then - if not discfound then - discfound=current - end - if current==stop then - break - else - current=getnext(current) - end - else - local schar=getchar(current) - if skipmark and marks[schar] then - current=getnext(current) - else - local lg=ligatures[schar] - if lg then - ligatures=lg - last=current - nofreplacements=nofreplacements+1 - if current==stop then - break - else - current=getnext(current) - end - else - break - end - end - end - end - local ligature=ligatures.ligature - if ligature then - if chainindex then - stop=last - end - if trace_ligatures then - if start==stop then - logprocess("%s: replacing character %s by ligature %s case 3",cref(dataset,sequence,chainindex),gref(startchar),gref(ligature)) - else - logprocess("%s: replacing character %s upto %s by ligature %s case 4",cref(dataset,sequence,chainindex),gref(startchar),gref(getchar(stop)),gref(ligature)) - end - end - head,start=toligature(head,start,stop,ligature,dataset,sequence,skipmark,discfound) - return head,start,true,nofreplacements,discfound - elseif trace_bugs then - if start==stop then - logwarning("%s: replacing character %s by ligature fails",cref(dataset,sequence,chainindex),gref(startchar)) - else - logwarning("%s: replacing character %s upto %s by ligature fails",cref(dataset,sequence,chainindex),gref(startchar),gref(getchar(stop))) - end - end - end - return head,start,false,0,false -end -function chainprocs.gpos_single(head,start,stop,dataset,sequence,currentlookup,rlmode,chainindex) - local steps=currentlookup.steps - local nofsteps=currentlookup.nofsteps - if nofsteps>1 then - reportmoresteps(dataset,sequence) - end - local startchar=getchar(start) - local step=steps[1] - local kerns=step.coverage[startchar] - if not kerns then - elseif step.format=="pair" then - local dx,dy,w,h=setpair(start,factor,rlmode,sequence.flags[4],kerns) - if trace_kerns then - logprocess("%s: shifting single %s by (%p,%p) and correction (%p,%p)",cref(dataset,sequence),gref(startchar),dx,dy,w,h) - end - else - local k=setkern(start,factor,rlmode,kerns,injection) - if trace_kerns then - logprocess("%s: shifting single %s by %p",cref(dataset,sequence),gref(startchar),k) - end - end - return head,start,false -end -function chainprocs.gpos_pair(head,start,stop,dataset,sequence,currentlookup,rlmode,chainindex) - local steps=currentlookup.steps - local nofsteps=currentlookup.nofsteps - if nofsteps>1 then - reportmoresteps(dataset,sequence) - end - local snext=getnext(start) - if snext then - local startchar=getchar(start) - local step=steps[1] - local kerns=step.coverage[startchar] - if kerns then - local prev=start - local done=false - while snext do - local nextchar=ischar(snext,currentfont) - if not nextchar then - break - end - local krn=kerns[nextchar] - if not krn and marks[nextchar] then - prev=snext - snext=getnext(snext) - elseif not krn then - break - elseif step.format=="pair" then - local a,b=krn[1],krn[2] - if optimizekerns then - if not b and a[1]==0 and a[2]==0 and a[4]==0 then - local k=setkern(snext,factor,rlmode,a[3],"injections") - if trace_kerns then - logprocess("%s: shifting single %s by %p",cref(dataset,sequence),gref(startchar),k) - end - done=true - break - end - end - if a and #a>0 then - local startchar=getchar(start) - local x,y,w,h=setpair(start,factor,rlmode,sequence.flags[4],a,"injections") - if trace_kerns then - logprocess("%s: shifting first of pair %s and %s by (%p,%p) and correction (%p,%p)",cref(dataset,sequence),gref(startchar),gref(nextchar),x,y,w,h) - end - end - if b and #b>0 then - local startchar=getchar(start) - local x,y,w,h=setpair(snext,factor,rlmode,sequence.flags[4],b,"injections") - if trace_kerns then - logprocess("%s: shifting second of pair %s and %s by (%p,%p) and correction (%p,%p)",cref(dataset,sequence),gref(startchar),gref(nextchar),x,y,w,h) - end - end - done=true - break - elseif krn~=0 then - local k=setkern(snext,factor,rlmode,krn) - if trace_kerns then - logprocess("%s: inserting kern %s between %s and %s",cref(dataset,sequence),k,gref(getchar(prev)),gref(nextchar)) - end - done=true - break - else - break - end - end - return head,start,done - end - end - return head,start,false -end -function chainprocs.gpos_mark2base(head,start,stop,dataset,sequence,currentlookup,rlmode) - local steps=currentlookup.steps - local nofsteps=currentlookup.nofsteps - if nofsteps>1 then - reportmoresteps(dataset,sequence) - end - local markchar=getchar(start) - if marks[markchar] then - local markanchors=steps[1].coverage[markchar] - if markanchors then - local base=getprev(start) - if base then - local basechar=ischar(base,currentfont) - if basechar then - if marks[basechar] then - while base do - base=getprev(base) - if base then - local basechar=ischar(base,currentfont) - if basechar then - if not marks[basechar] then - break - end - else - if trace_bugs then - logwarning("%s: no base for mark %s, case %i",pref(dataset,sequence),gref(markchar),1) - end - return head,start,false - end - else - if trace_bugs then - logwarning("%s: no base for mark %s, case %i",pref(dataset,sequence),gref(markchar),2) - end - return head,start,false - end - end - end - local ba=markanchors[1][basechar] - if ba then - local ma=markanchors[2] - if ma then - local dx,dy,bound=setmark(start,base,factor,rlmode,ba,ma,characters[basechar],false,checkmarks) - if trace_marks then - logprocess("%s, anchor %s, bound %s: anchoring mark %s to basechar %s => (%p,%p)", - cref(dataset,sequence),anchor,bound,gref(markchar),gref(basechar),dx,dy) - end - return head,start,true - end - end - elseif trace_bugs then - logwarning("%s: prev node is no char, case %i",cref(dataset,sequence),1) - end - elseif trace_bugs then - logwarning("%s: prev node is no char, case %i",cref(dataset,sequence),2) - end - elseif trace_bugs then - logwarning("%s: mark %s has no anchors",cref(dataset,sequence),gref(markchar)) - end - elseif trace_bugs then - logwarning("%s: mark %s is no mark",cref(dataset,sequence),gref(markchar)) - end - return head,start,false -end -function chainprocs.gpos_mark2ligature(head,start,stop,dataset,sequence,currentlookup,rlmode) - local steps=currentlookup.steps - local nofsteps=currentlookup.nofsteps - if nofsteps>1 then - reportmoresteps(dataset,sequence) - end - local markchar=getchar(start) - if marks[markchar] then - local markanchors=steps[1].coverage[markchar] - if markanchors then - local base=getprev(start) - if base then - local basechar=ischar(base,currentfont) - if basechar then - if marks[basechar] then - while base do - base=getprev(base) - if base then - local basechar=ischar(base,currentfont) - if basechar then - if not marks[basechar] then - break - end - else - if trace_bugs then - logwarning("%s: no base for mark %s, case %i",cref(dataset,sequence),markchar,1) - end - return head,start,false - end - else - if trace_bugs then - logwarning("%s: no base for mark %s, case %i",cref(dataset,sequence),markchar,2) - end - return head,start,false - end - end - end - local ba=markanchors[1][basechar] - if ba then - local ma=markanchors[2] - if ma then - local index=getligaindex(start) - ba=ba[index] - if ba then - local dx,dy,bound=setmark(start,base,factor,rlmode,ba,ma,characters[basechar],false,checkmarks) - if trace_marks then - logprocess("%s, anchor %s, bound %s: anchoring mark %s to baselig %s at index %s => (%p,%p)", - cref(dataset,sequence),anchor,a or bound,gref(markchar),gref(basechar),index,dx,dy) - end - return head,start,true - end - end - end - elseif trace_bugs then - logwarning("%s, prev node is no char, case %i",cref(dataset,sequence),1) - end - elseif trace_bugs then - logwarning("%s, prev node is no char, case %i",cref(dataset,sequence),2) - end - elseif trace_bugs then - logwarning("%s, mark %s has no anchors",cref(dataset,sequence),gref(markchar)) - end - elseif trace_bugs then - logwarning("%s, mark %s is no mark",cref(dataset,sequence),gref(markchar)) - end - return head,start,false -end -function chainprocs.gpos_mark2mark(head,start,stop,dataset,sequence,currentlookup,rlmode) - local steps=currentlookup.steps - local nofsteps=currentlookup.nofsteps - if nofsteps>1 then - reportmoresteps(dataset,sequence) - end - local markchar=getchar(start) - if marks[markchar] then - local markanchors=steps[1].coverage[markchar] - if markanchors then - local base=getprev(start) - local slc=getligaindex(start) - if slc then - while base do - local blc=getligaindex(base) - if blc and blc~=slc then - base=getprev(base) - else - break - end - end - end - if base then - local basechar=ischar(base,currentfont) - if basechar then - local ba=markanchors[1][basechar] - if ba then - local ma=markanchors[2] - if ma then - local dx,dy,bound=setmark(start,base,factor,rlmode,ba,ma,characters[basechar],true,checkmarks) - if trace_marks then - logprocess("%s, anchor %s, bound %s: anchoring mark %s to basemark %s => (%p,%p)", - cref(dataset,sequence),anchor,bound,gref(markchar),gref(basechar),dx,dy) - end - return head,start,true - end - end - elseif trace_bugs then - logwarning("%s: prev node is no mark, case %i",cref(dataset,sequence),1) - end - elseif trace_bugs then - logwarning("%s: prev node is no mark, case %i",cref(dataset,sequence),2) - end - elseif trace_bugs then - logwarning("%s: mark %s has no anchors",cref(dataset,sequence),gref(markchar)) - end - elseif trace_bugs then - logwarning("%s: mark %s is no mark",cref(dataset,sequence),gref(markchar)) - end - return head,start,false -end -function chainprocs.gpos_cursive(head,start,stop,dataset,sequence,currentlookup,rlmode) - local steps=currentlookup.steps - local nofsteps=currentlookup.nofsteps - if nofsteps>1 then - reportmoresteps(dataset,sequence) - end - local startchar=getchar(start) - local exitanchors=steps[1].coverage[startchar] - if exitanchors then - local done=false - if marks[startchar] then - if trace_cursive then - logprocess("%s: ignoring cursive for mark %s",pref(dataset,sequence),gref(startchar)) - end - else - local nxt=getnext(start) - while not done and nxt do - local nextchar=ischar(nxt,currentfont) - if not nextchar then - break - elseif marks[nextchar] then - nxt=getnext(nxt) - else - local exit=exitanchors[3] - if exit then - local entry=exitanchors[1][nextchar] - if entry then - entry=entry[2] - if entry then - local dx,dy,bound=setcursive(start,nxt,factor,rlmode,exit,entry,characters[startchar],characters[nextchar]) - if trace_cursive then - logprocess("%s: moving %s to %s cursive (%p,%p) using anchor %s and bound %s in %s mode",pref(dataset,sequence),gref(startchar),gref(nextchar),dx,dy,anchor,bound,mref(rlmode)) - end - done=true - break - end - end - elseif trace_bugs then - onetimemessage(currentfont,startchar,"no entry anchors",report_fonts) - end - break - end - end - end - return head,start,done - else - if trace_cursive and trace_details then - logprocess("%s, cursive %s is already done",pref(dataset,sequence),gref(getchar(start)),alreadydone) - end - return head,start,false - end -end -local function show_skip(dataset,sequence,char,ck,class) - logwarning("%s: skipping char %s, class %a, rule %a, lookuptype %a",cref(dataset,sequence),gref(char),class,ck[1],ck[8] or ck[2]) -end -local new_kern=nuts.pool.kern -local function checked(head) - local current=head - while current do - if getid(current)==glue_code then - local kern=new_kern(getfield(current,"width")) - if head==current then - local next=getnext(current) - if next then - setlink(kern,next) - end - flush_node(current) - head=kern - current=next - else - local prev,next=getboth(current) - setlink(prev,kern) - setlink(kern,next) - flush_node(current) - current=next - end - else - current=getnext(current) - end - end - return head -end -local function setdiscchecked(d,pre,post,replace) - if pre then pre=checked(pre) end - if post then post=checked(post) end - if replace then replace=checked(replace) end - setdisc(d,pre,post,replace) -end -local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,ck,chainproc) - if not start then - return head,start,false - end - local startishead=start==head - local seq=ck[3] - local f=ck[4] - local l=ck[5] - local s=#seq - local done=false - local sweepnode=sweepnode - local sweeptype=sweeptype - local sweepoverflow=false - local checkdisc=getprev(head) - local keepdisc=not sweepnode - local lookaheaddisc=nil - local backtrackdisc=nil - local current=start - local last=start - local prev=getprev(start) - local hasglue=false - local i=f - while i<=l do - local id=getid(current) - if id==glyph_code then - i=i+1 - last=current - current=getnext(current) - elseif id==glue_code then - i=i+1 - last=current - current=getnext(current) - hasglue=true - elseif id==disc_code then - if keepdisc then - keepdisc=false - if notmatchpre[current]~=notmatchreplace[current] then - lookaheaddisc=current - end - local replace=getfield(current,"replace") - while replace and i<=l do - if getid(replace)==glyph_code then - i=i+1 - end - replace=getnext(replace) - end - last=current - current=getnext(c) - else - head,current=flattendisk(head,current) - end - else - last=current - current=getnext(current) - end - if current then - elseif sweepoverflow then - break - elseif sweeptype=="post" or sweeptype=="replace" then - current=getnext(sweepnode) - if current then - sweeptype=nil - sweepoverflow=true - else - break - end - else - break - end - end - if sweepoverflow then - local prev=current and getprev(current) - if not current or prev~=sweepnode then - local head=getnext(sweepnode) - local tail=nil - if prev then - tail=prev - setprev(current,sweepnode) - else - tail=find_node_tail(head) - end - setnext(sweepnode,current) - setprev(head) - setnext(tail) - appenddisc(sweepnode,head) - end - end - if l<s then - local i=l - local t=sweeptype=="post" or sweeptype=="replace" - while current and i<s do - local id=getid(current) - if id==glyph_code then - i=i+1 - current=getnext(current) - elseif id==glue_code then - i=i+1 - current=getnext(current) - hasglue=true - elseif id==disc_code then - if keepdisc then - keepdisc=false - if notmatchpre[current]~=notmatchreplace[current] then - lookaheaddisc=current - end - local replace=getfield(c,"replace") - while replace and i<s do - if getid(replace)==glyph_code then - i=i+1 - end - replace=getnext(replace) - end - current=getnext(current) - elseif notmatchpre[current]~=notmatchreplace[current] then - head,current=flattendisk(head,current) - else - current=getnext(current) - end - else - current=getnext(current) - end - if not current and t then - current=getnext(sweepnode) - if current then - sweeptype=nil - end - end - end - end - if f>1 then - local current=prev - local i=f - local t=sweeptype=="pre" or sweeptype=="replace" - if not current and t and current==checkdisk then - current=getprev(sweepnode) - end - while current and i>1 do - local id=getid(current) - if id==glyph_code then - i=i-1 - elseif id==glue_code then - i=i-1 - hasglue=true - elseif id==disc_code then - if keepdisc then - keepdisc=false - if notmatchpost[current]~=notmatchreplace[current] then - backtrackdisc=current - end - local replace=getfield(current,"replace") - while replace and i>1 do - if getid(replace)==glyph_code then - i=i-1 - end - replace=getnext(replace) - end - elseif notmatchpost[current]~=notmatchreplace[current] then - head,current=flattendisk(head,current) - end - end - current=getprev(current) - if t and current==checkdisk then - current=getprev(sweepnode) - end - end - end - local ok=false - if lookaheaddisc then - local cf=start - local cl=getprev(lookaheaddisc) - local cprev=getprev(start) - local insertedmarks=0 - while cprev do - local char=ischar(cf,currentfont) - if char and marks[char] then - insertedmarks=insertedmarks+1 - cf=cprev - startishead=cf==head - cprev=getprev(cprev) - else - break - end - end - setprev(lookaheaddisc,cprev) - if cprev then - setnext(cprev,lookaheaddisc) - end - setprev(cf) - setnext(cl) - if startishead then - head=lookaheaddisc - end - local pre,post,replace=getdisc(lookaheaddisc) - local new=copy_node_list(cf) - local cnew=new - for i=1,insertedmarks do - cnew=getnext(cnew) - end - local clast=cnew - for i=f,l do - clast=getnext(clast) - end - if not notmatchpre[lookaheaddisc] then - cf,start,ok=chainproc(cf,start,last,dataset,sequence,chainlookup,rlmode,k) - end - if not notmatchreplace[lookaheaddisc] then - new,cnew,ok=chainproc(new,cnew,clast,dataset,sequence,chainlookup,rlmode,k) - end - if pre then - setlink(cl,pre) - end - if replace then - local tail=find_node_tail(new) - setlink(tail,replace) - end - if hasglue then - setdiscchecked(lookaheaddisc,cf,post,new) - else - setdisc(lookaheaddisc,cf,post,new) - end - start=getprev(lookaheaddisc) - sweephead[cf]=getnext(clast) - sweephead[new]=getnext(last) - elseif backtrackdisc then - local cf=getnext(backtrackdisc) - local cl=start - local cnext=getnext(start) - local insertedmarks=0 - while cnext do - local char=ischar(cnext,currentfont) - if char and marks[char] then - insertedmarks=insertedmarks+1 - cl=cnext - cnext=getnext(cnext) - else - break - end - end - if cnext then - setprev(cnext,backtrackdisc) - end - setnext(backtrackdisc,cnext) - setprev(cf) - setnext(cl) - local pre,post,replace,pretail,posttail,replacetail=getdisc(backtrackdisc,true) - local new=copy_node_list(cf) - local cnew=find_node_tail(new) - for i=1,insertedmarks do - cnew=getprev(cnew) - end - local clast=cnew - for i=f,l do - clast=getnext(clast) - end - if not notmatchpost[backtrackdisc] then - cf,start,ok=chainproc(cf,start,last,dataset,sequence,chainlookup,rlmode,k) - end - if not notmatchreplace[backtrackdisc] then - new,cnew,ok=chainproc(new,cnew,clast,dataset,sequence,chainlookup,rlmode,k) - end - if post then - setlink(posttail,cf) - else - post=cf - end - if replace then - setlink(replacetail,new) - else - replace=new - end - if hasglue then - setdiscchecked(backtrackdisc,pre,post,replace) - else - setdisc(backtrackdisc,pre,post,replace) - end - start=getprev(backtrackdisc) - sweephead[post]=getnext(clast) - sweephead[replace]=getnext(last) - else - head,start,ok=chainproc(head,start,last,dataset,sequence,chainlookup,rlmode,k) - end - return head,start,ok -end -local noflags={ false,false,false,false } -local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode) - local sweepnode=sweepnode - local sweeptype=sweeptype - local currentfont=currentfont - local diskseen=false - local checkdisc=getprev(head) - local flags=sequence.flags or noflags - local done=false - local skipmark=flags[1] - local skipligature=flags[2] - local skipbase=flags[3] - local markclass=sequence.markclass - local skipped=false - for k=1,#contexts do - local match=true - local current=start - local last=start - local ck=contexts[k] - local seq=ck[3] - local s=#seq - local size=1 - if s==1 then - local char=ischar(current,currentfont) - if char then - match=seq[1][char] - end - else - local f=ck[4] - local l=ck[5] - size=l-f+1 - if size>1 then - local discfound=nil - local n=f+1 - last=getnext(last) - while n<=l do - if not last and (sweeptype=="post" or sweeptype=="replace") then - last=getnext(sweepnode) - sweeptype=nil - end - if last then - local char,id=ischar(last,currentfont) - if char then - local ccd=descriptions[char] - if ccd then - local class=ccd.class or "base" - if class==skipmark or class==skipligature or class==skipbase or (markclass and class=="mark" and not markclass[char]) then - skipped=true - if trace_skips then - show_skip(dataset,sequence,char,ck,class) - end - last=getnext(last) - elseif seq[n][char] then - if n<l then - last=getnext(last) - end - n=n+1 - else - if discfound then - notmatchreplace[discfound]=true - match=not notmatchpre[discfound] - else - match=false - end - break - end - else - if discfound then - notmatchreplace[discfound]=true - match=not notmatchpre[discfound] - else - match=false - end - break - end - elseif char==false then - if discfound then - notmatchreplace[discfound]=true - match=not notmatchpre[discfound] - else - match=false - end - break - elseif id==disc_code then - diskseen=true - discfound=last - notmatchpre[last]=nil - notmatchpost[last]=true - notmatchreplace[last]=nil - local pre,post,replace=getdisc(last) - if pre then - local n=n - while pre do - if seq[n][getchar(pre)] then - n=n+1 - pre=getnext(pre) - if n>l then - break - end - else - notmatchpre[last]=true - break - end - end - if n<=l then - notmatchpre[last]=true - end - else - notmatchpre[last]=true - end - if replace then - while replace do - if seq[n][getchar(replace)] then - n=n+1 - replace=getnext(replace) - if n>l then - break - end - else - notmatchreplace[last]=true - match=not notmatchpre[last] - break - end - end - match=not notmatchpre[last] - end - last=getnext(last) - else - match=false - break - end - else - match=false - break - end - end - end - if match and f>1 then - local prev=getprev(start) - if prev then - if prev==checkdisc and (sweeptype=="pre" or sweeptype=="replace") then - prev=getprev(sweepnode) - end - if prev then - local discfound=nil - local n=f-1 - while n>=1 do - if prev then - local char,id=ischar(prev,currentfont) - if char then - local ccd=descriptions[char] - if ccd then - local class=ccd.class - if class==skipmark or class==skipligature or class==skipbase or (markclass and class=="mark" and not markclass[char]) then - skipped=true - if trace_skips then - show_skip(dataset,sequence,char,ck,class) - end - prev=getprev(prev) - elseif seq[n][char] then - if n>1 then - prev=getprev(prev) - end - n=n-1 - else - if discfound then - notmatchreplace[discfound]=true - match=not notmatchpost[discfound] - else - match=false - end - break - end - else - if discfound then - notmatchreplace[discfound]=true - match=not notmatchpost[discfound] - else - match=false - end - break - end - elseif char==false then - if discfound then - notmatchreplace[discfound]=true - match=not notmatchpost[discfound] - else - match=false - end - break - elseif id==disc_code then - diskseen=true - discfound=prev - notmatchpre[prev]=true - notmatchpost[prev]=nil - notmatchreplace[prev]=nil - local pre,post,replace,pretail,posttail,replacetail=getdisc(prev,true) - if pre~=start and post~=start and replace~=start then - if post then - local n=n - while posttail do - if seq[n][getchar(posttail)] then - n=n-1 - if posttail==post then - break - else - posttail=getprev(posttail) - if n<1 then - break - end - end - else - notmatchpost[prev]=true - break - end - end - if n>=1 then - notmatchpost[prev]=true - end - else - notmatchpost[prev]=true - end - if replace then - while replacetail do - if seq[n][getchar(replacetail)] then - n=n-1 - if replacetail==replace then - break - else - replacetail=getprev(replacetail) - if n<1 then - break - end - end - else - notmatchreplace[prev]=true - match=not notmatchpost[prev] - break - end - end - if not match then - break - end - end - end - prev=getprev(prev) - elseif seq[n][32] and isspace(prev,threshold) then - n=n-1 - prev=getprev(prev) - else - match=false - break - end - else - match=false - break - end - end - else - match=false - end - else - match=false - end - end - if match and s>l then - local current=last and getnext(last) - if not current then - if sweeptype=="post" or sweeptype=="replace" then - current=getnext(sweepnode) - end - end - if current then - local discfound=nil - local n=l+1 - while n<=s do - if current then - local char,id=ischar(current,currentfont) - if char then - local ccd=descriptions[char] - if ccd then - local class=ccd.class - if class==skipmark or class==skipligature or class==skipbase or (markclass and class=="mark" and not markclass[char]) then - skipped=true - if trace_skips then - show_skip(dataset,sequence,char,ck,class) - end - current=getnext(current) - elseif seq[n][char] then - if n<s then - current=getnext(current) - end - n=n+1 - else - if discfound then - notmatchreplace[discfound]=true - match=not notmatchpre[discfound] - else - match=false - end - break - end - else - if discfound then - notmatchreplace[discfound]=true - match=not notmatchpre[discfound] - else - match=false - end - break - end - elseif char==false then - if discfound then - notmatchreplace[discfound]=true - match=not notmatchpre[discfound] - else - match=false - end - break - elseif id==disc_code then - diskseen=true - discfound=current - notmatchpre[current]=nil - notmatchpost[current]=true - notmatchreplace[current]=nil - local pre,post,replace=getdisc(current) - if pre then - local n=n - while pre do - if seq[n][getchar(pre)] then - n=n+1 - pre=getnext(pre) - if n>s then - break - end - else - notmatchpre[current]=true - break - end - end - if n<=s then - notmatchpre[current]=true - end - else - notmatchpre[current]=true - end - if replace then - while replace do - if seq[n][getchar(replace)] then - n=n+1 - replace=getnext(replace) - if n>s then - break - end - else - notmatchreplace[current]=true - match=notmatchpre[current] - break - end - end - if not match then - break - end - else - end - current=getnext(current) - elseif seq[n][32] and isspace(current,threshold) then - n=n+1 - current=getnext(current) - else - match=false - break - end - else - match=false - break - end - end - else - match=false - end - end - end - if match then - local diskchain=diskseen or sweepnode - if trace_contexts then - local rule=ck[1] - local lookuptype=ck[8] or ck[2] - local first=ck[4] - local last=ck[5] - local char=getchar(start) - logwarning("%s: rule %s matches at char %s for (%s,%s,%s) chars, lookuptype %a", - cref(dataset,sequence),rule,gref(char),first-1,last-first+1,s-last,lookuptype) - end - local chainlookups=ck[6] - if chainlookups then - local nofchainlookups=#chainlookups - if size==1 then - local chainlookup=chainlookups[1] - local chainkind=chainlookup.type - local chainproc=chainprocs[chainkind] - if chainproc then - local ok - if diskchain then - head,start,ok=chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,1,ck,chainproc) - else - head,start,ok=chainproc(head,start,last,dataset,sequence,chainlookup,rlmode,1) - end - if ok then - done=true - end - else - logprocess("%s: %s is not yet supported (1)",cref(dataset,sequence),chainkind) - end - else - local i=1 - while start do - if skipped then - while start do - local char=getchar(start) - local ccd=descriptions[char] - if ccd then - local class=ccd.class or "base" - if class==skipmark or class==skipligature or class==skipbase or (markclass and class=="mark" and not markclass[char]) then - start=getnext(start) - else - break - end - else - break - end - end - end - local chainlookup=chainlookups[i] - if chainlookup then - local chainkind=chainlookup.type - local chainproc=chainprocs[chainkind] - if chainproc then - local ok,n - if diskchain then - head,start,ok=chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,i,ck,chainproc) - else - head,start,ok,n=chainproc(head,start,last,dataset,sequence,chainlookup,rlmode,i) - end - if ok then - done=true - if n and n>1 and i+n>nofchainlookups then - break - end - end - else - logprocess("%s: %s is not yet supported (2)",cref(dataset,sequence),chainkind) - end - end - i=i+1 - if i>size or not start then - break - elseif start then - start=getnext(start) - end - end - end - else - local replacements=ck[7] - if replacements then - head,start,done=reversesub(head,start,last,dataset,sequence,replacements,rlmode) - else - done=true - if trace_contexts then - logprocess("%s: skipping match",cref(dataset,sequence)) - end - end - end - if done then - break - end - end - end - if diskseen then - notmatchpre={} - notmatchpost={} - notmatchreplace={} - end - return head,start,done -end -handlers.gsub_context=handle_contextchain -handlers.gsub_contextchain=handle_contextchain -handlers.gsub_reversecontextchain=handle_contextchain -handlers.gpos_contextchain=handle_contextchain -handlers.gpos_context=handle_contextchain -local function chained_contextchain(head,start,stop,dataset,sequence,currentlookup,rlmode) - local steps=currentlookup.steps - local nofsteps=currentlookup.nofsteps - if nofsteps>1 then - reportmoresteps(dataset,sequence) - end - return handle_contextchain(head,start,dataset,sequence,currentlookup,rlmode) -end -chainprocs.gsub_context=chained_contextchain -chainprocs.gsub_contextchain=chained_contextchain -chainprocs.gsub_reversecontextchain=chained_contextchain -chainprocs.gpos_contextchain=chained_contextchain -chainprocs.gpos_context=chained_contextchain -local missing=setmetatableindex("table") -local function logprocess(...) - if trace_steps then - registermessage(...) - end - report_process(...) -end -local logwarning=report_process -local function report_missing_coverage(dataset,sequence) - local t=missing[currentfont] - if not t[sequence] then - t[sequence]=true - logwarning("missing coverage for feature %a, lookup %a, type %a, font %a, name %a", - dataset[4],sequence.name,sequence.type,currentfont,tfmdata.properties.fullname) - end -end -local resolved={} -local sequencelists=setmetatableindex(function(t,font) - local sequences=fontdata[font].resources.sequences - if not sequences or not next(sequences) then - sequences=false - end - t[font]=sequences - return sequences -end) -local autofeatures=fonts.analyzers.features -local featuretypes=otf.tables.featuretypes -local defaultscript=otf.features.checkeddefaultscript -local defaultlanguage=otf.features.checkeddefaultlanguage -local function initialize(sequence,script,language,enabled,autoscript,autolanguage) - local features=sequence.features - if features then - local order=sequence.order - if order then - local featuretype=featuretypes[sequence.type or "unknown"] - for i=1,#order do - local kind=order[i] - local valid=enabled[kind] - if valid then - local scripts=features[kind] - local languages=scripts and ( - scripts[script] or - scripts[wildcard] or - (autoscript and defaultscript(featuretype,autoscript,scripts)) - ) - local enabled=languages and ( - languages[language] or - languages[wildcard] or - (autolanguage and defaultlanguage(featuretype,autolanguage,languages)) - ) - if enabled then - return { valid,autofeatures[kind] or false,sequence,kind } - end - end - end - else - end - end - return false -end -function otf.dataset(tfmdata,font) - local shared=tfmdata.shared - local properties=tfmdata.properties - local language=properties.language or "dflt" - local script=properties.script or "dflt" - local enabled=shared.features - local autoscript=enabled and enabled.autoscript - local autolanguage=enabled and enabled.autolanguage - local res=resolved[font] - if not res then - res={} - resolved[font]=res - end - local rs=res[script] - if not rs then - rs={} - res[script]=rs - end - local rl=rs[language] - if not rl then - rl={ - } - rs[language]=rl - local sequences=tfmdata.resources.sequences - if sequences then - for s=1,#sequences do - local v=enabled and initialize(sequences[s],script,language,enabled,autoscript,autolanguage) - if v then - rl[#rl+1]=v - end - end - end - end - return rl -end -local function report_disc(what,n) - report_run("%s: %s > %s",what,n,languages.serializediscretionary(n)) -end -local function kernrun(disc,k_run,font,attr,...) - if trace_kernruns then - report_disc("kern",disc) - end - local prev,next=getboth(disc) - local nextstart=next - local done=false - local pre,post,replace,pretail,posttail,replacetail=getdisc(disc,true) - local prevmarks=prev - while prevmarks do - local char=ischar(prevmarks,font) - if char and marks[char] then - prevmarks=getprev(prevmarks) - else - break - end - end - if prev and not ischar(prev,font) then - prev=false - end - if next and not ischar(next,font) then - next=false - end - if pre then - if k_run(pre,"injections",nil,font,attr,...) then - done=true - end - if prev then - local nest=getprev(pre) - setlink(prev,pre) - if k_run(prevmarks,"preinjections",pre,font,attr,...) then - done=true - end - setprev(pre,nest) - setnext(prev,disc) - end - end - if post then - if k_run(post,"injections",nil,font,attr,...) then - done=true - end - if next then - setlink(posttail,next) - if k_run(posttail,"postinjections",next,font,attr,...) then - done=true - end - setnext(posttail) - setprev(next,disc) - end - end - if replace then - if k_run(replace,"injections",nil,font,attr,...) then - done=true - end - if prev then - local nest=getprev(replace) - setlink(prev,replace) - if k_run(prevmarks,"replaceinjections",replace,font,attr,...) then - done=true - end - setprev(replace,nest) - setnext(prev,disc) - end - if next then - setlink(replacetail,next) - if k_run(replacetail,"replaceinjections",next,font,attr,...) then - done=true - end - setnext(replacetail) - setprev(next,disc) - end - elseif prev and next then - setlink(prev,next) - if k_run(prevmarks,"emptyinjections",next,font,attr,...) then - done=true - end - setlink(prev,disc) - setlink(disc,next) - end - return nextstart,done -end -local function comprun(disc,c_run,...) - if trace_compruns then - report_disc("comp",disc) - end - local pre,post,replace=getdisc(disc) - local renewed=false - if pre then - sweepnode=disc - sweeptype="pre" - local new,done=c_run(pre,...) - if done then - pre=new - renewed=true - end - end - if post then - sweepnode=disc - sweeptype="post" - local new,done=c_run(post,...) - if done then - post=new - renewed=true - end - end - if replace then - sweepnode=disc - sweeptype="replace" - local new,done=c_run(replace,...) - if done then - replace=new - renewed=true - end - end - sweepnode=nil - sweeptype=nil - if renewed then - setdisc(disc,pre,post,replace) - end - return getnext(disc),renewed -end -local function testrun(disc,t_run,c_run,...) - if trace_testruns then - report_disc("test",disc) - end - local prev,next=getboth(disc) - if not next then - return - end - local pre,post,replace,pretail,posttail,replacetail=getdisc(disc,true) - local done=false - if replace and prev then - setlink(replacetail,next) - local ok,overflow=t_run(replace,next,...) - if ok and overflow then - setfield(disc,"replace") - setlink(prev,replace) - setboth(disc) - flush_node_list(disc) - return replace,true - else - setnext(replacetail) - setprev(next,disc) - end - end - local renewed=false - if pre then - sweepnode=disc - sweeptype="pre" - local new,ok=c_run(pre,...) - if ok then - pre=new - renewed=true - end - end - if post then - sweepnode=disc - sweeptype="post" - local new,ok=c_run(post,...) - if ok then - post=new - renewed=true - end - end - if replace then - sweepnode=disc - sweeptype="replace" - local new,ok=c_run(replace,...) - if ok then - replace=new - renewed=true - end - end - sweepnode=nil - sweeptype=nil - if renewed then - setdisc(disc,pre,post,replace) - return next,true - else - return next,done - end -end -local nesting=0 -local function c_run_single(head,font,attr,lookupcache,step,dataset,sequence,rlmode,handler) - local done=false - local sweep=sweephead[head] - if sweep then - start=sweep - sweephead[head]=nil - else - start=head - end - while start do - local char=ischar(start,font) - if char then - local a=attr and getattr(start,0) - if not a or (a==attr) then - local lookupmatch=lookupcache[char] - if lookupmatch then - local ok - head,start,ok=handler(head,start,dataset,sequence,lookupmatch,rlmode,step,1) - if ok then - done=true - end - end - if start then - start=getnext(start) - end - else - start=getnext(start) - end - elseif char==false then - return head,done - elseif sweep then - return head,done - else - start=getnext(start) - end - end - return head,done -end -local function t_run_single(start,stop,font,attr,lookupcache) - while start~=stop do - local char=ischar(start,font) - if char then - local a=attr and getattr(start,0) - if not a or (a==attr) then - local lookupmatch=lookupcache[char] - if lookupmatch then - local s=getnext(start) - local l=nil - local d=0 - while s do - if s==stop then - d=1 - elseif d>0 then - d=d+1 - end - local lg=lookupmatch[getchar(s)] - if lg then - l=lg - s=getnext(s) - else - break - end - end - if l and l.ligature then - return true,d>1 - end - end - else - end - start=getnext(start) - else - break - end - end -end -local function k_run_single(sub,injection,last,font,attr,lookupcache,step,dataset,sequence,rlmode,handler) - local a=attr and getattr(sub,0) - if not a or (a==attr) then - for n in traverse_nodes(sub) do - if n==last then - break - end - local char=ischar(n) - if char then - local lookupmatch=lookupcache[char] - if lookupmatch then - local h,d,ok=handler(sub,n,dataset,sequence,lookupmatch,rlmode,step,1,injection) - if ok then - return true - end - end - end - end - end -end -local function c_run_multiple(head,font,attr,steps,nofsteps,dataset,sequence,rlmode,handler) - local done=false - local sweep=sweephead[head] - if sweep then - start=sweep - sweephead[head]=nil - else - start=head - end - while start do - local char=ischar(start,font) - if char then - local a=attr and getattr(start,0) - if not a or (a==attr) then - for i=1,nofsteps do - local step=steps[i] - local lookupcache=step.coverage - if lookupcache then - local lookupmatch=lookupcache[char] - if lookupmatch then - local ok - head,start,ok=handler(head,start,dataset,sequence,lookupmatch,rlmode,step,i) - if ok then - done=true - break - elseif not start then - break - end - end - else - report_missing_coverage(dataset,sequence) - end - end - if start then - start=getnext(start) - end - else - start=getnext(start) - end - elseif char==false then - return head,done - elseif sweep then - return head,done - else - start=getnext(start) - end - end - return head,done -end -local function t_run_multiple(start,stop,font,attr,steps,nofsteps) - while start~=stop do - local char=ischar(start,font) - if char then - local a=attr and getattr(start,0) - if not a or (a==attr) then - for i=1,nofsteps do - local step=steps[i] - local lookupcache=step.coverage - if lookupcache then - local lookupmatch=lookupcache[char] - if lookupmatch then - local s=getnext(start) - local l=nil - local d=0 - while s do - if s==stop then - d=1 - elseif d>0 then - d=d+1 - end - local lg=lookupmatch[getchar(s)] - if lg then - l=lg - s=getnext(s) - else - break - end - end - if l and l.ligature then - return true,d>1 - end - end - else - report_missing_coverage(dataset,sequence) - end - end - else - end - start=getnext(start) - else - break - end - end -end -local function k_run_multiple(sub,injection,last,font,attr,steps,nofsteps,dataset,sequence,rlmode,handler) - local a=attr and getattr(sub,0) - if not a or (a==attr) then - for n in traverse_nodes(sub) do - if n==last then - break - end - local char=ischar(n) - if char then - for i=1,nofsteps do - local step=steps[i] - local lookupcache=step.coverage - if lookupcache then - local lookupmatch=lookupcache[char] - if lookupmatch then - local h,d,ok=handler(head,n,dataset,sequence,lookupmatch,step,rlmode,i,injection) - if ok then - return true - end - end - else - report_missing_coverage(dataset,sequence) - end - end - end - end - end -end -local function txtdirstate(start,stack,top,rlparmode) - local dir=getfield(start,"dir") - local new=1 - if dir=="+TRT" then - top=top+1 - stack[top]=dir - new=-1 - elseif dir=="+TLT" then - top=top+1 - stack[top]=dir - elseif dir=="-TRT" or dir=="-TLT" then - top=top-1 - if stack[top]=="+TRT" then - new=-1 - end - else - new=rlparmode - end - if trace_directions then - report_process("directions after txtdir %a: parmode %a, txtmode %a, level %a",dir,mref(rlparmode),mref(new),top) - end - return getnext(start),top,new -end -local function pardirstate(start) - local dir=getfield(start,"dir") - local new=0 - if dir=="TLT" then - new=1 - elseif dir=="TRT" then - new=-1 - end - if trace_directions then - report_process("directions after pardir %a: parmode %a",dir,mref(new)) - end - return getnext(start),new,new -end -otf.helpers=otf.helpers or {} -otf.helpers.txtdirstate=txtdirstate -otf.helpers.pardirstate=pardirstate -local function featuresprocessor(head,font,attr) - local sequences=sequencelists[font] - if not sequencelists then - return head,false - end - nesting=nesting+1 - if nesting==1 then - currentfont=font - tfmdata=fontdata[font] - descriptions=tfmdata.descriptions - characters=tfmdata.characters - marks=tfmdata.resources.marks - threshold, - factor=getthreshold(font) - checkmarks=tfmdata.properties.checkmarks - elseif currentfont~=font then - report_warning("nested call with a different font, level %s, quitting",nesting) - nesting=nesting-1 - return head,false - end - head=tonut(head) - if trace_steps then - checkstep(head) - end - local rlmode=0 - local done=false - local datasets=otf.dataset(tfmdata,font,attr) - local forcedisc=alwaysdisc or not attr - local dirstack={} - sweephead={} - for s=1,#datasets do - local dataset=datasets[s] - local attribute=dataset[2] - local sequence=dataset[3] - local rlparmode=0 - local topstack=0 - local success=false - local typ=sequence.type - local gpossing=typ=="gpos_single" or typ=="gpos_pair" - local handler=handlers[typ] - local steps=sequence.steps - local nofsteps=sequence.nofsteps - if not steps then - local h,d,ok=handler(head,head,dataset,sequence,nil,nil,nil,0,font,attr) - if ok then - success=true - if h then - head=h - end - end - elseif typ=="gsub_reversecontextchain" then - local start=find_node_tail(head) - while start do - local char=ischar(start,font) - if char then - local a=attr and getattr(start,0) - if not a or (a==attr) then - for i=1,nofsteps do - local step=steps[i] - local lookupcache=step.coverage - if lookupcache then - local lookupmatch=lookupcache[char] - if lookupmatch then - local ok - head,start,ok=handler(head,start,dataset,sequence,lookupmatch,rlmode,step,i) - if ok then - success=true - break - end - end - else - report_missing_coverage(dataset,sequence) - end - end - if start then - start=getprev(start) - end - else - start=getprev(start) - end - else - start=getprev(start) - end - end - else - local start=head - rlmode=0 - if nofsteps==1 then - local step=steps[1] - local lookupcache=step.coverage - if not lookupcache then - report_missing_coverage(dataset,sequence) - else - while start do - local char,id=ischar(start,font) - if char then - local a=attr and getattr(start,0) - if a then - a=(a==attr) and (not attribute or getprop(start,a_state)==attribute) - else - a=not attribute or getprop(start,a_state)==attribute - end - if a then - local lookupmatch=lookupcache[char] - if lookupmatch then - local ok - head,start,ok=handler(head,start,dataset,sequence,lookupmatch,rlmode,step,1) - if ok then - success=true - end - end - if start then - start=getnext(start) - end - else - start=getnext(start) - end - elseif char==false then - start=getnext(start) - elseif id==disc_code then - local a=forcedisc or getsubtype(start)==discretionary_code or getattr(start,0)==attr - if a then - local ok - if gpossing then - start,ok=kernrun(start,k_run_single,font,attr,lookupcache,step,dataset,sequence,rlmode,handler) - elseif typ=="gsub_ligature" then - start,ok=testrun(start,t_run_single,c_run_single,font,attr,lookupcache,step,dataset,sequence,rlmode,handler) - else - start,ok=comprun(start,c_run_single,font,attr,lookupcache,step,dataset,sequence,rlmode,handler) - end - if ok then - success=true - end - else - start=getnext(start) - end - elseif id==math_code then - start=getnext(end_of_math(start)) - elseif id==dir_code then - start,topstack,rlmode=txtdirstate(start,dirstack,topstack,rlparmode) - elseif id==localpar_code then - start,rlparmode,rlmode=pardirstate(start) - else - start=getnext(start) - end - end - end - else - while start do - local char,id=ischar(start,font) - if char then - local a=attr and getattr(start,0) - if a then - a=(a==attr) and (not attribute or getprop(start,a_state)==attribute) - else - a=not attribute or getprop(start,a_state)==attribute - end - if a then - for i=1,nofsteps do - local step=steps[i] - local lookupcache=step.coverage - if lookupcache then - local lookupmatch=lookupcache[char] - if lookupmatch then - local ok - head,start,ok=handler(head,start,dataset,sequence,lookupmatch,rlmode,step,i) - if ok then - success=true - break - elseif not start then - break - end - end - else - report_missing_coverage(dataset,sequence) - end - end - if start then - start=getnext(start) - end - else - start=getnext(start) - end - elseif char==false then - start=getnext(start) - elseif id==disc_code then - local a=forcedisc or getsubtype(start)==discretionary_code or getattr(start,0)==attr - if a then - local ok - if gpossing then - start,ok=kernrun(start,k_run_multiple,font,attr,steps,nofsteps,dataset,sequence,rlmode,handler) - elseif typ=="gsub_ligature" then - start,ok=testrun(start,t_run_multiple,c_run_multiple,font,attr,steps,nofsteps,dataset,sequence,rlmode,handler) - else - start,ok=comprun(start,c_run_multiple,font,attr,steps,nofsteps,dataset,sequence,rlmode,handler) - end - if ok then - success=true - end - else - start=getnext(start) - end - elseif id==math_code then - start=getnext(end_of_math(start)) - elseif id==dir_code then - start,topstack,rlmode=txtdirstate(start,dirstack,topstack,rlparmode) - elseif id==localpar_code then - start,rlparmode,rlmode=pardirstate(start) - else - start=getnext(start) - end - end - end - end - if success then - done=true - end - if trace_steps then - registerstep(head) - end - end - nesting=nesting-1 - head=tonode(head) - return head,done -end -local plugins={} -otf.plugins=plugins -function otf.registerplugin(name,f) - if type(name)=="string" and type(f)=="function" then - plugins[name]={ name,f } - end -end -local function plugininitializer(tfmdata,value) - if type(value)=="string" then - tfmdata.shared.plugin=plugins[value] - end -end -local function pluginprocessor(head,font) - local s=fontdata[font].shared - local p=s and s.plugin - if p then - if trace_plugins then - report_process("applying plugin %a",p[1]) - end - return p[2](head,font) - else - return head,false - end -end -local function featuresinitializer(tfmdata,value) -end -registerotffeature { - name="features", - description="features", - default=true, - initializers={ - position=1, - node=featuresinitializer, - plug=plugininitializer, - }, - processors={ - node=featuresprocessor, - plug=pluginprocessor, - } -} -otf.nodemodeinitializer=featuresinitializer -otf.featuresprocessor=featuresprocessor -otf.handlers=handlers -local setspacekerns=nodes.injections.setspacekerns if not setspacekerns then os.exit() end -if fontfeatures then - function otf.handlers.trigger_space_kerns(head,start,dataset,sequence,_,_,_,_,font,attr) - local features=fontfeatures[font] - local enabled=features and features.spacekern and features.kern - if enabled then - setspacekerns(font,sequence) - end - return head,start,enabled - end -else - function otf.handlers.trigger_space_kerns(head,start,dataset,sequence,_,_,_,_,font,attr) - local shared=fontdata[font].shared - local features=shared and shared.features - local enabled=features and features.spacekern and features.kern - if enabled then - setspacekerns(font,sequence) - end - return head,start,enabled - end -end -local function hasspacekerns(data) - local sequences=data.resources.sequences - for i=1,#sequences do - local sequence=sequences[i] - local steps=sequence.steps - if steps and sequence.features.kern then - for i=1,#steps do - local coverage=steps[i].coverage - if not coverage then - elseif coverage[32] then - return true - else - for k,v in next,coverage do - if v[32] then - return true - end - end - end - end - end - end - return false -end -otf.readers.registerextender { - name="spacekerns", - action=function(data) - data.properties.hasspacekerns=hasspacekerns(data) - end -} -local function spaceinitializer(tfmdata,value) - local resources=tfmdata.resources - local spacekerns=resources and resources.spacekerns - local properties=tfmdata.properties - if value and spacekerns==nil then - if properties and properties.hasspacekerns then - local sequences=resources.sequences - local left={} - local right={} - local last=0 - local feat=nil - for i=1,#sequences do - local sequence=sequences[i] - local steps=sequence.steps - if steps then - local kern=sequence.features.kern - if kern then - if feat then - for script,languages in next,kern do - local f=feat[script] - if f then - for l in next,languages do - f[l]=true - end - else - feat[script]=languages - end - end - else - feat=kern - end - for i=1,#steps do - local step=steps[i] - local coverage=step.coverage - local rules=step.rules - local format=step.format - if rules then - elseif coverage then - local single=format==gpos_single - local kerns=coverage[32] - if kerns then - for k,v in next,kerns do - if type(v)~="table" then - right[k]=v - elseif single then - right[k]=v[3] - else - local one=v[1] - if one then - right[k]=one[3] - end - end - end - end - for k,v in next,coverage do - local kern=v[32] - if kern then - if type(kern)~="table" then - left[k]=kern - elseif single then - left[k]=v[3] - else - local one=v[1] - if one then - left[k]=one[3] - end - end - end - end - end - end - last=i - end - else - end - end - left=next(left) and left or false - right=next(right) and right or false - if left or right then - spacekerns={ - left=left, - right=right, - } - if last>0 then - local triggersequence={ - features={ kern=feat or { dflt={ dflt=true,} } }, - flags=noflags, - name="trigger_space_kerns", - order={ "kern" }, - type="trigger_space_kerns", - left=left, - right=right, - } - insert(sequences,last,triggersequence) - end - else - spacekerns=false - end - else - spacekerns=false - end - resources.spacekerns=spacekerns - end - return spacekerns -end -registerotffeature { - name="spacekern", - description="space kern injection", - default=true, - initializers={ - node=spaceinitializer, - }, -} -local function markinitializer(tfmdata,value) - local properties=tfmdata.properties - properties.checkmarks=value -end -registerotffeature { - name="checkmarks", - description="check mark widths", - default=true, - initializers={ - node=markinitializer, - }, -} - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['font-osd']={ - version=1.001, - comment="companion to font-ini.mkiv", - author="Kai Eigner, TAT Zetwerk / Hans Hagen, PRAGMA ADE", - copyright="TAT Zetwerk / PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local insert,imerge,copy=table.insert,table.imerge,table.copy -local next,type=next,type -local report_devanagari=logs.reporter("otf","devanagari") -fonts=fonts or {} -fonts.analyzers=fonts.analyzers or {} -fonts.analyzers.methods=fonts.analyzers.methods or { node={ otf={} } } -local otf=fonts.handlers.otf -local handlers=otf.handlers -local methods=fonts.analyzers.methods -local otffeatures=fonts.constructors.features.otf -local registerotffeature=otffeatures.register -local nuts=nodes.nuts -local tonode=nuts.tonode -local tonut=nuts.tonut -local getnext=nuts.getnext -local getprev=nuts.getprev -local getboth=nuts.getboth -local getid=nuts.getid -local getchar=nuts.getchar -local getfont=nuts.getfont -local getsubtype=nuts.getsubtype -local setlink=nuts.setlink -local setnext=nuts.setnext -local setprev=nuts.setprev -local setchar=nuts.setchar -local getprop=nuts.getprop -local setprop=nuts.setprop -local ischar=nuts.is_char -local insert_node_after=nuts.insert_after -local copy_node=nuts.copy -local remove_node=nuts.remove -local flush_list=nuts.flush_list -local flush_node=nuts.flush_node -local copyinjection=nodes.injections.copy -local unsetvalue=attributes.unsetvalue -local fontdata=fonts.hashes.identifiers -local a_state=attributes.private('state') -local a_syllabe=attributes.private('syllabe') -local dotted_circle=0x25CC -local states=fonts.analyzers.states -local s_rphf=states.rphf -local s_half=states.half -local s_pref=states.pref -local s_blwf=states.blwf -local s_pstf=states.pstf -local replace_all_nbsp=nil -replace_all_nbsp=function(head) - replace_all_nbsp=typesetters and typesetters.characters and typesetters.characters.replacenbspaces or function(head) - return head - end - return replace_all_nbsp(head) -end -local xprocesscharacters=nil -if context then - xprocesscharacters=function(head,font) - xprocesscharacters=nodes.handlers.characters - return xprocesscharacters(head,font) - end -else - xprocesscharacters=function(head,font) - xprocesscharacters=nodes.handlers.nodepass - return xprocesscharacters(head,font) - end -end -local function processcharacters(head,font) - return tonut(xprocesscharacters(tonode(head))) -end -local consonant={ - [0x0915]=true,[0x0916]=true,[0x0917]=true,[0x0918]=true, - [0x0919]=true,[0x091A]=true,[0x091B]=true,[0x091C]=true, - [0x091D]=true,[0x091E]=true,[0x091F]=true,[0x0920]=true, - [0x0921]=true,[0x0922]=true,[0x0923]=true,[0x0924]=true, - [0x0925]=true,[0x0926]=true,[0x0927]=true,[0x0928]=true, - [0x0929]=true,[0x092A]=true,[0x092B]=true,[0x092C]=true, - [0x092D]=true,[0x092E]=true,[0x092F]=true,[0x0930]=true, - [0x0931]=true,[0x0932]=true,[0x0933]=true,[0x0934]=true, - [0x0935]=true,[0x0936]=true,[0x0937]=true,[0x0938]=true, - [0x0939]=true,[0x0958]=true,[0x0959]=true,[0x095A]=true, - [0x095B]=true,[0x095C]=true,[0x095D]=true,[0x095E]=true, - [0x095F]=true,[0x0979]=true,[0x097A]=true, - [0x0C95]=true,[0x0C96]=true,[0x0C97]=true,[0x0C98]=true, - [0x0C99]=true,[0x0C9A]=true,[0x0C9B]=true,[0x0C9C]=true, - [0x0C9D]=true,[0x0C9E]=true,[0x0C9F]=true,[0x0CA0]=true, - [0x0CA1]=true,[0x0CA2]=true,[0x0CA3]=true,[0x0CA4]=true, - [0x0CA5]=true,[0x0CA6]=true,[0x0CA7]=true,[0x0CA8]=true, - [0x0CA9]=true,[0x0CAA]=true,[0x0CAB]=true,[0x0CAC]=true, - [0x0CAD]=true,[0x0CAE]=true,[0x0CAF]=true,[0x0CB0]=true, - [0x0CB1]=true,[0x0CB2]=true,[0x0CB3]=true,[0x0CB4]=true, - [0x0CB5]=true,[0x0CB6]=true,[0x0CB7]=true,[0x0CB8]=true, - [0x0CB9]=true, - [0x0CDE]=true, - [0x0D15]=true,[0x0D16]=true,[0x0D17]=true,[0x0D18]=true, - [0x0D19]=true,[0x0D1A]=true,[0x0D1B]=true,[0x0D1C]=true, - [0x0D1D]=true,[0x0D1E]=true,[0x0D1F]=true,[0x0D20]=true, - [0x0D21]=true,[0x0D22]=true,[0x0D23]=true,[0x0D24]=true, - [0x0D25]=true,[0x0D26]=true,[0x0D27]=true,[0x0D28]=true, - [0x0D29]=true,[0x0D2A]=true,[0x0D2B]=true,[0x0D2C]=true, - [0x0D2D]=true,[0x0D2E]=true,[0x0D2F]=true,[0x0D30]=true, - [0x0D31]=true,[0x0D32]=true,[0x0D33]=true,[0x0D34]=true, - [0x0D35]=true,[0x0D36]=true,[0x0D37]=true,[0x0D38]=true, - [0x0D39]=true,[0x0D3A]=true, -} -local independent_vowel={ - [0x0904]=true,[0x0905]=true,[0x0906]=true,[0x0907]=true, - [0x0908]=true,[0x0909]=true,[0x090A]=true,[0x090B]=true, - [0x090C]=true,[0x090D]=true,[0x090E]=true,[0x090F]=true, - [0x0910]=true,[0x0911]=true,[0x0912]=true,[0x0913]=true, - [0x0914]=true,[0x0960]=true,[0x0961]=true,[0x0972]=true, - [0x0973]=true,[0x0974]=true,[0x0975]=true,[0x0976]=true, - [0x0977]=true, - [0x0C85]=true,[0x0C86]=true,[0x0C87]=true,[0x0C88]=true, - [0x0C89]=true,[0x0C8A]=true,[0x0C8B]=true,[0x0C8C]=true, - [0x0C8D]=true,[0x0C8E]=true,[0x0C8F]=true,[0x0C90]=true, - [0x0C91]=true,[0x0C92]=true,[0x0C93]=true,[0x0C94]=true, - [0x0D05]=true,[0x0D06]=true,[0x0D07]=true,[0x0D08]=true, - [0x0D09]=true,[0x0D0A]=true,[0x0D0B]=true,[0x0D0C]=true, - [0x0D0E]=true,[0x0D0F]=true,[0x0D10]=true,[0x0D12]=true, - [0x0D13]=true,[0x0D14]=true, -} -local dependent_vowel={ - [0x093A]=true,[0x093B]=true,[0x093E]=true,[0x093F]=true, - [0x0940]=true,[0x0941]=true,[0x0942]=true,[0x0943]=true, - [0x0944]=true,[0x0945]=true,[0x0946]=true,[0x0947]=true, - [0x0948]=true,[0x0949]=true,[0x094A]=true,[0x094B]=true, - [0x094C]=true,[0x094E]=true,[0x094F]=true,[0x0955]=true, - [0x0956]=true,[0x0957]=true,[0x0962]=true,[0x0963]=true, - [0x0CBE]=true,[0x0CBF]=true,[0x0CC0]=true,[0x0CC1]=true, - [0x0CC2]=true,[0x0CC3]=true,[0x0CC4]=true,[0x0CC5]=true, - [0x0CC6]=true,[0x0CC7]=true,[0x0CC8]=true,[0x0CC9]=true, - [0x0CCA]=true,[0x0CCB]=true,[0x0CCC]=true, - [0x0D3E]=true,[0x0D3F]=true,[0x0D40]=true,[0x0D41]=true, - [0x0D42]=true,[0x0D43]=true,[0x0D44]=true,[0x0D46]=true, - [0x0D47]=true,[0x0D48]=true,[0x0D4A]=true,[0x0D4B]=true, - [0x0D4C]=true,[0x0D57]=true, -} -local vowel_modifier={ - [0x0900]=true,[0x0901]=true,[0x0902]=true,[0x0903]=true, - [0xA8E0]=true,[0xA8E1]=true,[0xA8E2]=true,[0xA8E3]=true, - [0xA8E4]=true,[0xA8E5]=true,[0xA8E6]=true,[0xA8E7]=true, - [0xA8E8]=true,[0xA8E9]=true,[0xA8EA]=true,[0xA8EB]=true, - [0xA8EC]=true,[0xA8ED]=true,[0xA8EE]=true,[0xA8EF]=true, - [0xA8F0]=true,[0xA8F1]=true, - [0x0D02]=true,[0x0D03]=true, -} -local stress_tone_mark={ - [0x0951]=true,[0x0952]=true,[0x0953]=true,[0x0954]=true, - [0x0CCD]=true, - [0x0D4D]=true, -} -local nukta={ - [0x093C]=true, - [0x0CBC]=true, -} -local halant={ - [0x094D]=true, - [0x0CCD]=true, - [0x0D4D]=true, -} -local ra={ - [0x0930]=true, - [0x0CB0]=true, - [0x0D30]=true, -} -local c_anudatta=0x0952 -local c_nbsp=0x00A0 -local c_zwnj=0x200C -local c_zwj=0x200D -local zw_char={ - [0x200C]=true, - [0x200D]=true, -} -local pre_mark={ - [0x093F]=true,[0x094E]=true, - [0x0D46]=true,[0x0D47]=true,[0x0D48]=true, -} -local above_mark={ - [0x0900]=true,[0x0901]=true,[0x0902]=true,[0x093A]=true, - [0x0945]=true,[0x0946]=true,[0x0947]=true,[0x0948]=true, - [0x0951]=true,[0x0953]=true,[0x0954]=true,[0x0955]=true, - [0xA8E0]=true,[0xA8E1]=true,[0xA8E2]=true,[0xA8E3]=true, - [0xA8E4]=true,[0xA8E5]=true,[0xA8E6]=true,[0xA8E7]=true, - [0xA8E8]=true,[0xA8E9]=true,[0xA8EA]=true,[0xA8EB]=true, - [0xA8EC]=true,[0xA8ED]=true,[0xA8EE]=true,[0xA8EF]=true, - [0xA8F0]=true,[0xA8F1]=true, - [0x0D4E]=true, -} -local below_mark={ - [0x093C]=true,[0x0941]=true,[0x0942]=true,[0x0943]=true, - [0x0944]=true,[0x094D]=true,[0x0952]=true,[0x0956]=true, - [0x0957]=true,[0x0962]=true,[0x0963]=true, -} -local post_mark={ - [0x0903]=true,[0x093B]=true,[0x093E]=true,[0x0940]=true, - [0x0949]=true,[0x094A]=true,[0x094B]=true,[0x094C]=true, - [0x094F]=true, -} -local twopart_mark={ - [0x0D4A]={ 0x0D46,0x0D3E,}, - [0x0D4B]={ 0x0D47,0x0D3E,}, - [0x0D4C]={ 0x0D46,0x0D57,}, -} -local mark_four={} -for k,v in next,pre_mark do mark_four[k]=pre_mark end -for k,v in next,above_mark do mark_four[k]=above_mark end -for k,v in next,below_mark do mark_four[k]=below_mark end -for k,v in next,post_mark do mark_four[k]=post_mark end -local mark_above_below_post={} -for k,v in next,above_mark do mark_above_below_post[k]=above_mark end -for k,v in next,below_mark do mark_above_below_post[k]=below_mark end -for k,v in next,post_mark do mark_above_below_post[k]=post_mark end -local reorder_class={ - [0x0930]="before postscript", - [0x093F]="before half", - [0x0940]="after subscript", - [0x0941]="after subscript", - [0x0942]="after subscript", - [0x0943]="after subscript", - [0x0944]="after subscript", - [0x0945]="after subscript", - [0x0946]="after subscript", - [0x0947]="after subscript", - [0x0948]="after subscript", - [0x0949]="after subscript", - [0x094A]="after subscript", - [0x094B]="after subscript", - [0x094C]="after subscript", - [0x0962]="after subscript", - [0x0963]="after subscript", - [0x093E]="after subscript", - [0x0CB0]="after postscript", - [0x0CBF]="before subscript", - [0x0CC6]="before subscript", - [0x0CCC]="before subscript", - [0x0CBE]="before subscript", - [0x0CE2]="before subscript", - [0x0CE3]="before subscript", - [0x0CC1]="before subscript", - [0x0CC2]="before subscript", - [0x0CC3]="after subscript", - [0x0CC4]="after subscript", - [0x0CD5]="after subscript", - [0x0CD6]="after subscript", -} -local dflt_true={ - dflt=true -} -local dev2_defaults={ - dev2=dflt_true, -} -local deva_defaults={ - dev2=dflt_true, - deva=dflt_true, -} -local false_flags={ false,false,false,false } -local both_joiners_true={ - [0x200C]=true, - [0x200D]=true, -} -local sequence_reorder_matras={ - features={ dv01=dev2_defaults }, - flags=false_flags, - name="dv01_reorder_matras", - order={ "dv01" }, - type="devanagari_reorder_matras", - nofsteps=1, - steps={ - { - osdstep=true, - coverage=pre_mark, - } - } -} -local sequence_reorder_reph={ - features={ dv02=dev2_defaults }, - flags=false_flags, - name="dv02_reorder_reph", - order={ "dv02" }, - type="devanagari_reorder_reph", - nofsteps=1, - steps={ - { - osdstep=true, - coverage={}, - } - } -} -local sequence_reorder_pre_base_reordering_consonants={ - features={ dv03=dev2_defaults }, - flags=false_flags, - name="dv03_reorder_pre_base_reordering_consonants", - order={ "dv03" }, - type="devanagari_reorder_pre_base_reordering_consonants", - nofsteps=1, - steps={ - { - osdstep=true, - coverage={}, - } - } -} -local sequence_remove_joiners={ - features={ dv04=deva_defaults }, - flags=false_flags, - name="dv04_remove_joiners", - order={ "dv04" }, - type="devanagari_remove_joiners", - nofsteps=1, - steps={ - { osdstep=true, - coverage=both_joiners_true, - }, - } -} -local basic_shaping_forms={ - nukt=true, - akhn=true, - rphf=true, - pref=true, - rkrf=true, - blwf=true, - half=true, - pstf=true, - vatu=true, - cjct=true, -} -local valid={ - akhn=true, - rphf=true, - pref=true, - half=true, - blwf=true, - pstf=true, - pres=true, - blws=true, - psts=true, -} -local function initializedevanagi(tfmdata) - local script,language=otf.scriptandlanguage(tfmdata,attr) - if script=="deva" or script=="dev2" or script=="mlym" or script=="mlm2" then - local resources=tfmdata.resources - local devanagari=resources.devanagari - if not devanagari then - report_devanagari("adding devanagari features to font") - local gsubfeatures=resources.features.gsub - local sequences=resources.sequences - local sharedfeatures=tfmdata.shared.features - local lastmatch=0 - for s=1,#sequences do - local features=sequences[s].features - if features then - for k,v in next,features do - if basic_shaping_forms[k] then - lastmatch=s - end - end - end - end - local insertindex=lastmatch+1 - gsubfeatures["dv01"]=dev2_defaults - gsubfeatures["dv02"]=dev2_defaults - gsubfeatures["dv03"]=dev2_defaults - gsubfeatures["dv04"]=deva_defaults - local reorder_pre_base_reordering_consonants=copy(sequence_reorder_pre_base_reordering_consonants) - local reorder_reph=copy(sequence_reorder_reph) - local reorder_matras=copy(sequence_reorder_matras) - local remove_joiners=copy(sequence_remove_joiners) - insert(sequences,insertindex,reorder_pre_base_reordering_consonants) - insert(sequences,insertindex,reorder_reph) - insert(sequences,insertindex,reorder_matras) - insert(sequences,insertindex,remove_joiners) - local blwfcache={} - local seqsubset={} - local rephstep={ - coverage={} - } - local devanagari={ - reph=false, - vattu=false, - blwfcache=blwfcache, - seqsubset=seqsubset, - reorderreph=rephstep, - } - reorder_reph.steps={ rephstep } - local pre_base_reordering_consonants={} - reorder_pre_base_reordering_consonants.steps[1].coverage=pre_base_reordering_consonants - resources.devanagari=devanagari - for s=1,#sequences do - local sequence=sequences[s] - local steps=sequence.steps - local nofsteps=sequence.nofsteps - local features=sequence.features - local has_rphf=features.rphf - local has_blwf=features.blwf - if has_rphf and has_rphf.deva then - devanagari.reph=true - elseif has_blwf and has_blwf.deva then - devanagari.vattu=true - for i=1,nofsteps do - local step=steps[i] - local coverage=step.coverage - if coverage then - for k,v in next,coverage do - if not blwfcache[k] then - blwfcache[k]=v - end - end - end - end - end - for kind,spec in next,features do - if spec.dev2 and valid[kind] then - for i=1,nofsteps do - local step=steps[i] - local coverage=step.coverage - if coverage then - local reph=false - if kind=="rphf" then - if true then - for k,v in next,ra do - local r=coverage[k] - if r then - local h=false - for k,v in next,halant do - local h=r[k] - if h then - reph=h.ligature or false - break - end - end - if reph then - break - end - end - end - else - end - end - seqsubset[#seqsubset+1]={ kind,coverage,reph } - end - end - end - if kind=="pref" then - local steps=sequence.steps - local nofsteps=sequence.nofsteps - for i=1,nofsteps do - local step=steps[i] - local coverage=step.coverage - if coverage then - for k,v in next,halant do - local h=coverage[k] - if h then - local found=false - for k,v in next,h do - found=v and v.ligature - if found then - pre_base_reordering_consonants[k]=found - break - end - end - if found then - break - end - end - end - end - end - end - end - end - if script=="deva" then - sharedfeatures["dv04"]=true - elseif script=="dev2" then - sharedfeatures["dv01"]=true - sharedfeatures["dv02"]=true - sharedfeatures["dv03"]=true - sharedfeatures["dv04"]=true - elseif script=="mlym" then - sharedfeatures["pstf"]=true - elseif script=="mlm2" then - sharedfeatures["pstf"]=true - sharedfeatures["pref"]=true - sharedfeatures["dv03"]=true - gsubfeatures ["dv03"]=dev2_defaults - insert(sequences,insertindex,sequence_reorder_pre_base_reordering_consonants) - end - end - end -end -registerotffeature { - name="devanagari", - description="inject additional features", - default=true, - initializers={ - node=initializedevanagi, - }, -} -local function deva_initialize(font,attr) - local tfmdata=fontdata[font] - local datasets=otf.dataset(tfmdata,font,attr) - local devanagaridata=datasets.devanagari - if not devanagaridata then - devanagaridata={ - reph=false, - vattu=false, - blwfcache={}, - } - datasets.devanagari=devanagaridata - local resources=tfmdata.resources - local devanagari=resources.devanagari - for s=1,#datasets do - local dataset=datasets[s] - if dataset and dataset[1] then - local kind=dataset[4] - if kind=="rphf" then - devanagaridata.reph=true - elseif kind=="blwf" then - devanagaridata.vattu=true - devanagaridata.blwfcache=devanagari.blwfcache - end - end - end - end - return devanagaridata.reph,devanagaridata.vattu,devanagaridata.blwfcache -end -local function deva_reorder(head,start,stop,font,attr,nbspaces) - local reph,vattu,blwfcache=deva_initialize(font,attr) - local current=start - local n=getnext(start) - local base=nil - local firstcons=nil - local lastcons=nil - local basefound=false - if reph and ra[getchar(start)] and halant[getchar(n)] then - if n==stop then - return head,stop,nbspaces - end - if getchar(getnext(n))==c_zwj then - current=start - else - current=getnext(n) - setprop(start,a_state,s_rphf) - end - end - if getchar(current)==c_nbsp then - if current==stop then - stop=getprev(stop) - head=remove_node(head,current) - flush_node(current) - return head,stop,nbspaces - else - nbspaces=nbspaces+1 - base=current - firstcons=current - lastcons=current - current=getnext(current) - if current~=stop then - if nukta[getchar(current)] then - current=getnext(current) - end - if getchar(current)==c_zwj then - if current~=stop then - local next=getnext(current) - if next~=stop and halant[getchar(next)] then - current=next - next=getnext(current) - local tmp=next and getnext(next) or nil - local changestop=next==stop - local tempcurrent=copy_node(next) - copyinjection(tempcurrent,next) - local nextcurrent=copy_node(current) - copyinjection(nextcurrent,current) - setlink(tempcurrent,nextcurrent) - setprop(tempcurrent,a_state,s_blwf) - tempcurrent=processcharacters(tempcurrent,font) - setprop(tempcurrent,a_state,unsetvalue) - if getchar(next)==getchar(tempcurrent) then - flush_list(tempcurrent) - local n=copy_node(current) - copyinjection(n,current) - setchar(current,dotted_circle) - head=insert_node_after(head,current,n) - else - setchar(current,getchar(tempcurrent)) - local freenode=getnext(current) - setlink(current,tmp) - flush_node(freenode) - flush_list(tempcurrent) - if changestop then - stop=current - end - end - end - end - end - end - end - end - while not basefound do - local char=getchar(current) - if consonant[char] then - setprop(current,a_state,s_half) - if not firstcons then - firstcons=current - end - lastcons=current - if not base then - base=current - elseif blwfcache[char] then - setprop(current,a_state,s_blwf) - else - base=current - end - end - basefound=current==stop - current=getnext(current) - end - if base~=lastcons then - local np=base - local n=getnext(base) - local ch=getchar(n) - if nukta[ch] then - np=n - n=getnext(n) - ch=getchar(n) - end - if halant[ch] then - if lastcons~=stop then - local ln=getnext(lastcons) - if nukta[getchar(ln)] then - lastcons=ln - end - end - local nn=getnext(n) - local ln=getnext(lastcons) - setlink(np,nn) - setnext(lastcons,n) - if ln then - setprev(ln,n) - end - setnext(n,ln) - setprev(n,lastcons) - if lastcons==stop then - stop=n - end - end - end - n=getnext(start) - if n~=stop and ra[getchar(start)] and halant[getchar(n)] and not zw_char[getchar(getnext(n))] then - local matra=base - if base~=stop then - local next=getnext(base) - if dependent_vowel[getchar(next)] then - matra=next - end - end - local sp=getprev(start) - local nn=getnext(n) - local mn=getnext(matra) - setlink(sp,nn) - setlink(matra,start) - setlink(n,mn) - if head==start then - head=nn - end - start=nn - if matra==stop then - stop=n - end - end - local current=start - while current~=stop do - local next=getnext(current) - if next~=stop and halant[getchar(next)] and getchar(getnext(next))==c_zwnj then - setprop(current,a_state,unsetvalue) - end - current=next - end - if base~=stop and getprop(base,a_state) then - local next=getnext(base) - if halant[getchar(next)] and not (next~=stop and getchar(getnext(next))==c_zwj) then - setprop(base,a_state,unsetvalue) - end - end - local current,allreordered,moved=start,false,{ [base]=true } - local a,b,p,bn=base,base,base,getnext(base) - if base~=stop and nukta[getchar(bn)] then - a,b,p=bn,bn,bn - end - while not allreordered do - local c=current - local n=getnext(current) - local l=nil - if c~=stop then - local ch=getchar(n) - if nukta[ch] then - c=n - n=getnext(n) - ch=getchar(n) - end - if c~=stop then - if halant[ch] then - c=n - n=getnext(n) - ch=getchar(n) - end - while c~=stop and dependent_vowel[ch] do - c=n - n=getnext(n) - ch=getchar(n) - end - if c~=stop then - if vowel_modifier[ch] then - c=n - n=getnext(n) - ch=getchar(n) - end - if c~=stop and stress_tone_mark[ch] then - c=n - n=getnext(n) - end - end - end - end - local bp=getprev(firstcons) - local cn=getnext(current) - local last=getnext(c) - while cn~=last do - if pre_mark[getchar(cn)] then - if bp then - setnext(bp,cn) - end - local prev,next=getboth(cn) - if next then - setprev(next,prev) - end - setnext(prev,next) - if cn==stop then - stop=prev - end - setprev(cn,bp) - setlink(cn,firstcons) - if firstcons==start then - if head==start then - head=cn - end - start=cn - end - break - end - cn=getnext(cn) - end - allreordered=c==stop - current=getnext(c) - end - if reph or vattu then - local current,cns=start,nil - while current~=stop do - local c=current - local n=getnext(current) - if ra[getchar(current)] and halant[getchar(n)] then - c=n - n=getnext(n) - local b,bn=base,base - while bn~=stop do - local next=getnext(bn) - if dependent_vowel[getchar(next)] then - b=next - end - bn=next - end - if getprop(current,a_state)==s_rphf then - if b~=current then - if current==start then - if head==start then - head=n - end - start=n - end - if b==stop then - stop=c - end - local prev=getprev(current) - setlink(prev,n) - local next=getnext(b) - setlink(c,next) - setlink(b,current) - end - elseif cns and getnext(cns)~=current then - local cp=getprev(current) - local cnsn=getnext(cns) - setlink(cp,n) - setlink(cns,current) - setlink(c,cnsn) - if c==stop then - stop=cp - break - end - current=getprev(n) - end - else - local char=getchar(current) - if consonant[char] then - cns=current - local next=getnext(cns) - if halant[getchar(next)] then - cns=next - end - elseif char==c_nbsp then - nbspaces=nbspaces+1 - cns=current - local next=getnext(cns) - if halant[getchar(next)] then - cns=next - end - end - end - current=getnext(current) - end - end - if getchar(base)==c_nbsp then - nbspaces=nbspaces-1 - head=remove_node(head,base) - flush_node(base) - end - return head,stop,nbspaces -end -function handlers.devanagari_reorder_matras(head,start) - local current=start - local startfont=getfont(start) - local startattr=getprop(start,a_syllabe) - while current do - local char=ischar(current,startfont) - local next=getnext(current) - if char and getprop(current,a_syllabe)==startattr then - if halant[char] and not getprop(current,a_state) then - if next then - local char=ischar(next,startfont) - if char and zw_char[char] and getprop(next,a_syllabe)==startattr then - current=next - next=getnext(current) - end - end - local startnext=getnext(start) - head=remove_node(head,start) - setlink(start,next) - setlink(current,start) - start=startnext - break - end - else - break - end - current=next - end - return head,start,true -end -function handlers.devanagari_reorder_reph(head,start) - local current=getnext(start) - local startnext=nil - local startprev=nil - local startfont=getfont(start) - local startattr=getprop(start,a_syllabe) - while current do - local char=ischar(current,startfont) - if char and getprop(current,a_syllabe)==startattr then - if halant[char] and not getprop(current,a_state) then - local next=getnext(current) - if next then - local nextchar=ischar(next,startfont) - if nextchar and zw_char[nextchar] and getprop(next,a_syllabe)==startattr then - current=next - next=getnext(current) - end - end - startnext=getnext(start) - head=remove_node(head,start) - setlink(start,next) - setlink(current,start) - start=startnext - startattr=getprop(start,a_syllabe) - break - end - current=getnext(current) - else - break - end - end - if not startnext then - current=getnext(start) - while current do - local char=ischar(current,startfont) - if char and getprop(current,a_syllabe)==startattr then - if getprop(current,a_state)==s_pstf then - startnext=getnext(start) - head=remove_node(head,start) - local prev=getprev(current) - setlink(prev,start) - setlink(start,current) - start=startnext - startattr=getprop(start,a_syllabe) - break - end - current=getnext(current) - else - break - end - end - end - if not startnext then - current=getnext(start) - local c=nil - while current do - local char=ischar(current,startfont) - if char and getprop(current,a_syllabe)==startattr then - if not c and mark_above_below_post[char] and reorder_class[char]~="after subscript" then - c=current - end - current=getnext(current) - else - break - end - end - if c then - startnext=getnext(start) - head=remove_node(head,start) - local prev=getprev(c) - setlink(prev,start) - setlink(start,c) - start=startnext - startattr=getprop(start,a_syllabe) - end - end - if not startnext then - current=start - local next=getnext(current) - while next do - local nextchar=ischar(next,startfont) - if nextchar and getprop(next,a_syllabe)==startattr then - current=next - next=getnext(current) - else - break - end - end - if start~=current then - startnext=getnext(start) - head=remove_node(head,start) - local next=getnext(current) - setlink(start,next) - setlink(current,start) - start=startnext - end - end - return head,start,true -end -function handlers.devanagari_reorder_pre_base_reordering_consonants(head,start) - local current=start - local startnext=nil - local startprev=nil - local startfont=getfont(start) - local startattr=getprop(start,a_syllabe) - while current do - local char=ischar(current,startfont) - if char and getprop(current,a_syllabe)==startattr then - local next=getnext(current) - if halant[char] and not getprop(current,a_state) then - if next then - local nextchar=ischar(next,startfont) - if nextchar and getprop(next,a_syllabe)==startattr then - if nextchar==c_zwnj or nextchar==c_zwj then - current=next - next=getnext(current) - end - end - end - startnext=getnext(start) - removenode(start,start) - setlink(start,next) - setlink(current,start) - start=startnext - break - end - current=next - else - break - end - end - if not startnext then - current=getnext(start) - startattr=getprop(start,a_syllabe) - while current do - local char=ischar(current,startfont) - if char and getprop(current,a_syllabe)==startattr then - if not consonant[char] and getprop(current,a_state) then - startnext=getnext(start) - removenode(start,start) - local prev=getprev(current) - setlink(prev,start) - setlink(start,current) - start=startnext - break - end - current=getnext(current) - else - break - end - end - end - return head,start,true -end -function handlers.devanagari_remove_joiners(head,start,kind,lookupname,replacement) - local stop=getnext(start) - local font=getfont(start) - local last=start - while stop do - local char=ischar(stop,font) - if char and (char==c_zwnj or char==c_zwj) then - last=stop - stop=getnext(stop) - else - break - end - end - local prev=getprev(start) - if stop then - setnext(last) - setlink(prev,stop) - elseif prev then - setnext(prev) - end - if head==start then - head=stop - end - flush_list(start) - return head,stop,true -end -local function dev2_initialize(font,attr) - local devanagari=fontdata[font].resources.devanagari - if devanagari then - return devanagari.seqsubset or {},devanagari.reorderreph or {} - else - return {},{} - end -end -local function dev2_reorder(head,start,stop,font,attr,nbspaces) - local seqsubset,reorderreph=dev2_initialize(font,attr) - local reph=false - local halfpos=nil - local basepos=nil - local subpos=nil - local postpos=nil - local locl={} - for i=1,#seqsubset do - local subset=seqsubset[i] - local kind=subset[1] - local lookupcache=subset[2] - if kind=="rphf" then - reph=subset[3] - local current=start - local last=getnext(stop) - while current~=last do - if current~=stop then - local c=locl[current] or getchar(current) - local found=lookupcache[c] - if found then - local next=getnext(current) - local n=locl[next] or getchar(next) - if found[n] then - local afternext=next~=stop and getnext(next) - if afternext and zw_char[getchar(afternext)] then - current=next - current=getnext(current) - elseif current==start then - setprop(current,a_state,s_rphf) - current=next - else - current=next - end - end - end - end - current=getnext(current) - end - elseif kind=="pref" then - local current=start - local last=getnext(stop) - while current~=last do - if current~=stop then - local c=locl[current] or getchar(current) - local found=lookupcache[c] - if found then - local next=getnext(current) - local n=locl[next] or getchar(next) - if found[n] then - setprop(current,a_state,s_pref) - setprop(next,a_state,s_pref) - current=next - end - end - end - current=getnext(current) - end - elseif kind=="half" then - local current=start - local last=getnext(stop) - while current~=last do - if current~=stop then - local c=locl[current] or getchar(current) - local found=lookupcache[c] - if found then - local next=getnext(current) - local n=locl[next] or getchar(next) - if found[n] then - if next~=stop and getchar(getnext(next))==c_zwnj then - current=next - else - setprop(current,a_state,s_half) - if not halfpos then - halfpos=current - end - end - current=getnext(current) - end - end - end - current=getnext(current) - end - elseif kind=="blwf" then - local current=start - local last=getnext(stop) - while current~=last do - if current~=stop then - local c=locl[current] or getchar(current) - local found=lookupcache[c] - if found then - local next=getnext(current) - local n=locl[next] or getchar(next) - if found[n] then - setprop(current,a_state,s_blwf) - setprop(next,a_state,s_blwf) - current=next - subpos=current - end - end - end - current=getnext(current) - end - elseif kind=="pstf" then - local current=start - local last=getnext(stop) - while current~=last do - if current~=stop then - local c=locl[current] or getchar(current) - local found=lookupcache[c] - if found then - local next=getnext(current) - local n=locl[next] or getchar(next) - if found[n] then - setprop(current,a_state,s_pstf) - setprop(next,a_state,s_pstf) - current=next - postpos=current - end - end - end - current=getnext(current) - end - end - end - reorderreph.coverage={ [reph]=true } - local current,base,firstcons=start,nil,nil - if getprop(start,a_state)==s_rphf then - current=getnext(getnext(start)) - end - if current~=getnext(stop) and getchar(current)==c_nbsp then - if current==stop then - stop=getprev(stop) - head=remove_node(head,current) - flush_node(current) - return head,stop,nbspaces - else - nbspaces=nbspaces+1 - base=current - current=getnext(current) - if current~=stop then - local char=getchar(current) - if nukta[char] then - current=getnext(current) - char=getchar(current) - end - if char==c_zwj then - local next=getnext(current) - if current~=stop and next~=stop and halant[getchar(next)] then - current=next - next=getnext(current) - local tmp=getnext(next) - local changestop=next==stop - setnext(next,nil) - setprop(current,a_state,s_pref) - current=processcharacters(current,font) - setprop(current,a_state,s_blwf) - current=processcharacters(current,font) - setprop(current,a_state,s_pstf) - current=processcharacters(current,font) - setprop(current,a_state,unsetvalue) - if halant[getchar(current)] then - setnext(getnext(current),tmp) - local nc=copy_node(current) - copyinjection(nc,current) - setchar(current,dotted_circle) - head=insert_node_after(head,current,nc) - else - setnext(current,tmp) - if changestop then - stop=current - end - end - end - end - end - end - else - local last=getnext(stop) - while current~=last do - local next=getnext(current) - if consonant[getchar(current)] then - if not (current~=stop and next~=stop and halant[getchar(next)] and getchar(getnext(next))==c_zwj) then - if not firstcons then - firstcons=current - end - local a=getprop(current,a_state) - if not (a==s_pref or a==s_blwf or a==s_pstf) then - base=current - end - end - end - current=next - end - if not base then - base=firstcons - end - end - if not base then - if getprop(start,a_state)==s_rphf then - setprop(start,a_state,unsetvalue) - end - return head,stop,nbspaces - else - if getprop(base,a_state) then - setprop(base,a_state,unsetvalue) - end - basepos=base - end - if not halfpos then - halfpos=base - end - if not subpos then - subpos=base - end - if not postpos then - postpos=subpos or base - end - local moved={} - local current=start - local last=getnext(stop) - while current~=last do - local char,target,cn=locl[current] or getchar(current),nil,getnext(current) - local tpm=twopart_mark[char] - if tpm then - local extra=copy_node(current) - copyinjection(extra,current) - char=tpm[1] - setchar(current,char) - setchar(extra,tpm[2]) - head=insert_node_after(head,current,extra) - end - if not moved[current] and dependent_vowel[char] then - if pre_mark[char] then - moved[current]=true - local prev,next=getboth(current) - setlink(prev,next) - if current==stop then - stop=getprev(current) - end - if halfpos==start then - if head==start then - head=current - end - start=current - end - local prev=getprev(halfpos) - setlink(prev,current) - setlink(current,halfpos) - halfpos=current - elseif above_mark[char] then - target=basepos - if subpos==basepos then - subpos=current - end - if postpos==basepos then - postpos=current - end - basepos=current - elseif below_mark[char] then - target=subpos - if postpos==subpos then - postpos=current - end - subpos=current - elseif post_mark[char] then - target=postpos - postpos=current - end - if mark_above_below_post[char] then - local prev=getprev(current) - if prev~=target then - local next=getnext(current) - setlink(prev,next) - if current==stop then - stop=prev - end - local next=getnext(target) - setlink(current,next) - setlink(target,current) - end - end - end - current=cn - end - local current,c=start,nil - while current~=stop do - local char=getchar(current) - if halant[char] or stress_tone_mark[char] then - if not c then - c=current - end - else - c=nil - end - local next=getnext(current) - if c and nukta[getchar(next)] then - if head==c then - head=next - end - if stop==next then - stop=current - end - local prev=getprev(c) - setlink(prev,next) - local nextnext=getnext(next) - setnext(current,nextnext) - local nextnextnext=getnext(nextnext) - if nextnextnext then - setprev(nextnextnext,current) - end - setlink(nextnext,c) - end - if stop==current then break end - current=getnext(current) - end - if getchar(base)==c_nbsp then - if base==stop then - stop=getprev(stop) - end - nbspaces=nbspaces-1 - head=remove_node(head,base) - flush_node(base) - end - return head,stop,nbspaces -end -local separator={} -imerge(separator,consonant) -imerge(separator,independent_vowel) -imerge(separator,dependent_vowel) -imerge(separator,vowel_modifier) -imerge(separator,stress_tone_mark) -for k,v in next,nukta do separator[k]=true end -for k,v in next,halant do separator[k]=true end -local function analyze_next_chars_one(c,font,variant) - local n=getnext(c) - if not n then - return c - end - if variant==1 then - local v=ischar(n,font) - if v and nukta[v] then - n=getnext(n) - if n then - v=ischar(n,font) - end - end - if n and v then - local nn=getnext(n) - if nn then - local vv=ischar(nn,font) - if vv then - local nnn=getnext(nn) - if nnn then - local vvv=ischar(nnn,font) - if vvv then - if vv==c_zwj and consonant[vvv] then - c=nnn - elseif (vv==c_zwnj or vv==c_zwj) and halant[vvv] then - local nnnn=getnext(nnn) - if nnnn then - local vvvv=ischar(nnnn,font) - if vvvv and consonant[vvvv] then - c=nnnn - end - end - end - end - end - end - end - end - elseif variant==2 then - local v=ischar(n,font) - if v and nukta[v] then - c=n - end - n=getnext(c) - if n then - v=ischar(n,font) - if v then - local nn=getnext(n) - if nn then - local vv=ischar(nn,font) - if vv and zw_char[v] then - n=nn - v=vv - nn=getnext(nn) - vv=nn and ischar(nn,font) - end - if vv and halant[v] and consonant[vv] then - c=nn - end - end - end - end - end - local n=getnext(c) - if not n then - return c - end - local v=ischar(n,font) - if not v then - return c - end - if dependent_vowel[v] then - c=getnext(c) - n=getnext(c) - if not n then - return c - end - v=ischar(n,font) - if not v then - return c - end - end - if nukta[v] then - c=getnext(c) - n=getnext(c) - if not n then - return c - end - v=ischar(n,font) - if not v then - return c - end - end - if halant[v] then - c=getnext(c) - n=getnext(c) - if not n then - return c - end - v=ischar(n,font) - if not v then - return c - end - end - if vowel_modifier[v] then - c=getnext(c) - n=getnext(c) - if not n then - return c - end - v=ischar(n,font) - if not v then - return c - end - end - if stress_tone_mark[v] then - c=getnext(c) - n=getnext(c) - if not n then - return c - end - v=ischar(n,font) - if not v then - return c - end - end - if stress_tone_mark[v] then - return n - else - return c - end -end -local function analyze_next_chars_two(c,font) - local n=getnext(c) - if not n then - return c - end - local v=ischar(n,font) - if v and nukta[v] then - c=n - end - n=c - while true do - local nn=getnext(n) - if nn then - local vv=ischar(nn,font) - if vv then - if halant[vv] then - n=nn - local nnn=getnext(nn) - if nnn then - local vvv=ischar(nnn,font) - if vvv and zw_char[vvv] then - n=nnn - end - end - elseif vv==c_zwnj or vv==c_zwj then - local nnn=getnext(nn) - if nnn then - local vvv=ischar(nnn,font) - if vvv and halant[vvv] then - n=nnn - end - end - else - break - end - local nn=getnext(n) - if nn then - local vv=ischar(nn,font) - if vv and consonant[vv] then - n=nn - local nnn=getnext(nn) - if nnn then - local vvv=ischar(nnn,font) - if vvv and nukta[vvv] then - n=nnn - end - end - c=n - else - break - end - else - break - end - else - break - end - else - break - end - end - if not c then - return - end - local n=getnext(c) - if not n then - return c - end - local v=ischar(n,font) - if not v then - return c - end - if v==c_anudatta then - c=n - n=getnext(c) - if not n then - return c - end - v=ischar(n,font) - if not v then - return c - end - end - if halant[v] then - c=n - n=getnext(c) - if not n then - return c - end - v=ischar(n,font) - if not v then - return c - end - if v==c_zwnj or v==c_zwj then - c=n - n=getnext(c) - if not n then - return c - end - v=ischar(n,font) - if not v then - return c - end - end - else - if dependent_vowel[v] then - c=n - n=getnext(c) - if not n then - return c - end - v=ischar(n,font) - if not v then - return c - end - end - if nukta[v] then - c=n - n=getnext(c) - if not n then - return c - end - v=ischar(n,font) - if not v then - return c - end - end - if halant[v] then - c=n - n=getnext(c) - if not n then - return c - end - v=ischar(n,font) - if not v then - return c - end - end - end - if vowel_modifier[v] then - c=n - n=getnext(c) - if not n then - return c - end - v=ischar(n,font) - if not v then - return c - end - end - if stress_tone_mark[v] then - c=n - n=getnext(c) - if not n then - return c - end - v=ischar(n,font) - if not v then - return c - end - end - if stress_tone_mark[v] then - return n - else - return c - end -end -local function inject_syntax_error(head,current,mark) - local signal=copy_node(current) - copyinjection(signal,current) - if mark==pre_mark then - setchar(signal,dotted_circle) - else - setchar(current,dotted_circle) - end - return insert_node_after(head,current,signal) -end -function methods.deva(head,font,attr) - head=tonut(head) - local current=head - local start=true - local done=false - local nbspaces=0 - while current do - local char=ischar(current,font) - if char then - done=true - local syllablestart=current - local syllableend=nil - local c=current - local n=getnext(c) - local first=char - if n and ra[first] then - local second=ischar(n,font) - if second and halant[second] then - local n=getnext(n) - if n then - local third=ischar(n,font) - if third then - c=n - first=third - end - end - end - end - local standalone=first==c_nbsp - if standalone then - local prev=getprev(current) - if prev then - local prevchar=ischar(prev,font) - if not prevchar then - elseif not separator[prevchar] then - else - standalone=false - end - else - end - end - if standalone then - local syllableend=analyze_next_chars_one(c,font,2) - current=getnext(syllableend) - if syllablestart~=syllableend then - head,current,nbspaces=deva_reorder(head,syllablestart,syllableend,font,attr,nbspaces) - current=getnext(current) - end - else - if consonant[char] then - local prevc=true - while prevc do - prevc=false - local n=getnext(current) - if not n then - break - end - local v=ischar(n,font) - if not v then - break - end - if nukta[v] then - n=getnext(n) - if not n then - break - end - v=ischar(n,font) - if not v then - break - end - end - if halant[v] then - n=getnext(n) - if not n then - break - end - v=ischar(n,font) - if not v then - break - end - if v==c_zwnj or v==c_zwj then - n=getnext(n) - if not n then - break - end - v=ischar(n,font) - if not v then - break - end - end - if consonant[v] then - prevc=true - current=n - end - end - end - local n=getnext(current) - if n then - local v=ischar(n,font) - if v and nukta[v] then - current=n - n=getnext(current) - end - end - syllableend=current - current=n - if current then - local v=ischar(current,font) - if not v then - elseif halant[v] then - local n=getnext(current) - if n then - local v=ischar(n,font) - if v and zw_char[v] then - syllableend=n - current=getnext(n) - else - syllableend=current - current=n - end - else - syllableend=current - current=n - end - else - if dependent_vowel[v] then - syllableend=current - current=getnext(current) - v=ischar(current,font) - end - if v and vowel_modifier[v] then - syllableend=current - current=getnext(current) - v=ischar(current,font) - end - if v and stress_tone_mark[v] then - syllableend=current - current=getnext(current) - end - end - end - if syllablestart~=syllableend then - head,current,nbspaces=deva_reorder(head,syllablestart,syllableend,font,attr,nbspaces) - current=getnext(current) - end - elseif independent_vowel[char] then - syllableend=current - current=getnext(current) - if current then - local v=ischar(current,font) - if v then - if vowel_modifier[v] then - syllableend=current - current=getnext(current) - v=ischar(current,font) - end - if v and stress_tone_mark[v] then - syllableend=current - current=getnext(current) - end - end - end - else - local mark=mark_four[char] - if mark then - head,current=inject_syntax_error(head,current,mark) - end - current=getnext(current) - end - end - else - current=getnext(current) - end - start=false - end - if nbspaces>0 then - head=replace_all_nbsp(head) - end - head=tonode(head) - return head,done -end -function methods.dev2(head,font,attr) - head=tonut(head) - local current=head - local start=true - local done=false - local syllabe=0 - local nbspaces=0 - while current do - local syllablestart=nil - local syllableend=nil - local char=ischar(current,font) - if char then - done=true - syllablestart=current - local c=current - local n=getnext(current) - if n and ra[char] then - local nextchar=ischar(n,font) - if nextchar and halant[nextchar] then - local n=getnext(n) - if n then - local nextnextchar=ischar(n,font) - if nextnextchar then - c=n - char=nextnextchar - end - end - end - end - if independent_vowel[char] then - current=analyze_next_chars_one(c,font,1) - syllableend=current - else - local standalone=char==c_nbsp - if standalone then - nbspaces=nbspaces+1 - local p=getprev(current) - if not p then - elseif ischar(p,font) then - elseif not separator[getchar(p)] then - else - standalone=false - end - end - if standalone then - current=analyze_next_chars_one(c,font,2) - syllableend=current - elseif consonant[getchar(current)] then - current=analyze_next_chars_two(current,font) - syllableend=current - end - end - end - if syllableend then - syllabe=syllabe+1 - local c=syllablestart - local n=getnext(syllableend) - while c~=n do - setprop(c,a_syllabe,syllabe) - c=getnext(c) - end - end - if syllableend and syllablestart~=syllableend then - head,current,nbspaces=dev2_reorder(head,syllablestart,syllableend,font,attr,nbspaces) - end - if not syllableend then - local char=ischar(current,font) - if char and not getprop(current,a_state) then - local mark=mark_four[char] - if mark then - head,current=inject_syntax_error(head,current,mark) - end - end - end - start=false - current=getnext(current) - end - if nbspaces>0 then - head=replace_all_nbsp(head) - end - head=tonode(head) - return head,done -end -methods.mlym=methods.deva -methods.mlm2=methods.dev2 - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['font-ocl']={ - version=1.001, - comment="companion to font-otf.lua (context)", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local tostring,next,format=tostring,next,string.format -local round,max=math.round,math.round -local formatters=string.formatters -local tounicode=fonts.mappings.tounicode -local otf=fonts.handlers.otf -local f_color=formatters["pdf:direct:%f %f %f rg"] -local f_gray=formatters["pdf:direct:%f g"] -local s_black="pdf:direct:0 g" -if context then - local startactualtext=nil - local stopactualtext=nil - function otf.getactualtext(s) - if not startactualtext then - startactualtext=backends.codeinjections.startunicodetoactualtextdirect - stopactualtext=backends.codeinjections.stopunicodetoactualtextdirect - end - return startactualtext(s),stopactualtext() - end -else - local tounicode=fonts.mappings.tounicode16 - function otf.getactualtext(s) - return - "/Span << /ActualText <feff"..n.."> >> BDC", - "EMC" - end -end -local sharedpalettes={} -if context then - local graytorgb=attributes.colors.graytorgb - local cmyktorgb=attributes.colors.cmyktorgb - function otf.registerpalette(name,values) - sharedpalettes[name]=values - for i=1,#values do - local v=values[i] - local r,g,b - local s=v.s - if s then - r,g,b=graytorgb(s) - else - local c,m,y,k=v.c,v.m,v.y,v.k - if c or m or y or k then - r,g,b=cmyktorgb(c or 0,m or 0,y or 0,k or 0) - else - r,g,b=v.r,v.g,v.b - end - end - values[i]={ - max(r and round(r*255) or 0,255), - max(g and round(g*255) or 0,255), - max(b and round(b*255) or 0,255) - } - end - end -else - function otf.registerpalette(name,values) - sharedpalettes[name]=values - for i=1,#values do - local v=values[i] - values[i]={ - max(round((v.r or 0)*255),255), - max(round((v.g or 0)*255),255), - max(round((v.b or 0)*255),255) - } - end - end -end -local function initializecolr(tfmdata,kind,value) - if value then - local palettes=tfmdata.resources.colorpalettes - if palettes then - local palette=sharedpalettes[value] or palettes[tonumber(value) or 1] or palettes[1] or {} - local classes=#palette - if classes==0 then - return - end - local characters=tfmdata.characters - local descriptions=tfmdata.descriptions - local properties=tfmdata.properties - local colorvalues={} - properties.virtualized=true - tfmdata.fonts={ - { id=0 } - } - for i=1,classes do - local p=palette[i] - local r,g,b=p[1],p[2],p[3] - if r==g and g==b then - colorvalues[i]={ "special",f_gray(r/255) } - else - colorvalues[i]={ "special",f_color(r/255,g/255,b/255) } - end - end - local getactualtext=otf.getactualtext - for unicode,character in next,characters do - local description=descriptions[unicode] - if description then - local colorlist=description.colors - if colorlist then - local b,e=getactualtext(tounicode(characters[unicode].unicode or 0xFFFD)) - local w=character.width or 0 - local s=#colorlist - local t={ - { "special","pdf:page:q" }, - { "special","pdf:raw:"..b } - } - local n=#t - for i=1,s do - local entry=colorlist[i] - n=n+1 t[n]=colorvalues[entry.class] or s_black - n=n+1 t[n]={ "char",entry.slot } - if s>1 and i<s and w~=0 then - n=n+1 t[n]={ "right",-w } - end - end - n=n+1 t[n]={ "special","pdf:page:"..e } - n=n+1 t[n]={ "special","pdf:raw:Q" } - character.commands=t - end - end - end - end - end -end -fonts.handlers.otf.features.register { - name="colr", - description="color glyphs", - manipulators={ - base=initializecolr, - node=initializecolr, - } -} -local otfsvg=otf.svg or {} -otf.svg=otfsvg -otf.svgenabled=true -do - local nofstreams=0 - local f_name=formatters[ [[svg-glyph-%05i]] ] - local f_used=context and formatters[ [[original:///%s]] ] or formatters[ [[%s]] ] - local cache={} - function otfsvg.storepdfdata(pdf) - nofstreams=nofstreams+1 - local o,n=epdf.openMemStream(pdf,#pdf,f_name(nofstreams)) - cache[n]=o - return nil,f_used(n),nil - end - if context then - local storepdfdata=otfsvg.storepdfdata - local initialized=false - function otfsvg.storepdfdata(pdf) - if not initialized then - if resolvers.setmemstream then - local f_setstream=formatters[ [[resolvers.setmemstream("svg-glyph-%05i",%q,true)]] ] - local f_getstream=formatters[ [[memstream:///svg-glyph-%05i]] ] - local f_nilstream=formatters[ [[resolvers.resetmemstream("svg-glyph-%05i",true)]] ] - storepdfdata=function(pdf) - nofstreams=nofstreams+1 - return - f_setstream(nofstreams,pdf), - f_getstream(nofstreams), - f_nilstream(nofstreams) - end - otfsvg.storepdfdata=storepdfdata - end - initialized=true - end - return storepdfdata(pdf) - end - end -end -do - local report_svg=logs.reporter("fonts","svg conversion") - local loaddata=io.loaddata - local savedata=io.savedata - local remove=os.remove - if context and xml.convert then - local xmlconvert=xml.convert - local xmlfirst=xml.first - function otfsvg.filterglyph(entry,index) - local svg=xmlconvert(entry.data) - local root=svg and xmlfirst(svg,"/svg[@id='glyph"..index.."']") - local data=root and tostring(root) - return data - end - else - function otfsvg.filterglyph(entry,index) - return entry.data - end - end - function otfsvg.topdf(svgshapes) - local inkscape=io.popen("inkscape --shell > temp-otf-svg-shape.log","w") - local pdfshapes={} - local nofshapes=#svgshapes - local f_svgfile=formatters["temp-otf-svg-shape-%i.svg"] - local f_pdffile=formatters["temp-otf-svg-shape-%i.pdf"] - local f_convert=formatters["%s --export-pdf=%s\n"] - local filterglyph=otfsvg.filterglyph - report_svg("processing %i svg containers",nofshapes) - statistics.starttiming() - for i=1,nofshapes do - local entry=svgshapes[i] - for index=entry.first,entry.last do - local data=filterglyph(entry,index) - if data and data~="" then - local svgfile=f_svgfile(index) - local pdffile=f_pdffile(index) - savedata(svgfile,data) - inkscape:write(f_convert(svgfile,pdffile)) - pdfshapes[index]=true - end - end - end - inkscape:write("quit\n") - inkscape:close() - report_svg("processing %i pdf results",nofshapes) - for index in next,pdfshapes do - local svgfile=f_svgfile(index) - local pdffile=f_pdffile(index) - pdfshapes[index]=loaddata(pdffile) - remove(svgfile) - remove(pdffile) - end - statistics.stoptiming() - if statistics.elapsedseconds then - report_svg("svg conversion time %s",statistics.elapsedseconds()) - end - return pdfshapes - end -end -local function initializesvg(tfmdata,kind,value) - if value and otf.svgenabled then - local characters=tfmdata.characters - local descriptions=tfmdata.descriptions - local properties=tfmdata.properties - local svg=properties.svg - local hash=svg and svg.hash - local timestamp=svg and svg.timestamp - if not hash then - return - end - local pdffile=containers.read(otf.pdfcache,hash) - local pdfshapes=pdffile and pdffile.pdfshapes - if not pdfshapes or pdffile.timestamp~=timestamp then - local svgfile=containers.read(otf.svgcache,hash) - local svgshapes=svgfile and svgfile.svgshapes - pdfshapes=svgshapes and otfsvg.topdf(svgshapes) or {} - containers.write(otf.pdfcache,hash,{ - pdfshapes=pdfshapes, - timestamp=timestamp, - }) - end - if not pdfshapes or not next(pdfshapes) then - return - end - properties.virtualized=true - tfmdata.fonts={ - { id=0 } - } - local getactualtext=otf.getactualtext - local storepdfdata=otfsvg.storepdfdata - local nop={ "nop" } - for unicode,character in next,characters do - local index=character.index - if index then - local pdf=pdfshapes[index] - if pdf then - local setcode,name,nilcode=storepdfdata(pdf) - if name then - local bt,et=getactualtext(unicode) - local wd=character.width or 0 - local ht=character.height or 0 - local dp=character.depth or 0 - character.commands={ - { "special","pdf:direct:"..bt }, - { "down",dp }, - setcode and { "lua",setcode } or nop, - { "image",{ filename=name,width=wd,height=ht,depth=dp } }, - nilcode and { "lua",nilcode } or nop, - { "special","pdf:direct:"..et }, - } - character.svg=true - end - end - end - end - end -end -fonts.handlers.otf.features.register { - name="svg", - description="svg glyphs", - manipulators={ - base=initializesvg, - node=initializesvg, - } -} - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['font-otc']={ - version=1.001, - comment="companion to font-otf.lua (context)", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local format,insert,sortedkeys,tohash=string.format,table.insert,table.sortedkeys,table.tohash -local type,next=type,next -local lpegmatch=lpeg.match -local utfbyte,utflen=utf.byte,utf.len -local trace_loading=false trackers.register("otf.loading",function(v) trace_loading=v end) -local report_otf=logs.reporter("fonts","otf loading") -local fonts=fonts -local otf=fonts.handlers.otf -local registerotffeature=otf.features.register -local setmetatableindex=table.setmetatableindex -local normalized={ - substitution="substitution", - single="substitution", - ligature="ligature", - alternate="alternate", - multiple="multiple", - kern="kern", - pair="pair", - chainsubstitution="chainsubstitution", - chainposition="chainposition", -} -local types={ - substitution="gsub_single", - ligature="gsub_ligature", - alternate="gsub_alternate", - multiple="gsub_multiple", - kern="gpos_pair", - pair="gpos_pair", - chainsubstitution="gsub_contextchain", - chainposition="gpos_contextchain", -} -local names={ - gsub_single="gsub", - gsub_multiple="gsub", - gsub_alternate="gsub", - gsub_ligature="gsub", - gsub_context="gsub", - gsub_contextchain="gsub", - gsub_reversecontextchain="gsub", - gpos_single="gpos", - gpos_pair="gpos", - gpos_cursive="gpos", - gpos_mark2base="gpos", - gpos_mark2ligature="gpos", - gpos_mark2mark="gpos", - gpos_context="gpos", - gpos_contextchain="gpos", -} -setmetatableindex(types,function(t,k) t[k]=k return k end) -local everywhere={ ["*"]={ ["*"]=true } } -local noflags={ false,false,false,false } -local function getrange(sequences,category) - local count=#sequences - local first=nil - local last=nil - for i=1,count do - local t=sequences[i].type - if t and names[t]==category then - if not first then - first=i - end - last=i - end - end - return first or 1,last or count -end -local function validspecification(specification,name) - local dataset=specification.dataset - if dataset then - elseif specification[1] then - dataset=specification - specification={ dataset=dataset } - else - dataset={ { data=specification.data } } - specification.data=nil - specification.dataset=dataset - end - local first=dataset[1] - if first then - first=first.data - end - if not first then - report_otf("invalid feature specification, no dataset") - return - end - if type(name)~="string" then - name=specification.name or first.name - end - if type(name)~="string" then - report_otf("invalid feature specification, no name") - return - end - local n=#dataset - if n>0 then - for i=1,n do - setmetatableindex(dataset[i],specification) - end - return specification,name - end -end -local function addfeature(data,feature,specifications) - if not specifications then - report_otf("missing specification") - return - end - local descriptions=data.descriptions - local resources=data.resources - local features=resources.features - local sequences=resources.sequences - if not features or not sequences then - report_otf("missing specification") - return - end - local alreadydone=resources.alreadydone - if not alreadydone then - alreadydone={} - resources.alreadydone=alreadydone - end - if alreadydone[specifications] then - return - else - alreadydone[specifications]=true - end - local fontfeatures=resources.features or everywhere - local unicodes=resources.unicodes - local splitter=lpeg.splitter(" ",unicodes) - local done=0 - local skip=0 - local aglunicodes=false - local specifications=validspecification(specifications,feature) - if not specifications then - return - end - local function tounicode(code) - if not code then - return - end - if type(code)=="number" then - return code - end - local u=unicodes[code] - if u then - return u - end - if utflen(code)==1 then - u=utfbyte(code) - if u then - return u - end - end - if not aglunicodes then - aglunicodes=fonts.encodings.agl.unicodes - end - return aglunicodes[code] - end - local coverup=otf.coverup - local coveractions=coverup.actions - local stepkey=coverup.stepkey - local register=coverup.register - local function prepare_substitution(list,featuretype) - local coverage={} - local cover=coveractions[featuretype] - for code,replacement in next,list do - local unicode=tounicode(code) - local description=descriptions[unicode] - if description then - if type(replacement)=="table" then - replacement=replacement[1] - end - replacement=tounicode(replacement) - if replacement and descriptions[replacement] then - cover(coverage,unicode,replacement) - done=done+1 - else - skip=skip+1 - end - else - skip=skip+1 - end - end - return coverage - end - local function prepare_alternate(list,featuretype) - local coverage={} - local cover=coveractions[featuretype] - for code,replacement in next,list do - local unicode=tounicode(code) - local description=descriptions[unicode] - if not description then - skip=skip+1 - elseif type(replacement)=="table" then - local r={} - for i=1,#replacement do - local u=tounicode(replacement[i]) - r[i]=descriptions[u] and u or unicode - end - cover(coverage,unicode,r) - done=done+1 - else - local u=tounicode(replacement) - if u then - cover(coverage,unicode,{ u }) - done=done+1 - else - skip=skip+1 - end - end - end - return coverage - end - local function prepare_multiple(list,featuretype) - local coverage={} - local cover=coveractions[featuretype] - for code,replacement in next,list do - local unicode=tounicode(code) - local description=descriptions[unicode] - if not description then - skip=skip+1 - elseif type(replacement)=="table" then - local r,n={},0 - for i=1,#replacement do - local u=tounicode(replacement[i]) - if descriptions[u] then - n=n+1 - r[n]=u - end - end - if n>0 then - cover(coverage,unicode,r) - done=done+1 - else - skip=skip+1 - end - else - local u=tounicode(replacement) - if u then - cover(coverage,unicode,{ u }) - done=done+1 - else - skip=skip+1 - end - end - end - return coverage - end - local function prepare_ligature(list,featuretype) - local coverage={} - local cover=coveractions[featuretype] - for code,ligature in next,list do - local unicode=tounicode(code) - local description=descriptions[unicode] - if description then - if type(ligature)=="string" then - ligature={ lpegmatch(splitter,ligature) } - end - local present=true - for i=1,#ligature do - local l=ligature[i] - local u=tounicode(l) - if descriptions[u] then - ligature[i]=u - else - present=false - break - end - end - if present then - cover(coverage,unicode,ligature) - done=done+1 - else - skip=skip+1 - end - else - skip=skip+1 - end - end - return coverage - end - local function prepare_kern(list,featuretype) - local coverage={} - local cover=coveractions[featuretype] - for code,replacement in next,list do - local unicode=tounicode(code) - local description=descriptions[unicode] - if description and type(replacement)=="table" then - local r={} - for k,v in next,replacement do - local u=tounicode(k) - if u then - r[u]=v - end - end - if next(r) then - cover(coverage,unicode,r) - done=done+1 - else - skip=skip+1 - end - else - skip=skip+1 - end - end - return coverage - end - local function prepare_pair(list,featuretype) - local coverage={} - local cover=coveractions[featuretype] - if cover then - for code,replacement in next,list do - local unicode=tounicode(code) - local description=descriptions[unicode] - if description and type(replacement)=="table" then - local r={} - for k,v in next,replacement do - local u=tounicode(k) - if u then - r[u]=v - end - end - if next(r) then - cover(coverage,unicode,r) - done=done+1 - else - skip=skip+1 - end - else - skip=skip+1 - end - end - else - report_otf("unknown cover type %a",featuretype) - end - return coverage - end - local function prepare_chain(list,featuretype,sublookups) - local rules=list.rules - local coverage={} - if rules then - local rulehash={} - local rulesize=0 - local sequence={} - local nofsequences=0 - local lookuptype=types[featuretype] - for nofrules=1,#rules do - local rule=rules[nofrules] - local current=rule.current - local before=rule.before - local after=rule.after - local replacements=rule.replacements or false - local sequence={} - local nofsequences=0 - if before then - for n=1,#before do - nofsequences=nofsequences+1 - sequence[nofsequences]=before[n] - end - end - local start=nofsequences+1 - for n=1,#current do - nofsequences=nofsequences+1 - sequence[nofsequences]=current[n] - end - local stop=nofsequences - if after then - for n=1,#after do - nofsequences=nofsequences+1 - sequence[nofsequences]=after[n] - end - end - local lookups=rule.lookups or false - local subtype=nil - if lookups and sublookups then - for k,v in next,lookups do - local lookup=sublookups[v] - if lookup then - lookups[k]=lookup - if not subtype then - subtype=lookup.type - end - else - end - end - end - if nofsequences>0 then - local hashed={} - for i=1,nofsequences do - local t={} - local s=sequence[i] - for i=1,#s do - local u=tounicode(s[i]) - if u then - t[u]=true - end - end - hashed[i]=t - end - sequence=hashed - rulesize=rulesize+1 - rulehash[rulesize]={ - nofrules, - lookuptype, - sequence, - start, - stop, - lookups, - replacements, - subtype, - } - for unic in next,sequence[start] do - local cu=coverage[unic] - if not cu then - coverage[unic]=rulehash - end - end - end - end - end - return coverage - end - local dataset=specifications.dataset - local function report(name,category,position,first,last,sequences) - report_otf("injecting name %a of category %a at position %i in [%i,%i] of [%i,%i]", - name,category,position,first,last,1,#sequences) - end - local function inject(specification,sequences,sequence,first,last,category,name) - local position=specification.position or false - if not position then - position=specification.prepend - if position==true then - if trace_loading then - report(name,category,first,first,last,sequences) - end - insert(sequences,first,sequence) - return - end - end - if not position then - position=specification.append - if position==true then - if trace_loading then - report(name,category,last+1,first,last,sequences) - end - insert(sequences,last+1,sequence) - return - end - end - local kind=type(position) - if kind=="string" then - local index=false - for i=first,last do - local s=sequences[i] - local f=s.features - if f then - for k in next,f do - if k==position then - index=i - break - end - end - if index then - break - end - end - end - if index then - position=index - else - position=last+1 - end - elseif kind=="number" then - if position<0 then - position=last-position+1 - end - if position>last then - position=last+1 - elseif position<first then - position=first - end - else - position=last+1 - end - if trace_loading then - report(name,category,position,first,last,sequences) - end - insert(sequences,position,sequence) - end - for s=1,#dataset do - local specification=dataset[s] - local valid=specification.valid - local feature=specification.name or feature - if not feature or feature=="" then - report_otf("no valid name given for extra feature") - elseif not valid or valid(data,specification,feature) then - local initialize=specification.initialize - if initialize then - specification.initialize=initialize(specification,data) and initialize or nil - end - local askedfeatures=specification.features or everywhere - local askedsteps=specification.steps or specification.subtables or { specification.data } or {} - local featuretype=normalized[specification.type or "substitution"] or "substitution" - local featureflags=specification.flags or noflags - local featureorder=specification.order or { feature } - local featurechain=(featuretype=="chainsubstitution" or featuretype=="chainposition") and 1 or 0 - local nofsteps=0 - local steps={} - local sublookups=specification.lookups - local category=nil - if sublookups then - local s={} - for i=1,#sublookups do - local specification=sublookups[i] - local askedsteps=specification.steps or specification.subtables or { specification.data } or {} - local featuretype=normalized[specification.type or "substitution"] or "substitution" - local featureflags=specification.flags or noflags - local nofsteps=0 - local steps={} - for i=1,#askedsteps do - local list=askedsteps[i] - local coverage=nil - local format=nil - if featuretype=="substitution" then - coverage=prepare_substitution(list,featuretype) - elseif featuretype=="ligature" then - coverage=prepare_ligature(list,featuretype) - elseif featuretype=="alternate" then - coverage=prepare_alternate(list,featuretype) - elseif featuretype=="multiple" then - coverage=prepare_multiple(list,featuretype) - elseif featuretype=="kern" then - format="kern" - coverage=prepare_kern(list,featuretype) - elseif featuretype=="pair" then - format="pair" - coverage=prepare_pair(list,featuretype) - end - if coverage and next(coverage) then - nofsteps=nofsteps+1 - steps[nofsteps]=register(coverage,featuretype,format,feature,nofsteps,descriptions,resources) - end - end - s[i]={ - [stepkey]=steps, - nofsteps=nofsteps, - type=types[featuretype], - } - end - sublookups=s - end - for i=1,#askedsteps do - local list=askedsteps[i] - local coverage=nil - local format=nil - if featuretype=="substitution" then - category="gsub" - coverage=prepare_substitution(list,featuretype) - elseif featuretype=="ligature" then - category="gsub" - coverage=prepare_ligature(list,featuretype) - elseif featuretype=="alternate" then - category="gsub" - coverage=prepare_alternate(list,featuretype) - elseif featuretype=="multiple" then - category="gsub" - coverage=prepare_multiple(list,featuretype) - elseif featuretype=="kern" then - category="gpos" - format="kern" - coverage=prepare_kern(list,featuretype) - elseif featuretype=="pair" then - category="gpos" - format="pair" - coverage=prepare_pair(list,featuretype) - elseif featuretype=="chainsubstitution" then - category="gsub" - coverage=prepare_chain(list,featuretype,sublookups) - elseif featuretype=="chainposition" then - category="gpos" - coverage=prepare_chain(list,featuretype,sublookups) - else - report_otf("not registering feature %a, unknown category",feature) - return - end - if coverage and next(coverage) then - nofsteps=nofsteps+1 - steps[nofsteps]=register(coverage,featuretype,format,feature,nofsteps,descriptions,resources) - end - end - if nofsteps>0 then - for k,v in next,askedfeatures do - if v[1] then - askedfeatures[k]=tohash(v) - end - end - if featureflags[1] then featureflags[1]="mark" end - if featureflags[2] then featureflags[2]="ligature" end - if featureflags[3] then featureflags[3]="base" end - local steptype=types[featuretype] - local sequence={ - chain=featurechain, - features={ [feature]=askedfeatures }, - flags=featureflags, - name=feature, - order=featureorder, - [stepkey]=steps, - nofsteps=nofsteps, - type=steptype, - } - local first,last=getrange(sequences,category) - inject(specification,sequences,sequence,first,last,category,feature) - local features=fontfeatures[category] - if not features then - features={} - fontfeatures[category]=features - end - local k=features[feature] - if not k then - k={} - features[feature]=k - end - for script,languages in next,askedfeatures do - local kk=k[script] - if not kk then - kk={} - k[script]=kk - end - for language,value in next,languages do - kk[language]=value - end - end - end - end - end - if trace_loading then - report_otf("registering feature %a, affected glyphs %a, skipped glyphs %a",feature,done,skip) - end -end -otf.enhancers.addfeature=addfeature -local extrafeatures={} -local knownfeatures={} -function otf.addfeature(name,specification) - if type(name)=="table" then - specification=name - end - if type(specification)~="table" then - report_otf("invalid feature specification, no valid table") - return - end - specification,name=validspecification(specification,name) - if name and specification then - local slot=knownfeatures[name] - if slot then - else - slot=#extrafeatures+1 - knownfeatures[name]=slot - end - specification.name=name - extrafeatures[slot]=specification - end -end -local function enhance(data,filename,raw) - for slot=1,#extrafeatures do - local specification=extrafeatures[slot] - addfeature(data,specification.name,specification) - end -end -otf.enhancers.enhance=enhance -otf.enhancers.register("check extra features",enhance) -local tlig={ - [0x2013]={ 0x002D,0x002D }, - [0x2014]={ 0x002D,0x002D,0x002D }, -} -local tlig_specification={ - type="ligature", - features=everywhere, - data=tlig, - order={ "tlig" }, - flags=noflags, - prepend=true, -} -otf.addfeature("tlig",tlig_specification) -registerotffeature { - name='tlig', - description='tex ligatures', -} -local trep={ - [0x0027]=0x2019, -} -local trep_specification={ - type="substitution", - features=everywhere, - data=trep, - order={ "trep" }, - flags=noflags, - prepend=true, -} -otf.addfeature("trep",trep_specification) -registerotffeature { - name='trep', - description='tex replacements', -} -local anum_arabic={ - [0x0030]=0x0660, - [0x0031]=0x0661, - [0x0032]=0x0662, - [0x0033]=0x0663, - [0x0034]=0x0664, - [0x0035]=0x0665, - [0x0036]=0x0666, - [0x0037]=0x0667, - [0x0038]=0x0668, - [0x0039]=0x0669, -} -local anum_persian={ - [0x0030]=0x06F0, - [0x0031]=0x06F1, - [0x0032]=0x06F2, - [0x0033]=0x06F3, - [0x0034]=0x06F4, - [0x0035]=0x06F5, - [0x0036]=0x06F6, - [0x0037]=0x06F7, - [0x0038]=0x06F8, - [0x0039]=0x06F9, -} -local function valid(data) - local features=data.resources.features - if features then - for k,v in next,features do - for k,v in next,v do - if v.arab then - return true - end - end - end - end -end -local anum_specification={ - { - type="substitution", - features={ arab={ urd=true,dflt=true } }, - order={ "anum" }, - data=anum_arabic, - flags=noflags, - valid=valid, - }, - { - type="substitution", - features={ arab={ urd=true } }, - order={ "anum" }, - data=anum_persian, - flags=noflags, - valid=valid, - }, -} -otf.addfeature("anum",anum_specification) -registerotffeature { - name='anum', - description='arabic digits', -} - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['font-onr']={ - version=1.001, - comment="companion to font-ini.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local fonts,logs,trackers,resolvers=fonts,logs,trackers,resolvers -local next,type,tonumber,rawget,rawset=next,type,tonumber,rawget,rawset -local match,lower,gsub,strip,find=string.match,string.lower,string.gsub,string.strip,string.find -local char,byte,sub=string.char,string.byte,string.sub -local abs=math.abs -local bxor,rshift=bit32.bxor,bit32.rshift -local P,S,R,Cmt,C,Ct,Cs,Carg,Cf,Cg=lpeg.P,lpeg.S,lpeg.R,lpeg.Cmt,lpeg.C,lpeg.Ct,lpeg.Cs,lpeg.Carg,lpeg.Cf,lpeg.Cg -local lpegmatch,patterns=lpeg.match,lpeg.patterns -local trace_indexing=false trackers.register("afm.indexing",function(v) trace_indexing=v end) -local trace_loading=false trackers.register("afm.loading",function(v) trace_loading=v end) -local report_afm=logs.reporter("fonts","afm loading") -local report_pfb=logs.reporter("fonts","pfb loading") -local handlers=fonts.handlers -local afm=handlers.afm or {} -handlers.afm=afm -local readers=afm.readers or {} -afm.readers=readers -afm.version=1.512 -local get_indexes,get_shapes -do - local decrypt - do - local r,c1,c2,n=0,0,0,0 - local function step(c) - local cipher=byte(c) - local plain=bxor(cipher,rshift(r,8)) - r=((cipher+r)*c1+c2)%65536 - return char(plain) - end - decrypt=function(binary,initial,seed) - r,c1,c2,n=initial,52845,22719,seed - binary=gsub(binary,".",step) - return sub(binary,n+1) - end - end - local charstrings=P("/CharStrings") - local subroutines=P("/Subrs") - local encoding=P("/Encoding") - local dup=P("dup") - local put=P("put") - local array=P("array") - local name=P("/")*C((R("az")+R("AZ")+R("09")+S("-_."))^1) - local digits=R("09")^1 - local cardinal=digits/tonumber - local spaces=P(" ")^1 - local spacing=patterns.whitespace^0 - local routines,vector,chars,n,m - local initialize=function(str,position,size) - n=0 - m=size - return position+1 - end - local setroutine=function(str,position,index,size) - local forward=position+tonumber(size) - local stream=sub(str,position+1,forward) - routines[index]=decrypt(stream,4330,4) - return forward - end - local setvector=function(str,position,name,size) - local forward=position+tonumber(size) - if n>=m then - return #str - elseif forward<#str then - vector[n]=name - n=n+1 - return forward - else - return #str - end - end - local setshapes=function(str,position,name,size) - local forward=position+tonumber(size) - local stream=sub(str,position+1,forward) - if n>m then - return #str - elseif forward<#str then - vector[n]=name - n=n+1 - chars [n]=decrypt(stream,4330,4) - return forward - else - return #str - end - end - local p_rd=spacing*(P("RD")+P("-|")) - local p_np=spacing*(P("NP")+P("|")) - local p_nd=spacing*(P("ND")+P("|")) - local p_filterroutines= - (1-subroutines)^0*subroutines*spaces*Cmt(cardinal,initialize)*(Cmt(cardinal*spaces*cardinal*p_rd,setroutine)*p_np+P(1))^1 - local p_filtershapes= - (1-charstrings)^0*charstrings*spaces*Cmt(cardinal,initialize)*(Cmt(name*spaces*cardinal*p_rd,setshapes)*p_nd+P(1))^1 - local p_filternames=Ct ( - (1-charstrings)^0*charstrings*spaces*Cmt(cardinal,initialize)*(Cmt(name*spaces*cardinal,setvector)+P(1))^1 - ) - local p_filterencoding=(1-encoding)^0*encoding*spaces*digits*spaces*array*(1-dup)^0*Cf( - Ct("")*Cg(spacing*dup*spaces*cardinal*spaces*name*spaces*put)^1 -,rawset) - local function loadpfbvector(filename,shapestoo) - local data=io.loaddata(resolvers.findfile(filename)) - if not data then - report_pfb("no data in %a",filename) - return - end - if not (find(data,"!PS%-AdobeFont%-") or find(data,"%%!FontType1")) then - report_pfb("no font in %a",filename) - return - end - local ascii,binary=match(data,"(.*)eexec%s+......(.*)") - if not binary then - report_pfb("no binary data in %a",filename) - return - end - binary=decrypt(binary,55665,4) - local names={} - local encoding=lpegmatch(p_filterencoding,ascii) - local glyphs={} - routines,vector,chars={},{},{} - if shapestoo then - lpegmatch(p_filterroutines,binary) - lpegmatch(p_filtershapes,binary) - local data={ - dictionaries={ - { - charstrings=chars, - charset=vector, - subroutines=routines, - } - }, - } - fonts.handlers.otf.readers.parsecharstrings(data,glyphs,true,true) - else - lpegmatch(p_filternames,binary) - end - names=vector - routines,vector,chars=nil,nil,nil - return names,encoding,glyphs - end - local pfb=handlers.pfb or {} - handlers.pfb=pfb - pfb.loadvector=loadpfbvector - get_indexes=function(data,pfbname) - local vector=loadpfbvector(pfbname) - if vector then - local characters=data.characters - if trace_loading then - report_afm("getting index data from %a",pfbname) - end - for index=1,#vector do - local name=vector[index] - local char=characters[name] - if char then - if trace_indexing then - report_afm("glyph %a has index %a",name,index) - end - char.index=index - end - end - end - end - get_shapes=function(pfbname) - local vector,encoding,glyphs=loadpfbvector(pfbname,true) - return glyphs - end -end -local spacer=patterns.spacer -local whitespace=patterns.whitespace -local lineend=patterns.newline -local spacing=spacer^0 -local number=spacing*S("+-")^-1*(R("09")+S("."))^1/tonumber -local name=spacing*C((1-whitespace)^1) -local words=spacing*((1-lineend)^1/strip) -local rest=(1-lineend)^0 -local fontdata=Carg(1) -local semicolon=spacing*P(";") -local plus=spacing*P("plus")*number -local minus=spacing*P("minus")*number -local function addkernpair(data,one,two,value) - local chr=data.characters[one] - if chr then - local kerns=chr.kerns - if kerns then - kerns[two]=tonumber(value) - else - chr.kerns={ [two]=tonumber(value) } - end - end -end -local p_kernpair=(fontdata*P("KPX")*name*name*number)/addkernpair -local chr=false -local ind=0 -local function start(data,version) - data.metadata.afmversion=version - ind=0 - chr={} -end -local function stop() - ind=0 - chr=false -end -local function setindex(i) - if i<0 then - ind=ind+1 - else - ind=i - end - chr={ - index=ind - } -end -local function setwidth(width) - chr.width=width -end -local function setname(data,name) - data.characters[name]=chr -end -local function setboundingbox(boundingbox) - chr.boundingbox=boundingbox -end -local function setligature(plus,becomes) - local ligatures=chr.ligatures - if ligatures then - ligatures[plus]=becomes - else - chr.ligatures={ [plus]=becomes } - end -end -local p_charmetric=(( - P("C")*number/setindex+P("WX")*number/setwidth+P("N")*fontdata*name/setname+P("B")*Ct((number)^4)/setboundingbox+P("L")*(name)^2/setligature - )*semicolon )^1 -local p_charmetrics=P("StartCharMetrics")*number*(p_charmetric+(1-P("EndCharMetrics")))^0*P("EndCharMetrics") -local p_kernpairs=P("StartKernPairs")*number*(p_kernpair+(1-P("EndKernPairs" )))^0*P("EndKernPairs" ) -local function set_1(data,key,a) data.metadata[lower(key)]=a end -local function set_2(data,key,a,b) data.metadata[lower(key)]={ a,b } end -local function set_3(data,key,a,b,c) data.metadata[lower(key)]={ a,b,c } end -local p_parameters=P(false)+fontdata*((P("FontName")+P("FullName")+P("FamilyName"))/lower)*words/function(data,key,value) - data.metadata[key]=value - end+fontdata*((P("Weight")+P("Version"))/lower)*name/function(data,key,value) - data.metadata[key]=value - end+fontdata*P("IsFixedPitch")*name/function(data,pitch) - data.metadata.monospaced=toboolean(pitch,true) - end+fontdata*P("FontBBox")*Ct(number^4)/function(data,boundingbox) - data.metadata.boundingbox=boundingbox - end+fontdata*((P("CharWidth")+P("CapHeight")+P("XHeight")+P("Descender")+P("Ascender")+P("ItalicAngle"))/lower)*number/function(data,key,value) - data.metadata[key]=value - end+P("Comment")*spacing*(P(false)+(fontdata*C("DESIGNSIZE")*number*rest)/set_1 -+(fontdata*C("TFM designsize")*number*rest)/set_1+(fontdata*C("DesignSize")*number*rest)/set_1+(fontdata*C("CODINGSCHEME")*words*rest)/set_1 -+(fontdata*C("CHECKSUM")*number*words*rest)/set_1 -+(fontdata*C("SPACE")*number*plus*minus*rest)/set_3 -+(fontdata*C("QUAD")*number*rest)/set_1 -+(fontdata*C("EXTRASPACE")*number*rest)/set_1 -+(fontdata*C("NUM")*number*number*number*rest)/set_3 -+(fontdata*C("DENOM")*number*number*rest)/set_2 -+(fontdata*C("SUP")*number*number*number*rest)/set_3 -+(fontdata*C("SUB")*number*number*rest)/set_2 -+(fontdata*C("SUPDROP")*number*rest)/set_1 -+(fontdata*C("SUBDROP")*number*rest)/set_1 -+(fontdata*C("DELIM")*number*number*rest)/set_2 -+(fontdata*C("AXISHEIGHT")*number*rest)/set_1 - ) -local fullparser=(P("StartFontMetrics")*fontdata*name/start )*(p_charmetrics+p_kernpairs+p_parameters+(1-P("EndFontMetrics")) )^0*(P("EndFontMetrics")/stop ) -local fullparser=(P("StartFontMetrics")*fontdata*name/start )*(p_charmetrics+p_kernpairs+p_parameters+(1-P("EndFontMetrics")) )^0*(P("EndFontMetrics")/stop ) -local infoparser=(P("StartFontMetrics")*fontdata*name/start )*(p_parameters+(1-P("EndFontMetrics")) )^0*(P("EndFontMetrics")/stop ) -local function read(filename,parser) - local afmblob=io.loaddata(filename) - if afmblob then - local data={ - resources={ - filename=resolvers.unresolve(filename), - version=afm.version, - creator="context mkiv", - }, - properties={ - hasitalics=false, - }, - goodies={}, - metadata={ - filename=file.removesuffix(file.basename(filename)) - }, - characters={ - }, - descriptions={ - }, - } - if trace_loading then - report_afm("parsing afm file %a",filename) - end - lpegmatch(parser,afmblob,1,data) - return data - else - if trace_loading then - report_afm("no valid afm file %a",filename) - end - return nil - end -end -function readers.loadfont(afmname,pfbname) - local data=read(resolvers.findfile(afmname),fullparser) - if data then - if not pfbname or pfbname=="" then - pfbname=file.replacesuffix(file.nameonly(afmname),"pfb") - pfbname=resolvers.findfile(pfbname) - end - if pfbname and pfbname~="" then - data.resources.filename=resolvers.unresolve(pfbname) - get_indexes(data,pfbname) - elseif trace_loading then - report_afm("no pfb file for %a",afmname) - end - return data - end -end -function readers.loadshapes(filename) - local fullname=resolvers.findfile(filename) or "" - if fullname=="" then - return { - filename="not found: "..filename, - glyphs={} - } - else - return { - filename=fullname, - format="opentype", - glyphs=get_shapes(fullname) or {}, - units=1000, - } - end -end -function readers.getinfo(filename) - local data=read(resolvers.findfile(filename),infoparser) - if data then - return data.metadata - end -end - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['font-one']={ - version=1.001, - comment="companion to font-ini.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local fonts,logs,trackers,containers,resolvers=fonts,logs,trackers,containers,resolvers -local next,type,tonumber,rawget=next,type,tonumber,rawget -local match,gmatch,lower,gsub,strip,find=string.match,string.gmatch,string.lower,string.gsub,string.strip,string.find -local char,byte,sub=string.char,string.byte,string.sub -local abs=math.abs -local bxor,rshift=bit32.bxor,bit32.rshift -local P,S,R,Cmt,C,Ct,Cs,Carg=lpeg.P,lpeg.S,lpeg.R,lpeg.Cmt,lpeg.C,lpeg.Ct,lpeg.Cs,lpeg.Carg -local lpegmatch,patterns=lpeg.match,lpeg.patterns -local trace_features=false trackers.register("afm.features",function(v) trace_features=v end) -local trace_indexing=false trackers.register("afm.indexing",function(v) trace_indexing=v end) -local trace_loading=false trackers.register("afm.loading",function(v) trace_loading=v end) -local trace_defining=false trackers.register("fonts.defining",function(v) trace_defining=v end) -local report_afm=logs.reporter("fonts","afm loading") -local setmetatableindex=table.setmetatableindex -local derivetable=table.derive -local findbinfile=resolvers.findbinfile -local definers=fonts.definers -local readers=fonts.readers -local constructors=fonts.constructors -local afm=constructors.handlers.afm -local pfb=constructors.handlers.pfb -local otf=fonts.handlers.otf -local otfreaders=otf.readers -local otfenhancers=otf.enhancers -local afmfeatures=constructors.features.afm -local registerafmfeature=afmfeatures.register -local afmenhancers=constructors.enhancers.afm -local registerafmenhancer=afmenhancers.register -afm.version=1.512 -afm.cache=containers.define("fonts","one",afm.version,true) -afm.autoprefixed=true -afm.helpdata={} -afm.syncspace=true -local overloads=fonts.mappings.overloads -local applyruntimefixes=fonts.treatments and fonts.treatments.applyfixes -function afm.load(filename) - filename=resolvers.findfile(filename,'afm') or "" - if filename~="" and not fonts.names.ignoredfile(filename) then - local name=file.removesuffix(file.basename(filename)) - local data=containers.read(afm.cache,name) - local attr=lfs.attributes(filename) - local size,time=attr.size or 0,attr.modification or 0 - local pfbfile=file.replacesuffix(name,"pfb") - local pfbname=resolvers.findfile(pfbfile,"pfb") or "" - if pfbname=="" then - pfbname=resolvers.findfile(file.basename(pfbfile),"pfb") or "" - end - local pfbsize,pfbtime=0,0 - if pfbname~="" then - local attr=lfs.attributes(pfbname) - pfbsize=attr.size or 0 - pfbtime=attr.modification or 0 - end - if not data or data.size~=size or data.time~=time or data.pfbsize~=pfbsize or data.pfbtime~=pfbtime then - report_afm("reading %a",filename) - data=afm.readers.loadfont(filename,pfbname) - if data then - afmenhancers.apply(data,filename) - fonts.mappings.addtounicode(data,filename) - otfreaders.pack(data) - data.size=size - data.time=time - data.pfbsize=pfbsize - data.pfbtime=pfbtime - report_afm("saving %a in cache",name) - data=containers.write(afm.cache,name,data) - data=containers.read(afm.cache,name) - end - end - if data then - otfreaders.unpack(data) - otfreaders.expand(data) - otfreaders.addunicodetable(data) - otfenhancers.apply(data,filename,data) - if applyruntimefixes then - applyruntimefixes(filename,data) - end - end - return data - end -end -local uparser=fonts.mappings.makenameparser() -local function enhance_unify_names(data,filename) - local unicodevector=fonts.encodings.agl.unicodes - local unicodes={} - local names={} - local private=constructors.privateoffset - local descriptions=data.descriptions - for name,blob in next,data.characters do - local code=unicodevector[name] - if not code then - code=lpegmatch(uparser,name) - if type(code)~="number" then - code=private - private=private+1 - report_afm("assigning private slot %U for unknown glyph name %a",code,name) - end - end - local index=blob.index - unicodes[name]=code - names[name]=index - blob.name=name - descriptions[code]={ - boundingbox=blob.boundingbox, - width=blob.width, - kerns=blob.kerns, - index=index, - name=name, - } - end - for unicode,description in next,descriptions do - local kerns=description.kerns - if kerns then - local krn={} - for name,kern in next,kerns do - local unicode=unicodes[name] - if unicode then - krn[unicode]=kern - else - end - end - description.kerns=krn - end - end - data.characters=nil - local resources=data.resources - local filename=resources.filename or file.removesuffix(file.basename(filename)) - resources.filename=resolvers.unresolve(filename) - resources.unicodes=unicodes - resources.marks={} - resources.private=private -end -local everywhere={ ["*"]={ ["*"]=true } } -local noflags={ false,false,false,false } -local function enhance_normalize_features(data) - local ligatures=setmetatableindex("table") - local kerns=setmetatableindex("table") - local extrakerns=setmetatableindex("table") - for u,c in next,data.descriptions do - local l=c.ligatures - local k=c.kerns - local e=c.extrakerns - if l then - ligatures[u]=l - for u,v in next,l do - l[u]={ ligature=v } - end - c.ligatures=nil - end - if k then - kerns[u]=k - for u,v in next,k do - k[u]=v - end - c.kerns=nil - end - if e then - extrakerns[u]=e - for u,v in next,e do - e[u]=v - end - c.extrakerns=nil - end - end - local features={ - gpos={}, - gsub={}, - } - local sequences={ - } - if next(ligatures) then - features.gsub.liga=everywhere - data.properties.hasligatures=true - sequences[#sequences+1]={ - features={ - liga=everywhere, - }, - flags=noflags, - name="s_s_0", - nofsteps=1, - order={ "liga" }, - type="gsub_ligature", - steps={ - { - coverage=ligatures, - }, - }, - } - end - if next(kerns) then - features.gpos.kern=everywhere - data.properties.haskerns=true - sequences[#sequences+1]={ - features={ - kern=everywhere, - }, - flags=noflags, - name="p_s_0", - nofsteps=1, - order={ "kern" }, - type="gpos_pair", - steps={ - { - format="kern", - coverage=kerns, - }, - }, - } - end - if next(extrakerns) then - features.gpos.extrakerns=everywhere - data.properties.haskerns=true - sequences[#sequences+1]={ - features={ - extrakerns=everywhere, - }, - flags=noflags, - name="p_s_1", - nofsteps=1, - order={ "extrakerns" }, - type="gpos_pair", - steps={ - { - format="kern", - coverage=extrakerns, - }, - }, - } - end - data.resources.features=features - data.resources.sequences=sequences -end -local function enhance_fix_names(data) - for k,v in next,data.descriptions do - local n=v.name - local r=overloads[n] - if r then - local name=r.name - if trace_indexing then - report_afm("renaming characters %a to %a",n,name) - end - v.name=name - v.unicode=r.unicode - end - end -end -local addthem=function(rawdata,ligatures) - if ligatures then - local descriptions=rawdata.descriptions - local resources=rawdata.resources - local unicodes=resources.unicodes - for ligname,ligdata in next,ligatures do - local one=descriptions[unicodes[ligname]] - if one then - for _,pair in next,ligdata do - local two,three=unicodes[pair[1]],unicodes[pair[2]] - if two and three then - local ol=one.ligatures - if ol then - if not ol[two] then - ol[two]=three - end - else - one.ligatures={ [two]=three } - end - end - end - end - end - end -end -local function enhance_add_ligatures(rawdata) - addthem(rawdata,afm.helpdata.ligatures) -end -local function enhance_add_extra_kerns(rawdata) - local descriptions=rawdata.descriptions - local resources=rawdata.resources - local unicodes=resources.unicodes - local function do_it_left(what) - if what then - for unicode,description in next,descriptions do - local kerns=description.kerns - if kerns then - local extrakerns - for complex,simple in next,what do - complex=unicodes[complex] - simple=unicodes[simple] - if complex and simple then - local ks=kerns[simple] - if ks and not kerns[complex] then - if extrakerns then - extrakerns[complex]=ks - else - extrakerns={ [complex]=ks } - end - end - end - end - if extrakerns then - description.extrakerns=extrakerns - end - end - end - end - end - local function do_it_copy(what) - if what then - for complex,simple in next,what do - complex=unicodes[complex] - simple=unicodes[simple] - if complex and simple then - local complexdescription=descriptions[complex] - if complexdescription then - local simpledescription=descriptions[complex] - if simpledescription then - local extrakerns - local kerns=simpledescription.kerns - if kerns then - for unicode,kern in next,kerns do - if extrakerns then - extrakerns[unicode]=kern - else - extrakerns={ [unicode]=kern } - end - end - end - local extrakerns=simpledescription.extrakerns - if extrakerns then - for unicode,kern in next,extrakerns do - if extrakerns then - extrakerns[unicode]=kern - else - extrakerns={ [unicode]=kern } - end - end - end - if extrakerns then - complexdescription.extrakerns=extrakerns - end - end - end - end - end - end - end - do_it_left(afm.helpdata.leftkerned) - do_it_left(afm.helpdata.bothkerned) - do_it_copy(afm.helpdata.bothkerned) - do_it_copy(afm.helpdata.rightkerned) -end -local function adddimensions(data) - if data then - for unicode,description in next,data.descriptions do - local bb=description.boundingbox - if bb then - local ht,dp=bb[4],-bb[2] - if ht==0 or ht<0 then - else - description.height=ht - end - if dp==0 or dp<0 then - else - description.depth=dp - end - end - end - end -end -local function copytotfm(data) - if data and data.descriptions then - local metadata=data.metadata - local resources=data.resources - local properties=derivetable(data.properties) - local descriptions=derivetable(data.descriptions) - local goodies=derivetable(data.goodies) - local characters={} - local parameters={} - local unicodes=resources.unicodes - for unicode,description in next,data.descriptions do - characters[unicode]={} - end - local filename=constructors.checkedfilename(resources) - local fontname=metadata.fontname or metadata.fullname - local fullname=metadata.fullname or metadata.fontname - local endash=0x0020 - local emdash=0x2014 - local spacer="space" - local spaceunits=500 - local monospaced=metadata.monospaced - local charwidth=metadata.charwidth - local italicangle=metadata.italicangle - local charxheight=metadata.xheight and metadata.xheight>0 and metadata.xheight - properties.monospaced=monospaced - parameters.italicangle=italicangle - parameters.charwidth=charwidth - parameters.charxheight=charxheight - if properties.monospaced then - if descriptions[endash] then - spaceunits,spacer=descriptions[endash].width,"space" - end - if not spaceunits and descriptions[emdash] then - spaceunits,spacer=descriptions[emdash].width,"emdash" - end - if not spaceunits and charwidth then - spaceunits,spacer=charwidth,"charwidth" - end - else - if descriptions[endash] then - spaceunits,spacer=descriptions[endash].width,"space" - end - if not spaceunits and charwidth then - spaceunits,spacer=charwidth,"charwidth" - end - end - spaceunits=tonumber(spaceunits) - if spaceunits<200 then - end - parameters.slant=0 - parameters.space=spaceunits - parameters.space_stretch=500 - parameters.space_shrink=333 - parameters.x_height=400 - parameters.quad=1000 - if italicangle and italicangle~=0 then - parameters.italicangle=italicangle - parameters.italicfactor=math.cos(math.rad(90+italicangle)) - parameters.slant=- math.tan(italicangle*math.pi/180) - end - if monospaced then - parameters.space_stretch=0 - parameters.space_shrink=0 - elseif afm.syncspace then - parameters.space_stretch=spaceunits/2 - parameters.space_shrink=spaceunits/3 - end - parameters.extra_space=parameters.space_shrink - if charxheight then - parameters.x_height=charxheight - else - local x=0x0078 - if x then - local x=descriptions[x] - if x then - parameters.x_height=x.height - end - end - end - if metadata.sup then - local dummy={ 0,0,0 } - parameters[ 1]=metadata.designsize or 0 - parameters[ 2]=metadata.checksum or 0 - parameters[ 3], - parameters[ 4], - parameters[ 5]=unpack(metadata.space or dummy) - parameters[ 6]=metadata.quad or 0 - parameters[ 7]=metadata.extraspace or 0 - parameters[ 8], - parameters[ 9], - parameters[10]=unpack(metadata.num or dummy) - parameters[11], - parameters[12]=unpack(metadata.denom or dummy) - parameters[13], - parameters[14], - parameters[15]=unpack(metadata.sup or dummy) - parameters[16], - parameters[17]=unpack(metadata.sub or dummy) - parameters[18]=metadata.supdrop or 0 - parameters[19]=metadata.subdrop or 0 - parameters[20], - parameters[21]=unpack(metadata.delim or dummy) - parameters[22]=metadata.axisheight or 0 - end - parameters.designsize=(metadata.designsize or 10)*65536 - parameters.ascender=abs(metadata.ascender or 0) - parameters.descender=abs(metadata.descender or 0) - parameters.units=1000 - properties.spacer=spacer - properties.encodingbytes=2 - properties.format=fonts.formats[filename] or "type1" - properties.filename=filename - properties.fontname=fontname - properties.fullname=fullname - properties.psname=fullname - properties.name=filename or fullname or fontname - if next(characters) then - return { - characters=characters, - descriptions=descriptions, - parameters=parameters, - resources=resources, - properties=properties, - goodies=goodies, - } - end - end - return nil -end -function afm.setfeatures(tfmdata,features) - local okay=constructors.initializefeatures("afm",tfmdata,features,trace_features,report_afm) - if okay then - return constructors.collectprocessors("afm",tfmdata,features,trace_features,report_afm) - else - return {} - end -end -local function addtables(data) - local resources=data.resources - local lookuptags=resources.lookuptags - local unicodes=resources.unicodes - if not lookuptags then - lookuptags={} - resources.lookuptags=lookuptags - end - setmetatableindex(lookuptags,function(t,k) - local v=type(k)=="number" and ("lookup "..k) or k - t[k]=v - return v - end) - if not unicodes then - unicodes={} - resources.unicodes=unicodes - setmetatableindex(unicodes,function(t,k) - setmetatableindex(unicodes,nil) - for u,d in next,data.descriptions do - local n=d.name - if n then - t[n]=u - end - end - return rawget(t,k) - end) - end - constructors.addcoreunicodes(unicodes) -end -local function afmtotfm(specification) - local afmname=specification.filename or specification.name - if specification.forced=="afm" or specification.format=="afm" then - if trace_loading then - report_afm("forcing afm format for %a",afmname) - end - else - local tfmname=findbinfile(afmname,"ofm") or "" - if tfmname~="" then - if trace_loading then - report_afm("fallback from afm to tfm for %a",afmname) - end - return - end - end - if afmname~="" then - local features=constructors.checkedfeatures("afm",specification.features.normal) - specification.features.normal=features - constructors.hashinstance(specification,true) - specification=definers.resolve(specification) - local cache_id=specification.hash - local tfmdata=containers.read(constructors.cache,cache_id) - if not tfmdata then - local rawdata=afm.load(afmname) - if rawdata and next(rawdata) then - addtables(rawdata) - adddimensions(rawdata) - tfmdata=copytotfm(rawdata) - if tfmdata and next(tfmdata) then - local shared=tfmdata.shared - if not shared then - shared={} - tfmdata.shared=shared - end - shared.rawdata=rawdata - shared.dynamics={} - tfmdata.changed={} - shared.features=features - shared.processes=afm.setfeatures(tfmdata,features) - end - elseif trace_loading then - report_afm("no (valid) afm file found with name %a",afmname) - end - tfmdata=containers.write(constructors.cache,cache_id,tfmdata) - end - return tfmdata - end -end -local function read_from_afm(specification) - local tfmdata=afmtotfm(specification) - if tfmdata then - tfmdata.properties.name=specification.name - tfmdata=constructors.scale(tfmdata,specification) - local allfeatures=tfmdata.shared.features or specification.features.normal - constructors.applymanipulators("afm",tfmdata,allfeatures,trace_features,report_afm) - fonts.loggers.register(tfmdata,'afm',specification) - end - return tfmdata -end -registerafmfeature { - name="mode", - description="mode", - initializers={ - base=otf.modeinitializer, - node=otf.modeinitializer, - } -} -registerafmfeature { - name="features", - description="features", - default=true, - initializers={ - node=otf.nodemodeinitializer, - base=otf.basemodeinitializer, - }, - processors={ - node=otf.featuresprocessor, - } -} -fonts.formats.afm="type1" -fonts.formats.pfb="type1" -local function check_afm(specification,fullname) - local foundname=findbinfile(fullname,'afm') or "" - if foundname=="" then - foundname=fonts.names.getfilename(fullname,"afm") or "" - end - if foundname=="" and afm.autoprefixed then - local encoding,shortname=match(fullname,"^(.-)%-(.*)$") - if encoding and shortname and fonts.encodings.known[encoding] then - shortname=findbinfile(shortname,'afm') or "" - if shortname~="" then - foundname=shortname - if trace_defining then - report_afm("stripping encoding prefix from filename %a",afmname) - end - end - end - end - if foundname~="" then - specification.filename=foundname - specification.format="afm" - return read_from_afm(specification) - end -end -function readers.afm(specification,method) - local fullname=specification.filename or "" - local tfmdata=nil - if fullname=="" then - local forced=specification.forced or "" - if forced~="" then - tfmdata=check_afm(specification,specification.name.."."..forced) - end - if not tfmdata then - local check_tfm=readers.check_tfm - method=(check_tfm and (method or definers.method or "afm or tfm")) or "afm" - if method=="tfm" then - tfmdata=check_tfm(specification,specification.name) - elseif method=="afm" then - tfmdata=check_afm(specification,specification.name) - elseif method=="tfm or afm" then - tfmdata=check_tfm(specification,specification.name) or check_afm(specification,specification.name) - else - tfmdata=check_afm(specification,specification.name) or check_tfm(specification,specification.name) - end - end - else - tfmdata=check_afm(specification,fullname) - end - return tfmdata -end -function readers.pfb(specification,method) - local original=specification.specification - if trace_defining then - report_afm("using afm reader for %a",original) - end - specification.forced="afm" - local function swap(name) - local value=specification[swap] - if value then - specification[swap]=gsub("%.pfb",".afm",1) - end - end - swap("filename") - swap("fullname") - swap("forcedname") - swap("specification") - return readers.afm(specification,method) -end -registerafmenhancer("unify names",enhance_unify_names) -registerafmenhancer("add ligatures",enhance_add_ligatures) -registerafmenhancer("add extra kerns",enhance_add_extra_kerns) -registerafmenhancer("normalize features",enhance_normalize_features) -registerafmenhancer("check extra features",otfenhancers.enhance) -registerafmenhancer("fix names",enhance_fix_names) - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['font-afk']={ - version=1.001, - comment="companion to font-afm.lua", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files", - dataonly=true, -} -local allocate=utilities.storage.allocate -fonts.handlers.afm.helpdata={ - ligatures=allocate { - ['f']={ - { 'f','ff' }, - { 'i','fi' }, - { 'l','fl' }, - }, - ['ff']={ - { 'i','ffi' } - }, - ['fi']={ - { 'i','fii' } - }, - ['fl']={ - { 'i','fli' } - }, - ['s']={ - { 't','st' } - }, - ['i']={ - { 'j','ij' } - }, - }, - texligatures=allocate { - ['quoteleft']={ - { 'quoteleft','quotedblleft' } - }, - ['quoteright']={ - { 'quoteright','quotedblright' } - }, - ['hyphen']={ - { 'hyphen','endash' } - }, - ['endash']={ - { 'hyphen','emdash' } - } - }, - leftkerned=allocate { - AEligature="A",aeligature="a", - OEligature="O",oeligature="o", - IJligature="I",ijligature="i", - AE="A",ae="a", - OE="O",oe="o", - IJ="I",ij="i", - Ssharp="S",ssharp="s", - }, - rightkerned=allocate { - AEligature="E",aeligature="e", - OEligature="E",oeligature="e", - IJligature="J",ijligature="j", - AE="E",ae="e", - OE="E",oe="e", - IJ="J",ij="j", - Ssharp="S",ssharp="s", - }, - bothkerned=allocate { - Acircumflex="A",acircumflex="a", - Ccircumflex="C",ccircumflex="c", - Ecircumflex="E",ecircumflex="e", - Gcircumflex="G",gcircumflex="g", - Hcircumflex="H",hcircumflex="h", - Icircumflex="I",icircumflex="i", - Jcircumflex="J",jcircumflex="j", - Ocircumflex="O",ocircumflex="o", - Scircumflex="S",scircumflex="s", - Ucircumflex="U",ucircumflex="u", - Wcircumflex="W",wcircumflex="w", - Ycircumflex="Y",ycircumflex="y", - Agrave="A",agrave="a", - Egrave="E",egrave="e", - Igrave="I",igrave="i", - Ograve="O",ograve="o", - Ugrave="U",ugrave="u", - Ygrave="Y",ygrave="y", - Atilde="A",atilde="a", - Itilde="I",itilde="i", - Otilde="O",otilde="o", - Utilde="U",utilde="u", - Ntilde="N",ntilde="n", - Adiaeresis="A",adiaeresis="a",Adieresis="A",adieresis="a", - Ediaeresis="E",ediaeresis="e",Edieresis="E",edieresis="e", - Idiaeresis="I",idiaeresis="i",Idieresis="I",idieresis="i", - Odiaeresis="O",odiaeresis="o",Odieresis="O",odieresis="o", - Udiaeresis="U",udiaeresis="u",Udieresis="U",udieresis="u", - Ydiaeresis="Y",ydiaeresis="y",Ydieresis="Y",ydieresis="y", - Aacute="A",aacute="a", - Cacute="C",cacute="c", - Eacute="E",eacute="e", - Iacute="I",iacute="i", - Lacute="L",lacute="l", - Nacute="N",nacute="n", - Oacute="O",oacute="o", - Racute="R",racute="r", - Sacute="S",sacute="s", - Uacute="U",uacute="u", - Yacute="Y",yacute="y", - Zacute="Z",zacute="z", - Dstroke="D",dstroke="d", - Hstroke="H",hstroke="h", - Tstroke="T",tstroke="t", - Cdotaccent="C",cdotaccent="c", - Edotaccent="E",edotaccent="e", - Gdotaccent="G",gdotaccent="g", - Idotaccent="I",idotaccent="i", - Zdotaccent="Z",zdotaccent="z", - Amacron="A",amacron="a", - Emacron="E",emacron="e", - Imacron="I",imacron="i", - Omacron="O",omacron="o", - Umacron="U",umacron="u", - Ccedilla="C",ccedilla="c", - Kcedilla="K",kcedilla="k", - Lcedilla="L",lcedilla="l", - Ncedilla="N",ncedilla="n", - Rcedilla="R",rcedilla="r", - Scedilla="S",scedilla="s", - Tcedilla="T",tcedilla="t", - Ohungarumlaut="O",ohungarumlaut="o", - Uhungarumlaut="U",uhungarumlaut="u", - Aogonek="A",aogonek="a", - Eogonek="E",eogonek="e", - Iogonek="I",iogonek="i", - Uogonek="U",uogonek="u", - Aring="A",aring="a", - Uring="U",uring="u", - Abreve="A",abreve="a", - Ebreve="E",ebreve="e", - Gbreve="G",gbreve="g", - Ibreve="I",ibreve="i", - Obreve="O",obreve="o", - Ubreve="U",ubreve="u", - Ccaron="C",ccaron="c", - Dcaron="D",dcaron="d", - Ecaron="E",ecaron="e", - Lcaron="L",lcaron="l", - Ncaron="N",ncaron="n", - Rcaron="R",rcaron="r", - Scaron="S",scaron="s", - Tcaron="T",tcaron="t", - Zcaron="Z",zcaron="z", - dotlessI="I",dotlessi="i", - dotlessJ="J",dotlessj="j", - AEligature="AE",aeligature="ae",AE="AE",ae="ae", - OEligature="OE",oeligature="oe",OE="OE",oe="oe", - IJligature="IJ",ijligature="ij",IJ="IJ",ij="ij", - Lstroke="L",lstroke="l",Lslash="L",lslash="l", - Ostroke="O",ostroke="o",Oslash="O",oslash="o", - Ssharp="SS",ssharp="ss", - Aumlaut="A",aumlaut="a", - Eumlaut="E",eumlaut="e", - Iumlaut="I",iumlaut="i", - Oumlaut="O",oumlaut="o", - Uumlaut="U",uumlaut="u", - } -} - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['font-tfm']={ - version=1.001, - comment="companion to font-ini.mkiv", - 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 match,format=string.match,string.format -local concat,sortedhash=table.concat,table.sortedhash -local trace_defining=false trackers.register("fonts.defining",function(v) trace_defining=v end) -local trace_features=false trackers.register("tfm.features",function(v) trace_features=v end) -local report_defining=logs.reporter("fonts","defining") -local report_tfm=logs.reporter("fonts","tfm loading") -local findbinfile=resolvers.findbinfile -local setmetatableindex=table.setmetatableindex -local fonts=fonts -local handlers=fonts.handlers -local readers=fonts.readers -local constructors=fonts.constructors -local encodings=fonts.encodings -local tfm=constructors.handlers.tfm -tfm.version=1.000 -tfm.maxnestingdepth=5 -tfm.maxnestingsize=65536*1024 -local otf=fonts.handlers.otf -local otfenhancers=otf.enhancers -local tfmfeatures=constructors.features.tfm -local registertfmfeature=tfmfeatures.register -local tfmenhancers=constructors.enhancers.tfm -local registertfmenhancer=tfmenhancers.register -constructors.resolvevirtualtoo=false -fonts.formats.tfm="type1" -fonts.formats.ofm="type1" -function tfm.setfeatures(tfmdata,features) - local okay=constructors.initializefeatures("tfm",tfmdata,features,trace_features,report_tfm) - if okay then - return constructors.collectprocessors("tfm",tfmdata,features,trace_features,report_tfm) - else - return {} - end -end -local depth={} -local function read_from_tfm(specification) - local filename=specification.filename - local size=specification.size - depth[filename]=(depth[filename] or 0)+1 - if trace_defining then - report_defining("loading tfm file %a at size %s",filename,size) - end - local tfmdata=font.read_tfm(filename,size) - if tfmdata then - local features=specification.features and specification.features.normal or {} - local features=constructors.checkedfeatures("tfm",features) - specification.features.normal=features - local newtfmdata=(depth[filename]==1) and tfm.reencode(tfmdata,specification) - if newtfmdata then - tfmdata=newtfmdata - end - local resources=tfmdata.resources or {} - local properties=tfmdata.properties or {} - local parameters=tfmdata.parameters or {} - local shared=tfmdata.shared or {} - shared.features=features - shared.resources=resources - properties.name=tfmdata.name - properties.fontname=tfmdata.fontname - properties.psname=tfmdata.psname - properties.fullname=tfmdata.fullname - properties.filename=specification.filename - properties.format=fonts.formats.tfm - tfmdata.properties=properties - tfmdata.resources=resources - tfmdata.parameters=parameters - tfmdata.shared=shared - shared.rawdata={ resources=resources } - shared.features=features - if newtfmdata then - if not resources.marks then - resources.marks={} - end - if not resources.sequences then - resources.sequences={} - end - if not resources.features then - resources.features={ - gsub={}, - gpos={}, - } - end - if not tfmdata.changed then - tfmdata.changed={} - end - if not tfmdata.descriptions then - tfmdata.descriptions=tfmdata.characters - end - otf.readers.addunicodetable(tfmdata) - tfmenhancers.apply(tfmdata,filename) - constructors.applymanipulators("tfm",tfmdata,features,trace_features,report_tfm) - otf.readers.unifymissing(tfmdata) - fonts.mappings.addtounicode(tfmdata,filename) - tfmdata.tounicode=1 - local tounicode=fonts.mappings.tounicode - for unicode,v in next,tfmdata.characters do - local u=v.unicode - if u then - v.tounicode=tounicode(u) - end - end - if tfmdata.usedbitmap then - tfm.addtounicode(tfmdata) - end - end - shared.processes=next(features) and tfm.setfeatures(tfmdata,features) or nil - parameters.factor=1 - parameters.size=size - parameters.slant=parameters.slant or parameters[1] or 0 - parameters.space=parameters.space or parameters[2] or 0 - parameters.space_stretch=parameters.space_stretch or parameters[3] or 0 - parameters.space_shrink=parameters.space_shrink or parameters[4] or 0 - parameters.x_height=parameters.x_height or parameters[5] or 0 - parameters.quad=parameters.quad or parameters[6] or 0 - parameters.extra_space=parameters.extra_space or parameters[7] or 0 - constructors.enhanceparameters(parameters) - if newtfmdata then - elseif constructors.resolvevirtualtoo then - fonts.loggers.register(tfmdata,file.suffix(filename),specification) - local vfname=findbinfile(specification.name,'ovf') - if vfname and vfname~="" then - local vfdata=font.read_vf(vfname,size) - if vfdata then - local chars=tfmdata.characters - for k,v in next,vfdata.characters do - chars[k].commands=v.commands - end - properties.virtualized=true - tfmdata.fonts=vfdata.fonts - tfmdata.type="virtual" - local fontlist=vfdata.fonts - local name=file.nameonly(filename) - for i=1,#fontlist do - local n=fontlist[i].name - local s=fontlist[i].size - local d=depth[filename] - s=constructors.scaled(s,vfdata.designsize) - if d>tfm.maxnestingdepth then - report_defining("too deeply nested virtual font %a with size %a, max nesting depth %s",n,s,tfm.maxnestingdepth) - fontlist[i]={ id=0 } - elseif (d>1) and (s>tfm.maxnestingsize) then - report_defining("virtual font %a exceeds size %s",n,s) - fontlist[i]={ id=0 } - else - local t,id=fonts.constructors.readanddefine(n,s) - fontlist[i]={ id=id } - end - end - end - end - end - properties.haskerns=true - properties.hasligatures=true - resources.unicodes={} - resources.lookuptags={} - depth[filename]=depth[filename]-1 - return tfmdata - else - depth[filename]=depth[filename]-1 - end -end -local function check_tfm(specification,fullname) - local foundname=findbinfile(fullname,'tfm') or "" - if foundname=="" then - foundname=findbinfile(fullname,'ofm') or "" - end - if foundname=="" then - foundname=fonts.names.getfilename(fullname,"tfm") or "" - end - if foundname~="" then - specification.filename=foundname - specification.format="ofm" - return read_from_tfm(specification) - elseif trace_defining then - report_defining("loading tfm with name %a fails",specification.name) - end -end -readers.check_tfm=check_tfm -function readers.tfm(specification) - local fullname=specification.filename or "" - if fullname=="" then - local forced=specification.forced or "" - if forced~="" then - fullname=specification.name.."."..forced - else - fullname=specification.name - end - end - return check_tfm(specification,fullname) -end -readers.ofm=readers.tfm -do - local outfiles={} - local tfmcache=table.setmetatableindex(function(t,tfmdata) - local id=font.define(tfmdata) - t[tfmdata]=id - return id - end) - local encdone=table.setmetatableindex("table") - function tfm.reencode(tfmdata,specification) - local features=specification.features - if not features then - return - end - local features=features.normal - if not features then - return - end - local tfmfile=file.basename(tfmdata.name) - local encfile=features.reencode - local pfbfile=features.pfbfile - local bitmap=features.bitmap - if not encfile then - return - end - local pfbfile=outfiles[tfmfile] - if pfbfile==nil then - if bitmap then - pfbfile=false - elseif type(pfbfile)~="string" then - pfbfile=tfmfile - end - if type(pfbfile)=="string" then - pfbfile=file.addsuffix(pfbfile,"pfb") - report_tfm("using type1 shapes from %a for %a",pfbfile,tfmfile) - else - report_tfm("using bitmap shapes for %a",tfmfile) - pfbfile=false - end - outfiles[tfmfile]=pfbfile - end - local encoding=false - local vector=false - if type(pfbfile)=="string" then - local pfb=fonts.constructors.handlers.pfb - if pfb and pfb.loadvector then - local v,e=pfb.loadvector(pfbfile) - if v then - vector=v - end - if e then - encoding=e - end - end - end - if type(encfile)=="string" and encfile~="auto" then - encoding=fonts.encodings.load(file.addsuffix(encfile,"enc")) - if encoding then - encoding=encoding.vector - end - end - if not encoding then - report_tfm("bad encoding for %a, quitting",tfmfile) - return - end - local unicoding=fonts.encodings.agl and fonts.encodings.agl.unicodes - local virtualid=tfmcache[tfmdata] - local tfmdata=table.copy(tfmdata) - local characters={} - local originals=tfmdata.characters - local indices={} - local parentfont={ "font",1 } - local private=fonts.constructors.privateoffset - local reported=encdone[tfmfile][encfile] - local backmap=vector and table.swapped(vector) - local done={} - for index,name in sortedhash(encoding) do - local unicode=unicoding[name] - local original=originals[index] - if original then - if unicode then - original.unicode=unicode - else - unicode=private - private=private+1 - if not reported then - report_tfm("glyph %a in font %a with encoding %a gets unicode %U",name,tfmfile,encfile,unicode) - end - end - characters[unicode]=original - indices[index]=unicode - original.name=name - if backmap then - original.index=backmap[name] - else - original.commands={ parentfont,{ "char",index } } - original.oindex=index - end - done[name]=true - elseif not done[name] then - report_tfm("bad index %a in font %a with name %a",index,tfmfile,name) - end - end - encdone[tfmfile][encfile]=true - for k,v in next,characters do - local kerns=v.kerns - if kerns then - local t={} - for k,v in next,kerns do - local i=indices[k] - if i then - t[i]=v - end - end - v.kerns=next(t) and t or nil - end - local ligatures=v.ligatures - if ligatures then - local t={} - for k,v in next,ligatures do - local i=indices[k] - if i then - t[i]=v - v.char=indices[v.char] - end - end - v.ligatures=next(t) and t or nil - end - end - tfmdata.fonts={ { id=virtualid } } - tfmdata.characters=characters - tfmdata.fullname=tfmdata.fullname or tfmdata.name - tfmdata.psname=file.nameonly(pfbfile or tfmdata.name) - tfmdata.filename=pfbfile - tfmdata.encodingbytes=2 - tfmdata.format="type1" - tfmdata.tounicode=1 - tfmdata.embedding="subset" - tfmdata.usedbitmap=bitmap and virtualid - return tfmdata - end -end -do - local template=[[ -/CIDInit /ProcSet findresource begin - 12 dict begin - begincmap - /CIDSystemInfo << /Registry (TeX) /Ordering (bitmap-%s) /Supplement 0 >> def - /CMapName /TeX-bitmap-%s def - /CMapType 2 def - 1 begincodespacerange - <00> <FF> - endcodespacerange - %s beginbfchar -%s - endbfchar - endcmap -CMapName currentdict /CMap defineresource pop end -end -end -]] - local flushstreamobject=lpdf and lpdf.flushstreamobject - local setfontattributes=pdf.setfontattributes - if not flushstreamobject then - flushstreamobject=function(data) - return pdf.obj { - immediate=true, - type="stream", - string=data, - } - end - end - if not setfontattributes then - setfontattributes=function(id,data) - print(format("your luatex is too old so no tounicode bitmap font%i",id)) - end - end - function tfm.addtounicode(tfmdata) - local id=tfmdata.usedbitmap - local map={} - local char={} - for k,v in next,tfmdata.characters do - local index=v.oindex - local tounicode=v.tounicode - if index and tounicode then - map[index]=tounicode - end - end - for k,v in sortedhash(map) do - char[#char+1]=format("<%02X> <%s>",k,v) - end - char=concat(char,"\n") - local stream=format(template,id,id,#char,char) - local reference=flushstreamobject(stream,nil,true) - setfontattributes(id,format("/ToUnicode %i 0 R",reference)) - end -end -do - local everywhere={ ["*"]={ ["*"]=true } } - local noflags={ false,false,false,false } - local function enhance_normalize_features(data) - local ligatures=setmetatableindex("table") - local kerns=setmetatableindex("table") - local characters=data.characters - for u,c in next,characters do - local l=c.ligatures - local k=c.kerns - if l then - ligatures[u]=l - for u,v in next,l do - l[u]={ ligature=v.char } - end - c.ligatures=nil - end - if k then - kerns[u]=k - for u,v in next,k do - k[u]=v - end - c.kerns=nil - end - end - for u,l in next,ligatures do - for k,v in next,l do - local vl=v.ligature - local dl=ligatures[vl] - if dl then - for kk,vv in next,dl do - v[kk]=vv - end - end - end - end - local features={ - gpos={}, - gsub={}, - } - local sequences={ - } - if next(ligatures) then - features.gsub.liga=everywhere - data.properties.hasligatures=true - sequences[#sequences+1]={ - features={ - liga=everywhere, - }, - flags=noflags, - name="s_s_0", - nofsteps=1, - order={ "liga" }, - type="gsub_ligature", - steps={ - { - coverage=ligatures, - }, - }, - } - end - if next(kerns) then - features.gpos.kern=everywhere - data.properties.haskerns=true - sequences[#sequences+1]={ - features={ - kern=everywhere, - }, - flags=noflags, - name="p_s_0", - nofsteps=1, - order={ "kern" }, - type="gpos_pair", - steps={ - { - format="kern", - coverage=kerns, - }, - }, - } - end - data.resources.features=features - data.resources.sequences=sequences - data.shared.resources=data.shared.resources or resources - end - registertfmenhancer("normalize features",enhance_normalize_features) - registertfmenhancer("check extra features",otfenhancers.enhance) -end -registertfmfeature { - name="mode", - description="mode", - initializers={ - base=otf.modeinitializer, - node=otf.modeinitializer, - } -} -registertfmfeature { - name="features", - description="features", - default=true, - initializers={ - base=otf.basemodeinitializer, - node=otf.nodemodeinitializer, - }, - processors={ - node=otf.featuresprocessor, - } -} - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['font-lua']={ - version=1.001, - comment="companion to font-ini.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local trace_defining=false trackers.register("fonts.defining",function(v) trace_defining=v end) -local report_lua=logs.reporter("fonts","lua loading") -local fonts=fonts -local readers=fonts.readers -fonts.formats.lua="lua" -local function check_lua(specification,fullname) - local fullname=resolvers.findfile(fullname) or "" - if fullname~="" then - local loader=loadfile(fullname) - loader=loader and loader() - return loader and loader(specification) - end -end -readers.check_lua=check_lua -function readers.lua(specification) - local original=specification.specification - if trace_defining then - report_lua("using lua reader for %a",original) - end - local fullname=specification.filename or "" - if fullname=="" then - local forced=specification.forced or "" - if forced~="" then - fullname=specification.name.."."..forced - else - fullname=specification.name - end - end - return check_lua(specification,fullname) -end - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['font-def']={ - version=1.001, - comment="companion to font-ini.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local lower,gsub=string.lower,string.gsub -local tostring,next=tostring,next -local lpegmatch=lpeg.match -local suffixonly,removesuffix=file.suffix,file.removesuffix -local formatters=string.formatters -local allocate=utilities.storage.allocate -local trace_defining=false trackers .register("fonts.defining",function(v) trace_defining=v end) -local directive_embedall=false directives.register("fonts.embedall",function(v) directive_embedall=v end) -trackers.register("fonts.loading","fonts.defining","otf.loading","afm.loading","tfm.loading") -trackers.register("fonts.all","fonts.*","otf.*","afm.*","tfm.*") -local report_defining=logs.reporter("fonts","defining") -local fonts=fonts -local fontdata=fonts.hashes.identifiers -local readers=fonts.readers -local definers=fonts.definers -local specifiers=fonts.specifiers -local constructors=fonts.constructors -local fontgoodies=fonts.goodies -readers.sequence=allocate { 'otf','ttf','afm','tfm','lua' } -local variants=allocate() -specifiers.variants=variants -definers.methods=definers.methods or {} -local internalized=allocate() -local lastdefined=nil -local loadedfonts=constructors.loadedfonts -local designsizes=constructors.designsizes -local resolvefile=fontgoodies and fontgoodies.filenames and fontgoodies.filenames.resolve or function(s) return s end -local splitter,splitspecifiers=nil,"" -local P,C,S,Cc=lpeg.P,lpeg.C,lpeg.S,lpeg.Cc -local left=P("(") -local right=P(")") -local colon=P(":") -local space=P(" ") -definers.defaultlookup="file" -local prefixpattern=P(false) -local function addspecifier(symbol) - splitspecifiers=splitspecifiers..symbol - local method=S(splitspecifiers) - local lookup=C(prefixpattern)*colon - local sub=left*C(P(1-left-right-method)^1)*right - local specification=C(method)*C(P(1)^1) - local name=C((1-sub-specification)^1) - splitter=P((lookup+Cc(""))*name*(sub+Cc(""))*(specification+Cc(""))) -end -local function addlookup(str,default) - prefixpattern=prefixpattern+P(str) -end -definers.addlookup=addlookup -addlookup("file") -addlookup("name") -addlookup("spec") -local function getspecification(str) - return lpegmatch(splitter,str or "") -end -definers.getspecification=getspecification -function definers.registersplit(symbol,action,verbosename) - addspecifier(symbol) - variants[symbol]=action - if verbosename then - variants[verbosename]=action - end -end -local function makespecification(specification,lookup,name,sub,method,detail,size) - size=size or 655360 - if not lookup or lookup=="" then - lookup=definers.defaultlookup - end - if trace_defining then - report_defining("specification %a, lookup %a, name %a, sub %a, method %a, detail %a", - specification,lookup,name,sub,method,detail) - end - local t={ - lookup=lookup, - specification=specification, - size=size, - name=name, - sub=sub, - method=method, - detail=detail, - resolved="", - forced="", - features={}, - } - return t -end -definers.makespecification=makespecification -function definers.analyze(specification,size) - local lookup,name,sub,method,detail=getspecification(specification or "") - return makespecification(specification,lookup,name,sub,method,detail,size) -end -definers.resolvers=definers.resolvers or {} -local resolvers=definers.resolvers -function resolvers.file(specification) - local name=resolvefile(specification.name) - local suffix=lower(suffixonly(name)) - if fonts.formats[suffix] then - specification.forced=suffix - specification.forcedname=name - specification.name=removesuffix(name) - else - specification.name=name - end -end -function resolvers.name(specification) - local resolve=fonts.names.resolve - if resolve then - local resolved,sub,subindex=resolve(specification.name,specification.sub,specification) - if resolved then - specification.resolved=resolved - specification.sub=sub - specification.subindex=subindex - local suffix=lower(suffixonly(resolved)) - if fonts.formats[suffix] then - specification.forced=suffix - specification.forcedname=resolved - specification.name=removesuffix(resolved) - else - specification.name=resolved - end - end - else - resolvers.file(specification) - end -end -function resolvers.spec(specification) - local resolvespec=fonts.names.resolvespec - if resolvespec then - local resolved,sub,subindex=resolvespec(specification.name,specification.sub,specification) - if resolved then - specification.resolved=resolved - specification.sub=sub - specification.subindex=subindex - specification.forced=lower(suffixonly(resolved)) - specification.forcedname=resolved - specification.name=removesuffix(resolved) - end - else - resolvers.name(specification) - end -end -function definers.resolve(specification) - if not specification.resolved or specification.resolved=="" then - local r=resolvers[specification.lookup] - if r then - r(specification) - end - end - if specification.forced=="" then - specification.forced=nil - specification.forcedname=nil - end - specification.hash=lower(specification.name..' @ '..constructors.hashfeatures(specification)) - if specification.sub and specification.sub~="" then - specification.hash=specification.sub..' @ '..specification.hash - end - return specification -end -function definers.applypostprocessors(tfmdata) - local postprocessors=tfmdata.postprocessors - if postprocessors then - local properties=tfmdata.properties - for i=1,#postprocessors do - local extrahash=postprocessors[i](tfmdata) - if type(extrahash)=="string" and extrahash~="" then - extrahash=gsub(lower(extrahash),"[^a-z]","-") - properties.fullname=formatters["%s-%s"](properties.fullname,extrahash) - end - end - end - return tfmdata -end -local function checkembedding(tfmdata) - local properties=tfmdata.properties - local embedding - if directive_embedall then - embedding="full" - elseif properties and properties.filename and constructors.dontembed[properties.filename] then - embedding="no" - else - embedding="subset" - end - if properties then - properties.embedding=embedding - else - tfmdata.properties={ embedding=embedding } - end - tfmdata.embedding=embedding -end -function definers.loadfont(specification) - local hash=constructors.hashinstance(specification) - local tfmdata=loadedfonts[hash] - if not tfmdata then - local forced=specification.forced or "" - if forced~="" then - local reader=readers[lower(forced)] - tfmdata=reader and reader(specification) - if not tfmdata then - report_defining("forced type %a of %a not found",forced,specification.name) - end - else - local sequence=readers.sequence - for s=1,#sequence do - local reader=sequence[s] - if readers[reader] then - if trace_defining then - report_defining("trying (reader sequence driven) type %a for %a with file %a",reader,specification.name,specification.filename) - end - tfmdata=readers[reader](specification) - if tfmdata then - break - else - specification.filename=nil - end - end - end - end - if tfmdata then - tfmdata=definers.applypostprocessors(tfmdata) - checkembedding(tfmdata) - loadedfonts[hash]=tfmdata - designsizes[specification.hash]=tfmdata.parameters.designsize - end - end - if not tfmdata then - report_defining("font with asked name %a is not found using lookup %a",specification.name,specification.lookup) - end - return tfmdata -end -function constructors.checkvirtualids() -end -function constructors.readanddefine(name,size) - local specification=definers.analyze(name,size) - local method=specification.method - if method and variants[method] then - specification=variants[method](specification) - end - specification=definers.resolve(specification) - local hash=constructors.hashinstance(specification) - local id=definers.registered(hash) - if not id then - local tfmdata=definers.loadfont(specification) - if tfmdata then - tfmdata.properties.hash=hash - constructors.checkvirtualids(tfmdata) - id=font.define(tfmdata) - definers.register(tfmdata,id) - else - id=0 - end - end - return fontdata[id],id -end -function definers.current() - return lastdefined -end -function definers.registered(hash) - local id=internalized[hash] - return id,id and fontdata[id] -end -function definers.register(tfmdata,id) - if tfmdata and id then - local hash=tfmdata.properties.hash - if not hash then - report_defining("registering font, id %a, name %a, invalid hash",id,tfmdata.properties.filename or "?") - elseif not internalized[hash] then - internalized[hash]=id - if trace_defining then - report_defining("registering font, id %s, hash %a",id,hash) - end - fontdata[id]=tfmdata - end - end -end -function definers.read(specification,size,id) - statistics.starttiming(fonts) - if type(specification)=="string" then - specification=definers.analyze(specification,size) - end - local method=specification.method - if method and variants[method] then - specification=variants[method](specification) - end - specification=definers.resolve(specification) - local hash=constructors.hashinstance(specification) - local tfmdata=definers.registered(hash) - if tfmdata then - if trace_defining then - report_defining("already hashed: %s",hash) - end - else - tfmdata=definers.loadfont(specification) - if tfmdata then - if trace_defining then - report_defining("loaded and hashed: %s",hash) - end - tfmdata.properties.hash=hash - if id then - definers.register(tfmdata,id) - end - else - if trace_defining then - report_defining("not loaded and hashed: %s",hash) - end - end - end - lastdefined=tfmdata or id - if not tfmdata then - report_defining("unknown font %a, loading aborted",specification.name) - elseif trace_defining and type(tfmdata)=="table" then - local properties=tfmdata.properties or {} - local parameters=tfmdata.parameters or {} - report_defining("using %a font with id %a, name %a, size %a, bytes %a, encoding %a, fullname %a, filename %a", - properties.format or "unknown",id,properties.name,parameters.size,properties.encodingbytes, - properties.encodingname,properties.fullname,file.basename(properties.filename)) - end - statistics.stoptiming(fonts) - return tfmdata -end -function font.getfont(id) - return fontdata[id] -end -callbacks.register('define_font',definers.read,"definition of fonts (tfmdata preparation)") - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['luatex-fonts-def']={ - version=1.001, - comment="companion to luatex-*.tex", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -if context then - texio.write_nl("fatal error: this module is not for context") - os.exit() -end -local fonts=fonts -fonts.constructors.namemode="specification" -function fonts.definers.getspecification(str) - return "",str,"",":",str -end -local list={} -local function issome () list.lookup='name' end -local function isfile () list.lookup='file' end -local function isname () list.lookup='name' end -local function thename(s) list.name=s end -local function issub (v) list.sub=v end -local function iscrap (s) list.crap=string.lower(s) end -local function iskey (k,v) list[k]=v end -local function istrue (s) list[s]=true end -local function isfalse(s) list[s]=false end -local P,S,R,C=lpeg.P,lpeg.S,lpeg.R,lpeg.C -local spaces=P(" ")^0 -local namespec=(1-S("/:("))^0 -local crapspec=spaces*P("/")*(((1-P(":"))^0)/iscrap)*spaces -local filename_1=P("file:")/isfile*(namespec/thename) -local filename_2=P("[")*P(true)/isname*(((1-P("]"))^0)/thename)*P("]") -local fontname_1=P("name:")/isname*(namespec/thename) -local fontname_2=P(true)/issome*(namespec/thename) -local sometext=(R("az","AZ","09")+S("+-.{}"))^1 -local truevalue=P("+")*spaces*(sometext/istrue) -local falsevalue=P("-")*spaces*(sometext/isfalse) -local keyvalue=(C(sometext)*spaces*P("=")*spaces*C(sometext))/iskey -local somevalue=sometext/istrue -local subvalue=P("(")*(C(P(1-S("()"))^1)/issub)*P(")") -local option=spaces*(keyvalue+falsevalue+truevalue+somevalue)*spaces -local options=P(":")*spaces*(P(";")^0*option)^0 -local pattern=(filename_1+filename_2+fontname_1+fontname_2)*subvalue^0*crapspec^0*options^0 -local function colonized(specification) - list={} - lpeg.match(pattern,specification.specification) - list.crap=nil - if list.name then - specification.name=list.name - list.name=nil - end - if list.lookup then - specification.lookup=list.lookup - list.lookup=nil - end - if list.sub then - specification.sub=list.sub - list.sub=nil - end - specification.features.normal=fonts.handlers.otf.features.normalize(list) - return specification -end -fonts.definers.registersplit(":",colonized,"cryptic") -fonts.definers.registersplit("",colonized,"more cryptic") -function fonts.definers.applypostprocessors(tfmdata) - local postprocessors=tfmdata.postprocessors - if postprocessors then - for i=1,#postprocessors do - local extrahash=postprocessors[i](tfmdata) - if type(extrahash)=="string" and extrahash~="" then - extrahash=string.gsub(lower(extrahash),"[^a-z]","-") - tfmdata.properties.fullname=format("%s-%s",tfmdata.properties.fullname,extrahash) - end - end - end - return tfmdata -end - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['luatex-fonts-ext']={ - version=1.001, - comment="companion to luatex-*.tex", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -if context then - texio.write_nl("fatal error: this module is not for context") - os.exit() -end -local fonts=fonts -local otffeatures=fonts.constructors.features.otf -local function initializeitlc(tfmdata,value) - if value then - local parameters=tfmdata.parameters - local italicangle=parameters.italicangle - if italicangle and italicangle~=0 then - local properties=tfmdata.properties - local factor=tonumber(value) or 1 - properties.hasitalics=true - properties.autoitalicamount=factor*(parameters.uwidth or 40)/2 - end - end -end -otffeatures.register { - name="itlc", - description="italic correction", - initializers={ - base=initializeitlc, - node=initializeitlc, - } -} -local function initializeslant(tfmdata,value) - value=tonumber(value) - if not value then - value=0 - elseif value>1 then - value=1 - elseif value<-1 then - value=-1 - end - tfmdata.parameters.slantfactor=value -end -otffeatures.register { - name="slant", - description="slant glyphs", - initializers={ - base=initializeslant, - node=initializeslant, - } -} -local function initializeextend(tfmdata,value) - value=tonumber(value) - if not value then - value=0 - elseif value>10 then - value=10 - elseif value<-10 then - value=-10 - end - tfmdata.parameters.extendfactor=value -end -otffeatures.register { - name="extend", - description="scale glyphs horizontally", - initializers={ - base=initializeextend, - node=initializeextend, - } -} -fonts.protrusions=fonts.protrusions or {} -fonts.protrusions.setups=fonts.protrusions.setups or {} -local setups=fonts.protrusions.setups -local function initializeprotrusion(tfmdata,value) - if value then - local setup=setups[value] - if setup then - local factor,left,right=setup.factor or 1,setup.left or 1,setup.right or 1 - local emwidth=tfmdata.parameters.quad - tfmdata.parameters.protrusion={ - auto=true, - } - for i,chr in next,tfmdata.characters do - local v,pl,pr=setup[i],nil,nil - if v then - pl,pr=v[1],v[2] - end - if pl and pl~=0 then chr.left_protruding=left*pl*factor end - if pr and pr~=0 then chr.right_protruding=right*pr*factor end - end - end - end -end -otffeatures.register { - name="protrusion", - description="shift characters into the left and or right margin", - initializers={ - base=initializeprotrusion, - node=initializeprotrusion, - } -} -fonts.expansions=fonts.expansions or {} -fonts.expansions.setups=fonts.expansions.setups or {} -local setups=fonts.expansions.setups -local function initializeexpansion(tfmdata,value) - if value then - local setup=setups[value] - if setup then - local factor=setup.factor or 1 - tfmdata.parameters.expansion={ - stretch=10*(setup.stretch or 0), - shrink=10*(setup.shrink or 0), - step=10*(setup.step or 0), - auto=true, - } - for i,chr in next,tfmdata.characters do - local v=setup[i] - if v and v~=0 then - chr.expansion_factor=v*factor - else - chr.expansion_factor=factor - end - end - end - end -end -otffeatures.register { - name="expansion", - description="apply hz optimization", - initializers={ - base=initializeexpansion, - node=initializeexpansion, - } -} -function fonts.loggers.onetimemessage() end -local byte=string.byte -fonts.expansions.setups['default']={ - stretch=2,shrink=2,step=.5,factor=1, - [byte('A')]=0.5,[byte('B')]=0.7,[byte('C')]=0.7,[byte('D')]=0.5,[byte('E')]=0.7, - [byte('F')]=0.7,[byte('G')]=0.5,[byte('H')]=0.7,[byte('K')]=0.7,[byte('M')]=0.7, - [byte('N')]=0.7,[byte('O')]=0.5,[byte('P')]=0.7,[byte('Q')]=0.5,[byte('R')]=0.7, - [byte('S')]=0.7,[byte('U')]=0.7,[byte('W')]=0.7,[byte('Z')]=0.7, - [byte('a')]=0.7,[byte('b')]=0.7,[byte('c')]=0.7,[byte('d')]=0.7,[byte('e')]=0.7, - [byte('g')]=0.7,[byte('h')]=0.7,[byte('k')]=0.7,[byte('m')]=0.7,[byte('n')]=0.7, - [byte('o')]=0.7,[byte('p')]=0.7,[byte('q')]=0.7,[byte('s')]=0.7,[byte('u')]=0.7, - [byte('w')]=0.7,[byte('z')]=0.7, - [byte('2')]=0.7,[byte('3')]=0.7,[byte('6')]=0.7,[byte('8')]=0.7,[byte('9')]=0.7, -} -fonts.protrusions.setups['default']={ - factor=1,left=1,right=1, - [0x002C]={ 0,1 }, - [0x002E]={ 0,1 }, - [0x003A]={ 0,1 }, - [0x003B]={ 0,1 }, - [0x002D]={ 0,1 }, - [0x2013]={ 0,0.50 }, - [0x2014]={ 0,0.33 }, - [0x3001]={ 0,1 }, - [0x3002]={ 0,1 }, - [0x060C]={ 0,1 }, - [0x061B]={ 0,1 }, - [0x06D4]={ 0,1 }, -} -fonts.handlers.otf.features.normalize=function(t) - if t.rand then - t.rand="random" - end - return t -end -function fonts.helpers.nametoslot(name) - local t=type(name) - if t=="string" then - local tfmdata=fonts.hashes.identifiers[currentfont()] - local shared=tfmdata and tfmdata.shared - local fntdata=shared and shared.rawdata - return fntdata and fntdata.resources.unicodes[name] - elseif t=="number" then - return n - end -end -fonts.encodings=fonts.encodings or {} -local reencodings={} -fonts.encodings.reencodings=reencodings -local function specialreencode(tfmdata,value) - local encoding=value and reencodings[value] - if encoding then - local temp={} - local char=tfmdata.characters - for k,v in next,encoding do - temp[k]=char[v] - end - for k,v in next,temp do - char[k]=temp[k] - end - return string.format("reencoded:%s",value) - end -end -local function reencode(tfmdata,value) - tfmdata.postprocessors=tfmdata.postprocessors or {} - table.insert(tfmdata.postprocessors, - function(tfmdata) - return specialreencode(tfmdata,value) - end - ) -end -otffeatures.register { - name="reencode", - description="reencode characters", - manipulators={ - base=reencode, - node=reencode, - } -} -local function ignore(tfmdata,key,value) - if value then - tfmdata.mathparameters=nil - end -end -otffeatures.register { - name="ignoremathconstants", - description="ignore math constants table", - initializers={ - base=ignore, - node=ignore, - } -} - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['font-gbn']={ - version=1.001, - comment="companion to luatex-*.tex", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -if context then - texio.write_nl("fatal error: this module is not for context") - os.exit() -end -local fonts=fonts -local nodes=nodes -local nuts=nodes.nuts -local traverse_id=nuts.traverse_id -local flush_node=nuts.flush_node -local glyph_code=nodes.nodecodes.glyph -local disc_code=nodes.nodecodes.disc -local tonode=nuts.tonode -local tonut=nuts.tonut -local getfont=nuts.getfont -local getchar=nuts.getchar -local getid=nuts.getid -local getboth=nuts.getboth -local getprev=nuts.getprev -local getnext=nuts.getnext -local getdisc=nuts.getdisc -local setchar=nuts.setchar -local setlink=nuts.setlink -local setprev=nuts.setprev -local n_ligaturing=node.ligaturing -local n_kerning=node.kerning -local ligaturing=nuts.ligaturing -local kerning=nuts.kerning -local basemodepass=true -local function l_warning() texio.write_nl("warning: node.ligaturing called directly") l_warning=nil end -local function k_warning() texio.write_nl("warning: node.kerning called directly") k_warning=nil end -function node.ligaturing(...) - if basemodepass and l_warning then - l_warning() - end - return n_ligaturing(...) -end -function node.kerning(...) - if basemodepass and k_warning then - k_warning() - end - return n_kerning(...) -end -function nodes.handlers.setbasemodepass(v) - basemodepass=v -end -function nodes.handlers.nodepass(head) - local fontdata=fonts.hashes.identifiers - if fontdata then - local nuthead=tonut(head) - local usedfonts={} - local basefonts={} - local prevfont=nil - local basefont=nil - local variants=nil - local redundant=nil - for n in traverse_id(glyph_code,nuthead) do - local font=getfont(n) - if font~=prevfont then - if basefont then - basefont[2]=getprev(n) - end - prevfont=font - local used=usedfonts[font] - if not used then - local tfmdata=fontdata[font] - if tfmdata then - local shared=tfmdata.shared - if shared then - local processors=shared.processes - if processors and #processors>0 then - usedfonts[font]=processors - elseif basemodepass then - basefont={ n,nil } - basefonts[#basefonts+1]=basefont - end - end - local resources=tfmdata.resources - variants=resources and resources.variants - variants=variants and next(variants) and variants or false - end - else - local tfmdata=fontdata[prevfont] - if tfmdata then - local resources=tfmdata.resources - variants=resources and resources.variants - variants=variants and next(variants) and variants or false - end - end - end - if variants then - local char=getchar(n) - if char>=0xFE00 and (char<=0xFE0F or (char>=0xE0100 and char<=0xE01EF)) then - local hash=variants[char] - if hash then - local p=getprev(n) - if p and getid(p)==glyph_code then - local variant=hash[getchar(p)] - if variant then - setchar(p,variant) - end - end - end - if not redundant then - redundant={ n } - else - redundant[#redundant+1]=n - end - end - end - end - local nofbasefonts=#basefonts - if redundant then - for i=1,#redundant do - local r=redundant[i] - local p,n=getboth(r) - if r==nuthead then - nuthead=n - setprev(n) - else - setlink(p,n) - end - if nofbasefonts>0 then - for i=1,nofbasefonts do - local bi=basefonts[i] - if r==bi[1] then - bi[1]=n - end - if r==bi[2] then - bi[2]=n - end - end - end - flush_node(r) - end - end - for d in traverse_id(disc_code,nuthead) do - local _,_,r=getdisc(d) - if r then - for n in traverse_id(glyph_code,r) do - local font=getfont(n) - if font~=prevfont then - prevfont=font - local used=usedfonts[font] - if not used then - local tfmdata=fontdata[font] - if tfmdata then - local shared=tfmdata.shared - if shared then - local processors=shared.processes - if processors and #processors>0 then - usedfonts[font]=processors - end - end - end - end - end - end - end - end - if next(usedfonts) then - for font,processors in next,usedfonts do - for i=1,#processors do - head=processors[i](head,font,0) or head - end - end - end - if basemodepass and nofbasefonts>0 then - for i=1,nofbasefonts do - local range=basefonts[i] - local start=range[1] - local stop=range[2] - if start then - local front=nuthead==start - local prev,next - if stop then - next=getnext(stop) - start,stop=ligaturing(start,stop) - start,stop=kerning(start,stop) - else - prev=getprev(start) - start=ligaturing(start) - start=kerning(start) - end - if prev then - setlink(prev,start) - end - if next then - setlink(stop,next) - end - if front and nuthead~=start then - head=tonode(start) - end - end - end - end - return head,true - else - return head,false - end -end -function nodes.handlers.basepass(head) - if not basemodepass then - head=n_ligaturing(head) - head=n_kerning(head) - end - return head,true -end -local nodepass=nodes.handlers.nodepass -local basepass=nodes.handlers.basepass -local injectpass=nodes.injections.handler -local protectpass=nodes.handlers.protectglyphs -function nodes.simple_font_handler(head) - if head then - head=nodepass(head) - head=injectpass(head) - if not basemodepass then - head=basepass(head) - end - protectpass(head) - return head,true - else - return head,false - end -end - -end -- closure diff --git a/tex/compat/luaotfload/fontloader-swiglib-test.lua b/tex/compat/luaotfload/fontloader-swiglib-test.lua deleted file mode 100644 index 00d7c5a4efe9aae4ae86d26b8531fac7f42b03e2..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/fontloader-swiglib-test.lua +++ /dev/null @@ -1,743 +0,0 @@ - - --- local gm = require("swiglib.gmwand.core") -- local gm = swiglib("gmwand.core") --- --- gm.InitializeMagick(".") --- --- local magick_wand = gm.NewMagickWand() --- local drawing_wand = gm.NewDrawingWand() --- --- gm.MagickSetSize(magick_wand,800,600) --- gm.MagickReadImage(magick_wand,"xc:red") --- --- gm.DrawPushGraphicContext(drawing_wand) --- --- gm.DrawSetFillColor(drawing_wand,gm.NewPixelWand()) --- --- -- gm.DrawSetFont(drawing_wand, kpse.findfile("DejaVuSerifBold.ttf")) --- -- gm.DrawSetFontSize(drawing_wand, 96) --- -- gm.DrawAnnotation(drawing_wand,300,200, "LuaTeX") --- --- gm.DrawPopGraphicContext(drawing_wand) --- gm.MagickDrawImage(magick_wand,drawing_wand) --- --- gm.MagickWriteImages(magick_wand,"./luatex-swiglib-test.jpg",1) --- --- gm.DestroyDrawingWand(drawing_wand) --- gm.DestroyMagickWand(magick_wand) - -local swighelpers = require("swiglib.helpers.core") -local sqlite = require("swiglib.sqlite.core") - --- s.sqlite3_create_function_v2_lua_callback(function() end) - - -local t = [[ - CREATE TABLE IF NOT EXISTS loggers ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `time` int(11) NOT NULL, - `type` int(11) NOT NULL, - `action` varchar(15) NOT NULL, - `data` longtext, - PRIMARY KEY (`id`), - UNIQUE KEY `id_unique_key` (`id`) - ) - DEFAULT CHARSET = utf8 ; -]] - -local t = [[ -CREATE TABLE IF NOT EXISTS loggers ( - `id` INTEGER PRIMARY KEY AUTOINCREMENT, - `time` int(11) NOT NULL, - `type` int(11) NOT NULL, - `action` varchar(15) NOT NULL, - `data` longtext - ); -]] - -local function execute(name,query) - local db = sqlite.new_sqlite3_p_array(1) - local okay = sqlite.sqlite3_open(name,db) - local dbh = sqlite.sqlite3_p_array_getitem(db,0) - if okay ~= sqlite.SQLITE_OK then - return false, sqlite.sqlite3_errmsg(dbh) - end - local result = { } - local callback = function(data,nofcolumns,values,fields) - local r = { } - for i=0,nofcolumns-1 do - local field = sqlite.char_p_array_getitem(fields,i) - local value = sqlite.char_p_array_getitem(values,i) - r[field] = value - end - result[#result+1] = r - return sqlite.SQLITE_OK - end - local data = nil - local message = nil - local okay = sqlite.sqlite3_exec_lua_callback(dbh,query,callback,data,message) - if okay ~= sqlite.SQLITE_OK then - return false, sqlite.sqlite3_errmsg(dbh) - end - sqlite.sqlite3_close(dbh) - sqlite.delete_sqlite3_p_array(db) - return result -end - -execute("foo.db",t) --- execute("test.db",t) - -local template =[[ - INSERT INTO loggers ( - `time`, - `type`, - `action`, - `data` - ) VALUES ( - %s, - %s, - '%s', - '%s' - ) ; -]] - --- for i=1,100 do --- local t = string.format(template,os.time(),1,"oeps " .. i,"more") --- execute("foo.db",t) --- end - - -local r = execute("foo.db","select * from loggers;") -inspect(r) - - --- inspect(table.sortedkeys(sqlite)) --- inspect(table.sortedkeys(swighelpers)) - - - -t={ - "FULLY_WITHIN", - "NOT_WITHIN", - "PARTLY_WITHIN", - "SQLITE3_TEXT", - "SQLITE_ABORT", - "SQLITE_ABORT_ROLLBACK", - "SQLITE_ACCESS_EXISTS", - "SQLITE_ACCESS_READ", - "SQLITE_ACCESS_READWRITE", - "SQLITE_ALTER_TABLE", - "SQLITE_ANALYZE", - "SQLITE_ANY", - "SQLITE_ATTACH", - "SQLITE_AUTH", - "SQLITE_AUTH_USER", - "SQLITE_BLOB", - "SQLITE_BUSY", - "SQLITE_BUSY_RECOVERY", - "SQLITE_BUSY_SNAPSHOT", - "SQLITE_CANTOPEN", - "SQLITE_CANTOPEN_CONVPATH", - "SQLITE_CANTOPEN_FULLPATH", - "SQLITE_CANTOPEN_ISDIR", - "SQLITE_CANTOPEN_NOTEMPDIR", - "SQLITE_CHECKPOINT_FULL", - "SQLITE_CHECKPOINT_PASSIVE", - "SQLITE_CHECKPOINT_RESTART", - "SQLITE_CONFIG_COVERING_INDEX_SCAN", - "SQLITE_CONFIG_GETMALLOC", - "SQLITE_CONFIG_GETMUTEX", - "SQLITE_CONFIG_GETPCACHE", - "SQLITE_CONFIG_GETPCACHE2", - "SQLITE_CONFIG_HEAP", - "SQLITE_CONFIG_LOG", - "SQLITE_CONFIG_LOOKASIDE", - "SQLITE_CONFIG_MALLOC", - "SQLITE_CONFIG_MEMSTATUS", - "SQLITE_CONFIG_MMAP_SIZE", - "SQLITE_CONFIG_MULTITHREAD", - "SQLITE_CONFIG_MUTEX", - "SQLITE_CONFIG_PAGECACHE", - "SQLITE_CONFIG_PCACHE", - "SQLITE_CONFIG_PCACHE2", - "SQLITE_CONFIG_SCRATCH", - "SQLITE_CONFIG_SERIALIZED", - "SQLITE_CONFIG_SINGLETHREAD", - "SQLITE_CONFIG_SQLLOG", - "SQLITE_CONFIG_URI", - "SQLITE_CONFIG_WIN32_HEAPSIZE", - "SQLITE_CONSTRAINT", - "SQLITE_CONSTRAINT_CHECK", - "SQLITE_CONSTRAINT_COMMITHOOK", - "SQLITE_CONSTRAINT_FOREIGNKEY", - "SQLITE_CONSTRAINT_FUNCTION", - "SQLITE_CONSTRAINT_NOTNULL", - "SQLITE_CONSTRAINT_PRIMARYKEY", - "SQLITE_CONSTRAINT_ROWID", - "SQLITE_CONSTRAINT_TRIGGER", - "SQLITE_CONSTRAINT_UNIQUE", - "SQLITE_CONSTRAINT_VTAB", - "SQLITE_COPY", - "SQLITE_CORRUPT", - "SQLITE_CORRUPT_VTAB", - "SQLITE_CREATE_INDEX", - "SQLITE_CREATE_TABLE", - "SQLITE_CREATE_TEMP_INDEX", - "SQLITE_CREATE_TEMP_TABLE", - "SQLITE_CREATE_TEMP_TRIGGER", - "SQLITE_CREATE_TEMP_VIEW", - "SQLITE_CREATE_TRIGGER", - "SQLITE_CREATE_VIEW", - "SQLITE_CREATE_VTABLE", - "SQLITE_DBCONFIG_ENABLE_FKEY", - "SQLITE_DBCONFIG_ENABLE_TRIGGER", - "SQLITE_DBCONFIG_LOOKASIDE", - "SQLITE_DBSTATUS_CACHE_HIT", - "SQLITE_DBSTATUS_CACHE_MISS", - "SQLITE_DBSTATUS_CACHE_USED", - "SQLITE_DBSTATUS_CACHE_WRITE", - "SQLITE_DBSTATUS_DEFERRED_FKS", - "SQLITE_DBSTATUS_LOOKASIDE_HIT", - "SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL", - "SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE", - "SQLITE_DBSTATUS_LOOKASIDE_USED", - "SQLITE_DBSTATUS_MAX", - "SQLITE_DBSTATUS_SCHEMA_USED", - "SQLITE_DBSTATUS_STMT_USED", - "SQLITE_DELETE", - "SQLITE_DENY", - "SQLITE_DETACH", - "SQLITE_DETERMINISTIC", - "SQLITE_DONE", - "SQLITE_DROP_INDEX", - "SQLITE_DROP_TABLE", - "SQLITE_DROP_TEMP_INDEX", - "SQLITE_DROP_TEMP_TABLE", - "SQLITE_DROP_TEMP_TRIGGER", - "SQLITE_DROP_TEMP_VIEW", - "SQLITE_DROP_TRIGGER", - "SQLITE_DROP_VIEW", - "SQLITE_DROP_VTABLE", - "SQLITE_EMPTY", - "SQLITE_ERROR", - "SQLITE_FAIL", - "SQLITE_FCNTL_BUSYHANDLER", - "SQLITE_FCNTL_CHUNK_SIZE", - "SQLITE_FCNTL_COMMIT_PHASETWO", - "SQLITE_FCNTL_FILE_POINTER", - "SQLITE_FCNTL_HAS_MOVED", - "SQLITE_FCNTL_LOCKSTATE", - "SQLITE_FCNTL_MMAP_SIZE", - "SQLITE_FCNTL_OVERWRITE", - "SQLITE_FCNTL_PERSIST_WAL", - "SQLITE_FCNTL_POWERSAFE_OVERWRITE", - "SQLITE_FCNTL_PRAGMA", - "SQLITE_FCNTL_SIZE_HINT", - "SQLITE_FCNTL_SYNC", - "SQLITE_FCNTL_SYNC_OMITTED", - "SQLITE_FCNTL_TEMPFILENAME", - "SQLITE_FCNTL_TRACE", - "SQLITE_FCNTL_VFSNAME", - "SQLITE_FCNTL_WIN32_AV_RETRY", - "SQLITE_FCNTL_WIN32_SET_HANDLE", - "SQLITE_FLOAT", - "SQLITE_FORMAT", - "SQLITE_FULL", - "SQLITE_FUNCTION", - "SQLITE_GET_LOCKPROXYFILE", - "SQLITE_IGNORE", - "SQLITE_INDEX_CONSTRAINT_EQ", - "SQLITE_INDEX_CONSTRAINT_GE", - "SQLITE_INDEX_CONSTRAINT_GT", - "SQLITE_INDEX_CONSTRAINT_LE", - "SQLITE_INDEX_CONSTRAINT_LT", - "SQLITE_INDEX_CONSTRAINT_MATCH", - "SQLITE_INSERT", - "SQLITE_INTEGER", - "SQLITE_INTERNAL", - "SQLITE_INTERRUPT", - "SQLITE_IOCAP_ATOMIC", - "SQLITE_IOCAP_ATOMIC16K", - "SQLITE_IOCAP_ATOMIC1K", - "SQLITE_IOCAP_ATOMIC2K", - "SQLITE_IOCAP_ATOMIC32K", - "SQLITE_IOCAP_ATOMIC4K", - "SQLITE_IOCAP_ATOMIC512", - "SQLITE_IOCAP_ATOMIC64K", - "SQLITE_IOCAP_ATOMIC8K", - "SQLITE_IOCAP_IMMUTABLE", - "SQLITE_IOCAP_POWERSAFE_OVERWRITE", - "SQLITE_IOCAP_SAFE_APPEND", - "SQLITE_IOCAP_SEQUENTIAL", - "SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN", - "SQLITE_IOERR", - "SQLITE_IOERR_ACCESS", - "SQLITE_IOERR_BLOCKED", - "SQLITE_IOERR_CHECKRESERVEDLOCK", - "SQLITE_IOERR_CLOSE", - "SQLITE_IOERR_CONVPATH", - "SQLITE_IOERR_DELETE", - "SQLITE_IOERR_DELETE_NOENT", - "SQLITE_IOERR_DIR_CLOSE", - "SQLITE_IOERR_DIR_FSYNC", - "SQLITE_IOERR_FSTAT", - "SQLITE_IOERR_FSYNC", - "SQLITE_IOERR_GETTEMPPATH", - "SQLITE_IOERR_LOCK", - "SQLITE_IOERR_MMAP", - "SQLITE_IOERR_NOMEM", - "SQLITE_IOERR_RDLOCK", - "SQLITE_IOERR_READ", - "SQLITE_IOERR_SEEK", - "SQLITE_IOERR_SHMLOCK", - "SQLITE_IOERR_SHMMAP", - "SQLITE_IOERR_SHMOPEN", - "SQLITE_IOERR_SHMSIZE", - "SQLITE_IOERR_SHORT_READ", - "SQLITE_IOERR_TRUNCATE", - "SQLITE_IOERR_UNLOCK", - "SQLITE_IOERR_WRITE", - "SQLITE_LAST_ERRNO", - "SQLITE_LIMIT_ATTACHED", - "SQLITE_LIMIT_COLUMN", - "SQLITE_LIMIT_COMPOUND_SELECT", - "SQLITE_LIMIT_EXPR_DEPTH", - "SQLITE_LIMIT_FUNCTION_ARG", - "SQLITE_LIMIT_LENGTH", - "SQLITE_LIMIT_LIKE_PATTERN_LENGTH", - "SQLITE_LIMIT_SQL_LENGTH", - "SQLITE_LIMIT_TRIGGER_DEPTH", - "SQLITE_LIMIT_VARIABLE_NUMBER", - "SQLITE_LIMIT_VDBE_OP", - "SQLITE_LIMIT_WORKER_THREADS", - "SQLITE_LOCKED", - "SQLITE_LOCKED_SHAREDCACHE", - "SQLITE_LOCK_EXCLUSIVE", - "SQLITE_LOCK_NONE", - "SQLITE_LOCK_PENDING", - "SQLITE_LOCK_RESERVED", - "SQLITE_LOCK_SHARED", - "SQLITE_MISMATCH", - "SQLITE_MISUSE", - "SQLITE_MUTEX_FAST", - "SQLITE_MUTEX_RECURSIVE", - "SQLITE_MUTEX_STATIC_APP1", - "SQLITE_MUTEX_STATIC_APP2", - "SQLITE_MUTEX_STATIC_APP3", - "SQLITE_MUTEX_STATIC_LRU", - "SQLITE_MUTEX_STATIC_LRU2", - "SQLITE_MUTEX_STATIC_MASTER", - "SQLITE_MUTEX_STATIC_MEM", - "SQLITE_MUTEX_STATIC_MEM2", - "SQLITE_MUTEX_STATIC_OPEN", - "SQLITE_MUTEX_STATIC_PMEM", - "SQLITE_MUTEX_STATIC_PRNG", - "SQLITE_NOLFS", - "SQLITE_NOMEM", - "SQLITE_NOTADB", - "SQLITE_NOTFOUND", - "SQLITE_NOTICE", - "SQLITE_NOTICE_RECOVER_ROLLBACK", - "SQLITE_NOTICE_RECOVER_WAL", - "SQLITE_NULL", - "SQLITE_OK", - "SQLITE_OPEN_AUTOPROXY", - "SQLITE_OPEN_CREATE", - "SQLITE_OPEN_DELETEONCLOSE", - "SQLITE_OPEN_EXCLUSIVE", - "SQLITE_OPEN_FULLMUTEX", - "SQLITE_OPEN_MAIN_DB", - "SQLITE_OPEN_MAIN_JOURNAL", - "SQLITE_OPEN_MASTER_JOURNAL", - "SQLITE_OPEN_MEMORY", - "SQLITE_OPEN_NOMUTEX", - "SQLITE_OPEN_PRIVATECACHE", - "SQLITE_OPEN_READONLY", - "SQLITE_OPEN_READWRITE", - "SQLITE_OPEN_SHAREDCACHE", - "SQLITE_OPEN_SUBJOURNAL", - "SQLITE_OPEN_TEMP_DB", - "SQLITE_OPEN_TEMP_JOURNAL", - "SQLITE_OPEN_TRANSIENT_DB", - "SQLITE_OPEN_URI", - "SQLITE_OPEN_WAL", - "SQLITE_PERM", - "SQLITE_PRAGMA", - "SQLITE_PROTOCOL", - "SQLITE_RANGE", - "SQLITE_READ", - "SQLITE_READONLY", - "SQLITE_READONLY_CANTLOCK", - "SQLITE_READONLY_DBMOVED", - "SQLITE_READONLY_RECOVERY", - "SQLITE_READONLY_ROLLBACK", - "SQLITE_RECURSIVE", - "SQLITE_REINDEX", - "SQLITE_REPLACE", - "SQLITE_ROLLBACK", - "SQLITE_ROW", - "SQLITE_SAVEPOINT", - "SQLITE_SCHEMA", - "SQLITE_SELECT", - "SQLITE_SET_LOCKPROXYFILE", - "SQLITE_SHM_EXCLUSIVE", - "SQLITE_SHM_LOCK", - "SQLITE_SHM_NLOCK", - "SQLITE_SHM_SHARED", - "SQLITE_SHM_UNLOCK", - "SQLITE_SOURCE_ID", - "SQLITE_STATUS_MALLOC_COUNT", - "SQLITE_STATUS_MALLOC_SIZE", - "SQLITE_STATUS_MEMORY_USED", - "SQLITE_STATUS_PAGECACHE_OVERFLOW", - "SQLITE_STATUS_PAGECACHE_SIZE", - "SQLITE_STATUS_PAGECACHE_USED", - "SQLITE_STATUS_PARSER_STACK", - "SQLITE_STATUS_SCRATCH_OVERFLOW", - "SQLITE_STATUS_SCRATCH_SIZE", - "SQLITE_STATUS_SCRATCH_USED", - "SQLITE_STMTSTATUS_AUTOINDEX", - "SQLITE_STMTSTATUS_FULLSCAN_STEP", - "SQLITE_STMTSTATUS_SORT", - "SQLITE_STMTSTATUS_VM_STEP", - "SQLITE_SYNC_DATAONLY", - "SQLITE_SYNC_FULL", - "SQLITE_SYNC_NORMAL", - "SQLITE_TESTCTRL_ALWAYS", - "SQLITE_TESTCTRL_ASSERT", - "SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS", - "SQLITE_TESTCTRL_BITVEC_TEST", - "SQLITE_TESTCTRL_BYTEORDER", - "SQLITE_TESTCTRL_EXPLAIN_STMT", - "SQLITE_TESTCTRL_FAULT_INSTALL", - "SQLITE_TESTCTRL_FIRST", - "SQLITE_TESTCTRL_ISINIT", - "SQLITE_TESTCTRL_ISKEYWORD", - "SQLITE_TESTCTRL_LAST", - "SQLITE_TESTCTRL_LOCALTIME_FAULT", - "SQLITE_TESTCTRL_NEVER_CORRUPT", - "SQLITE_TESTCTRL_OPTIMIZATIONS", - "SQLITE_TESTCTRL_PENDING_BYTE", - "SQLITE_TESTCTRL_PRNG_RESET", - "SQLITE_TESTCTRL_PRNG_RESTORE", - "SQLITE_TESTCTRL_PRNG_SAVE", - "SQLITE_TESTCTRL_RESERVE", - "SQLITE_TESTCTRL_SCRATCHMALLOC", - "SQLITE_TESTCTRL_SORTER_MMAP", - "SQLITE_TESTCTRL_VDBE_COVERAGE", - "SQLITE_TEXT", - "SQLITE_TOOBIG", - "SQLITE_TRANSACTION", - "SQLITE_UPDATE", - "SQLITE_UTF16", - "SQLITE_UTF16BE", - "SQLITE_UTF16LE", - "SQLITE_UTF16_ALIGNED", - "SQLITE_UTF8", - "SQLITE_VERSION", - "SQLITE_VERSION_NUMBER", - "SQLITE_VTAB_CONSTRAINT_SUPPORT", - "SQLITE_WARNING", - "SQLITE_WARNING_AUTOINDEX", - "call_callback_sqlite3_create_collation_v2_1", - "call_callback_sqlite3_create_collation_v2_2", - "call_callback_sqlite3_create_function16_1", - "call_callback_sqlite3_create_function16_2", - "call_callback_sqlite3_create_function16_3", - "call_callback_sqlite3_create_function_1", - "call_callback_sqlite3_create_function_2", - "call_callback_sqlite3_create_function_3", - "call_callback_sqlite3_create_function_v2_1", - "call_callback_sqlite3_create_function_v2_2", - "call_callback_sqlite3_create_function_v2_3", - "call_callback_sqlite3_create_function_v2_4", - "call_callback_sqlite3_rtree_query_callback_1", - "call_callback_sqlite3_rtree_query_callback_2", - "char_p_array_getitem", - "char_p_array_setitem", - "delete_char_p_array", - "delete_sqlite3_p_array", - "delete_sqlite3_rtree_dbl_array", - "delete_sqlite3_stmt_p_array", - "delete_sqlite3_value_p_array", - "delete_sqlite3_vtab_cursor_p_array", - "delete_sqlite3_vtab_p_array", - "delete_void_p_array", - "new_char_p_array", - "new_sqlite3_p_array", - "new_sqlite3_rtree_dbl_array", - "new_sqlite3_stmt_p_array", - "new_sqlite3_value_p_array", - "new_sqlite3_vtab_cursor_p_array", - "new_sqlite3_vtab_p_array", - "new_void_p_array", - "sqlite3_aggregate_context", - "sqlite3_aggregate_count", - "sqlite3_auto_extension", - "sqlite3_auto_extension_lua_callback", - "sqlite3_backup_finish", - "sqlite3_backup_init", - "sqlite3_backup_pagecount", - "sqlite3_backup_remaining", - "sqlite3_backup_step", - "sqlite3_bind_blob", - "sqlite3_bind_blob64", - "sqlite3_bind_blob64_lua_callback", - "sqlite3_bind_blob_lua_callback", - "sqlite3_bind_double", - "sqlite3_bind_int", - "sqlite3_bind_int64", - "sqlite3_bind_null", - "sqlite3_bind_parameter_count", - "sqlite3_bind_parameter_index", - "sqlite3_bind_parameter_name", - "sqlite3_bind_text", - "sqlite3_bind_text16", - "sqlite3_bind_text16_lua_callback", - "sqlite3_bind_text64", - "sqlite3_bind_text64_lua_callback", - "sqlite3_bind_text_lua_callback", - "sqlite3_bind_value", - "sqlite3_bind_zeroblob", - "sqlite3_blob_bytes", - "sqlite3_blob_close", - "sqlite3_blob_open", - "sqlite3_blob_read", - "sqlite3_blob_reopen", - "sqlite3_blob_write", - "sqlite3_busy_handler", - "sqlite3_busy_handler_lua_callback", - "sqlite3_busy_timeout", - "sqlite3_cancel_auto_extension", - "sqlite3_cancel_auto_extension_lua_callback", - "sqlite3_changes", - "sqlite3_clear_bindings", - "sqlite3_close", - "sqlite3_close_v2", - "sqlite3_collation_needed", - "sqlite3_collation_needed16", - "sqlite3_collation_needed16_lua_callback", - "sqlite3_collation_needed_lua_callback", - "sqlite3_column_blob", - "sqlite3_column_bytes", - "sqlite3_column_bytes16", - "sqlite3_column_count", - "sqlite3_column_decltype", - "sqlite3_column_decltype16", - "sqlite3_column_double", - "sqlite3_column_int", - "sqlite3_column_int64", - "sqlite3_column_name", - "sqlite3_column_name16", - "sqlite3_column_text", - "sqlite3_column_text16", - "sqlite3_column_type", - "sqlite3_column_value", - "sqlite3_commit_hook", - "sqlite3_commit_hook_lua_callback", - "sqlite3_compileoption_get", - "sqlite3_compileoption_used", - "sqlite3_complete", - "sqlite3_complete16", - "sqlite3_config", - "sqlite3_context_db_handle", - "sqlite3_create_collation", - "sqlite3_create_collation16", - "sqlite3_create_collation16_lua_callback", - "sqlite3_create_collation_lua_callback", - "sqlite3_create_collation_v2", - "sqlite3_create_collation_v2_lua_callback", - "sqlite3_create_function", - "sqlite3_create_function16", - "sqlite3_create_function16_lua_callback", - "sqlite3_create_function_lua_callback", - "sqlite3_create_function_v2", - "sqlite3_create_function_v2_lua_callback", - "sqlite3_create_module", - "sqlite3_create_module_v2", - "sqlite3_create_module_v2_lua_callback", - "sqlite3_data_count", - "sqlite3_db_config", - "sqlite3_db_filename", - "sqlite3_db_handle", - "sqlite3_db_mutex", - "sqlite3_db_readonly", - "sqlite3_db_release_memory", - "sqlite3_db_status", - "sqlite3_declare_vtab", - "sqlite3_enable_load_extension", - "sqlite3_enable_shared_cache", - "sqlite3_errcode", - "sqlite3_errmsg", - "sqlite3_errmsg16", - "sqlite3_errstr", - "sqlite3_exec", - "sqlite3_exec_lua_callback", - "sqlite3_expired", - "sqlite3_extended_errcode", - "sqlite3_extended_result_codes", - "sqlite3_file", - "sqlite3_file_control", - "sqlite3_finalize", - "sqlite3_free", - "sqlite3_free_table", - "sqlite3_get_autocommit", - "sqlite3_get_auxdata", - "sqlite3_get_table", - "sqlite3_global_recover", - "sqlite3_index_info", - "sqlite3_index_info_aConstraint", - "sqlite3_index_info_aConstraintUsage", - "sqlite3_index_info_aOrderBy", - "sqlite3_initialize", - "sqlite3_interrupt", - "sqlite3_io_methods", - "sqlite3_last_insert_rowid", - "sqlite3_libversion", - "sqlite3_libversion_number", - "sqlite3_limit", - "sqlite3_load_extension", - "sqlite3_log", - "sqlite3_malloc", - "sqlite3_malloc64", - "sqlite3_mem_methods", - "sqlite3_memory_alarm", - "sqlite3_memory_highwater", - "sqlite3_memory_used", - "sqlite3_module", - "sqlite3_mprintf", - "sqlite3_msize", - "sqlite3_mutex_alloc", - "sqlite3_mutex_enter", - "sqlite3_mutex_free", - "sqlite3_mutex_leave", - "sqlite3_mutex_methods", - "sqlite3_mutex_try", - "sqlite3_next_stmt", - "sqlite3_open", - "sqlite3_open16", - "sqlite3_open_v2", - "sqlite3_os_end", - "sqlite3_os_init", - "sqlite3_overload_function", - "sqlite3_p_array_getitem", - "sqlite3_p_array_setitem", - "sqlite3_pcache_methods", - "sqlite3_pcache_methods2", - "sqlite3_pcache_page", - "sqlite3_prepare", - "sqlite3_prepare16", - "sqlite3_prepare16_v2", - "sqlite3_prepare_v2", - "sqlite3_profile", - "sqlite3_progress_handler", - "sqlite3_progress_handler_lua_callback", - "sqlite3_randomness", - "sqlite3_realloc", - "sqlite3_realloc64", - "sqlite3_release_memory", - "sqlite3_reset", - "sqlite3_reset_auto_extension", - "sqlite3_result_blob", - "sqlite3_result_blob64", - "sqlite3_result_blob64_lua_callback", - "sqlite3_result_blob_lua_callback", - "sqlite3_result_double", - "sqlite3_result_error", - "sqlite3_result_error16", - "sqlite3_result_error_code", - "sqlite3_result_error_nomem", - "sqlite3_result_error_toobig", - "sqlite3_result_int", - "sqlite3_result_int64", - "sqlite3_result_null", - "sqlite3_result_text", - "sqlite3_result_text16", - "sqlite3_result_text16_lua_callback", - "sqlite3_result_text16be", - "sqlite3_result_text16be_lua_callback", - "sqlite3_result_text16le", - "sqlite3_result_text16le_lua_callback", - "sqlite3_result_text64", - "sqlite3_result_text64_lua_callback", - "sqlite3_result_text_lua_callback", - "sqlite3_result_value", - "sqlite3_result_zeroblob", - "sqlite3_rollback_hook", - "sqlite3_rollback_hook_lua_callback", - "sqlite3_rtree_dbl_array_getitem", - "sqlite3_rtree_dbl_array_setitem", - "sqlite3_rtree_geometry", - "sqlite3_rtree_geometry_callback", - "sqlite3_rtree_geometry_callback_lua_callback", - "sqlite3_rtree_query_callback", - "sqlite3_rtree_query_callback_lua_callback", - "sqlite3_rtree_query_info", - "sqlite3_set_authorizer", - "sqlite3_set_authorizer_lua_callback", - "sqlite3_set_auxdata", - "sqlite3_set_auxdata_lua_callback", - "sqlite3_shutdown", - "sqlite3_sleep", - "sqlite3_snprintf", - "sqlite3_soft_heap_limit", - "sqlite3_soft_heap_limit64", - "sqlite3_sourceid", - "sqlite3_sql", - "sqlite3_status", - "sqlite3_step", - "sqlite3_stmt_busy", - "sqlite3_stmt_p_array_getitem", - "sqlite3_stmt_p_array_setitem", - "sqlite3_stmt_readonly", - "sqlite3_stmt_status", - "sqlite3_strglob", - "sqlite3_stricmp", - "sqlite3_strnicmp", - "sqlite3_test_control", - "sqlite3_thread_cleanup", - "sqlite3_threadsafe", - "sqlite3_total_changes", - "sqlite3_trace", - "sqlite3_trace_lua_callback", - "sqlite3_transfer_bindings", - "sqlite3_update_hook", - "sqlite3_update_hook_lua_callback", - "sqlite3_uri_boolean", - "sqlite3_uri_int64", - "sqlite3_uri_parameter", - "sqlite3_user_data", - "sqlite3_value_blob", - "sqlite3_value_bytes", - "sqlite3_value_bytes16", - "sqlite3_value_double", - "sqlite3_value_int", - "sqlite3_value_int64", - "sqlite3_value_numeric_type", - "sqlite3_value_p_array_getitem", - "sqlite3_value_p_array_setitem", - "sqlite3_value_text", - "sqlite3_value_text16", - "sqlite3_value_text16be", - "sqlite3_value_text16le", - "sqlite3_value_type", - "sqlite3_vfs", - "sqlite3_vfs_find", - "sqlite3_vfs_register", - "sqlite3_vfs_unregister", - "sqlite3_vtab", - "sqlite3_vtab_config", - "sqlite3_vtab_cursor", - "sqlite3_vtab_cursor_p_array_getitem", - "sqlite3_vtab_cursor_p_array_setitem", - "sqlite3_vtab_on_conflict", - "sqlite3_vtab_p_array_getitem", - "sqlite3_vtab_p_array_setitem", - "sqlite3_wal_autocheckpoint", - "sqlite3_wal_checkpoint", - "sqlite3_wal_checkpoint_v2", - "sqlite3_wal_hook", - "sqlite3_wal_hook_lua_callback", - "void_p_array_getitem", - "void_p_array_setitem", -} diff --git a/tex/compat/luaotfload/fontloader-swiglib-test.tex b/tex/compat/luaotfload/fontloader-swiglib-test.tex deleted file mode 100644 index d26bb6ffbb361c7a471373d3608e8c84166fc06b..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/fontloader-swiglib-test.tex +++ /dev/null @@ -1,11 +0,0 @@ -% luatex --fmt=luatex=plain luatex-swiglib-test.tex - -\input luatex-swiglib.tex - -\directlua { - dofile("luatex-swiglib-test.lua") -} - -\pdfximage {luatex-swiglib-test.jpg} \pdfrefximage\pdflastximage - -\end diff --git a/tex/compat/luaotfload/fontloader-swiglib.lua b/tex/compat/luaotfload/fontloader-swiglib.lua deleted file mode 100644 index 3108dd43fb823af48030ca959a80253ea0c7fba0..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/fontloader-swiglib.lua +++ /dev/null @@ -1,63 +0,0 @@ -if not modules then modules = { } end modules ['luatex-swiglib'] = { - version = 1.001, - comment = "companion to luatex-swiglib.tex", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -local savedrequire = require - -local libsuffix = os.type == "windows" and ".dll" or ".so" -local pathsplit = "([^" .. io.pathseparator .. "]+)" - -function requireswiglib(required,version) - local library = package.loaded[required] - if library then - return library - else - local name = string.gsub(required,"%.","/") .. libsuffix - local list = kpse.show_path("clua") - for root in string.gmatch(list,pathsplit) do - local full = false - if type(version) == "string" and version ~= "" then - full = root .. "/" .. version .. "/" .. name - full = lfs.isfile(full) and full - end - if not full then - full = root .. "/" .. name - full = lfs.isfile(full) and full - end - if full then - local path, base = string.match(full,"^(.-)([^\\/]+)" .. libsuffix .."$") - local savedlibrary = package.loaded[base] - package.loaded[base] = nil - local savedpath = lfs.currentdir() - lfs.chdir(path) - library = package.loadlib(full,"luaopen_" .. base) - if type(library) == "function" then - library = library() - texio.write("<swiglib: '",required,"' is loaded>") - end - lfs.chdir(savedpath) - package.loaded[base] = savedlibrary - package.loaded[required] = library - return library - end - end - texio.write("<swiglib: '",name,"'is not found on '",list,"'") - end - texio.write("<swiglib: '",required,"' is not found>") -end - -function require(name) - if string.find(name,"^swiglib%.") then - return requireswiglib(name) - else - return savedrequire(name) - end -end - -function swiglib(name,version) - return requireswiglib("swiglib." .. name,version) -end diff --git a/tex/compat/luaotfload/fontloader-swiglib.tex b/tex/compat/luaotfload/fontloader-swiglib.tex deleted file mode 100644 index 7c4377515879b92714ea5cb17461dec36c5edfa2..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/fontloader-swiglib.tex +++ /dev/null @@ -1,20 +0,0 @@ -%D \module -%D [ file=luatex-swiglib, -%D version=2013.03.30, -%D title=\LUATEX\ Support Macros, -%D subtitle=Generic \SWIGLIB\ Font Handler, -%D author=Hans Hagen, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] - -%D This is an experimental setup. Usage: -%D -%D \starttyping -%D local gm = swiglib("gmwand.core") -%D local gm = require("swiglib.gmwand.core") -%D local sq = swiglib("mysql.core") -%D local sq = swiglib("mysql.core","5.6") -%D \stoptyping - -\directlua { - dofile(kpse.find_file("luatex-swiglib.lua","tex")) -} diff --git a/tex/compat/luaotfload/fontloader-test.tex b/tex/compat/luaotfload/fontloader-test.tex deleted file mode 100644 index 2aa4f22d97565bb06c963d5a33c3f8376646dde4..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/fontloader-test.tex +++ /dev/null @@ -1,173 +0,0 @@ -% texformat=luatex-plain - -%D \module -%D [ file=luatex-test, -%D version=2009.12.01, -%D title=\LUATEX\ Support Macros, -%D subtitle=Simple Test File, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] - -%D See \type {luatex-plain.tex} (or on my machine \type {luatex.tex} -%D for how to make a format. - -% You can generate a font database with: -% -% mtxrun --script fonts --reload --save -% -% The file luatex-fonts-names.lua has to be moved to a place -% where kpse can find it. - -\pdfoutput=1 - -\font\testa=file:lmroman10-regular at 12pt \testa \input tufte \par -\font\testb=file:lmroman12-regular:+liga; at 24pt \testb effe flink fietsen \par -\font\testc=file:lmroman12-regular:mode=node;+liga; at 24pt \testc effe flink fietsen \par -\font\testd=name:lmroman10bold at 12pt \testd a bit bold \par - -\font\oeps=cmr10 - -\font\oeps=[lmroman12-regular]:+liga at 30pt \oeps crap -\font\oeps=[lmroman12-regular] at 40pt \oeps more crap - -\font\cidtest=adobesongstd-light - -\font\mathtest=cambria(math) {\mathtest 123} - -% \font\gothic=msgothic(ms-gothic) {\gothic whatever} % no longer in windows 10 - -\bgroup - - \ifdefined\pdfprotrudechars \pdfprotrudechars \else \protrudechars \fi 2 \relax - \ifdefined\pdfadjustspacing \pdfadjustspacing \else \adjustspacing \fi 2 \relax - - \font\testb=file:lmroman12-regular:+liga;extend=1.5 at 12pt \testb \input tufte \par - \font\testb=file:lmroman12-regular:+liga;slant=0.8 at 12pt \testb \input tufte \par - \font\testb=file:lmroman12-regular:+liga;protrusion=default at 12pt \testb \input tufte \par - -\egroup - -\setmplibformat{plain} - -\directlua { - function MpTest() - metapost.print("fullcircle scaled 3cm") - end -} - -\mplibcode - beginfig(1) ; - draw fullcircle - scaled 10cm - withcolor red - withpen pencircle xscaled 4mm yscaled 2mm rotated 30 ; - draw "test" infont defaultfont scaled 4 ; - verbatimtex \sl etex; - draw btex some more test etex scaled 2 ; - currentpicture := currentpicture shifted (0,1cm) ; - verbatimtex \bf etex; - draw btex another test etex scaled 2 ; - currentpicture := currentpicture shifted (0,1cm) ; - draw btex another test etex scaled 2 ; - draw - runscript("MpTest()") - withcolor green - withpen pencircle xscaled 2mm yscaled 1mm rotated 20 ; - endfig ; -\endmplibcode - -\font\mine=file:luatex-fonts-demo-vf-1.lua at 12pt - -\mine \input tufte \par - -% \font\mine=file:luatex-fonts-demo-vf-2.lua at 12pt \mine [abab] \par -% \font\mine=file:luatex-fonts-demo-vf-3.lua at 12pt \mine [abab] \par - -\font\test=dejavuserif:+kern at 10pt \test - - -\bgroup \hsize 1mm \noindent Циолковский \par \egroup - -\loadpatterns{ru} - -\bgroup \hsize 1mm \noindent Циолковский \par \egroup - -a bit of math - -$\it e=mc^2 \bf e=mc^2 \Uchar"1D49D$ - -$$\left( { {1} \over { {1} \over {x} } } \right) $$ - -$$\sqrt {2} { { {1} \over { {1} \over {x} } } } $$ - -\font\cows=file:koeieletters.afm at 50pt - -\cows Hello World! - -% math test - -\latinmodern - -\def\sqrt{\Uroot "0 "221A{}} - -\def\root#1\of{\Uroot "0 "221A{#1}} - -Inline $\sqrt{x}{1.2}$ math. % same for $\root n of x$ - -$\root3\of x$ - -$\sin{x}$ - -\lucidabright - -\def\sqrt{\Uroot "0 "221A{}} - -\def\root#1\of{\Uroot "0 "221A{#1}} - -Inline $\sqrt{x}{1.2}$ math. % same for $\root n of x$ - -$\root3\of x$ - -$\sin{x}$ - -\bgroup - - % drawback: no features (so use basemode) - - \font\crapa=lmroman12-regular:mode=base;liga=yes;kern=yes; at 12pt - \font\crapb=lmsans12-regular:mode=base;liga=yes;kern=yes; at 30pt - %\font\mine=file:luatex-fonts-demo-vf-4.lua:1=lmroman12-regular;2=lmsans12-regular{0x41-0x5A+0x30-0x39+0x21}; at 12pt - \font\mine=file:luatex-fonts-demo-vf-4.lua:1=\fontid\crapa;2=\fontid\crapb{0x41-0x5A+0x30-0x39+0x21}; at 12pt - - \crapa Test\par - \crapb Test\par - - \mine Zomaar een eindje fiets! En dan weer terug. - -\egroup - -% \font\amiri=file:amiri-regular.ttf:% -% mode=node;analyze=yes;language=dflt;script=arab;ccmp=yes;% -% init=yes;medi=yes;fina=yes;isol=yes;% -% mark=yes;mkmk=yes;kern=yes;curs=yes;% -% liga=yes;dlig=yes;rlig=yes;clig=yes;calt=yes % -% at 32pt - -% \bgroup -% \textdir TRT\amiri بِسْمِ اللَّـهِ الرَّحْمَـٰنِ الرَّحِيمِ -% \egroup - -% assumes csr10.tfm csr10.pfb csr.enc to be present - -% \font\foo=file:luatex-plain-tfm.lua:tfm=csr10;enc=csr;pfb=csr10 at 12pt -% -% \foo áäčďěíĺľňóôŕřšťúýž ff ffi - -% \font\foo=file:csr10.tfm:reencode=csr -% \font\foo=file:csr10.tfm:reencode=csr;bitmap=yes % use map file -% \font\foo=file:csr10.tfm:reencode=auto -% -% \foo áäčďěíĺľňóôŕřšťúýž ff ffi \input tufte\par - -\end diff --git a/tex/compat/luaotfload/fontloader-util-fil.lua b/tex/compat/luaotfload/fontloader-util-fil.lua deleted file mode 100644 index 0f9731a2656b5f9450381dfbdf6ad2ddd7c5369d..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/fontloader-util-fil.lua +++ /dev/null @@ -1,261 +0,0 @@ -if not modules then modules = { } end modules ['util-fil'] = { - version = 1.001, - comment = "companion to luat-lib.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -local byte = string.byte -local char = string.char -local extract = bit32 and bit32.extract -local floor = math.floor - --- Here are a few helpers (the starting point were old ones I used for parsing --- flac files). In Lua 5.3 we can probably do this better. Some code will move --- here. - -utilities = utilities or { } -local files = { } -utilities.files = files - -local zerobased = { } - -function files.open(filename,zb) - local f = io.open(filename,"rb") - if f then - zerobased[f] = zb or false - end - return f -end - -function files.close(f) - zerobased[f] = nil - f:close() -end - -function files.size(f) - return f:seek("end") -end - -files.getsize = files.size - -function files.setposition(f,n) - if zerobased[f] then - f:seek("set",n) - else - f:seek("set",n - 1) - end -end - -function files.getposition(f) - if zerobased[f] then - return f:seek() - else - return f:seek() + 1 - end -end - -function files.look(f,n,chars) - local p = f:seek() - local s = f:read(n) - f:seek("set",p) - if chars then - return s - else - return byte(s,1,#s) - end -end - -function files.skip(f,n) - if n == 1 then - f:read(n) - else - f:seek("set",f:seek()+n) - end -end - -function files.readbyte(f) - return byte(f:read(1)) -end - -function files.readbytes(f,n) - return byte(f:read(n),1,n) -end - -function files.readchar(f) - return f:read(1) -end - -function files.readstring(f,n) - return f:read(n or 1) -end - -function files.readinteger1(f) -- one byte - local n = byte(f:read(1)) - if n >= 0x80 then - -- return n - 0xFF - 1 - return n - 0x100 - else - return n - end -end - -files.readcardinal1 = files.readbyte -- one byte -files.readcardinal = files.readcardinal1 -files.readinteger = files.readinteger1 - -function files.readcardinal2(f) - local a, b = byte(f:read(2),1,2) - return 0x100 * a + b -end -function files.readcardinal2le(f) - local b, a = byte(f:read(2),1,2) - return 0x100 * a + b -end - -function files.readinteger2(f) - local a, b = byte(f:read(2),1,2) - local n = 0x100 * a + b - if n >= 0x8000 then - -- return n - 0xFFFF - 1 - return n - 0x10000 - else - return n - end -end -function files.readinteger2le(f) - local b, a = byte(f:read(2),1,2) - local n = 0x100 * a + b - if n >= 0x8000 then - -- return n - 0xFFFF - 1 - return n - 0x10000 - else - return n - end -end - -function files.readcardinal3(f) - local a, b, c = byte(f:read(3),1,3) - return 0x10000 * a + 0x100 * b + c -end -function files.readcardinal3le(f) - local c, b, a = byte(f:read(3),1,3) - return 0x10000 * a + 0x100 * b + c -end - -function files.readinteger3(f) - local a, b, c = byte(f:read(3),1,3) - local n = 0x10000 * a + 0x100 * b + c - if n >= 0x80000 then - -- return n - 0xFFFFFF - 1 - return n - 0x1000000 - else - return n - end -end -function files.readinteger3le(f) - local c, b, a = byte(f:read(3),1,3) - local n = 0x10000 * a + 0x100 * b + c - if n >= 0x80000 then - -- return n - 0xFFFFFF - 1 - return n - 0x1000000 - else - return n - end -end - -function files.readcardinal4(f) - local a, b, c, d = byte(f:read(4),1,4) - return 0x1000000 * a + 0x10000 * b + 0x100 * c + d -end -function files.readcardinal4le(f) - local d, c, b, a = byte(f:read(4),1,4) - return 0x1000000 * a + 0x10000 * b + 0x100 * c + d -end - -function files.readinteger4(f) - local a, b, c, d = byte(f:read(4),1,4) - local n = 0x1000000 * a + 0x10000 * b + 0x100 * c + d - if n >= 0x8000000 then - -- return n - 0xFFFFFFFF - 1 - return n - 0x100000000 - else - return n - end -end -function files.readinteger4le(f) - local d, c, b, a = byte(f:read(4),1,4) - local n = 0x1000000 * a + 0x10000 * b + 0x100 * c + d - if n >= 0x8000000 then - -- return n - 0xFFFFFFFF - 1 - return n - 0x100000000 - else - return n - end -end - -function files.readfixed4(f) - local a, b, c, d = byte(f:read(4),1,4) - local n = 0x100 * a + b - if n >= 0x8000 then - -- return n - 0xFFFF - 1 + (0x100 * c + d)/0xFFFF - return n - 0x10000 + (0x100 * c + d)/0xFFFF - else - return n + (0x100 * c + d)/0xFFFF - end -end - -if extract then - - function files.read2dot14(f) - local a, b = byte(f:read(2),1,2) - local n = 0x100 * a + b - local m = extract(n,0,30) - if n > 0x7FFF then - n = extract(n,30,2) - return m/0x4000 - 4 - else - n = extract(n,30,2) - return n + m/0x4000 - end - end - -end - -function files.skipshort(f,n) - f:read(2*(n or 1)) -end - -function files.skiplong(f,n) - f:read(4*(n or 1)) -end - --- writers (kind of slow) - -function files.writecardinal2(f,n) - local a = char(n % 256) - n = floor(n/256) - local b = char(n % 256) - f:write(b,a) -end - -function files.writecardinal4(f,n) - local a = char(n % 256) - n = floor(n/256) - local b = char(n % 256) - n = floor(n/256) - local c = char(n % 256) - n = floor(n/256) - local d = char(n % 256) - f:write(d,c,b,a) -end - -function files.writestring(f,s) - f:write(char(byte(s,1,#s))) -end - -function files.writebyte(f,b) - f:write(char(b)) -end - diff --git a/tex/compat/luaotfload/fontloader-util-str.lua b/tex/compat/luaotfload/fontloader-util-str.lua deleted file mode 100644 index fb510257a2f993b661d0d563afa3882f1e0ea1f8..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/fontloader-util-str.lua +++ /dev/null @@ -1,1151 +0,0 @@ -if not modules then modules = { } end modules ['util-str'] = { - version = 1.001, - comment = "companion to luat-lib.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -utilities = utilities or { } -utilities.strings = utilities.strings or { } -local strings = utilities.strings - -local format, gsub, rep, sub, find = string.format, string.gsub, string.rep, string.sub, string.find -local load, dump = load, string.dump -local tonumber, type, tostring = tonumber, type, tostring -local unpack, concat = table.unpack, table.concat -local P, V, C, S, R, Ct, Cs, Cp, Carg, Cc = lpeg.P, lpeg.V, lpeg.C, lpeg.S, lpeg.R, lpeg.Ct, lpeg.Cs, lpeg.Cp, lpeg.Carg, lpeg.Cc -local patterns, lpegmatch = lpeg.patterns, lpeg.match -local utfchar, utfbyte = utf.char, utf.byte ------ loadstripped = utilities.lua.loadstripped ------ setmetatableindex = table.setmetatableindex - -local loadstripped = nil - -if _LUAVERSION < 5.2 then - - loadstripped = function(str,shortcuts) - return load(str) - end - -else - - loadstripped = function(str,shortcuts) - if shortcuts then - return load(dump(load(str),true),nil,nil,shortcuts) - else - return load(dump(load(str),true)) - end - end - -end - --- todo: make a special namespace for the formatter - -if not number then number = { } end -- temp hack for luatex-fonts - -local stripper = patterns.stripzeros -local newline = patterns.newline -local endofstring = patterns.endofstring -local whitespace = patterns.whitespace -local spacer = patterns.spacer -local spaceortab = patterns.spaceortab - -local function points(n) - n = tonumber(n) - return (not n or n == 0) and "0pt" or lpegmatch(stripper,format("%.5fpt",n/65536)) -end - -local function basepoints(n) - n = tonumber(n) - return (not n or n == 0) and "0bp" or lpegmatch(stripper,format("%.5fbp", n*(7200/7227)/65536)) -end - -number.points = points -number.basepoints = basepoints - --- str = " \n \ntest \n test\ntest " --- print("["..string.gsub(string.collapsecrlf(str),"\n","+").."]") - -local rubish = spaceortab^0 * newline -local anyrubish = spaceortab + newline -local anything = patterns.anything -local stripped = (spaceortab^1 / "") * newline -local leading = rubish^0 / "" -local trailing = (anyrubish^1 * endofstring) / "" -local redundant = rubish^3 / "\n" - -local pattern = Cs(leading * (trailing + redundant + stripped + anything)^0) - -function strings.collapsecrlf(str) - return lpegmatch(pattern,str) -end - --- The following functions might end up in another namespace. - -local repeaters = { } -- watch how we also moved the -1 in depth-1 to the creator - -function strings.newrepeater(str,offset) - offset = offset or 0 - local s = repeaters[str] - if not s then - s = { } - repeaters[str] = s - end - local t = s[offset] - if t then - return t - end - t = { } - setmetatable(t, { __index = function(t,k) - if not k then - return "" - end - local n = k + offset - local s = n > 0 and rep(str,n) or "" - t[k] = s - return s - end }) - s[offset] = t - return t -end - --- local dashes = strings.newrepeater("--",-1) --- print(dashes[2],dashes[3],dashes[1]) - -local extra, tab, start = 0, 0, 4, 0 - -local nspaces = strings.newrepeater(" ") - -string.nspaces = nspaces - -local pattern = - Carg(1) / function(t) - extra, tab, start = 0, t or 7, 1 - end - * Cs(( - Cp() * patterns.tab / function(position) - local current = (position - start + 1) + extra - local spaces = tab-(current-1) % tab - if spaces > 0 then - extra = extra + spaces - 1 - return nspaces[spaces] -- rep(" ",spaces) - else - return "" - end - end - + newline * Cp() / function(position) - extra, start = 0, position - end - + patterns.anything - )^1) - -function strings.tabtospace(str,tab) - return lpegmatch(pattern,str,1,tab or 7) -end - --- local t = { --- "1234567123456712345671234567", --- "\tb\tc", --- "a\tb\tc", --- "aa\tbb\tcc", --- "aaa\tbbb\tccc", --- "aaaa\tbbbb\tcccc", --- "aaaaa\tbbbbb\tccccc", --- "aaaaaa\tbbbbbb\tcccccc\n aaaaaa\tbbbbbb\tcccccc", --- "one\n two\nxxx three\nxx four\nx five\nsix", --- } --- for k=1,#t do --- print(strings.tabtospace(t[k])) --- end - --- todo: lpeg - --- function strings.striplong(str) -- strips all leading spaces --- str = gsub(str,"^%s*","") --- str = gsub(str,"[\n\r]+ *","\n") --- return str --- end - -local space = spacer^0 -local nospace = space/"" -local endofline = nospace * newline - -local stripend = (whitespace^1 * endofstring)/"" - -local normalline = (nospace * ((1-space*(newline+endofstring))^1) * nospace) - -local stripempty = endofline^1/"" -local normalempty = endofline^1 -local singleempty = endofline * (endofline^0/"") -local doubleempty = endofline * endofline^-1 * (endofline^0/"") - -local stripstart = stripempty^0 - -local p_prune_normal = Cs ( stripstart * ( stripend + normalline + normalempty )^0 ) -local p_prune_collapse = Cs ( stripstart * ( stripend + normalline + doubleempty )^0 ) -local p_prune_noempty = Cs ( stripstart * ( stripend + normalline + singleempty )^0 ) -local p_retain_normal = Cs ( ( normalline + normalempty )^0 ) -local p_retain_collapse = Cs ( ( normalline + doubleempty )^0 ) -local p_retain_noempty = Cs ( ( normalline + singleempty )^0 ) - --- function striplines(str,prune,collapse,noempty) --- if prune then --- if noempty then --- return lpegmatch(p_prune_noempty,str) or str --- elseif collapse then --- return lpegmatch(p_prune_collapse,str) or str --- else --- return lpegmatch(p_prune_normal,str) or str --- end --- else --- if noempty then --- return lpegmatch(p_retain_noempty,str) or str --- elseif collapse then --- return lpegmatch(p_retain_collapse,str) or str --- else --- return lpegmatch(p_retain_normal,str) or str --- end --- end --- end - -local striplinepatterns = { - ["prune"] = p_prune_normal, - ["prune and collapse"] = p_prune_collapse, -- default - ["prune and no empty"] = p_prune_noempty, - ["retain"] = p_retain_normal, - ["retain and collapse"] = p_retain_collapse, - ["retain and no empty"] = p_retain_noempty, - ["collapse"] = patterns.collapser, -- how about: stripper fullstripper -} - -setmetatable(striplinepatterns,{ __index = function(t,k) return p_prune_collapse end }) - -strings.striplinepatterns = striplinepatterns - -function strings.striplines(str,how) - return str and lpegmatch(striplinepatterns[how],str) or str -end - --- also see: string.collapsespaces - -strings.striplong = strings.striplines -- for old times sake - --- local str = table.concat( { --- " ", --- " aap", --- " noot mies", --- " ", --- " ", --- " zus wim jet", --- "zus wim jet", --- " zus wim jet", --- " ", --- }, "\n") - --- local str = table.concat( { --- " aaaa", --- " bb", --- " cccccc", --- }, "\n") - --- for k, v in table.sortedhash(utilities.strings.striplinepatterns) do --- logs.report("stripper","method: %s, result: [[%s]]",k,utilities.strings.striplines(str,k)) --- end - --- inspect(strings.striplong([[ --- aaaa --- bb --- cccccc --- ]])) - -function strings.nice(str) - str = gsub(str,"[:%-+_]+"," ") -- maybe more - return str -end - --- Work in progress. Interesting is that compared to the built-in this is faster in --- luatex than in luajittex where we have a comparable speed. It only makes sense --- to use the formatter when a (somewhat) complex format is used a lot. Each formatter --- is a function so there is some overhead and not all formatted output is worth that --- overhead. Keep in mind that there is an extra function call involved. In principle --- we end up with a string concatination so one could inline such a sequence but often --- at the cost of less readabinity. So, it's a sort of (visual) compromise. Of course --- there is the benefit of more variants. (Concerning the speed: a simple format like --- %05fpt is better off with format than with a formatter, but as soon as you put --- something in front formatters become faster. Passing the pt as extra argument makes --- formatters behave better. Of course this is rather implementation dependent. Also, --- when a specific format is only used a few times the overhead in creating it is not --- compensated by speed.) --- --- More info can be found in cld-mkiv.pdf so here I stick to a simple list. --- --- integer %...i number --- integer %...d number --- unsigned %...u number --- character %...c number --- hexadecimal %...x number --- HEXADECIMAL %...X number --- octal %...o number --- string %...s string number --- float %...f number --- checked float %...F number --- exponential %...e number --- exponential %...E number --- autofloat %...g number --- autofloat %...G number --- utf character %...c number --- force tostring %...S any --- force tostring %Q any --- force tonumber %N number (strip leading zeros) --- signed number %I number --- rounded number %r number --- 0xhexadecimal %...h character number --- 0xHEXADECIMAL %...H character number --- U+hexadecimal %...u character number --- U+HEXADECIMAL %...U character number --- points %p number (scaled points) --- basepoints %b number (scaled points) --- table concat %...t table --- table concat %{.}t table --- serialize %...T sequenced (no nested tables) --- serialize %{.}T sequenced (no nested tables) --- boolean (logic) %l boolean --- BOOLEAN %L boolean --- whitespace %...w --- automatic %...a 'whatever' (string, table, ...) --- automatic %...A "whatever" (string, table, ...) - -local n = 0 - --- we are somewhat sloppy in parsing prefixes as it's not that critical - --- hard to avoid but we can collect them in a private namespace if needed - --- inline the next two makes no sense as we only use this in logging - -local sequenced = table.sequenced - -function string.autodouble(s,sep) - if s == nil then - return '""' - end - local t = type(s) - if t == "number" then - return tostring(s) -- tostring not really needed - end - if t == "table" then - return ('"' .. sequenced(s,sep or ",") .. '"') - end - return ('"' .. tostring(s) .. '"') -end - -function string.autosingle(s,sep) - if s == nil then - return "''" - end - local t = type(s) - if t == "number" then - return tostring(s) -- tostring not really needed - end - if t == "table" then - return ("'" .. sequenced(s,sep or ",") .. "'") - end - return ("'" .. tostring(s) .. "'") -end - -local tracedchars = { [0] = - -- the regular bunch - "[null]", "[soh]", "[stx]", "[etx]", "[eot]", "[enq]", "[ack]", "[bel]", - "[bs]", "[ht]", "[lf]", "[vt]", "[ff]", "[cr]", "[so]", "[si]", - "[dle]", "[dc1]", "[dc2]", "[dc3]", "[dc4]", "[nak]", "[syn]", "[etb]", - "[can]", "[em]", "[sub]", "[esc]", "[fs]", "[gs]", "[rs]", "[us]", - -- plus space - "[space]", -- 0x20 -} - -string.tracedchars = tracedchars -strings.tracers = tracedchars - -function string.tracedchar(b) - -- todo: table - if type(b) == "number" then - return tracedchars[b] or (utfchar(b) .. " (U+" .. format("%05X",b) .. ")") - else - local c = utfbyte(b) - return tracedchars[c] or (b .. " (U+" .. (c and format("%05X",c) or "?????") .. ")") - end -end - -function number.signed(i) - if i > 0 then - return "+", i - else - return "-", -i - end -end - --- maybe to util-num - -local digit = patterns.digit -local period = patterns.period -local three = digit * digit * digit - -local splitter = Cs ( - (((1 - (three^1 * period))^1 + C(three)) * (Carg(1) * three)^1 + C((1-period)^1)) - * (P(1)/"" * Carg(2)) * C(2) -) - -patterns.formattednumber = splitter - -function number.formatted(n,sep1,sep2) - local s = type(s) == "string" and n or format("%0.2f",n) - if sep1 == true then - return lpegmatch(splitter,s,1,".",",") - elseif sep1 == "." then - return lpegmatch(splitter,s,1,sep1,sep2 or ",") - elseif sep1 == "," then - return lpegmatch(splitter,s,1,sep1,sep2 or ".") - else - return lpegmatch(splitter,s,1,sep1 or ",",sep2 or ".") - end -end - --- print(number.formatted(1)) --- print(number.formatted(12)) --- print(number.formatted(123)) --- print(number.formatted(1234)) --- print(number.formatted(12345)) --- print(number.formatted(123456)) --- print(number.formatted(1234567)) --- print(number.formatted(12345678)) --- print(number.formatted(12345678,true)) --- print(number.formatted(1234.56,"!","?")) - -local zero = P("0")^1 / "" -local plus = P("+") / "" -local minus = P("-") -local separator = S(".") -local digit = R("09") -local trailing = zero^1 * #S("eE") -local exponent = (S("eE") * (plus + Cs((minus * zero^0 * P(-1))/"") + minus) * zero^0 * (P(-1) * Cc("0") + P(1)^1)) -local pattern_a = Cs(minus^0 * digit^1 * (separator/"" * trailing + separator * (trailing + digit)^0) * exponent) -local pattern_b = Cs((exponent + P(1))^0) - -function number.sparseexponent(f,n) - if not n then - n = f - f = "%e" - end - local tn = type(n) - if tn == "string" then -- cast to number - local m = tonumber(n) - if m then - return lpegmatch((f == "%e" or f == "%E") and pattern_a or pattern_b,format(f,m)) - end - elseif tn == "number" then - return lpegmatch((f == "%e" or f == "%E") and pattern_a or pattern_b,format(f,n)) - end - return tostring(n) -end - -local template = [[ -%s -%s -return function(%s) return %s end -]] - -local preamble, environment = "", { } - -if _LUAVERSION < 5.2 then - - preamble = [[ -local lpeg=lpeg -local type=type -local tostring=tostring -local tonumber=tonumber -local format=string.format -local concat=table.concat -local signed=number.signed -local points=number.points -local basepoints= number.basepoints -local utfchar=utf.char -local utfbyte=utf.byte -local lpegmatch=lpeg.match -local nspaces=string.nspaces -local tracedchar=string.tracedchar -local autosingle=string.autosingle -local autodouble=string.autodouble -local sequenced=table.sequenced -local formattednumber=number.formatted -local sparseexponent=number.sparseexponent - ]] - -else - - environment = { - global = global or _G, - lpeg = lpeg, - type = type, - tostring = tostring, - tonumber = tonumber, - format = string.format, - concat = table.concat, - signed = number.signed, - points = number.points, - basepoints = number.basepoints, - utfchar = utf.char, - utfbyte = utf.byte, - lpegmatch = lpeg.match, - nspaces = string.nspaces, - tracedchar = string.tracedchar, - autosingle = string.autosingle, - autodouble = string.autodouble, - sequenced = table.sequenced, - formattednumber = number.formatted, - sparseexponent = number.sparseexponent, - } - -end - --- -- -- - -local arguments = { "a1" } -- faster than previously used (select(n,...)) - -setmetatable(arguments, { __index = - function(t,k) - local v = t[k-1] .. ",a" .. k - t[k] = v - return v - end -}) - -local prefix_any = C((S("+- .") + R("09"))^0) -local prefix_tab = P("{") * C((1-P("}"))^0) * P("}") + C((1-R("az","AZ","09","%%"))^0) - --- we've split all cases as then we can optimize them (let's omit the fuzzy u) - --- todo: replace outer formats in next by .. - -local format_s = function(f) - n = n + 1 - if f and f ~= "" then - return format("format('%%%ss',a%s)",f,n) - else -- best no tostring in order to stay compatible (.. does a selective tostring too) - return format("(a%s or '')",n) -- goodie: nil check - end -end - -local format_S = function(f) -- can be optimized - n = n + 1 - if f and f ~= "" then - return format("format('%%%ss',tostring(a%s))",f,n) - else - return format("tostring(a%s)",n) - end -end - -local format_q = function() - n = n + 1 - return format("(a%s and format('%%q',a%s) or '')",n,n) -- goodie: nil check (maybe separate lpeg, not faster) -end - -local format_Q = function() -- can be optimized - n = n + 1 - return format("format('%%q',tostring(a%s))",n) -end - -local format_i = function(f) - n = n + 1 - if f and f ~= "" then - return format("format('%%%si',a%s)",f,n) - else - return format("format('%%i',a%s)",n) -- why not just tostring() - end -end - -local format_d = format_i - -local format_I = function(f) - n = n + 1 - return format("format('%%s%%%si',signed(a%s))",f,n) -end - -local format_f = function(f) - n = n + 1 - return format("format('%%%sf',a%s)",f,n) -end - --- The next one formats an integer as integer and very small values as zero. This is needed --- for pdf backend code. --- --- 1.23 % 1 : 0.23 --- - 1.23 % 1 : 0.77 --- --- We could probably use just %s with integers but who knows what Lua 5.3 will do? So let's --- for the moment use %i. - -local format_F = function(f) -- beware, no cast to number - n = n + 1 - if not f or f == "" then - return format("(((a%s > -0.0000000005 and a%s < 0.0000000005) and '0') or format((a%s %% 1 == 0) and '%%i' or '%%.9f',a%s))",n,n,n,n) - else - return format("format((a%s %% 1 == 0) and '%%i' or '%%%sf',a%s)",n,f,n) - end -end - -local format_g = function(f) - n = n + 1 - return format("format('%%%sg',a%s)",f,n) -end - -local format_G = function(f) - n = n + 1 - return format("format('%%%sG',a%s)",f,n) -end - -local format_e = function(f) - n = n + 1 - return format("format('%%%se',a%s)",f,n) -end - -local format_E = function(f) - n = n + 1 - return format("format('%%%sE',a%s)",f,n) -end - -local format_j = function(f) - n = n + 1 - return format("sparseexponent('%%%se',a%s)",f,n) -end - -local format_J = function(f) - n = n + 1 - return format("sparseexponent('%%%sE',a%s)",f,n) -end - -local format_x = function(f) - n = n + 1 - return format("format('%%%sx',a%s)",f,n) -end - -local format_X = function(f) - n = n + 1 - return format("format('%%%sX',a%s)",f,n) -end - -local format_o = function(f) - n = n + 1 - return format("format('%%%so',a%s)",f,n) -end - -local format_c = function() - n = n + 1 - return format("utfchar(a%s)",n) -end - -local format_C = function() - n = n + 1 - return format("tracedchar(a%s)",n) -end - -local format_r = function(f) - n = n + 1 - return format("format('%%%s.0f',a%s)",f,n) -end - -local format_h = function(f) - n = n + 1 - if f == "-" then - f = sub(f,2) - return format("format('%%%sx',type(a%s) == 'number' and a%s or utfbyte(a%s))",f == "" and "05" or f,n,n,n) - else - return format("format('0x%%%sx',type(a%s) == 'number' and a%s or utfbyte(a%s))",f == "" and "05" or f,n,n,n) - end -end - -local format_H = function(f) - n = n + 1 - if f == "-" then - f = sub(f,2) - return format("format('%%%sX',type(a%s) == 'number' and a%s or utfbyte(a%s))",f == "" and "05" or f,n,n,n) - else - return format("format('0x%%%sX',type(a%s) == 'number' and a%s or utfbyte(a%s))",f == "" and "05" or f,n,n,n) - end -end - -local format_u = function(f) - n = n + 1 - if f == "-" then - f = sub(f,2) - return format("format('%%%sx',type(a%s) == 'number' and a%s or utfbyte(a%s))",f == "" and "05" or f,n,n,n) - else - return format("format('u+%%%sx',type(a%s) == 'number' and a%s or utfbyte(a%s))",f == "" and "05" or f,n,n,n) - end -end - -local format_U = function(f) - n = n + 1 - if f == "-" then - f = sub(f,2) - return format("format('%%%sX',type(a%s) == 'number' and a%s or utfbyte(a%s))",f == "" and "05" or f,n,n,n) - else - return format("format('U+%%%sX',type(a%s) == 'number' and a%s or utfbyte(a%s))",f == "" and "05" or f,n,n,n) - end -end - -local format_p = function() - n = n + 1 - return format("points(a%s)",n) -end - -local format_b = function() - n = n + 1 - return format("basepoints(a%s)",n) -end - -local format_t = function(f) - n = n + 1 - if f and f ~= "" then - return format("concat(a%s,%q)",n,f) - else - return format("concat(a%s)",n) - end -end - -local format_T = function(f) - n = n + 1 - if f and f ~= "" then - return format("sequenced(a%s,%q)",n,f) - else - return format("sequenced(a%s)",n) - end -end - -local format_l = function() - n = n + 1 - return format("(a%s and 'true' or 'false')",n) -end - -local format_L = function() - n = n + 1 - return format("(a%s and 'TRUE' or 'FALSE')",n) -end - -local format_N = function() -- strips leading zeros - n = n + 1 - return format("tostring(tonumber(a%s) or a%s)",n,n) -end - -local format_a = function(f) - n = n + 1 - if f and f ~= "" then - return format("autosingle(a%s,%q)",n,f) - else - return format("autosingle(a%s)",n) - end -end - -local format_A = function(f) - n = n + 1 - if f and f ~= "" then - return format("autodouble(a%s,%q)",n,f) - else - return format("autodouble(a%s)",n) - end -end - -local format_w = function(f) -- handy when doing depth related indent - n = n + 1 - f = tonumber(f) - if f then -- not that useful - return format("nspaces[%s+a%s]",f,n) -- no real need for tonumber - else - return format("nspaces[a%s]",n) -- no real need for tonumber - end -end - -local format_W = function(f) -- handy when doing depth related indent - return format("nspaces[%s]",tonumber(f) or 0) -end - -local format_m = function(f) - n = n + 1 - if not f or f == "" then - f = "," - end - return format([[formattednumber(a%s,%q,".")]],n,f) -end - -local format_M = function(f) - n = n + 1 - if not f or f == "" then - f = "." - end - return format([[formattednumber(a%s,%q,",")]],n,f) -end - --- - -local format_z = function(f) - n = n + (tonumber(f) or 1) - return "''" -- okay, not that efficient to append '' but a special case anyway -end - --- - -local format_rest = function(s) - return format("%q",s) -- catches " and \n and such -end - -local format_extension = function(extensions,f,name) - local extension = extensions[name] or "tostring(%s)" - local f = tonumber(f) or 1 - local w = find(extension,"%.%.%.") - if f == 0 then - if w then - extension = gsub(extension,"%.%.%.","") - end - return extension - elseif f == 1 then - if w then - extension = gsub(extension,"%.%.%.","%%s") - end - n = n + 1 - local a = "a" .. n - return format(extension,a,a) -- maybe more times? - elseif f < 0 then - local a = "a" .. (n + f + 1) - return format(extension,a,a) - else - if w then - extension = gsub(extension,"%.%.%.",rep("%%s,",f-1).."%%s") - end - -- we could fill an array and then n = n + 1 unpack(t,n,n+f) but as we - -- cache we don't save much and there are hardly any extensions anyway - local t = { } - for i=1,f do - n = n + 1 - -- t[#t+1] = "a" .. n - t[i] = "a" .. n - end - return format(extension,unpack(t)) - end -end - --- aA b cC d eE f gG hH iI jJ lL mM N o p qQ r sS tT uU wW xX z - --- extensions : %!tag! - --- can be made faster but not called that often - -local builder = Cs { "start", - start = ( - ( - P("%") / "" - * ( - V("!") -- new - + V("s") + V("q") - + V("i") + V("d") - + V("f") + V("F") + V("g") + V("G") + V("e") + V("E") - + V("x") + V("X") + V("o") - -- - + V("c") - + V("C") - + V("S") -- new - + V("Q") -- new - + V("N") -- new - -- - + V("r") - + V("h") + V("H") + V("u") + V("U") - + V("p") + V("b") - + V("t") + V("T") - + V("l") + V("L") - + V("I") - + V("w") -- new - + V("W") -- new - + V("a") -- new - + V("A") -- new - + V("j") + V("J") -- stripped e E - + V("m") + V("M") -- new (formatted number) - + V("z") -- new - -- - -- + V("?") -- ignored, probably messed up % - ) - + V("*") - ) - * (P(-1) + Carg(1)) - )^0, - -- - ["s"] = (prefix_any * P("s")) / format_s, -- %s => regular %s (string) - ["q"] = (prefix_any * P("q")) / format_q, -- %q => regular %q (quoted string) - ["i"] = (prefix_any * P("i")) / format_i, -- %i => regular %i (integer) - ["d"] = (prefix_any * P("d")) / format_d, -- %d => regular %d (integer) - ["f"] = (prefix_any * P("f")) / format_f, -- %f => regular %f (float) - ["F"] = (prefix_any * P("F")) / format_F, -- %F => regular %f (float) but 0/1 check - ["g"] = (prefix_any * P("g")) / format_g, -- %g => regular %g (float) - ["G"] = (prefix_any * P("G")) / format_G, -- %G => regular %G (float) - ["e"] = (prefix_any * P("e")) / format_e, -- %e => regular %e (float) - ["E"] = (prefix_any * P("E")) / format_E, -- %E => regular %E (float) - ["x"] = (prefix_any * P("x")) / format_x, -- %x => regular %x (hexadecimal) - ["X"] = (prefix_any * P("X")) / format_X, -- %X => regular %X (HEXADECIMAL) - ["o"] = (prefix_any * P("o")) / format_o, -- %o => regular %o (octal) - -- - ["S"] = (prefix_any * P("S")) / format_S, -- %S => %s (tostring) - ["Q"] = (prefix_any * P("Q")) / format_S, -- %Q => %q (tostring) - ["N"] = (prefix_any * P("N")) / format_N, -- %N => tonumber (strips leading zeros) - ["c"] = (prefix_any * P("c")) / format_c, -- %c => utf character (extension to regular) - ["C"] = (prefix_any * P("C")) / format_C, -- %c => U+.... utf character - -- - ["r"] = (prefix_any * P("r")) / format_r, -- %r => round - ["h"] = (prefix_any * P("h")) / format_h, -- %h => 0x0a1b2 (when - no 0x) was v - ["H"] = (prefix_any * P("H")) / format_H, -- %H => 0x0A1B2 (when - no 0x) was V - ["u"] = (prefix_any * P("u")) / format_u, -- %u => u+0a1b2 (when - no u+) - ["U"] = (prefix_any * P("U")) / format_U, -- %U => U+0A1B2 (when - no U+) - ["p"] = (prefix_any * P("p")) / format_p, -- %p => 12.345pt / maybe: P (and more units) - ["b"] = (prefix_any * P("b")) / format_b, -- %b => 12.342bp / maybe: B (and more units) - ["t"] = (prefix_tab * P("t")) / format_t, -- %t => concat - ["T"] = (prefix_tab * P("T")) / format_T, -- %t => sequenced - ["l"] = (prefix_any * P("l")) / format_l, -- %l => boolean - ["L"] = (prefix_any * P("L")) / format_L, -- %L => BOOLEAN - ["I"] = (prefix_any * P("I")) / format_I, -- %I => signed integer - -- - ["w"] = (prefix_any * P("w")) / format_w, -- %w => n spaces (optional prefix is added) - ["W"] = (prefix_any * P("W")) / format_W, -- %W => mandate prefix, no specifier - -- - ["j"] = (prefix_any * P("j")) / format_j, -- %j => %e (float) stripped exponent (irrational) - ["J"] = (prefix_any * P("J")) / format_J, -- %J => %E (float) stripped exponent (irrational) - -- - ["m"] = (prefix_tab * P("m")) / format_m, -- %m => xxx.xxx.xxx,xx (optional prefix instead of .) - ["M"] = (prefix_tab * P("M")) / format_M, -- %M => xxx,xxx,xxx.xx (optional prefix instead of ,) - -- - ["z"] = (prefix_any * P("z")) / format_z, -- %M => xxx,xxx,xxx.xx (optional prefix instead of ,) - -- - ["a"] = (prefix_any * P("a")) / format_a, -- %a => '...' (forces tostring) - ["A"] = (prefix_any * P("A")) / format_A, -- %A => "..." (forces tostring) - -- - ["*"] = Cs(((1-P("%"))^1 + P("%%")/"%%")^1) / format_rest, -- rest (including %%) - ["?"] = Cs(((1-P("%"))^1 )^1) / format_rest, -- rest (including %%) - -- - ["!"] = Carg(2) * prefix_any * P("!") * C((1-P("!"))^1) * P("!") / format_extension, -} - --- we can be clever and only alias what is needed - --- local direct = Cs ( --- P("%")/"" --- * Cc([[local format = string.format return function(str) return format("%]]) --- * (S("+- .") + R("09"))^0 --- * S("sqidfgGeExXo") --- * Cc([[",str) end]]) --- * P(-1) --- ) - -local direct = Cs ( - P("%") - * (S("+- .") + R("09"))^0 - * S("sqidfgGeExXo") - * P(-1) / [[local format = string.format return function(str) return format("%0",str) end]] -) - -local function make(t,str) - local f - local p - local p = lpegmatch(direct,str) - if p then - -- f = loadstripped(p)() - -- print("builder 1 >",p) - f = loadstripped(p)() - else - n = 0 - -- p = lpegmatch(builder,str,1,"..",t._extensions_) -- after this we know n - p = lpegmatch(builder,str,1,t._connector_,t._extensions_) -- after this we know n - if n > 0 then - p = format(template,preamble,t._preamble_,arguments[n],p) - -- print("builder 2 >",p) - f = loadstripped(p,t._environment_)() -- t._environment is not populated (was experiment) - else - f = function() return str end - end - end - t[str] = f - return f -end - --- -- collect periodically --- --- local threshold = 1000 -- max nof cached formats --- --- local function make(t,str) --- local f = rawget(t,str) --- if f then --- return f --- end --- local parent = t._t_ --- if parent._n_ > threshold then --- local m = { _t_ = parent } --- getmetatable(parent).__index = m --- setmetatable(m, { __index = make }) --- else --- parent._n_ = parent._n_ + 1 --- end --- local f --- local p = lpegmatch(direct,str) --- if p then --- f = loadstripped(p)() --- else --- n = 0 --- p = lpegmatch(builder,str,1,"..",parent._extensions_) -- after this we know n --- if n > 0 then --- p = format(template,preamble,parent._preamble_,arguments[n],p) --- -- print("builder>",p) --- f = loadstripped(p)() --- else --- f = function() return str end --- end --- end --- t[str] = f --- return f --- end - -local function use(t,fmt,...) - return t[fmt](...) -end - -strings.formatters = { } - --- we cannot make these tables weak, unless we start using an indirect --- table (metatable) in which case we could better keep a count and --- clear that table when a threshold is reached - --- _connector_ is an experiment - -if _LUAVERSION < 5.2 then - - function strings.formatters.new(noconcat) - local t = { _type_ = "formatter", _connector_ = noconcat and "," or "..", _extensions_ = { }, _preamble_ = preamble, _environment_ = { } } - setmetatable(t, { __index = make, __call = use }) - return t - end - -else - - function strings.formatters.new(noconcat) - local e = { } -- better make a copy as we can overload - for k, v in next, environment do - e[k] = v - end - local t = { _type_ = "formatter", _connector_ = noconcat and "," or "..", _extensions_ = { }, _preamble_ = "", _environment_ = e } - setmetatable(t, { __index = make, __call = use }) - return t - end - -end - --- function strings.formatters.new() --- local t = { _extensions_ = { }, _preamble_ = "", _type_ = "formatter", _n_ = 0 } --- local m = { _t_ = t } --- setmetatable(t, { __index = m, __call = use }) --- setmetatable(m, { __index = make }) --- return t --- end - -local formatters = strings.formatters.new() -- the default instance - -string.formatters = formatters -- in the main string namespace -string.formatter = function(str,...) return formatters[str](...) end -- sometimes nicer name - -local function add(t,name,template,preamble) - if type(t) == "table" and t._type_ == "formatter" then - t._extensions_[name] = template or "%s" - if type(preamble) == "string" then - t._preamble_ = preamble .. "\n" .. t._preamble_ -- so no overload ! - elseif type(preamble) == "table" then - for k, v in next, preamble do - t._environment_[k] = v - end - end - end -end - -strings.formatters.add = add - --- registered in the default instance (should we fall back on this one?) - -patterns.xmlescape = Cs((P("<")/"<" + P(">")/">" + P("&")/"&" + P('"')/""" + P(1))^0) -patterns.texescape = Cs((C(S("#$%\\{}"))/"\\%1" + P(1))^0) -patterns.luaescape = Cs(((1-S('"\n'))^1 + P('"')/'\\"' + P('\n')/'\\n"')^0) -- maybe also \0 -patterns.luaquoted = Cs(Cc('"') * ((1-S('"\n'))^1 + P('"')/'\\"' + P('\n')/'\\n"')^0 * Cc('"')) - --- escaping by lpeg is faster for strings without quotes, slower on a string with quotes, but --- faster again when other q-escapables are found (the ones we don't need to escape) - --- add(formatters,"xml", [[lpegmatch(xmlescape,%s)]],[[local xmlescape = lpeg.patterns.xmlescape]]) --- add(formatters,"tex", [[lpegmatch(texescape,%s)]],[[local texescape = lpeg.patterns.texescape]]) --- add(formatters,"lua", [[lpegmatch(luaescape,%s)]],[[local luaescape = lpeg.patterns.luaescape]]) - -if _LUAVERSION < 5.2 then - - add(formatters,"xml",[[lpegmatch(xmlescape,%s)]],"local xmlescape = lpeg.patterns.xmlescape") - add(formatters,"tex",[[lpegmatch(texescape,%s)]],"local texescape = lpeg.patterns.texescape") - add(formatters,"lua",[[lpegmatch(luaescape,%s)]],"local luaescape = lpeg.patterns.luaescape") - -else - - add(formatters,"xml",[[lpegmatch(xmlescape,%s)]],{ xmlescape = lpeg.patterns.xmlescape }) - add(formatters,"tex",[[lpegmatch(texescape,%s)]],{ texescape = lpeg.patterns.texescape }) - add(formatters,"lua",[[lpegmatch(luaescape,%s)]],{ luaescape = lpeg.patterns.luaescape }) - -end - --- -- yes or no: --- --- local function make(t,str) --- local f --- local p = lpegmatch(direct,str) --- if p then --- f = loadstripped(p)() --- else --- n = 0 --- p = lpegmatch(builder,str,1,",") -- after this we know n --- if n > 0 then --- p = format(template,template_shortcuts,arguments[n],p) --- f = loadstripped(p)() --- else --- f = function() return str end --- end --- end --- t[str] = f --- return f --- end --- --- local formatteds = string.formatteds or { } --- string.formatteds = formatteds --- --- setmetatable(formatteds, { __index = make, __call = use }) - --- This is a somewhat silly one used in commandline reconstruction but the older --- method, using a combination of fine, gsub, quoted and unquoted was not that --- reliable. --- --- '"foo"bar \"and " whatever"' => "foo\"bar \"and \" whatever" --- 'foo"bar \"and " whatever' => "foo\"bar \"and \" whatever" - -local dquote = patterns.dquote -- P('"') -local equote = patterns.escaped + dquote / '\\"' + 1 -local space = patterns.space -local cquote = Cc('"') - -local pattern = - Cs(dquote * (equote - P(-2))^0 * dquote) -- we keep the outer but escape unescaped ones - + Cs(cquote * (equote - space)^0 * space * equote^0 * cquote) -- we escape unescaped ones - -function string.optionalquoted(str) - return lpegmatch(pattern,str) or str -end - -local pattern = Cs((newline / (os.newline or "\r") + 1)^0) - -function string.replacenewlines(str) - return lpegmatch(pattern,str) -end diff --git a/tex/compat/luaotfload/luaotfload-auxiliary.lua b/tex/compat/luaotfload/luaotfload-auxiliary.lua deleted file mode 100644 index 395f9b5b5193a5c6b2002bbb9e4bfca1d0e61c37..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/luaotfload-auxiliary.lua +++ /dev/null @@ -1,889 +0,0 @@ -#!/usr/bin/env texlua ------------------------------------------------------------------------ --- FILE: luaotfload-auxiliary.lua --- DESCRIPTION: part of luaotfload --- REQUIREMENTS: luaotfload 2.8 --- AUTHOR: Khaled Hosny, Élie Roux, Philipp Gesang ------------------------------------------------------------------------ --- - -luaotfload = luaotfload or { } -local log = luaotfload.log -local logreport = log.report -local fonthashes = fonts.hashes -local encodings = fonts.encodings -local identifiers = fonthashes.identifiers -local fontnames = fonts.names - -local fontid = font.id -local texsprint = tex.sprint - -local dofile = dofile -local getmetatable = getmetatable -local setmetatable = setmetatable -local utf8 = unicode.utf8 -local stringlower = string.lower -local stringformat = string.format -local stringgsub = string.gsub -local stringbyte = string.byte -local stringfind = string.find -local tablecopy = table.copy - -local aux = { } -local luaotfload_callbacks = { } - ------------------------------------------------------------------------ ---- font patches ------------------------------------------------------------------------ - ---- https://github.com/khaledhosny/luaotfload/issues/54 - -local rewrite_fontname = function (tfmdata, specification) - local format = tfmdata.format or tfmdata.properties.format - if stringfind (specification, " ") then - tfmdata.name = stringformat ("%q", specification) - else - --- other specs should parse just fine - tfmdata.name = specification - end -end - -local rewriting = false - -local start_rewrite_fontname = function () - if rewriting == false then - luatexbase.add_to_callback ( - "luaotfload.patch_font", - rewrite_fontname, - "luaotfload.rewrite_fontname") - rewriting = true - logreport ("log", 1, "aux", - "start rewriting tfmdata.name field") - end -end - -aux.start_rewrite_fontname = start_rewrite_fontname - -local stop_rewrite_fontname = function () - if rewriting == true then - luatexbase.remove_from_callback - ("luaotfload.patch_font", "luaotfload.rewrite_fontname") - rewriting = false - logreport ("log", 1, "aux", - "stop rewriting tfmdata.name field") - end -end - -aux.stop_rewrite_fontname = stop_rewrite_fontname - - ---[[doc-- -This sets two dimensions apparently relied upon by the unicode-math -package. ---doc]]-- - -local set_sscale_dimens = function (fontdata) - local resources = fontdata.resources if not resources then return end - local mathconstants = resources.MathConstants if not mathconstants then return end - local parameters = fontdata.parameters if not parameters then return end - --- the default values below are complete crap - parameters [10] = mathconstants.ScriptPercentScaleDown or 70 - parameters [11] = mathconstants.ScriptScriptPercentScaleDown or 50 -end - -luaotfload_callbacks [#luaotfload_callbacks + 1] = { - "patch_font", set_sscale_dimens, "set_sscale_dimens", -} - -local default_units = 1000 - ---- fontobj -> int -local lookup_units = function (fontdata) - local units = fontdata.units - if units and units > 0 then return units end - local shared = fontdata.shared if not shared then return default_units end - local rawdata = shared.rawdata if not rawdata then return default_units end - local metadata = rawdata.metadata if not metadata then return default_units end - local capheight = metadata.capheight if not capheight then return default_units end - local units = metadata.units or fontdata.units - if not units or units == 0 then - return default_units - end - return units -end - ---[[doc-- -This callback corrects some values of the Cambria font. ---doc]]-- ---- fontobj -> unit -local patch_cambria_domh = function (fontdata) - local mathconstants = fontdata.MathConstants - if mathconstants and fontdata.psname == "CambriaMath" then - --- my test Cambria has 2048 - local units = fontdata.units or lookup_units(fontdata) - local sz = fontdata.parameters.size or fontdata.size - local mh = 2800 / units * sz - if mathconstants.DisplayOperatorMinHeight < mh then - mathconstants.DisplayOperatorMinHeight = mh - end - end -end - -luaotfload_callbacks [#luaotfload_callbacks + 1] = { - "patch_font", patch_cambria_domh, "patch_cambria_domh", -} - - ---[[doc-- - - Add missing field to fonts that lack it. Addresses issue - https://github.com/lualatex/luaotfload/issues/253 - - This is considered a hack, especially since importing the - unicode-math package fixes the problem quite nicely. - ---doc]]-- - ---- fontobj -> unit -local fixup_fontdata = function (data) - - local t = type (data) - --- Some OT fonts like Libertine R lack the resources table, causing - --- the fontloader to nil-index. - if t == "table" then - if data and not data.resources then data.resources = { } end - end - -end - -luaotfload_callbacks [#luaotfload_callbacks + 1] = { - "patch_font_unsafe", fixup_fontdata, "fixup_fontdata", -} - - ---[[doc-- - -Comment from fontspec: - - “Here we patch fonts tfm table to emulate \XeTeX's \cs{fontdimen8}, - which stores the caps-height of the font. (Cf.\ \cs{fontdimen5} which - stores the x-height.) - - Falls back to measuring the glyph if the font doesn't contain the - necessary information. - This needs to be extended for fonts that don't contain an `X'.” - ---doc]]-- - -local capheight_reference_chars = { "X", "M", "Ж", "ξ", } -local capheight_reference_codepoints do - local utfbyte = unicode.utf8.byte - capheight_reference_codepoints = { } - for i = 1, #capheight_reference_chars do - local chr = capheight_reference_chars [i] - capheight_reference_codepoints [i] = utfbyte (chr) - end -end - -local determine_capheight = function (fontdata) - local parameters = fontdata.parameters if not parameters then return false end - local characters = fontdata.characters if not characters then return false end - --- Pretty simplistic but it does return *some* value for most fonts; - --- we could also refine the approach to return some kind of average - --- of all capital letters or a user-provided subset. - for i = 1, #capheight_reference_codepoints do - local refcp = capheight_reference_codepoints [i] - local refchar = characters [refcp] - if refchar then - logreport ("both", 4, "aux", - "picked height of character ‘%s’ (U+%d) as \\fontdimen8 \z - candidate", - capheight_reference_chars [i], refcp) - return refchar.height - end - end - return false -end - -local query_ascender = function (fontdata) - local parameters = fontdata.parameters if not parameters then return false end - local ascender = parameters.ascender - if ascender then - return ascender --- pre-scaled - end - - local shared = fontdata.shared if not shared then return false end - local rawdata = shared.rawdata if not rawdata then return false end - local metadata = rawdata.metadata if not metadata then return false end - ascender = metadata.ascender if not ascender then return false end - local size = parameters.size if not size then return false end - local units = lookup_units (fontdata) - if not units or units == 0 then return false end - return ascender * size / units --- scaled -end - -local query_capheight = function (fontdata) - local parameters = fontdata.parameters if not parameters then return false end - local shared = fontdata.shared if not shared then return false end - local rawdata = shared.rawdata if not rawdata then return false end - local metadata = rawdata.metadata if not metadata then return false end - local capheight = metadata.capheight if not capheight then return false end - local size = parameters.size if not size then return false end - local units = lookup_units (fontdata) - if not units or units == 0 then return false end - return capheight * size / units -end - -local query_fontdimen8 = function (fontdata) - local parameters = fontdata.parameters if not parameters then return false end - local fontdimen8 = parameters [8] - if fontdimen8 then return fontdimen8 end - return false -end - -local caphtfmt = function (ref, ht) - if not ht then return "<none>" end - if not ref then return tostring (ht) end - return stringformat ("%s(δ=%s)", ht, ht - ref) -end - -local set_capheight = function (fontdata) - if not fontdata then - logreport ("both", 0, "aux", - "error: set_capheight() received garbage") - return - end - local capheight_dimen8 = query_fontdimen8 (fontdata) - local capheight_alleged = query_capheight (fontdata) - local capheight_ascender = query_ascender (fontdata) - local capheight_measured = determine_capheight (fontdata) - logreport ("term", 4, "aux", - "capht: param[8]=%s advertised=%s ascender=%s measured=%s", - tostring (capheight_dimen8), - caphtfmt (capheight_dimen8, capheight_alleged), - caphtfmt (capheight_dimen8, capheight_ascender), - caphtfmt (capheight_dimen8, capheight_measured)) - if capheight_dimen8 then --- nothing to do - return - end - - local capheight = capheight_alleged or capheight_ascender or capheight_measured - if capheight then - fontdata.parameters [8] = capheight - end -end - -luaotfload_callbacks [#luaotfload_callbacks + 1] = { - "patch_font", set_capheight, "set_capheight", -} - ------------------------------------------------------------------------ ---- glyphs and characters ------------------------------------------------------------------------ - ---- int -> int -> bool -local font_has_glyph = function (font_id, codepoint) - local fontdata = fonts.hashes.identifiers[font_id] - if fontdata then - if fontdata.characters[codepoint] ~= nil then return true end - end - return false -end - -aux.font_has_glyph = font_has_glyph - ---- undocumented - -local raw_slot_of_name = function (font_id, glyphname) - local fontdata = font.fonts[font_id] - if fontdata.type == "virtual" then --- get base font for glyph idx - local codepoint = encodings.agl.unicodes[glyphname] - local glyph = fontdata.characters[codepoint] - if fontdata.characters[codepoint] then - return codepoint - end - end - return false -end - ---[[doc-- - - This one is approximately “name_to_slot” from the microtype package; - note that it is all about Adobe Glyph names and glyph slots in the - font. The names and values may diverge from actual Unicode. - - http://www.adobe.com/devnet/opentype/archives/glyph.html - - The “unsafe” switch triggers a fallback lookup in the raw fonts - table. As some of the information is stored as references, this may - have unpredictable side-effects. - ---doc]]-- - ---- int -> string -> bool -> (int | false) -local slot_of_name = function (font_id, glyphname, unsafe) - if not font_id or type (font_id) ~= "number" - or not glyphname or type (glyphname) ~= "string" - then - logreport ("both", 0, "aux", - "invalid parameters to slot_of_name (%s, %s)", - tostring (font_id), tostring (glyphname)) - return false - end - - local tfmdata = identifiers [font_id] - if not tfmdata then return raw_slot_of_name (font_id, glyphname) end - local resources = tfmdata.resources if not resources then return false end - local unicodes = resources.unicodes if not unicodes then return false end - - local unicode = unicodes [glyphname] - if unicode then - if type (unicode) == "number" then - return unicode - else - return unicode [1] --- for multiple components - end - end - return false -end - -aux.slot_of_name = slot_of_name - ---[[doc-- - - Inverse of above; not authoritative as to my knowledge the official - inverse of the AGL is the AGLFN. Maybe this whole issue should be - dealt with in a separate package that loads char-def.lua and thereby - solves the problem for the next couple decades. - - http://partners.adobe.com/public/developer/en/opentype/aglfn13.txt - ---doc]]-- - -local indices - ---- int -> (string | false) -local name_of_slot = function (codepoint) - if not codepoint or type (codepoint) ~= "number" then - logreport ("both", 0, "aux", - "invalid parameters to name_of_slot (%s)", - tostring (codepoint)) - return false - end - - if not indices then --- this will load the glyph list - local unicodes = encodings.agl.unicodes - if not unicodes or not next (unicodes)then - logreport ("both", 0, "aux", - "name_of_slot: failed to load the AGL.") - end - indices = table.swapped (unicodes) - end - - local glyphname = indices [codepoint] - if glyphname then - return glyphname - end - return false -end - -aux.name_of_slot = name_of_slot - - ------------------------------------------------------------------------ ---- features / scripts / languages ------------------------------------------------------------------------ ---- lots of arrowcode ahead - -local get_features = function (tfmdata) - local resources = tfmdata.resources if not resources then return false end - local features = resources.features if not features then return false end - return features -end - ---[[doc-- -This function, modeled after “check_script()” from fontspec, returns -true if in the given font, the script “asked_script” is accounted for in at -least one feature. ---doc]]-- - ---- int -> string -> bool -local provides_script = function (font_id, asked_script) - if not font_id or type (font_id) ~= "number" - or not asked_script or type (asked_script) ~= "string" - then - logreport ("both", 0, "aux", - "invalid parameters to provides_script(%s, %s)", - tostring (font_id), tostring (asked_script)) - return false - end - asked_script = stringlower(asked_script) - if font_id and font_id > 0 then - local tfmdata = identifiers[font_id] - if not tfmdata then return false end - local features = get_features (tfmdata) - if features == false then - logreport ("log", 1, "aux", "font no %d lacks a features table", font_id) - return false - end - for method, featuredata in next, features do - --- where method: "gpos" | "gsub" - for feature, data in next, featuredata do - if data[asked_script] then - logreport ("log", 1, "aux", - "font no %d (%s) defines feature %s for script %s", - font_id, fontname, feature, asked_script) - return true - end - end - end - logreport ("log", 0, "aux", - "font no %d (%s) defines no feature for script %s", - font_id, fontname, asked_script) - end - logreport ("log", 0, "aux", "no font with id %d", font_id) - return false -end - -aux.provides_script = provides_script - ---[[doc-- -This function, modeled after “check_language()” from fontspec, returns -true if in the given font, the language with tage “asked_language” is -accounted for in the script with tag “asked_script” in at least one -feature. ---doc]]-- - ---- int -> string -> string -> bool -local provides_language = function (font_id, asked_script, asked_language) - if not font_id or type (font_id) ~= "number" - or not asked_script or type (asked_script) ~= "string" - or not asked_language or type (asked_language) ~= "string" - then - logreport ("both", 0, "aux", - "invalid parameters to provides_language(%s, %s, %s)", - tostring (font_id), - tostring (asked_script), - tostring (asked_language)) - return false - end - asked_script = stringlower(asked_script) - asked_language = stringlower(asked_language) - if font_id and font_id > 0 then - local tfmdata = identifiers[font_id] - if not tfmdata then return false end - local features = get_features (tfmdata) - if features == false then - logreport ("log", 1, "aux", "font no %d lacks a features table", font_id) - return false - end - for method, featuredata in next, features do - --- where method: "gpos" | "gsub" - for feature, data in next, featuredata do - local scriptdata = data[asked_script] - if scriptdata and scriptdata[asked_language] then - logreport ("log", 1, "aux", - "font no %d (%s) defines feature %s " - .. "for script %s with language %s", - font_id, fontname, feature, - asked_script, asked_language) - return true - end - end - end - logreport ("log", 0, "aux", - "font no %d (%s) defines no feature " - .. "for script %s with language %s", - font_id, fontname, asked_script, asked_language) - end - logreport ("log", 0, "aux", "no font with id %d", font_id) - return false -end - -aux.provides_language = provides_language - ---[[doc-- -We strip the syntax elements from feature definitions (shouldn’t -actually be there in the first place, but who cares ...) ---doc]]-- - -local lpeg = require"lpeg" -local C, P, S = lpeg.C, lpeg.P, lpeg.S -local lpegmatch = lpeg.match - -local sign = S"+-" -local rhs = P"=" * P(1)^0 * P(-1) -local strip_garbage = sign^-1 * C((1 - rhs)^1) - ---s = "+foo" --> foo ---ss = "-bar" --> bar ---sss = "baz" --> baz ---t = "foo=bar" --> foo ---tt = "+bar=baz" --> bar ---ttt = "-baz=true" --> baz --- ---print(lpeg.match(strip_garbage, s)) ---print(lpeg.match(strip_garbage, ss)) ---print(lpeg.match(strip_garbage, sss)) ---print(lpeg.match(strip_garbage, t)) ---print(lpeg.match(strip_garbage, tt)) ---print(lpeg.match(strip_garbage, ttt)) - ---[[doc-- -This function, modeled after “check_feature()” from fontspec, returns -true if in the given font, the language with tag “asked_language” is -accounted for in the script with tag “asked_script” in feature -“asked_feature”. ---doc]]-- - ---- int -> string -> string -> string -> bool -local provides_feature = function (font_id, asked_script, - asked_language, asked_feature) - if not font_id or type (font_id) ~= "number" - or not asked_script or type (asked_script) ~= "string" - or not asked_language or type (asked_language) ~= "string" - or not asked_feature or type (asked_feature) ~= "string" - then - logreport ("both", 0, "aux", - "invalid parameters to provides_feature(%s, %s, %s, %s)", - tostring (font_id), tostring (asked_script), - tostring (asked_language), tostring (asked_feature)) - return false - end - asked_script = stringlower(asked_script) - asked_language = stringlower(asked_language) - asked_feature = lpegmatch(strip_garbage, asked_feature) - - if font_id and font_id > 0 then - local tfmdata = identifiers[font_id] - if not tfmdata then return false end - local features = get_features (tfmdata) - if features == false then - logreport ("log", 1, "aux", "font no %d lacks a features table", font_id) - return false - end - for method, featuredata in next, features do - --- where method: "gpos" | "gsub" - local feature = featuredata[asked_feature] - if feature then - local scriptdata = feature[asked_script] - if scriptdata and scriptdata[asked_language] then - logreport ("log", 1, "aux", - "font no %d (%s) defines feature %s " - .. "for script %s with language %s", - font_id, fontname, asked_feature, - asked_script, asked_language) - return true - end - end - end - logreport ("log", 0, "aux", - "font no %d (%s) does not define feature %s for script %s with language %s", - font_id, fontname, asked_feature, asked_script, asked_language) - end - logreport ("log", 0, "aux", "no font with id %d", font_id) - return false -end - -aux.provides_feature = provides_feature - ------------------------------------------------------------------------ ---- font dimensions ------------------------------------------------------------------------ - ---- int -> string -> int -local get_math_dimension = function (font_id, dimenname) - if type(font_id) == "string" then - font_id = fontid(font_id) --- safeguard - end - local fontdata = identifiers[font_id] - local mathdata = fontdata.mathparameters - if mathdata then - return mathdata[dimenname] or 0 - end - return 0 -end - -aux.get_math_dimension = get_math_dimension - ---- int -> string -> unit -local sprint_math_dimension = function (font_id, dimenname) - if type(font_id) == "string" then - font_id = fontid(font_id) - end - local dim = get_math_dimension(font_id, dimenname) - texsprint(luatexbase.catcodetables["latex-package"], dim, "sp") -end - -aux.sprint_math_dimension = sprint_math_dimension - ------------------------------------------------------------------------ ---- extra database functions ------------------------------------------------------------------------ - -local namesresolve = fontnames.resolve -local namesscan_dir = fontnames.scan_dir - ---[====[-- TODO -> port this to new db model - ---- local directories ------------------------------------------------- - ---- migrated from luaotfload-database.lua ---- https://github.com/lualatex/luaotfload/pull/61#issuecomment-17776975 - ---- string -> (int * int) -local scan_external_dir = function (dir) - local old_names, new_names = names.data() - if not old_names then - old_names = load_names() - end - new_names = tablecopy(old_names) - local n_scanned, n_new = scan_dir(dir, old_names, new_names) - --- FIXME - --- This doesn’t seem right. If a db update is triggered after this - --- point, then the added fonts will be saved along with it -- - --- which is not as “temporarily” as it should be. (This should be - --- addressed during a refactoring of names_resolve().) - names.data = new_names - return n_scanned, n_new -end - -aux.scan_external_dir = scan_external_dir - ---]====]-- - -aux.scan_external_dir = function () - print "ERROR: scan_external_dir() is not implemented" -end - ---- db queries -------------------------------------------------------- - ---- https://github.com/lualatex/luaotfload/issues/74 ---- string -> (string * int) -local resolve_fontname = function (name) - local foundname, subfont, success = namesresolve(nil, nil, { - name = name, - lookup = "name", - optsize = 0, - specification = "name:" .. name, - }) - if success then - return foundname, subfont - end - return false, false -end - -aux.resolve_fontname = resolve_fontname - ---- string list -> (string * int) -local resolve_fontlist -resolve_fontlist = function (names, n) - if not n then - return resolve_fontlist(names, 1) - end - local this = names[n] - if this then - local foundname, subfont = resolve_fontname(this) - if foundname then - return foundname, subfont - end - return resolve_fontlist(names, n+1) - end - return false, false -end - -aux.resolve_fontlist = resolve_fontlist - ---- index access ------------------------------------------------------ - ---- Based on a discussion on the Luatex mailing list: ---- http://tug.org/pipermail/luatex/2014-June/004881.html - ---[[doc-- - - aux.read_font_index -- Read the names index from the canonical - location and return its contents. This does not affect the behavior - of Luaotfload: The returned table is independent of what the font - resolvers use internally. Access is raw: each call to the function - will result in the entire table being re-read from disk. - ---doc]]-- - -local load_names = fontnames.load -local access_font_index = fontnames.access_font_index - -local read_font_index = function () - return load_names (true) or { } -end - ---[[doc-- - - aux.font_index -- Access Luaotfload’s internal database. If the - database hasn’t been loaded yet this will cause it to be loaded, with - all the possible side-effects like for instance creating the index - file if it doesn’t exist, reading all font files, &c. - ---doc]]-- - -local font_index = function () return access_font_index () end - -aux.read_font_index = read_font_index -aux.font_index = font_index - ---- loaded fonts ------------------------------------------------------ - ---- just a proof of concept - ---- fontobj -> string list -> (string list) list -local get_font_data get_font_data = function (tfmdata, keys, acc, n) - if not acc then - return get_font_data(tfmdata, keys, {}, 1) - end - local key = keys[n] - if key then - local val = tfmdata[key] - if val then - acc[#acc+1] = val - else - acc[#acc+1] = false - end - return get_font_data(tfmdata, keys, acc, n+1) - end - return acc -end - ---[[doc-- - - The next one operates on the fonts.hashes.identifiers table. - It returns a list containing tuples of font ids and the - contents of the fields specified in the first argument. - Font table entries that were created indirectly -- e.g. by - \letterspacefont or during font expansion -- will not be - listed. - ---doc]]-- - -local default_keys = { "fullname" } - ---- string list -> (int * string list) list -local get_loaded_fonts get_loaded_fonts = function (keys, acc, lastid) - if not acc then - if not keys then - keys = default_keys - end - return get_loaded_fonts(keys, {}, lastid) - end - local id, tfmdata = next(identifiers, lastid) - if id then - local data = get_font_data(tfmdata, keys) - acc[#acc+1] = { id, data } - return get_loaded_fonts (keys, acc, id) - end - return acc -end - -aux.get_loaded_fonts = get_loaded_fonts - ---- Raw access to the font.* namespace is unsafe so no documentation on ---- this one. -local get_raw_fonts = function ( ) - local res = { } - for i, v in font.each() do - if v.filename then - res[#res+1] = { i, v } - end - end - return res -end - -aux.get_raw_fonts = get_raw_fonts - ------------------------------------------------------------------------ ---- font parameters ------------------------------------------------------------------------ ---- analogy of font-hsh - -fonthashes.parameters = fonthashes.parameters or { } -fonthashes.quads = fonthashes.quads or { } - -local parameters = fonthashes.parameters or { } -local quads = fonthashes.quads or { } - -setmetatable(parameters, { __index = function (t, font_id) - local tfmdata = identifiers[font_id] - if not tfmdata then --- unsafe; avoid - tfmdata = font.fonts[font_id] - end - if tfmdata and type(tfmdata) == "table" then - local fontparameters = tfmdata.parameters - t[font_id] = fontparameters - return fontparameters - end - return nil -end}) - ---[[doc-- - - Note that the reason as to why we prefer functions over table indices - is that functions are much safer against unintended manipulation. - This justifies the overhead they cost. - ---doc]]-- - ---- int -> (number | false) -local get_quad = function (font_id) - local quad = quads[font_id] - if quad then - return quad - end - local fontparameters = parameters[font_id] - if fontparameters then - local quad = fontparameters.quad or 0 - quads[font_id] = quad - return quad - end - return false -end - -aux.get_quad = get_quad - - ------------------------------------------------------------------------ ---- initialization ------------------------------------------------------------------------ - -local inject_callbacks = function (lst) - if not lst and next (lst) then return false end - - local inject = function (def) - local cb, fn, id = unpack (def) - cb = tostring (cb) - id = tostring (id) - if not cb or not fn or not id or not type (fn) == "function" then - logreport ("both", 0, "aux", "Invalid callback requested (%q, %s, %q).", - cb, tostring (fn), id) - return false - end - cb = stringformat ("luaotfload.%s", cb) - id = stringformat ("luaotfload.aux.%s", id) - logreport ("log", 5, "aux", "Installing callback %q->%q.", cb, id) - luatexbase.add_to_callback (cb, fn, id) - return true - end - - local ret = true - for i = 1, #lst do ret = inject (lst [i]) end - return ret -end - -return { - init = function () - local ret = true - luaotfload.aux = aux - ret = inject_callbacks (luaotfload_callbacks) - return ret - end -} - --- vim:tw=79:sw=2:ts=8:et - diff --git a/tex/compat/luaotfload/luaotfload-blacklist.cnf b/tex/compat/luaotfload/luaotfload-blacklist.cnf deleted file mode 100644 index e82669b9f872dc46da662f4a3ffef3b03abe7f03..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/luaotfload-blacklist.cnf +++ /dev/null @@ -1,4 +0,0 @@ -spltfgbd.ttf -spltfgbi.ttf -spltfgit.ttf -spltfgrg.ttf diff --git a/tex/compat/luaotfload/luaotfload-characters.lua b/tex/compat/luaotfload/luaotfload-characters.lua deleted file mode 100644 index 258a5aee649e994149db5c672635be847b1c7672..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/luaotfload-characters.lua +++ /dev/null @@ -1,122491 +0,0 @@ -return { - [0x0]={ - category="cc", - direction="bn", - }, - { - category="cc", - direction="bn", - }, - { - category="cc", - direction="bn", - }, - { - category="cc", - direction="bn", - }, - { - category="cc", - direction="bn", - }, - { - category="cc", - direction="bn", - }, - { - category="cc", - direction="bn", - }, - { - category="cc", - direction="bn", - }, - { - category="cc", - direction="bn", - }, - { - category="cc", - direction="s", - }, - { - category="cc", - direction="b", - }, - { - category="cc", - direction="s", - }, - { - category="cc", - direction="ws", - }, - { - category="cc", - direction="b", - }, - { - category="cc", - direction="bn", - }, - { - category="cc", - direction="bn", - }, - { - category="cc", - direction="bn", - }, - { - category="cc", - direction="bn", - }, - { - category="cc", - direction="bn", - }, - { - category="cc", - direction="bn", - }, - { - category="cc", - direction="bn", - }, - { - category="cc", - direction="bn", - }, - { - category="cc", - direction="bn", - }, - { - category="cc", - direction="bn", - }, - { - category="cc", - direction="bn", - }, - { - category="cc", - direction="bn", - }, - { - category="cc", - direction="bn", - }, - { - category="cc", - direction="bn", - }, - { - category="cc", - direction="b", - }, - { - category="cc", - direction="b", - }, - { - category="cc", - direction="b", - }, - { - category="cc", - direction="s", - }, - { - category="zs", - direction="ws", - }, - { - category="po", - direction="on", - }, - { - category="po", - direction="on", - }, - { - category="po", - direction="et", - }, - { - category="sc", - direction="et", - }, - { - category="po", - direction="et", - }, - { - category="po", - direction="on", - }, - { - category="po", - direction="on", - }, - { - category="ps", - direction="on", - mirror=0x29, - textclass="open", - }, - { - category="pe", - direction="on", - mirror=0x28, - textclass="close", - }, - { - category="po", - direction="on", - }, - { - category="sm", - direction="es", - }, - { - category="po", - direction="cs", - }, - { - category="pd", - direction="es", - }, - { - category="po", - direction="cs", - }, - { - category="po", - direction="cs", - }, - { - category="nd", - direction="en", - }, - { - category="nd", - direction="en", - }, - { - category="nd", - direction="en", - }, - { - category="nd", - direction="en", - }, - { - category="nd", - direction="en", - }, - { - category="nd", - direction="en", - }, - { - category="nd", - direction="en", - }, - { - category="nd", - direction="en", - }, - { - category="nd", - direction="en", - }, - { - category="nd", - direction="en", - }, - { - category="po", - direction="cs", - }, - { - category="po", - direction="on", - }, - { - category="sm", - direction="on", - mirror=0x3E, - textclass="open", - }, - { - category="sm", - direction="on", - }, - { - category="sm", - direction="on", - mirror=0x3C, - textclass="close", - }, - { - category="po", - direction="on", - }, - { - category="po", - direction="on", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ps", - direction="on", - mirror=0x5D, - textclass="open", - }, - { - category="po", - direction="on", - }, - { - category="pe", - direction="on", - mirror=0x5B, - textclass="close", - }, - { - category="sk", - direction="on", - }, - { - category="pc", - direction="on", - }, - { - category="sk", - direction="on", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ps", - direction="on", - mirror=0x7D, - textclass="open", - }, - { - category="sm", - direction="on", - }, - { - category="pe", - direction="on", - mirror=0x7B, - textclass="close", - }, - { - category="sm", - direction="on", - }, - { - category="cc", - direction="bn", - }, - { - category="cc", - direction="bn", - }, - { - category="cc", - direction="bn", - }, - { - category="cc", - direction="bn", - }, - { - category="cc", - direction="bn", - }, - { - category="cc", - direction="bn", - }, - { - category="cc", - direction="b", - }, - { - category="cc", - direction="bn", - }, - { - category="cc", - direction="bn", - }, - { - category="cc", - direction="bn", - }, - { - category="cc", - direction="bn", - }, - { - category="cc", - direction="bn", - }, - { - category="cc", - direction="bn", - }, - { - category="cc", - direction="bn", - }, - { - category="cc", - direction="bn", - }, - { - category="cc", - direction="bn", - }, - { - category="cc", - direction="bn", - }, - { - category="cc", - direction="bn", - }, - { - category="cc", - direction="bn", - }, - { - category="cc", - direction="bn", - }, - { - category="cc", - direction="bn", - }, - { - category="cc", - direction="bn", - }, - { - category="cc", - direction="bn", - }, - { - category="cc", - direction="bn", - }, - { - category="cc", - direction="bn", - }, - { - category="cc", - direction="bn", - }, - { - category="cc", - direction="bn", - }, - { - category="cc", - direction="bn", - }, - { - category="cc", - direction="bn", - }, - { - category="cc", - direction="bn", - }, - { - category="cc", - direction="bn", - }, - { - category="cc", - direction="bn", - }, - { - category="cc", - direction="bn", - }, - { - category="zs", - direction="cs", - }, - { - category="po", - direction="on", - }, - { - category="sc", - direction="et", - }, - { - category="sc", - direction="et", - }, - { - category="sc", - direction="et", - }, - { - category="sc", - direction="et", - }, - { - category="so", - direction="on", - }, - { - category="so", - direction="on", - }, - { - category="sk", - direction="on", - }, - { - category="so", - direction="on", - }, - { - category="ll", - direction="l", - }, - { - category="pi", - direction="on", - mirror=0xBB, - textclass="open", - }, - { - category="sm", - direction="on", - }, - { - category="cf", - direction="bn", - }, - { - category="so", - direction="on", - }, - { - category="sk", - direction="on", - }, - { - category="so", - direction="et", - }, - { - category="sm", - direction="et", - }, - { - category="no", - direction="en", - }, - { - category="no", - direction="en", - }, - { - category="sk", - direction="on", - }, - { - category="ll", - direction="l", - }, - { - category="so", - direction="on", - }, - { - category="po", - direction="on", - }, - { - category="sk", - direction="on", - }, - { - category="no", - direction="en", - }, - { - category="ll", - direction="l", - }, - { - category="pf", - direction="on", - mirror=0xAB, - textclass="close", - }, - { - category="no", - direction="on", - }, - { - category="no", - direction="on", - }, - { - category="no", - direction="on", - }, - { - category="po", - direction="on", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="sm", - direction="on", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="sm", - direction="on", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lo", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lo", - direction="l", - }, - { - category="lo", - direction="l", - }, - { - category="lo", - direction="l", - }, - { - category="lo", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lt", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lt", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lt", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lt", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lo", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lm", - direction="l", - }, - { - category="lm", - direction="l", - }, - { - category="lm", - direction="l", - }, - { - category="lm", - direction="l", - }, - { - category="lm", - direction="l", - }, - { - category="lm", - direction="l", - }, - { - category="lm", - direction="l", - }, - { - category="lm", - direction="l", - }, - { - category="lm", - direction="l", - }, - { - category="lm", - direction="on", - }, - { - category="lm", - direction="on", - }, - { - category="lm", - direction="l", - }, - { - category="lm", - direction="l", - }, - { - category="lm", - direction="l", - }, - { - category="lm", - direction="l", - }, - { - category="lm", - direction="l", - }, - { - category="lm", - direction="l", - }, - { - category="lm", - direction="l", - }, - { - category="sk", - direction="on", - }, - { - category="sk", - direction="on", - }, - { - category="sk", - direction="on", - }, - { - category="sk", - direction="on", - }, - { - category="lm", - direction="on", - }, - { - category="lm", - direction="on", - }, - { - category="lm", - direction="on", - }, - { - category="lm", - direction="on", - }, - { - category="lm", - direction="on", - }, - { - category="lm", - direction="on", - }, - { - category="lm", - direction="on", - }, - { - category="lm", - direction="on", - }, - { - category="lm", - direction="on", - }, - { - category="lm", - direction="on", - }, - { - category="lm", - direction="l", - }, - { - category="lm", - direction="l", - }, - { - category="sk", - direction="on", - }, - { - category="sk", - direction="on", - }, - { - category="sk", - direction="on", - }, - { - category="sk", - direction="on", - }, - { - category="sk", - direction="on", - }, - { - category="sk", - direction="on", - }, - { - category="sk", - direction="on", - }, - { - category="sk", - direction="on", - }, - { - category="sk", - direction="on", - }, - { - category="sk", - direction="on", - }, - { - category="sk", - direction="on", - }, - { - category="sk", - direction="on", - }, - { - category="sk", - direction="on", - }, - { - category="sk", - direction="on", - }, - { - category="lm", - direction="l", - }, - { - category="lm", - direction="l", - }, - { - category="lm", - direction="l", - }, - { - category="lm", - direction="l", - }, - { - category="lm", - direction="l", - }, - { - category="sk", - direction="on", - }, - { - category="sk", - direction="on", - }, - { - category="sk", - direction="on", - }, - { - category="sk", - direction="on", - }, - { - category="sk", - direction="on", - }, - { - category="sk", - direction="on", - }, - { - category="sk", - direction="on", - }, - { - category="sk", - direction="on", - }, - { - category="sk", - direction="on", - }, - { - category="lm", - direction="l", - }, - { - category="sk", - direction="on", - }, - { - category="sk", - direction="on", - }, - { - category="sk", - direction="on", - }, - { - category="sk", - direction="on", - }, - { - category="sk", - direction="on", - }, - { - category="sk", - direction="on", - }, - { - category="sk", - direction="on", - }, - { - category="sk", - direction="on", - }, - { - category="sk", - direction="on", - }, - { - category="sk", - direction="on", - }, - { - category="sk", - direction="on", - }, - { - category="sk", - direction="on", - }, - { - category="sk", - direction="on", - }, - { - category="sk", - direction="on", - }, - { - category="sk", - direction="on", - }, - { - category="sk", - direction="on", - }, - { - category="sk", - direction="on", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="mn", - direction="nsm", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - { - category="sk", - direction="on", - }, - { - category="sk", - direction="on", - }, - { - category="lu", - direction="l", - }, - { - category="ll", - direction="l", - }, - [0x37A]={ - category="lm", - direction="l", - }, - [0x37B]={ - category="ll", - direction="l", - }, - [0x37C]={ - category="ll", - direction="l", - }, - [0x37D]={ - category="ll", - direction="l", - }, - [0x37E]={ - category="po", - direction="on", - }, - [0x37F]={ - category="lu", - direction="l", - }, - [0x384]={ - category="sk", - direction="on", - }, - [0x385]={ - category="sk", - direction="on", - }, - [0x386]={ - category="lu", - direction="l", - }, - [0x387]={ - category="po", - direction="on", - }, - [0x388]={ - category="lu", - direction="l", - }, - [0x389]={ - category="lu", - direction="l", - }, - [0x38A]={ - category="lu", - direction="l", - }, - [0x38C]={ - category="lu", - direction="l", - }, - [0x38E]={ - category="lu", - direction="l", - }, - [0x38F]={ - category="lu", - direction="l", - }, - [0x390]={ - category="ll", - direction="l", - }, - [0x391]={ - category="lu", - direction="l", - }, - [0x392]={ - category="lu", - direction="l", - }, - [0x393]={ - category="lu", - direction="l", - }, - [0x394]={ - category="lu", - direction="l", - }, - [0x395]={ - category="lu", - direction="l", - }, - [0x396]={ - category="lu", - direction="l", - }, - [0x397]={ - category="lu", - direction="l", - }, - [0x398]={ - category="lu", - direction="l", - }, - [0x399]={ - category="lu", - direction="l", - }, - [0x39A]={ - category="lu", - direction="l", - }, - [0x39B]={ - category="lu", - direction="l", - }, - [0x39C]={ - category="lu", - direction="l", - }, - [0x39D]={ - category="lu", - direction="l", - }, - [0x39E]={ - category="lu", - direction="l", - }, - [0x39F]={ - category="lu", - direction="l", - }, - [0x3A0]={ - category="lu", - direction="l", - }, - [0x3A1]={ - category="lu", - direction="l", - }, - [0x3A3]={ - category="lu", - direction="l", - }, - [0x3A4]={ - category="lu", - direction="l", - }, - [0x3A5]={ - category="lu", - direction="l", - }, - [0x3A6]={ - category="lu", - direction="l", - }, - [0x3A7]={ - category="lu", - direction="l", - }, - [0x3A8]={ - category="lu", - direction="l", - }, - [0x3A9]={ - category="lu", - direction="l", - }, - [0x3AA]={ - category="lu", - direction="l", - }, - [0x3AB]={ - category="lu", - direction="l", - }, - [0x3AC]={ - category="ll", - direction="l", - }, - [0x3AD]={ - category="ll", - direction="l", - }, - [0x3AE]={ - category="ll", - direction="l", - }, - [0x3AF]={ - category="ll", - direction="l", - }, - [0x3B0]={ - category="ll", - direction="l", - }, - [0x3B1]={ - category="ll", - direction="l", - }, - [0x3B2]={ - category="ll", - direction="l", - }, - [0x3B3]={ - category="ll", - direction="l", - }, - [0x3B4]={ - category="ll", - direction="l", - }, - [0x3B5]={ - category="ll", - direction="l", - }, - [0x3B6]={ - category="ll", - direction="l", - }, - [0x3B7]={ - category="ll", - direction="l", - }, - [0x3B8]={ - category="ll", - direction="l", - }, - [0x3B9]={ - category="ll", - direction="l", - }, - [0x3BA]={ - category="ll", - direction="l", - }, - [0x3BB]={ - category="ll", - direction="l", - }, - [0x3BC]={ - category="ll", - direction="l", - }, - [0x3BD]={ - category="ll", - direction="l", - }, - [0x3BE]={ - category="ll", - direction="l", - }, - [0x3BF]={ - category="ll", - direction="l", - }, - [0x3C0]={ - category="ll", - direction="l", - }, - [0x3C1]={ - category="ll", - direction="l", - }, - [0x3C2]={ - category="ll", - direction="l", - }, - [0x3C3]={ - category="ll", - direction="l", - }, - [0x3C4]={ - category="ll", - direction="l", - }, - [0x3C5]={ - category="ll", - direction="l", - }, - [0x3C6]={ - category="ll", - direction="l", - }, - [0x3C7]={ - category="ll", - direction="l", - }, - [0x3C8]={ - category="ll", - direction="l", - }, - [0x3C9]={ - category="ll", - direction="l", - }, - [0x3CA]={ - category="ll", - direction="l", - }, - [0x3CB]={ - category="ll", - direction="l", - }, - [0x3CC]={ - category="ll", - direction="l", - }, - [0x3CD]={ - category="ll", - direction="l", - }, - [0x3CE]={ - category="ll", - direction="l", - }, - [0x3CF]={ - category="lu", - direction="l", - }, - [0x3D0]={ - category="ll", - direction="l", - }, - [0x3D1]={ - category="ll", - direction="l", - }, - [0x3D2]={ - category="lu", - direction="l", - }, - [0x3D3]={ - category="lu", - direction="l", - }, - [0x3D4]={ - category="lu", - direction="l", - }, - [0x3D5]={ - category="ll", - direction="l", - }, - [0x3D6]={ - category="ll", - direction="l", - }, - [0x3D7]={ - category="ll", - direction="l", - }, - [0x3D8]={ - category="lu", - direction="l", - }, - [0x3D9]={ - category="ll", - direction="l", - }, - [0x3DA]={ - category="lu", - direction="l", - }, - [0x3DB]={ - category="ll", - direction="l", - }, - [0x3DC]={ - category="lu", - direction="l", - }, - [0x3DD]={ - category="ll", - direction="l", - }, - [0x3DE]={ - category="lu", - direction="l", - }, - [0x3DF]={ - category="ll", - direction="l", - }, - [0x3E0]={ - category="lu", - direction="l", - }, - [0x3E1]={ - category="ll", - direction="l", - }, - [0x3E2]={ - category="lu", - direction="l", - }, - [0x3E3]={ - category="ll", - direction="l", - }, - [0x3E4]={ - category="lu", - direction="l", - }, - [0x3E5]={ - category="ll", - direction="l", - }, - [0x3E6]={ - category="lu", - direction="l", - }, - [0x3E7]={ - category="ll", - direction="l", - }, - [0x3E8]={ - category="lu", - direction="l", - }, - [0x3E9]={ - category="ll", - direction="l", - }, - [0x3EA]={ - category="lu", - direction="l", - }, - [0x3EB]={ - category="ll", - direction="l", - }, - [0x3EC]={ - category="lu", - direction="l", - }, - [0x3ED]={ - category="ll", - direction="l", - }, - [0x3EE]={ - category="lu", - direction="l", - }, - [0x3EF]={ - category="ll", - direction="l", - }, - [0x3F0]={ - category="ll", - direction="l", - }, - [0x3F1]={ - category="ll", - direction="l", - }, - [0x3F2]={ - category="ll", - direction="l", - }, - [0x3F3]={ - category="ll", - direction="l", - }, - [0x3F4]={ - category="lu", - direction="l", - }, - [0x3F5]={ - category="ll", - direction="l", - }, - [0x3F6]={ - category="sm", - direction="on", - }, - [0x3F7]={ - category="lu", - direction="l", - }, - [0x3F8]={ - category="ll", - direction="l", - }, - [0x3F9]={ - category="lu", - direction="l", - }, - [0x3FA]={ - category="lu", - direction="l", - }, - [0x3FB]={ - category="ll", - direction="l", - }, - [0x3FC]={ - category="ll", - direction="l", - }, - [0x3FD]={ - category="lu", - direction="l", - }, - [0x3FE]={ - category="lu", - direction="l", - }, - [0x3FF]={ - category="lu", - direction="l", - }, - [0x400]={ - category="lu", - direction="l", - }, - [0x401]={ - category="lu", - direction="l", - }, - [0x402]={ - category="lu", - direction="l", - }, - [0x403]={ - category="lu", - direction="l", - }, - [0x404]={ - category="lu", - direction="l", - }, - [0x405]={ - category="lu", - direction="l", - }, - [0x406]={ - category="lu", - direction="l", - }, - [0x407]={ - category="lu", - direction="l", - }, - [0x408]={ - category="lu", - direction="l", - }, - [0x409]={ - category="lu", - direction="l", - }, - [0x40A]={ - category="lu", - direction="l", - }, - [0x40B]={ - category="lu", - direction="l", - }, - [0x40C]={ - category="lu", - direction="l", - }, - [0x40D]={ - category="lu", - direction="l", - }, - [0x40E]={ - category="lu", - direction="l", - }, - [0x40F]={ - category="lu", - direction="l", - }, - [0x410]={ - category="lu", - direction="l", - }, - [0x411]={ - category="lu", - direction="l", - }, - [0x412]={ - category="lu", - direction="l", - }, - [0x413]={ - category="lu", - direction="l", - }, - [0x414]={ - category="lu", - direction="l", - }, - [0x415]={ - category="lu", - direction="l", - }, - [0x416]={ - category="lu", - direction="l", - }, - [0x417]={ - category="lu", - direction="l", - }, - [0x418]={ - category="lu", - direction="l", - }, - [0x419]={ - category="lu", - direction="l", - }, - [0x41A]={ - category="lu", - direction="l", - }, - [0x41B]={ - category="lu", - direction="l", - }, - [0x41C]={ - category="lu", - direction="l", - }, - [0x41D]={ - category="lu", - direction="l", - }, - [0x41E]={ - category="lu", - direction="l", - }, - [0x41F]={ - category="lu", - direction="l", - }, - [0x420]={ - category="lu", - direction="l", - }, - [0x421]={ - category="lu", - direction="l", - }, - [0x422]={ - category="lu", - direction="l", - }, - [0x423]={ - category="lu", - direction="l", - }, - [0x424]={ - category="lu", - direction="l", - }, - [0x425]={ - category="lu", - direction="l", - }, - [0x426]={ - category="lu", - direction="l", - }, - [0x427]={ - category="lu", - direction="l", - }, - [0x428]={ - category="lu", - direction="l", - }, - [0x429]={ - category="lu", - direction="l", - }, - [0x42A]={ - category="lu", - direction="l", - }, - [0x42B]={ - category="lu", - direction="l", - }, - [0x42C]={ - category="lu", - direction="l", - }, - [0x42D]={ - category="lu", - direction="l", - }, - [0x42E]={ - category="lu", - direction="l", - }, - [0x42F]={ - category="lu", - direction="l", - }, - [0x430]={ - category="ll", - direction="l", - }, - [0x431]={ - category="ll", - direction="l", - }, - [0x432]={ - category="ll", - direction="l", - }, - [0x433]={ - category="ll", - direction="l", - }, - [0x434]={ - category="ll", - direction="l", - }, - [0x435]={ - category="ll", - direction="l", - }, - [0x436]={ - category="ll", - direction="l", - }, - [0x437]={ - category="ll", - direction="l", - }, - [0x438]={ - category="ll", - direction="l", - }, - [0x439]={ - category="ll", - direction="l", - }, - [0x43A]={ - category="ll", - direction="l", - }, - [0x43B]={ - category="ll", - direction="l", - }, - [0x43C]={ - category="ll", - direction="l", - }, - [0x43D]={ - category="ll", - direction="l", - }, - [0x43E]={ - category="ll", - direction="l", - }, - [0x43F]={ - category="ll", - direction="l", - }, - [0x440]={ - category="ll", - direction="l", - }, - [0x441]={ - category="ll", - direction="l", - }, - [0x442]={ - category="ll", - direction="l", - }, - [0x443]={ - category="ll", - direction="l", - }, - [0x444]={ - category="ll", - direction="l", - }, - [0x445]={ - category="ll", - direction="l", - }, - [0x446]={ - category="ll", - direction="l", - }, - [0x447]={ - category="ll", - direction="l", - }, - [0x448]={ - category="ll", - direction="l", - }, - [0x449]={ - category="ll", - direction="l", - }, - [0x44A]={ - category="ll", - direction="l", - }, - [0x44B]={ - category="ll", - direction="l", - }, - [0x44C]={ - category="ll", - direction="l", - }, - [0x44D]={ - category="ll", - direction="l", - }, - [0x44E]={ - category="ll", - direction="l", - }, - [0x44F]={ - category="ll", - direction="l", - }, - [0x450]={ - category="ll", - direction="l", - }, - [0x451]={ - category="ll", - direction="l", - }, - [0x452]={ - category="ll", - direction="l", - }, - [0x453]={ - category="ll", - direction="l", - }, - [0x454]={ - category="ll", - direction="l", - }, - [0x455]={ - category="ll", - direction="l", - }, - [0x456]={ - category="ll", - direction="l", - }, - [0x457]={ - category="ll", - direction="l", - }, - [0x458]={ - category="ll", - direction="l", - }, - [0x459]={ - category="ll", - direction="l", - }, - [0x45A]={ - category="ll", - direction="l", - }, - [0x45B]={ - category="ll", - direction="l", - }, - [0x45C]={ - category="ll", - direction="l", - }, - [0x45D]={ - category="ll", - direction="l", - }, - [0x45E]={ - category="ll", - direction="l", - }, - [0x45F]={ - category="ll", - direction="l", - }, - [0x460]={ - category="lu", - direction="l", - }, - [0x461]={ - category="ll", - direction="l", - }, - [0x462]={ - category="lu", - direction="l", - }, - [0x463]={ - category="ll", - direction="l", - }, - [0x464]={ - category="lu", - direction="l", - }, - [0x465]={ - category="ll", - direction="l", - }, - [0x466]={ - category="lu", - direction="l", - }, - [0x467]={ - category="ll", - direction="l", - }, - [0x468]={ - category="lu", - direction="l", - }, - [0x469]={ - category="ll", - direction="l", - }, - [0x46A]={ - category="lu", - direction="l", - }, - [0x46B]={ - category="ll", - direction="l", - }, - [0x46C]={ - category="lu", - direction="l", - }, - [0x46D]={ - category="ll", - direction="l", - }, - [0x46E]={ - category="lu", - direction="l", - }, - [0x46F]={ - category="ll", - direction="l", - }, - [0x470]={ - category="lu", - direction="l", - }, - [0x471]={ - category="ll", - direction="l", - }, - [0x472]={ - category="lu", - direction="l", - }, - [0x473]={ - category="ll", - direction="l", - }, - [0x474]={ - category="lu", - direction="l", - }, - [0x475]={ - category="ll", - direction="l", - }, - [0x476]={ - category="lu", - direction="l", - }, - [0x477]={ - category="ll", - direction="l", - }, - [0x478]={ - category="lu", - direction="l", - }, - [0x479]={ - category="ll", - direction="l", - }, - [0x47A]={ - category="lu", - direction="l", - }, - [0x47B]={ - category="ll", - direction="l", - }, - [0x47C]={ - category="lu", - direction="l", - }, - [0x47D]={ - category="ll", - direction="l", - }, - [0x47E]={ - category="lu", - direction="l", - }, - [0x47F]={ - category="ll", - direction="l", - }, - [0x480]={ - category="lu", - direction="l", - }, - [0x481]={ - category="ll", - direction="l", - }, - [0x482]={ - category="so", - direction="l", - }, - [0x483]={ - category="mn", - direction="nsm", - }, - [0x484]={ - category="mn", - direction="nsm", - }, - [0x485]={ - category="mn", - direction="nsm", - }, - [0x486]={ - category="mn", - direction="nsm", - }, - [0x487]={ - category="mn", - direction="nsm", - }, - [0x488]={ - category="me", - direction="nsm", - }, - [0x489]={ - category="me", - direction="nsm", - }, - [0x48A]={ - category="lu", - direction="l", - }, - [0x48B]={ - category="ll", - direction="l", - }, - [0x48C]={ - category="lu", - direction="l", - }, - [0x48D]={ - category="ll", - direction="l", - }, - [0x48E]={ - category="lu", - direction="l", - }, - [0x48F]={ - category="ll", - direction="l", - }, - [0x490]={ - category="lu", - direction="l", - }, - [0x491]={ - category="ll", - direction="l", - }, - [0x492]={ - category="lu", - direction="l", - }, - [0x493]={ - category="ll", - direction="l", - }, - [0x494]={ - category="lu", - direction="l", - }, - [0x495]={ - category="ll", - direction="l", - }, - [0x496]={ - category="lu", - direction="l", - }, - [0x497]={ - category="ll", - direction="l", - }, - [0x498]={ - category="lu", - direction="l", - }, - [0x499]={ - category="ll", - direction="l", - }, - [0x49A]={ - category="lu", - direction="l", - }, - [0x49B]={ - category="ll", - direction="l", - }, - [0x49C]={ - category="lu", - direction="l", - }, - [0x49D]={ - category="ll", - direction="l", - }, - [0x49E]={ - category="lu", - direction="l", - }, - [0x49F]={ - category="ll", - direction="l", - }, - [0x4A0]={ - category="lu", - direction="l", - }, - [0x4A1]={ - category="ll", - direction="l", - }, - [0x4A2]={ - category="lu", - direction="l", - }, - [0x4A3]={ - category="ll", - direction="l", - }, - [0x4A4]={ - category="lu", - direction="l", - }, - [0x4A5]={ - category="ll", - direction="l", - }, - [0x4A6]={ - category="lu", - direction="l", - }, - [0x4A7]={ - category="ll", - direction="l", - }, - [0x4A8]={ - category="lu", - direction="l", - }, - [0x4A9]={ - category="ll", - direction="l", - }, - [0x4AA]={ - category="lu", - direction="l", - }, - [0x4AB]={ - category="ll", - direction="l", - }, - [0x4AC]={ - category="lu", - direction="l", - }, - [0x4AD]={ - category="ll", - direction="l", - }, - [0x4AE]={ - category="lu", - direction="l", - }, - [0x4AF]={ - category="ll", - direction="l", - }, - [0x4B0]={ - category="lu", - direction="l", - }, - [0x4B1]={ - category="ll", - direction="l", - }, - [0x4B2]={ - category="lu", - direction="l", - }, - [0x4B3]={ - category="ll", - direction="l", - }, - [0x4B4]={ - category="lu", - direction="l", - }, - [0x4B5]={ - category="ll", - direction="l", - }, - [0x4B6]={ - category="lu", - direction="l", - }, - [0x4B7]={ - category="ll", - direction="l", - }, - [0x4B8]={ - category="lu", - direction="l", - }, - [0x4B9]={ - category="ll", - direction="l", - }, - [0x4BA]={ - category="lu", - direction="l", - }, - [0x4BB]={ - category="ll", - direction="l", - }, - [0x4BC]={ - category="lu", - direction="l", - }, - [0x4BD]={ - category="ll", - direction="l", - }, - [0x4BE]={ - category="lu", - direction="l", - }, - [0x4BF]={ - category="ll", - direction="l", - }, - [0x4C0]={ - category="lu", - direction="l", - }, - [0x4C1]={ - category="lu", - direction="l", - }, - [0x4C2]={ - category="ll", - direction="l", - }, - [0x4C3]={ - category="lu", - direction="l", - }, - [0x4C4]={ - category="ll", - direction="l", - }, - [0x4C5]={ - category="lu", - direction="l", - }, - [0x4C6]={ - category="ll", - direction="l", - }, - [0x4C7]={ - category="lu", - direction="l", - }, - [0x4C8]={ - category="ll", - direction="l", - }, - [0x4C9]={ - category="lu", - direction="l", - }, - [0x4CA]={ - category="ll", - direction="l", - }, - [0x4CB]={ - category="lu", - direction="l", - }, - [0x4CC]={ - category="ll", - direction="l", - }, - [0x4CD]={ - category="lu", - direction="l", - }, - [0x4CE]={ - category="ll", - direction="l", - }, - [0x4CF]={ - category="ll", - direction="l", - }, - [0x4D0]={ - category="lu", - direction="l", - }, - [0x4D1]={ - category="ll", - direction="l", - }, - [0x4D2]={ - category="lu", - direction="l", - }, - [0x4D3]={ - category="ll", - direction="l", - }, - [0x4D4]={ - category="lu", - direction="l", - }, - [0x4D5]={ - category="ll", - direction="l", - }, - [0x4D6]={ - category="lu", - direction="l", - }, - [0x4D7]={ - category="ll", - direction="l", - }, - [0x4D8]={ - category="lu", - direction="l", - }, - [0x4D9]={ - category="ll", - direction="l", - }, - [0x4DA]={ - category="lu", - direction="l", - }, - [0x4DB]={ - category="ll", - direction="l", - }, - [0x4DC]={ - category="lu", - direction="l", - }, - [0x4DD]={ - category="ll", - direction="l", - }, - [0x4DE]={ - category="lu", - direction="l", - }, - [0x4DF]={ - category="ll", - direction="l", - }, - [0x4E0]={ - category="lu", - direction="l", - }, - [0x4E1]={ - category="ll", - direction="l", - }, - [0x4E2]={ - category="lu", - direction="l", - }, - [0x4E3]={ - category="ll", - direction="l", - }, - [0x4E4]={ - category="lu", - direction="l", - }, - [0x4E5]={ - category="ll", - direction="l", - }, - [0x4E6]={ - category="lu", - direction="l", - }, - [0x4E7]={ - category="ll", - direction="l", - }, - [0x4E8]={ - category="lu", - direction="l", - }, - [0x4E9]={ - category="ll", - direction="l", - }, - [0x4EA]={ - category="lu", - direction="l", - }, - [0x4EB]={ - category="ll", - direction="l", - }, - [0x4EC]={ - category="lu", - direction="l", - }, - [0x4ED]={ - category="ll", - direction="l", - }, - [0x4EE]={ - category="lu", - direction="l", - }, - [0x4EF]={ - category="ll", - direction="l", - }, - [0x4F0]={ - category="lu", - direction="l", - }, - [0x4F1]={ - category="ll", - direction="l", - }, - [0x4F2]={ - category="lu", - direction="l", - }, - [0x4F3]={ - category="ll", - direction="l", - }, - [0x4F4]={ - category="lu", - direction="l", - }, - [0x4F5]={ - category="ll", - direction="l", - }, - [0x4F6]={ - category="lu", - direction="l", - }, - [0x4F7]={ - category="ll", - direction="l", - }, - [0x4F8]={ - category="lu", - direction="l", - }, - [0x4F9]={ - category="ll", - direction="l", - }, - [0x4FA]={ - category="lu", - direction="l", - }, - [0x4FB]={ - category="ll", - direction="l", - }, - [0x4FC]={ - category="lu", - direction="l", - }, - [0x4FD]={ - category="ll", - direction="l", - }, - [0x4FE]={ - category="lu", - direction="l", - }, - [0x4FF]={ - category="ll", - direction="l", - }, - [0x500]={ - category="lu", - direction="l", - }, - [0x501]={ - category="ll", - direction="l", - }, - [0x502]={ - category="lu", - direction="l", - }, - [0x503]={ - category="ll", - direction="l", - }, - [0x504]={ - category="lu", - direction="l", - }, - [0x505]={ - category="ll", - direction="l", - }, - [0x506]={ - category="lu", - direction="l", - }, - [0x507]={ - category="ll", - direction="l", - }, - [0x508]={ - category="lu", - direction="l", - }, - [0x509]={ - category="ll", - direction="l", - }, - [0x50A]={ - category="lu", - direction="l", - }, - [0x50B]={ - category="ll", - direction="l", - }, - [0x50C]={ - category="lu", - direction="l", - }, - [0x50D]={ - category="ll", - direction="l", - }, - [0x50E]={ - category="lu", - direction="l", - }, - [0x50F]={ - category="ll", - direction="l", - }, - [0x510]={ - category="lu", - direction="l", - }, - [0x511]={ - category="ll", - direction="l", - }, - [0x512]={ - category="lu", - direction="l", - }, - [0x513]={ - category="ll", - direction="l", - }, - [0x514]={ - category="lu", - direction="l", - }, - [0x515]={ - category="ll", - direction="l", - }, - [0x516]={ - category="lu", - direction="l", - }, - [0x517]={ - category="ll", - direction="l", - }, - [0x518]={ - category="lu", - direction="l", - }, - [0x519]={ - category="ll", - direction="l", - }, - [0x51A]={ - category="lu", - direction="l", - }, - [0x51B]={ - category="ll", - direction="l", - }, - [0x51C]={ - category="lu", - direction="l", - }, - [0x51D]={ - category="ll", - direction="l", - }, - [0x51E]={ - category="lu", - direction="l", - }, - [0x51F]={ - category="ll", - direction="l", - }, - [0x520]={ - category="lu", - direction="l", - }, - [0x521]={ - category="ll", - direction="l", - }, - [0x522]={ - category="lu", - direction="l", - }, - [0x523]={ - category="ll", - direction="l", - }, - [0x524]={ - category="lu", - direction="l", - }, - [0x525]={ - category="ll", - direction="l", - }, - [0x526]={ - category="lu", - direction="l", - }, - [0x527]={ - category="ll", - direction="l", - }, - [0x528]={ - category="lu", - direction="l", - }, - [0x529]={ - category="ll", - direction="l", - }, - [0x52A]={ - category="lu", - direction="l", - }, - [0x52B]={ - category="ll", - direction="l", - }, - [0x52C]={ - category="lu", - direction="l", - }, - [0x52D]={ - category="ll", - direction="l", - }, - [0x52E]={ - category="lu", - direction="l", - }, - [0x52F]={ - category="ll", - direction="l", - }, - [0x531]={ - category="lu", - direction="l", - }, - [0x532]={ - category="lu", - direction="l", - }, - [0x533]={ - category="lu", - direction="l", - }, - [0x534]={ - category="lu", - direction="l", - }, - [0x535]={ - category="lu", - direction="l", - }, - [0x536]={ - category="lu", - direction="l", - }, - [0x537]={ - category="lu", - direction="l", - }, - [0x538]={ - category="lu", - direction="l", - }, - [0x539]={ - category="lu", - direction="l", - }, - [0x53A]={ - category="lu", - direction="l", - }, - [0x53B]={ - category="lu", - direction="l", - }, - [0x53C]={ - category="lu", - direction="l", - }, - [0x53D]={ - category="lu", - direction="l", - }, - [0x53E]={ - category="lu", - direction="l", - }, - [0x53F]={ - category="lu", - direction="l", - }, - [0x540]={ - category="lu", - direction="l", - }, - [0x541]={ - category="lu", - direction="l", - }, - [0x542]={ - category="lu", - direction="l", - }, - [0x543]={ - category="lu", - direction="l", - }, - [0x544]={ - category="lu", - direction="l", - }, - [0x545]={ - category="lu", - direction="l", - }, - [0x546]={ - category="lu", - direction="l", - }, - [0x547]={ - category="lu", - direction="l", - }, - [0x548]={ - category="lu", - direction="l", - }, - [0x549]={ - category="lu", - direction="l", - }, - [0x54A]={ - category="lu", - direction="l", - }, - [0x54B]={ - category="lu", - direction="l", - }, - [0x54C]={ - category="lu", - direction="l", - }, - [0x54D]={ - category="lu", - direction="l", - }, - [0x54E]={ - category="lu", - direction="l", - }, - [0x54F]={ - category="lu", - direction="l", - }, - [0x550]={ - category="lu", - direction="l", - }, - [0x551]={ - category="lu", - direction="l", - }, - [0x552]={ - category="lu", - direction="l", - }, - [0x553]={ - category="lu", - direction="l", - }, - [0x554]={ - category="lu", - direction="l", - }, - [0x555]={ - category="lu", - direction="l", - }, - [0x556]={ - category="lu", - direction="l", - }, - [0x559]={ - category="lm", - direction="l", - }, - [0x55A]={ - category="po", - direction="l", - }, - [0x55B]={ - category="po", - direction="l", - }, - [0x55C]={ - category="po", - direction="l", - }, - [0x55D]={ - category="po", - direction="l", - }, - [0x55E]={ - category="po", - direction="l", - }, - [0x55F]={ - category="po", - direction="l", - }, - [0x561]={ - category="ll", - direction="l", - }, - [0x562]={ - category="ll", - direction="l", - }, - [0x563]={ - category="ll", - direction="l", - }, - [0x564]={ - category="ll", - direction="l", - }, - [0x565]={ - category="ll", - direction="l", - }, - [0x566]={ - category="ll", - direction="l", - }, - [0x567]={ - category="ll", - direction="l", - }, - [0x568]={ - category="ll", - direction="l", - }, - [0x569]={ - category="ll", - direction="l", - }, - [0x56A]={ - category="ll", - direction="l", - }, - [0x56B]={ - category="ll", - direction="l", - }, - [0x56C]={ - category="ll", - direction="l", - }, - [0x56D]={ - category="ll", - direction="l", - }, - [0x56E]={ - category="ll", - direction="l", - }, - [0x56F]={ - category="ll", - direction="l", - }, - [0x570]={ - category="ll", - direction="l", - }, - [0x571]={ - category="ll", - direction="l", - }, - [0x572]={ - category="ll", - direction="l", - }, - [0x573]={ - category="ll", - direction="l", - }, - [0x574]={ - category="ll", - direction="l", - }, - [0x575]={ - category="ll", - direction="l", - }, - [0x576]={ - category="ll", - direction="l", - }, - [0x577]={ - category="ll", - direction="l", - }, - [0x578]={ - category="ll", - direction="l", - }, - [0x579]={ - category="ll", - direction="l", - }, - [0x57A]={ - category="ll", - direction="l", - }, - [0x57B]={ - category="ll", - direction="l", - }, - [0x57C]={ - category="ll", - direction="l", - }, - [0x57D]={ - category="ll", - direction="l", - }, - [0x57E]={ - category="ll", - direction="l", - }, - [0x57F]={ - category="ll", - direction="l", - }, - [0x580]={ - category="ll", - direction="l", - }, - [0x581]={ - category="ll", - direction="l", - }, - [0x582]={ - category="ll", - direction="l", - }, - [0x583]={ - category="ll", - direction="l", - }, - [0x584]={ - category="ll", - direction="l", - }, - [0x585]={ - category="ll", - direction="l", - }, - [0x586]={ - category="ll", - direction="l", - }, - [0x587]={ - category="ll", - direction="l", - }, - [0x589]={ - category="po", - direction="l", - }, - [0x58A]={ - category="pd", - direction="on", - }, - [0x58D]={ - category="so", - direction="on", - }, - [0x58E]={ - category="so", - direction="on", - }, - [0x58F]={ - category="sc", - direction="et", - }, - [0x591]={ - category="mn", - direction="nsm", - }, - [0x592]={ - category="mn", - direction="nsm", - }, - [0x593]={ - category="mn", - direction="nsm", - }, - [0x594]={ - category="mn", - direction="nsm", - }, - [0x595]={ - category="mn", - direction="nsm", - }, - [0x596]={ - category="mn", - direction="nsm", - }, - [0x597]={ - category="mn", - direction="nsm", - }, - [0x598]={ - category="mn", - direction="nsm", - }, - [0x599]={ - category="mn", - direction="nsm", - }, - [0x59A]={ - category="mn", - direction="nsm", - }, - [0x59B]={ - category="mn", - direction="nsm", - }, - [0x59C]={ - category="mn", - direction="nsm", - }, - [0x59D]={ - category="mn", - direction="nsm", - }, - [0x59E]={ - category="mn", - direction="nsm", - }, - [0x59F]={ - category="mn", - direction="nsm", - }, - [0x5A0]={ - category="mn", - direction="nsm", - }, - [0x5A1]={ - category="mn", - direction="nsm", - }, - [0x5A2]={ - category="mn", - direction="nsm", - }, - [0x5A3]={ - category="mn", - direction="nsm", - }, - [0x5A4]={ - category="mn", - direction="nsm", - }, - [0x5A5]={ - category="mn", - direction="nsm", - }, - [0x5A6]={ - category="mn", - direction="nsm", - }, - [0x5A7]={ - category="mn", - direction="nsm", - }, - [0x5A8]={ - category="mn", - direction="nsm", - }, - [0x5A9]={ - category="mn", - direction="nsm", - }, - [0x5AA]={ - category="mn", - direction="nsm", - }, - [0x5AB]={ - category="mn", - direction="nsm", - }, - [0x5AC]={ - category="mn", - direction="nsm", - }, - [0x5AD]={ - category="mn", - direction="nsm", - }, - [0x5AE]={ - category="mn", - direction="nsm", - }, - [0x5AF]={ - category="mn", - direction="nsm", - }, - [0x5B0]={ - category="mn", - direction="nsm", - }, - [0x5B1]={ - category="mn", - direction="nsm", - }, - [0x5B2]={ - category="mn", - direction="nsm", - }, - [0x5B3]={ - category="mn", - direction="nsm", - }, - [0x5B4]={ - category="mn", - direction="nsm", - }, - [0x5B5]={ - category="mn", - direction="nsm", - }, - [0x5B6]={ - category="mn", - direction="nsm", - }, - [0x5B7]={ - category="mn", - direction="nsm", - }, - [0x5B8]={ - category="mn", - direction="nsm", - }, - [0x5B9]={ - category="mn", - direction="nsm", - }, - [0x5BA]={ - category="mn", - direction="nsm", - }, - [0x5BB]={ - category="mn", - direction="nsm", - }, - [0x5BC]={ - category="mn", - direction="nsm", - }, - [0x5BD]={ - category="mn", - direction="nsm", - }, - [0x5BE]={ - category="po", - direction="r", - }, - [0x5BF]={ - category="mn", - direction="nsm", - }, - [0x5C0]={ - category="po", - direction="r", - }, - [0x5C1]={ - category="mn", - direction="nsm", - }, - [0x5C2]={ - category="mn", - direction="nsm", - }, - [0x5C3]={ - category="po", - direction="r", - }, - [0x5C4]={ - category="mn", - direction="nsm", - }, - [0x5C5]={ - category="mn", - direction="nsm", - }, - [0x5C6]={ - category="po", - direction="r", - }, - [0x5C7]={ - category="mn", - direction="nsm", - }, - [0x5D0]={ - category="lo", - direction="r", - }, - [0x5D1]={ - category="lo", - direction="r", - }, - [0x5D2]={ - category="lo", - direction="r", - }, - [0x5D3]={ - category="lo", - direction="r", - }, - [0x5D4]={ - category="lo", - direction="r", - }, - [0x5D5]={ - category="lo", - direction="r", - }, - [0x5D6]={ - category="lo", - direction="r", - }, - [0x5D7]={ - category="lo", - direction="r", - }, - [0x5D8]={ - category="lo", - direction="r", - }, - [0x5D9]={ - category="lo", - direction="r", - }, - [0x5DA]={ - category="lo", - direction="r", - }, - [0x5DB]={ - category="lo", - direction="r", - }, - [0x5DC]={ - category="lo", - direction="r", - }, - [0x5DD]={ - category="lo", - direction="r", - }, - [0x5DE]={ - category="lo", - direction="r", - }, - [0x5DF]={ - category="lo", - direction="r", - }, - [0x5E0]={ - category="lo", - direction="r", - }, - [0x5E1]={ - category="lo", - direction="r", - }, - [0x5E2]={ - category="lo", - direction="r", - }, - [0x5E3]={ - category="lo", - direction="r", - }, - [0x5E4]={ - category="lo", - direction="r", - }, - [0x5E5]={ - category="lo", - direction="r", - }, - [0x5E6]={ - category="lo", - direction="r", - }, - [0x5E7]={ - category="lo", - direction="r", - }, - [0x5E8]={ - category="lo", - direction="r", - }, - [0x5E9]={ - category="lo", - direction="r", - }, - [0x5EA]={ - category="lo", - direction="r", - }, - [0x5F0]={ - category="lo", - direction="r", - }, - [0x5F1]={ - category="lo", - direction="r", - }, - [0x5F2]={ - category="lo", - direction="r", - }, - [0x5F3]={ - category="po", - direction="r", - }, - [0x5F4]={ - category="po", - direction="r", - }, - [0x600]={ - category="cf", - direction="an", - }, - [0x601]={ - category="cf", - direction="an", - }, - [0x602]={ - category="cf", - direction="an", - }, - [0x603]={ - category="cf", - direction="an", - }, - [0x604]={ - category="cf", - direction="an", - }, - [0x605]={ - category="cf", - direction="an", - }, - [0x606]={ - category="sm", - direction="on", - }, - [0x607]={ - category="sm", - direction="on", - }, - [0x608]={ - category="sm", - direction="al", - }, - [0x609]={ - category="po", - direction="et", - }, - [0x60A]={ - category="po", - direction="et", - }, - [0x60B]={ - category="sc", - direction="al", - }, - [0x60C]={ - category="po", - direction="cs", - }, - [0x60D]={ - category="po", - direction="al", - }, - [0x60E]={ - category="so", - direction="on", - }, - [0x60F]={ - category="so", - direction="on", - }, - [0x610]={ - category="mn", - direction="nsm", - }, - [0x611]={ - category="mn", - direction="nsm", - }, - [0x612]={ - category="mn", - direction="nsm", - }, - [0x613]={ - category="mn", - direction="nsm", - }, - [0x614]={ - category="mn", - direction="nsm", - }, - [0x615]={ - category="mn", - direction="nsm", - }, - [0x616]={ - category="mn", - direction="nsm", - }, - [0x617]={ - category="mn", - direction="nsm", - }, - [0x618]={ - category="mn", - direction="nsm", - }, - [0x619]={ - category="mn", - direction="nsm", - }, - [0x61A]={ - category="mn", - direction="nsm", - }, - [0x61B]={ - category="po", - direction="al", - }, - [0x61C]={ - category="cf", - direction="al", - }, - [0x61E]={ - category="po", - direction="al", - }, - [0x61F]={ - category="po", - direction="al", - }, - [0x620]={ - category="lo", - direction="al", - }, - [0x621]={ - category="lo", - direction="al", - }, - [0x622]={ - category="lo", - direction="al", - }, - [0x623]={ - category="lo", - direction="al", - }, - [0x624]={ - category="lo", - direction="al", - }, - [0x625]={ - category="lo", - direction="al", - }, - [0x626]={ - category="lo", - direction="al", - }, - [0x627]={ - category="lo", - direction="al", - }, - [0x628]={ - category="lo", - direction="al", - }, - [0x629]={ - category="lo", - direction="al", - }, - [0x62A]={ - category="lo", - direction="al", - }, - [0x62B]={ - category="lo", - direction="al", - }, - [0x62C]={ - category="lo", - direction="al", - }, - [0x62D]={ - category="lo", - direction="al", - }, - [0x62E]={ - category="lo", - direction="al", - }, - [0x62F]={ - category="lo", - direction="al", - }, - [0x630]={ - category="lo", - direction="al", - }, - [0x631]={ - category="lo", - direction="al", - }, - [0x632]={ - category="lo", - direction="al", - }, - [0x633]={ - category="lo", - direction="al", - }, - [0x634]={ - category="lo", - direction="al", - }, - [0x635]={ - category="lo", - direction="al", - }, - [0x636]={ - category="lo", - direction="al", - }, - [0x637]={ - category="lo", - direction="al", - }, - [0x638]={ - category="lo", - direction="al", - }, - [0x639]={ - category="lo", - direction="al", - }, - [0x63A]={ - category="lo", - direction="al", - }, - [0x63B]={ - category="lo", - direction="al", - }, - [0x63C]={ - category="lo", - direction="al", - }, - [0x63D]={ - category="lo", - direction="al", - }, - [0x63E]={ - category="lo", - direction="al", - }, - [0x63F]={ - category="lo", - direction="al", - }, - [0x640]={ - category="lm", - direction="al", - }, - [0x641]={ - category="lo", - direction="al", - }, - [0x642]={ - category="lo", - direction="al", - }, - [0x643]={ - category="lo", - direction="al", - }, - [0x644]={ - category="lo", - direction="al", - }, - [0x645]={ - category="lo", - direction="al", - }, - [0x646]={ - category="lo", - direction="al", - }, - [0x647]={ - category="lo", - direction="al", - }, - [0x648]={ - category="lo", - direction="al", - }, - [0x649]={ - category="lo", - direction="al", - }, - [0x64A]={ - category="lo", - direction="al", - }, - [0x64B]={ - category="mn", - direction="nsm", - }, - [0x64C]={ - category="mn", - direction="nsm", - }, - [0x64D]={ - category="mn", - direction="nsm", - }, - [0x64E]={ - category="mn", - direction="nsm", - }, - [0x64F]={ - category="mn", - direction="nsm", - }, - [0x650]={ - category="mn", - direction="nsm", - }, - [0x651]={ - category="mn", - direction="nsm", - }, - [0x652]={ - category="mn", - direction="nsm", - }, - [0x653]={ - category="mn", - direction="nsm", - }, - [0x654]={ - category="mn", - direction="nsm", - }, - [0x655]={ - category="mn", - direction="nsm", - }, - [0x656]={ - category="mn", - direction="nsm", - }, - [0x657]={ - category="mn", - direction="nsm", - }, - [0x658]={ - category="mn", - direction="nsm", - }, - [0x659]={ - category="mn", - direction="nsm", - }, - [0x65A]={ - category="mn", - direction="nsm", - }, - [0x65B]={ - category="mn", - direction="nsm", - }, - [0x65C]={ - category="mn", - direction="nsm", - }, - [0x65D]={ - category="mn", - direction="nsm", - }, - [0x65E]={ - category="mn", - direction="nsm", - }, - [0x65F]={ - category="mn", - direction="nsm", - }, - [0x660]={ - category="nd", - direction="an", - }, - [0x661]={ - category="nd", - direction="an", - }, - [0x662]={ - category="nd", - direction="an", - }, - [0x663]={ - category="nd", - direction="an", - }, - [0x664]={ - category="nd", - direction="an", - }, - [0x665]={ - category="nd", - direction="an", - }, - [0x666]={ - category="nd", - direction="an", - }, - [0x667]={ - category="nd", - direction="an", - }, - [0x668]={ - category="nd", - direction="an", - }, - [0x669]={ - category="nd", - direction="an", - }, - [0x66A]={ - category="po", - direction="et", - }, - [0x66B]={ - category="po", - direction="an", - }, - [0x66C]={ - category="po", - direction="an", - }, - [0x66D]={ - category="po", - direction="al", - }, - [0x66E]={ - category="lo", - direction="al", - }, - [0x66F]={ - category="lo", - direction="al", - }, - [0x670]={ - category="mn", - direction="nsm", - }, - [0x671]={ - category="lo", - direction="al", - }, - [0x672]={ - category="lo", - direction="al", - }, - [0x673]={ - category="lo", - direction="al", - }, - [0x674]={ - category="lo", - direction="al", - }, - [0x675]={ - category="lo", - direction="al", - }, - [0x676]={ - category="lo", - direction="al", - }, - [0x677]={ - category="lo", - direction="al", - }, - [0x678]={ - category="lo", - direction="al", - }, - [0x679]={ - category="lo", - direction="al", - }, - [0x67A]={ - category="lo", - direction="al", - }, - [0x67B]={ - category="lo", - direction="al", - }, - [0x67C]={ - category="lo", - direction="al", - }, - [0x67D]={ - category="lo", - direction="al", - }, - [0x67E]={ - category="lo", - direction="al", - }, - [0x67F]={ - category="lo", - direction="al", - }, - [0x680]={ - category="lo", - direction="al", - }, - [0x681]={ - category="lo", - direction="al", - }, - [0x682]={ - category="lo", - direction="al", - }, - [0x683]={ - category="lo", - direction="al", - }, - [0x684]={ - category="lo", - direction="al", - }, - [0x685]={ - category="lo", - direction="al", - }, - [0x686]={ - category="lo", - direction="al", - }, - [0x687]={ - category="lo", - direction="al", - }, - [0x688]={ - category="lo", - direction="al", - }, - [0x689]={ - category="lo", - direction="al", - }, - [0x68A]={ - category="lo", - direction="al", - }, - [0x68B]={ - category="lo", - direction="al", - }, - [0x68C]={ - category="lo", - direction="al", - }, - [0x68D]={ - category="lo", - direction="al", - }, - [0x68E]={ - category="lo", - direction="al", - }, - [0x68F]={ - category="lo", - direction="al", - }, - [0x690]={ - category="lo", - direction="al", - }, - [0x691]={ - category="lo", - direction="al", - }, - [0x692]={ - category="lo", - direction="al", - }, - [0x693]={ - category="lo", - direction="al", - }, - [0x694]={ - category="lo", - direction="al", - }, - [0x695]={ - category="lo", - direction="al", - }, - [0x696]={ - category="lo", - direction="al", - }, - [0x697]={ - category="lo", - direction="al", - }, - [0x698]={ - category="lo", - direction="al", - }, - [0x699]={ - category="lo", - direction="al", - }, - [0x69A]={ - category="lo", - direction="al", - }, - [0x69B]={ - category="lo", - direction="al", - }, - [0x69C]={ - category="lo", - direction="al", - }, - [0x69D]={ - category="lo", - direction="al", - }, - [0x69E]={ - category="lo", - direction="al", - }, - [0x69F]={ - category="lo", - direction="al", - }, - [0x6A0]={ - category="lo", - direction="al", - }, - [0x6A1]={ - category="lo", - direction="al", - }, - [0x6A2]={ - category="lo", - direction="al", - }, - [0x6A3]={ - category="lo", - direction="al", - }, - [0x6A4]={ - category="lo", - direction="al", - }, - [0x6A5]={ - category="lo", - direction="al", - }, - [0x6A6]={ - category="lo", - direction="al", - }, - [0x6A7]={ - category="lo", - direction="al", - }, - [0x6A8]={ - category="lo", - direction="al", - }, - [0x6A9]={ - category="lo", - direction="al", - }, - [0x6AA]={ - category="lo", - direction="al", - }, - [0x6AB]={ - category="lo", - direction="al", - }, - [0x6AC]={ - category="lo", - direction="al", - }, - [0x6AD]={ - category="lo", - direction="al", - }, - [0x6AE]={ - category="lo", - direction="al", - }, - [0x6AF]={ - category="lo", - direction="al", - }, - [0x6B0]={ - category="lo", - direction="al", - }, - [0x6B1]={ - category="lo", - direction="al", - }, - [0x6B2]={ - category="lo", - direction="al", - }, - [0x6B3]={ - category="lo", - direction="al", - }, - [0x6B4]={ - category="lo", - direction="al", - }, - [0x6B5]={ - category="lo", - direction="al", - }, - [0x6B6]={ - category="lo", - direction="al", - }, - [0x6B7]={ - category="lo", - direction="al", - }, - [0x6B8]={ - category="lo", - direction="al", - }, - [0x6B9]={ - category="lo", - direction="al", - }, - [0x6BA]={ - category="lo", - direction="al", - }, - [0x6BB]={ - category="lo", - direction="al", - }, - [0x6BC]={ - category="lo", - direction="al", - }, - [0x6BD]={ - category="lo", - direction="al", - }, - [0x6BE]={ - category="lo", - direction="al", - }, - [0x6BF]={ - category="lo", - direction="al", - }, - [0x6C0]={ - category="lo", - direction="al", - }, - [0x6C1]={ - category="lo", - direction="al", - }, - [0x6C2]={ - category="lo", - direction="al", - }, - [0x6C3]={ - category="lo", - direction="al", - }, - [0x6C4]={ - category="lo", - direction="al", - }, - [0x6C5]={ - category="lo", - direction="al", - }, - [0x6C6]={ - category="lo", - direction="al", - }, - [0x6C7]={ - category="lo", - direction="al", - }, - [0x6C8]={ - category="lo", - direction="al", - }, - [0x6C9]={ - category="lo", - direction="al", - }, - [0x6CA]={ - category="lo", - direction="al", - }, - [0x6CB]={ - category="lo", - direction="al", - }, - [0x6CC]={ - category="lo", - direction="al", - }, - [0x6CD]={ - category="lo", - direction="al", - }, - [0x6CE]={ - category="lo", - direction="al", - }, - [0x6CF]={ - category="lo", - direction="al", - }, - [0x6D0]={ - category="lo", - direction="al", - }, - [0x6D1]={ - category="lo", - direction="al", - }, - [0x6D2]={ - category="lo", - direction="al", - }, - [0x6D3]={ - category="lo", - direction="al", - }, - [0x6D4]={ - category="po", - direction="al", - }, - [0x6D5]={ - category="lo", - direction="al", - }, - [0x6D6]={ - category="mn", - direction="nsm", - }, - [0x6D7]={ - category="mn", - direction="nsm", - }, - [0x6D8]={ - category="mn", - direction="nsm", - }, - [0x6D9]={ - category="mn", - direction="nsm", - }, - [0x6DA]={ - category="mn", - direction="nsm", - }, - [0x6DB]={ - category="mn", - direction="nsm", - }, - [0x6DC]={ - category="mn", - direction="nsm", - }, - [0x6DD]={ - category="cf", - direction="an", - }, - [0x6DE]={ - category="me", - direction="on", - }, - [0x6DF]={ - category="mn", - direction="nsm", - }, - [0x6E0]={ - category="mn", - direction="nsm", - }, - [0x6E1]={ - category="mn", - direction="nsm", - }, - [0x6E2]={ - category="mn", - direction="nsm", - }, - [0x6E3]={ - category="mn", - direction="nsm", - }, - [0x6E4]={ - category="mn", - direction="nsm", - }, - [0x6E5]={ - category="lm", - direction="al", - }, - [0x6E6]={ - category="lm", - direction="al", - }, - [0x6E7]={ - category="mn", - direction="nsm", - }, - [0x6E8]={ - category="mn", - direction="nsm", - }, - [0x6E9]={ - category="so", - direction="on", - }, - [0x6EA]={ - category="mn", - direction="nsm", - }, - [0x6EB]={ - category="mn", - direction="nsm", - }, - [0x6EC]={ - category="mn", - direction="nsm", - }, - [0x6ED]={ - category="mn", - direction="nsm", - }, - [0x6EE]={ - category="lo", - direction="al", - }, - [0x6EF]={ - category="lo", - direction="al", - }, - [0x6F0]={ - category="nd", - direction="en", - }, - [0x6F1]={ - category="nd", - direction="en", - }, - [0x6F2]={ - category="nd", - direction="en", - }, - [0x6F3]={ - category="nd", - direction="en", - }, - [0x6F4]={ - category="nd", - direction="en", - }, - [0x6F5]={ - category="nd", - direction="en", - }, - [0x6F6]={ - category="nd", - direction="en", - }, - [0x6F7]={ - category="nd", - direction="en", - }, - [0x6F8]={ - category="nd", - direction="en", - }, - [0x6F9]={ - category="nd", - direction="en", - }, - [0x6FA]={ - category="lo", - direction="al", - }, - [0x6FB]={ - category="lo", - direction="al", - }, - [0x6FC]={ - category="lo", - direction="al", - }, - [0x6FD]={ - category="so", - direction="al", - }, - [0x6FE]={ - category="so", - direction="al", - }, - [0x6FF]={ - category="lo", - direction="al", - }, - [0x700]={ - category="po", - direction="al", - }, - [0x701]={ - category="po", - direction="al", - }, - [0x702]={ - category="po", - direction="al", - }, - [0x703]={ - category="po", - direction="al", - }, - [0x704]={ - category="po", - direction="al", - }, - [0x705]={ - category="po", - direction="al", - }, - [0x706]={ - category="po", - direction="al", - }, - [0x707]={ - category="po", - direction="al", - }, - [0x708]={ - category="po", - direction="al", - }, - [0x709]={ - category="po", - direction="al", - }, - [0x70A]={ - category="po", - direction="al", - }, - [0x70B]={ - category="po", - direction="al", - }, - [0x70C]={ - category="po", - direction="al", - }, - [0x70D]={ - category="po", - direction="al", - }, - [0x70F]={ - category="cf", - direction="al", - }, - [0x710]={ - category="lo", - direction="al", - }, - [0x711]={ - category="mn", - direction="nsm", - }, - [0x712]={ - category="lo", - direction="al", - }, - [0x713]={ - category="lo", - direction="al", - }, - [0x714]={ - category="lo", - direction="al", - }, - [0x715]={ - category="lo", - direction="al", - }, - [0x716]={ - category="lo", - direction="al", - }, - [0x717]={ - category="lo", - direction="al", - }, - [0x718]={ - category="lo", - direction="al", - }, - [0x719]={ - category="lo", - direction="al", - }, - [0x71A]={ - category="lo", - direction="al", - }, - [0x71B]={ - category="lo", - direction="al", - }, - [0x71C]={ - category="lo", - direction="al", - }, - [0x71D]={ - category="lo", - direction="al", - }, - [0x71E]={ - category="lo", - direction="al", - }, - [0x71F]={ - category="lo", - direction="al", - }, - [0x720]={ - category="lo", - direction="al", - }, - [0x721]={ - category="lo", - direction="al", - }, - [0x722]={ - category="lo", - direction="al", - }, - [0x723]={ - category="lo", - direction="al", - }, - [0x724]={ - category="lo", - direction="al", - }, - [0x725]={ - category="lo", - direction="al", - }, - [0x726]={ - category="lo", - direction="al", - }, - [0x727]={ - category="lo", - direction="al", - }, - [0x728]={ - category="lo", - direction="al", - }, - [0x729]={ - category="lo", - direction="al", - }, - [0x72A]={ - category="lo", - direction="al", - }, - [0x72B]={ - category="lo", - direction="al", - }, - [0x72C]={ - category="lo", - direction="al", - }, - [0x72D]={ - category="lo", - direction="al", - }, - [0x72E]={ - category="lo", - direction="al", - }, - [0x72F]={ - category="lo", - direction="al", - }, - [0x730]={ - category="mn", - direction="nsm", - }, - [0x731]={ - category="mn", - direction="nsm", - }, - [0x732]={ - category="mn", - direction="nsm", - }, - [0x733]={ - category="mn", - direction="nsm", - }, - [0x734]={ - category="mn", - direction="nsm", - }, - [0x735]={ - category="mn", - direction="nsm", - }, - [0x736]={ - category="mn", - direction="nsm", - }, - [0x737]={ - category="mn", - direction="nsm", - }, - [0x738]={ - category="mn", - direction="nsm", - }, - [0x739]={ - category="mn", - direction="nsm", - }, - [0x73A]={ - category="mn", - direction="nsm", - }, - [0x73B]={ - category="mn", - direction="nsm", - }, - [0x73C]={ - category="mn", - direction="nsm", - }, - [0x73D]={ - category="mn", - direction="nsm", - }, - [0x73E]={ - category="mn", - direction="nsm", - }, - [0x73F]={ - category="mn", - direction="nsm", - }, - [0x740]={ - category="mn", - direction="nsm", - }, - [0x741]={ - category="mn", - direction="nsm", - }, - [0x742]={ - category="mn", - direction="nsm", - }, - [0x743]={ - category="mn", - direction="nsm", - }, - [0x744]={ - category="mn", - direction="nsm", - }, - [0x745]={ - category="mn", - direction="nsm", - }, - [0x746]={ - category="mn", - direction="nsm", - }, - [0x747]={ - category="mn", - direction="nsm", - }, - [0x748]={ - category="mn", - direction="nsm", - }, - [0x749]={ - category="mn", - direction="nsm", - }, - [0x74A]={ - category="mn", - direction="nsm", - }, - [0x74D]={ - category="lo", - direction="al", - }, - [0x74E]={ - category="lo", - direction="al", - }, - [0x74F]={ - category="lo", - direction="al", - }, - [0x750]={ - category="lo", - direction="al", - }, - [0x751]={ - category="lo", - direction="al", - }, - [0x752]={ - category="lo", - direction="al", - }, - [0x753]={ - category="lo", - direction="al", - }, - [0x754]={ - category="lo", - direction="al", - }, - [0x755]={ - category="lo", - direction="al", - }, - [0x756]={ - category="lo", - direction="al", - }, - [0x757]={ - category="lo", - direction="al", - }, - [0x758]={ - category="lo", - direction="al", - }, - [0x759]={ - category="lo", - direction="al", - }, - [0x75A]={ - category="lo", - direction="al", - }, - [0x75B]={ - category="lo", - direction="al", - }, - [0x75C]={ - category="lo", - direction="al", - }, - [0x75D]={ - category="lo", - direction="al", - }, - [0x75E]={ - category="lo", - direction="al", - }, - [0x75F]={ - category="lo", - direction="al", - }, - [0x760]={ - category="lo", - direction="al", - }, - [0x761]={ - category="lo", - direction="al", - }, - [0x762]={ - category="lo", - direction="al", - }, - [0x763]={ - category="lo", - direction="al", - }, - [0x764]={ - category="lo", - direction="al", - }, - [0x765]={ - category="lo", - direction="al", - }, - [0x766]={ - category="lo", - direction="al", - }, - [0x767]={ - category="lo", - direction="al", - }, - [0x768]={ - category="lo", - direction="al", - }, - [0x769]={ - category="lo", - direction="al", - }, - [0x76A]={ - category="lo", - direction="al", - }, - [0x76B]={ - category="lo", - direction="al", - }, - [0x76C]={ - category="lo", - direction="al", - }, - [0x76D]={ - category="lo", - direction="al", - }, - [0x76E]={ - category="lo", - direction="al", - }, - [0x76F]={ - category="lo", - direction="al", - }, - [0x770]={ - category="lo", - direction="al", - }, - [0x771]={ - category="lo", - direction="al", - }, - [0x772]={ - category="lo", - direction="al", - }, - [0x773]={ - category="lo", - direction="al", - }, - [0x774]={ - category="lo", - direction="al", - }, - [0x775]={ - category="lo", - direction="al", - }, - [0x776]={ - category="lo", - direction="al", - }, - [0x777]={ - category="lo", - direction="al", - }, - [0x778]={ - category="lo", - direction="al", - }, - [0x779]={ - category="lo", - direction="al", - }, - [0x77A]={ - category="lo", - direction="al", - }, - [0x77B]={ - category="lo", - direction="al", - }, - [0x77C]={ - category="lo", - direction="al", - }, - [0x77D]={ - category="lo", - direction="al", - }, - [0x77E]={ - category="lo", - direction="al", - }, - [0x77F]={ - category="lo", - direction="al", - }, - [0x780]={ - category="lo", - direction="al", - }, - [0x781]={ - category="lo", - direction="al", - }, - [0x782]={ - category="lo", - direction="al", - }, - [0x783]={ - category="lo", - direction="al", - }, - [0x784]={ - category="lo", - direction="al", - }, - [0x785]={ - category="lo", - direction="al", - }, - [0x786]={ - category="lo", - direction="al", - }, - [0x787]={ - category="lo", - direction="al", - }, - [0x788]={ - category="lo", - direction="al", - }, - [0x789]={ - category="lo", - direction="al", - }, - [0x78A]={ - category="lo", - direction="al", - }, - [0x78B]={ - category="lo", - direction="al", - }, - [0x78C]={ - category="lo", - direction="al", - }, - [0x78D]={ - category="lo", - direction="al", - }, - [0x78E]={ - category="lo", - direction="al", - }, - [0x78F]={ - category="lo", - direction="al", - }, - [0x790]={ - category="lo", - direction="al", - }, - [0x791]={ - category="lo", - direction="al", - }, - [0x792]={ - category="lo", - direction="al", - }, - [0x793]={ - category="lo", - direction="al", - }, - [0x794]={ - category="lo", - direction="al", - }, - [0x795]={ - category="lo", - direction="al", - }, - [0x796]={ - category="lo", - direction="al", - }, - [0x797]={ - category="lo", - direction="al", - }, - [0x798]={ - category="lo", - direction="al", - }, - [0x799]={ - category="lo", - direction="al", - }, - [0x79A]={ - category="lo", - direction="al", - }, - [0x79B]={ - category="lo", - direction="al", - }, - [0x79C]={ - category="lo", - direction="al", - }, - [0x79D]={ - category="lo", - direction="al", - }, - [0x79E]={ - category="lo", - direction="al", - }, - [0x79F]={ - category="lo", - direction="al", - }, - [0x7A0]={ - category="lo", - direction="al", - }, - [0x7A1]={ - category="lo", - direction="al", - }, - [0x7A2]={ - category="lo", - direction="al", - }, - [0x7A3]={ - category="lo", - direction="al", - }, - [0x7A4]={ - category="lo", - direction="al", - }, - [0x7A5]={ - category="lo", - direction="al", - }, - [0x7A6]={ - category="mn", - direction="nsm", - }, - [0x7A7]={ - category="mn", - direction="nsm", - }, - [0x7A8]={ - category="mn", - direction="nsm", - }, - [0x7A9]={ - category="mn", - direction="nsm", - }, - [0x7AA]={ - category="mn", - direction="nsm", - }, - [0x7AB]={ - category="mn", - direction="nsm", - }, - [0x7AC]={ - category="mn", - direction="nsm", - }, - [0x7AD]={ - category="mn", - direction="nsm", - }, - [0x7AE]={ - category="mn", - direction="nsm", - }, - [0x7AF]={ - category="mn", - direction="nsm", - }, - [0x7B0]={ - category="mn", - direction="nsm", - }, - [0x7B1]={ - category="lo", - direction="al", - }, - [0x7C0]={ - category="nd", - direction="r", - }, - [0x7C1]={ - category="nd", - direction="r", - }, - [0x7C2]={ - category="nd", - direction="r", - }, - [0x7C3]={ - category="nd", - direction="r", - }, - [0x7C4]={ - category="nd", - direction="r", - }, - [0x7C5]={ - category="nd", - direction="r", - }, - [0x7C6]={ - category="nd", - direction="r", - }, - [0x7C7]={ - category="nd", - direction="r", - }, - [0x7C8]={ - category="nd", - direction="r", - }, - [0x7C9]={ - category="nd", - direction="r", - }, - [0x7CA]={ - category="lo", - direction="r", - }, - [0x7CB]={ - category="lo", - direction="r", - }, - [0x7CC]={ - category="lo", - direction="r", - }, - [0x7CD]={ - category="lo", - direction="r", - }, - [0x7CE]={ - category="lo", - direction="r", - }, - [0x7CF]={ - category="lo", - direction="r", - }, - [0x7D0]={ - category="lo", - direction="r", - }, - [0x7D1]={ - category="lo", - direction="r", - }, - [0x7D2]={ - category="lo", - direction="r", - }, - [0x7D3]={ - category="lo", - direction="r", - }, - [0x7D4]={ - category="lo", - direction="r", - }, - [0x7D5]={ - category="lo", - direction="r", - }, - [0x7D6]={ - category="lo", - direction="r", - }, - [0x7D7]={ - category="lo", - direction="r", - }, - [0x7D8]={ - category="lo", - direction="r", - }, - [0x7D9]={ - category="lo", - direction="r", - }, - [0x7DA]={ - category="lo", - direction="r", - }, - [0x7DB]={ - category="lo", - direction="r", - }, - [0x7DC]={ - category="lo", - direction="r", - }, - [0x7DD]={ - category="lo", - direction="r", - }, - [0x7DE]={ - category="lo", - direction="r", - }, - [0x7DF]={ - category="lo", - direction="r", - }, - [0x7E0]={ - category="lo", - direction="r", - }, - [0x7E1]={ - category="lo", - direction="r", - }, - [0x7E2]={ - category="lo", - direction="r", - }, - [0x7E3]={ - category="lo", - direction="r", - }, - [0x7E4]={ - category="lo", - direction="r", - }, - [0x7E5]={ - category="lo", - direction="r", - }, - [0x7E6]={ - category="lo", - direction="r", - }, - [0x7E7]={ - category="lo", - direction="r", - }, - [0x7E8]={ - category="lo", - direction="r", - }, - [0x7E9]={ - category="lo", - direction="r", - }, - [0x7EA]={ - category="lo", - direction="r", - }, - [0x7EB]={ - category="mn", - direction="nsm", - }, - [0x7EC]={ - category="mn", - direction="nsm", - }, - [0x7ED]={ - category="mn", - direction="nsm", - }, - [0x7EE]={ - category="mn", - direction="nsm", - }, - [0x7EF]={ - category="mn", - direction="nsm", - }, - [0x7F0]={ - category="mn", - direction="nsm", - }, - [0x7F1]={ - category="mn", - direction="nsm", - }, - [0x7F2]={ - category="mn", - direction="nsm", - }, - [0x7F3]={ - category="mn", - direction="nsm", - }, - [0x7F4]={ - category="lm", - direction="r", - }, - [0x7F5]={ - category="lm", - direction="r", - }, - [0x7F6]={ - category="so", - direction="on", - }, - [0x7F7]={ - category="po", - direction="on", - }, - [0x7F8]={ - category="po", - direction="on", - }, - [0x7F9]={ - category="po", - direction="on", - }, - [0x7FA]={ - category="lm", - direction="r", - }, - [0x800]={ - category="lo", - direction="r", - }, - [0x801]={ - category="lo", - direction="r", - }, - [0x802]={ - category="lo", - direction="r", - }, - [0x803]={ - category="lo", - direction="r", - }, - [0x804]={ - category="lo", - direction="r", - }, - [0x805]={ - category="lo", - direction="r", - }, - [0x806]={ - category="lo", - direction="r", - }, - [0x807]={ - category="lo", - direction="r", - }, - [0x808]={ - category="lo", - direction="r", - }, - [0x809]={ - category="lo", - direction="r", - }, - [0x80A]={ - category="lo", - direction="r", - }, - [0x80B]={ - category="lo", - direction="r", - }, - [0x80C]={ - category="lo", - direction="r", - }, - [0x80D]={ - category="lo", - direction="r", - }, - [0x80E]={ - category="lo", - direction="r", - }, - [0x80F]={ - category="lo", - direction="r", - }, - [0x810]={ - category="lo", - direction="r", - }, - [0x811]={ - category="lo", - direction="r", - }, - [0x812]={ - category="lo", - direction="r", - }, - [0x813]={ - category="lo", - direction="r", - }, - [0x814]={ - category="lo", - direction="r", - }, - [0x815]={ - category="lo", - direction="r", - }, - [0x816]={ - category="mn", - direction="nsm", - }, - [0x817]={ - category="mn", - direction="nsm", - }, - [0x818]={ - category="mn", - direction="nsm", - }, - [0x819]={ - category="mn", - direction="nsm", - }, - [0x81A]={ - category="lm", - direction="r", - }, - [0x81B]={ - category="mn", - direction="nsm", - }, - [0x81C]={ - category="mn", - direction="nsm", - }, - [0x81D]={ - category="mn", - direction="nsm", - }, - [0x81E]={ - category="mn", - direction="nsm", - }, - [0x81F]={ - category="mn", - direction="nsm", - }, - [0x820]={ - category="mn", - direction="nsm", - }, - [0x821]={ - category="mn", - direction="nsm", - }, - [0x822]={ - category="mn", - direction="nsm", - }, - [0x823]={ - category="mn", - direction="nsm", - }, - [0x824]={ - category="lm", - direction="r", - }, - [0x825]={ - category="mn", - direction="nsm", - }, - [0x826]={ - category="mn", - direction="nsm", - }, - [0x827]={ - category="mn", - direction="nsm", - }, - [0x828]={ - category="lm", - direction="r", - }, - [0x829]={ - category="mn", - direction="nsm", - }, - [0x82A]={ - category="mn", - direction="nsm", - }, - [0x82B]={ - category="mn", - direction="nsm", - }, - [0x82C]={ - category="mn", - direction="nsm", - }, - [0x82D]={ - category="mn", - direction="nsm", - }, - [0x830]={ - category="po", - direction="r", - }, - [0x831]={ - category="po", - direction="r", - }, - [0x832]={ - category="po", - direction="r", - }, - [0x833]={ - category="po", - direction="r", - }, - [0x834]={ - category="po", - direction="r", - }, - [0x835]={ - category="po", - direction="r", - }, - [0x836]={ - category="po", - direction="r", - }, - [0x837]={ - category="po", - direction="r", - }, - [0x838]={ - category="po", - direction="r", - }, - [0x839]={ - category="po", - direction="r", - }, - [0x83A]={ - category="po", - direction="r", - }, - [0x83B]={ - category="po", - direction="r", - }, - [0x83C]={ - category="po", - direction="r", - }, - [0x83D]={ - category="po", - direction="r", - }, - [0x83E]={ - category="po", - direction="r", - }, - [0x840]={ - category="lo", - direction="r", - }, - [0x841]={ - category="lo", - direction="r", - }, - [0x842]={ - category="lo", - direction="r", - }, - [0x843]={ - category="lo", - direction="r", - }, - [0x844]={ - category="lo", - direction="r", - }, - [0x845]={ - category="lo", - direction="r", - }, - [0x846]={ - category="lo", - direction="r", - }, - [0x847]={ - category="lo", - direction="r", - }, - [0x848]={ - category="lo", - direction="r", - }, - [0x849]={ - category="lo", - direction="r", - }, - [0x84A]={ - category="lo", - direction="r", - }, - [0x84B]={ - category="lo", - direction="r", - }, - [0x84C]={ - category="lo", - direction="r", - }, - [0x84D]={ - category="lo", - direction="r", - }, - [0x84E]={ - category="lo", - direction="r", - }, - [0x84F]={ - category="lo", - direction="r", - }, - [0x850]={ - category="lo", - direction="r", - }, - [0x851]={ - category="lo", - direction="r", - }, - [0x852]={ - category="lo", - direction="r", - }, - [0x853]={ - category="lo", - direction="r", - }, - [0x854]={ - category="lo", - direction="r", - }, - [0x855]={ - category="lo", - direction="r", - }, - [0x856]={ - category="lo", - direction="r", - }, - [0x857]={ - category="lo", - direction="r", - }, - [0x858]={ - category="lo", - direction="r", - }, - [0x859]={ - category="mn", - direction="nsm", - }, - [0x85A]={ - category="mn", - direction="nsm", - }, - [0x85B]={ - category="mn", - direction="nsm", - }, - [0x85E]={ - category="po", - direction="r", - }, - [0x8A0]={ - category="lo", - direction="al", - }, - [0x8A1]={ - category="lo", - direction="al", - }, - [0x8A2]={ - category="lo", - direction="al", - }, - [0x8A3]={ - category="lo", - direction="al", - }, - [0x8A4]={ - category="lo", - direction="al", - }, - [0x8A5]={ - category="lo", - direction="al", - }, - [0x8A6]={ - category="lo", - direction="al", - }, - [0x8A7]={ - category="lo", - direction="al", - }, - [0x8A8]={ - category="lo", - direction="al", - }, - [0x8A9]={ - category="lo", - direction="al", - }, - [0x8AA]={ - category="lo", - direction="al", - }, - [0x8AB]={ - category="lo", - direction="al", - }, - [0x8AC]={ - category="lo", - direction="al", - }, - [0x8AD]={ - category="lo", - direction="al", - }, - [0x8AE]={ - category="lo", - direction="al", - }, - [0x8AF]={ - category="lo", - direction="al", - }, - [0x8B0]={ - category="lo", - direction="al", - }, - [0x8B1]={ - category="lo", - direction="al", - }, - [0x8B2]={ - category="lo", - direction="al", - }, - [0x8B3]={ - category="lo", - direction="al", - }, - [0x8B4]={ - category="lo", - direction="al", - }, - [0x8B6]={ - category="lo", - direction="al", - }, - [0x8B7]={ - category="lo", - direction="al", - }, - [0x8B8]={ - category="lo", - direction="al", - }, - [0x8B9]={ - category="lo", - direction="al", - }, - [0x8BA]={ - category="lo", - direction="al", - }, - [0x8BB]={ - category="lo", - direction="al", - }, - [0x8BC]={ - category="lo", - direction="al", - }, - [0x8BD]={ - category="lo", - direction="al", - }, - [0x8D4]={ - category="mn", - direction="nsm", - }, - [0x8D5]={ - category="mn", - direction="nsm", - }, - [0x8D6]={ - category="mn", - direction="nsm", - }, - [0x8D7]={ - category="mn", - direction="nsm", - }, - [0x8D8]={ - category="mn", - direction="nsm", - }, - [0x8D9]={ - category="mn", - direction="nsm", - }, - [0x8DA]={ - category="mn", - direction="nsm", - }, - [0x8DB]={ - category="mn", - direction="nsm", - }, - [0x8DC]={ - category="mn", - direction="nsm", - }, - [0x8DD]={ - category="mn", - direction="nsm", - }, - [0x8DE]={ - category="mn", - direction="nsm", - }, - [0x8DF]={ - category="mn", - direction="nsm", - }, - [0x8E0]={ - category="mn", - direction="nsm", - }, - [0x8E1]={ - category="mn", - direction="nsm", - }, - [0x8E2]={ - category="cf", - direction="an", - }, - [0x8E3]={ - category="mn", - direction="nsm", - }, - [0x8E4]={ - category="mn", - direction="nsm", - }, - [0x8E5]={ - category="mn", - direction="nsm", - }, - [0x8E6]={ - category="mn", - direction="nsm", - }, - [0x8E7]={ - category="mn", - direction="nsm", - }, - [0x8E8]={ - category="mn", - direction="nsm", - }, - [0x8E9]={ - category="mn", - direction="nsm", - }, - [0x8EA]={ - category="mn", - direction="nsm", - }, - [0x8EB]={ - category="mn", - direction="nsm", - }, - [0x8EC]={ - category="mn", - direction="nsm", - }, - [0x8ED]={ - category="mn", - direction="nsm", - }, - [0x8EE]={ - category="mn", - direction="nsm", - }, - [0x8EF]={ - category="mn", - direction="nsm", - }, - [0x8F0]={ - category="mn", - direction="nsm", - }, - [0x8F1]={ - category="mn", - direction="nsm", - }, - [0x8F2]={ - category="mn", - direction="nsm", - }, - [0x8F3]={ - category="mn", - direction="nsm", - }, - [0x8F4]={ - category="mn", - direction="nsm", - }, - [0x8F5]={ - category="mn", - direction="nsm", - }, - [0x8F6]={ - category="mn", - direction="nsm", - }, - [0x8F7]={ - category="mn", - direction="nsm", - }, - [0x8F8]={ - category="mn", - direction="nsm", - }, - [0x8F9]={ - category="mn", - direction="nsm", - }, - [0x8FA]={ - category="mn", - direction="nsm", - }, - [0x8FB]={ - category="mn", - direction="nsm", - }, - [0x8FC]={ - category="mn", - direction="nsm", - }, - [0x8FD]={ - category="mn", - direction="nsm", - }, - [0x8FE]={ - category="mn", - direction="nsm", - }, - [0x8FF]={ - category="mn", - direction="nsm", - }, - [0x900]={ - category="mn", - direction="nsm", - }, - [0x901]={ - category="mn", - direction="nsm", - }, - [0x902]={ - category="mn", - direction="nsm", - }, - [0x903]={ - category="mc", - direction="l", - }, - [0x904]={ - category="lo", - direction="l", - }, - [0x905]={ - category="lo", - direction="l", - }, - [0x906]={ - category="lo", - direction="l", - }, - [0x907]={ - category="lo", - direction="l", - }, - [0x908]={ - category="lo", - direction="l", - }, - [0x909]={ - category="lo", - direction="l", - }, - [0x90A]={ - category="lo", - direction="l", - }, - [0x90B]={ - category="lo", - direction="l", - }, - [0x90C]={ - category="lo", - direction="l", - }, - [0x90D]={ - category="lo", - direction="l", - }, - [0x90E]={ - category="lo", - direction="l", - }, - [0x90F]={ - category="lo", - direction="l", - }, - [0x910]={ - category="lo", - direction="l", - }, - [0x911]={ - category="lo", - direction="l", - }, - [0x912]={ - category="lo", - direction="l", - }, - [0x913]={ - category="lo", - direction="l", - }, - [0x914]={ - category="lo", - direction="l", - }, - [0x915]={ - category="lo", - direction="l", - }, - [0x916]={ - category="lo", - direction="l", - }, - [0x917]={ - category="lo", - direction="l", - }, - [0x918]={ - category="lo", - direction="l", - }, - [0x919]={ - category="lo", - direction="l", - }, - [0x91A]={ - category="lo", - direction="l", - }, - [0x91B]={ - category="lo", - direction="l", - }, - [0x91C]={ - category="lo", - direction="l", - }, - [0x91D]={ - category="lo", - direction="l", - }, - [0x91E]={ - category="lo", - direction="l", - }, - [0x91F]={ - category="lo", - direction="l", - }, - [0x920]={ - category="lo", - direction="l", - }, - [0x921]={ - category="lo", - direction="l", - }, - [0x922]={ - category="lo", - direction="l", - }, - [0x923]={ - category="lo", - direction="l", - }, - [0x924]={ - category="lo", - direction="l", - }, - [0x925]={ - category="lo", - direction="l", - }, - [0x926]={ - category="lo", - direction="l", - }, - [0x927]={ - category="lo", - direction="l", - }, - [0x928]={ - category="lo", - direction="l", - }, - [0x929]={ - category="lo", - direction="l", - }, - [0x92A]={ - category="lo", - direction="l", - }, - [0x92B]={ - category="lo", - direction="l", - }, - [0x92C]={ - category="lo", - direction="l", - }, - [0x92D]={ - category="lo", - direction="l", - }, - [0x92E]={ - category="lo", - direction="l", - }, - [0x92F]={ - category="lo", - direction="l", - }, - [0x930]={ - category="lo", - direction="l", - }, - [0x931]={ - category="lo", - direction="l", - }, - [0x932]={ - category="lo", - direction="l", - }, - [0x933]={ - category="lo", - direction="l", - }, - [0x934]={ - category="lo", - direction="l", - }, - [0x935]={ - category="lo", - direction="l", - }, - [0x936]={ - category="lo", - direction="l", - }, - [0x937]={ - category="lo", - direction="l", - }, - [0x938]={ - category="lo", - direction="l", - }, - [0x939]={ - category="lo", - direction="l", - }, - [0x93A]={ - category="mn", - direction="nsm", - }, - [0x93B]={ - category="mc", - direction="l", - }, - [0x93C]={ - category="mn", - direction="nsm", - }, - [0x93D]={ - category="lo", - direction="l", - }, - [0x93E]={ - category="mc", - direction="l", - }, - [0x93F]={ - category="mc", - direction="l", - }, - [0x940]={ - category="mc", - direction="l", - }, - [0x941]={ - category="mn", - direction="nsm", - }, - [0x942]={ - category="mn", - direction="nsm", - }, - [0x943]={ - category="mn", - direction="nsm", - }, - [0x944]={ - category="mn", - direction="nsm", - }, - [0x945]={ - category="mn", - direction="nsm", - }, - [0x946]={ - category="mn", - direction="nsm", - }, - [0x947]={ - category="mn", - direction="nsm", - }, - [0x948]={ - category="mn", - direction="nsm", - }, - [0x949]={ - category="mc", - direction="l", - }, - [0x94A]={ - category="mc", - direction="l", - }, - [0x94B]={ - category="mc", - direction="l", - }, - [0x94C]={ - category="mc", - direction="l", - }, - [0x94D]={ - category="mn", - direction="nsm", - }, - [0x94E]={ - category="mc", - direction="l", - }, - [0x94F]={ - category="mc", - direction="l", - }, - [0x950]={ - category="lo", - direction="l", - }, - [0x951]={ - category="mn", - direction="nsm", - }, - [0x952]={ - category="mn", - direction="nsm", - }, - [0x953]={ - category="mn", - direction="nsm", - }, - [0x954]={ - category="mn", - direction="nsm", - }, - [0x955]={ - category="mn", - direction="nsm", - }, - [0x956]={ - category="mn", - direction="nsm", - }, - [0x957]={ - category="mn", - direction="nsm", - }, - [0x958]={ - category="lo", - direction="l", - }, - [0x959]={ - category="lo", - direction="l", - }, - [0x95A]={ - category="lo", - direction="l", - }, - [0x95B]={ - category="lo", - direction="l", - }, - [0x95C]={ - category="lo", - direction="l", - }, - [0x95D]={ - category="lo", - direction="l", - }, - [0x95E]={ - category="lo", - direction="l", - }, - [0x95F]={ - category="lo", - direction="l", - }, - [0x960]={ - category="lo", - direction="l", - }, - [0x961]={ - category="lo", - direction="l", - }, - [0x962]={ - category="mn", - direction="nsm", - }, - [0x963]={ - category="mn", - direction="nsm", - }, - [0x964]={ - category="po", - direction="l", - }, - [0x965]={ - category="po", - direction="l", - }, - [0x966]={ - category="nd", - direction="l", - }, - [0x967]={ - category="nd", - direction="l", - }, - [0x968]={ - category="nd", - direction="l", - }, - [0x969]={ - category="nd", - direction="l", - }, - [0x96A]={ - category="nd", - direction="l", - }, - [0x96B]={ - category="nd", - direction="l", - }, - [0x96C]={ - category="nd", - direction="l", - }, - [0x96D]={ - category="nd", - direction="l", - }, - [0x96E]={ - category="nd", - direction="l", - }, - [0x96F]={ - category="nd", - direction="l", - }, - [0x970]={ - category="po", - direction="l", - }, - [0x971]={ - category="lm", - direction="l", - }, - [0x972]={ - category="lo", - direction="l", - }, - [0x973]={ - category="lo", - direction="l", - }, - [0x974]={ - category="lo", - direction="l", - }, - [0x975]={ - category="lo", - direction="l", - }, - [0x976]={ - category="lo", - direction="l", - }, - [0x977]={ - category="lo", - direction="l", - }, - [0x978]={ - category="lo", - direction="l", - }, - [0x979]={ - category="lo", - direction="l", - }, - [0x97A]={ - category="lo", - direction="l", - }, - [0x97B]={ - category="lo", - direction="l", - }, - [0x97C]={ - category="lo", - direction="l", - }, - [0x97D]={ - category="lo", - direction="l", - }, - [0x97E]={ - category="lo", - direction="l", - }, - [0x97F]={ - category="lo", - direction="l", - }, - [0x980]={ - category="lo", - direction="l", - }, - [0x981]={ - category="mn", - direction="nsm", - }, - [0x982]={ - category="mc", - direction="l", - }, - [0x983]={ - category="mc", - direction="l", - }, - [0x985]={ - category="lo", - direction="l", - }, - [0x986]={ - category="lo", - direction="l", - }, - [0x987]={ - category="lo", - direction="l", - }, - [0x988]={ - category="lo", - direction="l", - }, - [0x989]={ - category="lo", - direction="l", - }, - [0x98A]={ - category="lo", - direction="l", - }, - [0x98B]={ - category="lo", - direction="l", - }, - [0x98C]={ - category="lo", - direction="l", - }, - [0x98F]={ - category="lo", - direction="l", - }, - [0x990]={ - category="lo", - direction="l", - }, - [0x993]={ - category="lo", - direction="l", - }, - [0x994]={ - category="lo", - direction="l", - }, - [0x995]={ - category="lo", - direction="l", - }, - [0x996]={ - category="lo", - direction="l", - }, - [0x997]={ - category="lo", - direction="l", - }, - [0x998]={ - category="lo", - direction="l", - }, - [0x999]={ - category="lo", - direction="l", - }, - [0x99A]={ - category="lo", - direction="l", - }, - [0x99B]={ - category="lo", - direction="l", - }, - [0x99C]={ - category="lo", - direction="l", - }, - [0x99D]={ - category="lo", - direction="l", - }, - [0x99E]={ - category="lo", - direction="l", - }, - [0x99F]={ - category="lo", - direction="l", - }, - [0x9A0]={ - category="lo", - direction="l", - }, - [0x9A1]={ - category="lo", - direction="l", - }, - [0x9A2]={ - category="lo", - direction="l", - }, - [0x9A3]={ - category="lo", - direction="l", - }, - [0x9A4]={ - category="lo", - direction="l", - }, - [0x9A5]={ - category="lo", - direction="l", - }, - [0x9A6]={ - category="lo", - direction="l", - }, - [0x9A7]={ - category="lo", - direction="l", - }, - [0x9A8]={ - category="lo", - direction="l", - }, - [0x9AA]={ - category="lo", - direction="l", - }, - [0x9AB]={ - category="lo", - direction="l", - }, - [0x9AC]={ - category="lo", - direction="l", - }, - [0x9AD]={ - category="lo", - direction="l", - }, - [0x9AE]={ - category="lo", - direction="l", - }, - [0x9AF]={ - category="lo", - direction="l", - }, - [0x9B0]={ - category="lo", - direction="l", - }, - [0x9B2]={ - category="lo", - direction="l", - }, - [0x9B6]={ - category="lo", - direction="l", - }, - [0x9B7]={ - category="lo", - direction="l", - }, - [0x9B8]={ - category="lo", - direction="l", - }, - [0x9B9]={ - category="lo", - direction="l", - }, - [0x9BC]={ - category="mn", - direction="nsm", - }, - [0x9BD]={ - category="lo", - direction="l", - }, - [0x9BE]={ - category="mc", - direction="l", - }, - [0x9BF]={ - category="mc", - direction="l", - }, - [0x9C0]={ - category="mc", - direction="l", - }, - [0x9C1]={ - category="mn", - direction="nsm", - }, - [0x9C2]={ - category="mn", - direction="nsm", - }, - [0x9C3]={ - category="mn", - direction="nsm", - }, - [0x9C4]={ - category="mn", - direction="nsm", - }, - [0x9C7]={ - category="mc", - direction="l", - }, - [0x9C8]={ - category="mc", - direction="l", - }, - [0x9CB]={ - category="mc", - direction="l", - }, - [0x9CC]={ - category="mc", - direction="l", - }, - [0x9CD]={ - category="mn", - direction="nsm", - }, - [0x9CE]={ - category="lo", - direction="l", - }, - [0x9D7]={ - category="mc", - direction="l", - }, - [0x9DC]={ - category="lo", - direction="l", - }, - [0x9DD]={ - category="lo", - direction="l", - }, - [0x9DF]={ - category="lo", - direction="l", - }, - [0x9E0]={ - category="lo", - direction="l", - }, - [0x9E1]={ - category="lo", - direction="l", - }, - [0x9E2]={ - category="mn", - direction="nsm", - }, - [0x9E3]={ - category="mn", - direction="nsm", - }, - [0x9E6]={ - category="nd", - direction="l", - }, - [0x9E7]={ - category="nd", - direction="l", - }, - [0x9E8]={ - category="nd", - direction="l", - }, - [0x9E9]={ - category="nd", - direction="l", - }, - [0x9EA]={ - category="nd", - direction="l", - }, - [0x9EB]={ - category="nd", - direction="l", - }, - [0x9EC]={ - category="nd", - direction="l", - }, - [0x9ED]={ - category="nd", - direction="l", - }, - [0x9EE]={ - category="nd", - direction="l", - }, - [0x9EF]={ - category="nd", - direction="l", - }, - [0x9F0]={ - category="lo", - direction="l", - }, - [0x9F1]={ - category="lo", - direction="l", - }, - [0x9F2]={ - category="sc", - direction="et", - }, - [0x9F3]={ - category="sc", - direction="et", - }, - [0x9F4]={ - category="no", - direction="l", - }, - [0x9F5]={ - category="no", - direction="l", - }, - [0x9F6]={ - category="no", - direction="l", - }, - [0x9F7]={ - category="no", - direction="l", - }, - [0x9F8]={ - category="no", - direction="l", - }, - [0x9F9]={ - category="no", - direction="l", - }, - [0x9FA]={ - category="so", - direction="l", - }, - [0x9FB]={ - category="sc", - direction="et", - }, - [0xA01]={ - category="mn", - direction="nsm", - }, - [0xA02]={ - category="mn", - direction="nsm", - }, - [0xA03]={ - category="mc", - direction="l", - }, - [0xA05]={ - category="lo", - direction="l", - }, - [0xA06]={ - category="lo", - direction="l", - }, - [0xA07]={ - category="lo", - direction="l", - }, - [0xA08]={ - category="lo", - direction="l", - }, - [0xA09]={ - category="lo", - direction="l", - }, - [0xA0A]={ - category="lo", - direction="l", - }, - [0xA0F]={ - category="lo", - direction="l", - }, - [0xA10]={ - category="lo", - direction="l", - }, - [0xA13]={ - category="lo", - direction="l", - }, - [0xA14]={ - category="lo", - direction="l", - }, - [0xA15]={ - category="lo", - direction="l", - }, - [0xA16]={ - category="lo", - direction="l", - }, - [0xA17]={ - category="lo", - direction="l", - }, - [0xA18]={ - category="lo", - direction="l", - }, - [0xA19]={ - category="lo", - direction="l", - }, - [0xA1A]={ - category="lo", - direction="l", - }, - [0xA1B]={ - category="lo", - direction="l", - }, - [0xA1C]={ - category="lo", - direction="l", - }, - [0xA1D]={ - category="lo", - direction="l", - }, - [0xA1E]={ - category="lo", - direction="l", - }, - [0xA1F]={ - category="lo", - direction="l", - }, - [0xA20]={ - category="lo", - direction="l", - }, - [0xA21]={ - category="lo", - direction="l", - }, - [0xA22]={ - category="lo", - direction="l", - }, - [0xA23]={ - category="lo", - direction="l", - }, - [0xA24]={ - category="lo", - direction="l", - }, - [0xA25]={ - category="lo", - direction="l", - }, - [0xA26]={ - category="lo", - direction="l", - }, - [0xA27]={ - category="lo", - direction="l", - }, - [0xA28]={ - category="lo", - direction="l", - }, - [0xA2A]={ - category="lo", - direction="l", - }, - [0xA2B]={ - category="lo", - direction="l", - }, - [0xA2C]={ - category="lo", - direction="l", - }, - [0xA2D]={ - category="lo", - direction="l", - }, - [0xA2E]={ - category="lo", - direction="l", - }, - [0xA2F]={ - category="lo", - direction="l", - }, - [0xA30]={ - category="lo", - direction="l", - }, - [0xA32]={ - category="lo", - direction="l", - }, - [0xA33]={ - category="lo", - direction="l", - }, - [0xA35]={ - category="lo", - direction="l", - }, - [0xA36]={ - category="lo", - direction="l", - }, - [0xA38]={ - category="lo", - direction="l", - }, - [0xA39]={ - category="lo", - direction="l", - }, - [0xA3C]={ - category="mn", - direction="nsm", - }, - [0xA3E]={ - category="mc", - direction="l", - }, - [0xA3F]={ - category="mc", - direction="l", - }, - [0xA40]={ - category="mc", - direction="l", - }, - [0xA41]={ - category="mn", - direction="nsm", - }, - [0xA42]={ - category="mn", - direction="nsm", - }, - [0xA47]={ - category="mn", - direction="nsm", - }, - [0xA48]={ - category="mn", - direction="nsm", - }, - [0xA4B]={ - category="mn", - direction="nsm", - }, - [0xA4C]={ - category="mn", - direction="nsm", - }, - [0xA4D]={ - category="mn", - direction="nsm", - }, - [0xA51]={ - category="mn", - direction="nsm", - }, - [0xA59]={ - category="lo", - direction="l", - }, - [0xA5A]={ - category="lo", - direction="l", - }, - [0xA5B]={ - category="lo", - direction="l", - }, - [0xA5C]={ - category="lo", - direction="l", - }, - [0xA5E]={ - category="lo", - direction="l", - }, - [0xA66]={ - category="nd", - direction="l", - }, - [0xA67]={ - category="nd", - direction="l", - }, - [0xA68]={ - category="nd", - direction="l", - }, - [0xA69]={ - category="nd", - direction="l", - }, - [0xA6A]={ - category="nd", - direction="l", - }, - [0xA6B]={ - category="nd", - direction="l", - }, - [0xA6C]={ - category="nd", - direction="l", - }, - [0xA6D]={ - category="nd", - direction="l", - }, - [0xA6E]={ - category="nd", - direction="l", - }, - [0xA6F]={ - category="nd", - direction="l", - }, - [0xA70]={ - category="mn", - direction="nsm", - }, - [0xA71]={ - category="mn", - direction="nsm", - }, - [0xA72]={ - category="lo", - direction="l", - }, - [0xA73]={ - category="lo", - direction="l", - }, - [0xA74]={ - category="lo", - direction="l", - }, - [0xA75]={ - category="mn", - direction="nsm", - }, - [0xA81]={ - category="mn", - direction="nsm", - }, - [0xA82]={ - category="mn", - direction="nsm", - }, - [0xA83]={ - category="mc", - direction="l", - }, - [0xA85]={ - category="lo", - direction="l", - }, - [0xA86]={ - category="lo", - direction="l", - }, - [0xA87]={ - category="lo", - direction="l", - }, - [0xA88]={ - category="lo", - direction="l", - }, - [0xA89]={ - category="lo", - direction="l", - }, - [0xA8A]={ - category="lo", - direction="l", - }, - [0xA8B]={ - category="lo", - direction="l", - }, - [0xA8C]={ - category="lo", - direction="l", - }, - [0xA8D]={ - category="lo", - direction="l", - }, - [0xA8F]={ - category="lo", - direction="l", - }, - [0xA90]={ - category="lo", - direction="l", - }, - [0xA91]={ - category="lo", - direction="l", - }, - [0xA93]={ - category="lo", - direction="l", - }, - [0xA94]={ - category="lo", - direction="l", - }, - [0xA95]={ - category="lo", - direction="l", - }, - [0xA96]={ - category="lo", - direction="l", - }, - [0xA97]={ - category="lo", - direction="l", - }, - [0xA98]={ - category="lo", - direction="l", - }, - [0xA99]={ - category="lo", - direction="l", - }, - [0xA9A]={ - category="lo", - direction="l", - }, - [0xA9B]={ - category="lo", - direction="l", - }, - [0xA9C]={ - category="lo", - direction="l", - }, - [0xA9D]={ - category="lo", - direction="l", - }, - [0xA9E]={ - category="lo", - direction="l", - }, - [0xA9F]={ - category="lo", - direction="l", - }, - [0xAA0]={ - category="lo", - direction="l", - }, - [0xAA1]={ - category="lo", - direction="l", - }, - [0xAA2]={ - category="lo", - direction="l", - }, - [0xAA3]={ - category="lo", - direction="l", - }, - [0xAA4]={ - category="lo", - direction="l", - }, - [0xAA5]={ - category="lo", - direction="l", - }, - [0xAA6]={ - category="lo", - direction="l", - }, - [0xAA7]={ - category="lo", - direction="l", - }, - [0xAA8]={ - category="lo", - direction="l", - }, - [0xAAA]={ - category="lo", - direction="l", - }, - [0xAAB]={ - category="lo", - direction="l", - }, - [0xAAC]={ - category="lo", - direction="l", - }, - [0xAAD]={ - category="lo", - direction="l", - }, - [0xAAE]={ - category="lo", - direction="l", - }, - [0xAAF]={ - category="lo", - direction="l", - }, - [0xAB0]={ - category="lo", - direction="l", - }, - [0xAB2]={ - category="lo", - direction="l", - }, - [0xAB3]={ - category="lo", - direction="l", - }, - [0xAB5]={ - category="lo", - direction="l", - }, - [0xAB6]={ - category="lo", - direction="l", - }, - [0xAB7]={ - category="lo", - direction="l", - }, - [0xAB8]={ - category="lo", - direction="l", - }, - [0xAB9]={ - category="lo", - direction="l", - }, - [0xABC]={ - category="mn", - direction="nsm", - }, - [0xABD]={ - category="lo", - direction="l", - }, - [0xABE]={ - category="mc", - direction="l", - }, - [0xABF]={ - category="mc", - direction="l", - }, - [0xAC0]={ - category="mc", - direction="l", - }, - [0xAC1]={ - category="mn", - direction="nsm", - }, - [0xAC2]={ - category="mn", - direction="nsm", - }, - [0xAC3]={ - category="mn", - direction="nsm", - }, - [0xAC4]={ - category="mn", - direction="nsm", - }, - [0xAC5]={ - category="mn", - direction="nsm", - }, - [0xAC7]={ - category="mn", - direction="nsm", - }, - [0xAC8]={ - category="mn", - direction="nsm", - }, - [0xAC9]={ - category="mc", - direction="l", - }, - [0xACB]={ - category="mc", - direction="l", - }, - [0xACC]={ - category="mc", - direction="l", - }, - [0xACD]={ - category="mn", - direction="nsm", - }, - [0xAD0]={ - category="lo", - direction="l", - }, - [0xAE0]={ - category="lo", - direction="l", - }, - [0xAE1]={ - category="lo", - direction="l", - }, - [0xAE2]={ - category="mn", - direction="nsm", - }, - [0xAE3]={ - category="mn", - direction="nsm", - }, - [0xAE6]={ - category="nd", - direction="l", - }, - [0xAE7]={ - category="nd", - direction="l", - }, - [0xAE8]={ - category="nd", - direction="l", - }, - [0xAE9]={ - category="nd", - direction="l", - }, - [0xAEA]={ - category="nd", - direction="l", - }, - [0xAEB]={ - category="nd", - direction="l", - }, - [0xAEC]={ - category="nd", - direction="l", - }, - [0xAED]={ - category="nd", - direction="l", - }, - [0xAEE]={ - category="nd", - direction="l", - }, - [0xAEF]={ - category="nd", - direction="l", - }, - [0xAF0]={ - category="po", - direction="l", - }, - [0xAF1]={ - category="sc", - direction="et", - }, - [0xAF9]={ - category="lo", - direction="l", - }, - [0xB01]={ - category="mn", - direction="nsm", - }, - [0xB02]={ - category="mc", - direction="l", - }, - [0xB03]={ - category="mc", - direction="l", - }, - [0xB05]={ - category="lo", - direction="l", - }, - [0xB06]={ - category="lo", - direction="l", - }, - [0xB07]={ - category="lo", - direction="l", - }, - [0xB08]={ - category="lo", - direction="l", - }, - [0xB09]={ - category="lo", - direction="l", - }, - [0xB0A]={ - category="lo", - direction="l", - }, - [0xB0B]={ - category="lo", - direction="l", - }, - [0xB0C]={ - category="lo", - direction="l", - }, - [0xB0F]={ - category="lo", - direction="l", - }, - [0xB10]={ - category="lo", - direction="l", - }, - [0xB13]={ - category="lo", - direction="l", - }, - [0xB14]={ - category="lo", - direction="l", - }, - [0xB15]={ - category="lo", - direction="l", - }, - [0xB16]={ - category="lo", - direction="l", - }, - [0xB17]={ - category="lo", - direction="l", - }, - [0xB18]={ - category="lo", - direction="l", - }, - [0xB19]={ - category="lo", - direction="l", - }, - [0xB1A]={ - category="lo", - direction="l", - }, - [0xB1B]={ - category="lo", - direction="l", - }, - [0xB1C]={ - category="lo", - direction="l", - }, - [0xB1D]={ - category="lo", - direction="l", - }, - [0xB1E]={ - category="lo", - direction="l", - }, - [0xB1F]={ - category="lo", - direction="l", - }, - [0xB20]={ - category="lo", - direction="l", - }, - [0xB21]={ - category="lo", - direction="l", - }, - [0xB22]={ - category="lo", - direction="l", - }, - [0xB23]={ - category="lo", - direction="l", - }, - [0xB24]={ - category="lo", - direction="l", - }, - [0xB25]={ - category="lo", - direction="l", - }, - [0xB26]={ - category="lo", - direction="l", - }, - [0xB27]={ - category="lo", - direction="l", - }, - [0xB28]={ - category="lo", - direction="l", - }, - [0xB2A]={ - category="lo", - direction="l", - }, - [0xB2B]={ - category="lo", - direction="l", - }, - [0xB2C]={ - category="lo", - direction="l", - }, - [0xB2D]={ - category="lo", - direction="l", - }, - [0xB2E]={ - category="lo", - direction="l", - }, - [0xB2F]={ - category="lo", - direction="l", - }, - [0xB30]={ - category="lo", - direction="l", - }, - [0xB32]={ - category="lo", - direction="l", - }, - [0xB33]={ - category="lo", - direction="l", - }, - [0xB35]={ - category="lo", - direction="l", - }, - [0xB36]={ - category="lo", - direction="l", - }, - [0xB37]={ - category="lo", - direction="l", - }, - [0xB38]={ - category="lo", - direction="l", - }, - [0xB39]={ - category="lo", - direction="l", - }, - [0xB3C]={ - category="mn", - direction="nsm", - }, - [0xB3D]={ - category="lo", - direction="l", - }, - [0xB3E]={ - category="mc", - direction="l", - }, - [0xB3F]={ - category="mn", - direction="nsm", - }, - [0xB40]={ - category="mc", - direction="l", - }, - [0xB41]={ - category="mn", - direction="nsm", - }, - [0xB42]={ - category="mn", - direction="nsm", - }, - [0xB43]={ - category="mn", - direction="nsm", - }, - [0xB44]={ - category="mn", - direction="nsm", - }, - [0xB47]={ - category="mc", - direction="l", - }, - [0xB48]={ - category="mc", - direction="l", - }, - [0xB4B]={ - category="mc", - direction="l", - }, - [0xB4C]={ - category="mc", - direction="l", - }, - [0xB4D]={ - category="mn", - direction="nsm", - }, - [0xB56]={ - category="mn", - direction="nsm", - }, - [0xB57]={ - category="mc", - direction="l", - }, - [0xB5C]={ - category="lo", - direction="l", - }, - [0xB5D]={ - category="lo", - direction="l", - }, - [0xB5F]={ - category="lo", - direction="l", - }, - [0xB60]={ - category="lo", - direction="l", - }, - [0xB61]={ - category="lo", - direction="l", - }, - [0xB62]={ - category="mn", - direction="nsm", - }, - [0xB63]={ - category="mn", - direction="nsm", - }, - [0xB66]={ - category="nd", - direction="l", - }, - [0xB67]={ - category="nd", - direction="l", - }, - [0xB68]={ - category="nd", - direction="l", - }, - [0xB69]={ - category="nd", - direction="l", - }, - [0xB6A]={ - category="nd", - direction="l", - }, - [0xB6B]={ - category="nd", - direction="l", - }, - [0xB6C]={ - category="nd", - direction="l", - }, - [0xB6D]={ - category="nd", - direction="l", - }, - [0xB6E]={ - category="nd", - direction="l", - }, - [0xB6F]={ - category="nd", - direction="l", - }, - [0xB70]={ - category="so", - direction="l", - }, - [0xB71]={ - category="lo", - direction="l", - }, - [0xB72]={ - category="no", - direction="l", - }, - [0xB73]={ - category="no", - direction="l", - }, - [0xB74]={ - category="no", - direction="l", - }, - [0xB75]={ - category="no", - direction="l", - }, - [0xB76]={ - category="no", - direction="l", - }, - [0xB77]={ - category="no", - direction="l", - }, - [0xB82]={ - category="mn", - direction="nsm", - }, - [0xB83]={ - category="lo", - direction="l", - }, - [0xB85]={ - category="lo", - direction="l", - }, - [0xB86]={ - category="lo", - direction="l", - }, - [0xB87]={ - category="lo", - direction="l", - }, - [0xB88]={ - category="lo", - direction="l", - }, - [0xB89]={ - category="lo", - direction="l", - }, - [0xB8A]={ - category="lo", - direction="l", - }, - [0xB8E]={ - category="lo", - direction="l", - }, - [0xB8F]={ - category="lo", - direction="l", - }, - [0xB90]={ - category="lo", - direction="l", - }, - [0xB92]={ - category="lo", - direction="l", - }, - [0xB93]={ - category="lo", - direction="l", - }, - [0xB94]={ - category="lo", - direction="l", - }, - [0xB95]={ - category="lo", - direction="l", - }, - [0xB99]={ - category="lo", - direction="l", - }, - [0xB9A]={ - category="lo", - direction="l", - }, - [0xB9C]={ - category="lo", - direction="l", - }, - [0xB9E]={ - category="lo", - direction="l", - }, - [0xB9F]={ - category="lo", - direction="l", - }, - [0xBA3]={ - category="lo", - direction="l", - }, - [0xBA4]={ - category="lo", - direction="l", - }, - [0xBA8]={ - category="lo", - direction="l", - }, - [0xBA9]={ - category="lo", - direction="l", - }, - [0xBAA]={ - category="lo", - direction="l", - }, - [0xBAE]={ - category="lo", - direction="l", - }, - [0xBAF]={ - category="lo", - direction="l", - }, - [0xBB0]={ - category="lo", - direction="l", - }, - [0xBB1]={ - category="lo", - direction="l", - }, - [0xBB2]={ - category="lo", - direction="l", - }, - [0xBB3]={ - category="lo", - direction="l", - }, - [0xBB4]={ - category="lo", - direction="l", - }, - [0xBB5]={ - category="lo", - direction="l", - }, - [0xBB6]={ - category="lo", - direction="l", - }, - [0xBB7]={ - category="lo", - direction="l", - }, - [0xBB8]={ - category="lo", - direction="l", - }, - [0xBB9]={ - category="lo", - direction="l", - }, - [0xBBE]={ - category="mc", - direction="l", - }, - [0xBBF]={ - category="mc", - direction="l", - }, - [0xBC0]={ - category="mn", - direction="nsm", - }, - [0xBC1]={ - category="mc", - direction="l", - }, - [0xBC2]={ - category="mc", - direction="l", - }, - [0xBC6]={ - category="mc", - direction="l", - }, - [0xBC7]={ - category="mc", - direction="l", - }, - [0xBC8]={ - category="mc", - direction="l", - }, - [0xBCA]={ - category="mc", - direction="l", - }, - [0xBCB]={ - category="mc", - direction="l", - }, - [0xBCC]={ - category="mc", - direction="l", - }, - [0xBCD]={ - category="mn", - direction="nsm", - }, - [0xBD0]={ - category="lo", - direction="l", - }, - [0xBD7]={ - category="mc", - direction="l", - }, - [0xBE6]={ - category="nd", - direction="l", - }, - [0xBE7]={ - category="nd", - direction="l", - }, - [0xBE8]={ - category="nd", - direction="l", - }, - [0xBE9]={ - category="nd", - direction="l", - }, - [0xBEA]={ - category="nd", - direction="l", - }, - [0xBEB]={ - category="nd", - direction="l", - }, - [0xBEC]={ - category="nd", - direction="l", - }, - [0xBED]={ - category="nd", - direction="l", - }, - [0xBEE]={ - category="nd", - direction="l", - }, - [0xBEF]={ - category="nd", - direction="l", - }, - [0xBF0]={ - category="no", - direction="l", - }, - [0xBF1]={ - category="no", - direction="l", - }, - [0xBF2]={ - category="no", - direction="l", - }, - [0xBF3]={ - category="so", - direction="on", - }, - [0xBF4]={ - category="so", - direction="on", - }, - [0xBF5]={ - category="so", - direction="on", - }, - [0xBF6]={ - category="so", - direction="on", - }, - [0xBF7]={ - category="so", - direction="on", - }, - [0xBF8]={ - category="so", - direction="on", - }, - [0xBF9]={ - category="sc", - direction="et", - }, - [0xBFA]={ - category="so", - direction="on", - }, - [0xC00]={ - category="mn", - direction="nsm", - }, - [0xC01]={ - category="mc", - direction="l", - }, - [0xC02]={ - category="mc", - direction="l", - }, - [0xC03]={ - category="mc", - direction="l", - }, - [0xC05]={ - category="lo", - direction="l", - }, - [0xC06]={ - category="lo", - direction="l", - }, - [0xC07]={ - category="lo", - direction="l", - }, - [0xC08]={ - category="lo", - direction="l", - }, - [0xC09]={ - category="lo", - direction="l", - }, - [0xC0A]={ - category="lo", - direction="l", - }, - [0xC0B]={ - category="lo", - direction="l", - }, - [0xC0C]={ - category="lo", - direction="l", - }, - [0xC0E]={ - category="lo", - direction="l", - }, - [0xC0F]={ - category="lo", - direction="l", - }, - [0xC10]={ - category="lo", - direction="l", - }, - [0xC12]={ - category="lo", - direction="l", - }, - [0xC13]={ - category="lo", - direction="l", - }, - [0xC14]={ - category="lo", - direction="l", - }, - [0xC15]={ - category="lo", - direction="l", - }, - [0xC16]={ - category="lo", - direction="l", - }, - [0xC17]={ - category="lo", - direction="l", - }, - [0xC18]={ - category="lo", - direction="l", - }, - [0xC19]={ - category="lo", - direction="l", - }, - [0xC1A]={ - category="lo", - direction="l", - }, - [0xC1B]={ - category="lo", - direction="l", - }, - [0xC1C]={ - category="lo", - direction="l", - }, - [0xC1D]={ - category="lo", - direction="l", - }, - [0xC1E]={ - category="lo", - direction="l", - }, - [0xC1F]={ - category="lo", - direction="l", - }, - [0xC20]={ - category="lo", - direction="l", - }, - [0xC21]={ - category="lo", - direction="l", - }, - [0xC22]={ - category="lo", - direction="l", - }, - [0xC23]={ - category="lo", - direction="l", - }, - [0xC24]={ - category="lo", - direction="l", - }, - [0xC25]={ - category="lo", - direction="l", - }, - [0xC26]={ - category="lo", - direction="l", - }, - [0xC27]={ - category="lo", - direction="l", - }, - [0xC28]={ - category="lo", - direction="l", - }, - [0xC2A]={ - category="lo", - direction="l", - }, - [0xC2B]={ - category="lo", - direction="l", - }, - [0xC2C]={ - category="lo", - direction="l", - }, - [0xC2D]={ - category="lo", - direction="l", - }, - [0xC2E]={ - category="lo", - direction="l", - }, - [0xC2F]={ - category="lo", - direction="l", - }, - [0xC30]={ - category="lo", - direction="l", - }, - [0xC31]={ - category="lo", - direction="l", - }, - [0xC32]={ - category="lo", - direction="l", - }, - [0xC33]={ - category="lo", - direction="l", - }, - [0xC34]={ - category="lo", - direction="l", - }, - [0xC35]={ - category="lo", - direction="l", - }, - [0xC36]={ - category="lo", - direction="l", - }, - [0xC37]={ - category="lo", - direction="l", - }, - [0xC38]={ - category="lo", - direction="l", - }, - [0xC39]={ - category="lo", - direction="l", - }, - [0xC3D]={ - category="lo", - direction="l", - }, - [0xC3E]={ - category="mn", - direction="nsm", - }, - [0xC3F]={ - category="mn", - direction="nsm", - }, - [0xC40]={ - category="mn", - direction="nsm", - }, - [0xC41]={ - category="mc", - direction="l", - }, - [0xC42]={ - category="mc", - direction="l", - }, - [0xC43]={ - category="mc", - direction="l", - }, - [0xC44]={ - category="mc", - direction="l", - }, - [0xC46]={ - category="mn", - direction="nsm", - }, - [0xC47]={ - category="mn", - direction="nsm", - }, - [0xC48]={ - category="mn", - direction="nsm", - }, - [0xC4A]={ - category="mn", - direction="nsm", - }, - [0xC4B]={ - category="mn", - direction="nsm", - }, - [0xC4C]={ - category="mn", - direction="nsm", - }, - [0xC4D]={ - category="mn", - direction="nsm", - }, - [0xC55]={ - category="mn", - direction="nsm", - }, - [0xC56]={ - category="mn", - direction="nsm", - }, - [0xC58]={ - category="lo", - direction="l", - }, - [0xC59]={ - category="lo", - direction="l", - }, - [0xC5A]={ - category="lo", - direction="l", - }, - [0xC60]={ - category="lo", - direction="l", - }, - [0xC61]={ - category="lo", - direction="l", - }, - [0xC62]={ - category="mn", - direction="nsm", - }, - [0xC63]={ - category="mn", - direction="nsm", - }, - [0xC66]={ - category="nd", - direction="l", - }, - [0xC67]={ - category="nd", - direction="l", - }, - [0xC68]={ - category="nd", - direction="l", - }, - [0xC69]={ - category="nd", - direction="l", - }, - [0xC6A]={ - category="nd", - direction="l", - }, - [0xC6B]={ - category="nd", - direction="l", - }, - [0xC6C]={ - category="nd", - direction="l", - }, - [0xC6D]={ - category="nd", - direction="l", - }, - [0xC6E]={ - category="nd", - direction="l", - }, - [0xC6F]={ - category="nd", - direction="l", - }, - [0xC78]={ - category="no", - direction="on", - }, - [0xC79]={ - category="no", - direction="on", - }, - [0xC7A]={ - category="no", - direction="on", - }, - [0xC7B]={ - category="no", - direction="on", - }, - [0xC7C]={ - category="no", - direction="on", - }, - [0xC7D]={ - category="no", - direction="on", - }, - [0xC7E]={ - category="no", - direction="on", - }, - [0xC7F]={ - category="so", - direction="l", - }, - [0xC80]={ - category="lo", - direction="l", - }, - [0xC81]={ - category="mn", - direction="nsm", - }, - [0xC82]={ - category="mc", - direction="l", - }, - [0xC83]={ - category="mc", - direction="l", - }, - [0xC85]={ - category="lo", - direction="l", - }, - [0xC86]={ - category="lo", - direction="l", - }, - [0xC87]={ - category="lo", - direction="l", - }, - [0xC88]={ - category="lo", - direction="l", - }, - [0xC89]={ - category="lo", - direction="l", - }, - [0xC8A]={ - category="lo", - direction="l", - }, - [0xC8B]={ - category="lo", - direction="l", - }, - [0xC8C]={ - category="lo", - direction="l", - }, - [0xC8E]={ - category="lo", - direction="l", - }, - [0xC8F]={ - category="lo", - direction="l", - }, - [0xC90]={ - category="lo", - direction="l", - }, - [0xC92]={ - category="lo", - direction="l", - }, - [0xC93]={ - category="lo", - direction="l", - }, - [0xC94]={ - category="lo", - direction="l", - }, - [0xC95]={ - category="lo", - direction="l", - }, - [0xC96]={ - category="lo", - direction="l", - }, - [0xC97]={ - category="lo", - direction="l", - }, - [0xC98]={ - category="lo", - direction="l", - }, - [0xC99]={ - category="lo", - direction="l", - }, - [0xC9A]={ - category="lo", - direction="l", - }, - [0xC9B]={ - category="lo", - direction="l", - }, - [0xC9C]={ - category="lo", - direction="l", - }, - [0xC9D]={ - category="lo", - direction="l", - }, - [0xC9E]={ - category="lo", - direction="l", - }, - [0xC9F]={ - category="lo", - direction="l", - }, - [0xCA0]={ - category="lo", - direction="l", - }, - [0xCA1]={ - category="lo", - direction="l", - }, - [0xCA2]={ - category="lo", - direction="l", - }, - [0xCA3]={ - category="lo", - direction="l", - }, - [0xCA4]={ - category="lo", - direction="l", - }, - [0xCA5]={ - category="lo", - direction="l", - }, - [0xCA6]={ - category="lo", - direction="l", - }, - [0xCA7]={ - category="lo", - direction="l", - }, - [0xCA8]={ - category="lo", - direction="l", - }, - [0xCAA]={ - category="lo", - direction="l", - }, - [0xCAB]={ - category="lo", - direction="l", - }, - [0xCAC]={ - category="lo", - direction="l", - }, - [0xCAD]={ - category="lo", - direction="l", - }, - [0xCAE]={ - category="lo", - direction="l", - }, - [0xCAF]={ - category="lo", - direction="l", - }, - [0xCB0]={ - category="lo", - direction="l", - }, - [0xCB1]={ - category="lo", - direction="l", - }, - [0xCB2]={ - category="lo", - direction="l", - }, - [0xCB3]={ - category="lo", - direction="l", - }, - [0xCB5]={ - category="lo", - direction="l", - }, - [0xCB6]={ - category="lo", - direction="l", - }, - [0xCB7]={ - category="lo", - direction="l", - }, - [0xCB8]={ - category="lo", - direction="l", - }, - [0xCB9]={ - category="lo", - direction="l", - }, - [0xCBC]={ - category="mn", - direction="nsm", - }, - [0xCBD]={ - category="lo", - direction="l", - }, - [0xCBE]={ - category="mc", - direction="l", - }, - [0xCBF]={ - category="mn", - direction="l", - }, - [0xCC0]={ - category="mc", - direction="l", - }, - [0xCC1]={ - category="mc", - direction="l", - }, - [0xCC2]={ - category="mc", - direction="l", - }, - [0xCC3]={ - category="mc", - direction="l", - }, - [0xCC4]={ - category="mc", - direction="l", - }, - [0xCC6]={ - category="mn", - direction="l", - }, - [0xCC7]={ - category="mc", - direction="l", - }, - [0xCC8]={ - category="mc", - direction="l", - }, - [0xCCA]={ - category="mc", - direction="l", - }, - [0xCCB]={ - category="mc", - direction="l", - }, - [0xCCC]={ - category="mn", - direction="nsm", - }, - [0xCCD]={ - category="mn", - direction="nsm", - }, - [0xCD5]={ - category="mc", - direction="l", - }, - [0xCD6]={ - category="mc", - direction="l", - }, - [0xCDE]={ - category="lo", - direction="l", - }, - [0xCE0]={ - category="lo", - direction="l", - }, - [0xCE1]={ - category="lo", - direction="l", - }, - [0xCE2]={ - category="mn", - direction="nsm", - }, - [0xCE3]={ - category="mn", - direction="nsm", - }, - [0xCE6]={ - category="nd", - direction="l", - }, - [0xCE7]={ - category="nd", - direction="l", - }, - [0xCE8]={ - category="nd", - direction="l", - }, - [0xCE9]={ - category="nd", - direction="l", - }, - [0xCEA]={ - category="nd", - direction="l", - }, - [0xCEB]={ - category="nd", - direction="l", - }, - [0xCEC]={ - category="nd", - direction="l", - }, - [0xCED]={ - category="nd", - direction="l", - }, - [0xCEE]={ - category="nd", - direction="l", - }, - [0xCEF]={ - category="nd", - direction="l", - }, - [0xCF1]={ - category="so", - direction="l", - }, - [0xCF2]={ - category="so", - direction="l", - }, - [0xD01]={ - category="mn", - direction="nsm", - }, - [0xD02]={ - category="mc", - direction="l", - }, - [0xD03]={ - category="mc", - direction="l", - }, - [0xD05]={ - category="lo", - direction="l", - }, - [0xD06]={ - category="lo", - direction="l", - }, - [0xD07]={ - category="lo", - direction="l", - }, - [0xD08]={ - category="lo", - direction="l", - }, - [0xD09]={ - category="lo", - direction="l", - }, - [0xD0A]={ - category="lo", - direction="l", - }, - [0xD0B]={ - category="lo", - direction="l", - }, - [0xD0C]={ - category="lo", - direction="l", - }, - [0xD0E]={ - category="lo", - direction="l", - }, - [0xD0F]={ - category="lo", - direction="l", - }, - [0xD10]={ - category="lo", - direction="l", - }, - [0xD12]={ - category="lo", - direction="l", - }, - [0xD13]={ - category="lo", - direction="l", - }, - [0xD14]={ - category="lo", - direction="l", - }, - [0xD15]={ - category="lo", - direction="l", - }, - [0xD16]={ - category="lo", - direction="l", - }, - [0xD17]={ - category="lo", - direction="l", - }, - [0xD18]={ - category="lo", - direction="l", - }, - [0xD19]={ - category="lo", - direction="l", - }, - [0xD1A]={ - category="lo", - direction="l", - }, - [0xD1B]={ - category="lo", - direction="l", - }, - [0xD1C]={ - category="lo", - direction="l", - }, - [0xD1D]={ - category="lo", - direction="l", - }, - [0xD1E]={ - category="lo", - direction="l", - }, - [0xD1F]={ - category="lo", - direction="l", - }, - [0xD20]={ - category="lo", - direction="l", - }, - [0xD21]={ - category="lo", - direction="l", - }, - [0xD22]={ - category="lo", - direction="l", - }, - [0xD23]={ - category="lo", - direction="l", - }, - [0xD24]={ - category="lo", - direction="l", - }, - [0xD25]={ - category="lo", - direction="l", - }, - [0xD26]={ - category="lo", - direction="l", - }, - [0xD27]={ - category="lo", - direction="l", - }, - [0xD28]={ - category="lo", - direction="l", - }, - [0xD29]={ - category="lo", - direction="l", - }, - [0xD2A]={ - category="lo", - direction="l", - }, - [0xD2B]={ - category="lo", - direction="l", - }, - [0xD2C]={ - category="lo", - direction="l", - }, - [0xD2D]={ - category="lo", - direction="l", - }, - [0xD2E]={ - category="lo", - direction="l", - }, - [0xD2F]={ - category="lo", - direction="l", - }, - [0xD30]={ - category="lo", - direction="l", - }, - [0xD31]={ - category="lo", - direction="l", - }, - [0xD32]={ - category="lo", - direction="l", - }, - [0xD33]={ - category="lo", - direction="l", - }, - [0xD34]={ - category="lo", - direction="l", - }, - [0xD35]={ - category="lo", - direction="l", - }, - [0xD36]={ - category="lo", - direction="l", - }, - [0xD37]={ - category="lo", - direction="l", - }, - [0xD38]={ - category="lo", - direction="l", - }, - [0xD39]={ - category="lo", - direction="l", - }, - [0xD3A]={ - category="lo", - direction="l", - }, - [0xD3D]={ - category="lo", - direction="l", - }, - [0xD3E]={ - category="mc", - direction="l", - }, - [0xD3F]={ - category="mc", - direction="l", - }, - [0xD40]={ - category="mc", - direction="l", - }, - [0xD41]={ - category="mn", - direction="nsm", - }, - [0xD42]={ - category="mn", - direction="nsm", - }, - [0xD43]={ - category="mn", - direction="nsm", - }, - [0xD44]={ - category="mn", - direction="nsm", - }, - [0xD46]={ - category="mc", - direction="l", - }, - [0xD47]={ - category="mc", - direction="l", - }, - [0xD48]={ - category="mc", - direction="l", - }, - [0xD4A]={ - category="mc", - direction="l", - }, - [0xD4B]={ - category="mc", - direction="l", - }, - [0xD4C]={ - category="mc", - direction="l", - }, - [0xD4D]={ - category="mn", - direction="nsm", - }, - [0xD4E]={ - category="lo", - direction="l", - }, - [0xD4F]={ - category="so", - direction="l", - }, - [0xD54]={ - category="lo", - direction="l", - }, - [0xD55]={ - category="lo", - direction="l", - }, - [0xD56]={ - category="lo", - direction="l", - }, - [0xD57]={ - category="mc", - direction="l", - }, - [0xD58]={ - category="no", - direction="l", - }, - [0xD59]={ - category="no", - direction="l", - }, - [0xD5A]={ - category="no", - direction="l", - }, - [0xD5B]={ - category="no", - direction="l", - }, - [0xD5C]={ - category="no", - direction="l", - }, - [0xD5D]={ - category="no", - direction="l", - }, - [0xD5E]={ - category="no", - direction="l", - }, - [0xD5F]={ - category="lo", - direction="l", - }, - [0xD60]={ - category="lo", - direction="l", - }, - [0xD61]={ - category="lo", - direction="l", - }, - [0xD62]={ - category="mn", - direction="nsm", - }, - [0xD63]={ - category="mn", - direction="nsm", - }, - [0xD66]={ - category="nd", - direction="l", - }, - [0xD67]={ - category="nd", - direction="l", - }, - [0xD68]={ - category="nd", - direction="l", - }, - [0xD69]={ - category="nd", - direction="l", - }, - [0xD6A]={ - category="nd", - direction="l", - }, - [0xD6B]={ - category="nd", - direction="l", - }, - [0xD6C]={ - category="nd", - direction="l", - }, - [0xD6D]={ - category="nd", - direction="l", - }, - [0xD6E]={ - category="nd", - direction="l", - }, - [0xD6F]={ - category="nd", - direction="l", - }, - [0xD70]={ - category="no", - direction="l", - }, - [0xD71]={ - category="no", - direction="l", - }, - [0xD72]={ - category="no", - direction="l", - }, - [0xD73]={ - category="no", - direction="l", - }, - [0xD74]={ - category="no", - direction="l", - }, - [0xD75]={ - category="no", - direction="l", - }, - [0xD76]={ - category="no", - direction="l", - }, - [0xD77]={ - category="no", - direction="l", - }, - [0xD78]={ - category="no", - direction="l", - }, - [0xD79]={ - category="so", - direction="l", - }, - [0xD7A]={ - category="lo", - direction="l", - }, - [0xD7B]={ - category="lo", - direction="l", - }, - [0xD7C]={ - category="lo", - direction="l", - }, - [0xD7D]={ - category="lo", - direction="l", - }, - [0xD7E]={ - category="lo", - direction="l", - }, - [0xD7F]={ - category="lo", - direction="l", - }, - [0xD82]={ - category="mc", - direction="l", - }, - [0xD83]={ - category="mc", - direction="l", - }, - [0xD85]={ - category="lo", - direction="l", - }, - [0xD86]={ - category="lo", - direction="l", - }, - [0xD87]={ - category="lo", - direction="l", - }, - [0xD88]={ - category="lo", - direction="l", - }, - [0xD89]={ - category="lo", - direction="l", - }, - [0xD8A]={ - category="lo", - direction="l", - }, - [0xD8B]={ - category="lo", - direction="l", - }, - [0xD8C]={ - category="lo", - direction="l", - }, - [0xD8D]={ - category="lo", - direction="l", - }, - [0xD8E]={ - category="lo", - direction="l", - }, - [0xD8F]={ - category="lo", - direction="l", - }, - [0xD90]={ - category="lo", - direction="l", - }, - [0xD91]={ - category="lo", - direction="l", - }, - [0xD92]={ - category="lo", - direction="l", - }, - [0xD93]={ - category="lo", - direction="l", - }, - [0xD94]={ - category="lo", - direction="l", - }, - [0xD95]={ - category="lo", - direction="l", - }, - [0xD96]={ - category="lo", - direction="l", - }, - [0xD9A]={ - category="lo", - direction="l", - }, - [0xD9B]={ - category="lo", - direction="l", - }, - [0xD9C]={ - category="lo", - direction="l", - }, - [0xD9D]={ - category="lo", - direction="l", - }, - [0xD9E]={ - category="lo", - direction="l", - }, - [0xD9F]={ - category="lo", - direction="l", - }, - [0xDA0]={ - category="lo", - direction="l", - }, - [0xDA1]={ - category="lo", - direction="l", - }, - [0xDA2]={ - category="lo", - direction="l", - }, - [0xDA3]={ - category="lo", - direction="l", - }, - [0xDA4]={ - category="lo", - direction="l", - }, - [0xDA5]={ - category="lo", - direction="l", - }, - [0xDA6]={ - category="lo", - direction="l", - }, - [0xDA7]={ - category="lo", - direction="l", - }, - [0xDA8]={ - category="lo", - direction="l", - }, - [0xDA9]={ - category="lo", - direction="l", - }, - [0xDAA]={ - category="lo", - direction="l", - }, - [0xDAB]={ - category="lo", - direction="l", - }, - [0xDAC]={ - category="lo", - direction="l", - }, - [0xDAD]={ - category="lo", - direction="l", - }, - [0xDAE]={ - category="lo", - direction="l", - }, - [0xDAF]={ - category="lo", - direction="l", - }, - [0xDB0]={ - category="lo", - direction="l", - }, - [0xDB1]={ - category="lo", - direction="l", - }, - [0xDB3]={ - category="lo", - direction="l", - }, - [0xDB4]={ - category="lo", - direction="l", - }, - [0xDB5]={ - category="lo", - direction="l", - }, - [0xDB6]={ - category="lo", - direction="l", - }, - [0xDB7]={ - category="lo", - direction="l", - }, - [0xDB8]={ - category="lo", - direction="l", - }, - [0xDB9]={ - category="lo", - direction="l", - }, - [0xDBA]={ - category="lo", - direction="l", - }, - [0xDBB]={ - category="lo", - direction="l", - }, - [0xDBD]={ - category="lo", - direction="l", - }, - [0xDC0]={ - category="lo", - direction="l", - }, - [0xDC1]={ - category="lo", - direction="l", - }, - [0xDC2]={ - category="lo", - direction="l", - }, - [0xDC3]={ - category="lo", - direction="l", - }, - [0xDC4]={ - category="lo", - direction="l", - }, - [0xDC5]={ - category="lo", - direction="l", - }, - [0xDC6]={ - category="lo", - direction="l", - }, - [0xDCA]={ - category="mn", - direction="nsm", - }, - [0xDCF]={ - category="mc", - direction="l", - }, - [0xDD0]={ - category="mc", - direction="l", - }, - [0xDD1]={ - category="mc", - direction="l", - }, - [0xDD2]={ - category="mn", - direction="nsm", - }, - [0xDD3]={ - category="mn", - direction="nsm", - }, - [0xDD4]={ - category="mn", - direction="nsm", - }, - [0xDD6]={ - category="mn", - direction="nsm", - }, - [0xDD8]={ - category="mc", - direction="l", - }, - [0xDD9]={ - category="mc", - direction="l", - }, - [0xDDA]={ - category="mc", - direction="l", - }, - [0xDDB]={ - category="mc", - direction="l", - }, - [0xDDC]={ - category="mc", - direction="l", - }, - [0xDDD]={ - category="mc", - direction="l", - }, - [0xDDE]={ - category="mc", - direction="l", - }, - [0xDDF]={ - category="mc", - direction="l", - }, - [0xDE6]={ - category="nd", - direction="l", - }, - [0xDE7]={ - category="nd", - direction="l", - }, - [0xDE8]={ - category="nd", - direction="l", - }, - [0xDE9]={ - category="nd", - direction="l", - }, - [0xDEA]={ - category="nd", - direction="l", - }, - [0xDEB]={ - category="nd", - direction="l", - }, - [0xDEC]={ - category="nd", - direction="l", - }, - [0xDED]={ - category="nd", - direction="l", - }, - [0xDEE]={ - category="nd", - direction="l", - }, - [0xDEF]={ - category="nd", - direction="l", - }, - [0xDF2]={ - category="mc", - direction="l", - }, - [0xDF3]={ - category="mc", - direction="l", - }, - [0xDF4]={ - category="po", - direction="l", - }, - [0xE01]={ - category="lo", - direction="l", - }, - [0xE02]={ - category="lo", - direction="l", - }, - [0xE03]={ - category="lo", - direction="l", - }, - [0xE04]={ - category="lo", - direction="l", - }, - [0xE05]={ - category="lo", - direction="l", - }, - [0xE06]={ - category="lo", - direction="l", - }, - [0xE07]={ - category="lo", - direction="l", - }, - [0xE08]={ - category="lo", - direction="l", - }, - [0xE09]={ - category="lo", - direction="l", - }, - [0xE0A]={ - category="lo", - direction="l", - }, - [0xE0B]={ - category="lo", - direction="l", - }, - [0xE0C]={ - category="lo", - direction="l", - }, - [0xE0D]={ - category="lo", - direction="l", - }, - [0xE0E]={ - category="lo", - direction="l", - }, - [0xE0F]={ - category="lo", - direction="l", - }, - [0xE10]={ - category="lo", - direction="l", - }, - [0xE11]={ - category="lo", - direction="l", - }, - [0xE12]={ - category="lo", - direction="l", - }, - [0xE13]={ - category="lo", - direction="l", - }, - [0xE14]={ - category="lo", - direction="l", - }, - [0xE15]={ - category="lo", - direction="l", - }, - [0xE16]={ - category="lo", - direction="l", - }, - [0xE17]={ - category="lo", - direction="l", - }, - [0xE18]={ - category="lo", - direction="l", - }, - [0xE19]={ - category="lo", - direction="l", - }, - [0xE1A]={ - category="lo", - direction="l", - }, - [0xE1B]={ - category="lo", - direction="l", - }, - [0xE1C]={ - category="lo", - direction="l", - }, - [0xE1D]={ - category="lo", - direction="l", - }, - [0xE1E]={ - category="lo", - direction="l", - }, - [0xE1F]={ - category="lo", - direction="l", - }, - [0xE20]={ - category="lo", - direction="l", - }, - [0xE21]={ - category="lo", - direction="l", - }, - [0xE22]={ - category="lo", - direction="l", - }, - [0xE23]={ - category="lo", - direction="l", - }, - [0xE24]={ - category="lo", - direction="l", - }, - [0xE25]={ - category="lo", - direction="l", - }, - [0xE26]={ - category="lo", - direction="l", - }, - [0xE27]={ - category="lo", - direction="l", - }, - [0xE28]={ - category="lo", - direction="l", - }, - [0xE29]={ - category="lo", - direction="l", - }, - [0xE2A]={ - category="lo", - direction="l", - }, - [0xE2B]={ - category="lo", - direction="l", - }, - [0xE2C]={ - category="lo", - direction="l", - }, - [0xE2D]={ - category="lo", - direction="l", - }, - [0xE2E]={ - category="lo", - direction="l", - }, - [0xE2F]={ - category="lo", - direction="l", - }, - [0xE30]={ - category="lo", - direction="l", - }, - [0xE31]={ - category="mn", - direction="nsm", - }, - [0xE32]={ - category="lo", - direction="l", - }, - [0xE33]={ - category="lo", - direction="l", - }, - [0xE34]={ - category="mn", - direction="nsm", - }, - [0xE35]={ - category="mn", - direction="nsm", - }, - [0xE36]={ - category="mn", - direction="nsm", - }, - [0xE37]={ - category="mn", - direction="nsm", - }, - [0xE38]={ - category="mn", - direction="nsm", - }, - [0xE39]={ - category="mn", - direction="nsm", - }, - [0xE3A]={ - category="mn", - direction="nsm", - }, - [0xE3F]={ - category="sc", - direction="et", - }, - [0xE40]={ - category="lo", - direction="l", - }, - [0xE41]={ - category="lo", - direction="l", - }, - [0xE42]={ - category="lo", - direction="l", - }, - [0xE43]={ - category="lo", - direction="l", - }, - [0xE44]={ - category="lo", - direction="l", - }, - [0xE45]={ - category="lo", - direction="l", - }, - [0xE46]={ - category="lm", - direction="l", - }, - [0xE47]={ - category="mn", - direction="nsm", - }, - [0xE48]={ - category="mn", - direction="nsm", - }, - [0xE49]={ - category="mn", - direction="nsm", - }, - [0xE4A]={ - category="mn", - direction="nsm", - }, - [0xE4B]={ - category="mn", - direction="nsm", - }, - [0xE4C]={ - category="mn", - direction="nsm", - }, - [0xE4D]={ - category="mn", - direction="nsm", - }, - [0xE4E]={ - category="mn", - direction="nsm", - }, - [0xE4F]={ - category="po", - direction="l", - }, - [0xE50]={ - category="nd", - direction="l", - }, - [0xE51]={ - category="nd", - direction="l", - }, - [0xE52]={ - category="nd", - direction="l", - }, - [0xE53]={ - category="nd", - direction="l", - }, - [0xE54]={ - category="nd", - direction="l", - }, - [0xE55]={ - category="nd", - direction="l", - }, - [0xE56]={ - category="nd", - direction="l", - }, - [0xE57]={ - category="nd", - direction="l", - }, - [0xE58]={ - category="nd", - direction="l", - }, - [0xE59]={ - category="nd", - direction="l", - }, - [0xE5A]={ - category="po", - direction="l", - }, - [0xE5B]={ - category="po", - direction="l", - }, - [0xE81]={ - category="lo", - direction="l", - }, - [0xE82]={ - category="lo", - direction="l", - }, - [0xE84]={ - category="lo", - direction="l", - }, - [0xE87]={ - category="lo", - direction="l", - }, - [0xE88]={ - category="lo", - direction="l", - }, - [0xE8A]={ - category="lo", - direction="l", - }, - [0xE8D]={ - category="lo", - direction="l", - }, - [0xE94]={ - category="lo", - direction="l", - }, - [0xE95]={ - category="lo", - direction="l", - }, - [0xE96]={ - category="lo", - direction="l", - }, - [0xE97]={ - category="lo", - direction="l", - }, - [0xE99]={ - category="lo", - direction="l", - }, - [0xE9A]={ - category="lo", - direction="l", - }, - [0xE9B]={ - category="lo", - direction="l", - }, - [0xE9C]={ - category="lo", - direction="l", - }, - [0xE9D]={ - category="lo", - direction="l", - }, - [0xE9E]={ - category="lo", - direction="l", - }, - [0xE9F]={ - category="lo", - direction="l", - }, - [0xEA1]={ - category="lo", - direction="l", - }, - [0xEA2]={ - category="lo", - direction="l", - }, - [0xEA3]={ - category="lo", - direction="l", - }, - [0xEA5]={ - category="lo", - direction="l", - }, - [0xEA7]={ - category="lo", - direction="l", - }, - [0xEAA]={ - category="lo", - direction="l", - }, - [0xEAB]={ - category="lo", - direction="l", - }, - [0xEAD]={ - category="lo", - direction="l", - }, - [0xEAE]={ - category="lo", - direction="l", - }, - [0xEAF]={ - category="lo", - direction="l", - }, - [0xEB0]={ - category="lo", - direction="l", - }, - [0xEB1]={ - category="mn", - direction="nsm", - }, - [0xEB2]={ - category="lo", - direction="l", - }, - [0xEB3]={ - category="lo", - direction="l", - }, - [0xEB4]={ - category="mn", - direction="nsm", - }, - [0xEB5]={ - category="mn", - direction="nsm", - }, - [0xEB6]={ - category="mn", - direction="nsm", - }, - [0xEB7]={ - category="mn", - direction="nsm", - }, - [0xEB8]={ - category="mn", - direction="nsm", - }, - [0xEB9]={ - category="mn", - direction="nsm", - }, - [0xEBB]={ - category="mn", - direction="nsm", - }, - [0xEBC]={ - category="mn", - direction="nsm", - }, - [0xEBD]={ - category="lo", - direction="l", - }, - [0xEC0]={ - category="lo", - direction="l", - }, - [0xEC1]={ - category="lo", - direction="l", - }, - [0xEC2]={ - category="lo", - direction="l", - }, - [0xEC3]={ - category="lo", - direction="l", - }, - [0xEC4]={ - category="lo", - direction="l", - }, - [0xEC6]={ - category="lm", - direction="l", - }, - [0xEC8]={ - category="mn", - direction="nsm", - }, - [0xEC9]={ - category="mn", - direction="nsm", - }, - [0xECA]={ - category="mn", - direction="nsm", - }, - [0xECB]={ - category="mn", - direction="nsm", - }, - [0xECC]={ - category="mn", - direction="nsm", - }, - [0xECD]={ - category="mn", - direction="nsm", - }, - [0xED0]={ - category="nd", - direction="l", - }, - [0xED1]={ - category="nd", - direction="l", - }, - [0xED2]={ - category="nd", - direction="l", - }, - [0xED3]={ - category="nd", - direction="l", - }, - [0xED4]={ - category="nd", - direction="l", - }, - [0xED5]={ - category="nd", - direction="l", - }, - [0xED6]={ - category="nd", - direction="l", - }, - [0xED7]={ - category="nd", - direction="l", - }, - [0xED8]={ - category="nd", - direction="l", - }, - [0xED9]={ - category="nd", - direction="l", - }, - [0xEDC]={ - category="lo", - direction="l", - }, - [0xEDD]={ - category="lo", - direction="l", - }, - [0xEDE]={ - category="lo", - direction="l", - }, - [0xEDF]={ - category="lo", - direction="l", - }, - [0xF00]={ - category="lo", - direction="l", - }, - [0xF01]={ - category="so", - direction="l", - }, - [0xF02]={ - category="so", - direction="l", - }, - [0xF03]={ - category="so", - direction="l", - }, - [0xF04]={ - category="po", - direction="l", - }, - [0xF05]={ - category="po", - direction="l", - }, - [0xF06]={ - category="po", - direction="l", - }, - [0xF07]={ - category="po", - direction="l", - }, - [0xF08]={ - category="po", - direction="l", - }, - [0xF09]={ - category="po", - direction="l", - }, - [0xF0A]={ - category="po", - direction="l", - }, - [0xF0B]={ - category="po", - direction="l", - }, - [0xF0C]={ - category="po", - direction="l", - }, - [0xF0D]={ - category="po", - direction="l", - }, - [0xF0E]={ - category="po", - direction="l", - }, - [0xF0F]={ - category="po", - direction="l", - }, - [0xF10]={ - category="po", - direction="l", - }, - [0xF11]={ - category="po", - direction="l", - }, - [0xF12]={ - category="po", - direction="l", - }, - [0xF13]={ - category="so", - direction="l", - }, - [0xF14]={ - category="so", - direction="l", - }, - [0xF15]={ - category="so", - direction="l", - }, - [0xF16]={ - category="so", - direction="l", - }, - [0xF17]={ - category="so", - direction="l", - }, - [0xF18]={ - category="mn", - direction="nsm", - }, - [0xF19]={ - category="mn", - direction="nsm", - }, - [0xF1A]={ - category="so", - direction="l", - }, - [0xF1B]={ - category="so", - direction="l", - }, - [0xF1C]={ - category="so", - direction="l", - }, - [0xF1D]={ - category="so", - direction="l", - }, - [0xF1E]={ - category="so", - direction="l", - }, - [0xF1F]={ - category="so", - direction="l", - }, - [0xF20]={ - category="nd", - direction="l", - }, - [0xF21]={ - category="nd", - direction="l", - }, - [0xF22]={ - category="nd", - direction="l", - }, - [0xF23]={ - category="nd", - direction="l", - }, - [0xF24]={ - category="nd", - direction="l", - }, - [0xF25]={ - category="nd", - direction="l", - }, - [0xF26]={ - category="nd", - direction="l", - }, - [0xF27]={ - category="nd", - direction="l", - }, - [0xF28]={ - category="nd", - direction="l", - }, - [0xF29]={ - category="nd", - direction="l", - }, - [0xF2A]={ - category="no", - direction="l", - }, - [0xF2B]={ - category="no", - direction="l", - }, - [0xF2C]={ - category="no", - direction="l", - }, - [0xF2D]={ - category="no", - direction="l", - }, - [0xF2E]={ - category="no", - direction="l", - }, - [0xF2F]={ - category="no", - direction="l", - }, - [0xF30]={ - category="no", - direction="l", - }, - [0xF31]={ - category="no", - direction="l", - }, - [0xF32]={ - category="no", - direction="l", - }, - [0xF33]={ - category="no", - direction="l", - }, - [0xF34]={ - category="so", - direction="l", - }, - [0xF35]={ - category="mn", - direction="nsm", - }, - [0xF36]={ - category="so", - direction="l", - }, - [0xF37]={ - category="mn", - direction="nsm", - }, - [0xF38]={ - category="so", - direction="l", - }, - [0xF39]={ - category="mn", - direction="nsm", - }, - [0xF3A]={ - category="ps", - direction="on", - mirror=0xF3B, - }, - [0xF3B]={ - category="pe", - direction="on", - mirror=0xF3A, - }, - [0xF3C]={ - category="ps", - direction="on", - mirror=0xF3D, - }, - [0xF3D]={ - category="pe", - direction="on", - mirror=0xF3C, - }, - [0xF3E]={ - category="mc", - direction="l", - }, - [0xF3F]={ - category="mc", - direction="l", - }, - [0xF40]={ - category="lo", - direction="l", - }, - [0xF41]={ - category="lo", - direction="l", - }, - [0xF42]={ - category="lo", - direction="l", - }, - [0xF43]={ - category="lo", - direction="l", - }, - [0xF44]={ - category="lo", - direction="l", - }, - [0xF45]={ - category="lo", - direction="l", - }, - [0xF46]={ - category="lo", - direction="l", - }, - [0xF47]={ - category="lo", - direction="l", - }, - [0xF49]={ - category="lo", - direction="l", - }, - [0xF4A]={ - category="lo", - direction="l", - }, - [0xF4B]={ - category="lo", - direction="l", - }, - [0xF4C]={ - category="lo", - direction="l", - }, - [0xF4D]={ - category="lo", - direction="l", - }, - [0xF4E]={ - category="lo", - direction="l", - }, - [0xF4F]={ - category="lo", - direction="l", - }, - [0xF50]={ - category="lo", - direction="l", - }, - [0xF51]={ - category="lo", - direction="l", - }, - [0xF52]={ - category="lo", - direction="l", - }, - [0xF53]={ - category="lo", - direction="l", - }, - [0xF54]={ - category="lo", - direction="l", - }, - [0xF55]={ - category="lo", - direction="l", - }, - [0xF56]={ - category="lo", - direction="l", - }, - [0xF57]={ - category="lo", - direction="l", - }, - [0xF58]={ - category="lo", - direction="l", - }, - [0xF59]={ - category="lo", - direction="l", - }, - [0xF5A]={ - category="lo", - direction="l", - }, - [0xF5B]={ - category="lo", - direction="l", - }, - [0xF5C]={ - category="lo", - direction="l", - }, - [0xF5D]={ - category="lo", - direction="l", - }, - [0xF5E]={ - category="lo", - direction="l", - }, - [0xF5F]={ - category="lo", - direction="l", - }, - [0xF60]={ - category="lo", - direction="l", - }, - [0xF61]={ - category="lo", - direction="l", - }, - [0xF62]={ - category="lo", - direction="l", - }, - [0xF63]={ - category="lo", - direction="l", - }, - [0xF64]={ - category="lo", - direction="l", - }, - [0xF65]={ - category="lo", - direction="l", - }, - [0xF66]={ - category="lo", - direction="l", - }, - [0xF67]={ - category="lo", - direction="l", - }, - [0xF68]={ - category="lo", - direction="l", - }, - [0xF69]={ - category="lo", - direction="l", - }, - [0xF6A]={ - category="lo", - direction="l", - }, - [0xF6B]={ - category="lo", - direction="l", - }, - [0xF6C]={ - category="lo", - direction="l", - }, - [0xF71]={ - category="mn", - direction="nsm", - }, - [0xF72]={ - category="mn", - direction="nsm", - }, - [0xF73]={ - category="mn", - direction="nsm", - }, - [0xF74]={ - category="mn", - direction="nsm", - }, - [0xF75]={ - category="mn", - direction="nsm", - }, - [0xF76]={ - category="mn", - direction="nsm", - }, - [0xF77]={ - category="mn", - direction="nsm", - }, - [0xF78]={ - category="mn", - direction="nsm", - }, - [0xF79]={ - category="mn", - direction="nsm", - }, - [0xF7A]={ - category="mn", - direction="nsm", - }, - [0xF7B]={ - category="mn", - direction="nsm", - }, - [0xF7C]={ - category="mn", - direction="nsm", - }, - [0xF7D]={ - category="mn", - direction="nsm", - }, - [0xF7E]={ - category="mn", - direction="nsm", - }, - [0xF7F]={ - category="mc", - direction="l", - }, - [0xF80]={ - category="mn", - direction="nsm", - }, - [0xF81]={ - category="mn", - direction="nsm", - }, - [0xF82]={ - category="mn", - direction="nsm", - }, - [0xF83]={ - category="mn", - direction="nsm", - }, - [0xF84]={ - category="mn", - direction="nsm", - }, - [0xF85]={ - category="po", - direction="l", - }, - [0xF86]={ - category="mn", - direction="nsm", - }, - [0xF87]={ - category="mn", - direction="nsm", - }, - [0xF88]={ - category="lo", - direction="l", - }, - [0xF89]={ - category="lo", - direction="l", - }, - [0xF8A]={ - category="lo", - direction="l", - }, - [0xF8B]={ - category="lo", - direction="l", - }, - [0xF8C]={ - category="lo", - direction="l", - }, - [0xF8D]={ - category="mn", - direction="nsm", - }, - [0xF8E]={ - category="mn", - direction="nsm", - }, - [0xF8F]={ - category="mn", - direction="nsm", - }, - [0xF90]={ - category="mn", - direction="nsm", - }, - [0xF91]={ - category="mn", - direction="nsm", - }, - [0xF92]={ - category="mn", - direction="nsm", - }, - [0xF93]={ - category="mn", - direction="nsm", - }, - [0xF94]={ - category="mn", - direction="nsm", - }, - [0xF95]={ - category="mn", - direction="nsm", - }, - [0xF96]={ - category="mn", - direction="nsm", - }, - [0xF97]={ - category="mn", - direction="nsm", - }, - [0xF99]={ - category="mn", - direction="nsm", - }, - [0xF9A]={ - category="mn", - direction="nsm", - }, - [0xF9B]={ - category="mn", - direction="nsm", - }, - [0xF9C]={ - category="mn", - direction="nsm", - }, - [0xF9D]={ - category="mn", - direction="nsm", - }, - [0xF9E]={ - category="mn", - direction="nsm", - }, - [0xF9F]={ - category="mn", - direction="nsm", - }, - [0xFA0]={ - category="mn", - direction="nsm", - }, - [0xFA1]={ - category="mn", - direction="nsm", - }, - [0xFA2]={ - category="mn", - direction="nsm", - }, - [0xFA3]={ - category="mn", - direction="nsm", - }, - [0xFA4]={ - category="mn", - direction="nsm", - }, - [0xFA5]={ - category="mn", - direction="nsm", - }, - [0xFA6]={ - category="mn", - direction="nsm", - }, - [0xFA7]={ - category="mn", - direction="nsm", - }, - [0xFA8]={ - category="mn", - direction="nsm", - }, - [0xFA9]={ - category="mn", - direction="nsm", - }, - [0xFAA]={ - category="mn", - direction="nsm", - }, - [0xFAB]={ - category="mn", - direction="nsm", - }, - [0xFAC]={ - category="mn", - direction="nsm", - }, - [0xFAD]={ - category="mn", - direction="nsm", - }, - [0xFAE]={ - category="mn", - direction="nsm", - }, - [0xFAF]={ - category="mn", - direction="nsm", - }, - [0xFB0]={ - category="mn", - direction="nsm", - }, - [0xFB1]={ - category="mn", - direction="nsm", - }, - [0xFB2]={ - category="mn", - direction="nsm", - }, - [0xFB3]={ - category="mn", - direction="nsm", - }, - [0xFB4]={ - category="mn", - direction="nsm", - }, - [0xFB5]={ - category="mn", - direction="nsm", - }, - [0xFB6]={ - category="mn", - direction="nsm", - }, - [0xFB7]={ - category="mn", - direction="nsm", - }, - [0xFB8]={ - category="mn", - direction="nsm", - }, - [0xFB9]={ - category="mn", - direction="nsm", - }, - [0xFBA]={ - category="mn", - direction="nsm", - }, - [0xFBB]={ - category="mn", - direction="nsm", - }, - [0xFBC]={ - category="mn", - direction="nsm", - }, - [0xFBE]={ - category="so", - direction="l", - }, - [0xFBF]={ - category="so", - direction="l", - }, - [0xFC0]={ - category="so", - direction="l", - }, - [0xFC1]={ - category="so", - direction="l", - }, - [0xFC2]={ - category="so", - direction="l", - }, - [0xFC3]={ - category="so", - direction="l", - }, - [0xFC4]={ - category="so", - direction="l", - }, - [0xFC5]={ - category="so", - direction="l", - }, - [0xFC6]={ - category="mn", - direction="nsm", - }, - [0xFC7]={ - category="so", - direction="l", - }, - [0xFC8]={ - category="so", - direction="l", - }, - [0xFC9]={ - category="so", - direction="l", - }, - [0xFCA]={ - category="so", - direction="l", - }, - [0xFCB]={ - category="so", - direction="l", - }, - [0xFCC]={ - category="so", - direction="l", - }, - [0xFCE]={ - category="so", - direction="l", - }, - [0xFCF]={ - category="so", - direction="l", - }, - [0xFD0]={ - category="po", - direction="l", - }, - [0xFD1]={ - category="po", - direction="l", - }, - [0xFD2]={ - category="po", - direction="l", - }, - [0xFD3]={ - category="po", - direction="l", - }, - [0xFD4]={ - category="po", - direction="l", - }, - [0xFD5]={ - category="so", - direction="l", - }, - [0xFD6]={ - category="so", - direction="l", - }, - [0xFD7]={ - category="so", - direction="l", - }, - [0xFD8]={ - category="so", - direction="l", - }, - [0xFD9]={ - category="po", - direction="l", - }, - [0xFDA]={ - category="po", - direction="l", - }, - [0x1000]={ - category="lo", - direction="l", - }, - [0x1001]={ - category="lo", - direction="l", - }, - [0x1002]={ - category="lo", - direction="l", - }, - [0x1003]={ - category="lo", - direction="l", - }, - [0x1004]={ - category="lo", - direction="l", - }, - [0x1005]={ - category="lo", - direction="l", - }, - [0x1006]={ - category="lo", - direction="l", - }, - [0x1007]={ - category="lo", - direction="l", - }, - [0x1008]={ - category="lo", - direction="l", - }, - [0x1009]={ - category="lo", - direction="l", - }, - [0x100A]={ - category="lo", - direction="l", - }, - [0x100B]={ - category="lo", - direction="l", - }, - [0x100C]={ - category="lo", - direction="l", - }, - [0x100D]={ - category="lo", - direction="l", - }, - [0x100E]={ - category="lo", - direction="l", - }, - [0x100F]={ - category="lo", - direction="l", - }, - [0x1010]={ - category="lo", - direction="l", - }, - [0x1011]={ - category="lo", - direction="l", - }, - [0x1012]={ - category="lo", - direction="l", - }, - [0x1013]={ - category="lo", - direction="l", - }, - [0x1014]={ - category="lo", - direction="l", - }, - [0x1015]={ - category="lo", - direction="l", - }, - [0x1016]={ - category="lo", - direction="l", - }, - [0x1017]={ - category="lo", - direction="l", - }, - [0x1018]={ - category="lo", - direction="l", - }, - [0x1019]={ - category="lo", - direction="l", - }, - [0x101A]={ - category="lo", - direction="l", - }, - [0x101B]={ - category="lo", - direction="l", - }, - [0x101C]={ - category="lo", - direction="l", - }, - [0x101D]={ - category="lo", - direction="l", - }, - [0x101E]={ - category="lo", - direction="l", - }, - [0x101F]={ - category="lo", - direction="l", - }, - [0x1020]={ - category="lo", - direction="l", - }, - [0x1021]={ - category="lo", - direction="l", - }, - [0x1022]={ - category="lo", - direction="l", - }, - [0x1023]={ - category="lo", - direction="l", - }, - [0x1024]={ - category="lo", - direction="l", - }, - [0x1025]={ - category="lo", - direction="l", - }, - [0x1026]={ - category="lo", - direction="l", - }, - [0x1027]={ - category="lo", - direction="l", - }, - [0x1028]={ - category="lo", - direction="l", - }, - [0x1029]={ - category="lo", - direction="l", - }, - [0x102A]={ - category="lo", - direction="l", - }, - [0x102B]={ - category="mc", - direction="l", - }, - [0x102C]={ - category="mc", - direction="l", - }, - [0x102D]={ - category="mn", - direction="nsm", - }, - [0x102E]={ - category="mn", - direction="nsm", - }, - [0x102F]={ - category="mn", - direction="nsm", - }, - [0x1030]={ - category="mn", - direction="nsm", - }, - [0x1031]={ - category="mc", - direction="l", - }, - [0x1032]={ - category="mn", - direction="nsm", - }, - [0x1033]={ - category="mn", - direction="nsm", - }, - [0x1034]={ - category="mn", - direction="nsm", - }, - [0x1035]={ - category="mn", - direction="nsm", - }, - [0x1036]={ - category="mn", - direction="nsm", - }, - [0x1037]={ - category="mn", - direction="nsm", - }, - [0x1038]={ - category="mc", - direction="l", - }, - [0x1039]={ - category="mn", - direction="nsm", - }, - [0x103A]={ - category="mn", - direction="nsm", - }, - [0x103B]={ - category="mc", - direction="l", - }, - [0x103C]={ - category="mc", - direction="l", - }, - [0x103D]={ - category="mn", - direction="nsm", - }, - [0x103E]={ - category="mn", - direction="nsm", - }, - [0x103F]={ - category="lo", - direction="l", - }, - [0x1040]={ - category="nd", - direction="l", - }, - [0x1041]={ - category="nd", - direction="l", - }, - [0x1042]={ - category="nd", - direction="l", - }, - [0x1043]={ - category="nd", - direction="l", - }, - [0x1044]={ - category="nd", - direction="l", - }, - [0x1045]={ - category="nd", - direction="l", - }, - [0x1046]={ - category="nd", - direction="l", - }, - [0x1047]={ - category="nd", - direction="l", - }, - [0x1048]={ - category="nd", - direction="l", - }, - [0x1049]={ - category="nd", - direction="l", - }, - [0x104A]={ - category="po", - direction="l", - }, - [0x104B]={ - category="po", - direction="l", - }, - [0x104C]={ - category="po", - direction="l", - }, - [0x104D]={ - category="po", - direction="l", - }, - [0x104E]={ - category="po", - direction="l", - }, - [0x104F]={ - category="po", - direction="l", - }, - [0x1050]={ - category="lo", - direction="l", - }, - [0x1051]={ - category="lo", - direction="l", - }, - [0x1052]={ - category="lo", - direction="l", - }, - [0x1053]={ - category="lo", - direction="l", - }, - [0x1054]={ - category="lo", - direction="l", - }, - [0x1055]={ - category="lo", - direction="l", - }, - [0x1056]={ - category="mc", - direction="l", - }, - [0x1057]={ - category="mc", - direction="l", - }, - [0x1058]={ - category="mn", - direction="nsm", - }, - [0x1059]={ - category="mn", - direction="nsm", - }, - [0x105A]={ - category="lo", - direction="l", - }, - [0x105B]={ - category="lo", - direction="l", - }, - [0x105C]={ - category="lo", - direction="l", - }, - [0x105D]={ - category="lo", - direction="l", - }, - [0x105E]={ - category="mn", - direction="nsm", - }, - [0x105F]={ - category="mn", - direction="nsm", - }, - [0x1060]={ - category="mn", - direction="nsm", - }, - [0x1061]={ - category="lo", - direction="l", - }, - [0x1062]={ - category="mc", - direction="l", - }, - [0x1063]={ - category="mc", - direction="l", - }, - [0x1064]={ - category="mc", - direction="l", - }, - [0x1065]={ - category="lo", - direction="l", - }, - [0x1066]={ - category="lo", - direction="l", - }, - [0x1067]={ - category="mc", - direction="l", - }, - [0x1068]={ - category="mc", - direction="l", - }, - [0x1069]={ - category="mc", - direction="l", - }, - [0x106A]={ - category="mc", - direction="l", - }, - [0x106B]={ - category="mc", - direction="l", - }, - [0x106C]={ - category="mc", - direction="l", - }, - [0x106D]={ - category="mc", - direction="l", - }, - [0x106E]={ - category="lo", - direction="l", - }, - [0x106F]={ - category="lo", - direction="l", - }, - [0x1070]={ - category="lo", - direction="l", - }, - [0x1071]={ - category="mn", - direction="nsm", - }, - [0x1072]={ - category="mn", - direction="nsm", - }, - [0x1073]={ - category="mn", - direction="nsm", - }, - [0x1074]={ - category="mn", - direction="nsm", - }, - [0x1075]={ - category="lo", - direction="l", - }, - [0x1076]={ - category="lo", - direction="l", - }, - [0x1077]={ - category="lo", - direction="l", - }, - [0x1078]={ - category="lo", - direction="l", - }, - [0x1079]={ - category="lo", - direction="l", - }, - [0x107A]={ - category="lo", - direction="l", - }, - [0x107B]={ - category="lo", - direction="l", - }, - [0x107C]={ - category="lo", - direction="l", - }, - [0x107D]={ - category="lo", - direction="l", - }, - [0x107E]={ - category="lo", - direction="l", - }, - [0x107F]={ - category="lo", - direction="l", - }, - [0x1080]={ - category="lo", - direction="l", - }, - [0x1081]={ - category="lo", - direction="l", - }, - [0x1082]={ - category="mn", - direction="nsm", - }, - [0x1083]={ - category="mc", - direction="l", - }, - [0x1084]={ - category="mc", - direction="l", - }, - [0x1085]={ - category="mn", - direction="nsm", - }, - [0x1086]={ - category="mn", - direction="nsm", - }, - [0x1087]={ - category="mc", - direction="l", - }, - [0x1088]={ - category="mc", - direction="l", - }, - [0x1089]={ - category="mc", - direction="l", - }, - [0x108A]={ - category="mc", - direction="l", - }, - [0x108B]={ - category="mc", - direction="l", - }, - [0x108C]={ - category="mc", - direction="l", - }, - [0x108D]={ - category="mn", - direction="nsm", - }, - [0x108E]={ - category="lo", - direction="l", - }, - [0x108F]={ - category="mc", - direction="l", - }, - [0x1090]={ - category="nd", - direction="l", - }, - [0x1091]={ - category="nd", - direction="l", - }, - [0x1092]={ - category="nd", - direction="l", - }, - [0x1093]={ - category="nd", - direction="l", - }, - [0x1094]={ - category="nd", - direction="l", - }, - [0x1095]={ - category="nd", - direction="l", - }, - [0x1096]={ - category="nd", - direction="l", - }, - [0x1097]={ - category="nd", - direction="l", - }, - [0x1098]={ - category="nd", - direction="l", - }, - [0x1099]={ - category="nd", - direction="l", - }, - [0x109A]={ - category="mc", - direction="l", - }, - [0x109B]={ - category="mc", - direction="l", - }, - [0x109C]={ - category="mc", - direction="l", - }, - [0x109D]={ - category="mn", - direction="nsm", - }, - [0x109E]={ - category="so", - direction="l", - }, - [0x109F]={ - category="so", - direction="l", - }, - [0x10A0]={ - category="lu", - direction="l", - }, - [0x10A1]={ - category="lu", - direction="l", - }, - [0x10A2]={ - category="lu", - direction="l", - }, - [0x10A3]={ - category="lu", - direction="l", - }, - [0x10A4]={ - category="lu", - direction="l", - }, - [0x10A5]={ - category="lu", - direction="l", - }, - [0x10A6]={ - category="lu", - direction="l", - }, - [0x10A7]={ - category="lu", - direction="l", - }, - [0x10A8]={ - category="lu", - direction="l", - }, - [0x10A9]={ - category="lu", - direction="l", - }, - [0x10AA]={ - category="lu", - direction="l", - }, - [0x10AB]={ - category="lu", - direction="l", - }, - [0x10AC]={ - category="lu", - direction="l", - }, - [0x10AD]={ - category="lu", - direction="l", - }, - [0x10AE]={ - category="lu", - direction="l", - }, - [0x10AF]={ - category="lu", - direction="l", - }, - [0x10B0]={ - category="lu", - direction="l", - }, - [0x10B1]={ - category="lu", - direction="l", - }, - [0x10B2]={ - category="lu", - direction="l", - }, - [0x10B3]={ - category="lu", - direction="l", - }, - [0x10B4]={ - category="lu", - direction="l", - }, - [0x10B5]={ - category="lu", - direction="l", - }, - [0x10B6]={ - category="lu", - direction="l", - }, - [0x10B7]={ - category="lu", - direction="l", - }, - [0x10B8]={ - category="lu", - direction="l", - }, - [0x10B9]={ - category="lu", - direction="l", - }, - [0x10BA]={ - category="lu", - direction="l", - }, - [0x10BB]={ - category="lu", - direction="l", - }, - [0x10BC]={ - category="lu", - direction="l", - }, - [0x10BD]={ - category="lu", - direction="l", - }, - [0x10BE]={ - category="lu", - direction="l", - }, - [0x10BF]={ - category="lu", - direction="l", - }, - [0x10C0]={ - category="lu", - direction="l", - }, - [0x10C1]={ - category="lu", - direction="l", - }, - [0x10C2]={ - category="lu", - direction="l", - }, - [0x10C3]={ - category="lu", - direction="l", - }, - [0x10C4]={ - category="lu", - direction="l", - }, - [0x10C5]={ - category="lu", - direction="l", - }, - [0x10C7]={ - category="lu", - direction="l", - }, - [0x10CD]={ - category="lu", - direction="l", - }, - [0x10D0]={ - category="lo", - direction="l", - }, - [0x10D1]={ - category="lo", - direction="l", - }, - [0x10D2]={ - category="lo", - direction="l", - }, - [0x10D3]={ - category="lo", - direction="l", - }, - [0x10D4]={ - category="lo", - direction="l", - }, - [0x10D5]={ - category="lo", - direction="l", - }, - [0x10D6]={ - category="lo", - direction="l", - }, - [0x10D7]={ - category="lo", - direction="l", - }, - [0x10D8]={ - category="lo", - direction="l", - }, - [0x10D9]={ - category="lo", - direction="l", - }, - [0x10DA]={ - category="lo", - direction="l", - }, - [0x10DB]={ - category="lo", - direction="l", - }, - [0x10DC]={ - category="lo", - direction="l", - }, - [0x10DD]={ - category="lo", - direction="l", - }, - [0x10DE]={ - category="lo", - direction="l", - }, - [0x10DF]={ - category="lo", - direction="l", - }, - [0x10E0]={ - category="lo", - direction="l", - }, - [0x10E1]={ - category="lo", - direction="l", - }, - [0x10E2]={ - category="lo", - direction="l", - }, - [0x10E3]={ - category="lo", - direction="l", - }, - [0x10E4]={ - category="lo", - direction="l", - }, - [0x10E5]={ - category="lo", - direction="l", - }, - [0x10E6]={ - category="lo", - direction="l", - }, - [0x10E7]={ - category="lo", - direction="l", - }, - [0x10E8]={ - category="lo", - direction="l", - }, - [0x10E9]={ - category="lo", - direction="l", - }, - [0x10EA]={ - category="lo", - direction="l", - }, - [0x10EB]={ - category="lo", - direction="l", - }, - [0x10EC]={ - category="lo", - direction="l", - }, - [0x10ED]={ - category="lo", - direction="l", - }, - [0x10EE]={ - category="lo", - direction="l", - }, - [0x10EF]={ - category="lo", - direction="l", - }, - [0x10F0]={ - category="lo", - direction="l", - }, - [0x10F1]={ - category="lo", - direction="l", - }, - [0x10F2]={ - category="lo", - direction="l", - }, - [0x10F3]={ - category="lo", - direction="l", - }, - [0x10F4]={ - category="lo", - direction="l", - }, - [0x10F5]={ - category="lo", - direction="l", - }, - [0x10F6]={ - category="lo", - direction="l", - }, - [0x10F7]={ - category="lo", - direction="l", - }, - [0x10F8]={ - category="lo", - direction="l", - }, - [0x10F9]={ - category="lo", - direction="l", - }, - [0x10FA]={ - category="lo", - direction="l", - }, - [0x10FB]={ - category="po", - direction="l", - }, - [0x10FC]={ - category="lm", - direction="l", - }, - [0x10FD]={ - category="lo", - direction="l", - }, - [0x10FE]={ - category="lo", - direction="l", - }, - [0x10FF]={ - category="lo", - direction="l", - }, - [0x1100]={ - category="lo", - direction="l", - }, - [0x1101]={ - category="lo", - direction="l", - }, - [0x1102]={ - category="lo", - direction="l", - }, - [0x1103]={ - category="lo", - direction="l", - }, - [0x1104]={ - category="lo", - direction="l", - }, - [0x1105]={ - category="lo", - direction="l", - }, - [0x1106]={ - category="lo", - direction="l", - }, - [0x1107]={ - category="lo", - direction="l", - }, - [0x1108]={ - category="lo", - direction="l", - }, - [0x1109]={ - category="lo", - direction="l", - }, - [0x110A]={ - category="lo", - direction="l", - }, - [0x110B]={ - category="lo", - direction="l", - }, - [0x110C]={ - category="lo", - direction="l", - }, - [0x110D]={ - category="lo", - direction="l", - }, - [0x110E]={ - category="lo", - direction="l", - }, - [0x110F]={ - category="lo", - direction="l", - }, - [0x1110]={ - category="lo", - direction="l", - }, - [0x1111]={ - category="lo", - direction="l", - }, - [0x1112]={ - category="lo", - direction="l", - }, - [0x1113]={ - category="lo", - direction="l", - }, - [0x1114]={ - category="lo", - direction="l", - }, - [0x1115]={ - category="lo", - direction="l", - }, - [0x1116]={ - category="lo", - direction="l", - }, - [0x1117]={ - category="lo", - direction="l", - }, - [0x1118]={ - category="lo", - direction="l", - }, - [0x1119]={ - category="lo", - direction="l", - }, - [0x111A]={ - category="lo", - direction="l", - }, - [0x111B]={ - category="lo", - direction="l", - }, - [0x111C]={ - category="lo", - direction="l", - }, - [0x111D]={ - category="lo", - direction="l", - }, - [0x111E]={ - category="lo", - direction="l", - }, - [0x111F]={ - category="lo", - direction="l", - }, - [0x1120]={ - category="lo", - direction="l", - }, - [0x1121]={ - category="lo", - direction="l", - }, - [0x1122]={ - category="lo", - direction="l", - }, - [0x1123]={ - category="lo", - direction="l", - }, - [0x1124]={ - category="lo", - direction="l", - }, - [0x1125]={ - category="lo", - direction="l", - }, - [0x1126]={ - category="lo", - direction="l", - }, - [0x1127]={ - category="lo", - direction="l", - }, - [0x1128]={ - category="lo", - direction="l", - }, - [0x1129]={ - category="lo", - direction="l", - }, - [0x112A]={ - category="lo", - direction="l", - }, - [0x112B]={ - category="lo", - direction="l", - }, - [0x112C]={ - category="lo", - direction="l", - }, - [0x112D]={ - category="lo", - direction="l", - }, - [0x112E]={ - category="lo", - direction="l", - }, - [0x112F]={ - category="lo", - direction="l", - }, - [0x1130]={ - category="lo", - direction="l", - }, - [0x1131]={ - category="lo", - direction="l", - }, - [0x1132]={ - category="lo", - direction="l", - }, - [0x1133]={ - category="lo", - direction="l", - }, - [0x1134]={ - category="lo", - direction="l", - }, - [0x1135]={ - category="lo", - direction="l", - }, - [0x1136]={ - category="lo", - direction="l", - }, - [0x1137]={ - category="lo", - direction="l", - }, - [0x1138]={ - category="lo", - direction="l", - }, - [0x1139]={ - category="lo", - direction="l", - }, - [0x113A]={ - category="lo", - direction="l", - }, - [0x113B]={ - category="lo", - direction="l", - }, - [0x113C]={ - category="lo", - direction="l", - }, - [0x113D]={ - category="lo", - direction="l", - }, - [0x113E]={ - category="lo", - direction="l", - }, - [0x113F]={ - category="lo", - direction="l", - }, - [0x1140]={ - category="lo", - direction="l", - }, - [0x1141]={ - category="lo", - direction="l", - }, - [0x1142]={ - category="lo", - direction="l", - }, - [0x1143]={ - category="lo", - direction="l", - }, - [0x1144]={ - category="lo", - direction="l", - }, - [0x1145]={ - category="lo", - direction="l", - }, - [0x1146]={ - category="lo", - direction="l", - }, - [0x1147]={ - category="lo", - direction="l", - }, - [0x1148]={ - category="lo", - direction="l", - }, - [0x1149]={ - category="lo", - direction="l", - }, - [0x114A]={ - category="lo", - direction="l", - }, - [0x114B]={ - category="lo", - direction="l", - }, - [0x114C]={ - category="lo", - direction="l", - }, - [0x114D]={ - category="lo", - direction="l", - }, - [0x114E]={ - category="lo", - direction="l", - }, - [0x114F]={ - category="lo", - direction="l", - }, - [0x1150]={ - category="lo", - direction="l", - }, - [0x1151]={ - category="lo", - direction="l", - }, - [0x1152]={ - category="lo", - direction="l", - }, - [0x1153]={ - category="lo", - direction="l", - }, - [0x1154]={ - category="lo", - direction="l", - }, - [0x1155]={ - category="lo", - direction="l", - }, - [0x1156]={ - category="lo", - direction="l", - }, - [0x1157]={ - category="lo", - direction="l", - }, - [0x1158]={ - category="lo", - direction="l", - }, - [0x1159]={ - category="lo", - direction="l", - }, - [0x115A]={ - category="lo", - direction="l", - }, - [0x115B]={ - category="lo", - direction="l", - }, - [0x115C]={ - category="lo", - direction="l", - }, - [0x115D]={ - category="lo", - direction="l", - }, - [0x115E]={ - category="lo", - direction="l", - }, - [0x115F]={ - category="lo", - direction="l", - }, - [0x1160]={ - category="lo", - direction="l", - }, - [0x1161]={ - category="lo", - direction="l", - }, - [0x1162]={ - category="lo", - direction="l", - }, - [0x1163]={ - category="lo", - direction="l", - }, - [0x1164]={ - category="lo", - direction="l", - }, - [0x1165]={ - category="lo", - direction="l", - }, - [0x1166]={ - category="lo", - direction="l", - }, - [0x1167]={ - category="lo", - direction="l", - }, - [0x1168]={ - category="lo", - direction="l", - }, - [0x1169]={ - category="lo", - direction="l", - }, - [0x116A]={ - category="lo", - direction="l", - }, - [0x116B]={ - category="lo", - direction="l", - }, - [0x116C]={ - category="lo", - direction="l", - }, - [0x116D]={ - category="lo", - direction="l", - }, - [0x116E]={ - category="lo", - direction="l", - }, - [0x116F]={ - category="lo", - direction="l", - }, - [0x1170]={ - category="lo", - direction="l", - }, - [0x1171]={ - category="lo", - direction="l", - }, - [0x1172]={ - category="lo", - direction="l", - }, - [0x1173]={ - category="lo", - direction="l", - }, - [0x1174]={ - category="lo", - direction="l", - }, - [0x1175]={ - category="lo", - direction="l", - }, - [0x1176]={ - category="lo", - direction="l", - }, - [0x1177]={ - category="lo", - direction="l", - }, - [0x1178]={ - category="lo", - direction="l", - }, - [0x1179]={ - category="lo", - direction="l", - }, - [0x117A]={ - category="lo", - direction="l", - }, - [0x117B]={ - category="lo", - direction="l", - }, - [0x117C]={ - category="lo", - direction="l", - }, - [0x117D]={ - category="lo", - direction="l", - }, - [0x117E]={ - category="lo", - direction="l", - }, - [0x117F]={ - category="lo", - direction="l", - }, - [0x1180]={ - category="lo", - direction="l", - }, - [0x1181]={ - category="lo", - direction="l", - }, - [0x1182]={ - category="lo", - direction="l", - }, - [0x1183]={ - category="lo", - direction="l", - }, - [0x1184]={ - category="lo", - direction="l", - }, - [0x1185]={ - category="lo", - direction="l", - }, - [0x1186]={ - category="lo", - direction="l", - }, - [0x1187]={ - category="lo", - direction="l", - }, - [0x1188]={ - category="lo", - direction="l", - }, - [0x1189]={ - category="lo", - direction="l", - }, - [0x118A]={ - category="lo", - direction="l", - }, - [0x118B]={ - category="lo", - direction="l", - }, - [0x118C]={ - category="lo", - direction="l", - }, - [0x118D]={ - category="lo", - direction="l", - }, - [0x118E]={ - category="lo", - direction="l", - }, - [0x118F]={ - category="lo", - direction="l", - }, - [0x1190]={ - category="lo", - direction="l", - }, - [0x1191]={ - category="lo", - direction="l", - }, - [0x1192]={ - category="lo", - direction="l", - }, - [0x1193]={ - category="lo", - direction="l", - }, - [0x1194]={ - category="lo", - direction="l", - }, - [0x1195]={ - category="lo", - direction="l", - }, - [0x1196]={ - category="lo", - direction="l", - }, - [0x1197]={ - category="lo", - direction="l", - }, - [0x1198]={ - category="lo", - direction="l", - }, - [0x1199]={ - category="lo", - direction="l", - }, - [0x119A]={ - category="lo", - direction="l", - }, - [0x119B]={ - category="lo", - direction="l", - }, - [0x119C]={ - category="lo", - direction="l", - }, - [0x119D]={ - category="lo", - direction="l", - }, - [0x119E]={ - category="lo", - direction="l", - }, - [0x119F]={ - category="lo", - direction="l", - }, - [0x11A0]={ - category="lo", - direction="l", - }, - [0x11A1]={ - category="lo", - direction="l", - }, - [0x11A2]={ - category="lo", - direction="l", - }, - [0x11A3]={ - category="lo", - direction="l", - }, - [0x11A4]={ - category="lo", - direction="l", - }, - [0x11A5]={ - category="lo", - direction="l", - }, - [0x11A6]={ - category="lo", - direction="l", - }, - [0x11A7]={ - category="lo", - direction="l", - }, - [0x11A8]={ - category="lo", - direction="l", - }, - [0x11A9]={ - category="lo", - direction="l", - }, - [0x11AA]={ - category="lo", - direction="l", - }, - [0x11AB]={ - category="lo", - direction="l", - }, - [0x11AC]={ - category="lo", - direction="l", - }, - [0x11AD]={ - category="lo", - direction="l", - }, - [0x11AE]={ - category="lo", - direction="l", - }, - [0x11AF]={ - category="lo", - direction="l", - }, - [0x11B0]={ - category="lo", - direction="l", - }, - [0x11B1]={ - category="lo", - direction="l", - }, - [0x11B2]={ - category="lo", - direction="l", - }, - [0x11B3]={ - category="lo", - direction="l", - }, - [0x11B4]={ - category="lo", - direction="l", - }, - [0x11B5]={ - category="lo", - direction="l", - }, - [0x11B6]={ - category="lo", - direction="l", - }, - [0x11B7]={ - category="lo", - direction="l", - }, - [0x11B8]={ - category="lo", - direction="l", - }, - [0x11B9]={ - category="lo", - direction="l", - }, - [0x11BA]={ - category="lo", - direction="l", - }, - [0x11BB]={ - category="lo", - direction="l", - }, - [0x11BC]={ - category="lo", - direction="l", - }, - [0x11BD]={ - category="lo", - direction="l", - }, - [0x11BE]={ - category="lo", - direction="l", - }, - [0x11BF]={ - category="lo", - direction="l", - }, - [0x11C0]={ - category="lo", - direction="l", - }, - [0x11C1]={ - category="lo", - direction="l", - }, - [0x11C2]={ - category="lo", - direction="l", - }, - [0x11C3]={ - category="lo", - direction="l", - }, - [0x11C4]={ - category="lo", - direction="l", - }, - [0x11C5]={ - category="lo", - direction="l", - }, - [0x11C6]={ - category="lo", - direction="l", - }, - [0x11C7]={ - category="lo", - direction="l", - }, - [0x11C8]={ - category="lo", - direction="l", - }, - [0x11C9]={ - category="lo", - direction="l", - }, - [0x11CA]={ - category="lo", - direction="l", - }, - [0x11CB]={ - category="lo", - direction="l", - }, - [0x11CC]={ - category="lo", - direction="l", - }, - [0x11CD]={ - category="lo", - direction="l", - }, - [0x11CE]={ - category="lo", - direction="l", - }, - [0x11CF]={ - category="lo", - direction="l", - }, - [0x11D0]={ - category="lo", - direction="l", - }, - [0x11D1]={ - category="lo", - direction="l", - }, - [0x11D2]={ - category="lo", - direction="l", - }, - [0x11D3]={ - category="lo", - direction="l", - }, - [0x11D4]={ - category="lo", - direction="l", - }, - [0x11D5]={ - category="lo", - direction="l", - }, - [0x11D6]={ - category="lo", - direction="l", - }, - [0x11D7]={ - category="lo", - direction="l", - }, - [0x11D8]={ - category="lo", - direction="l", - }, - [0x11D9]={ - category="lo", - direction="l", - }, - [0x11DA]={ - category="lo", - direction="l", - }, - [0x11DB]={ - category="lo", - direction="l", - }, - [0x11DC]={ - category="lo", - direction="l", - }, - [0x11DD]={ - category="lo", - direction="l", - }, - [0x11DE]={ - category="lo", - direction="l", - }, - [0x11DF]={ - category="lo", - direction="l", - }, - [0x11E0]={ - category="lo", - direction="l", - }, - [0x11E1]={ - category="lo", - direction="l", - }, - [0x11E2]={ - category="lo", - direction="l", - }, - [0x11E3]={ - category="lo", - direction="l", - }, - [0x11E4]={ - category="lo", - direction="l", - }, - [0x11E5]={ - category="lo", - direction="l", - }, - [0x11E6]={ - category="lo", - direction="l", - }, - [0x11E7]={ - category="lo", - direction="l", - }, - [0x11E8]={ - category="lo", - direction="l", - }, - [0x11E9]={ - category="lo", - direction="l", - }, - [0x11EA]={ - category="lo", - direction="l", - }, - [0x11EB]={ - category="lo", - direction="l", - }, - [0x11EC]={ - category="lo", - direction="l", - }, - [0x11ED]={ - category="lo", - direction="l", - }, - [0x11EE]={ - category="lo", - direction="l", - }, - [0x11EF]={ - category="lo", - direction="l", - }, - [0x11F0]={ - category="lo", - direction="l", - }, - [0x11F1]={ - category="lo", - direction="l", - }, - [0x11F2]={ - category="lo", - direction="l", - }, - [0x11F3]={ - category="lo", - direction="l", - }, - [0x11F4]={ - category="lo", - direction="l", - }, - [0x11F5]={ - category="lo", - direction="l", - }, - [0x11F6]={ - category="lo", - direction="l", - }, - [0x11F7]={ - category="lo", - direction="l", - }, - [0x11F8]={ - category="lo", - direction="l", - }, - [0x11F9]={ - category="lo", - direction="l", - }, - [0x11FA]={ - category="lo", - direction="l", - }, - [0x11FB]={ - category="lo", - direction="l", - }, - [0x11FC]={ - category="lo", - direction="l", - }, - [0x11FD]={ - category="lo", - direction="l", - }, - [0x11FE]={ - category="lo", - direction="l", - }, - [0x11FF]={ - category="lo", - direction="l", - }, - [0x1200]={ - category="lo", - direction="l", - }, - [0x1201]={ - category="lo", - direction="l", - }, - [0x1202]={ - category="lo", - direction="l", - }, - [0x1203]={ - category="lo", - direction="l", - }, - [0x1204]={ - category="lo", - direction="l", - }, - [0x1205]={ - category="lo", - direction="l", - }, - [0x1206]={ - category="lo", - direction="l", - }, - [0x1207]={ - category="lo", - direction="l", - }, - [0x1208]={ - category="lo", - direction="l", - }, - [0x1209]={ - category="lo", - direction="l", - }, - [0x120A]={ - category="lo", - direction="l", - }, - [0x120B]={ - category="lo", - direction="l", - }, - [0x120C]={ - category="lo", - direction="l", - }, - [0x120D]={ - category="lo", - direction="l", - }, - [0x120E]={ - category="lo", - direction="l", - }, - [0x120F]={ - category="lo", - direction="l", - }, - [0x1210]={ - category="lo", - direction="l", - }, - [0x1211]={ - category="lo", - direction="l", - }, - [0x1212]={ - category="lo", - direction="l", - }, - [0x1213]={ - category="lo", - direction="l", - }, - [0x1214]={ - category="lo", - direction="l", - }, - [0x1215]={ - category="lo", - direction="l", - }, - [0x1216]={ - category="lo", - direction="l", - }, - [0x1217]={ - category="lo", - direction="l", - }, - [0x1218]={ - category="lo", - direction="l", - }, - [0x1219]={ - category="lo", - direction="l", - }, - [0x121A]={ - category="lo", - direction="l", - }, - [0x121B]={ - category="lo", - direction="l", - }, - [0x121C]={ - category="lo", - direction="l", - }, - [0x121D]={ - category="lo", - direction="l", - }, - [0x121E]={ - category="lo", - direction="l", - }, - [0x121F]={ - category="lo", - direction="l", - }, - [0x1220]={ - category="lo", - direction="l", - }, - [0x1221]={ - category="lo", - direction="l", - }, - [0x1222]={ - category="lo", - direction="l", - }, - [0x1223]={ - category="lo", - direction="l", - }, - [0x1224]={ - category="lo", - direction="l", - }, - [0x1225]={ - category="lo", - direction="l", - }, - [0x1226]={ - category="lo", - direction="l", - }, - [0x1227]={ - category="lo", - direction="l", - }, - [0x1228]={ - category="lo", - direction="l", - }, - [0x1229]={ - category="lo", - direction="l", - }, - [0x122A]={ - category="lo", - direction="l", - }, - [0x122B]={ - category="lo", - direction="l", - }, - [0x122C]={ - category="lo", - direction="l", - }, - [0x122D]={ - category="lo", - direction="l", - }, - [0x122E]={ - category="lo", - direction="l", - }, - [0x122F]={ - category="lo", - direction="l", - }, - [0x1230]={ - category="lo", - direction="l", - }, - [0x1231]={ - category="lo", - direction="l", - }, - [0x1232]={ - category="lo", - direction="l", - }, - [0x1233]={ - category="lo", - direction="l", - }, - [0x1234]={ - category="lo", - direction="l", - }, - [0x1235]={ - category="lo", - direction="l", - }, - [0x1236]={ - category="lo", - direction="l", - }, - [0x1237]={ - category="lo", - direction="l", - }, - [0x1238]={ - category="lo", - direction="l", - }, - [0x1239]={ - category="lo", - direction="l", - }, - [0x123A]={ - category="lo", - direction="l", - }, - [0x123B]={ - category="lo", - direction="l", - }, - [0x123C]={ - category="lo", - direction="l", - }, - [0x123D]={ - category="lo", - direction="l", - }, - [0x123E]={ - category="lo", - direction="l", - }, - [0x123F]={ - category="lo", - direction="l", - }, - [0x1240]={ - category="lo", - direction="l", - }, - [0x1241]={ - category="lo", - direction="l", - }, - [0x1242]={ - category="lo", - direction="l", - }, - [0x1243]={ - category="lo", - direction="l", - }, - [0x1244]={ - category="lo", - direction="l", - }, - [0x1245]={ - category="lo", - direction="l", - }, - [0x1246]={ - category="lo", - direction="l", - }, - [0x1247]={ - category="lo", - direction="l", - }, - [0x1248]={ - category="lo", - direction="l", - }, - [0x124A]={ - category="lo", - direction="l", - }, - [0x124B]={ - category="lo", - direction="l", - }, - [0x124C]={ - category="lo", - direction="l", - }, - [0x124D]={ - category="lo", - direction="l", - }, - [0x1250]={ - category="lo", - direction="l", - }, - [0x1251]={ - category="lo", - direction="l", - }, - [0x1252]={ - category="lo", - direction="l", - }, - [0x1253]={ - category="lo", - direction="l", - }, - [0x1254]={ - category="lo", - direction="l", - }, - [0x1255]={ - category="lo", - direction="l", - }, - [0x1256]={ - category="lo", - direction="l", - }, - [0x1258]={ - category="lo", - direction="l", - }, - [0x125A]={ - category="lo", - direction="l", - }, - [0x125B]={ - category="lo", - direction="l", - }, - [0x125C]={ - category="lo", - direction="l", - }, - [0x125D]={ - category="lo", - direction="l", - }, - [0x1260]={ - category="lo", - direction="l", - }, - [0x1261]={ - category="lo", - direction="l", - }, - [0x1262]={ - category="lo", - direction="l", - }, - [0x1263]={ - category="lo", - direction="l", - }, - [0x1264]={ - category="lo", - direction="l", - }, - [0x1265]={ - category="lo", - direction="l", - }, - [0x1266]={ - category="lo", - direction="l", - }, - [0x1267]={ - category="lo", - direction="l", - }, - [0x1268]={ - category="lo", - direction="l", - }, - [0x1269]={ - category="lo", - direction="l", - }, - [0x126A]={ - category="lo", - direction="l", - }, - [0x126B]={ - category="lo", - direction="l", - }, - [0x126C]={ - category="lo", - direction="l", - }, - [0x126D]={ - category="lo", - direction="l", - }, - [0x126E]={ - category="lo", - direction="l", - }, - [0x126F]={ - category="lo", - direction="l", - }, - [0x1270]={ - category="lo", - direction="l", - }, - [0x1271]={ - category="lo", - direction="l", - }, - [0x1272]={ - category="lo", - direction="l", - }, - [0x1273]={ - category="lo", - direction="l", - }, - [0x1274]={ - category="lo", - direction="l", - }, - [0x1275]={ - category="lo", - direction="l", - }, - [0x1276]={ - category="lo", - direction="l", - }, - [0x1277]={ - category="lo", - direction="l", - }, - [0x1278]={ - category="lo", - direction="l", - }, - [0x1279]={ - category="lo", - direction="l", - }, - [0x127A]={ - category="lo", - direction="l", - }, - [0x127B]={ - category="lo", - direction="l", - }, - [0x127C]={ - category="lo", - direction="l", - }, - [0x127D]={ - category="lo", - direction="l", - }, - [0x127E]={ - category="lo", - direction="l", - }, - [0x127F]={ - category="lo", - direction="l", - }, - [0x1280]={ - category="lo", - direction="l", - }, - [0x1281]={ - category="lo", - direction="l", - }, - [0x1282]={ - category="lo", - direction="l", - }, - [0x1283]={ - category="lo", - direction="l", - }, - [0x1284]={ - category="lo", - direction="l", - }, - [0x1285]={ - category="lo", - direction="l", - }, - [0x1286]={ - category="lo", - direction="l", - }, - [0x1287]={ - category="lo", - direction="l", - }, - [0x1288]={ - category="lo", - direction="l", - }, - [0x128A]={ - category="lo", - direction="l", - }, - [0x128B]={ - category="lo", - direction="l", - }, - [0x128C]={ - category="lo", - direction="l", - }, - [0x128D]={ - category="lo", - direction="l", - }, - [0x1290]={ - category="lo", - direction="l", - }, - [0x1291]={ - category="lo", - direction="l", - }, - [0x1292]={ - category="lo", - direction="l", - }, - [0x1293]={ - category="lo", - direction="l", - }, - [0x1294]={ - category="lo", - direction="l", - }, - [0x1295]={ - category="lo", - direction="l", - }, - [0x1296]={ - category="lo", - direction="l", - }, - [0x1297]={ - category="lo", - direction="l", - }, - [0x1298]={ - category="lo", - direction="l", - }, - [0x1299]={ - category="lo", - direction="l", - }, - [0x129A]={ - category="lo", - direction="l", - }, - [0x129B]={ - category="lo", - direction="l", - }, - [0x129C]={ - category="lo", - direction="l", - }, - [0x129D]={ - category="lo", - direction="l", - }, - [0x129E]={ - category="lo", - direction="l", - }, - [0x129F]={ - category="lo", - direction="l", - }, - [0x12A0]={ - category="lo", - direction="l", - }, - [0x12A1]={ - category="lo", - direction="l", - }, - [0x12A2]={ - category="lo", - direction="l", - }, - [0x12A3]={ - category="lo", - direction="l", - }, - [0x12A4]={ - category="lo", - direction="l", - }, - [0x12A5]={ - category="lo", - direction="l", - }, - [0x12A6]={ - category="lo", - direction="l", - }, - [0x12A7]={ - category="lo", - direction="l", - }, - [0x12A8]={ - category="lo", - direction="l", - }, - [0x12A9]={ - category="lo", - direction="l", - }, - [0x12AA]={ - category="lo", - direction="l", - }, - [0x12AB]={ - category="lo", - direction="l", - }, - [0x12AC]={ - category="lo", - direction="l", - }, - [0x12AD]={ - category="lo", - direction="l", - }, - [0x12AE]={ - category="lo", - direction="l", - }, - [0x12AF]={ - category="lo", - direction="l", - }, - [0x12B0]={ - category="lo", - direction="l", - }, - [0x12B2]={ - category="lo", - direction="l", - }, - [0x12B3]={ - category="lo", - direction="l", - }, - [0x12B4]={ - category="lo", - direction="l", - }, - [0x12B5]={ - category="lo", - direction="l", - }, - [0x12B8]={ - category="lo", - direction="l", - }, - [0x12B9]={ - category="lo", - direction="l", - }, - [0x12BA]={ - category="lo", - direction="l", - }, - [0x12BB]={ - category="lo", - direction="l", - }, - [0x12BC]={ - category="lo", - direction="l", - }, - [0x12BD]={ - category="lo", - direction="l", - }, - [0x12BE]={ - category="lo", - direction="l", - }, - [0x12C0]={ - category="lo", - direction="l", - }, - [0x12C2]={ - category="lo", - direction="l", - }, - [0x12C3]={ - category="lo", - direction="l", - }, - [0x12C4]={ - category="lo", - direction="l", - }, - [0x12C5]={ - category="lo", - direction="l", - }, - [0x12C8]={ - category="lo", - direction="l", - }, - [0x12C9]={ - category="lo", - direction="l", - }, - [0x12CA]={ - category="lo", - direction="l", - }, - [0x12CB]={ - category="lo", - direction="l", - }, - [0x12CC]={ - category="lo", - direction="l", - }, - [0x12CD]={ - category="lo", - direction="l", - }, - [0x12CE]={ - category="lo", - direction="l", - }, - [0x12CF]={ - category="lo", - direction="l", - }, - [0x12D0]={ - category="lo", - direction="l", - }, - [0x12D1]={ - category="lo", - direction="l", - }, - [0x12D2]={ - category="lo", - direction="l", - }, - [0x12D3]={ - category="lo", - direction="l", - }, - [0x12D4]={ - category="lo", - direction="l", - }, - [0x12D5]={ - category="lo", - direction="l", - }, - [0x12D6]={ - category="lo", - direction="l", - }, - [0x12D8]={ - category="lo", - direction="l", - }, - [0x12D9]={ - category="lo", - direction="l", - }, - [0x12DA]={ - category="lo", - direction="l", - }, - [0x12DB]={ - category="lo", - direction="l", - }, - [0x12DC]={ - category="lo", - direction="l", - }, - [0x12DD]={ - category="lo", - direction="l", - }, - [0x12DE]={ - category="lo", - direction="l", - }, - [0x12DF]={ - category="lo", - direction="l", - }, - [0x12E0]={ - category="lo", - direction="l", - }, - [0x12E1]={ - category="lo", - direction="l", - }, - [0x12E2]={ - category="lo", - direction="l", - }, - [0x12E3]={ - category="lo", - direction="l", - }, - [0x12E4]={ - category="lo", - direction="l", - }, - [0x12E5]={ - category="lo", - direction="l", - }, - [0x12E6]={ - category="lo", - direction="l", - }, - [0x12E7]={ - category="lo", - direction="l", - }, - [0x12E8]={ - category="lo", - direction="l", - }, - [0x12E9]={ - category="lo", - direction="l", - }, - [0x12EA]={ - category="lo", - direction="l", - }, - [0x12EB]={ - category="lo", - direction="l", - }, - [0x12EC]={ - category="lo", - direction="l", - }, - [0x12ED]={ - category="lo", - direction="l", - }, - [0x12EE]={ - category="lo", - direction="l", - }, - [0x12EF]={ - category="lo", - direction="l", - }, - [0x12F0]={ - category="lo", - direction="l", - }, - [0x12F1]={ - category="lo", - direction="l", - }, - [0x12F2]={ - category="lo", - direction="l", - }, - [0x12F3]={ - category="lo", - direction="l", - }, - [0x12F4]={ - category="lo", - direction="l", - }, - [0x12F5]={ - category="lo", - direction="l", - }, - [0x12F6]={ - category="lo", - direction="l", - }, - [0x12F7]={ - category="lo", - direction="l", - }, - [0x12F8]={ - category="lo", - direction="l", - }, - [0x12F9]={ - category="lo", - direction="l", - }, - [0x12FA]={ - category="lo", - direction="l", - }, - [0x12FB]={ - category="lo", - direction="l", - }, - [0x12FC]={ - category="lo", - direction="l", - }, - [0x12FD]={ - category="lo", - direction="l", - }, - [0x12FE]={ - category="lo", - direction="l", - }, - [0x12FF]={ - category="lo", - direction="l", - }, - [0x1300]={ - category="lo", - direction="l", - }, - [0x1301]={ - category="lo", - direction="l", - }, - [0x1302]={ - category="lo", - direction="l", - }, - [0x1303]={ - category="lo", - direction="l", - }, - [0x1304]={ - category="lo", - direction="l", - }, - [0x1305]={ - category="lo", - direction="l", - }, - [0x1306]={ - category="lo", - direction="l", - }, - [0x1307]={ - category="lo", - direction="l", - }, - [0x1308]={ - category="lo", - direction="l", - }, - [0x1309]={ - category="lo", - direction="l", - }, - [0x130A]={ - category="lo", - direction="l", - }, - [0x130B]={ - category="lo", - direction="l", - }, - [0x130C]={ - category="lo", - direction="l", - }, - [0x130D]={ - category="lo", - direction="l", - }, - [0x130E]={ - category="lo", - direction="l", - }, - [0x130F]={ - category="lo", - direction="l", - }, - [0x1310]={ - category="lo", - direction="l", - }, - [0x1312]={ - category="lo", - direction="l", - }, - [0x1313]={ - category="lo", - direction="l", - }, - [0x1314]={ - category="lo", - direction="l", - }, - [0x1315]={ - category="lo", - direction="l", - }, - [0x1318]={ - category="lo", - direction="l", - }, - [0x1319]={ - category="lo", - direction="l", - }, - [0x131A]={ - category="lo", - direction="l", - }, - [0x131B]={ - category="lo", - direction="l", - }, - [0x131C]={ - category="lo", - direction="l", - }, - [0x131D]={ - category="lo", - direction="l", - }, - [0x131E]={ - category="lo", - direction="l", - }, - [0x131F]={ - category="lo", - direction="l", - }, - [0x1320]={ - category="lo", - direction="l", - }, - [0x1321]={ - category="lo", - direction="l", - }, - [0x1322]={ - category="lo", - direction="l", - }, - [0x1323]={ - category="lo", - direction="l", - }, - [0x1324]={ - category="lo", - direction="l", - }, - [0x1325]={ - category="lo", - direction="l", - }, - [0x1326]={ - category="lo", - direction="l", - }, - [0x1327]={ - category="lo", - direction="l", - }, - [0x1328]={ - category="lo", - direction="l", - }, - [0x1329]={ - category="lo", - direction="l", - }, - [0x132A]={ - category="lo", - direction="l", - }, - [0x132B]={ - category="lo", - direction="l", - }, - [0x132C]={ - category="lo", - direction="l", - }, - [0x132D]={ - category="lo", - direction="l", - }, - [0x132E]={ - category="lo", - direction="l", - }, - [0x132F]={ - category="lo", - direction="l", - }, - [0x1330]={ - category="lo", - direction="l", - }, - [0x1331]={ - category="lo", - direction="l", - }, - [0x1332]={ - category="lo", - direction="l", - }, - [0x1333]={ - category="lo", - direction="l", - }, - [0x1334]={ - category="lo", - direction="l", - }, - [0x1335]={ - category="lo", - direction="l", - }, - [0x1336]={ - category="lo", - direction="l", - }, - [0x1337]={ - category="lo", - direction="l", - }, - [0x1338]={ - category="lo", - direction="l", - }, - [0x1339]={ - category="lo", - direction="l", - }, - [0x133A]={ - category="lo", - direction="l", - }, - [0x133B]={ - category="lo", - direction="l", - }, - [0x133C]={ - category="lo", - direction="l", - }, - [0x133D]={ - category="lo", - direction="l", - }, - [0x133E]={ - category="lo", - direction="l", - }, - [0x133F]={ - category="lo", - direction="l", - }, - [0x1340]={ - category="lo", - direction="l", - }, - [0x1341]={ - category="lo", - direction="l", - }, - [0x1342]={ - category="lo", - direction="l", - }, - [0x1343]={ - category="lo", - direction="l", - }, - [0x1344]={ - category="lo", - direction="l", - }, - [0x1345]={ - category="lo", - direction="l", - }, - [0x1346]={ - category="lo", - direction="l", - }, - [0x1347]={ - category="lo", - direction="l", - }, - [0x1348]={ - category="lo", - direction="l", - }, - [0x1349]={ - category="lo", - direction="l", - }, - [0x134A]={ - category="lo", - direction="l", - }, - [0x134B]={ - category="lo", - direction="l", - }, - [0x134C]={ - category="lo", - direction="l", - }, - [0x134D]={ - category="lo", - direction="l", - }, - [0x134E]={ - category="lo", - direction="l", - }, - [0x134F]={ - category="lo", - direction="l", - }, - [0x1350]={ - category="lo", - direction="l", - }, - [0x1351]={ - category="lo", - direction="l", - }, - [0x1352]={ - category="lo", - direction="l", - }, - [0x1353]={ - category="lo", - direction="l", - }, - [0x1354]={ - category="lo", - direction="l", - }, - [0x1355]={ - category="lo", - direction="l", - }, - [0x1356]={ - category="lo", - direction="l", - }, - [0x1357]={ - category="lo", - direction="l", - }, - [0x1358]={ - category="lo", - direction="l", - }, - [0x1359]={ - category="lo", - direction="l", - }, - [0x135A]={ - category="lo", - direction="l", - }, - [0x135D]={ - category="mn", - direction="nsm", - }, - [0x135E]={ - category="mn", - direction="nsm", - }, - [0x135F]={ - category="mn", - direction="nsm", - }, - [0x1360]={ - category="so", - direction="l", - }, - [0x1361]={ - category="po", - direction="l", - }, - [0x1362]={ - category="po", - direction="l", - }, - [0x1363]={ - category="po", - direction="l", - }, - [0x1364]={ - category="po", - direction="l", - }, - [0x1365]={ - category="po", - direction="l", - }, - [0x1366]={ - category="po", - direction="l", - }, - [0x1367]={ - category="po", - direction="l", - }, - [0x1368]={ - category="po", - direction="l", - }, - [0x1369]={ - category="no", - direction="l", - }, - [0x136A]={ - category="no", - direction="l", - }, - [0x136B]={ - category="no", - direction="l", - }, - [0x136C]={ - category="no", - direction="l", - }, - [0x136D]={ - category="no", - direction="l", - }, - [0x136E]={ - category="no", - direction="l", - }, - [0x136F]={ - category="no", - direction="l", - }, - [0x1370]={ - category="no", - direction="l", - }, - [0x1371]={ - category="no", - direction="l", - }, - [0x1372]={ - category="no", - direction="l", - }, - [0x1373]={ - category="no", - direction="l", - }, - [0x1374]={ - category="no", - direction="l", - }, - [0x1375]={ - category="no", - direction="l", - }, - [0x1376]={ - category="no", - direction="l", - }, - [0x1377]={ - category="no", - direction="l", - }, - [0x1378]={ - category="no", - direction="l", - }, - [0x1379]={ - category="no", - direction="l", - }, - [0x137A]={ - category="no", - direction="l", - }, - [0x137B]={ - category="no", - direction="l", - }, - [0x137C]={ - category="no", - direction="l", - }, - [0x1380]={ - category="lo", - direction="l", - }, - [0x1381]={ - category="lo", - direction="l", - }, - [0x1382]={ - category="lo", - direction="l", - }, - [0x1383]={ - category="lo", - direction="l", - }, - [0x1384]={ - category="lo", - direction="l", - }, - [0x1385]={ - category="lo", - direction="l", - }, - [0x1386]={ - category="lo", - direction="l", - }, - [0x1387]={ - category="lo", - direction="l", - }, - [0x1388]={ - category="lo", - direction="l", - }, - [0x1389]={ - category="lo", - direction="l", - }, - [0x138A]={ - category="lo", - direction="l", - }, - [0x138B]={ - category="lo", - direction="l", - }, - [0x138C]={ - category="lo", - direction="l", - }, - [0x138D]={ - category="lo", - direction="l", - }, - [0x138E]={ - category="lo", - direction="l", - }, - [0x138F]={ - category="lo", - direction="l", - }, - [0x1390]={ - category="so", - direction="on", - }, - [0x1391]={ - category="so", - direction="on", - }, - [0x1392]={ - category="so", - direction="on", - }, - [0x1393]={ - category="so", - direction="on", - }, - [0x1394]={ - category="so", - direction="on", - }, - [0x1395]={ - category="so", - direction="on", - }, - [0x1396]={ - category="so", - direction="on", - }, - [0x1397]={ - category="so", - direction="on", - }, - [0x1398]={ - category="so", - direction="on", - }, - [0x1399]={ - category="so", - direction="on", - }, - [0x13A0]={ - category="lo", - direction="l", - }, - [0x13A1]={ - category="lo", - direction="l", - }, - [0x13A2]={ - category="lo", - direction="l", - }, - [0x13A3]={ - category="lo", - direction="l", - }, - [0x13A4]={ - category="lo", - direction="l", - }, - [0x13A5]={ - category="lo", - direction="l", - }, - [0x13A6]={ - category="lo", - direction="l", - }, - [0x13A7]={ - category="lo", - direction="l", - }, - [0x13A8]={ - category="lo", - direction="l", - }, - [0x13A9]={ - category="lo", - direction="l", - }, - [0x13AA]={ - category="lo", - direction="l", - }, - [0x13AB]={ - category="lo", - direction="l", - }, - [0x13AC]={ - category="lo", - direction="l", - }, - [0x13AD]={ - category="lo", - direction="l", - }, - [0x13AE]={ - category="lo", - direction="l", - }, - [0x13AF]={ - category="lo", - direction="l", - }, - [0x13B0]={ - category="lo", - direction="l", - }, - [0x13B1]={ - category="lo", - direction="l", - }, - [0x13B2]={ - category="lo", - direction="l", - }, - [0x13B3]={ - category="lo", - direction="l", - }, - [0x13B4]={ - category="lo", - direction="l", - }, - [0x13B5]={ - category="lo", - direction="l", - }, - [0x13B6]={ - category="lo", - direction="l", - }, - [0x13B7]={ - category="lo", - direction="l", - }, - [0x13B8]={ - category="lo", - direction="l", - }, - [0x13B9]={ - category="lo", - direction="l", - }, - [0x13BA]={ - category="lo", - direction="l", - }, - [0x13BB]={ - category="lo", - direction="l", - }, - [0x13BC]={ - category="lo", - direction="l", - }, - [0x13BD]={ - category="lo", - direction="l", - }, - [0x13BE]={ - category="lo", - direction="l", - }, - [0x13BF]={ - category="lo", - direction="l", - }, - [0x13C0]={ - category="lo", - direction="l", - }, - [0x13C1]={ - category="lo", - direction="l", - }, - [0x13C2]={ - category="lo", - direction="l", - }, - [0x13C3]={ - category="lo", - direction="l", - }, - [0x13C4]={ - category="lo", - direction="l", - }, - [0x13C5]={ - category="lo", - direction="l", - }, - [0x13C6]={ - category="lo", - direction="l", - }, - [0x13C7]={ - category="lo", - direction="l", - }, - [0x13C8]={ - category="lo", - direction="l", - }, - [0x13C9]={ - category="lo", - direction="l", - }, - [0x13CA]={ - category="lo", - direction="l", - }, - [0x13CB]={ - category="lo", - direction="l", - }, - [0x13CC]={ - category="lo", - direction="l", - }, - [0x13CD]={ - category="lo", - direction="l", - }, - [0x13CE]={ - category="lo", - direction="l", - }, - [0x13CF]={ - category="lo", - direction="l", - }, - [0x13D0]={ - category="lo", - direction="l", - }, - [0x13D1]={ - category="lo", - direction="l", - }, - [0x13D2]={ - category="lo", - direction="l", - }, - [0x13D3]={ - category="lo", - direction="l", - }, - [0x13D4]={ - category="lo", - direction="l", - }, - [0x13D5]={ - category="lo", - direction="l", - }, - [0x13D6]={ - category="lo", - direction="l", - }, - [0x13D7]={ - category="lo", - direction="l", - }, - [0x13D8]={ - category="lo", - direction="l", - }, - [0x13D9]={ - category="lo", - direction="l", - }, - [0x13DA]={ - category="lo", - direction="l", - }, - [0x13DB]={ - category="lo", - direction="l", - }, - [0x13DC]={ - category="lo", - direction="l", - }, - [0x13DD]={ - category="lo", - direction="l", - }, - [0x13DE]={ - category="lo", - direction="l", - }, - [0x13DF]={ - category="lo", - direction="l", - }, - [0x13E0]={ - category="lo", - direction="l", - }, - [0x13E1]={ - category="lo", - direction="l", - }, - [0x13E2]={ - category="lo", - direction="l", - }, - [0x13E3]={ - category="lo", - direction="l", - }, - [0x13E4]={ - category="lo", - direction="l", - }, - [0x13E5]={ - category="lo", - direction="l", - }, - [0x13E6]={ - category="lo", - direction="l", - }, - [0x13E7]={ - category="lo", - direction="l", - }, - [0x13E8]={ - category="lo", - direction="l", - }, - [0x13E9]={ - category="lo", - direction="l", - }, - [0x13EA]={ - category="lo", - direction="l", - }, - [0x13EB]={ - category="lo", - direction="l", - }, - [0x13EC]={ - category="lo", - direction="l", - }, - [0x13ED]={ - category="lo", - direction="l", - }, - [0x13EE]={ - category="lo", - direction="l", - }, - [0x13EF]={ - category="lo", - direction="l", - }, - [0x13F0]={ - category="lo", - direction="l", - }, - [0x13F1]={ - category="lo", - direction="l", - }, - [0x13F2]={ - category="lo", - direction="l", - }, - [0x13F3]={ - category="lo", - direction="l", - }, - [0x13F4]={ - category="lo", - direction="l", - }, - [0x13F5]={ - category="lu", - direction="l", - }, - [0x13F8]={ - category="ll", - direction="l", - }, - [0x13F9]={ - category="ll", - direction="l", - }, - [0x13FA]={ - category="ll", - direction="l", - }, - [0x13FB]={ - category="ll", - direction="l", - }, - [0x13FC]={ - category="ll", - direction="l", - }, - [0x13FD]={ - category="ll", - direction="l", - }, - [0x1400]={ - category="pd", - direction="on", - }, - [0x1401]={ - category="lo", - direction="l", - }, - [0x1402]={ - category="lo", - direction="l", - }, - [0x1403]={ - category="lo", - direction="l", - }, - [0x1404]={ - category="lo", - direction="l", - }, - [0x1405]={ - category="lo", - direction="l", - }, - [0x1406]={ - category="lo", - direction="l", - }, - [0x1407]={ - category="lo", - direction="l", - }, - [0x1408]={ - category="lo", - direction="l", - }, - [0x1409]={ - category="lo", - direction="l", - }, - [0x140A]={ - category="lo", - direction="l", - }, - [0x140B]={ - category="lo", - direction="l", - }, - [0x140C]={ - category="lo", - direction="l", - }, - [0x140D]={ - category="lo", - direction="l", - }, - [0x140E]={ - category="lo", - direction="l", - }, - [0x140F]={ - category="lo", - direction="l", - }, - [0x1410]={ - category="lo", - direction="l", - }, - [0x1411]={ - category="lo", - direction="l", - }, - [0x1412]={ - category="lo", - direction="l", - }, - [0x1413]={ - category="lo", - direction="l", - }, - [0x1414]={ - category="lo", - direction="l", - }, - [0x1415]={ - category="lo", - direction="l", - }, - [0x1416]={ - category="lo", - direction="l", - }, - [0x1417]={ - category="lo", - direction="l", - }, - [0x1418]={ - category="lo", - direction="l", - }, - [0x1419]={ - category="lo", - direction="l", - }, - [0x141A]={ - category="lo", - direction="l", - }, - [0x141B]={ - category="lo", - direction="l", - }, - [0x141C]={ - category="lo", - direction="l", - }, - [0x141D]={ - category="lo", - direction="l", - }, - [0x141E]={ - category="lo", - direction="l", - }, - [0x141F]={ - category="lo", - direction="l", - }, - [0x1420]={ - category="lo", - direction="l", - }, - [0x1421]={ - category="lo", - direction="l", - }, - [0x1422]={ - category="lo", - direction="l", - }, - [0x1423]={ - category="lo", - direction="l", - }, - [0x1424]={ - category="lo", - direction="l", - }, - [0x1425]={ - category="lo", - direction="l", - }, - [0x1426]={ - category="lo", - direction="l", - }, - [0x1427]={ - category="lo", - direction="l", - }, - [0x1428]={ - category="lo", - direction="l", - }, - [0x1429]={ - category="lo", - direction="l", - }, - [0x142A]={ - category="lo", - direction="l", - }, - [0x142B]={ - category="lo", - direction="l", - }, - [0x142C]={ - category="lo", - direction="l", - }, - [0x142D]={ - category="lo", - direction="l", - }, - [0x142E]={ - category="lo", - direction="l", - }, - [0x142F]={ - category="lo", - direction="l", - }, - [0x1430]={ - category="lo", - direction="l", - }, - [0x1431]={ - category="lo", - direction="l", - }, - [0x1432]={ - category="lo", - direction="l", - }, - [0x1433]={ - category="lo", - direction="l", - }, - [0x1434]={ - category="lo", - direction="l", - }, - [0x1435]={ - category="lo", - direction="l", - }, - [0x1436]={ - category="lo", - direction="l", - }, - [0x1437]={ - category="lo", - direction="l", - }, - [0x1438]={ - category="lo", - direction="l", - }, - [0x1439]={ - category="lo", - direction="l", - }, - [0x143A]={ - category="lo", - direction="l", - }, - [0x143B]={ - category="lo", - direction="l", - }, - [0x143C]={ - category="lo", - direction="l", - }, - [0x143D]={ - category="lo", - direction="l", - }, - [0x143E]={ - category="lo", - direction="l", - }, - [0x143F]={ - category="lo", - direction="l", - }, - [0x1440]={ - category="lo", - direction="l", - }, - [0x1441]={ - category="lo", - direction="l", - }, - [0x1442]={ - category="lo", - direction="l", - }, - [0x1443]={ - category="lo", - direction="l", - }, - [0x1444]={ - category="lo", - direction="l", - }, - [0x1445]={ - category="lo", - direction="l", - }, - [0x1446]={ - category="lo", - direction="l", - }, - [0x1447]={ - category="lo", - direction="l", - }, - [0x1448]={ - category="lo", - direction="l", - }, - [0x1449]={ - category="lo", - direction="l", - }, - [0x144A]={ - category="lo", - direction="l", - }, - [0x144B]={ - category="lo", - direction="l", - }, - [0x144C]={ - category="lo", - direction="l", - }, - [0x144D]={ - category="lo", - direction="l", - }, - [0x144E]={ - category="lo", - direction="l", - }, - [0x144F]={ - category="lo", - direction="l", - }, - [0x1450]={ - category="lo", - direction="l", - }, - [0x1451]={ - category="lo", - direction="l", - }, - [0x1452]={ - category="lo", - direction="l", - }, - [0x1453]={ - category="lo", - direction="l", - }, - [0x1454]={ - category="lo", - direction="l", - }, - [0x1455]={ - category="lo", - direction="l", - }, - [0x1456]={ - category="lo", - direction="l", - }, - [0x1457]={ - category="lo", - direction="l", - }, - [0x1458]={ - category="lo", - direction="l", - }, - [0x1459]={ - category="lo", - direction="l", - }, - [0x145A]={ - category="lo", - direction="l", - }, - [0x145B]={ - category="lo", - direction="l", - }, - [0x145C]={ - category="lo", - direction="l", - }, - [0x145D]={ - category="lo", - direction="l", - }, - [0x145E]={ - category="lo", - direction="l", - }, - [0x145F]={ - category="lo", - direction="l", - }, - [0x1460]={ - category="lo", - direction="l", - }, - [0x1461]={ - category="lo", - direction="l", - }, - [0x1462]={ - category="lo", - direction="l", - }, - [0x1463]={ - category="lo", - direction="l", - }, - [0x1464]={ - category="lo", - direction="l", - }, - [0x1465]={ - category="lo", - direction="l", - }, - [0x1466]={ - category="lo", - direction="l", - }, - [0x1467]={ - category="lo", - direction="l", - }, - [0x1468]={ - category="lo", - direction="l", - }, - [0x1469]={ - category="lo", - direction="l", - }, - [0x146A]={ - category="lo", - direction="l", - }, - [0x146B]={ - category="lo", - direction="l", - }, - [0x146C]={ - category="lo", - direction="l", - }, - [0x146D]={ - category="lo", - direction="l", - }, - [0x146E]={ - category="lo", - direction="l", - }, - [0x146F]={ - category="lo", - direction="l", - }, - [0x1470]={ - category="lo", - direction="l", - }, - [0x1471]={ - category="lo", - direction="l", - }, - [0x1472]={ - category="lo", - direction="l", - }, - [0x1473]={ - category="lo", - direction="l", - }, - [0x1474]={ - category="lo", - direction="l", - }, - [0x1475]={ - category="lo", - direction="l", - }, - [0x1476]={ - category="lo", - direction="l", - }, - [0x1477]={ - category="lo", - direction="l", - }, - [0x1478]={ - category="lo", - direction="l", - }, - [0x1479]={ - category="lo", - direction="l", - }, - [0x147A]={ - category="lo", - direction="l", - }, - [0x147B]={ - category="lo", - direction="l", - }, - [0x147C]={ - category="lo", - direction="l", - }, - [0x147D]={ - category="lo", - direction="l", - }, - [0x147E]={ - category="lo", - direction="l", - }, - [0x147F]={ - category="lo", - direction="l", - }, - [0x1480]={ - category="lo", - direction="l", - }, - [0x1481]={ - category="lo", - direction="l", - }, - [0x1482]={ - category="lo", - direction="l", - }, - [0x1483]={ - category="lo", - direction="l", - }, - [0x1484]={ - category="lo", - direction="l", - }, - [0x1485]={ - category="lo", - direction="l", - }, - [0x1486]={ - category="lo", - direction="l", - }, - [0x1487]={ - category="lo", - direction="l", - }, - [0x1488]={ - category="lo", - direction="l", - }, - [0x1489]={ - category="lo", - direction="l", - }, - [0x148A]={ - category="lo", - direction="l", - }, - [0x148B]={ - category="lo", - direction="l", - }, - [0x148C]={ - category="lo", - direction="l", - }, - [0x148D]={ - category="lo", - direction="l", - }, - [0x148E]={ - category="lo", - direction="l", - }, - [0x148F]={ - category="lo", - direction="l", - }, - [0x1490]={ - category="lo", - direction="l", - }, - [0x1491]={ - category="lo", - direction="l", - }, - [0x1492]={ - category="lo", - direction="l", - }, - [0x1493]={ - category="lo", - direction="l", - }, - [0x1494]={ - category="lo", - direction="l", - }, - [0x1495]={ - category="lo", - direction="l", - }, - [0x1496]={ - category="lo", - direction="l", - }, - [0x1497]={ - category="lo", - direction="l", - }, - [0x1498]={ - category="lo", - direction="l", - }, - [0x1499]={ - category="lo", - direction="l", - }, - [0x149A]={ - category="lo", - direction="l", - }, - [0x149B]={ - category="lo", - direction="l", - }, - [0x149C]={ - category="lo", - direction="l", - }, - [0x149D]={ - category="lo", - direction="l", - }, - [0x149E]={ - category="lo", - direction="l", - }, - [0x149F]={ - category="lo", - direction="l", - }, - [0x14A0]={ - category="lo", - direction="l", - }, - [0x14A1]={ - category="lo", - direction="l", - }, - [0x14A2]={ - category="lo", - direction="l", - }, - [0x14A3]={ - category="lo", - direction="l", - }, - [0x14A4]={ - category="lo", - direction="l", - }, - [0x14A5]={ - category="lo", - direction="l", - }, - [0x14A6]={ - category="lo", - direction="l", - }, - [0x14A7]={ - category="lo", - direction="l", - }, - [0x14A8]={ - category="lo", - direction="l", - }, - [0x14A9]={ - category="lo", - direction="l", - }, - [0x14AA]={ - category="lo", - direction="l", - }, - [0x14AB]={ - category="lo", - direction="l", - }, - [0x14AC]={ - category="lo", - direction="l", - }, - [0x14AD]={ - category="lo", - direction="l", - }, - [0x14AE]={ - category="lo", - direction="l", - }, - [0x14AF]={ - category="lo", - direction="l", - }, - [0x14B0]={ - category="lo", - direction="l", - }, - [0x14B1]={ - category="lo", - direction="l", - }, - [0x14B2]={ - category="lo", - direction="l", - }, - [0x14B3]={ - category="lo", - direction="l", - }, - [0x14B4]={ - category="lo", - direction="l", - }, - [0x14B5]={ - category="lo", - direction="l", - }, - [0x14B6]={ - category="lo", - direction="l", - }, - [0x14B7]={ - category="lo", - direction="l", - }, - [0x14B8]={ - category="lo", - direction="l", - }, - [0x14B9]={ - category="lo", - direction="l", - }, - [0x14BA]={ - category="lo", - direction="l", - }, - [0x14BB]={ - category="lo", - direction="l", - }, - [0x14BC]={ - category="lo", - direction="l", - }, - [0x14BD]={ - category="lo", - direction="l", - }, - [0x14BE]={ - category="lo", - direction="l", - }, - [0x14BF]={ - category="lo", - direction="l", - }, - [0x14C0]={ - category="lo", - direction="l", - }, - [0x14C1]={ - category="lo", - direction="l", - }, - [0x14C2]={ - category="lo", - direction="l", - }, - [0x14C3]={ - category="lo", - direction="l", - }, - [0x14C4]={ - category="lo", - direction="l", - }, - [0x14C5]={ - category="lo", - direction="l", - }, - [0x14C6]={ - category="lo", - direction="l", - }, - [0x14C7]={ - category="lo", - direction="l", - }, - [0x14C8]={ - category="lo", - direction="l", - }, - [0x14C9]={ - category="lo", - direction="l", - }, - [0x14CA]={ - category="lo", - direction="l", - }, - [0x14CB]={ - category="lo", - direction="l", - }, - [0x14CC]={ - category="lo", - direction="l", - }, - [0x14CD]={ - category="lo", - direction="l", - }, - [0x14CE]={ - category="lo", - direction="l", - }, - [0x14CF]={ - category="lo", - direction="l", - }, - [0x14D0]={ - category="lo", - direction="l", - }, - [0x14D1]={ - category="lo", - direction="l", - }, - [0x14D2]={ - category="lo", - direction="l", - }, - [0x14D3]={ - category="lo", - direction="l", - }, - [0x14D4]={ - category="lo", - direction="l", - }, - [0x14D5]={ - category="lo", - direction="l", - }, - [0x14D6]={ - category="lo", - direction="l", - }, - [0x14D7]={ - category="lo", - direction="l", - }, - [0x14D8]={ - category="lo", - direction="l", - }, - [0x14D9]={ - category="lo", - direction="l", - }, - [0x14DA]={ - category="lo", - direction="l", - }, - [0x14DB]={ - category="lo", - direction="l", - }, - [0x14DC]={ - category="lo", - direction="l", - }, - [0x14DD]={ - category="lo", - direction="l", - }, - [0x14DE]={ - category="lo", - direction="l", - }, - [0x14DF]={ - category="lo", - direction="l", - }, - [0x14E0]={ - category="lo", - direction="l", - }, - [0x14E1]={ - category="lo", - direction="l", - }, - [0x14E2]={ - category="lo", - direction="l", - }, - [0x14E3]={ - category="lo", - direction="l", - }, - [0x14E4]={ - category="lo", - direction="l", - }, - [0x14E5]={ - category="lo", - direction="l", - }, - [0x14E6]={ - category="lo", - direction="l", - }, - [0x14E7]={ - category="lo", - direction="l", - }, - [0x14E8]={ - category="lo", - direction="l", - }, - [0x14E9]={ - category="lo", - direction="l", - }, - [0x14EA]={ - category="lo", - direction="l", - }, - [0x14EB]={ - category="lo", - direction="l", - }, - [0x14EC]={ - category="lo", - direction="l", - }, - [0x14ED]={ - category="lo", - direction="l", - }, - [0x14EE]={ - category="lo", - direction="l", - }, - [0x14EF]={ - category="lo", - direction="l", - }, - [0x14F0]={ - category="lo", - direction="l", - }, - [0x14F1]={ - category="lo", - direction="l", - }, - [0x14F2]={ - category="lo", - direction="l", - }, - [0x14F3]={ - category="lo", - direction="l", - }, - [0x14F4]={ - category="lo", - direction="l", - }, - [0x14F5]={ - category="lo", - direction="l", - }, - [0x14F6]={ - category="lo", - direction="l", - }, - [0x14F7]={ - category="lo", - direction="l", - }, - [0x14F8]={ - category="lo", - direction="l", - }, - [0x14F9]={ - category="lo", - direction="l", - }, - [0x14FA]={ - category="lo", - direction="l", - }, - [0x14FB]={ - category="lo", - direction="l", - }, - [0x14FC]={ - category="lo", - direction="l", - }, - [0x14FD]={ - category="lo", - direction="l", - }, - [0x14FE]={ - category="lo", - direction="l", - }, - [0x14FF]={ - category="lo", - direction="l", - }, - [0x1500]={ - category="lo", - direction="l", - }, - [0x1501]={ - category="lo", - direction="l", - }, - [0x1502]={ - category="lo", - direction="l", - }, - [0x1503]={ - category="lo", - direction="l", - }, - [0x1504]={ - category="lo", - direction="l", - }, - [0x1505]={ - category="lo", - direction="l", - }, - [0x1506]={ - category="lo", - direction="l", - }, - [0x1507]={ - category="lo", - direction="l", - }, - [0x1508]={ - category="lo", - direction="l", - }, - [0x1509]={ - category="lo", - direction="l", - }, - [0x150A]={ - category="lo", - direction="l", - }, - [0x150B]={ - category="lo", - direction="l", - }, - [0x150C]={ - category="lo", - direction="l", - }, - [0x150D]={ - category="lo", - direction="l", - }, - [0x150E]={ - category="lo", - direction="l", - }, - [0x150F]={ - category="lo", - direction="l", - }, - [0x1510]={ - category="lo", - direction="l", - }, - [0x1511]={ - category="lo", - direction="l", - }, - [0x1512]={ - category="lo", - direction="l", - }, - [0x1513]={ - category="lo", - direction="l", - }, - [0x1514]={ - category="lo", - direction="l", - }, - [0x1515]={ - category="lo", - direction="l", - }, - [0x1516]={ - category="lo", - direction="l", - }, - [0x1517]={ - category="lo", - direction="l", - }, - [0x1518]={ - category="lo", - direction="l", - }, - [0x1519]={ - category="lo", - direction="l", - }, - [0x151A]={ - category="lo", - direction="l", - }, - [0x151B]={ - category="lo", - direction="l", - }, - [0x151C]={ - category="lo", - direction="l", - }, - [0x151D]={ - category="lo", - direction="l", - }, - [0x151E]={ - category="lo", - direction="l", - }, - [0x151F]={ - category="lo", - direction="l", - }, - [0x1520]={ - category="lo", - direction="l", - }, - [0x1521]={ - category="lo", - direction="l", - }, - [0x1522]={ - category="lo", - direction="l", - }, - [0x1523]={ - category="lo", - direction="l", - }, - [0x1524]={ - category="lo", - direction="l", - }, - [0x1525]={ - category="lo", - direction="l", - }, - [0x1526]={ - category="lo", - direction="l", - }, - [0x1527]={ - category="lo", - direction="l", - }, - [0x1528]={ - category="lo", - direction="l", - }, - [0x1529]={ - category="lo", - direction="l", - }, - [0x152A]={ - category="lo", - direction="l", - }, - [0x152B]={ - category="lo", - direction="l", - }, - [0x152C]={ - category="lo", - direction="l", - }, - [0x152D]={ - category="lo", - direction="l", - }, - [0x152E]={ - category="lo", - direction="l", - }, - [0x152F]={ - category="lo", - direction="l", - }, - [0x1530]={ - category="lo", - direction="l", - }, - [0x1531]={ - category="lo", - direction="l", - }, - [0x1532]={ - category="lo", - direction="l", - }, - [0x1533]={ - category="lo", - direction="l", - }, - [0x1534]={ - category="lo", - direction="l", - }, - [0x1535]={ - category="lo", - direction="l", - }, - [0x1536]={ - category="lo", - direction="l", - }, - [0x1537]={ - category="lo", - direction="l", - }, - [0x1538]={ - category="lo", - direction="l", - }, - [0x1539]={ - category="lo", - direction="l", - }, - [0x153A]={ - category="lo", - direction="l", - }, - [0x153B]={ - category="lo", - direction="l", - }, - [0x153C]={ - category="lo", - direction="l", - }, - [0x153D]={ - category="lo", - direction="l", - }, - [0x153E]={ - category="lo", - direction="l", - }, - [0x153F]={ - category="lo", - direction="l", - }, - [0x1540]={ - category="lo", - direction="l", - }, - [0x1541]={ - category="lo", - direction="l", - }, - [0x1542]={ - category="lo", - direction="l", - }, - [0x1543]={ - category="lo", - direction="l", - }, - [0x1544]={ - category="lo", - direction="l", - }, - [0x1545]={ - category="lo", - direction="l", - }, - [0x1546]={ - category="lo", - direction="l", - }, - [0x1547]={ - category="lo", - direction="l", - }, - [0x1548]={ - category="lo", - direction="l", - }, - [0x1549]={ - category="lo", - direction="l", - }, - [0x154A]={ - category="lo", - direction="l", - }, - [0x154B]={ - category="lo", - direction="l", - }, - [0x154C]={ - category="lo", - direction="l", - }, - [0x154D]={ - category="lo", - direction="l", - }, - [0x154E]={ - category="lo", - direction="l", - }, - [0x154F]={ - category="lo", - direction="l", - }, - [0x1550]={ - category="lo", - direction="l", - }, - [0x1551]={ - category="lo", - direction="l", - }, - [0x1552]={ - category="lo", - direction="l", - }, - [0x1553]={ - category="lo", - direction="l", - }, - [0x1554]={ - category="lo", - direction="l", - }, - [0x1555]={ - category="lo", - direction="l", - }, - [0x1556]={ - category="lo", - direction="l", - }, - [0x1557]={ - category="lo", - direction="l", - }, - [0x1558]={ - category="lo", - direction="l", - }, - [0x1559]={ - category="lo", - direction="l", - }, - [0x155A]={ - category="lo", - direction="l", - }, - [0x155B]={ - category="lo", - direction="l", - }, - [0x155C]={ - category="lo", - direction="l", - }, - [0x155D]={ - category="lo", - direction="l", - }, - [0x155E]={ - category="lo", - direction="l", - }, - [0x155F]={ - category="lo", - direction="l", - }, - [0x1560]={ - category="lo", - direction="l", - }, - [0x1561]={ - category="lo", - direction="l", - }, - [0x1562]={ - category="lo", - direction="l", - }, - [0x1563]={ - category="lo", - direction="l", - }, - [0x1564]={ - category="lo", - direction="l", - }, - [0x1565]={ - category="lo", - direction="l", - }, - [0x1566]={ - category="lo", - direction="l", - }, - [0x1567]={ - category="lo", - direction="l", - }, - [0x1568]={ - category="lo", - direction="l", - }, - [0x1569]={ - category="lo", - direction="l", - }, - [0x156A]={ - category="lo", - direction="l", - }, - [0x156B]={ - category="lo", - direction="l", - }, - [0x156C]={ - category="lo", - direction="l", - }, - [0x156D]={ - category="lo", - direction="l", - }, - [0x156E]={ - category="lo", - direction="l", - }, - [0x156F]={ - category="lo", - direction="l", - }, - [0x1570]={ - category="lo", - direction="l", - }, - [0x1571]={ - category="lo", - direction="l", - }, - [0x1572]={ - category="lo", - direction="l", - }, - [0x1573]={ - category="lo", - direction="l", - }, - [0x1574]={ - category="lo", - direction="l", - }, - [0x1575]={ - category="lo", - direction="l", - }, - [0x1576]={ - category="lo", - direction="l", - }, - [0x1577]={ - category="lo", - direction="l", - }, - [0x1578]={ - category="lo", - direction="l", - }, - [0x1579]={ - category="lo", - direction="l", - }, - [0x157A]={ - category="lo", - direction="l", - }, - [0x157B]={ - category="lo", - direction="l", - }, - [0x157C]={ - category="lo", - direction="l", - }, - [0x157D]={ - category="lo", - direction="l", - }, - [0x157E]={ - category="lo", - direction="l", - }, - [0x157F]={ - category="lo", - direction="l", - }, - [0x1580]={ - category="lo", - direction="l", - }, - [0x1581]={ - category="lo", - direction="l", - }, - [0x1582]={ - category="lo", - direction="l", - }, - [0x1583]={ - category="lo", - direction="l", - }, - [0x1584]={ - category="lo", - direction="l", - }, - [0x1585]={ - category="lo", - direction="l", - }, - [0x1586]={ - category="lo", - direction="l", - }, - [0x1587]={ - category="lo", - direction="l", - }, - [0x1588]={ - category="lo", - direction="l", - }, - [0x1589]={ - category="lo", - direction="l", - }, - [0x158A]={ - category="lo", - direction="l", - }, - [0x158B]={ - category="lo", - direction="l", - }, - [0x158C]={ - category="lo", - direction="l", - }, - [0x158D]={ - category="lo", - direction="l", - }, - [0x158E]={ - category="lo", - direction="l", - }, - [0x158F]={ - category="lo", - direction="l", - }, - [0x1590]={ - category="lo", - direction="l", - }, - [0x1591]={ - category="lo", - direction="l", - }, - [0x1592]={ - category="lo", - direction="l", - }, - [0x1593]={ - category="lo", - direction="l", - }, - [0x1594]={ - category="lo", - direction="l", - }, - [0x1595]={ - category="lo", - direction="l", - }, - [0x1596]={ - category="lo", - direction="l", - }, - [0x1597]={ - category="lo", - direction="l", - }, - [0x1598]={ - category="lo", - direction="l", - }, - [0x1599]={ - category="lo", - direction="l", - }, - [0x159A]={ - category="lo", - direction="l", - }, - [0x159B]={ - category="lo", - direction="l", - }, - [0x159C]={ - category="lo", - direction="l", - }, - [0x159D]={ - category="lo", - direction="l", - }, - [0x159E]={ - category="lo", - direction="l", - }, - [0x159F]={ - category="lo", - direction="l", - }, - [0x15A0]={ - category="lo", - direction="l", - }, - [0x15A1]={ - category="lo", - direction="l", - }, - [0x15A2]={ - category="lo", - direction="l", - }, - [0x15A3]={ - category="lo", - direction="l", - }, - [0x15A4]={ - category="lo", - direction="l", - }, - [0x15A5]={ - category="lo", - direction="l", - }, - [0x15A6]={ - category="lo", - direction="l", - }, - [0x15A7]={ - category="lo", - direction="l", - }, - [0x15A8]={ - category="lo", - direction="l", - }, - [0x15A9]={ - category="lo", - direction="l", - }, - [0x15AA]={ - category="lo", - direction="l", - }, - [0x15AB]={ - category="lo", - direction="l", - }, - [0x15AC]={ - category="lo", - direction="l", - }, - [0x15AD]={ - category="lo", - direction="l", - }, - [0x15AE]={ - category="lo", - direction="l", - }, - [0x15AF]={ - category="lo", - direction="l", - }, - [0x15B0]={ - category="lo", - direction="l", - }, - [0x15B1]={ - category="lo", - direction="l", - }, - [0x15B2]={ - category="lo", - direction="l", - }, - [0x15B3]={ - category="lo", - direction="l", - }, - [0x15B4]={ - category="lo", - direction="l", - }, - [0x15B5]={ - category="lo", - direction="l", - }, - [0x15B6]={ - category="lo", - direction="l", - }, - [0x15B7]={ - category="lo", - direction="l", - }, - [0x15B8]={ - category="lo", - direction="l", - }, - [0x15B9]={ - category="lo", - direction="l", - }, - [0x15BA]={ - category="lo", - direction="l", - }, - [0x15BB]={ - category="lo", - direction="l", - }, - [0x15BC]={ - category="lo", - direction="l", - }, - [0x15BD]={ - category="lo", - direction="l", - }, - [0x15BE]={ - category="lo", - direction="l", - }, - [0x15BF]={ - category="lo", - direction="l", - }, - [0x15C0]={ - category="lo", - direction="l", - }, - [0x15C1]={ - category="lo", - direction="l", - }, - [0x15C2]={ - category="lo", - direction="l", - }, - [0x15C3]={ - category="lo", - direction="l", - }, - [0x15C4]={ - category="lo", - direction="l", - }, - [0x15C5]={ - category="lo", - direction="l", - }, - [0x15C6]={ - category="lo", - direction="l", - }, - [0x15C7]={ - category="lo", - direction="l", - }, - [0x15C8]={ - category="lo", - direction="l", - }, - [0x15C9]={ - category="lo", - direction="l", - }, - [0x15CA]={ - category="lo", - direction="l", - }, - [0x15CB]={ - category="lo", - direction="l", - }, - [0x15CC]={ - category="lo", - direction="l", - }, - [0x15CD]={ - category="lo", - direction="l", - }, - [0x15CE]={ - category="lo", - direction="l", - }, - [0x15CF]={ - category="lo", - direction="l", - }, - [0x15D0]={ - category="lo", - direction="l", - }, - [0x15D1]={ - category="lo", - direction="l", - }, - [0x15D2]={ - category="lo", - direction="l", - }, - [0x15D3]={ - category="lo", - direction="l", - }, - [0x15D4]={ - category="lo", - direction="l", - }, - [0x15D5]={ - category="lo", - direction="l", - }, - [0x15D6]={ - category="lo", - direction="l", - }, - [0x15D7]={ - category="lo", - direction="l", - }, - [0x15D8]={ - category="lo", - direction="l", - }, - [0x15D9]={ - category="lo", - direction="l", - }, - [0x15DA]={ - category="lo", - direction="l", - }, - [0x15DB]={ - category="lo", - direction="l", - }, - [0x15DC]={ - category="lo", - direction="l", - }, - [0x15DD]={ - category="lo", - direction="l", - }, - [0x15DE]={ - category="lo", - direction="l", - }, - [0x15DF]={ - category="lo", - direction="l", - }, - [0x15E0]={ - category="lo", - direction="l", - }, - [0x15E1]={ - category="lo", - direction="l", - }, - [0x15E2]={ - category="lo", - direction="l", - }, - [0x15E3]={ - category="lo", - direction="l", - }, - [0x15E4]={ - category="lo", - direction="l", - }, - [0x15E5]={ - category="lo", - direction="l", - }, - [0x15E6]={ - category="lo", - direction="l", - }, - [0x15E7]={ - category="lo", - direction="l", - }, - [0x15E8]={ - category="lo", - direction="l", - }, - [0x15E9]={ - category="lo", - direction="l", - }, - [0x15EA]={ - category="lo", - direction="l", - }, - [0x15EB]={ - category="lo", - direction="l", - }, - [0x15EC]={ - category="lo", - direction="l", - }, - [0x15ED]={ - category="lo", - direction="l", - }, - [0x15EE]={ - category="lo", - direction="l", - }, - [0x15EF]={ - category="lo", - direction="l", - }, - [0x15F0]={ - category="lo", - direction="l", - }, - [0x15F1]={ - category="lo", - direction="l", - }, - [0x15F2]={ - category="lo", - direction="l", - }, - [0x15F3]={ - category="lo", - direction="l", - }, - [0x15F4]={ - category="lo", - direction="l", - }, - [0x15F5]={ - category="lo", - direction="l", - }, - [0x15F6]={ - category="lo", - direction="l", - }, - [0x15F7]={ - category="lo", - direction="l", - }, - [0x15F8]={ - category="lo", - direction="l", - }, - [0x15F9]={ - category="lo", - direction="l", - }, - [0x15FA]={ - category="lo", - direction="l", - }, - [0x15FB]={ - category="lo", - direction="l", - }, - [0x15FC]={ - category="lo", - direction="l", - }, - [0x15FD]={ - category="lo", - direction="l", - }, - [0x15FE]={ - category="lo", - direction="l", - }, - [0x15FF]={ - category="lo", - direction="l", - }, - [0x1600]={ - category="lo", - direction="l", - }, - [0x1601]={ - category="lo", - direction="l", - }, - [0x1602]={ - category="lo", - direction="l", - }, - [0x1603]={ - category="lo", - direction="l", - }, - [0x1604]={ - category="lo", - direction="l", - }, - [0x1605]={ - category="lo", - direction="l", - }, - [0x1606]={ - category="lo", - direction="l", - }, - [0x1607]={ - category="lo", - direction="l", - }, - [0x1608]={ - category="lo", - direction="l", - }, - [0x1609]={ - category="lo", - direction="l", - }, - [0x160A]={ - category="lo", - direction="l", - }, - [0x160B]={ - category="lo", - direction="l", - }, - [0x160C]={ - category="lo", - direction="l", - }, - [0x160D]={ - category="lo", - direction="l", - }, - [0x160E]={ - category="lo", - direction="l", - }, - [0x160F]={ - category="lo", - direction="l", - }, - [0x1610]={ - category="lo", - direction="l", - }, - [0x1611]={ - category="lo", - direction="l", - }, - [0x1612]={ - category="lo", - direction="l", - }, - [0x1613]={ - category="lo", - direction="l", - }, - [0x1614]={ - category="lo", - direction="l", - }, - [0x1615]={ - category="lo", - direction="l", - }, - [0x1616]={ - category="lo", - direction="l", - }, - [0x1617]={ - category="lo", - direction="l", - }, - [0x1618]={ - category="lo", - direction="l", - }, - [0x1619]={ - category="lo", - direction="l", - }, - [0x161A]={ - category="lo", - direction="l", - }, - [0x161B]={ - category="lo", - direction="l", - }, - [0x161C]={ - category="lo", - direction="l", - }, - [0x161D]={ - category="lo", - direction="l", - }, - [0x161E]={ - category="lo", - direction="l", - }, - [0x161F]={ - category="lo", - direction="l", - }, - [0x1620]={ - category="lo", - direction="l", - }, - [0x1621]={ - category="lo", - direction="l", - }, - [0x1622]={ - category="lo", - direction="l", - }, - [0x1623]={ - category="lo", - direction="l", - }, - [0x1624]={ - category="lo", - direction="l", - }, - [0x1625]={ - category="lo", - direction="l", - }, - [0x1626]={ - category="lo", - direction="l", - }, - [0x1627]={ - category="lo", - direction="l", - }, - [0x1628]={ - category="lo", - direction="l", - }, - [0x1629]={ - category="lo", - direction="l", - }, - [0x162A]={ - category="lo", - direction="l", - }, - [0x162B]={ - category="lo", - direction="l", - }, - [0x162C]={ - category="lo", - direction="l", - }, - [0x162D]={ - category="lo", - direction="l", - }, - [0x162E]={ - category="lo", - direction="l", - }, - [0x162F]={ - category="lo", - direction="l", - }, - [0x1630]={ - category="lo", - direction="l", - }, - [0x1631]={ - category="lo", - direction="l", - }, - [0x1632]={ - category="lo", - direction="l", - }, - [0x1633]={ - category="lo", - direction="l", - }, - [0x1634]={ - category="lo", - direction="l", - }, - [0x1635]={ - category="lo", - direction="l", - }, - [0x1636]={ - category="lo", - direction="l", - }, - [0x1637]={ - category="lo", - direction="l", - }, - [0x1638]={ - category="lo", - direction="l", - }, - [0x1639]={ - category="lo", - direction="l", - }, - [0x163A]={ - category="lo", - direction="l", - }, - [0x163B]={ - category="lo", - direction="l", - }, - [0x163C]={ - category="lo", - direction="l", - }, - [0x163D]={ - category="lo", - direction="l", - }, - [0x163E]={ - category="lo", - direction="l", - }, - [0x163F]={ - category="lo", - direction="l", - }, - [0x1640]={ - category="lo", - direction="l", - }, - [0x1641]={ - category="lo", - direction="l", - }, - [0x1642]={ - category="lo", - direction="l", - }, - [0x1643]={ - category="lo", - direction="l", - }, - [0x1644]={ - category="lo", - direction="l", - }, - [0x1645]={ - category="lo", - direction="l", - }, - [0x1646]={ - category="lo", - direction="l", - }, - [0x1647]={ - category="lo", - direction="l", - }, - [0x1648]={ - category="lo", - direction="l", - }, - [0x1649]={ - category="lo", - direction="l", - }, - [0x164A]={ - category="lo", - direction="l", - }, - [0x164B]={ - category="lo", - direction="l", - }, - [0x164C]={ - category="lo", - direction="l", - }, - [0x164D]={ - category="lo", - direction="l", - }, - [0x164E]={ - category="lo", - direction="l", - }, - [0x164F]={ - category="lo", - direction="l", - }, - [0x1650]={ - category="lo", - direction="l", - }, - [0x1651]={ - category="lo", - direction="l", - }, - [0x1652]={ - category="lo", - direction="l", - }, - [0x1653]={ - category="lo", - direction="l", - }, - [0x1654]={ - category="lo", - direction="l", - }, - [0x1655]={ - category="lo", - direction="l", - }, - [0x1656]={ - category="lo", - direction="l", - }, - [0x1657]={ - category="lo", - direction="l", - }, - [0x1658]={ - category="lo", - direction="l", - }, - [0x1659]={ - category="lo", - direction="l", - }, - [0x165A]={ - category="lo", - direction="l", - }, - [0x165B]={ - category="lo", - direction="l", - }, - [0x165C]={ - category="lo", - direction="l", - }, - [0x165D]={ - category="lo", - direction="l", - }, - [0x165E]={ - category="lo", - direction="l", - }, - [0x165F]={ - category="lo", - direction="l", - }, - [0x1660]={ - category="lo", - direction="l", - }, - [0x1661]={ - category="lo", - direction="l", - }, - [0x1662]={ - category="lo", - direction="l", - }, - [0x1663]={ - category="lo", - direction="l", - }, - [0x1664]={ - category="lo", - direction="l", - }, - [0x1665]={ - category="lo", - direction="l", - }, - [0x1666]={ - category="lo", - direction="l", - }, - [0x1667]={ - category="lo", - direction="l", - }, - [0x1668]={ - category="lo", - direction="l", - }, - [0x1669]={ - category="lo", - direction="l", - }, - [0x166A]={ - category="lo", - direction="l", - }, - [0x166B]={ - category="lo", - direction="l", - }, - [0x166C]={ - category="lo", - direction="l", - }, - [0x166D]={ - category="po", - direction="l", - }, - [0x166E]={ - category="po", - direction="l", - }, - [0x166F]={ - category="lo", - direction="l", - }, - [0x1670]={ - category="lo", - direction="l", - }, - [0x1671]={ - category="lo", - direction="l", - }, - [0x1672]={ - category="lo", - direction="l", - }, - [0x1673]={ - category="lo", - direction="l", - }, - [0x1674]={ - category="lo", - direction="l", - }, - [0x1675]={ - category="lo", - direction="l", - }, - [0x1676]={ - category="lo", - direction="l", - }, - [0x1677]={ - category="lo", - direction="l", - }, - [0x1678]={ - category="lo", - direction="l", - }, - [0x1679]={ - category="lo", - direction="l", - }, - [0x167A]={ - category="lo", - direction="l", - }, - [0x167B]={ - category="lo", - direction="l", - }, - [0x167C]={ - category="lo", - direction="l", - }, - [0x167D]={ - category="lo", - direction="l", - }, - [0x167E]={ - category="lo", - direction="l", - }, - [0x167F]={ - category="lo", - direction="l", - }, - [0x1680]={ - category="zs", - direction="ws", - }, - [0x1681]={ - category="lo", - direction="l", - }, - [0x1682]={ - category="lo", - direction="l", - }, - [0x1683]={ - category="lo", - direction="l", - }, - [0x1684]={ - category="lo", - direction="l", - }, - [0x1685]={ - category="lo", - direction="l", - }, - [0x1686]={ - category="lo", - direction="l", - }, - [0x1687]={ - category="lo", - direction="l", - }, - [0x1688]={ - category="lo", - direction="l", - }, - [0x1689]={ - category="lo", - direction="l", - }, - [0x168A]={ - category="lo", - direction="l", - }, - [0x168B]={ - category="lo", - direction="l", - }, - [0x168C]={ - category="lo", - direction="l", - }, - [0x168D]={ - category="lo", - direction="l", - }, - [0x168E]={ - category="lo", - direction="l", - }, - [0x168F]={ - category="lo", - direction="l", - }, - [0x1690]={ - category="lo", - direction="l", - }, - [0x1691]={ - category="lo", - direction="l", - }, - [0x1692]={ - category="lo", - direction="l", - }, - [0x1693]={ - category="lo", - direction="l", - }, - [0x1694]={ - category="lo", - direction="l", - }, - [0x1695]={ - category="lo", - direction="l", - }, - [0x1696]={ - category="lo", - direction="l", - }, - [0x1697]={ - category="lo", - direction="l", - }, - [0x1698]={ - category="lo", - direction="l", - }, - [0x1699]={ - category="lo", - direction="l", - }, - [0x169A]={ - category="lo", - direction="l", - }, - [0x169B]={ - category="ps", - direction="on", - mirror=0x169C, - }, - [0x169C]={ - category="pe", - direction="on", - mirror=0x169B, - }, - [0x16A0]={ - category="lo", - direction="l", - }, - [0x16A1]={ - category="lo", - direction="l", - }, - [0x16A2]={ - category="lo", - direction="l", - }, - [0x16A3]={ - category="lo", - direction="l", - }, - [0x16A4]={ - category="lo", - direction="l", - }, - [0x16A5]={ - category="lo", - direction="l", - }, - [0x16A6]={ - category="lo", - direction="l", - }, - [0x16A7]={ - category="lo", - direction="l", - }, - [0x16A8]={ - category="lo", - direction="l", - }, - [0x16A9]={ - category="lo", - direction="l", - }, - [0x16AA]={ - category="lo", - direction="l", - }, - [0x16AB]={ - category="lo", - direction="l", - }, - [0x16AC]={ - category="lo", - direction="l", - }, - [0x16AD]={ - category="lo", - direction="l", - }, - [0x16AE]={ - category="lo", - direction="l", - }, - [0x16AF]={ - category="lo", - direction="l", - }, - [0x16B0]={ - category="lo", - direction="l", - }, - [0x16B1]={ - category="lo", - direction="l", - }, - [0x16B2]={ - category="lo", - direction="l", - }, - [0x16B3]={ - category="lo", - direction="l", - }, - [0x16B4]={ - category="lo", - direction="l", - }, - [0x16B5]={ - category="lo", - direction="l", - }, - [0x16B6]={ - category="lo", - direction="l", - }, - [0x16B7]={ - category="lo", - direction="l", - }, - [0x16B8]={ - category="lo", - direction="l", - }, - [0x16B9]={ - category="lo", - direction="l", - }, - [0x16BA]={ - category="lo", - direction="l", - }, - [0x16BB]={ - category="lo", - direction="l", - }, - [0x16BC]={ - category="lo", - direction="l", - }, - [0x16BD]={ - category="lo", - direction="l", - }, - [0x16BE]={ - category="lo", - direction="l", - }, - [0x16BF]={ - category="lo", - direction="l", - }, - [0x16C0]={ - category="lo", - direction="l", - }, - [0x16C1]={ - category="lo", - direction="l", - }, - [0x16C2]={ - category="lo", - direction="l", - }, - [0x16C3]={ - category="lo", - direction="l", - }, - [0x16C4]={ - category="lo", - direction="l", - }, - [0x16C5]={ - category="lo", - direction="l", - }, - [0x16C6]={ - category="lo", - direction="l", - }, - [0x16C7]={ - category="lo", - direction="l", - }, - [0x16C8]={ - category="lo", - direction="l", - }, - [0x16C9]={ - category="lo", - direction="l", - }, - [0x16CA]={ - category="lo", - direction="l", - }, - [0x16CB]={ - category="lo", - direction="l", - }, - [0x16CC]={ - category="lo", - direction="l", - }, - [0x16CD]={ - category="lo", - direction="l", - }, - [0x16CE]={ - category="lo", - direction="l", - }, - [0x16CF]={ - category="lo", - direction="l", - }, - [0x16D0]={ - category="lo", - direction="l", - }, - [0x16D1]={ - category="lo", - direction="l", - }, - [0x16D2]={ - category="lo", - direction="l", - }, - [0x16D3]={ - category="lo", - direction="l", - }, - [0x16D4]={ - category="lo", - direction="l", - }, - [0x16D5]={ - category="lo", - direction="l", - }, - [0x16D6]={ - category="lo", - direction="l", - }, - [0x16D7]={ - category="lo", - direction="l", - }, - [0x16D8]={ - category="lo", - direction="l", - }, - [0x16D9]={ - category="lo", - direction="l", - }, - [0x16DA]={ - category="lo", - direction="l", - }, - [0x16DB]={ - category="lo", - direction="l", - }, - [0x16DC]={ - category="lo", - direction="l", - }, - [0x16DD]={ - category="lo", - direction="l", - }, - [0x16DE]={ - category="lo", - direction="l", - }, - [0x16DF]={ - category="lo", - direction="l", - }, - [0x16E0]={ - category="lo", - direction="l", - }, - [0x16E1]={ - category="lo", - direction="l", - }, - [0x16E2]={ - category="lo", - direction="l", - }, - [0x16E3]={ - category="lo", - direction="l", - }, - [0x16E4]={ - category="lo", - direction="l", - }, - [0x16E5]={ - category="lo", - direction="l", - }, - [0x16E6]={ - category="lo", - direction="l", - }, - [0x16E7]={ - category="lo", - direction="l", - }, - [0x16E8]={ - category="lo", - direction="l", - }, - [0x16E9]={ - category="lo", - direction="l", - }, - [0x16EA]={ - category="lo", - direction="l", - }, - [0x16EB]={ - category="po", - direction="l", - }, - [0x16EC]={ - category="po", - direction="l", - }, - [0x16ED]={ - category="po", - direction="l", - }, - [0x16EE]={ - category="nl", - direction="l", - }, - [0x16EF]={ - category="nl", - direction="l", - }, - [0x16F0]={ - category="nl", - direction="l", - }, - [0x16F1]={ - category="lo", - direction="l", - }, - [0x16F2]={ - category="lo", - direction="l", - }, - [0x16F3]={ - category="lo", - direction="l", - }, - [0x16F4]={ - category="lo", - direction="l", - }, - [0x16F5]={ - category="lo", - direction="l", - }, - [0x16F6]={ - category="lo", - direction="l", - }, - [0x16F7]={ - category="lo", - direction="l", - }, - [0x16F8]={ - category="lo", - direction="l", - }, - [0x1700]={ - category="lo", - direction="l", - }, - [0x1701]={ - category="lo", - direction="l", - }, - [0x1702]={ - category="lo", - direction="l", - }, - [0x1703]={ - category="lo", - direction="l", - }, - [0x1704]={ - category="lo", - direction="l", - }, - [0x1705]={ - category="lo", - direction="l", - }, - [0x1706]={ - category="lo", - direction="l", - }, - [0x1707]={ - category="lo", - direction="l", - }, - [0x1708]={ - category="lo", - direction="l", - }, - [0x1709]={ - category="lo", - direction="l", - }, - [0x170A]={ - category="lo", - direction="l", - }, - [0x170B]={ - category="lo", - direction="l", - }, - [0x170C]={ - category="lo", - direction="l", - }, - [0x170E]={ - category="lo", - direction="l", - }, - [0x170F]={ - category="lo", - direction="l", - }, - [0x1710]={ - category="lo", - direction="l", - }, - [0x1711]={ - category="lo", - direction="l", - }, - [0x1712]={ - category="mn", - direction="nsm", - }, - [0x1713]={ - category="mn", - direction="nsm", - }, - [0x1714]={ - category="mn", - direction="nsm", - }, - [0x1720]={ - category="lo", - direction="l", - }, - [0x1721]={ - category="lo", - direction="l", - }, - [0x1722]={ - category="lo", - direction="l", - }, - [0x1723]={ - category="lo", - direction="l", - }, - [0x1724]={ - category="lo", - direction="l", - }, - [0x1725]={ - category="lo", - direction="l", - }, - [0x1726]={ - category="lo", - direction="l", - }, - [0x1727]={ - category="lo", - direction="l", - }, - [0x1728]={ - category="lo", - direction="l", - }, - [0x1729]={ - category="lo", - direction="l", - }, - [0x172A]={ - category="lo", - direction="l", - }, - [0x172B]={ - category="lo", - direction="l", - }, - [0x172C]={ - category="lo", - direction="l", - }, - [0x172D]={ - category="lo", - direction="l", - }, - [0x172E]={ - category="lo", - direction="l", - }, - [0x172F]={ - category="lo", - direction="l", - }, - [0x1730]={ - category="lo", - direction="l", - }, - [0x1731]={ - category="lo", - direction="l", - }, - [0x1732]={ - category="mn", - direction="nsm", - }, - [0x1733]={ - category="mn", - direction="nsm", - }, - [0x1734]={ - category="mn", - direction="nsm", - }, - [0x1735]={ - category="po", - direction="l", - }, - [0x1736]={ - category="po", - direction="l", - }, - [0x1740]={ - category="lo", - direction="l", - }, - [0x1741]={ - category="lo", - direction="l", - }, - [0x1742]={ - category="lo", - direction="l", - }, - [0x1743]={ - category="lo", - direction="l", - }, - [0x1744]={ - category="lo", - direction="l", - }, - [0x1745]={ - category="lo", - direction="l", - }, - [0x1746]={ - category="lo", - direction="l", - }, - [0x1747]={ - category="lo", - direction="l", - }, - [0x1748]={ - category="lo", - direction="l", - }, - [0x1749]={ - category="lo", - direction="l", - }, - [0x174A]={ - category="lo", - direction="l", - }, - [0x174B]={ - category="lo", - direction="l", - }, - [0x174C]={ - category="lo", - direction="l", - }, - [0x174D]={ - category="lo", - direction="l", - }, - [0x174E]={ - category="lo", - direction="l", - }, - [0x174F]={ - category="lo", - direction="l", - }, - [0x1750]={ - category="lo", - direction="l", - }, - [0x1751]={ - category="lo", - direction="l", - }, - [0x1752]={ - category="mn", - direction="nsm", - }, - [0x1753]={ - category="mn", - direction="nsm", - }, - [0x1760]={ - category="lo", - direction="l", - }, - [0x1761]={ - category="lo", - direction="l", - }, - [0x1762]={ - category="lo", - direction="l", - }, - [0x1763]={ - category="lo", - direction="l", - }, - [0x1764]={ - category="lo", - direction="l", - }, - [0x1765]={ - category="lo", - direction="l", - }, - [0x1766]={ - category="lo", - direction="l", - }, - [0x1767]={ - category="lo", - direction="l", - }, - [0x1768]={ - category="lo", - direction="l", - }, - [0x1769]={ - category="lo", - direction="l", - }, - [0x176A]={ - category="lo", - direction="l", - }, - [0x176B]={ - category="lo", - direction="l", - }, - [0x176C]={ - category="lo", - direction="l", - }, - [0x176E]={ - category="lo", - direction="l", - }, - [0x176F]={ - category="lo", - direction="l", - }, - [0x1770]={ - category="lo", - direction="l", - }, - [0x1772]={ - category="mn", - direction="nsm", - }, - [0x1773]={ - category="mn", - direction="nsm", - }, - [0x1780]={ - category="lo", - direction="l", - }, - [0x1781]={ - category="lo", - direction="l", - }, - [0x1782]={ - category="lo", - direction="l", - }, - [0x1783]={ - category="lo", - direction="l", - }, - [0x1784]={ - category="lo", - direction="l", - }, - [0x1785]={ - category="lo", - direction="l", - }, - [0x1786]={ - category="lo", - direction="l", - }, - [0x1787]={ - category="lo", - direction="l", - }, - [0x1788]={ - category="lo", - direction="l", - }, - [0x1789]={ - category="lo", - direction="l", - }, - [0x178A]={ - category="lo", - direction="l", - }, - [0x178B]={ - category="lo", - direction="l", - }, - [0x178C]={ - category="lo", - direction="l", - }, - [0x178D]={ - category="lo", - direction="l", - }, - [0x178E]={ - category="lo", - direction="l", - }, - [0x178F]={ - category="lo", - direction="l", - }, - [0x1790]={ - category="lo", - direction="l", - }, - [0x1791]={ - category="lo", - direction="l", - }, - [0x1792]={ - category="lo", - direction="l", - }, - [0x1793]={ - category="lo", - direction="l", - }, - [0x1794]={ - category="lo", - direction="l", - }, - [0x1795]={ - category="lo", - direction="l", - }, - [0x1796]={ - category="lo", - direction="l", - }, - [0x1797]={ - category="lo", - direction="l", - }, - [0x1798]={ - category="lo", - direction="l", - }, - [0x1799]={ - category="lo", - direction="l", - }, - [0x179A]={ - category="lo", - direction="l", - }, - [0x179B]={ - category="lo", - direction="l", - }, - [0x179C]={ - category="lo", - direction="l", - }, - [0x179D]={ - category="lo", - direction="l", - }, - [0x179E]={ - category="lo", - direction="l", - }, - [0x179F]={ - category="lo", - direction="l", - }, - [0x17A0]={ - category="lo", - direction="l", - }, - [0x17A1]={ - category="lo", - direction="l", - }, - [0x17A2]={ - category="lo", - direction="l", - }, - [0x17A3]={ - category="lo", - direction="l", - }, - [0x17A4]={ - category="lo", - direction="l", - }, - [0x17A5]={ - category="lo", - direction="l", - }, - [0x17A6]={ - category="lo", - direction="l", - }, - [0x17A7]={ - category="lo", - direction="l", - }, - [0x17A8]={ - category="lo", - direction="l", - }, - [0x17A9]={ - category="lo", - direction="l", - }, - [0x17AA]={ - category="lo", - direction="l", - }, - [0x17AB]={ - category="lo", - direction="l", - }, - [0x17AC]={ - category="lo", - direction="l", - }, - [0x17AD]={ - category="lo", - direction="l", - }, - [0x17AE]={ - category="lo", - direction="l", - }, - [0x17AF]={ - category="lo", - direction="l", - }, - [0x17B0]={ - category="lo", - direction="l", - }, - [0x17B1]={ - category="lo", - direction="l", - }, - [0x17B2]={ - category="lo", - direction="l", - }, - [0x17B3]={ - category="lo", - direction="l", - }, - [0x17B4]={ - category="cf", - direction="nsm", - }, - [0x17B5]={ - category="cf", - direction="nsm", - }, - [0x17B6]={ - category="mc", - direction="l", - }, - [0x17B7]={ - category="mn", - direction="nsm", - }, - [0x17B8]={ - category="mn", - direction="nsm", - }, - [0x17B9]={ - category="mn", - direction="nsm", - }, - [0x17BA]={ - category="mn", - direction="nsm", - }, - [0x17BB]={ - category="mn", - direction="nsm", - }, - [0x17BC]={ - category="mn", - direction="nsm", - }, - [0x17BD]={ - category="mn", - direction="nsm", - }, - [0x17BE]={ - category="mc", - direction="l", - }, - [0x17BF]={ - category="mc", - direction="l", - }, - [0x17C0]={ - category="mc", - direction="l", - }, - [0x17C1]={ - category="mc", - direction="l", - }, - [0x17C2]={ - category="mc", - direction="l", - }, - [0x17C3]={ - category="mc", - direction="l", - }, - [0x17C4]={ - category="mc", - direction="l", - }, - [0x17C5]={ - category="mc", - direction="l", - }, - [0x17C6]={ - category="mn", - direction="nsm", - }, - [0x17C7]={ - category="mc", - direction="l", - }, - [0x17C8]={ - category="mc", - direction="l", - }, - [0x17C9]={ - category="mn", - direction="nsm", - }, - [0x17CA]={ - category="mn", - direction="nsm", - }, - [0x17CB]={ - category="mn", - direction="nsm", - }, - [0x17CC]={ - category="mn", - direction="nsm", - }, - [0x17CD]={ - category="mn", - direction="nsm", - }, - [0x17CE]={ - category="mn", - direction="nsm", - }, - [0x17CF]={ - category="mn", - direction="nsm", - }, - [0x17D0]={ - category="mn", - direction="nsm", - }, - [0x17D1]={ - category="mn", - direction="nsm", - }, - [0x17D2]={ - category="mn", - direction="nsm", - }, - [0x17D3]={ - category="mn", - direction="nsm", - }, - [0x17D4]={ - category="po", - direction="l", - }, - [0x17D5]={ - category="po", - direction="l", - }, - [0x17D6]={ - category="po", - direction="l", - }, - [0x17D7]={ - category="lm", - direction="l", - }, - [0x17D8]={ - category="po", - direction="l", - }, - [0x17D9]={ - category="po", - direction="l", - }, - [0x17DA]={ - category="po", - direction="l", - }, - [0x17DB]={ - category="sc", - direction="et", - }, - [0x17DC]={ - category="lo", - direction="l", - }, - [0x17DD]={ - category="mn", - direction="nsm", - }, - [0x17E0]={ - category="nd", - direction="l", - }, - [0x17E1]={ - category="nd", - direction="l", - }, - [0x17E2]={ - category="nd", - direction="l", - }, - [0x17E3]={ - category="nd", - direction="l", - }, - [0x17E4]={ - category="nd", - direction="l", - }, - [0x17E5]={ - category="nd", - direction="l", - }, - [0x17E6]={ - category="nd", - direction="l", - }, - [0x17E7]={ - category="nd", - direction="l", - }, - [0x17E8]={ - category="nd", - direction="l", - }, - [0x17E9]={ - category="nd", - direction="l", - }, - [0x17F0]={ - category="no", - direction="on", - }, - [0x17F1]={ - category="no", - direction="on", - }, - [0x17F2]={ - category="no", - direction="on", - }, - [0x17F3]={ - category="no", - direction="on", - }, - [0x17F4]={ - category="no", - direction="on", - }, - [0x17F5]={ - category="no", - direction="on", - }, - [0x17F6]={ - category="no", - direction="on", - }, - [0x17F7]={ - category="no", - direction="on", - }, - [0x17F8]={ - category="no", - direction="on", - }, - [0x17F9]={ - category="no", - direction="on", - }, - [0x1800]={ - category="po", - direction="on", - }, - [0x1801]={ - category="po", - direction="on", - }, - [0x1802]={ - category="po", - direction="on", - }, - [0x1803]={ - category="po", - direction="on", - }, - [0x1804]={ - category="po", - direction="on", - }, - [0x1805]={ - category="po", - direction="on", - }, - [0x1806]={ - category="pd", - direction="on", - }, - [0x1807]={ - category="po", - direction="on", - }, - [0x1808]={ - category="po", - direction="on", - }, - [0x1809]={ - category="po", - direction="on", - }, - [0x180A]={ - category="po", - direction="on", - }, - [0x180B]={ - category="mn", - direction="nsm", - }, - [0x180C]={ - category="mn", - direction="nsm", - }, - [0x180D]={ - category="mn", - direction="nsm", - }, - [0x180E]={ - category="zs", - direction="bn", - }, - [0x1810]={ - category="nd", - direction="l", - }, - [0x1811]={ - category="nd", - direction="l", - }, - [0x1812]={ - category="nd", - direction="l", - }, - [0x1813]={ - category="nd", - direction="l", - }, - [0x1814]={ - category="nd", - direction="l", - }, - [0x1815]={ - category="nd", - direction="l", - }, - [0x1816]={ - category="nd", - direction="l", - }, - [0x1817]={ - category="nd", - direction="l", - }, - [0x1818]={ - category="nd", - direction="l", - }, - [0x1819]={ - category="nd", - direction="l", - }, - [0x1820]={ - category="lo", - direction="l", - }, - [0x1821]={ - category="lo", - direction="l", - }, - [0x1822]={ - category="lo", - direction="l", - }, - [0x1823]={ - category="lo", - direction="l", - }, - [0x1824]={ - category="lo", - direction="l", - }, - [0x1825]={ - category="lo", - direction="l", - }, - [0x1826]={ - category="lo", - direction="l", - }, - [0x1827]={ - category="lo", - direction="l", - }, - [0x1828]={ - category="lo", - direction="l", - }, - [0x1829]={ - category="lo", - direction="l", - }, - [0x182A]={ - category="lo", - direction="l", - }, - [0x182B]={ - category="lo", - direction="l", - }, - [0x182C]={ - category="lo", - direction="l", - }, - [0x182D]={ - category="lo", - direction="l", - }, - [0x182E]={ - category="lo", - direction="l", - }, - [0x182F]={ - category="lo", - direction="l", - }, - [0x1830]={ - category="lo", - direction="l", - }, - [0x1831]={ - category="lo", - direction="l", - }, - [0x1832]={ - category="lo", - direction="l", - }, - [0x1833]={ - category="lo", - direction="l", - }, - [0x1834]={ - category="lo", - direction="l", - }, - [0x1835]={ - category="lo", - direction="l", - }, - [0x1836]={ - category="lo", - direction="l", - }, - [0x1837]={ - category="lo", - direction="l", - }, - [0x1838]={ - category="lo", - direction="l", - }, - [0x1839]={ - category="lo", - direction="l", - }, - [0x183A]={ - category="lo", - direction="l", - }, - [0x183B]={ - category="lo", - direction="l", - }, - [0x183C]={ - category="lo", - direction="l", - }, - [0x183D]={ - category="lo", - direction="l", - }, - [0x183E]={ - category="lo", - direction="l", - }, - [0x183F]={ - category="lo", - direction="l", - }, - [0x1840]={ - category="lo", - direction="l", - }, - [0x1841]={ - category="lo", - direction="l", - }, - [0x1842]={ - category="lo", - direction="l", - }, - [0x1843]={ - category="lm", - direction="l", - }, - [0x1844]={ - category="lo", - direction="l", - }, - [0x1845]={ - category="lo", - direction="l", - }, - [0x1846]={ - category="lo", - direction="l", - }, - [0x1847]={ - category="lo", - direction="l", - }, - [0x1848]={ - category="lo", - direction="l", - }, - [0x1849]={ - category="lo", - direction="l", - }, - [0x184A]={ - category="lo", - direction="l", - }, - [0x184B]={ - category="lo", - direction="l", - }, - [0x184C]={ - category="lo", - direction="l", - }, - [0x184D]={ - category="lo", - direction="l", - }, - [0x184E]={ - category="lo", - direction="l", - }, - [0x184F]={ - category="lo", - direction="l", - }, - [0x1850]={ - category="lo", - direction="l", - }, - [0x1851]={ - category="lo", - direction="l", - }, - [0x1852]={ - category="lo", - direction="l", - }, - [0x1853]={ - category="lo", - direction="l", - }, - [0x1854]={ - category="lo", - direction="l", - }, - [0x1855]={ - category="lo", - direction="l", - }, - [0x1856]={ - category="lo", - direction="l", - }, - [0x1857]={ - category="lo", - direction="l", - }, - [0x1858]={ - category="lo", - direction="l", - }, - [0x1859]={ - category="lo", - direction="l", - }, - [0x185A]={ - category="lo", - direction="l", - }, - [0x185B]={ - category="lo", - direction="l", - }, - [0x185C]={ - category="lo", - direction="l", - }, - [0x185D]={ - category="lo", - direction="l", - }, - [0x185E]={ - category="lo", - direction="l", - }, - [0x185F]={ - category="lo", - direction="l", - }, - [0x1860]={ - category="lo", - direction="l", - }, - [0x1861]={ - category="lo", - direction="l", - }, - [0x1862]={ - category="lo", - direction="l", - }, - [0x1863]={ - category="lo", - direction="l", - }, - [0x1864]={ - category="lo", - direction="l", - }, - [0x1865]={ - category="lo", - direction="l", - }, - [0x1866]={ - category="lo", - direction="l", - }, - [0x1867]={ - category="lo", - direction="l", - }, - [0x1868]={ - category="lo", - direction="l", - }, - [0x1869]={ - category="lo", - direction="l", - }, - [0x186A]={ - category="lo", - direction="l", - }, - [0x186B]={ - category="lo", - direction="l", - }, - [0x186C]={ - category="lo", - direction="l", - }, - [0x186D]={ - category="lo", - direction="l", - }, - [0x186E]={ - category="lo", - direction="l", - }, - [0x186F]={ - category="lo", - direction="l", - }, - [0x1870]={ - category="lo", - direction="l", - }, - [0x1871]={ - category="lo", - direction="l", - }, - [0x1872]={ - category="lo", - direction="l", - }, - [0x1873]={ - category="lo", - direction="l", - }, - [0x1874]={ - category="lo", - direction="l", - }, - [0x1875]={ - category="lo", - direction="l", - }, - [0x1876]={ - category="lo", - direction="l", - }, - [0x1877]={ - category="lo", - direction="l", - }, - [0x1880]={ - category="lo", - direction="l", - }, - [0x1881]={ - category="lo", - direction="l", - }, - [0x1882]={ - category="lo", - direction="l", - }, - [0x1883]={ - category="lo", - direction="l", - }, - [0x1884]={ - category="lo", - direction="l", - }, - [0x1885]={ - category="lo", - direction="nsm", - }, - [0x1886]={ - category="lo", - direction="nsm", - }, - [0x1887]={ - category="lo", - direction="l", - }, - [0x1888]={ - category="lo", - direction="l", - }, - [0x1889]={ - category="lo", - direction="l", - }, - [0x188A]={ - category="lo", - direction="l", - }, - [0x188B]={ - category="lo", - direction="l", - }, - [0x188C]={ - category="lo", - direction="l", - }, - [0x188D]={ - category="lo", - direction="l", - }, - [0x188E]={ - category="lo", - direction="l", - }, - [0x188F]={ - category="lo", - direction="l", - }, - [0x1890]={ - category="lo", - direction="l", - }, - [0x1891]={ - category="lo", - direction="l", - }, - [0x1892]={ - category="lo", - direction="l", - }, - [0x1893]={ - category="lo", - direction="l", - }, - [0x1894]={ - category="lo", - direction="l", - }, - [0x1895]={ - category="lo", - direction="l", - }, - [0x1896]={ - category="lo", - direction="l", - }, - [0x1897]={ - category="lo", - direction="l", - }, - [0x1898]={ - category="lo", - direction="l", - }, - [0x1899]={ - category="lo", - direction="l", - }, - [0x189A]={ - category="lo", - direction="l", - }, - [0x189B]={ - category="lo", - direction="l", - }, - [0x189C]={ - category="lo", - direction="l", - }, - [0x189D]={ - category="lo", - direction="l", - }, - [0x189E]={ - category="lo", - direction="l", - }, - [0x189F]={ - category="lo", - direction="l", - }, - [0x18A0]={ - category="lo", - direction="l", - }, - [0x18A1]={ - category="lo", - direction="l", - }, - [0x18A2]={ - category="lo", - direction="l", - }, - [0x18A3]={ - category="lo", - direction="l", - }, - [0x18A4]={ - category="lo", - direction="l", - }, - [0x18A5]={ - category="lo", - direction="l", - }, - [0x18A6]={ - category="lo", - direction="l", - }, - [0x18A7]={ - category="lo", - direction="l", - }, - [0x18A8]={ - category="lo", - direction="l", - }, - [0x18A9]={ - category="mn", - direction="nsm", - }, - [0x18AA]={ - category="lo", - direction="l", - }, - [0x18B0]={ - category="lo", - direction="l", - }, - [0x18B1]={ - category="lo", - direction="l", - }, - [0x18B2]={ - category="lo", - direction="l", - }, - [0x18B3]={ - category="lo", - direction="l", - }, - [0x18B4]={ - category="lo", - direction="l", - }, - [0x18B5]={ - category="lo", - direction="l", - }, - [0x18B6]={ - category="lo", - direction="l", - }, - [0x18B7]={ - category="lo", - direction="l", - }, - [0x18B8]={ - category="lo", - direction="l", - }, - [0x18B9]={ - category="lo", - direction="l", - }, - [0x18BA]={ - category="lo", - direction="l", - }, - [0x18BB]={ - category="lo", - direction="l", - }, - [0x18BC]={ - category="lo", - direction="l", - }, - [0x18BD]={ - category="lo", - direction="l", - }, - [0x18BE]={ - category="lo", - direction="l", - }, - [0x18BF]={ - category="lo", - direction="l", - }, - [0x18C0]={ - category="lo", - direction="l", - }, - [0x18C1]={ - category="lo", - direction="l", - }, - [0x18C2]={ - category="lo", - direction="l", - }, - [0x18C3]={ - category="lo", - direction="l", - }, - [0x18C4]={ - category="lo", - direction="l", - }, - [0x18C5]={ - category="lo", - direction="l", - }, - [0x18C6]={ - category="lo", - direction="l", - }, - [0x18C7]={ - category="lo", - direction="l", - }, - [0x18C8]={ - category="lo", - direction="l", - }, - [0x18C9]={ - category="lo", - direction="l", - }, - [0x18CA]={ - category="lo", - direction="l", - }, - [0x18CB]={ - category="lo", - direction="l", - }, - [0x18CC]={ - category="lo", - direction="l", - }, - [0x18CD]={ - category="lo", - direction="l", - }, - [0x18CE]={ - category="lo", - direction="l", - }, - [0x18CF]={ - category="lo", - direction="l", - }, - [0x18D0]={ - category="lo", - direction="l", - }, - [0x18D1]={ - category="lo", - direction="l", - }, - [0x18D2]={ - category="lo", - direction="l", - }, - [0x18D3]={ - category="lo", - direction="l", - }, - [0x18D4]={ - category="lo", - direction="l", - }, - [0x18D5]={ - category="lo", - direction="l", - }, - [0x18D6]={ - category="lo", - direction="l", - }, - [0x18D7]={ - category="lo", - direction="l", - }, - [0x18D8]={ - category="lo", - direction="l", - }, - [0x18D9]={ - category="lo", - direction="l", - }, - [0x18DA]={ - category="lo", - direction="l", - }, - [0x18DB]={ - category="lo", - direction="l", - }, - [0x18DC]={ - category="lo", - direction="l", - }, - [0x18DD]={ - category="lo", - direction="l", - }, - [0x18DE]={ - category="lo", - direction="l", - }, - [0x18DF]={ - category="lo", - direction="l", - }, - [0x18E0]={ - category="lo", - direction="l", - }, - [0x18E1]={ - category="lo", - direction="l", - }, - [0x18E2]={ - category="lo", - direction="l", - }, - [0x18E3]={ - category="lo", - direction="l", - }, - [0x18E4]={ - category="lo", - direction="l", - }, - [0x18E5]={ - category="lo", - direction="l", - }, - [0x18E6]={ - category="lo", - direction="l", - }, - [0x18E7]={ - category="lo", - direction="l", - }, - [0x18E8]={ - category="lo", - direction="l", - }, - [0x18E9]={ - category="lo", - direction="l", - }, - [0x18EA]={ - category="lo", - direction="l", - }, - [0x18EB]={ - category="lo", - direction="l", - }, - [0x18EC]={ - category="lo", - direction="l", - }, - [0x18ED]={ - category="lo", - direction="l", - }, - [0x18EE]={ - category="lo", - direction="l", - }, - [0x18EF]={ - category="lo", - direction="l", - }, - [0x18F0]={ - category="lo", - direction="l", - }, - [0x18F1]={ - category="lo", - direction="l", - }, - [0x18F2]={ - category="lo", - direction="l", - }, - [0x18F3]={ - category="lo", - direction="l", - }, - [0x18F4]={ - category="lo", - direction="l", - }, - [0x18F5]={ - category="lo", - direction="l", - }, - [0x1900]={ - category="lo", - direction="l", - }, - [0x1901]={ - category="lo", - direction="l", - }, - [0x1902]={ - category="lo", - direction="l", - }, - [0x1903]={ - category="lo", - direction="l", - }, - [0x1904]={ - category="lo", - direction="l", - }, - [0x1905]={ - category="lo", - direction="l", - }, - [0x1906]={ - category="lo", - direction="l", - }, - [0x1907]={ - category="lo", - direction="l", - }, - [0x1908]={ - category="lo", - direction="l", - }, - [0x1909]={ - category="lo", - direction="l", - }, - [0x190A]={ - category="lo", - direction="l", - }, - [0x190B]={ - category="lo", - direction="l", - }, - [0x190C]={ - category="lo", - direction="l", - }, - [0x190D]={ - category="lo", - direction="l", - }, - [0x190E]={ - category="lo", - direction="l", - }, - [0x190F]={ - category="lo", - direction="l", - }, - [0x1910]={ - category="lo", - direction="l", - }, - [0x1911]={ - category="lo", - direction="l", - }, - [0x1912]={ - category="lo", - direction="l", - }, - [0x1913]={ - category="lo", - direction="l", - }, - [0x1914]={ - category="lo", - direction="l", - }, - [0x1915]={ - category="lo", - direction="l", - }, - [0x1916]={ - category="lo", - direction="l", - }, - [0x1917]={ - category="lo", - direction="l", - }, - [0x1918]={ - category="lo", - direction="l", - }, - [0x1919]={ - category="lo", - direction="l", - }, - [0x191A]={ - category="lo", - direction="l", - }, - [0x191B]={ - category="lo", - direction="l", - }, - [0x191C]={ - category="lo", - direction="l", - }, - [0x191D]={ - category="lo", - direction="l", - }, - [0x191E]={ - category="lo", - direction="l", - }, - [0x1920]={ - category="mn", - direction="nsm", - }, - [0x1921]={ - category="mn", - direction="nsm", - }, - [0x1922]={ - category="mn", - direction="nsm", - }, - [0x1923]={ - category="mc", - direction="l", - }, - [0x1924]={ - category="mc", - direction="l", - }, - [0x1925]={ - category="mc", - direction="l", - }, - [0x1926]={ - category="mc", - direction="l", - }, - [0x1927]={ - category="mn", - direction="nsm", - }, - [0x1928]={ - category="mn", - direction="nsm", - }, - [0x1929]={ - category="mc", - direction="l", - }, - [0x192A]={ - category="mc", - direction="l", - }, - [0x192B]={ - category="mc", - direction="l", - }, - [0x1930]={ - category="mc", - direction="l", - }, - [0x1931]={ - category="mc", - direction="l", - }, - [0x1932]={ - category="mn", - direction="nsm", - }, - [0x1933]={ - category="mc", - direction="l", - }, - [0x1934]={ - category="mc", - direction="l", - }, - [0x1935]={ - category="mc", - direction="l", - }, - [0x1936]={ - category="mc", - direction="l", - }, - [0x1937]={ - category="mc", - direction="l", - }, - [0x1938]={ - category="mc", - direction="l", - }, - [0x1939]={ - category="mn", - direction="nsm", - }, - [0x193A]={ - category="mn", - direction="nsm", - }, - [0x193B]={ - category="mn", - direction="nsm", - }, - [0x1940]={ - category="so", - direction="on", - }, - [0x1944]={ - category="po", - direction="on", - }, - [0x1945]={ - category="po", - direction="on", - }, - [0x1946]={ - category="nd", - direction="l", - }, - [0x1947]={ - category="nd", - direction="l", - }, - [0x1948]={ - category="nd", - direction="l", - }, - [0x1949]={ - category="nd", - direction="l", - }, - [0x194A]={ - category="nd", - direction="l", - }, - [0x194B]={ - category="nd", - direction="l", - }, - [0x194C]={ - category="nd", - direction="l", - }, - [0x194D]={ - category="nd", - direction="l", - }, - [0x194E]={ - category="nd", - direction="l", - }, - [0x194F]={ - category="nd", - direction="l", - }, - [0x1950]={ - category="lo", - direction="l", - }, - [0x1951]={ - category="lo", - direction="l", - }, - [0x1952]={ - category="lo", - direction="l", - }, - [0x1953]={ - category="lo", - direction="l", - }, - [0x1954]={ - category="lo", - direction="l", - }, - [0x1955]={ - category="lo", - direction="l", - }, - [0x1956]={ - category="lo", - direction="l", - }, - [0x1957]={ - category="lo", - direction="l", - }, - [0x1958]={ - category="lo", - direction="l", - }, - [0x1959]={ - category="lo", - direction="l", - }, - [0x195A]={ - category="lo", - direction="l", - }, - [0x195B]={ - category="lo", - direction="l", - }, - [0x195C]={ - category="lo", - direction="l", - }, - [0x195D]={ - category="lo", - direction="l", - }, - [0x195E]={ - category="lo", - direction="l", - }, - [0x195F]={ - category="lo", - direction="l", - }, - [0x1960]={ - category="lo", - direction="l", - }, - [0x1961]={ - category="lo", - direction="l", - }, - [0x1962]={ - category="lo", - direction="l", - }, - [0x1963]={ - category="lo", - direction="l", - }, - [0x1964]={ - category="lo", - direction="l", - }, - [0x1965]={ - category="lo", - direction="l", - }, - [0x1966]={ - category="lo", - direction="l", - }, - [0x1967]={ - category="lo", - direction="l", - }, - [0x1968]={ - category="lo", - direction="l", - }, - [0x1969]={ - category="lo", - direction="l", - }, - [0x196A]={ - category="lo", - direction="l", - }, - [0x196B]={ - category="lo", - direction="l", - }, - [0x196C]={ - category="lo", - direction="l", - }, - [0x196D]={ - category="lo", - direction="l", - }, - [0x1970]={ - category="lo", - direction="l", - }, - [0x1971]={ - category="lo", - direction="l", - }, - [0x1972]={ - category="lo", - direction="l", - }, - [0x1973]={ - category="lo", - direction="l", - }, - [0x1974]={ - category="lo", - direction="l", - }, - [0x1980]={ - category="lo", - direction="l", - }, - [0x1981]={ - category="lo", - direction="l", - }, - [0x1982]={ - category="lo", - direction="l", - }, - [0x1983]={ - category="lo", - direction="l", - }, - [0x1984]={ - category="lo", - direction="l", - }, - [0x1985]={ - category="lo", - direction="l", - }, - [0x1986]={ - category="lo", - direction="l", - }, - [0x1987]={ - category="lo", - direction="l", - }, - [0x1988]={ - category="lo", - direction="l", - }, - [0x1989]={ - category="lo", - direction="l", - }, - [0x198A]={ - category="lo", - direction="l", - }, - [0x198B]={ - category="lo", - direction="l", - }, - [0x198C]={ - category="lo", - direction="l", - }, - [0x198D]={ - category="lo", - direction="l", - }, - [0x198E]={ - category="lo", - direction="l", - }, - [0x198F]={ - category="lo", - direction="l", - }, - [0x1990]={ - category="lo", - direction="l", - }, - [0x1991]={ - category="lo", - direction="l", - }, - [0x1992]={ - category="lo", - direction="l", - }, - [0x1993]={ - category="lo", - direction="l", - }, - [0x1994]={ - category="lo", - direction="l", - }, - [0x1995]={ - category="lo", - direction="l", - }, - [0x1996]={ - category="lo", - direction="l", - }, - [0x1997]={ - category="lo", - direction="l", - }, - [0x1998]={ - category="lo", - direction="l", - }, - [0x1999]={ - category="lo", - direction="l", - }, - [0x199A]={ - category="lo", - direction="l", - }, - [0x199B]={ - category="lo", - direction="l", - }, - [0x199C]={ - category="lo", - direction="l", - }, - [0x199D]={ - category="lo", - direction="l", - }, - [0x199E]={ - category="lo", - direction="l", - }, - [0x199F]={ - category="lo", - direction="l", - }, - [0x19A0]={ - category="lo", - direction="l", - }, - [0x19A1]={ - category="lo", - direction="l", - }, - [0x19A2]={ - category="lo", - direction="l", - }, - [0x19A3]={ - category="lo", - direction="l", - }, - [0x19A4]={ - category="lo", - direction="l", - }, - [0x19A5]={ - category="lo", - direction="l", - }, - [0x19A6]={ - category="lo", - direction="l", - }, - [0x19A7]={ - category="lo", - direction="l", - }, - [0x19A8]={ - category="lo", - direction="l", - }, - [0x19A9]={ - category="lo", - direction="l", - }, - [0x19AA]={ - category="lo", - direction="l", - }, - [0x19AB]={ - category="lo", - direction="l", - }, - [0x19B0]={ - category="mc", - direction="l", - }, - [0x19B1]={ - category="mc", - direction="l", - }, - [0x19B2]={ - category="mc", - direction="l", - }, - [0x19B3]={ - category="mc", - direction="l", - }, - [0x19B4]={ - category="mc", - direction="l", - }, - [0x19B5]={ - category="mc", - direction="l", - }, - [0x19B6]={ - category="mc", - direction="l", - }, - [0x19B7]={ - category="mc", - direction="l", - }, - [0x19B8]={ - category="mc", - direction="l", - }, - [0x19B9]={ - category="mc", - direction="l", - }, - [0x19BA]={ - category="mc", - direction="l", - }, - [0x19BB]={ - category="mc", - direction="l", - }, - [0x19BC]={ - category="mc", - direction="l", - }, - [0x19BD]={ - category="mc", - direction="l", - }, - [0x19BE]={ - category="mc", - direction="l", - }, - [0x19BF]={ - category="mc", - direction="l", - }, - [0x19C0]={ - category="mc", - direction="l", - }, - [0x19C1]={ - category="lo", - direction="l", - }, - [0x19C2]={ - category="lo", - direction="l", - }, - [0x19C3]={ - category="lo", - direction="l", - }, - [0x19C4]={ - category="lo", - direction="l", - }, - [0x19C5]={ - category="lo", - direction="l", - }, - [0x19C6]={ - category="lo", - direction="l", - }, - [0x19C7]={ - category="lo", - direction="l", - }, - [0x19C8]={ - category="mc", - direction="l", - }, - [0x19C9]={ - category="mc", - direction="l", - }, - [0x19D0]={ - category="nd", - direction="l", - }, - [0x19D1]={ - category="nd", - direction="l", - }, - [0x19D2]={ - category="nd", - direction="l", - }, - [0x19D3]={ - category="nd", - direction="l", - }, - [0x19D4]={ - category="nd", - direction="l", - }, - [0x19D5]={ - category="nd", - direction="l", - }, - [0x19D6]={ - category="nd", - direction="l", - }, - [0x19D7]={ - category="nd", - direction="l", - }, - [0x19D8]={ - category="nd", - direction="l", - }, - [0x19D9]={ - category="nd", - direction="l", - }, - [0x19DA]={ - category="no", - direction="l", - }, - [0x19DE]={ - category="po", - direction="on", - }, - [0x19DF]={ - category="po", - direction="on", - }, - [0x19E0]={ - category="so", - direction="on", - }, - [0x19E1]={ - category="so", - direction="on", - }, - [0x19E2]={ - category="so", - direction="on", - }, - [0x19E3]={ - category="so", - direction="on", - }, - [0x19E4]={ - category="so", - direction="on", - }, - [0x19E5]={ - category="so", - direction="on", - }, - [0x19E6]={ - category="so", - direction="on", - }, - [0x19E7]={ - category="so", - direction="on", - }, - [0x19E8]={ - category="so", - direction="on", - }, - [0x19E9]={ - category="so", - direction="on", - }, - [0x19EA]={ - category="so", - direction="on", - }, - [0x19EB]={ - category="so", - direction="on", - }, - [0x19EC]={ - category="so", - direction="on", - }, - [0x19ED]={ - category="so", - direction="on", - }, - [0x19EE]={ - category="so", - direction="on", - }, - [0x19EF]={ - category="so", - direction="on", - }, - [0x19F0]={ - category="so", - direction="on", - }, - [0x19F1]={ - category="so", - direction="on", - }, - [0x19F2]={ - category="so", - direction="on", - }, - [0x19F3]={ - category="so", - direction="on", - }, - [0x19F4]={ - category="so", - direction="on", - }, - [0x19F5]={ - category="so", - direction="on", - }, - [0x19F6]={ - category="so", - direction="on", - }, - [0x19F7]={ - category="so", - direction="on", - }, - [0x19F8]={ - category="so", - direction="on", - }, - [0x19F9]={ - category="so", - direction="on", - }, - [0x19FA]={ - category="so", - direction="on", - }, - [0x19FB]={ - category="so", - direction="on", - }, - [0x19FC]={ - category="so", - direction="on", - }, - [0x19FD]={ - category="so", - direction="on", - }, - [0x19FE]={ - category="so", - direction="on", - }, - [0x19FF]={ - category="so", - direction="on", - }, - [0x1A00]={ - category="lo", - direction="l", - }, - [0x1A01]={ - category="lo", - direction="l", - }, - [0x1A02]={ - category="lo", - direction="l", - }, - [0x1A03]={ - category="lo", - direction="l", - }, - [0x1A04]={ - category="lo", - direction="l", - }, - [0x1A05]={ - category="lo", - direction="l", - }, - [0x1A06]={ - category="lo", - direction="l", - }, - [0x1A07]={ - category="lo", - direction="l", - }, - [0x1A08]={ - category="lo", - direction="l", - }, - [0x1A09]={ - category="lo", - direction="l", - }, - [0x1A0A]={ - category="lo", - direction="l", - }, - [0x1A0B]={ - category="lo", - direction="l", - }, - [0x1A0C]={ - category="lo", - direction="l", - }, - [0x1A0D]={ - category="lo", - direction="l", - }, - [0x1A0E]={ - category="lo", - direction="l", - }, - [0x1A0F]={ - category="lo", - direction="l", - }, - [0x1A10]={ - category="lo", - direction="l", - }, - [0x1A11]={ - category="lo", - direction="l", - }, - [0x1A12]={ - category="lo", - direction="l", - }, - [0x1A13]={ - category="lo", - direction="l", - }, - [0x1A14]={ - category="lo", - direction="l", - }, - [0x1A15]={ - category="lo", - direction="l", - }, - [0x1A16]={ - category="lo", - direction="l", - }, - [0x1A17]={ - category="mn", - direction="nsm", - }, - [0x1A18]={ - category="mn", - direction="nsm", - }, - [0x1A19]={ - category="mc", - direction="l", - }, - [0x1A1A]={ - category="mc", - direction="l", - }, - [0x1A1B]={ - category="mc", - direction="nsm", - }, - [0x1A1E]={ - category="po", - direction="l", - }, - [0x1A1F]={ - category="po", - direction="l", - }, - [0x1A20]={ - category="lo", - direction="l", - }, - [0x1A21]={ - category="lo", - direction="l", - }, - [0x1A22]={ - category="lo", - direction="l", - }, - [0x1A23]={ - category="lo", - direction="l", - }, - [0x1A24]={ - category="lo", - direction="l", - }, - [0x1A25]={ - category="lo", - direction="l", - }, - [0x1A26]={ - category="lo", - direction="l", - }, - [0x1A27]={ - category="lo", - direction="l", - }, - [0x1A28]={ - category="lo", - direction="l", - }, - [0x1A29]={ - category="lo", - direction="l", - }, - [0x1A2A]={ - category="lo", - direction="l", - }, - [0x1A2B]={ - category="lo", - direction="l", - }, - [0x1A2C]={ - category="lo", - direction="l", - }, - [0x1A2D]={ - category="lo", - direction="l", - }, - [0x1A2E]={ - category="lo", - direction="l", - }, - [0x1A2F]={ - category="lo", - direction="l", - }, - [0x1A30]={ - category="lo", - direction="l", - }, - [0x1A31]={ - category="lo", - direction="l", - }, - [0x1A32]={ - category="lo", - direction="l", - }, - [0x1A33]={ - category="lo", - direction="l", - }, - [0x1A34]={ - category="lo", - direction="l", - }, - [0x1A35]={ - category="lo", - direction="l", - }, - [0x1A36]={ - category="lo", - direction="l", - }, - [0x1A37]={ - category="lo", - direction="l", - }, - [0x1A38]={ - category="lo", - direction="l", - }, - [0x1A39]={ - category="lo", - direction="l", - }, - [0x1A3A]={ - category="lo", - direction="l", - }, - [0x1A3B]={ - category="lo", - direction="l", - }, - [0x1A3C]={ - category="lo", - direction="l", - }, - [0x1A3D]={ - category="lo", - direction="l", - }, - [0x1A3E]={ - category="lo", - direction="l", - }, - [0x1A3F]={ - category="lo", - direction="l", - }, - [0x1A40]={ - category="lo", - direction="l", - }, - [0x1A41]={ - category="lo", - direction="l", - }, - [0x1A42]={ - category="lo", - direction="l", - }, - [0x1A43]={ - category="lo", - direction="l", - }, - [0x1A44]={ - category="lo", - direction="l", - }, - [0x1A45]={ - category="lo", - direction="l", - }, - [0x1A46]={ - category="lo", - direction="l", - }, - [0x1A47]={ - category="lo", - direction="l", - }, - [0x1A48]={ - category="lo", - direction="l", - }, - [0x1A49]={ - category="lo", - direction="l", - }, - [0x1A4A]={ - category="lo", - direction="l", - }, - [0x1A4B]={ - category="lo", - direction="l", - }, - [0x1A4C]={ - category="lo", - direction="l", - }, - [0x1A4D]={ - category="lo", - direction="l", - }, - [0x1A4E]={ - category="lo", - direction="l", - }, - [0x1A4F]={ - category="lo", - direction="l", - }, - [0x1A50]={ - category="lo", - direction="l", - }, - [0x1A51]={ - category="lo", - direction="l", - }, - [0x1A52]={ - category="lo", - direction="l", - }, - [0x1A53]={ - category="lo", - direction="l", - }, - [0x1A54]={ - category="lo", - direction="l", - }, - [0x1A55]={ - category="mc", - direction="l", - }, - [0x1A56]={ - category="mn", - direction="nsm", - }, - [0x1A57]={ - category="mc", - direction="l", - }, - [0x1A58]={ - category="mn", - direction="nsm", - }, - [0x1A59]={ - category="mn", - direction="nsm", - }, - [0x1A5A]={ - category="mn", - direction="nsm", - }, - [0x1A5B]={ - category="mn", - direction="nsm", - }, - [0x1A5C]={ - category="mn", - direction="nsm", - }, - [0x1A5D]={ - category="mn", - direction="nsm", - }, - [0x1A5E]={ - category="mn", - direction="nsm", - }, - [0x1A60]={ - category="mn", - direction="nsm", - }, - [0x1A61]={ - category="mc", - direction="l", - }, - [0x1A62]={ - category="mn", - direction="nsm", - }, - [0x1A63]={ - category="mc", - direction="l", - }, - [0x1A64]={ - category="mc", - direction="l", - }, - [0x1A65]={ - category="mn", - direction="nsm", - }, - [0x1A66]={ - category="mn", - direction="nsm", - }, - [0x1A67]={ - category="mn", - direction="nsm", - }, - [0x1A68]={ - category="mn", - direction="nsm", - }, - [0x1A69]={ - category="mn", - direction="nsm", - }, - [0x1A6A]={ - category="mn", - direction="nsm", - }, - [0x1A6B]={ - category="mn", - direction="nsm", - }, - [0x1A6C]={ - category="mn", - direction="nsm", - }, - [0x1A6D]={ - category="mc", - direction="l", - }, - [0x1A6E]={ - category="mc", - direction="l", - }, - [0x1A6F]={ - category="mc", - direction="l", - }, - [0x1A70]={ - category="mc", - direction="l", - }, - [0x1A71]={ - category="mc", - direction="l", - }, - [0x1A72]={ - category="mc", - direction="l", - }, - [0x1A73]={ - category="mn", - direction="nsm", - }, - [0x1A74]={ - category="mn", - direction="nsm", - }, - [0x1A75]={ - category="mn", - direction="nsm", - }, - [0x1A76]={ - category="mn", - direction="nsm", - }, - [0x1A77]={ - category="mn", - direction="nsm", - }, - [0x1A78]={ - category="mn", - direction="nsm", - }, - [0x1A79]={ - category="mn", - direction="nsm", - }, - [0x1A7A]={ - category="mn", - direction="nsm", - }, - [0x1A7B]={ - category="mn", - direction="nsm", - }, - [0x1A7C]={ - category="mn", - direction="nsm", - }, - [0x1A7F]={ - category="mn", - direction="nsm", - }, - [0x1A80]={ - category="nd", - direction="l", - }, - [0x1A81]={ - category="nd", - direction="l", - }, - [0x1A82]={ - category="nd", - direction="l", - }, - [0x1A83]={ - category="nd", - direction="l", - }, - [0x1A84]={ - category="nd", - direction="l", - }, - [0x1A85]={ - category="nd", - direction="l", - }, - [0x1A86]={ - category="nd", - direction="l", - }, - [0x1A87]={ - category="nd", - direction="l", - }, - [0x1A88]={ - category="nd", - direction="l", - }, - [0x1A89]={ - category="nd", - direction="l", - }, - [0x1A90]={ - category="nd", - direction="l", - }, - [0x1A91]={ - category="nd", - direction="l", - }, - [0x1A92]={ - category="nd", - direction="l", - }, - [0x1A93]={ - category="nd", - direction="l", - }, - [0x1A94]={ - category="nd", - direction="l", - }, - [0x1A95]={ - category="nd", - direction="l", - }, - [0x1A96]={ - category="nd", - direction="l", - }, - [0x1A97]={ - category="nd", - direction="l", - }, - [0x1A98]={ - category="nd", - direction="l", - }, - [0x1A99]={ - category="nd", - direction="l", - }, - [0x1AA0]={ - category="po", - direction="l", - }, - [0x1AA1]={ - category="po", - direction="l", - }, - [0x1AA2]={ - category="po", - direction="l", - }, - [0x1AA3]={ - category="po", - direction="l", - }, - [0x1AA4]={ - category="po", - direction="l", - }, - [0x1AA5]={ - category="po", - direction="l", - }, - [0x1AA6]={ - category="po", - direction="l", - }, - [0x1AA7]={ - category="lm", - direction="l", - }, - [0x1AA8]={ - category="po", - direction="l", - }, - [0x1AA9]={ - category="po", - direction="l", - }, - [0x1AAA]={ - category="po", - direction="l", - }, - [0x1AAB]={ - category="po", - direction="l", - }, - [0x1AAC]={ - category="po", - direction="l", - }, - [0x1AAD]={ - category="po", - direction="l", - }, - [0x1AB0]={ - category="mn", - direction="nsm", - }, - [0x1AB1]={ - category="mn", - direction="nsm", - }, - [0x1AB2]={ - category="mn", - direction="nsm", - }, - [0x1AB3]={ - category="mn", - direction="nsm", - }, - [0x1AB4]={ - category="mn", - direction="nsm", - }, - [0x1AB5]={ - category="mn", - direction="nsm", - }, - [0x1AB6]={ - category="mn", - direction="nsm", - }, - [0x1AB7]={ - category="mn", - direction="nsm", - }, - [0x1AB8]={ - category="mn", - direction="nsm", - }, - [0x1AB9]={ - category="mn", - direction="nsm", - }, - [0x1ABA]={ - category="mn", - direction="nsm", - }, - [0x1ABB]={ - category="mn", - direction="nsm", - }, - [0x1ABC]={ - category="mn", - direction="nsm", - }, - [0x1ABD]={ - category="mn", - direction="nsm", - }, - [0x1ABE]={ - category="me", - direction="nsm", - }, - [0x1B00]={ - category="mn", - direction="nsm", - }, - [0x1B01]={ - category="mn", - direction="nsm", - }, - [0x1B02]={ - category="mn", - direction="nsm", - }, - [0x1B03]={ - category="mn", - direction="nsm", - }, - [0x1B04]={ - category="mc", - direction="l", - }, - [0x1B05]={ - category="lo", - direction="l", - }, - [0x1B06]={ - category="lo", - direction="l", - }, - [0x1B07]={ - category="lo", - direction="l", - }, - [0x1B08]={ - category="lo", - direction="l", - }, - [0x1B09]={ - category="lo", - direction="l", - }, - [0x1B0A]={ - category="lo", - direction="l", - }, - [0x1B0B]={ - category="lo", - direction="l", - }, - [0x1B0C]={ - category="lo", - direction="l", - }, - [0x1B0D]={ - category="lo", - direction="l", - }, - [0x1B0E]={ - category="lo", - direction="l", - }, - [0x1B0F]={ - category="lo", - direction="l", - }, - [0x1B10]={ - category="lo", - direction="l", - }, - [0x1B11]={ - category="lo", - direction="l", - }, - [0x1B12]={ - category="lo", - direction="l", - }, - [0x1B13]={ - category="lo", - direction="l", - }, - [0x1B14]={ - category="lo", - direction="l", - }, - [0x1B15]={ - category="lo", - direction="l", - }, - [0x1B16]={ - category="lo", - direction="l", - }, - [0x1B17]={ - category="lo", - direction="l", - }, - [0x1B18]={ - category="lo", - direction="l", - }, - [0x1B19]={ - category="lo", - direction="l", - }, - [0x1B1A]={ - category="lo", - direction="l", - }, - [0x1B1B]={ - category="lo", - direction="l", - }, - [0x1B1C]={ - category="lo", - direction="l", - }, - [0x1B1D]={ - category="lo", - direction="l", - }, - [0x1B1E]={ - category="lo", - direction="l", - }, - [0x1B1F]={ - category="lo", - direction="l", - }, - [0x1B20]={ - category="lo", - direction="l", - }, - [0x1B21]={ - category="lo", - direction="l", - }, - [0x1B22]={ - category="lo", - direction="l", - }, - [0x1B23]={ - category="lo", - direction="l", - }, - [0x1B24]={ - category="lo", - direction="l", - }, - [0x1B25]={ - category="lo", - direction="l", - }, - [0x1B26]={ - category="lo", - direction="l", - }, - [0x1B27]={ - category="lo", - direction="l", - }, - [0x1B28]={ - category="lo", - direction="l", - }, - [0x1B29]={ - category="lo", - direction="l", - }, - [0x1B2A]={ - category="lo", - direction="l", - }, - [0x1B2B]={ - category="lo", - direction="l", - }, - [0x1B2C]={ - category="lo", - direction="l", - }, - [0x1B2D]={ - category="lo", - direction="l", - }, - [0x1B2E]={ - category="lo", - direction="l", - }, - [0x1B2F]={ - category="lo", - direction="l", - }, - [0x1B30]={ - category="lo", - direction="l", - }, - [0x1B31]={ - category="lo", - direction="l", - }, - [0x1B32]={ - category="lo", - direction="l", - }, - [0x1B33]={ - category="lo", - direction="l", - }, - [0x1B34]={ - category="mn", - direction="nsm", - }, - [0x1B35]={ - category="mc", - direction="l", - }, - [0x1B36]={ - category="mn", - direction="nsm", - }, - [0x1B37]={ - category="mn", - direction="nsm", - }, - [0x1B38]={ - category="mn", - direction="nsm", - }, - [0x1B39]={ - category="mn", - direction="nsm", - }, - [0x1B3A]={ - category="mn", - direction="nsm", - }, - [0x1B3B]={ - category="mc", - direction="l", - }, - [0x1B3C]={ - category="mn", - direction="nsm", - }, - [0x1B3D]={ - category="mc", - direction="l", - }, - [0x1B3E]={ - category="mc", - direction="l", - }, - [0x1B3F]={ - category="mc", - direction="l", - }, - [0x1B40]={ - category="mc", - direction="l", - }, - [0x1B41]={ - category="mc", - direction="l", - }, - [0x1B42]={ - category="mn", - direction="nsm", - }, - [0x1B43]={ - category="mc", - direction="l", - }, - [0x1B44]={ - category="mc", - direction="l", - }, - [0x1B45]={ - category="lo", - direction="l", - }, - [0x1B46]={ - category="lo", - direction="l", - }, - [0x1B47]={ - category="lo", - direction="l", - }, - [0x1B48]={ - category="lo", - direction="l", - }, - [0x1B49]={ - category="lo", - direction="l", - }, - [0x1B4A]={ - category="lo", - direction="l", - }, - [0x1B4B]={ - category="lo", - direction="l", - }, - [0x1B50]={ - category="nd", - direction="l", - }, - [0x1B51]={ - category="nd", - direction="l", - }, - [0x1B52]={ - category="nd", - direction="l", - }, - [0x1B53]={ - category="nd", - direction="l", - }, - [0x1B54]={ - category="nd", - direction="l", - }, - [0x1B55]={ - category="nd", - direction="l", - }, - [0x1B56]={ - category="nd", - direction="l", - }, - [0x1B57]={ - category="nd", - direction="l", - }, - [0x1B58]={ - category="nd", - direction="l", - }, - [0x1B59]={ - category="nd", - direction="l", - }, - [0x1B5A]={ - category="po", - direction="l", - }, - [0x1B5B]={ - category="po", - direction="l", - }, - [0x1B5C]={ - category="po", - direction="l", - }, - [0x1B5D]={ - category="po", - direction="l", - }, - [0x1B5E]={ - category="po", - direction="l", - }, - [0x1B5F]={ - category="po", - direction="l", - }, - [0x1B60]={ - category="po", - direction="l", - }, - [0x1B61]={ - category="so", - direction="l", - }, - [0x1B62]={ - category="so", - direction="l", - }, - [0x1B63]={ - category="so", - direction="l", - }, - [0x1B64]={ - category="so", - direction="l", - }, - [0x1B65]={ - category="so", - direction="l", - }, - [0x1B66]={ - category="so", - direction="l", - }, - [0x1B67]={ - category="so", - direction="l", - }, - [0x1B68]={ - category="so", - direction="l", - }, - [0x1B69]={ - category="so", - direction="l", - }, - [0x1B6A]={ - category="so", - direction="l", - }, - [0x1B6B]={ - category="mn", - direction="nsm", - }, - [0x1B6C]={ - category="mn", - direction="nsm", - }, - [0x1B6D]={ - category="mn", - direction="nsm", - }, - [0x1B6E]={ - category="mn", - direction="nsm", - }, - [0x1B6F]={ - category="mn", - direction="nsm", - }, - [0x1B70]={ - category="mn", - direction="nsm", - }, - [0x1B71]={ - category="mn", - direction="nsm", - }, - [0x1B72]={ - category="mn", - direction="nsm", - }, - [0x1B73]={ - category="mn", - direction="nsm", - }, - [0x1B74]={ - category="so", - direction="l", - }, - [0x1B75]={ - category="so", - direction="l", - }, - [0x1B76]={ - category="so", - direction="l", - }, - [0x1B77]={ - category="so", - direction="l", - }, - [0x1B78]={ - category="so", - direction="l", - }, - [0x1B79]={ - category="so", - direction="l", - }, - [0x1B7A]={ - category="so", - direction="l", - }, - [0x1B7B]={ - category="so", - direction="l", - }, - [0x1B7C]={ - category="so", - direction="l", - }, - [0x1B80]={ - category="mn", - direction="nsm", - }, - [0x1B81]={ - category="mn", - direction="nsm", - }, - [0x1B82]={ - category="mc", - direction="l", - }, - [0x1B83]={ - category="lo", - direction="l", - }, - [0x1B84]={ - category="lo", - direction="l", - }, - [0x1B85]={ - category="lo", - direction="l", - }, - [0x1B86]={ - category="lo", - direction="l", - }, - [0x1B87]={ - category="lo", - direction="l", - }, - [0x1B88]={ - category="lo", - direction="l", - }, - [0x1B89]={ - category="lo", - direction="l", - }, - [0x1B8A]={ - category="lo", - direction="l", - }, - [0x1B8B]={ - category="lo", - direction="l", - }, - [0x1B8C]={ - category="lo", - direction="l", - }, - [0x1B8D]={ - category="lo", - direction="l", - }, - [0x1B8E]={ - category="lo", - direction="l", - }, - [0x1B8F]={ - category="lo", - direction="l", - }, - [0x1B90]={ - category="lo", - direction="l", - }, - [0x1B91]={ - category="lo", - direction="l", - }, - [0x1B92]={ - category="lo", - direction="l", - }, - [0x1B93]={ - category="lo", - direction="l", - }, - [0x1B94]={ - category="lo", - direction="l", - }, - [0x1B95]={ - category="lo", - direction="l", - }, - [0x1B96]={ - category="lo", - direction="l", - }, - [0x1B97]={ - category="lo", - direction="l", - }, - [0x1B98]={ - category="lo", - direction="l", - }, - [0x1B99]={ - category="lo", - direction="l", - }, - [0x1B9A]={ - category="lo", - direction="l", - }, - [0x1B9B]={ - category="lo", - direction="l", - }, - [0x1B9C]={ - category="lo", - direction="l", - }, - [0x1B9D]={ - category="lo", - direction="l", - }, - [0x1B9E]={ - category="lo", - direction="l", - }, - [0x1B9F]={ - category="lo", - direction="l", - }, - [0x1BA0]={ - category="lo", - direction="l", - }, - [0x1BA1]={ - category="mc", - direction="l", - }, - [0x1BA2]={ - category="mn", - direction="nsm", - }, - [0x1BA3]={ - category="mn", - direction="nsm", - }, - [0x1BA4]={ - category="mn", - direction="nsm", - }, - [0x1BA5]={ - category="mn", - direction="nsm", - }, - [0x1BA6]={ - category="mc", - direction="l", - }, - [0x1BA7]={ - category="mc", - direction="l", - }, - [0x1BA8]={ - category="mn", - direction="nsm", - }, - [0x1BA9]={ - category="mn", - direction="nsm", - }, - [0x1BAA]={ - category="mc", - direction="l", - }, - [0x1BAB]={ - category="mn", - direction="nsm", - }, - [0x1BAC]={ - category="mc", - direction="nsm", - }, - [0x1BAD]={ - category="mc", - direction="nsm", - }, - [0x1BAE]={ - category="lo", - direction="l", - }, - [0x1BAF]={ - category="lo", - direction="l", - }, - [0x1BB0]={ - category="nd", - direction="l", - }, - [0x1BB1]={ - category="nd", - direction="l", - }, - [0x1BB2]={ - category="nd", - direction="l", - }, - [0x1BB3]={ - category="nd", - direction="l", - }, - [0x1BB4]={ - category="nd", - direction="l", - }, - [0x1BB5]={ - category="nd", - direction="l", - }, - [0x1BB6]={ - category="nd", - direction="l", - }, - [0x1BB7]={ - category="nd", - direction="l", - }, - [0x1BB8]={ - category="nd", - direction="l", - }, - [0x1BB9]={ - category="nd", - direction="l", - }, - [0x1BBA]={ - category="lo", - direction="l", - }, - [0x1BBB]={ - category="lo", - direction="l", - }, - [0x1BBC]={ - category="lo", - direction="l", - }, - [0x1BBD]={ - category="lo", - direction="l", - }, - [0x1BBE]={ - category="lo", - direction="l", - }, - [0x1BBF]={ - category="lo", - direction="l", - }, - [0x1BC0]={ - category="lo", - direction="l", - }, - [0x1BC1]={ - category="lo", - direction="l", - }, - [0x1BC2]={ - category="lo", - direction="l", - }, - [0x1BC3]={ - category="lo", - direction="l", - }, - [0x1BC4]={ - category="lo", - direction="l", - }, - [0x1BC5]={ - category="lo", - direction="l", - }, - [0x1BC6]={ - category="lo", - direction="l", - }, - [0x1BC7]={ - category="lo", - direction="l", - }, - [0x1BC8]={ - category="lo", - direction="l", - }, - [0x1BC9]={ - category="lo", - direction="l", - }, - [0x1BCA]={ - category="lo", - direction="l", - }, - [0x1BCB]={ - category="lo", - direction="l", - }, - [0x1BCC]={ - category="lo", - direction="l", - }, - [0x1BCD]={ - category="lo", - direction="l", - }, - [0x1BCE]={ - category="lo", - direction="l", - }, - [0x1BCF]={ - category="lo", - direction="l", - }, - [0x1BD0]={ - category="lo", - direction="l", - }, - [0x1BD1]={ - category="lo", - direction="l", - }, - [0x1BD2]={ - category="lo", - direction="l", - }, - [0x1BD3]={ - category="lo", - direction="l", - }, - [0x1BD4]={ - category="lo", - direction="l", - }, - [0x1BD5]={ - category="lo", - direction="l", - }, - [0x1BD6]={ - category="lo", - direction="l", - }, - [0x1BD7]={ - category="lo", - direction="l", - }, - [0x1BD8]={ - category="lo", - direction="l", - }, - [0x1BD9]={ - category="lo", - direction="l", - }, - [0x1BDA]={ - category="lo", - direction="l", - }, - [0x1BDB]={ - category="lo", - direction="l", - }, - [0x1BDC]={ - category="lo", - direction="l", - }, - [0x1BDD]={ - category="lo", - direction="l", - }, - [0x1BDE]={ - category="lo", - direction="l", - }, - [0x1BDF]={ - category="lo", - direction="l", - }, - [0x1BE0]={ - category="lo", - direction="l", - }, - [0x1BE1]={ - category="lo", - direction="l", - }, - [0x1BE2]={ - category="lo", - direction="l", - }, - [0x1BE3]={ - category="lo", - direction="l", - }, - [0x1BE4]={ - category="lo", - direction="l", - }, - [0x1BE5]={ - category="lo", - direction="l", - }, - [0x1BE6]={ - category="mn", - direction="nsm", - }, - [0x1BE7]={ - category="mc", - direction="l", - }, - [0x1BE8]={ - category="mn", - direction="nsm", - }, - [0x1BE9]={ - category="mn", - direction="nsm", - }, - [0x1BEA]={ - category="mc", - direction="l", - }, - [0x1BEB]={ - category="mc", - direction="l", - }, - [0x1BEC]={ - category="mc", - direction="l", - }, - [0x1BED]={ - category="mn", - direction="nsm", - }, - [0x1BEE]={ - category="mc", - direction="l", - }, - [0x1BEF]={ - category="mn", - direction="nsm", - }, - [0x1BF0]={ - category="mn", - direction="nsm", - }, - [0x1BF1]={ - category="mn", - direction="nsm", - }, - [0x1BF2]={ - category="mc", - direction="l", - }, - [0x1BF3]={ - category="mc", - direction="l", - }, - [0x1BFC]={ - category="po", - direction="l", - }, - [0x1BFD]={ - category="po", - direction="l", - }, - [0x1BFE]={ - category="po", - direction="l", - }, - [0x1BFF]={ - category="po", - direction="l", - }, - [0x1C00]={ - category="lo", - direction="l", - }, - [0x1C01]={ - category="lo", - direction="l", - }, - [0x1C02]={ - category="lo", - direction="l", - }, - [0x1C03]={ - category="lo", - direction="l", - }, - [0x1C04]={ - category="lo", - direction="l", - }, - [0x1C05]={ - category="lo", - direction="l", - }, - [0x1C06]={ - category="lo", - direction="l", - }, - [0x1C07]={ - category="lo", - direction="l", - }, - [0x1C08]={ - category="lo", - direction="l", - }, - [0x1C09]={ - category="lo", - direction="l", - }, - [0x1C0A]={ - category="lo", - direction="l", - }, - [0x1C0B]={ - category="lo", - direction="l", - }, - [0x1C0C]={ - category="lo", - direction="l", - }, - [0x1C0D]={ - category="lo", - direction="l", - }, - [0x1C0E]={ - category="lo", - direction="l", - }, - [0x1C0F]={ - category="lo", - direction="l", - }, - [0x1C10]={ - category="lo", - direction="l", - }, - [0x1C11]={ - category="lo", - direction="l", - }, - [0x1C12]={ - category="lo", - direction="l", - }, - [0x1C13]={ - category="lo", - direction="l", - }, - [0x1C14]={ - category="lo", - direction="l", - }, - [0x1C15]={ - category="lo", - direction="l", - }, - [0x1C16]={ - category="lo", - direction="l", - }, - [0x1C17]={ - category="lo", - direction="l", - }, - [0x1C18]={ - category="lo", - direction="l", - }, - [0x1C19]={ - category="lo", - direction="l", - }, - [0x1C1A]={ - category="lo", - direction="l", - }, - [0x1C1B]={ - category="lo", - direction="l", - }, - [0x1C1C]={ - category="lo", - direction="l", - }, - [0x1C1D]={ - category="lo", - direction="l", - }, - [0x1C1E]={ - category="lo", - direction="l", - }, - [0x1C1F]={ - category="lo", - direction="l", - }, - [0x1C20]={ - category="lo", - direction="l", - }, - [0x1C21]={ - category="lo", - direction="l", - }, - [0x1C22]={ - category="lo", - direction="l", - }, - [0x1C23]={ - category="lo", - direction="l", - }, - [0x1C24]={ - category="mc", - direction="l", - }, - [0x1C25]={ - category="mc", - direction="l", - }, - [0x1C26]={ - category="mc", - direction="l", - }, - [0x1C27]={ - category="mc", - direction="l", - }, - [0x1C28]={ - category="mc", - direction="l", - }, - [0x1C29]={ - category="mc", - direction="l", - }, - [0x1C2A]={ - category="mc", - direction="l", - }, - [0x1C2B]={ - category="mc", - direction="l", - }, - [0x1C2C]={ - category="mn", - direction="nsm", - }, - [0x1C2D]={ - category="mn", - direction="nsm", - }, - [0x1C2E]={ - category="mn", - direction="nsm", - }, - [0x1C2F]={ - category="mn", - direction="nsm", - }, - [0x1C30]={ - category="mn", - direction="nsm", - }, - [0x1C31]={ - category="mn", - direction="nsm", - }, - [0x1C32]={ - category="mn", - direction="nsm", - }, - [0x1C33]={ - category="mn", - direction="nsm", - }, - [0x1C34]={ - category="mc", - direction="l", - }, - [0x1C35]={ - category="mc", - direction="l", - }, - [0x1C36]={ - category="mn", - direction="nsm", - }, - [0x1C37]={ - category="mn", - direction="nsm", - }, - [0x1C3B]={ - category="po", - direction="l", - }, - [0x1C3C]={ - category="po", - direction="l", - }, - [0x1C3D]={ - category="po", - direction="l", - }, - [0x1C3E]={ - category="po", - direction="l", - }, - [0x1C3F]={ - category="po", - direction="l", - }, - [0x1C40]={ - category="nd", - direction="l", - }, - [0x1C41]={ - category="nd", - direction="l", - }, - [0x1C42]={ - category="nd", - direction="l", - }, - [0x1C43]={ - category="nd", - direction="l", - }, - [0x1C44]={ - category="nd", - direction="l", - }, - [0x1C45]={ - category="nd", - direction="l", - }, - [0x1C46]={ - category="nd", - direction="l", - }, - [0x1C47]={ - category="nd", - direction="l", - }, - [0x1C48]={ - category="nd", - direction="l", - }, - [0x1C49]={ - category="nd", - direction="l", - }, - [0x1C4D]={ - category="lo", - direction="l", - }, - [0x1C4E]={ - category="lo", - direction="l", - }, - [0x1C4F]={ - category="lo", - direction="l", - }, - [0x1C50]={ - category="nd", - direction="l", - }, - [0x1C51]={ - category="nd", - direction="l", - }, - [0x1C52]={ - category="nd", - direction="l", - }, - [0x1C53]={ - category="nd", - direction="l", - }, - [0x1C54]={ - category="nd", - direction="l", - }, - [0x1C55]={ - category="nd", - direction="l", - }, - [0x1C56]={ - category="nd", - direction="l", - }, - [0x1C57]={ - category="nd", - direction="l", - }, - [0x1C58]={ - category="nd", - direction="l", - }, - [0x1C59]={ - category="nd", - direction="l", - }, - [0x1C5A]={ - category="lo", - direction="l", - }, - [0x1C5B]={ - category="lo", - direction="l", - }, - [0x1C5C]={ - category="lo", - direction="l", - }, - [0x1C5D]={ - category="lo", - direction="l", - }, - [0x1C5E]={ - category="lo", - direction="l", - }, - [0x1C5F]={ - category="lo", - direction="l", - }, - [0x1C60]={ - category="lo", - direction="l", - }, - [0x1C61]={ - category="lo", - direction="l", - }, - [0x1C62]={ - category="lo", - direction="l", - }, - [0x1C63]={ - category="lo", - direction="l", - }, - [0x1C64]={ - category="lo", - direction="l", - }, - [0x1C65]={ - category="lo", - direction="l", - }, - [0x1C66]={ - category="lo", - direction="l", - }, - [0x1C67]={ - category="lo", - direction="l", - }, - [0x1C68]={ - category="lo", - direction="l", - }, - [0x1C69]={ - category="lo", - direction="l", - }, - [0x1C6A]={ - category="lo", - direction="l", - }, - [0x1C6B]={ - category="lo", - direction="l", - }, - [0x1C6C]={ - category="lo", - direction="l", - }, - [0x1C6D]={ - category="lo", - direction="l", - }, - [0x1C6E]={ - category="lo", - direction="l", - }, - [0x1C6F]={ - category="lo", - direction="l", - }, - [0x1C70]={ - category="lo", - direction="l", - }, - [0x1C71]={ - category="lo", - direction="l", - }, - [0x1C72]={ - category="lo", - direction="l", - }, - [0x1C73]={ - category="lo", - direction="l", - }, - [0x1C74]={ - category="lo", - direction="l", - }, - [0x1C75]={ - category="lo", - direction="l", - }, - [0x1C76]={ - category="lo", - direction="l", - }, - [0x1C77]={ - category="lo", - direction="l", - }, - [0x1C78]={ - category="lm", - direction="l", - }, - [0x1C79]={ - category="lm", - direction="l", - }, - [0x1C7A]={ - category="lm", - direction="l", - }, - [0x1C7B]={ - category="lm", - direction="l", - }, - [0x1C7C]={ - category="lm", - direction="l", - }, - [0x1C7D]={ - category="lm", - direction="l", - }, - [0x1C7E]={ - category="po", - direction="l", - }, - [0x1C7F]={ - category="po", - direction="l", - }, - [0x1C80]={ - category="ll", - direction="l", - }, - [0x1C81]={ - category="ll", - direction="l", - }, - [0x1C82]={ - category="ll", - direction="l", - }, - [0x1C83]={ - category="ll", - direction="l", - }, - [0x1C84]={ - category="ll", - direction="l", - }, - [0x1C85]={ - category="ll", - direction="l", - }, - [0x1C86]={ - category="ll", - direction="l", - }, - [0x1C87]={ - category="ll", - direction="l", - }, - [0x1C88]={ - category="ll", - direction="l", - }, - [0x1CC0]={ - category="po", - direction="l", - }, - [0x1CC1]={ - category="po", - direction="l", - }, - [0x1CC2]={ - category="po", - direction="l", - }, - [0x1CC3]={ - category="po", - direction="l", - }, - [0x1CC4]={ - category="po", - direction="l", - }, - [0x1CC5]={ - category="po", - direction="l", - }, - [0x1CC6]={ - category="po", - direction="l", - }, - [0x1CC7]={ - category="po", - direction="l", - }, - [0x1CD0]={ - category="mn", - direction="nsm", - }, - [0x1CD1]={ - category="mn", - direction="nsm", - }, - [0x1CD2]={ - category="mn", - direction="nsm", - }, - [0x1CD3]={ - category="po", - direction="l", - }, - [0x1CD4]={ - category="mn", - direction="nsm", - }, - [0x1CD5]={ - category="mn", - direction="nsm", - }, - [0x1CD6]={ - category="mn", - direction="nsm", - }, - [0x1CD7]={ - category="mn", - direction="nsm", - }, - [0x1CD8]={ - category="mn", - direction="nsm", - }, - [0x1CD9]={ - category="mn", - direction="nsm", - }, - [0x1CDA]={ - category="mn", - direction="nsm", - }, - [0x1CDB]={ - category="mn", - direction="nsm", - }, - [0x1CDC]={ - category="mn", - direction="nsm", - }, - [0x1CDD]={ - category="mn", - direction="nsm", - }, - [0x1CDE]={ - category="mn", - direction="nsm", - }, - [0x1CDF]={ - category="mn", - direction="nsm", - }, - [0x1CE0]={ - category="mn", - direction="nsm", - }, - [0x1CE1]={ - category="mc", - direction="l", - }, - [0x1CE2]={ - category="mn", - direction="nsm", - }, - [0x1CE3]={ - category="mn", - direction="nsm", - }, - [0x1CE4]={ - category="mn", - direction="nsm", - }, - [0x1CE5]={ - category="mn", - direction="nsm", - }, - [0x1CE6]={ - category="mn", - direction="nsm", - }, - [0x1CE7]={ - category="mn", - direction="nsm", - }, - [0x1CE8]={ - category="mn", - direction="nsm", - }, - [0x1CE9]={ - category="lo", - direction="l", - }, - [0x1CEA]={ - category="lo", - direction="l", - }, - [0x1CEB]={ - category="lo", - direction="l", - }, - [0x1CEC]={ - category="lo", - direction="l", - }, - [0x1CED]={ - category="mn", - direction="nsm", - }, - [0x1CEE]={ - category="lo", - direction="l", - }, - [0x1CEF]={ - category="lo", - direction="l", - }, - [0x1CF0]={ - category="lo", - direction="l", - }, - [0x1CF1]={ - category="lo", - direction="l", - }, - [0x1CF2]={ - category="mc", - direction="l", - }, - [0x1CF3]={ - category="mc", - direction="l", - }, - [0x1CF4]={ - category="mn", - direction="nsm", - }, - [0x1CF5]={ - category="lo", - direction="l", - }, - [0x1CF6]={ - category="lo", - direction="l", - }, - [0x1CF8]={ - category="mn", - direction="nsm", - }, - [0x1CF9]={ - category="mn", - direction="nsm", - }, - [0x1D00]={ - category="ll", - direction="l", - }, - [0x1D01]={ - category="ll", - direction="l", - }, - [0x1D02]={ - category="ll", - direction="l", - }, - [0x1D03]={ - category="ll", - direction="l", - }, - [0x1D04]={ - category="ll", - direction="l", - }, - [0x1D05]={ - category="ll", - direction="l", - }, - [0x1D06]={ - category="ll", - direction="l", - }, - [0x1D07]={ - category="ll", - direction="l", - }, - [0x1D08]={ - category="ll", - direction="l", - }, - [0x1D09]={ - category="ll", - direction="l", - }, - [0x1D0A]={ - category="ll", - direction="l", - }, - [0x1D0B]={ - category="ll", - direction="l", - }, - [0x1D0C]={ - category="ll", - direction="l", - }, - [0x1D0D]={ - category="ll", - direction="l", - }, - [0x1D0E]={ - category="ll", - direction="l", - }, - [0x1D0F]={ - category="ll", - direction="l", - }, - [0x1D10]={ - category="ll", - direction="l", - }, - [0x1D11]={ - category="ll", - direction="l", - }, - [0x1D12]={ - category="ll", - direction="l", - }, - [0x1D13]={ - category="ll", - direction="l", - }, - [0x1D14]={ - category="ll", - direction="l", - }, - [0x1D15]={ - category="ll", - direction="l", - }, - [0x1D16]={ - category="ll", - direction="l", - }, - [0x1D17]={ - category="ll", - direction="l", - }, - [0x1D18]={ - category="ll", - direction="l", - }, - [0x1D19]={ - category="ll", - direction="l", - }, - [0x1D1A]={ - category="ll", - direction="l", - }, - [0x1D1B]={ - category="ll", - direction="l", - }, - [0x1D1C]={ - category="ll", - direction="l", - }, - [0x1D1D]={ - category="ll", - direction="l", - }, - [0x1D1E]={ - category="ll", - direction="l", - }, - [0x1D1F]={ - category="ll", - direction="l", - }, - [0x1D20]={ - category="ll", - direction="l", - }, - [0x1D21]={ - category="ll", - direction="l", - }, - [0x1D22]={ - category="ll", - direction="l", - }, - [0x1D23]={ - category="ll", - direction="l", - }, - [0x1D24]={ - category="ll", - direction="l", - }, - [0x1D25]={ - category="ll", - direction="l", - }, - [0x1D26]={ - category="ll", - direction="l", - }, - [0x1D27]={ - category="ll", - direction="l", - }, - [0x1D28]={ - category="ll", - direction="l", - }, - [0x1D29]={ - category="ll", - direction="l", - }, - [0x1D2A]={ - category="ll", - direction="l", - }, - [0x1D2B]={ - category="ll", - direction="l", - }, - [0x1D2C]={ - category="lm", - direction="l", - }, - [0x1D2D]={ - category="lm", - direction="l", - }, - [0x1D2E]={ - category="lm", - direction="l", - }, - [0x1D2F]={ - category="lm", - direction="l", - }, - [0x1D30]={ - category="lm", - direction="l", - }, - [0x1D31]={ - category="lm", - direction="l", - }, - [0x1D32]={ - category="lm", - direction="l", - }, - [0x1D33]={ - category="lm", - direction="l", - }, - [0x1D34]={ - category="lm", - direction="l", - }, - [0x1D35]={ - category="lm", - direction="l", - }, - [0x1D36]={ - category="lm", - direction="l", - }, - [0x1D37]={ - category="lm", - direction="l", - }, - [0x1D38]={ - category="lm", - direction="l", - }, - [0x1D39]={ - category="lm", - direction="l", - }, - [0x1D3A]={ - category="lm", - direction="l", - }, - [0x1D3B]={ - category="lm", - direction="l", - }, - [0x1D3C]={ - category="lm", - direction="l", - }, - [0x1D3D]={ - category="lm", - direction="l", - }, - [0x1D3E]={ - category="lm", - direction="l", - }, - [0x1D3F]={ - category="lm", - direction="l", - }, - [0x1D40]={ - category="lm", - direction="l", - }, - [0x1D41]={ - category="lm", - direction="l", - }, - [0x1D42]={ - category="lm", - direction="l", - }, - [0x1D43]={ - category="lm", - direction="l", - }, - [0x1D44]={ - category="lm", - direction="l", - }, - [0x1D45]={ - category="lm", - direction="l", - }, - [0x1D46]={ - category="lm", - direction="l", - }, - [0x1D47]={ - category="lm", - direction="l", - }, - [0x1D48]={ - category="lm", - direction="l", - }, - [0x1D49]={ - category="lm", - direction="l", - }, - [0x1D4A]={ - category="lm", - direction="l", - }, - [0x1D4B]={ - category="lm", - direction="l", - }, - [0x1D4C]={ - category="lm", - direction="l", - }, - [0x1D4D]={ - category="lm", - direction="l", - }, - [0x1D4E]={ - category="lm", - direction="l", - }, - [0x1D4F]={ - category="lm", - direction="l", - }, - [0x1D50]={ - category="lm", - direction="l", - }, - [0x1D51]={ - category="lm", - direction="l", - }, - [0x1D52]={ - category="lm", - direction="l", - }, - [0x1D53]={ - category="lm", - direction="l", - }, - [0x1D54]={ - category="lm", - direction="l", - }, - [0x1D55]={ - category="lm", - direction="l", - }, - [0x1D56]={ - category="lm", - direction="l", - }, - [0x1D57]={ - category="lm", - direction="l", - }, - [0x1D58]={ - category="lm", - direction="l", - }, - [0x1D59]={ - category="lm", - direction="l", - }, - [0x1D5A]={ - category="lm", - direction="l", - }, - [0x1D5B]={ - category="lm", - direction="l", - }, - [0x1D5C]={ - category="lm", - direction="l", - }, - [0x1D5D]={ - category="lm", - direction="l", - }, - [0x1D5E]={ - category="lm", - direction="l", - }, - [0x1D5F]={ - category="lm", - direction="l", - }, - [0x1D60]={ - category="lm", - direction="l", - }, - [0x1D61]={ - category="lm", - direction="l", - }, - [0x1D62]={ - category="ll", - direction="l", - }, - [0x1D63]={ - category="ll", - direction="l", - }, - [0x1D64]={ - category="ll", - direction="l", - }, - [0x1D65]={ - category="ll", - direction="l", - }, - [0x1D66]={ - category="ll", - direction="l", - }, - [0x1D67]={ - category="ll", - direction="l", - }, - [0x1D68]={ - category="ll", - direction="l", - }, - [0x1D69]={ - category="ll", - direction="l", - }, - [0x1D6A]={ - category="ll", - direction="l", - }, - [0x1D6B]={ - category="ll", - direction="l", - }, - [0x1D6C]={ - category="ll", - direction="l", - }, - [0x1D6D]={ - category="ll", - direction="l", - }, - [0x1D6E]={ - category="ll", - direction="l", - }, - [0x1D6F]={ - category="ll", - direction="l", - }, - [0x1D70]={ - category="ll", - direction="l", - }, - [0x1D71]={ - category="ll", - direction="l", - }, - [0x1D72]={ - category="ll", - direction="l", - }, - [0x1D73]={ - category="ll", - direction="l", - }, - [0x1D74]={ - category="ll", - direction="l", - }, - [0x1D75]={ - category="ll", - direction="l", - }, - [0x1D76]={ - category="ll", - direction="l", - }, - [0x1D77]={ - category="ll", - direction="l", - }, - [0x1D78]={ - category="lm", - direction="l", - }, - [0x1D79]={ - category="ll", - direction="l", - }, - [0x1D7A]={ - category="ll", - direction="l", - }, - [0x1D7B]={ - category="ll", - direction="l", - }, - [0x1D7C]={ - category="ll", - direction="l", - }, - [0x1D7D]={ - category="ll", - direction="l", - }, - [0x1D7E]={ - category="ll", - direction="l", - }, - [0x1D7F]={ - category="ll", - direction="l", - }, - [0x1D80]={ - category="ll", - direction="l", - }, - [0x1D81]={ - category="ll", - direction="l", - }, - [0x1D82]={ - category="ll", - direction="l", - }, - [0x1D83]={ - category="ll", - direction="l", - }, - [0x1D84]={ - category="ll", - direction="l", - }, - [0x1D85]={ - category="ll", - direction="l", - }, - [0x1D86]={ - category="ll", - direction="l", - }, - [0x1D87]={ - category="ll", - direction="l", - }, - [0x1D88]={ - category="ll", - direction="l", - }, - [0x1D89]={ - category="ll", - direction="l", - }, - [0x1D8A]={ - category="ll", - direction="l", - }, - [0x1D8B]={ - category="ll", - direction="l", - }, - [0x1D8C]={ - category="ll", - direction="l", - }, - [0x1D8D]={ - category="ll", - direction="l", - }, - [0x1D8E]={ - category="ll", - direction="l", - }, - [0x1D8F]={ - category="ll", - direction="l", - }, - [0x1D90]={ - category="ll", - direction="l", - }, - [0x1D91]={ - category="ll", - direction="l", - }, - [0x1D92]={ - category="ll", - direction="l", - }, - [0x1D93]={ - category="ll", - direction="l", - }, - [0x1D94]={ - category="ll", - direction="l", - }, - [0x1D95]={ - category="ll", - direction="l", - }, - [0x1D96]={ - category="ll", - direction="l", - }, - [0x1D97]={ - category="ll", - direction="l", - }, - [0x1D98]={ - category="ll", - direction="l", - }, - [0x1D99]={ - category="ll", - direction="l", - }, - [0x1D9A]={ - category="ll", - direction="l", - }, - [0x1D9B]={ - category="lm", - direction="l", - }, - [0x1D9C]={ - category="lm", - direction="l", - }, - [0x1D9D]={ - category="lm", - direction="l", - }, - [0x1D9E]={ - category="lm", - direction="l", - }, - [0x1D9F]={ - category="lm", - direction="l", - }, - [0x1DA0]={ - category="lm", - direction="l", - }, - [0x1DA1]={ - category="lm", - direction="l", - }, - [0x1DA2]={ - category="lm", - direction="l", - }, - [0x1DA3]={ - category="lm", - direction="l", - }, - [0x1DA4]={ - category="lm", - direction="l", - }, - [0x1DA5]={ - category="lm", - direction="l", - }, - [0x1DA6]={ - category="lm", - direction="l", - }, - [0x1DA7]={ - category="lm", - direction="l", - }, - [0x1DA8]={ - category="lm", - direction="l", - }, - [0x1DA9]={ - category="lm", - direction="l", - }, - [0x1DAA]={ - category="lm", - direction="l", - }, - [0x1DAB]={ - category="lm", - direction="l", - }, - [0x1DAC]={ - category="lm", - direction="l", - }, - [0x1DAD]={ - category="lm", - direction="l", - }, - [0x1DAE]={ - category="lm", - direction="l", - }, - [0x1DAF]={ - category="lm", - direction="l", - }, - [0x1DB0]={ - category="lm", - direction="l", - }, - [0x1DB1]={ - category="lm", - direction="l", - }, - [0x1DB2]={ - category="lm", - direction="l", - }, - [0x1DB3]={ - category="lm", - direction="l", - }, - [0x1DB4]={ - category="lm", - direction="l", - }, - [0x1DB5]={ - category="lm", - direction="l", - }, - [0x1DB6]={ - category="lm", - direction="l", - }, - [0x1DB7]={ - category="lm", - direction="l", - }, - [0x1DB8]={ - category="lm", - direction="l", - }, - [0x1DB9]={ - category="lm", - direction="l", - }, - [0x1DBA]={ - category="lm", - direction="l", - }, - [0x1DBB]={ - category="lm", - direction="l", - }, - [0x1DBC]={ - category="lm", - direction="l", - }, - [0x1DBD]={ - category="lm", - direction="l", - }, - [0x1DBE]={ - category="lm", - direction="l", - }, - [0x1DBF]={ - category="lm", - direction="l", - }, - [0x1DC0]={ - category="mn", - direction="nsm", - }, - [0x1DC1]={ - category="mn", - direction="nsm", - }, - [0x1DC2]={ - category="mn", - direction="nsm", - }, - [0x1DC3]={ - category="mn", - direction="nsm", - }, - [0x1DC4]={ - category="mn", - direction="nsm", - }, - [0x1DC5]={ - category="mn", - direction="nsm", - }, - [0x1DC6]={ - category="mn", - direction="nsm", - }, - [0x1DC7]={ - category="mn", - direction="nsm", - }, - [0x1DC8]={ - category="mn", - direction="nsm", - }, - [0x1DC9]={ - category="mn", - direction="nsm", - }, - [0x1DCA]={ - category="mn", - direction="nsm", - }, - [0x1DCB]={ - category="mn", - direction="nsm", - }, - [0x1DCC]={ - category="mn", - direction="nsm", - }, - [0x1DCD]={ - category="mn", - direction="nsm", - }, - [0x1DCE]={ - category="mn", - direction="nsm", - }, - [0x1DCF]={ - category="mn", - direction="nsm", - }, - [0x1DD0]={ - category="mn", - direction="nsm", - }, - [0x1DD1]={ - category="mn", - direction="nsm", - }, - [0x1DD2]={ - category="mn", - direction="nsm", - }, - [0x1DD3]={ - category="mn", - direction="nsm", - }, - [0x1DD4]={ - category="mn", - direction="nsm", - }, - [0x1DD5]={ - category="mn", - direction="nsm", - }, - [0x1DD6]={ - category="mn", - direction="nsm", - }, - [0x1DD7]={ - category="mn", - direction="nsm", - }, - [0x1DD8]={ - category="mn", - direction="nsm", - }, - [0x1DD9]={ - category="mn", - direction="nsm", - }, - [0x1DDA]={ - category="mn", - direction="nsm", - }, - [0x1DDB]={ - category="mn", - direction="nsm", - }, - [0x1DDC]={ - category="mn", - direction="nsm", - }, - [0x1DDD]={ - category="mn", - direction="nsm", - }, - [0x1DDE]={ - category="mn", - direction="nsm", - }, - [0x1DDF]={ - category="mn", - direction="nsm", - }, - [0x1DE0]={ - category="mn", - direction="nsm", - }, - [0x1DE1]={ - category="mn", - direction="nsm", - }, - [0x1DE2]={ - category="mn", - direction="nsm", - }, - [0x1DE3]={ - category="mn", - direction="nsm", - }, - [0x1DE4]={ - category="mn", - direction="nsm", - }, - [0x1DE5]={ - category="mn", - direction="nsm", - }, - [0x1DE6]={ - category="mn", - direction="nsm", - }, - [0x1DE7]={ - category="mn", - direction="nsm", - }, - [0x1DE8]={ - category="mn", - direction="nsm", - }, - [0x1DE9]={ - category="mn", - direction="nsm", - }, - [0x1DEA]={ - category="mn", - direction="nsm", - }, - [0x1DEB]={ - category="mn", - direction="nsm", - }, - [0x1DEC]={ - category="mn", - direction="nsm", - }, - [0x1DED]={ - category="mn", - direction="nsm", - }, - [0x1DEE]={ - category="mn", - direction="nsm", - }, - [0x1DEF]={ - category="mn", - direction="nsm", - }, - [0x1DF0]={ - category="mn", - direction="nsm", - }, - [0x1DF1]={ - category="mn", - direction="nsm", - }, - [0x1DF2]={ - category="mn", - direction="nsm", - }, - [0x1DF3]={ - category="mn", - direction="nsm", - }, - [0x1DF4]={ - category="mn", - direction="nsm", - }, - [0x1DF5]={ - category="mn", - direction="nsm", - }, - [0x1DFB]={ - category="mn", - direction="nsm", - }, - [0x1DFC]={ - category="mn", - direction="nsm", - }, - [0x1DFD]={ - category="mn", - direction="nsm", - }, - [0x1DFE]={ - category="mn", - direction="nsm", - }, - [0x1DFF]={ - category="mn", - direction="nsm", - }, - [0x1E00]={ - category="lu", - direction="l", - }, - [0x1E01]={ - category="ll", - direction="l", - }, - [0x1E02]={ - category="lu", - direction="l", - }, - [0x1E03]={ - category="ll", - direction="l", - }, - [0x1E04]={ - category="lu", - direction="l", - }, - [0x1E05]={ - category="ll", - direction="l", - }, - [0x1E06]={ - category="lu", - direction="l", - }, - [0x1E07]={ - category="ll", - direction="l", - }, - [0x1E08]={ - category="lu", - direction="l", - }, - [0x1E09]={ - category="ll", - direction="l", - }, - [0x1E0A]={ - category="lu", - direction="l", - }, - [0x1E0B]={ - category="ll", - direction="l", - }, - [0x1E0C]={ - category="lu", - direction="l", - }, - [0x1E0D]={ - category="ll", - direction="l", - }, - [0x1E0E]={ - category="lu", - direction="l", - }, - [0x1E0F]={ - category="ll", - direction="l", - }, - [0x1E10]={ - category="lu", - direction="l", - }, - [0x1E11]={ - category="ll", - direction="l", - }, - [0x1E12]={ - category="lu", - direction="l", - }, - [0x1E13]={ - category="ll", - direction="l", - }, - [0x1E14]={ - category="lu", - direction="l", - }, - [0x1E15]={ - category="ll", - direction="l", - }, - [0x1E16]={ - category="lu", - direction="l", - }, - [0x1E17]={ - category="ll", - direction="l", - }, - [0x1E18]={ - category="lu", - direction="l", - }, - [0x1E19]={ - category="ll", - direction="l", - }, - [0x1E1A]={ - category="lu", - direction="l", - }, - [0x1E1B]={ - category="ll", - direction="l", - }, - [0x1E1C]={ - category="lu", - direction="l", - }, - [0x1E1D]={ - category="ll", - direction="l", - }, - [0x1E1E]={ - category="lu", - direction="l", - }, - [0x1E1F]={ - category="ll", - direction="l", - }, - [0x1E20]={ - category="lu", - direction="l", - }, - [0x1E21]={ - category="ll", - direction="l", - }, - [0x1E22]={ - category="lu", - direction="l", - }, - [0x1E23]={ - category="ll", - direction="l", - }, - [0x1E24]={ - category="lu", - direction="l", - }, - [0x1E25]={ - category="ll", - direction="l", - }, - [0x1E26]={ - category="lu", - direction="l", - }, - [0x1E27]={ - category="ll", - direction="l", - }, - [0x1E28]={ - category="lu", - direction="l", - }, - [0x1E29]={ - category="ll", - direction="l", - }, - [0x1E2A]={ - category="lu", - direction="l", - }, - [0x1E2B]={ - category="ll", - direction="l", - }, - [0x1E2C]={ - category="lu", - direction="l", - }, - [0x1E2D]={ - category="ll", - direction="l", - }, - [0x1E2E]={ - category="lu", - direction="l", - }, - [0x1E2F]={ - category="ll", - direction="l", - }, - [0x1E30]={ - category="lu", - direction="l", - }, - [0x1E31]={ - category="ll", - direction="l", - }, - [0x1E32]={ - category="lu", - direction="l", - }, - [0x1E33]={ - category="ll", - direction="l", - }, - [0x1E34]={ - category="lu", - direction="l", - }, - [0x1E35]={ - category="ll", - direction="l", - }, - [0x1E36]={ - category="lu", - direction="l", - }, - [0x1E37]={ - category="ll", - direction="l", - }, - [0x1E38]={ - category="lu", - direction="l", - }, - [0x1E39]={ - category="ll", - direction="l", - }, - [0x1E3A]={ - category="lu", - direction="l", - }, - [0x1E3B]={ - category="ll", - direction="l", - }, - [0x1E3C]={ - category="lu", - direction="l", - }, - [0x1E3D]={ - category="ll", - direction="l", - }, - [0x1E3E]={ - category="lu", - direction="l", - }, - [0x1E3F]={ - category="ll", - direction="l", - }, - [0x1E40]={ - category="lu", - direction="l", - }, - [0x1E41]={ - category="ll", - direction="l", - }, - [0x1E42]={ - category="lu", - direction="l", - }, - [0x1E43]={ - category="ll", - direction="l", - }, - [0x1E44]={ - category="lu", - direction="l", - }, - [0x1E45]={ - category="ll", - direction="l", - }, - [0x1E46]={ - category="lu", - direction="l", - }, - [0x1E47]={ - category="ll", - direction="l", - }, - [0x1E48]={ - category="lu", - direction="l", - }, - [0x1E49]={ - category="ll", - direction="l", - }, - [0x1E4A]={ - category="lu", - direction="l", - }, - [0x1E4B]={ - category="ll", - direction="l", - }, - [0x1E4C]={ - category="lu", - direction="l", - }, - [0x1E4D]={ - category="ll", - direction="l", - }, - [0x1E4E]={ - category="lu", - direction="l", - }, - [0x1E4F]={ - category="ll", - direction="l", - }, - [0x1E50]={ - category="lu", - direction="l", - }, - [0x1E51]={ - category="ll", - direction="l", - }, - [0x1E52]={ - category="lu", - direction="l", - }, - [0x1E53]={ - category="ll", - direction="l", - }, - [0x1E54]={ - category="lu", - direction="l", - }, - [0x1E55]={ - category="ll", - direction="l", - }, - [0x1E56]={ - category="lu", - direction="l", - }, - [0x1E57]={ - category="ll", - direction="l", - }, - [0x1E58]={ - category="lu", - direction="l", - }, - [0x1E59]={ - category="ll", - direction="l", - }, - [0x1E5A]={ - category="lu", - direction="l", - }, - [0x1E5B]={ - category="ll", - direction="l", - }, - [0x1E5C]={ - category="lu", - direction="l", - }, - [0x1E5D]={ - category="ll", - direction="l", - }, - [0x1E5E]={ - category="lu", - direction="l", - }, - [0x1E5F]={ - category="ll", - direction="l", - }, - [0x1E60]={ - category="lu", - direction="l", - }, - [0x1E61]={ - category="ll", - direction="l", - }, - [0x1E62]={ - category="lu", - direction="l", - }, - [0x1E63]={ - category="ll", - direction="l", - }, - [0x1E64]={ - category="lu", - direction="l", - }, - [0x1E65]={ - category="ll", - direction="l", - }, - [0x1E66]={ - category="lu", - direction="l", - }, - [0x1E67]={ - category="ll", - direction="l", - }, - [0x1E68]={ - category="lu", - direction="l", - }, - [0x1E69]={ - category="ll", - direction="l", - }, - [0x1E6A]={ - category="lu", - direction="l", - }, - [0x1E6B]={ - category="ll", - direction="l", - }, - [0x1E6C]={ - category="lu", - direction="l", - }, - [0x1E6D]={ - category="ll", - direction="l", - }, - [0x1E6E]={ - category="lu", - direction="l", - }, - [0x1E6F]={ - category="ll", - direction="l", - }, - [0x1E70]={ - category="lu", - direction="l", - }, - [0x1E71]={ - category="ll", - direction="l", - }, - [0x1E72]={ - category="lu", - direction="l", - }, - [0x1E73]={ - category="ll", - direction="l", - }, - [0x1E74]={ - category="lu", - direction="l", - }, - [0x1E75]={ - category="ll", - direction="l", - }, - [0x1E76]={ - category="lu", - direction="l", - }, - [0x1E77]={ - category="ll", - direction="l", - }, - [0x1E78]={ - category="lu", - direction="l", - }, - [0x1E79]={ - category="ll", - direction="l", - }, - [0x1E7A]={ - category="lu", - direction="l", - }, - [0x1E7B]={ - category="ll", - direction="l", - }, - [0x1E7C]={ - category="lu", - direction="l", - }, - [0x1E7D]={ - category="ll", - direction="l", - }, - [0x1E7E]={ - category="lu", - direction="l", - }, - [0x1E7F]={ - category="ll", - direction="l", - }, - [0x1E80]={ - category="lu", - direction="l", - }, - [0x1E81]={ - category="ll", - direction="l", - }, - [0x1E82]={ - category="lu", - direction="l", - }, - [0x1E83]={ - category="ll", - direction="l", - }, - [0x1E84]={ - category="lu", - direction="l", - }, - [0x1E85]={ - category="ll", - direction="l", - }, - [0x1E86]={ - category="lu", - direction="l", - }, - [0x1E87]={ - category="ll", - direction="l", - }, - [0x1E88]={ - category="lu", - direction="l", - }, - [0x1E89]={ - category="ll", - direction="l", - }, - [0x1E8A]={ - category="lu", - direction="l", - }, - [0x1E8B]={ - category="ll", - direction="l", - }, - [0x1E8C]={ - category="lu", - direction="l", - }, - [0x1E8D]={ - category="ll", - direction="l", - }, - [0x1E8E]={ - category="lu", - direction="l", - }, - [0x1E8F]={ - category="ll", - direction="l", - }, - [0x1E90]={ - category="lu", - direction="l", - }, - [0x1E91]={ - category="ll", - direction="l", - }, - [0x1E92]={ - category="lu", - direction="l", - }, - [0x1E93]={ - category="ll", - direction="l", - }, - [0x1E94]={ - category="lu", - direction="l", - }, - [0x1E95]={ - category="ll", - direction="l", - }, - [0x1E96]={ - category="ll", - direction="l", - }, - [0x1E97]={ - category="ll", - direction="l", - }, - [0x1E98]={ - category="ll", - direction="l", - }, - [0x1E99]={ - category="ll", - direction="l", - }, - [0x1E9A]={ - category="ll", - direction="l", - }, - [0x1E9B]={ - category="ll", - direction="l", - }, - [0x1E9C]={ - category="ll", - direction="l", - }, - [0x1E9D]={ - category="ll", - direction="l", - }, - [0x1E9E]={ - category="lu", - direction="l", - }, - [0x1E9F]={ - category="ll", - direction="l", - }, - [0x1EA0]={ - category="lu", - direction="l", - }, - [0x1EA1]={ - category="ll", - direction="l", - }, - [0x1EA2]={ - category="lu", - direction="l", - }, - [0x1EA3]={ - category="ll", - direction="l", - }, - [0x1EA4]={ - category="lu", - direction="l", - }, - [0x1EA5]={ - category="ll", - direction="l", - }, - [0x1EA6]={ - category="lu", - direction="l", - }, - [0x1EA7]={ - category="ll", - direction="l", - }, - [0x1EA8]={ - category="lu", - direction="l", - }, - [0x1EA9]={ - category="ll", - direction="l", - }, - [0x1EAA]={ - category="lu", - direction="l", - }, - [0x1EAB]={ - category="ll", - direction="l", - }, - [0x1EAC]={ - category="lu", - direction="l", - }, - [0x1EAD]={ - category="ll", - direction="l", - }, - [0x1EAE]={ - category="lu", - direction="l", - }, - [0x1EAF]={ - category="ll", - direction="l", - }, - [0x1EB0]={ - category="lu", - direction="l", - }, - [0x1EB1]={ - category="ll", - direction="l", - }, - [0x1EB2]={ - category="lu", - direction="l", - }, - [0x1EB3]={ - category="ll", - direction="l", - }, - [0x1EB4]={ - category="lu", - direction="l", - }, - [0x1EB5]={ - category="ll", - direction="l", - }, - [0x1EB6]={ - category="lu", - direction="l", - }, - [0x1EB7]={ - category="ll", - direction="l", - }, - [0x1EB8]={ - category="lu", - direction="l", - }, - [0x1EB9]={ - category="ll", - direction="l", - }, - [0x1EBA]={ - category="lu", - direction="l", - }, - [0x1EBB]={ - category="ll", - direction="l", - }, - [0x1EBC]={ - category="lu", - direction="l", - }, - [0x1EBD]={ - category="ll", - direction="l", - }, - [0x1EBE]={ - category="lu", - direction="l", - }, - [0x1EBF]={ - category="ll", - direction="l", - }, - [0x1EC0]={ - category="lu", - direction="l", - }, - [0x1EC1]={ - category="ll", - direction="l", - }, - [0x1EC2]={ - category="lu", - direction="l", - }, - [0x1EC3]={ - category="ll", - direction="l", - }, - [0x1EC4]={ - category="lu", - direction="l", - }, - [0x1EC5]={ - category="ll", - direction="l", - }, - [0x1EC6]={ - category="lu", - direction="l", - }, - [0x1EC7]={ - category="ll", - direction="l", - }, - [0x1EC8]={ - category="lu", - direction="l", - }, - [0x1EC9]={ - category="ll", - direction="l", - }, - [0x1ECA]={ - category="lu", - direction="l", - }, - [0x1ECB]={ - category="ll", - direction="l", - }, - [0x1ECC]={ - category="lu", - direction="l", - }, - [0x1ECD]={ - category="ll", - direction="l", - }, - [0x1ECE]={ - category="lu", - direction="l", - }, - [0x1ECF]={ - category="ll", - direction="l", - }, - [0x1ED0]={ - category="lu", - direction="l", - }, - [0x1ED1]={ - category="ll", - direction="l", - }, - [0x1ED2]={ - category="lu", - direction="l", - }, - [0x1ED3]={ - category="ll", - direction="l", - }, - [0x1ED4]={ - category="lu", - direction="l", - }, - [0x1ED5]={ - category="ll", - direction="l", - }, - [0x1ED6]={ - category="lu", - direction="l", - }, - [0x1ED7]={ - category="ll", - direction="l", - }, - [0x1ED8]={ - category="lu", - direction="l", - }, - [0x1ED9]={ - category="ll", - direction="l", - }, - [0x1EDA]={ - category="lu", - direction="l", - }, - [0x1EDB]={ - category="ll", - direction="l", - }, - [0x1EDC]={ - category="lu", - direction="l", - }, - [0x1EDD]={ - category="ll", - direction="l", - }, - [0x1EDE]={ - category="lu", - direction="l", - }, - [0x1EDF]={ - category="ll", - direction="l", - }, - [0x1EE0]={ - category="lu", - direction="l", - }, - [0x1EE1]={ - category="ll", - direction="l", - }, - [0x1EE2]={ - category="lu", - direction="l", - }, - [0x1EE3]={ - category="ll", - direction="l", - }, - [0x1EE4]={ - category="lu", - direction="l", - }, - [0x1EE5]={ - category="ll", - direction="l", - }, - [0x1EE6]={ - category="lu", - direction="l", - }, - [0x1EE7]={ - category="ll", - direction="l", - }, - [0x1EE8]={ - category="lu", - direction="l", - }, - [0x1EE9]={ - category="ll", - direction="l", - }, - [0x1EEA]={ - category="lu", - direction="l", - }, - [0x1EEB]={ - category="ll", - direction="l", - }, - [0x1EEC]={ - category="lu", - direction="l", - }, - [0x1EED]={ - category="ll", - direction="l", - }, - [0x1EEE]={ - category="lu", - direction="l", - }, - [0x1EEF]={ - category="ll", - direction="l", - }, - [0x1EF0]={ - category="lu", - direction="l", - }, - [0x1EF1]={ - category="ll", - direction="l", - }, - [0x1EF2]={ - category="lu", - direction="l", - }, - [0x1EF3]={ - category="ll", - direction="l", - }, - [0x1EF4]={ - category="lu", - direction="l", - }, - [0x1EF5]={ - category="ll", - direction="l", - }, - [0x1EF6]={ - category="lu", - direction="l", - }, - [0x1EF7]={ - category="ll", - direction="l", - }, - [0x1EF8]={ - category="lu", - direction="l", - }, - [0x1EF9]={ - category="ll", - direction="l", - }, - [0x1EFA]={ - category="lu", - direction="l", - }, - [0x1EFB]={ - category="ll", - direction="l", - }, - [0x1EFC]={ - category="lu", - direction="l", - }, - [0x1EFD]={ - category="ll", - direction="l", - }, - [0x1EFE]={ - category="lu", - direction="l", - }, - [0x1EFF]={ - category="ll", - direction="l", - }, - [0x1F00]={ - category="ll", - direction="l", - }, - [0x1F01]={ - category="ll", - direction="l", - }, - [0x1F02]={ - category="ll", - direction="l", - }, - [0x1F03]={ - category="ll", - direction="l", - }, - [0x1F04]={ - category="ll", - direction="l", - }, - [0x1F05]={ - category="ll", - direction="l", - }, - [0x1F06]={ - category="ll", - direction="l", - }, - [0x1F07]={ - category="ll", - direction="l", - }, - [0x1F08]={ - category="lu", - direction="l", - }, - [0x1F09]={ - category="lu", - direction="l", - }, - [0x1F0A]={ - category="lu", - direction="l", - }, - [0x1F0B]={ - category="lu", - direction="l", - }, - [0x1F0C]={ - category="lu", - direction="l", - }, - [0x1F0D]={ - category="lu", - direction="l", - }, - [0x1F0E]={ - category="lu", - direction="l", - }, - [0x1F0F]={ - category="lu", - direction="l", - }, - [0x1F10]={ - category="ll", - direction="l", - }, - [0x1F11]={ - category="ll", - direction="l", - }, - [0x1F12]={ - category="ll", - direction="l", - }, - [0x1F13]={ - category="ll", - direction="l", - }, - [0x1F14]={ - category="ll", - direction="l", - }, - [0x1F15]={ - category="ll", - direction="l", - }, - [0x1F18]={ - category="lu", - direction="l", - }, - [0x1F19]={ - category="lu", - direction="l", - }, - [0x1F1A]={ - category="lu", - direction="l", - }, - [0x1F1B]={ - category="lu", - direction="l", - }, - [0x1F1C]={ - category="lu", - direction="l", - }, - [0x1F1D]={ - category="lu", - direction="l", - }, - [0x1F20]={ - category="ll", - direction="l", - }, - [0x1F21]={ - category="ll", - direction="l", - }, - [0x1F22]={ - category="ll", - direction="l", - }, - [0x1F23]={ - category="ll", - direction="l", - }, - [0x1F24]={ - category="ll", - direction="l", - }, - [0x1F25]={ - category="ll", - direction="l", - }, - [0x1F26]={ - category="ll", - direction="l", - }, - [0x1F27]={ - category="ll", - direction="l", - }, - [0x1F28]={ - category="lu", - direction="l", - }, - [0x1F29]={ - category="lu", - direction="l", - }, - [0x1F2A]={ - category="lu", - direction="l", - }, - [0x1F2B]={ - category="lu", - direction="l", - }, - [0x1F2C]={ - category="lu", - direction="l", - }, - [0x1F2D]={ - category="lu", - direction="l", - }, - [0x1F2E]={ - category="lu", - direction="l", - }, - [0x1F2F]={ - category="lu", - direction="l", - }, - [0x1F30]={ - category="ll", - direction="l", - }, - [0x1F31]={ - category="ll", - direction="l", - }, - [0x1F32]={ - category="ll", - direction="l", - }, - [0x1F33]={ - category="ll", - direction="l", - }, - [0x1F34]={ - category="ll", - direction="l", - }, - [0x1F35]={ - category="ll", - direction="l", - }, - [0x1F36]={ - category="ll", - direction="l", - }, - [0x1F37]={ - category="ll", - direction="l", - }, - [0x1F38]={ - category="lu", - direction="l", - }, - [0x1F39]={ - category="lu", - direction="l", - }, - [0x1F3A]={ - category="lu", - direction="l", - }, - [0x1F3B]={ - category="lu", - direction="l", - }, - [0x1F3C]={ - category="lu", - direction="l", - }, - [0x1F3D]={ - category="lu", - direction="l", - }, - [0x1F3E]={ - category="lu", - direction="l", - }, - [0x1F3F]={ - category="lu", - direction="l", - }, - [0x1F40]={ - category="ll", - direction="l", - }, - [0x1F41]={ - category="ll", - direction="l", - }, - [0x1F42]={ - category="ll", - direction="l", - }, - [0x1F43]={ - category="ll", - direction="l", - }, - [0x1F44]={ - category="ll", - direction="l", - }, - [0x1F45]={ - category="ll", - direction="l", - }, - [0x1F48]={ - category="lu", - direction="l", - }, - [0x1F49]={ - category="lu", - direction="l", - }, - [0x1F4A]={ - category="lu", - direction="l", - }, - [0x1F4B]={ - category="lu", - direction="l", - }, - [0x1F4C]={ - category="lu", - direction="l", - }, - [0x1F4D]={ - category="lu", - direction="l", - }, - [0x1F50]={ - category="ll", - direction="l", - }, - [0x1F51]={ - category="ll", - direction="l", - }, - [0x1F52]={ - category="ll", - direction="l", - }, - [0x1F53]={ - category="ll", - direction="l", - }, - [0x1F54]={ - category="ll", - direction="l", - }, - [0x1F55]={ - category="ll", - direction="l", - }, - [0x1F56]={ - category="ll", - direction="l", - }, - [0x1F57]={ - category="ll", - direction="l", - }, - [0x1F59]={ - category="lu", - direction="l", - }, - [0x1F5B]={ - category="lu", - direction="l", - }, - [0x1F5D]={ - category="lu", - direction="l", - }, - [0x1F5F]={ - category="lu", - direction="l", - }, - [0x1F60]={ - category="ll", - direction="l", - }, - [0x1F61]={ - category="ll", - direction="l", - }, - [0x1F62]={ - category="ll", - direction="l", - }, - [0x1F63]={ - category="ll", - direction="l", - }, - [0x1F64]={ - category="ll", - direction="l", - }, - [0x1F65]={ - category="ll", - direction="l", - }, - [0x1F66]={ - category="ll", - direction="l", - }, - [0x1F67]={ - category="ll", - direction="l", - }, - [0x1F68]={ - category="lu", - direction="l", - }, - [0x1F69]={ - category="lu", - direction="l", - }, - [0x1F6A]={ - category="lu", - direction="l", - }, - [0x1F6B]={ - category="lu", - direction="l", - }, - [0x1F6C]={ - category="lu", - direction="l", - }, - [0x1F6D]={ - category="lu", - direction="l", - }, - [0x1F6E]={ - category="lu", - direction="l", - }, - [0x1F6F]={ - category="lu", - direction="l", - }, - [0x1F70]={ - category="ll", - direction="l", - }, - [0x1F71]={ - category="ll", - direction="l", - }, - [0x1F72]={ - category="ll", - direction="l", - }, - [0x1F73]={ - category="ll", - direction="l", - }, - [0x1F74]={ - category="ll", - direction="l", - }, - [0x1F75]={ - category="ll", - direction="l", - }, - [0x1F76]={ - category="ll", - direction="l", - }, - [0x1F77]={ - category="ll", - direction="l", - }, - [0x1F78]={ - category="ll", - direction="l", - }, - [0x1F79]={ - category="ll", - direction="l", - }, - [0x1F7A]={ - category="ll", - direction="l", - }, - [0x1F7B]={ - category="ll", - direction="l", - }, - [0x1F7C]={ - category="ll", - direction="l", - }, - [0x1F7D]={ - category="ll", - direction="l", - }, - [0x1F80]={ - category="ll", - direction="l", - }, - [0x1F81]={ - category="ll", - direction="l", - }, - [0x1F82]={ - category="ll", - direction="l", - }, - [0x1F83]={ - category="ll", - direction="l", - }, - [0x1F84]={ - category="ll", - direction="l", - }, - [0x1F85]={ - category="ll", - direction="l", - }, - [0x1F86]={ - category="ll", - direction="l", - }, - [0x1F87]={ - category="ll", - direction="l", - }, - [0x1F88]={ - category="lt", - direction="l", - }, - [0x1F89]={ - category="lt", - direction="l", - }, - [0x1F8A]={ - category="lt", - direction="l", - }, - [0x1F8B]={ - category="lt", - direction="l", - }, - [0x1F8C]={ - category="lt", - direction="l", - }, - [0x1F8D]={ - category="lt", - direction="l", - }, - [0x1F8E]={ - category="lt", - direction="l", - }, - [0x1F8F]={ - category="lt", - direction="l", - }, - [0x1F90]={ - category="ll", - direction="l", - }, - [0x1F91]={ - category="ll", - direction="l", - }, - [0x1F92]={ - category="ll", - direction="l", - }, - [0x1F93]={ - category="ll", - direction="l", - }, - [0x1F94]={ - category="ll", - direction="l", - }, - [0x1F95]={ - category="ll", - direction="l", - }, - [0x1F96]={ - category="ll", - direction="l", - }, - [0x1F97]={ - category="ll", - direction="l", - }, - [0x1F98]={ - category="lt", - direction="l", - }, - [0x1F99]={ - category="lt", - direction="l", - }, - [0x1F9A]={ - category="lt", - direction="l", - }, - [0x1F9B]={ - category="lt", - direction="l", - }, - [0x1F9C]={ - category="lt", - direction="l", - }, - [0x1F9D]={ - category="lt", - direction="l", - }, - [0x1F9E]={ - category="lt", - direction="l", - }, - [0x1F9F]={ - category="lt", - direction="l", - }, - [0x1FA0]={ - category="ll", - direction="l", - }, - [0x1FA1]={ - category="ll", - direction="l", - }, - [0x1FA2]={ - category="ll", - direction="l", - }, - [0x1FA3]={ - category="ll", - direction="l", - }, - [0x1FA4]={ - category="ll", - direction="l", - }, - [0x1FA5]={ - category="ll", - direction="l", - }, - [0x1FA6]={ - category="ll", - direction="l", - }, - [0x1FA7]={ - category="ll", - direction="l", - }, - [0x1FA8]={ - category="lt", - direction="l", - }, - [0x1FA9]={ - category="lt", - direction="l", - }, - [0x1FAA]={ - category="lt", - direction="l", - }, - [0x1FAB]={ - category="lt", - direction="l", - }, - [0x1FAC]={ - category="lt", - direction="l", - }, - [0x1FAD]={ - category="lt", - direction="l", - }, - [0x1FAE]={ - category="lt", - direction="l", - }, - [0x1FAF]={ - category="lt", - direction="l", - }, - [0x1FB0]={ - category="ll", - direction="l", - }, - [0x1FB1]={ - category="ll", - direction="l", - }, - [0x1FB2]={ - category="ll", - direction="l", - }, - [0x1FB3]={ - category="ll", - direction="l", - }, - [0x1FB4]={ - category="ll", - direction="l", - }, - [0x1FB6]={ - category="ll", - direction="l", - }, - [0x1FB7]={ - category="ll", - direction="l", - }, - [0x1FB8]={ - category="lu", - direction="l", - }, - [0x1FB9]={ - category="lu", - direction="l", - }, - [0x1FBA]={ - category="lu", - direction="l", - }, - [0x1FBB]={ - category="lu", - direction="l", - }, - [0x1FBC]={ - category="lt", - direction="l", - }, - [0x1FBD]={ - category="sk", - direction="on", - }, - [0x1FBE]={ - category="ll", - direction="l", - }, - [0x1FBF]={ - category="sk", - direction="on", - }, - [0x1FC0]={ - category="sk", - direction="on", - }, - [0x1FC1]={ - category="sk", - direction="on", - }, - [0x1FC2]={ - category="ll", - direction="l", - }, - [0x1FC3]={ - category="ll", - direction="l", - }, - [0x1FC4]={ - category="ll", - direction="l", - }, - [0x1FC6]={ - category="ll", - direction="l", - }, - [0x1FC7]={ - category="ll", - direction="l", - }, - [0x1FC8]={ - category="lu", - direction="l", - }, - [0x1FC9]={ - category="lu", - direction="l", - }, - [0x1FCA]={ - category="lu", - direction="l", - }, - [0x1FCB]={ - category="lu", - direction="l", - }, - [0x1FCC]={ - category="lt", - direction="l", - }, - [0x1FCD]={ - category="sk", - direction="on", - }, - [0x1FCE]={ - category="sk", - direction="on", - }, - [0x1FCF]={ - category="sk", - direction="on", - }, - [0x1FD0]={ - category="ll", - direction="l", - }, - [0x1FD1]={ - category="ll", - direction="l", - }, - [0x1FD2]={ - category="ll", - direction="l", - }, - [0x1FD3]={ - category="ll", - direction="l", - }, - [0x1FD6]={ - category="ll", - direction="l", - }, - [0x1FD7]={ - category="ll", - direction="l", - }, - [0x1FD8]={ - category="lu", - direction="l", - }, - [0x1FD9]={ - category="lu", - direction="l", - }, - [0x1FDA]={ - category="lu", - direction="l", - }, - [0x1FDB]={ - category="lu", - direction="l", - }, - [0x1FDD]={ - category="sk", - direction="on", - }, - [0x1FDE]={ - category="sk", - direction="on", - }, - [0x1FDF]={ - category="sk", - direction="on", - }, - [0x1FE0]={ - category="ll", - direction="l", - }, - [0x1FE1]={ - category="ll", - direction="l", - }, - [0x1FE2]={ - category="ll", - direction="l", - }, - [0x1FE3]={ - category="ll", - direction="l", - }, - [0x1FE4]={ - category="ll", - direction="l", - }, - [0x1FE5]={ - category="ll", - direction="l", - }, - [0x1FE6]={ - category="ll", - direction="l", - }, - [0x1FE7]={ - category="ll", - direction="l", - }, - [0x1FE8]={ - category="lu", - direction="l", - }, - [0x1FE9]={ - category="lu", - direction="l", - }, - [0x1FEA]={ - category="lu", - direction="l", - }, - [0x1FEB]={ - category="lu", - direction="l", - }, - [0x1FEC]={ - category="lu", - direction="l", - }, - [0x1FED]={ - category="sk", - direction="on", - }, - [0x1FEE]={ - category="sk", - direction="on", - }, - [0x1FEF]={ - category="sk", - direction="on", - }, - [0x1FF2]={ - category="ll", - direction="l", - }, - [0x1FF3]={ - category="ll", - direction="l", - }, - [0x1FF4]={ - category="ll", - direction="l", - }, - [0x1FF6]={ - category="ll", - direction="l", - }, - [0x1FF7]={ - category="ll", - direction="l", - }, - [0x1FF8]={ - category="lu", - direction="l", - }, - [0x1FF9]={ - category="lu", - direction="l", - }, - [0x1FFA]={ - category="lu", - direction="l", - }, - [0x1FFB]={ - category="lu", - direction="l", - }, - [0x1FFC]={ - category="lt", - direction="l", - }, - [0x1FFD]={ - category="sk", - direction="on", - }, - [0x1FFE]={ - category="sk", - direction="on", - }, - [0x2000]={ - category="zs", - direction="ws", - }, - [0x2001]={ - category="zs", - direction="ws", - }, - [0x2002]={ - category="zs", - direction="ws", - }, - [0x2003]={ - category="zs", - direction="ws", - }, - [0x2004]={ - category="zs", - direction="ws", - }, - [0x2005]={ - category="zs", - direction="ws", - }, - [0x2006]={ - category="zs", - direction="ws", - }, - [0x2007]={ - category="zs", - direction="ws", - }, - [0x2008]={ - category="zs", - direction="ws", - }, - [0x2009]={ - category="zs", - direction="ws", - }, - [0x200A]={ - category="zs", - direction="ws", - }, - [0x200B]={ - category="cf", - direction="bn", - }, - [0x200C]={ - category="cf", - direction="bn", - }, - [0x200D]={ - category="cf", - direction="bn", - }, - [0x200E]={ - category="cf", - direction="l", - }, - [0x200F]={ - category="cf", - direction="r", - }, - [0x2010]={ - category="pd", - direction="on", - }, - [0x2011]={ - category="pd", - direction="on", - }, - [0x2012]={ - category="pd", - direction="on", - }, - [0x2013]={ - category="pd", - direction="on", - }, - [0x2014]={ - category="pd", - direction="on", - }, - [0x2015]={ - category="pd", - direction="on", - }, - [0x2016]={ - category="po", - direction="on", - }, - [0x2017]={ - category="po", - direction="on", - }, - [0x2018]={ - category="pi", - direction="on", - }, - [0x2019]={ - category="pf", - direction="on", - }, - [0x201A]={ - category="ps", - direction="on", - }, - [0x201B]={ - category="pi", - direction="on", - }, - [0x201C]={ - category="pi", - direction="on", - }, - [0x201D]={ - category="pf", - direction="on", - }, - [0x201E]={ - category="ps", - direction="on", - }, - [0x201F]={ - category="pi", - direction="on", - }, - [0x2020]={ - category="po", - direction="on", - }, - [0x2021]={ - category="po", - direction="on", - }, - [0x2022]={ - category="po", - direction="on", - }, - [0x2023]={ - category="po", - direction="on", - }, - [0x2024]={ - category="po", - direction="on", - }, - [0x2025]={ - category="po", - direction="on", - }, - [0x2026]={ - category="po", - direction="on", - }, - [0x2027]={ - category="po", - direction="on", - }, - [0x2028]={ - category="zl", - direction="ws", - }, - [0x2029]={ - category="zp", - direction="b", - }, - [0x202A]={ - category="cf", - direction="lre", - }, - [0x202B]={ - category="cf", - direction="rle", - }, - [0x202C]={ - category="cf", - direction="pdf", - }, - [0x202D]={ - category="cf", - direction="lro", - }, - [0x202E]={ - category="cf", - direction="rlo", - }, - [0x202F]={ - category="zs", - direction="cs", - }, - [0x2030]={ - category="po", - direction="et", - }, - [0x2031]={ - category="po", - direction="et", - }, - [0x2032]={ - category="po", - direction="et", - }, - [0x2033]={ - category="po", - direction="et", - }, - [0x2034]={ - category="po", - direction="et", - }, - [0x2035]={ - category="po", - direction="on", - }, - [0x2036]={ - category="po", - direction="on", - }, - [0x2037]={ - category="po", - direction="on", - }, - [0x2038]={ - category="po", - direction="on", - }, - [0x2039]={ - category="pi", - direction="on", - mirror=0x203A, - textclass="open", - }, - [0x203A]={ - category="pf", - direction="on", - mirror=0x2039, - textclass="close", - }, - [0x203B]={ - category="po", - direction="on", - }, - [0x203C]={ - category="po", - direction="on", - }, - [0x203D]={ - category="po", - direction="on", - }, - [0x203E]={ - category="po", - direction="on", - }, - [0x203F]={ - category="pc", - direction="on", - }, - [0x2040]={ - category="pc", - direction="on", - }, - [0x2041]={ - category="po", - direction="on", - }, - [0x2042]={ - category="po", - direction="on", - }, - [0x2043]={ - category="po", - direction="on", - }, - [0x2044]={ - category="sm", - direction="cs", - }, - [0x2045]={ - category="ps", - direction="on", - mirror=0x2046, - }, - [0x2046]={ - category="pe", - direction="on", - mirror=0x2045, - }, - [0x2047]={ - category="po", - direction="on", - }, - [0x2048]={ - category="po", - direction="on", - }, - [0x2049]={ - category="po", - direction="on", - }, - [0x204A]={ - category="po", - direction="on", - }, - [0x204B]={ - category="po", - direction="on", - }, - [0x204C]={ - category="po", - direction="on", - }, - [0x204D]={ - category="po", - direction="on", - }, - [0x204E]={ - category="po", - direction="on", - }, - [0x204F]={ - category="po", - direction="on", - }, - [0x2050]={ - category="po", - direction="on", - }, - [0x2051]={ - category="po", - direction="on", - }, - [0x2052]={ - category="sm", - direction="on", - }, - [0x2053]={ - category="po", - direction="on", - }, - [0x2054]={ - category="pc", - direction="on", - }, - [0x2055]={ - category="po", - direction="on", - }, - [0x2056]={ - category="po", - direction="on", - }, - [0x2057]={ - category="po", - direction="on", - }, - [0x2058]={ - category="po", - direction="on", - }, - [0x2059]={ - category="po", - direction="on", - }, - [0x205A]={ - category="po", - direction="on", - }, - [0x205B]={ - category="po", - direction="on", - }, - [0x205C]={ - category="po", - direction="on", - }, - [0x205D]={ - category="po", - direction="on", - }, - [0x205E]={ - category="po", - direction="on", - }, - [0x205F]={ - category="zs", - direction="ws", - }, - [0x2060]={ - category="cf", - direction="bn", - }, - [0x2061]={ - category="cf", - direction="bn", - }, - [0x2062]={ - category="cf", - direction="bn", - }, - [0x2063]={ - category="cf", - direction="bn", - }, - [0x2064]={ - category="cf", - direction="bn", - }, - [0x2066]={ - category="cf", - direction="lri", - }, - [0x2067]={ - category="cf", - direction="rli", - }, - [0x2068]={ - category="cf", - direction="fsi", - }, - [0x2069]={ - category="cf", - direction="pdi", - }, - [0x206A]={ - category="cf", - direction="bn", - }, - [0x206B]={ - category="cf", - direction="bn", - }, - [0x206C]={ - category="cf", - direction="bn", - }, - [0x206D]={ - category="cf", - direction="bn", - }, - [0x206E]={ - category="cf", - direction="bn", - }, - [0x206F]={ - category="cf", - direction="bn", - }, - [0x2070]={ - category="no", - direction="en", - }, - [0x2071]={ - category="ll", - direction="l", - }, - [0x2074]={ - category="no", - direction="en", - }, - [0x2075]={ - category="no", - direction="en", - }, - [0x2076]={ - category="no", - direction="en", - }, - [0x2077]={ - category="no", - direction="en", - }, - [0x2078]={ - category="no", - direction="en", - }, - [0x2079]={ - category="no", - direction="en", - }, - [0x207A]={ - category="sm", - direction="es", - }, - [0x207B]={ - category="sm", - direction="es", - }, - [0x207C]={ - category="sm", - direction="on", - }, - [0x207D]={ - category="ps", - direction="on", - mirror=0x207E, - textclass="open", - }, - [0x207E]={ - category="pe", - direction="on", - mirror=0x207D, - textclass="close", - }, - [0x207F]={ - category="ll", - direction="l", - }, - [0x2080]={ - category="no", - direction="en", - }, - [0x2081]={ - category="no", - direction="en", - }, - [0x2082]={ - category="no", - direction="en", - }, - [0x2083]={ - category="no", - direction="en", - }, - [0x2084]={ - category="no", - direction="en", - }, - [0x2085]={ - category="no", - direction="en", - }, - [0x2086]={ - category="no", - direction="en", - }, - [0x2087]={ - category="no", - direction="en", - }, - [0x2088]={ - category="no", - direction="en", - }, - [0x2089]={ - category="no", - direction="en", - }, - [0x208A]={ - category="sm", - direction="es", - }, - [0x208B]={ - category="sm", - direction="es", - }, - [0x208C]={ - category="sm", - direction="on", - }, - [0x208D]={ - category="ps", - direction="on", - mirror=0x208E, - textclass="open", - }, - [0x208E]={ - category="pe", - direction="on", - mirror=0x208D, - textclass="close", - }, - [0x2090]={ - category="lm", - direction="l", - }, - [0x2091]={ - category="lm", - direction="l", - }, - [0x2092]={ - category="lm", - direction="l", - }, - [0x2093]={ - category="lm", - direction="l", - }, - [0x2094]={ - category="lm", - direction="l", - }, - [0x2095]={ - category="lm", - direction="l", - }, - [0x2096]={ - category="lm", - direction="l", - }, - [0x2097]={ - category="lm", - direction="l", - }, - [0x2098]={ - category="lm", - direction="l", - }, - [0x2099]={ - category="lm", - direction="l", - }, - [0x209A]={ - category="lm", - direction="l", - }, - [0x209B]={ - category="lm", - direction="l", - }, - [0x209C]={ - category="lm", - direction="l", - }, - [0x20A0]={ - category="sc", - direction="et", - }, - [0x20A1]={ - category="sc", - direction="et", - }, - [0x20A2]={ - category="sc", - direction="et", - }, - [0x20A3]={ - category="sc", - direction="et", - }, - [0x20A4]={ - category="sc", - direction="et", - }, - [0x20A5]={ - category="sc", - direction="et", - }, - [0x20A6]={ - category="sc", - direction="et", - }, - [0x20A7]={ - category="sc", - direction="et", - }, - [0x20A8]={ - category="sc", - direction="et", - }, - [0x20A9]={ - category="sc", - direction="et", - }, - [0x20AA]={ - category="sc", - direction="et", - }, - [0x20AB]={ - category="sc", - direction="et", - }, - [0x20AC]={ - category="sc", - direction="et", - }, - [0x20AD]={ - category="sc", - direction="et", - }, - [0x20AE]={ - category="sc", - direction="et", - }, - [0x20AF]={ - category="sc", - direction="et", - }, - [0x20B0]={ - category="sc", - direction="et", - }, - [0x20B1]={ - category="sc", - direction="et", - }, - [0x20B2]={ - category="sc", - direction="et", - }, - [0x20B3]={ - category="sc", - direction="et", - }, - [0x20B4]={ - category="sc", - direction="et", - }, - [0x20B5]={ - category="sc", - direction="et", - }, - [0x20B6]={ - category="sc", - direction="et", - }, - [0x20B7]={ - category="sc", - direction="et", - }, - [0x20B8]={ - category="sc", - direction="et", - }, - [0x20B9]={ - category="sc", - direction="et", - }, - [0x20BA]={ - category="sc", - direction="et", - }, - [0x20BB]={ - category="sc", - direction="et", - }, - [0x20BC]={ - category="sc", - direction="et", - }, - [0x20BD]={ - category="sc", - direction="et", - }, - [0x20BE]={ - category="sc", - direction="et", - }, - [0x20D0]={ - category="mn", - direction="nsm", - }, - [0x20D1]={ - category="mn", - direction="nsm", - }, - [0x20D2]={ - category="mn", - direction="nsm", - }, - [0x20D3]={ - category="mn", - direction="nsm", - }, - [0x20D4]={ - category="mn", - direction="nsm", - }, - [0x20D5]={ - category="mn", - direction="nsm", - }, - [0x20D6]={ - category="mn", - direction="nsm", - }, - [0x20D7]={ - category="mn", - direction="nsm", - }, - [0x20D8]={ - category="mn", - direction="nsm", - }, - [0x20D9]={ - category="mn", - direction="nsm", - }, - [0x20DA]={ - category="mn", - direction="nsm", - }, - [0x20DB]={ - category="mn", - direction="nsm", - }, - [0x20DC]={ - category="mn", - direction="nsm", - }, - [0x20DD]={ - category="me", - direction="nsm", - }, - [0x20DE]={ - category="me", - direction="nsm", - }, - [0x20DF]={ - category="me", - direction="nsm", - }, - [0x20E0]={ - category="me", - direction="nsm", - }, - [0x20E1]={ - category="mn", - direction="nsm", - }, - [0x20E2]={ - category="me", - direction="nsm", - }, - [0x20E3]={ - category="me", - direction="nsm", - }, - [0x20E4]={ - category="me", - direction="nsm", - }, - [0x20E5]={ - category="mn", - direction="nsm", - }, - [0x20E6]={ - category="mn", - direction="nsm", - }, - [0x20E7]={ - category="mn", - direction="nsm", - }, - [0x20E8]={ - category="mn", - direction="nsm", - }, - [0x20E9]={ - category="mn", - direction="nsm", - }, - [0x20EA]={ - category="mn", - direction="nsm", - }, - [0x20EB]={ - category="mn", - direction="nsm", - }, - [0x20EC]={ - category="mn", - direction="nsm", - }, - [0x20ED]={ - category="mn", - direction="nsm", - }, - [0x20EE]={ - category="mn", - direction="nsm", - }, - [0x20EF]={ - category="mn", - direction="nsm", - }, - [0x20F0]={ - category="mn", - direction="nsm", - }, - [0x2100]={ - category="so", - direction="on", - }, - [0x2101]={ - category="so", - direction="on", - }, - [0x2102]={ - category="lu", - direction="l", - }, - [0x2103]={ - category="so", - direction="on", - }, - [0x2104]={ - category="so", - direction="on", - }, - [0x2105]={ - category="so", - direction="on", - }, - [0x2106]={ - category="so", - direction="on", - }, - [0x2107]={ - category="lu", - direction="l", - }, - [0x2108]={ - category="so", - direction="on", - }, - [0x2109]={ - category="so", - direction="on", - }, - [0x210A]={ - category="ll", - direction="l", - }, - [0x210B]={ - category="lu", - direction="l", - }, - [0x210C]={ - category="lu", - direction="l", - }, - [0x210D]={ - category="lu", - direction="l", - }, - [0x210E]={ - category="ll", - direction="l", - }, - [0x210F]={ - category="ll", - direction="l", - }, - [0x2110]={ - category="lu", - direction="l", - }, - [0x2111]={ - category="lu", - direction="l", - }, - [0x2112]={ - category="lu", - direction="l", - }, - [0x2113]={ - category="ll", - direction="l", - }, - [0x2114]={ - category="so", - direction="on", - }, - [0x2115]={ - category="lu", - direction="l", - }, - [0x2116]={ - category="so", - direction="on", - }, - [0x2117]={ - category="so", - direction="on", - }, - [0x2118]={ - category="so", - direction="on", - }, - [0x2119]={ - category="lu", - direction="l", - }, - [0x211A]={ - category="lu", - direction="l", - }, - [0x211B]={ - category="lu", - direction="l", - }, - [0x211C]={ - category="lu", - direction="l", - }, - [0x211D]={ - category="lu", - direction="l", - }, - [0x211E]={ - category="so", - direction="on", - }, - [0x211F]={ - category="so", - direction="on", - }, - [0x2120]={ - category="so", - direction="on", - }, - [0x2121]={ - category="so", - direction="on", - }, - [0x2122]={ - category="so", - direction="on", - }, - [0x2123]={ - category="so", - direction="on", - }, - [0x2124]={ - category="lu", - direction="l", - }, - [0x2125]={ - category="so", - direction="on", - }, - [0x2126]={ - category="lu", - direction="l", - }, - [0x2127]={ - category="so", - direction="on", - }, - [0x2128]={ - category="lu", - direction="l", - }, - [0x2129]={ - category="so", - direction="on", - }, - [0x212A]={ - category="lu", - direction="l", - }, - [0x212B]={ - category="lu", - direction="l", - }, - [0x212C]={ - category="lu", - direction="l", - }, - [0x212D]={ - category="lu", - direction="l", - }, - [0x212E]={ - category="so", - direction="et", - }, - [0x212F]={ - category="ll", - direction="l", - }, - [0x2130]={ - category="lu", - direction="l", - }, - [0x2131]={ - category="lu", - direction="l", - }, - [0x2132]={ - category="lu", - direction="l", - }, - [0x2133]={ - category="lu", - direction="l", - }, - [0x2134]={ - category="ll", - direction="l", - }, - [0x2135]={ - category="lo", - direction="l", - }, - [0x2136]={ - category="lo", - direction="l", - }, - [0x2137]={ - category="lo", - direction="l", - }, - [0x2138]={ - category="lo", - direction="l", - }, - [0x2139]={ - category="ll", - direction="l", - }, - [0x213A]={ - category="so", - direction="on", - }, - [0x213B]={ - category="so", - direction="on", - }, - [0x213C]={ - category="ll", - direction="l", - }, - [0x213D]={ - category="ll", - direction="l", - }, - [0x213E]={ - category="lu", - direction="l", - }, - [0x213F]={ - category="lu", - direction="l", - }, - [0x2140]={ - category="sm", - direction="on", - }, - [0x2141]={ - category="sm", - direction="on", - }, - [0x2142]={ - category="sm", - direction="on", - }, - [0x2143]={ - category="sm", - direction="on", - }, - [0x2144]={ - category="sm", - direction="on", - }, - [0x2145]={ - category="lu", - direction="l", - }, - [0x2146]={ - category="ll", - direction="l", - }, - [0x2147]={ - category="ll", - direction="l", - }, - [0x2148]={ - category="ll", - direction="l", - }, - [0x2149]={ - category="ll", - direction="l", - }, - [0x214A]={ - category="so", - direction="on", - }, - [0x214B]={ - category="sm", - direction="on", - }, - [0x214C]={ - category="so", - direction="on", - }, - [0x214D]={ - category="so", - direction="on", - }, - [0x214E]={ - category="ll", - direction="l", - }, - [0x214F]={ - category="so", - direction="l", - }, - [0x2150]={ - category="no", - direction="on", - }, - [0x2151]={ - category="no", - direction="on", - }, - [0x2152]={ - category="no", - direction="on", - }, - [0x2153]={ - category="no", - direction="on", - }, - [0x2154]={ - category="no", - direction="on", - }, - [0x2155]={ - category="no", - direction="on", - }, - [0x2156]={ - category="no", - direction="on", - }, - [0x2157]={ - category="no", - direction="on", - }, - [0x2158]={ - category="no", - direction="on", - }, - [0x2159]={ - category="no", - direction="on", - }, - [0x215A]={ - category="no", - direction="on", - }, - [0x215B]={ - category="no", - direction="on", - }, - [0x215C]={ - category="no", - direction="on", - }, - [0x215D]={ - category="no", - direction="on", - }, - [0x215E]={ - category="no", - direction="on", - }, - [0x215F]={ - category="no", - direction="on", - }, - [0x2160]={ - category="nl", - direction="l", - }, - [0x2161]={ - category="nl", - direction="l", - }, - [0x2162]={ - category="nl", - direction="l", - }, - [0x2163]={ - category="nl", - direction="l", - }, - [0x2164]={ - category="nl", - direction="l", - }, - [0x2165]={ - category="nl", - direction="l", - }, - [0x2166]={ - category="nl", - direction="l", - }, - [0x2167]={ - category="nl", - direction="l", - }, - [0x2168]={ - category="nl", - direction="l", - }, - [0x2169]={ - category="nl", - direction="l", - }, - [0x216A]={ - category="nl", - direction="l", - }, - [0x216B]={ - category="nl", - direction="l", - }, - [0x216C]={ - category="nl", - direction="l", - }, - [0x216D]={ - category="nl", - direction="l", - }, - [0x216E]={ - category="nl", - direction="l", - }, - [0x216F]={ - category="nl", - direction="l", - }, - [0x2170]={ - category="nl", - direction="l", - }, - [0x2171]={ - category="nl", - direction="l", - }, - [0x2172]={ - category="nl", - direction="l", - }, - [0x2173]={ - category="nl", - direction="l", - }, - [0x2174]={ - category="nl", - direction="l", - }, - [0x2175]={ - category="nl", - direction="l", - }, - [0x2176]={ - category="nl", - direction="l", - }, - [0x2177]={ - category="nl", - direction="l", - }, - [0x2178]={ - category="nl", - direction="l", - }, - [0x2179]={ - category="nl", - direction="l", - }, - [0x217A]={ - category="nl", - direction="l", - }, - [0x217B]={ - category="nl", - direction="l", - }, - [0x217C]={ - category="nl", - direction="l", - }, - [0x217D]={ - category="nl", - direction="l", - }, - [0x217E]={ - category="nl", - direction="l", - }, - [0x217F]={ - category="nl", - direction="l", - }, - [0x2180]={ - category="nl", - direction="l", - }, - [0x2181]={ - category="nl", - direction="l", - }, - [0x2182]={ - category="nl", - direction="l", - }, - [0x2183]={ - category="lu", - direction="l", - }, - [0x2184]={ - category="ll", - direction="l", - }, - [0x2185]={ - category="nl", - direction="l", - }, - [0x2186]={ - category="nl", - direction="l", - }, - [0x2187]={ - category="nl", - direction="l", - }, - [0x2188]={ - category="nl", - direction="l", - }, - [0x2189]={ - category="no", - direction="on", - }, - [0x218A]={ - category="so", - direction="on", - }, - [0x218B]={ - category="so", - direction="on", - }, - [0x2190]={ - category="sm", - direction="on", - }, - [0x2191]={ - category="sm", - direction="on", - }, - [0x2192]={ - category="sm", - direction="on", - }, - [0x2193]={ - category="sm", - direction="on", - }, - [0x2194]={ - category="sm", - direction="on", - }, - [0x2195]={ - category="so", - direction="on", - }, - [0x2196]={ - category="so", - direction="on", - }, - [0x2197]={ - category="so", - direction="on", - }, - [0x2198]={ - category="so", - direction="on", - }, - [0x2199]={ - category="so", - direction="on", - }, - [0x219A]={ - category="sm", - direction="on", - }, - [0x219B]={ - category="sm", - direction="on", - }, - [0x219C]={ - category="so", - direction="on", - }, - [0x219D]={ - category="so", - direction="on", - }, - [0x219E]={ - category="so", - direction="on", - }, - [0x219F]={ - category="so", - direction="on", - }, - [0x21A0]={ - category="sm", - direction="on", - }, - [0x21A1]={ - category="so", - direction="on", - }, - [0x21A2]={ - category="so", - direction="on", - }, - [0x21A3]={ - category="sm", - direction="on", - }, - [0x21A4]={ - category="so", - direction="on", - }, - [0x21A5]={ - category="so", - direction="on", - }, - [0x21A6]={ - category="sm", - direction="on", - }, - [0x21A7]={ - category="so", - direction="on", - }, - [0x21A8]={ - category="so", - direction="on", - }, - [0x21A9]={ - category="so", - direction="on", - }, - [0x21AA]={ - category="so", - direction="on", - }, - [0x21AB]={ - category="so", - direction="on", - }, - [0x21AC]={ - category="so", - direction="on", - }, - [0x21AD]={ - category="so", - direction="on", - }, - [0x21AE]={ - category="sm", - direction="on", - }, - [0x21AF]={ - category="so", - direction="on", - }, - [0x21B0]={ - category="so", - direction="on", - }, - [0x21B1]={ - category="so", - direction="on", - }, - [0x21B2]={ - category="so", - direction="on", - }, - [0x21B3]={ - category="so", - direction="on", - }, - [0x21B4]={ - category="so", - direction="on", - }, - [0x21B5]={ - category="so", - direction="on", - }, - [0x21B6]={ - category="so", - direction="on", - }, - [0x21B7]={ - category="so", - direction="on", - }, - [0x21B8]={ - category="so", - direction="on", - }, - [0x21B9]={ - category="so", - direction="on", - }, - [0x21BA]={ - category="so", - direction="on", - }, - [0x21BB]={ - category="so", - direction="on", - }, - [0x21BC]={ - category="so", - direction="on", - }, - [0x21BD]={ - category="so", - direction="on", - }, - [0x21BE]={ - category="so", - direction="on", - }, - [0x21BF]={ - category="so", - direction="on", - }, - [0x21C0]={ - category="so", - direction="on", - }, - [0x21C1]={ - category="so", - direction="on", - }, - [0x21C2]={ - category="so", - direction="on", - }, - [0x21C3]={ - category="so", - direction="on", - }, - [0x21C4]={ - category="so", - direction="on", - }, - [0x21C5]={ - category="so", - direction="on", - }, - [0x21C6]={ - category="so", - direction="on", - }, - [0x21C7]={ - category="so", - direction="on", - }, - [0x21C8]={ - category="so", - direction="on", - }, - [0x21C9]={ - category="so", - direction="on", - }, - [0x21CA]={ - category="so", - direction="on", - }, - [0x21CB]={ - category="so", - direction="on", - }, - [0x21CC]={ - category="so", - direction="on", - }, - [0x21CD]={ - category="so", - direction="on", - }, - [0x21CE]={ - category="sm", - direction="on", - }, - [0x21CF]={ - category="sm", - direction="on", - }, - [0x21D0]={ - category="so", - direction="on", - }, - [0x21D1]={ - category="so", - direction="on", - }, - [0x21D2]={ - category="sm", - direction="on", - }, - [0x21D3]={ - category="so", - direction="on", - }, - [0x21D4]={ - category="sm", - direction="on", - }, - [0x21D5]={ - category="so", - direction="on", - }, - [0x21D6]={ - category="so", - direction="on", - }, - [0x21D7]={ - category="so", - direction="on", - }, - [0x21D8]={ - category="so", - direction="on", - }, - [0x21D9]={ - category="so", - direction="on", - }, - [0x21DA]={ - category="so", - direction="on", - }, - [0x21DB]={ - category="so", - direction="on", - }, - [0x21DC]={ - category="so", - direction="on", - }, - [0x21DD]={ - category="so", - direction="on", - }, - [0x21DE]={ - category="so", - direction="on", - }, - [0x21DF]={ - category="so", - direction="on", - }, - [0x21E0]={ - category="so", - direction="on", - }, - [0x21E1]={ - category="so", - direction="on", - }, - [0x21E2]={ - category="so", - direction="on", - }, - [0x21E3]={ - category="so", - direction="on", - }, - [0x21E4]={ - category="so", - direction="on", - }, - [0x21E5]={ - category="so", - direction="on", - }, - [0x21E6]={ - category="so", - direction="on", - }, - [0x21E7]={ - category="so", - direction="on", - }, - [0x21E8]={ - category="so", - direction="on", - }, - [0x21E9]={ - category="so", - direction="on", - }, - [0x21EA]={ - category="so", - direction="on", - }, - [0x21EB]={ - category="so", - direction="on", - }, - [0x21EC]={ - category="so", - direction="on", - }, - [0x21ED]={ - category="so", - direction="on", - }, - [0x21EE]={ - category="so", - direction="on", - }, - [0x21EF]={ - category="so", - direction="on", - }, - [0x21F0]={ - category="so", - direction="on", - }, - [0x21F1]={ - category="so", - direction="on", - }, - [0x21F2]={ - category="so", - direction="on", - }, - [0x21F3]={ - category="so", - direction="on", - }, - [0x21F4]={ - category="sm", - direction="on", - }, - [0x21F5]={ - category="sm", - direction="on", - }, - [0x21F6]={ - category="sm", - direction="on", - }, - [0x21F7]={ - category="sm", - direction="on", - }, - [0x21F8]={ - category="sm", - direction="on", - }, - [0x21F9]={ - category="sm", - direction="on", - }, - [0x21FA]={ - category="sm", - direction="on", - }, - [0x21FB]={ - category="sm", - direction="on", - }, - [0x21FC]={ - category="sm", - direction="on", - }, - [0x21FD]={ - category="sm", - direction="on", - }, - [0x21FE]={ - category="sm", - direction="on", - }, - [0x21FF]={ - category="sm", - direction="on", - }, - [0x2200]={ - category="sm", - direction="on", - }, - [0x2201]={ - category="sm", - direction="on", - }, - [0x2202]={ - category="sm", - direction="on", - }, - [0x2203]={ - category="sm", - direction="on", - }, - [0x2204]={ - category="sm", - direction="on", - }, - [0x2205]={ - category="sm", - direction="on", - }, - [0x2206]={ - category="sm", - direction="on", - }, - [0x2207]={ - category="sm", - direction="on", - }, - [0x2208]={ - category="sm", - direction="on", - mirror=0x220B, - }, - [0x2209]={ - category="sm", - direction="on", - mirror=0x220C, - }, - [0x220A]={ - category="sm", - direction="on", - mirror=0x220D, - }, - [0x220B]={ - category="sm", - direction="on", - mirror=0x2208, - }, - [0x220C]={ - category="sm", - direction="on", - mirror=0x2209, - }, - [0x220D]={ - category="sm", - direction="on", - mirror=0x220A, - }, - [0x220E]={ - category="sm", - direction="on", - }, - [0x220F]={ - category="sm", - direction="on", - }, - [0x2210]={ - category="sm", - direction="on", - }, - [0x2211]={ - category="sm", - direction="on", - }, - [0x2212]={ - category="sm", - direction="es", - }, - [0x2213]={ - category="sm", - direction="et", - }, - [0x2214]={ - category="sm", - direction="on", - }, - [0x2215]={ - category="sm", - direction="on", - mirror=0x29F5, - }, - [0x2216]={ - category="sm", - direction="on", - }, - [0x2217]={ - category="sm", - direction="on", - }, - [0x2218]={ - category="sm", - direction="on", - }, - [0x2219]={ - category="sm", - direction="on", - }, - [0x221A]={ - category="sm", - direction="on", - }, - [0x221B]={ - category="sm", - direction="on", - }, - [0x221C]={ - category="sm", - direction="on", - }, - [0x221D]={ - category="sm", - direction="on", - }, - [0x221E]={ - category="sm", - direction="on", - }, - [0x221F]={ - category="sm", - direction="on", - }, - [0x2220]={ - category="sm", - direction="on", - }, - [0x2221]={ - category="sm", - direction="on", - }, - [0x2222]={ - category="sm", - direction="on", - }, - [0x2223]={ - category="sm", - direction="on", - }, - [0x2224]={ - category="sm", - direction="on", - }, - [0x2225]={ - category="sm", - direction="on", - }, - [0x2226]={ - category="sm", - direction="on", - }, - [0x2227]={ - category="sm", - direction="on", - }, - [0x2228]={ - category="sm", - direction="on", - }, - [0x2229]={ - category="sm", - direction="on", - }, - [0x222A]={ - category="sm", - direction="on", - }, - [0x222B]={ - category="sm", - direction="on", - }, - [0x222C]={ - category="sm", - direction="on", - }, - [0x222D]={ - category="sm", - direction="on", - }, - [0x222E]={ - category="sm", - direction="on", - }, - [0x222F]={ - category="sm", - direction="on", - }, - [0x2230]={ - category="sm", - direction="on", - }, - [0x2231]={ - category="sm", - direction="on", - }, - [0x2232]={ - category="sm", - direction="on", - }, - [0x2233]={ - category="sm", - direction="on", - }, - [0x2234]={ - category="sm", - direction="on", - }, - [0x2235]={ - category="sm", - direction="on", - }, - [0x2236]={ - category="sm", - direction="on", - }, - [0x2237]={ - category="sm", - direction="on", - }, - [0x2238]={ - category="sm", - direction="on", - }, - [0x2239]={ - category="sm", - direction="on", - }, - [0x223A]={ - category="sm", - direction="on", - }, - [0x223B]={ - category="sm", - direction="on", - }, - [0x223C]={ - category="sm", - direction="on", - mirror=0x223D, - }, - [0x223D]={ - category="sm", - direction="on", - mirror=0x223C, - }, - [0x223E]={ - category="sm", - direction="on", - }, - [0x223F]={ - category="sm", - direction="on", - }, - [0x2240]={ - category="sm", - direction="on", - }, - [0x2241]={ - category="sm", - direction="on", - }, - [0x2242]={ - category="sm", - direction="on", - }, - [0x2243]={ - category="sm", - direction="on", - mirror=0x22CD, - }, - [0x2244]={ - category="sm", - direction="on", - }, - [0x2245]={ - category="sm", - direction="on", - }, - [0x2246]={ - category="sm", - direction="on", - }, - [0x2247]={ - category="sm", - direction="on", - }, - [0x2248]={ - category="sm", - direction="on", - }, - [0x2249]={ - category="sm", - direction="on", - }, - [0x224A]={ - category="sm", - direction="on", - }, - [0x224B]={ - category="sm", - direction="on", - }, - [0x224C]={ - category="sm", - direction="on", - }, - [0x224D]={ - category="sm", - direction="on", - }, - [0x224E]={ - category="sm", - direction="on", - }, - [0x224F]={ - category="sm", - direction="on", - }, - [0x2250]={ - category="sm", - direction="on", - }, - [0x2251]={ - category="sm", - direction="on", - }, - [0x2252]={ - category="sm", - direction="on", - mirror=0x2253, - }, - [0x2253]={ - category="sm", - direction="on", - mirror=0x2252, - }, - [0x2254]={ - category="sm", - direction="on", - mirror=0x2255, - }, - [0x2255]={ - category="sm", - direction="on", - mirror=0x2254, - }, - [0x2256]={ - category="sm", - direction="on", - }, - [0x2257]={ - category="sm", - direction="on", - }, - [0x2258]={ - category="sm", - direction="on", - }, - [0x2259]={ - category="sm", - direction="on", - }, - [0x225A]={ - category="sm", - direction="on", - }, - [0x225B]={ - category="sm", - direction="on", - }, - [0x225C]={ - category="sm", - direction="on", - }, - [0x225D]={ - category="sm", - direction="on", - }, - [0x225E]={ - category="sm", - direction="on", - }, - [0x225F]={ - category="sm", - direction="on", - }, - [0x2260]={ - category="sm", - direction="on", - }, - [0x2261]={ - category="sm", - direction="on", - }, - [0x2262]={ - category="sm", - direction="on", - }, - [0x2263]={ - category="sm", - direction="on", - }, - [0x2264]={ - category="sm", - direction="on", - mirror=0x2265, - }, - [0x2265]={ - category="sm", - direction="on", - mirror=0x2264, - }, - [0x2266]={ - category="sm", - direction="on", - mirror=0x2267, - }, - [0x2267]={ - category="sm", - direction="on", - mirror=0x2266, - }, - [0x2268]={ - category="sm", - direction="on", - mirror=0x2269, - }, - [0x2269]={ - category="sm", - direction="on", - mirror=0x2268, - }, - [0x226A]={ - category="sm", - direction="on", - mirror=0x226B, - }, - [0x226B]={ - category="sm", - direction="on", - mirror=0x226A, - }, - [0x226C]={ - category="sm", - direction="on", - }, - [0x226D]={ - category="sm", - direction="on", - }, - [0x226E]={ - category="sm", - direction="on", - mirror=0x226F, - }, - [0x226F]={ - category="sm", - direction="on", - mirror=0x226E, - }, - [0x2270]={ - category="sm", - direction="on", - mirror=0x2271, - }, - [0x2271]={ - category="sm", - direction="on", - mirror=0x2270, - }, - [0x2272]={ - category="sm", - direction="on", - mirror=0x2273, - }, - [0x2273]={ - category="sm", - direction="on", - mirror=0x2272, - }, - [0x2274]={ - category="sm", - direction="on", - mirror=0x2275, - }, - [0x2275]={ - category="sm", - direction="on", - mirror=0x2274, - }, - [0x2276]={ - category="sm", - direction="on", - mirror=0x2277, - }, - [0x2277]={ - category="sm", - direction="on", - mirror=0x2276, - }, - [0x2278]={ - category="sm", - direction="on", - mirror=0x2279, - }, - [0x2279]={ - category="sm", - direction="on", - mirror=0x2278, - }, - [0x227A]={ - category="sm", - direction="on", - mirror=0x227B, - }, - [0x227B]={ - category="sm", - direction="on", - mirror=0x227A, - }, - [0x227C]={ - category="sm", - direction="on", - mirror=0x227D, - }, - [0x227D]={ - category="sm", - direction="on", - mirror=0x227C, - }, - [0x227E]={ - category="sm", - direction="on", - mirror=0x227F, - }, - [0x227F]={ - category="sm", - direction="on", - mirror=0x227E, - }, - [0x2280]={ - category="sm", - direction="on", - mirror=0x2281, - }, - [0x2281]={ - category="sm", - direction="on", - mirror=0x2280, - }, - [0x2282]={ - category="sm", - direction="on", - mirror=0x2283, - }, - [0x2283]={ - category="sm", - direction="on", - mirror=0x2282, - }, - [0x2284]={ - category="sm", - direction="on", - mirror=0x2285, - }, - [0x2285]={ - category="sm", - direction="on", - mirror=0x2284, - }, - [0x2286]={ - category="sm", - direction="on", - mirror=0x2287, - }, - [0x2287]={ - category="sm", - direction="on", - mirror=0x2286, - }, - [0x2288]={ - category="sm", - direction="on", - mirror=0x2289, - }, - [0x2289]={ - category="sm", - direction="on", - mirror=0x2288, - }, - [0x228A]={ - category="sm", - direction="on", - mirror=0x228B, - }, - [0x228B]={ - category="sm", - direction="on", - mirror=0x228A, - }, - [0x228C]={ - category="sm", - direction="on", - }, - [0x228D]={ - category="sm", - direction="on", - }, - [0x228E]={ - category="sm", - direction="on", - }, - [0x228F]={ - category="sm", - direction="on", - mirror=0x2290, - }, - [0x2290]={ - category="sm", - direction="on", - mirror=0x228F, - }, - [0x2291]={ - category="sm", - direction="on", - mirror=0x2292, - }, - [0x2292]={ - category="sm", - direction="on", - mirror=0x2291, - }, - [0x2293]={ - category="sm", - direction="on", - }, - [0x2294]={ - category="sm", - direction="on", - }, - [0x2295]={ - category="sm", - direction="on", - }, - [0x2296]={ - category="sm", - direction="on", - }, - [0x2297]={ - category="sm", - direction="on", - }, - [0x2298]={ - category="sm", - direction="on", - mirror=0x29B8, - }, - [0x2299]={ - category="sm", - direction="on", - }, - [0x229A]={ - category="sm", - direction="on", - }, - [0x229B]={ - category="sm", - direction="on", - }, - [0x229C]={ - category="sm", - direction="on", - }, - [0x229D]={ - category="sm", - direction="on", - }, - [0x229E]={ - category="sm", - direction="on", - }, - [0x229F]={ - category="sm", - direction="on", - }, - [0x22A0]={ - category="sm", - direction="on", - }, - [0x22A1]={ - category="sm", - direction="on", - }, - [0x22A2]={ - category="sm", - direction="on", - mirror=0x22A3, - }, - [0x22A3]={ - category="sm", - direction="on", - mirror=0x22A2, - }, - [0x22A4]={ - category="sm", - direction="on", - }, - [0x22A5]={ - category="sm", - direction="on", - }, - [0x22A6]={ - category="sm", - direction="on", - mirror=0x2ADE, - }, - [0x22A7]={ - category="sm", - direction="on", - }, - [0x22A8]={ - category="sm", - direction="on", - mirror=0x2AE4, - }, - [0x22A9]={ - category="sm", - direction="on", - mirror=0x2AE3, - }, - [0x22AA]={ - category="sm", - direction="on", - }, - [0x22AB]={ - category="sm", - direction="on", - mirror=0x2AE5, - }, - [0x22AC]={ - category="sm", - direction="on", - }, - [0x22AD]={ - category="sm", - direction="on", - }, - [0x22AE]={ - category="sm", - direction="on", - }, - [0x22AF]={ - category="sm", - direction="on", - }, - [0x22B0]={ - category="sm", - direction="on", - mirror=0x22B1, - }, - [0x22B1]={ - category="sm", - direction="on", - mirror=0x22B0, - }, - [0x22B2]={ - category="sm", - direction="on", - mirror=0x22B3, - }, - [0x22B3]={ - category="sm", - direction="on", - mirror=0x22B2, - }, - [0x22B4]={ - category="sm", - direction="on", - mirror=0x22B5, - }, - [0x22B5]={ - category="sm", - direction="on", - mirror=0x22B4, - }, - [0x22B6]={ - category="sm", - direction="on", - mirror=0x22B7, - }, - [0x22B7]={ - category="sm", - direction="on", - mirror=0x22B6, - }, - [0x22B8]={ - category="sm", - direction="on", - }, - [0x22B9]={ - category="sm", - direction="on", - }, - [0x22BA]={ - category="sm", - direction="on", - }, - [0x22BB]={ - category="sm", - direction="on", - }, - [0x22BC]={ - category="sm", - direction="on", - }, - [0x22BD]={ - category="sm", - direction="on", - }, - [0x22BE]={ - category="sm", - direction="on", - }, - [0x22BF]={ - category="sm", - direction="on", - }, - [0x22C0]={ - category="sm", - direction="on", - }, - [0x22C1]={ - category="sm", - direction="on", - }, - [0x22C2]={ - category="sm", - direction="on", - }, - [0x22C3]={ - category="sm", - direction="on", - }, - [0x22C4]={ - category="sm", - direction="on", - }, - [0x22C5]={ - category="sm", - direction="on", - }, - [0x22C6]={ - category="sm", - direction="on", - }, - [0x22C7]={ - category="sm", - direction="on", - }, - [0x22C8]={ - category="sm", - direction="on", - }, - [0x22C9]={ - category="sm", - direction="on", - mirror=0x22CA, - }, - [0x22CA]={ - category="sm", - direction="on", - mirror=0x22C9, - }, - [0x22CB]={ - category="sm", - direction="on", - mirror=0x22CC, - }, - [0x22CC]={ - category="sm", - direction="on", - mirror=0x22CB, - }, - [0x22CD]={ - category="sm", - direction="on", - mirror=0x2243, - }, - [0x22CE]={ - category="sm", - direction="on", - }, - [0x22CF]={ - category="sm", - direction="on", - }, - [0x22D0]={ - category="sm", - direction="on", - mirror=0x22D1, - }, - [0x22D1]={ - category="sm", - direction="on", - mirror=0x22D0, - }, - [0x22D2]={ - category="sm", - direction="on", - }, - [0x22D3]={ - category="sm", - direction="on", - }, - [0x22D4]={ - category="sm", - direction="on", - }, - [0x22D5]={ - category="sm", - direction="on", - }, - [0x22D6]={ - category="sm", - direction="on", - mirror=0x22D7, - }, - [0x22D7]={ - category="sm", - direction="on", - mirror=0x22D6, - }, - [0x22D8]={ - category="sm", - direction="on", - mirror=0x22D9, - }, - [0x22D9]={ - category="sm", - direction="on", - mirror=0x22D8, - }, - [0x22DA]={ - category="sm", - direction="on", - mirror=0x22DB, - }, - [0x22DB]={ - category="sm", - direction="on", - mirror=0x22DA, - }, - [0x22DC]={ - category="sm", - direction="on", - mirror=0x22DD, - }, - [0x22DD]={ - category="sm", - direction="on", - mirror=0x22DC, - }, - [0x22DE]={ - category="sm", - direction="on", - mirror=0x22DF, - }, - [0x22DF]={ - category="sm", - direction="on", - mirror=0x22DE, - }, - [0x22E0]={ - category="sm", - direction="on", - mirror=0x22E1, - }, - [0x22E1]={ - category="sm", - direction="on", - mirror=0x22E0, - }, - [0x22E2]={ - category="sm", - direction="on", - mirror=0x22E3, - }, - [0x22E3]={ - category="sm", - direction="on", - mirror=0x22E2, - }, - [0x22E4]={ - category="sm", - direction="on", - mirror=0x22E5, - }, - [0x22E5]={ - category="sm", - direction="on", - mirror=0x22E4, - }, - [0x22E6]={ - category="sm", - direction="on", - mirror=0x22E7, - }, - [0x22E7]={ - category="sm", - direction="on", - mirror=0x22E6, - }, - [0x22E8]={ - category="sm", - direction="on", - mirror=0x22E9, - }, - [0x22E9]={ - category="sm", - direction="on", - mirror=0x22E8, - }, - [0x22EA]={ - category="sm", - direction="on", - mirror=0x22EB, - }, - [0x22EB]={ - category="sm", - direction="on", - mirror=0x22EA, - }, - [0x22EC]={ - category="sm", - direction="on", - mirror=0x22ED, - }, - [0x22ED]={ - category="sm", - direction="on", - mirror=0x22EC, - }, - [0x22EE]={ - category="sm", - direction="on", - }, - [0x22EF]={ - category="sm", - direction="on", - }, - [0x22F0]={ - category="sm", - direction="on", - mirror=0x22F1, - }, - [0x22F1]={ - category="sm", - direction="on", - mirror=0x22F0, - }, - [0x22F2]={ - category="sm", - direction="on", - mirror=0x22FA, - }, - [0x22F3]={ - category="sm", - direction="on", - mirror=0x22FB, - }, - [0x22F4]={ - category="sm", - direction="on", - mirror=0x22FC, - }, - [0x22F5]={ - category="sm", - direction="on", - }, - [0x22F6]={ - category="sm", - direction="on", - mirror=0x22FD, - }, - [0x22F7]={ - category="sm", - direction="on", - mirror=0x22FE, - }, - [0x22F8]={ - category="sm", - direction="on", - }, - [0x22F9]={ - category="sm", - direction="on", - }, - [0x22FA]={ - category="sm", - direction="on", - mirror=0x22F2, - }, - [0x22FB]={ - category="sm", - direction="on", - mirror=0x22F3, - }, - [0x22FC]={ - category="sm", - direction="on", - mirror=0x22F4, - }, - [0x22FD]={ - category="sm", - direction="on", - mirror=0x22F6, - }, - [0x22FE]={ - category="sm", - direction="on", - mirror=0x22F7, - }, - [0x22FF]={ - category="sm", - direction="on", - }, - [0x2300]={ - category="so", - direction="on", - }, - [0x2301]={ - category="so", - direction="on", - }, - [0x2302]={ - category="so", - direction="on", - }, - [0x2303]={ - category="so", - direction="on", - }, - [0x2304]={ - category="so", - direction="on", - }, - [0x2305]={ - category="so", - direction="on", - }, - [0x2306]={ - category="so", - direction="on", - }, - [0x2307]={ - category="so", - direction="on", - }, - [0x2308]={ - category="sm", - direction="on", - mirror=0x2309, - }, - [0x2309]={ - category="sm", - direction="on", - mirror=0x2308, - }, - [0x230A]={ - category="sm", - direction="on", - mirror=0x230B, - }, - [0x230B]={ - category="sm", - direction="on", - mirror=0x230A, - }, - [0x230C]={ - category="so", - direction="on", - }, - [0x230D]={ - category="so", - direction="on", - }, - [0x230E]={ - category="so", - direction="on", - }, - [0x230F]={ - category="so", - direction="on", - }, - [0x2310]={ - category="so", - direction="on", - }, - [0x2311]={ - category="so", - direction="on", - }, - [0x2312]={ - category="so", - direction="on", - }, - [0x2313]={ - category="so", - direction="on", - }, - [0x2314]={ - category="so", - direction="on", - }, - [0x2315]={ - category="so", - direction="on", - }, - [0x2316]={ - category="so", - direction="on", - }, - [0x2317]={ - category="so", - direction="on", - }, - [0x2318]={ - category="so", - direction="on", - }, - [0x2319]={ - category="so", - direction="on", - }, - [0x231A]={ - category="so", - direction="on", - }, - [0x231B]={ - category="so", - direction="on", - }, - [0x231C]={ - category="so", - direction="on", - }, - [0x231D]={ - category="so", - direction="on", - }, - [0x231E]={ - category="so", - direction="on", - }, - [0x231F]={ - category="so", - direction="on", - }, - [0x2320]={ - category="sm", - direction="on", - }, - [0x2321]={ - category="sm", - direction="on", - }, - [0x2322]={ - category="so", - direction="on", - }, - [0x2323]={ - category="so", - direction="on", - }, - [0x2324]={ - category="so", - direction="on", - }, - [0x2325]={ - category="so", - direction="on", - }, - [0x2326]={ - category="so", - direction="on", - }, - [0x2327]={ - category="so", - direction="on", - }, - [0x2328]={ - category="so", - direction="on", - }, - [0x2329]={ - category="ps", - direction="on", - mirror=0x232A, - }, - [0x232A]={ - category="pe", - direction="on", - mirror=0x2329, - }, - [0x232B]={ - category="so", - direction="on", - }, - [0x232C]={ - category="so", - direction="on", - }, - [0x232D]={ - category="so", - direction="on", - }, - [0x232E]={ - category="so", - direction="on", - }, - [0x232F]={ - category="so", - direction="on", - }, - [0x2330]={ - category="so", - direction="on", - }, - [0x2331]={ - category="so", - direction="on", - }, - [0x2332]={ - category="so", - direction="on", - }, - [0x2333]={ - category="so", - direction="on", - }, - [0x2334]={ - category="so", - direction="on", - }, - [0x2335]={ - category="so", - direction="on", - }, - [0x2336]={ - category="so", - direction="l", - }, - [0x2337]={ - category="so", - direction="l", - }, - [0x2338]={ - category="so", - direction="l", - }, - [0x2339]={ - category="so", - direction="l", - }, - [0x233A]={ - category="so", - direction="l", - }, - [0x233B]={ - category="so", - direction="l", - }, - [0x233C]={ - category="so", - direction="l", - }, - [0x233D]={ - category="so", - direction="l", - }, - [0x233E]={ - category="so", - direction="l", - }, - [0x233F]={ - category="so", - direction="l", - }, - [0x2340]={ - category="so", - direction="l", - }, - [0x2341]={ - category="so", - direction="l", - }, - [0x2342]={ - category="so", - direction="l", - }, - [0x2343]={ - category="so", - direction="l", - }, - [0x2344]={ - category="so", - direction="l", - }, - [0x2345]={ - category="so", - direction="l", - }, - [0x2346]={ - category="so", - direction="l", - }, - [0x2347]={ - category="so", - direction="l", - }, - [0x2348]={ - category="so", - direction="l", - }, - [0x2349]={ - category="so", - direction="l", - }, - [0x234A]={ - category="so", - direction="l", - }, - [0x234B]={ - category="so", - direction="l", - }, - [0x234C]={ - category="so", - direction="l", - }, - [0x234D]={ - category="so", - direction="l", - }, - [0x234E]={ - category="so", - direction="l", - }, - [0x234F]={ - category="so", - direction="l", - }, - [0x2350]={ - category="so", - direction="l", - }, - [0x2351]={ - category="so", - direction="l", - }, - [0x2352]={ - category="so", - direction="l", - }, - [0x2353]={ - category="so", - direction="l", - }, - [0x2354]={ - category="so", - direction="l", - }, - [0x2355]={ - category="so", - direction="l", - }, - [0x2356]={ - category="so", - direction="l", - }, - [0x2357]={ - category="so", - direction="l", - }, - [0x2358]={ - category="so", - direction="l", - }, - [0x2359]={ - category="so", - direction="l", - }, - [0x235A]={ - category="so", - direction="l", - }, - [0x235B]={ - category="so", - direction="l", - }, - [0x235C]={ - category="so", - direction="l", - }, - [0x235D]={ - category="so", - direction="l", - }, - [0x235E]={ - category="so", - direction="l", - }, - [0x235F]={ - category="so", - direction="l", - }, - [0x2360]={ - category="so", - direction="l", - }, - [0x2361]={ - category="so", - direction="l", - }, - [0x2362]={ - category="so", - direction="l", - }, - [0x2363]={ - category="so", - direction="l", - }, - [0x2364]={ - category="so", - direction="l", - }, - [0x2365]={ - category="so", - direction="l", - }, - [0x2366]={ - category="so", - direction="l", - }, - [0x2367]={ - category="so", - direction="l", - }, - [0x2368]={ - category="so", - direction="l", - }, - [0x2369]={ - category="so", - direction="l", - }, - [0x236A]={ - category="so", - direction="l", - }, - [0x236B]={ - category="so", - direction="l", - }, - [0x236C]={ - category="so", - direction="l", - }, - [0x236D]={ - category="so", - direction="l", - }, - [0x236E]={ - category="so", - direction="l", - }, - [0x236F]={ - category="so", - direction="l", - }, - [0x2370]={ - category="so", - direction="l", - }, - [0x2371]={ - category="so", - direction="l", - }, - [0x2372]={ - category="so", - direction="l", - }, - [0x2373]={ - category="so", - direction="l", - }, - [0x2374]={ - category="so", - direction="l", - }, - [0x2375]={ - category="so", - direction="l", - }, - [0x2376]={ - category="so", - direction="l", - }, - [0x2377]={ - category="so", - direction="l", - }, - [0x2378]={ - category="so", - direction="l", - }, - [0x2379]={ - category="so", - direction="l", - }, - [0x237A]={ - category="so", - direction="l", - }, - [0x237B]={ - category="so", - direction="on", - }, - [0x237C]={ - category="sm", - direction="on", - }, - [0x237D]={ - category="so", - direction="on", - }, - [0x237E]={ - category="so", - direction="on", - }, - [0x237F]={ - category="so", - direction="on", - }, - [0x2380]={ - category="so", - direction="on", - }, - [0x2381]={ - category="so", - direction="on", - }, - [0x2382]={ - category="so", - direction="on", - }, - [0x2383]={ - category="so", - direction="on", - }, - [0x2384]={ - category="so", - direction="on", - }, - [0x2385]={ - category="so", - direction="on", - }, - [0x2386]={ - category="so", - direction="on", - }, - [0x2387]={ - category="so", - direction="on", - }, - [0x2388]={ - category="so", - direction="on", - }, - [0x2389]={ - category="so", - direction="on", - }, - [0x238A]={ - category="so", - direction="on", - }, - [0x238B]={ - category="so", - direction="on", - }, - [0x238C]={ - category="so", - direction="on", - }, - [0x238D]={ - category="so", - direction="on", - }, - [0x238E]={ - category="so", - direction="on", - }, - [0x238F]={ - category="so", - direction="on", - }, - [0x2390]={ - category="so", - direction="on", - }, - [0x2391]={ - category="so", - direction="on", - }, - [0x2392]={ - category="so", - direction="on", - }, - [0x2393]={ - category="so", - direction="on", - }, - [0x2394]={ - category="so", - direction="on", - }, - [0x2395]={ - category="so", - direction="l", - }, - [0x2396]={ - category="so", - direction="on", - }, - [0x2397]={ - category="so", - direction="on", - }, - [0x2398]={ - category="so", - direction="on", - }, - [0x2399]={ - category="so", - direction="on", - }, - [0x239A]={ - category="so", - direction="on", - }, - [0x239B]={ - category="sm", - direction="on", - }, - [0x239C]={ - category="sm", - direction="on", - }, - [0x239D]={ - category="sm", - direction="on", - }, - [0x239E]={ - category="sm", - direction="on", - }, - [0x239F]={ - category="sm", - direction="on", - }, - [0x23A0]={ - category="sm", - direction="on", - }, - [0x23A1]={ - category="sm", - direction="on", - }, - [0x23A2]={ - category="sm", - direction="on", - }, - [0x23A3]={ - category="sm", - direction="on", - }, - [0x23A4]={ - category="sm", - direction="on", - }, - [0x23A5]={ - category="sm", - direction="on", - }, - [0x23A6]={ - category="sm", - direction="on", - }, - [0x23A7]={ - category="sm", - direction="on", - }, - [0x23A8]={ - category="sm", - direction="on", - }, - [0x23A9]={ - category="sm", - direction="on", - }, - [0x23AA]={ - category="sm", - direction="on", - }, - [0x23AB]={ - category="sm", - direction="on", - }, - [0x23AC]={ - category="sm", - direction="on", - }, - [0x23AD]={ - category="sm", - direction="on", - }, - [0x23AE]={ - category="sm", - direction="on", - }, - [0x23AF]={ - category="sm", - direction="on", - }, - [0x23B0]={ - category="sm", - direction="on", - }, - [0x23B1]={ - category="sm", - direction="on", - }, - [0x23B2]={ - category="sm", - direction="on", - }, - [0x23B3]={ - category="sm", - direction="on", - }, - [0x23B4]={ - category="so", - direction="on", - }, - [0x23B5]={ - category="so", - direction="on", - }, - [0x23B6]={ - category="so", - direction="on", - }, - [0x23B7]={ - category="so", - direction="on", - }, - [0x23B8]={ - category="so", - direction="on", - }, - [0x23B9]={ - category="so", - direction="on", - }, - [0x23BA]={ - category="so", - direction="on", - }, - [0x23BB]={ - category="so", - direction="on", - }, - [0x23BC]={ - category="so", - direction="on", - }, - [0x23BD]={ - category="so", - direction="on", - }, - [0x23BE]={ - category="so", - direction="on", - }, - [0x23BF]={ - category="so", - direction="on", - }, - [0x23C0]={ - category="so", - direction="on", - }, - [0x23C1]={ - category="so", - direction="on", - }, - [0x23C2]={ - category="so", - direction="on", - }, - [0x23C3]={ - category="so", - direction="on", - }, - [0x23C4]={ - category="so", - direction="on", - }, - [0x23C5]={ - category="so", - direction="on", - }, - [0x23C6]={ - category="so", - direction="on", - }, - [0x23C7]={ - category="so", - direction="on", - }, - [0x23C8]={ - category="so", - direction="on", - }, - [0x23C9]={ - category="so", - direction="on", - }, - [0x23CA]={ - category="so", - direction="on", - }, - [0x23CB]={ - category="so", - direction="on", - }, - [0x23CC]={ - category="so", - direction="on", - }, - [0x23CD]={ - category="so", - direction="on", - }, - [0x23CE]={ - category="so", - direction="on", - }, - [0x23CF]={ - category="so", - direction="on", - }, - [0x23D0]={ - category="so", - direction="on", - }, - [0x23D1]={ - category="so", - direction="on", - }, - [0x23D2]={ - category="so", - direction="on", - }, - [0x23D3]={ - category="so", - direction="on", - }, - [0x23D4]={ - category="so", - direction="on", - }, - [0x23D5]={ - category="so", - direction="on", - }, - [0x23D6]={ - category="so", - direction="on", - }, - [0x23D7]={ - category="so", - direction="on", - }, - [0x23D8]={ - category="so", - direction="on", - }, - [0x23D9]={ - category="so", - direction="on", - }, - [0x23DA]={ - category="so", - direction="on", - }, - [0x23DB]={ - category="so", - direction="on", - }, - [0x23DC]={ - category="sm", - direction="on", - }, - [0x23DD]={ - category="sm", - direction="on", - }, - [0x23DE]={ - category="sm", - direction="on", - }, - [0x23DF]={ - category="sm", - direction="on", - }, - [0x23E0]={ - category="sm", - direction="on", - }, - [0x23E1]={ - category="sm", - direction="on", - }, - [0x23E2]={ - category="so", - direction="on", - }, - [0x23E3]={ - category="so", - direction="on", - }, - [0x23E4]={ - category="so", - direction="on", - }, - [0x23E5]={ - category="so", - direction="on", - }, - [0x23E6]={ - category="so", - direction="on", - }, - [0x23E7]={ - category="so", - direction="on", - }, - [0x23E8]={ - category="so", - direction="on", - }, - [0x23E9]={ - category="so", - direction="on", - }, - [0x23EA]={ - category="so", - direction="on", - }, - [0x23EB]={ - category="so", - direction="on", - }, - [0x23EC]={ - category="so", - direction="on", - }, - [0x23ED]={ - category="so", - direction="on", - }, - [0x23EE]={ - category="so", - direction="on", - }, - [0x23EF]={ - category="so", - direction="on", - }, - [0x23F0]={ - category="so", - direction="on", - }, - [0x23F1]={ - category="so", - direction="on", - }, - [0x23F2]={ - category="so", - direction="on", - }, - [0x23F3]={ - category="so", - direction="on", - }, - [0x23F4]={ - category="so", - direction="on", - }, - [0x23F5]={ - category="so", - direction="on", - }, - [0x23F6]={ - category="so", - direction="on", - }, - [0x23F7]={ - category="so", - direction="on", - }, - [0x23F8]={ - category="so", - direction="on", - }, - [0x23F9]={ - category="so", - direction="on", - }, - [0x23FA]={ - category="so", - direction="on", - }, - [0x23FB]={ - category="so", - direction="on", - }, - [0x23FC]={ - category="so", - direction="on", - }, - [0x23FD]={ - category="so", - direction="on", - }, - [0x23FE]={ - category="so", - direction="on", - }, - [0x2400]={ - category="so", - direction="on", - }, - [0x2401]={ - category="so", - direction="on", - }, - [0x2402]={ - category="so", - direction="on", - }, - [0x2403]={ - category="so", - direction="on", - }, - [0x2404]={ - category="so", - direction="on", - }, - [0x2405]={ - category="so", - direction="on", - }, - [0x2406]={ - category="so", - direction="on", - }, - [0x2407]={ - category="so", - direction="on", - }, - [0x2408]={ - category="so", - direction="on", - }, - [0x2409]={ - category="so", - direction="on", - }, - [0x240A]={ - category="so", - direction="on", - }, - [0x240B]={ - category="so", - direction="on", - }, - [0x240C]={ - category="so", - direction="on", - }, - [0x240D]={ - category="so", - direction="on", - }, - [0x240E]={ - category="so", - direction="on", - }, - [0x240F]={ - category="so", - direction="on", - }, - [0x2410]={ - category="so", - direction="on", - }, - [0x2411]={ - category="so", - direction="on", - }, - [0x2412]={ - category="so", - direction="on", - }, - [0x2413]={ - category="so", - direction="on", - }, - [0x2414]={ - category="so", - direction="on", - }, - [0x2415]={ - category="so", - direction="on", - }, - [0x2416]={ - category="so", - direction="on", - }, - [0x2417]={ - category="so", - direction="on", - }, - [0x2418]={ - category="so", - direction="on", - }, - [0x2419]={ - category="so", - direction="on", - }, - [0x241A]={ - category="so", - direction="on", - }, - [0x241B]={ - category="so", - direction="on", - }, - [0x241C]={ - category="so", - direction="on", - }, - [0x241D]={ - category="so", - direction="on", - }, - [0x241E]={ - category="so", - direction="on", - }, - [0x241F]={ - category="so", - direction="on", - }, - [0x2420]={ - category="so", - direction="on", - }, - [0x2421]={ - category="so", - direction="on", - }, - [0x2422]={ - category="so", - direction="on", - }, - [0x2423]={ - category="so", - direction="on", - }, - [0x2424]={ - category="so", - direction="on", - }, - [0x2425]={ - category="so", - direction="on", - }, - [0x2426]={ - category="so", - direction="on", - }, - [0x2440]={ - category="so", - direction="on", - }, - [0x2441]={ - category="so", - direction="on", - }, - [0x2442]={ - category="so", - direction="on", - }, - [0x2443]={ - category="so", - direction="on", - }, - [0x2444]={ - category="so", - direction="on", - }, - [0x2445]={ - category="so", - direction="on", - }, - [0x2446]={ - category="so", - direction="on", - }, - [0x2447]={ - category="so", - direction="on", - }, - [0x2448]={ - category="so", - direction="on", - }, - [0x2449]={ - category="so", - direction="on", - }, - [0x244A]={ - category="so", - direction="on", - }, - [0x2460]={ - category="no", - direction="on", - }, - [0x2461]={ - category="no", - direction="on", - }, - [0x2462]={ - category="no", - direction="on", - }, - [0x2463]={ - category="no", - direction="on", - }, - [0x2464]={ - category="no", - direction="on", - }, - [0x2465]={ - category="no", - direction="on", - }, - [0x2466]={ - category="no", - direction="on", - }, - [0x2467]={ - category="no", - direction="on", - }, - [0x2468]={ - category="no", - direction="on", - }, - [0x2469]={ - category="no", - direction="on", - }, - [0x246A]={ - category="no", - direction="on", - }, - [0x246B]={ - category="no", - direction="on", - }, - [0x246C]={ - category="no", - direction="on", - }, - [0x246D]={ - category="no", - direction="on", - }, - [0x246E]={ - category="no", - direction="on", - }, - [0x246F]={ - category="no", - direction="on", - }, - [0x2470]={ - category="no", - direction="on", - }, - [0x2471]={ - category="no", - direction="on", - }, - [0x2472]={ - category="no", - direction="on", - }, - [0x2473]={ - category="no", - direction="on", - }, - [0x2474]={ - category="no", - direction="on", - }, - [0x2475]={ - category="no", - direction="on", - }, - [0x2476]={ - category="no", - direction="on", - }, - [0x2477]={ - category="no", - direction="on", - }, - [0x2478]={ - category="no", - direction="on", - }, - [0x2479]={ - category="no", - direction="on", - }, - [0x247A]={ - category="no", - direction="on", - }, - [0x247B]={ - category="no", - direction="on", - }, - [0x247C]={ - category="no", - direction="on", - }, - [0x247D]={ - category="no", - direction="on", - }, - [0x247E]={ - category="no", - direction="on", - }, - [0x247F]={ - category="no", - direction="on", - }, - [0x2480]={ - category="no", - direction="on", - }, - [0x2481]={ - category="no", - direction="on", - }, - [0x2482]={ - category="no", - direction="on", - }, - [0x2483]={ - category="no", - direction="on", - }, - [0x2484]={ - category="no", - direction="on", - }, - [0x2485]={ - category="no", - direction="on", - }, - [0x2486]={ - category="no", - direction="on", - }, - [0x2487]={ - category="no", - direction="on", - }, - [0x2488]={ - category="no", - direction="en", - }, - [0x2489]={ - category="no", - direction="en", - }, - [0x248A]={ - category="no", - direction="en", - }, - [0x248B]={ - category="no", - direction="en", - }, - [0x248C]={ - category="no", - direction="en", - }, - [0x248D]={ - category="no", - direction="en", - }, - [0x248E]={ - category="no", - direction="en", - }, - [0x248F]={ - category="no", - direction="en", - }, - [0x2490]={ - category="no", - direction="en", - }, - [0x2491]={ - category="no", - direction="en", - }, - [0x2492]={ - category="no", - direction="en", - }, - [0x2493]={ - category="no", - direction="en", - }, - [0x2494]={ - category="no", - direction="en", - }, - [0x2495]={ - category="no", - direction="en", - }, - [0x2496]={ - category="no", - direction="en", - }, - [0x2497]={ - category="no", - direction="en", - }, - [0x2498]={ - category="no", - direction="en", - }, - [0x2499]={ - category="no", - direction="en", - }, - [0x249A]={ - category="no", - direction="en", - }, - [0x249B]={ - category="no", - direction="en", - }, - [0x249C]={ - category="so", - direction="l", - }, - [0x249D]={ - category="so", - direction="l", - }, - [0x249E]={ - category="so", - direction="l", - }, - [0x249F]={ - category="so", - direction="l", - }, - [0x24A0]={ - category="so", - direction="l", - }, - [0x24A1]={ - category="so", - direction="l", - }, - [0x24A2]={ - category="so", - direction="l", - }, - [0x24A3]={ - category="so", - direction="l", - }, - [0x24A4]={ - category="so", - direction="l", - }, - [0x24A5]={ - category="so", - direction="l", - }, - [0x24A6]={ - category="so", - direction="l", - }, - [0x24A7]={ - category="so", - direction="l", - }, - [0x24A8]={ - category="so", - direction="l", - }, - [0x24A9]={ - category="so", - direction="l", - }, - [0x24AA]={ - category="so", - direction="l", - }, - [0x24AB]={ - category="so", - direction="l", - }, - [0x24AC]={ - category="so", - direction="l", - }, - [0x24AD]={ - category="so", - direction="l", - }, - [0x24AE]={ - category="so", - direction="l", - }, - [0x24AF]={ - category="so", - direction="l", - }, - [0x24B0]={ - category="so", - direction="l", - }, - [0x24B1]={ - category="so", - direction="l", - }, - [0x24B2]={ - category="so", - direction="l", - }, - [0x24B3]={ - category="so", - direction="l", - }, - [0x24B4]={ - category="so", - direction="l", - }, - [0x24B5]={ - category="so", - direction="l", - }, - [0x24B6]={ - category="so", - direction="l", - }, - [0x24B7]={ - category="so", - direction="l", - }, - [0x24B8]={ - category="so", - direction="l", - }, - [0x24B9]={ - category="so", - direction="l", - }, - [0x24BA]={ - category="so", - direction="l", - }, - [0x24BB]={ - category="so", - direction="l", - }, - [0x24BC]={ - category="so", - direction="l", - }, - [0x24BD]={ - category="so", - direction="l", - }, - [0x24BE]={ - category="so", - direction="l", - }, - [0x24BF]={ - category="so", - direction="l", - }, - [0x24C0]={ - category="so", - direction="l", - }, - [0x24C1]={ - category="so", - direction="l", - }, - [0x24C2]={ - category="so", - direction="l", - }, - [0x24C3]={ - category="so", - direction="l", - }, - [0x24C4]={ - category="so", - direction="l", - }, - [0x24C5]={ - category="so", - direction="l", - }, - [0x24C6]={ - category="so", - direction="l", - }, - [0x24C7]={ - category="so", - direction="l", - }, - [0x24C8]={ - category="so", - direction="l", - }, - [0x24C9]={ - category="so", - direction="l", - }, - [0x24CA]={ - category="so", - direction="l", - }, - [0x24CB]={ - category="so", - direction="l", - }, - [0x24CC]={ - category="so", - direction="l", - }, - [0x24CD]={ - category="so", - direction="l", - }, - [0x24CE]={ - category="so", - direction="l", - }, - [0x24CF]={ - category="so", - direction="l", - }, - [0x24D0]={ - category="so", - direction="l", - }, - [0x24D1]={ - category="so", - direction="l", - }, - [0x24D2]={ - category="so", - direction="l", - }, - [0x24D3]={ - category="so", - direction="l", - }, - [0x24D4]={ - category="so", - direction="l", - }, - [0x24D5]={ - category="so", - direction="l", - }, - [0x24D6]={ - category="so", - direction="l", - }, - [0x24D7]={ - category="so", - direction="l", - }, - [0x24D8]={ - category="so", - direction="l", - }, - [0x24D9]={ - category="so", - direction="l", - }, - [0x24DA]={ - category="so", - direction="l", - }, - [0x24DB]={ - category="so", - direction="l", - }, - [0x24DC]={ - category="so", - direction="l", - }, - [0x24DD]={ - category="so", - direction="l", - }, - [0x24DE]={ - category="so", - direction="l", - }, - [0x24DF]={ - category="so", - direction="l", - }, - [0x24E0]={ - category="so", - direction="l", - }, - [0x24E1]={ - category="so", - direction="l", - }, - [0x24E2]={ - category="so", - direction="l", - }, - [0x24E3]={ - category="so", - direction="l", - }, - [0x24E4]={ - category="so", - direction="l", - }, - [0x24E5]={ - category="so", - direction="l", - }, - [0x24E6]={ - category="so", - direction="l", - }, - [0x24E7]={ - category="so", - direction="l", - }, - [0x24E8]={ - category="so", - direction="l", - }, - [0x24E9]={ - category="so", - direction="l", - }, - [0x24EA]={ - category="no", - direction="on", - }, - [0x24EB]={ - category="no", - direction="on", - }, - [0x24EC]={ - category="no", - direction="on", - }, - [0x24ED]={ - category="no", - direction="on", - }, - [0x24EE]={ - category="no", - direction="on", - }, - [0x24EF]={ - category="no", - direction="on", - }, - [0x24F0]={ - category="no", - direction="on", - }, - [0x24F1]={ - category="no", - direction="on", - }, - [0x24F2]={ - category="no", - direction="on", - }, - [0x24F3]={ - category="no", - direction="on", - }, - [0x24F4]={ - category="no", - direction="on", - }, - [0x24F5]={ - category="no", - direction="on", - }, - [0x24F6]={ - category="no", - direction="on", - }, - [0x24F7]={ - category="no", - direction="on", - }, - [0x24F8]={ - category="no", - direction="on", - }, - [0x24F9]={ - category="no", - direction="on", - }, - [0x24FA]={ - category="no", - direction="on", - }, - [0x24FB]={ - category="no", - direction="on", - }, - [0x24FC]={ - category="no", - direction="on", - }, - [0x24FD]={ - category="no", - direction="on", - }, - [0x24FE]={ - category="no", - direction="on", - }, - [0x24FF]={ - category="no", - direction="on", - }, - [0x2500]={ - category="so", - direction="on", - }, - [0x2501]={ - category="so", - direction="on", - }, - [0x2502]={ - category="so", - direction="on", - }, - [0x2503]={ - category="so", - direction="on", - }, - [0x2504]={ - category="so", - direction="on", - }, - [0x2505]={ - category="so", - direction="on", - }, - [0x2506]={ - category="so", - direction="on", - }, - [0x2507]={ - category="so", - direction="on", - }, - [0x2508]={ - category="so", - direction="on", - }, - [0x2509]={ - category="so", - direction="on", - }, - [0x250A]={ - category="so", - direction="on", - }, - [0x250B]={ - category="so", - direction="on", - }, - [0x250C]={ - category="so", - direction="on", - }, - [0x250D]={ - category="so", - direction="on", - }, - [0x250E]={ - category="so", - direction="on", - }, - [0x250F]={ - category="so", - direction="on", - }, - [0x2510]={ - category="so", - direction="on", - }, - [0x2511]={ - category="so", - direction="on", - }, - [0x2512]={ - category="so", - direction="on", - }, - [0x2513]={ - category="so", - direction="on", - }, - [0x2514]={ - category="so", - direction="on", - }, - [0x2515]={ - category="so", - direction="on", - }, - [0x2516]={ - category="so", - direction="on", - }, - [0x2517]={ - category="so", - direction="on", - }, - [0x2518]={ - category="so", - direction="on", - }, - [0x2519]={ - category="so", - direction="on", - }, - [0x251A]={ - category="so", - direction="on", - }, - [0x251B]={ - category="so", - direction="on", - }, - [0x251C]={ - category="so", - direction="on", - }, - [0x251D]={ - category="so", - direction="on", - }, - [0x251E]={ - category="so", - direction="on", - }, - [0x251F]={ - category="so", - direction="on", - }, - [0x2520]={ - category="so", - direction="on", - }, - [0x2521]={ - category="so", - direction="on", - }, - [0x2522]={ - category="so", - direction="on", - }, - [0x2523]={ - category="so", - direction="on", - }, - [0x2524]={ - category="so", - direction="on", - }, - [0x2525]={ - category="so", - direction="on", - }, - [0x2526]={ - category="so", - direction="on", - }, - [0x2527]={ - category="so", - direction="on", - }, - [0x2528]={ - category="so", - direction="on", - }, - [0x2529]={ - category="so", - direction="on", - }, - [0x252A]={ - category="so", - direction="on", - }, - [0x252B]={ - category="so", - direction="on", - }, - [0x252C]={ - category="so", - direction="on", - }, - [0x252D]={ - category="so", - direction="on", - }, - [0x252E]={ - category="so", - direction="on", - }, - [0x252F]={ - category="so", - direction="on", - }, - [0x2530]={ - category="so", - direction="on", - }, - [0x2531]={ - category="so", - direction="on", - }, - [0x2532]={ - category="so", - direction="on", - }, - [0x2533]={ - category="so", - direction="on", - }, - [0x2534]={ - category="so", - direction="on", - }, - [0x2535]={ - category="so", - direction="on", - }, - [0x2536]={ - category="so", - direction="on", - }, - [0x2537]={ - category="so", - direction="on", - }, - [0x2538]={ - category="so", - direction="on", - }, - [0x2539]={ - category="so", - direction="on", - }, - [0x253A]={ - category="so", - direction="on", - }, - [0x253B]={ - category="so", - direction="on", - }, - [0x253C]={ - category="so", - direction="on", - }, - [0x253D]={ - category="so", - direction="on", - }, - [0x253E]={ - category="so", - direction="on", - }, - [0x253F]={ - category="so", - direction="on", - }, - [0x2540]={ - category="so", - direction="on", - }, - [0x2541]={ - category="so", - direction="on", - }, - [0x2542]={ - category="so", - direction="on", - }, - [0x2543]={ - category="so", - direction="on", - }, - [0x2544]={ - category="so", - direction="on", - }, - [0x2545]={ - category="so", - direction="on", - }, - [0x2546]={ - category="so", - direction="on", - }, - [0x2547]={ - category="so", - direction="on", - }, - [0x2548]={ - category="so", - direction="on", - }, - [0x2549]={ - category="so", - direction="on", - }, - [0x254A]={ - category="so", - direction="on", - }, - [0x254B]={ - category="so", - direction="on", - }, - [0x254C]={ - category="so", - direction="on", - }, - [0x254D]={ - category="so", - direction="on", - }, - [0x254E]={ - category="so", - direction="on", - }, - [0x254F]={ - category="so", - direction="on", - }, - [0x2550]={ - category="so", - direction="on", - }, - [0x2551]={ - category="so", - direction="on", - }, - [0x2552]={ - category="so", - direction="on", - }, - [0x2553]={ - category="so", - direction="on", - }, - [0x2554]={ - category="so", - direction="on", - }, - [0x2555]={ - category="so", - direction="on", - }, - [0x2556]={ - category="so", - direction="on", - }, - [0x2557]={ - category="so", - direction="on", - }, - [0x2558]={ - category="so", - direction="on", - }, - [0x2559]={ - category="so", - direction="on", - }, - [0x255A]={ - category="so", - direction="on", - }, - [0x255B]={ - category="so", - direction="on", - }, - [0x255C]={ - category="so", - direction="on", - }, - [0x255D]={ - category="so", - direction="on", - }, - [0x255E]={ - category="so", - direction="on", - }, - [0x255F]={ - category="so", - direction="on", - }, - [0x2560]={ - category="so", - direction="on", - }, - [0x2561]={ - category="so", - direction="on", - }, - [0x2562]={ - category="so", - direction="on", - }, - [0x2563]={ - category="so", - direction="on", - }, - [0x2564]={ - category="so", - direction="on", - }, - [0x2565]={ - category="so", - direction="on", - }, - [0x2566]={ - category="so", - direction="on", - }, - [0x2567]={ - category="so", - direction="on", - }, - [0x2568]={ - category="so", - direction="on", - }, - [0x2569]={ - category="so", - direction="on", - }, - [0x256A]={ - category="so", - direction="on", - }, - [0x256B]={ - category="so", - direction="on", - }, - [0x256C]={ - category="so", - direction="on", - }, - [0x256D]={ - category="so", - direction="on", - }, - [0x256E]={ - category="so", - direction="on", - }, - [0x256F]={ - category="so", - direction="on", - }, - [0x2570]={ - category="so", - direction="on", - }, - [0x2571]={ - category="so", - direction="on", - }, - [0x2572]={ - category="so", - direction="on", - }, - [0x2573]={ - category="so", - direction="on", - }, - [0x2574]={ - category="so", - direction="on", - }, - [0x2575]={ - category="so", - direction="on", - }, - [0x2576]={ - category="so", - direction="on", - }, - [0x2577]={ - category="so", - direction="on", - }, - [0x2578]={ - category="so", - direction="on", - }, - [0x2579]={ - category="so", - direction="on", - }, - [0x257A]={ - category="so", - direction="on", - }, - [0x257B]={ - category="so", - direction="on", - }, - [0x257C]={ - category="so", - direction="on", - }, - [0x257D]={ - category="so", - direction="on", - }, - [0x257E]={ - category="so", - direction="on", - }, - [0x257F]={ - category="so", - direction="on", - }, - [0x2580]={ - category="so", - direction="on", - }, - [0x2581]={ - category="so", - direction="on", - }, - [0x2582]={ - category="so", - direction="on", - }, - [0x2583]={ - category="so", - direction="on", - }, - [0x2584]={ - category="so", - direction="on", - }, - [0x2585]={ - category="so", - direction="on", - }, - [0x2586]={ - category="so", - direction="on", - }, - [0x2587]={ - category="so", - direction="on", - }, - [0x2588]={ - category="so", - direction="on", - }, - [0x2589]={ - category="so", - direction="on", - }, - [0x258A]={ - category="so", - direction="on", - }, - [0x258B]={ - category="so", - direction="on", - }, - [0x258C]={ - category="so", - direction="on", - }, - [0x258D]={ - category="so", - direction="on", - }, - [0x258E]={ - category="so", - direction="on", - }, - [0x258F]={ - category="so", - direction="on", - }, - [0x2590]={ - category="so", - direction="on", - }, - [0x2591]={ - category="so", - direction="on", - }, - [0x2592]={ - category="so", - direction="on", - }, - [0x2593]={ - category="so", - direction="on", - }, - [0x2594]={ - category="so", - direction="on", - }, - [0x2595]={ - category="so", - direction="on", - }, - [0x2596]={ - category="so", - direction="on", - }, - [0x2597]={ - category="so", - direction="on", - }, - [0x2598]={ - category="so", - direction="on", - }, - [0x2599]={ - category="so", - direction="on", - }, - [0x259A]={ - category="so", - direction="on", - }, - [0x259B]={ - category="so", - direction="on", - }, - [0x259C]={ - category="so", - direction="on", - }, - [0x259D]={ - category="so", - direction="on", - }, - [0x259E]={ - category="so", - direction="on", - }, - [0x259F]={ - category="so", - direction="on", - }, - [0x25A0]={ - category="so", - direction="on", - }, - [0x25A1]={ - category="so", - direction="on", - }, - [0x25A2]={ - category="so", - direction="on", - }, - [0x25A3]={ - category="so", - direction="on", - }, - [0x25A4]={ - category="so", - direction="on", - }, - [0x25A5]={ - category="so", - direction="on", - }, - [0x25A6]={ - category="so", - direction="on", - }, - [0x25A7]={ - category="so", - direction="on", - }, - [0x25A8]={ - category="so", - direction="on", - }, - [0x25A9]={ - category="so", - direction="on", - }, - [0x25AA]={ - category="so", - direction="on", - }, - [0x25AB]={ - category="so", - direction="on", - }, - [0x25AC]={ - category="so", - direction="on", - }, - [0x25AD]={ - category="so", - direction="on", - }, - [0x25AE]={ - category="so", - direction="on", - }, - [0x25AF]={ - category="so", - direction="on", - }, - [0x25B0]={ - category="so", - direction="on", - }, - [0x25B1]={ - category="so", - direction="on", - }, - [0x25B2]={ - category="so", - direction="on", - }, - [0x25B3]={ - category="so", - direction="on", - }, - [0x25B4]={ - category="so", - direction="on", - }, - [0x25B5]={ - category="so", - direction="on", - }, - [0x25B6]={ - category="so", - direction="on", - }, - [0x25B7]={ - category="sm", - direction="on", - }, - [0x25B8]={ - category="so", - direction="on", - }, - [0x25B9]={ - category="so", - direction="on", - }, - [0x25BA]={ - category="so", - direction="on", - }, - [0x25BB]={ - category="so", - direction="on", - }, - [0x25BC]={ - category="so", - direction="on", - }, - [0x25BD]={ - category="so", - direction="on", - }, - [0x25BE]={ - category="so", - direction="on", - }, - [0x25BF]={ - category="so", - direction="on", - }, - [0x25C0]={ - category="so", - direction="on", - }, - [0x25C1]={ - category="sm", - direction="on", - }, - [0x25C2]={ - category="so", - direction="on", - }, - [0x25C3]={ - category="so", - direction="on", - }, - [0x25C4]={ - category="so", - direction="on", - }, - [0x25C5]={ - category="so", - direction="on", - }, - [0x25C6]={ - category="so", - direction="on", - }, - [0x25C7]={ - category="so", - direction="on", - }, - [0x25C8]={ - category="so", - direction="on", - }, - [0x25C9]={ - category="so", - direction="on", - }, - [0x25CA]={ - category="so", - direction="on", - }, - [0x25CB]={ - category="so", - direction="on", - }, - [0x25CC]={ - category="so", - direction="on", - }, - [0x25CD]={ - category="so", - direction="on", - }, - [0x25CE]={ - category="so", - direction="on", - }, - [0x25CF]={ - category="so", - direction="on", - }, - [0x25D0]={ - category="so", - direction="on", - }, - [0x25D1]={ - category="so", - direction="on", - }, - [0x25D2]={ - category="so", - direction="on", - }, - [0x25D3]={ - category="so", - direction="on", - }, - [0x25D4]={ - category="so", - direction="on", - }, - [0x25D5]={ - category="so", - direction="on", - }, - [0x25D6]={ - category="so", - direction="on", - }, - [0x25D7]={ - category="so", - direction="on", - }, - [0x25D8]={ - category="so", - direction="on", - }, - [0x25D9]={ - category="so", - direction="on", - }, - [0x25DA]={ - category="so", - direction="on", - }, - [0x25DB]={ - category="so", - direction="on", - }, - [0x25DC]={ - category="so", - direction="on", - }, - [0x25DD]={ - category="so", - direction="on", - }, - [0x25DE]={ - category="so", - direction="on", - }, - [0x25DF]={ - category="so", - direction="on", - }, - [0x25E0]={ - category="so", - direction="on", - }, - [0x25E1]={ - category="so", - direction="on", - }, - [0x25E2]={ - category="so", - direction="on", - }, - [0x25E3]={ - category="so", - direction="on", - }, - [0x25E4]={ - category="so", - direction="on", - }, - [0x25E5]={ - category="so", - direction="on", - }, - [0x25E6]={ - category="so", - direction="on", - }, - [0x25E7]={ - category="so", - direction="on", - }, - [0x25E8]={ - category="so", - direction="on", - }, - [0x25E9]={ - category="so", - direction="on", - }, - [0x25EA]={ - category="so", - direction="on", - }, - [0x25EB]={ - category="so", - direction="on", - }, - [0x25EC]={ - category="so", - direction="on", - }, - [0x25ED]={ - category="so", - direction="on", - }, - [0x25EE]={ - category="so", - direction="on", - }, - [0x25EF]={ - category="so", - direction="on", - }, - [0x25F0]={ - category="so", - direction="on", - }, - [0x25F1]={ - category="so", - direction="on", - }, - [0x25F2]={ - category="so", - direction="on", - }, - [0x25F3]={ - category="so", - direction="on", - }, - [0x25F4]={ - category="so", - direction="on", - }, - [0x25F5]={ - category="so", - direction="on", - }, - [0x25F6]={ - category="so", - direction="on", - }, - [0x25F7]={ - category="so", - direction="on", - }, - [0x25F8]={ - category="sm", - direction="on", - }, - [0x25F9]={ - category="sm", - direction="on", - }, - [0x25FA]={ - category="sm", - direction="on", - }, - [0x25FB]={ - category="sm", - direction="on", - }, - [0x25FC]={ - category="sm", - direction="on", - }, - [0x25FD]={ - category="sm", - direction="on", - }, - [0x25FE]={ - category="sm", - direction="on", - }, - [0x25FF]={ - category="sm", - direction="on", - }, - [0x2600]={ - category="so", - direction="on", - }, - [0x2601]={ - category="so", - direction="on", - }, - [0x2602]={ - category="so", - direction="on", - }, - [0x2603]={ - category="so", - direction="on", - }, - [0x2604]={ - category="so", - direction="on", - }, - [0x2605]={ - category="so", - direction="on", - }, - [0x2606]={ - category="so", - direction="on", - }, - [0x2607]={ - category="so", - direction="on", - }, - [0x2608]={ - category="so", - direction="on", - }, - [0x2609]={ - category="so", - direction="on", - }, - [0x260A]={ - category="so", - direction="on", - }, - [0x260B]={ - category="so", - direction="on", - }, - [0x260C]={ - category="so", - direction="on", - }, - [0x260D]={ - category="so", - direction="on", - }, - [0x260E]={ - category="so", - direction="on", - }, - [0x260F]={ - category="so", - direction="on", - }, - [0x2610]={ - category="so", - direction="on", - }, - [0x2611]={ - category="so", - direction="on", - }, - [0x2612]={ - category="so", - direction="on", - }, - [0x2613]={ - category="so", - direction="on", - }, - [0x2614]={ - category="so", - direction="on", - }, - [0x2615]={ - category="so", - direction="on", - }, - [0x2616]={ - category="so", - direction="on", - }, - [0x2617]={ - category="so", - direction="on", - }, - [0x2618]={ - category="so", - direction="on", - }, - [0x2619]={ - category="so", - direction="on", - }, - [0x261A]={ - category="so", - direction="on", - }, - [0x261B]={ - category="so", - direction="on", - }, - [0x261C]={ - category="so", - direction="on", - }, - [0x261D]={ - category="so", - direction="on", - }, - [0x261E]={ - category="so", - direction="on", - }, - [0x261F]={ - category="so", - direction="on", - }, - [0x2620]={ - category="so", - direction="on", - }, - [0x2621]={ - category="so", - direction="on", - }, - [0x2622]={ - category="so", - direction="on", - }, - [0x2623]={ - category="so", - direction="on", - }, - [0x2624]={ - category="so", - direction="on", - }, - [0x2625]={ - category="so", - direction="on", - }, - [0x2626]={ - category="so", - direction="on", - }, - [0x2627]={ - category="so", - direction="on", - }, - [0x2628]={ - category="so", - direction="on", - }, - [0x2629]={ - category="so", - direction="on", - }, - [0x262A]={ - category="so", - direction="on", - }, - [0x262B]={ - category="so", - direction="on", - }, - [0x262C]={ - category="so", - direction="on", - }, - [0x262D]={ - category="so", - direction="on", - }, - [0x262E]={ - category="so", - direction="on", - }, - [0x262F]={ - category="so", - direction="on", - }, - [0x2630]={ - category="so", - direction="on", - }, - [0x2631]={ - category="so", - direction="on", - }, - [0x2632]={ - category="so", - direction="on", - }, - [0x2633]={ - category="so", - direction="on", - }, - [0x2634]={ - category="so", - direction="on", - }, - [0x2635]={ - category="so", - direction="on", - }, - [0x2636]={ - category="so", - direction="on", - }, - [0x2637]={ - category="so", - direction="on", - }, - [0x2638]={ - category="so", - direction="on", - }, - [0x2639]={ - category="so", - direction="on", - }, - [0x263A]={ - category="so", - direction="on", - }, - [0x263B]={ - category="so", - direction="on", - }, - [0x263C]={ - category="so", - direction="on", - }, - [0x263D]={ - category="so", - direction="on", - }, - [0x263E]={ - category="so", - direction="on", - }, - [0x263F]={ - category="so", - direction="on", - }, - [0x2640]={ - category="so", - direction="on", - }, - [0x2641]={ - category="so", - direction="on", - }, - [0x2642]={ - category="so", - direction="on", - }, - [0x2643]={ - category="so", - direction="on", - }, - [0x2644]={ - category="so", - direction="on", - }, - [0x2645]={ - category="so", - direction="on", - }, - [0x2646]={ - category="so", - direction="on", - }, - [0x2647]={ - category="so", - direction="on", - }, - [0x2648]={ - category="so", - direction="on", - }, - [0x2649]={ - category="so", - direction="on", - }, - [0x264A]={ - category="so", - direction="on", - }, - [0x264B]={ - category="so", - direction="on", - }, - [0x264C]={ - category="so", - direction="on", - }, - [0x264D]={ - category="so", - direction="on", - }, - [0x264E]={ - category="so", - direction="on", - }, - [0x264F]={ - category="so", - direction="on", - }, - [0x2650]={ - category="so", - direction="on", - }, - [0x2651]={ - category="so", - direction="on", - }, - [0x2652]={ - category="so", - direction="on", - }, - [0x2653]={ - category="so", - direction="on", - }, - [0x2654]={ - category="so", - direction="on", - }, - [0x2655]={ - category="so", - direction="on", - }, - [0x2656]={ - category="so", - direction="on", - }, - [0x2657]={ - category="so", - direction="on", - }, - [0x2658]={ - category="so", - direction="on", - }, - [0x2659]={ - category="so", - direction="on", - }, - [0x265A]={ - category="so", - direction="on", - }, - [0x265B]={ - category="so", - direction="on", - }, - [0x265C]={ - category="so", - direction="on", - }, - [0x265D]={ - category="so", - direction="on", - }, - [0x265E]={ - category="so", - direction="on", - }, - [0x265F]={ - category="so", - direction="on", - }, - [0x2660]={ - category="so", - direction="on", - }, - [0x2661]={ - category="so", - direction="on", - }, - [0x2662]={ - category="so", - direction="on", - }, - [0x2663]={ - category="so", - direction="on", - }, - [0x2664]={ - category="so", - direction="on", - }, - [0x2665]={ - category="so", - direction="on", - }, - [0x2666]={ - category="so", - direction="on", - }, - [0x2667]={ - category="so", - direction="on", - }, - [0x2668]={ - category="so", - direction="on", - }, - [0x2669]={ - category="so", - direction="on", - }, - [0x266A]={ - category="so", - direction="on", - }, - [0x266B]={ - category="so", - direction="on", - }, - [0x266C]={ - category="so", - direction="on", - }, - [0x266D]={ - category="so", - direction="on", - }, - [0x266E]={ - category="so", - direction="on", - }, - [0x266F]={ - category="sm", - direction="on", - }, - [0x2670]={ - category="so", - direction="on", - }, - [0x2671]={ - category="so", - direction="on", - }, - [0x2672]={ - category="so", - direction="on", - }, - [0x2673]={ - category="so", - direction="on", - }, - [0x2674]={ - category="so", - direction="on", - }, - [0x2675]={ - category="so", - direction="on", - }, - [0x2676]={ - category="so", - direction="on", - }, - [0x2677]={ - category="so", - direction="on", - }, - [0x2678]={ - category="so", - direction="on", - }, - [0x2679]={ - category="so", - direction="on", - }, - [0x267A]={ - category="so", - direction="on", - }, - [0x267B]={ - category="so", - direction="on", - }, - [0x267C]={ - category="so", - direction="on", - }, - [0x267D]={ - category="so", - direction="on", - }, - [0x267E]={ - category="so", - direction="on", - }, - [0x267F]={ - category="so", - direction="on", - }, - [0x2680]={ - category="so", - direction="on", - }, - [0x2681]={ - category="so", - direction="on", - }, - [0x2682]={ - category="so", - direction="on", - }, - [0x2683]={ - category="so", - direction="on", - }, - [0x2684]={ - category="so", - direction="on", - }, - [0x2685]={ - category="so", - direction="on", - }, - [0x2686]={ - category="so", - direction="on", - }, - [0x2687]={ - category="so", - direction="on", - }, - [0x2688]={ - category="so", - direction="on", - }, - [0x2689]={ - category="so", - direction="on", - }, - [0x268A]={ - category="so", - direction="on", - }, - [0x268B]={ - category="so", - direction="on", - }, - [0x268C]={ - category="so", - direction="on", - }, - [0x268D]={ - category="so", - direction="on", - }, - [0x268E]={ - category="so", - direction="on", - }, - [0x268F]={ - category="so", - direction="on", - }, - [0x2690]={ - category="so", - direction="on", - }, - [0x2691]={ - category="so", - direction="on", - }, - [0x2692]={ - category="so", - direction="on", - }, - [0x2693]={ - category="so", - direction="on", - }, - [0x2694]={ - category="so", - direction="on", - }, - [0x2695]={ - category="so", - direction="on", - }, - [0x2696]={ - category="so", - direction="on", - }, - [0x2697]={ - category="so", - direction="on", - }, - [0x2698]={ - category="so", - direction="on", - }, - [0x2699]={ - category="so", - direction="on", - }, - [0x269A]={ - category="so", - direction="on", - }, - [0x269B]={ - category="so", - direction="on", - }, - [0x269C]={ - category="so", - direction="on", - }, - [0x269D]={ - category="so", - direction="on", - }, - [0x269E]={ - category="so", - direction="on", - }, - [0x269F]={ - category="so", - direction="on", - }, - [0x26A0]={ - category="so", - direction="on", - }, - [0x26A1]={ - category="so", - direction="on", - }, - [0x26A2]={ - category="so", - direction="on", - }, - [0x26A3]={ - category="so", - direction="on", - }, - [0x26A4]={ - category="so", - direction="on", - }, - [0x26A5]={ - category="so", - direction="on", - }, - [0x26A6]={ - category="so", - direction="on", - }, - [0x26A7]={ - category="so", - direction="on", - }, - [0x26A8]={ - category="so", - direction="on", - }, - [0x26A9]={ - category="so", - direction="on", - }, - [0x26AA]={ - category="so", - direction="on", - }, - [0x26AB]={ - category="so", - direction="on", - }, - [0x26AC]={ - category="so", - direction="l", - }, - [0x26AD]={ - category="so", - direction="on", - }, - [0x26AE]={ - category="so", - direction="on", - }, - [0x26AF]={ - category="so", - direction="on", - }, - [0x26B0]={ - category="so", - direction="on", - }, - [0x26B1]={ - category="so", - direction="on", - }, - [0x26B2]={ - category="so", - direction="on", - }, - [0x26B3]={ - category="so", - direction="on", - }, - [0x26B4]={ - category="so", - direction="on", - }, - [0x26B5]={ - category="so", - direction="on", - }, - [0x26B6]={ - category="so", - direction="on", - }, - [0x26B7]={ - category="so", - direction="on", - }, - [0x26B8]={ - category="so", - direction="on", - }, - [0x26B9]={ - category="so", - direction="on", - }, - [0x26BA]={ - category="so", - direction="on", - }, - [0x26BB]={ - category="so", - direction="on", - }, - [0x26BC]={ - category="so", - direction="on", - }, - [0x26BD]={ - category="so", - direction="on", - }, - [0x26BE]={ - category="so", - direction="on", - }, - [0x26BF]={ - category="so", - direction="on", - }, - [0x26C0]={ - category="so", - direction="on", - }, - [0x26C1]={ - category="so", - direction="on", - }, - [0x26C2]={ - category="so", - direction="on", - }, - [0x26C3]={ - category="so", - direction="on", - }, - [0x26C4]={ - category="so", - direction="on", - }, - [0x26C5]={ - category="so", - direction="on", - }, - [0x26C6]={ - category="so", - direction="on", - }, - [0x26C7]={ - category="so", - direction="on", - }, - [0x26C8]={ - category="so", - direction="on", - }, - [0x26C9]={ - category="so", - direction="on", - }, - [0x26CA]={ - category="so", - direction="on", - }, - [0x26CB]={ - category="so", - direction="on", - }, - [0x26CC]={ - category="so", - direction="on", - }, - [0x26CD]={ - category="so", - direction="on", - }, - [0x26CE]={ - category="so", - direction="on", - }, - [0x26CF]={ - category="so", - direction="on", - }, - [0x26D0]={ - category="so", - direction="on", - }, - [0x26D1]={ - category="so", - direction="on", - }, - [0x26D2]={ - category="so", - direction="on", - }, - [0x26D3]={ - category="so", - direction="on", - }, - [0x26D4]={ - category="so", - direction="on", - }, - [0x26D5]={ - category="so", - direction="on", - }, - [0x26D6]={ - category="so", - direction="on", - }, - [0x26D7]={ - category="so", - direction="on", - }, - [0x26D8]={ - category="so", - direction="on", - }, - [0x26D9]={ - category="so", - direction="on", - }, - [0x26DA]={ - category="so", - direction="on", - }, - [0x26DB]={ - category="so", - direction="on", - }, - [0x26DC]={ - category="so", - direction="on", - }, - [0x26DD]={ - category="so", - direction="on", - }, - [0x26DE]={ - category="so", - direction="on", - }, - [0x26DF]={ - category="so", - direction="on", - }, - [0x26E0]={ - category="so", - direction="on", - }, - [0x26E1]={ - category="so", - direction="on", - }, - [0x26E2]={ - category="so", - direction="on", - }, - [0x26E3]={ - category="so", - direction="on", - }, - [0x26E4]={ - category="so", - direction="on", - }, - [0x26E5]={ - category="so", - direction="on", - }, - [0x26E6]={ - category="so", - direction="on", - }, - [0x26E7]={ - category="so", - direction="on", - }, - [0x26E8]={ - category="so", - direction="on", - }, - [0x26E9]={ - category="so", - direction="on", - }, - [0x26EA]={ - category="so", - direction="on", - }, - [0x26EB]={ - category="so", - direction="on", - }, - [0x26EC]={ - category="so", - direction="on", - }, - [0x26ED]={ - category="so", - direction="on", - }, - [0x26EE]={ - category="so", - direction="on", - }, - [0x26EF]={ - category="so", - direction="on", - }, - [0x26F0]={ - category="so", - direction="on", - }, - [0x26F1]={ - category="so", - direction="on", - }, - [0x26F2]={ - category="so", - direction="on", - }, - [0x26F3]={ - category="so", - direction="on", - }, - [0x26F4]={ - category="so", - direction="on", - }, - [0x26F5]={ - category="so", - direction="on", - }, - [0x26F6]={ - category="so", - direction="on", - }, - [0x26F7]={ - category="so", - direction="on", - }, - [0x26F8]={ - category="so", - direction="on", - }, - [0x26F9]={ - category="so", - direction="on", - }, - [0x26FA]={ - category="so", - direction="on", - }, - [0x26FB]={ - category="so", - direction="on", - }, - [0x26FC]={ - category="so", - direction="on", - }, - [0x26FD]={ - category="so", - direction="on", - }, - [0x26FE]={ - category="so", - direction="on", - }, - [0x26FF]={ - category="so", - direction="on", - }, - [0x2700]={ - category="so", - direction="on", - }, - [0x2701]={ - category="so", - direction="on", - }, - [0x2702]={ - category="so", - direction="on", - }, - [0x2703]={ - category="so", - direction="on", - }, - [0x2704]={ - category="so", - direction="on", - }, - [0x2705]={ - category="so", - direction="on", - }, - [0x2706]={ - category="so", - direction="on", - }, - [0x2707]={ - category="so", - direction="on", - }, - [0x2708]={ - category="so", - direction="on", - }, - [0x2709]={ - category="so", - direction="on", - }, - [0x270A]={ - category="so", - direction="on", - }, - [0x270B]={ - category="so", - direction="on", - }, - [0x270C]={ - category="so", - direction="on", - }, - [0x270D]={ - category="so", - direction="on", - }, - [0x270E]={ - category="so", - direction="on", - }, - [0x270F]={ - category="so", - direction="on", - }, - [0x2710]={ - category="so", - direction="on", - }, - [0x2711]={ - category="so", - direction="on", - }, - [0x2712]={ - category="so", - direction="on", - }, - [0x2713]={ - category="so", - direction="on", - }, - [0x2714]={ - category="so", - direction="on", - }, - [0x2715]={ - category="so", - direction="on", - }, - [0x2716]={ - category="so", - direction="on", - }, - [0x2717]={ - category="so", - direction="on", - }, - [0x2718]={ - category="so", - direction="on", - }, - [0x2719]={ - category="so", - direction="on", - }, - [0x271A]={ - category="so", - direction="on", - }, - [0x271B]={ - category="so", - direction="on", - }, - [0x271C]={ - category="so", - direction="on", - }, - [0x271D]={ - category="so", - direction="on", - }, - [0x271E]={ - category="so", - direction="on", - }, - [0x271F]={ - category="so", - direction="on", - }, - [0x2720]={ - category="so", - direction="on", - }, - [0x2721]={ - category="so", - direction="on", - }, - [0x2722]={ - category="so", - direction="on", - }, - [0x2723]={ - category="so", - direction="on", - }, - [0x2724]={ - category="so", - direction="on", - }, - [0x2725]={ - category="so", - direction="on", - }, - [0x2726]={ - category="so", - direction="on", - }, - [0x2727]={ - category="so", - direction="on", - }, - [0x2728]={ - category="so", - direction="on", - }, - [0x2729]={ - category="so", - direction="on", - }, - [0x272A]={ - category="so", - direction="on", - }, - [0x272B]={ - category="so", - direction="on", - }, - [0x272C]={ - category="so", - direction="on", - }, - [0x272D]={ - category="so", - direction="on", - }, - [0x272E]={ - category="so", - direction="on", - }, - [0x272F]={ - category="so", - direction="on", - }, - [0x2730]={ - category="so", - direction="on", - }, - [0x2731]={ - category="so", - direction="on", - }, - [0x2732]={ - category="so", - direction="on", - }, - [0x2733]={ - category="so", - direction="on", - }, - [0x2734]={ - category="so", - direction="on", - }, - [0x2735]={ - category="so", - direction="on", - }, - [0x2736]={ - category="so", - direction="on", - }, - [0x2737]={ - category="so", - direction="on", - }, - [0x2738]={ - category="so", - direction="on", - }, - [0x2739]={ - category="so", - direction="on", - }, - [0x273A]={ - category="so", - direction="on", - }, - [0x273B]={ - category="so", - direction="on", - }, - [0x273C]={ - category="so", - direction="on", - }, - [0x273D]={ - category="so", - direction="on", - }, - [0x273E]={ - category="so", - direction="on", - }, - [0x273F]={ - category="so", - direction="on", - }, - [0x2740]={ - category="so", - direction="on", - }, - [0x2741]={ - category="so", - direction="on", - }, - [0x2742]={ - category="so", - direction="on", - }, - [0x2743]={ - category="so", - direction="on", - }, - [0x2744]={ - category="so", - direction="on", - }, - [0x2745]={ - category="so", - direction="on", - }, - [0x2746]={ - category="so", - direction="on", - }, - [0x2747]={ - category="so", - direction="on", - }, - [0x2748]={ - category="so", - direction="on", - }, - [0x2749]={ - category="so", - direction="on", - }, - [0x274A]={ - category="so", - direction="on", - }, - [0x274B]={ - category="so", - direction="on", - }, - [0x274C]={ - category="so", - direction="on", - }, - [0x274D]={ - category="so", - direction="on", - }, - [0x274E]={ - category="so", - direction="on", - }, - [0x274F]={ - category="so", - direction="on", - }, - [0x2750]={ - category="so", - direction="on", - }, - [0x2751]={ - category="so", - direction="on", - }, - [0x2752]={ - category="so", - direction="on", - }, - [0x2753]={ - category="so", - direction="on", - }, - [0x2754]={ - category="so", - direction="on", - }, - [0x2755]={ - category="so", - direction="on", - }, - [0x2756]={ - category="so", - direction="on", - }, - [0x2757]={ - category="so", - direction="on", - }, - [0x2758]={ - category="so", - direction="on", - }, - [0x2759]={ - category="so", - direction="on", - }, - [0x275A]={ - category="so", - direction="on", - }, - [0x275B]={ - category="so", - direction="on", - }, - [0x275C]={ - category="so", - direction="on", - }, - [0x275D]={ - category="so", - direction="on", - }, - [0x275E]={ - category="so", - direction="on", - }, - [0x275F]={ - category="so", - direction="on", - }, - [0x2760]={ - category="so", - direction="on", - }, - [0x2761]={ - category="so", - direction="on", - }, - [0x2762]={ - category="so", - direction="on", - }, - [0x2763]={ - category="so", - direction="on", - }, - [0x2764]={ - category="so", - direction="on", - }, - [0x2765]={ - category="so", - direction="on", - }, - [0x2766]={ - category="so", - direction="on", - }, - [0x2767]={ - category="so", - direction="on", - }, - [0x2768]={ - category="ps", - direction="on", - mirror=0x2769, - }, - [0x2769]={ - category="pe", - direction="on", - mirror=0x2768, - }, - [0x276A]={ - category="ps", - direction="on", - mirror=0x276B, - }, - [0x276B]={ - category="pe", - direction="on", - mirror=0x276A, - }, - [0x276C]={ - category="ps", - direction="on", - mirror=0x276D, - }, - [0x276D]={ - category="pe", - direction="on", - mirror=0x276C, - }, - [0x276E]={ - category="ps", - direction="on", - mirror=0x276F, - }, - [0x276F]={ - category="pe", - direction="on", - mirror=0x276E, - }, - [0x2770]={ - category="ps", - direction="on", - mirror=0x2771, - }, - [0x2771]={ - category="pe", - direction="on", - mirror=0x2770, - }, - [0x2772]={ - category="ps", - direction="on", - mirror=0x2773, - }, - [0x2773]={ - category="pe", - direction="on", - mirror=0x2772, - }, - [0x2774]={ - category="ps", - direction="on", - mirror=0x2775, - }, - [0x2775]={ - category="pe", - direction="on", - mirror=0x2774, - }, - [0x2776]={ - category="no", - direction="on", - }, - [0x2777]={ - category="no", - direction="on", - }, - [0x2778]={ - category="no", - direction="on", - }, - [0x2779]={ - category="no", - direction="on", - }, - [0x277A]={ - category="no", - direction="on", - }, - [0x277B]={ - category="no", - direction="on", - }, - [0x277C]={ - category="no", - direction="on", - }, - [0x277D]={ - category="no", - direction="on", - }, - [0x277E]={ - category="no", - direction="on", - }, - [0x277F]={ - category="no", - direction="on", - }, - [0x2780]={ - category="no", - direction="on", - }, - [0x2781]={ - category="no", - direction="on", - }, - [0x2782]={ - category="no", - direction="on", - }, - [0x2783]={ - category="no", - direction="on", - }, - [0x2784]={ - category="no", - direction="on", - }, - [0x2785]={ - category="no", - direction="on", - }, - [0x2786]={ - category="no", - direction="on", - }, - [0x2787]={ - category="no", - direction="on", - }, - [0x2788]={ - category="no", - direction="on", - }, - [0x2789]={ - category="no", - direction="on", - }, - [0x278A]={ - category="no", - direction="on", - }, - [0x278B]={ - category="no", - direction="on", - }, - [0x278C]={ - category="no", - direction="on", - }, - [0x278D]={ - category="no", - direction="on", - }, - [0x278E]={ - category="no", - direction="on", - }, - [0x278F]={ - category="no", - direction="on", - }, - [0x2790]={ - category="no", - direction="on", - }, - [0x2791]={ - category="no", - direction="on", - }, - [0x2792]={ - category="no", - direction="on", - }, - [0x2793]={ - category="no", - direction="on", - }, - [0x2794]={ - category="so", - direction="on", - }, - [0x2795]={ - category="so", - direction="on", - }, - [0x2796]={ - category="so", - direction="on", - }, - [0x2797]={ - category="so", - direction="on", - }, - [0x2798]={ - category="so", - direction="on", - }, - [0x2799]={ - category="so", - direction="on", - }, - [0x279A]={ - category="so", - direction="on", - }, - [0x279B]={ - category="so", - direction="on", - }, - [0x279C]={ - category="so", - direction="on", - }, - [0x279D]={ - category="so", - direction="on", - }, - [0x279E]={ - category="so", - direction="on", - }, - [0x279F]={ - category="so", - direction="on", - }, - [0x27A0]={ - category="so", - direction="on", - }, - [0x27A1]={ - category="so", - direction="on", - }, - [0x27A2]={ - category="so", - direction="on", - }, - [0x27A3]={ - category="so", - direction="on", - }, - [0x27A4]={ - category="so", - direction="on", - }, - [0x27A5]={ - category="so", - direction="on", - }, - [0x27A6]={ - category="so", - direction="on", - }, - [0x27A7]={ - category="so", - direction="on", - }, - [0x27A8]={ - category="so", - direction="on", - }, - [0x27A9]={ - category="so", - direction="on", - }, - [0x27AA]={ - category="so", - direction="on", - }, - [0x27AB]={ - category="so", - direction="on", - }, - [0x27AC]={ - category="so", - direction="on", - }, - [0x27AD]={ - category="so", - direction="on", - }, - [0x27AE]={ - category="so", - direction="on", - }, - [0x27AF]={ - category="so", - direction="on", - }, - [0x27B0]={ - category="so", - direction="on", - }, - [0x27B1]={ - category="so", - direction="on", - }, - [0x27B2]={ - category="so", - direction="on", - }, - [0x27B3]={ - category="so", - direction="on", - }, - [0x27B4]={ - category="so", - direction="on", - }, - [0x27B5]={ - category="so", - direction="on", - }, - [0x27B6]={ - category="so", - direction="on", - }, - [0x27B7]={ - category="so", - direction="on", - }, - [0x27B8]={ - category="so", - direction="on", - }, - [0x27B9]={ - category="so", - direction="on", - }, - [0x27BA]={ - category="so", - direction="on", - }, - [0x27BB]={ - category="so", - direction="on", - }, - [0x27BC]={ - category="so", - direction="on", - }, - [0x27BD]={ - category="so", - direction="on", - }, - [0x27BE]={ - category="so", - direction="on", - }, - [0x27BF]={ - category="so", - direction="on", - }, - [0x27C0]={ - category="sm", - direction="on", - }, - [0x27C1]={ - category="sm", - direction="on", - }, - [0x27C2]={ - category="sm", - direction="on", - }, - [0x27C3]={ - category="sm", - direction="on", - mirror=0x27C4, - }, - [0x27C4]={ - category="sm", - direction="on", - mirror=0x27C3, - }, - [0x27C5]={ - category="ps", - direction="on", - mirror=0x27C6, - }, - [0x27C6]={ - category="pe", - direction="on", - mirror=0x27C5, - }, - [0x27C7]={ - category="sm", - direction="on", - }, - [0x27C8]={ - category="sm", - direction="on", - mirror=0x27C9, - }, - [0x27C9]={ - category="sm", - direction="on", - mirror=0x27C8, - }, - [0x27CA]={ - category="sm", - direction="on", - }, - [0x27CB]={ - category="sm", - direction="on", - mirror=0x27CD, - }, - [0x27CC]={ - category="sm", - direction="on", - }, - [0x27CD]={ - category="sm", - direction="on", - mirror=0x27CB, - }, - [0x27CE]={ - category="sm", - direction="on", - }, - [0x27CF]={ - category="sm", - direction="on", - }, - [0x27D0]={ - category="sm", - direction="on", - }, - [0x27D1]={ - category="sm", - direction="on", - }, - [0x27D2]={ - category="sm", - direction="on", - }, - [0x27D3]={ - category="sm", - direction="on", - }, - [0x27D4]={ - category="sm", - direction="on", - }, - [0x27D5]={ - category="sm", - direction="on", - mirror=0x27D6, - }, - [0x27D6]={ - category="sm", - direction="on", - mirror=0x27D5, - }, - [0x27D7]={ - category="sm", - direction="on", - }, - [0x27D8]={ - category="sm", - direction="on", - }, - [0x27D9]={ - category="sm", - direction="on", - }, - [0x27DA]={ - category="sm", - direction="on", - }, - [0x27DB]={ - category="sm", - direction="on", - }, - [0x27DC]={ - category="sm", - direction="on", - }, - [0x27DD]={ - category="sm", - direction="on", - mirror=0x27DE, - }, - [0x27DE]={ - category="sm", - direction="on", - mirror=0x27DD, - }, - [0x27DF]={ - category="sm", - direction="on", - }, - [0x27E0]={ - category="sm", - direction="on", - }, - [0x27E1]={ - category="sm", - direction="on", - }, - [0x27E2]={ - category="sm", - direction="on", - mirror=0x27E3, - }, - [0x27E3]={ - category="sm", - direction="on", - mirror=0x27E2, - }, - [0x27E4]={ - category="sm", - direction="on", - mirror=0x27E5, - }, - [0x27E5]={ - category="sm", - direction="on", - mirror=0x27E4, - }, - [0x27E6]={ - category="ps", - direction="on", - mirror=0x27E7, - }, - [0x27E7]={ - category="pe", - direction="on", - mirror=0x27E6, - }, - [0x27E8]={ - category="ps", - direction="on", - mirror=0x27E9, - }, - [0x27E9]={ - category="pe", - direction="on", - mirror=0x27E8, - }, - [0x27EA]={ - category="ps", - direction="on", - mirror=0x27EB, - }, - [0x27EB]={ - category="pe", - direction="on", - mirror=0x27EA, - }, - [0x27EC]={ - category="ps", - direction="on", - mirror=0x27ED, - }, - [0x27ED]={ - category="pe", - direction="on", - mirror=0x27EC, - }, - [0x27EE]={ - category="ps", - direction="on", - mirror=0x27EF, - }, - [0x27EF]={ - category="pe", - direction="on", - mirror=0x27EE, - }, - [0x27F0]={ - category="sm", - direction="on", - }, - [0x27F1]={ - category="sm", - direction="on", - }, - [0x27F2]={ - category="sm", - direction="on", - }, - [0x27F3]={ - category="sm", - direction="on", - }, - [0x27F4]={ - category="sm", - direction="on", - }, - [0x27F5]={ - category="sm", - direction="on", - }, - [0x27F6]={ - category="sm", - direction="on", - }, - [0x27F7]={ - category="sm", - direction="on", - }, - [0x27F8]={ - category="sm", - direction="on", - }, - [0x27F9]={ - category="sm", - direction="on", - }, - [0x27FA]={ - category="sm", - direction="on", - }, - [0x27FB]={ - category="sm", - direction="on", - }, - [0x27FC]={ - category="sm", - direction="on", - }, - [0x27FD]={ - category="sm", - direction="on", - }, - [0x27FE]={ - category="sm", - direction="on", - }, - [0x27FF]={ - category="sm", - direction="on", - }, - [0x2800]={ - category="so", - direction="l", - }, - [0x2801]={ - category="so", - direction="l", - }, - [0x2802]={ - category="so", - direction="l", - }, - [0x2803]={ - category="so", - direction="l", - }, - [0x2804]={ - category="so", - direction="l", - }, - [0x2805]={ - category="so", - direction="l", - }, - [0x2806]={ - category="so", - direction="l", - }, - [0x2807]={ - category="so", - direction="l", - }, - [0x2808]={ - category="so", - direction="l", - }, - [0x2809]={ - category="so", - direction="l", - }, - [0x280A]={ - category="so", - direction="l", - }, - [0x280B]={ - category="so", - direction="l", - }, - [0x280C]={ - category="so", - direction="l", - }, - [0x280D]={ - category="so", - direction="l", - }, - [0x280E]={ - category="so", - direction="l", - }, - [0x280F]={ - category="so", - direction="l", - }, - [0x2810]={ - category="so", - direction="l", - }, - [0x2811]={ - category="so", - direction="l", - }, - [0x2812]={ - category="so", - direction="l", - }, - [0x2813]={ - category="so", - direction="l", - }, - [0x2814]={ - category="so", - direction="l", - }, - [0x2815]={ - category="so", - direction="l", - }, - [0x2816]={ - category="so", - direction="l", - }, - [0x2817]={ - category="so", - direction="l", - }, - [0x2818]={ - category="so", - direction="l", - }, - [0x2819]={ - category="so", - direction="l", - }, - [0x281A]={ - category="so", - direction="l", - }, - [0x281B]={ - category="so", - direction="l", - }, - [0x281C]={ - category="so", - direction="l", - }, - [0x281D]={ - category="so", - direction="l", - }, - [0x281E]={ - category="so", - direction="l", - }, - [0x281F]={ - category="so", - direction="l", - }, - [0x2820]={ - category="so", - direction="l", - }, - [0x2821]={ - category="so", - direction="l", - }, - [0x2822]={ - category="so", - direction="l", - }, - [0x2823]={ - category="so", - direction="l", - }, - [0x2824]={ - category="so", - direction="l", - }, - [0x2825]={ - category="so", - direction="l", - }, - [0x2826]={ - category="so", - direction="l", - }, - [0x2827]={ - category="so", - direction="l", - }, - [0x2828]={ - category="so", - direction="l", - }, - [0x2829]={ - category="so", - direction="l", - }, - [0x282A]={ - category="so", - direction="l", - }, - [0x282B]={ - category="so", - direction="l", - }, - [0x282C]={ - category="so", - direction="l", - }, - [0x282D]={ - category="so", - direction="l", - }, - [0x282E]={ - category="so", - direction="l", - }, - [0x282F]={ - category="so", - direction="l", - }, - [0x2830]={ - category="so", - direction="l", - }, - [0x2831]={ - category="so", - direction="l", - }, - [0x2832]={ - category="so", - direction="l", - }, - [0x2833]={ - category="so", - direction="l", - }, - [0x2834]={ - category="so", - direction="l", - }, - [0x2835]={ - category="so", - direction="l", - }, - [0x2836]={ - category="so", - direction="l", - }, - [0x2837]={ - category="so", - direction="l", - }, - [0x2838]={ - category="so", - direction="l", - }, - [0x2839]={ - category="so", - direction="l", - }, - [0x283A]={ - category="so", - direction="l", - }, - [0x283B]={ - category="so", - direction="l", - }, - [0x283C]={ - category="so", - direction="l", - }, - [0x283D]={ - category="so", - direction="l", - }, - [0x283E]={ - category="so", - direction="l", - }, - [0x283F]={ - category="so", - direction="l", - }, - [0x2840]={ - category="so", - direction="l", - }, - [0x2841]={ - category="so", - direction="l", - }, - [0x2842]={ - category="so", - direction="l", - }, - [0x2843]={ - category="so", - direction="l", - }, - [0x2844]={ - category="so", - direction="l", - }, - [0x2845]={ - category="so", - direction="l", - }, - [0x2846]={ - category="so", - direction="l", - }, - [0x2847]={ - category="so", - direction="l", - }, - [0x2848]={ - category="so", - direction="l", - }, - [0x2849]={ - category="so", - direction="l", - }, - [0x284A]={ - category="so", - direction="l", - }, - [0x284B]={ - category="so", - direction="l", - }, - [0x284C]={ - category="so", - direction="l", - }, - [0x284D]={ - category="so", - direction="l", - }, - [0x284E]={ - category="so", - direction="l", - }, - [0x284F]={ - category="so", - direction="l", - }, - [0x2850]={ - category="so", - direction="l", - }, - [0x2851]={ - category="so", - direction="l", - }, - [0x2852]={ - category="so", - direction="l", - }, - [0x2853]={ - category="so", - direction="l", - }, - [0x2854]={ - category="so", - direction="l", - }, - [0x2855]={ - category="so", - direction="l", - }, - [0x2856]={ - category="so", - direction="l", - }, - [0x2857]={ - category="so", - direction="l", - }, - [0x2858]={ - category="so", - direction="l", - }, - [0x2859]={ - category="so", - direction="l", - }, - [0x285A]={ - category="so", - direction="l", - }, - [0x285B]={ - category="so", - direction="l", - }, - [0x285C]={ - category="so", - direction="l", - }, - [0x285D]={ - category="so", - direction="l", - }, - [0x285E]={ - category="so", - direction="l", - }, - [0x285F]={ - category="so", - direction="l", - }, - [0x2860]={ - category="so", - direction="l", - }, - [0x2861]={ - category="so", - direction="l", - }, - [0x2862]={ - category="so", - direction="l", - }, - [0x2863]={ - category="so", - direction="l", - }, - [0x2864]={ - category="so", - direction="l", - }, - [0x2865]={ - category="so", - direction="l", - }, - [0x2866]={ - category="so", - direction="l", - }, - [0x2867]={ - category="so", - direction="l", - }, - [0x2868]={ - category="so", - direction="l", - }, - [0x2869]={ - category="so", - direction="l", - }, - [0x286A]={ - category="so", - direction="l", - }, - [0x286B]={ - category="so", - direction="l", - }, - [0x286C]={ - category="so", - direction="l", - }, - [0x286D]={ - category="so", - direction="l", - }, - [0x286E]={ - category="so", - direction="l", - }, - [0x286F]={ - category="so", - direction="l", - }, - [0x2870]={ - category="so", - direction="l", - }, - [0x2871]={ - category="so", - direction="l", - }, - [0x2872]={ - category="so", - direction="l", - }, - [0x2873]={ - category="so", - direction="l", - }, - [0x2874]={ - category="so", - direction="l", - }, - [0x2875]={ - category="so", - direction="l", - }, - [0x2876]={ - category="so", - direction="l", - }, - [0x2877]={ - category="so", - direction="l", - }, - [0x2878]={ - category="so", - direction="l", - }, - [0x2879]={ - category="so", - direction="l", - }, - [0x287A]={ - category="so", - direction="l", - }, - [0x287B]={ - category="so", - direction="l", - }, - [0x287C]={ - category="so", - direction="l", - }, - [0x287D]={ - category="so", - direction="l", - }, - [0x287E]={ - category="so", - direction="l", - }, - [0x287F]={ - category="so", - direction="l", - }, - [0x2880]={ - category="so", - direction="l", - }, - [0x2881]={ - category="so", - direction="l", - }, - [0x2882]={ - category="so", - direction="l", - }, - [0x2883]={ - category="so", - direction="l", - }, - [0x2884]={ - category="so", - direction="l", - }, - [0x2885]={ - category="so", - direction="l", - }, - [0x2886]={ - category="so", - direction="l", - }, - [0x2887]={ - category="so", - direction="l", - }, - [0x2888]={ - category="so", - direction="l", - }, - [0x2889]={ - category="so", - direction="l", - }, - [0x288A]={ - category="so", - direction="l", - }, - [0x288B]={ - category="so", - direction="l", - }, - [0x288C]={ - category="so", - direction="l", - }, - [0x288D]={ - category="so", - direction="l", - }, - [0x288E]={ - category="so", - direction="l", - }, - [0x288F]={ - category="so", - direction="l", - }, - [0x2890]={ - category="so", - direction="l", - }, - [0x2891]={ - category="so", - direction="l", - }, - [0x2892]={ - category="so", - direction="l", - }, - [0x2893]={ - category="so", - direction="l", - }, - [0x2894]={ - category="so", - direction="l", - }, - [0x2895]={ - category="so", - direction="l", - }, - [0x2896]={ - category="so", - direction="l", - }, - [0x2897]={ - category="so", - direction="l", - }, - [0x2898]={ - category="so", - direction="l", - }, - [0x2899]={ - category="so", - direction="l", - }, - [0x289A]={ - category="so", - direction="l", - }, - [0x289B]={ - category="so", - direction="l", - }, - [0x289C]={ - category="so", - direction="l", - }, - [0x289D]={ - category="so", - direction="l", - }, - [0x289E]={ - category="so", - direction="l", - }, - [0x289F]={ - category="so", - direction="l", - }, - [0x28A0]={ - category="so", - direction="l", - }, - [0x28A1]={ - category="so", - direction="l", - }, - [0x28A2]={ - category="so", - direction="l", - }, - [0x28A3]={ - category="so", - direction="l", - }, - [0x28A4]={ - category="so", - direction="l", - }, - [0x28A5]={ - category="so", - direction="l", - }, - [0x28A6]={ - category="so", - direction="l", - }, - [0x28A7]={ - category="so", - direction="l", - }, - [0x28A8]={ - category="so", - direction="l", - }, - [0x28A9]={ - category="so", - direction="l", - }, - [0x28AA]={ - category="so", - direction="l", - }, - [0x28AB]={ - category="so", - direction="l", - }, - [0x28AC]={ - category="so", - direction="l", - }, - [0x28AD]={ - category="so", - direction="l", - }, - [0x28AE]={ - category="so", - direction="l", - }, - [0x28AF]={ - category="so", - direction="l", - }, - [0x28B0]={ - category="so", - direction="l", - }, - [0x28B1]={ - category="so", - direction="l", - }, - [0x28B2]={ - category="so", - direction="l", - }, - [0x28B3]={ - category="so", - direction="l", - }, - [0x28B4]={ - category="so", - direction="l", - }, - [0x28B5]={ - category="so", - direction="l", - }, - [0x28B6]={ - category="so", - direction="l", - }, - [0x28B7]={ - category="so", - direction="l", - }, - [0x28B8]={ - category="so", - direction="l", - }, - [0x28B9]={ - category="so", - direction="l", - }, - [0x28BA]={ - category="so", - direction="l", - }, - [0x28BB]={ - category="so", - direction="l", - }, - [0x28BC]={ - category="so", - direction="l", - }, - [0x28BD]={ - category="so", - direction="l", - }, - [0x28BE]={ - category="so", - direction="l", - }, - [0x28BF]={ - category="so", - direction="l", - }, - [0x28C0]={ - category="so", - direction="l", - }, - [0x28C1]={ - category="so", - direction="l", - }, - [0x28C2]={ - category="so", - direction="l", - }, - [0x28C3]={ - category="so", - direction="l", - }, - [0x28C4]={ - category="so", - direction="l", - }, - [0x28C5]={ - category="so", - direction="l", - }, - [0x28C6]={ - category="so", - direction="l", - }, - [0x28C7]={ - category="so", - direction="l", - }, - [0x28C8]={ - category="so", - direction="l", - }, - [0x28C9]={ - category="so", - direction="l", - }, - [0x28CA]={ - category="so", - direction="l", - }, - [0x28CB]={ - category="so", - direction="l", - }, - [0x28CC]={ - category="so", - direction="l", - }, - [0x28CD]={ - category="so", - direction="l", - }, - [0x28CE]={ - category="so", - direction="l", - }, - [0x28CF]={ - category="so", - direction="l", - }, - [0x28D0]={ - category="so", - direction="l", - }, - [0x28D1]={ - category="so", - direction="l", - }, - [0x28D2]={ - category="so", - direction="l", - }, - [0x28D3]={ - category="so", - direction="l", - }, - [0x28D4]={ - category="so", - direction="l", - }, - [0x28D5]={ - category="so", - direction="l", - }, - [0x28D6]={ - category="so", - direction="l", - }, - [0x28D7]={ - category="so", - direction="l", - }, - [0x28D8]={ - category="so", - direction="l", - }, - [0x28D9]={ - category="so", - direction="l", - }, - [0x28DA]={ - category="so", - direction="l", - }, - [0x28DB]={ - category="so", - direction="l", - }, - [0x28DC]={ - category="so", - direction="l", - }, - [0x28DD]={ - category="so", - direction="l", - }, - [0x28DE]={ - category="so", - direction="l", - }, - [0x28DF]={ - category="so", - direction="l", - }, - [0x28E0]={ - category="so", - direction="l", - }, - [0x28E1]={ - category="so", - direction="l", - }, - [0x28E2]={ - category="so", - direction="l", - }, - [0x28E3]={ - category="so", - direction="l", - }, - [0x28E4]={ - category="so", - direction="l", - }, - [0x28E5]={ - category="so", - direction="l", - }, - [0x28E6]={ - category="so", - direction="l", - }, - [0x28E7]={ - category="so", - direction="l", - }, - [0x28E8]={ - category="so", - direction="l", - }, - [0x28E9]={ - category="so", - direction="l", - }, - [0x28EA]={ - category="so", - direction="l", - }, - [0x28EB]={ - category="so", - direction="l", - }, - [0x28EC]={ - category="so", - direction="l", - }, - [0x28ED]={ - category="so", - direction="l", - }, - [0x28EE]={ - category="so", - direction="l", - }, - [0x28EF]={ - category="so", - direction="l", - }, - [0x28F0]={ - category="so", - direction="l", - }, - [0x28F1]={ - category="so", - direction="l", - }, - [0x28F2]={ - category="so", - direction="l", - }, - [0x28F3]={ - category="so", - direction="l", - }, - [0x28F4]={ - category="so", - direction="l", - }, - [0x28F5]={ - category="so", - direction="l", - }, - [0x28F6]={ - category="so", - direction="l", - }, - [0x28F7]={ - category="so", - direction="l", - }, - [0x28F8]={ - category="so", - direction="l", - }, - [0x28F9]={ - category="so", - direction="l", - }, - [0x28FA]={ - category="so", - direction="l", - }, - [0x28FB]={ - category="so", - direction="l", - }, - [0x28FC]={ - category="so", - direction="l", - }, - [0x28FD]={ - category="so", - direction="l", - }, - [0x28FE]={ - category="so", - direction="l", - }, - [0x28FF]={ - category="so", - direction="l", - }, - [0x2900]={ - category="sm", - direction="on", - }, - [0x2901]={ - category="sm", - direction="on", - }, - [0x2902]={ - category="sm", - direction="on", - }, - [0x2903]={ - category="sm", - direction="on", - }, - [0x2904]={ - category="sm", - direction="on", - }, - [0x2905]={ - category="sm", - direction="on", - }, - [0x2906]={ - category="sm", - direction="on", - }, - [0x2907]={ - category="sm", - direction="on", - }, - [0x2908]={ - category="sm", - direction="on", - }, - [0x2909]={ - category="sm", - direction="on", - }, - [0x290A]={ - category="sm", - direction="on", - }, - [0x290B]={ - category="sm", - direction="on", - }, - [0x290C]={ - category="sm", - direction="on", - }, - [0x290D]={ - category="sm", - direction="on", - }, - [0x290E]={ - category="sm", - direction="on", - }, - [0x290F]={ - category="sm", - direction="on", - }, - [0x2910]={ - category="sm", - direction="on", - }, - [0x2911]={ - category="sm", - direction="on", - }, - [0x2912]={ - category="sm", - direction="on", - }, - [0x2913]={ - category="sm", - direction="on", - }, - [0x2914]={ - category="sm", - direction="on", - }, - [0x2915]={ - category="sm", - direction="on", - }, - [0x2916]={ - category="sm", - direction="on", - }, - [0x2917]={ - category="sm", - direction="on", - }, - [0x2918]={ - category="sm", - direction="on", - }, - [0x2919]={ - category="sm", - direction="on", - }, - [0x291A]={ - category="sm", - direction="on", - }, - [0x291B]={ - category="sm", - direction="on", - }, - [0x291C]={ - category="sm", - direction="on", - }, - [0x291D]={ - category="sm", - direction="on", - }, - [0x291E]={ - category="sm", - direction="on", - }, - [0x291F]={ - category="sm", - direction="on", - }, - [0x2920]={ - category="sm", - direction="on", - }, - [0x2921]={ - category="sm", - direction="on", - }, - [0x2922]={ - category="sm", - direction="on", - }, - [0x2923]={ - category="sm", - direction="on", - }, - [0x2924]={ - category="sm", - direction="on", - }, - [0x2925]={ - category="sm", - direction="on", - }, - [0x2926]={ - category="sm", - direction="on", - }, - [0x2927]={ - category="sm", - direction="on", - }, - [0x2928]={ - category="sm", - direction="on", - }, - [0x2929]={ - category="sm", - direction="on", - }, - [0x292A]={ - category="sm", - direction="on", - }, - [0x292B]={ - category="sm", - direction="on", - }, - [0x292C]={ - category="sm", - direction="on", - }, - [0x292D]={ - category="sm", - direction="on", - }, - [0x292E]={ - category="sm", - direction="on", - }, - [0x292F]={ - category="sm", - direction="on", - }, - [0x2930]={ - category="sm", - direction="on", - }, - [0x2931]={ - category="sm", - direction="on", - }, - [0x2932]={ - category="sm", - direction="on", - }, - [0x2933]={ - category="sm", - direction="on", - }, - [0x2934]={ - category="sm", - direction="on", - }, - [0x2935]={ - category="sm", - direction="on", - }, - [0x2936]={ - category="sm", - direction="on", - }, - [0x2937]={ - category="sm", - direction="on", - }, - [0x2938]={ - category="sm", - direction="on", - }, - [0x2939]={ - category="sm", - direction="on", - }, - [0x293A]={ - category="sm", - direction="on", - }, - [0x293B]={ - category="sm", - direction="on", - }, - [0x293C]={ - category="sm", - direction="on", - }, - [0x293D]={ - category="sm", - direction="on", - }, - [0x293E]={ - category="sm", - direction="on", - }, - [0x293F]={ - category="sm", - direction="on", - }, - [0x2940]={ - category="sm", - direction="on", - }, - [0x2941]={ - category="sm", - direction="on", - }, - [0x2942]={ - category="sm", - direction="on", - }, - [0x2943]={ - category="sm", - direction="on", - }, - [0x2944]={ - category="sm", - direction="on", - }, - [0x2945]={ - category="sm", - direction="on", - }, - [0x2946]={ - category="sm", - direction="on", - }, - [0x2947]={ - category="sm", - direction="on", - }, - [0x2948]={ - category="sm", - direction="on", - }, - [0x2949]={ - category="sm", - direction="on", - }, - [0x294A]={ - category="sm", - direction="on", - }, - [0x294B]={ - category="sm", - direction="on", - }, - [0x294C]={ - category="sm", - direction="on", - }, - [0x294D]={ - category="sm", - direction="on", - }, - [0x294E]={ - category="sm", - direction="on", - }, - [0x294F]={ - category="sm", - direction="on", - }, - [0x2950]={ - category="sm", - direction="on", - }, - [0x2951]={ - category="sm", - direction="on", - }, - [0x2952]={ - category="sm", - direction="on", - }, - [0x2953]={ - category="sm", - direction="on", - }, - [0x2954]={ - category="sm", - direction="on", - }, - [0x2955]={ - category="sm", - direction="on", - }, - [0x2956]={ - category="sm", - direction="on", - }, - [0x2957]={ - category="sm", - direction="on", - }, - [0x2958]={ - category="sm", - direction="on", - }, - [0x2959]={ - category="sm", - direction="on", - }, - [0x295A]={ - category="sm", - direction="on", - }, - [0x295B]={ - category="sm", - direction="on", - }, - [0x295C]={ - category="sm", - direction="on", - }, - [0x295D]={ - category="sm", - direction="on", - }, - [0x295E]={ - category="sm", - direction="on", - }, - [0x295F]={ - category="sm", - direction="on", - }, - [0x2960]={ - category="sm", - direction="on", - }, - [0x2961]={ - category="sm", - direction="on", - }, - [0x2962]={ - category="sm", - direction="on", - }, - [0x2963]={ - category="sm", - direction="on", - }, - [0x2964]={ - category="sm", - direction="on", - }, - [0x2965]={ - category="sm", - direction="on", - }, - [0x2966]={ - category="sm", - direction="on", - }, - [0x2967]={ - category="sm", - direction="on", - }, - [0x2968]={ - category="sm", - direction="on", - }, - [0x2969]={ - category="sm", - direction="on", - }, - [0x296A]={ - category="sm", - direction="on", - }, - [0x296B]={ - category="sm", - direction="on", - }, - [0x296C]={ - category="sm", - direction="on", - }, - [0x296D]={ - category="sm", - direction="on", - }, - [0x296E]={ - category="sm", - direction="on", - }, - [0x296F]={ - category="sm", - direction="on", - }, - [0x2970]={ - category="sm", - direction="on", - }, - [0x2971]={ - category="sm", - direction="on", - }, - [0x2972]={ - category="sm", - direction="on", - }, - [0x2973]={ - category="sm", - direction="on", - }, - [0x2974]={ - category="sm", - direction="on", - }, - [0x2975]={ - category="sm", - direction="on", - }, - [0x2976]={ - category="sm", - direction="on", - }, - [0x2977]={ - category="sm", - direction="on", - }, - [0x2978]={ - category="sm", - direction="on", - }, - [0x2979]={ - category="sm", - direction="on", - }, - [0x297A]={ - category="sm", - direction="on", - }, - [0x297B]={ - category="sm", - direction="on", - }, - [0x297C]={ - category="sm", - direction="on", - }, - [0x297D]={ - category="sm", - direction="on", - }, - [0x297E]={ - category="sm", - direction="on", - }, - [0x297F]={ - category="sm", - direction="on", - }, - [0x2980]={ - category="sm", - direction="on", - }, - [0x2981]={ - category="sm", - direction="on", - }, - [0x2982]={ - category="sm", - direction="on", - }, - [0x2983]={ - category="ps", - direction="on", - mirror=0x2984, - }, - [0x2984]={ - category="pe", - direction="on", - mirror=0x2983, - }, - [0x2985]={ - category="ps", - direction="on", - mirror=0x2986, - }, - [0x2986]={ - category="pe", - direction="on", - mirror=0x2985, - }, - [0x2987]={ - category="ps", - direction="on", - mirror=0x2988, - }, - [0x2988]={ - category="pe", - direction="on", - mirror=0x2987, - }, - [0x2989]={ - category="ps", - direction="on", - mirror=0x298A, - }, - [0x298A]={ - category="pe", - direction="on", - mirror=0x2989, - }, - [0x298B]={ - category="ps", - direction="on", - mirror=0x298C, - }, - [0x298C]={ - category="pe", - direction="on", - mirror=0x298B, - }, - [0x298D]={ - category="ps", - direction="on", - mirror=0x2990, - }, - [0x298E]={ - category="pe", - direction="on", - mirror=0x298F, - }, - [0x298F]={ - category="ps", - direction="on", - mirror=0x298E, - }, - [0x2990]={ - category="pe", - direction="on", - mirror=0x298D, - }, - [0x2991]={ - category="ps", - direction="on", - mirror=0x2992, - }, - [0x2992]={ - category="pe", - direction="on", - mirror=0x2991, - }, - [0x2993]={ - category="ps", - direction="on", - mirror=0x2994, - }, - [0x2994]={ - category="pe", - direction="on", - mirror=0x2993, - }, - [0x2995]={ - category="ps", - direction="on", - mirror=0x2996, - }, - [0x2996]={ - category="pe", - direction="on", - mirror=0x2995, - }, - [0x2997]={ - category="ps", - direction="on", - mirror=0x2998, - textclass="open", - }, - [0x2998]={ - category="pe", - direction="on", - mirror=0x2997, - textclass="close", - }, - [0x2999]={ - category="sm", - direction="on", - }, - [0x299A]={ - category="sm", - direction="on", - }, - [0x299B]={ - category="sm", - direction="on", - }, - [0x299C]={ - category="sm", - direction="on", - }, - [0x299D]={ - category="sm", - direction="on", - }, - [0x299E]={ - category="sm", - direction="on", - }, - [0x299F]={ - category="sm", - direction="on", - }, - [0x29A0]={ - category="sm", - direction="on", - }, - [0x29A1]={ - category="sm", - direction="on", - }, - [0x29A2]={ - category="sm", - direction="on", - }, - [0x29A3]={ - category="sm", - direction="on", - }, - [0x29A4]={ - category="sm", - direction="on", - }, - [0x29A5]={ - category="sm", - direction="on", - }, - [0x29A6]={ - category="sm", - direction="on", - }, - [0x29A7]={ - category="sm", - direction="on", - }, - [0x29A8]={ - category="sm", - direction="on", - }, - [0x29A9]={ - category="sm", - direction="on", - }, - [0x29AA]={ - category="sm", - direction="on", - }, - [0x29AB]={ - category="sm", - direction="on", - }, - [0x29AC]={ - category="sm", - direction="on", - }, - [0x29AD]={ - category="sm", - direction="on", - }, - [0x29AE]={ - category="sm", - direction="on", - }, - [0x29AF]={ - category="sm", - direction="on", - }, - [0x29B0]={ - category="sm", - direction="on", - }, - [0x29B1]={ - category="sm", - direction="on", - }, - [0x29B2]={ - category="sm", - direction="on", - }, - [0x29B3]={ - category="sm", - direction="on", - }, - [0x29B4]={ - category="sm", - direction="on", - }, - [0x29B5]={ - category="sm", - direction="on", - }, - [0x29B6]={ - category="sm", - direction="on", - }, - [0x29B7]={ - category="sm", - direction="on", - }, - [0x29B8]={ - category="sm", - direction="on", - mirror=0x2298, - }, - [0x29B9]={ - category="sm", - direction="on", - }, - [0x29BA]={ - category="sm", - direction="on", - }, - [0x29BB]={ - category="sm", - direction="on", - }, - [0x29BC]={ - category="sm", - direction="on", - }, - [0x29BD]={ - category="sm", - direction="on", - }, - [0x29BE]={ - category="sm", - direction="on", - }, - [0x29BF]={ - category="sm", - direction="on", - }, - [0x29C0]={ - category="sm", - direction="on", - mirror=0x29C1, - }, - [0x29C1]={ - category="sm", - direction="on", - mirror=0x29C0, - }, - [0x29C2]={ - category="sm", - direction="on", - }, - [0x29C3]={ - category="sm", - direction="on", - }, - [0x29C4]={ - category="sm", - direction="on", - mirror=0x29C5, - }, - [0x29C5]={ - category="sm", - direction="on", - mirror=0x29C4, - }, - [0x29C6]={ - category="sm", - direction="on", - }, - [0x29C7]={ - category="sm", - direction="on", - }, - [0x29C8]={ - category="sm", - direction="on", - }, - [0x29C9]={ - category="sm", - direction="on", - }, - [0x29CA]={ - category="sm", - direction="on", - }, - [0x29CB]={ - category="sm", - direction="on", - }, - [0x29CC]={ - category="sm", - direction="on", - }, - [0x29CD]={ - category="sm", - direction="on", - }, - [0x29CE]={ - category="sm", - direction="on", - }, - [0x29CF]={ - category="sm", - direction="on", - mirror=0x29D0, - }, - [0x29D0]={ - category="sm", - direction="on", - mirror=0x29CF, - }, - [0x29D1]={ - category="sm", - direction="on", - mirror=0x29D2, - }, - [0x29D2]={ - category="sm", - direction="on", - mirror=0x29D1, - }, - [0x29D3]={ - category="sm", - direction="on", - }, - [0x29D4]={ - category="sm", - direction="on", - mirror=0x29D5, - }, - [0x29D5]={ - category="sm", - direction="on", - mirror=0x29D4, - }, - [0x29D6]={ - category="sm", - direction="on", - }, - [0x29D7]={ - category="sm", - direction="on", - }, - [0x29D8]={ - category="ps", - direction="on", - mirror=0x29D9, - }, - [0x29D9]={ - category="pe", - direction="on", - mirror=0x29D8, - }, - [0x29DA]={ - category="ps", - direction="on", - mirror=0x29DB, - }, - [0x29DB]={ - category="pe", - direction="on", - mirror=0x29DA, - }, - [0x29DC]={ - category="sm", - direction="on", - }, - [0x29DD]={ - category="sm", - direction="on", - }, - [0x29DE]={ - category="sm", - direction="on", - }, - [0x29DF]={ - category="sm", - direction="on", - }, - [0x29E0]={ - category="sm", - direction="on", - }, - [0x29E1]={ - category="sm", - direction="on", - }, - [0x29E2]={ - category="sm", - direction="on", - }, - [0x29E3]={ - category="sm", - direction="on", - }, - [0x29E4]={ - category="sm", - direction="on", - }, - [0x29E5]={ - category="sm", - direction="on", - }, - [0x29E6]={ - category="sm", - direction="on", - }, - [0x29E7]={ - category="sm", - direction="on", - }, - [0x29E8]={ - category="sm", - direction="on", - }, - [0x29E9]={ - category="sm", - direction="on", - }, - [0x29EA]={ - category="sm", - direction="on", - }, - [0x29EB]={ - category="sm", - direction="on", - }, - [0x29EC]={ - category="sm", - direction="on", - }, - [0x29ED]={ - category="sm", - direction="on", - }, - [0x29EE]={ - category="sm", - direction="on", - }, - [0x29EF]={ - category="sm", - direction="on", - }, - [0x29F0]={ - category="sm", - direction="on", - }, - [0x29F1]={ - category="sm", - direction="on", - }, - [0x29F2]={ - category="sm", - direction="on", - }, - [0x29F3]={ - category="sm", - direction="on", - }, - [0x29F4]={ - category="sm", - direction="on", - }, - [0x29F5]={ - category="sm", - direction="on", - mirror=0x2215, - }, - [0x29F6]={ - category="sm", - direction="on", - }, - [0x29F7]={ - category="sm", - direction="on", - }, - [0x29F8]={ - category="sm", - direction="on", - mirror=0x29F9, - }, - [0x29F9]={ - category="sm", - direction="on", - mirror=0x29F8, - }, - [0x29FA]={ - category="sm", - direction="on", - }, - [0x29FB]={ - category="sm", - direction="on", - }, - [0x29FC]={ - category="ps", - direction="on", - mirror=0x29FD, - }, - [0x29FD]={ - category="pe", - direction="on", - mirror=0x29FC, - }, - [0x29FE]={ - category="sm", - direction="on", - }, - [0x29FF]={ - category="sm", - direction="on", - }, - [0x2A00]={ - category="sm", - direction="on", - }, - [0x2A01]={ - category="sm", - direction="on", - }, - [0x2A02]={ - category="sm", - direction="on", - }, - [0x2A03]={ - category="sm", - direction="on", - }, - [0x2A04]={ - category="sm", - direction="on", - }, - [0x2A05]={ - category="sm", - direction="on", - }, - [0x2A06]={ - category="sm", - direction="on", - }, - [0x2A07]={ - category="sm", - direction="on", - }, - [0x2A08]={ - category="sm", - direction="on", - }, - [0x2A09]={ - category="sm", - direction="on", - }, - [0x2A0A]={ - category="sm", - direction="on", - }, - [0x2A0B]={ - category="sm", - direction="on", - }, - [0x2A0C]={ - category="sm", - direction="on", - }, - [0x2A0D]={ - category="sm", - direction="on", - }, - [0x2A0E]={ - category="sm", - direction="on", - }, - [0x2A0F]={ - category="sm", - direction="on", - }, - [0x2A10]={ - category="sm", - direction="on", - }, - [0x2A11]={ - category="sm", - direction="on", - }, - [0x2A12]={ - category="sm", - direction="on", - }, - [0x2A13]={ - category="sm", - direction="on", - }, - [0x2A14]={ - category="sm", - direction="on", - }, - [0x2A15]={ - category="sm", - direction="on", - }, - [0x2A16]={ - category="sm", - direction="on", - }, - [0x2A17]={ - category="sm", - direction="on", - }, - [0x2A18]={ - category="sm", - direction="on", - }, - [0x2A19]={ - category="sm", - direction="on", - }, - [0x2A1A]={ - category="sm", - direction="on", - }, - [0x2A1B]={ - category="sm", - direction="on", - }, - [0x2A1C]={ - category="sm", - direction="on", - }, - [0x2A1D]={ - category="sm", - direction="on", - }, - [0x2A1E]={ - category="sm", - direction="on", - }, - [0x2A1F]={ - category="sm", - direction="on", - }, - [0x2A20]={ - category="sm", - direction="on", - }, - [0x2A21]={ - category="sm", - direction="on", - }, - [0x2A22]={ - category="sm", - direction="on", - }, - [0x2A23]={ - category="sm", - direction="on", - }, - [0x2A24]={ - category="sm", - direction="on", - }, - [0x2A25]={ - category="sm", - direction="on", - }, - [0x2A26]={ - category="sm", - direction="on", - }, - [0x2A27]={ - category="sm", - direction="on", - }, - [0x2A28]={ - category="sm", - direction="on", - }, - [0x2A29]={ - category="sm", - direction="on", - }, - [0x2A2A]={ - category="sm", - direction="on", - }, - [0x2A2B]={ - category="sm", - direction="on", - mirror=0x2A2C, - }, - [0x2A2C]={ - category="sm", - direction="on", - mirror=0x2A2B, - }, - [0x2A2D]={ - category="sm", - direction="on", - mirror=0x2A2E, - }, - [0x2A2E]={ - category="sm", - direction="on", - mirror=0x2A2D, - }, - [0x2A2F]={ - category="sm", - direction="on", - }, - [0x2A30]={ - category="sm", - direction="on", - }, - [0x2A31]={ - category="sm", - direction="on", - }, - [0x2A32]={ - category="sm", - direction="on", - }, - [0x2A33]={ - category="sm", - direction="on", - }, - [0x2A34]={ - category="sm", - direction="on", - mirror=0x2A35, - }, - [0x2A35]={ - category="sm", - direction="on", - mirror=0x2A34, - }, - [0x2A36]={ - category="sm", - direction="on", - }, - [0x2A37]={ - category="sm", - direction="on", - }, - [0x2A38]={ - category="sm", - direction="on", - }, - [0x2A39]={ - category="sm", - direction="on", - }, - [0x2A3A]={ - category="sm", - direction="on", - }, - [0x2A3B]={ - category="sm", - direction="on", - }, - [0x2A3C]={ - category="sm", - direction="on", - mirror=0x2A3D, - }, - [0x2A3D]={ - category="sm", - direction="on", - mirror=0x2A3C, - }, - [0x2A3E]={ - category="sm", - direction="on", - }, - [0x2A3F]={ - category="sm", - direction="on", - }, - [0x2A40]={ - category="sm", - direction="on", - }, - [0x2A41]={ - category="sm", - direction="on", - }, - [0x2A42]={ - category="sm", - direction="on", - }, - [0x2A43]={ - category="sm", - direction="on", - }, - [0x2A44]={ - category="sm", - direction="on", - }, - [0x2A45]={ - category="sm", - direction="on", - }, - [0x2A46]={ - category="sm", - direction="on", - }, - [0x2A47]={ - category="sm", - direction="on", - }, - [0x2A48]={ - category="sm", - direction="on", - }, - [0x2A49]={ - category="sm", - direction="on", - }, - [0x2A4A]={ - category="sm", - direction="on", - }, - [0x2A4B]={ - category="sm", - direction="on", - }, - [0x2A4C]={ - category="sm", - direction="on", - }, - [0x2A4D]={ - category="sm", - direction="on", - }, - [0x2A4E]={ - category="sm", - direction="on", - }, - [0x2A4F]={ - category="sm", - direction="on", - }, - [0x2A50]={ - category="sm", - direction="on", - }, - [0x2A51]={ - category="sm", - direction="on", - }, - [0x2A52]={ - category="sm", - direction="on", - }, - [0x2A53]={ - category="sm", - direction="on", - }, - [0x2A54]={ - category="sm", - direction="on", - }, - [0x2A55]={ - category="sm", - direction="on", - }, - [0x2A56]={ - category="sm", - direction="on", - }, - [0x2A57]={ - category="sm", - direction="on", - }, - [0x2A58]={ - category="sm", - direction="on", - }, - [0x2A59]={ - category="sm", - direction="on", - }, - [0x2A5A]={ - category="sm", - direction="on", - }, - [0x2A5B]={ - category="sm", - direction="on", - }, - [0x2A5C]={ - category="sm", - direction="on", - }, - [0x2A5D]={ - category="sm", - direction="on", - }, - [0x2A5E]={ - category="sm", - direction="on", - }, - [0x2A5F]={ - category="sm", - direction="on", - }, - [0x2A60]={ - category="sm", - direction="on", - }, - [0x2A61]={ - category="sm", - direction="on", - }, - [0x2A62]={ - category="sm", - direction="on", - }, - [0x2A63]={ - category="sm", - direction="on", - }, - [0x2A64]={ - category="sm", - direction="on", - mirror=0x2A65, - }, - [0x2A65]={ - category="sm", - direction="on", - mirror=0x2A64, - }, - [0x2A66]={ - category="sm", - direction="on", - }, - [0x2A67]={ - category="sm", - direction="on", - }, - [0x2A68]={ - category="sm", - direction="on", - }, - [0x2A69]={ - category="sm", - direction="on", - }, - [0x2A6A]={ - category="sm", - direction="on", - }, - [0x2A6B]={ - category="sm", - direction="on", - }, - [0x2A6C]={ - category="sm", - direction="on", - }, - [0x2A6D]={ - category="sm", - direction="on", - }, - [0x2A6E]={ - category="sm", - direction="on", - }, - [0x2A6F]={ - category="sm", - direction="on", - }, - [0x2A70]={ - category="sm", - direction="on", - }, - [0x2A71]={ - category="sm", - direction="on", - }, - [0x2A72]={ - category="sm", - direction="on", - }, - [0x2A73]={ - category="sm", - direction="on", - }, - [0x2A74]={ - category="sm", - direction="on", - }, - [0x2A75]={ - category="sm", - direction="on", - }, - [0x2A76]={ - category="sm", - direction="on", - }, - [0x2A77]={ - category="sm", - direction="on", - }, - [0x2A78]={ - category="sm", - direction="on", - }, - [0x2A79]={ - category="sm", - direction="on", - mirror=0x2A7A, - }, - [0x2A7A]={ - category="sm", - direction="on", - mirror=0x2A79, - }, - [0x2A7B]={ - category="sm", - direction="on", - }, - [0x2A7C]={ - category="sm", - direction="on", - }, - [0x2A7D]={ - category="sm", - direction="on", - mirror=0x2A7E, - }, - [0x2A7E]={ - category="sm", - direction="on", - mirror=0x2A7D, - }, - [0x2A7F]={ - category="sm", - direction="on", - mirror=0x2A80, - }, - [0x2A80]={ - category="sm", - direction="on", - mirror=0x2A7F, - }, - [0x2A81]={ - category="sm", - direction="on", - mirror=0x2A82, - }, - [0x2A82]={ - category="sm", - direction="on", - mirror=0x2A81, - }, - [0x2A83]={ - category="sm", - direction="on", - mirror=0x2A84, - }, - [0x2A84]={ - category="sm", - direction="on", - mirror=0x2A83, - }, - [0x2A85]={ - category="sm", - direction="on", - }, - [0x2A86]={ - category="sm", - direction="on", - }, - [0x2A87]={ - category="sm", - direction="on", - }, - [0x2A88]={ - category="sm", - direction="on", - }, - [0x2A89]={ - category="sm", - direction="on", - }, - [0x2A8A]={ - category="sm", - direction="on", - }, - [0x2A8B]={ - category="sm", - direction="on", - mirror=0x2A8C, - }, - [0x2A8C]={ - category="sm", - direction="on", - mirror=0x2A8B, - }, - [0x2A8D]={ - category="sm", - direction="on", - }, - [0x2A8E]={ - category="sm", - direction="on", - }, - [0x2A8F]={ - category="sm", - direction="on", - }, - [0x2A90]={ - category="sm", - direction="on", - }, - [0x2A91]={ - category="sm", - direction="on", - mirror=0x2A92, - }, - [0x2A92]={ - category="sm", - direction="on", - mirror=0x2A91, - }, - [0x2A93]={ - category="sm", - direction="on", - mirror=0x2A94, - }, - [0x2A94]={ - category="sm", - direction="on", - mirror=0x2A93, - }, - [0x2A95]={ - category="sm", - direction="on", - mirror=0x2A96, - }, - [0x2A96]={ - category="sm", - direction="on", - mirror=0x2A95, - }, - [0x2A97]={ - category="sm", - direction="on", - mirror=0x2A98, - }, - [0x2A98]={ - category="sm", - direction="on", - mirror=0x2A97, - }, - [0x2A99]={ - category="sm", - direction="on", - mirror=0x2A9A, - }, - [0x2A9A]={ - category="sm", - direction="on", - mirror=0x2A99, - }, - [0x2A9B]={ - category="sm", - direction="on", - mirror=0x2A9C, - }, - [0x2A9C]={ - category="sm", - direction="on", - mirror=0x2A9B, - }, - [0x2A9D]={ - category="sm", - direction="on", - }, - [0x2A9E]={ - category="sm", - direction="on", - }, - [0x2A9F]={ - category="sm", - direction="on", - }, - [0x2AA0]={ - category="sm", - direction="on", - }, - [0x2AA1]={ - category="sm", - direction="on", - mirror=0x2AA2, - }, - [0x2AA2]={ - category="sm", - direction="on", - mirror=0x2AA1, - }, - [0x2AA3]={ - category="sm", - direction="on", - }, - [0x2AA4]={ - category="sm", - direction="on", - }, - [0x2AA5]={ - category="sm", - direction="on", - }, - [0x2AA6]={ - category="sm", - direction="on", - mirror=0x2AA7, - }, - [0x2AA7]={ - category="sm", - direction="on", - mirror=0x2AA6, - }, - [0x2AA8]={ - category="sm", - direction="on", - mirror=0x2AA9, - }, - [0x2AA9]={ - category="sm", - direction="on", - mirror=0x2AA8, - }, - [0x2AAA]={ - category="sm", - direction="on", - mirror=0x2AAB, - }, - [0x2AAB]={ - category="sm", - direction="on", - mirror=0x2AAA, - }, - [0x2AAC]={ - category="sm", - direction="on", - mirror=0x2AAD, - }, - [0x2AAD]={ - category="sm", - direction="on", - mirror=0x2AAC, - }, - [0x2AAE]={ - category="sm", - direction="on", - }, - [0x2AAF]={ - category="sm", - direction="on", - mirror=0x2AB0, - }, - [0x2AB0]={ - category="sm", - direction="on", - mirror=0x2AAF, - }, - [0x2AB1]={ - category="sm", - direction="on", - }, - [0x2AB2]={ - category="sm", - direction="on", - }, - [0x2AB3]={ - category="sm", - direction="on", - mirror=0x2AB4, - }, - [0x2AB4]={ - category="sm", - direction="on", - mirror=0x2AB3, - }, - [0x2AB5]={ - category="sm", - direction="on", - }, - [0x2AB6]={ - category="sm", - direction="on", - }, - [0x2AB7]={ - category="sm", - direction="on", - }, - [0x2AB8]={ - category="sm", - direction="on", - }, - [0x2AB9]={ - category="sm", - direction="on", - }, - [0x2ABA]={ - category="sm", - direction="on", - }, - [0x2ABB]={ - category="sm", - direction="on", - mirror=0x2ABC, - }, - [0x2ABC]={ - category="sm", - direction="on", - mirror=0x2ABB, - }, - [0x2ABD]={ - category="sm", - direction="on", - mirror=0x2ABE, - }, - [0x2ABE]={ - category="sm", - direction="on", - mirror=0x2ABD, - }, - [0x2ABF]={ - category="sm", - direction="on", - mirror=0x2AC0, - }, - [0x2AC0]={ - category="sm", - direction="on", - mirror=0x2ABF, - }, - [0x2AC1]={ - category="sm", - direction="on", - mirror=0x2AC2, - }, - [0x2AC2]={ - category="sm", - direction="on", - mirror=0x2AC1, - }, - [0x2AC3]={ - category="sm", - direction="on", - mirror=0x2AC4, - }, - [0x2AC4]={ - category="sm", - direction="on", - mirror=0x2AC3, - }, - [0x2AC5]={ - category="sm", - direction="on", - mirror=0x2AC6, - }, - [0x2AC6]={ - category="sm", - direction="on", - mirror=0x2AC5, - }, - [0x2AC7]={ - category="sm", - direction="on", - }, - [0x2AC8]={ - category="sm", - direction="on", - }, - [0x2AC9]={ - category="sm", - direction="on", - }, - [0x2ACA]={ - category="sm", - direction="on", - }, - [0x2ACB]={ - category="sm", - direction="on", - }, - [0x2ACC]={ - category="sm", - direction="on", - }, - [0x2ACD]={ - category="sm", - direction="on", - mirror=0x2ACE, - }, - [0x2ACE]={ - category="sm", - direction="on", - mirror=0x2ACD, - }, - [0x2ACF]={ - category="sm", - direction="on", - mirror=0x2AD0, - }, - [0x2AD0]={ - category="sm", - direction="on", - mirror=0x2ACF, - }, - [0x2AD1]={ - category="sm", - direction="on", - mirror=0x2AD2, - }, - [0x2AD2]={ - category="sm", - direction="on", - mirror=0x2AD1, - }, - [0x2AD3]={ - category="sm", - direction="on", - mirror=0x2AD4, - }, - [0x2AD4]={ - category="sm", - direction="on", - mirror=0x2AD3, - }, - [0x2AD5]={ - category="sm", - direction="on", - mirror=0x2AD6, - }, - [0x2AD6]={ - category="sm", - direction="on", - mirror=0x2AD5, - }, - [0x2AD7]={ - category="sm", - direction="on", - }, - [0x2AD8]={ - category="sm", - direction="on", - }, - [0x2AD9]={ - category="sm", - direction="on", - }, - [0x2ADA]={ - category="sm", - direction="on", - }, - [0x2ADB]={ - category="sm", - direction="on", - }, - [0x2ADC]={ - category="sm", - direction="on", - }, - [0x2ADD]={ - category="sm", - direction="on", - }, - [0x2ADE]={ - category="sm", - direction="on", - mirror=0x22A6, - }, - [0x2ADF]={ - category="sm", - direction="on", - }, - [0x2AE0]={ - category="sm", - direction="on", - }, - [0x2AE1]={ - category="sm", - direction="on", - }, - [0x2AE2]={ - category="sm", - direction="on", - }, - [0x2AE3]={ - category="sm", - direction="on", - mirror=0x22A9, - }, - [0x2AE4]={ - category="sm", - direction="on", - mirror=0x22A8, - }, - [0x2AE5]={ - category="sm", - direction="on", - mirror=0x22AB, - }, - [0x2AE6]={ - category="sm", - direction="on", - }, - [0x2AE7]={ - category="sm", - direction="on", - }, - [0x2AE8]={ - category="sm", - direction="on", - }, - [0x2AE9]={ - category="sm", - direction="on", - }, - [0x2AEA]={ - category="sm", - direction="on", - }, - [0x2AEB]={ - category="sm", - direction="on", - }, - [0x2AEC]={ - category="sm", - direction="on", - mirror=0x2AED, - }, - [0x2AED]={ - category="sm", - direction="on", - mirror=0x2AEC, - }, - [0x2AEE]={ - category="sm", - direction="on", - }, - [0x2AEF]={ - category="sm", - direction="on", - }, - [0x2AF0]={ - category="sm", - direction="on", - }, - [0x2AF1]={ - category="sm", - direction="on", - }, - [0x2AF2]={ - category="sm", - direction="on", - }, - [0x2AF3]={ - category="sm", - direction="on", - }, - [0x2AF4]={ - category="sm", - direction="on", - }, - [0x2AF5]={ - category="sm", - direction="on", - }, - [0x2AF6]={ - category="sm", - direction="on", - }, - [0x2AF7]={ - category="sm", - direction="on", - mirror=0x2AF8, - }, - [0x2AF8]={ - category="sm", - direction="on", - mirror=0x2AF7, - }, - [0x2AF9]={ - category="sm", - direction="on", - mirror=0x2AFA, - }, - [0x2AFA]={ - category="sm", - direction="on", - mirror=0x2AF9, - }, - [0x2AFB]={ - category="sm", - direction="on", - }, - [0x2AFC]={ - category="sm", - direction="on", - }, - [0x2AFD]={ - category="sm", - direction="on", - }, - [0x2AFE]={ - category="sm", - direction="on", - }, - [0x2AFF]={ - category="sm", - direction="on", - }, - [0x2B00]={ - category="so", - direction="on", - }, - [0x2B01]={ - category="so", - direction="on", - }, - [0x2B02]={ - category="so", - direction="on", - }, - [0x2B03]={ - category="so", - direction="on", - }, - [0x2B04]={ - category="so", - direction="on", - }, - [0x2B05]={ - category="so", - direction="on", - }, - [0x2B06]={ - category="so", - direction="on", - }, - [0x2B07]={ - category="so", - direction="on", - }, - [0x2B08]={ - category="so", - direction="on", - }, - [0x2B09]={ - category="so", - direction="on", - }, - [0x2B0A]={ - category="so", - direction="on", - }, - [0x2B0B]={ - category="so", - direction="on", - }, - [0x2B0C]={ - category="so", - direction="on", - }, - [0x2B0D]={ - category="so", - direction="on", - }, - [0x2B0E]={ - category="so", - direction="on", - }, - [0x2B0F]={ - category="so", - direction="on", - }, - [0x2B10]={ - category="so", - direction="on", - }, - [0x2B11]={ - category="so", - direction="on", - }, - [0x2B12]={ - category="so", - direction="on", - }, - [0x2B13]={ - category="so", - direction="on", - }, - [0x2B14]={ - category="so", - direction="on", - }, - [0x2B15]={ - category="so", - direction="on", - }, - [0x2B16]={ - category="so", - direction="on", - }, - [0x2B17]={ - category="so", - direction="on", - }, - [0x2B18]={ - category="so", - direction="on", - }, - [0x2B19]={ - category="so", - direction="on", - }, - [0x2B1A]={ - category="so", - direction="on", - }, - [0x2B1B]={ - category="so", - direction="on", - }, - [0x2B1C]={ - category="so", - direction="on", - }, - [0x2B1D]={ - category="so", - direction="on", - }, - [0x2B1E]={ - category="so", - direction="on", - }, - [0x2B1F]={ - category="so", - direction="on", - }, - [0x2B20]={ - category="so", - direction="on", - }, - [0x2B21]={ - category="so", - direction="on", - }, - [0x2B22]={ - category="so", - direction="on", - }, - [0x2B23]={ - category="so", - direction="on", - }, - [0x2B24]={ - category="so", - direction="on", - }, - [0x2B25]={ - category="so", - direction="on", - }, - [0x2B26]={ - category="so", - direction="on", - }, - [0x2B27]={ - category="so", - direction="on", - }, - [0x2B28]={ - category="so", - direction="on", - }, - [0x2B29]={ - category="so", - direction="on", - }, - [0x2B2A]={ - category="so", - direction="on", - }, - [0x2B2B]={ - category="so", - direction="on", - }, - [0x2B2C]={ - category="so", - direction="on", - }, - [0x2B2D]={ - category="so", - direction="on", - }, - [0x2B2E]={ - category="so", - direction="on", - }, - [0x2B2F]={ - category="so", - direction="on", - }, - [0x2B30]={ - category="sm", - direction="on", - }, - [0x2B31]={ - category="sm", - direction="on", - }, - [0x2B32]={ - category="sm", - direction="on", - }, - [0x2B33]={ - category="sm", - direction="on", - }, - [0x2B34]={ - category="sm", - direction="on", - }, - [0x2B35]={ - category="sm", - direction="on", - }, - [0x2B36]={ - category="sm", - direction="on", - }, - [0x2B37]={ - category="sm", - direction="on", - }, - [0x2B38]={ - category="sm", - direction="on", - }, - [0x2B39]={ - category="sm", - direction="on", - }, - [0x2B3A]={ - category="sm", - direction="on", - }, - [0x2B3B]={ - category="sm", - direction="on", - }, - [0x2B3C]={ - category="sm", - direction="on", - }, - [0x2B3D]={ - category="sm", - direction="on", - }, - [0x2B3E]={ - category="sm", - direction="on", - }, - [0x2B3F]={ - category="sm", - direction="on", - }, - [0x2B40]={ - category="sm", - direction="on", - }, - [0x2B41]={ - category="sm", - direction="on", - }, - [0x2B42]={ - category="sm", - direction="on", - }, - [0x2B43]={ - category="sm", - direction="on", - }, - [0x2B44]={ - category="sm", - direction="on", - }, - [0x2B45]={ - category="so", - direction="on", - }, - [0x2B46]={ - category="so", - direction="on", - }, - [0x2B47]={ - category="sm", - direction="on", - }, - [0x2B48]={ - category="sm", - direction="on", - }, - [0x2B49]={ - category="sm", - direction="on", - }, - [0x2B4A]={ - category="sm", - direction="on", - }, - [0x2B4B]={ - category="sm", - direction="on", - }, - [0x2B4C]={ - category="sm", - direction="on", - }, - [0x2B4D]={ - category="so", - direction="on", - }, - [0x2B4E]={ - category="so", - direction="on", - }, - [0x2B4F]={ - category="so", - direction="on", - }, - [0x2B50]={ - category="so", - direction="on", - }, - [0x2B51]={ - category="so", - direction="on", - }, - [0x2B52]={ - category="so", - direction="on", - }, - [0x2B53]={ - category="so", - direction="on", - }, - [0x2B54]={ - category="so", - direction="on", - }, - [0x2B55]={ - category="so", - direction="on", - }, - [0x2B56]={ - category="so", - direction="on", - }, - [0x2B57]={ - category="so", - direction="on", - }, - [0x2B58]={ - category="so", - direction="on", - }, - [0x2B59]={ - category="so", - direction="on", - }, - [0x2B5A]={ - category="so", - direction="on", - }, - [0x2B5B]={ - category="so", - direction="on", - }, - [0x2B5C]={ - category="so", - direction="on", - }, - [0x2B5D]={ - category="so", - direction="on", - }, - [0x2B5E]={ - category="so", - direction="on", - }, - [0x2B5F]={ - category="so", - direction="on", - }, - [0x2B60]={ - category="so", - direction="on", - }, - [0x2B61]={ - category="so", - direction="on", - }, - [0x2B62]={ - category="so", - direction="on", - }, - [0x2B63]={ - category="so", - direction="on", - }, - [0x2B64]={ - category="so", - direction="on", - }, - [0x2B65]={ - category="so", - direction="on", - }, - [0x2B66]={ - category="so", - direction="on", - }, - [0x2B67]={ - category="so", - direction="on", - }, - [0x2B68]={ - category="so", - direction="on", - }, - [0x2B69]={ - category="so", - direction="on", - }, - [0x2B6A]={ - category="so", - direction="on", - }, - [0x2B6B]={ - category="so", - direction="on", - }, - [0x2B6C]={ - category="so", - direction="on", - }, - [0x2B6D]={ - category="so", - direction="on", - }, - [0x2B6E]={ - category="so", - direction="on", - }, - [0x2B6F]={ - category="so", - direction="on", - }, - [0x2B70]={ - category="so", - direction="on", - }, - [0x2B71]={ - category="so", - direction="on", - }, - [0x2B72]={ - category="so", - direction="on", - }, - [0x2B73]={ - category="so", - direction="on", - }, - [0x2B76]={ - category="so", - direction="on", - }, - [0x2B77]={ - category="so", - direction="on", - }, - [0x2B78]={ - category="so", - direction="on", - }, - [0x2B79]={ - category="so", - direction="on", - }, - [0x2B7A]={ - category="so", - direction="on", - }, - [0x2B7B]={ - category="so", - direction="on", - }, - [0x2B7C]={ - category="so", - direction="on", - }, - [0x2B7D]={ - category="so", - direction="on", - }, - [0x2B7E]={ - category="so", - direction="on", - }, - [0x2B7F]={ - category="so", - direction="on", - }, - [0x2B80]={ - category="so", - direction="on", - }, - [0x2B81]={ - category="so", - direction="on", - }, - [0x2B82]={ - category="so", - direction="on", - }, - [0x2B83]={ - category="so", - direction="on", - }, - [0x2B84]={ - category="so", - direction="on", - }, - [0x2B85]={ - category="so", - direction="on", - }, - [0x2B86]={ - category="so", - direction="on", - }, - [0x2B87]={ - category="so", - direction="on", - }, - [0x2B88]={ - category="so", - direction="on", - }, - [0x2B89]={ - category="so", - direction="on", - }, - [0x2B8A]={ - category="so", - direction="on", - }, - [0x2B8B]={ - category="so", - direction="on", - }, - [0x2B8C]={ - category="so", - direction="on", - }, - [0x2B8D]={ - category="so", - direction="on", - }, - [0x2B8E]={ - category="so", - direction="on", - }, - [0x2B8F]={ - category="so", - direction="on", - }, - [0x2B90]={ - category="so", - direction="on", - }, - [0x2B91]={ - category="so", - direction="on", - }, - [0x2B92]={ - category="so", - direction="on", - }, - [0x2B93]={ - category="so", - direction="on", - }, - [0x2B94]={ - category="so", - direction="on", - }, - [0x2B95]={ - category="so", - direction="on", - }, - [0x2B98]={ - category="so", - direction="on", - }, - [0x2B99]={ - category="so", - direction="on", - }, - [0x2B9A]={ - category="so", - direction="on", - }, - [0x2B9B]={ - category="so", - direction="on", - }, - [0x2B9C]={ - category="so", - direction="on", - }, - [0x2B9D]={ - category="so", - direction="on", - }, - [0x2B9E]={ - category="so", - direction="on", - }, - [0x2B9F]={ - category="so", - direction="on", - }, - [0x2BA0]={ - category="so", - direction="on", - }, - [0x2BA1]={ - category="so", - direction="on", - }, - [0x2BA2]={ - category="so", - direction="on", - }, - [0x2BA3]={ - category="so", - direction="on", - }, - [0x2BA4]={ - category="so", - direction="on", - }, - [0x2BA5]={ - category="so", - direction="on", - }, - [0x2BA6]={ - category="so", - direction="on", - }, - [0x2BA7]={ - category="so", - direction="on", - }, - [0x2BA8]={ - category="so", - direction="on", - }, - [0x2BA9]={ - category="so", - direction="on", - }, - [0x2BAA]={ - category="so", - direction="on", - }, - [0x2BAB]={ - category="so", - direction="on", - }, - [0x2BAC]={ - category="so", - direction="on", - }, - [0x2BAD]={ - category="so", - direction="on", - }, - [0x2BAE]={ - category="so", - direction="on", - }, - [0x2BAF]={ - category="so", - direction="on", - }, - [0x2BB0]={ - category="so", - direction="on", - }, - [0x2BB1]={ - category="so", - direction="on", - }, - [0x2BB2]={ - category="so", - direction="on", - }, - [0x2BB3]={ - category="so", - direction="on", - }, - [0x2BB4]={ - category="so", - direction="on", - }, - [0x2BB5]={ - category="so", - direction="on", - }, - [0x2BB6]={ - category="so", - direction="on", - }, - [0x2BB7]={ - category="so", - direction="on", - }, - [0x2BB8]={ - category="so", - direction="on", - }, - [0x2BB9]={ - category="so", - direction="on", - }, - [0x2BBD]={ - category="so", - direction="on", - }, - [0x2BBE]={ - category="so", - direction="on", - }, - [0x2BBF]={ - category="so", - direction="on", - }, - [0x2BC0]={ - category="so", - direction="on", - }, - [0x2BC1]={ - category="so", - direction="on", - }, - [0x2BC2]={ - category="so", - direction="on", - }, - [0x2BC3]={ - category="so", - direction="on", - }, - [0x2BC4]={ - category="so", - direction="on", - }, - [0x2BC5]={ - category="so", - direction="on", - }, - [0x2BC6]={ - category="so", - direction="on", - }, - [0x2BC7]={ - category="so", - direction="on", - }, - [0x2BC8]={ - category="so", - direction="on", - }, - [0x2BCA]={ - category="so", - direction="on", - }, - [0x2BCB]={ - category="so", - direction="on", - }, - [0x2BCC]={ - category="so", - direction="on", - }, - [0x2BCD]={ - category="so", - direction="on", - }, - [0x2BCE]={ - category="so", - direction="on", - }, - [0x2BCF]={ - category="so", - direction="on", - }, - [0x2BD0]={ - category="so", - direction="on", - }, - [0x2BD1]={ - category="so", - direction="on", - }, - [0x2BEC]={ - category="so", - direction="on", - }, - [0x2BED]={ - category="so", - direction="on", - }, - [0x2BEE]={ - category="so", - direction="on", - }, - [0x2BEF]={ - category="so", - direction="on", - }, - [0x2C00]={ - category="lu", - direction="l", - }, - [0x2C01]={ - category="lu", - direction="l", - }, - [0x2C02]={ - category="lu", - direction="l", - }, - [0x2C03]={ - category="lu", - direction="l", - }, - [0x2C04]={ - category="lu", - direction="l", - }, - [0x2C05]={ - category="lu", - direction="l", - }, - [0x2C06]={ - category="lu", - direction="l", - }, - [0x2C07]={ - category="lu", - direction="l", - }, - [0x2C08]={ - category="lu", - direction="l", - }, - [0x2C09]={ - category="lu", - direction="l", - }, - [0x2C0A]={ - category="lu", - direction="l", - }, - [0x2C0B]={ - category="lu", - direction="l", - }, - [0x2C0C]={ - category="lu", - direction="l", - }, - [0x2C0D]={ - category="lu", - direction="l", - }, - [0x2C0E]={ - category="lu", - direction="l", - }, - [0x2C0F]={ - category="lu", - direction="l", - }, - [0x2C10]={ - category="lu", - direction="l", - }, - [0x2C11]={ - category="lu", - direction="l", - }, - [0x2C12]={ - category="lu", - direction="l", - }, - [0x2C13]={ - category="lu", - direction="l", - }, - [0x2C14]={ - category="lu", - direction="l", - }, - [0x2C15]={ - category="lu", - direction="l", - }, - [0x2C16]={ - category="lu", - direction="l", - }, - [0x2C17]={ - category="lu", - direction="l", - }, - [0x2C18]={ - category="lu", - direction="l", - }, - [0x2C19]={ - category="lu", - direction="l", - }, - [0x2C1A]={ - category="lu", - direction="l", - }, - [0x2C1B]={ - category="lu", - direction="l", - }, - [0x2C1C]={ - category="lu", - direction="l", - }, - [0x2C1D]={ - category="lu", - direction="l", - }, - [0x2C1E]={ - category="lu", - direction="l", - }, - [0x2C1F]={ - category="lu", - direction="l", - }, - [0x2C20]={ - category="lu", - direction="l", - }, - [0x2C21]={ - category="lu", - direction="l", - }, - [0x2C22]={ - category="lu", - direction="l", - }, - [0x2C23]={ - category="lu", - direction="l", - }, - [0x2C24]={ - category="lu", - direction="l", - }, - [0x2C25]={ - category="lu", - direction="l", - }, - [0x2C26]={ - category="lu", - direction="l", - }, - [0x2C27]={ - category="lu", - direction="l", - }, - [0x2C28]={ - category="lu", - direction="l", - }, - [0x2C29]={ - category="lu", - direction="l", - }, - [0x2C2A]={ - category="lu", - direction="l", - }, - [0x2C2B]={ - category="lu", - direction="l", - }, - [0x2C2C]={ - category="lu", - direction="l", - }, - [0x2C2D]={ - category="lu", - direction="l", - }, - [0x2C2E]={ - category="lu", - direction="l", - }, - [0x2C30]={ - category="ll", - direction="l", - }, - [0x2C31]={ - category="ll", - direction="l", - }, - [0x2C32]={ - category="ll", - direction="l", - }, - [0x2C33]={ - category="ll", - direction="l", - }, - [0x2C34]={ - category="ll", - direction="l", - }, - [0x2C35]={ - category="ll", - direction="l", - }, - [0x2C36]={ - category="ll", - direction="l", - }, - [0x2C37]={ - category="ll", - direction="l", - }, - [0x2C38]={ - category="ll", - direction="l", - }, - [0x2C39]={ - category="ll", - direction="l", - }, - [0x2C3A]={ - category="ll", - direction="l", - }, - [0x2C3B]={ - category="ll", - direction="l", - }, - [0x2C3C]={ - category="ll", - direction="l", - }, - [0x2C3D]={ - category="ll", - direction="l", - }, - [0x2C3E]={ - category="ll", - direction="l", - }, - [0x2C3F]={ - category="ll", - direction="l", - }, - [0x2C40]={ - category="ll", - direction="l", - }, - [0x2C41]={ - category="ll", - direction="l", - }, - [0x2C42]={ - category="ll", - direction="l", - }, - [0x2C43]={ - category="ll", - direction="l", - }, - [0x2C44]={ - category="ll", - direction="l", - }, - [0x2C45]={ - category="ll", - direction="l", - }, - [0x2C46]={ - category="ll", - direction="l", - }, - [0x2C47]={ - category="ll", - direction="l", - }, - [0x2C48]={ - category="ll", - direction="l", - }, - [0x2C49]={ - category="ll", - direction="l", - }, - [0x2C4A]={ - category="ll", - direction="l", - }, - [0x2C4B]={ - category="ll", - direction="l", - }, - [0x2C4C]={ - category="ll", - direction="l", - }, - [0x2C4D]={ - category="ll", - direction="l", - }, - [0x2C4E]={ - category="ll", - direction="l", - }, - [0x2C4F]={ - category="ll", - direction="l", - }, - [0x2C50]={ - category="ll", - direction="l", - }, - [0x2C51]={ - category="ll", - direction="l", - }, - [0x2C52]={ - category="ll", - direction="l", - }, - [0x2C53]={ - category="ll", - direction="l", - }, - [0x2C54]={ - category="ll", - direction="l", - }, - [0x2C55]={ - category="ll", - direction="l", - }, - [0x2C56]={ - category="ll", - direction="l", - }, - [0x2C57]={ - category="ll", - direction="l", - }, - [0x2C58]={ - category="ll", - direction="l", - }, - [0x2C59]={ - category="ll", - direction="l", - }, - [0x2C5A]={ - category="ll", - direction="l", - }, - [0x2C5B]={ - category="ll", - direction="l", - }, - [0x2C5C]={ - category="ll", - direction="l", - }, - [0x2C5D]={ - category="ll", - direction="l", - }, - [0x2C5E]={ - category="ll", - direction="l", - }, - [0x2C60]={ - category="lu", - direction="l", - }, - [0x2C61]={ - category="ll", - direction="l", - }, - [0x2C62]={ - category="lu", - direction="l", - }, - [0x2C63]={ - category="lu", - direction="l", - }, - [0x2C64]={ - category="lu", - direction="l", - }, - [0x2C65]={ - category="ll", - direction="l", - }, - [0x2C66]={ - category="ll", - direction="l", - }, - [0x2C67]={ - category="lu", - direction="l", - }, - [0x2C68]={ - category="ll", - direction="l", - }, - [0x2C69]={ - category="lu", - direction="l", - }, - [0x2C6A]={ - category="ll", - direction="l", - }, - [0x2C6B]={ - category="lu", - direction="l", - }, - [0x2C6C]={ - category="ll", - direction="l", - }, - [0x2C6D]={ - category="lu", - direction="l", - }, - [0x2C6E]={ - category="lu", - direction="l", - }, - [0x2C6F]={ - category="lu", - direction="l", - }, - [0x2C70]={ - category="lu", - direction="l", - }, - [0x2C71]={ - category="ll", - direction="l", - }, - [0x2C72]={ - category="lu", - direction="l", - }, - [0x2C73]={ - category="ll", - direction="l", - }, - [0x2C74]={ - category="ll", - direction="l", - }, - [0x2C75]={ - category="lu", - direction="l", - }, - [0x2C76]={ - category="ll", - direction="l", - }, - [0x2C77]={ - category="ll", - direction="l", - }, - [0x2C78]={ - category="ll", - direction="l", - }, - [0x2C79]={ - category="ll", - direction="l", - }, - [0x2C7A]={ - category="ll", - direction="l", - }, - [0x2C7B]={ - category="ll", - direction="l", - }, - [0x2C7C]={ - category="ll", - direction="l", - }, - [0x2C7D]={ - category="lm", - direction="l", - }, - [0x2C7E]={ - category="lu", - direction="l", - }, - [0x2C7F]={ - category="lu", - direction="l", - }, - [0x2C80]={ - category="lu", - direction="l", - }, - [0x2C81]={ - category="ll", - direction="l", - }, - [0x2C82]={ - category="lu", - direction="l", - }, - [0x2C83]={ - category="ll", - direction="l", - }, - [0x2C84]={ - category="lu", - direction="l", - }, - [0x2C85]={ - category="ll", - direction="l", - }, - [0x2C86]={ - category="lu", - direction="l", - }, - [0x2C87]={ - category="ll", - direction="l", - }, - [0x2C88]={ - category="lu", - direction="l", - }, - [0x2C89]={ - category="ll", - direction="l", - }, - [0x2C8A]={ - category="lu", - direction="l", - }, - [0x2C8B]={ - category="ll", - direction="l", - }, - [0x2C8C]={ - category="lu", - direction="l", - }, - [0x2C8D]={ - category="ll", - direction="l", - }, - [0x2C8E]={ - category="lu", - direction="l", - }, - [0x2C8F]={ - category="ll", - direction="l", - }, - [0x2C90]={ - category="lu", - direction="l", - }, - [0x2C91]={ - category="ll", - direction="l", - }, - [0x2C92]={ - category="lu", - direction="l", - }, - [0x2C93]={ - category="ll", - direction="l", - }, - [0x2C94]={ - category="lu", - direction="l", - }, - [0x2C95]={ - category="ll", - direction="l", - }, - [0x2C96]={ - category="lu", - direction="l", - }, - [0x2C97]={ - category="ll", - direction="l", - }, - [0x2C98]={ - category="lu", - direction="l", - }, - [0x2C99]={ - category="ll", - direction="l", - }, - [0x2C9A]={ - category="lu", - direction="l", - }, - [0x2C9B]={ - category="ll", - direction="l", - }, - [0x2C9C]={ - category="lu", - direction="l", - }, - [0x2C9D]={ - category="ll", - direction="l", - }, - [0x2C9E]={ - category="lu", - direction="l", - }, - [0x2C9F]={ - category="ll", - direction="l", - }, - [0x2CA0]={ - category="lu", - direction="l", - }, - [0x2CA1]={ - category="ll", - direction="l", - }, - [0x2CA2]={ - category="lu", - direction="l", - }, - [0x2CA3]={ - category="ll", - direction="l", - }, - [0x2CA4]={ - category="lu", - direction="l", - }, - [0x2CA5]={ - category="ll", - direction="l", - }, - [0x2CA6]={ - category="lu", - direction="l", - }, - [0x2CA7]={ - category="ll", - direction="l", - }, - [0x2CA8]={ - category="lu", - direction="l", - }, - [0x2CA9]={ - category="ll", - direction="l", - }, - [0x2CAA]={ - category="lu", - direction="l", - }, - [0x2CAB]={ - category="ll", - direction="l", - }, - [0x2CAC]={ - category="lu", - direction="l", - }, - [0x2CAD]={ - category="ll", - direction="l", - }, - [0x2CAE]={ - category="lu", - direction="l", - }, - [0x2CAF]={ - category="ll", - direction="l", - }, - [0x2CB0]={ - category="lu", - direction="l", - }, - [0x2CB1]={ - category="ll", - direction="l", - }, - [0x2CB2]={ - category="lu", - direction="l", - }, - [0x2CB3]={ - category="ll", - direction="l", - }, - [0x2CB4]={ - category="lu", - direction="l", - }, - [0x2CB5]={ - category="ll", - direction="l", - }, - [0x2CB6]={ - category="lu", - direction="l", - }, - [0x2CB7]={ - category="ll", - direction="l", - }, - [0x2CB8]={ - category="lu", - direction="l", - }, - [0x2CB9]={ - category="ll", - direction="l", - }, - [0x2CBA]={ - category="lu", - direction="l", - }, - [0x2CBB]={ - category="ll", - direction="l", - }, - [0x2CBC]={ - category="lu", - direction="l", - }, - [0x2CBD]={ - category="ll", - direction="l", - }, - [0x2CBE]={ - category="lu", - direction="l", - }, - [0x2CBF]={ - category="ll", - direction="l", - }, - [0x2CC0]={ - category="lu", - direction="l", - }, - [0x2CC1]={ - category="ll", - direction="l", - }, - [0x2CC2]={ - category="lu", - direction="l", - }, - [0x2CC3]={ - category="ll", - direction="l", - }, - [0x2CC4]={ - category="lu", - direction="l", - }, - [0x2CC5]={ - category="ll", - direction="l", - }, - [0x2CC6]={ - category="lu", - direction="l", - }, - [0x2CC7]={ - category="ll", - direction="l", - }, - [0x2CC8]={ - category="lu", - direction="l", - }, - [0x2CC9]={ - category="ll", - direction="l", - }, - [0x2CCA]={ - category="lu", - direction="l", - }, - [0x2CCB]={ - category="ll", - direction="l", - }, - [0x2CCC]={ - category="lu", - direction="l", - }, - [0x2CCD]={ - category="ll", - direction="l", - }, - [0x2CCE]={ - category="lu", - direction="l", - }, - [0x2CCF]={ - category="ll", - direction="l", - }, - [0x2CD0]={ - category="lu", - direction="l", - }, - [0x2CD1]={ - category="ll", - direction="l", - }, - [0x2CD2]={ - category="lu", - direction="l", - }, - [0x2CD3]={ - category="ll", - direction="l", - }, - [0x2CD4]={ - category="lu", - direction="l", - }, - [0x2CD5]={ - category="ll", - direction="l", - }, - [0x2CD6]={ - category="lu", - direction="l", - }, - [0x2CD7]={ - category="ll", - direction="l", - }, - [0x2CD8]={ - category="lu", - direction="l", - }, - [0x2CD9]={ - category="ll", - direction="l", - }, - [0x2CDA]={ - category="lu", - direction="l", - }, - [0x2CDB]={ - category="ll", - direction="l", - }, - [0x2CDC]={ - category="lu", - direction="l", - }, - [0x2CDD]={ - category="ll", - direction="l", - }, - [0x2CDE]={ - category="lu", - direction="l", - }, - [0x2CDF]={ - category="ll", - direction="l", - }, - [0x2CE0]={ - category="lu", - direction="l", - }, - [0x2CE1]={ - category="ll", - direction="l", - }, - [0x2CE2]={ - category="lu", - direction="l", - }, - [0x2CE3]={ - category="ll", - direction="l", - }, - [0x2CE4]={ - category="ll", - direction="l", - }, - [0x2CE5]={ - category="so", - direction="on", - }, - [0x2CE6]={ - category="so", - direction="on", - }, - [0x2CE7]={ - category="so", - direction="on", - }, - [0x2CE8]={ - category="so", - direction="on", - }, - [0x2CE9]={ - category="so", - direction="on", - }, - [0x2CEA]={ - category="so", - direction="on", - }, - [0x2CEB]={ - category="lu", - direction="l", - }, - [0x2CEC]={ - category="ll", - direction="l", - }, - [0x2CED]={ - category="lu", - direction="l", - }, - [0x2CEE]={ - category="ll", - direction="l", - }, - [0x2CEF]={ - category="mn", - direction="nsm", - }, - [0x2CF0]={ - category="mn", - direction="nsm", - }, - [0x2CF1]={ - category="mn", - direction="nsm", - }, - [0x2CF2]={ - category="lu", - direction="l", - }, - [0x2CF3]={ - category="ll", - direction="l", - }, - [0x2CF9]={ - category="po", - direction="on", - }, - [0x2CFA]={ - category="po", - direction="on", - }, - [0x2CFB]={ - category="po", - direction="on", - }, - [0x2CFC]={ - category="po", - direction="on", - }, - [0x2CFD]={ - category="no", - direction="on", - }, - [0x2CFE]={ - category="po", - direction="on", - }, - [0x2CFF]={ - category="po", - direction="on", - }, - [0x2D00]={ - category="ll", - direction="l", - }, - [0x2D01]={ - category="ll", - direction="l", - }, - [0x2D02]={ - category="ll", - direction="l", - }, - [0x2D03]={ - category="ll", - direction="l", - }, - [0x2D04]={ - category="ll", - direction="l", - }, - [0x2D05]={ - category="ll", - direction="l", - }, - [0x2D06]={ - category="ll", - direction="l", - }, - [0x2D07]={ - category="ll", - direction="l", - }, - [0x2D08]={ - category="ll", - direction="l", - }, - [0x2D09]={ - category="ll", - direction="l", - }, - [0x2D0A]={ - category="ll", - direction="l", - }, - [0x2D0B]={ - category="ll", - direction="l", - }, - [0x2D0C]={ - category="ll", - direction="l", - }, - [0x2D0D]={ - category="ll", - direction="l", - }, - [0x2D0E]={ - category="ll", - direction="l", - }, - [0x2D0F]={ - category="ll", - direction="l", - }, - [0x2D10]={ - category="ll", - direction="l", - }, - [0x2D11]={ - category="ll", - direction="l", - }, - [0x2D12]={ - category="ll", - direction="l", - }, - [0x2D13]={ - category="ll", - direction="l", - }, - [0x2D14]={ - category="ll", - direction="l", - }, - [0x2D15]={ - category="ll", - direction="l", - }, - [0x2D16]={ - category="ll", - direction="l", - }, - [0x2D17]={ - category="ll", - direction="l", - }, - [0x2D18]={ - category="ll", - direction="l", - }, - [0x2D19]={ - category="ll", - direction="l", - }, - [0x2D1A]={ - category="ll", - direction="l", - }, - [0x2D1B]={ - category="ll", - direction="l", - }, - [0x2D1C]={ - category="ll", - direction="l", - }, - [0x2D1D]={ - category="ll", - direction="l", - }, - [0x2D1E]={ - category="ll", - direction="l", - }, - [0x2D1F]={ - category="ll", - direction="l", - }, - [0x2D20]={ - category="ll", - direction="l", - }, - [0x2D21]={ - category="ll", - direction="l", - }, - [0x2D22]={ - category="ll", - direction="l", - }, - [0x2D23]={ - category="ll", - direction="l", - }, - [0x2D24]={ - category="ll", - direction="l", - }, - [0x2D25]={ - category="ll", - direction="l", - }, - [0x2D27]={ - category="ll", - direction="l", - }, - [0x2D2D]={ - category="ll", - direction="l", - }, - [0x2D30]={ - category="lo", - direction="l", - }, - [0x2D31]={ - category="lo", - direction="l", - }, - [0x2D32]={ - category="lo", - direction="l", - }, - [0x2D33]={ - category="lo", - direction="l", - }, - [0x2D34]={ - category="lo", - direction="l", - }, - [0x2D35]={ - category="lo", - direction="l", - }, - [0x2D36]={ - category="lo", - direction="l", - }, - [0x2D37]={ - category="lo", - direction="l", - }, - [0x2D38]={ - category="lo", - direction="l", - }, - [0x2D39]={ - category="lo", - direction="l", - }, - [0x2D3A]={ - category="lo", - direction="l", - }, - [0x2D3B]={ - category="lo", - direction="l", - }, - [0x2D3C]={ - category="lo", - direction="l", - }, - [0x2D3D]={ - category="lo", - direction="l", - }, - [0x2D3E]={ - category="lo", - direction="l", - }, - [0x2D3F]={ - category="lo", - direction="l", - }, - [0x2D40]={ - category="lo", - direction="l", - }, - [0x2D41]={ - category="lo", - direction="l", - }, - [0x2D42]={ - category="lo", - direction="l", - }, - [0x2D43]={ - category="lo", - direction="l", - }, - [0x2D44]={ - category="lo", - direction="l", - }, - [0x2D45]={ - category="lo", - direction="l", - }, - [0x2D46]={ - category="lo", - direction="l", - }, - [0x2D47]={ - category="lo", - direction="l", - }, - [0x2D48]={ - category="lo", - direction="l", - }, - [0x2D49]={ - category="lo", - direction="l", - }, - [0x2D4A]={ - category="lo", - direction="l", - }, - [0x2D4B]={ - category="lo", - direction="l", - }, - [0x2D4C]={ - category="lo", - direction="l", - }, - [0x2D4D]={ - category="lo", - direction="l", - }, - [0x2D4E]={ - category="lo", - direction="l", - }, - [0x2D4F]={ - category="lo", - direction="l", - }, - [0x2D50]={ - category="lo", - direction="l", - }, - [0x2D51]={ - category="lo", - direction="l", - }, - [0x2D52]={ - category="lo", - direction="l", - }, - [0x2D53]={ - category="lo", - direction="l", - }, - [0x2D54]={ - category="lo", - direction="l", - }, - [0x2D55]={ - category="lo", - direction="l", - }, - [0x2D56]={ - category="lo", - direction="l", - }, - [0x2D57]={ - category="lo", - direction="l", - }, - [0x2D58]={ - category="lo", - direction="l", - }, - [0x2D59]={ - category="lo", - direction="l", - }, - [0x2D5A]={ - category="lo", - direction="l", - }, - [0x2D5B]={ - category="lo", - direction="l", - }, - [0x2D5C]={ - category="lo", - direction="l", - }, - [0x2D5D]={ - category="lo", - direction="l", - }, - [0x2D5E]={ - category="lo", - direction="l", - }, - [0x2D5F]={ - category="lo", - direction="l", - }, - [0x2D60]={ - category="lo", - direction="l", - }, - [0x2D61]={ - category="lo", - direction="l", - }, - [0x2D62]={ - category="lo", - direction="l", - }, - [0x2D63]={ - category="lo", - direction="l", - }, - [0x2D64]={ - category="lo", - direction="l", - }, - [0x2D65]={ - category="lo", - direction="l", - }, - [0x2D66]={ - category="lo", - direction="l", - }, - [0x2D67]={ - category="lo", - direction="l", - }, - [0x2D6F]={ - category="lm", - direction="l", - }, - [0x2D70]={ - category="po", - direction="l", - }, - [0x2D7F]={ - category="mn", - direction="nsm", - }, - [0x2D80]={ - category="lo", - direction="l", - }, - [0x2D81]={ - category="lo", - direction="l", - }, - [0x2D82]={ - category="lo", - direction="l", - }, - [0x2D83]={ - category="lo", - direction="l", - }, - [0x2D84]={ - category="lo", - direction="l", - }, - [0x2D85]={ - category="lo", - direction="l", - }, - [0x2D86]={ - category="lo", - direction="l", - }, - [0x2D87]={ - category="lo", - direction="l", - }, - [0x2D88]={ - category="lo", - direction="l", - }, - [0x2D89]={ - category="lo", - direction="l", - }, - [0x2D8A]={ - category="lo", - direction="l", - }, - [0x2D8B]={ - category="lo", - direction="l", - }, - [0x2D8C]={ - category="lo", - direction="l", - }, - [0x2D8D]={ - category="lo", - direction="l", - }, - [0x2D8E]={ - category="lo", - direction="l", - }, - [0x2D8F]={ - category="lo", - direction="l", - }, - [0x2D90]={ - category="lo", - direction="l", - }, - [0x2D91]={ - category="lo", - direction="l", - }, - [0x2D92]={ - category="lo", - direction="l", - }, - [0x2D93]={ - category="lo", - direction="l", - }, - [0x2D94]={ - category="lo", - direction="l", - }, - [0x2D95]={ - category="lo", - direction="l", - }, - [0x2D96]={ - category="lo", - direction="l", - }, - [0x2DA0]={ - category="lo", - direction="l", - }, - [0x2DA1]={ - category="lo", - direction="l", - }, - [0x2DA2]={ - category="lo", - direction="l", - }, - [0x2DA3]={ - category="lo", - direction="l", - }, - [0x2DA4]={ - category="lo", - direction="l", - }, - [0x2DA5]={ - category="lo", - direction="l", - }, - [0x2DA6]={ - category="lo", - direction="l", - }, - [0x2DA8]={ - category="lo", - direction="l", - }, - [0x2DA9]={ - category="lo", - direction="l", - }, - [0x2DAA]={ - category="lo", - direction="l", - }, - [0x2DAB]={ - category="lo", - direction="l", - }, - [0x2DAC]={ - category="lo", - direction="l", - }, - [0x2DAD]={ - category="lo", - direction="l", - }, - [0x2DAE]={ - category="lo", - direction="l", - }, - [0x2DB0]={ - category="lo", - direction="l", - }, - [0x2DB1]={ - category="lo", - direction="l", - }, - [0x2DB2]={ - category="lo", - direction="l", - }, - [0x2DB3]={ - category="lo", - direction="l", - }, - [0x2DB4]={ - category="lo", - direction="l", - }, - [0x2DB5]={ - category="lo", - direction="l", - }, - [0x2DB6]={ - category="lo", - direction="l", - }, - [0x2DB8]={ - category="lo", - direction="l", - }, - [0x2DB9]={ - category="lo", - direction="l", - }, - [0x2DBA]={ - category="lo", - direction="l", - }, - [0x2DBB]={ - category="lo", - direction="l", - }, - [0x2DBC]={ - category="lo", - direction="l", - }, - [0x2DBD]={ - category="lo", - direction="l", - }, - [0x2DBE]={ - category="lo", - direction="l", - }, - [0x2DC0]={ - category="lo", - direction="l", - }, - [0x2DC1]={ - category="lo", - direction="l", - }, - [0x2DC2]={ - category="lo", - direction="l", - }, - [0x2DC3]={ - category="lo", - direction="l", - }, - [0x2DC4]={ - category="lo", - direction="l", - }, - [0x2DC5]={ - category="lo", - direction="l", - }, - [0x2DC6]={ - category="lo", - direction="l", - }, - [0x2DC8]={ - category="lo", - direction="l", - }, - [0x2DC9]={ - category="lo", - direction="l", - }, - [0x2DCA]={ - category="lo", - direction="l", - }, - [0x2DCB]={ - category="lo", - direction="l", - }, - [0x2DCC]={ - category="lo", - direction="l", - }, - [0x2DCD]={ - category="lo", - direction="l", - }, - [0x2DCE]={ - category="lo", - direction="l", - }, - [0x2DD0]={ - category="lo", - direction="l", - }, - [0x2DD1]={ - category="lo", - direction="l", - }, - [0x2DD2]={ - category="lo", - direction="l", - }, - [0x2DD3]={ - category="lo", - direction="l", - }, - [0x2DD4]={ - category="lo", - direction="l", - }, - [0x2DD5]={ - category="lo", - direction="l", - }, - [0x2DD6]={ - category="lo", - direction="l", - }, - [0x2DD8]={ - category="lo", - direction="l", - }, - [0x2DD9]={ - category="lo", - direction="l", - }, - [0x2DDA]={ - category="lo", - direction="l", - }, - [0x2DDB]={ - category="lo", - direction="l", - }, - [0x2DDC]={ - category="lo", - direction="l", - }, - [0x2DDD]={ - category="lo", - direction="l", - }, - [0x2DDE]={ - category="lo", - direction="l", - }, - [0x2DE0]={ - category="mn", - direction="nsm", - }, - [0x2DE1]={ - category="mn", - direction="nsm", - }, - [0x2DE2]={ - category="mn", - direction="nsm", - }, - [0x2DE3]={ - category="mn", - direction="nsm", - }, - [0x2DE4]={ - category="mn", - direction="nsm", - }, - [0x2DE5]={ - category="mn", - direction="nsm", - }, - [0x2DE6]={ - category="mn", - direction="nsm", - }, - [0x2DE7]={ - category="mn", - direction="nsm", - }, - [0x2DE8]={ - category="mn", - direction="nsm", - }, - [0x2DE9]={ - category="mn", - direction="nsm", - }, - [0x2DEA]={ - category="mn", - direction="nsm", - }, - [0x2DEB]={ - category="mn", - direction="nsm", - }, - [0x2DEC]={ - category="mn", - direction="nsm", - }, - [0x2DED]={ - category="mn", - direction="nsm", - }, - [0x2DEE]={ - category="mn", - direction="nsm", - }, - [0x2DEF]={ - category="mn", - direction="nsm", - }, - [0x2DF0]={ - category="mn", - direction="nsm", - }, - [0x2DF1]={ - category="mn", - direction="nsm", - }, - [0x2DF2]={ - category="mn", - direction="nsm", - }, - [0x2DF3]={ - category="mn", - direction="nsm", - }, - [0x2DF4]={ - category="mn", - direction="nsm", - }, - [0x2DF5]={ - category="mn", - direction="nsm", - }, - [0x2DF6]={ - category="mn", - direction="nsm", - }, - [0x2DF7]={ - category="mn", - direction="nsm", - }, - [0x2DF8]={ - category="mn", - direction="nsm", - }, - [0x2DF9]={ - category="mn", - direction="nsm", - }, - [0x2DFA]={ - category="mn", - direction="nsm", - }, - [0x2DFB]={ - category="mn", - direction="nsm", - }, - [0x2DFC]={ - category="mn", - direction="nsm", - }, - [0x2DFD]={ - category="mn", - direction="nsm", - }, - [0x2DFE]={ - category="mn", - direction="nsm", - }, - [0x2DFF]={ - category="mn", - direction="nsm", - }, - [0x2E00]={ - category="po", - direction="on", - }, - [0x2E01]={ - category="po", - direction="on", - }, - [0x2E02]={ - category="pi", - direction="on", - mirror=0x2E03, - }, - [0x2E03]={ - category="pf", - direction="on", - mirror=0x2E02, - }, - [0x2E04]={ - category="pi", - direction="on", - mirror=0x2E05, - }, - [0x2E05]={ - category="pf", - direction="on", - mirror=0x2E04, - }, - [0x2E06]={ - category="po", - direction="on", - }, - [0x2E07]={ - category="po", - direction="on", - }, - [0x2E08]={ - category="po", - direction="on", - }, - [0x2E09]={ - category="pi", - direction="on", - mirror=0x2E0A, - }, - [0x2E0A]={ - category="pf", - direction="on", - mirror=0x2E09, - }, - [0x2E0B]={ - category="po", - direction="on", - }, - [0x2E0C]={ - category="pi", - direction="on", - mirror=0x2E0D, - }, - [0x2E0D]={ - category="pf", - direction="on", - mirror=0x2E0C, - }, - [0x2E0E]={ - category="po", - direction="on", - }, - [0x2E0F]={ - category="po", - direction="on", - }, - [0x2E10]={ - category="po", - direction="on", - }, - [0x2E11]={ - category="po", - direction="on", - }, - [0x2E12]={ - category="po", - direction="on", - }, - [0x2E13]={ - category="po", - direction="on", - }, - [0x2E14]={ - category="po", - direction="on", - }, - [0x2E15]={ - category="po", - direction="on", - }, - [0x2E16]={ - category="po", - direction="on", - }, - [0x2E17]={ - category="pd", - direction="on", - }, - [0x2E18]={ - category="po", - direction="on", - }, - [0x2E19]={ - category="po", - direction="on", - }, - [0x2E1A]={ - category="pd", - direction="on", - }, - [0x2E1B]={ - category="po", - direction="on", - }, - [0x2E1C]={ - category="pi", - direction="on", - mirror=0x2E1D, - }, - [0x2E1D]={ - category="pf", - direction="on", - mirror=0x2E1C, - }, - [0x2E1E]={ - category="po", - direction="on", - }, - [0x2E1F]={ - category="po", - direction="on", - }, - [0x2E20]={ - category="pi", - direction="on", - mirror=0x2E21, - }, - [0x2E21]={ - category="pf", - direction="on", - mirror=0x2E20, - }, - [0x2E22]={ - category="ps", - direction="on", - mirror=0x2E23, - }, - [0x2E23]={ - category="pe", - direction="on", - mirror=0x2E22, - }, - [0x2E24]={ - category="ps", - direction="on", - mirror=0x2E25, - }, - [0x2E25]={ - category="pe", - direction="on", - mirror=0x2E24, - }, - [0x2E26]={ - category="ps", - direction="on", - mirror=0x2E27, - }, - [0x2E27]={ - category="pe", - direction="on", - mirror=0x2E26, - }, - [0x2E28]={ - category="ps", - direction="on", - mirror=0x2E29, - }, - [0x2E29]={ - category="pe", - direction="on", - mirror=0x2E28, - }, - [0x2E2A]={ - category="po", - direction="on", - }, - [0x2E2B]={ - category="po", - direction="on", - }, - [0x2E2C]={ - category="po", - direction="on", - }, - [0x2E2D]={ - category="po", - direction="on", - }, - [0x2E2E]={ - category="po", - direction="on", - }, - [0x2E2F]={ - category="lm", - direction="on", - }, - [0x2E30]={ - category="po", - direction="on", - }, - [0x2E31]={ - category="po", - direction="on", - }, - [0x2E32]={ - category="po", - direction="on", - }, - [0x2E33]={ - category="po", - direction="on", - }, - [0x2E34]={ - category="po", - direction="on", - }, - [0x2E35]={ - category="po", - direction="on", - }, - [0x2E36]={ - category="po", - direction="on", - }, - [0x2E37]={ - category="po", - direction="on", - }, - [0x2E38]={ - category="po", - direction="on", - }, - [0x2E39]={ - category="po", - direction="on", - }, - [0x2E3A]={ - category="pd", - direction="on", - }, - [0x2E3B]={ - category="pd", - direction="on", - }, - [0x2E3C]={ - category="po", - direction="on", - }, - [0x2E3D]={ - category="po", - direction="on", - }, - [0x2E3E]={ - category="po", - direction="on", - }, - [0x2E3F]={ - category="po", - direction="on", - }, - [0x2E40]={ - category="pd", - direction="on", - }, - [0x2E41]={ - category="po", - direction="on", - }, - [0x2E42]={ - category="ps", - direction="on", - }, - [0x2E43]={ - category="po", - direction="on", - }, - [0x2E44]={ - category="po", - direction="on", - }, - [0x2E80]={ - category="so", - direction="on", - }, - [0x2E81]={ - category="so", - direction="on", - }, - [0x2E82]={ - category="so", - direction="on", - }, - [0x2E83]={ - category="so", - direction="on", - }, - [0x2E84]={ - category="so", - direction="on", - }, - [0x2E85]={ - category="so", - direction="on", - }, - [0x2E86]={ - category="so", - direction="on", - }, - [0x2E87]={ - category="so", - direction="on", - }, - [0x2E88]={ - category="so", - direction="on", - }, - [0x2E89]={ - category="so", - direction="on", - }, - [0x2E8A]={ - category="so", - direction="on", - }, - [0x2E8B]={ - category="so", - direction="on", - }, - [0x2E8C]={ - category="so", - direction="on", - }, - [0x2E8D]={ - category="so", - direction="on", - }, - [0x2E8E]={ - category="so", - direction="on", - }, - [0x2E8F]={ - category="so", - direction="on", - }, - [0x2E90]={ - category="so", - direction="on", - }, - [0x2E91]={ - category="so", - direction="on", - }, - [0x2E92]={ - category="so", - direction="on", - }, - [0x2E93]={ - category="so", - direction="on", - }, - [0x2E94]={ - category="so", - direction="on", - }, - [0x2E95]={ - category="so", - direction="on", - }, - [0x2E96]={ - category="so", - direction="on", - }, - [0x2E97]={ - category="so", - direction="on", - }, - [0x2E98]={ - category="so", - direction="on", - }, - [0x2E99]={ - category="so", - direction="on", - }, - [0x2E9B]={ - category="so", - direction="on", - }, - [0x2E9C]={ - category="so", - direction="on", - }, - [0x2E9D]={ - category="so", - direction="on", - }, - [0x2E9E]={ - category="so", - direction="on", - }, - [0x2E9F]={ - category="so", - direction="on", - }, - [0x2EA0]={ - category="so", - direction="on", - }, - [0x2EA1]={ - category="so", - direction="on", - }, - [0x2EA2]={ - category="so", - direction="on", - }, - [0x2EA3]={ - category="so", - direction="on", - }, - [0x2EA4]={ - category="so", - direction="on", - }, - [0x2EA5]={ - category="so", - direction="on", - }, - [0x2EA6]={ - category="so", - direction="on", - }, - [0x2EA7]={ - category="so", - direction="on", - }, - [0x2EA8]={ - category="so", - direction="on", - }, - [0x2EA9]={ - category="so", - direction="on", - }, - [0x2EAA]={ - category="so", - direction="on", - }, - [0x2EAB]={ - category="so", - direction="on", - }, - [0x2EAC]={ - category="so", - direction="on", - }, - [0x2EAD]={ - category="so", - direction="on", - }, - [0x2EAE]={ - category="so", - direction="on", - }, - [0x2EAF]={ - category="so", - direction="on", - }, - [0x2EB0]={ - category="so", - direction="on", - }, - [0x2EB1]={ - category="so", - direction="on", - }, - [0x2EB2]={ - category="so", - direction="on", - }, - [0x2EB3]={ - category="so", - direction="on", - }, - [0x2EB4]={ - category="so", - direction="on", - }, - [0x2EB5]={ - category="so", - direction="on", - }, - [0x2EB6]={ - category="so", - direction="on", - }, - [0x2EB7]={ - category="so", - direction="on", - }, - [0x2EB8]={ - category="so", - direction="on", - }, - [0x2EB9]={ - category="so", - direction="on", - }, - [0x2EBA]={ - category="so", - direction="on", - }, - [0x2EBB]={ - category="so", - direction="on", - }, - [0x2EBC]={ - category="so", - direction="on", - }, - [0x2EBD]={ - category="so", - direction="on", - }, - [0x2EBE]={ - category="so", - direction="on", - }, - [0x2EBF]={ - category="so", - direction="on", - }, - [0x2EC0]={ - category="so", - direction="on", - }, - [0x2EC1]={ - category="so", - direction="on", - }, - [0x2EC2]={ - category="so", - direction="on", - }, - [0x2EC3]={ - category="so", - direction="on", - }, - [0x2EC4]={ - category="so", - direction="on", - }, - [0x2EC5]={ - category="so", - direction="on", - }, - [0x2EC6]={ - category="so", - direction="on", - }, - [0x2EC7]={ - category="so", - direction="on", - }, - [0x2EC8]={ - category="so", - direction="on", - }, - [0x2EC9]={ - category="so", - direction="on", - }, - [0x2ECA]={ - category="so", - direction="on", - }, - [0x2ECB]={ - category="so", - direction="on", - }, - [0x2ECC]={ - category="so", - direction="on", - }, - [0x2ECD]={ - category="so", - direction="on", - }, - [0x2ECE]={ - category="so", - direction="on", - }, - [0x2ECF]={ - category="so", - direction="on", - }, - [0x2ED0]={ - category="so", - direction="on", - }, - [0x2ED1]={ - category="so", - direction="on", - }, - [0x2ED2]={ - category="so", - direction="on", - }, - [0x2ED3]={ - category="so", - direction="on", - }, - [0x2ED4]={ - category="so", - direction="on", - }, - [0x2ED5]={ - category="so", - direction="on", - }, - [0x2ED6]={ - category="so", - direction="on", - }, - [0x2ED7]={ - category="so", - direction="on", - }, - [0x2ED8]={ - category="so", - direction="on", - }, - [0x2ED9]={ - category="so", - direction="on", - }, - [0x2EDA]={ - category="so", - direction="on", - }, - [0x2EDB]={ - category="so", - direction="on", - }, - [0x2EDC]={ - category="so", - direction="on", - }, - [0x2EDD]={ - category="so", - direction="on", - }, - [0x2EDE]={ - category="so", - direction="on", - }, - [0x2EDF]={ - category="so", - direction="on", - }, - [0x2EE0]={ - category="so", - direction="on", - }, - [0x2EE1]={ - category="so", - direction="on", - }, - [0x2EE2]={ - category="so", - direction="on", - }, - [0x2EE3]={ - category="so", - direction="on", - }, - [0x2EE4]={ - category="so", - direction="on", - }, - [0x2EE5]={ - category="so", - direction="on", - }, - [0x2EE6]={ - category="so", - direction="on", - }, - [0x2EE7]={ - category="so", - direction="on", - }, - [0x2EE8]={ - category="so", - direction="on", - }, - [0x2EE9]={ - category="so", - direction="on", - }, - [0x2EEA]={ - category="so", - direction="on", - }, - [0x2EEB]={ - category="so", - direction="on", - }, - [0x2EEC]={ - category="so", - direction="on", - }, - [0x2EED]={ - category="so", - direction="on", - }, - [0x2EEE]={ - category="so", - direction="on", - }, - [0x2EEF]={ - category="so", - direction="on", - }, - [0x2EF0]={ - category="so", - direction="on", - }, - [0x2EF1]={ - category="so", - direction="on", - }, - [0x2EF2]={ - category="so", - direction="on", - }, - [0x2EF3]={ - category="so", - direction="on", - }, - [0x2F00]={ - category="so", - direction="on", - }, - [0x2F01]={ - category="so", - direction="on", - }, - [0x2F02]={ - category="so", - direction="on", - }, - [0x2F03]={ - category="so", - direction="on", - }, - [0x2F04]={ - category="so", - direction="on", - }, - [0x2F05]={ - category="so", - direction="on", - }, - [0x2F06]={ - category="so", - direction="on", - }, - [0x2F07]={ - category="so", - direction="on", - }, - [0x2F08]={ - category="so", - direction="on", - }, - [0x2F09]={ - category="so", - direction="on", - }, - [0x2F0A]={ - category="so", - direction="on", - }, - [0x2F0B]={ - category="so", - direction="on", - }, - [0x2F0C]={ - category="so", - direction="on", - }, - [0x2F0D]={ - category="so", - direction="on", - }, - [0x2F0E]={ - category="so", - direction="on", - }, - [0x2F0F]={ - category="so", - direction="on", - }, - [0x2F10]={ - category="so", - direction="on", - }, - [0x2F11]={ - category="so", - direction="on", - }, - [0x2F12]={ - category="so", - direction="on", - }, - [0x2F13]={ - category="so", - direction="on", - }, - [0x2F14]={ - category="so", - direction="on", - }, - [0x2F15]={ - category="so", - direction="on", - }, - [0x2F16]={ - category="so", - direction="on", - }, - [0x2F17]={ - category="so", - direction="on", - }, - [0x2F18]={ - category="so", - direction="on", - }, - [0x2F19]={ - category="so", - direction="on", - }, - [0x2F1A]={ - category="so", - direction="on", - }, - [0x2F1B]={ - category="so", - direction="on", - }, - [0x2F1C]={ - category="so", - direction="on", - }, - [0x2F1D]={ - category="so", - direction="on", - }, - [0x2F1E]={ - category="so", - direction="on", - }, - [0x2F1F]={ - category="so", - direction="on", - }, - [0x2F20]={ - category="so", - direction="on", - }, - [0x2F21]={ - category="so", - direction="on", - }, - [0x2F22]={ - category="so", - direction="on", - }, - [0x2F23]={ - category="so", - direction="on", - }, - [0x2F24]={ - category="so", - direction="on", - }, - [0x2F25]={ - category="so", - direction="on", - }, - [0x2F26]={ - category="so", - direction="on", - }, - [0x2F27]={ - category="so", - direction="on", - }, - [0x2F28]={ - category="so", - direction="on", - }, - [0x2F29]={ - category="so", - direction="on", - }, - [0x2F2A]={ - category="so", - direction="on", - }, - [0x2F2B]={ - category="so", - direction="on", - }, - [0x2F2C]={ - category="so", - direction="on", - }, - [0x2F2D]={ - category="so", - direction="on", - }, - [0x2F2E]={ - category="so", - direction="on", - }, - [0x2F2F]={ - category="so", - direction="on", - }, - [0x2F30]={ - category="so", - direction="on", - }, - [0x2F31]={ - category="so", - direction="on", - }, - [0x2F32]={ - category="so", - direction="on", - }, - [0x2F33]={ - category="so", - direction="on", - }, - [0x2F34]={ - category="so", - direction="on", - }, - [0x2F35]={ - category="so", - direction="on", - }, - [0x2F36]={ - category="so", - direction="on", - }, - [0x2F37]={ - category="so", - direction="on", - }, - [0x2F38]={ - category="so", - direction="on", - }, - [0x2F39]={ - category="so", - direction="on", - }, - [0x2F3A]={ - category="so", - direction="on", - }, - [0x2F3B]={ - category="so", - direction="on", - }, - [0x2F3C]={ - category="so", - direction="on", - }, - [0x2F3D]={ - category="so", - direction="on", - }, - [0x2F3E]={ - category="so", - direction="on", - }, - [0x2F3F]={ - category="so", - direction="on", - }, - [0x2F40]={ - category="so", - direction="on", - }, - [0x2F41]={ - category="so", - direction="on", - }, - [0x2F42]={ - category="so", - direction="on", - }, - [0x2F43]={ - category="so", - direction="on", - }, - [0x2F44]={ - category="so", - direction="on", - }, - [0x2F45]={ - category="so", - direction="on", - }, - [0x2F46]={ - category="so", - direction="on", - }, - [0x2F47]={ - category="so", - direction="on", - }, - [0x2F48]={ - category="so", - direction="on", - }, - [0x2F49]={ - category="so", - direction="on", - }, - [0x2F4A]={ - category="so", - direction="on", - }, - [0x2F4B]={ - category="so", - direction="on", - }, - [0x2F4C]={ - category="so", - direction="on", - }, - [0x2F4D]={ - category="so", - direction="on", - }, - [0x2F4E]={ - category="so", - direction="on", - }, - [0x2F4F]={ - category="so", - direction="on", - }, - [0x2F50]={ - category="so", - direction="on", - }, - [0x2F51]={ - category="so", - direction="on", - }, - [0x2F52]={ - category="so", - direction="on", - }, - [0x2F53]={ - category="so", - direction="on", - }, - [0x2F54]={ - category="so", - direction="on", - }, - [0x2F55]={ - category="so", - direction="on", - }, - [0x2F56]={ - category="so", - direction="on", - }, - [0x2F57]={ - category="so", - direction="on", - }, - [0x2F58]={ - category="so", - direction="on", - }, - [0x2F59]={ - category="so", - direction="on", - }, - [0x2F5A]={ - category="so", - direction="on", - }, - [0x2F5B]={ - category="so", - direction="on", - }, - [0x2F5C]={ - category="so", - direction="on", - }, - [0x2F5D]={ - category="so", - direction="on", - }, - [0x2F5E]={ - category="so", - direction="on", - }, - [0x2F5F]={ - category="so", - direction="on", - }, - [0x2F60]={ - category="so", - direction="on", - }, - [0x2F61]={ - category="so", - direction="on", - }, - [0x2F62]={ - category="so", - direction="on", - }, - [0x2F63]={ - category="so", - direction="on", - }, - [0x2F64]={ - category="so", - direction="on", - }, - [0x2F65]={ - category="so", - direction="on", - }, - [0x2F66]={ - category="so", - direction="on", - }, - [0x2F67]={ - category="so", - direction="on", - }, - [0x2F68]={ - category="so", - direction="on", - }, - [0x2F69]={ - category="so", - direction="on", - }, - [0x2F6A]={ - category="so", - direction="on", - }, - [0x2F6B]={ - category="so", - direction="on", - }, - [0x2F6C]={ - category="so", - direction="on", - }, - [0x2F6D]={ - category="so", - direction="on", - }, - [0x2F6E]={ - category="so", - direction="on", - }, - [0x2F6F]={ - category="so", - direction="on", - }, - [0x2F70]={ - category="so", - direction="on", - }, - [0x2F71]={ - category="so", - direction="on", - }, - [0x2F72]={ - category="so", - direction="on", - }, - [0x2F73]={ - category="so", - direction="on", - }, - [0x2F74]={ - category="so", - direction="on", - }, - [0x2F75]={ - category="so", - direction="on", - }, - [0x2F76]={ - category="so", - direction="on", - }, - [0x2F77]={ - category="so", - direction="on", - }, - [0x2F78]={ - category="so", - direction="on", - }, - [0x2F79]={ - category="so", - direction="on", - }, - [0x2F7A]={ - category="so", - direction="on", - }, - [0x2F7B]={ - category="so", - direction="on", - }, - [0x2F7C]={ - category="so", - direction="on", - }, - [0x2F7D]={ - category="so", - direction="on", - }, - [0x2F7E]={ - category="so", - direction="on", - }, - [0x2F7F]={ - category="so", - direction="on", - }, - [0x2F80]={ - category="so", - direction="on", - }, - [0x2F81]={ - category="so", - direction="on", - }, - [0x2F82]={ - category="so", - direction="on", - }, - [0x2F83]={ - category="so", - direction="on", - }, - [0x2F84]={ - category="so", - direction="on", - }, - [0x2F85]={ - category="so", - direction="on", - }, - [0x2F86]={ - category="so", - direction="on", - }, - [0x2F87]={ - category="so", - direction="on", - }, - [0x2F88]={ - category="so", - direction="on", - }, - [0x2F89]={ - category="so", - direction="on", - }, - [0x2F8A]={ - category="so", - direction="on", - }, - [0x2F8B]={ - category="so", - direction="on", - }, - [0x2F8C]={ - category="so", - direction="on", - }, - [0x2F8D]={ - category="so", - direction="on", - }, - [0x2F8E]={ - category="so", - direction="on", - }, - [0x2F8F]={ - category="so", - direction="on", - }, - [0x2F90]={ - category="so", - direction="on", - }, - [0x2F91]={ - category="so", - direction="on", - }, - [0x2F92]={ - category="so", - direction="on", - }, - [0x2F93]={ - category="so", - direction="on", - }, - [0x2F94]={ - category="so", - direction="on", - }, - [0x2F95]={ - category="so", - direction="on", - }, - [0x2F96]={ - category="so", - direction="on", - }, - [0x2F97]={ - category="so", - direction="on", - }, - [0x2F98]={ - category="so", - direction="on", - }, - [0x2F99]={ - category="so", - direction="on", - }, - [0x2F9A]={ - category="so", - direction="on", - }, - [0x2F9B]={ - category="so", - direction="on", - }, - [0x2F9C]={ - category="so", - direction="on", - }, - [0x2F9D]={ - category="so", - direction="on", - }, - [0x2F9E]={ - category="so", - direction="on", - }, - [0x2F9F]={ - category="so", - direction="on", - }, - [0x2FA0]={ - category="so", - direction="on", - }, - [0x2FA1]={ - category="so", - direction="on", - }, - [0x2FA2]={ - category="so", - direction="on", - }, - [0x2FA3]={ - category="so", - direction="on", - }, - [0x2FA4]={ - category="so", - direction="on", - }, - [0x2FA5]={ - category="so", - direction="on", - }, - [0x2FA6]={ - category="so", - direction="on", - }, - [0x2FA7]={ - category="so", - direction="on", - }, - [0x2FA8]={ - category="so", - direction="on", - }, - [0x2FA9]={ - category="so", - direction="on", - }, - [0x2FAA]={ - category="so", - direction="on", - }, - [0x2FAB]={ - category="so", - direction="on", - }, - [0x2FAC]={ - category="so", - direction="on", - }, - [0x2FAD]={ - category="so", - direction="on", - }, - [0x2FAE]={ - category="so", - direction="on", - }, - [0x2FAF]={ - category="so", - direction="on", - }, - [0x2FB0]={ - category="so", - direction="on", - }, - [0x2FB1]={ - category="so", - direction="on", - }, - [0x2FB2]={ - category="so", - direction="on", - }, - [0x2FB3]={ - category="so", - direction="on", - }, - [0x2FB4]={ - category="so", - direction="on", - }, - [0x2FB5]={ - category="so", - direction="on", - }, - [0x2FB6]={ - category="so", - direction="on", - }, - [0x2FB7]={ - category="so", - direction="on", - }, - [0x2FB8]={ - category="so", - direction="on", - }, - [0x2FB9]={ - category="so", - direction="on", - }, - [0x2FBA]={ - category="so", - direction="on", - }, - [0x2FBB]={ - category="so", - direction="on", - }, - [0x2FBC]={ - category="so", - direction="on", - }, - [0x2FBD]={ - category="so", - direction="on", - }, - [0x2FBE]={ - category="so", - direction="on", - }, - [0x2FBF]={ - category="so", - direction="on", - }, - [0x2FC0]={ - category="so", - direction="on", - }, - [0x2FC1]={ - category="so", - direction="on", - }, - [0x2FC2]={ - category="so", - direction="on", - }, - [0x2FC3]={ - category="so", - direction="on", - }, - [0x2FC4]={ - category="so", - direction="on", - }, - [0x2FC5]={ - category="so", - direction="on", - }, - [0x2FC6]={ - category="so", - direction="on", - }, - [0x2FC7]={ - category="so", - direction="on", - }, - [0x2FC8]={ - category="so", - direction="on", - }, - [0x2FC9]={ - category="so", - direction="on", - }, - [0x2FCA]={ - category="so", - direction="on", - }, - [0x2FCB]={ - category="so", - direction="on", - }, - [0x2FCC]={ - category="so", - direction="on", - }, - [0x2FCD]={ - category="so", - direction="on", - }, - [0x2FCE]={ - category="so", - direction="on", - }, - [0x2FCF]={ - category="so", - direction="on", - }, - [0x2FD0]={ - category="so", - direction="on", - }, - [0x2FD1]={ - category="so", - direction="on", - }, - [0x2FD2]={ - category="so", - direction="on", - }, - [0x2FD3]={ - category="so", - direction="on", - }, - [0x2FD4]={ - category="so", - direction="on", - }, - [0x2FD5]={ - category="so", - direction="on", - }, - [0x2FF0]={ - category="so", - direction="on", - }, - [0x2FF1]={ - category="so", - direction="on", - }, - [0x2FF2]={ - category="so", - direction="on", - }, - [0x2FF3]={ - category="so", - direction="on", - }, - [0x2FF4]={ - category="so", - direction="on", - }, - [0x2FF5]={ - category="so", - direction="on", - }, - [0x2FF6]={ - category="so", - direction="on", - }, - [0x2FF7]={ - category="so", - direction="on", - }, - [0x2FF8]={ - category="so", - direction="on", - }, - [0x2FF9]={ - category="so", - direction="on", - }, - [0x2FFA]={ - category="so", - direction="on", - }, - [0x2FFB]={ - category="so", - direction="on", - }, - [0x3000]={ - category="zs", - direction="ws", - }, - [0x3001]={ - category="po", - direction="on", - }, - [0x3002]={ - category="po", - direction="on", - }, - [0x3003]={ - category="po", - direction="on", - }, - [0x3004]={ - category="so", - direction="on", - }, - [0x3005]={ - category="lm", - direction="l", - }, - [0x3006]={ - category="lo", - direction="l", - }, - [0x3007]={ - category="nl", - direction="l", - }, - [0x3008]={ - category="ps", - direction="on", - mirror=0x3009, - }, - [0x3009]={ - category="pe", - direction="on", - mirror=0x3008, - }, - [0x300A]={ - category="ps", - direction="on", - mirror=0x300B, - }, - [0x300B]={ - category="pe", - direction="on", - mirror=0x300A, - }, - [0x300C]={ - category="ps", - direction="on", - mirror=0x300D, - }, - [0x300D]={ - category="pe", - direction="on", - mirror=0x300C, - }, - [0x300E]={ - category="ps", - direction="on", - mirror=0x300F, - }, - [0x300F]={ - category="pe", - direction="on", - mirror=0x300E, - }, - [0x3010]={ - category="ps", - direction="on", - mirror=0x3011, - }, - [0x3011]={ - category="pe", - direction="on", - mirror=0x3010, - }, - [0x3012]={ - category="so", - direction="on", - }, - [0x3013]={ - category="so", - direction="on", - }, - [0x3014]={ - category="ps", - direction="on", - mirror=0x3015, - }, - [0x3015]={ - category="pe", - direction="on", - mirror=0x3014, - }, - [0x3016]={ - category="ps", - direction="on", - mirror=0x3017, - }, - [0x3017]={ - category="pe", - direction="on", - mirror=0x3016, - }, - [0x3018]={ - category="ps", - direction="on", - mirror=0x3019, - }, - [0x3019]={ - category="pe", - direction="on", - mirror=0x3018, - }, - [0x301A]={ - category="ps", - direction="on", - mirror=0x301B, - }, - [0x301B]={ - category="pe", - direction="on", - mirror=0x301A, - }, - [0x301C]={ - category="pd", - direction="on", - }, - [0x301D]={ - category="ps", - direction="on", - }, - [0x301E]={ - category="pe", - direction="on", - }, - [0x301F]={ - category="pe", - direction="on", - }, - [0x3020]={ - category="so", - direction="on", - }, - [0x3021]={ - category="nl", - direction="l", - }, - [0x3022]={ - category="nl", - direction="l", - }, - [0x3023]={ - category="nl", - direction="l", - }, - [0x3024]={ - category="nl", - direction="l", - }, - [0x3025]={ - category="nl", - direction="l", - }, - [0x3026]={ - category="nl", - direction="l", - }, - [0x3027]={ - category="nl", - direction="l", - }, - [0x3028]={ - category="nl", - direction="l", - }, - [0x3029]={ - category="nl", - direction="l", - }, - [0x302A]={ - category="mn", - direction="nsm", - }, - [0x302B]={ - category="mn", - direction="nsm", - }, - [0x302C]={ - category="mn", - direction="nsm", - }, - [0x302D]={ - category="mn", - direction="nsm", - }, - [0x302E]={ - category="mn", - direction="l", - }, - [0x302F]={ - category="mn", - direction="l", - }, - [0x3030]={ - category="pd", - direction="on", - }, - [0x3031]={ - category="lm", - direction="l", - }, - [0x3032]={ - category="lm", - direction="l", - }, - [0x3033]={ - category="lm", - direction="l", - }, - [0x3034]={ - category="lm", - direction="l", - }, - [0x3035]={ - category="lm", - direction="l", - }, - [0x3036]={ - category="so", - direction="on", - }, - [0x3037]={ - category="so", - direction="on", - }, - [0x3038]={ - category="nl", - direction="l", - }, - [0x3039]={ - category="nl", - direction="l", - }, - [0x303A]={ - category="nl", - direction="l", - }, - [0x303B]={ - category="lm", - direction="l", - }, - [0x303C]={ - category="lo", - direction="l", - }, - [0x303D]={ - category="po", - direction="on", - }, - [0x303E]={ - category="so", - direction="on", - }, - [0x303F]={ - category="so", - direction="on", - }, - [0x3041]={ - category="lo", - direction="l", - }, - [0x3042]={ - category="lo", - direction="l", - }, - [0x3043]={ - category="lo", - direction="l", - }, - [0x3044]={ - category="lo", - direction="l", - }, - [0x3045]={ - category="lo", - direction="l", - }, - [0x3046]={ - category="lo", - direction="l", - }, - [0x3047]={ - category="lo", - direction="l", - }, - [0x3048]={ - category="lo", - direction="l", - }, - [0x3049]={ - category="lo", - direction="l", - }, - [0x304A]={ - category="lo", - direction="l", - }, - [0x304B]={ - category="lo", - direction="l", - }, - [0x304C]={ - category="lo", - direction="l", - }, - [0x304D]={ - category="lo", - direction="l", - }, - [0x304E]={ - category="lo", - direction="l", - }, - [0x304F]={ - category="lo", - direction="l", - }, - [0x3050]={ - category="lo", - direction="l", - }, - [0x3051]={ - category="lo", - direction="l", - }, - [0x3052]={ - category="lo", - direction="l", - }, - [0x3053]={ - category="lo", - direction="l", - }, - [0x3054]={ - category="lo", - direction="l", - }, - [0x3055]={ - category="lo", - direction="l", - }, - [0x3056]={ - category="lo", - direction="l", - }, - [0x3057]={ - category="lo", - direction="l", - }, - [0x3058]={ - category="lo", - direction="l", - }, - [0x3059]={ - category="lo", - direction="l", - }, - [0x305A]={ - category="lo", - direction="l", - }, - [0x305B]={ - category="lo", - direction="l", - }, - [0x305C]={ - category="lo", - direction="l", - }, - [0x305D]={ - category="lo", - direction="l", - }, - [0x305E]={ - category="lo", - direction="l", - }, - [0x305F]={ - category="lo", - direction="l", - }, - [0x3060]={ - category="lo", - direction="l", - }, - [0x3061]={ - category="lo", - direction="l", - }, - [0x3062]={ - category="lo", - direction="l", - }, - [0x3063]={ - category="lo", - direction="l", - }, - [0x3064]={ - category="lo", - direction="l", - }, - [0x3065]={ - category="lo", - direction="l", - }, - [0x3066]={ - category="lo", - direction="l", - }, - [0x3067]={ - category="lo", - direction="l", - }, - [0x3068]={ - category="lo", - direction="l", - }, - [0x3069]={ - category="lo", - direction="l", - }, - [0x306A]={ - category="lo", - direction="l", - }, - [0x306B]={ - category="lo", - direction="l", - }, - [0x306C]={ - category="lo", - direction="l", - }, - [0x306D]={ - category="lo", - direction="l", - }, - [0x306E]={ - category="lo", - direction="l", - }, - [0x306F]={ - category="lo", - direction="l", - }, - [0x3070]={ - category="lo", - direction="l", - }, - [0x3071]={ - category="lo", - direction="l", - }, - [0x3072]={ - category="lo", - direction="l", - }, - [0x3073]={ - category="lo", - direction="l", - }, - [0x3074]={ - category="lo", - direction="l", - }, - [0x3075]={ - category="lo", - direction="l", - }, - [0x3076]={ - category="lo", - direction="l", - }, - [0x3077]={ - category="lo", - direction="l", - }, - [0x3078]={ - category="lo", - direction="l", - }, - [0x3079]={ - category="lo", - direction="l", - }, - [0x307A]={ - category="lo", - direction="l", - }, - [0x307B]={ - category="lo", - direction="l", - }, - [0x307C]={ - category="lo", - direction="l", - }, - [0x307D]={ - category="lo", - direction="l", - }, - [0x307E]={ - category="lo", - direction="l", - }, - [0x307F]={ - category="lo", - direction="l", - }, - [0x3080]={ - category="lo", - direction="l", - }, - [0x3081]={ - category="lo", - direction="l", - }, - [0x3082]={ - category="lo", - direction="l", - }, - [0x3083]={ - category="lo", - direction="l", - }, - [0x3084]={ - category="lo", - direction="l", - }, - [0x3085]={ - category="lo", - direction="l", - }, - [0x3086]={ - category="lo", - direction="l", - }, - [0x3087]={ - category="lo", - direction="l", - }, - [0x3088]={ - category="lo", - direction="l", - }, - [0x3089]={ - category="lo", - direction="l", - }, - [0x308A]={ - category="lo", - direction="l", - }, - [0x308B]={ - category="lo", - direction="l", - }, - [0x308C]={ - category="lo", - direction="l", - }, - [0x308D]={ - category="lo", - direction="l", - }, - [0x308E]={ - category="lo", - direction="l", - }, - [0x308F]={ - category="lo", - direction="l", - }, - [0x3090]={ - category="lo", - direction="l", - }, - [0x3091]={ - category="lo", - direction="l", - }, - [0x3092]={ - category="lo", - direction="l", - }, - [0x3093]={ - category="lo", - direction="l", - }, - [0x3094]={ - category="lo", - direction="l", - }, - [0x3095]={ - category="lo", - direction="l", - }, - [0x3096]={ - category="lo", - direction="l", - }, - [0x3099]={ - category="mn", - direction="nsm", - }, - [0x309A]={ - category="mn", - direction="nsm", - }, - [0x309B]={ - category="sk", - direction="on", - }, - [0x309C]={ - category="sk", - direction="on", - }, - [0x309D]={ - category="lm", - direction="l", - }, - [0x309E]={ - category="lm", - direction="l", - }, - [0x309F]={ - category="lo", - direction="l", - }, - [0x30A0]={ - category="pd", - direction="on", - }, - [0x30A1]={ - category="lo", - direction="l", - }, - [0x30A2]={ - category="lo", - direction="l", - }, - [0x30A3]={ - category="lo", - direction="l", - }, - [0x30A4]={ - category="lo", - direction="l", - }, - [0x30A5]={ - category="lo", - direction="l", - }, - [0x30A6]={ - category="lo", - direction="l", - }, - [0x30A7]={ - category="lo", - direction="l", - }, - [0x30A8]={ - category="lo", - direction="l", - }, - [0x30A9]={ - category="lo", - direction="l", - }, - [0x30AA]={ - category="lo", - direction="l", - }, - [0x30AB]={ - category="lo", - direction="l", - }, - [0x30AC]={ - category="lo", - direction="l", - }, - [0x30AD]={ - category="lo", - direction="l", - }, - [0x30AE]={ - category="lo", - direction="l", - }, - [0x30AF]={ - category="lo", - direction="l", - }, - [0x30B0]={ - category="lo", - direction="l", - }, - [0x30B1]={ - category="lo", - direction="l", - }, - [0x30B2]={ - category="lo", - direction="l", - }, - [0x30B3]={ - category="lo", - direction="l", - }, - [0x30B4]={ - category="lo", - direction="l", - }, - [0x30B5]={ - category="lo", - direction="l", - }, - [0x30B6]={ - category="lo", - direction="l", - }, - [0x30B7]={ - category="lo", - direction="l", - }, - [0x30B8]={ - category="lo", - direction="l", - }, - [0x30B9]={ - category="lo", - direction="l", - }, - [0x30BA]={ - category="lo", - direction="l", - }, - [0x30BB]={ - category="lo", - direction="l", - }, - [0x30BC]={ - category="lo", - direction="l", - }, - [0x30BD]={ - category="lo", - direction="l", - }, - [0x30BE]={ - category="lo", - direction="l", - }, - [0x30BF]={ - category="lo", - direction="l", - }, - [0x30C0]={ - category="lo", - direction="l", - }, - [0x30C1]={ - category="lo", - direction="l", - }, - [0x30C2]={ - category="lo", - direction="l", - }, - [0x30C3]={ - category="lo", - direction="l", - }, - [0x30C4]={ - category="lo", - direction="l", - }, - [0x30C5]={ - category="lo", - direction="l", - }, - [0x30C6]={ - category="lo", - direction="l", - }, - [0x30C7]={ - category="lo", - direction="l", - }, - [0x30C8]={ - category="lo", - direction="l", - }, - [0x30C9]={ - category="lo", - direction="l", - }, - [0x30CA]={ - category="lo", - direction="l", - }, - [0x30CB]={ - category="lo", - direction="l", - }, - [0x30CC]={ - category="lo", - direction="l", - }, - [0x30CD]={ - category="lo", - direction="l", - }, - [0x30CE]={ - category="lo", - direction="l", - }, - [0x30CF]={ - category="lo", - direction="l", - }, - [0x30D0]={ - category="lo", - direction="l", - }, - [0x30D1]={ - category="lo", - direction="l", - }, - [0x30D2]={ - category="lo", - direction="l", - }, - [0x30D3]={ - category="lo", - direction="l", - }, - [0x30D4]={ - category="lo", - direction="l", - }, - [0x30D5]={ - category="lo", - direction="l", - }, - [0x30D6]={ - category="lo", - direction="l", - }, - [0x30D7]={ - category="lo", - direction="l", - }, - [0x30D8]={ - category="lo", - direction="l", - }, - [0x30D9]={ - category="lo", - direction="l", - }, - [0x30DA]={ - category="lo", - direction="l", - }, - [0x30DB]={ - category="lo", - direction="l", - }, - [0x30DC]={ - category="lo", - direction="l", - }, - [0x30DD]={ - category="lo", - direction="l", - }, - [0x30DE]={ - category="lo", - direction="l", - }, - [0x30DF]={ - category="lo", - direction="l", - }, - [0x30E0]={ - category="lo", - direction="l", - }, - [0x30E1]={ - category="lo", - direction="l", - }, - [0x30E2]={ - category="lo", - direction="l", - }, - [0x30E3]={ - category="lo", - direction="l", - }, - [0x30E4]={ - category="lo", - direction="l", - }, - [0x30E5]={ - category="lo", - direction="l", - }, - [0x30E6]={ - category="lo", - direction="l", - }, - [0x30E7]={ - category="lo", - direction="l", - }, - [0x30E8]={ - category="lo", - direction="l", - }, - [0x30E9]={ - category="lo", - direction="l", - }, - [0x30EA]={ - category="lo", - direction="l", - }, - [0x30EB]={ - category="lo", - direction="l", - }, - [0x30EC]={ - category="lo", - direction="l", - }, - [0x30ED]={ - category="lo", - direction="l", - }, - [0x30EE]={ - category="lo", - direction="l", - }, - [0x30EF]={ - category="lo", - direction="l", - }, - [0x30F0]={ - category="lo", - direction="l", - }, - [0x30F1]={ - category="lo", - direction="l", - }, - [0x30F2]={ - category="lo", - direction="l", - }, - [0x30F3]={ - category="lo", - direction="l", - }, - [0x30F4]={ - category="lo", - direction="l", - }, - [0x30F5]={ - category="lo", - direction="l", - }, - [0x30F6]={ - category="lo", - direction="l", - }, - [0x30F7]={ - category="lo", - direction="l", - }, - [0x30F8]={ - category="lo", - direction="l", - }, - [0x30F9]={ - category="lo", - direction="l", - }, - [0x30FA]={ - category="lo", - direction="l", - }, - [0x30FB]={ - category="po", - direction="on", - }, - [0x30FC]={ - category="lm", - direction="l", - }, - [0x30FD]={ - category="lm", - direction="l", - }, - [0x30FE]={ - category="lm", - direction="l", - }, - [0x30FF]={ - category="lo", - direction="l", - }, - [0x3105]={ - category="lo", - direction="l", - }, - [0x3106]={ - category="lo", - direction="l", - }, - [0x3107]={ - category="lo", - direction="l", - }, - [0x3108]={ - category="lo", - direction="l", - }, - [0x3109]={ - category="lo", - direction="l", - }, - [0x310A]={ - category="lo", - direction="l", - }, - [0x310B]={ - category="lo", - direction="l", - }, - [0x310C]={ - category="lo", - direction="l", - }, - [0x310D]={ - category="lo", - direction="l", - }, - [0x310E]={ - category="lo", - direction="l", - }, - [0x310F]={ - category="lo", - direction="l", - }, - [0x3110]={ - category="lo", - direction="l", - }, - [0x3111]={ - category="lo", - direction="l", - }, - [0x3112]={ - category="lo", - direction="l", - }, - [0x3113]={ - category="lo", - direction="l", - }, - [0x3114]={ - category="lo", - direction="l", - }, - [0x3115]={ - category="lo", - direction="l", - }, - [0x3116]={ - category="lo", - direction="l", - }, - [0x3117]={ - category="lo", - direction="l", - }, - [0x3118]={ - category="lo", - direction="l", - }, - [0x3119]={ - category="lo", - direction="l", - }, - [0x311A]={ - category="lo", - direction="l", - }, - [0x311B]={ - category="lo", - direction="l", - }, - [0x311C]={ - category="lo", - direction="l", - }, - [0x311D]={ - category="lo", - direction="l", - }, - [0x311E]={ - category="lo", - direction="l", - }, - [0x311F]={ - category="lo", - direction="l", - }, - [0x3120]={ - category="lo", - direction="l", - }, - [0x3121]={ - category="lo", - direction="l", - }, - [0x3122]={ - category="lo", - direction="l", - }, - [0x3123]={ - category="lo", - direction="l", - }, - [0x3124]={ - category="lo", - direction="l", - }, - [0x3125]={ - category="lo", - direction="l", - }, - [0x3126]={ - category="lo", - direction="l", - }, - [0x3127]={ - category="lo", - direction="l", - }, - [0x3128]={ - category="lo", - direction="l", - }, - [0x3129]={ - category="lo", - direction="l", - }, - [0x312A]={ - category="lo", - direction="l", - }, - [0x312B]={ - category="lo", - direction="l", - }, - [0x312C]={ - category="lo", - direction="l", - }, - [0x312D]={ - category="lo", - direction="l", - }, - [0x3131]={ - category="lo", - direction="l", - }, - [0x3132]={ - category="lo", - direction="l", - }, - [0x3133]={ - category="lo", - direction="l", - }, - [0x3134]={ - category="lo", - direction="l", - }, - [0x3135]={ - category="lo", - direction="l", - }, - [0x3136]={ - category="lo", - direction="l", - }, - [0x3137]={ - category="lo", - direction="l", - }, - [0x3138]={ - category="lo", - direction="l", - }, - [0x3139]={ - category="lo", - direction="l", - }, - [0x313A]={ - category="lo", - direction="l", - }, - [0x313B]={ - category="lo", - direction="l", - }, - [0x313C]={ - category="lo", - direction="l", - }, - [0x313D]={ - category="lo", - direction="l", - }, - [0x313E]={ - category="lo", - direction="l", - }, - [0x313F]={ - category="lo", - direction="l", - }, - [0x3140]={ - category="lo", - direction="l", - }, - [0x3141]={ - category="lo", - direction="l", - }, - [0x3142]={ - category="lo", - direction="l", - }, - [0x3143]={ - category="lo", - direction="l", - }, - [0x3144]={ - category="lo", - direction="l", - }, - [0x3145]={ - category="lo", - direction="l", - }, - [0x3146]={ - category="lo", - direction="l", - }, - [0x3147]={ - category="lo", - direction="l", - }, - [0x3148]={ - category="lo", - direction="l", - }, - [0x3149]={ - category="lo", - direction="l", - }, - [0x314A]={ - category="lo", - direction="l", - }, - [0x314B]={ - category="lo", - direction="l", - }, - [0x314C]={ - category="lo", - direction="l", - }, - [0x314D]={ - category="lo", - direction="l", - }, - [0x314E]={ - category="lo", - direction="l", - }, - [0x314F]={ - category="lo", - direction="l", - }, - [0x3150]={ - category="lo", - direction="l", - }, - [0x3151]={ - category="lo", - direction="l", - }, - [0x3152]={ - category="lo", - direction="l", - }, - [0x3153]={ - category="lo", - direction="l", - }, - [0x3154]={ - category="lo", - direction="l", - }, - [0x3155]={ - category="lo", - direction="l", - }, - [0x3156]={ - category="lo", - direction="l", - }, - [0x3157]={ - category="lo", - direction="l", - }, - [0x3158]={ - category="lo", - direction="l", - }, - [0x3159]={ - category="lo", - direction="l", - }, - [0x315A]={ - category="lo", - direction="l", - }, - [0x315B]={ - category="lo", - direction="l", - }, - [0x315C]={ - category="lo", - direction="l", - }, - [0x315D]={ - category="lo", - direction="l", - }, - [0x315E]={ - category="lo", - direction="l", - }, - [0x315F]={ - category="lo", - direction="l", - }, - [0x3160]={ - category="lo", - direction="l", - }, - [0x3161]={ - category="lo", - direction="l", - }, - [0x3162]={ - category="lo", - direction="l", - }, - [0x3163]={ - category="lo", - direction="l", - }, - [0x3164]={ - category="lo", - direction="l", - }, - [0x3165]={ - category="lo", - direction="l", - }, - [0x3166]={ - category="lo", - direction="l", - }, - [0x3167]={ - category="lo", - direction="l", - }, - [0x3168]={ - category="lo", - direction="l", - }, - [0x3169]={ - category="lo", - direction="l", - }, - [0x316A]={ - category="lo", - direction="l", - }, - [0x316B]={ - category="lo", - direction="l", - }, - [0x316C]={ - category="lo", - direction="l", - }, - [0x316D]={ - category="lo", - direction="l", - }, - [0x316E]={ - category="lo", - direction="l", - }, - [0x316F]={ - category="lo", - direction="l", - }, - [0x3170]={ - category="lo", - direction="l", - }, - [0x3171]={ - category="lo", - direction="l", - }, - [0x3172]={ - category="lo", - direction="l", - }, - [0x3173]={ - category="lo", - direction="l", - }, - [0x3174]={ - category="lo", - direction="l", - }, - [0x3175]={ - category="lo", - direction="l", - }, - [0x3176]={ - category="lo", - direction="l", - }, - [0x3177]={ - category="lo", - direction="l", - }, - [0x3178]={ - category="lo", - direction="l", - }, - [0x3179]={ - category="lo", - direction="l", - }, - [0x317A]={ - category="lo", - direction="l", - }, - [0x317B]={ - category="lo", - direction="l", - }, - [0x317C]={ - category="lo", - direction="l", - }, - [0x317D]={ - category="lo", - direction="l", - }, - [0x317E]={ - category="lo", - direction="l", - }, - [0x317F]={ - category="lo", - direction="l", - }, - [0x3180]={ - category="lo", - direction="l", - }, - [0x3181]={ - category="lo", - direction="l", - }, - [0x3182]={ - category="lo", - direction="l", - }, - [0x3183]={ - category="lo", - direction="l", - }, - [0x3184]={ - category="lo", - direction="l", - }, - [0x3185]={ - category="lo", - direction="l", - }, - [0x3186]={ - category="lo", - direction="l", - }, - [0x3187]={ - category="lo", - direction="l", - }, - [0x3188]={ - category="lo", - direction="l", - }, - [0x3189]={ - category="lo", - direction="l", - }, - [0x318A]={ - category="lo", - direction="l", - }, - [0x318B]={ - category="lo", - direction="l", - }, - [0x318C]={ - category="lo", - direction="l", - }, - [0x318D]={ - category="lo", - direction="l", - }, - [0x318E]={ - category="lo", - direction="l", - }, - [0x3190]={ - category="so", - direction="l", - }, - [0x3191]={ - category="so", - direction="l", - }, - [0x3192]={ - category="no", - direction="l", - }, - [0x3193]={ - category="no", - direction="l", - }, - [0x3194]={ - category="no", - direction="l", - }, - [0x3195]={ - category="no", - direction="l", - }, - [0x3196]={ - category="so", - direction="l", - }, - [0x3197]={ - category="so", - direction="l", - }, - [0x3198]={ - category="so", - direction="l", - }, - [0x3199]={ - category="so", - direction="l", - }, - [0x319A]={ - category="so", - direction="l", - }, - [0x319B]={ - category="so", - direction="l", - }, - [0x319C]={ - category="so", - direction="l", - }, - [0x319D]={ - category="so", - direction="l", - }, - [0x319E]={ - category="so", - direction="l", - }, - [0x319F]={ - category="so", - direction="l", - }, - [0x31A0]={ - category="lo", - direction="l", - }, - [0x31A1]={ - category="lo", - direction="l", - }, - [0x31A2]={ - category="lo", - direction="l", - }, - [0x31A3]={ - category="lo", - direction="l", - }, - [0x31A4]={ - category="lo", - direction="l", - }, - [0x31A5]={ - category="lo", - direction="l", - }, - [0x31A6]={ - category="lo", - direction="l", - }, - [0x31A7]={ - category="lo", - direction="l", - }, - [0x31A8]={ - category="lo", - direction="l", - }, - [0x31A9]={ - category="lo", - direction="l", - }, - [0x31AA]={ - category="lo", - direction="l", - }, - [0x31AB]={ - category="lo", - direction="l", - }, - [0x31AC]={ - category="lo", - direction="l", - }, - [0x31AD]={ - category="lo", - direction="l", - }, - [0x31AE]={ - category="lo", - direction="l", - }, - [0x31AF]={ - category="lo", - direction="l", - }, - [0x31B0]={ - category="lo", - direction="l", - }, - [0x31B1]={ - category="lo", - direction="l", - }, - [0x31B2]={ - category="lo", - direction="l", - }, - [0x31B3]={ - category="lo", - direction="l", - }, - [0x31B4]={ - category="lo", - direction="l", - }, - [0x31B5]={ - category="lo", - direction="l", - }, - [0x31B6]={ - category="lo", - direction="l", - }, - [0x31B7]={ - category="lo", - direction="l", - }, - [0x31B8]={ - category="lo", - direction="l", - }, - [0x31B9]={ - category="lo", - direction="l", - }, - [0x31BA]={ - category="lo", - direction="l", - }, - [0x31C0]={ - category="so", - direction="on", - }, - [0x31C1]={ - category="so", - direction="on", - }, - [0x31C2]={ - category="so", - direction="on", - }, - [0x31C3]={ - category="so", - direction="on", - }, - [0x31C4]={ - category="so", - direction="on", - }, - [0x31C5]={ - category="so", - direction="on", - }, - [0x31C6]={ - category="so", - direction="on", - }, - [0x31C7]={ - category="so", - direction="on", - }, - [0x31C8]={ - category="so", - direction="on", - }, - [0x31C9]={ - category="so", - direction="on", - }, - [0x31CA]={ - category="so", - direction="on", - }, - [0x31CB]={ - category="so", - direction="on", - }, - [0x31CC]={ - category="so", - direction="on", - }, - [0x31CD]={ - category="so", - direction="on", - }, - [0x31CE]={ - category="so", - direction="on", - }, - [0x31CF]={ - category="so", - direction="on", - }, - [0x31D0]={ - category="so", - direction="on", - }, - [0x31D1]={ - category="so", - direction="on", - }, - [0x31D2]={ - category="so", - direction="on", - }, - [0x31D3]={ - category="so", - direction="on", - }, - [0x31D4]={ - category="so", - direction="on", - }, - [0x31D5]={ - category="so", - direction="on", - }, - [0x31D6]={ - category="so", - direction="on", - }, - [0x31D7]={ - category="so", - direction="on", - }, - [0x31D8]={ - category="so", - direction="on", - }, - [0x31D9]={ - category="so", - direction="on", - }, - [0x31DA]={ - category="so", - direction="on", - }, - [0x31DB]={ - category="so", - direction="on", - }, - [0x31DC]={ - category="so", - direction="on", - }, - [0x31DD]={ - category="so", - direction="on", - }, - [0x31DE]={ - category="so", - direction="on", - }, - [0x31DF]={ - category="so", - direction="on", - }, - [0x31E0]={ - category="so", - direction="on", - }, - [0x31E1]={ - category="so", - direction="on", - }, - [0x31E2]={ - category="so", - direction="on", - }, - [0x31E3]={ - category="so", - direction="on", - }, - [0x31F0]={ - category="lo", - direction="l", - }, - [0x31F1]={ - category="lo", - direction="l", - }, - [0x31F2]={ - category="lo", - direction="l", - }, - [0x31F3]={ - category="lo", - direction="l", - }, - [0x31F4]={ - category="lo", - direction="l", - }, - [0x31F5]={ - category="lo", - direction="l", - }, - [0x31F6]={ - category="lo", - direction="l", - }, - [0x31F7]={ - category="lo", - direction="l", - }, - [0x31F8]={ - category="lo", - direction="l", - }, - [0x31F9]={ - category="lo", - direction="l", - }, - [0x31FA]={ - category="lo", - direction="l", - }, - [0x31FB]={ - category="lo", - direction="l", - }, - [0x31FC]={ - category="lo", - direction="l", - }, - [0x31FD]={ - category="lo", - direction="l", - }, - [0x31FE]={ - category="lo", - direction="l", - }, - [0x31FF]={ - category="lo", - direction="l", - }, - [0x3200]={ - category="so", - direction="l", - }, - [0x3201]={ - category="so", - direction="l", - }, - [0x3202]={ - category="so", - direction="l", - }, - [0x3203]={ - category="so", - direction="l", - }, - [0x3204]={ - category="so", - direction="l", - }, - [0x3205]={ - category="so", - direction="l", - }, - [0x3206]={ - category="so", - direction="l", - }, - [0x3207]={ - category="so", - direction="l", - }, - [0x3208]={ - category="so", - direction="l", - }, - [0x3209]={ - category="so", - direction="l", - }, - [0x320A]={ - category="so", - direction="l", - }, - [0x320B]={ - category="so", - direction="l", - }, - [0x320C]={ - category="so", - direction="l", - }, - [0x320D]={ - category="so", - direction="l", - }, - [0x320E]={ - category="so", - direction="l", - }, - [0x320F]={ - category="so", - direction="l", - }, - [0x3210]={ - category="so", - direction="l", - }, - [0x3211]={ - category="so", - direction="l", - }, - [0x3212]={ - category="so", - direction="l", - }, - [0x3213]={ - category="so", - direction="l", - }, - [0x3214]={ - category="so", - direction="l", - }, - [0x3215]={ - category="so", - direction="l", - }, - [0x3216]={ - category="so", - direction="l", - }, - [0x3217]={ - category="so", - direction="l", - }, - [0x3218]={ - category="so", - direction="l", - }, - [0x3219]={ - category="so", - direction="l", - }, - [0x321A]={ - category="so", - direction="l", - }, - [0x321B]={ - category="so", - direction="l", - }, - [0x321C]={ - category="so", - direction="l", - }, - [0x321D]={ - category="so", - direction="on", - }, - [0x321E]={ - category="so", - direction="on", - }, - [0x3220]={ - category="no", - direction="l", - }, - [0x3221]={ - category="no", - direction="l", - }, - [0x3222]={ - category="no", - direction="l", - }, - [0x3223]={ - category="no", - direction="l", - }, - [0x3224]={ - category="no", - direction="l", - }, - [0x3225]={ - category="no", - direction="l", - }, - [0x3226]={ - category="no", - direction="l", - }, - [0x3227]={ - category="no", - direction="l", - }, - [0x3228]={ - category="no", - direction="l", - }, - [0x3229]={ - category="no", - direction="l", - }, - [0x322A]={ - category="so", - direction="l", - }, - [0x322B]={ - category="so", - direction="l", - }, - [0x322C]={ - category="so", - direction="l", - }, - [0x322D]={ - category="so", - direction="l", - }, - [0x322E]={ - category="so", - direction="l", - }, - [0x322F]={ - category="so", - direction="l", - }, - [0x3230]={ - category="so", - direction="l", - }, - [0x3231]={ - category="so", - direction="l", - }, - [0x3232]={ - category="so", - direction="l", - }, - [0x3233]={ - category="so", - direction="l", - }, - [0x3234]={ - category="so", - direction="l", - }, - [0x3235]={ - category="so", - direction="l", - }, - [0x3236]={ - category="so", - direction="l", - }, - [0x3237]={ - category="so", - direction="l", - }, - [0x3238]={ - category="so", - direction="l", - }, - [0x3239]={ - category="so", - direction="l", - }, - [0x323A]={ - category="so", - direction="l", - }, - [0x323B]={ - category="so", - direction="l", - }, - [0x323C]={ - category="so", - direction="l", - }, - [0x323D]={ - category="so", - direction="l", - }, - [0x323E]={ - category="so", - direction="l", - }, - [0x323F]={ - category="so", - direction="l", - }, - [0x3240]={ - category="so", - direction="l", - }, - [0x3241]={ - category="so", - direction="l", - }, - [0x3242]={ - category="so", - direction="l", - }, - [0x3243]={ - category="so", - direction="l", - }, - [0x3244]={ - category="so", - direction="l", - }, - [0x3245]={ - category="so", - direction="l", - }, - [0x3246]={ - category="so", - direction="l", - }, - [0x3247]={ - category="so", - direction="l", - }, - [0x3248]={ - category="so", - direction="l", - }, - [0x3249]={ - category="so", - direction="l", - }, - [0x324A]={ - category="so", - direction="l", - }, - [0x324B]={ - category="so", - direction="l", - }, - [0x324C]={ - category="so", - direction="l", - }, - [0x324D]={ - category="so", - direction="l", - }, - [0x324E]={ - category="so", - direction="l", - }, - [0x324F]={ - category="so", - direction="l", - }, - [0x3250]={ - category="so", - direction="on", - }, - [0x3251]={ - category="no", - direction="on", - }, - [0x3252]={ - category="no", - direction="on", - }, - [0x3253]={ - category="no", - direction="on", - }, - [0x3254]={ - category="no", - direction="on", - }, - [0x3255]={ - category="no", - direction="on", - }, - [0x3256]={ - category="no", - direction="on", - }, - [0x3257]={ - category="no", - direction="on", - }, - [0x3258]={ - category="no", - direction="on", - }, - [0x3259]={ - category="no", - direction="on", - }, - [0x325A]={ - category="no", - direction="on", - }, - [0x325B]={ - category="no", - direction="on", - }, - [0x325C]={ - category="no", - direction="on", - }, - [0x325D]={ - category="no", - direction="on", - }, - [0x325E]={ - category="no", - direction="on", - }, - [0x325F]={ - category="no", - direction="on", - }, - [0x3260]={ - category="so", - direction="l", - }, - [0x3261]={ - category="so", - direction="l", - }, - [0x3262]={ - category="so", - direction="l", - }, - [0x3263]={ - category="so", - direction="l", - }, - [0x3264]={ - category="so", - direction="l", - }, - [0x3265]={ - category="so", - direction="l", - }, - [0x3266]={ - category="so", - direction="l", - }, - [0x3267]={ - category="so", - direction="l", - }, - [0x3268]={ - category="so", - direction="l", - }, - [0x3269]={ - category="so", - direction="l", - }, - [0x326A]={ - category="so", - direction="l", - }, - [0x326B]={ - category="so", - direction="l", - }, - [0x326C]={ - category="so", - direction="l", - }, - [0x326D]={ - category="so", - direction="l", - }, - [0x326E]={ - category="so", - direction="l", - }, - [0x326F]={ - category="so", - direction="l", - }, - [0x3270]={ - category="so", - direction="l", - }, - [0x3271]={ - category="so", - direction="l", - }, - [0x3272]={ - category="so", - direction="l", - }, - [0x3273]={ - category="so", - direction="l", - }, - [0x3274]={ - category="so", - direction="l", - }, - [0x3275]={ - category="so", - direction="l", - }, - [0x3276]={ - category="so", - direction="l", - }, - [0x3277]={ - category="so", - direction="l", - }, - [0x3278]={ - category="so", - direction="l", - }, - [0x3279]={ - category="so", - direction="l", - }, - [0x327A]={ - category="so", - direction="l", - }, - [0x327B]={ - category="so", - direction="l", - }, - [0x327C]={ - category="so", - direction="on", - }, - [0x327D]={ - category="so", - direction="on", - }, - [0x327E]={ - category="so", - direction="on", - }, - [0x327F]={ - category="so", - direction="l", - }, - [0x3280]={ - category="no", - direction="l", - }, - [0x3281]={ - category="no", - direction="l", - }, - [0x3282]={ - category="no", - direction="l", - }, - [0x3283]={ - category="no", - direction="l", - }, - [0x3284]={ - category="no", - direction="l", - }, - [0x3285]={ - category="no", - direction="l", - }, - [0x3286]={ - category="no", - direction="l", - }, - [0x3287]={ - category="no", - direction="l", - }, - [0x3288]={ - category="no", - direction="l", - }, - [0x3289]={ - category="no", - direction="l", - }, - [0x328A]={ - category="so", - direction="l", - }, - [0x328B]={ - category="so", - direction="l", - }, - [0x328C]={ - category="so", - direction="l", - }, - [0x328D]={ - category="so", - direction="l", - }, - [0x328E]={ - category="so", - direction="l", - }, - [0x328F]={ - category="so", - direction="l", - }, - [0x3290]={ - category="so", - direction="l", - }, - [0x3291]={ - category="so", - direction="l", - }, - [0x3292]={ - category="so", - direction="l", - }, - [0x3293]={ - category="so", - direction="l", - }, - [0x3294]={ - category="so", - direction="l", - }, - [0x3295]={ - category="so", - direction="l", - }, - [0x3296]={ - category="so", - direction="l", - }, - [0x3297]={ - category="so", - direction="l", - }, - [0x3298]={ - category="so", - direction="l", - }, - [0x3299]={ - category="so", - direction="l", - }, - [0x329A]={ - category="so", - direction="l", - }, - [0x329B]={ - category="so", - direction="l", - }, - [0x329C]={ - category="so", - direction="l", - }, - [0x329D]={ - category="so", - direction="l", - }, - [0x329E]={ - category="so", - direction="l", - }, - [0x329F]={ - category="so", - direction="l", - }, - [0x32A0]={ - category="so", - direction="l", - }, - [0x32A1]={ - category="so", - direction="l", - }, - [0x32A2]={ - category="so", - direction="l", - }, - [0x32A3]={ - category="so", - direction="l", - }, - [0x32A4]={ - category="so", - direction="l", - }, - [0x32A5]={ - category="so", - direction="l", - }, - [0x32A6]={ - category="so", - direction="l", - }, - [0x32A7]={ - category="so", - direction="l", - }, - [0x32A8]={ - category="so", - direction="l", - }, - [0x32A9]={ - category="so", - direction="l", - }, - [0x32AA]={ - category="so", - direction="l", - }, - [0x32AB]={ - category="so", - direction="l", - }, - [0x32AC]={ - category="so", - direction="l", - }, - [0x32AD]={ - category="so", - direction="l", - }, - [0x32AE]={ - category="so", - direction="l", - }, - [0x32AF]={ - category="so", - direction="l", - }, - [0x32B0]={ - category="so", - direction="l", - }, - [0x32B1]={ - category="no", - direction="on", - }, - [0x32B2]={ - category="no", - direction="on", - }, - [0x32B3]={ - category="no", - direction="on", - }, - [0x32B4]={ - category="no", - direction="on", - }, - [0x32B5]={ - category="no", - direction="on", - }, - [0x32B6]={ - category="no", - direction="on", - }, - [0x32B7]={ - category="no", - direction="on", - }, - [0x32B8]={ - category="no", - direction="on", - }, - [0x32B9]={ - category="no", - direction="on", - }, - [0x32BA]={ - category="no", - direction="on", - }, - [0x32BB]={ - category="no", - direction="on", - }, - [0x32BC]={ - category="no", - direction="on", - }, - [0x32BD]={ - category="no", - direction="on", - }, - [0x32BE]={ - category="no", - direction="on", - }, - [0x32BF]={ - category="no", - direction="on", - }, - [0x32C0]={ - category="so", - direction="l", - }, - [0x32C1]={ - category="so", - direction="l", - }, - [0x32C2]={ - category="so", - direction="l", - }, - [0x32C3]={ - category="so", - direction="l", - }, - [0x32C4]={ - category="so", - direction="l", - }, - [0x32C5]={ - category="so", - direction="l", - }, - [0x32C6]={ - category="so", - direction="l", - }, - [0x32C7]={ - category="so", - direction="l", - }, - [0x32C8]={ - category="so", - direction="l", - }, - [0x32C9]={ - category="so", - direction="l", - }, - [0x32CA]={ - category="so", - direction="l", - }, - [0x32CB]={ - category="so", - direction="l", - }, - [0x32CC]={ - category="so", - direction="on", - }, - [0x32CD]={ - category="so", - direction="on", - }, - [0x32CE]={ - category="so", - direction="on", - }, - [0x32CF]={ - category="so", - direction="on", - }, - [0x32D0]={ - category="so", - direction="l", - }, - [0x32D1]={ - category="so", - direction="l", - }, - [0x32D2]={ - category="so", - direction="l", - }, - [0x32D3]={ - category="so", - direction="l", - }, - [0x32D4]={ - category="so", - direction="l", - }, - [0x32D5]={ - category="so", - direction="l", - }, - [0x32D6]={ - category="so", - direction="l", - }, - [0x32D7]={ - category="so", - direction="l", - }, - [0x32D8]={ - category="so", - direction="l", - }, - [0x32D9]={ - category="so", - direction="l", - }, - [0x32DA]={ - category="so", - direction="l", - }, - [0x32DB]={ - category="so", - direction="l", - }, - [0x32DC]={ - category="so", - direction="l", - }, - [0x32DD]={ - category="so", - direction="l", - }, - [0x32DE]={ - category="so", - direction="l", - }, - [0x32DF]={ - category="so", - direction="l", - }, - [0x32E0]={ - category="so", - direction="l", - }, - [0x32E1]={ - category="so", - direction="l", - }, - [0x32E2]={ - category="so", - direction="l", - }, - [0x32E3]={ - category="so", - direction="l", - }, - [0x32E4]={ - category="so", - direction="l", - }, - [0x32E5]={ - category="so", - direction="l", - }, - [0x32E6]={ - category="so", - direction="l", - }, - [0x32E7]={ - category="so", - direction="l", - }, - [0x32E8]={ - category="so", - direction="l", - }, - [0x32E9]={ - category="so", - direction="l", - }, - [0x32EA]={ - category="so", - direction="l", - }, - [0x32EB]={ - category="so", - direction="l", - }, - [0x32EC]={ - category="so", - direction="l", - }, - [0x32ED]={ - category="so", - direction="l", - }, - [0x32EE]={ - category="so", - direction="l", - }, - [0x32EF]={ - category="so", - direction="l", - }, - [0x32F0]={ - category="so", - direction="l", - }, - [0x32F1]={ - category="so", - direction="l", - }, - [0x32F2]={ - category="so", - direction="l", - }, - [0x32F3]={ - category="so", - direction="l", - }, - [0x32F4]={ - category="so", - direction="l", - }, - [0x32F5]={ - category="so", - direction="l", - }, - [0x32F6]={ - category="so", - direction="l", - }, - [0x32F7]={ - category="so", - direction="l", - }, - [0x32F8]={ - category="so", - direction="l", - }, - [0x32F9]={ - category="so", - direction="l", - }, - [0x32FA]={ - category="so", - direction="l", - }, - [0x32FB]={ - category="so", - direction="l", - }, - [0x32FC]={ - category="so", - direction="l", - }, - [0x32FD]={ - category="so", - direction="l", - }, - [0x32FE]={ - category="so", - direction="l", - }, - [0x3300]={ - category="so", - direction="l", - }, - [0x3301]={ - category="so", - direction="l", - }, - [0x3302]={ - category="so", - direction="l", - }, - [0x3303]={ - category="so", - direction="l", - }, - [0x3304]={ - category="so", - direction="l", - }, - [0x3305]={ - category="so", - direction="l", - }, - [0x3306]={ - category="so", - direction="l", - }, - [0x3307]={ - category="so", - direction="l", - }, - [0x3308]={ - category="so", - direction="l", - }, - [0x3309]={ - category="so", - direction="l", - }, - [0x330A]={ - category="so", - direction="l", - }, - [0x330B]={ - category="so", - direction="l", - }, - [0x330C]={ - category="so", - direction="l", - }, - [0x330D]={ - category="so", - direction="l", - }, - [0x330E]={ - category="so", - direction="l", - }, - [0x330F]={ - category="so", - direction="l", - }, - [0x3310]={ - category="so", - direction="l", - }, - [0x3311]={ - category="so", - direction="l", - }, - [0x3312]={ - category="so", - direction="l", - }, - [0x3313]={ - category="so", - direction="l", - }, - [0x3314]={ - category="so", - direction="l", - }, - [0x3315]={ - category="so", - direction="l", - }, - [0x3316]={ - category="so", - direction="l", - }, - [0x3317]={ - category="so", - direction="l", - }, - [0x3318]={ - category="so", - direction="l", - }, - [0x3319]={ - category="so", - direction="l", - }, - [0x331A]={ - category="so", - direction="l", - }, - [0x331B]={ - category="so", - direction="l", - }, - [0x331C]={ - category="so", - direction="l", - }, - [0x331D]={ - category="so", - direction="l", - }, - [0x331E]={ - category="so", - direction="l", - }, - [0x331F]={ - category="so", - direction="l", - }, - [0x3320]={ - category="so", - direction="l", - }, - [0x3321]={ - category="so", - direction="l", - }, - [0x3322]={ - category="so", - direction="l", - }, - [0x3323]={ - category="so", - direction="l", - }, - [0x3324]={ - category="so", - direction="l", - }, - [0x3325]={ - category="so", - direction="l", - }, - [0x3326]={ - category="so", - direction="l", - }, - [0x3327]={ - category="so", - direction="l", - }, - [0x3328]={ - category="so", - direction="l", - }, - [0x3329]={ - category="so", - direction="l", - }, - [0x332A]={ - category="so", - direction="l", - }, - [0x332B]={ - category="so", - direction="l", - }, - [0x332C]={ - category="so", - direction="l", - }, - [0x332D]={ - category="so", - direction="l", - }, - [0x332E]={ - category="so", - direction="l", - }, - [0x332F]={ - category="so", - direction="l", - }, - [0x3330]={ - category="so", - direction="l", - }, - [0x3331]={ - category="so", - direction="l", - }, - [0x3332]={ - category="so", - direction="l", - }, - [0x3333]={ - category="so", - direction="l", - }, - [0x3334]={ - category="so", - direction="l", - }, - [0x3335]={ - category="so", - direction="l", - }, - [0x3336]={ - category="so", - direction="l", - }, - [0x3337]={ - category="so", - direction="l", - }, - [0x3338]={ - category="so", - direction="l", - }, - [0x3339]={ - category="so", - direction="l", - }, - [0x333A]={ - category="so", - direction="l", - }, - [0x333B]={ - category="so", - direction="l", - }, - [0x333C]={ - category="so", - direction="l", - }, - [0x333D]={ - category="so", - direction="l", - }, - [0x333E]={ - category="so", - direction="l", - }, - [0x333F]={ - category="so", - direction="l", - }, - [0x3340]={ - category="so", - direction="l", - }, - [0x3341]={ - category="so", - direction="l", - }, - [0x3342]={ - category="so", - direction="l", - }, - [0x3343]={ - category="so", - direction="l", - }, - [0x3344]={ - category="so", - direction="l", - }, - [0x3345]={ - category="so", - direction="l", - }, - [0x3346]={ - category="so", - direction="l", - }, - [0x3347]={ - category="so", - direction="l", - }, - [0x3348]={ - category="so", - direction="l", - }, - [0x3349]={ - category="so", - direction="l", - }, - [0x334A]={ - category="so", - direction="l", - }, - [0x334B]={ - category="so", - direction="l", - }, - [0x334C]={ - category="so", - direction="l", - }, - [0x334D]={ - category="so", - direction="l", - }, - [0x334E]={ - category="so", - direction="l", - }, - [0x334F]={ - category="so", - direction="l", - }, - [0x3350]={ - category="so", - direction="l", - }, - [0x3351]={ - category="so", - direction="l", - }, - [0x3352]={ - category="so", - direction="l", - }, - [0x3353]={ - category="so", - direction="l", - }, - [0x3354]={ - category="so", - direction="l", - }, - [0x3355]={ - category="so", - direction="l", - }, - [0x3356]={ - category="so", - direction="l", - }, - [0x3357]={ - category="so", - direction="l", - }, - [0x3358]={ - category="so", - direction="l", - }, - [0x3359]={ - category="so", - direction="l", - }, - [0x335A]={ - category="so", - direction="l", - }, - [0x335B]={ - category="so", - direction="l", - }, - [0x335C]={ - category="so", - direction="l", - }, - [0x335D]={ - category="so", - direction="l", - }, - [0x335E]={ - category="so", - direction="l", - }, - [0x335F]={ - category="so", - direction="l", - }, - [0x3360]={ - category="so", - direction="l", - }, - [0x3361]={ - category="so", - direction="l", - }, - [0x3362]={ - category="so", - direction="l", - }, - [0x3363]={ - category="so", - direction="l", - }, - [0x3364]={ - category="so", - direction="l", - }, - [0x3365]={ - category="so", - direction="l", - }, - [0x3366]={ - category="so", - direction="l", - }, - [0x3367]={ - category="so", - direction="l", - }, - [0x3368]={ - category="so", - direction="l", - }, - [0x3369]={ - category="so", - direction="l", - }, - [0x336A]={ - category="so", - direction="l", - }, - [0x336B]={ - category="so", - direction="l", - }, - [0x336C]={ - category="so", - direction="l", - }, - [0x336D]={ - category="so", - direction="l", - }, - [0x336E]={ - category="so", - direction="l", - }, - [0x336F]={ - category="so", - direction="l", - }, - [0x3370]={ - category="so", - direction="l", - }, - [0x3371]={ - category="so", - direction="l", - }, - [0x3372]={ - category="so", - direction="l", - }, - [0x3373]={ - category="so", - direction="l", - }, - [0x3374]={ - category="so", - direction="l", - }, - [0x3375]={ - category="so", - direction="l", - }, - [0x3376]={ - category="so", - direction="l", - }, - [0x3377]={ - category="so", - direction="on", - }, - [0x3378]={ - category="so", - direction="on", - }, - [0x3379]={ - category="so", - direction="on", - }, - [0x337A]={ - category="so", - direction="on", - }, - [0x337B]={ - category="so", - direction="l", - }, - [0x337C]={ - category="so", - direction="l", - }, - [0x337D]={ - category="so", - direction="l", - }, - [0x337E]={ - category="so", - direction="l", - }, - [0x337F]={ - category="so", - direction="l", - }, - [0x3380]={ - category="so", - direction="l", - }, - [0x3381]={ - category="so", - direction="l", - }, - [0x3382]={ - category="so", - direction="l", - }, - [0x3383]={ - category="so", - direction="l", - }, - [0x3384]={ - category="so", - direction="l", - }, - [0x3385]={ - category="so", - direction="l", - }, - [0x3386]={ - category="so", - direction="l", - }, - [0x3387]={ - category="so", - direction="l", - }, - [0x3388]={ - category="so", - direction="l", - }, - [0x3389]={ - category="so", - direction="l", - }, - [0x338A]={ - category="so", - direction="l", - }, - [0x338B]={ - category="so", - direction="l", - }, - [0x338C]={ - category="so", - direction="l", - }, - [0x338D]={ - category="so", - direction="l", - }, - [0x338E]={ - category="so", - direction="l", - }, - [0x338F]={ - category="so", - direction="l", - }, - [0x3390]={ - category="so", - direction="l", - }, - [0x3391]={ - category="so", - direction="l", - }, - [0x3392]={ - category="so", - direction="l", - }, - [0x3393]={ - category="so", - direction="l", - }, - [0x3394]={ - category="so", - direction="l", - }, - [0x3395]={ - category="so", - direction="l", - }, - [0x3396]={ - category="so", - direction="l", - }, - [0x3397]={ - category="so", - direction="l", - }, - [0x3398]={ - category="so", - direction="l", - }, - [0x3399]={ - category="so", - direction="l", - }, - [0x339A]={ - category="so", - direction="l", - }, - [0x339B]={ - category="so", - direction="l", - }, - [0x339C]={ - category="so", - direction="l", - }, - [0x339D]={ - category="so", - direction="l", - }, - [0x339E]={ - category="so", - direction="l", - }, - [0x339F]={ - category="so", - direction="l", - }, - [0x33A0]={ - category="so", - direction="l", - }, - [0x33A1]={ - category="so", - direction="l", - }, - [0x33A2]={ - category="so", - direction="l", - }, - [0x33A3]={ - category="so", - direction="l", - }, - [0x33A4]={ - category="so", - direction="l", - }, - [0x33A5]={ - category="so", - direction="l", - }, - [0x33A6]={ - category="so", - direction="l", - }, - [0x33A7]={ - category="so", - direction="l", - }, - [0x33A8]={ - category="so", - direction="l", - }, - [0x33A9]={ - category="so", - direction="l", - }, - [0x33AA]={ - category="so", - direction="l", - }, - [0x33AB]={ - category="so", - direction="l", - }, - [0x33AC]={ - category="so", - direction="l", - }, - [0x33AD]={ - category="so", - direction="l", - }, - [0x33AE]={ - category="so", - direction="l", - }, - [0x33AF]={ - category="so", - direction="l", - }, - [0x33B0]={ - category="so", - direction="l", - }, - [0x33B1]={ - category="so", - direction="l", - }, - [0x33B2]={ - category="so", - direction="l", - }, - [0x33B3]={ - category="so", - direction="l", - }, - [0x33B4]={ - category="so", - direction="l", - }, - [0x33B5]={ - category="so", - direction="l", - }, - [0x33B6]={ - category="so", - direction="l", - }, - [0x33B7]={ - category="so", - direction="l", - }, - [0x33B8]={ - category="so", - direction="l", - }, - [0x33B9]={ - category="so", - direction="l", - }, - [0x33BA]={ - category="so", - direction="l", - }, - [0x33BB]={ - category="so", - direction="l", - }, - [0x33BC]={ - category="so", - direction="l", - }, - [0x33BD]={ - category="so", - direction="l", - }, - [0x33BE]={ - category="so", - direction="l", - }, - [0x33BF]={ - category="so", - direction="l", - }, - [0x33C0]={ - category="so", - direction="l", - }, - [0x33C1]={ - category="so", - direction="l", - }, - [0x33C2]={ - category="so", - direction="l", - }, - [0x33C3]={ - category="so", - direction="l", - }, - [0x33C4]={ - category="so", - direction="l", - }, - [0x33C5]={ - category="so", - direction="l", - }, - [0x33C6]={ - category="so", - direction="l", - }, - [0x33C7]={ - category="so", - direction="l", - }, - [0x33C8]={ - category="so", - direction="l", - }, - [0x33C9]={ - category="so", - direction="l", - }, - [0x33CA]={ - category="so", - direction="l", - }, - [0x33CB]={ - category="so", - direction="l", - }, - [0x33CC]={ - category="so", - direction="l", - }, - [0x33CD]={ - category="so", - direction="l", - }, - [0x33CE]={ - category="so", - direction="l", - }, - [0x33CF]={ - category="so", - direction="l", - }, - [0x33D0]={ - category="so", - direction="l", - }, - [0x33D1]={ - category="so", - direction="l", - }, - [0x33D2]={ - category="so", - direction="l", - }, - [0x33D3]={ - category="so", - direction="l", - }, - [0x33D4]={ - category="so", - direction="l", - }, - [0x33D5]={ - category="so", - direction="l", - }, - [0x33D6]={ - category="so", - direction="l", - }, - [0x33D7]={ - category="so", - direction="l", - }, - [0x33D8]={ - category="so", - direction="l", - }, - [0x33D9]={ - category="so", - direction="l", - }, - [0x33DA]={ - category="so", - direction="l", - }, - [0x33DB]={ - category="so", - direction="l", - }, - [0x33DC]={ - category="so", - direction="l", - }, - [0x33DD]={ - category="so", - direction="l", - }, - [0x33DE]={ - category="so", - direction="on", - }, - [0x33DF]={ - category="so", - direction="on", - }, - [0x33E0]={ - category="so", - direction="l", - }, - [0x33E1]={ - category="so", - direction="l", - }, - [0x33E2]={ - category="so", - direction="l", - }, - [0x33E3]={ - category="so", - direction="l", - }, - [0x33E4]={ - category="so", - direction="l", - }, - [0x33E5]={ - category="so", - direction="l", - }, - [0x33E6]={ - category="so", - direction="l", - }, - [0x33E7]={ - category="so", - direction="l", - }, - [0x33E8]={ - category="so", - direction="l", - }, - [0x33E9]={ - category="so", - direction="l", - }, - [0x33EA]={ - category="so", - direction="l", - }, - [0x33EB]={ - category="so", - direction="l", - }, - [0x33EC]={ - category="so", - direction="l", - }, - [0x33ED]={ - category="so", - direction="l", - }, - [0x33EE]={ - category="so", - direction="l", - }, - [0x33EF]={ - category="so", - direction="l", - }, - [0x33F0]={ - category="so", - direction="l", - }, - [0x33F1]={ - category="so", - direction="l", - }, - [0x33F2]={ - category="so", - direction="l", - }, - [0x33F3]={ - category="so", - direction="l", - }, - [0x33F4]={ - category="so", - direction="l", - }, - [0x33F5]={ - category="so", - direction="l", - }, - [0x33F6]={ - category="so", - direction="l", - }, - [0x33F7]={ - category="so", - direction="l", - }, - [0x33F8]={ - category="so", - direction="l", - }, - [0x33F9]={ - category="so", - direction="l", - }, - [0x33FA]={ - category="so", - direction="l", - }, - [0x33FB]={ - category="so", - direction="l", - }, - [0x33FC]={ - category="so", - direction="l", - }, - [0x33FD]={ - category="so", - direction="l", - }, - [0x33FE]={ - category="so", - direction="l", - }, - [0x33FF]={ - category="so", - direction="on", - }, - [0x4DC0]={ - category="so", - direction="on", - }, - [0x4DC1]={ - category="so", - direction="on", - }, - [0x4DC2]={ - category="so", - direction="on", - }, - [0x4DC3]={ - category="so", - direction="on", - }, - [0x4DC4]={ - category="so", - direction="on", - }, - [0x4DC5]={ - category="so", - direction="on", - }, - [0x4DC6]={ - category="so", - direction="on", - }, - [0x4DC7]={ - category="so", - direction="on", - }, - [0x4DC8]={ - category="so", - direction="on", - }, - [0x4DC9]={ - category="so", - direction="on", - }, - [0x4DCA]={ - category="so", - direction="on", - }, - [0x4DCB]={ - category="so", - direction="on", - }, - [0x4DCC]={ - category="so", - direction="on", - }, - [0x4DCD]={ - category="so", - direction="on", - }, - [0x4DCE]={ - category="so", - direction="on", - }, - [0x4DCF]={ - category="so", - direction="on", - }, - [0x4DD0]={ - category="so", - direction="on", - }, - [0x4DD1]={ - category="so", - direction="on", - }, - [0x4DD2]={ - category="so", - direction="on", - }, - [0x4DD3]={ - category="so", - direction="on", - }, - [0x4DD4]={ - category="so", - direction="on", - }, - [0x4DD5]={ - category="so", - direction="on", - }, - [0x4DD6]={ - category="so", - direction="on", - }, - [0x4DD7]={ - category="so", - direction="on", - }, - [0x4DD8]={ - category="so", - direction="on", - }, - [0x4DD9]={ - category="so", - direction="on", - }, - [0x4DDA]={ - category="so", - direction="on", - }, - [0x4DDB]={ - category="so", - direction="on", - }, - [0x4DDC]={ - category="so", - direction="on", - }, - [0x4DDD]={ - category="so", - direction="on", - }, - [0x4DDE]={ - category="so", - direction="on", - }, - [0x4DDF]={ - category="so", - direction="on", - }, - [0x4DE0]={ - category="so", - direction="on", - }, - [0x4DE1]={ - category="so", - direction="on", - }, - [0x4DE2]={ - category="so", - direction="on", - }, - [0x4DE3]={ - category="so", - direction="on", - }, - [0x4DE4]={ - category="so", - direction="on", - }, - [0x4DE5]={ - category="so", - direction="on", - }, - [0x4DE6]={ - category="so", - direction="on", - }, - [0x4DE7]={ - category="so", - direction="on", - }, - [0x4DE8]={ - category="so", - direction="on", - }, - [0x4DE9]={ - category="so", - direction="on", - }, - [0x4DEA]={ - category="so", - direction="on", - }, - [0x4DEB]={ - category="so", - direction="on", - }, - [0x4DEC]={ - category="so", - direction="on", - }, - [0x4DED]={ - category="so", - direction="on", - }, - [0x4DEE]={ - category="so", - direction="on", - }, - [0x4DEF]={ - category="so", - direction="on", - }, - [0x4DF0]={ - category="so", - direction="on", - }, - [0x4DF1]={ - category="so", - direction="on", - }, - [0x4DF2]={ - category="so", - direction="on", - }, - [0x4DF3]={ - category="so", - direction="on", - }, - [0x4DF4]={ - category="so", - direction="on", - }, - [0x4DF5]={ - category="so", - direction="on", - }, - [0x4DF6]={ - category="so", - direction="on", - }, - [0x4DF7]={ - category="so", - direction="on", - }, - [0x4DF8]={ - category="so", - direction="on", - }, - [0x4DF9]={ - category="so", - direction="on", - }, - [0x4DFA]={ - category="so", - direction="on", - }, - [0x4DFB]={ - category="so", - direction="on", - }, - [0x4DFC]={ - category="so", - direction="on", - }, - [0x4DFD]={ - category="so", - direction="on", - }, - [0x4DFE]={ - category="so", - direction="on", - }, - [0x4DFF]={ - category="so", - direction="on", - }, - [0xA000]={ - category="lo", - direction="l", - }, - [0xA001]={ - category="lo", - direction="l", - }, - [0xA002]={ - category="lo", - direction="l", - }, - [0xA003]={ - category="lo", - direction="l", - }, - [0xA004]={ - category="lo", - direction="l", - }, - [0xA005]={ - category="lo", - direction="l", - }, - [0xA006]={ - category="lo", - direction="l", - }, - [0xA007]={ - category="lo", - direction="l", - }, - [0xA008]={ - category="lo", - direction="l", - }, - [0xA009]={ - category="lo", - direction="l", - }, - [0xA00A]={ - category="lo", - direction="l", - }, - [0xA00B]={ - category="lo", - direction="l", - }, - [0xA00C]={ - category="lo", - direction="l", - }, - [0xA00D]={ - category="lo", - direction="l", - }, - [0xA00E]={ - category="lo", - direction="l", - }, - [0xA00F]={ - category="lo", - direction="l", - }, - [0xA010]={ - category="lo", - direction="l", - }, - [0xA011]={ - category="lo", - direction="l", - }, - [0xA012]={ - category="lo", - direction="l", - }, - [0xA013]={ - category="lo", - direction="l", - }, - [0xA014]={ - category="lo", - direction="l", - }, - [0xA015]={ - category="lm", - direction="l", - }, - [0xA016]={ - category="lo", - direction="l", - }, - [0xA017]={ - category="lo", - direction="l", - }, - [0xA018]={ - category="lo", - direction="l", - }, - [0xA019]={ - category="lo", - direction="l", - }, - [0xA01A]={ - category="lo", - direction="l", - }, - [0xA01B]={ - category="lo", - direction="l", - }, - [0xA01C]={ - category="lo", - direction="l", - }, - [0xA01D]={ - category="lo", - direction="l", - }, - [0xA01E]={ - category="lo", - direction="l", - }, - [0xA01F]={ - category="lo", - direction="l", - }, - [0xA020]={ - category="lo", - direction="l", - }, - [0xA021]={ - category="lo", - direction="l", - }, - [0xA022]={ - category="lo", - direction="l", - }, - [0xA023]={ - category="lo", - direction="l", - }, - [0xA024]={ - category="lo", - direction="l", - }, - [0xA025]={ - category="lo", - direction="l", - }, - [0xA026]={ - category="lo", - direction="l", - }, - [0xA027]={ - category="lo", - direction="l", - }, - [0xA028]={ - category="lo", - direction="l", - }, - [0xA029]={ - category="lo", - direction="l", - }, - [0xA02A]={ - category="lo", - direction="l", - }, - [0xA02B]={ - category="lo", - direction="l", - }, - [0xA02C]={ - category="lo", - direction="l", - }, - [0xA02D]={ - category="lo", - direction="l", - }, - [0xA02E]={ - category="lo", - direction="l", - }, - [0xA02F]={ - category="lo", - direction="l", - }, - [0xA030]={ - category="lo", - direction="l", - }, - [0xA031]={ - category="lo", - direction="l", - }, - [0xA032]={ - category="lo", - direction="l", - }, - [0xA033]={ - category="lo", - direction="l", - }, - [0xA034]={ - category="lo", - direction="l", - }, - [0xA035]={ - category="lo", - direction="l", - }, - [0xA036]={ - category="lo", - direction="l", - }, - [0xA037]={ - category="lo", - direction="l", - }, - [0xA038]={ - category="lo", - direction="l", - }, - [0xA039]={ - category="lo", - direction="l", - }, - [0xA03A]={ - category="lo", - direction="l", - }, - [0xA03B]={ - category="lo", - direction="l", - }, - [0xA03C]={ - category="lo", - direction="l", - }, - [0xA03D]={ - category="lo", - direction="l", - }, - [0xA03E]={ - category="lo", - direction="l", - }, - [0xA03F]={ - category="lo", - direction="l", - }, - [0xA040]={ - category="lo", - direction="l", - }, - [0xA041]={ - category="lo", - direction="l", - }, - [0xA042]={ - category="lo", - direction="l", - }, - [0xA043]={ - category="lo", - direction="l", - }, - [0xA044]={ - category="lo", - direction="l", - }, - [0xA045]={ - category="lo", - direction="l", - }, - [0xA046]={ - category="lo", - direction="l", - }, - [0xA047]={ - category="lo", - direction="l", - }, - [0xA048]={ - category="lo", - direction="l", - }, - [0xA049]={ - category="lo", - direction="l", - }, - [0xA04A]={ - category="lo", - direction="l", - }, - [0xA04B]={ - category="lo", - direction="l", - }, - [0xA04C]={ - category="lo", - direction="l", - }, - [0xA04D]={ - category="lo", - direction="l", - }, - [0xA04E]={ - category="lo", - direction="l", - }, - [0xA04F]={ - category="lo", - direction="l", - }, - [0xA050]={ - category="lo", - direction="l", - }, - [0xA051]={ - category="lo", - direction="l", - }, - [0xA052]={ - category="lo", - direction="l", - }, - [0xA053]={ - category="lo", - direction="l", - }, - [0xA054]={ - category="lo", - direction="l", - }, - [0xA055]={ - category="lo", - direction="l", - }, - [0xA056]={ - category="lo", - direction="l", - }, - [0xA057]={ - category="lo", - direction="l", - }, - [0xA058]={ - category="lo", - direction="l", - }, - [0xA059]={ - category="lo", - direction="l", - }, - [0xA05A]={ - category="lo", - direction="l", - }, - [0xA05B]={ - category="lo", - direction="l", - }, - [0xA05C]={ - category="lo", - direction="l", - }, - [0xA05D]={ - category="lo", - direction="l", - }, - [0xA05E]={ - category="lo", - direction="l", - }, - [0xA05F]={ - category="lo", - direction="l", - }, - [0xA060]={ - category="lo", - direction="l", - }, - [0xA061]={ - category="lo", - direction="l", - }, - [0xA062]={ - category="lo", - direction="l", - }, - [0xA063]={ - category="lo", - direction="l", - }, - [0xA064]={ - category="lo", - direction="l", - }, - [0xA065]={ - category="lo", - direction="l", - }, - [0xA066]={ - category="lo", - direction="l", - }, - [0xA067]={ - category="lo", - direction="l", - }, - [0xA068]={ - category="lo", - direction="l", - }, - [0xA069]={ - category="lo", - direction="l", - }, - [0xA06A]={ - category="lo", - direction="l", - }, - [0xA06B]={ - category="lo", - direction="l", - }, - [0xA06C]={ - category="lo", - direction="l", - }, - [0xA06D]={ - category="lo", - direction="l", - }, - [0xA06E]={ - category="lo", - direction="l", - }, - [0xA06F]={ - category="lo", - direction="l", - }, - [0xA070]={ - category="lo", - direction="l", - }, - [0xA071]={ - category="lo", - direction="l", - }, - [0xA072]={ - category="lo", - direction="l", - }, - [0xA073]={ - category="lo", - direction="l", - }, - [0xA074]={ - category="lo", - direction="l", - }, - [0xA075]={ - category="lo", - direction="l", - }, - [0xA076]={ - category="lo", - direction="l", - }, - [0xA077]={ - category="lo", - direction="l", - }, - [0xA078]={ - category="lo", - direction="l", - }, - [0xA079]={ - category="lo", - direction="l", - }, - [0xA07A]={ - category="lo", - direction="l", - }, - [0xA07B]={ - category="lo", - direction="l", - }, - [0xA07C]={ - category="lo", - direction="l", - }, - [0xA07D]={ - category="lo", - direction="l", - }, - [0xA07E]={ - category="lo", - direction="l", - }, - [0xA07F]={ - category="lo", - direction="l", - }, - [0xA080]={ - category="lo", - direction="l", - }, - [0xA081]={ - category="lo", - direction="l", - }, - [0xA082]={ - category="lo", - direction="l", - }, - [0xA083]={ - category="lo", - direction="l", - }, - [0xA084]={ - category="lo", - direction="l", - }, - [0xA085]={ - category="lo", - direction="l", - }, - [0xA086]={ - category="lo", - direction="l", - }, - [0xA087]={ - category="lo", - direction="l", - }, - [0xA088]={ - category="lo", - direction="l", - }, - [0xA089]={ - category="lo", - direction="l", - }, - [0xA08A]={ - category="lo", - direction="l", - }, - [0xA08B]={ - category="lo", - direction="l", - }, - [0xA08C]={ - category="lo", - direction="l", - }, - [0xA08D]={ - category="lo", - direction="l", - }, - [0xA08E]={ - category="lo", - direction="l", - }, - [0xA08F]={ - category="lo", - direction="l", - }, - [0xA090]={ - category="lo", - direction="l", - }, - [0xA091]={ - category="lo", - direction="l", - }, - [0xA092]={ - category="lo", - direction="l", - }, - [0xA093]={ - category="lo", - direction="l", - }, - [0xA094]={ - category="lo", - direction="l", - }, - [0xA095]={ - category="lo", - direction="l", - }, - [0xA096]={ - category="lo", - direction="l", - }, - [0xA097]={ - category="lo", - direction="l", - }, - [0xA098]={ - category="lo", - direction="l", - }, - [0xA099]={ - category="lo", - direction="l", - }, - [0xA09A]={ - category="lo", - direction="l", - }, - [0xA09B]={ - category="lo", - direction="l", - }, - [0xA09C]={ - category="lo", - direction="l", - }, - [0xA09D]={ - category="lo", - direction="l", - }, - [0xA09E]={ - category="lo", - direction="l", - }, - [0xA09F]={ - category="lo", - direction="l", - }, - [0xA0A0]={ - category="lo", - direction="l", - }, - [0xA0A1]={ - category="lo", - direction="l", - }, - [0xA0A2]={ - category="lo", - direction="l", - }, - [0xA0A3]={ - category="lo", - direction="l", - }, - [0xA0A4]={ - category="lo", - direction="l", - }, - [0xA0A5]={ - category="lo", - direction="l", - }, - [0xA0A6]={ - category="lo", - direction="l", - }, - [0xA0A7]={ - category="lo", - direction="l", - }, - [0xA0A8]={ - category="lo", - direction="l", - }, - [0xA0A9]={ - category="lo", - direction="l", - }, - [0xA0AA]={ - category="lo", - direction="l", - }, - [0xA0AB]={ - category="lo", - direction="l", - }, - [0xA0AC]={ - category="lo", - direction="l", - }, - [0xA0AD]={ - category="lo", - direction="l", - }, - [0xA0AE]={ - category="lo", - direction="l", - }, - [0xA0AF]={ - category="lo", - direction="l", - }, - [0xA0B0]={ - category="lo", - direction="l", - }, - [0xA0B1]={ - category="lo", - direction="l", - }, - [0xA0B2]={ - category="lo", - direction="l", - }, - [0xA0B3]={ - category="lo", - direction="l", - }, - [0xA0B4]={ - category="lo", - direction="l", - }, - [0xA0B5]={ - category="lo", - direction="l", - }, - [0xA0B6]={ - category="lo", - direction="l", - }, - [0xA0B7]={ - category="lo", - direction="l", - }, - [0xA0B8]={ - category="lo", - direction="l", - }, - [0xA0B9]={ - category="lo", - direction="l", - }, - [0xA0BA]={ - category="lo", - direction="l", - }, - [0xA0BB]={ - category="lo", - direction="l", - }, - [0xA0BC]={ - category="lo", - direction="l", - }, - [0xA0BD]={ - category="lo", - direction="l", - }, - [0xA0BE]={ - category="lo", - direction="l", - }, - [0xA0BF]={ - category="lo", - direction="l", - }, - [0xA0C0]={ - category="lo", - direction="l", - }, - [0xA0C1]={ - category="lo", - direction="l", - }, - [0xA0C2]={ - category="lo", - direction="l", - }, - [0xA0C3]={ - category="lo", - direction="l", - }, - [0xA0C4]={ - category="lo", - direction="l", - }, - [0xA0C5]={ - category="lo", - direction="l", - }, - [0xA0C6]={ - category="lo", - direction="l", - }, - [0xA0C7]={ - category="lo", - direction="l", - }, - [0xA0C8]={ - category="lo", - direction="l", - }, - [0xA0C9]={ - category="lo", - direction="l", - }, - [0xA0CA]={ - category="lo", - direction="l", - }, - [0xA0CB]={ - category="lo", - direction="l", - }, - [0xA0CC]={ - category="lo", - direction="l", - }, - [0xA0CD]={ - category="lo", - direction="l", - }, - [0xA0CE]={ - category="lo", - direction="l", - }, - [0xA0CF]={ - category="lo", - direction="l", - }, - [0xA0D0]={ - category="lo", - direction="l", - }, - [0xA0D1]={ - category="lo", - direction="l", - }, - [0xA0D2]={ - category="lo", - direction="l", - }, - [0xA0D3]={ - category="lo", - direction="l", - }, - [0xA0D4]={ - category="lo", - direction="l", - }, - [0xA0D5]={ - category="lo", - direction="l", - }, - [0xA0D6]={ - category="lo", - direction="l", - }, - [0xA0D7]={ - category="lo", - direction="l", - }, - [0xA0D8]={ - category="lo", - direction="l", - }, - [0xA0D9]={ - category="lo", - direction="l", - }, - [0xA0DA]={ - category="lo", - direction="l", - }, - [0xA0DB]={ - category="lo", - direction="l", - }, - [0xA0DC]={ - category="lo", - direction="l", - }, - [0xA0DD]={ - category="lo", - direction="l", - }, - [0xA0DE]={ - category="lo", - direction="l", - }, - [0xA0DF]={ - category="lo", - direction="l", - }, - [0xA0E0]={ - category="lo", - direction="l", - }, - [0xA0E1]={ - category="lo", - direction="l", - }, - [0xA0E2]={ - category="lo", - direction="l", - }, - [0xA0E3]={ - category="lo", - direction="l", - }, - [0xA0E4]={ - category="lo", - direction="l", - }, - [0xA0E5]={ - category="lo", - direction="l", - }, - [0xA0E6]={ - category="lo", - direction="l", - }, - [0xA0E7]={ - category="lo", - direction="l", - }, - [0xA0E8]={ - category="lo", - direction="l", - }, - [0xA0E9]={ - category="lo", - direction="l", - }, - [0xA0EA]={ - category="lo", - direction="l", - }, - [0xA0EB]={ - category="lo", - direction="l", - }, - [0xA0EC]={ - category="lo", - direction="l", - }, - [0xA0ED]={ - category="lo", - direction="l", - }, - [0xA0EE]={ - category="lo", - direction="l", - }, - [0xA0EF]={ - category="lo", - direction="l", - }, - [0xA0F0]={ - category="lo", - direction="l", - }, - [0xA0F1]={ - category="lo", - direction="l", - }, - [0xA0F2]={ - category="lo", - direction="l", - }, - [0xA0F3]={ - category="lo", - direction="l", - }, - [0xA0F4]={ - category="lo", - direction="l", - }, - [0xA0F5]={ - category="lo", - direction="l", - }, - [0xA0F6]={ - category="lo", - direction="l", - }, - [0xA0F7]={ - category="lo", - direction="l", - }, - [0xA0F8]={ - category="lo", - direction="l", - }, - [0xA0F9]={ - category="lo", - direction="l", - }, - [0xA0FA]={ - category="lo", - direction="l", - }, - [0xA0FB]={ - category="lo", - direction="l", - }, - [0xA0FC]={ - category="lo", - direction="l", - }, - [0xA0FD]={ - category="lo", - direction="l", - }, - [0xA0FE]={ - category="lo", - direction="l", - }, - [0xA0FF]={ - category="lo", - direction="l", - }, - [0xA100]={ - category="lo", - direction="l", - }, - [0xA101]={ - category="lo", - direction="l", - }, - [0xA102]={ - category="lo", - direction="l", - }, - [0xA103]={ - category="lo", - direction="l", - }, - [0xA104]={ - category="lo", - direction="l", - }, - [0xA105]={ - category="lo", - direction="l", - }, - [0xA106]={ - category="lo", - direction="l", - }, - [0xA107]={ - category="lo", - direction="l", - }, - [0xA108]={ - category="lo", - direction="l", - }, - [0xA109]={ - category="lo", - direction="l", - }, - [0xA10A]={ - category="lo", - direction="l", - }, - [0xA10B]={ - category="lo", - direction="l", - }, - [0xA10C]={ - category="lo", - direction="l", - }, - [0xA10D]={ - category="lo", - direction="l", - }, - [0xA10E]={ - category="lo", - direction="l", - }, - [0xA10F]={ - category="lo", - direction="l", - }, - [0xA110]={ - category="lo", - direction="l", - }, - [0xA111]={ - category="lo", - direction="l", - }, - [0xA112]={ - category="lo", - direction="l", - }, - [0xA113]={ - category="lo", - direction="l", - }, - [0xA114]={ - category="lo", - direction="l", - }, - [0xA115]={ - category="lo", - direction="l", - }, - [0xA116]={ - category="lo", - direction="l", - }, - [0xA117]={ - category="lo", - direction="l", - }, - [0xA118]={ - category="lo", - direction="l", - }, - [0xA119]={ - category="lo", - direction="l", - }, - [0xA11A]={ - category="lo", - direction="l", - }, - [0xA11B]={ - category="lo", - direction="l", - }, - [0xA11C]={ - category="lo", - direction="l", - }, - [0xA11D]={ - category="lo", - direction="l", - }, - [0xA11E]={ - category="lo", - direction="l", - }, - [0xA11F]={ - category="lo", - direction="l", - }, - [0xA120]={ - category="lo", - direction="l", - }, - [0xA121]={ - category="lo", - direction="l", - }, - [0xA122]={ - category="lo", - direction="l", - }, - [0xA123]={ - category="lo", - direction="l", - }, - [0xA124]={ - category="lo", - direction="l", - }, - [0xA125]={ - category="lo", - direction="l", - }, - [0xA126]={ - category="lo", - direction="l", - }, - [0xA127]={ - category="lo", - direction="l", - }, - [0xA128]={ - category="lo", - direction="l", - }, - [0xA129]={ - category="lo", - direction="l", - }, - [0xA12A]={ - category="lo", - direction="l", - }, - [0xA12B]={ - category="lo", - direction="l", - }, - [0xA12C]={ - category="lo", - direction="l", - }, - [0xA12D]={ - category="lo", - direction="l", - }, - [0xA12E]={ - category="lo", - direction="l", - }, - [0xA12F]={ - category="lo", - direction="l", - }, - [0xA130]={ - category="lo", - direction="l", - }, - [0xA131]={ - category="lo", - direction="l", - }, - [0xA132]={ - category="lo", - direction="l", - }, - [0xA133]={ - category="lo", - direction="l", - }, - [0xA134]={ - category="lo", - direction="l", - }, - [0xA135]={ - category="lo", - direction="l", - }, - [0xA136]={ - category="lo", - direction="l", - }, - [0xA137]={ - category="lo", - direction="l", - }, - [0xA138]={ - category="lo", - direction="l", - }, - [0xA139]={ - category="lo", - direction="l", - }, - [0xA13A]={ - category="lo", - direction="l", - }, - [0xA13B]={ - category="lo", - direction="l", - }, - [0xA13C]={ - category="lo", - direction="l", - }, - [0xA13D]={ - category="lo", - direction="l", - }, - [0xA13E]={ - category="lo", - direction="l", - }, - [0xA13F]={ - category="lo", - direction="l", - }, - [0xA140]={ - category="lo", - direction="l", - }, - [0xA141]={ - category="lo", - direction="l", - }, - [0xA142]={ - category="lo", - direction="l", - }, - [0xA143]={ - category="lo", - direction="l", - }, - [0xA144]={ - category="lo", - direction="l", - }, - [0xA145]={ - category="lo", - direction="l", - }, - [0xA146]={ - category="lo", - direction="l", - }, - [0xA147]={ - category="lo", - direction="l", - }, - [0xA148]={ - category="lo", - direction="l", - }, - [0xA149]={ - category="lo", - direction="l", - }, - [0xA14A]={ - category="lo", - direction="l", - }, - [0xA14B]={ - category="lo", - direction="l", - }, - [0xA14C]={ - category="lo", - direction="l", - }, - [0xA14D]={ - category="lo", - direction="l", - }, - [0xA14E]={ - category="lo", - direction="l", - }, - [0xA14F]={ - category="lo", - direction="l", - }, - [0xA150]={ - category="lo", - direction="l", - }, - [0xA151]={ - category="lo", - direction="l", - }, - [0xA152]={ - category="lo", - direction="l", - }, - [0xA153]={ - category="lo", - direction="l", - }, - [0xA154]={ - category="lo", - direction="l", - }, - [0xA155]={ - category="lo", - direction="l", - }, - [0xA156]={ - category="lo", - direction="l", - }, - [0xA157]={ - category="lo", - direction="l", - }, - [0xA158]={ - category="lo", - direction="l", - }, - [0xA159]={ - category="lo", - direction="l", - }, - [0xA15A]={ - category="lo", - direction="l", - }, - [0xA15B]={ - category="lo", - direction="l", - }, - [0xA15C]={ - category="lo", - direction="l", - }, - [0xA15D]={ - category="lo", - direction="l", - }, - [0xA15E]={ - category="lo", - direction="l", - }, - [0xA15F]={ - category="lo", - direction="l", - }, - [0xA160]={ - category="lo", - direction="l", - }, - [0xA161]={ - category="lo", - direction="l", - }, - [0xA162]={ - category="lo", - direction="l", - }, - [0xA163]={ - category="lo", - direction="l", - }, - [0xA164]={ - category="lo", - direction="l", - }, - [0xA165]={ - category="lo", - direction="l", - }, - [0xA166]={ - category="lo", - direction="l", - }, - [0xA167]={ - category="lo", - direction="l", - }, - [0xA168]={ - category="lo", - direction="l", - }, - [0xA169]={ - category="lo", - direction="l", - }, - [0xA16A]={ - category="lo", - direction="l", - }, - [0xA16B]={ - category="lo", - direction="l", - }, - [0xA16C]={ - category="lo", - direction="l", - }, - [0xA16D]={ - category="lo", - direction="l", - }, - [0xA16E]={ - category="lo", - direction="l", - }, - [0xA16F]={ - category="lo", - direction="l", - }, - [0xA170]={ - category="lo", - direction="l", - }, - [0xA171]={ - category="lo", - direction="l", - }, - [0xA172]={ - category="lo", - direction="l", - }, - [0xA173]={ - category="lo", - direction="l", - }, - [0xA174]={ - category="lo", - direction="l", - }, - [0xA175]={ - category="lo", - direction="l", - }, - [0xA176]={ - category="lo", - direction="l", - }, - [0xA177]={ - category="lo", - direction="l", - }, - [0xA178]={ - category="lo", - direction="l", - }, - [0xA179]={ - category="lo", - direction="l", - }, - [0xA17A]={ - category="lo", - direction="l", - }, - [0xA17B]={ - category="lo", - direction="l", - }, - [0xA17C]={ - category="lo", - direction="l", - }, - [0xA17D]={ - category="lo", - direction="l", - }, - [0xA17E]={ - category="lo", - direction="l", - }, - [0xA17F]={ - category="lo", - direction="l", - }, - [0xA180]={ - category="lo", - direction="l", - }, - [0xA181]={ - category="lo", - direction="l", - }, - [0xA182]={ - category="lo", - direction="l", - }, - [0xA183]={ - category="lo", - direction="l", - }, - [0xA184]={ - category="lo", - direction="l", - }, - [0xA185]={ - category="lo", - direction="l", - }, - [0xA186]={ - category="lo", - direction="l", - }, - [0xA187]={ - category="lo", - direction="l", - }, - [0xA188]={ - category="lo", - direction="l", - }, - [0xA189]={ - category="lo", - direction="l", - }, - [0xA18A]={ - category="lo", - direction="l", - }, - [0xA18B]={ - category="lo", - direction="l", - }, - [0xA18C]={ - category="lo", - direction="l", - }, - [0xA18D]={ - category="lo", - direction="l", - }, - [0xA18E]={ - category="lo", - direction="l", - }, - [0xA18F]={ - category="lo", - direction="l", - }, - [0xA190]={ - category="lo", - direction="l", - }, - [0xA191]={ - category="lo", - direction="l", - }, - [0xA192]={ - category="lo", - direction="l", - }, - [0xA193]={ - category="lo", - direction="l", - }, - [0xA194]={ - category="lo", - direction="l", - }, - [0xA195]={ - category="lo", - direction="l", - }, - [0xA196]={ - category="lo", - direction="l", - }, - [0xA197]={ - category="lo", - direction="l", - }, - [0xA198]={ - category="lo", - direction="l", - }, - [0xA199]={ - category="lo", - direction="l", - }, - [0xA19A]={ - category="lo", - direction="l", - }, - [0xA19B]={ - category="lo", - direction="l", - }, - [0xA19C]={ - category="lo", - direction="l", - }, - [0xA19D]={ - category="lo", - direction="l", - }, - [0xA19E]={ - category="lo", - direction="l", - }, - [0xA19F]={ - category="lo", - direction="l", - }, - [0xA1A0]={ - category="lo", - direction="l", - }, - [0xA1A1]={ - category="lo", - direction="l", - }, - [0xA1A2]={ - category="lo", - direction="l", - }, - [0xA1A3]={ - category="lo", - direction="l", - }, - [0xA1A4]={ - category="lo", - direction="l", - }, - [0xA1A5]={ - category="lo", - direction="l", - }, - [0xA1A6]={ - category="lo", - direction="l", - }, - [0xA1A7]={ - category="lo", - direction="l", - }, - [0xA1A8]={ - category="lo", - direction="l", - }, - [0xA1A9]={ - category="lo", - direction="l", - }, - [0xA1AA]={ - category="lo", - direction="l", - }, - [0xA1AB]={ - category="lo", - direction="l", - }, - [0xA1AC]={ - category="lo", - direction="l", - }, - [0xA1AD]={ - category="lo", - direction="l", - }, - [0xA1AE]={ - category="lo", - direction="l", - }, - [0xA1AF]={ - category="lo", - direction="l", - }, - [0xA1B0]={ - category="lo", - direction="l", - }, - [0xA1B1]={ - category="lo", - direction="l", - }, - [0xA1B2]={ - category="lo", - direction="l", - }, - [0xA1B3]={ - category="lo", - direction="l", - }, - [0xA1B4]={ - category="lo", - direction="l", - }, - [0xA1B5]={ - category="lo", - direction="l", - }, - [0xA1B6]={ - category="lo", - direction="l", - }, - [0xA1B7]={ - category="lo", - direction="l", - }, - [0xA1B8]={ - category="lo", - direction="l", - }, - [0xA1B9]={ - category="lo", - direction="l", - }, - [0xA1BA]={ - category="lo", - direction="l", - }, - [0xA1BB]={ - category="lo", - direction="l", - }, - [0xA1BC]={ - category="lo", - direction="l", - }, - [0xA1BD]={ - category="lo", - direction="l", - }, - [0xA1BE]={ - category="lo", - direction="l", - }, - [0xA1BF]={ - category="lo", - direction="l", - }, - [0xA1C0]={ - category="lo", - direction="l", - }, - [0xA1C1]={ - category="lo", - direction="l", - }, - [0xA1C2]={ - category="lo", - direction="l", - }, - [0xA1C3]={ - category="lo", - direction="l", - }, - [0xA1C4]={ - category="lo", - direction="l", - }, - [0xA1C5]={ - category="lo", - direction="l", - }, - [0xA1C6]={ - category="lo", - direction="l", - }, - [0xA1C7]={ - category="lo", - direction="l", - }, - [0xA1C8]={ - category="lo", - direction="l", - }, - [0xA1C9]={ - category="lo", - direction="l", - }, - [0xA1CA]={ - category="lo", - direction="l", - }, - [0xA1CB]={ - category="lo", - direction="l", - }, - [0xA1CC]={ - category="lo", - direction="l", - }, - [0xA1CD]={ - category="lo", - direction="l", - }, - [0xA1CE]={ - category="lo", - direction="l", - }, - [0xA1CF]={ - category="lo", - direction="l", - }, - [0xA1D0]={ - category="lo", - direction="l", - }, - [0xA1D1]={ - category="lo", - direction="l", - }, - [0xA1D2]={ - category="lo", - direction="l", - }, - [0xA1D3]={ - category="lo", - direction="l", - }, - [0xA1D4]={ - category="lo", - direction="l", - }, - [0xA1D5]={ - category="lo", - direction="l", - }, - [0xA1D6]={ - category="lo", - direction="l", - }, - [0xA1D7]={ - category="lo", - direction="l", - }, - [0xA1D8]={ - category="lo", - direction="l", - }, - [0xA1D9]={ - category="lo", - direction="l", - }, - [0xA1DA]={ - category="lo", - direction="l", - }, - [0xA1DB]={ - category="lo", - direction="l", - }, - [0xA1DC]={ - category="lo", - direction="l", - }, - [0xA1DD]={ - category="lo", - direction="l", - }, - [0xA1DE]={ - category="lo", - direction="l", - }, - [0xA1DF]={ - category="lo", - direction="l", - }, - [0xA1E0]={ - category="lo", - direction="l", - }, - [0xA1E1]={ - category="lo", - direction="l", - }, - [0xA1E2]={ - category="lo", - direction="l", - }, - [0xA1E3]={ - category="lo", - direction="l", - }, - [0xA1E4]={ - category="lo", - direction="l", - }, - [0xA1E5]={ - category="lo", - direction="l", - }, - [0xA1E6]={ - category="lo", - direction="l", - }, - [0xA1E7]={ - category="lo", - direction="l", - }, - [0xA1E8]={ - category="lo", - direction="l", - }, - [0xA1E9]={ - category="lo", - direction="l", - }, - [0xA1EA]={ - category="lo", - direction="l", - }, - [0xA1EB]={ - category="lo", - direction="l", - }, - [0xA1EC]={ - category="lo", - direction="l", - }, - [0xA1ED]={ - category="lo", - direction="l", - }, - [0xA1EE]={ - category="lo", - direction="l", - }, - [0xA1EF]={ - category="lo", - direction="l", - }, - [0xA1F0]={ - category="lo", - direction="l", - }, - [0xA1F1]={ - category="lo", - direction="l", - }, - [0xA1F2]={ - category="lo", - direction="l", - }, - [0xA1F3]={ - category="lo", - direction="l", - }, - [0xA1F4]={ - category="lo", - direction="l", - }, - [0xA1F5]={ - category="lo", - direction="l", - }, - [0xA1F6]={ - category="lo", - direction="l", - }, - [0xA1F7]={ - category="lo", - direction="l", - }, - [0xA1F8]={ - category="lo", - direction="l", - }, - [0xA1F9]={ - category="lo", - direction="l", - }, - [0xA1FA]={ - category="lo", - direction="l", - }, - [0xA1FB]={ - category="lo", - direction="l", - }, - [0xA1FC]={ - category="lo", - direction="l", - }, - [0xA1FD]={ - category="lo", - direction="l", - }, - [0xA1FE]={ - category="lo", - direction="l", - }, - [0xA1FF]={ - category="lo", - direction="l", - }, - [0xA200]={ - category="lo", - direction="l", - }, - [0xA201]={ - category="lo", - direction="l", - }, - [0xA202]={ - category="lo", - direction="l", - }, - [0xA203]={ - category="lo", - direction="l", - }, - [0xA204]={ - category="lo", - direction="l", - }, - [0xA205]={ - category="lo", - direction="l", - }, - [0xA206]={ - category="lo", - direction="l", - }, - [0xA207]={ - category="lo", - direction="l", - }, - [0xA208]={ - category="lo", - direction="l", - }, - [0xA209]={ - category="lo", - direction="l", - }, - [0xA20A]={ - category="lo", - direction="l", - }, - [0xA20B]={ - category="lo", - direction="l", - }, - [0xA20C]={ - category="lo", - direction="l", - }, - [0xA20D]={ - category="lo", - direction="l", - }, - [0xA20E]={ - category="lo", - direction="l", - }, - [0xA20F]={ - category="lo", - direction="l", - }, - [0xA210]={ - category="lo", - direction="l", - }, - [0xA211]={ - category="lo", - direction="l", - }, - [0xA212]={ - category="lo", - direction="l", - }, - [0xA213]={ - category="lo", - direction="l", - }, - [0xA214]={ - category="lo", - direction="l", - }, - [0xA215]={ - category="lo", - direction="l", - }, - [0xA216]={ - category="lo", - direction="l", - }, - [0xA217]={ - category="lo", - direction="l", - }, - [0xA218]={ - category="lo", - direction="l", - }, - [0xA219]={ - category="lo", - direction="l", - }, - [0xA21A]={ - category="lo", - direction="l", - }, - [0xA21B]={ - category="lo", - direction="l", - }, - [0xA21C]={ - category="lo", - direction="l", - }, - [0xA21D]={ - category="lo", - direction="l", - }, - [0xA21E]={ - category="lo", - direction="l", - }, - [0xA21F]={ - category="lo", - direction="l", - }, - [0xA220]={ - category="lo", - direction="l", - }, - [0xA221]={ - category="lo", - direction="l", - }, - [0xA222]={ - category="lo", - direction="l", - }, - [0xA223]={ - category="lo", - direction="l", - }, - [0xA224]={ - category="lo", - direction="l", - }, - [0xA225]={ - category="lo", - direction="l", - }, - [0xA226]={ - category="lo", - direction="l", - }, - [0xA227]={ - category="lo", - direction="l", - }, - [0xA228]={ - category="lo", - direction="l", - }, - [0xA229]={ - category="lo", - direction="l", - }, - [0xA22A]={ - category="lo", - direction="l", - }, - [0xA22B]={ - category="lo", - direction="l", - }, - [0xA22C]={ - category="lo", - direction="l", - }, - [0xA22D]={ - category="lo", - direction="l", - }, - [0xA22E]={ - category="lo", - direction="l", - }, - [0xA22F]={ - category="lo", - direction="l", - }, - [0xA230]={ - category="lo", - direction="l", - }, - [0xA231]={ - category="lo", - direction="l", - }, - [0xA232]={ - category="lo", - direction="l", - }, - [0xA233]={ - category="lo", - direction="l", - }, - [0xA234]={ - category="lo", - direction="l", - }, - [0xA235]={ - category="lo", - direction="l", - }, - [0xA236]={ - category="lo", - direction="l", - }, - [0xA237]={ - category="lo", - direction="l", - }, - [0xA238]={ - category="lo", - direction="l", - }, - [0xA239]={ - category="lo", - direction="l", - }, - [0xA23A]={ - category="lo", - direction="l", - }, - [0xA23B]={ - category="lo", - direction="l", - }, - [0xA23C]={ - category="lo", - direction="l", - }, - [0xA23D]={ - category="lo", - direction="l", - }, - [0xA23E]={ - category="lo", - direction="l", - }, - [0xA23F]={ - category="lo", - direction="l", - }, - [0xA240]={ - category="lo", - direction="l", - }, - [0xA241]={ - category="lo", - direction="l", - }, - [0xA242]={ - category="lo", - direction="l", - }, - [0xA243]={ - category="lo", - direction="l", - }, - [0xA244]={ - category="lo", - direction="l", - }, - [0xA245]={ - category="lo", - direction="l", - }, - [0xA246]={ - category="lo", - direction="l", - }, - [0xA247]={ - category="lo", - direction="l", - }, - [0xA248]={ - category="lo", - direction="l", - }, - [0xA249]={ - category="lo", - direction="l", - }, - [0xA24A]={ - category="lo", - direction="l", - }, - [0xA24B]={ - category="lo", - direction="l", - }, - [0xA24C]={ - category="lo", - direction="l", - }, - [0xA24D]={ - category="lo", - direction="l", - }, - [0xA24E]={ - category="lo", - direction="l", - }, - [0xA24F]={ - category="lo", - direction="l", - }, - [0xA250]={ - category="lo", - direction="l", - }, - [0xA251]={ - category="lo", - direction="l", - }, - [0xA252]={ - category="lo", - direction="l", - }, - [0xA253]={ - category="lo", - direction="l", - }, - [0xA254]={ - category="lo", - direction="l", - }, - [0xA255]={ - category="lo", - direction="l", - }, - [0xA256]={ - category="lo", - direction="l", - }, - [0xA257]={ - category="lo", - direction="l", - }, - [0xA258]={ - category="lo", - direction="l", - }, - [0xA259]={ - category="lo", - direction="l", - }, - [0xA25A]={ - category="lo", - direction="l", - }, - [0xA25B]={ - category="lo", - direction="l", - }, - [0xA25C]={ - category="lo", - direction="l", - }, - [0xA25D]={ - category="lo", - direction="l", - }, - [0xA25E]={ - category="lo", - direction="l", - }, - [0xA25F]={ - category="lo", - direction="l", - }, - [0xA260]={ - category="lo", - direction="l", - }, - [0xA261]={ - category="lo", - direction="l", - }, - [0xA262]={ - category="lo", - direction="l", - }, - [0xA263]={ - category="lo", - direction="l", - }, - [0xA264]={ - category="lo", - direction="l", - }, - [0xA265]={ - category="lo", - direction="l", - }, - [0xA266]={ - category="lo", - direction="l", - }, - [0xA267]={ - category="lo", - direction="l", - }, - [0xA268]={ - category="lo", - direction="l", - }, - [0xA269]={ - category="lo", - direction="l", - }, - [0xA26A]={ - category="lo", - direction="l", - }, - [0xA26B]={ - category="lo", - direction="l", - }, - [0xA26C]={ - category="lo", - direction="l", - }, - [0xA26D]={ - category="lo", - direction="l", - }, - [0xA26E]={ - category="lo", - direction="l", - }, - [0xA26F]={ - category="lo", - direction="l", - }, - [0xA270]={ - category="lo", - direction="l", - }, - [0xA271]={ - category="lo", - direction="l", - }, - [0xA272]={ - category="lo", - direction="l", - }, - [0xA273]={ - category="lo", - direction="l", - }, - [0xA274]={ - category="lo", - direction="l", - }, - [0xA275]={ - category="lo", - direction="l", - }, - [0xA276]={ - category="lo", - direction="l", - }, - [0xA277]={ - category="lo", - direction="l", - }, - [0xA278]={ - category="lo", - direction="l", - }, - [0xA279]={ - category="lo", - direction="l", - }, - [0xA27A]={ - category="lo", - direction="l", - }, - [0xA27B]={ - category="lo", - direction="l", - }, - [0xA27C]={ - category="lo", - direction="l", - }, - [0xA27D]={ - category="lo", - direction="l", - }, - [0xA27E]={ - category="lo", - direction="l", - }, - [0xA27F]={ - category="lo", - direction="l", - }, - [0xA280]={ - category="lo", - direction="l", - }, - [0xA281]={ - category="lo", - direction="l", - }, - [0xA282]={ - category="lo", - direction="l", - }, - [0xA283]={ - category="lo", - direction="l", - }, - [0xA284]={ - category="lo", - direction="l", - }, - [0xA285]={ - category="lo", - direction="l", - }, - [0xA286]={ - category="lo", - direction="l", - }, - [0xA287]={ - category="lo", - direction="l", - }, - [0xA288]={ - category="lo", - direction="l", - }, - [0xA289]={ - category="lo", - direction="l", - }, - [0xA28A]={ - category="lo", - direction="l", - }, - [0xA28B]={ - category="lo", - direction="l", - }, - [0xA28C]={ - category="lo", - direction="l", - }, - [0xA28D]={ - category="lo", - direction="l", - }, - [0xA28E]={ - category="lo", - direction="l", - }, - [0xA28F]={ - category="lo", - direction="l", - }, - [0xA290]={ - category="lo", - direction="l", - }, - [0xA291]={ - category="lo", - direction="l", - }, - [0xA292]={ - category="lo", - direction="l", - }, - [0xA293]={ - category="lo", - direction="l", - }, - [0xA294]={ - category="lo", - direction="l", - }, - [0xA295]={ - category="lo", - direction="l", - }, - [0xA296]={ - category="lo", - direction="l", - }, - [0xA297]={ - category="lo", - direction="l", - }, - [0xA298]={ - category="lo", - direction="l", - }, - [0xA299]={ - category="lo", - direction="l", - }, - [0xA29A]={ - category="lo", - direction="l", - }, - [0xA29B]={ - category="lo", - direction="l", - }, - [0xA29C]={ - category="lo", - direction="l", - }, - [0xA29D]={ - category="lo", - direction="l", - }, - [0xA29E]={ - category="lo", - direction="l", - }, - [0xA29F]={ - category="lo", - direction="l", - }, - [0xA2A0]={ - category="lo", - direction="l", - }, - [0xA2A1]={ - category="lo", - direction="l", - }, - [0xA2A2]={ - category="lo", - direction="l", - }, - [0xA2A3]={ - category="lo", - direction="l", - }, - [0xA2A4]={ - category="lo", - direction="l", - }, - [0xA2A5]={ - category="lo", - direction="l", - }, - [0xA2A6]={ - category="lo", - direction="l", - }, - [0xA2A7]={ - category="lo", - direction="l", - }, - [0xA2A8]={ - category="lo", - direction="l", - }, - [0xA2A9]={ - category="lo", - direction="l", - }, - [0xA2AA]={ - category="lo", - direction="l", - }, - [0xA2AB]={ - category="lo", - direction="l", - }, - [0xA2AC]={ - category="lo", - direction="l", - }, - [0xA2AD]={ - category="lo", - direction="l", - }, - [0xA2AE]={ - category="lo", - direction="l", - }, - [0xA2AF]={ - category="lo", - direction="l", - }, - [0xA2B0]={ - category="lo", - direction="l", - }, - [0xA2B1]={ - category="lo", - direction="l", - }, - [0xA2B2]={ - category="lo", - direction="l", - }, - [0xA2B3]={ - category="lo", - direction="l", - }, - [0xA2B4]={ - category="lo", - direction="l", - }, - [0xA2B5]={ - category="lo", - direction="l", - }, - [0xA2B6]={ - category="lo", - direction="l", - }, - [0xA2B7]={ - category="lo", - direction="l", - }, - [0xA2B8]={ - category="lo", - direction="l", - }, - [0xA2B9]={ - category="lo", - direction="l", - }, - [0xA2BA]={ - category="lo", - direction="l", - }, - [0xA2BB]={ - category="lo", - direction="l", - }, - [0xA2BC]={ - category="lo", - direction="l", - }, - [0xA2BD]={ - category="lo", - direction="l", - }, - [0xA2BE]={ - category="lo", - direction="l", - }, - [0xA2BF]={ - category="lo", - direction="l", - }, - [0xA2C0]={ - category="lo", - direction="l", - }, - [0xA2C1]={ - category="lo", - direction="l", - }, - [0xA2C2]={ - category="lo", - direction="l", - }, - [0xA2C3]={ - category="lo", - direction="l", - }, - [0xA2C4]={ - category="lo", - direction="l", - }, - [0xA2C5]={ - category="lo", - direction="l", - }, - [0xA2C6]={ - category="lo", - direction="l", - }, - [0xA2C7]={ - category="lo", - direction="l", - }, - [0xA2C8]={ - category="lo", - direction="l", - }, - [0xA2C9]={ - category="lo", - direction="l", - }, - [0xA2CA]={ - category="lo", - direction="l", - }, - [0xA2CB]={ - category="lo", - direction="l", - }, - [0xA2CC]={ - category="lo", - direction="l", - }, - [0xA2CD]={ - category="lo", - direction="l", - }, - [0xA2CE]={ - category="lo", - direction="l", - }, - [0xA2CF]={ - category="lo", - direction="l", - }, - [0xA2D0]={ - category="lo", - direction="l", - }, - [0xA2D1]={ - category="lo", - direction="l", - }, - [0xA2D2]={ - category="lo", - direction="l", - }, - [0xA2D3]={ - category="lo", - direction="l", - }, - [0xA2D4]={ - category="lo", - direction="l", - }, - [0xA2D5]={ - category="lo", - direction="l", - }, - [0xA2D6]={ - category="lo", - direction="l", - }, - [0xA2D7]={ - category="lo", - direction="l", - }, - [0xA2D8]={ - category="lo", - direction="l", - }, - [0xA2D9]={ - category="lo", - direction="l", - }, - [0xA2DA]={ - category="lo", - direction="l", - }, - [0xA2DB]={ - category="lo", - direction="l", - }, - [0xA2DC]={ - category="lo", - direction="l", - }, - [0xA2DD]={ - category="lo", - direction="l", - }, - [0xA2DE]={ - category="lo", - direction="l", - }, - [0xA2DF]={ - category="lo", - direction="l", - }, - [0xA2E0]={ - category="lo", - direction="l", - }, - [0xA2E1]={ - category="lo", - direction="l", - }, - [0xA2E2]={ - category="lo", - direction="l", - }, - [0xA2E3]={ - category="lo", - direction="l", - }, - [0xA2E4]={ - category="lo", - direction="l", - }, - [0xA2E5]={ - category="lo", - direction="l", - }, - [0xA2E6]={ - category="lo", - direction="l", - }, - [0xA2E7]={ - category="lo", - direction="l", - }, - [0xA2E8]={ - category="lo", - direction="l", - }, - [0xA2E9]={ - category="lo", - direction="l", - }, - [0xA2EA]={ - category="lo", - direction="l", - }, - [0xA2EB]={ - category="lo", - direction="l", - }, - [0xA2EC]={ - category="lo", - direction="l", - }, - [0xA2ED]={ - category="lo", - direction="l", - }, - [0xA2EE]={ - category="lo", - direction="l", - }, - [0xA2EF]={ - category="lo", - direction="l", - }, - [0xA2F0]={ - category="lo", - direction="l", - }, - [0xA2F1]={ - category="lo", - direction="l", - }, - [0xA2F2]={ - category="lo", - direction="l", - }, - [0xA2F3]={ - category="lo", - direction="l", - }, - [0xA2F4]={ - category="lo", - direction="l", - }, - [0xA2F5]={ - category="lo", - direction="l", - }, - [0xA2F6]={ - category="lo", - direction="l", - }, - [0xA2F7]={ - category="lo", - direction="l", - }, - [0xA2F8]={ - category="lo", - direction="l", - }, - [0xA2F9]={ - category="lo", - direction="l", - }, - [0xA2FA]={ - category="lo", - direction="l", - }, - [0xA2FB]={ - category="lo", - direction="l", - }, - [0xA2FC]={ - category="lo", - direction="l", - }, - [0xA2FD]={ - category="lo", - direction="l", - }, - [0xA2FE]={ - category="lo", - direction="l", - }, - [0xA2FF]={ - category="lo", - direction="l", - }, - [0xA300]={ - category="lo", - direction="l", - }, - [0xA301]={ - category="lo", - direction="l", - }, - [0xA302]={ - category="lo", - direction="l", - }, - [0xA303]={ - category="lo", - direction="l", - }, - [0xA304]={ - category="lo", - direction="l", - }, - [0xA305]={ - category="lo", - direction="l", - }, - [0xA306]={ - category="lo", - direction="l", - }, - [0xA307]={ - category="lo", - direction="l", - }, - [0xA308]={ - category="lo", - direction="l", - }, - [0xA309]={ - category="lo", - direction="l", - }, - [0xA30A]={ - category="lo", - direction="l", - }, - [0xA30B]={ - category="lo", - direction="l", - }, - [0xA30C]={ - category="lo", - direction="l", - }, - [0xA30D]={ - category="lo", - direction="l", - }, - [0xA30E]={ - category="lo", - direction="l", - }, - [0xA30F]={ - category="lo", - direction="l", - }, - [0xA310]={ - category="lo", - direction="l", - }, - [0xA311]={ - category="lo", - direction="l", - }, - [0xA312]={ - category="lo", - direction="l", - }, - [0xA313]={ - category="lo", - direction="l", - }, - [0xA314]={ - category="lo", - direction="l", - }, - [0xA315]={ - category="lo", - direction="l", - }, - [0xA316]={ - category="lo", - direction="l", - }, - [0xA317]={ - category="lo", - direction="l", - }, - [0xA318]={ - category="lo", - direction="l", - }, - [0xA319]={ - category="lo", - direction="l", - }, - [0xA31A]={ - category="lo", - direction="l", - }, - [0xA31B]={ - category="lo", - direction="l", - }, - [0xA31C]={ - category="lo", - direction="l", - }, - [0xA31D]={ - category="lo", - direction="l", - }, - [0xA31E]={ - category="lo", - direction="l", - }, - [0xA31F]={ - category="lo", - direction="l", - }, - [0xA320]={ - category="lo", - direction="l", - }, - [0xA321]={ - category="lo", - direction="l", - }, - [0xA322]={ - category="lo", - direction="l", - }, - [0xA323]={ - category="lo", - direction="l", - }, - [0xA324]={ - category="lo", - direction="l", - }, - [0xA325]={ - category="lo", - direction="l", - }, - [0xA326]={ - category="lo", - direction="l", - }, - [0xA327]={ - category="lo", - direction="l", - }, - [0xA328]={ - category="lo", - direction="l", - }, - [0xA329]={ - category="lo", - direction="l", - }, - [0xA32A]={ - category="lo", - direction="l", - }, - [0xA32B]={ - category="lo", - direction="l", - }, - [0xA32C]={ - category="lo", - direction="l", - }, - [0xA32D]={ - category="lo", - direction="l", - }, - [0xA32E]={ - category="lo", - direction="l", - }, - [0xA32F]={ - category="lo", - direction="l", - }, - [0xA330]={ - category="lo", - direction="l", - }, - [0xA331]={ - category="lo", - direction="l", - }, - [0xA332]={ - category="lo", - direction="l", - }, - [0xA333]={ - category="lo", - direction="l", - }, - [0xA334]={ - category="lo", - direction="l", - }, - [0xA335]={ - category="lo", - direction="l", - }, - [0xA336]={ - category="lo", - direction="l", - }, - [0xA337]={ - category="lo", - direction="l", - }, - [0xA338]={ - category="lo", - direction="l", - }, - [0xA339]={ - category="lo", - direction="l", - }, - [0xA33A]={ - category="lo", - direction="l", - }, - [0xA33B]={ - category="lo", - direction="l", - }, - [0xA33C]={ - category="lo", - direction="l", - }, - [0xA33D]={ - category="lo", - direction="l", - }, - [0xA33E]={ - category="lo", - direction="l", - }, - [0xA33F]={ - category="lo", - direction="l", - }, - [0xA340]={ - category="lo", - direction="l", - }, - [0xA341]={ - category="lo", - direction="l", - }, - [0xA342]={ - category="lo", - direction="l", - }, - [0xA343]={ - category="lo", - direction="l", - }, - [0xA344]={ - category="lo", - direction="l", - }, - [0xA345]={ - category="lo", - direction="l", - }, - [0xA346]={ - category="lo", - direction="l", - }, - [0xA347]={ - category="lo", - direction="l", - }, - [0xA348]={ - category="lo", - direction="l", - }, - [0xA349]={ - category="lo", - direction="l", - }, - [0xA34A]={ - category="lo", - direction="l", - }, - [0xA34B]={ - category="lo", - direction="l", - }, - [0xA34C]={ - category="lo", - direction="l", - }, - [0xA34D]={ - category="lo", - direction="l", - }, - [0xA34E]={ - category="lo", - direction="l", - }, - [0xA34F]={ - category="lo", - direction="l", - }, - [0xA350]={ - category="lo", - direction="l", - }, - [0xA351]={ - category="lo", - direction="l", - }, - [0xA352]={ - category="lo", - direction="l", - }, - [0xA353]={ - category="lo", - direction="l", - }, - [0xA354]={ - category="lo", - direction="l", - }, - [0xA355]={ - category="lo", - direction="l", - }, - [0xA356]={ - category="lo", - direction="l", - }, - [0xA357]={ - category="lo", - direction="l", - }, - [0xA358]={ - category="lo", - direction="l", - }, - [0xA359]={ - category="lo", - direction="l", - }, - [0xA35A]={ - category="lo", - direction="l", - }, - [0xA35B]={ - category="lo", - direction="l", - }, - [0xA35C]={ - category="lo", - direction="l", - }, - [0xA35D]={ - category="lo", - direction="l", - }, - [0xA35E]={ - category="lo", - direction="l", - }, - [0xA35F]={ - category="lo", - direction="l", - }, - [0xA360]={ - category="lo", - direction="l", - }, - [0xA361]={ - category="lo", - direction="l", - }, - [0xA362]={ - category="lo", - direction="l", - }, - [0xA363]={ - category="lo", - direction="l", - }, - [0xA364]={ - category="lo", - direction="l", - }, - [0xA365]={ - category="lo", - direction="l", - }, - [0xA366]={ - category="lo", - direction="l", - }, - [0xA367]={ - category="lo", - direction="l", - }, - [0xA368]={ - category="lo", - direction="l", - }, - [0xA369]={ - category="lo", - direction="l", - }, - [0xA36A]={ - category="lo", - direction="l", - }, - [0xA36B]={ - category="lo", - direction="l", - }, - [0xA36C]={ - category="lo", - direction="l", - }, - [0xA36D]={ - category="lo", - direction="l", - }, - [0xA36E]={ - category="lo", - direction="l", - }, - [0xA36F]={ - category="lo", - direction="l", - }, - [0xA370]={ - category="lo", - direction="l", - }, - [0xA371]={ - category="lo", - direction="l", - }, - [0xA372]={ - category="lo", - direction="l", - }, - [0xA373]={ - category="lo", - direction="l", - }, - [0xA374]={ - category="lo", - direction="l", - }, - [0xA375]={ - category="lo", - direction="l", - }, - [0xA376]={ - category="lo", - direction="l", - }, - [0xA377]={ - category="lo", - direction="l", - }, - [0xA378]={ - category="lo", - direction="l", - }, - [0xA379]={ - category="lo", - direction="l", - }, - [0xA37A]={ - category="lo", - direction="l", - }, - [0xA37B]={ - category="lo", - direction="l", - }, - [0xA37C]={ - category="lo", - direction="l", - }, - [0xA37D]={ - category="lo", - direction="l", - }, - [0xA37E]={ - category="lo", - direction="l", - }, - [0xA37F]={ - category="lo", - direction="l", - }, - [0xA380]={ - category="lo", - direction="l", - }, - [0xA381]={ - category="lo", - direction="l", - }, - [0xA382]={ - category="lo", - direction="l", - }, - [0xA383]={ - category="lo", - direction="l", - }, - [0xA384]={ - category="lo", - direction="l", - }, - [0xA385]={ - category="lo", - direction="l", - }, - [0xA386]={ - category="lo", - direction="l", - }, - [0xA387]={ - category="lo", - direction="l", - }, - [0xA388]={ - category="lo", - direction="l", - }, - [0xA389]={ - category="lo", - direction="l", - }, - [0xA38A]={ - category="lo", - direction="l", - }, - [0xA38B]={ - category="lo", - direction="l", - }, - [0xA38C]={ - category="lo", - direction="l", - }, - [0xA38D]={ - category="lo", - direction="l", - }, - [0xA38E]={ - category="lo", - direction="l", - }, - [0xA38F]={ - category="lo", - direction="l", - }, - [0xA390]={ - category="lo", - direction="l", - }, - [0xA391]={ - category="lo", - direction="l", - }, - [0xA392]={ - category="lo", - direction="l", - }, - [0xA393]={ - category="lo", - direction="l", - }, - [0xA394]={ - category="lo", - direction="l", - }, - [0xA395]={ - category="lo", - direction="l", - }, - [0xA396]={ - category="lo", - direction="l", - }, - [0xA397]={ - category="lo", - direction="l", - }, - [0xA398]={ - category="lo", - direction="l", - }, - [0xA399]={ - category="lo", - direction="l", - }, - [0xA39A]={ - category="lo", - direction="l", - }, - [0xA39B]={ - category="lo", - direction="l", - }, - [0xA39C]={ - category="lo", - direction="l", - }, - [0xA39D]={ - category="lo", - direction="l", - }, - [0xA39E]={ - category="lo", - direction="l", - }, - [0xA39F]={ - category="lo", - direction="l", - }, - [0xA3A0]={ - category="lo", - direction="l", - }, - [0xA3A1]={ - category="lo", - direction="l", - }, - [0xA3A2]={ - category="lo", - direction="l", - }, - [0xA3A3]={ - category="lo", - direction="l", - }, - [0xA3A4]={ - category="lo", - direction="l", - }, - [0xA3A5]={ - category="lo", - direction="l", - }, - [0xA3A6]={ - category="lo", - direction="l", - }, - [0xA3A7]={ - category="lo", - direction="l", - }, - [0xA3A8]={ - category="lo", - direction="l", - }, - [0xA3A9]={ - category="lo", - direction="l", - }, - [0xA3AA]={ - category="lo", - direction="l", - }, - [0xA3AB]={ - category="lo", - direction="l", - }, - [0xA3AC]={ - category="lo", - direction="l", - }, - [0xA3AD]={ - category="lo", - direction="l", - }, - [0xA3AE]={ - category="lo", - direction="l", - }, - [0xA3AF]={ - category="lo", - direction="l", - }, - [0xA3B0]={ - category="lo", - direction="l", - }, - [0xA3B1]={ - category="lo", - direction="l", - }, - [0xA3B2]={ - category="lo", - direction="l", - }, - [0xA3B3]={ - category="lo", - direction="l", - }, - [0xA3B4]={ - category="lo", - direction="l", - }, - [0xA3B5]={ - category="lo", - direction="l", - }, - [0xA3B6]={ - category="lo", - direction="l", - }, - [0xA3B7]={ - category="lo", - direction="l", - }, - [0xA3B8]={ - category="lo", - direction="l", - }, - [0xA3B9]={ - category="lo", - direction="l", - }, - [0xA3BA]={ - category="lo", - direction="l", - }, - [0xA3BB]={ - category="lo", - direction="l", - }, - [0xA3BC]={ - category="lo", - direction="l", - }, - [0xA3BD]={ - category="lo", - direction="l", - }, - [0xA3BE]={ - category="lo", - direction="l", - }, - [0xA3BF]={ - category="lo", - direction="l", - }, - [0xA3C0]={ - category="lo", - direction="l", - }, - [0xA3C1]={ - category="lo", - direction="l", - }, - [0xA3C2]={ - category="lo", - direction="l", - }, - [0xA3C3]={ - category="lo", - direction="l", - }, - [0xA3C4]={ - category="lo", - direction="l", - }, - [0xA3C5]={ - category="lo", - direction="l", - }, - [0xA3C6]={ - category="lo", - direction="l", - }, - [0xA3C7]={ - category="lo", - direction="l", - }, - [0xA3C8]={ - category="lo", - direction="l", - }, - [0xA3C9]={ - category="lo", - direction="l", - }, - [0xA3CA]={ - category="lo", - direction="l", - }, - [0xA3CB]={ - category="lo", - direction="l", - }, - [0xA3CC]={ - category="lo", - direction="l", - }, - [0xA3CD]={ - category="lo", - direction="l", - }, - [0xA3CE]={ - category="lo", - direction="l", - }, - [0xA3CF]={ - category="lo", - direction="l", - }, - [0xA3D0]={ - category="lo", - direction="l", - }, - [0xA3D1]={ - category="lo", - direction="l", - }, - [0xA3D2]={ - category="lo", - direction="l", - }, - [0xA3D3]={ - category="lo", - direction="l", - }, - [0xA3D4]={ - category="lo", - direction="l", - }, - [0xA3D5]={ - category="lo", - direction="l", - }, - [0xA3D6]={ - category="lo", - direction="l", - }, - [0xA3D7]={ - category="lo", - direction="l", - }, - [0xA3D8]={ - category="lo", - direction="l", - }, - [0xA3D9]={ - category="lo", - direction="l", - }, - [0xA3DA]={ - category="lo", - direction="l", - }, - [0xA3DB]={ - category="lo", - direction="l", - }, - [0xA3DC]={ - category="lo", - direction="l", - }, - [0xA3DD]={ - category="lo", - direction="l", - }, - [0xA3DE]={ - category="lo", - direction="l", - }, - [0xA3DF]={ - category="lo", - direction="l", - }, - [0xA3E0]={ - category="lo", - direction="l", - }, - [0xA3E1]={ - category="lo", - direction="l", - }, - [0xA3E2]={ - category="lo", - direction="l", - }, - [0xA3E3]={ - category="lo", - direction="l", - }, - [0xA3E4]={ - category="lo", - direction="l", - }, - [0xA3E5]={ - category="lo", - direction="l", - }, - [0xA3E6]={ - category="lo", - direction="l", - }, - [0xA3E7]={ - category="lo", - direction="l", - }, - [0xA3E8]={ - category="lo", - direction="l", - }, - [0xA3E9]={ - category="lo", - direction="l", - }, - [0xA3EA]={ - category="lo", - direction="l", - }, - [0xA3EB]={ - category="lo", - direction="l", - }, - [0xA3EC]={ - category="lo", - direction="l", - }, - [0xA3ED]={ - category="lo", - direction="l", - }, - [0xA3EE]={ - category="lo", - direction="l", - }, - [0xA3EF]={ - category="lo", - direction="l", - }, - [0xA3F0]={ - category="lo", - direction="l", - }, - [0xA3F1]={ - category="lo", - direction="l", - }, - [0xA3F2]={ - category="lo", - direction="l", - }, - [0xA3F3]={ - category="lo", - direction="l", - }, - [0xA3F4]={ - category="lo", - direction="l", - }, - [0xA3F5]={ - category="lo", - direction="l", - }, - [0xA3F6]={ - category="lo", - direction="l", - }, - [0xA3F7]={ - category="lo", - direction="l", - }, - [0xA3F8]={ - category="lo", - direction="l", - }, - [0xA3F9]={ - category="lo", - direction="l", - }, - [0xA3FA]={ - category="lo", - direction="l", - }, - [0xA3FB]={ - category="lo", - direction="l", - }, - [0xA3FC]={ - category="lo", - direction="l", - }, - [0xA3FD]={ - category="lo", - direction="l", - }, - [0xA3FE]={ - category="lo", - direction="l", - }, - [0xA3FF]={ - category="lo", - direction="l", - }, - [0xA400]={ - category="lo", - direction="l", - }, - [0xA401]={ - category="lo", - direction="l", - }, - [0xA402]={ - category="lo", - direction="l", - }, - [0xA403]={ - category="lo", - direction="l", - }, - [0xA404]={ - category="lo", - direction="l", - }, - [0xA405]={ - category="lo", - direction="l", - }, - [0xA406]={ - category="lo", - direction="l", - }, - [0xA407]={ - category="lo", - direction="l", - }, - [0xA408]={ - category="lo", - direction="l", - }, - [0xA409]={ - category="lo", - direction="l", - }, - [0xA40A]={ - category="lo", - direction="l", - }, - [0xA40B]={ - category="lo", - direction="l", - }, - [0xA40C]={ - category="lo", - direction="l", - }, - [0xA40D]={ - category="lo", - direction="l", - }, - [0xA40E]={ - category="lo", - direction="l", - }, - [0xA40F]={ - category="lo", - direction="l", - }, - [0xA410]={ - category="lo", - direction="l", - }, - [0xA411]={ - category="lo", - direction="l", - }, - [0xA412]={ - category="lo", - direction="l", - }, - [0xA413]={ - category="lo", - direction="l", - }, - [0xA414]={ - category="lo", - direction="l", - }, - [0xA415]={ - category="lo", - direction="l", - }, - [0xA416]={ - category="lo", - direction="l", - }, - [0xA417]={ - category="lo", - direction="l", - }, - [0xA418]={ - category="lo", - direction="l", - }, - [0xA419]={ - category="lo", - direction="l", - }, - [0xA41A]={ - category="lo", - direction="l", - }, - [0xA41B]={ - category="lo", - direction="l", - }, - [0xA41C]={ - category="lo", - direction="l", - }, - [0xA41D]={ - category="lo", - direction="l", - }, - [0xA41E]={ - category="lo", - direction="l", - }, - [0xA41F]={ - category="lo", - direction="l", - }, - [0xA420]={ - category="lo", - direction="l", - }, - [0xA421]={ - category="lo", - direction="l", - }, - [0xA422]={ - category="lo", - direction="l", - }, - [0xA423]={ - category="lo", - direction="l", - }, - [0xA424]={ - category="lo", - direction="l", - }, - [0xA425]={ - category="lo", - direction="l", - }, - [0xA426]={ - category="lo", - direction="l", - }, - [0xA427]={ - category="lo", - direction="l", - }, - [0xA428]={ - category="lo", - direction="l", - }, - [0xA429]={ - category="lo", - direction="l", - }, - [0xA42A]={ - category="lo", - direction="l", - }, - [0xA42B]={ - category="lo", - direction="l", - }, - [0xA42C]={ - category="lo", - direction="l", - }, - [0xA42D]={ - category="lo", - direction="l", - }, - [0xA42E]={ - category="lo", - direction="l", - }, - [0xA42F]={ - category="lo", - direction="l", - }, - [0xA430]={ - category="lo", - direction="l", - }, - [0xA431]={ - category="lo", - direction="l", - }, - [0xA432]={ - category="lo", - direction="l", - }, - [0xA433]={ - category="lo", - direction="l", - }, - [0xA434]={ - category="lo", - direction="l", - }, - [0xA435]={ - category="lo", - direction="l", - }, - [0xA436]={ - category="lo", - direction="l", - }, - [0xA437]={ - category="lo", - direction="l", - }, - [0xA438]={ - category="lo", - direction="l", - }, - [0xA439]={ - category="lo", - direction="l", - }, - [0xA43A]={ - category="lo", - direction="l", - }, - [0xA43B]={ - category="lo", - direction="l", - }, - [0xA43C]={ - category="lo", - direction="l", - }, - [0xA43D]={ - category="lo", - direction="l", - }, - [0xA43E]={ - category="lo", - direction="l", - }, - [0xA43F]={ - category="lo", - direction="l", - }, - [0xA440]={ - category="lo", - direction="l", - }, - [0xA441]={ - category="lo", - direction="l", - }, - [0xA442]={ - category="lo", - direction="l", - }, - [0xA443]={ - category="lo", - direction="l", - }, - [0xA444]={ - category="lo", - direction="l", - }, - [0xA445]={ - category="lo", - direction="l", - }, - [0xA446]={ - category="lo", - direction="l", - }, - [0xA447]={ - category="lo", - direction="l", - }, - [0xA448]={ - category="lo", - direction="l", - }, - [0xA449]={ - category="lo", - direction="l", - }, - [0xA44A]={ - category="lo", - direction="l", - }, - [0xA44B]={ - category="lo", - direction="l", - }, - [0xA44C]={ - category="lo", - direction="l", - }, - [0xA44D]={ - category="lo", - direction="l", - }, - [0xA44E]={ - category="lo", - direction="l", - }, - [0xA44F]={ - category="lo", - direction="l", - }, - [0xA450]={ - category="lo", - direction="l", - }, - [0xA451]={ - category="lo", - direction="l", - }, - [0xA452]={ - category="lo", - direction="l", - }, - [0xA453]={ - category="lo", - direction="l", - }, - [0xA454]={ - category="lo", - direction="l", - }, - [0xA455]={ - category="lo", - direction="l", - }, - [0xA456]={ - category="lo", - direction="l", - }, - [0xA457]={ - category="lo", - direction="l", - }, - [0xA458]={ - category="lo", - direction="l", - }, - [0xA459]={ - category="lo", - direction="l", - }, - [0xA45A]={ - category="lo", - direction="l", - }, - [0xA45B]={ - category="lo", - direction="l", - }, - [0xA45C]={ - category="lo", - direction="l", - }, - [0xA45D]={ - category="lo", - direction="l", - }, - [0xA45E]={ - category="lo", - direction="l", - }, - [0xA45F]={ - category="lo", - direction="l", - }, - [0xA460]={ - category="lo", - direction="l", - }, - [0xA461]={ - category="lo", - direction="l", - }, - [0xA462]={ - category="lo", - direction="l", - }, - [0xA463]={ - category="lo", - direction="l", - }, - [0xA464]={ - category="lo", - direction="l", - }, - [0xA465]={ - category="lo", - direction="l", - }, - [0xA466]={ - category="lo", - direction="l", - }, - [0xA467]={ - category="lo", - direction="l", - }, - [0xA468]={ - category="lo", - direction="l", - }, - [0xA469]={ - category="lo", - direction="l", - }, - [0xA46A]={ - category="lo", - direction="l", - }, - [0xA46B]={ - category="lo", - direction="l", - }, - [0xA46C]={ - category="lo", - direction="l", - }, - [0xA46D]={ - category="lo", - direction="l", - }, - [0xA46E]={ - category="lo", - direction="l", - }, - [0xA46F]={ - category="lo", - direction="l", - }, - [0xA470]={ - category="lo", - direction="l", - }, - [0xA471]={ - category="lo", - direction="l", - }, - [0xA472]={ - category="lo", - direction="l", - }, - [0xA473]={ - category="lo", - direction="l", - }, - [0xA474]={ - category="lo", - direction="l", - }, - [0xA475]={ - category="lo", - direction="l", - }, - [0xA476]={ - category="lo", - direction="l", - }, - [0xA477]={ - category="lo", - direction="l", - }, - [0xA478]={ - category="lo", - direction="l", - }, - [0xA479]={ - category="lo", - direction="l", - }, - [0xA47A]={ - category="lo", - direction="l", - }, - [0xA47B]={ - category="lo", - direction="l", - }, - [0xA47C]={ - category="lo", - direction="l", - }, - [0xA47D]={ - category="lo", - direction="l", - }, - [0xA47E]={ - category="lo", - direction="l", - }, - [0xA47F]={ - category="lo", - direction="l", - }, - [0xA480]={ - category="lo", - direction="l", - }, - [0xA481]={ - category="lo", - direction="l", - }, - [0xA482]={ - category="lo", - direction="l", - }, - [0xA483]={ - category="lo", - direction="l", - }, - [0xA484]={ - category="lo", - direction="l", - }, - [0xA485]={ - category="lo", - direction="l", - }, - [0xA486]={ - category="lo", - direction="l", - }, - [0xA487]={ - category="lo", - direction="l", - }, - [0xA488]={ - category="lo", - direction="l", - }, - [0xA489]={ - category="lo", - direction="l", - }, - [0xA48A]={ - category="lo", - direction="l", - }, - [0xA48B]={ - category="lo", - direction="l", - }, - [0xA48C]={ - category="lo", - direction="l", - }, - [0xA490]={ - category="so", - direction="on", - }, - [0xA491]={ - category="so", - direction="on", - }, - [0xA492]={ - category="so", - direction="on", - }, - [0xA493]={ - category="so", - direction="on", - }, - [0xA494]={ - category="so", - direction="on", - }, - [0xA495]={ - category="so", - direction="on", - }, - [0xA496]={ - category="so", - direction="on", - }, - [0xA497]={ - category="so", - direction="on", - }, - [0xA498]={ - category="so", - direction="on", - }, - [0xA499]={ - category="so", - direction="on", - }, - [0xA49A]={ - category="so", - direction="on", - }, - [0xA49B]={ - category="so", - direction="on", - }, - [0xA49C]={ - category="so", - direction="on", - }, - [0xA49D]={ - category="so", - direction="on", - }, - [0xA49E]={ - category="so", - direction="on", - }, - [0xA49F]={ - category="so", - direction="on", - }, - [0xA4A0]={ - category="so", - direction="on", - }, - [0xA4A1]={ - category="so", - direction="on", - }, - [0xA4A2]={ - category="so", - direction="on", - }, - [0xA4A3]={ - category="so", - direction="on", - }, - [0xA4A4]={ - category="so", - direction="on", - }, - [0xA4A5]={ - category="so", - direction="on", - }, - [0xA4A6]={ - category="so", - direction="on", - }, - [0xA4A7]={ - category="so", - direction="on", - }, - [0xA4A8]={ - category="so", - direction="on", - }, - [0xA4A9]={ - category="so", - direction="on", - }, - [0xA4AA]={ - category="so", - direction="on", - }, - [0xA4AB]={ - category="so", - direction="on", - }, - [0xA4AC]={ - category="so", - direction="on", - }, - [0xA4AD]={ - category="so", - direction="on", - }, - [0xA4AE]={ - category="so", - direction="on", - }, - [0xA4AF]={ - category="so", - direction="on", - }, - [0xA4B0]={ - category="so", - direction="on", - }, - [0xA4B1]={ - category="so", - direction="on", - }, - [0xA4B2]={ - category="so", - direction="on", - }, - [0xA4B3]={ - category="so", - direction="on", - }, - [0xA4B4]={ - category="so", - direction="on", - }, - [0xA4B5]={ - category="so", - direction="on", - }, - [0xA4B6]={ - category="so", - direction="on", - }, - [0xA4B7]={ - category="so", - direction="on", - }, - [0xA4B8]={ - category="so", - direction="on", - }, - [0xA4B9]={ - category="so", - direction="on", - }, - [0xA4BA]={ - category="so", - direction="on", - }, - [0xA4BB]={ - category="so", - direction="on", - }, - [0xA4BC]={ - category="so", - direction="on", - }, - [0xA4BD]={ - category="so", - direction="on", - }, - [0xA4BE]={ - category="so", - direction="on", - }, - [0xA4BF]={ - category="so", - direction="on", - }, - [0xA4C0]={ - category="so", - direction="on", - }, - [0xA4C1]={ - category="so", - direction="on", - }, - [0xA4C2]={ - category="so", - direction="on", - }, - [0xA4C3]={ - category="so", - direction="on", - }, - [0xA4C4]={ - category="so", - direction="on", - }, - [0xA4C5]={ - category="so", - direction="on", - }, - [0xA4C6]={ - category="so", - direction="on", - }, - [0xA4D0]={ - category="lo", - direction="l", - }, - [0xA4D1]={ - category="lo", - direction="l", - }, - [0xA4D2]={ - category="lo", - direction="l", - }, - [0xA4D3]={ - category="lo", - direction="l", - }, - [0xA4D4]={ - category="lo", - direction="l", - }, - [0xA4D5]={ - category="lo", - direction="l", - }, - [0xA4D6]={ - category="lo", - direction="l", - }, - [0xA4D7]={ - category="lo", - direction="l", - }, - [0xA4D8]={ - category="lo", - direction="l", - }, - [0xA4D9]={ - category="lo", - direction="l", - }, - [0xA4DA]={ - category="lo", - direction="l", - }, - [0xA4DB]={ - category="lo", - direction="l", - }, - [0xA4DC]={ - category="lo", - direction="l", - }, - [0xA4DD]={ - category="lo", - direction="l", - }, - [0xA4DE]={ - category="lo", - direction="l", - }, - [0xA4DF]={ - category="lo", - direction="l", - }, - [0xA4E0]={ - category="lo", - direction="l", - }, - [0xA4E1]={ - category="lo", - direction="l", - }, - [0xA4E2]={ - category="lo", - direction="l", - }, - [0xA4E3]={ - category="lo", - direction="l", - }, - [0xA4E4]={ - category="lo", - direction="l", - }, - [0xA4E5]={ - category="lo", - direction="l", - }, - [0xA4E6]={ - category="lo", - direction="l", - }, - [0xA4E7]={ - category="lo", - direction="l", - }, - [0xA4E8]={ - category="lo", - direction="l", - }, - [0xA4E9]={ - category="lo", - direction="l", - }, - [0xA4EA]={ - category="lo", - direction="l", - }, - [0xA4EB]={ - category="lo", - direction="l", - }, - [0xA4EC]={ - category="lo", - direction="l", - }, - [0xA4ED]={ - category="lo", - direction="l", - }, - [0xA4EE]={ - category="lo", - direction="l", - }, - [0xA4EF]={ - category="lo", - direction="l", - }, - [0xA4F0]={ - category="lo", - direction="l", - }, - [0xA4F1]={ - category="lo", - direction="l", - }, - [0xA4F2]={ - category="lo", - direction="l", - }, - [0xA4F3]={ - category="lo", - direction="l", - }, - [0xA4F4]={ - category="lo", - direction="l", - }, - [0xA4F5]={ - category="lo", - direction="l", - }, - [0xA4F6]={ - category="lo", - direction="l", - }, - [0xA4F7]={ - category="lo", - direction="l", - }, - [0xA4F8]={ - category="lm", - direction="l", - }, - [0xA4F9]={ - category="lm", - direction="l", - }, - [0xA4FA]={ - category="lm", - direction="l", - }, - [0xA4FB]={ - category="lm", - direction="l", - }, - [0xA4FC]={ - category="lm", - direction="l", - }, - [0xA4FD]={ - category="lm", - direction="l", - }, - [0xA4FE]={ - category="po", - direction="l", - }, - [0xA4FF]={ - category="po", - direction="l", - }, - [0xA500]={ - category="lo", - direction="l", - }, - [0xA501]={ - category="lo", - direction="l", - }, - [0xA502]={ - category="lo", - direction="l", - }, - [0xA503]={ - category="lo", - direction="l", - }, - [0xA504]={ - category="lo", - direction="l", - }, - [0xA505]={ - category="lo", - direction="l", - }, - [0xA506]={ - category="lo", - direction="l", - }, - [0xA507]={ - category="lo", - direction="l", - }, - [0xA508]={ - category="lo", - direction="l", - }, - [0xA509]={ - category="lo", - direction="l", - }, - [0xA50A]={ - category="lo", - direction="l", - }, - [0xA50B]={ - category="lo", - direction="l", - }, - [0xA50C]={ - category="lo", - direction="l", - }, - [0xA50D]={ - category="lo", - direction="l", - }, - [0xA50E]={ - category="lo", - direction="l", - }, - [0xA50F]={ - category="lo", - direction="l", - }, - [0xA510]={ - category="lo", - direction="l", - }, - [0xA511]={ - category="lo", - direction="l", - }, - [0xA512]={ - category="lo", - direction="l", - }, - [0xA513]={ - category="lo", - direction="l", - }, - [0xA514]={ - category="lo", - direction="l", - }, - [0xA515]={ - category="lo", - direction="l", - }, - [0xA516]={ - category="lo", - direction="l", - }, - [0xA517]={ - category="lo", - direction="l", - }, - [0xA518]={ - category="lo", - direction="l", - }, - [0xA519]={ - category="lo", - direction="l", - }, - [0xA51A]={ - category="lo", - direction="l", - }, - [0xA51B]={ - category="lo", - direction="l", - }, - [0xA51C]={ - category="lo", - direction="l", - }, - [0xA51D]={ - category="lo", - direction="l", - }, - [0xA51E]={ - category="lo", - direction="l", - }, - [0xA51F]={ - category="lo", - direction="l", - }, - [0xA520]={ - category="lo", - direction="l", - }, - [0xA521]={ - category="lo", - direction="l", - }, - [0xA522]={ - category="lo", - direction="l", - }, - [0xA523]={ - category="lo", - direction="l", - }, - [0xA524]={ - category="lo", - direction="l", - }, - [0xA525]={ - category="lo", - direction="l", - }, - [0xA526]={ - category="lo", - direction="l", - }, - [0xA527]={ - category="lo", - direction="l", - }, - [0xA528]={ - category="lo", - direction="l", - }, - [0xA529]={ - category="lo", - direction="l", - }, - [0xA52A]={ - category="lo", - direction="l", - }, - [0xA52B]={ - category="lo", - direction="l", - }, - [0xA52C]={ - category="lo", - direction="l", - }, - [0xA52D]={ - category="lo", - direction="l", - }, - [0xA52E]={ - category="lo", - direction="l", - }, - [0xA52F]={ - category="lo", - direction="l", - }, - [0xA530]={ - category="lo", - direction="l", - }, - [0xA531]={ - category="lo", - direction="l", - }, - [0xA532]={ - category="lo", - direction="l", - }, - [0xA533]={ - category="lo", - direction="l", - }, - [0xA534]={ - category="lo", - direction="l", - }, - [0xA535]={ - category="lo", - direction="l", - }, - [0xA536]={ - category="lo", - direction="l", - }, - [0xA537]={ - category="lo", - direction="l", - }, - [0xA538]={ - category="lo", - direction="l", - }, - [0xA539]={ - category="lo", - direction="l", - }, - [0xA53A]={ - category="lo", - direction="l", - }, - [0xA53B]={ - category="lo", - direction="l", - }, - [0xA53C]={ - category="lo", - direction="l", - }, - [0xA53D]={ - category="lo", - direction="l", - }, - [0xA53E]={ - category="lo", - direction="l", - }, - [0xA53F]={ - category="lo", - direction="l", - }, - [0xA540]={ - category="lo", - direction="l", - }, - [0xA541]={ - category="lo", - direction="l", - }, - [0xA542]={ - category="lo", - direction="l", - }, - [0xA543]={ - category="lo", - direction="l", - }, - [0xA544]={ - category="lo", - direction="l", - }, - [0xA545]={ - category="lo", - direction="l", - }, - [0xA546]={ - category="lo", - direction="l", - }, - [0xA547]={ - category="lo", - direction="l", - }, - [0xA548]={ - category="lo", - direction="l", - }, - [0xA549]={ - category="lo", - direction="l", - }, - [0xA54A]={ - category="lo", - direction="l", - }, - [0xA54B]={ - category="lo", - direction="l", - }, - [0xA54C]={ - category="lo", - direction="l", - }, - [0xA54D]={ - category="lo", - direction="l", - }, - [0xA54E]={ - category="lo", - direction="l", - }, - [0xA54F]={ - category="lo", - direction="l", - }, - [0xA550]={ - category="lo", - direction="l", - }, - [0xA551]={ - category="lo", - direction="l", - }, - [0xA552]={ - category="lo", - direction="l", - }, - [0xA553]={ - category="lo", - direction="l", - }, - [0xA554]={ - category="lo", - direction="l", - }, - [0xA555]={ - category="lo", - direction="l", - }, - [0xA556]={ - category="lo", - direction="l", - }, - [0xA557]={ - category="lo", - direction="l", - }, - [0xA558]={ - category="lo", - direction="l", - }, - [0xA559]={ - category="lo", - direction="l", - }, - [0xA55A]={ - category="lo", - direction="l", - }, - [0xA55B]={ - category="lo", - direction="l", - }, - [0xA55C]={ - category="lo", - direction="l", - }, - [0xA55D]={ - category="lo", - direction="l", - }, - [0xA55E]={ - category="lo", - direction="l", - }, - [0xA55F]={ - category="lo", - direction="l", - }, - [0xA560]={ - category="lo", - direction="l", - }, - [0xA561]={ - category="lo", - direction="l", - }, - [0xA562]={ - category="lo", - direction="l", - }, - [0xA563]={ - category="lo", - direction="l", - }, - [0xA564]={ - category="lo", - direction="l", - }, - [0xA565]={ - category="lo", - direction="l", - }, - [0xA566]={ - category="lo", - direction="l", - }, - [0xA567]={ - category="lo", - direction="l", - }, - [0xA568]={ - category="lo", - direction="l", - }, - [0xA569]={ - category="lo", - direction="l", - }, - [0xA56A]={ - category="lo", - direction="l", - }, - [0xA56B]={ - category="lo", - direction="l", - }, - [0xA56C]={ - category="lo", - direction="l", - }, - [0xA56D]={ - category="lo", - direction="l", - }, - [0xA56E]={ - category="lo", - direction="l", - }, - [0xA56F]={ - category="lo", - direction="l", - }, - [0xA570]={ - category="lo", - direction="l", - }, - [0xA571]={ - category="lo", - direction="l", - }, - [0xA572]={ - category="lo", - direction="l", - }, - [0xA573]={ - category="lo", - direction="l", - }, - [0xA574]={ - category="lo", - direction="l", - }, - [0xA575]={ - category="lo", - direction="l", - }, - [0xA576]={ - category="lo", - direction="l", - }, - [0xA577]={ - category="lo", - direction="l", - }, - [0xA578]={ - category="lo", - direction="l", - }, - [0xA579]={ - category="lo", - direction="l", - }, - [0xA57A]={ - category="lo", - direction="l", - }, - [0xA57B]={ - category="lo", - direction="l", - }, - [0xA57C]={ - category="lo", - direction="l", - }, - [0xA57D]={ - category="lo", - direction="l", - }, - [0xA57E]={ - category="lo", - direction="l", - }, - [0xA57F]={ - category="lo", - direction="l", - }, - [0xA580]={ - category="lo", - direction="l", - }, - [0xA581]={ - category="lo", - direction="l", - }, - [0xA582]={ - category="lo", - direction="l", - }, - [0xA583]={ - category="lo", - direction="l", - }, - [0xA584]={ - category="lo", - direction="l", - }, - [0xA585]={ - category="lo", - direction="l", - }, - [0xA586]={ - category="lo", - direction="l", - }, - [0xA587]={ - category="lo", - direction="l", - }, - [0xA588]={ - category="lo", - direction="l", - }, - [0xA589]={ - category="lo", - direction="l", - }, - [0xA58A]={ - category="lo", - direction="l", - }, - [0xA58B]={ - category="lo", - direction="l", - }, - [0xA58C]={ - category="lo", - direction="l", - }, - [0xA58D]={ - category="lo", - direction="l", - }, - [0xA58E]={ - category="lo", - direction="l", - }, - [0xA58F]={ - category="lo", - direction="l", - }, - [0xA590]={ - category="lo", - direction="l", - }, - [0xA591]={ - category="lo", - direction="l", - }, - [0xA592]={ - category="lo", - direction="l", - }, - [0xA593]={ - category="lo", - direction="l", - }, - [0xA594]={ - category="lo", - direction="l", - }, - [0xA595]={ - category="lo", - direction="l", - }, - [0xA596]={ - category="lo", - direction="l", - }, - [0xA597]={ - category="lo", - direction="l", - }, - [0xA598]={ - category="lo", - direction="l", - }, - [0xA599]={ - category="lo", - direction="l", - }, - [0xA59A]={ - category="lo", - direction="l", - }, - [0xA59B]={ - category="lo", - direction="l", - }, - [0xA59C]={ - category="lo", - direction="l", - }, - [0xA59D]={ - category="lo", - direction="l", - }, - [0xA59E]={ - category="lo", - direction="l", - }, - [0xA59F]={ - category="lo", - direction="l", - }, - [0xA5A0]={ - category="lo", - direction="l", - }, - [0xA5A1]={ - category="lo", - direction="l", - }, - [0xA5A2]={ - category="lo", - direction="l", - }, - [0xA5A3]={ - category="lo", - direction="l", - }, - [0xA5A4]={ - category="lo", - direction="l", - }, - [0xA5A5]={ - category="lo", - direction="l", - }, - [0xA5A6]={ - category="lo", - direction="l", - }, - [0xA5A7]={ - category="lo", - direction="l", - }, - [0xA5A8]={ - category="lo", - direction="l", - }, - [0xA5A9]={ - category="lo", - direction="l", - }, - [0xA5AA]={ - category="lo", - direction="l", - }, - [0xA5AB]={ - category="lo", - direction="l", - }, - [0xA5AC]={ - category="lo", - direction="l", - }, - [0xA5AD]={ - category="lo", - direction="l", - }, - [0xA5AE]={ - category="lo", - direction="l", - }, - [0xA5AF]={ - category="lo", - direction="l", - }, - [0xA5B0]={ - category="lo", - direction="l", - }, - [0xA5B1]={ - category="lo", - direction="l", - }, - [0xA5B2]={ - category="lo", - direction="l", - }, - [0xA5B3]={ - category="lo", - direction="l", - }, - [0xA5B4]={ - category="lo", - direction="l", - }, - [0xA5B5]={ - category="lo", - direction="l", - }, - [0xA5B6]={ - category="lo", - direction="l", - }, - [0xA5B7]={ - category="lo", - direction="l", - }, - [0xA5B8]={ - category="lo", - direction="l", - }, - [0xA5B9]={ - category="lo", - direction="l", - }, - [0xA5BA]={ - category="lo", - direction="l", - }, - [0xA5BB]={ - category="lo", - direction="l", - }, - [0xA5BC]={ - category="lo", - direction="l", - }, - [0xA5BD]={ - category="lo", - direction="l", - }, - [0xA5BE]={ - category="lo", - direction="l", - }, - [0xA5BF]={ - category="lo", - direction="l", - }, - [0xA5C0]={ - category="lo", - direction="l", - }, - [0xA5C1]={ - category="lo", - direction="l", - }, - [0xA5C2]={ - category="lo", - direction="l", - }, - [0xA5C3]={ - category="lo", - direction="l", - }, - [0xA5C4]={ - category="lo", - direction="l", - }, - [0xA5C5]={ - category="lo", - direction="l", - }, - [0xA5C6]={ - category="lo", - direction="l", - }, - [0xA5C7]={ - category="lo", - direction="l", - }, - [0xA5C8]={ - category="lo", - direction="l", - }, - [0xA5C9]={ - category="lo", - direction="l", - }, - [0xA5CA]={ - category="lo", - direction="l", - }, - [0xA5CB]={ - category="lo", - direction="l", - }, - [0xA5CC]={ - category="lo", - direction="l", - }, - [0xA5CD]={ - category="lo", - direction="l", - }, - [0xA5CE]={ - category="lo", - direction="l", - }, - [0xA5CF]={ - category="lo", - direction="l", - }, - [0xA5D0]={ - category="lo", - direction="l", - }, - [0xA5D1]={ - category="lo", - direction="l", - }, - [0xA5D2]={ - category="lo", - direction="l", - }, - [0xA5D3]={ - category="lo", - direction="l", - }, - [0xA5D4]={ - category="lo", - direction="l", - }, - [0xA5D5]={ - category="lo", - direction="l", - }, - [0xA5D6]={ - category="lo", - direction="l", - }, - [0xA5D7]={ - category="lo", - direction="l", - }, - [0xA5D8]={ - category="lo", - direction="l", - }, - [0xA5D9]={ - category="lo", - direction="l", - }, - [0xA5DA]={ - category="lo", - direction="l", - }, - [0xA5DB]={ - category="lo", - direction="l", - }, - [0xA5DC]={ - category="lo", - direction="l", - }, - [0xA5DD]={ - category="lo", - direction="l", - }, - [0xA5DE]={ - category="lo", - direction="l", - }, - [0xA5DF]={ - category="lo", - direction="l", - }, - [0xA5E0]={ - category="lo", - direction="l", - }, - [0xA5E1]={ - category="lo", - direction="l", - }, - [0xA5E2]={ - category="lo", - direction="l", - }, - [0xA5E3]={ - category="lo", - direction="l", - }, - [0xA5E4]={ - category="lo", - direction="l", - }, - [0xA5E5]={ - category="lo", - direction="l", - }, - [0xA5E6]={ - category="lo", - direction="l", - }, - [0xA5E7]={ - category="lo", - direction="l", - }, - [0xA5E8]={ - category="lo", - direction="l", - }, - [0xA5E9]={ - category="lo", - direction="l", - }, - [0xA5EA]={ - category="lo", - direction="l", - }, - [0xA5EB]={ - category="lo", - direction="l", - }, - [0xA5EC]={ - category="lo", - direction="l", - }, - [0xA5ED]={ - category="lo", - direction="l", - }, - [0xA5EE]={ - category="lo", - direction="l", - }, - [0xA5EF]={ - category="lo", - direction="l", - }, - [0xA5F0]={ - category="lo", - direction="l", - }, - [0xA5F1]={ - category="lo", - direction="l", - }, - [0xA5F2]={ - category="lo", - direction="l", - }, - [0xA5F3]={ - category="lo", - direction="l", - }, - [0xA5F4]={ - category="lo", - direction="l", - }, - [0xA5F5]={ - category="lo", - direction="l", - }, - [0xA5F6]={ - category="lo", - direction="l", - }, - [0xA5F7]={ - category="lo", - direction="l", - }, - [0xA5F8]={ - category="lo", - direction="l", - }, - [0xA5F9]={ - category="lo", - direction="l", - }, - [0xA5FA]={ - category="lo", - direction="l", - }, - [0xA5FB]={ - category="lo", - direction="l", - }, - [0xA5FC]={ - category="lo", - direction="l", - }, - [0xA5FD]={ - category="lo", - direction="l", - }, - [0xA5FE]={ - category="lo", - direction="l", - }, - [0xA5FF]={ - category="lo", - direction="l", - }, - [0xA600]={ - category="lo", - direction="l", - }, - [0xA601]={ - category="lo", - direction="l", - }, - [0xA602]={ - category="lo", - direction="l", - }, - [0xA603]={ - category="lo", - direction="l", - }, - [0xA604]={ - category="lo", - direction="l", - }, - [0xA605]={ - category="lo", - direction="l", - }, - [0xA606]={ - category="lo", - direction="l", - }, - [0xA607]={ - category="lo", - direction="l", - }, - [0xA608]={ - category="lo", - direction="l", - }, - [0xA609]={ - category="lo", - direction="l", - }, - [0xA60A]={ - category="lo", - direction="l", - }, - [0xA60B]={ - category="lo", - direction="l", - }, - [0xA60C]={ - category="lm", - direction="l", - }, - [0xA60D]={ - category="po", - direction="on", - }, - [0xA60E]={ - category="po", - direction="on", - }, - [0xA60F]={ - category="po", - direction="on", - }, - [0xA610]={ - category="lo", - direction="l", - }, - [0xA611]={ - category="lo", - direction="l", - }, - [0xA612]={ - category="lo", - direction="l", - }, - [0xA613]={ - category="lo", - direction="l", - }, - [0xA614]={ - category="lo", - direction="l", - }, - [0xA615]={ - category="lo", - direction="l", - }, - [0xA616]={ - category="lo", - direction="l", - }, - [0xA617]={ - category="lo", - direction="l", - }, - [0xA618]={ - category="lo", - direction="l", - }, - [0xA619]={ - category="lo", - direction="l", - }, - [0xA61A]={ - category="lo", - direction="l", - }, - [0xA61B]={ - category="lo", - direction="l", - }, - [0xA61C]={ - category="lo", - direction="l", - }, - [0xA61D]={ - category="lo", - direction="l", - }, - [0xA61E]={ - category="lo", - direction="l", - }, - [0xA61F]={ - category="lo", - direction="l", - }, - [0xA620]={ - category="nd", - direction="l", - }, - [0xA621]={ - category="nd", - direction="l", - }, - [0xA622]={ - category="nd", - direction="l", - }, - [0xA623]={ - category="nd", - direction="l", - }, - [0xA624]={ - category="nd", - direction="l", - }, - [0xA625]={ - category="nd", - direction="l", - }, - [0xA626]={ - category="nd", - direction="l", - }, - [0xA627]={ - category="nd", - direction="l", - }, - [0xA628]={ - category="nd", - direction="l", - }, - [0xA629]={ - category="nd", - direction="l", - }, - [0xA62A]={ - category="lo", - direction="l", - }, - [0xA62B]={ - category="lo", - direction="l", - }, - [0xA640]={ - category="lu", - direction="l", - }, - [0xA641]={ - category="ll", - direction="l", - }, - [0xA642]={ - category="lu", - direction="l", - }, - [0xA643]={ - category="ll", - direction="l", - }, - [0xA644]={ - category="lu", - direction="l", - }, - [0xA645]={ - category="ll", - direction="l", - }, - [0xA646]={ - category="lu", - direction="l", - }, - [0xA647]={ - category="ll", - direction="l", - }, - [0xA648]={ - category="lu", - direction="l", - }, - [0xA649]={ - category="ll", - direction="l", - }, - [0xA64A]={ - category="lu", - direction="l", - }, - [0xA64B]={ - category="ll", - direction="l", - }, - [0xA64C]={ - category="lu", - direction="l", - }, - [0xA64D]={ - category="ll", - direction="l", - }, - [0xA64E]={ - category="lu", - direction="l", - }, - [0xA64F]={ - category="ll", - direction="l", - }, - [0xA650]={ - category="lu", - direction="l", - }, - [0xA651]={ - category="ll", - direction="l", - }, - [0xA652]={ - category="lu", - direction="l", - }, - [0xA653]={ - category="ll", - direction="l", - }, - [0xA654]={ - category="lu", - direction="l", - }, - [0xA655]={ - category="ll", - direction="l", - }, - [0xA656]={ - category="lu", - direction="l", - }, - [0xA657]={ - category="ll", - direction="l", - }, - [0xA658]={ - category="lu", - direction="l", - }, - [0xA659]={ - category="ll", - direction="l", - }, - [0xA65A]={ - category="lu", - direction="l", - }, - [0xA65B]={ - category="ll", - direction="l", - }, - [0xA65C]={ - category="lu", - direction="l", - }, - [0xA65D]={ - category="ll", - direction="l", - }, - [0xA65E]={ - category="lu", - direction="l", - }, - [0xA65F]={ - category="ll", - direction="l", - }, - [0xA660]={ - category="lu", - direction="l", - }, - [0xA661]={ - category="ll", - direction="l", - }, - [0xA662]={ - category="lu", - direction="l", - }, - [0xA663]={ - category="ll", - direction="l", - }, - [0xA664]={ - category="lu", - direction="l", - }, - [0xA665]={ - category="ll", - direction="l", - }, - [0xA666]={ - category="lu", - direction="l", - }, - [0xA667]={ - category="ll", - direction="l", - }, - [0xA668]={ - category="lu", - direction="l", - }, - [0xA669]={ - category="ll", - direction="l", - }, - [0xA66A]={ - category="lu", - direction="l", - }, - [0xA66B]={ - category="ll", - direction="l", - }, - [0xA66C]={ - category="lu", - direction="l", - }, - [0xA66D]={ - category="ll", - direction="l", - }, - [0xA66E]={ - category="lo", - direction="l", - }, - [0xA66F]={ - category="mn", - direction="nsm", - }, - [0xA670]={ - category="me", - direction="nsm", - }, - [0xA671]={ - category="me", - direction="nsm", - }, - [0xA672]={ - category="me", - direction="nsm", - }, - [0xA673]={ - category="po", - direction="on", - }, - [0xA674]={ - category="mn", - direction="nsm", - }, - [0xA675]={ - category="mn", - direction="nsm", - }, - [0xA676]={ - category="mn", - direction="nsm", - }, - [0xA677]={ - category="mn", - direction="nsm", - }, - [0xA678]={ - category="mn", - direction="nsm", - }, - [0xA679]={ - category="mn", - direction="nsm", - }, - [0xA67A]={ - category="mn", - direction="nsm", - }, - [0xA67B]={ - category="mn", - direction="nsm", - }, - [0xA67C]={ - category="mn", - direction="nsm", - }, - [0xA67D]={ - category="mn", - direction="nsm", - }, - [0xA67E]={ - category="po", - direction="on", - }, - [0xA67F]={ - category="lm", - direction="on", - }, - [0xA680]={ - category="lu", - direction="l", - }, - [0xA681]={ - category="ll", - direction="l", - }, - [0xA682]={ - category="lu", - direction="l", - }, - [0xA683]={ - category="ll", - direction="l", - }, - [0xA684]={ - category="lu", - direction="l", - }, - [0xA685]={ - category="ll", - direction="l", - }, - [0xA686]={ - category="lu", - direction="l", - }, - [0xA687]={ - category="ll", - direction="l", - }, - [0xA688]={ - category="lu", - direction="l", - }, - [0xA689]={ - category="ll", - direction="l", - }, - [0xA68A]={ - category="lu", - direction="l", - }, - [0xA68B]={ - category="ll", - direction="l", - }, - [0xA68C]={ - category="lu", - direction="l", - }, - [0xA68D]={ - category="ll", - direction="l", - }, - [0xA68E]={ - category="lu", - direction="l", - }, - [0xA68F]={ - category="ll", - direction="l", - }, - [0xA690]={ - category="lu", - direction="l", - }, - [0xA691]={ - category="ll", - direction="l", - }, - [0xA692]={ - category="lu", - direction="l", - }, - [0xA693]={ - category="ll", - direction="l", - }, - [0xA694]={ - category="lu", - direction="l", - }, - [0xA695]={ - category="ll", - direction="l", - }, - [0xA696]={ - category="lu", - direction="l", - }, - [0xA697]={ - category="ll", - direction="l", - }, - [0xA698]={ - category="lu", - direction="l", - }, - [0xA699]={ - category="ll", - direction="l", - }, - [0xA69A]={ - category="lu", - direction="l", - }, - [0xA69B]={ - category="ll", - direction="l", - }, - [0xA69C]={ - category="lm", - direction="l", - }, - [0xA69D]={ - category="lm", - direction="l", - }, - [0xA69E]={ - category="mn", - direction="nsm", - }, - [0xA69F]={ - category="mn", - direction="nsm", - }, - [0xA6A0]={ - category="lo", - direction="l", - }, - [0xA6A1]={ - category="lo", - direction="l", - }, - [0xA6A2]={ - category="lo", - direction="l", - }, - [0xA6A3]={ - category="lo", - direction="l", - }, - [0xA6A4]={ - category="lo", - direction="l", - }, - [0xA6A5]={ - category="lo", - direction="l", - }, - [0xA6A6]={ - category="lo", - direction="l", - }, - [0xA6A7]={ - category="lo", - direction="l", - }, - [0xA6A8]={ - category="lo", - direction="l", - }, - [0xA6A9]={ - category="lo", - direction="l", - }, - [0xA6AA]={ - category="lo", - direction="l", - }, - [0xA6AB]={ - category="lo", - direction="l", - }, - [0xA6AC]={ - category="lo", - direction="l", - }, - [0xA6AD]={ - category="lo", - direction="l", - }, - [0xA6AE]={ - category="lo", - direction="l", - }, - [0xA6AF]={ - category="lo", - direction="l", - }, - [0xA6B0]={ - category="lo", - direction="l", - }, - [0xA6B1]={ - category="lo", - direction="l", - }, - [0xA6B2]={ - category="lo", - direction="l", - }, - [0xA6B3]={ - category="lo", - direction="l", - }, - [0xA6B4]={ - category="lo", - direction="l", - }, - [0xA6B5]={ - category="lo", - direction="l", - }, - [0xA6B6]={ - category="lo", - direction="l", - }, - [0xA6B7]={ - category="lo", - direction="l", - }, - [0xA6B8]={ - category="lo", - direction="l", - }, - [0xA6B9]={ - category="lo", - direction="l", - }, - [0xA6BA]={ - category="lo", - direction="l", - }, - [0xA6BB]={ - category="lo", - direction="l", - }, - [0xA6BC]={ - category="lo", - direction="l", - }, - [0xA6BD]={ - category="lo", - direction="l", - }, - [0xA6BE]={ - category="lo", - direction="l", - }, - [0xA6BF]={ - category="lo", - direction="l", - }, - [0xA6C0]={ - category="lo", - direction="l", - }, - [0xA6C1]={ - category="lo", - direction="l", - }, - [0xA6C2]={ - category="lo", - direction="l", - }, - [0xA6C3]={ - category="lo", - direction="l", - }, - [0xA6C4]={ - category="lo", - direction="l", - }, - [0xA6C5]={ - category="lo", - direction="l", - }, - [0xA6C6]={ - category="lo", - direction="l", - }, - [0xA6C7]={ - category="lo", - direction="l", - }, - [0xA6C8]={ - category="lo", - direction="l", - }, - [0xA6C9]={ - category="lo", - direction="l", - }, - [0xA6CA]={ - category="lo", - direction="l", - }, - [0xA6CB]={ - category="lo", - direction="l", - }, - [0xA6CC]={ - category="lo", - direction="l", - }, - [0xA6CD]={ - category="lo", - direction="l", - }, - [0xA6CE]={ - category="lo", - direction="l", - }, - [0xA6CF]={ - category="lo", - direction="l", - }, - [0xA6D0]={ - category="lo", - direction="l", - }, - [0xA6D1]={ - category="lo", - direction="l", - }, - [0xA6D2]={ - category="lo", - direction="l", - }, - [0xA6D3]={ - category="lo", - direction="l", - }, - [0xA6D4]={ - category="lo", - direction="l", - }, - [0xA6D5]={ - category="lo", - direction="l", - }, - [0xA6D6]={ - category="lo", - direction="l", - }, - [0xA6D7]={ - category="lo", - direction="l", - }, - [0xA6D8]={ - category="lo", - direction="l", - }, - [0xA6D9]={ - category="lo", - direction="l", - }, - [0xA6DA]={ - category="lo", - direction="l", - }, - [0xA6DB]={ - category="lo", - direction="l", - }, - [0xA6DC]={ - category="lo", - direction="l", - }, - [0xA6DD]={ - category="lo", - direction="l", - }, - [0xA6DE]={ - category="lo", - direction="l", - }, - [0xA6DF]={ - category="lo", - direction="l", - }, - [0xA6E0]={ - category="lo", - direction="l", - }, - [0xA6E1]={ - category="lo", - direction="l", - }, - [0xA6E2]={ - category="lo", - direction="l", - }, - [0xA6E3]={ - category="lo", - direction="l", - }, - [0xA6E4]={ - category="lo", - direction="l", - }, - [0xA6E5]={ - category="lo", - direction="l", - }, - [0xA6E6]={ - category="nl", - direction="l", - }, - [0xA6E7]={ - category="nl", - direction="l", - }, - [0xA6E8]={ - category="nl", - direction="l", - }, - [0xA6E9]={ - category="nl", - direction="l", - }, - [0xA6EA]={ - category="nl", - direction="l", - }, - [0xA6EB]={ - category="nl", - direction="l", - }, - [0xA6EC]={ - category="nl", - direction="l", - }, - [0xA6ED]={ - category="nl", - direction="l", - }, - [0xA6EE]={ - category="nl", - direction="l", - }, - [0xA6EF]={ - category="nl", - direction="l", - }, - [0xA6F0]={ - category="mn", - direction="nsm", - }, - [0xA6F1]={ - category="mn", - direction="nsm", - }, - [0xA6F2]={ - category="po", - direction="l", - }, - [0xA6F3]={ - category="po", - direction="l", - }, - [0xA6F4]={ - category="po", - direction="l", - }, - [0xA6F5]={ - category="po", - direction="l", - }, - [0xA6F6]={ - category="po", - direction="l", - }, - [0xA6F7]={ - category="po", - direction="l", - }, - [0xA700]={ - category="sk", - direction="on", - }, - [0xA701]={ - category="sk", - direction="on", - }, - [0xA702]={ - category="sk", - direction="on", - }, - [0xA703]={ - category="sk", - direction="on", - }, - [0xA704]={ - category="sk", - direction="on", - }, - [0xA705]={ - category="sk", - direction="on", - }, - [0xA706]={ - category="sk", - direction="on", - }, - [0xA707]={ - category="sk", - direction="on", - }, - [0xA708]={ - category="sk", - direction="on", - }, - [0xA709]={ - category="sk", - direction="on", - }, - [0xA70A]={ - category="sk", - direction="on", - }, - [0xA70B]={ - category="sk", - direction="on", - }, - [0xA70C]={ - category="sk", - direction="on", - }, - [0xA70D]={ - category="sk", - direction="on", - }, - [0xA70E]={ - category="sk", - direction="on", - }, - [0xA70F]={ - category="sk", - direction="on", - }, - [0xA710]={ - category="sk", - direction="on", - }, - [0xA711]={ - category="sk", - direction="on", - }, - [0xA712]={ - category="sk", - direction="on", - }, - [0xA713]={ - category="sk", - direction="on", - }, - [0xA714]={ - category="sk", - direction="on", - }, - [0xA715]={ - category="sk", - direction="on", - }, - [0xA716]={ - category="sk", - direction="on", - }, - [0xA717]={ - category="lm", - direction="on", - }, - [0xA718]={ - category="lm", - direction="on", - }, - [0xA719]={ - category="lm", - direction="on", - }, - [0xA71A]={ - category="lm", - direction="on", - }, - [0xA71B]={ - category="lm", - direction="on", - }, - [0xA71C]={ - category="lm", - direction="on", - }, - [0xA71D]={ - category="lm", - direction="on", - }, - [0xA71E]={ - category="lm", - direction="on", - }, - [0xA71F]={ - category="lm", - direction="on", - }, - [0xA720]={ - category="sk", - direction="on", - }, - [0xA721]={ - category="sk", - direction="on", - }, - [0xA722]={ - category="lu", - direction="l", - }, - [0xA723]={ - category="ll", - direction="l", - }, - [0xA724]={ - category="lu", - direction="l", - }, - [0xA725]={ - category="ll", - direction="l", - }, - [0xA726]={ - category="lu", - direction="l", - }, - [0xA727]={ - category="ll", - direction="l", - }, - [0xA728]={ - category="lu", - direction="l", - }, - [0xA729]={ - category="ll", - direction="l", - }, - [0xA72A]={ - category="lu", - direction="l", - }, - [0xA72B]={ - category="ll", - direction="l", - }, - [0xA72C]={ - category="lu", - direction="l", - }, - [0xA72D]={ - category="ll", - direction="l", - }, - [0xA72E]={ - category="lu", - direction="l", - }, - [0xA72F]={ - category="ll", - direction="l", - }, - [0xA730]={ - category="ll", - direction="l", - }, - [0xA731]={ - category="ll", - direction="l", - }, - [0xA732]={ - category="lu", - direction="l", - }, - [0xA733]={ - category="ll", - direction="l", - }, - [0xA734]={ - category="lu", - direction="l", - }, - [0xA735]={ - category="ll", - direction="l", - }, - [0xA736]={ - category="lu", - direction="l", - }, - [0xA737]={ - category="ll", - direction="l", - }, - [0xA738]={ - category="lu", - direction="l", - }, - [0xA739]={ - category="ll", - direction="l", - }, - [0xA73A]={ - category="lu", - direction="l", - }, - [0xA73B]={ - category="ll", - direction="l", - }, - [0xA73C]={ - category="lu", - direction="l", - }, - [0xA73D]={ - category="ll", - direction="l", - }, - [0xA73E]={ - category="lu", - direction="l", - }, - [0xA73F]={ - category="ll", - direction="l", - }, - [0xA740]={ - category="lu", - direction="l", - }, - [0xA741]={ - category="ll", - direction="l", - }, - [0xA742]={ - category="lu", - direction="l", - }, - [0xA743]={ - category="ll", - direction="l", - }, - [0xA744]={ - category="lu", - direction="l", - }, - [0xA745]={ - category="ll", - direction="l", - }, - [0xA746]={ - category="lu", - direction="l", - }, - [0xA747]={ - category="ll", - direction="l", - }, - [0xA748]={ - category="lu", - direction="l", - }, - [0xA749]={ - category="ll", - direction="l", - }, - [0xA74A]={ - category="lu", - direction="l", - }, - [0xA74B]={ - category="ll", - direction="l", - }, - [0xA74C]={ - category="lu", - direction="l", - }, - [0xA74D]={ - category="ll", - direction="l", - }, - [0xA74E]={ - category="lu", - direction="l", - }, - [0xA74F]={ - category="ll", - direction="l", - }, - [0xA750]={ - category="lu", - direction="l", - }, - [0xA751]={ - category="ll", - direction="l", - }, - [0xA752]={ - category="lu", - direction="l", - }, - [0xA753]={ - category="ll", - direction="l", - }, - [0xA754]={ - category="lu", - direction="l", - }, - [0xA755]={ - category="ll", - direction="l", - }, - [0xA756]={ - category="lu", - direction="l", - }, - [0xA757]={ - category="ll", - direction="l", - }, - [0xA758]={ - category="lu", - direction="l", - }, - [0xA759]={ - category="ll", - direction="l", - }, - [0xA75A]={ - category="lu", - direction="l", - }, - [0xA75B]={ - category="ll", - direction="l", - }, - [0xA75C]={ - category="lu", - direction="l", - }, - [0xA75D]={ - category="ll", - direction="l", - }, - [0xA75E]={ - category="lu", - direction="l", - }, - [0xA75F]={ - category="ll", - direction="l", - }, - [0xA760]={ - category="lu", - direction="l", - }, - [0xA761]={ - category="ll", - direction="l", - }, - [0xA762]={ - category="lu", - direction="l", - }, - [0xA763]={ - category="ll", - direction="l", - }, - [0xA764]={ - category="lu", - direction="l", - }, - [0xA765]={ - category="ll", - direction="l", - }, - [0xA766]={ - category="lu", - direction="l", - }, - [0xA767]={ - category="ll", - direction="l", - }, - [0xA768]={ - category="lu", - direction="l", - }, - [0xA769]={ - category="ll", - direction="l", - }, - [0xA76A]={ - category="lu", - direction="l", - }, - [0xA76B]={ - category="ll", - direction="l", - }, - [0xA76C]={ - category="lu", - direction="l", - }, - [0xA76D]={ - category="ll", - direction="l", - }, - [0xA76E]={ - category="lu", - direction="l", - }, - [0xA76F]={ - category="ll", - direction="l", - }, - [0xA770]={ - category="lm", - direction="l", - }, - [0xA771]={ - category="ll", - direction="l", - }, - [0xA772]={ - category="ll", - direction="l", - }, - [0xA773]={ - category="ll", - direction="l", - }, - [0xA774]={ - category="ll", - direction="l", - }, - [0xA775]={ - category="ll", - direction="l", - }, - [0xA776]={ - category="ll", - direction="l", - }, - [0xA777]={ - category="ll", - direction="l", - }, - [0xA778]={ - category="ll", - direction="l", - }, - [0xA779]={ - category="lu", - direction="l", - }, - [0xA77A]={ - category="ll", - direction="l", - }, - [0xA77B]={ - category="lu", - direction="l", - }, - [0xA77C]={ - category="ll", - direction="l", - }, - [0xA77D]={ - category="lu", - direction="l", - }, - [0xA77E]={ - category="lu", - direction="l", - }, - [0xA77F]={ - category="ll", - direction="l", - }, - [0xA780]={ - category="lu", - direction="l", - }, - [0xA781]={ - category="ll", - direction="l", - }, - [0xA782]={ - category="lu", - direction="l", - }, - [0xA783]={ - category="ll", - direction="l", - }, - [0xA784]={ - category="lu", - direction="l", - }, - [0xA785]={ - category="ll", - direction="l", - }, - [0xA786]={ - category="lu", - direction="l", - }, - [0xA787]={ - category="ll", - direction="l", - }, - [0xA788]={ - category="lm", - direction="on", - }, - [0xA789]={ - category="sk", - direction="l", - }, - [0xA78A]={ - category="sk", - direction="l", - }, - [0xA78B]={ - category="lu", - direction="l", - }, - [0xA78C]={ - category="ll", - direction="l", - }, - [0xA78D]={ - category="lu", - direction="l", - }, - [0xA78E]={ - category="ll", - direction="l", - }, - [0xA78F]={ - category="lo", - direction="l", - }, - [0xA790]={ - category="lu", - direction="l", - }, - [0xA791]={ - category="ll", - direction="l", - }, - [0xA792]={ - category="lu", - direction="l", - }, - [0xA793]={ - category="ll", - direction="l", - }, - [0xA794]={ - category="ll", - direction="l", - }, - [0xA795]={ - category="ll", - direction="l", - }, - [0xA796]={ - category="lu", - direction="l", - }, - [0xA797]={ - category="ll", - direction="l", - }, - [0xA798]={ - category="lu", - direction="l", - }, - [0xA799]={ - category="ll", - direction="l", - }, - [0xA79A]={ - category="lu", - direction="l", - }, - [0xA79B]={ - category="ll", - direction="l", - }, - [0xA79C]={ - category="lu", - direction="l", - }, - [0xA79D]={ - category="ll", - direction="l", - }, - [0xA79E]={ - category="lu", - direction="l", - }, - [0xA79F]={ - category="ll", - direction="l", - }, - [0xA7A0]={ - category="lu", - direction="l", - }, - [0xA7A1]={ - category="ll", - direction="l", - }, - [0xA7A2]={ - category="lu", - direction="l", - }, - [0xA7A3]={ - category="ll", - direction="l", - }, - [0xA7A4]={ - category="lu", - direction="l", - }, - [0xA7A5]={ - category="ll", - direction="l", - }, - [0xA7A6]={ - category="lu", - direction="l", - }, - [0xA7A7]={ - category="ll", - direction="l", - }, - [0xA7A8]={ - category="lu", - direction="l", - }, - [0xA7A9]={ - category="ll", - direction="l", - }, - [0xA7AA]={ - category="lu", - direction="l", - }, - [0xA7AB]={ - category="lu", - direction="l", - }, - [0xA7AC]={ - category="lu", - direction="l", - }, - [0xA7AD]={ - category="lu", - direction="l", - }, - [0xA7AE]={ - category="lu", - direction="l", - }, - [0xA7B0]={ - category="lu", - direction="l", - }, - [0xA7B1]={ - category="lu", - direction="l", - }, - [0xA7B2]={ - category="lu", - direction="l", - }, - [0xA7B3]={ - category="lu", - direction="l", - }, - [0xA7B4]={ - category="lu", - direction="l", - }, - [0xA7B5]={ - category="ll", - direction="l", - }, - [0xA7B6]={ - category="lu", - direction="l", - }, - [0xA7B7]={ - category="ll", - direction="l", - }, - [0xA7F7]={ - category="lo", - direction="l", - }, - [0xA7F8]={ - category="lm", - direction="l", - }, - [0xA7F9]={ - category="lm", - direction="l", - }, - [0xA7FA]={ - category="ll", - direction="l", - }, - [0xA7FB]={ - category="lo", - direction="l", - }, - [0xA7FC]={ - category="lo", - direction="l", - }, - [0xA7FD]={ - category="lo", - direction="l", - }, - [0xA7FE]={ - category="lo", - direction="l", - }, - [0xA7FF]={ - category="lo", - direction="l", - }, - [0xA800]={ - category="lo", - direction="l", - }, - [0xA801]={ - category="lo", - direction="l", - }, - [0xA802]={ - category="mc", - direction="nsm", - }, - [0xA803]={ - category="lo", - direction="l", - }, - [0xA804]={ - category="lo", - direction="l", - }, - [0xA805]={ - category="lo", - direction="l", - }, - [0xA806]={ - category="mn", - direction="nsm", - }, - [0xA807]={ - category="lo", - direction="l", - }, - [0xA808]={ - category="lo", - direction="l", - }, - [0xA809]={ - category="lo", - direction="l", - }, - [0xA80A]={ - category="lo", - direction="l", - }, - [0xA80B]={ - category="mn", - direction="nsm", - }, - [0xA80C]={ - category="lo", - direction="l", - }, - [0xA80D]={ - category="lo", - direction="l", - }, - [0xA80E]={ - category="lo", - direction="l", - }, - [0xA80F]={ - category="lo", - direction="l", - }, - [0xA810]={ - category="lo", - direction="l", - }, - [0xA811]={ - category="lo", - direction="l", - }, - [0xA812]={ - category="lo", - direction="l", - }, - [0xA813]={ - category="lo", - direction="l", - }, - [0xA814]={ - category="lo", - direction="l", - }, - [0xA815]={ - category="lo", - direction="l", - }, - [0xA816]={ - category="lo", - direction="l", - }, - [0xA817]={ - category="lo", - direction="l", - }, - [0xA818]={ - category="lo", - direction="l", - }, - [0xA819]={ - category="lo", - direction="l", - }, - [0xA81A]={ - category="lo", - direction="l", - }, - [0xA81B]={ - category="lo", - direction="l", - }, - [0xA81C]={ - category="lo", - direction="l", - }, - [0xA81D]={ - category="lo", - direction="l", - }, - [0xA81E]={ - category="lo", - direction="l", - }, - [0xA81F]={ - category="lo", - direction="l", - }, - [0xA820]={ - category="lo", - direction="l", - }, - [0xA821]={ - category="lo", - direction="l", - }, - [0xA822]={ - category="lo", - direction="l", - }, - [0xA823]={ - category="mc", - direction="l", - }, - [0xA824]={ - category="mc", - direction="l", - }, - [0xA825]={ - category="mn", - direction="nsm", - }, - [0xA826]={ - category="mn", - direction="nsm", - }, - [0xA827]={ - category="mc", - direction="l", - }, - [0xA828]={ - category="so", - direction="on", - }, - [0xA829]={ - category="so", - direction="on", - }, - [0xA82A]={ - category="so", - direction="on", - }, - [0xA82B]={ - category="so", - direction="on", - }, - [0xA830]={ - category="no", - direction="l", - }, - [0xA831]={ - category="no", - direction="l", - }, - [0xA832]={ - category="no", - direction="l", - }, - [0xA833]={ - category="no", - direction="l", - }, - [0xA834]={ - category="no", - direction="l", - }, - [0xA835]={ - category="no", - direction="l", - }, - [0xA836]={ - category="so", - direction="l", - }, - [0xA837]={ - category="so", - direction="l", - }, - [0xA838]={ - category="sc", - direction="et", - }, - [0xA839]={ - category="so", - direction="et", - }, - [0xA840]={ - category="lo", - direction="l", - }, - [0xA841]={ - category="lo", - direction="l", - }, - [0xA842]={ - category="lo", - direction="l", - }, - [0xA843]={ - category="lo", - direction="l", - }, - [0xA844]={ - category="lo", - direction="l", - }, - [0xA845]={ - category="lo", - direction="l", - }, - [0xA846]={ - category="lo", - direction="l", - }, - [0xA847]={ - category="lo", - direction="l", - }, - [0xA848]={ - category="lo", - direction="l", - }, - [0xA849]={ - category="lo", - direction="l", - }, - [0xA84A]={ - category="lo", - direction="l", - }, - [0xA84B]={ - category="lo", - direction="l", - }, - [0xA84C]={ - category="lo", - direction="l", - }, - [0xA84D]={ - category="lo", - direction="l", - }, - [0xA84E]={ - category="lo", - direction="l", - }, - [0xA84F]={ - category="lo", - direction="l", - }, - [0xA850]={ - category="lo", - direction="l", - }, - [0xA851]={ - category="lo", - direction="l", - }, - [0xA852]={ - category="lo", - direction="l", - }, - [0xA853]={ - category="lo", - direction="l", - }, - [0xA854]={ - category="lo", - direction="l", - }, - [0xA855]={ - category="lo", - direction="l", - }, - [0xA856]={ - category="lo", - direction="l", - }, - [0xA857]={ - category="lo", - direction="l", - }, - [0xA858]={ - category="lo", - direction="l", - }, - [0xA859]={ - category="lo", - direction="l", - }, - [0xA85A]={ - category="lo", - direction="l", - }, - [0xA85B]={ - category="lo", - direction="l", - }, - [0xA85C]={ - category="lo", - direction="l", - }, - [0xA85D]={ - category="lo", - direction="l", - }, - [0xA85E]={ - category="lo", - direction="l", - }, - [0xA85F]={ - category="lo", - direction="l", - }, - [0xA860]={ - category="lo", - direction="l", - }, - [0xA861]={ - category="lo", - direction="l", - }, - [0xA862]={ - category="lo", - direction="l", - }, - [0xA863]={ - category="lo", - direction="l", - }, - [0xA864]={ - category="lo", - direction="l", - }, - [0xA865]={ - category="lo", - direction="l", - }, - [0xA866]={ - category="lo", - direction="l", - }, - [0xA867]={ - category="lo", - direction="l", - }, - [0xA868]={ - category="lo", - direction="l", - }, - [0xA869]={ - category="lo", - direction="l", - }, - [0xA86A]={ - category="lo", - direction="l", - }, - [0xA86B]={ - category="lo", - direction="l", - }, - [0xA86C]={ - category="lo", - direction="l", - }, - [0xA86D]={ - category="lo", - direction="l", - }, - [0xA86E]={ - category="lo", - direction="l", - }, - [0xA86F]={ - category="lo", - direction="l", - }, - [0xA870]={ - category="lo", - direction="l", - }, - [0xA871]={ - category="lo", - direction="l", - }, - [0xA872]={ - category="lo", - direction="l", - }, - [0xA873]={ - category="lo", - direction="l", - }, - [0xA874]={ - category="po", - direction="on", - }, - [0xA875]={ - category="po", - direction="on", - }, - [0xA876]={ - category="po", - direction="on", - }, - [0xA877]={ - category="po", - direction="on", - }, - [0xA880]={ - category="mc", - direction="l", - }, - [0xA881]={ - category="mc", - direction="l", - }, - [0xA882]={ - category="lo", - direction="l", - }, - [0xA883]={ - category="lo", - direction="l", - }, - [0xA884]={ - category="lo", - direction="l", - }, - [0xA885]={ - category="lo", - direction="l", - }, - [0xA886]={ - category="lo", - direction="l", - }, - [0xA887]={ - category="lo", - direction="l", - }, - [0xA888]={ - category="lo", - direction="l", - }, - [0xA889]={ - category="lo", - direction="l", - }, - [0xA88A]={ - category="lo", - direction="l", - }, - [0xA88B]={ - category="lo", - direction="l", - }, - [0xA88C]={ - category="lo", - direction="l", - }, - [0xA88D]={ - category="lo", - direction="l", - }, - [0xA88E]={ - category="lo", - direction="l", - }, - [0xA88F]={ - category="lo", - direction="l", - }, - [0xA890]={ - category="lo", - direction="l", - }, - [0xA891]={ - category="lo", - direction="l", - }, - [0xA892]={ - category="lo", - direction="l", - }, - [0xA893]={ - category="lo", - direction="l", - }, - [0xA894]={ - category="lo", - direction="l", - }, - [0xA895]={ - category="lo", - direction="l", - }, - [0xA896]={ - category="lo", - direction="l", - }, - [0xA897]={ - category="lo", - direction="l", - }, - [0xA898]={ - category="lo", - direction="l", - }, - [0xA899]={ - category="lo", - direction="l", - }, - [0xA89A]={ - category="lo", - direction="l", - }, - [0xA89B]={ - category="lo", - direction="l", - }, - [0xA89C]={ - category="lo", - direction="l", - }, - [0xA89D]={ - category="lo", - direction="l", - }, - [0xA89E]={ - category="lo", - direction="l", - }, - [0xA89F]={ - category="lo", - direction="l", - }, - [0xA8A0]={ - category="lo", - direction="l", - }, - [0xA8A1]={ - category="lo", - direction="l", - }, - [0xA8A2]={ - category="lo", - direction="l", - }, - [0xA8A3]={ - category="lo", - direction="l", - }, - [0xA8A4]={ - category="lo", - direction="l", - }, - [0xA8A5]={ - category="lo", - direction="l", - }, - [0xA8A6]={ - category="lo", - direction="l", - }, - [0xA8A7]={ - category="lo", - direction="l", - }, - [0xA8A8]={ - category="lo", - direction="l", - }, - [0xA8A9]={ - category="lo", - direction="l", - }, - [0xA8AA]={ - category="lo", - direction="l", - }, - [0xA8AB]={ - category="lo", - direction="l", - }, - [0xA8AC]={ - category="lo", - direction="l", - }, - [0xA8AD]={ - category="lo", - direction="l", - }, - [0xA8AE]={ - category="lo", - direction="l", - }, - [0xA8AF]={ - category="lo", - direction="l", - }, - [0xA8B0]={ - category="lo", - direction="l", - }, - [0xA8B1]={ - category="lo", - direction="l", - }, - [0xA8B2]={ - category="lo", - direction="l", - }, - [0xA8B3]={ - category="lo", - direction="l", - }, - [0xA8B4]={ - category="mc", - direction="l", - }, - [0xA8B5]={ - category="mc", - direction="l", - }, - [0xA8B6]={ - category="mc", - direction="l", - }, - [0xA8B7]={ - category="mc", - direction="l", - }, - [0xA8B8]={ - category="mc", - direction="l", - }, - [0xA8B9]={ - category="mc", - direction="l", - }, - [0xA8BA]={ - category="mc", - direction="l", - }, - [0xA8BB]={ - category="mc", - direction="l", - }, - [0xA8BC]={ - category="mc", - direction="l", - }, - [0xA8BD]={ - category="mc", - direction="l", - }, - [0xA8BE]={ - category="mc", - direction="l", - }, - [0xA8BF]={ - category="mc", - direction="l", - }, - [0xA8C0]={ - category="mc", - direction="l", - }, - [0xA8C1]={ - category="mc", - direction="l", - }, - [0xA8C2]={ - category="mc", - direction="l", - }, - [0xA8C3]={ - category="mc", - direction="l", - }, - [0xA8C4]={ - category="mn", - direction="nsm", - }, - [0xA8C5]={ - category="mn", - direction="nsm", - }, - [0xA8CE]={ - category="po", - direction="l", - }, - [0xA8CF]={ - category="po", - direction="l", - }, - [0xA8D0]={ - category="nd", - direction="l", - }, - [0xA8D1]={ - category="nd", - direction="l", - }, - [0xA8D2]={ - category="nd", - direction="l", - }, - [0xA8D3]={ - category="nd", - direction="l", - }, - [0xA8D4]={ - category="nd", - direction="l", - }, - [0xA8D5]={ - category="nd", - direction="l", - }, - [0xA8D6]={ - category="nd", - direction="l", - }, - [0xA8D7]={ - category="nd", - direction="l", - }, - [0xA8D8]={ - category="nd", - direction="l", - }, - [0xA8D9]={ - category="nd", - direction="l", - }, - [0xA8E0]={ - category="mn", - direction="nsm", - }, - [0xA8E1]={ - category="mn", - direction="nsm", - }, - [0xA8E2]={ - category="mn", - direction="nsm", - }, - [0xA8E3]={ - category="mn", - direction="nsm", - }, - [0xA8E4]={ - category="mn", - direction="nsm", - }, - [0xA8E5]={ - category="mn", - direction="nsm", - }, - [0xA8E6]={ - category="mn", - direction="nsm", - }, - [0xA8E7]={ - category="mn", - direction="nsm", - }, - [0xA8E8]={ - category="mn", - direction="nsm", - }, - [0xA8E9]={ - category="mn", - direction="nsm", - }, - [0xA8EA]={ - category="mn", - direction="nsm", - }, - [0xA8EB]={ - category="mn", - direction="nsm", - }, - [0xA8EC]={ - category="mn", - direction="nsm", - }, - [0xA8ED]={ - category="mn", - direction="nsm", - }, - [0xA8EE]={ - category="mn", - direction="nsm", - }, - [0xA8EF]={ - category="mn", - direction="nsm", - }, - [0xA8F0]={ - category="mn", - direction="nsm", - }, - [0xA8F1]={ - category="mn", - direction="nsm", - }, - [0xA8F2]={ - category="lo", - direction="l", - }, - [0xA8F3]={ - category="lo", - direction="l", - }, - [0xA8F4]={ - category="lo", - direction="l", - }, - [0xA8F5]={ - category="lo", - direction="l", - }, - [0xA8F6]={ - category="lo", - direction="l", - }, - [0xA8F7]={ - category="lo", - direction="l", - }, - [0xA8F8]={ - category="po", - direction="l", - }, - [0xA8F9]={ - category="po", - direction="l", - }, - [0xA8FA]={ - category="po", - direction="l", - }, - [0xA8FB]={ - category="lo", - direction="l", - }, - [0xA8FC]={ - category="po", - direction="l", - }, - [0xA8FD]={ - category="lo", - direction="l", - }, - [0xA900]={ - category="nd", - direction="l", - }, - [0xA901]={ - category="nd", - direction="l", - }, - [0xA902]={ - category="nd", - direction="l", - }, - [0xA903]={ - category="nd", - direction="l", - }, - [0xA904]={ - category="nd", - direction="l", - }, - [0xA905]={ - category="nd", - direction="l", - }, - [0xA906]={ - category="nd", - direction="l", - }, - [0xA907]={ - category="nd", - direction="l", - }, - [0xA908]={ - category="nd", - direction="l", - }, - [0xA909]={ - category="nd", - direction="l", - }, - [0xA90A]={ - category="lo", - direction="l", - }, - [0xA90B]={ - category="lo", - direction="l", - }, - [0xA90C]={ - category="lo", - direction="l", - }, - [0xA90D]={ - category="lo", - direction="l", - }, - [0xA90E]={ - category="lo", - direction="l", - }, - [0xA90F]={ - category="lo", - direction="l", - }, - [0xA910]={ - category="lo", - direction="l", - }, - [0xA911]={ - category="lo", - direction="l", - }, - [0xA912]={ - category="lo", - direction="l", - }, - [0xA913]={ - category="lo", - direction="l", - }, - [0xA914]={ - category="lo", - direction="l", - }, - [0xA915]={ - category="lo", - direction="l", - }, - [0xA916]={ - category="lo", - direction="l", - }, - [0xA917]={ - category="lo", - direction="l", - }, - [0xA918]={ - category="lo", - direction="l", - }, - [0xA919]={ - category="lo", - direction="l", - }, - [0xA91A]={ - category="lo", - direction="l", - }, - [0xA91B]={ - category="lo", - direction="l", - }, - [0xA91C]={ - category="lo", - direction="l", - }, - [0xA91D]={ - category="lo", - direction="l", - }, - [0xA91E]={ - category="lo", - direction="l", - }, - [0xA91F]={ - category="lo", - direction="l", - }, - [0xA920]={ - category="lo", - direction="l", - }, - [0xA921]={ - category="lo", - direction="l", - }, - [0xA922]={ - category="lo", - direction="l", - }, - [0xA923]={ - category="lo", - direction="l", - }, - [0xA924]={ - category="lo", - direction="l", - }, - [0xA925]={ - category="lo", - direction="l", - }, - [0xA926]={ - category="mn", - direction="nsm", - }, - [0xA927]={ - category="mn", - direction="nsm", - }, - [0xA928]={ - category="mn", - direction="nsm", - }, - [0xA929]={ - category="mn", - direction="nsm", - }, - [0xA92A]={ - category="mn", - direction="nsm", - }, - [0xA92B]={ - category="mn", - direction="nsm", - }, - [0xA92C]={ - category="mn", - direction="nsm", - }, - [0xA92D]={ - category="mn", - direction="nsm", - }, - [0xA92E]={ - category="po", - direction="l", - }, - [0xA92F]={ - category="po", - direction="l", - }, - [0xA930]={ - category="lo", - direction="l", - }, - [0xA931]={ - category="lo", - direction="l", - }, - [0xA932]={ - category="lo", - direction="l", - }, - [0xA933]={ - category="lo", - direction="l", - }, - [0xA934]={ - category="lo", - direction="l", - }, - [0xA935]={ - category="lo", - direction="l", - }, - [0xA936]={ - category="lo", - direction="l", - }, - [0xA937]={ - category="lo", - direction="l", - }, - [0xA938]={ - category="lo", - direction="l", - }, - [0xA939]={ - category="lo", - direction="l", - }, - [0xA93A]={ - category="lo", - direction="l", - }, - [0xA93B]={ - category="lo", - direction="l", - }, - [0xA93C]={ - category="lo", - direction="l", - }, - [0xA93D]={ - category="lo", - direction="l", - }, - [0xA93E]={ - category="lo", - direction="l", - }, - [0xA93F]={ - category="lo", - direction="l", - }, - [0xA940]={ - category="lo", - direction="l", - }, - [0xA941]={ - category="lo", - direction="l", - }, - [0xA942]={ - category="lo", - direction="l", - }, - [0xA943]={ - category="lo", - direction="l", - }, - [0xA944]={ - category="lo", - direction="l", - }, - [0xA945]={ - category="lo", - direction="l", - }, - [0xA946]={ - category="lo", - direction="l", - }, - [0xA947]={ - category="mn", - direction="nsm", - }, - [0xA948]={ - category="mn", - direction="nsm", - }, - [0xA949]={ - category="mn", - direction="nsm", - }, - [0xA94A]={ - category="mn", - direction="nsm", - }, - [0xA94B]={ - category="mn", - direction="nsm", - }, - [0xA94C]={ - category="mn", - direction="nsm", - }, - [0xA94D]={ - category="mn", - direction="nsm", - }, - [0xA94E]={ - category="mn", - direction="nsm", - }, - [0xA94F]={ - category="mn", - direction="nsm", - }, - [0xA950]={ - category="mn", - direction="nsm", - }, - [0xA951]={ - category="mn", - direction="nsm", - }, - [0xA952]={ - category="mc", - direction="l", - }, - [0xA953]={ - category="mc", - direction="l", - }, - [0xA95F]={ - category="po", - direction="l", - }, - [0xA960]={ - category="lo", - direction="l", - }, - [0xA961]={ - category="lo", - direction="l", - }, - [0xA962]={ - category="lo", - direction="l", - }, - [0xA963]={ - category="lo", - direction="l", - }, - [0xA964]={ - category="lo", - direction="l", - }, - [0xA965]={ - category="lo", - direction="l", - }, - [0xA966]={ - category="lo", - direction="l", - }, - [0xA967]={ - category="lo", - direction="l", - }, - [0xA968]={ - category="lo", - direction="l", - }, - [0xA969]={ - category="lo", - direction="l", - }, - [0xA96A]={ - category="lo", - direction="l", - }, - [0xA96B]={ - category="lo", - direction="l", - }, - [0xA96C]={ - category="lo", - direction="l", - }, - [0xA96D]={ - category="lo", - direction="l", - }, - [0xA96E]={ - category="lo", - direction="l", - }, - [0xA96F]={ - category="lo", - direction="l", - }, - [0xA970]={ - category="lo", - direction="l", - }, - [0xA971]={ - category="lo", - direction="l", - }, - [0xA972]={ - category="lo", - direction="l", - }, - [0xA973]={ - category="lo", - direction="l", - }, - [0xA974]={ - category="lo", - direction="l", - }, - [0xA975]={ - category="lo", - direction="l", - }, - [0xA976]={ - category="lo", - direction="l", - }, - [0xA977]={ - category="lo", - direction="l", - }, - [0xA978]={ - category="lo", - direction="l", - }, - [0xA979]={ - category="lo", - direction="l", - }, - [0xA97A]={ - category="lo", - direction="l", - }, - [0xA97B]={ - category="lo", - direction="l", - }, - [0xA97C]={ - category="lo", - direction="l", - }, - [0xA980]={ - category="mn", - direction="nsm", - }, - [0xA981]={ - category="mn", - direction="nsm", - }, - [0xA982]={ - category="mn", - direction="nsm", - }, - [0xA983]={ - category="mc", - direction="l", - }, - [0xA984]={ - category="lo", - direction="l", - }, - [0xA985]={ - category="lo", - direction="l", - }, - [0xA986]={ - category="lo", - direction="l", - }, - [0xA987]={ - category="lo", - direction="l", - }, - [0xA988]={ - category="lo", - direction="l", - }, - [0xA989]={ - category="lo", - direction="l", - }, - [0xA98A]={ - category="lo", - direction="l", - }, - [0xA98B]={ - category="lo", - direction="l", - }, - [0xA98C]={ - category="lo", - direction="l", - }, - [0xA98D]={ - category="lo", - direction="l", - }, - [0xA98E]={ - category="lo", - direction="l", - }, - [0xA98F]={ - category="lo", - direction="l", - }, - [0xA990]={ - category="lo", - direction="l", - }, - [0xA991]={ - category="lo", - direction="l", - }, - [0xA992]={ - category="lo", - direction="l", - }, - [0xA993]={ - category="lo", - direction="l", - }, - [0xA994]={ - category="lo", - direction="l", - }, - [0xA995]={ - category="lo", - direction="l", - }, - [0xA996]={ - category="lo", - direction="l", - }, - [0xA997]={ - category="lo", - direction="l", - }, - [0xA998]={ - category="lo", - direction="l", - }, - [0xA999]={ - category="lo", - direction="l", - }, - [0xA99A]={ - category="lo", - direction="l", - }, - [0xA99B]={ - category="lo", - direction="l", - }, - [0xA99C]={ - category="lo", - direction="l", - }, - [0xA99D]={ - category="lo", - direction="l", - }, - [0xA99E]={ - category="lo", - direction="l", - }, - [0xA99F]={ - category="lo", - direction="l", - }, - [0xA9A0]={ - category="lo", - direction="l", - }, - [0xA9A1]={ - category="lo", - direction="l", - }, - [0xA9A2]={ - category="lo", - direction="l", - }, - [0xA9A3]={ - category="lo", - direction="l", - }, - [0xA9A4]={ - category="lo", - direction="l", - }, - [0xA9A5]={ - category="lo", - direction="l", - }, - [0xA9A6]={ - category="lo", - direction="l", - }, - [0xA9A7]={ - category="lo", - direction="l", - }, - [0xA9A8]={ - category="lo", - direction="l", - }, - [0xA9A9]={ - category="lo", - direction="l", - }, - [0xA9AA]={ - category="lo", - direction="l", - }, - [0xA9AB]={ - category="lo", - direction="l", - }, - [0xA9AC]={ - category="lo", - direction="l", - }, - [0xA9AD]={ - category="lo", - direction="l", - }, - [0xA9AE]={ - category="lo", - direction="l", - }, - [0xA9AF]={ - category="lo", - direction="l", - }, - [0xA9B0]={ - category="lo", - direction="l", - }, - [0xA9B1]={ - category="lo", - direction="l", - }, - [0xA9B2]={ - category="lo", - direction="l", - }, - [0xA9B3]={ - category="mn", - direction="nsm", - }, - [0xA9B4]={ - category="mc", - direction="l", - }, - [0xA9B5]={ - category="mc", - direction="l", - }, - [0xA9B6]={ - category="mn", - direction="nsm", - }, - [0xA9B7]={ - category="mn", - direction="nsm", - }, - [0xA9B8]={ - category="mn", - direction="nsm", - }, - [0xA9B9]={ - category="mn", - direction="nsm", - }, - [0xA9BA]={ - category="mc", - direction="l", - }, - [0xA9BB]={ - category="mc", - direction="l", - }, - [0xA9BC]={ - category="mn", - direction="nsm", - }, - [0xA9BD]={ - category="mc", - direction="l", - }, - [0xA9BE]={ - category="mc", - direction="l", - }, - [0xA9BF]={ - category="mc", - direction="l", - }, - [0xA9C0]={ - category="mc", - direction="l", - }, - [0xA9C1]={ - category="po", - direction="l", - }, - [0xA9C2]={ - category="po", - direction="l", - }, - [0xA9C3]={ - category="po", - direction="l", - }, - [0xA9C4]={ - category="po", - direction="l", - }, - [0xA9C5]={ - category="po", - direction="l", - }, - [0xA9C6]={ - category="po", - direction="l", - }, - [0xA9C7]={ - category="po", - direction="l", - }, - [0xA9C8]={ - category="po", - direction="l", - }, - [0xA9C9]={ - category="po", - direction="l", - }, - [0xA9CA]={ - category="po", - direction="l", - }, - [0xA9CB]={ - category="po", - direction="l", - }, - [0xA9CC]={ - category="po", - direction="l", - }, - [0xA9CD]={ - category="po", - direction="l", - }, - [0xA9CF]={ - category="lm", - direction="l", - }, - [0xA9D0]={ - category="nd", - direction="l", - }, - [0xA9D1]={ - category="nd", - direction="l", - }, - [0xA9D2]={ - category="nd", - direction="l", - }, - [0xA9D3]={ - category="nd", - direction="l", - }, - [0xA9D4]={ - category="nd", - direction="l", - }, - [0xA9D5]={ - category="nd", - direction="l", - }, - [0xA9D6]={ - category="nd", - direction="l", - }, - [0xA9D7]={ - category="nd", - direction="l", - }, - [0xA9D8]={ - category="nd", - direction="l", - }, - [0xA9D9]={ - category="nd", - direction="l", - }, - [0xA9DE]={ - category="po", - direction="l", - }, - [0xA9DF]={ - category="po", - direction="l", - }, - [0xA9E0]={ - category="lo", - direction="l", - }, - [0xA9E1]={ - category="lo", - direction="l", - }, - [0xA9E2]={ - category="lo", - direction="l", - }, - [0xA9E3]={ - category="lo", - direction="l", - }, - [0xA9E4]={ - category="lo", - direction="l", - }, - [0xA9E5]={ - category="mn", - direction="nsm", - }, - [0xA9E6]={ - category="lm", - direction="l", - }, - [0xA9E7]={ - category="lo", - direction="l", - }, - [0xA9E8]={ - category="lo", - direction="l", - }, - [0xA9E9]={ - category="lo", - direction="l", - }, - [0xA9EA]={ - category="lo", - direction="l", - }, - [0xA9EB]={ - category="lo", - direction="l", - }, - [0xA9EC]={ - category="lo", - direction="l", - }, - [0xA9ED]={ - category="lo", - direction="l", - }, - [0xA9EE]={ - category="lo", - direction="l", - }, - [0xA9EF]={ - category="lo", - direction="l", - }, - [0xA9F0]={ - category="nd", - direction="l", - }, - [0xA9F1]={ - category="nd", - direction="l", - }, - [0xA9F2]={ - category="nd", - direction="l", - }, - [0xA9F3]={ - category="nd", - direction="l", - }, - [0xA9F4]={ - category="nd", - direction="l", - }, - [0xA9F5]={ - category="nd", - direction="l", - }, - [0xA9F6]={ - category="nd", - direction="l", - }, - [0xA9F7]={ - category="nd", - direction="l", - }, - [0xA9F8]={ - category="nd", - direction="l", - }, - [0xA9F9]={ - category="nd", - direction="l", - }, - [0xA9FA]={ - category="lo", - direction="l", - }, - [0xA9FB]={ - category="lo", - direction="l", - }, - [0xA9FC]={ - category="lo", - direction="l", - }, - [0xA9FD]={ - category="lo", - direction="l", - }, - [0xA9FE]={ - category="lo", - direction="l", - }, - [0xAA00]={ - category="lo", - direction="l", - }, - [0xAA01]={ - category="lo", - direction="l", - }, - [0xAA02]={ - category="lo", - direction="l", - }, - [0xAA03]={ - category="lo", - direction="l", - }, - [0xAA04]={ - category="lo", - direction="l", - }, - [0xAA05]={ - category="lo", - direction="l", - }, - [0xAA06]={ - category="lo", - direction="l", - }, - [0xAA07]={ - category="lo", - direction="l", - }, - [0xAA08]={ - category="lo", - direction="l", - }, - [0xAA09]={ - category="lo", - direction="l", - }, - [0xAA0A]={ - category="lo", - direction="l", - }, - [0xAA0B]={ - category="lo", - direction="l", - }, - [0xAA0C]={ - category="lo", - direction="l", - }, - [0xAA0D]={ - category="lo", - direction="l", - }, - [0xAA0E]={ - category="lo", - direction="l", - }, - [0xAA0F]={ - category="lo", - direction="l", - }, - [0xAA10]={ - category="lo", - direction="l", - }, - [0xAA11]={ - category="lo", - direction="l", - }, - [0xAA12]={ - category="lo", - direction="l", - }, - [0xAA13]={ - category="lo", - direction="l", - }, - [0xAA14]={ - category="lo", - direction="l", - }, - [0xAA15]={ - category="lo", - direction="l", - }, - [0xAA16]={ - category="lo", - direction="l", - }, - [0xAA17]={ - category="lo", - direction="l", - }, - [0xAA18]={ - category="lo", - direction="l", - }, - [0xAA19]={ - category="lo", - direction="l", - }, - [0xAA1A]={ - category="lo", - direction="l", - }, - [0xAA1B]={ - category="lo", - direction="l", - }, - [0xAA1C]={ - category="lo", - direction="l", - }, - [0xAA1D]={ - category="lo", - direction="l", - }, - [0xAA1E]={ - category="lo", - direction="l", - }, - [0xAA1F]={ - category="lo", - direction="l", - }, - [0xAA20]={ - category="lo", - direction="l", - }, - [0xAA21]={ - category="lo", - direction="l", - }, - [0xAA22]={ - category="lo", - direction="l", - }, - [0xAA23]={ - category="lo", - direction="l", - }, - [0xAA24]={ - category="lo", - direction="l", - }, - [0xAA25]={ - category="lo", - direction="l", - }, - [0xAA26]={ - category="lo", - direction="l", - }, - [0xAA27]={ - category="lo", - direction="l", - }, - [0xAA28]={ - category="lo", - direction="l", - }, - [0xAA29]={ - category="mn", - direction="nsm", - }, - [0xAA2A]={ - category="mn", - direction="nsm", - }, - [0xAA2B]={ - category="mn", - direction="nsm", - }, - [0xAA2C]={ - category="mn", - direction="nsm", - }, - [0xAA2D]={ - category="mn", - direction="nsm", - }, - [0xAA2E]={ - category="mn", - direction="nsm", - }, - [0xAA2F]={ - category="mc", - direction="l", - }, - [0xAA30]={ - category="mc", - direction="l", - }, - [0xAA31]={ - category="mn", - direction="nsm", - }, - [0xAA32]={ - category="mn", - direction="nsm", - }, - [0xAA33]={ - category="mc", - direction="l", - }, - [0xAA34]={ - category="mc", - direction="l", - }, - [0xAA35]={ - category="mn", - direction="nsm", - }, - [0xAA36]={ - category="mn", - direction="nsm", - }, - [0xAA40]={ - category="lo", - direction="l", - }, - [0xAA41]={ - category="lo", - direction="l", - }, - [0xAA42]={ - category="lo", - direction="l", - }, - [0xAA43]={ - category="mn", - direction="nsm", - }, - [0xAA44]={ - category="lo", - direction="l", - }, - [0xAA45]={ - category="lo", - direction="l", - }, - [0xAA46]={ - category="lo", - direction="l", - }, - [0xAA47]={ - category="lo", - direction="l", - }, - [0xAA48]={ - category="lo", - direction="l", - }, - [0xAA49]={ - category="lo", - direction="l", - }, - [0xAA4A]={ - category="lo", - direction="l", - }, - [0xAA4B]={ - category="lo", - direction="l", - }, - [0xAA4C]={ - category="mn", - direction="nsm", - }, - [0xAA4D]={ - category="mc", - direction="l", - }, - [0xAA50]={ - category="nd", - direction="l", - }, - [0xAA51]={ - category="nd", - direction="l", - }, - [0xAA52]={ - category="nd", - direction="l", - }, - [0xAA53]={ - category="nd", - direction="l", - }, - [0xAA54]={ - category="nd", - direction="l", - }, - [0xAA55]={ - category="nd", - direction="l", - }, - [0xAA56]={ - category="nd", - direction="l", - }, - [0xAA57]={ - category="nd", - direction="l", - }, - [0xAA58]={ - category="nd", - direction="l", - }, - [0xAA59]={ - category="nd", - direction="l", - }, - [0xAA5C]={ - category="po", - direction="l", - }, - [0xAA5D]={ - category="po", - direction="l", - }, - [0xAA5E]={ - category="po", - direction="l", - }, - [0xAA5F]={ - category="po", - direction="l", - }, - [0xAA60]={ - category="lo", - direction="l", - }, - [0xAA61]={ - category="lo", - direction="l", - }, - [0xAA62]={ - category="lo", - direction="l", - }, - [0xAA63]={ - category="lo", - direction="l", - }, - [0xAA64]={ - category="lo", - direction="l", - }, - [0xAA65]={ - category="lo", - direction="l", - }, - [0xAA66]={ - category="lo", - direction="l", - }, - [0xAA67]={ - category="lo", - direction="l", - }, - [0xAA68]={ - category="lo", - direction="l", - }, - [0xAA69]={ - category="lo", - direction="l", - }, - [0xAA6A]={ - category="lo", - direction="l", - }, - [0xAA6B]={ - category="lo", - direction="l", - }, - [0xAA6C]={ - category="lo", - direction="l", - }, - [0xAA6D]={ - category="lo", - direction="l", - }, - [0xAA6E]={ - category="lo", - direction="l", - }, - [0xAA6F]={ - category="lo", - direction="l", - }, - [0xAA70]={ - category="lm", - direction="l", - }, - [0xAA71]={ - category="lo", - direction="l", - }, - [0xAA72]={ - category="lo", - direction="l", - }, - [0xAA73]={ - category="lo", - direction="l", - }, - [0xAA74]={ - category="lo", - direction="l", - }, - [0xAA75]={ - category="lo", - direction="l", - }, - [0xAA76]={ - category="lo", - direction="l", - }, - [0xAA77]={ - category="so", - direction="l", - }, - [0xAA78]={ - category="so", - direction="l", - }, - [0xAA79]={ - category="so", - direction="l", - }, - [0xAA7A]={ - category="lo", - direction="l", - }, - [0xAA7B]={ - category="mc", - direction="l", - }, - [0xAA7C]={ - category="mn", - direction="nsm", - }, - [0xAA7D]={ - category="mc", - direction="l", - }, - [0xAA7E]={ - category="lo", - direction="l", - }, - [0xAA7F]={ - category="lo", - direction="l", - }, - [0xAA80]={ - category="lo", - direction="l", - }, - [0xAA81]={ - category="lo", - direction="l", - }, - [0xAA82]={ - category="lo", - direction="l", - }, - [0xAA83]={ - category="lo", - direction="l", - }, - [0xAA84]={ - category="lo", - direction="l", - }, - [0xAA85]={ - category="lo", - direction="l", - }, - [0xAA86]={ - category="lo", - direction="l", - }, - [0xAA87]={ - category="lo", - direction="l", - }, - [0xAA88]={ - category="lo", - direction="l", - }, - [0xAA89]={ - category="lo", - direction="l", - }, - [0xAA8A]={ - category="lo", - direction="l", - }, - [0xAA8B]={ - category="lo", - direction="l", - }, - [0xAA8C]={ - category="lo", - direction="l", - }, - [0xAA8D]={ - category="lo", - direction="l", - }, - [0xAA8E]={ - category="lo", - direction="l", - }, - [0xAA8F]={ - category="lo", - direction="l", - }, - [0xAA90]={ - category="lo", - direction="l", - }, - [0xAA91]={ - category="lo", - direction="l", - }, - [0xAA92]={ - category="lo", - direction="l", - }, - [0xAA93]={ - category="lo", - direction="l", - }, - [0xAA94]={ - category="lo", - direction="l", - }, - [0xAA95]={ - category="lo", - direction="l", - }, - [0xAA96]={ - category="lo", - direction="l", - }, - [0xAA97]={ - category="lo", - direction="l", - }, - [0xAA98]={ - category="lo", - direction="l", - }, - [0xAA99]={ - category="lo", - direction="l", - }, - [0xAA9A]={ - category="lo", - direction="l", - }, - [0xAA9B]={ - category="lo", - direction="l", - }, - [0xAA9C]={ - category="lo", - direction="l", - }, - [0xAA9D]={ - category="lo", - direction="l", - }, - [0xAA9E]={ - category="lo", - direction="l", - }, - [0xAA9F]={ - category="lo", - direction="l", - }, - [0xAAA0]={ - category="lo", - direction="l", - }, - [0xAAA1]={ - category="lo", - direction="l", - }, - [0xAAA2]={ - category="lo", - direction="l", - }, - [0xAAA3]={ - category="lo", - direction="l", - }, - [0xAAA4]={ - category="lo", - direction="l", - }, - [0xAAA5]={ - category="lo", - direction="l", - }, - [0xAAA6]={ - category="lo", - direction="l", - }, - [0xAAA7]={ - category="lo", - direction="l", - }, - [0xAAA8]={ - category="lo", - direction="l", - }, - [0xAAA9]={ - category="lo", - direction="l", - }, - [0xAAAA]={ - category="lo", - direction="l", - }, - [0xAAAB]={ - category="lo", - direction="l", - }, - [0xAAAC]={ - category="lo", - direction="l", - }, - [0xAAAD]={ - category="lo", - direction="l", - }, - [0xAAAE]={ - category="lo", - direction="l", - }, - [0xAAAF]={ - category="lo", - direction="l", - }, - [0xAAB0]={ - category="mn", - direction="nsm", - }, - [0xAAB1]={ - category="lo", - direction="l", - }, - [0xAAB2]={ - category="mn", - direction="nsm", - }, - [0xAAB3]={ - category="mn", - direction="nsm", - }, - [0xAAB4]={ - category="mn", - direction="nsm", - }, - [0xAAB5]={ - category="lo", - direction="l", - }, - [0xAAB6]={ - category="lo", - direction="l", - }, - [0xAAB7]={ - category="mn", - direction="nsm", - }, - [0xAAB8]={ - category="mn", - direction="nsm", - }, - [0xAAB9]={ - category="lo", - direction="l", - }, - [0xAABA]={ - category="lo", - direction="l", - }, - [0xAABB]={ - category="lo", - direction="l", - }, - [0xAABC]={ - category="lo", - direction="l", - }, - [0xAABD]={ - category="lo", - direction="l", - }, - [0xAABE]={ - category="mn", - direction="nsm", - }, - [0xAABF]={ - category="mn", - direction="nsm", - }, - [0xAAC0]={ - category="lo", - direction="l", - }, - [0xAAC1]={ - category="mn", - direction="nsm", - }, - [0xAAC2]={ - category="lo", - direction="l", - }, - [0xAADB]={ - category="lo", - direction="l", - }, - [0xAADC]={ - category="lo", - direction="l", - }, - [0xAADD]={ - category="lm", - direction="l", - }, - [0xAADE]={ - category="po", - direction="l", - }, - [0xAADF]={ - category="po", - direction="l", - }, - [0xAAE0]={ - category="lo", - direction="l", - }, - [0xAAE1]={ - category="lo", - direction="l", - }, - [0xAAE2]={ - category="lo", - direction="l", - }, - [0xAAE3]={ - category="lo", - direction="l", - }, - [0xAAE4]={ - category="lo", - direction="l", - }, - [0xAAE5]={ - category="lo", - direction="l", - }, - [0xAAE6]={ - category="lo", - direction="l", - }, - [0xAAE7]={ - category="lo", - direction="l", - }, - [0xAAE8]={ - category="lo", - direction="l", - }, - [0xAAE9]={ - category="lo", - direction="l", - }, - [0xAAEA]={ - category="lo", - direction="l", - }, - [0xAAEB]={ - category="mc", - direction="l", - }, - [0xAAEC]={ - category="mn", - direction="nsm", - }, - [0xAAED]={ - category="mn", - direction="nsm", - }, - [0xAAEE]={ - category="mc", - direction="l", - }, - [0xAAEF]={ - category="mc", - direction="l", - }, - [0xAAF0]={ - category="po", - direction="l", - }, - [0xAAF1]={ - category="po", - direction="l", - }, - [0xAAF2]={ - category="lo", - direction="l", - }, - [0xAAF3]={ - category="lm", - direction="l", - }, - [0xAAF4]={ - category="lm", - direction="l", - }, - [0xAAF5]={ - category="mc", - direction="l", - }, - [0xAAF6]={ - category="mn", - direction="nsm", - }, - [0xAB01]={ - category="lo", - direction="l", - }, - [0xAB02]={ - category="lo", - direction="l", - }, - [0xAB03]={ - category="lo", - direction="l", - }, - [0xAB04]={ - category="lo", - direction="l", - }, - [0xAB05]={ - category="lo", - direction="l", - }, - [0xAB06]={ - category="lo", - direction="l", - }, - [0xAB09]={ - category="lo", - direction="l", - }, - [0xAB0A]={ - category="lo", - direction="l", - }, - [0xAB0B]={ - category="lo", - direction="l", - }, - [0xAB0C]={ - category="lo", - direction="l", - }, - [0xAB0D]={ - category="lo", - direction="l", - }, - [0xAB0E]={ - category="lo", - direction="l", - }, - [0xAB11]={ - category="lo", - direction="l", - }, - [0xAB12]={ - category="lo", - direction="l", - }, - [0xAB13]={ - category="lo", - direction="l", - }, - [0xAB14]={ - category="lo", - direction="l", - }, - [0xAB15]={ - category="lo", - direction="l", - }, - [0xAB16]={ - category="lo", - direction="l", - }, - [0xAB20]={ - category="lo", - direction="l", - }, - [0xAB21]={ - category="lo", - direction="l", - }, - [0xAB22]={ - category="lo", - direction="l", - }, - [0xAB23]={ - category="lo", - direction="l", - }, - [0xAB24]={ - category="lo", - direction="l", - }, - [0xAB25]={ - category="lo", - direction="l", - }, - [0xAB26]={ - category="lo", - direction="l", - }, - [0xAB28]={ - category="lo", - direction="l", - }, - [0xAB29]={ - category="lo", - direction="l", - }, - [0xAB2A]={ - category="lo", - direction="l", - }, - [0xAB2B]={ - category="lo", - direction="l", - }, - [0xAB2C]={ - category="lo", - direction="l", - }, - [0xAB2D]={ - category="lo", - direction="l", - }, - [0xAB2E]={ - category="lo", - direction="l", - }, - [0xAB30]={ - category="ll", - direction="l", - }, - [0xAB31]={ - category="ll", - direction="l", - }, - [0xAB32]={ - category="ll", - direction="l", - }, - [0xAB33]={ - category="ll", - direction="l", - }, - [0xAB34]={ - category="ll", - direction="l", - }, - [0xAB35]={ - category="ll", - direction="l", - }, - [0xAB36]={ - category="ll", - direction="l", - }, - [0xAB37]={ - category="ll", - direction="l", - }, - [0xAB38]={ - category="ll", - direction="l", - }, - [0xAB39]={ - category="ll", - direction="l", - }, - [0xAB3A]={ - category="ll", - direction="l", - }, - [0xAB3B]={ - category="ll", - direction="l", - }, - [0xAB3C]={ - category="ll", - direction="l", - }, - [0xAB3D]={ - category="ll", - direction="l", - }, - [0xAB3E]={ - category="ll", - direction="l", - }, - [0xAB3F]={ - category="ll", - direction="l", - }, - [0xAB40]={ - category="ll", - direction="l", - }, - [0xAB41]={ - category="ll", - direction="l", - }, - [0xAB42]={ - category="ll", - direction="l", - }, - [0xAB43]={ - category="ll", - direction="l", - }, - [0xAB44]={ - category="ll", - direction="l", - }, - [0xAB45]={ - category="ll", - direction="l", - }, - [0xAB46]={ - category="ll", - direction="l", - }, - [0xAB47]={ - category="ll", - direction="l", - }, - [0xAB48]={ - category="ll", - direction="l", - }, - [0xAB49]={ - category="ll", - direction="l", - }, - [0xAB4A]={ - category="ll", - direction="l", - }, - [0xAB4B]={ - category="ll", - direction="l", - }, - [0xAB4C]={ - category="ll", - direction="l", - }, - [0xAB4D]={ - category="ll", - direction="l", - }, - [0xAB4E]={ - category="ll", - direction="l", - }, - [0xAB4F]={ - category="ll", - direction="l", - }, - [0xAB50]={ - category="ll", - direction="l", - }, - [0xAB51]={ - category="ll", - direction="l", - }, - [0xAB52]={ - category="ll", - direction="l", - }, - [0xAB53]={ - category="ll", - direction="l", - }, - [0xAB54]={ - category="ll", - direction="l", - }, - [0xAB55]={ - category="ll", - direction="l", - }, - [0xAB56]={ - category="ll", - direction="l", - }, - [0xAB57]={ - category="ll", - direction="l", - }, - [0xAB58]={ - category="ll", - direction="l", - }, - [0xAB59]={ - category="ll", - direction="l", - }, - [0xAB5A]={ - category="ll", - direction="l", - }, - [0xAB5B]={ - category="sk", - direction="l", - }, - [0xAB5C]={ - category="lm", - direction="l", - }, - [0xAB5D]={ - category="lm", - direction="l", - }, - [0xAB5E]={ - category="lm", - direction="l", - }, - [0xAB5F]={ - category="lm", - direction="l", - }, - [0xAB60]={ - category="ll", - direction="l", - }, - [0xAB61]={ - category="ll", - direction="l", - }, - [0xAB62]={ - category="ll", - direction="l", - }, - [0xAB63]={ - category="ll", - direction="l", - }, - [0xAB64]={ - category="ll", - direction="l", - }, - [0xAB65]={ - category="ll", - direction="l", - }, - [0xAB70]={ - category="ll", - direction="l", - }, - [0xAB71]={ - category="ll", - direction="l", - }, - [0xAB72]={ - category="ll", - direction="l", - }, - [0xAB73]={ - category="ll", - direction="l", - }, - [0xAB74]={ - category="ll", - direction="l", - }, - [0xAB75]={ - category="ll", - direction="l", - }, - [0xAB76]={ - category="ll", - direction="l", - }, - [0xAB77]={ - category="ll", - direction="l", - }, - [0xAB78]={ - category="ll", - direction="l", - }, - [0xAB79]={ - category="ll", - direction="l", - }, - [0xAB7A]={ - category="ll", - direction="l", - }, - [0xAB7B]={ - category="ll", - direction="l", - }, - [0xAB7C]={ - category="ll", - direction="l", - }, - [0xAB7D]={ - category="ll", - direction="l", - }, - [0xAB7E]={ - category="ll", - direction="l", - }, - [0xAB7F]={ - category="ll", - direction="l", - }, - [0xAB80]={ - category="ll", - direction="l", - }, - [0xAB81]={ - category="ll", - direction="l", - }, - [0xAB82]={ - category="ll", - direction="l", - }, - [0xAB83]={ - category="ll", - direction="l", - }, - [0xAB84]={ - category="ll", - direction="l", - }, - [0xAB85]={ - category="ll", - direction="l", - }, - [0xAB86]={ - category="ll", - direction="l", - }, - [0xAB87]={ - category="ll", - direction="l", - }, - [0xAB88]={ - category="ll", - direction="l", - }, - [0xAB89]={ - category="ll", - direction="l", - }, - [0xAB8A]={ - category="ll", - direction="l", - }, - [0xAB8B]={ - category="ll", - direction="l", - }, - [0xAB8C]={ - category="ll", - direction="l", - }, - [0xAB8D]={ - category="ll", - direction="l", - }, - [0xAB8E]={ - category="ll", - direction="l", - }, - [0xAB8F]={ - category="ll", - direction="l", - }, - [0xAB90]={ - category="ll", - direction="l", - }, - [0xAB91]={ - category="ll", - direction="l", - }, - [0xAB92]={ - category="ll", - direction="l", - }, - [0xAB93]={ - category="ll", - direction="l", - }, - [0xAB94]={ - category="ll", - direction="l", - }, - [0xAB95]={ - category="ll", - direction="l", - }, - [0xAB96]={ - category="ll", - direction="l", - }, - [0xAB97]={ - category="ll", - direction="l", - }, - [0xAB98]={ - category="ll", - direction="l", - }, - [0xAB99]={ - category="ll", - direction="l", - }, - [0xAB9A]={ - category="ll", - direction="l", - }, - [0xAB9B]={ - category="ll", - direction="l", - }, - [0xAB9C]={ - category="ll", - direction="l", - }, - [0xAB9D]={ - category="ll", - direction="l", - }, - [0xAB9E]={ - category="ll", - direction="l", - }, - [0xAB9F]={ - category="ll", - direction="l", - }, - [0xABA0]={ - category="ll", - direction="l", - }, - [0xABA1]={ - category="ll", - direction="l", - }, - [0xABA2]={ - category="ll", - direction="l", - }, - [0xABA3]={ - category="ll", - direction="l", - }, - [0xABA4]={ - category="ll", - direction="l", - }, - [0xABA5]={ - category="ll", - direction="l", - }, - [0xABA6]={ - category="ll", - direction="l", - }, - [0xABA7]={ - category="ll", - direction="l", - }, - [0xABA8]={ - category="ll", - direction="l", - }, - [0xABA9]={ - category="ll", - direction="l", - }, - [0xABAA]={ - category="ll", - direction="l", - }, - [0xABAB]={ - category="ll", - direction="l", - }, - [0xABAC]={ - category="ll", - direction="l", - }, - [0xABAD]={ - category="ll", - direction="l", - }, - [0xABAE]={ - category="ll", - direction="l", - }, - [0xABAF]={ - category="ll", - direction="l", - }, - [0xABB0]={ - category="ll", - direction="l", - }, - [0xABB1]={ - category="ll", - direction="l", - }, - [0xABB2]={ - category="ll", - direction="l", - }, - [0xABB3]={ - category="ll", - direction="l", - }, - [0xABB4]={ - category="ll", - direction="l", - }, - [0xABB5]={ - category="ll", - direction="l", - }, - [0xABB6]={ - category="ll", - direction="l", - }, - [0xABB7]={ - category="ll", - direction="l", - }, - [0xABB8]={ - category="ll", - direction="l", - }, - [0xABB9]={ - category="ll", - direction="l", - }, - [0xABBA]={ - category="ll", - direction="l", - }, - [0xABBB]={ - category="ll", - direction="l", - }, - [0xABBC]={ - category="ll", - direction="l", - }, - [0xABBD]={ - category="ll", - direction="l", - }, - [0xABBE]={ - category="ll", - direction="l", - }, - [0xABBF]={ - category="ll", - direction="l", - }, - [0xABC0]={ - category="lo", - direction="l", - }, - [0xABC1]={ - category="lo", - direction="l", - }, - [0xABC2]={ - category="lo", - direction="l", - }, - [0xABC3]={ - category="lo", - direction="l", - }, - [0xABC4]={ - category="lo", - direction="l", - }, - [0xABC5]={ - category="lo", - direction="l", - }, - [0xABC6]={ - category="lo", - direction="l", - }, - [0xABC7]={ - category="lo", - direction="l", - }, - [0xABC8]={ - category="lo", - direction="l", - }, - [0xABC9]={ - category="lo", - direction="l", - }, - [0xABCA]={ - category="lo", - direction="l", - }, - [0xABCB]={ - category="lo", - direction="l", - }, - [0xABCC]={ - category="lo", - direction="l", - }, - [0xABCD]={ - category="lo", - direction="l", - }, - [0xABCE]={ - category="lo", - direction="l", - }, - [0xABCF]={ - category="lo", - direction="l", - }, - [0xABD0]={ - category="lo", - direction="l", - }, - [0xABD1]={ - category="lo", - direction="l", - }, - [0xABD2]={ - category="lo", - direction="l", - }, - [0xABD3]={ - category="lo", - direction="l", - }, - [0xABD4]={ - category="lo", - direction="l", - }, - [0xABD5]={ - category="lo", - direction="l", - }, - [0xABD6]={ - category="lo", - direction="l", - }, - [0xABD7]={ - category="lo", - direction="l", - }, - [0xABD8]={ - category="lo", - direction="l", - }, - [0xABD9]={ - category="lo", - direction="l", - }, - [0xABDA]={ - category="lo", - direction="l", - }, - [0xABDB]={ - category="lo", - direction="l", - }, - [0xABDC]={ - category="lo", - direction="l", - }, - [0xABDD]={ - category="lo", - direction="l", - }, - [0xABDE]={ - category="lo", - direction="l", - }, - [0xABDF]={ - category="lo", - direction="l", - }, - [0xABE0]={ - category="lo", - direction="l", - }, - [0xABE1]={ - category="lo", - direction="l", - }, - [0xABE2]={ - category="lo", - direction="l", - }, - [0xABE3]={ - category="mc", - direction="l", - }, - [0xABE4]={ - category="mc", - direction="l", - }, - [0xABE5]={ - category="mn", - direction="nsm", - }, - [0xABE6]={ - category="mc", - direction="l", - }, - [0xABE7]={ - category="mc", - direction="l", - }, - [0xABE8]={ - category="mn", - direction="nsm", - }, - [0xABE9]={ - category="mc", - direction="l", - }, - [0xABEA]={ - category="mc", - direction="l", - }, - [0xABEB]={ - category="po", - direction="l", - }, - [0xABEC]={ - category="mc", - direction="l", - }, - [0xABED]={ - category="mn", - direction="nsm", - }, - [0xABF0]={ - category="nd", - direction="l", - }, - [0xABF1]={ - category="nd", - direction="l", - }, - [0xABF2]={ - category="nd", - direction="l", - }, - [0xABF3]={ - category="nd", - direction="l", - }, - [0xABF4]={ - category="nd", - direction="l", - }, - [0xABF5]={ - category="nd", - direction="l", - }, - [0xABF6]={ - category="nd", - direction="l", - }, - [0xABF7]={ - category="nd", - direction="l", - }, - [0xABF8]={ - category="nd", - direction="l", - }, - [0xABF9]={ - category="nd", - direction="l", - }, - [0xD7B0]={ - category="lo", - direction="l", - }, - [0xD7B1]={ - category="lo", - direction="l", - }, - [0xD7B2]={ - category="lo", - direction="l", - }, - [0xD7B3]={ - category="lo", - direction="l", - }, - [0xD7B4]={ - category="lo", - direction="l", - }, - [0xD7B5]={ - category="lo", - direction="l", - }, - [0xD7B6]={ - category="lo", - direction="l", - }, - [0xD7B7]={ - category="lo", - direction="l", - }, - [0xD7B8]={ - category="lo", - direction="l", - }, - [0xD7B9]={ - category="lo", - direction="l", - }, - [0xD7BA]={ - category="lo", - direction="l", - }, - [0xD7BB]={ - category="lo", - direction="l", - }, - [0xD7BC]={ - category="lo", - direction="l", - }, - [0xD7BD]={ - category="lo", - direction="l", - }, - [0xD7BE]={ - category="lo", - direction="l", - }, - [0xD7BF]={ - category="lo", - direction="l", - }, - [0xD7C0]={ - category="lo", - direction="l", - }, - [0xD7C1]={ - category="lo", - direction="l", - }, - [0xD7C2]={ - category="lo", - direction="l", - }, - [0xD7C3]={ - category="lo", - direction="l", - }, - [0xD7C4]={ - category="lo", - direction="l", - }, - [0xD7C5]={ - category="lo", - direction="l", - }, - [0xD7C6]={ - category="lo", - direction="l", - }, - [0xD7CB]={ - category="lo", - direction="l", - }, - [0xD7CC]={ - category="lo", - direction="l", - }, - [0xD7CD]={ - category="lo", - direction="l", - }, - [0xD7CE]={ - category="lo", - direction="l", - }, - [0xD7CF]={ - category="lo", - direction="l", - }, - [0xD7D0]={ - category="lo", - direction="l", - }, - [0xD7D1]={ - category="lo", - direction="l", - }, - [0xD7D2]={ - category="lo", - direction="l", - }, - [0xD7D3]={ - category="lo", - direction="l", - }, - [0xD7D4]={ - category="lo", - direction="l", - }, - [0xD7D5]={ - category="lo", - direction="l", - }, - [0xD7D6]={ - category="lo", - direction="l", - }, - [0xD7D7]={ - category="lo", - direction="l", - }, - [0xD7D8]={ - category="lo", - direction="l", - }, - [0xD7D9]={ - category="lo", - direction="l", - }, - [0xD7DA]={ - category="lo", - direction="l", - }, - [0xD7DB]={ - category="lo", - direction="l", - }, - [0xD7DC]={ - category="lo", - direction="l", - }, - [0xD7DD]={ - category="lo", - direction="l", - }, - [0xD7DE]={ - category="lo", - direction="l", - }, - [0xD7DF]={ - category="lo", - direction="l", - }, - [0xD7E0]={ - category="lo", - direction="l", - }, - [0xD7E1]={ - category="lo", - direction="l", - }, - [0xD7E2]={ - category="lo", - direction="l", - }, - [0xD7E3]={ - category="lo", - direction="l", - }, - [0xD7E4]={ - category="lo", - direction="l", - }, - [0xD7E5]={ - category="lo", - direction="l", - }, - [0xD7E6]={ - category="lo", - direction="l", - }, - [0xD7E7]={ - category="lo", - direction="l", - }, - [0xD7E8]={ - category="lo", - direction="l", - }, - [0xD7E9]={ - category="lo", - direction="l", - }, - [0xD7EA]={ - category="lo", - direction="l", - }, - [0xD7EB]={ - category="lo", - direction="l", - }, - [0xD7EC]={ - category="lo", - direction="l", - }, - [0xD7ED]={ - category="lo", - direction="l", - }, - [0xD7EE]={ - category="lo", - direction="l", - }, - [0xD7EF]={ - category="lo", - direction="l", - }, - [0xD7F0]={ - category="lo", - direction="l", - }, - [0xD7F1]={ - category="lo", - direction="l", - }, - [0xD7F2]={ - category="lo", - direction="l", - }, - [0xD7F3]={ - category="lo", - direction="l", - }, - [0xD7F4]={ - category="lo", - direction="l", - }, - [0xD7F5]={ - category="lo", - direction="l", - }, - [0xD7F6]={ - category="lo", - direction="l", - }, - [0xD7F7]={ - category="lo", - direction="l", - }, - [0xD7F8]={ - category="lo", - direction="l", - }, - [0xD7F9]={ - category="lo", - direction="l", - }, - [0xD7FA]={ - category="lo", - direction="l", - }, - [0xD7FB]={ - category="lo", - direction="l", - }, - [0xD800]={ - category="cs", - direction="l", - }, - [0xDB7F]={ - category="cs", - direction="l", - }, - [0xDB80]={ - category="cs", - direction="l", - }, - [0xDBFF]={ - category="cs", - direction="l", - }, - [0xDC00]={ - category="cs", - direction="l", - }, - [0xDFFF]={ - category="cs", - direction="l", - }, - [0xE000]={ - category="co", - direction="l", - }, - [0xF8FF]={ - category="co", - direction="l", - }, - [0xF900]={ - category="lo", - direction="l", - }, - [0xF901]={ - category="lo", - direction="l", - }, - [0xF902]={ - category="lo", - direction="l", - }, - [0xF903]={ - category="lo", - direction="l", - }, - [0xF904]={ - category="lo", - direction="l", - }, - [0xF905]={ - category="lo", - direction="l", - }, - [0xF906]={ - category="lo", - direction="l", - }, - [0xF907]={ - category="lo", - direction="l", - }, - [0xF908]={ - category="lo", - direction="l", - }, - [0xF909]={ - category="lo", - direction="l", - }, - [0xF90A]={ - category="lo", - direction="l", - }, - [0xF90B]={ - category="lo", - direction="l", - }, - [0xF90C]={ - category="lo", - direction="l", - }, - [0xF90D]={ - category="lo", - direction="l", - }, - [0xF90E]={ - category="lo", - direction="l", - }, - [0xF90F]={ - category="lo", - direction="l", - }, - [0xF910]={ - category="lo", - direction="l", - }, - [0xF911]={ - category="lo", - direction="l", - }, - [0xF912]={ - category="lo", - direction="l", - }, - [0xF913]={ - category="lo", - direction="l", - }, - [0xF914]={ - category="lo", - direction="l", - }, - [0xF915]={ - category="lo", - direction="l", - }, - [0xF916]={ - category="lo", - direction="l", - }, - [0xF917]={ - category="lo", - direction="l", - }, - [0xF918]={ - category="lo", - direction="l", - }, - [0xF919]={ - category="lo", - direction="l", - }, - [0xF91A]={ - category="lo", - direction="l", - }, - [0xF91B]={ - category="lo", - direction="l", - }, - [0xF91C]={ - category="lo", - direction="l", - }, - [0xF91D]={ - category="lo", - direction="l", - }, - [0xF91E]={ - category="lo", - direction="l", - }, - [0xF91F]={ - category="lo", - direction="l", - }, - [0xF920]={ - category="lo", - direction="l", - }, - [0xF921]={ - category="lo", - direction="l", - }, - [0xF922]={ - category="lo", - direction="l", - }, - [0xF923]={ - category="lo", - direction="l", - }, - [0xF924]={ - category="lo", - direction="l", - }, - [0xF925]={ - category="lo", - direction="l", - }, - [0xF926]={ - category="lo", - direction="l", - }, - [0xF927]={ - category="lo", - direction="l", - }, - [0xF928]={ - category="lo", - direction="l", - }, - [0xF929]={ - category="lo", - direction="l", - }, - [0xF92A]={ - category="lo", - direction="l", - }, - [0xF92B]={ - category="lo", - direction="l", - }, - [0xF92C]={ - category="lo", - direction="l", - }, - [0xF92D]={ - category="lo", - direction="l", - }, - [0xF92E]={ - category="lo", - direction="l", - }, - [0xF92F]={ - category="lo", - direction="l", - }, - [0xF930]={ - category="lo", - direction="l", - }, - [0xF931]={ - category="lo", - direction="l", - }, - [0xF932]={ - category="lo", - direction="l", - }, - [0xF933]={ - category="lo", - direction="l", - }, - [0xF934]={ - category="lo", - direction="l", - }, - [0xF935]={ - category="lo", - direction="l", - }, - [0xF936]={ - category="lo", - direction="l", - }, - [0xF937]={ - category="lo", - direction="l", - }, - [0xF938]={ - category="lo", - direction="l", - }, - [0xF939]={ - category="lo", - direction="l", - }, - [0xF93A]={ - category="lo", - direction="l", - }, - [0xF93B]={ - category="lo", - direction="l", - }, - [0xF93C]={ - category="lo", - direction="l", - }, - [0xF93D]={ - category="lo", - direction="l", - }, - [0xF93E]={ - category="lo", - direction="l", - }, - [0xF93F]={ - category="lo", - direction="l", - }, - [0xF940]={ - category="lo", - direction="l", - }, - [0xF941]={ - category="lo", - direction="l", - }, - [0xF942]={ - category="lo", - direction="l", - }, - [0xF943]={ - category="lo", - direction="l", - }, - [0xF944]={ - category="lo", - direction="l", - }, - [0xF945]={ - category="lo", - direction="l", - }, - [0xF946]={ - category="lo", - direction="l", - }, - [0xF947]={ - category="lo", - direction="l", - }, - [0xF948]={ - category="lo", - direction="l", - }, - [0xF949]={ - category="lo", - direction="l", - }, - [0xF94A]={ - category="lo", - direction="l", - }, - [0xF94B]={ - category="lo", - direction="l", - }, - [0xF94C]={ - category="lo", - direction="l", - }, - [0xF94D]={ - category="lo", - direction="l", - }, - [0xF94E]={ - category="lo", - direction="l", - }, - [0xF94F]={ - category="lo", - direction="l", - }, - [0xF950]={ - category="lo", - direction="l", - }, - [0xF951]={ - category="lo", - direction="l", - }, - [0xF952]={ - category="lo", - direction="l", - }, - [0xF953]={ - category="lo", - direction="l", - }, - [0xF954]={ - category="lo", - direction="l", - }, - [0xF955]={ - category="lo", - direction="l", - }, - [0xF956]={ - category="lo", - direction="l", - }, - [0xF957]={ - category="lo", - direction="l", - }, - [0xF958]={ - category="lo", - direction="l", - }, - [0xF959]={ - category="lo", - direction="l", - }, - [0xF95A]={ - category="lo", - direction="l", - }, - [0xF95B]={ - category="lo", - direction="l", - }, - [0xF95C]={ - category="lo", - direction="l", - }, - [0xF95D]={ - category="lo", - direction="l", - }, - [0xF95E]={ - category="lo", - direction="l", - }, - [0xF95F]={ - category="lo", - direction="l", - }, - [0xF960]={ - category="lo", - direction="l", - }, - [0xF961]={ - category="lo", - direction="l", - }, - [0xF962]={ - category="lo", - direction="l", - }, - [0xF963]={ - category="lo", - direction="l", - }, - [0xF964]={ - category="lo", - direction="l", - }, - [0xF965]={ - category="lo", - direction="l", - }, - [0xF966]={ - category="lo", - direction="l", - }, - [0xF967]={ - category="lo", - direction="l", - }, - [0xF968]={ - category="lo", - direction="l", - }, - [0xF969]={ - category="lo", - direction="l", - }, - [0xF96A]={ - category="lo", - direction="l", - }, - [0xF96B]={ - category="lo", - direction="l", - }, - [0xF96C]={ - category="lo", - direction="l", - }, - [0xF96D]={ - category="lo", - direction="l", - }, - [0xF96E]={ - category="lo", - direction="l", - }, - [0xF96F]={ - category="lo", - direction="l", - }, - [0xF970]={ - category="lo", - direction="l", - }, - [0xF971]={ - category="lo", - direction="l", - }, - [0xF972]={ - category="lo", - direction="l", - }, - [0xF973]={ - category="lo", - direction="l", - }, - [0xF974]={ - category="lo", - direction="l", - }, - [0xF975]={ - category="lo", - direction="l", - }, - [0xF976]={ - category="lo", - direction="l", - }, - [0xF977]={ - category="lo", - direction="l", - }, - [0xF978]={ - category="lo", - direction="l", - }, - [0xF979]={ - category="lo", - direction="l", - }, - [0xF97A]={ - category="lo", - direction="l", - }, - [0xF97B]={ - category="lo", - direction="l", - }, - [0xF97C]={ - category="lo", - direction="l", - }, - [0xF97D]={ - category="lo", - direction="l", - }, - [0xF97E]={ - category="lo", - direction="l", - }, - [0xF97F]={ - category="lo", - direction="l", - }, - [0xF980]={ - category="lo", - direction="l", - }, - [0xF981]={ - category="lo", - direction="l", - }, - [0xF982]={ - category="lo", - direction="l", - }, - [0xF983]={ - category="lo", - direction="l", - }, - [0xF984]={ - category="lo", - direction="l", - }, - [0xF985]={ - category="lo", - direction="l", - }, - [0xF986]={ - category="lo", - direction="l", - }, - [0xF987]={ - category="lo", - direction="l", - }, - [0xF988]={ - category="lo", - direction="l", - }, - [0xF989]={ - category="lo", - direction="l", - }, - [0xF98A]={ - category="lo", - direction="l", - }, - [0xF98B]={ - category="lo", - direction="l", - }, - [0xF98C]={ - category="lo", - direction="l", - }, - [0xF98D]={ - category="lo", - direction="l", - }, - [0xF98E]={ - category="lo", - direction="l", - }, - [0xF98F]={ - category="lo", - direction="l", - }, - [0xF990]={ - category="lo", - direction="l", - }, - [0xF991]={ - category="lo", - direction="l", - }, - [0xF992]={ - category="lo", - direction="l", - }, - [0xF993]={ - category="lo", - direction="l", - }, - [0xF994]={ - category="lo", - direction="l", - }, - [0xF995]={ - category="lo", - direction="l", - }, - [0xF996]={ - category="lo", - direction="l", - }, - [0xF997]={ - category="lo", - direction="l", - }, - [0xF998]={ - category="lo", - direction="l", - }, - [0xF999]={ - category="lo", - direction="l", - }, - [0xF99A]={ - category="lo", - direction="l", - }, - [0xF99B]={ - category="lo", - direction="l", - }, - [0xF99C]={ - category="lo", - direction="l", - }, - [0xF99D]={ - category="lo", - direction="l", - }, - [0xF99E]={ - category="lo", - direction="l", - }, - [0xF99F]={ - category="lo", - direction="l", - }, - [0xF9A0]={ - category="lo", - direction="l", - }, - [0xF9A1]={ - category="lo", - direction="l", - }, - [0xF9A2]={ - category="lo", - direction="l", - }, - [0xF9A3]={ - category="lo", - direction="l", - }, - [0xF9A4]={ - category="lo", - direction="l", - }, - [0xF9A5]={ - category="lo", - direction="l", - }, - [0xF9A6]={ - category="lo", - direction="l", - }, - [0xF9A7]={ - category="lo", - direction="l", - }, - [0xF9A8]={ - category="lo", - direction="l", - }, - [0xF9A9]={ - category="lo", - direction="l", - }, - [0xF9AA]={ - category="lo", - direction="l", - }, - [0xF9AB]={ - category="lo", - direction="l", - }, - [0xF9AC]={ - category="lo", - direction="l", - }, - [0xF9AD]={ - category="lo", - direction="l", - }, - [0xF9AE]={ - category="lo", - direction="l", - }, - [0xF9AF]={ - category="lo", - direction="l", - }, - [0xF9B0]={ - category="lo", - direction="l", - }, - [0xF9B1]={ - category="lo", - direction="l", - }, - [0xF9B2]={ - category="lo", - direction="l", - }, - [0xF9B3]={ - category="lo", - direction="l", - }, - [0xF9B4]={ - category="lo", - direction="l", - }, - [0xF9B5]={ - category="lo", - direction="l", - }, - [0xF9B6]={ - category="lo", - direction="l", - }, - [0xF9B7]={ - category="lo", - direction="l", - }, - [0xF9B8]={ - category="lo", - direction="l", - }, - [0xF9B9]={ - category="lo", - direction="l", - }, - [0xF9BA]={ - category="lo", - direction="l", - }, - [0xF9BB]={ - category="lo", - direction="l", - }, - [0xF9BC]={ - category="lo", - direction="l", - }, - [0xF9BD]={ - category="lo", - direction="l", - }, - [0xF9BE]={ - category="lo", - direction="l", - }, - [0xF9BF]={ - category="lo", - direction="l", - }, - [0xF9C0]={ - category="lo", - direction="l", - }, - [0xF9C1]={ - category="lo", - direction="l", - }, - [0xF9C2]={ - category="lo", - direction="l", - }, - [0xF9C3]={ - category="lo", - direction="l", - }, - [0xF9C4]={ - category="lo", - direction="l", - }, - [0xF9C5]={ - category="lo", - direction="l", - }, - [0xF9C6]={ - category="lo", - direction="l", - }, - [0xF9C7]={ - category="lo", - direction="l", - }, - [0xF9C8]={ - category="lo", - direction="l", - }, - [0xF9C9]={ - category="lo", - direction="l", - }, - [0xF9CA]={ - category="lo", - direction="l", - }, - [0xF9CB]={ - category="lo", - direction="l", - }, - [0xF9CC]={ - category="lo", - direction="l", - }, - [0xF9CD]={ - category="lo", - direction="l", - }, - [0xF9CE]={ - category="lo", - direction="l", - }, - [0xF9CF]={ - category="lo", - direction="l", - }, - [0xF9D0]={ - category="lo", - direction="l", - }, - [0xF9D1]={ - category="lo", - direction="l", - }, - [0xF9D2]={ - category="lo", - direction="l", - }, - [0xF9D3]={ - category="lo", - direction="l", - }, - [0xF9D4]={ - category="lo", - direction="l", - }, - [0xF9D5]={ - category="lo", - direction="l", - }, - [0xF9D6]={ - category="lo", - direction="l", - }, - [0xF9D7]={ - category="lo", - direction="l", - }, - [0xF9D8]={ - category="lo", - direction="l", - }, - [0xF9D9]={ - category="lo", - direction="l", - }, - [0xF9DA]={ - category="lo", - direction="l", - }, - [0xF9DB]={ - category="lo", - direction="l", - }, - [0xF9DC]={ - category="lo", - direction="l", - }, - [0xF9DD]={ - category="lo", - direction="l", - }, - [0xF9DE]={ - category="lo", - direction="l", - }, - [0xF9DF]={ - category="lo", - direction="l", - }, - [0xF9E0]={ - category="lo", - direction="l", - }, - [0xF9E1]={ - category="lo", - direction="l", - }, - [0xF9E2]={ - category="lo", - direction="l", - }, - [0xF9E3]={ - category="lo", - direction="l", - }, - [0xF9E4]={ - category="lo", - direction="l", - }, - [0xF9E5]={ - category="lo", - direction="l", - }, - [0xF9E6]={ - category="lo", - direction="l", - }, - [0xF9E7]={ - category="lo", - direction="l", - }, - [0xF9E8]={ - category="lo", - direction="l", - }, - [0xF9E9]={ - category="lo", - direction="l", - }, - [0xF9EA]={ - category="lo", - direction="l", - }, - [0xF9EB]={ - category="lo", - direction="l", - }, - [0xF9EC]={ - category="lo", - direction="l", - }, - [0xF9ED]={ - category="lo", - direction="l", - }, - [0xF9EE]={ - category="lo", - direction="l", - }, - [0xF9EF]={ - category="lo", - direction="l", - }, - [0xF9F0]={ - category="lo", - direction="l", - }, - [0xF9F1]={ - category="lo", - direction="l", - }, - [0xF9F2]={ - category="lo", - direction="l", - }, - [0xF9F3]={ - category="lo", - direction="l", - }, - [0xF9F4]={ - category="lo", - direction="l", - }, - [0xF9F5]={ - category="lo", - direction="l", - }, - [0xF9F6]={ - category="lo", - direction="l", - }, - [0xF9F7]={ - category="lo", - direction="l", - }, - [0xF9F8]={ - category="lo", - direction="l", - }, - [0xF9F9]={ - category="lo", - direction="l", - }, - [0xF9FA]={ - category="lo", - direction="l", - }, - [0xF9FB]={ - category="lo", - direction="l", - }, - [0xF9FC]={ - category="lo", - direction="l", - }, - [0xF9FD]={ - category="lo", - direction="l", - }, - [0xF9FE]={ - category="lo", - direction="l", - }, - [0xF9FF]={ - category="lo", - direction="l", - }, - [0xFA00]={ - category="lo", - direction="l", - }, - [0xFA01]={ - category="lo", - direction="l", - }, - [0xFA02]={ - category="lo", - direction="l", - }, - [0xFA03]={ - category="lo", - direction="l", - }, - [0xFA04]={ - category="lo", - direction="l", - }, - [0xFA05]={ - category="lo", - direction="l", - }, - [0xFA06]={ - category="lo", - direction="l", - }, - [0xFA07]={ - category="lo", - direction="l", - }, - [0xFA08]={ - category="lo", - direction="l", - }, - [0xFA09]={ - category="lo", - direction="l", - }, - [0xFA0A]={ - category="lo", - direction="l", - }, - [0xFA0B]={ - category="lo", - direction="l", - }, - [0xFA0C]={ - category="lo", - direction="l", - }, - [0xFA0D]={ - category="lo", - direction="l", - }, - [0xFA0E]={ - category="lo", - direction="l", - }, - [0xFA0F]={ - category="lo", - direction="l", - }, - [0xFA10]={ - category="lo", - direction="l", - }, - [0xFA11]={ - category="lo", - direction="l", - }, - [0xFA12]={ - category="lo", - direction="l", - }, - [0xFA13]={ - category="lo", - direction="l", - }, - [0xFA14]={ - category="lo", - direction="l", - }, - [0xFA15]={ - category="lo", - direction="l", - }, - [0xFA16]={ - category="lo", - direction="l", - }, - [0xFA17]={ - category="lo", - direction="l", - }, - [0xFA18]={ - category="lo", - direction="l", - }, - [0xFA19]={ - category="lo", - direction="l", - }, - [0xFA1A]={ - category="lo", - direction="l", - }, - [0xFA1B]={ - category="lo", - direction="l", - }, - [0xFA1C]={ - category="lo", - direction="l", - }, - [0xFA1D]={ - category="lo", - direction="l", - }, - [0xFA1E]={ - category="lo", - direction="l", - }, - [0xFA1F]={ - category="lo", - direction="l", - }, - [0xFA20]={ - category="lo", - direction="l", - }, - [0xFA21]={ - category="lo", - direction="l", - }, - [0xFA22]={ - category="lo", - direction="l", - }, - [0xFA23]={ - category="lo", - direction="l", - }, - [0xFA24]={ - category="lo", - direction="l", - }, - [0xFA25]={ - category="lo", - direction="l", - }, - [0xFA26]={ - category="lo", - direction="l", - }, - [0xFA27]={ - category="lo", - direction="l", - }, - [0xFA28]={ - category="lo", - direction="l", - }, - [0xFA29]={ - category="lo", - direction="l", - }, - [0xFA2A]={ - category="lo", - direction="l", - }, - [0xFA2B]={ - category="lo", - direction="l", - }, - [0xFA2C]={ - category="lo", - direction="l", - }, - [0xFA2D]={ - category="lo", - direction="l", - }, - [0xFA2E]={ - category="lo", - direction="l", - }, - [0xFA2F]={ - category="lo", - direction="l", - }, - [0xFA30]={ - category="lo", - direction="l", - }, - [0xFA31]={ - category="lo", - direction="l", - }, - [0xFA32]={ - category="lo", - direction="l", - }, - [0xFA33]={ - category="lo", - direction="l", - }, - [0xFA34]={ - category="lo", - direction="l", - }, - [0xFA35]={ - category="lo", - direction="l", - }, - [0xFA36]={ - category="lo", - direction="l", - }, - [0xFA37]={ - category="lo", - direction="l", - }, - [0xFA38]={ - category="lo", - direction="l", - }, - [0xFA39]={ - category="lo", - direction="l", - }, - [0xFA3A]={ - category="lo", - direction="l", - }, - [0xFA3B]={ - category="lo", - direction="l", - }, - [0xFA3C]={ - category="lo", - direction="l", - }, - [0xFA3D]={ - category="lo", - direction="l", - }, - [0xFA3E]={ - category="lo", - direction="l", - }, - [0xFA3F]={ - category="lo", - direction="l", - }, - [0xFA40]={ - category="lo", - direction="l", - }, - [0xFA41]={ - category="lo", - direction="l", - }, - [0xFA42]={ - category="lo", - direction="l", - }, - [0xFA43]={ - category="lo", - direction="l", - }, - [0xFA44]={ - category="lo", - direction="l", - }, - [0xFA45]={ - category="lo", - direction="l", - }, - [0xFA46]={ - category="lo", - direction="l", - }, - [0xFA47]={ - category="lo", - direction="l", - }, - [0xFA48]={ - category="lo", - direction="l", - }, - [0xFA49]={ - category="lo", - direction="l", - }, - [0xFA4A]={ - category="lo", - direction="l", - }, - [0xFA4B]={ - category="lo", - direction="l", - }, - [0xFA4C]={ - category="lo", - direction="l", - }, - [0xFA4D]={ - category="lo", - direction="l", - }, - [0xFA4E]={ - category="lo", - direction="l", - }, - [0xFA4F]={ - category="lo", - direction="l", - }, - [0xFA50]={ - category="lo", - direction="l", - }, - [0xFA51]={ - category="lo", - direction="l", - }, - [0xFA52]={ - category="lo", - direction="l", - }, - [0xFA53]={ - category="lo", - direction="l", - }, - [0xFA54]={ - category="lo", - direction="l", - }, - [0xFA55]={ - category="lo", - direction="l", - }, - [0xFA56]={ - category="lo", - direction="l", - }, - [0xFA57]={ - category="lo", - direction="l", - }, - [0xFA58]={ - category="lo", - direction="l", - }, - [0xFA59]={ - category="lo", - direction="l", - }, - [0xFA5A]={ - category="lo", - direction="l", - }, - [0xFA5B]={ - category="lo", - direction="l", - }, - [0xFA5C]={ - category="lo", - direction="l", - }, - [0xFA5D]={ - category="lo", - direction="l", - }, - [0xFA5E]={ - category="lo", - direction="l", - }, - [0xFA5F]={ - category="lo", - direction="l", - }, - [0xFA60]={ - category="lo", - direction="l", - }, - [0xFA61]={ - category="lo", - direction="l", - }, - [0xFA62]={ - category="lo", - direction="l", - }, - [0xFA63]={ - category="lo", - direction="l", - }, - [0xFA64]={ - category="lo", - direction="l", - }, - [0xFA65]={ - category="lo", - direction="l", - }, - [0xFA66]={ - category="lo", - direction="l", - }, - [0xFA67]={ - category="lo", - direction="l", - }, - [0xFA68]={ - category="lo", - direction="l", - }, - [0xFA69]={ - category="lo", - direction="l", - }, - [0xFA6A]={ - category="lo", - direction="l", - }, - [0xFA6B]={ - category="lo", - direction="l", - }, - [0xFA6C]={ - category="lo", - direction="l", - }, - [0xFA6D]={ - category="lo", - direction="l", - }, - [0xFA70]={ - category="lo", - direction="l", - }, - [0xFA71]={ - category="lo", - direction="l", - }, - [0xFA72]={ - category="lo", - direction="l", - }, - [0xFA73]={ - category="lo", - direction="l", - }, - [0xFA74]={ - category="lo", - direction="l", - }, - [0xFA75]={ - category="lo", - direction="l", - }, - [0xFA76]={ - category="lo", - direction="l", - }, - [0xFA77]={ - category="lo", - direction="l", - }, - [0xFA78]={ - category="lo", - direction="l", - }, - [0xFA79]={ - category="lo", - direction="l", - }, - [0xFA7A]={ - category="lo", - direction="l", - }, - [0xFA7B]={ - category="lo", - direction="l", - }, - [0xFA7C]={ - category="lo", - direction="l", - }, - [0xFA7D]={ - category="lo", - direction="l", - }, - [0xFA7E]={ - category="lo", - direction="l", - }, - [0xFA7F]={ - category="lo", - direction="l", - }, - [0xFA80]={ - category="lo", - direction="l", - }, - [0xFA81]={ - category="lo", - direction="l", - }, - [0xFA82]={ - category="lo", - direction="l", - }, - [0xFA83]={ - category="lo", - direction="l", - }, - [0xFA84]={ - category="lo", - direction="l", - }, - [0xFA85]={ - category="lo", - direction="l", - }, - [0xFA86]={ - category="lo", - direction="l", - }, - [0xFA87]={ - category="lo", - direction="l", - }, - [0xFA88]={ - category="lo", - direction="l", - }, - [0xFA89]={ - category="lo", - direction="l", - }, - [0xFA8A]={ - category="lo", - direction="l", - }, - [0xFA8B]={ - category="lo", - direction="l", - }, - [0xFA8C]={ - category="lo", - direction="l", - }, - [0xFA8D]={ - category="lo", - direction="l", - }, - [0xFA8E]={ - category="lo", - direction="l", - }, - [0xFA8F]={ - category="lo", - direction="l", - }, - [0xFA90]={ - category="lo", - direction="l", - }, - [0xFA91]={ - category="lo", - direction="l", - }, - [0xFA92]={ - category="lo", - direction="l", - }, - [0xFA93]={ - category="lo", - direction="l", - }, - [0xFA94]={ - category="lo", - direction="l", - }, - [0xFA95]={ - category="lo", - direction="l", - }, - [0xFA96]={ - category="lo", - direction="l", - }, - [0xFA97]={ - category="lo", - direction="l", - }, - [0xFA98]={ - category="lo", - direction="l", - }, - [0xFA99]={ - category="lo", - direction="l", - }, - [0xFA9A]={ - category="lo", - direction="l", - }, - [0xFA9B]={ - category="lo", - direction="l", - }, - [0xFA9C]={ - category="lo", - direction="l", - }, - [0xFA9D]={ - category="lo", - direction="l", - }, - [0xFA9E]={ - category="lo", - direction="l", - }, - [0xFA9F]={ - category="lo", - direction="l", - }, - [0xFAA0]={ - category="lo", - direction="l", - }, - [0xFAA1]={ - category="lo", - direction="l", - }, - [0xFAA2]={ - category="lo", - direction="l", - }, - [0xFAA3]={ - category="lo", - direction="l", - }, - [0xFAA4]={ - category="lo", - direction="l", - }, - [0xFAA5]={ - category="lo", - direction="l", - }, - [0xFAA6]={ - category="lo", - direction="l", - }, - [0xFAA7]={ - category="lo", - direction="l", - }, - [0xFAA8]={ - category="lo", - direction="l", - }, - [0xFAA9]={ - category="lo", - direction="l", - }, - [0xFAAA]={ - category="lo", - direction="l", - }, - [0xFAAB]={ - category="lo", - direction="l", - }, - [0xFAAC]={ - category="lo", - direction="l", - }, - [0xFAAD]={ - category="lo", - direction="l", - }, - [0xFAAE]={ - category="lo", - direction="l", - }, - [0xFAAF]={ - category="lo", - direction="l", - }, - [0xFAB0]={ - category="lo", - direction="l", - }, - [0xFAB1]={ - category="lo", - direction="l", - }, - [0xFAB2]={ - category="lo", - direction="l", - }, - [0xFAB3]={ - category="lo", - direction="l", - }, - [0xFAB4]={ - category="lo", - direction="l", - }, - [0xFAB5]={ - category="lo", - direction="l", - }, - [0xFAB6]={ - category="lo", - direction="l", - }, - [0xFAB7]={ - category="lo", - direction="l", - }, - [0xFAB8]={ - category="lo", - direction="l", - }, - [0xFAB9]={ - category="lo", - direction="l", - }, - [0xFABA]={ - category="lo", - direction="l", - }, - [0xFABB]={ - category="lo", - direction="l", - }, - [0xFABC]={ - category="lo", - direction="l", - }, - [0xFABD]={ - category="lo", - direction="l", - }, - [0xFABE]={ - category="lo", - direction="l", - }, - [0xFABF]={ - category="lo", - direction="l", - }, - [0xFAC0]={ - category="lo", - direction="l", - }, - [0xFAC1]={ - category="lo", - direction="l", - }, - [0xFAC2]={ - category="lo", - direction="l", - }, - [0xFAC3]={ - category="lo", - direction="l", - }, - [0xFAC4]={ - category="lo", - direction="l", - }, - [0xFAC5]={ - category="lo", - direction="l", - }, - [0xFAC6]={ - category="lo", - direction="l", - }, - [0xFAC7]={ - category="lo", - direction="l", - }, - [0xFAC8]={ - category="lo", - direction="l", - }, - [0xFAC9]={ - category="lo", - direction="l", - }, - [0xFACA]={ - category="lo", - direction="l", - }, - [0xFACB]={ - category="lo", - direction="l", - }, - [0xFACC]={ - category="lo", - direction="l", - }, - [0xFACD]={ - category="lo", - direction="l", - }, - [0xFACE]={ - category="lo", - direction="l", - }, - [0xFACF]={ - category="lo", - direction="l", - }, - [0xFAD0]={ - category="lo", - direction="l", - }, - [0xFAD1]={ - category="lo", - direction="l", - }, - [0xFAD2]={ - category="lo", - direction="l", - }, - [0xFAD3]={ - category="lo", - direction="l", - }, - [0xFAD4]={ - category="lo", - direction="l", - }, - [0xFAD5]={ - category="lo", - direction="l", - }, - [0xFAD6]={ - category="lo", - direction="l", - }, - [0xFAD7]={ - category="lo", - direction="l", - }, - [0xFAD8]={ - category="lo", - direction="l", - }, - [0xFAD9]={ - category="lo", - direction="l", - }, - [0xFB00]={ - category="ll", - direction="l", - }, - [0xFB01]={ - category="ll", - direction="l", - }, - [0xFB02]={ - category="ll", - direction="l", - }, - [0xFB03]={ - category="ll", - direction="l", - }, - [0xFB04]={ - category="ll", - direction="l", - }, - [0xFB05]={ - category="ll", - direction="l", - }, - [0xFB06]={ - category="ll", - direction="l", - }, - [0xFB13]={ - category="ll", - direction="l", - }, - [0xFB14]={ - category="ll", - direction="l", - }, - [0xFB15]={ - category="ll", - direction="l", - }, - [0xFB16]={ - category="ll", - direction="l", - }, - [0xFB17]={ - category="ll", - direction="l", - }, - [0xFB1D]={ - category="lo", - direction="r", - }, - [0xFB1E]={ - category="mn", - direction="nsm", - }, - [0xFB1F]={ - category="lo", - direction="r", - }, - [0xFB20]={ - category="lo", - direction="r", - }, - [0xFB21]={ - category="lo", - direction="r", - }, - [0xFB22]={ - category="lo", - direction="r", - }, - [0xFB23]={ - category="lo", - direction="r", - }, - [0xFB24]={ - category="lo", - direction="r", - }, - [0xFB25]={ - category="lo", - direction="r", - }, - [0xFB26]={ - category="lo", - direction="r", - }, - [0xFB27]={ - category="lo", - direction="r", - }, - [0xFB28]={ - category="lo", - direction="r", - }, - [0xFB29]={ - category="sm", - direction="es", - }, - [0xFB2A]={ - category="lo", - direction="r", - }, - [0xFB2B]={ - category="lo", - direction="r", - }, - [0xFB2C]={ - category="lo", - direction="r", - }, - [0xFB2D]={ - category="lo", - direction="r", - }, - [0xFB2E]={ - category="lo", - direction="r", - }, - [0xFB2F]={ - category="lo", - direction="r", - }, - [0xFB30]={ - category="lo", - direction="r", - }, - [0xFB31]={ - category="lo", - direction="r", - }, - [0xFB32]={ - category="lo", - direction="r", - }, - [0xFB33]={ - category="lo", - direction="r", - }, - [0xFB34]={ - category="lo", - direction="r", - }, - [0xFB35]={ - category="lo", - direction="r", - }, - [0xFB36]={ - category="lo", - direction="r", - }, - [0xFB38]={ - category="lo", - direction="r", - }, - [0xFB39]={ - category="lo", - direction="r", - }, - [0xFB3A]={ - category="lo", - direction="r", - }, - [0xFB3B]={ - category="lo", - direction="r", - }, - [0xFB3C]={ - category="lo", - direction="r", - }, - [0xFB3E]={ - category="lo", - direction="r", - }, - [0xFB40]={ - category="lo", - direction="r", - }, - [0xFB41]={ - category="lo", - direction="r", - }, - [0xFB43]={ - category="lo", - direction="r", - }, - [0xFB44]={ - category="lo", - direction="r", - }, - [0xFB46]={ - category="lo", - direction="r", - }, - [0xFB47]={ - category="lo", - direction="r", - }, - [0xFB48]={ - category="lo", - direction="r", - }, - [0xFB49]={ - category="lo", - direction="r", - }, - [0xFB4A]={ - category="lo", - direction="r", - }, - [0xFB4B]={ - category="lo", - direction="r", - }, - [0xFB4C]={ - category="lo", - direction="r", - }, - [0xFB4D]={ - category="lo", - direction="r", - }, - [0xFB4E]={ - category="lo", - direction="r", - }, - [0xFB4F]={ - category="lo", - direction="r", - }, - [0xFB50]={ - category="lo", - direction="al", - }, - [0xFB51]={ - category="lo", - direction="al", - }, - [0xFB52]={ - category="lo", - direction="al", - }, - [0xFB53]={ - category="lo", - direction="al", - }, - [0xFB54]={ - category="lo", - direction="al", - }, - [0xFB55]={ - category="lo", - direction="al", - }, - [0xFB56]={ - category="lo", - direction="al", - }, - [0xFB57]={ - category="lo", - direction="al", - }, - [0xFB58]={ - category="lo", - direction="al", - }, - [0xFB59]={ - category="lo", - direction="al", - }, - [0xFB5A]={ - category="lo", - direction="al", - }, - [0xFB5B]={ - category="lo", - direction="al", - }, - [0xFB5C]={ - category="lo", - direction="al", - }, - [0xFB5D]={ - category="lo", - direction="al", - }, - [0xFB5E]={ - category="lo", - direction="al", - }, - [0xFB5F]={ - category="lo", - direction="al", - }, - [0xFB60]={ - category="lo", - direction="al", - }, - [0xFB61]={ - category="lo", - direction="al", - }, - [0xFB62]={ - category="lo", - direction="al", - }, - [0xFB63]={ - category="lo", - direction="al", - }, - [0xFB64]={ - category="lo", - direction="al", - }, - [0xFB65]={ - category="lo", - direction="al", - }, - [0xFB66]={ - category="lo", - direction="al", - }, - [0xFB67]={ - category="lo", - direction="al", - }, - [0xFB68]={ - category="lo", - direction="al", - }, - [0xFB69]={ - category="lo", - direction="al", - }, - [0xFB6A]={ - category="lo", - direction="al", - }, - [0xFB6B]={ - category="lo", - direction="al", - }, - [0xFB6C]={ - category="lo", - direction="al", - }, - [0xFB6D]={ - category="lo", - direction="al", - }, - [0xFB6E]={ - category="lo", - direction="al", - }, - [0xFB6F]={ - category="lo", - direction="al", - }, - [0xFB70]={ - category="lo", - direction="al", - }, - [0xFB71]={ - category="lo", - direction="al", - }, - [0xFB72]={ - category="lo", - direction="al", - }, - [0xFB73]={ - category="lo", - direction="al", - }, - [0xFB74]={ - category="lo", - direction="al", - }, - [0xFB75]={ - category="lo", - direction="al", - }, - [0xFB76]={ - category="lo", - direction="al", - }, - [0xFB77]={ - category="lo", - direction="al", - }, - [0xFB78]={ - category="lo", - direction="al", - }, - [0xFB79]={ - category="lo", - direction="al", - }, - [0xFB7A]={ - category="lo", - direction="al", - }, - [0xFB7B]={ - category="lo", - direction="al", - }, - [0xFB7C]={ - category="lo", - direction="al", - }, - [0xFB7D]={ - category="lo", - direction="al", - }, - [0xFB7E]={ - category="lo", - direction="al", - }, - [0xFB7F]={ - category="lo", - direction="al", - }, - [0xFB80]={ - category="lo", - direction="al", - }, - [0xFB81]={ - category="lo", - direction="al", - }, - [0xFB82]={ - category="lo", - direction="al", - }, - [0xFB83]={ - category="lo", - direction="al", - }, - [0xFB84]={ - category="lo", - direction="al", - }, - [0xFB85]={ - category="lo", - direction="al", - }, - [0xFB86]={ - category="lo", - direction="al", - }, - [0xFB87]={ - category="lo", - direction="al", - }, - [0xFB88]={ - category="lo", - direction="al", - }, - [0xFB89]={ - category="lo", - direction="al", - }, - [0xFB8A]={ - category="lo", - direction="al", - }, - [0xFB8B]={ - category="lo", - direction="al", - }, - [0xFB8C]={ - category="lo", - direction="al", - }, - [0xFB8D]={ - category="lo", - direction="al", - }, - [0xFB8E]={ - category="lo", - direction="al", - }, - [0xFB8F]={ - category="lo", - direction="al", - }, - [0xFB90]={ - category="lo", - direction="al", - }, - [0xFB91]={ - category="lo", - direction="al", - }, - [0xFB92]={ - category="lo", - direction="al", - }, - [0xFB93]={ - category="lo", - direction="al", - }, - [0xFB94]={ - category="lo", - direction="al", - }, - [0xFB95]={ - category="lo", - direction="al", - }, - [0xFB96]={ - category="lo", - direction="al", - }, - [0xFB97]={ - category="lo", - direction="al", - }, - [0xFB98]={ - category="lo", - direction="al", - }, - [0xFB99]={ - category="lo", - direction="al", - }, - [0xFB9A]={ - category="lo", - direction="al", - }, - [0xFB9B]={ - category="lo", - direction="al", - }, - [0xFB9C]={ - category="lo", - direction="al", - }, - [0xFB9D]={ - category="lo", - direction="al", - }, - [0xFB9E]={ - category="lo", - direction="al", - }, - [0xFB9F]={ - category="lo", - direction="al", - }, - [0xFBA0]={ - category="lo", - direction="al", - }, - [0xFBA1]={ - category="lo", - direction="al", - }, - [0xFBA2]={ - category="lo", - direction="al", - }, - [0xFBA3]={ - category="lo", - direction="al", - }, - [0xFBA4]={ - category="lo", - direction="al", - }, - [0xFBA5]={ - category="lo", - direction="al", - }, - [0xFBA6]={ - category="lo", - direction="al", - }, - [0xFBA7]={ - category="lo", - direction="al", - }, - [0xFBA8]={ - category="lo", - direction="al", - }, - [0xFBA9]={ - category="lo", - direction="al", - }, - [0xFBAA]={ - category="lo", - direction="al", - }, - [0xFBAB]={ - category="lo", - direction="al", - }, - [0xFBAC]={ - category="lo", - direction="al", - }, - [0xFBAD]={ - category="lo", - direction="al", - }, - [0xFBAE]={ - category="lo", - direction="al", - }, - [0xFBAF]={ - category="lo", - direction="al", - }, - [0xFBB0]={ - category="lo", - direction="al", - }, - [0xFBB1]={ - category="lo", - direction="al", - }, - [0xFBB2]={ - category="sk", - direction="al", - }, - [0xFBB3]={ - category="sk", - direction="al", - }, - [0xFBB4]={ - category="sk", - direction="al", - }, - [0xFBB5]={ - category="sk", - direction="al", - }, - [0xFBB6]={ - category="sk", - direction="al", - }, - [0xFBB7]={ - category="sk", - direction="al", - }, - [0xFBB8]={ - category="sk", - direction="al", - }, - [0xFBB9]={ - category="sk", - direction="al", - }, - [0xFBBA]={ - category="sk", - direction="al", - }, - [0xFBBB]={ - category="sk", - direction="al", - }, - [0xFBBC]={ - category="sk", - direction="al", - }, - [0xFBBD]={ - category="sk", - direction="al", - }, - [0xFBBE]={ - category="sk", - direction="al", - }, - [0xFBBF]={ - category="sk", - direction="al", - }, - [0xFBC0]={ - category="sk", - direction="al", - }, - [0xFBC1]={ - category="sk", - direction="al", - }, - [0xFBD3]={ - category="lo", - direction="al", - }, - [0xFBD4]={ - category="lo", - direction="al", - }, - [0xFBD5]={ - category="lo", - direction="al", - }, - [0xFBD6]={ - category="lo", - direction="al", - }, - [0xFBD7]={ - category="lo", - direction="al", - }, - [0xFBD8]={ - category="lo", - direction="al", - }, - [0xFBD9]={ - category="lo", - direction="al", - }, - [0xFBDA]={ - category="lo", - direction="al", - }, - [0xFBDB]={ - category="lo", - direction="al", - }, - [0xFBDC]={ - category="lo", - direction="al", - }, - [0xFBDD]={ - category="lo", - direction="al", - }, - [0xFBDE]={ - category="lo", - direction="al", - }, - [0xFBDF]={ - category="lo", - direction="al", - }, - [0xFBE0]={ - category="lo", - direction="al", - }, - [0xFBE1]={ - category="lo", - direction="al", - }, - [0xFBE2]={ - category="lo", - direction="al", - }, - [0xFBE3]={ - category="lo", - direction="al", - }, - [0xFBE4]={ - category="lo", - direction="al", - }, - [0xFBE5]={ - category="lo", - direction="al", - }, - [0xFBE6]={ - category="lo", - direction="al", - }, - [0xFBE7]={ - category="lo", - direction="al", - }, - [0xFBE8]={ - category="lo", - direction="al", - }, - [0xFBE9]={ - category="lo", - direction="al", - }, - [0xFBEA]={ - category="lo", - direction="al", - }, - [0xFBEB]={ - category="lo", - direction="al", - }, - [0xFBEC]={ - category="lo", - direction="al", - }, - [0xFBED]={ - category="lo", - direction="al", - }, - [0xFBEE]={ - category="lo", - direction="al", - }, - [0xFBEF]={ - category="lo", - direction="al", - }, - [0xFBF0]={ - category="lo", - direction="al", - }, - [0xFBF1]={ - category="lo", - direction="al", - }, - [0xFBF2]={ - category="lo", - direction="al", - }, - [0xFBF3]={ - category="lo", - direction="al", - }, - [0xFBF4]={ - category="lo", - direction="al", - }, - [0xFBF5]={ - category="lo", - direction="al", - }, - [0xFBF6]={ - category="lo", - direction="al", - }, - [0xFBF7]={ - category="lo", - direction="al", - }, - [0xFBF8]={ - category="lo", - direction="al", - }, - [0xFBF9]={ - category="lo", - direction="al", - }, - [0xFBFA]={ - category="lo", - direction="al", - }, - [0xFBFB]={ - category="lo", - direction="al", - }, - [0xFBFC]={ - category="lo", - direction="al", - }, - [0xFBFD]={ - category="lo", - direction="al", - }, - [0xFBFE]={ - category="lo", - direction="al", - }, - [0xFBFF]={ - category="lo", - direction="al", - }, - [0xFC00]={ - category="lo", - direction="al", - }, - [0xFC01]={ - category="lo", - direction="al", - }, - [0xFC02]={ - category="lo", - direction="al", - }, - [0xFC03]={ - category="lo", - direction="al", - }, - [0xFC04]={ - category="lo", - direction="al", - }, - [0xFC05]={ - category="lo", - direction="al", - }, - [0xFC06]={ - category="lo", - direction="al", - }, - [0xFC07]={ - category="lo", - direction="al", - }, - [0xFC08]={ - category="lo", - direction="al", - }, - [0xFC09]={ - category="lo", - direction="al", - }, - [0xFC0A]={ - category="lo", - direction="al", - }, - [0xFC0B]={ - category="lo", - direction="al", - }, - [0xFC0C]={ - category="lo", - direction="al", - }, - [0xFC0D]={ - category="lo", - direction="al", - }, - [0xFC0E]={ - category="lo", - direction="al", - }, - [0xFC0F]={ - category="lo", - direction="al", - }, - [0xFC10]={ - category="lo", - direction="al", - }, - [0xFC11]={ - category="lo", - direction="al", - }, - [0xFC12]={ - category="lo", - direction="al", - }, - [0xFC13]={ - category="lo", - direction="al", - }, - [0xFC14]={ - category="lo", - direction="al", - }, - [0xFC15]={ - category="lo", - direction="al", - }, - [0xFC16]={ - category="lo", - direction="al", - }, - [0xFC17]={ - category="lo", - direction="al", - }, - [0xFC18]={ - category="lo", - direction="al", - }, - [0xFC19]={ - category="lo", - direction="al", - }, - [0xFC1A]={ - category="lo", - direction="al", - }, - [0xFC1B]={ - category="lo", - direction="al", - }, - [0xFC1C]={ - category="lo", - direction="al", - }, - [0xFC1D]={ - category="lo", - direction="al", - }, - [0xFC1E]={ - category="lo", - direction="al", - }, - [0xFC1F]={ - category="lo", - direction="al", - }, - [0xFC20]={ - category="lo", - direction="al", - }, - [0xFC21]={ - category="lo", - direction="al", - }, - [0xFC22]={ - category="lo", - direction="al", - }, - [0xFC23]={ - category="lo", - direction="al", - }, - [0xFC24]={ - category="lo", - direction="al", - }, - [0xFC25]={ - category="lo", - direction="al", - }, - [0xFC26]={ - category="lo", - direction="al", - }, - [0xFC27]={ - category="lo", - direction="al", - }, - [0xFC28]={ - category="lo", - direction="al", - }, - [0xFC29]={ - category="lo", - direction="al", - }, - [0xFC2A]={ - category="lo", - direction="al", - }, - [0xFC2B]={ - category="lo", - direction="al", - }, - [0xFC2C]={ - category="lo", - direction="al", - }, - [0xFC2D]={ - category="lo", - direction="al", - }, - [0xFC2E]={ - category="lo", - direction="al", - }, - [0xFC2F]={ - category="lo", - direction="al", - }, - [0xFC30]={ - category="lo", - direction="al", - }, - [0xFC31]={ - category="lo", - direction="al", - }, - [0xFC32]={ - category="lo", - direction="al", - }, - [0xFC33]={ - category="lo", - direction="al", - }, - [0xFC34]={ - category="lo", - direction="al", - }, - [0xFC35]={ - category="lo", - direction="al", - }, - [0xFC36]={ - category="lo", - direction="al", - }, - [0xFC37]={ - category="lo", - direction="al", - }, - [0xFC38]={ - category="lo", - direction="al", - }, - [0xFC39]={ - category="lo", - direction="al", - }, - [0xFC3A]={ - category="lo", - direction="al", - }, - [0xFC3B]={ - category="lo", - direction="al", - }, - [0xFC3C]={ - category="lo", - direction="al", - }, - [0xFC3D]={ - category="lo", - direction="al", - }, - [0xFC3E]={ - category="lo", - direction="al", - }, - [0xFC3F]={ - category="lo", - direction="al", - }, - [0xFC40]={ - category="lo", - direction="al", - }, - [0xFC41]={ - category="lo", - direction="al", - }, - [0xFC42]={ - category="lo", - direction="al", - }, - [0xFC43]={ - category="lo", - direction="al", - }, - [0xFC44]={ - category="lo", - direction="al", - }, - [0xFC45]={ - category="lo", - direction="al", - }, - [0xFC46]={ - category="lo", - direction="al", - }, - [0xFC47]={ - category="lo", - direction="al", - }, - [0xFC48]={ - category="lo", - direction="al", - }, - [0xFC49]={ - category="lo", - direction="al", - }, - [0xFC4A]={ - category="lo", - direction="al", - }, - [0xFC4B]={ - category="lo", - direction="al", - }, - [0xFC4C]={ - category="lo", - direction="al", - }, - [0xFC4D]={ - category="lo", - direction="al", - }, - [0xFC4E]={ - category="lo", - direction="al", - }, - [0xFC4F]={ - category="lo", - direction="al", - }, - [0xFC50]={ - category="lo", - direction="al", - }, - [0xFC51]={ - category="lo", - direction="al", - }, - [0xFC52]={ - category="lo", - direction="al", - }, - [0xFC53]={ - category="lo", - direction="al", - }, - [0xFC54]={ - category="lo", - direction="al", - }, - [0xFC55]={ - category="lo", - direction="al", - }, - [0xFC56]={ - category="lo", - direction="al", - }, - [0xFC57]={ - category="lo", - direction="al", - }, - [0xFC58]={ - category="lo", - direction="al", - }, - [0xFC59]={ - category="lo", - direction="al", - }, - [0xFC5A]={ - category="lo", - direction="al", - }, - [0xFC5B]={ - category="lo", - direction="al", - }, - [0xFC5C]={ - category="lo", - direction="al", - }, - [0xFC5D]={ - category="lo", - direction="al", - }, - [0xFC5E]={ - category="lo", - direction="al", - }, - [0xFC5F]={ - category="lo", - direction="al", - }, - [0xFC60]={ - category="lo", - direction="al", - }, - [0xFC61]={ - category="lo", - direction="al", - }, - [0xFC62]={ - category="lo", - direction="al", - }, - [0xFC63]={ - category="lo", - direction="al", - }, - [0xFC64]={ - category="lo", - direction="al", - }, - [0xFC65]={ - category="lo", - direction="al", - }, - [0xFC66]={ - category="lo", - direction="al", - }, - [0xFC67]={ - category="lo", - direction="al", - }, - [0xFC68]={ - category="lo", - direction="al", - }, - [0xFC69]={ - category="lo", - direction="al", - }, - [0xFC6A]={ - category="lo", - direction="al", - }, - [0xFC6B]={ - category="lo", - direction="al", - }, - [0xFC6C]={ - category="lo", - direction="al", - }, - [0xFC6D]={ - category="lo", - direction="al", - }, - [0xFC6E]={ - category="lo", - direction="al", - }, - [0xFC6F]={ - category="lo", - direction="al", - }, - [0xFC70]={ - category="lo", - direction="al", - }, - [0xFC71]={ - category="lo", - direction="al", - }, - [0xFC72]={ - category="lo", - direction="al", - }, - [0xFC73]={ - category="lo", - direction="al", - }, - [0xFC74]={ - category="lo", - direction="al", - }, - [0xFC75]={ - category="lo", - direction="al", - }, - [0xFC76]={ - category="lo", - direction="al", - }, - [0xFC77]={ - category="lo", - direction="al", - }, - [0xFC78]={ - category="lo", - direction="al", - }, - [0xFC79]={ - category="lo", - direction="al", - }, - [0xFC7A]={ - category="lo", - direction="al", - }, - [0xFC7B]={ - category="lo", - direction="al", - }, - [0xFC7C]={ - category="lo", - direction="al", - }, - [0xFC7D]={ - category="lo", - direction="al", - }, - [0xFC7E]={ - category="lo", - direction="al", - }, - [0xFC7F]={ - category="lo", - direction="al", - }, - [0xFC80]={ - category="lo", - direction="al", - }, - [0xFC81]={ - category="lo", - direction="al", - }, - [0xFC82]={ - category="lo", - direction="al", - }, - [0xFC83]={ - category="lo", - direction="al", - }, - [0xFC84]={ - category="lo", - direction="al", - }, - [0xFC85]={ - category="lo", - direction="al", - }, - [0xFC86]={ - category="lo", - direction="al", - }, - [0xFC87]={ - category="lo", - direction="al", - }, - [0xFC88]={ - category="lo", - direction="al", - }, - [0xFC89]={ - category="lo", - direction="al", - }, - [0xFC8A]={ - category="lo", - direction="al", - }, - [0xFC8B]={ - category="lo", - direction="al", - }, - [0xFC8C]={ - category="lo", - direction="al", - }, - [0xFC8D]={ - category="lo", - direction="al", - }, - [0xFC8E]={ - category="lo", - direction="al", - }, - [0xFC8F]={ - category="lo", - direction="al", - }, - [0xFC90]={ - category="lo", - direction="al", - }, - [0xFC91]={ - category="lo", - direction="al", - }, - [0xFC92]={ - category="lo", - direction="al", - }, - [0xFC93]={ - category="lo", - direction="al", - }, - [0xFC94]={ - category="lo", - direction="al", - }, - [0xFC95]={ - category="lo", - direction="al", - }, - [0xFC96]={ - category="lo", - direction="al", - }, - [0xFC97]={ - category="lo", - direction="al", - }, - [0xFC98]={ - category="lo", - direction="al", - }, - [0xFC99]={ - category="lo", - direction="al", - }, - [0xFC9A]={ - category="lo", - direction="al", - }, - [0xFC9B]={ - category="lo", - direction="al", - }, - [0xFC9C]={ - category="lo", - direction="al", - }, - [0xFC9D]={ - category="lo", - direction="al", - }, - [0xFC9E]={ - category="lo", - direction="al", - }, - [0xFC9F]={ - category="lo", - direction="al", - }, - [0xFCA0]={ - category="lo", - direction="al", - }, - [0xFCA1]={ - category="lo", - direction="al", - }, - [0xFCA2]={ - category="lo", - direction="al", - }, - [0xFCA3]={ - category="lo", - direction="al", - }, - [0xFCA4]={ - category="lo", - direction="al", - }, - [0xFCA5]={ - category="lo", - direction="al", - }, - [0xFCA6]={ - category="lo", - direction="al", - }, - [0xFCA7]={ - category="lo", - direction="al", - }, - [0xFCA8]={ - category="lo", - direction="al", - }, - [0xFCA9]={ - category="lo", - direction="al", - }, - [0xFCAA]={ - category="lo", - direction="al", - }, - [0xFCAB]={ - category="lo", - direction="al", - }, - [0xFCAC]={ - category="lo", - direction="al", - }, - [0xFCAD]={ - category="lo", - direction="al", - }, - [0xFCAE]={ - category="lo", - direction="al", - }, - [0xFCAF]={ - category="lo", - direction="al", - }, - [0xFCB0]={ - category="lo", - direction="al", - }, - [0xFCB1]={ - category="lo", - direction="al", - }, - [0xFCB2]={ - category="lo", - direction="al", - }, - [0xFCB3]={ - category="lo", - direction="al", - }, - [0xFCB4]={ - category="lo", - direction="al", - }, - [0xFCB5]={ - category="lo", - direction="al", - }, - [0xFCB6]={ - category="lo", - direction="al", - }, - [0xFCB7]={ - category="lo", - direction="al", - }, - [0xFCB8]={ - category="lo", - direction="al", - }, - [0xFCB9]={ - category="lo", - direction="al", - }, - [0xFCBA]={ - category="lo", - direction="al", - }, - [0xFCBB]={ - category="lo", - direction="al", - }, - [0xFCBC]={ - category="lo", - direction="al", - }, - [0xFCBD]={ - category="lo", - direction="al", - }, - [0xFCBE]={ - category="lo", - direction="al", - }, - [0xFCBF]={ - category="lo", - direction="al", - }, - [0xFCC0]={ - category="lo", - direction="al", - }, - [0xFCC1]={ - category="lo", - direction="al", - }, - [0xFCC2]={ - category="lo", - direction="al", - }, - [0xFCC3]={ - category="lo", - direction="al", - }, - [0xFCC4]={ - category="lo", - direction="al", - }, - [0xFCC5]={ - category="lo", - direction="al", - }, - [0xFCC6]={ - category="lo", - direction="al", - }, - [0xFCC7]={ - category="lo", - direction="al", - }, - [0xFCC8]={ - category="lo", - direction="al", - }, - [0xFCC9]={ - category="lo", - direction="al", - }, - [0xFCCA]={ - category="lo", - direction="al", - }, - [0xFCCB]={ - category="lo", - direction="al", - }, - [0xFCCC]={ - category="lo", - direction="al", - }, - [0xFCCD]={ - category="lo", - direction="al", - }, - [0xFCCE]={ - category="lo", - direction="al", - }, - [0xFCCF]={ - category="lo", - direction="al", - }, - [0xFCD0]={ - category="lo", - direction="al", - }, - [0xFCD1]={ - category="lo", - direction="al", - }, - [0xFCD2]={ - category="lo", - direction="al", - }, - [0xFCD3]={ - category="lo", - direction="al", - }, - [0xFCD4]={ - category="lo", - direction="al", - }, - [0xFCD5]={ - category="lo", - direction="al", - }, - [0xFCD6]={ - category="lo", - direction="al", - }, - [0xFCD7]={ - category="lo", - direction="al", - }, - [0xFCD8]={ - category="lo", - direction="al", - }, - [0xFCD9]={ - category="lo", - direction="al", - }, - [0xFCDA]={ - category="lo", - direction="al", - }, - [0xFCDB]={ - category="lo", - direction="al", - }, - [0xFCDC]={ - category="lo", - direction="al", - }, - [0xFCDD]={ - category="lo", - direction="al", - }, - [0xFCDE]={ - category="lo", - direction="al", - }, - [0xFCDF]={ - category="lo", - direction="al", - }, - [0xFCE0]={ - category="lo", - direction="al", - }, - [0xFCE1]={ - category="lo", - direction="al", - }, - [0xFCE2]={ - category="lo", - direction="al", - }, - [0xFCE3]={ - category="lo", - direction="al", - }, - [0xFCE4]={ - category="lo", - direction="al", - }, - [0xFCE5]={ - category="lo", - direction="al", - }, - [0xFCE6]={ - category="lo", - direction="al", - }, - [0xFCE7]={ - category="lo", - direction="al", - }, - [0xFCE8]={ - category="lo", - direction="al", - }, - [0xFCE9]={ - category="lo", - direction="al", - }, - [0xFCEA]={ - category="lo", - direction="al", - }, - [0xFCEB]={ - category="lo", - direction="al", - }, - [0xFCEC]={ - category="lo", - direction="al", - }, - [0xFCED]={ - category="lo", - direction="al", - }, - [0xFCEE]={ - category="lo", - direction="al", - }, - [0xFCEF]={ - category="lo", - direction="al", - }, - [0xFCF0]={ - category="lo", - direction="al", - }, - [0xFCF1]={ - category="lo", - direction="al", - }, - [0xFCF2]={ - category="lo", - direction="al", - }, - [0xFCF3]={ - category="lo", - direction="al", - }, - [0xFCF4]={ - category="lo", - direction="al", - }, - [0xFCF5]={ - category="lo", - direction="al", - }, - [0xFCF6]={ - category="lo", - direction="al", - }, - [0xFCF7]={ - category="lo", - direction="al", - }, - [0xFCF8]={ - category="lo", - direction="al", - }, - [0xFCF9]={ - category="lo", - direction="al", - }, - [0xFCFA]={ - category="lo", - direction="al", - }, - [0xFCFB]={ - category="lo", - direction="al", - }, - [0xFCFC]={ - category="lo", - direction="al", - }, - [0xFCFD]={ - category="lo", - direction="al", - }, - [0xFCFE]={ - category="lo", - direction="al", - }, - [0xFCFF]={ - category="lo", - direction="al", - }, - [0xFD00]={ - category="lo", - direction="al", - }, - [0xFD01]={ - category="lo", - direction="al", - }, - [0xFD02]={ - category="lo", - direction="al", - }, - [0xFD03]={ - category="lo", - direction="al", - }, - [0xFD04]={ - category="lo", - direction="al", - }, - [0xFD05]={ - category="lo", - direction="al", - }, - [0xFD06]={ - category="lo", - direction="al", - }, - [0xFD07]={ - category="lo", - direction="al", - }, - [0xFD08]={ - category="lo", - direction="al", - }, - [0xFD09]={ - category="lo", - direction="al", - }, - [0xFD0A]={ - category="lo", - direction="al", - }, - [0xFD0B]={ - category="lo", - direction="al", - }, - [0xFD0C]={ - category="lo", - direction="al", - }, - [0xFD0D]={ - category="lo", - direction="al", - }, - [0xFD0E]={ - category="lo", - direction="al", - }, - [0xFD0F]={ - category="lo", - direction="al", - }, - [0xFD10]={ - category="lo", - direction="al", - }, - [0xFD11]={ - category="lo", - direction="al", - }, - [0xFD12]={ - category="lo", - direction="al", - }, - [0xFD13]={ - category="lo", - direction="al", - }, - [0xFD14]={ - category="lo", - direction="al", - }, - [0xFD15]={ - category="lo", - direction="al", - }, - [0xFD16]={ - category="lo", - direction="al", - }, - [0xFD17]={ - category="lo", - direction="al", - }, - [0xFD18]={ - category="lo", - direction="al", - }, - [0xFD19]={ - category="lo", - direction="al", - }, - [0xFD1A]={ - category="lo", - direction="al", - }, - [0xFD1B]={ - category="lo", - direction="al", - }, - [0xFD1C]={ - category="lo", - direction="al", - }, - [0xFD1D]={ - category="lo", - direction="al", - }, - [0xFD1E]={ - category="lo", - direction="al", - }, - [0xFD1F]={ - category="lo", - direction="al", - }, - [0xFD20]={ - category="lo", - direction="al", - }, - [0xFD21]={ - category="lo", - direction="al", - }, - [0xFD22]={ - category="lo", - direction="al", - }, - [0xFD23]={ - category="lo", - direction="al", - }, - [0xFD24]={ - category="lo", - direction="al", - }, - [0xFD25]={ - category="lo", - direction="al", - }, - [0xFD26]={ - category="lo", - direction="al", - }, - [0xFD27]={ - category="lo", - direction="al", - }, - [0xFD28]={ - category="lo", - direction="al", - }, - [0xFD29]={ - category="lo", - direction="al", - }, - [0xFD2A]={ - category="lo", - direction="al", - }, - [0xFD2B]={ - category="lo", - direction="al", - }, - [0xFD2C]={ - category="lo", - direction="al", - }, - [0xFD2D]={ - category="lo", - direction="al", - }, - [0xFD2E]={ - category="lo", - direction="al", - }, - [0xFD2F]={ - category="lo", - direction="al", - }, - [0xFD30]={ - category="lo", - direction="al", - }, - [0xFD31]={ - category="lo", - direction="al", - }, - [0xFD32]={ - category="lo", - direction="al", - }, - [0xFD33]={ - category="lo", - direction="al", - }, - [0xFD34]={ - category="lo", - direction="al", - }, - [0xFD35]={ - category="lo", - direction="al", - }, - [0xFD36]={ - category="lo", - direction="al", - }, - [0xFD37]={ - category="lo", - direction="al", - }, - [0xFD38]={ - category="lo", - direction="al", - }, - [0xFD39]={ - category="lo", - direction="al", - }, - [0xFD3A]={ - category="lo", - direction="al", - }, - [0xFD3B]={ - category="lo", - direction="al", - }, - [0xFD3C]={ - category="lo", - direction="al", - }, - [0xFD3D]={ - category="lo", - direction="al", - }, - [0xFD3E]={ - category="ps", - direction="on", - }, - [0xFD3F]={ - category="pe", - direction="on", - }, - [0xFD50]={ - category="lo", - direction="al", - }, - [0xFD51]={ - category="lo", - direction="al", - }, - [0xFD52]={ - category="lo", - direction="al", - }, - [0xFD53]={ - category="lo", - direction="al", - }, - [0xFD54]={ - category="lo", - direction="al", - }, - [0xFD55]={ - category="lo", - direction="al", - }, - [0xFD56]={ - category="lo", - direction="al", - }, - [0xFD57]={ - category="lo", - direction="al", - }, - [0xFD58]={ - category="lo", - direction="al", - }, - [0xFD59]={ - category="lo", - direction="al", - }, - [0xFD5A]={ - category="lo", - direction="al", - }, - [0xFD5B]={ - category="lo", - direction="al", - }, - [0xFD5C]={ - category="lo", - direction="al", - }, - [0xFD5D]={ - category="lo", - direction="al", - }, - [0xFD5E]={ - category="lo", - direction="al", - }, - [0xFD5F]={ - category="lo", - direction="al", - }, - [0xFD60]={ - category="lo", - direction="al", - }, - [0xFD61]={ - category="lo", - direction="al", - }, - [0xFD62]={ - category="lo", - direction="al", - }, - [0xFD63]={ - category="lo", - direction="al", - }, - [0xFD64]={ - category="lo", - direction="al", - }, - [0xFD65]={ - category="lo", - direction="al", - }, - [0xFD66]={ - category="lo", - direction="al", - }, - [0xFD67]={ - category="lo", - direction="al", - }, - [0xFD68]={ - category="lo", - direction="al", - }, - [0xFD69]={ - category="lo", - direction="al", - }, - [0xFD6A]={ - category="lo", - direction="al", - }, - [0xFD6B]={ - category="lo", - direction="al", - }, - [0xFD6C]={ - category="lo", - direction="al", - }, - [0xFD6D]={ - category="lo", - direction="al", - }, - [0xFD6E]={ - category="lo", - direction="al", - }, - [0xFD6F]={ - category="lo", - direction="al", - }, - [0xFD70]={ - category="lo", - direction="al", - }, - [0xFD71]={ - category="lo", - direction="al", - }, - [0xFD72]={ - category="lo", - direction="al", - }, - [0xFD73]={ - category="lo", - direction="al", - }, - [0xFD74]={ - category="lo", - direction="al", - }, - [0xFD75]={ - category="lo", - direction="al", - }, - [0xFD76]={ - category="lo", - direction="al", - }, - [0xFD77]={ - category="lo", - direction="al", - }, - [0xFD78]={ - category="lo", - direction="al", - }, - [0xFD79]={ - category="lo", - direction="al", - }, - [0xFD7A]={ - category="lo", - direction="al", - }, - [0xFD7B]={ - category="lo", - direction="al", - }, - [0xFD7C]={ - category="lo", - direction="al", - }, - [0xFD7D]={ - category="lo", - direction="al", - }, - [0xFD7E]={ - category="lo", - direction="al", - }, - [0xFD7F]={ - category="lo", - direction="al", - }, - [0xFD80]={ - category="lo", - direction="al", - }, - [0xFD81]={ - category="lo", - direction="al", - }, - [0xFD82]={ - category="lo", - direction="al", - }, - [0xFD83]={ - category="lo", - direction="al", - }, - [0xFD84]={ - category="lo", - direction="al", - }, - [0xFD85]={ - category="lo", - direction="al", - }, - [0xFD86]={ - category="lo", - direction="al", - }, - [0xFD87]={ - category="lo", - direction="al", - }, - [0xFD88]={ - category="lo", - direction="al", - }, - [0xFD89]={ - category="lo", - direction="al", - }, - [0xFD8A]={ - category="lo", - direction="al", - }, - [0xFD8B]={ - category="lo", - direction="al", - }, - [0xFD8C]={ - category="lo", - direction="al", - }, - [0xFD8D]={ - category="lo", - direction="al", - }, - [0xFD8E]={ - category="lo", - direction="al", - }, - [0xFD8F]={ - category="lo", - direction="al", - }, - [0xFD92]={ - category="lo", - direction="al", - }, - [0xFD93]={ - category="lo", - direction="al", - }, - [0xFD94]={ - category="lo", - direction="al", - }, - [0xFD95]={ - category="lo", - direction="al", - }, - [0xFD96]={ - category="lo", - direction="al", - }, - [0xFD97]={ - category="lo", - direction="al", - }, - [0xFD98]={ - category="lo", - direction="al", - }, - [0xFD99]={ - category="lo", - direction="al", - }, - [0xFD9A]={ - category="lo", - direction="al", - }, - [0xFD9B]={ - category="lo", - direction="al", - }, - [0xFD9C]={ - category="lo", - direction="al", - }, - [0xFD9D]={ - category="lo", - direction="al", - }, - [0xFD9E]={ - category="lo", - direction="al", - }, - [0xFD9F]={ - category="lo", - direction="al", - }, - [0xFDA0]={ - category="lo", - direction="al", - }, - [0xFDA1]={ - category="lo", - direction="al", - }, - [0xFDA2]={ - category="lo", - direction="al", - }, - [0xFDA3]={ - category="lo", - direction="al", - }, - [0xFDA4]={ - category="lo", - direction="al", - }, - [0xFDA5]={ - category="lo", - direction="al", - }, - [0xFDA6]={ - category="lo", - direction="al", - }, - [0xFDA7]={ - category="lo", - direction="al", - }, - [0xFDA8]={ - category="lo", - direction="al", - }, - [0xFDA9]={ - category="lo", - direction="al", - }, - [0xFDAA]={ - category="lo", - direction="al", - }, - [0xFDAB]={ - category="lo", - direction="al", - }, - [0xFDAC]={ - category="lo", - direction="al", - }, - [0xFDAD]={ - category="lo", - direction="al", - }, - [0xFDAE]={ - category="lo", - direction="al", - }, - [0xFDAF]={ - category="lo", - direction="al", - }, - [0xFDB0]={ - category="lo", - direction="al", - }, - [0xFDB1]={ - category="lo", - direction="al", - }, - [0xFDB2]={ - category="lo", - direction="al", - }, - [0xFDB3]={ - category="lo", - direction="al", - }, - [0xFDB4]={ - category="lo", - direction="al", - }, - [0xFDB5]={ - category="lo", - direction="al", - }, - [0xFDB6]={ - category="lo", - direction="al", - }, - [0xFDB7]={ - category="lo", - direction="al", - }, - [0xFDB8]={ - category="lo", - direction="al", - }, - [0xFDB9]={ - category="lo", - direction="al", - }, - [0xFDBA]={ - category="lo", - direction="al", - }, - [0xFDBB]={ - category="lo", - direction="al", - }, - [0xFDBC]={ - category="lo", - direction="al", - }, - [0xFDBD]={ - category="lo", - direction="al", - }, - [0xFDBE]={ - category="lo", - direction="al", - }, - [0xFDBF]={ - category="lo", - direction="al", - }, - [0xFDC0]={ - category="lo", - direction="al", - }, - [0xFDC1]={ - category="lo", - direction="al", - }, - [0xFDC2]={ - category="lo", - direction="al", - }, - [0xFDC3]={ - category="lo", - direction="al", - }, - [0xFDC4]={ - category="lo", - direction="al", - }, - [0xFDC5]={ - category="lo", - direction="al", - }, - [0xFDC6]={ - category="lo", - direction="al", - }, - [0xFDC7]={ - category="lo", - direction="al", - }, - [0xFDF0]={ - category="lo", - direction="al", - }, - [0xFDF1]={ - category="lo", - direction="al", - }, - [0xFDF2]={ - category="lo", - direction="al", - }, - [0xFDF3]={ - category="lo", - direction="al", - }, - [0xFDF4]={ - category="lo", - direction="al", - }, - [0xFDF5]={ - category="lo", - direction="al", - }, - [0xFDF6]={ - category="lo", - direction="al", - }, - [0xFDF7]={ - category="lo", - direction="al", - }, - [0xFDF8]={ - category="lo", - direction="al", - }, - [0xFDF9]={ - category="lo", - direction="al", - }, - [0xFDFA]={ - category="lo", - direction="al", - }, - [0xFDFB]={ - category="lo", - direction="al", - }, - [0xFDFC]={ - category="sc", - direction="al", - }, - [0xFDFD]={ - category="so", - direction="on", - }, - [0xFE10]={ - category="po", - direction="on", - }, - [0xFE11]={ - category="po", - direction="on", - }, - [0xFE12]={ - category="po", - direction="on", - }, - [0xFE13]={ - category="po", - direction="on", - }, - [0xFE14]={ - category="po", - direction="on", - }, - [0xFE15]={ - category="po", - direction="on", - }, - [0xFE16]={ - category="po", - direction="on", - }, - [0xFE17]={ - category="ps", - direction="on", - }, - [0xFE18]={ - category="pe", - direction="on", - }, - [0xFE19]={ - category="po", - direction="on", - }, - [0xFE20]={ - category="mn", - direction="nsm", - }, - [0xFE21]={ - category="mn", - direction="nsm", - }, - [0xFE22]={ - category="mn", - direction="nsm", - }, - [0xFE23]={ - category="mn", - direction="nsm", - }, - [0xFE24]={ - category="mn", - direction="nsm", - }, - [0xFE25]={ - category="mn", - direction="nsm", - }, - [0xFE26]={ - category="mn", - direction="nsm", - }, - [0xFE27]={ - category="mn", - direction="nsm", - }, - [0xFE28]={ - category="mn", - direction="nsm", - }, - [0xFE29]={ - category="mn", - direction="nsm", - }, - [0xFE2A]={ - category="mn", - direction="nsm", - }, - [0xFE2B]={ - category="mn", - direction="nsm", - }, - [0xFE2C]={ - category="mn", - direction="nsm", - }, - [0xFE2D]={ - category="mn", - direction="nsm", - }, - [0xFE2E]={ - category="mn", - direction="nsm", - }, - [0xFE2F]={ - category="mn", - direction="nsm", - }, - [0xFE30]={ - category="po", - direction="on", - }, - [0xFE31]={ - category="pd", - direction="on", - }, - [0xFE32]={ - category="pd", - direction="on", - }, - [0xFE33]={ - category="pc", - direction="on", - }, - [0xFE34]={ - category="pc", - direction="on", - }, - [0xFE35]={ - category="ps", - direction="on", - }, - [0xFE36]={ - category="pe", - direction="on", - }, - [0xFE37]={ - category="ps", - direction="on", - }, - [0xFE38]={ - category="pe", - direction="on", - }, - [0xFE39]={ - category="ps", - direction="on", - }, - [0xFE3A]={ - category="pe", - direction="on", - }, - [0xFE3B]={ - category="ps", - direction="on", - }, - [0xFE3C]={ - category="pe", - direction="on", - }, - [0xFE3D]={ - category="ps", - direction="on", - }, - [0xFE3E]={ - category="pe", - direction="on", - }, - [0xFE3F]={ - category="ps", - direction="on", - }, - [0xFE40]={ - category="pe", - direction="on", - }, - [0xFE41]={ - category="ps", - direction="on", - }, - [0xFE42]={ - category="pe", - direction="on", - }, - [0xFE43]={ - category="ps", - direction="on", - }, - [0xFE44]={ - category="pe", - direction="on", - }, - [0xFE45]={ - category="po", - direction="on", - }, - [0xFE46]={ - category="po", - direction="on", - }, - [0xFE47]={ - category="ps", - direction="on", - }, - [0xFE48]={ - category="pe", - direction="on", - }, - [0xFE49]={ - category="po", - direction="on", - }, - [0xFE4A]={ - category="po", - direction="on", - }, - [0xFE4B]={ - category="po", - direction="on", - }, - [0xFE4C]={ - category="po", - direction="on", - }, - [0xFE4D]={ - category="pc", - direction="on", - }, - [0xFE4E]={ - category="pc", - direction="on", - }, - [0xFE4F]={ - category="pc", - direction="on", - }, - [0xFE50]={ - category="po", - direction="cs", - }, - [0xFE51]={ - category="po", - direction="on", - }, - [0xFE52]={ - category="po", - direction="cs", - }, - [0xFE54]={ - category="po", - direction="on", - }, - [0xFE55]={ - category="po", - direction="cs", - }, - [0xFE56]={ - category="po", - direction="on", - }, - [0xFE57]={ - category="po", - direction="on", - }, - [0xFE58]={ - category="pd", - direction="on", - }, - [0xFE59]={ - category="ps", - direction="on", - mirror=0xFE5A, - textclass="open", - }, - [0xFE5A]={ - category="pe", - direction="on", - mirror=0xFE59, - textclass="close", - }, - [0xFE5B]={ - category="ps", - direction="on", - mirror=0xFE5C, - textclass="open", - }, - [0xFE5C]={ - category="pe", - direction="on", - mirror=0xFE5B, - textclass="close", - }, - [0xFE5D]={ - category="ps", - direction="on", - mirror=0xFE5E, - textclass="open", - }, - [0xFE5E]={ - category="pe", - direction="on", - mirror=0xFE5D, - textclass="close", - }, - [0xFE5F]={ - category="po", - direction="et", - }, - [0xFE60]={ - category="po", - direction="on", - }, - [0xFE61]={ - category="po", - direction="on", - }, - [0xFE62]={ - category="sm", - direction="es", - }, - [0xFE63]={ - category="pd", - direction="es", - }, - [0xFE64]={ - category="sm", - direction="on", - mirror=0xFE65, - textclass="open", - }, - [0xFE65]={ - category="sm", - direction="on", - mirror=0xFE64, - textclass="close", - }, - [0xFE66]={ - category="sm", - direction="on", - }, - [0xFE68]={ - category="po", - direction="on", - }, - [0xFE69]={ - category="sc", - direction="et", - }, - [0xFE6A]={ - category="po", - direction="et", - }, - [0xFE6B]={ - category="po", - direction="on", - }, - [0xFE70]={ - category="lo", - direction="al", - }, - [0xFE71]={ - category="lo", - direction="al", - }, - [0xFE72]={ - category="lo", - direction="al", - }, - [0xFE73]={ - category="lo", - direction="al", - }, - [0xFE74]={ - category="lo", - direction="al", - }, - [0xFE76]={ - category="lo", - direction="al", - }, - [0xFE77]={ - category="lo", - direction="al", - }, - [0xFE78]={ - category="lo", - direction="al", - }, - [0xFE79]={ - category="lo", - direction="al", - }, - [0xFE7A]={ - category="lo", - direction="al", - }, - [0xFE7B]={ - category="lo", - direction="al", - }, - [0xFE7C]={ - category="lo", - direction="al", - }, - [0xFE7D]={ - category="lo", - direction="al", - }, - [0xFE7E]={ - category="lo", - direction="al", - }, - [0xFE7F]={ - category="lo", - direction="al", - }, - [0xFE80]={ - category="lo", - direction="al", - }, - [0xFE81]={ - category="lo", - direction="al", - }, - [0xFE82]={ - category="lo", - direction="al", - }, - [0xFE83]={ - category="lo", - direction="al", - }, - [0xFE84]={ - category="lo", - direction="al", - }, - [0xFE85]={ - category="lo", - direction="al", - }, - [0xFE86]={ - category="lo", - direction="al", - }, - [0xFE87]={ - category="lo", - direction="al", - }, - [0xFE88]={ - category="lo", - direction="al", - }, - [0xFE89]={ - category="lo", - direction="al", - }, - [0xFE8A]={ - category="lo", - direction="al", - }, - [0xFE8B]={ - category="lo", - direction="al", - }, - [0xFE8C]={ - category="lo", - direction="al", - }, - [0xFE8D]={ - category="lo", - direction="al", - }, - [0xFE8E]={ - category="lo", - direction="al", - }, - [0xFE8F]={ - category="lo", - direction="al", - }, - [0xFE90]={ - category="lo", - direction="al", - }, - [0xFE91]={ - category="lo", - direction="al", - }, - [0xFE92]={ - category="lo", - direction="al", - }, - [0xFE93]={ - category="lo", - direction="al", - }, - [0xFE94]={ - category="lo", - direction="al", - }, - [0xFE95]={ - category="lo", - direction="al", - }, - [0xFE96]={ - category="lo", - direction="al", - }, - [0xFE97]={ - category="lo", - direction="al", - }, - [0xFE98]={ - category="lo", - direction="al", - }, - [0xFE99]={ - category="lo", - direction="al", - }, - [0xFE9A]={ - category="lo", - direction="al", - }, - [0xFE9B]={ - category="lo", - direction="al", - }, - [0xFE9C]={ - category="lo", - direction="al", - }, - [0xFE9D]={ - category="lo", - direction="al", - }, - [0xFE9E]={ - category="lo", - direction="al", - }, - [0xFE9F]={ - category="lo", - direction="al", - }, - [0xFEA0]={ - category="lo", - direction="al", - }, - [0xFEA1]={ - category="lo", - direction="al", - }, - [0xFEA2]={ - category="lo", - direction="al", - }, - [0xFEA3]={ - category="lo", - direction="al", - }, - [0xFEA4]={ - category="lo", - direction="al", - }, - [0xFEA5]={ - category="lo", - direction="al", - }, - [0xFEA6]={ - category="lo", - direction="al", - }, - [0xFEA7]={ - category="lo", - direction="al", - }, - [0xFEA8]={ - category="lo", - direction="al", - }, - [0xFEA9]={ - category="lo", - direction="al", - }, - [0xFEAA]={ - category="lo", - direction="al", - }, - [0xFEAB]={ - category="lo", - direction="al", - }, - [0xFEAC]={ - category="lo", - direction="al", - }, - [0xFEAD]={ - category="lo", - direction="al", - }, - [0xFEAE]={ - category="lo", - direction="al", - }, - [0xFEAF]={ - category="lo", - direction="al", - }, - [0xFEB0]={ - category="lo", - direction="al", - }, - [0xFEB1]={ - category="lo", - direction="al", - }, - [0xFEB2]={ - category="lo", - direction="al", - }, - [0xFEB3]={ - category="lo", - direction="al", - }, - [0xFEB4]={ - category="lo", - direction="al", - }, - [0xFEB5]={ - category="lo", - direction="al", - }, - [0xFEB6]={ - category="lo", - direction="al", - }, - [0xFEB7]={ - category="lo", - direction="al", - }, - [0xFEB8]={ - category="lo", - direction="al", - }, - [0xFEB9]={ - category="lo", - direction="al", - }, - [0xFEBA]={ - category="lo", - direction="al", - }, - [0xFEBB]={ - category="lo", - direction="al", - }, - [0xFEBC]={ - category="lo", - direction="al", - }, - [0xFEBD]={ - category="lo", - direction="al", - }, - [0xFEBE]={ - category="lo", - direction="al", - }, - [0xFEBF]={ - category="lo", - direction="al", - }, - [0xFEC0]={ - category="lo", - direction="al", - }, - [0xFEC1]={ - category="lo", - direction="al", - }, - [0xFEC2]={ - category="lo", - direction="al", - }, - [0xFEC3]={ - category="lo", - direction="al", - }, - [0xFEC4]={ - category="lo", - direction="al", - }, - [0xFEC5]={ - category="lo", - direction="al", - }, - [0xFEC6]={ - category="lo", - direction="al", - }, - [0xFEC7]={ - category="lo", - direction="al", - }, - [0xFEC8]={ - category="lo", - direction="al", - }, - [0xFEC9]={ - category="lo", - direction="al", - }, - [0xFECA]={ - category="lo", - direction="al", - }, - [0xFECB]={ - category="lo", - direction="al", - }, - [0xFECC]={ - category="lo", - direction="al", - }, - [0xFECD]={ - category="lo", - direction="al", - }, - [0xFECE]={ - category="lo", - direction="al", - }, - [0xFECF]={ - category="lo", - direction="al", - }, - [0xFED0]={ - category="lo", - direction="al", - }, - [0xFED1]={ - category="lo", - direction="al", - }, - [0xFED2]={ - category="lo", - direction="al", - }, - [0xFED3]={ - category="lo", - direction="al", - }, - [0xFED4]={ - category="lo", - direction="al", - }, - [0xFED5]={ - category="lo", - direction="al", - }, - [0xFED6]={ - category="lo", - direction="al", - }, - [0xFED7]={ - category="lo", - direction="al", - }, - [0xFED8]={ - category="lo", - direction="al", - }, - [0xFED9]={ - category="lo", - direction="al", - }, - [0xFEDA]={ - category="lo", - direction="al", - }, - [0xFEDB]={ - category="lo", - direction="al", - }, - [0xFEDC]={ - category="lo", - direction="al", - }, - [0xFEDD]={ - category="lo", - direction="al", - }, - [0xFEDE]={ - category="lo", - direction="al", - }, - [0xFEDF]={ - category="lo", - direction="al", - }, - [0xFEE0]={ - category="lo", - direction="al", - }, - [0xFEE1]={ - category="lo", - direction="al", - }, - [0xFEE2]={ - category="lo", - direction="al", - }, - [0xFEE3]={ - category="lo", - direction="al", - }, - [0xFEE4]={ - category="lo", - direction="al", - }, - [0xFEE5]={ - category="lo", - direction="al", - }, - [0xFEE6]={ - category="lo", - direction="al", - }, - [0xFEE7]={ - category="lo", - direction="al", - }, - [0xFEE8]={ - category="lo", - direction="al", - }, - [0xFEE9]={ - category="lo", - direction="al", - }, - [0xFEEA]={ - category="lo", - direction="al", - }, - [0xFEEB]={ - category="lo", - direction="al", - }, - [0xFEEC]={ - category="lo", - direction="al", - }, - [0xFEED]={ - category="lo", - direction="al", - }, - [0xFEEE]={ - category="lo", - direction="al", - }, - [0xFEEF]={ - category="lo", - direction="al", - }, - [0xFEF0]={ - category="lo", - direction="al", - }, - [0xFEF1]={ - category="lo", - direction="al", - }, - [0xFEF2]={ - category="lo", - direction="al", - }, - [0xFEF3]={ - category="lo", - direction="al", - }, - [0xFEF4]={ - category="lo", - direction="al", - }, - [0xFEF5]={ - category="lo", - direction="al", - }, - [0xFEF6]={ - category="lo", - direction="al", - }, - [0xFEF7]={ - category="lo", - direction="al", - }, - [0xFEF8]={ - category="lo", - direction="al", - }, - [0xFEF9]={ - category="lo", - direction="al", - }, - [0xFEFA]={ - category="lo", - direction="al", - }, - [0xFEFB]={ - category="lo", - direction="al", - }, - [0xFEFC]={ - category="lo", - direction="al", - }, - [0xFEFF]={ - category="cf", - direction="bn", - }, - [0xFF01]={ - category="po", - direction="on", - }, - [0xFF02]={ - category="po", - direction="on", - }, - [0xFF03]={ - category="po", - direction="et", - }, - [0xFF04]={ - category="sc", - direction="et", - }, - [0xFF05]={ - category="po", - direction="et", - }, - [0xFF06]={ - category="po", - direction="on", - }, - [0xFF07]={ - category="po", - direction="on", - }, - [0xFF08]={ - category="ps", - direction="on", - mirror=0xFF09, - textclass="open", - }, - [0xFF09]={ - category="pe", - direction="on", - mirror=0xFF08, - textclass="close", - }, - [0xFF0A]={ - category="po", - direction="on", - }, - [0xFF0B]={ - category="sm", - direction="es", - }, - [0xFF0C]={ - category="po", - direction="cs", - }, - [0xFF0D]={ - category="pd", - direction="es", - }, - [0xFF0E]={ - category="po", - direction="cs", - }, - [0xFF0F]={ - category="po", - direction="cs", - }, - [0xFF10]={ - category="nd", - direction="en", - }, - [0xFF11]={ - category="nd", - direction="en", - }, - [0xFF12]={ - category="nd", - direction="en", - }, - [0xFF13]={ - category="nd", - direction="en", - }, - [0xFF14]={ - category="nd", - direction="en", - }, - [0xFF15]={ - category="nd", - direction="en", - }, - [0xFF16]={ - category="nd", - direction="en", - }, - [0xFF17]={ - category="nd", - direction="en", - }, - [0xFF18]={ - category="nd", - direction="en", - }, - [0xFF19]={ - category="nd", - direction="en", - }, - [0xFF1A]={ - category="po", - direction="cs", - }, - [0xFF1B]={ - category="po", - direction="on", - }, - [0xFF1C]={ - category="sm", - direction="on", - mirror=0xFF1E, - textclass="open", - }, - [0xFF1D]={ - category="sm", - direction="on", - }, - [0xFF1E]={ - category="sm", - direction="on", - mirror=0xFF1C, - textclass="close", - }, - [0xFF1F]={ - category="po", - direction="on", - }, - [0xFF20]={ - category="po", - direction="on", - }, - [0xFF21]={ - category="lu", - direction="l", - }, - [0xFF22]={ - category="lu", - direction="l", - }, - [0xFF23]={ - category="lu", - direction="l", - }, - [0xFF24]={ - category="lu", - direction="l", - }, - [0xFF25]={ - category="lu", - direction="l", - }, - [0xFF26]={ - category="lu", - direction="l", - }, - [0xFF27]={ - category="lu", - direction="l", - }, - [0xFF28]={ - category="lu", - direction="l", - }, - [0xFF29]={ - category="lu", - direction="l", - }, - [0xFF2A]={ - category="lu", - direction="l", - }, - [0xFF2B]={ - category="lu", - direction="l", - }, - [0xFF2C]={ - category="lu", - direction="l", - }, - [0xFF2D]={ - category="lu", - direction="l", - }, - [0xFF2E]={ - category="lu", - direction="l", - }, - [0xFF2F]={ - category="lu", - direction="l", - }, - [0xFF30]={ - category="lu", - direction="l", - }, - [0xFF31]={ - category="lu", - direction="l", - }, - [0xFF32]={ - category="lu", - direction="l", - }, - [0xFF33]={ - category="lu", - direction="l", - }, - [0xFF34]={ - category="lu", - direction="l", - }, - [0xFF35]={ - category="lu", - direction="l", - }, - [0xFF36]={ - category="lu", - direction="l", - }, - [0xFF37]={ - category="lu", - direction="l", - }, - [0xFF38]={ - category="lu", - direction="l", - }, - [0xFF39]={ - category="lu", - direction="l", - }, - [0xFF3A]={ - category="lu", - direction="l", - }, - [0xFF3B]={ - category="ps", - direction="on", - mirror=0xFF3D, - textclass="open", - }, - [0xFF3C]={ - category="po", - direction="on", - }, - [0xFF3D]={ - category="pe", - direction="on", - mirror=0xFF3B, - textclass="close", - }, - [0xFF3E]={ - category="sk", - direction="on", - }, - [0xFF3F]={ - category="pc", - direction="on", - }, - [0xFF40]={ - category="sk", - direction="on", - }, - [0xFF41]={ - category="ll", - direction="l", - }, - [0xFF42]={ - category="ll", - direction="l", - }, - [0xFF43]={ - category="ll", - direction="l", - }, - [0xFF44]={ - category="ll", - direction="l", - }, - [0xFF45]={ - category="ll", - direction="l", - }, - [0xFF46]={ - category="ll", - direction="l", - }, - [0xFF47]={ - category="ll", - direction="l", - }, - [0xFF48]={ - category="ll", - direction="l", - }, - [0xFF49]={ - category="ll", - direction="l", - }, - [0xFF4A]={ - category="ll", - direction="l", - }, - [0xFF4B]={ - category="ll", - direction="l", - }, - [0xFF4C]={ - category="ll", - direction="l", - }, - [0xFF4D]={ - category="ll", - direction="l", - }, - [0xFF4E]={ - category="ll", - direction="l", - }, - [0xFF4F]={ - category="ll", - direction="l", - }, - [0xFF50]={ - category="ll", - direction="l", - }, - [0xFF51]={ - category="ll", - direction="l", - }, - [0xFF52]={ - category="ll", - direction="l", - }, - [0xFF53]={ - category="ll", - direction="l", - }, - [0xFF54]={ - category="ll", - direction="l", - }, - [0xFF55]={ - category="ll", - direction="l", - }, - [0xFF56]={ - category="ll", - direction="l", - }, - [0xFF57]={ - category="ll", - direction="l", - }, - [0xFF58]={ - category="ll", - direction="l", - }, - [0xFF59]={ - category="ll", - direction="l", - }, - [0xFF5A]={ - category="ll", - direction="l", - }, - [0xFF5B]={ - category="ps", - direction="on", - mirror=0xFF5D, - textclass="open", - }, - [0xFF5C]={ - category="sm", - direction="on", - }, - [0xFF5D]={ - category="pe", - direction="on", - mirror=0xFF5B, - textclass="close", - }, - [0xFF5E]={ - category="sm", - direction="on", - }, - [0xFF5F]={ - category="ps", - direction="on", - mirror=0xFF60, - textclass="open", - }, - [0xFF60]={ - category="pe", - direction="on", - mirror=0xFF5F, - textclass="close", - }, - [0xFF61]={ - category="po", - direction="on", - }, - [0xFF62]={ - category="ps", - direction="on", - mirror=0xFF63, - textclass="open", - }, - [0xFF63]={ - category="pe", - direction="on", - mirror=0xFF62, - textclass="close", - }, - [0xFF64]={ - category="po", - direction="on", - }, - [0xFF65]={ - category="po", - direction="on", - }, - [0xFF66]={ - category="lo", - direction="l", - }, - [0xFF67]={ - category="lo", - direction="l", - }, - [0xFF68]={ - category="lo", - direction="l", - }, - [0xFF69]={ - category="lo", - direction="l", - }, - [0xFF6A]={ - category="lo", - direction="l", - }, - [0xFF6B]={ - category="lo", - direction="l", - }, - [0xFF6C]={ - category="lo", - direction="l", - }, - [0xFF6D]={ - category="lo", - direction="l", - }, - [0xFF6E]={ - category="lo", - direction="l", - }, - [0xFF6F]={ - category="lo", - direction="l", - }, - [0xFF70]={ - category="lm", - direction="l", - }, - [0xFF71]={ - category="lo", - direction="l", - }, - [0xFF72]={ - category="lo", - direction="l", - }, - [0xFF73]={ - category="lo", - direction="l", - }, - [0xFF74]={ - category="lo", - direction="l", - }, - [0xFF75]={ - category="lo", - direction="l", - }, - [0xFF76]={ - category="lo", - direction="l", - }, - [0xFF77]={ - category="lo", - direction="l", - }, - [0xFF78]={ - category="lo", - direction="l", - }, - [0xFF79]={ - category="lo", - direction="l", - }, - [0xFF7A]={ - category="lo", - direction="l", - }, - [0xFF7B]={ - category="lo", - direction="l", - }, - [0xFF7C]={ - category="lo", - direction="l", - }, - [0xFF7D]={ - category="lo", - direction="l", - }, - [0xFF7E]={ - category="lo", - direction="l", - }, - [0xFF7F]={ - category="lo", - direction="l", - }, - [0xFF80]={ - category="lo", - direction="l", - }, - [0xFF81]={ - category="lo", - direction="l", - }, - [0xFF82]={ - category="lo", - direction="l", - }, - [0xFF83]={ - category="lo", - direction="l", - }, - [0xFF84]={ - category="lo", - direction="l", - }, - [0xFF85]={ - category="lo", - direction="l", - }, - [0xFF86]={ - category="lo", - direction="l", - }, - [0xFF87]={ - category="lo", - direction="l", - }, - [0xFF88]={ - category="lo", - direction="l", - }, - [0xFF89]={ - category="lo", - direction="l", - }, - [0xFF8A]={ - category="lo", - direction="l", - }, - [0xFF8B]={ - category="lo", - direction="l", - }, - [0xFF8C]={ - category="lo", - direction="l", - }, - [0xFF8D]={ - category="lo", - direction="l", - }, - [0xFF8E]={ - category="lo", - direction="l", - }, - [0xFF8F]={ - category="lo", - direction="l", - }, - [0xFF90]={ - category="lo", - direction="l", - }, - [0xFF91]={ - category="lo", - direction="l", - }, - [0xFF92]={ - category="lo", - direction="l", - }, - [0xFF93]={ - category="lo", - direction="l", - }, - [0xFF94]={ - category="lo", - direction="l", - }, - [0xFF95]={ - category="lo", - direction="l", - }, - [0xFF96]={ - category="lo", - direction="l", - }, - [0xFF97]={ - category="lo", - direction="l", - }, - [0xFF98]={ - category="lo", - direction="l", - }, - [0xFF99]={ - category="lo", - direction="l", - }, - [0xFF9A]={ - category="lo", - direction="l", - }, - [0xFF9B]={ - category="lo", - direction="l", - }, - [0xFF9C]={ - category="lo", - direction="l", - }, - [0xFF9D]={ - category="lo", - direction="l", - }, - [0xFF9E]={ - category="lm", - direction="l", - }, - [0xFF9F]={ - category="lm", - direction="l", - }, - [0xFFA0]={ - category="lo", - direction="l", - }, - [0xFFA1]={ - category="lo", - direction="l", - }, - [0xFFA2]={ - category="lo", - direction="l", - }, - [0xFFA3]={ - category="lo", - direction="l", - }, - [0xFFA4]={ - category="lo", - direction="l", - }, - [0xFFA5]={ - category="lo", - direction="l", - }, - [0xFFA6]={ - category="lo", - direction="l", - }, - [0xFFA7]={ - category="lo", - direction="l", - }, - [0xFFA8]={ - category="lo", - direction="l", - }, - [0xFFA9]={ - category="lo", - direction="l", - }, - [0xFFAA]={ - category="lo", - direction="l", - }, - [0xFFAB]={ - category="lo", - direction="l", - }, - [0xFFAC]={ - category="lo", - direction="l", - }, - [0xFFAD]={ - category="lo", - direction="l", - }, - [0xFFAE]={ - category="lo", - direction="l", - }, - [0xFFAF]={ - category="lo", - direction="l", - }, - [0xFFB0]={ - category="lo", - direction="l", - }, - [0xFFB1]={ - category="lo", - direction="l", - }, - [0xFFB2]={ - category="lo", - direction="l", - }, - [0xFFB3]={ - category="lo", - direction="l", - }, - [0xFFB4]={ - category="lo", - direction="l", - }, - [0xFFB5]={ - category="lo", - direction="l", - }, - [0xFFB6]={ - category="lo", - direction="l", - }, - [0xFFB7]={ - category="lo", - direction="l", - }, - [0xFFB8]={ - category="lo", - direction="l", - }, - [0xFFB9]={ - category="lo", - direction="l", - }, - [0xFFBA]={ - category="lo", - direction="l", - }, - [0xFFBB]={ - category="lo", - direction="l", - }, - [0xFFBC]={ - category="lo", - direction="l", - }, - [0xFFBD]={ - category="lo", - direction="l", - }, - [0xFFBE]={ - category="lo", - direction="l", - }, - [0xFFC2]={ - category="lo", - direction="l", - }, - [0xFFC3]={ - category="lo", - direction="l", - }, - [0xFFC4]={ - category="lo", - direction="l", - }, - [0xFFC5]={ - category="lo", - direction="l", - }, - [0xFFC6]={ - category="lo", - direction="l", - }, - [0xFFC7]={ - category="lo", - direction="l", - }, - [0xFFCA]={ - category="lo", - direction="l", - }, - [0xFFCB]={ - category="lo", - direction="l", - }, - [0xFFCC]={ - category="lo", - direction="l", - }, - [0xFFCD]={ - category="lo", - direction="l", - }, - [0xFFCE]={ - category="lo", - direction="l", - }, - [0xFFCF]={ - category="lo", - direction="l", - }, - [0xFFD2]={ - category="lo", - direction="l", - }, - [0xFFD3]={ - category="lo", - direction="l", - }, - [0xFFD4]={ - category="lo", - direction="l", - }, - [0xFFD5]={ - category="lo", - direction="l", - }, - [0xFFD6]={ - category="lo", - direction="l", - }, - [0xFFD7]={ - category="lo", - direction="l", - }, - [0xFFDA]={ - category="lo", - direction="l", - }, - [0xFFDB]={ - category="lo", - direction="l", - }, - [0xFFDC]={ - category="lo", - direction="l", - }, - [0xFFE0]={ - category="sc", - direction="et", - }, - [0xFFE1]={ - category="sc", - direction="et", - }, - [0xFFE2]={ - category="sm", - direction="on", - }, - [0xFFE3]={ - category="sk", - direction="on", - }, - [0xFFE4]={ - category="so", - direction="on", - }, - [0xFFE5]={ - category="sc", - direction="et", - }, - [0xFFE6]={ - category="sc", - direction="et", - }, - [0xFFE8]={ - category="so", - direction="on", - }, - [0xFFE9]={ - category="sm", - direction="on", - }, - [0xFFEA]={ - category="sm", - direction="on", - }, - [0xFFEB]={ - category="sm", - direction="on", - }, - [0xFFEC]={ - category="sm", - direction="on", - }, - [0xFFED]={ - category="so", - direction="on", - }, - [0xFFEE]={ - category="so", - direction="on", - }, - [0xFFF9]={ - category="cf", - direction="on", - }, - [0xFFFA]={ - category="cf", - direction="on", - }, - [0xFFFB]={ - category="cf", - direction="on", - }, - [0xFFFC]={ - category="so", - direction="on", - }, - [0xFFFD]={ - category="so", - direction="on", - }, - [0x10000]={ - category="lo", - direction="l", - }, - [0x10001]={ - category="lo", - direction="l", - }, - [0x10002]={ - category="lo", - direction="l", - }, - [0x10003]={ - category="lo", - direction="l", - }, - [0x10004]={ - category="lo", - direction="l", - }, - [0x10005]={ - category="lo", - direction="l", - }, - [0x10006]={ - category="lo", - direction="l", - }, - [0x10007]={ - category="lo", - direction="l", - }, - [0x10008]={ - category="lo", - direction="l", - }, - [0x10009]={ - category="lo", - direction="l", - }, - [0x1000A]={ - category="lo", - direction="l", - }, - [0x1000B]={ - category="lo", - direction="l", - }, - [0x1000D]={ - category="lo", - direction="l", - }, - [0x1000E]={ - category="lo", - direction="l", - }, - [0x1000F]={ - category="lo", - direction="l", - }, - [0x10010]={ - category="lo", - direction="l", - }, - [0x10011]={ - category="lo", - direction="l", - }, - [0x10012]={ - category="lo", - direction="l", - }, - [0x10013]={ - category="lo", - direction="l", - }, - [0x10014]={ - category="lo", - direction="l", - }, - [0x10015]={ - category="lo", - direction="l", - }, - [0x10016]={ - category="lo", - direction="l", - }, - [0x10017]={ - category="lo", - direction="l", - }, - [0x10018]={ - category="lo", - direction="l", - }, - [0x10019]={ - category="lo", - direction="l", - }, - [0x1001A]={ - category="lo", - direction="l", - }, - [0x1001B]={ - category="lo", - direction="l", - }, - [0x1001C]={ - category="lo", - direction="l", - }, - [0x1001D]={ - category="lo", - direction="l", - }, - [0x1001E]={ - category="lo", - direction="l", - }, - [0x1001F]={ - category="lo", - direction="l", - }, - [0x10020]={ - category="lo", - direction="l", - }, - [0x10021]={ - category="lo", - direction="l", - }, - [0x10022]={ - category="lo", - direction="l", - }, - [0x10023]={ - category="lo", - direction="l", - }, - [0x10024]={ - category="lo", - direction="l", - }, - [0x10025]={ - category="lo", - direction="l", - }, - [0x10026]={ - category="lo", - direction="l", - }, - [0x10028]={ - category="lo", - direction="l", - }, - [0x10029]={ - category="lo", - direction="l", - }, - [0x1002A]={ - category="lo", - direction="l", - }, - [0x1002B]={ - category="lo", - direction="l", - }, - [0x1002C]={ - category="lo", - direction="l", - }, - [0x1002D]={ - category="lo", - direction="l", - }, - [0x1002E]={ - category="lo", - direction="l", - }, - [0x1002F]={ - category="lo", - direction="l", - }, - [0x10030]={ - category="lo", - direction="l", - }, - [0x10031]={ - category="lo", - direction="l", - }, - [0x10032]={ - category="lo", - direction="l", - }, - [0x10033]={ - category="lo", - direction="l", - }, - [0x10034]={ - category="lo", - direction="l", - }, - [0x10035]={ - category="lo", - direction="l", - }, - [0x10036]={ - category="lo", - direction="l", - }, - [0x10037]={ - category="lo", - direction="l", - }, - [0x10038]={ - category="lo", - direction="l", - }, - [0x10039]={ - category="lo", - direction="l", - }, - [0x1003A]={ - category="lo", - direction="l", - }, - [0x1003C]={ - category="lo", - direction="l", - }, - [0x1003D]={ - category="lo", - direction="l", - }, - [0x1003F]={ - category="lo", - direction="l", - }, - [0x10040]={ - category="lo", - direction="l", - }, - [0x10041]={ - category="lo", - direction="l", - }, - [0x10042]={ - category="lo", - direction="l", - }, - [0x10043]={ - category="lo", - direction="l", - }, - [0x10044]={ - category="lo", - direction="l", - }, - [0x10045]={ - category="lo", - direction="l", - }, - [0x10046]={ - category="lo", - direction="l", - }, - [0x10047]={ - category="lo", - direction="l", - }, - [0x10048]={ - category="lo", - direction="l", - }, - [0x10049]={ - category="lo", - direction="l", - }, - [0x1004A]={ - category="lo", - direction="l", - }, - [0x1004B]={ - category="lo", - direction="l", - }, - [0x1004C]={ - category="lo", - direction="l", - }, - [0x1004D]={ - category="lo", - direction="l", - }, - [0x10050]={ - category="lo", - direction="l", - }, - [0x10051]={ - category="lo", - direction="l", - }, - [0x10052]={ - category="lo", - direction="l", - }, - [0x10053]={ - category="lo", - direction="l", - }, - [0x10054]={ - category="lo", - direction="l", - }, - [0x10055]={ - category="lo", - direction="l", - }, - [0x10056]={ - category="lo", - direction="l", - }, - [0x10057]={ - category="lo", - direction="l", - }, - [0x10058]={ - category="lo", - direction="l", - }, - [0x10059]={ - category="lo", - direction="l", - }, - [0x1005A]={ - category="lo", - direction="l", - }, - [0x1005B]={ - category="lo", - direction="l", - }, - [0x1005C]={ - category="lo", - direction="l", - }, - [0x1005D]={ - category="lo", - direction="l", - }, - [0x10080]={ - category="lo", - direction="l", - }, - [0x10081]={ - category="lo", - direction="l", - }, - [0x10082]={ - category="lo", - direction="l", - }, - [0x10083]={ - category="lo", - direction="l", - }, - [0x10084]={ - category="lo", - direction="l", - }, - [0x10085]={ - category="lo", - direction="l", - }, - [0x10086]={ - category="lo", - direction="l", - }, - [0x10087]={ - category="lo", - direction="l", - }, - [0x10088]={ - category="lo", - direction="l", - }, - [0x10089]={ - category="lo", - direction="l", - }, - [0x1008A]={ - category="lo", - direction="l", - }, - [0x1008B]={ - category="lo", - direction="l", - }, - [0x1008C]={ - category="lo", - direction="l", - }, - [0x1008D]={ - category="lo", - direction="l", - }, - [0x1008E]={ - category="lo", - direction="l", - }, - [0x1008F]={ - category="lo", - direction="l", - }, - [0x10090]={ - category="lo", - direction="l", - }, - [0x10091]={ - category="lo", - direction="l", - }, - [0x10092]={ - category="lo", - direction="l", - }, - [0x10093]={ - category="lo", - direction="l", - }, - [0x10094]={ - category="lo", - direction="l", - }, - [0x10095]={ - category="lo", - direction="l", - }, - [0x10096]={ - category="lo", - direction="l", - }, - [0x10097]={ - category="lo", - direction="l", - }, - [0x10098]={ - category="lo", - direction="l", - }, - [0x10099]={ - category="lo", - direction="l", - }, - [0x1009A]={ - category="lo", - direction="l", - }, - [0x1009B]={ - category="lo", - direction="l", - }, - [0x1009C]={ - category="lo", - direction="l", - }, - [0x1009D]={ - category="lo", - direction="l", - }, - [0x1009E]={ - category="lo", - direction="l", - }, - [0x1009F]={ - category="lo", - direction="l", - }, - [0x100A0]={ - category="lo", - direction="l", - }, - [0x100A1]={ - category="lo", - direction="l", - }, - [0x100A2]={ - category="lo", - direction="l", - }, - [0x100A3]={ - category="lo", - direction="l", - }, - [0x100A4]={ - category="lo", - direction="l", - }, - [0x100A5]={ - category="lo", - direction="l", - }, - [0x100A6]={ - category="lo", - direction="l", - }, - [0x100A7]={ - category="lo", - direction="l", - }, - [0x100A8]={ - category="lo", - direction="l", - }, - [0x100A9]={ - category="lo", - direction="l", - }, - [0x100AA]={ - category="lo", - direction="l", - }, - [0x100AB]={ - category="lo", - direction="l", - }, - [0x100AC]={ - category="lo", - direction="l", - }, - [0x100AD]={ - category="lo", - direction="l", - }, - [0x100AE]={ - category="lo", - direction="l", - }, - [0x100AF]={ - category="lo", - direction="l", - }, - [0x100B0]={ - category="lo", - direction="l", - }, - [0x100B1]={ - category="lo", - direction="l", - }, - [0x100B2]={ - category="lo", - direction="l", - }, - [0x100B3]={ - category="lo", - direction="l", - }, - [0x100B4]={ - category="lo", - direction="l", - }, - [0x100B5]={ - category="lo", - direction="l", - }, - [0x100B6]={ - category="lo", - direction="l", - }, - [0x100B7]={ - category="lo", - direction="l", - }, - [0x100B8]={ - category="lo", - direction="l", - }, - [0x100B9]={ - category="lo", - direction="l", - }, - [0x100BA]={ - category="lo", - direction="l", - }, - [0x100BB]={ - category="lo", - direction="l", - }, - [0x100BC]={ - category="lo", - direction="l", - }, - [0x100BD]={ - category="lo", - direction="l", - }, - [0x100BE]={ - category="lo", - direction="l", - }, - [0x100BF]={ - category="lo", - direction="l", - }, - [0x100C0]={ - category="lo", - direction="l", - }, - [0x100C1]={ - category="lo", - direction="l", - }, - [0x100C2]={ - category="lo", - direction="l", - }, - [0x100C3]={ - category="lo", - direction="l", - }, - [0x100C4]={ - category="lo", - direction="l", - }, - [0x100C5]={ - category="lo", - direction="l", - }, - [0x100C6]={ - category="lo", - direction="l", - }, - [0x100C7]={ - category="lo", - direction="l", - }, - [0x100C8]={ - category="lo", - direction="l", - }, - [0x100C9]={ - category="lo", - direction="l", - }, - [0x100CA]={ - category="lo", - direction="l", - }, - [0x100CB]={ - category="lo", - direction="l", - }, - [0x100CC]={ - category="lo", - direction="l", - }, - [0x100CD]={ - category="lo", - direction="l", - }, - [0x100CE]={ - category="lo", - direction="l", - }, - [0x100CF]={ - category="lo", - direction="l", - }, - [0x100D0]={ - category="lo", - direction="l", - }, - [0x100D1]={ - category="lo", - direction="l", - }, - [0x100D2]={ - category="lo", - direction="l", - }, - [0x100D3]={ - category="lo", - direction="l", - }, - [0x100D4]={ - category="lo", - direction="l", - }, - [0x100D5]={ - category="lo", - direction="l", - }, - [0x100D6]={ - category="lo", - direction="l", - }, - [0x100D7]={ - category="lo", - direction="l", - }, - [0x100D8]={ - category="lo", - direction="l", - }, - [0x100D9]={ - category="lo", - direction="l", - }, - [0x100DA]={ - category="lo", - direction="l", - }, - [0x100DB]={ - category="lo", - direction="l", - }, - [0x100DC]={ - category="lo", - direction="l", - }, - [0x100DD]={ - category="lo", - direction="l", - }, - [0x100DE]={ - category="lo", - direction="l", - }, - [0x100DF]={ - category="lo", - direction="l", - }, - [0x100E0]={ - category="lo", - direction="l", - }, - [0x100E1]={ - category="lo", - direction="l", - }, - [0x100E2]={ - category="lo", - direction="l", - }, - [0x100E3]={ - category="lo", - direction="l", - }, - [0x100E4]={ - category="lo", - direction="l", - }, - [0x100E5]={ - category="lo", - direction="l", - }, - [0x100E6]={ - category="lo", - direction="l", - }, - [0x100E7]={ - category="lo", - direction="l", - }, - [0x100E8]={ - category="lo", - direction="l", - }, - [0x100E9]={ - category="lo", - direction="l", - }, - [0x100EA]={ - category="lo", - direction="l", - }, - [0x100EB]={ - category="lo", - direction="l", - }, - [0x100EC]={ - category="lo", - direction="l", - }, - [0x100ED]={ - category="lo", - direction="l", - }, - [0x100EE]={ - category="lo", - direction="l", - }, - [0x100EF]={ - category="lo", - direction="l", - }, - [0x100F0]={ - category="lo", - direction="l", - }, - [0x100F1]={ - category="lo", - direction="l", - }, - [0x100F2]={ - category="lo", - direction="l", - }, - [0x100F3]={ - category="lo", - direction="l", - }, - [0x100F4]={ - category="lo", - direction="l", - }, - [0x100F5]={ - category="lo", - direction="l", - }, - [0x100F6]={ - category="lo", - direction="l", - }, - [0x100F7]={ - category="lo", - direction="l", - }, - [0x100F8]={ - category="lo", - direction="l", - }, - [0x100F9]={ - category="lo", - direction="l", - }, - [0x100FA]={ - category="lo", - direction="l", - }, - [0x10100]={ - category="po", - direction="l", - }, - [0x10101]={ - category="po", - direction="on", - }, - [0x10102]={ - category="so", - direction="l", - }, - [0x10107]={ - category="no", - direction="l", - }, - [0x10108]={ - category="no", - direction="l", - }, - [0x10109]={ - category="no", - direction="l", - }, - [0x1010A]={ - category="no", - direction="l", - }, - [0x1010B]={ - category="no", - direction="l", - }, - [0x1010C]={ - category="no", - direction="l", - }, - [0x1010D]={ - category="no", - direction="l", - }, - [0x1010E]={ - category="no", - direction="l", - }, - [0x1010F]={ - category="no", - direction="l", - }, - [0x10110]={ - category="no", - direction="l", - }, - [0x10111]={ - category="no", - direction="l", - }, - [0x10112]={ - category="no", - direction="l", - }, - [0x10113]={ - category="no", - direction="l", - }, - [0x10114]={ - category="no", - direction="l", - }, - [0x10115]={ - category="no", - direction="l", - }, - [0x10116]={ - category="no", - direction="l", - }, - [0x10117]={ - category="no", - direction="l", - }, - [0x10118]={ - category="no", - direction="l", - }, - [0x10119]={ - category="no", - direction="l", - }, - [0x1011A]={ - category="no", - direction="l", - }, - [0x1011B]={ - category="no", - direction="l", - }, - [0x1011C]={ - category="no", - direction="l", - }, - [0x1011D]={ - category="no", - direction="l", - }, - [0x1011E]={ - category="no", - direction="l", - }, - [0x1011F]={ - category="no", - direction="l", - }, - [0x10120]={ - category="no", - direction="l", - }, - [0x10121]={ - category="no", - direction="l", - }, - [0x10122]={ - category="no", - direction="l", - }, - [0x10123]={ - category="no", - direction="l", - }, - [0x10124]={ - category="no", - direction="l", - }, - [0x10125]={ - category="no", - direction="l", - }, - [0x10126]={ - category="no", - direction="l", - }, - [0x10127]={ - category="no", - direction="l", - }, - [0x10128]={ - category="no", - direction="l", - }, - [0x10129]={ - category="no", - direction="l", - }, - [0x1012A]={ - category="no", - direction="l", - }, - [0x1012B]={ - category="no", - direction="l", - }, - [0x1012C]={ - category="no", - direction="l", - }, - [0x1012D]={ - category="no", - direction="l", - }, - [0x1012E]={ - category="no", - direction="l", - }, - [0x1012F]={ - category="no", - direction="l", - }, - [0x10130]={ - category="no", - direction="l", - }, - [0x10131]={ - category="no", - direction="l", - }, - [0x10132]={ - category="no", - direction="l", - }, - [0x10133]={ - category="no", - direction="l", - }, - [0x10137]={ - category="so", - direction="l", - }, - [0x10138]={ - category="so", - direction="l", - }, - [0x10139]={ - category="so", - direction="l", - }, - [0x1013A]={ - category="so", - direction="l", - }, - [0x1013B]={ - category="so", - direction="l", - }, - [0x1013C]={ - category="so", - direction="l", - }, - [0x1013D]={ - category="so", - direction="l", - }, - [0x1013E]={ - category="so", - direction="l", - }, - [0x1013F]={ - category="so", - direction="l", - }, - [0x10140]={ - category="nl", - direction="on", - }, - [0x10141]={ - category="nl", - direction="on", - }, - [0x10142]={ - category="nl", - direction="on", - }, - [0x10143]={ - category="nl", - direction="on", - }, - [0x10144]={ - category="nl", - direction="on", - }, - [0x10145]={ - category="nl", - direction="on", - }, - [0x10146]={ - category="nl", - direction="on", - }, - [0x10147]={ - category="nl", - direction="on", - }, - [0x10148]={ - category="nl", - direction="on", - }, - [0x10149]={ - category="nl", - direction="on", - }, - [0x1014A]={ - category="nl", - direction="on", - }, - [0x1014B]={ - category="nl", - direction="on", - }, - [0x1014C]={ - category="nl", - direction="on", - }, - [0x1014D]={ - category="nl", - direction="on", - }, - [0x1014E]={ - category="nl", - direction="on", - }, - [0x1014F]={ - category="nl", - direction="on", - }, - [0x10150]={ - category="nl", - direction="on", - }, - [0x10151]={ - category="nl", - direction="on", - }, - [0x10152]={ - category="nl", - direction="on", - }, - [0x10153]={ - category="nl", - direction="on", - }, - [0x10154]={ - category="nl", - direction="on", - }, - [0x10155]={ - category="nl", - direction="on", - }, - [0x10156]={ - category="nl", - direction="on", - }, - [0x10157]={ - category="nl", - direction="on", - }, - [0x10158]={ - category="nl", - direction="on", - }, - [0x10159]={ - category="nl", - direction="on", - }, - [0x1015A]={ - category="nl", - direction="on", - }, - [0x1015B]={ - category="nl", - direction="on", - }, - [0x1015C]={ - category="nl", - direction="on", - }, - [0x1015D]={ - category="nl", - direction="on", - }, - [0x1015E]={ - category="nl", - direction="on", - }, - [0x1015F]={ - category="nl", - direction="on", - }, - [0x10160]={ - category="nl", - direction="on", - }, - [0x10161]={ - category="nl", - direction="on", - }, - [0x10162]={ - category="nl", - direction="on", - }, - [0x10163]={ - category="nl", - direction="on", - }, - [0x10164]={ - category="nl", - direction="on", - }, - [0x10165]={ - category="nl", - direction="on", - }, - [0x10166]={ - category="nl", - direction="on", - }, - [0x10167]={ - category="nl", - direction="on", - }, - [0x10168]={ - category="nl", - direction="on", - }, - [0x10169]={ - category="nl", - direction="on", - }, - [0x1016A]={ - category="nl", - direction="on", - }, - [0x1016B]={ - category="nl", - direction="on", - }, - [0x1016C]={ - category="nl", - direction="on", - }, - [0x1016D]={ - category="nl", - direction="on", - }, - [0x1016E]={ - category="nl", - direction="on", - }, - [0x1016F]={ - category="nl", - direction="on", - }, - [0x10170]={ - category="nl", - direction="on", - }, - [0x10171]={ - category="nl", - direction="on", - }, - [0x10172]={ - category="nl", - direction="on", - }, - [0x10173]={ - category="nl", - direction="on", - }, - [0x10174]={ - category="nl", - direction="on", - }, - [0x10175]={ - category="no", - direction="on", - }, - [0x10176]={ - category="no", - direction="on", - }, - [0x10177]={ - category="no", - direction="on", - }, - [0x10178]={ - category="no", - direction="on", - }, - [0x10179]={ - category="so", - direction="on", - }, - [0x1017A]={ - category="so", - direction="on", - }, - [0x1017B]={ - category="so", - direction="on", - }, - [0x1017C]={ - category="so", - direction="on", - }, - [0x1017D]={ - category="so", - direction="on", - }, - [0x1017E]={ - category="so", - direction="on", - }, - [0x1017F]={ - category="so", - direction="on", - }, - [0x10180]={ - category="so", - direction="on", - }, - [0x10181]={ - category="so", - direction="on", - }, - [0x10182]={ - category="so", - direction="on", - }, - [0x10183]={ - category="so", - direction="on", - }, - [0x10184]={ - category="so", - direction="on", - }, - [0x10185]={ - category="so", - direction="on", - }, - [0x10186]={ - category="so", - direction="on", - }, - [0x10187]={ - category="so", - direction="on", - }, - [0x10188]={ - category="so", - direction="on", - }, - [0x10189]={ - category="so", - direction="on", - }, - [0x1018A]={ - category="no", - direction="on", - }, - [0x1018B]={ - category="no", - direction="on", - }, - [0x1018C]={ - category="so", - direction="on", - }, - [0x1018D]={ - category="so", - direction="l", - }, - [0x1018E]={ - category="so", - direction="l", - }, - [0x10190]={ - category="so", - direction="on", - }, - [0x10191]={ - category="so", - direction="on", - }, - [0x10192]={ - category="so", - direction="on", - }, - [0x10193]={ - category="so", - direction="on", - }, - [0x10194]={ - category="so", - direction="on", - }, - [0x10195]={ - category="so", - direction="on", - }, - [0x10196]={ - category="so", - direction="on", - }, - [0x10197]={ - category="so", - direction="on", - }, - [0x10198]={ - category="so", - direction="on", - }, - [0x10199]={ - category="so", - direction="on", - }, - [0x1019A]={ - category="so", - direction="on", - }, - [0x1019B]={ - category="so", - direction="on", - }, - [0x101A0]={ - category="so", - direction="on", - }, - [0x101D0]={ - category="so", - direction="l", - }, - [0x101D1]={ - category="so", - direction="l", - }, - [0x101D2]={ - category="so", - direction="l", - }, - [0x101D3]={ - category="so", - direction="l", - }, - [0x101D4]={ - category="so", - direction="l", - }, - [0x101D5]={ - category="so", - direction="l", - }, - [0x101D6]={ - category="so", - direction="l", - }, - [0x101D7]={ - category="so", - direction="l", - }, - [0x101D8]={ - category="so", - direction="l", - }, - [0x101D9]={ - category="so", - direction="l", - }, - [0x101DA]={ - category="so", - direction="l", - }, - [0x101DB]={ - category="so", - direction="l", - }, - [0x101DC]={ - category="so", - direction="l", - }, - [0x101DD]={ - category="so", - direction="l", - }, - [0x101DE]={ - category="so", - direction="l", - }, - [0x101DF]={ - category="so", - direction="l", - }, - [0x101E0]={ - category="so", - direction="l", - }, - [0x101E1]={ - category="so", - direction="l", - }, - [0x101E2]={ - category="so", - direction="l", - }, - [0x101E3]={ - category="so", - direction="l", - }, - [0x101E4]={ - category="so", - direction="l", - }, - [0x101E5]={ - category="so", - direction="l", - }, - [0x101E6]={ - category="so", - direction="l", - }, - [0x101E7]={ - category="so", - direction="l", - }, - [0x101E8]={ - category="so", - direction="l", - }, - [0x101E9]={ - category="so", - direction="l", - }, - [0x101EA]={ - category="so", - direction="l", - }, - [0x101EB]={ - category="so", - direction="l", - }, - [0x101EC]={ - category="so", - direction="l", - }, - [0x101ED]={ - category="so", - direction="l", - }, - [0x101EE]={ - category="so", - direction="l", - }, - [0x101EF]={ - category="so", - direction="l", - }, - [0x101F0]={ - category="so", - direction="l", - }, - [0x101F1]={ - category="so", - direction="l", - }, - [0x101F2]={ - category="so", - direction="l", - }, - [0x101F3]={ - category="so", - direction="l", - }, - [0x101F4]={ - category="so", - direction="l", - }, - [0x101F5]={ - category="so", - direction="l", - }, - [0x101F6]={ - category="so", - direction="l", - }, - [0x101F7]={ - category="so", - direction="l", - }, - [0x101F8]={ - category="so", - direction="l", - }, - [0x101F9]={ - category="so", - direction="l", - }, - [0x101FA]={ - category="so", - direction="l", - }, - [0x101FB]={ - category="so", - direction="l", - }, - [0x101FC]={ - category="so", - direction="l", - }, - [0x101FD]={ - category="mn", - direction="nsm", - }, - [0x10280]={ - category="lo", - direction="l", - }, - [0x10281]={ - category="lo", - direction="l", - }, - [0x10282]={ - category="lo", - direction="l", - }, - [0x10283]={ - category="lo", - direction="l", - }, - [0x10284]={ - category="lo", - direction="l", - }, - [0x10285]={ - category="lo", - direction="l", - }, - [0x10286]={ - category="lo", - direction="l", - }, - [0x10287]={ - category="lo", - direction="l", - }, - [0x10288]={ - category="lo", - direction="l", - }, - [0x10289]={ - category="lo", - direction="l", - }, - [0x1028A]={ - category="lo", - direction="l", - }, - [0x1028B]={ - category="lo", - direction="l", - }, - [0x1028C]={ - category="lo", - direction="l", - }, - [0x1028D]={ - category="lo", - direction="l", - }, - [0x1028E]={ - category="lo", - direction="l", - }, - [0x1028F]={ - category="lo", - direction="l", - }, - [0x10290]={ - category="lo", - direction="l", - }, - [0x10291]={ - category="lo", - direction="l", - }, - [0x10292]={ - category="lo", - direction="l", - }, - [0x10293]={ - category="lo", - direction="l", - }, - [0x10294]={ - category="lo", - direction="l", - }, - [0x10295]={ - category="lo", - direction="l", - }, - [0x10296]={ - category="lo", - direction="l", - }, - [0x10297]={ - category="lo", - direction="l", - }, - [0x10298]={ - category="lo", - direction="l", - }, - [0x10299]={ - category="lo", - direction="l", - }, - [0x1029A]={ - category="lo", - direction="l", - }, - [0x1029B]={ - category="lo", - direction="l", - }, - [0x1029C]={ - category="lo", - direction="l", - }, - [0x102A0]={ - category="lo", - direction="l", - }, - [0x102A1]={ - category="lo", - direction="l", - }, - [0x102A2]={ - category="lo", - direction="l", - }, - [0x102A3]={ - category="lo", - direction="l", - }, - [0x102A4]={ - category="lo", - direction="l", - }, - [0x102A5]={ - category="lo", - direction="l", - }, - [0x102A6]={ - category="lo", - direction="l", - }, - [0x102A7]={ - category="lo", - direction="l", - }, - [0x102A8]={ - category="lo", - direction="l", - }, - [0x102A9]={ - category="lo", - direction="l", - }, - [0x102AA]={ - category="lo", - direction="l", - }, - [0x102AB]={ - category="lo", - direction="l", - }, - [0x102AC]={ - category="lo", - direction="l", - }, - [0x102AD]={ - category="lo", - direction="l", - }, - [0x102AE]={ - category="lo", - direction="l", - }, - [0x102AF]={ - category="lo", - direction="l", - }, - [0x102B0]={ - category="lo", - direction="l", - }, - [0x102B1]={ - category="lo", - direction="l", - }, - [0x102B2]={ - category="lo", - direction="l", - }, - [0x102B3]={ - category="lo", - direction="l", - }, - [0x102B4]={ - category="lo", - direction="l", - }, - [0x102B5]={ - category="lo", - direction="l", - }, - [0x102B6]={ - category="lo", - direction="l", - }, - [0x102B7]={ - category="lo", - direction="l", - }, - [0x102B8]={ - category="lo", - direction="l", - }, - [0x102B9]={ - category="lo", - direction="l", - }, - [0x102BA]={ - category="lo", - direction="l", - }, - [0x102BB]={ - category="lo", - direction="l", - }, - [0x102BC]={ - category="lo", - direction="l", - }, - [0x102BD]={ - category="lo", - direction="l", - }, - [0x102BE]={ - category="lo", - direction="l", - }, - [0x102BF]={ - category="lo", - direction="l", - }, - [0x102C0]={ - category="lo", - direction="l", - }, - [0x102C1]={ - category="lo", - direction="l", - }, - [0x102C2]={ - category="lo", - direction="l", - }, - [0x102C3]={ - category="lo", - direction="l", - }, - [0x102C4]={ - category="lo", - direction="l", - }, - [0x102C5]={ - category="lo", - direction="l", - }, - [0x102C6]={ - category="lo", - direction="l", - }, - [0x102C7]={ - category="lo", - direction="l", - }, - [0x102C8]={ - category="lo", - direction="l", - }, - [0x102C9]={ - category="lo", - direction="l", - }, - [0x102CA]={ - category="lo", - direction="l", - }, - [0x102CB]={ - category="lo", - direction="l", - }, - [0x102CC]={ - category="lo", - direction="l", - }, - [0x102CD]={ - category="lo", - direction="l", - }, - [0x102CE]={ - category="lo", - direction="l", - }, - [0x102CF]={ - category="lo", - direction="l", - }, - [0x102D0]={ - category="lo", - direction="l", - }, - [0x102E0]={ - category="mn", - direction="nsm", - }, - [0x102E1]={ - category="no", - direction="en", - }, - [0x102E2]={ - category="no", - direction="en", - }, - [0x102E3]={ - category="no", - direction="en", - }, - [0x102E4]={ - category="no", - direction="en", - }, - [0x102E5]={ - category="no", - direction="en", - }, - [0x102E6]={ - category="no", - direction="en", - }, - [0x102E7]={ - category="no", - direction="en", - }, - [0x102E8]={ - category="no", - direction="en", - }, - [0x102E9]={ - category="no", - direction="en", - }, - [0x102EA]={ - category="no", - direction="en", - }, - [0x102EB]={ - category="no", - direction="en", - }, - [0x102EC]={ - category="no", - direction="en", - }, - [0x102ED]={ - category="no", - direction="en", - }, - [0x102EE]={ - category="no", - direction="en", - }, - [0x102EF]={ - category="no", - direction="en", - }, - [0x102F0]={ - category="no", - direction="en", - }, - [0x102F1]={ - category="no", - direction="en", - }, - [0x102F2]={ - category="no", - direction="en", - }, - [0x102F3]={ - category="no", - direction="en", - }, - [0x102F4]={ - category="no", - direction="en", - }, - [0x102F5]={ - category="no", - direction="en", - }, - [0x102F6]={ - category="no", - direction="en", - }, - [0x102F7]={ - category="no", - direction="en", - }, - [0x102F8]={ - category="no", - direction="en", - }, - [0x102F9]={ - category="no", - direction="en", - }, - [0x102FA]={ - category="no", - direction="en", - }, - [0x102FB]={ - category="no", - direction="en", - }, - [0x10300]={ - category="lo", - direction="l", - }, - [0x10301]={ - category="lo", - direction="l", - }, - [0x10302]={ - category="lo", - direction="l", - }, - [0x10303]={ - category="lo", - direction="l", - }, - [0x10304]={ - category="lo", - direction="l", - }, - [0x10305]={ - category="lo", - direction="l", - }, - [0x10306]={ - category="lo", - direction="l", - }, - [0x10307]={ - category="lo", - direction="l", - }, - [0x10308]={ - category="lo", - direction="l", - }, - [0x10309]={ - category="lo", - direction="l", - }, - [0x1030A]={ - category="lo", - direction="l", - }, - [0x1030B]={ - category="lo", - direction="l", - }, - [0x1030C]={ - category="lo", - direction="l", - }, - [0x1030D]={ - category="lo", - direction="l", - }, - [0x1030E]={ - category="lo", - direction="l", - }, - [0x1030F]={ - category="lo", - direction="l", - }, - [0x10310]={ - category="lo", - direction="l", - }, - [0x10311]={ - category="lo", - direction="l", - }, - [0x10312]={ - category="lo", - direction="l", - }, - [0x10313]={ - category="lo", - direction="l", - }, - [0x10314]={ - category="lo", - direction="l", - }, - [0x10315]={ - category="lo", - direction="l", - }, - [0x10316]={ - category="lo", - direction="l", - }, - [0x10317]={ - category="lo", - direction="l", - }, - [0x10318]={ - category="lo", - direction="l", - }, - [0x10319]={ - category="lo", - direction="l", - }, - [0x1031A]={ - category="lo", - direction="l", - }, - [0x1031B]={ - category="lo", - direction="l", - }, - [0x1031C]={ - category="lo", - direction="l", - }, - [0x1031D]={ - category="lo", - direction="l", - }, - [0x1031E]={ - category="lo", - direction="l", - }, - [0x1031F]={ - category="lo", - direction="l", - }, - [0x10320]={ - category="no", - direction="l", - }, - [0x10321]={ - category="no", - direction="l", - }, - [0x10322]={ - category="no", - direction="l", - }, - [0x10323]={ - category="no", - direction="l", - }, - [0x10330]={ - category="lo", - direction="l", - }, - [0x10331]={ - category="lo", - direction="l", - }, - [0x10332]={ - category="lo", - direction="l", - }, - [0x10333]={ - category="lo", - direction="l", - }, - [0x10334]={ - category="lo", - direction="l", - }, - [0x10335]={ - category="lo", - direction="l", - }, - [0x10336]={ - category="lo", - direction="l", - }, - [0x10337]={ - category="lo", - direction="l", - }, - [0x10338]={ - category="lo", - direction="l", - }, - [0x10339]={ - category="lo", - direction="l", - }, - [0x1033A]={ - category="lo", - direction="l", - }, - [0x1033B]={ - category="lo", - direction="l", - }, - [0x1033C]={ - category="lo", - direction="l", - }, - [0x1033D]={ - category="lo", - direction="l", - }, - [0x1033E]={ - category="lo", - direction="l", - }, - [0x1033F]={ - category="lo", - direction="l", - }, - [0x10340]={ - category="lo", - direction="l", - }, - [0x10341]={ - category="nl", - direction="l", - }, - [0x10342]={ - category="lo", - direction="l", - }, - [0x10343]={ - category="lo", - direction="l", - }, - [0x10344]={ - category="lo", - direction="l", - }, - [0x10345]={ - category="lo", - direction="l", - }, - [0x10346]={ - category="lo", - direction="l", - }, - [0x10347]={ - category="lo", - direction="l", - }, - [0x10348]={ - category="lo", - direction="l", - }, - [0x10349]={ - category="lo", - direction="l", - }, - [0x1034A]={ - category="nl", - direction="l", - }, - [0x10350]={ - category="lo", - direction="l", - }, - [0x10351]={ - category="lo", - direction="l", - }, - [0x10352]={ - category="lo", - direction="l", - }, - [0x10353]={ - category="lo", - direction="l", - }, - [0x10354]={ - category="lo", - direction="l", - }, - [0x10355]={ - category="lo", - direction="l", - }, - [0x10356]={ - category="lo", - direction="l", - }, - [0x10357]={ - category="lo", - direction="l", - }, - [0x10358]={ - category="lo", - direction="l", - }, - [0x10359]={ - category="lo", - direction="l", - }, - [0x1035A]={ - category="lo", - direction="l", - }, - [0x1035B]={ - category="lo", - direction="l", - }, - [0x1035C]={ - category="lo", - direction="l", - }, - [0x1035D]={ - category="lo", - direction="l", - }, - [0x1035E]={ - category="lo", - direction="l", - }, - [0x1035F]={ - category="lo", - direction="l", - }, - [0x10360]={ - category="lo", - direction="l", - }, - [0x10361]={ - category="lo", - direction="l", - }, - [0x10362]={ - category="lo", - direction="l", - }, - [0x10363]={ - category="lo", - direction="l", - }, - [0x10364]={ - category="lo", - direction="l", - }, - [0x10365]={ - category="lo", - direction="l", - }, - [0x10366]={ - category="lo", - direction="l", - }, - [0x10367]={ - category="lo", - direction="l", - }, - [0x10368]={ - category="lo", - direction="l", - }, - [0x10369]={ - category="lo", - direction="l", - }, - [0x1036A]={ - category="lo", - direction="l", - }, - [0x1036B]={ - category="lo", - direction="l", - }, - [0x1036C]={ - category="lo", - direction="l", - }, - [0x1036D]={ - category="lo", - direction="l", - }, - [0x1036E]={ - category="lo", - direction="l", - }, - [0x1036F]={ - category="lo", - direction="l", - }, - [0x10370]={ - category="lo", - direction="l", - }, - [0x10371]={ - category="lo", - direction="l", - }, - [0x10372]={ - category="lo", - direction="l", - }, - [0x10373]={ - category="lo", - direction="l", - }, - [0x10374]={ - category="lo", - direction="l", - }, - [0x10375]={ - category="lo", - direction="l", - }, - [0x10376]={ - category="mn", - direction="nsm", - }, - [0x10377]={ - category="mn", - direction="nsm", - }, - [0x10378]={ - category="mn", - direction="nsm", - }, - [0x10379]={ - category="mn", - direction="nsm", - }, - [0x1037A]={ - category="mn", - direction="nsm", - }, - [0x10380]={ - category="lo", - direction="l", - }, - [0x10381]={ - category="lo", - direction="l", - }, - [0x10382]={ - category="lo", - direction="l", - }, - [0x10383]={ - category="lo", - direction="l", - }, - [0x10384]={ - category="lo", - direction="l", - }, - [0x10385]={ - category="lo", - direction="l", - }, - [0x10386]={ - category="lo", - direction="l", - }, - [0x10387]={ - category="lo", - direction="l", - }, - [0x10388]={ - category="lo", - direction="l", - }, - [0x10389]={ - category="lo", - direction="l", - }, - [0x1038A]={ - category="lo", - direction="l", - }, - [0x1038B]={ - category="lo", - direction="l", - }, - [0x1038C]={ - category="lo", - direction="l", - }, - [0x1038D]={ - category="lo", - direction="l", - }, - [0x1038E]={ - category="lo", - direction="l", - }, - [0x1038F]={ - category="lo", - direction="l", - }, - [0x10390]={ - category="lo", - direction="l", - }, - [0x10391]={ - category="lo", - direction="l", - }, - [0x10392]={ - category="lo", - direction="l", - }, - [0x10393]={ - category="lo", - direction="l", - }, - [0x10394]={ - category="lo", - direction="l", - }, - [0x10395]={ - category="lo", - direction="l", - }, - [0x10396]={ - category="lo", - direction="l", - }, - [0x10397]={ - category="lo", - direction="l", - }, - [0x10398]={ - category="lo", - direction="l", - }, - [0x10399]={ - category="lo", - direction="l", - }, - [0x1039A]={ - category="lo", - direction="l", - }, - [0x1039B]={ - category="lo", - direction="l", - }, - [0x1039C]={ - category="lo", - direction="l", - }, - [0x1039D]={ - category="lo", - direction="l", - }, - [0x1039F]={ - category="po", - direction="l", - }, - [0x103A0]={ - category="lo", - direction="l", - }, - [0x103A1]={ - category="lo", - direction="l", - }, - [0x103A2]={ - category="lo", - direction="l", - }, - [0x103A3]={ - category="lo", - direction="l", - }, - [0x103A4]={ - category="lo", - direction="l", - }, - [0x103A5]={ - category="lo", - direction="l", - }, - [0x103A6]={ - category="lo", - direction="l", - }, - [0x103A7]={ - category="lo", - direction="l", - }, - [0x103A8]={ - category="lo", - direction="l", - }, - [0x103A9]={ - category="lo", - direction="l", - }, - [0x103AA]={ - category="lo", - direction="l", - }, - [0x103AB]={ - category="lo", - direction="l", - }, - [0x103AC]={ - category="lo", - direction="l", - }, - [0x103AD]={ - category="lo", - direction="l", - }, - [0x103AE]={ - category="lo", - direction="l", - }, - [0x103AF]={ - category="lo", - direction="l", - }, - [0x103B0]={ - category="lo", - direction="l", - }, - [0x103B1]={ - category="lo", - direction="l", - }, - [0x103B2]={ - category="lo", - direction="l", - }, - [0x103B3]={ - category="lo", - direction="l", - }, - [0x103B4]={ - category="lo", - direction="l", - }, - [0x103B5]={ - category="lo", - direction="l", - }, - [0x103B6]={ - category="lo", - direction="l", - }, - [0x103B7]={ - category="lo", - direction="l", - }, - [0x103B8]={ - category="lo", - direction="l", - }, - [0x103B9]={ - category="lo", - direction="l", - }, - [0x103BA]={ - category="lo", - direction="l", - }, - [0x103BB]={ - category="lo", - direction="l", - }, - [0x103BC]={ - category="lo", - direction="l", - }, - [0x103BD]={ - category="lo", - direction="l", - }, - [0x103BE]={ - category="lo", - direction="l", - }, - [0x103BF]={ - category="lo", - direction="l", - }, - [0x103C0]={ - category="lo", - direction="l", - }, - [0x103C1]={ - category="lo", - direction="l", - }, - [0x103C2]={ - category="lo", - direction="l", - }, - [0x103C3]={ - category="lo", - direction="l", - }, - [0x103C8]={ - category="lo", - direction="l", - }, - [0x103C9]={ - category="lo", - direction="l", - }, - [0x103CA]={ - category="lo", - direction="l", - }, - [0x103CB]={ - category="lo", - direction="l", - }, - [0x103CC]={ - category="lo", - direction="l", - }, - [0x103CD]={ - category="lo", - direction="l", - }, - [0x103CE]={ - category="lo", - direction="l", - }, - [0x103CF]={ - category="lo", - direction="l", - }, - [0x103D0]={ - category="po", - direction="l", - }, - [0x103D1]={ - category="nl", - direction="l", - }, - [0x103D2]={ - category="nl", - direction="l", - }, - [0x103D3]={ - category="nl", - direction="l", - }, - [0x103D4]={ - category="nl", - direction="l", - }, - [0x103D5]={ - category="nl", - direction="l", - }, - [0x10400]={ - category="lu", - direction="l", - }, - [0x10401]={ - category="lu", - direction="l", - }, - [0x10402]={ - category="lu", - direction="l", - }, - [0x10403]={ - category="lu", - direction="l", - }, - [0x10404]={ - category="lu", - direction="l", - }, - [0x10405]={ - category="lu", - direction="l", - }, - [0x10406]={ - category="lu", - direction="l", - }, - [0x10407]={ - category="lu", - direction="l", - }, - [0x10408]={ - category="lu", - direction="l", - }, - [0x10409]={ - category="lu", - direction="l", - }, - [0x1040A]={ - category="lu", - direction="l", - }, - [0x1040B]={ - category="lu", - direction="l", - }, - [0x1040C]={ - category="lu", - direction="l", - }, - [0x1040D]={ - category="lu", - direction="l", - }, - [0x1040E]={ - category="lu", - direction="l", - }, - [0x1040F]={ - category="lu", - direction="l", - }, - [0x10410]={ - category="lu", - direction="l", - }, - [0x10411]={ - category="lu", - direction="l", - }, - [0x10412]={ - category="lu", - direction="l", - }, - [0x10413]={ - category="lu", - direction="l", - }, - [0x10414]={ - category="lu", - direction="l", - }, - [0x10415]={ - category="lu", - direction="l", - }, - [0x10416]={ - category="lu", - direction="l", - }, - [0x10417]={ - category="lu", - direction="l", - }, - [0x10418]={ - category="lu", - direction="l", - }, - [0x10419]={ - category="lu", - direction="l", - }, - [0x1041A]={ - category="lu", - direction="l", - }, - [0x1041B]={ - category="lu", - direction="l", - }, - [0x1041C]={ - category="lu", - direction="l", - }, - [0x1041D]={ - category="lu", - direction="l", - }, - [0x1041E]={ - category="lu", - direction="l", - }, - [0x1041F]={ - category="lu", - direction="l", - }, - [0x10420]={ - category="lu", - direction="l", - }, - [0x10421]={ - category="lu", - direction="l", - }, - [0x10422]={ - category="lu", - direction="l", - }, - [0x10423]={ - category="lu", - direction="l", - }, - [0x10424]={ - category="lu", - direction="l", - }, - [0x10425]={ - category="lu", - direction="l", - }, - [0x10426]={ - category="lu", - direction="l", - }, - [0x10427]={ - category="lu", - direction="l", - }, - [0x10428]={ - category="ll", - direction="l", - }, - [0x10429]={ - category="ll", - direction="l", - }, - [0x1042A]={ - category="ll", - direction="l", - }, - [0x1042B]={ - category="ll", - direction="l", - }, - [0x1042C]={ - category="ll", - direction="l", - }, - [0x1042D]={ - category="ll", - direction="l", - }, - [0x1042E]={ - category="ll", - direction="l", - }, - [0x1042F]={ - category="ll", - direction="l", - }, - [0x10430]={ - category="ll", - direction="l", - }, - [0x10431]={ - category="ll", - direction="l", - }, - [0x10432]={ - category="ll", - direction="l", - }, - [0x10433]={ - category="ll", - direction="l", - }, - [0x10434]={ - category="ll", - direction="l", - }, - [0x10435]={ - category="ll", - direction="l", - }, - [0x10436]={ - category="ll", - direction="l", - }, - [0x10437]={ - category="ll", - direction="l", - }, - [0x10438]={ - category="ll", - direction="l", - }, - [0x10439]={ - category="ll", - direction="l", - }, - [0x1043A]={ - category="ll", - direction="l", - }, - [0x1043B]={ - category="ll", - direction="l", - }, - [0x1043C]={ - category="ll", - direction="l", - }, - [0x1043D]={ - category="ll", - direction="l", - }, - [0x1043E]={ - category="ll", - direction="l", - }, - [0x1043F]={ - category="ll", - direction="l", - }, - [0x10440]={ - category="ll", - direction="l", - }, - [0x10441]={ - category="ll", - direction="l", - }, - [0x10442]={ - category="ll", - direction="l", - }, - [0x10443]={ - category="ll", - direction="l", - }, - [0x10444]={ - category="ll", - direction="l", - }, - [0x10445]={ - category="ll", - direction="l", - }, - [0x10446]={ - category="ll", - direction="l", - }, - [0x10447]={ - category="ll", - direction="l", - }, - [0x10448]={ - category="ll", - direction="l", - }, - [0x10449]={ - category="ll", - direction="l", - }, - [0x1044A]={ - category="ll", - direction="l", - }, - [0x1044B]={ - category="ll", - direction="l", - }, - [0x1044C]={ - category="ll", - direction="l", - }, - [0x1044D]={ - category="ll", - direction="l", - }, - [0x1044E]={ - category="ll", - direction="l", - }, - [0x1044F]={ - category="ll", - direction="l", - }, - [0x10450]={ - category="lo", - direction="l", - }, - [0x10451]={ - category="lo", - direction="l", - }, - [0x10452]={ - category="lo", - direction="l", - }, - [0x10453]={ - category="lo", - direction="l", - }, - [0x10454]={ - category="lo", - direction="l", - }, - [0x10455]={ - category="lo", - direction="l", - }, - [0x10456]={ - category="lo", - direction="l", - }, - [0x10457]={ - category="lo", - direction="l", - }, - [0x10458]={ - category="lo", - direction="l", - }, - [0x10459]={ - category="lo", - direction="l", - }, - [0x1045A]={ - category="lo", - direction="l", - }, - [0x1045B]={ - category="lo", - direction="l", - }, - [0x1045C]={ - category="lo", - direction="l", - }, - [0x1045D]={ - category="lo", - direction="l", - }, - [0x1045E]={ - category="lo", - direction="l", - }, - [0x1045F]={ - category="lo", - direction="l", - }, - [0x10460]={ - category="lo", - direction="l", - }, - [0x10461]={ - category="lo", - direction="l", - }, - [0x10462]={ - category="lo", - direction="l", - }, - [0x10463]={ - category="lo", - direction="l", - }, - [0x10464]={ - category="lo", - direction="l", - }, - [0x10465]={ - category="lo", - direction="l", - }, - [0x10466]={ - category="lo", - direction="l", - }, - [0x10467]={ - category="lo", - direction="l", - }, - [0x10468]={ - category="lo", - direction="l", - }, - [0x10469]={ - category="lo", - direction="l", - }, - [0x1046A]={ - category="lo", - direction="l", - }, - [0x1046B]={ - category="lo", - direction="l", - }, - [0x1046C]={ - category="lo", - direction="l", - }, - [0x1046D]={ - category="lo", - direction="l", - }, - [0x1046E]={ - category="lo", - direction="l", - }, - [0x1046F]={ - category="lo", - direction="l", - }, - [0x10470]={ - category="lo", - direction="l", - }, - [0x10471]={ - category="lo", - direction="l", - }, - [0x10472]={ - category="lo", - direction="l", - }, - [0x10473]={ - category="lo", - direction="l", - }, - [0x10474]={ - category="lo", - direction="l", - }, - [0x10475]={ - category="lo", - direction="l", - }, - [0x10476]={ - category="lo", - direction="l", - }, - [0x10477]={ - category="lo", - direction="l", - }, - [0x10478]={ - category="lo", - direction="l", - }, - [0x10479]={ - category="lo", - direction="l", - }, - [0x1047A]={ - category="lo", - direction="l", - }, - [0x1047B]={ - category="lo", - direction="l", - }, - [0x1047C]={ - category="lo", - direction="l", - }, - [0x1047D]={ - category="lo", - direction="l", - }, - [0x1047E]={ - category="lo", - direction="l", - }, - [0x1047F]={ - category="lo", - direction="l", - }, - [0x10480]={ - category="lo", - direction="l", - }, - [0x10481]={ - category="lo", - direction="l", - }, - [0x10482]={ - category="lo", - direction="l", - }, - [0x10483]={ - category="lo", - direction="l", - }, - [0x10484]={ - category="lo", - direction="l", - }, - [0x10485]={ - category="lo", - direction="l", - }, - [0x10486]={ - category="lo", - direction="l", - }, - [0x10487]={ - category="lo", - direction="l", - }, - [0x10488]={ - category="lo", - direction="l", - }, - [0x10489]={ - category="lo", - direction="l", - }, - [0x1048A]={ - category="lo", - direction="l", - }, - [0x1048B]={ - category="lo", - direction="l", - }, - [0x1048C]={ - category="lo", - direction="l", - }, - [0x1048D]={ - category="lo", - direction="l", - }, - [0x1048E]={ - category="lo", - direction="l", - }, - [0x1048F]={ - category="lo", - direction="l", - }, - [0x10490]={ - category="lo", - direction="l", - }, - [0x10491]={ - category="lo", - direction="l", - }, - [0x10492]={ - category="lo", - direction="l", - }, - [0x10493]={ - category="lo", - direction="l", - }, - [0x10494]={ - category="lo", - direction="l", - }, - [0x10495]={ - category="lo", - direction="l", - }, - [0x10496]={ - category="lo", - direction="l", - }, - [0x10497]={ - category="lo", - direction="l", - }, - [0x10498]={ - category="lo", - direction="l", - }, - [0x10499]={ - category="lo", - direction="l", - }, - [0x1049A]={ - category="lo", - direction="l", - }, - [0x1049B]={ - category="lo", - direction="l", - }, - [0x1049C]={ - category="lo", - direction="l", - }, - [0x1049D]={ - category="lo", - direction="l", - }, - [0x104A0]={ - category="nd", - direction="l", - }, - [0x104A1]={ - category="nd", - direction="l", - }, - [0x104A2]={ - category="nd", - direction="l", - }, - [0x104A3]={ - category="nd", - direction="l", - }, - [0x104A4]={ - category="nd", - direction="l", - }, - [0x104A5]={ - category="nd", - direction="l", - }, - [0x104A6]={ - category="nd", - direction="l", - }, - [0x104A7]={ - category="nd", - direction="l", - }, - [0x104A8]={ - category="nd", - direction="l", - }, - [0x104A9]={ - category="nd", - direction="l", - }, - [0x104B0]={ - category="lu", - direction="l", - }, - [0x104B1]={ - category="lu", - direction="l", - }, - [0x104B2]={ - category="lu", - direction="l", - }, - [0x104B3]={ - category="lu", - direction="l", - }, - [0x104B4]={ - category="lu", - direction="l", - }, - [0x104B5]={ - category="lu", - direction="l", - }, - [0x104B6]={ - category="lu", - direction="l", - }, - [0x104B7]={ - category="lu", - direction="l", - }, - [0x104B8]={ - category="lu", - direction="l", - }, - [0x104B9]={ - category="lu", - direction="l", - }, - [0x104BA]={ - category="lu", - direction="l", - }, - [0x104BB]={ - category="lu", - direction="l", - }, - [0x104BC]={ - category="lu", - direction="l", - }, - [0x104BD]={ - category="lu", - direction="l", - }, - [0x104BE]={ - category="lu", - direction="l", - }, - [0x104BF]={ - category="lu", - direction="l", - }, - [0x104C0]={ - category="lu", - direction="l", - }, - [0x104C1]={ - category="lu", - direction="l", - }, - [0x104C2]={ - category="lu", - direction="l", - }, - [0x104C3]={ - category="lu", - direction="l", - }, - [0x104C4]={ - category="lu", - direction="l", - }, - [0x104C5]={ - category="lu", - direction="l", - }, - [0x104C6]={ - category="lu", - direction="l", - }, - [0x104C7]={ - category="lu", - direction="l", - }, - [0x104C8]={ - category="lu", - direction="l", - }, - [0x104C9]={ - category="lu", - direction="l", - }, - [0x104CA]={ - category="lu", - direction="l", - }, - [0x104CB]={ - category="lu", - direction="l", - }, - [0x104CC]={ - category="lu", - direction="l", - }, - [0x104CD]={ - category="lu", - direction="l", - }, - [0x104CE]={ - category="lu", - direction="l", - }, - [0x104CF]={ - category="lu", - direction="l", - }, - [0x104D0]={ - category="lu", - direction="l", - }, - [0x104D1]={ - category="lu", - direction="l", - }, - [0x104D2]={ - category="lu", - direction="l", - }, - [0x104D3]={ - category="lu", - direction="l", - }, - [0x104D8]={ - category="ll", - direction="l", - }, - [0x104D9]={ - category="ll", - direction="l", - }, - [0x104DA]={ - category="ll", - direction="l", - }, - [0x104DB]={ - category="ll", - direction="l", - }, - [0x104DC]={ - category="ll", - direction="l", - }, - [0x104DD]={ - category="ll", - direction="l", - }, - [0x104DE]={ - category="ll", - direction="l", - }, - [0x104DF]={ - category="ll", - direction="l", - }, - [0x104E0]={ - category="ll", - direction="l", - }, - [0x104E1]={ - category="ll", - direction="l", - }, - [0x104E2]={ - category="ll", - direction="l", - }, - [0x104E3]={ - category="ll", - direction="l", - }, - [0x104E4]={ - category="ll", - direction="l", - }, - [0x104E5]={ - category="ll", - direction="l", - }, - [0x104E6]={ - category="ll", - direction="l", - }, - [0x104E7]={ - category="ll", - direction="l", - }, - [0x104E8]={ - category="ll", - direction="l", - }, - [0x104E9]={ - category="ll", - direction="l", - }, - [0x104EA]={ - category="ll", - direction="l", - }, - [0x104EB]={ - category="ll", - direction="l", - }, - [0x104EC]={ - category="ll", - direction="l", - }, - [0x104ED]={ - category="ll", - direction="l", - }, - [0x104EE]={ - category="ll", - direction="l", - }, - [0x104EF]={ - category="ll", - direction="l", - }, - [0x104F0]={ - category="ll", - direction="l", - }, - [0x104F1]={ - category="ll", - direction="l", - }, - [0x104F2]={ - category="ll", - direction="l", - }, - [0x104F3]={ - category="ll", - direction="l", - }, - [0x104F4]={ - category="ll", - direction="l", - }, - [0x104F5]={ - category="ll", - direction="l", - }, - [0x104F6]={ - category="ll", - direction="l", - }, - [0x104F7]={ - category="ll", - direction="l", - }, - [0x104F8]={ - category="ll", - direction="l", - }, - [0x104F9]={ - category="ll", - direction="l", - }, - [0x104FA]={ - category="ll", - direction="l", - }, - [0x104FB]={ - category="ll", - direction="l", - }, - [0x10500]={ - category="lo", - direction="l", - }, - [0x10501]={ - category="lo", - direction="l", - }, - [0x10502]={ - category="lo", - direction="l", - }, - [0x10503]={ - category="lo", - direction="l", - }, - [0x10504]={ - category="lo", - direction="l", - }, - [0x10505]={ - category="lo", - direction="l", - }, - [0x10506]={ - category="lo", - direction="l", - }, - [0x10507]={ - category="lo", - direction="l", - }, - [0x10508]={ - category="lo", - direction="l", - }, - [0x10509]={ - category="lo", - direction="l", - }, - [0x1050A]={ - category="lo", - direction="l", - }, - [0x1050B]={ - category="lo", - direction="l", - }, - [0x1050C]={ - category="lo", - direction="l", - }, - [0x1050D]={ - category="lo", - direction="l", - }, - [0x1050E]={ - category="lo", - direction="l", - }, - [0x1050F]={ - category="lo", - direction="l", - }, - [0x10510]={ - category="lo", - direction="l", - }, - [0x10511]={ - category="lo", - direction="l", - }, - [0x10512]={ - category="lo", - direction="l", - }, - [0x10513]={ - category="lo", - direction="l", - }, - [0x10514]={ - category="lo", - direction="l", - }, - [0x10515]={ - category="lo", - direction="l", - }, - [0x10516]={ - category="lo", - direction="l", - }, - [0x10517]={ - category="lo", - direction="l", - }, - [0x10518]={ - category="lo", - direction="l", - }, - [0x10519]={ - category="lo", - direction="l", - }, - [0x1051A]={ - category="lo", - direction="l", - }, - [0x1051B]={ - category="lo", - direction="l", - }, - [0x1051C]={ - category="lo", - direction="l", - }, - [0x1051D]={ - category="lo", - direction="l", - }, - [0x1051E]={ - category="lo", - direction="l", - }, - [0x1051F]={ - category="lo", - direction="l", - }, - [0x10520]={ - category="lo", - direction="l", - }, - [0x10521]={ - category="lo", - direction="l", - }, - [0x10522]={ - category="lo", - direction="l", - }, - [0x10523]={ - category="lo", - direction="l", - }, - [0x10524]={ - category="lo", - direction="l", - }, - [0x10525]={ - category="lo", - direction="l", - }, - [0x10526]={ - category="lo", - direction="l", - }, - [0x10527]={ - category="lo", - direction="l", - }, - [0x10530]={ - category="lo", - direction="l", - }, - [0x10531]={ - category="lo", - direction="l", - }, - [0x10532]={ - category="lo", - direction="l", - }, - [0x10533]={ - category="lo", - direction="l", - }, - [0x10534]={ - category="lo", - direction="l", - }, - [0x10535]={ - category="lo", - direction="l", - }, - [0x10536]={ - category="lo", - direction="l", - }, - [0x10537]={ - category="lo", - direction="l", - }, - [0x10538]={ - category="lo", - direction="l", - }, - [0x10539]={ - category="lo", - direction="l", - }, - [0x1053A]={ - category="lo", - direction="l", - }, - [0x1053B]={ - category="lo", - direction="l", - }, - [0x1053C]={ - category="lo", - direction="l", - }, - [0x1053D]={ - category="lo", - direction="l", - }, - [0x1053E]={ - category="lo", - direction="l", - }, - [0x1053F]={ - category="lo", - direction="l", - }, - [0x10540]={ - category="lo", - direction="l", - }, - [0x10541]={ - category="lo", - direction="l", - }, - [0x10542]={ - category="lo", - direction="l", - }, - [0x10543]={ - category="lo", - direction="l", - }, - [0x10544]={ - category="lo", - direction="l", - }, - [0x10545]={ - category="lo", - direction="l", - }, - [0x10546]={ - category="lo", - direction="l", - }, - [0x10547]={ - category="lo", - direction="l", - }, - [0x10548]={ - category="lo", - direction="l", - }, - [0x10549]={ - category="lo", - direction="l", - }, - [0x1054A]={ - category="lo", - direction="l", - }, - [0x1054B]={ - category="lo", - direction="l", - }, - [0x1054C]={ - category="lo", - direction="l", - }, - [0x1054D]={ - category="lo", - direction="l", - }, - [0x1054E]={ - category="lo", - direction="l", - }, - [0x1054F]={ - category="lo", - direction="l", - }, - [0x10550]={ - category="lo", - direction="l", - }, - [0x10551]={ - category="lo", - direction="l", - }, - [0x10552]={ - category="lo", - direction="l", - }, - [0x10553]={ - category="lo", - direction="l", - }, - [0x10554]={ - category="lo", - direction="l", - }, - [0x10555]={ - category="lo", - direction="l", - }, - [0x10556]={ - category="lo", - direction="l", - }, - [0x10557]={ - category="lo", - direction="l", - }, - [0x10558]={ - category="lo", - direction="l", - }, - [0x10559]={ - category="lo", - direction="l", - }, - [0x1055A]={ - category="lo", - direction="l", - }, - [0x1055B]={ - category="lo", - direction="l", - }, - [0x1055C]={ - category="lo", - direction="l", - }, - [0x1055D]={ - category="lo", - direction="l", - }, - [0x1055E]={ - category="lo", - direction="l", - }, - [0x1055F]={ - category="lo", - direction="l", - }, - [0x10560]={ - category="lo", - direction="l", - }, - [0x10561]={ - category="lo", - direction="l", - }, - [0x10562]={ - category="lo", - direction="l", - }, - [0x10563]={ - category="lo", - direction="l", - }, - [0x1056F]={ - category="po", - direction="l", - }, - [0x10600]={ - category="lo", - direction="l", - }, - [0x10601]={ - category="lo", - direction="l", - }, - [0x10602]={ - category="lo", - direction="l", - }, - [0x10603]={ - category="lo", - direction="l", - }, - [0x10604]={ - category="lo", - direction="l", - }, - [0x10605]={ - category="lo", - direction="l", - }, - [0x10606]={ - category="lo", - direction="l", - }, - [0x10607]={ - category="lo", - direction="l", - }, - [0x10608]={ - category="lo", - direction="l", - }, - [0x10609]={ - category="lo", - direction="l", - }, - [0x1060A]={ - category="lo", - direction="l", - }, - [0x1060B]={ - category="lo", - direction="l", - }, - [0x1060C]={ - category="lo", - direction="l", - }, - [0x1060D]={ - category="lo", - direction="l", - }, - [0x1060E]={ - category="lo", - direction="l", - }, - [0x1060F]={ - category="lo", - direction="l", - }, - [0x10610]={ - category="lo", - direction="l", - }, - [0x10611]={ - category="lo", - direction="l", - }, - [0x10612]={ - category="lo", - direction="l", - }, - [0x10613]={ - category="lo", - direction="l", - }, - [0x10614]={ - category="lo", - direction="l", - }, - [0x10615]={ - category="lo", - direction="l", - }, - [0x10616]={ - category="lo", - direction="l", - }, - [0x10617]={ - category="lo", - direction="l", - }, - [0x10618]={ - category="lo", - direction="l", - }, - [0x10619]={ - category="lo", - direction="l", - }, - [0x1061A]={ - category="lo", - direction="l", - }, - [0x1061B]={ - category="lo", - direction="l", - }, - [0x1061C]={ - category="lo", - direction="l", - }, - [0x1061D]={ - category="lo", - direction="l", - }, - [0x1061E]={ - category="lo", - direction="l", - }, - [0x1061F]={ - category="lo", - direction="l", - }, - [0x10620]={ - category="lo", - direction="l", - }, - [0x10621]={ - category="lo", - direction="l", - }, - [0x10622]={ - category="lo", - direction="l", - }, - [0x10623]={ - category="lo", - direction="l", - }, - [0x10624]={ - category="lo", - direction="l", - }, - [0x10625]={ - category="lo", - direction="l", - }, - [0x10626]={ - category="lo", - direction="l", - }, - [0x10627]={ - category="lo", - direction="l", - }, - [0x10628]={ - category="lo", - direction="l", - }, - [0x10629]={ - category="lo", - direction="l", - }, - [0x1062A]={ - category="lo", - direction="l", - }, - [0x1062B]={ - category="lo", - direction="l", - }, - [0x1062C]={ - category="lo", - direction="l", - }, - [0x1062D]={ - category="lo", - direction="l", - }, - [0x1062E]={ - category="lo", - direction="l", - }, - [0x1062F]={ - category="lo", - direction="l", - }, - [0x10630]={ - category="lo", - direction="l", - }, - [0x10631]={ - category="lo", - direction="l", - }, - [0x10632]={ - category="lo", - direction="l", - }, - [0x10633]={ - category="lo", - direction="l", - }, - [0x10634]={ - category="lo", - direction="l", - }, - [0x10635]={ - category="lo", - direction="l", - }, - [0x10636]={ - category="lo", - direction="l", - }, - [0x10637]={ - category="lo", - direction="l", - }, - [0x10638]={ - category="lo", - direction="l", - }, - [0x10639]={ - category="lo", - direction="l", - }, - [0x1063A]={ - category="lo", - direction="l", - }, - [0x1063B]={ - category="lo", - direction="l", - }, - [0x1063C]={ - category="lo", - direction="l", - }, - [0x1063D]={ - category="lo", - direction="l", - }, - [0x1063E]={ - category="lo", - direction="l", - }, - [0x1063F]={ - category="lo", - direction="l", - }, - [0x10640]={ - category="lo", - direction="l", - }, - [0x10641]={ - category="lo", - direction="l", - }, - [0x10642]={ - category="lo", - direction="l", - }, - [0x10643]={ - category="lo", - direction="l", - }, - [0x10644]={ - category="lo", - direction="l", - }, - [0x10645]={ - category="lo", - direction="l", - }, - [0x10646]={ - category="lo", - direction="l", - }, - [0x10647]={ - category="lo", - direction="l", - }, - [0x10648]={ - category="lo", - direction="l", - }, - [0x10649]={ - category="lo", - direction="l", - }, - [0x1064A]={ - category="lo", - direction="l", - }, - [0x1064B]={ - category="lo", - direction="l", - }, - [0x1064C]={ - category="lo", - direction="l", - }, - [0x1064D]={ - category="lo", - direction="l", - }, - [0x1064E]={ - category="lo", - direction="l", - }, - [0x1064F]={ - category="lo", - direction="l", - }, - [0x10650]={ - category="lo", - direction="l", - }, - [0x10651]={ - category="lo", - direction="l", - }, - [0x10652]={ - category="lo", - direction="l", - }, - [0x10653]={ - category="lo", - direction="l", - }, - [0x10654]={ - category="lo", - direction="l", - }, - [0x10655]={ - category="lo", - direction="l", - }, - [0x10656]={ - category="lo", - direction="l", - }, - [0x10657]={ - category="lo", - direction="l", - }, - [0x10658]={ - category="lo", - direction="l", - }, - [0x10659]={ - category="lo", - direction="l", - }, - [0x1065A]={ - category="lo", - direction="l", - }, - [0x1065B]={ - category="lo", - direction="l", - }, - [0x1065C]={ - category="lo", - direction="l", - }, - [0x1065D]={ - category="lo", - direction="l", - }, - [0x1065E]={ - category="lo", - direction="l", - }, - [0x1065F]={ - category="lo", - direction="l", - }, - [0x10660]={ - category="lo", - direction="l", - }, - [0x10661]={ - category="lo", - direction="l", - }, - [0x10662]={ - category="lo", - direction="l", - }, - [0x10663]={ - category="lo", - direction="l", - }, - [0x10664]={ - category="lo", - direction="l", - }, - [0x10665]={ - category="lo", - direction="l", - }, - [0x10666]={ - category="lo", - direction="l", - }, - [0x10667]={ - category="lo", - direction="l", - }, - [0x10668]={ - category="lo", - direction="l", - }, - [0x10669]={ - category="lo", - direction="l", - }, - [0x1066A]={ - category="lo", - direction="l", - }, - [0x1066B]={ - category="lo", - direction="l", - }, - [0x1066C]={ - category="lo", - direction="l", - }, - [0x1066D]={ - category="lo", - direction="l", - }, - [0x1066E]={ - category="lo", - direction="l", - }, - [0x1066F]={ - category="lo", - direction="l", - }, - [0x10670]={ - category="lo", - direction="l", - }, - [0x10671]={ - category="lo", - direction="l", - }, - [0x10672]={ - category="lo", - direction="l", - }, - [0x10673]={ - category="lo", - direction="l", - }, - [0x10674]={ - category="lo", - direction="l", - }, - [0x10675]={ - category="lo", - direction="l", - }, - [0x10676]={ - category="lo", - direction="l", - }, - [0x10677]={ - category="lo", - direction="l", - }, - [0x10678]={ - category="lo", - direction="l", - }, - [0x10679]={ - category="lo", - direction="l", - }, - [0x1067A]={ - category="lo", - direction="l", - }, - [0x1067B]={ - category="lo", - direction="l", - }, - [0x1067C]={ - category="lo", - direction="l", - }, - [0x1067D]={ - category="lo", - direction="l", - }, - [0x1067E]={ - category="lo", - direction="l", - }, - [0x1067F]={ - category="lo", - direction="l", - }, - [0x10680]={ - category="lo", - direction="l", - }, - [0x10681]={ - category="lo", - direction="l", - }, - [0x10682]={ - category="lo", - direction="l", - }, - [0x10683]={ - category="lo", - direction="l", - }, - [0x10684]={ - category="lo", - direction="l", - }, - [0x10685]={ - category="lo", - direction="l", - }, - [0x10686]={ - category="lo", - direction="l", - }, - [0x10687]={ - category="lo", - direction="l", - }, - [0x10688]={ - category="lo", - direction="l", - }, - [0x10689]={ - category="lo", - direction="l", - }, - [0x1068A]={ - category="lo", - direction="l", - }, - [0x1068B]={ - category="lo", - direction="l", - }, - [0x1068C]={ - category="lo", - direction="l", - }, - [0x1068D]={ - category="lo", - direction="l", - }, - [0x1068E]={ - category="lo", - direction="l", - }, - [0x1068F]={ - category="lo", - direction="l", - }, - [0x10690]={ - category="lo", - direction="l", - }, - [0x10691]={ - category="lo", - direction="l", - }, - [0x10692]={ - category="lo", - direction="l", - }, - [0x10693]={ - category="lo", - direction="l", - }, - [0x10694]={ - category="lo", - direction="l", - }, - [0x10695]={ - category="lo", - direction="l", - }, - [0x10696]={ - category="lo", - direction="l", - }, - [0x10697]={ - category="lo", - direction="l", - }, - [0x10698]={ - category="lo", - direction="l", - }, - [0x10699]={ - category="lo", - direction="l", - }, - [0x1069A]={ - category="lo", - direction="l", - }, - [0x1069B]={ - category="lo", - direction="l", - }, - [0x1069C]={ - category="lo", - direction="l", - }, - [0x1069D]={ - category="lo", - direction="l", - }, - [0x1069E]={ - category="lo", - direction="l", - }, - [0x1069F]={ - category="lo", - direction="l", - }, - [0x106A0]={ - category="lo", - direction="l", - }, - [0x106A1]={ - category="lo", - direction="l", - }, - [0x106A2]={ - category="lo", - direction="l", - }, - [0x106A3]={ - category="lo", - direction="l", - }, - [0x106A4]={ - category="lo", - direction="l", - }, - [0x106A5]={ - category="lo", - direction="l", - }, - [0x106A6]={ - category="lo", - direction="l", - }, - [0x106A7]={ - category="lo", - direction="l", - }, - [0x106A8]={ - category="lo", - direction="l", - }, - [0x106A9]={ - category="lo", - direction="l", - }, - [0x106AA]={ - category="lo", - direction="l", - }, - [0x106AB]={ - category="lo", - direction="l", - }, - [0x106AC]={ - category="lo", - direction="l", - }, - [0x106AD]={ - category="lo", - direction="l", - }, - [0x106AE]={ - category="lo", - direction="l", - }, - [0x106AF]={ - category="lo", - direction="l", - }, - [0x106B0]={ - category="lo", - direction="l", - }, - [0x106B1]={ - category="lo", - direction="l", - }, - [0x106B2]={ - category="lo", - direction="l", - }, - [0x106B3]={ - category="lo", - direction="l", - }, - [0x106B4]={ - category="lo", - direction="l", - }, - [0x106B5]={ - category="lo", - direction="l", - }, - [0x106B6]={ - category="lo", - direction="l", - }, - [0x106B7]={ - category="lo", - direction="l", - }, - [0x106B8]={ - category="lo", - direction="l", - }, - [0x106B9]={ - category="lo", - direction="l", - }, - [0x106BA]={ - category="lo", - direction="l", - }, - [0x106BB]={ - category="lo", - direction="l", - }, - [0x106BC]={ - category="lo", - direction="l", - }, - [0x106BD]={ - category="lo", - direction="l", - }, - [0x106BE]={ - category="lo", - direction="l", - }, - [0x106BF]={ - category="lo", - direction="l", - }, - [0x106C0]={ - category="lo", - direction="l", - }, - [0x106C1]={ - category="lo", - direction="l", - }, - [0x106C2]={ - category="lo", - direction="l", - }, - [0x106C3]={ - category="lo", - direction="l", - }, - [0x106C4]={ - category="lo", - direction="l", - }, - [0x106C5]={ - category="lo", - direction="l", - }, - [0x106C6]={ - category="lo", - direction="l", - }, - [0x106C7]={ - category="lo", - direction="l", - }, - [0x106C8]={ - category="lo", - direction="l", - }, - [0x106C9]={ - category="lo", - direction="l", - }, - [0x106CA]={ - category="lo", - direction="l", - }, - [0x106CB]={ - category="lo", - direction="l", - }, - [0x106CC]={ - category="lo", - direction="l", - }, - [0x106CD]={ - category="lo", - direction="l", - }, - [0x106CE]={ - category="lo", - direction="l", - }, - [0x106CF]={ - category="lo", - direction="l", - }, - [0x106D0]={ - category="lo", - direction="l", - }, - [0x106D1]={ - category="lo", - direction="l", - }, - [0x106D2]={ - category="lo", - direction="l", - }, - [0x106D3]={ - category="lo", - direction="l", - }, - [0x106D4]={ - category="lo", - direction="l", - }, - [0x106D5]={ - category="lo", - direction="l", - }, - [0x106D6]={ - category="lo", - direction="l", - }, - [0x106D7]={ - category="lo", - direction="l", - }, - [0x106D8]={ - category="lo", - direction="l", - }, - [0x106D9]={ - category="lo", - direction="l", - }, - [0x106DA]={ - category="lo", - direction="l", - }, - [0x106DB]={ - category="lo", - direction="l", - }, - [0x106DC]={ - category="lo", - direction="l", - }, - [0x106DD]={ - category="lo", - direction="l", - }, - [0x106DE]={ - category="lo", - direction="l", - }, - [0x106DF]={ - category="lo", - direction="l", - }, - [0x106E0]={ - category="lo", - direction="l", - }, - [0x106E1]={ - category="lo", - direction="l", - }, - [0x106E2]={ - category="lo", - direction="l", - }, - [0x106E3]={ - category="lo", - direction="l", - }, - [0x106E4]={ - category="lo", - direction="l", - }, - [0x106E5]={ - category="lo", - direction="l", - }, - [0x106E6]={ - category="lo", - direction="l", - }, - [0x106E7]={ - category="lo", - direction="l", - }, - [0x106E8]={ - category="lo", - direction="l", - }, - [0x106E9]={ - category="lo", - direction="l", - }, - [0x106EA]={ - category="lo", - direction="l", - }, - [0x106EB]={ - category="lo", - direction="l", - }, - [0x106EC]={ - category="lo", - direction="l", - }, - [0x106ED]={ - category="lo", - direction="l", - }, - [0x106EE]={ - category="lo", - direction="l", - }, - [0x106EF]={ - category="lo", - direction="l", - }, - [0x106F0]={ - category="lo", - direction="l", - }, - [0x106F1]={ - category="lo", - direction="l", - }, - [0x106F2]={ - category="lo", - direction="l", - }, - [0x106F3]={ - category="lo", - direction="l", - }, - [0x106F4]={ - category="lo", - direction="l", - }, - [0x106F5]={ - category="lo", - direction="l", - }, - [0x106F6]={ - category="lo", - direction="l", - }, - [0x106F7]={ - category="lo", - direction="l", - }, - [0x106F8]={ - category="lo", - direction="l", - }, - [0x106F9]={ - category="lo", - direction="l", - }, - [0x106FA]={ - category="lo", - direction="l", - }, - [0x106FB]={ - category="lo", - direction="l", - }, - [0x106FC]={ - category="lo", - direction="l", - }, - [0x106FD]={ - category="lo", - direction="l", - }, - [0x106FE]={ - category="lo", - direction="l", - }, - [0x106FF]={ - category="lo", - direction="l", - }, - [0x10700]={ - category="lo", - direction="l", - }, - [0x10701]={ - category="lo", - direction="l", - }, - [0x10702]={ - category="lo", - direction="l", - }, - [0x10703]={ - category="lo", - direction="l", - }, - [0x10704]={ - category="lo", - direction="l", - }, - [0x10705]={ - category="lo", - direction="l", - }, - [0x10706]={ - category="lo", - direction="l", - }, - [0x10707]={ - category="lo", - direction="l", - }, - [0x10708]={ - category="lo", - direction="l", - }, - [0x10709]={ - category="lo", - direction="l", - }, - [0x1070A]={ - category="lo", - direction="l", - }, - [0x1070B]={ - category="lo", - direction="l", - }, - [0x1070C]={ - category="lo", - direction="l", - }, - [0x1070D]={ - category="lo", - direction="l", - }, - [0x1070E]={ - category="lo", - direction="l", - }, - [0x1070F]={ - category="lo", - direction="l", - }, - [0x10710]={ - category="lo", - direction="l", - }, - [0x10711]={ - category="lo", - direction="l", - }, - [0x10712]={ - category="lo", - direction="l", - }, - [0x10713]={ - category="lo", - direction="l", - }, - [0x10714]={ - category="lo", - direction="l", - }, - [0x10715]={ - category="lo", - direction="l", - }, - [0x10716]={ - category="lo", - direction="l", - }, - [0x10717]={ - category="lo", - direction="l", - }, - [0x10718]={ - category="lo", - direction="l", - }, - [0x10719]={ - category="lo", - direction="l", - }, - [0x1071A]={ - category="lo", - direction="l", - }, - [0x1071B]={ - category="lo", - direction="l", - }, - [0x1071C]={ - category="lo", - direction="l", - }, - [0x1071D]={ - category="lo", - direction="l", - }, - [0x1071E]={ - category="lo", - direction="l", - }, - [0x1071F]={ - category="lo", - direction="l", - }, - [0x10720]={ - category="lo", - direction="l", - }, - [0x10721]={ - category="lo", - direction="l", - }, - [0x10722]={ - category="lo", - direction="l", - }, - [0x10723]={ - category="lo", - direction="l", - }, - [0x10724]={ - category="lo", - direction="l", - }, - [0x10725]={ - category="lo", - direction="l", - }, - [0x10726]={ - category="lo", - direction="l", - }, - [0x10727]={ - category="lo", - direction="l", - }, - [0x10728]={ - category="lo", - direction="l", - }, - [0x10729]={ - category="lo", - direction="l", - }, - [0x1072A]={ - category="lo", - direction="l", - }, - [0x1072B]={ - category="lo", - direction="l", - }, - [0x1072C]={ - category="lo", - direction="l", - }, - [0x1072D]={ - category="lo", - direction="l", - }, - [0x1072E]={ - category="lo", - direction="l", - }, - [0x1072F]={ - category="lo", - direction="l", - }, - [0x10730]={ - category="lo", - direction="l", - }, - [0x10731]={ - category="lo", - direction="l", - }, - [0x10732]={ - category="lo", - direction="l", - }, - [0x10733]={ - category="lo", - direction="l", - }, - [0x10734]={ - category="lo", - direction="l", - }, - [0x10735]={ - category="lo", - direction="l", - }, - [0x10736]={ - category="lo", - direction="l", - }, - [0x10740]={ - category="lo", - direction="l", - }, - [0x10741]={ - category="lo", - direction="l", - }, - [0x10742]={ - category="lo", - direction="l", - }, - [0x10743]={ - category="lo", - direction="l", - }, - [0x10744]={ - category="lo", - direction="l", - }, - [0x10745]={ - category="lo", - direction="l", - }, - [0x10746]={ - category="lo", - direction="l", - }, - [0x10747]={ - category="lo", - direction="l", - }, - [0x10748]={ - category="lo", - direction="l", - }, - [0x10749]={ - category="lo", - direction="l", - }, - [0x1074A]={ - category="lo", - direction="l", - }, - [0x1074B]={ - category="lo", - direction="l", - }, - [0x1074C]={ - category="lo", - direction="l", - }, - [0x1074D]={ - category="lo", - direction="l", - }, - [0x1074E]={ - category="lo", - direction="l", - }, - [0x1074F]={ - category="lo", - direction="l", - }, - [0x10750]={ - category="lo", - direction="l", - }, - [0x10751]={ - category="lo", - direction="l", - }, - [0x10752]={ - category="lo", - direction="l", - }, - [0x10753]={ - category="lo", - direction="l", - }, - [0x10754]={ - category="lo", - direction="l", - }, - [0x10755]={ - category="lo", - direction="l", - }, - [0x10760]={ - category="lo", - direction="l", - }, - [0x10761]={ - category="lo", - direction="l", - }, - [0x10762]={ - category="lo", - direction="l", - }, - [0x10763]={ - category="lo", - direction="l", - }, - [0x10764]={ - category="lo", - direction="l", - }, - [0x10765]={ - category="lo", - direction="l", - }, - [0x10766]={ - category="lo", - direction="l", - }, - [0x10767]={ - category="lo", - direction="l", - }, - [0x10800]={ - category="lo", - direction="r", - }, - [0x10801]={ - category="lo", - direction="r", - }, - [0x10802]={ - category="lo", - direction="r", - }, - [0x10803]={ - category="lo", - direction="r", - }, - [0x10804]={ - category="lo", - direction="r", - }, - [0x10805]={ - category="lo", - direction="r", - }, - [0x10808]={ - category="lo", - direction="r", - }, - [0x1080A]={ - category="lo", - direction="r", - }, - [0x1080B]={ - category="lo", - direction="r", - }, - [0x1080C]={ - category="lo", - direction="r", - }, - [0x1080D]={ - category="lo", - direction="r", - }, - [0x1080E]={ - category="lo", - direction="r", - }, - [0x1080F]={ - category="lo", - direction="r", - }, - [0x10810]={ - category="lo", - direction="r", - }, - [0x10811]={ - category="lo", - direction="r", - }, - [0x10812]={ - category="lo", - direction="r", - }, - [0x10813]={ - category="lo", - direction="r", - }, - [0x10814]={ - category="lo", - direction="r", - }, - [0x10815]={ - category="lo", - direction="r", - }, - [0x10816]={ - category="lo", - direction="r", - }, - [0x10817]={ - category="lo", - direction="r", - }, - [0x10818]={ - category="lo", - direction="r", - }, - [0x10819]={ - category="lo", - direction="r", - }, - [0x1081A]={ - category="lo", - direction="r", - }, - [0x1081B]={ - category="lo", - direction="r", - }, - [0x1081C]={ - category="lo", - direction="r", - }, - [0x1081D]={ - category="lo", - direction="r", - }, - [0x1081E]={ - category="lo", - direction="r", - }, - [0x1081F]={ - category="lo", - direction="r", - }, - [0x10820]={ - category="lo", - direction="r", - }, - [0x10821]={ - category="lo", - direction="r", - }, - [0x10822]={ - category="lo", - direction="r", - }, - [0x10823]={ - category="lo", - direction="r", - }, - [0x10824]={ - category="lo", - direction="r", - }, - [0x10825]={ - category="lo", - direction="r", - }, - [0x10826]={ - category="lo", - direction="r", - }, - [0x10827]={ - category="lo", - direction="r", - }, - [0x10828]={ - category="lo", - direction="r", - }, - [0x10829]={ - category="lo", - direction="r", - }, - [0x1082A]={ - category="lo", - direction="r", - }, - [0x1082B]={ - category="lo", - direction="r", - }, - [0x1082C]={ - category="lo", - direction="r", - }, - [0x1082D]={ - category="lo", - direction="r", - }, - [0x1082E]={ - category="lo", - direction="r", - }, - [0x1082F]={ - category="lo", - direction="r", - }, - [0x10830]={ - category="lo", - direction="r", - }, - [0x10831]={ - category="lo", - direction="r", - }, - [0x10832]={ - category="lo", - direction="r", - }, - [0x10833]={ - category="lo", - direction="r", - }, - [0x10834]={ - category="lo", - direction="r", - }, - [0x10835]={ - category="lo", - direction="r", - }, - [0x10837]={ - category="lo", - direction="r", - }, - [0x10838]={ - category="lo", - direction="r", - }, - [0x1083C]={ - category="lo", - direction="r", - }, - [0x1083F]={ - category="lo", - direction="r", - }, - [0x10840]={ - category="lo", - direction="r", - }, - [0x10841]={ - category="lo", - direction="r", - }, - [0x10842]={ - category="lo", - direction="r", - }, - [0x10843]={ - category="lo", - direction="r", - }, - [0x10844]={ - category="lo", - direction="r", - }, - [0x10845]={ - category="lo", - direction="r", - }, - [0x10846]={ - category="lo", - direction="r", - }, - [0x10847]={ - category="lo", - direction="r", - }, - [0x10848]={ - category="lo", - direction="r", - }, - [0x10849]={ - category="lo", - direction="r", - }, - [0x1084A]={ - category="lo", - direction="r", - }, - [0x1084B]={ - category="lo", - direction="r", - }, - [0x1084C]={ - category="lo", - direction="r", - }, - [0x1084D]={ - category="lo", - direction="r", - }, - [0x1084E]={ - category="lo", - direction="r", - }, - [0x1084F]={ - category="lo", - direction="r", - }, - [0x10850]={ - category="lo", - direction="r", - }, - [0x10851]={ - category="lo", - direction="r", - }, - [0x10852]={ - category="lo", - direction="r", - }, - [0x10853]={ - category="lo", - direction="r", - }, - [0x10854]={ - category="lo", - direction="r", - }, - [0x10855]={ - category="lo", - direction="r", - }, - [0x10857]={ - category="po", - direction="r", - }, - [0x10858]={ - category="no", - direction="r", - }, - [0x10859]={ - category="no", - direction="r", - }, - [0x1085A]={ - category="no", - direction="r", - }, - [0x1085B]={ - category="no", - direction="r", - }, - [0x1085C]={ - category="no", - direction="r", - }, - [0x1085D]={ - category="no", - direction="r", - }, - [0x1085E]={ - category="no", - direction="r", - }, - [0x1085F]={ - category="no", - direction="r", - }, - [0x10860]={ - category="lo", - direction="r", - }, - [0x10861]={ - category="lo", - direction="r", - }, - [0x10862]={ - category="lo", - direction="r", - }, - [0x10863]={ - category="lo", - direction="r", - }, - [0x10864]={ - category="lo", - direction="r", - }, - [0x10865]={ - category="lo", - direction="r", - }, - [0x10866]={ - category="lo", - direction="r", - }, - [0x10867]={ - category="lo", - direction="r", - }, - [0x10868]={ - category="lo", - direction="r", - }, - [0x10869]={ - category="lo", - direction="r", - }, - [0x1086A]={ - category="lo", - direction="r", - }, - [0x1086B]={ - category="lo", - direction="r", - }, - [0x1086C]={ - category="lo", - direction="r", - }, - [0x1086D]={ - category="lo", - direction="r", - }, - [0x1086E]={ - category="lo", - direction="r", - }, - [0x1086F]={ - category="lo", - direction="r", - }, - [0x10870]={ - category="lo", - direction="r", - }, - [0x10871]={ - category="lo", - direction="r", - }, - [0x10872]={ - category="lo", - direction="r", - }, - [0x10873]={ - category="lo", - direction="r", - }, - [0x10874]={ - category="lo", - direction="r", - }, - [0x10875]={ - category="lo", - direction="r", - }, - [0x10876]={ - category="lo", - direction="r", - }, - [0x10877]={ - category="so", - direction="r", - }, - [0x10878]={ - category="so", - direction="r", - }, - [0x10879]={ - category="no", - direction="r", - }, - [0x1087A]={ - category="no", - direction="r", - }, - [0x1087B]={ - category="no", - direction="r", - }, - [0x1087C]={ - category="no", - direction="r", - }, - [0x1087D]={ - category="no", - direction="r", - }, - [0x1087E]={ - category="no", - direction="r", - }, - [0x1087F]={ - category="no", - direction="r", - }, - [0x10880]={ - category="lo", - direction="r", - }, - [0x10881]={ - category="lo", - direction="r", - }, - [0x10882]={ - category="lo", - direction="r", - }, - [0x10883]={ - category="lo", - direction="r", - }, - [0x10884]={ - category="lo", - direction="r", - }, - [0x10885]={ - category="lo", - direction="r", - }, - [0x10886]={ - category="lo", - direction="r", - }, - [0x10887]={ - category="lo", - direction="r", - }, - [0x10888]={ - category="lo", - direction="r", - }, - [0x10889]={ - category="lo", - direction="r", - }, - [0x1088A]={ - category="lo", - direction="r", - }, - [0x1088B]={ - category="lo", - direction="r", - }, - [0x1088C]={ - category="lo", - direction="r", - }, - [0x1088D]={ - category="lo", - direction="r", - }, - [0x1088E]={ - category="lo", - direction="r", - }, - [0x1088F]={ - category="lo", - direction="r", - }, - [0x10890]={ - category="lo", - direction="r", - }, - [0x10891]={ - category="lo", - direction="r", - }, - [0x10892]={ - category="lo", - direction="r", - }, - [0x10893]={ - category="lo", - direction="r", - }, - [0x10894]={ - category="lo", - direction="r", - }, - [0x10895]={ - category="lo", - direction="r", - }, - [0x10896]={ - category="lo", - direction="r", - }, - [0x10897]={ - category="lo", - direction="r", - }, - [0x10898]={ - category="lo", - direction="r", - }, - [0x10899]={ - category="lo", - direction="r", - }, - [0x1089A]={ - category="lo", - direction="r", - }, - [0x1089B]={ - category="lo", - direction="r", - }, - [0x1089C]={ - category="lo", - direction="r", - }, - [0x1089D]={ - category="lo", - direction="r", - }, - [0x1089E]={ - category="lo", - direction="r", - }, - [0x108A7]={ - category="no", - direction="r", - }, - [0x108A8]={ - category="no", - direction="r", - }, - [0x108A9]={ - category="no", - direction="r", - }, - [0x108AA]={ - category="no", - direction="r", - }, - [0x108AB]={ - category="no", - direction="r", - }, - [0x108AC]={ - category="no", - direction="r", - }, - [0x108AD]={ - category="no", - direction="r", - }, - [0x108AE]={ - category="no", - direction="r", - }, - [0x108AF]={ - category="no", - direction="r", - }, - [0x108E0]={ - category="lo", - direction="r", - }, - [0x108E1]={ - category="lo", - direction="r", - }, - [0x108E2]={ - category="lo", - direction="r", - }, - [0x108E3]={ - category="lo", - direction="r", - }, - [0x108E4]={ - category="lo", - direction="r", - }, - [0x108E5]={ - category="lo", - direction="r", - }, - [0x108E6]={ - category="lo", - direction="r", - }, - [0x108E7]={ - category="lo", - direction="r", - }, - [0x108E8]={ - category="lo", - direction="r", - }, - [0x108E9]={ - category="lo", - direction="r", - }, - [0x108EA]={ - category="lo", - direction="r", - }, - [0x108EB]={ - category="lo", - direction="r", - }, - [0x108EC]={ - category="lo", - direction="r", - }, - [0x108ED]={ - category="lo", - direction="r", - }, - [0x108EE]={ - category="lo", - direction="r", - }, - [0x108EF]={ - category="lo", - direction="r", - }, - [0x108F0]={ - category="lo", - direction="r", - }, - [0x108F1]={ - category="lo", - direction="r", - }, - [0x108F2]={ - category="lo", - direction="r", - }, - [0x108F4]={ - category="lo", - direction="r", - }, - [0x108F5]={ - category="lo", - direction="r", - }, - [0x108FB]={ - category="no", - direction="r", - }, - [0x108FC]={ - category="no", - direction="r", - }, - [0x108FD]={ - category="no", - direction="r", - }, - [0x108FE]={ - category="no", - direction="r", - }, - [0x108FF]={ - category="no", - direction="r", - }, - [0x10900]={ - category="lo", - direction="r", - }, - [0x10901]={ - category="lo", - direction="r", - }, - [0x10902]={ - category="lo", - direction="r", - }, - [0x10903]={ - category="lo", - direction="r", - }, - [0x10904]={ - category="lo", - direction="r", - }, - [0x10905]={ - category="lo", - direction="r", - }, - [0x10906]={ - category="lo", - direction="r", - }, - [0x10907]={ - category="lo", - direction="r", - }, - [0x10908]={ - category="lo", - direction="r", - }, - [0x10909]={ - category="lo", - direction="r", - }, - [0x1090A]={ - category="lo", - direction="r", - }, - [0x1090B]={ - category="lo", - direction="r", - }, - [0x1090C]={ - category="lo", - direction="r", - }, - [0x1090D]={ - category="lo", - direction="r", - }, - [0x1090E]={ - category="lo", - direction="r", - }, - [0x1090F]={ - category="lo", - direction="r", - }, - [0x10910]={ - category="lo", - direction="r", - }, - [0x10911]={ - category="lo", - direction="r", - }, - [0x10912]={ - category="lo", - direction="r", - }, - [0x10913]={ - category="lo", - direction="r", - }, - [0x10914]={ - category="lo", - direction="r", - }, - [0x10915]={ - category="lo", - direction="r", - }, - [0x10916]={ - category="no", - direction="r", - }, - [0x10917]={ - category="no", - direction="r", - }, - [0x10918]={ - category="no", - direction="r", - }, - [0x10919]={ - category="no", - direction="r", - }, - [0x1091A]={ - category="no", - direction="r", - }, - [0x1091B]={ - category="no", - direction="r", - }, - [0x1091F]={ - category="po", - direction="on", - }, - [0x10920]={ - category="lo", - direction="r", - }, - [0x10921]={ - category="lo", - direction="r", - }, - [0x10922]={ - category="lo", - direction="r", - }, - [0x10923]={ - category="lo", - direction="r", - }, - [0x10924]={ - category="lo", - direction="r", - }, - [0x10925]={ - category="lo", - direction="r", - }, - [0x10926]={ - category="lo", - direction="r", - }, - [0x10927]={ - category="lo", - direction="r", - }, - [0x10928]={ - category="lo", - direction="r", - }, - [0x10929]={ - category="lo", - direction="r", - }, - [0x1092A]={ - category="lo", - direction="r", - }, - [0x1092B]={ - category="lo", - direction="r", - }, - [0x1092C]={ - category="lo", - direction="r", - }, - [0x1092D]={ - category="lo", - direction="r", - }, - [0x1092E]={ - category="lo", - direction="r", - }, - [0x1092F]={ - category="lo", - direction="r", - }, - [0x10930]={ - category="lo", - direction="r", - }, - [0x10931]={ - category="lo", - direction="r", - }, - [0x10932]={ - category="lo", - direction="r", - }, - [0x10933]={ - category="lo", - direction="r", - }, - [0x10934]={ - category="lo", - direction="r", - }, - [0x10935]={ - category="lo", - direction="r", - }, - [0x10936]={ - category="lo", - direction="r", - }, - [0x10937]={ - category="lo", - direction="r", - }, - [0x10938]={ - category="lo", - direction="r", - }, - [0x10939]={ - category="lo", - direction="r", - }, - [0x1093F]={ - category="po", - direction="r", - }, - [0x10980]={ - category="lo", - direction="r", - }, - [0x10981]={ - category="lo", - direction="r", - }, - [0x10982]={ - category="lo", - direction="r", - }, - [0x10983]={ - category="lo", - direction="r", - }, - [0x10984]={ - category="lo", - direction="r", - }, - [0x10985]={ - category="lo", - direction="r", - }, - [0x10986]={ - category="lo", - direction="r", - }, - [0x10987]={ - category="lo", - direction="r", - }, - [0x10988]={ - category="lo", - direction="r", - }, - [0x10989]={ - category="lo", - direction="r", - }, - [0x1098A]={ - category="lo", - direction="r", - }, - [0x1098B]={ - category="lo", - direction="r", - }, - [0x1098C]={ - category="lo", - direction="r", - }, - [0x1098D]={ - category="lo", - direction="r", - }, - [0x1098E]={ - category="lo", - direction="r", - }, - [0x1098F]={ - category="lo", - direction="r", - }, - [0x10990]={ - category="lo", - direction="r", - }, - [0x10991]={ - category="lo", - direction="r", - }, - [0x10992]={ - category="lo", - direction="r", - }, - [0x10993]={ - category="lo", - direction="r", - }, - [0x10994]={ - category="lo", - direction="r", - }, - [0x10995]={ - category="lo", - direction="r", - }, - [0x10996]={ - category="lo", - direction="r", - }, - [0x10997]={ - category="lo", - direction="r", - }, - [0x10998]={ - category="lo", - direction="r", - }, - [0x10999]={ - category="lo", - direction="r", - }, - [0x1099A]={ - category="lo", - direction="r", - }, - [0x1099B]={ - category="lo", - direction="r", - }, - [0x1099C]={ - category="lo", - direction="r", - }, - [0x1099D]={ - category="lo", - direction="r", - }, - [0x1099E]={ - category="lo", - direction="r", - }, - [0x1099F]={ - category="lo", - direction="r", - }, - [0x109A0]={ - category="lo", - direction="r", - }, - [0x109A1]={ - category="lo", - direction="r", - }, - [0x109A2]={ - category="lo", - direction="r", - }, - [0x109A3]={ - category="lo", - direction="r", - }, - [0x109A4]={ - category="lo", - direction="r", - }, - [0x109A5]={ - category="lo", - direction="r", - }, - [0x109A6]={ - category="lo", - direction="r", - }, - [0x109A7]={ - category="lo", - direction="r", - }, - [0x109A8]={ - category="lo", - direction="r", - }, - [0x109A9]={ - category="lo", - direction="r", - }, - [0x109AA]={ - category="lo", - direction="r", - }, - [0x109AB]={ - category="lo", - direction="r", - }, - [0x109AC]={ - category="lo", - direction="r", - }, - [0x109AD]={ - category="lo", - direction="r", - }, - [0x109AE]={ - category="lo", - direction="r", - }, - [0x109AF]={ - category="lo", - direction="r", - }, - [0x109B0]={ - category="lo", - direction="r", - }, - [0x109B1]={ - category="lo", - direction="r", - }, - [0x109B2]={ - category="lo", - direction="r", - }, - [0x109B3]={ - category="lo", - direction="r", - }, - [0x109B4]={ - category="lo", - direction="r", - }, - [0x109B5]={ - category="lo", - direction="r", - }, - [0x109B6]={ - category="lo", - direction="r", - }, - [0x109B7]={ - category="lo", - direction="r", - }, - [0x109BC]={ - category="no", - direction="r", - }, - [0x109BD]={ - category="no", - direction="r", - }, - [0x109BE]={ - category="lo", - direction="r", - }, - [0x109BF]={ - category="lo", - direction="r", - }, - [0x109C0]={ - category="no", - direction="r", - }, - [0x109C1]={ - category="no", - direction="r", - }, - [0x109C2]={ - category="no", - direction="r", - }, - [0x109C3]={ - category="no", - direction="r", - }, - [0x109C4]={ - category="no", - direction="r", - }, - [0x109C5]={ - category="no", - direction="r", - }, - [0x109C6]={ - category="no", - direction="r", - }, - [0x109C7]={ - category="no", - direction="r", - }, - [0x109C8]={ - category="no", - direction="r", - }, - [0x109C9]={ - category="no", - direction="r", - }, - [0x109CA]={ - category="no", - direction="r", - }, - [0x109CB]={ - category="no", - direction="r", - }, - [0x109CC]={ - category="no", - direction="r", - }, - [0x109CD]={ - category="no", - direction="r", - }, - [0x109CE]={ - category="no", - direction="r", - }, - [0x109CF]={ - category="no", - direction="r", - }, - [0x109D2]={ - category="no", - direction="r", - }, - [0x109D3]={ - category="no", - direction="r", - }, - [0x109D4]={ - category="no", - direction="r", - }, - [0x109D5]={ - category="no", - direction="r", - }, - [0x109D6]={ - category="no", - direction="r", - }, - [0x109D7]={ - category="no", - direction="r", - }, - [0x109D8]={ - category="no", - direction="r", - }, - [0x109D9]={ - category="no", - direction="r", - }, - [0x109DA]={ - category="no", - direction="r", - }, - [0x109DB]={ - category="no", - direction="r", - }, - [0x109DC]={ - category="no", - direction="r", - }, - [0x109DD]={ - category="no", - direction="r", - }, - [0x109DE]={ - category="no", - direction="r", - }, - [0x109DF]={ - category="no", - direction="r", - }, - [0x109E0]={ - category="no", - direction="r", - }, - [0x109E1]={ - category="no", - direction="r", - }, - [0x109E2]={ - category="no", - direction="r", - }, - [0x109E3]={ - category="no", - direction="r", - }, - [0x109E4]={ - category="no", - direction="r", - }, - [0x109E5]={ - category="no", - direction="r", - }, - [0x109E6]={ - category="no", - direction="r", - }, - [0x109E7]={ - category="no", - direction="r", - }, - [0x109E8]={ - category="no", - direction="r", - }, - [0x109E9]={ - category="no", - direction="r", - }, - [0x109EA]={ - category="no", - direction="r", - }, - [0x109EB]={ - category="no", - direction="r", - }, - [0x109EC]={ - category="no", - direction="r", - }, - [0x109ED]={ - category="no", - direction="r", - }, - [0x109EE]={ - category="no", - direction="r", - }, - [0x109EF]={ - category="no", - direction="r", - }, - [0x109F0]={ - category="no", - direction="r", - }, - [0x109F1]={ - category="no", - direction="r", - }, - [0x109F2]={ - category="no", - direction="r", - }, - [0x109F3]={ - category="no", - direction="r", - }, - [0x109F4]={ - category="no", - direction="r", - }, - [0x109F5]={ - category="no", - direction="r", - }, - [0x109F6]={ - category="no", - direction="r", - }, - [0x109F7]={ - category="no", - direction="r", - }, - [0x109F8]={ - category="no", - direction="r", - }, - [0x109F9]={ - category="no", - direction="r", - }, - [0x109FA]={ - category="no", - direction="r", - }, - [0x109FB]={ - category="no", - direction="r", - }, - [0x109FC]={ - category="no", - direction="r", - }, - [0x109FD]={ - category="no", - direction="r", - }, - [0x109FE]={ - category="no", - direction="r", - }, - [0x109FF]={ - category="no", - direction="r", - }, - [0x10A00]={ - category="lo", - direction="r", - }, - [0x10A01]={ - category="mn", - direction="nsm", - }, - [0x10A02]={ - category="mn", - direction="nsm", - }, - [0x10A03]={ - category="mn", - direction="nsm", - }, - [0x10A05]={ - category="mn", - direction="nsm", - }, - [0x10A06]={ - category="mn", - direction="nsm", - }, - [0x10A0C]={ - category="mn", - direction="nsm", - }, - [0x10A0D]={ - category="mn", - direction="nsm", - }, - [0x10A0E]={ - category="mn", - direction="nsm", - }, - [0x10A0F]={ - category="mn", - direction="nsm", - }, - [0x10A10]={ - category="lo", - direction="r", - }, - [0x10A11]={ - category="lo", - direction="r", - }, - [0x10A12]={ - category="lo", - direction="r", - }, - [0x10A13]={ - category="lo", - direction="r", - }, - [0x10A15]={ - category="lo", - direction="r", - }, - [0x10A16]={ - category="lo", - direction="r", - }, - [0x10A17]={ - category="lo", - direction="r", - }, - [0x10A19]={ - category="lo", - direction="r", - }, - [0x10A1A]={ - category="lo", - direction="r", - }, - [0x10A1B]={ - category="lo", - direction="r", - }, - [0x10A1C]={ - category="lo", - direction="r", - }, - [0x10A1D]={ - category="lo", - direction="r", - }, - [0x10A1E]={ - category="lo", - direction="r", - }, - [0x10A1F]={ - category="lo", - direction="r", - }, - [0x10A20]={ - category="lo", - direction="r", - }, - [0x10A21]={ - category="lo", - direction="r", - }, - [0x10A22]={ - category="lo", - direction="r", - }, - [0x10A23]={ - category="lo", - direction="r", - }, - [0x10A24]={ - category="lo", - direction="r", - }, - [0x10A25]={ - category="lo", - direction="r", - }, - [0x10A26]={ - category="lo", - direction="r", - }, - [0x10A27]={ - category="lo", - direction="r", - }, - [0x10A28]={ - category="lo", - direction="r", - }, - [0x10A29]={ - category="lo", - direction="r", - }, - [0x10A2A]={ - category="lo", - direction="r", - }, - [0x10A2B]={ - category="lo", - direction="r", - }, - [0x10A2C]={ - category="lo", - direction="r", - }, - [0x10A2D]={ - category="lo", - direction="r", - }, - [0x10A2E]={ - category="lo", - direction="r", - }, - [0x10A2F]={ - category="lo", - direction="r", - }, - [0x10A30]={ - category="lo", - direction="r", - }, - [0x10A31]={ - category="lo", - direction="r", - }, - [0x10A32]={ - category="lo", - direction="r", - }, - [0x10A33]={ - category="lo", - direction="r", - }, - [0x10A38]={ - category="mn", - direction="nsm", - }, - [0x10A39]={ - category="mn", - direction="nsm", - }, - [0x10A3A]={ - category="mn", - direction="nsm", - }, - [0x10A3F]={ - category="mn", - direction="nsm", - }, - [0x10A40]={ - category="no", - direction="r", - }, - [0x10A41]={ - category="no", - direction="r", - }, - [0x10A42]={ - category="no", - direction="r", - }, - [0x10A43]={ - category="no", - direction="r", - }, - [0x10A44]={ - category="no", - direction="r", - }, - [0x10A45]={ - category="no", - direction="r", - }, - [0x10A46]={ - category="no", - direction="r", - }, - [0x10A47]={ - category="no", - direction="r", - }, - [0x10A50]={ - category="po", - direction="r", - }, - [0x10A51]={ - category="po", - direction="r", - }, - [0x10A52]={ - category="po", - direction="r", - }, - [0x10A53]={ - category="po", - direction="r", - }, - [0x10A54]={ - category="po", - direction="r", - }, - [0x10A55]={ - category="po", - direction="r", - }, - [0x10A56]={ - category="po", - direction="r", - }, - [0x10A57]={ - category="po", - direction="r", - }, - [0x10A58]={ - category="po", - direction="r", - }, - [0x10A60]={ - category="lo", - direction="r", - }, - [0x10A61]={ - category="lo", - direction="r", - }, - [0x10A62]={ - category="lo", - direction="r", - }, - [0x10A63]={ - category="lo", - direction="r", - }, - [0x10A64]={ - category="lo", - direction="r", - }, - [0x10A65]={ - category="lo", - direction="r", - }, - [0x10A66]={ - category="lo", - direction="r", - }, - [0x10A67]={ - category="lo", - direction="r", - }, - [0x10A68]={ - category="lo", - direction="r", - }, - [0x10A69]={ - category="lo", - direction="r", - }, - [0x10A6A]={ - category="lo", - direction="r", - }, - [0x10A6B]={ - category="lo", - direction="r", - }, - [0x10A6C]={ - category="lo", - direction="r", - }, - [0x10A6D]={ - category="lo", - direction="r", - }, - [0x10A6E]={ - category="lo", - direction="r", - }, - [0x10A6F]={ - category="lo", - direction="r", - }, - [0x10A70]={ - category="lo", - direction="r", - }, - [0x10A71]={ - category="lo", - direction="r", - }, - [0x10A72]={ - category="lo", - direction="r", - }, - [0x10A73]={ - category="lo", - direction="r", - }, - [0x10A74]={ - category="lo", - direction="r", - }, - [0x10A75]={ - category="lo", - direction="r", - }, - [0x10A76]={ - category="lo", - direction="r", - }, - [0x10A77]={ - category="lo", - direction="r", - }, - [0x10A78]={ - category="lo", - direction="r", - }, - [0x10A79]={ - category="lo", - direction="r", - }, - [0x10A7A]={ - category="lo", - direction="r", - }, - [0x10A7B]={ - category="lo", - direction="r", - }, - [0x10A7C]={ - category="lo", - direction="r", - }, - [0x10A7D]={ - category="no", - direction="r", - }, - [0x10A7E]={ - category="no", - direction="r", - }, - [0x10A7F]={ - category="po", - direction="r", - }, - [0x10A80]={ - category="lo", - direction="r", - }, - [0x10A81]={ - category="lo", - direction="r", - }, - [0x10A82]={ - category="lo", - direction="r", - }, - [0x10A83]={ - category="lo", - direction="r", - }, - [0x10A84]={ - category="lo", - direction="r", - }, - [0x10A85]={ - category="lo", - direction="r", - }, - [0x10A86]={ - category="lo", - direction="r", - }, - [0x10A87]={ - category="lo", - direction="r", - }, - [0x10A88]={ - category="lo", - direction="r", - }, - [0x10A89]={ - category="lo", - direction="r", - }, - [0x10A8A]={ - category="lo", - direction="r", - }, - [0x10A8B]={ - category="lo", - direction="r", - }, - [0x10A8C]={ - category="lo", - direction="r", - }, - [0x10A8D]={ - category="lo", - direction="r", - }, - [0x10A8E]={ - category="lo", - direction="r", - }, - [0x10A8F]={ - category="lo", - direction="r", - }, - [0x10A90]={ - category="lo", - direction="r", - }, - [0x10A91]={ - category="lo", - direction="r", - }, - [0x10A92]={ - category="lo", - direction="r", - }, - [0x10A93]={ - category="lo", - direction="r", - }, - [0x10A94]={ - category="lo", - direction="r", - }, - [0x10A95]={ - category="lo", - direction="r", - }, - [0x10A96]={ - category="lo", - direction="r", - }, - [0x10A97]={ - category="lo", - direction="r", - }, - [0x10A98]={ - category="lo", - direction="r", - }, - [0x10A99]={ - category="lo", - direction="r", - }, - [0x10A9A]={ - category="lo", - direction="r", - }, - [0x10A9B]={ - category="lo", - direction="r", - }, - [0x10A9C]={ - category="lo", - direction="r", - }, - [0x10A9D]={ - category="no", - direction="r", - }, - [0x10A9E]={ - category="no", - direction="r", - }, - [0x10A9F]={ - category="no", - direction="r", - }, - [0x10AC0]={ - category="lo", - direction="r", - }, - [0x10AC1]={ - category="lo", - direction="r", - }, - [0x10AC2]={ - category="lo", - direction="r", - }, - [0x10AC3]={ - category="lo", - direction="r", - }, - [0x10AC4]={ - category="lo", - direction="r", - }, - [0x10AC5]={ - category="lo", - direction="r", - }, - [0x10AC6]={ - category="lo", - direction="r", - }, - [0x10AC7]={ - category="lo", - direction="r", - }, - [0x10AC8]={ - category="so", - direction="r", - }, - [0x10AC9]={ - category="lo", - direction="r", - }, - [0x10ACA]={ - category="lo", - direction="r", - }, - [0x10ACB]={ - category="lo", - direction="r", - }, - [0x10ACC]={ - category="lo", - direction="r", - }, - [0x10ACD]={ - category="lo", - direction="r", - }, - [0x10ACE]={ - category="lo", - direction="r", - }, - [0x10ACF]={ - category="lo", - direction="r", - }, - [0x10AD0]={ - category="lo", - direction="r", - }, - [0x10AD1]={ - category="lo", - direction="r", - }, - [0x10AD2]={ - category="lo", - direction="r", - }, - [0x10AD3]={ - category="lo", - direction="r", - }, - [0x10AD4]={ - category="lo", - direction="r", - }, - [0x10AD5]={ - category="lo", - direction="r", - }, - [0x10AD6]={ - category="lo", - direction="r", - }, - [0x10AD7]={ - category="lo", - direction="r", - }, - [0x10AD8]={ - category="lo", - direction="r", - }, - [0x10AD9]={ - category="lo", - direction="r", - }, - [0x10ADA]={ - category="lo", - direction="r", - }, - [0x10ADB]={ - category="lo", - direction="r", - }, - [0x10ADC]={ - category="lo", - direction="r", - }, - [0x10ADD]={ - category="lo", - direction="r", - }, - [0x10ADE]={ - category="lo", - direction="r", - }, - [0x10ADF]={ - category="lo", - direction="r", - }, - [0x10AE0]={ - category="lo", - direction="r", - }, - [0x10AE1]={ - category="lo", - direction="r", - }, - [0x10AE2]={ - category="lo", - direction="r", - }, - [0x10AE3]={ - category="lo", - direction="r", - }, - [0x10AE4]={ - category="lo", - direction="r", - }, - [0x10AE5]={ - category="mn", - direction="nsm", - }, - [0x10AE6]={ - category="mn", - direction="nsm", - }, - [0x10AEB]={ - category="no", - direction="r", - }, - [0x10AEC]={ - category="no", - direction="r", - }, - [0x10AED]={ - category="no", - direction="r", - }, - [0x10AEE]={ - category="no", - direction="r", - }, - [0x10AEF]={ - category="no", - direction="r", - }, - [0x10AF0]={ - category="po", - direction="r", - }, - [0x10AF1]={ - category="po", - direction="r", - }, - [0x10AF2]={ - category="po", - direction="r", - }, - [0x10AF3]={ - category="po", - direction="r", - }, - [0x10AF4]={ - category="po", - direction="r", - }, - [0x10AF5]={ - category="po", - direction="r", - }, - [0x10AF6]={ - category="po", - direction="r", - }, - [0x10B00]={ - category="lo", - direction="r", - }, - [0x10B01]={ - category="lo", - direction="r", - }, - [0x10B02]={ - category="lo", - direction="r", - }, - [0x10B03]={ - category="lo", - direction="r", - }, - [0x10B04]={ - category="lo", - direction="r", - }, - [0x10B05]={ - category="lo", - direction="r", - }, - [0x10B06]={ - category="lo", - direction="r", - }, - [0x10B07]={ - category="lo", - direction="r", - }, - [0x10B08]={ - category="lo", - direction="r", - }, - [0x10B09]={ - category="lo", - direction="r", - }, - [0x10B0A]={ - category="lo", - direction="r", - }, - [0x10B0B]={ - category="lo", - direction="r", - }, - [0x10B0C]={ - category="lo", - direction="r", - }, - [0x10B0D]={ - category="lo", - direction="r", - }, - [0x10B0E]={ - category="lo", - direction="r", - }, - [0x10B0F]={ - category="lo", - direction="r", - }, - [0x10B10]={ - category="lo", - direction="r", - }, - [0x10B11]={ - category="lo", - direction="r", - }, - [0x10B12]={ - category="lo", - direction="r", - }, - [0x10B13]={ - category="lo", - direction="r", - }, - [0x10B14]={ - category="lo", - direction="r", - }, - [0x10B15]={ - category="lo", - direction="r", - }, - [0x10B16]={ - category="lo", - direction="r", - }, - [0x10B17]={ - category="lo", - direction="r", - }, - [0x10B18]={ - category="lo", - direction="r", - }, - [0x10B19]={ - category="lo", - direction="r", - }, - [0x10B1A]={ - category="lo", - direction="r", - }, - [0x10B1B]={ - category="lo", - direction="r", - }, - [0x10B1C]={ - category="lo", - direction="r", - }, - [0x10B1D]={ - category="lo", - direction="r", - }, - [0x10B1E]={ - category="lo", - direction="r", - }, - [0x10B1F]={ - category="lo", - direction="r", - }, - [0x10B20]={ - category="lo", - direction="r", - }, - [0x10B21]={ - category="lo", - direction="r", - }, - [0x10B22]={ - category="lo", - direction="r", - }, - [0x10B23]={ - category="lo", - direction="r", - }, - [0x10B24]={ - category="lo", - direction="r", - }, - [0x10B25]={ - category="lo", - direction="r", - }, - [0x10B26]={ - category="lo", - direction="r", - }, - [0x10B27]={ - category="lo", - direction="r", - }, - [0x10B28]={ - category="lo", - direction="r", - }, - [0x10B29]={ - category="lo", - direction="r", - }, - [0x10B2A]={ - category="lo", - direction="r", - }, - [0x10B2B]={ - category="lo", - direction="r", - }, - [0x10B2C]={ - category="lo", - direction="r", - }, - [0x10B2D]={ - category="lo", - direction="r", - }, - [0x10B2E]={ - category="lo", - direction="r", - }, - [0x10B2F]={ - category="lo", - direction="r", - }, - [0x10B30]={ - category="lo", - direction="r", - }, - [0x10B31]={ - category="lo", - direction="r", - }, - [0x10B32]={ - category="lo", - direction="r", - }, - [0x10B33]={ - category="lo", - direction="r", - }, - [0x10B34]={ - category="lo", - direction="r", - }, - [0x10B35]={ - category="lo", - direction="r", - }, - [0x10B39]={ - category="po", - direction="on", - }, - [0x10B3A]={ - category="po", - direction="on", - }, - [0x10B3B]={ - category="po", - direction="on", - }, - [0x10B3C]={ - category="po", - direction="on", - }, - [0x10B3D]={ - category="po", - direction="on", - }, - [0x10B3E]={ - category="po", - direction="on", - }, - [0x10B3F]={ - category="po", - direction="on", - }, - [0x10B40]={ - category="lo", - direction="r", - }, - [0x10B41]={ - category="lo", - direction="r", - }, - [0x10B42]={ - category="lo", - direction="r", - }, - [0x10B43]={ - category="lo", - direction="r", - }, - [0x10B44]={ - category="lo", - direction="r", - }, - [0x10B45]={ - category="lo", - direction="r", - }, - [0x10B46]={ - category="lo", - direction="r", - }, - [0x10B47]={ - category="lo", - direction="r", - }, - [0x10B48]={ - category="lo", - direction="r", - }, - [0x10B49]={ - category="lo", - direction="r", - }, - [0x10B4A]={ - category="lo", - direction="r", - }, - [0x10B4B]={ - category="lo", - direction="r", - }, - [0x10B4C]={ - category="lo", - direction="r", - }, - [0x10B4D]={ - category="lo", - direction="r", - }, - [0x10B4E]={ - category="lo", - direction="r", - }, - [0x10B4F]={ - category="lo", - direction="r", - }, - [0x10B50]={ - category="lo", - direction="r", - }, - [0x10B51]={ - category="lo", - direction="r", - }, - [0x10B52]={ - category="lo", - direction="r", - }, - [0x10B53]={ - category="lo", - direction="r", - }, - [0x10B54]={ - category="lo", - direction="r", - }, - [0x10B55]={ - category="lo", - direction="r", - }, - [0x10B58]={ - category="no", - direction="r", - }, - [0x10B59]={ - category="no", - direction="r", - }, - [0x10B5A]={ - category="no", - direction="r", - }, - [0x10B5B]={ - category="no", - direction="r", - }, - [0x10B5C]={ - category="no", - direction="r", - }, - [0x10B5D]={ - category="no", - direction="r", - }, - [0x10B5E]={ - category="no", - direction="r", - }, - [0x10B5F]={ - category="no", - direction="r", - }, - [0x10B60]={ - category="lo", - direction="r", - }, - [0x10B61]={ - category="lo", - direction="r", - }, - [0x10B62]={ - category="lo", - direction="r", - }, - [0x10B63]={ - category="lo", - direction="r", - }, - [0x10B64]={ - category="lo", - direction="r", - }, - [0x10B65]={ - category="lo", - direction="r", - }, - [0x10B66]={ - category="lo", - direction="r", - }, - [0x10B67]={ - category="lo", - direction="r", - }, - [0x10B68]={ - category="lo", - direction="r", - }, - [0x10B69]={ - category="lo", - direction="r", - }, - [0x10B6A]={ - category="lo", - direction="r", - }, - [0x10B6B]={ - category="lo", - direction="r", - }, - [0x10B6C]={ - category="lo", - direction="r", - }, - [0x10B6D]={ - category="lo", - direction="r", - }, - [0x10B6E]={ - category="lo", - direction="r", - }, - [0x10B6F]={ - category="lo", - direction="r", - }, - [0x10B70]={ - category="lo", - direction="r", - }, - [0x10B71]={ - category="lo", - direction="r", - }, - [0x10B72]={ - category="lo", - direction="r", - }, - [0x10B78]={ - category="no", - direction="r", - }, - [0x10B79]={ - category="no", - direction="r", - }, - [0x10B7A]={ - category="no", - direction="r", - }, - [0x10B7B]={ - category="no", - direction="r", - }, - [0x10B7C]={ - category="no", - direction="r", - }, - [0x10B7D]={ - category="no", - direction="r", - }, - [0x10B7E]={ - category="no", - direction="r", - }, - [0x10B7F]={ - category="no", - direction="r", - }, - [0x10B80]={ - category="lo", - direction="r", - }, - [0x10B81]={ - category="lo", - direction="r", - }, - [0x10B82]={ - category="lo", - direction="r", - }, - [0x10B83]={ - category="lo", - direction="r", - }, - [0x10B84]={ - category="lo", - direction="r", - }, - [0x10B85]={ - category="lo", - direction="r", - }, - [0x10B86]={ - category="lo", - direction="r", - }, - [0x10B87]={ - category="lo", - direction="r", - }, - [0x10B88]={ - category="lo", - direction="r", - }, - [0x10B89]={ - category="lo", - direction="r", - }, - [0x10B8A]={ - category="lo", - direction="r", - }, - [0x10B8B]={ - category="lo", - direction="r", - }, - [0x10B8C]={ - category="lo", - direction="r", - }, - [0x10B8D]={ - category="lo", - direction="r", - }, - [0x10B8E]={ - category="lo", - direction="r", - }, - [0x10B8F]={ - category="lo", - direction="r", - }, - [0x10B90]={ - category="lo", - direction="r", - }, - [0x10B91]={ - category="lo", - direction="r", - }, - [0x10B99]={ - category="po", - direction="r", - }, - [0x10B9A]={ - category="po", - direction="r", - }, - [0x10B9B]={ - category="po", - direction="r", - }, - [0x10B9C]={ - category="po", - direction="r", - }, - [0x10BA9]={ - category="no", - direction="r", - }, - [0x10BAA]={ - category="no", - direction="r", - }, - [0x10BAB]={ - category="no", - direction="r", - }, - [0x10BAC]={ - category="no", - direction="r", - }, - [0x10BAD]={ - category="no", - direction="r", - }, - [0x10BAE]={ - category="no", - direction="r", - }, - [0x10BAF]={ - category="no", - direction="r", - }, - [0x10C00]={ - category="lo", - direction="r", - }, - [0x10C01]={ - category="lo", - direction="r", - }, - [0x10C02]={ - category="lo", - direction="r", - }, - [0x10C03]={ - category="lo", - direction="r", - }, - [0x10C04]={ - category="lo", - direction="r", - }, - [0x10C05]={ - category="lo", - direction="r", - }, - [0x10C06]={ - category="lo", - direction="r", - }, - [0x10C07]={ - category="lo", - direction="r", - }, - [0x10C08]={ - category="lo", - direction="r", - }, - [0x10C09]={ - category="lo", - direction="r", - }, - [0x10C0A]={ - category="lo", - direction="r", - }, - [0x10C0B]={ - category="lo", - direction="r", - }, - [0x10C0C]={ - category="lo", - direction="r", - }, - [0x10C0D]={ - category="lo", - direction="r", - }, - [0x10C0E]={ - category="lo", - direction="r", - }, - [0x10C0F]={ - category="lo", - direction="r", - }, - [0x10C10]={ - category="lo", - direction="r", - }, - [0x10C11]={ - category="lo", - direction="r", - }, - [0x10C12]={ - category="lo", - direction="r", - }, - [0x10C13]={ - category="lo", - direction="r", - }, - [0x10C14]={ - category="lo", - direction="r", - }, - [0x10C15]={ - category="lo", - direction="r", - }, - [0x10C16]={ - category="lo", - direction="r", - }, - [0x10C17]={ - category="lo", - direction="r", - }, - [0x10C18]={ - category="lo", - direction="r", - }, - [0x10C19]={ - category="lo", - direction="r", - }, - [0x10C1A]={ - category="lo", - direction="r", - }, - [0x10C1B]={ - category="lo", - direction="r", - }, - [0x10C1C]={ - category="lo", - direction="r", - }, - [0x10C1D]={ - category="lo", - direction="r", - }, - [0x10C1E]={ - category="lo", - direction="r", - }, - [0x10C1F]={ - category="lo", - direction="r", - }, - [0x10C20]={ - category="lo", - direction="r", - }, - [0x10C21]={ - category="lo", - direction="r", - }, - [0x10C22]={ - category="lo", - direction="r", - }, - [0x10C23]={ - category="lo", - direction="r", - }, - [0x10C24]={ - category="lo", - direction="r", - }, - [0x10C25]={ - category="lo", - direction="r", - }, - [0x10C26]={ - category="lo", - direction="r", - }, - [0x10C27]={ - category="lo", - direction="r", - }, - [0x10C28]={ - category="lo", - direction="r", - }, - [0x10C29]={ - category="lo", - direction="r", - }, - [0x10C2A]={ - category="lo", - direction="r", - }, - [0x10C2B]={ - category="lo", - direction="r", - }, - [0x10C2C]={ - category="lo", - direction="r", - }, - [0x10C2D]={ - category="lo", - direction="r", - }, - [0x10C2E]={ - category="lo", - direction="r", - }, - [0x10C2F]={ - category="lo", - direction="r", - }, - [0x10C30]={ - category="lo", - direction="r", - }, - [0x10C31]={ - category="lo", - direction="r", - }, - [0x10C32]={ - category="lo", - direction="r", - }, - [0x10C33]={ - category="lo", - direction="r", - }, - [0x10C34]={ - category="lo", - direction="r", - }, - [0x10C35]={ - category="lo", - direction="r", - }, - [0x10C36]={ - category="lo", - direction="r", - }, - [0x10C37]={ - category="lo", - direction="r", - }, - [0x10C38]={ - category="lo", - direction="r", - }, - [0x10C39]={ - category="lo", - direction="r", - }, - [0x10C3A]={ - category="lo", - direction="r", - }, - [0x10C3B]={ - category="lo", - direction="r", - }, - [0x10C3C]={ - category="lo", - direction="r", - }, - [0x10C3D]={ - category="lo", - direction="r", - }, - [0x10C3E]={ - category="lo", - direction="r", - }, - [0x10C3F]={ - category="lo", - direction="r", - }, - [0x10C40]={ - category="lo", - direction="r", - }, - [0x10C41]={ - category="lo", - direction="r", - }, - [0x10C42]={ - category="lo", - direction="r", - }, - [0x10C43]={ - category="lo", - direction="r", - }, - [0x10C44]={ - category="lo", - direction="r", - }, - [0x10C45]={ - category="lo", - direction="r", - }, - [0x10C46]={ - category="lo", - direction="r", - }, - [0x10C47]={ - category="lo", - direction="r", - }, - [0x10C48]={ - category="lo", - direction="r", - }, - [0x10C80]={ - category="lu", - direction="r", - }, - [0x10C81]={ - category="lu", - direction="r", - }, - [0x10C82]={ - category="lu", - direction="r", - }, - [0x10C83]={ - category="lu", - direction="r", - }, - [0x10C84]={ - category="lu", - direction="r", - }, - [0x10C85]={ - category="lu", - direction="r", - }, - [0x10C86]={ - category="lu", - direction="r", - }, - [0x10C87]={ - category="lu", - direction="r", - }, - [0x10C88]={ - category="lu", - direction="r", - }, - [0x10C89]={ - category="lu", - direction="r", - }, - [0x10C8A]={ - category="lu", - direction="r", - }, - [0x10C8B]={ - category="lu", - direction="r", - }, - [0x10C8C]={ - category="lu", - direction="r", - }, - [0x10C8D]={ - category="lu", - direction="r", - }, - [0x10C8E]={ - category="lu", - direction="r", - }, - [0x10C8F]={ - category="lu", - direction="r", - }, - [0x10C90]={ - category="lu", - direction="r", - }, - [0x10C91]={ - category="lu", - direction="r", - }, - [0x10C92]={ - category="lu", - direction="r", - }, - [0x10C93]={ - category="lu", - direction="r", - }, - [0x10C94]={ - category="lu", - direction="r", - }, - [0x10C95]={ - category="lu", - direction="r", - }, - [0x10C96]={ - category="lu", - direction="r", - }, - [0x10C97]={ - category="lu", - direction="r", - }, - [0x10C98]={ - category="lu", - direction="r", - }, - [0x10C99]={ - category="lu", - direction="r", - }, - [0x10C9A]={ - category="lu", - direction="r", - }, - [0x10C9B]={ - category="lu", - direction="r", - }, - [0x10C9C]={ - category="lu", - direction="r", - }, - [0x10C9D]={ - category="lu", - direction="r", - }, - [0x10C9E]={ - category="lu", - direction="r", - }, - [0x10C9F]={ - category="lu", - direction="r", - }, - [0x10CA0]={ - category="lu", - direction="r", - }, - [0x10CA1]={ - category="lu", - direction="r", - }, - [0x10CA2]={ - category="lu", - direction="r", - }, - [0x10CA3]={ - category="lu", - direction="r", - }, - [0x10CA4]={ - category="lu", - direction="r", - }, - [0x10CA5]={ - category="lu", - direction="r", - }, - [0x10CA6]={ - category="lu", - direction="r", - }, - [0x10CA7]={ - category="lu", - direction="r", - }, - [0x10CA8]={ - category="lu", - direction="r", - }, - [0x10CA9]={ - category="lu", - direction="r", - }, - [0x10CAA]={ - category="lu", - direction="r", - }, - [0x10CAB]={ - category="lu", - direction="r", - }, - [0x10CAC]={ - category="lu", - direction="r", - }, - [0x10CAD]={ - category="lu", - direction="r", - }, - [0x10CAE]={ - category="lu", - direction="r", - }, - [0x10CAF]={ - category="lu", - direction="r", - }, - [0x10CB0]={ - category="lu", - direction="r", - }, - [0x10CB1]={ - category="lu", - direction="r", - }, - [0x10CB2]={ - category="lu", - direction="r", - }, - [0x10CC0]={ - category="ll", - direction="r", - }, - [0x10CC1]={ - category="ll", - direction="r", - }, - [0x10CC2]={ - category="ll", - direction="r", - }, - [0x10CC3]={ - category="ll", - direction="r", - }, - [0x10CC4]={ - category="ll", - direction="r", - }, - [0x10CC5]={ - category="ll", - direction="r", - }, - [0x10CC6]={ - category="ll", - direction="r", - }, - [0x10CC7]={ - category="ll", - direction="r", - }, - [0x10CC8]={ - category="ll", - direction="r", - }, - [0x10CC9]={ - category="ll", - direction="r", - }, - [0x10CCA]={ - category="ll", - direction="r", - }, - [0x10CCB]={ - category="ll", - direction="r", - }, - [0x10CCC]={ - category="ll", - direction="r", - }, - [0x10CCD]={ - category="ll", - direction="r", - }, - [0x10CCE]={ - category="ll", - direction="r", - }, - [0x10CCF]={ - category="ll", - direction="r", - }, - [0x10CD0]={ - category="ll", - direction="r", - }, - [0x10CD1]={ - category="ll", - direction="r", - }, - [0x10CD2]={ - category="ll", - direction="r", - }, - [0x10CD3]={ - category="ll", - direction="r", - }, - [0x10CD4]={ - category="ll", - direction="r", - }, - [0x10CD5]={ - category="ll", - direction="r", - }, - [0x10CD6]={ - category="ll", - direction="r", - }, - [0x10CD7]={ - category="ll", - direction="r", - }, - [0x10CD8]={ - category="ll", - direction="r", - }, - [0x10CD9]={ - category="ll", - direction="r", - }, - [0x10CDA]={ - category="ll", - direction="r", - }, - [0x10CDB]={ - category="ll", - direction="r", - }, - [0x10CDC]={ - category="ll", - direction="r", - }, - [0x10CDD]={ - category="ll", - direction="r", - }, - [0x10CDE]={ - category="ll", - direction="r", - }, - [0x10CDF]={ - category="ll", - direction="r", - }, - [0x10CE0]={ - category="ll", - direction="r", - }, - [0x10CE1]={ - category="ll", - direction="r", - }, - [0x10CE2]={ - category="ll", - direction="r", - }, - [0x10CE3]={ - category="ll", - direction="r", - }, - [0x10CE4]={ - category="ll", - direction="r", - }, - [0x10CE5]={ - category="ll", - direction="r", - }, - [0x10CE6]={ - category="ll", - direction="r", - }, - [0x10CE7]={ - category="ll", - direction="r", - }, - [0x10CE8]={ - category="ll", - direction="r", - }, - [0x10CE9]={ - category="ll", - direction="r", - }, - [0x10CEA]={ - category="ll", - direction="r", - }, - [0x10CEB]={ - category="ll", - direction="r", - }, - [0x10CEC]={ - category="ll", - direction="r", - }, - [0x10CED]={ - category="ll", - direction="r", - }, - [0x10CEE]={ - category="ll", - direction="r", - }, - [0x10CEF]={ - category="ll", - direction="r", - }, - [0x10CF0]={ - category="ll", - direction="r", - }, - [0x10CF1]={ - category="ll", - direction="r", - }, - [0x10CF2]={ - category="ll", - direction="r", - }, - [0x10CFA]={ - category="no", - direction="r", - }, - [0x10CFB]={ - category="no", - direction="r", - }, - [0x10CFC]={ - category="no", - direction="r", - }, - [0x10CFD]={ - category="no", - direction="r", - }, - [0x10CFE]={ - category="no", - direction="r", - }, - [0x10CFF]={ - category="no", - direction="r", - }, - [0x10E60]={ - category="no", - direction="an", - }, - [0x10E61]={ - category="no", - direction="an", - }, - [0x10E62]={ - category="no", - direction="an", - }, - [0x10E63]={ - category="no", - direction="an", - }, - [0x10E64]={ - category="no", - direction="an", - }, - [0x10E65]={ - category="no", - direction="an", - }, - [0x10E66]={ - category="no", - direction="an", - }, - [0x10E67]={ - category="no", - direction="an", - }, - [0x10E68]={ - category="no", - direction="an", - }, - [0x10E69]={ - category="no", - direction="an", - }, - [0x10E6A]={ - category="no", - direction="an", - }, - [0x10E6B]={ - category="no", - direction="an", - }, - [0x10E6C]={ - category="no", - direction="an", - }, - [0x10E6D]={ - category="no", - direction="an", - }, - [0x10E6E]={ - category="no", - direction="an", - }, - [0x10E6F]={ - category="no", - direction="an", - }, - [0x10E70]={ - category="no", - direction="an", - }, - [0x10E71]={ - category="no", - direction="an", - }, - [0x10E72]={ - category="no", - direction="an", - }, - [0x10E73]={ - category="no", - direction="an", - }, - [0x10E74]={ - category="no", - direction="an", - }, - [0x10E75]={ - category="no", - direction="an", - }, - [0x10E76]={ - category="no", - direction="an", - }, - [0x10E77]={ - category="no", - direction="an", - }, - [0x10E78]={ - category="no", - direction="an", - }, - [0x10E79]={ - category="no", - direction="an", - }, - [0x10E7A]={ - category="no", - direction="an", - }, - [0x10E7B]={ - category="no", - direction="an", - }, - [0x10E7C]={ - category="no", - direction="an", - }, - [0x10E7D]={ - category="no", - direction="an", - }, - [0x10E7E]={ - category="no", - direction="an", - }, - [0x11000]={ - category="mc", - direction="l", - }, - [0x11001]={ - category="mn", - direction="nsm", - }, - [0x11002]={ - category="mc", - direction="l", - }, - [0x11003]={ - category="lo", - direction="l", - }, - [0x11004]={ - category="lo", - direction="l", - }, - [0x11005]={ - category="lo", - direction="l", - }, - [0x11006]={ - category="lo", - direction="l", - }, - [0x11007]={ - category="lo", - direction="l", - }, - [0x11008]={ - category="lo", - direction="l", - }, - [0x11009]={ - category="lo", - direction="l", - }, - [0x1100A]={ - category="lo", - direction="l", - }, - [0x1100B]={ - category="lo", - direction="l", - }, - [0x1100C]={ - category="lo", - direction="l", - }, - [0x1100D]={ - category="lo", - direction="l", - }, - [0x1100E]={ - category="lo", - direction="l", - }, - [0x1100F]={ - category="lo", - direction="l", - }, - [0x11010]={ - category="lo", - direction="l", - }, - [0x11011]={ - category="lo", - direction="l", - }, - [0x11012]={ - category="lo", - direction="l", - }, - [0x11013]={ - category="lo", - direction="l", - }, - [0x11014]={ - category="lo", - direction="l", - }, - [0x11015]={ - category="lo", - direction="l", - }, - [0x11016]={ - category="lo", - direction="l", - }, - [0x11017]={ - category="lo", - direction="l", - }, - [0x11018]={ - category="lo", - direction="l", - }, - [0x11019]={ - category="lo", - direction="l", - }, - [0x1101A]={ - category="lo", - direction="l", - }, - [0x1101B]={ - category="lo", - direction="l", - }, - [0x1101C]={ - category="lo", - direction="l", - }, - [0x1101D]={ - category="lo", - direction="l", - }, - [0x1101E]={ - category="lo", - direction="l", - }, - [0x1101F]={ - category="lo", - direction="l", - }, - [0x11020]={ - category="lo", - direction="l", - }, - [0x11021]={ - category="lo", - direction="l", - }, - [0x11022]={ - category="lo", - direction="l", - }, - [0x11023]={ - category="lo", - direction="l", - }, - [0x11024]={ - category="lo", - direction="l", - }, - [0x11025]={ - category="lo", - direction="l", - }, - [0x11026]={ - category="lo", - direction="l", - }, - [0x11027]={ - category="lo", - direction="l", - }, - [0x11028]={ - category="lo", - direction="l", - }, - [0x11029]={ - category="lo", - direction="l", - }, - [0x1102A]={ - category="lo", - direction="l", - }, - [0x1102B]={ - category="lo", - direction="l", - }, - [0x1102C]={ - category="lo", - direction="l", - }, - [0x1102D]={ - category="lo", - direction="l", - }, - [0x1102E]={ - category="lo", - direction="l", - }, - [0x1102F]={ - category="lo", - direction="l", - }, - [0x11030]={ - category="lo", - direction="l", - }, - [0x11031]={ - category="lo", - direction="l", - }, - [0x11032]={ - category="lo", - direction="l", - }, - [0x11033]={ - category="lo", - direction="l", - }, - [0x11034]={ - category="lo", - direction="l", - }, - [0x11035]={ - category="lo", - direction="l", - }, - [0x11036]={ - category="lo", - direction="l", - }, - [0x11037]={ - category="lo", - direction="l", - }, - [0x11038]={ - category="mn", - direction="nsm", - }, - [0x11039]={ - category="mn", - direction="nsm", - }, - [0x1103A]={ - category="mn", - direction="nsm", - }, - [0x1103B]={ - category="mn", - direction="nsm", - }, - [0x1103C]={ - category="mn", - direction="nsm", - }, - [0x1103D]={ - category="mn", - direction="nsm", - }, - [0x1103E]={ - category="mn", - direction="nsm", - }, - [0x1103F]={ - category="mn", - direction="nsm", - }, - [0x11040]={ - category="mn", - direction="nsm", - }, - [0x11041]={ - category="mn", - direction="nsm", - }, - [0x11042]={ - category="mn", - direction="nsm", - }, - [0x11043]={ - category="mn", - direction="nsm", - }, - [0x11044]={ - category="mn", - direction="nsm", - }, - [0x11045]={ - category="mn", - direction="nsm", - }, - [0x11046]={ - category="mn", - direction="nsm", - }, - [0x11047]={ - category="po", - direction="l", - }, - [0x11048]={ - category="po", - direction="l", - }, - [0x11049]={ - category="po", - direction="l", - }, - [0x1104A]={ - category="po", - direction="l", - }, - [0x1104B]={ - category="po", - direction="l", - }, - [0x1104C]={ - category="po", - direction="l", - }, - [0x1104D]={ - category="po", - direction="l", - }, - [0x11052]={ - category="no", - direction="on", - }, - [0x11053]={ - category="no", - direction="on", - }, - [0x11054]={ - category="no", - direction="on", - }, - [0x11055]={ - category="no", - direction="on", - }, - [0x11056]={ - category="no", - direction="on", - }, - [0x11057]={ - category="no", - direction="on", - }, - [0x11058]={ - category="no", - direction="on", - }, - [0x11059]={ - category="no", - direction="on", - }, - [0x1105A]={ - category="no", - direction="on", - }, - [0x1105B]={ - category="no", - direction="on", - }, - [0x1105C]={ - category="no", - direction="on", - }, - [0x1105D]={ - category="no", - direction="on", - }, - [0x1105E]={ - category="no", - direction="on", - }, - [0x1105F]={ - category="no", - direction="on", - }, - [0x11060]={ - category="no", - direction="on", - }, - [0x11061]={ - category="no", - direction="on", - }, - [0x11062]={ - category="no", - direction="on", - }, - [0x11063]={ - category="no", - direction="on", - }, - [0x11064]={ - category="no", - direction="on", - }, - [0x11065]={ - category="no", - direction="on", - }, - [0x11066]={ - category="nd", - direction="l", - }, - [0x11067]={ - category="nd", - direction="l", - }, - [0x11068]={ - category="nd", - direction="l", - }, - [0x11069]={ - category="nd", - direction="l", - }, - [0x1106A]={ - category="nd", - direction="l", - }, - [0x1106B]={ - category="nd", - direction="l", - }, - [0x1106C]={ - category="nd", - direction="l", - }, - [0x1106D]={ - category="nd", - direction="l", - }, - [0x1106E]={ - category="nd", - direction="l", - }, - [0x1106F]={ - category="nd", - direction="l", - }, - [0x1107F]={ - category="mn", - direction="nsm", - }, - [0x11080]={ - category="mn", - direction="nsm", - }, - [0x11081]={ - category="mn", - direction="nsm", - }, - [0x11082]={ - category="mc", - direction="l", - }, - [0x11083]={ - category="lo", - direction="l", - }, - [0x11084]={ - category="lo", - direction="l", - }, - [0x11085]={ - category="lo", - direction="l", - }, - [0x11086]={ - category="lo", - direction="l", - }, - [0x11087]={ - category="lo", - direction="l", - }, - [0x11088]={ - category="lo", - direction="l", - }, - [0x11089]={ - category="lo", - direction="l", - }, - [0x1108A]={ - category="lo", - direction="l", - }, - [0x1108B]={ - category="lo", - direction="l", - }, - [0x1108C]={ - category="lo", - direction="l", - }, - [0x1108D]={ - category="lo", - direction="l", - }, - [0x1108E]={ - category="lo", - direction="l", - }, - [0x1108F]={ - category="lo", - direction="l", - }, - [0x11090]={ - category="lo", - direction="l", - }, - [0x11091]={ - category="lo", - direction="l", - }, - [0x11092]={ - category="lo", - direction="l", - }, - [0x11093]={ - category="lo", - direction="l", - }, - [0x11094]={ - category="lo", - direction="l", - }, - [0x11095]={ - category="lo", - direction="l", - }, - [0x11096]={ - category="lo", - direction="l", - }, - [0x11097]={ - category="lo", - direction="l", - }, - [0x11098]={ - category="lo", - direction="l", - }, - [0x11099]={ - category="lo", - direction="l", - }, - [0x1109A]={ - category="lo", - direction="l", - }, - [0x1109B]={ - category="lo", - direction="l", - }, - [0x1109C]={ - category="lo", - direction="l", - }, - [0x1109D]={ - category="lo", - direction="l", - }, - [0x1109E]={ - category="lo", - direction="l", - }, - [0x1109F]={ - category="lo", - direction="l", - }, - [0x110A0]={ - category="lo", - direction="l", - }, - [0x110A1]={ - category="lo", - direction="l", - }, - [0x110A2]={ - category="lo", - direction="l", - }, - [0x110A3]={ - category="lo", - direction="l", - }, - [0x110A4]={ - category="lo", - direction="l", - }, - [0x110A5]={ - category="lo", - direction="l", - }, - [0x110A6]={ - category="lo", - direction="l", - }, - [0x110A7]={ - category="lo", - direction="l", - }, - [0x110A8]={ - category="lo", - direction="l", - }, - [0x110A9]={ - category="lo", - direction="l", - }, - [0x110AA]={ - category="lo", - direction="l", - }, - [0x110AB]={ - category="lo", - direction="l", - }, - [0x110AC]={ - category="lo", - direction="l", - }, - [0x110AD]={ - category="lo", - direction="l", - }, - [0x110AE]={ - category="lo", - direction="l", - }, - [0x110AF]={ - category="lo", - direction="l", - }, - [0x110B0]={ - category="mc", - direction="l", - }, - [0x110B1]={ - category="mc", - direction="l", - }, - [0x110B2]={ - category="mc", - direction="l", - }, - [0x110B3]={ - category="mn", - direction="nsm", - }, - [0x110B4]={ - category="mn", - direction="nsm", - }, - [0x110B5]={ - category="mn", - direction="nsm", - }, - [0x110B6]={ - category="mn", - direction="nsm", - }, - [0x110B7]={ - category="mc", - direction="l", - }, - [0x110B8]={ - category="mc", - direction="l", - }, - [0x110B9]={ - category="mn", - direction="nsm", - }, - [0x110BA]={ - category="mn", - direction="nsm", - }, - [0x110BB]={ - category="po", - direction="l", - }, - [0x110BC]={ - category="po", - direction="l", - }, - [0x110BD]={ - category="cf", - direction="l", - }, - [0x110BE]={ - category="po", - direction="l", - }, - [0x110BF]={ - category="po", - direction="l", - }, - [0x110C0]={ - category="po", - direction="l", - }, - [0x110C1]={ - category="po", - direction="l", - }, - [0x110D0]={ - category="lo", - direction="l", - }, - [0x110D1]={ - category="lo", - direction="l", - }, - [0x110D2]={ - category="lo", - direction="l", - }, - [0x110D3]={ - category="lo", - direction="l", - }, - [0x110D4]={ - category="lo", - direction="l", - }, - [0x110D5]={ - category="lo", - direction="l", - }, - [0x110D6]={ - category="lo", - direction="l", - }, - [0x110D7]={ - category="lo", - direction="l", - }, - [0x110D8]={ - category="lo", - direction="l", - }, - [0x110D9]={ - category="lo", - direction="l", - }, - [0x110DA]={ - category="lo", - direction="l", - }, - [0x110DB]={ - category="lo", - direction="l", - }, - [0x110DC]={ - category="lo", - direction="l", - }, - [0x110DD]={ - category="lo", - direction="l", - }, - [0x110DE]={ - category="lo", - direction="l", - }, - [0x110DF]={ - category="lo", - direction="l", - }, - [0x110E0]={ - category="lo", - direction="l", - }, - [0x110E1]={ - category="lo", - direction="l", - }, - [0x110E2]={ - category="lo", - direction="l", - }, - [0x110E3]={ - category="lo", - direction="l", - }, - [0x110E4]={ - category="lo", - direction="l", - }, - [0x110E5]={ - category="lo", - direction="l", - }, - [0x110E6]={ - category="lo", - direction="l", - }, - [0x110E7]={ - category="lo", - direction="l", - }, - [0x110E8]={ - category="lo", - direction="l", - }, - [0x110F0]={ - category="nd", - direction="l", - }, - [0x110F1]={ - category="nd", - direction="l", - }, - [0x110F2]={ - category="nd", - direction="l", - }, - [0x110F3]={ - category="nd", - direction="l", - }, - [0x110F4]={ - category="nd", - direction="l", - }, - [0x110F5]={ - category="nd", - direction="l", - }, - [0x110F6]={ - category="nd", - direction="l", - }, - [0x110F7]={ - category="nd", - direction="l", - }, - [0x110F8]={ - category="nd", - direction="l", - }, - [0x110F9]={ - category="nd", - direction="l", - }, - [0x11100]={ - category="mn", - direction="nsm", - }, - [0x11101]={ - category="mn", - direction="nsm", - }, - [0x11102]={ - category="mn", - direction="nsm", - }, - [0x11103]={ - category="lo", - direction="l", - }, - [0x11104]={ - category="lo", - direction="l", - }, - [0x11105]={ - category="lo", - direction="l", - }, - [0x11106]={ - category="lo", - direction="l", - }, - [0x11107]={ - category="lo", - direction="l", - }, - [0x11108]={ - category="lo", - direction="l", - }, - [0x11109]={ - category="lo", - direction="l", - }, - [0x1110A]={ - category="lo", - direction="l", - }, - [0x1110B]={ - category="lo", - direction="l", - }, - [0x1110C]={ - category="lo", - direction="l", - }, - [0x1110D]={ - category="lo", - direction="l", - }, - [0x1110E]={ - category="lo", - direction="l", - }, - [0x1110F]={ - category="lo", - direction="l", - }, - [0x11110]={ - category="lo", - direction="l", - }, - [0x11111]={ - category="lo", - direction="l", - }, - [0x11112]={ - category="lo", - direction="l", - }, - [0x11113]={ - category="lo", - direction="l", - }, - [0x11114]={ - category="lo", - direction="l", - }, - [0x11115]={ - category="lo", - direction="l", - }, - [0x11116]={ - category="lo", - direction="l", - }, - [0x11117]={ - category="lo", - direction="l", - }, - [0x11118]={ - category="lo", - direction="l", - }, - [0x11119]={ - category="lo", - direction="l", - }, - [0x1111A]={ - category="lo", - direction="l", - }, - [0x1111B]={ - category="lo", - direction="l", - }, - [0x1111C]={ - category="lo", - direction="l", - }, - [0x1111D]={ - category="lo", - direction="l", - }, - [0x1111E]={ - category="lo", - direction="l", - }, - [0x1111F]={ - category="lo", - direction="l", - }, - [0x11120]={ - category="lo", - direction="l", - }, - [0x11121]={ - category="lo", - direction="l", - }, - [0x11122]={ - category="lo", - direction="l", - }, - [0x11123]={ - category="lo", - direction="l", - }, - [0x11124]={ - category="lo", - direction="l", - }, - [0x11125]={ - category="lo", - direction="l", - }, - [0x11126]={ - category="lo", - direction="l", - }, - [0x11127]={ - category="mn", - direction="nsm", - }, - [0x11128]={ - category="mn", - direction="nsm", - }, - [0x11129]={ - category="mn", - direction="nsm", - }, - [0x1112A]={ - category="mn", - direction="nsm", - }, - [0x1112B]={ - category="mn", - direction="nsm", - }, - [0x1112C]={ - category="mc", - direction="l", - }, - [0x1112D]={ - category="mn", - direction="nsm", - }, - [0x1112E]={ - category="mn", - direction="nsm", - }, - [0x1112F]={ - category="mn", - direction="nsm", - }, - [0x11130]={ - category="mn", - direction="nsm", - }, - [0x11131]={ - category="mn", - direction="nsm", - }, - [0x11132]={ - category="mn", - direction="nsm", - }, - [0x11133]={ - category="mn", - direction="nsm", - }, - [0x11134]={ - category="mn", - direction="nsm", - }, - [0x11136]={ - category="nd", - direction="l", - }, - [0x11137]={ - category="nd", - direction="l", - }, - [0x11138]={ - category="nd", - direction="l", - }, - [0x11139]={ - category="nd", - direction="l", - }, - [0x1113A]={ - category="nd", - direction="l", - }, - [0x1113B]={ - category="nd", - direction="l", - }, - [0x1113C]={ - category="nd", - direction="l", - }, - [0x1113D]={ - category="nd", - direction="l", - }, - [0x1113E]={ - category="nd", - direction="l", - }, - [0x1113F]={ - category="nd", - direction="l", - }, - [0x11140]={ - category="po", - direction="l", - }, - [0x11141]={ - category="po", - direction="l", - }, - [0x11142]={ - category="po", - direction="l", - }, - [0x11143]={ - category="po", - direction="l", - }, - [0x11150]={ - category="lo", - direction="l", - }, - [0x11151]={ - category="lo", - direction="l", - }, - [0x11152]={ - category="lo", - direction="l", - }, - [0x11153]={ - category="lo", - direction="l", - }, - [0x11154]={ - category="lo", - direction="l", - }, - [0x11155]={ - category="lo", - direction="l", - }, - [0x11156]={ - category="lo", - direction="l", - }, - [0x11157]={ - category="lo", - direction="l", - }, - [0x11158]={ - category="lo", - direction="l", - }, - [0x11159]={ - category="lo", - direction="l", - }, - [0x1115A]={ - category="lo", - direction="l", - }, - [0x1115B]={ - category="lo", - direction="l", - }, - [0x1115C]={ - category="lo", - direction="l", - }, - [0x1115D]={ - category="lo", - direction="l", - }, - [0x1115E]={ - category="lo", - direction="l", - }, - [0x1115F]={ - category="lo", - direction="l", - }, - [0x11160]={ - category="lo", - direction="l", - }, - [0x11161]={ - category="lo", - direction="l", - }, - [0x11162]={ - category="lo", - direction="l", - }, - [0x11163]={ - category="lo", - direction="l", - }, - [0x11164]={ - category="lo", - direction="l", - }, - [0x11165]={ - category="lo", - direction="l", - }, - [0x11166]={ - category="lo", - direction="l", - }, - [0x11167]={ - category="lo", - direction="l", - }, - [0x11168]={ - category="lo", - direction="l", - }, - [0x11169]={ - category="lo", - direction="l", - }, - [0x1116A]={ - category="lo", - direction="l", - }, - [0x1116B]={ - category="lo", - direction="l", - }, - [0x1116C]={ - category="lo", - direction="l", - }, - [0x1116D]={ - category="lo", - direction="l", - }, - [0x1116E]={ - category="lo", - direction="l", - }, - [0x1116F]={ - category="lo", - direction="l", - }, - [0x11170]={ - category="lo", - direction="l", - }, - [0x11171]={ - category="lo", - direction="l", - }, - [0x11172]={ - category="lo", - direction="l", - }, - [0x11173]={ - category="mn", - direction="nsm", - }, - [0x11174]={ - category="po", - direction="l", - }, - [0x11175]={ - category="po", - direction="l", - }, - [0x11176]={ - category="lo", - direction="l", - }, - [0x11180]={ - category="mn", - direction="nsm", - }, - [0x11181]={ - category="mn", - direction="nsm", - }, - [0x11182]={ - category="mc", - direction="l", - }, - [0x11183]={ - category="lo", - direction="l", - }, - [0x11184]={ - category="lo", - direction="l", - }, - [0x11185]={ - category="lo", - direction="l", - }, - [0x11186]={ - category="lo", - direction="l", - }, - [0x11187]={ - category="lo", - direction="l", - }, - [0x11188]={ - category="lo", - direction="l", - }, - [0x11189]={ - category="lo", - direction="l", - }, - [0x1118A]={ - category="lo", - direction="l", - }, - [0x1118B]={ - category="lo", - direction="l", - }, - [0x1118C]={ - category="lo", - direction="l", - }, - [0x1118D]={ - category="lo", - direction="l", - }, - [0x1118E]={ - category="lo", - direction="l", - }, - [0x1118F]={ - category="lo", - direction="l", - }, - [0x11190]={ - category="lo", - direction="l", - }, - [0x11191]={ - category="lo", - direction="l", - }, - [0x11192]={ - category="lo", - direction="l", - }, - [0x11193]={ - category="lo", - direction="l", - }, - [0x11194]={ - category="lo", - direction="l", - }, - [0x11195]={ - category="lo", - direction="l", - }, - [0x11196]={ - category="lo", - direction="l", - }, - [0x11197]={ - category="lo", - direction="l", - }, - [0x11198]={ - category="lo", - direction="l", - }, - [0x11199]={ - category="lo", - direction="l", - }, - [0x1119A]={ - category="lo", - direction="l", - }, - [0x1119B]={ - category="lo", - direction="l", - }, - [0x1119C]={ - category="lo", - direction="l", - }, - [0x1119D]={ - category="lo", - direction="l", - }, - [0x1119E]={ - category="lo", - direction="l", - }, - [0x1119F]={ - category="lo", - direction="l", - }, - [0x111A0]={ - category="lo", - direction="l", - }, - [0x111A1]={ - category="lo", - direction="l", - }, - [0x111A2]={ - category="lo", - direction="l", - }, - [0x111A3]={ - category="lo", - direction="l", - }, - [0x111A4]={ - category="lo", - direction="l", - }, - [0x111A5]={ - category="lo", - direction="l", - }, - [0x111A6]={ - category="lo", - direction="l", - }, - [0x111A7]={ - category="lo", - direction="l", - }, - [0x111A8]={ - category="lo", - direction="l", - }, - [0x111A9]={ - category="lo", - direction="l", - }, - [0x111AA]={ - category="lo", - direction="l", - }, - [0x111AB]={ - category="lo", - direction="l", - }, - [0x111AC]={ - category="lo", - direction="l", - }, - [0x111AD]={ - category="lo", - direction="l", - }, - [0x111AE]={ - category="lo", - direction="l", - }, - [0x111AF]={ - category="lo", - direction="l", - }, - [0x111B0]={ - category="lo", - direction="l", - }, - [0x111B1]={ - category="lo", - direction="l", - }, - [0x111B2]={ - category="lo", - direction="l", - }, - [0x111B3]={ - category="mc", - direction="l", - }, - [0x111B4]={ - category="mc", - direction="l", - }, - [0x111B5]={ - category="mc", - direction="l", - }, - [0x111B6]={ - category="mn", - direction="nsm", - }, - [0x111B7]={ - category="mn", - direction="nsm", - }, - [0x111B8]={ - category="mn", - direction="nsm", - }, - [0x111B9]={ - category="mn", - direction="nsm", - }, - [0x111BA]={ - category="mn", - direction="nsm", - }, - [0x111BB]={ - category="mn", - direction="nsm", - }, - [0x111BC]={ - category="mn", - direction="nsm", - }, - [0x111BD]={ - category="mn", - direction="nsm", - }, - [0x111BE]={ - category="mn", - direction="nsm", - }, - [0x111BF]={ - category="mc", - direction="l", - }, - [0x111C0]={ - category="mc", - direction="l", - }, - [0x111C1]={ - category="lo", - direction="l", - }, - [0x111C2]={ - category="lo", - direction="l", - }, - [0x111C3]={ - category="lo", - direction="l", - }, - [0x111C4]={ - category="lo", - direction="l", - }, - [0x111C5]={ - category="po", - direction="l", - }, - [0x111C6]={ - category="po", - direction="l", - }, - [0x111C7]={ - category="po", - direction="l", - }, - [0x111C8]={ - category="po", - direction="l", - }, - [0x111C9]={ - category="po", - direction="l", - }, - [0x111CA]={ - category="mn", - direction="nsm", - }, - [0x111CB]={ - category="mn", - direction="nsm", - }, - [0x111CC]={ - category="mn", - direction="nsm", - }, - [0x111CD]={ - category="po", - direction="l", - }, - [0x111D0]={ - category="nd", - direction="l", - }, - [0x111D1]={ - category="nd", - direction="l", - }, - [0x111D2]={ - category="nd", - direction="l", - }, - [0x111D3]={ - category="nd", - direction="l", - }, - [0x111D4]={ - category="nd", - direction="l", - }, - [0x111D5]={ - category="nd", - direction="l", - }, - [0x111D6]={ - category="nd", - direction="l", - }, - [0x111D7]={ - category="nd", - direction="l", - }, - [0x111D8]={ - category="nd", - direction="l", - }, - [0x111D9]={ - category="nd", - direction="l", - }, - [0x111DA]={ - category="lo", - direction="l", - }, - [0x111DB]={ - category="po", - direction="l", - }, - [0x111DC]={ - category="lo", - direction="l", - }, - [0x111DD]={ - category="po", - direction="l", - }, - [0x111DE]={ - category="po", - direction="l", - }, - [0x111DF]={ - category="po", - direction="l", - }, - [0x111E1]={ - category="no", - direction="l", - }, - [0x111E2]={ - category="no", - direction="l", - }, - [0x111E3]={ - category="no", - direction="l", - }, - [0x111E4]={ - category="no", - direction="l", - }, - [0x111E5]={ - category="no", - direction="l", - }, - [0x111E6]={ - category="no", - direction="l", - }, - [0x111E7]={ - category="no", - direction="l", - }, - [0x111E8]={ - category="no", - direction="l", - }, - [0x111E9]={ - category="no", - direction="l", - }, - [0x111EA]={ - category="no", - direction="l", - }, - [0x111EB]={ - category="no", - direction="l", - }, - [0x111EC]={ - category="no", - direction="l", - }, - [0x111ED]={ - category="no", - direction="l", - }, - [0x111EE]={ - category="no", - direction="l", - }, - [0x111EF]={ - category="no", - direction="l", - }, - [0x111F0]={ - category="no", - direction="l", - }, - [0x111F1]={ - category="no", - direction="l", - }, - [0x111F2]={ - category="no", - direction="l", - }, - [0x111F3]={ - category="no", - direction="l", - }, - [0x111F4]={ - category="no", - direction="l", - }, - [0x11200]={ - category="lo", - direction="l", - }, - [0x11201]={ - category="lo", - direction="l", - }, - [0x11202]={ - category="lo", - direction="l", - }, - [0x11203]={ - category="lo", - direction="l", - }, - [0x11204]={ - category="lo", - direction="l", - }, - [0x11205]={ - category="lo", - direction="l", - }, - [0x11206]={ - category="lo", - direction="l", - }, - [0x11207]={ - category="lo", - direction="l", - }, - [0x11208]={ - category="lo", - direction="l", - }, - [0x11209]={ - category="lo", - direction="l", - }, - [0x1120A]={ - category="lo", - direction="l", - }, - [0x1120B]={ - category="lo", - direction="l", - }, - [0x1120C]={ - category="lo", - direction="l", - }, - [0x1120D]={ - category="lo", - direction="l", - }, - [0x1120E]={ - category="lo", - direction="l", - }, - [0x1120F]={ - category="lo", - direction="l", - }, - [0x11210]={ - category="lo", - direction="l", - }, - [0x11211]={ - category="lo", - direction="l", - }, - [0x11213]={ - category="lo", - direction="l", - }, - [0x11214]={ - category="lo", - direction="l", - }, - [0x11215]={ - category="lo", - direction="l", - }, - [0x11216]={ - category="lo", - direction="l", - }, - [0x11217]={ - category="lo", - direction="l", - }, - [0x11218]={ - category="lo", - direction="l", - }, - [0x11219]={ - category="lo", - direction="l", - }, - [0x1121A]={ - category="lo", - direction="l", - }, - [0x1121B]={ - category="lo", - direction="l", - }, - [0x1121C]={ - category="lo", - direction="l", - }, - [0x1121D]={ - category="lo", - direction="l", - }, - [0x1121E]={ - category="lo", - direction="l", - }, - [0x1121F]={ - category="lo", - direction="l", - }, - [0x11220]={ - category="lo", - direction="l", - }, - [0x11221]={ - category="lo", - direction="l", - }, - [0x11222]={ - category="lo", - direction="l", - }, - [0x11223]={ - category="lo", - direction="l", - }, - [0x11224]={ - category="lo", - direction="l", - }, - [0x11225]={ - category="lo", - direction="l", - }, - [0x11226]={ - category="lo", - direction="l", - }, - [0x11227]={ - category="lo", - direction="l", - }, - [0x11228]={ - category="lo", - direction="l", - }, - [0x11229]={ - category="lo", - direction="l", - }, - [0x1122A]={ - category="lo", - direction="l", - }, - [0x1122B]={ - category="lo", - direction="l", - }, - [0x1122C]={ - category="mc", - direction="l", - }, - [0x1122D]={ - category="mc", - direction="l", - }, - [0x1122E]={ - category="mc", - direction="l", - }, - [0x1122F]={ - category="mn", - direction="nsm", - }, - [0x11230]={ - category="mn", - direction="nsm", - }, - [0x11231]={ - category="mn", - direction="nsm", - }, - [0x11232]={ - category="mc", - direction="l", - }, - [0x11233]={ - category="mc", - direction="l", - }, - [0x11234]={ - category="mn", - direction="nsm", - }, - [0x11235]={ - category="mc", - direction="l", - }, - [0x11236]={ - category="mn", - direction="nsm", - }, - [0x11237]={ - category="mn", - direction="nsm", - }, - [0x11238]={ - category="po", - direction="l", - }, - [0x11239]={ - category="po", - direction="l", - }, - [0x1123A]={ - category="po", - direction="l", - }, - [0x1123B]={ - category="po", - direction="l", - }, - [0x1123C]={ - category="po", - direction="l", - }, - [0x1123D]={ - category="po", - direction="l", - }, - [0x1123E]={ - category="mn", - direction="nsm", - }, - [0x11280]={ - category="lo", - direction="l", - }, - [0x11281]={ - category="lo", - direction="l", - }, - [0x11282]={ - category="lo", - direction="l", - }, - [0x11283]={ - category="lo", - direction="l", - }, - [0x11284]={ - category="lo", - direction="l", - }, - [0x11285]={ - category="lo", - direction="l", - }, - [0x11286]={ - category="lo", - direction="l", - }, - [0x11288]={ - category="lo", - direction="l", - }, - [0x1128A]={ - category="lo", - direction="l", - }, - [0x1128B]={ - category="lo", - direction="l", - }, - [0x1128C]={ - category="lo", - direction="l", - }, - [0x1128D]={ - category="lo", - direction="l", - }, - [0x1128F]={ - category="lo", - direction="l", - }, - [0x11290]={ - category="lo", - direction="l", - }, - [0x11291]={ - category="lo", - direction="l", - }, - [0x11292]={ - category="lo", - direction="l", - }, - [0x11293]={ - category="lo", - direction="l", - }, - [0x11294]={ - category="lo", - direction="l", - }, - [0x11295]={ - category="lo", - direction="l", - }, - [0x11296]={ - category="lo", - direction="l", - }, - [0x11297]={ - category="lo", - direction="l", - }, - [0x11298]={ - category="lo", - direction="l", - }, - [0x11299]={ - category="lo", - direction="l", - }, - [0x1129A]={ - category="lo", - direction="l", - }, - [0x1129B]={ - category="lo", - direction="l", - }, - [0x1129C]={ - category="lo", - direction="l", - }, - [0x1129D]={ - category="lo", - direction="l", - }, - [0x1129F]={ - category="lo", - direction="l", - }, - [0x112A0]={ - category="lo", - direction="l", - }, - [0x112A1]={ - category="lo", - direction="l", - }, - [0x112A2]={ - category="lo", - direction="l", - }, - [0x112A3]={ - category="lo", - direction="l", - }, - [0x112A4]={ - category="lo", - direction="l", - }, - [0x112A5]={ - category="lo", - direction="l", - }, - [0x112A6]={ - category="lo", - direction="l", - }, - [0x112A7]={ - category="lo", - direction="l", - }, - [0x112A8]={ - category="lo", - direction="l", - }, - [0x112A9]={ - category="po", - direction="l", - }, - [0x112B0]={ - category="lo", - direction="l", - }, - [0x112B1]={ - category="lo", - direction="l", - }, - [0x112B2]={ - category="lo", - direction="l", - }, - [0x112B3]={ - category="lo", - direction="l", - }, - [0x112B4]={ - category="lo", - direction="l", - }, - [0x112B5]={ - category="lo", - direction="l", - }, - [0x112B6]={ - category="lo", - direction="l", - }, - [0x112B7]={ - category="lo", - direction="l", - }, - [0x112B8]={ - category="lo", - direction="l", - }, - [0x112B9]={ - category="lo", - direction="l", - }, - [0x112BA]={ - category="lo", - direction="l", - }, - [0x112BB]={ - category="lo", - direction="l", - }, - [0x112BC]={ - category="lo", - direction="l", - }, - [0x112BD]={ - category="lo", - direction="l", - }, - [0x112BE]={ - category="lo", - direction="l", - }, - [0x112BF]={ - category="lo", - direction="l", - }, - [0x112C0]={ - category="lo", - direction="l", - }, - [0x112C1]={ - category="lo", - direction="l", - }, - [0x112C2]={ - category="lo", - direction="l", - }, - [0x112C3]={ - category="lo", - direction="l", - }, - [0x112C4]={ - category="lo", - direction="l", - }, - [0x112C5]={ - category="lo", - direction="l", - }, - [0x112C6]={ - category="lo", - direction="l", - }, - [0x112C7]={ - category="lo", - direction="l", - }, - [0x112C8]={ - category="lo", - direction="l", - }, - [0x112C9]={ - category="lo", - direction="l", - }, - [0x112CA]={ - category="lo", - direction="l", - }, - [0x112CB]={ - category="lo", - direction="l", - }, - [0x112CC]={ - category="lo", - direction="l", - }, - [0x112CD]={ - category="lo", - direction="l", - }, - [0x112CE]={ - category="lo", - direction="l", - }, - [0x112CF]={ - category="lo", - direction="l", - }, - [0x112D0]={ - category="lo", - direction="l", - }, - [0x112D1]={ - category="lo", - direction="l", - }, - [0x112D2]={ - category="lo", - direction="l", - }, - [0x112D3]={ - category="lo", - direction="l", - }, - [0x112D4]={ - category="lo", - direction="l", - }, - [0x112D5]={ - category="lo", - direction="l", - }, - [0x112D6]={ - category="lo", - direction="l", - }, - [0x112D7]={ - category="lo", - direction="l", - }, - [0x112D8]={ - category="lo", - direction="l", - }, - [0x112D9]={ - category="lo", - direction="l", - }, - [0x112DA]={ - category="lo", - direction="l", - }, - [0x112DB]={ - category="lo", - direction="l", - }, - [0x112DC]={ - category="lo", - direction="l", - }, - [0x112DD]={ - category="lo", - direction="l", - }, - [0x112DE]={ - category="lo", - direction="l", - }, - [0x112DF]={ - category="mn", - direction="nsm", - }, - [0x112E0]={ - category="mc", - direction="l", - }, - [0x112E1]={ - category="mc", - direction="l", - }, - [0x112E2]={ - category="mc", - direction="l", - }, - [0x112E3]={ - category="mn", - direction="nsm", - }, - [0x112E4]={ - category="mn", - direction="nsm", - }, - [0x112E5]={ - category="mn", - direction="nsm", - }, - [0x112E6]={ - category="mn", - direction="nsm", - }, - [0x112E7]={ - category="mn", - direction="nsm", - }, - [0x112E8]={ - category="mn", - direction="nsm", - }, - [0x112E9]={ - category="mn", - direction="nsm", - }, - [0x112EA]={ - category="mn", - direction="nsm", - }, - [0x112F0]={ - category="nd", - direction="l", - }, - [0x112F1]={ - category="nd", - direction="l", - }, - [0x112F2]={ - category="nd", - direction="l", - }, - [0x112F3]={ - category="nd", - direction="l", - }, - [0x112F4]={ - category="nd", - direction="l", - }, - [0x112F5]={ - category="nd", - direction="l", - }, - [0x112F6]={ - category="nd", - direction="l", - }, - [0x112F7]={ - category="nd", - direction="l", - }, - [0x112F8]={ - category="nd", - direction="l", - }, - [0x112F9]={ - category="nd", - direction="l", - }, - [0x11300]={ - category="mn", - direction="nsm", - }, - [0x11301]={ - category="mn", - direction="nsm", - }, - [0x11302]={ - category="mc", - direction="l", - }, - [0x11303]={ - category="mc", - direction="l", - }, - [0x11305]={ - category="lo", - direction="l", - }, - [0x11306]={ - category="lo", - direction="l", - }, - [0x11307]={ - category="lo", - direction="l", - }, - [0x11308]={ - category="lo", - direction="l", - }, - [0x11309]={ - category="lo", - direction="l", - }, - [0x1130A]={ - category="lo", - direction="l", - }, - [0x1130B]={ - category="lo", - direction="l", - }, - [0x1130C]={ - category="lo", - direction="l", - }, - [0x1130F]={ - category="lo", - direction="l", - }, - [0x11310]={ - category="lo", - direction="l", - }, - [0x11313]={ - category="lo", - direction="l", - }, - [0x11314]={ - category="lo", - direction="l", - }, - [0x11315]={ - category="lo", - direction="l", - }, - [0x11316]={ - category="lo", - direction="l", - }, - [0x11317]={ - category="lo", - direction="l", - }, - [0x11318]={ - category="lo", - direction="l", - }, - [0x11319]={ - category="lo", - direction="l", - }, - [0x1131A]={ - category="lo", - direction="l", - }, - [0x1131B]={ - category="lo", - direction="l", - }, - [0x1131C]={ - category="lo", - direction="l", - }, - [0x1131D]={ - category="lo", - direction="l", - }, - [0x1131E]={ - category="lo", - direction="l", - }, - [0x1131F]={ - category="lo", - direction="l", - }, - [0x11320]={ - category="lo", - direction="l", - }, - [0x11321]={ - category="lo", - direction="l", - }, - [0x11322]={ - category="lo", - direction="l", - }, - [0x11323]={ - category="lo", - direction="l", - }, - [0x11324]={ - category="lo", - direction="l", - }, - [0x11325]={ - category="lo", - direction="l", - }, - [0x11326]={ - category="lo", - direction="l", - }, - [0x11327]={ - category="lo", - direction="l", - }, - [0x11328]={ - category="lo", - direction="l", - }, - [0x1132A]={ - category="lo", - direction="l", - }, - [0x1132B]={ - category="lo", - direction="l", - }, - [0x1132C]={ - category="lo", - direction="l", - }, - [0x1132D]={ - category="lo", - direction="l", - }, - [0x1132E]={ - category="lo", - direction="l", - }, - [0x1132F]={ - category="lo", - direction="l", - }, - [0x11330]={ - category="lo", - direction="l", - }, - [0x11332]={ - category="lo", - direction="l", - }, - [0x11333]={ - category="lo", - direction="l", - }, - [0x11335]={ - category="lo", - direction="l", - }, - [0x11336]={ - category="lo", - direction="l", - }, - [0x11337]={ - category="lo", - direction="l", - }, - [0x11338]={ - category="lo", - direction="l", - }, - [0x11339]={ - category="lo", - direction="l", - }, - [0x1133C]={ - category="mn", - direction="nsm", - }, - [0x1133D]={ - category="lo", - direction="l", - }, - [0x1133E]={ - category="mc", - direction="l", - }, - [0x1133F]={ - category="mc", - direction="l", - }, - [0x11340]={ - category="mn", - direction="nsm", - }, - [0x11341]={ - category="mc", - direction="l", - }, - [0x11342]={ - category="mc", - direction="l", - }, - [0x11343]={ - category="mc", - direction="l", - }, - [0x11344]={ - category="mc", - direction="l", - }, - [0x11347]={ - category="mc", - direction="l", - }, - [0x11348]={ - category="mc", - direction="l", - }, - [0x1134B]={ - category="mc", - direction="l", - }, - [0x1134C]={ - category="mc", - direction="l", - }, - [0x1134D]={ - category="mc", - direction="l", - }, - [0x11350]={ - category="lo", - direction="l", - }, - [0x11357]={ - category="mc", - direction="l", - }, - [0x1135D]={ - category="lo", - direction="l", - }, - [0x1135E]={ - category="lo", - direction="l", - }, - [0x1135F]={ - category="lo", - direction="l", - }, - [0x11360]={ - category="lo", - direction="l", - }, - [0x11361]={ - category="lo", - direction="l", - }, - [0x11362]={ - category="mc", - direction="l", - }, - [0x11363]={ - category="mc", - direction="l", - }, - [0x11366]={ - category="mn", - direction="nsm", - }, - [0x11367]={ - category="mn", - direction="nsm", - }, - [0x11368]={ - category="mn", - direction="nsm", - }, - [0x11369]={ - category="mn", - direction="nsm", - }, - [0x1136A]={ - category="mn", - direction="nsm", - }, - [0x1136B]={ - category="mn", - direction="nsm", - }, - [0x1136C]={ - category="mn", - direction="nsm", - }, - [0x11370]={ - category="mn", - direction="nsm", - }, - [0x11371]={ - category="mn", - direction="nsm", - }, - [0x11372]={ - category="mn", - direction="nsm", - }, - [0x11373]={ - category="mn", - direction="nsm", - }, - [0x11374]={ - category="mn", - direction="nsm", - }, - [0x11400]={ - category="lo", - direction="l", - }, - [0x11401]={ - category="lo", - direction="l", - }, - [0x11402]={ - category="lo", - direction="l", - }, - [0x11403]={ - category="lo", - direction="l", - }, - [0x11404]={ - category="lo", - direction="l", - }, - [0x11405]={ - category="lo", - direction="l", - }, - [0x11406]={ - category="lo", - direction="l", - }, - [0x11407]={ - category="lo", - direction="l", - }, - [0x11408]={ - category="lo", - direction="l", - }, - [0x11409]={ - category="lo", - direction="l", - }, - [0x1140A]={ - category="lo", - direction="l", - }, - [0x1140B]={ - category="lo", - direction="l", - }, - [0x1140C]={ - category="lo", - direction="l", - }, - [0x1140D]={ - category="lo", - direction="l", - }, - [0x1140E]={ - category="lo", - direction="l", - }, - [0x1140F]={ - category="lo", - direction="l", - }, - [0x11410]={ - category="lo", - direction="l", - }, - [0x11411]={ - category="lo", - direction="l", - }, - [0x11412]={ - category="lo", - direction="l", - }, - [0x11413]={ - category="lo", - direction="l", - }, - [0x11414]={ - category="lo", - direction="l", - }, - [0x11415]={ - category="lo", - direction="l", - }, - [0x11416]={ - category="lo", - direction="l", - }, - [0x11417]={ - category="lo", - direction="l", - }, - [0x11418]={ - category="lo", - direction="l", - }, - [0x11419]={ - category="lo", - direction="l", - }, - [0x1141A]={ - category="lo", - direction="l", - }, - [0x1141B]={ - category="lo", - direction="l", - }, - [0x1141C]={ - category="lo", - direction="l", - }, - [0x1141D]={ - category="lo", - direction="l", - }, - [0x1141E]={ - category="lo", - direction="l", - }, - [0x1141F]={ - category="lo", - direction="l", - }, - [0x11420]={ - category="lo", - direction="l", - }, - [0x11421]={ - category="lo", - direction="l", - }, - [0x11422]={ - category="lo", - direction="l", - }, - [0x11423]={ - category="lo", - direction="l", - }, - [0x11424]={ - category="lo", - direction="l", - }, - [0x11425]={ - category="lo", - direction="l", - }, - [0x11426]={ - category="lo", - direction="l", - }, - [0x11427]={ - category="lo", - direction="l", - }, - [0x11428]={ - category="lo", - direction="l", - }, - [0x11429]={ - category="lo", - direction="l", - }, - [0x1142A]={ - category="lo", - direction="l", - }, - [0x1142B]={ - category="lo", - direction="l", - }, - [0x1142C]={ - category="lo", - direction="l", - }, - [0x1142D]={ - category="lo", - direction="l", - }, - [0x1142E]={ - category="lo", - direction="l", - }, - [0x1142F]={ - category="lo", - direction="l", - }, - [0x11430]={ - category="lo", - direction="l", - }, - [0x11431]={ - category="lo", - direction="l", - }, - [0x11432]={ - category="lo", - direction="l", - }, - [0x11433]={ - category="lo", - direction="l", - }, - [0x11434]={ - category="lo", - direction="l", - }, - [0x11435]={ - category="mc", - direction="l", - }, - [0x11436]={ - category="mc", - direction="l", - }, - [0x11437]={ - category="mc", - direction="l", - }, - [0x11438]={ - category="mn", - direction="nsm", - }, - [0x11439]={ - category="mn", - direction="nsm", - }, - [0x1143A]={ - category="mn", - direction="nsm", - }, - [0x1143B]={ - category="mn", - direction="nsm", - }, - [0x1143C]={ - category="mn", - direction="nsm", - }, - [0x1143D]={ - category="mn", - direction="nsm", - }, - [0x1143E]={ - category="mn", - direction="nsm", - }, - [0x1143F]={ - category="mn", - direction="nsm", - }, - [0x11440]={ - category="mc", - direction="l", - }, - [0x11441]={ - category="mc", - direction="l", - }, - [0x11442]={ - category="mn", - direction="nsm", - }, - [0x11443]={ - category="mn", - direction="nsm", - }, - [0x11444]={ - category="mn", - direction="nsm", - }, - [0x11445]={ - category="mc", - direction="l", - }, - [0x11446]={ - category="mn", - direction="nsm", - }, - [0x11447]={ - category="lo", - direction="l", - }, - [0x11448]={ - category="lo", - direction="l", - }, - [0x11449]={ - category="lo", - direction="l", - }, - [0x1144A]={ - category="lo", - direction="l", - }, - [0x1144B]={ - category="po", - direction="l", - }, - [0x1144C]={ - category="po", - direction="l", - }, - [0x1144D]={ - category="po", - direction="l", - }, - [0x1144E]={ - category="po", - direction="l", - }, - [0x1144F]={ - category="po", - direction="l", - }, - [0x11450]={ - category="nd", - direction="l", - }, - [0x11451]={ - category="nd", - direction="l", - }, - [0x11452]={ - category="nd", - direction="l", - }, - [0x11453]={ - category="nd", - direction="l", - }, - [0x11454]={ - category="nd", - direction="l", - }, - [0x11455]={ - category="nd", - direction="l", - }, - [0x11456]={ - category="nd", - direction="l", - }, - [0x11457]={ - category="nd", - direction="l", - }, - [0x11458]={ - category="nd", - direction="l", - }, - [0x11459]={ - category="nd", - direction="l", - }, - [0x1145B]={ - category="po", - direction="l", - }, - [0x1145D]={ - category="po", - direction="l", - }, - [0x11480]={ - category="lo", - direction="l", - }, - [0x11481]={ - category="lo", - direction="l", - }, - [0x11482]={ - category="lo", - direction="l", - }, - [0x11483]={ - category="lo", - direction="l", - }, - [0x11484]={ - category="lo", - direction="l", - }, - [0x11485]={ - category="lo", - direction="l", - }, - [0x11486]={ - category="lo", - direction="l", - }, - [0x11487]={ - category="lo", - direction="l", - }, - [0x11488]={ - category="lo", - direction="l", - }, - [0x11489]={ - category="lo", - direction="l", - }, - [0x1148A]={ - category="lo", - direction="l", - }, - [0x1148B]={ - category="lo", - direction="l", - }, - [0x1148C]={ - category="lo", - direction="l", - }, - [0x1148D]={ - category="lo", - direction="l", - }, - [0x1148E]={ - category="lo", - direction="l", - }, - [0x1148F]={ - category="lo", - direction="l", - }, - [0x11490]={ - category="lo", - direction="l", - }, - [0x11491]={ - category="lo", - direction="l", - }, - [0x11492]={ - category="lo", - direction="l", - }, - [0x11493]={ - category="lo", - direction="l", - }, - [0x11494]={ - category="lo", - direction="l", - }, - [0x11495]={ - category="lo", - direction="l", - }, - [0x11496]={ - category="lo", - direction="l", - }, - [0x11497]={ - category="lo", - direction="l", - }, - [0x11498]={ - category="lo", - direction="l", - }, - [0x11499]={ - category="lo", - direction="l", - }, - [0x1149A]={ - category="lo", - direction="l", - }, - [0x1149B]={ - category="lo", - direction="l", - }, - [0x1149C]={ - category="lo", - direction="l", - }, - [0x1149D]={ - category="lo", - direction="l", - }, - [0x1149E]={ - category="lo", - direction="l", - }, - [0x1149F]={ - category="lo", - direction="l", - }, - [0x114A0]={ - category="lo", - direction="l", - }, - [0x114A1]={ - category="lo", - direction="l", - }, - [0x114A2]={ - category="lo", - direction="l", - }, - [0x114A3]={ - category="lo", - direction="l", - }, - [0x114A4]={ - category="lo", - direction="l", - }, - [0x114A5]={ - category="lo", - direction="l", - }, - [0x114A6]={ - category="lo", - direction="l", - }, - [0x114A7]={ - category="lo", - direction="l", - }, - [0x114A8]={ - category="lo", - direction="l", - }, - [0x114A9]={ - category="lo", - direction="l", - }, - [0x114AA]={ - category="lo", - direction="l", - }, - [0x114AB]={ - category="lo", - direction="l", - }, - [0x114AC]={ - category="lo", - direction="l", - }, - [0x114AD]={ - category="lo", - direction="l", - }, - [0x114AE]={ - category="lo", - direction="l", - }, - [0x114AF]={ - category="lo", - direction="l", - }, - [0x114B0]={ - category="mc", - direction="l", - }, - [0x114B1]={ - category="mc", - direction="l", - }, - [0x114B2]={ - category="mc", - direction="l", - }, - [0x114B3]={ - category="mn", - direction="nsm", - }, - [0x114B4]={ - category="mn", - direction="nsm", - }, - [0x114B5]={ - category="mn", - direction="nsm", - }, - [0x114B6]={ - category="mn", - direction="nsm", - }, - [0x114B7]={ - category="mn", - direction="nsm", - }, - [0x114B8]={ - category="mn", - direction="nsm", - }, - [0x114B9]={ - category="mc", - direction="l", - }, - [0x114BA]={ - category="mn", - direction="nsm", - }, - [0x114BB]={ - category="mc", - direction="l", - }, - [0x114BC]={ - category="mc", - direction="l", - }, - [0x114BD]={ - category="mc", - direction="l", - }, - [0x114BE]={ - category="mc", - direction="l", - }, - [0x114BF]={ - category="mn", - direction="nsm", - }, - [0x114C0]={ - category="mn", - direction="nsm", - }, - [0x114C1]={ - category="mc", - direction="l", - }, - [0x114C2]={ - category="mn", - direction="nsm", - }, - [0x114C3]={ - category="mn", - direction="nsm", - }, - [0x114C4]={ - category="lo", - direction="l", - }, - [0x114C5]={ - category="lo", - direction="l", - }, - [0x114C6]={ - category="po", - direction="l", - }, - [0x114C7]={ - category="lo", - direction="l", - }, - [0x114D0]={ - category="nd", - direction="l", - }, - [0x114D1]={ - category="nd", - direction="l", - }, - [0x114D2]={ - category="nd", - direction="l", - }, - [0x114D3]={ - category="nd", - direction="l", - }, - [0x114D4]={ - category="nd", - direction="l", - }, - [0x114D5]={ - category="nd", - direction="l", - }, - [0x114D6]={ - category="nd", - direction="l", - }, - [0x114D7]={ - category="nd", - direction="l", - }, - [0x114D8]={ - category="nd", - direction="l", - }, - [0x114D9]={ - category="nd", - direction="l", - }, - [0x11580]={ - category="lo", - direction="l", - }, - [0x11581]={ - category="lo", - direction="l", - }, - [0x11582]={ - category="lo", - direction="l", - }, - [0x11583]={ - category="lo", - direction="l", - }, - [0x11584]={ - category="lo", - direction="l", - }, - [0x11585]={ - category="lo", - direction="l", - }, - [0x11586]={ - category="lo", - direction="l", - }, - [0x11587]={ - category="lo", - direction="l", - }, - [0x11588]={ - category="lo", - direction="l", - }, - [0x11589]={ - category="lo", - direction="l", - }, - [0x1158A]={ - category="lo", - direction="l", - }, - [0x1158B]={ - category="lo", - direction="l", - }, - [0x1158C]={ - category="lo", - direction="l", - }, - [0x1158D]={ - category="lo", - direction="l", - }, - [0x1158E]={ - category="lo", - direction="l", - }, - [0x1158F]={ - category="lo", - direction="l", - }, - [0x11590]={ - category="lo", - direction="l", - }, - [0x11591]={ - category="lo", - direction="l", - }, - [0x11592]={ - category="lo", - direction="l", - }, - [0x11593]={ - category="lo", - direction="l", - }, - [0x11594]={ - category="lo", - direction="l", - }, - [0x11595]={ - category="lo", - direction="l", - }, - [0x11596]={ - category="lo", - direction="l", - }, - [0x11597]={ - category="lo", - direction="l", - }, - [0x11598]={ - category="lo", - direction="l", - }, - [0x11599]={ - category="lo", - direction="l", - }, - [0x1159A]={ - category="lo", - direction="l", - }, - [0x1159B]={ - category="lo", - direction="l", - }, - [0x1159C]={ - category="lo", - direction="l", - }, - [0x1159D]={ - category="lo", - direction="l", - }, - [0x1159E]={ - category="lo", - direction="l", - }, - [0x1159F]={ - category="lo", - direction="l", - }, - [0x115A0]={ - category="lo", - direction="l", - }, - [0x115A1]={ - category="lo", - direction="l", - }, - [0x115A2]={ - category="lo", - direction="l", - }, - [0x115A3]={ - category="lo", - direction="l", - }, - [0x115A4]={ - category="lo", - direction="l", - }, - [0x115A5]={ - category="lo", - direction="l", - }, - [0x115A6]={ - category="lo", - direction="l", - }, - [0x115A7]={ - category="lo", - direction="l", - }, - [0x115A8]={ - category="lo", - direction="l", - }, - [0x115A9]={ - category="lo", - direction="l", - }, - [0x115AA]={ - category="lo", - direction="l", - }, - [0x115AB]={ - category="lo", - direction="l", - }, - [0x115AC]={ - category="lo", - direction="l", - }, - [0x115AD]={ - category="lo", - direction="l", - }, - [0x115AE]={ - category="lo", - direction="l", - }, - [0x115AF]={ - category="mc", - direction="l", - }, - [0x115B0]={ - category="mc", - direction="l", - }, - [0x115B1]={ - category="mc", - direction="l", - }, - [0x115B2]={ - category="mn", - direction="nsm", - }, - [0x115B3]={ - category="mn", - direction="nsm", - }, - [0x115B4]={ - category="mn", - direction="nsm", - }, - [0x115B5]={ - category="mn", - direction="nsm", - }, - [0x115B8]={ - category="mc", - direction="l", - }, - [0x115B9]={ - category="mc", - direction="l", - }, - [0x115BA]={ - category="mc", - direction="l", - }, - [0x115BB]={ - category="mc", - direction="l", - }, - [0x115BC]={ - category="mn", - direction="nsm", - }, - [0x115BD]={ - category="mn", - direction="nsm", - }, - [0x115BE]={ - category="mc", - direction="l", - }, - [0x115BF]={ - category="mn", - direction="nsm", - }, - [0x115C0]={ - category="mn", - direction="nsm", - }, - [0x115C1]={ - category="po", - direction="l", - }, - [0x115C2]={ - category="po", - direction="l", - }, - [0x115C3]={ - category="po", - direction="l", - }, - [0x115C4]={ - category="po", - direction="l", - }, - [0x115C5]={ - category="po", - direction="l", - }, - [0x115C6]={ - category="po", - direction="l", - }, - [0x115C7]={ - category="po", - direction="l", - }, - [0x115C8]={ - category="po", - direction="l", - }, - [0x115C9]={ - category="po", - direction="l", - }, - [0x115CA]={ - category="po", - direction="l", - }, - [0x115CB]={ - category="po", - direction="l", - }, - [0x115CC]={ - category="po", - direction="l", - }, - [0x115CD]={ - category="po", - direction="l", - }, - [0x115CE]={ - category="po", - direction="l", - }, - [0x115CF]={ - category="po", - direction="l", - }, - [0x115D0]={ - category="po", - direction="l", - }, - [0x115D1]={ - category="po", - direction="l", - }, - [0x115D2]={ - category="po", - direction="l", - }, - [0x115D3]={ - category="po", - direction="l", - }, - [0x115D4]={ - category="po", - direction="l", - }, - [0x115D5]={ - category="po", - direction="l", - }, - [0x115D6]={ - category="po", - direction="l", - }, - [0x115D7]={ - category="po", - direction="l", - }, - [0x115D8]={ - category="lo", - direction="l", - }, - [0x115D9]={ - category="lo", - direction="l", - }, - [0x115DA]={ - category="lo", - direction="l", - }, - [0x115DB]={ - category="lo", - direction="l", - }, - [0x115DC]={ - category="mn", - direction="nsm", - }, - [0x115DD]={ - category="mn", - direction="nsm", - }, - [0x11600]={ - category="lo", - direction="l", - }, - [0x11601]={ - category="lo", - direction="l", - }, - [0x11602]={ - category="lo", - direction="l", - }, - [0x11603]={ - category="lo", - direction="l", - }, - [0x11604]={ - category="lo", - direction="l", - }, - [0x11605]={ - category="lo", - direction="l", - }, - [0x11606]={ - category="lo", - direction="l", - }, - [0x11607]={ - category="lo", - direction="l", - }, - [0x11608]={ - category="lo", - direction="l", - }, - [0x11609]={ - category="lo", - direction="l", - }, - [0x1160A]={ - category="lo", - direction="l", - }, - [0x1160B]={ - category="lo", - direction="l", - }, - [0x1160C]={ - category="lo", - direction="l", - }, - [0x1160D]={ - category="lo", - direction="l", - }, - [0x1160E]={ - category="lo", - direction="l", - }, - [0x1160F]={ - category="lo", - direction="l", - }, - [0x11610]={ - category="lo", - direction="l", - }, - [0x11611]={ - category="lo", - direction="l", - }, - [0x11612]={ - category="lo", - direction="l", - }, - [0x11613]={ - category="lo", - direction="l", - }, - [0x11614]={ - category="lo", - direction="l", - }, - [0x11615]={ - category="lo", - direction="l", - }, - [0x11616]={ - category="lo", - direction="l", - }, - [0x11617]={ - category="lo", - direction="l", - }, - [0x11618]={ - category="lo", - direction="l", - }, - [0x11619]={ - category="lo", - direction="l", - }, - [0x1161A]={ - category="lo", - direction="l", - }, - [0x1161B]={ - category="lo", - direction="l", - }, - [0x1161C]={ - category="lo", - direction="l", - }, - [0x1161D]={ - category="lo", - direction="l", - }, - [0x1161E]={ - category="lo", - direction="l", - }, - [0x1161F]={ - category="lo", - direction="l", - }, - [0x11620]={ - category="lo", - direction="l", - }, - [0x11621]={ - category="lo", - direction="l", - }, - [0x11622]={ - category="lo", - direction="l", - }, - [0x11623]={ - category="lo", - direction="l", - }, - [0x11624]={ - category="lo", - direction="l", - }, - [0x11625]={ - category="lo", - direction="l", - }, - [0x11626]={ - category="lo", - direction="l", - }, - [0x11627]={ - category="lo", - direction="l", - }, - [0x11628]={ - category="lo", - direction="l", - }, - [0x11629]={ - category="lo", - direction="l", - }, - [0x1162A]={ - category="lo", - direction="l", - }, - [0x1162B]={ - category="lo", - direction="l", - }, - [0x1162C]={ - category="lo", - direction="l", - }, - [0x1162D]={ - category="lo", - direction="l", - }, - [0x1162E]={ - category="lo", - direction="l", - }, - [0x1162F]={ - category="lo", - direction="l", - }, - [0x11630]={ - category="mc", - direction="l", - }, - [0x11631]={ - category="mc", - direction="l", - }, - [0x11632]={ - category="mc", - direction="l", - }, - [0x11633]={ - category="mn", - direction="nsm", - }, - [0x11634]={ - category="mn", - direction="nsm", - }, - [0x11635]={ - category="mn", - direction="nsm", - }, - [0x11636]={ - category="mn", - direction="nsm", - }, - [0x11637]={ - category="mn", - direction="nsm", - }, - [0x11638]={ - category="mn", - direction="nsm", - }, - [0x11639]={ - category="mn", - direction="nsm", - }, - [0x1163A]={ - category="mn", - direction="nsm", - }, - [0x1163B]={ - category="mc", - direction="l", - }, - [0x1163C]={ - category="mc", - direction="l", - }, - [0x1163D]={ - category="mn", - direction="nsm", - }, - [0x1163E]={ - category="mc", - direction="l", - }, - [0x1163F]={ - category="mn", - direction="nsm", - }, - [0x11640]={ - category="mn", - direction="nsm", - }, - [0x11641]={ - category="po", - direction="l", - }, - [0x11642]={ - category="po", - direction="l", - }, - [0x11643]={ - category="po", - direction="l", - }, - [0x11644]={ - category="lo", - direction="l", - }, - [0x11650]={ - category="nd", - direction="l", - }, - [0x11651]={ - category="nd", - direction="l", - }, - [0x11652]={ - category="nd", - direction="l", - }, - [0x11653]={ - category="nd", - direction="l", - }, - [0x11654]={ - category="nd", - direction="l", - }, - [0x11655]={ - category="nd", - direction="l", - }, - [0x11656]={ - category="nd", - direction="l", - }, - [0x11657]={ - category="nd", - direction="l", - }, - [0x11658]={ - category="nd", - direction="l", - }, - [0x11659]={ - category="nd", - direction="l", - }, - [0x11660]={ - category="po", - direction="on", - }, - [0x11661]={ - category="po", - direction="on", - }, - [0x11662]={ - category="po", - direction="on", - }, - [0x11663]={ - category="po", - direction="on", - }, - [0x11664]={ - category="po", - direction="on", - }, - [0x11665]={ - category="po", - direction="on", - }, - [0x11666]={ - category="po", - direction="on", - }, - [0x11667]={ - category="po", - direction="on", - }, - [0x11668]={ - category="po", - direction="on", - }, - [0x11669]={ - category="po", - direction="on", - }, - [0x1166A]={ - category="po", - direction="on", - }, - [0x1166B]={ - category="po", - direction="on", - }, - [0x1166C]={ - category="po", - direction="on", - }, - [0x11680]={ - category="lo", - direction="l", - }, - [0x11681]={ - category="lo", - direction="l", - }, - [0x11682]={ - category="lo", - direction="l", - }, - [0x11683]={ - category="lo", - direction="l", - }, - [0x11684]={ - category="lo", - direction="l", - }, - [0x11685]={ - category="lo", - direction="l", - }, - [0x11686]={ - category="lo", - direction="l", - }, - [0x11687]={ - category="lo", - direction="l", - }, - [0x11688]={ - category="lo", - direction="l", - }, - [0x11689]={ - category="lo", - direction="l", - }, - [0x1168A]={ - category="lo", - direction="l", - }, - [0x1168B]={ - category="lo", - direction="l", - }, - [0x1168C]={ - category="lo", - direction="l", - }, - [0x1168D]={ - category="lo", - direction="l", - }, - [0x1168E]={ - category="lo", - direction="l", - }, - [0x1168F]={ - category="lo", - direction="l", - }, - [0x11690]={ - category="lo", - direction="l", - }, - [0x11691]={ - category="lo", - direction="l", - }, - [0x11692]={ - category="lo", - direction="l", - }, - [0x11693]={ - category="lo", - direction="l", - }, - [0x11694]={ - category="lo", - direction="l", - }, - [0x11695]={ - category="lo", - direction="l", - }, - [0x11696]={ - category="lo", - direction="l", - }, - [0x11697]={ - category="lo", - direction="l", - }, - [0x11698]={ - category="lo", - direction="l", - }, - [0x11699]={ - category="lo", - direction="l", - }, - [0x1169A]={ - category="lo", - direction="l", - }, - [0x1169B]={ - category="lo", - direction="l", - }, - [0x1169C]={ - category="lo", - direction="l", - }, - [0x1169D]={ - category="lo", - direction="l", - }, - [0x1169E]={ - category="lo", - direction="l", - }, - [0x1169F]={ - category="lo", - direction="l", - }, - [0x116A0]={ - category="lo", - direction="l", - }, - [0x116A1]={ - category="lo", - direction="l", - }, - [0x116A2]={ - category="lo", - direction="l", - }, - [0x116A3]={ - category="lo", - direction="l", - }, - [0x116A4]={ - category="lo", - direction="l", - }, - [0x116A5]={ - category="lo", - direction="l", - }, - [0x116A6]={ - category="lo", - direction="l", - }, - [0x116A7]={ - category="lo", - direction="l", - }, - [0x116A8]={ - category="lo", - direction="l", - }, - [0x116A9]={ - category="lo", - direction="l", - }, - [0x116AA]={ - category="lo", - direction="l", - }, - [0x116AB]={ - category="mn", - direction="nsm", - }, - [0x116AC]={ - category="mc", - direction="l", - }, - [0x116AD]={ - category="mn", - direction="nsm", - }, - [0x116AE]={ - category="mc", - direction="l", - }, - [0x116AF]={ - category="mc", - direction="l", - }, - [0x116B0]={ - category="mn", - direction="nsm", - }, - [0x116B1]={ - category="mn", - direction="nsm", - }, - [0x116B2]={ - category="mn", - direction="nsm", - }, - [0x116B3]={ - category="mn", - direction="nsm", - }, - [0x116B4]={ - category="mn", - direction="nsm", - }, - [0x116B5]={ - category="mn", - direction="nsm", - }, - [0x116B6]={ - category="mc", - direction="l", - }, - [0x116B7]={ - category="mn", - direction="nsm", - }, - [0x116C0]={ - category="nd", - direction="l", - }, - [0x116C1]={ - category="nd", - direction="l", - }, - [0x116C2]={ - category="nd", - direction="l", - }, - [0x116C3]={ - category="nd", - direction="l", - }, - [0x116C4]={ - category="nd", - direction="l", - }, - [0x116C5]={ - category="nd", - direction="l", - }, - [0x116C6]={ - category="nd", - direction="l", - }, - [0x116C7]={ - category="nd", - direction="l", - }, - [0x116C8]={ - category="nd", - direction="l", - }, - [0x116C9]={ - category="nd", - direction="l", - }, - [0x11700]={ - category="lo", - direction="l", - }, - [0x11701]={ - category="lo", - direction="l", - }, - [0x11702]={ - category="lo", - direction="l", - }, - [0x11703]={ - category="lo", - direction="l", - }, - [0x11704]={ - category="lo", - direction="l", - }, - [0x11705]={ - category="lo", - direction="l", - }, - [0x11706]={ - category="lo", - direction="l", - }, - [0x11707]={ - category="lo", - direction="l", - }, - [0x11708]={ - category="lo", - direction="l", - }, - [0x11709]={ - category="lo", - direction="l", - }, - [0x1170A]={ - category="lo", - direction="l", - }, - [0x1170B]={ - category="lo", - direction="l", - }, - [0x1170C]={ - category="lo", - direction="l", - }, - [0x1170D]={ - category="lo", - direction="l", - }, - [0x1170E]={ - category="lo", - direction="l", - }, - [0x1170F]={ - category="lo", - direction="l", - }, - [0x11710]={ - category="lo", - direction="l", - }, - [0x11711]={ - category="lo", - direction="l", - }, - [0x11712]={ - category="lo", - direction="l", - }, - [0x11713]={ - category="lo", - direction="l", - }, - [0x11714]={ - category="lo", - direction="l", - }, - [0x11715]={ - category="lo", - direction="l", - }, - [0x11716]={ - category="lo", - direction="l", - }, - [0x11717]={ - category="lo", - direction="l", - }, - [0x11718]={ - category="lo", - direction="l", - }, - [0x11719]={ - category="lo", - direction="l", - }, - [0x1171D]={ - category="mn", - direction="nsm", - }, - [0x1171E]={ - category="mn", - direction="nsm", - }, - [0x1171F]={ - category="mn", - direction="nsm", - }, - [0x11720]={ - category="mc", - direction="l", - }, - [0x11721]={ - category="mc", - direction="l", - }, - [0x11722]={ - category="mn", - direction="nsm", - }, - [0x11723]={ - category="mn", - direction="nsm", - }, - [0x11724]={ - category="mn", - direction="nsm", - }, - [0x11725]={ - category="mn", - direction="nsm", - }, - [0x11726]={ - category="mc", - direction="l", - }, - [0x11727]={ - category="mn", - direction="nsm", - }, - [0x11728]={ - category="mn", - direction="nsm", - }, - [0x11729]={ - category="mn", - direction="nsm", - }, - [0x1172A]={ - category="mn", - direction="nsm", - }, - [0x1172B]={ - category="mn", - direction="nsm", - }, - [0x11730]={ - category="nd", - direction="l", - }, - [0x11731]={ - category="nd", - direction="l", - }, - [0x11732]={ - category="nd", - direction="l", - }, - [0x11733]={ - category="nd", - direction="l", - }, - [0x11734]={ - category="nd", - direction="l", - }, - [0x11735]={ - category="nd", - direction="l", - }, - [0x11736]={ - category="nd", - direction="l", - }, - [0x11737]={ - category="nd", - direction="l", - }, - [0x11738]={ - category="nd", - direction="l", - }, - [0x11739]={ - category="nd", - direction="l", - }, - [0x1173A]={ - category="no", - direction="l", - }, - [0x1173B]={ - category="no", - direction="l", - }, - [0x1173C]={ - category="po", - direction="l", - }, - [0x1173D]={ - category="po", - direction="l", - }, - [0x1173E]={ - category="po", - direction="l", - }, - [0x1173F]={ - category="so", - direction="l", - }, - [0x118A0]={ - category="lu", - direction="l", - }, - [0x118A1]={ - category="lu", - direction="l", - }, - [0x118A2]={ - category="lu", - direction="l", - }, - [0x118A3]={ - category="lu", - direction="l", - }, - [0x118A4]={ - category="lu", - direction="l", - }, - [0x118A5]={ - category="lu", - direction="l", - }, - [0x118A6]={ - category="lu", - direction="l", - }, - [0x118A7]={ - category="lu", - direction="l", - }, - [0x118A8]={ - category="lu", - direction="l", - }, - [0x118A9]={ - category="lu", - direction="l", - }, - [0x118AA]={ - category="lu", - direction="l", - }, - [0x118AB]={ - category="lu", - direction="l", - }, - [0x118AC]={ - category="lu", - direction="l", - }, - [0x118AD]={ - category="lu", - direction="l", - }, - [0x118AE]={ - category="lu", - direction="l", - }, - [0x118AF]={ - category="lu", - direction="l", - }, - [0x118B0]={ - category="lu", - direction="l", - }, - [0x118B1]={ - category="lu", - direction="l", - }, - [0x118B2]={ - category="lu", - direction="l", - }, - [0x118B3]={ - category="lu", - direction="l", - }, - [0x118B4]={ - category="lu", - direction="l", - }, - [0x118B5]={ - category="lu", - direction="l", - }, - [0x118B6]={ - category="lu", - direction="l", - }, - [0x118B7]={ - category="lu", - direction="l", - }, - [0x118B8]={ - category="lu", - direction="l", - }, - [0x118B9]={ - category="lu", - direction="l", - }, - [0x118BA]={ - category="lu", - direction="l", - }, - [0x118BB]={ - category="lu", - direction="l", - }, - [0x118BC]={ - category="lu", - direction="l", - }, - [0x118BD]={ - category="lu", - direction="l", - }, - [0x118BE]={ - category="lu", - direction="l", - }, - [0x118BF]={ - category="lu", - direction="l", - }, - [0x118C0]={ - category="ll", - direction="l", - }, - [0x118C1]={ - category="ll", - direction="l", - }, - [0x118C2]={ - category="ll", - direction="l", - }, - [0x118C3]={ - category="ll", - direction="l", - }, - [0x118C4]={ - category="ll", - direction="l", - }, - [0x118C5]={ - category="ll", - direction="l", - }, - [0x118C6]={ - category="ll", - direction="l", - }, - [0x118C7]={ - category="ll", - direction="l", - }, - [0x118C8]={ - category="ll", - direction="l", - }, - [0x118C9]={ - category="ll", - direction="l", - }, - [0x118CA]={ - category="ll", - direction="l", - }, - [0x118CB]={ - category="ll", - direction="l", - }, - [0x118CC]={ - category="ll", - direction="l", - }, - [0x118CD]={ - category="ll", - direction="l", - }, - [0x118CE]={ - category="ll", - direction="l", - }, - [0x118CF]={ - category="ll", - direction="l", - }, - [0x118D0]={ - category="ll", - direction="l", - }, - [0x118D1]={ - category="ll", - direction="l", - }, - [0x118D2]={ - category="ll", - direction="l", - }, - [0x118D3]={ - category="ll", - direction="l", - }, - [0x118D4]={ - category="ll", - direction="l", - }, - [0x118D5]={ - category="ll", - direction="l", - }, - [0x118D6]={ - category="ll", - direction="l", - }, - [0x118D7]={ - category="ll", - direction="l", - }, - [0x118D8]={ - category="ll", - direction="l", - }, - [0x118D9]={ - category="ll", - direction="l", - }, - [0x118DA]={ - category="ll", - direction="l", - }, - [0x118DB]={ - category="ll", - direction="l", - }, - [0x118DC]={ - category="ll", - direction="l", - }, - [0x118DD]={ - category="ll", - direction="l", - }, - [0x118DE]={ - category="ll", - direction="l", - }, - [0x118DF]={ - category="ll", - direction="l", - }, - [0x118E0]={ - category="nd", - direction="l", - }, - [0x118E1]={ - category="nd", - direction="l", - }, - [0x118E2]={ - category="nd", - direction="l", - }, - [0x118E3]={ - category="nd", - direction="l", - }, - [0x118E4]={ - category="nd", - direction="l", - }, - [0x118E5]={ - category="nd", - direction="l", - }, - [0x118E6]={ - category="nd", - direction="l", - }, - [0x118E7]={ - category="nd", - direction="l", - }, - [0x118E8]={ - category="nd", - direction="l", - }, - [0x118E9]={ - category="nd", - direction="l", - }, - [0x118EA]={ - category="no", - direction="l", - }, - [0x118EB]={ - category="no", - direction="l", - }, - [0x118EC]={ - category="no", - direction="l", - }, - [0x118ED]={ - category="no", - direction="l", - }, - [0x118EE]={ - category="no", - direction="l", - }, - [0x118EF]={ - category="no", - direction="l", - }, - [0x118F0]={ - category="no", - direction="l", - }, - [0x118F1]={ - category="no", - direction="l", - }, - [0x118F2]={ - category="no", - direction="l", - }, - [0x118FF]={ - category="lo", - direction="l", - }, - [0x11AC0]={ - category="lo", - direction="l", - }, - [0x11AC1]={ - category="lo", - direction="l", - }, - [0x11AC2]={ - category="lo", - direction="l", - }, - [0x11AC3]={ - category="lo", - direction="l", - }, - [0x11AC4]={ - category="lo", - direction="l", - }, - [0x11AC5]={ - category="lo", - direction="l", - }, - [0x11AC6]={ - category="lo", - direction="l", - }, - [0x11AC7]={ - category="lo", - direction="l", - }, - [0x11AC8]={ - category="lo", - direction="l", - }, - [0x11AC9]={ - category="lo", - direction="l", - }, - [0x11ACA]={ - category="lo", - direction="l", - }, - [0x11ACB]={ - category="lo", - direction="l", - }, - [0x11ACC]={ - category="lo", - direction="l", - }, - [0x11ACD]={ - category="lo", - direction="l", - }, - [0x11ACE]={ - category="lo", - direction="l", - }, - [0x11ACF]={ - category="lo", - direction="l", - }, - [0x11AD0]={ - category="lo", - direction="l", - }, - [0x11AD1]={ - category="lo", - direction="l", - }, - [0x11AD2]={ - category="lo", - direction="l", - }, - [0x11AD3]={ - category="lo", - direction="l", - }, - [0x11AD4]={ - category="lo", - direction="l", - }, - [0x11AD5]={ - category="lo", - direction="l", - }, - [0x11AD6]={ - category="lo", - direction="l", - }, - [0x11AD7]={ - category="lo", - direction="l", - }, - [0x11AD8]={ - category="lo", - direction="l", - }, - [0x11AD9]={ - category="lo", - direction="l", - }, - [0x11ADA]={ - category="lo", - direction="l", - }, - [0x11ADB]={ - category="lo", - direction="l", - }, - [0x11ADC]={ - category="lo", - direction="l", - }, - [0x11ADD]={ - category="lo", - direction="l", - }, - [0x11ADE]={ - category="lo", - direction="l", - }, - [0x11ADF]={ - category="lo", - direction="l", - }, - [0x11AE0]={ - category="lo", - direction="l", - }, - [0x11AE1]={ - category="lo", - direction="l", - }, - [0x11AE2]={ - category="lo", - direction="l", - }, - [0x11AE3]={ - category="lo", - direction="l", - }, - [0x11AE4]={ - category="lo", - direction="l", - }, - [0x11AE5]={ - category="lo", - direction="l", - }, - [0x11AE6]={ - category="lo", - direction="l", - }, - [0x11AE7]={ - category="lo", - direction="l", - }, - [0x11AE8]={ - category="lo", - direction="l", - }, - [0x11AE9]={ - category="lo", - direction="l", - }, - [0x11AEA]={ - category="lo", - direction="l", - }, - [0x11AEB]={ - category="lo", - direction="l", - }, - [0x11AEC]={ - category="lo", - direction="l", - }, - [0x11AED]={ - category="lo", - direction="l", - }, - [0x11AEE]={ - category="lo", - direction="l", - }, - [0x11AEF]={ - category="lo", - direction="l", - }, - [0x11AF0]={ - category="lo", - direction="l", - }, - [0x11AF1]={ - category="lo", - direction="l", - }, - [0x11AF2]={ - category="lo", - direction="l", - }, - [0x11AF3]={ - category="lo", - direction="l", - }, - [0x11AF4]={ - category="lo", - direction="l", - }, - [0x11AF5]={ - category="lo", - direction="l", - }, - [0x11AF6]={ - category="lo", - direction="l", - }, - [0x11AF7]={ - category="lo", - direction="l", - }, - [0x11AF8]={ - category="lo", - direction="l", - }, - [0x11C00]={ - category="lo", - direction="l", - }, - [0x11C01]={ - category="lo", - direction="l", - }, - [0x11C02]={ - category="lo", - direction="l", - }, - [0x11C03]={ - category="lo", - direction="l", - }, - [0x11C04]={ - category="lo", - direction="l", - }, - [0x11C05]={ - category="lo", - direction="l", - }, - [0x11C06]={ - category="lo", - direction="l", - }, - [0x11C07]={ - category="lo", - direction="l", - }, - [0x11C08]={ - category="lo", - direction="l", - }, - [0x11C0A]={ - category="lo", - direction="l", - }, - [0x11C0B]={ - category="lo", - direction="l", - }, - [0x11C0C]={ - category="lo", - direction="l", - }, - [0x11C0D]={ - category="lo", - direction="l", - }, - [0x11C0E]={ - category="lo", - direction="l", - }, - [0x11C0F]={ - category="lo", - direction="l", - }, - [0x11C10]={ - category="lo", - direction="l", - }, - [0x11C11]={ - category="lo", - direction="l", - }, - [0x11C12]={ - category="lo", - direction="l", - }, - [0x11C13]={ - category="lo", - direction="l", - }, - [0x11C14]={ - category="lo", - direction="l", - }, - [0x11C15]={ - category="lo", - direction="l", - }, - [0x11C16]={ - category="lo", - direction="l", - }, - [0x11C17]={ - category="lo", - direction="l", - }, - [0x11C18]={ - category="lo", - direction="l", - }, - [0x11C19]={ - category="lo", - direction="l", - }, - [0x11C1A]={ - category="lo", - direction="l", - }, - [0x11C1B]={ - category="lo", - direction="l", - }, - [0x11C1C]={ - category="lo", - direction="l", - }, - [0x11C1D]={ - category="lo", - direction="l", - }, - [0x11C1E]={ - category="lo", - direction="l", - }, - [0x11C1F]={ - category="lo", - direction="l", - }, - [0x11C20]={ - category="lo", - direction="l", - }, - [0x11C21]={ - category="lo", - direction="l", - }, - [0x11C22]={ - category="lo", - direction="l", - }, - [0x11C23]={ - category="lo", - direction="l", - }, - [0x11C24]={ - category="lo", - direction="l", - }, - [0x11C25]={ - category="lo", - direction="l", - }, - [0x11C26]={ - category="lo", - direction="l", - }, - [0x11C27]={ - category="lo", - direction="l", - }, - [0x11C28]={ - category="lo", - direction="l", - }, - [0x11C29]={ - category="lo", - direction="l", - }, - [0x11C2A]={ - category="lo", - direction="l", - }, - [0x11C2B]={ - category="lo", - direction="l", - }, - [0x11C2C]={ - category="lo", - direction="l", - }, - [0x11C2D]={ - category="lo", - direction="l", - }, - [0x11C2E]={ - category="lo", - direction="l", - }, - [0x11C2F]={ - category="mc", - direction="l", - }, - [0x11C30]={ - category="mn", - direction="nsm", - }, - [0x11C31]={ - category="mn", - direction="nsm", - }, - [0x11C32]={ - category="mn", - direction="nsm", - }, - [0x11C33]={ - category="mn", - direction="nsm", - }, - [0x11C34]={ - category="mn", - direction="nsm", - }, - [0x11C35]={ - category="mn", - direction="nsm", - }, - [0x11C36]={ - category="mn", - direction="nsm", - }, - [0x11C38]={ - category="mn", - direction="nsm", - }, - [0x11C39]={ - category="mn", - direction="nsm", - }, - [0x11C3A]={ - category="mn", - direction="nsm", - }, - [0x11C3B]={ - category="mn", - direction="nsm", - }, - [0x11C3C]={ - category="mn", - direction="nsm", - }, - [0x11C3D]={ - category="mn", - direction="nsm", - }, - [0x11C3E]={ - category="mc", - direction="l", - }, - [0x11C3F]={ - category="mn", - direction="l", - }, - [0x11C40]={ - category="lo", - direction="l", - }, - [0x11C41]={ - category="po", - direction="l", - }, - [0x11C42]={ - category="po", - direction="l", - }, - [0x11C43]={ - category="po", - direction="l", - }, - [0x11C44]={ - category="po", - direction="l", - }, - [0x11C45]={ - category="po", - direction="l", - }, - [0x11C50]={ - category="nd", - direction="l", - }, - [0x11C51]={ - category="nd", - direction="l", - }, - [0x11C52]={ - category="nd", - direction="l", - }, - [0x11C53]={ - category="nd", - direction="l", - }, - [0x11C54]={ - category="nd", - direction="l", - }, - [0x11C55]={ - category="nd", - direction="l", - }, - [0x11C56]={ - category="nd", - direction="l", - }, - [0x11C57]={ - category="nd", - direction="l", - }, - [0x11C58]={ - category="nd", - direction="l", - }, - [0x11C59]={ - category="nd", - direction="l", - }, - [0x11C5A]={ - category="no", - direction="l", - }, - [0x11C5B]={ - category="no", - direction="l", - }, - [0x11C5C]={ - category="no", - direction="l", - }, - [0x11C5D]={ - category="no", - direction="l", - }, - [0x11C5E]={ - category="no", - direction="l", - }, - [0x11C5F]={ - category="no", - direction="l", - }, - [0x11C60]={ - category="no", - direction="l", - }, - [0x11C61]={ - category="no", - direction="l", - }, - [0x11C62]={ - category="no", - direction="l", - }, - [0x11C63]={ - category="no", - direction="l", - }, - [0x11C64]={ - category="no", - direction="l", - }, - [0x11C65]={ - category="no", - direction="l", - }, - [0x11C66]={ - category="no", - direction="l", - }, - [0x11C67]={ - category="no", - direction="l", - }, - [0x11C68]={ - category="no", - direction="l", - }, - [0x11C69]={ - category="no", - direction="l", - }, - [0x11C6A]={ - category="no", - direction="l", - }, - [0x11C6B]={ - category="no", - direction="l", - }, - [0x11C6C]={ - category="no", - direction="l", - }, - [0x11C70]={ - category="po", - direction="l", - }, - [0x11C71]={ - category="po", - direction="l", - }, - [0x11C72]={ - category="lo", - direction="l", - }, - [0x11C73]={ - category="lo", - direction="l", - }, - [0x11C74]={ - category="lo", - direction="l", - }, - [0x11C75]={ - category="lo", - direction="l", - }, - [0x11C76]={ - category="lo", - direction="l", - }, - [0x11C77]={ - category="lo", - direction="l", - }, - [0x11C78]={ - category="lo", - direction="l", - }, - [0x11C79]={ - category="lo", - direction="l", - }, - [0x11C7A]={ - category="lo", - direction="l", - }, - [0x11C7B]={ - category="lo", - direction="l", - }, - [0x11C7C]={ - category="lo", - direction="l", - }, - [0x11C7D]={ - category="lo", - direction="l", - }, - [0x11C7E]={ - category="lo", - direction="l", - }, - [0x11C7F]={ - category="lo", - direction="l", - }, - [0x11C80]={ - category="lo", - direction="l", - }, - [0x11C81]={ - category="lo", - direction="l", - }, - [0x11C82]={ - category="lo", - direction="l", - }, - [0x11C83]={ - category="lo", - direction="l", - }, - [0x11C84]={ - category="lo", - direction="l", - }, - [0x11C85]={ - category="lo", - direction="l", - }, - [0x11C86]={ - category="lo", - direction="l", - }, - [0x11C87]={ - category="lo", - direction="l", - }, - [0x11C88]={ - category="lo", - direction="l", - }, - [0x11C89]={ - category="lo", - direction="l", - }, - [0x11C8A]={ - category="lo", - direction="l", - }, - [0x11C8B]={ - category="lo", - direction="l", - }, - [0x11C8C]={ - category="lo", - direction="l", - }, - [0x11C8D]={ - category="lo", - direction="l", - }, - [0x11C8E]={ - category="lo", - direction="l", - }, - [0x11C8F]={ - category="lo", - direction="l", - }, - [0x11C92]={ - category="mn", - direction="nsm", - }, - [0x11C93]={ - category="mn", - direction="nsm", - }, - [0x11C94]={ - category="mn", - direction="nsm", - }, - [0x11C95]={ - category="mn", - direction="nsm", - }, - [0x11C96]={ - category="mn", - direction="nsm", - }, - [0x11C97]={ - category="mn", - direction="nsm", - }, - [0x11C98]={ - category="mn", - direction="nsm", - }, - [0x11C99]={ - category="mn", - direction="nsm", - }, - [0x11C9A]={ - category="mn", - direction="nsm", - }, - [0x11C9B]={ - category="mn", - direction="nsm", - }, - [0x11C9C]={ - category="mn", - direction="nsm", - }, - [0x11C9D]={ - category="mn", - direction="nsm", - }, - [0x11C9E]={ - category="mn", - direction="nsm", - }, - [0x11C9F]={ - category="mn", - direction="nsm", - }, - [0x11CA0]={ - category="mn", - direction="nsm", - }, - [0x11CA1]={ - category="mn", - direction="nsm", - }, - [0x11CA2]={ - category="mn", - direction="nsm", - }, - [0x11CA3]={ - category="mn", - direction="nsm", - }, - [0x11CA4]={ - category="mn", - direction="nsm", - }, - [0x11CA5]={ - category="mn", - direction="nsm", - }, - [0x11CA6]={ - category="mn", - direction="nsm", - }, - [0x11CA7]={ - category="mn", - direction="nsm", - }, - [0x11CA9]={ - category="mc", - direction="l", - }, - [0x11CAA]={ - category="mn", - direction="nsm", - }, - [0x11CAB]={ - category="mn", - direction="nsm", - }, - [0x11CAC]={ - category="mn", - direction="nsm", - }, - [0x11CAD]={ - category="mn", - direction="nsm", - }, - [0x11CAE]={ - category="mn", - direction="nsm", - }, - [0x11CAF]={ - category="mn", - direction="nsm", - }, - [0x11CB0]={ - category="mn", - direction="nsm", - }, - [0x11CB1]={ - category="mc", - direction="l", - }, - [0x11CB2]={ - category="mn", - direction="nsm", - }, - [0x11CB3]={ - category="mn", - direction="nsm", - }, - [0x11CB4]={ - category="mc", - direction="l", - }, - [0x11CB5]={ - category="mn", - direction="nsm", - }, - [0x11CB6]={ - category="mn", - direction="nsm", - }, - [0x12000]={ - category="lo", - direction="l", - }, - [0x12001]={ - category="lo", - direction="l", - }, - [0x12002]={ - category="lo", - direction="l", - }, - [0x12003]={ - category="lo", - direction="l", - }, - [0x12004]={ - category="lo", - direction="l", - }, - [0x12005]={ - category="lo", - direction="l", - }, - [0x12006]={ - category="lo", - direction="l", - }, - [0x12007]={ - category="lo", - direction="l", - }, - [0x12008]={ - category="lo", - direction="l", - }, - [0x12009]={ - category="lo", - direction="l", - }, - [0x1200A]={ - category="lo", - direction="l", - }, - [0x1200B]={ - category="lo", - direction="l", - }, - [0x1200C]={ - category="lo", - direction="l", - }, - [0x1200D]={ - category="lo", - direction="l", - }, - [0x1200E]={ - category="lo", - direction="l", - }, - [0x1200F]={ - category="lo", - direction="l", - }, - [0x12010]={ - category="lo", - direction="l", - }, - [0x12011]={ - category="lo", - direction="l", - }, - [0x12012]={ - category="lo", - direction="l", - }, - [0x12013]={ - category="lo", - direction="l", - }, - [0x12014]={ - category="lo", - direction="l", - }, - [0x12015]={ - category="lo", - direction="l", - }, - [0x12016]={ - category="lo", - direction="l", - }, - [0x12017]={ - category="lo", - direction="l", - }, - [0x12018]={ - category="lo", - direction="l", - }, - [0x12019]={ - category="lo", - direction="l", - }, - [0x1201A]={ - category="lo", - direction="l", - }, - [0x1201B]={ - category="lo", - direction="l", - }, - [0x1201C]={ - category="lo", - direction="l", - }, - [0x1201D]={ - category="lo", - direction="l", - }, - [0x1201E]={ - category="lo", - direction="l", - }, - [0x1201F]={ - category="lo", - direction="l", - }, - [0x12020]={ - category="lo", - direction="l", - }, - [0x12021]={ - category="lo", - direction="l", - }, - [0x12022]={ - category="lo", - direction="l", - }, - [0x12023]={ - category="lo", - direction="l", - }, - [0x12024]={ - category="lo", - direction="l", - }, - [0x12025]={ - category="lo", - direction="l", - }, - [0x12026]={ - category="lo", - direction="l", - }, - [0x12027]={ - category="lo", - direction="l", - }, - [0x12028]={ - category="lo", - direction="l", - }, - [0x12029]={ - category="lo", - direction="l", - }, - [0x1202A]={ - category="lo", - direction="l", - }, - [0x1202B]={ - category="lo", - direction="l", - }, - [0x1202C]={ - category="lo", - direction="l", - }, - [0x1202D]={ - category="lo", - direction="l", - }, - [0x1202E]={ - category="lo", - direction="l", - }, - [0x1202F]={ - category="lo", - direction="l", - }, - [0x12030]={ - category="lo", - direction="l", - }, - [0x12031]={ - category="lo", - direction="l", - }, - [0x12032]={ - category="lo", - direction="l", - }, - [0x12033]={ - category="lo", - direction="l", - }, - [0x12034]={ - category="lo", - direction="l", - }, - [0x12035]={ - category="lo", - direction="l", - }, - [0x12036]={ - category="lo", - direction="l", - }, - [0x12037]={ - category="lo", - direction="l", - }, - [0x12038]={ - category="lo", - direction="l", - }, - [0x12039]={ - category="lo", - direction="l", - }, - [0x1203A]={ - category="lo", - direction="l", - }, - [0x1203B]={ - category="lo", - direction="l", - }, - [0x1203C]={ - category="lo", - direction="l", - }, - [0x1203D]={ - category="lo", - direction="l", - }, - [0x1203E]={ - category="lo", - direction="l", - }, - [0x1203F]={ - category="lo", - direction="l", - }, - [0x12040]={ - category="lo", - direction="l", - }, - [0x12041]={ - category="lo", - direction="l", - }, - [0x12042]={ - category="lo", - direction="l", - }, - [0x12043]={ - category="lo", - direction="l", - }, - [0x12044]={ - category="lo", - direction="l", - }, - [0x12045]={ - category="lo", - direction="l", - }, - [0x12046]={ - category="lo", - direction="l", - }, - [0x12047]={ - category="lo", - direction="l", - }, - [0x12048]={ - category="lo", - direction="l", - }, - [0x12049]={ - category="lo", - direction="l", - }, - [0x1204A]={ - category="lo", - direction="l", - }, - [0x1204B]={ - category="lo", - direction="l", - }, - [0x1204C]={ - category="lo", - direction="l", - }, - [0x1204D]={ - category="lo", - direction="l", - }, - [0x1204E]={ - category="lo", - direction="l", - }, - [0x1204F]={ - category="lo", - direction="l", - }, - [0x12050]={ - category="lo", - direction="l", - }, - [0x12051]={ - category="lo", - direction="l", - }, - [0x12052]={ - category="lo", - direction="l", - }, - [0x12053]={ - category="lo", - direction="l", - }, - [0x12054]={ - category="lo", - direction="l", - }, - [0x12055]={ - category="lo", - direction="l", - }, - [0x12056]={ - category="lo", - direction="l", - }, - [0x12057]={ - category="lo", - direction="l", - }, - [0x12058]={ - category="lo", - direction="l", - }, - [0x12059]={ - category="lo", - direction="l", - }, - [0x1205A]={ - category="lo", - direction="l", - }, - [0x1205B]={ - category="lo", - direction="l", - }, - [0x1205C]={ - category="lo", - direction="l", - }, - [0x1205D]={ - category="lo", - direction="l", - }, - [0x1205E]={ - category="lo", - direction="l", - }, - [0x1205F]={ - category="lo", - direction="l", - }, - [0x12060]={ - category="lo", - direction="l", - }, - [0x12061]={ - category="lo", - direction="l", - }, - [0x12062]={ - category="lo", - direction="l", - }, - [0x12063]={ - category="lo", - direction="l", - }, - [0x12064]={ - category="lo", - direction="l", - }, - [0x12065]={ - category="lo", - direction="l", - }, - [0x12066]={ - category="lo", - direction="l", - }, - [0x12067]={ - category="lo", - direction="l", - }, - [0x12068]={ - category="lo", - direction="l", - }, - [0x12069]={ - category="lo", - direction="l", - }, - [0x1206A]={ - category="lo", - direction="l", - }, - [0x1206B]={ - category="lo", - direction="l", - }, - [0x1206C]={ - category="lo", - direction="l", - }, - [0x1206D]={ - category="lo", - direction="l", - }, - [0x1206E]={ - category="lo", - direction="l", - }, - [0x1206F]={ - category="lo", - direction="l", - }, - [0x12070]={ - category="lo", - direction="l", - }, - [0x12071]={ - category="lo", - direction="l", - }, - [0x12072]={ - category="lo", - direction="l", - }, - [0x12073]={ - category="lo", - direction="l", - }, - [0x12074]={ - category="lo", - direction="l", - }, - [0x12075]={ - category="lo", - direction="l", - }, - [0x12076]={ - category="lo", - direction="l", - }, - [0x12077]={ - category="lo", - direction="l", - }, - [0x12078]={ - category="lo", - direction="l", - }, - [0x12079]={ - category="lo", - direction="l", - }, - [0x1207A]={ - category="lo", - direction="l", - }, - [0x1207B]={ - category="lo", - direction="l", - }, - [0x1207C]={ - category="lo", - direction="l", - }, - [0x1207D]={ - category="lo", - direction="l", - }, - [0x1207E]={ - category="lo", - direction="l", - }, - [0x1207F]={ - category="lo", - direction="l", - }, - [0x12080]={ - category="lo", - direction="l", - }, - [0x12081]={ - category="lo", - direction="l", - }, - [0x12082]={ - category="lo", - direction="l", - }, - [0x12083]={ - category="lo", - direction="l", - }, - [0x12084]={ - category="lo", - direction="l", - }, - [0x12085]={ - category="lo", - direction="l", - }, - [0x12086]={ - category="lo", - direction="l", - }, - [0x12087]={ - category="lo", - direction="l", - }, - [0x12088]={ - category="lo", - direction="l", - }, - [0x12089]={ - category="lo", - direction="l", - }, - [0x1208A]={ - category="lo", - direction="l", - }, - [0x1208B]={ - category="lo", - direction="l", - }, - [0x1208C]={ - category="lo", - direction="l", - }, - [0x1208D]={ - category="lo", - direction="l", - }, - [0x1208E]={ - category="lo", - direction="l", - }, - [0x1208F]={ - category="lo", - direction="l", - }, - [0x12090]={ - category="lo", - direction="l", - }, - [0x12091]={ - category="lo", - direction="l", - }, - [0x12092]={ - category="lo", - direction="l", - }, - [0x12093]={ - category="lo", - direction="l", - }, - [0x12094]={ - category="lo", - direction="l", - }, - [0x12095]={ - category="lo", - direction="l", - }, - [0x12096]={ - category="lo", - direction="l", - }, - [0x12097]={ - category="lo", - direction="l", - }, - [0x12098]={ - category="lo", - direction="l", - }, - [0x12099]={ - category="lo", - direction="l", - }, - [0x1209A]={ - category="lo", - direction="l", - }, - [0x1209B]={ - category="lo", - direction="l", - }, - [0x1209C]={ - category="lo", - direction="l", - }, - [0x1209D]={ - category="lo", - direction="l", - }, - [0x1209E]={ - category="lo", - direction="l", - }, - [0x1209F]={ - category="lo", - direction="l", - }, - [0x120A0]={ - category="lo", - direction="l", - }, - [0x120A1]={ - category="lo", - direction="l", - }, - [0x120A2]={ - category="lo", - direction="l", - }, - [0x120A3]={ - category="lo", - direction="l", - }, - [0x120A4]={ - category="lo", - direction="l", - }, - [0x120A5]={ - category="lo", - direction="l", - }, - [0x120A6]={ - category="lo", - direction="l", - }, - [0x120A7]={ - category="lo", - direction="l", - }, - [0x120A8]={ - category="lo", - direction="l", - }, - [0x120A9]={ - category="lo", - direction="l", - }, - [0x120AA]={ - category="lo", - direction="l", - }, - [0x120AB]={ - category="lo", - direction="l", - }, - [0x120AC]={ - category="lo", - direction="l", - }, - [0x120AD]={ - category="lo", - direction="l", - }, - [0x120AE]={ - category="lo", - direction="l", - }, - [0x120AF]={ - category="lo", - direction="l", - }, - [0x120B0]={ - category="lo", - direction="l", - }, - [0x120B1]={ - category="lo", - direction="l", - }, - [0x120B2]={ - category="lo", - direction="l", - }, - [0x120B3]={ - category="lo", - direction="l", - }, - [0x120B4]={ - category="lo", - direction="l", - }, - [0x120B5]={ - category="lo", - direction="l", - }, - [0x120B6]={ - category="lo", - direction="l", - }, - [0x120B7]={ - category="lo", - direction="l", - }, - [0x120B8]={ - category="lo", - direction="l", - }, - [0x120B9]={ - category="lo", - direction="l", - }, - [0x120BA]={ - category="lo", - direction="l", - }, - [0x120BB]={ - category="lo", - direction="l", - }, - [0x120BC]={ - category="lo", - direction="l", - }, - [0x120BD]={ - category="lo", - direction="l", - }, - [0x120BE]={ - category="lo", - direction="l", - }, - [0x120BF]={ - category="lo", - direction="l", - }, - [0x120C0]={ - category="lo", - direction="l", - }, - [0x120C1]={ - category="lo", - direction="l", - }, - [0x120C2]={ - category="lo", - direction="l", - }, - [0x120C3]={ - category="lo", - direction="l", - }, - [0x120C4]={ - category="lo", - direction="l", - }, - [0x120C5]={ - category="lo", - direction="l", - }, - [0x120C6]={ - category="lo", - direction="l", - }, - [0x120C7]={ - category="lo", - direction="l", - }, - [0x120C8]={ - category="lo", - direction="l", - }, - [0x120C9]={ - category="lo", - direction="l", - }, - [0x120CA]={ - category="lo", - direction="l", - }, - [0x120CB]={ - category="lo", - direction="l", - }, - [0x120CC]={ - category="lo", - direction="l", - }, - [0x120CD]={ - category="lo", - direction="l", - }, - [0x120CE]={ - category="lo", - direction="l", - }, - [0x120CF]={ - category="lo", - direction="l", - }, - [0x120D0]={ - category="lo", - direction="l", - }, - [0x120D1]={ - category="lo", - direction="l", - }, - [0x120D2]={ - category="lo", - direction="l", - }, - [0x120D3]={ - category="lo", - direction="l", - }, - [0x120D4]={ - category="lo", - direction="l", - }, - [0x120D5]={ - category="lo", - direction="l", - }, - [0x120D6]={ - category="lo", - direction="l", - }, - [0x120D7]={ - category="lo", - direction="l", - }, - [0x120D8]={ - category="lo", - direction="l", - }, - [0x120D9]={ - category="lo", - direction="l", - }, - [0x120DA]={ - category="lo", - direction="l", - }, - [0x120DB]={ - category="lo", - direction="l", - }, - [0x120DC]={ - category="lo", - direction="l", - }, - [0x120DD]={ - category="lo", - direction="l", - }, - [0x120DE]={ - category="lo", - direction="l", - }, - [0x120DF]={ - category="lo", - direction="l", - }, - [0x120E0]={ - category="lo", - direction="l", - }, - [0x120E1]={ - category="lo", - direction="l", - }, - [0x120E2]={ - category="lo", - direction="l", - }, - [0x120E3]={ - category="lo", - direction="l", - }, - [0x120E4]={ - category="lo", - direction="l", - }, - [0x120E5]={ - category="lo", - direction="l", - }, - [0x120E6]={ - category="lo", - direction="l", - }, - [0x120E7]={ - category="lo", - direction="l", - }, - [0x120E8]={ - category="lo", - direction="l", - }, - [0x120E9]={ - category="lo", - direction="l", - }, - [0x120EA]={ - category="lo", - direction="l", - }, - [0x120EB]={ - category="lo", - direction="l", - }, - [0x120EC]={ - category="lo", - direction="l", - }, - [0x120ED]={ - category="lo", - direction="l", - }, - [0x120EE]={ - category="lo", - direction="l", - }, - [0x120EF]={ - category="lo", - direction="l", - }, - [0x120F0]={ - category="lo", - direction="l", - }, - [0x120F1]={ - category="lo", - direction="l", - }, - [0x120F2]={ - category="lo", - direction="l", - }, - [0x120F3]={ - category="lo", - direction="l", - }, - [0x120F4]={ - category="lo", - direction="l", - }, - [0x120F5]={ - category="lo", - direction="l", - }, - [0x120F6]={ - category="lo", - direction="l", - }, - [0x120F7]={ - category="lo", - direction="l", - }, - [0x120F8]={ - category="lo", - direction="l", - }, - [0x120F9]={ - category="lo", - direction="l", - }, - [0x120FA]={ - category="lo", - direction="l", - }, - [0x120FB]={ - category="lo", - direction="l", - }, - [0x120FC]={ - category="lo", - direction="l", - }, - [0x120FD]={ - category="lo", - direction="l", - }, - [0x120FE]={ - category="lo", - direction="l", - }, - [0x120FF]={ - category="lo", - direction="l", - }, - [0x12100]={ - category="lo", - direction="l", - }, - [0x12101]={ - category="lo", - direction="l", - }, - [0x12102]={ - category="lo", - direction="l", - }, - [0x12103]={ - category="lo", - direction="l", - }, - [0x12104]={ - category="lo", - direction="l", - }, - [0x12105]={ - category="lo", - direction="l", - }, - [0x12106]={ - category="lo", - direction="l", - }, - [0x12107]={ - category="lo", - direction="l", - }, - [0x12108]={ - category="lo", - direction="l", - }, - [0x12109]={ - category="lo", - direction="l", - }, - [0x1210A]={ - category="lo", - direction="l", - }, - [0x1210B]={ - category="lo", - direction="l", - }, - [0x1210C]={ - category="lo", - direction="l", - }, - [0x1210D]={ - category="lo", - direction="l", - }, - [0x1210E]={ - category="lo", - direction="l", - }, - [0x1210F]={ - category="lo", - direction="l", - }, - [0x12110]={ - category="lo", - direction="l", - }, - [0x12111]={ - category="lo", - direction="l", - }, - [0x12112]={ - category="lo", - direction="l", - }, - [0x12113]={ - category="lo", - direction="l", - }, - [0x12114]={ - category="lo", - direction="l", - }, - [0x12115]={ - category="lo", - direction="l", - }, - [0x12116]={ - category="lo", - direction="l", - }, - [0x12117]={ - category="lo", - direction="l", - }, - [0x12118]={ - category="lo", - direction="l", - }, - [0x12119]={ - category="lo", - direction="l", - }, - [0x1211A]={ - category="lo", - direction="l", - }, - [0x1211B]={ - category="lo", - direction="l", - }, - [0x1211C]={ - category="lo", - direction="l", - }, - [0x1211D]={ - category="lo", - direction="l", - }, - [0x1211E]={ - category="lo", - direction="l", - }, - [0x1211F]={ - category="lo", - direction="l", - }, - [0x12120]={ - category="lo", - direction="l", - }, - [0x12121]={ - category="lo", - direction="l", - }, - [0x12122]={ - category="lo", - direction="l", - }, - [0x12123]={ - category="lo", - direction="l", - }, - [0x12124]={ - category="lo", - direction="l", - }, - [0x12125]={ - category="lo", - direction="l", - }, - [0x12126]={ - category="lo", - direction="l", - }, - [0x12127]={ - category="lo", - direction="l", - }, - [0x12128]={ - category="lo", - direction="l", - }, - [0x12129]={ - category="lo", - direction="l", - }, - [0x1212A]={ - category="lo", - direction="l", - }, - [0x1212B]={ - category="lo", - direction="l", - }, - [0x1212C]={ - category="lo", - direction="l", - }, - [0x1212D]={ - category="lo", - direction="l", - }, - [0x1212E]={ - category="lo", - direction="l", - }, - [0x1212F]={ - category="lo", - direction="l", - }, - [0x12130]={ - category="lo", - direction="l", - }, - [0x12131]={ - category="lo", - direction="l", - }, - [0x12132]={ - category="lo", - direction="l", - }, - [0x12133]={ - category="lo", - direction="l", - }, - [0x12134]={ - category="lo", - direction="l", - }, - [0x12135]={ - category="lo", - direction="l", - }, - [0x12136]={ - category="lo", - direction="l", - }, - [0x12137]={ - category="lo", - direction="l", - }, - [0x12138]={ - category="lo", - direction="l", - }, - [0x12139]={ - category="lo", - direction="l", - }, - [0x1213A]={ - category="lo", - direction="l", - }, - [0x1213B]={ - category="lo", - direction="l", - }, - [0x1213C]={ - category="lo", - direction="l", - }, - [0x1213D]={ - category="lo", - direction="l", - }, - [0x1213E]={ - category="lo", - direction="l", - }, - [0x1213F]={ - category="lo", - direction="l", - }, - [0x12140]={ - category="lo", - direction="l", - }, - [0x12141]={ - category="lo", - direction="l", - }, - [0x12142]={ - category="lo", - direction="l", - }, - [0x12143]={ - category="lo", - direction="l", - }, - [0x12144]={ - category="lo", - direction="l", - }, - [0x12145]={ - category="lo", - direction="l", - }, - [0x12146]={ - category="lo", - direction="l", - }, - [0x12147]={ - category="lo", - direction="l", - }, - [0x12148]={ - category="lo", - direction="l", - }, - [0x12149]={ - category="lo", - direction="l", - }, - [0x1214A]={ - category="lo", - direction="l", - }, - [0x1214B]={ - category="lo", - direction="l", - }, - [0x1214C]={ - category="lo", - direction="l", - }, - [0x1214D]={ - category="lo", - direction="l", - }, - [0x1214E]={ - category="lo", - direction="l", - }, - [0x1214F]={ - category="lo", - direction="l", - }, - [0x12150]={ - category="lo", - direction="l", - }, - [0x12151]={ - category="lo", - direction="l", - }, - [0x12152]={ - category="lo", - direction="l", - }, - [0x12153]={ - category="lo", - direction="l", - }, - [0x12154]={ - category="lo", - direction="l", - }, - [0x12155]={ - category="lo", - direction="l", - }, - [0x12156]={ - category="lo", - direction="l", - }, - [0x12157]={ - category="lo", - direction="l", - }, - [0x12158]={ - category="lo", - direction="l", - }, - [0x12159]={ - category="lo", - direction="l", - }, - [0x1215A]={ - category="lo", - direction="l", - }, - [0x1215B]={ - category="lo", - direction="l", - }, - [0x1215C]={ - category="lo", - direction="l", - }, - [0x1215D]={ - category="lo", - direction="l", - }, - [0x1215E]={ - category="lo", - direction="l", - }, - [0x1215F]={ - category="lo", - direction="l", - }, - [0x12160]={ - category="lo", - direction="l", - }, - [0x12161]={ - category="lo", - direction="l", - }, - [0x12162]={ - category="lo", - direction="l", - }, - [0x12163]={ - category="lo", - direction="l", - }, - [0x12164]={ - category="lo", - direction="l", - }, - [0x12165]={ - category="lo", - direction="l", - }, - [0x12166]={ - category="lo", - direction="l", - }, - [0x12167]={ - category="lo", - direction="l", - }, - [0x12168]={ - category="lo", - direction="l", - }, - [0x12169]={ - category="lo", - direction="l", - }, - [0x1216A]={ - category="lo", - direction="l", - }, - [0x1216B]={ - category="lo", - direction="l", - }, - [0x1216C]={ - category="lo", - direction="l", - }, - [0x1216D]={ - category="lo", - direction="l", - }, - [0x1216E]={ - category="lo", - direction="l", - }, - [0x1216F]={ - category="lo", - direction="l", - }, - [0x12170]={ - category="lo", - direction="l", - }, - [0x12171]={ - category="lo", - direction="l", - }, - [0x12172]={ - category="lo", - direction="l", - }, - [0x12173]={ - category="lo", - direction="l", - }, - [0x12174]={ - category="lo", - direction="l", - }, - [0x12175]={ - category="lo", - direction="l", - }, - [0x12176]={ - category="lo", - direction="l", - }, - [0x12177]={ - category="lo", - direction="l", - }, - [0x12178]={ - category="lo", - direction="l", - }, - [0x12179]={ - category="lo", - direction="l", - }, - [0x1217A]={ - category="lo", - direction="l", - }, - [0x1217B]={ - category="lo", - direction="l", - }, - [0x1217C]={ - category="lo", - direction="l", - }, - [0x1217D]={ - category="lo", - direction="l", - }, - [0x1217E]={ - category="lo", - direction="l", - }, - [0x1217F]={ - category="lo", - direction="l", - }, - [0x12180]={ - category="lo", - direction="l", - }, - [0x12181]={ - category="lo", - direction="l", - }, - [0x12182]={ - category="lo", - direction="l", - }, - [0x12183]={ - category="lo", - direction="l", - }, - [0x12184]={ - category="lo", - direction="l", - }, - [0x12185]={ - category="lo", - direction="l", - }, - [0x12186]={ - category="lo", - direction="l", - }, - [0x12187]={ - category="lo", - direction="l", - }, - [0x12188]={ - category="lo", - direction="l", - }, - [0x12189]={ - category="lo", - direction="l", - }, - [0x1218A]={ - category="lo", - direction="l", - }, - [0x1218B]={ - category="lo", - direction="l", - }, - [0x1218C]={ - category="lo", - direction="l", - }, - [0x1218D]={ - category="lo", - direction="l", - }, - [0x1218E]={ - category="lo", - direction="l", - }, - [0x1218F]={ - category="lo", - direction="l", - }, - [0x12190]={ - category="lo", - direction="l", - }, - [0x12191]={ - category="lo", - direction="l", - }, - [0x12192]={ - category="lo", - direction="l", - }, - [0x12193]={ - category="lo", - direction="l", - }, - [0x12194]={ - category="lo", - direction="l", - }, - [0x12195]={ - category="lo", - direction="l", - }, - [0x12196]={ - category="lo", - direction="l", - }, - [0x12197]={ - category="lo", - direction="l", - }, - [0x12198]={ - category="lo", - direction="l", - }, - [0x12199]={ - category="lo", - direction="l", - }, - [0x1219A]={ - category="lo", - direction="l", - }, - [0x1219B]={ - category="lo", - direction="l", - }, - [0x1219C]={ - category="lo", - direction="l", - }, - [0x1219D]={ - category="lo", - direction="l", - }, - [0x1219E]={ - category="lo", - direction="l", - }, - [0x1219F]={ - category="lo", - direction="l", - }, - [0x121A0]={ - category="lo", - direction="l", - }, - [0x121A1]={ - category="lo", - direction="l", - }, - [0x121A2]={ - category="lo", - direction="l", - }, - [0x121A3]={ - category="lo", - direction="l", - }, - [0x121A4]={ - category="lo", - direction="l", - }, - [0x121A5]={ - category="lo", - direction="l", - }, - [0x121A6]={ - category="lo", - direction="l", - }, - [0x121A7]={ - category="lo", - direction="l", - }, - [0x121A8]={ - category="lo", - direction="l", - }, - [0x121A9]={ - category="lo", - direction="l", - }, - [0x121AA]={ - category="lo", - direction="l", - }, - [0x121AB]={ - category="lo", - direction="l", - }, - [0x121AC]={ - category="lo", - direction="l", - }, - [0x121AD]={ - category="lo", - direction="l", - }, - [0x121AE]={ - category="lo", - direction="l", - }, - [0x121AF]={ - category="lo", - direction="l", - }, - [0x121B0]={ - category="lo", - direction="l", - }, - [0x121B1]={ - category="lo", - direction="l", - }, - [0x121B2]={ - category="lo", - direction="l", - }, - [0x121B3]={ - category="lo", - direction="l", - }, - [0x121B4]={ - category="lo", - direction="l", - }, - [0x121B5]={ - category="lo", - direction="l", - }, - [0x121B6]={ - category="lo", - direction="l", - }, - [0x121B7]={ - category="lo", - direction="l", - }, - [0x121B8]={ - category="lo", - direction="l", - }, - [0x121B9]={ - category="lo", - direction="l", - }, - [0x121BA]={ - category="lo", - direction="l", - }, - [0x121BB]={ - category="lo", - direction="l", - }, - [0x121BC]={ - category="lo", - direction="l", - }, - [0x121BD]={ - category="lo", - direction="l", - }, - [0x121BE]={ - category="lo", - direction="l", - }, - [0x121BF]={ - category="lo", - direction="l", - }, - [0x121C0]={ - category="lo", - direction="l", - }, - [0x121C1]={ - category="lo", - direction="l", - }, - [0x121C2]={ - category="lo", - direction="l", - }, - [0x121C3]={ - category="lo", - direction="l", - }, - [0x121C4]={ - category="lo", - direction="l", - }, - [0x121C5]={ - category="lo", - direction="l", - }, - [0x121C6]={ - category="lo", - direction="l", - }, - [0x121C7]={ - category="lo", - direction="l", - }, - [0x121C8]={ - category="lo", - direction="l", - }, - [0x121C9]={ - category="lo", - direction="l", - }, - [0x121CA]={ - category="lo", - direction="l", - }, - [0x121CB]={ - category="lo", - direction="l", - }, - [0x121CC]={ - category="lo", - direction="l", - }, - [0x121CD]={ - category="lo", - direction="l", - }, - [0x121CE]={ - category="lo", - direction="l", - }, - [0x121CF]={ - category="lo", - direction="l", - }, - [0x121D0]={ - category="lo", - direction="l", - }, - [0x121D1]={ - category="lo", - direction="l", - }, - [0x121D2]={ - category="lo", - direction="l", - }, - [0x121D3]={ - category="lo", - direction="l", - }, - [0x121D4]={ - category="lo", - direction="l", - }, - [0x121D5]={ - category="lo", - direction="l", - }, - [0x121D6]={ - category="lo", - direction="l", - }, - [0x121D7]={ - category="lo", - direction="l", - }, - [0x121D8]={ - category="lo", - direction="l", - }, - [0x121D9]={ - category="lo", - direction="l", - }, - [0x121DA]={ - category="lo", - direction="l", - }, - [0x121DB]={ - category="lo", - direction="l", - }, - [0x121DC]={ - category="lo", - direction="l", - }, - [0x121DD]={ - category="lo", - direction="l", - }, - [0x121DE]={ - category="lo", - direction="l", - }, - [0x121DF]={ - category="lo", - direction="l", - }, - [0x121E0]={ - category="lo", - direction="l", - }, - [0x121E1]={ - category="lo", - direction="l", - }, - [0x121E2]={ - category="lo", - direction="l", - }, - [0x121E3]={ - category="lo", - direction="l", - }, - [0x121E4]={ - category="lo", - direction="l", - }, - [0x121E5]={ - category="lo", - direction="l", - }, - [0x121E6]={ - category="lo", - direction="l", - }, - [0x121E7]={ - category="lo", - direction="l", - }, - [0x121E8]={ - category="lo", - direction="l", - }, - [0x121E9]={ - category="lo", - direction="l", - }, - [0x121EA]={ - category="lo", - direction="l", - }, - [0x121EB]={ - category="lo", - direction="l", - }, - [0x121EC]={ - category="lo", - direction="l", - }, - [0x121ED]={ - category="lo", - direction="l", - }, - [0x121EE]={ - category="lo", - direction="l", - }, - [0x121EF]={ - category="lo", - direction="l", - }, - [0x121F0]={ - category="lo", - direction="l", - }, - [0x121F1]={ - category="lo", - direction="l", - }, - [0x121F2]={ - category="lo", - direction="l", - }, - [0x121F3]={ - category="lo", - direction="l", - }, - [0x121F4]={ - category="lo", - direction="l", - }, - [0x121F5]={ - category="lo", - direction="l", - }, - [0x121F6]={ - category="lo", - direction="l", - }, - [0x121F7]={ - category="lo", - direction="l", - }, - [0x121F8]={ - category="lo", - direction="l", - }, - [0x121F9]={ - category="lo", - direction="l", - }, - [0x121FA]={ - category="lo", - direction="l", - }, - [0x121FB]={ - category="lo", - direction="l", - }, - [0x121FC]={ - category="lo", - direction="l", - }, - [0x121FD]={ - category="lo", - direction="l", - }, - [0x121FE]={ - category="lo", - direction="l", - }, - [0x121FF]={ - category="lo", - direction="l", - }, - [0x12200]={ - category="lo", - direction="l", - }, - [0x12201]={ - category="lo", - direction="l", - }, - [0x12202]={ - category="lo", - direction="l", - }, - [0x12203]={ - category="lo", - direction="l", - }, - [0x12204]={ - category="lo", - direction="l", - }, - [0x12205]={ - category="lo", - direction="l", - }, - [0x12206]={ - category="lo", - direction="l", - }, - [0x12207]={ - category="lo", - direction="l", - }, - [0x12208]={ - category="lo", - direction="l", - }, - [0x12209]={ - category="lo", - direction="l", - }, - [0x1220A]={ - category="lo", - direction="l", - }, - [0x1220B]={ - category="lo", - direction="l", - }, - [0x1220C]={ - category="lo", - direction="l", - }, - [0x1220D]={ - category="lo", - direction="l", - }, - [0x1220E]={ - category="lo", - direction="l", - }, - [0x1220F]={ - category="lo", - direction="l", - }, - [0x12210]={ - category="lo", - direction="l", - }, - [0x12211]={ - category="lo", - direction="l", - }, - [0x12212]={ - category="lo", - direction="l", - }, - [0x12213]={ - category="lo", - direction="l", - }, - [0x12214]={ - category="lo", - direction="l", - }, - [0x12215]={ - category="lo", - direction="l", - }, - [0x12216]={ - category="lo", - direction="l", - }, - [0x12217]={ - category="lo", - direction="l", - }, - [0x12218]={ - category="lo", - direction="l", - }, - [0x12219]={ - category="lo", - direction="l", - }, - [0x1221A]={ - category="lo", - direction="l", - }, - [0x1221B]={ - category="lo", - direction="l", - }, - [0x1221C]={ - category="lo", - direction="l", - }, - [0x1221D]={ - category="lo", - direction="l", - }, - [0x1221E]={ - category="lo", - direction="l", - }, - [0x1221F]={ - category="lo", - direction="l", - }, - [0x12220]={ - category="lo", - direction="l", - }, - [0x12221]={ - category="lo", - direction="l", - }, - [0x12222]={ - category="lo", - direction="l", - }, - [0x12223]={ - category="lo", - direction="l", - }, - [0x12224]={ - category="lo", - direction="l", - }, - [0x12225]={ - category="lo", - direction="l", - }, - [0x12226]={ - category="lo", - direction="l", - }, - [0x12227]={ - category="lo", - direction="l", - }, - [0x12228]={ - category="lo", - direction="l", - }, - [0x12229]={ - category="lo", - direction="l", - }, - [0x1222A]={ - category="lo", - direction="l", - }, - [0x1222B]={ - category="lo", - direction="l", - }, - [0x1222C]={ - category="lo", - direction="l", - }, - [0x1222D]={ - category="lo", - direction="l", - }, - [0x1222E]={ - category="lo", - direction="l", - }, - [0x1222F]={ - category="lo", - direction="l", - }, - [0x12230]={ - category="lo", - direction="l", - }, - [0x12231]={ - category="lo", - direction="l", - }, - [0x12232]={ - category="lo", - direction="l", - }, - [0x12233]={ - category="lo", - direction="l", - }, - [0x12234]={ - category="lo", - direction="l", - }, - [0x12235]={ - category="lo", - direction="l", - }, - [0x12236]={ - category="lo", - direction="l", - }, - [0x12237]={ - category="lo", - direction="l", - }, - [0x12238]={ - category="lo", - direction="l", - }, - [0x12239]={ - category="lo", - direction="l", - }, - [0x1223A]={ - category="lo", - direction="l", - }, - [0x1223B]={ - category="lo", - direction="l", - }, - [0x1223C]={ - category="lo", - direction="l", - }, - [0x1223D]={ - category="lo", - direction="l", - }, - [0x1223E]={ - category="lo", - direction="l", - }, - [0x1223F]={ - category="lo", - direction="l", - }, - [0x12240]={ - category="lo", - direction="l", - }, - [0x12241]={ - category="lo", - direction="l", - }, - [0x12242]={ - category="lo", - direction="l", - }, - [0x12243]={ - category="lo", - direction="l", - }, - [0x12244]={ - category="lo", - direction="l", - }, - [0x12245]={ - category="lo", - direction="l", - }, - [0x12246]={ - category="lo", - direction="l", - }, - [0x12247]={ - category="lo", - direction="l", - }, - [0x12248]={ - category="lo", - direction="l", - }, - [0x12249]={ - category="lo", - direction="l", - }, - [0x1224A]={ - category="lo", - direction="l", - }, - [0x1224B]={ - category="lo", - direction="l", - }, - [0x1224C]={ - category="lo", - direction="l", - }, - [0x1224D]={ - category="lo", - direction="l", - }, - [0x1224E]={ - category="lo", - direction="l", - }, - [0x1224F]={ - category="lo", - direction="l", - }, - [0x12250]={ - category="lo", - direction="l", - }, - [0x12251]={ - category="lo", - direction="l", - }, - [0x12252]={ - category="lo", - direction="l", - }, - [0x12253]={ - category="lo", - direction="l", - }, - [0x12254]={ - category="lo", - direction="l", - }, - [0x12255]={ - category="lo", - direction="l", - }, - [0x12256]={ - category="lo", - direction="l", - }, - [0x12257]={ - category="lo", - direction="l", - }, - [0x12258]={ - category="lo", - direction="l", - }, - [0x12259]={ - category="lo", - direction="l", - }, - [0x1225A]={ - category="lo", - direction="l", - }, - [0x1225B]={ - category="lo", - direction="l", - }, - [0x1225C]={ - category="lo", - direction="l", - }, - [0x1225D]={ - category="lo", - direction="l", - }, - [0x1225E]={ - category="lo", - direction="l", - }, - [0x1225F]={ - category="lo", - direction="l", - }, - [0x12260]={ - category="lo", - direction="l", - }, - [0x12261]={ - category="lo", - direction="l", - }, - [0x12262]={ - category="lo", - direction="l", - }, - [0x12263]={ - category="lo", - direction="l", - }, - [0x12264]={ - category="lo", - direction="l", - }, - [0x12265]={ - category="lo", - direction="l", - }, - [0x12266]={ - category="lo", - direction="l", - }, - [0x12267]={ - category="lo", - direction="l", - }, - [0x12268]={ - category="lo", - direction="l", - }, - [0x12269]={ - category="lo", - direction="l", - }, - [0x1226A]={ - category="lo", - direction="l", - }, - [0x1226B]={ - category="lo", - direction="l", - }, - [0x1226C]={ - category="lo", - direction="l", - }, - [0x1226D]={ - category="lo", - direction="l", - }, - [0x1226E]={ - category="lo", - direction="l", - }, - [0x1226F]={ - category="lo", - direction="l", - }, - [0x12270]={ - category="lo", - direction="l", - }, - [0x12271]={ - category="lo", - direction="l", - }, - [0x12272]={ - category="lo", - direction="l", - }, - [0x12273]={ - category="lo", - direction="l", - }, - [0x12274]={ - category="lo", - direction="l", - }, - [0x12275]={ - category="lo", - direction="l", - }, - [0x12276]={ - category="lo", - direction="l", - }, - [0x12277]={ - category="lo", - direction="l", - }, - [0x12278]={ - category="lo", - direction="l", - }, - [0x12279]={ - category="lo", - direction="l", - }, - [0x1227A]={ - category="lo", - direction="l", - }, - [0x1227B]={ - category="lo", - direction="l", - }, - [0x1227C]={ - category="lo", - direction="l", - }, - [0x1227D]={ - category="lo", - direction="l", - }, - [0x1227E]={ - category="lo", - direction="l", - }, - [0x1227F]={ - category="lo", - direction="l", - }, - [0x12280]={ - category="lo", - direction="l", - }, - [0x12281]={ - category="lo", - direction="l", - }, - [0x12282]={ - category="lo", - direction="l", - }, - [0x12283]={ - category="lo", - direction="l", - }, - [0x12284]={ - category="lo", - direction="l", - }, - [0x12285]={ - category="lo", - direction="l", - }, - [0x12286]={ - category="lo", - direction="l", - }, - [0x12287]={ - category="lo", - direction="l", - }, - [0x12288]={ - category="lo", - direction="l", - }, - [0x12289]={ - category="lo", - direction="l", - }, - [0x1228A]={ - category="lo", - direction="l", - }, - [0x1228B]={ - category="lo", - direction="l", - }, - [0x1228C]={ - category="lo", - direction="l", - }, - [0x1228D]={ - category="lo", - direction="l", - }, - [0x1228E]={ - category="lo", - direction="l", - }, - [0x1228F]={ - category="lo", - direction="l", - }, - [0x12290]={ - category="lo", - direction="l", - }, - [0x12291]={ - category="lo", - direction="l", - }, - [0x12292]={ - category="lo", - direction="l", - }, - [0x12293]={ - category="lo", - direction="l", - }, - [0x12294]={ - category="lo", - direction="l", - }, - [0x12295]={ - category="lo", - direction="l", - }, - [0x12296]={ - category="lo", - direction="l", - }, - [0x12297]={ - category="lo", - direction="l", - }, - [0x12298]={ - category="lo", - direction="l", - }, - [0x12299]={ - category="lo", - direction="l", - }, - [0x1229A]={ - category="lo", - direction="l", - }, - [0x1229B]={ - category="lo", - direction="l", - }, - [0x1229C]={ - category="lo", - direction="l", - }, - [0x1229D]={ - category="lo", - direction="l", - }, - [0x1229E]={ - category="lo", - direction="l", - }, - [0x1229F]={ - category="lo", - direction="l", - }, - [0x122A0]={ - category="lo", - direction="l", - }, - [0x122A1]={ - category="lo", - direction="l", - }, - [0x122A2]={ - category="lo", - direction="l", - }, - [0x122A3]={ - category="lo", - direction="l", - }, - [0x122A4]={ - category="lo", - direction="l", - }, - [0x122A5]={ - category="lo", - direction="l", - }, - [0x122A6]={ - category="lo", - direction="l", - }, - [0x122A7]={ - category="lo", - direction="l", - }, - [0x122A8]={ - category="lo", - direction="l", - }, - [0x122A9]={ - category="lo", - direction="l", - }, - [0x122AA]={ - category="lo", - direction="l", - }, - [0x122AB]={ - category="lo", - direction="l", - }, - [0x122AC]={ - category="lo", - direction="l", - }, - [0x122AD]={ - category="lo", - direction="l", - }, - [0x122AE]={ - category="lo", - direction="l", - }, - [0x122AF]={ - category="lo", - direction="l", - }, - [0x122B0]={ - category="lo", - direction="l", - }, - [0x122B1]={ - category="lo", - direction="l", - }, - [0x122B2]={ - category="lo", - direction="l", - }, - [0x122B3]={ - category="lo", - direction="l", - }, - [0x122B4]={ - category="lo", - direction="l", - }, - [0x122B5]={ - category="lo", - direction="l", - }, - [0x122B6]={ - category="lo", - direction="l", - }, - [0x122B7]={ - category="lo", - direction="l", - }, - [0x122B8]={ - category="lo", - direction="l", - }, - [0x122B9]={ - category="lo", - direction="l", - }, - [0x122BA]={ - category="lo", - direction="l", - }, - [0x122BB]={ - category="lo", - direction="l", - }, - [0x122BC]={ - category="lo", - direction="l", - }, - [0x122BD]={ - category="lo", - direction="l", - }, - [0x122BE]={ - category="lo", - direction="l", - }, - [0x122BF]={ - category="lo", - direction="l", - }, - [0x122C0]={ - category="lo", - direction="l", - }, - [0x122C1]={ - category="lo", - direction="l", - }, - [0x122C2]={ - category="lo", - direction="l", - }, - [0x122C3]={ - category="lo", - direction="l", - }, - [0x122C4]={ - category="lo", - direction="l", - }, - [0x122C5]={ - category="lo", - direction="l", - }, - [0x122C6]={ - category="lo", - direction="l", - }, - [0x122C7]={ - category="lo", - direction="l", - }, - [0x122C8]={ - category="lo", - direction="l", - }, - [0x122C9]={ - category="lo", - direction="l", - }, - [0x122CA]={ - category="lo", - direction="l", - }, - [0x122CB]={ - category="lo", - direction="l", - }, - [0x122CC]={ - category="lo", - direction="l", - }, - [0x122CD]={ - category="lo", - direction="l", - }, - [0x122CE]={ - category="lo", - direction="l", - }, - [0x122CF]={ - category="lo", - direction="l", - }, - [0x122D0]={ - category="lo", - direction="l", - }, - [0x122D1]={ - category="lo", - direction="l", - }, - [0x122D2]={ - category="lo", - direction="l", - }, - [0x122D3]={ - category="lo", - direction="l", - }, - [0x122D4]={ - category="lo", - direction="l", - }, - [0x122D5]={ - category="lo", - direction="l", - }, - [0x122D6]={ - category="lo", - direction="l", - }, - [0x122D7]={ - category="lo", - direction="l", - }, - [0x122D8]={ - category="lo", - direction="l", - }, - [0x122D9]={ - category="lo", - direction="l", - }, - [0x122DA]={ - category="lo", - direction="l", - }, - [0x122DB]={ - category="lo", - direction="l", - }, - [0x122DC]={ - category="lo", - direction="l", - }, - [0x122DD]={ - category="lo", - direction="l", - }, - [0x122DE]={ - category="lo", - direction="l", - }, - [0x122DF]={ - category="lo", - direction="l", - }, - [0x122E0]={ - category="lo", - direction="l", - }, - [0x122E1]={ - category="lo", - direction="l", - }, - [0x122E2]={ - category="lo", - direction="l", - }, - [0x122E3]={ - category="lo", - direction="l", - }, - [0x122E4]={ - category="lo", - direction="l", - }, - [0x122E5]={ - category="lo", - direction="l", - }, - [0x122E6]={ - category="lo", - direction="l", - }, - [0x122E7]={ - category="lo", - direction="l", - }, - [0x122E8]={ - category="lo", - direction="l", - }, - [0x122E9]={ - category="lo", - direction="l", - }, - [0x122EA]={ - category="lo", - direction="l", - }, - [0x122EB]={ - category="lo", - direction="l", - }, - [0x122EC]={ - category="lo", - direction="l", - }, - [0x122ED]={ - category="lo", - direction="l", - }, - [0x122EE]={ - category="lo", - direction="l", - }, - [0x122EF]={ - category="lo", - direction="l", - }, - [0x122F0]={ - category="lo", - direction="l", - }, - [0x122F1]={ - category="lo", - direction="l", - }, - [0x122F2]={ - category="lo", - direction="l", - }, - [0x122F3]={ - category="lo", - direction="l", - }, - [0x122F4]={ - category="lo", - direction="l", - }, - [0x122F5]={ - category="lo", - direction="l", - }, - [0x122F6]={ - category="lo", - direction="l", - }, - [0x122F7]={ - category="lo", - direction="l", - }, - [0x122F8]={ - category="lo", - direction="l", - }, - [0x122F9]={ - category="lo", - direction="l", - }, - [0x122FA]={ - category="lo", - direction="l", - }, - [0x122FB]={ - category="lo", - direction="l", - }, - [0x122FC]={ - category="lo", - direction="l", - }, - [0x122FD]={ - category="lo", - direction="l", - }, - [0x122FE]={ - category="lo", - direction="l", - }, - [0x122FF]={ - category="lo", - direction="l", - }, - [0x12300]={ - category="lo", - direction="l", - }, - [0x12301]={ - category="lo", - direction="l", - }, - [0x12302]={ - category="lo", - direction="l", - }, - [0x12303]={ - category="lo", - direction="l", - }, - [0x12304]={ - category="lo", - direction="l", - }, - [0x12305]={ - category="lo", - direction="l", - }, - [0x12306]={ - category="lo", - direction="l", - }, - [0x12307]={ - category="lo", - direction="l", - }, - [0x12308]={ - category="lo", - direction="l", - }, - [0x12309]={ - category="lo", - direction="l", - }, - [0x1230A]={ - category="lo", - direction="l", - }, - [0x1230B]={ - category="lo", - direction="l", - }, - [0x1230C]={ - category="lo", - direction="l", - }, - [0x1230D]={ - category="lo", - direction="l", - }, - [0x1230E]={ - category="lo", - direction="l", - }, - [0x1230F]={ - category="lo", - direction="l", - }, - [0x12310]={ - category="lo", - direction="l", - }, - [0x12311]={ - category="lo", - direction="l", - }, - [0x12312]={ - category="lo", - direction="l", - }, - [0x12313]={ - category="lo", - direction="l", - }, - [0x12314]={ - category="lo", - direction="l", - }, - [0x12315]={ - category="lo", - direction="l", - }, - [0x12316]={ - category="lo", - direction="l", - }, - [0x12317]={ - category="lo", - direction="l", - }, - [0x12318]={ - category="lo", - direction="l", - }, - [0x12319]={ - category="lo", - direction="l", - }, - [0x1231A]={ - category="lo", - direction="l", - }, - [0x1231B]={ - category="lo", - direction="l", - }, - [0x1231C]={ - category="lo", - direction="l", - }, - [0x1231D]={ - category="lo", - direction="l", - }, - [0x1231E]={ - category="lo", - direction="l", - }, - [0x1231F]={ - category="lo", - direction="l", - }, - [0x12320]={ - category="lo", - direction="l", - }, - [0x12321]={ - category="lo", - direction="l", - }, - [0x12322]={ - category="lo", - direction="l", - }, - [0x12323]={ - category="lo", - direction="l", - }, - [0x12324]={ - category="lo", - direction="l", - }, - [0x12325]={ - category="lo", - direction="l", - }, - [0x12326]={ - category="lo", - direction="l", - }, - [0x12327]={ - category="lo", - direction="l", - }, - [0x12328]={ - category="lo", - direction="l", - }, - [0x12329]={ - category="lo", - direction="l", - }, - [0x1232A]={ - category="lo", - direction="l", - }, - [0x1232B]={ - category="lo", - direction="l", - }, - [0x1232C]={ - category="lo", - direction="l", - }, - [0x1232D]={ - category="lo", - direction="l", - }, - [0x1232E]={ - category="lo", - direction="l", - }, - [0x1232F]={ - category="lo", - direction="l", - }, - [0x12330]={ - category="lo", - direction="l", - }, - [0x12331]={ - category="lo", - direction="l", - }, - [0x12332]={ - category="lo", - direction="l", - }, - [0x12333]={ - category="lo", - direction="l", - }, - [0x12334]={ - category="lo", - direction="l", - }, - [0x12335]={ - category="lo", - direction="l", - }, - [0x12336]={ - category="lo", - direction="l", - }, - [0x12337]={ - category="lo", - direction="l", - }, - [0x12338]={ - category="lo", - direction="l", - }, - [0x12339]={ - category="lo", - direction="l", - }, - [0x1233A]={ - category="lo", - direction="l", - }, - [0x1233B]={ - category="lo", - direction="l", - }, - [0x1233C]={ - category="lo", - direction="l", - }, - [0x1233D]={ - category="lo", - direction="l", - }, - [0x1233E]={ - category="lo", - direction="l", - }, - [0x1233F]={ - category="lo", - direction="l", - }, - [0x12340]={ - category="lo", - direction="l", - }, - [0x12341]={ - category="lo", - direction="l", - }, - [0x12342]={ - category="lo", - direction="l", - }, - [0x12343]={ - category="lo", - direction="l", - }, - [0x12344]={ - category="lo", - direction="l", - }, - [0x12345]={ - category="lo", - direction="l", - }, - [0x12346]={ - category="lo", - direction="l", - }, - [0x12347]={ - category="lo", - direction="l", - }, - [0x12348]={ - category="lo", - direction="l", - }, - [0x12349]={ - category="lo", - direction="l", - }, - [0x1234A]={ - category="lo", - direction="l", - }, - [0x1234B]={ - category="lo", - direction="l", - }, - [0x1234C]={ - category="lo", - direction="l", - }, - [0x1234D]={ - category="lo", - direction="l", - }, - [0x1234E]={ - category="lo", - direction="l", - }, - [0x1234F]={ - category="lo", - direction="l", - }, - [0x12350]={ - category="lo", - direction="l", - }, - [0x12351]={ - category="lo", - direction="l", - }, - [0x12352]={ - category="lo", - direction="l", - }, - [0x12353]={ - category="lo", - direction="l", - }, - [0x12354]={ - category="lo", - direction="l", - }, - [0x12355]={ - category="lo", - direction="l", - }, - [0x12356]={ - category="lo", - direction="l", - }, - [0x12357]={ - category="lo", - direction="l", - }, - [0x12358]={ - category="lo", - direction="l", - }, - [0x12359]={ - category="lo", - direction="l", - }, - [0x1235A]={ - category="lo", - direction="l", - }, - [0x1235B]={ - category="lo", - direction="l", - }, - [0x1235C]={ - category="lo", - direction="l", - }, - [0x1235D]={ - category="lo", - direction="l", - }, - [0x1235E]={ - category="lo", - direction="l", - }, - [0x1235F]={ - category="lo", - direction="l", - }, - [0x12360]={ - category="lo", - direction="l", - }, - [0x12361]={ - category="lo", - direction="l", - }, - [0x12362]={ - category="lo", - direction="l", - }, - [0x12363]={ - category="lo", - direction="l", - }, - [0x12364]={ - category="lo", - direction="l", - }, - [0x12365]={ - category="lo", - direction="l", - }, - [0x12366]={ - category="lo", - direction="l", - }, - [0x12367]={ - category="lo", - direction="l", - }, - [0x12368]={ - category="lo", - direction="l", - }, - [0x12369]={ - category="lo", - direction="l", - }, - [0x1236A]={ - category="lo", - direction="l", - }, - [0x1236B]={ - category="lo", - direction="l", - }, - [0x1236C]={ - category="lo", - direction="l", - }, - [0x1236D]={ - category="lo", - direction="l", - }, - [0x1236E]={ - category="lo", - direction="l", - }, - [0x1236F]={ - category="lo", - direction="l", - }, - [0x12370]={ - category="lo", - direction="l", - }, - [0x12371]={ - category="lo", - direction="l", - }, - [0x12372]={ - category="lo", - direction="l", - }, - [0x12373]={ - category="lo", - direction="l", - }, - [0x12374]={ - category="lo", - direction="l", - }, - [0x12375]={ - category="lo", - direction="l", - }, - [0x12376]={ - category="lo", - direction="l", - }, - [0x12377]={ - category="lo", - direction="l", - }, - [0x12378]={ - category="lo", - direction="l", - }, - [0x12379]={ - category="lo", - direction="l", - }, - [0x1237A]={ - category="lo", - direction="l", - }, - [0x1237B]={ - category="lo", - direction="l", - }, - [0x1237C]={ - category="lo", - direction="l", - }, - [0x1237D]={ - category="lo", - direction="l", - }, - [0x1237E]={ - category="lo", - direction="l", - }, - [0x1237F]={ - category="lo", - direction="l", - }, - [0x12380]={ - category="lo", - direction="l", - }, - [0x12381]={ - category="lo", - direction="l", - }, - [0x12382]={ - category="lo", - direction="l", - }, - [0x12383]={ - category="lo", - direction="l", - }, - [0x12384]={ - category="lo", - direction="l", - }, - [0x12385]={ - category="lo", - direction="l", - }, - [0x12386]={ - category="lo", - direction="l", - }, - [0x12387]={ - category="lo", - direction="l", - }, - [0x12388]={ - category="lo", - direction="l", - }, - [0x12389]={ - category="lo", - direction="l", - }, - [0x1238A]={ - category="lo", - direction="l", - }, - [0x1238B]={ - category="lo", - direction="l", - }, - [0x1238C]={ - category="lo", - direction="l", - }, - [0x1238D]={ - category="lo", - direction="l", - }, - [0x1238E]={ - category="lo", - direction="l", - }, - [0x1238F]={ - category="lo", - direction="l", - }, - [0x12390]={ - category="lo", - direction="l", - }, - [0x12391]={ - category="lo", - direction="l", - }, - [0x12392]={ - category="lo", - direction="l", - }, - [0x12393]={ - category="lo", - direction="l", - }, - [0x12394]={ - category="lo", - direction="l", - }, - [0x12395]={ - category="lo", - direction="l", - }, - [0x12396]={ - category="lo", - direction="l", - }, - [0x12397]={ - category="lo", - direction="l", - }, - [0x12398]={ - category="lo", - direction="l", - }, - [0x12399]={ - category="lo", - direction="l", - }, - [0x12400]={ - category="nl", - direction="l", - }, - [0x12401]={ - category="nl", - direction="l", - }, - [0x12402]={ - category="nl", - direction="l", - }, - [0x12403]={ - category="nl", - direction="l", - }, - [0x12404]={ - category="nl", - direction="l", - }, - [0x12405]={ - category="nl", - direction="l", - }, - [0x12406]={ - category="nl", - direction="l", - }, - [0x12407]={ - category="nl", - direction="l", - }, - [0x12408]={ - category="nl", - direction="l", - }, - [0x12409]={ - category="nl", - direction="l", - }, - [0x1240A]={ - category="nl", - direction="l", - }, - [0x1240B]={ - category="nl", - direction="l", - }, - [0x1240C]={ - category="nl", - direction="l", - }, - [0x1240D]={ - category="nl", - direction="l", - }, - [0x1240E]={ - category="nl", - direction="l", - }, - [0x1240F]={ - category="nl", - direction="l", - }, - [0x12410]={ - category="nl", - direction="l", - }, - [0x12411]={ - category="nl", - direction="l", - }, - [0x12412]={ - category="nl", - direction="l", - }, - [0x12413]={ - category="nl", - direction="l", - }, - [0x12414]={ - category="nl", - direction="l", - }, - [0x12415]={ - category="nl", - direction="l", - }, - [0x12416]={ - category="nl", - direction="l", - }, - [0x12417]={ - category="nl", - direction="l", - }, - [0x12418]={ - category="nl", - direction="l", - }, - [0x12419]={ - category="nl", - direction="l", - }, - [0x1241A]={ - category="nl", - direction="l", - }, - [0x1241B]={ - category="nl", - direction="l", - }, - [0x1241C]={ - category="nl", - direction="l", - }, - [0x1241D]={ - category="nl", - direction="l", - }, - [0x1241E]={ - category="nl", - direction="l", - }, - [0x1241F]={ - category="nl", - direction="l", - }, - [0x12420]={ - category="nl", - direction="l", - }, - [0x12421]={ - category="nl", - direction="l", - }, - [0x12422]={ - category="nl", - direction="l", - }, - [0x12423]={ - category="nl", - direction="l", - }, - [0x12424]={ - category="nl", - direction="l", - }, - [0x12425]={ - category="nl", - direction="l", - }, - [0x12426]={ - category="nl", - direction="l", - }, - [0x12427]={ - category="nl", - direction="l", - }, - [0x12428]={ - category="nl", - direction="l", - }, - [0x12429]={ - category="nl", - direction="l", - }, - [0x1242A]={ - category="nl", - direction="l", - }, - [0x1242B]={ - category="nl", - direction="l", - }, - [0x1242C]={ - category="nl", - direction="l", - }, - [0x1242D]={ - category="nl", - direction="l", - }, - [0x1242E]={ - category="nl", - direction="l", - }, - [0x1242F]={ - category="nl", - direction="l", - }, - [0x12430]={ - category="nl", - direction="l", - }, - [0x12431]={ - category="nl", - direction="l", - }, - [0x12432]={ - category="nl", - direction="l", - }, - [0x12433]={ - category="nl", - direction="l", - }, - [0x12434]={ - category="nl", - direction="l", - }, - [0x12435]={ - category="nl", - direction="l", - }, - [0x12436]={ - category="nl", - direction="l", - }, - [0x12437]={ - category="nl", - direction="l", - }, - [0x12438]={ - category="nl", - direction="l", - }, - [0x12439]={ - category="nl", - direction="l", - }, - [0x1243A]={ - category="nl", - direction="l", - }, - [0x1243B]={ - category="nl", - direction="l", - }, - [0x1243C]={ - category="nl", - direction="l", - }, - [0x1243D]={ - category="nl", - direction="l", - }, - [0x1243E]={ - category="nl", - direction="l", - }, - [0x1243F]={ - category="nl", - direction="l", - }, - [0x12440]={ - category="nl", - direction="l", - }, - [0x12441]={ - category="nl", - direction="l", - }, - [0x12442]={ - category="nl", - direction="l", - }, - [0x12443]={ - category="nl", - direction="l", - }, - [0x12444]={ - category="nl", - direction="l", - }, - [0x12445]={ - category="nl", - direction="l", - }, - [0x12446]={ - category="nl", - direction="l", - }, - [0x12447]={ - category="nl", - direction="l", - }, - [0x12448]={ - category="nl", - direction="l", - }, - [0x12449]={ - category="nl", - direction="l", - }, - [0x1244A]={ - category="nl", - direction="l", - }, - [0x1244B]={ - category="nl", - direction="l", - }, - [0x1244C]={ - category="nl", - direction="l", - }, - [0x1244D]={ - category="nl", - direction="l", - }, - [0x1244E]={ - category="nl", - direction="l", - }, - [0x1244F]={ - category="nl", - direction="l", - }, - [0x12450]={ - category="nl", - direction="l", - }, - [0x12451]={ - category="nl", - direction="l", - }, - [0x12452]={ - category="nl", - direction="l", - }, - [0x12453]={ - category="nl", - direction="l", - }, - [0x12454]={ - category="nl", - direction="l", - }, - [0x12455]={ - category="nl", - direction="l", - }, - [0x12456]={ - category="nl", - direction="l", - }, - [0x12457]={ - category="nl", - direction="l", - }, - [0x12458]={ - category="nl", - direction="l", - }, - [0x12459]={ - category="nl", - direction="l", - }, - [0x1245A]={ - category="nl", - direction="l", - }, - [0x1245B]={ - category="nl", - direction="l", - }, - [0x1245C]={ - category="nl", - direction="l", - }, - [0x1245D]={ - category="nl", - direction="l", - }, - [0x1245E]={ - category="nl", - direction="l", - }, - [0x1245F]={ - category="nl", - direction="l", - }, - [0x12460]={ - category="nl", - direction="l", - }, - [0x12461]={ - category="nl", - direction="l", - }, - [0x12462]={ - category="nl", - direction="l", - }, - [0x12463]={ - category="nl", - direction="l", - }, - [0x12464]={ - category="nl", - direction="l", - }, - [0x12465]={ - category="nl", - direction="l", - }, - [0x12466]={ - category="nl", - direction="l", - }, - [0x12467]={ - category="nl", - direction="l", - }, - [0x12468]={ - category="nl", - direction="l", - }, - [0x12469]={ - category="nl", - direction="l", - }, - [0x1246A]={ - category="nl", - direction="l", - }, - [0x1246B]={ - category="nl", - direction="l", - }, - [0x1246C]={ - category="nl", - direction="l", - }, - [0x1246D]={ - category="nl", - direction="l", - }, - [0x1246E]={ - category="nl", - direction="l", - }, - [0x12470]={ - category="po", - direction="l", - }, - [0x12471]={ - category="po", - direction="l", - }, - [0x12472]={ - category="po", - direction="l", - }, - [0x12473]={ - category="po", - direction="l", - }, - [0x12474]={ - category="po", - direction="l", - }, - [0x12480]={ - category="lo", - direction="l", - }, - [0x12481]={ - category="lo", - direction="l", - }, - [0x12482]={ - category="lo", - direction="l", - }, - [0x12483]={ - category="lo", - direction="l", - }, - [0x12484]={ - category="lo", - direction="l", - }, - [0x12485]={ - category="lo", - direction="l", - }, - [0x12486]={ - category="lo", - direction="l", - }, - [0x12487]={ - category="lo", - direction="l", - }, - [0x12488]={ - category="lo", - direction="l", - }, - [0x12489]={ - category="lo", - direction="l", - }, - [0x1248A]={ - category="lo", - direction="l", - }, - [0x1248B]={ - category="lo", - direction="l", - }, - [0x1248C]={ - category="lo", - direction="l", - }, - [0x1248D]={ - category="lo", - direction="l", - }, - [0x1248E]={ - category="lo", - direction="l", - }, - [0x1248F]={ - category="lo", - direction="l", - }, - [0x12490]={ - category="lo", - direction="l", - }, - [0x12491]={ - category="lo", - direction="l", - }, - [0x12492]={ - category="lo", - direction="l", - }, - [0x12493]={ - category="lo", - direction="l", - }, - [0x12494]={ - category="lo", - direction="l", - }, - [0x12495]={ - category="lo", - direction="l", - }, - [0x12496]={ - category="lo", - direction="l", - }, - [0x12497]={ - category="lo", - direction="l", - }, - [0x12498]={ - category="lo", - direction="l", - }, - [0x12499]={ - category="lo", - direction="l", - }, - [0x1249A]={ - category="lo", - direction="l", - }, - [0x1249B]={ - category="lo", - direction="l", - }, - [0x1249C]={ - category="lo", - direction="l", - }, - [0x1249D]={ - category="lo", - direction="l", - }, - [0x1249E]={ - category="lo", - direction="l", - }, - [0x1249F]={ - category="lo", - direction="l", - }, - [0x124A0]={ - category="lo", - direction="l", - }, - [0x124A1]={ - category="lo", - direction="l", - }, - [0x124A2]={ - category="lo", - direction="l", - }, - [0x124A3]={ - category="lo", - direction="l", - }, - [0x124A4]={ - category="lo", - direction="l", - }, - [0x124A5]={ - category="lo", - direction="l", - }, - [0x124A6]={ - category="lo", - direction="l", - }, - [0x124A7]={ - category="lo", - direction="l", - }, - [0x124A8]={ - category="lo", - direction="l", - }, - [0x124A9]={ - category="lo", - direction="l", - }, - [0x124AA]={ - category="lo", - direction="l", - }, - [0x124AB]={ - category="lo", - direction="l", - }, - [0x124AC]={ - category="lo", - direction="l", - }, - [0x124AD]={ - category="lo", - direction="l", - }, - [0x124AE]={ - category="lo", - direction="l", - }, - [0x124AF]={ - category="lo", - direction="l", - }, - [0x124B0]={ - category="lo", - direction="l", - }, - [0x124B1]={ - category="lo", - direction="l", - }, - [0x124B2]={ - category="lo", - direction="l", - }, - [0x124B3]={ - category="lo", - direction="l", - }, - [0x124B4]={ - category="lo", - direction="l", - }, - [0x124B5]={ - category="lo", - direction="l", - }, - [0x124B6]={ - category="lo", - direction="l", - }, - [0x124B7]={ - category="lo", - direction="l", - }, - [0x124B8]={ - category="lo", - direction="l", - }, - [0x124B9]={ - category="lo", - direction="l", - }, - [0x124BA]={ - category="lo", - direction="l", - }, - [0x124BB]={ - category="lo", - direction="l", - }, - [0x124BC]={ - category="lo", - direction="l", - }, - [0x124BD]={ - category="lo", - direction="l", - }, - [0x124BE]={ - category="lo", - direction="l", - }, - [0x124BF]={ - category="lo", - direction="l", - }, - [0x124C0]={ - category="lo", - direction="l", - }, - [0x124C1]={ - category="lo", - direction="l", - }, - [0x124C2]={ - category="lo", - direction="l", - }, - [0x124C3]={ - category="lo", - direction="l", - }, - [0x124C4]={ - category="lo", - direction="l", - }, - [0x124C5]={ - category="lo", - direction="l", - }, - [0x124C6]={ - category="lo", - direction="l", - }, - [0x124C7]={ - category="lo", - direction="l", - }, - [0x124C8]={ - category="lo", - direction="l", - }, - [0x124C9]={ - category="lo", - direction="l", - }, - [0x124CA]={ - category="lo", - direction="l", - }, - [0x124CB]={ - category="lo", - direction="l", - }, - [0x124CC]={ - category="lo", - direction="l", - }, - [0x124CD]={ - category="lo", - direction="l", - }, - [0x124CE]={ - category="lo", - direction="l", - }, - [0x124CF]={ - category="lo", - direction="l", - }, - [0x124D0]={ - category="lo", - direction="l", - }, - [0x124D1]={ - category="lo", - direction="l", - }, - [0x124D2]={ - category="lo", - direction="l", - }, - [0x124D3]={ - category="lo", - direction="l", - }, - [0x124D4]={ - category="lo", - direction="l", - }, - [0x124D5]={ - category="lo", - direction="l", - }, - [0x124D6]={ - category="lo", - direction="l", - }, - [0x124D7]={ - category="lo", - direction="l", - }, - [0x124D8]={ - category="lo", - direction="l", - }, - [0x124D9]={ - category="lo", - direction="l", - }, - [0x124DA]={ - category="lo", - direction="l", - }, - [0x124DB]={ - category="lo", - direction="l", - }, - [0x124DC]={ - category="lo", - direction="l", - }, - [0x124DD]={ - category="lo", - direction="l", - }, - [0x124DE]={ - category="lo", - direction="l", - }, - [0x124DF]={ - category="lo", - direction="l", - }, - [0x124E0]={ - category="lo", - direction="l", - }, - [0x124E1]={ - category="lo", - direction="l", - }, - [0x124E2]={ - category="lo", - direction="l", - }, - [0x124E3]={ - category="lo", - direction="l", - }, - [0x124E4]={ - category="lo", - direction="l", - }, - [0x124E5]={ - category="lo", - direction="l", - }, - [0x124E6]={ - category="lo", - direction="l", - }, - [0x124E7]={ - category="lo", - direction="l", - }, - [0x124E8]={ - category="lo", - direction="l", - }, - [0x124E9]={ - category="lo", - direction="l", - }, - [0x124EA]={ - category="lo", - direction="l", - }, - [0x124EB]={ - category="lo", - direction="l", - }, - [0x124EC]={ - category="lo", - direction="l", - }, - [0x124ED]={ - category="lo", - direction="l", - }, - [0x124EE]={ - category="lo", - direction="l", - }, - [0x124EF]={ - category="lo", - direction="l", - }, - [0x124F0]={ - category="lo", - direction="l", - }, - [0x124F1]={ - category="lo", - direction="l", - }, - [0x124F2]={ - category="lo", - direction="l", - }, - [0x124F3]={ - category="lo", - direction="l", - }, - [0x124F4]={ - category="lo", - direction="l", - }, - [0x124F5]={ - category="lo", - direction="l", - }, - [0x124F6]={ - category="lo", - direction="l", - }, - [0x124F7]={ - category="lo", - direction="l", - }, - [0x124F8]={ - category="lo", - direction="l", - }, - [0x124F9]={ - category="lo", - direction="l", - }, - [0x124FA]={ - category="lo", - direction="l", - }, - [0x124FB]={ - category="lo", - direction="l", - }, - [0x124FC]={ - category="lo", - direction="l", - }, - [0x124FD]={ - category="lo", - direction="l", - }, - [0x124FE]={ - category="lo", - direction="l", - }, - [0x124FF]={ - category="lo", - direction="l", - }, - [0x12500]={ - category="lo", - direction="l", - }, - [0x12501]={ - category="lo", - direction="l", - }, - [0x12502]={ - category="lo", - direction="l", - }, - [0x12503]={ - category="lo", - direction="l", - }, - [0x12504]={ - category="lo", - direction="l", - }, - [0x12505]={ - category="lo", - direction="l", - }, - [0x12506]={ - category="lo", - direction="l", - }, - [0x12507]={ - category="lo", - direction="l", - }, - [0x12508]={ - category="lo", - direction="l", - }, - [0x12509]={ - category="lo", - direction="l", - }, - [0x1250A]={ - category="lo", - direction="l", - }, - [0x1250B]={ - category="lo", - direction="l", - }, - [0x1250C]={ - category="lo", - direction="l", - }, - [0x1250D]={ - category="lo", - direction="l", - }, - [0x1250E]={ - category="lo", - direction="l", - }, - [0x1250F]={ - category="lo", - direction="l", - }, - [0x12510]={ - category="lo", - direction="l", - }, - [0x12511]={ - category="lo", - direction="l", - }, - [0x12512]={ - category="lo", - direction="l", - }, - [0x12513]={ - category="lo", - direction="l", - }, - [0x12514]={ - category="lo", - direction="l", - }, - [0x12515]={ - category="lo", - direction="l", - }, - [0x12516]={ - category="lo", - direction="l", - }, - [0x12517]={ - category="lo", - direction="l", - }, - [0x12518]={ - category="lo", - direction="l", - }, - [0x12519]={ - category="lo", - direction="l", - }, - [0x1251A]={ - category="lo", - direction="l", - }, - [0x1251B]={ - category="lo", - direction="l", - }, - [0x1251C]={ - category="lo", - direction="l", - }, - [0x1251D]={ - category="lo", - direction="l", - }, - [0x1251E]={ - category="lo", - direction="l", - }, - [0x1251F]={ - category="lo", - direction="l", - }, - [0x12520]={ - category="lo", - direction="l", - }, - [0x12521]={ - category="lo", - direction="l", - }, - [0x12522]={ - category="lo", - direction="l", - }, - [0x12523]={ - category="lo", - direction="l", - }, - [0x12524]={ - category="lo", - direction="l", - }, - [0x12525]={ - category="lo", - direction="l", - }, - [0x12526]={ - category="lo", - direction="l", - }, - [0x12527]={ - category="lo", - direction="l", - }, - [0x12528]={ - category="lo", - direction="l", - }, - [0x12529]={ - category="lo", - direction="l", - }, - [0x1252A]={ - category="lo", - direction="l", - }, - [0x1252B]={ - category="lo", - direction="l", - }, - [0x1252C]={ - category="lo", - direction="l", - }, - [0x1252D]={ - category="lo", - direction="l", - }, - [0x1252E]={ - category="lo", - direction="l", - }, - [0x1252F]={ - category="lo", - direction="l", - }, - [0x12530]={ - category="lo", - direction="l", - }, - [0x12531]={ - category="lo", - direction="l", - }, - [0x12532]={ - category="lo", - direction="l", - }, - [0x12533]={ - category="lo", - direction="l", - }, - [0x12534]={ - category="lo", - direction="l", - }, - [0x12535]={ - category="lo", - direction="l", - }, - [0x12536]={ - category="lo", - direction="l", - }, - [0x12537]={ - category="lo", - direction="l", - }, - [0x12538]={ - category="lo", - direction="l", - }, - [0x12539]={ - category="lo", - direction="l", - }, - [0x1253A]={ - category="lo", - direction="l", - }, - [0x1253B]={ - category="lo", - direction="l", - }, - [0x1253C]={ - category="lo", - direction="l", - }, - [0x1253D]={ - category="lo", - direction="l", - }, - [0x1253E]={ - category="lo", - direction="l", - }, - [0x1253F]={ - category="lo", - direction="l", - }, - [0x12540]={ - category="lo", - direction="l", - }, - [0x12541]={ - category="lo", - direction="l", - }, - [0x12542]={ - category="lo", - direction="l", - }, - [0x12543]={ - category="lo", - direction="l", - }, - [0x13000]={ - category="lo", - direction="l", - }, - [0x13001]={ - category="lo", - direction="l", - }, - [0x13002]={ - category="lo", - direction="l", - }, - [0x13003]={ - category="lo", - direction="l", - }, - [0x13004]={ - category="lo", - direction="l", - }, - [0x13005]={ - category="lo", - direction="l", - }, - [0x13006]={ - category="lo", - direction="l", - }, - [0x13007]={ - category="lo", - direction="l", - }, - [0x13008]={ - category="lo", - direction="l", - }, - [0x13009]={ - category="lo", - direction="l", - }, - [0x1300A]={ - category="lo", - direction="l", - }, - [0x1300B]={ - category="lo", - direction="l", - }, - [0x1300C]={ - category="lo", - direction="l", - }, - [0x1300D]={ - category="lo", - direction="l", - }, - [0x1300E]={ - category="lo", - direction="l", - }, - [0x1300F]={ - category="lo", - direction="l", - }, - [0x13010]={ - category="lo", - direction="l", - }, - [0x13011]={ - category="lo", - direction="l", - }, - [0x13012]={ - category="lo", - direction="l", - }, - [0x13013]={ - category="lo", - direction="l", - }, - [0x13014]={ - category="lo", - direction="l", - }, - [0x13015]={ - category="lo", - direction="l", - }, - [0x13016]={ - category="lo", - direction="l", - }, - [0x13017]={ - category="lo", - direction="l", - }, - [0x13018]={ - category="lo", - direction="l", - }, - [0x13019]={ - category="lo", - direction="l", - }, - [0x1301A]={ - category="lo", - direction="l", - }, - [0x1301B]={ - category="lo", - direction="l", - }, - [0x1301C]={ - category="lo", - direction="l", - }, - [0x1301D]={ - category="lo", - direction="l", - }, - [0x1301E]={ - category="lo", - direction="l", - }, - [0x1301F]={ - category="lo", - direction="l", - }, - [0x13020]={ - category="lo", - direction="l", - }, - [0x13021]={ - category="lo", - direction="l", - }, - [0x13022]={ - category="lo", - direction="l", - }, - [0x13023]={ - category="lo", - direction="l", - }, - [0x13024]={ - category="lo", - direction="l", - }, - [0x13025]={ - category="lo", - direction="l", - }, - [0x13026]={ - category="lo", - direction="l", - }, - [0x13027]={ - category="lo", - direction="l", - }, - [0x13028]={ - category="lo", - direction="l", - }, - [0x13029]={ - category="lo", - direction="l", - }, - [0x1302A]={ - category="lo", - direction="l", - }, - [0x1302B]={ - category="lo", - direction="l", - }, - [0x1302C]={ - category="lo", - direction="l", - }, - [0x1302D]={ - category="lo", - direction="l", - }, - [0x1302E]={ - category="lo", - direction="l", - }, - [0x1302F]={ - category="lo", - direction="l", - }, - [0x13030]={ - category="lo", - direction="l", - }, - [0x13031]={ - category="lo", - direction="l", - }, - [0x13032]={ - category="lo", - direction="l", - }, - [0x13033]={ - category="lo", - direction="l", - }, - [0x13034]={ - category="lo", - direction="l", - }, - [0x13035]={ - category="lo", - direction="l", - }, - [0x13036]={ - category="lo", - direction="l", - }, - [0x13037]={ - category="lo", - direction="l", - }, - [0x13038]={ - category="lo", - direction="l", - }, - [0x13039]={ - category="lo", - direction="l", - }, - [0x1303A]={ - category="lo", - direction="l", - }, - [0x1303B]={ - category="lo", - direction="l", - }, - [0x1303C]={ - category="lo", - direction="l", - }, - [0x1303D]={ - category="lo", - direction="l", - }, - [0x1303E]={ - category="lo", - direction="l", - }, - [0x1303F]={ - category="lo", - direction="l", - }, - [0x13040]={ - category="lo", - direction="l", - }, - [0x13041]={ - category="lo", - direction="l", - }, - [0x13042]={ - category="lo", - direction="l", - }, - [0x13043]={ - category="lo", - direction="l", - }, - [0x13044]={ - category="lo", - direction="l", - }, - [0x13045]={ - category="lo", - direction="l", - }, - [0x13046]={ - category="lo", - direction="l", - }, - [0x13047]={ - category="lo", - direction="l", - }, - [0x13048]={ - category="lo", - direction="l", - }, - [0x13049]={ - category="lo", - direction="l", - }, - [0x1304A]={ - category="lo", - direction="l", - }, - [0x1304B]={ - category="lo", - direction="l", - }, - [0x1304C]={ - category="lo", - direction="l", - }, - [0x1304D]={ - category="lo", - direction="l", - }, - [0x1304E]={ - category="lo", - direction="l", - }, - [0x1304F]={ - category="lo", - direction="l", - }, - [0x13050]={ - category="lo", - direction="l", - }, - [0x13051]={ - category="lo", - direction="l", - }, - [0x13052]={ - category="lo", - direction="l", - }, - [0x13053]={ - category="lo", - direction="l", - }, - [0x13054]={ - category="lo", - direction="l", - }, - [0x13055]={ - category="lo", - direction="l", - }, - [0x13056]={ - category="lo", - direction="l", - }, - [0x13057]={ - category="lo", - direction="l", - }, - [0x13058]={ - category="lo", - direction="l", - }, - [0x13059]={ - category="lo", - direction="l", - }, - [0x1305A]={ - category="lo", - direction="l", - }, - [0x1305B]={ - category="lo", - direction="l", - }, - [0x1305C]={ - category="lo", - direction="l", - }, - [0x1305D]={ - category="lo", - direction="l", - }, - [0x1305E]={ - category="lo", - direction="l", - }, - [0x1305F]={ - category="lo", - direction="l", - }, - [0x13060]={ - category="lo", - direction="l", - }, - [0x13061]={ - category="lo", - direction="l", - }, - [0x13062]={ - category="lo", - direction="l", - }, - [0x13063]={ - category="lo", - direction="l", - }, - [0x13064]={ - category="lo", - direction="l", - }, - [0x13065]={ - category="lo", - direction="l", - }, - [0x13066]={ - category="lo", - direction="l", - }, - [0x13067]={ - category="lo", - direction="l", - }, - [0x13068]={ - category="lo", - direction="l", - }, - [0x13069]={ - category="lo", - direction="l", - }, - [0x1306A]={ - category="lo", - direction="l", - }, - [0x1306B]={ - category="lo", - direction="l", - }, - [0x1306C]={ - category="lo", - direction="l", - }, - [0x1306D]={ - category="lo", - direction="l", - }, - [0x1306E]={ - category="lo", - direction="l", - }, - [0x1306F]={ - category="lo", - direction="l", - }, - [0x13070]={ - category="lo", - direction="l", - }, - [0x13071]={ - category="lo", - direction="l", - }, - [0x13072]={ - category="lo", - direction="l", - }, - [0x13073]={ - category="lo", - direction="l", - }, - [0x13074]={ - category="lo", - direction="l", - }, - [0x13075]={ - category="lo", - direction="l", - }, - [0x13076]={ - category="lo", - direction="l", - }, - [0x13077]={ - category="lo", - direction="l", - }, - [0x13078]={ - category="lo", - direction="l", - }, - [0x13079]={ - category="lo", - direction="l", - }, - [0x1307A]={ - category="lo", - direction="l", - }, - [0x1307B]={ - category="lo", - direction="l", - }, - [0x1307C]={ - category="lo", - direction="l", - }, - [0x1307D]={ - category="lo", - direction="l", - }, - [0x1307E]={ - category="lo", - direction="l", - }, - [0x1307F]={ - category="lo", - direction="l", - }, - [0x13080]={ - category="lo", - direction="l", - }, - [0x13081]={ - category="lo", - direction="l", - }, - [0x13082]={ - category="lo", - direction="l", - }, - [0x13083]={ - category="lo", - direction="l", - }, - [0x13084]={ - category="lo", - direction="l", - }, - [0x13085]={ - category="lo", - direction="l", - }, - [0x13086]={ - category="lo", - direction="l", - }, - [0x13087]={ - category="lo", - direction="l", - }, - [0x13088]={ - category="lo", - direction="l", - }, - [0x13089]={ - category="lo", - direction="l", - }, - [0x1308A]={ - category="lo", - direction="l", - }, - [0x1308B]={ - category="lo", - direction="l", - }, - [0x1308C]={ - category="lo", - direction="l", - }, - [0x1308D]={ - category="lo", - direction="l", - }, - [0x1308E]={ - category="lo", - direction="l", - }, - [0x1308F]={ - category="lo", - direction="l", - }, - [0x13090]={ - category="lo", - direction="l", - }, - [0x13091]={ - category="lo", - direction="l", - }, - [0x13092]={ - category="lo", - direction="l", - }, - [0x13093]={ - category="lo", - direction="l", - }, - [0x13094]={ - category="lo", - direction="l", - }, - [0x13095]={ - category="lo", - direction="l", - }, - [0x13096]={ - category="lo", - direction="l", - }, - [0x13097]={ - category="lo", - direction="l", - }, - [0x13098]={ - category="lo", - direction="l", - }, - [0x13099]={ - category="lo", - direction="l", - }, - [0x1309A]={ - category="lo", - direction="l", - }, - [0x1309B]={ - category="lo", - direction="l", - }, - [0x1309C]={ - category="lo", - direction="l", - }, - [0x1309D]={ - category="lo", - direction="l", - }, - [0x1309E]={ - category="lo", - direction="l", - }, - [0x1309F]={ - category="lo", - direction="l", - }, - [0x130A0]={ - category="lo", - direction="l", - }, - [0x130A1]={ - category="lo", - direction="l", - }, - [0x130A2]={ - category="lo", - direction="l", - }, - [0x130A3]={ - category="lo", - direction="l", - }, - [0x130A4]={ - category="lo", - direction="l", - }, - [0x130A5]={ - category="lo", - direction="l", - }, - [0x130A6]={ - category="lo", - direction="l", - }, - [0x130A7]={ - category="lo", - direction="l", - }, - [0x130A8]={ - category="lo", - direction="l", - }, - [0x130A9]={ - category="lo", - direction="l", - }, - [0x130AA]={ - category="lo", - direction="l", - }, - [0x130AB]={ - category="lo", - direction="l", - }, - [0x130AC]={ - category="lo", - direction="l", - }, - [0x130AD]={ - category="lo", - direction="l", - }, - [0x130AE]={ - category="lo", - direction="l", - }, - [0x130AF]={ - category="lo", - direction="l", - }, - [0x130B0]={ - category="lo", - direction="l", - }, - [0x130B1]={ - category="lo", - direction="l", - }, - [0x130B2]={ - category="lo", - direction="l", - }, - [0x130B3]={ - category="lo", - direction="l", - }, - [0x130B4]={ - category="lo", - direction="l", - }, - [0x130B5]={ - category="lo", - direction="l", - }, - [0x130B6]={ - category="lo", - direction="l", - }, - [0x130B7]={ - category="lo", - direction="l", - }, - [0x130B8]={ - category="lo", - direction="l", - }, - [0x130B9]={ - category="lo", - direction="l", - }, - [0x130BA]={ - category="lo", - direction="l", - }, - [0x130BB]={ - category="lo", - direction="l", - }, - [0x130BC]={ - category="lo", - direction="l", - }, - [0x130BD]={ - category="lo", - direction="l", - }, - [0x130BE]={ - category="lo", - direction="l", - }, - [0x130BF]={ - category="lo", - direction="l", - }, - [0x130C0]={ - category="lo", - direction="l", - }, - [0x130C1]={ - category="lo", - direction="l", - }, - [0x130C2]={ - category="lo", - direction="l", - }, - [0x130C3]={ - category="lo", - direction="l", - }, - [0x130C4]={ - category="lo", - direction="l", - }, - [0x130C5]={ - category="lo", - direction="l", - }, - [0x130C6]={ - category="lo", - direction="l", - }, - [0x130C7]={ - category="lo", - direction="l", - }, - [0x130C8]={ - category="lo", - direction="l", - }, - [0x130C9]={ - category="lo", - direction="l", - }, - [0x130CA]={ - category="lo", - direction="l", - }, - [0x130CB]={ - category="lo", - direction="l", - }, - [0x130CC]={ - category="lo", - direction="l", - }, - [0x130CD]={ - category="lo", - direction="l", - }, - [0x130CE]={ - category="lo", - direction="l", - }, - [0x130CF]={ - category="lo", - direction="l", - }, - [0x130D0]={ - category="lo", - direction="l", - }, - [0x130D1]={ - category="lo", - direction="l", - }, - [0x130D2]={ - category="lo", - direction="l", - }, - [0x130D3]={ - category="lo", - direction="l", - }, - [0x130D4]={ - category="lo", - direction="l", - }, - [0x130D5]={ - category="lo", - direction="l", - }, - [0x130D6]={ - category="lo", - direction="l", - }, - [0x130D7]={ - category="lo", - direction="l", - }, - [0x130D8]={ - category="lo", - direction="l", - }, - [0x130D9]={ - category="lo", - direction="l", - }, - [0x130DA]={ - category="lo", - direction="l", - }, - [0x130DB]={ - category="lo", - direction="l", - }, - [0x130DC]={ - category="lo", - direction="l", - }, - [0x130DD]={ - category="lo", - direction="l", - }, - [0x130DE]={ - category="lo", - direction="l", - }, - [0x130DF]={ - category="lo", - direction="l", - }, - [0x130E0]={ - category="lo", - direction="l", - }, - [0x130E1]={ - category="lo", - direction="l", - }, - [0x130E2]={ - category="lo", - direction="l", - }, - [0x130E3]={ - category="lo", - direction="l", - }, - [0x130E4]={ - category="lo", - direction="l", - }, - [0x130E5]={ - category="lo", - direction="l", - }, - [0x130E6]={ - category="lo", - direction="l", - }, - [0x130E7]={ - category="lo", - direction="l", - }, - [0x130E8]={ - category="lo", - direction="l", - }, - [0x130E9]={ - category="lo", - direction="l", - }, - [0x130EA]={ - category="lo", - direction="l", - }, - [0x130EB]={ - category="lo", - direction="l", - }, - [0x130EC]={ - category="lo", - direction="l", - }, - [0x130ED]={ - category="lo", - direction="l", - }, - [0x130EE]={ - category="lo", - direction="l", - }, - [0x130EF]={ - category="lo", - direction="l", - }, - [0x130F0]={ - category="lo", - direction="l", - }, - [0x130F1]={ - category="lo", - direction="l", - }, - [0x130F2]={ - category="lo", - direction="l", - }, - [0x130F3]={ - category="lo", - direction="l", - }, - [0x130F4]={ - category="lo", - direction="l", - }, - [0x130F5]={ - category="lo", - direction="l", - }, - [0x130F6]={ - category="lo", - direction="l", - }, - [0x130F7]={ - category="lo", - direction="l", - }, - [0x130F8]={ - category="lo", - direction="l", - }, - [0x130F9]={ - category="lo", - direction="l", - }, - [0x130FA]={ - category="lo", - direction="l", - }, - [0x130FB]={ - category="lo", - direction="l", - }, - [0x130FC]={ - category="lo", - direction="l", - }, - [0x130FD]={ - category="lo", - direction="l", - }, - [0x130FE]={ - category="lo", - direction="l", - }, - [0x130FF]={ - category="lo", - direction="l", - }, - [0x13100]={ - category="lo", - direction="l", - }, - [0x13101]={ - category="lo", - direction="l", - }, - [0x13102]={ - category="lo", - direction="l", - }, - [0x13103]={ - category="lo", - direction="l", - }, - [0x13104]={ - category="lo", - direction="l", - }, - [0x13105]={ - category="lo", - direction="l", - }, - [0x13106]={ - category="lo", - direction="l", - }, - [0x13107]={ - category="lo", - direction="l", - }, - [0x13108]={ - category="lo", - direction="l", - }, - [0x13109]={ - category="lo", - direction="l", - }, - [0x1310A]={ - category="lo", - direction="l", - }, - [0x1310B]={ - category="lo", - direction="l", - }, - [0x1310C]={ - category="lo", - direction="l", - }, - [0x1310D]={ - category="lo", - direction="l", - }, - [0x1310E]={ - category="lo", - direction="l", - }, - [0x1310F]={ - category="lo", - direction="l", - }, - [0x13110]={ - category="lo", - direction="l", - }, - [0x13111]={ - category="lo", - direction="l", - }, - [0x13112]={ - category="lo", - direction="l", - }, - [0x13113]={ - category="lo", - direction="l", - }, - [0x13114]={ - category="lo", - direction="l", - }, - [0x13115]={ - category="lo", - direction="l", - }, - [0x13116]={ - category="lo", - direction="l", - }, - [0x13117]={ - category="lo", - direction="l", - }, - [0x13118]={ - category="lo", - direction="l", - }, - [0x13119]={ - category="lo", - direction="l", - }, - [0x1311A]={ - category="lo", - direction="l", - }, - [0x1311B]={ - category="lo", - direction="l", - }, - [0x1311C]={ - category="lo", - direction="l", - }, - [0x1311D]={ - category="lo", - direction="l", - }, - [0x1311E]={ - category="lo", - direction="l", - }, - [0x1311F]={ - category="lo", - direction="l", - }, - [0x13120]={ - category="lo", - direction="l", - }, - [0x13121]={ - category="lo", - direction="l", - }, - [0x13122]={ - category="lo", - direction="l", - }, - [0x13123]={ - category="lo", - direction="l", - }, - [0x13124]={ - category="lo", - direction="l", - }, - [0x13125]={ - category="lo", - direction="l", - }, - [0x13126]={ - category="lo", - direction="l", - }, - [0x13127]={ - category="lo", - direction="l", - }, - [0x13128]={ - category="lo", - direction="l", - }, - [0x13129]={ - category="lo", - direction="l", - }, - [0x1312A]={ - category="lo", - direction="l", - }, - [0x1312B]={ - category="lo", - direction="l", - }, - [0x1312C]={ - category="lo", - direction="l", - }, - [0x1312D]={ - category="lo", - direction="l", - }, - [0x1312E]={ - category="lo", - direction="l", - }, - [0x1312F]={ - category="lo", - direction="l", - }, - [0x13130]={ - category="lo", - direction="l", - }, - [0x13131]={ - category="lo", - direction="l", - }, - [0x13132]={ - category="lo", - direction="l", - }, - [0x13133]={ - category="lo", - direction="l", - }, - [0x13134]={ - category="lo", - direction="l", - }, - [0x13135]={ - category="lo", - direction="l", - }, - [0x13136]={ - category="lo", - direction="l", - }, - [0x13137]={ - category="lo", - direction="l", - }, - [0x13138]={ - category="lo", - direction="l", - }, - [0x13139]={ - category="lo", - direction="l", - }, - [0x1313A]={ - category="lo", - direction="l", - }, - [0x1313B]={ - category="lo", - direction="l", - }, - [0x1313C]={ - category="lo", - direction="l", - }, - [0x1313D]={ - category="lo", - direction="l", - }, - [0x1313E]={ - category="lo", - direction="l", - }, - [0x1313F]={ - category="lo", - direction="l", - }, - [0x13140]={ - category="lo", - direction="l", - }, - [0x13141]={ - category="lo", - direction="l", - }, - [0x13142]={ - category="lo", - direction="l", - }, - [0x13143]={ - category="lo", - direction="l", - }, - [0x13144]={ - category="lo", - direction="l", - }, - [0x13145]={ - category="lo", - direction="l", - }, - [0x13146]={ - category="lo", - direction="l", - }, - [0x13147]={ - category="lo", - direction="l", - }, - [0x13148]={ - category="lo", - direction="l", - }, - [0x13149]={ - category="lo", - direction="l", - }, - [0x1314A]={ - category="lo", - direction="l", - }, - [0x1314B]={ - category="lo", - direction="l", - }, - [0x1314C]={ - category="lo", - direction="l", - }, - [0x1314D]={ - category="lo", - direction="l", - }, - [0x1314E]={ - category="lo", - direction="l", - }, - [0x1314F]={ - category="lo", - direction="l", - }, - [0x13150]={ - category="lo", - direction="l", - }, - [0x13151]={ - category="lo", - direction="l", - }, - [0x13152]={ - category="lo", - direction="l", - }, - [0x13153]={ - category="lo", - direction="l", - }, - [0x13154]={ - category="lo", - direction="l", - }, - [0x13155]={ - category="lo", - direction="l", - }, - [0x13156]={ - category="lo", - direction="l", - }, - [0x13157]={ - category="lo", - direction="l", - }, - [0x13158]={ - category="lo", - direction="l", - }, - [0x13159]={ - category="lo", - direction="l", - }, - [0x1315A]={ - category="lo", - direction="l", - }, - [0x1315B]={ - category="lo", - direction="l", - }, - [0x1315C]={ - category="lo", - direction="l", - }, - [0x1315D]={ - category="lo", - direction="l", - }, - [0x1315E]={ - category="lo", - direction="l", - }, - [0x1315F]={ - category="lo", - direction="l", - }, - [0x13160]={ - category="lo", - direction="l", - }, - [0x13161]={ - category="lo", - direction="l", - }, - [0x13162]={ - category="lo", - direction="l", - }, - [0x13163]={ - category="lo", - direction="l", - }, - [0x13164]={ - category="lo", - direction="l", - }, - [0x13165]={ - category="lo", - direction="l", - }, - [0x13166]={ - category="lo", - direction="l", - }, - [0x13167]={ - category="lo", - direction="l", - }, - [0x13168]={ - category="lo", - direction="l", - }, - [0x13169]={ - category="lo", - direction="l", - }, - [0x1316A]={ - category="lo", - direction="l", - }, - [0x1316B]={ - category="lo", - direction="l", - }, - [0x1316C]={ - category="lo", - direction="l", - }, - [0x1316D]={ - category="lo", - direction="l", - }, - [0x1316E]={ - category="lo", - direction="l", - }, - [0x1316F]={ - category="lo", - direction="l", - }, - [0x13170]={ - category="lo", - direction="l", - }, - [0x13171]={ - category="lo", - direction="l", - }, - [0x13172]={ - category="lo", - direction="l", - }, - [0x13173]={ - category="lo", - direction="l", - }, - [0x13174]={ - category="lo", - direction="l", - }, - [0x13175]={ - category="lo", - direction="l", - }, - [0x13176]={ - category="lo", - direction="l", - }, - [0x13177]={ - category="lo", - direction="l", - }, - [0x13178]={ - category="lo", - direction="l", - }, - [0x13179]={ - category="lo", - direction="l", - }, - [0x1317A]={ - category="lo", - direction="l", - }, - [0x1317B]={ - category="lo", - direction="l", - }, - [0x1317C]={ - category="lo", - direction="l", - }, - [0x1317D]={ - category="lo", - direction="l", - }, - [0x1317E]={ - category="lo", - direction="l", - }, - [0x1317F]={ - category="lo", - direction="l", - }, - [0x13180]={ - category="lo", - direction="l", - }, - [0x13181]={ - category="lo", - direction="l", - }, - [0x13182]={ - category="lo", - direction="l", - }, - [0x13183]={ - category="lo", - direction="l", - }, - [0x13184]={ - category="lo", - direction="l", - }, - [0x13185]={ - category="lo", - direction="l", - }, - [0x13186]={ - category="lo", - direction="l", - }, - [0x13187]={ - category="lo", - direction="l", - }, - [0x13188]={ - category="lo", - direction="l", - }, - [0x13189]={ - category="lo", - direction="l", - }, - [0x1318A]={ - category="lo", - direction="l", - }, - [0x1318B]={ - category="lo", - direction="l", - }, - [0x1318C]={ - category="lo", - direction="l", - }, - [0x1318D]={ - category="lo", - direction="l", - }, - [0x1318E]={ - category="lo", - direction="l", - }, - [0x1318F]={ - category="lo", - direction="l", - }, - [0x13190]={ - category="lo", - direction="l", - }, - [0x13191]={ - category="lo", - direction="l", - }, - [0x13192]={ - category="lo", - direction="l", - }, - [0x13193]={ - category="lo", - direction="l", - }, - [0x13194]={ - category="lo", - direction="l", - }, - [0x13195]={ - category="lo", - direction="l", - }, - [0x13196]={ - category="lo", - direction="l", - }, - [0x13197]={ - category="lo", - direction="l", - }, - [0x13198]={ - category="lo", - direction="l", - }, - [0x13199]={ - category="lo", - direction="l", - }, - [0x1319A]={ - category="lo", - direction="l", - }, - [0x1319B]={ - category="lo", - direction="l", - }, - [0x1319C]={ - category="lo", - direction="l", - }, - [0x1319D]={ - category="lo", - direction="l", - }, - [0x1319E]={ - category="lo", - direction="l", - }, - [0x1319F]={ - category="lo", - direction="l", - }, - [0x131A0]={ - category="lo", - direction="l", - }, - [0x131A1]={ - category="lo", - direction="l", - }, - [0x131A2]={ - category="lo", - direction="l", - }, - [0x131A3]={ - category="lo", - direction="l", - }, - [0x131A4]={ - category="lo", - direction="l", - }, - [0x131A5]={ - category="lo", - direction="l", - }, - [0x131A6]={ - category="lo", - direction="l", - }, - [0x131A7]={ - category="lo", - direction="l", - }, - [0x131A8]={ - category="lo", - direction="l", - }, - [0x131A9]={ - category="lo", - direction="l", - }, - [0x131AA]={ - category="lo", - direction="l", - }, - [0x131AB]={ - category="lo", - direction="l", - }, - [0x131AC]={ - category="lo", - direction="l", - }, - [0x131AD]={ - category="lo", - direction="l", - }, - [0x131AE]={ - category="lo", - direction="l", - }, - [0x131AF]={ - category="lo", - direction="l", - }, - [0x131B0]={ - category="lo", - direction="l", - }, - [0x131B1]={ - category="lo", - direction="l", - }, - [0x131B2]={ - category="lo", - direction="l", - }, - [0x131B3]={ - category="lo", - direction="l", - }, - [0x131B4]={ - category="lo", - direction="l", - }, - [0x131B5]={ - category="lo", - direction="l", - }, - [0x131B6]={ - category="lo", - direction="l", - }, - [0x131B7]={ - category="lo", - direction="l", - }, - [0x131B8]={ - category="lo", - direction="l", - }, - [0x131B9]={ - category="lo", - direction="l", - }, - [0x131BA]={ - category="lo", - direction="l", - }, - [0x131BB]={ - category="lo", - direction="l", - }, - [0x131BC]={ - category="lo", - direction="l", - }, - [0x131BD]={ - category="lo", - direction="l", - }, - [0x131BE]={ - category="lo", - direction="l", - }, - [0x131BF]={ - category="lo", - direction="l", - }, - [0x131C0]={ - category="lo", - direction="l", - }, - [0x131C1]={ - category="lo", - direction="l", - }, - [0x131C2]={ - category="lo", - direction="l", - }, - [0x131C3]={ - category="lo", - direction="l", - }, - [0x131C4]={ - category="lo", - direction="l", - }, - [0x131C5]={ - category="lo", - direction="l", - }, - [0x131C6]={ - category="lo", - direction="l", - }, - [0x131C7]={ - category="lo", - direction="l", - }, - [0x131C8]={ - category="lo", - direction="l", - }, - [0x131C9]={ - category="lo", - direction="l", - }, - [0x131CA]={ - category="lo", - direction="l", - }, - [0x131CB]={ - category="lo", - direction="l", - }, - [0x131CC]={ - category="lo", - direction="l", - }, - [0x131CD]={ - category="lo", - direction="l", - }, - [0x131CE]={ - category="lo", - direction="l", - }, - [0x131CF]={ - category="lo", - direction="l", - }, - [0x131D0]={ - category="lo", - direction="l", - }, - [0x131D1]={ - category="lo", - direction="l", - }, - [0x131D2]={ - category="lo", - direction="l", - }, - [0x131D3]={ - category="lo", - direction="l", - }, - [0x131D4]={ - category="lo", - direction="l", - }, - [0x131D5]={ - category="lo", - direction="l", - }, - [0x131D6]={ - category="lo", - direction="l", - }, - [0x131D7]={ - category="lo", - direction="l", - }, - [0x131D8]={ - category="lo", - direction="l", - }, - [0x131D9]={ - category="lo", - direction="l", - }, - [0x131DA]={ - category="lo", - direction="l", - }, - [0x131DB]={ - category="lo", - direction="l", - }, - [0x131DC]={ - category="lo", - direction="l", - }, - [0x131DD]={ - category="lo", - direction="l", - }, - [0x131DE]={ - category="lo", - direction="l", - }, - [0x131DF]={ - category="lo", - direction="l", - }, - [0x131E0]={ - category="lo", - direction="l", - }, - [0x131E1]={ - category="lo", - direction="l", - }, - [0x131E2]={ - category="lo", - direction="l", - }, - [0x131E3]={ - category="lo", - direction="l", - }, - [0x131E4]={ - category="lo", - direction="l", - }, - [0x131E5]={ - category="lo", - direction="l", - }, - [0x131E6]={ - category="lo", - direction="l", - }, - [0x131E7]={ - category="lo", - direction="l", - }, - [0x131E8]={ - category="lo", - direction="l", - }, - [0x131E9]={ - category="lo", - direction="l", - }, - [0x131EA]={ - category="lo", - direction="l", - }, - [0x131EB]={ - category="lo", - direction="l", - }, - [0x131EC]={ - category="lo", - direction="l", - }, - [0x131ED]={ - category="lo", - direction="l", - }, - [0x131EE]={ - category="lo", - direction="l", - }, - [0x131EF]={ - category="lo", - direction="l", - }, - [0x131F0]={ - category="lo", - direction="l", - }, - [0x131F1]={ - category="lo", - direction="l", - }, - [0x131F2]={ - category="lo", - direction="l", - }, - [0x131F3]={ - category="lo", - direction="l", - }, - [0x131F4]={ - category="lo", - direction="l", - }, - [0x131F5]={ - category="lo", - direction="l", - }, - [0x131F6]={ - category="lo", - direction="l", - }, - [0x131F7]={ - category="lo", - direction="l", - }, - [0x131F8]={ - category="lo", - direction="l", - }, - [0x131F9]={ - category="lo", - direction="l", - }, - [0x131FA]={ - category="lo", - direction="l", - }, - [0x131FB]={ - category="lo", - direction="l", - }, - [0x131FC]={ - category="lo", - direction="l", - }, - [0x131FD]={ - category="lo", - direction="l", - }, - [0x131FE]={ - category="lo", - direction="l", - }, - [0x131FF]={ - category="lo", - direction="l", - }, - [0x13200]={ - category="lo", - direction="l", - }, - [0x13201]={ - category="lo", - direction="l", - }, - [0x13202]={ - category="lo", - direction="l", - }, - [0x13203]={ - category="lo", - direction="l", - }, - [0x13204]={ - category="lo", - direction="l", - }, - [0x13205]={ - category="lo", - direction="l", - }, - [0x13206]={ - category="lo", - direction="l", - }, - [0x13207]={ - category="lo", - direction="l", - }, - [0x13208]={ - category="lo", - direction="l", - }, - [0x13209]={ - category="lo", - direction="l", - }, - [0x1320A]={ - category="lo", - direction="l", - }, - [0x1320B]={ - category="lo", - direction="l", - }, - [0x1320C]={ - category="lo", - direction="l", - }, - [0x1320D]={ - category="lo", - direction="l", - }, - [0x1320E]={ - category="lo", - direction="l", - }, - [0x1320F]={ - category="lo", - direction="l", - }, - [0x13210]={ - category="lo", - direction="l", - }, - [0x13211]={ - category="lo", - direction="l", - }, - [0x13212]={ - category="lo", - direction="l", - }, - [0x13213]={ - category="lo", - direction="l", - }, - [0x13214]={ - category="lo", - direction="l", - }, - [0x13215]={ - category="lo", - direction="l", - }, - [0x13216]={ - category="lo", - direction="l", - }, - [0x13217]={ - category="lo", - direction="l", - }, - [0x13218]={ - category="lo", - direction="l", - }, - [0x13219]={ - category="lo", - direction="l", - }, - [0x1321A]={ - category="lo", - direction="l", - }, - [0x1321B]={ - category="lo", - direction="l", - }, - [0x1321C]={ - category="lo", - direction="l", - }, - [0x1321D]={ - category="lo", - direction="l", - }, - [0x1321E]={ - category="lo", - direction="l", - }, - [0x1321F]={ - category="lo", - direction="l", - }, - [0x13220]={ - category="lo", - direction="l", - }, - [0x13221]={ - category="lo", - direction="l", - }, - [0x13222]={ - category="lo", - direction="l", - }, - [0x13223]={ - category="lo", - direction="l", - }, - [0x13224]={ - category="lo", - direction="l", - }, - [0x13225]={ - category="lo", - direction="l", - }, - [0x13226]={ - category="lo", - direction="l", - }, - [0x13227]={ - category="lo", - direction="l", - }, - [0x13228]={ - category="lo", - direction="l", - }, - [0x13229]={ - category="lo", - direction="l", - }, - [0x1322A]={ - category="lo", - direction="l", - }, - [0x1322B]={ - category="lo", - direction="l", - }, - [0x1322C]={ - category="lo", - direction="l", - }, - [0x1322D]={ - category="lo", - direction="l", - }, - [0x1322E]={ - category="lo", - direction="l", - }, - [0x1322F]={ - category="lo", - direction="l", - }, - [0x13230]={ - category="lo", - direction="l", - }, - [0x13231]={ - category="lo", - direction="l", - }, - [0x13232]={ - category="lo", - direction="l", - }, - [0x13233]={ - category="lo", - direction="l", - }, - [0x13234]={ - category="lo", - direction="l", - }, - [0x13235]={ - category="lo", - direction="l", - }, - [0x13236]={ - category="lo", - direction="l", - }, - [0x13237]={ - category="lo", - direction="l", - }, - [0x13238]={ - category="lo", - direction="l", - }, - [0x13239]={ - category="lo", - direction="l", - }, - [0x1323A]={ - category="lo", - direction="l", - }, - [0x1323B]={ - category="lo", - direction="l", - }, - [0x1323C]={ - category="lo", - direction="l", - }, - [0x1323D]={ - category="lo", - direction="l", - }, - [0x1323E]={ - category="lo", - direction="l", - }, - [0x1323F]={ - category="lo", - direction="l", - }, - [0x13240]={ - category="lo", - direction="l", - }, - [0x13241]={ - category="lo", - direction="l", - }, - [0x13242]={ - category="lo", - direction="l", - }, - [0x13243]={ - category="lo", - direction="l", - }, - [0x13244]={ - category="lo", - direction="l", - }, - [0x13245]={ - category="lo", - direction="l", - }, - [0x13246]={ - category="lo", - direction="l", - }, - [0x13247]={ - category="lo", - direction="l", - }, - [0x13248]={ - category="lo", - direction="l", - }, - [0x13249]={ - category="lo", - direction="l", - }, - [0x1324A]={ - category="lo", - direction="l", - }, - [0x1324B]={ - category="lo", - direction="l", - }, - [0x1324C]={ - category="lo", - direction="l", - }, - [0x1324D]={ - category="lo", - direction="l", - }, - [0x1324E]={ - category="lo", - direction="l", - }, - [0x1324F]={ - category="lo", - direction="l", - }, - [0x13250]={ - category="lo", - direction="l", - }, - [0x13251]={ - category="lo", - direction="l", - }, - [0x13252]={ - category="lo", - direction="l", - }, - [0x13253]={ - category="lo", - direction="l", - }, - [0x13254]={ - category="lo", - direction="l", - }, - [0x13255]={ - category="lo", - direction="l", - }, - [0x13256]={ - category="lo", - direction="l", - }, - [0x13257]={ - category="lo", - direction="l", - }, - [0x13258]={ - category="lo", - direction="l", - }, - [0x13259]={ - category="lo", - direction="l", - }, - [0x1325A]={ - category="lo", - direction="l", - }, - [0x1325B]={ - category="lo", - direction="l", - }, - [0x1325C]={ - category="lo", - direction="l", - }, - [0x1325D]={ - category="lo", - direction="l", - }, - [0x1325E]={ - category="lo", - direction="l", - }, - [0x1325F]={ - category="lo", - direction="l", - }, - [0x13260]={ - category="lo", - direction="l", - }, - [0x13261]={ - category="lo", - direction="l", - }, - [0x13262]={ - category="lo", - direction="l", - }, - [0x13263]={ - category="lo", - direction="l", - }, - [0x13264]={ - category="lo", - direction="l", - }, - [0x13265]={ - category="lo", - direction="l", - }, - [0x13266]={ - category="lo", - direction="l", - }, - [0x13267]={ - category="lo", - direction="l", - }, - [0x13268]={ - category="lo", - direction="l", - }, - [0x13269]={ - category="lo", - direction="l", - }, - [0x1326A]={ - category="lo", - direction="l", - }, - [0x1326B]={ - category="lo", - direction="l", - }, - [0x1326C]={ - category="lo", - direction="l", - }, - [0x1326D]={ - category="lo", - direction="l", - }, - [0x1326E]={ - category="lo", - direction="l", - }, - [0x1326F]={ - category="lo", - direction="l", - }, - [0x13270]={ - category="lo", - direction="l", - }, - [0x13271]={ - category="lo", - direction="l", - }, - [0x13272]={ - category="lo", - direction="l", - }, - [0x13273]={ - category="lo", - direction="l", - }, - [0x13274]={ - category="lo", - direction="l", - }, - [0x13275]={ - category="lo", - direction="l", - }, - [0x13276]={ - category="lo", - direction="l", - }, - [0x13277]={ - category="lo", - direction="l", - }, - [0x13278]={ - category="lo", - direction="l", - }, - [0x13279]={ - category="lo", - direction="l", - }, - [0x1327A]={ - category="lo", - direction="l", - }, - [0x1327B]={ - category="lo", - direction="l", - }, - [0x1327C]={ - category="lo", - direction="l", - }, - [0x1327D]={ - category="lo", - direction="l", - }, - [0x1327E]={ - category="lo", - direction="l", - }, - [0x1327F]={ - category="lo", - direction="l", - }, - [0x13280]={ - category="lo", - direction="l", - }, - [0x13281]={ - category="lo", - direction="l", - }, - [0x13282]={ - category="lo", - direction="l", - }, - [0x13283]={ - category="lo", - direction="l", - }, - [0x13284]={ - category="lo", - direction="l", - }, - [0x13285]={ - category="lo", - direction="l", - }, - [0x13286]={ - category="lo", - direction="l", - }, - [0x13287]={ - category="lo", - direction="l", - }, - [0x13288]={ - category="lo", - direction="l", - }, - [0x13289]={ - category="lo", - direction="l", - }, - [0x1328A]={ - category="lo", - direction="l", - }, - [0x1328B]={ - category="lo", - direction="l", - }, - [0x1328C]={ - category="lo", - direction="l", - }, - [0x1328D]={ - category="lo", - direction="l", - }, - [0x1328E]={ - category="lo", - direction="l", - }, - [0x1328F]={ - category="lo", - direction="l", - }, - [0x13290]={ - category="lo", - direction="l", - }, - [0x13291]={ - category="lo", - direction="l", - }, - [0x13292]={ - category="lo", - direction="l", - }, - [0x13293]={ - category="lo", - direction="l", - }, - [0x13294]={ - category="lo", - direction="l", - }, - [0x13295]={ - category="lo", - direction="l", - }, - [0x13296]={ - category="lo", - direction="l", - }, - [0x13297]={ - category="lo", - direction="l", - }, - [0x13298]={ - category="lo", - direction="l", - }, - [0x13299]={ - category="lo", - direction="l", - }, - [0x1329A]={ - category="lo", - direction="l", - }, - [0x1329B]={ - category="lo", - direction="l", - }, - [0x1329C]={ - category="lo", - direction="l", - }, - [0x1329D]={ - category="lo", - direction="l", - }, - [0x1329E]={ - category="lo", - direction="l", - }, - [0x1329F]={ - category="lo", - direction="l", - }, - [0x132A0]={ - category="lo", - direction="l", - }, - [0x132A1]={ - category="lo", - direction="l", - }, - [0x132A2]={ - category="lo", - direction="l", - }, - [0x132A3]={ - category="lo", - direction="l", - }, - [0x132A4]={ - category="lo", - direction="l", - }, - [0x132A5]={ - category="lo", - direction="l", - }, - [0x132A6]={ - category="lo", - direction="l", - }, - [0x132A7]={ - category="lo", - direction="l", - }, - [0x132A8]={ - category="lo", - direction="l", - }, - [0x132A9]={ - category="lo", - direction="l", - }, - [0x132AA]={ - category="lo", - direction="l", - }, - [0x132AB]={ - category="lo", - direction="l", - }, - [0x132AC]={ - category="lo", - direction="l", - }, - [0x132AD]={ - category="lo", - direction="l", - }, - [0x132AE]={ - category="lo", - direction="l", - }, - [0x132AF]={ - category="lo", - direction="l", - }, - [0x132B0]={ - category="lo", - direction="l", - }, - [0x132B1]={ - category="lo", - direction="l", - }, - [0x132B2]={ - category="lo", - direction="l", - }, - [0x132B3]={ - category="lo", - direction="l", - }, - [0x132B4]={ - category="lo", - direction="l", - }, - [0x132B5]={ - category="lo", - direction="l", - }, - [0x132B6]={ - category="lo", - direction="l", - }, - [0x132B7]={ - category="lo", - direction="l", - }, - [0x132B8]={ - category="lo", - direction="l", - }, - [0x132B9]={ - category="lo", - direction="l", - }, - [0x132BA]={ - category="lo", - direction="l", - }, - [0x132BB]={ - category="lo", - direction="l", - }, - [0x132BC]={ - category="lo", - direction="l", - }, - [0x132BD]={ - category="lo", - direction="l", - }, - [0x132BE]={ - category="lo", - direction="l", - }, - [0x132BF]={ - category="lo", - direction="l", - }, - [0x132C0]={ - category="lo", - direction="l", - }, - [0x132C1]={ - category="lo", - direction="l", - }, - [0x132C2]={ - category="lo", - direction="l", - }, - [0x132C3]={ - category="lo", - direction="l", - }, - [0x132C4]={ - category="lo", - direction="l", - }, - [0x132C5]={ - category="lo", - direction="l", - }, - [0x132C6]={ - category="lo", - direction="l", - }, - [0x132C7]={ - category="lo", - direction="l", - }, - [0x132C8]={ - category="lo", - direction="l", - }, - [0x132C9]={ - category="lo", - direction="l", - }, - [0x132CA]={ - category="lo", - direction="l", - }, - [0x132CB]={ - category="lo", - direction="l", - }, - [0x132CC]={ - category="lo", - direction="l", - }, - [0x132CD]={ - category="lo", - direction="l", - }, - [0x132CE]={ - category="lo", - direction="l", - }, - [0x132CF]={ - category="lo", - direction="l", - }, - [0x132D0]={ - category="lo", - direction="l", - }, - [0x132D1]={ - category="lo", - direction="l", - }, - [0x132D2]={ - category="lo", - direction="l", - }, - [0x132D3]={ - category="lo", - direction="l", - }, - [0x132D4]={ - category="lo", - direction="l", - }, - [0x132D5]={ - category="lo", - direction="l", - }, - [0x132D6]={ - category="lo", - direction="l", - }, - [0x132D7]={ - category="lo", - direction="l", - }, - [0x132D8]={ - category="lo", - direction="l", - }, - [0x132D9]={ - category="lo", - direction="l", - }, - [0x132DA]={ - category="lo", - direction="l", - }, - [0x132DB]={ - category="lo", - direction="l", - }, - [0x132DC]={ - category="lo", - direction="l", - }, - [0x132DD]={ - category="lo", - direction="l", - }, - [0x132DE]={ - category="lo", - direction="l", - }, - [0x132DF]={ - category="lo", - direction="l", - }, - [0x132E0]={ - category="lo", - direction="l", - }, - [0x132E1]={ - category="lo", - direction="l", - }, - [0x132E2]={ - category="lo", - direction="l", - }, - [0x132E3]={ - category="lo", - direction="l", - }, - [0x132E4]={ - category="lo", - direction="l", - }, - [0x132E5]={ - category="lo", - direction="l", - }, - [0x132E6]={ - category="lo", - direction="l", - }, - [0x132E7]={ - category="lo", - direction="l", - }, - [0x132E8]={ - category="lo", - direction="l", - }, - [0x132E9]={ - category="lo", - direction="l", - }, - [0x132EA]={ - category="lo", - direction="l", - }, - [0x132EB]={ - category="lo", - direction="l", - }, - [0x132EC]={ - category="lo", - direction="l", - }, - [0x132ED]={ - category="lo", - direction="l", - }, - [0x132EE]={ - category="lo", - direction="l", - }, - [0x132EF]={ - category="lo", - direction="l", - }, - [0x132F0]={ - category="lo", - direction="l", - }, - [0x132F1]={ - category="lo", - direction="l", - }, - [0x132F2]={ - category="lo", - direction="l", - }, - [0x132F3]={ - category="lo", - direction="l", - }, - [0x132F4]={ - category="lo", - direction="l", - }, - [0x132F5]={ - category="lo", - direction="l", - }, - [0x132F6]={ - category="lo", - direction="l", - }, - [0x132F7]={ - category="lo", - direction="l", - }, - [0x132F8]={ - category="lo", - direction="l", - }, - [0x132F9]={ - category="lo", - direction="l", - }, - [0x132FA]={ - category="lo", - direction="l", - }, - [0x132FB]={ - category="lo", - direction="l", - }, - [0x132FC]={ - category="lo", - direction="l", - }, - [0x132FD]={ - category="lo", - direction="l", - }, - [0x132FE]={ - category="lo", - direction="l", - }, - [0x132FF]={ - category="lo", - direction="l", - }, - [0x13300]={ - category="lo", - direction="l", - }, - [0x13301]={ - category="lo", - direction="l", - }, - [0x13302]={ - category="lo", - direction="l", - }, - [0x13303]={ - category="lo", - direction="l", - }, - [0x13304]={ - category="lo", - direction="l", - }, - [0x13305]={ - category="lo", - direction="l", - }, - [0x13306]={ - category="lo", - direction="l", - }, - [0x13307]={ - category="lo", - direction="l", - }, - [0x13308]={ - category="lo", - direction="l", - }, - [0x13309]={ - category="lo", - direction="l", - }, - [0x1330A]={ - category="lo", - direction="l", - }, - [0x1330B]={ - category="lo", - direction="l", - }, - [0x1330C]={ - category="lo", - direction="l", - }, - [0x1330D]={ - category="lo", - direction="l", - }, - [0x1330E]={ - category="lo", - direction="l", - }, - [0x1330F]={ - category="lo", - direction="l", - }, - [0x13310]={ - category="lo", - direction="l", - }, - [0x13311]={ - category="lo", - direction="l", - }, - [0x13312]={ - category="lo", - direction="l", - }, - [0x13313]={ - category="lo", - direction="l", - }, - [0x13314]={ - category="lo", - direction="l", - }, - [0x13315]={ - category="lo", - direction="l", - }, - [0x13316]={ - category="lo", - direction="l", - }, - [0x13317]={ - category="lo", - direction="l", - }, - [0x13318]={ - category="lo", - direction="l", - }, - [0x13319]={ - category="lo", - direction="l", - }, - [0x1331A]={ - category="lo", - direction="l", - }, - [0x1331B]={ - category="lo", - direction="l", - }, - [0x1331C]={ - category="lo", - direction="l", - }, - [0x1331D]={ - category="lo", - direction="l", - }, - [0x1331E]={ - category="lo", - direction="l", - }, - [0x1331F]={ - category="lo", - direction="l", - }, - [0x13320]={ - category="lo", - direction="l", - }, - [0x13321]={ - category="lo", - direction="l", - }, - [0x13322]={ - category="lo", - direction="l", - }, - [0x13323]={ - category="lo", - direction="l", - }, - [0x13324]={ - category="lo", - direction="l", - }, - [0x13325]={ - category="lo", - direction="l", - }, - [0x13326]={ - category="lo", - direction="l", - }, - [0x13327]={ - category="lo", - direction="l", - }, - [0x13328]={ - category="lo", - direction="l", - }, - [0x13329]={ - category="lo", - direction="l", - }, - [0x1332A]={ - category="lo", - direction="l", - }, - [0x1332B]={ - category="lo", - direction="l", - }, - [0x1332C]={ - category="lo", - direction="l", - }, - [0x1332D]={ - category="lo", - direction="l", - }, - [0x1332E]={ - category="lo", - direction="l", - }, - [0x1332F]={ - category="lo", - direction="l", - }, - [0x13330]={ - category="lo", - direction="l", - }, - [0x13331]={ - category="lo", - direction="l", - }, - [0x13332]={ - category="lo", - direction="l", - }, - [0x13333]={ - category="lo", - direction="l", - }, - [0x13334]={ - category="lo", - direction="l", - }, - [0x13335]={ - category="lo", - direction="l", - }, - [0x13336]={ - category="lo", - direction="l", - }, - [0x13337]={ - category="lo", - direction="l", - }, - [0x13338]={ - category="lo", - direction="l", - }, - [0x13339]={ - category="lo", - direction="l", - }, - [0x1333A]={ - category="lo", - direction="l", - }, - [0x1333B]={ - category="lo", - direction="l", - }, - [0x1333C]={ - category="lo", - direction="l", - }, - [0x1333D]={ - category="lo", - direction="l", - }, - [0x1333E]={ - category="lo", - direction="l", - }, - [0x1333F]={ - category="lo", - direction="l", - }, - [0x13340]={ - category="lo", - direction="l", - }, - [0x13341]={ - category="lo", - direction="l", - }, - [0x13342]={ - category="lo", - direction="l", - }, - [0x13343]={ - category="lo", - direction="l", - }, - [0x13344]={ - category="lo", - direction="l", - }, - [0x13345]={ - category="lo", - direction="l", - }, - [0x13346]={ - category="lo", - direction="l", - }, - [0x13347]={ - category="lo", - direction="l", - }, - [0x13348]={ - category="lo", - direction="l", - }, - [0x13349]={ - category="lo", - direction="l", - }, - [0x1334A]={ - category="lo", - direction="l", - }, - [0x1334B]={ - category="lo", - direction="l", - }, - [0x1334C]={ - category="lo", - direction="l", - }, - [0x1334D]={ - category="lo", - direction="l", - }, - [0x1334E]={ - category="lo", - direction="l", - }, - [0x1334F]={ - category="lo", - direction="l", - }, - [0x13350]={ - category="lo", - direction="l", - }, - [0x13351]={ - category="lo", - direction="l", - }, - [0x13352]={ - category="lo", - direction="l", - }, - [0x13353]={ - category="lo", - direction="l", - }, - [0x13354]={ - category="lo", - direction="l", - }, - [0x13355]={ - category="lo", - direction="l", - }, - [0x13356]={ - category="lo", - direction="l", - }, - [0x13357]={ - category="lo", - direction="l", - }, - [0x13358]={ - category="lo", - direction="l", - }, - [0x13359]={ - category="lo", - direction="l", - }, - [0x1335A]={ - category="lo", - direction="l", - }, - [0x1335B]={ - category="lo", - direction="l", - }, - [0x1335C]={ - category="lo", - direction="l", - }, - [0x1335D]={ - category="lo", - direction="l", - }, - [0x1335E]={ - category="lo", - direction="l", - }, - [0x1335F]={ - category="lo", - direction="l", - }, - [0x13360]={ - category="lo", - direction="l", - }, - [0x13361]={ - category="lo", - direction="l", - }, - [0x13362]={ - category="lo", - direction="l", - }, - [0x13363]={ - category="lo", - direction="l", - }, - [0x13364]={ - category="lo", - direction="l", - }, - [0x13365]={ - category="lo", - direction="l", - }, - [0x13366]={ - category="lo", - direction="l", - }, - [0x13367]={ - category="lo", - direction="l", - }, - [0x13368]={ - category="lo", - direction="l", - }, - [0x13369]={ - category="lo", - direction="l", - }, - [0x1336A]={ - category="lo", - direction="l", - }, - [0x1336B]={ - category="lo", - direction="l", - }, - [0x1336C]={ - category="lo", - direction="l", - }, - [0x1336D]={ - category="lo", - direction="l", - }, - [0x1336E]={ - category="lo", - direction="l", - }, - [0x1336F]={ - category="lo", - direction="l", - }, - [0x13370]={ - category="lo", - direction="l", - }, - [0x13371]={ - category="lo", - direction="l", - }, - [0x13372]={ - category="lo", - direction="l", - }, - [0x13373]={ - category="lo", - direction="l", - }, - [0x13374]={ - category="lo", - direction="l", - }, - [0x13375]={ - category="lo", - direction="l", - }, - [0x13376]={ - category="lo", - direction="l", - }, - [0x13377]={ - category="lo", - direction="l", - }, - [0x13378]={ - category="lo", - direction="l", - }, - [0x13379]={ - category="lo", - direction="l", - }, - [0x1337A]={ - category="lo", - direction="l", - }, - [0x1337B]={ - category="lo", - direction="l", - }, - [0x1337C]={ - category="lo", - direction="l", - }, - [0x1337D]={ - category="lo", - direction="l", - }, - [0x1337E]={ - category="lo", - direction="l", - }, - [0x1337F]={ - category="lo", - direction="l", - }, - [0x13380]={ - category="lo", - direction="l", - }, - [0x13381]={ - category="lo", - direction="l", - }, - [0x13382]={ - category="lo", - direction="l", - }, - [0x13383]={ - category="lo", - direction="l", - }, - [0x13384]={ - category="lo", - direction="l", - }, - [0x13385]={ - category="lo", - direction="l", - }, - [0x13386]={ - category="lo", - direction="l", - }, - [0x13387]={ - category="lo", - direction="l", - }, - [0x13388]={ - category="lo", - direction="l", - }, - [0x13389]={ - category="lo", - direction="l", - }, - [0x1338A]={ - category="lo", - direction="l", - }, - [0x1338B]={ - category="lo", - direction="l", - }, - [0x1338C]={ - category="lo", - direction="l", - }, - [0x1338D]={ - category="lo", - direction="l", - }, - [0x1338E]={ - category="lo", - direction="l", - }, - [0x1338F]={ - category="lo", - direction="l", - }, - [0x13390]={ - category="lo", - direction="l", - }, - [0x13391]={ - category="lo", - direction="l", - }, - [0x13392]={ - category="lo", - direction="l", - }, - [0x13393]={ - category="lo", - direction="l", - }, - [0x13394]={ - category="lo", - direction="l", - }, - [0x13395]={ - category="lo", - direction="l", - }, - [0x13396]={ - category="lo", - direction="l", - }, - [0x13397]={ - category="lo", - direction="l", - }, - [0x13398]={ - category="lo", - direction="l", - }, - [0x13399]={ - category="lo", - direction="l", - }, - [0x1339A]={ - category="lo", - direction="l", - }, - [0x1339B]={ - category="lo", - direction="l", - }, - [0x1339C]={ - category="lo", - direction="l", - }, - [0x1339D]={ - category="lo", - direction="l", - }, - [0x1339E]={ - category="lo", - direction="l", - }, - [0x1339F]={ - category="lo", - direction="l", - }, - [0x133A0]={ - category="lo", - direction="l", - }, - [0x133A1]={ - category="lo", - direction="l", - }, - [0x133A2]={ - category="lo", - direction="l", - }, - [0x133A3]={ - category="lo", - direction="l", - }, - [0x133A4]={ - category="lo", - direction="l", - }, - [0x133A5]={ - category="lo", - direction="l", - }, - [0x133A6]={ - category="lo", - direction="l", - }, - [0x133A7]={ - category="lo", - direction="l", - }, - [0x133A8]={ - category="lo", - direction="l", - }, - [0x133A9]={ - category="lo", - direction="l", - }, - [0x133AA]={ - category="lo", - direction="l", - }, - [0x133AB]={ - category="lo", - direction="l", - }, - [0x133AC]={ - category="lo", - direction="l", - }, - [0x133AD]={ - category="lo", - direction="l", - }, - [0x133AE]={ - category="lo", - direction="l", - }, - [0x133AF]={ - category="lo", - direction="l", - }, - [0x133B0]={ - category="lo", - direction="l", - }, - [0x133B1]={ - category="lo", - direction="l", - }, - [0x133B2]={ - category="lo", - direction="l", - }, - [0x133B3]={ - category="lo", - direction="l", - }, - [0x133B4]={ - category="lo", - direction="l", - }, - [0x133B5]={ - category="lo", - direction="l", - }, - [0x133B6]={ - category="lo", - direction="l", - }, - [0x133B7]={ - category="lo", - direction="l", - }, - [0x133B8]={ - category="lo", - direction="l", - }, - [0x133B9]={ - category="lo", - direction="l", - }, - [0x133BA]={ - category="lo", - direction="l", - }, - [0x133BB]={ - category="lo", - direction="l", - }, - [0x133BC]={ - category="lo", - direction="l", - }, - [0x133BD]={ - category="lo", - direction="l", - }, - [0x133BE]={ - category="lo", - direction="l", - }, - [0x133BF]={ - category="lo", - direction="l", - }, - [0x133C0]={ - category="lo", - direction="l", - }, - [0x133C1]={ - category="lo", - direction="l", - }, - [0x133C2]={ - category="lo", - direction="l", - }, - [0x133C3]={ - category="lo", - direction="l", - }, - [0x133C4]={ - category="lo", - direction="l", - }, - [0x133C5]={ - category="lo", - direction="l", - }, - [0x133C6]={ - category="lo", - direction="l", - }, - [0x133C7]={ - category="lo", - direction="l", - }, - [0x133C8]={ - category="lo", - direction="l", - }, - [0x133C9]={ - category="lo", - direction="l", - }, - [0x133CA]={ - category="lo", - direction="l", - }, - [0x133CB]={ - category="lo", - direction="l", - }, - [0x133CC]={ - category="lo", - direction="l", - }, - [0x133CD]={ - category="lo", - direction="l", - }, - [0x133CE]={ - category="lo", - direction="l", - }, - [0x133CF]={ - category="lo", - direction="l", - }, - [0x133D0]={ - category="lo", - direction="l", - }, - [0x133D1]={ - category="lo", - direction="l", - }, - [0x133D2]={ - category="lo", - direction="l", - }, - [0x133D3]={ - category="lo", - direction="l", - }, - [0x133D4]={ - category="lo", - direction="l", - }, - [0x133D5]={ - category="lo", - direction="l", - }, - [0x133D6]={ - category="lo", - direction="l", - }, - [0x133D7]={ - category="lo", - direction="l", - }, - [0x133D8]={ - category="lo", - direction="l", - }, - [0x133D9]={ - category="lo", - direction="l", - }, - [0x133DA]={ - category="lo", - direction="l", - }, - [0x133DB]={ - category="lo", - direction="l", - }, - [0x133DC]={ - category="lo", - direction="l", - }, - [0x133DD]={ - category="lo", - direction="l", - }, - [0x133DE]={ - category="lo", - direction="l", - }, - [0x133DF]={ - category="lo", - direction="l", - }, - [0x133E0]={ - category="lo", - direction="l", - }, - [0x133E1]={ - category="lo", - direction="l", - }, - [0x133E2]={ - category="lo", - direction="l", - }, - [0x133E3]={ - category="lo", - direction="l", - }, - [0x133E4]={ - category="lo", - direction="l", - }, - [0x133E5]={ - category="lo", - direction="l", - }, - [0x133E6]={ - category="lo", - direction="l", - }, - [0x133E7]={ - category="lo", - direction="l", - }, - [0x133E8]={ - category="lo", - direction="l", - }, - [0x133E9]={ - category="lo", - direction="l", - }, - [0x133EA]={ - category="lo", - direction="l", - }, - [0x133EB]={ - category="lo", - direction="l", - }, - [0x133EC]={ - category="lo", - direction="l", - }, - [0x133ED]={ - category="lo", - direction="l", - }, - [0x133EE]={ - category="lo", - direction="l", - }, - [0x133EF]={ - category="lo", - direction="l", - }, - [0x133F0]={ - category="lo", - direction="l", - }, - [0x133F1]={ - category="lo", - direction="l", - }, - [0x133F2]={ - category="lo", - direction="l", - }, - [0x133F3]={ - category="lo", - direction="l", - }, - [0x133F4]={ - category="lo", - direction="l", - }, - [0x133F5]={ - category="lo", - direction="l", - }, - [0x133F6]={ - category="lo", - direction="l", - }, - [0x133F7]={ - category="lo", - direction="l", - }, - [0x133F8]={ - category="lo", - direction="l", - }, - [0x133F9]={ - category="lo", - direction="l", - }, - [0x133FA]={ - category="lo", - direction="l", - }, - [0x133FB]={ - category="lo", - direction="l", - }, - [0x133FC]={ - category="lo", - direction="l", - }, - [0x133FD]={ - category="lo", - direction="l", - }, - [0x133FE]={ - category="lo", - direction="l", - }, - [0x133FF]={ - category="lo", - direction="l", - }, - [0x13400]={ - category="lo", - direction="l", - }, - [0x13401]={ - category="lo", - direction="l", - }, - [0x13402]={ - category="lo", - direction="l", - }, - [0x13403]={ - category="lo", - direction="l", - }, - [0x13404]={ - category="lo", - direction="l", - }, - [0x13405]={ - category="lo", - direction="l", - }, - [0x13406]={ - category="lo", - direction="l", - }, - [0x13407]={ - category="lo", - direction="l", - }, - [0x13408]={ - category="lo", - direction="l", - }, - [0x13409]={ - category="lo", - direction="l", - }, - [0x1340A]={ - category="lo", - direction="l", - }, - [0x1340B]={ - category="lo", - direction="l", - }, - [0x1340C]={ - category="lo", - direction="l", - }, - [0x1340D]={ - category="lo", - direction="l", - }, - [0x1340E]={ - category="lo", - direction="l", - }, - [0x1340F]={ - category="lo", - direction="l", - }, - [0x13410]={ - category="lo", - direction="l", - }, - [0x13411]={ - category="lo", - direction="l", - }, - [0x13412]={ - category="lo", - direction="l", - }, - [0x13413]={ - category="lo", - direction="l", - }, - [0x13414]={ - category="lo", - direction="l", - }, - [0x13415]={ - category="lo", - direction="l", - }, - [0x13416]={ - category="lo", - direction="l", - }, - [0x13417]={ - category="lo", - direction="l", - }, - [0x13418]={ - category="lo", - direction="l", - }, - [0x13419]={ - category="lo", - direction="l", - }, - [0x1341A]={ - category="lo", - direction="l", - }, - [0x1341B]={ - category="lo", - direction="l", - }, - [0x1341C]={ - category="lo", - direction="l", - }, - [0x1341D]={ - category="lo", - direction="l", - }, - [0x1341E]={ - category="lo", - direction="l", - }, - [0x1341F]={ - category="lo", - direction="l", - }, - [0x13420]={ - category="lo", - direction="l", - }, - [0x13421]={ - category="lo", - direction="l", - }, - [0x13422]={ - category="lo", - direction="l", - }, - [0x13423]={ - category="lo", - direction="l", - }, - [0x13424]={ - category="lo", - direction="l", - }, - [0x13425]={ - category="lo", - direction="l", - }, - [0x13426]={ - category="lo", - direction="l", - }, - [0x13427]={ - category="lo", - direction="l", - }, - [0x13428]={ - category="lo", - direction="l", - }, - [0x13429]={ - category="lo", - direction="l", - }, - [0x1342A]={ - category="lo", - direction="l", - }, - [0x1342B]={ - category="lo", - direction="l", - }, - [0x1342C]={ - category="lo", - direction="l", - }, - [0x1342D]={ - category="lo", - direction="l", - }, - [0x1342E]={ - category="lo", - direction="l", - }, - [0x14400]={ - category="lo", - direction="l", - }, - [0x14401]={ - category="lo", - direction="l", - }, - [0x14402]={ - category="lo", - direction="l", - }, - [0x14403]={ - category="lo", - direction="l", - }, - [0x14404]={ - category="lo", - direction="l", - }, - [0x14405]={ - category="lo", - direction="l", - }, - [0x14406]={ - category="lo", - direction="l", - }, - [0x14407]={ - category="lo", - direction="l", - }, - [0x14408]={ - category="lo", - direction="l", - }, - [0x14409]={ - category="lo", - direction="l", - }, - [0x1440A]={ - category="lo", - direction="l", - }, - [0x1440B]={ - category="lo", - direction="l", - }, - [0x1440C]={ - category="lo", - direction="l", - }, - [0x1440D]={ - category="lo", - direction="l", - }, - [0x1440E]={ - category="lo", - direction="l", - }, - [0x1440F]={ - category="lo", - direction="l", - }, - [0x14410]={ - category="lo", - direction="l", - }, - [0x14411]={ - category="lo", - direction="l", - }, - [0x14412]={ - category="lo", - direction="l", - }, - [0x14413]={ - category="lo", - direction="l", - }, - [0x14414]={ - category="lo", - direction="l", - }, - [0x14415]={ - category="lo", - direction="l", - }, - [0x14416]={ - category="lo", - direction="l", - }, - [0x14417]={ - category="lo", - direction="l", - }, - [0x14418]={ - category="lo", - direction="l", - }, - [0x14419]={ - category="lo", - direction="l", - }, - [0x1441A]={ - category="lo", - direction="l", - }, - [0x1441B]={ - category="lo", - direction="l", - }, - [0x1441C]={ - category="lo", - direction="l", - }, - [0x1441D]={ - category="lo", - direction="l", - }, - [0x1441E]={ - category="lo", - direction="l", - }, - [0x1441F]={ - category="lo", - direction="l", - }, - [0x14420]={ - category="lo", - direction="l", - }, - [0x14421]={ - category="lo", - direction="l", - }, - [0x14422]={ - category="lo", - direction="l", - }, - [0x14423]={ - category="lo", - direction="l", - }, - [0x14424]={ - category="lo", - direction="l", - }, - [0x14425]={ - category="lo", - direction="l", - }, - [0x14426]={ - category="lo", - direction="l", - }, - [0x14427]={ - category="lo", - direction="l", - }, - [0x14428]={ - category="lo", - direction="l", - }, - [0x14429]={ - category="lo", - direction="l", - }, - [0x1442A]={ - category="lo", - direction="l", - }, - [0x1442B]={ - category="lo", - direction="l", - }, - [0x1442C]={ - category="lo", - direction="l", - }, - [0x1442D]={ - category="lo", - direction="l", - }, - [0x1442E]={ - category="lo", - direction="l", - }, - [0x1442F]={ - category="lo", - direction="l", - }, - [0x14430]={ - category="lo", - direction="l", - }, - [0x14431]={ - category="lo", - direction="l", - }, - [0x14432]={ - category="lo", - direction="l", - }, - [0x14433]={ - category="lo", - direction="l", - }, - [0x14434]={ - category="lo", - direction="l", - }, - [0x14435]={ - category="lo", - direction="l", - }, - [0x14436]={ - category="lo", - direction="l", - }, - [0x14437]={ - category="lo", - direction="l", - }, - [0x14438]={ - category="lo", - direction="l", - }, - [0x14439]={ - category="lo", - direction="l", - }, - [0x1443A]={ - category="lo", - direction="l", - }, - [0x1443B]={ - category="lo", - direction="l", - }, - [0x1443C]={ - category="lo", - direction="l", - }, - [0x1443D]={ - category="lo", - direction="l", - }, - [0x1443E]={ - category="lo", - direction="l", - }, - [0x1443F]={ - category="lo", - direction="l", - }, - [0x14440]={ - category="lo", - direction="l", - }, - [0x14441]={ - category="lo", - direction="l", - }, - [0x14442]={ - category="lo", - direction="l", - }, - [0x14443]={ - category="lo", - direction="l", - }, - [0x14444]={ - category="lo", - direction="l", - }, - [0x14445]={ - category="lo", - direction="l", - }, - [0x14446]={ - category="lo", - direction="l", - }, - [0x14447]={ - category="lo", - direction="l", - }, - [0x14448]={ - category="lo", - direction="l", - }, - [0x14449]={ - category="lo", - direction="l", - }, - [0x1444A]={ - category="lo", - direction="l", - }, - [0x1444B]={ - category="lo", - direction="l", - }, - [0x1444C]={ - category="lo", - direction="l", - }, - [0x1444D]={ - category="lo", - direction="l", - }, - [0x1444E]={ - category="lo", - direction="l", - }, - [0x1444F]={ - category="lo", - direction="l", - }, - [0x14450]={ - category="lo", - direction="l", - }, - [0x14451]={ - category="lo", - direction="l", - }, - [0x14452]={ - category="lo", - direction="l", - }, - [0x14453]={ - category="lo", - direction="l", - }, - [0x14454]={ - category="lo", - direction="l", - }, - [0x14455]={ - category="lo", - direction="l", - }, - [0x14456]={ - category="lo", - direction="l", - }, - [0x14457]={ - category="lo", - direction="l", - }, - [0x14458]={ - category="lo", - direction="l", - }, - [0x14459]={ - category="lo", - direction="l", - }, - [0x1445A]={ - category="lo", - direction="l", - }, - [0x1445B]={ - category="lo", - direction="l", - }, - [0x1445C]={ - category="lo", - direction="l", - }, - [0x1445D]={ - category="lo", - direction="l", - }, - [0x1445E]={ - category="lo", - direction="l", - }, - [0x1445F]={ - category="lo", - direction="l", - }, - [0x14460]={ - category="lo", - direction="l", - }, - [0x14461]={ - category="lo", - direction="l", - }, - [0x14462]={ - category="lo", - direction="l", - }, - [0x14463]={ - category="lo", - direction="l", - }, - [0x14464]={ - category="lo", - direction="l", - }, - [0x14465]={ - category="lo", - direction="l", - }, - [0x14466]={ - category="lo", - direction="l", - }, - [0x14467]={ - category="lo", - direction="l", - }, - [0x14468]={ - category="lo", - direction="l", - }, - [0x14469]={ - category="lo", - direction="l", - }, - [0x1446A]={ - category="lo", - direction="l", - }, - [0x1446B]={ - category="lo", - direction="l", - }, - [0x1446C]={ - category="lo", - direction="l", - }, - [0x1446D]={ - category="lo", - direction="l", - }, - [0x1446E]={ - category="lo", - direction="l", - }, - [0x1446F]={ - category="lo", - direction="l", - }, - [0x14470]={ - category="lo", - direction="l", - }, - [0x14471]={ - category="lo", - direction="l", - }, - [0x14472]={ - category="lo", - direction="l", - }, - [0x14473]={ - category="lo", - direction="l", - }, - [0x14474]={ - category="lo", - direction="l", - }, - [0x14475]={ - category="lo", - direction="l", - }, - [0x14476]={ - category="lo", - direction="l", - }, - [0x14477]={ - category="lo", - direction="l", - }, - [0x14478]={ - category="lo", - direction="l", - }, - [0x14479]={ - category="lo", - direction="l", - }, - [0x1447A]={ - category="lo", - direction="l", - }, - [0x1447B]={ - category="lo", - direction="l", - }, - [0x1447C]={ - category="lo", - direction="l", - }, - [0x1447D]={ - category="lo", - direction="l", - }, - [0x1447E]={ - category="lo", - direction="l", - }, - [0x1447F]={ - category="lo", - direction="l", - }, - [0x14480]={ - category="lo", - direction="l", - }, - [0x14481]={ - category="lo", - direction="l", - }, - [0x14482]={ - category="lo", - direction="l", - }, - [0x14483]={ - category="lo", - direction="l", - }, - [0x14484]={ - category="lo", - direction="l", - }, - [0x14485]={ - category="lo", - direction="l", - }, - [0x14486]={ - category="lo", - direction="l", - }, - [0x14487]={ - category="lo", - direction="l", - }, - [0x14488]={ - category="lo", - direction="l", - }, - [0x14489]={ - category="lo", - direction="l", - }, - [0x1448A]={ - category="lo", - direction="l", - }, - [0x1448B]={ - category="lo", - direction="l", - }, - [0x1448C]={ - category="lo", - direction="l", - }, - [0x1448D]={ - category="lo", - direction="l", - }, - [0x1448E]={ - category="lo", - direction="l", - }, - [0x1448F]={ - category="lo", - direction="l", - }, - [0x14490]={ - category="lo", - direction="l", - }, - [0x14491]={ - category="lo", - direction="l", - }, - [0x14492]={ - category="lo", - direction="l", - }, - [0x14493]={ - category="lo", - direction="l", - }, - [0x14494]={ - category="lo", - direction="l", - }, - [0x14495]={ - category="lo", - direction="l", - }, - [0x14496]={ - category="lo", - direction="l", - }, - [0x14497]={ - category="lo", - direction="l", - }, - [0x14498]={ - category="lo", - direction="l", - }, - [0x14499]={ - category="lo", - direction="l", - }, - [0x1449A]={ - category="lo", - direction="l", - }, - [0x1449B]={ - category="lo", - direction="l", - }, - [0x1449C]={ - category="lo", - direction="l", - }, - [0x1449D]={ - category="lo", - direction="l", - }, - [0x1449E]={ - category="lo", - direction="l", - }, - [0x1449F]={ - category="lo", - direction="l", - }, - [0x144A0]={ - category="lo", - direction="l", - }, - [0x144A1]={ - category="lo", - direction="l", - }, - [0x144A2]={ - category="lo", - direction="l", - }, - [0x144A3]={ - category="lo", - direction="l", - }, - [0x144A4]={ - category="lo", - direction="l", - }, - [0x144A5]={ - category="lo", - direction="l", - }, - [0x144A6]={ - category="lo", - direction="l", - }, - [0x144A7]={ - category="lo", - direction="l", - }, - [0x144A8]={ - category="lo", - direction="l", - }, - [0x144A9]={ - category="lo", - direction="l", - }, - [0x144AA]={ - category="lo", - direction="l", - }, - [0x144AB]={ - category="lo", - direction="l", - }, - [0x144AC]={ - category="lo", - direction="l", - }, - [0x144AD]={ - category="lo", - direction="l", - }, - [0x144AE]={ - category="lo", - direction="l", - }, - [0x144AF]={ - category="lo", - direction="l", - }, - [0x144B0]={ - category="lo", - direction="l", - }, - [0x144B1]={ - category="lo", - direction="l", - }, - [0x144B2]={ - category="lo", - direction="l", - }, - [0x144B3]={ - category="lo", - direction="l", - }, - [0x144B4]={ - category="lo", - direction="l", - }, - [0x144B5]={ - category="lo", - direction="l", - }, - [0x144B6]={ - category="lo", - direction="l", - }, - [0x144B7]={ - category="lo", - direction="l", - }, - [0x144B8]={ - category="lo", - direction="l", - }, - [0x144B9]={ - category="lo", - direction="l", - }, - [0x144BA]={ - category="lo", - direction="l", - }, - [0x144BB]={ - category="lo", - direction="l", - }, - [0x144BC]={ - category="lo", - direction="l", - }, - [0x144BD]={ - category="lo", - direction="l", - }, - [0x144BE]={ - category="lo", - direction="l", - }, - [0x144BF]={ - category="lo", - direction="l", - }, - [0x144C0]={ - category="lo", - direction="l", - }, - [0x144C1]={ - category="lo", - direction="l", - }, - [0x144C2]={ - category="lo", - direction="l", - }, - [0x144C3]={ - category="lo", - direction="l", - }, - [0x144C4]={ - category="lo", - direction="l", - }, - [0x144C5]={ - category="lo", - direction="l", - }, - [0x144C6]={ - category="lo", - direction="l", - }, - [0x144C7]={ - category="lo", - direction="l", - }, - [0x144C8]={ - category="lo", - direction="l", - }, - [0x144C9]={ - category="lo", - direction="l", - }, - [0x144CA]={ - category="lo", - direction="l", - }, - [0x144CB]={ - category="lo", - direction="l", - }, - [0x144CC]={ - category="lo", - direction="l", - }, - [0x144CD]={ - category="lo", - direction="l", - }, - [0x144CE]={ - category="lo", - direction="l", - }, - [0x144CF]={ - category="lo", - direction="l", - }, - [0x144D0]={ - category="lo", - direction="l", - }, - [0x144D1]={ - category="lo", - direction="l", - }, - [0x144D2]={ - category="lo", - direction="l", - }, - [0x144D3]={ - category="lo", - direction="l", - }, - [0x144D4]={ - category="lo", - direction="l", - }, - [0x144D5]={ - category="lo", - direction="l", - }, - [0x144D6]={ - category="lo", - direction="l", - }, - [0x144D7]={ - category="lo", - direction="l", - }, - [0x144D8]={ - category="lo", - direction="l", - }, - [0x144D9]={ - category="lo", - direction="l", - }, - [0x144DA]={ - category="lo", - direction="l", - }, - [0x144DB]={ - category="lo", - direction="l", - }, - [0x144DC]={ - category="lo", - direction="l", - }, - [0x144DD]={ - category="lo", - direction="l", - }, - [0x144DE]={ - category="lo", - direction="l", - }, - [0x144DF]={ - category="lo", - direction="l", - }, - [0x144E0]={ - category="lo", - direction="l", - }, - [0x144E1]={ - category="lo", - direction="l", - }, - [0x144E2]={ - category="lo", - direction="l", - }, - [0x144E3]={ - category="lo", - direction="l", - }, - [0x144E4]={ - category="lo", - direction="l", - }, - [0x144E5]={ - category="lo", - direction="l", - }, - [0x144E6]={ - category="lo", - direction="l", - }, - [0x144E7]={ - category="lo", - direction="l", - }, - [0x144E8]={ - category="lo", - direction="l", - }, - [0x144E9]={ - category="lo", - direction="l", - }, - [0x144EA]={ - category="lo", - direction="l", - }, - [0x144EB]={ - category="lo", - direction="l", - }, - [0x144EC]={ - category="lo", - direction="l", - }, - [0x144ED]={ - category="lo", - direction="l", - }, - [0x144EE]={ - category="lo", - direction="l", - }, - [0x144EF]={ - category="lo", - direction="l", - }, - [0x144F0]={ - category="lo", - direction="l", - }, - [0x144F1]={ - category="lo", - direction="l", - }, - [0x144F2]={ - category="lo", - direction="l", - }, - [0x144F3]={ - category="lo", - direction="l", - }, - [0x144F4]={ - category="lo", - direction="l", - }, - [0x144F5]={ - category="lo", - direction="l", - }, - [0x144F6]={ - category="lo", - direction="l", - }, - [0x144F7]={ - category="lo", - direction="l", - }, - [0x144F8]={ - category="lo", - direction="l", - }, - [0x144F9]={ - category="lo", - direction="l", - }, - [0x144FA]={ - category="lo", - direction="l", - }, - [0x144FB]={ - category="lo", - direction="l", - }, - [0x144FC]={ - category="lo", - direction="l", - }, - [0x144FD]={ - category="lo", - direction="l", - }, - [0x144FE]={ - category="lo", - direction="l", - }, - [0x144FF]={ - category="lo", - direction="l", - }, - [0x14500]={ - category="lo", - direction="l", - }, - [0x14501]={ - category="lo", - direction="l", - }, - [0x14502]={ - category="lo", - direction="l", - }, - [0x14503]={ - category="lo", - direction="l", - }, - [0x14504]={ - category="lo", - direction="l", - }, - [0x14505]={ - category="lo", - direction="l", - }, - [0x14506]={ - category="lo", - direction="l", - }, - [0x14507]={ - category="lo", - direction="l", - }, - [0x14508]={ - category="lo", - direction="l", - }, - [0x14509]={ - category="lo", - direction="l", - }, - [0x1450A]={ - category="lo", - direction="l", - }, - [0x1450B]={ - category="lo", - direction="l", - }, - [0x1450C]={ - category="lo", - direction="l", - }, - [0x1450D]={ - category="lo", - direction="l", - }, - [0x1450E]={ - category="lo", - direction="l", - }, - [0x1450F]={ - category="lo", - direction="l", - }, - [0x14510]={ - category="lo", - direction="l", - }, - [0x14511]={ - category="lo", - direction="l", - }, - [0x14512]={ - category="lo", - direction="l", - }, - [0x14513]={ - category="lo", - direction="l", - }, - [0x14514]={ - category="lo", - direction="l", - }, - [0x14515]={ - category="lo", - direction="l", - }, - [0x14516]={ - category="lo", - direction="l", - }, - [0x14517]={ - category="lo", - direction="l", - }, - [0x14518]={ - category="lo", - direction="l", - }, - [0x14519]={ - category="lo", - direction="l", - }, - [0x1451A]={ - category="lo", - direction="l", - }, - [0x1451B]={ - category="lo", - direction="l", - }, - [0x1451C]={ - category="lo", - direction="l", - }, - [0x1451D]={ - category="lo", - direction="l", - }, - [0x1451E]={ - category="lo", - direction="l", - }, - [0x1451F]={ - category="lo", - direction="l", - }, - [0x14520]={ - category="lo", - direction="l", - }, - [0x14521]={ - category="lo", - direction="l", - }, - [0x14522]={ - category="lo", - direction="l", - }, - [0x14523]={ - category="lo", - direction="l", - }, - [0x14524]={ - category="lo", - direction="l", - }, - [0x14525]={ - category="lo", - direction="l", - }, - [0x14526]={ - category="lo", - direction="l", - }, - [0x14527]={ - category="lo", - direction="l", - }, - [0x14528]={ - category="lo", - direction="l", - }, - [0x14529]={ - category="lo", - direction="l", - }, - [0x1452A]={ - category="lo", - direction="l", - }, - [0x1452B]={ - category="lo", - direction="l", - }, - [0x1452C]={ - category="lo", - direction="l", - }, - [0x1452D]={ - category="lo", - direction="l", - }, - [0x1452E]={ - category="lo", - direction="l", - }, - [0x1452F]={ - category="lo", - direction="l", - }, - [0x14530]={ - category="lo", - direction="l", - }, - [0x14531]={ - category="lo", - direction="l", - }, - [0x14532]={ - category="lo", - direction="l", - }, - [0x14533]={ - category="lo", - direction="l", - }, - [0x14534]={ - category="lo", - direction="l", - }, - [0x14535]={ - category="lo", - direction="l", - }, - [0x14536]={ - category="lo", - direction="l", - }, - [0x14537]={ - category="lo", - direction="l", - }, - [0x14538]={ - category="lo", - direction="l", - }, - [0x14539]={ - category="lo", - direction="l", - }, - [0x1453A]={ - category="lo", - direction="l", - }, - [0x1453B]={ - category="lo", - direction="l", - }, - [0x1453C]={ - category="lo", - direction="l", - }, - [0x1453D]={ - category="lo", - direction="l", - }, - [0x1453E]={ - category="lo", - direction="l", - }, - [0x1453F]={ - category="lo", - direction="l", - }, - [0x14540]={ - category="lo", - direction="l", - }, - [0x14541]={ - category="lo", - direction="l", - }, - [0x14542]={ - category="lo", - direction="l", - }, - [0x14543]={ - category="lo", - direction="l", - }, - [0x14544]={ - category="lo", - direction="l", - }, - [0x14545]={ - category="lo", - direction="l", - }, - [0x14546]={ - category="lo", - direction="l", - }, - [0x14547]={ - category="lo", - direction="l", - }, - [0x14548]={ - category="lo", - direction="l", - }, - [0x14549]={ - category="lo", - direction="l", - }, - [0x1454A]={ - category="lo", - direction="l", - }, - [0x1454B]={ - category="lo", - direction="l", - }, - [0x1454C]={ - category="lo", - direction="l", - }, - [0x1454D]={ - category="lo", - direction="l", - }, - [0x1454E]={ - category="lo", - direction="l", - }, - [0x1454F]={ - category="lo", - direction="l", - }, - [0x14550]={ - category="lo", - direction="l", - }, - [0x14551]={ - category="lo", - direction="l", - }, - [0x14552]={ - category="lo", - direction="l", - }, - [0x14553]={ - category="lo", - direction="l", - }, - [0x14554]={ - category="lo", - direction="l", - }, - [0x14555]={ - category="lo", - direction="l", - }, - [0x14556]={ - category="lo", - direction="l", - }, - [0x14557]={ - category="lo", - direction="l", - }, - [0x14558]={ - category="lo", - direction="l", - }, - [0x14559]={ - category="lo", - direction="l", - }, - [0x1455A]={ - category="lo", - direction="l", - }, - [0x1455B]={ - category="lo", - direction="l", - }, - [0x1455C]={ - category="lo", - direction="l", - }, - [0x1455D]={ - category="lo", - direction="l", - }, - [0x1455E]={ - category="lo", - direction="l", - }, - [0x1455F]={ - category="lo", - direction="l", - }, - [0x14560]={ - category="lo", - direction="l", - }, - [0x14561]={ - category="lo", - direction="l", - }, - [0x14562]={ - category="lo", - direction="l", - }, - [0x14563]={ - category="lo", - direction="l", - }, - [0x14564]={ - category="lo", - direction="l", - }, - [0x14565]={ - category="lo", - direction="l", - }, - [0x14566]={ - category="lo", - direction="l", - }, - [0x14567]={ - category="lo", - direction="l", - }, - [0x14568]={ - category="lo", - direction="l", - }, - [0x14569]={ - category="lo", - direction="l", - }, - [0x1456A]={ - category="lo", - direction="l", - }, - [0x1456B]={ - category="lo", - direction="l", - }, - [0x1456C]={ - category="lo", - direction="l", - }, - [0x1456D]={ - category="lo", - direction="l", - }, - [0x1456E]={ - category="lo", - direction="l", - }, - [0x1456F]={ - category="lo", - direction="l", - }, - [0x14570]={ - category="lo", - direction="l", - }, - [0x14571]={ - category="lo", - direction="l", - }, - [0x14572]={ - category="lo", - direction="l", - }, - [0x14573]={ - category="lo", - direction="l", - }, - [0x14574]={ - category="lo", - direction="l", - }, - [0x14575]={ - category="lo", - direction="l", - }, - [0x14576]={ - category="lo", - direction="l", - }, - [0x14577]={ - category="lo", - direction="l", - }, - [0x14578]={ - category="lo", - direction="l", - }, - [0x14579]={ - category="lo", - direction="l", - }, - [0x1457A]={ - category="lo", - direction="l", - }, - [0x1457B]={ - category="lo", - direction="l", - }, - [0x1457C]={ - category="lo", - direction="l", - }, - [0x1457D]={ - category="lo", - direction="l", - }, - [0x1457E]={ - category="lo", - direction="l", - }, - [0x1457F]={ - category="lo", - direction="l", - }, - [0x14580]={ - category="lo", - direction="l", - }, - [0x14581]={ - category="lo", - direction="l", - }, - [0x14582]={ - category="lo", - direction="l", - }, - [0x14583]={ - category="lo", - direction="l", - }, - [0x14584]={ - category="lo", - direction="l", - }, - [0x14585]={ - category="lo", - direction="l", - }, - [0x14586]={ - category="lo", - direction="l", - }, - [0x14587]={ - category="lo", - direction="l", - }, - [0x14588]={ - category="lo", - direction="l", - }, - [0x14589]={ - category="lo", - direction="l", - }, - [0x1458A]={ - category="lo", - direction="l", - }, - [0x1458B]={ - category="lo", - direction="l", - }, - [0x1458C]={ - category="lo", - direction="l", - }, - [0x1458D]={ - category="lo", - direction="l", - }, - [0x1458E]={ - category="lo", - direction="l", - }, - [0x1458F]={ - category="lo", - direction="l", - }, - [0x14590]={ - category="lo", - direction="l", - }, - [0x14591]={ - category="lo", - direction="l", - }, - [0x14592]={ - category="lo", - direction="l", - }, - [0x14593]={ - category="lo", - direction="l", - }, - [0x14594]={ - category="lo", - direction="l", - }, - [0x14595]={ - category="lo", - direction="l", - }, - [0x14596]={ - category="lo", - direction="l", - }, - [0x14597]={ - category="lo", - direction="l", - }, - [0x14598]={ - category="lo", - direction="l", - }, - [0x14599]={ - category="lo", - direction="l", - }, - [0x1459A]={ - category="lo", - direction="l", - }, - [0x1459B]={ - category="lo", - direction="l", - }, - [0x1459C]={ - category="lo", - direction="l", - }, - [0x1459D]={ - category="lo", - direction="l", - }, - [0x1459E]={ - category="lo", - direction="l", - }, - [0x1459F]={ - category="lo", - direction="l", - }, - [0x145A0]={ - category="lo", - direction="l", - }, - [0x145A1]={ - category="lo", - direction="l", - }, - [0x145A2]={ - category="lo", - direction="l", - }, - [0x145A3]={ - category="lo", - direction="l", - }, - [0x145A4]={ - category="lo", - direction="l", - }, - [0x145A5]={ - category="lo", - direction="l", - }, - [0x145A6]={ - category="lo", - direction="l", - }, - [0x145A7]={ - category="lo", - direction="l", - }, - [0x145A8]={ - category="lo", - direction="l", - }, - [0x145A9]={ - category="lo", - direction="l", - }, - [0x145AA]={ - category="lo", - direction="l", - }, - [0x145AB]={ - category="lo", - direction="l", - }, - [0x145AC]={ - category="lo", - direction="l", - }, - [0x145AD]={ - category="lo", - direction="l", - }, - [0x145AE]={ - category="lo", - direction="l", - }, - [0x145AF]={ - category="lo", - direction="l", - }, - [0x145B0]={ - category="lo", - direction="l", - }, - [0x145B1]={ - category="lo", - direction="l", - }, - [0x145B2]={ - category="lo", - direction="l", - }, - [0x145B3]={ - category="lo", - direction="l", - }, - [0x145B4]={ - category="lo", - direction="l", - }, - [0x145B5]={ - category="lo", - direction="l", - }, - [0x145B6]={ - category="lo", - direction="l", - }, - [0x145B7]={ - category="lo", - direction="l", - }, - [0x145B8]={ - category="lo", - direction="l", - }, - [0x145B9]={ - category="lo", - direction="l", - }, - [0x145BA]={ - category="lo", - direction="l", - }, - [0x145BB]={ - category="lo", - direction="l", - }, - [0x145BC]={ - category="lo", - direction="l", - }, - [0x145BD]={ - category="lo", - direction="l", - }, - [0x145BE]={ - category="lo", - direction="l", - }, - [0x145BF]={ - category="lo", - direction="l", - }, - [0x145C0]={ - category="lo", - direction="l", - }, - [0x145C1]={ - category="lo", - direction="l", - }, - [0x145C2]={ - category="lo", - direction="l", - }, - [0x145C3]={ - category="lo", - direction="l", - }, - [0x145C4]={ - category="lo", - direction="l", - }, - [0x145C5]={ - category="lo", - direction="l", - }, - [0x145C6]={ - category="lo", - direction="l", - }, - [0x145C7]={ - category="lo", - direction="l", - }, - [0x145C8]={ - category="lo", - direction="l", - }, - [0x145C9]={ - category="lo", - direction="l", - }, - [0x145CA]={ - category="lo", - direction="l", - }, - [0x145CB]={ - category="lo", - direction="l", - }, - [0x145CC]={ - category="lo", - direction="l", - }, - [0x145CD]={ - category="lo", - direction="l", - }, - [0x145CE]={ - category="lo", - direction="l", - }, - [0x145CF]={ - category="lo", - direction="l", - }, - [0x145D0]={ - category="lo", - direction="l", - }, - [0x145D1]={ - category="lo", - direction="l", - }, - [0x145D2]={ - category="lo", - direction="l", - }, - [0x145D3]={ - category="lo", - direction="l", - }, - [0x145D4]={ - category="lo", - direction="l", - }, - [0x145D5]={ - category="lo", - direction="l", - }, - [0x145D6]={ - category="lo", - direction="l", - }, - [0x145D7]={ - category="lo", - direction="l", - }, - [0x145D8]={ - category="lo", - direction="l", - }, - [0x145D9]={ - category="lo", - direction="l", - }, - [0x145DA]={ - category="lo", - direction="l", - }, - [0x145DB]={ - category="lo", - direction="l", - }, - [0x145DC]={ - category="lo", - direction="l", - }, - [0x145DD]={ - category="lo", - direction="l", - }, - [0x145DE]={ - category="lo", - direction="l", - }, - [0x145DF]={ - category="lo", - direction="l", - }, - [0x145E0]={ - category="lo", - direction="l", - }, - [0x145E1]={ - category="lo", - direction="l", - }, - [0x145E2]={ - category="lo", - direction="l", - }, - [0x145E3]={ - category="lo", - direction="l", - }, - [0x145E4]={ - category="lo", - direction="l", - }, - [0x145E5]={ - category="lo", - direction="l", - }, - [0x145E6]={ - category="lo", - direction="l", - }, - [0x145E7]={ - category="lo", - direction="l", - }, - [0x145E8]={ - category="lo", - direction="l", - }, - [0x145E9]={ - category="lo", - direction="l", - }, - [0x145EA]={ - category="lo", - direction="l", - }, - [0x145EB]={ - category="lo", - direction="l", - }, - [0x145EC]={ - category="lo", - direction="l", - }, - [0x145ED]={ - category="lo", - direction="l", - }, - [0x145EE]={ - category="lo", - direction="l", - }, - [0x145EF]={ - category="lo", - direction="l", - }, - [0x145F0]={ - category="lo", - direction="l", - }, - [0x145F1]={ - category="lo", - direction="l", - }, - [0x145F2]={ - category="lo", - direction="l", - }, - [0x145F3]={ - category="lo", - direction="l", - }, - [0x145F4]={ - category="lo", - direction="l", - }, - [0x145F5]={ - category="lo", - direction="l", - }, - [0x145F6]={ - category="lo", - direction="l", - }, - [0x145F7]={ - category="lo", - direction="l", - }, - [0x145F8]={ - category="lo", - direction="l", - }, - [0x145F9]={ - category="lo", - direction="l", - }, - [0x145FA]={ - category="lo", - direction="l", - }, - [0x145FB]={ - category="lo", - direction="l", - }, - [0x145FC]={ - category="lo", - direction="l", - }, - [0x145FD]={ - category="lo", - direction="l", - }, - [0x145FE]={ - category="lo", - direction="l", - }, - [0x145FF]={ - category="lo", - direction="l", - }, - [0x14600]={ - category="lo", - direction="l", - }, - [0x14601]={ - category="lo", - direction="l", - }, - [0x14602]={ - category="lo", - direction="l", - }, - [0x14603]={ - category="lo", - direction="l", - }, - [0x14604]={ - category="lo", - direction="l", - }, - [0x14605]={ - category="lo", - direction="l", - }, - [0x14606]={ - category="lo", - direction="l", - }, - [0x14607]={ - category="lo", - direction="l", - }, - [0x14608]={ - category="lo", - direction="l", - }, - [0x14609]={ - category="lo", - direction="l", - }, - [0x1460A]={ - category="lo", - direction="l", - }, - [0x1460B]={ - category="lo", - direction="l", - }, - [0x1460C]={ - category="lo", - direction="l", - }, - [0x1460D]={ - category="lo", - direction="l", - }, - [0x1460E]={ - category="lo", - direction="l", - }, - [0x1460F]={ - category="lo", - direction="l", - }, - [0x14610]={ - category="lo", - direction="l", - }, - [0x14611]={ - category="lo", - direction="l", - }, - [0x14612]={ - category="lo", - direction="l", - }, - [0x14613]={ - category="lo", - direction="l", - }, - [0x14614]={ - category="lo", - direction="l", - }, - [0x14615]={ - category="lo", - direction="l", - }, - [0x14616]={ - category="lo", - direction="l", - }, - [0x14617]={ - category="lo", - direction="l", - }, - [0x14618]={ - category="lo", - direction="l", - }, - [0x14619]={ - category="lo", - direction="l", - }, - [0x1461A]={ - category="lo", - direction="l", - }, - [0x1461B]={ - category="lo", - direction="l", - }, - [0x1461C]={ - category="lo", - direction="l", - }, - [0x1461D]={ - category="lo", - direction="l", - }, - [0x1461E]={ - category="lo", - direction="l", - }, - [0x1461F]={ - category="lo", - direction="l", - }, - [0x14620]={ - category="lo", - direction="l", - }, - [0x14621]={ - category="lo", - direction="l", - }, - [0x14622]={ - category="lo", - direction="l", - }, - [0x14623]={ - category="lo", - direction="l", - }, - [0x14624]={ - category="lo", - direction="l", - }, - [0x14625]={ - category="lo", - direction="l", - }, - [0x14626]={ - category="lo", - direction="l", - }, - [0x14627]={ - category="lo", - direction="l", - }, - [0x14628]={ - category="lo", - direction="l", - }, - [0x14629]={ - category="lo", - direction="l", - }, - [0x1462A]={ - category="lo", - direction="l", - }, - [0x1462B]={ - category="lo", - direction="l", - }, - [0x1462C]={ - category="lo", - direction="l", - }, - [0x1462D]={ - category="lo", - direction="l", - }, - [0x1462E]={ - category="lo", - direction="l", - }, - [0x1462F]={ - category="lo", - direction="l", - }, - [0x14630]={ - category="lo", - direction="l", - }, - [0x14631]={ - category="lo", - direction="l", - }, - [0x14632]={ - category="lo", - direction="l", - }, - [0x14633]={ - category="lo", - direction="l", - }, - [0x14634]={ - category="lo", - direction="l", - }, - [0x14635]={ - category="lo", - direction="l", - }, - [0x14636]={ - category="lo", - direction="l", - }, - [0x14637]={ - category="lo", - direction="l", - }, - [0x14638]={ - category="lo", - direction="l", - }, - [0x14639]={ - category="lo", - direction="l", - }, - [0x1463A]={ - category="lo", - direction="l", - }, - [0x1463B]={ - category="lo", - direction="l", - }, - [0x1463C]={ - category="lo", - direction="l", - }, - [0x1463D]={ - category="lo", - direction="l", - }, - [0x1463E]={ - category="lo", - direction="l", - }, - [0x1463F]={ - category="lo", - direction="l", - }, - [0x14640]={ - category="lo", - direction="l", - }, - [0x14641]={ - category="lo", - direction="l", - }, - [0x14642]={ - category="lo", - direction="l", - }, - [0x14643]={ - category="lo", - direction="l", - }, - [0x14644]={ - category="lo", - direction="l", - }, - [0x14645]={ - category="lo", - direction="l", - }, - [0x14646]={ - category="lo", - direction="l", - }, - [0x16800]={ - category="lo", - direction="l", - }, - [0x16801]={ - category="lo", - direction="l", - }, - [0x16802]={ - category="lo", - direction="l", - }, - [0x16803]={ - category="lo", - direction="l", - }, - [0x16804]={ - category="lo", - direction="l", - }, - [0x16805]={ - category="lo", - direction="l", - }, - [0x16806]={ - category="lo", - direction="l", - }, - [0x16807]={ - category="lo", - direction="l", - }, - [0x16808]={ - category="lo", - direction="l", - }, - [0x16809]={ - category="lo", - direction="l", - }, - [0x1680A]={ - category="lo", - direction="l", - }, - [0x1680B]={ - category="lo", - direction="l", - }, - [0x1680C]={ - category="lo", - direction="l", - }, - [0x1680D]={ - category="lo", - direction="l", - }, - [0x1680E]={ - category="lo", - direction="l", - }, - [0x1680F]={ - category="lo", - direction="l", - }, - [0x16810]={ - category="lo", - direction="l", - }, - [0x16811]={ - category="lo", - direction="l", - }, - [0x16812]={ - category="lo", - direction="l", - }, - [0x16813]={ - category="lo", - direction="l", - }, - [0x16814]={ - category="lo", - direction="l", - }, - [0x16815]={ - category="lo", - direction="l", - }, - [0x16816]={ - category="lo", - direction="l", - }, - [0x16817]={ - category="lo", - direction="l", - }, - [0x16818]={ - category="lo", - direction="l", - }, - [0x16819]={ - category="lo", - direction="l", - }, - [0x1681A]={ - category="lo", - direction="l", - }, - [0x1681B]={ - category="lo", - direction="l", - }, - [0x1681C]={ - category="lo", - direction="l", - }, - [0x1681D]={ - category="lo", - direction="l", - }, - [0x1681E]={ - category="lo", - direction="l", - }, - [0x1681F]={ - category="lo", - direction="l", - }, - [0x16820]={ - category="lo", - direction="l", - }, - [0x16821]={ - category="lo", - direction="l", - }, - [0x16822]={ - category="lo", - direction="l", - }, - [0x16823]={ - category="lo", - direction="l", - }, - [0x16824]={ - category="lo", - direction="l", - }, - [0x16825]={ - category="lo", - direction="l", - }, - [0x16826]={ - category="lo", - direction="l", - }, - [0x16827]={ - category="lo", - direction="l", - }, - [0x16828]={ - category="lo", - direction="l", - }, - [0x16829]={ - category="lo", - direction="l", - }, - [0x1682A]={ - category="lo", - direction="l", - }, - [0x1682B]={ - category="lo", - direction="l", - }, - [0x1682C]={ - category="lo", - direction="l", - }, - [0x1682D]={ - category="lo", - direction="l", - }, - [0x1682E]={ - category="lo", - direction="l", - }, - [0x1682F]={ - category="lo", - direction="l", - }, - [0x16830]={ - category="lo", - direction="l", - }, - [0x16831]={ - category="lo", - direction="l", - }, - [0x16832]={ - category="lo", - direction="l", - }, - [0x16833]={ - category="lo", - direction="l", - }, - [0x16834]={ - category="lo", - direction="l", - }, - [0x16835]={ - category="lo", - direction="l", - }, - [0x16836]={ - category="lo", - direction="l", - }, - [0x16837]={ - category="lo", - direction="l", - }, - [0x16838]={ - category="lo", - direction="l", - }, - [0x16839]={ - category="lo", - direction="l", - }, - [0x1683A]={ - category="lo", - direction="l", - }, - [0x1683B]={ - category="lo", - direction="l", - }, - [0x1683C]={ - category="lo", - direction="l", - }, - [0x1683D]={ - category="lo", - direction="l", - }, - [0x1683E]={ - category="lo", - direction="l", - }, - [0x1683F]={ - category="lo", - direction="l", - }, - [0x16840]={ - category="lo", - direction="l", - }, - [0x16841]={ - category="lo", - direction="l", - }, - [0x16842]={ - category="lo", - direction="l", - }, - [0x16843]={ - category="lo", - direction="l", - }, - [0x16844]={ - category="lo", - direction="l", - }, - [0x16845]={ - category="lo", - direction="l", - }, - [0x16846]={ - category="lo", - direction="l", - }, - [0x16847]={ - category="lo", - direction="l", - }, - [0x16848]={ - category="lo", - direction="l", - }, - [0x16849]={ - category="lo", - direction="l", - }, - [0x1684A]={ - category="lo", - direction="l", - }, - [0x1684B]={ - category="lo", - direction="l", - }, - [0x1684C]={ - category="lo", - direction="l", - }, - [0x1684D]={ - category="lo", - direction="l", - }, - [0x1684E]={ - category="lo", - direction="l", - }, - [0x1684F]={ - category="lo", - direction="l", - }, - [0x16850]={ - category="lo", - direction="l", - }, - [0x16851]={ - category="lo", - direction="l", - }, - [0x16852]={ - category="lo", - direction="l", - }, - [0x16853]={ - category="lo", - direction="l", - }, - [0x16854]={ - category="lo", - direction="l", - }, - [0x16855]={ - category="lo", - direction="l", - }, - [0x16856]={ - category="lo", - direction="l", - }, - [0x16857]={ - category="lo", - direction="l", - }, - [0x16858]={ - category="lo", - direction="l", - }, - [0x16859]={ - category="lo", - direction="l", - }, - [0x1685A]={ - category="lo", - direction="l", - }, - [0x1685B]={ - category="lo", - direction="l", - }, - [0x1685C]={ - category="lo", - direction="l", - }, - [0x1685D]={ - category="lo", - direction="l", - }, - [0x1685E]={ - category="lo", - direction="l", - }, - [0x1685F]={ - category="lo", - direction="l", - }, - [0x16860]={ - category="lo", - direction="l", - }, - [0x16861]={ - category="lo", - direction="l", - }, - [0x16862]={ - category="lo", - direction="l", - }, - [0x16863]={ - category="lo", - direction="l", - }, - [0x16864]={ - category="lo", - direction="l", - }, - [0x16865]={ - category="lo", - direction="l", - }, - [0x16866]={ - category="lo", - direction="l", - }, - [0x16867]={ - category="lo", - direction="l", - }, - [0x16868]={ - category="lo", - direction="l", - }, - [0x16869]={ - category="lo", - direction="l", - }, - [0x1686A]={ - category="lo", - direction="l", - }, - [0x1686B]={ - category="lo", - direction="l", - }, - [0x1686C]={ - category="lo", - direction="l", - }, - [0x1686D]={ - category="lo", - direction="l", - }, - [0x1686E]={ - category="lo", - direction="l", - }, - [0x1686F]={ - category="lo", - direction="l", - }, - [0x16870]={ - category="lo", - direction="l", - }, - [0x16871]={ - category="lo", - direction="l", - }, - [0x16872]={ - category="lo", - direction="l", - }, - [0x16873]={ - category="lo", - direction="l", - }, - [0x16874]={ - category="lo", - direction="l", - }, - [0x16875]={ - category="lo", - direction="l", - }, - [0x16876]={ - category="lo", - direction="l", - }, - [0x16877]={ - category="lo", - direction="l", - }, - [0x16878]={ - category="lo", - direction="l", - }, - [0x16879]={ - category="lo", - direction="l", - }, - [0x1687A]={ - category="lo", - direction="l", - }, - [0x1687B]={ - category="lo", - direction="l", - }, - [0x1687C]={ - category="lo", - direction="l", - }, - [0x1687D]={ - category="lo", - direction="l", - }, - [0x1687E]={ - category="lo", - direction="l", - }, - [0x1687F]={ - category="lo", - direction="l", - }, - [0x16880]={ - category="lo", - direction="l", - }, - [0x16881]={ - category="lo", - direction="l", - }, - [0x16882]={ - category="lo", - direction="l", - }, - [0x16883]={ - category="lo", - direction="l", - }, - [0x16884]={ - category="lo", - direction="l", - }, - [0x16885]={ - category="lo", - direction="l", - }, - [0x16886]={ - category="lo", - direction="l", - }, - [0x16887]={ - category="lo", - direction="l", - }, - [0x16888]={ - category="lo", - direction="l", - }, - [0x16889]={ - category="lo", - direction="l", - }, - [0x1688A]={ - category="lo", - direction="l", - }, - [0x1688B]={ - category="lo", - direction="l", - }, - [0x1688C]={ - category="lo", - direction="l", - }, - [0x1688D]={ - category="lo", - direction="l", - }, - [0x1688E]={ - category="lo", - direction="l", - }, - [0x1688F]={ - category="lo", - direction="l", - }, - [0x16890]={ - category="lo", - direction="l", - }, - [0x16891]={ - category="lo", - direction="l", - }, - [0x16892]={ - category="lo", - direction="l", - }, - [0x16893]={ - category="lo", - direction="l", - }, - [0x16894]={ - category="lo", - direction="l", - }, - [0x16895]={ - category="lo", - direction="l", - }, - [0x16896]={ - category="lo", - direction="l", - }, - [0x16897]={ - category="lo", - direction="l", - }, - [0x16898]={ - category="lo", - direction="l", - }, - [0x16899]={ - category="lo", - direction="l", - }, - [0x1689A]={ - category="lo", - direction="l", - }, - [0x1689B]={ - category="lo", - direction="l", - }, - [0x1689C]={ - category="lo", - direction="l", - }, - [0x1689D]={ - category="lo", - direction="l", - }, - [0x1689E]={ - category="lo", - direction="l", - }, - [0x1689F]={ - category="lo", - direction="l", - }, - [0x168A0]={ - category="lo", - direction="l", - }, - [0x168A1]={ - category="lo", - direction="l", - }, - [0x168A2]={ - category="lo", - direction="l", - }, - [0x168A3]={ - category="lo", - direction="l", - }, - [0x168A4]={ - category="lo", - direction="l", - }, - [0x168A5]={ - category="lo", - direction="l", - }, - [0x168A6]={ - category="lo", - direction="l", - }, - [0x168A7]={ - category="lo", - direction="l", - }, - [0x168A8]={ - category="lo", - direction="l", - }, - [0x168A9]={ - category="lo", - direction="l", - }, - [0x168AA]={ - category="lo", - direction="l", - }, - [0x168AB]={ - category="lo", - direction="l", - }, - [0x168AC]={ - category="lo", - direction="l", - }, - [0x168AD]={ - category="lo", - direction="l", - }, - [0x168AE]={ - category="lo", - direction="l", - }, - [0x168AF]={ - category="lo", - direction="l", - }, - [0x168B0]={ - category="lo", - direction="l", - }, - [0x168B1]={ - category="lo", - direction="l", - }, - [0x168B2]={ - category="lo", - direction="l", - }, - [0x168B3]={ - category="lo", - direction="l", - }, - [0x168B4]={ - category="lo", - direction="l", - }, - [0x168B5]={ - category="lo", - direction="l", - }, - [0x168B6]={ - category="lo", - direction="l", - }, - [0x168B7]={ - category="lo", - direction="l", - }, - [0x168B8]={ - category="lo", - direction="l", - }, - [0x168B9]={ - category="lo", - direction="l", - }, - [0x168BA]={ - category="lo", - direction="l", - }, - [0x168BB]={ - category="lo", - direction="l", - }, - [0x168BC]={ - category="lo", - direction="l", - }, - [0x168BD]={ - category="lo", - direction="l", - }, - [0x168BE]={ - category="lo", - direction="l", - }, - [0x168BF]={ - category="lo", - direction="l", - }, - [0x168C0]={ - category="lo", - direction="l", - }, - [0x168C1]={ - category="lo", - direction="l", - }, - [0x168C2]={ - category="lo", - direction="l", - }, - [0x168C3]={ - category="lo", - direction="l", - }, - [0x168C4]={ - category="lo", - direction="l", - }, - [0x168C5]={ - category="lo", - direction="l", - }, - [0x168C6]={ - category="lo", - direction="l", - }, - [0x168C7]={ - category="lo", - direction="l", - }, - [0x168C8]={ - category="lo", - direction="l", - }, - [0x168C9]={ - category="lo", - direction="l", - }, - [0x168CA]={ - category="lo", - direction="l", - }, - [0x168CB]={ - category="lo", - direction="l", - }, - [0x168CC]={ - category="lo", - direction="l", - }, - [0x168CD]={ - category="lo", - direction="l", - }, - [0x168CE]={ - category="lo", - direction="l", - }, - [0x168CF]={ - category="lo", - direction="l", - }, - [0x168D0]={ - category="lo", - direction="l", - }, - [0x168D1]={ - category="lo", - direction="l", - }, - [0x168D2]={ - category="lo", - direction="l", - }, - [0x168D3]={ - category="lo", - direction="l", - }, - [0x168D4]={ - category="lo", - direction="l", - }, - [0x168D5]={ - category="lo", - direction="l", - }, - [0x168D6]={ - category="lo", - direction="l", - }, - [0x168D7]={ - category="lo", - direction="l", - }, - [0x168D8]={ - category="lo", - direction="l", - }, - [0x168D9]={ - category="lo", - direction="l", - }, - [0x168DA]={ - category="lo", - direction="l", - }, - [0x168DB]={ - category="lo", - direction="l", - }, - [0x168DC]={ - category="lo", - direction="l", - }, - [0x168DD]={ - category="lo", - direction="l", - }, - [0x168DE]={ - category="lo", - direction="l", - }, - [0x168DF]={ - category="lo", - direction="l", - }, - [0x168E0]={ - category="lo", - direction="l", - }, - [0x168E1]={ - category="lo", - direction="l", - }, - [0x168E2]={ - category="lo", - direction="l", - }, - [0x168E3]={ - category="lo", - direction="l", - }, - [0x168E4]={ - category="lo", - direction="l", - }, - [0x168E5]={ - category="lo", - direction="l", - }, - [0x168E6]={ - category="lo", - direction="l", - }, - [0x168E7]={ - category="lo", - direction="l", - }, - [0x168E8]={ - category="lo", - direction="l", - }, - [0x168E9]={ - category="lo", - direction="l", - }, - [0x168EA]={ - category="lo", - direction="l", - }, - [0x168EB]={ - category="lo", - direction="l", - }, - [0x168EC]={ - category="lo", - direction="l", - }, - [0x168ED]={ - category="lo", - direction="l", - }, - [0x168EE]={ - category="lo", - direction="l", - }, - [0x168EF]={ - category="lo", - direction="l", - }, - [0x168F0]={ - category="lo", - direction="l", - }, - [0x168F1]={ - category="lo", - direction="l", - }, - [0x168F2]={ - category="lo", - direction="l", - }, - [0x168F3]={ - category="lo", - direction="l", - }, - [0x168F4]={ - category="lo", - direction="l", - }, - [0x168F5]={ - category="lo", - direction="l", - }, - [0x168F6]={ - category="lo", - direction="l", - }, - [0x168F7]={ - category="lo", - direction="l", - }, - [0x168F8]={ - category="lo", - direction="l", - }, - [0x168F9]={ - category="lo", - direction="l", - }, - [0x168FA]={ - category="lo", - direction="l", - }, - [0x168FB]={ - category="lo", - direction="l", - }, - [0x168FC]={ - category="lo", - direction="l", - }, - [0x168FD]={ - category="lo", - direction="l", - }, - [0x168FE]={ - category="lo", - direction="l", - }, - [0x168FF]={ - category="lo", - direction="l", - }, - [0x16900]={ - category="lo", - direction="l", - }, - [0x16901]={ - category="lo", - direction="l", - }, - [0x16902]={ - category="lo", - direction="l", - }, - [0x16903]={ - category="lo", - direction="l", - }, - [0x16904]={ - category="lo", - direction="l", - }, - [0x16905]={ - category="lo", - direction="l", - }, - [0x16906]={ - category="lo", - direction="l", - }, - [0x16907]={ - category="lo", - direction="l", - }, - [0x16908]={ - category="lo", - direction="l", - }, - [0x16909]={ - category="lo", - direction="l", - }, - [0x1690A]={ - category="lo", - direction="l", - }, - [0x1690B]={ - category="lo", - direction="l", - }, - [0x1690C]={ - category="lo", - direction="l", - }, - [0x1690D]={ - category="lo", - direction="l", - }, - [0x1690E]={ - category="lo", - direction="l", - }, - [0x1690F]={ - category="lo", - direction="l", - }, - [0x16910]={ - category="lo", - direction="l", - }, - [0x16911]={ - category="lo", - direction="l", - }, - [0x16912]={ - category="lo", - direction="l", - }, - [0x16913]={ - category="lo", - direction="l", - }, - [0x16914]={ - category="lo", - direction="l", - }, - [0x16915]={ - category="lo", - direction="l", - }, - [0x16916]={ - category="lo", - direction="l", - }, - [0x16917]={ - category="lo", - direction="l", - }, - [0x16918]={ - category="lo", - direction="l", - }, - [0x16919]={ - category="lo", - direction="l", - }, - [0x1691A]={ - category="lo", - direction="l", - }, - [0x1691B]={ - category="lo", - direction="l", - }, - [0x1691C]={ - category="lo", - direction="l", - }, - [0x1691D]={ - category="lo", - direction="l", - }, - [0x1691E]={ - category="lo", - direction="l", - }, - [0x1691F]={ - category="lo", - direction="l", - }, - [0x16920]={ - category="lo", - direction="l", - }, - [0x16921]={ - category="lo", - direction="l", - }, - [0x16922]={ - category="lo", - direction="l", - }, - [0x16923]={ - category="lo", - direction="l", - }, - [0x16924]={ - category="lo", - direction="l", - }, - [0x16925]={ - category="lo", - direction="l", - }, - [0x16926]={ - category="lo", - direction="l", - }, - [0x16927]={ - category="lo", - direction="l", - }, - [0x16928]={ - category="lo", - direction="l", - }, - [0x16929]={ - category="lo", - direction="l", - }, - [0x1692A]={ - category="lo", - direction="l", - }, - [0x1692B]={ - category="lo", - direction="l", - }, - [0x1692C]={ - category="lo", - direction="l", - }, - [0x1692D]={ - category="lo", - direction="l", - }, - [0x1692E]={ - category="lo", - direction="l", - }, - [0x1692F]={ - category="lo", - direction="l", - }, - [0x16930]={ - category="lo", - direction="l", - }, - [0x16931]={ - category="lo", - direction="l", - }, - [0x16932]={ - category="lo", - direction="l", - }, - [0x16933]={ - category="lo", - direction="l", - }, - [0x16934]={ - category="lo", - direction="l", - }, - [0x16935]={ - category="lo", - direction="l", - }, - [0x16936]={ - category="lo", - direction="l", - }, - [0x16937]={ - category="lo", - direction="l", - }, - [0x16938]={ - category="lo", - direction="l", - }, - [0x16939]={ - category="lo", - direction="l", - }, - [0x1693A]={ - category="lo", - direction="l", - }, - [0x1693B]={ - category="lo", - direction="l", - }, - [0x1693C]={ - category="lo", - direction="l", - }, - [0x1693D]={ - category="lo", - direction="l", - }, - [0x1693E]={ - category="lo", - direction="l", - }, - [0x1693F]={ - category="lo", - direction="l", - }, - [0x16940]={ - category="lo", - direction="l", - }, - [0x16941]={ - category="lo", - direction="l", - }, - [0x16942]={ - category="lo", - direction="l", - }, - [0x16943]={ - category="lo", - direction="l", - }, - [0x16944]={ - category="lo", - direction="l", - }, - [0x16945]={ - category="lo", - direction="l", - }, - [0x16946]={ - category="lo", - direction="l", - }, - [0x16947]={ - category="lo", - direction="l", - }, - [0x16948]={ - category="lo", - direction="l", - }, - [0x16949]={ - category="lo", - direction="l", - }, - [0x1694A]={ - category="lo", - direction="l", - }, - [0x1694B]={ - category="lo", - direction="l", - }, - [0x1694C]={ - category="lo", - direction="l", - }, - [0x1694D]={ - category="lo", - direction="l", - }, - [0x1694E]={ - category="lo", - direction="l", - }, - [0x1694F]={ - category="lo", - direction="l", - }, - [0x16950]={ - category="lo", - direction="l", - }, - [0x16951]={ - category="lo", - direction="l", - }, - [0x16952]={ - category="lo", - direction="l", - }, - [0x16953]={ - category="lo", - direction="l", - }, - [0x16954]={ - category="lo", - direction="l", - }, - [0x16955]={ - category="lo", - direction="l", - }, - [0x16956]={ - category="lo", - direction="l", - }, - [0x16957]={ - category="lo", - direction="l", - }, - [0x16958]={ - category="lo", - direction="l", - }, - [0x16959]={ - category="lo", - direction="l", - }, - [0x1695A]={ - category="lo", - direction="l", - }, - [0x1695B]={ - category="lo", - direction="l", - }, - [0x1695C]={ - category="lo", - direction="l", - }, - [0x1695D]={ - category="lo", - direction="l", - }, - [0x1695E]={ - category="lo", - direction="l", - }, - [0x1695F]={ - category="lo", - direction="l", - }, - [0x16960]={ - category="lo", - direction="l", - }, - [0x16961]={ - category="lo", - direction="l", - }, - [0x16962]={ - category="lo", - direction="l", - }, - [0x16963]={ - category="lo", - direction="l", - }, - [0x16964]={ - category="lo", - direction="l", - }, - [0x16965]={ - category="lo", - direction="l", - }, - [0x16966]={ - category="lo", - direction="l", - }, - [0x16967]={ - category="lo", - direction="l", - }, - [0x16968]={ - category="lo", - direction="l", - }, - [0x16969]={ - category="lo", - direction="l", - }, - [0x1696A]={ - category="lo", - direction="l", - }, - [0x1696B]={ - category="lo", - direction="l", - }, - [0x1696C]={ - category="lo", - direction="l", - }, - [0x1696D]={ - category="lo", - direction="l", - }, - [0x1696E]={ - category="lo", - direction="l", - }, - [0x1696F]={ - category="lo", - direction="l", - }, - [0x16970]={ - category="lo", - direction="l", - }, - [0x16971]={ - category="lo", - direction="l", - }, - [0x16972]={ - category="lo", - direction="l", - }, - [0x16973]={ - category="lo", - direction="l", - }, - [0x16974]={ - category="lo", - direction="l", - }, - [0x16975]={ - category="lo", - direction="l", - }, - [0x16976]={ - category="lo", - direction="l", - }, - [0x16977]={ - category="lo", - direction="l", - }, - [0x16978]={ - category="lo", - direction="l", - }, - [0x16979]={ - category="lo", - direction="l", - }, - [0x1697A]={ - category="lo", - direction="l", - }, - [0x1697B]={ - category="lo", - direction="l", - }, - [0x1697C]={ - category="lo", - direction="l", - }, - [0x1697D]={ - category="lo", - direction="l", - }, - [0x1697E]={ - category="lo", - direction="l", - }, - [0x1697F]={ - category="lo", - direction="l", - }, - [0x16980]={ - category="lo", - direction="l", - }, - [0x16981]={ - category="lo", - direction="l", - }, - [0x16982]={ - category="lo", - direction="l", - }, - [0x16983]={ - category="lo", - direction="l", - }, - [0x16984]={ - category="lo", - direction="l", - }, - [0x16985]={ - category="lo", - direction="l", - }, - [0x16986]={ - category="lo", - direction="l", - }, - [0x16987]={ - category="lo", - direction="l", - }, - [0x16988]={ - category="lo", - direction="l", - }, - [0x16989]={ - category="lo", - direction="l", - }, - [0x1698A]={ - category="lo", - direction="l", - }, - [0x1698B]={ - category="lo", - direction="l", - }, - [0x1698C]={ - category="lo", - direction="l", - }, - [0x1698D]={ - category="lo", - direction="l", - }, - [0x1698E]={ - category="lo", - direction="l", - }, - [0x1698F]={ - category="lo", - direction="l", - }, - [0x16990]={ - category="lo", - direction="l", - }, - [0x16991]={ - category="lo", - direction="l", - }, - [0x16992]={ - category="lo", - direction="l", - }, - [0x16993]={ - category="lo", - direction="l", - }, - [0x16994]={ - category="lo", - direction="l", - }, - [0x16995]={ - category="lo", - direction="l", - }, - [0x16996]={ - category="lo", - direction="l", - }, - [0x16997]={ - category="lo", - direction="l", - }, - [0x16998]={ - category="lo", - direction="l", - }, - [0x16999]={ - category="lo", - direction="l", - }, - [0x1699A]={ - category="lo", - direction="l", - }, - [0x1699B]={ - category="lo", - direction="l", - }, - [0x1699C]={ - category="lo", - direction="l", - }, - [0x1699D]={ - category="lo", - direction="l", - }, - [0x1699E]={ - category="lo", - direction="l", - }, - [0x1699F]={ - category="lo", - direction="l", - }, - [0x169A0]={ - category="lo", - direction="l", - }, - [0x169A1]={ - category="lo", - direction="l", - }, - [0x169A2]={ - category="lo", - direction="l", - }, - [0x169A3]={ - category="lo", - direction="l", - }, - [0x169A4]={ - category="lo", - direction="l", - }, - [0x169A5]={ - category="lo", - direction="l", - }, - [0x169A6]={ - category="lo", - direction="l", - }, - [0x169A7]={ - category="lo", - direction="l", - }, - [0x169A8]={ - category="lo", - direction="l", - }, - [0x169A9]={ - category="lo", - direction="l", - }, - [0x169AA]={ - category="lo", - direction="l", - }, - [0x169AB]={ - category="lo", - direction="l", - }, - [0x169AC]={ - category="lo", - direction="l", - }, - [0x169AD]={ - category="lo", - direction="l", - }, - [0x169AE]={ - category="lo", - direction="l", - }, - [0x169AF]={ - category="lo", - direction="l", - }, - [0x169B0]={ - category="lo", - direction="l", - }, - [0x169B1]={ - category="lo", - direction="l", - }, - [0x169B2]={ - category="lo", - direction="l", - }, - [0x169B3]={ - category="lo", - direction="l", - }, - [0x169B4]={ - category="lo", - direction="l", - }, - [0x169B5]={ - category="lo", - direction="l", - }, - [0x169B6]={ - category="lo", - direction="l", - }, - [0x169B7]={ - category="lo", - direction="l", - }, - [0x169B8]={ - category="lo", - direction="l", - }, - [0x169B9]={ - category="lo", - direction="l", - }, - [0x169BA]={ - category="lo", - direction="l", - }, - [0x169BB]={ - category="lo", - direction="l", - }, - [0x169BC]={ - category="lo", - direction="l", - }, - [0x169BD]={ - category="lo", - direction="l", - }, - [0x169BE]={ - category="lo", - direction="l", - }, - [0x169BF]={ - category="lo", - direction="l", - }, - [0x169C0]={ - category="lo", - direction="l", - }, - [0x169C1]={ - category="lo", - direction="l", - }, - [0x169C2]={ - category="lo", - direction="l", - }, - [0x169C3]={ - category="lo", - direction="l", - }, - [0x169C4]={ - category="lo", - direction="l", - }, - [0x169C5]={ - category="lo", - direction="l", - }, - [0x169C6]={ - category="lo", - direction="l", - }, - [0x169C7]={ - category="lo", - direction="l", - }, - [0x169C8]={ - category="lo", - direction="l", - }, - [0x169C9]={ - category="lo", - direction="l", - }, - [0x169CA]={ - category="lo", - direction="l", - }, - [0x169CB]={ - category="lo", - direction="l", - }, - [0x169CC]={ - category="lo", - direction="l", - }, - [0x169CD]={ - category="lo", - direction="l", - }, - [0x169CE]={ - category="lo", - direction="l", - }, - [0x169CF]={ - category="lo", - direction="l", - }, - [0x169D0]={ - category="lo", - direction="l", - }, - [0x169D1]={ - category="lo", - direction="l", - }, - [0x169D2]={ - category="lo", - direction="l", - }, - [0x169D3]={ - category="lo", - direction="l", - }, - [0x169D4]={ - category="lo", - direction="l", - }, - [0x169D5]={ - category="lo", - direction="l", - }, - [0x169D6]={ - category="lo", - direction="l", - }, - [0x169D7]={ - category="lo", - direction="l", - }, - [0x169D8]={ - category="lo", - direction="l", - }, - [0x169D9]={ - category="lo", - direction="l", - }, - [0x169DA]={ - category="lo", - direction="l", - }, - [0x169DB]={ - category="lo", - direction="l", - }, - [0x169DC]={ - category="lo", - direction="l", - }, - [0x169DD]={ - category="lo", - direction="l", - }, - [0x169DE]={ - category="lo", - direction="l", - }, - [0x169DF]={ - category="lo", - direction="l", - }, - [0x169E0]={ - category="lo", - direction="l", - }, - [0x169E1]={ - category="lo", - direction="l", - }, - [0x169E2]={ - category="lo", - direction="l", - }, - [0x169E3]={ - category="lo", - direction="l", - }, - [0x169E4]={ - category="lo", - direction="l", - }, - [0x169E5]={ - category="lo", - direction="l", - }, - [0x169E6]={ - category="lo", - direction="l", - }, - [0x169E7]={ - category="lo", - direction="l", - }, - [0x169E8]={ - category="lo", - direction="l", - }, - [0x169E9]={ - category="lo", - direction="l", - }, - [0x169EA]={ - category="lo", - direction="l", - }, - [0x169EB]={ - category="lo", - direction="l", - }, - [0x169EC]={ - category="lo", - direction="l", - }, - [0x169ED]={ - category="lo", - direction="l", - }, - [0x169EE]={ - category="lo", - direction="l", - }, - [0x169EF]={ - category="lo", - direction="l", - }, - [0x169F0]={ - category="lo", - direction="l", - }, - [0x169F1]={ - category="lo", - direction="l", - }, - [0x169F2]={ - category="lo", - direction="l", - }, - [0x169F3]={ - category="lo", - direction="l", - }, - [0x169F4]={ - category="lo", - direction="l", - }, - [0x169F5]={ - category="lo", - direction="l", - }, - [0x169F6]={ - category="lo", - direction="l", - }, - [0x169F7]={ - category="lo", - direction="l", - }, - [0x169F8]={ - category="lo", - direction="l", - }, - [0x169F9]={ - category="lo", - direction="l", - }, - [0x169FA]={ - category="lo", - direction="l", - }, - [0x169FB]={ - category="lo", - direction="l", - }, - [0x169FC]={ - category="lo", - direction="l", - }, - [0x169FD]={ - category="lo", - direction="l", - }, - [0x169FE]={ - category="lo", - direction="l", - }, - [0x169FF]={ - category="lo", - direction="l", - }, - [0x16A00]={ - category="lo", - direction="l", - }, - [0x16A01]={ - category="lo", - direction="l", - }, - [0x16A02]={ - category="lo", - direction="l", - }, - [0x16A03]={ - category="lo", - direction="l", - }, - [0x16A04]={ - category="lo", - direction="l", - }, - [0x16A05]={ - category="lo", - direction="l", - }, - [0x16A06]={ - category="lo", - direction="l", - }, - [0x16A07]={ - category="lo", - direction="l", - }, - [0x16A08]={ - category="lo", - direction="l", - }, - [0x16A09]={ - category="lo", - direction="l", - }, - [0x16A0A]={ - category="lo", - direction="l", - }, - [0x16A0B]={ - category="lo", - direction="l", - }, - [0x16A0C]={ - category="lo", - direction="l", - }, - [0x16A0D]={ - category="lo", - direction="l", - }, - [0x16A0E]={ - category="lo", - direction="l", - }, - [0x16A0F]={ - category="lo", - direction="l", - }, - [0x16A10]={ - category="lo", - direction="l", - }, - [0x16A11]={ - category="lo", - direction="l", - }, - [0x16A12]={ - category="lo", - direction="l", - }, - [0x16A13]={ - category="lo", - direction="l", - }, - [0x16A14]={ - category="lo", - direction="l", - }, - [0x16A15]={ - category="lo", - direction="l", - }, - [0x16A16]={ - category="lo", - direction="l", - }, - [0x16A17]={ - category="lo", - direction="l", - }, - [0x16A18]={ - category="lo", - direction="l", - }, - [0x16A19]={ - category="lo", - direction="l", - }, - [0x16A1A]={ - category="lo", - direction="l", - }, - [0x16A1B]={ - category="lo", - direction="l", - }, - [0x16A1C]={ - category="lo", - direction="l", - }, - [0x16A1D]={ - category="lo", - direction="l", - }, - [0x16A1E]={ - category="lo", - direction="l", - }, - [0x16A1F]={ - category="lo", - direction="l", - }, - [0x16A20]={ - category="lo", - direction="l", - }, - [0x16A21]={ - category="lo", - direction="l", - }, - [0x16A22]={ - category="lo", - direction="l", - }, - [0x16A23]={ - category="lo", - direction="l", - }, - [0x16A24]={ - category="lo", - direction="l", - }, - [0x16A25]={ - category="lo", - direction="l", - }, - [0x16A26]={ - category="lo", - direction="l", - }, - [0x16A27]={ - category="lo", - direction="l", - }, - [0x16A28]={ - category="lo", - direction="l", - }, - [0x16A29]={ - category="lo", - direction="l", - }, - [0x16A2A]={ - category="lo", - direction="l", - }, - [0x16A2B]={ - category="lo", - direction="l", - }, - [0x16A2C]={ - category="lo", - direction="l", - }, - [0x16A2D]={ - category="lo", - direction="l", - }, - [0x16A2E]={ - category="lo", - direction="l", - }, - [0x16A2F]={ - category="lo", - direction="l", - }, - [0x16A30]={ - category="lo", - direction="l", - }, - [0x16A31]={ - category="lo", - direction="l", - }, - [0x16A32]={ - category="lo", - direction="l", - }, - [0x16A33]={ - category="lo", - direction="l", - }, - [0x16A34]={ - category="lo", - direction="l", - }, - [0x16A35]={ - category="lo", - direction="l", - }, - [0x16A36]={ - category="lo", - direction="l", - }, - [0x16A37]={ - category="lo", - direction="l", - }, - [0x16A38]={ - category="lo", - direction="l", - }, - [0x16A40]={ - category="lo", - direction="l", - }, - [0x16A41]={ - category="lo", - direction="l", - }, - [0x16A42]={ - category="lo", - direction="l", - }, - [0x16A43]={ - category="lo", - direction="l", - }, - [0x16A44]={ - category="lo", - direction="l", - }, - [0x16A45]={ - category="lo", - direction="l", - }, - [0x16A46]={ - category="lo", - direction="l", - }, - [0x16A47]={ - category="lo", - direction="l", - }, - [0x16A48]={ - category="lo", - direction="l", - }, - [0x16A49]={ - category="lo", - direction="l", - }, - [0x16A4A]={ - category="lo", - direction="l", - }, - [0x16A4B]={ - category="lo", - direction="l", - }, - [0x16A4C]={ - category="lo", - direction="l", - }, - [0x16A4D]={ - category="lo", - direction="l", - }, - [0x16A4E]={ - category="lo", - direction="l", - }, - [0x16A4F]={ - category="lo", - direction="l", - }, - [0x16A50]={ - category="lo", - direction="l", - }, - [0x16A51]={ - category="lo", - direction="l", - }, - [0x16A52]={ - category="lo", - direction="l", - }, - [0x16A53]={ - category="lo", - direction="l", - }, - [0x16A54]={ - category="lo", - direction="l", - }, - [0x16A55]={ - category="lo", - direction="l", - }, - [0x16A56]={ - category="lo", - direction="l", - }, - [0x16A57]={ - category="lo", - direction="l", - }, - [0x16A58]={ - category="lo", - direction="l", - }, - [0x16A59]={ - category="lo", - direction="l", - }, - [0x16A5A]={ - category="lo", - direction="l", - }, - [0x16A5B]={ - category="lo", - direction="l", - }, - [0x16A5C]={ - category="lo", - direction="l", - }, - [0x16A5D]={ - category="lo", - direction="l", - }, - [0x16A5E]={ - category="lo", - direction="l", - }, - [0x16A60]={ - category="nd", - direction="l", - }, - [0x16A61]={ - category="nd", - direction="l", - }, - [0x16A62]={ - category="nd", - direction="l", - }, - [0x16A63]={ - category="nd", - direction="l", - }, - [0x16A64]={ - category="nd", - direction="l", - }, - [0x16A65]={ - category="nd", - direction="l", - }, - [0x16A66]={ - category="nd", - direction="l", - }, - [0x16A67]={ - category="nd", - direction="l", - }, - [0x16A68]={ - category="nd", - direction="l", - }, - [0x16A69]={ - category="nd", - direction="l", - }, - [0x16A6E]={ - category="po", - direction="l", - }, - [0x16A6F]={ - category="po", - direction="l", - }, - [0x16AD0]={ - category="lo", - direction="l", - }, - [0x16AD1]={ - category="lo", - direction="l", - }, - [0x16AD2]={ - category="lo", - direction="l", - }, - [0x16AD3]={ - category="lo", - direction="l", - }, - [0x16AD4]={ - category="lo", - direction="l", - }, - [0x16AD5]={ - category="lo", - direction="l", - }, - [0x16AD6]={ - category="lo", - direction="l", - }, - [0x16AD7]={ - category="lo", - direction="l", - }, - [0x16AD8]={ - category="lo", - direction="l", - }, - [0x16AD9]={ - category="lo", - direction="l", - }, - [0x16ADA]={ - category="lo", - direction="l", - }, - [0x16ADB]={ - category="lo", - direction="l", - }, - [0x16ADC]={ - category="lo", - direction="l", - }, - [0x16ADD]={ - category="lo", - direction="l", - }, - [0x16ADE]={ - category="lo", - direction="l", - }, - [0x16ADF]={ - category="lo", - direction="l", - }, - [0x16AE0]={ - category="lo", - direction="l", - }, - [0x16AE1]={ - category="lo", - direction="l", - }, - [0x16AE2]={ - category="lo", - direction="l", - }, - [0x16AE3]={ - category="lo", - direction="l", - }, - [0x16AE4]={ - category="lo", - direction="l", - }, - [0x16AE5]={ - category="lo", - direction="l", - }, - [0x16AE6]={ - category="lo", - direction="l", - }, - [0x16AE7]={ - category="lo", - direction="l", - }, - [0x16AE8]={ - category="lo", - direction="l", - }, - [0x16AE9]={ - category="lo", - direction="l", - }, - [0x16AEA]={ - category="lo", - direction="l", - }, - [0x16AEB]={ - category="lo", - direction="l", - }, - [0x16AEC]={ - category="lo", - direction="l", - }, - [0x16AED]={ - category="lo", - direction="l", - }, - [0x16AF0]={ - category="mn", - direction="nsm", - }, - [0x16AF1]={ - category="mn", - direction="nsm", - }, - [0x16AF2]={ - category="mn", - direction="nsm", - }, - [0x16AF3]={ - category="mn", - direction="nsm", - }, - [0x16AF4]={ - category="mn", - direction="nsm", - }, - [0x16AF5]={ - category="po", - direction="l", - }, - [0x16B00]={ - category="lo", - direction="l", - }, - [0x16B01]={ - category="lo", - direction="l", - }, - [0x16B02]={ - category="lo", - direction="l", - }, - [0x16B03]={ - category="lo", - direction="l", - }, - [0x16B04]={ - category="lo", - direction="l", - }, - [0x16B05]={ - category="lo", - direction="l", - }, - [0x16B06]={ - category="lo", - direction="l", - }, - [0x16B07]={ - category="lo", - direction="l", - }, - [0x16B08]={ - category="lo", - direction="l", - }, - [0x16B09]={ - category="lo", - direction="l", - }, - [0x16B0A]={ - category="lo", - direction="l", - }, - [0x16B0B]={ - category="lo", - direction="l", - }, - [0x16B0C]={ - category="lo", - direction="l", - }, - [0x16B0D]={ - category="lo", - direction="l", - }, - [0x16B0E]={ - category="lo", - direction="l", - }, - [0x16B0F]={ - category="lo", - direction="l", - }, - [0x16B10]={ - category="lo", - direction="l", - }, - [0x16B11]={ - category="lo", - direction="l", - }, - [0x16B12]={ - category="lo", - direction="l", - }, - [0x16B13]={ - category="lo", - direction="l", - }, - [0x16B14]={ - category="lo", - direction="l", - }, - [0x16B15]={ - category="lo", - direction="l", - }, - [0x16B16]={ - category="lo", - direction="l", - }, - [0x16B17]={ - category="lo", - direction="l", - }, - [0x16B18]={ - category="lo", - direction="l", - }, - [0x16B19]={ - category="lo", - direction="l", - }, - [0x16B1A]={ - category="lo", - direction="l", - }, - [0x16B1B]={ - category="lo", - direction="l", - }, - [0x16B1C]={ - category="lo", - direction="l", - }, - [0x16B1D]={ - category="lo", - direction="l", - }, - [0x16B1E]={ - category="lo", - direction="l", - }, - [0x16B1F]={ - category="lo", - direction="l", - }, - [0x16B20]={ - category="lo", - direction="l", - }, - [0x16B21]={ - category="lo", - direction="l", - }, - [0x16B22]={ - category="lo", - direction="l", - }, - [0x16B23]={ - category="lo", - direction="l", - }, - [0x16B24]={ - category="lo", - direction="l", - }, - [0x16B25]={ - category="lo", - direction="l", - }, - [0x16B26]={ - category="lo", - direction="l", - }, - [0x16B27]={ - category="lo", - direction="l", - }, - [0x16B28]={ - category="lo", - direction="l", - }, - [0x16B29]={ - category="lo", - direction="l", - }, - [0x16B2A]={ - category="lo", - direction="l", - }, - [0x16B2B]={ - category="lo", - direction="l", - }, - [0x16B2C]={ - category="lo", - direction="l", - }, - [0x16B2D]={ - category="lo", - direction="l", - }, - [0x16B2E]={ - category="lo", - direction="l", - }, - [0x16B2F]={ - category="lo", - direction="l", - }, - [0x16B30]={ - category="mn", - direction="nsm", - }, - [0x16B31]={ - category="mn", - direction="nsm", - }, - [0x16B32]={ - category="mn", - direction="nsm", - }, - [0x16B33]={ - category="mn", - direction="nsm", - }, - [0x16B34]={ - category="mn", - direction="nsm", - }, - [0x16B35]={ - category="mn", - direction="nsm", - }, - [0x16B36]={ - category="mn", - direction="nsm", - }, - [0x16B37]={ - category="po", - direction="l", - }, - [0x16B38]={ - category="po", - direction="l", - }, - [0x16B39]={ - category="po", - direction="l", - }, - [0x16B3A]={ - category="po", - direction="l", - }, - [0x16B3B]={ - category="po", - direction="l", - }, - [0x16B3C]={ - category="so", - direction="l", - }, - [0x16B3D]={ - category="so", - direction="l", - }, - [0x16B3E]={ - category="so", - direction="l", - }, - [0x16B3F]={ - category="so", - direction="l", - }, - [0x16B40]={ - category="lm", - direction="l", - }, - [0x16B41]={ - category="lm", - direction="l", - }, - [0x16B42]={ - category="lm", - direction="l", - }, - [0x16B43]={ - category="lm", - direction="l", - }, - [0x16B44]={ - category="po", - direction="l", - }, - [0x16B45]={ - category="so", - direction="l", - }, - [0x16B50]={ - category="nd", - direction="l", - }, - [0x16B51]={ - category="nd", - direction="l", - }, - [0x16B52]={ - category="nd", - direction="l", - }, - [0x16B53]={ - category="nd", - direction="l", - }, - [0x16B54]={ - category="nd", - direction="l", - }, - [0x16B55]={ - category="nd", - direction="l", - }, - [0x16B56]={ - category="nd", - direction="l", - }, - [0x16B57]={ - category="nd", - direction="l", - }, - [0x16B58]={ - category="nd", - direction="l", - }, - [0x16B59]={ - category="nd", - direction="l", - }, - [0x16B5B]={ - category="no", - direction="l", - }, - [0x16B5C]={ - category="no", - direction="l", - }, - [0x16B5D]={ - category="no", - direction="l", - }, - [0x16B5E]={ - category="no", - direction="l", - }, - [0x16B5F]={ - category="no", - direction="l", - }, - [0x16B60]={ - category="no", - direction="l", - }, - [0x16B61]={ - category="no", - direction="l", - }, - [0x16B63]={ - category="lo", - direction="l", - }, - [0x16B64]={ - category="lo", - direction="l", - }, - [0x16B65]={ - category="lo", - direction="l", - }, - [0x16B66]={ - category="lo", - direction="l", - }, - [0x16B67]={ - category="lo", - direction="l", - }, - [0x16B68]={ - category="lo", - direction="l", - }, - [0x16B69]={ - category="lo", - direction="l", - }, - [0x16B6A]={ - category="lo", - direction="l", - }, - [0x16B6B]={ - category="lo", - direction="l", - }, - [0x16B6C]={ - category="lo", - direction="l", - }, - [0x16B6D]={ - category="lo", - direction="l", - }, - [0x16B6E]={ - category="lo", - direction="l", - }, - [0x16B6F]={ - category="lo", - direction="l", - }, - [0x16B70]={ - category="lo", - direction="l", - }, - [0x16B71]={ - category="lo", - direction="l", - }, - [0x16B72]={ - category="lo", - direction="l", - }, - [0x16B73]={ - category="lo", - direction="l", - }, - [0x16B74]={ - category="lo", - direction="l", - }, - [0x16B75]={ - category="lo", - direction="l", - }, - [0x16B76]={ - category="lo", - direction="l", - }, - [0x16B77]={ - category="lo", - direction="l", - }, - [0x16B7D]={ - category="lo", - direction="l", - }, - [0x16B7E]={ - category="lo", - direction="l", - }, - [0x16B7F]={ - category="lo", - direction="l", - }, - [0x16B80]={ - category="lo", - direction="l", - }, - [0x16B81]={ - category="lo", - direction="l", - }, - [0x16B82]={ - category="lo", - direction="l", - }, - [0x16B83]={ - category="lo", - direction="l", - }, - [0x16B84]={ - category="lo", - direction="l", - }, - [0x16B85]={ - category="lo", - direction="l", - }, - [0x16B86]={ - category="lo", - direction="l", - }, - [0x16B87]={ - category="lo", - direction="l", - }, - [0x16B88]={ - category="lo", - direction="l", - }, - [0x16B89]={ - category="lo", - direction="l", - }, - [0x16B8A]={ - category="lo", - direction="l", - }, - [0x16B8B]={ - category="lo", - direction="l", - }, - [0x16B8C]={ - category="lo", - direction="l", - }, - [0x16B8D]={ - category="lo", - direction="l", - }, - [0x16B8E]={ - category="lo", - direction="l", - }, - [0x16B8F]={ - category="lo", - direction="l", - }, - [0x16F00]={ - category="lo", - direction="l", - }, - [0x16F01]={ - category="lo", - direction="l", - }, - [0x16F02]={ - category="lo", - direction="l", - }, - [0x16F03]={ - category="lo", - direction="l", - }, - [0x16F04]={ - category="lo", - direction="l", - }, - [0x16F05]={ - category="lo", - direction="l", - }, - [0x16F06]={ - category="lo", - direction="l", - }, - [0x16F07]={ - category="lo", - direction="l", - }, - [0x16F08]={ - category="lo", - direction="l", - }, - [0x16F09]={ - category="lo", - direction="l", - }, - [0x16F0A]={ - category="lo", - direction="l", - }, - [0x16F0B]={ - category="lo", - direction="l", - }, - [0x16F0C]={ - category="lo", - direction="l", - }, - [0x16F0D]={ - category="lo", - direction="l", - }, - [0x16F0E]={ - category="lo", - direction="l", - }, - [0x16F0F]={ - category="lo", - direction="l", - }, - [0x16F10]={ - category="lo", - direction="l", - }, - [0x16F11]={ - category="lo", - direction="l", - }, - [0x16F12]={ - category="lo", - direction="l", - }, - [0x16F13]={ - category="lo", - direction="l", - }, - [0x16F14]={ - category="lo", - direction="l", - }, - [0x16F15]={ - category="lo", - direction="l", - }, - [0x16F16]={ - category="lo", - direction="l", - }, - [0x16F17]={ - category="lo", - direction="l", - }, - [0x16F18]={ - category="lo", - direction="l", - }, - [0x16F19]={ - category="lo", - direction="l", - }, - [0x16F1A]={ - category="lo", - direction="l", - }, - [0x16F1B]={ - category="lo", - direction="l", - }, - [0x16F1C]={ - category="lo", - direction="l", - }, - [0x16F1D]={ - category="lo", - direction="l", - }, - [0x16F1E]={ - category="lo", - direction="l", - }, - [0x16F1F]={ - category="lo", - direction="l", - }, - [0x16F20]={ - category="lo", - direction="l", - }, - [0x16F21]={ - category="lo", - direction="l", - }, - [0x16F22]={ - category="lo", - direction="l", - }, - [0x16F23]={ - category="lo", - direction="l", - }, - [0x16F24]={ - category="lo", - direction="l", - }, - [0x16F25]={ - category="lo", - direction="l", - }, - [0x16F26]={ - category="lo", - direction="l", - }, - [0x16F27]={ - category="lo", - direction="l", - }, - [0x16F28]={ - category="lo", - direction="l", - }, - [0x16F29]={ - category="lo", - direction="l", - }, - [0x16F2A]={ - category="lo", - direction="l", - }, - [0x16F2B]={ - category="lo", - direction="l", - }, - [0x16F2C]={ - category="lo", - direction="l", - }, - [0x16F2D]={ - category="lo", - direction="l", - }, - [0x16F2E]={ - category="lo", - direction="l", - }, - [0x16F2F]={ - category="lo", - direction="l", - }, - [0x16F30]={ - category="lo", - direction="l", - }, - [0x16F31]={ - category="lo", - direction="l", - }, - [0x16F32]={ - category="lo", - direction="l", - }, - [0x16F33]={ - category="lo", - direction="l", - }, - [0x16F34]={ - category="lo", - direction="l", - }, - [0x16F35]={ - category="lo", - direction="l", - }, - [0x16F36]={ - category="lo", - direction="l", - }, - [0x16F37]={ - category="lo", - direction="l", - }, - [0x16F38]={ - category="lo", - direction="l", - }, - [0x16F39]={ - category="lo", - direction="l", - }, - [0x16F3A]={ - category="lo", - direction="l", - }, - [0x16F3B]={ - category="lo", - direction="l", - }, - [0x16F3C]={ - category="lo", - direction="l", - }, - [0x16F3D]={ - category="lo", - direction="l", - }, - [0x16F3E]={ - category="lo", - direction="l", - }, - [0x16F3F]={ - category="lo", - direction="l", - }, - [0x16F40]={ - category="lo", - direction="l", - }, - [0x16F41]={ - category="lo", - direction="l", - }, - [0x16F42]={ - category="lo", - direction="l", - }, - [0x16F43]={ - category="lo", - direction="l", - }, - [0x16F44]={ - category="lo", - direction="l", - }, - [0x16F50]={ - category="lo", - direction="l", - }, - [0x16F51]={ - category="mc", - direction="l", - }, - [0x16F52]={ - category="mc", - direction="l", - }, - [0x16F53]={ - category="mc", - direction="l", - }, - [0x16F54]={ - category="mc", - direction="l", - }, - [0x16F55]={ - category="mc", - direction="l", - }, - [0x16F56]={ - category="mc", - direction="l", - }, - [0x16F57]={ - category="mc", - direction="l", - }, - [0x16F58]={ - category="mc", - direction="l", - }, - [0x16F59]={ - category="mc", - direction="l", - }, - [0x16F5A]={ - category="mc", - direction="l", - }, - [0x16F5B]={ - category="mc", - direction="l", - }, - [0x16F5C]={ - category="mc", - direction="l", - }, - [0x16F5D]={ - category="mc", - direction="l", - }, - [0x16F5E]={ - category="mc", - direction="l", - }, - [0x16F5F]={ - category="mc", - direction="l", - }, - [0x16F60]={ - category="mc", - direction="l", - }, - [0x16F61]={ - category="mc", - direction="l", - }, - [0x16F62]={ - category="mc", - direction="l", - }, - [0x16F63]={ - category="mc", - direction="l", - }, - [0x16F64]={ - category="mc", - direction="l", - }, - [0x16F65]={ - category="mc", - direction="l", - }, - [0x16F66]={ - category="mc", - direction="l", - }, - [0x16F67]={ - category="mc", - direction="l", - }, - [0x16F68]={ - category="mc", - direction="l", - }, - [0x16F69]={ - category="mc", - direction="l", - }, - [0x16F6A]={ - category="mc", - direction="l", - }, - [0x16F6B]={ - category="mc", - direction="l", - }, - [0x16F6C]={ - category="mc", - direction="l", - }, - [0x16F6D]={ - category="mc", - direction="l", - }, - [0x16F6E]={ - category="mc", - direction="l", - }, - [0x16F6F]={ - category="mc", - direction="l", - }, - [0x16F70]={ - category="mc", - direction="l", - }, - [0x16F71]={ - category="mc", - direction="l", - }, - [0x16F72]={ - category="mc", - direction="l", - }, - [0x16F73]={ - category="mc", - direction="l", - }, - [0x16F74]={ - category="mc", - direction="l", - }, - [0x16F75]={ - category="mc", - direction="l", - }, - [0x16F76]={ - category="mc", - direction="l", - }, - [0x16F77]={ - category="mc", - direction="l", - }, - [0x16F78]={ - category="mc", - direction="l", - }, - [0x16F79]={ - category="mc", - direction="l", - }, - [0x16F7A]={ - category="mc", - direction="l", - }, - [0x16F7B]={ - category="mc", - direction="l", - }, - [0x16F7C]={ - category="mc", - direction="l", - }, - [0x16F7D]={ - category="mc", - direction="l", - }, - [0x16F7E]={ - category="mc", - direction="l", - }, - [0x16F8F]={ - category="mn", - direction="nsm", - }, - [0x16F90]={ - category="mn", - direction="nsm", - }, - [0x16F91]={ - category="mn", - direction="nsm", - }, - [0x16F92]={ - category="mn", - direction="nsm", - }, - [0x16F93]={ - category="lm", - direction="l", - }, - [0x16F94]={ - category="lm", - direction="l", - }, - [0x16F95]={ - category="lm", - direction="l", - }, - [0x16F96]={ - category="lm", - direction="l", - }, - [0x16F97]={ - category="lm", - direction="l", - }, - [0x16F98]={ - category="lm", - direction="l", - }, - [0x16F99]={ - category="lm", - direction="l", - }, - [0x16F9A]={ - category="lm", - direction="l", - }, - [0x16F9B]={ - category="lm", - direction="l", - }, - [0x16F9C]={ - category="lm", - direction="l", - }, - [0x16F9D]={ - category="lm", - direction="l", - }, - [0x16F9E]={ - category="lm", - direction="l", - }, - [0x16F9F]={ - category="lm", - direction="l", - }, - [0x16FE0]={ - category="lm", - direction="l", - }, - [0x18800]={ - category="lo", - direction="l", - }, - [0x18801]={ - category="lo", - direction="l", - }, - [0x18802]={ - category="lo", - direction="l", - }, - [0x18803]={ - category="lo", - direction="l", - }, - [0x18804]={ - category="lo", - direction="l", - }, - [0x18805]={ - category="lo", - direction="l", - }, - [0x18806]={ - category="lo", - direction="l", - }, - [0x18807]={ - category="lo", - direction="l", - }, - [0x18808]={ - category="lo", - direction="l", - }, - [0x18809]={ - category="lo", - direction="l", - }, - [0x1880A]={ - category="lo", - direction="l", - }, - [0x1880B]={ - category="lo", - direction="l", - }, - [0x1880C]={ - category="lo", - direction="l", - }, - [0x1880D]={ - category="lo", - direction="l", - }, - [0x1880E]={ - category="lo", - direction="l", - }, - [0x1880F]={ - category="lo", - direction="l", - }, - [0x18810]={ - category="lo", - direction="l", - }, - [0x18811]={ - category="lo", - direction="l", - }, - [0x18812]={ - category="lo", - direction="l", - }, - [0x18813]={ - category="lo", - direction="l", - }, - [0x18814]={ - category="lo", - direction="l", - }, - [0x18815]={ - category="lo", - direction="l", - }, - [0x18816]={ - category="lo", - direction="l", - }, - [0x18817]={ - category="lo", - direction="l", - }, - [0x18818]={ - category="lo", - direction="l", - }, - [0x18819]={ - category="lo", - direction="l", - }, - [0x1881A]={ - category="lo", - direction="l", - }, - [0x1881B]={ - category="lo", - direction="l", - }, - [0x1881C]={ - category="lo", - direction="l", - }, - [0x1881D]={ - category="lo", - direction="l", - }, - [0x1881E]={ - category="lo", - direction="l", - }, - [0x1881F]={ - category="lo", - direction="l", - }, - [0x18820]={ - category="lo", - direction="l", - }, - [0x18821]={ - category="lo", - direction="l", - }, - [0x18822]={ - category="lo", - direction="l", - }, - [0x18823]={ - category="lo", - direction="l", - }, - [0x18824]={ - category="lo", - direction="l", - }, - [0x18825]={ - category="lo", - direction="l", - }, - [0x18826]={ - category="lo", - direction="l", - }, - [0x18827]={ - category="lo", - direction="l", - }, - [0x18828]={ - category="lo", - direction="l", - }, - [0x18829]={ - category="lo", - direction="l", - }, - [0x1882A]={ - category="lo", - direction="l", - }, - [0x1882B]={ - category="lo", - direction="l", - }, - [0x1882C]={ - category="lo", - direction="l", - }, - [0x1882D]={ - category="lo", - direction="l", - }, - [0x1882E]={ - category="lo", - direction="l", - }, - [0x1882F]={ - category="lo", - direction="l", - }, - [0x18830]={ - category="lo", - direction="l", - }, - [0x18831]={ - category="lo", - direction="l", - }, - [0x18832]={ - category="lo", - direction="l", - }, - [0x18833]={ - category="lo", - direction="l", - }, - [0x18834]={ - category="lo", - direction="l", - }, - [0x18835]={ - category="lo", - direction="l", - }, - [0x18836]={ - category="lo", - direction="l", - }, - [0x18837]={ - category="lo", - direction="l", - }, - [0x18838]={ - category="lo", - direction="l", - }, - [0x18839]={ - category="lo", - direction="l", - }, - [0x1883A]={ - category="lo", - direction="l", - }, - [0x1883B]={ - category="lo", - direction="l", - }, - [0x1883C]={ - category="lo", - direction="l", - }, - [0x1883D]={ - category="lo", - direction="l", - }, - [0x1883E]={ - category="lo", - direction="l", - }, - [0x1883F]={ - category="lo", - direction="l", - }, - [0x18840]={ - category="lo", - direction="l", - }, - [0x18841]={ - category="lo", - direction="l", - }, - [0x18842]={ - category="lo", - direction="l", - }, - [0x18843]={ - category="lo", - direction="l", - }, - [0x18844]={ - category="lo", - direction="l", - }, - [0x18845]={ - category="lo", - direction="l", - }, - [0x18846]={ - category="lo", - direction="l", - }, - [0x18847]={ - category="lo", - direction="l", - }, - [0x18848]={ - category="lo", - direction="l", - }, - [0x18849]={ - category="lo", - direction="l", - }, - [0x1884A]={ - category="lo", - direction="l", - }, - [0x1884B]={ - category="lo", - direction="l", - }, - [0x1884C]={ - category="lo", - direction="l", - }, - [0x1884D]={ - category="lo", - direction="l", - }, - [0x1884E]={ - category="lo", - direction="l", - }, - [0x1884F]={ - category="lo", - direction="l", - }, - [0x18850]={ - category="lo", - direction="l", - }, - [0x18851]={ - category="lo", - direction="l", - }, - [0x18852]={ - category="lo", - direction="l", - }, - [0x18853]={ - category="lo", - direction="l", - }, - [0x18854]={ - category="lo", - direction="l", - }, - [0x18855]={ - category="lo", - direction="l", - }, - [0x18856]={ - category="lo", - direction="l", - }, - [0x18857]={ - category="lo", - direction="l", - }, - [0x18858]={ - category="lo", - direction="l", - }, - [0x18859]={ - category="lo", - direction="l", - }, - [0x1885A]={ - category="lo", - direction="l", - }, - [0x1885B]={ - category="lo", - direction="l", - }, - [0x1885C]={ - category="lo", - direction="l", - }, - [0x1885D]={ - category="lo", - direction="l", - }, - [0x1885E]={ - category="lo", - direction="l", - }, - [0x1885F]={ - category="lo", - direction="l", - }, - [0x18860]={ - category="lo", - direction="l", - }, - [0x18861]={ - category="lo", - direction="l", - }, - [0x18862]={ - category="lo", - direction="l", - }, - [0x18863]={ - category="lo", - direction="l", - }, - [0x18864]={ - category="lo", - direction="l", - }, - [0x18865]={ - category="lo", - direction="l", - }, - [0x18866]={ - category="lo", - direction="l", - }, - [0x18867]={ - category="lo", - direction="l", - }, - [0x18868]={ - category="lo", - direction="l", - }, - [0x18869]={ - category="lo", - direction="l", - }, - [0x1886A]={ - category="lo", - direction="l", - }, - [0x1886B]={ - category="lo", - direction="l", - }, - [0x1886C]={ - category="lo", - direction="l", - }, - [0x1886D]={ - category="lo", - direction="l", - }, - [0x1886E]={ - category="lo", - direction="l", - }, - [0x1886F]={ - category="lo", - direction="l", - }, - [0x18870]={ - category="lo", - direction="l", - }, - [0x18871]={ - category="lo", - direction="l", - }, - [0x18872]={ - category="lo", - direction="l", - }, - [0x18873]={ - category="lo", - direction="l", - }, - [0x18874]={ - category="lo", - direction="l", - }, - [0x18875]={ - category="lo", - direction="l", - }, - [0x18876]={ - category="lo", - direction="l", - }, - [0x18877]={ - category="lo", - direction="l", - }, - [0x18878]={ - category="lo", - direction="l", - }, - [0x18879]={ - category="lo", - direction="l", - }, - [0x1887A]={ - category="lo", - direction="l", - }, - [0x1887B]={ - category="lo", - direction="l", - }, - [0x1887C]={ - category="lo", - direction="l", - }, - [0x1887D]={ - category="lo", - direction="l", - }, - [0x1887E]={ - category="lo", - direction="l", - }, - [0x1887F]={ - category="lo", - direction="l", - }, - [0x18880]={ - category="lo", - direction="l", - }, - [0x18881]={ - category="lo", - direction="l", - }, - [0x18882]={ - category="lo", - direction="l", - }, - [0x18883]={ - category="lo", - direction="l", - }, - [0x18884]={ - category="lo", - direction="l", - }, - [0x18885]={ - category="lo", - direction="l", - }, - [0x18886]={ - category="lo", - direction="l", - }, - [0x18887]={ - category="lo", - direction="l", - }, - [0x18888]={ - category="lo", - direction="l", - }, - [0x18889]={ - category="lo", - direction="l", - }, - [0x1888A]={ - category="lo", - direction="l", - }, - [0x1888B]={ - category="lo", - direction="l", - }, - [0x1888C]={ - category="lo", - direction="l", - }, - [0x1888D]={ - category="lo", - direction="l", - }, - [0x1888E]={ - category="lo", - direction="l", - }, - [0x1888F]={ - category="lo", - direction="l", - }, - [0x18890]={ - category="lo", - direction="l", - }, - [0x18891]={ - category="lo", - direction="l", - }, - [0x18892]={ - category="lo", - direction="l", - }, - [0x18893]={ - category="lo", - direction="l", - }, - [0x18894]={ - category="lo", - direction="l", - }, - [0x18895]={ - category="lo", - direction="l", - }, - [0x18896]={ - category="lo", - direction="l", - }, - [0x18897]={ - category="lo", - direction="l", - }, - [0x18898]={ - category="lo", - direction="l", - }, - [0x18899]={ - category="lo", - direction="l", - }, - [0x1889A]={ - category="lo", - direction="l", - }, - [0x1889B]={ - category="lo", - direction="l", - }, - [0x1889C]={ - category="lo", - direction="l", - }, - [0x1889D]={ - category="lo", - direction="l", - }, - [0x1889E]={ - category="lo", - direction="l", - }, - [0x1889F]={ - category="lo", - direction="l", - }, - [0x188A0]={ - category="lo", - direction="l", - }, - [0x188A1]={ - category="lo", - direction="l", - }, - [0x188A2]={ - category="lo", - direction="l", - }, - [0x188A3]={ - category="lo", - direction="l", - }, - [0x188A4]={ - category="lo", - direction="l", - }, - [0x188A5]={ - category="lo", - direction="l", - }, - [0x188A6]={ - category="lo", - direction="l", - }, - [0x188A7]={ - category="lo", - direction="l", - }, - [0x188A8]={ - category="lo", - direction="l", - }, - [0x188A9]={ - category="lo", - direction="l", - }, - [0x188AA]={ - category="lo", - direction="l", - }, - [0x188AB]={ - category="lo", - direction="l", - }, - [0x188AC]={ - category="lo", - direction="l", - }, - [0x188AD]={ - category="lo", - direction="l", - }, - [0x188AE]={ - category="lo", - direction="l", - }, - [0x188AF]={ - category="lo", - direction="l", - }, - [0x188B0]={ - category="lo", - direction="l", - }, - [0x188B1]={ - category="lo", - direction="l", - }, - [0x188B2]={ - category="lo", - direction="l", - }, - [0x188B3]={ - category="lo", - direction="l", - }, - [0x188B4]={ - category="lo", - direction="l", - }, - [0x188B5]={ - category="lo", - direction="l", - }, - [0x188B6]={ - category="lo", - direction="l", - }, - [0x188B7]={ - category="lo", - direction="l", - }, - [0x188B8]={ - category="lo", - direction="l", - }, - [0x188B9]={ - category="lo", - direction="l", - }, - [0x188BA]={ - category="lo", - direction="l", - }, - [0x188BB]={ - category="lo", - direction="l", - }, - [0x188BC]={ - category="lo", - direction="l", - }, - [0x188BD]={ - category="lo", - direction="l", - }, - [0x188BE]={ - category="lo", - direction="l", - }, - [0x188BF]={ - category="lo", - direction="l", - }, - [0x188C0]={ - category="lo", - direction="l", - }, - [0x188C1]={ - category="lo", - direction="l", - }, - [0x188C2]={ - category="lo", - direction="l", - }, - [0x188C3]={ - category="lo", - direction="l", - }, - [0x188C4]={ - category="lo", - direction="l", - }, - [0x188C5]={ - category="lo", - direction="l", - }, - [0x188C6]={ - category="lo", - direction="l", - }, - [0x188C7]={ - category="lo", - direction="l", - }, - [0x188C8]={ - category="lo", - direction="l", - }, - [0x188C9]={ - category="lo", - direction="l", - }, - [0x188CA]={ - category="lo", - direction="l", - }, - [0x188CB]={ - category="lo", - direction="l", - }, - [0x188CC]={ - category="lo", - direction="l", - }, - [0x188CD]={ - category="lo", - direction="l", - }, - [0x188CE]={ - category="lo", - direction="l", - }, - [0x188CF]={ - category="lo", - direction="l", - }, - [0x188D0]={ - category="lo", - direction="l", - }, - [0x188D1]={ - category="lo", - direction="l", - }, - [0x188D2]={ - category="lo", - direction="l", - }, - [0x188D3]={ - category="lo", - direction="l", - }, - [0x188D4]={ - category="lo", - direction="l", - }, - [0x188D5]={ - category="lo", - direction="l", - }, - [0x188D6]={ - category="lo", - direction="l", - }, - [0x188D7]={ - category="lo", - direction="l", - }, - [0x188D8]={ - category="lo", - direction="l", - }, - [0x188D9]={ - category="lo", - direction="l", - }, - [0x188DA]={ - category="lo", - direction="l", - }, - [0x188DB]={ - category="lo", - direction="l", - }, - [0x188DC]={ - category="lo", - direction="l", - }, - [0x188DD]={ - category="lo", - direction="l", - }, - [0x188DE]={ - category="lo", - direction="l", - }, - [0x188DF]={ - category="lo", - direction="l", - }, - [0x188E0]={ - category="lo", - direction="l", - }, - [0x188E1]={ - category="lo", - direction="l", - }, - [0x188E2]={ - category="lo", - direction="l", - }, - [0x188E3]={ - category="lo", - direction="l", - }, - [0x188E4]={ - category="lo", - direction="l", - }, - [0x188E5]={ - category="lo", - direction="l", - }, - [0x188E6]={ - category="lo", - direction="l", - }, - [0x188E7]={ - category="lo", - direction="l", - }, - [0x188E8]={ - category="lo", - direction="l", - }, - [0x188E9]={ - category="lo", - direction="l", - }, - [0x188EA]={ - category="lo", - direction="l", - }, - [0x188EB]={ - category="lo", - direction="l", - }, - [0x188EC]={ - category="lo", - direction="l", - }, - [0x188ED]={ - category="lo", - direction="l", - }, - [0x188EE]={ - category="lo", - direction="l", - }, - [0x188EF]={ - category="lo", - direction="l", - }, - [0x188F0]={ - category="lo", - direction="l", - }, - [0x188F1]={ - category="lo", - direction="l", - }, - [0x188F2]={ - category="lo", - direction="l", - }, - [0x188F3]={ - category="lo", - direction="l", - }, - [0x188F4]={ - category="lo", - direction="l", - }, - [0x188F5]={ - category="lo", - direction="l", - }, - [0x188F6]={ - category="lo", - direction="l", - }, - [0x188F7]={ - category="lo", - direction="l", - }, - [0x188F8]={ - category="lo", - direction="l", - }, - [0x188F9]={ - category="lo", - direction="l", - }, - [0x188FA]={ - category="lo", - direction="l", - }, - [0x188FB]={ - category="lo", - direction="l", - }, - [0x188FC]={ - category="lo", - direction="l", - }, - [0x188FD]={ - category="lo", - direction="l", - }, - [0x188FE]={ - category="lo", - direction="l", - }, - [0x188FF]={ - category="lo", - direction="l", - }, - [0x18900]={ - category="lo", - direction="l", - }, - [0x18901]={ - category="lo", - direction="l", - }, - [0x18902]={ - category="lo", - direction="l", - }, - [0x18903]={ - category="lo", - direction="l", - }, - [0x18904]={ - category="lo", - direction="l", - }, - [0x18905]={ - category="lo", - direction="l", - }, - [0x18906]={ - category="lo", - direction="l", - }, - [0x18907]={ - category="lo", - direction="l", - }, - [0x18908]={ - category="lo", - direction="l", - }, - [0x18909]={ - category="lo", - direction="l", - }, - [0x1890A]={ - category="lo", - direction="l", - }, - [0x1890B]={ - category="lo", - direction="l", - }, - [0x1890C]={ - category="lo", - direction="l", - }, - [0x1890D]={ - category="lo", - direction="l", - }, - [0x1890E]={ - category="lo", - direction="l", - }, - [0x1890F]={ - category="lo", - direction="l", - }, - [0x18910]={ - category="lo", - direction="l", - }, - [0x18911]={ - category="lo", - direction="l", - }, - [0x18912]={ - category="lo", - direction="l", - }, - [0x18913]={ - category="lo", - direction="l", - }, - [0x18914]={ - category="lo", - direction="l", - }, - [0x18915]={ - category="lo", - direction="l", - }, - [0x18916]={ - category="lo", - direction="l", - }, - [0x18917]={ - category="lo", - direction="l", - }, - [0x18918]={ - category="lo", - direction="l", - }, - [0x18919]={ - category="lo", - direction="l", - }, - [0x1891A]={ - category="lo", - direction="l", - }, - [0x1891B]={ - category="lo", - direction="l", - }, - [0x1891C]={ - category="lo", - direction="l", - }, - [0x1891D]={ - category="lo", - direction="l", - }, - [0x1891E]={ - category="lo", - direction="l", - }, - [0x1891F]={ - category="lo", - direction="l", - }, - [0x18920]={ - category="lo", - direction="l", - }, - [0x18921]={ - category="lo", - direction="l", - }, - [0x18922]={ - category="lo", - direction="l", - }, - [0x18923]={ - category="lo", - direction="l", - }, - [0x18924]={ - category="lo", - direction="l", - }, - [0x18925]={ - category="lo", - direction="l", - }, - [0x18926]={ - category="lo", - direction="l", - }, - [0x18927]={ - category="lo", - direction="l", - }, - [0x18928]={ - category="lo", - direction="l", - }, - [0x18929]={ - category="lo", - direction="l", - }, - [0x1892A]={ - category="lo", - direction="l", - }, - [0x1892B]={ - category="lo", - direction="l", - }, - [0x1892C]={ - category="lo", - direction="l", - }, - [0x1892D]={ - category="lo", - direction="l", - }, - [0x1892E]={ - category="lo", - direction="l", - }, - [0x1892F]={ - category="lo", - direction="l", - }, - [0x18930]={ - category="lo", - direction="l", - }, - [0x18931]={ - category="lo", - direction="l", - }, - [0x18932]={ - category="lo", - direction="l", - }, - [0x18933]={ - category="lo", - direction="l", - }, - [0x18934]={ - category="lo", - direction="l", - }, - [0x18935]={ - category="lo", - direction="l", - }, - [0x18936]={ - category="lo", - direction="l", - }, - [0x18937]={ - category="lo", - direction="l", - }, - [0x18938]={ - category="lo", - direction="l", - }, - [0x18939]={ - category="lo", - direction="l", - }, - [0x1893A]={ - category="lo", - direction="l", - }, - [0x1893B]={ - category="lo", - direction="l", - }, - [0x1893C]={ - category="lo", - direction="l", - }, - [0x1893D]={ - category="lo", - direction="l", - }, - [0x1893E]={ - category="lo", - direction="l", - }, - [0x1893F]={ - category="lo", - direction="l", - }, - [0x18940]={ - category="lo", - direction="l", - }, - [0x18941]={ - category="lo", - direction="l", - }, - [0x18942]={ - category="lo", - direction="l", - }, - [0x18943]={ - category="lo", - direction="l", - }, - [0x18944]={ - category="lo", - direction="l", - }, - [0x18945]={ - category="lo", - direction="l", - }, - [0x18946]={ - category="lo", - direction="l", - }, - [0x18947]={ - category="lo", - direction="l", - }, - [0x18948]={ - category="lo", - direction="l", - }, - [0x18949]={ - category="lo", - direction="l", - }, - [0x1894A]={ - category="lo", - direction="l", - }, - [0x1894B]={ - category="lo", - direction="l", - }, - [0x1894C]={ - category="lo", - direction="l", - }, - [0x1894D]={ - category="lo", - direction="l", - }, - [0x1894E]={ - category="lo", - direction="l", - }, - [0x1894F]={ - category="lo", - direction="l", - }, - [0x18950]={ - category="lo", - direction="l", - }, - [0x18951]={ - category="lo", - direction="l", - }, - [0x18952]={ - category="lo", - direction="l", - }, - [0x18953]={ - category="lo", - direction="l", - }, - [0x18954]={ - category="lo", - direction="l", - }, - [0x18955]={ - category="lo", - direction="l", - }, - [0x18956]={ - category="lo", - direction="l", - }, - [0x18957]={ - category="lo", - direction="l", - }, - [0x18958]={ - category="lo", - direction="l", - }, - [0x18959]={ - category="lo", - direction="l", - }, - [0x1895A]={ - category="lo", - direction="l", - }, - [0x1895B]={ - category="lo", - direction="l", - }, - [0x1895C]={ - category="lo", - direction="l", - }, - [0x1895D]={ - category="lo", - direction="l", - }, - [0x1895E]={ - category="lo", - direction="l", - }, - [0x1895F]={ - category="lo", - direction="l", - }, - [0x18960]={ - category="lo", - direction="l", - }, - [0x18961]={ - category="lo", - direction="l", - }, - [0x18962]={ - category="lo", - direction="l", - }, - [0x18963]={ - category="lo", - direction="l", - }, - [0x18964]={ - category="lo", - direction="l", - }, - [0x18965]={ - category="lo", - direction="l", - }, - [0x18966]={ - category="lo", - direction="l", - }, - [0x18967]={ - category="lo", - direction="l", - }, - [0x18968]={ - category="lo", - direction="l", - }, - [0x18969]={ - category="lo", - direction="l", - }, - [0x1896A]={ - category="lo", - direction="l", - }, - [0x1896B]={ - category="lo", - direction="l", - }, - [0x1896C]={ - category="lo", - direction="l", - }, - [0x1896D]={ - category="lo", - direction="l", - }, - [0x1896E]={ - category="lo", - direction="l", - }, - [0x1896F]={ - category="lo", - direction="l", - }, - [0x18970]={ - category="lo", - direction="l", - }, - [0x18971]={ - category="lo", - direction="l", - }, - [0x18972]={ - category="lo", - direction="l", - }, - [0x18973]={ - category="lo", - direction="l", - }, - [0x18974]={ - category="lo", - direction="l", - }, - [0x18975]={ - category="lo", - direction="l", - }, - [0x18976]={ - category="lo", - direction="l", - }, - [0x18977]={ - category="lo", - direction="l", - }, - [0x18978]={ - category="lo", - direction="l", - }, - [0x18979]={ - category="lo", - direction="l", - }, - [0x1897A]={ - category="lo", - direction="l", - }, - [0x1897B]={ - category="lo", - direction="l", - }, - [0x1897C]={ - category="lo", - direction="l", - }, - [0x1897D]={ - category="lo", - direction="l", - }, - [0x1897E]={ - category="lo", - direction="l", - }, - [0x1897F]={ - category="lo", - direction="l", - }, - [0x18980]={ - category="lo", - direction="l", - }, - [0x18981]={ - category="lo", - direction="l", - }, - [0x18982]={ - category="lo", - direction="l", - }, - [0x18983]={ - category="lo", - direction="l", - }, - [0x18984]={ - category="lo", - direction="l", - }, - [0x18985]={ - category="lo", - direction="l", - }, - [0x18986]={ - category="lo", - direction="l", - }, - [0x18987]={ - category="lo", - direction="l", - }, - [0x18988]={ - category="lo", - direction="l", - }, - [0x18989]={ - category="lo", - direction="l", - }, - [0x1898A]={ - category="lo", - direction="l", - }, - [0x1898B]={ - category="lo", - direction="l", - }, - [0x1898C]={ - category="lo", - direction="l", - }, - [0x1898D]={ - category="lo", - direction="l", - }, - [0x1898E]={ - category="lo", - direction="l", - }, - [0x1898F]={ - category="lo", - direction="l", - }, - [0x18990]={ - category="lo", - direction="l", - }, - [0x18991]={ - category="lo", - direction="l", - }, - [0x18992]={ - category="lo", - direction="l", - }, - [0x18993]={ - category="lo", - direction="l", - }, - [0x18994]={ - category="lo", - direction="l", - }, - [0x18995]={ - category="lo", - direction="l", - }, - [0x18996]={ - category="lo", - direction="l", - }, - [0x18997]={ - category="lo", - direction="l", - }, - [0x18998]={ - category="lo", - direction="l", - }, - [0x18999]={ - category="lo", - direction="l", - }, - [0x1899A]={ - category="lo", - direction="l", - }, - [0x1899B]={ - category="lo", - direction="l", - }, - [0x1899C]={ - category="lo", - direction="l", - }, - [0x1899D]={ - category="lo", - direction="l", - }, - [0x1899E]={ - category="lo", - direction="l", - }, - [0x1899F]={ - category="lo", - direction="l", - }, - [0x189A0]={ - category="lo", - direction="l", - }, - [0x189A1]={ - category="lo", - direction="l", - }, - [0x189A2]={ - category="lo", - direction="l", - }, - [0x189A3]={ - category="lo", - direction="l", - }, - [0x189A4]={ - category="lo", - direction="l", - }, - [0x189A5]={ - category="lo", - direction="l", - }, - [0x189A6]={ - category="lo", - direction="l", - }, - [0x189A7]={ - category="lo", - direction="l", - }, - [0x189A8]={ - category="lo", - direction="l", - }, - [0x189A9]={ - category="lo", - direction="l", - }, - [0x189AA]={ - category="lo", - direction="l", - }, - [0x189AB]={ - category="lo", - direction="l", - }, - [0x189AC]={ - category="lo", - direction="l", - }, - [0x189AD]={ - category="lo", - direction="l", - }, - [0x189AE]={ - category="lo", - direction="l", - }, - [0x189AF]={ - category="lo", - direction="l", - }, - [0x189B0]={ - category="lo", - direction="l", - }, - [0x189B1]={ - category="lo", - direction="l", - }, - [0x189B2]={ - category="lo", - direction="l", - }, - [0x189B3]={ - category="lo", - direction="l", - }, - [0x189B4]={ - category="lo", - direction="l", - }, - [0x189B5]={ - category="lo", - direction="l", - }, - [0x189B6]={ - category="lo", - direction="l", - }, - [0x189B7]={ - category="lo", - direction="l", - }, - [0x189B8]={ - category="lo", - direction="l", - }, - [0x189B9]={ - category="lo", - direction="l", - }, - [0x189BA]={ - category="lo", - direction="l", - }, - [0x189BB]={ - category="lo", - direction="l", - }, - [0x189BC]={ - category="lo", - direction="l", - }, - [0x189BD]={ - category="lo", - direction="l", - }, - [0x189BE]={ - category="lo", - direction="l", - }, - [0x189BF]={ - category="lo", - direction="l", - }, - [0x189C0]={ - category="lo", - direction="l", - }, - [0x189C1]={ - category="lo", - direction="l", - }, - [0x189C2]={ - category="lo", - direction="l", - }, - [0x189C3]={ - category="lo", - direction="l", - }, - [0x189C4]={ - category="lo", - direction="l", - }, - [0x189C5]={ - category="lo", - direction="l", - }, - [0x189C6]={ - category="lo", - direction="l", - }, - [0x189C7]={ - category="lo", - direction="l", - }, - [0x189C8]={ - category="lo", - direction="l", - }, - [0x189C9]={ - category="lo", - direction="l", - }, - [0x189CA]={ - category="lo", - direction="l", - }, - [0x189CB]={ - category="lo", - direction="l", - }, - [0x189CC]={ - category="lo", - direction="l", - }, - [0x189CD]={ - category="lo", - direction="l", - }, - [0x189CE]={ - category="lo", - direction="l", - }, - [0x189CF]={ - category="lo", - direction="l", - }, - [0x189D0]={ - category="lo", - direction="l", - }, - [0x189D1]={ - category="lo", - direction="l", - }, - [0x189D2]={ - category="lo", - direction="l", - }, - [0x189D3]={ - category="lo", - direction="l", - }, - [0x189D4]={ - category="lo", - direction="l", - }, - [0x189D5]={ - category="lo", - direction="l", - }, - [0x189D6]={ - category="lo", - direction="l", - }, - [0x189D7]={ - category="lo", - direction="l", - }, - [0x189D8]={ - category="lo", - direction="l", - }, - [0x189D9]={ - category="lo", - direction="l", - }, - [0x189DA]={ - category="lo", - direction="l", - }, - [0x189DB]={ - category="lo", - direction="l", - }, - [0x189DC]={ - category="lo", - direction="l", - }, - [0x189DD]={ - category="lo", - direction="l", - }, - [0x189DE]={ - category="lo", - direction="l", - }, - [0x189DF]={ - category="lo", - direction="l", - }, - [0x189E0]={ - category="lo", - direction="l", - }, - [0x189E1]={ - category="lo", - direction="l", - }, - [0x189E2]={ - category="lo", - direction="l", - }, - [0x189E3]={ - category="lo", - direction="l", - }, - [0x189E4]={ - category="lo", - direction="l", - }, - [0x189E5]={ - category="lo", - direction="l", - }, - [0x189E6]={ - category="lo", - direction="l", - }, - [0x189E7]={ - category="lo", - direction="l", - }, - [0x189E8]={ - category="lo", - direction="l", - }, - [0x189E9]={ - category="lo", - direction="l", - }, - [0x189EA]={ - category="lo", - direction="l", - }, - [0x189EB]={ - category="lo", - direction="l", - }, - [0x189EC]={ - category="lo", - direction="l", - }, - [0x189ED]={ - category="lo", - direction="l", - }, - [0x189EE]={ - category="lo", - direction="l", - }, - [0x189EF]={ - category="lo", - direction="l", - }, - [0x189F0]={ - category="lo", - direction="l", - }, - [0x189F1]={ - category="lo", - direction="l", - }, - [0x189F2]={ - category="lo", - direction="l", - }, - [0x189F3]={ - category="lo", - direction="l", - }, - [0x189F4]={ - category="lo", - direction="l", - }, - [0x189F5]={ - category="lo", - direction="l", - }, - [0x189F6]={ - category="lo", - direction="l", - }, - [0x189F7]={ - category="lo", - direction="l", - }, - [0x189F8]={ - category="lo", - direction="l", - }, - [0x189F9]={ - category="lo", - direction="l", - }, - [0x189FA]={ - category="lo", - direction="l", - }, - [0x189FB]={ - category="lo", - direction="l", - }, - [0x189FC]={ - category="lo", - direction="l", - }, - [0x189FD]={ - category="lo", - direction="l", - }, - [0x189FE]={ - category="lo", - direction="l", - }, - [0x189FF]={ - category="lo", - direction="l", - }, - [0x18A00]={ - category="lo", - direction="l", - }, - [0x18A01]={ - category="lo", - direction="l", - }, - [0x18A02]={ - category="lo", - direction="l", - }, - [0x18A03]={ - category="lo", - direction="l", - }, - [0x18A04]={ - category="lo", - direction="l", - }, - [0x18A05]={ - category="lo", - direction="l", - }, - [0x18A06]={ - category="lo", - direction="l", - }, - [0x18A07]={ - category="lo", - direction="l", - }, - [0x18A08]={ - category="lo", - direction="l", - }, - [0x18A09]={ - category="lo", - direction="l", - }, - [0x18A0A]={ - category="lo", - direction="l", - }, - [0x18A0B]={ - category="lo", - direction="l", - }, - [0x18A0C]={ - category="lo", - direction="l", - }, - [0x18A0D]={ - category="lo", - direction="l", - }, - [0x18A0E]={ - category="lo", - direction="l", - }, - [0x18A0F]={ - category="lo", - direction="l", - }, - [0x18A10]={ - category="lo", - direction="l", - }, - [0x18A11]={ - category="lo", - direction="l", - }, - [0x18A12]={ - category="lo", - direction="l", - }, - [0x18A13]={ - category="lo", - direction="l", - }, - [0x18A14]={ - category="lo", - direction="l", - }, - [0x18A15]={ - category="lo", - direction="l", - }, - [0x18A16]={ - category="lo", - direction="l", - }, - [0x18A17]={ - category="lo", - direction="l", - }, - [0x18A18]={ - category="lo", - direction="l", - }, - [0x18A19]={ - category="lo", - direction="l", - }, - [0x18A1A]={ - category="lo", - direction="l", - }, - [0x18A1B]={ - category="lo", - direction="l", - }, - [0x18A1C]={ - category="lo", - direction="l", - }, - [0x18A1D]={ - category="lo", - direction="l", - }, - [0x18A1E]={ - category="lo", - direction="l", - }, - [0x18A1F]={ - category="lo", - direction="l", - }, - [0x18A20]={ - category="lo", - direction="l", - }, - [0x18A21]={ - category="lo", - direction="l", - }, - [0x18A22]={ - category="lo", - direction="l", - }, - [0x18A23]={ - category="lo", - direction="l", - }, - [0x18A24]={ - category="lo", - direction="l", - }, - [0x18A25]={ - category="lo", - direction="l", - }, - [0x18A26]={ - category="lo", - direction="l", - }, - [0x18A27]={ - category="lo", - direction="l", - }, - [0x18A28]={ - category="lo", - direction="l", - }, - [0x18A29]={ - category="lo", - direction="l", - }, - [0x18A2A]={ - category="lo", - direction="l", - }, - [0x18A2B]={ - category="lo", - direction="l", - }, - [0x18A2C]={ - category="lo", - direction="l", - }, - [0x18A2D]={ - category="lo", - direction="l", - }, - [0x18A2E]={ - category="lo", - direction="l", - }, - [0x18A2F]={ - category="lo", - direction="l", - }, - [0x18A30]={ - category="lo", - direction="l", - }, - [0x18A31]={ - category="lo", - direction="l", - }, - [0x18A32]={ - category="lo", - direction="l", - }, - [0x18A33]={ - category="lo", - direction="l", - }, - [0x18A34]={ - category="lo", - direction="l", - }, - [0x18A35]={ - category="lo", - direction="l", - }, - [0x18A36]={ - category="lo", - direction="l", - }, - [0x18A37]={ - category="lo", - direction="l", - }, - [0x18A38]={ - category="lo", - direction="l", - }, - [0x18A39]={ - category="lo", - direction="l", - }, - [0x18A3A]={ - category="lo", - direction="l", - }, - [0x18A3B]={ - category="lo", - direction="l", - }, - [0x18A3C]={ - category="lo", - direction="l", - }, - [0x18A3D]={ - category="lo", - direction="l", - }, - [0x18A3E]={ - category="lo", - direction="l", - }, - [0x18A3F]={ - category="lo", - direction="l", - }, - [0x18A40]={ - category="lo", - direction="l", - }, - [0x18A41]={ - category="lo", - direction="l", - }, - [0x18A42]={ - category="lo", - direction="l", - }, - [0x18A43]={ - category="lo", - direction="l", - }, - [0x18A44]={ - category="lo", - direction="l", - }, - [0x18A45]={ - category="lo", - direction="l", - }, - [0x18A46]={ - category="lo", - direction="l", - }, - [0x18A47]={ - category="lo", - direction="l", - }, - [0x18A48]={ - category="lo", - direction="l", - }, - [0x18A49]={ - category="lo", - direction="l", - }, - [0x18A4A]={ - category="lo", - direction="l", - }, - [0x18A4B]={ - category="lo", - direction="l", - }, - [0x18A4C]={ - category="lo", - direction="l", - }, - [0x18A4D]={ - category="lo", - direction="l", - }, - [0x18A4E]={ - category="lo", - direction="l", - }, - [0x18A4F]={ - category="lo", - direction="l", - }, - [0x18A50]={ - category="lo", - direction="l", - }, - [0x18A51]={ - category="lo", - direction="l", - }, - [0x18A52]={ - category="lo", - direction="l", - }, - [0x18A53]={ - category="lo", - direction="l", - }, - [0x18A54]={ - category="lo", - direction="l", - }, - [0x18A55]={ - category="lo", - direction="l", - }, - [0x18A56]={ - category="lo", - direction="l", - }, - [0x18A57]={ - category="lo", - direction="l", - }, - [0x18A58]={ - category="lo", - direction="l", - }, - [0x18A59]={ - category="lo", - direction="l", - }, - [0x18A5A]={ - category="lo", - direction="l", - }, - [0x18A5B]={ - category="lo", - direction="l", - }, - [0x18A5C]={ - category="lo", - direction="l", - }, - [0x18A5D]={ - category="lo", - direction="l", - }, - [0x18A5E]={ - category="lo", - direction="l", - }, - [0x18A5F]={ - category="lo", - direction="l", - }, - [0x18A60]={ - category="lo", - direction="l", - }, - [0x18A61]={ - category="lo", - direction="l", - }, - [0x18A62]={ - category="lo", - direction="l", - }, - [0x18A63]={ - category="lo", - direction="l", - }, - [0x18A64]={ - category="lo", - direction="l", - }, - [0x18A65]={ - category="lo", - direction="l", - }, - [0x18A66]={ - category="lo", - direction="l", - }, - [0x18A67]={ - category="lo", - direction="l", - }, - [0x18A68]={ - category="lo", - direction="l", - }, - [0x18A69]={ - category="lo", - direction="l", - }, - [0x18A6A]={ - category="lo", - direction="l", - }, - [0x18A6B]={ - category="lo", - direction="l", - }, - [0x18A6C]={ - category="lo", - direction="l", - }, - [0x18A6D]={ - category="lo", - direction="l", - }, - [0x18A6E]={ - category="lo", - direction="l", - }, - [0x18A6F]={ - category="lo", - direction="l", - }, - [0x18A70]={ - category="lo", - direction="l", - }, - [0x18A71]={ - category="lo", - direction="l", - }, - [0x18A72]={ - category="lo", - direction="l", - }, - [0x18A73]={ - category="lo", - direction="l", - }, - [0x18A74]={ - category="lo", - direction="l", - }, - [0x18A75]={ - category="lo", - direction="l", - }, - [0x18A76]={ - category="lo", - direction="l", - }, - [0x18A77]={ - category="lo", - direction="l", - }, - [0x18A78]={ - category="lo", - direction="l", - }, - [0x18A79]={ - category="lo", - direction="l", - }, - [0x18A7A]={ - category="lo", - direction="l", - }, - [0x18A7B]={ - category="lo", - direction="l", - }, - [0x18A7C]={ - category="lo", - direction="l", - }, - [0x18A7D]={ - category="lo", - direction="l", - }, - [0x18A7E]={ - category="lo", - direction="l", - }, - [0x18A7F]={ - category="lo", - direction="l", - }, - [0x18A80]={ - category="lo", - direction="l", - }, - [0x18A81]={ - category="lo", - direction="l", - }, - [0x18A82]={ - category="lo", - direction="l", - }, - [0x18A83]={ - category="lo", - direction="l", - }, - [0x18A84]={ - category="lo", - direction="l", - }, - [0x18A85]={ - category="lo", - direction="l", - }, - [0x18A86]={ - category="lo", - direction="l", - }, - [0x18A87]={ - category="lo", - direction="l", - }, - [0x18A88]={ - category="lo", - direction="l", - }, - [0x18A89]={ - category="lo", - direction="l", - }, - [0x18A8A]={ - category="lo", - direction="l", - }, - [0x18A8B]={ - category="lo", - direction="l", - }, - [0x18A8C]={ - category="lo", - direction="l", - }, - [0x18A8D]={ - category="lo", - direction="l", - }, - [0x18A8E]={ - category="lo", - direction="l", - }, - [0x18A8F]={ - category="lo", - direction="l", - }, - [0x18A90]={ - category="lo", - direction="l", - }, - [0x18A91]={ - category="lo", - direction="l", - }, - [0x18A92]={ - category="lo", - direction="l", - }, - [0x18A93]={ - category="lo", - direction="l", - }, - [0x18A94]={ - category="lo", - direction="l", - }, - [0x18A95]={ - category="lo", - direction="l", - }, - [0x18A96]={ - category="lo", - direction="l", - }, - [0x18A97]={ - category="lo", - direction="l", - }, - [0x18A98]={ - category="lo", - direction="l", - }, - [0x18A99]={ - category="lo", - direction="l", - }, - [0x18A9A]={ - category="lo", - direction="l", - }, - [0x18A9B]={ - category="lo", - direction="l", - }, - [0x18A9C]={ - category="lo", - direction="l", - }, - [0x18A9D]={ - category="lo", - direction="l", - }, - [0x18A9E]={ - category="lo", - direction="l", - }, - [0x18A9F]={ - category="lo", - direction="l", - }, - [0x18AA0]={ - category="lo", - direction="l", - }, - [0x18AA1]={ - category="lo", - direction="l", - }, - [0x18AA2]={ - category="lo", - direction="l", - }, - [0x18AA3]={ - category="lo", - direction="l", - }, - [0x18AA4]={ - category="lo", - direction="l", - }, - [0x18AA5]={ - category="lo", - direction="l", - }, - [0x18AA6]={ - category="lo", - direction="l", - }, - [0x18AA7]={ - category="lo", - direction="l", - }, - [0x18AA8]={ - category="lo", - direction="l", - }, - [0x18AA9]={ - category="lo", - direction="l", - }, - [0x18AAA]={ - category="lo", - direction="l", - }, - [0x18AAB]={ - category="lo", - direction="l", - }, - [0x18AAC]={ - category="lo", - direction="l", - }, - [0x18AAD]={ - category="lo", - direction="l", - }, - [0x18AAE]={ - category="lo", - direction="l", - }, - [0x18AAF]={ - category="lo", - direction="l", - }, - [0x18AB0]={ - category="lo", - direction="l", - }, - [0x18AB1]={ - category="lo", - direction="l", - }, - [0x18AB2]={ - category="lo", - direction="l", - }, - [0x18AB3]={ - category="lo", - direction="l", - }, - [0x18AB4]={ - category="lo", - direction="l", - }, - [0x18AB5]={ - category="lo", - direction="l", - }, - [0x18AB6]={ - category="lo", - direction="l", - }, - [0x18AB7]={ - category="lo", - direction="l", - }, - [0x18AB8]={ - category="lo", - direction="l", - }, - [0x18AB9]={ - category="lo", - direction="l", - }, - [0x18ABA]={ - category="lo", - direction="l", - }, - [0x18ABB]={ - category="lo", - direction="l", - }, - [0x18ABC]={ - category="lo", - direction="l", - }, - [0x18ABD]={ - category="lo", - direction="l", - }, - [0x18ABE]={ - category="lo", - direction="l", - }, - [0x18ABF]={ - category="lo", - direction="l", - }, - [0x18AC0]={ - category="lo", - direction="l", - }, - [0x18AC1]={ - category="lo", - direction="l", - }, - [0x18AC2]={ - category="lo", - direction="l", - }, - [0x18AC3]={ - category="lo", - direction="l", - }, - [0x18AC4]={ - category="lo", - direction="l", - }, - [0x18AC5]={ - category="lo", - direction="l", - }, - [0x18AC6]={ - category="lo", - direction="l", - }, - [0x18AC7]={ - category="lo", - direction="l", - }, - [0x18AC8]={ - category="lo", - direction="l", - }, - [0x18AC9]={ - category="lo", - direction="l", - }, - [0x18ACA]={ - category="lo", - direction="l", - }, - [0x18ACB]={ - category="lo", - direction="l", - }, - [0x18ACC]={ - category="lo", - direction="l", - }, - [0x18ACD]={ - category="lo", - direction="l", - }, - [0x18ACE]={ - category="lo", - direction="l", - }, - [0x18ACF]={ - category="lo", - direction="l", - }, - [0x18AD0]={ - category="lo", - direction="l", - }, - [0x18AD1]={ - category="lo", - direction="l", - }, - [0x18AD2]={ - category="lo", - direction="l", - }, - [0x18AD3]={ - category="lo", - direction="l", - }, - [0x18AD4]={ - category="lo", - direction="l", - }, - [0x18AD5]={ - category="lo", - direction="l", - }, - [0x18AD6]={ - category="lo", - direction="l", - }, - [0x18AD7]={ - category="lo", - direction="l", - }, - [0x18AD8]={ - category="lo", - direction="l", - }, - [0x18AD9]={ - category="lo", - direction="l", - }, - [0x18ADA]={ - category="lo", - direction="l", - }, - [0x18ADB]={ - category="lo", - direction="l", - }, - [0x18ADC]={ - category="lo", - direction="l", - }, - [0x18ADD]={ - category="lo", - direction="l", - }, - [0x18ADE]={ - category="lo", - direction="l", - }, - [0x18ADF]={ - category="lo", - direction="l", - }, - [0x18AE0]={ - category="lo", - direction="l", - }, - [0x18AE1]={ - category="lo", - direction="l", - }, - [0x18AE2]={ - category="lo", - direction="l", - }, - [0x18AE3]={ - category="lo", - direction="l", - }, - [0x18AE4]={ - category="lo", - direction="l", - }, - [0x18AE5]={ - category="lo", - direction="l", - }, - [0x18AE6]={ - category="lo", - direction="l", - }, - [0x18AE7]={ - category="lo", - direction="l", - }, - [0x18AE8]={ - category="lo", - direction="l", - }, - [0x18AE9]={ - category="lo", - direction="l", - }, - [0x18AEA]={ - category="lo", - direction="l", - }, - [0x18AEB]={ - category="lo", - direction="l", - }, - [0x18AEC]={ - category="lo", - direction="l", - }, - [0x18AED]={ - category="lo", - direction="l", - }, - [0x18AEE]={ - category="lo", - direction="l", - }, - [0x18AEF]={ - category="lo", - direction="l", - }, - [0x18AF0]={ - category="lo", - direction="l", - }, - [0x18AF1]={ - category="lo", - direction="l", - }, - [0x18AF2]={ - category="lo", - direction="l", - }, - [0x1B000]={ - category="lo", - direction="l", - }, - [0x1B001]={ - category="lo", - direction="l", - }, - [0x1BC00]={ - category="lo", - direction="l", - }, - [0x1BC01]={ - category="lo", - direction="l", - }, - [0x1BC02]={ - category="lo", - direction="l", - }, - [0x1BC03]={ - category="lo", - direction="l", - }, - [0x1BC04]={ - category="lo", - direction="l", - }, - [0x1BC05]={ - category="lo", - direction="l", - }, - [0x1BC06]={ - category="lo", - direction="l", - }, - [0x1BC07]={ - category="lo", - direction="l", - }, - [0x1BC08]={ - category="lo", - direction="l", - }, - [0x1BC09]={ - category="lo", - direction="l", - }, - [0x1BC0A]={ - category="lo", - direction="l", - }, - [0x1BC0B]={ - category="lo", - direction="l", - }, - [0x1BC0C]={ - category="lo", - direction="l", - }, - [0x1BC0D]={ - category="lo", - direction="l", - }, - [0x1BC0E]={ - category="lo", - direction="l", - }, - [0x1BC0F]={ - category="lo", - direction="l", - }, - [0x1BC10]={ - category="lo", - direction="l", - }, - [0x1BC11]={ - category="lo", - direction="l", - }, - [0x1BC12]={ - category="lo", - direction="l", - }, - [0x1BC13]={ - category="lo", - direction="l", - }, - [0x1BC14]={ - category="lo", - direction="l", - }, - [0x1BC15]={ - category="lo", - direction="l", - }, - [0x1BC16]={ - category="lo", - direction="l", - }, - [0x1BC17]={ - category="lo", - direction="l", - }, - [0x1BC18]={ - category="lo", - direction="l", - }, - [0x1BC19]={ - category="lo", - direction="l", - }, - [0x1BC1A]={ - category="lo", - direction="l", - }, - [0x1BC1B]={ - category="lo", - direction="l", - }, - [0x1BC1C]={ - category="lo", - direction="l", - }, - [0x1BC1D]={ - category="lo", - direction="l", - }, - [0x1BC1E]={ - category="lo", - direction="l", - }, - [0x1BC1F]={ - category="lo", - direction="l", - }, - [0x1BC20]={ - category="lo", - direction="l", - }, - [0x1BC21]={ - category="lo", - direction="l", - }, - [0x1BC22]={ - category="lo", - direction="l", - }, - [0x1BC23]={ - category="lo", - direction="l", - }, - [0x1BC24]={ - category="lo", - direction="l", - }, - [0x1BC25]={ - category="lo", - direction="l", - }, - [0x1BC26]={ - category="lo", - direction="l", - }, - [0x1BC27]={ - category="lo", - direction="l", - }, - [0x1BC28]={ - category="lo", - direction="l", - }, - [0x1BC29]={ - category="lo", - direction="l", - }, - [0x1BC2A]={ - category="lo", - direction="l", - }, - [0x1BC2B]={ - category="lo", - direction="l", - }, - [0x1BC2C]={ - category="lo", - direction="l", - }, - [0x1BC2D]={ - category="lo", - direction="l", - }, - [0x1BC2E]={ - category="lo", - direction="l", - }, - [0x1BC2F]={ - category="lo", - direction="l", - }, - [0x1BC30]={ - category="lo", - direction="l", - }, - [0x1BC31]={ - category="lo", - direction="l", - }, - [0x1BC32]={ - category="lo", - direction="l", - }, - [0x1BC33]={ - category="lo", - direction="l", - }, - [0x1BC34]={ - category="lo", - direction="l", - }, - [0x1BC35]={ - category="lo", - direction="l", - }, - [0x1BC36]={ - category="lo", - direction="l", - }, - [0x1BC37]={ - category="lo", - direction="l", - }, - [0x1BC38]={ - category="lo", - direction="l", - }, - [0x1BC39]={ - category="lo", - direction="l", - }, - [0x1BC3A]={ - category="lo", - direction="l", - }, - [0x1BC3B]={ - category="lo", - direction="l", - }, - [0x1BC3C]={ - category="lo", - direction="l", - }, - [0x1BC3D]={ - category="lo", - direction="l", - }, - [0x1BC3E]={ - category="lo", - direction="l", - }, - [0x1BC3F]={ - category="lo", - direction="l", - }, - [0x1BC40]={ - category="lo", - direction="l", - }, - [0x1BC41]={ - category="lo", - direction="l", - }, - [0x1BC42]={ - category="lo", - direction="l", - }, - [0x1BC43]={ - category="lo", - direction="l", - }, - [0x1BC44]={ - category="lo", - direction="l", - }, - [0x1BC45]={ - category="lo", - direction="l", - }, - [0x1BC46]={ - category="lo", - direction="l", - }, - [0x1BC47]={ - category="lo", - direction="l", - }, - [0x1BC48]={ - category="lo", - direction="l", - }, - [0x1BC49]={ - category="lo", - direction="l", - }, - [0x1BC4A]={ - category="lo", - direction="l", - }, - [0x1BC4B]={ - category="lo", - direction="l", - }, - [0x1BC4C]={ - category="lo", - direction="l", - }, - [0x1BC4D]={ - category="lo", - direction="l", - }, - [0x1BC4E]={ - category="lo", - direction="l", - }, - [0x1BC4F]={ - category="lo", - direction="l", - }, - [0x1BC50]={ - category="lo", - direction="l", - }, - [0x1BC51]={ - category="lo", - direction="l", - }, - [0x1BC52]={ - category="lo", - direction="l", - }, - [0x1BC53]={ - category="lo", - direction="l", - }, - [0x1BC54]={ - category="lo", - direction="l", - }, - [0x1BC55]={ - category="lo", - direction="l", - }, - [0x1BC56]={ - category="lo", - direction="l", - }, - [0x1BC57]={ - category="lo", - direction="l", - }, - [0x1BC58]={ - category="lo", - direction="l", - }, - [0x1BC59]={ - category="lo", - direction="l", - }, - [0x1BC5A]={ - category="lo", - direction="l", - }, - [0x1BC5B]={ - category="lo", - direction="l", - }, - [0x1BC5C]={ - category="lo", - direction="l", - }, - [0x1BC5D]={ - category="lo", - direction="l", - }, - [0x1BC5E]={ - category="lo", - direction="l", - }, - [0x1BC5F]={ - category="lo", - direction="l", - }, - [0x1BC60]={ - category="lo", - direction="l", - }, - [0x1BC61]={ - category="lo", - direction="l", - }, - [0x1BC62]={ - category="lo", - direction="l", - }, - [0x1BC63]={ - category="lo", - direction="l", - }, - [0x1BC64]={ - category="lo", - direction="l", - }, - [0x1BC65]={ - category="lo", - direction="l", - }, - [0x1BC66]={ - category="lo", - direction="l", - }, - [0x1BC67]={ - category="lo", - direction="l", - }, - [0x1BC68]={ - category="lo", - direction="l", - }, - [0x1BC69]={ - category="lo", - direction="l", - }, - [0x1BC6A]={ - category="lo", - direction="l", - }, - [0x1BC70]={ - category="lo", - direction="l", - }, - [0x1BC71]={ - category="lo", - direction="l", - }, - [0x1BC72]={ - category="lo", - direction="l", - }, - [0x1BC73]={ - category="lo", - direction="l", - }, - [0x1BC74]={ - category="lo", - direction="l", - }, - [0x1BC75]={ - category="lo", - direction="l", - }, - [0x1BC76]={ - category="lo", - direction="l", - }, - [0x1BC77]={ - category="lo", - direction="l", - }, - [0x1BC78]={ - category="lo", - direction="l", - }, - [0x1BC79]={ - category="lo", - direction="l", - }, - [0x1BC7A]={ - category="lo", - direction="l", - }, - [0x1BC7B]={ - category="lo", - direction="l", - }, - [0x1BC7C]={ - category="lo", - direction="l", - }, - [0x1BC80]={ - category="lo", - direction="l", - }, - [0x1BC81]={ - category="lo", - direction="l", - }, - [0x1BC82]={ - category="lo", - direction="l", - }, - [0x1BC83]={ - category="lo", - direction="l", - }, - [0x1BC84]={ - category="lo", - direction="l", - }, - [0x1BC85]={ - category="lo", - direction="l", - }, - [0x1BC86]={ - category="lo", - direction="l", - }, - [0x1BC87]={ - category="lo", - direction="l", - }, - [0x1BC88]={ - category="lo", - direction="l", - }, - [0x1BC90]={ - category="lo", - direction="l", - }, - [0x1BC91]={ - category="lo", - direction="l", - }, - [0x1BC92]={ - category="lo", - direction="l", - }, - [0x1BC93]={ - category="lo", - direction="l", - }, - [0x1BC94]={ - category="lo", - direction="l", - }, - [0x1BC95]={ - category="lo", - direction="l", - }, - [0x1BC96]={ - category="lo", - direction="l", - }, - [0x1BC97]={ - category="lo", - direction="l", - }, - [0x1BC98]={ - category="lo", - direction="l", - }, - [0x1BC99]={ - category="lo", - direction="l", - }, - [0x1BC9C]={ - category="so", - direction="l", - }, - [0x1BC9D]={ - category="mn", - direction="nsm", - }, - [0x1BC9E]={ - category="mn", - direction="nsm", - }, - [0x1BC9F]={ - category="po", - direction="l", - }, - [0x1BCA0]={ - category="cf", - direction="bn", - }, - [0x1BCA1]={ - category="cf", - direction="bn", - }, - [0x1BCA2]={ - category="cf", - direction="bn", - }, - [0x1BCA3]={ - category="cf", - direction="bn", - }, - [0x1D000]={ - category="so", - direction="l", - }, - [0x1D001]={ - category="so", - direction="l", - }, - [0x1D002]={ - category="so", - direction="l", - }, - [0x1D003]={ - category="so", - direction="l", - }, - [0x1D004]={ - category="so", - direction="l", - }, - [0x1D005]={ - category="so", - direction="l", - }, - [0x1D006]={ - category="so", - direction="l", - }, - [0x1D007]={ - category="so", - direction="l", - }, - [0x1D008]={ - category="so", - direction="l", - }, - [0x1D009]={ - category="so", - direction="l", - }, - [0x1D00A]={ - category="so", - direction="l", - }, - [0x1D00B]={ - category="so", - direction="l", - }, - [0x1D00C]={ - category="so", - direction="l", - }, - [0x1D00D]={ - category="so", - direction="l", - }, - [0x1D00E]={ - category="so", - direction="l", - }, - [0x1D00F]={ - category="so", - direction="l", - }, - [0x1D010]={ - category="so", - direction="l", - }, - [0x1D011]={ - category="so", - direction="l", - }, - [0x1D012]={ - category="so", - direction="l", - }, - [0x1D013]={ - category="so", - direction="l", - }, - [0x1D014]={ - category="so", - direction="l", - }, - [0x1D015]={ - category="so", - direction="l", - }, - [0x1D016]={ - category="so", - direction="l", - }, - [0x1D017]={ - category="so", - direction="l", - }, - [0x1D018]={ - category="so", - direction="l", - }, - [0x1D019]={ - category="so", - direction="l", - }, - [0x1D01A]={ - category="so", - direction="l", - }, - [0x1D01B]={ - category="so", - direction="l", - }, - [0x1D01C]={ - category="so", - direction="l", - }, - [0x1D01D]={ - category="so", - direction="l", - }, - [0x1D01E]={ - category="so", - direction="l", - }, - [0x1D01F]={ - category="so", - direction="l", - }, - [0x1D020]={ - category="so", - direction="l", - }, - [0x1D021]={ - category="so", - direction="l", - }, - [0x1D022]={ - category="so", - direction="l", - }, - [0x1D023]={ - category="so", - direction="l", - }, - [0x1D024]={ - category="so", - direction="l", - }, - [0x1D025]={ - category="so", - direction="l", - }, - [0x1D026]={ - category="so", - direction="l", - }, - [0x1D027]={ - category="so", - direction="l", - }, - [0x1D028]={ - category="so", - direction="l", - }, - [0x1D029]={ - category="so", - direction="l", - }, - [0x1D02A]={ - category="so", - direction="l", - }, - [0x1D02B]={ - category="so", - direction="l", - }, - [0x1D02C]={ - category="so", - direction="l", - }, - [0x1D02D]={ - category="so", - direction="l", - }, - [0x1D02E]={ - category="so", - direction="l", - }, - [0x1D02F]={ - category="so", - direction="l", - }, - [0x1D030]={ - category="so", - direction="l", - }, - [0x1D031]={ - category="so", - direction="l", - }, - [0x1D032]={ - category="so", - direction="l", - }, - [0x1D033]={ - category="so", - direction="l", - }, - [0x1D034]={ - category="so", - direction="l", - }, - [0x1D035]={ - category="so", - direction="l", - }, - [0x1D036]={ - category="so", - direction="l", - }, - [0x1D037]={ - category="so", - direction="l", - }, - [0x1D038]={ - category="so", - direction="l", - }, - [0x1D039]={ - category="so", - direction="l", - }, - [0x1D03A]={ - category="so", - direction="l", - }, - [0x1D03B]={ - category="so", - direction="l", - }, - [0x1D03C]={ - category="so", - direction="l", - }, - [0x1D03D]={ - category="so", - direction="l", - }, - [0x1D03E]={ - category="so", - direction="l", - }, - [0x1D03F]={ - category="so", - direction="l", - }, - [0x1D040]={ - category="so", - direction="l", - }, - [0x1D041]={ - category="so", - direction="l", - }, - [0x1D042]={ - category="so", - direction="l", - }, - [0x1D043]={ - category="so", - direction="l", - }, - [0x1D044]={ - category="so", - direction="l", - }, - [0x1D045]={ - category="so", - direction="l", - }, - [0x1D046]={ - category="so", - direction="l", - }, - [0x1D047]={ - category="so", - direction="l", - }, - [0x1D048]={ - category="so", - direction="l", - }, - [0x1D049]={ - category="so", - direction="l", - }, - [0x1D04A]={ - category="so", - direction="l", - }, - [0x1D04B]={ - category="so", - direction="l", - }, - [0x1D04C]={ - category="so", - direction="l", - }, - [0x1D04D]={ - category="so", - direction="l", - }, - [0x1D04E]={ - category="so", - direction="l", - }, - [0x1D04F]={ - category="so", - direction="l", - }, - [0x1D050]={ - category="so", - direction="l", - }, - [0x1D051]={ - category="so", - direction="l", - }, - [0x1D052]={ - category="so", - direction="l", - }, - [0x1D053]={ - category="so", - direction="l", - }, - [0x1D054]={ - category="so", - direction="l", - }, - [0x1D055]={ - category="so", - direction="l", - }, - [0x1D056]={ - category="so", - direction="l", - }, - [0x1D057]={ - category="so", - direction="l", - }, - [0x1D058]={ - category="so", - direction="l", - }, - [0x1D059]={ - category="so", - direction="l", - }, - [0x1D05A]={ - category="so", - direction="l", - }, - [0x1D05B]={ - category="so", - direction="l", - }, - [0x1D05C]={ - category="so", - direction="l", - }, - [0x1D05D]={ - category="so", - direction="l", - }, - [0x1D05E]={ - category="so", - direction="l", - }, - [0x1D05F]={ - category="so", - direction="l", - }, - [0x1D060]={ - category="so", - direction="l", - }, - [0x1D061]={ - category="so", - direction="l", - }, - [0x1D062]={ - category="so", - direction="l", - }, - [0x1D063]={ - category="so", - direction="l", - }, - [0x1D064]={ - category="so", - direction="l", - }, - [0x1D065]={ - category="so", - direction="l", - }, - [0x1D066]={ - category="so", - direction="l", - }, - [0x1D067]={ - category="so", - direction="l", - }, - [0x1D068]={ - category="so", - direction="l", - }, - [0x1D069]={ - category="so", - direction="l", - }, - [0x1D06A]={ - category="so", - direction="l", - }, - [0x1D06B]={ - category="so", - direction="l", - }, - [0x1D06C]={ - category="so", - direction="l", - }, - [0x1D06D]={ - category="so", - direction="l", - }, - [0x1D06E]={ - category="so", - direction="l", - }, - [0x1D06F]={ - category="so", - direction="l", - }, - [0x1D070]={ - category="so", - direction="l", - }, - [0x1D071]={ - category="so", - direction="l", - }, - [0x1D072]={ - category="so", - direction="l", - }, - [0x1D073]={ - category="so", - direction="l", - }, - [0x1D074]={ - category="so", - direction="l", - }, - [0x1D075]={ - category="so", - direction="l", - }, - [0x1D076]={ - category="so", - direction="l", - }, - [0x1D077]={ - category="so", - direction="l", - }, - [0x1D078]={ - category="so", - direction="l", - }, - [0x1D079]={ - category="so", - direction="l", - }, - [0x1D07A]={ - category="so", - direction="l", - }, - [0x1D07B]={ - category="so", - direction="l", - }, - [0x1D07C]={ - category="so", - direction="l", - }, - [0x1D07D]={ - category="so", - direction="l", - }, - [0x1D07E]={ - category="so", - direction="l", - }, - [0x1D07F]={ - category="so", - direction="l", - }, - [0x1D080]={ - category="so", - direction="l", - }, - [0x1D081]={ - category="so", - direction="l", - }, - [0x1D082]={ - category="so", - direction="l", - }, - [0x1D083]={ - category="so", - direction="l", - }, - [0x1D084]={ - category="so", - direction="l", - }, - [0x1D085]={ - category="so", - direction="l", - }, - [0x1D086]={ - category="so", - direction="l", - }, - [0x1D087]={ - category="so", - direction="l", - }, - [0x1D088]={ - category="so", - direction="l", - }, - [0x1D089]={ - category="so", - direction="l", - }, - [0x1D08A]={ - category="so", - direction="l", - }, - [0x1D08B]={ - category="so", - direction="l", - }, - [0x1D08C]={ - category="so", - direction="l", - }, - [0x1D08D]={ - category="so", - direction="l", - }, - [0x1D08E]={ - category="so", - direction="l", - }, - [0x1D08F]={ - category="so", - direction="l", - }, - [0x1D090]={ - category="so", - direction="l", - }, - [0x1D091]={ - category="so", - direction="l", - }, - [0x1D092]={ - category="so", - direction="l", - }, - [0x1D093]={ - category="so", - direction="l", - }, - [0x1D094]={ - category="so", - direction="l", - }, - [0x1D095]={ - category="so", - direction="l", - }, - [0x1D096]={ - category="so", - direction="l", - }, - [0x1D097]={ - category="so", - direction="l", - }, - [0x1D098]={ - category="so", - direction="l", - }, - [0x1D099]={ - category="so", - direction="l", - }, - [0x1D09A]={ - category="so", - direction="l", - }, - [0x1D09B]={ - category="so", - direction="l", - }, - [0x1D09C]={ - category="so", - direction="l", - }, - [0x1D09D]={ - category="so", - direction="l", - }, - [0x1D09E]={ - category="so", - direction="l", - }, - [0x1D09F]={ - category="so", - direction="l", - }, - [0x1D0A0]={ - category="so", - direction="l", - }, - [0x1D0A1]={ - category="so", - direction="l", - }, - [0x1D0A2]={ - category="so", - direction="l", - }, - [0x1D0A3]={ - category="so", - direction="l", - }, - [0x1D0A4]={ - category="so", - direction="l", - }, - [0x1D0A5]={ - category="so", - direction="l", - }, - [0x1D0A6]={ - category="so", - direction="l", - }, - [0x1D0A7]={ - category="so", - direction="l", - }, - [0x1D0A8]={ - category="so", - direction="l", - }, - [0x1D0A9]={ - category="so", - direction="l", - }, - [0x1D0AA]={ - category="so", - direction="l", - }, - [0x1D0AB]={ - category="so", - direction="l", - }, - [0x1D0AC]={ - category="so", - direction="l", - }, - [0x1D0AD]={ - category="so", - direction="l", - }, - [0x1D0AE]={ - category="so", - direction="l", - }, - [0x1D0AF]={ - category="so", - direction="l", - }, - [0x1D0B0]={ - category="so", - direction="l", - }, - [0x1D0B1]={ - category="so", - direction="l", - }, - [0x1D0B2]={ - category="so", - direction="l", - }, - [0x1D0B3]={ - category="so", - direction="l", - }, - [0x1D0B4]={ - category="so", - direction="l", - }, - [0x1D0B5]={ - category="so", - direction="l", - }, - [0x1D0B6]={ - category="so", - direction="l", - }, - [0x1D0B7]={ - category="so", - direction="l", - }, - [0x1D0B8]={ - category="so", - direction="l", - }, - [0x1D0B9]={ - category="so", - direction="l", - }, - [0x1D0BA]={ - category="so", - direction="l", - }, - [0x1D0BB]={ - category="so", - direction="l", - }, - [0x1D0BC]={ - category="so", - direction="l", - }, - [0x1D0BD]={ - category="so", - direction="l", - }, - [0x1D0BE]={ - category="so", - direction="l", - }, - [0x1D0BF]={ - category="so", - direction="l", - }, - [0x1D0C0]={ - category="so", - direction="l", - }, - [0x1D0C1]={ - category="so", - direction="l", - }, - [0x1D0C2]={ - category="so", - direction="l", - }, - [0x1D0C3]={ - category="so", - direction="l", - }, - [0x1D0C4]={ - category="so", - direction="l", - }, - [0x1D0C5]={ - category="so", - direction="l", - }, - [0x1D0C6]={ - category="so", - direction="l", - }, - [0x1D0C7]={ - category="so", - direction="l", - }, - [0x1D0C8]={ - category="so", - direction="l", - }, - [0x1D0C9]={ - category="so", - direction="l", - }, - [0x1D0CA]={ - category="so", - direction="l", - }, - [0x1D0CB]={ - category="so", - direction="l", - }, - [0x1D0CC]={ - category="so", - direction="l", - }, - [0x1D0CD]={ - category="so", - direction="l", - }, - [0x1D0CE]={ - category="so", - direction="l", - }, - [0x1D0CF]={ - category="so", - direction="l", - }, - [0x1D0D0]={ - category="so", - direction="l", - }, - [0x1D0D1]={ - category="so", - direction="l", - }, - [0x1D0D2]={ - category="so", - direction="l", - }, - [0x1D0D3]={ - category="so", - direction="l", - }, - [0x1D0D4]={ - category="so", - direction="l", - }, - [0x1D0D5]={ - category="so", - direction="l", - }, - [0x1D0D6]={ - category="so", - direction="l", - }, - [0x1D0D7]={ - category="so", - direction="l", - }, - [0x1D0D8]={ - category="so", - direction="l", - }, - [0x1D0D9]={ - category="so", - direction="l", - }, - [0x1D0DA]={ - category="so", - direction="l", - }, - [0x1D0DB]={ - category="so", - direction="l", - }, - [0x1D0DC]={ - category="so", - direction="l", - }, - [0x1D0DD]={ - category="so", - direction="l", - }, - [0x1D0DE]={ - category="so", - direction="l", - }, - [0x1D0DF]={ - category="so", - direction="l", - }, - [0x1D0E0]={ - category="so", - direction="l", - }, - [0x1D0E1]={ - category="so", - direction="l", - }, - [0x1D0E2]={ - category="so", - direction="l", - }, - [0x1D0E3]={ - category="so", - direction="l", - }, - [0x1D0E4]={ - category="so", - direction="l", - }, - [0x1D0E5]={ - category="so", - direction="l", - }, - [0x1D0E6]={ - category="so", - direction="l", - }, - [0x1D0E7]={ - category="so", - direction="l", - }, - [0x1D0E8]={ - category="so", - direction="l", - }, - [0x1D0E9]={ - category="so", - direction="l", - }, - [0x1D0EA]={ - category="so", - direction="l", - }, - [0x1D0EB]={ - category="so", - direction="l", - }, - [0x1D0EC]={ - category="so", - direction="l", - }, - [0x1D0ED]={ - category="so", - direction="l", - }, - [0x1D0EE]={ - category="so", - direction="l", - }, - [0x1D0EF]={ - category="so", - direction="l", - }, - [0x1D0F0]={ - category="so", - direction="l", - }, - [0x1D0F1]={ - category="so", - direction="l", - }, - [0x1D0F2]={ - category="so", - direction="l", - }, - [0x1D0F3]={ - category="so", - direction="l", - }, - [0x1D0F4]={ - category="so", - direction="l", - }, - [0x1D0F5]={ - category="so", - direction="l", - }, - [0x1D100]={ - category="so", - direction="l", - }, - [0x1D101]={ - category="so", - direction="l", - }, - [0x1D102]={ - category="so", - direction="l", - }, - [0x1D103]={ - category="so", - direction="l", - }, - [0x1D104]={ - category="so", - direction="l", - }, - [0x1D105]={ - category="so", - direction="l", - }, - [0x1D106]={ - category="so", - direction="l", - }, - [0x1D107]={ - category="so", - direction="l", - }, - [0x1D108]={ - category="so", - direction="l", - }, - [0x1D109]={ - category="so", - direction="l", - }, - [0x1D10A]={ - category="so", - direction="l", - }, - [0x1D10B]={ - category="so", - direction="l", - }, - [0x1D10C]={ - category="so", - direction="l", - }, - [0x1D10D]={ - category="so", - direction="l", - }, - [0x1D10E]={ - category="so", - direction="l", - }, - [0x1D10F]={ - category="so", - direction="l", - }, - [0x1D110]={ - category="so", - direction="l", - }, - [0x1D111]={ - category="so", - direction="l", - }, - [0x1D112]={ - category="so", - direction="l", - }, - [0x1D113]={ - category="so", - direction="l", - }, - [0x1D114]={ - category="so", - direction="l", - }, - [0x1D115]={ - category="so", - direction="l", - }, - [0x1D116]={ - category="so", - direction="l", - }, - [0x1D117]={ - category="so", - direction="l", - }, - [0x1D118]={ - category="so", - direction="l", - }, - [0x1D119]={ - category="so", - direction="l", - }, - [0x1D11A]={ - category="so", - direction="l", - }, - [0x1D11B]={ - category="so", - direction="l", - }, - [0x1D11C]={ - category="so", - direction="l", - }, - [0x1D11D]={ - category="so", - direction="l", - }, - [0x1D11E]={ - category="so", - direction="l", - }, - [0x1D11F]={ - category="so", - direction="l", - }, - [0x1D120]={ - category="so", - direction="l", - }, - [0x1D121]={ - category="so", - direction="l", - }, - [0x1D122]={ - category="so", - direction="l", - }, - [0x1D123]={ - category="so", - direction="l", - }, - [0x1D124]={ - category="so", - direction="l", - }, - [0x1D125]={ - category="so", - direction="l", - }, - [0x1D126]={ - category="so", - direction="l", - }, - [0x1D129]={ - category="so", - direction="l", - }, - [0x1D12A]={ - category="so", - direction="l", - }, - [0x1D12B]={ - category="so", - direction="l", - }, - [0x1D12C]={ - category="so", - direction="l", - }, - [0x1D12D]={ - category="so", - direction="l", - }, - [0x1D12E]={ - category="so", - direction="l", - }, - [0x1D12F]={ - category="so", - direction="l", - }, - [0x1D130]={ - category="so", - direction="l", - }, - [0x1D131]={ - category="so", - direction="l", - }, - [0x1D132]={ - category="so", - direction="l", - }, - [0x1D133]={ - category="so", - direction="l", - }, - [0x1D134]={ - category="so", - direction="l", - }, - [0x1D135]={ - category="so", - direction="l", - }, - [0x1D136]={ - category="so", - direction="l", - }, - [0x1D137]={ - category="so", - direction="l", - }, - [0x1D138]={ - category="so", - direction="l", - }, - [0x1D139]={ - category="so", - direction="l", - }, - [0x1D13A]={ - category="so", - direction="l", - }, - [0x1D13B]={ - category="so", - direction="l", - }, - [0x1D13C]={ - category="so", - direction="l", - }, - [0x1D13D]={ - category="so", - direction="l", - }, - [0x1D13E]={ - category="so", - direction="l", - }, - [0x1D13F]={ - category="so", - direction="l", - }, - [0x1D140]={ - category="so", - direction="l", - }, - [0x1D141]={ - category="so", - direction="l", - }, - [0x1D142]={ - category="so", - direction="l", - }, - [0x1D143]={ - category="so", - direction="l", - }, - [0x1D144]={ - category="so", - direction="l", - }, - [0x1D145]={ - category="so", - direction="l", - }, - [0x1D146]={ - category="so", - direction="l", - }, - [0x1D147]={ - category="so", - direction="l", - }, - [0x1D148]={ - category="so", - direction="l", - }, - [0x1D149]={ - category="so", - direction="l", - }, - [0x1D14A]={ - category="so", - direction="l", - }, - [0x1D14B]={ - category="so", - direction="l", - }, - [0x1D14C]={ - category="so", - direction="l", - }, - [0x1D14D]={ - category="so", - direction="l", - }, - [0x1D14E]={ - category="so", - direction="l", - }, - [0x1D14F]={ - category="so", - direction="l", - }, - [0x1D150]={ - category="so", - direction="l", - }, - [0x1D151]={ - category="so", - direction="l", - }, - [0x1D152]={ - category="so", - direction="l", - }, - [0x1D153]={ - category="so", - direction="l", - }, - [0x1D154]={ - category="so", - direction="l", - }, - [0x1D155]={ - category="so", - direction="l", - }, - [0x1D156]={ - category="so", - direction="l", - }, - [0x1D157]={ - category="so", - direction="l", - }, - [0x1D158]={ - category="so", - direction="l", - }, - [0x1D159]={ - category="so", - direction="l", - }, - [0x1D15A]={ - category="so", - direction="l", - }, - [0x1D15B]={ - category="so", - direction="l", - }, - [0x1D15C]={ - category="so", - direction="l", - }, - [0x1D15D]={ - category="so", - direction="l", - }, - [0x1D15E]={ - category="so", - direction="l", - }, - [0x1D15F]={ - category="so", - direction="l", - }, - [0x1D160]={ - category="so", - direction="l", - }, - [0x1D161]={ - category="so", - direction="l", - }, - [0x1D162]={ - category="so", - direction="l", - }, - [0x1D163]={ - category="so", - direction="l", - }, - [0x1D164]={ - category="so", - direction="l", - }, - [0x1D165]={ - category="mc", - direction="l", - }, - [0x1D166]={ - category="mc", - direction="l", - }, - [0x1D167]={ - category="mn", - direction="nsm", - }, - [0x1D168]={ - category="mn", - direction="nsm", - }, - [0x1D169]={ - category="mn", - direction="nsm", - }, - [0x1D16A]={ - category="so", - direction="l", - }, - [0x1D16B]={ - category="so", - direction="l", - }, - [0x1D16C]={ - category="so", - direction="l", - }, - [0x1D16D]={ - category="mc", - direction="l", - }, - [0x1D16E]={ - category="mc", - direction="l", - }, - [0x1D16F]={ - category="mc", - direction="l", - }, - [0x1D170]={ - category="mc", - direction="l", - }, - [0x1D171]={ - category="mc", - direction="l", - }, - [0x1D172]={ - category="mc", - direction="l", - }, - [0x1D173]={ - category="cf", - direction="bn", - }, - [0x1D174]={ - category="cf", - direction="bn", - }, - [0x1D175]={ - category="cf", - direction="bn", - }, - [0x1D176]={ - category="cf", - direction="bn", - }, - [0x1D177]={ - category="cf", - direction="bn", - }, - [0x1D178]={ - category="cf", - direction="bn", - }, - [0x1D179]={ - category="cf", - direction="bn", - }, - [0x1D17A]={ - category="cf", - direction="bn", - }, - [0x1D17B]={ - category="mn", - direction="nsm", - }, - [0x1D17C]={ - category="mn", - direction="nsm", - }, - [0x1D17D]={ - category="mn", - direction="nsm", - }, - [0x1D17E]={ - category="mn", - direction="nsm", - }, - [0x1D17F]={ - category="mn", - direction="nsm", - }, - [0x1D180]={ - category="mn", - direction="nsm", - }, - [0x1D181]={ - category="mn", - direction="nsm", - }, - [0x1D182]={ - category="mn", - direction="nsm", - }, - [0x1D183]={ - category="so", - direction="l", - }, - [0x1D184]={ - category="so", - direction="l", - }, - [0x1D185]={ - category="mn", - direction="nsm", - }, - [0x1D186]={ - category="mn", - direction="nsm", - }, - [0x1D187]={ - category="mn", - direction="nsm", - }, - [0x1D188]={ - category="mn", - direction="nsm", - }, - [0x1D189]={ - category="mn", - direction="nsm", - }, - [0x1D18A]={ - category="mn", - direction="nsm", - }, - [0x1D18B]={ - category="mn", - direction="nsm", - }, - [0x1D18C]={ - category="so", - direction="l", - }, - [0x1D18D]={ - category="so", - direction="l", - }, - [0x1D18E]={ - category="so", - direction="l", - }, - [0x1D18F]={ - category="so", - direction="l", - }, - [0x1D190]={ - category="so", - direction="l", - }, - [0x1D191]={ - category="so", - direction="l", - }, - [0x1D192]={ - category="so", - direction="l", - }, - [0x1D193]={ - category="so", - direction="l", - }, - [0x1D194]={ - category="so", - direction="l", - }, - [0x1D195]={ - category="so", - direction="l", - }, - [0x1D196]={ - category="so", - direction="l", - }, - [0x1D197]={ - category="so", - direction="l", - }, - [0x1D198]={ - category="so", - direction="l", - }, - [0x1D199]={ - category="so", - direction="l", - }, - [0x1D19A]={ - category="so", - direction="l", - }, - [0x1D19B]={ - category="so", - direction="l", - }, - [0x1D19C]={ - category="so", - direction="l", - }, - [0x1D19D]={ - category="so", - direction="l", - }, - [0x1D19E]={ - category="so", - direction="l", - }, - [0x1D19F]={ - category="so", - direction="l", - }, - [0x1D1A0]={ - category="so", - direction="l", - }, - [0x1D1A1]={ - category="so", - direction="l", - }, - [0x1D1A2]={ - category="so", - direction="l", - }, - [0x1D1A3]={ - category="so", - direction="l", - }, - [0x1D1A4]={ - category="so", - direction="l", - }, - [0x1D1A5]={ - category="so", - direction="l", - }, - [0x1D1A6]={ - category="so", - direction="l", - }, - [0x1D1A7]={ - category="so", - direction="l", - }, - [0x1D1A8]={ - category="so", - direction="l", - }, - [0x1D1A9]={ - category="so", - direction="l", - }, - [0x1D1AA]={ - category="mn", - direction="nsm", - }, - [0x1D1AB]={ - category="mn", - direction="nsm", - }, - [0x1D1AC]={ - category="mn", - direction="nsm", - }, - [0x1D1AD]={ - category="mn", - direction="nsm", - }, - [0x1D1AE]={ - category="so", - direction="l", - }, - [0x1D1AF]={ - category="so", - direction="l", - }, - [0x1D1B0]={ - category="so", - direction="l", - }, - [0x1D1B1]={ - category="so", - direction="l", - }, - [0x1D1B2]={ - category="so", - direction="l", - }, - [0x1D1B3]={ - category="so", - direction="l", - }, - [0x1D1B4]={ - category="so", - direction="l", - }, - [0x1D1B5]={ - category="so", - direction="l", - }, - [0x1D1B6]={ - category="so", - direction="l", - }, - [0x1D1B7]={ - category="so", - direction="l", - }, - [0x1D1B8]={ - category="so", - direction="l", - }, - [0x1D1B9]={ - category="so", - direction="l", - }, - [0x1D1BA]={ - category="so", - direction="l", - }, - [0x1D1BB]={ - category="so", - direction="l", - }, - [0x1D1BC]={ - category="so", - direction="l", - }, - [0x1D1BD]={ - category="so", - direction="l", - }, - [0x1D1BE]={ - category="so", - direction="l", - }, - [0x1D1BF]={ - category="so", - direction="l", - }, - [0x1D1C0]={ - category="so", - direction="l", - }, - [0x1D1C1]={ - category="so", - direction="l", - }, - [0x1D1C2]={ - category="so", - direction="l", - }, - [0x1D1C3]={ - category="so", - direction="l", - }, - [0x1D1C4]={ - category="so", - direction="l", - }, - [0x1D1C5]={ - category="so", - direction="l", - }, - [0x1D1C6]={ - category="so", - direction="l", - }, - [0x1D1C7]={ - category="so", - direction="l", - }, - [0x1D1C8]={ - category="so", - direction="l", - }, - [0x1D1C9]={ - category="so", - direction="l", - }, - [0x1D1CA]={ - category="so", - direction="l", - }, - [0x1D1CB]={ - category="so", - direction="l", - }, - [0x1D1CC]={ - category="so", - direction="l", - }, - [0x1D1CD]={ - category="so", - direction="l", - }, - [0x1D1CE]={ - category="so", - direction="l", - }, - [0x1D1CF]={ - category="so", - direction="l", - }, - [0x1D1D0]={ - category="so", - direction="l", - }, - [0x1D1D1]={ - category="so", - direction="l", - }, - [0x1D1D2]={ - category="so", - direction="l", - }, - [0x1D1D3]={ - category="so", - direction="l", - }, - [0x1D1D4]={ - category="so", - direction="l", - }, - [0x1D1D5]={ - category="so", - direction="l", - }, - [0x1D1D6]={ - category="so", - direction="l", - }, - [0x1D1D7]={ - category="so", - direction="l", - }, - [0x1D1D8]={ - category="so", - direction="l", - }, - [0x1D1D9]={ - category="so", - direction="l", - }, - [0x1D1DA]={ - category="so", - direction="l", - }, - [0x1D1DB]={ - category="so", - direction="l", - }, - [0x1D1DC]={ - category="so", - direction="l", - }, - [0x1D1DD]={ - category="so", - direction="l", - }, - [0x1D1DE]={ - category="so", - direction="l", - }, - [0x1D1DF]={ - category="so", - direction="l", - }, - [0x1D1E0]={ - category="so", - direction="l", - }, - [0x1D1E1]={ - category="so", - direction="l", - }, - [0x1D1E2]={ - category="so", - direction="l", - }, - [0x1D1E3]={ - category="so", - direction="l", - }, - [0x1D1E4]={ - category="so", - direction="l", - }, - [0x1D1E5]={ - category="so", - direction="l", - }, - [0x1D1E6]={ - category="so", - direction="l", - }, - [0x1D1E7]={ - category="so", - direction="l", - }, - [0x1D1E8]={ - category="so", - direction="l", - }, - [0x1D200]={ - category="so", - direction="on", - }, - [0x1D201]={ - category="so", - direction="on", - }, - [0x1D202]={ - category="so", - direction="on", - }, - [0x1D203]={ - category="so", - direction="on", - }, - [0x1D204]={ - category="so", - direction="on", - }, - [0x1D205]={ - category="so", - direction="on", - }, - [0x1D206]={ - category="so", - direction="on", - }, - [0x1D207]={ - category="so", - direction="on", - }, - [0x1D208]={ - category="so", - direction="on", - }, - [0x1D209]={ - category="so", - direction="on", - }, - [0x1D20A]={ - category="so", - direction="on", - }, - [0x1D20B]={ - category="so", - direction="on", - }, - [0x1D20C]={ - category="so", - direction="on", - }, - [0x1D20D]={ - category="so", - direction="on", - }, - [0x1D20E]={ - category="so", - direction="on", - }, - [0x1D20F]={ - category="so", - direction="on", - }, - [0x1D210]={ - category="so", - direction="on", - }, - [0x1D211]={ - category="so", - direction="on", - }, - [0x1D212]={ - category="so", - direction="on", - }, - [0x1D213]={ - category="so", - direction="on", - }, - [0x1D214]={ - category="so", - direction="on", - }, - [0x1D215]={ - category="so", - direction="on", - }, - [0x1D216]={ - category="so", - direction="on", - }, - [0x1D217]={ - category="so", - direction="on", - }, - [0x1D218]={ - category="so", - direction="on", - }, - [0x1D219]={ - category="so", - direction="on", - }, - [0x1D21A]={ - category="so", - direction="on", - }, - [0x1D21B]={ - category="so", - direction="on", - }, - [0x1D21C]={ - category="so", - direction="on", - }, - [0x1D21D]={ - category="so", - direction="on", - }, - [0x1D21E]={ - category="so", - direction="on", - }, - [0x1D21F]={ - category="so", - direction="on", - }, - [0x1D220]={ - category="so", - direction="on", - }, - [0x1D221]={ - category="so", - direction="on", - }, - [0x1D222]={ - category="so", - direction="on", - }, - [0x1D223]={ - category="so", - direction="on", - }, - [0x1D224]={ - category="so", - direction="on", - }, - [0x1D225]={ - category="so", - direction="on", - }, - [0x1D226]={ - category="so", - direction="on", - }, - [0x1D227]={ - category="so", - direction="on", - }, - [0x1D228]={ - category="so", - direction="on", - }, - [0x1D229]={ - category="so", - direction="on", - }, - [0x1D22A]={ - category="so", - direction="on", - }, - [0x1D22B]={ - category="so", - direction="on", - }, - [0x1D22C]={ - category="so", - direction="on", - }, - [0x1D22D]={ - category="so", - direction="on", - }, - [0x1D22E]={ - category="so", - direction="on", - }, - [0x1D22F]={ - category="so", - direction="on", - }, - [0x1D230]={ - category="so", - direction="on", - }, - [0x1D231]={ - category="so", - direction="on", - }, - [0x1D232]={ - category="so", - direction="on", - }, - [0x1D233]={ - category="so", - direction="on", - }, - [0x1D234]={ - category="so", - direction="on", - }, - [0x1D235]={ - category="so", - direction="on", - }, - [0x1D236]={ - category="so", - direction="on", - }, - [0x1D237]={ - category="so", - direction="on", - }, - [0x1D238]={ - category="so", - direction="on", - }, - [0x1D239]={ - category="so", - direction="on", - }, - [0x1D23A]={ - category="so", - direction="on", - }, - [0x1D23B]={ - category="so", - direction="on", - }, - [0x1D23C]={ - category="so", - direction="on", - }, - [0x1D23D]={ - category="so", - direction="on", - }, - [0x1D23E]={ - category="so", - direction="on", - }, - [0x1D23F]={ - category="so", - direction="on", - }, - [0x1D240]={ - category="so", - direction="on", - }, - [0x1D241]={ - category="so", - direction="on", - }, - [0x1D242]={ - category="mn", - direction="nsm", - }, - [0x1D243]={ - category="mn", - direction="nsm", - }, - [0x1D244]={ - category="mn", - direction="nsm", - }, - [0x1D245]={ - category="so", - direction="on", - }, - [0x1D300]={ - category="so", - direction="on", - }, - [0x1D301]={ - category="so", - direction="on", - }, - [0x1D302]={ - category="so", - direction="on", - }, - [0x1D303]={ - category="so", - direction="on", - }, - [0x1D304]={ - category="so", - direction="on", - }, - [0x1D305]={ - category="so", - direction="on", - }, - [0x1D306]={ - category="so", - direction="on", - }, - [0x1D307]={ - category="so", - direction="on", - }, - [0x1D308]={ - category="so", - direction="on", - }, - [0x1D309]={ - category="so", - direction="on", - }, - [0x1D30A]={ - category="so", - direction="on", - }, - [0x1D30B]={ - category="so", - direction="on", - }, - [0x1D30C]={ - category="so", - direction="on", - }, - [0x1D30D]={ - category="so", - direction="on", - }, - [0x1D30E]={ - category="so", - direction="on", - }, - [0x1D30F]={ - category="so", - direction="on", - }, - [0x1D310]={ - category="so", - direction="on", - }, - [0x1D311]={ - category="so", - direction="on", - }, - [0x1D312]={ - category="so", - direction="on", - }, - [0x1D313]={ - category="so", - direction="on", - }, - [0x1D314]={ - category="so", - direction="on", - }, - [0x1D315]={ - category="so", - direction="on", - }, - [0x1D316]={ - category="so", - direction="on", - }, - [0x1D317]={ - category="so", - direction="on", - }, - [0x1D318]={ - category="so", - direction="on", - }, - [0x1D319]={ - category="so", - direction="on", - }, - [0x1D31A]={ - category="so", - direction="on", - }, - [0x1D31B]={ - category="so", - direction="on", - }, - [0x1D31C]={ - category="so", - direction="on", - }, - [0x1D31D]={ - category="so", - direction="on", - }, - [0x1D31E]={ - category="so", - direction="on", - }, - [0x1D31F]={ - category="so", - direction="on", - }, - [0x1D320]={ - category="so", - direction="on", - }, - [0x1D321]={ - category="so", - direction="on", - }, - [0x1D322]={ - category="so", - direction="on", - }, - [0x1D323]={ - category="so", - direction="on", - }, - [0x1D324]={ - category="so", - direction="on", - }, - [0x1D325]={ - category="so", - direction="on", - }, - [0x1D326]={ - category="so", - direction="on", - }, - [0x1D327]={ - category="so", - direction="on", - }, - [0x1D328]={ - category="so", - direction="on", - }, - [0x1D329]={ - category="so", - direction="on", - }, - [0x1D32A]={ - category="so", - direction="on", - }, - [0x1D32B]={ - category="so", - direction="on", - }, - [0x1D32C]={ - category="so", - direction="on", - }, - [0x1D32D]={ - category="so", - direction="on", - }, - [0x1D32E]={ - category="so", - direction="on", - }, - [0x1D32F]={ - category="so", - direction="on", - }, - [0x1D330]={ - category="so", - direction="on", - }, - [0x1D331]={ - category="so", - direction="on", - }, - [0x1D332]={ - category="so", - direction="on", - }, - [0x1D333]={ - category="so", - direction="on", - }, - [0x1D334]={ - category="so", - direction="on", - }, - [0x1D335]={ - category="so", - direction="on", - }, - [0x1D336]={ - category="so", - direction="on", - }, - [0x1D337]={ - category="so", - direction="on", - }, - [0x1D338]={ - category="so", - direction="on", - }, - [0x1D339]={ - category="so", - direction="on", - }, - [0x1D33A]={ - category="so", - direction="on", - }, - [0x1D33B]={ - category="so", - direction="on", - }, - [0x1D33C]={ - category="so", - direction="on", - }, - [0x1D33D]={ - category="so", - direction="on", - }, - [0x1D33E]={ - category="so", - direction="on", - }, - [0x1D33F]={ - category="so", - direction="on", - }, - [0x1D340]={ - category="so", - direction="on", - }, - [0x1D341]={ - category="so", - direction="on", - }, - [0x1D342]={ - category="so", - direction="on", - }, - [0x1D343]={ - category="so", - direction="on", - }, - [0x1D344]={ - category="so", - direction="on", - }, - [0x1D345]={ - category="so", - direction="on", - }, - [0x1D346]={ - category="so", - direction="on", - }, - [0x1D347]={ - category="so", - direction="on", - }, - [0x1D348]={ - category="so", - direction="on", - }, - [0x1D349]={ - category="so", - direction="on", - }, - [0x1D34A]={ - category="so", - direction="on", - }, - [0x1D34B]={ - category="so", - direction="on", - }, - [0x1D34C]={ - category="so", - direction="on", - }, - [0x1D34D]={ - category="so", - direction="on", - }, - [0x1D34E]={ - category="so", - direction="on", - }, - [0x1D34F]={ - category="so", - direction="on", - }, - [0x1D350]={ - category="so", - direction="on", - }, - [0x1D351]={ - category="so", - direction="on", - }, - [0x1D352]={ - category="so", - direction="on", - }, - [0x1D353]={ - category="so", - direction="on", - }, - [0x1D354]={ - category="so", - direction="on", - }, - [0x1D355]={ - category="so", - direction="on", - }, - [0x1D356]={ - category="so", - direction="on", - }, - [0x1D360]={ - category="no", - direction="l", - }, - [0x1D361]={ - category="no", - direction="l", - }, - [0x1D362]={ - category="no", - direction="l", - }, - [0x1D363]={ - category="no", - direction="l", - }, - [0x1D364]={ - category="no", - direction="l", - }, - [0x1D365]={ - category="no", - direction="l", - }, - [0x1D366]={ - category="no", - direction="l", - }, - [0x1D367]={ - category="no", - direction="l", - }, - [0x1D368]={ - category="no", - direction="l", - }, - [0x1D369]={ - category="no", - direction="l", - }, - [0x1D36A]={ - category="no", - direction="l", - }, - [0x1D36B]={ - category="no", - direction="l", - }, - [0x1D36C]={ - category="no", - direction="l", - }, - [0x1D36D]={ - category="no", - direction="l", - }, - [0x1D36E]={ - category="no", - direction="l", - }, - [0x1D36F]={ - category="no", - direction="l", - }, - [0x1D370]={ - category="no", - direction="l", - }, - [0x1D371]={ - category="no", - direction="l", - }, - [0x1D400]={ - category="lu", - direction="l", - }, - [0x1D401]={ - category="lu", - direction="l", - }, - [0x1D402]={ - category="lu", - direction="l", - }, - [0x1D403]={ - category="lu", - direction="l", - }, - [0x1D404]={ - category="lu", - direction="l", - }, - [0x1D405]={ - category="lu", - direction="l", - }, - [0x1D406]={ - category="lu", - direction="l", - }, - [0x1D407]={ - category="lu", - direction="l", - }, - [0x1D408]={ - category="lu", - direction="l", - }, - [0x1D409]={ - category="lu", - direction="l", - }, - [0x1D40A]={ - category="lu", - direction="l", - }, - [0x1D40B]={ - category="lu", - direction="l", - }, - [0x1D40C]={ - category="lu", - direction="l", - }, - [0x1D40D]={ - category="lu", - direction="l", - }, - [0x1D40E]={ - category="lu", - direction="l", - }, - [0x1D40F]={ - category="lu", - direction="l", - }, - [0x1D410]={ - category="lu", - direction="l", - }, - [0x1D411]={ - category="lu", - direction="l", - }, - [0x1D412]={ - category="lu", - direction="l", - }, - [0x1D413]={ - category="lu", - direction="l", - }, - [0x1D414]={ - category="lu", - direction="l", - }, - [0x1D415]={ - category="lu", - direction="l", - }, - [0x1D416]={ - category="lu", - direction="l", - }, - [0x1D417]={ - category="lu", - direction="l", - }, - [0x1D418]={ - category="lu", - direction="l", - }, - [0x1D419]={ - category="lu", - direction="l", - }, - [0x1D41A]={ - category="ll", - direction="l", - }, - [0x1D41B]={ - category="ll", - direction="l", - }, - [0x1D41C]={ - category="ll", - direction="l", - }, - [0x1D41D]={ - category="ll", - direction="l", - }, - [0x1D41E]={ - category="ll", - direction="l", - }, - [0x1D41F]={ - category="ll", - direction="l", - }, - [0x1D420]={ - category="ll", - direction="l", - }, - [0x1D421]={ - category="ll", - direction="l", - }, - [0x1D422]={ - category="ll", - direction="l", - }, - [0x1D423]={ - category="ll", - direction="l", - }, - [0x1D424]={ - category="ll", - direction="l", - }, - [0x1D425]={ - category="ll", - direction="l", - }, - [0x1D426]={ - category="ll", - direction="l", - }, - [0x1D427]={ - category="ll", - direction="l", - }, - [0x1D428]={ - category="ll", - direction="l", - }, - [0x1D429]={ - category="ll", - direction="l", - }, - [0x1D42A]={ - category="ll", - direction="l", - }, - [0x1D42B]={ - category="ll", - direction="l", - }, - [0x1D42C]={ - category="ll", - direction="l", - }, - [0x1D42D]={ - category="ll", - direction="l", - }, - [0x1D42E]={ - category="ll", - direction="l", - }, - [0x1D42F]={ - category="ll", - direction="l", - }, - [0x1D430]={ - category="ll", - direction="l", - }, - [0x1D431]={ - category="ll", - direction="l", - }, - [0x1D432]={ - category="ll", - direction="l", - }, - [0x1D433]={ - category="ll", - direction="l", - }, - [0x1D434]={ - category="lu", - direction="l", - }, - [0x1D435]={ - category="lu", - direction="l", - }, - [0x1D436]={ - category="lu", - direction="l", - }, - [0x1D437]={ - category="lu", - direction="l", - }, - [0x1D438]={ - category="lu", - direction="l", - }, - [0x1D439]={ - category="lu", - direction="l", - }, - [0x1D43A]={ - category="lu", - direction="l", - }, - [0x1D43B]={ - category="lu", - direction="l", - }, - [0x1D43C]={ - category="lu", - direction="l", - }, - [0x1D43D]={ - category="lu", - direction="l", - }, - [0x1D43E]={ - category="lu", - direction="l", - }, - [0x1D43F]={ - category="lu", - direction="l", - }, - [0x1D440]={ - category="lu", - direction="l", - }, - [0x1D441]={ - category="lu", - direction="l", - }, - [0x1D442]={ - category="lu", - direction="l", - }, - [0x1D443]={ - category="lu", - direction="l", - }, - [0x1D444]={ - category="lu", - direction="l", - }, - [0x1D445]={ - category="lu", - direction="l", - }, - [0x1D446]={ - category="lu", - direction="l", - }, - [0x1D447]={ - category="lu", - direction="l", - }, - [0x1D448]={ - category="lu", - direction="l", - }, - [0x1D449]={ - category="lu", - direction="l", - }, - [0x1D44A]={ - category="lu", - direction="l", - }, - [0x1D44B]={ - category="lu", - direction="l", - }, - [0x1D44C]={ - category="lu", - direction="l", - }, - [0x1D44D]={ - category="lu", - direction="l", - }, - [0x1D44E]={ - category="ll", - direction="l", - }, - [0x1D44F]={ - category="ll", - direction="l", - }, - [0x1D450]={ - category="ll", - direction="l", - }, - [0x1D451]={ - category="ll", - direction="l", - }, - [0x1D452]={ - category="ll", - direction="l", - }, - [0x1D453]={ - category="ll", - direction="l", - }, - [0x1D454]={ - category="ll", - direction="l", - }, - [0x1D456]={ - category="ll", - direction="l", - }, - [0x1D457]={ - category="ll", - direction="l", - }, - [0x1D458]={ - category="ll", - direction="l", - }, - [0x1D459]={ - category="ll", - direction="l", - }, - [0x1D45A]={ - category="ll", - direction="l", - }, - [0x1D45B]={ - category="ll", - direction="l", - }, - [0x1D45C]={ - category="ll", - direction="l", - }, - [0x1D45D]={ - category="ll", - direction="l", - }, - [0x1D45E]={ - category="ll", - direction="l", - }, - [0x1D45F]={ - category="ll", - direction="l", - }, - [0x1D460]={ - category="ll", - direction="l", - }, - [0x1D461]={ - category="ll", - direction="l", - }, - [0x1D462]={ - category="ll", - direction="l", - }, - [0x1D463]={ - category="ll", - direction="l", - }, - [0x1D464]={ - category="ll", - direction="l", - }, - [0x1D465]={ - category="ll", - direction="l", - }, - [0x1D466]={ - category="ll", - direction="l", - }, - [0x1D467]={ - category="ll", - direction="l", - }, - [0x1D468]={ - category="lu", - direction="l", - }, - [0x1D469]={ - category="lu", - direction="l", - }, - [0x1D46A]={ - category="lu", - direction="l", - }, - [0x1D46B]={ - category="lu", - direction="l", - }, - [0x1D46C]={ - category="lu", - direction="l", - }, - [0x1D46D]={ - category="lu", - direction="l", - }, - [0x1D46E]={ - category="lu", - direction="l", - }, - [0x1D46F]={ - category="lu", - direction="l", - }, - [0x1D470]={ - category="lu", - direction="l", - }, - [0x1D471]={ - category="lu", - direction="l", - }, - [0x1D472]={ - category="lu", - direction="l", - }, - [0x1D473]={ - category="lu", - direction="l", - }, - [0x1D474]={ - category="lu", - direction="l", - }, - [0x1D475]={ - category="lu", - direction="l", - }, - [0x1D476]={ - category="lu", - direction="l", - }, - [0x1D477]={ - category="lu", - direction="l", - }, - [0x1D478]={ - category="lu", - direction="l", - }, - [0x1D479]={ - category="lu", - direction="l", - }, - [0x1D47A]={ - category="lu", - direction="l", - }, - [0x1D47B]={ - category="lu", - direction="l", - }, - [0x1D47C]={ - category="lu", - direction="l", - }, - [0x1D47D]={ - category="lu", - direction="l", - }, - [0x1D47E]={ - category="lu", - direction="l", - }, - [0x1D47F]={ - category="lu", - direction="l", - }, - [0x1D480]={ - category="lu", - direction="l", - }, - [0x1D481]={ - category="lu", - direction="l", - }, - [0x1D482]={ - category="ll", - direction="l", - }, - [0x1D483]={ - category="ll", - direction="l", - }, - [0x1D484]={ - category="ll", - direction="l", - }, - [0x1D485]={ - category="ll", - direction="l", - }, - [0x1D486]={ - category="ll", - direction="l", - }, - [0x1D487]={ - category="ll", - direction="l", - }, - [0x1D488]={ - category="ll", - direction="l", - }, - [0x1D489]={ - category="ll", - direction="l", - }, - [0x1D48A]={ - category="ll", - direction="l", - }, - [0x1D48B]={ - category="ll", - direction="l", - }, - [0x1D48C]={ - category="ll", - direction="l", - }, - [0x1D48D]={ - category="ll", - direction="l", - }, - [0x1D48E]={ - category="ll", - direction="l", - }, - [0x1D48F]={ - category="ll", - direction="l", - }, - [0x1D490]={ - category="ll", - direction="l", - }, - [0x1D491]={ - category="ll", - direction="l", - }, - [0x1D492]={ - category="ll", - direction="l", - }, - [0x1D493]={ - category="ll", - direction="l", - }, - [0x1D494]={ - category="ll", - direction="l", - }, - [0x1D495]={ - category="ll", - direction="l", - }, - [0x1D496]={ - category="ll", - direction="l", - }, - [0x1D497]={ - category="ll", - direction="l", - }, - [0x1D498]={ - category="ll", - direction="l", - }, - [0x1D499]={ - category="ll", - direction="l", - }, - [0x1D49A]={ - category="ll", - direction="l", - }, - [0x1D49B]={ - category="ll", - direction="l", - }, - [0x1D49C]={ - category="lu", - direction="l", - }, - [0x1D49E]={ - category="lu", - direction="l", - }, - [0x1D49F]={ - category="lu", - direction="l", - }, - [0x1D4A2]={ - category="lu", - direction="l", - }, - [0x1D4A5]={ - category="lu", - direction="l", - }, - [0x1D4A6]={ - category="lu", - direction="l", - }, - [0x1D4A9]={ - category="lu", - direction="l", - }, - [0x1D4AA]={ - category="lu", - direction="l", - }, - [0x1D4AB]={ - category="lu", - direction="l", - }, - [0x1D4AC]={ - category="lu", - direction="l", - }, - [0x1D4AE]={ - category="lu", - direction="l", - }, - [0x1D4AF]={ - category="lu", - direction="l", - }, - [0x1D4B0]={ - category="lu", - direction="l", - }, - [0x1D4B1]={ - category="lu", - direction="l", - }, - [0x1D4B2]={ - category="lu", - direction="l", - }, - [0x1D4B3]={ - category="lu", - direction="l", - }, - [0x1D4B4]={ - category="lu", - direction="l", - }, - [0x1D4B5]={ - category="lu", - direction="l", - }, - [0x1D4B6]={ - category="ll", - direction="l", - }, - [0x1D4B7]={ - category="ll", - direction="l", - }, - [0x1D4B8]={ - category="ll", - direction="l", - }, - [0x1D4B9]={ - category="ll", - direction="l", - }, - [0x1D4BB]={ - category="ll", - direction="l", - }, - [0x1D4BD]={ - category="ll", - direction="l", - }, - [0x1D4BE]={ - category="ll", - direction="l", - }, - [0x1D4BF]={ - category="ll", - direction="l", - }, - [0x1D4C0]={ - category="ll", - direction="l", - }, - [0x1D4C1]={ - category="ll", - direction="l", - }, - [0x1D4C2]={ - category="ll", - direction="l", - }, - [0x1D4C3]={ - category="ll", - direction="l", - }, - [0x1D4C5]={ - category="ll", - direction="l", - }, - [0x1D4C6]={ - category="ll", - direction="l", - }, - [0x1D4C7]={ - category="ll", - direction="l", - }, - [0x1D4C8]={ - category="ll", - direction="l", - }, - [0x1D4C9]={ - category="ll", - direction="l", - }, - [0x1D4CA]={ - category="ll", - direction="l", - }, - [0x1D4CB]={ - category="ll", - direction="l", - }, - [0x1D4CC]={ - category="ll", - direction="l", - }, - [0x1D4CD]={ - category="ll", - direction="l", - }, - [0x1D4CE]={ - category="ll", - direction="l", - }, - [0x1D4CF]={ - category="ll", - direction="l", - }, - [0x1D4D0]={ - category="lu", - direction="l", - }, - [0x1D4D1]={ - category="lu", - direction="l", - }, - [0x1D4D2]={ - category="lu", - direction="l", - }, - [0x1D4D3]={ - category="lu", - direction="l", - }, - [0x1D4D4]={ - category="lu", - direction="l", - }, - [0x1D4D5]={ - category="lu", - direction="l", - }, - [0x1D4D6]={ - category="lu", - direction="l", - }, - [0x1D4D7]={ - category="lu", - direction="l", - }, - [0x1D4D8]={ - category="lu", - direction="l", - }, - [0x1D4D9]={ - category="lu", - direction="l", - }, - [0x1D4DA]={ - category="lu", - direction="l", - }, - [0x1D4DB]={ - category="lu", - direction="l", - }, - [0x1D4DC]={ - category="lu", - direction="l", - }, - [0x1D4DD]={ - category="lu", - direction="l", - }, - [0x1D4DE]={ - category="lu", - direction="l", - }, - [0x1D4DF]={ - category="lu", - direction="l", - }, - [0x1D4E0]={ - category="lu", - direction="l", - }, - [0x1D4E1]={ - category="lu", - direction="l", - }, - [0x1D4E2]={ - category="lu", - direction="l", - }, - [0x1D4E3]={ - category="lu", - direction="l", - }, - [0x1D4E4]={ - category="lu", - direction="l", - }, - [0x1D4E5]={ - category="lu", - direction="l", - }, - [0x1D4E6]={ - category="lu", - direction="l", - }, - [0x1D4E7]={ - category="lu", - direction="l", - }, - [0x1D4E8]={ - category="lu", - direction="l", - }, - [0x1D4E9]={ - category="lu", - direction="l", - }, - [0x1D4EA]={ - category="ll", - direction="l", - }, - [0x1D4EB]={ - category="ll", - direction="l", - }, - [0x1D4EC]={ - category="ll", - direction="l", - }, - [0x1D4ED]={ - category="ll", - direction="l", - }, - [0x1D4EE]={ - category="ll", - direction="l", - }, - [0x1D4EF]={ - category="ll", - direction="l", - }, - [0x1D4F0]={ - category="ll", - direction="l", - }, - [0x1D4F1]={ - category="ll", - direction="l", - }, - [0x1D4F2]={ - category="ll", - direction="l", - }, - [0x1D4F3]={ - category="ll", - direction="l", - }, - [0x1D4F4]={ - category="ll", - direction="l", - }, - [0x1D4F5]={ - category="ll", - direction="l", - }, - [0x1D4F6]={ - category="ll", - direction="l", - }, - [0x1D4F7]={ - category="ll", - direction="l", - }, - [0x1D4F8]={ - category="ll", - direction="l", - }, - [0x1D4F9]={ - category="ll", - direction="l", - }, - [0x1D4FA]={ - category="ll", - direction="l", - }, - [0x1D4FB]={ - category="ll", - direction="l", - }, - [0x1D4FC]={ - category="ll", - direction="l", - }, - [0x1D4FD]={ - category="ll", - direction="l", - }, - [0x1D4FE]={ - category="ll", - direction="l", - }, - [0x1D4FF]={ - category="ll", - direction="l", - }, - [0x1D500]={ - category="ll", - direction="l", - }, - [0x1D501]={ - category="ll", - direction="l", - }, - [0x1D502]={ - category="ll", - direction="l", - }, - [0x1D503]={ - category="ll", - direction="l", - }, - [0x1D504]={ - category="lu", - direction="l", - }, - [0x1D505]={ - category="lu", - direction="l", - }, - [0x1D507]={ - category="lu", - direction="l", - }, - [0x1D508]={ - category="lu", - direction="l", - }, - [0x1D509]={ - category="lu", - direction="l", - }, - [0x1D50A]={ - category="lu", - direction="l", - }, - [0x1D50D]={ - category="lu", - direction="l", - }, - [0x1D50E]={ - category="lu", - direction="l", - }, - [0x1D50F]={ - category="lu", - direction="l", - }, - [0x1D510]={ - category="lu", - direction="l", - }, - [0x1D511]={ - category="lu", - direction="l", - }, - [0x1D512]={ - category="lu", - direction="l", - }, - [0x1D513]={ - category="lu", - direction="l", - }, - [0x1D514]={ - category="lu", - direction="l", - }, - [0x1D516]={ - category="lu", - direction="l", - }, - [0x1D517]={ - category="lu", - direction="l", - }, - [0x1D518]={ - category="lu", - direction="l", - }, - [0x1D519]={ - category="lu", - direction="l", - }, - [0x1D51A]={ - category="lu", - direction="l", - }, - [0x1D51B]={ - category="lu", - direction="l", - }, - [0x1D51C]={ - category="lu", - direction="l", - }, - [0x1D51E]={ - category="ll", - direction="l", - }, - [0x1D51F]={ - category="ll", - direction="l", - }, - [0x1D520]={ - category="ll", - direction="l", - }, - [0x1D521]={ - category="ll", - direction="l", - }, - [0x1D522]={ - category="ll", - direction="l", - }, - [0x1D523]={ - category="ll", - direction="l", - }, - [0x1D524]={ - category="ll", - direction="l", - }, - [0x1D525]={ - category="ll", - direction="l", - }, - [0x1D526]={ - category="ll", - direction="l", - }, - [0x1D527]={ - category="ll", - direction="l", - }, - [0x1D528]={ - category="ll", - direction="l", - }, - [0x1D529]={ - category="ll", - direction="l", - }, - [0x1D52A]={ - category="ll", - direction="l", - }, - [0x1D52B]={ - category="ll", - direction="l", - }, - [0x1D52C]={ - category="ll", - direction="l", - }, - [0x1D52D]={ - category="ll", - direction="l", - }, - [0x1D52E]={ - category="ll", - direction="l", - }, - [0x1D52F]={ - category="ll", - direction="l", - }, - [0x1D530]={ - category="ll", - direction="l", - }, - [0x1D531]={ - category="ll", - direction="l", - }, - [0x1D532]={ - category="ll", - direction="l", - }, - [0x1D533]={ - category="ll", - direction="l", - }, - [0x1D534]={ - category="ll", - direction="l", - }, - [0x1D535]={ - category="ll", - direction="l", - }, - [0x1D536]={ - category="ll", - direction="l", - }, - [0x1D537]={ - category="ll", - direction="l", - }, - [0x1D538]={ - category="lu", - direction="l", - }, - [0x1D539]={ - category="lu", - direction="l", - }, - [0x1D53B]={ - category="lu", - direction="l", - }, - [0x1D53C]={ - category="lu", - direction="l", - }, - [0x1D53D]={ - category="lu", - direction="l", - }, - [0x1D53E]={ - category="lu", - direction="l", - }, - [0x1D540]={ - category="lu", - direction="l", - }, - [0x1D541]={ - category="lu", - direction="l", - }, - [0x1D542]={ - category="lu", - direction="l", - }, - [0x1D543]={ - category="lu", - direction="l", - }, - [0x1D544]={ - category="lu", - direction="l", - }, - [0x1D546]={ - category="lu", - direction="l", - }, - [0x1D54A]={ - category="lu", - direction="l", - }, - [0x1D54B]={ - category="lu", - direction="l", - }, - [0x1D54C]={ - category="lu", - direction="l", - }, - [0x1D54D]={ - category="lu", - direction="l", - }, - [0x1D54E]={ - category="lu", - direction="l", - }, - [0x1D54F]={ - category="lu", - direction="l", - }, - [0x1D550]={ - category="lu", - direction="l", - }, - [0x1D552]={ - category="ll", - direction="l", - }, - [0x1D553]={ - category="ll", - direction="l", - }, - [0x1D554]={ - category="ll", - direction="l", - }, - [0x1D555]={ - category="ll", - direction="l", - }, - [0x1D556]={ - category="ll", - direction="l", - }, - [0x1D557]={ - category="ll", - direction="l", - }, - [0x1D558]={ - category="ll", - direction="l", - }, - [0x1D559]={ - category="ll", - direction="l", - }, - [0x1D55A]={ - category="ll", - direction="l", - }, - [0x1D55B]={ - category="ll", - direction="l", - }, - [0x1D55C]={ - category="ll", - direction="l", - }, - [0x1D55D]={ - category="ll", - direction="l", - }, - [0x1D55E]={ - category="ll", - direction="l", - }, - [0x1D55F]={ - category="ll", - direction="l", - }, - [0x1D560]={ - category="ll", - direction="l", - }, - [0x1D561]={ - category="ll", - direction="l", - }, - [0x1D562]={ - category="ll", - direction="l", - }, - [0x1D563]={ - category="ll", - direction="l", - }, - [0x1D564]={ - category="ll", - direction="l", - }, - [0x1D565]={ - category="ll", - direction="l", - }, - [0x1D566]={ - category="ll", - direction="l", - }, - [0x1D567]={ - category="ll", - direction="l", - }, - [0x1D568]={ - category="ll", - direction="l", - }, - [0x1D569]={ - category="ll", - direction="l", - }, - [0x1D56A]={ - category="ll", - direction="l", - }, - [0x1D56B]={ - category="ll", - direction="l", - }, - [0x1D56C]={ - category="lu", - direction="l", - }, - [0x1D56D]={ - category="lu", - direction="l", - }, - [0x1D56E]={ - category="lu", - direction="l", - }, - [0x1D56F]={ - category="lu", - direction="l", - }, - [0x1D570]={ - category="lu", - direction="l", - }, - [0x1D571]={ - category="lu", - direction="l", - }, - [0x1D572]={ - category="lu", - direction="l", - }, - [0x1D573]={ - category="lu", - direction="l", - }, - [0x1D574]={ - category="lu", - direction="l", - }, - [0x1D575]={ - category="lu", - direction="l", - }, - [0x1D576]={ - category="lu", - direction="l", - }, - [0x1D577]={ - category="lu", - direction="l", - }, - [0x1D578]={ - category="lu", - direction="l", - }, - [0x1D579]={ - category="lu", - direction="l", - }, - [0x1D57A]={ - category="lu", - direction="l", - }, - [0x1D57B]={ - category="lu", - direction="l", - }, - [0x1D57C]={ - category="lu", - direction="l", - }, - [0x1D57D]={ - category="lu", - direction="l", - }, - [0x1D57E]={ - category="lu", - direction="l", - }, - [0x1D57F]={ - category="lu", - direction="l", - }, - [0x1D580]={ - category="lu", - direction="l", - }, - [0x1D581]={ - category="lu", - direction="l", - }, - [0x1D582]={ - category="lu", - direction="l", - }, - [0x1D583]={ - category="lu", - direction="l", - }, - [0x1D584]={ - category="lu", - direction="l", - }, - [0x1D585]={ - category="lu", - direction="l", - }, - [0x1D586]={ - category="ll", - direction="l", - }, - [0x1D587]={ - category="ll", - direction="l", - }, - [0x1D588]={ - category="ll", - direction="l", - }, - [0x1D589]={ - category="ll", - direction="l", - }, - [0x1D58A]={ - category="ll", - direction="l", - }, - [0x1D58B]={ - category="ll", - direction="l", - }, - [0x1D58C]={ - category="ll", - direction="l", - }, - [0x1D58D]={ - category="ll", - direction="l", - }, - [0x1D58E]={ - category="ll", - direction="l", - }, - [0x1D58F]={ - category="ll", - direction="l", - }, - [0x1D590]={ - category="ll", - direction="l", - }, - [0x1D591]={ - category="ll", - direction="l", - }, - [0x1D592]={ - category="ll", - direction="l", - }, - [0x1D593]={ - category="ll", - direction="l", - }, - [0x1D594]={ - category="ll", - direction="l", - }, - [0x1D595]={ - category="ll", - direction="l", - }, - [0x1D596]={ - category="ll", - direction="l", - }, - [0x1D597]={ - category="ll", - direction="l", - }, - [0x1D598]={ - category="ll", - direction="l", - }, - [0x1D599]={ - category="ll", - direction="l", - }, - [0x1D59A]={ - category="ll", - direction="l", - }, - [0x1D59B]={ - category="ll", - direction="l", - }, - [0x1D59C]={ - category="ll", - direction="l", - }, - [0x1D59D]={ - category="ll", - direction="l", - }, - [0x1D59E]={ - category="ll", - direction="l", - }, - [0x1D59F]={ - category="ll", - direction="l", - }, - [0x1D5A0]={ - category="lu", - direction="l", - }, - [0x1D5A1]={ - category="lu", - direction="l", - }, - [0x1D5A2]={ - category="lu", - direction="l", - }, - [0x1D5A3]={ - category="lu", - direction="l", - }, - [0x1D5A4]={ - category="lu", - direction="l", - }, - [0x1D5A5]={ - category="lu", - direction="l", - }, - [0x1D5A6]={ - category="lu", - direction="l", - }, - [0x1D5A7]={ - category="lu", - direction="l", - }, - [0x1D5A8]={ - category="lu", - direction="l", - }, - [0x1D5A9]={ - category="lu", - direction="l", - }, - [0x1D5AA]={ - category="lu", - direction="l", - }, - [0x1D5AB]={ - category="lu", - direction="l", - }, - [0x1D5AC]={ - category="lu", - direction="l", - }, - [0x1D5AD]={ - category="lu", - direction="l", - }, - [0x1D5AE]={ - category="lu", - direction="l", - }, - [0x1D5AF]={ - category="lu", - direction="l", - }, - [0x1D5B0]={ - category="lu", - direction="l", - }, - [0x1D5B1]={ - category="lu", - direction="l", - }, - [0x1D5B2]={ - category="lu", - direction="l", - }, - [0x1D5B3]={ - category="lu", - direction="l", - }, - [0x1D5B4]={ - category="lu", - direction="l", - }, - [0x1D5B5]={ - category="lu", - direction="l", - }, - [0x1D5B6]={ - category="lu", - direction="l", - }, - [0x1D5B7]={ - category="lu", - direction="l", - }, - [0x1D5B8]={ - category="lu", - direction="l", - }, - [0x1D5B9]={ - category="lu", - direction="l", - }, - [0x1D5BA]={ - category="ll", - direction="l", - }, - [0x1D5BB]={ - category="ll", - direction="l", - }, - [0x1D5BC]={ - category="ll", - direction="l", - }, - [0x1D5BD]={ - category="ll", - direction="l", - }, - [0x1D5BE]={ - category="ll", - direction="l", - }, - [0x1D5BF]={ - category="ll", - direction="l", - }, - [0x1D5C0]={ - category="ll", - direction="l", - }, - [0x1D5C1]={ - category="ll", - direction="l", - }, - [0x1D5C2]={ - category="ll", - direction="l", - }, - [0x1D5C3]={ - category="ll", - direction="l", - }, - [0x1D5C4]={ - category="ll", - direction="l", - }, - [0x1D5C5]={ - category="ll", - direction="l", - }, - [0x1D5C6]={ - category="ll", - direction="l", - }, - [0x1D5C7]={ - category="ll", - direction="l", - }, - [0x1D5C8]={ - category="ll", - direction="l", - }, - [0x1D5C9]={ - category="ll", - direction="l", - }, - [0x1D5CA]={ - category="ll", - direction="l", - }, - [0x1D5CB]={ - category="ll", - direction="l", - }, - [0x1D5CC]={ - category="ll", - direction="l", - }, - [0x1D5CD]={ - category="ll", - direction="l", - }, - [0x1D5CE]={ - category="ll", - direction="l", - }, - [0x1D5CF]={ - category="ll", - direction="l", - }, - [0x1D5D0]={ - category="ll", - direction="l", - }, - [0x1D5D1]={ - category="ll", - direction="l", - }, - [0x1D5D2]={ - category="ll", - direction="l", - }, - [0x1D5D3]={ - category="ll", - direction="l", - }, - [0x1D5D4]={ - category="lu", - direction="l", - }, - [0x1D5D5]={ - category="lu", - direction="l", - }, - [0x1D5D6]={ - category="lu", - direction="l", - }, - [0x1D5D7]={ - category="lu", - direction="l", - }, - [0x1D5D8]={ - category="lu", - direction="l", - }, - [0x1D5D9]={ - category="lu", - direction="l", - }, - [0x1D5DA]={ - category="lu", - direction="l", - }, - [0x1D5DB]={ - category="lu", - direction="l", - }, - [0x1D5DC]={ - category="lu", - direction="l", - }, - [0x1D5DD]={ - category="lu", - direction="l", - }, - [0x1D5DE]={ - category="lu", - direction="l", - }, - [0x1D5DF]={ - category="lu", - direction="l", - }, - [0x1D5E0]={ - category="lu", - direction="l", - }, - [0x1D5E1]={ - category="lu", - direction="l", - }, - [0x1D5E2]={ - category="lu", - direction="l", - }, - [0x1D5E3]={ - category="lu", - direction="l", - }, - [0x1D5E4]={ - category="lu", - direction="l", - }, - [0x1D5E5]={ - category="lu", - direction="l", - }, - [0x1D5E6]={ - category="lu", - direction="l", - }, - [0x1D5E7]={ - category="lu", - direction="l", - }, - [0x1D5E8]={ - category="lu", - direction="l", - }, - [0x1D5E9]={ - category="lu", - direction="l", - }, - [0x1D5EA]={ - category="lu", - direction="l", - }, - [0x1D5EB]={ - category="lu", - direction="l", - }, - [0x1D5EC]={ - category="lu", - direction="l", - }, - [0x1D5ED]={ - category="lu", - direction="l", - }, - [0x1D5EE]={ - category="ll", - direction="l", - }, - [0x1D5EF]={ - category="ll", - direction="l", - }, - [0x1D5F0]={ - category="ll", - direction="l", - }, - [0x1D5F1]={ - category="ll", - direction="l", - }, - [0x1D5F2]={ - category="ll", - direction="l", - }, - [0x1D5F3]={ - category="ll", - direction="l", - }, - [0x1D5F4]={ - category="ll", - direction="l", - }, - [0x1D5F5]={ - category="ll", - direction="l", - }, - [0x1D5F6]={ - category="ll", - direction="l", - }, - [0x1D5F7]={ - category="ll", - direction="l", - }, - [0x1D5F8]={ - category="ll", - direction="l", - }, - [0x1D5F9]={ - category="ll", - direction="l", - }, - [0x1D5FA]={ - category="ll", - direction="l", - }, - [0x1D5FB]={ - category="ll", - direction="l", - }, - [0x1D5FC]={ - category="ll", - direction="l", - }, - [0x1D5FD]={ - category="ll", - direction="l", - }, - [0x1D5FE]={ - category="ll", - direction="l", - }, - [0x1D5FF]={ - category="ll", - direction="l", - }, - [0x1D600]={ - category="ll", - direction="l", - }, - [0x1D601]={ - category="ll", - direction="l", - }, - [0x1D602]={ - category="ll", - direction="l", - }, - [0x1D603]={ - category="ll", - direction="l", - }, - [0x1D604]={ - category="ll", - direction="l", - }, - [0x1D605]={ - category="ll", - direction="l", - }, - [0x1D606]={ - category="ll", - direction="l", - }, - [0x1D607]={ - category="ll", - direction="l", - }, - [0x1D608]={ - category="lu", - direction="l", - }, - [0x1D609]={ - category="lu", - direction="l", - }, - [0x1D60A]={ - category="lu", - direction="l", - }, - [0x1D60B]={ - category="lu", - direction="l", - }, - [0x1D60C]={ - category="lu", - direction="l", - }, - [0x1D60D]={ - category="lu", - direction="l", - }, - [0x1D60E]={ - category="lu", - direction="l", - }, - [0x1D60F]={ - category="lu", - direction="l", - }, - [0x1D610]={ - category="lu", - direction="l", - }, - [0x1D611]={ - category="lu", - direction="l", - }, - [0x1D612]={ - category="lu", - direction="l", - }, - [0x1D613]={ - category="lu", - direction="l", - }, - [0x1D614]={ - category="lu", - direction="l", - }, - [0x1D615]={ - category="lu", - direction="l", - }, - [0x1D616]={ - category="lu", - direction="l", - }, - [0x1D617]={ - category="lu", - direction="l", - }, - [0x1D618]={ - category="lu", - direction="l", - }, - [0x1D619]={ - category="lu", - direction="l", - }, - [0x1D61A]={ - category="lu", - direction="l", - }, - [0x1D61B]={ - category="lu", - direction="l", - }, - [0x1D61C]={ - category="lu", - direction="l", - }, - [0x1D61D]={ - category="lu", - direction="l", - }, - [0x1D61E]={ - category="lu", - direction="l", - }, - [0x1D61F]={ - category="lu", - direction="l", - }, - [0x1D620]={ - category="lu", - direction="l", - }, - [0x1D621]={ - category="lu", - direction="l", - }, - [0x1D622]={ - category="ll", - direction="l", - }, - [0x1D623]={ - category="ll", - direction="l", - }, - [0x1D624]={ - category="ll", - direction="l", - }, - [0x1D625]={ - category="ll", - direction="l", - }, - [0x1D626]={ - category="ll", - direction="l", - }, - [0x1D627]={ - category="ll", - direction="l", - }, - [0x1D628]={ - category="ll", - direction="l", - }, - [0x1D629]={ - category="ll", - direction="l", - }, - [0x1D62A]={ - category="ll", - direction="l", - }, - [0x1D62B]={ - category="ll", - direction="l", - }, - [0x1D62C]={ - category="ll", - direction="l", - }, - [0x1D62D]={ - category="ll", - direction="l", - }, - [0x1D62E]={ - category="ll", - direction="l", - }, - [0x1D62F]={ - category="ll", - direction="l", - }, - [0x1D630]={ - category="ll", - direction="l", - }, - [0x1D631]={ - category="ll", - direction="l", - }, - [0x1D632]={ - category="ll", - direction="l", - }, - [0x1D633]={ - category="ll", - direction="l", - }, - [0x1D634]={ - category="ll", - direction="l", - }, - [0x1D635]={ - category="ll", - direction="l", - }, - [0x1D636]={ - category="ll", - direction="l", - }, - [0x1D637]={ - category="ll", - direction="l", - }, - [0x1D638]={ - category="ll", - direction="l", - }, - [0x1D639]={ - category="ll", - direction="l", - }, - [0x1D63A]={ - category="ll", - direction="l", - }, - [0x1D63B]={ - category="ll", - direction="l", - }, - [0x1D63C]={ - category="lu", - direction="l", - }, - [0x1D63D]={ - category="lu", - direction="l", - }, - [0x1D63E]={ - category="lu", - direction="l", - }, - [0x1D63F]={ - category="lu", - direction="l", - }, - [0x1D640]={ - category="lu", - direction="l", - }, - [0x1D641]={ - category="lu", - direction="l", - }, - [0x1D642]={ - category="lu", - direction="l", - }, - [0x1D643]={ - category="lu", - direction="l", - }, - [0x1D644]={ - category="lu", - direction="l", - }, - [0x1D645]={ - category="lu", - direction="l", - }, - [0x1D646]={ - category="lu", - direction="l", - }, - [0x1D647]={ - category="lu", - direction="l", - }, - [0x1D648]={ - category="lu", - direction="l", - }, - [0x1D649]={ - category="lu", - direction="l", - }, - [0x1D64A]={ - category="lu", - direction="l", - }, - [0x1D64B]={ - category="lu", - direction="l", - }, - [0x1D64C]={ - category="lu", - direction="l", - }, - [0x1D64D]={ - category="lu", - direction="l", - }, - [0x1D64E]={ - category="lu", - direction="l", - }, - [0x1D64F]={ - category="lu", - direction="l", - }, - [0x1D650]={ - category="lu", - direction="l", - }, - [0x1D651]={ - category="lu", - direction="l", - }, - [0x1D652]={ - category="lu", - direction="l", - }, - [0x1D653]={ - category="lu", - direction="l", - }, - [0x1D654]={ - category="lu", - direction="l", - }, - [0x1D655]={ - category="lu", - direction="l", - }, - [0x1D656]={ - category="ll", - direction="l", - }, - [0x1D657]={ - category="ll", - direction="l", - }, - [0x1D658]={ - category="ll", - direction="l", - }, - [0x1D659]={ - category="ll", - direction="l", - }, - [0x1D65A]={ - category="ll", - direction="l", - }, - [0x1D65B]={ - category="ll", - direction="l", - }, - [0x1D65C]={ - category="ll", - direction="l", - }, - [0x1D65D]={ - category="ll", - direction="l", - }, - [0x1D65E]={ - category="ll", - direction="l", - }, - [0x1D65F]={ - category="ll", - direction="l", - }, - [0x1D660]={ - category="ll", - direction="l", - }, - [0x1D661]={ - category="ll", - direction="l", - }, - [0x1D662]={ - category="ll", - direction="l", - }, - [0x1D663]={ - category="ll", - direction="l", - }, - [0x1D664]={ - category="ll", - direction="l", - }, - [0x1D665]={ - category="ll", - direction="l", - }, - [0x1D666]={ - category="ll", - direction="l", - }, - [0x1D667]={ - category="ll", - direction="l", - }, - [0x1D668]={ - category="ll", - direction="l", - }, - [0x1D669]={ - category="ll", - direction="l", - }, - [0x1D66A]={ - category="ll", - direction="l", - }, - [0x1D66B]={ - category="ll", - direction="l", - }, - [0x1D66C]={ - category="ll", - direction="l", - }, - [0x1D66D]={ - category="ll", - direction="l", - }, - [0x1D66E]={ - category="ll", - direction="l", - }, - [0x1D66F]={ - category="ll", - direction="l", - }, - [0x1D670]={ - category="lu", - direction="l", - }, - [0x1D671]={ - category="lu", - direction="l", - }, - [0x1D672]={ - category="lu", - direction="l", - }, - [0x1D673]={ - category="lu", - direction="l", - }, - [0x1D674]={ - category="lu", - direction="l", - }, - [0x1D675]={ - category="lu", - direction="l", - }, - [0x1D676]={ - category="lu", - direction="l", - }, - [0x1D677]={ - category="lu", - direction="l", - }, - [0x1D678]={ - category="lu", - direction="l", - }, - [0x1D679]={ - category="lu", - direction="l", - }, - [0x1D67A]={ - category="lu", - direction="l", - }, - [0x1D67B]={ - category="lu", - direction="l", - }, - [0x1D67C]={ - category="lu", - direction="l", - }, - [0x1D67D]={ - category="lu", - direction="l", - }, - [0x1D67E]={ - category="lu", - direction="l", - }, - [0x1D67F]={ - category="lu", - direction="l", - }, - [0x1D680]={ - category="lu", - direction="l", - }, - [0x1D681]={ - category="lu", - direction="l", - }, - [0x1D682]={ - category="lu", - direction="l", - }, - [0x1D683]={ - category="lu", - direction="l", - }, - [0x1D684]={ - category="lu", - direction="l", - }, - [0x1D685]={ - category="lu", - direction="l", - }, - [0x1D686]={ - category="lu", - direction="l", - }, - [0x1D687]={ - category="lu", - direction="l", - }, - [0x1D688]={ - category="lu", - direction="l", - }, - [0x1D689]={ - category="lu", - direction="l", - }, - [0x1D68A]={ - category="ll", - direction="l", - }, - [0x1D68B]={ - category="ll", - direction="l", - }, - [0x1D68C]={ - category="ll", - direction="l", - }, - [0x1D68D]={ - category="ll", - direction="l", - }, - [0x1D68E]={ - category="ll", - direction="l", - }, - [0x1D68F]={ - category="ll", - direction="l", - }, - [0x1D690]={ - category="ll", - direction="l", - }, - [0x1D691]={ - category="ll", - direction="l", - }, - [0x1D692]={ - category="ll", - direction="l", - }, - [0x1D693]={ - category="ll", - direction="l", - }, - [0x1D694]={ - category="ll", - direction="l", - }, - [0x1D695]={ - category="ll", - direction="l", - }, - [0x1D696]={ - category="ll", - direction="l", - }, - [0x1D697]={ - category="ll", - direction="l", - }, - [0x1D698]={ - category="ll", - direction="l", - }, - [0x1D699]={ - category="ll", - direction="l", - }, - [0x1D69A]={ - category="ll", - direction="l", - }, - [0x1D69B]={ - category="ll", - direction="l", - }, - [0x1D69C]={ - category="ll", - direction="l", - }, - [0x1D69D]={ - category="ll", - direction="l", - }, - [0x1D69E]={ - category="ll", - direction="l", - }, - [0x1D69F]={ - category="ll", - direction="l", - }, - [0x1D6A0]={ - category="ll", - direction="l", - }, - [0x1D6A1]={ - category="ll", - direction="l", - }, - [0x1D6A2]={ - category="ll", - direction="l", - }, - [0x1D6A3]={ - category="ll", - direction="l", - }, - [0x1D6A4]={ - category="ll", - direction="l", - }, - [0x1D6A5]={ - category="ll", - direction="l", - }, - [0x1D6A8]={ - category="lu", - direction="l", - }, - [0x1D6A9]={ - category="lu", - direction="l", - }, - [0x1D6AA]={ - category="lu", - direction="l", - }, - [0x1D6AB]={ - category="lu", - direction="l", - }, - [0x1D6AC]={ - category="lu", - direction="l", - }, - [0x1D6AD]={ - category="lu", - direction="l", - }, - [0x1D6AE]={ - category="lu", - direction="l", - }, - [0x1D6AF]={ - category="lu", - direction="l", - }, - [0x1D6B0]={ - category="lu", - direction="l", - }, - [0x1D6B1]={ - category="lu", - direction="l", - }, - [0x1D6B2]={ - category="lu", - direction="l", - }, - [0x1D6B3]={ - category="lu", - direction="l", - }, - [0x1D6B4]={ - category="lu", - direction="l", - }, - [0x1D6B5]={ - category="lu", - direction="l", - }, - [0x1D6B6]={ - category="lu", - direction="l", - }, - [0x1D6B7]={ - category="lu", - direction="l", - }, - [0x1D6B8]={ - category="lu", - direction="l", - }, - [0x1D6B9]={ - category="lu", - direction="l", - }, - [0x1D6BA]={ - category="lu", - direction="l", - }, - [0x1D6BB]={ - category="lu", - direction="l", - }, - [0x1D6BC]={ - category="lu", - direction="l", - }, - [0x1D6BD]={ - category="lu", - direction="l", - }, - [0x1D6BE]={ - category="lu", - direction="l", - }, - [0x1D6BF]={ - category="lu", - direction="l", - }, - [0x1D6C0]={ - category="lu", - direction="l", - }, - [0x1D6C1]={ - category="sm", - direction="l", - }, - [0x1D6C2]={ - category="ll", - direction="l", - }, - [0x1D6C3]={ - category="ll", - direction="l", - }, - [0x1D6C4]={ - category="ll", - direction="l", - }, - [0x1D6C5]={ - category="ll", - direction="l", - }, - [0x1D6C6]={ - category="ll", - direction="l", - }, - [0x1D6C7]={ - category="ll", - direction="l", - }, - [0x1D6C8]={ - category="ll", - direction="l", - }, - [0x1D6C9]={ - category="ll", - direction="l", - }, - [0x1D6CA]={ - category="ll", - direction="l", - }, - [0x1D6CB]={ - category="ll", - direction="l", - }, - [0x1D6CC]={ - category="ll", - direction="l", - }, - [0x1D6CD]={ - category="ll", - direction="l", - }, - [0x1D6CE]={ - category="ll", - direction="l", - }, - [0x1D6CF]={ - category="ll", - direction="l", - }, - [0x1D6D0]={ - category="ll", - direction="l", - }, - [0x1D6D1]={ - category="ll", - direction="l", - }, - [0x1D6D2]={ - category="ll", - direction="l", - }, - [0x1D6D3]={ - category="ll", - direction="l", - }, - [0x1D6D4]={ - category="ll", - direction="l", - }, - [0x1D6D5]={ - category="ll", - direction="l", - }, - [0x1D6D6]={ - category="ll", - direction="l", - }, - [0x1D6D7]={ - category="ll", - direction="l", - }, - [0x1D6D8]={ - category="ll", - direction="l", - }, - [0x1D6D9]={ - category="ll", - direction="l", - }, - [0x1D6DA]={ - category="ll", - direction="l", - }, - [0x1D6DB]={ - category="sm", - direction="on", - }, - [0x1D6DC]={ - category="ll", - direction="l", - }, - [0x1D6DD]={ - category="ll", - direction="l", - }, - [0x1D6DE]={ - category="ll", - direction="l", - }, - [0x1D6DF]={ - category="ll", - direction="l", - }, - [0x1D6E0]={ - category="ll", - direction="l", - }, - [0x1D6E1]={ - category="ll", - direction="l", - }, - [0x1D6E2]={ - category="lu", - direction="l", - }, - [0x1D6E3]={ - category="lu", - direction="l", - }, - [0x1D6E4]={ - category="lu", - direction="l", - }, - [0x1D6E5]={ - category="lu", - direction="l", - }, - [0x1D6E6]={ - category="lu", - direction="l", - }, - [0x1D6E7]={ - category="lu", - direction="l", - }, - [0x1D6E8]={ - category="lu", - direction="l", - }, - [0x1D6E9]={ - category="lu", - direction="l", - }, - [0x1D6EA]={ - category="lu", - direction="l", - }, - [0x1D6EB]={ - category="lu", - direction="l", - }, - [0x1D6EC]={ - category="lu", - direction="l", - }, - [0x1D6ED]={ - category="lu", - direction="l", - }, - [0x1D6EE]={ - category="lu", - direction="l", - }, - [0x1D6EF]={ - category="lu", - direction="l", - }, - [0x1D6F0]={ - category="lu", - direction="l", - }, - [0x1D6F1]={ - category="lu", - direction="l", - }, - [0x1D6F2]={ - category="lu", - direction="l", - }, - [0x1D6F3]={ - category="lu", - direction="l", - }, - [0x1D6F4]={ - category="lu", - direction="l", - }, - [0x1D6F5]={ - category="lu", - direction="l", - }, - [0x1D6F6]={ - category="lu", - direction="l", - }, - [0x1D6F7]={ - category="lu", - direction="l", - }, - [0x1D6F8]={ - category="lu", - direction="l", - }, - [0x1D6F9]={ - category="lu", - direction="l", - }, - [0x1D6FA]={ - category="lu", - direction="l", - }, - [0x1D6FB]={ - category="sm", - direction="l", - }, - [0x1D6FC]={ - category="ll", - direction="l", - }, - [0x1D6FD]={ - category="ll", - direction="l", - }, - [0x1D6FE]={ - category="ll", - direction="l", - }, - [0x1D6FF]={ - category="ll", - direction="l", - }, - [0x1D700]={ - category="ll", - direction="l", - }, - [0x1D701]={ - category="ll", - direction="l", - }, - [0x1D702]={ - category="ll", - direction="l", - }, - [0x1D703]={ - category="ll", - direction="l", - }, - [0x1D704]={ - category="ll", - direction="l", - }, - [0x1D705]={ - category="ll", - direction="l", - }, - [0x1D706]={ - category="ll", - direction="l", - }, - [0x1D707]={ - category="ll", - direction="l", - }, - [0x1D708]={ - category="ll", - direction="l", - }, - [0x1D709]={ - category="ll", - direction="l", - }, - [0x1D70A]={ - category="ll", - direction="l", - }, - [0x1D70B]={ - category="ll", - direction="l", - }, - [0x1D70C]={ - category="ll", - direction="l", - }, - [0x1D70D]={ - category="ll", - direction="l", - }, - [0x1D70E]={ - category="ll", - direction="l", - }, - [0x1D70F]={ - category="ll", - direction="l", - }, - [0x1D710]={ - category="ll", - direction="l", - }, - [0x1D711]={ - category="ll", - direction="l", - }, - [0x1D712]={ - category="ll", - direction="l", - }, - [0x1D713]={ - category="ll", - direction="l", - }, - [0x1D714]={ - category="ll", - direction="l", - }, - [0x1D715]={ - category="sm", - direction="on", - }, - [0x1D716]={ - category="ll", - direction="l", - }, - [0x1D717]={ - category="ll", - direction="l", - }, - [0x1D718]={ - category="ll", - direction="l", - }, - [0x1D719]={ - category="ll", - direction="l", - }, - [0x1D71A]={ - category="ll", - direction="l", - }, - [0x1D71B]={ - category="ll", - direction="l", - }, - [0x1D71C]={ - category="lu", - direction="l", - }, - [0x1D71D]={ - category="lu", - direction="l", - }, - [0x1D71E]={ - category="lu", - direction="l", - }, - [0x1D71F]={ - category="lu", - direction="l", - }, - [0x1D720]={ - category="lu", - direction="l", - }, - [0x1D721]={ - category="lu", - direction="l", - }, - [0x1D722]={ - category="lu", - direction="l", - }, - [0x1D723]={ - category="lu", - direction="l", - }, - [0x1D724]={ - category="lu", - direction="l", - }, - [0x1D725]={ - category="lu", - direction="l", - }, - [0x1D726]={ - category="lu", - direction="l", - }, - [0x1D727]={ - category="lu", - direction="l", - }, - [0x1D728]={ - category="lu", - direction="l", - }, - [0x1D729]={ - category="lu", - direction="l", - }, - [0x1D72A]={ - category="lu", - direction="l", - }, - [0x1D72B]={ - category="lu", - direction="l", - }, - [0x1D72C]={ - category="lu", - direction="l", - }, - [0x1D72D]={ - category="lu", - direction="l", - }, - [0x1D72E]={ - category="lu", - direction="l", - }, - [0x1D72F]={ - category="lu", - direction="l", - }, - [0x1D730]={ - category="lu", - direction="l", - }, - [0x1D731]={ - category="lu", - direction="l", - }, - [0x1D732]={ - category="lu", - direction="l", - }, - [0x1D733]={ - category="lu", - direction="l", - }, - [0x1D734]={ - category="lu", - direction="l", - }, - [0x1D735]={ - category="sm", - direction="l", - }, - [0x1D736]={ - category="ll", - direction="l", - }, - [0x1D737]={ - category="ll", - direction="l", - }, - [0x1D738]={ - category="ll", - direction="l", - }, - [0x1D739]={ - category="ll", - direction="l", - }, - [0x1D73A]={ - category="ll", - direction="l", - }, - [0x1D73B]={ - category="ll", - direction="l", - }, - [0x1D73C]={ - category="ll", - direction="l", - }, - [0x1D73D]={ - category="ll", - direction="l", - }, - [0x1D73E]={ - category="ll", - direction="l", - }, - [0x1D73F]={ - category="ll", - direction="l", - }, - [0x1D740]={ - category="ll", - direction="l", - }, - [0x1D741]={ - category="ll", - direction="l", - }, - [0x1D742]={ - category="ll", - direction="l", - }, - [0x1D743]={ - category="ll", - direction="l", - }, - [0x1D744]={ - category="ll", - direction="l", - }, - [0x1D745]={ - category="ll", - direction="l", - }, - [0x1D746]={ - category="ll", - direction="l", - }, - [0x1D747]={ - category="ll", - direction="l", - }, - [0x1D748]={ - category="ll", - direction="l", - }, - [0x1D749]={ - category="ll", - direction="l", - }, - [0x1D74A]={ - category="ll", - direction="l", - }, - [0x1D74B]={ - category="ll", - direction="l", - }, - [0x1D74C]={ - category="ll", - direction="l", - }, - [0x1D74D]={ - category="ll", - direction="l", - }, - [0x1D74E]={ - category="ll", - direction="l", - }, - [0x1D74F]={ - category="sm", - direction="on", - }, - [0x1D750]={ - category="ll", - direction="l", - }, - [0x1D751]={ - category="ll", - direction="l", - }, - [0x1D752]={ - category="ll", - direction="l", - }, - [0x1D753]={ - category="ll", - direction="l", - }, - [0x1D754]={ - category="ll", - direction="l", - }, - [0x1D755]={ - category="ll", - direction="l", - }, - [0x1D756]={ - category="lu", - direction="l", - }, - [0x1D757]={ - category="lu", - direction="l", - }, - [0x1D758]={ - category="lu", - direction="l", - }, - [0x1D759]={ - category="lu", - direction="l", - }, - [0x1D75A]={ - category="lu", - direction="l", - }, - [0x1D75B]={ - category="lu", - direction="l", - }, - [0x1D75C]={ - category="lu", - direction="l", - }, - [0x1D75D]={ - category="lu", - direction="l", - }, - [0x1D75E]={ - category="lu", - direction="l", - }, - [0x1D75F]={ - category="lu", - direction="l", - }, - [0x1D760]={ - category="lu", - direction="l", - }, - [0x1D761]={ - category="lu", - direction="l", - }, - [0x1D762]={ - category="lu", - direction="l", - }, - [0x1D763]={ - category="lu", - direction="l", - }, - [0x1D764]={ - category="lu", - direction="l", - }, - [0x1D765]={ - category="lu", - direction="l", - }, - [0x1D766]={ - category="lu", - direction="l", - }, - [0x1D767]={ - category="lu", - direction="l", - }, - [0x1D768]={ - category="lu", - direction="l", - }, - [0x1D769]={ - category="lu", - direction="l", - }, - [0x1D76A]={ - category="lu", - direction="l", - }, - [0x1D76B]={ - category="lu", - direction="l", - }, - [0x1D76C]={ - category="lu", - direction="l", - }, - [0x1D76D]={ - category="lu", - direction="l", - }, - [0x1D76E]={ - category="lu", - direction="l", - }, - [0x1D76F]={ - category="sm", - direction="l", - }, - [0x1D770]={ - category="ll", - direction="l", - }, - [0x1D771]={ - category="ll", - direction="l", - }, - [0x1D772]={ - category="ll", - direction="l", - }, - [0x1D773]={ - category="ll", - direction="l", - }, - [0x1D774]={ - category="ll", - direction="l", - }, - [0x1D775]={ - category="ll", - direction="l", - }, - [0x1D776]={ - category="ll", - direction="l", - }, - [0x1D777]={ - category="ll", - direction="l", - }, - [0x1D778]={ - category="ll", - direction="l", - }, - [0x1D779]={ - category="ll", - direction="l", - }, - [0x1D77A]={ - category="ll", - direction="l", - }, - [0x1D77B]={ - category="ll", - direction="l", - }, - [0x1D77C]={ - category="ll", - direction="l", - }, - [0x1D77D]={ - category="ll", - direction="l", - }, - [0x1D77E]={ - category="ll", - direction="l", - }, - [0x1D77F]={ - category="ll", - direction="l", - }, - [0x1D780]={ - category="ll", - direction="l", - }, - [0x1D781]={ - category="ll", - direction="l", - }, - [0x1D782]={ - category="ll", - direction="l", - }, - [0x1D783]={ - category="ll", - direction="l", - }, - [0x1D784]={ - category="ll", - direction="l", - }, - [0x1D785]={ - category="ll", - direction="l", - }, - [0x1D786]={ - category="ll", - direction="l", - }, - [0x1D787]={ - category="ll", - direction="l", - }, - [0x1D788]={ - category="ll", - direction="l", - }, - [0x1D789]={ - category="sm", - direction="on", - }, - [0x1D78A]={ - category="ll", - direction="l", - }, - [0x1D78B]={ - category="ll", - direction="l", - }, - [0x1D78C]={ - category="ll", - direction="l", - }, - [0x1D78D]={ - category="ll", - direction="l", - }, - [0x1D78E]={ - category="ll", - direction="l", - }, - [0x1D78F]={ - category="ll", - direction="l", - }, - [0x1D790]={ - category="lu", - direction="l", - }, - [0x1D791]={ - category="lu", - direction="l", - }, - [0x1D792]={ - category="lu", - direction="l", - }, - [0x1D793]={ - category="lu", - direction="l", - }, - [0x1D794]={ - category="lu", - direction="l", - }, - [0x1D795]={ - category="lu", - direction="l", - }, - [0x1D796]={ - category="lu", - direction="l", - }, - [0x1D797]={ - category="lu", - direction="l", - }, - [0x1D798]={ - category="lu", - direction="l", - }, - [0x1D799]={ - category="lu", - direction="l", - }, - [0x1D79A]={ - category="lu", - direction="l", - }, - [0x1D79B]={ - category="lu", - direction="l", - }, - [0x1D79C]={ - category="lu", - direction="l", - }, - [0x1D79D]={ - category="lu", - direction="l", - }, - [0x1D79E]={ - category="lu", - direction="l", - }, - [0x1D79F]={ - category="lu", - direction="l", - }, - [0x1D7A0]={ - category="lu", - direction="l", - }, - [0x1D7A1]={ - category="lu", - direction="l", - }, - [0x1D7A2]={ - category="lu", - direction="l", - }, - [0x1D7A3]={ - category="lu", - direction="l", - }, - [0x1D7A4]={ - category="lu", - direction="l", - }, - [0x1D7A5]={ - category="lu", - direction="l", - }, - [0x1D7A6]={ - category="lu", - direction="l", - }, - [0x1D7A7]={ - category="lu", - direction="l", - }, - [0x1D7A8]={ - category="lu", - direction="l", - }, - [0x1D7A9]={ - category="sm", - direction="l", - }, - [0x1D7AA]={ - category="ll", - direction="l", - }, - [0x1D7AB]={ - category="ll", - direction="l", - }, - [0x1D7AC]={ - category="ll", - direction="l", - }, - [0x1D7AD]={ - category="ll", - direction="l", - }, - [0x1D7AE]={ - category="ll", - direction="l", - }, - [0x1D7AF]={ - category="ll", - direction="l", - }, - [0x1D7B0]={ - category="ll", - direction="l", - }, - [0x1D7B1]={ - category="ll", - direction="l", - }, - [0x1D7B2]={ - category="ll", - direction="l", - }, - [0x1D7B3]={ - category="ll", - direction="l", - }, - [0x1D7B4]={ - category="ll", - direction="l", - }, - [0x1D7B5]={ - category="ll", - direction="l", - }, - [0x1D7B6]={ - category="ll", - direction="l", - }, - [0x1D7B7]={ - category="ll", - direction="l", - }, - [0x1D7B8]={ - category="ll", - direction="l", - }, - [0x1D7B9]={ - category="ll", - direction="l", - }, - [0x1D7BA]={ - category="ll", - direction="l", - }, - [0x1D7BB]={ - category="ll", - direction="l", - }, - [0x1D7BC]={ - category="ll", - direction="l", - }, - [0x1D7BD]={ - category="ll", - direction="l", - }, - [0x1D7BE]={ - category="ll", - direction="l", - }, - [0x1D7BF]={ - category="ll", - direction="l", - }, - [0x1D7C0]={ - category="ll", - direction="l", - }, - [0x1D7C1]={ - category="ll", - direction="l", - }, - [0x1D7C2]={ - category="ll", - direction="l", - }, - [0x1D7C3]={ - category="sm", - direction="on", - }, - [0x1D7C4]={ - category="ll", - direction="l", - }, - [0x1D7C5]={ - category="ll", - direction="l", - }, - [0x1D7C6]={ - category="ll", - direction="l", - }, - [0x1D7C7]={ - category="ll", - direction="l", - }, - [0x1D7C8]={ - category="ll", - direction="l", - }, - [0x1D7C9]={ - category="ll", - direction="l", - }, - [0x1D7CA]={ - category="lu", - direction="l", - }, - [0x1D7CB]={ - category="ll", - direction="l", - }, - [0x1D7CE]={ - category="nd", - direction="en", - }, - [0x1D7CF]={ - category="nd", - direction="en", - }, - [0x1D7D0]={ - category="nd", - direction="en", - }, - [0x1D7D1]={ - category="nd", - direction="en", - }, - [0x1D7D2]={ - category="nd", - direction="en", - }, - [0x1D7D3]={ - category="nd", - direction="en", - }, - [0x1D7D4]={ - category="nd", - direction="en", - }, - [0x1D7D5]={ - category="nd", - direction="en", - }, - [0x1D7D6]={ - category="nd", - direction="en", - }, - [0x1D7D7]={ - category="nd", - direction="en", - }, - [0x1D7D8]={ - category="nd", - direction="en", - }, - [0x1D7D9]={ - category="nd", - direction="en", - }, - [0x1D7DA]={ - category="nd", - direction="en", - }, - [0x1D7DB]={ - category="nd", - direction="en", - }, - [0x1D7DC]={ - category="nd", - direction="en", - }, - [0x1D7DD]={ - category="nd", - direction="en", - }, - [0x1D7DE]={ - category="nd", - direction="en", - }, - [0x1D7DF]={ - category="nd", - direction="en", - }, - [0x1D7E0]={ - category="nd", - direction="en", - }, - [0x1D7E1]={ - category="nd", - direction="en", - }, - [0x1D7E2]={ - category="nd", - direction="en", - }, - [0x1D7E3]={ - category="nd", - direction="en", - }, - [0x1D7E4]={ - category="nd", - direction="en", - }, - [0x1D7E5]={ - category="nd", - direction="en", - }, - [0x1D7E6]={ - category="nd", - direction="en", - }, - [0x1D7E7]={ - category="nd", - direction="en", - }, - [0x1D7E8]={ - category="nd", - direction="en", - }, - [0x1D7E9]={ - category="nd", - direction="en", - }, - [0x1D7EA]={ - category="nd", - direction="en", - }, - [0x1D7EB]={ - category="nd", - direction="en", - }, - [0x1D7EC]={ - category="nd", - direction="en", - }, - [0x1D7ED]={ - category="nd", - direction="en", - }, - [0x1D7EE]={ - category="nd", - direction="en", - }, - [0x1D7EF]={ - category="nd", - direction="en", - }, - [0x1D7F0]={ - category="nd", - direction="en", - }, - [0x1D7F1]={ - category="nd", - direction="en", - }, - [0x1D7F2]={ - category="nd", - direction="en", - }, - [0x1D7F3]={ - category="nd", - direction="en", - }, - [0x1D7F4]={ - category="nd", - direction="en", - }, - [0x1D7F5]={ - category="nd", - direction="en", - }, - [0x1D7F6]={ - category="nd", - direction="en", - }, - [0x1D7F7]={ - category="nd", - direction="en", - }, - [0x1D7F8]={ - category="nd", - direction="en", - }, - [0x1D7F9]={ - category="nd", - direction="en", - }, - [0x1D7FA]={ - category="nd", - direction="en", - }, - [0x1D7FB]={ - category="nd", - direction="en", - }, - [0x1D7FC]={ - category="nd", - direction="en", - }, - [0x1D7FD]={ - category="nd", - direction="en", - }, - [0x1D7FE]={ - category="nd", - direction="en", - }, - [0x1D7FF]={ - category="nd", - direction="en", - }, - [0x1D800]={ - category="so", - direction="l", - }, - [0x1D801]={ - category="so", - direction="l", - }, - [0x1D802]={ - category="so", - direction="l", - }, - [0x1D803]={ - category="so", - direction="l", - }, - [0x1D804]={ - category="so", - direction="l", - }, - [0x1D805]={ - category="so", - direction="l", - }, - [0x1D806]={ - category="so", - direction="l", - }, - [0x1D807]={ - category="so", - direction="l", - }, - [0x1D808]={ - category="so", - direction="l", - }, - [0x1D809]={ - category="so", - direction="l", - }, - [0x1D80A]={ - category="so", - direction="l", - }, - [0x1D80B]={ - category="so", - direction="l", - }, - [0x1D80C]={ - category="so", - direction="l", - }, - [0x1D80D]={ - category="so", - direction="l", - }, - [0x1D80E]={ - category="so", - direction="l", - }, - [0x1D80F]={ - category="so", - direction="l", - }, - [0x1D810]={ - category="so", - direction="l", - }, - [0x1D811]={ - category="so", - direction="l", - }, - [0x1D812]={ - category="so", - direction="l", - }, - [0x1D813]={ - category="so", - direction="l", - }, - [0x1D814]={ - category="so", - direction="l", - }, - [0x1D815]={ - category="so", - direction="l", - }, - [0x1D816]={ - category="so", - direction="l", - }, - [0x1D817]={ - category="so", - direction="l", - }, - [0x1D818]={ - category="so", - direction="l", - }, - [0x1D819]={ - category="so", - direction="l", - }, - [0x1D81A]={ - category="so", - direction="l", - }, - [0x1D81B]={ - category="so", - direction="l", - }, - [0x1D81C]={ - category="so", - direction="l", - }, - [0x1D81D]={ - category="so", - direction="l", - }, - [0x1D81E]={ - category="so", - direction="l", - }, - [0x1D81F]={ - category="so", - direction="l", - }, - [0x1D820]={ - category="so", - direction="l", - }, - [0x1D821]={ - category="so", - direction="l", - }, - [0x1D822]={ - category="so", - direction="l", - }, - [0x1D823]={ - category="so", - direction="l", - }, - [0x1D824]={ - category="so", - direction="l", - }, - [0x1D825]={ - category="so", - direction="l", - }, - [0x1D826]={ - category="so", - direction="l", - }, - [0x1D827]={ - category="so", - direction="l", - }, - [0x1D828]={ - category="so", - direction="l", - }, - [0x1D829]={ - category="so", - direction="l", - }, - [0x1D82A]={ - category="so", - direction="l", - }, - [0x1D82B]={ - category="so", - direction="l", - }, - [0x1D82C]={ - category="so", - direction="l", - }, - [0x1D82D]={ - category="so", - direction="l", - }, - [0x1D82E]={ - category="so", - direction="l", - }, - [0x1D82F]={ - category="so", - direction="l", - }, - [0x1D830]={ - category="so", - direction="l", - }, - [0x1D831]={ - category="so", - direction="l", - }, - [0x1D832]={ - category="so", - direction="l", - }, - [0x1D833]={ - category="so", - direction="l", - }, - [0x1D834]={ - category="so", - direction="l", - }, - [0x1D835]={ - category="so", - direction="l", - }, - [0x1D836]={ - category="so", - direction="l", - }, - [0x1D837]={ - category="so", - direction="l", - }, - [0x1D838]={ - category="so", - direction="l", - }, - [0x1D839]={ - category="so", - direction="l", - }, - [0x1D83A]={ - category="so", - direction="l", - }, - [0x1D83B]={ - category="so", - direction="l", - }, - [0x1D83C]={ - category="so", - direction="l", - }, - [0x1D83D]={ - category="so", - direction="l", - }, - [0x1D83E]={ - category="so", - direction="l", - }, - [0x1D83F]={ - category="so", - direction="l", - }, - [0x1D840]={ - category="so", - direction="l", - }, - [0x1D841]={ - category="so", - direction="l", - }, - [0x1D842]={ - category="so", - direction="l", - }, - [0x1D843]={ - category="so", - direction="l", - }, - [0x1D844]={ - category="so", - direction="l", - }, - [0x1D845]={ - category="so", - direction="l", - }, - [0x1D846]={ - category="so", - direction="l", - }, - [0x1D847]={ - category="so", - direction="l", - }, - [0x1D848]={ - category="so", - direction="l", - }, - [0x1D849]={ - category="so", - direction="l", - }, - [0x1D84A]={ - category="so", - direction="l", - }, - [0x1D84B]={ - category="so", - direction="l", - }, - [0x1D84C]={ - category="so", - direction="l", - }, - [0x1D84D]={ - category="so", - direction="l", - }, - [0x1D84E]={ - category="so", - direction="l", - }, - [0x1D84F]={ - category="so", - direction="l", - }, - [0x1D850]={ - category="so", - direction="l", - }, - [0x1D851]={ - category="so", - direction="l", - }, - [0x1D852]={ - category="so", - direction="l", - }, - [0x1D853]={ - category="so", - direction="l", - }, - [0x1D854]={ - category="so", - direction="l", - }, - [0x1D855]={ - category="so", - direction="l", - }, - [0x1D856]={ - category="so", - direction="l", - }, - [0x1D857]={ - category="so", - direction="l", - }, - [0x1D858]={ - category="so", - direction="l", - }, - [0x1D859]={ - category="so", - direction="l", - }, - [0x1D85A]={ - category="so", - direction="l", - }, - [0x1D85B]={ - category="so", - direction="l", - }, - [0x1D85C]={ - category="so", - direction="l", - }, - [0x1D85D]={ - category="so", - direction="l", - }, - [0x1D85E]={ - category="so", - direction="l", - }, - [0x1D85F]={ - category="so", - direction="l", - }, - [0x1D860]={ - category="so", - direction="l", - }, - [0x1D861]={ - category="so", - direction="l", - }, - [0x1D862]={ - category="so", - direction="l", - }, - [0x1D863]={ - category="so", - direction="l", - }, - [0x1D864]={ - category="so", - direction="l", - }, - [0x1D865]={ - category="so", - direction="l", - }, - [0x1D866]={ - category="so", - direction="l", - }, - [0x1D867]={ - category="so", - direction="l", - }, - [0x1D868]={ - category="so", - direction="l", - }, - [0x1D869]={ - category="so", - direction="l", - }, - [0x1D86A]={ - category="so", - direction="l", - }, - [0x1D86B]={ - category="so", - direction="l", - }, - [0x1D86C]={ - category="so", - direction="l", - }, - [0x1D86D]={ - category="so", - direction="l", - }, - [0x1D86E]={ - category="so", - direction="l", - }, - [0x1D86F]={ - category="so", - direction="l", - }, - [0x1D870]={ - category="so", - direction="l", - }, - [0x1D871]={ - category="so", - direction="l", - }, - [0x1D872]={ - category="so", - direction="l", - }, - [0x1D873]={ - category="so", - direction="l", - }, - [0x1D874]={ - category="so", - direction="l", - }, - [0x1D875]={ - category="so", - direction="l", - }, - [0x1D876]={ - category="so", - direction="l", - }, - [0x1D877]={ - category="so", - direction="l", - }, - [0x1D878]={ - category="so", - direction="l", - }, - [0x1D879]={ - category="so", - direction="l", - }, - [0x1D87A]={ - category="so", - direction="l", - }, - [0x1D87B]={ - category="so", - direction="l", - }, - [0x1D87C]={ - category="so", - direction="l", - }, - [0x1D87D]={ - category="so", - direction="l", - }, - [0x1D87E]={ - category="so", - direction="l", - }, - [0x1D87F]={ - category="so", - direction="l", - }, - [0x1D880]={ - category="so", - direction="l", - }, - [0x1D881]={ - category="so", - direction="l", - }, - [0x1D882]={ - category="so", - direction="l", - }, - [0x1D883]={ - category="so", - direction="l", - }, - [0x1D884]={ - category="so", - direction="l", - }, - [0x1D885]={ - category="so", - direction="l", - }, - [0x1D886]={ - category="so", - direction="l", - }, - [0x1D887]={ - category="so", - direction="l", - }, - [0x1D888]={ - category="so", - direction="l", - }, - [0x1D889]={ - category="so", - direction="l", - }, - [0x1D88A]={ - category="so", - direction="l", - }, - [0x1D88B]={ - category="so", - direction="l", - }, - [0x1D88C]={ - category="so", - direction="l", - }, - [0x1D88D]={ - category="so", - direction="l", - }, - [0x1D88E]={ - category="so", - direction="l", - }, - [0x1D88F]={ - category="so", - direction="l", - }, - [0x1D890]={ - category="so", - direction="l", - }, - [0x1D891]={ - category="so", - direction="l", - }, - [0x1D892]={ - category="so", - direction="l", - }, - [0x1D893]={ - category="so", - direction="l", - }, - [0x1D894]={ - category="so", - direction="l", - }, - [0x1D895]={ - category="so", - direction="l", - }, - [0x1D896]={ - category="so", - direction="l", - }, - [0x1D897]={ - category="so", - direction="l", - }, - [0x1D898]={ - category="so", - direction="l", - }, - [0x1D899]={ - category="so", - direction="l", - }, - [0x1D89A]={ - category="so", - direction="l", - }, - [0x1D89B]={ - category="so", - direction="l", - }, - [0x1D89C]={ - category="so", - direction="l", - }, - [0x1D89D]={ - category="so", - direction="l", - }, - [0x1D89E]={ - category="so", - direction="l", - }, - [0x1D89F]={ - category="so", - direction="l", - }, - [0x1D8A0]={ - category="so", - direction="l", - }, - [0x1D8A1]={ - category="so", - direction="l", - }, - [0x1D8A2]={ - category="so", - direction="l", - }, - [0x1D8A3]={ - category="so", - direction="l", - }, - [0x1D8A4]={ - category="so", - direction="l", - }, - [0x1D8A5]={ - category="so", - direction="l", - }, - [0x1D8A6]={ - category="so", - direction="l", - }, - [0x1D8A7]={ - category="so", - direction="l", - }, - [0x1D8A8]={ - category="so", - direction="l", - }, - [0x1D8A9]={ - category="so", - direction="l", - }, - [0x1D8AA]={ - category="so", - direction="l", - }, - [0x1D8AB]={ - category="so", - direction="l", - }, - [0x1D8AC]={ - category="so", - direction="l", - }, - [0x1D8AD]={ - category="so", - direction="l", - }, - [0x1D8AE]={ - category="so", - direction="l", - }, - [0x1D8AF]={ - category="so", - direction="l", - }, - [0x1D8B0]={ - category="so", - direction="l", - }, - [0x1D8B1]={ - category="so", - direction="l", - }, - [0x1D8B2]={ - category="so", - direction="l", - }, - [0x1D8B3]={ - category="so", - direction="l", - }, - [0x1D8B4]={ - category="so", - direction="l", - }, - [0x1D8B5]={ - category="so", - direction="l", - }, - [0x1D8B6]={ - category="so", - direction="l", - }, - [0x1D8B7]={ - category="so", - direction="l", - }, - [0x1D8B8]={ - category="so", - direction="l", - }, - [0x1D8B9]={ - category="so", - direction="l", - }, - [0x1D8BA]={ - category="so", - direction="l", - }, - [0x1D8BB]={ - category="so", - direction="l", - }, - [0x1D8BC]={ - category="so", - direction="l", - }, - [0x1D8BD]={ - category="so", - direction="l", - }, - [0x1D8BE]={ - category="so", - direction="l", - }, - [0x1D8BF]={ - category="so", - direction="l", - }, - [0x1D8C0]={ - category="so", - direction="l", - }, - [0x1D8C1]={ - category="so", - direction="l", - }, - [0x1D8C2]={ - category="so", - direction="l", - }, - [0x1D8C3]={ - category="so", - direction="l", - }, - [0x1D8C4]={ - category="so", - direction="l", - }, - [0x1D8C5]={ - category="so", - direction="l", - }, - [0x1D8C6]={ - category="so", - direction="l", - }, - [0x1D8C7]={ - category="so", - direction="l", - }, - [0x1D8C8]={ - category="so", - direction="l", - }, - [0x1D8C9]={ - category="so", - direction="l", - }, - [0x1D8CA]={ - category="so", - direction="l", - }, - [0x1D8CB]={ - category="so", - direction="l", - }, - [0x1D8CC]={ - category="so", - direction="l", - }, - [0x1D8CD]={ - category="so", - direction="l", - }, - [0x1D8CE]={ - category="so", - direction="l", - }, - [0x1D8CF]={ - category="so", - direction="l", - }, - [0x1D8D0]={ - category="so", - direction="l", - }, - [0x1D8D1]={ - category="so", - direction="l", - }, - [0x1D8D2]={ - category="so", - direction="l", - }, - [0x1D8D3]={ - category="so", - direction="l", - }, - [0x1D8D4]={ - category="so", - direction="l", - }, - [0x1D8D5]={ - category="so", - direction="l", - }, - [0x1D8D6]={ - category="so", - direction="l", - }, - [0x1D8D7]={ - category="so", - direction="l", - }, - [0x1D8D8]={ - category="so", - direction="l", - }, - [0x1D8D9]={ - category="so", - direction="l", - }, - [0x1D8DA]={ - category="so", - direction="l", - }, - [0x1D8DB]={ - category="so", - direction="l", - }, - [0x1D8DC]={ - category="so", - direction="l", - }, - [0x1D8DD]={ - category="so", - direction="l", - }, - [0x1D8DE]={ - category="so", - direction="l", - }, - [0x1D8DF]={ - category="so", - direction="l", - }, - [0x1D8E0]={ - category="so", - direction="l", - }, - [0x1D8E1]={ - category="so", - direction="l", - }, - [0x1D8E2]={ - category="so", - direction="l", - }, - [0x1D8E3]={ - category="so", - direction="l", - }, - [0x1D8E4]={ - category="so", - direction="l", - }, - [0x1D8E5]={ - category="so", - direction="l", - }, - [0x1D8E6]={ - category="so", - direction="l", - }, - [0x1D8E7]={ - category="so", - direction="l", - }, - [0x1D8E8]={ - category="so", - direction="l", - }, - [0x1D8E9]={ - category="so", - direction="l", - }, - [0x1D8EA]={ - category="so", - direction="l", - }, - [0x1D8EB]={ - category="so", - direction="l", - }, - [0x1D8EC]={ - category="so", - direction="l", - }, - [0x1D8ED]={ - category="so", - direction="l", - }, - [0x1D8EE]={ - category="so", - direction="l", - }, - [0x1D8EF]={ - category="so", - direction="l", - }, - [0x1D8F0]={ - category="so", - direction="l", - }, - [0x1D8F1]={ - category="so", - direction="l", - }, - [0x1D8F2]={ - category="so", - direction="l", - }, - [0x1D8F3]={ - category="so", - direction="l", - }, - [0x1D8F4]={ - category="so", - direction="l", - }, - [0x1D8F5]={ - category="so", - direction="l", - }, - [0x1D8F6]={ - category="so", - direction="l", - }, - [0x1D8F7]={ - category="so", - direction="l", - }, - [0x1D8F8]={ - category="so", - direction="l", - }, - [0x1D8F9]={ - category="so", - direction="l", - }, - [0x1D8FA]={ - category="so", - direction="l", - }, - [0x1D8FB]={ - category="so", - direction="l", - }, - [0x1D8FC]={ - category="so", - direction="l", - }, - [0x1D8FD]={ - category="so", - direction="l", - }, - [0x1D8FE]={ - category="so", - direction="l", - }, - [0x1D8FF]={ - category="so", - direction="l", - }, - [0x1D900]={ - category="so", - direction="l", - }, - [0x1D901]={ - category="so", - direction="l", - }, - [0x1D902]={ - category="so", - direction="l", - }, - [0x1D903]={ - category="so", - direction="l", - }, - [0x1D904]={ - category="so", - direction="l", - }, - [0x1D905]={ - category="so", - direction="l", - }, - [0x1D906]={ - category="so", - direction="l", - }, - [0x1D907]={ - category="so", - direction="l", - }, - [0x1D908]={ - category="so", - direction="l", - }, - [0x1D909]={ - category="so", - direction="l", - }, - [0x1D90A]={ - category="so", - direction="l", - }, - [0x1D90B]={ - category="so", - direction="l", - }, - [0x1D90C]={ - category="so", - direction="l", - }, - [0x1D90D]={ - category="so", - direction="l", - }, - [0x1D90E]={ - category="so", - direction="l", - }, - [0x1D90F]={ - category="so", - direction="l", - }, - [0x1D910]={ - category="so", - direction="l", - }, - [0x1D911]={ - category="so", - direction="l", - }, - [0x1D912]={ - category="so", - direction="l", - }, - [0x1D913]={ - category="so", - direction="l", - }, - [0x1D914]={ - category="so", - direction="l", - }, - [0x1D915]={ - category="so", - direction="l", - }, - [0x1D916]={ - category="so", - direction="l", - }, - [0x1D917]={ - category="so", - direction="l", - }, - [0x1D918]={ - category="so", - direction="l", - }, - [0x1D919]={ - category="so", - direction="l", - }, - [0x1D91A]={ - category="so", - direction="l", - }, - [0x1D91B]={ - category="so", - direction="l", - }, - [0x1D91C]={ - category="so", - direction="l", - }, - [0x1D91D]={ - category="so", - direction="l", - }, - [0x1D91E]={ - category="so", - direction="l", - }, - [0x1D91F]={ - category="so", - direction="l", - }, - [0x1D920]={ - category="so", - direction="l", - }, - [0x1D921]={ - category="so", - direction="l", - }, - [0x1D922]={ - category="so", - direction="l", - }, - [0x1D923]={ - category="so", - direction="l", - }, - [0x1D924]={ - category="so", - direction="l", - }, - [0x1D925]={ - category="so", - direction="l", - }, - [0x1D926]={ - category="so", - direction="l", - }, - [0x1D927]={ - category="so", - direction="l", - }, - [0x1D928]={ - category="so", - direction="l", - }, - [0x1D929]={ - category="so", - direction="l", - }, - [0x1D92A]={ - category="so", - direction="l", - }, - [0x1D92B]={ - category="so", - direction="l", - }, - [0x1D92C]={ - category="so", - direction="l", - }, - [0x1D92D]={ - category="so", - direction="l", - }, - [0x1D92E]={ - category="so", - direction="l", - }, - [0x1D92F]={ - category="so", - direction="l", - }, - [0x1D930]={ - category="so", - direction="l", - }, - [0x1D931]={ - category="so", - direction="l", - }, - [0x1D932]={ - category="so", - direction="l", - }, - [0x1D933]={ - category="so", - direction="l", - }, - [0x1D934]={ - category="so", - direction="l", - }, - [0x1D935]={ - category="so", - direction="l", - }, - [0x1D936]={ - category="so", - direction="l", - }, - [0x1D937]={ - category="so", - direction="l", - }, - [0x1D938]={ - category="so", - direction="l", - }, - [0x1D939]={ - category="so", - direction="l", - }, - [0x1D93A]={ - category="so", - direction="l", - }, - [0x1D93B]={ - category="so", - direction="l", - }, - [0x1D93C]={ - category="so", - direction="l", - }, - [0x1D93D]={ - category="so", - direction="l", - }, - [0x1D93E]={ - category="so", - direction="l", - }, - [0x1D93F]={ - category="so", - direction="l", - }, - [0x1D940]={ - category="so", - direction="l", - }, - [0x1D941]={ - category="so", - direction="l", - }, - [0x1D942]={ - category="so", - direction="l", - }, - [0x1D943]={ - category="so", - direction="l", - }, - [0x1D944]={ - category="so", - direction="l", - }, - [0x1D945]={ - category="so", - direction="l", - }, - [0x1D946]={ - category="so", - direction="l", - }, - [0x1D947]={ - category="so", - direction="l", - }, - [0x1D948]={ - category="so", - direction="l", - }, - [0x1D949]={ - category="so", - direction="l", - }, - [0x1D94A]={ - category="so", - direction="l", - }, - [0x1D94B]={ - category="so", - direction="l", - }, - [0x1D94C]={ - category="so", - direction="l", - }, - [0x1D94D]={ - category="so", - direction="l", - }, - [0x1D94E]={ - category="so", - direction="l", - }, - [0x1D94F]={ - category="so", - direction="l", - }, - [0x1D950]={ - category="so", - direction="l", - }, - [0x1D951]={ - category="so", - direction="l", - }, - [0x1D952]={ - category="so", - direction="l", - }, - [0x1D953]={ - category="so", - direction="l", - }, - [0x1D954]={ - category="so", - direction="l", - }, - [0x1D955]={ - category="so", - direction="l", - }, - [0x1D956]={ - category="so", - direction="l", - }, - [0x1D957]={ - category="so", - direction="l", - }, - [0x1D958]={ - category="so", - direction="l", - }, - [0x1D959]={ - category="so", - direction="l", - }, - [0x1D95A]={ - category="so", - direction="l", - }, - [0x1D95B]={ - category="so", - direction="l", - }, - [0x1D95C]={ - category="so", - direction="l", - }, - [0x1D95D]={ - category="so", - direction="l", - }, - [0x1D95E]={ - category="so", - direction="l", - }, - [0x1D95F]={ - category="so", - direction="l", - }, - [0x1D960]={ - category="so", - direction="l", - }, - [0x1D961]={ - category="so", - direction="l", - }, - [0x1D962]={ - category="so", - direction="l", - }, - [0x1D963]={ - category="so", - direction="l", - }, - [0x1D964]={ - category="so", - direction="l", - }, - [0x1D965]={ - category="so", - direction="l", - }, - [0x1D966]={ - category="so", - direction="l", - }, - [0x1D967]={ - category="so", - direction="l", - }, - [0x1D968]={ - category="so", - direction="l", - }, - [0x1D969]={ - category="so", - direction="l", - }, - [0x1D96A]={ - category="so", - direction="l", - }, - [0x1D96B]={ - category="so", - direction="l", - }, - [0x1D96C]={ - category="so", - direction="l", - }, - [0x1D96D]={ - category="so", - direction="l", - }, - [0x1D96E]={ - category="so", - direction="l", - }, - [0x1D96F]={ - category="so", - direction="l", - }, - [0x1D970]={ - category="so", - direction="l", - }, - [0x1D971]={ - category="so", - direction="l", - }, - [0x1D972]={ - category="so", - direction="l", - }, - [0x1D973]={ - category="so", - direction="l", - }, - [0x1D974]={ - category="so", - direction="l", - }, - [0x1D975]={ - category="so", - direction="l", - }, - [0x1D976]={ - category="so", - direction="l", - }, - [0x1D977]={ - category="so", - direction="l", - }, - [0x1D978]={ - category="so", - direction="l", - }, - [0x1D979]={ - category="so", - direction="l", - }, - [0x1D97A]={ - category="so", - direction="l", - }, - [0x1D97B]={ - category="so", - direction="l", - }, - [0x1D97C]={ - category="so", - direction="l", - }, - [0x1D97D]={ - category="so", - direction="l", - }, - [0x1D97E]={ - category="so", - direction="l", - }, - [0x1D97F]={ - category="so", - direction="l", - }, - [0x1D980]={ - category="so", - direction="l", - }, - [0x1D981]={ - category="so", - direction="l", - }, - [0x1D982]={ - category="so", - direction="l", - }, - [0x1D983]={ - category="so", - direction="l", - }, - [0x1D984]={ - category="so", - direction="l", - }, - [0x1D985]={ - category="so", - direction="l", - }, - [0x1D986]={ - category="so", - direction="l", - }, - [0x1D987]={ - category="so", - direction="l", - }, - [0x1D988]={ - category="so", - direction="l", - }, - [0x1D989]={ - category="so", - direction="l", - }, - [0x1D98A]={ - category="so", - direction="l", - }, - [0x1D98B]={ - category="so", - direction="l", - }, - [0x1D98C]={ - category="so", - direction="l", - }, - [0x1D98D]={ - category="so", - direction="l", - }, - [0x1D98E]={ - category="so", - direction="l", - }, - [0x1D98F]={ - category="so", - direction="l", - }, - [0x1D990]={ - category="so", - direction="l", - }, - [0x1D991]={ - category="so", - direction="l", - }, - [0x1D992]={ - category="so", - direction="l", - }, - [0x1D993]={ - category="so", - direction="l", - }, - [0x1D994]={ - category="so", - direction="l", - }, - [0x1D995]={ - category="so", - direction="l", - }, - [0x1D996]={ - category="so", - direction="l", - }, - [0x1D997]={ - category="so", - direction="l", - }, - [0x1D998]={ - category="so", - direction="l", - }, - [0x1D999]={ - category="so", - direction="l", - }, - [0x1D99A]={ - category="so", - direction="l", - }, - [0x1D99B]={ - category="so", - direction="l", - }, - [0x1D99C]={ - category="so", - direction="l", - }, - [0x1D99D]={ - category="so", - direction="l", - }, - [0x1D99E]={ - category="so", - direction="l", - }, - [0x1D99F]={ - category="so", - direction="l", - }, - [0x1D9A0]={ - category="so", - direction="l", - }, - [0x1D9A1]={ - category="so", - direction="l", - }, - [0x1D9A2]={ - category="so", - direction="l", - }, - [0x1D9A3]={ - category="so", - direction="l", - }, - [0x1D9A4]={ - category="so", - direction="l", - }, - [0x1D9A5]={ - category="so", - direction="l", - }, - [0x1D9A6]={ - category="so", - direction="l", - }, - [0x1D9A7]={ - category="so", - direction="l", - }, - [0x1D9A8]={ - category="so", - direction="l", - }, - [0x1D9A9]={ - category="so", - direction="l", - }, - [0x1D9AA]={ - category="so", - direction="l", - }, - [0x1D9AB]={ - category="so", - direction="l", - }, - [0x1D9AC]={ - category="so", - direction="l", - }, - [0x1D9AD]={ - category="so", - direction="l", - }, - [0x1D9AE]={ - category="so", - direction="l", - }, - [0x1D9AF]={ - category="so", - direction="l", - }, - [0x1D9B0]={ - category="so", - direction="l", - }, - [0x1D9B1]={ - category="so", - direction="l", - }, - [0x1D9B2]={ - category="so", - direction="l", - }, - [0x1D9B3]={ - category="so", - direction="l", - }, - [0x1D9B4]={ - category="so", - direction="l", - }, - [0x1D9B5]={ - category="so", - direction="l", - }, - [0x1D9B6]={ - category="so", - direction="l", - }, - [0x1D9B7]={ - category="so", - direction="l", - }, - [0x1D9B8]={ - category="so", - direction="l", - }, - [0x1D9B9]={ - category="so", - direction="l", - }, - [0x1D9BA]={ - category="so", - direction="l", - }, - [0x1D9BB]={ - category="so", - direction="l", - }, - [0x1D9BC]={ - category="so", - direction="l", - }, - [0x1D9BD]={ - category="so", - direction="l", - }, - [0x1D9BE]={ - category="so", - direction="l", - }, - [0x1D9BF]={ - category="so", - direction="l", - }, - [0x1D9C0]={ - category="so", - direction="l", - }, - [0x1D9C1]={ - category="so", - direction="l", - }, - [0x1D9C2]={ - category="so", - direction="l", - }, - [0x1D9C3]={ - category="so", - direction="l", - }, - [0x1D9C4]={ - category="so", - direction="l", - }, - [0x1D9C5]={ - category="so", - direction="l", - }, - [0x1D9C6]={ - category="so", - direction="l", - }, - [0x1D9C7]={ - category="so", - direction="l", - }, - [0x1D9C8]={ - category="so", - direction="l", - }, - [0x1D9C9]={ - category="so", - direction="l", - }, - [0x1D9CA]={ - category="so", - direction="l", - }, - [0x1D9CB]={ - category="so", - direction="l", - }, - [0x1D9CC]={ - category="so", - direction="l", - }, - [0x1D9CD]={ - category="so", - direction="l", - }, - [0x1D9CE]={ - category="so", - direction="l", - }, - [0x1D9CF]={ - category="so", - direction="l", - }, - [0x1D9D0]={ - category="so", - direction="l", - }, - [0x1D9D1]={ - category="so", - direction="l", - }, - [0x1D9D2]={ - category="so", - direction="l", - }, - [0x1D9D3]={ - category="so", - direction="l", - }, - [0x1D9D4]={ - category="so", - direction="l", - }, - [0x1D9D5]={ - category="so", - direction="l", - }, - [0x1D9D6]={ - category="so", - direction="l", - }, - [0x1D9D7]={ - category="so", - direction="l", - }, - [0x1D9D8]={ - category="so", - direction="l", - }, - [0x1D9D9]={ - category="so", - direction="l", - }, - [0x1D9DA]={ - category="so", - direction="l", - }, - [0x1D9DB]={ - category="so", - direction="l", - }, - [0x1D9DC]={ - category="so", - direction="l", - }, - [0x1D9DD]={ - category="so", - direction="l", - }, - [0x1D9DE]={ - category="so", - direction="l", - }, - [0x1D9DF]={ - category="so", - direction="l", - }, - [0x1D9E0]={ - category="so", - direction="l", - }, - [0x1D9E1]={ - category="so", - direction="l", - }, - [0x1D9E2]={ - category="so", - direction="l", - }, - [0x1D9E3]={ - category="so", - direction="l", - }, - [0x1D9E4]={ - category="so", - direction="l", - }, - [0x1D9E5]={ - category="so", - direction="l", - }, - [0x1D9E6]={ - category="so", - direction="l", - }, - [0x1D9E7]={ - category="so", - direction="l", - }, - [0x1D9E8]={ - category="so", - direction="l", - }, - [0x1D9E9]={ - category="so", - direction="l", - }, - [0x1D9EA]={ - category="so", - direction="l", - }, - [0x1D9EB]={ - category="so", - direction="l", - }, - [0x1D9EC]={ - category="so", - direction="l", - }, - [0x1D9ED]={ - category="so", - direction="l", - }, - [0x1D9EE]={ - category="so", - direction="l", - }, - [0x1D9EF]={ - category="so", - direction="l", - }, - [0x1D9F0]={ - category="so", - direction="l", - }, - [0x1D9F1]={ - category="so", - direction="l", - }, - [0x1D9F2]={ - category="so", - direction="l", - }, - [0x1D9F3]={ - category="so", - direction="l", - }, - [0x1D9F4]={ - category="so", - direction="l", - }, - [0x1D9F5]={ - category="so", - direction="l", - }, - [0x1D9F6]={ - category="so", - direction="l", - }, - [0x1D9F7]={ - category="so", - direction="l", - }, - [0x1D9F8]={ - category="so", - direction="l", - }, - [0x1D9F9]={ - category="so", - direction="l", - }, - [0x1D9FA]={ - category="so", - direction="l", - }, - [0x1D9FB]={ - category="so", - direction="l", - }, - [0x1D9FC]={ - category="so", - direction="l", - }, - [0x1D9FD]={ - category="so", - direction="l", - }, - [0x1D9FE]={ - category="so", - direction="l", - }, - [0x1D9FF]={ - category="so", - direction="l", - }, - [0x1DA00]={ - category="mn", - direction="nsm", - }, - [0x1DA01]={ - category="mn", - direction="nsm", - }, - [0x1DA02]={ - category="mn", - direction="nsm", - }, - [0x1DA03]={ - category="mn", - direction="nsm", - }, - [0x1DA04]={ - category="mn", - direction="nsm", - }, - [0x1DA05]={ - category="mn", - direction="nsm", - }, - [0x1DA06]={ - category="mn", - direction="nsm", - }, - [0x1DA07]={ - category="mn", - direction="nsm", - }, - [0x1DA08]={ - category="mn", - direction="nsm", - }, - [0x1DA09]={ - category="mn", - direction="nsm", - }, - [0x1DA0A]={ - category="mn", - direction="nsm", - }, - [0x1DA0B]={ - category="mn", - direction="nsm", - }, - [0x1DA0C]={ - category="mn", - direction="nsm", - }, - [0x1DA0D]={ - category="mn", - direction="nsm", - }, - [0x1DA0E]={ - category="mn", - direction="nsm", - }, - [0x1DA0F]={ - category="mn", - direction="nsm", - }, - [0x1DA10]={ - category="mn", - direction="nsm", - }, - [0x1DA11]={ - category="mn", - direction="nsm", - }, - [0x1DA12]={ - category="mn", - direction="nsm", - }, - [0x1DA13]={ - category="mn", - direction="nsm", - }, - [0x1DA14]={ - category="mn", - direction="nsm", - }, - [0x1DA15]={ - category="mn", - direction="nsm", - }, - [0x1DA16]={ - category="mn", - direction="nsm", - }, - [0x1DA17]={ - category="mn", - direction="nsm", - }, - [0x1DA18]={ - category="mn", - direction="nsm", - }, - [0x1DA19]={ - category="mn", - direction="nsm", - }, - [0x1DA1A]={ - category="mn", - direction="nsm", - }, - [0x1DA1B]={ - category="mn", - direction="nsm", - }, - [0x1DA1C]={ - category="mn", - direction="nsm", - }, - [0x1DA1D]={ - category="mn", - direction="nsm", - }, - [0x1DA1E]={ - category="mn", - direction="nsm", - }, - [0x1DA1F]={ - category="mn", - direction="nsm", - }, - [0x1DA20]={ - category="mn", - direction="nsm", - }, - [0x1DA21]={ - category="mn", - direction="nsm", - }, - [0x1DA22]={ - category="mn", - direction="nsm", - }, - [0x1DA23]={ - category="mn", - direction="nsm", - }, - [0x1DA24]={ - category="mn", - direction="nsm", - }, - [0x1DA25]={ - category="mn", - direction="nsm", - }, - [0x1DA26]={ - category="mn", - direction="nsm", - }, - [0x1DA27]={ - category="mn", - direction="nsm", - }, - [0x1DA28]={ - category="mn", - direction="nsm", - }, - [0x1DA29]={ - category="mn", - direction="nsm", - }, - [0x1DA2A]={ - category="mn", - direction="nsm", - }, - [0x1DA2B]={ - category="mn", - direction="nsm", - }, - [0x1DA2C]={ - category="mn", - direction="nsm", - }, - [0x1DA2D]={ - category="mn", - direction="nsm", - }, - [0x1DA2E]={ - category="mn", - direction="nsm", - }, - [0x1DA2F]={ - category="mn", - direction="nsm", - }, - [0x1DA30]={ - category="mn", - direction="nsm", - }, - [0x1DA31]={ - category="mn", - direction="nsm", - }, - [0x1DA32]={ - category="mn", - direction="nsm", - }, - [0x1DA33]={ - category="mn", - direction="nsm", - }, - [0x1DA34]={ - category="mn", - direction="nsm", - }, - [0x1DA35]={ - category="mn", - direction="nsm", - }, - [0x1DA36]={ - category="mn", - direction="nsm", - }, - [0x1DA37]={ - category="so", - direction="l", - }, - [0x1DA38]={ - category="so", - direction="l", - }, - [0x1DA39]={ - category="so", - direction="l", - }, - [0x1DA3A]={ - category="so", - direction="l", - }, - [0x1DA3B]={ - category="mn", - direction="nsm", - }, - [0x1DA3C]={ - category="mn", - direction="nsm", - }, - [0x1DA3D]={ - category="mn", - direction="nsm", - }, - [0x1DA3E]={ - category="mn", - direction="nsm", - }, - [0x1DA3F]={ - category="mn", - direction="nsm", - }, - [0x1DA40]={ - category="mn", - direction="nsm", - }, - [0x1DA41]={ - category="mn", - direction="nsm", - }, - [0x1DA42]={ - category="mn", - direction="nsm", - }, - [0x1DA43]={ - category="mn", - direction="nsm", - }, - [0x1DA44]={ - category="mn", - direction="nsm", - }, - [0x1DA45]={ - category="mn", - direction="nsm", - }, - [0x1DA46]={ - category="mn", - direction="nsm", - }, - [0x1DA47]={ - category="mn", - direction="nsm", - }, - [0x1DA48]={ - category="mn", - direction="nsm", - }, - [0x1DA49]={ - category="mn", - direction="nsm", - }, - [0x1DA4A]={ - category="mn", - direction="nsm", - }, - [0x1DA4B]={ - category="mn", - direction="nsm", - }, - [0x1DA4C]={ - category="mn", - direction="nsm", - }, - [0x1DA4D]={ - category="mn", - direction="nsm", - }, - [0x1DA4E]={ - category="mn", - direction="nsm", - }, - [0x1DA4F]={ - category="mn", - direction="nsm", - }, - [0x1DA50]={ - category="mn", - direction="nsm", - }, - [0x1DA51]={ - category="mn", - direction="nsm", - }, - [0x1DA52]={ - category="mn", - direction="nsm", - }, - [0x1DA53]={ - category="mn", - direction="nsm", - }, - [0x1DA54]={ - category="mn", - direction="nsm", - }, - [0x1DA55]={ - category="mn", - direction="nsm", - }, - [0x1DA56]={ - category="mn", - direction="nsm", - }, - [0x1DA57]={ - category="mn", - direction="nsm", - }, - [0x1DA58]={ - category="mn", - direction="nsm", - }, - [0x1DA59]={ - category="mn", - direction="nsm", - }, - [0x1DA5A]={ - category="mn", - direction="nsm", - }, - [0x1DA5B]={ - category="mn", - direction="nsm", - }, - [0x1DA5C]={ - category="mn", - direction="nsm", - }, - [0x1DA5D]={ - category="mn", - direction="nsm", - }, - [0x1DA5E]={ - category="mn", - direction="nsm", - }, - [0x1DA5F]={ - category="mn", - direction="nsm", - }, - [0x1DA60]={ - category="mn", - direction="nsm", - }, - [0x1DA61]={ - category="mn", - direction="nsm", - }, - [0x1DA62]={ - category="mn", - direction="nsm", - }, - [0x1DA63]={ - category="mn", - direction="nsm", - }, - [0x1DA64]={ - category="mn", - direction="nsm", - }, - [0x1DA65]={ - category="mn", - direction="nsm", - }, - [0x1DA66]={ - category="mn", - direction="nsm", - }, - [0x1DA67]={ - category="mn", - direction="nsm", - }, - [0x1DA68]={ - category="mn", - direction="nsm", - }, - [0x1DA69]={ - category="mn", - direction="nsm", - }, - [0x1DA6A]={ - category="mn", - direction="nsm", - }, - [0x1DA6B]={ - category="mn", - direction="nsm", - }, - [0x1DA6C]={ - category="mn", - direction="nsm", - }, - [0x1DA6D]={ - category="so", - direction="l", - }, - [0x1DA6E]={ - category="so", - direction="l", - }, - [0x1DA6F]={ - category="so", - direction="l", - }, - [0x1DA70]={ - category="so", - direction="l", - }, - [0x1DA71]={ - category="so", - direction="l", - }, - [0x1DA72]={ - category="so", - direction="l", - }, - [0x1DA73]={ - category="so", - direction="l", - }, - [0x1DA74]={ - category="so", - direction="l", - }, - [0x1DA75]={ - category="mn", - direction="nsm", - }, - [0x1DA76]={ - category="so", - direction="l", - }, - [0x1DA77]={ - category="so", - direction="l", - }, - [0x1DA78]={ - category="so", - direction="l", - }, - [0x1DA79]={ - category="so", - direction="l", - }, - [0x1DA7A]={ - category="so", - direction="l", - }, - [0x1DA7B]={ - category="so", - direction="l", - }, - [0x1DA7C]={ - category="so", - direction="l", - }, - [0x1DA7D]={ - category="so", - direction="l", - }, - [0x1DA7E]={ - category="so", - direction="l", - }, - [0x1DA7F]={ - category="so", - direction="l", - }, - [0x1DA80]={ - category="so", - direction="l", - }, - [0x1DA81]={ - category="so", - direction="l", - }, - [0x1DA82]={ - category="so", - direction="l", - }, - [0x1DA83]={ - category="so", - direction="l", - }, - [0x1DA84]={ - category="mn", - direction="nsm", - }, - [0x1DA85]={ - category="so", - direction="l", - }, - [0x1DA86]={ - category="so", - direction="l", - }, - [0x1DA87]={ - category="po", - direction="l", - }, - [0x1DA88]={ - category="po", - direction="l", - }, - [0x1DA89]={ - category="po", - direction="l", - }, - [0x1DA8A]={ - category="po", - direction="l", - }, - [0x1DA8B]={ - category="po", - direction="l", - }, - [0x1DA9B]={ - category="mn", - direction="nsm", - }, - [0x1DA9C]={ - category="mn", - direction="nsm", - }, - [0x1DA9D]={ - category="mn", - direction="nsm", - }, - [0x1DA9E]={ - category="mn", - direction="nsm", - }, - [0x1DA9F]={ - category="mn", - direction="nsm", - }, - [0x1DAA1]={ - category="mn", - direction="nsm", - }, - [0x1DAA2]={ - category="mn", - direction="nsm", - }, - [0x1DAA3]={ - category="mn", - direction="nsm", - }, - [0x1DAA4]={ - category="mn", - direction="nsm", - }, - [0x1DAA5]={ - category="mn", - direction="nsm", - }, - [0x1DAA6]={ - category="mn", - direction="nsm", - }, - [0x1DAA7]={ - category="mn", - direction="nsm", - }, - [0x1DAA8]={ - category="mn", - direction="nsm", - }, - [0x1DAA9]={ - category="mn", - direction="nsm", - }, - [0x1DAAA]={ - category="mn", - direction="nsm", - }, - [0x1DAAB]={ - category="mn", - direction="nsm", - }, - [0x1DAAC]={ - category="mn", - direction="nsm", - }, - [0x1DAAD]={ - category="mn", - direction="nsm", - }, - [0x1DAAE]={ - category="mn", - direction="nsm", - }, - [0x1DAAF]={ - category="mn", - direction="nsm", - }, - [0x1E000]={ - category="mn", - direction="nsm", - }, - [0x1E001]={ - category="mn", - direction="nsm", - }, - [0x1E002]={ - category="mn", - direction="nsm", - }, - [0x1E003]={ - category="mn", - direction="nsm", - }, - [0x1E004]={ - category="mn", - direction="nsm", - }, - [0x1E005]={ - category="mn", - direction="nsm", - }, - [0x1E006]={ - category="mn", - direction="nsm", - }, - [0x1E008]={ - category="mn", - direction="nsm", - }, - [0x1E009]={ - category="mn", - direction="nsm", - }, - [0x1E00A]={ - category="mn", - direction="nsm", - }, - [0x1E00B]={ - category="mn", - direction="nsm", - }, - [0x1E00C]={ - category="mn", - direction="nsm", - }, - [0x1E00D]={ - category="mn", - direction="nsm", - }, - [0x1E00E]={ - category="mn", - direction="nsm", - }, - [0x1E00F]={ - category="mn", - direction="nsm", - }, - [0x1E010]={ - category="mn", - direction="nsm", - }, - [0x1E011]={ - category="mn", - direction="nsm", - }, - [0x1E012]={ - category="mn", - direction="nsm", - }, - [0x1E013]={ - category="mn", - direction="nsm", - }, - [0x1E014]={ - category="mn", - direction="nsm", - }, - [0x1E015]={ - category="mn", - direction="nsm", - }, - [0x1E016]={ - category="mn", - direction="nsm", - }, - [0x1E017]={ - category="mn", - direction="nsm", - }, - [0x1E018]={ - category="mn", - direction="nsm", - }, - [0x1E01B]={ - category="mn", - direction="nsm", - }, - [0x1E01C]={ - category="mn", - direction="nsm", - }, - [0x1E01D]={ - category="mn", - direction="nsm", - }, - [0x1E01E]={ - category="mn", - direction="nsm", - }, - [0x1E01F]={ - category="mn", - direction="nsm", - }, - [0x1E020]={ - category="mn", - direction="nsm", - }, - [0x1E021]={ - category="mn", - direction="nsm", - }, - [0x1E023]={ - category="mn", - direction="nsm", - }, - [0x1E024]={ - category="mn", - direction="nsm", - }, - [0x1E026]={ - category="mn", - direction="nsm", - }, - [0x1E027]={ - category="mn", - direction="nsm", - }, - [0x1E028]={ - category="mn", - direction="nsm", - }, - [0x1E029]={ - category="mn", - direction="nsm", - }, - [0x1E02A]={ - category="mn", - direction="nsm", - }, - [0x1E800]={ - category="lo", - direction="r", - }, - [0x1E801]={ - category="lo", - direction="r", - }, - [0x1E802]={ - category="lo", - direction="r", - }, - [0x1E803]={ - category="lo", - direction="r", - }, - [0x1E804]={ - category="lo", - direction="r", - }, - [0x1E805]={ - category="lo", - direction="r", - }, - [0x1E806]={ - category="lo", - direction="r", - }, - [0x1E807]={ - category="lo", - direction="r", - }, - [0x1E808]={ - category="lo", - direction="r", - }, - [0x1E809]={ - category="lo", - direction="r", - }, - [0x1E80A]={ - category="lo", - direction="r", - }, - [0x1E80B]={ - category="lo", - direction="r", - }, - [0x1E80C]={ - category="lo", - direction="r", - }, - [0x1E80D]={ - category="lo", - direction="r", - }, - [0x1E80E]={ - category="lo", - direction="r", - }, - [0x1E80F]={ - category="lo", - direction="r", - }, - [0x1E810]={ - category="lo", - direction="r", - }, - [0x1E811]={ - category="lo", - direction="r", - }, - [0x1E812]={ - category="lo", - direction="r", - }, - [0x1E813]={ - category="lo", - direction="r", - }, - [0x1E814]={ - category="lo", - direction="r", - }, - [0x1E815]={ - category="lo", - direction="r", - }, - [0x1E816]={ - category="lo", - direction="r", - }, - [0x1E817]={ - category="lo", - direction="r", - }, - [0x1E818]={ - category="lo", - direction="r", - }, - [0x1E819]={ - category="lo", - direction="r", - }, - [0x1E81A]={ - category="lo", - direction="r", - }, - [0x1E81B]={ - category="lo", - direction="r", - }, - [0x1E81C]={ - category="lo", - direction="r", - }, - [0x1E81D]={ - category="lo", - direction="r", - }, - [0x1E81E]={ - category="lo", - direction="r", - }, - [0x1E81F]={ - category="lo", - direction="r", - }, - [0x1E820]={ - category="lo", - direction="r", - }, - [0x1E821]={ - category="lo", - direction="r", - }, - [0x1E822]={ - category="lo", - direction="r", - }, - [0x1E823]={ - category="lo", - direction="r", - }, - [0x1E824]={ - category="lo", - direction="r", - }, - [0x1E825]={ - category="lo", - direction="r", - }, - [0x1E826]={ - category="lo", - direction="r", - }, - [0x1E827]={ - category="lo", - direction="r", - }, - [0x1E828]={ - category="lo", - direction="r", - }, - [0x1E829]={ - category="lo", - direction="r", - }, - [0x1E82A]={ - category="lo", - direction="r", - }, - [0x1E82B]={ - category="lo", - direction="r", - }, - [0x1E82C]={ - category="lo", - direction="r", - }, - [0x1E82D]={ - category="lo", - direction="r", - }, - [0x1E82E]={ - category="lo", - direction="r", - }, - [0x1E82F]={ - category="lo", - direction="r", - }, - [0x1E830]={ - category="lo", - direction="r", - }, - [0x1E831]={ - category="lo", - direction="r", - }, - [0x1E832]={ - category="lo", - direction="r", - }, - [0x1E833]={ - category="lo", - direction="r", - }, - [0x1E834]={ - category="lo", - direction="r", - }, - [0x1E835]={ - category="lo", - direction="r", - }, - [0x1E836]={ - category="lo", - direction="r", - }, - [0x1E837]={ - category="lo", - direction="r", - }, - [0x1E838]={ - category="lo", - direction="r", - }, - [0x1E839]={ - category="lo", - direction="r", - }, - [0x1E83A]={ - category="lo", - direction="r", - }, - [0x1E83B]={ - category="lo", - direction="r", - }, - [0x1E83C]={ - category="lo", - direction="r", - }, - [0x1E83D]={ - category="lo", - direction="r", - }, - [0x1E83E]={ - category="lo", - direction="r", - }, - [0x1E83F]={ - category="lo", - direction="r", - }, - [0x1E840]={ - category="lo", - direction="r", - }, - [0x1E841]={ - category="lo", - direction="r", - }, - [0x1E842]={ - category="lo", - direction="r", - }, - [0x1E843]={ - category="lo", - direction="r", - }, - [0x1E844]={ - category="lo", - direction="r", - }, - [0x1E845]={ - category="lo", - direction="r", - }, - [0x1E846]={ - category="lo", - direction="r", - }, - [0x1E847]={ - category="lo", - direction="r", - }, - [0x1E848]={ - category="lo", - direction="r", - }, - [0x1E849]={ - category="lo", - direction="r", - }, - [0x1E84A]={ - category="lo", - direction="r", - }, - [0x1E84B]={ - category="lo", - direction="r", - }, - [0x1E84C]={ - category="lo", - direction="r", - }, - [0x1E84D]={ - category="lo", - direction="r", - }, - [0x1E84E]={ - category="lo", - direction="r", - }, - [0x1E84F]={ - category="lo", - direction="r", - }, - [0x1E850]={ - category="lo", - direction="r", - }, - [0x1E851]={ - category="lo", - direction="r", - }, - [0x1E852]={ - category="lo", - direction="r", - }, - [0x1E853]={ - category="lo", - direction="r", - }, - [0x1E854]={ - category="lo", - direction="r", - }, - [0x1E855]={ - category="lo", - direction="r", - }, - [0x1E856]={ - category="lo", - direction="r", - }, - [0x1E857]={ - category="lo", - direction="r", - }, - [0x1E858]={ - category="lo", - direction="r", - }, - [0x1E859]={ - category="lo", - direction="r", - }, - [0x1E85A]={ - category="lo", - direction="r", - }, - [0x1E85B]={ - category="lo", - direction="r", - }, - [0x1E85C]={ - category="lo", - direction="r", - }, - [0x1E85D]={ - category="lo", - direction="r", - }, - [0x1E85E]={ - category="lo", - direction="r", - }, - [0x1E85F]={ - category="lo", - direction="r", - }, - [0x1E860]={ - category="lo", - direction="r", - }, - [0x1E861]={ - category="lo", - direction="r", - }, - [0x1E862]={ - category="lo", - direction="r", - }, - [0x1E863]={ - category="lo", - direction="r", - }, - [0x1E864]={ - category="lo", - direction="r", - }, - [0x1E865]={ - category="lo", - direction="r", - }, - [0x1E866]={ - category="lo", - direction="r", - }, - [0x1E867]={ - category="lo", - direction="r", - }, - [0x1E868]={ - category="lo", - direction="r", - }, - [0x1E869]={ - category="lo", - direction="r", - }, - [0x1E86A]={ - category="lo", - direction="r", - }, - [0x1E86B]={ - category="lo", - direction="r", - }, - [0x1E86C]={ - category="lo", - direction="r", - }, - [0x1E86D]={ - category="lo", - direction="r", - }, - [0x1E86E]={ - category="lo", - direction="r", - }, - [0x1E86F]={ - category="lo", - direction="r", - }, - [0x1E870]={ - category="lo", - direction="r", - }, - [0x1E871]={ - category="lo", - direction="r", - }, - [0x1E872]={ - category="lo", - direction="r", - }, - [0x1E873]={ - category="lo", - direction="r", - }, - [0x1E874]={ - category="lo", - direction="r", - }, - [0x1E875]={ - category="lo", - direction="r", - }, - [0x1E876]={ - category="lo", - direction="r", - }, - [0x1E877]={ - category="lo", - direction="r", - }, - [0x1E878]={ - category="lo", - direction="r", - }, - [0x1E879]={ - category="lo", - direction="r", - }, - [0x1E87A]={ - category="lo", - direction="r", - }, - [0x1E87B]={ - category="lo", - direction="r", - }, - [0x1E87C]={ - category="lo", - direction="r", - }, - [0x1E87D]={ - category="lo", - direction="r", - }, - [0x1E87E]={ - category="lo", - direction="r", - }, - [0x1E87F]={ - category="lo", - direction="r", - }, - [0x1E880]={ - category="lo", - direction="r", - }, - [0x1E881]={ - category="lo", - direction="r", - }, - [0x1E882]={ - category="lo", - direction="r", - }, - [0x1E883]={ - category="lo", - direction="r", - }, - [0x1E884]={ - category="lo", - direction="r", - }, - [0x1E885]={ - category="lo", - direction="r", - }, - [0x1E886]={ - category="lo", - direction="r", - }, - [0x1E887]={ - category="lo", - direction="r", - }, - [0x1E888]={ - category="lo", - direction="r", - }, - [0x1E889]={ - category="lo", - direction="r", - }, - [0x1E88A]={ - category="lo", - direction="r", - }, - [0x1E88B]={ - category="lo", - direction="r", - }, - [0x1E88C]={ - category="lo", - direction="r", - }, - [0x1E88D]={ - category="lo", - direction="r", - }, - [0x1E88E]={ - category="lo", - direction="r", - }, - [0x1E88F]={ - category="lo", - direction="r", - }, - [0x1E890]={ - category="lo", - direction="r", - }, - [0x1E891]={ - category="lo", - direction="r", - }, - [0x1E892]={ - category="lo", - direction="r", - }, - [0x1E893]={ - category="lo", - direction="r", - }, - [0x1E894]={ - category="lo", - direction="r", - }, - [0x1E895]={ - category="lo", - direction="r", - }, - [0x1E896]={ - category="lo", - direction="r", - }, - [0x1E897]={ - category="lo", - direction="r", - }, - [0x1E898]={ - category="lo", - direction="r", - }, - [0x1E899]={ - category="lo", - direction="r", - }, - [0x1E89A]={ - category="lo", - direction="r", - }, - [0x1E89B]={ - category="lo", - direction="r", - }, - [0x1E89C]={ - category="lo", - direction="r", - }, - [0x1E89D]={ - category="lo", - direction="r", - }, - [0x1E89E]={ - category="lo", - direction="r", - }, - [0x1E89F]={ - category="lo", - direction="r", - }, - [0x1E8A0]={ - category="lo", - direction="r", - }, - [0x1E8A1]={ - category="lo", - direction="r", - }, - [0x1E8A2]={ - category="lo", - direction="r", - }, - [0x1E8A3]={ - category="lo", - direction="r", - }, - [0x1E8A4]={ - category="lo", - direction="r", - }, - [0x1E8A5]={ - category="lo", - direction="r", - }, - [0x1E8A6]={ - category="lo", - direction="r", - }, - [0x1E8A7]={ - category="lo", - direction="r", - }, - [0x1E8A8]={ - category="lo", - direction="r", - }, - [0x1E8A9]={ - category="lo", - direction="r", - }, - [0x1E8AA]={ - category="lo", - direction="r", - }, - [0x1E8AB]={ - category="lo", - direction="r", - }, - [0x1E8AC]={ - category="lo", - direction="r", - }, - [0x1E8AD]={ - category="lo", - direction="r", - }, - [0x1E8AE]={ - category="lo", - direction="r", - }, - [0x1E8AF]={ - category="lo", - direction="r", - }, - [0x1E8B0]={ - category="lo", - direction="r", - }, - [0x1E8B1]={ - category="lo", - direction="r", - }, - [0x1E8B2]={ - category="lo", - direction="r", - }, - [0x1E8B3]={ - category="lo", - direction="r", - }, - [0x1E8B4]={ - category="lo", - direction="r", - }, - [0x1E8B5]={ - category="lo", - direction="r", - }, - [0x1E8B6]={ - category="lo", - direction="r", - }, - [0x1E8B7]={ - category="lo", - direction="r", - }, - [0x1E8B8]={ - category="lo", - direction="r", - }, - [0x1E8B9]={ - category="lo", - direction="r", - }, - [0x1E8BA]={ - category="lo", - direction="r", - }, - [0x1E8BB]={ - category="lo", - direction="r", - }, - [0x1E8BC]={ - category="lo", - direction="r", - }, - [0x1E8BD]={ - category="lo", - direction="r", - }, - [0x1E8BE]={ - category="lo", - direction="r", - }, - [0x1E8BF]={ - category="lo", - direction="r", - }, - [0x1E8C0]={ - category="lo", - direction="r", - }, - [0x1E8C1]={ - category="lo", - direction="r", - }, - [0x1E8C2]={ - category="lo", - direction="r", - }, - [0x1E8C3]={ - category="lo", - direction="r", - }, - [0x1E8C4]={ - category="lo", - direction="r", - }, - [0x1E8C7]={ - category="no", - direction="r", - }, - [0x1E8C8]={ - category="no", - direction="r", - }, - [0x1E8C9]={ - category="no", - direction="r", - }, - [0x1E8CA]={ - category="no", - direction="r", - }, - [0x1E8CB]={ - category="no", - direction="r", - }, - [0x1E8CC]={ - category="no", - direction="r", - }, - [0x1E8CD]={ - category="no", - direction="r", - }, - [0x1E8CE]={ - category="no", - direction="r", - }, - [0x1E8CF]={ - category="no", - direction="r", - }, - [0x1E8D0]={ - category="mn", - direction="nsm", - }, - [0x1E8D1]={ - category="mn", - direction="nsm", - }, - [0x1E8D2]={ - category="mn", - direction="nsm", - }, - [0x1E8D3]={ - category="mn", - direction="nsm", - }, - [0x1E8D4]={ - category="mn", - direction="nsm", - }, - [0x1E8D5]={ - category="mn", - direction="nsm", - }, - [0x1E8D6]={ - category="mn", - direction="nsm", - }, - [0x1E900]={ - category="lu", - direction="r", - }, - [0x1E901]={ - category="lu", - direction="r", - }, - [0x1E902]={ - category="lu", - direction="r", - }, - [0x1E903]={ - category="lu", - direction="r", - }, - [0x1E904]={ - category="lu", - direction="r", - }, - [0x1E905]={ - category="lu", - direction="r", - }, - [0x1E906]={ - category="lu", - direction="r", - }, - [0x1E907]={ - category="lu", - direction="r", - }, - [0x1E908]={ - category="lu", - direction="r", - }, - [0x1E909]={ - category="lu", - direction="r", - }, - [0x1E90A]={ - category="lu", - direction="r", - }, - [0x1E90B]={ - category="lu", - direction="r", - }, - [0x1E90C]={ - category="lu", - direction="r", - }, - [0x1E90D]={ - category="lu", - direction="r", - }, - [0x1E90E]={ - category="lu", - direction="r", - }, - [0x1E90F]={ - category="lu", - direction="r", - }, - [0x1E910]={ - category="lu", - direction="r", - }, - [0x1E911]={ - category="lu", - direction="r", - }, - [0x1E912]={ - category="lu", - direction="r", - }, - [0x1E913]={ - category="lu", - direction="r", - }, - [0x1E914]={ - category="lu", - direction="r", - }, - [0x1E915]={ - category="lu", - direction="r", - }, - [0x1E916]={ - category="lu", - direction="r", - }, - [0x1E917]={ - category="lu", - direction="r", - }, - [0x1E918]={ - category="lu", - direction="r", - }, - [0x1E919]={ - category="lu", - direction="r", - }, - [0x1E91A]={ - category="lu", - direction="r", - }, - [0x1E91B]={ - category="lu", - direction="r", - }, - [0x1E91C]={ - category="lu", - direction="r", - }, - [0x1E91D]={ - category="lu", - direction="r", - }, - [0x1E91E]={ - category="lu", - direction="r", - }, - [0x1E91F]={ - category="lu", - direction="r", - }, - [0x1E920]={ - category="lu", - direction="r", - }, - [0x1E921]={ - category="lu", - direction="r", - }, - [0x1E922]={ - category="ll", - direction="r", - }, - [0x1E923]={ - category="ll", - direction="r", - }, - [0x1E924]={ - category="ll", - direction="r", - }, - [0x1E925]={ - category="ll", - direction="r", - }, - [0x1E926]={ - category="ll", - direction="r", - }, - [0x1E927]={ - category="ll", - direction="r", - }, - [0x1E928]={ - category="ll", - direction="r", - }, - [0x1E929]={ - category="ll", - direction="r", - }, - [0x1E92A]={ - category="ll", - direction="r", - }, - [0x1E92B]={ - category="ll", - direction="r", - }, - [0x1E92C]={ - category="ll", - direction="r", - }, - [0x1E92D]={ - category="ll", - direction="r", - }, - [0x1E92E]={ - category="ll", - direction="r", - }, - [0x1E92F]={ - category="ll", - direction="r", - }, - [0x1E930]={ - category="ll", - direction="r", - }, - [0x1E931]={ - category="ll", - direction="r", - }, - [0x1E932]={ - category="ll", - direction="r", - }, - [0x1E933]={ - category="ll", - direction="r", - }, - [0x1E934]={ - category="ll", - direction="r", - }, - [0x1E935]={ - category="ll", - direction="r", - }, - [0x1E936]={ - category="ll", - direction="r", - }, - [0x1E937]={ - category="ll", - direction="r", - }, - [0x1E938]={ - category="ll", - direction="r", - }, - [0x1E939]={ - category="ll", - direction="r", - }, - [0x1E93A]={ - category="ll", - direction="r", - }, - [0x1E93B]={ - category="ll", - direction="r", - }, - [0x1E93C]={ - category="ll", - direction="r", - }, - [0x1E93D]={ - category="ll", - direction="r", - }, - [0x1E93E]={ - category="ll", - direction="r", - }, - [0x1E93F]={ - category="ll", - direction="r", - }, - [0x1E940]={ - category="ll", - direction="r", - }, - [0x1E941]={ - category="ll", - direction="r", - }, - [0x1E942]={ - category="ll", - direction="r", - }, - [0x1E943]={ - category="ll", - direction="r", - }, - [0x1E944]={ - category="mn", - direction="nsm", - }, - [0x1E945]={ - category="mn", - direction="nsm", - }, - [0x1E946]={ - category="mn", - direction="nsm", - }, - [0x1E947]={ - category="mn", - direction="nsm", - }, - [0x1E948]={ - category="mn", - direction="nsm", - }, - [0x1E949]={ - category="mn", - direction="nsm", - }, - [0x1E94A]={ - category="mn", - direction="nsm", - }, - [0x1E950]={ - category="nd", - direction="r", - }, - [0x1E951]={ - category="nd", - direction="r", - }, - [0x1E952]={ - category="nd", - direction="r", - }, - [0x1E953]={ - category="nd", - direction="r", - }, - [0x1E954]={ - category="nd", - direction="r", - }, - [0x1E955]={ - category="nd", - direction="r", - }, - [0x1E956]={ - category="nd", - direction="r", - }, - [0x1E957]={ - category="nd", - direction="r", - }, - [0x1E958]={ - category="nd", - direction="r", - }, - [0x1E959]={ - category="nd", - direction="r", - }, - [0x1E95E]={ - category="po", - direction="r", - }, - [0x1E95F]={ - category="po", - direction="r", - }, - [0x1EE00]={ - category="lo", - direction="al", - }, - [0x1EE01]={ - category="lo", - direction="al", - }, - [0x1EE02]={ - category="lo", - direction="al", - }, - [0x1EE03]={ - category="lo", - direction="al", - }, - [0x1EE05]={ - category="lo", - direction="al", - }, - [0x1EE06]={ - category="lo", - direction="al", - }, - [0x1EE07]={ - category="lo", - direction="al", - }, - [0x1EE08]={ - category="lo", - direction="al", - }, - [0x1EE09]={ - category="lo", - direction="al", - }, - [0x1EE0A]={ - category="lo", - direction="al", - }, - [0x1EE0B]={ - category="lo", - direction="al", - }, - [0x1EE0C]={ - category="lo", - direction="al", - }, - [0x1EE0D]={ - category="lo", - direction="al", - }, - [0x1EE0E]={ - category="lo", - direction="al", - }, - [0x1EE0F]={ - category="lo", - direction="al", - }, - [0x1EE10]={ - category="lo", - direction="al", - }, - [0x1EE11]={ - category="lo", - direction="al", - }, - [0x1EE12]={ - category="lo", - direction="al", - }, - [0x1EE13]={ - category="lo", - direction="al", - }, - [0x1EE14]={ - category="lo", - direction="al", - }, - [0x1EE15]={ - category="lo", - direction="al", - }, - [0x1EE16]={ - category="lo", - direction="al", - }, - [0x1EE17]={ - category="lo", - direction="al", - }, - [0x1EE18]={ - category="lo", - direction="al", - }, - [0x1EE19]={ - category="lo", - direction="al", - }, - [0x1EE1A]={ - category="lo", - direction="al", - }, - [0x1EE1B]={ - category="lo", - direction="al", - }, - [0x1EE1C]={ - category="lo", - direction="al", - }, - [0x1EE1D]={ - category="lo", - direction="al", - }, - [0x1EE1E]={ - category="lo", - direction="al", - }, - [0x1EE1F]={ - category="lo", - direction="al", - }, - [0x1EE21]={ - category="lo", - direction="al", - }, - [0x1EE22]={ - category="lo", - direction="al", - }, - [0x1EE24]={ - category="lo", - direction="al", - }, - [0x1EE27]={ - category="lo", - direction="al", - }, - [0x1EE29]={ - category="lo", - direction="al", - }, - [0x1EE2A]={ - category="lo", - direction="al", - }, - [0x1EE2B]={ - category="lo", - direction="al", - }, - [0x1EE2C]={ - category="lo", - direction="al", - }, - [0x1EE2D]={ - category="lo", - direction="al", - }, - [0x1EE2E]={ - category="lo", - direction="al", - }, - [0x1EE2F]={ - category="lo", - direction="al", - }, - [0x1EE30]={ - category="lo", - direction="al", - }, - [0x1EE31]={ - category="lo", - direction="al", - }, - [0x1EE32]={ - category="lo", - direction="al", - }, - [0x1EE34]={ - category="lo", - direction="al", - }, - [0x1EE35]={ - category="lo", - direction="al", - }, - [0x1EE36]={ - category="lo", - direction="al", - }, - [0x1EE37]={ - category="lo", - direction="al", - }, - [0x1EE39]={ - category="lo", - direction="al", - }, - [0x1EE3B]={ - category="lo", - direction="al", - }, - [0x1EE42]={ - category="lo", - direction="al", - }, - [0x1EE47]={ - category="lo", - direction="al", - }, - [0x1EE49]={ - category="lo", - direction="al", - }, - [0x1EE4B]={ - category="lo", - direction="al", - }, - [0x1EE4D]={ - category="lo", - direction="al", - }, - [0x1EE4E]={ - category="lo", - direction="al", - }, - [0x1EE4F]={ - category="lo", - direction="al", - }, - [0x1EE51]={ - category="lo", - direction="al", - }, - [0x1EE52]={ - category="lo", - direction="al", - }, - [0x1EE54]={ - category="lo", - direction="al", - }, - [0x1EE57]={ - category="lo", - direction="al", - }, - [0x1EE59]={ - category="lo", - direction="al", - }, - [0x1EE5B]={ - category="lo", - direction="al", - }, - [0x1EE5D]={ - category="lo", - direction="al", - }, - [0x1EE5F]={ - category="lo", - direction="al", - }, - [0x1EE61]={ - category="lo", - direction="al", - }, - [0x1EE62]={ - category="lo", - direction="al", - }, - [0x1EE64]={ - category="lo", - direction="al", - }, - [0x1EE67]={ - category="lo", - direction="al", - }, - [0x1EE68]={ - category="lo", - direction="al", - }, - [0x1EE69]={ - category="lo", - direction="al", - }, - [0x1EE6A]={ - category="lo", - direction="al", - }, - [0x1EE6C]={ - category="lo", - direction="al", - }, - [0x1EE6D]={ - category="lo", - direction="al", - }, - [0x1EE6E]={ - category="lo", - direction="al", - }, - [0x1EE6F]={ - category="lo", - direction="al", - }, - [0x1EE70]={ - category="lo", - direction="al", - }, - [0x1EE71]={ - category="lo", - direction="al", - }, - [0x1EE72]={ - category="lo", - direction="al", - }, - [0x1EE74]={ - category="lo", - direction="al", - }, - [0x1EE75]={ - category="lo", - direction="al", - }, - [0x1EE76]={ - category="lo", - direction="al", - }, - [0x1EE77]={ - category="lo", - direction="al", - }, - [0x1EE79]={ - category="lo", - direction="al", - }, - [0x1EE7A]={ - category="lo", - direction="al", - }, - [0x1EE7B]={ - category="lo", - direction="al", - }, - [0x1EE7C]={ - category="lo", - direction="al", - }, - [0x1EE7E]={ - category="lo", - direction="al", - }, - [0x1EE80]={ - category="lo", - direction="al", - }, - [0x1EE81]={ - category="lo", - direction="al", - }, - [0x1EE82]={ - category="lo", - direction="al", - }, - [0x1EE83]={ - category="lo", - direction="al", - }, - [0x1EE84]={ - category="lo", - direction="al", - }, - [0x1EE85]={ - category="lo", - direction="al", - }, - [0x1EE86]={ - category="lo", - direction="al", - }, - [0x1EE87]={ - category="lo", - direction="al", - }, - [0x1EE88]={ - category="lo", - direction="al", - }, - [0x1EE89]={ - category="lo", - direction="al", - }, - [0x1EE8B]={ - category="lo", - direction="al", - }, - [0x1EE8C]={ - category="lo", - direction="al", - }, - [0x1EE8D]={ - category="lo", - direction="al", - }, - [0x1EE8E]={ - category="lo", - direction="al", - }, - [0x1EE8F]={ - category="lo", - direction="al", - }, - [0x1EE90]={ - category="lo", - direction="al", - }, - [0x1EE91]={ - category="lo", - direction="al", - }, - [0x1EE92]={ - category="lo", - direction="al", - }, - [0x1EE93]={ - category="lo", - direction="al", - }, - [0x1EE94]={ - category="lo", - direction="al", - }, - [0x1EE95]={ - category="lo", - direction="al", - }, - [0x1EE96]={ - category="lo", - direction="al", - }, - [0x1EE97]={ - category="lo", - direction="al", - }, - [0x1EE98]={ - category="lo", - direction="al", - }, - [0x1EE99]={ - category="lo", - direction="al", - }, - [0x1EE9A]={ - category="lo", - direction="al", - }, - [0x1EE9B]={ - category="lo", - direction="al", - }, - [0x1EEA1]={ - category="lo", - direction="al", - }, - [0x1EEA2]={ - category="lo", - direction="al", - }, - [0x1EEA3]={ - category="lo", - direction="al", - }, - [0x1EEA5]={ - category="lo", - direction="al", - }, - [0x1EEA6]={ - category="lo", - direction="al", - }, - [0x1EEA7]={ - category="lo", - direction="al", - }, - [0x1EEA8]={ - category="lo", - direction="al", - }, - [0x1EEA9]={ - category="lo", - direction="al", - }, - [0x1EEAB]={ - category="lo", - direction="al", - }, - [0x1EEAC]={ - category="lo", - direction="al", - }, - [0x1EEAD]={ - category="lo", - direction="al", - }, - [0x1EEAE]={ - category="lo", - direction="al", - }, - [0x1EEAF]={ - category="lo", - direction="al", - }, - [0x1EEB0]={ - category="lo", - direction="al", - }, - [0x1EEB1]={ - category="lo", - direction="al", - }, - [0x1EEB2]={ - category="lo", - direction="al", - }, - [0x1EEB3]={ - category="lo", - direction="al", - }, - [0x1EEB4]={ - category="lo", - direction="al", - }, - [0x1EEB5]={ - category="lo", - direction="al", - }, - [0x1EEB6]={ - category="lo", - direction="al", - }, - [0x1EEB7]={ - category="lo", - direction="al", - }, - [0x1EEB8]={ - category="lo", - direction="al", - }, - [0x1EEB9]={ - category="lo", - direction="al", - }, - [0x1EEBA]={ - category="lo", - direction="al", - }, - [0x1EEBB]={ - category="lo", - direction="al", - }, - [0x1EEF0]={ - category="sm", - direction="on", - }, - [0x1EEF1]={ - category="sm", - direction="on", - }, - [0x1F000]={ - category="so", - direction="on", - }, - [0x1F001]={ - category="so", - direction="on", - }, - [0x1F002]={ - category="so", - direction="on", - }, - [0x1F003]={ - category="so", - direction="on", - }, - [0x1F004]={ - category="so", - direction="on", - }, - [0x1F005]={ - category="so", - direction="on", - }, - [0x1F006]={ - category="so", - direction="on", - }, - [0x1F007]={ - category="so", - direction="on", - }, - [0x1F008]={ - category="so", - direction="on", - }, - [0x1F009]={ - category="so", - direction="on", - }, - [0x1F00A]={ - category="so", - direction="on", - }, - [0x1F00B]={ - category="so", - direction="on", - }, - [0x1F00C]={ - category="so", - direction="on", - }, - [0x1F00D]={ - category="so", - direction="on", - }, - [0x1F00E]={ - category="so", - direction="on", - }, - [0x1F00F]={ - category="so", - direction="on", - }, - [0x1F010]={ - category="so", - direction="on", - }, - [0x1F011]={ - category="so", - direction="on", - }, - [0x1F012]={ - category="so", - direction="on", - }, - [0x1F013]={ - category="so", - direction="on", - }, - [0x1F014]={ - category="so", - direction="on", - }, - [0x1F015]={ - category="so", - direction="on", - }, - [0x1F016]={ - category="so", - direction="on", - }, - [0x1F017]={ - category="so", - direction="on", - }, - [0x1F018]={ - category="so", - direction="on", - }, - [0x1F019]={ - category="so", - direction="on", - }, - [0x1F01A]={ - category="so", - direction="on", - }, - [0x1F01B]={ - category="so", - direction="on", - }, - [0x1F01C]={ - category="so", - direction="on", - }, - [0x1F01D]={ - category="so", - direction="on", - }, - [0x1F01E]={ - category="so", - direction="on", - }, - [0x1F01F]={ - category="so", - direction="on", - }, - [0x1F020]={ - category="so", - direction="on", - }, - [0x1F021]={ - category="so", - direction="on", - }, - [0x1F022]={ - category="so", - direction="on", - }, - [0x1F023]={ - category="so", - direction="on", - }, - [0x1F024]={ - category="so", - direction="on", - }, - [0x1F025]={ - category="so", - direction="on", - }, - [0x1F026]={ - category="so", - direction="on", - }, - [0x1F027]={ - category="so", - direction="on", - }, - [0x1F028]={ - category="so", - direction="on", - }, - [0x1F029]={ - category="so", - direction="on", - }, - [0x1F02A]={ - category="so", - direction="on", - }, - [0x1F02B]={ - category="so", - direction="on", - }, - [0x1F030]={ - category="so", - direction="on", - }, - [0x1F031]={ - category="so", - direction="on", - }, - [0x1F032]={ - category="so", - direction="on", - }, - [0x1F033]={ - category="so", - direction="on", - }, - [0x1F034]={ - category="so", - direction="on", - }, - [0x1F035]={ - category="so", - direction="on", - }, - [0x1F036]={ - category="so", - direction="on", - }, - [0x1F037]={ - category="so", - direction="on", - }, - [0x1F038]={ - category="so", - direction="on", - }, - [0x1F039]={ - category="so", - direction="on", - }, - [0x1F03A]={ - category="so", - direction="on", - }, - [0x1F03B]={ - category="so", - direction="on", - }, - [0x1F03C]={ - category="so", - direction="on", - }, - [0x1F03D]={ - category="so", - direction="on", - }, - [0x1F03E]={ - category="so", - direction="on", - }, - [0x1F03F]={ - category="so", - direction="on", - }, - [0x1F040]={ - category="so", - direction="on", - }, - [0x1F041]={ - category="so", - direction="on", - }, - [0x1F042]={ - category="so", - direction="on", - }, - [0x1F043]={ - category="so", - direction="on", - }, - [0x1F044]={ - category="so", - direction="on", - }, - [0x1F045]={ - category="so", - direction="on", - }, - [0x1F046]={ - category="so", - direction="on", - }, - [0x1F047]={ - category="so", - direction="on", - }, - [0x1F048]={ - category="so", - direction="on", - }, - [0x1F049]={ - category="so", - direction="on", - }, - [0x1F04A]={ - category="so", - direction="on", - }, - [0x1F04B]={ - category="so", - direction="on", - }, - [0x1F04C]={ - category="so", - direction="on", - }, - [0x1F04D]={ - category="so", - direction="on", - }, - [0x1F04E]={ - category="so", - direction="on", - }, - [0x1F04F]={ - category="so", - direction="on", - }, - [0x1F050]={ - category="so", - direction="on", - }, - [0x1F051]={ - category="so", - direction="on", - }, - [0x1F052]={ - category="so", - direction="on", - }, - [0x1F053]={ - category="so", - direction="on", - }, - [0x1F054]={ - category="so", - direction="on", - }, - [0x1F055]={ - category="so", - direction="on", - }, - [0x1F056]={ - category="so", - direction="on", - }, - [0x1F057]={ - category="so", - direction="on", - }, - [0x1F058]={ - category="so", - direction="on", - }, - [0x1F059]={ - category="so", - direction="on", - }, - [0x1F05A]={ - category="so", - direction="on", - }, - [0x1F05B]={ - category="so", - direction="on", - }, - [0x1F05C]={ - category="so", - direction="on", - }, - [0x1F05D]={ - category="so", - direction="on", - }, - [0x1F05E]={ - category="so", - direction="on", - }, - [0x1F05F]={ - category="so", - direction="on", - }, - [0x1F060]={ - category="so", - direction="on", - }, - [0x1F061]={ - category="so", - direction="on", - }, - [0x1F062]={ - category="so", - direction="on", - }, - [0x1F063]={ - category="so", - direction="on", - }, - [0x1F064]={ - category="so", - direction="on", - }, - [0x1F065]={ - category="so", - direction="on", - }, - [0x1F066]={ - category="so", - direction="on", - }, - [0x1F067]={ - category="so", - direction="on", - }, - [0x1F068]={ - category="so", - direction="on", - }, - [0x1F069]={ - category="so", - direction="on", - }, - [0x1F06A]={ - category="so", - direction="on", - }, - [0x1F06B]={ - category="so", - direction="on", - }, - [0x1F06C]={ - category="so", - direction="on", - }, - [0x1F06D]={ - category="so", - direction="on", - }, - [0x1F06E]={ - category="so", - direction="on", - }, - [0x1F06F]={ - category="so", - direction="on", - }, - [0x1F070]={ - category="so", - direction="on", - }, - [0x1F071]={ - category="so", - direction="on", - }, - [0x1F072]={ - category="so", - direction="on", - }, - [0x1F073]={ - category="so", - direction="on", - }, - [0x1F074]={ - category="so", - direction="on", - }, - [0x1F075]={ - category="so", - direction="on", - }, - [0x1F076]={ - category="so", - direction="on", - }, - [0x1F077]={ - category="so", - direction="on", - }, - [0x1F078]={ - category="so", - direction="on", - }, - [0x1F079]={ - category="so", - direction="on", - }, - [0x1F07A]={ - category="so", - direction="on", - }, - [0x1F07B]={ - category="so", - direction="on", - }, - [0x1F07C]={ - category="so", - direction="on", - }, - [0x1F07D]={ - category="so", - direction="on", - }, - [0x1F07E]={ - category="so", - direction="on", - }, - [0x1F07F]={ - category="so", - direction="on", - }, - [0x1F080]={ - category="so", - direction="on", - }, - [0x1F081]={ - category="so", - direction="on", - }, - [0x1F082]={ - category="so", - direction="on", - }, - [0x1F083]={ - category="so", - direction="on", - }, - [0x1F084]={ - category="so", - direction="on", - }, - [0x1F085]={ - category="so", - direction="on", - }, - [0x1F086]={ - category="so", - direction="on", - }, - [0x1F087]={ - category="so", - direction="on", - }, - [0x1F088]={ - category="so", - direction="on", - }, - [0x1F089]={ - category="so", - direction="on", - }, - [0x1F08A]={ - category="so", - direction="on", - }, - [0x1F08B]={ - category="so", - direction="on", - }, - [0x1F08C]={ - category="so", - direction="on", - }, - [0x1F08D]={ - category="so", - direction="on", - }, - [0x1F08E]={ - category="so", - direction="on", - }, - [0x1F08F]={ - category="so", - direction="on", - }, - [0x1F090]={ - category="so", - direction="on", - }, - [0x1F091]={ - category="so", - direction="on", - }, - [0x1F092]={ - category="so", - direction="on", - }, - [0x1F093]={ - category="so", - direction="on", - }, - [0x1F0A0]={ - category="so", - direction="on", - }, - [0x1F0A1]={ - category="so", - direction="on", - }, - [0x1F0A2]={ - category="so", - direction="on", - }, - [0x1F0A3]={ - category="so", - direction="on", - }, - [0x1F0A4]={ - category="so", - direction="on", - }, - [0x1F0A5]={ - category="so", - direction="on", - }, - [0x1F0A6]={ - category="so", - direction="on", - }, - [0x1F0A7]={ - category="so", - direction="on", - }, - [0x1F0A8]={ - category="so", - direction="on", - }, - [0x1F0A9]={ - category="so", - direction="on", - }, - [0x1F0AA]={ - category="so", - direction="on", - }, - [0x1F0AB]={ - category="so", - direction="on", - }, - [0x1F0AC]={ - category="so", - direction="on", - }, - [0x1F0AD]={ - category="so", - direction="on", - }, - [0x1F0AE]={ - category="so", - direction="on", - }, - [0x1F0B1]={ - category="so", - direction="on", - }, - [0x1F0B2]={ - category="so", - direction="on", - }, - [0x1F0B3]={ - category="so", - direction="on", - }, - [0x1F0B4]={ - category="so", - direction="on", - }, - [0x1F0B5]={ - category="so", - direction="on", - }, - [0x1F0B6]={ - category="so", - direction="on", - }, - [0x1F0B7]={ - category="so", - direction="on", - }, - [0x1F0B8]={ - category="so", - direction="on", - }, - [0x1F0B9]={ - category="so", - direction="on", - }, - [0x1F0BA]={ - category="so", - direction="on", - }, - [0x1F0BB]={ - category="so", - direction="on", - }, - [0x1F0BC]={ - category="so", - direction="on", - }, - [0x1F0BD]={ - category="so", - direction="on", - }, - [0x1F0BE]={ - category="so", - direction="on", - }, - [0x1F0BF]={ - category="so", - direction="on", - }, - [0x1F0C1]={ - category="so", - direction="on", - }, - [0x1F0C2]={ - category="so", - direction="on", - }, - [0x1F0C3]={ - category="so", - direction="on", - }, - [0x1F0C4]={ - category="so", - direction="on", - }, - [0x1F0C5]={ - category="so", - direction="on", - }, - [0x1F0C6]={ - category="so", - direction="on", - }, - [0x1F0C7]={ - category="so", - direction="on", - }, - [0x1F0C8]={ - category="so", - direction="on", - }, - [0x1F0C9]={ - category="so", - direction="on", - }, - [0x1F0CA]={ - category="so", - direction="on", - }, - [0x1F0CB]={ - category="so", - direction="on", - }, - [0x1F0CC]={ - category="so", - direction="on", - }, - [0x1F0CD]={ - category="so", - direction="on", - }, - [0x1F0CE]={ - category="so", - direction="on", - }, - [0x1F0CF]={ - category="so", - direction="on", - }, - [0x1F0D1]={ - category="so", - direction="on", - }, - [0x1F0D2]={ - category="so", - direction="on", - }, - [0x1F0D3]={ - category="so", - direction="on", - }, - [0x1F0D4]={ - category="so", - direction="on", - }, - [0x1F0D5]={ - category="so", - direction="on", - }, - [0x1F0D6]={ - category="so", - direction="on", - }, - [0x1F0D7]={ - category="so", - direction="on", - }, - [0x1F0D8]={ - category="so", - direction="on", - }, - [0x1F0D9]={ - category="so", - direction="on", - }, - [0x1F0DA]={ - category="so", - direction="on", - }, - [0x1F0DB]={ - category="so", - direction="on", - }, - [0x1F0DC]={ - category="so", - direction="on", - }, - [0x1F0DD]={ - category="so", - direction="on", - }, - [0x1F0DE]={ - category="so", - direction="on", - }, - [0x1F0DF]={ - category="so", - direction="on", - }, - [0x1F0E0]={ - category="so", - direction="on", - }, - [0x1F0E1]={ - category="so", - direction="on", - }, - [0x1F0E2]={ - category="so", - direction="on", - }, - [0x1F0E3]={ - category="so", - direction="on", - }, - [0x1F0E4]={ - category="so", - direction="on", - }, - [0x1F0E5]={ - category="so", - direction="on", - }, - [0x1F0E6]={ - category="so", - direction="on", - }, - [0x1F0E7]={ - category="so", - direction="on", - }, - [0x1F0E8]={ - category="so", - direction="on", - }, - [0x1F0E9]={ - category="so", - direction="on", - }, - [0x1F0EA]={ - category="so", - direction="on", - }, - [0x1F0EB]={ - category="so", - direction="on", - }, - [0x1F0EC]={ - category="so", - direction="on", - }, - [0x1F0ED]={ - category="so", - direction="on", - }, - [0x1F0EE]={ - category="so", - direction="on", - }, - [0x1F0EF]={ - category="so", - direction="on", - }, - [0x1F0F0]={ - category="so", - direction="on", - }, - [0x1F0F1]={ - category="so", - direction="on", - }, - [0x1F0F2]={ - category="so", - direction="on", - }, - [0x1F0F3]={ - category="so", - direction="on", - }, - [0x1F0F4]={ - category="so", - direction="on", - }, - [0x1F0F5]={ - category="so", - direction="on", - }, - [0x1F100]={ - category="no", - direction="en", - }, - [0x1F101]={ - category="no", - direction="en", - }, - [0x1F102]={ - category="no", - direction="en", - }, - [0x1F103]={ - category="no", - direction="en", - }, - [0x1F104]={ - category="no", - direction="en", - }, - [0x1F105]={ - category="no", - direction="en", - }, - [0x1F106]={ - category="no", - direction="en", - }, - [0x1F107]={ - category="no", - direction="en", - }, - [0x1F108]={ - category="no", - direction="en", - }, - [0x1F109]={ - category="no", - direction="en", - }, - [0x1F10A]={ - category="no", - direction="en", - }, - [0x1F10B]={ - category="no", - direction="on", - }, - [0x1F10C]={ - category="no", - direction="on", - }, - [0x1F110]={ - category="so", - direction="l", - }, - [0x1F111]={ - category="so", - direction="l", - }, - [0x1F112]={ - category="so", - direction="l", - }, - [0x1F113]={ - category="so", - direction="l", - }, - [0x1F114]={ - category="so", - direction="l", - }, - [0x1F115]={ - category="so", - direction="l", - }, - [0x1F116]={ - category="so", - direction="l", - }, - [0x1F117]={ - category="so", - direction="l", - }, - [0x1F118]={ - category="so", - direction="l", - }, - [0x1F119]={ - category="so", - direction="l", - }, - [0x1F11A]={ - category="so", - direction="l", - }, - [0x1F11B]={ - category="so", - direction="l", - }, - [0x1F11C]={ - category="so", - direction="l", - }, - [0x1F11D]={ - category="so", - direction="l", - }, - [0x1F11E]={ - category="so", - direction="l", - }, - [0x1F11F]={ - category="so", - direction="l", - }, - [0x1F120]={ - category="so", - direction="l", - }, - [0x1F121]={ - category="so", - direction="l", - }, - [0x1F122]={ - category="so", - direction="l", - }, - [0x1F123]={ - category="so", - direction="l", - }, - [0x1F124]={ - category="so", - direction="l", - }, - [0x1F125]={ - category="so", - direction="l", - }, - [0x1F126]={ - category="so", - direction="l", - }, - [0x1F127]={ - category="so", - direction="l", - }, - [0x1F128]={ - category="so", - direction="l", - }, - [0x1F129]={ - category="so", - direction="l", - }, - [0x1F12A]={ - category="so", - direction="l", - }, - [0x1F12B]={ - category="so", - direction="l", - }, - [0x1F12C]={ - category="so", - direction="l", - }, - [0x1F12D]={ - category="so", - direction="l", - }, - [0x1F12E]={ - category="so", - direction="l", - }, - [0x1F130]={ - category="so", - direction="l", - }, - [0x1F131]={ - category="so", - direction="l", - }, - [0x1F132]={ - category="so", - direction="l", - }, - [0x1F133]={ - category="so", - direction="l", - }, - [0x1F134]={ - category="so", - direction="l", - }, - [0x1F135]={ - category="so", - direction="l", - }, - [0x1F136]={ - category="so", - direction="l", - }, - [0x1F137]={ - category="so", - direction="l", - }, - [0x1F138]={ - category="so", - direction="l", - }, - [0x1F139]={ - category="so", - direction="l", - }, - [0x1F13A]={ - category="so", - direction="l", - }, - [0x1F13B]={ - category="so", - direction="l", - }, - [0x1F13C]={ - category="so", - direction="l", - }, - [0x1F13D]={ - category="so", - direction="l", - }, - [0x1F13E]={ - category="so", - direction="l", - }, - [0x1F13F]={ - category="so", - direction="l", - }, - [0x1F140]={ - category="so", - direction="l", - }, - [0x1F141]={ - category="so", - direction="l", - }, - [0x1F142]={ - category="so", - direction="l", - }, - [0x1F143]={ - category="so", - direction="l", - }, - [0x1F144]={ - category="so", - direction="l", - }, - [0x1F145]={ - category="so", - direction="l", - }, - [0x1F146]={ - category="so", - direction="l", - }, - [0x1F147]={ - category="so", - direction="l", - }, - [0x1F148]={ - category="so", - direction="l", - }, - [0x1F149]={ - category="so", - direction="l", - }, - [0x1F14A]={ - category="so", - direction="l", - }, - [0x1F14B]={ - category="so", - direction="l", - }, - [0x1F14C]={ - category="so", - direction="l", - }, - [0x1F14D]={ - category="so", - direction="l", - }, - [0x1F14E]={ - category="so", - direction="l", - }, - [0x1F14F]={ - category="so", - direction="l", - }, - [0x1F150]={ - category="so", - direction="l", - }, - [0x1F151]={ - category="so", - direction="l", - }, - [0x1F152]={ - category="so", - direction="l", - }, - [0x1F153]={ - category="so", - direction="l", - }, - [0x1F154]={ - category="so", - direction="l", - }, - [0x1F155]={ - category="so", - direction="l", - }, - [0x1F156]={ - category="so", - direction="l", - }, - [0x1F157]={ - category="so", - direction="l", - }, - [0x1F158]={ - category="so", - direction="l", - }, - [0x1F159]={ - category="so", - direction="l", - }, - [0x1F15A]={ - category="so", - direction="l", - }, - [0x1F15B]={ - category="so", - direction="l", - }, - [0x1F15C]={ - category="so", - direction="l", - }, - [0x1F15D]={ - category="so", - direction="l", - }, - [0x1F15E]={ - category="so", - direction="l", - }, - [0x1F15F]={ - category="so", - direction="l", - }, - [0x1F160]={ - category="so", - direction="l", - }, - [0x1F161]={ - category="so", - direction="l", - }, - [0x1F162]={ - category="so", - direction="l", - }, - [0x1F163]={ - category="so", - direction="l", - }, - [0x1F164]={ - category="so", - direction="l", - }, - [0x1F165]={ - category="so", - direction="l", - }, - [0x1F166]={ - category="so", - direction="l", - }, - [0x1F167]={ - category="so", - direction="l", - }, - [0x1F168]={ - category="so", - direction="l", - }, - [0x1F169]={ - category="so", - direction="l", - }, - [0x1F16A]={ - category="so", - direction="on", - }, - [0x1F16B]={ - category="so", - direction="on", - }, - [0x1F170]={ - category="so", - direction="l", - }, - [0x1F171]={ - category="so", - direction="l", - }, - [0x1F172]={ - category="so", - direction="l", - }, - [0x1F173]={ - category="so", - direction="l", - }, - [0x1F174]={ - category="so", - direction="l", - }, - [0x1F175]={ - category="so", - direction="l", - }, - [0x1F176]={ - category="so", - direction="l", - }, - [0x1F177]={ - category="so", - direction="l", - }, - [0x1F178]={ - category="so", - direction="l", - }, - [0x1F179]={ - category="so", - direction="l", - }, - [0x1F17A]={ - category="so", - direction="l", - }, - [0x1F17B]={ - category="so", - direction="l", - }, - [0x1F17C]={ - category="so", - direction="l", - }, - [0x1F17D]={ - category="so", - direction="l", - }, - [0x1F17E]={ - category="so", - direction="l", - }, - [0x1F17F]={ - category="so", - direction="l", - }, - [0x1F180]={ - category="so", - direction="l", - }, - [0x1F181]={ - category="so", - direction="l", - }, - [0x1F182]={ - category="so", - direction="l", - }, - [0x1F183]={ - category="so", - direction="l", - }, - [0x1F184]={ - category="so", - direction="l", - }, - [0x1F185]={ - category="so", - direction="l", - }, - [0x1F186]={ - category="so", - direction="l", - }, - [0x1F187]={ - category="so", - direction="l", - }, - [0x1F188]={ - category="so", - direction="l", - }, - [0x1F189]={ - category="so", - direction="l", - }, - [0x1F18A]={ - category="so", - direction="l", - }, - [0x1F18B]={ - category="so", - direction="l", - }, - [0x1F18C]={ - category="so", - direction="l", - }, - [0x1F18D]={ - category="so", - direction="l", - }, - [0x1F18E]={ - category="so", - direction="l", - }, - [0x1F18F]={ - category="so", - direction="l", - }, - [0x1F190]={ - category="so", - direction="l", - }, - [0x1F191]={ - category="so", - direction="l", - }, - [0x1F192]={ - category="so", - direction="l", - }, - [0x1F193]={ - category="so", - direction="l", - }, - [0x1F194]={ - category="so", - direction="l", - }, - [0x1F195]={ - category="so", - direction="l", - }, - [0x1F196]={ - category="so", - direction="l", - }, - [0x1F197]={ - category="so", - direction="l", - }, - [0x1F198]={ - category="so", - direction="l", - }, - [0x1F199]={ - category="so", - direction="l", - }, - [0x1F19A]={ - category="so", - direction="l", - }, - [0x1F19B]={ - category="so", - direction="l", - }, - [0x1F19C]={ - category="so", - direction="l", - }, - [0x1F19D]={ - category="so", - direction="l", - }, - [0x1F19E]={ - category="so", - direction="l", - }, - [0x1F19F]={ - category="so", - direction="l", - }, - [0x1F1A0]={ - category="so", - direction="l", - }, - [0x1F1A1]={ - category="so", - direction="l", - }, - [0x1F1A2]={ - category="so", - direction="l", - }, - [0x1F1A3]={ - category="so", - direction="l", - }, - [0x1F1A4]={ - category="so", - direction="l", - }, - [0x1F1A5]={ - category="so", - direction="l", - }, - [0x1F1A6]={ - category="so", - direction="l", - }, - [0x1F1A7]={ - category="so", - direction="l", - }, - [0x1F1A8]={ - category="so", - direction="l", - }, - [0x1F1A9]={ - category="so", - direction="l", - }, - [0x1F1AA]={ - category="so", - direction="l", - }, - [0x1F1AB]={ - category="so", - direction="l", - }, - [0x1F1AC]={ - category="so", - direction="l", - }, - [0x1F1E6]={ - category="so", - direction="l", - }, - [0x1F1E7]={ - category="so", - direction="l", - }, - [0x1F1E8]={ - category="so", - direction="l", - }, - [0x1F1E9]={ - category="so", - direction="l", - }, - [0x1F1EA]={ - category="so", - direction="l", - }, - [0x1F1EB]={ - category="so", - direction="l", - }, - [0x1F1EC]={ - category="so", - direction="l", - }, - [0x1F1ED]={ - category="so", - direction="l", - }, - [0x1F1EE]={ - category="so", - direction="l", - }, - [0x1F1EF]={ - category="so", - direction="l", - }, - [0x1F1F0]={ - category="so", - direction="l", - }, - [0x1F1F1]={ - category="so", - direction="l", - }, - [0x1F1F2]={ - category="so", - direction="l", - }, - [0x1F1F3]={ - category="so", - direction="l", - }, - [0x1F1F4]={ - category="so", - direction="l", - }, - [0x1F1F5]={ - category="so", - direction="l", - }, - [0x1F1F6]={ - category="so", - direction="l", - }, - [0x1F1F7]={ - category="so", - direction="l", - }, - [0x1F1F8]={ - category="so", - direction="l", - }, - [0x1F1F9]={ - category="so", - direction="l", - }, - [0x1F1FA]={ - category="so", - direction="l", - }, - [0x1F1FB]={ - category="so", - direction="l", - }, - [0x1F1FC]={ - category="so", - direction="l", - }, - [0x1F1FD]={ - category="so", - direction="l", - }, - [0x1F1FE]={ - category="so", - direction="l", - }, - [0x1F1FF]={ - category="so", - direction="l", - }, - [0x1F200]={ - category="so", - direction="l", - }, - [0x1F201]={ - category="so", - direction="l", - }, - [0x1F202]={ - category="so", - direction="l", - }, - [0x1F210]={ - category="so", - direction="l", - }, - [0x1F211]={ - category="so", - direction="l", - }, - [0x1F212]={ - category="so", - direction="l", - }, - [0x1F213]={ - category="so", - direction="l", - }, - [0x1F214]={ - category="so", - direction="l", - }, - [0x1F215]={ - category="so", - direction="l", - }, - [0x1F216]={ - category="so", - direction="l", - }, - [0x1F217]={ - category="so", - direction="l", - }, - [0x1F218]={ - category="so", - direction="l", - }, - [0x1F219]={ - category="so", - direction="l", - }, - [0x1F21A]={ - category="so", - direction="l", - }, - [0x1F21B]={ - category="so", - direction="l", - }, - [0x1F21C]={ - category="so", - direction="l", - }, - [0x1F21D]={ - category="so", - direction="l", - }, - [0x1F21E]={ - category="so", - direction="l", - }, - [0x1F21F]={ - category="so", - direction="l", - }, - [0x1F220]={ - category="so", - direction="l", - }, - [0x1F221]={ - category="so", - direction="l", - }, - [0x1F222]={ - category="so", - direction="l", - }, - [0x1F223]={ - category="so", - direction="l", - }, - [0x1F224]={ - category="so", - direction="l", - }, - [0x1F225]={ - category="so", - direction="l", - }, - [0x1F226]={ - category="so", - direction="l", - }, - [0x1F227]={ - category="so", - direction="l", - }, - [0x1F228]={ - category="so", - direction="l", - }, - [0x1F229]={ - category="so", - direction="l", - }, - [0x1F22A]={ - category="so", - direction="l", - }, - [0x1F22B]={ - category="so", - direction="l", - }, - [0x1F22C]={ - category="so", - direction="l", - }, - [0x1F22D]={ - category="so", - direction="l", - }, - [0x1F22E]={ - category="so", - direction="l", - }, - [0x1F22F]={ - category="so", - direction="l", - }, - [0x1F230]={ - category="so", - direction="l", - }, - [0x1F231]={ - category="so", - direction="l", - }, - [0x1F232]={ - category="so", - direction="l", - }, - [0x1F233]={ - category="so", - direction="l", - }, - [0x1F234]={ - category="so", - direction="l", - }, - [0x1F235]={ - category="so", - direction="l", - }, - [0x1F236]={ - category="so", - direction="l", - }, - [0x1F237]={ - category="so", - direction="l", - }, - [0x1F238]={ - category="so", - direction="l", - }, - [0x1F239]={ - category="so", - direction="l", - }, - [0x1F23A]={ - category="so", - direction="l", - }, - [0x1F23B]={ - category="so", - direction="l", - }, - [0x1F240]={ - category="so", - direction="l", - }, - [0x1F241]={ - category="so", - direction="l", - }, - [0x1F242]={ - category="so", - direction="l", - }, - [0x1F243]={ - category="so", - direction="l", - }, - [0x1F244]={ - category="so", - direction="l", - }, - [0x1F245]={ - category="so", - direction="l", - }, - [0x1F246]={ - category="so", - direction="l", - }, - [0x1F247]={ - category="so", - direction="l", - }, - [0x1F248]={ - category="so", - direction="l", - }, - [0x1F250]={ - category="so", - direction="l", - }, - [0x1F251]={ - category="so", - direction="l", - }, - [0x1F300]={ - category="so", - direction="on", - }, - [0x1F301]={ - category="so", - direction="on", - }, - [0x1F302]={ - category="so", - direction="on", - }, - [0x1F303]={ - category="so", - direction="on", - }, - [0x1F304]={ - category="so", - direction="on", - }, - [0x1F305]={ - category="so", - direction="on", - }, - [0x1F306]={ - category="so", - direction="on", - }, - [0x1F307]={ - category="so", - direction="on", - }, - [0x1F308]={ - category="so", - direction="on", - }, - [0x1F309]={ - category="so", - direction="on", - }, - [0x1F30A]={ - category="so", - direction="on", - }, - [0x1F30B]={ - category="so", - direction="on", - }, - [0x1F30C]={ - category="so", - direction="on", - }, - [0x1F30D]={ - category="so", - direction="on", - }, - [0x1F30E]={ - category="so", - direction="on", - }, - [0x1F30F]={ - category="so", - direction="on", - }, - [0x1F310]={ - category="so", - direction="on", - }, - [0x1F311]={ - category="so", - direction="on", - }, - [0x1F312]={ - category="so", - direction="on", - }, - [0x1F313]={ - category="so", - direction="on", - }, - [0x1F314]={ - category="so", - direction="on", - }, - [0x1F315]={ - category="so", - direction="on", - }, - [0x1F316]={ - category="so", - direction="on", - }, - [0x1F317]={ - category="so", - direction="on", - }, - [0x1F318]={ - category="so", - direction="on", - }, - [0x1F319]={ - category="so", - direction="on", - }, - [0x1F31A]={ - category="so", - direction="on", - }, - [0x1F31B]={ - category="so", - direction="on", - }, - [0x1F31C]={ - category="so", - direction="on", - }, - [0x1F31D]={ - category="so", - direction="on", - }, - [0x1F31E]={ - category="so", - direction="on", - }, - [0x1F31F]={ - category="so", - direction="on", - }, - [0x1F320]={ - category="so", - direction="on", - }, - [0x1F321]={ - category="so", - direction="on", - }, - [0x1F322]={ - category="so", - direction="on", - }, - [0x1F323]={ - category="so", - direction="on", - }, - [0x1F324]={ - category="so", - direction="on", - }, - [0x1F325]={ - category="so", - direction="on", - }, - [0x1F326]={ - category="so", - direction="on", - }, - [0x1F327]={ - category="so", - direction="on", - }, - [0x1F328]={ - category="so", - direction="on", - }, - [0x1F329]={ - category="so", - direction="on", - }, - [0x1F32A]={ - category="so", - direction="on", - }, - [0x1F32B]={ - category="so", - direction="on", - }, - [0x1F32C]={ - category="so", - direction="on", - }, - [0x1F32D]={ - category="so", - direction="on", - }, - [0x1F32E]={ - category="so", - direction="on", - }, - [0x1F32F]={ - category="so", - direction="on", - }, - [0x1F330]={ - category="so", - direction="on", - }, - [0x1F331]={ - category="so", - direction="on", - }, - [0x1F332]={ - category="so", - direction="on", - }, - [0x1F333]={ - category="so", - direction="on", - }, - [0x1F334]={ - category="so", - direction="on", - }, - [0x1F335]={ - category="so", - direction="on", - }, - [0x1F336]={ - category="so", - direction="on", - }, - [0x1F337]={ - category="so", - direction="on", - }, - [0x1F338]={ - category="so", - direction="on", - }, - [0x1F339]={ - category="so", - direction="on", - }, - [0x1F33A]={ - category="so", - direction="on", - }, - [0x1F33B]={ - category="so", - direction="on", - }, - [0x1F33C]={ - category="so", - direction="on", - }, - [0x1F33D]={ - category="so", - direction="on", - }, - [0x1F33E]={ - category="so", - direction="on", - }, - [0x1F33F]={ - category="so", - direction="on", - }, - [0x1F340]={ - category="so", - direction="on", - }, - [0x1F341]={ - category="so", - direction="on", - }, - [0x1F342]={ - category="so", - direction="on", - }, - [0x1F343]={ - category="so", - direction="on", - }, - [0x1F344]={ - category="so", - direction="on", - }, - [0x1F345]={ - category="so", - direction="on", - }, - [0x1F346]={ - category="so", - direction="on", - }, - [0x1F347]={ - category="so", - direction="on", - }, - [0x1F348]={ - category="so", - direction="on", - }, - [0x1F349]={ - category="so", - direction="on", - }, - [0x1F34A]={ - category="so", - direction="on", - }, - [0x1F34B]={ - category="so", - direction="on", - }, - [0x1F34C]={ - category="so", - direction="on", - }, - [0x1F34D]={ - category="so", - direction="on", - }, - [0x1F34E]={ - category="so", - direction="on", - }, - [0x1F34F]={ - category="so", - direction="on", - }, - [0x1F350]={ - category="so", - direction="on", - }, - [0x1F351]={ - category="so", - direction="on", - }, - [0x1F352]={ - category="so", - direction="on", - }, - [0x1F353]={ - category="so", - direction="on", - }, - [0x1F354]={ - category="so", - direction="on", - }, - [0x1F355]={ - category="so", - direction="on", - }, - [0x1F356]={ - category="so", - direction="on", - }, - [0x1F357]={ - category="so", - direction="on", - }, - [0x1F358]={ - category="so", - direction="on", - }, - [0x1F359]={ - category="so", - direction="on", - }, - [0x1F35A]={ - category="so", - direction="on", - }, - [0x1F35B]={ - category="so", - direction="on", - }, - [0x1F35C]={ - category="so", - direction="on", - }, - [0x1F35D]={ - category="so", - direction="on", - }, - [0x1F35E]={ - category="so", - direction="on", - }, - [0x1F35F]={ - category="so", - direction="on", - }, - [0x1F360]={ - category="so", - direction="on", - }, - [0x1F361]={ - category="so", - direction="on", - }, - [0x1F362]={ - category="so", - direction="on", - }, - [0x1F363]={ - category="so", - direction="on", - }, - [0x1F364]={ - category="so", - direction="on", - }, - [0x1F365]={ - category="so", - direction="on", - }, - [0x1F366]={ - category="so", - direction="on", - }, - [0x1F367]={ - category="so", - direction="on", - }, - [0x1F368]={ - category="so", - direction="on", - }, - [0x1F369]={ - category="so", - direction="on", - }, - [0x1F36A]={ - category="so", - direction="on", - }, - [0x1F36B]={ - category="so", - direction="on", - }, - [0x1F36C]={ - category="so", - direction="on", - }, - [0x1F36D]={ - category="so", - direction="on", - }, - [0x1F36E]={ - category="so", - direction="on", - }, - [0x1F36F]={ - category="so", - direction="on", - }, - [0x1F370]={ - category="so", - direction="on", - }, - [0x1F371]={ - category="so", - direction="on", - }, - [0x1F372]={ - category="so", - direction="on", - }, - [0x1F373]={ - category="so", - direction="on", - }, - [0x1F374]={ - category="so", - direction="on", - }, - [0x1F375]={ - category="so", - direction="on", - }, - [0x1F376]={ - category="so", - direction="on", - }, - [0x1F377]={ - category="so", - direction="on", - }, - [0x1F378]={ - category="so", - direction="on", - }, - [0x1F379]={ - category="so", - direction="on", - }, - [0x1F37A]={ - category="so", - direction="on", - }, - [0x1F37B]={ - category="so", - direction="on", - }, - [0x1F37C]={ - category="so", - direction="on", - }, - [0x1F37D]={ - category="so", - direction="on", - }, - [0x1F37E]={ - category="so", - direction="on", - }, - [0x1F37F]={ - category="so", - direction="on", - }, - [0x1F380]={ - category="so", - direction="on", - }, - [0x1F381]={ - category="so", - direction="on", - }, - [0x1F382]={ - category="so", - direction="on", - }, - [0x1F383]={ - category="so", - direction="on", - }, - [0x1F384]={ - category="so", - direction="on", - }, - [0x1F385]={ - category="so", - direction="on", - }, - [0x1F386]={ - category="so", - direction="on", - }, - [0x1F387]={ - category="so", - direction="on", - }, - [0x1F388]={ - category="so", - direction="on", - }, - [0x1F389]={ - category="so", - direction="on", - }, - [0x1F38A]={ - category="so", - direction="on", - }, - [0x1F38B]={ - category="so", - direction="on", - }, - [0x1F38C]={ - category="so", - direction="on", - }, - [0x1F38D]={ - category="so", - direction="on", - }, - [0x1F38E]={ - category="so", - direction="on", - }, - [0x1F38F]={ - category="so", - direction="on", - }, - [0x1F390]={ - category="so", - direction="on", - }, - [0x1F391]={ - category="so", - direction="on", - }, - [0x1F392]={ - category="so", - direction="on", - }, - [0x1F393]={ - category="so", - direction="on", - }, - [0x1F394]={ - category="so", - direction="on", - }, - [0x1F395]={ - category="so", - direction="on", - }, - [0x1F396]={ - category="so", - direction="on", - }, - [0x1F397]={ - category="so", - direction="on", - }, - [0x1F398]={ - category="so", - direction="on", - }, - [0x1F399]={ - category="so", - direction="on", - }, - [0x1F39A]={ - category="so", - direction="on", - }, - [0x1F39B]={ - category="so", - direction="on", - }, - [0x1F39C]={ - category="so", - direction="on", - }, - [0x1F39D]={ - category="so", - direction="on", - }, - [0x1F39E]={ - category="so", - direction="on", - }, - [0x1F39F]={ - category="so", - direction="on", - }, - [0x1F3A0]={ - category="so", - direction="on", - }, - [0x1F3A1]={ - category="so", - direction="on", - }, - [0x1F3A2]={ - category="so", - direction="on", - }, - [0x1F3A3]={ - category="so", - direction="on", - }, - [0x1F3A4]={ - category="so", - direction="on", - }, - [0x1F3A5]={ - category="so", - direction="on", - }, - [0x1F3A6]={ - category="so", - direction="on", - }, - [0x1F3A7]={ - category="so", - direction="on", - }, - [0x1F3A8]={ - category="so", - direction="on", - }, - [0x1F3A9]={ - category="so", - direction="on", - }, - [0x1F3AA]={ - category="so", - direction="on", - }, - [0x1F3AB]={ - category="so", - direction="on", - }, - [0x1F3AC]={ - category="so", - direction="on", - }, - [0x1F3AD]={ - category="so", - direction="on", - }, - [0x1F3AE]={ - category="so", - direction="on", - }, - [0x1F3AF]={ - category="so", - direction="on", - }, - [0x1F3B0]={ - category="so", - direction="on", - }, - [0x1F3B1]={ - category="so", - direction="on", - }, - [0x1F3B2]={ - category="so", - direction="on", - }, - [0x1F3B3]={ - category="so", - direction="on", - }, - [0x1F3B4]={ - category="so", - direction="on", - }, - [0x1F3B5]={ - category="so", - direction="on", - }, - [0x1F3B6]={ - category="so", - direction="on", - }, - [0x1F3B7]={ - category="so", - direction="on", - }, - [0x1F3B8]={ - category="so", - direction="on", - }, - [0x1F3B9]={ - category="so", - direction="on", - }, - [0x1F3BA]={ - category="so", - direction="on", - }, - [0x1F3BB]={ - category="so", - direction="on", - }, - [0x1F3BC]={ - category="so", - direction="on", - }, - [0x1F3BD]={ - category="so", - direction="on", - }, - [0x1F3BE]={ - category="so", - direction="on", - }, - [0x1F3BF]={ - category="so", - direction="on", - }, - [0x1F3C0]={ - category="so", - direction="on", - }, - [0x1F3C1]={ - category="so", - direction="on", - }, - [0x1F3C2]={ - category="so", - direction="on", - }, - [0x1F3C3]={ - category="so", - direction="on", - }, - [0x1F3C4]={ - category="so", - direction="on", - }, - [0x1F3C5]={ - category="so", - direction="on", - }, - [0x1F3C6]={ - category="so", - direction="on", - }, - [0x1F3C7]={ - category="so", - direction="on", - }, - [0x1F3C8]={ - category="so", - direction="on", - }, - [0x1F3C9]={ - category="so", - direction="on", - }, - [0x1F3CA]={ - category="so", - direction="on", - }, - [0x1F3CB]={ - category="so", - direction="on", - }, - [0x1F3CC]={ - category="so", - direction="on", - }, - [0x1F3CD]={ - category="so", - direction="on", - }, - [0x1F3CE]={ - category="so", - direction="on", - }, - [0x1F3CF]={ - category="so", - direction="on", - }, - [0x1F3D0]={ - category="so", - direction="on", - }, - [0x1F3D1]={ - category="so", - direction="on", - }, - [0x1F3D2]={ - category="so", - direction="on", - }, - [0x1F3D3]={ - category="so", - direction="on", - }, - [0x1F3D4]={ - category="so", - direction="on", - }, - [0x1F3D5]={ - category="so", - direction="on", - }, - [0x1F3D6]={ - category="so", - direction="on", - }, - [0x1F3D7]={ - category="so", - direction="on", - }, - [0x1F3D8]={ - category="so", - direction="on", - }, - [0x1F3D9]={ - category="so", - direction="on", - }, - [0x1F3DA]={ - category="so", - direction="on", - }, - [0x1F3DB]={ - category="so", - direction="on", - }, - [0x1F3DC]={ - category="so", - direction="on", - }, - [0x1F3DD]={ - category="so", - direction="on", - }, - [0x1F3DE]={ - category="so", - direction="on", - }, - [0x1F3DF]={ - category="so", - direction="on", - }, - [0x1F3E0]={ - category="so", - direction="on", - }, - [0x1F3E1]={ - category="so", - direction="on", - }, - [0x1F3E2]={ - category="so", - direction="on", - }, - [0x1F3E3]={ - category="so", - direction="on", - }, - [0x1F3E4]={ - category="so", - direction="on", - }, - [0x1F3E5]={ - category="so", - direction="on", - }, - [0x1F3E6]={ - category="so", - direction="on", - }, - [0x1F3E7]={ - category="so", - direction="on", - }, - [0x1F3E8]={ - category="so", - direction="on", - }, - [0x1F3E9]={ - category="so", - direction="on", - }, - [0x1F3EA]={ - category="so", - direction="on", - }, - [0x1F3EB]={ - category="so", - direction="on", - }, - [0x1F3EC]={ - category="so", - direction="on", - }, - [0x1F3ED]={ - category="so", - direction="on", - }, - [0x1F3EE]={ - category="so", - direction="on", - }, - [0x1F3EF]={ - category="so", - direction="on", - }, - [0x1F3F0]={ - category="so", - direction="on", - }, - [0x1F3F1]={ - category="so", - direction="on", - }, - [0x1F3F2]={ - category="so", - direction="on", - }, - [0x1F3F3]={ - category="so", - direction="on", - }, - [0x1F3F4]={ - category="so", - direction="on", - }, - [0x1F3F5]={ - category="so", - direction="on", - }, - [0x1F3F6]={ - category="so", - direction="on", - }, - [0x1F3F7]={ - category="so", - direction="on", - }, - [0x1F3F8]={ - category="so", - direction="on", - }, - [0x1F3F9]={ - category="so", - direction="on", - }, - [0x1F3FA]={ - category="so", - direction="on", - }, - [0x1F3FB]={ - category="sk", - direction="on", - }, - [0x1F3FC]={ - category="sk", - direction="on", - }, - [0x1F3FD]={ - category="sk", - direction="on", - }, - [0x1F3FE]={ - category="sk", - direction="on", - }, - [0x1F3FF]={ - category="sk", - direction="on", - }, - [0x1F400]={ - category="so", - direction="on", - }, - [0x1F401]={ - category="so", - direction="on", - }, - [0x1F402]={ - category="so", - direction="on", - }, - [0x1F403]={ - category="so", - direction="on", - }, - [0x1F404]={ - category="so", - direction="on", - }, - [0x1F405]={ - category="so", - direction="on", - }, - [0x1F406]={ - category="so", - direction="on", - }, - [0x1F407]={ - category="so", - direction="on", - }, - [0x1F408]={ - category="so", - direction="on", - }, - [0x1F409]={ - category="so", - direction="on", - }, - [0x1F40A]={ - category="so", - direction="on", - }, - [0x1F40B]={ - category="so", - direction="on", - }, - [0x1F40C]={ - category="so", - direction="on", - }, - [0x1F40D]={ - category="so", - direction="on", - }, - [0x1F40E]={ - category="so", - direction="on", - }, - [0x1F40F]={ - category="so", - direction="on", - }, - [0x1F410]={ - category="so", - direction="on", - }, - [0x1F411]={ - category="so", - direction="on", - }, - [0x1F412]={ - category="so", - direction="on", - }, - [0x1F413]={ - category="so", - direction="on", - }, - [0x1F414]={ - category="so", - direction="on", - }, - [0x1F415]={ - category="so", - direction="on", - }, - [0x1F416]={ - category="so", - direction="on", - }, - [0x1F417]={ - category="so", - direction="on", - }, - [0x1F418]={ - category="so", - direction="on", - }, - [0x1F419]={ - category="so", - direction="on", - }, - [0x1F41A]={ - category="so", - direction="on", - }, - [0x1F41B]={ - category="so", - direction="on", - }, - [0x1F41C]={ - category="so", - direction="on", - }, - [0x1F41D]={ - category="so", - direction="on", - }, - [0x1F41E]={ - category="so", - direction="on", - }, - [0x1F41F]={ - category="so", - direction="on", - }, - [0x1F420]={ - category="so", - direction="on", - }, - [0x1F421]={ - category="so", - direction="on", - }, - [0x1F422]={ - category="so", - direction="on", - }, - [0x1F423]={ - category="so", - direction="on", - }, - [0x1F424]={ - category="so", - direction="on", - }, - [0x1F425]={ - category="so", - direction="on", - }, - [0x1F426]={ - category="so", - direction="on", - }, - [0x1F427]={ - category="so", - direction="on", - }, - [0x1F428]={ - category="so", - direction="on", - }, - [0x1F429]={ - category="so", - direction="on", - }, - [0x1F42A]={ - category="so", - direction="on", - }, - [0x1F42B]={ - category="so", - direction="on", - }, - [0x1F42C]={ - category="so", - direction="on", - }, - [0x1F42D]={ - category="so", - direction="on", - }, - [0x1F42E]={ - category="so", - direction="on", - }, - [0x1F42F]={ - category="so", - direction="on", - }, - [0x1F430]={ - category="so", - direction="on", - }, - [0x1F431]={ - category="so", - direction="on", - }, - [0x1F432]={ - category="so", - direction="on", - }, - [0x1F433]={ - category="so", - direction="on", - }, - [0x1F434]={ - category="so", - direction="on", - }, - [0x1F435]={ - category="so", - direction="on", - }, - [0x1F436]={ - category="so", - direction="on", - }, - [0x1F437]={ - category="so", - direction="on", - }, - [0x1F438]={ - category="so", - direction="on", - }, - [0x1F439]={ - category="so", - direction="on", - }, - [0x1F43A]={ - category="so", - direction="on", - }, - [0x1F43B]={ - category="so", - direction="on", - }, - [0x1F43C]={ - category="so", - direction="on", - }, - [0x1F43D]={ - category="so", - direction="on", - }, - [0x1F43E]={ - category="so", - direction="on", - }, - [0x1F43F]={ - category="so", - direction="on", - }, - [0x1F440]={ - category="so", - direction="on", - }, - [0x1F441]={ - category="so", - direction="on", - }, - [0x1F442]={ - category="so", - direction="on", - }, - [0x1F443]={ - category="so", - direction="on", - }, - [0x1F444]={ - category="so", - direction="on", - }, - [0x1F445]={ - category="so", - direction="on", - }, - [0x1F446]={ - category="so", - direction="on", - }, - [0x1F447]={ - category="so", - direction="on", - }, - [0x1F448]={ - category="so", - direction="on", - }, - [0x1F449]={ - category="so", - direction="on", - }, - [0x1F44A]={ - category="so", - direction="on", - }, - [0x1F44B]={ - category="so", - direction="on", - }, - [0x1F44C]={ - category="so", - direction="on", - }, - [0x1F44D]={ - category="so", - direction="on", - }, - [0x1F44E]={ - category="so", - direction="on", - }, - [0x1F44F]={ - category="so", - direction="on", - }, - [0x1F450]={ - category="so", - direction="on", - }, - [0x1F451]={ - category="so", - direction="on", - }, - [0x1F452]={ - category="so", - direction="on", - }, - [0x1F453]={ - category="so", - direction="on", - }, - [0x1F454]={ - category="so", - direction="on", - }, - [0x1F455]={ - category="so", - direction="on", - }, - [0x1F456]={ - category="so", - direction="on", - }, - [0x1F457]={ - category="so", - direction="on", - }, - [0x1F458]={ - category="so", - direction="on", - }, - [0x1F459]={ - category="so", - direction="on", - }, - [0x1F45A]={ - category="so", - direction="on", - }, - [0x1F45B]={ - category="so", - direction="on", - }, - [0x1F45C]={ - category="so", - direction="on", - }, - [0x1F45D]={ - category="so", - direction="on", - }, - [0x1F45E]={ - category="so", - direction="on", - }, - [0x1F45F]={ - category="so", - direction="on", - }, - [0x1F460]={ - category="so", - direction="on", - }, - [0x1F461]={ - category="so", - direction="on", - }, - [0x1F462]={ - category="so", - direction="on", - }, - [0x1F463]={ - category="so", - direction="on", - }, - [0x1F464]={ - category="so", - direction="on", - }, - [0x1F465]={ - category="so", - direction="on", - }, - [0x1F466]={ - category="so", - direction="on", - }, - [0x1F467]={ - category="so", - direction="on", - }, - [0x1F468]={ - category="so", - direction="on", - }, - [0x1F469]={ - category="so", - direction="on", - }, - [0x1F46A]={ - category="so", - direction="on", - }, - [0x1F46B]={ - category="so", - direction="on", - }, - [0x1F46C]={ - category="so", - direction="on", - }, - [0x1F46D]={ - category="so", - direction="on", - }, - [0x1F46E]={ - category="so", - direction="on", - }, - [0x1F46F]={ - category="so", - direction="on", - }, - [0x1F470]={ - category="so", - direction="on", - }, - [0x1F471]={ - category="so", - direction="on", - }, - [0x1F472]={ - category="so", - direction="on", - }, - [0x1F473]={ - category="so", - direction="on", - }, - [0x1F474]={ - category="so", - direction="on", - }, - [0x1F475]={ - category="so", - direction="on", - }, - [0x1F476]={ - category="so", - direction="on", - }, - [0x1F477]={ - category="so", - direction="on", - }, - [0x1F478]={ - category="so", - direction="on", - }, - [0x1F479]={ - category="so", - direction="on", - }, - [0x1F47A]={ - category="so", - direction="on", - }, - [0x1F47B]={ - category="so", - direction="on", - }, - [0x1F47C]={ - category="so", - direction="on", - }, - [0x1F47D]={ - category="so", - direction="on", - }, - [0x1F47E]={ - category="so", - direction="on", - }, - [0x1F47F]={ - category="so", - direction="on", - }, - [0x1F480]={ - category="so", - direction="on", - }, - [0x1F481]={ - category="so", - direction="on", - }, - [0x1F482]={ - category="so", - direction="on", - }, - [0x1F483]={ - category="so", - direction="on", - }, - [0x1F484]={ - category="so", - direction="on", - }, - [0x1F485]={ - category="so", - direction="on", - }, - [0x1F486]={ - category="so", - direction="on", - }, - [0x1F487]={ - category="so", - direction="on", - }, - [0x1F488]={ - category="so", - direction="on", - }, - [0x1F489]={ - category="so", - direction="on", - }, - [0x1F48A]={ - category="so", - direction="on", - }, - [0x1F48B]={ - category="so", - direction="on", - }, - [0x1F48C]={ - category="so", - direction="on", - }, - [0x1F48D]={ - category="so", - direction="on", - }, - [0x1F48E]={ - category="so", - direction="on", - }, - [0x1F48F]={ - category="so", - direction="on", - }, - [0x1F490]={ - category="so", - direction="on", - }, - [0x1F491]={ - category="so", - direction="on", - }, - [0x1F492]={ - category="so", - direction="on", - }, - [0x1F493]={ - category="so", - direction="on", - }, - [0x1F494]={ - category="so", - direction="on", - }, - [0x1F495]={ - category="so", - direction="on", - }, - [0x1F496]={ - category="so", - direction="on", - }, - [0x1F497]={ - category="so", - direction="on", - }, - [0x1F498]={ - category="so", - direction="on", - }, - [0x1F499]={ - category="so", - direction="on", - }, - [0x1F49A]={ - category="so", - direction="on", - }, - [0x1F49B]={ - category="so", - direction="on", - }, - [0x1F49C]={ - category="so", - direction="on", - }, - [0x1F49D]={ - category="so", - direction="on", - }, - [0x1F49E]={ - category="so", - direction="on", - }, - [0x1F49F]={ - category="so", - direction="on", - }, - [0x1F4A0]={ - category="so", - direction="on", - }, - [0x1F4A1]={ - category="so", - direction="on", - }, - [0x1F4A2]={ - category="so", - direction="on", - }, - [0x1F4A3]={ - category="so", - direction="on", - }, - [0x1F4A4]={ - category="so", - direction="on", - }, - [0x1F4A5]={ - category="so", - direction="on", - }, - [0x1F4A6]={ - category="so", - direction="on", - }, - [0x1F4A7]={ - category="so", - direction="on", - }, - [0x1F4A8]={ - category="so", - direction="on", - }, - [0x1F4A9]={ - category="so", - direction="on", - }, - [0x1F4AA]={ - category="so", - direction="on", - }, - [0x1F4AB]={ - category="so", - direction="on", - }, - [0x1F4AC]={ - category="so", - direction="on", - }, - [0x1F4AD]={ - category="so", - direction="on", - }, - [0x1F4AE]={ - category="so", - direction="on", - }, - [0x1F4AF]={ - category="so", - direction="on", - }, - [0x1F4B0]={ - category="so", - direction="on", - }, - [0x1F4B1]={ - category="so", - direction="on", - }, - [0x1F4B2]={ - category="so", - direction="on", - }, - [0x1F4B3]={ - category="so", - direction="on", - }, - [0x1F4B4]={ - category="so", - direction="on", - }, - [0x1F4B5]={ - category="so", - direction="on", - }, - [0x1F4B6]={ - category="so", - direction="on", - }, - [0x1F4B7]={ - category="so", - direction="on", - }, - [0x1F4B8]={ - category="so", - direction="on", - }, - [0x1F4B9]={ - category="so", - direction="on", - }, - [0x1F4BA]={ - category="so", - direction="on", - }, - [0x1F4BB]={ - category="so", - direction="on", - }, - [0x1F4BC]={ - category="so", - direction="on", - }, - [0x1F4BD]={ - category="so", - direction="on", - }, - [0x1F4BE]={ - category="so", - direction="on", - }, - [0x1F4BF]={ - category="so", - direction="on", - }, - [0x1F4C0]={ - category="so", - direction="on", - }, - [0x1F4C1]={ - category="so", - direction="on", - }, - [0x1F4C2]={ - category="so", - direction="on", - }, - [0x1F4C3]={ - category="so", - direction="on", - }, - [0x1F4C4]={ - category="so", - direction="on", - }, - [0x1F4C5]={ - category="so", - direction="on", - }, - [0x1F4C6]={ - category="so", - direction="on", - }, - [0x1F4C7]={ - category="so", - direction="on", - }, - [0x1F4C8]={ - category="so", - direction="on", - }, - [0x1F4C9]={ - category="so", - direction="on", - }, - [0x1F4CA]={ - category="so", - direction="on", - }, - [0x1F4CB]={ - category="so", - direction="on", - }, - [0x1F4CC]={ - category="so", - direction="on", - }, - [0x1F4CD]={ - category="so", - direction="on", - }, - [0x1F4CE]={ - category="so", - direction="on", - }, - [0x1F4CF]={ - category="so", - direction="on", - }, - [0x1F4D0]={ - category="so", - direction="on", - }, - [0x1F4D1]={ - category="so", - direction="on", - }, - [0x1F4D2]={ - category="so", - direction="on", - }, - [0x1F4D3]={ - category="so", - direction="on", - }, - [0x1F4D4]={ - category="so", - direction="on", - }, - [0x1F4D5]={ - category="so", - direction="on", - }, - [0x1F4D6]={ - category="so", - direction="on", - }, - [0x1F4D7]={ - category="so", - direction="on", - }, - [0x1F4D8]={ - category="so", - direction="on", - }, - [0x1F4D9]={ - category="so", - direction="on", - }, - [0x1F4DA]={ - category="so", - direction="on", - }, - [0x1F4DB]={ - category="so", - direction="on", - }, - [0x1F4DC]={ - category="so", - direction="on", - }, - [0x1F4DD]={ - category="so", - direction="on", - }, - [0x1F4DE]={ - category="so", - direction="on", - }, - [0x1F4DF]={ - category="so", - direction="on", - }, - [0x1F4E0]={ - category="so", - direction="on", - }, - [0x1F4E1]={ - category="so", - direction="on", - }, - [0x1F4E2]={ - category="so", - direction="on", - }, - [0x1F4E3]={ - category="so", - direction="on", - }, - [0x1F4E4]={ - category="so", - direction="on", - }, - [0x1F4E5]={ - category="so", - direction="on", - }, - [0x1F4E6]={ - category="so", - direction="on", - }, - [0x1F4E7]={ - category="so", - direction="on", - }, - [0x1F4E8]={ - category="so", - direction="on", - }, - [0x1F4E9]={ - category="so", - direction="on", - }, - [0x1F4EA]={ - category="so", - direction="on", - }, - [0x1F4EB]={ - category="so", - direction="on", - }, - [0x1F4EC]={ - category="so", - direction="on", - }, - [0x1F4ED]={ - category="so", - direction="on", - }, - [0x1F4EE]={ - category="so", - direction="on", - }, - [0x1F4EF]={ - category="so", - direction="on", - }, - [0x1F4F0]={ - category="so", - direction="on", - }, - [0x1F4F1]={ - category="so", - direction="on", - }, - [0x1F4F2]={ - category="so", - direction="on", - }, - [0x1F4F3]={ - category="so", - direction="on", - }, - [0x1F4F4]={ - category="so", - direction="on", - }, - [0x1F4F5]={ - category="so", - direction="on", - }, - [0x1F4F6]={ - category="so", - direction="on", - }, - [0x1F4F7]={ - category="so", - direction="on", - }, - [0x1F4F8]={ - category="so", - direction="on", - }, - [0x1F4F9]={ - category="so", - direction="on", - }, - [0x1F4FA]={ - category="so", - direction="on", - }, - [0x1F4FB]={ - category="so", - direction="on", - }, - [0x1F4FC]={ - category="so", - direction="on", - }, - [0x1F4FD]={ - category="so", - direction="on", - }, - [0x1F4FE]={ - category="so", - direction="on", - }, - [0x1F4FF]={ - category="so", - direction="on", - }, - [0x1F500]={ - category="so", - direction="on", - }, - [0x1F501]={ - category="so", - direction="on", - }, - [0x1F502]={ - category="so", - direction="on", - }, - [0x1F503]={ - category="so", - direction="on", - }, - [0x1F504]={ - category="so", - direction="on", - }, - [0x1F505]={ - category="so", - direction="on", - }, - [0x1F506]={ - category="so", - direction="on", - }, - [0x1F507]={ - category="so", - direction="on", - }, - [0x1F508]={ - category="so", - direction="on", - }, - [0x1F509]={ - category="so", - direction="on", - }, - [0x1F50A]={ - category="so", - direction="on", - }, - [0x1F50B]={ - category="so", - direction="on", - }, - [0x1F50C]={ - category="so", - direction="on", - }, - [0x1F50D]={ - category="so", - direction="on", - }, - [0x1F50E]={ - category="so", - direction="on", - }, - [0x1F50F]={ - category="so", - direction="on", - }, - [0x1F510]={ - category="so", - direction="on", - }, - [0x1F511]={ - category="so", - direction="on", - }, - [0x1F512]={ - category="so", - direction="on", - }, - [0x1F513]={ - category="so", - direction="on", - }, - [0x1F514]={ - category="so", - direction="on", - }, - [0x1F515]={ - category="so", - direction="on", - }, - [0x1F516]={ - category="so", - direction="on", - }, - [0x1F517]={ - category="so", - direction="on", - }, - [0x1F518]={ - category="so", - direction="on", - }, - [0x1F519]={ - category="so", - direction="on", - }, - [0x1F51A]={ - category="so", - direction="on", - }, - [0x1F51B]={ - category="so", - direction="on", - }, - [0x1F51C]={ - category="so", - direction="on", - }, - [0x1F51D]={ - category="so", - direction="on", - }, - [0x1F51E]={ - category="so", - direction="on", - }, - [0x1F51F]={ - category="so", - direction="on", - }, - [0x1F520]={ - category="so", - direction="on", - }, - [0x1F521]={ - category="so", - direction="on", - }, - [0x1F522]={ - category="so", - direction="on", - }, - [0x1F523]={ - category="so", - direction="on", - }, - [0x1F524]={ - category="so", - direction="on", - }, - [0x1F525]={ - category="so", - direction="on", - }, - [0x1F526]={ - category="so", - direction="on", - }, - [0x1F527]={ - category="so", - direction="on", - }, - [0x1F528]={ - category="so", - direction="on", - }, - [0x1F529]={ - category="so", - direction="on", - }, - [0x1F52A]={ - category="so", - direction="on", - }, - [0x1F52B]={ - category="so", - direction="on", - }, - [0x1F52C]={ - category="so", - direction="on", - }, - [0x1F52D]={ - category="so", - direction="on", - }, - [0x1F52E]={ - category="so", - direction="on", - }, - [0x1F52F]={ - category="so", - direction="on", - }, - [0x1F530]={ - category="so", - direction="on", - }, - [0x1F531]={ - category="so", - direction="on", - }, - [0x1F532]={ - category="so", - direction="on", - }, - [0x1F533]={ - category="so", - direction="on", - }, - [0x1F534]={ - category="so", - direction="on", - }, - [0x1F535]={ - category="so", - direction="on", - }, - [0x1F536]={ - category="so", - direction="on", - }, - [0x1F537]={ - category="so", - direction="on", - }, - [0x1F538]={ - category="so", - direction="on", - }, - [0x1F539]={ - category="so", - direction="on", - }, - [0x1F53A]={ - category="so", - direction="on", - }, - [0x1F53B]={ - category="so", - direction="on", - }, - [0x1F53C]={ - category="so", - direction="on", - }, - [0x1F53D]={ - category="so", - direction="on", - }, - [0x1F53E]={ - category="so", - direction="on", - }, - [0x1F53F]={ - category="so", - direction="on", - }, - [0x1F540]={ - category="so", - direction="on", - }, - [0x1F541]={ - category="so", - direction="on", - }, - [0x1F542]={ - category="so", - direction="on", - }, - [0x1F543]={ - category="so", - direction="on", - }, - [0x1F544]={ - category="so", - direction="on", - }, - [0x1F545]={ - category="so", - direction="on", - }, - [0x1F546]={ - category="so", - direction="on", - }, - [0x1F547]={ - category="so", - direction="on", - }, - [0x1F548]={ - category="so", - direction="on", - }, - [0x1F549]={ - category="so", - direction="on", - }, - [0x1F54A]={ - category="so", - direction="on", - }, - [0x1F54B]={ - category="so", - direction="on", - }, - [0x1F54C]={ - category="so", - direction="on", - }, - [0x1F54D]={ - category="so", - direction="on", - }, - [0x1F54E]={ - category="so", - direction="on", - }, - [0x1F54F]={ - category="so", - direction="on", - }, - [0x1F550]={ - category="so", - direction="on", - }, - [0x1F551]={ - category="so", - direction="on", - }, - [0x1F552]={ - category="so", - direction="on", - }, - [0x1F553]={ - category="so", - direction="on", - }, - [0x1F554]={ - category="so", - direction="on", - }, - [0x1F555]={ - category="so", - direction="on", - }, - [0x1F556]={ - category="so", - direction="on", - }, - [0x1F557]={ - category="so", - direction="on", - }, - [0x1F558]={ - category="so", - direction="on", - }, - [0x1F559]={ - category="so", - direction="on", - }, - [0x1F55A]={ - category="so", - direction="on", - }, - [0x1F55B]={ - category="so", - direction="on", - }, - [0x1F55C]={ - category="so", - direction="on", - }, - [0x1F55D]={ - category="so", - direction="on", - }, - [0x1F55E]={ - category="so", - direction="on", - }, - [0x1F55F]={ - category="so", - direction="on", - }, - [0x1F560]={ - category="so", - direction="on", - }, - [0x1F561]={ - category="so", - direction="on", - }, - [0x1F562]={ - category="so", - direction="on", - }, - [0x1F563]={ - category="so", - direction="on", - }, - [0x1F564]={ - category="so", - direction="on", - }, - [0x1F565]={ - category="so", - direction="on", - }, - [0x1F566]={ - category="so", - direction="on", - }, - [0x1F567]={ - category="so", - direction="on", - }, - [0x1F568]={ - category="so", - direction="on", - }, - [0x1F569]={ - category="so", - direction="on", - }, - [0x1F56A]={ - category="so", - direction="on", - }, - [0x1F56B]={ - category="so", - direction="on", - }, - [0x1F56C]={ - category="so", - direction="on", - }, - [0x1F56D]={ - category="so", - direction="on", - }, - [0x1F56E]={ - category="so", - direction="on", - }, - [0x1F56F]={ - category="so", - direction="on", - }, - [0x1F570]={ - category="so", - direction="on", - }, - [0x1F571]={ - category="so", - direction="on", - }, - [0x1F572]={ - category="so", - direction="on", - }, - [0x1F573]={ - category="so", - direction="on", - }, - [0x1F574]={ - category="so", - direction="on", - }, - [0x1F575]={ - category="so", - direction="on", - }, - [0x1F576]={ - category="so", - direction="on", - }, - [0x1F577]={ - category="so", - direction="on", - }, - [0x1F578]={ - category="so", - direction="on", - }, - [0x1F579]={ - category="so", - direction="on", - }, - [0x1F57A]={ - category="so", - direction="on", - }, - [0x1F57B]={ - category="so", - direction="on", - }, - [0x1F57C]={ - category="so", - direction="on", - }, - [0x1F57D]={ - category="so", - direction="on", - }, - [0x1F57E]={ - category="so", - direction="on", - }, - [0x1F57F]={ - category="so", - direction="on", - }, - [0x1F580]={ - category="so", - direction="on", - }, - [0x1F581]={ - category="so", - direction="on", - }, - [0x1F582]={ - category="so", - direction="on", - }, - [0x1F583]={ - category="so", - direction="on", - }, - [0x1F584]={ - category="so", - direction="on", - }, - [0x1F585]={ - category="so", - direction="on", - }, - [0x1F586]={ - category="so", - direction="on", - }, - [0x1F587]={ - category="so", - direction="on", - }, - [0x1F588]={ - category="so", - direction="on", - }, - [0x1F589]={ - category="so", - direction="on", - }, - [0x1F58A]={ - category="so", - direction="on", - }, - [0x1F58B]={ - category="so", - direction="on", - }, - [0x1F58C]={ - category="so", - direction="on", - }, - [0x1F58D]={ - category="so", - direction="on", - }, - [0x1F58E]={ - category="so", - direction="on", - }, - [0x1F58F]={ - category="so", - direction="on", - }, - [0x1F590]={ - category="so", - direction="on", - }, - [0x1F591]={ - category="so", - direction="on", - }, - [0x1F592]={ - category="so", - direction="on", - }, - [0x1F593]={ - category="so", - direction="on", - }, - [0x1F594]={ - category="so", - direction="on", - }, - [0x1F595]={ - category="so", - direction="on", - }, - [0x1F596]={ - category="so", - direction="on", - }, - [0x1F597]={ - category="so", - direction="on", - }, - [0x1F598]={ - category="so", - direction="on", - }, - [0x1F599]={ - category="so", - direction="on", - }, - [0x1F59A]={ - category="so", - direction="on", - }, - [0x1F59B]={ - category="so", - direction="on", - }, - [0x1F59C]={ - category="so", - direction="on", - }, - [0x1F59D]={ - category="so", - direction="on", - }, - [0x1F59E]={ - category="so", - direction="on", - }, - [0x1F59F]={ - category="so", - direction="on", - }, - [0x1F5A0]={ - category="so", - direction="on", - }, - [0x1F5A1]={ - category="so", - direction="on", - }, - [0x1F5A2]={ - category="so", - direction="on", - }, - [0x1F5A3]={ - category="so", - direction="on", - }, - [0x1F5A4]={ - category="so", - direction="on", - }, - [0x1F5A5]={ - category="so", - direction="on", - }, - [0x1F5A6]={ - category="so", - direction="on", - }, - [0x1F5A7]={ - category="so", - direction="on", - }, - [0x1F5A8]={ - category="so", - direction="on", - }, - [0x1F5A9]={ - category="so", - direction="on", - }, - [0x1F5AA]={ - category="so", - direction="on", - }, - [0x1F5AB]={ - category="so", - direction="on", - }, - [0x1F5AC]={ - category="so", - direction="on", - }, - [0x1F5AD]={ - category="so", - direction="on", - }, - [0x1F5AE]={ - category="so", - direction="on", - }, - [0x1F5AF]={ - category="so", - direction="on", - }, - [0x1F5B0]={ - category="so", - direction="on", - }, - [0x1F5B1]={ - category="so", - direction="on", - }, - [0x1F5B2]={ - category="so", - direction="on", - }, - [0x1F5B3]={ - category="so", - direction="on", - }, - [0x1F5B4]={ - category="so", - direction="on", - }, - [0x1F5B5]={ - category="so", - direction="on", - }, - [0x1F5B6]={ - category="so", - direction="on", - }, - [0x1F5B7]={ - category="so", - direction="on", - }, - [0x1F5B8]={ - category="so", - direction="on", - }, - [0x1F5B9]={ - category="so", - direction="on", - }, - [0x1F5BA]={ - category="so", - direction="on", - }, - [0x1F5BB]={ - category="so", - direction="on", - }, - [0x1F5BC]={ - category="so", - direction="on", - }, - [0x1F5BD]={ - category="so", - direction="on", - }, - [0x1F5BE]={ - category="so", - direction="on", - }, - [0x1F5BF]={ - category="so", - direction="on", - }, - [0x1F5C0]={ - category="so", - direction="on", - }, - [0x1F5C1]={ - category="so", - direction="on", - }, - [0x1F5C2]={ - category="so", - direction="on", - }, - [0x1F5C3]={ - category="so", - direction="on", - }, - [0x1F5C4]={ - category="so", - direction="on", - }, - [0x1F5C5]={ - category="so", - direction="on", - }, - [0x1F5C6]={ - category="so", - direction="on", - }, - [0x1F5C7]={ - category="so", - direction="on", - }, - [0x1F5C8]={ - category="so", - direction="on", - }, - [0x1F5C9]={ - category="so", - direction="on", - }, - [0x1F5CA]={ - category="so", - direction="on", - }, - [0x1F5CB]={ - category="so", - direction="on", - }, - [0x1F5CC]={ - category="so", - direction="on", - }, - [0x1F5CD]={ - category="so", - direction="on", - }, - [0x1F5CE]={ - category="so", - direction="on", - }, - [0x1F5CF]={ - category="so", - direction="on", - }, - [0x1F5D0]={ - category="so", - direction="on", - }, - [0x1F5D1]={ - category="so", - direction="on", - }, - [0x1F5D2]={ - category="so", - direction="on", - }, - [0x1F5D3]={ - category="so", - direction="on", - }, - [0x1F5D4]={ - category="so", - direction="on", - }, - [0x1F5D5]={ - category="so", - direction="on", - }, - [0x1F5D6]={ - category="so", - direction="on", - }, - [0x1F5D7]={ - category="so", - direction="on", - }, - [0x1F5D8]={ - category="so", - direction="on", - }, - [0x1F5D9]={ - category="so", - direction="on", - }, - [0x1F5DA]={ - category="so", - direction="on", - }, - [0x1F5DB]={ - category="so", - direction="on", - }, - [0x1F5DC]={ - category="so", - direction="on", - }, - [0x1F5DD]={ - category="so", - direction="on", - }, - [0x1F5DE]={ - category="so", - direction="on", - }, - [0x1F5DF]={ - category="so", - direction="on", - }, - [0x1F5E0]={ - category="so", - direction="on", - }, - [0x1F5E1]={ - category="so", - direction="on", - }, - [0x1F5E2]={ - category="so", - direction="on", - }, - [0x1F5E3]={ - category="so", - direction="on", - }, - [0x1F5E4]={ - category="so", - direction="on", - }, - [0x1F5E5]={ - category="so", - direction="on", - }, - [0x1F5E6]={ - category="so", - direction="on", - }, - [0x1F5E7]={ - category="so", - direction="on", - }, - [0x1F5E8]={ - category="so", - direction="on", - }, - [0x1F5E9]={ - category="so", - direction="on", - }, - [0x1F5EA]={ - category="so", - direction="on", - }, - [0x1F5EB]={ - category="so", - direction="on", - }, - [0x1F5EC]={ - category="so", - direction="on", - }, - [0x1F5ED]={ - category="so", - direction="on", - }, - [0x1F5EE]={ - category="so", - direction="on", - }, - [0x1F5EF]={ - category="so", - direction="on", - }, - [0x1F5F0]={ - category="so", - direction="on", - }, - [0x1F5F1]={ - category="so", - direction="on", - }, - [0x1F5F2]={ - category="so", - direction="on", - }, - [0x1F5F3]={ - category="so", - direction="on", - }, - [0x1F5F4]={ - category="so", - direction="on", - }, - [0x1F5F5]={ - category="so", - direction="on", - }, - [0x1F5F6]={ - category="so", - direction="on", - }, - [0x1F5F7]={ - category="so", - direction="on", - }, - [0x1F5F8]={ - category="so", - direction="on", - }, - [0x1F5F9]={ - category="so", - direction="on", - }, - [0x1F5FA]={ - category="so", - direction="on", - }, - [0x1F5FB]={ - category="so", - direction="on", - }, - [0x1F5FC]={ - category="so", - direction="on", - }, - [0x1F5FD]={ - category="so", - direction="on", - }, - [0x1F5FE]={ - category="so", - direction="on", - }, - [0x1F5FF]={ - category="so", - direction="on", - }, - [0x1F600]={ - category="so", - direction="on", - }, - [0x1F601]={ - category="so", - direction="on", - }, - [0x1F602]={ - category="so", - direction="on", - }, - [0x1F603]={ - category="so", - direction="on", - }, - [0x1F604]={ - category="so", - direction="on", - }, - [0x1F605]={ - category="so", - direction="on", - }, - [0x1F606]={ - category="so", - direction="on", - }, - [0x1F607]={ - category="so", - direction="on", - }, - [0x1F608]={ - category="so", - direction="on", - }, - [0x1F609]={ - category="so", - direction="on", - }, - [0x1F60A]={ - category="so", - direction="on", - }, - [0x1F60B]={ - category="so", - direction="on", - }, - [0x1F60C]={ - category="so", - direction="on", - }, - [0x1F60D]={ - category="so", - direction="on", - }, - [0x1F60E]={ - category="so", - direction="on", - }, - [0x1F60F]={ - category="so", - direction="on", - }, - [0x1F610]={ - category="so", - direction="on", - }, - [0x1F611]={ - category="so", - direction="on", - }, - [0x1F612]={ - category="so", - direction="on", - }, - [0x1F613]={ - category="so", - direction="on", - }, - [0x1F614]={ - category="so", - direction="on", - }, - [0x1F615]={ - category="so", - direction="on", - }, - [0x1F616]={ - category="so", - direction="on", - }, - [0x1F617]={ - category="so", - direction="on", - }, - [0x1F618]={ - category="so", - direction="on", - }, - [0x1F619]={ - category="so", - direction="on", - }, - [0x1F61A]={ - category="so", - direction="on", - }, - [0x1F61B]={ - category="so", - direction="on", - }, - [0x1F61C]={ - category="so", - direction="on", - }, - [0x1F61D]={ - category="so", - direction="on", - }, - [0x1F61E]={ - category="so", - direction="on", - }, - [0x1F61F]={ - category="so", - direction="on", - }, - [0x1F620]={ - category="so", - direction="on", - }, - [0x1F621]={ - category="so", - direction="on", - }, - [0x1F622]={ - category="so", - direction="on", - }, - [0x1F623]={ - category="so", - direction="on", - }, - [0x1F624]={ - category="so", - direction="on", - }, - [0x1F625]={ - category="so", - direction="on", - }, - [0x1F626]={ - category="so", - direction="on", - }, - [0x1F627]={ - category="so", - direction="on", - }, - [0x1F628]={ - category="so", - direction="on", - }, - [0x1F629]={ - category="so", - direction="on", - }, - [0x1F62A]={ - category="so", - direction="on", - }, - [0x1F62B]={ - category="so", - direction="on", - }, - [0x1F62C]={ - category="so", - direction="on", - }, - [0x1F62D]={ - category="so", - direction="on", - }, - [0x1F62E]={ - category="so", - direction="on", - }, - [0x1F62F]={ - category="so", - direction="on", - }, - [0x1F630]={ - category="so", - direction="on", - }, - [0x1F631]={ - category="so", - direction="on", - }, - [0x1F632]={ - category="so", - direction="on", - }, - [0x1F633]={ - category="so", - direction="on", - }, - [0x1F634]={ - category="so", - direction="on", - }, - [0x1F635]={ - category="so", - direction="on", - }, - [0x1F636]={ - category="so", - direction="on", - }, - [0x1F637]={ - category="so", - direction="on", - }, - [0x1F638]={ - category="so", - direction="on", - }, - [0x1F639]={ - category="so", - direction="on", - }, - [0x1F63A]={ - category="so", - direction="on", - }, - [0x1F63B]={ - category="so", - direction="on", - }, - [0x1F63C]={ - category="so", - direction="on", - }, - [0x1F63D]={ - category="so", - direction="on", - }, - [0x1F63E]={ - category="so", - direction="on", - }, - [0x1F63F]={ - category="so", - direction="on", - }, - [0x1F640]={ - category="so", - direction="on", - }, - [0x1F641]={ - category="so", - direction="on", - }, - [0x1F642]={ - category="so", - direction="on", - }, - [0x1F643]={ - category="so", - direction="on", - }, - [0x1F644]={ - category="so", - direction="on", - }, - [0x1F645]={ - category="so", - direction="on", - }, - [0x1F646]={ - category="so", - direction="on", - }, - [0x1F647]={ - category="so", - direction="on", - }, - [0x1F648]={ - category="so", - direction="on", - }, - [0x1F649]={ - category="so", - direction="on", - }, - [0x1F64A]={ - category="so", - direction="on", - }, - [0x1F64B]={ - category="so", - direction="on", - }, - [0x1F64C]={ - category="so", - direction="on", - }, - [0x1F64D]={ - category="so", - direction="on", - }, - [0x1F64E]={ - category="so", - direction="on", - }, - [0x1F64F]={ - category="so", - direction="on", - }, - [0x1F650]={ - category="so", - direction="on", - }, - [0x1F651]={ - category="so", - direction="on", - }, - [0x1F652]={ - category="so", - direction="on", - }, - [0x1F653]={ - category="so", - direction="on", - }, - [0x1F654]={ - category="so", - direction="on", - }, - [0x1F655]={ - category="so", - direction="on", - }, - [0x1F656]={ - category="so", - direction="on", - }, - [0x1F657]={ - category="so", - direction="on", - }, - [0x1F658]={ - category="so", - direction="on", - }, - [0x1F659]={ - category="so", - direction="on", - }, - [0x1F65A]={ - category="so", - direction="on", - }, - [0x1F65B]={ - category="so", - direction="on", - }, - [0x1F65C]={ - category="so", - direction="on", - }, - [0x1F65D]={ - category="so", - direction="on", - }, - [0x1F65E]={ - category="so", - direction="on", - }, - [0x1F65F]={ - category="so", - direction="on", - }, - [0x1F660]={ - category="so", - direction="on", - }, - [0x1F661]={ - category="so", - direction="on", - }, - [0x1F662]={ - category="so", - direction="on", - }, - [0x1F663]={ - category="so", - direction="on", - }, - [0x1F664]={ - category="so", - direction="on", - }, - [0x1F665]={ - category="so", - direction="on", - }, - [0x1F666]={ - category="so", - direction="on", - }, - [0x1F667]={ - category="so", - direction="on", - }, - [0x1F668]={ - category="so", - direction="on", - }, - [0x1F669]={ - category="so", - direction="on", - }, - [0x1F66A]={ - category="so", - direction="on", - }, - [0x1F66B]={ - category="so", - direction="on", - }, - [0x1F66C]={ - category="so", - direction="on", - }, - [0x1F66D]={ - category="so", - direction="on", - }, - [0x1F66E]={ - category="so", - direction="on", - }, - [0x1F66F]={ - category="so", - direction="on", - }, - [0x1F670]={ - category="so", - direction="on", - }, - [0x1F671]={ - category="so", - direction="on", - }, - [0x1F672]={ - category="so", - direction="on", - }, - [0x1F673]={ - category="so", - direction="on", - }, - [0x1F674]={ - category="so", - direction="on", - }, - [0x1F675]={ - category="so", - direction="on", - }, - [0x1F676]={ - category="so", - direction="on", - }, - [0x1F677]={ - category="so", - direction="on", - }, - [0x1F678]={ - category="so", - direction="on", - }, - [0x1F679]={ - category="so", - direction="on", - }, - [0x1F67A]={ - category="so", - direction="on", - }, - [0x1F67B]={ - category="so", - direction="on", - }, - [0x1F67C]={ - category="so", - direction="on", - }, - [0x1F67D]={ - category="so", - direction="on", - }, - [0x1F67E]={ - category="so", - direction="on", - }, - [0x1F67F]={ - category="so", - direction="on", - }, - [0x1F680]={ - category="so", - direction="on", - }, - [0x1F681]={ - category="so", - direction="on", - }, - [0x1F682]={ - category="so", - direction="on", - }, - [0x1F683]={ - category="so", - direction="on", - }, - [0x1F684]={ - category="so", - direction="on", - }, - [0x1F685]={ - category="so", - direction="on", - }, - [0x1F686]={ - category="so", - direction="on", - }, - [0x1F687]={ - category="so", - direction="on", - }, - [0x1F688]={ - category="so", - direction="on", - }, - [0x1F689]={ - category="so", - direction="on", - }, - [0x1F68A]={ - category="so", - direction="on", - }, - [0x1F68B]={ - category="so", - direction="on", - }, - [0x1F68C]={ - category="so", - direction="on", - }, - [0x1F68D]={ - category="so", - direction="on", - }, - [0x1F68E]={ - category="so", - direction="on", - }, - [0x1F68F]={ - category="so", - direction="on", - }, - [0x1F690]={ - category="so", - direction="on", - }, - [0x1F691]={ - category="so", - direction="on", - }, - [0x1F692]={ - category="so", - direction="on", - }, - [0x1F693]={ - category="so", - direction="on", - }, - [0x1F694]={ - category="so", - direction="on", - }, - [0x1F695]={ - category="so", - direction="on", - }, - [0x1F696]={ - category="so", - direction="on", - }, - [0x1F697]={ - category="so", - direction="on", - }, - [0x1F698]={ - category="so", - direction="on", - }, - [0x1F699]={ - category="so", - direction="on", - }, - [0x1F69A]={ - category="so", - direction="on", - }, - [0x1F69B]={ - category="so", - direction="on", - }, - [0x1F69C]={ - category="so", - direction="on", - }, - [0x1F69D]={ - category="so", - direction="on", - }, - [0x1F69E]={ - category="so", - direction="on", - }, - [0x1F69F]={ - category="so", - direction="on", - }, - [0x1F6A0]={ - category="so", - direction="on", - }, - [0x1F6A1]={ - category="so", - direction="on", - }, - [0x1F6A2]={ - category="so", - direction="on", - }, - [0x1F6A3]={ - category="so", - direction="on", - }, - [0x1F6A4]={ - category="so", - direction="on", - }, - [0x1F6A5]={ - category="so", - direction="on", - }, - [0x1F6A6]={ - category="so", - direction="on", - }, - [0x1F6A7]={ - category="so", - direction="on", - }, - [0x1F6A8]={ - category="so", - direction="on", - }, - [0x1F6A9]={ - category="so", - direction="on", - }, - [0x1F6AA]={ - category="so", - direction="on", - }, - [0x1F6AB]={ - category="so", - direction="on", - }, - [0x1F6AC]={ - category="so", - direction="on", - }, - [0x1F6AD]={ - category="so", - direction="on", - }, - [0x1F6AE]={ - category="so", - direction="on", - }, - [0x1F6AF]={ - category="so", - direction="on", - }, - [0x1F6B0]={ - category="so", - direction="on", - }, - [0x1F6B1]={ - category="so", - direction="on", - }, - [0x1F6B2]={ - category="so", - direction="on", - }, - [0x1F6B3]={ - category="so", - direction="on", - }, - [0x1F6B4]={ - category="so", - direction="on", - }, - [0x1F6B5]={ - category="so", - direction="on", - }, - [0x1F6B6]={ - category="so", - direction="on", - }, - [0x1F6B7]={ - category="so", - direction="on", - }, - [0x1F6B8]={ - category="so", - direction="on", - }, - [0x1F6B9]={ - category="so", - direction="on", - }, - [0x1F6BA]={ - category="so", - direction="on", - }, - [0x1F6BB]={ - category="so", - direction="on", - }, - [0x1F6BC]={ - category="so", - direction="on", - }, - [0x1F6BD]={ - category="so", - direction="on", - }, - [0x1F6BE]={ - category="so", - direction="on", - }, - [0x1F6BF]={ - category="so", - direction="on", - }, - [0x1F6C0]={ - category="so", - direction="on", - }, - [0x1F6C1]={ - category="so", - direction="on", - }, - [0x1F6C2]={ - category="so", - direction="on", - }, - [0x1F6C3]={ - category="so", - direction="on", - }, - [0x1F6C4]={ - category="so", - direction="on", - }, - [0x1F6C5]={ - category="so", - direction="on", - }, - [0x1F6C6]={ - category="so", - direction="on", - }, - [0x1F6C7]={ - category="so", - direction="on", - }, - [0x1F6C8]={ - category="so", - direction="on", - }, - [0x1F6C9]={ - category="so", - direction="on", - }, - [0x1F6CA]={ - category="so", - direction="on", - }, - [0x1F6CB]={ - category="so", - direction="on", - }, - [0x1F6CC]={ - category="so", - direction="on", - }, - [0x1F6CD]={ - category="so", - direction="on", - }, - [0x1F6CE]={ - category="so", - direction="on", - }, - [0x1F6CF]={ - category="so", - direction="on", - }, - [0x1F6D0]={ - category="so", - direction="on", - }, - [0x1F6D1]={ - category="so", - direction="on", - }, - [0x1F6D2]={ - category="so", - direction="on", - }, - [0x1F6E0]={ - category="so", - direction="on", - }, - [0x1F6E1]={ - category="so", - direction="on", - }, - [0x1F6E2]={ - category="so", - direction="on", - }, - [0x1F6E3]={ - category="so", - direction="on", - }, - [0x1F6E4]={ - category="so", - direction="on", - }, - [0x1F6E5]={ - category="so", - direction="on", - }, - [0x1F6E6]={ - category="so", - direction="on", - }, - [0x1F6E7]={ - category="so", - direction="on", - }, - [0x1F6E8]={ - category="so", - direction="on", - }, - [0x1F6E9]={ - category="so", - direction="on", - }, - [0x1F6EA]={ - category="so", - direction="on", - }, - [0x1F6EB]={ - category="so", - direction="on", - }, - [0x1F6EC]={ - category="so", - direction="on", - }, - [0x1F6F0]={ - category="so", - direction="on", - }, - [0x1F6F1]={ - category="so", - direction="on", - }, - [0x1F6F2]={ - category="so", - direction="on", - }, - [0x1F6F3]={ - category="so", - direction="on", - }, - [0x1F6F4]={ - category="so", - direction="on", - }, - [0x1F6F5]={ - category="so", - direction="on", - }, - [0x1F6F6]={ - category="so", - direction="on", - }, - [0x1F700]={ - category="so", - direction="on", - }, - [0x1F701]={ - category="so", - direction="on", - }, - [0x1F702]={ - category="so", - direction="on", - }, - [0x1F703]={ - category="so", - direction="on", - }, - [0x1F704]={ - category="so", - direction="on", - }, - [0x1F705]={ - category="so", - direction="on", - }, - [0x1F706]={ - category="so", - direction="on", - }, - [0x1F707]={ - category="so", - direction="on", - }, - [0x1F708]={ - category="so", - direction="on", - }, - [0x1F709]={ - category="so", - direction="on", - }, - [0x1F70A]={ - category="so", - direction="on", - }, - [0x1F70B]={ - category="so", - direction="on", - }, - [0x1F70C]={ - category="so", - direction="on", - }, - [0x1F70D]={ - category="so", - direction="on", - }, - [0x1F70E]={ - category="so", - direction="on", - }, - [0x1F70F]={ - category="so", - direction="on", - }, - [0x1F710]={ - category="so", - direction="on", - }, - [0x1F711]={ - category="so", - direction="on", - }, - [0x1F712]={ - category="so", - direction="on", - }, - [0x1F713]={ - category="so", - direction="on", - }, - [0x1F714]={ - category="so", - direction="on", - }, - [0x1F715]={ - category="so", - direction="on", - }, - [0x1F716]={ - category="so", - direction="on", - }, - [0x1F717]={ - category="so", - direction="on", - }, - [0x1F718]={ - category="so", - direction="on", - }, - [0x1F719]={ - category="so", - direction="on", - }, - [0x1F71A]={ - category="so", - direction="on", - }, - [0x1F71B]={ - category="so", - direction="on", - }, - [0x1F71C]={ - category="so", - direction="on", - }, - [0x1F71D]={ - category="so", - direction="on", - }, - [0x1F71E]={ - category="so", - direction="on", - }, - [0x1F71F]={ - category="so", - direction="on", - }, - [0x1F720]={ - category="so", - direction="on", - }, - [0x1F721]={ - category="so", - direction="on", - }, - [0x1F722]={ - category="so", - direction="on", - }, - [0x1F723]={ - category="so", - direction="on", - }, - [0x1F724]={ - category="so", - direction="on", - }, - [0x1F725]={ - category="so", - direction="on", - }, - [0x1F726]={ - category="so", - direction="on", - }, - [0x1F727]={ - category="so", - direction="on", - }, - [0x1F728]={ - category="so", - direction="on", - }, - [0x1F729]={ - category="so", - direction="on", - }, - [0x1F72A]={ - category="so", - direction="on", - }, - [0x1F72B]={ - category="so", - direction="on", - }, - [0x1F72C]={ - category="so", - direction="on", - }, - [0x1F72D]={ - category="so", - direction="on", - }, - [0x1F72E]={ - category="so", - direction="on", - }, - [0x1F72F]={ - category="so", - direction="on", - }, - [0x1F730]={ - category="so", - direction="on", - }, - [0x1F731]={ - category="so", - direction="on", - }, - [0x1F732]={ - category="so", - direction="on", - }, - [0x1F733]={ - category="so", - direction="on", - }, - [0x1F734]={ - category="so", - direction="on", - }, - [0x1F735]={ - category="so", - direction="on", - }, - [0x1F736]={ - category="so", - direction="on", - }, - [0x1F737]={ - category="so", - direction="on", - }, - [0x1F738]={ - category="so", - direction="on", - }, - [0x1F739]={ - category="so", - direction="on", - }, - [0x1F73A]={ - category="so", - direction="on", - }, - [0x1F73B]={ - category="so", - direction="on", - }, - [0x1F73C]={ - category="so", - direction="on", - }, - [0x1F73D]={ - category="so", - direction="on", - }, - [0x1F73E]={ - category="so", - direction="on", - }, - [0x1F73F]={ - category="so", - direction="on", - }, - [0x1F740]={ - category="so", - direction="on", - }, - [0x1F741]={ - category="so", - direction="on", - }, - [0x1F742]={ - category="so", - direction="on", - }, - [0x1F743]={ - category="so", - direction="on", - }, - [0x1F744]={ - category="so", - direction="on", - }, - [0x1F745]={ - category="so", - direction="on", - }, - [0x1F746]={ - category="so", - direction="on", - }, - [0x1F747]={ - category="so", - direction="on", - }, - [0x1F748]={ - category="so", - direction="on", - }, - [0x1F749]={ - category="so", - direction="on", - }, - [0x1F74A]={ - category="so", - direction="on", - }, - [0x1F74B]={ - category="so", - direction="on", - }, - [0x1F74C]={ - category="so", - direction="on", - }, - [0x1F74D]={ - category="so", - direction="on", - }, - [0x1F74E]={ - category="so", - direction="on", - }, - [0x1F74F]={ - category="so", - direction="on", - }, - [0x1F750]={ - category="so", - direction="on", - }, - [0x1F751]={ - category="so", - direction="on", - }, - [0x1F752]={ - category="so", - direction="on", - }, - [0x1F753]={ - category="so", - direction="on", - }, - [0x1F754]={ - category="so", - direction="on", - }, - [0x1F755]={ - category="so", - direction="on", - }, - [0x1F756]={ - category="so", - direction="on", - }, - [0x1F757]={ - category="so", - direction="on", - }, - [0x1F758]={ - category="so", - direction="on", - }, - [0x1F759]={ - category="so", - direction="on", - }, - [0x1F75A]={ - category="so", - direction="on", - }, - [0x1F75B]={ - category="so", - direction="on", - }, - [0x1F75C]={ - category="so", - direction="on", - }, - [0x1F75D]={ - category="so", - direction="on", - }, - [0x1F75E]={ - category="so", - direction="on", - }, - [0x1F75F]={ - category="so", - direction="on", - }, - [0x1F760]={ - category="so", - direction="on", - }, - [0x1F761]={ - category="so", - direction="on", - }, - [0x1F762]={ - category="so", - direction="on", - }, - [0x1F763]={ - category="so", - direction="on", - }, - [0x1F764]={ - category="so", - direction="on", - }, - [0x1F765]={ - category="so", - direction="on", - }, - [0x1F766]={ - category="so", - direction="on", - }, - [0x1F767]={ - category="so", - direction="on", - }, - [0x1F768]={ - category="so", - direction="on", - }, - [0x1F769]={ - category="so", - direction="on", - }, - [0x1F76A]={ - category="so", - direction="on", - }, - [0x1F76B]={ - category="so", - direction="on", - }, - [0x1F76C]={ - category="so", - direction="on", - }, - [0x1F76D]={ - category="so", - direction="on", - }, - [0x1F76E]={ - category="so", - direction="on", - }, - [0x1F76F]={ - category="so", - direction="on", - }, - [0x1F770]={ - category="so", - direction="on", - }, - [0x1F771]={ - category="so", - direction="on", - }, - [0x1F772]={ - category="so", - direction="on", - }, - [0x1F773]={ - category="so", - direction="on", - }, - [0x1F780]={ - category="so", - direction="on", - }, - [0x1F781]={ - category="so", - direction="on", - }, - [0x1F782]={ - category="so", - direction="on", - }, - [0x1F783]={ - category="so", - direction="on", - }, - [0x1F784]={ - category="so", - direction="on", - }, - [0x1F785]={ - category="so", - direction="on", - }, - [0x1F786]={ - category="so", - direction="on", - }, - [0x1F787]={ - category="so", - direction="on", - }, - [0x1F788]={ - category="so", - direction="on", - }, - [0x1F789]={ - category="so", - direction="on", - }, - [0x1F78A]={ - category="so", - direction="on", - }, - [0x1F78B]={ - category="so", - direction="on", - }, - [0x1F78C]={ - category="so", - direction="on", - }, - [0x1F78D]={ - category="so", - direction="on", - }, - [0x1F78E]={ - category="so", - direction="on", - }, - [0x1F78F]={ - category="so", - direction="on", - }, - [0x1F790]={ - category="so", - direction="on", - }, - [0x1F791]={ - category="so", - direction="on", - }, - [0x1F792]={ - category="so", - direction="on", - }, - [0x1F793]={ - category="so", - direction="on", - }, - [0x1F794]={ - category="so", - direction="on", - }, - [0x1F795]={ - category="so", - direction="on", - }, - [0x1F796]={ - category="so", - direction="on", - }, - [0x1F797]={ - category="so", - direction="on", - }, - [0x1F798]={ - category="so", - direction="on", - }, - [0x1F799]={ - category="so", - direction="on", - }, - [0x1F79A]={ - category="so", - direction="on", - }, - [0x1F79B]={ - category="so", - direction="on", - }, - [0x1F79C]={ - category="so", - direction="on", - }, - [0x1F79D]={ - category="so", - direction="on", - }, - [0x1F79E]={ - category="so", - direction="on", - }, - [0x1F79F]={ - category="so", - direction="on", - }, - [0x1F7A0]={ - category="so", - direction="on", - }, - [0x1F7A1]={ - category="so", - direction="on", - }, - [0x1F7A2]={ - category="so", - direction="on", - }, - [0x1F7A3]={ - category="so", - direction="on", - }, - [0x1F7A4]={ - category="so", - direction="on", - }, - [0x1F7A5]={ - category="so", - direction="on", - }, - [0x1F7A6]={ - category="so", - direction="on", - }, - [0x1F7A7]={ - category="so", - direction="on", - }, - [0x1F7A8]={ - category="so", - direction="on", - }, - [0x1F7A9]={ - category="so", - direction="on", - }, - [0x1F7AA]={ - category="so", - direction="on", - }, - [0x1F7AB]={ - category="so", - direction="on", - }, - [0x1F7AC]={ - category="so", - direction="on", - }, - [0x1F7AD]={ - category="so", - direction="on", - }, - [0x1F7AE]={ - category="so", - direction="on", - }, - [0x1F7AF]={ - category="so", - direction="on", - }, - [0x1F7B0]={ - category="so", - direction="on", - }, - [0x1F7B1]={ - category="so", - direction="on", - }, - [0x1F7B2]={ - category="so", - direction="on", - }, - [0x1F7B3]={ - category="so", - direction="on", - }, - [0x1F7B4]={ - category="so", - direction="on", - }, - [0x1F7B5]={ - category="so", - direction="on", - }, - [0x1F7B6]={ - category="so", - direction="on", - }, - [0x1F7B7]={ - category="so", - direction="on", - }, - [0x1F7B8]={ - category="so", - direction="on", - }, - [0x1F7B9]={ - category="so", - direction="on", - }, - [0x1F7BA]={ - category="so", - direction="on", - }, - [0x1F7BB]={ - category="so", - direction="on", - }, - [0x1F7BC]={ - category="so", - direction="on", - }, - [0x1F7BD]={ - category="so", - direction="on", - }, - [0x1F7BE]={ - category="so", - direction="on", - }, - [0x1F7BF]={ - category="so", - direction="on", - }, - [0x1F7C0]={ - category="so", - direction="on", - }, - [0x1F7C1]={ - category="so", - direction="on", - }, - [0x1F7C2]={ - category="so", - direction="on", - }, - [0x1F7C3]={ - category="so", - direction="on", - }, - [0x1F7C4]={ - category="so", - direction="on", - }, - [0x1F7C5]={ - category="so", - direction="on", - }, - [0x1F7C6]={ - category="so", - direction="on", - }, - [0x1F7C7]={ - category="so", - direction="on", - }, - [0x1F7C8]={ - category="so", - direction="on", - }, - [0x1F7C9]={ - category="so", - direction="on", - }, - [0x1F7CA]={ - category="so", - direction="on", - }, - [0x1F7CB]={ - category="so", - direction="on", - }, - [0x1F7CC]={ - category="so", - direction="on", - }, - [0x1F7CD]={ - category="so", - direction="on", - }, - [0x1F7CE]={ - category="so", - direction="on", - }, - [0x1F7CF]={ - category="so", - direction="on", - }, - [0x1F7D0]={ - category="so", - direction="on", - }, - [0x1F7D1]={ - category="so", - direction="on", - }, - [0x1F7D2]={ - category="so", - direction="on", - }, - [0x1F7D3]={ - category="so", - direction="on", - }, - [0x1F7D4]={ - category="so", - direction="on", - }, - [0x1F800]={ - category="so", - direction="on", - }, - [0x1F801]={ - category="so", - direction="on", - }, - [0x1F802]={ - category="so", - direction="on", - }, - [0x1F803]={ - category="so", - direction="on", - }, - [0x1F804]={ - category="so", - direction="on", - }, - [0x1F805]={ - category="so", - direction="on", - }, - [0x1F806]={ - category="so", - direction="on", - }, - [0x1F807]={ - category="so", - direction="on", - }, - [0x1F808]={ - category="so", - direction="on", - }, - [0x1F809]={ - category="so", - direction="on", - }, - [0x1F80A]={ - category="so", - direction="on", - }, - [0x1F80B]={ - category="so", - direction="on", - }, - [0x1F810]={ - category="so", - direction="on", - }, - [0x1F811]={ - category="so", - direction="on", - }, - [0x1F812]={ - category="so", - direction="on", - }, - [0x1F813]={ - category="so", - direction="on", - }, - [0x1F814]={ - category="so", - direction="on", - }, - [0x1F815]={ - category="so", - direction="on", - }, - [0x1F816]={ - category="so", - direction="on", - }, - [0x1F817]={ - category="so", - direction="on", - }, - [0x1F818]={ - category="so", - direction="on", - }, - [0x1F819]={ - category="so", - direction="on", - }, - [0x1F81A]={ - category="so", - direction="on", - }, - [0x1F81B]={ - category="so", - direction="on", - }, - [0x1F81C]={ - category="so", - direction="on", - }, - [0x1F81D]={ - category="so", - direction="on", - }, - [0x1F81E]={ - category="so", - direction="on", - }, - [0x1F81F]={ - category="so", - direction="on", - }, - [0x1F820]={ - category="so", - direction="on", - }, - [0x1F821]={ - category="so", - direction="on", - }, - [0x1F822]={ - category="so", - direction="on", - }, - [0x1F823]={ - category="so", - direction="on", - }, - [0x1F824]={ - category="so", - direction="on", - }, - [0x1F825]={ - category="so", - direction="on", - }, - [0x1F826]={ - category="so", - direction="on", - }, - [0x1F827]={ - category="so", - direction="on", - }, - [0x1F828]={ - category="so", - direction="on", - }, - [0x1F829]={ - category="so", - direction="on", - }, - [0x1F82A]={ - category="so", - direction="on", - }, - [0x1F82B]={ - category="so", - direction="on", - }, - [0x1F82C]={ - category="so", - direction="on", - }, - [0x1F82D]={ - category="so", - direction="on", - }, - [0x1F82E]={ - category="so", - direction="on", - }, - [0x1F82F]={ - category="so", - direction="on", - }, - [0x1F830]={ - category="so", - direction="on", - }, - [0x1F831]={ - category="so", - direction="on", - }, - [0x1F832]={ - category="so", - direction="on", - }, - [0x1F833]={ - category="so", - direction="on", - }, - [0x1F834]={ - category="so", - direction="on", - }, - [0x1F835]={ - category="so", - direction="on", - }, - [0x1F836]={ - category="so", - direction="on", - }, - [0x1F837]={ - category="so", - direction="on", - }, - [0x1F838]={ - category="so", - direction="on", - }, - [0x1F839]={ - category="so", - direction="on", - }, - [0x1F83A]={ - category="so", - direction="on", - }, - [0x1F83B]={ - category="so", - direction="on", - }, - [0x1F83C]={ - category="so", - direction="on", - }, - [0x1F83D]={ - category="so", - direction="on", - }, - [0x1F83E]={ - category="so", - direction="on", - }, - [0x1F83F]={ - category="so", - direction="on", - }, - [0x1F840]={ - category="so", - direction="on", - }, - [0x1F841]={ - category="so", - direction="on", - }, - [0x1F842]={ - category="so", - direction="on", - }, - [0x1F843]={ - category="so", - direction="on", - }, - [0x1F844]={ - category="so", - direction="on", - }, - [0x1F845]={ - category="so", - direction="on", - }, - [0x1F846]={ - category="so", - direction="on", - }, - [0x1F847]={ - category="so", - direction="on", - }, - [0x1F850]={ - category="so", - direction="on", - }, - [0x1F851]={ - category="so", - direction="on", - }, - [0x1F852]={ - category="so", - direction="on", - }, - [0x1F853]={ - category="so", - direction="on", - }, - [0x1F854]={ - category="so", - direction="on", - }, - [0x1F855]={ - category="so", - direction="on", - }, - [0x1F856]={ - category="so", - direction="on", - }, - [0x1F857]={ - category="so", - direction="on", - }, - [0x1F858]={ - category="so", - direction="on", - }, - [0x1F859]={ - category="so", - direction="on", - }, - [0x1F860]={ - category="so", - direction="on", - }, - [0x1F861]={ - category="so", - direction="on", - }, - [0x1F862]={ - category="so", - direction="on", - }, - [0x1F863]={ - category="so", - direction="on", - }, - [0x1F864]={ - category="so", - direction="on", - }, - [0x1F865]={ - category="so", - direction="on", - }, - [0x1F866]={ - category="so", - direction="on", - }, - [0x1F867]={ - category="so", - direction="on", - }, - [0x1F868]={ - category="so", - direction="on", - }, - [0x1F869]={ - category="so", - direction="on", - }, - [0x1F86A]={ - category="so", - direction="on", - }, - [0x1F86B]={ - category="so", - direction="on", - }, - [0x1F86C]={ - category="so", - direction="on", - }, - [0x1F86D]={ - category="so", - direction="on", - }, - [0x1F86E]={ - category="so", - direction="on", - }, - [0x1F86F]={ - category="so", - direction="on", - }, - [0x1F870]={ - category="so", - direction="on", - }, - [0x1F871]={ - category="so", - direction="on", - }, - [0x1F872]={ - category="so", - direction="on", - }, - [0x1F873]={ - category="so", - direction="on", - }, - [0x1F874]={ - category="so", - direction="on", - }, - [0x1F875]={ - category="so", - direction="on", - }, - [0x1F876]={ - category="so", - direction="on", - }, - [0x1F877]={ - category="so", - direction="on", - }, - [0x1F878]={ - category="so", - direction="on", - }, - [0x1F879]={ - category="so", - direction="on", - }, - [0x1F87A]={ - category="so", - direction="on", - }, - [0x1F87B]={ - category="so", - direction="on", - }, - [0x1F87C]={ - category="so", - direction="on", - }, - [0x1F87D]={ - category="so", - direction="on", - }, - [0x1F87E]={ - category="so", - direction="on", - }, - [0x1F87F]={ - category="so", - direction="on", - }, - [0x1F880]={ - category="so", - direction="on", - }, - [0x1F881]={ - category="so", - direction="on", - }, - [0x1F882]={ - category="so", - direction="on", - }, - [0x1F883]={ - category="so", - direction="on", - }, - [0x1F884]={ - category="so", - direction="on", - }, - [0x1F885]={ - category="so", - direction="on", - }, - [0x1F886]={ - category="so", - direction="on", - }, - [0x1F887]={ - category="so", - direction="on", - }, - [0x1F890]={ - category="so", - direction="on", - }, - [0x1F891]={ - category="so", - direction="on", - }, - [0x1F892]={ - category="so", - direction="on", - }, - [0x1F893]={ - category="so", - direction="on", - }, - [0x1F894]={ - category="so", - direction="on", - }, - [0x1F895]={ - category="so", - direction="on", - }, - [0x1F896]={ - category="so", - direction="on", - }, - [0x1F897]={ - category="so", - direction="on", - }, - [0x1F898]={ - category="so", - direction="on", - }, - [0x1F899]={ - category="so", - direction="on", - }, - [0x1F89A]={ - category="so", - direction="on", - }, - [0x1F89B]={ - category="so", - direction="on", - }, - [0x1F89C]={ - category="so", - direction="on", - }, - [0x1F89D]={ - category="so", - direction="on", - }, - [0x1F89E]={ - category="so", - direction="on", - }, - [0x1F89F]={ - category="so", - direction="on", - }, - [0x1F8A0]={ - category="so", - direction="on", - }, - [0x1F8A1]={ - category="so", - direction="on", - }, - [0x1F8A2]={ - category="so", - direction="on", - }, - [0x1F8A3]={ - category="so", - direction="on", - }, - [0x1F8A4]={ - category="so", - direction="on", - }, - [0x1F8A5]={ - category="so", - direction="on", - }, - [0x1F8A6]={ - category="so", - direction="on", - }, - [0x1F8A7]={ - category="so", - direction="on", - }, - [0x1F8A8]={ - category="so", - direction="on", - }, - [0x1F8A9]={ - category="so", - direction="on", - }, - [0x1F8AA]={ - category="so", - direction="on", - }, - [0x1F8AB]={ - category="so", - direction="on", - }, - [0x1F8AC]={ - category="so", - direction="on", - }, - [0x1F8AD]={ - category="so", - direction="on", - }, - [0x1F910]={ - category="so", - direction="on", - }, - [0x1F911]={ - category="so", - direction="on", - }, - [0x1F912]={ - category="so", - direction="on", - }, - [0x1F913]={ - category="so", - direction="on", - }, - [0x1F914]={ - category="so", - direction="on", - }, - [0x1F915]={ - category="so", - direction="on", - }, - [0x1F916]={ - category="so", - direction="on", - }, - [0x1F917]={ - category="so", - direction="on", - }, - [0x1F918]={ - category="so", - direction="on", - }, - [0x1F919]={ - category="so", - direction="on", - }, - [0x1F91A]={ - category="so", - direction="on", - }, - [0x1F91B]={ - category="so", - direction="on", - }, - [0x1F91C]={ - category="so", - direction="on", - }, - [0x1F91D]={ - category="so", - direction="on", - }, - [0x1F91E]={ - category="so", - direction="on", - }, - [0x1F920]={ - category="so", - direction="on", - }, - [0x1F921]={ - category="so", - direction="on", - }, - [0x1F922]={ - category="so", - direction="on", - }, - [0x1F923]={ - category="so", - direction="on", - }, - [0x1F924]={ - category="so", - direction="on", - }, - [0x1F925]={ - category="so", - direction="on", - }, - [0x1F926]={ - category="so", - direction="on", - }, - [0x1F927]={ - category="so", - direction="on", - }, - [0x1F930]={ - category="so", - direction="on", - }, - [0x1F933]={ - category="so", - direction="on", - }, - [0x1F934]={ - category="so", - direction="on", - }, - [0x1F935]={ - category="so", - direction="on", - }, - [0x1F936]={ - category="so", - direction="on", - }, - [0x1F937]={ - category="so", - direction="on", - }, - [0x1F938]={ - category="so", - direction="on", - }, - [0x1F939]={ - category="so", - direction="on", - }, - [0x1F93A]={ - category="so", - direction="on", - }, - [0x1F93B]={ - category="so", - direction="on", - }, - [0x1F93C]={ - category="so", - direction="on", - }, - [0x1F93D]={ - category="so", - direction="on", - }, - [0x1F93E]={ - category="so", - direction="on", - }, - [0x1F940]={ - category="so", - direction="on", - }, - [0x1F941]={ - category="so", - direction="on", - }, - [0x1F942]={ - category="so", - direction="on", - }, - [0x1F943]={ - category="so", - direction="on", - }, - [0x1F944]={ - category="so", - direction="on", - }, - [0x1F945]={ - category="so", - direction="on", - }, - [0x1F946]={ - category="so", - direction="on", - }, - [0x1F947]={ - category="so", - direction="on", - }, - [0x1F948]={ - category="so", - direction="on", - }, - [0x1F949]={ - category="so", - direction="on", - }, - [0x1F94A]={ - category="so", - direction="on", - }, - [0x1F94B]={ - category="so", - direction="on", - }, - [0x1F950]={ - category="so", - direction="on", - }, - [0x1F951]={ - category="so", - direction="on", - }, - [0x1F952]={ - category="so", - direction="on", - }, - [0x1F953]={ - category="so", - direction="on", - }, - [0x1F954]={ - category="so", - direction="on", - }, - [0x1F955]={ - category="so", - direction="on", - }, - [0x1F956]={ - category="so", - direction="on", - }, - [0x1F957]={ - category="so", - direction="on", - }, - [0x1F958]={ - category="so", - direction="on", - }, - [0x1F959]={ - category="so", - direction="on", - }, - [0x1F95A]={ - category="so", - direction="on", - }, - [0x1F95B]={ - category="so", - direction="on", - }, - [0x1F95C]={ - category="so", - direction="on", - }, - [0x1F95D]={ - category="so", - direction="on", - }, - [0x1F95E]={ - category="so", - direction="on", - }, - [0x1F980]={ - category="so", - direction="on", - }, - [0x1F981]={ - category="so", - direction="on", - }, - [0x1F982]={ - category="so", - direction="on", - }, - [0x1F983]={ - category="so", - direction="on", - }, - [0x1F984]={ - category="so", - direction="on", - }, - [0x1F985]={ - category="so", - direction="on", - }, - [0x1F986]={ - category="so", - direction="on", - }, - [0x1F987]={ - category="so", - direction="on", - }, - [0x1F988]={ - category="so", - direction="on", - }, - [0x1F989]={ - category="so", - direction="on", - }, - [0x1F98A]={ - category="so", - direction="on", - }, - [0x1F98B]={ - category="so", - direction="on", - }, - [0x1F98C]={ - category="so", - direction="on", - }, - [0x1F98D]={ - category="so", - direction="on", - }, - [0x1F98E]={ - category="so", - direction="on", - }, - [0x1F98F]={ - category="so", - direction="on", - }, - [0x1F990]={ - category="so", - direction="on", - }, - [0x1F991]={ - category="so", - direction="on", - }, - [0x1F9C0]={ - category="so", - direction="on", - }, - [0x2F800]={ - category="lo", - direction="l", - }, - [0x2F801]={ - category="lo", - direction="l", - }, - [0x2F802]={ - category="lo", - direction="l", - }, - [0x2F803]={ - category="lo", - direction="l", - }, - [0x2F804]={ - category="lo", - direction="l", - }, - [0x2F805]={ - category="lo", - direction="l", - }, - [0x2F806]={ - category="lo", - direction="l", - }, - [0x2F807]={ - category="lo", - direction="l", - }, - [0x2F808]={ - category="lo", - direction="l", - }, - [0x2F809]={ - category="lo", - direction="l", - }, - [0x2F80A]={ - category="lo", - direction="l", - }, - [0x2F80B]={ - category="lo", - direction="l", - }, - [0x2F80C]={ - category="lo", - direction="l", - }, - [0x2F80D]={ - category="lo", - direction="l", - }, - [0x2F80E]={ - category="lo", - direction="l", - }, - [0x2F80F]={ - category="lo", - direction="l", - }, - [0x2F810]={ - category="lo", - direction="l", - }, - [0x2F811]={ - category="lo", - direction="l", - }, - [0x2F812]={ - category="lo", - direction="l", - }, - [0x2F813]={ - category="lo", - direction="l", - }, - [0x2F814]={ - category="lo", - direction="l", - }, - [0x2F815]={ - category="lo", - direction="l", - }, - [0x2F816]={ - category="lo", - direction="l", - }, - [0x2F817]={ - category="lo", - direction="l", - }, - [0x2F818]={ - category="lo", - direction="l", - }, - [0x2F819]={ - category="lo", - direction="l", - }, - [0x2F81A]={ - category="lo", - direction="l", - }, - [0x2F81B]={ - category="lo", - direction="l", - }, - [0x2F81C]={ - category="lo", - direction="l", - }, - [0x2F81D]={ - category="lo", - direction="l", - }, - [0x2F81E]={ - category="lo", - direction="l", - }, - [0x2F81F]={ - category="lo", - direction="l", - }, - [0x2F820]={ - category="lo", - direction="l", - }, - [0x2F821]={ - category="lo", - direction="l", - }, - [0x2F822]={ - category="lo", - direction="l", - }, - [0x2F823]={ - category="lo", - direction="l", - }, - [0x2F824]={ - category="lo", - direction="l", - }, - [0x2F825]={ - category="lo", - direction="l", - }, - [0x2F826]={ - category="lo", - direction="l", - }, - [0x2F827]={ - category="lo", - direction="l", - }, - [0x2F828]={ - category="lo", - direction="l", - }, - [0x2F829]={ - category="lo", - direction="l", - }, - [0x2F82A]={ - category="lo", - direction="l", - }, - [0x2F82B]={ - category="lo", - direction="l", - }, - [0x2F82C]={ - category="lo", - direction="l", - }, - [0x2F82D]={ - category="lo", - direction="l", - }, - [0x2F82E]={ - category="lo", - direction="l", - }, - [0x2F82F]={ - category="lo", - direction="l", - }, - [0x2F830]={ - category="lo", - direction="l", - }, - [0x2F831]={ - category="lo", - direction="l", - }, - [0x2F832]={ - category="lo", - direction="l", - }, - [0x2F833]={ - category="lo", - direction="l", - }, - [0x2F834]={ - category="lo", - direction="l", - }, - [0x2F835]={ - category="lo", - direction="l", - }, - [0x2F836]={ - category="lo", - direction="l", - }, - [0x2F837]={ - category="lo", - direction="l", - }, - [0x2F838]={ - category="lo", - direction="l", - }, - [0x2F839]={ - category="lo", - direction="l", - }, - [0x2F83A]={ - category="lo", - direction="l", - }, - [0x2F83B]={ - category="lo", - direction="l", - }, - [0x2F83C]={ - category="lo", - direction="l", - }, - [0x2F83D]={ - category="lo", - direction="l", - }, - [0x2F83E]={ - category="lo", - direction="l", - }, - [0x2F83F]={ - category="lo", - direction="l", - }, - [0x2F840]={ - category="lo", - direction="l", - }, - [0x2F841]={ - category="lo", - direction="l", - }, - [0x2F842]={ - category="lo", - direction="l", - }, - [0x2F843]={ - category="lo", - direction="l", - }, - [0x2F844]={ - category="lo", - direction="l", - }, - [0x2F845]={ - category="lo", - direction="l", - }, - [0x2F846]={ - category="lo", - direction="l", - }, - [0x2F847]={ - category="lo", - direction="l", - }, - [0x2F848]={ - category="lo", - direction="l", - }, - [0x2F849]={ - category="lo", - direction="l", - }, - [0x2F84A]={ - category="lo", - direction="l", - }, - [0x2F84B]={ - category="lo", - direction="l", - }, - [0x2F84C]={ - category="lo", - direction="l", - }, - [0x2F84D]={ - category="lo", - direction="l", - }, - [0x2F84E]={ - category="lo", - direction="l", - }, - [0x2F84F]={ - category="lo", - direction="l", - }, - [0x2F850]={ - category="lo", - direction="l", - }, - [0x2F851]={ - category="lo", - direction="l", - }, - [0x2F852]={ - category="lo", - direction="l", - }, - [0x2F853]={ - category="lo", - direction="l", - }, - [0x2F854]={ - category="lo", - direction="l", - }, - [0x2F855]={ - category="lo", - direction="l", - }, - [0x2F856]={ - category="lo", - direction="l", - }, - [0x2F857]={ - category="lo", - direction="l", - }, - [0x2F858]={ - category="lo", - direction="l", - }, - [0x2F859]={ - category="lo", - direction="l", - }, - [0x2F85A]={ - category="lo", - direction="l", - }, - [0x2F85B]={ - category="lo", - direction="l", - }, - [0x2F85C]={ - category="lo", - direction="l", - }, - [0x2F85D]={ - category="lo", - direction="l", - }, - [0x2F85E]={ - category="lo", - direction="l", - }, - [0x2F85F]={ - category="lo", - direction="l", - }, - [0x2F860]={ - category="lo", - direction="l", - }, - [0x2F861]={ - category="lo", - direction="l", - }, - [0x2F862]={ - category="lo", - direction="l", - }, - [0x2F863]={ - category="lo", - direction="l", - }, - [0x2F864]={ - category="lo", - direction="l", - }, - [0x2F865]={ - category="lo", - direction="l", - }, - [0x2F866]={ - category="lo", - direction="l", - }, - [0x2F867]={ - category="lo", - direction="l", - }, - [0x2F868]={ - category="lo", - direction="l", - }, - [0x2F869]={ - category="lo", - direction="l", - }, - [0x2F86A]={ - category="lo", - direction="l", - }, - [0x2F86B]={ - category="lo", - direction="l", - }, - [0x2F86C]={ - category="lo", - direction="l", - }, - [0x2F86D]={ - category="lo", - direction="l", - }, - [0x2F86E]={ - category="lo", - direction="l", - }, - [0x2F86F]={ - category="lo", - direction="l", - }, - [0x2F870]={ - category="lo", - direction="l", - }, - [0x2F871]={ - category="lo", - direction="l", - }, - [0x2F872]={ - category="lo", - direction="l", - }, - [0x2F873]={ - category="lo", - direction="l", - }, - [0x2F874]={ - category="lo", - direction="l", - }, - [0x2F875]={ - category="lo", - direction="l", - }, - [0x2F876]={ - category="lo", - direction="l", - }, - [0x2F877]={ - category="lo", - direction="l", - }, - [0x2F878]={ - category="lo", - direction="l", - }, - [0x2F879]={ - category="lo", - direction="l", - }, - [0x2F87A]={ - category="lo", - direction="l", - }, - [0x2F87B]={ - category="lo", - direction="l", - }, - [0x2F87C]={ - category="lo", - direction="l", - }, - [0x2F87D]={ - category="lo", - direction="l", - }, - [0x2F87E]={ - category="lo", - direction="l", - }, - [0x2F87F]={ - category="lo", - direction="l", - }, - [0x2F880]={ - category="lo", - direction="l", - }, - [0x2F881]={ - category="lo", - direction="l", - }, - [0x2F882]={ - category="lo", - direction="l", - }, - [0x2F883]={ - category="lo", - direction="l", - }, - [0x2F884]={ - category="lo", - direction="l", - }, - [0x2F885]={ - category="lo", - direction="l", - }, - [0x2F886]={ - category="lo", - direction="l", - }, - [0x2F887]={ - category="lo", - direction="l", - }, - [0x2F888]={ - category="lo", - direction="l", - }, - [0x2F889]={ - category="lo", - direction="l", - }, - [0x2F88A]={ - category="lo", - direction="l", - }, - [0x2F88B]={ - category="lo", - direction="l", - }, - [0x2F88C]={ - category="lo", - direction="l", - }, - [0x2F88D]={ - category="lo", - direction="l", - }, - [0x2F88E]={ - category="lo", - direction="l", - }, - [0x2F88F]={ - category="lo", - direction="l", - }, - [0x2F890]={ - category="lo", - direction="l", - }, - [0x2F891]={ - category="lo", - direction="l", - }, - [0x2F892]={ - category="lo", - direction="l", - }, - [0x2F893]={ - category="lo", - direction="l", - }, - [0x2F894]={ - category="lo", - direction="l", - }, - [0x2F895]={ - category="lo", - direction="l", - }, - [0x2F896]={ - category="lo", - direction="l", - }, - [0x2F897]={ - category="lo", - direction="l", - }, - [0x2F898]={ - category="lo", - direction="l", - }, - [0x2F899]={ - category="lo", - direction="l", - }, - [0x2F89A]={ - category="lo", - direction="l", - }, - [0x2F89B]={ - category="lo", - direction="l", - }, - [0x2F89C]={ - category="lo", - direction="l", - }, - [0x2F89D]={ - category="lo", - direction="l", - }, - [0x2F89E]={ - category="lo", - direction="l", - }, - [0x2F89F]={ - category="lo", - direction="l", - }, - [0x2F8A0]={ - category="lo", - direction="l", - }, - [0x2F8A1]={ - category="lo", - direction="l", - }, - [0x2F8A2]={ - category="lo", - direction="l", - }, - [0x2F8A3]={ - category="lo", - direction="l", - }, - [0x2F8A4]={ - category="lo", - direction="l", - }, - [0x2F8A5]={ - category="lo", - direction="l", - }, - [0x2F8A6]={ - category="lo", - direction="l", - }, - [0x2F8A7]={ - category="lo", - direction="l", - }, - [0x2F8A8]={ - category="lo", - direction="l", - }, - [0x2F8A9]={ - category="lo", - direction="l", - }, - [0x2F8AA]={ - category="lo", - direction="l", - }, - [0x2F8AB]={ - category="lo", - direction="l", - }, - [0x2F8AC]={ - category="lo", - direction="l", - }, - [0x2F8AD]={ - category="lo", - direction="l", - }, - [0x2F8AE]={ - category="lo", - direction="l", - }, - [0x2F8AF]={ - category="lo", - direction="l", - }, - [0x2F8B0]={ - category="lo", - direction="l", - }, - [0x2F8B1]={ - category="lo", - direction="l", - }, - [0x2F8B2]={ - category="lo", - direction="l", - }, - [0x2F8B3]={ - category="lo", - direction="l", - }, - [0x2F8B4]={ - category="lo", - direction="l", - }, - [0x2F8B5]={ - category="lo", - direction="l", - }, - [0x2F8B6]={ - category="lo", - direction="l", - }, - [0x2F8B7]={ - category="lo", - direction="l", - }, - [0x2F8B8]={ - category="lo", - direction="l", - }, - [0x2F8B9]={ - category="lo", - direction="l", - }, - [0x2F8BA]={ - category="lo", - direction="l", - }, - [0x2F8BB]={ - category="lo", - direction="l", - }, - [0x2F8BC]={ - category="lo", - direction="l", - }, - [0x2F8BD]={ - category="lo", - direction="l", - }, - [0x2F8BE]={ - category="lo", - direction="l", - }, - [0x2F8BF]={ - category="lo", - direction="l", - }, - [0x2F8C0]={ - category="lo", - direction="l", - }, - [0x2F8C1]={ - category="lo", - direction="l", - }, - [0x2F8C2]={ - category="lo", - direction="l", - }, - [0x2F8C3]={ - category="lo", - direction="l", - }, - [0x2F8C4]={ - category="lo", - direction="l", - }, - [0x2F8C5]={ - category="lo", - direction="l", - }, - [0x2F8C6]={ - category="lo", - direction="l", - }, - [0x2F8C7]={ - category="lo", - direction="l", - }, - [0x2F8C8]={ - category="lo", - direction="l", - }, - [0x2F8C9]={ - category="lo", - direction="l", - }, - [0x2F8CA]={ - category="lo", - direction="l", - }, - [0x2F8CB]={ - category="lo", - direction="l", - }, - [0x2F8CC]={ - category="lo", - direction="l", - }, - [0x2F8CD]={ - category="lo", - direction="l", - }, - [0x2F8CE]={ - category="lo", - direction="l", - }, - [0x2F8CF]={ - category="lo", - direction="l", - }, - [0x2F8D0]={ - category="lo", - direction="l", - }, - [0x2F8D1]={ - category="lo", - direction="l", - }, - [0x2F8D2]={ - category="lo", - direction="l", - }, - [0x2F8D3]={ - category="lo", - direction="l", - }, - [0x2F8D4]={ - category="lo", - direction="l", - }, - [0x2F8D5]={ - category="lo", - direction="l", - }, - [0x2F8D6]={ - category="lo", - direction="l", - }, - [0x2F8D7]={ - category="lo", - direction="l", - }, - [0x2F8D8]={ - category="lo", - direction="l", - }, - [0x2F8D9]={ - category="lo", - direction="l", - }, - [0x2F8DA]={ - category="lo", - direction="l", - }, - [0x2F8DB]={ - category="lo", - direction="l", - }, - [0x2F8DC]={ - category="lo", - direction="l", - }, - [0x2F8DD]={ - category="lo", - direction="l", - }, - [0x2F8DE]={ - category="lo", - direction="l", - }, - [0x2F8DF]={ - category="lo", - direction="l", - }, - [0x2F8E0]={ - category="lo", - direction="l", - }, - [0x2F8E1]={ - category="lo", - direction="l", - }, - [0x2F8E2]={ - category="lo", - direction="l", - }, - [0x2F8E3]={ - category="lo", - direction="l", - }, - [0x2F8E4]={ - category="lo", - direction="l", - }, - [0x2F8E5]={ - category="lo", - direction="l", - }, - [0x2F8E6]={ - category="lo", - direction="l", - }, - [0x2F8E7]={ - category="lo", - direction="l", - }, - [0x2F8E8]={ - category="lo", - direction="l", - }, - [0x2F8E9]={ - category="lo", - direction="l", - }, - [0x2F8EA]={ - category="lo", - direction="l", - }, - [0x2F8EB]={ - category="lo", - direction="l", - }, - [0x2F8EC]={ - category="lo", - direction="l", - }, - [0x2F8ED]={ - category="lo", - direction="l", - }, - [0x2F8EE]={ - category="lo", - direction="l", - }, - [0x2F8EF]={ - category="lo", - direction="l", - }, - [0x2F8F0]={ - category="lo", - direction="l", - }, - [0x2F8F1]={ - category="lo", - direction="l", - }, - [0x2F8F2]={ - category="lo", - direction="l", - }, - [0x2F8F3]={ - category="lo", - direction="l", - }, - [0x2F8F4]={ - category="lo", - direction="l", - }, - [0x2F8F5]={ - category="lo", - direction="l", - }, - [0x2F8F6]={ - category="lo", - direction="l", - }, - [0x2F8F7]={ - category="lo", - direction="l", - }, - [0x2F8F8]={ - category="lo", - direction="l", - }, - [0x2F8F9]={ - category="lo", - direction="l", - }, - [0x2F8FA]={ - category="lo", - direction="l", - }, - [0x2F8FB]={ - category="lo", - direction="l", - }, - [0x2F8FC]={ - category="lo", - direction="l", - }, - [0x2F8FD]={ - category="lo", - direction="l", - }, - [0x2F8FE]={ - category="lo", - direction="l", - }, - [0x2F8FF]={ - category="lo", - direction="l", - }, - [0x2F900]={ - category="lo", - direction="l", - }, - [0x2F901]={ - category="lo", - direction="l", - }, - [0x2F902]={ - category="lo", - direction="l", - }, - [0x2F903]={ - category="lo", - direction="l", - }, - [0x2F904]={ - category="lo", - direction="l", - }, - [0x2F905]={ - category="lo", - direction="l", - }, - [0x2F906]={ - category="lo", - direction="l", - }, - [0x2F907]={ - category="lo", - direction="l", - }, - [0x2F908]={ - category="lo", - direction="l", - }, - [0x2F909]={ - category="lo", - direction="l", - }, - [0x2F90A]={ - category="lo", - direction="l", - }, - [0x2F90B]={ - category="lo", - direction="l", - }, - [0x2F90C]={ - category="lo", - direction="l", - }, - [0x2F90D]={ - category="lo", - direction="l", - }, - [0x2F90E]={ - category="lo", - direction="l", - }, - [0x2F90F]={ - category="lo", - direction="l", - }, - [0x2F910]={ - category="lo", - direction="l", - }, - [0x2F911]={ - category="lo", - direction="l", - }, - [0x2F912]={ - category="lo", - direction="l", - }, - [0x2F913]={ - category="lo", - direction="l", - }, - [0x2F914]={ - category="lo", - direction="l", - }, - [0x2F915]={ - category="lo", - direction="l", - }, - [0x2F916]={ - category="lo", - direction="l", - }, - [0x2F917]={ - category="lo", - direction="l", - }, - [0x2F918]={ - category="lo", - direction="l", - }, - [0x2F919]={ - category="lo", - direction="l", - }, - [0x2F91A]={ - category="lo", - direction="l", - }, - [0x2F91B]={ - category="lo", - direction="l", - }, - [0x2F91C]={ - category="lo", - direction="l", - }, - [0x2F91D]={ - category="lo", - direction="l", - }, - [0x2F91E]={ - category="lo", - direction="l", - }, - [0x2F91F]={ - category="lo", - direction="l", - }, - [0x2F920]={ - category="lo", - direction="l", - }, - [0x2F921]={ - category="lo", - direction="l", - }, - [0x2F922]={ - category="lo", - direction="l", - }, - [0x2F923]={ - category="lo", - direction="l", - }, - [0x2F924]={ - category="lo", - direction="l", - }, - [0x2F925]={ - category="lo", - direction="l", - }, - [0x2F926]={ - category="lo", - direction="l", - }, - [0x2F927]={ - category="lo", - direction="l", - }, - [0x2F928]={ - category="lo", - direction="l", - }, - [0x2F929]={ - category="lo", - direction="l", - }, - [0x2F92A]={ - category="lo", - direction="l", - }, - [0x2F92B]={ - category="lo", - direction="l", - }, - [0x2F92C]={ - category="lo", - direction="l", - }, - [0x2F92D]={ - category="lo", - direction="l", - }, - [0x2F92E]={ - category="lo", - direction="l", - }, - [0x2F92F]={ - category="lo", - direction="l", - }, - [0x2F930]={ - category="lo", - direction="l", - }, - [0x2F931]={ - category="lo", - direction="l", - }, - [0x2F932]={ - category="lo", - direction="l", - }, - [0x2F933]={ - category="lo", - direction="l", - }, - [0x2F934]={ - category="lo", - direction="l", - }, - [0x2F935]={ - category="lo", - direction="l", - }, - [0x2F936]={ - category="lo", - direction="l", - }, - [0x2F937]={ - category="lo", - direction="l", - }, - [0x2F938]={ - category="lo", - direction="l", - }, - [0x2F939]={ - category="lo", - direction="l", - }, - [0x2F93A]={ - category="lo", - direction="l", - }, - [0x2F93B]={ - category="lo", - direction="l", - }, - [0x2F93C]={ - category="lo", - direction="l", - }, - [0x2F93D]={ - category="lo", - direction="l", - }, - [0x2F93E]={ - category="lo", - direction="l", - }, - [0x2F93F]={ - category="lo", - direction="l", - }, - [0x2F940]={ - category="lo", - direction="l", - }, - [0x2F941]={ - category="lo", - direction="l", - }, - [0x2F942]={ - category="lo", - direction="l", - }, - [0x2F943]={ - category="lo", - direction="l", - }, - [0x2F944]={ - category="lo", - direction="l", - }, - [0x2F945]={ - category="lo", - direction="l", - }, - [0x2F946]={ - category="lo", - direction="l", - }, - [0x2F947]={ - category="lo", - direction="l", - }, - [0x2F948]={ - category="lo", - direction="l", - }, - [0x2F949]={ - category="lo", - direction="l", - }, - [0x2F94A]={ - category="lo", - direction="l", - }, - [0x2F94B]={ - category="lo", - direction="l", - }, - [0x2F94C]={ - category="lo", - direction="l", - }, - [0x2F94D]={ - category="lo", - direction="l", - }, - [0x2F94E]={ - category="lo", - direction="l", - }, - [0x2F94F]={ - category="lo", - direction="l", - }, - [0x2F950]={ - category="lo", - direction="l", - }, - [0x2F951]={ - category="lo", - direction="l", - }, - [0x2F952]={ - category="lo", - direction="l", - }, - [0x2F953]={ - category="lo", - direction="l", - }, - [0x2F954]={ - category="lo", - direction="l", - }, - [0x2F955]={ - category="lo", - direction="l", - }, - [0x2F956]={ - category="lo", - direction="l", - }, - [0x2F957]={ - category="lo", - direction="l", - }, - [0x2F958]={ - category="lo", - direction="l", - }, - [0x2F959]={ - category="lo", - direction="l", - }, - [0x2F95A]={ - category="lo", - direction="l", - }, - [0x2F95B]={ - category="lo", - direction="l", - }, - [0x2F95C]={ - category="lo", - direction="l", - }, - [0x2F95D]={ - category="lo", - direction="l", - }, - [0x2F95E]={ - category="lo", - direction="l", - }, - [0x2F95F]={ - category="lo", - direction="l", - }, - [0x2F960]={ - category="lo", - direction="l", - }, - [0x2F961]={ - category="lo", - direction="l", - }, - [0x2F962]={ - category="lo", - direction="l", - }, - [0x2F963]={ - category="lo", - direction="l", - }, - [0x2F964]={ - category="lo", - direction="l", - }, - [0x2F965]={ - category="lo", - direction="l", - }, - [0x2F966]={ - category="lo", - direction="l", - }, - [0x2F967]={ - category="lo", - direction="l", - }, - [0x2F968]={ - category="lo", - direction="l", - }, - [0x2F969]={ - category="lo", - direction="l", - }, - [0x2F96A]={ - category="lo", - direction="l", - }, - [0x2F96B]={ - category="lo", - direction="l", - }, - [0x2F96C]={ - category="lo", - direction="l", - }, - [0x2F96D]={ - category="lo", - direction="l", - }, - [0x2F96E]={ - category="lo", - direction="l", - }, - [0x2F96F]={ - category="lo", - direction="l", - }, - [0x2F970]={ - category="lo", - direction="l", - }, - [0x2F971]={ - category="lo", - direction="l", - }, - [0x2F972]={ - category="lo", - direction="l", - }, - [0x2F973]={ - category="lo", - direction="l", - }, - [0x2F974]={ - category="lo", - direction="l", - }, - [0x2F975]={ - category="lo", - direction="l", - }, - [0x2F976]={ - category="lo", - direction="l", - }, - [0x2F977]={ - category="lo", - direction="l", - }, - [0x2F978]={ - category="lo", - direction="l", - }, - [0x2F979]={ - category="lo", - direction="l", - }, - [0x2F97A]={ - category="lo", - direction="l", - }, - [0x2F97B]={ - category="lo", - direction="l", - }, - [0x2F97C]={ - category="lo", - direction="l", - }, - [0x2F97D]={ - category="lo", - direction="l", - }, - [0x2F97E]={ - category="lo", - direction="l", - }, - [0x2F97F]={ - category="lo", - direction="l", - }, - [0x2F980]={ - category="lo", - direction="l", - }, - [0x2F981]={ - category="lo", - direction="l", - }, - [0x2F982]={ - category="lo", - direction="l", - }, - [0x2F983]={ - category="lo", - direction="l", - }, - [0x2F984]={ - category="lo", - direction="l", - }, - [0x2F985]={ - category="lo", - direction="l", - }, - [0x2F986]={ - category="lo", - direction="l", - }, - [0x2F987]={ - category="lo", - direction="l", - }, - [0x2F988]={ - category="lo", - direction="l", - }, - [0x2F989]={ - category="lo", - direction="l", - }, - [0x2F98A]={ - category="lo", - direction="l", - }, - [0x2F98B]={ - category="lo", - direction="l", - }, - [0x2F98C]={ - category="lo", - direction="l", - }, - [0x2F98D]={ - category="lo", - direction="l", - }, - [0x2F98E]={ - category="lo", - direction="l", - }, - [0x2F98F]={ - category="lo", - direction="l", - }, - [0x2F990]={ - category="lo", - direction="l", - }, - [0x2F991]={ - category="lo", - direction="l", - }, - [0x2F992]={ - category="lo", - direction="l", - }, - [0x2F993]={ - category="lo", - direction="l", - }, - [0x2F994]={ - category="lo", - direction="l", - }, - [0x2F995]={ - category="lo", - direction="l", - }, - [0x2F996]={ - category="lo", - direction="l", - }, - [0x2F997]={ - category="lo", - direction="l", - }, - [0x2F998]={ - category="lo", - direction="l", - }, - [0x2F999]={ - category="lo", - direction="l", - }, - [0x2F99A]={ - category="lo", - direction="l", - }, - [0x2F99B]={ - category="lo", - direction="l", - }, - [0x2F99C]={ - category="lo", - direction="l", - }, - [0x2F99D]={ - category="lo", - direction="l", - }, - [0x2F99E]={ - category="lo", - direction="l", - }, - [0x2F99F]={ - category="lo", - direction="l", - }, - [0x2F9A0]={ - category="lo", - direction="l", - }, - [0x2F9A1]={ - category="lo", - direction="l", - }, - [0x2F9A2]={ - category="lo", - direction="l", - }, - [0x2F9A3]={ - category="lo", - direction="l", - }, - [0x2F9A4]={ - category="lo", - direction="l", - }, - [0x2F9A5]={ - category="lo", - direction="l", - }, - [0x2F9A6]={ - category="lo", - direction="l", - }, - [0x2F9A7]={ - category="lo", - direction="l", - }, - [0x2F9A8]={ - category="lo", - direction="l", - }, - [0x2F9A9]={ - category="lo", - direction="l", - }, - [0x2F9AA]={ - category="lo", - direction="l", - }, - [0x2F9AB]={ - category="lo", - direction="l", - }, - [0x2F9AC]={ - category="lo", - direction="l", - }, - [0x2F9AD]={ - category="lo", - direction="l", - }, - [0x2F9AE]={ - category="lo", - direction="l", - }, - [0x2F9AF]={ - category="lo", - direction="l", - }, - [0x2F9B0]={ - category="lo", - direction="l", - }, - [0x2F9B1]={ - category="lo", - direction="l", - }, - [0x2F9B2]={ - category="lo", - direction="l", - }, - [0x2F9B3]={ - category="lo", - direction="l", - }, - [0x2F9B4]={ - category="lo", - direction="l", - }, - [0x2F9B5]={ - category="lo", - direction="l", - }, - [0x2F9B6]={ - category="lo", - direction="l", - }, - [0x2F9B7]={ - category="lo", - direction="l", - }, - [0x2F9B8]={ - category="lo", - direction="l", - }, - [0x2F9B9]={ - category="lo", - direction="l", - }, - [0x2F9BA]={ - category="lo", - direction="l", - }, - [0x2F9BB]={ - category="lo", - direction="l", - }, - [0x2F9BC]={ - category="lo", - direction="l", - }, - [0x2F9BD]={ - category="lo", - direction="l", - }, - [0x2F9BE]={ - category="lo", - direction="l", - }, - [0x2F9BF]={ - category="lo", - direction="l", - }, - [0x2F9C0]={ - category="lo", - direction="l", - }, - [0x2F9C1]={ - category="lo", - direction="l", - }, - [0x2F9C2]={ - category="lo", - direction="l", - }, - [0x2F9C3]={ - category="lo", - direction="l", - }, - [0x2F9C4]={ - category="lo", - direction="l", - }, - [0x2F9C5]={ - category="lo", - direction="l", - }, - [0x2F9C6]={ - category="lo", - direction="l", - }, - [0x2F9C7]={ - category="lo", - direction="l", - }, - [0x2F9C8]={ - category="lo", - direction="l", - }, - [0x2F9C9]={ - category="lo", - direction="l", - }, - [0x2F9CA]={ - category="lo", - direction="l", - }, - [0x2F9CB]={ - category="lo", - direction="l", - }, - [0x2F9CC]={ - category="lo", - direction="l", - }, - [0x2F9CD]={ - category="lo", - direction="l", - }, - [0x2F9CE]={ - category="lo", - direction="l", - }, - [0x2F9CF]={ - category="lo", - direction="l", - }, - [0x2F9D0]={ - category="lo", - direction="l", - }, - [0x2F9D1]={ - category="lo", - direction="l", - }, - [0x2F9D2]={ - category="lo", - direction="l", - }, - [0x2F9D3]={ - category="lo", - direction="l", - }, - [0x2F9D4]={ - category="lo", - direction="l", - }, - [0x2F9D5]={ - category="lo", - direction="l", - }, - [0x2F9D6]={ - category="lo", - direction="l", - }, - [0x2F9D7]={ - category="lo", - direction="l", - }, - [0x2F9D8]={ - category="lo", - direction="l", - }, - [0x2F9D9]={ - category="lo", - direction="l", - }, - [0x2F9DA]={ - category="lo", - direction="l", - }, - [0x2F9DB]={ - category="lo", - direction="l", - }, - [0x2F9DC]={ - category="lo", - direction="l", - }, - [0x2F9DD]={ - category="lo", - direction="l", - }, - [0x2F9DE]={ - category="lo", - direction="l", - }, - [0x2F9DF]={ - category="lo", - direction="l", - }, - [0x2F9E0]={ - category="lo", - direction="l", - }, - [0x2F9E1]={ - category="lo", - direction="l", - }, - [0x2F9E2]={ - category="lo", - direction="l", - }, - [0x2F9E3]={ - category="lo", - direction="l", - }, - [0x2F9E4]={ - category="lo", - direction="l", - }, - [0x2F9E5]={ - category="lo", - direction="l", - }, - [0x2F9E6]={ - category="lo", - direction="l", - }, - [0x2F9E7]={ - category="lo", - direction="l", - }, - [0x2F9E8]={ - category="lo", - direction="l", - }, - [0x2F9E9]={ - category="lo", - direction="l", - }, - [0x2F9EA]={ - category="lo", - direction="l", - }, - [0x2F9EB]={ - category="lo", - direction="l", - }, - [0x2F9EC]={ - category="lo", - direction="l", - }, - [0x2F9ED]={ - category="lo", - direction="l", - }, - [0x2F9EE]={ - category="lo", - direction="l", - }, - [0x2F9EF]={ - category="lo", - direction="l", - }, - [0x2F9F0]={ - category="lo", - direction="l", - }, - [0x2F9F1]={ - category="lo", - direction="l", - }, - [0x2F9F2]={ - category="lo", - direction="l", - }, - [0x2F9F3]={ - category="lo", - direction="l", - }, - [0x2F9F4]={ - category="lo", - direction="l", - }, - [0x2F9F5]={ - category="lo", - direction="l", - }, - [0x2F9F6]={ - category="lo", - direction="l", - }, - [0x2F9F7]={ - category="lo", - direction="l", - }, - [0x2F9F8]={ - category="lo", - direction="l", - }, - [0x2F9F9]={ - category="lo", - direction="l", - }, - [0x2F9FA]={ - category="lo", - direction="l", - }, - [0x2F9FB]={ - category="lo", - direction="l", - }, - [0x2F9FC]={ - category="lo", - direction="l", - }, - [0x2F9FD]={ - category="lo", - direction="l", - }, - [0x2F9FE]={ - category="lo", - direction="l", - }, - [0x2F9FF]={ - category="lo", - direction="l", - }, - [0x2FA00]={ - category="lo", - direction="l", - }, - [0x2FA01]={ - category="lo", - direction="l", - }, - [0x2FA02]={ - category="lo", - direction="l", - }, - [0x2FA03]={ - category="lo", - direction="l", - }, - [0x2FA04]={ - category="lo", - direction="l", - }, - [0x2FA05]={ - category="lo", - direction="l", - }, - [0x2FA06]={ - category="lo", - direction="l", - }, - [0x2FA07]={ - category="lo", - direction="l", - }, - [0x2FA08]={ - category="lo", - direction="l", - }, - [0x2FA09]={ - category="lo", - direction="l", - }, - [0x2FA0A]={ - category="lo", - direction="l", - }, - [0x2FA0B]={ - category="lo", - direction="l", - }, - [0x2FA0C]={ - category="lo", - direction="l", - }, - [0x2FA0D]={ - category="lo", - direction="l", - }, - [0x2FA0E]={ - category="lo", - direction="l", - }, - [0x2FA0F]={ - category="lo", - direction="l", - }, - [0x2FA10]={ - category="lo", - direction="l", - }, - [0x2FA11]={ - category="lo", - direction="l", - }, - [0x2FA12]={ - category="lo", - direction="l", - }, - [0x2FA13]={ - category="lo", - direction="l", - }, - [0x2FA14]={ - category="lo", - direction="l", - }, - [0x2FA15]={ - category="lo", - direction="l", - }, - [0x2FA16]={ - category="lo", - direction="l", - }, - [0x2FA17]={ - category="lo", - direction="l", - }, - [0x2FA18]={ - category="lo", - direction="l", - }, - [0x2FA19]={ - category="lo", - direction="l", - }, - [0x2FA1A]={ - category="lo", - direction="l", - }, - [0x2FA1B]={ - category="lo", - direction="l", - }, - [0x2FA1C]={ - category="lo", - direction="l", - }, - [0x2FA1D]={ - category="lo", - direction="l", - }, - [0xE0001]={ - category="cf", - direction="bn", - }, - [0xE0020]={ - category="cf", - direction="bn", - }, - [0xE0021]={ - category="cf", - direction="bn", - }, - [0xE0022]={ - category="cf", - direction="bn", - }, - [0xE0023]={ - category="cf", - direction="bn", - }, - [0xE0024]={ - category="cf", - direction="bn", - }, - [0xE0025]={ - category="cf", - direction="bn", - }, - [0xE0026]={ - category="cf", - direction="bn", - }, - [0xE0027]={ - category="cf", - direction="bn", - }, - [0xE0028]={ - category="cf", - direction="bn", - }, - [0xE0029]={ - category="cf", - direction="bn", - }, - [0xE002A]={ - category="cf", - direction="bn", - }, - [0xE002B]={ - category="cf", - direction="bn", - }, - [0xE002C]={ - category="cf", - direction="bn", - }, - [0xE002D]={ - category="cf", - direction="bn", - }, - [0xE002E]={ - category="cf", - direction="bn", - }, - [0xE002F]={ - category="cf", - direction="bn", - }, - [0xE0030]={ - category="cf", - direction="bn", - }, - [0xE0031]={ - category="cf", - direction="bn", - }, - [0xE0032]={ - category="cf", - direction="bn", - }, - [0xE0033]={ - category="cf", - direction="bn", - }, - [0xE0034]={ - category="cf", - direction="bn", - }, - [0xE0035]={ - category="cf", - direction="bn", - }, - [0xE0036]={ - category="cf", - direction="bn", - }, - [0xE0037]={ - category="cf", - direction="bn", - }, - [0xE0038]={ - category="cf", - direction="bn", - }, - [0xE0039]={ - category="cf", - direction="bn", - }, - [0xE003A]={ - category="cf", - direction="bn", - }, - [0xE003B]={ - category="cf", - direction="bn", - }, - [0xE003C]={ - category="cf", - direction="bn", - }, - [0xE003D]={ - category="cf", - direction="bn", - }, - [0xE003E]={ - category="cf", - direction="bn", - }, - [0xE003F]={ - category="cf", - direction="bn", - }, - [0xE0040]={ - category="cf", - direction="bn", - }, - [0xE0041]={ - category="cf", - direction="bn", - }, - [0xE0042]={ - category="cf", - direction="bn", - }, - [0xE0043]={ - category="cf", - direction="bn", - }, - [0xE0044]={ - category="cf", - direction="bn", - }, - [0xE0045]={ - category="cf", - direction="bn", - }, - [0xE0046]={ - category="cf", - direction="bn", - }, - [0xE0047]={ - category="cf", - direction="bn", - }, - [0xE0048]={ - category="cf", - direction="bn", - }, - [0xE0049]={ - category="cf", - direction="bn", - }, - [0xE004A]={ - category="cf", - direction="bn", - }, - [0xE004B]={ - category="cf", - direction="bn", - }, - [0xE004C]={ - category="cf", - direction="bn", - }, - [0xE004D]={ - category="cf", - direction="bn", - }, - [0xE004E]={ - category="cf", - direction="bn", - }, - [0xE004F]={ - category="cf", - direction="bn", - }, - [0xE0050]={ - category="cf", - direction="bn", - }, - [0xE0051]={ - category="cf", - direction="bn", - }, - [0xE0052]={ - category="cf", - direction="bn", - }, - [0xE0053]={ - category="cf", - direction="bn", - }, - [0xE0054]={ - category="cf", - direction="bn", - }, - [0xE0055]={ - category="cf", - direction="bn", - }, - [0xE0056]={ - category="cf", - direction="bn", - }, - [0xE0057]={ - category="cf", - direction="bn", - }, - [0xE0058]={ - category="cf", - direction="bn", - }, - [0xE0059]={ - category="cf", - direction="bn", - }, - [0xE005A]={ - category="cf", - direction="bn", - }, - [0xE005B]={ - category="cf", - direction="bn", - }, - [0xE005C]={ - category="cf", - direction="bn", - }, - [0xE005D]={ - category="cf", - direction="bn", - }, - [0xE005E]={ - category="cf", - direction="bn", - }, - [0xE005F]={ - category="cf", - direction="bn", - }, - [0xE0060]={ - category="cf", - direction="bn", - }, - [0xE0061]={ - category="cf", - direction="bn", - }, - [0xE0062]={ - category="cf", - direction="bn", - }, - [0xE0063]={ - category="cf", - direction="bn", - }, - [0xE0064]={ - category="cf", - direction="bn", - }, - [0xE0065]={ - category="cf", - direction="bn", - }, - [0xE0066]={ - category="cf", - direction="bn", - }, - [0xE0067]={ - category="cf", - direction="bn", - }, - [0xE0068]={ - category="cf", - direction="bn", - }, - [0xE0069]={ - category="cf", - direction="bn", - }, - [0xE006A]={ - category="cf", - direction="bn", - }, - [0xE006B]={ - category="cf", - direction="bn", - }, - [0xE006C]={ - category="cf", - direction="bn", - }, - [0xE006D]={ - category="cf", - direction="bn", - }, - [0xE006E]={ - category="cf", - direction="bn", - }, - [0xE006F]={ - category="cf", - direction="bn", - }, - [0xE0070]={ - category="cf", - direction="bn", - }, - [0xE0071]={ - category="cf", - direction="bn", - }, - [0xE0072]={ - category="cf", - direction="bn", - }, - [0xE0073]={ - category="cf", - direction="bn", - }, - [0xE0074]={ - category="cf", - direction="bn", - }, - [0xE0075]={ - category="cf", - direction="bn", - }, - [0xE0076]={ - category="cf", - direction="bn", - }, - [0xE0077]={ - category="cf", - direction="bn", - }, - [0xE0078]={ - category="cf", - direction="bn", - }, - [0xE0079]={ - category="cf", - direction="bn", - }, - [0xE007A]={ - category="cf", - direction="bn", - }, - [0xE007B]={ - category="cf", - direction="bn", - }, - [0xE007C]={ - category="cf", - direction="bn", - }, - [0xE007D]={ - category="cf", - direction="bn", - }, - [0xE007E]={ - category="cf", - direction="bn", - }, - [0xE007F]={ - category="cf", - direction="bn", - }, - characters={}, - classifiers={ - [0x600]=0x4, - [0x601]=0x4, - [0x602]=0x4, - [0x603]=0x4, - [0x604]=0x4, - [0x605]=0x4, - [0x606]=0x6, - [0x607]=0x6, - [0x608]=0x4, - [0x609]=0x6, - [0x60A]=0x6, - [0x60B]=0x4, - [0x60C]=0x6, - [0x60D]=0x6, - [0x60E]=0x6, - [0x60F]=0x6, - [0x610]=0x5, - [0x611]=0x5, - [0x612]=0x5, - [0x613]=0x5, - [0x614]=0x5, - [0x615]=0x5, - [0x616]=0x5, - [0x617]=0x5, - [0x618]=0x5, - [0x619]=0x5, - [0x61A]=0x5, - [0x61B]=0x6, - [0x61C]=0x6, - [0x61E]=0x6, - [0x61F]=0x6, - [0x620]=0x2, - [0x621]=0x4, - [0x622]=0x3, - [0x623]=0x3, - [0x624]=0x3, - [0x625]=0x3, - [0x626]=0x2, - [0x627]=0x3, - [0x628]=0x2, - [0x629]=0x3, - [0x62A]=0x2, - [0x62B]=0x2, - [0x62C]=0x2, - [0x62D]=0x2, - [0x62E]=0x2, - [0x62F]=0x3, - [0x630]=0x3, - [0x631]=0x3, - [0x632]=0x3, - [0x633]=0x2, - [0x634]=0x2, - [0x635]=0x2, - [0x636]=0x2, - [0x637]=0x2, - [0x638]=0x2, - [0x639]=0x2, - [0x63A]=0x2, - [0x63B]=0x2, - [0x63C]=0x2, - [0x63D]=0x2, - [0x63E]=0x2, - [0x63F]=0x2, - [0x640]=0x2, - [0x641]=0x2, - [0x642]=0x2, - [0x643]=0x2, - [0x644]=0x2, - [0x645]=0x2, - [0x646]=0x2, - [0x647]=0x2, - [0x648]=0x3, - [0x649]=0x2, - [0x64A]=0x2, - [0x64B]=0x5, - [0x64C]=0x5, - [0x64D]=0x5, - [0x64E]=0x5, - [0x64F]=0x5, - [0x650]=0x5, - [0x651]=0x5, - [0x652]=0x5, - [0x653]=0x5, - [0x654]=0x5, - [0x655]=0x5, - [0x656]=0x5, - [0x657]=0x5, - [0x658]=0x5, - [0x659]=0x5, - [0x65A]=0x5, - [0x65B]=0x5, - [0x65C]=0x5, - [0x65D]=0x5, - [0x65E]=0x5, - [0x65F]=0x5, - [0x660]=0x6, - [0x661]=0x6, - [0x662]=0x6, - [0x663]=0x6, - [0x664]=0x6, - [0x665]=0x6, - [0x666]=0x6, - [0x667]=0x6, - [0x668]=0x6, - [0x669]=0x6, - [0x66A]=0x6, - [0x66B]=0x6, - [0x66C]=0x6, - [0x66D]=0x6, - [0x66E]=0x2, - [0x66F]=0x2, - [0x670]=0x5, - [0x671]=0x3, - [0x672]=0x3, - [0x673]=0x3, - [0x674]=0x4, - [0x675]=0x3, - [0x676]=0x3, - [0x677]=0x3, - [0x678]=0x2, - [0x679]=0x2, - [0x67A]=0x2, - [0x67B]=0x2, - [0x67C]=0x2, - [0x67D]=0x2, - [0x67E]=0x2, - [0x67F]=0x2, - [0x680]=0x2, - [0x681]=0x2, - [0x682]=0x2, - [0x683]=0x2, - [0x684]=0x2, - [0x685]=0x2, - [0x686]=0x2, - [0x687]=0x2, - [0x688]=0x3, - [0x689]=0x3, - [0x68A]=0x3, - [0x68B]=0x3, - [0x68C]=0x3, - [0x68D]=0x3, - [0x68E]=0x3, - [0x68F]=0x3, - [0x690]=0x3, - [0x691]=0x3, - [0x692]=0x3, - [0x693]=0x3, - [0x694]=0x3, - [0x695]=0x3, - [0x696]=0x3, - [0x697]=0x3, - [0x698]=0x3, - [0x699]=0x3, - [0x69A]=0x2, - [0x69B]=0x2, - [0x69C]=0x2, - [0x69D]=0x2, - [0x69E]=0x2, - [0x69F]=0x2, - [0x6A0]=0x2, - [0x6A1]=0x2, - [0x6A2]=0x2, - [0x6A3]=0x2, - [0x6A4]=0x2, - [0x6A5]=0x2, - [0x6A6]=0x2, - [0x6A7]=0x2, - [0x6A8]=0x2, - [0x6A9]=0x2, - [0x6AA]=0x2, - [0x6AB]=0x2, - [0x6AC]=0x2, - [0x6AD]=0x2, - [0x6AE]=0x2, - [0x6AF]=0x2, - [0x6B0]=0x2, - [0x6B1]=0x2, - [0x6B2]=0x2, - [0x6B3]=0x2, - [0x6B4]=0x2, - [0x6B5]=0x2, - [0x6B6]=0x2, - [0x6B7]=0x2, - [0x6B8]=0x2, - [0x6B9]=0x2, - [0x6BA]=0x2, - [0x6BB]=0x2, - [0x6BC]=0x2, - [0x6BD]=0x2, - [0x6BE]=0x2, - [0x6BF]=0x2, - [0x6C0]=0x3, - [0x6C1]=0x2, - [0x6C2]=0x2, - [0x6C3]=0x3, - [0x6C4]=0x3, - [0x6C5]=0x3, - [0x6C6]=0x3, - [0x6C7]=0x3, - [0x6C8]=0x3, - [0x6C9]=0x3, - [0x6CA]=0x3, - [0x6CB]=0x3, - [0x6CC]=0x2, - [0x6CD]=0x3, - [0x6CE]=0x2, - [0x6CF]=0x3, - [0x6D0]=0x2, - [0x6D1]=0x2, - [0x6D2]=0x3, - [0x6D3]=0x3, - [0x6D4]=0x6, - [0x6D5]=0x3, - [0x6D6]=0x5, - [0x6D7]=0x5, - [0x6D8]=0x5, - [0x6D9]=0x5, - [0x6DA]=0x5, - [0x6DB]=0x5, - [0x6DC]=0x5, - [0x6DD]=0x4, - [0x6DE]=0x6, - [0x6DF]=0x5, - [0x6E0]=0x5, - [0x6E1]=0x5, - [0x6E2]=0x5, - [0x6E3]=0x5, - [0x6E4]=0x5, - [0x6E5]=0x6, - [0x6E6]=0x6, - [0x6E7]=0x5, - [0x6E8]=0x5, - [0x6E9]=0x6, - [0x6EA]=0x5, - [0x6EB]=0x5, - [0x6EC]=0x5, - [0x6ED]=0x5, - [0x6EE]=0x3, - [0x6EF]=0x3, - [0x6F0]=0x6, - [0x6F1]=0x6, - [0x6F2]=0x6, - [0x6F3]=0x6, - [0x6F4]=0x6, - [0x6F5]=0x6, - [0x6F6]=0x6, - [0x6F7]=0x6, - [0x6F8]=0x6, - [0x6F9]=0x6, - [0x6FA]=0x2, - [0x6FB]=0x2, - [0x6FC]=0x2, - [0x6FD]=0x6, - [0x6FE]=0x6, - [0x6FF]=0x2, - [0x700]=0x6, - [0x701]=0x6, - [0x702]=0x6, - [0x703]=0x6, - [0x704]=0x6, - [0x705]=0x6, - [0x706]=0x6, - [0x707]=0x6, - [0x708]=0x6, - [0x709]=0x6, - [0x70A]=0x6, - [0x70B]=0x6, - [0x70C]=0x6, - [0x70D]=0x6, - [0x70F]=0x6, - [0x710]=0x3, - [0x711]=0x5, - [0x712]=0x2, - [0x713]=0x2, - [0x714]=0x2, - [0x715]=0x3, - [0x716]=0x3, - [0x717]=0x3, - [0x718]=0x3, - [0x719]=0x3, - [0x71A]=0x2, - [0x71B]=0x2, - [0x71C]=0x2, - [0x71D]=0x2, - [0x71E]=0x3, - [0x71F]=0x2, - [0x720]=0x2, - [0x721]=0x2, - [0x722]=0x2, - [0x723]=0x2, - [0x724]=0x2, - [0x725]=0x2, - [0x726]=0x2, - [0x727]=0x2, - [0x728]=0x3, - [0x729]=0x2, - [0x72A]=0x3, - [0x72B]=0x2, - [0x72C]=0x3, - [0x72D]=0x2, - [0x72E]=0x2, - [0x72F]=0x3, - [0x730]=0x5, - [0x731]=0x5, - [0x732]=0x5, - [0x733]=0x5, - [0x734]=0x5, - [0x735]=0x5, - [0x736]=0x5, - [0x737]=0x5, - [0x738]=0x5, - [0x739]=0x5, - [0x73A]=0x5, - [0x73B]=0x5, - [0x73C]=0x5, - [0x73D]=0x5, - [0x73E]=0x5, - [0x73F]=0x5, - [0x740]=0x5, - [0x741]=0x5, - [0x742]=0x5, - [0x743]=0x5, - [0x744]=0x5, - [0x745]=0x5, - [0x746]=0x5, - [0x747]=0x5, - [0x748]=0x5, - [0x749]=0x5, - [0x74A]=0x5, - [0x74D]=0x3, - [0x74E]=0x2, - [0x74F]=0x2, - [0x750]=0x2, - [0x751]=0x2, - [0x752]=0x2, - [0x753]=0x2, - [0x754]=0x2, - [0x755]=0x2, - [0x756]=0x2, - [0x757]=0x2, - [0x758]=0x2, - [0x759]=0x3, - [0x75A]=0x3, - [0x75B]=0x3, - [0x75C]=0x2, - [0x75D]=0x2, - [0x75E]=0x2, - [0x75F]=0x2, - [0x760]=0x2, - [0x761]=0x2, - [0x762]=0x2, - [0x763]=0x2, - [0x764]=0x2, - [0x765]=0x2, - [0x766]=0x2, - [0x767]=0x2, - [0x768]=0x2, - [0x769]=0x2, - [0x76A]=0x2, - [0x76B]=0x3, - [0x76C]=0x3, - [0x76D]=0x2, - [0x76E]=0x2, - [0x76F]=0x2, - [0x770]=0x2, - [0x771]=0x3, - [0x772]=0x2, - [0x773]=0x3, - [0x774]=0x3, - [0x775]=0x2, - [0x776]=0x2, - [0x777]=0x2, - [0x778]=0x3, - [0x779]=0x3, - [0x77A]=0x2, - [0x77B]=0x2, - [0x77C]=0x2, - [0x77D]=0x2, - [0x77E]=0x2, - [0x77F]=0x2, - [0x7C0]=0x6, - [0x7C1]=0x6, - [0x7C2]=0x6, - [0x7C3]=0x6, - [0x7C4]=0x6, - [0x7C5]=0x6, - [0x7C6]=0x6, - [0x7C7]=0x6, - [0x7C8]=0x6, - [0x7C9]=0x6, - [0x7CA]=0x2, - [0x7CB]=0x2, - [0x7CC]=0x2, - [0x7CD]=0x2, - [0x7CE]=0x2, - [0x7CF]=0x2, - [0x7D0]=0x2, - [0x7D1]=0x2, - [0x7D2]=0x2, - [0x7D3]=0x2, - [0x7D4]=0x2, - [0x7D5]=0x2, - [0x7D6]=0x2, - [0x7D7]=0x2, - [0x7D8]=0x2, - [0x7D9]=0x2, - [0x7DA]=0x2, - [0x7DB]=0x2, - [0x7DC]=0x2, - [0x7DD]=0x2, - [0x7DE]=0x2, - [0x7DF]=0x2, - [0x7E0]=0x2, - [0x7E1]=0x2, - [0x7E2]=0x2, - [0x7E3]=0x2, - [0x7E4]=0x2, - [0x7E5]=0x2, - [0x7E6]=0x2, - [0x7E7]=0x2, - [0x7E8]=0x2, - [0x7E9]=0x2, - [0x7EA]=0x2, - [0x7EB]=0x5, - [0x7EC]=0x5, - [0x7ED]=0x5, - [0x7EE]=0x5, - [0x7EF]=0x5, - [0x7F0]=0x5, - [0x7F1]=0x5, - [0x7F2]=0x5, - [0x7F3]=0x5, - [0x7F4]=0x6, - [0x7F5]=0x6, - [0x7F6]=0x6, - [0x7F7]=0x6, - [0x7F8]=0x6, - [0x7F9]=0x6, - [0x7FA]=0x2, - [0x840]=0x3, - [0x841]=0x2, - [0x842]=0x2, - [0x843]=0x2, - [0x844]=0x2, - [0x845]=0x2, - [0x846]=0x3, - [0x847]=0x3, - [0x848]=0x2, - [0x849]=0x3, - [0x84A]=0x2, - [0x84B]=0x2, - [0x84C]=0x2, - [0x84D]=0x2, - [0x84E]=0x2, - [0x84F]=0x2, - [0x850]=0x2, - [0x851]=0x2, - [0x852]=0x2, - [0x853]=0x2, - [0x854]=0x3, - [0x855]=0x2, - [0x856]=0x4, - [0x857]=0x4, - [0x858]=0x4, - [0x8A0]=0x2, - [0x8A1]=0x2, - [0x8A2]=0x2, - [0x8A3]=0x2, - [0x8A4]=0x2, - [0x8A5]=0x2, - [0x8A6]=0x2, - [0x8A7]=0x2, - [0x8A8]=0x2, - [0x8A9]=0x2, - [0x8AA]=0x3, - [0x8AB]=0x3, - [0x8AC]=0x3, - [0x8AD]=0x4, - [0x8AE]=0x3, - [0x8AF]=0x2, - [0x8B0]=0x2, - [0x8B1]=0x3, - [0x8B2]=0x3, - [0x8B3]=0x2, - [0x8B4]=0x2, - [0x8B6]=0x2, - [0x8B7]=0x2, - [0x8B8]=0x2, - [0x8B9]=0x3, - [0x8BA]=0x2, - [0x8BB]=0x2, - [0x8BC]=0x2, - [0x8BD]=0x2, - [0x8E2]=0x4, - [0x1806]=0x4, - [0x1807]=0x2, - [0x180A]=0x2, - [0x180E]=0x4, - [0x1820]=0x2, - [0x1821]=0x2, - [0x1822]=0x2, - [0x1823]=0x2, - [0x1824]=0x2, - [0x1825]=0x2, - [0x1826]=0x2, - [0x1827]=0x2, - [0x1828]=0x2, - [0x1829]=0x2, - [0x182A]=0x2, - [0x182B]=0x2, - [0x182C]=0x2, - [0x182D]=0x2, - [0x182E]=0x2, - [0x182F]=0x2, - [0x1830]=0x2, - [0x1831]=0x2, - [0x1832]=0x2, - [0x1833]=0x2, - [0x1834]=0x2, - [0x1835]=0x2, - [0x1836]=0x2, - [0x1837]=0x2, - [0x1838]=0x2, - [0x1839]=0x2, - [0x183A]=0x2, - [0x183B]=0x2, - [0x183C]=0x2, - [0x183D]=0x2, - [0x183E]=0x2, - [0x183F]=0x2, - [0x1840]=0x2, - [0x1841]=0x2, - [0x1842]=0x2, - [0x1843]=0x2, - [0x1844]=0x2, - [0x1845]=0x2, - [0x1846]=0x2, - [0x1847]=0x2, - [0x1848]=0x2, - [0x1849]=0x2, - [0x184A]=0x2, - [0x184B]=0x2, - [0x184C]=0x2, - [0x184D]=0x2, - [0x184E]=0x2, - [0x184F]=0x2, - [0x1850]=0x2, - [0x1851]=0x2, - [0x1852]=0x2, - [0x1853]=0x2, - [0x1854]=0x2, - [0x1855]=0x2, - [0x1856]=0x2, - [0x1857]=0x2, - [0x1858]=0x2, - [0x1859]=0x2, - [0x185A]=0x2, - [0x185B]=0x2, - [0x185C]=0x2, - [0x185D]=0x2, - [0x185E]=0x2, - [0x185F]=0x2, - [0x1860]=0x2, - [0x1861]=0x2, - [0x1862]=0x2, - [0x1863]=0x2, - [0x1864]=0x2, - [0x1865]=0x2, - [0x1866]=0x2, - [0x1867]=0x2, - [0x1868]=0x2, - [0x1869]=0x2, - [0x186A]=0x2, - [0x186B]=0x2, - [0x186C]=0x2, - [0x186D]=0x2, - [0x186E]=0x2, - [0x186F]=0x2, - [0x1870]=0x2, - [0x1871]=0x2, - [0x1872]=0x2, - [0x1873]=0x2, - [0x1874]=0x2, - [0x1875]=0x2, - [0x1876]=0x2, - [0x1877]=0x2, - [0x1880]=0x4, - [0x1881]=0x4, - [0x1882]=0x4, - [0x1883]=0x4, - [0x1884]=0x4, - [0x1887]=0x2, - [0x1888]=0x2, - [0x1889]=0x2, - [0x188A]=0x2, - [0x188B]=0x2, - [0x188C]=0x2, - [0x188D]=0x2, - [0x188E]=0x2, - [0x188F]=0x2, - [0x1890]=0x2, - [0x1891]=0x2, - [0x1892]=0x2, - [0x1893]=0x2, - [0x1894]=0x2, - [0x1895]=0x2, - [0x1896]=0x2, - [0x1897]=0x2, - [0x1898]=0x2, - [0x1899]=0x2, - [0x189A]=0x2, - [0x189B]=0x2, - [0x189C]=0x2, - [0x189D]=0x2, - [0x189E]=0x2, - [0x189F]=0x2, - [0x18A0]=0x2, - [0x18A1]=0x2, - [0x18A2]=0x2, - [0x18A3]=0x2, - [0x18A4]=0x2, - [0x18A5]=0x2, - [0x18A6]=0x2, - [0x18A7]=0x2, - [0x18A8]=0x2, - [0x18AA]=0x2, - [0x200C]=0x4, - [0x200D]=0x2, - [0x202F]=0x4, - [0x2066]=0x4, - [0x2067]=0x4, - [0x2068]=0x4, - [0x2069]=0x4, - [0xA840]=0x2, - [0xA841]=0x2, - [0xA842]=0x2, - [0xA843]=0x2, - [0xA844]=0x2, - [0xA845]=0x2, - [0xA846]=0x2, - [0xA847]=0x2, - [0xA848]=0x2, - [0xA849]=0x2, - [0xA84A]=0x2, - [0xA84B]=0x2, - [0xA84C]=0x2, - [0xA84D]=0x2, - [0xA84E]=0x2, - [0xA84F]=0x2, - [0xA850]=0x2, - [0xA851]=0x2, - [0xA852]=0x2, - [0xA853]=0x2, - [0xA854]=0x2, - [0xA855]=0x2, - [0xA856]=0x2, - [0xA857]=0x2, - [0xA858]=0x2, - [0xA859]=0x2, - [0xA85A]=0x2, - [0xA85B]=0x2, - [0xA85C]=0x2, - [0xA85D]=0x2, - [0xA85E]=0x2, - [0xA85F]=0x2, - [0xA860]=0x2, - [0xA861]=0x2, - [0xA862]=0x2, - [0xA863]=0x2, - [0xA864]=0x2, - [0xA865]=0x2, - [0xA866]=0x2, - [0xA867]=0x2, - [0xA868]=0x2, - [0xA869]=0x2, - [0xA86A]=0x2, - [0xA86B]=0x2, - [0xA86C]=0x2, - [0xA86D]=0x2, - [0xA86E]=0x2, - [0xA86F]=0x2, - [0xA870]=0x2, - [0xA871]=0x2, - [0xA872]=0x1, - [0xA873]=0x4, - [0x10AC0]=0x2, - [0x10AC1]=0x2, - [0x10AC2]=0x2, - [0x10AC3]=0x2, - [0x10AC4]=0x2, - [0x10AC5]=0x3, - [0x10AC6]=0x4, - [0x10AC7]=0x3, - [0x10AC8]=0x4, - [0x10AC9]=0x3, - [0x10ACA]=0x3, - [0x10ACB]=0x4, - [0x10ACC]=0x4, - [0x10ACD]=0x1, - [0x10ACE]=0x3, - [0x10ACF]=0x3, - [0x10AD0]=0x3, - [0x10AD1]=0x3, - [0x10AD2]=0x3, - [0x10AD3]=0x2, - [0x10AD4]=0x2, - [0x10AD5]=0x2, - [0x10AD6]=0x2, - [0x10AD7]=0x1, - [0x10AD8]=0x2, - [0x10AD9]=0x2, - [0x10ADA]=0x2, - [0x10ADB]=0x2, - [0x10ADC]=0x2, - [0x10ADD]=0x3, - [0x10ADE]=0x2, - [0x10ADF]=0x2, - [0x10AE0]=0x2, - [0x10AE1]=0x3, - [0x10AE2]=0x4, - [0x10AE3]=0x4, - [0x10AE4]=0x3, - [0x10AEB]=0x2, - [0x10AEC]=0x2, - [0x10AED]=0x2, - [0x10AEE]=0x2, - [0x10AEF]=0x3, - [0x10B80]=0x2, - [0x10B81]=0x3, - [0x10B82]=0x2, - [0x10B83]=0x3, - [0x10B84]=0x3, - [0x10B85]=0x3, - [0x10B86]=0x2, - [0x10B87]=0x2, - [0x10B88]=0x2, - [0x10B89]=0x3, - [0x10B8A]=0x2, - [0x10B8B]=0x2, - [0x10B8C]=0x3, - [0x10B8D]=0x2, - [0x10B8E]=0x3, - [0x10B8F]=0x3, - [0x10B90]=0x2, - [0x10B91]=0x3, - [0x10BA9]=0x3, - [0x10BAA]=0x3, - [0x10BAB]=0x3, - [0x10BAC]=0x3, - [0x10BAD]=0x2, - [0x10BAE]=0x2, - [0x10BAF]=0x4, - [0x1E900]=0x2, - [0x1E901]=0x2, - [0x1E902]=0x2, - [0x1E903]=0x2, - [0x1E904]=0x2, - [0x1E905]=0x2, - [0x1E906]=0x2, - [0x1E907]=0x2, - [0x1E908]=0x2, - [0x1E909]=0x2, - [0x1E90A]=0x2, - [0x1E90B]=0x2, - [0x1E90C]=0x2, - [0x1E90D]=0x2, - [0x1E90E]=0x2, - [0x1E90F]=0x2, - [0x1E910]=0x2, - [0x1E911]=0x2, - [0x1E912]=0x2, - [0x1E913]=0x2, - [0x1E914]=0x2, - [0x1E915]=0x2, - [0x1E916]=0x2, - [0x1E917]=0x2, - [0x1E918]=0x2, - [0x1E919]=0x2, - [0x1E91A]=0x2, - [0x1E91B]=0x2, - [0x1E91C]=0x2, - [0x1E91D]=0x2, - [0x1E91E]=0x2, - [0x1E91F]=0x2, - [0x1E920]=0x2, - [0x1E921]=0x2, - [0x1E922]=0x2, - [0x1E923]=0x2, - [0x1E924]=0x2, - [0x1E925]=0x2, - [0x1E926]=0x2, - [0x1E927]=0x2, - [0x1E928]=0x2, - [0x1E929]=0x2, - [0x1E92A]=0x2, - [0x1E92B]=0x2, - [0x1E92C]=0x2, - [0x1E92D]=0x2, - [0x1E92E]=0x2, - [0x1E92F]=0x2, - [0x1E930]=0x2, - [0x1E931]=0x2, - [0x1E932]=0x2, - [0x1E933]=0x2, - [0x1E934]=0x2, - [0x1E935]=0x2, - [0x1E936]=0x2, - [0x1E937]=0x2, - [0x1E938]=0x2, - [0x1E939]=0x2, - [0x1E93A]=0x2, - [0x1E93B]=0x2, - [0x1E93C]=0x2, - [0x1E93D]=0x2, - [0x1E93E]=0x2, - [0x1E93F]=0x2, - [0x1E940]=0x2, - [0x1E941]=0x2, - [0x1E942]=0x2, - [0x1E943]=0x2, - }, -} \ No newline at end of file diff --git a/tex/compat/luaotfload/luaotfload-colors.lua b/tex/compat/luaotfload/luaotfload-colors.lua deleted file mode 100644 index f2fdceb2c50c1dc0bd4a69d231091f5bde204ea1..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/luaotfload-colors.lua +++ /dev/null @@ -1,405 +0,0 @@ -if not modules then modules = { } end modules ['luaotfload-colors'] = { - version = "2.8", - comment = "companion to luaotfload-main.lua (font color)", - author = "Khaled Hosny, Elie Roux, Philipp Gesang, Dohyun Kim, David Carlisle", - copyright = "Luaotfload Development Team", - license = "GNU GPL v2.0" -} - ---[[doc-- - -buggy coloring with the pre_output_filter when expansion is enabled - · tfmdata for different expansion values is split over different objects - · in ``initializeexpansion()``, chr.expansion_factor is set, and only - those characters that have it are affected - · in constructors.scale: chr.expansion_factor = ve*1000 if commented out - makes the bug vanish - -explanation: http://tug.org/pipermail/luatex/2013-May/004305.html - ---doc]]-- - -local logreport = luaotfload and luaotfload.log.report or print - -local nodedirect = node.direct -local newnode = nodedirect.new -local insert_node_before = nodedirect.insert_before -local insert_node_after = nodedirect.insert_after -local todirect = nodedirect.todirect -local tonode = nodedirect.tonode -local setfield = nodedirect.setfield -local getid = nodedirect.getid -local getfont = nodedirect.getfont -local getlist = nodedirect.getlist -local getsubtype = nodedirect.getsubtype -local getnext = nodedirect.getnext -local nodetail = nodedirect.tail -local getattribute = nodedirect.has_attribute -local setattribute = nodedirect.set_attribute - -local stringformat = string.format -local identifiers = fonts.hashes.identifiers - -local add_color_callback --[[ this used to be a global‽ ]] - ---[[doc-- -This converts a single octet into a decimal with three digits of -precision. The optional second argument limits precision to a single -digit. ---doc]]-- - ---- string -> bool? -> string -local hex_to_dec = function (hex,one) --- one isn’t actually used anywhere ... - if one then - return stringformat("%.1g", tonumber(hex, 16)/255) - else - return stringformat("%.3g", tonumber(hex, 16)/255) - end -end - ---[[doc-- -Color string validator / parser. ---doc]]-- - -local lpeg = require"lpeg" -local lpegmatch = lpeg.match -local C, Cg, Ct, P, R, S = lpeg.C, lpeg.Cg, lpeg.Ct, lpeg.P, lpeg.R, lpeg.S - -local digit16 = R("09", "af", "AF") -local opaque = S("fF") * S("fF") -local octet = C(digit16 * digit16) - -local p_rgb = octet * octet * octet -local p_rgba = p_rgb * (octet - opaque) -local valid_digits = C(p_rgba + p_rgb) -- matches eight or six hex digits - -local p_Crgb = Cg(octet/hex_to_dec, "red") --- for captures - * Cg(octet/hex_to_dec, "green") - * Cg(octet/hex_to_dec, "blue") -local p_Crgba = p_Crgb * Cg(octet/hex_to_dec, "alpha") -local extract_color = Ct(p_Crgba + p_Crgb) - ---- string -> (string | nil) -local sanitize_color_expression = function (digits) - digits = tostring(digits) - local sanitized = lpegmatch(valid_digits, digits) - if not sanitized then - logreport("both", 0, "color", - "%q is not a valid rgb[a] color expression", - digits) - return nil - end - return sanitized -end - ---- something is carried around in ``res`` ---- for later use by color_handler() --- but what? - -local res = nil - ---- float -> unit -local function pageresources(alpha) - res = res or {} - res[alpha] = true -end - ---- we store results of below color handler as tuples of ---- push/pop strings -local color_cache = { } --- (string, (string * string)) hash_t - ---- string -> (string * string) -local hex_to_rgba = function (digits) - if not digits then - return - end - - --- this is called like a thousand times, so some - --- memoizing is in order. - local cached = color_cache[digits] - if not cached then - local push, pop - local rgb = lpegmatch(extract_color, digits) - if rgb.alpha then - pageresources(rgb.alpha) - push = stringformat( - "/TransGs%g gs %s %s %s rg", - rgb.alpha, - rgb.red, - rgb.green, - rgb.blue) - pop = "0 g /TransGs1 gs" - else - push = stringformat( - "%s %s %s rg", - rgb.red, - rgb.green, - rgb.blue) - pop = "0 g" - end - color_cache[digits] = { push, pop } - return push, pop - end - - return cached[1], cached[2] -end - ---- Luatex internal types - -local nodetype = node.id -local glyph_t = nodetype("glyph") -local hlist_t = nodetype("hlist") -local vlist_t = nodetype("vlist") -local whatsit_t = nodetype("whatsit") -local disc_t = nodetype("disc") -local pdfliteral_t = node.subtype("pdf_literal") -local colorstack_t = node.subtype("pdf_colorstack") -local mlist_to_hlist = node.mlist_to_hlist - -local color_callback -local color_attr = luatexbase.new_attribute("luaotfload_color_attribute") - --- (node * node * string * bool * (bool | nil)) -> (node * node * (string | nil)) -local color_whatsit -color_whatsit = function (head, curr, color, push, tail) - local pushdata = hex_to_rgba(color) - local colornode = newnode(whatsit_t, colorstack_t) - setfield(colornode, "stack", 0) - setfield(colornode, "command", push and 1 or 2) -- 1: push, 2: pop - setfield(colornode, "data", push and pushdata or nil) - if tail then - head, curr = insert_node_after (head, curr, colornode) - else - head = insert_node_before(head, curr, colornode) - end - if not push and color:len() > 6 then - local colornode = newnode(whatsit_t, pdfliteral_t) - setfield(colornode, "mode", 2) - setfield(colornode, "data", "/TransGs1 gs") - if tail then - head, curr = insert_node_after (head, curr, colornode) - else - head = insert_node_before(head, curr, colornode) - end - end - color = push and color or nil - return head, curr, color -end - --- number -> string | nil -local get_font_color = function (font_id) - local tfmdata = identifiers[font_id] - local font_color = tfmdata and tfmdata.properties and tfmdata.properties.color - return font_color -end - ---[[doc-- -While the second argument and second returned value are apparently -always nil when the function is called, they temporarily take string -values during the node list traversal. ---doc]]-- - ---- (node * (string | nil)) -> (node * (string | nil)) -local node_colorize -node_colorize = function (head, toplevel, current_color) - local n = head - while n do - local n_id = getid(n) - - if n_id == hlist_t or n_id == vlist_t then - local n_list = getlist(n) - if getattribute(n_list, color_attr) then - if current_color then - head, n, current_color = color_whatsit(head, n, current_color, false) - end - else - n_list, current_color = node_colorize(n_list, false, current_color) - if current_color and getsubtype(n) == 1 then -- created by linebreak - n_list, _, current_color = color_whatsit(n_list, nodetail(n_list), current_color, false, true) - end - setfield(n, "head", n_list) - end - - elseif n_id == glyph_t then - --- colorization is restricted to those fonts - --- that received the “color” property upon - --- loading (see ``setcolor()`` above) - local font_color = get_font_color(getfont(n)) - if font_color ~= current_color then - if current_color then - head, n, current_color = color_whatsit(head, n, current_color, false) - end - if font_color then - head, n, current_color = color_whatsit(head, n, font_color, true) - end - end - - if current_color and color_callback == "pre_linebreak_filter" then - local nn = getnext(n) - while nn and getid(nn) == glyph_t do - local font_color = get_font_color(getfont(nn)) - if font_color == current_color then - n = nn - else - break - end - nn = getnext(nn) - end - if getid(nn) == disc_t then - head, n, current_color = color_whatsit(head, nn, current_color, false, true) - else - head, n, current_color = color_whatsit(head, n, current_color, false, true) - end - end - - elseif n_id == whatsit_t then - if current_color then - head, n, current_color = color_whatsit(head, n, current_color, false) - end - - end - - n = getnext(n) - end - - if toplevel and current_color then - head, _, current_color = color_whatsit(head, nodetail(head), current_color, false, true) - end - - setattribute(head, color_attr, 1) - return head, current_color -end - -local getpageres = pdf.getpageresources or function() return pdf.pageresources end -local setpageres = pdf.setpageresources or function(s) pdf.pageresources = s end -local catat11 = luatexbase.registernumber("catcodetable@atletter") -local gettoks, scantoks = tex.gettoks, tex.scantoks -local pgf = { bye = "pgfutil@everybye", extgs = "\\pgf@sys@addpdfresource@extgs@plain" } - ---- node -> node -local color_handler = function (head) - head = todirect(head) - head = node_colorize(head, true) - head = tonode(head) - - -- now append our page resources - if res then - res["1"] = true - if scantoks and pgf.bye and not pgf.loaded then - pgf.loaded = token.create(pgf.bye).cmdname == "assign_toks" - pgf.bye = pgf.loaded and pgf.bye - end - local tpr = pgf.loaded and gettoks(pgf.bye) or getpageres() or "" - - local t = "" - for k in pairs(res) do - local str = stringformat("/TransGs%s<</ca %s>>", k, k) -- don't touch stroking elements - if not tpr:find(str) then - t = t .. str - end - end - if t ~= "" then - if pgf.loaded then - scantoks("global", pgf.bye, catat11, stringformat("%s{%s}%s", pgf.extgs, t, tpr)) - else - local tpr, n = tpr:gsub("/ExtGState<<", "%1"..t) - if n == 0 then - tpr = stringformat("%s/ExtGState<<%s>>", tpr, t) - end - setpageres(tpr) - end - end - res = nil -- reset res - end - return head -end - -local color_callback_name = "luaotfload.color_handler" -local color_callback_activated = 0 -local add_to_callback = luatexbase.add_to_callback - ---- unit -> bool -local mlist_to_hlist_initial = function () - local cdesc = luatexbase.callback_descriptions "mlist_to_hlist" - return cdesc and cdesc[1] == color_callback_name -end - ---- unit -> unit -add_color_callback = function ( ) - color_callback = config.luaotfload.run.color_callback - if not color_callback then - color_callback = "post_linebreak_filter" - end - - if color_callback_activated == 0 then - add_to_callback(color_callback, - color_handler, - color_callback_name) - add_to_callback("hpack_filter", - function (head, groupcode) - if groupcode == "hbox" or - groupcode == "adjusted_hbox" or - groupcode == "align_set" then - head = color_handler(head) - end - return head - end, - color_callback_name) - add_to_callback("mlist_to_hlist", - function (head, display_type, need_penalties) - if mlist_to_hlist_initial () then - head = mlist_to_hlist(head, display_type, need_penalties) - end - if display_type == "text" then - return head - end - return color_handler(head) - end, - color_callback_name) - color_callback_activated = 1 - end -end - ---[[doc-- -``setcolor`` modifies tfmdata.properties.color in place ---doc]]-- - ---- fontobj -> string -> unit ---- ---- (where “string” is a rgb value as three octet ---- hexadecimal, with an optional fourth transparency ---- value) ---- -local setcolor = function (tfmdata, value) - local sanitized = sanitize_color_expression(value) - local properties = tfmdata.properties - - if sanitized then - properties.color = sanitized - add_color_callback() - end -end - -return { - init = function () - logreport = luaotfload.log.report - if not fonts then - logreport ("log", 0, "color", - "OTF mechanisms missing -- did you forget to \z - load a font loader?") - return false - end - fonts.handlers.otf.features.register { - name = "color", - description = "color", - initializers = { - base = setcolor, - node = setcolor, - } - } - return true - end -} - - --- vim:tw=71:sw=4:ts=4:expandtab - diff --git a/tex/compat/luaotfload/luaotfload-configuration.lua b/tex/compat/luaotfload/luaotfload-configuration.lua deleted file mode 100644 index 2f4589b10d0848cfbfda31605fc23e4168e36e4d..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/luaotfload-configuration.lua +++ /dev/null @@ -1,1034 +0,0 @@ -#!/usr/bin/env texlua -------------------------------------------------------------------------------- --- FILE: luaotfload-configuration.lua --- DESCRIPTION: config file reader --- REQUIREMENTS: Luaotfload 2.8 or above --- AUTHOR: Philipp Gesang, <phg@phi-gamma.net> --- AUTHOR: Dohyun Kim <nomosnomos@gmail.com> -------------------------------------------------------------------------------- --- - -if not modules then modules = { } end modules ["luaotfload-configuration"] = { - version = "2.8", - comment = "part of Luaotfload", - author = "Philipp Gesang, Dohyun Kim", - copyright = "Luaotfload Development Team", - license = "GNU GPL v2.0" -} - -local status_file = "luaotfload-status" -local luaotfloadstatus = require (status_file) - -local string = string -local stringfind = string.find -local stringformat = string.format -local stringstrip = string.strip -local stringsub = string.sub - -local tableappend = table.append -local tableconcat = table.concat -local tablecopy = table.copy -local table = table -local tabletohash = table.tohash - -local math = math -local mathfloor = math.floor - -local io = io -local ioloaddata = io.loaddata -local iopopen = io.popen -local iowrite = io.write - -local os = os -local osdate = os.date -local osgetenv = os.getenv - -local lpeg = require "lpeg" -local lpegmatch = lpeg.match -local commasplitter = lpeg.splitat "," -local equalssplitter = lpeg.splitat "=" - -local kpseexpand_path = kpse.expand_path - -local lfs = lfs -local lfsisfile = lfs.isfile -local lfsisdir = lfs.isdir - -local file = file -local filejoin = file.join -local filereplacesuffix = file.replacesuffix - -local logreport = print -- overloaded later -local getwritablepath = caches.getwritablepath - - -local config_parser -- set later during init -local stripslashes -- set later during init - -------------------------------------------------------------------------------- ---- SETTINGS -------------------------------------------------------------------------------- - -local path_t = 0 -local kpse_t = 1 - -local val_home = kpseexpand_path "~" -local val_xdg_config_home = kpseexpand_path "$XDG_CONFIG_HOME" - -if val_xdg_config_home == "" then val_xdg_config_home = "~/.config" end - -local config_paths = { - --- needs adapting for those other OS - { path_t, "./luaotfload.conf" }, - { path_t, "./luaotfloadrc" }, - { path_t, filejoin (val_xdg_config_home, "luaotfload/luaotfload.conf") }, - { path_t, filejoin (val_xdg_config_home, "luaotfload/luaotfloadrc") }, - { path_t, filejoin (val_home, ".luaotfloadrc") }, - { kpse_t, "luaotfloadrc" }, - { kpse_t, "luaotfload.conf" }, -} - -local valid_formats = tabletohash { - "otf", "ttc", "ttf", "afm", "pfb" -} - -local default_anon_sequence = { - "tex", "path", "name" -} - -local valid_resolvers = tabletohash { - "tex", "path", "name", "file", "my" -} - -local feature_presets = { - arab = tabletohash { - "ccmp", "locl", "isol", "fina", "fin2", - "fin3", "medi", "med2", "init", "rlig", - "calt", "liga", "cswh", "mset", "curs", - "kern", "mark", "mkmk", - }, - deva = tabletohash { - "ccmp", "locl", "init", "nukt", "akhn", - "rphf", "blwf", "half", "pstf", "vatu", - "pres", "blws", "abvs", "psts", "haln", - "calt", "blwm", "abvm", "dist", "kern", - "mark", "mkmk", - }, - khmr = tabletohash { - "ccmp", "locl", "pref", "blwf", "abvf", - "pstf", "pres", "blws", "abvs", "psts", - "clig", "calt", "blwm", "abvm", "dist", - "kern", "mark", "mkmk", - }, - thai = tabletohash { - "ccmp", "locl", "liga", "kern", "mark", - "mkmk", - }, -} - ---[[doc-- - - We allow loading of arbitrary fontloaders. Nevertheless we maintain a - list of the “official” ones shipped with Luaotfload so we can emit a - different log message. - ---doc]]-- - -local default_fontloader = function () - return luaotfloadstatus and luaotfloadstatus.notes.loader or "reference" -end - -local registered_loaders = { - default = default_fontloader (), - reference = "reference", - unpackaged = "unpackaged", - context = "context", -} - -local pick_fontloader = function (s) - local ldr = registered_loaders[s] - if ldr ~= nil and type (ldr) == "string" then - logreport ("log", 2, "conf", "Using predefined fontloader \"%s\".", ldr) - return ldr - end - local idx = stringfind (s, ":") - if idx and idx > 2 then - if stringsub (s, 1, idx - 1) == "context" then - local pth = stringsub (s, idx + 1) - pth = stringstrip (pth) - logreport ("log", 2, "conf", "Context base path specified at \"%s\".", pth) - if lfsisdir (pth) then - logreport ("log", 5, "conf", "Context base path exists at \"%s\".", pth) - return pth - end - pth = kpseexpand_path (pth) - if lfsisdir (pth) then - logreport ("log", 5, "conf", "Context base path exists at \"%s\".", pth) - return pth - end - logreport ("both", 0, "conf", "Context base path not found at \"%s\".", pth) - end - end - return nil -end - ---[[doc-- - - The ``post_linebreak_filter`` has been made the default callback for - hooking the colorizer into. This helps with the linebreaking whose - inserted hyphens would remain unaffected by the coloring otherwise. - - http://tex.stackexchange.com/q/238539/14066 - ---doc]]-- - -local permissible_color_callbacks = { - default = "post_linebreak_filter", - pre_linebreak_filter = "pre_linebreak_filter", - post_linebreak_filter = "post_linebreak_filter", - pre_output_filter = "pre_output_filter", -} - - -------------------------------------------------------------------------------- ---- DEFAULTS -------------------------------------------------------------------------------- - -local default_config = { - db = { - formats = "otf,ttf,ttc", - scan_local = false, - skip_read = false, - strip = true, - update_live = true, - compress = true, - max_fonts = 2^51, - designsize_dimen= "bp", - }, - run = { - anon_sequence = default_anon_sequence, - resolver = "cached", - definer = "patch", - log_level = 0, - color_callback = "post_linebreak_filter", - fontloader = default_fontloader (), - }, - misc = { - bisect = false, - version = luaotfload.version, - statistics = false, - termwidth = nil, - }, - paths = { - names_dir = "names", - cache_dir = "fonts", - index_file = "luaotfload-names.lua", - lookups_file = "luaotfload-lookup-cache.lua", - lookup_path_lua = nil, - lookup_path_luc = nil, - index_path_lua = nil, - index_path_luc = nil, - }, - default_features = { - global = { mode = "node" }, - dflt = tabletohash { - "ccmp", "locl", "rlig", "liga", "clig", - "kern", "mark", "mkmk", 'itlc', - }, - - arab = feature_presets.arab, - syrc = feature_presets.arab, - mong = feature_presets.arab, - nko = feature_presets.arab, - - deva = feature_presets.deva, - beng = feature_presets.deva, - guru = feature_presets.deva, - gujr = feature_presets.deva, - orya = feature_presets.deva, - taml = feature_presets.deva, - telu = feature_presets.deva, - knda = feature_presets.deva, - mlym = feature_presets.deva, - sinh = feature_presets.deva, - - khmr = feature_presets.khmr, - tibt = feature_presets.khmr, - thai = feature_presets.thai, - lao = feature_presets.thai, - - hang = tabletohash { "ccmp", "ljmo", "vjmo", "tjmo", }, - }, -} - -------------------------------------------------------------------------------- ---- RECONFIGURATION TASKS -------------------------------------------------------------------------------- - ---[[doc-- - - Procedures to be executed in order to put the new configuration into effect. - ---doc]]-- - -local reconf_tasks = nil - -local min_terminal_width = 40 - ---- The “termwidth” value is only considered when printing ---- short status messages, e.g. when building the database ---- online. -local check_termwidth = function () - if config.luaotfload.misc.termwidth == nil then - local tw = 79 - if not ( os.type == "windows" --- Assume broken terminal. - or osgetenv "TERM" == "dumb") - then - local p = iopopen "tput cols" - if p then - result = tonumber (p:read "*all") - p:close () - if result then - tw = result - else - logreport ("log", 2, "db", "tput returned non-number.") - end - else - logreport ("log", 2, "db", "Shell escape disabled or tput executable missing.") - logreport ("log", 2, "db", "Assuming 79 cols terminal width.") - end - end - config.luaotfload.misc.termwidth = tw - end - return true -end - -local set_font_filter = function () - local names = fonts.names - if names and names.set_font_filter then - local formats = config.luaotfload.db.formats - if not formats or formats == "" then - formats = default_config.db.formats - end - names.set_font_filter (formats) - end - return true -end - -local set_size_dimension = function () - local names = fonts.names - if names and names.set_size_dimension then - local dim = config.luaotfload.db.designsize_dimen - if not dim or dim == "" then - dim = default_config.db.designsize_dimen - end - names.set_size_dimension (dim) - end - return true -end - -local set_name_resolver = function () - local names = fonts.names - if names and names.resolve_cached then - --- replace the resolver from luatex-fonts - if config.luaotfload.db.resolver == "cached" then - logreport ("both", 2, "cache", "Caching of name: lookups active.") - names.resolvespec = fonts.names.lookup_font_name_cached - else - names.resolvespec = fonts.names.lookup_font_name - end - end - return true -end - -local set_loglevel = function () - if luaotfload then - luaotfload.log.set_loglevel (config.luaotfload.run.log_level) - return true - end - return false -end - -local build_cache_paths = function () - local paths = config.luaotfload.paths - local prefix = getwritablepath (paths.names_dir, "") - - if not prefix then - luaotfload.error ("Impossible to find a suitable writeable cache...") - return false - end - - prefix = lpegmatch (stripslashes, prefix) - logreport ("log", 0, "conf", "Root cache directory is %s.", prefix) - - local index_file = filejoin (prefix, paths.index_file) - local lookups_file = filejoin (prefix, paths.lookups_file) - - paths.prefix = prefix - paths.index_path_lua = filereplacesuffix (index_file, "lua") - paths.index_path_luc = filereplacesuffix (index_file, "luc") - paths.lookup_path_lua = filereplacesuffix (lookups_file, "lua") - paths.lookup_path_luc = filereplacesuffix (lookups_file, "luc") - return true -end - - -local set_default_features = function () - local default_features = config.luaotfload.default_features - luaotfload.features = luaotfload.features or { - global = { }, - defaults = { }, - } - current_features = luaotfload.features - for var, val in next, default_features do - if var == "global" then - current_features.global = val - else - current_features.defaults[var] = val - end - end - return true -end - -reconf_tasks = { - { "Set the log level" , set_loglevel }, - { "Build cache paths" , build_cache_paths }, - { "Check terminal dimensions" , check_termwidth }, - { "Set the font filter" , set_font_filter }, - { "Set design size dimension" , set_size_dimension }, - { "Install font name resolver", set_name_resolver }, - { "Set default features" , set_default_features }, -} - -------------------------------------------------------------------------------- ---- OPTION SPECIFICATION -------------------------------------------------------------------------------- - -local string_t = "string" -local table_t = "table" -local number_t = "number" -local boolean_t = "boolean" -local function_t = "function" - -local tointeger = function (n) - n = tonumber (n) - if n then - return mathfloor (n + 0.5) - end -end - -local toarray = function (s) - local fields = { lpegmatch (commasplitter, s) } - local ret = { } - for i = 1, #fields do - local field = stringstrip (fields[i]) - if field and field ~= "" then - ret[#ret + 1] = field - end - end - return ret -end - -local tohash = function (s) - local result = { } - local fields = toarray (s) - for _, field in next, fields do - local var, val - if stringfind (field, "=") then - local tmp - var, tmp = lpegmatch (equalssplitter, field) - if tmp == "true" or tmp == "yes" then val = true else val = tmp end - else - var, val = field, true - end - result[var] = val - end - return result -end - -local option_spec = { - db = { - formats = { - in_t = string_t, - out_t = string_t, - transform = function (f) - local fields = toarray (f) - - --- check validity - if not fields then - logreport ("both", 0, "conf", - "Expected list of identifiers, got %q.", f) - return nil - end - - --- strip dupes - local known = { } - local result = { } - for i = 1, #fields do - local field = fields[i] - if known[field] ~= true then - --- yet unknown, tag as seen - known[field] = true - --- include in output if valid - if valid_formats[field] == true then - result[#result + 1] = field - else - logreport ("both", 4, "conf", - "Invalid font format identifier %q, ignoring.", - field) - end - end - end - if #result == 0 then - --- force defaults - return nil - end - return tableconcat (result, ",") - end - }, - scan_local = { in_t = boolean_t, }, - skip_read = { in_t = boolean_t, }, - strip = { in_t = boolean_t, }, - update_live = { in_t = boolean_t, }, - compress = { in_t = boolean_t, }, - max_fonts = { - in_t = number_t, - out_t = number_t, --- TODO int_t from 5.3.x on - transform = tointeger, - }, - designsize_dimen = { - in_t = string_t, - out_t = string_t, - }, - }, - run = { - anon_sequence = { - in_t = string_t, - out_t = table_t, - transform = function (s) - if s ~= "default" then - local bits = { lpegmatch (commasplitter, s) } - if next (bits) then - local seq = { } - local done = { } - for i = 1, #bits do - local bit = bits [i] - if valid_resolvers [bit] then - if not done [bit] then - done [bit] = true - seq [#seq + 1] = bit - else - logreport ("both", 0, "conf", - "ignoring duplicate resolver %s at position %d \z - in lookup sequence", - bit, i) - end - else - logreport ("both", 0, "conf", - "lookup sequence contains invalid item %s \z - at position %d.", - bit, i) - end - end - if next (seq) then - logreport ("both", 2, "conf", - "overriding anon lookup sequence %s.", - tableconcat (seq, ",")) - return seq - end - end - end - return default_anon_sequence - end - }, - live = { in_t = boolean_t, }, --- false for the tool, true for TeX run - resolver = { - in_t = string_t, - out_t = string_t, - transform = function (r) return r == "normal" and r or "cached" end, - }, - definer = { - in_t = string_t, - out_t = string_t, - transform = function (d) - if d == "generic" or d == "patch" - or d == "info_generic" or d == "info_patch" - then - return d - end - return "patch" - end, - }, - fontloader = { - in_t = string_t, - out_t = string_t, - transform = function (id) - local ldr = pick_fontloader (id) - if ldr ~= nil then - return ldr - end - logreport ("log", 0, "conf", - "Requested fontloader \"%s\" not defined, " - .. "use at your own risk.", - id) - return id - end, - }, - log_level = { - in_t = number_t, - out_t = number_t, --- TODO int_t from 5.3.x on - transform = tointeger, - }, - color_callback = { - in_t = string_t, - out_t = string_t, - transform = function (cb_spec) - --- These are the two that make sense. - local cb = permissible_color_callbacks[cb_spec] - if cb then - logreport ("log", 3, "conf", - "Using callback \"%s\" for font colorization.", - cb) - return cb - end - logreport ("log", 0, "conf", - "Requested callback identifier \"%s\" invalid, " - .. "falling back to default.", - cb_spec) - return permissible_color_callbacks.default - end, - }, - }, - misc = { - bisect = { in_t = boolean_t, }, --- doesn’t make sense in a config file - version = { in_t = string_t, }, - statistics = { in_t = boolean_t, }, - termwidth = { - in_t = number_t, - out_t = number_t, - transform = function (w) - w = tointeger (w) - if w < min_terminal_width then - return min_terminal_width - end - return w - end, - }, - }, - paths = { - names_dir = { in_t = string_t, }, - cache_dir = { in_t = string_t, }, - index_file = { in_t = string_t, }, - lookups_file = { in_t = string_t, }, - lookup_path_lua = { in_t = string_t, }, - lookup_path_luc = { in_t = string_t, }, - index_path_lua = { in_t = string_t, }, - index_path_luc = { in_t = string_t, }, - }, - default_features = { - __default = { in_t = string_t, out_t = table_t, transform = tohash, }, - }, -} - -------------------------------------------------------------------------------- ---- FORMATTERS -------------------------------------------------------------------------------- - -local commented = function (str) - return ";" .. str -end - -local underscore_replacer = lpeg.replacer ("_", "-", true) - -local dashed = function (var) - --- INI spec dictates that dashes are valid in variable names, not - --- underscores. - return underscore_replacer (var) or var -end - -local indent = " " -local format_string = function (var, val) - return stringformat (indent .. "%s = %s", var, val) -end - -local format_integer = function (var, val) - return stringformat (indent .. "%s = %d", var, val) -end - -local format_boolean = function (var, val) - return stringformat (indent .. "%s = %s", var, val == true and "true" or "false") -end - -local format_keyval = function (var, val) - local list = { } - local keys = table.sortedkeys (val) - for i = 1, #keys do - local key = keys[i] - local subval = val[key] - if subval == true then - list[#list + 1] = stringformat ("%s", key) - else - list[#list + 1] = stringformat ("%s=%s", key, val[key]) - end - end - if next (list) then - return stringformat (indent .. "%s = %s", - var, - tableconcat (list, ",")) - end -end - -local format_list = function (var, val) - local elts = { } - for i = 1, #val do elts [i] = val [i] end - if next (elts) then - return stringformat (indent .. "%s = %s", - var, tableconcat (elts, ",")) - end -end - -local format_section = function (title) - return stringformat ("[%s]", dashed (title)) -end - -local conf_header = [==[ -;;----------------------------------------------------------------------------- -;; Luaotfload Configuration -;;----------------------------------------------------------------------------- -;; -;; This file was generated by luaotfload-tool -;; on %s. Configuration variables -;; are documented in the manual to luaotfload.conf(5). -;; -;;----------------------------------------------------------------------------- - -]==] - -local conf_footer = [==[ - -;; vim:filetype=dosini:expandtab:shiftwidth=2 -]==] - ---- Each dumpable variable (the ones mentioned in the man page) receives a ---- formatter that will be used in dumping the variable. Each value receives a ---- “commented” flag that indicates whether or not the line should be printed ---- as a comment. - -local formatters = { - db = { - compress = { false, format_boolean }, - designsize_dimen = { false, format_string }, - formats = { false, format_string }, - max_fonts = { false, format_integer }, - scan_local = { false, format_boolean }, - skip_read = { false, format_boolean }, - strip = { false, format_boolean }, - update_live = { false, format_boolean }, - }, - default_features = { - __default = { true, format_keyval }, - }, - misc = { - bisect = { false, format_boolean }, - statistics = { false, format_boolean }, - termwidth = { true , format_integer }, - version = { true , format_string }, - }, - paths = { - cache_dir = { false, format_string }, - names_dir = { false, format_string }, - index_file = { false, format_string }, - lookups_file = { false, format_string }, - }, - run = { - anon_sequence = { false, format_list }, - color_callback = { false, format_string }, - definer = { false, format_string }, - fontloader = { false, format_string }, - log_level = { false, format_integer }, - resolver = { false, format_string }, - }, -} - -------------------------------------------------------------------------------- ---- MAIN FUNCTIONALITY -------------------------------------------------------------------------------- - ---[[doc-- - - tilde_expand -- Rudimentary tilde expansion; covers just the “substitute ‘~’ - by the current users’s $HOME” part. - ---doc]]-- - -local tilde_expand = function (p) - if #p > 2 then - if stringsub (p, 1, 2) == "~/" then - local homedir = osgetenv "HOME" - if homedir and lfsisdir (homedir) then - p = filejoin (homedir, stringsub (p, 3)) - end - end - end - return p -end - -local resolve_config_path = function () - for i = 1, #config_paths do - local t, p = unpack (config_paths[i]) - local fullname - if t == kpse_t then - fullname = kpse.lookup (p) - logreport ("both", 6, "conf", "kpse lookup: %s -> %s.", p, fullname) - elseif t == path_t then - local expanded = tilde_expand (p) - if lfsisfile (expanded) then - fullname = expanded - end - logreport ("both", 6, "conf", "path lookup: %s -> %s.", p, fullname) - end - if fullname then - logreport ("both", 3, "conf", "Reading configuration file at %q.", fullname) - return fullname - end - end - logreport ("both", 2, "conf", "No configuration file found.") - return false -end - -local add_config_paths = function (t) - if not next (t) then - return - end - local result = { } - for i = 1, #t do - local path = t[i] - result[#result + 1] = { path_t, path } - end - config_paths = tableappend (result, config_paths) -end - -local process_options = function (opts) - local new = { } - for i = 1, #opts do - local section = opts[i] - local title = section.section.title - local vars = section.variables - - if not title then --- trigger warning: arrow code ahead - logreport ("both", 2, "conf", "Section %d lacks a title; skipping.", i) - elseif not vars then - logreport ("both", 2, "conf", "Section %d (%s) lacks a variable section; skipping.", i, title) - else - local spec = option_spec[title] - if not spec then - logreport ("both", 2, "conf", "Section %d (%s) unknown; skipping.", i, title) - else - local newsection = new[title] - if not newsection then - newsection = { } - new[title] = newsection - end - - for var, val in next, vars do - local vspec = spec[var] or spec.__default - local t_val = type (val) - if not vspec then - logreport ("both", 2, "conf", - "Section %d (%s): invalid configuration variable %q (%q); ignoring.", - i, title, - var, tostring (val)) - elseif t_val ~= vspec.in_t then - logreport ("both", 2, "conf", - "Section %d (%s): type mismatch of input value %q (%q, %s != %s); ignoring.", - i, title, - var, tostring (val), t_val, vspec.in_t) - else --- type matches - local transform = vspec.transform - if transform then - local dval - local t_transform = type (transform) - if t_transform == function_t then - dval = transform (val) - elseif t_transform == table_t then - dval = transform[val] - end - if dval then - local out_t = vspec.out_t - if out_t then - local t_dval = type (dval) - if t_dval == out_t then - newsection[var] = dval - else - logreport ("both", 2, "conf", - "Section %d (%s): type mismatch of derived value of %q (%q, %s != %s); ignoring.", - i, title, - var, tostring (dval), t_dval, out_t) - end - else - newsection[var] = dval - end - else - logreport ("both", 2, "conf", - "Section %d (%s): value of %q could not be derived via %s from input %q; ignoring.", - i, title, var, t_transform, tostring (val)) - end - else --- insert as is - newsection[var] = val - end - end - end - end - end - end - return new -end - -local apply -apply = function (old, new) - if not new then - if not old then - return false - end - return tablecopy (old) - elseif not old then - return tablecopy (new) - end - local result = tablecopy (old) - for name, section in next, new do - local t_section = type (section) - if t_section ~= table_t then - logreport ("both", 1, "conf", - "Error applying configuration: entry %s is %s, expected table.", - section, t_section) - --- ignore - else - local currentsection = result[name] - for var, val in next, section do - currentsection[var] = val - end - end - end - result.status = luaotfloadstatus - return result -end - -local reconfigure = function () - for i = 1, #reconf_tasks do - local name, task = unpack (reconf_tasks[i]) - logreport ("both", 3, "conf", "Launch post-configuration task %q.", name) - if not task () then - logreport ("both", 0, "conf", "Post-configuration task %q failed.", name) - return false - end - end - return true -end - -local read = function (extra) - if extra then - add_config_paths (extra) - end - - local readme = resolve_config_path () - if readme == false then - logreport ("both", 2, "conf", "No configuration file.") - return false - end - - local raw = ioloaddata (readme) - if not raw then - logreport ("both", 2, "conf", "Error reading the configuration file %q.", readme) - return false - end - - local parsed = lpegmatch (config_parser, raw) - if not parsed then - logreport ("both", 2, "conf", "Error parsing configuration file %q.", readme) - return false - end - - local ret, msg = process_options (parsed) - if not ret then - logreport ("both", 2, "conf", "File %q is not a valid configuration file.", readme) - logreport ("both", 2, "conf", "Error: %s", msg) - return false - end - return ret -end - -local apply_defaults = function () - local defaults = default_config - local vars = read () - --- Side-effects galore ... - config.luaotfload = apply (defaults, vars) - return reconfigure () -end - -local dump = function () - local sections = table.sortedkeys (config.luaotfload) - local confdata = { } - for i = 1, #sections do - local section = sections[i] - local vars = config.luaotfload[section] - local varnames = table.sortedkeys (vars) - local sformats = formatters[section] - if sformats then - confdata[#confdata + 1] = format_section (section) - for j = 1, #varnames do - local var = varnames[j] - local val = vars[var] - local comment, sformat = unpack (sformats[var] or { }) - if not sformat then - comment, sformat = unpack (sformats.__default or { }) - end - - if sformat then - local dashedvar = dashed (var) - if comment then - confdata[#confdata + 1] = commented (sformat (dashedvar, val)) - else - confdata[#confdata + 1] = sformat (dashedvar, val) - end - end - - end - confdata[#confdata + 1] = "" - end - end - if next(confdata) then - iowrite (stringformat (conf_header, - osdate ("%Y-%m-d %H:%M:%S", os.time ()))) - iowrite (tableconcat (confdata, "\n")) - iowrite (conf_footer) - end -end - -------------------------------------------------------------------------------- ---- EXPORTS -------------------------------------------------------------------------------- - -return { - init = function () - config.luaotfload = { } - logreport = luaotfload.log.report - local parsers = luaotfload.parsers - config_parser = parsers.config - stripslashes = parsers.stripslashes - - luaotfload.default_config = default_config - config.actions = { - read = read, - apply = apply, - apply_defaults = apply_defaults, - reconfigure = reconfigure, - dump = dump, - } - if not apply_defaults () then - logreport ("log", 0, "load", - "Configuration unsuccessful: error loading default settings.") - end - return true - end -} - diff --git a/tex/compat/luaotfload/luaotfload-database.lua b/tex/compat/luaotfload/luaotfload-database.lua deleted file mode 100644 index 9c8c298636a6ea0525553122ed10fc24f12c5c86..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/luaotfload-database.lua +++ /dev/null @@ -1,3693 +0,0 @@ -if not modules then modules = { } end modules ['luaotfload-database'] = { - version = "2.8", - comment = "companion to luaotfload-main.lua", - author = "Khaled Hosny, Elie Roux, Philipp Gesang", - copyright = "Luaotfload Development Team", - license = "GNU GPL v2.0" -} - ---[[doc-- - - With version 2.7 we killed of the Fontforge libraries in favor of - the Lua implementation of the OT format reader. There were many - reasons to do this on top of the fact that FF won’t be around at - version 1.0 anymore: In addition to maintainability, memory safety - and general code hygiene, the new reader shows an amazing - performance: Scanning of the 3200 font files on my system takes - around 23 s now, as opposed to 74 s with the Fontforge libs. Memory - usage has improved drastically as well, as illustrated by these - profiles: - - GB - 1.324^ # - | # - | ::# - | : #:: - | @: #: - | @: #: - | @@@: #: - | @@@ @: #: - | @@ @ @ @: #: - | @ @@:@ @ @: #: : - | @@ : @ :@ @ @: #: : - | @@: ::@@ :@@ ::@ :@ @ @: #: : ::: - | @@ : :: @@ :@ : @ :@ @ @: #: : :: : - | @@ : ::: @@ :@ ::: @ :@ @ @: #: :: :: : - | @@@@ :: :::: @@ :@ : : @ :@ @ @: #: :: :::: :: - | :@ @@ :: :::: @@ :@ : :: : @ :@ @ @: #: :: :: :: :: - | @:@ @@ :: ::::: @@ :@ : :::: : @ :@ @ @: #: :::: :::: :: :: - | @@:@ @@ :: ::::::: @@ :@ : : :: : @ :@ @ @: #: ::: @: :: :: ::@ - | @@@:@ @@ :: :: ::::: @@ :@ ::: :: : @ :@ @ @: #: ::: @: :: :: ::@ - | @@@@@:@ @@ ::::::: ::::: @@ :@ ::: :: : @ :@ @ @: #: ::: ::@: :: :: ::@ - 0 +----------------------------------------------------------------------->GB - 0 16.29 - - This is the memory usage during a complete database rebuild with - the Fontforge libraries. The same action using the new - ``getinfo()`` method gives a different picture: - - MB - 43.37^ # - | @ @ @# - | @@ @ @ @# : - | @@@ : @: @ @ @# : - | @ @@@ : : @: @ @: :@# : - | @ @ @@@ : : @: @ @: :@# : - | @ : : :@ @@@:::: @::@ @: :@#:: : - | :: : @ : @ : :::@ @ :@@@:::::@::@ @:::@#:::: - | : @ : :: : :@:: :@: :::::@ @ :@@@:::::@::@:@:::@#:::: - | :: :@ : @ ::@:@:::@:: :@: :::::@: :@ :@@@:::::@::@:@:::@#:::: - | :: :@::: :@ ::@:@: :@::::@::::::::@:::@::@@@:::::@::@:@:::@#:::: - | :@::::@::: :@:::@:@: :@::::@::::::::@:::@::@@@:::::@::@:@:::@#:::: - | :::::@::::@::: :@:::@:@: :@::::@::::::::@:::@::@@@:::::@::@:@:::@#:::: - | ::: :@::::@::: :@:::@:@: :@::::@::::::::@:::@::@@@:::::@::@:@:::@#:::: - | :::: :@::::@::: :@:::@:@: :@::::@::::::::@:::@::@@@:::::@::@:@:::@#:::: - | :::: :@::::@::: :@:::@:@: :@::::@::::::::@:::@::@@@:::::@::@:@:::@#:::: - | :::: :@::::@::: :@:::@:@: :@::::@::::::::@:::@::@@@:::::@::@:@:::@#:::: - | :::: :@::::@::: :@:::@:@: :@::::@::::::::@:::@::@@@:::::@::@:@:::@#:::: - | :::: :@::::@::: :@:::@:@: :@::::@::::::::@:::@::@@@:::::@::@:@:::@#:::: - | :::: :@::::@::: :@:::@:@: :@::::@::::::::@:::@::@@@:::::@::@:@:::@#:::: - 0 +----------------------------------------------------------------------->GB - 0 3.231 - - FF peaks at around 1.4 GB after 12.5 GB worth of allocations, - whereas the Lua implementation arrives at around 45 MB after 3.2 GB - total: - - impl time(B) total(B) useful-heap(B) extra-heap(B) - fontforge 12,496,407,184 1,421,150,144 1,327,888,638 93,261,506 - lua 3,263,698,960 45,478,640 37,231,892 8,246,748 - - Much of the inefficiency of Fontforge is a direct consequence of - having to parse the entire font to extract what essentially boils - down to a couple hundred bytes of metadata per font. Since some - information like design sizes (oh, Adobe!) is stuffed away in - Opentype tables, the vastly more efficient approach of - fontloader.info() proves insufficient for indexing. Thus, we ended - up using fontloader.open() which causes even the character tables - to be parsed, which incidentally are responsible for most of the - allocations during that peak of 1.4 GB measured above, along with - the encodings: - - 20.67% (293,781,048B) 0x6A8F72: SplineCharCreate (splineutil.c:3878) - 09.82% (139,570,318B) 0x618ACD: _FontViewBaseCreate (fontviewbase.c:84) - 08.77% (124,634,384B) 0x6A8FB3: SplineCharCreate (splineutil.c:3885) - 04.53% (64,436,904B) in 80 places, all below massif's threshold (1.00%) - 02.68% (38,071,520B) 0x64E14E: addKernPair (parsettfatt.c:493) - 01.04% (14,735,320B) 0x64DE7D: addPairPos (parsettfatt.c:452) - 39.26% (557,942,484B) 0x64A4E0: PsuedoEncodeUnencoded (parsettf.c:5706) - - What gives? For 2.7 we expect a rougher transition than a year back - due to the complete revamp of the OT loading code. Breakage of - fragile aspects like font and style names has been anticipated and - addressed prior to the 2016 pretest release. In contrast to the - earlier approach of letting FF do a complete dump and then harvest - identifiers from the output we now have to coordinate with upstream - as to which fields are actually needed in order to provide a - similarly acceptable name → file lookup. On the bright side, these - things are a lot simpler to fix than the rather tedious work of - having users update their Luatex binary =) - ---doc]]-- - -local lpeg = require "lpeg" -local P, lpegmatch = lpeg.P, lpeg.match - -local log = luaotfload.log -local logreport = log and log.report or print -- overriden later on -local report_status = log.names_status -local report_status_start = log.names_status_start -local report_status_stop = log.names_status_stop - - ---- Luatex builtins -local load = load -local next = next -local require = require -local tonumber = tonumber -local unpack = table.unpack - -local fonts = fonts or { } -local fontshandlers = fonts.handlers or { } -local otfhandler = fonts.handlers.otf or { } -fonts.handlers = fontshandlers - -local gzipload = gzip.load -local gzipsave = gzip.save -local iolines = io.lines -local ioopen = io.open -local iopopen = io.popen -local kpseexpand_path = kpse.expand_path -local kpsefind_file = kpse.find_file -local kpselookup = kpse.lookup -local kpsereadable_file = kpse.readable_file -local lfsattributes = lfs.attributes -local lfschdir = lfs.chdir -local lfscurrentdir = lfs.currentdir -local lfsdir = lfs.dir -local mathabs = math.abs -local mathmin = math.min -local osgetenv = os.getenv -local osgettimeofday = os.gettimeofday -local osremove = os.remove -local stringfind = string.find -local stringformat = string.format -local stringgmatch = string.gmatch -local stringgsub = string.gsub -local stringlower = string.lower -local stringsub = string.sub -local stringupper = string.upper -local tableconcat = table.concat -local tablesort = table.sort -local utf8gsub = unicode.utf8.gsub -local utf8lower = unicode.utf8.lower -local utf8len = unicode.utf8.len - ---- these come from Lualibs/Context -local filebasename = file.basename -local filecollapsepath = file.collapsepath or file.collapse_path -local filedirname = file.dirname -local fileextname = file.extname -local fileiswritable = file.iswritable -local filejoin = file.join -local filenameonly = file.nameonly -local filereplacesuffix = file.replacesuffix -local filesplitpath = file.splitpath or file.split_path -local filesuffix = file.suffix -local getwritablepath = caches.getwritablepath -local lfsisdir = lfs.isdir -local lfsisfile = lfs.isfile -local lfsmkdirs = lfs.mkdirs -local lpegsplitat = lpeg.splitat -local stringis_empty = string.is_empty -local stringsplit = string.split -local stringstrip = string.strip -local tableappend = table.append -local tablecontains = table.contains -local tablecopy = table.copy -local tablefastcopy = table.fastcopy -local tabletofile = table.tofile -local tabletohash = table.tohash -local tableserialize = table.serialize -local names = fonts and fonts.names or { } - -local name_index = nil --> upvalue for names.data -local lookup_cache = nil --> for names.lookups - ---- string -> (string * string) -local make_luanames = function (path) - return filereplacesuffix(path, "lua"), - filereplacesuffix(path, "luc") -end - -local format_precedence = { - "otf", "ttc", "ttf", "afm", "pfb" -} - -local location_precedence = { - "local", "system", "texmf", -} - -local set_location_precedence = function (precedence) - location_precedence = precedence -end - ---[[doc-- - - Auxiliary functions - ---doc]]-- - ---- fontnames contain all kinds of garbage; as a precaution we ---- lowercase and strip them of non alphanumerical characters - ---- string -> string - -local invalidchars = "[^%a%d]" - -local sanitize_fontname = function (str) - if str ~= nil then - str = utf8gsub (utf8lower (str), invalidchars, "") - return str - end - return nil -end - -local sanitize_fontnames = function (rawnames) - local result = { } - for category, namedata in next, rawnames do - - if type (namedata) == "string" then - result [category] = utf8gsub (utf8lower (namedata), - invalidchars, - "") - else - local target = { } - for field, name in next, namedata do - target [field] = utf8gsub (utf8lower (name), - invalidchars, - "") - end - result [category] = target - end - end - return result -end - -local find_files_indeed -find_files_indeed = function (acc, dirs, filter) - if not next (dirs) then --- done - return acc - end - - local pwd = lfscurrentdir () - local dir = dirs[#dirs] - dirs[#dirs] = nil - - if lfschdir (dir) then - lfschdir (pwd) - - local newfiles = { } - for ent in lfsdir (dir) do - if ent ~= "." and ent ~= ".." then - local fullpath = dir .. "/" .. ent - if filter (fullpath) == true then - if lfsisdir (fullpath) then - dirs[#dirs+1] = fullpath - elseif lfsisfile (fullpath) then - newfiles[#newfiles+1] = fullpath - end - end - end - end - return find_files_indeed (tableappend (acc, newfiles), - dirs, filter) - end - --- could not cd into, so we skip it - return find_files_indeed (acc, dirs, filter) -end - -local dummyfilter = function () return true end - ---- the optional filter function receives the full path of a file ---- system entity. a filter applies if the first argument it returns is ---- true. - ---- string -> function? -> string list -local find_files = function (root, filter) - if lfsisdir (root) then - return find_files_indeed ({}, { root }, filter or dummyfilter) - end -end - - ---[[doc-- -This is a sketch of the luaotfload db: - - type dbobj = { - families : familytable; - files : filemap; - status : filestatus; - mappings : fontentry list; - meta : metadata; - } - and familytable = { - local : (format, familyentry) hash; // specified with include dir - texmf : (format, familyentry) hash; - system : (format, familyentry) hash; - } - and familyentry = { - r : sizes; // regular - i : sizes; // italic - b : sizes; // bold - bi : sizes; // bold italic - } - and sizes = { - default : int; // points into mappings or names - optical : (int, int) list; // design size -> index entry - } - and metadata = { - created : string // creation time - formats : string list; // { "otf", "ttf", "ttc" } - local : bool; (* set if local fonts were added to the db *) - modified : string // modification time - statistics : TODO; // created when built with "--stats" - version : float; // index version - } - and filemap = { // created by generate_filedata() - base : { - local : (string, int) hash; // basename -> idx - system : (string, int) hash; - texmf : (string, int) hash; - }; - bare : { - local : (string, (string, int) hash) hash; // location -> (barename -> idx) - system : (string, (string, int) hash) hash; - texmf : (string, (string, int) hash) hash; - }; - full : (int, string) hash; // idx -> full path - } - and fontentry = { // finalized by collect_families() - basename : string; // file name without path "foo.otf" - conflicts : { barename : int; basename : int }; // filename conflict with font at index; happens with subfonts - familyname : string; // sanitized name of the font family the font belongs to, usually from the names table - fontname : string; // sanitized name of the font - format : string; // "otf" | "ttf" | "afm" (* | "pfb" *) - fullname : string; // sanitized full name of the font including style modifiers - fullpath : string; // path to font in filesystem - index : int; // index in the mappings table - italicangle : float; // italic angle; non-zero with oblique faces - location : string; // "texmf" | "system" | "local" - metafamily : string; // alternative family identifier if appropriate, sanitized - plainname : string; // unsanitized font name - typographicsubfamily : string; // sanitized preferred subfamily (names table 14) - psname : string; // PostScript name - size : (false | float * float * float); // if available, size info from the size table converted from decipoints - subfamily : string; // sanitized subfamily (names table 2) - subfont : (int | bool); // integer if font is part of a TrueType collection ("ttc") - version : string; // font version string - weight : int; // usWeightClass - } - and filestatus = (string, // fullname - { index : int list; // pointer into mappings - timestamp : int; }) dict - -beware that this is a reconstruction and may be incomplete or out of -date. Last update: 2014-04-06, describing version 2.51. - -mtx-fonts has in names.tma: - - type names = { - cache_uuid : uuid; - cache_version : float; - datastate : uuid list; - fallbacks : (filetype, (basename, int) hash) hash; - families : (basename, int list) hash; - files : (filename, fullname) hash; - indices : (fullname, int) hash; - mappings : (filetype, (basename, int) hash) hash; - names : ? (empty hash) ?; - rejected : (basename, int) hash; - specifications: fontentry list; - } - and fontentry = { - designsize : int; - familyname : string; - filename : string; - fontname : string; - format : string; - fullname : string; - maxsize : int; - minsize : int; - modification : int; - rawname : string; - style : string; - subfamily : string; - variant : string; - weight : string; - width : string; - } - ---doc]]-- - ---- string list -> string option -> dbobj - -local initialize_namedata = function (formats, created) - local now = os.date "%Y-%m-%d %H:%M:%S" --- i. e. "%F %T" on POSIX systems - return { - status = { }, -- was: status; map abspath -> mapping - mappings = { }, -- TODO: check if still necessary after rewrite - files = { }, -- created later - meta = { - created = created or now, - formats = formats, - ["local"] = false, - modified = now, - statistics = { }, - version = names.version, - }, - } -end - ---- When loading a lua file we try its binary complement first, which ---- is assumed to be located at an identical path, carrying the suffix ---- .luc. - ---- string -> (string * table) -local load_lua_file = function (path) - local foundname = filereplacesuffix (path, "luc") - local code = nil - - local fh = ioopen (foundname, "rb") -- try bin first - if fh then - local chunk = fh:read"*all" - fh:close() - code = load (chunk, "b") - end - - if not code then --- fall back to text file - foundname = filereplacesuffix (path, "lua") - fh = ioopen(foundname, "rb") - if fh then - local chunk = fh:read"*all" - fh:close() - code = load (chunk, "t") - end - end - - if not code then --- probe gzipped file - foundname = filereplacesuffix (path, "lua.gz") - local chunk = gzipload (foundname) - if chunk then - code = load (chunk, "t") - end - end - - if not code then return nil, nil end - return foundname, code () -end - ---- define locals in scope -local access_font_index -local find_closest -local flush_lookup_cache -local generate_filedata -local get_font_filter -local group_modifiers -local load_names -local lookup_font_name -local getmetadata -local order_design_sizes -local ot_fullinfo -local read_blacklist -local reload_db -local lookup_fullpath -local save_lookups -local save_names -local set_font_filter -local t1_fullinfo -local update_names - ---- state of the database -local fonts_reloaded = false - ---- limit output when approximate font matching (luaotfload-tool -F) -local fuzzy_limit = 1 --- display closest only - ---- bool? -> -> bool? -> dbobj option -load_names = function (dry_run, no_rebuild) - local starttime = osgettimeofday () - local foundname, data = load_lua_file (config.luaotfload.paths.index_path_lua) - - if data then - logreport ("log", 0, "db", - "Font names database loaded from %s", foundname) - logreport ("term", 3, "db", - "Font names database loaded from %s", foundname) - logreport ("info", 3, "db", "Loading took %0.f ms.", - 1000 * (osgettimeofday () - starttime)) - - local db_version, names_version - if data.meta then - db_version = data.meta.version - else - --- Compatibility branch; the version info used to be - --- stored in the table root which is why updating from - --- an earlier index version broke. - db_version = data.version or -42 --- invalid - end - names_version = names.version - if db_version ~= names_version then - logreport ("both", 0, "db", - [[Version mismatch; expected %d, got %d.]], - names_version, db_version) - if not fonts_reloaded then - logreport ("both", 0, "db", [[Force rebuild.]]) - data = update_names (initialize_namedata (get_font_filter ()), - true, false) - if not data then - logreport ("both", 0, "db", - "Database creation unsuccessful.") - end - end - end - else - if no_rebuild == true then - logreport ("both", 2, "db", - [[Database does not exist, skipping rebuild though.]]) - return false - end - logreport ("both", 0, "db", - [[Font names database not found, generating new one.]]) - logreport ("both", 0, "db", - [[This can take several minutes; please be patient.]]) - data = update_names (initialize_namedata (get_font_filter ()), - nil, dry_run) - if not data then - logreport ("both", 0, "db", "Database creation unsuccessful.") - end - end - return data -end - ---[[doc-- - - access_font_index -- Provide a reference of the index table. Will - cause the index to be loaded if not present. - ---doc]]-- - -access_font_index = function () - if not name_index then name_index = load_names () end - return name_index -end - -getmetadata = function () - if not name_index then - name_index = load_names (false, true) - if name_index then return tablefastcopy (name_index.meta) end - end - return false -end - ---- unit -> unit -local load_lookups -load_lookups = function ( ) - local foundname, data = load_lua_file(config.luaotfload.paths.lookup_path_lua) - if data then - logreport ("log", 0, "cache", "Lookup cache loaded from %s.", foundname) - logreport ("term", 3, "cache", - "Lookup cache loaded from %s.", foundname) - else - logreport ("both", 1, "cache", - "No lookup cache, creating empty.") - data = { } - end - lookup_cache = data -end - -local regular_synonym = { - book = true, - normal = true, - plain = true, - regular = true, - roman = true, -} - -local italic_synonym = { - oblique = true, - slanted = true, - italic = true, -} - -local bold_synonym = { - bold = true, - black = true, - heavy = true, -} - -local style_category = { - regular = "r", - bold = "b", - bolditalic = "bi", - italic = "i", - r = "regular", - b = "bold", - bi = "bolditalic", - i = "italic", -} - -local type1_metrics = { "tfm", "ofm", } - -local lookup_filename = function (filename) - if not name_index then name_index = load_names () end - local files = name_index.files - local basedata = files.base - local baredata = files.bare - for i = 1, #location_precedence do - local location = location_precedence [i] - local basenames = basedata [location] - local barenames = baredata [location] - local idx - if basenames ~= nil then - idx = basenames [filename] - if idx then - goto done - end - end - if barenames ~= nil then - for j = 1, #format_precedence do - local format = format_precedence [j] - local filemap = barenames [format] - if filemap then - idx = barenames [format] [filename] - if idx then - break - end - end - end - end -::done:: - if idx then - return files.full [idx] - end - end -end - ---[[doc-- - - lookup_font_file -- The ``file:`` are ultimately delegated here. - The lookups are kind of a blunt instrument since they try locating - the file using every conceivable method, which is quite - inefficient. Nevertheless, resolving files that way is rarely the - bottleneck. - ---doc]]-- - -local dummy_findfile = resolvers.findfile -- from basics-gen - ---- string -> string * string * bool -local lookup_font_file -lookup_font_file = function (filename) - local found = lookup_filename (filename) - - if not found then - found = dummy_findfile(filename) - end - - if found then - return found, nil, true - end - - for i=1, #type1_metrics do - local format = type1_metrics[i] - if resolvers.findfile(filename, format) then - return file.addsuffix(filename, format), format, true - end - end - - if not fonts_reloaded and config.luaotfload.db.update_live == true then - return reload_db (stringformat ("File not found: %s.", filename), - lookup_font_file, - filename) - end - return filename, nil, false -end - ---[[doc-- - - get_font_file -- Look up the file of an entry in the mappings - table. If the index is valid, pass on the name and subfont index - after verifing the existence of the resolved file. This - verification differs depending the index entry’s ``location`` - field: - - * ``texmf`` fonts are verified using the (slow) function - ``kpse.lookup()``; - * other locations are tested by resolving the full path and - checking for the presence of a file there. - ---doc]]-- - ---- int -> bool * (string * int) option -local get_font_file = function (index) - local entry = name_index.mappings [index] - if not entry then - return false - end - local basename = entry.basename - if entry.location == "texmf" then - if kpselookup(basename) then - return true, basename, entry.subfont - end - else --- system, local - local fullname = name_index.files.full [index] - if lfsisfile (fullname) then - return true, basename, entry.subfont - end - end - return false -end - ---[[doc-- -We need to verify if the result of a cached lookup actually exists in -the texmf or filesystem. Again, due to the schizoprenic nature of the -font managment we have to check both the system path and the texmf. ---doc]]-- - -local verify_font_file = function (basename) - local path = lookup_fullpath (basename) - if path and lfsisfile(path) then - return true - end - if kpsefind_file(basename) then - return true - end - return false -end - ---[[doc-- -Lookups can be quite costly, more so the less specific they are. -Even if we find a matching font eventually, the next time the -user compiles Eir document E will have to stand through the delay -again. -Thus, some caching of results -- even between runs -- is in order. -We’ll just store successful name: lookups in a separate cache file. - -type lookup_cache = (string, (string * num)) dict - -The spec is expected to be modified in place (ugh), so we’ll have to -catalogue what fields actually influence its behavior. - -Idk what the “spec” resolver is for. - - lookup inspects modifies - ---------- ----------------- --------------------------- - file: name forced, name - name:[*] name, style, sub, resolved, sub, name, forced - optsize, size - spec: name, sub resolved, sub, name, forced - -[*] name: contains both the name resolver from luatex-fonts and - lookup_font_name () below - -From my reading of font-def.lua, what a resolver does is -basically rewrite the “name” field of the specification record -with the resolution. -Also, the fields “resolved”, “sub”, “force” etc. influence the outcome. - ---doc]]-- - -local concat_char = "#" -local hash_fields = { - --- order is important - "specification", "style", "sub", "optsize", "size", -} -local n_hash_fields = #hash_fields - ---- spec -> string -local hash_request = function (specification) - local key = { } --- segments of the hash - for i=1, n_hash_fields do - local field = specification[hash_fields[i]] - if field then - key[#key+1] = field - end - end - return tableconcat(key, concat_char) -end - ---- 'a -> 'a -> table -> (string * int|boolean * boolean) -local lookup_font_name_cached -lookup_font_name_cached = function (specification) - if not lookup_cache then load_lookups () end - local request = hash_request(specification) - logreport ("both", 4, "cache", "Looking for %q in cache ...", - request) - - local found = lookup_cache [request] - - --- case 1) cache positive ---------------------------------------- - if found then --- replay fields from cache hit - logreport ("info", 4, "cache", "Found!") - local basename = found[1] - --- check the presence of the file in case it’s been removed - local success = verify_font_file (basename) - if success == true then - return basename, found[2], true - end - logreport ("both", 4, "cache", - "Cached file not found; resolving again.") - else - logreport ("both", 4, "cache", "Not cached; resolving.") - end - - --- case 2) cache negative ---------------------------------------- - --- first we resolve normally ... - local filename, subfont = lookup_font_name (specification) - if not filename then - return nil, nil - end - --- ... then we add the fields to the cache ... ... - local entry = { filename, subfont } - logreport ("both", 4, "cache", "New entry: %s.", request) - lookup_cache [request] = entry - - --- obviously, the updated cache needs to be stored. - --- TODO this should trigger a save only once the - --- document is compiled (finish_pdffile callback?) - logreport ("both", 5, "cache", "Saving updated cache.") - local success = save_lookups () - if not success then --- sad, but not critical - logreport ("both", 0, "cache", "Error writing cache.") - end - return filename, subfont -end - ---- this used to be inlined; with the lookup cache we don’t ---- have to be parsimonious wrt function calls anymore ---- “found” is the match accumulator -local add_to_match = function (found, size, face) - - local continue = true - - local optsize = face.size - - if optsize and next (optsize) then - local dsnsize, maxsize, minsize - dsnsize = optsize[1] - maxsize = optsize[2] - minsize = optsize[3] - - if size ~= nil - and (dsnsize == size or (size > minsize and size <= maxsize)) - then - found[1] = face - continue = false ---> break - else - found[#found+1] = face - end - else - found[1] = face - continue = false ---> break - end - - return found, continue -end - -local choose_closest = function (distances) - local closest = 2^51 - local match - for i = 1, #distances do - local d, index = unpack (distances [i]) - if d < closest then - closest = d - match = index - end - end - return match -end - ---[[doc-- - - choose_size -- Pick a font face of appropriate size (in sp) from - the list of family members with matching style. There are three - categories: - - 1. exact matches: if there is a face whose design size equals - the asked size, it is returned immediately and no further - candidates are inspected. - - 2. range matches: of all faces in whose design range the - requested size falls the one whose center the requested - size is closest to is returned. - - 3. out-of-range matches: of all other faces (i. e. whose range - is above or below the asked size) the one is chosen whose - boundary (upper or lower) is closest to the requested size. - - 4. default matches: if no design size or a design size of zero - is requested, the face with the default size is returned. - ---doc]]-- - ---- int * int * int * int list -> int -> int -local choose_size = function (sizes, askedsize) - local mappings = name_index.mappings - local match = sizes.default - local exact - local inrange = { } --- distance * index list - local norange = { } --- distance * index list - local fontname, subfont - if askedsize ~= 0 then - --- firstly, look for an exactly matching design size or - --- matching range - for i = 1, #sizes do - local dsnsize, high, low, index = unpack (sizes [i]) - if dsnsize == askedsize then - --- exact match, this is what we were looking for - exact = index - goto skip - elseif askedsize <= low then - --- below range, add to the norange table - local d = low - askedsize - norange [#norange + 1] = { d, index } - elseif askedsize > high then - --- beyond range, add to the norange table - local d = askedsize - high - norange [#norange + 1] = { d, index } - else - --- range match - local d = 0 - - -- should always be true. Just in case there's some - -- weried fonts out there - if dsnsize > low and dsnsize < high then - d = dsnsize - askedsize - else - d = ((low + high) / 2) - askedsize - end - if d < 0 then - d = -d - end - - inrange [#inrange + 1] = { d, index } - end - end - end -::skip:: - if exact then - match = exact - elseif #inrange > 0 then - match = choose_closest (inrange) - elseif #norange > 0 then - match = choose_closest (norange) - end - return match -end - ---[[doc-- - - lookup_familyname -- Query the families table for an entry - matching the specification. - The parameters “name” and “style” are pre-sanitized. - ---doc]]-- ---- spec -> string -> string -> int -> string * int -local lookup_familyname = function (specification, name, style, askedsize) - local families = name_index.families - local mappings = name_index.mappings - local candidates = nil - --- arrow code alert - for i = 1, #location_precedence do - local location = location_precedence [i] - local locgroup = families [location] - for j = 1, #format_precedence do - local format = format_precedence [j] - local fmtgroup = locgroup [format] - if fmtgroup then - local familygroup = fmtgroup [name] - if familygroup then - local stylegroup = familygroup [style] - if stylegroup then --- suitable match - candidates = stylegroup - goto done - end - end - end - end - end - if true then - return nil, nil - end -::done:: - index = choose_size (candidates, askedsize) - local success, resolved, subfont = get_font_file (index) - if not success then - return nil, nil - end - logreport ("info", 2, "db", "Match found: %s(%d).", - resolved, subfont or 0) - return resolved, subfont -end - -local lookup_fontname = function (specification, name, style) - local mappings = name_index.mappings - local fallback = nil - local lastresort = nil - style = style_category [style] - for i = 1, #mappings do - local face = mappings [i] - local typographicsubfamily = face.typographicsubfamily - local subfamily = face.subfamily - if face.fontname == name - or face.fullname == name - or face.psname == name - then - return face.basename, face.subfont - elseif face.familyname == name then - if typographicsubfamily == style - or subfamily == style - then - fallback = face - elseif regular_synonym [typographicsubfamily] - or regular_synonym [subfamily] - then - lastresort = face - end - elseif face.metafamily == name - and ( regular_synonym [typographicsubfamily] - or regular_synonym [subfamily]) - then - lastresort = face - end - end - if fallback then - return fallback.basename, fallback.subfont - end - if lastresort then - return lastresort.basename, lastresort.subfont - end - return nil, nil -end - -local design_size_dimension --- scale asked size if not using bp -local set_size_dimension --- called from config -do - - --- cf. TeXbook p. 57; the index stores sizes pre-scaled from bp to - --- sp. This allows requesting sizes we got from the TeX end - --- without further conversion. For the other options *pt* and *dd* - --- we scale the requested size as though the value in the font was - --- specified in the requested unit. - - --- From @zhouyan: - - --- Let P be the asked size in pt, and Aᵤ = CᵤP, where u is the - --- designed unit, pt, bp, or dd, and - --- - --- Cpt = 1, Cbp = 7200/7227, Cdd = 1157/1238. - --- - --- That is, Aᵤ is the asked size in the desired unit. Let D be the - --- de-sign size (assumed to be in the unit of bp) as reported by - --- the font (divided by 10; in all the following we ignore the - --- factor 2^16 ). - --- - --- For simplicity, consider only the case of exact match to the - --- design size. That is, we would like to have Aᵤ = D. Let A′ᵤ = αᵤP - --- and D′ = βD be the scaled values used in comparisons. For the - --- comparison to work correctly, we need, - --- - --- Aᵤ = D ⟺ A′ᵤ = D′ , - --- - --- and thus αᵤ = βCᵤ. The fix in PR 400 is the case of β = 1. The - --- fix for review is β = 7227/7200, and the value of αᵤ is thus - --- correct for pt, bp, but not for dd. - - local dimens = { - bp = false, - pt = 7227 / 7200, - dd = (7227 / 7200) * (1157 / 1238), - } - - design_size_dimension = dimens.bp - - set_size_dimension = function (dim) - local conv = dimens [dim] - if conv ~= nil then - logreport ("both", 4, "db", - "Interpreting design sizes as %q, factor %.6f.", - dim, conv) - design_size_dimension = conv - return - end - logreport ("both", 0, "db", - "Invalid dimension %q requested for design sizes; \z - ignoring.") - end -end - - ---[[doc-- - - lookup_font_name -- Perform a name: lookup. This first queries the - font families table and, if there is no match for the spec, the - font names table. - The return value is a pair consisting of the file name and the - subfont index if appropriate.. - - the request specification has the fields: - - · features: table - · normal: set of { ccmp clig itlc kern liga locl mark mkmk rlig } - · ??? - · forced: string - · lookup: "name" - · method: string - · name: string - · resolved: string - · size: int - · specification: string (== <lookup> ":" <name>) - · sub: string - - The “size” field deserves special attention: if its value is - negative, then it actually specifies a scalefactor of the - design size of the requested font. This happens e.g. if a font is - requested without an explicit “at size”. If the font is part of a - larger collection with different design sizes, this complicates - matters a bit: Normally, the resolver prefers fonts that have a - design size as close as possible to the requested size. If no - size specified, then the design size is implied. But which design - size should that be? Xetex appears to pick the “normal” (unmarked) - size: with Adobe fonts this would be the one that is neither - “caption” nor “subhead” nor “display” &c ... For fonts by Adobe this - seems to be the one that does not receive a “typographicsubfamily” - field. (IOW Adobe uses the “typographicsubfamily” field to encode - the design size in more or less human readable format.) However, - this is not true of LM and EB Garamond. As this matters only where - there are multiple design sizes to a given font/style combination, - we put a workaround in place that chooses that unmarked version. - - The first return value of “lookup_font_name” is the file name of the - requested font (string). It can be passed to the fullname resolver - get_font_file(). - The second value is either “false” or an integer indicating the - subfont index in a TTC. - ---doc]]-- - ---- table -> string * (int | bool) -lookup_font_name = function (specification) - local resolved, subfont - if not name_index then name_index = load_names () end - local name = sanitize_fontname (specification.name) - local style = sanitize_fontname (specification.style) or "r" - local askedsize = specification.optsize - - if askedsize then - askedsize = tonumber (askedsize) * 65536 - else - askedsize = specification.size - if not askedsize or askedsize < 0 then - askedsize = 0 - end - end - - if design_size_dimension ~= false then - askedsize = design_size_dimension * askedsize - end - - resolved, subfont = lookup_familyname (specification, - name, - style, - askedsize) - if not resolved then - resolved, subfont = lookup_fontname (specification, - name, - style) - end - - if not resolved then - if not fonts_reloaded and config.luaotfload.db.update_live == true then - return reload_db (stringformat ("Font %s not found.", - specification.name or "<?>"), - lookup_font_name, - specification) - end - end - return resolved, subfont -end - -lookup_fullpath = function (fontname, ext) --- getfilename() - if not name_index then name_index = load_names () end - local files = name_index.files - local basedata = files.base - local baredata = files.bare - for i = 1, #location_precedence do - local location = location_precedence [i] - local basenames = basedata [location] - local idx - if basenames ~= nil then - idx = basenames [fontname] - end - if ext then - local barenames = baredata [location] [ext] - if not idx and barenames ~= nil then - idx = barenames [fontname] - end - end - if idx then - return files.full [idx] - end - end - return "" -end - ---- when reload is triggered we update the database ---- and then re-run the caller with the arg list - ---- string -> ('a -> 'a) -> 'a list -> 'a -reload_db = function (why, caller, ...) - local namedata = name_index - local formats = tableconcat (namedata.meta.formats, ",") - - logreport ("both", 0, "db", - "Reload initiated (formats: %s); reason: %q.", - formats, why) - - set_font_filter (formats) - namedata = update_names (namedata, false, false) - - if namedata then - fonts_reloaded = true - name_index = namedata - return caller (...) - end - - logreport ("both", 0, "db", "Database update unsuccessful.") -end - ---- string -> string -> int -local iterative_levenshtein = function (s1, s2) - - local costs = { } - local len1, len2 = #s1, #s2 - - for i = 0, len1 do - local last = i - for j = 0, len2 do - if i == 0 then - costs[j] = j - else - if j > 0 then - local current = costs[j-1] - if stringsub(s1, i, i) ~= stringsub(s2, j, j) then - current = mathmin(current, last, costs[j]) + 1 - end - costs[j-1] = last - last = current - end - end - end - if i > 0 then costs[len2] = last end - end - - return costs[len2]--- lower right has the distance -end - ---- string list -> string list -local delete_dupes = function (lst) - local n0 = #lst - if n0 == 0 then return lst end - tablesort (lst) - local ret = { } - local last - for i = 1, n0 do - local cur = lst[i] - if cur ~= last then - last = cur - ret[#ret + 1] = cur - end - end - logreport (false, 8, "query", - "Removed %d duplicate names.", n0 - #ret) - return ret -end - ---- string -> int -> bool -find_closest = function (name, limit) - local name = sanitize_fontname (name) - limit = limit or fuzzy_limit - - if not name_index then name_index = load_names () end - if not name_index or type (name_index) ~= "table" then - if not fonts_reloaded then - return reload_db("Font index missing.", find_closest, name) - end - return false - end - - local by_distance = { } --- (int, string list) dict - local distances = { } --- int list - local cached = { } --- (string, int) dict - local mappings = name_index.mappings - local n_fonts = #mappings - - for n = 1, n_fonts do - local current = mappings[n] - --[[ - This is simplistic but surpisingly fast. - Matching is performed against the “fullname” field - of a db record in preprocessed form. We then store the - raw “fullname” at its edit distance. - We should probably do some weighting over all the - font name categories as well as whatever agrep - does. - --]] - local fullname = current.plainname - local sfullname = current.fullname - local dist = cached[sfullname]--- maybe already calculated - - if not dist then - dist = iterative_levenshtein(name, sfullname) - cached[sfullname] = 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 - 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) - logreport (false, 1, "query", - "Displaying %d distance levels.", limit) - - for i = 1, limit do - local dist = distances[i] - local namelst = delete_dupes (by_distance[dist]) - logreport (false, 0, "query", - "Distance from \"%s\": %s\n " - .. tableconcat (namelst, "\n "), - name, dist) - end - - return true - end - return false -end --- find_closest() - ---- string -> uint -> bool * (string | rawdata) -local read_font_file = function (filename, subfont) - local fontdata = otfhandler.readers.getinfo (filename, - { subfont = subfont - , details = false - , platformnames = true - , rawfamilynames = true - }) - local msg = fontdata.comment - if msg then - return false, msg - end - return true, fontdata -end - -local load_font_file = function (filename, subfont) - local err, ret = read_font_file (filename, subfont) - if err == false then - logreport ("both", 1, "db", "ERROR: failed to open %q: %q.", - tostring (filename), tostring (ret)) - return - end - return ret -end - ---- Design sizes in the fonts are specified in decipoints. For the ---- index these values are prescaled to sp which is what we’re dealing ---- with at the TeX end. - -local get_size_info do --- too many upvalues :/ - --- rawdata -> (int * int * int | bool) - - local sp = 2^16 -- pt - local bp = 7227 / 7200 -- pt - - get_size_info = function (rawinfo) - local design_size = rawinfo.design_size - local design_range_top = rawinfo.design_range_top - local design_range_bottom = rawinfo.design_range_bottom - - local fallback_size = design_size ~= 0 and design_size - or design_range_bottom ~= 0 and design_range_bottom - or design_range_top ~= 0 and design_range_top - - if fallback_size then - design_size = ((design_size or fallback_size) * sp) / 10 - design_range_top = ((design_range_top or fallback_size) * sp) / 10 - design_range_bottom = ((design_range_bottom or fallback_size) * sp) / 10 - - design_size = design_size * bp - design_range_top = design_range_top * bp - design_range_bottom = design_range_bottom * bp - - return { - design_size, design_range_top, design_range_bottom, - } - end - - return false - end -end ---[local get_size_info] - ---[[doc-- - map_enlish_names -- Names-table for Lua fontloader objects. This - may vanish eventually once we ditch Fontforge completely. Only - subset of entries of that table are actually relevant so we’ll - stick to that part. ---doc]]-- - -local get_english_names = function (metadata) - local namesource - local platformnames = metadata.platformnames - --[[-- - Hans added the “platformnames” option for us to access parts of - the original name table. The names are unreliable and - completely disorganized, sure, but the Windows variant of the - field often contains the superior information. Case in point: - - ["platformnames"]={ - ["macintosh"]={ - ["compatiblefullname"]="Garamond Premr Pro Smbd It", - ["family"]="Garamond Premier Pro", - ["fullname"]="Garamond Premier Pro Semibold Italic", - ["postscriptname"]="GaramondPremrPro-SmbdIt", - ["subfamily"]="Semibold Italic", - }, - ["windows"]={ - ["family"]="Garamond Premr Pro Smbd", - ["fullname"]="GaramondPremrPro-SmbdIt", - ["postscriptname"]="GaramondPremrPro-SmbdIt", - ["subfamily"]="Italic", - ["typographicfamily"]="Garamond Premier Pro", - ["typographicsubfamily"]="Semibold Italic", - }, - }, - - The essential bit is contained as “typographicfamily” (which we - call for historical reasons the “preferred family”) and the - “subfamily”. Only Why this is the case, only Adobe knows for - certain. - --]]-- - if platformnames then - --namesource = platformnames.macintosh or platformnames.windows - namesource = platformnames.windows or platformnames.macintosh - end - return namesource or metadata -end - ---[[-- - In case of broken PS names we set some dummies. - - For this reason we copy what is necessary whilst keeping the table - structure the same as in the tfmdata. ---]]-- -local get_raw_info = function (metadata, basename) - local fontname = metadata.fontname - local fullname = metadata.fullname - - if not fontname or not fullname then - --- Broken names table, e.g. avkv.ttf with UTF-16 strings; - --- we put some dummies in place like the fontloader - --- (font-otf.lua) does. - logreport ("both", 3, "db", - "Invalid names table of font %s, using dummies. \z - Reported: fontname=%q, fullname=%q.", - tostring (basename), tostring (fontname), - tostring (fullname)) - fontname = "bad-fontname-" .. basename - fullname = "bad-fullname-" .. basename - end - - return { - familyname = metadata.familyname, - fontname = fontname, - fullname = fullname, - italicangle = metadata.italicangle, - names = metadata.names, - units_per_em = metadata.units_per_em, - version = metadata.version, - design_size = metadata.design_size or metadata.designsize, - design_range_top = metadata.design_range_top or metadata.maxsize, - design_range_bottom = metadata.design_range_bottom or metadata.minsize, - } -end - -local organize_namedata = function (rawinfo, - nametable, - basename, - info) - local default_name = nametable.compatiblefullname - or nametable.fullname - or nametable.postscriptname - or rawinfo.fullname - or rawinfo.fontname - or info.fullname - or info.fontname - local default_family = nametable.typographicfamily - or nametable.family - or rawinfo.familyname - or info.familyname --- local default_modifier = nametable.typographicsubfamily --- or nametable.subfamily - local fontnames = { - --- see - --- https://developer.apple.com/fonts/TTRefMan/RM06/Chap6name.html - --- http://www.microsoft.com/typography/OTSPEC/name.htm#NameIDs - english = { - --- where a “compatiblefullname” field is given, the value - --- of “fullname” is either identical or differs by - --- separating the style with a hyphen and omitting spaces. - --- (According to the spec, “compatiblefullname” is - --- “Macintosh only”.) Of the three “fullname” fields, this - --- one appears to be the one with the entire name given in - --- a legible, non-abbreviated fashion, for most fonts at - --- any rate. However, in some fonts (e.g. CMU) all three - --- fields are identical. - fullname = --[[ 18 ]] nametable.compatiblefullname - or --[[ 4 ]] nametable.fullname - or default_name, - --- we keep both the “preferred family” and the “family” - --- values around since both are valid but can turn out - --- quite differently, e.g. with Latin Modern: - --- typographicfamily: “Latin Modern Sans”, - --- family: “LM Sans 10” - family = --[[ 1 ]] nametable.family or default_family, - subfamily = --[[ 2 ]] nametable.subfamily or rawinfo.subfamilyname, - psname = --[[ 6 ]] nametable.postscriptname, - typographicfamily = --[[ 16 ]] nametable.typographicfamily, - typographicsubfamily = --[[ 17 ]] nametable.typographicsubfamily, - }, - - metadata = { - fullname = rawinfo.fullname, - fontname = rawinfo.fontname, - familyname = rawinfo.familyname, - }, - - info = { - fullname = info.fullname, - familyname = info.familyname, - fontname = info.fontname, - }, - } - - return { - sanitized = sanitize_fontnames (fontnames), - fontname = rawinfo.fontname, - fullname = rawinfo.fullname, - familyname = rawinfo.familyname, - } -end - - -local dashsplitter = lpegsplitat "-" - -local split_fontname = function (fontname) - --- sometimes the style hides in the latter part of the - --- fontname, separated by a dash, e.g. “Iwona-Regular”, - --- “GFSSolomos-Regular” - local splitted = { lpegmatch (dashsplitter, fontname) } - if next (splitted) then - return sanitize_fontname (splitted [#splitted]) - end -end - -local organize_styledata = function (metadata, rawinfo, info) - local pfminfo = metadata.pfminfo - local names = rawinfo.names - return { - --- see http://www.microsoft.com/typography/OTSPEC/features_pt.htm#size - size = get_size_info (rawinfo), - pfmweight = pfminfo and pfminfo.weight or metadata.pfmweight or 400, - weight = rawinfo.weight or metadata.weight or "unspecified", - split = split_fontname (rawinfo.fontname), - width = pfminfo and pfminfo.width or metadata.pfmwidth, - italicangle = metadata.italicangle, - --- this is for querying, see www.ntg.nl/maps/40/07.pdf for details - units_per_em = metadata.units_per_em or metadata.units, - version = metadata.version, - } -end - ---[[doc-- -The data inside an Opentype font file can be quite heterogeneous. -Thus in order to get the relevant information, parts of the original -table as returned by the font file reader need to be relocated. ---doc]]-- - ---- string -> int -> bool -> string -> fontentry - -ot_fullinfo = function (filename, - subfont, - location, - basename, - format, - info) - - local metadata = load_font_file (filename, subfont) - if not metadata then - return nil - end - - local rawinfo = get_raw_info (metadata, basename) - local nametable = get_english_names (metadata) - local namedata = organize_namedata (rawinfo, - nametable, - basename, - info) - local style = organize_styledata (metadata, - rawinfo, - info) - - local res = { - file = { base = basename, - full = filename, - subfont = subfont, - location = location or "system" }, - format = format, - names = namedata, - style = style, - version = rawinfo.version, - } - return res -end - ---[[doc-- - - Type1 font inspector. In comparison with OTF, PFB’s contain a good - deal less name fields which makes it tricky in some parts to find a - meaningful representation for the database. - - Good read: http://www.adobe.com/devnet/font/pdfs/5004.AFM_Spec.pdf - ---doc]]-- - ---- string -> int -> bool -> string -> fontentry - -t1_fullinfo = function (filename, _subfont, location, basename, format) - local sanitized - local metadata = load_font_file (filename) - local fontname = metadata.fontname - local fullname = metadata.fullname - local familyname = metadata.familyname - local italicangle = metadata.italicangle - local style = "" - local weight - - sanitized = sanitize_fontnames ({ - fontname = fontname, - psname = fullname, - metafamily = familyname, - familyname = familyname, - weight = metadata.weight, --- string identifier - typographicsubfamily = style, - }) - - weight = sanitized.weight - - if weight == "bold" then - style = weight - end - - if italicangle ~= 0 then - style = style .. "italic" - end - - return { - basename = basename, - fullpath = filename, - subfont = false, - location = location or "system", - format = format, - fullname = sanitized.fullname, - fontname = sanitized.fontname, - familyname = sanitized.familyname, - plainname = fullname, - psname = sanitized.fontname, - version = metadata.version, - size = false, - typographicsubfamily = style ~= "" and style or weight, - weight = metadata.pfminfo and pfminfo.weight or 400, - italicangle = italicangle, - } -end - -local loaders = { - otf = ot_fullinfo, - ttc = ot_fullinfo, - ttf = ot_fullinfo, - afm = t1_fullinfo, - pfb = t1_fullinfo, -} - ---- not side-effect free! - -local compare_timestamps = function (fullname, - currentstatus, - currententrystatus, - currentmappings, - targetstatus, - targetentrystatus, - targetmappings) - - local currenttimestamp = currententrystatus - and currententrystatus.timestamp - local targettimestamp = lfsattributes (fullname, "modification") - - if targetentrystatus ~= nil - and targetentrystatus.timestamp == targettimestamp then - logreport ("log", 3, "db", "Font %q already read.", fullname) - return false - end - - targetentrystatus.timestamp = targettimestamp - targetentrystatus.index = targetentrystatus.index or { } - - if currenttimestamp == targettimestamp - and not targetentrystatus.index [1] - then - --- copy old namedata into new - - for _, currentindex in next, currententrystatus.index do - - local targetindex = #targetentrystatus.index - local fullinfo = currentmappings [currentindex] - local location = #targetmappings + 1 - - targetmappings [location] = fullinfo - targetentrystatus.index [targetindex + 1] = location - end - - logreport ("log", 3, "db", "Font %q already indexed.", fullname) - - return false - end - - return true -end - -local insert_fullinfo = function (fullname, - basename, - n_font, - loader, - format, - location, - targetmappings, - targetentrystatus, - info) - - local fullinfo = loader (fullname, n_font, - location, basename, - format, info) - - if not fullinfo then - return false - end - - local index = targetentrystatus.index [n_font] - - if not index then - index = #targetmappings + 1 - end - - targetmappings [index] = fullinfo - targetentrystatus.index [n_font] = index - - return true -end - - - ---- we return true if the font is new or re-indexed ---- string -> dbobj -> dbobj -> bool - -local read_font_names = function (fullname, - currentnames, - targetnames, - location) - - local targetmappings = targetnames.mappings - local targetstatus = targetnames.status --- by full path - local targetentrystatus = targetstatus [fullname] - - if targetentrystatus == nil then - targetentrystatus = { } - targetstatus [fullname] = targetentrystatus - end - - local currentmappings = currentnames.mappings - local currentstatus = currentnames.status - local currententrystatus = currentstatus [fullname] - - local basename = filebasename (fullname) - local barename = filenameonly (fullname) - local entryname = fullname - - if location == "texmf" then - entryname = basename - end - - --- 1) skip if blacklisted - - if names.blacklist[fullname] or names.blacklist[basename] then - logreport ("log", 2, "db", - "Ignoring blacklisted font %q.", fullname) - return false - end - - --- 2) skip if known with same timestamp - - if not compare_timestamps (fullname, - currentstatus, - currententrystatus, - currentmappings, - targetstatus, - targetentrystatus, - targetmappings) - then - return false - end - - --- 3) new font; choose a loader, abort if unknown - - local format = stringlower (filesuffix (basename)) - local loader = loaders [format] --- ot_fullinfo, t1_fullinfo - - if not loader then - logreport ("both", 0, "db", - "Unknown format: %q, skipping.", format) - return false - end - - --- 4) get basic info, abort if fontloader can’t read it - - local err, info = read_font_file (fullname) - - if err == false then - logreport ("log", 1, "db", - "Failed to read basic information from %q: %q", - basename, tostring (info)) - return false - end - - - --- 5) check for subfonts and process each of them - - if type (info) == "table" and #info >= 1 then --- ttc - - local success = false --- true if at least one subfont got read - - for n_font = 1, #info do - if insert_fullinfo (fullname, basename, n_font, - loader, format, location, - targetmappings, targetentrystatus, - info) - then - success = true - end - end - - return success - end - - return insert_fullinfo (fullname, basename, false, - loader, format, location, - targetmappings, targetentrystatus, - info) -end - -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 = filecollapsepath(path) - return path - end ---[[doc-- - The special treatment for cygwin was removed with a patch submitted - by Ken Brown. - Reference: http://cygwin.com/ml/cygwin/2013-05/msg00006.html ---doc]]-- - - 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 -end - -local blacklist = { } -local p_blacklist --- prefixes of dirs - ---- string list -> string list -local collapse_prefixes = function (lst) - --- avoid redundancies in blacklist - if #lst < 2 then - return lst - end - - tablesort(lst) - local cur = lst[1] - local result = { cur } - for i=2, #lst do - local elm = lst[i] - if stringsub(elm, 1, #cur) ~= cur then - --- different prefix - cur = elm - result[#result+1] = cur - end - end - return result -end - ---- string list -> string list -> (string, bool) hash_t -local create_blacklist = function (blacklist, whitelist) - local result = { } - local dirs = { } - - logreport ("info", 2, "db", "Blacklisting %d files and directories.", - #blacklist) - for i=1, #blacklist do - local entry = blacklist[i] - if lfsisdir(entry) then - dirs[#dirs+1] = entry - else - result[blacklist[i]] = true - end - end - - logreport ("info", 2, "db", "Whitelisting %d files.", #whitelist) - for i=1, #whitelist do - result[whitelist[i]] = nil - end - - dirs = collapse_prefixes(dirs) - - --- build the disjunction of the blacklisted directories - for i=1, #dirs do - local p_dir = P(dirs[i]) - if p_blacklist then - p_blacklist = p_blacklist + p_dir - else - p_blacklist = p_dir - end - end - - if p_blacklist == nil then - --- always return false - p_blacklist = lpeg.Cc(false) - end - - return result -end - ---- unit -> unit -read_blacklist = function () - local files = { - kpselookup ("luaotfload-blacklist.cnf", - {all=true, format="tex"}) - } - local blacklist = { } - local whitelist = { } - - if files and type(files) == "table" then - for _, path in next, files do - for line in iolines (path) do - line = stringstrip(line) -- to get rid of lines like " % foo" - local first_chr = stringsub(line, 1, 1) - if first_chr == "%" or stringis_empty(line) then - -- comment or empty line - elseif first_chr == "-" then - logreport ("both", 3, "db", - "Whitelisted file %q via %q.", - line, path) - whitelist[#whitelist+1] = stringsub(line, 2, -1) - else - local cmt = stringfind(line, "%%") - if cmt then - line = stringsub(line, 1, cmt - 1) - end - line = stringstrip(line) - logreport ("both", 3, "db", - "Blacklisted file %q via %q.", - line, path) - blacklist[#blacklist+1] = line - end - end - end - end - names.blacklist = create_blacklist(blacklist, whitelist) -end - -local p_font_filter - -do - local extension_pattern = function (list) - if type (list) ~= "table" or #list == 0 then return P(-1) end - local pat - for i=#list, 1, -1 do - local e = list[i] - if not pat then - pat = P(e) - else - pat = pat + P(e) - end - end - pat = pat * P(-1) - return (1 - pat)^1 * pat - end - - --- small helper to adjust the font filter pattern (--formats - --- option) - - local current_formats = { } - - set_font_filter = function (formats) - - if not formats or type (formats) ~= "string" then - return - end - - if splitcomma == nil then - splitcomma = luaotfload.parsers and luaotfload.parsers.splitcomma - end - if stringsub (formats, 1, 1) == "+" then -- add - formats = lpegmatch (splitcomma, stringsub (formats, 2)) - if formats then - current_formats = tableappend (current_formats, formats) - end - elseif stringsub (formats, 1, 1) == "-" then -- add - formats = lpegmatch (splitcomma, stringsub (formats, 2)) - if formats then - local newformats = { } - for i = 1, #current_formats do - local fmt = current_formats[i] - local include = true - for j = 1, #formats do - if current_formats[i] == formats[j] then - include = false - goto skip - end - end - newformats[#newformats+1] = fmt - ::skip:: - end - current_formats = newformats - end - else -- set - formats = lpegmatch (splitcomma, formats) - if formats then - current_formats = formats - end - end - - p_font_filter = extension_pattern (current_formats) - end - - get_font_filter = function (formats) - return tablefastcopy (current_formats) - end -end - -local locate_matching_pfb = function (afmfile, dir) - local pfbname = filereplacesuffix (afmfile, "pfb") - local pfbpath = dir .. "/" .. pfbname - if lfsisfile (pfbpath) then - return pfbpath - end - --- Check for match in texmf too - return kpsefind_file (pfbname, "type1 fonts") -end - -local process_dir_tree -process_dir_tree = function (acc, dirs, done) - if not next (dirs) then --- done - return acc - end - - local pwd = lfscurrentdir () - local dir = dirs[#dirs] - dirs[#dirs] = nil - - if not lfschdir (dir) then - --- Cannot cd; skip. - return process_dir_tree (acc, dirs, done) - end - - dir = lfscurrentdir () --- resolve symlinks - lfschdir (pwd) - if tablecontains (done, dir) then - --- Already traversed. Note that it’d be unsafe to rely on the - --- hash part above due to Lua only processing up to 32 bytes - --- of string data. The lookup shouldn’t impact performance too - --- much but we could check the performance of alternative data - --- structures at some point. - return process_dir_tree (acc, dirs, done) - end - - local newfiles = { } - local blacklist = names.blacklist - for ent in lfsdir (dir) do - --- filter right away - if ent ~= "." and ent ~= ".." and not blacklist[ent] then - local fullpath = dir .. "/" .. ent - if lfsisdir (fullpath) - and not lpegmatch (p_blacklist, fullpath) - then - dirs[#dirs+1] = fullpath - elseif lfsisfile (fullpath) then - ent = stringlower (ent) - if lpegmatch (p_font_filter, ent) then - if filesuffix (ent) == "afm" then - local pfbpath = locate_matching_pfb (ent, dir) - if pfbpath then - newfiles[#newfiles+1] = pfbpath - end - end - newfiles[#newfiles+1] = fullpath - end - end - end - end - done [#done + 1] = dir - return process_dir_tree (tableappend (acc, newfiles), dirs, done) -end - -local process_dir = function (dir) - local pwd = lfscurrentdir () - if lfschdir (dir) then - dir = lfscurrentdir () --- resolve symlinks - lfschdir (pwd) - - local files = { } - local blacklist = names.blacklist - for ent in lfsdir (dir) do - if ent ~= "." and ent ~= ".." and not blacklist[ent] then - local fullpath = dir .. "/" .. ent - if lfsisfile (fullpath) then - ent = stringlower (ent) - if lpegmatch (p_font_filter, ent) - then - if filesuffix (ent) == "afm" then - local pfbpath = locate_matching_pfb (ent, dir) - if pfbpath then - files[#files+1] = pfbpath - end - else - files[#files+1] = fullpath - end - end - end - end - end - return files - end - return { } -end - ---- string -> bool -> string list -local find_font_files = function (root, recurse) - if lfsisdir (root) then - if recurse == true then - return process_dir_tree ({}, { root }, {}) - else --- kpathsea already delivered the necessary subdirs - return process_dir (root) - end - end -end - ---- truncate_string -- Cut the first part of a string to fit it ---- into a given terminal width. The parameter “restrict” (int) ---- indicates the number of characters already consumed on the ---- line. -local truncate_string = function (str, restrict) - local tw = config.luaotfload.misc.termwidth - local wd = tw - restrict - local len = utf8len (str) - if wd - len < 0 then - --- combined length exceeds terminal, - str = ".." .. stringsub(str, len - wd + 2) - end - return str -end - - ---[[doc-- - - collect_font_filenames_dir -- Traverse the directory root at - ``dirname`` looking for font files. Returns a list of {*filename*; - *location*} pairs. - ---doc]]-- - ---- string -> string -> string * string list -local collect_font_filenames_dir = function (dirname, location) - if lpegmatch (p_blacklist, dirname) then - logreport ("both", 4, "db", - "Skipping blacklisted directory %s.", dirname) - --- ignore - return { } - end - local found = find_font_files (dirname, location ~= "texmf" and location ~= "local") - if not found then - logreport ("both", 4, "db", - "No such directory: %q; skipping.", dirname) - return { } - end - - local nfound = #found - local files = { } - - logreport ("both", 4, "db", - "%d font files detected in %s.", - nfound, dirname) - for j = 1, nfound do - local fullname = found[j] - files[#files + 1] = { path_normalize (fullname), location } - end - return files -end - ---- string list -> string list -local filter_out_pwd = function (dirs) - local result = { } - if stripslashes == nil then - stripslashes = luaotfload.parsers and luaotfload.parsers.stripslashes - end - local pwd = path_normalize (lpegmatch (stripslashes, - lfscurrentdir ())) - for i = 1, #dirs do - --- better safe than sorry - local dir = path_normalize (lpegmatch (stripslashes, dirs[i])) - if dir == "." or dir == pwd then - logreport ("both", 3, "db", - "Path “%s” matches $PWD (“%s”), skipping.", - dir, pwd) - else - result[#result+1] = dir - end - end - return result -end - -local path_separator = os.type == "windows" and ";" or ":" - ---[[doc-- - - collect_font_filenames_texmf -- Scan texmf tree for font files - relying on the kpathsea variables $OPENTYPEFONTS and $TTFONTS of - texmf.cnf. - The current working directory comes as “.” (texlive) or absolute - path (miktex) and will always be filtered out. - - Returns a list of { *filename*; *location* } pairs. - ---doc]]-- - ---- unit -> string * string list -local collect_font_filenames_texmf = function () - - local osfontdir = kpseexpand_path "$OSFONTDIR" - - if stringis_empty (osfontdir) then - logreport ("both", 1, "db", "Scanning TEXMF for fonts...") - else - logreport ("both", 1, "db", "Scanning TEXMF and $OSFONTDIR for fonts...") - if log.get_loglevel () > 3 then - local osdirs = filesplitpath (osfontdir) - logreport ("both", 0, "db", "$OSFONTDIR has %d entries:", #osdirs) - for i = 1, #osdirs do - logreport ("both", 0, "db", "[%d] %s", i, osdirs[i]) - end - end - end - - fontdirs = kpseexpand_path "$OPENTYPEFONTS" - fontdirs = fontdirs .. path_separator .. kpseexpand_path "$TTFONTS" - fontdirs = fontdirs .. path_separator .. kpseexpand_path "$T1FONTS" - fontdirs = fontdirs .. path_separator .. kpseexpand_path "$AFMFONTS" - - if stringis_empty (fontdirs) then - return { } - end - - local tasks = filter_out_pwd (filesplitpath (fontdirs)) - logreport ("both", 3, "db", - "Initiating scan of %d directories.", #tasks) - - local files = { } - for _, dir in next, tasks do - files = tableappend (files, collect_font_filenames_dir (dir, "texmf")) - end - logreport ("both", 3, "db", "Collected %d files.", #files) - return files -end - ---- unit -> string list -local function get_os_dirs () - if os.name == 'macosx' then - return { - filejoin(kpseexpand_path('~'), "Library/Fonts"), - "/Library/Fonts", - "/System/Library/Fonts", - "/Network/Library/Fonts", - } - elseif os.type == "windows" or os.type == "msdos" then - local windir = osgetenv("WINDIR") - return { filejoin(windir, 'Fonts') } - else - local fonts_conves = { --- plural, much? - "/usr/local/etc/fonts/fonts.conf", - "/etc/fonts/fonts.conf", - } - if not luaotfload.parsers then - logreport ("log", 0, "db", "Fatal: no fonts.conf parser.") - end - local os_dirs = luaotfload.parsers.read_fonts_conf(fonts_conves, find_files) - return os_dirs - end - return {} -end - ---[[doc-- - - count_removed -- Count paths that do not exist in the file system. - ---doc]]-- - ---- string list -> size_t -local count_removed = function (files) - if not files or not files.full then - logreport ("log", 4, "db", "Empty file store; no data to work with.") - return 0 - end - local old = files.full - logreport ("log", 4, "db", "Checking removed files.") - local nrem = 0 - local nold = #old - for i = 1, nold do - local f = old[i] - if not kpsereadable_file (f) then - logreport ("log", 2, "db", - "File %s does not exist in file system.") - nrem = nrem + 1 - end - end - return nrem -end - ---[[doc-- - - retrieve_namedata -- Scan the list of collected fonts and populate - the list of namedata. - - · dirname : name of the directory to scan - · currentnames : current font db object - · targetnames : font db object to fill - · dry_run : don’t touch anything - - Returns the number of fonts that were actually added to the index. - ---doc]]-- - ---- string * string list -> dbobj -> dbobj -> bool? -> int * int -local retrieve_namedata = function (files, currentnames, targetnames, dry_run) - - local nfiles = #files - local nnew = 0 - - logreport ("info", 1, "db", "Scanning %d collected font files ...", nfiles) - - local bylocation = { texmf = { 0, 0 } - , ["local"] = { 0, 0 } - , system = { 0, 0 } - } - report_status_start (2, 4) - for i = 1, nfiles do - local fullname, location = unpack (files[i]) - local count = bylocation[location] - count[1] = count[1] + 1 - if dry_run == true then - local truncated = truncate_string (fullname, 43) - logreport ("log", 2, "db", "Would have been loading %s.", fullname) - report_status ("term", "db", "Would have been loading %s", truncated) - --- skip the read_font_names part - else - local truncated = truncate_string (fullname, 32) - logreport ("log", 2, "db", "Loading font %s.", fullname) - report_status ("term", "db", "Loading font %s", truncated) - local new = read_font_names (fullname, currentnames, - targetnames, location) - if new == true then - nnew = nnew + 1 - count[2] = count[2] + 1 - end - end - end - report_status_stop ("term", "db", "Scanned %d files, %d new.", nfiles, nnew) - for location, count in next, bylocation do - logreport ("term", 4, "db", " * %s: %d files, %d new", - location, count[1], count[2]) - end - return nnew -end - ---- unit -> string * string list -local collect_font_filenames_system = function () - - local n_scanned, n_new = 0, 0 - logreport ("info", 1, "db", "Scanning system fonts...") - logreport ("info", 2, "db", - "Searching in static system directories...") - - local files = { } - for _, dir in next, get_os_dirs () do - tableappend (files, collect_font_filenames_dir (dir, "system")) - end - logreport ("term", 3, "db", "Collected %d files.", #files) - return files -end - ---- unit -> bool -flush_lookup_cache = function () - lookup_cache = { } - collectgarbage "collect" - return true -end - ---[[doc-- - - collect_font_filenames_local -- Scan $PWD (during a TeX run) - for font files. - - Side effect: This sets the “local” flag in the subtable “meta” to - prevent the merged table from being saved to disk. - - TODO the local tree could be cached in $PWD. - ---doc]]-- - ---- unit -> string * string list -local collect_font_filenames_local = function () - local pwd = lfscurrentdir () - logreport ("both", 1, "db", "Scanning for fonts in $PWD (%q) ...", pwd) - - local files = collect_font_filenames_dir (pwd, "local") - local nfiles = #files - if nfiles > 0 then - targetnames.meta["local"] = true --- prevent saving to disk - logreport ("term", 1, "db", "Found %d files.", pwd) - else - logreport ("term", 1, "db", - "Couldn’t find a thing here. What a waste.", pwd) - end - logreport ("term", 3, "db", "Collected %d files.", #files) - return files -end - ---- fontentry list -> filemap -generate_filedata = function (mappings) - - logreport ("both", 2, "db", "Creating filename map.") - - local nmappings = #mappings - - local files = { - bare = { - ["local"] = { }, - system = { }, --- mapped to mapping format -> index in full - texmf = { }, --- mapped to mapping format -> “true” - }, - base = { - ["local"] = { }, - system = { }, --- mapped to index in “full” - texmf = { }, --- set; all values are “true” - }, - full = { }, --- non-texmf - } - - local base = files.base - local bare = files.bare - local full = files.full - - local conflicts = { - basenames = 0, - barenames = 0, - } - - for index = 1, nmappings do - local entry = mappings [index] - local filedata = entry.file - local format - local location - local fullpath - local basename - local barename - local subfont - - if filedata then --- new entry - format = entry.format --- otf, afm, ... - location = filedata.location --- texmf, system, ... - fullpath = filedata.full - basename = filedata.base - barename = filenameonly (fullpath) - subfont = filedata.subfont - else - format = entry.format --- otf, afm, ... - location = entry.location --- texmf, system, ... - fullpath = entry.fullpath - basename = entry.basename - barename = filenameonly (fullpath) - subfont = entry.subfont - end - - entry.index = index - - --- 1) add to basename table - - local inbase = base [location] --- no format since the suffix is known - - if inbase then - local present = inbase [basename] - if present then - logreport ("both", 4, "db", - "Conflicting basename: %q already indexed \z - in category %s, ignoring.", - barename, location) - conflicts.basenames = conflicts.basenames + 1 - - --- track conflicts per font - local conflictdata = entry.conflicts - - if not conflictdata then - entry.conflicts = { basename = present } - else -- some conflicts already detected - conflictdata.basename = present - end - - else - inbase [basename] = index - end - else - inbase = { basename = index } - base [location] = inbase - end - - --- 2) add to barename table - - local inbare = bare [location] [format] - - if inbare then - local present = inbare [barename] - if present then - logreport ("both", 4, "db", - "Conflicting barename: %q already indexed \z - in category %s/%s, ignoring.", - barename, location, format) - conflicts.barenames = conflicts.barenames + 1 - - --- track conflicts per font - local conflictdata = entry.conflicts - - if not conflictdata then - entry.conflicts = { barename = present } - else -- some conflicts already detected - conflictdata.barename = present - end - - else - inbare [barename] = index - end - else - inbare = { [barename] = index } - bare [location] [format] = inbare - end - - --- 3) add to fullpath map - - full [index] = fullpath - end --- mapping traversal - - return files -end - -local bold_spectrum_low = 501 --- 500 is medium, 900 heavy/black -local normal_weight = 400 -local bold_weight = 700 -local normal_width = 5 - -local pick_style -local pick_fallback_style -local check_regular - -do - local choose_exact = function (field) - --- only clean matches, without guessing - if italic_synonym [field] then - return "i" - end - - if stringsub (field, 1, 10) == "bolditalic" - or stringsub (field, 1, 11) == "boldoblique" then - return "bi" - end - - if stringsub (field, 1, 4) == "bold" then - return "b" - end - - if stringsub (field, 1, 6) == "italic" then - return "i" - end - - return false - end - - pick_style = function (typographicsubfamily, subfamily) - local style - if typographicsubfamily then - style = choose_exact (typographicsubfamily) - if style then return style end - elseif subfamily then - style = choose_exact (subfamily) - if style then return style end - end - return false - end - - pick_fallback_style = function (italicangle, pfmweight, width) - --[[-- - More aggressive, but only to determine bold faces. - Note: Before you make this test more inclusive, ensure - no fonts are matched in the bold synonym spectrum over - a literally “bold[italic]” one. In the past, heuristics - been tried but ultimately caused unwanted modifiers - polluting the lookup table. What doesn’t work is, e. g. - treating weights > 500 as bold or allowing synonyms like - “heavy”, “black”. - --]]-- - if width == normal_width then - if pfmweight == bold_weight then - --- bold spectrum matches - if italicangle == 0 then - return "b" - end - return "bi" - elseif pfmweight == normal_weight then - if italicangle ~= 0 then - return "i" - end - end - end - return false - end - - --- we use only exact matches here since there are constructs - --- like “regularitalic” (Cabin, Bodoni Old Fashion) - - check_regular = function (typographicsubfamily, - subfamily, - italicangle, - weight, - width, - pfmweight) - local plausible_weight = false - --[[-- - This filters out undesirable candidates that specify their - typographicsubfamily or subfamily as “regular” but are actually of - “semibold” or other weight—another drawback of the - oversimplifying classification into only three styles (r, i, - b, bi). - --]]-- - if italicangle == 0 then - if pfmweight == 400 then - --[[-- - Some fonts like Dejavu advertise an undistinguished - regular and a “condensed” version with the same - weight whilst also providing the style info in the - typographic subfamily instead of the subfamily (i. e. - the converse of what Adobe’s doing). The only way to - weed out the undesired pseudo-regular shape is to - peek at its advertised width (4 vs. 5). - --]]-- - if width then - plausible_weight = width == normal_width - else - plausible_weight = true - end - elseif weight and regular_synonym [weight] then - plausible_weight = true - end - end - - if plausible_weight then - if subfamily then - if regular_synonym [subfamily] then return "r" end - elseif typographicsubfamily then - if regular_synonym [typographicsubfamily] then return "r" end - end - end - return false - end -end - -local pull_values = function (entry) - local file = entry.file - local names = entry.names - local style = entry.style - local sanitized = names.sanitized - local english = sanitized.english - local info = sanitized.info - local metadata = sanitized.metadata - - --- pull file info ... - entry.basename = file.base - entry.fullpath = file.full - entry.location = file.location - entry.subfont = file.subfont - - --- pull name info ... - entry.psname = english.psname - entry.fontname = info.fontname or metadata.fontname - entry.fullname = english.fullname or info.fullname - entry.typographicsubfamily = english.typographicsubfamily - entry.familyname = metadata.familyname or english.typographicfamily or english.family - entry.plainname = names.fullname - entry.subfamily = english.subfamily - - --- pull style info ... - entry.italicangle = style.italicangle - entry.size = style.size - entry.weight = style.weight - entry.width = style.width - entry.pfmweight = style.pfmweight - - if config.luaotfload.db.strip == true then - entry.file = nil - entry.names = nil - entry.style = nil - end -end - -local add_family = function (name, subtable, modifier, entry) - if not name then --- probably borked font - return - end - local familytable = subtable [name] - if not familytable then - familytable = { } - subtable [name] = familytable - end - - familytable [#familytable + 1] = { - index = entry.index, - modifier = modifier, - } -end - -local get_subtable = function (families, entry) - local location = entry.location - local format = entry.format - local subtable = families [location] [format] - if not subtable then - subtable = { } - families [location] [format] = subtable - end - return subtable -end - -local collect_families = function (mappings) - - logreport ("info", 2, "db", "Analyzing families.") - - local families = { - ["local"] = { }, - system = { }, - texmf = { }, - } - - for i = 1, #mappings do - - local entry = mappings [i] - - if entry.file then - pull_values (entry) - end - - local subtable = get_subtable (families, entry) - local familyname = entry.familyname - local typographicsubfamily = entry.typographicsubfamily - local subfamily = entry.subfamily - local weight = entry.weight - local width = entry.width - local pfmweight = entry.pfmweight - local italicangle = entry.italicangle - local modifier = pick_style (typographicsubfamily, subfamily) - - if not modifier then --- regular, exact only - modifier = check_regular (typographicsubfamily, - subfamily, - italicangle, - weight, - width, - pfmweight) - end - - if not modifier then - modifier = pick_fallback_style (italicangle, pfmweight, width) - end - - if modifier then - add_family (familyname, subtable, modifier, entry) - end - end - - collectgarbage "collect" - return families -end - ---[[doc-- - - group_modifiers -- For not-quite-bold faces, determine whether - they can fill in for a missing bold face slot in a matching family. - - Some families like Lucida do not contain real bold / bold italic - members. Instead, they have semibold variants at weight 600 which - we must add in a separate pass. - ---doc]]-- - -local style_categories = { "r", "b", "i", "bi" } -local bold_categories = { "b", "bi" } - -group_modifiers = function (mappings, families) - logreport ("info", 2, "db", "Analyzing shapes, weights, and styles.") - for location, location_data in next, families do - for format, format_data in next, location_data do - for familyname, collected in next, format_data do - local styledata = { } --- will replace the “collected” table - --- First, fill in the ordinary style data that - --- fits neatly into the four relevant modifier - --- categories. - for _, modifier in next, style_categories do - local entries - for key, info in next, collected do - if info.modifier == modifier then - if not entries then - entries = { } - end - local index = info.index - local entry = mappings [index] - local size = entry.size - if size then - entries [#entries + 1] = { - size [1], - size [2], - size [3], - index, - } - else - entries.default = index - end - collected [key] = nil - end - styledata [modifier] = entries - end - end - - --- At this point the family set may still lack - --- entries for bold or bold italic. We will fill - --- those in using the modifier with the numeric - --- weight that is closest to bold (700). - if next (collected) then --- there are uncategorized entries - for _, modifier in next, bold_categories do - if not styledata [modifier] then - local closest - local minimum = 2^51 - for key, info in next, collected do - local info_modifier = tonumber (info.modifier) and "b" or "bi" - if modifier == info_modifier then - local index = info.index - local entry = mappings [index] - local weight = entry.pfmweight - local diff = weight < 700 and 700 - weight or weight - 700 - if diff < minimum then - minimum = diff - closest = weight - end - end - end - if closest then - --- We know there is a substitute face for the modifier. - --- Now we scan the list again to extract the size data - --- in case the shape is available at multiple sizes. - local entries = { } - for key, info in next, collected do - local info_modifier = tonumber (info.modifier) and "b" or "bi" - if modifier == info_modifier then - local index = info.index - local entry = mappings [index] - local size = entry.size - if entry.pfmweight == closest then - if size then - entries [#entries + 1] = { - size [1], - size [2], - size [3], - index, - } - else - entries.default = index - end - end - end - end - styledata [modifier] = entries - end - end - end - end - format_data [familyname] = styledata - end - end - end - return families -end - -local cmp_sizes = function (a, b) - return a [1] < b [1] -end - -order_design_sizes = function (families) - - logreport ("info", 2, "db", "Ordering design sizes.") - - for location, data in next, families do - for format, data in next, data do - for familyname, data in next, data do - for style, data in next, data do - tablesort (data, cmp_sizes) - end - end - end - end - - return families -end - ---[[doc-- - - collect_font_filenames -- Scan the three search path categories for - font files. This constitutes the first pass of the update mode. - ---doc]]-- - ---- unit -> string * string list -local collect_font_filenames = function () - - logreport ("info", 4, "db", "Scanning the filesystem for font files.") - - local filenames = { } - local bisect = config.luaotfload.misc.bisect - local max_fonts = config.luaotfload.db.max_fonts --- XXX revisit for lua 5.3 wrt integers - - tableappend (filenames, collect_font_filenames_texmf ()) - tableappend (filenames, collect_font_filenames_system ()) - if config.luaotfload.db.scan_local == true then - tableappend (filenames, collect_font_filenames_local ()) - end - --- Now drop everything above max_fonts. - if max_fonts < #filenames then - filenames = { unpack (filenames, 1, max_fonts) } - end - --- And choose the requested slice if in bisect mode. - if bisect then - return { unpack (filenames, bisect[1], bisect[2]) } - end - return filenames -end - ---[[doc-- - - nth_font_file -- Return the filename of the nth font. - ---doc]]-- - ---- int -> string -local nth_font_filename = function (n) - logreport ("info", 4, "db", "Picking font file no. %d.", n) - if not p_blacklist then - read_blacklist () - end - local filenames = collect_font_filenames () - return filenames[n] and filenames[n][1] or "<error>" -end - ---[[doc-- - - font_slice -- Return the fonts in the range from lo to hi. - ---doc]]-- - -local font_slice = function (lo, hi) - logreport ("info", 4, "db", "Retrieving font files nos. %d--%d.", lo, hi) - if not p_blacklist then - read_blacklist () - end - local filenames = collect_font_filenames () - local result = { } - for i = lo, hi do - result[#result + 1] = filenames[i][1] - end - return result -end - ---[[doc - - count_font_files -- Return the number of files found by - collect_font_filenames. This function is exported primarily - for use with luaotfload-tool.lua in bisect mode. - ---doc]]-- - ---- unit -> int -local count_font_files = function () - logreport ("info", 4, "db", "Counting font files.") - if not p_blacklist then - read_blacklist () - end - return #collect_font_filenames () -end - ---- dbobj -> stats - -local collect_statistics = function (mappings) - local sum_dsnsize, n_dsnsize = 0, 0 - - local fullname, family, families = { }, { }, { } - local subfamily, typographicsubfamily = { }, { } - - local addtohash = function (hash, item) - if item then - local times = hash [item] - if times then - hash [item] = times + 1 - else - hash [item] = 1 - end - end - end - - local appendtohash = function (hash, key, value) - if key and value then - local entry = hash [key] - if entry then - entry [#entry + 1] = value - else - hash [key] = { value } - end - end - end - - local addtoset = function (hash, key, value) - if key and value then - local set = hash [key] - if set then - set [value] = true - else - hash [key] = { [value] = true } - end - end - end - - local setsize = function (set) - local n = 0 - for _, _ in next, set do - n = n + 1 - end - return n - end - - local hashsum = function (hash) - local n = 0 - for _, m in next, hash do - n = n + m - end - return n - end - - for _, entry in next, mappings do - local style = entry.style - local names = entry.names.sanitized - local englishnames = names.english - - addtohash (fullname, englishnames.fullname) - addtohash (family, englishnames.family) - addtohash (subfamily, englishnames.subfamily) - addtohash (typographicsubfamily, englishnames.typographicsubfamily) - - addtoset (families, englishnames.family, englishnames.fullname) - - local sizeinfo = entry.style.size - if sizeinfo then - sum_dsnsize = sum_dsnsize + sizeinfo [1] - n_dsnsize = n_dsnsize + 1 - end - end - - --inspect (families) - - local n_fullname = setsize (fullname) - local n_family = setsize (family) - - if log.get_loglevel () > 1 then - local pprint_top = function (hash, n, set) - - local freqs = { } - local items = { } - - for item, value in next, hash do - if set then - freq = setsize (value) - else - freq = value - end - local ifreq = items [freq] - if ifreq then - ifreq [#ifreq + 1] = item - else - items [freq] = { item } - freqs [#freqs + 1] = freq - end - end - - tablesort (freqs) - - local from = #freqs - local to = from - (n - 1) - if to < 1 then - to = 1 - end - - for i = from, to, -1 do - local freq = freqs [i] - local itemlist = items [freq] - - if type (itemlist) == "table" then - itemlist = tableconcat (itemlist, ", ") - end - - logreport ("both", 0, "db", - " · %4d × %s.", - freq, itemlist) - end - end - - logreport ("both", 0, "", "~~~~ font index statistics ~~~~") - logreport ("both", 0, "db", - " · Collected %d fonts (%d names) in %d families.", - #mappings, n_fullname, n_family) - pprint_top (families, 4, true) - - logreport ("both", 0, "db", - " · %d different “subfamily” kinds.", - setsize (subfamily)) - pprint_top (subfamily, 4) - - logreport ("both", 0, "db", - " · %d different “typographicsubfamily” kinds.", - setsize (typographicsubfamily)) - pprint_top (typographicsubfamily, 4) - - end - - local mean_dsnsize = 0 - if n_dsnsize > 0 then - mean_dsnsize = sum_dsnsize / n_dsnsize - end - - return { - mean_dsnsize = mean_dsnsize, - names = { - fullname = n_fullname, - families = n_family, - }, --- style = { --- subfamily = subfamily, --- typographicsubfamily = typographicsubfamily, --- }, - } -end - ---- force: dictate rebuild from scratch ---- dry_dun: don’t write to the db, just scan dirs - ---- dbobj? -> bool? -> bool? -> dbobj -update_names = function (currentnames, force, dry_run) - local targetnames - local n_new = 0 - local n_rem = 0 - - local conf = config.luaotfload - if conf.run.live ~= false and conf.db.update_live == false then - logreport ("info", 2, "db", "Skipping database update.") - --- skip all db updates - return currentnames or name_index - end - - local starttime = osgettimeofday () - - --[[ - The main function, scans everything - - “targetnames” is the final table to return - - force is whether we rebuild it from scratch or not - ]] - logreport ("both", 1, "db", - "Updating the font names database" - .. (force and " forcefully." or ".")) - - if config.luaotfload.db.skip_read == true then - --- the difference to a “dry run” is that we don’t search - --- for font files entirely. we also ignore the “force” - --- parameter since it concerns only the font files. - logreport ("info", 2, "db", - "Ignoring font files, reusing old data.") - currentnames = load_names (false) - targetnames = currentnames - else - if force then - currentnames = initialize_namedata (get_font_filter ()) - else - if not currentnames or not next (currentnames) then - currentnames = load_names (dry_run) - end - if currentnames.meta.version ~= names.version then - logreport ("both", 1, "db", - "No font names database or old \z - one found; generating new one.") - currentnames = initialize_namedata (get_font_filter ()) - end - end - - targetnames = initialize_namedata (get_font_filter (), - currentnames.meta and currentnames.meta.created) - - read_blacklist () - - --- pass 1: Collect the names of all fonts we are going to process. - local font_filenames = collect_font_filenames () - - --- pass 2: read font files (normal case) or reuse information - --- present in index - - n_rem = count_removed (currentnames.files) - - n_new = retrieve_namedata (font_filenames, - currentnames, - targetnames, - dry_run) - - logreport ("info", 3, "db", - "Found %d font files; %d new, %d stale entries.", - #font_filenames, n_new, n_rem) - end - - --- pass 3 (optional): collect some stats about the raw font info - if config.luaotfload.misc.statistics == true then - targetnames.meta.statistics = collect_statistics - (targetnames.mappings) - end - - --- we always generate the file lookup tables because - --- non-texmf entries are redirected there and the mapping - --- needs to be 100% consistent - - --- pass 4: build filename table - targetnames.files = generate_filedata (targetnames.mappings) - - --- pass 5: build family lookup table - targetnames.families = collect_families (targetnames.mappings) - - --- pass 6: arrange style and size info - targetnames.families = group_modifiers (targetnames.mappings, - targetnames.families) - - --- pass 7: order design size tables - targetnames.families = order_design_sizes (targetnames.families) - - logreport ("info", 3, "db", - "Rebuilt in %0.f ms.", - 1000 * (osgettimeofday () - starttime)) - name_index = targetnames - - if dry_run ~= true then - - if n_new + n_rem == 0 then - logreport ("info", 2, "db", - "No new or removed fonts, skip saving to disk.") - else - local success, reason = save_names () - if not success then - logreport ("both", 0, "db", - "Failed to save database to disk: %s", - reason) - end - end - - if flush_lookup_cache () and save_lookups () then - logreport ("both", 2, "cache", "Lookup cache emptied.") - return targetnames - end - end - return targetnames -end - ---- unit -> bool -save_lookups = function ( ) - local paths = config.luaotfload.paths - local luaname, lucname = paths.lookup_path_lua, paths.lookup_path_luc - if fileiswritable (luaname) and fileiswritable (lucname) then - tabletofile (luaname, lookup_cache, true) - osremove (lucname) - caches.compile (lookup_cache, luaname, lucname) - --- double check ... - if lfsisfile (luaname) and lfsisfile (lucname) then - logreport ("both", 3, "cache", "Lookup cache saved.") - return true - end - logreport ("info", 0, "cache", "Could not compile lookup cache.") - return false - end - logreport ("info", 0, "cache", "Lookup cache file not writable.") - if not fileiswritable (luaname) then - logreport ("info", 0, "cache", "Failed to write %s.", luaname) - end - if not fileiswritable (lucname) then - logreport ("info", 0, "cache", "Failed to write %s.", lucname) - end - return false -end - ---- save_names() is usually called without the argument ---- dbobj? -> bool * string option -save_names = function (currentnames) - if not currentnames then - currentnames = name_index - end - if not currentnames or type (currentnames) ~= "table" then - return false, "invalid names table" - elseif currentnames.meta and currentnames.meta["local"] then - return false, "table contains local entries" - end - local paths = config.luaotfload.paths - local luaname, lucname = paths.index_path_lua, paths.index_path_luc - if fileiswritable (luaname) and fileiswritable (lucname) then - osremove (lucname) - local gzname = luaname .. ".gz" - if config.luaotfload.db.compress then - local serialized = tableserialize (currentnames, true) - gzipsave (gzname, serialized) - caches.compile (currentnames, "", lucname) - else - tabletofile (luaname, currentnames, true) - caches.compile (currentnames, luaname, lucname) - end - logreport ("info", 2, "db", "Font index saved at ...") - local success = false - if lfsisfile (luaname) then - logreport ("info", 2, "db", "Text: " .. luaname) - success = true - end - if lfsisfile (gzname) then - logreport ("info", 2, "db", "Gzip: " .. gzname) - success = true - end - if lfsisfile (lucname) then - logreport ("info", 2, "db", "Byte: " .. lucname) - success = true - end - if success then - return true - else - logreport ("info", 0, "db", "Could not compile font index.") - return false - end - end - logreport ("info", 0, "db", "Index file not writable") - if not fileiswritable (luaname) then - logreport ("info", 0, "db", "Failed to write %s.", luaname) - end - if not fileiswritable (lucname) then - logreport ("info", 0, "db", "Failed to write %s.", lucname) - end - return false -end - ---[[doc-- - - Below set of functions is modeled after mtx-cache. - ---doc]]-- - ---- string -> string -> string list -> string list -> string list -> unit -local print_cache = function (category, path, luanames, lucnames, rest) - local report_indeed = function (...) - logreport ("info", 0, "cache", ...) - end - report_indeed("Luaotfload cache: %s", category) - report_indeed("location: %s", path) - report_indeed("[raw] %4i", #luanames) - report_indeed("[compiled] %4i", #lucnames) - report_indeed("[other] %4i", #rest) - report_indeed("[total] %4i", #luanames + #lucnames + #rest) -end - ---- string -> string -> string list -> bool -> bool -local purge_from_cache = function (category, path, list, all) - logreport ("info", 1, "cache", "Luaotfload cache: %s %s", - (all and "erase" or "purge"), category) - logreport ("info", 1, "cache", "location: %s", path) - local n = 0 - for i=1,#list do - local filename = list[i] - if stringfind(filename,"luatex%-cache") then -- safeguard - if all then - logreport ("info", 5, "cache", "Removing %s.", filename) - osremove(filename) - n = n + 1 - else - local suffix = filesuffix(filename) - if suffix == "lua" then - local checkname = file.replacesuffix( - filename, "lua", "luc") - if lfsisfile(checkname) then - logreport ("info", 5, "cache", "Removing %s.", filename) - osremove(filename) - n = n + 1 - end - end - end - end - end - logreport ("info", 1, "cache", "Removed lua files : %i", n) - return true -end - ---- string -> string list -> int -> string list -> string list -> string list -> ---- (string list * string list * string list * string list) -local collect_cache collect_cache = function (path, all, n, luanames, - lucnames, rest) - if not all then - local all = find_files (path) - - local luanames, lucnames, rest = { }, { }, { } - return collect_cache(nil, all, 1, luanames, lucnames, rest) - end - - local filename = all[n] - if filename then - local suffix = filesuffix(filename) - if suffix == "lua" then - luanames[#luanames+1] = filename - elseif suffix == "luc" then - lucnames[#lucnames+1] = filename - else - rest[#rest+1] = filename - end - return collect_cache(nil, all, n+1, luanames, lucnames, rest) - end - return luanames, lucnames, rest, all -end - -local getwritablecachepath = function ( ) - --- fonts.handlers.otf doesn’t exist outside a Luatex run, - --- so we have to improvise - local writable = getwritablepath (config.luaotfload.paths.cache_dir, "") - if writable then - return writable - end -end - -local getreadablecachepaths = function ( ) - local readables = caches.getreadablepaths - (config.luaotfload.paths.cache_dir) - local result = { } - if readables then - for i=1, #readables do - local readable = readables[i] - if lfsisdir (readable) then - result[#result+1] = readable - end - end - end - return result -end - ---- unit -> unit -local purge_cache = function ( ) - local writable_path = getwritablecachepath () - local luanames, lucnames, rest = collect_cache(writable_path) - if log.get_loglevel() > 1 then - print_cache("writable path", writable_path, luanames, lucnames, rest) - end - local success = purge_from_cache("writable path", writable_path, luanames, false) - return success -end - ---- unit -> unit -local erase_cache = function ( ) - local writable_path = getwritablecachepath () - local luanames, lucnames, rest, all = collect_cache(writable_path) - if log.get_loglevel() > 1 then - print_cache("writable path", writable_path, luanames, lucnames, rest) - end - local success = purge_from_cache("writable path", writable_path, all, true) - return success -end - -local separator = function ( ) - logreport ("info", 0, string.rep("-", 67)) -end - ---- unit -> unit -local show_cache = function ( ) - local readable_paths = getreadablecachepaths () - local writable_path = getwritablecachepath () - local luanames, lucnames, rest = collect_cache(writable_path) - - separator () - print_cache ("writable path", writable_path, - luanames, lucnames, rest) - texio.write_nl"" - for i=1,#readable_paths do - local readable_path = readable_paths[i] - if readable_path ~= writable_path then - local luanames, lucnames = collect_cache (readable_path) - print_cache ("readable path", - readable_path, luanames, lucnames, rest) - end - end - separator() - return true -end - ------------------------------------------------------------------------ ---- API assumptions of the fontloader ------------------------------------------------------------------------ ---- PHG: we need to investigate these, maybe they’re useful as early ---- hooks - -local ignoredfile = function () return false end - -local reportmissingbase = function () - logreport ("info", 0, "db", --> bug‽ - "Font name database not found but expected by fontloader.") - fonts.names.reportmissingbase = nil -end - -local reportmissingname = function () - logreport ("info", 0, "db", --> bug‽ - "Fontloader attempted to lookup name before Luaotfload \z - was initialized.") - fonts.names.reportmissingname = nil -end - -local getfilename = function (a1, a2) - logreport ("info", 6, "db", --> bug‽ - "Fontloader looked up font file (%s, %s) before Luaotfload \z - was initialized.", tostring(a1), tostring(a2)) - return lookup_fullpath (a1, a2) -end - -local resolve = function (name, subfont) - logreport ("info", 6, "db", --> bug‽ - "Fontloader attempted to resolve name (%s, %s) before \z - Luaotfload was initialized.", tostring(name), tostring(subfont)) - return lookup_font_name { name = name, sub = subfont } -end - -local api = { - ignoredfile = ignoredfile, - reportmissingbase = reportmissingbase, - reportmissingname = reportmissingname, - getfilename = getfilename, - resolve = resolve, -} - ------------------------------------------------------------------------ ---- export functionality to the namespace “fonts.names” ------------------------------------------------------------------------ - -local export = { - set_font_filter = set_font_filter, - set_size_dimension = set_size_dimension, - flush_lookup_cache = flush_lookup_cache, - save_lookups = save_lookups, - load = load_names, - access_font_index = access_font_index, - data = function () return name_index end, - save = save_names, - update = update_names, - lookup_font_file = lookup_font_file, - lookup_font_name = lookup_font_name, - lookup_font_name_cached = lookup_font_name_cached, - getfilename = lookup_fullpath, - lookup_fullpath = lookup_fullpath, - read_blacklist = read_blacklist, - sanitize_fontname = sanitize_fontname, - getmetadata = getmetadata, - set_location_precedence = set_location_precedence, - count_font_files = count_font_files, - nth_font_filename = nth_font_filename, - font_slice = font_slice, - --- font cache - purge_cache = purge_cache, - erase_cache = erase_cache, - show_cache = show_cache, - find_closest = find_closest, -} - -return { - init = function () - --- the font loader namespace is “fonts”, same as in Context - --- we need to put some fallbacks into place for when running - --- as a script - if not fonts then return false end - logreport = luaotfload.log.report - local fonts = fonts - fonts.names = fonts.names or names - fonts.formats = fonts.formats or { } - fonts.definers = fonts.definers or { resolvers = { } } - - names.blacklist = blacklist - names.version = 5 --- increase monotonically - names.data = nil --- contains the loaded database - names.lookups = nil --- contains the lookup cache - - for sym, ref in next, export do names[sym] = ref end - for sym, ref in next, api do names[sym] = names[sym] or ref end - return true - end -} - --- vim:tw=71:sw=4:ts=4:expandtab diff --git a/tex/compat/luaotfload/luaotfload-diagnostics.lua b/tex/compat/luaotfload/luaotfload-diagnostics.lua deleted file mode 100644 index a3a18418e61ef5386812d06470096b5286144bbe..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/luaotfload-diagnostics.lua +++ /dev/null @@ -1,686 +0,0 @@ -#!/usr/bin/env texlua ------------------------------------------------------------------------ --- FILE: luaotfload-diagnostics.lua --- DESCRIPTION: functionality accessible by the --diagnose option --- REQUIREMENTS: luaotfload-tool.lua --- AUTHOR: Philipp Gesang <phg@phi-gamma.net> ------------------------------------------------------------------------ --- -local names = fonts.names - -local kpse = require "kpse" -local kpseexpand_path = kpse.expand_path -local kpseexpand_var = kpse.expand_var -local kpsefind_file = kpse.find_file - -local lfs = require "lfs" -local lfsattributes = lfs.attributes -local lfsisfile = lfs.isfile -local lfsreadlink = lfs.readlink - -local md5 = require "md5" -local md5sumhexa = md5.sumhexa - -local ioopen = io.open - -local osgetenv = os.getenv -local osname = os.name -local osremove = os.remove -local ostype = os.type -local stringformat = string.format -local stringlower = string.lower -local stringsub = string.sub - -local fileisreadable = file.isreadable -local fileiswritable = file.iswritable -local filesplitpath = file.splitpath -local filesuffix = file.suffix -local ioloaddata = io.loaddata -local lua_of_json = utilities.json.tolua -local tableconcat = table.concat -local tablesortedkeys = table.sortedkeys -local tabletohash = table.tohash - -local lpeg = require "lpeg" -local C, Cg, Ct = lpeg.C, lpeg.Cg, lpeg.Ct -local lpegmatch = lpeg.match - -local report = luaotfload.log.report -local out = function (...) - report (false, 0, "diagnose", ...) -end - -local parsers = luaotfload.parsers -local stripslashes = parsers.stripslashes -local splitcomma = parsers.splitcomma - -local check_index = function (errcnt) - - out "================= font names ==================" - local namedata = names.data() - - if not namedata then - namedata = names.load () - end - - local mappings = namedata.mappings - - if not namedata and namedata.formats and namedata.version then - out "Database corrupt." - return errcnt + 1 - end - - out ("Database version: %.3f.", namedata.meta.version) - out ("Font formats indexed: %s.", - tableconcat (namedata.meta.formats, ", ")) - out ("%d font files indexed.", #mappings) - - local by_format = { } - for i = 1, #mappings do - local record = mappings[i] - local format = stringlower (filesuffix (record.filename)) - local count = by_format[format] - if count then - by_format[format] = count + 1 - else - by_format[format] = 1 - end - end - - local formats = tablesortedkeys (by_format) - for i = 1, #formats do - local format = formats[i] - out ("%20s: %5d", format, by_format[format]) - end - return errcnt -end - -local verify_files = function (errcnt) - out "================ verify files =================" - local status = config.luaotfload.status - local hashes = status.hashes - local notes = status.notes - if not hashes or #hashes == 0 then - out ("FAILED: cannot read checksums from %s.", status_file) - return 1/0 - elseif not notes then - out ("FAILED: cannot read commit metadata from %s.", - status_file) - return 1/0 - end - - out ("Luaotfload revision %s.", notes.revision) - out ("Committed by %s.", notes.committer) - out ("Timestamp %s.", notes.timestamp) - - local nhashes = #hashes - out ("Testing %d files for integrity.", nhashes) - for i = 1, nhashes do - local fname, canonicalsum = unpack (hashes[i]) - local location = kpsefind_file (fname) - or kpsefind_file (fname, "texmfscripts") - if not location then - errcnt = errcnt + 1 - out ("FAILED: file %s missing.", fname) - else - out ("File: %s.", location) - local raw = ioloaddata (location) - if not raw then - errcnt = errcnt + 1 - out ("FAILED: file %d not readable.", fname) - else - local sum = md5sumhexa (raw) - if sum ~= canonicalsum then - errcnt = errcnt + 1 - out ("FAILED: checksum mismatch for file %s.", - fname) - out ("Expected %s.", canonicalsum) - out ("Got %s.", sum) - else - out ("Ok, %s passed.", fname) - end - end - end - end - return errcnt -end - -local get_tentative_attributes = function (file) - if not lfsisfile (file) then - local chan = ioopen (file, "w") - if chan then - chan:close () - local attributes = lfsattributes (file) - os.remove (file) - return attributes - end - end -end - -local p_permissions = Ct(Cg(Ct(C(1) * C(1) * C(1)), "u") - * Cg(Ct(C(1) * C(1) * C(1)), "g") - * Cg(Ct(C(1) * C(1) * C(1)), "o")) - -local analyze_permissions = function (raw) - return lpegmatch (p_permissions, raw) -end - -local get_permissions = function (t, location) - if stringsub (location, #location) == "/" then - --- strip trailing slashes (lfs idiosyncrasy on Win) - location = lpegmatch (stripslashes, location) - end - local attributes = lfsattributes (location) - if not attributes then - print"" - print("attr", location, attributes) - os.exit() - end - - if not attributes and t == "f" then - attributes = get_tentative_attributes (location) - if not attributes then - return false - end - end - - local permissions - - if fileisreadable (location) then - --- link handling appears to be unnecessary because - --- lfs.attributes() will return the information on - --- the link target. - if mode == "link" then --follow and repeat - location = lfsreadlink (location) - attributes = lfsattributes (location) - end - end - - permissions = analyze_permissions (attributes.permissions) - - return { - location = location, - mode = attributes.mode, - owner = attributes.uid, --- useless on windows - permissions = permissions, - attributes = attributes, - } -end - -local check_conformance = function (spec, permissions, errcnt) - local uid = permissions.attributes.uid - local gid = permissions.attributes.gid - local raw = permissions.attributes.permissions - - out ("Owner: %d, group %d, permissions %s.", uid, gid, raw) - if ostype == "unix" then - if uid == 0 or gid == 0 then - out "Owned by the superuser, permission conflict likely." - errcnt = errcnt + 1 - end - end - - local user = permissions.permissions.u - if spec.r == true then - if user[1] == "r" then - out "Readable: ok." - else - out "Not readable: permissions need fixing." - errcnt = errcnt + 1 - end - end - - if spec.w == true then - if user[2] == "w" - or fileiswritable (permissions.location) then - out "Writable: ok." - else - out "Not writable: permissions need fixing." - errcnt = errcnt + 1 - end - end - - return errcnt -end - -local init_desired_permissions = function () - local paths = config.luaotfload.paths - return { - { "d", {"r","w"}, function () return caches.getwritablepath ("", "") end }, - { "d", {"r","w"}, paths.prefix }, - { "f", {"r","w"}, paths.index_path_lua .. ".gz" }, - { "f", {"r","w"}, paths.index_path_luc }, - { "f", {"r","w"}, paths.lookup_path_lua }, - { "f", {"r","w"}, paths.lookup_path_luc }, - } -end - -local check_permissions = function (errcnt) - out [[=============== file permissions ==============]] - local desired_permissions = init_desired_permissions () - for i = 1, #desired_permissions do - local t, spec, path = unpack (desired_permissions[i]) - if type (path) == "function" then - path = path () - end - - spec = tabletohash (spec) - - out ("Checking permissions of %s.", path) - - local permissions = get_permissions (t, path) - if permissions then - --inspect (permissions) - errcnt = check_conformance (spec, permissions, errcnt) - else - errcnt = errcnt + 1 - end - end - return errcnt -end - -local check_upstream - -if kpsefind_file ("https.lua", "lua") == nil then - check_upstream = function (errcnt) - out [[============= upstream repository ============= - WARNING: Cannot retrieve repository data. - Github API access requires the luasec library. - Grab it from <https://github.com/brunoos/luasec> - and retry.]] - return errcnt - end -else ---- github api stuff begin - local https = require "ssl.https" - - local gh_api_root = [[https://api.github.com]] - local release_url = [[https://github.com/lualatex/luaotfload/releases]] - local luaotfload_repo = [[lualatex/luaotfload]] - local user_agent = [[lualatex/luaotfload integrity check]] - local shortbytes = 8 - - local gh_shortrevision = function (rev) - return stringsub (rev, 1, shortbytes) - end - - local gh_encode_parameters = function (parameters) - local acc = {} - for field, value in next, parameters do - --- unsafe, non-urlencoded coz it’s all ascii chars - acc[#acc+1] = field .. "=" .. value - end - return "?" .. tableconcat (acc, "&") - end - - local gh_make_url = function (components, parameters) - local url = tableconcat ({ gh_api_root, - unpack (components) }, - "/") - if parameters then - url = url .. gh_encode_parameters (parameters) - end - return url - end - - local alright = [[HTTP/1.1 200 OK]] - - local gh_api_request = function (...) - local args = {...} - local nargs = #args - local final = args[nargs] - local request = { - url = "", - headers = { ["user-agent"] = user_agent }, - } - if type (final) == "table" then - args[nargs] = nil - request = gh_make_url (args, final) - else - request = gh_make_url (args) - end - - out ("Requesting <%s>.", request) - local response, code, headers, status = https.request (request) - if status ~= alright then - out "Request failed!" - return false - end - return response - end - - local gh_api_checklimit = function (headers) - local rawlimit = gh_api_request "rate_limit" - local limitdata = lua_of_json (rawlimit) - if not limitdata and limitdata.rate then - out "Cannot parse API rate limit." - return false - end - limitdata = limitdata.rate - - local limit = tonumber (limitdata.limit) - local left = tonumber (limitdata.remaining) - local reset = tonumber (limitdata.reset) - - out ("%d of %d Github API requests left.", left, limit) - if left == 0 then - out ("Cannot make any more API requests.") - if ostype == "unix" then - out ("Try again later at %s.", osdate ("%F %T", reset)) - else --- windows doesn’t C99 - out ("Try again later at %s.", - osdate ("%Y-%m-d %H:%M:%S", reset)) - end - end - return true - end - - local gh_tags = function () - out "Fetching tags from repository, please stand by." - local rawtags = gh_api_request ("repos", - luaotfload_repo, - "tags") - local taglist = lua_of_json (rawtags) - if not taglist or #taglist == 0 then - out "Cannot parse response." - return false - end - - local ntags = #taglist - out ("Repository contains %d tags.", ntags) - local _idx, latest = next (taglist) - out ("The most recent release is %s (revision %s).", - latest.name, - gh_shortrevision (latest.commit.sha)) - return latest - end - - local gh_compare = function (head, base) - if base == nil then - base = "HEAD" - end - out ("Fetching comparison between %s and %s, \z - please stand by.", - gh_shortrevision (head), - gh_shortrevision (base)) - local comparison = base .. "..." .. head - local rawstatus = gh_api_request ("repos", - luaotfload_repo, - "compare", - comparison) - local status = lua_of_json (rawstatus) - if not status then - out "Cannot parse response for status request." - return false - end - return status - end - - local gh_news = function (since) - local compared = gh_compare (since) - if not compared then - return false - end - local behind_by = compared.behind_by - local ahead_by = compared.ahead_by - local status = compared.status - out ("Comparison state: %s.", status) - if behind_by > 0 then - out ("Your Luaotfload is %d \z - revisions behind upstream.", - behind_by) - return behind_by - elseif status == "ahead" then - out "Since you are obviously from the future \z - I assume you already know the repository state." - else - out "Everything up to date. \z - Luaotfload is in sync with upstream." - end - return false - end - - local gh_catchup = function (current, latest) - local compared = gh_compare (latest, current) - local ahead_by = tonumber (compared.ahead_by) - if ahead_by > 0 then - local permalink_url = compared.permalink_url - out ("Your Luaotfload is %d revisions \z - behind the most recent release.", - ahead_by) - out ("To view the commit log, visit <%s>.", - permalink_url) - out ("You can grab an up to date tarball at <%s>.", - release_url) - return true - else - out "There weren't any new releases in the meantime." - out "Luaotfload is up to date." - end - return false - end - - check_upstream = function (current) - out "============= upstream repository =============" - local _succ = gh_api_checklimit () - local behind = gh_news (current) - if behind then - local latest = gh_tags () - local _behind = gh_catchup (current, - latest.commit.sha, - latest.name) - end - end - - --- trivium: diff since the first revision as pushed by Élie - --- in 2009 - --- local firstrevision = "c3ccb3ee07e0a67171c24960966ae974e0dd8e98" - --- check_upstream (firstrevision) -end ---- github api stuff end - -local print_envvar = function (var) - local val = osgetenv (var) - if val then - out ("%20s: %q", stringformat ("$%s", var), val) - return val - else - out ("%20s: <unset>", stringformat ("$%s", var)) - end -end - -local print_path = function (var) - local val = osgetenv (var) - if val then - local paths = filesplitpath (val) - if paths then - local npaths = #paths - if npaths == 1 then - out ("%20s: %q", stringformat ("$%s", var), val) - elseif npaths > 1 then - out ("%20s: <%d items>", stringformat ("$%s", var), npaths) - for i = 1, npaths do - out (" +: %q", paths[i]) - end - else - out ("%20s: <empty>") - end - end - else - out ("%20s: <unset>", stringformat ("$%s", var)) - end -end - -local print_kpsevar = function (var) - var = "$" .. var - local val = kpseexpand_var (var) - if val and val ~= var then - out ("%20s: %q", var, val) - return val - else - out ("%20s: <empty or unset>", var) - end -end - -local print_kpsepath = function (var) - var = "$" .. var - local val = kpseexpand_path (var) - if val and val ~= "" then - local paths = filesplitpath (val) - if paths then - local npaths = #paths - if npaths == 1 then - out ("%20s: %q", var, paths[1]) - elseif npaths > 1 then - out ("%20s: <%d items>", var, npaths) - for i = 1, npaths do - out (" +: %q", paths[i]) - end - else - out ("%20s: <empty>") - end - end - else - out ("%20s: <empty or unset>", var) - end -end - ---- this test first if a variable is set and then expands the ---- paths; this is necessitated by the fact that expand-path will ---- return the empty string both if the variable is unset and if ---- the directory does not exist - -local print_kpsepathvar = function (var) - local vvar = "$" .. var - local val = kpseexpand_var (vvar) - if val and val ~= vvar then - out ("%20s: %q", vvar, val) - print_kpsepath (var) - else - out ("%20s: <empty or unset>", var) - end -end - -local check_environment = function (errcnt) - out "============ environment settings =============" - out ("system: %s/%s", ostype, osname) - if ostype == "unix" and io.popen then - local chan = io.popen ("uname -a", "r") - if chan then - out ("info: %s", chan:read "*all") - chan:close () - end - end - - out "1) *shell environment*" - print_envvar "SHELL" - print_path "PATH" - print_path "OSFONTDIR" - print_envvar "USER" - if ostype == "windows" then - print_envvar "WINDIR" - print_envvar "CD" - print_path "TEMP" - elseif ostype == "unix" then - print_envvar "HOME" - print_envvar "PWD" - print_path "TMPDIR" - end - - out "2) *kpathsea*" - print_kpsepathvar "OPENTYPEFONTS" - print_kpsepathvar "TTFONTS" - - print_kpsepathvar "TEXMFCACHE" - print_kpsepathvar "TEXMFVAR" - - --- the expansion of these can be quite large; as they aren’t - --- usually essential to luaotfload, we won’t dump every single - --- path - print_kpsevar "LUAINPUTS" - print_kpsevar "CLUAINPUTS" - - return errcnt -end - -local anamneses = { - "environment", - "files", - "index", - "repository", - "permissions" -} - -local diagnose = function (job) - local errcnt = 0 - local asked = job.asked_diagnostics - if asked == "all" or asked == "thorough" then - asked = tabletohash (anamneses, true) - else - asked = lpegmatch (splitcomma, asked) - asked = tabletohash (asked, true) - end - - if asked.index == true then - errcnt = check_index (errcnt) - asked.index = nil - end - - if asked.environment == true then - errcnt = check_environment (errcnt) - asked.environment = nil - end - - if asked.files == true then - errcnt = verify_files (errcnt) - asked.files = nil - end - - if asked.permissions == true then - errcnt = check_permissions (errcnt) - asked.permissions = nil - end - - if asked.repository == true then - local status = config.luaotfload.status - check_upstream (status.notes.revision) - asked.repository = nil - end - - local rest = next (asked) - if rest ~= nil then --> something unknown - out ("Unknown diagnostic %q.", rest) - end - if errcnt == 0 then --> success - out ("Everything appears to be in order, \z - you may sleep well.") - return true, false - end - out ( [[=============================================== - WARNING - =============================================== - - The diagnostic detected %d errors. - - This version of luaotfload may have been - tampered with. Modified versions of the - luaotfload source are unsupported. Read the log - carefully and get a clean version from CTAN or - github: - - × http://www.ctan.org/pkg/luaotfload - × https://github.com/lualatex/luaotfload/releases - - If you are uncertain as to how to proceed, then - ask on the lualatex mailing list: - - http://www.tug.org/mailman/listinfo/lualatex-dev - - =============================================== -]], errcnt) - return true, false -end - -return diagnose - --- vim:tw=71:sw=4:ts=4:expandtab diff --git a/tex/compat/luaotfload/luaotfload-features.lua b/tex/compat/luaotfload/luaotfload-features.lua deleted file mode 100644 index f11f05b9b0ee299f20831037a8e3ffe9398f4e58..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/luaotfload-features.lua +++ /dev/null @@ -1,1406 +0,0 @@ -if not modules then modules = { } end modules ["features"] = { - version = "2.8", - comment = "companion to luaotfload-main.lua", - author = "Hans Hagen, Khaled Hosny, Elie Roux, Philipp Gesang", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -local type = type -local next = next -local tonumber = tonumber - -local lpeg = require "lpeg" -local lpegmatch = lpeg.match -local P = lpeg.P -local R = lpeg.R -local C = lpeg.C - -local table = table -local tabletohash = table.tohash -local tablesort = table.sort - ---- this appears to be based in part on luatex-fonts-def.lua - -local fonts = fonts -local definers = fonts.definers -local handlers = fonts.handlers -local fontidentifiers = fonts.hashes and fonts.hashes.identifiers -local otf = handlers.otf - -local config = config or { luaotfload = { run = { } } } - -local as_script = true -local normalize = function () end - -if config.luaotfload.run.live ~= false then - normalize = otf.features.normalize - as_script = false -end - ---[[HH (font-xtx) -- - tricky: we sort of bypass the parser and directly feed all into - the sub parser ---HH]]-- - -function definers.getspecification(str) - return "", str, "", ":", str -end - -local log = luaotfload.log -local report = log.report - -local stringgsub = string.gsub -local stringformat = string.format -local stringis_empty = string.is_empty - -local cmp_by_idx = function (a, b) return a.idx < b.idx end - -local defined_combos = 0 - -local handle_combination = function (combo, spec) - defined_combos = defined_combos + 1 - if not combo [1] then - report ("both", 0, "features", - "combo %d: Empty font combination requested.", - defined_combos) - return false - end - - if not fontidentifiers then - fontidentifiers = fonts.hashes and fonts.hashes.identifiers - end - - local chain = { } - local fontids = { } - local n = #combo - - tablesort (combo, cmp_by_idx) - - --- pass 1: skim combo and resolve fonts - report ("both", 2, "features", "combo %d: combining %d fonts.", - defined_combos, n) - for i = 1, n do - local cur = combo [i] - local id = cur.id - local idx = cur.idx - local fnt = fontidentifiers [id] - if fnt then - local chars = cur.chars - if chars == true then - report ("both", 2, "features", - " *> %.2d: fallback font %d at rank %d.", - i, id, idx) - else - report ("both", 2, "features", - " *> %.2d: include font %d at rank %d (%d items).", - i, id, idx, (chars and #chars or 0)) - end - chain [#chain + 1] = { fnt, chars, idx = idx } - fontids [#fontids + 1] = { id = id } - else - report ("both", 0, "features", - " *> %.2d: font %d at rank %d unknown, skipping.", - n, id, idx) - --- TODO might instead attempt to define the font at this point - --- but that’d require some modifications to the syntax - end - end - - local nc = #chain - if nc == 0 then - report ("both", 0, "features", - " *> no valid font (of %d) in combination.", n) - return false - end - - local basefnt = chain [1] [1] - if nc == 1 then - report ("both", 0, "features", - " *> combination boils down to a single font (%s) \z - of %d initially specified; not pursuing this any \z - further.", basefnt.fullname, n) - return basefnt - end - - local basechar = basefnt.characters - local baseprop = basefnt.properties - baseprop.name = spec.name - baseprop.virtualized = true - basefnt.fonts = fontids - - for i = 2, nc do - local cur = chain [i] - local fnt = cur [1] - local def = cur [2] - local src = fnt.characters - local cnt = 0 - - local pickchr = function (uc, unavailable) - local chr = src [uc] - if unavailable == true and basechar [uc] then - --- fallback mode: already known - return - end - if chr then - chr.commands = { { "slot", i, uc } } - basechar [uc] = chr - cnt = cnt + 1 - end - end - - if def == true then --> fallback; grab all currently unavailable - for uc, _chr in next, src do pickchr (uc, true) end - else --> grab only defined range - for j = 1, #def do - local this = def [j] - if type (this) == "number" then - report ("both", 2, "features", - " *> [%d][%d]: import codepoint U+%.4X", - i, j, this) - pickchr (this) - elseif type (this) == "table" then - local lo, hi = unpack (this) - report ("both", 2, "features", - " *> [%d][%d]: import codepoint range U+%.4X--U+%.4X", - i, j, lo, hi) - for uc = lo, hi do pickchr (uc) end - else - report ("both", 0, "features", - " *> item no. %d of combination definition \z - %d not processable.", j, i) - end - end - end - report ("both", 2, "features", - " *> font %d / %d: imported %d glyphs into combo.", - i, nc, cnt) - end - spec.lookup = "combo" - spec.file = basefnt.filename - spec.name = stringformat ("luaotfload<%d>", defined_combos) - spec.features = { normal = { spec.specification } } - spec.forced = "evl" - spec.eval = function () return basefnt end - return spec -end - ----[[ begin excerpt from font-ott.lua ]] - -local scripts = { - ["arab"] = "arabic", - ["armn"] = "armenian", - ["bali"] = "balinese", - ["beng"] = "bengali", - ["bopo"] = "bopomofo", - ["brai"] = "braille", - ["bugi"] = "buginese", - ["buhd"] = "buhid", - ["byzm"] = "byzantine music", - ["cans"] = "canadian syllabics", - ["cher"] = "cherokee", - ["copt"] = "coptic", - ["cprt"] = "cypriot syllabary", - ["cyrl"] = "cyrillic", - ["deva"] = "devanagari", - ["dsrt"] = "deseret", - ["ethi"] = "ethiopic", - ["geor"] = "georgian", - ["glag"] = "glagolitic", - ["goth"] = "gothic", - ["grek"] = "greek", - ["gujr"] = "gujarati", - ["guru"] = "gurmukhi", - ["hang"] = "hangul", - ["hani"] = "cjk ideographic", - ["hano"] = "hanunoo", - ["hebr"] = "hebrew", - ["ital"] = "old italic", - ["jamo"] = "hangul jamo", - ["java"] = "javanese", - ["kana"] = "hiragana and katakana", - ["khar"] = "kharosthi", - ["khmr"] = "khmer", - ["knda"] = "kannada", - ["lao" ] = "lao", - ["latn"] = "latin", - ["limb"] = "limbu", - ["linb"] = "linear b", - ["math"] = "mathematical alphanumeric symbols", - ["mlym"] = "malayalam", - ["mong"] = "mongolian", - ["musc"] = "musical symbols", - ["mymr"] = "myanmar", - ["nko" ] = "n\"ko", - ["ogam"] = "ogham", - ["orya"] = "oriya", - ["osma"] = "osmanya", - ["phag"] = "phags-pa", - ["phnx"] = "phoenician", - ["runr"] = "runic", - ["shaw"] = "shavian", - ["sinh"] = "sinhala", - ["sylo"] = "syloti nagri", - ["syrc"] = "syriac", - ["tagb"] = "tagbanwa", - ["tale"] = "tai le", - ["talu"] = "tai lu", - ["taml"] = "tamil", - ["telu"] = "telugu", - ["tfng"] = "tifinagh", - ["tglg"] = "tagalog", - ["thaa"] = "thaana", - ["thai"] = "thai", - ["tibt"] = "tibetan", - ["ugar"] = "ugaritic cuneiform", - ["xpeo"] = "old persian cuneiform", - ["xsux"] = "sumero-akkadian cuneiform", - ["yi" ] = "yi", -} -- [[ [scripts] ]] - -local languages = { - ["aba" ] = "abaza", - ["abk" ] = "abkhazian", - ["ach" ] = "acholi", - ["acr" ] = "achi", - ["ady" ] = "adyghe", - ["afk" ] = "afrikaans", - ["afr" ] = "afar", - ["agw" ] = "agaw", - ["aio" ] = "aiton", - ["aka" ] = "akan", - ["als" ] = "alsatian", - ["alt" ] = "altai", - ["amh" ] = "amharic", - ["ang" ] = "anglo-saxon", - ["apph"] = "phonetic transcription—americanist conventions", - ["ara" ] = "arabic", - ["arg" ] = "aragonese", - ["ari" ] = "aari", - ["ark" ] = "rakhine", - ["asm" ] = "assamese", - ["ast" ] = "asturian", - ["ath" ] = "athapaskan", - ["avr" ] = "avar", - ["awa" ] = "awadhi", - ["aym" ] = "aymara", - ["azb" ] = "torki", - ["aze" ] = "azerbaijani", - ["bad" ] = "badaga", - ["bad0"] = "banda", - ["bag" ] = "baghelkhandi", - ["bal" ] = "balkar", - ["ban" ] = "balinese", - ["bar" ] = "bavarian", - ["bau" ] = "baulé", - ["bbc" ] = "batak toba", - ["bbr" ] = "berber", - ["bch" ] = "bench", - ["bcr" ] = "bible cree", - ["bdy" ] = "bandjalang", - ["bel" ] = "belarussian", - ["bem" ] = "bemba", - ["ben" ] = "bengali", - ["bgc" ] = "haryanvi", - ["bgq" ] = "bagri", - ["bgr" ] = "bulgarian", - ["bhi" ] = "bhili", - ["bho" ] = "bhojpuri", - ["bik" ] = "bikol", - ["bil" ] = "bilen", - ["bis" ] = "bislama", - ["bjj" ] = "kanauji", - ["bkf" ] = "blackfoot", - ["bli" ] = "baluchi", - ["blk" ] = "pa'o karen", - ["bln" ] = "balante", - ["blt" ] = "balti", - ["bmb" ] = "bambara (bamanankan)", - ["bml" ] = "bamileke", - ["bos" ] = "bosnian", - ["bpy" ] = "bishnupriya manipuri", - ["bre" ] = "breton", - ["brh" ] = "brahui", - ["bri" ] = "braj bhasha", - ["brm" ] = "burmese", - ["brx" ] = "bodo", - ["bsh" ] = "bashkir", - ["bti" ] = "beti", - ["bts" ] = "batak simalungun", - ["bug" ] = "bugis", - ["cak" ] = "kaqchikel", - ["cat" ] = "catalan", - ["cbk" ] = "zamboanga chavacano", - ["ceb" ] = "cebuano", - ["cgg" ] = "chiga", - ["cha" ] = "chamorro", - ["che" ] = "chechen", - ["chg" ] = "chaha gurage", - ["chh" ] = "chattisgarhi", - ["chi" ] = "chichewa (chewa, nyanja)", - ["chk" ] = "chukchi", - ["chk0"] = "chuukese", - ["cho" ] = "choctaw", - ["chp" ] = "chipewyan", - ["chr" ] = "cherokee", - ["chu" ] = "chuvash", - ["chy" ] = "cheyenne", - ["cmr" ] = "comorian", - ["cop" ] = "coptic", - ["cor" ] = "cornish", - ["cos" ] = "corsican", - ["cpp" ] = "creoles", - ["cre" ] = "cree", - ["crr" ] = "carrier", - ["crt" ] = "crimean tatar", - ["csb" ] = "kashubian", - ["csl" ] = "church slavonic", - ["csy" ] = "czech", - ["ctg" ] = "chittagonian", - ["cuk" ] = "san blas kuna", - ["dan" ] = "danish", - ["dar" ] = "dargwa", - ["dax" ] = "dayi", - ["dcr" ] = "woods cree", - ["deu" ] = "german", - ["dgo" ] = "dogri", - ["dgr" ] = "dogri", - ["dhg" ] = "dhangu", - ["dhv" ] = "divehi (dhivehi, maldivian)", - ["diq" ] = "dimli", - ["div" ] = "divehi (dhivehi, maldivian)", - ["djr" ] = "zarma", - ["djr0"] = "djambarrpuyngu", - ["dng" ] = "dangme", - ["dnj" ] = "dan", - ["dnk" ] = "dinka", - ["dri" ] = "dari", - ["duj" ] = "dhuwal", - ["dun" ] = "dungan", - ["dzn" ] = "dzongkha", - ["ebi" ] = "ebira", - ["ecr" ] = "eastern cree", - ["edo" ] = "edo", - ["efi" ] = "efik", - ["ell" ] = "greek", - ["emk" ] = "eastern maninkakan", - ["eng" ] = "english", - ["erz" ] = "erzya", - ["esp" ] = "spanish", - ["esu" ] = "central yupik", - ["eti" ] = "estonian", - ["euq" ] = "basque", - ["evk" ] = "evenki", - ["evn" ] = "even", - ["ewe" ] = "ewe", - ["fan" ] = "french antillean", - ["fan0"] = " fang", - ["far" ] = "persian", - ["fat" ] = "fanti", - ["fin" ] = "finnish", - ["fji" ] = "fijian", - ["fle" ] = "dutch (flemish)", - ["fne" ] = "forest nenets", - ["fon" ] = "fon", - ["fos" ] = "faroese", - ["fra" ] = "french", - ["frc" ] = "cajun french", - ["fri" ] = "frisian", - ["frl" ] = "friulian", - ["frp" ] = "arpitan", - ["fta" ] = "futa", - ["ful" ] = "fulah", - ["fuv" ] = "nigerian fulfulde", - ["gad" ] = "ga", - ["gae" ] = "scottish gaelic (gaelic)", - ["gag" ] = "gagauz", - ["gal" ] = "galician", - ["gar" ] = "garshuni", - ["gaw" ] = "garhwali", - ["gez" ] = "ge'ez", - ["gih" ] = "githabul", - ["gil" ] = "gilyak", - ["gil0"] = " kiribati (gilbertese)", - ["gkp" ] = "kpelle (guinea)", - ["glk" ] = "gilaki", - ["gmz" ] = "gumuz", - ["gnn" ] = "gumatj", - ["gog" ] = "gogo", - ["gon" ] = "gondi", - ["grn" ] = "greenlandic", - ["gro" ] = "garo", - ["gua" ] = "guarani", - ["guc" ] = "wayuu", - ["guf" ] = "gupapuyngu", - ["guj" ] = "gujarati", - ["guz" ] = "gusii", - ["hai" ] = "haitian (haitian creole)", - ["hal" ] = "halam", - ["har" ] = "harauti", - ["hau" ] = "hausa", - ["haw" ] = "hawaiian", - ["hay" ] = "haya", - ["haz" ] = "hazaragi", - ["hbn" ] = "hammer-banna", - ["her" ] = "herero", - ["hil" ] = "hiligaynon", - ["hin" ] = "hindi", - ["hma" ] = "high mari", - ["hmn" ] = "hmong", - ["hmo" ] = "hiri motu", - ["hnd" ] = "hindko", - ["ho" ] = "ho", - ["hri" ] = "harari", - ["hrv" ] = "croatian", - ["hun" ] = "hungarian", - ["hye" ] = "armenian", - ["hye0"] = "armenian east", - ["iba" ] = "iban", - ["ibb" ] = "ibibio", - ["ibo" ] = "igbo", - ["ido" ] = "ido", - ["ijo" ] = "ijo languages", - ["ile" ] = "interlingue", - ["ilo" ] = "ilokano", - ["ina" ] = "interlingua", - ["ind" ] = "indonesian", - ["ing" ] = "ingush", - ["inu" ] = "inuktitut", - ["ipk" ] = "inupiat", - ["ipph"] = "phonetic transcription—ipa conventions", - ["iri" ] = "irish", - ["irt" ] = "irish traditional", - ["isl" ] = "icelandic", - ["ism" ] = "inari sami", - ["ita" ] = "italian", - ["iwr" ] = "hebrew", - ["jam" ] = "jamaican creole", - ["jan" ] = "japanese", - ["jav" ] = "javanese", - ["jbo" ] = "lojban", - ["jii" ] = "yiddish", - ["jud" ] = "ladino", - ["jul" ] = "jula", - ["kab" ] = "kabardian", - ["kab0"] = "kabyle", - ["kac" ] = "kachchi", - ["kal" ] = "kalenjin", - ["kan" ] = "kannada", - ["kar" ] = "karachay", - ["kat" ] = "georgian", - ["kaz" ] = "kazakh", - ["kde" ] = "makonde", - ["kea" ] = "kabuverdianu (crioulo)", - ["keb" ] = "kebena", - ["kek" ] = "kekchi", - ["kge" ] = "khutsuri georgian", - ["kha" ] = "khakass", - ["khk" ] = "khanty-kazim", - ["khm" ] = "khmer", - ["khs" ] = "khanty-shurishkar", - ["kht" ] = "khamti shan", - ["khv" ] = "khanty-vakhi", - ["khw" ] = "khowar", - ["kik" ] = "kikuyu (gikuyu)", - ["kir" ] = "kirghiz (kyrgyz)", - ["kis" ] = "kisii", - ["kiu" ] = "kirmanjki", - ["kjd" ] = "southern kiwai", - ["kjp" ] = "eastern pwo karen", - ["kkn" ] = "kokni", - ["klm" ] = "kalmyk", - ["kmb" ] = "kamba", - ["kmn" ] = "kumaoni", - ["kmo" ] = "komo", - ["kms" ] = "komso", - ["knr" ] = "kanuri", - ["kod" ] = "kodagu", - ["koh" ] = "korean old hangul", - ["kok" ] = "konkani", - ["kom" ] = "komi", - ["kon" ] = "kikongo", - ["kon0"] = "kongo", - ["kop" ] = "komi-permyak", - ["kor" ] = "korean", - ["kos" ] = "kosraean", - ["koz" ] = "komi-zyrian", - ["kpl" ] = "kpelle", - ["kri" ] = "krio", - ["krk" ] = "karakalpak", - ["krl" ] = "karelian", - ["krm" ] = "karaim", - ["krn" ] = "karen", - ["krt" ] = "koorete", - ["ksh" ] = "kashmiri", - ["ksh0"] = "ripuarian", - ["ksi" ] = "khasi", - ["ksm" ] = "kildin sami", - ["ksw" ] = "s’gaw karen", - ["kua" ] = "kuanyama", - ["kui" ] = "kui", - ["kul" ] = "kulvi", - ["kum" ] = "kumyk", - ["kur" ] = "kurdish", - ["kuu" ] = "kurukh", - ["kuy" ] = "kuy", - ["kyk" ] = "koryak", - ["kyu" ] = "western kayah", - ["lad" ] = "ladin", - ["lah" ] = "lahuli", - ["lak" ] = "lak", - ["lam" ] = "lambani", - ["lao" ] = "lao", - ["lat" ] = "latin", - ["laz" ] = "laz", - ["lcr" ] = "l-cree", - ["ldk" ] = "ladakhi", - ["lez" ] = "lezgi", - ["lij" ] = "ligurian", - ["lim" ] = "limburgish", - ["lin" ] = "lingala", - ["lis" ] = "lisu", - ["ljp" ] = "lampung", - ["lki" ] = "laki", - ["lma" ] = "low mari", - ["lmb" ] = "limbu", - ["lmo" ] = "lombard", - ["lmw" ] = "lomwe", - ["lom" ] = "loma", - ["lrc" ] = "luri", - ["lsb" ] = "lower sorbian", - ["lsm" ] = "lule sami", - ["lth" ] = "lithuanian", - ["ltz" ] = "luxembourgish", - ["lua" ] = "luba-lulua", - ["lub" ] = "luba-katanga", - ["lug" ] = "ganda", - ["luh" ] = "luyia", - ["luo" ] = "luo", - ["lvi" ] = "latvian", - ["mad" ] = "madura", - ["mag" ] = "magahi", - ["mah" ] = "marshallese", - ["maj" ] = "majang", - ["mak" ] = "makhuwa", - ["mal" ] = "malayalam reformed", - ["mam" ] = "mam", - ["man" ] = "mansi", - ["map" ] = "mapudungun", - ["mar" ] = "marathi", - ["maw" ] = "marwari", - ["mbn" ] = "mbundu", - ["mch" ] = "manchu", - ["mcr" ] = "moose cree", - ["mde" ] = "mende", - ["mdr" ] = "mandar", - ["men" ] = "me'en", - ["mer" ] = "meru", - ["mfe" ] = "morisyen", - ["min" ] = "minangkabau", - ["miz" ] = "mizo", - ["mkd" ] = "macedonian", - ["mkr" ] = "makasar", - ["mkw" ] = "kituba", - ["mle" ] = "male", - ["mlg" ] = "malagasy", - ["mln" ] = "malinke", - ["mly" ] = "malay", - ["mnd" ] = "mandinka", - ["mng" ] = "mongolian", - ["mni" ] = "manipuri", - ["mnk" ] = "maninka", - ["mnx" ] = "manx", - ["moh" ] = "mohawk", - ["mok" ] = "moksha", - ["mol" ] = "moldavian", - ["mon" ] = "mon", - ["mor" ] = "moroccan", - ["mos" ] = "mossi", - ["mri" ] = "maori", - ["mth" ] = "maithili", - ["mts" ] = "maltese", - ["mun" ] = "mundari", - ["mus" ] = "muscogee", - ["mwl" ] = "mirandese", - ["mww" ] = "hmong daw", - ["myn" ] = "mayan", - ["mzn" ] = "mazanderani", - ["nag" ] = "naga-assamese", - ["nah" ] = "nahuatl", - ["nan" ] = "nanai", - ["nap" ] = "neapolitan", - ["nas" ] = "naskapi", - ["nau" ] = "nauruan", - ["nav" ] = "navajo", - ["ncr" ] = "n-cree", - ["ndb" ] = "ndebele", - ["ndc" ] = "ndau", - ["ndg" ] = "ndonga", - ["nds" ] = "low saxon", - ["nep" ] = "nepali", - ["new" ] = "newari", - ["nga" ] = "ngbaka", - ["ngr" ] = "nagari", - ["nhc" ] = "norway house cree", - ["nis" ] = "nisi", - ["niu" ] = "niuean", - ["nkl" ] = "nyankole", - ["nko" ] = "n'ko", - ["nld" ] = "dutch", - ["noe" ] = "nimadi", - ["nog" ] = "nogai", - ["nor" ] = "norwegian", - ["nov" ] = "novial", - ["nsm" ] = "northern sami", - ["nso" ] = "sotho, northern", - ["nta" ] = "northern tai", - ["nto" ] = "esperanto", - ["nym" ] = "nyamwezi", - ["nyn" ] = "norwegian nynorsk", - ["oci" ] = "occitan", - ["ocr" ] = "oji-cree", - ["ojb" ] = "ojibway", - ["ori" ] = "odia", - ["oro" ] = "oromo", - ["oss" ] = "ossetian", - ["paa" ] = "palestinian aramaic", - ["pag" ] = "pangasinan", - ["pal" ] = "pali", - ["pam" ] = "pampangan", - ["pan" ] = "punjabi", - ["pap" ] = "palpa", - ["pap0"] = "papiamentu", - ["pas" ] = "pashto", - ["pau" ] = "palauan", - ["pcc" ] = "bouyei", - ["pcd" ] = "picard", - ["pdc" ] = "pennsylvania german", - ["pgr" ] = "polytonic greek", - ["phk" ] = "phake", - ["pih" ] = "norfolk", - ["pil" ] = "filipino", - ["plg" ] = "palaung", - ["plk" ] = "polish", - ["pms" ] = "piemontese", - ["pnb" ] = "western panjabi", - ["poh" ] = "pocomchi", - ["pon" ] = "pohnpeian", - ["pro" ] = "provencal", - ["ptg" ] = "portuguese", - ["pwo" ] = "western pwo karen", - ["qin" ] = "chin", - ["quc" ] = "k’iche’", - ["quh" ] = "quechua (bolivia)", - ["quz" ] = "quechua", - ["qvi" ] = "quechua (ecuador)", - ["qwh" ] = "quechua (peru)", - ["raj" ] = "rajasthani", - ["rar" ] = "rarotongan", - ["rbu" ] = "russian buriat", - ["rcr" ] = "r-cree", - ["rej" ] = "rejang", - ["ria" ] = "riang", - ["rif" ] = "tarifit", - ["rit" ] = "ritarungo", - ["rkw" ] = "arakwal", - ["rms" ] = "romansh", - ["rmy" ] = "vlax romani", - ["rom" ] = "romanian", - ["roy" ] = "romany", - ["rsy" ] = "rusyn", - ["rtm" ] = "rotuman", - ["rua" ] = "kinyarwanda", - ["run" ] = "rundi", - ["rup" ] = "aromanian", - ["rus" ] = "russian", - ["sad" ] = "sadri", - ["san" ] = "sanskrit", - ["sas" ] = "sasak", - ["sat" ] = "santali", - ["say" ] = "sayisi", - ["scn" ] = "sicilian", - ["sco" ] = "scots", - ["sek" ] = "sekota", - ["sel" ] = "selkup", - ["sga" ] = "old irish", - ["sgo" ] = "sango", - ["sgs" ] = "samogitian", - ["shi" ] = "tachelhit", - ["shn" ] = "shan", - ["sib" ] = "sibe", - ["sid" ] = "sidamo", - ["sig" ] = "silte gurage", - ["sks" ] = "skolt sami", - ["sky" ] = "slovak", - ["sla" ] = "slavey", - ["slv" ] = "slovenian", - ["sml" ] = "somali", - ["smo" ] = "samoan", - ["sna" ] = "sena", - ["sna0"] = "shona", - ["snd" ] = "sindhi", - ["snh" ] = "sinhala (sinhalese)", - ["snk" ] = "soninke", - ["sog" ] = "sodo gurage", - ["sop" ] = "songe", - ["sot" ] = "sotho, southern", - ["sqi" ] = "albanian", - ["srb" ] = "serbian", - ["srd" ] = "sardinian", - ["srk" ] = "saraiki", - ["srr" ] = "serer", - ["ssl" ] = "south slavey", - ["ssm" ] = "southern sami", - ["stq" ] = "saterland frisian", - ["suk" ] = "sukuma", - ["sun" ] = "sundanese", - ["sur" ] = "suri", - ["sva" ] = "svan", - ["sve" ] = "swedish", - ["swa" ] = "swadaya aramaic", - ["swk" ] = "swahili", - ["swz" ] = "swati", - ["sxt" ] = "sutu", - ["sxu" ] = "upper saxon", - ["syl" ] = "sylheti", - ["syr" ] = "syriac", - ["szl" ] = "silesian", - ["tab" ] = "tabasaran", - ["taj" ] = "tajiki", - ["tam" ] = "tamil", - ["tat" ] = "tatar", - ["tcr" ] = "th-cree", - ["tdd" ] = "dehong dai", - ["tel" ] = "telugu", - ["tet" ] = "tetum", - ["tgl" ] = "tagalog", - ["tgn" ] = "tongan", - ["tgr" ] = "tigre", - ["tgy" ] = "tigrinya", - ["tha" ] = "thai", - ["tht" ] = "tahitian", - ["tib" ] = "tibetan", - ["tiv" ] = "tiv", - ["tkm" ] = "turkmen", - ["tmh" ] = "tamashek", - ["tmn" ] = "temne", - ["tna" ] = "tswana", - ["tne" ] = "tundra nenets", - ["tng" ] = "tonga", - ["tod" ] = "todo", - ["tod0"] = "toma", - ["tpi" ] = "tok pisin", - ["trk" ] = "turkish", - ["tsg" ] = "tsonga", - ["tua" ] = "turoyo aramaic", - ["tul" ] = "tulu", - ["tuv" ] = "tuvin", - ["tvl" ] = "tuvalu", - ["twi" ] = "twi", - ["tyz" ] = "tày", - ["tzm" ] = "tamazight", - ["tzo" ] = "tzotzil", - ["udm" ] = "udmurt", - ["ukr" ] = "ukrainian", - ["umb" ] = "umbundu", - ["urd" ] = "urdu", - ["usb" ] = "upper sorbian", - ["uyg" ] = "uyghur", - ["uzb" ] = "uzbek", - ["vec" ] = "venetian", - ["ven" ] = "venda", - ["vit" ] = "vietnamese", - ["vol" ] = "volapük", - ["vro" ] = "võro", - ["wa" ] = "wa", - ["wag" ] = "wagdi", - ["war" ] = "waray-waray", - ["wcr" ] = "west-cree", - ["wel" ] = "welsh", - ["wlf" ] = "wolof", - ["wln" ] = "walloon", - ["xbd" ] = "lü", - ["xhs" ] = "xhosa", - ["xjb" ] = "minjangbal", - ["xog" ] = "soga", - ["xpe" ] = "kpelle (liberia)", - ["yak" ] = "sakha", - ["yao" ] = "yao", - ["yap" ] = "yapese", - ["yba" ] = "yoruba", - ["ycr" ] = "y-cree", - ["yic" ] = "yi classic", - ["yim" ] = "yi modern", - ["zea" ] = "zealandic", - ["zgh" ] = "standard morrocan tamazigh", - ["zha" ] = "zhuang", - ["zhh" ] = "chinese, hong kong sar", - ["zhp" ] = "chinese phonetic", - ["zhs" ] = "chinese simplified", - ["zht" ] = "chinese traditional", - ["znd" ] = "zande", - ["zul" ] = "zulu", - ["zza" ] = "zazaki", -} --[[ [languages] ]] - -local features = { - ["aalt"] = "access all alternates", - ["abvf"] = "above-base forms", - ["abvm"] = "above-base mark positioning", - ["abvs"] = "above-base substitutions", - ["afrc"] = "alternative fractions", - ["akhn"] = "akhands", - ["blwf"] = "below-base forms", - ["blwm"] = "below-base mark positioning", - ["blws"] = "below-base substitutions", - ["c2pc"] = "petite capitals from capitals", - ["c2sc"] = "small capitals from capitals", - ["calt"] = "contextual alternates", - ["case"] = "case-sensitive forms", - ["ccmp"] = "glyph composition/decomposition", - ["cfar"] = "conjunct form after ro", - ["cjct"] = "conjunct forms", - ["clig"] = "contextual ligatures", - ["cpct"] = "centered cjk punctuation", - ["cpsp"] = "capital spacing", - ["cswh"] = "contextual swash", - ["curs"] = "cursive positioning", - ["dflt"] = "default processing", - ["dist"] = "distances", - ["dlig"] = "discretionary ligatures", - ["dnom"] = "denominators", - ["dtls"] = "dotless forms", -- math - ["expt"] = "expert forms", - ["falt"] = "final glyph alternates", - ["fin2"] = "terminal forms #2", - ["fin3"] = "terminal forms #3", - ["fina"] = "terminal forms", - ["flac"] = "flattened accents over capitals", -- math - ["frac"] = "fractions", - ["fwid"] = "full width", - ["half"] = "half forms", - ["haln"] = "halant forms", - ["halt"] = "alternate half width", - ["hist"] = "historical forms", - ["hkna"] = "horizontal kana alternates", - ["hlig"] = "historical ligatures", - ["hngl"] = "hangul", - ["hojo"] = "hojo kanji forms", - ["hwid"] = "half width", - ["init"] = "initial forms", - ["isol"] = "isolated forms", - ["ital"] = "italics", - ["jalt"] = "justification alternatives", - ["jp04"] = "jis2004 forms", - ["jp78"] = "jis78 forms", - ["jp83"] = "jis83 forms", - ["jp90"] = "jis90 forms", - ["kern"] = "kerning", - ["lfbd"] = "left bounds", - ["liga"] = "standard ligatures", - ["ljmo"] = "leading jamo forms", - ["lnum"] = "lining figures", - ["locl"] = "localized forms", - ["ltra"] = "left-to-right alternates", - ["ltrm"] = "left-to-right mirrored forms", - ["mark"] = "mark positioning", - ["med2"] = "medial forms #2", - ["medi"] = "medial forms", - ["mgrk"] = "mathematical greek", - ["mkmk"] = "mark to mark positioning", - ["mset"] = "mark positioning via substitution", - ["nalt"] = "alternate annotation forms", - ["nlck"] = "nlc kanji forms", - ["nukt"] = "nukta forms", - ["numr"] = "numerators", - ["onum"] = "old style figures", - ["opbd"] = "optical bounds", - ["ordn"] = "ordinals", - ["ornm"] = "ornaments", - ["palt"] = "proportional alternate width", - ["pcap"] = "petite capitals", - ["pkna"] = "proportional kana", - ["pnum"] = "proportional figures", - ["pref"] = "pre-base forms", - ["pres"] = "pre-base substitutions", - ["pstf"] = "post-base forms", - ["psts"] = "post-base substitutions", - ["pwid"] = "proportional widths", - ["qwid"] = "quarter widths", - ["rand"] = "randomize", - ["rclt"] = "required contextual alternates", - ["rkrf"] = "rakar forms", - ["rlig"] = "required ligatures", - ["rphf"] = "reph form", - ["rtbd"] = "right bounds", - ["rtla"] = "right-to-left alternates", - ["rtlm"] = "right to left math", -- math - ["ruby"] = "ruby notation forms", - ["salt"] = "stylistic alternates", - ["sinf"] = "scientific inferiors", - ["size"] = "optical size", - ["smcp"] = "small capitals", - ["smpl"] = "simplified forms", - -- ["ss01"] = "stylistic set 1", - -- ["ss02"] = "stylistic set 2", - -- ["ss03"] = "stylistic set 3", - -- ["ss04"] = "stylistic set 4", - -- ["ss05"] = "stylistic set 5", - -- ["ss06"] = "stylistic set 6", - -- ["ss07"] = "stylistic set 7", - -- ["ss08"] = "stylistic set 8", - -- ["ss09"] = "stylistic set 9", - -- ["ss10"] = "stylistic set 10", - -- ["ss11"] = "stylistic set 11", - -- ["ss12"] = "stylistic set 12", - -- ["ss13"] = "stylistic set 13", - -- ["ss14"] = "stylistic set 14", - -- ["ss15"] = "stylistic set 15", - -- ["ss16"] = "stylistic set 16", - -- ["ss17"] = "stylistic set 17", - -- ["ss18"] = "stylistic set 18", - -- ["ss19"] = "stylistic set 19", - -- ["ss20"] = "stylistic set 20", - ["ssty"] = "script style", -- math - ["stch"] = "stretching glyph decomposition", - ["subs"] = "subscript", - ["sups"] = "superscript", - ["swsh"] = "swash", - ["titl"] = "titling", - ["tjmo"] = "trailing jamo forms", - ["tnam"] = "traditional name forms", - ["tnum"] = "tabular figures", - ["trad"] = "traditional forms", - ["twid"] = "third widths", - ["unic"] = "unicase", - ["valt"] = "alternate vertical metrics", - ["vatu"] = "vattu variants", - ["vert"] = "vertical writing", - ["vhal"] = "alternate vertical half metrics", - ["vjmo"] = "vowel jamo forms", - ["vkna"] = "vertical kana alternates", - ["vkrn"] = "vertical kerning", - ["vpal"] = "proportional alternate vertical metrics", - ["vrt2"] = "vertical rotation", - ["zero"] = "slashed zero", - - ["trep"] = "traditional tex replacements", - ["tlig"] = "traditional tex ligatures", - - ["ss.."] = "stylistic set ..", - ["cv.."] = "character variant ..", - ["js.."] = "justification ..", - - ["dv.."] = "devanagari ..", - ["ml.."] = "malayalam ..", -} --[[ [features] ]] - -local baselines = { - ["hang"] = "hanging baseline", - ["icfb"] = "ideographic character face bottom edge baseline", - ["icft"] = "ideographic character face tope edige baseline", - ["ideo"] = "ideographic em-box bottom edge baseline", - ["idtp"] = "ideographic em-box top edge baseline", - ["math"] = "mathematical centered baseline", - ["romn"] = "roman baseline" -} --[[ [baselines] ]] - -local swapped = function (h) - local r = { } - for k, v in next, h do - r[stringgsub(v,"[^a-z0-9]","")] = k -- is already lower - end - return r -end - -local verbosescripts = swapped(scripts ) -local verboselanguages = swapped(languages) -local verbosefeatures = swapped(features ) -local verbosebaselines = swapped(baselines) - ----[[ end excerpt from font-ott.lua ]] - ---[[doc-- - - As discussed, we will issue a warning because of incomplete support - when one of the scripts below is requested. - - Reference: https://github.com/lualatex/luaotfload/issues/31 - ---doc]]-- - -local support_incomplete = tabletohash({ - "deva", "beng", "guru", "gujr", - "orya", "taml", "telu", "knda", - "mlym", "sinh", -}, true) - ---[[doc-- - - Which features are active by default depends on the script - requested. - ---doc]]-- - ---- (string, string) dict -> (string, string) dict -local apply_default_features = function (speclist) - local default_features = luaotfload.features - - speclist = speclist or { } - speclist[""] = nil --- invalid options stub - - --- handle language tag - local language = speclist.language - if language then --- already lowercase at this point - language = stringgsub(language, "[^a-z0-9]", "") - language = rawget(verboselanguages, language) -- srsly, rawget? - or (languages[language] and language) - or "dflt" - else - language = "dflt" - end - speclist.language = language - - --- handle script tag - local script = speclist.script - if script then - script = stringgsub(script, "[^a-z0-9]","") - script = rawget(verbosescripts, script) - or (scripts[script] and script) - or "dflt" - if support_incomplete[script] then - report("log", 0, "features", - "Support for the requested script: " - .. "%q may be incomplete.", script) - end - else - script = "dflt" - end - speclist.script = script - - report("log", 2, "features", - "Auto-selecting default features for script: %s.", - script) - - local requested = default_features.defaults[script] - if not requested then - report("log", 2, "features", - "No default features for script %q, falling back to \"dflt\".", - script) - requested = default_features.defaults.dflt - end - - for feat, state in next, requested do - if speclist[feat] == nil then speclist[feat] = state end - end - - for feat, state in next, default_features.global do - --- This is primarily intended for setting node - --- mode unless “base” is requested, as stated - --- in the manual. - if speclist[feat] == nil then speclist[feat] = state end - end - return speclist -end - -local import_values = { - --- That’s what the 1.x parser did, not quite as graciously, - --- with an array of branch expressions. - -- "style", "optsize",--> from slashed notation; handled otherwise - { "lookup", false }, - { "sub", false }, -} - -local lookup_types = { "anon" , "file", "kpse" - , "my" , "name", "path" - , "combo" - } - -local select_lookup = function (request) - for i=1, #lookup_types do - local lookup = lookup_types[i] - local value = request[lookup] - if value then - return lookup, value - end - end -end - -local supported = { - b = "b", - i = "i", - bi = "bi", - aat = false, - icu = false, - gr = false, -} - ---- (string | (string * string) | bool) list -> (string * number) -local handle_slashed = function (modifiers) - local style, optsize - for i=1, #modifiers do - local mod = modifiers[i] - if type(mod) == "table" and mod[1] == "optsize" then --> optical size - optsize = tonumber(mod[2]) - elseif mod == false then - --- ignore - report("log", 0, "features", "unsupported font option: %s", v) - elseif supported[mod] then - style = supported[mod] - elseif not stringis_empty(mod) then - style = stringgsub(mod, "[^%a%d]", "") - end - end - return style, optsize -end - -local extract_subfont -do - local eof = P(-1) - local digit = R"09" - --- Theoretically a valid subfont address can be up to ten - --- digits long. - local sub_expr = P"(" * C(digit^1) * P")" * eof - local full_path = C(P(1 - sub_expr)^1) - extract_subfont = full_path * sub_expr -end - ---- spec -> spec -local handle_request = function (specification) - local request = lpegmatch(luaotfload.parsers.font_request, - specification.specification) -----inspect(request) - if not request then - --- happens when called with an absolute path - --- in an anonymous lookup; - --- we try to behave as friendly as possible - --- just go with it ... - report("log", 1, "features", "invalid request %q of type anon", - specification.specification) - report("log", 1, "features", - "use square bracket syntax or consult the documentation.") - --- The result of \fontname must be re-feedable into \font - --- which is expected by the Latex font mechanism. Now this - --- is complicated with TTC fonts that need to pass the - --- number of the requested subfont along with the file name. - --- Thus we test whether the request is a bare path only or - --- ends in a subfont expression (decimal digits inside - --- parentheses). - --- https://github.com/lualatex/luaotfload/issues/57 - local fullpath, sub = lpegmatch(extract_subfont, - specification.specification) - if fullpath and sub then - specification.sub = tonumber(sub) - specification.name = fullpath - else - specification.name = specification.specification - end - specification.lookup = "path" - return specification - end - - local lookup, name = select_lookup (request) - if lookup == "combo" then - return handle_combination (request.combo, specification) - end - - request.features = apply_default_features(request.features) - - if name then - if lookup == "file" then - local suffix = file.suffix (name) - specification.forcedname = name - specification.forced = suffix - name = file.removesuffix (name) - end - specification.name = name - specification.lookup = lookup or specification.lookup - end - - if request.modifiers then - local style, optsize = handle_slashed(request.modifiers) - specification.style, specification.optsize = style, optsize - end - - for n=1, #import_values do - local feat = import_values[n][1] - local keep = import_values[n][2] - local newvalue = request.features[feat] - if newvalue then - specification[feat] = request.features[feat] - if not keep then - request.features[feat] = nil - end - end - end - - --- The next line sets the “rand” feature to “random”; I haven’t - --- investigated it any further (luatex-fonts-ext), so it will - --- just stay here. - local features = specification.features - if not features then - features = { } - specification.features = features - end - features.normal = normalize (request.features) - local subfont = tonumber (request.sub) - if subfont and subfont >= 0 then - specification.sub = subfont + 1 - else - specification.sub = false - end - return specification -end - -fonts.names.handle_request = handle_request - - -if as_script == true then --- skip the remainder of the file - report ("log", 5, "features", - "Exiting early from luaotfload-features.lua.") - return -else - local registersplit = definers.registersplit - registersplit (":", handle_request, "common") - registersplit ("", handle_request, "xetex path style") -- catches \font\text=[names] -end - --- We assume that the other otf stuff is loaded already; though there’s --- another check below during the initialization phase. - - -local tlig_specification = { - { - type = "substitution", - features = everywhere, - data = { - --- quotedblright: - --- " (QUOTATION MARK) → ” (RIGHT DOUBLE QUOTATION MARK) - [0x0022] = 0x201D, - - --- quoteleft: - --- ' (APOSTROPHE) → ’ (RIGHT SINGLE QUOTATION MARK) - [0x0027] = 0x2019, - - --- quoteright: - --- ` (GRAVE ACCENT) → ‘ (LEFT SINGLE QUOTATION MARK) - [0x0060] = 0x2018, - }, - flags = noflags, - order = { "tlig" }, - prepend = true, - }, - { - type = "ligature", - features = everywhere, - data = { - - --- endash: - --- [--] (HYPHEN-MINUS, HYPHEN-MINUS) → – (EN DASH) - [0x2013] = {0x002D, 0x002D}, - - --- emdash: - --- [---] (HYPHEN-MINUS, HYPHEN-MINUS, HYPHEN-MINUS) → — (EM DASH) - [0x2014] = {0x002D, 0x002D, 0x002D}, - - --- quotedblleft: - --- [''] (GRAVE ACCENT, GRAVE ACCENT) → “ (LEFT DOUBLE QUOTATION MARK) - [0x201C] = {0x0060, 0x0060}, - - --- quotedblright: - --- [``] (APOSTROPHE, APOSTROPHE) → ” (RIGHT DOUBLE QUOTATION MARK) - [0x201D] = {0x0027, 0x0027}, - - --- exclamdown: - --- [!'] (EXCLAMATION MARK, GRAVE ACCENT) → ¡ (INVERTED EXCLAMATION MARK) - [0x00A1] = {0x0021, 0x0060}, - - --- questiondown: - --- [?'] (QUESTION MARK, GRAVE ACCENT) → ¡ (INVERTED EXCLAMATION MARK) - [0x00BF] = {0x003F, 0x0060}, - - --- next three originate in T1 encoding (Xetex applies them too) - --- quotedblbase: - --- [,,] (COMMA, COMMA) → ¡ (DOUBLE LOW-9 QUOTATION MARK) - [0x201E] = {0x002C, 0x002C}, - - --- LEFT-POINTING DOUBLE ANGLE QUOTATION MARK: - --- [,,] (LESS-THAN SIGN, LESS-THAN SIGN) → ¡ (LEFT-POINTING ANGLE QUOTATION MARK) - [0x00AB] = {0x003C, 0x003C}, - - --- RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK: - --- [,,] (GREATER-THAN SIGN, GREATER-THAN SIGN) → ¡ (RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK) - [0x00BB] = {0x003E, 0x003E}, - }, - flags = noflags, - order = { "tlig" }, - prepend = true, - }, -} - -local rot13_specification = { - type = "substitution", - features = everywhere, - data = { - [65] = 78, [ 97] = 110, [78] = 65, [110] = 97, - [66] = 79, [ 98] = 111, [79] = 66, [111] = 98, - [67] = 80, [ 99] = 112, [80] = 67, [112] = 99, - [68] = 81, [100] = 113, [81] = 68, [113] = 100, - [69] = 82, [101] = 114, [82] = 69, [114] = 101, - [70] = 83, [102] = 115, [83] = 70, [115] = 102, - [71] = 84, [103] = 116, [84] = 71, [116] = 103, - [72] = 85, [104] = 117, [85] = 72, [117] = 104, - [73] = 86, [105] = 118, [86] = 73, [118] = 105, - [74] = 87, [106] = 119, [87] = 74, [119] = 106, - [75] = 88, [107] = 120, [88] = 75, [120] = 107, - [76] = 89, [108] = 121, [89] = 76, [121] = 108, - [77] = 90, [109] = 122, [90] = 77, [122] = 109, - }, - flags = noflags, - order = { "rot13" }, - prepend = true, -} - -local interrolig_specification = { - { type = "ligature", data = { [0x203d] = {0x21, 0x3f}, [0x2e18] = {0xa1, 0xbf}, }, }, - { type = "ligature", data = { [0x203d] = {0x3f, 0x21}, [0x2e18] = {0xbf, 0xa1}, }, }, -} - -local autofeatures = { - --- always present with Luaotfload; anum for Arabic and Persian is - --- predefined in font-otc. - { "tlig" , tlig_specification , "tex ligatures and substitutions" }, - { "rot13", rot13_specification, "rot13" }, - { "!!??", interrolig_specification, "interrobang substitutions" }, -} - -local add_auto_features = function () - local nfeats = #autofeatures - logreport ("both", 5, "features", - "auto-installing %d feature definitions", nfeats) - for i = 1, nfeats do - local name, spec, desc = unpack (autofeatures [i]) - spec.description = desc - otf.addfeature (name, spec) - end -end - -return { - init = function () - - logreport = luaotfload.log.report - - if not fonts and fonts.handlers then - logreport ("log", 0, "features", - "OTF mechanisms missing -- did you forget to \z - load a font loader?") - return false - end - - add_auto_features () - - return true - end -} - --- vim:tw=79:sw=4:ts=4:expandtab diff --git a/tex/compat/luaotfload/luaotfload-glyphlist.lua b/tex/compat/luaotfload/luaotfload-glyphlist.lua deleted file mode 100644 index 55d629c833e7480ceb5c15e6f08a95e00da2b055..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/luaotfload-glyphlist.lua +++ /dev/null @@ -1,4312 +0,0 @@ -if not modules then modules = { } end modules ["font-age"] = { - version = 2.400, - comment = "part of the luaotfload package", - author = "luaotfload team / mkglyphlist", - copyright = "derived from https://raw.githubusercontent.com/adobe-type-tools/agl-aglfn/master/glyphlist.txt", - 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 -luaotfload-glyphlist.lua. ---doc]]-- - -return { - ["A"]=65, - ["AE"]=198, - ["AEacute"]=508, - ["AEmacron"]=482, - ["AEsmall"]=63462, - ["Aacute"]=193, - ["Aacutesmall"]=63457, - ["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, - ["Acircumflexsmall"]=63458, - ["Acircumflextilde"]=7850, - ["Acute"]=63177, - ["Acutesmall"]=63412, - ["Acyrillic"]=1040, - ["Adblgrave"]=512, - ["Adieresis"]=196, - ["Adieresiscyrillic"]=1234, - ["Adieresismacron"]=478, - ["Adieresissmall"]=63460, - ["Adotbelow"]=7840, - ["Adotmacron"]=480, - ["Agrave"]=192, - ["Agravesmall"]=63456, - ["Ahookabove"]=7842, - ["Aiecyrillic"]=1236, - ["Ainvertedbreve"]=514, - ["Alpha"]=913, - ["Alphatonos"]=902, - ["Amacron"]=256, - ["Amonospace"]=65313, - ["Aogonek"]=260, - ["Aring"]=197, - ["Aringacute"]=506, - ["Aringbelow"]=7680, - ["Aringsmall"]=63461, - ["Asmall"]=63329, - ["Atilde"]=195, - ["Atildesmall"]=63459, - ["Aybarmenian"]=1329, - ["B"]=66, - ["Bcircle"]=9399, - ["Bdotaccent"]=7682, - ["Bdotbelow"]=7684, - ["Becyrillic"]=1041, - ["Benarmenian"]=1330, - ["Beta"]=914, - ["Bhook"]=385, - ["Blinebelow"]=7686, - ["Bmonospace"]=65314, - ["Brevesmall"]=63220, - ["Bsmall"]=63330, - ["Btopbar"]=386, - ["C"]=67, - ["Caarmenian"]=1342, - ["Cacute"]=262, - ["Caron"]=63178, - ["Caronsmall"]=63221, - ["Ccaron"]=268, - ["Ccedilla"]=199, - ["Ccedillaacute"]=7688, - ["Ccedillasmall"]=63463, - ["Ccircle"]=9400, - ["Ccircumflex"]=264, - ["Cdot"]=266, - ["Cdotaccent"]=266, - ["Cedillasmall"]=63416, - ["Chaarmenian"]=1353, - ["Cheabkhasiancyrillic"]=1212, - ["Checyrillic"]=1063, - ["Chedescenderabkhasiancyrillic"]=1214, - ["Chedescendercyrillic"]=1206, - ["Chedieresiscyrillic"]=1268, - ["Cheharmenian"]=1347, - ["Chekhakassiancyrillic"]=1227, - ["Cheverticalstrokecyrillic"]=1208, - ["Chi"]=935, - ["Chook"]=391, - ["Circumflexsmall"]=63222, - ["Cmonospace"]=65315, - ["Coarmenian"]=1361, - ["Csmall"]=63331, - ["D"]=68, - ["DZ"]=497, - ["DZcaron"]=452, - ["Daarmenian"]=1332, - ["Dafrican"]=393, - ["Dcaron"]=270, - ["Dcedilla"]=7696, - ["Dcircle"]=9401, - ["Dcircumflexbelow"]=7698, - ["Dcroat"]=272, - ["Ddotaccent"]=7690, - ["Ddotbelow"]=7692, - ["Decyrillic"]=1044, - ["Deicoptic"]=1006, - ["Delta"]=8710, - ["Deltagreek"]=916, - ["Dhook"]=394, - ["Dieresis"]=63179, - ["DieresisAcute"]=63180, - ["DieresisGrave"]=63181, - ["Dieresissmall"]=63400, - ["Digammagreek"]=988, - ["Djecyrillic"]=1026, - ["Dlinebelow"]=7694, - ["Dmonospace"]=65316, - ["Dotaccentsmall"]=63223, - ["Dslash"]=272, - ["Dsmall"]=63332, - ["Dtopbar"]=395, - ["Dz"]=498, - ["Dzcaron"]=453, - ["Dzeabkhasiancyrillic"]=1248, - ["Dzecyrillic"]=1029, - ["Dzhecyrillic"]=1039, - ["E"]=69, - ["Eacute"]=201, - ["Eacutesmall"]=63465, - ["Ebreve"]=276, - ["Ecaron"]=282, - ["Ecedillabreve"]=7708, - ["Echarmenian"]=1333, - ["Ecircle"]=9402, - ["Ecircumflex"]=202, - ["Ecircumflexacute"]=7870, - ["Ecircumflexbelow"]=7704, - ["Ecircumflexdotbelow"]=7878, - ["Ecircumflexgrave"]=7872, - ["Ecircumflexhookabove"]=7874, - ["Ecircumflexsmall"]=63466, - ["Ecircumflextilde"]=7876, - ["Ecyrillic"]=1028, - ["Edblgrave"]=516, - ["Edieresis"]=203, - ["Edieresissmall"]=63467, - ["Edot"]=278, - ["Edotaccent"]=278, - ["Edotbelow"]=7864, - ["Efcyrillic"]=1060, - ["Egrave"]=200, - ["Egravesmall"]=63464, - ["Eharmenian"]=1335, - ["Ehookabove"]=7866, - ["Eightroman"]=8551, - ["Einvertedbreve"]=518, - ["Eiotifiedcyrillic"]=1124, - ["Elcyrillic"]=1051, - ["Elevenroman"]=8554, - ["Emacron"]=274, - ["Emacronacute"]=7702, - ["Emacrongrave"]=7700, - ["Emcyrillic"]=1052, - ["Emonospace"]=65317, - ["Encyrillic"]=1053, - ["Endescendercyrillic"]=1186, - ["Eng"]=330, - ["Enghecyrillic"]=1188, - ["Enhookcyrillic"]=1223, - ["Eogonek"]=280, - ["Eopen"]=400, - ["Epsilon"]=917, - ["Epsilontonos"]=904, - ["Ercyrillic"]=1056, - ["Ereversed"]=398, - ["Ereversedcyrillic"]=1069, - ["Escyrillic"]=1057, - ["Esdescendercyrillic"]=1194, - ["Esh"]=425, - ["Esmall"]=63333, - ["Eta"]=919, - ["Etarmenian"]=1336, - ["Etatonos"]=905, - ["Eth"]=208, - ["Ethsmall"]=63472, - ["Etilde"]=7868, - ["Etildebelow"]=7706, - ["Euro"]=8364, - ["Ezh"]=439, - ["Ezhcaron"]=494, - ["Ezhreversed"]=440, - ["F"]=70, - ["Fcircle"]=9403, - ["Fdotaccent"]=7710, - ["Feharmenian"]=1366, - ["Feicoptic"]=996, - ["Fhook"]=401, - ["Fitacyrillic"]=1138, - ["Fiveroman"]=8548, - ["Fmonospace"]=65318, - ["Fourroman"]=8547, - ["Fsmall"]=63334, - ["G"]=71, - ["GBsquare"]=13191, - ["Gacute"]=500, - ["Gamma"]=915, - ["Gammaafrican"]=404, - ["Gangiacoptic"]=1002, - ["Gbreve"]=286, - ["Gcaron"]=486, - ["Gcedilla"]=290, - ["Gcircle"]=9404, - ["Gcircumflex"]=284, - ["Gcommaaccent"]=290, - ["Gdot"]=288, - ["Gdotaccent"]=288, - ["Gecyrillic"]=1043, - ["Ghadarmenian"]=1346, - ["Ghemiddlehookcyrillic"]=1172, - ["Ghestrokecyrillic"]=1170, - ["Gheupturncyrillic"]=1168, - ["Ghook"]=403, - ["Gimarmenian"]=1331, - ["Gjecyrillic"]=1027, - ["Gmacron"]=7712, - ["Gmonospace"]=65319, - ["Grave"]=63182, - ["Gravesmall"]=63328, - ["Gsmall"]=63335, - ["Gsmallhook"]=667, - ["Gstroke"]=484, - ["H"]=72, - ["H18533"]=9679, - ["H18543"]=9642, - ["H18551"]=9643, - ["H22073"]=9633, - ["HPsquare"]=13259, - ["Haabkhasiancyrillic"]=1192, - ["Hadescendercyrillic"]=1202, - ["Hardsigncyrillic"]=1066, - ["Hbar"]=294, - ["Hbrevebelow"]=7722, - ["Hcedilla"]=7720, - ["Hcircle"]=9405, - ["Hcircumflex"]=292, - ["Hdieresis"]=7718, - ["Hdotaccent"]=7714, - ["Hdotbelow"]=7716, - ["Hmonospace"]=65320, - ["Hoarmenian"]=1344, - ["Horicoptic"]=1000, - ["Hsmall"]=63336, - ["Hungarumlaut"]=63183, - ["Hungarumlautsmall"]=63224, - ["Hzsquare"]=13200, - ["I"]=73, - ["IAcyrillic"]=1071, - ["IJ"]=306, - ["IUcyrillic"]=1070, - ["Iacute"]=205, - ["Iacutesmall"]=63469, - ["Ibreve"]=300, - ["Icaron"]=463, - ["Icircle"]=9406, - ["Icircumflex"]=206, - ["Icircumflexsmall"]=63470, - ["Icyrillic"]=1030, - ["Idblgrave"]=520, - ["Idieresis"]=207, - ["Idieresisacute"]=7726, - ["Idieresiscyrillic"]=1252, - ["Idieresissmall"]=63471, - ["Idot"]=304, - ["Idotaccent"]=304, - ["Idotbelow"]=7882, - ["Iebrevecyrillic"]=1238, - ["Iecyrillic"]=1045, - ["Ifraktur"]=8465, - ["Igrave"]=204, - ["Igravesmall"]=63468, - ["Ihookabove"]=7880, - ["Iicyrillic"]=1048, - ["Iinvertedbreve"]=522, - ["Iishortcyrillic"]=1049, - ["Imacron"]=298, - ["Imacroncyrillic"]=1250, - ["Imonospace"]=65321, - ["Iniarmenian"]=1339, - ["Iocyrillic"]=1025, - ["Iogonek"]=302, - ["Iota"]=921, - ["Iotaafrican"]=406, - ["Iotadieresis"]=938, - ["Iotatonos"]=906, - ["Ismall"]=63337, - ["Istroke"]=407, - ["Itilde"]=296, - ["Itildebelow"]=7724, - ["Izhitsacyrillic"]=1140, - ["Izhitsadblgravecyrillic"]=1142, - ["J"]=74, - ["Jaarmenian"]=1345, - ["Jcircle"]=9407, - ["Jcircumflex"]=308, - ["Jecyrillic"]=1032, - ["Jheharmenian"]=1355, - ["Jmonospace"]=65322, - ["Jsmall"]=63338, - ["K"]=75, - ["KBsquare"]=13189, - ["KKsquare"]=13261, - ["Kabashkircyrillic"]=1184, - ["Kacute"]=7728, - ["Kacyrillic"]=1050, - ["Kadescendercyrillic"]=1178, - ["Kahookcyrillic"]=1219, - ["Kappa"]=922, - ["Kastrokecyrillic"]=1182, - ["Kaverticalstrokecyrillic"]=1180, - ["Kcaron"]=488, - ["Kcedilla"]=310, - ["Kcircle"]=9408, - ["Kcommaaccent"]=310, - ["Kdotbelow"]=7730, - ["Keharmenian"]=1364, - ["Kenarmenian"]=1343, - ["Khacyrillic"]=1061, - ["Kheicoptic"]=998, - ["Khook"]=408, - ["Kjecyrillic"]=1036, - ["Klinebelow"]=7732, - ["Kmonospace"]=65323, - ["Koppacyrillic"]=1152, - ["Koppagreek"]=990, - ["Ksicyrillic"]=1134, - ["Ksmall"]=63339, - ["L"]=76, - ["LJ"]=455, - ["LL"]=63167, - ["Lacute"]=313, - ["Lambda"]=923, - ["Lcaron"]=317, - ["Lcedilla"]=315, - ["Lcircle"]=9409, - ["Lcircumflexbelow"]=7740, - ["Lcommaaccent"]=315, - ["Ldot"]=319, - ["Ldotaccent"]=319, - ["Ldotbelow"]=7734, - ["Ldotbelowmacron"]=7736, - ["Liwnarmenian"]=1340, - ["Lj"]=456, - ["Ljecyrillic"]=1033, - ["Llinebelow"]=7738, - ["Lmonospace"]=65324, - ["Lslash"]=321, - ["Lslashsmall"]=63225, - ["Lsmall"]=63340, - ["M"]=77, - ["MBsquare"]=13190, - ["Macron"]=63184, - ["Macronsmall"]=63407, - ["Macute"]=7742, - ["Mcircle"]=9410, - ["Mdotaccent"]=7744, - ["Mdotbelow"]=7746, - ["Menarmenian"]=1348, - ["Mmonospace"]=65325, - ["Msmall"]=63341, - ["Mturned"]=412, - ["Mu"]=924, - ["N"]=78, - ["NJ"]=458, - ["Nacute"]=323, - ["Ncaron"]=327, - ["Ncedilla"]=325, - ["Ncircle"]=9411, - ["Ncircumflexbelow"]=7754, - ["Ncommaaccent"]=325, - ["Ndotaccent"]=7748, - ["Ndotbelow"]=7750, - ["Nhookleft"]=413, - ["Nineroman"]=8552, - ["Nj"]=459, - ["Njecyrillic"]=1034, - ["Nlinebelow"]=7752, - ["Nmonospace"]=65326, - ["Nowarmenian"]=1350, - ["Nsmall"]=63342, - ["Ntilde"]=209, - ["Ntildesmall"]=63473, - ["Nu"]=925, - ["O"]=79, - ["OE"]=338, - ["OEsmall"]=63226, - ["Oacute"]=211, - ["Oacutesmall"]=63475, - ["Obarredcyrillic"]=1256, - ["Obarreddieresiscyrillic"]=1258, - ["Obreve"]=334, - ["Ocaron"]=465, - ["Ocenteredtilde"]=415, - ["Ocircle"]=9412, - ["Ocircumflex"]=212, - ["Ocircumflexacute"]=7888, - ["Ocircumflexdotbelow"]=7896, - ["Ocircumflexgrave"]=7890, - ["Ocircumflexhookabove"]=7892, - ["Ocircumflexsmall"]=63476, - ["Ocircumflextilde"]=7894, - ["Ocyrillic"]=1054, - ["Odblacute"]=336, - ["Odblgrave"]=524, - ["Odieresis"]=214, - ["Odieresiscyrillic"]=1254, - ["Odieresissmall"]=63478, - ["Odotbelow"]=7884, - ["Ogoneksmall"]=63227, - ["Ograve"]=210, - ["Ogravesmall"]=63474, - ["Oharmenian"]=1365, - ["Ohm"]=8486, - ["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, - ["Oslashacute"]=510, - ["Oslashsmall"]=63480, - ["Osmall"]=63343, - ["Ostrokeacute"]=510, - ["Otcyrillic"]=1150, - ["Otilde"]=213, - ["Otildeacute"]=7756, - ["Otildedieresis"]=7758, - ["Otildesmall"]=63477, - ["P"]=80, - ["Pacute"]=7764, - ["Pcircle"]=9413, - ["Pdotaccent"]=7766, - ["Pecyrillic"]=1055, - ["Peharmenian"]=1354, - ["Pemiddlehookcyrillic"]=1190, - ["Phi"]=934, - ["Phook"]=420, - ["Pi"]=928, - ["Piwrarmenian"]=1363, - ["Pmonospace"]=65328, - ["Psi"]=936, - ["Psicyrillic"]=1136, - ["Psmall"]=63344, - ["Q"]=81, - ["Qcircle"]=9414, - ["Qmonospace"]=65329, - ["Qsmall"]=63345, - ["R"]=82, - ["Raarmenian"]=1356, - ["Racute"]=340, - ["Rcaron"]=344, - ["Rcedilla"]=342, - ["Rcircle"]=9415, - ["Rcommaaccent"]=342, - ["Rdblgrave"]=528, - ["Rdotaccent"]=7768, - ["Rdotbelow"]=7770, - ["Rdotbelowmacron"]=7772, - ["Reharmenian"]=1360, - ["Rfraktur"]=8476, - ["Rho"]=929, - ["Ringsmall"]=63228, - ["Rinvertedbreve"]=530, - ["Rlinebelow"]=7774, - ["Rmonospace"]=65330, - ["Rsmall"]=63346, - ["Rsmallinverted"]=641, - ["Rsmallinvertedsuperior"]=694, - ["S"]=83, - ["SF010000"]=9484, - ["SF020000"]=9492, - ["SF030000"]=9488, - ["SF040000"]=9496, - ["SF050000"]=9532, - ["SF060000"]=9516, - ["SF070000"]=9524, - ["SF080000"]=9500, - ["SF090000"]=9508, - ["SF10000"]=9484, - ["SF100000"]=9472, - ["SF110000"]=9474, - ["SF190000"]=9569, - ["SF20000"]=9492, - ["SF200000"]=9570, - ["SF210000"]=9558, - ["SF220000"]=9557, - ["SF230000"]=9571, - ["SF240000"]=9553, - ["SF250000"]=9559, - ["SF260000"]=9565, - ["SF270000"]=9564, - ["SF280000"]=9563, - ["SF30000"]=9488, - ["SF360000"]=9566, - ["SF370000"]=9567, - ["SF380000"]=9562, - ["SF390000"]=9556, - ["SF40000"]=9496, - ["SF400000"]=9577, - ["SF410000"]=9574, - ["SF420000"]=9568, - ["SF430000"]=9552, - ["SF440000"]=9580, - ["SF450000"]=9575, - ["SF460000"]=9576, - ["SF470000"]=9572, - ["SF480000"]=9573, - ["SF490000"]=9561, - ["SF50000"]=9532, - ["SF500000"]=9560, - ["SF510000"]=9554, - ["SF520000"]=9555, - ["SF530000"]=9579, - ["SF540000"]=9578, - ["SF60000"]=9516, - ["SF70000"]=9524, - ["SF80000"]=9500, - ["SF90000"]=9508, - ["Sacute"]=346, - ["Sacutedotaccent"]=7780, - ["Sampigreek"]=992, - ["Scaron"]=352, - ["Scarondotaccent"]=7782, - ["Scaronsmall"]=63229, - ["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, - ["Shacyrillic"]=1064, - ["Shchacyrillic"]=1065, - ["Sheicoptic"]=994, - ["Shhacyrillic"]=1210, - ["Shimacoptic"]=1004, - ["Sigma"]=931, - ["Sixroman"]=8549, - ["Smonospace"]=65331, - ["Softsigncyrillic"]=1068, - ["Ssmall"]=63347, - ["Stigmagreek"]=986, - ["T"]=84, - ["Tau"]=932, - ["Tbar"]=358, - ["Tcaron"]=356, - ["Tcedilla"]=354, - ["Tcircle"]=9417, - ["Tcircumflexbelow"]=7792, - ["Tcommaaccent"]=354, - ["Tdotaccent"]=7786, - ["Tdotbelow"]=7788, - ["Tecyrillic"]=1058, - ["Tedescendercyrillic"]=1196, - ["Tenroman"]=8553, - ["Tetsecyrillic"]=1204, - ["Theta"]=920, - ["Thook"]=428, - ["Thorn"]=222, - ["Thornsmall"]=63486, - ["Threeroman"]=8546, - ["Tildesmall"]=63230, - ["Tiwnarmenian"]=1359, - ["Tlinebelow"]=7790, - ["Tmonospace"]=65332, - ["Toarmenian"]=1337, - ["Tonefive"]=444, - ["Tonesix"]=388, - ["Tonetwo"]=423, - ["Tretroflexhook"]=430, - ["Tsecyrillic"]=1062, - ["Tshecyrillic"]=1035, - ["Tsmall"]=63348, - ["Twelveroman"]=8555, - ["Tworoman"]=8545, - ["U"]=85, - ["Uacute"]=218, - ["Uacutesmall"]=63482, - ["Ubreve"]=364, - ["Ucaron"]=467, - ["Ucircle"]=9418, - ["Ucircumflex"]=219, - ["Ucircumflexbelow"]=7798, - ["Ucircumflexsmall"]=63483, - ["Ucyrillic"]=1059, - ["Udblacute"]=368, - ["Udblgrave"]=532, - ["Udieresis"]=220, - ["Udieresisacute"]=471, - ["Udieresisbelow"]=7794, - ["Udieresiscaron"]=473, - ["Udieresiscyrillic"]=1264, - ["Udieresisgrave"]=475, - ["Udieresismacron"]=469, - ["Udieresissmall"]=63484, - ["Udotbelow"]=7908, - ["Ugrave"]=217, - ["Ugravesmall"]=63481, - ["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, - ["Upsilon1"]=978, - ["Upsilonacutehooksymbolgreek"]=979, - ["Upsilonafrican"]=433, - ["Upsilondieresis"]=939, - ["Upsilondieresishooksymbolgreek"]=980, - ["Upsilonhooksymbol"]=978, - ["Upsilontonos"]=910, - ["Uring"]=366, - ["Ushortcyrillic"]=1038, - ["Usmall"]=63349, - ["Ustraightcyrillic"]=1198, - ["Ustraightstrokecyrillic"]=1200, - ["Utilde"]=360, - ["Utildeacute"]=7800, - ["Utildebelow"]=7796, - ["V"]=86, - ["Vcircle"]=9419, - ["Vdotbelow"]=7806, - ["Vecyrillic"]=1042, - ["Vewarmenian"]=1358, - ["Vhook"]=434, - ["Vmonospace"]=65334, - ["Voarmenian"]=1352, - ["Vsmall"]=63350, - ["Vtilde"]=7804, - ["W"]=87, - ["Wacute"]=7810, - ["Wcircle"]=9420, - ["Wcircumflex"]=372, - ["Wdieresis"]=7812, - ["Wdotaccent"]=7814, - ["Wdotbelow"]=7816, - ["Wgrave"]=7808, - ["Wmonospace"]=65335, - ["Wsmall"]=63351, - ["X"]=88, - ["Xcircle"]=9421, - ["Xdieresis"]=7820, - ["Xdotaccent"]=7818, - ["Xeharmenian"]=1341, - ["Xi"]=926, - ["Xmonospace"]=65336, - ["Xsmall"]=63352, - ["Y"]=89, - ["Yacute"]=221, - ["Yacutesmall"]=63485, - ["Yatcyrillic"]=1122, - ["Ycircle"]=9422, - ["Ycircumflex"]=374, - ["Ydieresis"]=376, - ["Ydieresissmall"]=63487, - ["Ydotaccent"]=7822, - ["Ydotbelow"]=7924, - ["Yericyrillic"]=1067, - ["Yerudieresiscyrillic"]=1272, - ["Ygrave"]=7922, - ["Yhook"]=435, - ["Yhookabove"]=7926, - ["Yiarmenian"]=1349, - ["Yicyrillic"]=1031, - ["Yiwnarmenian"]=1362, - ["Ymonospace"]=65337, - ["Ysmall"]=63353, - ["Ytilde"]=7928, - ["Yusbigcyrillic"]=1130, - ["Yusbigiotifiedcyrillic"]=1132, - ["Yuslittlecyrillic"]=1126, - ["Yuslittleiotifiedcyrillic"]=1128, - ["Z"]=90, - ["Zaarmenian"]=1334, - ["Zacute"]=377, - ["Zcaron"]=381, - ["Zcaronsmall"]=63231, - ["Zcircle"]=9423, - ["Zcircumflex"]=7824, - ["Zdot"]=379, - ["Zdotaccent"]=379, - ["Zdotbelow"]=7826, - ["Zecyrillic"]=1047, - ["Zedescendercyrillic"]=1176, - ["Zedieresiscyrillic"]=1246, - ["Zeta"]=918, - ["Zhearmenian"]=1338, - ["Zhebrevecyrillic"]=1217, - ["Zhecyrillic"]=1046, - ["Zhedescendercyrillic"]=1174, - ["Zhedieresiscyrillic"]=1244, - ["Zlinebelow"]=7828, - ["Zmonospace"]=65338, - ["Zsmall"]=63354, - ["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, - ["acutecmb"]=769, - ["acutecomb"]=769, - ["acutedeva"]=2388, - ["acutelowmod"]=719, - ["acutetonecmb"]=833, - ["acyrillic"]=1072, - ["adblgrave"]=513, - ["addakgurmukhi"]=2673, - ["adeva"]=2309, - ["adieresis"]=228, - ["adieresiscyrillic"]=1235, - ["adieresismacron"]=479, - ["adotbelow"]=7841, - ["adotmacron"]=481, - ["ae"]=230, - ["aeacute"]=509, - ["aekorean"]=12624, - ["aemacron"]=483, - ["afii00208"]=8213, - ["afii08941"]=8356, - ["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, - ["afii10063"]=63172, - ["afii10064"]=63173, - ["afii10065"]=1072, - ["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, - ["afii10145"]=1039, - ["afii10146"]=1122, - ["afii10147"]=1138, - ["afii10148"]=1140, - ["afii10192"]=63174, - ["afii10193"]=1119, - ["afii10194"]=1123, - ["afii10195"]=1139, - ["afii10196"]=1141, - ["afii10831"]=63175, - ["afii10832"]=63176, - ["afii10846"]=1241, - ["afii208"]=8213, - ["afii299"]=8206, - ["afii300"]=8207, - ["afii301"]=8205, - ["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, - ["afii57534"]=1749, - ["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, - ["afii57694"]=64298, - ["afii57695"]=64299, - ["afii57700"]=64331, - ["afii57705"]=64287, - ["afii57716"]=1520, - ["afii57717"]=1521, - ["afii57718"]=1522, - ["afii57723"]=64309, - ["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, - ["afii61573"]=8236, - ["afii61574"]=8237, - ["afii61575"]=8238, - ["afii61664"]=8204, - ["afii63167"]=1645, - ["afii64937"]=701, - ["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, - ["alef"]=1488, - ["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, - ["alefmaksurainitialarabic"]=65267, - ["alefmaksuramedialarabic"]=65268, - ["alefpatahhebrew"]=64302, - ["alefqamatshebrew"]=64303, - ["aleph"]=8501, - ["allequal"]=8780, - ["alpha"]=945, - ["alphatonos"]=940, - ["amacron"]=257, - ["amonospace"]=65345, - ["ampersand"]=38, - ["ampersandmonospace"]=65286, - ["ampersandsmall"]=63270, - ["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, - ["approximatelyequal"]=8773, - ["araeaekorean"]=12686, - ["araeakorean"]=12685, - ["arc"]=8978, - ["arighthalfring"]=7834, - ["aring"]=229, - ["aringacute"]=507, - ["aringbelow"]=7681, - ["arrowboth"]=8596, - ["arrowdashdown"]=8675, - ["arrowdashleft"]=8672, - ["arrowdashright"]=8674, - ["arrowdashup"]=8673, - ["arrowdblboth"]=8660, - ["arrowdbldown"]=8659, - ["arrowdblleft"]=8656, - ["arrowdblright"]=8658, - ["arrowdblup"]=8657, - ["arrowdown"]=8595, - ["arrowdownleft"]=8601, - ["arrowdownright"]=8600, - ["arrowdownwhite"]=8681, - ["arrowheaddownmod"]=709, - ["arrowheadleftmod"]=706, - ["arrowheadrightmod"]=707, - ["arrowheadupmod"]=708, - ["arrowhorizex"]=63719, - ["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, - ["arrowupdnbse"]=8616, - ["arrowupdownbase"]=8616, - ["arrowupleft"]=8598, - ["arrowupleftofdown"]=8645, - ["arrowupright"]=8599, - ["arrowupwhite"]=8679, - ["arrowvertex"]=63718, - ["asciicircum"]=94, - ["asciicircummonospace"]=65342, - ["asciitilde"]=126, - ["asciitildemonospace"]=65374, - ["ascript"]=593, - ["ascriptturned"]=594, - ["asmallhiragana"]=12353, - ["asmallkatakana"]=12449, - ["asmallkatakanahalfwidth"]=65383, - ["asterisk"]=42, - ["asteriskaltonearabic"]=1645, - ["asteriskarabic"]=1645, - ["asteriskmath"]=8727, - ["asteriskmonospace"]=65290, - ["asterisksmall"]=65121, - ["asterism"]=8258, - ["asuperior"]=63209, - ["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, - ["ayin"]=1506, - ["ayinaltonehebrew"]=64288, - ["ayinhebrew"]=1506, - ["b"]=98, - ["babengali"]=2476, - ["backslash"]=92, - ["backslashmonospace"]=65340, - ["badeva"]=2348, - ["bagujarati"]=2732, - ["bagurmukhi"]=2604, - ["bahiragana"]=12400, - ["bahtthai"]=3647, - ["bakatakana"]=12496, - ["bar"]=124, - ["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, - ["bet"]=1489, - ["beta"]=946, - ["betasymbolgreek"]=976, - ["betdagesh"]=64305, - ["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, - ["blackdownpointingtriangle"]=9660, - ["blackleftpointingpointer"]=9668, - ["blackleftpointingtriangle"]=9664, - ["blacklenticularbracketleft"]=12304, - ["blacklenticularbracketleftvertical"]=65083, - ["blacklenticularbracketright"]=12305, - ["blacklenticularbracketrightvertical"]=65084, - ["blacklowerlefttriangle"]=9699, - ["blacklowerrighttriangle"]=9698, - ["blackrectangle"]=9644, - ["blackrightpointingpointer"]=9658, - ["blackrightpointingtriangle"]=9654, - ["blacksmallsquare"]=9642, - ["blacksmilingface"]=9787, - ["blacksquare"]=9632, - ["blackstar"]=9733, - ["blackupperlefttriangle"]=9700, - ["blackupperrighttriangle"]=9701, - ["blackuppointingsmalltriangle"]=9652, - ["blackuppointingtriangle"]=9650, - ["blank"]=9251, - ["blinebelow"]=7687, - ["block"]=9608, - ["bmonospace"]=65346, - ["bobaimaithai"]=3610, - ["bohiragana"]=12412, - ["bokatakana"]=12508, - ["bparen"]=9373, - ["bqsquare"]=13251, - ["braceex"]=63732, - ["braceleft"]=123, - ["braceleftbt"]=63731, - ["braceleftmid"]=63730, - ["braceleftmonospace"]=65371, - ["braceleftsmall"]=65115, - ["bracelefttp"]=63729, - ["braceleftvertical"]=65079, - ["braceright"]=125, - ["bracerightbt"]=63742, - ["bracerightmid"]=63741, - ["bracerightmonospace"]=65373, - ["bracerightsmall"]=65116, - ["bracerighttp"]=63740, - ["bracerightvertical"]=65080, - ["bracketleft"]=91, - ["bracketleftbt"]=63728, - ["bracketleftex"]=63727, - ["bracketleftmonospace"]=65339, - ["bracketlefttp"]=63726, - ["bracketright"]=93, - ["bracketrightbt"]=63739, - ["bracketrightex"]=63738, - ["bracketrightmonospace"]=65341, - ["bracketrighttp"]=63737, - ["breve"]=728, - ["brevebelowcmb"]=814, - ["brevecmb"]=774, - ["breveinvertedbelowcmb"]=815, - ["breveinvertedcmb"]=785, - ["breveinverteddoublecmb"]=865, - ["bridgebelowcmb"]=810, - ["bridgeinvertedbelowcmb"]=826, - ["brokenbar"]=166, - ["bstroke"]=384, - ["bsuperior"]=63210, - ["btopbar"]=387, - ["buhiragana"]=12406, - ["bukatakana"]=12502, - ["bullet"]=8226, - ["bulletinverse"]=9688, - ["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, - ["cdot"]=267, - ["cdotaccent"]=267, - ["cdsquare"]=13253, - ["cedilla"]=184, - ["cedillacmb"]=807, - ["cent"]=162, - ["centigrade"]=8451, - ["centinferior"]=63199, - ["centmonospace"]=65504, - ["centoldstyle"]=63394, - ["centsuperior"]=63200, - ["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, - ["circle"]=9675, - ["circlemultiply"]=8855, - ["circleot"]=8857, - ["circleplus"]=8853, - ["circlepostalmark"]=12342, - ["circlewithlefthalfblack"]=9680, - ["circlewithrighthalfblack"]=9681, - ["circumflex"]=710, - ["circumflexbelowcmb"]=813, - ["circumflexcmb"]=770, - ["clear"]=8999, - ["clickalveolar"]=450, - ["clickdental"]=448, - ["clicklateral"]=449, - ["clickretroflex"]=451, - ["club"]=9827, - ["clubsuitblack"]=9827, - ["clubsuitwhite"]=9831, - ["cmcubedsquare"]=13220, - ["cmonospace"]=65347, - ["cmsquaredsquare"]=13216, - ["coarmenian"]=1409, - ["colon"]=58, - ["colonmonetary"]=8353, - ["colonmonospace"]=65306, - ["colonsign"]=8353, - ["colonsmall"]=65109, - ["colontriangularhalfmod"]=721, - ["colontriangularmod"]=720, - ["comma"]=44, - ["commaabovecmb"]=787, - ["commaaboverightcmb"]=789, - ["commaaccent"]=63171, - ["commaarabic"]=1548, - ["commaarmenian"]=1373, - ["commainferior"]=63201, - ["commamonospace"]=65292, - ["commareversedabovecmb"]=788, - ["commareversedmod"]=701, - ["commasmall"]=65104, - ["commasuperior"]=63202, - ["commaturnedabovecmb"]=786, - ["commaturnedmod"]=699, - ["compass"]=9788, - ["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, - ["copyrightsans"]=63721, - ["copyrightserif"]=63193, - ["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, - ["cyrBreve"]=63185, - ["cyrFlex"]=63186, - ["cyrbreve"]=63188, - ["cyrflex"]=63189, - ["d"]=100, - ["daarmenian"]=1380, - ["dabengali"]=2470, - ["dadarabic"]=1590, - ["dadeva"]=2342, - ["dadfinalarabic"]=65214, - ["dadinitialarabic"]=65215, - ["dadmedialarabic"]=65216, - ["dagesh"]=1468, - ["dageshhebrew"]=1468, - ["dagger"]=8224, - ["daggerdbl"]=8225, - ["dagujarati"]=2726, - ["dagurmukhi"]=2598, - ["dahiragana"]=12384, - ["dakatakana"]=12480, - ["dalarabic"]=1583, - ["dalet"]=1491, - ["daletdagesh"]=64307, - ["daletdageshhebrew"]=64307, - ["dalethatafpatah"]=1491, - ["dalethatafpatahhebrew"]=1491, - ["dalethatafsegol"]=1491, - ["dalethatafsegolhebrew"]=1491, - ["dalethebrew"]=1491, - ["dalethiriq"]=1491, - ["dalethiriqhebrew"]=1491, - ["daletholam"]=1491, - ["daletholamhebrew"]=1491, - ["daletpatah"]=1491, - ["daletpatahhebrew"]=1491, - ["daletqamats"]=1491, - ["daletqamatshebrew"]=1491, - ["daletqubuts"]=1491, - ["daletqubutshebrew"]=1491, - ["daletsegol"]=1491, - ["daletsegolhebrew"]=1491, - ["daletsheva"]=1491, - ["daletshevahebrew"]=1491, - ["dalettsere"]=1491, - ["dalettserehebrew"]=1491, - ["dalfinalarabic"]=65194, - ["dammaarabic"]=1615, - ["dammalowarabic"]=1615, - ["dammatanaltonearabic"]=1612, - ["dammatanarabic"]=1612, - ["danda"]=2404, - ["dargahebrew"]=1447, - ["dargalefthebrew"]=1447, - ["dasiapneumatacyrilliccmb"]=1157, - ["dblGrave"]=63187, - ["dblanglebracketleft"]=12298, - ["dblanglebracketleftvertical"]=65085, - ["dblanglebracketright"]=12299, - ["dblanglebracketrightvertical"]=65086, - ["dblarchinvertedbelowcmb"]=811, - ["dblarrowleft"]=8660, - ["dblarrowright"]=8658, - ["dbldanda"]=2405, - ["dblgrave"]=63190, - ["dblgravecmb"]=783, - ["dblintegral"]=8748, - ["dbllowline"]=8215, - ["dbllowlinecmb"]=819, - ["dbloverlinecmb"]=831, - ["dblprimemod"]=698, - ["dblverticalbar"]=8214, - ["dblverticallineabovecmb"]=782, - ["dbopomofo"]=12553, - ["dbsquare"]=13256, - ["dcaron"]=271, - ["dcedilla"]=7697, - ["dcircle"]=9427, - ["dcircumflexbelow"]=7699, - ["dcroat"]=273, - ["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, - ["decimalseparatorarabic"]=1643, - ["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, - ["dialytikatonos"]=901, - ["dialytikatonoscmb"]=836, - ["diamond"]=9830, - ["diamondsuitwhite"]=9826, - ["dieresis"]=168, - ["dieresisacute"]=63191, - ["dieresisbelowcmb"]=804, - ["dieresiscmb"]=776, - ["dieresisgrave"]=63192, - ["dieresistonos"]=901, - ["dihiragana"]=12386, - ["dikatakana"]=12482, - ["dittomark"]=12291, - ["divide"]=247, - ["divides"]=8739, - ["divisionslash"]=8725, - ["djecyrillic"]=1106, - ["dkshade"]=9619, - ["dlinebelow"]=7695, - ["dlsquare"]=13207, - ["dmacron"]=273, - ["dmonospace"]=65348, - ["dnblock"]=9604, - ["dochadathai"]=3598, - ["dodekthai"]=3604, - ["dohiragana"]=12393, - ["dokatakana"]=12489, - ["dollar"]=36, - ["dollarinferior"]=63203, - ["dollarmonospace"]=65284, - ["dollaroldstyle"]=63268, - ["dollarsmall"]=65129, - ["dollarsuperior"]=63204, - ["dong"]=8363, - ["dorusquare"]=13094, - ["dotaccent"]=729, - ["dotaccentcmb"]=775, - ["dotbelowcmb"]=803, - ["dotbelowcomb"]=803, - ["dotkatakana"]=12539, - ["dotlessi"]=305, - ["dotlessj"]=63166, - ["dotlessjstrokehook"]=644, - ["dotmath"]=8901, - ["dottedcircle"]=9676, - ["doubleyodpatah"]=64287, - ["doubleyodpatahhebrew"]=64287, - ["downtackbelowcmb"]=798, - ["downtackmod"]=725, - ["dparen"]=9375, - ["dsuperior"]=63211, - ["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, - ["edot"]=279, - ["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, - ["eightarabic"]=1640, - ["eightbengali"]=2542, - ["eightcircle"]=9319, - ["eightcircleinversesansserif"]=10129, - ["eightdeva"]=2414, - ["eighteencircle"]=9329, - ["eighteenparen"]=9349, - ["eighteenperiod"]=9369, - ["eightgujarati"]=2798, - ["eightgurmukhi"]=2670, - ["eighthackarabic"]=1640, - ["eighthangzhou"]=12328, - ["eighthnotebeamed"]=9835, - ["eightideographicparen"]=12839, - ["eightinferior"]=8328, - ["eightmonospace"]=65304, - ["eightoldstyle"]=63288, - ["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, - ["esuperior"]=63212, - ["eta"]=951, - ["etarmenian"]=1384, - ["etatonos"]=942, - ["eth"]=240, - ["etilde"]=7869, - ["etildebelow"]=7707, - ["etnahtafoukhhebrew"]=1425, - ["etnahtafoukhlefthebrew"]=1425, - ["etnahtahebrew"]=1425, - ["etnahtalefthebrew"]=1425, - ["eturned"]=477, - ["eukorean"]=12641, - ["euro"]=8364, - ["evowelsignbengali"]=2503, - ["evowelsigndeva"]=2375, - ["evowelsigngujarati"]=2759, - ["exclam"]=33, - ["exclamarmenian"]=1372, - ["exclamdbl"]=8252, - ["exclamdown"]=161, - ["exclamdownsmall"]=63393, - ["exclammonospace"]=65281, - ["exclamsmall"]=63265, - ["existential"]=8707, - ["ezh"]=658, - ["ezhcaron"]=495, - ["ezhcurl"]=659, - ["ezhreversed"]=441, - ["ezhtail"]=442, - ["f"]=102, - ["fadeva"]=2398, - ["fagurmukhi"]=2654, - ["fahrenheit"]=8457, - ["fathaarabic"]=1614, - ["fathalowarabic"]=1614, - ["fathatanarabic"]=1611, - ["fbopomofo"]=12552, - ["fcircle"]=9429, - ["fdotaccent"]=7711, - ["feharabic"]=1601, - ["feharmenian"]=1414, - ["fehfinalarabic"]=65234, - ["fehinitialarabic"]=65235, - ["fehmedialarabic"]=65236, - ["feicoptic"]=997, - ["female"]=9792, - ["ff"]=64256, - ["ffi"]=64259, - ["ffl"]=64260, - ["fi"]=64257, - ["fifteencircle"]=9326, - ["fifteenparen"]=9346, - ["fifteenperiod"]=9366, - ["figuredash"]=8210, - ["filledbox"]=9632, - ["filledrect"]=9644, - ["finalkaf"]=1498, - ["finalkafdagesh"]=64314, - ["finalkafdageshhebrew"]=64314, - ["finalkafhebrew"]=1498, - ["finalkafqamats"]=1498, - ["finalkafqamatshebrew"]=1498, - ["finalkafsheva"]=1498, - ["finalkafshevahebrew"]=1498, - ["finalmem"]=1501, - ["finalmemhebrew"]=1501, - ["finalnun"]=1503, - ["finalnunhebrew"]=1503, - ["finalpe"]=1507, - ["finalpehebrew"]=1507, - ["finaltsadi"]=1509, - ["finaltsadihebrew"]=1509, - ["firsttonechinese"]=713, - ["fisheye"]=9673, - ["fitacyrillic"]=1139, - ["five"]=53, - ["fivearabic"]=1637, - ["fivebengali"]=2539, - ["fivecircle"]=9316, - ["fivecircleinversesansserif"]=10126, - ["fivedeva"]=2411, - ["fiveeighths"]=8541, - ["fivegujarati"]=2795, - ["fivegurmukhi"]=2667, - ["fivehackarabic"]=1637, - ["fivehangzhou"]=12325, - ["fiveideographicparen"]=12836, - ["fiveinferior"]=8325, - ["fivemonospace"]=65301, - ["fiveoldstyle"]=63285, - ["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, - ["forall"]=8704, - ["four"]=52, - ["fourarabic"]=1636, - ["fourbengali"]=2538, - ["fourcircle"]=9315, - ["fourcircleinversesansserif"]=10125, - ["fourdeva"]=2410, - ["fourgujarati"]=2794, - ["fourgurmukhi"]=2666, - ["fourhackarabic"]=1636, - ["fourhangzhou"]=12324, - ["fourideographicparen"]=12835, - ["fourinferior"]=8324, - ["fourmonospace"]=65300, - ["fournumeratorbengali"]=2551, - ["fouroldstyle"]=63284, - ["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, - ["gcedilla"]=291, - ["gcircle"]=9430, - ["gcircumflex"]=285, - ["gcommaaccent"]=291, - ["gdot"]=289, - ["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, - ["gimel"]=1490, - ["gimeldagesh"]=64306, - ["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, - ["gradient"]=8711, - ["grave"]=96, - ["gravebelowcmb"]=790, - ["gravecmb"]=768, - ["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, - ["haaltonearabic"]=1729, - ["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, - ["hamzaarabic"]=1569, - ["hamzadammaarabic"]=1569, - ["hamzadammatanarabic"]=1569, - ["hamzafathaarabic"]=1569, - ["hamzafathatanarabic"]=1569, - ["hamzalowarabic"]=1569, - ["hamzalowkasraarabic"]=1569, - ["hamzalowkasratanarabic"]=1569, - ["hamzasukunarabic"]=1569, - ["hangulfiller"]=12644, - ["hardsigncyrillic"]=1098, - ["harpoonleftbarbup"]=8636, - ["harpoonrightbarbup"]=8640, - ["hasquare"]=13258, - ["hatafpatah"]=1458, - ["hatafpatah16"]=1458, - ["hatafpatah23"]=1458, - ["hatafpatah2f"]=1458, - ["hatafpatahhebrew"]=1458, - ["hatafpatahnarrowhebrew"]=1458, - ["hatafpatahquarterhebrew"]=1458, - ["hatafpatahwidehebrew"]=1458, - ["hatafqamats"]=1459, - ["hatafqamats1b"]=1459, - ["hatafqamats28"]=1459, - ["hatafqamats34"]=1459, - ["hatafqamatshebrew"]=1459, - ["hatafqamatsnarrowhebrew"]=1459, - ["hatafqamatsquarterhebrew"]=1459, - ["hatafqamatswidehebrew"]=1459, - ["hatafsegol"]=1457, - ["hatafsegol17"]=1457, - ["hatafsegol24"]=1457, - ["hatafsegol30"]=1457, - ["hatafsegolhebrew"]=1457, - ["hatafsegolnarrowhebrew"]=1457, - ["hatafsegolquarterhebrew"]=1457, - ["hatafsegolwidehebrew"]=1457, - ["hbar"]=295, - ["hbopomofo"]=12559, - ["hbrevebelow"]=7723, - ["hcedilla"]=7721, - ["hcircle"]=9431, - ["hcircumflex"]=293, - ["hdieresis"]=7719, - ["hdotaccent"]=7715, - ["hdotbelow"]=7717, - ["he"]=1492, - ["heart"]=9829, - ["heartsuitblack"]=9829, - ["heartsuitwhite"]=9825, - ["hedagesh"]=64308, - ["hedageshhebrew"]=64308, - ["hehaltonearabic"]=1729, - ["heharabic"]=1607, - ["hehebrew"]=1492, - ["hehfinalaltonearabic"]=64423, - ["hehfinalalttwoarabic"]=65258, - ["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, - ["het"]=1495, - ["hethebrew"]=1495, - ["hhook"]=614, - ["hhooksuperior"]=689, - ["hieuhacirclekorean"]=12923, - ["hieuhaparenkorean"]=12827, - ["hieuhcirclekorean"]=12909, - ["hieuhkorean"]=12622, - ["hieuhparenkorean"]=12813, - ["hihiragana"]=12402, - ["hikatakana"]=12498, - ["hikatakanahalfwidth"]=65419, - ["hiriq"]=1460, - ["hiriq14"]=1460, - ["hiriq21"]=1460, - ["hiriq2d"]=1460, - ["hiriqhebrew"]=1460, - ["hiriqnarrowhebrew"]=1460, - ["hiriqquarterhebrew"]=1460, - ["hiriqwidehebrew"]=1460, - ["hlinebelow"]=7830, - ["hmonospace"]=65352, - ["hoarmenian"]=1392, - ["hohipthai"]=3627, - ["hohiragana"]=12411, - ["hokatakana"]=12507, - ["hokatakanahalfwidth"]=65422, - ["holam"]=1465, - ["holam19"]=1465, - ["holam26"]=1465, - ["holam32"]=1465, - ["holamhebrew"]=1465, - ["holamnarrowhebrew"]=1465, - ["holamquarterhebrew"]=1465, - ["holamwidehebrew"]=1465, - ["honokhukthai"]=3630, - ["hookabovecomb"]=777, - ["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, - ["hypheninferior"]=63205, - ["hyphenmonospace"]=65293, - ["hyphensmall"]=65123, - ["hyphensuperior"]=63206, - ["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, - ["ilde"]=732, - ["iluyhebrew"]=1452, - ["imacron"]=299, - ["imacroncyrillic"]=1251, - ["imageorapproximatelyequal"]=8787, - ["imatragurmukhi"]=2623, - ["imonospace"]=65353, - ["increment"]=8710, - ["infinity"]=8734, - ["iniarmenian"]=1387, - ["integral"]=8747, - ["integralbottom"]=8993, - ["integralbt"]=8993, - ["integralex"]=63733, - ["integraltop"]=8992, - ["integraltp"]=8992, - ["intersection"]=8745, - ["intisquare"]=13061, - ["invbullet"]=9688, - ["invcircle"]=9689, - ["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, - ["isuperior"]=63213, - ["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, - ["kaf"]=1499, - ["kafarabic"]=1603, - ["kafdagesh"]=64315, - ["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, - ["kashidaautoarabic"]=1600, - ["kashidaautonosidebearingarabic"]=1600, - ["kasmallkatakana"]=12533, - ["kasquare"]=13188, - ["kasraarabic"]=1616, - ["kasratanarabic"]=1613, - ["kastrokecyrillic"]=1183, - ["katahiraprolongmarkhalfwidth"]=65392, - ["kaverticalstrokecyrillic"]=1181, - ["kbopomofo"]=12558, - ["kcalsquare"]=13193, - ["kcaron"]=489, - ["kcedilla"]=311, - ["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, - ["lamed"]=1500, - ["lameddagesh"]=64316, - ["lameddageshhebrew"]=64316, - ["lamedhebrew"]=1500, - ["lamedholam"]=1500, - ["lamedholamdagesh"]=1500, - ["lamedholamdageshhebrew"]=1500, - ["lamedholamhebrew"]=1500, - ["lamfinalarabic"]=65246, - ["lamhahinitialarabic"]=64714, - ["laminitialarabic"]=65247, - ["lamjeeminitialarabic"]=64713, - ["lamkhahinitialarabic"]=64715, - ["lamlamhehisolatedarabic"]=65010, - ["lammedialarabic"]=65248, - ["lammeemhahinitialarabic"]=64904, - ["lammeeminitialarabic"]=64716, - ["lammeemjeeminitialarabic"]=65247, - ["lammeemkhahinitialarabic"]=65247, - ["largecircle"]=9711, - ["lbar"]=410, - ["lbelt"]=620, - ["lbopomofo"]=12556, - ["lcaron"]=318, - ["lcedilla"]=316, - ["lcircle"]=9435, - ["lcircumflexbelow"]=7741, - ["lcommaaccent"]=316, - ["ldot"]=320, - ["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, - ["ll"]=63168, - ["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, - ["logicalnotreversed"]=8976, - ["logicalor"]=8744, - ["lolingthai"]=3621, - ["longs"]=383, - ["lowlinecenterline"]=65102, - ["lowlinecmb"]=818, - ["lowlinedashed"]=65101, - ["lozenge"]=9674, - ["lparen"]=9383, - ["lslash"]=322, - ["lsquare"]=8467, - ["lsuperior"]=63214, - ["ltshade"]=9617, - ["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, - ["mahapakhhebrew"]=1444, - ["mahapakhlefthebrew"]=1444, - ["mahiragana"]=12414, - ["maichattawalowleftthai"]=63637, - ["maichattawalowrightthai"]=63636, - ["maichattawathai"]=3659, - ["maichattawaupperleftthai"]=63635, - ["maieklowleftthai"]=63628, - ["maieklowrightthai"]=63627, - ["maiekthai"]=3656, - ["maiekupperleftthai"]=63626, - ["maihanakatleftthai"]=63620, - ["maihanakatthai"]=3633, - ["maitaikhuleftthai"]=63625, - ["maitaikhuthai"]=3655, - ["maitholowleftthai"]=63631, - ["maitholowrightthai"]=63630, - ["maithothai"]=3657, - ["maithoupperleftthai"]=63629, - ["maitrilowleftthai"]=63634, - ["maitrilowrightthai"]=63633, - ["maitrithai"]=3658, - ["maitriupperleftthai"]=63632, - ["maiyamokthai"]=3654, - ["makatakana"]=12510, - ["makatakanahalfwidth"]=65423, - ["male"]=9794, - ["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, - ["mem"]=1502, - ["memdagesh"]=64318, - ["memdageshhebrew"]=64318, - ["memhebrew"]=1502, - ["menarmenian"]=1396, - ["merkhahebrew"]=1445, - ["merkhakefulahebrew"]=1446, - ["merkhakefulalefthebrew"]=1446, - ["merkhalefthebrew"]=1445, - ["mhook"]=625, - ["mhzsquare"]=13202, - ["middledotkatakanahalfwidth"]=65381, - ["middot"]=183, - ["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, - ["msuperior"]=63215, - ["mturned"]=623, - ["mu"]=181, - ["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, - ["munahhebrew"]=1443, - ["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, - ["napostrophe"]=329, - ["nasquare"]=13185, - ["nbopomofo"]=12555, - ["nbspace"]=160, - ["ncaron"]=328, - ["ncedilla"]=326, - ["ncircle"]=9437, - ["ncircumflexbelow"]=7755, - ["ncommaaccent"]=326, - ["ndotaccent"]=7749, - ["ndotbelow"]=7751, - ["nehiragana"]=12397, - ["nekatakana"]=12493, - ["nekatakanahalfwidth"]=65416, - ["newsheqelsign"]=8362, - ["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, - ["nikhahitleftthai"]=63641, - ["nikhahitthai"]=3661, - ["nine"]=57, - ["ninearabic"]=1641, - ["ninebengali"]=2543, - ["ninecircle"]=9320, - ["ninecircleinversesansserif"]=10130, - ["ninedeva"]=2415, - ["ninegujarati"]=2799, - ["ninegurmukhi"]=2671, - ["ninehackarabic"]=1641, - ["ninehangzhou"]=12329, - ["nineideographicparen"]=12840, - ["nineinferior"]=8329, - ["ninemonospace"]=65305, - ["nineoldstyle"]=63289, - ["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, - ["noonhehinitialarabic"]=65255, - ["nooninitialarabic"]=65255, - ["noonjeeminitialarabic"]=64722, - ["noonjeemisolatedarabic"]=64587, - ["noonmedialarabic"]=65256, - ["noonmeeminitialarabic"]=64725, - ["noonmeemisolatedarabic"]=64590, - ["noonnoonfinalarabic"]=64653, - ["notcontains"]=8716, - ["notelement"]=8713, - ["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, - ["nun"]=1504, - ["nundagesh"]=64320, - ["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, - ["odblacute"]=337, - ["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, - ["omega1"]=982, - ["omegacyrillic"]=1121, - ["omegalatinclosed"]=631, - ["omegaroundcyrillic"]=1147, - ["omegatitlocyrillic"]=1149, - ["omegatonos"]=974, - ["omgujarati"]=2768, - ["omicron"]=959, - ["omicrontonos"]=972, - ["omonospace"]=65359, - ["one"]=49, - ["onearabic"]=1633, - ["onebengali"]=2535, - ["onecircle"]=9312, - ["onecircleinversesansserif"]=10122, - ["onedeva"]=2407, - ["onedotenleader"]=8228, - ["oneeighth"]=8539, - ["onefitted"]=63196, - ["onegujarati"]=2791, - ["onegurmukhi"]=2663, - ["onehackarabic"]=1633, - ["onehalf"]=189, - ["onehangzhou"]=12321, - ["oneideographicparen"]=12832, - ["oneinferior"]=8321, - ["onemonospace"]=65297, - ["onenumeratorbengali"]=2548, - ["oneoldstyle"]=63281, - ["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, - ["openbullet"]=9702, - ["option"]=8997, - ["ordfeminine"]=170, - ["ordmasculine"]=186, - ["orthogonal"]=8735, - ["oshortdeva"]=2322, - ["oshortvowelsigndeva"]=2378, - ["oslash"]=248, - ["oslashacute"]=511, - ["osmallhiragana"]=12361, - ["osmallkatakana"]=12457, - ["osmallkatakanahalfwidth"]=65387, - ["ostrokeacute"]=511, - ["osuperior"]=63216, - ["otcyrillic"]=1151, - ["otilde"]=245, - ["otildeacute"]=7757, - ["otildedieresis"]=7759, - ["oubopomofo"]=12577, - ["overline"]=8254, - ["overlinecenterline"]=65098, - ["overlinecmb"]=773, - ["overlinedashed"]=65097, - ["overlinedblwavy"]=65100, - ["overlinewavy"]=65099, - ["overscore"]=175, - ["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, - ["parenleftbt"]=63725, - ["parenleftex"]=63724, - ["parenleftinferior"]=8333, - ["parenleftmonospace"]=65288, - ["parenleftsmall"]=65113, - ["parenleftsuperior"]=8317, - ["parenlefttp"]=63723, - ["parenleftvertical"]=65077, - ["parenright"]=41, - ["parenrightaltonearabic"]=64831, - ["parenrightbt"]=63736, - ["parenrightex"]=63735, - ["parenrightinferior"]=8334, - ["parenrightmonospace"]=65289, - ["parenrightsmall"]=65114, - ["parenrightsuperior"]=8318, - ["parenrighttp"]=63734, - ["parenrightvertical"]=65078, - ["partialdiff"]=8706, - ["paseqhebrew"]=1472, - ["pashtahebrew"]=1433, - ["pasquare"]=13225, - ["patah"]=1463, - ["patah11"]=1463, - ["patah1d"]=1463, - ["patah2a"]=1463, - ["patahhebrew"]=1463, - ["patahnarrowhebrew"]=1463, - ["patahquarterhebrew"]=1463, - ["patahwidehebrew"]=1463, - ["pazerhebrew"]=1441, - ["pbopomofo"]=12550, - ["pcircle"]=9439, - ["pdotaccent"]=7767, - ["pe"]=1508, - ["pecyrillic"]=1087, - ["pedagesh"]=64324, - ["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, - ["periodinferior"]=63207, - ["periodmonospace"]=65294, - ["periodsmall"]=65106, - ["periodsuperior"]=63208, - ["perispomenigreekcmb"]=834, - ["perpendicular"]=8869, - ["perthousand"]=8240, - ["peseta"]=8359, - ["pfsquare"]=13194, - ["phabengali"]=2475, - ["phadeva"]=2347, - ["phagujarati"]=2731, - ["phagurmukhi"]=2603, - ["phi"]=966, - ["phi1"]=981, - ["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, - ["propersubset"]=8834, - ["propersuperset"]=8835, - ["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, - ["qamats"]=1464, - ["qamats10"]=1464, - ["qamats1a"]=1464, - ["qamats1c"]=1464, - ["qamats27"]=1464, - ["qamats29"]=1464, - ["qamats33"]=1464, - ["qamatsde"]=1464, - ["qamatshebrew"]=1464, - ["qamatsnarrowhebrew"]=1464, - ["qamatsqatanhebrew"]=1464, - ["qamatsqatannarrowhebrew"]=1464, - ["qamatsqatanquarterhebrew"]=1464, - ["qamatsqatanwidehebrew"]=1464, - ["qamatsquarterhebrew"]=1464, - ["qamatswidehebrew"]=1464, - ["qarneyparahebrew"]=1439, - ["qbopomofo"]=12561, - ["qcircle"]=9440, - ["qhook"]=672, - ["qmonospace"]=65361, - ["qof"]=1511, - ["qofdagesh"]=64327, - ["qofdageshhebrew"]=64327, - ["qofhatafpatah"]=1511, - ["qofhatafpatahhebrew"]=1511, - ["qofhatafsegol"]=1511, - ["qofhatafsegolhebrew"]=1511, - ["qofhebrew"]=1511, - ["qofhiriq"]=1511, - ["qofhiriqhebrew"]=1511, - ["qofholam"]=1511, - ["qofholamhebrew"]=1511, - ["qofpatah"]=1511, - ["qofpatahhebrew"]=1511, - ["qofqamats"]=1511, - ["qofqamatshebrew"]=1511, - ["qofqubuts"]=1511, - ["qofqubutshebrew"]=1511, - ["qofsegol"]=1511, - ["qofsegolhebrew"]=1511, - ["qofsheva"]=1511, - ["qofshevahebrew"]=1511, - ["qoftsere"]=1511, - ["qoftserehebrew"]=1511, - ["qparen"]=9388, - ["quarternote"]=9833, - ["qubuts"]=1467, - ["qubuts18"]=1467, - ["qubuts25"]=1467, - ["qubuts31"]=1467, - ["qubutshebrew"]=1467, - ["qubutsnarrowhebrew"]=1467, - ["qubutsquarterhebrew"]=1467, - ["qubutswidehebrew"]=1467, - ["question"]=63, - ["questionarabic"]=1567, - ["questionarmenian"]=1374, - ["questiondown"]=191, - ["questiondownsmall"]=63423, - ["questiongreek"]=894, - ["questionmonospace"]=65311, - ["questionsmall"]=63295, - ["quotedbl"]=34, - ["quotedblbase"]=8222, - ["quotedblleft"]=8220, - ["quotedblmonospace"]=65282, - ["quotedblprime"]=12318, - ["quotedblprimereversed"]=12317, - ["quotedblright"]=8221, - ["quoteleft"]=8216, - ["quoteleftreversed"]=8219, - ["quotereversed"]=8219, - ["quoteright"]=8217, - ["quoterightn"]=329, - ["quotesinglbase"]=8218, - ["quotesingle"]=39, - ["quotesinglemonospace"]=65287, - ["r"]=114, - ["raarmenian"]=1404, - ["rabengali"]=2480, - ["racute"]=341, - ["radeva"]=2352, - ["radical"]=8730, - ["radicalex"]=63717, - ["radoverssquare"]=13230, - ["radoverssquaredsquare"]=13231, - ["radsquare"]=13229, - ["rafe"]=1471, - ["rafehebrew"]=1471, - ["ragujarati"]=2736, - ["ragurmukhi"]=2608, - ["rahiragana"]=12425, - ["rakatakana"]=12521, - ["rakatakanahalfwidth"]=65431, - ["ralowerdiagonalbengali"]=2545, - ["ramiddlediagonalbengali"]=2544, - ["ramshorn"]=612, - ["ratio"]=8758, - ["rbopomofo"]=12566, - ["rcaron"]=345, - ["rcedilla"]=343, - ["rcircle"]=9441, - ["rcommaaccent"]=343, - ["rdblgrave"]=529, - ["rdotaccent"]=7769, - ["rdotbelow"]=7771, - ["rdotbelowmacron"]=7773, - ["referencemark"]=8251, - ["reflexsubset"]=8838, - ["reflexsuperset"]=8839, - ["registered"]=174, - ["registersans"]=63720, - ["registerserif"]=63194, - ["reharabic"]=1585, - ["reharmenian"]=1408, - ["rehfinalarabic"]=65198, - ["rehiragana"]=12428, - ["rehyehaleflamarabic"]=1585, - ["rekatakana"]=12524, - ["rekatakanahalfwidth"]=65434, - ["resh"]=1512, - ["reshdageshhebrew"]=64328, - ["reshhatafpatah"]=1512, - ["reshhatafpatahhebrew"]=1512, - ["reshhatafsegol"]=1512, - ["reshhatafsegolhebrew"]=1512, - ["reshhebrew"]=1512, - ["reshhiriq"]=1512, - ["reshhiriqhebrew"]=1512, - ["reshholam"]=1512, - ["reshholamhebrew"]=1512, - ["reshpatah"]=1512, - ["reshpatahhebrew"]=1512, - ["reshqamats"]=1512, - ["reshqamatshebrew"]=1512, - ["reshqubuts"]=1512, - ["reshqubutshebrew"]=1512, - ["reshsegol"]=1512, - ["reshsegolhebrew"]=1512, - ["reshsheva"]=1512, - ["reshshevahebrew"]=1512, - ["reshtsere"]=1512, - ["reshtserehebrew"]=1512, - ["reversedtilde"]=8765, - ["reviahebrew"]=1431, - ["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, - ["rsuperior"]=63217, - ["rtblock"]=9616, - ["rturned"]=633, - ["rturnedsuperior"]=692, - ["ruhiragana"]=12427, - ["rukatakana"]=12523, - ["rukatakanahalfwidth"]=65433, - ["rupeemarkbengali"]=2546, - ["rupeesignbengali"]=2547, - ["rupiah"]=63197, - ["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, - ["samekh"]=1505, - ["samekhdagesh"]=64321, - ["samekhdageshhebrew"]=64321, - ["samekhhebrew"]=1505, - ["saraaathai"]=3634, - ["saraaethai"]=3649, - ["saraaimaimalaithai"]=3652, - ["saraaimaimuanthai"]=3651, - ["saraamthai"]=3635, - ["saraathai"]=3632, - ["saraethai"]=3648, - ["saraiileftthai"]=63622, - ["saraiithai"]=3637, - ["saraileftthai"]=63621, - ["saraithai"]=3636, - ["saraothai"]=3650, - ["saraueeleftthai"]=63624, - ["saraueethai"]=3639, - ["saraueleftthai"]=63623, - ["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, - ["segol"]=1462, - ["segol13"]=1462, - ["segol1f"]=1462, - ["segol2c"]=1462, - ["segolhebrew"]=1462, - ["segolnarrowhebrew"]=1462, - ["segolquarterhebrew"]=1462, - ["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, - ["sevenarabic"]=1639, - ["sevenbengali"]=2541, - ["sevencircle"]=9318, - ["sevencircleinversesansserif"]=10128, - ["sevendeva"]=2413, - ["seveneighths"]=8542, - ["sevengujarati"]=2797, - ["sevengurmukhi"]=2669, - ["sevenhackarabic"]=1639, - ["sevenhangzhou"]=12327, - ["sevenideographicparen"]=12838, - ["seveninferior"]=8327, - ["sevenmonospace"]=65303, - ["sevenoldstyle"]=63287, - ["sevenparen"]=9338, - ["sevenperiod"]=9358, - ["sevenpersian"]=1783, - ["sevenroman"]=8566, - ["sevensuperior"]=8311, - ["seventeencircle"]=9328, - ["seventeenparen"]=9348, - ["seventeenperiod"]=9368, - ["seventhai"]=3671, - ["sfthyphen"]=173, - ["shaarmenian"]=1399, - ["shabengali"]=2486, - ["shacyrillic"]=1096, - ["shaddaarabic"]=1617, - ["shaddadammaarabic"]=64609, - ["shaddadammatanarabic"]=64606, - ["shaddafathaarabic"]=64608, - ["shaddafathatanarabic"]=1617, - ["shaddakasraarabic"]=64610, - ["shaddakasratanarabic"]=64607, - ["shade"]=9618, - ["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, - ["sheqel"]=8362, - ["sheqelhebrew"]=8362, - ["sheva"]=1456, - ["sheva115"]=1456, - ["sheva15"]=1456, - ["sheva22"]=1456, - ["sheva2e"]=1456, - ["shevahebrew"]=1456, - ["shevanarrowhebrew"]=1456, - ["shevaquarterhebrew"]=1456, - ["shevawidehebrew"]=1456, - ["shhacyrillic"]=1211, - ["shimacoptic"]=1005, - ["shin"]=1513, - ["shindagesh"]=64329, - ["shindageshhebrew"]=64329, - ["shindageshshindot"]=64300, - ["shindageshshindothebrew"]=64300, - ["shindageshsindot"]=64301, - ["shindageshsindothebrew"]=64301, - ["shindothebrew"]=1473, - ["shinhebrew"]=1513, - ["shinshindot"]=64298, - ["shinshindothebrew"]=64298, - ["shinsindot"]=64299, - ["shinsindothebrew"]=64299, - ["shook"]=642, - ["sigma"]=963, - ["sigma1"]=962, - ["sigmafinal"]=962, - ["sigmalunatesymbolgreek"]=1010, - ["sihiragana"]=12375, - ["sikatakana"]=12471, - ["sikatakanahalfwidth"]=65404, - ["siluqhebrew"]=1469, - ["siluqlefthebrew"]=1469, - ["similar"]=8764, - ["sindothebrew"]=1474, - ["siosacirclekorean"]=12916, - ["siosaparenkorean"]=12820, - ["sioscieuckorean"]=12670, - ["sioscirclekorean"]=12902, - ["sioskiyeokkorean"]=12666, - ["sioskorean"]=12613, - ["siosnieunkorean"]=12667, - ["siosparenkorean"]=12806, - ["siospieupkorean"]=12669, - ["siostikeutkorean"]=12668, - ["six"]=54, - ["sixarabic"]=1638, - ["sixbengali"]=2540, - ["sixcircle"]=9317, - ["sixcircleinversesansserif"]=10127, - ["sixdeva"]=2412, - ["sixgujarati"]=2796, - ["sixgurmukhi"]=2668, - ["sixhackarabic"]=1638, - ["sixhangzhou"]=12326, - ["sixideographicparen"]=12837, - ["sixinferior"]=8326, - ["sixmonospace"]=65302, - ["sixoldstyle"]=63286, - ["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, - ["smileface"]=9786, - ["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, - ["spacehackarabic"]=32, - ["spade"]=9824, - ["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, - ["ssuperior"]=63218, - ["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, - ["tav"]=1514, - ["tavdages"]=64330, - ["tavdagesh"]=64330, - ["tavdageshhebrew"]=64330, - ["tavhebrew"]=1514, - ["tbar"]=359, - ["tbopomofo"]=12554, - ["tcaron"]=357, - ["tccurl"]=680, - ["tcedilla"]=355, - ["tcheharabic"]=1670, - ["tchehfinalarabic"]=64379, - ["tchehinitialarabic"]=64380, - ["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, - ["tet"]=1496, - ["tetdagesh"]=64312, - ["tetdageshhebrew"]=64312, - ["tethebrew"]=1496, - ["tetsecyrillic"]=1205, - ["tevirhebrew"]=1435, - ["tevirlefthebrew"]=1435, - ["thabengali"]=2469, - ["thadeva"]=2341, - ["thagujarati"]=2725, - ["thagurmukhi"]=2597, - ["thalarabic"]=1584, - ["thalfinalarabic"]=65196, - ["thanthakhatlowleftthai"]=63640, - ["thanthakhatlowrightthai"]=63639, - ["thanthakhatthai"]=3660, - ["thanthakhatupperleftthai"]=63638, - ["theharabic"]=1579, - ["thehfinalarabic"]=65178, - ["thehinitialarabic"]=65179, - ["thehmedialarabic"]=65180, - ["thereexists"]=8707, - ["therefore"]=8756, - ["theta"]=952, - ["theta1"]=977, - ["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, - ["thousandsseparatorarabic"]=1644, - ["thousandsseparatorpersian"]=1644, - ["three"]=51, - ["threearabic"]=1635, - ["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, - ["threeoldstyle"]=63283, - ["threeparen"]=9334, - ["threeperiod"]=9354, - ["threepersian"]=1779, - ["threequarters"]=190, - ["threequartersemdash"]=63198, - ["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, - ["tildecmb"]=771, - ["tildecomb"]=771, - ["tildedoublecmb"]=864, - ["tildeoperator"]=8764, - ["tildeoverlaycmb"]=820, - ["tildeverticalcmb"]=830, - ["timescircle"]=8855, - ["tipehahebrew"]=1430, - ["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, - ["trademarksans"]=63722, - ["trademarkserif"]=63195, - ["tretroflexhook"]=648, - ["triagdn"]=9660, - ["triaglf"]=9668, - ["triagrt"]=9658, - ["triagup"]=9650, - ["ts"]=678, - ["tsadi"]=1510, - ["tsadidagesh"]=64326, - ["tsadidageshhebrew"]=64326, - ["tsadihebrew"]=1510, - ["tsecyrillic"]=1094, - ["tsere"]=1461, - ["tsere12"]=1461, - ["tsere1e"]=1461, - ["tsere2b"]=1461, - ["tserehebrew"]=1461, - ["tserenarrowhebrew"]=1461, - ["tserequarterhebrew"]=1461, - ["tserewidehebrew"]=1461, - ["tshecyrillic"]=1115, - ["tsuperior"]=63219, - ["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, - ["twentyhangzhou"]=21316, - ["twentyparen"]=9351, - ["twentyperiod"]=9371, - ["two"]=50, - ["twoarabic"]=1634, - ["twobengali"]=2536, - ["twocircle"]=9313, - ["twocircleinversesansserif"]=10123, - ["twodeva"]=2408, - ["twodotenleader"]=8229, - ["twodotleader"]=8229, - ["twodotleadervertical"]=65072, - ["twogujarati"]=2792, - ["twogurmukhi"]=2664, - ["twohackarabic"]=1634, - ["twohangzhou"]=12322, - ["twoideographicparen"]=12833, - ["twoinferior"]=8322, - ["twomonospace"]=65298, - ["twonumeratorbengali"]=2549, - ["twooldstyle"]=63282, - ["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, - ["udblacute"]=369, - ["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, - ["vav"]=1493, - ["vavdagesh"]=64309, - ["vavdagesh65"]=64309, - ["vavdageshhebrew"]=64309, - ["vavhebrew"]=1493, - ["vavholam"]=64331, - ["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, - ["yerahbenyomohebrew"]=1450, - ["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, - ["yod"]=1497, - ["yoddagesh"]=64313, - ["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, - ["zayin"]=1494, - ["zayindagesh"]=64310, - ["zayindageshhebrew"]=64310, - ["zayinhebrew"]=1494, - ["zbopomofo"]=12567, - ["zcaron"]=382, - ["zcircle"]=9449, - ["zcircumflex"]=7825, - ["zcurl"]=657, - ["zdot"]=380, - ["zdotaccent"]=380, - ["zdotbelow"]=7827, - ["zecyrillic"]=1079, - ["zedescendercyrillic"]=1177, - ["zedieresiscyrillic"]=1247, - ["zehiragana"]=12380, - ["zekatakana"]=12476, - ["zero"]=48, - ["zeroarabic"]=1632, - ["zerobengali"]=2534, - ["zerodeva"]=2406, - ["zerogujarati"]=2790, - ["zerogurmukhi"]=2662, - ["zerohackarabic"]=1632, - ["zeroinferior"]=8320, - ["zeromonospace"]=65296, - ["zerooldstyle"]=63280, - ["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, -} \ No newline at end of file diff --git a/tex/compat/luaotfload/luaotfload-init.lua b/tex/compat/luaotfload/luaotfload-init.lua deleted file mode 100644 index ad18b321c5e9c90151553176a186614b3743aa85..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/luaotfload-init.lua +++ /dev/null @@ -1,779 +0,0 @@ -#!/usr/bin/env texlua ------------------------------------------------------------------------ --- FILE: luaotfload-init.lua --- DESCRIPTION: Luaotfload font loader initialization --- REQUIREMENTS: luatex v.0.80 or later; packages lualibs --- AUTHOR: Philipp Gesang (Phg), <phg@phi-gamma.net> ------------------------------------------------------------------------ --- - -local setmetatable = setmetatable -local kpselookup = kpse.lookup -local lfsisdir = lfs.isdir - ---[[doc-- - - Initialization phases: - - - Load Lualibs from package - - Set up the logger routines - - Load Fontloader - - as package specified in configuration - - from Context install - - (optional: from raw unpackaged files distributed with - Luaotfload) - - The initialization of the Lualibs may be made configurable in the - future as well allowing to load both the files and the merged package - depending on a configuration setting. However, this would require - separating out the configuration parser into a self-contained - package, which might be problematic due to its current dependency on - the Lualibs itself. - ---doc]]-- - -local log --- filled in after loading the log module -local logreport --- filled in after loading the log module - ---[[doc-- - - \subsection{Preparing the Font Loader} - We treat the fontloader as a semi-black box so behavior is - consistent between formats. - We load the fontloader code directly in the same fashion as the - Plain format \identifier{luatex-fonts} that is part of Context. - How this is executed depends on the presence on the - \emphasis{merged font loader code}. - In \identifier{luaotfload} this is contained in the file - \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. - Since these files are not shipped with Luaotfload, an installation - of Context is required. - (Since we pull the fontloader directly from the Context minimals, - the necessary Context version is likely to be more recent than that - of other TeX distributions like Texlive.) - 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 if we make it call a dummy instead. - However, this problem might vanish if we decide to do the merging - ourselves, like the \identifier{lualibs} package does. - With this step we would obtain the freedom to load our own - overrides in the process right where they are needed, at the cost - of losing encapsulation. - The decision on how to progress is currently on indefinite hold. - ---doc]]-- - -local glyph_codes = - { [0] = "character" - , [1] = "glyph" - , [2] = "ligature" - , [3] = "ghost" - , [4] = "left" - , [5] = "right" - } - -local disc_codes = - { [0] = "discretionary" - , [1] = "explicit" - , [2] = "automatic" - , [3] = "regular" - , [4] = "first" - , [5] = "second" - } - -local node_types = { disc = disc_codes, glyph = glyph_codes } - -local luatex_stubs = function () - if not node.subtypes then - node.subtypes = function (t) return node_types [t] or { } end - local direct = node.direct - - local getfield = direct.getfield - local setfield = direct.setfield - - direct.setchar = direct.setchar or function (n, ...) setfield (n, "char", ...) end - direct.setprev = direct.setprev or function (n, ...) setfield (n, "prev", ...) end - direct.setnext = direct.setnext or function (n, ...) setfield (n, "next", ...) end - - direct.getchar = direct.getchar or function (n) getfield (n, "char") end - direct.getprev = direct.getprev or function (n) getfield (n, "prev") end - direct.getnext = direct.getnext or function (n) getfield (n, "next") end - end -end - -local init_early = function () - - local store = { } - config = config or { } --- global - config.luaotfload = config.luaotfload or { } - config.lualibs = config.lualibs or { } - config.lualibs.verbose = false - config.lualibs.prefer_merged = true - config.lualibs.load_extended = true - fonts = fonts or { } - - require "lualibs" - - if not lualibs then error "this module requires Luaotfload" end - if not luaotfload then error "this module requires Luaotfload" end - - luatex_stubs () - - --[[doc-- - - The logger needs to be in place prior to loading the fontloader due - to order of initialization being crucial for the logger functions - that are swapped. - - --doc]]-- - - luaotfload.loaders.luaotfload "log" - log = luaotfload.log - logreport = log.report - log.set_loglevel (default_log_level) - - logreport ("log", 4, "init", "Concealing callback.register().") - store.trapped_register = callback.register - - callback.register = function (id) - logreport ("log", 4, "init", - "Dummy callback.register() invoked on %s.", - id) - end - - --[[doc-- - - By default, the fontloader requires a number of \emphasis{private - attributes} for internal use. - These must be kept consistent with the attribute handling methods - as provided by \identifier{luatexbase}. - Our strategy is to override the function that allocates new - attributes before we initialize the font loader, making it a - wrapper around \luafunction{luatexbase.new_attribute}.\footnote{% - Many thanks, again, to Hans Hagen for making this part - configurable! - } - The attribute identifiers are prefixed “\fileent{luaotfload@}” to - avoid name clashes. - - --doc]]-- - - local new_attribute = luatexbase.new_attribute - local the_attributes = luatexbase.attributes - - attributes = attributes or { } --- this writes a global, sorry - - attributes.private = function (name) - local attr = "luaotfload@" .. name --- used to be: “otfl@” - local number = the_attributes[attr] - if not number then number = new_attribute(attr) end - return number - end - - luaotfload.loaders.fontloader "basics-gen" - - return store -end --- [init_early] - ---[[doc-- - - These next lines replicate the behavior of - \fileent{luatex-fonts.lua}. - ---doc]]-- - -local push_namespaces = function () - logreport ("log", 4, "init", "push namespace for font loader") - local normalglobal = { } - for k, v in next, _G do - normalglobal[k] = v - end - return normalglobal -end - -local pop_namespaces = function (normalglobal, - isolate, - context_environment) - if normalglobal then - local _G = _G - local mode = "non-destructive" - if isolate then mode = "destructive" end - logreport ("log", 4, "init", "pop namespace from font loader -- " .. mode) - for k, v in next, _G do - if not normalglobal[k] then - context_environment[k] = v - if isolate then - _G[k] = nil - end - end - end - for k, v in next, normalglobal do - _G[k] = v - end - -- just to be sure: - setmetatable(context_environment, _G) - else - logreport ("both", 0, "init", - "irrecoverable error during pop_namespace: no globals to restore") - os.exit () - end -end - ---- below paths are relative to the texmf-context -local ltx = "tex/generic/context/luatex" -local ctx = { "tex/context/base/mkiv", "tex/context/base" } - -local context_modules = { - - --- Since 2.6 those are directly provided by the Lualibs package. - { false, "l-lua" }, - { false, "l-lpeg" }, - { false, "l-function" }, - { false, "l-string" }, - { false, "l-table" }, - { false, "l-io" }, - { false, "l-file" }, - { false, "l-boolean" }, - { false, "l-math" }, - { false, "util-str" }, - { false, "util-fil" }, - - --- These constitute the fontloader proper. - { ltx, "luatex-basics-gen" }, - { ctx, "data-con" }, - { ltx, "luatex-basics-nod" }, - { ctx, "font-ini" }, - { ctx, "font-con" }, - { ltx, "luatex-fonts-enc" }, - { ctx, "font-cid" }, - { ctx, "font-map" }, - { ltx, "luatex-fonts-syn" }, - { ctx, "font-oti" }, - { ctx, "font-otr" }, - { ctx, "font-cff" }, - { ctx, "font-ttf" }, - { ctx, "font-dsp" }, - { ctx, "font-oup" }, - { ctx, "font-otl" }, - { ctx, "font-oto" }, - { ctx, "font-otj" }, - { ctx, "font-ota" }, - { ctx, "font-ots" }, - { ctx, "font-osd" }, - { ctx, "font-ocl" }, - { ctx, "font-otc" }, - { ctx, "font-onr" }, - { ctx, "font-one" }, - { ctx, "font-afk" }, - { ctx, "font-tfm" }, - { ctx, "font-lua" }, - { ctx, "font-def" }, - { ltx, "luatex-fonts-ext" }, - { ctx, "font-gbn" }, - -} --[[context_modules]] - -local load_context_modules = function (pth) - - local load_module = luaotfload.loaders.context - local ignore_module = luaotfload.loaders.ignore - - logreport ("both", 2, "init", - "Loading fontloader components from context.") - local n = #context_modules - for i = 1, n do - local sub, spec = unpack (context_modules [i]) - if sub == false then - ignore_module (spec) - else - local tsub = type (sub) - if not pth then - load_module (spec) - elseif tsub == "string" then - load_module (spec, file.join (pth, sub)) - elseif tsub == "table" then - local pfx - local nsub = #sub - for j = 1, nsub do - local full = file.join (pth, sub [j]) - if lfsisdir (full) then --- pick the first real one - pfx = full - break - end - end - if pfx then - load_module (spec, pfx) - else - logreport ("both", 0, "init", - "None of the %d search paths for module %q exist; \z - falling back to default path.", - nsub, tostring (spec)) - load_module (spec) --- maybe we’ll get by after all? - end - else - logreport ("both", 0, "init", - "Internal error, please report. \z - This is not your fault.") - os.exit (-1) - end - end - end - -end - -local init_adapt = function () - - local context_environment = { } - local our_environment = push_namespaces () - - --[[doc-- - - The font loader requires that the attribute with index zero be - zero. We happily oblige. - (Cf. \fileent{luatex-fonts-nod.lua}.) - - --doc]]-- - - tex.attribute[0] = 0 - - return our_environment, context_environment - -end --- [init_adapt] - ---[[doc-- - - In Context, characters.data is where the data from char-def.lua - resides. The file is huge (>4.4 MB as of 2016) and only a stripped - down version is part of the isolated font loader. Nevertheless, we - include an excerpt generated by the mkcharacters script that contains - a subset of the fields of each character defined and some extra - metadata. - - Currently, these are (compare the mkcharacters script!) - - · "direction" - · "mirror" - · "category" - · "textclass" - - The directional information is required for packages like Simurgh [0] - to work correctly. In an early stage [1] it was necessary to load - further files from Context directly, including the full blown version - of char-def. Since we have no use for most of the so imported - functionality, the required parts have been isolated and are now - instated along with luaotfload-characters.lua. We can extend the set - of imported features easily should it not be enough. - - [0] https://github.com/persian-tex/simurgh - [1] http://tex.stackexchange.com/a/132301/14066 - ---doc]]-- - -characters = characters or { } --- should be created in basics-gen -characters.data = nil -local chardef = "luaotfload-characters" - -do - local setmetatableindex = function (t, f) - local mt = getmetatable (t) - if mt then - mt.__index = f - else - setmetatable (t, { __index = f }) - end - end - - --- there are some special tables for each field that provide access - --- to fields of the character table by means of a metatable - - local mkcharspecial = function (characters, tablename, field) - - local chardata = characters.data - - if chardata then - local newspecial = { } - characters [tablename] = newspecial --> e.g. “characters.data.mirrors” - - local idx = function (t, char) - local c = chardata [char] - if c then - local m = c [field] --> e.g. “mirror” - if m then - t [char] = m - return m - end - end - newspecial [char] = false - return char - end - - setmetatableindex (newspecial, idx) - end - - end - - local mkcategories = function (characters) -- different from the others - - local chardata = characters.data - local categories = characters.categories or { } - characters.categories = categories - - setmetatable (categories, { __index = function (t, char) - if char then - local c = chardata [char] - c = c.category or char - t [char] = c - return c - end - end}) - - end - - local load_failed = false - local chardata --> characters.data; loaded on demand - - local load_chardef = function () - - logreport ("both", 1, "aux", "Loading character metadata from %s.", chardef) - chardata = dofile (kpse.find_file (chardef, "lua")) - - if chardata == nil then - logreport ("both", 0, "aux", - "Could not load %s; continuing with empty character table.", - chardef) - chardata = { } - load_failed = true - end - - characters = { } --- nuke metatable - characters.data = chardata - characters.classifiers = chardata.classifiers - chardata.classifiers = nil - - --- institute some of the functionality from char-ini.lua - - mkcharspecial (characters, "mirrors", "mirror") - mkcharspecial (characters, "directions", "direction") - mkcharspecial (characters, "textclasses", "textclass") - mkcategories (characters) - - end - - local charindex = function (t, k) - if chardata == nil and load_failed ~= true then - load_chardef () - end - - return rawget (characters, k) - end - - setmetatableindex (characters, charindex) - -end - -local init_main = function () - - local load_fontloader_module = luaotfload.loaders.fontloader - local ignore_module = luaotfload.loaders.ignore - - --[[doc-- - - Now that things are sorted out we can finally load the - fontloader. - - --doc]]-- - - local fontloader = config.luaotfload and config.luaotfload.run.fontloader - or "reference" - fontloader = tostring (fontloader) - - if fontloader == "reference" then - logreport ("log", 0, "init", "Using reference fontloader.") - load_fontloader_module (luaotfload.fontloader_package) - - elseif fontloader == "default" then - --- Same as above but loader name not correctly replaced by the file name - --- of our fontloader package. Perhaps something’s wrong with the status - --- file which contains the datestamped filename? In any case, it can’t - --- hurt reporting it as a bug. - logreport ("both", 0, "init", "Fontloader substitution failed, got “default”.") - logreport ("log", 4, "init", "Falling back to reference fontloader.") - load_fontloader_module (luaotfload.fontloader_package) - - elseif fontloader == "unpackaged" then - logreport ("log", 0, "init", - "Loading fontloader components individually.") - --- The loading sequence is known to change, so this might have to be - --- updated with future updates. Do not modify it though unless there is - --- a change to the upstream package! - - --- Since 2.6 those are directly provided by the Lualibs package. - ignore_module "l-lua" - ignore_module "l-lpeg" - ignore_module "l-function" - ignore_module "l-string" - ignore_module "l-table" - ignore_module "l-io" - ignore_module "l-file" - ignore_module "l-boolean" - ignore_module "l-math" - ignore_module "util-str" - ignore_module "util-fil" - ignore_module "luatex-basics-gen" - - load_fontloader_module "data-con" - load_fontloader_module "basics-nod" - load_fontloader_module "font-ini" - load_fontloader_module "font-con" - load_fontloader_module "fonts-enc" - load_fontloader_module "font-cid" - load_fontloader_module "font-map" - load_fontloader_module "fonts-syn" - load_fontloader_module "font-oti" - load_fontloader_module "font-otr" - load_fontloader_module "font-cff" - load_fontloader_module "font-ttf" - load_fontloader_module "font-dsp" - load_fontloader_module "font-oup" - load_fontloader_module "font-otl" - load_fontloader_module "font-oto" - load_fontloader_module "font-otj" - load_fontloader_module "font-ota" - load_fontloader_module "font-ots" - load_fontloader_module "font-osd" - load_fontloader_module "font-ocl" - load_fontloader_module "font-onr" - load_fontloader_module "font-one" - load_fontloader_module "font-afk" - load_fontloader_module "font-tfm" - load_fontloader_module "font-lua" - load_fontloader_module "font-def" - load_fontloader_module "fonts-ext" - load_fontloader_module "font-gbn" - - elseif fontloader == "context" then - logreport ("log", 0, "init", - "Loading Context modules in lookup path.") - load_context_modules () - - elseif lfsisdir (fontloader) then - logreport ("log", 0, "init", - "Loading Context files under prefix “%s”.", - fontloader) - load_context_modules (fontloader) - - elseif lfs.isfile (fontloader) then - logreport ("log", 0, "init", - "Loading fontloader from absolute path “%s”.", - fontloader) - local _void = require (fontloader) - - elseif kpselookup (fontloader) then - local path = kpselookup (fontloader) - logreport ("log", 0, "init", - "Loading fontloader “%s” from kpse-resolved path “%s”.", - fontloader, path) - local _void = require (path) - - elseif fontloader then - logreport ("log", 0, "init", - "Using predefined fontloader “%s”.", - fontloader) - load_fontloader_module (fontloader) - - else - logreport ("log", 0, "init", - "No match for requested fontloader “%s”.", - fontloader) - fontloader = luaotfload.fontloader_package - logreport ("log", 0, "init", - "Defaulting to predefined fontloader “%s”.", - fontloader) - load_fontloader_module (fontloader) - end - - ---load_fontloader_module "font-odv.lua" --- <= Devanagari support from Context - - logreport ("log", 0, "init", - "Context OpenType loader version “%s”", - fonts.handlers.otf.version) -end --- [init_main] - -local init_cleanup = function (store) - --- reinstate all the stuff we had to move out of the way to - --- accomodate the loader - - --[[doc-- - - Here we adjust the globals created during font loader - initialization. If the second argument to - \luafunction{pop_namespaces()} is \verb|true| this will restore the - state of \luafunction{_G}, eliminating every global generated since - the last call to \luafunction{push_namespaces()}. At the moment we - see no reason to do this, and since the font loader is considered - an essential part of \identifier{luatex} as well as a very well - organized piece of code, we happily concede it the right to add to - \luafunction{_G} if needed. - - --doc]]-- - - pop_namespaces (store.our_environment, - false, - store.context_environment) - - --[[doc-- - - \subsection{Callbacks} - After the fontloader is ready we can restore the callback trap - from \identifier{luatexbase}. - - --doc]]-- - - logreport ("log", 4, "init", - "Restoring original callback.register().") - callback.register = store.trapped_register -end --- [init_cleanup] - -local init_post_install_callbacks = function () - --[[doc-- - - we do our own callback handling with the means provided by - luatexbase. - note: \luafunction{pre_linebreak_filter} and - \luafunction{hpack_filter} are coupled in \context in the - concept of \emphasis{node processor}. - - --doc]]-- - - luatexbase.add_to_callback("pre_linebreak_filter", - nodes.simple_font_handler, - "luaotfload.node_processor", - 1) - luatexbase.add_to_callback("hpack_filter", - nodes.simple_font_handler, - "luaotfload.node_processor", - 1) -end - -local init_post_load_agl = function () - - --[[doc-- - - Adobe Glyph List. - ----------------------------------------------------------------- - - Context provides a somewhat different font-age.lua from an - unclear origin. Unfortunately, the file name it reads from is - hard-coded in font-enc.lua, so we have to replace the entire - table. - - This shouldn’t cause any complications. Due to its implementation - the glyph list will be loaded upon loading a OTF or TTF for the - first time during a TeX run. (If one sticks to TFM/OFM then it is - never read at all.) For this reason we can install a metatable - that looks up the file of our choosing and only falls back to the - Context one in case it cannot be found. - - --doc]]-- - - local findfile = resolvers.findfile - local encodings = fonts.encodings - - if not findfile or not encodings then - --- Might happen during refactoring; we continue graciously but in - --- a somewhat defect state. - logreport ("log", 0, "init", - "preconditions unmet, skipping the Adobe Glyph List; " - .. "this is a Luaotfload bug.") - return - end - - if next (fonts.encodings.agl) then - --- unnecessary because the file shouldn’t be loaded at this time - --- but we’re just making sure - fonts.encodings.agl = nil - collectgarbage"collect" - end - - local agl_init = { } --- start out empty, fill on demand - encodings.agl = agl_init --- ugh, replaced again later - - setmetatable (agl_init, { __index = function (t, k) - - if k ~= "unicodes" then - return nil - end - - local glyphlist = findfile "luaotfload-glyphlist.lua" - if glyphlist then - logreport ("log", 1, "init", "loading the Adobe glyph list") - else - glyphlist = findfile "font-age.lua" - logreport ("both", 0, "init", - "loading the extended glyph list from ConTeXt") - end - - if not glyphlist then - logreport ("both", 4, "init", - "Adobe glyph list not found, please check your installation.") - return nil - end - logreport ("both", 4, "init", - "found Adobe glyph list file at ``%s``, using that.", - glyphlist) - - local unicodes = dofile(glyphlist) - encodings.agl = { unicodes = unicodes } - return unicodes - end }) - -end - ---- (unit -> unit) list -local init_post_actions = { - init_post_install_callbacks, - init_post_load_agl, -} - ---- unit -> size_t -local init_post = function () - --- hook for actions that need to take place after the fontloader is - --- installed - - local n = #init_post_actions - for i = 1, n do - local action = init_post_actions[i] - local taction = type (action) - if not action or taction ~= "function" then - logreport ("both", 1, "init", - "post hook WARNING: action %d not a function but %s/%s; ignoring.", - i, action, taction) - else - --- call closure - action () - end - end - - return n -end --- [init_post] - -return { - early = init_early, - main = function (store) - local starttime = os.gettimeofday () - store.our_environment, store.context_environment = init_adapt () - init_main () - init_cleanup (store) - logreport ("both", 1, "init", - "fontloader loaded in %0.3f seconds", - os.gettimeofday() - starttime) - local n = init_post () - logreport ("both", 5, "init", "post hook terminated, %d actions performed", n) - return true - end -} - --- vim:tw=79:sw=2:ts=2:expandtab diff --git a/tex/compat/luaotfload/luaotfload-latex.tex b/tex/compat/luaotfload/luaotfload-latex.tex deleted file mode 100644 index b4cd3c343427ff91ee6868c5e9c08b470ee08ac8..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/luaotfload-latex.tex +++ /dev/null @@ -1,486 +0,0 @@ -\suppresslongerror1%% sigh ... -%% Copyright (C) 2009-2015 -%% -%% by Elie Roux <elie.roux@telecom-bretagne.eu> -%% and Khaled Hosny <khaledhosny@eglug.org> -%% and Philipp Gesang <phg@phi-gamma.net> -%% -%% This file is part of Luaotfload. -%% -%% Home: https://github.com/lualatex/luaotfload -%% Support: <lualatex-dev@tug.org>. -%% -%% Luaotfload is under the GPL v2.0 (exactly) license. -%% -%% ---------------------------------------------------------------------------- -%% -%% Luaotfload is free software; you can redistribute it and/or -%% modify it under the terms of the GNU General Public License -%% as published by the Free Software Foundation; version 2 -%% of the License. -%% -%% Luaotfload is distributed in the hope that it will be useful, -%% but WITHOUT ANY WARRANTY; without even the implied warranty of -%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -%% GNU General Public License for more details. -%% -%% You should have received a copy of the GNU General Public License -%% along with Luaotfload; if not, see <http://www.gnu.org/licenses/>. -%% -%% ---------------------------------------------------------------------------- -%% - -\documentclass{ltxdoc} - -\makeatletter - -\usepackage {metalogo,multicol,fancyvrb,xspace} -\usepackage [x11names] {xcolor} - -\def \primarycolor {DodgerBlue4} %%-> rgb 16 78 139 | #104e8b -\def \secondarycolor {Goldenrod4} %%-> rgb 139 105 200 | #8b6914 - -\usepackage[ - bookmarks=true, - colorlinks=true, - linkcolor=\primarycolor, - urlcolor=\secondarycolor, - citecolor=\primarycolor, - pdftitle={The Luaotfload package}, - pdfsubject={OpenType layout system for Plain TeX and LaTeX}, - pdfauthor={Elie Roux & Khaled Hosny & Philipp Gesang}, - pdfkeywords={luatex, lualatex, unicode, opentype} -]{hyperref} - -\usepackage {fontspec} -\usepackage {unicode-math} - -\setmainfont[ -% Numbers = OldStyle, %% buggy with font cache - Ligatures = TeX, - BoldFont = {Linux Libertine O Bold}, - ItalicFont = {Linux Libertine O Italic}, - SlantedFont = {Linux Libertine O Italic}, -]{Linux Libertine O} -\setmonofont[Ligatures=TeX,Scale=MatchLowercase]{Liberation Mono} -%setsansfont[Ligatures=TeX]{Linux Biolinum O} -\setsansfont[Ligatures=TeX,Scale=MatchLowercase]{Iwona Medium} -%setmathfont{XITS Math} - -\usepackage{hologo} - -\newcommand\TEX {\TeX\xspace} -\newcommand\LUA {Lua\xspace} -\newcommand\PDFTEX {pdf\TeX\xspace} -\newcommand\LUATEX {Lua\TeX\xspace} -\newcommand\XETEX {\XeTeX\xspace} -\newcommand\LATEX {\LaTeX\xspace} -\newcommand\LUALATEX {Lua\LaTeX\xspace} -\newcommand\CONTEXT {Con\TeX t\xspace} -\newcommand\OpenType {\identifier{Open\kern-.25ex Type}\xspace} - -%% \groupedcommand, with some omissions taken from syst-aux.mkiv -\let \handlegroupnormalbefore \relax -\let \handlegroupnormalafter \relax - -\protected \def \handlegroupnormal #1#2{% - \bgroup % 1 - \def \handlegroupbefore {#1}% - \def \handlegroupafter {#2}% - \afterassignment \handlegroupnormalbefore - \let \next = -} - -\def \handlegroupnormalbefore {% - \bgroup % 2 - \handlegroupbefore - \bgroup % 3 - \aftergroup \handlegroupnormalafter% -} - -\def \handlegroupnormalafter {% - \handlegroupafter - \egroup % 3 - \egroup % 2 -} - -\let \groupedcommand \handlegroupnormal %% only the two arg version - -\def \definehighlight [#1][#2]{% - \ifcsname #1\endcsname\else - \expandafter\def\csname #1\endcsname{% - \leavevmode - \groupedcommand {#2}\empty% - } - \fi% -} - -%% old, simplistic definition: obsolete now that we have -%% \groupedcommand -%\def\definehighlight[#1][#2]% - %{\ifcsname #1\endcsname\else - %\expandafter\def\csname #1\endcsname% - %{\bgroup#2\csname #1_indeed\endcsname} - %\expandafter\def\csname #1_indeed\endcsname##1% - %{##1\egroup}% - %\fi} - -\def\restoreunderscore{\catcode`\_=12\relax} - -\definehighlight [fileent][\ttfamily\restoreunderscore] %% files, dirs -\definehighlight [texmacro][\sffamily\itshape\textbackslash] %% cs -\definehighlight [luaident][\sffamily\itshape\restoreunderscore] %% lua identifiers -\definehighlight [identifier][\sffamily] %% names -\definehighlight [abbrev][\rmfamily\scshape] %% acronyms -\definehighlight [emphasis][\rmfamily\slshape] %% level 1 emph - -\definehighlight [Largefont][\Large] %% font size -\definehighlight [smallcaps][\sc] %% font feature -\definehighlight [nonproportional][\tt] %% font switch - -\newcommand*\email[1]{\href{mailto:#1}{#1}} - -\renewcommand\partname{Part}%% gets rid of the stupid “file” heading - -\usepackage{syntax}%% bnf for font request syntax - -\usepackage{titlesec} - -\def\movecountertomargin#1{\llap{\rmfamily\upshape#1\hskip2em}} -\def\zeropoint{0pt} -\titleformat \part - {\normalsize\rmfamily\bfseries} - {\movecountertomargin\thepart} \zeropoint {} -\titleformat \section - {\normalsize\rmfamily\scshape} - {\movecountertomargin\thesection} \zeropoint {} -\titleformat \subsection - {\small\rmfamily\itshape} - {\movecountertomargin\thesubsection} \zeropoint {} -\titleformat \subsubsection - {\normalsize\rmfamily\upshape} - {\movecountertomargin\thesubsubsection} \zeropoint {} - -\usepackage{tocloft} -\renewcommand \cftpartfont {\rmfamily\upshape} -\renewcommand \cftsecfont {\rmfamily\upshape} -\renewcommand \cftsubsecfont {\rmfamily\upshape} -\setlength \cftbeforepartskip {1ex} -\setlength \cftbeforesecskip {1ex} - -\VerbatimFootnotes - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% structurals -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\def \definestructural #1{% - \expandafter \let \csname end#1\endcsname \relax - - \expandafter \def \csname begin#1\endcsname {% - \@ifnextchar[{\csname begin#1indeed\endcsname} - {\csname begin#1indeed\endcsname[]}% - } - - \expandafter \def \csname begin#1indeed\endcsname [##1]##2{% - \edef \first {##1}% - \ifx \first \empty - \csname #1\endcsname [##2]{##2}% - \else - \csname #1\endcsname [\first]{##2}% - \fi - } -} - -\definestructural {section} -\definestructural {subsection} -\definestructural {subsubsection} - -\def \fakesection #1{\section*{#1}} - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% inline verbatim -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -%% Context offers both \type{…} and \type<<…>>, but not an unbalanced -%% one that we could map directly onto Latex’s \verb|…|. - -\usepackage {listings} -\usepackage {luatexbase} -\lstset { - basicstyle=\ttfamily, -} - -%\let \inlinecode \lstinline -\protected \def \inlinecode {\lstinline} - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% codelistings; this sucks hard since we lack access to buffers -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\newcount \othercatcode \othercatcode 12 -\newcount \activecatcode \othercatcode 13 - -\newcatcodetable \vrbcatcodes -\setcatcodetable \vrbcatcodes {% - \catcodetable \CatcodeTableIniTeX - \catcode 9 \othercatcode %% \tabasciicode - \catcode 13 \othercatcode %% \endoflineasciicode - \catcode 12 \othercatcode %% \formfeedasciicode - \catcode 26 \othercatcode %% \endoffileasciicode - \catcode 32 \othercatcode %% \spaceasciicode -} - -\directlua { - document = document or { } - document.vrbcatcodesidx = tonumber (\the \vrbcatcodes) -} - -\newcatcodetable \literalcatcodes -\setcatcodetable \literalcatcodes {% - \catcodetable \CatcodeTableString - \catcode 32 \activecatcode %% \spaceasciicode -} - -\def \listingsurroundskip {\vskip \baselineskip} - -\def \beginlisting {% - \noindent - \begingroup - \catcodetable \vrbcatcodes - \beginlistingindeed% -} - -\directlua { - local texsprint = tex.sprint - local stringis_empty = string.is_empty - local stringsub = string.sub - local stringgsub = string.gsub - %local backslash = unicode.utf8.char (0x200c) - local backslash = unicode.utf8.char (0x5c) - local escaped = [[\string\string\string\]] - document.printlines = function (buffer) - local lines = string.explode (buffer, "\noexpand\n") - print "" - for i, line in next, lines do - local line = stringgsub (line, backslash, escaped) - if stringis_empty (line) then - print (i, "listing: <empty line />") - texsprint [[\string\listingpar]] - else - local line = [[\string\beginlistingline]] - .. line - .. [[\string\endlistingline]] - .. [[\string\listingpar]] - print (i, "listing: «" .. line .. "»") - texsprint (document.vrbcatcodesidx, line) - end - end - end -} - -\def \listingpar {\endgraf} - -\let \endlistingline \relax -\let \endlisting \relax - -\protected \def \beginlistingline{% - \leavevmode - \begingroup - \beginlistinglineindeed% -} - -\def \beginlistinglineindeed #1\endlistingline{% - \endgroup - \hbox{% - \addfontfeature {RawFeature=-tlig;-liga}%% So one can’t just turn them all off at once using the ``Ligatures`` key? - \obeyspaces - #1}% -} - -\def \beginlistingindeed#1\endlisting{% - \endgroup - \begingroup - \endgraf - \listingsurroundskip - \ttfamily - \small - \parindent = 0em - \leftskip = 2em - \hangindent = 2em - \directlua{document.printlines ([==[\detokenize {#1}]==])}% - \listingsurroundskip - \endgroup -} - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% enumerations and lists -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\def \definelist [#1]#2{% name, itemcode - \expandafter \def \csname begin#1\endcsname {% - \begin {itemize} - \let \normalitem = \item - \def \altitem ####1{% - \def \first {####1}% - #2 - } - \let \beginnormalitem \item - \let \endnormalitem \relax - \let \beginaltitem \altitem - \let \endaltitem \relax - } - - \expandafter \def \csname end#1\endcsname {% - \end {itemize} - } -} - -\definelist [descriptions]{\normalitem {\textbf \first}\hfill\break} -\definelist [definitions]{\normalitem {\fileent {\first}}} -\definelist [filelist]{\normalitem {\fileent {\first}}\space--\hskip 1em} -\definelist [functionlist]{\normalitem {\luaident {\first}}\hfill\break} - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% columns -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\def \begindoublecolumns {\begin {multicols} {2}} -\def \enddoublecolumns {\end {multicols}} - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% alignment -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\def \begincentered {\begin {center}} -\def \endcentered {\end {center}} - -\def \beginnarrower {\begin {quote}} -\def \endnarrower {\end {quote}} - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% special elements -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\let \beginfrontmatter \relax -\let \endfrontmatter \relax - -\def \beginabstractcontent {\begin {abstract}} -\def \endabstractcontent {\end {abstract}} - -\let \setdocumenttitle \title -\let \setdocumentdate \date -\let \setdocumentauthor \author -\let \typesetdocumenttitle \maketitle - -\AtBeginDocument {%% seriously? - \let \typesetcontent \tableofcontents% -} - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% floats -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -%% syntax definition -\def \beginsyntaxfloat #1#2{%% #1:label #2:caption - \begin {figure} [b] - \edef \syntaxlabel {#1}% - \def \syntaxcaption {#2}% - \setlength\grammarparsep{12pt plus 2pt minus 2pt}% - \setlength\grammarindent{5cm}% - \begingroup - \small - \begin {grammar} -} - -\def \endsyntaxfloat {% - \end {grammar} - \endgroup - \caption \syntaxcaption - \label \syntaxlabel - \end {figure} -} - -%% figures, e.g. the file graph -\def \figurefloat #1#2#3{%% #1:label #2:caption #3:file - \begin {figure} [b] - \caption {#2}% - \includegraphics[width=\textwidth]{#3}% - \label {#1} - \end {figure} -} - -%% tables -\def \tablefloat #1#2{%% #1:label #2:caption - \begin {table} [t] - \hrule - \caption {#2}% - \label {#1} - \hrule - \end {table} -} - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% hyperlinks -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\protected \def \hyperlink{% - \@ifnextchar[{\hyperlinkindeed}% - {\hyperlinkindeed[]}% -} - -\def \hyperlinkindeed [#1]#2{% - \def \first {#1}% - \ifx \first \empty - \url {#2}% - \else - \href {#2}{#1}% - \fi% -} - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% tables -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% Our tables aren’t anything special so we stick with “tabular” on the -%% Latex end. -%% -%% This is going to be largely incompatible with Context since format -%% specifications work quite differently (even between different -%% Context table variants). - -\def \begintabulate [#1]#2\endtabulate{% - \begingroup - \let \beginrow = \relax %% -> \NC in Context - \let \newcell = & %% -> \NC - \let \endrow = \cr %% -> \NC \NR - \begin {tabular}{#1}% - #2 - \end {tabular} - \endgroup -} - -\let \endtabulate \relax - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% escaped characters -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\let \charpercent \textpercent -\let \charbackslash \textbackslash -\let \chartilde \textasciitilde - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% main -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\makeatother - -\newif \ifcontextmkiv \contextmkivfalse - -\begin {document} - \input {luaotfload-main.tex} -\end {document} - - diff --git a/tex/compat/luaotfload/luaotfload-letterspace.lua b/tex/compat/luaotfload/luaotfload-letterspace.lua deleted file mode 100644 index fd64c90a4b8aeab897743d4551a54b010fef11e3..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/luaotfload-letterspace.lua +++ /dev/null @@ -1,672 +0,0 @@ -if not modules then modules = { } end modules ['letterspace'] = { - version = "2.8", - comment = "companion to luaotfload-main.lua", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL; adapted by Philipp Gesang", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - ---- This code diverged quite a bit from its origin in Context. Please ---- do *not* report bugs on the Context list. - -local log = luaotfload.log -local logreport = log.report - -local getmetatable = getmetatable -local require = require -local setmetatable = setmetatable -local tonumber = tonumber - -local next = next -local nodes, node, fonts = nodes, node, fonts - -local nodedirect = nodes.nuts - -local getfield = nodedirect.getfield -local setfield = nodedirect.setfield - -local field_setter = function (name) return function (n, ...) setfield (n, name, ...) end end -local field_getter = function (name) return function (n, ...) getfield (n, name, ...) end end - -local getfont = nodedirect.getfont -local getid = nodedirect.getid - -local getnext = nodedirect.getnext or field_getter "next" -local setnext = nodedirect.setnext or field_setter "next" - -local getprev = nodedirect.getprev or field_getter "prev" -local setprev = nodedirect.setprev or field_setter "prev" - ---- since r5336 -local getboth = nodedirect.getboth or function (n) - return getprev (n), getnext (n) -end - -local setlink = nodedirect.setlink or function (a, b) - setnext (a, b) - setprev (b, a) -end - -local getdisc = nodedirect.getdisc or field_getter "disc" -local setdisc = nodedirect.setdisc or field_setter "disc" - -local getsubtype = nodedirect.getsubtype or field_getter "subtype" -local setsubtype = nodedirect.setsubtype or field_setter "subtype" - -local getchar = nodedirect.getchar or field_getter "subtype" -local setchar = nodedirect.setchar or field_setter "subtype" - -local find_node_tail = nodedirect.tail -local todirect = nodedirect.tonut -local tonode = nodedirect.tonode - -local insert_node_before = nodedirect.insert_before -local free_node = nodedirect.free -- may cause double free -local free_node = function (n) - logreport ("term", 5, "letterspace", "not calling free_node(%d)", n) - -- free_node (n) -end -local copy_node = nodedirect.copy -local new_node = nodedirect.new - -local nodepool = nodedirect.pool -local new_kern = nodepool.kern - -local nodecodes = nodes.nodecodes - -local glyph_code = nodecodes.glyph -local kern_code = nodecodes.kern -local disc_code = nodecodes.disc -local math_code = nodecodes.math -local glue_code = nodecodes.glue - -local fonthashes = fonts.hashes -local chardata = fonthashes.characters -local quaddata = fonthashes.quads -local otffeatures = fonts.constructors.newfeatures "otf" - ---[[doc-- - - Since the letterspacing method was derived initially from Context’s - typo-krn.lua we keep the sub-namespace “letterspace” inside the - “luaotfload” table. - ---doc]]-- - -luaotfload.letterspace = luaotfload.letterspace or { } -local letterspace = luaotfload.letterspace - -letterspace.keepligature = false -letterspace.keeptogether = false - ----=================================================================--- ---- preliminary definitions ----=================================================================--- --- We set up a layer emulating some Context internals that are needed --- for the letterspacing callback. ------------------------------------------------------------------------ ---- node-ini ------------------------------------------------------------------------ - -local bothways = function (t) return table.swapped (t, t) end -local kerncodes = bothways { [0] = "fontkern" - , [1] = "userkern" - , [2] = "accentkern" - } -local skipcodes = bothways { [0] = "userskip" - , [13] = "spaceskip" - , [14] = "xspaceskip" - } - -kerncodes.kerning = kerncodes.fontkern --- idiosyncrasy -local kerning_code = kerncodes.kerning -local userkern_code = kerncodes.userkern -local userskip_code = skipcodes.userskip -local spaceskip_code = skipcodes.spaceskip -local xspaceskip_code = skipcodes.xspaceskip - ------------------------------------------------------------------------ ---- node-res ------------------------------------------------------------------------ - -local glue_spec = new_node "glue_spec" - -local new_gluespec = function (width, - stretch, shrink, - stretch_order, shrink_order) - local spec = copy_node(glue_spec) - if width then setfield(spec, "width" , width ) end - if stretch then setfield(spec, "stretch" , stretch ) end - if shrink then setfield(spec, "shrink" , shrink ) end - if stretch_order then setfield(spec, "stretch_order", stretch_order) end - if shrink_order then setfield(spec, "shrink_order" , shrink_order ) end - return spec -end - -local new_glue = function (width, stretch, shrink, - stretch_order, shrink_order) - local n = new_node "glue" - if not width then return n end - -- no spec - if width == false then - local width = tonumber(width) - if width then - setfield(n, "spec", - new_gluespec(width, stretch, shrink, - stretch_order, shrink_order)) - end - else - -- shared - setfield(n, "spec", copy_node(width)) - end - return n -end - ------------------------------------------------------------------------ ---- font-hsh ------------------------------------------------------------------------ ---- some initialization resembling font-hsh -local fonthashes = fonts.hashes -local identifiers = fonthashes.identifiers --- was: fontdata -local chardata = fonthashes.characters -local quaddata = fonthashes.quads -local parameters = fonthashes.parameters - ---- ('a, 'a) hash -> (('a, 'a) hash -> 'a -> 'a) -> ('a, 'a) hash -local setmetatableindex = function (t, f) - local mt = getmetatable(t) - if mt then - mt.__index = f - else - setmetatable(t, { __index = f }) - end - return t -end - -if not parameters then - parameters = { } - setmetatableindex(parameters, function(t, k) - if k == true then - return parameters[currentfont()] - else - local parameters = identifiers[k].parameters - t[k] = parameters - return parameters - end - end) - --fonthashes.parameters = parameters -end - -if not chardata then - chardata = { } - setmetatableindex(chardata, function(t, k) - if k == true then - return chardata[currentfont()] - else - local tfmdata = identifiers[k] - if not tfmdata then --- unsafe - tfmdata = font.fonts[k] - end - if tfmdata then - local characters = tfmdata.characters - t[k] = characters - return characters - end - end - end) - fonthashes.characters = chardata -end - -if not quaddata then - quaddata = { } - setmetatableindex(quaddata, function(t, k) - if k == true then - return quads[currentfont()] - else - local parameters = parameters[k] - local quad = parameters and parameters.quad or 0 - t[k] = quad - return quad - end - end) - --fonthashes.quads = quaddata -end - ----=================================================================--- ---- character kerning functionality ----=================================================================--- - -local kern_injector = function (fillup, kern) - if fillup then - local g = new_glue(kern) - local s = getfield(g, "spec") - setfield(s, "stretch", kern) - setfield(s, "stretch_order", 1) - return g - end - return new_kern(kern) -end - -local kernable_skip = function (n) - local st = getsubtype (n) - return st == userskip_code - or st == spaceskip_code - or st == xspaceskip_code -end - -local function spec_injector (fillup, width, stretch, shrink) - if fillup then - local spec = new_gluespec(width, 2 * stretch, 2 * shrink) - setfield(spec, "stretch_order", 1) - return spec - end - return new_gluespec(width,stretch,shrink) -end - ---[[doc-- - - Caveat lector. - This is an adaptation of the Context character kerning mechanism - that emulates XeTeX-style fontwise letterspacing. Note that in its - present state it is far inferior to the original, which is - attribute-based and ignores font-boundaries. Nevertheless, due to - popular demand the following callback has been added. - ---doc]]-- - -local kernfactors = { } --- fontid -> factor - -local kerncharacters -kerncharacters = function (head) - local start = head - local lastfont = nil - local keepligature = letterspace.keepligature --- function - local keeptogether = letterspace.keeptogether --- function - local fillup = false - - local identifiers = fonthashes.identifiers - local kernfactors = kernfactors - local firstkern = true - - while start do - local id = getid(start) - if id == glyph_code then - --- 1) look up kern factor (slow, but cached rudimentarily) - local krn - local fontid = getfont(start) - do - krn = kernfactors[fontid] - if not krn then - local tfmdata = identifiers[fontid] - if not tfmdata then -- unsafe - tfmdata = font.fonts[fontid] - end - if tfmdata then - fontproperties = tfmdata.properties - if fontproperties then - krn = fontproperties.kerncharacters - end - end - kernfactors[fontid] = krn - end - if not krn or krn == 0 then - firstkern = true - goto nextnode - elseif firstkern then - firstkern = false - if (id ~= disc_code) and (not getfield(start, "components")) then - --- not a ligature, skip node - goto nextnode - end - end - end - - if krn == "max" then - krn = .25 - fillup = true - else - fillup = false - end - - lastfont = fontid - - --- 2) resolve ligatures - local c = getfield(start, "components") - - if c then - if keepligature and keepligature(start) then - -- keep 'm - c = nil - else - while c do - local s = start - local p, n = getboth (s) - if p then - setlink (p, c) - else - head = c - end - if n then - local tail = find_node_tail(c) - setlink (tail, n) - end - start = c - setfield(s, "components", nil) - free_node(s) --> double free with multipart components - c = getfield (start, "components") - end - end - end -- kern ligature - - --- 3) apply the extra kerning - local prev = getprev(start) - if prev then - local pid = getid(prev) - - if not pid then - -- nothing - - elseif pid == glue_code and kernable_skip(prev) then - local spec = getfield(prev, "spec") - local wd = getfield(spec, "width") - if wd > 0 then - --- formula taken from Context - --- existing_width extended by four times the - --- width times the font’s kernfactor - local newwd = wd + --[[two en to a quad]] 4 * wd * krn - local stretched = (getfield(spec,"stretch") * newwd) / wd - local shrunk = (getfield(spec,"shrink") * newwd) / wd - setfield(prev, "spec", - spec_injector(fillup, newwd, stretched, shrunk)) - end - - elseif pid == kern_code then - local prev_subtype = getsubtype(prev) - if prev_subtype == kerning_code --- context does this by means of an - or prev_subtype == userkern_code --- attribute; we may need a test - then - - local pprev = getprev(prev) - local pprev_id = getid(pprev) - - if keeptogether - and pprev_id == glyph_code - and keeptogether(pprev, start) - then - -- keep - else - setsubtype (prev, userkern_code) - local prev_kern = getfield(prev, "kern") - prev_kern = prev_kern + quaddata[lastfont] * krn - setfield (prev, "kern", prev_kern) - end - end - - elseif pid == glyph_code then - if getfont(prev) == lastfont then - local prevchar = getchar(prev) - local lastchar = getchar(start) - if keeptogether and keeptogether(prev, start) then - -- keep 'm - elseif identifiers[lastfont] then - local lastfontchars = chardata[lastfont] - if lastfontchars then - local prevchardata = lastfontchars[prevchar] - if not prevchardata then - --- font doesn’t contain the glyph - else - local kern = 0 - local kerns = prevchardata.kerns - if kerns then kern = kerns[lastchar] or kern end - krn = kern + quaddata[lastfont]*krn -- here - insert_node_before(head,start,kern_injector(fillup,krn)) - end - end - end - else - krn = quaddata[lastfont]*krn -- here - insert_node_before(head,start,kern_injector(fillup,krn)) - end - - elseif pid == disc_code then - local disc = prev -- disc - local pre, post, replace = getdisc (disc) - local prv = getprev(disc) - local nxt = getnext(disc) - - if pre and prv then -- must pair with start.prev - -- this one happens in most cases - local before = copy_node(prv) - setprev(pre, before) - setnext(before, pre) - setprev(before, nil) - pre = kerncharacters (before) - pre = getnext(pre) - setprev(pre, nil) - setfield(disc, "pre", pre) - free_node(before) - end - - if post and nxt then -- must pair with start - local after = copy_node(nxt) - local tail = find_node_tail(post) - setnext(tail, after) - setprev(after, tail) - setnext(after, nil) - post = kerncharacters (post) - setnext(tail, nil) - setfield(disc, "post", post) - free_node(after) - end - - if replace and prv and nxt then -- must pair with start and start.prev - local before = copy_node(prv) - local after = copy_node(nxt) - local tail = find_node_tail(replace) - setprev(replace, before) - setnext(before, replace) - setprev(before, nil) - setnext(tail, after) - setprev(after, tail) - setnext(after, nil) - replace = kerncharacters (before) - replace = getnext(replace) - setprev(replace, nil) - setnext(getprev(after), nil) - setfield(disc, "replace", replace) - free_node(after) - free_node(before) - - elseif identifiers[lastfont] then - if prv - and getid(prv) == glyph_code - and getfont(prv) == lastfont - then - local kern = 0 - local prevchar = getchar(prv) - local lastchar = getchar(start) - local lastfontchars = chardata[lastfont] - if lastfontchars then - local prevchardata = lastfontchars[prevchar] - if not prevchardata then - --- font doesn’t contain the glyph - else - local kerns = prevchardata.kerns - if kerns then kern = kerns[lastchar] or kern end - end - end - krn = kern + quaddata[lastfont]*krn -- here - else - krn = quaddata[lastfont]*krn -- here - end - setfield(disc, "replace", kern_injector(false, krn)) - end --[[if replace and prv and nxt]] - end --[[if not pid]] - end --[[if prev]] - end --[[if id == glyph_code]] - - ::nextnode:: - if start then - start = getnext(start) - end - end - return head -end - ----=================================================================--- ---- integration ----=================================================================--- - ---- · callback: kerncharacters ---- · enabler: enablefontkerning ---- · disabler: disablefontkerning - ---- callback wrappers - ---- (node_t -> node_t) -> string -> string list -> bool -local registered_as = { } --- procname -> callbacks -local add_processor = function (processor, name, ...) - local callbacks = { ... } - for i=1, #callbacks do - luatexbase.add_to_callback(callbacks[i], processor, name) - end - registered_as[name] = callbacks --- for removal - return true -end - ---- string -> bool -local remove_processor = function (name) - local callbacks = registered_as[name] - if callbacks then - for i=1, #callbacks do - luatexbase.remove_from_callback(callbacks[i], name) - end - return true - end - return false --> unregistered -end - ---- When font kerning is requested, usually by defining a font with the ---- ``letterspace`` parameter, we inject a wrapper for the ---- ``kerncharacters()`` node processor in the relevant callbacks. This ---- wrapper initially converts the received head node into its “direct” ---- counterpart. Likewise, the callback result is converted back to an ---- ordinary node prior to returning. Internally, ``kerncharacters()`` ---- performs all node operations on direct nodes. - ---- unit -> bool -local enablefontkerning = function ( ) - - local handler = function (hd) - local direct_hd = todirect (hd) - logreport ("term", 5, "letterspace", - "kerncharacters() invoked with node.direct interface \z - (``%s`` -> ``%s``)", tostring (hd), tostring (direct_hd)) - local direct_hd = kerncharacters (direct_hd) - if not direct_hd then --- bad - logreport ("both", 0, "letterspace", - "kerncharacters() failed to return a valid new head") - end - return tonode (direct_hd) - end - - return add_processor( handler - , "luaotfload.letterspace" - , "pre_linebreak_filter" - , "hpack_filter") -end - ---- unit -> bool ----al disablefontkerning = function ( ) ----eturn remove_processor "luaotfload.letterspace" ---- - ---[[doc-- - - Fontwise kerning is enabled via the “kernfactor” option at font - definition time. Unlike the Context implementation which relies on - Luatex attributes, it uses a font property for passing along the - letterspacing factor of a node. - - The callback is activated the first time a letterspaced font is - requested and stays active until the end of the run. Since the font - is a property of individual glyphs, every glyph in the entire - document must be checked for the kern property. This is quite - inefficient compared to Context’s attribute based approach, but Xetex - compatibility reduces our options significantly. - ---doc]]-- - - -local fontkerning_enabled = false --- callback state - ---- fontobj -> float -> unit -local initializefontkerning = function (tfmdata, factor) - if factor ~= "max" then - factor = tonumber (factor) or 0 - end - if factor == "max" or factor ~= 0 then - local fontproperties = tfmdata.properties - if fontproperties then - --- hopefully this field stays unused otherwise - fontproperties.kerncharacters = factor - end - if not fontkerning_enabled then - fontkerning_enabled = enablefontkerning () - end - end -end - ---- like the font colorization, fontwise kerning is hooked into the ---- feature mechanism - -otffeatures.register { - name = "kernfactor", - description = "kernfactor", - initializers = { - base = initializefontkerning, - node = initializefontkerning, - } -} - ---[[doc-- - - The “letterspace” feature is essentially identical with the above - “kernfactor” method, but scales the factor to percentages to match - Xetex’s behavior. (See the Xetex reference, page 5, section 1.2.2.) - - Since Xetex doesn’t appear to have a (documented) “max” keyword, we - assume all input values are numeric. - ---doc]]-- - -local initializecompatfontkerning = function (tfmdata, percentage) - local factor = tonumber (percentage) - if not factor then - logreport ("both", 0, "letterspace", - "Invalid argument to letterspace: %s (type %q), " .. - "was expecting percentage as Lua number instead.", - percentage, type (percentage)) - return - end - return initializefontkerning (tfmdata, factor * 0.01) -end - -otffeatures.register { - name = "letterspace", - description = "letterspace", - initializers = { - base = initializecompatfontkerning, - node = initializecompatfontkerning, - } -} - ---[[example-- - -See https://bitbucket.org/phg/lua-la-tex-tests/src/tip/pln-letterspace-8-compare.tex -for an example. - ---example]]-- - ---- vim:sw=2:ts=2:expandtab:tw=71 - diff --git a/tex/compat/luaotfload/luaotfload-loaders.lua b/tex/compat/luaotfload/luaotfload-loaders.lua deleted file mode 100644 index 802776c5be80c70e55b45ce8576c57cf037b5aa3..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/luaotfload-loaders.lua +++ /dev/null @@ -1,231 +0,0 @@ -#!/usr/bin/env texlua ------------------------------------------------------------------------ --- FILE: luaotfload-loaders.lua --- DESCRIPTION: Luaotfload callback handling --- REQUIREMENTS: luatex v.0.80 or later; package lualibs --- AUTHOR: Philipp Gesang <phg@phi-gamma.net> --- AUTHOR: Hans Hagen, Khaled Hosny, Elie Roux, David Carlisle ------------------------------------------------------------------------ --- ---- Contains parts of the earlier main script. - -if not lualibs then error "this module requires Luaotfload" end -if not luaotfload then error "this module requires Luaotfload" end - -local logreport = luaotfload.log and luaotfload.log.report or print - -local lua_reader = function (specification) - local fullname = specification.filename or "" - if fullname == "" then - local forced = specification.forced or "" - if forced ~= "" then - fullname = specification.name .. "." .. forced - else - fullname = specification.name - end - end - local fullname = resolvers.findfile (fullname) or "" - if fullname ~= "" then - local loader = loadfile (fullname) - loader = loader and loader () - return loader and loader (specification) - end -end - -local eval_reader = function (specification) - local eval = specification.eval - if not eval or type (eval) ~= "function" then return nil end - logreport ("both", 0, "loaders", - "eval: found tfmdata for “%s”, injecting.", - specification.name) - return eval () -end - -local unsupported_reader = function (format) - return function (specification) - logreport ("both", 4, "loaders", - "font format “%s” unsupported; cannot load %s.", - format, tostring (specification.name)) - end -end - -local type1_reader = fonts.readers.afm -local tfm_reader = fonts.readers.tfm - -local install_formats = function () - local fonts = fonts - if not fonts then return false end - - local readers = fonts.readers - local sequence = readers.sequence - local seqset = table.tohash (sequence) - local formats = fonts.formats - if not readers or not formats then return false end - - local aux = function (which, reader) - if not which or type (which) ~= "string" - or not reader or type (reader) ~= "function" then - logreport ("both", 2, "loaders", "Error installing reader for “%s”.", which) - return false - end - formats [which] = "type1" - readers [which] = reader - if not seqset [which] then - logreport ("both", 3, "loaders", - "Extending reader sequence for “%s”.", which) - sequence [#sequence + 1] = which - seqset [which] = true - end - return true - end - - return aux ("evl", eval_reader) - and aux ("lua", lua_reader) - and aux ("pfa", unsupported_reader "pfa") - and aux ("afm", type1_reader) - and aux ("pfb", type1_reader) - and aux ("tfm", tfm_reader) - and aux ("ofm", tfm_reader) - and aux ("dfont", unsupported_reader "dfont") -end - -local not_found_msg = function (specification, size, id) - logreport ("both", 0, "loaders", "") - logreport ("both", 0, "loaders", - "--------------------------------------------------------") - logreport ("both", 0, "loaders", "") - logreport ("both", 0, "loaders", "Font definition failed for:") - logreport ("both", 0, "loaders", "") - logreport ("both", 0, "loaders", " > id : %d", id) - logreport ("both", 0, "loaders", " > specification : %q", specification) - if size > 0 then - logreport ("both", 0, "loaders", " > size : %.2f pt", size / 2^16) - end - logreport ("both", 0, "loaders", "") - logreport ("both", 0, "loaders", - "--------------------------------------------------------") -end ---[[doc-- - - \subsection{\CONTEXT override} - \label{define-font} - We provide a simplified version of the original font definition - callback. - ---doc]]-- - - -local definers --- (string, spec -> size -> id -> tmfdata) hash_t -do - local read = fonts.definers.read - - local patch = function (specification, size, id) - local fontdata = read (specification, size, id) -----if not fontdata then not_found_msg (specification, size, id) end - if type (fontdata) == "table" and fontdata.shared then - --- We need to test for the “shared” field here - --- or else the fontspec capheight callback will - --- operate on tfm fonts. - luatexbase.call_callback ("luaotfload.patch_font", fontdata, specification) - else - luatexbase.call_callback ("luaotfload.patch_font_unsafe", fontdata, specification) - end - return fontdata - end - - local mk_info = function (name) - local definer = name == "patch" and patch or read - return function (specification, size, id) - logreport ("both", 0, "loaders", "defining font no. %d", id) - logreport ("both", 0, "loaders", " > active font definer: %q", name) - logreport ("both", 0, "loaders", " > spec %q", specification) - logreport ("both", 0, "loaders", " > at size %.2f pt", size / 2^16) - local result = definer (specification, size, id) - if not result then return not_found_msg (specification, size, id) end - if type (result) == "number" then - logreport ("both", 0, "loaders", " > font definition yielded id %d", result) - return result - end - logreport ("both", 0, "loaders", " > font definition successful") - logreport ("both", 0, "loaders", " > name %q", result.name or "<nil>") - logreport ("both", 0, "loaders", " > fontname %q", result.fontname or "<nil>") - logreport ("both", 0, "loaders", " > fullname %q", result.fullname or "<nil>") - logreport ("both", 0, "loaders", " > type %s", result.type or "<nil>") - local spec = result.specification - if spec then - logreport ("both", 0, "loaders", " > file %q", spec.filename or "<nil>") - logreport ("both", 0, "loaders", " > subfont %s", spec.sub or "<nil>") - end - return result - end - end - - definers = { - patch = patch, - generic = read, - info_patch = mk_info "patch", - info_generic = mk_info "generic", - } -end - ---[[doc-- - - We create callbacks for patching fonts on the fly, to be used by - other packages. In addition to the regular \identifier{patch_font} - callback there is an unsafe variant \identifier{patch_font_unsafe} - that will be invoked even if the target font lacks certain essential - tfmdata tables. - - The callbacks initially contain the empty function that we are going - to override below. - ---doc]]-- - -local purge_define_font = function () - local cdesc = luatexbase.callback_descriptions "define_font" - --- define_font is an “exclusive” callback, meaning that there can - --- only ever be one entry. Everything beyond that would indicate - --- that something is broken. - local _, d = next (cdesc) - if d then - local i, d2 = next (cdesc, 1) - if d2 then --> issue warning - logreport ("both", 0, "loaders", - "Callback table for define_font contains multiple entries: \z - { [%d] = “%s” } -- seems fishy.", i, d2) - end - logreport ("log", 0, "loaders", - "Entry ``%s`` present in define_font callback; overriding.", d) - luatexbase.remove_from_callback ("define_font", d) - end -end - -local install_callbacks = function () - local create_callback = luatexbase.create_callback - local dummy_function = function () end - create_callback ("luaotfload.patch_font", "simple", dummy_function) - create_callback ("luaotfload.patch_font_unsafe", "simple", dummy_function) - purge_define_font () - local definer = config.luaotfload.run.definer - luatexbase.add_to_callback ("define_font", - definers[definer or "patch"], - "luaotfload.define_font", - 1) - return true -end - -return { - init = function () - local ret = true - if not install_formats () then - logreport ("log", 0, "loaders", "Error initializing OFM/PF{A,B} loaders.") - ret = false - end - if not install_callbacks () then - logreport ("log", 0, "loaders", "Error installing font loader callbacks.") - ret = false - end - return ret - end -} --- vim:tw=79:sw=2:ts=2:expandtab diff --git a/tex/compat/luaotfload/luaotfload-log.lua b/tex/compat/luaotfload/luaotfload-log.lua deleted file mode 100644 index ab38ffaac142c58f2aa7b65735995728bf2840ae..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/luaotfload-log.lua +++ /dev/null @@ -1,381 +0,0 @@ -if not modules then modules = { } end modules ["luaotfload-log"] = { - version = "2.8", - comment = "companion to Luaotfload", - author = "Khaled Hosny, Elie Roux, Philipp Gesang", - copyright = "Luaotfload Development Team", - license = "GNU GPL v2.0" -} - ---[[doc-- -The logging system is slow in general, as we always have the function -call overhead even if we aren’t going to output anything. On the other -hand, the more efficient approach followed by Context isn’t an option -because we lack a user interface to toggle per-subsystem tracing. ---doc]]-- - -local module_name = "luaotfload" --- prefix for messages -local debug = debug - -luaotfload = luaotfload or { } -luaotfload.log = luaotfload.log or { } -local log = luaotfload.log - -local ioopen = io.open -local iowrite = io.write -local lfsisdir = lfs.isdir -local lfsisfile = lfs.isfile -local osdate = os.date -local ostime = os.time -local osuuid = os.uuid -local select = select -local stringformat = string.format -local stringsub = string.sub -local tableconcat = table.concat -local texiowrite_nl = texio.write_nl -local texiowrite = texio.write -local type = type - -local dummyfunction = function () end - -local texjob = false -if tex and (tex.jobname or tex.formatname) then - --- TeX - texjob = true -end - -local loglevel = 0 --- default -local logout = "log" - ---- int -> bool -local set_loglevel = function (n) - if type(n) == "number" then - loglevel = n - end - return true -end -log.set_loglevel = set_loglevel - ---- unit -> int -local get_loglevel = function ( ) - return loglevel -end -log.get_loglevel = get_loglevel - -local writeln --- pointer to terminal/log writer -local statusln --- terminal writer that reuses the current line -local first_status = true --- indicate the begin of a status region - -local log_msg = [[ -logging output redirected to %s -to monitor the progress run "tail -f %s" in another terminal -]] - -local tmppath = os.getenv "TMPDIR" or "/tmp" - -local choose_logfile = function ( ) - if lfsisdir (tmppath) then - local fname - repeat --- ensure that file of that name doesn’t exist - fname = tmppath .. "/luaotfload-log-" .. osuuid() - until not lfsisfile (fname) - iowrite (stringformat (log_msg, fname, fname)) - return ioopen (fname, "w") - end - --- missing /tmp - return false -end - -local set_logout = function (s, finalizers) - if s == "stdout" then - logout = "redirect" - elseif s == "file" then --- inject custom logger - logout = "redirect" - local chan = choose_logfile () - chan:write (stringformat ("logging initiated at %s", - osdate ("%Y-%m-%d %H:%M:%S", --- i. e. osdate "%F %T" - ostime ()))) - local writefile = function (...) - if select ("#", ...) == 2 then - chan:write (select (2, ...)) - else - chan:write (select (1, ...)) - end - end - local writefile_nl= function (...) - chan:write "\n" - if select ("#", ...) == 2 then - chan:write (select (2, ...)) - else - chan:write (select (1, ...)) - end - end - - local writeln_orig = writeln - - texiowrite = writefile - texiowrite_nl = writefile_nl - writeln = writefile_nl - statusln = dummyfunction - - finalizers[#finalizers+1] = function () - chan:write (stringformat ("\nlogging finished at %s\n", - osdate ("%Y-%m-%d %H:%M:%S", --- i. e. osdate "%F %T" - ostime ()))) - chan:close () - texiowrite = texio.write - texiowrite_nl = texio.write_nl - writeln = writeln_orig - end - --else --- remains “log” - end - return finalizers -end - -log.set_logout = set_logout - -local format_error_handler -if debug then - local debugtraceback = debug.traceback - format_error_handler = function (err) - print "" - print (stringformat ("luaotfload error: %q", err)) - print (stringformat ("Lua interpreter %s", debugtraceback ())) - print "" - end -else - format_error_handler = function (err) - print "" - print (stringformat ("luaotfload error: %q", err)) - print "Lua debug module not available; please enable for a backtrace" - print "" - end -end - -local basic_logger = function (category, fmt, ...) - local res = { module_name, "|", category or "UNKNOWN", ":" } - if fmt then - local ok, val = xpcall (stringformat, format_error_handler, fmt, ...) - if ok then - res [#res + 1] = val - else - res [#res + 1] = stringformat ("ERROR: %q", val) - end - end - texiowrite_nl (logout, tableconcat(res, " ")) -end - ---- with faux db update with maximum verbosity: ---- ---- --------- -------- ---- buffering time (s) ---- --------- -------- ---- full 4.12 ---- line 4.20 ---- none 4.39 ---- --------- -------- ---- - -io.stdout:setvbuf "no" -io.stderr:setvbuf "no" - -local kill_line = "\r\x1b[K" - -if texjob == true then - --- We imitate the texio.* functions so the output is consistent. - writeln = function (str) - iowrite "\n" - iowrite(str) - end - statusln = function (str) - if first_status == false then - iowrite (kill_line) - else - iowrite "\n" - end - iowrite (str) - end -else - writeln = function (str) - iowrite(str) - iowrite "\n" - end - statusln = function (str) - if first_status == false then - iowrite (kill_line) - end - iowrite (str) - end -end - -stdout = function (writer, category, ...) - local res = { module_name, "|", category, ":" } - local nargs = select("#", ...) - if nargs == 0 then - --writeln tableconcat(res, " ") - --return - elseif nargs == 1 then - res[#res+1] = select(1, ...) -- around 30% faster than unpack() - else - res[#res+1] = stringformat(...) - end - writer (tableconcat(res, " ")) -end - ---- at default (zero), we aim to be quiet -local level_ids = { common = 1, loading = 2, search = 3 } - ---[[doc-- - - The report() logger is used more or less all over luaotfload. - Its requirements are twofold: - - 1) Provide two logging channels, the terminal and the log file; - 2) Allow for control over verbosity levels. - - The first part is addressed by specifying the log *mode* as the - first argument that can be either “log”, meaning the log file, or - “both”: log file and stdout. Anything else is taken as referring to - stdout only. - - Verbosity levels, though not as fine-grained as e.g. Context’s - system of tracers, allow keeping the logging spam caused by - different subsystems manageable. By default, luaotfload will not - emit anything if things are running smoothly on level zero. Only - warning messages are relayed, while the other messages are skipped - over. (This is a little sub-optimal performance-wise since the - function calls to the logger are executed regardless.) The log - level during a Luatex run can be adjusted by setting the “loglevel” - field in config.luaotfload, or by calling log.set_loglevel() as - defined above. - ---doc]]-- - -local report = function (mode, lvl, ...) - if type(lvl) == "string" then - lvl = level_ids[lvl] - end - if not lvl then lvl = 0 end - - if loglevel >= lvl then - if mode == "log" then - basic_logger (...) - elseif mode == "both" and logout ~= "redirect" then - basic_logger (...) - stdout (writeln, ...) - else - stdout (writeln, ...) - end - end -end - -log.report = report - ---[[doc-- - - status_logger -- Overwrites the most recently printed line of the - terminal. Its purpose is to provide feedback without spamming - stdout with irrelevant messages, i.e. when building the database. - - Status logging must be initialized by calling status_start() and - properly reset via status_stop(). - - The arguments low and high indicate the loglevel threshold at which - linewise and full logging is triggered, respectively. E.g. - - names_status (1, 4, "term", "Hello, world!") - - will print nothing if the loglevel is less than one, reuse the - current line if the loglevel ranges from one to three inclusively, - and output the message on a separate line otherwise. - ---doc]]-- - -local status_logger = function (mode, ...) - if mode == "log" then - basic_logger (...) - else - if mode == "both" and logout ~= "redirect" then - basic_logger (...) - stdout (statusln, ...) - else - stdout (statusln, ...) - end - first_status = false - end -end - ---[[doc-- - - status_start -- Initialize status logging. This installs the status - logger if the loglevel is in the specified range, and the normal - logger otherwise. It also resets the first line state which - causing the next line printed using the status logger to not kill - the current line. - ---doc]]-- - -local status_writer -local status_low = 99 -local status_high = 99 - -local status_start = function (low, high) - first_status = true - status_low = low - status_high = high - - if os.type == "windows" --- Assume broken terminal. - or os.getenv "TERM" == "dumb" - then - status_writer = function (mode, ...) - report (mode, high, ...) - end - return - end - - if low <= loglevel and loglevel < high then - status_writer = status_logger - else - status_writer = function (mode, ...) - report (mode, high, ...) - end - end -end - ---[[doc-- - - status_stop -- Finalize a status region by outputting a newline and - printing a message. - ---doc]]-- - -local status_stop = function (...) - if first_status == false then - status_writer(...) - if texjob == false then - writeln "" - end - end -end - -log.names_status = function (...) status_writer (...) end -log.names_status_start = status_start -log.names_status_stop = status_stop - ---[[doc-- - - The fontloader comes with the Context logging mechanisms - inaccessible. Instead, it provides dumb fallbacks based - on the functions in texio.write*() that can be overridden - by providing a function texio.reporter(). - - The fontloader output can be quite verbose, so we disable - it entirely by default. - ---doc]]-- - -local texioreporter = function (message) - report ("log", 2, message) -end - -texio.reporter = texioreporter ---- vim:shiftwidth=4:expandtab:ft=lua diff --git a/tex/compat/luaotfload/luaotfload-main.lua b/tex/compat/luaotfload/luaotfload-main.lua deleted file mode 100644 index 14d531683a26041223a99d2fc6da758026472165..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/luaotfload-main.lua +++ /dev/null @@ -1,301 +0,0 @@ ------------------------------------------------------------------------ --- FILE: luaotfload-main.lua --- DESCRIPTION: Luaotfload entry point --- REQUIREMENTS: luatex v.0.95.0 or later; package lualibs --- AUTHOR: Élie Roux, Khaled Hosny, Philipp Gesang ------------------------------------------------------------------------ --- - -local osgettimeofday = os.gettimeofday -config = config or { } -luaotfload = luaotfload or { } -local luaotfload = luaotfload -luaotfload.log = luaotfload.log or { } -luaotfload.version = "2.8" -luaotfload.loaders = { } -luaotfload.min_luatex_version = { 0, 95, 0 } -luaotfload.fontloader_package = "reference" --- default: from current Context - -if not tex or not tex.luatexversion then - error "this program must be run in TeX mode" --- or call tex.initialize() =) -else - --- version check - local major = tex.luatexversion / 100 - local minor = tex.luatexversion % 100 - local revision = tex.luatexrevision --[[ : string ]] - local revno = tonumber (revision) - local minimum = luaotfload.min_luatex_version - local actual = { major, minor, revno or 0 } - if actual [1] < minimum [1] - or actual == minimum and actual [2] < minimum [2] - or actual == minimum and actual [2] == minimum [2] and actual [3] < minimum [3] - then - texio.write_nl ("term and log", - string.format ("\tFATAL ERROR\n\z - \tLuaotfload requires a Luatex version >= %d.%d.%d.\n\z - \tPlease update your TeX distribution!\n\n", - (unpack or table.unpack) (minimum))) - error "version check failed" - end -end - -local authors = "\z - Hans Hagen,\z - Khaled Hosny,\z - Elie Roux,\z - Will Robertson,\z - Philipp Gesang,\z - Dohyun Kim,\z - Reuben Thomas\z -" - - -luaotfload.module = { - name = "luaotfload-main", - version = 2.80001, - date = "2017/01/29", - description = "OpenType layout system.", - author = authors, - copyright = authors, - license = "GPL v2.0" -} - ---[[doc-- - - This file initializes the system and loads the font loader. To - minimize potential conflicts between other packages and the code - imported from \CONTEXT, several precautions are in order. Some of - the functionality that the font loader expects to be present, like - raw access to callbacks, are assumed to have been disabled by - \identifier{luatexbase} when this file is processed. In some cases - it is possible to trick it by putting dummies into place and - restoring the behavior from \identifier{luatexbase} after - initilization. Other cases such as attribute allocation require - that we hook the functionality from \identifier{luatexbase} into - locations where they normally wouldn’t be. - - Anyways we can import the code base without modifications, which is - due mostly to the extra effort by Hans Hagen to make \LUATEX-Fonts - self-contained and encapsulate it, and especially due to his - willingness to incorporate our suggestions. - ---doc]]-- - -local luatexbase = luatexbase -local require = require -local type = type - -luatexbase.provides_module (luaotfload.module) - ---[[doc-- - - \subsection{Module loading} - We load the files imported from \CONTEXT with function derived this way. It - automatically prepends a prefix to its argument, so we can refer to the - files with their actual \CONTEXT name. - ---doc]]-- - -local make_loader_name = function (prefix, name) - local msg = luaotfload.log and luaotfload.log.report - or function (stream, lvl, cat, ...) - if lvl > 1 then --[[not pressing]] return end - texio.write_nl ("log", - string.format ("luaotfload | %s : ", - tostring (cat))) - texio.write (string.format (...)) - end - if not name then - msg ("both", 0, "load", - "Fatal error: make_loader_name (“%s”, “%s”).", - tostring (prefix), tostring (name)) - return "dummy-name" - end - name = tostring (name) - if prefix == false then - msg ("log", 9, "load", - "No prefix requested, passing module name “%s” unmodified.", - name) - return tostring (name) .. ".lua" - end - prefix = tostring (prefix) - msg ("log", 9, "load", - "Composing module name from constituents %s, %s.", - prefix, name) - return prefix .. "-" .. name .. ".lua" -end - -local timing_info = { - t_load = { }, - t_init = { }, -} - -local make_loader = function (prefix) - return function (name) - local t_0 = osgettimeofday () - local modname = make_loader_name (prefix, name) - --- We don’t want the stack info from inside, so just pcall(). - local ok, data = pcall (require, modname) - local t_end = osgettimeofday () - timing_info.t_load [name] = t_end - t_0 - if not ok then - io.write "\n" - local msg = luaotfload.log and luaotfload.log.report or print - msg ("both", 0, "load", "FATAL ERROR") - msg ("both", 0, "load", " × Failed to load module %q.", - tostring (modname)) - local lines = string.split (data, "\n\t") - if not lines then - msg ("both", 0, "load", " × Error message: %q", data) - else - msg ("both", 0, "load", " × Error message:") - for i = 1, #lines do - msg ("both", 0, "load", " × %q.", lines [i]) - end - end - io.write "\n\n" - local debug = debug - if debug then - io.write (debug.traceback()) - io.write "\n\n" - end - os.exit(-1) - end - return data - end -end - ---[[doc-- - Certain files are kept around that aren’t loaded because they are part of - the imported fontloader. In order to keep the initialization structure - intact we also provide a no-op version of the module loader that can be - called in the expected places. ---doc]]-- - -local dummy_loader = function (name) - luaotfload.log.report ("log", 3, "load", - "Skipping module “%s” on purpose.", - name) -end - -local context_loader = function (name, path) - luaotfload.log.report ("log", 3, "load", - "Loading module “%s” from Context.", - name) - local t_0 = osgettimeofday () - local modname = make_loader_name (false, name) - local modpath = modname - if path then - if lfs.isdir (path) then - luaotfload.log.report ("log", 3, "load", - "Prepending path “%s”.", - path) - modpath = file.join (path, modname) - else - luaotfload.log.report ("both", 0, "load", - "Non-existant path “%s” specified, ignoring.", - path) - end - end - local ret = require (modpath) - local t_end = osgettimeofday () - timing_info.t_load [name] = t_end - t_0 - - if ret ~= true then - --- require () returns “true” upon success unless the loaded file - --- yields a non-zero exit code. This isn’t per se indicating that - --- something isn’t right, but against HH’s coding practices. We’ll - --- silently ignore this ever happening on lower log levels. - luaotfload.log.report ("log", 4, "load", - "Module “%s” returned “%s”.", ret) - end - return ret -end - -local install_loaders = function () - local loaders = { } - local loadmodule = make_loader "luaotfload" - loaders.luaotfload = loadmodule - loaders.fontloader = make_loader "fontloader" - loaders.context = context_loader - loaders.ignore = dummy_loader -----loaders.plaintex = make_loader "luatex" --=> for Luatex-Plain - - loaders.initialize = function (name) - local tmp = loadmodule (name) - local logreport = luaotfload.log.report - if type (tmp) == "table" then - local init = tmp.init - if init and type (init) == "function" then - local t_0 = osgettimeofday () - if not init () then - logreport ("log", 0, "load", - "Failed to load module “%s”.", name) - return - end - local t_end = osgettimeofday () - local d_t = t_end - t_0 - logreport ("log", 4, "load", - "Module “%s” loaded in %d ms.", - name, d_t) - timing_info.t_init [name] = d_t - end - end - end - - return loaders -end - -local luaotfload_initialized = false --- prevent multiple invocations - -luaotfload.main = function () - - if luaotfload_initialized then - logreport ("log", 0, "load", - "Luaotfload initialization requested but is already \z - loaded, ignoring.") - return - end - luaotfload_initialized = true - - luaotfload.loaders = install_loaders () - local loaders = luaotfload.loaders - local loadmodule = loaders.luaotfload - local initialize = loaders.initialize - - local starttime = osgettimeofday () - local init = loadmodule "init" --- fontloader initialization - local store = init.early () --- injects the log module too - local logreport = luaotfload.log.report - - initialize "parsers" --- fonts.conf and syntax - initialize "configuration" --- configuration options - - if not init.main (store) then - logreport ("log", 0, "load", "Main fontloader initialization failed.") - end - - initialize "loaders" --- Font loading; callbacks - initialize "database" --- Font management. - initialize "colors" --- Per-font colors. - - luaotfload.resolvers = loadmodule "resolvers" --- Font lookup - luaotfload.resolvers.init () - - if not config.actions.reconfigure () then - logreport ("log", 0, "load", "Post-configuration hooks failed.") - end - - initialize "features" --- font request and feature handling - loadmodule "letterspace" --- extra character kerning - initialize "auxiliary" --- additional high-level functionality - - luaotfload.aux.start_rewrite_fontname () --- to be migrated to fontspec - - logreport ("both", 0, "main", - "initialization completed in %0.3f seconds", - osgettimeofday() - starttime) -----inspect (timing_info) -end - --- vim:tw=79:sw=4:ts=4:et diff --git a/tex/compat/luaotfload/luaotfload-main.tex b/tex/compat/luaotfload/luaotfload-main.tex deleted file mode 100644 index 21e001b2e293bf75a8c0c297f09aca274fe42245..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/luaotfload-main.tex +++ /dev/null @@ -1,1908 +0,0 @@ -%% Copyright (C) 2009-2017 -%% -%% by Elie Roux <elie.roux@telecom-bretagne.eu> -%% and Khaled Hosny <khaledhosny@eglug.org> -%% and Philipp Gesang <phg@phi-gamma.net> -%% -%% This file is part of Luaotfload. -%% -%% Home: https://github.com/lualatex/luaotfload -%% Support: <lualatex-dev@tug.org>. -%% -%% Luaotfload is under the GPL v2.0 (exactly) license. -%% -%% ---------------------------------------------------------------------------- -%% -%% Luaotfload is free software; you can redistribute it and/or -%% modify it under the terms of the GNU General Public License -%% as published by the Free Software Foundation; version 2 -%% of the License. -%% -%% Luaotfload is distributed in the hope that it will be useful, -%% but WITHOUT ANY WARRANTY; without even the implied warranty of -%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -%% GNU General Public License for more details. -%% -%% You should have received a copy of the GNU General Public License -%% along with Luaotfload; if not, see <http://www.gnu.org/licenses/>. -%% -%% ---------------------------------------------------------------------------- -%% - -\beginfrontmatter - - \setdocumenttitle {The \identifier{luaotfload} package} - \setdocumentdate {2017/01/29 v2.8} - \setdocumentauthor {Elie Roux · Khaled Hosny · Philipp Gesang\\ - Home: \hyperlink {https://github.com/lualatex/luaotfload}\\ - Support: \email {lualatex-dev@tug.org}} - - \typesetdocumenttitle - - \beginabstractcontent - This package is an adaptation of the \CONTEXT font loading system. - It allows for loading \OpenType fonts with an extended syntax and adds - support for a variety of font features. - - After discussion of the font loading API, this manual gives an - overview of the core components of \identifier{Luaotfload}: The - packaged font loader code, the names database, configuration, and - helper functions on the \LUA\ end. - \endabstractcontent - -\endfrontmatter - -\typesetcontent - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\beginsection {Introduction} -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -Font management and installation has always been painful with \TEX. A -lot of files are needed for one font (\abbrev{tfm}, \abbrev{pfb}, -\abbrev{map}, \abbrev{fd}, \abbrev{vf}), and due to the 8-Bit encoding -each font is limited to 256 characters. - -But the font world has evolved since the original \TEX, and new -typographic systems have appeared, most notably the so called -\emphasis{smart font} technologies like \OpenType fonts (\abbrev{otf}). - -These fonts can contain many more characters than \TEX fonts, as well -as additional functionality like ligatures, old-style numbers, small -capitals, etc., and support more complex writing systems like Arabic -and Indic\footnote{% - Unfortunately, \identifier{luaotfload} doesn‘t support many Indic - scripts right now. - Assistance in implementing the prerequisites is greatly - appreciated. -} -scripts. - -\OpenType fonts are widely deployed and available for all modern -operating systems. - -As of 2013 they have become the de facto standard for advanced text -layout. - -However, until recently the only way to use them directly in the \TEX -world was with the \XETEX engine. - -Unlike \XETEX, \LUATEX has no built-in support for \OpenType or -technologies other than the original \TEX fonts. - -Instead, it provides hooks for executing \LUA code during the \TEX run -that allow implementing extensions for loading fonts and manipulating -how input text is processed without modifying the underlying engine. - -This is where \identifier{luaotfload} comes into play: -Based on code from \CONTEXT, it extends \LUATEX with functionality necessary -for handling \OpenType fonts. - -Additionally, it provides means for accessing fonts known to the operating -system conveniently by indexing the metadata. - -\endsection - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\beginsection {Thanks} -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\identifier{Luaotfload} is part of \LUALATEX, the community-driven -project to provide a foundation for using the \LATEX format with the -full capabilites of the \LUATEX engine. -% -As such, the distinction between end users, contributors, and project -maintainers is intentionally kept less strict, lest we unduly -personalize the common effort. - -Nevertheless, the current maintainers would like to express their -gratitude to Khaled Hosny, Akira Kakuto, Hironori Kitagawa and Dohyun -Kim. -% -Their contributions -- be it patches, advice, or systematic -testing -- made the switch from version 1.x to 2.2 possible. -% -Also, Hans Hagen, the author of the font loader, made porting the -code to \LATEX a breeze due to the extra effort he invested into -isolating it from the rest of \CONTEXT, not to mention his assistance -in the task and willingness to respond to our suggestions. - -\endsection - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\beginsection {Loading Fonts} -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\identifier{luaotfload} supports an extended font request syntax: - -\beginnarrower - \nonproportional{\string\font\string\foo\space= \string{}% - \meta{prefix}\nonproportional{:}% - \meta{font name}\nonproportional{:}% - \meta{font features}\nonproportional{\string}}% - \meta{\TEX font features} -\endnarrower - -\noindent -The curly brackets are optional and escape the spaces in the enclosed -font name. -% -Alternatively, double quotes serve the same purpose. -% -A selection of individual parts of the syntax are discussed below; -for a more formal description see figure \ref{font-syntax}. - -\beginsyntaxfloat - {font-syntax} - {Font request syntax. - Braces or double quotes around the - \emphasis{specification} rule will - preserve whitespace in file names. - In addition to the font style modifiers - (\emphasis{slash-notation}) given above, there - are others that are recognized but will be silently - ignored: \nonproportional{aat}, - \nonproportional{icu}, and - \nonproportional{gr}. - The special terminals are: - \smallcaps {feature\textunderscore id} for a valid font - feature name and - \smallcaps {feature\textunderscore value} for the corresponding - value. - \smallcaps {tfmname} is the name of a \abbrev{tfm} file. - \smallcaps {digit} again refers to bytes 48--57, and - \smallcaps {all\textunderscore characters} to all byte values. - \smallcaps {csname} and \smallcaps {dimension} are the \TEX concepts.} -% - <definition> ::= `\\font', {\sc csname}, `=', <font request>, [ <size> ] ; - - <size> ::= `at', {\sc dimension} ; - - <font request> ::= `"', <unquoted font request> `"' - \alt `{', <unquoted font request> `}' - \alt <unquoted font request> ; - - <unquoted font request> ::= <specification>, [`:', <feature list> ] - \alt <path lookup>, [ [`:'], <feature list> ] ; - - <specification> ::= <prefixed spec>, [ <subfont no> ], \{ <modifier> \} - \alt <anon lookup>, \{ <modifier> \} ; - - <prefixed spec> ::= `combo:', <combo list> - \alt `file:', <file lookup> - \alt `name:', <name lookup> ; - - <combo list> ::= <combo def 1>, \{ `;', <combo def> \} ; - - <combo def 1> ::= <combo id>, `->', <combo id> ; - - <combo def> ::= <combo id>, `->', <combo id chars> ; - - <combo id> ::= (`(', \{ {\sc digit} \}, `)' | \{ {\sc digit} \} ) ; - - <combo id chars> ::= (`(', \{ {\sc digit} \}, `,', <combo chars>, `)' - \alt \{ {\sc digit} \} ) ; - - <combo chars> ::= `fallback' - \alt \{ <combo range>, \{ `*', <combo range> \} \} ; - - <combo range> ::= <combo num>, [ `-', <combo num> ] ; - - <combo num> ::= `0x', \{ {\sc hexdigit} \} - \alt `U+', \{ {\sc digit} \} - \alt \{ {\sc digit} \} ; - - <file lookup> ::= \{ <name character> \} ; - - <name lookup> ::= \{ <name character> \} ; - - <anon lookup> ::= {\sc tfmname} | <name lookup> ; - - <path lookup> ::= `[', \{ <path content> \}, `]', [ <subfont no> ] ; - - <path content> ::= <path balanced> - \alt `\\', {\sc all_characters} - \alt {\sc all_characters} - `]' - - <path balanced> ::= `[', [ <path content> ], `]' - - <modifier> ::= `/', (`I' | `B' | `BI' | `IB' | `S=', \{ {\sc digit} \} ) ; - - <subfont no> ::= `(', \{ {\sc digit} \}, `)' ; - - <feature list> ::= <feature expr>, \{ `;', <feature expr> \} ; - - <feature expr> ::= {\sc feature_id}, `=', {\sc feature_value} - \alt <feature switch>, {\sc feature_id} ; - - <feature switch> ::= `+' | `-' ; - - <name character> ::= {\sc all_characters} - ( `(' | `/' | `:' ) ; -\endsyntaxfloat - -%% Below guarded space gets borked in index; why‽ -\beginsubsection{Prefix -- the \identifier{luaotfload}{ }Way} - -In \identifier{luaotfload}, the canonical syntax for font requests -requires a \emphasis{prefix}: -% -\beginnarrower - \nonproportional{\string\font\string\fontname\space= }% - \meta{prefix}% - \nonproportional{:}% - \meta{fontname}% - \dots -\endnarrower -% -where \meta{prefix} is either \inlinecode{file:} or \inlinecode {name:}.\footnote{% - \identifier{Luaotfload} also knows two further prefixes, \inlinecode {kpse:} - and \inlinecode {my:}. - % - A \inlinecode {kpse} lookup is restricted to files that can be found by - \identifier{kpathsea} and will not attempt to locate system fonts. - % - This behavior can be of value when an extra degree of encapsulation is - needed, for instance when supplying a customized tex distribution. - - The \inlinecode {my} lookup takes this a step further: it lets you define - a custom resolver function and hook it into the \luaident{resolve_font} - callback. - % - This ensures full control over how a file is located. - % - For a working example see the - \hyperlink [test repo]{https://bitbucket.org/phg/lua-la-tex-tests/src/5f6a535d/pln-lookup-callback-1.tex}. -} -% -It determines whether the font loader should interpret the request as -a \emphasis{file name} or - \emphasis{font name}, respectively, -which again influences how it will attempt to locate the font. -% -Examples for font names are - “Latin Modern Italic”, - “GFS Bodoni Rg”, and - “PT Serif Caption” --- they are the human readable identifiers -usually listed in drop-down menus and the like.\footnote{% - Font names may appear like a great choice at first because they - offer seemingly more intuitive identifiers in comparison to arguably - cryptic file names: - % - “PT Sans Bold” is a lot more descriptive than \fileent{PTS75F.ttf}. - On the other hand, font names are quite arbitrary and there is no - universal method to determine their meaning. - % - While \identifier{luaotfload} provides fairly sophisticated heuristic - to figure out a matching font style, weight, and optical size, it - cannot be relied upon to work satisfactorily for all font files. - % - For an in-depth analysis of the situation and how broken font names - are, please refer to - \hyperlink [this post]{http://www.ntg.nl/pipermail/ntg-context/2013/073889.html} - by Hans Hagen, the author of the font loader. - % - If in doubt, use filenames. - % - \fileent{luaotfload-tool} can perform the matching for you with the - option \inlinecode {--find=<name>}, and you can use the file name it returns - in your font definition. -} -% -In order for fonts installed both in system locations and in your -\fileent{texmf} to be accessible by font name, \identifier{luaotfload} must -first collect the metadata included in the files. -% -Please refer to section~\ref{sec:fontdb} below for instructions on how to -create the database. - -File names are whatever your file system allows them to be, except -that that they may not contain the characters - \inlinecode {(}, - \inlinecode {:}, and - \inlinecode {/}. -% -As is obvious from the last exception, the \inlinecode {file:} lookup will -not process paths to the font location -- only those -files found when generating the database are addressable this way. -% -Continue below in the \XETEX section if you need to load your fonts -by path. -% -The file names corresponding to the example font names above are - \fileent{lmroman12-italic.otf}, - \fileent{GFSBodoni.otf}, and - \fileent{PTZ56F.ttf}. - -\endsubsection - -\beginsubsection {Bracketed Lookups} -\label{sec:conf} -Bracketed lookups allow for arbitrary character content to be used in a -definition. -% -A simple bracketed request looks follows the scheme - -\beginnarrower - \nonproportional{\string\font\string\fontname\space = [}% - \meta{/path/to/file}% - \nonproportional{]} -\endnarrower - -\noindent -Inside the square brackets, every character except for a closing bracket is -permitted, allowing for arbitrary paths to a font file -- including Windows -style paths with UNC or drive letter prepended -- to be specified. -% -The \identifier{Luaotfload} syntax differs from \XETEX in that the subfont -selector goes \emphasis{after} the closing bracket: - -\beginnarrower - \nonproportional{\string\font\string\fontname\space = [}% - \meta{/path/to/file}% - \nonproportional{]} - \nonproportional{(}n\nonproportional{)} -\endnarrower - -Naturally, path-less file names are equally valid and processed the -same way as an ordinary \inlinecode {file:} lookup. - -\beginsubsection {Compatibility} - -In addition to the regular prefixed requests, \identifier{luaotfload} -accepts loading fonts the \XETEX way. -% -There are again two modes: bracketed and unbracketed. -For the bracketed variety, see above, \ref{sec:conf}. - -Unbracketed (or, for lack of a better word: \emphasis{anonymous}) -font requests resemble the conventional \TEX syntax. - -\beginnarrower - \nonproportional{\string\font\string\fontname\space= }% - \meta{font name} - \dots -\endnarrower -\endsubsection - -However, they have a broader spectrum of possible interpretations: -before anything else, \identifier{luaotfload} attempts to load a -traditional \TEX Font Metric (\abbrev{tfm} or \abbrev{ofm}). -% -If this fails, it performs a \inlinecode {path:} lookup, which itself will -fall back to a \inlinecode {file:} lookup. -% -Lastly, if none of the above succeeded, attempt to resolve the request as a -\inlinecode {name:} lookup by searching the font index for \meta{font name}. -% -The behavior of this “anonymous” lookup is configurable, see the configuation -manpage for details. - -Furthermore, \identifier{luaotfload} supports the slashed (shorthand) -font style notation from \XETEX. - -\beginnarrower - \nonproportional{\string\font\string\fontname\space= }% - \meta{font name}% - \nonproportional{/}% - \meta{modifier} - \dots -\endnarrower - -\noindent -Currently, four style modifiers are supported: - \inlinecode {I} for italic shape, - \inlinecode {B} for bold weight, - \inlinecode {BI} or \inlinecode {IB} for the combination of both. -% -Other “slashed” modifiers are too specific to the \XETEX engine and -have no meaning in \LUATEX. - -\endsubsection - -\beginsubsection{Examples} - -\beginsubsubsection{Loading by File Name} - -For example, conventional \TeX\ font can be loaded with a -\inlinecode {file:} request like so: - -\beginlisting - \font \lmromanten = {file:ec-lmr10} at 10pt -\endlisting - -The \OpenType version of Janusz Nowacki’s font \emphasis{Antykwa -Półtawskiego}\footnote{% - \hyperlink {http://jmn.pl/antykwa-poltawskiego/}, also available in - in \TEX Live. -} -in its condensed variant can be loaded as follows: - -\beginlisting - \font \apcregular = file:antpoltltcond-regular.otf at 42pt -\endlisting - -The next example shows how to load the \emphasis{Porson} font digitized by -the Greek Font Society using \XETEX-style syntax and an absolute path from a -non-standard directory: - -\beginlisting - \font \gfsporson = "[/tmp/GFSPorson.otf]" at 12pt -\endlisting - -\identifier{TrueType} collection files (the extension is usually -\inlinecode{.ttc}) contain more than a single font. In order to refer to these -subfonts, the respective index may be added in parentheses after the file -name.\footnote{% - Incidentally, this syntactical detail also prevents one from loading files - that end in balanced parentheses. -} - -\beginlisting - \font \cambriamain = "file:cambria.ttc(0)" at 10pt - \font \cambriamath = "file:cambria.ttc(1)" at 10pt -\endlisting - -and likewise, requesting subfont inside a TTC container by path: - -\beginlisting - \font \asanamain = "[/home/typesetter/.fonts/math/asana.ttc](0):mode=node;+tlig" at 10pt - \font \asanamath = "[/home/typesetter/.fonts/math/asana.ttc](1):mode=base" at 10pt -\endlisting - -\endsubsubsection - -\beginsubsubsection{Loading by Font Name} - -The \inlinecode {name:} lookup does not depend on cryptic filenames: - -\beginlisting - \font \pagellaregular = {name:TeX Gyre Pagella} at 9pt -\endlisting - -A bit more specific but essentially the same lookup would be: - -\beginlisting - \font \pagellaregular = {name:TeX Gyre Pagella Regular} at 9pt -\endlisting - -\noindent -Which fits nicely with the whole set: - -\beginlisting - \font\pagellaregular = {name:TeX Gyre Pagella Regular} at 9pt - \font\pagellaitalic = {name:TeX Gyre Pagella Italic} at 9pt - \font\pagellabold = {name:TeX Gyre Pagella Bold} at 9pt - \font\pagellabolditalic = {name:TeX Gyre Pagella Bolditalic} at 9pt - - {\pagellaregular foo bar baz\endgraf} - {\pagellaitalic foo bar baz\endgraf} - {\pagellabold foo bar baz\endgraf} - {\pagellabolditalic foo bar baz\endgraf} - - ... -\endlisting - -\endsubsubsection - -\beginsubsubsection{Modifiers} - -If the entire \emphasis{Iwona} family\footnote{% - \hyperlink {http://jmn.pl/kurier-i-iwona/}, - also in \TEX Live. -} -is installed in some location accessible by \identifier{luaotfload}, -the regular shape can be loaded as follows: - -\beginlisting - \font \iwona = Iwona at 20pt -\endlisting - -\noindent -To load the most common of the other styles, the slash notation can -be employed as shorthand: - -\beginlisting - \font \iwonaitalic = Iwona/I at 20pt - \font \iwonabold = Iwona/B at 20pt - \font \iwonabolditalic = Iwona/BI at 20pt -\endlisting - -\noindent -which is equivalent to these full names: - -\beginlisting - \font \iwonaitalic = "Iwona Italic" at 20pt - \font \iwonabold = "Iwona Bold" at 20pt - \font \iwonabolditalic = "Iwona BoldItalic" at 20pt -\endlisting - -\endsubsubsection -\endsubsection -\endsection - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\beginsection {Font features} -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\emphasis{Font features} are the second to last component in the -general scheme for font requests: - -\beginnarrower - \nonproportional{\string\font\string\foo\space= "}% - \meta{prefix}% - \nonproportional{:}% - \meta{font name}% - \nonproportional{:}% - \meta{font features}% - \meta{\TEX font features}% - \nonproportional{"} -\endnarrower - -\noindent -If style modifiers are present (\XETEX style), they must precede -\meta{font features}. - -The element \meta{font features} is a semicolon-separated list of feature -tags\footnote{% - Cf. \hyperlink {http://www.microsoft.com/typography/otspec/featurelist.htm}. -} -and font options. -% -Prepending a font feature with a \inlinecode{+} (plus sign) enables it, -whereas a \inlinecode{-} (minus) disables it. For instance, the request - -\beginlisting - \font \test = LatinModernRoman:+clig;-kern -\endlisting - -\noindent activates contextual ligatures (\inlinecode{clig}) and -disables kerning (\inlinecode{kern}). -% -Alternatively the options \inlinecode{true} or \inlinecode{false} can -be passed to the feature in a key/value expression. -% -The following request has the same meaning as the last one: - -\beginlisting - \font \test = LatinModernRoman:clig=true;kern=false -\endlisting - -\noindent -Furthermore, this second syntax is required should a font feature -accept other options besides a true/false switch. -% -For example, \emphasis{stylistic alternates} (\inlinecode{salt}) are -variants of given glyphs. -% -They can be selected either explicitly by supplying the variant -index (starting from one), or randomly by setting the value to, -obviously, \inlinecode{random}. - -%% TODO verify that this actually works with a font that supports -%% the salt/random feature!\fi -\beginlisting - \font \librmsaltfirst = LatinModernRoman:salt=1 -\endlisting - -\beginsubsection {Basic font features} - -\begindescriptions - - \beginaltitem {mode} - \identifier{luaotfload} has two \OpenType processing - \emphasis{modes}: - \identifier{base} and \identifier{node}. - - \identifier{base} mode works by mapping \OpenType - features to traditional \TEX ligature and kerning mechanisms. - % - Supporting only non-contextual substitutions and kerning - pairs, it is the slightly faster, albeit somewhat limited, variant. - % - \identifier{node} mode works by processing \TeX’s internal - node list directly at the \LUA end and supports - a wider range of \OpenType features. - % - The downside is that the intricate operations required for - \identifier{node} mode may slow down typesetting especially - with complex fonts and it does not work in math mode. - - By default \identifier{luaotfload} is in \identifier{node} - mode, and \identifier{base} mode has to be requested where needed, - e.~g. for math fonts. - \endaltitem - - \beginaltitem {script} \label{script-tag} - An \OpenType script tag;\footnote{% - See \hyperlink {http://www.microsoft.com/typography/otspec/scripttags.htm} - for a list of valid values. - % - For scripts derived from the Latin alphabet the value - \inlinecode{latn} is good choice. - } - the default value is \inlinecode{dflt}. - % - Some fonts, including very popular ones by foundries like Adobe, - do not assign features to the \inlinecode{dflt} script, in - which case the script needs to be set explicitly. - \endaltitem - - \beginaltitem {language} - An \OpenType language system identifier,\footnote{% - Cf. \hyperlink {http://www.microsoft.com/typography/otspec/languagetags.htm}. - } - defaulting to \inlinecode{dflt}. - \endaltitem - - \beginaltitem {color} - A font color, defined as a triplet of two-digit hexadecimal - \abbrev{rgb} values, with an optional fourth value for - transparency - (where \inlinecode{00} is completely transparent and - \inlinecode{FF} is opaque). - - For example, in order to set text in semitransparent red: - - \beginlisting - \font \test = "Latin Modern Roman:color=FF0000BB" - \endlisting - \endaltitem - - \beginaltitem {kernfactor \& letterspace} - Define a font with letterspacing (tracking) enabled. - % - In \identifier{luaotfload}, letterspacing is implemented by - inserting additional kerning between glyphs. - - This approach is derived from and still quite similar to the - \emphasis{character kerning} (\texmacro{setcharacterkerning} / - \texmacro{definecharacterkerning} \& al.) functionality of - Context, see the file \fileent{typo-krn.lua} there. - % - The main difference is that \identifier{luaotfload} does not - use \LUATEX attributes to assign letterspacing to regions, - but defines virtual letterspaced versions of a font. - - The option \identifier{kernfactor} accepts a numeric value that - determines the letterspacing factor to be applied to the font - size. - % - E.~g. a kern factor of $0.42$ applied to a $10$ pt font - results in $4.2$ pt of additional kerning applied to each - pair of glyphs. - % - Ligatures are split into their component glyphs unless - explicitly ignored (see below). - - For compatibility with \XETEX an alternative - \identifier{letterspace} option is supplied that interprets the - supplied value as a \emphasis{percentage} of the font size but - is otherwise identical to \identifier{kernfactor}. - % - Consequently, both definitions in below snippet yield the same - letterspacing width: - - \beginlisting - \font \iwonakernedA = "file:Iwona-Regular.otf:kernfactor=0.125" - \font \iwonakernedB = "file:Iwona-Regular.otf:letterspace=12.5" - \endlisting - - Specific pairs of letters and ligatures may be exempt from - letterspacing by defining the \LUA functions - \luaident{keeptogether} and \luaident{keepligature}, - respectively, inside the namespace \inlinecode {luaotfload.letterspace}. - % - Both functions are called whenever the letterspacing callback - encounters an appropriate node or set of nodes. - % - If they return a true-ish value, no extra kern is inserted at - the current position. - % - \luaident{keeptogether} receives a pair of consecutive - glyph nodes in order of their appearance in the node list. - % - \luaident{keepligature} receives a single node which can be - analyzed into components. - % - (For details refer to the \emphasis{glyph nodes} section in the - \LUATEX reference manual.) - % - The implementation of both functions is left entirely to the - user. - \endaltitem - -\iffalse - \startbuffer [printvectors] - \directlua{inspect(fonts.protrusions.setups.default) - inspect(fonts.expansions.setups.default)} - \stopbuffer -\fi - - \beginaltitem {protrusion \& expansion} - These keys control microtypographic features of the font, - namely \emphasis{character protrusion} and \emphasis{font - expansion}. - % - Their arguments are names of \LUA tables that contain - values for the respective features.\footnote{% - For examples of the table layout please refer to the - section of the file \fileent{luaotfload-fonts-ext.lua} where the - default values are defined. - % - Alternatively and with loss of information, you can dump - those tables into your terminal by issuing - \unless \iffalse - \beginlisting - \directlua{inspect(fonts.protrusions.setups.default) - inspect(fonts.expansions.setups.default)} - \endlisting - \else - \typebuffer [printvectors] - \fi - at some point after loading \fileent{luaotfload.sty}. - } - % - For both, only the set \identifier{default} is predefined. - - For example, to define a font with the default - protrusion vector applied\footnote{% - You also need to set - \inlinecode {pdfprotrudechars=2} and - \inlinecode {pdfadjustspacing=2} - to activate protrusion and expansion, respectively. - See the - \hyperlink [\PDFTEX manual]{http://mirrors.ctan.org/systems/pdftex/manual/pdftex-a.pdf}% - for details. - }: - - \beginlisting - \font \test = LatinModernRoman:protrusion=default - \endlisting - \endaltitem -\enddescriptions - -\endsubsection - -\beginsubsection {Non-standard font features} -\identifier{luaotfload} adds a number of features that are not defined -in the original \OpenType specification, most of them -aiming at emulating the behavior familiar from other \TEX engines. -% -Currently (2014) there are three of them: - -\begindescriptions - - \beginaltitem {anum} - Substitutes the glyphs in the \abbrev{ascii} number range - with their counterparts from eastern Arabic or Persian, - depending on the value of \identifier{language}. - \endaltitem - - \beginaltitem {tlig} - Applies legacy \TEX ligatures\footnote{% - These contain the feature set \inlinecode {trep} of earlier - versions of \identifier{luaotfload}. - - Note to \XETEX users: this is the equivalent of the - assignment \inlinecode {mapping=text-tex} using \XETEX's input - remapping feature. - }: - - \unless \iffalse - %% Using braced arg syntax with inline code appears to be - %% impossible within Latex tables -- just ignore the weird - %% exclamation points below. - \begintabulate [rlrl] - \beginrow `` \newcell {\inlinecode !``! } \newcell '' \newcell {\inlinecode !''!} \endrow - \beginrow ` \newcell {\inlinecode !`! } \newcell ' \newcell {\inlinecode !'! } \endrow - \beginrow " \newcell {\inlinecode !"! } \newcell -- \newcell {\inlinecode !--!} \endrow - \beginrow --- \newcell {\inlinecode !---!} \newcell !` \newcell {\inlinecode ?!`?} \endrow - \beginrow ?` \newcell {\inlinecode !?`! } \newcell \newcell \endrow - \endtabulate - \else - %% XXX find a way to wrap these in the tabulate environment - \startframed [frame=off,width=broad,align=middle] - \startframed [frame=off,width=\dimexpr(\textwidth/2)] - \startxtable [align=middle] - \startxrow \startxcell `` \stopxcell \startxcell \inlinecode {``} \stopxcell \startxcell '' \stopxcell \startxcell \inlinecode {''} \stopxcell \stopxrow - \startxrow \startxcell ` \stopxcell \startxcell \inlinecode {`} \stopxcell \startxcell ' \stopxcell \startxcell \inlinecode {'} \stopxcell \stopxrow - \startxrow \startxcell " \stopxcell \startxcell \inlinecode {"} \stopxcell \startxcell -- \stopxcell \startxcell \inlinecode {--} \stopxcell \stopxrow - \startxrow \startxcell --- \stopxcell \startxcell \inlinecode {---} \stopxcell \startxcell !` \stopxcell \startxcell \inlinecode {!`} \stopxcell \stopxrow - \startxrow \startxcell ?` \stopxcell \startxcell \inlinecode {?`} \stopxcell \startxcell \stopxcell \startxcell \stopxcell \stopxrow - \stopxtable - \stopframed - \stopframed - \fi - \endaltitem - - \beginaltitem {itlc} - Computes italic correction values (active by default). - \endaltitem - -\enddescriptions - -\endsubsection -\endsection - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\beginsection {Combining fonts} -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -Version 2.7 and later support combining characters from multiple fonts into a -single virtualized one. This requires that the affected fonts be loaded in -advance as well as a special \emphasis{request syntax}. Furthermore, this -allows to define \emphasis{fallback fonts} to supplement fonts that may lack -certain required glyphs. - -Combinations are created by defining a font using the \luaident{combo:} prefix. - -\beginsubsection {Fallbacks} - -For example, the \identifier{Latin Modern} family of fonts does, as indicated -in the name, not provide Cyrillic glyphs. If Latin script dominates in the copy -with interspersed Cyrillic, a fallback can be created from a similiar looking -font like \identifier{Computer Modern Unicode}, taking advantage of the fact -that it too derives from Knuth’s original \identifier{Computer Modern} series: - -\beginlisting - \input luaotfload.sty - \font \lm = file:lmroman10-regular.otf:mode=base - \font \cmu = file:cmunrm.otf:mode=base - \font \lmu = "combo: 1->\fontid\lm; 2->\fontid\cmu,fallback" - \lmu Eh bien, mon prince. Gênes et Lueques ne sont plus que des - apanages, des поместья, de la famille Buonaparte. - \bye -\endlisting - -As simple as this may look on the first glance, this approach is entirely -inappropriate if more than a couple letters are required from a different font. -Because the combination pulls nothing except the glyph data, all of the -important other information that constitute a proper font -- kerning, styles, -features, and suchlike -- will be missing. - -\endsubsection %% Fallbacks - -\beginsubsection {Combinations} - -Generalizing the idea of a \emphasis{fallback font}, it is also possible to -pick definite sets of glyphs from multiple fonts. On a bad day, for instance, -it may be the sanest choice to start out with \identifier{EB Garamond} italics, -typeset all decimal digits in the bold italics of \identifier{GNU Freefont}, -and tone down the punctuation with extra thin glyphs from \identifier{Source -Sans}: - -\beginlisting - \def \feats {-tlig;-liga;mode=base;-kern} - \def \fileone {EBGaramond12-Italic.otf} - \def \filetwo {FreeMonoBoldOblique.otf} - \def \filethree {SourceSansPro-ExtraLight.otf} - - \input luaotfload.sty - - \font \one = file:\fileone :\feats - \font \two = file:\filetwo :\feats - \font \three = file:\filethree:\feats - - \font \onetwothree = "combo: 1 -> \fontid\one; - 2 -> \fontid\two, 0x30-0x39; - 3 -> \fontid\three, 0x21*0x3f; " - - {\onetwothree \TeX—0123456789—?!} - \bye -\endlisting - -\noindent Despite the atrocious result, the example demonstrates well the -syntax that is used to specify ranges and fonts. Fonts are being referred to by -their internal index which can be obtained by passing the font command into the -\texmacro{fontid} macro, e. g. \inlinecode{\fontid\one}, after a font has been -defined. The first component of the combination is the base font which will be -extended by the others. It is specified by the index alone. - -All further fonts require either the literal \inlinecode{fallback} or a list of -codepoint definitions to be appended after a comma. The elements of this list -again denote either single codepoints like \inlinecode{0x21} (referring to the -exclamation point character) or ranges of codepoints (\inlinecode{0x30-0x39}). -Elements are separated by the \identifier{ASCII} asterisk character -(\inlinecode{*}). The characters referenced in the list will be imported from -the respective font, if available. - -\endsubsection %% Combinations - -\endsection - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\beginsection {Font names database} -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\label{sec:fontdb} - -As mentioned above, \identifier{luaotfload} keeps track of which -fonts are available to \LUATEX by means of a \emphasis{database}. -% -This allows referring to fonts not only by explicit filenames but -also by the proper names contained in the metadata which is often -more accessible to humans.\footnote{% - The tool \hyperlink[\fileent{otfinfo}]{http://www.lcdf.org/type/} - (comes with \TEX Live), when invoked on a font file with the - \inlinecode {-i} option, lists the variety of name fields defined for - it. -} - -When \identifier{luaotfload} is asked to load a font by a font name, -it will check if the database exists and load it, or else generate a -fresh one. -% -Should it then fail to locate the font, an update to the database is -performed in case the font has been added to the system only -recently. -% -As soon as the database is updated, the resolver will try -and look up the font again, all without user intervention. -% -The goal is for \identifier{luaotfload} to act in the background and -behave as unobtrusively as possible, while providing a convenient -interface to the fonts installed on the system. - -Generating the database for the first time may take a while since it -inspects every font file on your computer. -% -This is particularly noticeable if it occurs during a typesetting run. -In any case, subsequent updates to the database will be quite fast. - -\beginsubsection[luaotfload-tool] - {\fileent{luaotfload-tool}} - -It can still be desirable at times to do some of these steps -manually, and without having to compile a document. -% -To this end, \identifier{luaotfload} comes with the utility -\fileent{luaotfload-tool} that offers an interface to the database -functionality. -% -Being a \LUA script, there are two ways to run it: -either make it executable (\inlinecode {chmod +x} on unixoid systems) or -pass it as an argument to \fileent{texlua}.\footnote{% - Tests by the maintainer show only marginal performance gain by - running with Luigi Scarso’s - \hyperlink [\identifier{Luajit\kern-.25ex\TEX}]{https://foundry.supelec.fr/projects/luajittex/}, - which is probably due to the fact that most of the time is spent - on file system operations. - - \emphasis{Note}: - On \abbrev{MS} \identifier{Windows} systems, the script can be run - either by calling the wrapper application - \fileent{luaotfload-tool.exe} or as - \inlinecode {texlua.exe luaotfload-tool.lua}. -} -% -Invoked with the argument \inlinecode {--update} it will perform a database -update, scanning for fonts not indexed. - -\beginlisting - luaotfload-tool --update -\endlisting - -Adding the \inlinecode {--force} switch will initiate a complete -rebuild of the database. - -\beginlisting - luaotfload-tool --update --force -\endlisting - -\endsubsection - -\beginsubsection{Search Paths} - -\identifier{luaotfload} scans those directories where fonts are -expected to be located on a given system. -% -On a Linux machine it follows the paths listed in the -\identifier{Fontconfig} configuration files; -consult \inlinecode {man 5 fonts.conf} for further information. -% -On \identifier{Windows} systems, the standard location is -\inlinecode {Windows\\Fonts}, -% -while \identifier{Mac OS~X} requires a multitude of paths to -be examined. -% -The complete list is is given in table \ref{table-searchpaths}. -Other paths can be specified by setting the environment variable -\inlinecode {OSFONTDIR}. -% -If it is non-empty, then search will be extended to the included -directories. - -\tablefloat {table-searchpaths} - {List of paths searched for each supported operating system.} - {% - \unless \iffalse - \begincentered - \begintabulate [lp{.5\textwidth}] - \beginrow - Windows \newcell \inlinecode !\% WINDIR\%\\ Fonts! - \endrow - \beginrow - Linux \newcell \fileent{/usr/local/etc/fonts/fonts.conf} and\hfill\break - \fileent{/etc/fonts/fonts.conf} - \endrow - \beginrow - Mac \newcell \fileent{\textasciitilde/Library/Fonts},\break - \fileent{/Library/Fonts},\break - \fileent{/System/Library/Fonts}, and\hfill\break - \fileent{/Network/Library/Fonts} - \endrow - \endtabulate - \endcentered - \else - \setuplocalinterlinespace [14pt] - \starttabulate [|l|p(.5\textwidth)|] - \NC Windows \NC \inlinecode {\% WINDIR\%\\ Fonts} \NC \NR - \NC Linux \NC \fileent{/usr/local/etc/fonts/fonts.conf} and\crlf - \fileent{/etc/fonts/fonts.conf} \NC \NR - \NC - Mac \NC \fileent{\textasciitilde/Library/Fonts},\crlf - \fileent{/Library/Fonts},\break - \fileent{/System/Library/Fonts}, and\crlf - \fileent{/Network/Library/Fonts} \NC \NR - \stoptabulate - \fi% - } - -\endsubsection - -\beginsubsection{Querying from Outside} - -\fileent{luaotfload-tool} also provides rudimentary means of -accessing the information collected in the font database. -% -If the option \inlinecode {--find=}\emphasis{name} is given, the script will -try and search the fonts indexed by \identifier{luaotfload} for a -matching name. -% -For instance, the invocation - -\beginlisting - luaotfload-tool --find="Iwona Regular" -\endlisting - -\noindent -will verify if “Iwona Regular” is found in the database and can be -readily requested in a document. - -If you are unsure about the actual font name, then add the -\inlinecode {-F} (or \inlinecode {--fuzzy}) switch to the command line to enable -approximate matching. -% -Suppose you cannot precisely remember if the variant of -\identifier{Iwona} you are looking for was “Bright” or “Light”. -The query - -\beginlisting - luaotfload-tool -F --find="Iwona Bright" -\endlisting - -\noindent -will tell you that indeed the latter name is correct. - -Basic information about fonts in the database can be displayed -using the \inlinecode {-i} option (\inlinecode {--info}). -% -\beginlisting - luaotfload-tool -i --find="Iwona Light Italic" -\endlisting -% -\noindent -The meaning of the printed values is described in section 4.4 of the -\LUATEX reference manual.\footnote{% - In \TEX Live: \fileent{texmf-dist/doc/luatex/base/luatexref-t.pdf}. -} - -For a much more detailed report about a given font try the -\inlinecode {-I} option instead (\inlinecode {--inspect}). -\beginlisting - luaotfload-tool -I --find="Iwona Light Italic" -\endlisting - -\inlinecode {luaotfload-tool --help} will list the available command line -switches, including some not discussed in detail here. -% -For a full documentation of \identifier{luaotfload-tool} and its -capabilities refer to the manpage -(\inlinecode {man 1 luaotfload-tool}).\footnote{% - Or see \inlinecode {luaotfload-tool.rst} in the source directory. -} - -\endsubsection - -\beginsubsection {Blacklisting Fonts} -\label{font-blacklist} - -Some fonts are problematic in general, or just in \LUATEX. -% -If you find that compiling your document takes far too long or eats -away all your system’s memory, you can track down the culprit by -running \inlinecode {luaotfload-tool -v} to increase verbosity. -% -Take a note of the \emphasis{filename} of the font that database -creation fails with and append it to the file -\fileent{luaotfload-blacklist.cnf}. - -A blacklist file is a list of font filenames, one per line. -Specifying the full path to where the file is located is optional, the -plain filename should suffice. -% -File extensions (\fileent{.otf}, \fileent{.ttf}, etc.) may be omitted. -% -Anything after a percent (\inlinecode {\%}) character until the end of the line -is ignored, so use this to add comments. -% -Place this file to some location where the \identifier{kpse} -library can find it, e.~g. -\fileent{texmf-local/tex/luatex/luaotfload} if you are running -\identifier{\TEX Live},\footnote{% - You may have to run \inlinecode {mktexlsr} if you created a new file in - your \fileent{texmf} tree. -} -or just leave it in the working directory of your document. -% -\identifier{luaotfload} reads all files named -\fileent{luaotfload-blacklist.cnf} it finds, so the fonts in -\fileent{./luaotfload-blacklist.cnf} extend the global blacklist. - -Furthermore, a filename prepended with a dash character (\inlinecode{-}) is -removed from the blacklist, causing it to be temporarily whitelisted -without modifying the global file. -% -An example with explicit paths: - -\beginlisting -% example otf-blacklist.cnf -/Library/Fonts/GillSans.ttc % Luaotfload ignores this font. --/Library/Fonts/Optima.ttc % This one is usable again, even if - % blacklisted somewhere else. -\endlisting - -\endsubsection -\endsection - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\beginsection {The Fontloader} -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\beginsubsection {Overview} - -To a large extent, \identifier{luaotfload} relies on code originally -written by Hans Hagen for the -\hyperlink[\identifier{\CONTEXT}]{http://wiki.contextgarden.net} -format. -% -It integrates the font loader, written entirely in \LUA, as distributed -in the \identifier{\LUATEX-Fonts} package. -% -The original \LUA source files have been combined using the \CONTEXT -packaging library into a single, self-contained blob. In -this form the font loader depends only on the \identifier{lualibs} -package and requires only minor adaptions to integrate into -\identifier{luaotfload}. - -The guiding principle is to let \CONTEXT/\LUATEX-Fonts take care of the -implementation, and update the imported code as frequently as -necessary. -% -As maintainers, we aim at importing files from upstream essentially -\emphasis{unmodified}, except for renaming them to prevent name -clashes. -% -This job has been greatly alleviated since the advent of -\LUATEX-Fonts, prior to which the individual dependencies had to be -manually spotted and extracted from the \CONTEXT source code in a -complicated and error-prone fashion. - -\endsubsection - -\beginsubsection {Contents and Dependencies} - -Below is a commented list of the files distributed with -\identifier{luaotfload} in one way or the other. -% -See figure \ref{file-graph} on page \pageref{file-graph} for a -graphical representation of the dependencies. -% -\label{package}% -Through the script \fileent{mkimport} a \CONTEXT library -is invoked to create the \identifier{luaotfload} fontloader as a merged -(amalgamated) source file.\footnote{% - In \CONTEXT, this facility can be accessed by means of a - \hyperlink[script]{https://bitbucket.org/phg/context-mirror/src/beta/scripts/context/lua/mtx-package.lua?at=beta} - which is integrated into \fileent{mtxrun} as a subcommand. - Run \inlinecode {mtxrun --script package --help} to display further - information. - For the actual merging code see the file - \fileent{util-mrg.lua} that is part of \CONTEXT. -} -% -This file constitutes the “default fontloader” and is part of the -\identifier{luaotfload} package as \fileent{fontloader-YY-MM-DD.lua}, -where the uppercase letters are placeholders for the build date. -% -A companion to it, \fileent{luatex-basics-gen.lua} must be loaded -beforehand to set up parts of the environment required by the \CONTEXT -libraries. -% -During a \TEX\ run, the fontloader initialization and injection happens -in the module \fileent{luaotfload-init.lua}. -% -Additionally, the “reference fontloader” as imported from \LUATEX-Fonts -is provided as the file \fileent{fontloader-reference.lua}. -% -This file is self-contained in that it packages all the auxiliary \LUA -libraries too, as Luaotfload did up to the 2.5 series; since that job -has been offloaded to the \identifier{Lualibs} package, loading this -fontloader introduces a certain code duplication. - -A number of \emphasis{\LUA utility libraries} are not part of the -\identifier{luaotfload} fontloader, contrary to its equivalent in -\LUATEX-Fonts. These are already provided by the \identifier{lualibs} -and have thus been omitted from the merge.\footnote{% - Faithful listeners will remember the pre-2.6 era when the fontloader - used to be integrated as-is which caused all kinds of code - duplication with the pervasive \identifier{lualibs} package. - This conceptual glitch has since been amended by tightening the - coupling with the excellent \CONTEXT\ toolchain. -} - -\begindoublecolumns - \begindefinitions - \beginaltitem {l-lua.lua} \endaltitem - \beginaltitem {l-lpeg.lua} \endaltitem - \beginaltitem {l-function.lua} \endaltitem - \beginaltitem {l-string.lua} \endaltitem - \beginaltitem {l-table.lua} \endaltitem - \beginaltitem {l-io.lua} \endaltitem - \beginaltitem {l-file.lua} \endaltitem - \beginaltitem {l-boolean.lua} \endaltitem - \beginaltitem {l-math.lua} \endaltitem - \beginaltitem {util-str.lua} \endaltitem - \beginaltitem {util-fil.lua} \endaltitem - \enddefinitions -\enddoublecolumns - -The reference fontloader is home to several \LUA files that can be -grouped twofold as below: - -\begindefinitions - \beginnormalitem - The \emphasis{font loader} itself. - These files have been written for \LUATEX-Fonts and they are - distributed along with \identifier{luaotfload} so as to resemble - the state of the code when it was imported. Their purpose is either - to give a slightly aged version of a file if upstream considers - latest developments for not yet ready for use outside Context; or, - to install placeholders or minimalist versions of APIs relied upon - but usually provided by parts of Context not included in the - fontloader. - \begindoublecolumns - \begindefinitions - \beginaltitem{luatex-basics-nod.lua} \endaltitem - \beginaltitem{luatex-basics-chr.lua} \endaltitem - \beginaltitem{luatex-fonts-enc.lua} \endaltitem - \beginaltitem{luatex-fonts-syn.lua} \endaltitem - \beginaltitem{luatex-fonts-ext.lua} \endaltitem - \enddefinitions - \enddoublecolumns - \endnormalitem - - \beginnormalitem - Code related to \emphasis{font handling and node processing}, taken - directly from \CONTEXT. - \begindoublecolumns - \begindefinitions - \beginaltitem{data-con.lua} \endaltitem - \beginaltitem{font-ini.lua} \endaltitem - \beginaltitem{font-con.lua} \endaltitem - \beginaltitem{font-cid.lua} \endaltitem - \beginaltitem{font-map.lua} \endaltitem - \beginaltitem{font-tfm.lua} \endaltitem - \beginaltitem{font-one.lua} \endaltitem - \beginaltitem{font-afk.lua} \endaltitem - \beginaltitem{font-oti.lua} \endaltitem - \beginaltitem{font-otr.lua} \endaltitem - \beginaltitem{font-cff.lua} \endaltitem - \beginaltitem{font-ttf.lua} \endaltitem - \beginaltitem{font-dsp.lua} \endaltitem - \beginaltitem{font-oup.lua} \endaltitem - \beginaltitem{font-otl.lua} \endaltitem - \beginaltitem{font-oto.lua} \endaltitem - \beginaltitem{font-otj.lua} \endaltitem - \beginaltitem{font-ota.lua} \endaltitem - \beginaltitem{font-ots.lua} \endaltitem - \beginaltitem{font-osd.lua} \endaltitem - \beginaltitem{font-ocl.lua} \endaltitem - \beginaltitem{font-lua.lua} \endaltitem - \beginaltitem{font-def.lua} \endaltitem - \beginaltitem{font-xtx.lua} \endaltitem - \beginaltitem{font-gbn.lua} \endaltitem - \enddefinitions - \enddoublecolumns - \endnormalitem -\enddefinitions - -As an alternative to the merged file, \identifier {Luaotfload} may load -individual unpackaged \LUA libraries that come with the source, or even -use the files from Context directly. -% -Thus if you prefer running bleeding edge code from the \CONTEXT beta, -choose the \inlinecode {context} fontloader via the configuration file -(see sections \ref{sec:conf} and \ref{sec:pkg} below). - -Also, the merged file at some point loads the Adobe Glyph List from a -\LUA table that is contained in \fileent{luaotfload-glyphlist.lua}, -which is automatically generated by the script -\fileent{mkglyphlist}.\footnote{% - See \fileent{luaotfload-font-enc.lua}. - The hard-coded file name is why we have to replace the procedure - that loads the file in \fileent{luaotfload-init.lua}. -} -% -There is a make target \identifier{glyphs} that will create a fresh -glyph list 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 latter. - - -\beginfilelist - \beginaltitem {luaotfload-features.lua} - font feature handling; incorporates some of the code from - \fileent{font-otc} from \CONTEXT; - \endaltitem - \beginaltitem {luaotfload-configuration.lua} - handling of \fileent{luaotfload.conf(5)}. - \endaltitem - \beginaltitem {luaotfload-log.lua} - overrides the \CONTEXT logging functionality. - \endaltitem - \beginaltitem {luaotfload-loaders.lua} - registers readers in the fontloader for various kinds of - font formats - \endaltitem - \beginaltitem {luaotfload-parsers.lua} - various \abbrev{lpeg}-based parsers. - \endaltitem - \beginaltitem {luaotfload-database.lua} - font names database. - \endaltitem - \beginaltitem {luaotfload-resolvers.lua} - file name resolvers. - \endaltitem - \beginaltitem {luaotfload-colors.lua} - color handling. - \endaltitem - \beginaltitem {luaotfload-auxiliary.lua} - access to internal functionality for package authors (proposals - for additions welcome). - \endaltitem - \beginaltitem {luaotfload-letterspace.lua} - font-based letterspacing. - \endaltitem -\endfilelist - -\figurefloat - {file-graph} - {Schematic of the files in \identifier{Luaotfload}} - {filegraph.pdf} - -\endsubsection - -\beginsubsection {Packaging} - -\label{sec:pkg}% -The fontloader code is integrated as an isolated component that can be -switched out on demand. -% -To specify the fontloader you wish to use, the configuration file -(described in section \ref{sec:conf}) provides the option -\inlinecode{fontloader}. -% -Its value can be one of the identifiers \inlinecode{default} or -\inlinecode{reference} (see above, section \ref{package}) or the name -of a file somewhere in the search path of \LUATEX. -% -This will make \identifier {Luaotfload} locate the \CONTEXT source by -means of \identifier{kpathsea} lookups and use those instead of the -merged package. -% -The parameter may be extended with a path to the \CONTEXT -\fileent{texmf}, separated with a colon: - -\beginlisting -[run] - fontloader = context:~/context/tex/texmf-context -\endlisting - -\noindent This setting allows accessing an installation -- e. g. the -standalone distribution or a source repository -- outside the current -\TEX distribution. - -Like the \identifier{Lualibs} package, the fontloader is deployed as a -\emphasis{merged package} containing a series of \LUA files joined -together in their expected order and stripped of non-significant parts. -% -The \fileent{mkimport} utility assists in pulling the files from a -\CONTEXT tree and packaging them for use with \identifier{Luaotfload}.% -% -The state of the files currently in \identifier{Luaotfload}’s -repository can be queried: -\beginlisting -./scripts/mkimport news -\endlisting -% -The subcommand for importing takes the prefix of the desired \CONTEXT -\identifier{texmf} as an optional argument: -\beginlisting -./scripts/mkimport import ~/context/tex/texmf-context -\endlisting -% -Whereas the command for packaging requires a path to the -\emphasis{package description file} and the output name to be passed. -\beginlisting -./scripts/mkimport package fontloader-custom.lua -\endlisting - -From the toplevel makefile, the targets \inlinecode{import} and -\inlinecode{package} provide easy access to the commands as invoked during -the \identifier{Luaotfload} build process.\footnote{% - \emphasis{Hint for those interested in the packaging process}: issue - \inlinecode{make show} for a list of available build routines. -} -These will call \inlinecode{mkimport} script with the correct -parameters to generate a datestamped package. -% -Whether files have been updated in the upstream distribution can be -queried by \inlinecode{./scripts/mkimport news}. -% -This will compare the imported files with their counterparts in the -\CONTEXT distribution and report changes. - -\endsubsection - -\endsection - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\beginsection {Configuration Files} -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\beginnarrower - \emphasis{Caution}: For the authoritative documentation, consult the - manpage for \fileent{luaotfload.conf(5)}. -\endnarrower - -\label{sec:conf} -The runtime behavior of \identifier{Luaotfload} can be customized by -means of a configuration file. -% location -At startup, it attempts to locate a file called \fileent -{luaotfload.conf} or \fileent {luaotfloadrc} at a number of candidate -locations: - -\begincentered - \begindefinitions - \beginnormalitem \fileent{./luaotfload.conf} \endnormalitem - \beginnormalitem \fileent{./luaotfloadrc} \endnormalitem - \beginnormalitem \fileent{\$XDG_CONFIG_HOME/luaotfload/luaotfload.conf} \endnormalitem - \beginnormalitem \fileent{\$XDG_CONFIG_HOME/luaotfload/luaotfload.rc} \endnormalitem - \beginnormalitem \fileent{~/.luaotfloadrc} \endnormalitem - \enddefinitions -\endcentered - -\beginnarrower - \emphasis{Caution}: The configuration potentially modifies the final - document. A project-local file belongs under version control along - with the rest of the document. This is to ensure that everybody who - builds the project also receives the same customizations as the - author. -\endnarrower - -% syntax -The syntax is fairly close to the format used by -\fileent{git-config(1)} which in turn was derived from the popular -\identifier{.INI} format: Lines of key-value pairs are grouped under -different configuration “sections”.\footnote{% - The configuration parser in \fileent {luoatfload-parsers.lua} might - be employed by other packages for similar purposes. -} -% example settings -An example for customization via \fileent {luaotfload.conf} might look -as below: - -\beginlisting -; Example luaotfload.conf containing a rudimentary configuration -[db] - update-live = false -[run] - color-callback = pre_linebreak_filter - definer = info_patch - log-level = 5 -[default-features] - global = mode=base -\endlisting - -This specifies that for the given project, \identifier{Luaotfload} -shall not attempt to automatically scan for fonts if it can’t resolve a -request. The font-based colorization will happen during \LUATEX’s -pre-linebreak filter. The fontloader will output verbose information -about the fonts at definition time along with globally increased -verbosity. Lastly, the fontloader defaults to the less expensive -\luaident{base} mode like it does in \CONTEXT. - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\beginsection {Auxiliary Functions} -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -With release version 2.2, \identifier{Luaotfload} received -additional functions for package authors to call from outside -(see the file \fileent{luaotfload-auxiliary.lua} for details). -% -The purpose of this addition twofold. -% -Firstly, \identifier{luaotfload} failed to provide a stable interface -to internals in the past which resulted in an unmanageable situation -of different packages abusing the raw access to font objects by means -of the \luaident{patch_font} callback. -% -When the structure of the font object changed due to an update, all -of these imploded and several packages had to be fixed while -simultaneously providing fallbacks for earlier versions. -% -Now the patching is done on the \identifier{luaotfload} side and can -be adapted with future modifications to font objects without touching -the packages that depend on it. -% -Second, some the capabilities of the font loader and the names -database are not immediately relevant in \identifier{luaotfload} -itself but might nevertheless be of great value to package authors or -end users. - -Note that the current interface is not yet set in stone and the -development team is open to suggestions for improvements or -additions. - -\beginsubsection {Callback Functions} - -The \luaident{patch_font} callback is inserted in the wrapper -\identifier{luaotfload} provides for the font definition callback. -% -At this place it allows manipulating the font object immediately after -the font loader is done creating it. -% -For a short demonstration of its usefulness, here is a snippet that -writes an entire font object to the file \fileent{fontdump.lua}: - -\beginlisting - \input luaotfload.sty - \directlua{ - local dumpfile = "fontdump.lua" - local dump_font = function (tfmdata) - local data = table.serialize(tfmdata) - io.savedata(dumpfile, data) - end - - luatexbase.add_to_callback( - "luaotfload.patch_font", - dump_font, - "my_private_callbacks.dump_font" - ) - } - \font \dumpme = name:Iwona - \bye -\endlisting - -\emphasis{Beware}: this creates a Lua file of around 150,000 lines of -code, taking up 3~\abbrev{mb} of disk space. -% -By inspecting the output you can get a first impression of how a font -is structured in \LUATEX’s memory, what elements it is composed of, -and in what ways it can be rearranged. - -\beginsubsubsection {Compatibility with Earlier Versions} - -As has been touched on in the preface to this section, the structure -of the object as returned by the fontloader underwent rather drastic -changes during different stages of its development, and not all -packages that made use of font patching have kept up with every one -of it. -% -To ensure compatibility with these as well as older versions of -some packages, \identifier{luaotfload} sets up copies of or references -to data in the font table where it used to be located. -% -For instance, important parameters like the requested point size, the -units factor, and the font name have again been made accessible from -the toplevel of the table even though they were migrated to different -subtables in the meantime. - -\endsubsubsection - -\beginsubsubsection{Patches} - -These are mostly concerned with establishing compatibility with \XETEX. - -\beginfunctionlist - - \beginaltitem {set_sscale_dimens} - Calculate \texmacro{fontdimen}s 10 and 11 to emulate \XETEX. - \endaltitem - - \beginaltitem {set_capheight} - Calculates \texmacro{fontdimen} 8 like \XETEX. - \endaltitem - - \beginaltitem {patch_cambria_domh} - Correct some values of the font \emphasis{Cambria Math}. - \endaltitem - -\endfunctionlist - -\endsubsection - -\beginsubsection {Package Author’s Interface} - -As \LUATEX release 1.0 is nearing, the demand for a reliable interface -for package authors increases. - -\endsubsubsection - -\beginsubsubsection{Font Properties} - -Below functions mostly concern querying the different components of a -font like for instance the glyphs it contains, or what font features -are defined for which scripts. - -\beginfunctionlist - - \beginaltitem {aux.font_has_glyph (id : int, index : int)} - Predicate that returns true if the font \luaident{id} - has glyph \luaident{index}. - \endaltitem - - \beginaltitem {aux.slot_of_name(name : string)} - Translates an Adobe Glyph name to the corresponding glyph - slot. - \endaltitem - - \beginaltitem {aux.name_of_slot(slot : int)} - The inverse of \luaident{slot_of_name}; note that this - might be incomplete as multiple glyph names may map to the - same codepoint, only one of which is returned by - \luaident{name_of_slot}. - \endaltitem - - \beginaltitem {aux.provides_script(id : int, script : string)} - Test if a font supports \luaident{script}. - \endaltitem - - \beginaltitem {aux.provides_language(id : int, script : string, language : string)} - Test if a font defines \luaident{language} for a given - \luaident{script}. - \endaltitem - - \beginaltitem {aux.provides_feature(id : int, script : string, - language : string, feature : string)} - Test if a font defines \luaident{feature} for - \luaident{language} for a given \luaident{script}. - \endaltitem - - \beginaltitem {aux.get_math_dimension(id : int, dimension : string)} - Get the dimension \luaident{dimension} of font \luaident{id}. - \endaltitem - - \beginaltitem {aux.sprint_math_dimension(id : int, dimension : string)} - Same as \luaident{get_math_dimension()}, but output the value - in scaled points at the \TEX end. - \endaltitem - -\endfunctionlist - -\endsubsubsection - -\beginsubsubsection{Database} - -%% not implemented, may come back later -\beginfunctionlist -% \beginaltitem {aux.scan_external_dir(dir : string)} -% Include fonts in directory \luaident{dir} in font lookups without -% adding them to the database. -% - \beginaltitem {aux.read_font_index (void)} - Read the index file from the appropriate location (usually - the bytecode file \fileent{luaotfload-names.luc} somewhere - in the \fileent{texmf-var} tree) and return the result as a - table. The file is processed with each call so it is up to - the user to store the result for later access. - \endaltitem - - \beginaltitem {aux.font_index (void)} - Return a reference of the font names table used internally - by \identifier{luaotfload}. The index will be read if it - has not been loaded up to this point. Also a font scan that - overwrites the current index file might be triggered. Since - the return value points to the actual index, any - modifications to the table might influence runtime behavior - of \identifier{luaotfload}. - \endaltitem - -\endfunctionlist - -\endsubsubsection - -\endsubsection -\endsection - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\beginsection {Troubleshooting} -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\beginsubsection {Database Generation} - -If you encounter problems with some fonts, please first update to the -latest 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 -\hyperlink {https://github.com/lualatex/luaotfload} where there is an issue -tracker for submitting bug reports, feature requests and the likes. - -Bug reports are more likely to be addressed if they contain the output -of - -\beginlisting - luaotfload-tool --diagnose=environment,files,permissions -\endlisting - -\noindent Consult the man page for a description of these options. - -Errors during database generation can be traced by increasing the -verbosity level and redirecting log output to \fileent{stdout}: - -\beginlisting - luaotfload-tool -fuvvv --log=stdout -\endlisting - -\noindent or to a file in \fileent{/tmp}: - -\beginlisting - luaotfload-tool -fuvvv --log=file -\endlisting - -\noindent In the latter case, invoke the \inlinecode {tail(1)} utility on the -file for live monitoring of the progress. - -If database generation fails, the font last printed to the terminal or -log file is likely to be the culprit. -% -Please specify it when reporting a bug, and blacklist it for the time -being (see above, page \pageref{font-blacklist}). - -\endsubsection - -\beginsubsection {Font Features} - -A common problem is the lack of features for some -\OpenType fonts even when specified. -% -This can be related to the fact that some fonts do not provide features -for the \inlinecode {dflt} script (see above on page \pageref{script-tag}), -which is the default one in this package. -% -If this happens, assigning a noth script when the font is defined should -fix it. -% -For example with \inlinecode {latn}: - -\beginlisting - \font \test = file:MyFont.otf:script=latn;+liga; -\endlisting - -You can get a list of features that a font defines for scripts and -languages by querying it in \fileent{luaotfload-tool}: - -\beginlisting - luaotfload-tool --find="Iwona" --inspect -\endlisting - -\endsubsection - -\beginsubsection {\LUATEX Programming} - -Another strategy that helps avoiding problems is to not access raw -\LUATEX internals directly. -% -Some of them, even though they are dangerous to access, have not been -overridden or disabled. -% -Thus, whenever possible prefer the functions in the \luaident{aux} -namespace over direct manipulation of font objects. For example, raw -access to the \luaident{font.fonts} table like: - -\beginlisting - local somefont = font.fonts[2] -\endlisting - -\noindent can render already defined fonts unusable. -% -Instead, the function \luaident{font.getfont()} should be used -because it has been replaced by a safe variant. - -However, \luaident{font.getfont()} only covers fonts handled by the -font loader, e.~g. \identifier{OpenType} and \identifier{TrueType} -fonts, but not \abbrev{tfm} or \abbrev{ofm}. -% -Should you absolutely require access to all fonts known to \LUATEX, -including the virtual and autogenerated ones, then you need to query -both \luaident{font.getfont()} and \luaident{font.fonts}. -% -In this case, best define you own accessor: - -\beginlisting - local unsafe_getfont = function (id) - local tfmdata = font.getfont (id) - if not tfmdata then - tfmdata = font.fonts[id] - end - return tfmdata - end - - --- use like getfont() - local somefont = unsafe_getfont (2) -\endlisting - -\endsubsection -\endsection - -\beginsection {License} - -\identifier {luaotfload} is licensed under the terms of the -\hyperlink [GNU General Public License version 2.0]% - {https://www.gnu.org/licenses/old-licenses/gpl-2.0.html}. -Following the underlying fontloader code \identifier {luaotfload} -recognizes only that exact version as its license. -The „any later version” clause of the original license text as -copyrighted by the \hyperlink [Free Software Foundation]{http://www.fsf.org/} -\emphasis {does not apply} to either \identifier {luaotfload} or the -code imported from \CONTEXT. - -The complete text of the license is given as a separate file \fileent -{COPYING} in the toplevel directory of the -\hyperlink [\fileent {Luaotfload} Git repository]{https://github.com/lualatex/luaotfload/blob/master/COPYING}. -Distributions probably package it as \fileent -{doc/luatex/luaotfload/COPYING} in the relevant \fileent {texmf} tree. - -\endsection - -\endinput - -% vim:ft=tex:tw=79:et:sw=2 diff --git a/tex/compat/luaotfload/luaotfload-parsers.lua b/tex/compat/luaotfload/luaotfload-parsers.lua deleted file mode 100644 index b188bb0d28c6a26bf275b353b5043fa269ba79d5..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/luaotfload-parsers.lua +++ /dev/null @@ -1,817 +0,0 @@ -#!/usr/bin/env texlua -------------------------------------------------------------------------------- --- FILE: luaotfload-parsers.lua --- DESCRIPTION: various lpeg-based parsers used in Luaotfload --- REQUIREMENTS: Luaotfload >= 2.8 --- AUTHOR: Philipp Gesang (Phg), <phg@phi-gamma.net> -------------------------------------------------------------------------------- --- - -local traversal_maxdepth = 42 --- prevent stack overflows - -local rawset = rawset - -local lpeg = require "lpeg" -local patterns = lpeg.patterns -local P, R, S, V = lpeg.P, lpeg.R, lpeg.S, lpeg.V -local lpegmatch = lpeg.match -local C, Cc, Cf = lpeg.C, lpeg.Cc, lpeg.Cf -local Cg, Cmt, Cs, Ct = lpeg.Cg, lpeg.Cmt, lpeg.Cs, lpeg.Ct - -local kpse = kpse -local kpseexpand_path = kpse.expand_path -local kpsereadable_file = kpse.readable_file - -local file = file -local filejoin = file.join -local filedirname = file.dirname - -local io = io -local ioopen = io.open - -local logreport = print - -local string = string -local stringsub = string.sub -local stringfind = string.find -local stringlower = string.lower - -local mathceil = math.ceil - -local lfs = lfs -local lfsisfile = lfs.isfile -local lfsisdir = lfs.isdir - -------------------------------------------------------------------------------- ---- COMMON PATTERNS -------------------------------------------------------------------------------- - -local asterisk = P"*" -local dot = P"." -local colon = P":" -local semicolon = P";" -local comma = P"," -local noncomma = 1 - comma -local slash = P"/" -local backslash = P"\\" -local equals = P"=" -local dash = P"-" -local gartenzaun = P"#" -local lbrk, rbrk = P"[", P"]" -local brackets = lbrk + rbrk -local squote = P"'" -local dquote = P"\"" - -local newline = P"\n" -local returnchar = P"\r" -local spacing = S" \t\v" -local linebreak = S"\n\r" -local whitespace = spacing + linebreak -local ws = spacing^0 -local xmlws = whitespace^1 -local eol = P"\n\r" + P"\r\n" + linebreak - -local digit = R"09" -local alpha = R("az", "AZ") -local anum = alpha + digit -local decimal = digit^1 * (dot * digit^0)^-1 -local hexdigit = R("09", "af", "AF") -local hex = P"0x" * hexdigit^1 - -------------------------------------------------------------------------------- ---- FONTCONFIG -------------------------------------------------------------------------------- - ---[[doc-- - - For fonts installed on the operating system, there are several - options to make Luaotfload index them: - - - If OSFONTDIR is set (which is the case under windows by default - but not on the other OSs), it scans it at the same time as the - texmf tree, in the function scan_texmf_fonts(). - - - Otherwise - - under Windows and Mac OSX, we take a look at some hardcoded - directories, - - under Unix, it reads /etc/fonts/fonts.conf and processes the - directories specified there. - - This means that if you have fonts in fancy directories, you need to - set them in OSFONTDIR. - - Beware: OSFONTDIR is a kpathsea variable, so fonts found in these - paths, though technically system fonts, are registered in the - category “texmf”, not “system”. This may have consequences for the - lookup order when a font file (or a font with the same name - information) is located in both the system and the texmf tree. - ---doc]]-- - -local tag_name = C(alpha^1) -local comment = P"<!--" * (1 - P"--")^0 * P"-->" - ----> header specifica -local xml_declaration = P"<?xml" * (1 - P"?>")^0 * P"?>" -local xml_doctype = P"<!DOCTYPE" * xmlws - * "fontconfig" * (1 - P">")^0 * P">" -local header = xml_declaration^-1 - * (xml_doctype + comment + xmlws)^0 - ----> enforce root node -local root_start = P"<" * xmlws^-1 * P"fontconfig" * xmlws^-1 * P">" -local root_stop = P"</" * xmlws^-1 * P"fontconfig" * xmlws^-1 * P">" - -local dquote, squote = P[["]], P"'" -local xml_namestartchar = S":_" + alpha --- ascii only, funk the rest -local xml_namechar = S":._" + alpha + digit -local xml_name = xmlws^-1 - * C(xml_namestartchar * xml_namechar^0) -local xml_attvalue = dquote * C((1 - S[[%&"]])^1) * dquote * xmlws^-1 - + squote * C((1 - S[[%&']])^1) * squote * xmlws^-1 -local xml_attr = Cg(xml_name * P"=" * xml_attvalue) -local xml_attr_list = Cf(Ct"" * xml_attr^1, rawset) - ---[[doc-- - scan_node creates a parser for a given xml tag. ---doc]]-- ---- string -> bool -> lpeg_t -local scan_node = function (tag) - --- Node attributes go into a table with the index “attributes” - --- (relevant for “prefix="xdg"” and the likes). - local p_tag = P(tag) - local with_attributes = P"<" * p_tag - * Cg(xml_attr_list, "attributes")^-1 - * xmlws^-1 - * P">" - local plain = P"<" * p_tag * xmlws^-1 * P">" - local node_start = plain + with_attributes - local node_stop = P"</" * p_tag * xmlws^-1 * P">" - --- there is no nesting, the earth is flat ... - local node = node_start - * Cc(tag) * C(comment + (1 - node_stop)^1) - * node_stop - return Ct(node) -- returns {string, string [, attributes = { key = val }] } -end - ---[[doc-- - At the moment, the interesting tags are “dir” for - directory declarations, and “include” for including - further configuration files. - - spec: http://freedesktop.org/software/fontconfig/fontconfig-user.html ---doc]]-- -local include_node = scan_node"include" -local dir_node = scan_node"dir" - -local element = dir_node - + include_node - + comment --> ignore - + P(1-root_stop) --> skip byte - -local root = root_start * Ct(element^0) * root_stop -local p_cheapxml = header * root - ---lpeg.print(p_cheapxml) ---> 757 rules with v0.10 - ---[[doc-- - fonts_conf_scanner() handles configuration files. - It is called on an abolute path to a config file (e.g. - /home/luser/.config/fontconfig/fonts.conf) and returns a list - of the nodes it managed to extract from the file. ---doc]]-- ---- string -> path list -local fonts_conf_scanner = function (path) - logreport("both", 5, "db", "Read fontconfig file %s.", path) - local fh = ioopen(path, "r") - if not fh then - logreport("both", 3, "db", "Cannot open fontconfig file %s.", path) - return - end - local raw = fh:read"*all" - fh:close() - logreport("both", 7, "db", - "Reading fontconfig file %s completed (%d bytes).", - path, #raw) - - logreport("both", 5, "db", "Scan fontconfig file %s.", path) - local confdata = lpegmatch(p_cheapxml, raw) - if not confdata then - logreport("both", 3, "db", "Cannot scan fontconfig file %s.", path) - return - end - logreport("both", 7, "db", "Scan of fontconfig file %s completed.", path) - return confdata -end - -local p_conf = P".conf" * P(-1) -local p_filter = (1 - p_conf)^1 * p_conf - -local conf_filter = function (path) - if lpegmatch (p_filter, path) then - return true - end - return false -end - ---[[doc-- - - read_fonts_conf_indeed() -- Scan paths included from fontconfig - configuration files recursively. Called with eight arguments. - The first five are - - · the current recursion depth - · the path to the file - · the expanded $HOME - · the expanded $XDG_CONFIG_HOME - · the expanded $XDG_DATA_HOME - - determining the path to be checked. Another three arguments are - tables that represent the state of the current job as lists of - strings; these are always returned. Finally a reference to the - find_files function is passed. - ---doc]]-- - ---- size_t -> string -> string -> string -> string ---- -> string list -> string list -> string list ---- -> (string -> fun option -> string list) ---- -> tab * tab * tab -local read_fonts_conf_indeed -read_fonts_conf_indeed = function (depth, - start, - home, - xdg_config_home, - xdg_data_home, - acc, - done, - dirs_done, - find_files) - - logreport ("both", 4, "db", - "Fontconfig scanner processing path %s.", - start) - if depth >= traversal_maxdepth then - --- prevent overflow of Lua call stack - logreport ("both", 0, "db", - "Fontconfig scanner hit recursion limit (%d); " - .. "aborting directory traversal.", - traversal_maxdepth) - return acc, done, dirs_done - end - - local paths = fonts_conf_scanner(start) - if not paths then --- nothing to do - return acc, done, dirs_done - end - - for i=1, #paths do - local pathobj = paths[i] - local kind, path = pathobj[1], pathobj[2] - local attributes = pathobj.attributes - - if kind == "dir" then - if attributes and attributes.prefix == "xdg" then - path = filejoin(xdg_data_home, path) - end - if stringsub(path, 1, 1) == "~" then - path = filejoin(home, stringsub(path, 2)) - end - --- We exclude paths with texmf in them, as they should be - --- found anyway; also duplicates are ignored by checking - --- if they are elements of dirs_done. - --- - --- FIXME does this mean we cannot access paths from - --- distributions (e.g. Context minimals) installed - --- separately? - if not (stringfind(path, "texmf") or dirs_done[path]) then - logreport ("log", 5, "db", - "New fontconfig path at %s.", - path) - acc[#acc+1] = path - dirs_done[path] = true - end - - elseif kind == "include" then - if attributes and attributes.prefix == "xdg" then - path = filejoin(xdg_config_home, path) - end - --- here the path can be four things: a directory or a file, - --- an absolute or relative path. - if stringsub(path, 1, 1) == "~" then - path = filejoin(home, stringsub(path, 2)) - elseif --- if the path is relative, we make it absolute - not ( lfsisfile(path) or lfsisdir(path) ) - then - path = filejoin(filedirname(start), path) - end - if lfsisfile(path) - and kpsereadable_file(path) - then - if done[path] then - logreport("log", 3, "db", - "Skipping file at %s, already included.", path) - else - done[path] = true - acc = read_fonts_conf_indeed(depth + 1, - path, - home, - xdg_config_home, - xdg_data_home, - acc, - done, - dirs_done, - find_files) - end - elseif lfsisdir(path) then --- arrow code ahead - local config_files = find_files (path, conf_filter) - for _, filename in next, config_files do - if not done[filename] then - if done[path] then - logreport ("log", 3, "db", - "Skipping file at %s, already included.", path) - else - done[path] = true - acc = read_fonts_conf_indeed(depth + 1, - filename, - home, - xdg_config_home, - xdg_data_home, - acc, - done, - dirs_done, - find_files) - end - end - end - end --- match “kind” - end --- iterate paths - end - - --inspect(acc) - --inspect(done) - return acc, done, dirs_done -end --- read_fonts_conf_indeed() - ---[[doc-- - read_fonts_conf() sets up an accumulator and two sets - for tracking what’s been done. - - Also, the environment variables HOME, XDG_DATA_HOME and - XDG_CONFIG_HOME -- which are constants anyways -- are expanded - so we don’t have to repeat that over and over again as with the - old parser. Now they’re just passed on to every call of - read_fonts_conf_indeed(). ---doc]]-- - ---- list -> (string -> function option -> string list) -> list - -local read_fonts_conf = function (path_list, find_files) - local home = kpseexpand_path"~" --- could be os.getenv"HOME" - local xdg_config_home = kpseexpand_path"$XDG_CONFIG_HOME" - if xdg_config_home == "" then xdg_config_home = filejoin(home, ".config") end - local xdg_data_home = kpseexpand_path"$XDG_DATA_HOME" - if xdg_data_home == "" then xdg_data_home = filejoin(home, ".local/share") end - local acc = { } ---> list: paths collected - local done = { } ---> set: files inspected - local dirs_done = { } ---> set: dirs in list - for i=1, #path_list do --- we keep the state between files - acc, done, dirs_done = read_fonts_conf_indeed(0, - path_list[i], - home, - xdg_config_home, - xdg_data_home, - acc, - done, - dirs_done, - find_files) - end - return acc -end - -------------------------------------------------------------------------------- ---- MISC PARSERS -------------------------------------------------------------------------------- - - -local trailingslashes = slash^1 * P(-1) -local stripslashes = C((1 - trailingslashes)^0) - -local splitcomma = Ct((C(noncomma^1) + comma)^1) - - - -------------------------------------------------------------------------------- ---- FONT REQUEST -------------------------------------------------------------------------------- - - ---[[doc------------------------------------------------------------------------ - - The luaotfload font request syntax (see manual) - has a canonical form: - - \font<csname>=<prefix>:<identifier>:<features> - - where - <csname> is the control sequence that activates the font - <prefix> is either “file” or “name”, determining the lookup - <identifer> is either a file name (no path) or a font - name, depending on the lookup - <features> is a list of switches or options, separated by - semicolons or commas; a switch is of the form “+” foo - or “-” foo, options are of the form lhs “=” rhs - - however, to ensure backward compatibility we also have - support for Xetex-style requests. - - for the Xetex emulation see: - · The XeTeX Reference Guide by Will Robertson, 2011 - · The XeTeX Companion by Michel Goosens, 2010 - · About XeTeX by Jonathan Kew, 2005 - - - caueat emptor. - - the request is parsed into one of **four** different lookup - categories: the regular ones, file and name, as well as the - Xetex compatibility ones, path and anon. (maybe a better choice - of identifier would be “ambig”.) - - according to my reconstruction, the correct chaining of the - lookups for each category is as follows: - - | File -> ( db/filename lookup ) - - | Name -> ( db/name lookup, - db/filename lookup ) - - | Path -> ( db/filename lookup, - fullpath lookup ) - - | Anon -> ( kpse.find_file(), // <- for tfm, ofm - db/name lookup, - db/filename lookup, - fullpath lookup ) - - caching of successful lookups is essential. we now as of v2.2 - have a lookup cache that is stored in a separate file. it - pertains only to name: lookups, and is described in more detail - in luaotfload-database.lua. - -------------------------------------------------------------------------------- - - One further incompatibility between Xetex and Luatex-Fonts consists - in their option list syntax: apparently, Xetex requires key-value - options to be prefixed by a "+" (ascii “plus”) character. We - silently accept this as well, dropping the first byte if it is a - plus or minus character. - - Reference: https://github.com/lualatex/luaotfload/issues/79#issuecomment-18104483 - ---doc]]------------------------------------------------------------------------ - - -local handle_normal_option = function (key, val) - val = stringlower(val) - --- the former “toboolean()” handler - if val == "true" then - val = true - elseif val == "false" then - val = false - end - return key, val -end - ---[[doc-- - - Xetex style indexing begins at zero which we just increment before - passing it along to the font loader. Ymmv. - ---doc]]-- - -local handle_xetex_option = function (key, val) - val = stringlower(val) - local numeric = tonumber(val) --- decimal only; keeps colors intact - if numeric then --- ugh - if mathceil(numeric) == numeric then -- integer, possible index - val = tostring(numeric + 1) - end - elseif val == "true" then - val = true - elseif val == "false" then - val = false - end - return key, val -end - ---[[doc-- - - Instead of silently ignoring invalid options we emit a warning to - the log. - - Note that we have to return a pair to please rawset(). This creates - an entry on the resulting features hash which will later be removed - during set_default_features(). - ---doc]]-- - -local handle_invalid_option = function (opt) - logreport("log", 0, "load", "font option %q unknown.", opt) - return "", false -end - ---[[doc-- - - Dirty test if a file: request is actually a path: lookup; don’t - ask! Note this fails on Windows-style absolute paths. These will - *really* have to use the correct request. - ---doc]]-- - -local check_garbage = function (_,i, garbage) - if stringfind(garbage, "/") then - logreport("log", 0, "load", --- ffs use path! - "warning: path in file: lookups is deprecated; ") - logreport("log", 0, "load", "use bracket syntax instead!") - logreport("log", 0, "load", - "position: %d; full match: %q", - i, garbage) - return true - end - return false -end - -local featuresep = comma + semicolon - ---- modifiers --------------------------------------------------------- ---[[doc-- - The slash notation: called “modifiers” (Kew) or “font options” - (Robertson, Goosens) - we only support the shorthands for italic / bold / bold italic - shapes, as well as setting optical size, the rest is ignored. ---doc]]-- -local style_modifier = (P"BI" + P"IB" + P"bi" + P"ib" + S"biBI") - / stringlower -local size_modifier = S"Ss" * P"=" --- optical size - * Cc"optsize" * C(decimal) -local other_modifier = P"AAT" + P"aat" --- apple stuff; unsupported - + P"ICU" + P"icu" --- not applicable - + P"GR" + P"gr" --- sil stuff; unsupported -local garbage_modifier = ((1 - colon - slash)^0 * Cc(false)) -local modifier = slash * (other_modifier --> ignore - + Cs(style_modifier) --> collect - + Ct(size_modifier) --> collect - + garbage_modifier) --> warn -local modifier_list = Cg(Ct(modifier^0), "modifiers") - ---- combining --------------------------------------------------------- ---- ---- \font \three = combo: 1->42; 2->99,0xdeadbeef; 3->(1,U+2a-U+1337*42) ---- v +~ v +~ +~~~~~~~~~ v v +~~~ +~~~~~ +~ ---- | | | | | | | | | | ---- | | | | | | | | | | ---- idx : ---+--÷---+--÷--÷-----------+ | +----+ | ---- | | | | | | ---- id : ------+------+--÷---------------+ +-----------+ ---- | | ---- chars : ----------------+-----------------+ ---- -local comborowsep = ws * semicolon * ws -local combomapsep = ws * P"->" * ws -local combodefsep = ws * comma * ws -local comborangesep = ws * asterisk * ws - -local combohex = hex / tonumber -local combouint = digit^1 / tonumber -local tonumber16 = function (s) return tonumber (s, 16) end -local combouni = P"U+" * (digit^1 / tonumber16) -local combonum = combohex + combouni + combouint -local comborange = Ct(combonum * dash * combonum) + combonum -local combochars = comborange * (comborangesep * comborange)^0 -local parenthesized = function (p) return P"(" * ws * p * ws * P")" end - -local comboidxpat = Cg(combouint, "idx") -local comboidpat = Cg(combouint, "id" ) -local combocharspat = Cg(P"fallback" * Cc(true) + Ct(combochars^1), "chars") -local comboidcharspat = comboidpat * combodefsep * combocharspat - -local comboidx = parenthesized (comboidxpat ) + comboidxpat -local comboid = parenthesized (comboidpat ) + comboidpat -local comboidchars = parenthesized (comboidcharspat) + comboidcharspat - -local combodef1 = Ct(comboidx * combomapsep * comboid) --> no chars -local combodef = Ct(comboidx * combomapsep * comboidchars) -local combolist = Ct(combodef1 * (comborowsep * combodef)^1) - ---- subfonts ---------------------------------------------------------- ---- This rule is present in the original parser. It sets the “sub” ---- field of the specification which allows addressing a specific ---- font inside a TTC container. Neither in Luatex-Fonts nor in ---- Luaotfload is this documented, so we might as well silently drop ---- it. However, as backward compatibility is one of our prime goals we ---- just insert it here and leave it undocumented until someone cares ---- to ask. (Note: afair subfonts are numbered, but this rule matches a ---- string; I won’t mess with it though until someone reports a ---- problem.) ---- local subvalue = P("(") * (C(P(1-S("()"))^1)/issub) * P(")") -- for Kim ---- Note to self: subfonts apparently start at index 0. Tested with ---- Cambria.ttc that includes “Cambria Math” at 0 and “Cambria” at 1. ---- Other values cause luatex to segfault. -local subfont = P"(" * Cg((1 - S"()")^1, "sub") * P")" - ---- lookups ----------------------------------------------------------- -local fontname = C((1-S":(/")^1) --- like luatex-fonts -local unsupported = Cmt((1-S":(")^1, check_garbage) -local combo = P"combo:" * ws * Cg(combolist, "combo") -local prefixed = P"name:" * ws * Cg(fontname, "name") ---- initially we intended file: to emulate the behavior of ---- luatex-fonts, i.e. no paths allowed. after all, we do have XeTeX ---- emulation with the path lookup and it interferes with db lookups. ---- turns out fontspec and other widely used packages rely on file: ---- with paths already, so we’ll add a less strict rule here. anyways, ---- we’ll emit a warning. - + P"file:" * ws * Cg(unsupported, "path") - + P"file:" * ws * Cg(fontname, "file") - + P"kpse:" * ws * Cg(fontname, "kpse") - + P"my:" * ws * Cg(fontname, "my") -local unprefixed = Cg(fontname, "anon") ---- Bracketed “path” lookups: These may contain any character except ---- for unbalanced brackets. A backslash escapes any following ---- character. Everything inside the outermost brackets is treated as ---- part of the filename or path to look up. Subfonts may be specified ---- in parens *after* the closing bracket. Note that this differs from ---- Xetex whose syntax expects the subfont passed inside the brackets, ---- separated by a colon. -local path_escape = backslash / "" * patterns.utf8char -local path_content = path_escape + (1 - brackets) -local path_balanced = { (path_content + V(2))^1 - , lbrk * V(1)^-1 * rbrk } -local path_lookup = lbrk * Cg(Cs(path_balanced), "path") * rbrk - * subfont^-1 - ---- features ---------------------------------------------------------- -local field_char = anum + S"+-.!?" --- sic! -local field = field_char^1 ---- assignments are “lhs=rhs” ---- or “+lhs=rhs” (Xetex-style) ---- switches are “+key” | “-key” -local normal_option = C(field) * ws * equals * ws * C(field) * ws -local xetex_option = P"+" * ws * normal_option -local ignore_option = (1 - equals - featuresep)^1 - * equals - * (1 - featuresep)^1 -local assignment = xetex_option / handle_xetex_option - + normal_option / handle_normal_option - + ignore_option / handle_invalid_option -local switch = P"+" * ws * C(field) * Cc(true) - + P"-" * ws * C(field) * Cc(false) - + C(field) * Cc(true) --- default -local feature_expr = ws * Cg(assignment + switch) * ws -local option = feature_expr -local feature_list = Cf(Ct"" - * option - * (featuresep * option^-1)^0 - , rawset) - * featuresep^-1 ---- top-level rules --------------------------------------------------- ---- \font\foo=<specification>:<features> -local features = Cg(feature_list, "features") -local specification = (prefixed + unprefixed) - * subfont^-1 - * modifier_list^-1 -local font_request = Ct(path_lookup * (colon^-1 * features)^-1 - + combo --> TODO: feature list needed? - + specification * (colon * features)^-1) - --- lpeg.print(font_request) ---- v2.5 parser: 1065 rules ---- v1.2 parser: 230 rules - -------------------------------------------------------------------------------- ---- INI FILES -------------------------------------------------------------------------------- - ---[[doc-- - - Luaotfload uses the pervasive flavor of the INI files that allows '#' in - addition to ';' to indicate comment lines (see git-config(1) for a - description of the syntax we’re targeting). - ---doc]]-- - -local truth_ids = { - ["true"] = true, - ["1"] = true, - yes = true, - on = true, - ["false"] = false, - ["2"] = false, - no = false, - off = false, -} - -local maybe_cast = function (var) - local bool = truth_ids[var] - if bool ~= nil then - return bool - end - return tonumber (var) or var -end - -local escape = function (chr, repl) - return (backslash * P(chr) / (repl or chr)) -end - -local valid_escapes = escape "\"" - + escape "\\" - + escape ("n", "\n") - + escape ("t", "\t") - + escape ("b", "\b") -local comment_char = semicolon + gartenzaun -local comment_line = ws * comment_char * (1 - eol)^0 * eol -local blank_line = ws * eol -local skip_line = comment_line + blank_line -local ini_id_char = alpha + (dash / "_") -local ini_id = Cs(alpha * ini_id_char^0) / stringlower -local ini_value_char = (valid_escapes + (1 - linebreak - backslash - comment_char)) -local ini_value = (Cs (ini_value_char^0) / string.strip) - * (comment_char * (1 - eol)^0)^-1 -local ini_string_char = (valid_escapes + (1 - linebreak - dquote - backslash)) -local ini_string = dquote - * Cs (ini_string_char^0) - * dquote - -local ini_heading_title = Ct (Cg (ini_id, "title") - * (ws * Cg (ini_string / stringlower, "subtitle"))^-1) -local ini_heading = lbrk * ws - * Cg (ini_heading_title, "section") - * ws * rbrk * ws * eol - -local ini_variable_full = Cg (ws - * ini_id - * ws - * equals - * ws - * (ini_string + (ini_value / maybe_cast)) - * ws - * eol) -local ini_variable_true = Cg (ws * ini_id * ws * eol * Cc (true)) -local ini_variable = ini_variable_full - + ini_variable_true - + skip_line -local ini_variables = Cg (Cf (Ct "" * ini_variable^0, rawset), "variables") - -local ini_section = Ct (ini_heading * ini_variables) -local ini_sections = skip_line^0 * ini_section^0 -local parse_config = Ct (ini_sections) - ---[=[doc-- - - The INI parser converts an input of the form - - [==[ - [foo] - bar = baz - xyzzy = no - buzz - - [lavernica "brutalitops"] - # It’s a locomotive that runs on us. - laan-ev = zip zop zooey ; jib-jab - Crouton = "Fibrosis \"\\ # " - - ]==] - - to a Lua table of the form - - { { section = { title = "foo" }, - variables = { bar = "baz", - xyzzy = false, - buzz = true } }, - { section = { title = "boing", - subtitle = "brutalitops" }, - variables = { ["laan-ev"] = "zip zop zooey", - crouton = "Fibrosis \"\\ # " } } } - ---doc]=]-- - -return { - init = function () - logreport = luaotfload.log.report - luaotfload.parsers = { - --- parameters - traversal_maxdepth = traversal_maxdepth, - --- main parsers - read_fonts_conf = read_fonts_conf, - font_request = font_request, - config = parse_config, - --- common patterns - stripslashes = stripslashes, - splitcomma = splitcomma, - } - return true - end -} - --- vim:ft=lua:tw=71:et:sw=2:sts=4:ts=8 diff --git a/tex/compat/luaotfload/luaotfload-resolvers.lua b/tex/compat/luaotfload/luaotfload-resolvers.lua deleted file mode 100644 index 983d3fc6694a321faf23ffd000e6bda2bb90196a..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/luaotfload-resolvers.lua +++ /dev/null @@ -1,308 +0,0 @@ -#!/usr/bin/env texlua ------------------------------------------------------------------------ --- FILE: luaotfload-resolvers.lua --- USAGE: ./luaotfload-resolvers.lua --- DESCRIPTION: Resolvers for hooking into the fontloader --- REQUIREMENTS: Luaotfload and a decent bit of courage --- AUTHOR: Philipp Gesang (Phg), <phg@phi-gamma.net> ------------------------------------------------------------------------ --- ---- The bare fontloader uses a set of simplistic file name resolvers ---- that must be overloaded by the user (i. e. us). - -if not lualibs then error "this module requires Luaotfload" end -if not luaotfload then error "this module requires Luaotfload" end - ---[[doc-- - - Relying on the \verb|name:| resolver for everything has been the - source of permanent trouble with the database. - With the introduction of the new syntax parser we now have enough - granularity to distinguish between the \XETEX emulation layer and - the genuine \verb|name:| and \verb|file:| lookups of \LUATEX-Fonts. - Another benefit is that we can now easily plug in or replace new - lookup behaviors if necessary. - The name resolver remains untouched, but it calls - \luafunction{fonts.names.resolve()} internally anyways (see - \fileent{luaotfload-database.lua}). - ---doc]]-- - -local next = next -local tableconcat = table.concat -local kpsefind_file = kpse.find_file -local lfsisfile = lfs.isfile -local stringlower = string.lower -local stringformat = string.format -local filesuffix = file.suffix -local fileremovesuffix = file.removesuffix -local luatexbase = luatexbase -local logreport = luaotfload.log.report - ---[[doc-- - - \identifier{luaotfload} promises easy access to system fonts. - Without additional precautions, this cannot be achieved by - \identifier{kpathsea} alone, because it searches only the - \fileent{texmf} directories by default. - Although it is possible for \identifier{kpathsea} to include extra - paths by adding them to the \verb|OSFONTDIR| environment variable, - this is still short of the goal »\emphasis{it just works!}«. - When building the font database \identifier{luaotfload} scans - system font directories anyways, so we already have all the - information for looking sytem fonts. - With the release version 2.2 the file names are indexed in the - database as well and we are ready to resolve \verb|file:| lookups - this way. - Thus we no longer need to call the \identifier{kpathsea} library in - most cases when looking up font files, only when generating the - database, and when verifying the existence of a file in the - \fileent{texmf} tree. - ---doc]]-- - -local resolve_file -resolve_file = function (specification) - local name, _format, success = fonts.names.lookup_font_file (specification.name) - local suffix = filesuffix (name) - if fonts.formats[suffix] then - specification.forced = stringlower (suffix) - specification.forcedname = fileremovesuffix (name) - else - specification.name = name - end - if success ~= true then - logreport ("log", 1, "resolve", "file lookup of %q unsuccessful", name) - end - return success -end - ---[[doc-- - - Prior to version 2.2, \identifier{luaotfload} did not distinguish - \verb|file:| and \verb|path:| lookups, causing complications with - the resolver. - Now we test if the requested name is an absolute path in the file - system, otherwise we fall back to the \verb|file:| lookup. - ---doc]]-- - -local resolve_path -resolve_path = function (specification) - local name = specification.name - local exists, _ = lfsisfile (name) - if not exists then -- resort to file: lookup - logreport ("log", 1, "resolve", - "path lookup of %q unsuccessful, falling back to file:", - name) - return resolve_file (specification) - end - local suffix = filesuffix (name) - if fonts.formats [suffix] then - specification.forced = stringlower (suffix) - specification.name = fileremovesuffix (name) - specification.forcedname = name - else - specification.name = name - end - return true -end - ---[[doc-- - - The \verb|name:| resolver. - ---doc]]-- - ---- fonts.names.resolvers.name -- Customized version of the ---- generic name resolver. - -local resolve_name -resolve_name = function (specification) - local resolver = fonts.names.lookup_font_name_cached - if config.luaotfload.run.resolver == "normal" then - resolver = fonts.names.lookup_font_name - end - local resolved, subfont = resolver (specification) - if resolved then - logreport ("log", 1, "resolve", "name lookup %q -> \"%s%s\"", - specification.name, resolved, - subfont and stringformat ("(%d)", subfont) or "") - specification.resolved = resolved - specification.sub = subfont - specification.forced = stringlower (filesuffix (resolved) or "") - specification.forcedname = resolved - specification.name = fileremovesuffix (resolved) - return true - end - return resolve_file (specification) -end - ---[[doc-- - - We classify as \verb|anon:| those requests that have neither a - prefix nor brackets. According to Khaled\footnote{% - % XXX dead link‽ - \url{https://github.com/phi-gamma/luaotfload/issues/4#issuecomment-17090553}. - } - they are the \XETEX equivalent of a \verb|name:| request, so we - will be treating them as such or, at least, in a similar fashion. - - Not distinguishing between “anon” and “name” requests has a serious - drawback: The syntax is overloaded for requesting fonts in - \identifier{Type1} (\abbrev{tfm}, \abbrev{ofm}) format. - These are essentially \verb|file:| lookups and must be caught - before the \verb|name:| resolver kicks in, lest they cause the - database to update. - Even if we were to require the \verb|file:| prefix for all - \identifier{Type1} requests, tests have shown that certain fonts - still include further fonts (e.~g. \fileent{omlgcb.ofm} will ask - for \fileent{omsecob.tfm}) \emphasis{using the old syntax}. - For this reason, we introduce an extra check with an early return. - ---doc]]-- - -local tex_formats = { "tfm", "ofm", "TFM", "OFM", } - -local resolve_tex_format = function (specification) - local name = specification.name - for i=1, #tex_formats do - local format = tex_formats [i] - local suffix = filesuffix (name) - if resolvers.findfile (name, format) then - local usename = suffix == format and fileremovesuffix (name) or name - specification.forcedname = file.addsuffix (usename, format) - specification.forced = format ----- specification.resolved = name - return true - end - end - return false -end - -local resolve_path_if_exists = function (specification) - local spec = specification.specification - local exists, _void = lfsisfile (spec) - if exists then - --- If this path is taken a file matching the specification - --- literally was found. In this situation, Luaotfload is - --- expected to load that file directly, even though we provide - --- explicit “file” and “path” lookups to address exactly this - --- situation. - logreport ("log", 1, "resolve", - "file %q exists, performing path lookup", spec) - specification.name = spec - return resolve_path (specification) - end - return false -end - ---[[doc-- - Custom file resolvers via callback. ---doc]]-- - -local resolve_my = function (specification) - luatexbase.call_callback ("luaotfload.resolve_font", specification) -end - -local resolve_methods = { - tex = resolve_tex_format, - path = resolve_path_if_exists, - name = resolve_name, - file = resolve_file, - my = resolve_my, -} - -local resolve_sequence = function (seq, specification) - for i = 1, #seq do - local id = seq [i] - local mth = resolve_methods [id] - if not mth then - logreport ("both", 0, "resolve", - "step %d: invalid lookup method %q", i, id) - else - logreport ("both", 3, "resolve", "step %d: apply method %q (%s)", i, id, mth) - if mth (specification) == true then - logreport ("both", 3, "resolve", - "%d: method %q resolved %q -> %s (%s).", - i, id, specification.specification, - specification.name, - specification.forcedname) - return true - end - end - end - logreport ("both", 0, "resolve", - "sequence of %d lookups yielded nothing appropriate.", #seq) - return false -end - -local default_anon_sequence = { - "tex", "path", "name", -} - -local resolve_anon -resolve_anon = function (specification) - local seq = default_anon_sequence - if config and config.luaotfload then - local anonseq = config.luaotfload.run.anon_sequence - if anonseq and next (anonseq) then - seq = anonseq - end - end - return resolve_sequence (seq, specification) -end - ---[[doc-- - - {\bfseries EXPERIMENTAL}: - \identifier{kpse}-only resolver, for those who can do without - system fonts. - ---doc]]-- - -local resolve_kpse -resolve_kpse = function (specification) - local name = specification.name - local suffix = filesuffix (name) - if suffix and fonts.formats[suffix] then - name = fileremovesuffix (name) - if resolvers.findfile (name, suffix) then - specification.forced = stringlower (suffix) - specification.forcedname = name - return true - end - end - for t, format in next, fonts.formats do --- brute force - if kpsefind_file (name, format) then - specification.forced = t - specification.name = name - return true - end - end - return false -end - -return { - init = function ( ) - if luatexbase and luatexbase.create_callback then - luatexbase.create_callback ("luaotfload.resolve_font", - "simple", function () end) - end - logreport ("log", 5, "resolvers", "installing font resolvers", name) - local request_resolvers = fonts.definers.resolvers - request_resolvers.file = resolve_file - request_resolvers.name = resolve_name - request_resolvers.anon = resolve_anon - request_resolvers.path = resolve_path - request_resolvers.kpse = resolve_kpse - request_resolvers.my = resolve_my - fonts.formats.ofm = "type1" - fonts.encodings = fonts.encodings or { } - fonts.encodings.known = fonts.encodings.known or { } - return true - end, --- [.init] -} - ---- vim:ft=lua:ts=8:sw=4:et:tw=79 - diff --git a/tex/compat/luaotfload/luaotfload-status.lua b/tex/compat/luaotfload/luaotfload-status.lua deleted file mode 100644 index 5571e947cf06d08b7aa8e894095d33cd214305dd..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/luaotfload-status.lua +++ /dev/null @@ -1,85 +0,0 @@ -return { - ["hashes"]={ - { "fontloader-2017-02-11.lua", "c2db29b75e1838c08ff5867778f79cc3" }, - { "fontloader-util-fil.lua", "0573e91847e722ffe0fcdb465ba89e6b" }, - { "fontloader-util-str.lua", "513836cfea6a8027c1451a95bc74649f" }, - { "fontloader-swiglib-test.lua", "2f0b431faf53d3e19bfae22035bdc77e" }, - { "fontloader-swiglib.lua", "c20138e09bfd743dba7de1d5421be4af" }, - { "fontloader-preprocessor.lua", "f87963c22d5523218f1beee7e315bae5" }, - { "fontloader-mplib.lua", "55ad1c7febc72c6700b49692c2384738" }, - { "fontloader-math.lua", "f7eda9d5922e4aa7bb858ba9943fdacd" }, - { "fontloader-l-table.lua", "92978e5ea9ca13dae04fb606f5be4a1c" }, - { "fontloader-l-string.lua", "2ca01eeb225c09e73ff4f3a2d101827a" }, - { "fontloader-l-math.lua", "51275e81c652e3fbd7d02b1c383d3049" }, - { "fontloader-l-lua.lua", "5466b2db6d8cc3b9786a398bb4230ea1" }, - { "fontloader-l-lpeg.lua", "93b90b22d7d3600ddd9def9f3ad9a7bb" }, - { "fontloader-l-io.lua", "ee77e357f5965196f9559b8fcccc6e71" }, - { "fontloader-l-function.lua", "a7e68a9703c35238729da41a474e951b" }, - { "fontloader-l-file.lua", "32d9ba0a5cdd3509a3847bb050bfb800" }, - { "fontloader-l-boolean.lua", "abe28515dd33e8f6c416c09bca351cf8" }, - { "fontloader-languages.lua", "4e5bbdad336fa4969ac21a5242643a40" }, - { "fontloader-font-otc.lua", "85d63e257c748c624768aa7c8ec7f0bc" }, - { "fontloader-font-ocl.lua", "fbc00782e4efb24a7569f99cd1574ffb" }, - { "fontloader-font-osd.lua", "10ecd4b375680b011e7c6a25e5ad74f7" }, - { "fontloader-font-ots.lua", "7e1e55f9f728474372665e4a64a43f5a" }, - { "fontloader-font-ota.lua", "c281d18dfc89a8ca18af64f55e9fa92b" }, - { "fontloader-font-otj.lua", "5ea70db9f1990dc1459425853c79f663" }, - { "fontloader-font-oto.lua", "5fbdd899624d4eef639f81b580afe9aa" }, - { "fontloader-font-otl.lua", "2e7c8d9a331c46826211bd507f8e488a" }, - { "fontloader-font-oup.lua", "f7237130b648a4c2b477dabedc7f90e8" }, - { "fontloader-font-dsp.lua", "4a5266ada979d5c2d48867dc3ffaefea" }, - { "fontloader-font-ttf.lua", "e0893de6d0f3f421ee4386fa90429db8" }, - { "fontloader-font-cff.lua", "f3fc74e8629f7a2825c34a34550c790d" }, - { "fontloader-font-otr.lua", "2bd0085b78027f261218d63034f43474" }, - { "fontloader-font-tfm.lua", "3d813578dbf6c447e4b859c2bf0618f7" }, - { "fontloader-fonts-syn.lua", "6753dfb9a28aad35266284bb00072dca" }, - { "fontloader-font-lua.lua", "1fbfdf7b689b2bdfd0e3bb9bf74ce136" }, - { "fontloader-fonts.lua", "96e568c9b2ffa8108fb95d886bb2b645" }, - { "fontloader-fonts-ext.lua", "aff3846f4c1f15de0a9f4fd7081e0c68" }, - { "fontloader-fonts-enc.lua", "a7ace7c1969cd64a5ca9888838f3edb6" }, - { "fontloader-fonts-demo-vf-1.lua", "7a4cb26eda4f1090d195114c10a33a75" }, - { "fontloader-font-def.lua", "49fa2b50d8d2a1bb70b08b72f858ecd0" }, - { "fontloader-font-gbn.lua", "850f31ba73ff8de96371d0aed2b2b4cb" }, - { "fontloader-font-oti.lua", "8f48c06a1d632febd7231ad5dfadfc53" }, - { "fontloader-font-map.lua", "8708bde7467785c4d3b7afdaf2f9333a" }, - { "fontloader-font-ini.lua", "10cb9a563a98e06ff79c35a8751e13dc" }, - { "fontloader-font-def.lua", "49fa2b50d8d2a1bb70b08b72f858ecd0" }, - { "fontloader-font-con.lua", "7575a7b4e6d04816072945e27d7d0b33" }, - { "fontloader-font-cid.lua", "52421d1fdaa07ec4b1d936c6ff5079be" }, - { "fontloader-font-one.lua", "6fbf6b9e219a944cd1ad5933d77cc488" }, - { "fontloader-font-onr.lua", "205c8bc640715aecf3538a33b842f450" }, - { "fontloader-font-afk.lua", "b36a76ceb835f41f8c05b471000ddc14" }, - { "fontloader-data-con.lua", "d8982c834ed9acc6193eee23067b9d5d" }, - { "fontloader-basics-nod.lua", "9288471b8395bfb683aba0ff3964d950" }, - { "fontloader-reference.lua", "12efa565c640e8583a8fde380dc0e1a0" }, - { "fontloader-basics-gen.lua", "b6c8f256b6c6d3350bf5bad2034857a0" }, - { "mktests", "918cb50be9ee8bd645ac1a27dc501e8c" }, - { "mkstatus", "d66d9237a9e18e64732f239e49e77633" }, - { "mkimport", "a90dbe00a99c7e77494b07fbe0e669af" }, - { "mkglyphlist", "b573c7a7645e5b84e776d7d0bb06c559" }, - { "mkcharacters", "1db01d8172c49c8a405897dc45340917" }, - { "luaotfload-glyphlist.lua", "bcf89e1441be9f4ad29c0cf3a076bcea" }, - { "luaotfload-characters.lua", "99578c3eff8b68cae3da45a4a7cbfcf2" }, - { "luaotfload-tool.lua", "e6ca512e0620ccaac968ccc17239ee39" }, - { "luaotfload-resolvers.lua", "bcdde7940630c4b563f3884b64ae3c84" }, - { "luaotfload-parsers.lua", "0f40bde1938a5cb72b75fccbbaa43d75" }, - { "luaotfload-main.lua", "8411e662c9867c423dc0229b12eb174c" }, - { "luaotfload-log.lua", "cc79197903756cde068d3c197844be99" }, - { "luaotfload-loaders.lua", "26fef8c4436e02b03deab714716a0948" }, - { "luaotfload-letterspace.lua", "0f4bd9bc0365e96f099e68f4a8114d3e" }, - { "luaotfload-init.lua", "e5c4c96fc7e3bf150229013fb56e77b5" }, - { "luaotfload-features.lua", "dc9dcfb374577b47dafac01e19935050" }, - { "luaotfload-diagnostics.lua", "7b35c9f91e3e73fc5a61dbfe1f0e7ad9" }, - { "luaotfload-database.lua", "62fee5ba6afb4ee38aa1a2b183d59ff8" }, - { "luaotfload-configuration.lua", "64fa81f2f8fe6815f109873fb27f78aa" }, - { "luaotfload-colors.lua", "2582a42a68739087a72e5ea6440cf0d8" }, - { "luaotfload-auxiliary.lua", "a6c092c006660ee6e6fbdcddf104a99b" }, - }, - ["notes"]={ - ["committer"]="Philipp Gesang <phg@phi-gamma.net>", - ["description"]="v2.8-fix-2", - ["loader"]="fontloader-2017-02-11.lua", - ["revision"]="ad480924393fffa2896156e1a32c22f5c61120dd", - ["timestamp"]="2017-02-11 00:21:52 +0100", - }, -} \ No newline at end of file diff --git a/tex/compat/luaotfload/luaotfload-tool.lua b/tex/compat/luaotfload/luaotfload-tool.lua deleted file mode 100755 index e7df3ce44825d9f83c300356e44071f01c9e6b9c..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/luaotfload-tool.lua +++ /dev/null @@ -1,1638 +0,0 @@ -#!/usr/bin/env texlua ------------------------------------------------------------------------ --- FILE: luaotfload-tool.lua --- DESCRIPTION: database functionality --- REQUIREMENTS: luaotfload 2.8 --- AUTHOR: Khaled Hosny, Élie Roux, Philipp Gesang --- LICENSE: GPL v2.0 ------------------------------------------------------------------------ - -luaotfload = luaotfload or { } -local version = "2.8" -luaotfload.version = version -luaotfload.min_luatex_version = { 0, 95, 0 } -luaotfload.self = "luaotfload-tool" - ---[[doc-- - -luaotfload-tool(1) - -This file was originally written (as \fileent{mkluatexfontdb.lua}) by -Elie Roux and Khaled Hosny and, as a derived work of ConTeXt, is -provided under the terms of the GPL v2.0 license as printed in full -text in the manual (luaotfload.pdf). - - \url{http://www.gnu.org/licenses/old-licenses/gpl-2.0.html}. - -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" - -local iowrite = io.write -local kpsefind_file = kpse.find_file -local mathfloor = math.floor -local next = next -local osdate = os.date -local ostype = os.type -local stringexplode = string.explode -local stringformat = string.format -local stringlower = string.lower -local stringrep = string.rep -local tableconcat = table.concat -local texiowrite_nl = texio.write_nl -local texiowrite = texio.write -local tonumber = tonumber -local type = type - -do - local runtime = _G.jit and { "jit" , jit.version } - or { "stock", _VERSION } - local stats = status and status.list () - local minimum = luaotfload.min_luatex_version - local actual = { 0, 0, 0 } - if stats then - local major = stats.luatex_version / 100 - local minor = stats.luatex_version % 100 - local revision = stats.luatex_revision --[[ : string ]] - local revno = tonumber (revision) - actual = { major, minor, revno or 0 } - end - - if actual [1] < minimum [1] - or actual == minimum and actual [2] < minimum [2] - or actual == minimum and actual [2] == minimum [2] and actual [3] < minimum [3] - then - texio.write_nl ("term and log", - string.format ("\tFATAL ERROR\n\z - \tLuaotfload requires a Luatex version >= %d.%d.%d.\n\z - \tPlease update your TeX distribution!\n\n", - (unpack or table.unpack) (minimum))) - error "version check failed" - end - luaotfload.runtime = runtime - luaotfload.luatex_version = actual -end - -local C, Ct, P, S = lpeg.C, lpeg.Ct, lpeg.P, lpeg.S -local lpegmatch = lpeg.match - -string.quoted = string.quoted or function (str) - return string.format("%q",str) -end - ---[[doc-- - - XXX: - Creating the config table will be moved to the common - initialization when the times comes. - ---doc]]-- - -config = config or { } -local config = config -config.luaotfload = config.luaotfload or { } - -config.lualibs = config.lualibs or { } -config.lualibs.verbose = false -config.lualibs.prefer_merged = true -config.lualibs.load_extended = true - -require "lualibs" - -local iosavedata = io.savedata -local lfsisdir = lfs.isdir -local lfsisfile = lfs.isfile -local stringsplit = string.split -local tablekeys = table.keys -local tableserialize = table.serialize -local tablesortedkeys = table.sortedkeys -local tabletohash = table.tohash - ---[[doc-- -\fileent{luatex-basics-gen.lua} calls functions from the -\luafunction{texio.*} library; too much for our taste. -We intercept them with dummies. - -Also, it sets up dummies in place of the tables created by the Context -libraries. Since we have loaded the lualibs already this would cause -collateral damage for some libraries whose namespace would be -overridden. We employ our usual backup-restore strategy to work around -this. (Postponing the loading of the lualibs code is not an option -because the functionality is needed by basics-gen itself.) ---doc]]-- - -local dummy_function = function ( ) end -local backup = { - write = texio.write, - write_nl = texio.write_nl, - utilities = utilities, -} - -texio.write, texio.write_nl = dummy_function, dummy_function -require "fontloader-basics-gen.lua" -texio.write, texio.write_nl = backup.write, backup.write_nl -utilities = backup.utilities - -pdf = pdf or { } --- for font-tfm - -require "fontloader-data-con" -require "fontloader-font-ini" -require "fontloader-font-con" -require "fontloader-fonts-enc" -require "fontloader-font-cid" -require "fontloader-font-map" -require "fontloader-font-oti" -require "fontloader-font-otr" -require "fontloader-font-cff" -require "fontloader-font-ttf" -require "fontloader-font-dsp" -require "fontloader-font-oup" -require "fontloader-font-onr" -require "fontloader-font-def" - -fonts = fonts or { } -local fontsnames = fonts.names or { } -fonts.names = fontsnames - -local require_init = { } - -local loadmodule = function (name) - local v = require ("luaotfload-" .. name) - if v then - local mod = { } - local tv = type (v) - if tv == "table" then - mod.name = name - mod.init = v.init - require_init [#require_init + 1] = mod - elseif tv == "function" then - mod.name = name - mod.init = v - require_init [#require_init + 1] = mod - end - end -end - -require "alt_getopt" - -loadmodule "log" --- this populates the luaotfload.log.* namespace -loadmodule "parsers" --- fonts.conf, configuration, and request syntax -loadmodule "configuration" --- configuration file handling -loadmodule "database" -loadmodule "resolvers" --- Font lookup - -local logreport - -local init_modules = function () - --- NB we don’t command the logger at this point. - local todo = #require_init - local ret = true - for i = 1, todo do - local mod = require_init[i] - local name = mod.name - local init = mod.init - if type (init) ~= "function" then - error ("luaotfload broken; module " - .. name .. " missing initializers!") - end - local v = mod.init () - if v == true then - --- evaluated well - elseif type (v) == "table" then - luaotfload[name] = v - else - error ("luaotfload broken; initialization of module " - .. name .. " returned " .. tostring (v) .. ".") - return false - end - end - logreport = luaotfload.log.report - return ret -end - - -local help_messages = { - ["luaotfload-tool"] = [[ - -Usage: %s [OPTIONS...] - - Luaotfload font management and diagnostic utility. - This program is part of the Luaotfload package. - - Valid options are: - -------------------------------------------------------------------------------- - VERBOSITY AND DIAGNOSTICS - - -q --quiet don't output anything - -v --verbose=LEVEL be more verbose (print the searched directories) - -v, -vv .. -vvvvvvvvv set loglevel in unary - --log=stdout redirect log output to stdout - - -V --version print version and exit - -h --help print this message - --diagnose=CHECK run a self test procedure; one of "files", - "environment", "index", "permissions", or - "repository" - -------------------------------------------------------------------------------- - DATABASE - - -u --update update the database - -n --no-reload suppress db update - --no-strip keep redundant information in db - -f --force force re-indexing all fonts - -L --local scan font files in $PWD - -c --no-compress do not gzip index file (text version only) - -l --flush-lookups empty lookup cache of font requests - -D --dry-run skip loading of fonts, just scan - --formats=[+|-]EXTENSIONS set, add, or subtract file formats - -p --prefer-texmf prefer fonts in the TEXMF over system fonts - --max-fonts=N process at most N font files - - --find="font name" query the database for a font name - -F --fuzzy look for approximate matches if --find fails - --limit=n limit display of fuzzy matches to <n> - (default: n = 1) - - -i --info display basic font metadata - -I --inspect display detailed font metadata - - --list=<criterion> output list of entries by field <criterion> - --list=<criterion>:<value> restrict to entries with <criterion>=<value> - --fields=<f1>,<f2>,…,<fn> which fields <f> to print with --list - -b --show-blacklist show blacklisted files - - --bisect=<directive> control database bisection: valid - directives are "start", "stop", "run", "status", - "good", "bad" - -The font database will be saved to - %s - %s - -------------------------------------------------------------------------------- - FONT CACHE - - --cache=<directive> operate on font cache, where <directive> is - "show", "purge", or "erase" - -The font cache will be written to - %s - -]], - mkluatexfontdb = [[ -FATAL ERROR -As of Luaotfload v2.5, legacy behavior is not supported anymore. Please -update your scripts and/or habits! Kthxbye. -]], - short = [[ -Usage: luaotfload-tool [--help] [--version] [--verbose=<lvl>] - [--update] [--force] [--prefer-texmf] [--local] - [--dry-run] [--formats=<extension list>] - [--find=<font name>] [--fuzzy] [--info] [--inspect] - [--list=<criterion>] [--fields=<field list>] - [--cache=<directive>] [--flush-lookups] - [--show-blacklist] [--diagnose=<procedure>] - [--no-compress] [--no-strip] [--local] - [--max-fonts=<n>] [--bisect=<directive>] - -Enter 'luaotfload-tool --help' for a larger list of options. -]] -} - -local help_msg = function (version) - local template = help_messages[version] - local paths = config.luaotfload.paths - local names_plain = paths.index_path_lua - local names_gzip = names_plain .. ".gz" - local names_bin = paths.index_path_luc - - iowrite(stringformat(template, - luaotfload.self, - names_gzip, - names_bin, - caches.getwritablepath (config.luaotfload.paths.cache_dir, ""))) -end - -local about = [[ -%s: - Luaotfload font management and diagnostic utility. - License: GNU GPL v2.0. - Report problems to <https://github.com/lualatex/luaotfload/issues> -]] - -local version_msg = function ( ) - local out = function (...) texiowrite_nl (stringformat (...)) end - local uname = os.uname () - local meta = fonts.names.getmetadata () - - local runtime = luaotfload.runtime - local actual = luaotfload.luatex_version - local status = config.luaotfload.status - local notes = status and status.notes or { } - - out (about, luaotfload.self) - out ("%s version: %q", luaotfload.self, version) - if notes.description then - out ("Luaotfload: %q", notes.description) - end - out ("Revision: %q", notes.revision) - out ("Lua interpreter: %s; version %q", runtime[1], runtime[2]) ---[[out ("Luatex SVN revision: %d", info.luatex_svn)]] --> SVN r5624 - out ("Luatex version: %d.%d", actual [1], actual [2]) - out ("Platform: type=%s name=%s", os.type, os.name) - - local uname_vars = tablesortedkeys (uname) - for i = 1, #uname_vars do - local var = uname_vars[i] - out (" + %8s: %s", var, uname[var]) - end - if meta == false then - out("No database metadata available.") - else - out ("Index: version=%q created=%q modified=%q", - meta.version or "too old", - meta.created or "ages ago", - meta.modified or "ages ago") - end - out "" -end - - ---- makeshift formatting - -local head_adornchars = { - [1] = "*", [2] = "=", [3] = "~", [4] = "-", [5] = "·", -} - -local textwidth = 80 -local wd_leftcolumn = mathfloor(textwidth * .25) -local key_fmt = stringformat([[%%%ds]], wd_leftcolumn) -local val_fmt = [[%s]] -local fieldseparator = ":" -local info_fmt = key_fmt .. fieldseparator .. " " .. val_fmt - -local currentdepth = 0 -local counterstack = { } -- counters per level -local counterformat = "%d" - -local format_counter = function (stack) - local acc = { } - for lvl=1, #stack do - acc[#acc+1] = stringformat(counterformat, stack[lvl]) - end - return tableconcat(acc, ".") -end - -local print_heading = function (title, level) - if not title then return end - local structuredata - if currentdepth == level then -- top is current - counterstack[#counterstack] = counterstack[#counterstack] + 1 - elseif currentdepth < level then -- push new - counterstack[#counterstack+1] = 1 - else -- pop - local diff = currentdepth - level - while diff > 0 do - counterstack[#counterstack] = nil - diff = diff - 1 - end - counterstack[#counterstack] = counterstack[#counterstack] + 1 - end - currentdepth = level - - texiowrite_nl "" - if not level or level > #head_adornchars then - level = #head_adornchars - end - local adornchar = head_adornchars[level] - - local counter = format_counter(counterstack) - - local s = adornchar .. adornchar .. " " - .. counter .. " " - .. title .. " " - texiowrite_nl (s .. stringrep(adornchar, textwidth-utf.len(s))) -end - -local baseindent = " " - ---[[doc-- - - show_info_items -- Together with show_info_table prints the table returned by - readers.getinfo(), recursing into nested tables if appropriate (as necessitated - by Luatex versions 0.78+ which include the pfminfo table in the result. - ---doc]]-- - -local show_info_table show_info_table = function (t, depth) - depth = depth or 0 - local indent = stringrep (baseindent, depth) - local keys = tablesortedkeys (t) - for n = 1, #keys do - local key = keys [n] - local val = t [key] - if type (val) == "table" then - texiowrite_nl (indent .. stringformat (info_fmt, key, "<table>")) - show_info_table (val, depth + 1) - else - texiowrite_nl (indent .. stringformat (info_fmt, key, val)) - end - end -end - -local show_info_items = function (fontinfo) - print_heading (fontinfo.fullname, 1) - texiowrite_nl "" - show_info_table (fontinfo) - texiowrite_nl "" -end - -local p_spacechar = S" \n\r\t\v" -local p_wordchar = (1 - p_spacechar) -local p_whitespace = p_spacechar^1 -local p_word = C(p_wordchar^1) -local p_words = Ct(p_word * (p_whitespace * p_word)^0) - ---- string -> int -> string list -local reflow = function (text, width) - local words - local t_text = type (text) - if t_text == "string" then - words = lpegmatch(p_words, text) - if #words < 2 then - return { text } - end - elseif t_text == "table" then - words = text - if #text < 2 then - return text - end - end - - local space = " " - local utflen = utf.len - local reflowed = { } - - local first = words[1] - local linelen = #first - local line = { first } - - for i=2, #words do - local word = words[i] - local lword = utflen(word) - linelen = linelen + lword + 1 - if linelen > width then - reflowed[#reflowed+1] = tableconcat(line) - linelen = #word - line = { word } - else - line[#line+1] = space - line[#line+1] = word - end - end - reflowed[#reflowed+1] = tableconcat(line) - return reflowed -end - ---- string -> 'a -> string list -local print_field = function (key, val) - val = tostring(val) - local lhs = stringformat(key_fmt, key) .. fieldseparator .. " " - local wd_lhs = #lhs - local lines = reflow(val, textwidth - wd_lhs) - - texiowrite_nl(lhs) - texiowrite(lines[1]) - if #lines > 1 then - local indent = stringrep(" ", wd_lhs) - for i=2, #lines do - texiowrite_nl(indent) - texiowrite (lines[i]) - end - end -end - ---- see luafflib.c -local general_fields = { - --- second: l -> literal | n -> length | d -> date - { "fullname", "l", "font name" }, - { "version", "l", "font version" }, - { "width", "l", "width" }, - { "averagewidth", "l", "average width" }, - { "panosewidth", "l", "panose width" }, - { "weight", "l", "weight indicator" }, - { "pfmweight", "l", "numerical weight" }, - { "panoseweight", "l", "panose weight" }, - { "designsize", "l", "design size" }, - { "minsize", "l", "design size min" }, - { "maxsize", "l", "design size max" }, - { "units", "l", "units per em" }, - { "ascender", "l", "ascender height" }, - { "descender", "l", "descender height" }, - { "capheight", "l", "capital height" }, -} - -local display_general = function (fullinfo) - texiowrite_nl "" - print_heading("General Information", 2) - texiowrite_nl "" - for i=1, #general_fields do - local field = general_fields[i] - local key, mode, desc = unpack(field) - local val - if mode == "l" then - val = fullinfo[key] - elseif mode == "S" then --- style names table - local data = fullinfo[key] - if type (data) == "table" then - if #data > 0 then - for n = 1, #data do - local nth = data[n] - if nth.lang == 1033 then - val = nth.name - goto found - end - end - val = next (data).name - else - val = "" - end - ::found:: - else - val = data - end - elseif mode == "n" then - local v = fullinfo[key] - if v then - val = #fullinfo[key] - end - elseif mode == "d" then - if ostype == "unix" then - val = osdate("%F %T", fullinfo[key]) - else - --- the MS compiler doesn’t support C99, so - --- strftime is missing some functionality; - --- see loslib.c for details. - val = osdate("%Y-%m-d %H:%M:%S", fullinfo[key]) - end - end - if not val then - val = "<none>" - end - print_field(desc, val) - end -end - -local print_features = function (features) - for tag, data in next, features do - print_heading(tag, 4) - for script, languages in next, data do - local field = stringformat(key_fmt, script).. fieldseparator .. " " - local wd_field = #field - local lines = reflow(tablekeys(languages), textwidth - wd_field) - local indent = stringrep(" ", wd_field) - texiowrite_nl(field) - texiowrite(lines[1]) - if #lines > 1 then - for i=1, #lines do - texiowrite_nl(indent .. lines[i]) - end - end - end - end -end - -local display_feature_set = function (set) - print_features(set) -end - -local display_features_type = function (id, feat) - if next (feat) then - print_heading(id, 3) - display_feature_set(feat) - return true - end - return false -end - -local display_features = function (features) - texiowrite_nl "" - print_heading("Features", 2) - - if not display_features_type ("GSUB Features", features.gsub) - or not display_features_type ("GPOS Features", features.gpos) - then - texiowrite_nl("font defines neither gsub nor gpos features") - end -end - -local show_full_info = function (path, subfont) - local rawinfo, warn = fonts.handlers.otf.readers.loadfont (path, subfont) - if not rawinfo then - texiowrite_nl(stringformat([[cannot open font %s]], path)) - return - end - display_general(rawinfo.metadata) - display_features(rawinfo.resources.features) -end - -local subfont_by_name -subfont_by_name = function (lst, askedname, n) - if not n then - return subfont_by_name (lst, askedname, 1) - end - - local font = lst[n] - if font then - if fonts.names.sanitize_fontname (font.fullname) == askedname then - return font - end - return subfont_by_name (lst, askedname, n + 1) - end - return false -end - ---[[doc-- -The font info knows two levels of detail: - - a) basic information returned by readers.getinfo(); and - b) detailed information that is a subset of the font table - returned by readers.loadfont(). ---doc]]-- - -local show_font_info = function (basename, askedname, detail, subfont) - local filenames = fonts.names.data().files - local index = filenames.base[basename] - local fullname = filenames.full[index] - askedname = fonts.names.sanitize_fontname (askedname) - if not fullname then -- texmf - fullname = resolvers.findfile(basename) - end - if fullname then - local shortinfo = fonts.handlers.otf.readers.getinfo (fullname, { - subfont = subfont, - platformnames = true, - rawfamilynames = true, - }) - local nfonts = #shortinfo - if nfonts > 0 then -- true type collection - local subfont - if askedname then - logreport (true, 1, "resolve", - [[%s is part of the font collection %s]], - askedname, basename) - subfont = subfont_by_name(shortinfo, askedname) - end - if subfont then - show_info_items(subfont) - if detail == true then - show_full_info(fullname, subfont) - end - else -- list all subfonts - logreport (true, 1, "resolve", - [[%s is a font collection]], basename) - for subfont = 1, nfonts do - logreport (true, 1, "resolve", - [[Showing info for font no. %d]], - subfont) - show_info_items(shortinfo[subfont]) - if detail == true then - show_full_info(fullname, subfont) - end - end - end - else - show_info_items(shortinfo) - if detail == true then - show_full_info(fullname, subfont) - end - end - else - logreport (true, 1, "resolve", "Font %s not found", filename) - end -end - ---[[-- -Running the scripts triggers one or more actions that have to be -executed in the correct order. To avoid duplication we track them in a -set. ---]]-- - -local action_sequence = { - "config" , "loglevel" , "help" , "version" , - "dumpconf" , "diagnose" , "blacklist" , "cache" , - "flush" , "bisect" , "generate" , "list" , - "query" , -} - -local action_pending = tabletohash(action_sequence, false) - -action_pending.config = true --- always read the configuration -action_pending.loglevel = true --- always set the loglevel -action_pending.generate = false --- this is the default action - -local actions = { } --- (jobspec -> (bool * bool)) list - -actions.loglevel = function (job) - local lvl = job.log_level - if lvl then - luaotfload.log.set_loglevel(lvl) - logreport ("info", 3, "util", "Setting the log level to %d.", lvl) - logreport ("log", 2, "util", "Lua=%q", _VERSION) - end - return true, true -end - -actions.config = function (job) - local defaults = luaotfload.default_config - local vars = config.actions.read (job.extra_config) - config.luaotfload = config.actions.apply (defaults, vars) - config.luaotfload = config.actions.apply (config.luaotfload, job.config) - - --inspect(config.luaotfload) - --os.exit() - if not config.actions.reconfigure () then - return false, false - end - return true, true -end - -actions.version = function (job) - version_msg() - return true, false -end - -actions.dumpconf = function (job) - config.actions.dump () - return true, false -end - -actions.help = function (job) - help_msg (job.help_version or "luaotfload-tool") - return true, false -end - -actions.blacklist = function (job) - fonts.names.read_blacklist() - local n = 0 - for n, entry in next, tablesortedkeys(fonts.names.blacklist) do - iowrite (stringformat("(%d %s)\n", n, entry)) - end - return true, false -end - -actions.generate = function (job) - local _ = fonts.names.update ({ }, job.force_reload, job.dry_run) - local namedata = fonts.names.data () - if namedata then - logreport ("info", 2, "db", - "Fonts in the database: %i", - #namedata.mappings) - return true, true - end - return false, false -end - -------------------------------------------------------------------------------- ---- bisect mode -------------------------------------------------------------------------------- - -local bisect_status_path = caches.getwritablepath ("bisect", "") -local bisect_status_file = bisect_status_path .."/" .. "luaotfload-bisect-status.lua" -local bisect_status_fmt = [[ ---[==[------------------------------------------------------------------------- - This file is generated by Luaotfload. It can be safely deleted. - Creation date: %s. --------------------------------------------------------------------------]==]-- - -%s - ---- vim:ft=lua:ts=8:et:sw=2 -]] - ---[[doc-- - - write_bisect_status -- Write the history of the current bisection to disk. - ---doc]]-- - ---- state list -> bool -local write_bisect_status = function (data) - local payload = tableserialize (data, true) - local status = stringformat (bisect_status_fmt, - osdate ("%Y-%m-d %H:%M:%S", os.time ()), - payload) - if status and iosavedata (bisect_status_file, status) then - logreport ("info", 4, "bisect", - "Bisection state written to %s.", - bisect_status_file) - return true - end - logreport ("info", 0, "bisect", - "Failed to write bisection state to %s.", - bisect_status_file) - return false -end - ---[[doc-- - - read_bisect_status -- Read the bisect log from disk. - ---doc]]-- - ---- unit -> state list -local read_bisect_status = function () - logreport ("info", 4, "bisect", - "Testing for status file: %q.", - bisect_status_file) - if not lfsisfile (bisect_status_file) then - logreport ("info", 2, "bisect", - "No such file: %q.", bisect_status_file) - logreport ("info", 0, "bisect", - "Not in bisect mode.") - return false - end - logreport ("info", 4, "bisect", - "Reading status file: %q.", bisect_status_file) - local success, status = pcall (dofile, bisect_status_file) - if not success then - logreport ("info", 0, "bisect", - "Could not read status file.") - return false - end - return status -end - ---[[doc-- - - bisect_start -- Begin a bisect session. Determines the number of - fonts and sets the initial high, low, and pivot values. - ---doc]]-- - -local bisect_start = function () - if lfsisfile (bisect_status_file) then - logreport ("info", 0, "bisect", - "Bisect session in progress.", - bisect_status_file) - logreport ("info", 0, "bisect", - "Use --bisect=stop to erase it before starting over.") - return false, false - end - logreport ("info", 2, "bisect", - "Starting bisection of font database %q.", - bisect_status_file) - local n = fonts.names.count_font_files () - local pivot = mathfloor (n / 2) - local data = { { 1, n, pivot } } - logreport ("info", 0, "bisect", - "Initializing pivot to %d.", pivot) - if write_bisect_status (data) then - return true, false - end - return false, false -end - ---[[doc-- - - bisect_stop -- Terminate bisection session by removing all state info. - ---doc]]-- - -local bisect_stop = function () - logreport ("info", 3, "bisect", - "Erasing bisection state at %s.", - bisect_status_file) - if lfsisfile (bisect_status_file) then - local success, msg = os.remove (bisect_status_file) - if not success then - logreport ("info", 2, "bisect", - "Failed to erase file %s (%s).", - bisect_status_file, msg) - end - end - if lfsisdir (bisect_status_path) then - local success, msg = os.remove (bisect_status_path) - if not success then - logreport ("info", 2, "bisect", - "Failed to erase directory %s (%s).", - bisect_status_path, msg) - end - end - if lfsisfile (bisect_status_file) then - return false, false - end - return true, false -end - ---[[doc-- - - bisect_terminate -- Wrap up a bisect session by printing the - offending font and removing the state file. - ---doc]]-- - -local bisect_terminate = function (nsteps, culprit) - logreport ("info", 1, "bisect", - "Bisection completed after %d steps.", nsteps) - logreport ("info", 0, "bisect", - "Bad file: %s.", fonts.names.nth_font_filename (culprit)) - logreport ("info", 0, "bisect", - "Run with --bisect=stop to finish bisection.") - return true, false -end - ---[[doc-- - - list_remainder -- Show remaining fonts in bisect slice. - ---doc]]-- - -local list_remainder = function (lo, hi) - local fonts = fonts.names.font_slice (lo, hi) - logreport ("info", 0, "bisect", "%d fonts left.", hi - lo + 1) - for i = 1, #fonts do - logreport ("info", 1, "bisect", " · %2d: %s", lo, fonts[i]) - lo = lo + 1 - end -end - ---[[doc-- - - bisect_set -- Prepare the next bisection step by setting high, low, - and pivot to new values. - - The “run” directive always picks the segment below the pivot so we - can rely on the “outcome parameter” to be referring to that. - ---doc]]-- - -local bisect_set = function (outcome) - local status = read_bisect_status () - if not status then - return false, false - end - - local nsteps = #status - local previous = status[nsteps] - if previous == true then - --- Bisection already completed; we exit early through - --- bisect_terminate() to avoid further writes to the - --- state files that mess up step counting. - nsteps = nsteps - 1 - return bisect_terminate (nsteps, status[nsteps][1]) - end - - local lo, hi, pivot = unpack (previous) - - logreport ("info", 3, "bisect", - "Previous step %d: lo=%d, hi=%d, pivot=%d.", - nsteps, lo, hi, pivot) - - if outcome == "bad" then - hi = pivot - if lo >= hi then --- complete - status[nsteps + 1] = { lo, lo, lo } - status[nsteps + 2] = true - write_bisect_status (status) - return bisect_terminate (nsteps, lo) - end - pivot = mathfloor ((lo + hi) / 2) - logreport ("info", 0, "bisect", - "Continuing with the lower segment: lo=%d, hi=%d, pivot=%d.", - lo, hi, pivot) - elseif outcome == "good" then - lo = pivot + 1 - if lo >= hi then --- complete - status[nsteps + 1] = { lo, lo, lo } - write_bisect_status (status) - status[nsteps + 2] = true - return bisect_terminate (nsteps, lo) - end - pivot = mathfloor ((lo + hi) / 2) - logreport ("info", 0, "bisect", - "Continuing with the upper segment: lo=%d, hi=%d, pivot=%d.", - lo, hi, pivot) - else -- can’t happen - logreport ("info", 0, "bisect", - "What the hell?", lo, hi, pivot) - return false, false - end - - status[nsteps + 1] = { lo, hi, pivot } - write_bisect_status (status) - if hi - lo <= 10 then - list_remainder (lo, hi) - end - return true, false -end - ---[[doc-- - - bisect_status -- Output information about the current bisect session. - ---doc]]-- - -local bisect_status = function () - local status = read_bisect_status () - if not status then - return false, false - end - local nsteps = #status - if nsteps > 1 then - for i = nsteps - 1, 1, -1 do - local step = status[i] - logreport ("info", 2, "bisect", "Step %d: lo=%d, hi=%d, pivot=%d.", - i, unpack (step)) - end - end - local current = status[nsteps] - logreport ("info", 0, "bisect", "Step %d: lo=%d, hi=%d, pivot=%d.", - nsteps, unpack (current)) - return true, false -end - ---[[doc-- - - bisect_run -- Run Luaotfload utilizing the current bisection state. - This should be combined with the --update mode, possibly with the - --force option. - - Luaotfload always tests the segment below the pivot first. - ---doc]]-- - -local bisect_run = function () - local status = read_bisect_status () - if not status then - return false, false - end - local nsteps = #status - local currentstep = nsteps + 1 - local current = status[nsteps] - if current == true then -- final step - current = status[nsteps - 1] - end - local lo, hi, pivot = unpack (current) - logreport ("info", 3, "bisect", "Previous step %d: lo=%d, hi=%d, pivot=%d.", - nsteps, lo, hi, pivot) - logreport ("info", 1, "bisect", "Step %d: Testing fonts from %d to %d.", - currentstep, lo, pivot) - config.luaotfload.misc.bisect = { lo, pivot } - return true, true -end - -local bisect_modes = { - start = bisect_start, - good = function () return bisect_set "good" end, - bad = function () return bisect_set "bad" end, - stop = bisect_stop, - status = bisect_status, - run = bisect_run, -} - -actions.bisect = function (job) - local mode = job.bisect - local runner = bisect_modes[mode] - if not runner then - logreport ("info", 0, "bisect", "Unknown directive %q.", mode) - return false, false - end - return runner (job) -end - -actions.flush = function (job) - local success = fonts.names.flush_lookup_cache() - if success then - local success = fonts.names.save_lookups() - if success then - logreport ("info", 2, "cache", "Lookup cache emptied") - return true, true - end - end - return false, false -end - -local cache_directives = function () - --- These exist only after initialization. - return { - ["purge"] = fonts.names.purge_cache, - ["erase"] = fonts.names.erase_cache, - ["show"] = fonts.names.show_cache, - } -end - -actions.cache = function (job) - local directive = cache_directives()[job.cache] - if not directive or type(directive) ~= "function" then - logreport ("info", 2, "cache", - "Invalid font cache directive %s.", job.cache) - return false, false - end - if directive() then - return true, true - end - return false, false -end - -actions.query = function (job) - - require "luaotfload-features" - - local query = job.query - - local tmpspec = { - name = query, - lookup = "name", - specification = query, - optsize = 0, - features = { }, - } - - tmpspec = fonts.names.handle_request (tmpspec) - - if not tmpspec.size then - tmpspec.size = 655360 --- assume 10pt - end - - local foundname, subfont, success, needle - - if tmpspec.lookup == "name" then - if fonts.definers.resolvers.name (tmpspec) then - needle = tmpspec.resolved - end - elseif tmpspec.lookup == "anon" then - if fonts.definers.resolvers.anon (tmpspec) then - needle = tmpspec.resolved or tmpspec.name - end - elseif tmpspec.lookup == "file" then - needle = tmpspec.name - subfont = tmpspec.sub - end - - if needle then - foundname, _, success = fonts.names.lookup_font_file (tmpspec.name) - end - - if success then - logreport (false, 0, "resolve", "Font %q found!", query) - if subfont then - logreport (false, 0, "resolve", - "Resolved file name %q, subfont nr. %q", - foundname, subfont) - else - logreport (false, 0, "resolve", - "Resolved file name %q", foundname) - end - if job.show_info then - logreport (false, 3, "resolve", "Dump extra info.") - show_font_info (foundname, query, job.full_info, subfont) - iowrite "\n" - end - else - logreport (false, 0, "resolve", "Cannot find %q in index.", query) - if job.fuzzy == true then - logreport (false, 0, "resolve", - "Looking for close matches, this may take a while ...") - local _success = fonts.names.find_closest(query, job.fuzzy_limit) - else - logreport (false, 0, "resolve", - "Hint: use the --fuzzy option to display suggestions.", - query) - end - end - return true, true -end - ---- --list=<criterion> ---- --list=<criterion>:<value> ---- ---- --list=<criterion> --fields=<f1>,<f2>,<f3>,...<fn> - -local get_fields get_fields = function (entry, fields, acc, n) - if not acc then - return get_fields (entry, fields, { }, 1) - end - - local field = fields [n] - if field then - local chain = stringsplit (field, "->") - local tmp = entry - for i = 1, #chain - 1 do - tmp = tmp [chain [i]] - if not tmp then - --- invalid field - break - end - end - if tmp then - local value = tmp [chain [#chain]] - acc[#acc+1] = value or false - else - acc[#acc+1] = false - end - return get_fields (entry, fields, acc, n+1) - end - return acc -end - -local separator = "\t" --- could be “,” for csv - -local format_fields format_fields = function (fields, acc, n) - if not acc then - return format_fields(fields, { }, 1) - end - - local field = fields[n] - if field ~= nil then - if field == false then - acc[#acc+1] = "<none>" - else - acc[#acc+1] = tostring(field) - end - return format_fields(fields, acc, n+1) - end - return tableconcat(acc, separator) -end - -local set_primary_field -set_primary_field = function (fields, addme, acc, n) - if not acc then - return set_primary_field(fields, addme, { addme }, 1) - end - - local field = fields[n] - if field then - if field ~= addme then - acc[#acc+1] = field - end - return set_primary_field(fields, addme, acc, n+1) - end - return acc -end - -actions.list = function (job) - local criterion = job.criterion - local asked_fields = job.asked_fields - local name_index = fonts.names.data () - - if asked_fields then - local splitcomma = luaotfload.parsers.splitcomma - asked_fields = lpegmatch(splitcomma, asked_fields) - end - - if not asked_fields then - --- some defaults - asked_fields = { "plainname", "version", } - end - - if not name_index then - name_index = fonts.names.load() - end - - local mappings = name_index.mappings - local nmappings = #mappings - - if criterion == "*" then - logreport (false, 1, "list", "All %d entries", nmappings) - for i=1, nmappings do - local entry = mappings[i] - local fields = get_fields(entry, asked_fields) - --- we could collect these instead ... - local formatted = format_fields(fields) - texiowrite_nl(formatted) - end - - else - criterion = stringexplode(criterion, ":") --> { field, value } - local asked_value = criterion[2] - criterion = criterion[1] - asked_fields = set_primary_field(asked_fields, criterion) - - logreport (false, 1, "list", "By %s", criterion) - - --- firstly, build a list of fonts to operate on - local targets = { } - if asked_value then --- only those whose value matches - logreport (false, 2, "list", "Restricting to value %s", asked_value) - for i=1, nmappings do - local entry = mappings[i] - if entry[criterion] - and tostring(entry[criterion]) == asked_value - then - targets[#targets+1] = entry - end - end - - else --- whichever have the field, sorted - local categories, by_category = { }, { } - for i=1, nmappings do - local entry = mappings[i] - local tmp = entry - local chain = stringsplit (criterion, "->") - for i = 1, #chain - 1 do - tmp = tmp [chain [i]] - if not tmp then - break - end - end - local value = tmp and tmp [chain [#chain]] or "<none>" - if value then - --value = tostring(value) - local entries = by_category[value] - if not entries then - entries = { entry } - categories[#categories+1] = value - else - entries[#entries+1] = entry - end - by_category[value] = entries - end - end - table.sort(categories) - - for i=1, #categories do - local entries = by_category[categories[i]] - for j=1, #entries do - targets[#targets+1] = entries[j] - end - end - end - local ntargets = #targets - logreport (false, 2, "list", "%d entries", ntargets) - - --- now, output the collection - for i=1, ntargets do - local entry = targets[i] - local fields = get_fields(entry, asked_fields) - local formatted = format_fields(fields) - texiowrite_nl(formatted) - end - end - - texiowrite_nl "" - - return true, true -end - -actions.diagnose = function (job) - --- diagnostics are loaded on demand - local diagnose = require "luaotfload-diagnostics.lua" - return diagnose (job) -end - ---- stuff to be carried out prior to exit - -local finalizers = { } - ---- returns false if at least one of the actions failed, mainly ---- for closing io channels -local finalize = function () - local success = true - for _, fun in next, finalizers do - if type (fun) == "function" then - if fun () == false then success = false end - end - end - return success -end - ---[[-- -Command-line processing. -luaotfload-tool relies on the script alt_getopt to process argv and -analyzes its output. - -TODO with extended lualibs we have the functionality from the -environment.* namespace that could eliminate the dependency on -alt_getopt. ---]]-- - -local process_cmdline = function ( ) -- unit -> jobspec - local result = { -- jobspec - force_reload = nil, - full_info = false, - criterion = "", - query = "", - log_level = nil, - bisect = nil, - config = { db = { }, misc = { }, run = { live = false }, paths = { } }, - } - - local long_options = { - ["bisect"] = 1, - cache = 1, - conf = 1, - diagnose = 1, - dumpconf = 0, - ["dry-run"] = "D", - ["flush-lookups"] = "l", - fields = 1, - find = 1, - force = "f", - formats = 1, - fuzzy = "F", - help = "h", - info = "i", - inspect = "I", - limit = 1, - list = 1, - ["local"] = "L", - log = 1, - ["max-fonts"] = 1, - ["no-compress"] = "c", - ["no-reload"] = "n", - ["no-strip"] = 0, - ["skip-read"] = "R", - ["prefer-texmf"] = "p", - ["print-conf"] = 0, - quiet = "q", - ["show-blacklist"] = "b", - stats = "S", - update = "u", - verbose = 1, - version = "V", - } - - local short_options = "bcDfFiIlLnpqRSuvVh" - - local options, _, optarg = - alt_getopt.get_ordered_opts (arg, short_options, long_options) - - local nopts = #options - for n=1, nopts do - local v = options[n] - if v == "q" then - result.log_level = 0 - elseif v == "u" then - action_pending["generate"] = true - elseif v == "v" then - local lvl = result.log_level - if not lvl or lvl < 1 then - lvl = 1 - else - lvl = lvl + 1 - end - result.log_level = lvl - elseif v == "V" then - action_pending["version"] = true - elseif v == "h" then - action_pending["help"] = true - elseif v == "f" then - result.update = true - result.force_reload = 1 - elseif v == "verbose" then - local lvl = optarg[n] - if lvl then - lvl = tonumber(lvl) - result.log_level = lvl - end - elseif v == "log" then - local str = optarg[n] - if str then - finalizers = luaotfload.log.set_logout(str, finalizers) - end - elseif v == "find" then - action_pending["query"] = true - result.query = optarg[n] - elseif v == "F" then - result.fuzzy = true - elseif v == "limit" then - local lim = optarg[n] - if lim then - result.fuzzy_limit = tonumber(lim) - end - elseif v == "i" then - result.show_info = true - elseif v == "I" then - result.show_info = true - result.full_info = true - elseif v == "l" then - action_pending["flush"] = true - elseif v == "L" then - action_pending["generate"] = true - result.config.db.scan_local = true - elseif v == "list" then - action_pending["list"] = true - result.criterion = optarg[n] - elseif v == "fields" then - result.asked_fields = optarg[n] - elseif v == "cache" then - action_pending["cache"] = true - result.cache = optarg[n] - elseif v == "D" then - result.dry_run = true - elseif v == "p" then - fonts.names.set_location_precedence { - "local", "texmf", "system" - } - elseif v == "b" then - action_pending["blacklist"] = true - elseif v == "diagnose" then - action_pending["diagnose"] = true - result.asked_diagnostics = optarg[n] - elseif v == "formats" then - result.config.db.formats = optarg[n] - --names.set_font_filter (optarg[n]) - elseif v == "n" then - result.config.db.update_live = false - elseif v == "S" then - result.config.misc.statistics = true - elseif v == "R" then - --- dev only, undocumented - result.config.db.skip_read = true - elseif v == "c" then - result.config.db.compress = false - elseif v == "no-strip" then - result.config.db.strip = false - elseif v == "max-fonts" then - local n = optarg[n] - if n then - n = tonumber(n) - if n and n > 0 then - result.config.db.max_fonts = n - end - end - elseif v == "bisect" then - result.bisect = optarg[n] - action_pending.bisect = true - elseif v == "conf" then - local confname = optarg[n] - if confname then - local extra = stringexplode (optarg[n], ",+") - if extra then - local extra_config = result.extra_config - if extra_config then - table.append (extra_config, extra) - else - result.extra_config = extra - end - end - end - elseif v == "dumpconf" then - action_pending["dumpconf"] = true - elseif v == "print-conf" then - result.print_config = true - end - end - - if nopts == 0 then - action_pending["help"] = true - result.help_version = "short" - end - return result -end - -local main = function ( ) -- unit -> int - if init_modules () == false then return -42 end - - local retval = 0 - local job = process_cmdline() - --- inspect(action_pending) --- inspect(job) - - for i=1, #action_sequence do - local actionname = action_sequence[i] - local exit = false - if action_pending[actionname] then - logreport ("log", 3, "util", "Preparing for task", "%s", actionname) - - local action = actions[actionname] - local success, continue = action(job) - - if not success then - logreport (false, 0, "util", - "Failed to execute task.", "%s", actionname) - retval = -1 - exit = true - elseif not continue then - logreport (false, 3, "util", - "Task completed, exiting.", "%s", actionname) - exit = true - else - logreport (false, 3, "util", - "Task completed successfully.", "%s", actionname) - end - end - if exit then break end - end - - if finalize () == false then - retval = -1 - end - - --texiowrite_nl"" - return retval -end - -return main() - --- vim:tw=71:sw=4:ts=4:expandtab diff --git a/tex/compat/luaotfload/luaotfload.sty b/tex/compat/luaotfload/luaotfload.sty deleted file mode 100644 index 45744d15053410d84b5acdf32eb9643a0aad1223..0000000000000000000000000000000000000000 --- a/tex/compat/luaotfload/luaotfload.sty +++ /dev/null @@ -1,50 +0,0 @@ -%% Copyright (C) 2009-2017 -%% -%% by Elie Roux <elie.roux@telecom-bretagne.eu> -%% and Khaled Hosny <khaledhosny@eglug.org> -%% and Philipp Gesang <phg@phi-gamma.net> -%% and Dohyun Kim <nomosnomos@gmail.com> -%% and David Carlisle <d.p.carlisle@gmail.com> -%% -%% This file is part of Luaotfload. -%% -%% Home: https://github.com/lualatex/luaotfload -%% Support: <lualatex-dev@tug.org>. -%% -%% Luaotfload is under the GPL v2.0 (exactly) license. -%% -%% ---------------------------------------------------------------------------- -%% -%% Luaotfload is free software; you can redistribute it and/or -%% modify it under the terms of the GNU General Public License -%% as published by the Free Software Foundation; version 2 -%% of the License. -%% -%% Luaotfload is distributed in the hope that it will be useful, -%% but WITHOUT ANY WARRANTY; without even the implied warranty of -%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -%% GNU General Public License for more details. -%% -%% You should have received a copy of the GNU General Public License -%% along with Luaotfload; if not, see <http://www.gnu.org/licenses/>. -%% -%% ---------------------------------------------------------------------------- -%% -%% Classical Plain+\LATEX package initialization. -%% -\csname ifluaotfloadloaded\endcsname -\let\ifluaotfloadloaded\endinput -\ifx\newluafunction\undefined - \input ltluatex -\fi -\ifdefined\ProvidesPackage - \ProvidesPackage{luaotfload}% - %% FIXME The date is meaningless, we need to find a way to - %% use the git revision instead. - [2017/01/29 v2.8 OpenType layout system] -\fi -\directlua{ - require('luaotfload-main') - local _void = luaotfload.main () -} - diff --git a/tex/compat/luatex85/luatex85.dtx b/tex/compat/luatex85/luatex85.dtx deleted file mode 100644 index 3d1da23c57925513f2f678b4c4ee7c2d60adb491..0000000000000000000000000000000000000000 --- a/tex/compat/luatex85/luatex85.dtx +++ /dev/null @@ -1,277 +0,0 @@ -% \iffalse -%% Source File: luatex85.dtx -%% Copyright 2015-2016 LaTeX3 project -%% -%% This file may be distributed under the terms of the LPPL. -%% See README for details. -% -%<*dtx> - \ProvidesFile{luatex85.dtx} -%</dtx> -%<package>\ifx\ProvidesPackage\undefined -%<package>\def\next#1#2[#3]{\wlog{#2 #3}\expandafter\gdef -%<package>\csname ver@luatex85.sty\endcsname{#3}} -%<package>\expandafter\next\fi -%<package>\ProvidesPackage{luatex85} -%<driver> \ProvidesFile{luatex85.drv} -% \fi -% \ProvidesFile{luatex85.dtx} - [2016/06/15 v1.4 pdftex aliases for luatex] -% -% \iffalse -%<*driver> -\documentclass{ltxdoc} -\begin{document} -\DocInput{luatex85.dtx} -\end{document} -%</driver> -% \fi -% -% \hfuzz0.6pt -% -% \GetFileInfo{luatex85.dtx} -% -% \title{The \textsf{luatex85} Package\thanks{This file -% has version number \fileversion, last -% revised \filedate. -% Please report any issues at https://github.com/josephwright/luatex85/issues}} -% \author{LaTeX3 project} -% \date{\filedate} -% \maketitle -% -% \section{Introduction} -% -% Lua\TeX\ 0.85 and 0.87 contain many changes from Lua\TeX~0.80 as contained in \TeX{}Live 2014. -% Most notably almost all the pdf\TeX\ extended primitves with names -% \verb|\pdf...| have been renamed or removed. Lua\TeX\ is aiming for -% a cleaner separation of the ``back end'' PDF generation (that -% corresponds to the work of a dvi driver with classical \TeX). -% -% There are many other changes and bug fixes in the Lua\TeX\ sources, -% however this package is just concerned with compatibility for -% documents or packages using the pdf\TeX\ primitives. -% -% The changes are of several types: -% -% A few commands have been removed, -% as the facilities are achievable in Lua (mostly these had already -% been removed in earlier release). -% -% Some commands have been ``adopted'' as Lua\TeX\ primitives and so -% lose their \verb|\pdf| prefix (and in some cases are renamed) -% so \verb|\pdfsavepos| becomes \verb|\savepos|, but \verb|\pdfoutput| -% becomes \verb|\outputmode|. -% -% The majority of the ``back end'' commands have been removed and -% replaced by calls to one of three new primitives, -% \verb|\pdffeedback|, \verb|\pdfextension| and \verb|\pdfvariable| -% These take keywords so for example \verb|\pdfliteral| becomes -% \verb|\pdfextension literal|. -% -% The Lua\TeX\ manual lists suitable compatibility definitions -% that may be made so that documents can continue to use the old -% names. Mostly this package just consists of those definitions, with -% minor changes in some cases. (Mostly different choices over the use -% of \verb|\protected| or \verb|\edef|.) -% -% In general it is recommended that packages are updated to use the -% new primitive Lua\TeX\ syntax when used with Lua\TeX, but until -% packages are updated authors may find that adding\\% -% \verb|\RequirePackage{luatex85}|\\ -% as the first line of their -% document helps with the use of older packages with the new Lua\TeX. -% -% As noted above, there are other changes in Lua\TeX, notably the -% removal of the |\verb\write18| syntax for accessing system commands. -% The \LaTeX\ \textsf{tools} bundle includes -% the \textsf{shellesc} package which emulates -% \verb|\write18| as well as providing an alternative -% \verb|\Shellescape| syntax that may be used with all engines. -% -% Note that if packages are found that require \textsf{luatex85} -% you may want to contact the authors asking that the packages -% be updated to current Lua\TeX\ syntax. The \textsf{luatex85} package -% should be seen as a temporary aid to improve compatibility during -% the transition towards Lua\TeX~1.0 it is not intended that future -% documents should always have to load this compatibility emulation. -% -% The package is designed to also be usable with plain Lua\TeX. -% -% -% \section{Implementation} -% -% \begin{macrocode} -%<*package> -% \end{macrocode} -% -% \subsection{Checking the engine} -% \begin{macrocode} -\ifx\pdfvariable\undefined - \expandafter\endinput -\fi -% \end{macrocode} - -% \subsection{Commands promoted to Lua\TeX\ primitives.} -% -% -% \begin{macrocode} -\let\pdfpagewidth \pagewidth -\let\pdfpageheight \pageheight -\let\pdfadjustspacing \adjustspacing -\let\pdfprotrudechars \protrudechars -\let\pdfnoligatures \ignoreligaturesinfont -\let\pdffontexpand \expandglyphsinfont -\let\pdfcopyfont \copyfont -\let\pdfxform \saveboxresource -\let\pdflastxform \lastsavedboxresourceindex -\let\pdfrefxform \useboxresource -\let\pdfximage \saveimageresource -\let\pdflastximage \lastsavedimageresourceindex -\let\pdflastximagepages \lastsavedimageresourcepages -\let\pdfrefximage \useimageresource -\let\pdfsavepos \savepos -\let\pdflastxpos \lastxpos -\let\pdflastypos \lastypos -\let\pdfoutput \outputmode -\let\pdfdraftmode \draftmode -\let\pdfpxdimen \pxdimen -\let\pdfinsertht \insertht -\let\pdfnormaldeviate \normaldeviate -\let\pdfuniformdeviate \uniformdeviate -\let\pdfsetrandomseed \setrandomseed -\let\pdfrandomseed \randomseed -\let\pdfprimitive \primitive -\let\ifpdfprimitive \ifprimitive -\let\ifpdfabsnum \ifabsnum -\let\ifpdfabsdim \ifabsdim -% \end{macrocode} -% Use |\enableprimitives| here in case of conflict with tracefnt. -% \begin{macrocode} -\directlua{tex.enableprimitives('pdf',{'tracingfonts'})} -% \end{macrocode} -% -% \subsection{Commands converted to constants} -% The |\pdffeedback| version is not defined in dvi mode and (currently) is -% curiously defined to be 40 in pdf mode, so define these as constant values. -% \begin{macrocode} -\protected\def\pdftexversion {\numexpr 140\relax} - \def\pdftexrevision {7} -%\protected\def\pdftexversion {\numexpr\pdffeedback version\relax} -% \def\pdftexrevision {\pdffeedback revision} -% \end{macrocode} -% -% \subsection{Commands converted to \cs{pdffeedback}} -% Expandable commands use a simple |\def|. Internal registers that -% were accessed via |\the| in PDF\TeX\ use a |\protected| definition -% using |\numexpr| terminated by an explicit |\relax|. -% \begin{macrocode} -\protected\def\pdflastlink {\numexpr\pdffeedback lastlink\relax} -\protected\def\pdfretval {\numexpr\pdffeedback retval\relax} -\protected\def\pdflastobj {\numexpr\pdffeedback lastobj\relax} -\protected\def\pdflastannot {\numexpr\pdffeedback lastannot\relax} - \def\pdfxformname {\pdffeedback xformname} -{\outputmode=1 - \xdef\pdfcreationdate {\pdffeedback creationdate} -} - \def\pdffontname {\pdffeedback fontname} - \def\pdffontobjnum {\pdffeedback fontobjnum} - \def\pdffontsize {\pdffeedback fontsize} - \def\pdfpageref {\pdffeedback pageref} - \def\pdfcolorstackinit {\pdffeedback colorstackinit} -% \end{macrocode} -% -% \subsection{Commands converted to calls to \cs{pdfextension}} -% These use a |\protected| definition. Commands that take no following -% argument are currently terminated by |\relax| as suggested in the -% Lua\TeX\ manual, although it would be appear to be sufficient to -% consistently terminate these commands with a space. -% \begin{macrocode} -\protected\def\pdfliteral {\pdfextension literal} -\protected\def\pdfcolorstack {\pdfextension colorstack} -\protected\def\pdfsetmatrix {\pdfextension setmatrix} -\protected\def\pdfsave {\pdfextension save\relax} -\protected\def\pdfrestore {\pdfextension restore\relax} -\protected\def\pdfobj {\pdfextension obj } -\protected\def\pdfrefobj {\pdfextension refobj } -\protected\def\pdfannot {\pdfextension annot } -\protected\def\pdfstartlink {\pdfextension startlink } -\protected\def\pdfendlink {\pdfextension endlink\relax} -\protected\def\pdfoutline {\pdfextension outline } -\protected\def\pdfdest {\pdfextension dest } -\protected\def\pdfthread {\pdfextension thread } -\protected\def\pdfstartthread {\pdfextension startthread } -\protected\def\pdfendthread {\pdfextension endthread\relax} -\protected\def\pdfinfo {\pdfextension info } -\protected\def\pdfcatalog {\pdfextension catalog } -\protected\def\pdfnames {\pdfextension names } -\protected\def\pdfincludechars {\pdfextension includechars } -\protected\def\pdffontattr {\pdfextension fontattr } -\protected\def\pdfmapfile {\pdfextension mapfile } -\protected\def\pdfmapline {\pdfextension mapline } -\protected\def\pdftrailer {\pdfextension trailer } -\protected\def\pdfglyphtounicode {\pdfextension glyphtounicode } -% \end{macrocode} -% -% \subsection{Commands converted to calls to \cs{pdfvariable}} -% Currently as suggested in the manual the call to |\pdfvariable| has -% no explict termination, and relies on the fact that no variable name -% is a prefix of another. |\edef| is used to save one expansion step -% when these comands are used the definition directly access the -% internal command token. -% \begin{macrocode} -\protected\edef\pdfcompresslevel {\pdfvariable compresslevel} -\protected\edef\pdfobjcompresslevel {\pdfvariable objcompresslevel} -\protected\edef\pdfdecimaldigits {\pdfvariable decimaldigits} -\protected\edef\pdfgamma {\pdfvariable gamma} -\protected\edef\pdfimageresolution {\pdfvariable imageresolution} -\protected\edef\pdfimageapplygamma {\pdfvariable imageapplygamma} -\protected\edef\pdfimagegamma {\pdfvariable imagegamma} -\protected\edef\pdfimagehicolor {\pdfvariable imagehicolor} -% \end{macrocode} -% Note that |\pdfimageaddfilename| was never actually in PDF\TeX, -% But is included here so that all the |\pdfvariable| cases are covered. -% \begin{macrocode} -\protected\edef\pdfimageaddfilename {\pdfvariable imageaddfilename} -% \end{macrocode} -% \begin{macrocode} -\protected\edef\pdfpkresolution {\pdfvariable pkresolution} -\protected\edef\pdfinclusioncopyfonts {\pdfvariable inclusioncopyfonts} -\protected\edef\pdfinclusionerrorlevel {\pdfvariable inclusionerrorlevel} -% \end{macrocode} -% Note that |\pdfreplacefont| was never in public releases of -% PDF\TeX, It was in Lua\TeX0.85, but discussion on luatex list -% lead to it being removed in 0.87 -% \begin{macrocode} -%\protected\edef\pdfreplacefont {\pdfvariable replacefont} -% \end{macrocode} -% \begin{macrocode} -\protected\edef\pdfgentounicode {\pdfvariable gentounicode} -\protected\edef\pdfpagebox {\pdfvariable pagebox} -\protected\edef\pdfminorversion {\pdfvariable minorversion} -\protected\edef\pdfuniqueresname {\pdfvariable uniqueresname} -\protected\edef\pdfhorigin {\pdfvariable horigin} -\protected\edef\pdfvorigin {\pdfvariable vorigin} -\protected\edef\pdflinkmargin {\pdfvariable linkmargin} -\protected\edef\pdfdestmargin {\pdfvariable destmargin} -\protected\edef\pdfthreadmargin {\pdfvariable threadmargin} -\protected\edef\pdfpagesattr {\pdfvariable pagesattr} -\protected\edef\pdfpageattr {\pdfvariable pageattr} -\protected\edef\pdfpageresources {\pdfvariable pageresources} -% \end{macrocode} -% Note that |\pdfxformattr| and |\pdfxformresources| were never -% in PDF\TeX, But are included here so that all the -% |\pdfvariable| cases are covered. -% \begin{macrocode} -\protected\edef\pdfxformattr {\pdfvariable xformattr} -\protected\edef\pdfxformresources {\pdfvariable xformresources} -% \end{macrocode} -% \begin{macrocode} -\protected\edef\pdfpkmode {\pdfvariable pkmode} -% \end{macrocode} -% -% \begin{macrocode} -%</package> -% \end{macrocode} -% -% \Finale -% diff --git a/tex/compat/luatex85/luatex85.ins b/tex/compat/luatex85/luatex85.ins deleted file mode 100644 index 8a9b7e93442a253df1fdc436bd96ba305eec5323..0000000000000000000000000000000000000000 --- a/tex/compat/luatex85/luatex85.ins +++ /dev/null @@ -1,10 +0,0 @@ -\input docstrip -\keepsilent -\preamble -\endpreamble - -\askforoverwritefalse - -\generate{\file{luatex85.sty}{\from{luatex85.dtx}{package}}} - -\endbatchfile diff --git a/tex/compat/luatex85/luatex85.sty b/tex/compat/luatex85/luatex85.sty deleted file mode 100644 index 738a1aafdfb227a7294b11b333351fbfe847f63f..0000000000000000000000000000000000000000 --- a/tex/compat/luatex85/luatex85.sty +++ /dev/null @@ -1,122 +0,0 @@ -%% -%% This is file `luatex85.sty', -%% generated with the docstrip utility. -%% -%% The original source files were: -%% -%% luatex85.dtx (with options: `package') -%% -%% Source File: luatex85.dtx -%% Copyright 2015-2016 LaTeX3 project -%% -%% This file may be distributed under the terms of the LPPL. -%% See README for details. -\ifx\ProvidesPackage\undefined -\def\next#1#2[#3]{\wlog{#2 #3}\expandafter\gdef -\csname ver@luatex85.sty\endcsname{#3}} -\expandafter\next\fi -\ProvidesPackage{luatex85} - [2016/06/15 v1.4 pdftex aliases for luatex] -\ifx\pdfvariable\undefined - \expandafter\endinput -\fi - -\let\pdfpagewidth \pagewidth -\let\pdfpageheight \pageheight -\let\pdfadjustspacing \adjustspacing -\let\pdfprotrudechars \protrudechars -\let\pdfnoligatures \ignoreligaturesinfont -\let\pdffontexpand \expandglyphsinfont -\let\pdfcopyfont \copyfont -\let\pdfxform \saveboxresource -\let\pdflastxform \lastsavedboxresourceindex -\let\pdfrefxform \useboxresource -\let\pdfximage \saveimageresource -\let\pdflastximage \lastsavedimageresourceindex -\let\pdflastximagepages \lastsavedimageresourcepages -\let\pdfrefximage \useimageresource -\let\pdfsavepos \savepos -\let\pdflastxpos \lastxpos -\let\pdflastypos \lastypos -\let\pdfoutput \outputmode -\let\pdfdraftmode \draftmode -\let\pdfpxdimen \pxdimen -\let\pdfinsertht \insertht -\let\pdfnormaldeviate \normaldeviate -\let\pdfuniformdeviate \uniformdeviate -\let\pdfsetrandomseed \setrandomseed -\let\pdfrandomseed \randomseed -\let\pdfprimitive \primitive -\let\ifpdfprimitive \ifprimitive -\let\ifpdfabsnum \ifabsnum -\let\ifpdfabsdim \ifabsdim -\directlua{tex.enableprimitives('pdf',{'tracingfonts'})} -\protected\def\pdftexversion {\numexpr 140\relax} - \def\pdftexrevision {7} -\protected\def\pdflastlink {\numexpr\pdffeedback lastlink\relax} -\protected\def\pdfretval {\numexpr\pdffeedback retval\relax} -\protected\def\pdflastobj {\numexpr\pdffeedback lastobj\relax} -\protected\def\pdflastannot {\numexpr\pdffeedback lastannot\relax} - \def\pdfxformname {\pdffeedback xformname} -{\outputmode=1 - \xdef\pdfcreationdate {\pdffeedback creationdate} -} - \def\pdffontname {\pdffeedback fontname} - \def\pdffontobjnum {\pdffeedback fontobjnum} - \def\pdffontsize {\pdffeedback fontsize} - \def\pdfpageref {\pdffeedback pageref} - \def\pdfcolorstackinit {\pdffeedback colorstackinit} -\protected\def\pdfliteral {\pdfextension literal} -\protected\def\pdfcolorstack {\pdfextension colorstack} -\protected\def\pdfsetmatrix {\pdfextension setmatrix} -\protected\def\pdfsave {\pdfextension save\relax} -\protected\def\pdfrestore {\pdfextension restore\relax} -\protected\def\pdfobj {\pdfextension obj } -\protected\def\pdfrefobj {\pdfextension refobj } -\protected\def\pdfannot {\pdfextension annot } -\protected\def\pdfstartlink {\pdfextension startlink } -\protected\def\pdfendlink {\pdfextension endlink\relax} -\protected\def\pdfoutline {\pdfextension outline } -\protected\def\pdfdest {\pdfextension dest } -\protected\def\pdfthread {\pdfextension thread } -\protected\def\pdfstartthread {\pdfextension startthread } -\protected\def\pdfendthread {\pdfextension endthread\relax} -\protected\def\pdfinfo {\pdfextension info } -\protected\def\pdfcatalog {\pdfextension catalog } -\protected\def\pdfnames {\pdfextension names } -\protected\def\pdfincludechars {\pdfextension includechars } -\protected\def\pdffontattr {\pdfextension fontattr } -\protected\def\pdfmapfile {\pdfextension mapfile } -\protected\def\pdfmapline {\pdfextension mapline } -\protected\def\pdftrailer {\pdfextension trailer } -\protected\def\pdfglyphtounicode {\pdfextension glyphtounicode } -\protected\edef\pdfcompresslevel {\pdfvariable compresslevel} -\protected\edef\pdfobjcompresslevel {\pdfvariable objcompresslevel} -\protected\edef\pdfdecimaldigits {\pdfvariable decimaldigits} -\protected\edef\pdfgamma {\pdfvariable gamma} -\protected\edef\pdfimageresolution {\pdfvariable imageresolution} -\protected\edef\pdfimageapplygamma {\pdfvariable imageapplygamma} -\protected\edef\pdfimagegamma {\pdfvariable imagegamma} -\protected\edef\pdfimagehicolor {\pdfvariable imagehicolor} -\protected\edef\pdfimageaddfilename {\pdfvariable imageaddfilename} -\protected\edef\pdfpkresolution {\pdfvariable pkresolution} -\protected\edef\pdfinclusioncopyfonts {\pdfvariable inclusioncopyfonts} -\protected\edef\pdfinclusionerrorlevel {\pdfvariable inclusionerrorlevel} -\protected\edef\pdfgentounicode {\pdfvariable gentounicode} -\protected\edef\pdfpagebox {\pdfvariable pagebox} -\protected\edef\pdfminorversion {\pdfvariable minorversion} -\protected\edef\pdfuniqueresname {\pdfvariable uniqueresname} -\protected\edef\pdfhorigin {\pdfvariable horigin} -\protected\edef\pdfvorigin {\pdfvariable vorigin} -\protected\edef\pdflinkmargin {\pdfvariable linkmargin} -\protected\edef\pdfdestmargin {\pdfvariable destmargin} -\protected\edef\pdfthreadmargin {\pdfvariable threadmargin} -\protected\edef\pdfpagesattr {\pdfvariable pagesattr} -\protected\edef\pdfpageattr {\pdfvariable pageattr} -\protected\edef\pdfpageresources {\pdfvariable pageresources} -\protected\edef\pdfxformattr {\pdfvariable xformattr} -\protected\edef\pdfxformresources {\pdfvariable xformresources} -\protected\edef\pdfpkmode {\pdfvariable pkmode} -\endinput -%% -%% End of file `luatex85.sty'. diff --git a/tex/compat/luatexbase/luatexbase-attr.sty b/tex/compat/luatexbase/luatexbase-attr.sty deleted file mode 100644 index 5bd229cfd5f5b5070eb3231a853a0cc93fd1d7cc..0000000000000000000000000000000000000000 --- a/tex/compat/luatexbase/luatexbase-attr.sty +++ /dev/null @@ -1,14 +0,0 @@ - -\ifx - \ProvidesPackage\undefined\begingroup\def\ProvidesPackage - #1#2[#3]{\endgroup\immediate\write-1{Package: #1 #3}} -\fi -\ProvidesPackage{luatexbase-attr} -[2015/10/04 v1.3 - luatexbase interface to LuaTeX (legacy subpackage) -] -\ifx\RequirePackage\undefined - \input{luatexbase.sty}% -\else - \RequirePackage{luatexbase} -\fi diff --git a/tex/compat/luatexbase/luatexbase-cctb.sty b/tex/compat/luatexbase/luatexbase-cctb.sty deleted file mode 100644 index b49771228a433a9c23179e5e4d1f9b90f9a5ca78..0000000000000000000000000000000000000000 --- a/tex/compat/luatexbase/luatexbase-cctb.sty +++ /dev/null @@ -1,14 +0,0 @@ - -\ifx - \ProvidesPackage\undefined\begingroup\def\ProvidesPackage - #1#2[#3]{\endgroup\immediate\write-1{Package: #1 #3}} -\fi -\ProvidesPackage{luatexbase-cctb} -[2015/10/04 v1.3 - luatexbase interface to LuaTeX (legacy subpackage) -] -\ifx\RequirePackage\undefined - \input{luatexbase.sty}% -\else - \RequirePackage{luatexbase} -\fi diff --git a/tex/compat/luatexbase/luatexbase-compat.sty b/tex/compat/luatexbase/luatexbase-compat.sty deleted file mode 100644 index b7e3e105573f333db5342f0d30bd057397461bd0..0000000000000000000000000000000000000000 --- a/tex/compat/luatexbase/luatexbase-compat.sty +++ /dev/null @@ -1,14 +0,0 @@ - -\ifx - \ProvidesPackage\undefined\begingroup\def\ProvidesPackage - #1#2[#3]{\endgroup\immediate\write-1{Package: #1 #3}} -\fi -\ProvidesPackage{luatexbase-compat} -[2015/10/04 v1.3 - luatexbase interface to LuaTeX (legacy subpackage) -] -\ifx\RequirePackage\undefined - \input{luatexbase.sty}% -\else - \RequirePackage{luatexbase} -\fi diff --git a/tex/compat/luatexbase/luatexbase-loader.sty b/tex/compat/luatexbase/luatexbase-loader.sty deleted file mode 100644 index 600fea502fc6cb6f3ccbdf3f39a29dd229298068..0000000000000000000000000000000000000000 --- a/tex/compat/luatexbase/luatexbase-loader.sty +++ /dev/null @@ -1,14 +0,0 @@ - -\ifx - \ProvidesPackage\undefined\begingroup\def\ProvidesPackage - #1#2[#3]{\endgroup\immediate\write-1{Package: #1 #3}} -\fi -\ProvidesPackage{luatexbase-loader} -[2015/10/04 v1.3 - luatexbase interface to LuaTeX (legacy subpackage) -] -\ifx\RequirePackage\undefined - \input{luatexbase.sty}% -\else - \RequirePackage{luatexbase} -\fi diff --git a/tex/compat/luatexbase/luatexbase-mcb.sty b/tex/compat/luatexbase/luatexbase-mcb.sty deleted file mode 100644 index cda38f7675e2283618bf2997f1bb4fdd5c106cd6..0000000000000000000000000000000000000000 --- a/tex/compat/luatexbase/luatexbase-mcb.sty +++ /dev/null @@ -1,14 +0,0 @@ - -\ifx - \ProvidesPackage\undefined\begingroup\def\ProvidesPackage - #1#2[#3]{\endgroup\immediate\write-1{Package: #1 #3}} -\fi -\ProvidesPackage{luatexbase-mcb} -[2015/10/04 v1.3 - luatexbase interface to LuaTeX (legacy subpackage) -] -\ifx\RequirePackage\undefined - \input{luatexbase.sty}% -\else - \RequirePackage{luatexbase} -\fi diff --git a/tex/compat/luatexbase/luatexbase-modutils.sty b/tex/compat/luatexbase/luatexbase-modutils.sty deleted file mode 100644 index 2a36764c2b769116d543f87ce67ddbdf364147a6..0000000000000000000000000000000000000000 --- a/tex/compat/luatexbase/luatexbase-modutils.sty +++ /dev/null @@ -1,14 +0,0 @@ - -\ifx - \ProvidesPackage\undefined\begingroup\def\ProvidesPackage - #1#2[#3]{\endgroup\immediate\write-1{Package: #1 #3}} -\fi -\ProvidesPackage{luatexbase-modutils} -[2015/10/04 v1.3 - luatexbase interface to LuaTeX (legacy subpackage) -] -\ifx\RequirePackage\undefined - \input{luatexbase.sty}% -\else - \RequirePackage{luatexbase} -\fi diff --git a/tex/compat/luatexbase/luatexbase-regs.sty b/tex/compat/luatexbase/luatexbase-regs.sty deleted file mode 100644 index 9cd43f33623d453891e682312ee9dec77426e093..0000000000000000000000000000000000000000 --- a/tex/compat/luatexbase/luatexbase-regs.sty +++ /dev/null @@ -1,14 +0,0 @@ - -\ifx - \ProvidesPackage\undefined\begingroup\def\ProvidesPackage - #1#2[#3]{\endgroup\immediate\write-1{Package: #1 #3}} -\fi -\ProvidesPackage{luatexbase-regs} -[2015/10/04 v1.3 - luatexbase interface to LuaTeX (legacy subpackage) -] -\ifx\RequirePackage\undefined - \input{luatexbase.sty}% -\else - \RequirePackage{luatexbase} -\fi diff --git a/tex/compat/luatexbase/luatexbase.loader.lua b/tex/compat/luatexbase/luatexbase.loader.lua deleted file mode 100644 index dd2984b32088fc6ff7bb6b4629740d7793a8b138..0000000000000000000000000000000000000000 --- a/tex/compat/luatexbase/luatexbase.loader.lua +++ /dev/null @@ -1 +0,0 @@ -luatexbase = luatexbase or { } diff --git a/tex/compat/luatexbase/luatexbase.sty b/tex/compat/luatexbase/luatexbase.sty deleted file mode 100644 index a3416152758592a4aa2e7e4f0e030853398b775a..0000000000000000000000000000000000000000 --- a/tex/compat/luatexbase/luatexbase.sty +++ /dev/null @@ -1,301 +0,0 @@ -\ifx\BeginCatcodeRegime\undefined\else\expandafter\endinput\fi - -\ifx - \ProvidesPackage\undefined\begingroup\def\ProvidesPackage - #1#2[#3]{\endgroup\immediate\write-1{Package: #1 #3}} -\fi -\ProvidesPackage{luatexbase} -[2015/10/04 v1.3 - luatexbase interface to LuaTeX -] -\edef\emuatcatcode{\the\catcode`\@} -\catcode`\@=11 -\ifx\@setrangecatcode\@undefined - \ifx\RequirePackage\@undefined - \input{ctablestack.sty}% - \else - \RequirePackage{ctablestack} - \fi -\fi -\def\RequireLuaModule#1{\directlua{require("#1")}\@gobbleoptarg} -\ifdefined\@ifnextchar -\def\@gobbleoptarg{\@ifnextchar[\@gobble@optarg{}}% -\else -\long\def\@gobbleoptarg#1{\ifx[#1\expandafter\@gobble@optarg\fi#1}% -\fi -\def\@gobble@optarg[#1]{} -\let\CatcodeTableIniTeX\catcodetable@initex -\let\CatcodeTableString\catcodetable@string -\let\CatcodeTableLaTeX\catcodetable@latex -\let\CatcodeTableLaTeXAtLetter\catcodetable@atletter -\newcatcodetable\CatcodeTableOther -\@setcatcodetable\CatcodeTableOther{% - \catcodetable\CatcodeTableString - \catcode32 12 } -\newcatcodetable\CatcodeTableExpl -\@setcatcodetable\CatcodeTableExpl{% - \catcodetable\CatcodeTableLaTeX - \catcode126 10 % tilde is a space char - \catcode32 9 % space is ignored - \catcode9 9 % tab also ignored - \catcode95 11 % underscore letter - \catcode58 11 % colon letter -} -\def\BeginCatcodeRegime#1{% - \@pushcatcodetable - \catcodetable#1\relax} -\def\EndCatcodeRegime{% - \@popcatcodetable} -\let\PushCatcodeTableNumStack\@pushcatcodetable -\let\PopCatcodeTableNumStack\@popcatcodetable -\let\SetCatcodeRange\@setrangecatcode -\let\setcatcodetable\@setcatcodetable -\directlua{ -function luatexbase.reset_callback(name,make_false) - for _,v in pairs(luatexbase.callback_descriptions(name)) - do - luatexbase.remove_from_callback(name,v) - end - if make_false == true then - luatexbase.disable_callback(name) - end -end -luatexbase.base_add_to_callback=luatexbase.add_to_callback -function luatexbase.add_to_callback(name,fun,description,priority) - local priority= priority - if priority==nil then - priority=\string#luatexbase.callback_descriptions(name)+1 - end - if(luatexbase.callbacktypes[name] == 3 and - priority == 1 and - \string#luatexbase.callback_descriptions(name)==1) then - luatexbase.module_warning("luatexbase", - "resetting exclusive callback: " .. name) - luatexbase.reset_callback(name) - end - local saved_callback={},ff,dd - for k,v in pairs(luatexbase.callback_descriptions(name)) do - if k >= priority then - ff,dd= luatexbase.remove_from_callback(name, v) - saved_callback[k]={ff,dd} - end - end - luatexbase.base_add_to_callback(name,fun,description) - for k,v in pairs(saved_callback) do - luatexbase.base_add_to_callback(name,v[1],v[2]) - end - return -end -luatexbase.catcodetables=setmetatable( - {['latex-package'] = \number\CatcodeTableLaTeXAtLetter, - ini = \number\CatcodeTableIniTeX, - string = \number\CatcodeTableString, - other = \number\CatcodeTableOther, - latex = \number\CatcodeTableLaTeX, - expl = \number\CatcodeTableExpl, - expl3 = \number\CatcodeTableExpl}, - { __index = function(t,key) - return luatexbase.registernumber(key) or nil - end} -)} -\ifnum\luatexversion<80 % -\def\newcatcodetable#1{% - \e@alloc\catcodetable\chardef - \e@alloc@ccodetable@count\m@ne{"8000}#1% - \initcatcodetable\allocationnumber - {\escapechar=\m@ne - \directlua{luatexbase.catcodetables['\string#1']=% - \the\allocationnumber}}% -} -\fi -\directlua{ -function luatexbase.priority_in_callback (name,description) - for i,v in ipairs(luatexbase.callback_descriptions(name)) - do - if v == description then - return i - end - end - return false -end -luatexbase.is_active_callback = luatexbase.in_callback -luatexbase.base_provides_module=luatexbase.provides_module -function luatexbase.errwarinf(name) - return - function(s,...) return luatexbase.module_error(name, s:format(...)) end, - function(s,...) return luatexbase.module_warning(name, s:format(...)) end, - function(s,...) return luatexbase.module_info(name, s:format(...)) end, - function(s,...) return luatexbase.module_info(name, s:format(...)) end -end -function luatexbase.provides_module(info) - luatexbase.base_provides_module(info) - return luatexbase.errwarinf(info.name) -end -} -\ifnum\luatexversion<80 % -\def\newattribute#1{% - \e@alloc\attribute\attributedef - \e@alloc@attribute@count\m@ne\e@alloc@top#1% - {\escapechar=\m@ne - \directlua{luatexbase.attributes['\string#1']=% - \the\allocationnumber}}% -} -\fi -\ifx\@percentchar\@undefined - {\catcode`\%=12 \gdef\@percentchar{%}} -\fi -\directlua{% -local copynode = node.copy -local newnode = node.new -local nodesubtype = node.subtype -local nodetype = node.id -local stringformat = string.format -local tableunpack = unpack or table.unpack -local texiowrite_nl = texio.write_nl -local texiowrite = texio.write -local whatsit_t = nodetype"whatsit" -local user_defined_t = nodesubtype"user_defined" -local unassociated = "__unassociated" -local user_whatsits = { __unassociated = { } } -local whatsit_ids = { } -local anonymous_whatsits = 0 -local anonymous_prefix = "anon" -local new_user_whatsit_id = function (name, package) - if name then - if not package then - package = unassociated - end - else % anonymous - anonymous_whatsits = anonymous_whatsits + 1 - warning("defining anonymous user whatsit no. \@percentchar - d", anonymous_whatsits) - package = unassociated - name = anonymous_prefix .. tostring(anonymous_whatsits) - end - - local whatsitdata = user_whatsits[package] - if not whatsitdata then - whatsitdata = { } - user_whatsits[package] = whatsitdata - end - - local id = whatsitdata[name] - if id then %- warning - warning("replacing whatsit \@percentchar s:\@percentchar - s (\@percentchar d)", package, name, id) - else %- new id - id=luatexbase.new_whatsit(name) - whatsitdata[name] = id - whatsit_ids[id] = { name, package } - end - return id -end -luatexbase.new_user_whatsit_id = new_user_whatsit_id -local new_user_whatsit = function (req, package) - local id, whatsit - if type(req) == "string" then - id = new_user_whatsit_id(req, package) - whatsit = newnode(whatsit_t, user_defined_t) - whatsit.user_id = id - elseif req.id == whatsit_t and req.subtype == user_defined_t then - id = req.user_id - whatsit = copynode(req) - if not whatsit_ids[id] then - warning("whatsit id \@percentchar d unregistered; " - .. "inconsistencies may arise", id) - end - end - return function () return copynode(whatsit) end, id -end -luatexbase.new_user_whatsit = new_user_whatsit -local get_user_whatsit_id = function (name, package) - if not package then - package = unassociated - end - return user_whatsits[package][name] -end -luatexbase.get_user_whatsit_id = get_user_whatsit_id -local get_user_whatsit_name = function (asked) - local id - if type(asked) == "number" then - id = asked - elseif type(asked) == "function" then - %- node generator - local n = asked() - id = n.user_id - else %- node - id = asked.user_id - end - local metadata = whatsit_ids[id] - if not metadata then % unknown - warning("whatsit id \@percentchar d unregistered; - inconsistencies may arise", id) - return "", "" - end - return tableunpack(metadata) -end -luatexbase.get_user_whatsit_name = get_user_whatsit_name -local dump_registered_whatsits = function (asked_package) - local whatsit_list = { } - if asked_package then - local whatsitdata = user_whatsits[asked_package] - if not whatsitdata then - error("(no user whatsits registered for package - \@percentchar s)", asked_package) - return - end - texiowrite_nl("(user whatsit allocation stats for " .. - asked_package) - for name, id in next, whatsitdata do - whatsit_list[\string#whatsit_list+1] = - stringformat("(\@percentchar s:\@percentchar - s \@percentchar d)", asked_package, name, id) - end - else - texiowrite_nl("(user whatsit allocation stats") - texiowrite_nl(stringformat(" ((total \@percentchar d)\string\n - (anonymous \@percentchar d))", - current_whatsit, anonymous_whatsits)) - for package, whatsitdata in next, user_whatsits do - for name, id in next, whatsitdata do - whatsit_list[\string#whatsit_list+1] = - stringformat("(\@percentchar s:\@percentchar - s \@percentchar d)", package, name, id) - end - end - end - texiowrite_nl" (" - local first = true - for i=1, \string#whatsit_list do - if first then - first = false - else % indent - texiowrite_nl" " - end - texiowrite(whatsit_list[i]) - end - texiowrite"))\string\n" -end -luatexbase.dump_registered_whatsits = dump_registered_whatsits -luatexbase.newattribute = new_attribute -luatexbase.newuserwhatsit = new_user_whatsit -luatexbase.newuserwhatsitid = new_user_whatsit_id -luatexbase.getuserwhatsitid = get_user_whatsit_id -luatexbase.getuserwhatsitname = get_user_whatsit_name -luatexbase.dumpregisteredwhatsits = dump_registered_whatsits -} -\let\newluatexattribute\newattribute -\let\setluatexattribute\setattribute -\let\unsetluatexattribute\unsetattribute -\let\newluatexcatcodetable\newcatcodetable -\let\setluatexcatcodetable\setcatcodetable -\let\luatexbase@directlua\directlua -\let\luatexbase@ensure@primitive\@gobble -\let\luatexattribute\attribute -\let\luatexattributedef\attributedef -\let\luatexcatcodetable\catcodetable -\let\luatexluaescapestring\luaescapestring -\let\luatexlatelua\latelua -\let\luatexoutputbox\outputbox -\let\luatexscantextokens\scantextokens -\catcode`\@=\emuatcatcode\relax