diff options
author | Hans Hagen <pragma@wxs.nl> | 2017-02-23 18:12:36 +0100 |
---|---|---|
committer | Context Git Mirror Bot <phg42.2a@gmail.com> | 2017-02-23 18:12:36 +0100 |
commit | c91d92093b72a73a92c3ae3c641137abe6fb64b9 (patch) | |
tree | bfbdc4359ae391d0d96e577fb544023464427e81 | |
parent | e4223677ac0d23e4888e41efda0d2e6aabbe76bf (diff) | |
download | context-c91d92093b72a73a92c3ae3c641137abe6fb64b9.tar.gz |
2017-02-23 17:13:00
47 files changed, 6950 insertions, 910 deletions
diff --git a/doc/context/documents/general/qrcs/setup-cs.pdf b/doc/context/documents/general/qrcs/setup-cs.pdf Binary files differindex e26a63165..bb028e14d 100644 --- a/doc/context/documents/general/qrcs/setup-cs.pdf +++ b/doc/context/documents/general/qrcs/setup-cs.pdf diff --git a/doc/context/documents/general/qrcs/setup-de.pdf b/doc/context/documents/general/qrcs/setup-de.pdf Binary files differindex bf2114679..4b739bb8f 100644 --- a/doc/context/documents/general/qrcs/setup-de.pdf +++ b/doc/context/documents/general/qrcs/setup-de.pdf diff --git a/doc/context/documents/general/qrcs/setup-en.pdf b/doc/context/documents/general/qrcs/setup-en.pdf Binary files differindex 56f1b02a0..a62e63912 100644 --- a/doc/context/documents/general/qrcs/setup-en.pdf +++ b/doc/context/documents/general/qrcs/setup-en.pdf diff --git a/doc/context/documents/general/qrcs/setup-fr.pdf b/doc/context/documents/general/qrcs/setup-fr.pdf Binary files differindex 9c188ce53..44854efd4 100644 --- a/doc/context/documents/general/qrcs/setup-fr.pdf +++ b/doc/context/documents/general/qrcs/setup-fr.pdf diff --git a/doc/context/documents/general/qrcs/setup-it.pdf b/doc/context/documents/general/qrcs/setup-it.pdf Binary files differindex 47e23baef..71b9f0004 100644 --- a/doc/context/documents/general/qrcs/setup-it.pdf +++ b/doc/context/documents/general/qrcs/setup-it.pdf diff --git a/doc/context/documents/general/qrcs/setup-nl.pdf b/doc/context/documents/general/qrcs/setup-nl.pdf Binary files differindex 9799f7635..40635c015 100644 --- a/doc/context/documents/general/qrcs/setup-nl.pdf +++ b/doc/context/documents/general/qrcs/setup-nl.pdf diff --git a/doc/context/documents/general/qrcs/setup-ro.pdf b/doc/context/documents/general/qrcs/setup-ro.pdf Binary files differindex a570ab195..5a33bc8e0 100644 --- a/doc/context/documents/general/qrcs/setup-ro.pdf +++ b/doc/context/documents/general/qrcs/setup-ro.pdf diff --git a/scripts/context/lua/mtxrun.lua b/scripts/context/lua/mtxrun.lua index bdb81b477..0c3355fcc 100644 --- a/scripts/context/lua/mtxrun.lua +++ b/scripts/context/lua/mtxrun.lua @@ -5632,7 +5632,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-str"] = package.loaded["util-str"] or true --- original size: 36650, stripped down to: 19963 +-- original size: 37582, stripped down to: 20676 if not modules then modules={} end modules ['util-str']={ version=1.001, @@ -5871,6 +5871,27 @@ function number.sparseexponent(f,n) end return tostring(n) end +local hf={} +local hs={} +setmetatable(hf,{ __index=function(t,k) + local v="%."..k.."f" + t[k]=v + return v +end } ) +setmetatable(hs,{ __index=function(t,k) + local v="%"..k.."s" + t[k]=v + return v +end } ) +function number.formattedfloat(n,b,a) + local s=format(hf[a],n) + local l=(b or 0)+(a or 0)+1 + if #s<l then + return format(hs[l],s) + else + return s + end +end local template=[[ %s %s @@ -5898,6 +5919,7 @@ local autodouble=string.autodouble local sequenced=table.sequenced local formattednumber=number.formatted local sparseexponent=number.sparseexponent +local formattedfloat=number.formattedfloat ]] else environment={ @@ -5921,6 +5943,7 @@ else sequenced=table.sequenced, formattednumber=number.formatted, sparseexponent=number.sparseexponent, + formattedfloat=number.formattedfloat } end local arguments={ "a1" } @@ -5931,6 +5954,7 @@ setmetatable(arguments,{ __index=function(t,k) end }) local prefix_any=C((S("+- .")+R("09"))^0) +local prefix_sub=(C((S("+-")+R("09"))^0)+Cc(0))*P(".")*(C((S("+-")+R("09"))^0)+Cc(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 @@ -5981,6 +6005,10 @@ local format_F=function(f) return format("format((a%s %% 1 == 0) and '%%i' or '%%%sf',a%s)",n,f,n) end end +local format_k=function(b,a) + n=n+1 + return format("formattedfloat(a%s,%i,%i)",n,b or 0,a or 0) +end local format_g=function(f) n=n+1 return format("format('%%%sg',a%s)",f,n) @@ -6189,7 +6217,8 @@ local builder=Cs { "start", +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("N") ++V("k") +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") @@ -6216,6 +6245,7 @@ local builder=Cs { "start", ["S"]=(prefix_any*P("S"))/format_S, ["Q"]=(prefix_any*P("Q"))/format_S, ["N"]=(prefix_any*P("N"))/format_N, + ["k"]=(prefix_sub*P("k"))/format_k, ["c"]=(prefix_any*P("c"))/format_c, ["C"]=(prefix_any*P("C"))/format_C, ["r"]=(prefix_any*P("r"))/format_r, @@ -7012,7 +7042,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-fil"] = package.loaded["util-fil"] or true --- original size: 6316, stripped down to: 4866 +-- original size: 6362, stripped down to: 4907 if not modules then modules={} end modules ['util-fil']={ version=1.001, @@ -7098,6 +7128,7 @@ end files.readcardinal1=files.readbyte files.readcardinal=files.readcardinal1 files.readinteger=files.readinteger1 +files.readsignedbyte=files.readinteger1 function files.readcardinal2(f) local a,b=byte(f:read(2),1,2) return 0x100*a+b @@ -9795,7 +9826,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-deb"] = package.loaded["util-deb"] or true --- original size: 4030, stripped down to: 2718 +-- original size: 8473, stripped down to: 6211 if not modules then modules={} end modules ['util-deb']={ version=1.001, @@ -9805,75 +9836,219 @@ if not modules then modules={} end modules ['util-deb']={ license="see context related readme files" } local debug=require "debug" -local getinfo=debug.getinfo +local getinfo,sethook=debug.getinfo,debug.sethook local type,next,tostring=type,next,tostring -local format,find=string.format,string.find -local is_boolean=string.is_boolean +local format,find,sub,gsub=string.format,string.find,string.sub,string.gsub +local insert,remove,sort=table.insert,table.remove,table.sort 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) +local ticks=os.gettimeofday or os.clock +local seconds=function(n) return n or 0 end +local overhead=0 +local dummycalls=10*1000 +local nesting=0 +local names={} +local function initialize() + if FFISUPPORTED and ffi then + if os.type=="windows" then + local okay,kernel=pcall(ffi.load,"kernel32") + if kernel then + local tonumber=ffi.number or tonumber +ffi.cdef[[ +int QueryPerformanceFrequency(int64_t *lpFrequency); +int QueryPerformanceCounter(int64_t *lpPerformanceCount); +]] + local target=ffi.new("__int64[1]") + ticks=function() + if kernel.QueryPerformanceCounter(target)==1 then + return tonumber(target[0]) + else + return 0 + end + end + local target=ffi.new("__int64[1]") + seconds=function(ticks) + if kernel.QueryPerformanceFrequency(target)==1 then + return ticks/tonumber(target[0]) + else + return 0 + end + end end - else - n=f.name or f.namewhat or f.what - if not n or n=="" then - n="?" + elseif os.type=="unix" then + local C=ffi.C + local tonumber=ffi.number or tonumber +ffi.cdef [[ +struct timespec { long sec; long nsec; }; +int clock_gettime(int timerid, struct timespec *t); + ]] + local target=ffi.new("timespec[?]",1) + function ticks() + C.clock_gettime(2,target) + return tonumber(target[0].sec*1000000000+target[0].nsec) + end + seconds=function(ticks) + return ticks/1000000000 + end + end + end + initialize=false +end +table.setmetatableindex(names,function(t,name) + local v=table.setmetatableindex(function(t,source) + local v=table.setmetatableindex(function(t,line) + local v={ total=0,count=0 } + t[line]=v + return v + end) + t[source]=v + return v + end) + t[name]=v + return v +end) +local function hook(where) + local f=getinfo(2,"nSl") + if f then + local source=f.short_src + if not source then + return + end + local line=f.linedefined or 0 + local name=f.name + if not name then + local what=f.what + if what=="C" then + name="<anonymous>" + else + name=f.namewhat or what or "<unknown>" end - if not names[n] then - names[n]=format("%42s : % 5i : %s",n,f.linedefined or 0,f.short_src or "unknown source") + end + local data=names[name][source][line] + if where=="call" then + data.count=data.count+1 + insert(data,ticks()) + elseif where=="return" then + local t=remove(data) + if t then + data.total=data.total+ticks()-t 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 +function debugger.showstats(printer) + local printer=printer or report + local calls=0 + local functions=0 local dataset={} - for name,count in next,counters do - dataset[#dataset+1]={ name,count } + local length=0 + local wholetime=0 + for name,sources in next,names do + for source,lines in next,sources do + for line,data in next,lines do + if #name>length then + length=#name + end + local total=data.total + local count=data.count + local real=total + if real>0 then + real=total-(count*overhead/dummycalls) + if real<0 then + real=0 + end + wholetime=wholetime+real + end + if line<0 then + line=0 + end + dataset[#dataset+1]={ real,total,count,name,source,line } + end + end + end + sort(dataset,function(a,b) + if a[1]==b[1] then + if a[2]==b[2] then + if a[3]==b[3] then + if a[4]==b[4] then + if a[5]==b[5] then + return a[6]<b[6] + else + return a[5]<b[5] + end + else + return a[4]<b[4] + end + else + return b[3]<a[3] + end + else + return b[2]<a[2] + end + else + return b[1]<a[1] + end + end) + if length>50 then + length=50 end - table.sort(dataset,function(a,b) return a[2]==b[2] and b[1]>a[1] or a[2]>b[2] end) + local fmt=string.formatters["%4.9k %4.9k %3.3k %8i %-"..length.."s %4i %s"] 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 + local data=dataset[i] + local real=data[1] + local total=data[2] + local count=data[3] + local name=data[4] + local source=data[5] + local line=data[6] + local percent=real/wholetime + calls=calls+count functions=functions+1 + name=gsub(name,"%s+"," ") + if #name>length then + name=sub(name,1,length) + end + printer(fmt(seconds(total),seconds(real),percent,count,name,line,source)) 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)) + printer("") + printer(format("functions : %i",functions)) + printer(format("calls : %i",calls)) + printer(format("overhead : %f",seconds(overhead/1000))) end -function debugger.savestats(filename,threshold) +function debugger.savestats(filename) local f=io.open(filename,'w') if f then - debugger.showstats(function(str) f:write(str) end,threshold) + debugger.showstats(function(str) f:write(str,"\n") end) f:close() end end function debugger.enable() - debug.sethook(hook,"c") + if nesting==0 then + running=true + if initialize then + initialize() + end + sethook(hook,"cr") + local function dummy() end + local t=ticks() + for i=1,dummycalls do + dummy() + end + overhead=ticks()-t + end + if nesting>0 then + nesting=nesting+1 + end end function debugger.disable() - debug.sethook() + if nesting>0 then + nesting=nesting-1 + end + if nesting==0 then + sethook() + end end local function showtraceback(rep) local level=2 @@ -10716,7 +10891,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-env"] = package.loaded["util-env"] or true --- original size: 9028, stripped down to: 5176 +-- original size: 9552, stripped down to: 5176 if not modules then modules={} end modules ['util-env']={ version=1.001, @@ -15055,7 +15230,7 @@ do -- create closure to overcome 200 locals limit package.loaded["data-ini"] = package.loaded["data-ini"] or true --- original size: 11444, stripped down to: 7830 +-- original size: 11459, stripped down to: 7680 if not modules then modules={} end modules ['data-ini']={ version=1.001, @@ -15200,11 +15375,6 @@ if not texroot or texroot=="" then ossetenv('TEXROOT',texroot) end environment.texroot=file.collapsepath(texroot) -if type(profiler)=="table" and not jit then - directives.register("system.profile",function() - profiler.start("luatex-profile.log") - end) -end local prefixes=utilities.storage.allocate() resolvers.prefixes=prefixes local resolved={} @@ -19454,7 +19624,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-lib"] = package.loaded["util-lib"] or true --- original size: 11846, stripped down to: 6059 +-- original size: 13648, stripped down to: 7455 if not modules then modules={} end modules ['util-lib']={ version=1.001, @@ -19463,35 +19633,51 @@ if not modules then modules={} end modules ['util-lib']={ copyright="PRAGMA ADE / ConTeXt Development Team", license="see context related readme files", } -local gsub,find=string.gsub,string.find -local pathpart,nameonly,joinfile=file.pathpart,file.nameonly,file.join -local findfile,findfiles=resolvers and resolvers.findfile,resolvers and resolvers.findfiles -local loaded=package.loaded -local report_swiglib=logs.reporter("swiglib") -local trace_swiglib=false trackers.register("resolvers.swiglib",function(v) trace_swiglib=v end) +local type=type +local next=next +local pcall=pcall +local gsub=string.gsub +local find=string.find +local sort=table.sort +local pathpart=file.pathpart +local nameonly=file.nameonly +local joinfile=file.join +local removesuffix=file.removesuffix +local findfile=resolvers.findfile +local findfiles=resolvers.findfiles +local expandpaths=resolvers.expandedpathlistfromvariable +local qualifiedpath=file.is_qualified_path +local isfile=lfs.isfile local done=false -local function requireswiglib(required,version) - local trace_swiglib=trace_swiglib or package.helpers.trace - local library=loaded[required] - if library==nil then - if trace_swiglib then - report_swiglib("requiring library %a with version %a",required,version or "any") +local function locate(required,version,trace,report,action) + if type(required)~="string" then + report("provide a proper library name") + return + end + if trace then + report("requiring library %a with version %a",required,version or "any") + end + local found_library=nil + if qualifiedpath(required) then + if isfile(required) then + found_library=required end + else local required_full=gsub(required,"%.","/") local required_path=pathpart(required_full) local required_base=nameonly(required_full) local required_name=required_base.."."..os.libsuffix local version=type(version)=="string" and version~="" and version or false local engine=environment.ownmain or false - if trace_swiglib and not done then - local list=resolvers.expandedpathlistfromvariable("lib") + if trace and not done then + local list=expandpaths("lib") for i=1,#list do - report_swiglib("tds path %i: %s",i,list[i]) + report("tds path %i: %s",i,list[i]) end end local function found(locate,asked_library,how,...) - if trace_swiglib then - report_swiglib("checking %s: %a",how,asked_library) + if trace then + report("checking %s: %a",how,asked_library) end return locate(asked_library,...) end @@ -19499,45 +19685,45 @@ local function requireswiglib(required,version) local found=nil if version then local asked_library=joinfile(required_path,version,required_name) - if trace_swiglib then - report_swiglib("checking %s: %a","with version",asked_library) + if trace then + report("checking %s: %a","with version",asked_library) end found=locate(asked_library,...) end if not found or found=="" then local asked_library=joinfile(required_path,required_name) - if trace_swiglib then - report_swiglib("checking %s: %a","with version",asked_library) + if trace then + report("checking %s: %a","with version",asked_library) end found=locate(asked_library,...) end return found and found~="" and found or false end local function attempt(checkpattern) - if trace_swiglib then - report_swiglib("checking tds lib paths strictly") + if trace then + report("checking tds lib paths strictly") end local found=findfile and check(findfile,"lib") if found and (not checkpattern or find(found,checkpattern)) then return found end - if trace_swiglib then - report_swiglib("checking tds lib paths with wildcard") + if trace then + report("checking tds lib paths with wildcard") end local asked_library=joinfile(required_path,".*",required_name) - if trace_swiglib then - report_swiglib("checking %s: %a","latest version",asked_library) + if trace then + report("checking %s: %a","latest version",asked_library) end local list=findfiles(asked_library,"lib",true) if list and #list>0 then - table.sort(list) + sort(list) local found=list[#list] if found and (not checkpattern or find(found,checkpattern)) then return found end end - if trace_swiglib then - report_swiglib("checking lib paths") + if trace then + report("checking lib paths") end package.extralibpath(environment.ownpath) local paths=package.libpaths() @@ -19549,89 +19735,132 @@ local function requireswiglib(required,version) end return false end - local found_library=nil if engine then - if trace_swiglib then - report_swiglib("attemp 1, engine %a",engine) + if trace then + report("attemp 1, engine %a",engine) end found_library=attempt("/"..engine.."/") if not found_library then - if trace_swiglib then - report_swiglib("attemp 2, no engine",asked_library) + if trace then + report("attemp 2, no engine",asked_library) end found_library=attempt() end else found_library=attempt() end - if not found_library then - if trace_swiglib then - report_swiglib("not found: %a",required) - end + end + if not found_library then + if trace then + report("not found: %a",required) + end + library=false + else + if trace then + report("found: %a",found_library) + end + local message,result=action(found_library,required_base) + if result then + library=result + else library=false + report("load error: message %a, library %a",tostring(message),found_library or "no library") + end + end + if not library then + report("unknown: %a",required) + elseif trace then + report("stored: %a",required) + end + return library +end +do + local report_swiglib=logs.reporter("swiglib") + local trace_swiglib=false + local savedrequire=require + local loadedlibs={} + trackers.register("resolvers.swiglib",function(v) trace_swiglib=v end) + function requireswiglib(required,version) + local library=loadedlibs[library] + if library==nil then + local trace_swiglib=trace_swiglib or package.helpers.trace + library=locate(required,version,trace_swiglib,report_swiglib,function(name,base) + dir.push(pathpart(name)) + local opener="luaopen_"..base + local library,message=package.loadlib(name,opener) + local libtype=type(library) + if libtype=="function" then + library=library() + message=true + else + report_swiglib("load error: %a returns %a, message %a, library %a",opener,libtype,(string.gsub(message or "no message","[%s]+$","")),found_library or "no library") + library=false + end + dir.pop() + return message,library + end) + loadedlibs[required]=library or false + end + return library + end + function require(name,version) + if find(name,"^swiglib%.") then + return requireswiglib(name,version) else - local path=pathpart(found_library) - local base=nameonly(found_library) - dir.push(path) + return savedrequire(name) + end + end + local swiglibs={} + local initializer="core" + function swiglib(name,version) + local library=swiglibs[name] + if not library then + statistics.starttiming(swiglibs) if trace_swiglib then - report_swiglib("found: %a",found_library) - end - local message=nil - local opener="luaopen_"..required_base - library,message=package.loadlib(found_library,opener) - local libtype=type(library) - if libtype=="function" then - library=library() + report_swiglib("loading %a",name) + end + if not find(name,"%."..initializer.."$") then + fullname="swiglib."..name.."."..initializer else - report_swiglib("load error: %a returns %a, message %a, library %a",opener,libtype,(string.gsub(message or "no message","[%s]+$","")),found_library or "no library") - library=false + fullname="swiglib."..name end - dir.pop() + library=requireswiglib(fullname,version) + swiglibs[name]=library + statistics.stoptiming(swiglibs) end - if not library then - report_swiglib("unknown: %a",required) - elseif trace_swiglib then - report_swiglib("stored: %a",required) - end - loaded[required]=library - else - report_swiglib("reused: %a",required) + return library end - return library + statistics.register("used swiglibs",function() + if next(swiglibs) then + return string.format("%s, initial load time %s seconds",table.concat(table.sortedkeys(swiglibs)," "),statistics.elapsedtime(swiglibs)) + end + end) end -local savedrequire=require -function require(name,version) - if find(name,"^swiglib%.") then - return requireswiglib(name,version) - else - return savedrequire(name) +if FFISUPPORTED and ffi and ffi.load then + local report_ffilib=logs.reporter("ffilib") + local trace_ffilib=false + local savedffiload=ffi.load + trackers.register("resolvers.ffilib",function(v) trace_ffilib=v end) + function ffilib(required,version) + return locate(required,version,trace_ffilib,report_ffilib,function(name) + local message,library=pcall(savedffiload,removesuffix(name)) + if type(library)=="userdata" then + return message,library + else + return message,false + end + end) end -end -local swiglibs={} -local initializer="core" -function swiglib(name,version) - local library=swiglibs[name] - if not library then - statistics.starttiming(swiglibs) - if trace_swiglib then - report_swiglib("loading %a",name) - end - if not find(name,"%."..initializer.."$") then - fullname="swiglib."..name.."."..initializer + function ffi.load(name) + local library=ffilib(name) + if type(library)=="userdata" then + return library else - fullname="swiglib."..name + report_ffilib("trying to load %a using normal loader",name) + return savedffiload(name) end - library=requireswiglib(fullname,version) - swiglibs[name]=library - statistics.stoptiming(swiglibs) end - return library end -statistics.register("used swiglibs",function() - if next(swiglibs) then - return string.format("%s, initial load time %s seconds",table.concat(table.sortedkeys(swiglibs)," "),statistics.elapsedtime(swiglibs)) - end -end) end -- of closure @@ -19975,8 +20204,8 @@ end -- of closure -- used libraries : l-lua.lua l-sandbox.lua l-package.lua l-lpeg.lua l-function.lua l-string.lua l-table.lua l-io.lua l-number.lua l-set.lua l-os.lua l-file.lua l-gzip.lua l-md5.lua l-url.lua l-dir.lua l-boolean.lua l-unicode.lua l-math.lua util-str.lua util-tab.lua util-fil.lua util-sac.lua util-sto.lua util-prs.lua util-fmt.lua trac-set.lua trac-log.lua trac-inf.lua trac-pro.lua util-lua.lua util-deb.lua util-tpl.lua util-sbx.lua util-mrg.lua util-env.lua luat-env.lua lxml-tab.lua lxml-lpt.lua lxml-mis.lua lxml-aux.lua lxml-xml.lua trac-xml.lua data-ini.lua data-exp.lua data-env.lua data-tmp.lua data-met.lua data-res.lua data-pre.lua data-inp.lua data-out.lua data-fil.lua data-con.lua data-use.lua data-zip.lua data-tre.lua data-sch.lua data-lua.lua data-aux.lua data-tmf.lua data-lst.lua util-lib.lua luat-sta.lua luat-fmt.lua -- skipped libraries : - --- original bytes : 847975 --- stripped bytes : 308174 +-- original bytes : 855737 +-- stripped bytes : 310443 -- end library merge diff --git a/scripts/context/stubs/mswin/mtxrun.lua b/scripts/context/stubs/mswin/mtxrun.lua index bdb81b477..0c3355fcc 100644 --- a/scripts/context/stubs/mswin/mtxrun.lua +++ b/scripts/context/stubs/mswin/mtxrun.lua @@ -5632,7 +5632,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-str"] = package.loaded["util-str"] or true --- original size: 36650, stripped down to: 19963 +-- original size: 37582, stripped down to: 20676 if not modules then modules={} end modules ['util-str']={ version=1.001, @@ -5871,6 +5871,27 @@ function number.sparseexponent(f,n) end return tostring(n) end +local hf={} +local hs={} +setmetatable(hf,{ __index=function(t,k) + local v="%."..k.."f" + t[k]=v + return v +end } ) +setmetatable(hs,{ __index=function(t,k) + local v="%"..k.."s" + t[k]=v + return v +end } ) +function number.formattedfloat(n,b,a) + local s=format(hf[a],n) + local l=(b or 0)+(a or 0)+1 + if #s<l then + return format(hs[l],s) + else + return s + end +end local template=[[ %s %s @@ -5898,6 +5919,7 @@ local autodouble=string.autodouble local sequenced=table.sequenced local formattednumber=number.formatted local sparseexponent=number.sparseexponent +local formattedfloat=number.formattedfloat ]] else environment={ @@ -5921,6 +5943,7 @@ else sequenced=table.sequenced, formattednumber=number.formatted, sparseexponent=number.sparseexponent, + formattedfloat=number.formattedfloat } end local arguments={ "a1" } @@ -5931,6 +5954,7 @@ setmetatable(arguments,{ __index=function(t,k) end }) local prefix_any=C((S("+- .")+R("09"))^0) +local prefix_sub=(C((S("+-")+R("09"))^0)+Cc(0))*P(".")*(C((S("+-")+R("09"))^0)+Cc(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 @@ -5981,6 +6005,10 @@ local format_F=function(f) return format("format((a%s %% 1 == 0) and '%%i' or '%%%sf',a%s)",n,f,n) end end +local format_k=function(b,a) + n=n+1 + return format("formattedfloat(a%s,%i,%i)",n,b or 0,a or 0) +end local format_g=function(f) n=n+1 return format("format('%%%sg',a%s)",f,n) @@ -6189,7 +6217,8 @@ local builder=Cs { "start", +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("N") ++V("k") +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") @@ -6216,6 +6245,7 @@ local builder=Cs { "start", ["S"]=(prefix_any*P("S"))/format_S, ["Q"]=(prefix_any*P("Q"))/format_S, ["N"]=(prefix_any*P("N"))/format_N, + ["k"]=(prefix_sub*P("k"))/format_k, ["c"]=(prefix_any*P("c"))/format_c, ["C"]=(prefix_any*P("C"))/format_C, ["r"]=(prefix_any*P("r"))/format_r, @@ -7012,7 +7042,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-fil"] = package.loaded["util-fil"] or true --- original size: 6316, stripped down to: 4866 +-- original size: 6362, stripped down to: 4907 if not modules then modules={} end modules ['util-fil']={ version=1.001, @@ -7098,6 +7128,7 @@ end files.readcardinal1=files.readbyte files.readcardinal=files.readcardinal1 files.readinteger=files.readinteger1 +files.readsignedbyte=files.readinteger1 function files.readcardinal2(f) local a,b=byte(f:read(2),1,2) return 0x100*a+b @@ -9795,7 +9826,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-deb"] = package.loaded["util-deb"] or true --- original size: 4030, stripped down to: 2718 +-- original size: 8473, stripped down to: 6211 if not modules then modules={} end modules ['util-deb']={ version=1.001, @@ -9805,75 +9836,219 @@ if not modules then modules={} end modules ['util-deb']={ license="see context related readme files" } local debug=require "debug" -local getinfo=debug.getinfo +local getinfo,sethook=debug.getinfo,debug.sethook local type,next,tostring=type,next,tostring -local format,find=string.format,string.find -local is_boolean=string.is_boolean +local format,find,sub,gsub=string.format,string.find,string.sub,string.gsub +local insert,remove,sort=table.insert,table.remove,table.sort 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) +local ticks=os.gettimeofday or os.clock +local seconds=function(n) return n or 0 end +local overhead=0 +local dummycalls=10*1000 +local nesting=0 +local names={} +local function initialize() + if FFISUPPORTED and ffi then + if os.type=="windows" then + local okay,kernel=pcall(ffi.load,"kernel32") + if kernel then + local tonumber=ffi.number or tonumber +ffi.cdef[[ +int QueryPerformanceFrequency(int64_t *lpFrequency); +int QueryPerformanceCounter(int64_t *lpPerformanceCount); +]] + local target=ffi.new("__int64[1]") + ticks=function() + if kernel.QueryPerformanceCounter(target)==1 then + return tonumber(target[0]) + else + return 0 + end + end + local target=ffi.new("__int64[1]") + seconds=function(ticks) + if kernel.QueryPerformanceFrequency(target)==1 then + return ticks/tonumber(target[0]) + else + return 0 + end + end end - else - n=f.name or f.namewhat or f.what - if not n or n=="" then - n="?" + elseif os.type=="unix" then + local C=ffi.C + local tonumber=ffi.number or tonumber +ffi.cdef [[ +struct timespec { long sec; long nsec; }; +int clock_gettime(int timerid, struct timespec *t); + ]] + local target=ffi.new("timespec[?]",1) + function ticks() + C.clock_gettime(2,target) + return tonumber(target[0].sec*1000000000+target[0].nsec) + end + seconds=function(ticks) + return ticks/1000000000 + end + end + end + initialize=false +end +table.setmetatableindex(names,function(t,name) + local v=table.setmetatableindex(function(t,source) + local v=table.setmetatableindex(function(t,line) + local v={ total=0,count=0 } + t[line]=v + return v + end) + t[source]=v + return v + end) + t[name]=v + return v +end) +local function hook(where) + local f=getinfo(2,"nSl") + if f then + local source=f.short_src + if not source then + return + end + local line=f.linedefined or 0 + local name=f.name + if not name then + local what=f.what + if what=="C" then + name="<anonymous>" + else + name=f.namewhat or what or "<unknown>" end - if not names[n] then - names[n]=format("%42s : % 5i : %s",n,f.linedefined or 0,f.short_src or "unknown source") + end + local data=names[name][source][line] + if where=="call" then + data.count=data.count+1 + insert(data,ticks()) + elseif where=="return" then + local t=remove(data) + if t then + data.total=data.total+ticks()-t 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 +function debugger.showstats(printer) + local printer=printer or report + local calls=0 + local functions=0 local dataset={} - for name,count in next,counters do - dataset[#dataset+1]={ name,count } + local length=0 + local wholetime=0 + for name,sources in next,names do + for source,lines in next,sources do + for line,data in next,lines do + if #name>length then + length=#name + end + local total=data.total + local count=data.count + local real=total + if real>0 then + real=total-(count*overhead/dummycalls) + if real<0 then + real=0 + end + wholetime=wholetime+real + end + if line<0 then + line=0 + end + dataset[#dataset+1]={ real,total,count,name,source,line } + end + end + end + sort(dataset,function(a,b) + if a[1]==b[1] then + if a[2]==b[2] then + if a[3]==b[3] then + if a[4]==b[4] then + if a[5]==b[5] then + return a[6]<b[6] + else + return a[5]<b[5] + end + else + return a[4]<b[4] + end + else + return b[3]<a[3] + end + else + return b[2]<a[2] + end + else + return b[1]<a[1] + end + end) + if length>50 then + length=50 end - table.sort(dataset,function(a,b) return a[2]==b[2] and b[1]>a[1] or a[2]>b[2] end) + local fmt=string.formatters["%4.9k %4.9k %3.3k %8i %-"..length.."s %4i %s"] 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 + local data=dataset[i] + local real=data[1] + local total=data[2] + local count=data[3] + local name=data[4] + local source=data[5] + local line=data[6] + local percent=real/wholetime + calls=calls+count functions=functions+1 + name=gsub(name,"%s+"," ") + if #name>length then + name=sub(name,1,length) + end + printer(fmt(seconds(total),seconds(real),percent,count,name,line,source)) 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)) + printer("") + printer(format("functions : %i",functions)) + printer(format("calls : %i",calls)) + printer(format("overhead : %f",seconds(overhead/1000))) end -function debugger.savestats(filename,threshold) +function debugger.savestats(filename) local f=io.open(filename,'w') if f then - debugger.showstats(function(str) f:write(str) end,threshold) + debugger.showstats(function(str) f:write(str,"\n") end) f:close() end end function debugger.enable() - debug.sethook(hook,"c") + if nesting==0 then + running=true + if initialize then + initialize() + end + sethook(hook,"cr") + local function dummy() end + local t=ticks() + for i=1,dummycalls do + dummy() + end + overhead=ticks()-t + end + if nesting>0 then + nesting=nesting+1 + end end function debugger.disable() - debug.sethook() + if nesting>0 then + nesting=nesting-1 + end + if nesting==0 then + sethook() + end end local function showtraceback(rep) local level=2 @@ -10716,7 +10891,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-env"] = package.loaded["util-env"] or true --- original size: 9028, stripped down to: 5176 +-- original size: 9552, stripped down to: 5176 if not modules then modules={} end modules ['util-env']={ version=1.001, @@ -15055,7 +15230,7 @@ do -- create closure to overcome 200 locals limit package.loaded["data-ini"] = package.loaded["data-ini"] or true --- original size: 11444, stripped down to: 7830 +-- original size: 11459, stripped down to: 7680 if not modules then modules={} end modules ['data-ini']={ version=1.001, @@ -15200,11 +15375,6 @@ if not texroot or texroot=="" then ossetenv('TEXROOT',texroot) end environment.texroot=file.collapsepath(texroot) -if type(profiler)=="table" and not jit then - directives.register("system.profile",function() - profiler.start("luatex-profile.log") - end) -end local prefixes=utilities.storage.allocate() resolvers.prefixes=prefixes local resolved={} @@ -19454,7 +19624,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-lib"] = package.loaded["util-lib"] or true --- original size: 11846, stripped down to: 6059 +-- original size: 13648, stripped down to: 7455 if not modules then modules={} end modules ['util-lib']={ version=1.001, @@ -19463,35 +19633,51 @@ if not modules then modules={} end modules ['util-lib']={ copyright="PRAGMA ADE / ConTeXt Development Team", license="see context related readme files", } -local gsub,find=string.gsub,string.find -local pathpart,nameonly,joinfile=file.pathpart,file.nameonly,file.join -local findfile,findfiles=resolvers and resolvers.findfile,resolvers and resolvers.findfiles -local loaded=package.loaded -local report_swiglib=logs.reporter("swiglib") -local trace_swiglib=false trackers.register("resolvers.swiglib",function(v) trace_swiglib=v end) +local type=type +local next=next +local pcall=pcall +local gsub=string.gsub +local find=string.find +local sort=table.sort +local pathpart=file.pathpart +local nameonly=file.nameonly +local joinfile=file.join +local removesuffix=file.removesuffix +local findfile=resolvers.findfile +local findfiles=resolvers.findfiles +local expandpaths=resolvers.expandedpathlistfromvariable +local qualifiedpath=file.is_qualified_path +local isfile=lfs.isfile local done=false -local function requireswiglib(required,version) - local trace_swiglib=trace_swiglib or package.helpers.trace - local library=loaded[required] - if library==nil then - if trace_swiglib then - report_swiglib("requiring library %a with version %a",required,version or "any") +local function locate(required,version,trace,report,action) + if type(required)~="string" then + report("provide a proper library name") + return + end + if trace then + report("requiring library %a with version %a",required,version or "any") + end + local found_library=nil + if qualifiedpath(required) then + if isfile(required) then + found_library=required end + else local required_full=gsub(required,"%.","/") local required_path=pathpart(required_full) local required_base=nameonly(required_full) local required_name=required_base.."."..os.libsuffix local version=type(version)=="string" and version~="" and version or false local engine=environment.ownmain or false - if trace_swiglib and not done then - local list=resolvers.expandedpathlistfromvariable("lib") + if trace and not done then + local list=expandpaths("lib") for i=1,#list do - report_swiglib("tds path %i: %s",i,list[i]) + report("tds path %i: %s",i,list[i]) end end local function found(locate,asked_library,how,...) - if trace_swiglib then - report_swiglib("checking %s: %a",how,asked_library) + if trace then + report("checking %s: %a",how,asked_library) end return locate(asked_library,...) end @@ -19499,45 +19685,45 @@ local function requireswiglib(required,version) local found=nil if version then local asked_library=joinfile(required_path,version,required_name) - if trace_swiglib then - report_swiglib("checking %s: %a","with version",asked_library) + if trace then + report("checking %s: %a","with version",asked_library) end found=locate(asked_library,...) end if not found or found=="" then local asked_library=joinfile(required_path,required_name) - if trace_swiglib then - report_swiglib("checking %s: %a","with version",asked_library) + if trace then + report("checking %s: %a","with version",asked_library) end found=locate(asked_library,...) end return found and found~="" and found or false end local function attempt(checkpattern) - if trace_swiglib then - report_swiglib("checking tds lib paths strictly") + if trace then + report("checking tds lib paths strictly") end local found=findfile and check(findfile,"lib") if found and (not checkpattern or find(found,checkpattern)) then return found end - if trace_swiglib then - report_swiglib("checking tds lib paths with wildcard") + if trace then + report("checking tds lib paths with wildcard") end local asked_library=joinfile(required_path,".*",required_name) - if trace_swiglib then - report_swiglib("checking %s: %a","latest version",asked_library) + if trace then + report("checking %s: %a","latest version",asked_library) end local list=findfiles(asked_library,"lib",true) if list and #list>0 then - table.sort(list) + sort(list) local found=list[#list] if found and (not checkpattern or find(found,checkpattern)) then return found end end - if trace_swiglib then - report_swiglib("checking lib paths") + if trace then + report("checking lib paths") end package.extralibpath(environment.ownpath) local paths=package.libpaths() @@ -19549,89 +19735,132 @@ local function requireswiglib(required,version) end return false end - local found_library=nil if engine then - if trace_swiglib then - report_swiglib("attemp 1, engine %a",engine) + if trace then + report("attemp 1, engine %a",engine) end found_library=attempt("/"..engine.."/") if not found_library then - if trace_swiglib then - report_swiglib("attemp 2, no engine",asked_library) + if trace then + report("attemp 2, no engine",asked_library) end found_library=attempt() end else found_library=attempt() end - if not found_library then - if trace_swiglib then - report_swiglib("not found: %a",required) - end + end + if not found_library then + if trace then + report("not found: %a",required) + end + library=false + else + if trace then + report("found: %a",found_library) + end + local message,result=action(found_library,required_base) + if result then + library=result + else library=false + report("load error: message %a, library %a",tostring(message),found_library or "no library") + end + end + if not library then + report("unknown: %a",required) + elseif trace then + report("stored: %a",required) + end + return library +end +do + local report_swiglib=logs.reporter("swiglib") + local trace_swiglib=false + local savedrequire=require + local loadedlibs={} + trackers.register("resolvers.swiglib",function(v) trace_swiglib=v end) + function requireswiglib(required,version) + local library=loadedlibs[library] + if library==nil then + local trace_swiglib=trace_swiglib or package.helpers.trace + library=locate(required,version,trace_swiglib,report_swiglib,function(name,base) + dir.push(pathpart(name)) + local opener="luaopen_"..base + local library,message=package.loadlib(name,opener) + local libtype=type(library) + if libtype=="function" then + library=library() + message=true + else + report_swiglib("load error: %a returns %a, message %a, library %a",opener,libtype,(string.gsub(message or "no message","[%s]+$","")),found_library or "no library") + library=false + end + dir.pop() + return message,library + end) + loadedlibs[required]=library or false + end + return library + end + function require(name,version) + if find(name,"^swiglib%.") then + return requireswiglib(name,version) else - local path=pathpart(found_library) - local base=nameonly(found_library) - dir.push(path) + return savedrequire(name) + end + end + local swiglibs={} + local initializer="core" + function swiglib(name,version) + local library=swiglibs[name] + if not library then + statistics.starttiming(swiglibs) if trace_swiglib then - report_swiglib("found: %a",found_library) - end - local message=nil - local opener="luaopen_"..required_base - library,message=package.loadlib(found_library,opener) - local libtype=type(library) - if libtype=="function" then - library=library() + report_swiglib("loading %a",name) + end + if not find(name,"%."..initializer.."$") then + fullname="swiglib."..name.."."..initializer else - report_swiglib("load error: %a returns %a, message %a, library %a",opener,libtype,(string.gsub(message or "no message","[%s]+$","")),found_library or "no library") - library=false + fullname="swiglib."..name end - dir.pop() + library=requireswiglib(fullname,version) + swiglibs[name]=library + statistics.stoptiming(swiglibs) end - if not library then - report_swiglib("unknown: %a",required) - elseif trace_swiglib then - report_swiglib("stored: %a",required) - end - loaded[required]=library - else - report_swiglib("reused: %a",required) + return library end - return library + statistics.register("used swiglibs",function() + if next(swiglibs) then + return string.format("%s, initial load time %s seconds",table.concat(table.sortedkeys(swiglibs)," "),statistics.elapsedtime(swiglibs)) + end + end) end -local savedrequire=require -function require(name,version) - if find(name,"^swiglib%.") then - return requireswiglib(name,version) - else - return savedrequire(name) +if FFISUPPORTED and ffi and ffi.load then + local report_ffilib=logs.reporter("ffilib") + local trace_ffilib=false + local savedffiload=ffi.load + trackers.register("resolvers.ffilib",function(v) trace_ffilib=v end) + function ffilib(required,version) + return locate(required,version,trace_ffilib,report_ffilib,function(name) + local message,library=pcall(savedffiload,removesuffix(name)) + if type(library)=="userdata" then + return message,library + else + return message,false + end + end) end -end -local swiglibs={} -local initializer="core" -function swiglib(name,version) - local library=swiglibs[name] - if not library then - statistics.starttiming(swiglibs) - if trace_swiglib then - report_swiglib("loading %a",name) - end - if not find(name,"%."..initializer.."$") then - fullname="swiglib."..name.."."..initializer + function ffi.load(name) + local library=ffilib(name) + if type(library)=="userdata" then + return library else - fullname="swiglib."..name + report_ffilib("trying to load %a using normal loader",name) + return savedffiload(name) end - library=requireswiglib(fullname,version) - swiglibs[name]=library - statistics.stoptiming(swiglibs) end - return library end -statistics.register("used swiglibs",function() - if next(swiglibs) then - return string.format("%s, initial load time %s seconds",table.concat(table.sortedkeys(swiglibs)," "),statistics.elapsedtime(swiglibs)) - end -end) end -- of closure @@ -19975,8 +20204,8 @@ end -- of closure -- used libraries : l-lua.lua l-sandbox.lua l-package.lua l-lpeg.lua l-function.lua l-string.lua l-table.lua l-io.lua l-number.lua l-set.lua l-os.lua l-file.lua l-gzip.lua l-md5.lua l-url.lua l-dir.lua l-boolean.lua l-unicode.lua l-math.lua util-str.lua util-tab.lua util-fil.lua util-sac.lua util-sto.lua util-prs.lua util-fmt.lua trac-set.lua trac-log.lua trac-inf.lua trac-pro.lua util-lua.lua util-deb.lua util-tpl.lua util-sbx.lua util-mrg.lua util-env.lua luat-env.lua lxml-tab.lua lxml-lpt.lua lxml-mis.lua lxml-aux.lua lxml-xml.lua trac-xml.lua data-ini.lua data-exp.lua data-env.lua data-tmp.lua data-met.lua data-res.lua data-pre.lua data-inp.lua data-out.lua data-fil.lua data-con.lua data-use.lua data-zip.lua data-tre.lua data-sch.lua data-lua.lua data-aux.lua data-tmf.lua data-lst.lua util-lib.lua luat-sta.lua luat-fmt.lua -- skipped libraries : - --- original bytes : 847975 --- stripped bytes : 308174 +-- original bytes : 855737 +-- stripped bytes : 310443 -- end library merge diff --git a/scripts/context/stubs/unix/mtxrun b/scripts/context/stubs/unix/mtxrun index bdb81b477..0c3355fcc 100644 --- a/scripts/context/stubs/unix/mtxrun +++ b/scripts/context/stubs/unix/mtxrun @@ -5632,7 +5632,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-str"] = package.loaded["util-str"] or true --- original size: 36650, stripped down to: 19963 +-- original size: 37582, stripped down to: 20676 if not modules then modules={} end modules ['util-str']={ version=1.001, @@ -5871,6 +5871,27 @@ function number.sparseexponent(f,n) end return tostring(n) end +local hf={} +local hs={} +setmetatable(hf,{ __index=function(t,k) + local v="%."..k.."f" + t[k]=v + return v +end } ) +setmetatable(hs,{ __index=function(t,k) + local v="%"..k.."s" + t[k]=v + return v +end } ) +function number.formattedfloat(n,b,a) + local s=format(hf[a],n) + local l=(b or 0)+(a or 0)+1 + if #s<l then + return format(hs[l],s) + else + return s + end +end local template=[[ %s %s @@ -5898,6 +5919,7 @@ local autodouble=string.autodouble local sequenced=table.sequenced local formattednumber=number.formatted local sparseexponent=number.sparseexponent +local formattedfloat=number.formattedfloat ]] else environment={ @@ -5921,6 +5943,7 @@ else sequenced=table.sequenced, formattednumber=number.formatted, sparseexponent=number.sparseexponent, + formattedfloat=number.formattedfloat } end local arguments={ "a1" } @@ -5931,6 +5954,7 @@ setmetatable(arguments,{ __index=function(t,k) end }) local prefix_any=C((S("+- .")+R("09"))^0) +local prefix_sub=(C((S("+-")+R("09"))^0)+Cc(0))*P(".")*(C((S("+-")+R("09"))^0)+Cc(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 @@ -5981,6 +6005,10 @@ local format_F=function(f) return format("format((a%s %% 1 == 0) and '%%i' or '%%%sf',a%s)",n,f,n) end end +local format_k=function(b,a) + n=n+1 + return format("formattedfloat(a%s,%i,%i)",n,b or 0,a or 0) +end local format_g=function(f) n=n+1 return format("format('%%%sg',a%s)",f,n) @@ -6189,7 +6217,8 @@ local builder=Cs { "start", +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("N") ++V("k") +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") @@ -6216,6 +6245,7 @@ local builder=Cs { "start", ["S"]=(prefix_any*P("S"))/format_S, ["Q"]=(prefix_any*P("Q"))/format_S, ["N"]=(prefix_any*P("N"))/format_N, + ["k"]=(prefix_sub*P("k"))/format_k, ["c"]=(prefix_any*P("c"))/format_c, ["C"]=(prefix_any*P("C"))/format_C, ["r"]=(prefix_any*P("r"))/format_r, @@ -7012,7 +7042,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-fil"] = package.loaded["util-fil"] or true --- original size: 6316, stripped down to: 4866 +-- original size: 6362, stripped down to: 4907 if not modules then modules={} end modules ['util-fil']={ version=1.001, @@ -7098,6 +7128,7 @@ end files.readcardinal1=files.readbyte files.readcardinal=files.readcardinal1 files.readinteger=files.readinteger1 +files.readsignedbyte=files.readinteger1 function files.readcardinal2(f) local a,b=byte(f:read(2),1,2) return 0x100*a+b @@ -9795,7 +9826,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-deb"] = package.loaded["util-deb"] or true --- original size: 4030, stripped down to: 2718 +-- original size: 8473, stripped down to: 6211 if not modules then modules={} end modules ['util-deb']={ version=1.001, @@ -9805,75 +9836,219 @@ if not modules then modules={} end modules ['util-deb']={ license="see context related readme files" } local debug=require "debug" -local getinfo=debug.getinfo +local getinfo,sethook=debug.getinfo,debug.sethook local type,next,tostring=type,next,tostring -local format,find=string.format,string.find -local is_boolean=string.is_boolean +local format,find,sub,gsub=string.format,string.find,string.sub,string.gsub +local insert,remove,sort=table.insert,table.remove,table.sort 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) +local ticks=os.gettimeofday or os.clock +local seconds=function(n) return n or 0 end +local overhead=0 +local dummycalls=10*1000 +local nesting=0 +local names={} +local function initialize() + if FFISUPPORTED and ffi then + if os.type=="windows" then + local okay,kernel=pcall(ffi.load,"kernel32") + if kernel then + local tonumber=ffi.number or tonumber +ffi.cdef[[ +int QueryPerformanceFrequency(int64_t *lpFrequency); +int QueryPerformanceCounter(int64_t *lpPerformanceCount); +]] + local target=ffi.new("__int64[1]") + ticks=function() + if kernel.QueryPerformanceCounter(target)==1 then + return tonumber(target[0]) + else + return 0 + end + end + local target=ffi.new("__int64[1]") + seconds=function(ticks) + if kernel.QueryPerformanceFrequency(target)==1 then + return ticks/tonumber(target[0]) + else + return 0 + end + end end - else - n=f.name or f.namewhat or f.what - if not n or n=="" then - n="?" + elseif os.type=="unix" then + local C=ffi.C + local tonumber=ffi.number or tonumber +ffi.cdef [[ +struct timespec { long sec; long nsec; }; +int clock_gettime(int timerid, struct timespec *t); + ]] + local target=ffi.new("timespec[?]",1) + function ticks() + C.clock_gettime(2,target) + return tonumber(target[0].sec*1000000000+target[0].nsec) + end + seconds=function(ticks) + return ticks/1000000000 + end + end + end + initialize=false +end +table.setmetatableindex(names,function(t,name) + local v=table.setmetatableindex(function(t,source) + local v=table.setmetatableindex(function(t,line) + local v={ total=0,count=0 } + t[line]=v + return v + end) + t[source]=v + return v + end) + t[name]=v + return v +end) +local function hook(where) + local f=getinfo(2,"nSl") + if f then + local source=f.short_src + if not source then + return + end + local line=f.linedefined or 0 + local name=f.name + if not name then + local what=f.what + if what=="C" then + name="<anonymous>" + else + name=f.namewhat or what or "<unknown>" end - if not names[n] then - names[n]=format("%42s : % 5i : %s",n,f.linedefined or 0,f.short_src or "unknown source") + end + local data=names[name][source][line] + if where=="call" then + data.count=data.count+1 + insert(data,ticks()) + elseif where=="return" then + local t=remove(data) + if t then + data.total=data.total+ticks()-t 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 +function debugger.showstats(printer) + local printer=printer or report + local calls=0 + local functions=0 local dataset={} - for name,count in next,counters do - dataset[#dataset+1]={ name,count } + local length=0 + local wholetime=0 + for name,sources in next,names do + for source,lines in next,sources do + for line,data in next,lines do + if #name>length then + length=#name + end + local total=data.total + local count=data.count + local real=total + if real>0 then + real=total-(count*overhead/dummycalls) + if real<0 then + real=0 + end + wholetime=wholetime+real + end + if line<0 then + line=0 + end + dataset[#dataset+1]={ real,total,count,name,source,line } + end + end + end + sort(dataset,function(a,b) + if a[1]==b[1] then + if a[2]==b[2] then + if a[3]==b[3] then + if a[4]==b[4] then + if a[5]==b[5] then + return a[6]<b[6] + else + return a[5]<b[5] + end + else + return a[4]<b[4] + end + else + return b[3]<a[3] + end + else + return b[2]<a[2] + end + else + return b[1]<a[1] + end + end) + if length>50 then + length=50 end - table.sort(dataset,function(a,b) return a[2]==b[2] and b[1]>a[1] or a[2]>b[2] end) + local fmt=string.formatters["%4.9k %4.9k %3.3k %8i %-"..length.."s %4i %s"] 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 + local data=dataset[i] + local real=data[1] + local total=data[2] + local count=data[3] + local name=data[4] + local source=data[5] + local line=data[6] + local percent=real/wholetime + calls=calls+count functions=functions+1 + name=gsub(name,"%s+"," ") + if #name>length then + name=sub(name,1,length) + end + printer(fmt(seconds(total),seconds(real),percent,count,name,line,source)) 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)) + printer("") + printer(format("functions : %i",functions)) + printer(format("calls : %i",calls)) + printer(format("overhead : %f",seconds(overhead/1000))) end -function debugger.savestats(filename,threshold) +function debugger.savestats(filename) local f=io.open(filename,'w') if f then - debugger.showstats(function(str) f:write(str) end,threshold) + debugger.showstats(function(str) f:write(str,"\n") end) f:close() end end function debugger.enable() - debug.sethook(hook,"c") + if nesting==0 then + running=true + if initialize then + initialize() + end + sethook(hook,"cr") + local function dummy() end + local t=ticks() + for i=1,dummycalls do + dummy() + end + overhead=ticks()-t + end + if nesting>0 then + nesting=nesting+1 + end end function debugger.disable() - debug.sethook() + if nesting>0 then + nesting=nesting-1 + end + if nesting==0 then + sethook() + end end local function showtraceback(rep) local level=2 @@ -10716,7 +10891,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-env"] = package.loaded["util-env"] or true --- original size: 9028, stripped down to: 5176 +-- original size: 9552, stripped down to: 5176 if not modules then modules={} end modules ['util-env']={ version=1.001, @@ -15055,7 +15230,7 @@ do -- create closure to overcome 200 locals limit package.loaded["data-ini"] = package.loaded["data-ini"] or true --- original size: 11444, stripped down to: 7830 +-- original size: 11459, stripped down to: 7680 if not modules then modules={} end modules ['data-ini']={ version=1.001, @@ -15200,11 +15375,6 @@ if not texroot or texroot=="" then ossetenv('TEXROOT',texroot) end environment.texroot=file.collapsepath(texroot) -if type(profiler)=="table" and not jit then - directives.register("system.profile",function() - profiler.start("luatex-profile.log") - end) -end local prefixes=utilities.storage.allocate() resolvers.prefixes=prefixes local resolved={} @@ -19454,7 +19624,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-lib"] = package.loaded["util-lib"] or true --- original size: 11846, stripped down to: 6059 +-- original size: 13648, stripped down to: 7455 if not modules then modules={} end modules ['util-lib']={ version=1.001, @@ -19463,35 +19633,51 @@ if not modules then modules={} end modules ['util-lib']={ copyright="PRAGMA ADE / ConTeXt Development Team", license="see context related readme files", } -local gsub,find=string.gsub,string.find -local pathpart,nameonly,joinfile=file.pathpart,file.nameonly,file.join -local findfile,findfiles=resolvers and resolvers.findfile,resolvers and resolvers.findfiles -local loaded=package.loaded -local report_swiglib=logs.reporter("swiglib") -local trace_swiglib=false trackers.register("resolvers.swiglib",function(v) trace_swiglib=v end) +local type=type +local next=next +local pcall=pcall +local gsub=string.gsub +local find=string.find +local sort=table.sort +local pathpart=file.pathpart +local nameonly=file.nameonly +local joinfile=file.join +local removesuffix=file.removesuffix +local findfile=resolvers.findfile +local findfiles=resolvers.findfiles +local expandpaths=resolvers.expandedpathlistfromvariable +local qualifiedpath=file.is_qualified_path +local isfile=lfs.isfile local done=false -local function requireswiglib(required,version) - local trace_swiglib=trace_swiglib or package.helpers.trace - local library=loaded[required] - if library==nil then - if trace_swiglib then - report_swiglib("requiring library %a with version %a",required,version or "any") +local function locate(required,version,trace,report,action) + if type(required)~="string" then + report("provide a proper library name") + return + end + if trace then + report("requiring library %a with version %a",required,version or "any") + end + local found_library=nil + if qualifiedpath(required) then + if isfile(required) then + found_library=required end + else local required_full=gsub(required,"%.","/") local required_path=pathpart(required_full) local required_base=nameonly(required_full) local required_name=required_base.."."..os.libsuffix local version=type(version)=="string" and version~="" and version or false local engine=environment.ownmain or false - if trace_swiglib and not done then - local list=resolvers.expandedpathlistfromvariable("lib") + if trace and not done then + local list=expandpaths("lib") for i=1,#list do - report_swiglib("tds path %i: %s",i,list[i]) + report("tds path %i: %s",i,list[i]) end end local function found(locate,asked_library,how,...) - if trace_swiglib then - report_swiglib("checking %s: %a",how,asked_library) + if trace then + report("checking %s: %a",how,asked_library) end return locate(asked_library,...) end @@ -19499,45 +19685,45 @@ local function requireswiglib(required,version) local found=nil if version then local asked_library=joinfile(required_path,version,required_name) - if trace_swiglib then - report_swiglib("checking %s: %a","with version",asked_library) + if trace then + report("checking %s: %a","with version",asked_library) end found=locate(asked_library,...) end if not found or found=="" then local asked_library=joinfile(required_path,required_name) - if trace_swiglib then - report_swiglib("checking %s: %a","with version",asked_library) + if trace then + report("checking %s: %a","with version",asked_library) end found=locate(asked_library,...) end return found and found~="" and found or false end local function attempt(checkpattern) - if trace_swiglib then - report_swiglib("checking tds lib paths strictly") + if trace then + report("checking tds lib paths strictly") end local found=findfile and check(findfile,"lib") if found and (not checkpattern or find(found,checkpattern)) then return found end - if trace_swiglib then - report_swiglib("checking tds lib paths with wildcard") + if trace then + report("checking tds lib paths with wildcard") end local asked_library=joinfile(required_path,".*",required_name) - if trace_swiglib then - report_swiglib("checking %s: %a","latest version",asked_library) + if trace then + report("checking %s: %a","latest version",asked_library) end local list=findfiles(asked_library,"lib",true) if list and #list>0 then - table.sort(list) + sort(list) local found=list[#list] if found and (not checkpattern or find(found,checkpattern)) then return found end end - if trace_swiglib then - report_swiglib("checking lib paths") + if trace then + report("checking lib paths") end package.extralibpath(environment.ownpath) local paths=package.libpaths() @@ -19549,89 +19735,132 @@ local function requireswiglib(required,version) end return false end - local found_library=nil if engine then - if trace_swiglib then - report_swiglib("attemp 1, engine %a",engine) + if trace then + report("attemp 1, engine %a",engine) end found_library=attempt("/"..engine.."/") if not found_library then - if trace_swiglib then - report_swiglib("attemp 2, no engine",asked_library) + if trace then + report("attemp 2, no engine",asked_library) end found_library=attempt() end else found_library=attempt() end - if not found_library then - if trace_swiglib then - report_swiglib("not found: %a",required) - end + end + if not found_library then + if trace then + report("not found: %a",required) + end + library=false + else + if trace then + report("found: %a",found_library) + end + local message,result=action(found_library,required_base) + if result then + library=result + else library=false + report("load error: message %a, library %a",tostring(message),found_library or "no library") + end + end + if not library then + report("unknown: %a",required) + elseif trace then + report("stored: %a",required) + end + return library +end +do + local report_swiglib=logs.reporter("swiglib") + local trace_swiglib=false + local savedrequire=require + local loadedlibs={} + trackers.register("resolvers.swiglib",function(v) trace_swiglib=v end) + function requireswiglib(required,version) + local library=loadedlibs[library] + if library==nil then + local trace_swiglib=trace_swiglib or package.helpers.trace + library=locate(required,version,trace_swiglib,report_swiglib,function(name,base) + dir.push(pathpart(name)) + local opener="luaopen_"..base + local library,message=package.loadlib(name,opener) + local libtype=type(library) + if libtype=="function" then + library=library() + message=true + else + report_swiglib("load error: %a returns %a, message %a, library %a",opener,libtype,(string.gsub(message or "no message","[%s]+$","")),found_library or "no library") + library=false + end + dir.pop() + return message,library + end) + loadedlibs[required]=library or false + end + return library + end + function require(name,version) + if find(name,"^swiglib%.") then + return requireswiglib(name,version) else - local path=pathpart(found_library) - local base=nameonly(found_library) - dir.push(path) + return savedrequire(name) + end + end + local swiglibs={} + local initializer="core" + function swiglib(name,version) + local library=swiglibs[name] + if not library then + statistics.starttiming(swiglibs) if trace_swiglib then - report_swiglib("found: %a",found_library) - end - local message=nil - local opener="luaopen_"..required_base - library,message=package.loadlib(found_library,opener) - local libtype=type(library) - if libtype=="function" then - library=library() + report_swiglib("loading %a",name) + end + if not find(name,"%."..initializer.."$") then + fullname="swiglib."..name.."."..initializer else - report_swiglib("load error: %a returns %a, message %a, library %a",opener,libtype,(string.gsub(message or "no message","[%s]+$","")),found_library or "no library") - library=false + fullname="swiglib."..name end - dir.pop() + library=requireswiglib(fullname,version) + swiglibs[name]=library + statistics.stoptiming(swiglibs) end - if not library then - report_swiglib("unknown: %a",required) - elseif trace_swiglib then - report_swiglib("stored: %a",required) - end - loaded[required]=library - else - report_swiglib("reused: %a",required) + return library end - return library + statistics.register("used swiglibs",function() + if next(swiglibs) then + return string.format("%s, initial load time %s seconds",table.concat(table.sortedkeys(swiglibs)," "),statistics.elapsedtime(swiglibs)) + end + end) end -local savedrequire=require -function require(name,version) - if find(name,"^swiglib%.") then - return requireswiglib(name,version) - else - return savedrequire(name) +if FFISUPPORTED and ffi and ffi.load then + local report_ffilib=logs.reporter("ffilib") + local trace_ffilib=false + local savedffiload=ffi.load + trackers.register("resolvers.ffilib",function(v) trace_ffilib=v end) + function ffilib(required,version) + return locate(required,version,trace_ffilib,report_ffilib,function(name) + local message,library=pcall(savedffiload,removesuffix(name)) + if type(library)=="userdata" then + return message,library + else + return message,false + end + end) end -end -local swiglibs={} -local initializer="core" -function swiglib(name,version) - local library=swiglibs[name] - if not library then - statistics.starttiming(swiglibs) - if trace_swiglib then - report_swiglib("loading %a",name) - end - if not find(name,"%."..initializer.."$") then - fullname="swiglib."..name.."."..initializer + function ffi.load(name) + local library=ffilib(name) + if type(library)=="userdata" then + return library else - fullname="swiglib."..name + report_ffilib("trying to load %a using normal loader",name) + return savedffiload(name) end - library=requireswiglib(fullname,version) - swiglibs[name]=library - statistics.stoptiming(swiglibs) end - return library end -statistics.register("used swiglibs",function() - if next(swiglibs) then - return string.format("%s, initial load time %s seconds",table.concat(table.sortedkeys(swiglibs)," "),statistics.elapsedtime(swiglibs)) - end -end) end -- of closure @@ -19975,8 +20204,8 @@ end -- of closure -- used libraries : l-lua.lua l-sandbox.lua l-package.lua l-lpeg.lua l-function.lua l-string.lua l-table.lua l-io.lua l-number.lua l-set.lua l-os.lua l-file.lua l-gzip.lua l-md5.lua l-url.lua l-dir.lua l-boolean.lua l-unicode.lua l-math.lua util-str.lua util-tab.lua util-fil.lua util-sac.lua util-sto.lua util-prs.lua util-fmt.lua trac-set.lua trac-log.lua trac-inf.lua trac-pro.lua util-lua.lua util-deb.lua util-tpl.lua util-sbx.lua util-mrg.lua util-env.lua luat-env.lua lxml-tab.lua lxml-lpt.lua lxml-mis.lua lxml-aux.lua lxml-xml.lua trac-xml.lua data-ini.lua data-exp.lua data-env.lua data-tmp.lua data-met.lua data-res.lua data-pre.lua data-inp.lua data-out.lua data-fil.lua data-con.lua data-use.lua data-zip.lua data-tre.lua data-sch.lua data-lua.lua data-aux.lua data-tmf.lua data-lst.lua util-lib.lua luat-sta.lua luat-fmt.lua -- skipped libraries : - --- original bytes : 847975 --- stripped bytes : 308174 +-- original bytes : 855737 +-- stripped bytes : 310443 -- end library merge diff --git a/scripts/context/stubs/win64/mtxrun.lua b/scripts/context/stubs/win64/mtxrun.lua index bdb81b477..0c3355fcc 100644 --- a/scripts/context/stubs/win64/mtxrun.lua +++ b/scripts/context/stubs/win64/mtxrun.lua @@ -5632,7 +5632,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-str"] = package.loaded["util-str"] or true --- original size: 36650, stripped down to: 19963 +-- original size: 37582, stripped down to: 20676 if not modules then modules={} end modules ['util-str']={ version=1.001, @@ -5871,6 +5871,27 @@ function number.sparseexponent(f,n) end return tostring(n) end +local hf={} +local hs={} +setmetatable(hf,{ __index=function(t,k) + local v="%."..k.."f" + t[k]=v + return v +end } ) +setmetatable(hs,{ __index=function(t,k) + local v="%"..k.."s" + t[k]=v + return v +end } ) +function number.formattedfloat(n,b,a) + local s=format(hf[a],n) + local l=(b or 0)+(a or 0)+1 + if #s<l then + return format(hs[l],s) + else + return s + end +end local template=[[ %s %s @@ -5898,6 +5919,7 @@ local autodouble=string.autodouble local sequenced=table.sequenced local formattednumber=number.formatted local sparseexponent=number.sparseexponent +local formattedfloat=number.formattedfloat ]] else environment={ @@ -5921,6 +5943,7 @@ else sequenced=table.sequenced, formattednumber=number.formatted, sparseexponent=number.sparseexponent, + formattedfloat=number.formattedfloat } end local arguments={ "a1" } @@ -5931,6 +5954,7 @@ setmetatable(arguments,{ __index=function(t,k) end }) local prefix_any=C((S("+- .")+R("09"))^0) +local prefix_sub=(C((S("+-")+R("09"))^0)+Cc(0))*P(".")*(C((S("+-")+R("09"))^0)+Cc(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 @@ -5981,6 +6005,10 @@ local format_F=function(f) return format("format((a%s %% 1 == 0) and '%%i' or '%%%sf',a%s)",n,f,n) end end +local format_k=function(b,a) + n=n+1 + return format("formattedfloat(a%s,%i,%i)",n,b or 0,a or 0) +end local format_g=function(f) n=n+1 return format("format('%%%sg',a%s)",f,n) @@ -6189,7 +6217,8 @@ local builder=Cs { "start", +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("N") ++V("k") +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") @@ -6216,6 +6245,7 @@ local builder=Cs { "start", ["S"]=(prefix_any*P("S"))/format_S, ["Q"]=(prefix_any*P("Q"))/format_S, ["N"]=(prefix_any*P("N"))/format_N, + ["k"]=(prefix_sub*P("k"))/format_k, ["c"]=(prefix_any*P("c"))/format_c, ["C"]=(prefix_any*P("C"))/format_C, ["r"]=(prefix_any*P("r"))/format_r, @@ -7012,7 +7042,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-fil"] = package.loaded["util-fil"] or true --- original size: 6316, stripped down to: 4866 +-- original size: 6362, stripped down to: 4907 if not modules then modules={} end modules ['util-fil']={ version=1.001, @@ -7098,6 +7128,7 @@ end files.readcardinal1=files.readbyte files.readcardinal=files.readcardinal1 files.readinteger=files.readinteger1 +files.readsignedbyte=files.readinteger1 function files.readcardinal2(f) local a,b=byte(f:read(2),1,2) return 0x100*a+b @@ -9795,7 +9826,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-deb"] = package.loaded["util-deb"] or true --- original size: 4030, stripped down to: 2718 +-- original size: 8473, stripped down to: 6211 if not modules then modules={} end modules ['util-deb']={ version=1.001, @@ -9805,75 +9836,219 @@ if not modules then modules={} end modules ['util-deb']={ license="see context related readme files" } local debug=require "debug" -local getinfo=debug.getinfo +local getinfo,sethook=debug.getinfo,debug.sethook local type,next,tostring=type,next,tostring -local format,find=string.format,string.find -local is_boolean=string.is_boolean +local format,find,sub,gsub=string.format,string.find,string.sub,string.gsub +local insert,remove,sort=table.insert,table.remove,table.sort 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) +local ticks=os.gettimeofday or os.clock +local seconds=function(n) return n or 0 end +local overhead=0 +local dummycalls=10*1000 +local nesting=0 +local names={} +local function initialize() + if FFISUPPORTED and ffi then + if os.type=="windows" then + local okay,kernel=pcall(ffi.load,"kernel32") + if kernel then + local tonumber=ffi.number or tonumber +ffi.cdef[[ +int QueryPerformanceFrequency(int64_t *lpFrequency); +int QueryPerformanceCounter(int64_t *lpPerformanceCount); +]] + local target=ffi.new("__int64[1]") + ticks=function() + if kernel.QueryPerformanceCounter(target)==1 then + return tonumber(target[0]) + else + return 0 + end + end + local target=ffi.new("__int64[1]") + seconds=function(ticks) + if kernel.QueryPerformanceFrequency(target)==1 then + return ticks/tonumber(target[0]) + else + return 0 + end + end end - else - n=f.name or f.namewhat or f.what - if not n or n=="" then - n="?" + elseif os.type=="unix" then + local C=ffi.C + local tonumber=ffi.number or tonumber +ffi.cdef [[ +struct timespec { long sec; long nsec; }; +int clock_gettime(int timerid, struct timespec *t); + ]] + local target=ffi.new("timespec[?]",1) + function ticks() + C.clock_gettime(2,target) + return tonumber(target[0].sec*1000000000+target[0].nsec) + end + seconds=function(ticks) + return ticks/1000000000 + end + end + end + initialize=false +end +table.setmetatableindex(names,function(t,name) + local v=table.setmetatableindex(function(t,source) + local v=table.setmetatableindex(function(t,line) + local v={ total=0,count=0 } + t[line]=v + return v + end) + t[source]=v + return v + end) + t[name]=v + return v +end) +local function hook(where) + local f=getinfo(2,"nSl") + if f then + local source=f.short_src + if not source then + return + end + local line=f.linedefined or 0 + local name=f.name + if not name then + local what=f.what + if what=="C" then + name="<anonymous>" + else + name=f.namewhat or what or "<unknown>" end - if not names[n] then - names[n]=format("%42s : % 5i : %s",n,f.linedefined or 0,f.short_src or "unknown source") + end + local data=names[name][source][line] + if where=="call" then + data.count=data.count+1 + insert(data,ticks()) + elseif where=="return" then + local t=remove(data) + if t then + data.total=data.total+ticks()-t 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 +function debugger.showstats(printer) + local printer=printer or report + local calls=0 + local functions=0 local dataset={} - for name,count in next,counters do - dataset[#dataset+1]={ name,count } + local length=0 + local wholetime=0 + for name,sources in next,names do + for source,lines in next,sources do + for line,data in next,lines do + if #name>length then + length=#name + end + local total=data.total + local count=data.count + local real=total + if real>0 then + real=total-(count*overhead/dummycalls) + if real<0 then + real=0 + end + wholetime=wholetime+real + end + if line<0 then + line=0 + end + dataset[#dataset+1]={ real,total,count,name,source,line } + end + end + end + sort(dataset,function(a,b) + if a[1]==b[1] then + if a[2]==b[2] then + if a[3]==b[3] then + if a[4]==b[4] then + if a[5]==b[5] then + return a[6]<b[6] + else + return a[5]<b[5] + end + else + return a[4]<b[4] + end + else + return b[3]<a[3] + end + else + return b[2]<a[2] + end + else + return b[1]<a[1] + end + end) + if length>50 then + length=50 end - table.sort(dataset,function(a,b) return a[2]==b[2] and b[1]>a[1] or a[2]>b[2] end) + local fmt=string.formatters["%4.9k %4.9k %3.3k %8i %-"..length.."s %4i %s"] 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 + local data=dataset[i] + local real=data[1] + local total=data[2] + local count=data[3] + local name=data[4] + local source=data[5] + local line=data[6] + local percent=real/wholetime + calls=calls+count functions=functions+1 + name=gsub(name,"%s+"," ") + if #name>length then + name=sub(name,1,length) + end + printer(fmt(seconds(total),seconds(real),percent,count,name,line,source)) 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)) + printer("") + printer(format("functions : %i",functions)) + printer(format("calls : %i",calls)) + printer(format("overhead : %f",seconds(overhead/1000))) end -function debugger.savestats(filename,threshold) +function debugger.savestats(filename) local f=io.open(filename,'w') if f then - debugger.showstats(function(str) f:write(str) end,threshold) + debugger.showstats(function(str) f:write(str,"\n") end) f:close() end end function debugger.enable() - debug.sethook(hook,"c") + if nesting==0 then + running=true + if initialize then + initialize() + end + sethook(hook,"cr") + local function dummy() end + local t=ticks() + for i=1,dummycalls do + dummy() + end + overhead=ticks()-t + end + if nesting>0 then + nesting=nesting+1 + end end function debugger.disable() - debug.sethook() + if nesting>0 then + nesting=nesting-1 + end + if nesting==0 then + sethook() + end end local function showtraceback(rep) local level=2 @@ -10716,7 +10891,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-env"] = package.loaded["util-env"] or true --- original size: 9028, stripped down to: 5176 +-- original size: 9552, stripped down to: 5176 if not modules then modules={} end modules ['util-env']={ version=1.001, @@ -15055,7 +15230,7 @@ do -- create closure to overcome 200 locals limit package.loaded["data-ini"] = package.loaded["data-ini"] or true --- original size: 11444, stripped down to: 7830 +-- original size: 11459, stripped down to: 7680 if not modules then modules={} end modules ['data-ini']={ version=1.001, @@ -15200,11 +15375,6 @@ if not texroot or texroot=="" then ossetenv('TEXROOT',texroot) end environment.texroot=file.collapsepath(texroot) -if type(profiler)=="table" and not jit then - directives.register("system.profile",function() - profiler.start("luatex-profile.log") - end) -end local prefixes=utilities.storage.allocate() resolvers.prefixes=prefixes local resolved={} @@ -19454,7 +19624,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-lib"] = package.loaded["util-lib"] or true --- original size: 11846, stripped down to: 6059 +-- original size: 13648, stripped down to: 7455 if not modules then modules={} end modules ['util-lib']={ version=1.001, @@ -19463,35 +19633,51 @@ if not modules then modules={} end modules ['util-lib']={ copyright="PRAGMA ADE / ConTeXt Development Team", license="see context related readme files", } -local gsub,find=string.gsub,string.find -local pathpart,nameonly,joinfile=file.pathpart,file.nameonly,file.join -local findfile,findfiles=resolvers and resolvers.findfile,resolvers and resolvers.findfiles -local loaded=package.loaded -local report_swiglib=logs.reporter("swiglib") -local trace_swiglib=false trackers.register("resolvers.swiglib",function(v) trace_swiglib=v end) +local type=type +local next=next +local pcall=pcall +local gsub=string.gsub +local find=string.find +local sort=table.sort +local pathpart=file.pathpart +local nameonly=file.nameonly +local joinfile=file.join +local removesuffix=file.removesuffix +local findfile=resolvers.findfile +local findfiles=resolvers.findfiles +local expandpaths=resolvers.expandedpathlistfromvariable +local qualifiedpath=file.is_qualified_path +local isfile=lfs.isfile local done=false -local function requireswiglib(required,version) - local trace_swiglib=trace_swiglib or package.helpers.trace - local library=loaded[required] - if library==nil then - if trace_swiglib then - report_swiglib("requiring library %a with version %a",required,version or "any") +local function locate(required,version,trace,report,action) + if type(required)~="string" then + report("provide a proper library name") + return + end + if trace then + report("requiring library %a with version %a",required,version or "any") + end + local found_library=nil + if qualifiedpath(required) then + if isfile(required) then + found_library=required end + else local required_full=gsub(required,"%.","/") local required_path=pathpart(required_full) local required_base=nameonly(required_full) local required_name=required_base.."."..os.libsuffix local version=type(version)=="string" and version~="" and version or false local engine=environment.ownmain or false - if trace_swiglib and not done then - local list=resolvers.expandedpathlistfromvariable("lib") + if trace and not done then + local list=expandpaths("lib") for i=1,#list do - report_swiglib("tds path %i: %s",i,list[i]) + report("tds path %i: %s",i,list[i]) end end local function found(locate,asked_library,how,...) - if trace_swiglib then - report_swiglib("checking %s: %a",how,asked_library) + if trace then + report("checking %s: %a",how,asked_library) end return locate(asked_library,...) end @@ -19499,45 +19685,45 @@ local function requireswiglib(required,version) local found=nil if version then local asked_library=joinfile(required_path,version,required_name) - if trace_swiglib then - report_swiglib("checking %s: %a","with version",asked_library) + if trace then + report("checking %s: %a","with version",asked_library) end found=locate(asked_library,...) end if not found or found=="" then local asked_library=joinfile(required_path,required_name) - if trace_swiglib then - report_swiglib("checking %s: %a","with version",asked_library) + if trace then + report("checking %s: %a","with version",asked_library) end found=locate(asked_library,...) end return found and found~="" and found or false end local function attempt(checkpattern) - if trace_swiglib then - report_swiglib("checking tds lib paths strictly") + if trace then + report("checking tds lib paths strictly") end local found=findfile and check(findfile,"lib") if found and (not checkpattern or find(found,checkpattern)) then return found end - if trace_swiglib then - report_swiglib("checking tds lib paths with wildcard") + if trace then + report("checking tds lib paths with wildcard") end local asked_library=joinfile(required_path,".*",required_name) - if trace_swiglib then - report_swiglib("checking %s: %a","latest version",asked_library) + if trace then + report("checking %s: %a","latest version",asked_library) end local list=findfiles(asked_library,"lib",true) if list and #list>0 then - table.sort(list) + sort(list) local found=list[#list] if found and (not checkpattern or find(found,checkpattern)) then return found end end - if trace_swiglib then - report_swiglib("checking lib paths") + if trace then + report("checking lib paths") end package.extralibpath(environment.ownpath) local paths=package.libpaths() @@ -19549,89 +19735,132 @@ local function requireswiglib(required,version) end return false end - local found_library=nil if engine then - if trace_swiglib then - report_swiglib("attemp 1, engine %a",engine) + if trace then + report("attemp 1, engine %a",engine) end found_library=attempt("/"..engine.."/") if not found_library then - if trace_swiglib then - report_swiglib("attemp 2, no engine",asked_library) + if trace then + report("attemp 2, no engine",asked_library) end found_library=attempt() end else found_library=attempt() end - if not found_library then - if trace_swiglib then - report_swiglib("not found: %a",required) - end + end + if not found_library then + if trace then + report("not found: %a",required) + end + library=false + else + if trace then + report("found: %a",found_library) + end + local message,result=action(found_library,required_base) + if result then + library=result + else library=false + report("load error: message %a, library %a",tostring(message),found_library or "no library") + end + end + if not library then + report("unknown: %a",required) + elseif trace then + report("stored: %a",required) + end + return library +end +do + local report_swiglib=logs.reporter("swiglib") + local trace_swiglib=false + local savedrequire=require + local loadedlibs={} + trackers.register("resolvers.swiglib",function(v) trace_swiglib=v end) + function requireswiglib(required,version) + local library=loadedlibs[library] + if library==nil then + local trace_swiglib=trace_swiglib or package.helpers.trace + library=locate(required,version,trace_swiglib,report_swiglib,function(name,base) + dir.push(pathpart(name)) + local opener="luaopen_"..base + local library,message=package.loadlib(name,opener) + local libtype=type(library) + if libtype=="function" then + library=library() + message=true + else + report_swiglib("load error: %a returns %a, message %a, library %a",opener,libtype,(string.gsub(message or "no message","[%s]+$","")),found_library or "no library") + library=false + end + dir.pop() + return message,library + end) + loadedlibs[required]=library or false + end + return library + end + function require(name,version) + if find(name,"^swiglib%.") then + return requireswiglib(name,version) else - local path=pathpart(found_library) - local base=nameonly(found_library) - dir.push(path) + return savedrequire(name) + end + end + local swiglibs={} + local initializer="core" + function swiglib(name,version) + local library=swiglibs[name] + if not library then + statistics.starttiming(swiglibs) if trace_swiglib then - report_swiglib("found: %a",found_library) - end - local message=nil - local opener="luaopen_"..required_base - library,message=package.loadlib(found_library,opener) - local libtype=type(library) - if libtype=="function" then - library=library() + report_swiglib("loading %a",name) + end + if not find(name,"%."..initializer.."$") then + fullname="swiglib."..name.."."..initializer else - report_swiglib("load error: %a returns %a, message %a, library %a",opener,libtype,(string.gsub(message or "no message","[%s]+$","")),found_library or "no library") - library=false + fullname="swiglib."..name end - dir.pop() + library=requireswiglib(fullname,version) + swiglibs[name]=library + statistics.stoptiming(swiglibs) end - if not library then - report_swiglib("unknown: %a",required) - elseif trace_swiglib then - report_swiglib("stored: %a",required) - end - loaded[required]=library - else - report_swiglib("reused: %a",required) + return library end - return library + statistics.register("used swiglibs",function() + if next(swiglibs) then + return string.format("%s, initial load time %s seconds",table.concat(table.sortedkeys(swiglibs)," "),statistics.elapsedtime(swiglibs)) + end + end) end -local savedrequire=require -function require(name,version) - if find(name,"^swiglib%.") then - return requireswiglib(name,version) - else - return savedrequire(name) +if FFISUPPORTED and ffi and ffi.load then + local report_ffilib=logs.reporter("ffilib") + local trace_ffilib=false + local savedffiload=ffi.load + trackers.register("resolvers.ffilib",function(v) trace_ffilib=v end) + function ffilib(required,version) + return locate(required,version,trace_ffilib,report_ffilib,function(name) + local message,library=pcall(savedffiload,removesuffix(name)) + if type(library)=="userdata" then + return message,library + else + return message,false + end + end) end -end -local swiglibs={} -local initializer="core" -function swiglib(name,version) - local library=swiglibs[name] - if not library then - statistics.starttiming(swiglibs) - if trace_swiglib then - report_swiglib("loading %a",name) - end - if not find(name,"%."..initializer.."$") then - fullname="swiglib."..name.."."..initializer + function ffi.load(name) + local library=ffilib(name) + if type(library)=="userdata" then + return library else - fullname="swiglib."..name + report_ffilib("trying to load %a using normal loader",name) + return savedffiload(name) end - library=requireswiglib(fullname,version) - swiglibs[name]=library - statistics.stoptiming(swiglibs) end - return library end -statistics.register("used swiglibs",function() - if next(swiglibs) then - return string.format("%s, initial load time %s seconds",table.concat(table.sortedkeys(swiglibs)," "),statistics.elapsedtime(swiglibs)) - end -end) end -- of closure @@ -19975,8 +20204,8 @@ end -- of closure -- used libraries : l-lua.lua l-sandbox.lua l-package.lua l-lpeg.lua l-function.lua l-string.lua l-table.lua l-io.lua l-number.lua l-set.lua l-os.lua l-file.lua l-gzip.lua l-md5.lua l-url.lua l-dir.lua l-boolean.lua l-unicode.lua l-math.lua util-str.lua util-tab.lua util-fil.lua util-sac.lua util-sto.lua util-prs.lua util-fmt.lua trac-set.lua trac-log.lua trac-inf.lua trac-pro.lua util-lua.lua util-deb.lua util-tpl.lua util-sbx.lua util-mrg.lua util-env.lua luat-env.lua lxml-tab.lua lxml-lpt.lua lxml-mis.lua lxml-aux.lua lxml-xml.lua trac-xml.lua data-ini.lua data-exp.lua data-env.lua data-tmp.lua data-met.lua data-res.lua data-pre.lua data-inp.lua data-out.lua data-fil.lua data-con.lua data-use.lua data-zip.lua data-tre.lua data-sch.lua data-lua.lua data-aux.lua data-tmf.lua data-lst.lua util-lib.lua luat-sta.lua luat-fmt.lua -- skipped libraries : - --- original bytes : 847975 --- stripped bytes : 308174 +-- original bytes : 855737 +-- stripped bytes : 310443 -- end library merge diff --git a/tex/context/base/mkii/cont-new.mkii b/tex/context/base/mkii/cont-new.mkii index 0e6e6851f..1c5dfe2d5 100644 --- a/tex/context/base/mkii/cont-new.mkii +++ b/tex/context/base/mkii/cont-new.mkii @@ -11,7 +11,7 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -\newcontextversion{2017.02.20 17:55} +\newcontextversion{2017.02.23 17:07} %D This file is loaded at runtime, thereby providing an %D excellent place for hacks, patches, extensions and new diff --git a/tex/context/base/mkii/context.mkii b/tex/context/base/mkii/context.mkii index 868227917..a89ce83ff 100644 --- a/tex/context/base/mkii/context.mkii +++ b/tex/context/base/mkii/context.mkii @@ -20,7 +20,7 @@ %D your styles an modules. \edef\contextformat {\jobname} -\edef\contextversion{2017.02.20 17:55} +\edef\contextversion{2017.02.23 17:07} %D For those who want to use this: diff --git a/tex/context/base/mkiv/anch-pos.lua b/tex/context/base/mkiv/anch-pos.lua index 6a9612d9e..2ba9e2420 100644 --- a/tex/context/base/mkiv/anch-pos.lua +++ b/tex/context/base/mkiv/anch-pos.lua @@ -90,8 +90,6 @@ local jobpositions = { job.positions = jobpositions -_plib_ = jobpositions -- might go - local default = { -- not r and paragraphs etc __index = { x = 0, -- x position baseline diff --git a/tex/context/base/mkiv/char-fio.lua b/tex/context/base/mkiv/char-fio.lua index ab2555935..fa69d9356 100644 --- a/tex/context/base/mkiv/char-fio.lua +++ b/tex/context/base/mkiv/char-fio.lua @@ -42,18 +42,19 @@ local reporting = "no" -- per line by default local enforced = { - ["characters.filters.utf.reorder"] = true, ["characters.filters.utf.collapse"] = true, ["characters.filters.utf.decompose"] = true, + ["characters.filters.utf.reorder"] = false, } function utffilters.enable() + -- only used one time (normally) for k, v in next, enforced do if v then if reporting == "yes" then report("%a enabled",k) end - enableaction(textfileactions,v) + enableaction(textfileactions,k) else if reporting == "yes" then report("%a not enabled",k) diff --git a/tex/context/base/mkiv/char-utf.lua b/tex/context/base/mkiv/char-utf.lua index ece9d7a76..f4a6d50e1 100644 --- a/tex/context/base/mkiv/char-utf.lua +++ b/tex/context/base/mkiv/char-utf.lua @@ -409,8 +409,8 @@ function utffilters.addgrapheme(result,first,second) -- can be U+ 0x string or u graphemes[first][second] = result end local pair = first .. second - if not composed[pair] then - composed[pair] = result + if not collapsed[pair] then + collapsed[pair] = result p_composed = nil end end @@ -498,7 +498,8 @@ local function prepare() for k, v in sortedhash(characters.data) do local combining = v.combining -- v.ordering or v.combining if combining then - hash[utfchar(k)] = { utfchar(k), combining, 0 } -- slot 3 can be used in sort + local u = utfchar(k) + hash[u] = { u, combining, 0 } -- slot 3 can be used in sort end end local e = utfchartabletopattern(exceptions) @@ -522,7 +523,7 @@ end -- local collapse = utffilters.collapse -- local decompose = utffilters.decompose --- local preprocess = utffilters.preprocess +-- local reorder = utffilters.reorder -- -- local c1, c2, c3 = "a", "̂", "̃" -- local r2, r3 = "â", "ẫ" @@ -540,7 +541,7 @@ end -- for i=1,10000 do -- collapse(data) -- decompose(data) --- -- preprocess(data) +-- -- reorder(data) -- end -- print(os.clock()-t,decompose(collapse(data))==okay,decompose(collapse(str))) -- end diff --git a/tex/context/base/mkiv/char-utf.mkiv b/tex/context/base/mkiv/char-utf.mkiv index fe9f402ef..3b77771a7 100644 --- a/tex/context/base/mkiv/char-utf.mkiv +++ b/tex/context/base/mkiv/char-utf.mkiv @@ -31,9 +31,9 @@ %D since the source files are rather simple, we postpone the %D initialization till runtime. -\appendtoks - \clf_enableutf % not needed when we create a format so we do it now -\to \everyjob +% \appendtoks +% \clf_enableutf % not needed when we create a format so we do it now +% \to \everyjob %D The next one influences input parsing. %D diff --git a/tex/context/base/mkiv/cont-new.mkiv b/tex/context/base/mkiv/cont-new.mkiv index 4c044c330..c67cf1c25 100644 --- a/tex/context/base/mkiv/cont-new.mkiv +++ b/tex/context/base/mkiv/cont-new.mkiv @@ -11,7 +11,7 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -\newcontextversion{2017.02.20 17:55} +\newcontextversion{2017.02.23 17:07} %D This file is loaded at runtime, thereby providing an excellent place for %D hacks, patches, extensions and new features. diff --git a/tex/context/base/mkiv/context.mkiv b/tex/context/base/mkiv/context.mkiv index 31d79390a..dc66b5564 100644 --- a/tex/context/base/mkiv/context.mkiv +++ b/tex/context/base/mkiv/context.mkiv @@ -39,7 +39,7 @@ %D up and the dependencies are more consistent. \edef\contextformat {\jobname} -\edef\contextversion{2017.02.20 17:55} +\edef\contextversion{2017.02.23 17:07} \edef\contextkind {beta} %D For those who want to use this: diff --git a/tex/context/base/mkiv/data-ini.lua b/tex/context/base/mkiv/data-ini.lua index 5ed2cce26..09357368c 100644 --- a/tex/context/base/mkiv/data-ini.lua +++ b/tex/context/base/mkiv/data-ini.lua @@ -217,11 +217,11 @@ end environment.texroot = file.collapsepath(texroot) -if type(profiler) == "table" and not jit then - directives.register("system.profile",function() - profiler.start("luatex-profile.log") - end) -end +-- if type(profiler) == "table" and not jit then +-- directives.register("system.profile",function() +-- profiler.start("luatex-profile.log") +-- end) +-- end -- a forward definition diff --git a/tex/context/base/mkiv/font-dsp.lua b/tex/context/base/mkiv/font-dsp.lua index 2d52c23a9..a5a1ae7c0 100644 --- a/tex/context/base/mkiv/font-dsp.lua +++ b/tex/context/base/mkiv/font-dsp.lua @@ -72,6 +72,7 @@ local streamreader = readers.streamreader local setposition = streamreader.setposition local getposition = streamreader.getposition local skipshort = streamreader.skipshort +local skipbytes = streamreader.skip local readushort = streamreader.readcardinal2 -- 16-bit unsigned integer local readulong = streamreader.readcardinal4 -- 24-bit unsigned integer local readshort = streamreader.readinteger2 -- 16-bit signed integer @@ -79,6 +80,9 @@ local readfword = readshort local readstring = streamreader.readstring local readtag = streamreader.readtag local readbytes = streamreader.readbytes +local readfixed = streamreader.readfixed4 +local read2dot14 = streamreader.read2dot14 +local readinteger = streamreader.readinteger1 local gsubhandlers = { } local gposhandlers = { } @@ -2434,3 +2438,213 @@ function readers.svg(f,fontdata,specification) fontdata.hascolor = true end end + +-- This next few are work in progress. I have no fonts that have these tables so it's a +-- gamble. I'll pick up this thread some day (if needed at all). See font-tst.tex for a +-- possible test. Something for a rainy day and a stack of fresh cd's. + +function readers.fvar(f,fontdata,specification) + local datatable = fontdata.tables.fvar + if datatable then + local tableoffset = datatable.offset + setposition(f,tableoffset) + local majorversion = readushort(f) -- 1 + local minorversion = readushort(f) -- 0 + if majorversion ~= 1 and minorversion ~= 0 then + report("table version %a.%a of %a is not supported (yet), maybe font %s is bad", + majorversion,minorversion,"fvar",fontdata.filename) + return + end + local offsettoaxis = tableoffset + readushort(f) + local nofsizepairs = readushort(f) -- 2 count/size pairs + -- pair 1 + local nofaxis = readushort(f) + local sizeofaxis = readushort(f) + -- pair 2 + local nofinstances = readushort(f) + local sizeofinstances = readushort(f) + -- + local extras = fontdata.extras + local axis = { } + local instances = { } + -- + setposition(f,offsettoaxis) + -- + local function readtuple(f) + local t = { } + for i=1,nofaxis do + t[i] = readfixed(f) + end + return t + end + -- + for i=1,nofaxis do + axis[i] = { + tag = readtag(f), -- ital opsz slnt wdth wght + minimum = readfixed(f), -- we get weird values from a test font ... to be checked + default = readfixed(f), -- idem + maximum = readfixed(f), -- idem + flags = readushort(f), + nameid = extras[readushort(f)], + } + local n = sizeofaxis - 20 + if n > 0 then + skipbytes(f,n) + elseif n < 0 then + -- error + end + end + -- + for i=1,nofinstances do + local subfamid = readushort(f) + local flags = readushort(f) + local tuple = readtuple(f) + local psnameid = false + local nofbytes = 2 + 2 + #tuple * 2 + if nofbytes < sizeofinstances then + psnameid = readushort(f) + nofbytes = nofbytes + 2 + end + instances[i] = { + subfamily = extras[subfamid], + flags = flags, + tuple = tuple, + psname = extras[psnameid] or nil, + } + if nofbytes > 0 then + skipbytes(f,nofbytes) + end + end + -- + fontdata.variable = { + axis = axis, + instances = instances, + } + end +end + +-- function readers.gvar(f,fontdata,specification) +-- end + +-- function readers.hvar(f,fontdata,specification) +-- end + +-- function readers.vvar(f,fontdata,specification) +-- end + +-- We don't need all these dimensions so we only mention those that make +-- sense. Mapping to some function makes most sense. + +local tags = { + hasc = "", -- horizontal ascender OS/2.sTypoAscender + hdsc = "", -- horizontal descender OS/2.sTypoDescender + -- hlgp = "", -- horizontal line gap OS/2.sTypoLineGap + -- hcla = "", -- horizontal clipping ascent OS/2.usWinAscent + -- hcld = "", -- horizontal clipping descent OS/2.usWinDescent + vasc = "", -- vertical ascender vhea.ascent + vdsc = "", -- vertical descender vhea.descent + vlgp = "", -- vertical line gap vhea.lineGap + xhgt = "", -- x height OS/2.sxHeight + cpht = "", -- cap height OS/2.sCapHeight + -- sbxs = "", -- subscript em x size OS/2.ySubscriptXSize + -- sbys = "", -- subscript em y size OS/2.ySubscriptYSize + -- sbxo = "", -- subscript em x offset OS/2.ySubscriptXOffset + -- sbyo = "", -- subscript em y offset OS/2.ySubscriptYOffset + -- spxs = "", -- superscript em x size OS/2.ySuperscriptXSize + -- spys = "", -- superscript em y size OS/2.ySuperscriptYSize + -- spxo = "", -- superscript em x offset OS/2.ySuperscriptXOffset + -- spyo = "", -- superscript em y offset OS/2.ySuperscriptYOffset + -- strs = "", -- strikeout size OS/2.yStrikeoutSize + -- stro = "", -- strikeout offset OS/2.yStrikeoutPosition + -- unds = "", -- underline size post.underlineThickness + -- undo = "", -- underline offset post.underlinePosition +} + +function readers.mvar(f,fontdata,specification) + local datatable = fontdata.tables.mvar + if datatable then + local tableoffset = datatable.offset + setposition(f,tableoffset) + local majorversion = readushort(f) -- 1 + local minorversion = readushort(f) -- 0 + if majorversion ~= 1 and minorversion ~= 0 then + report("table version %a.%a of %a is not supported (yet), maybe font %s is bad", + majorversion,minorversion,"fvar",fontdata.filename) + return + end + -- + local nofaxis = readushort(f) + local recordsize = readushort(f) + local nofrecords = readushort(f) + local offsettostore = tableoffset + readushort(f) + local records = { } + local dimensions = { } + local store = { } + local regions = { } + -- + for i=1,nofrecords do + local tag = readtag(f) + if tags[tag] then + dimensions[tag] = { + outer = readushort(f), + inner = readushort(f), + } + else + skipshort(f,2) + end + end + -- + setposition(f,offsettostore) + local nofaxis = readushort(f) + local nofregions = readushort(f) + for i=1,nofregions do + local t = { } + for i=1,nofaxis do + t[i] = { + start = read2dot14(f), + peak = read2dot14(f), + stop = read2dot14(f), + } + end + regions[i] = t + end + -- + local format = readushort(f) -- 1 + local offset = offsettostore + readulong(f) + local nofdata = readushort(f) + local data = { } + for i=1,nofdata do + data[i] = readulong(f) + offset + end + for i=1,nofdata do + local offset = data[i] + setposition(f,offset) + local nofdeltas = readushort(f) + local nofshort = readushort(f) + local nofregions = readushort(f) + local deltas = { } + local regions = { } + local length = nofshort + nofregions + for i=1,nofregions do + regions[i] = readushort(f) + end + for i=1,nofdeltas do + local t = { } + for i=1,nofshort do + t[i] = readushort(f) + end + for i=1,nofregions do + t[nofshort+i] = readinteger(f) + end + deltas[i] = t + end + data[i] = { + regions = regions, + deltas = deltas, + } + end + end +end + +-- function readers.vorg(f,fontdata,specification) +-- end diff --git a/tex/context/base/mkiv/font-lib.mkvi b/tex/context/base/mkiv/font-lib.mkvi index ed7d896c5..316e70019 100644 --- a/tex/context/base/mkiv/font-lib.mkvi +++ b/tex/context/base/mkiv/font-lib.mkvi @@ -97,6 +97,7 @@ \registerctxluafile{font-ctx}{1.001} % after def as it overloads \registerctxluafile{font-ext}{1.001} +\registerctxluafile{font-lig}{1.001} % only for experiments so try to avoid it \registerctxluafile{font-fbk}{1.001} \registerctxluafile{font-aux}{1.001} diff --git a/tex/context/base/mkiv/font-lig.lua b/tex/context/base/mkiv/font-lig.lua new file mode 100644 index 000000000..823be9c3b --- /dev/null +++ b/tex/context/base/mkiv/font-lig.lua @@ -0,0 +1,52 @@ +if not modules then modules = { } end modules ['font-lig'] = { + 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 module is not loaded but generated a file for plain TeX as a substitute +-- for collapsing the input: "luatex-fonts-lig.lua" with "collapse=yes". + +local standalone = not characters + +if standalone then + require("char-def") + require("char-utf") + if characters.initialize then + characters.initialize() + end +end + +local data = { } -- if we ever preload this i'll cache it + +for first, seconds in next, characters.graphemes do + for second, combined in next, seconds do + data[combined] = { first, second } + end +end + +-- data['c'] = { 'a', 'b' } +-- data['d'] = { 'c', 'c' } + +local feature = { + name = "collapse", + type = "ligature", + prepend = true, + dataset = { + { data = data }, + { data = data }, + } +} + +if standalone then + local filename = "luatex-fonts-lig.lua" + local filedata = "-- this file is generated by context\n\n" + .. "fonts.handlers.otf.addfeature " + .. table.serialize(feature,false) + logs.report("fonts","pseudo ligature file %a saved",filename) + io.savedata(filename,filedata) +else + fonts.handlers.otf.addfeature(feature) +end diff --git a/tex/context/base/mkiv/font-otc.lua b/tex/context/base/mkiv/font-otc.lua index a55320903..a0dda593d 100644 --- a/tex/context/base/mkiv/font-otc.lua +++ b/tex/context/base/mkiv/font-otc.lua @@ -195,13 +195,15 @@ local function addfeature(data,feature,specifications) local stepkey = coverup.stepkey local register = coverup.register - local function prepare_substitution(list,featuretype) + local function prepare_substitution(list,featuretype,nocheck) 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 not nocheck and not description then + skip = skip + 1 + else if type(replacement) == "table" then replacement = replacement[1] end @@ -212,20 +214,18 @@ local function addfeature(data,feature,specifications) else skip = skip + 1 end - else - skip = skip + 1 end end return coverage end - local function prepare_alternate(list,featuretype) + local function prepare_alternate(list,featuretype,nocheck) 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 + if not nocheck and not description then skip = skip + 1 elseif type(replacement) == "table" then local r = { } @@ -248,13 +248,13 @@ local function addfeature(data,feature,specifications) return coverage end - local function prepare_multiple(list,featuretype) + local function prepare_multiple(list,featuretype,nocheck) 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 + if not nocheck and not description then skip = skip + 1 elseif type(replacement) == "table" then local r, n = { }, 0 @@ -281,16 +281,19 @@ local function addfeature(data,feature,specifications) end end end + inspect(coverage) return coverage end - local function prepare_ligature(list,featuretype) + local function prepare_ligature(list,featuretype,nocheck) 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 not nocheck and not description then + skip = skip + 1 + else if type(ligature) == "string" then ligature = { lpegmatch(splitter,ligature) } end @@ -311,8 +314,6 @@ local function addfeature(data,feature,specifications) else skip = skip + 1 end - else - skip = skip + 1 end end return coverage @@ -552,6 +553,7 @@ local function addfeature(data,feature,specifications) 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 nocheck = specification.nocheck local featureorder = specification.order or { feature } local featurechain = (featuretype == "chainsubstitution" or featuretype == "chainposition") and 1 or 0 local nofsteps = 0 @@ -572,13 +574,13 @@ local function addfeature(data,feature,specifications) local coverage = nil local format = nil if featuretype == "substitution" then - coverage = prepare_substitution(list,featuretype) + coverage = prepare_substitution(list,featuretype,nocheck) elseif featuretype == "ligature" then - coverage = prepare_ligature(list,featuretype) + coverage = prepare_ligature(list,featuretype,nocheck) elseif featuretype == "alternate" then - coverage = prepare_alternate(list,featuretype) + coverage = prepare_alternate(list,featuretype,nocheck) elseif featuretype == "multiple" then - coverage = prepare_multiple(list,featuretype) + coverage = prepare_multiple(list,featuretype,nocheck) elseif featuretype == "kern" then format = "kern" coverage = prepare_kern(list,featuretype) @@ -605,16 +607,16 @@ local function addfeature(data,feature,specifications) local format = nil if featuretype == "substitution" then category = "gsub" - coverage = prepare_substitution(list,featuretype) + coverage = prepare_substitution(list,featuretype,nocheck) elseif featuretype == "ligature" then category = "gsub" - coverage = prepare_ligature(list,featuretype) + coverage = prepare_ligature(list,featuretype,nocheck) elseif featuretype == "alternate" then category = "gsub" - coverage = prepare_alternate(list,featuretype) + coverage = prepare_alternate(list,featuretype,nocheck) elseif featuretype == "multiple" then category = "gsub" - coverage = prepare_multiple(list,featuretype) + coverage = prepare_multiple(list,featuretype,nocheck) elseif featuretype == "kern" then category = "gpos" format = "kern" diff --git a/tex/context/base/mkiv/font-otj.lua b/tex/context/base/mkiv/font-otj.lua index fdee3513f..50330cb83 100644 --- a/tex/context/base/mkiv/font-otj.lua +++ b/tex/context/base/mkiv/font-otj.lua @@ -25,7 +25,7 @@ if not modules then modules = { } end modules ['font-otj'] = { if not nodes.properties then return end -local next, rawget = next, rawget +local next, rawget, tonumber = next, rawget, tonumber local fastcopy = table.fastcopy local registertracker = trackers.register diff --git a/tex/context/base/mkiv/font-otr.lua b/tex/context/base/mkiv/font-otr.lua index a9d3a8b29..c5c5d8f32 100644 --- a/tex/context/base/mkiv/font-otr.lua +++ b/tex/context/base/mkiv/font-otr.lua @@ -65,11 +65,9 @@ if not modules then modules = { } end modules ['font-otr'] = { -- 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 next, type = next, type +local byte, lower, char, gsub = string.byte, string.lower, string.char, string.gsub +local floor, round = math.floor, 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 @@ -120,7 +118,7 @@ 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))) + return lower(stripstring(readstring(f,4))) end -- date represented in number of seconds since 12:00 midnight, January 1, 1904. The value is represented as a @@ -174,6 +172,7 @@ local reservednames = { [0] = "wwssubfamily", "lightbackgroundpalette", "darkbackgroundpalette", + "variationspostscriptnameprefix", } -- more at: https://www.microsoft.com/typography/otspec/name.htm @@ -747,7 +746,8 @@ function readers.name(f,fontdata,specification) local encoding = encodings[encoding] local language = languages[language] if encoding and language then - local name = reservednames[readushort(f)] + local index = readushort(f) + local name = reservednames[index] if name then namelist[#namelist+1] = { platform = platform, @@ -758,7 +758,14 @@ function readers.name(f,fontdata,specification) offset = start + readushort(f), } else - skipshort(f,2) +namelist[#namelist+1] = { + platform = platform, + encoding = encoding, + language = language, + length = readushort(f), + offset = start + readushort(f), +} +-- skipshort(f,2) end else skipshort(f,3) @@ -783,8 +790,9 @@ function readers.name(f,fontdata,specification) -- -- we need to choose one we like, for instance an unicode one -- - local names = { } - local done = { } + local names = { } + local done = { } + local extras = { } -- -- 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 @@ -795,7 +803,7 @@ function readers.name(f,fontdata,specification) for i=1,#namelist do local name = namelist[i] local nametag = name.name - if not done[nametag] then + if not done[nametag or i] then local encoding = name.encoding local language = name.language if (not e or encoding == e) and (not l or language == l) then @@ -808,13 +816,16 @@ function readers.name(f,fontdata,specification) if decoder then content = decoder(content) end - names[nametag] = { - content = content, - platform = platform, - encoding = encoding, - language = language, - } - done[nametag] = true + if nametag then + names[nametag] = { + content = content, + platform = platform, + encoding = encoding, + language = language, + } + end + extras[i-1] = content + done[nametag or i] = true end end end @@ -827,7 +838,8 @@ function readers.name(f,fontdata,specification) filter("macintosh") filter("unicode") -- - fontdata.names = names + fontdata.names = names + fontdata.extras = extras -- if specification.platformnames then local collected = { } @@ -1288,7 +1300,8 @@ local sequence = { local supported = { } for i=1,#sequence do - local sp, se, sf = unpack(sequence[i]) + local si = sequence[i] + local sp, se, sf = si[1], si[2], si[3] local p = supported[sp] if not p then p = { } @@ -1704,7 +1717,8 @@ function readers.cmap(f,fontdata,specification) -- local ok = false for i=1,#sequence do - local sp, se, sf = unpack(sequence[i]) + local si = sequence[i] + local sp, se, sf = si[1], si[2], si[3] if checkcmap(f,fontdata,records,sp,se,sf) > 0 then ok = true end @@ -2000,7 +2014,6 @@ local function readdata(f,offset,specification) end end -- - -- readers["os/2"](f,fontdata,specification) readers["head"](f,fontdata,specification) readers["maxp"](f,fontdata,specification) @@ -2023,6 +2036,12 @@ local function readdata(f,offset,specification) readers["gpos"](f,fontdata,specification) readers["math"](f,fontdata,specification) -- + -- readers["fvar"](f,fontdata,specification) + -- readers["hvar"](f,fontdata,specification) + -- readers["vvar"](f,fontdata,specification) + -- readers["mvar"](f,fontdata,specification) + -- readers["vorg"](f,fontdata,specification) + -- fontdata.locations = nil fontdata.tables = nil fontdata.cidmaps = nil diff --git a/tex/context/base/mkiv/font-ots.lua b/tex/context/base/mkiv/font-ots.lua index 22dd082d1..742a0c561 100644 --- a/tex/context/base/mkiv/font-ots.lua +++ b/tex/context/base/mkiv/font-ots.lua @@ -125,7 +125,6 @@ local fonts = fonts local otf = fonts.handlers.otf local tracers = nodes.tracers -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) @@ -738,7 +737,11 @@ end local function get_alternative_glyph(start,alternatives,value) local n = #alternatives - if value == "random" then + if n == 1 then + -- we could actually change that into a gsub and save some memory in the + -- font loader but it makes tracing more messy + return alternatives[1], trace_alternatives and "1 (only one present)" + elseif 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 @@ -2356,7 +2359,7 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode) size = l - f + 1 if size > 1 then -- before/current/after | before/current | current/after - local discfound = nil + local discfound -- = nil local n = f + 1 -- last = getnext(last) -- the second in current (first already matched) last = startnext -- the second in current (first already matched) @@ -2485,7 +2488,7 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode) -- sweeptype = nil end if prev then - local discfound = nil + local discfound -- = nil local n = f - 1 while n >= 1 do if prev then @@ -2597,7 +2600,7 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode) end -- maybe only if match prev = getprev(prev) - elseif seq[n][32] and id == glue_code and isspace(prev,threshold,id) then + elseif id == glue_code and seq[n][32] and isspace(prev,threshold,id) then n = n - 1 prev = getprev(prev) else @@ -2619,14 +2622,12 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode) -- 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 + if not current and (sweeptype == "post" or sweeptype == "replace") then + current = getnext(sweepnode) + -- sweeptype = nil end if current then - local discfound = nil + local discfound -- = nil -- removed optimization for s-l == 1, we have to deal with marks anyway local n = l + 1 while n <= s do @@ -2731,7 +2732,7 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode) end -- maybe only if match current = getnext(current) - elseif seq[n][32] and id == glue_code and isspace(current,threshold,id) then + elseif id == glue_code and seq[n][32] and isspace(current,threshold,id) then n = n + 1 current = getnext(current) else @@ -2910,6 +2911,14 @@ do -- overcome local limit end +-- Functions like kernrun, comprun etc evolved over time and in the end look rather +-- complex. It's a bit of a compromis between extensive copying and creating subruns. +-- The logic has been improved a lot by Kai and Ivo who use complex fonts which +-- really helped to identify border cases on the one hand and get insight in the diverse +-- ways fonts implement features (not always that consistent and efficient). At the same +-- time I tried to keep the code relatively efficient so that the overhead in runtime +-- stays acceptable. + local function report_disc(what,n) report_run("%s: %s > %s",what,n,languages.serializediscretionary(n)) end @@ -3014,7 +3023,7 @@ local function kernrun(disc,k_run,font,attr,...) return nextstart, done end --- fonts like ebgaramond do ligatuires this way (less efficient than e.g. dejavu which +-- fonts like ebgaramond do ligatures this way (less efficient than e.g. dejavu which -- will do the testrun variant) local function comprun(disc,c_run,...) -- vararg faster than the whole list @@ -3741,6 +3750,14 @@ otf.helpers = otf.helpers or { } otf.helpers.txtdirstate = txtdirstate otf.helpers.pardirstate = pardirstate +-- This is the main loop. We run over the node list dealing with a specific font. The +-- attribute is a context specific thing. 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. Apart from +-- optimizations the principles of processing the features hasn't changed much since +-- the beginning. + local function featuresprocessor(head,font,attr) local sequences = sequencelists[font] -- temp hack @@ -3791,11 +3808,6 @@ local function featuresprocessor(head,font,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 could prepend a temp node. @@ -3906,6 +3918,9 @@ local function featuresprocessor(head,font,attr) elseif char == false then -- whatever glyph start = getnext(start) + elseif id == glue_code then + -- happens often + start = getnext(start) elseif id == disc_code then local ok if gpossing then @@ -3977,6 +3992,10 @@ local function featuresprocessor(head,font,attr) start = getnext(start) end elseif char == false then + -- whatever glyph + start = getnext(start) + elseif id == glue_code then + -- happens often start = getnext(start) elseif id == disc_code then local ok diff --git a/tex/context/base/mkiv/luat-cnf.lua b/tex/context/base/mkiv/luat-cnf.lua index 9d37df7bb..c26b4775b 100644 --- a/tex/context/base/mkiv/luat-cnf.lua +++ b/tex/context/base/mkiv/luat-cnf.lua @@ -70,9 +70,8 @@ function texconfig.init() "epdf", "fontloader", "kpse", "mplib", }, obsolete = { - "fontforge", -- can be filled by luat-log + "fontloader", -- can be filled by luat-log "kpse", - "token", }, functions = { "assert", "pcall", "xpcall", "error", "collectgarbage", diff --git a/tex/context/base/mkiv/node-fin.lua b/tex/context/base/mkiv/node-fin.lua index 03c8a7607..ffb2ae49e 100644 --- a/tex/context/base/mkiv/node-fin.lua +++ b/tex/context/base/mkiv/node-fin.lua @@ -327,7 +327,7 @@ local function selective(namespace,attribute,head,inheritance,default) -- two at if id == glyph_code then check = true elseif id == disc_code then - check = true -- notneeded when we flatten replace + check = true -- not needed when we flatten replace elseif id == glue_code then leader = getleader(stack) if leader then diff --git a/tex/context/base/mkiv/publ-imp-apa.lua b/tex/context/base/mkiv/publ-imp-apa.lua index f2e7f11e1..ec46b7f7e 100644 --- a/tex/context/base/mkiv/publ-imp-apa.lua +++ b/tex/context/base/mkiv/publ-imp-apa.lua @@ -191,7 +191,7 @@ categories.inbook = { optional = { "withauthor", "translator", "subtitle", "type", "file", - "booktitle", + "booktitle", "subbooktitle", -- APA ignores this: "chapter", "editionset", "series", "month", @@ -217,6 +217,7 @@ categories.incollection = { optional = { "withauthor", "translator", "subtitle", "type", "file", + "subbooktitle", "editionset", "series", -- APA ignores this: "chapter", "month", diff --git a/tex/context/base/mkiv/publ-imp-apa.mkvi b/tex/context/base/mkiv/publ-imp-apa.mkvi index 6470bb089..77fcb8995 100644 --- a/tex/context/base/mkiv/publ-imp-apa.mkvi +++ b/tex/context/base/mkiv/publ-imp-apa.mkvi @@ -88,6 +88,14 @@ [\c!authorconversion=normalshort] \definebtx + [apa:\s!list:director] + [apa:\s!list:author] + +\definebtx + [apa:\s!list:producer] + [apa:\s!list:author] + +\definebtx [apa:\s!list:suffix] [apa:\s!list] diff --git a/tex/context/base/mkiv/publ-ini.lua b/tex/context/base/mkiv/publ-ini.lua index 86dc6cea2..52642c89d 100644 --- a/tex/context/base/mkiv/publ-ini.lua +++ b/tex/context/base/mkiv/publ-ini.lua @@ -1984,6 +1984,33 @@ do arguments = { "string", "string" } } + local function identical(a,b) + local na, nb = #a, #b + if na ~= nb then + return false + end + if na > 0 then + for i=1,na do + if not identical(a[i],b[i]) then + return false + end + end + return true + end + local ha, hb = a.hash, b.hash + if ha then + return ha == hb + end + for k, v in next, a do + if k == "original" or k == "snippets" then + -- skip diagnostic info + elseif v ~= b[k] then + return false + end + end + return true + end + function lists.sameasprevious(dataset,i,name,order,method) local rendering = renderings[dataset] local list = rendering.list @@ -2030,7 +2057,7 @@ do if c_casted and c_casted == p_casted then sameentry = true elseif type(c_casted) == "table" and type(p_casted) == "table" then - sameentry = table.identical(c_casted,p_casted) + sameentry = identical(c_casted,p_casted) end end if trace_detail then diff --git a/tex/context/base/mkiv/status-files.pdf b/tex/context/base/mkiv/status-files.pdf Binary files differindex 1441c0e6c..6d7f14ae0 100644 --- a/tex/context/base/mkiv/status-files.pdf +++ b/tex/context/base/mkiv/status-files.pdf diff --git a/tex/context/base/mkiv/status-lua.pdf b/tex/context/base/mkiv/status-lua.pdf Binary files differindex cc2383ec2..189773237 100644 --- a/tex/context/base/mkiv/status-lua.pdf +++ b/tex/context/base/mkiv/status-lua.pdf diff --git a/tex/context/base/mkiv/trac-deb.lua b/tex/context/base/mkiv/trac-deb.lua index 782be154f..d1168a3a9 100644 --- a/tex/context/base/mkiv/trac-deb.lua +++ b/tex/context/base/mkiv/trac-deb.lua @@ -372,3 +372,15 @@ implement { name = "disableexperiments", actions = experiments.disable, argument implement { name = "showdebuginfo", actions = lmx.showdebuginfo } implement { name = "overloaderror", actions = lmx.overloaderror } implement { name = "showlogcategories", actions = logs.show } + +directives.register("system.profile",function() + luatex.registerstopactions(function() + debugger.disable() + debugger.savestats("luatex-profile.log") + report_nl() + logs.report("system","profiler stopped, log saved in %a","luatex-profile.log") + report_nl() + end) + logs.report("system","profiler started") + debugger.enable() +end) diff --git a/tex/context/base/mkiv/util-deb.lua b/tex/context/base/mkiv/util-deb.lua index ee732b3b5..040a7a9cf 100644 --- a/tex/context/base/mkiv/util-deb.lua +++ b/tex/context/base/mkiv/util-deb.lua @@ -12,87 +12,236 @@ if not modules then modules = { } end modules ['util-deb'] = { local debug = require "debug" -local getinfo = debug.getinfo +local getinfo, sethook = debug.getinfo, debug.sethook local type, next, tostring = type, next, tostring -local format, find = string.format, string.find -local is_boolean = string.is_boolean +local format, find, sub, gsub = string.format, string.find, string.sub, string.gsub +local insert, remove, sort = table.insert, table.remove, table.sort utilities = utilities or { } local debugger = utilities.debugger or { } utilities.debugger = debugger -local counters = { } +local report = logs.reporter("debugger") + +local ticks = os.gettimeofday or os.clock +local seconds = function(n) return n or 0 end +local overhead = 0 +local dummycalls = 10*1000 +local nesting = 0 local names = { } -local report = logs.reporter("debugger") +local function initialize() --- one + if FFISUPPORTED and ffi then -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) + if os.type == "windows" then + local okay, kernel = pcall(ffi.load,"kernel32") + if kernel then + local tonumber = ffi.number or tonumber +ffi.cdef[[ +int QueryPerformanceFrequency(int64_t *lpFrequency); +int QueryPerformanceCounter(int64_t *lpPerformanceCount); +]] + local target = ffi.new("__int64[1]") + ticks = function() + if kernel.QueryPerformanceCounter(target) == 1 then + return tonumber(target[0]) + else + return 0 + end + end + local target = ffi.new("__int64[1]") + seconds = function(ticks) + if kernel.QueryPerformanceFrequency(target) == 1 then + return ticks / tonumber(target[0]) + else + return 0 + end + end 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 = "?" + elseif os.type == "unix" then + local C = ffi.C + local tonumber = ffi.number or tonumber + -- 1 = CLOCK_MONOTONIC + -- 2 = CLOCK_PROCESS_CPUTIME_ID +ffi.cdef [[ +struct timespec { long sec; long nsec; }; +int clock_gettime(int timerid, struct timespec *t); + ]] + local target = ffi.new("timespec[?]",1) + function ticks() + C.clock_gettime(2,target) + return tonumber(target[0].sec*1000000000 + target[0].nsec) end - if not names[n] then - names[n] = format("%42s : % 5i : %s",n,f.linedefined or 0,f.short_src or "unknown source") + seconds = function(ticks) + return ticks/1000000000 end + end - counters[n] = (counters[n] or 0) + 1 end + + initialize = false + 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 } +table.setmetatableindex(names,function(t,name) + local v = table.setmetatableindex(function(t,source) + local v = table.setmetatableindex(function(t,line) + local v = { total = 0, count = 0 } + t[line] = v + return v + end) + t[source] = v + return v + end) + t[name] = v + return v +end) + +local function hook(where) + local f = getinfo(2,"nSl") + if f then + local source = f.short_src + if not source then + return + end + local line = f.linedefined or 0 + local name = f.name + if not name then + local what = f.what + if what == "C" then + name = "<anonymous>" + else + name = f.namewhat or what or "<unknown>" + end + end + local data = names[name][source][line] + if where == "call" then + data.count = data.count + 1 + insert(data,ticks()) + elseif where == "return" then + local t = remove(data) + if t then + data.total = data.total + ticks() - t + end + end 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 + +function debugger.showstats(printer) + local printer = printer or report + local calls = 0 + local functions = 0 + local dataset = { } + local length = 0 + local wholetime = 0 + for name, sources in next, names do + for source, lines in next, sources do + for line, data in next, lines do + if #name > length then + length = #name + end + local total = data.total + local count = data.count + local real = total + if real > 0 then + real = total - (count * overhead / dummycalls) + if real < 0 then + real = 0 + end + wholetime = wholetime + real + end + if line < 0 then + line = 0 + end + dataset[#dataset+1] = { real, total, count, name, source, line } + end + end + end + sort(dataset,function(a,b) + if a[1] == b[1] then + if a[2] == b[2] then + if a[3] == b[3] then + if a[4] == b[4] then + if a[5] == b[5] then + return a[6] < b[6] + else + return a[5] < b[5] + end + else + return a[4] < b[4] + end + else + return b[3] < a[3] + end + else + return b[2] < a[2] + end + else + return b[1] < a[1] end - grandtotal = grandtotal + count + end) + if length > 50 then + length = 50 + end + local fmt = string.formatters["%4.9k %4.9k %3.3k %8i %-" .. length .. "s %4i %s"] + for i=1,#dataset do + local data = dataset[i] + local real = data[1] + local total = data[2] + local count = data[3] + local name = data[4] + local source = data[5] + local line = data[6] + local percent = real / wholetime + calls = calls + count functions = functions + 1 + name = gsub(name,"%s+"," ") + if #name > length then + name = sub(name,1,length) + end + printer(fmt(seconds(total),seconds(real),percent,count,name,line,source)) 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)) + printer("") + printer(format("functions : %i", functions)) + printer(format("calls : %i", calls)) + printer(format("overhead : %f", seconds(overhead/1000))) end -function debugger.savestats(filename,threshold) +function debugger.savestats(filename) local f = io.open(filename,'w') if f then - debugger.showstats(function(str) f:write(str) end,threshold) + debugger.showstats(function(str) f:write(str,"\n") end) f:close() end end function debugger.enable() - debug.sethook(hook,"c") + if nesting == 0 then + running = true + if initialize then + initialize() + end + sethook(hook,"cr") + local function dummy() end + local t = ticks() + for i=1,dummycalls do + dummy() + end + overhead = ticks() - t + end + if nesting > 0 then + nesting = nesting + 1 + end end function debugger.disable() - debug.sethook() - -- counters[debug.getinfo(2,"f").func] = nil + if nesting > 0 then + nesting = nesting - 1 + end + if nesting == 0 then + sethook() + end end -- debugger.enable() diff --git a/tex/context/base/mkiv/util-env.lua b/tex/context/base/mkiv/util-env.lua index fb3dda41f..0b832e72e 100644 --- a/tex/context/base/mkiv/util-env.lua +++ b/tex/context/base/mkiv/util-env.lua @@ -31,15 +31,23 @@ end -- setlocale(nil,nil) -- end -- --- function os.pushlocale(...) +-- function os.pushlocale(l,...) -- insert(stack, { --- collate = setlocale("collate"), --- ctype = setlocale("ctype"), --- monetary = setlocale("monetary"), --- numeric = setlocale("numeric"), --- time = setlocale("time"), +-- collate = setlocale(nil,"collate"), +-- ctype = setlocale(nil,"ctype"), +-- monetary = setlocale(nil,"monetary"), +-- numeric = setlocale(nil,"numeric"), +-- time = setlocale(nil,"time"), -- }) --- setlocale(...) +-- if l then +-- setlocale(l,...) +-- else +-- setlocale(status.lc_collate ,"collate"), +-- setlocale(status.lc_ctype ,"ctype"), +-- setlocale(status.lc_monetary,"monetary"), +-- setlocale(status.lc_numeric ,"numeric"), +-- setlocale(status.lc_time ,"time"), +-- end -- end -- -- function os.poplocale(...) @@ -51,6 +59,12 @@ end -- end -- end -- +-- function os.setlocale() +-- -- no way you can mess with it, use push/pop +-- end +-- +-- setlocale(nil,nil) -- setlocale("all","C") +-- -- end -- dirty tricks (we will replace the texlua call by luatex --luaonly) diff --git a/tex/context/base/mkiv/util-fil.lua b/tex/context/base/mkiv/util-fil.lua index cf97d9541..dba3b235c 100644 --- a/tex/context/base/mkiv/util-fil.lua +++ b/tex/context/base/mkiv/util-fil.lua @@ -101,9 +101,10 @@ function files.readinteger1(f) -- one byte end end -files.readcardinal1 = files.readbyte -- one byte -files.readcardinal = files.readcardinal1 -files.readinteger = files.readinteger1 +files.readcardinal1 = files.readbyte -- one byte +files.readcardinal = files.readcardinal1 +files.readinteger = files.readinteger1 +files.readsignedbyte = files.readinteger1 function files.readcardinal2(f) local a, b = byte(f:read(2),1,2) diff --git a/tex/context/base/mkiv/util-lib.lua b/tex/context/base/mkiv/util-lib.lua index 2601b2e57..e9a968228 100644 --- a/tex/context/base/mkiv/util-lib.lua +++ b/tex/context/base/mkiv/util-lib.lua @@ -6,9 +6,6 @@ if not modules then modules = { } end modules ['util-lib'] = { license = "see context related readme files", } --- This is experimental code for Hans and Luigi. Don't depend on it! There --- will be a plain variant. - --[[ The problem with library bindings is manyfold. They are of course platform @@ -73,29 +70,41 @@ and then without. ]]-- --- seems to be clua in recent texlive - -local gsub, find = string.gsub, string.find -local pathpart, nameonly, joinfile = file.pathpart, file.nameonly, file.join -local findfile, findfiles = resolvers and resolvers.findfile, resolvers and resolvers.findfiles - -local loaded = package.loaded +local type = type +local next = next +local pcall = pcall +local gsub = string.gsub +local find = string.find +local sort = table.sort +local pathpart = file.pathpart +local nameonly = file.nameonly +local joinfile = file.join +local removesuffix = file.removesuffix +local findfile = resolvers.findfile +local findfiles = resolvers.findfiles +local expandpaths = resolvers.expandedpathlistfromvariable +local qualifiedpath = file.is_qualified_path +local isfile = lfs.isfile -local report_swiglib = logs.reporter("swiglib") -local trace_swiglib = false trackers.register("resolvers.swiglib", function(v) trace_swiglib = v end) +local done = false -- We can check if there are more that one component, and if not, we can -- append 'core'. -local done = false - -local function requireswiglib(required,version) - local trace_swiglib = trace_swiglib or package.helpers.trace - local library = loaded[required] - if library == nil then - if trace_swiglib then - report_swiglib("requiring library %a with version %a",required,version or "any") +local function locate(required,version,trace,report,action) + if type(required) ~= "string" then + report("provide a proper library name") + return + end + if trace then + report("requiring library %a with version %a",required,version or "any") + end + local found_library = nil + if qualifiedpath(required) then + if isfile(required) then + found_library = required end + else -- initialize a few variables local required_full = gsub(required,"%.","/") -- package.helpers.lualibfile local required_path = pathpart(required_full) @@ -104,16 +113,16 @@ local function requireswiglib(required,version) local version = type(version) == "string" and version ~= "" and version or false local engine = environment.ownmain or false -- - if trace_swiglib and not done then - local list = resolvers.expandedpathlistfromvariable("lib") -- fresh, no reuse + if trace and not done then + local list = expandpaths("lib") -- fresh, no reuse for i=1,#list do - report_swiglib("tds path %i: %s",i,list[i]) + report("tds path %i: %s",i,list[i]) end end -- helpers local function found(locate,asked_library,how,...) - if trace_swiglib then - report_swiglib("checking %s: %a",how,asked_library) + if trace then + report("checking %s: %a",how,asked_library) end return locate(asked_library,...) end @@ -121,15 +130,15 @@ local function requireswiglib(required,version) local found = nil if version then local asked_library = joinfile(required_path,version,required_name) - if trace_swiglib then - report_swiglib("checking %s: %a","with version",asked_library) + if trace then + report("checking %s: %a","with version",asked_library) end found = locate(asked_library,...) end if not found or found == "" then local asked_library = joinfile(required_path,required_name) - if trace_swiglib then - report_swiglib("checking %s: %a","with version",asked_library) + if trace then + report("checking %s: %a","with version",asked_library) end found = locate(asked_library,...) end @@ -140,32 +149,32 @@ local function requireswiglib(required,version) -- match anyway. local function attempt(checkpattern) -- check cnf spec using name and version - if trace_swiglib then - report_swiglib("checking tds lib paths strictly") + if trace then + report("checking tds lib paths strictly") end local found = findfile and check(findfile,"lib") if found and (not checkpattern or find(found,checkpattern)) then return found end -- check cnf spec using wildcard - if trace_swiglib then - report_swiglib("checking tds lib paths with wildcard") + if trace then + report("checking tds lib paths with wildcard") end local asked_library = joinfile(required_path,".*",required_name) - if trace_swiglib then - report_swiglib("checking %s: %a","latest version",asked_library) + if trace then + report("checking %s: %a","latest version",asked_library) end local list = findfiles(asked_library,"lib",true) if list and #list > 0 then - table.sort(list) + sort(list) local found = list[#list] if found and (not checkpattern or find(found,checkpattern)) then return found end end -- Check lib paths using name and version. - if trace_swiglib then - report_swiglib("checking lib paths") + if trace then + report("checking lib paths") end package.extralibpath(environment.ownpath) local paths = package.libpaths() @@ -177,59 +186,80 @@ local function requireswiglib(required,version) end return false end - local found_library = nil if engine then - if trace_swiglib then - report_swiglib("attemp 1, engine %a",engine) + if trace then + report("attemp 1, engine %a",engine) end found_library = attempt("/"..engine.."/") if not found_library then - if trace_swiglib then - report_swiglib("attemp 2, no engine",asked_library) + if trace then + report("attemp 2, no engine",asked_library) end found_library = attempt() end else found_library = attempt() end - -- load and initialize when found - if not found_library then - if trace_swiglib then - report_swiglib("not found: %a",required) - end - library = false - else - local path = pathpart(found_library) - local base = nameonly(found_library) - dir.push(path) - if trace_swiglib then - report_swiglib("found: %a",found_library) - end - local message = nil - local opener = "luaopen_" .. required_base - library, message = package.loadlib(found_library,opener) - local libtype = type(library) - if libtype == "function" then - library = library() - else - report_swiglib("load error: %a returns %a, message %a, library %a",opener,libtype,(string.gsub(message or "no message","[%s]+$","")),found_library or "no library") - library = false - end - dir.pop() - end - -- cache result - if not library then - report_swiglib("unknown: %a",required) - elseif trace_swiglib then - report_swiglib("stored: %a",required) + end + -- load and initialize when found + if not found_library then + if trace then + report("not found: %a",required) end - loaded[required] = library + library = false else - report_swiglib("reused: %a",required) + if trace then + report("found: %a",found_library) + end + local message, result = action(found_library,required_base) + if result then + library = result + else + library = false + report("load error: message %a, library %a",tostring(message),found_library or "no library") + end + end + if not library then + report("unknown: %a",required) + elseif trace then + report("stored: %a",required) end return library end +do + + local report_swiglib = logs.reporter("swiglib") + local trace_swiglib = false + local savedrequire = require + local loadedlibs = { } + + trackers.register("resolvers.swiglib", function(v) trace_swiglib = v end) + + function requireswiglib(required,version) + local library = loadedlibs[library] + if library == nil then + local trace_swiglib = trace_swiglib or package.helpers.trace + library = locate(required,version,trace_swiglib,report_swiglib,function(name,base) + dir.push(pathpart(name)) + local opener = "luaopen_" .. base + local library, message = package.loadlib(name,opener) + local libtype = type(library) + if libtype == "function" then + library = library() + message = true + else + report_swiglib("load error: %a returns %a, message %a, library %a",opener,libtype,(string.gsub(message or "no message","[%s]+$","")),found_library or "no library") + library = false + end + dir.pop() + return message, library + end) + loadedlibs[required] = library or false + end + return library + end + --[[ For convenience we make the require loader function swiglib aware. Alternatively @@ -237,15 +267,13 @@ we could put the specific loader in the global namespace. ]]-- -local savedrequire = require - -function require(name,version) - if find(name,"^swiglib%.") then - return requireswiglib(name,version) - else - return savedrequire(name) + function require(name,version) + if find(name,"^swiglib%.") then + return requireswiglib(name,version) + else + return savedrequire(name) + end end -end --[[ @@ -255,43 +283,87 @@ recommended loader. ]]-- -local swiglibs = { } -local initializer = "core" + local swiglibs = { } + local initializer = "core" -function swiglib(name,version) - local library = swiglibs[name] - if not library then - statistics.starttiming(swiglibs) - if trace_swiglib then - report_swiglib("loading %a",name) - end - if not find(name,"%." .. initializer .. "$") then - fullname = "swiglib." .. name .. "." .. initializer - else - fullname = "swiglib." .. name + function swiglib(name,version) + local library = swiglibs[name] + if not library then + statistics.starttiming(swiglibs) + if trace_swiglib then + report_swiglib("loading %a",name) + end + if not find(name,"%." .. initializer .. "$") then + fullname = "swiglib." .. name .. "." .. initializer + else + fullname = "swiglib." .. name + end + library = requireswiglib(fullname,version) + swiglibs[name] = library + statistics.stoptiming(swiglibs) end - library = requireswiglib(fullname,version) - swiglibs[name] = library - statistics.stoptiming(swiglibs) + return library end - return library + + statistics.register("used swiglibs", function() + if next(swiglibs) then + return string.format("%s, initial load time %s seconds",table.concat(table.sortedkeys(swiglibs)," "),statistics.elapsedtime(swiglibs)) + end + end) + end -statistics.register("used swiglibs", function() - if next(swiglibs) then - return string.format("%s, initial load time %s seconds",table.concat(table.sortedkeys(swiglibs)," "),statistics.elapsedtime(swiglibs)) +if FFISUPPORTED and ffi and ffi.load then + +--[[ + +We use the same lookup logic for ffi loading. + +]]-- + + local report_ffilib = logs.reporter("ffilib") + local trace_ffilib = false + local savedffiload = ffi.load + + trackers.register("resolvers.ffilib", function(v) trace_ffilib = v end) + + function ffilib(required,version) + return locate(required,version,trace_ffilib,report_ffilib,function(name) + local message, library = pcall(savedffiload,removesuffix(name)) + if type(library) == "userdata" then + return message, library + else + return message, false + end + end) end -end) + + function ffi.load(name) + local library = ffilib(name) + if type(library) == "userdata" then + return library + else + report_ffilib("trying to load %a using normal loader",name) + return savedffiload(name) + end + end + +end --[[ -So, we now have: +-- So, we now have: + +trackers.enable("resolvers.ffilib") +trackers.enable("resolvers.swiglib") local gm = require("swiglib.gmwand.core") local gm = swiglib("gmwand.core") local sq = swiglib("mysql.core") local sq = swiglib("mysql.core","5.6") -Watch out, the last one is less explicit and lacks the swiglib prefix. +ffilib("libmysql","5.6.14") + +-- Watch out, the last one is less explicit and lacks the swiglib prefix. ]]-- diff --git a/tex/context/base/mkiv/util-str.lua b/tex/context/base/mkiv/util-str.lua index fb510257a..9e6be9999 100644 --- a/tex/context/base/mkiv/util-str.lua +++ b/tex/context/base/mkiv/util-str.lua @@ -449,6 +449,31 @@ function number.sparseexponent(f,n) return tostring(n) end +local hf = { } +local hs = { } + +setmetatable(hf, { __index = function(t,k) + local v = "%." .. k .. "f" + t[k] = v + return v +end } ) + +setmetatable(hs, { __index = function(t,k) + local v = "%" .. k .. "s" + t[k] = v + return v +end } ) + +function number.formattedfloat(n,b,a) + local s = format(hf[a],n) + local l = (b or 0) + (a or 0) + 1 + if #s < l then + return format(hs[l],s) + else + return s + end +end + local template = [[ %s %s @@ -479,6 +504,7 @@ local autodouble=string.autodouble local sequenced=table.sequenced local formattednumber=number.formatted local sparseexponent=number.sparseexponent +local formattedfloat=number.formattedfloat ]] else @@ -504,6 +530,7 @@ else sequenced = table.sequenced, formattednumber = number.formatted, sparseexponent = number.sparseexponent, + formattedfloat = number.formattedfloat } end @@ -521,6 +548,9 @@ setmetatable(arguments, { __index = }) local prefix_any = C((S("+- .") + R("09"))^0) +local prefix_sub = (C((S("+-") + R("09"))^0) + Cc(0)) + * P(".") + * (C((S("+-") + R("09"))^0) + Cc(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) @@ -594,6 +624,11 @@ local format_F = function(f) -- beware, no cast to number end end +local format_k = function(b,a) -- slow + n = n + 1 + return format("formattedfloat(a%s,%i,%i)",n,b or 0, a or 0) +end + local format_g = function(f) n = n + 1 return format("format('%%%sg',a%s)",f,n) @@ -855,6 +890,7 @@ local builder = Cs { "start", + V("S") -- new + V("Q") -- new + V("N") -- new + + V("k") -- new -- + V("r") + V("h") + V("H") + V("u") + V("U") @@ -894,6 +930,7 @@ local builder = Cs { "start", ["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) + ["k"] = (prefix_sub * P("k")) / format_k, -- %k => like f but with n.m ["c"] = (prefix_any * P("c")) / format_c, -- %c => utf character (extension to regular) ["C"] = (prefix_any * P("C")) / format_C, -- %c => U+.... utf character -- diff --git a/tex/context/interface/mkiv/i-context.pdf b/tex/context/interface/mkiv/i-context.pdf Binary files differindex 56f1b02a0..a62e63912 100644 --- a/tex/context/interface/mkiv/i-context.pdf +++ b/tex/context/interface/mkiv/i-context.pdf diff --git a/tex/context/interface/mkiv/i-readme.pdf b/tex/context/interface/mkiv/i-readme.pdf Binary files differindex 09945eaec..e1648bc33 100644 --- a/tex/context/interface/mkiv/i-readme.pdf +++ b/tex/context/interface/mkiv/i-readme.pdf diff --git a/tex/context/modules/mkiv/m-matrix.mkiv b/tex/context/modules/mkiv/m-matrix.mkiv index b72453bdd..f59363e94 100644 --- a/tex/context/modules/mkiv/m-matrix.mkiv +++ b/tex/context/modules/mkiv/m-matrix.mkiv @@ -28,6 +28,7 @@ local formatters = string.formatters local copy = table.copy local insert = table.insert local remove = table.remove +local random = math.random local context = context @@ -92,8 +93,8 @@ function matrix.typeset(m,options) if options.fences then whatever = fences[options.fences] or whatever elseif options.determinant then - whatever = fences.brackets - -- whatever = fences.bars + -- whatever = fences.brackets + whatever = fences.bars end local template = options.template or matrix.template if template == "yes" then @@ -125,10 +126,64 @@ end -- interchange two rows (i-th, j-th) -function matrix.swap(t,i,j) - t[i], t[j] = t[j], t[i] +-- function matrix.swaprows(t,i,j) +-- if i <= #t and j <= #t then +-- t[i], t[j] = t[j], t[i] +-- return t +-- else +-- return "error: out of bound" +-- end +-- end + +function matrix.swaprows(t,i,j) + local ti = t[i] + if not ti then + return "error: no row i" + end + local tj = t[j] + if not tj then + return "error: no row j" + end + t[i], t[j] = tj, ti + return t +end + +-- interchange two columns (i-th, j-th) + +-- function matrix.swapcolumns(t, i, j) +-- if i <= #t[1] and j <= #t[1] then +-- for k = 1, #t do +-- t[k][i], t[k][j] = t[k][j], t[k][i] +-- end +-- return t +-- else +-- return "error: out of bound" +-- end +-- end + +function matrix.swapcolumns(t, i, j) + local t1 = t[1] + if not t1 then + return "error: no rows" + end + local n = #t1 + if i <= n then + return "error: no row i" + end + if j <= n then + return "error: no row j" + end + for k = 1, #t do + local tk = t[k] + tk[i], tk[j] = tk[j], tk[i] + end + return t end +matrix.swapC = matrix.swapcolumns +matrix.swapR = matrix.swaprows +matrix.swap = matrix.swaprows + -- replace i-th row with factor * (i-th row) function matrix.multiply(m,i,factor) @@ -251,7 +306,7 @@ end matrix.uppertri = uppertri -function matrix.determinant(m) +local function determinant(m) if #m == #m[1] then local d = 1 local t, s = uppertri(m,1) @@ -264,6 +319,8 @@ function matrix.determinant(m) end end +matrix.determinant = determinant + local function rowechelon(m,r) local temp = copy(m) local pRow = 1 @@ -328,6 +385,99 @@ end matrix.rowechelon = rowechelon matrix.rowEchelon = rowechelon +-- make matrices until its determinant is not 0 + +function matrix.make(n,m,low,high) + if not n then + n = 10 + end + if not m then + m = 10 + end + if not low then + low = 0 + end + if not high then + high = 100 + end + local t = { } -- make an empty n1 x n2 array + local again = true + for i=1,n do + t[i] = { } + end + while true do + for i=1,n do + local ti = t[i] + for j=1,m do + ti[j] = random(low,high) + end + end + if n ~= m or determinant(t,1) ~= 0 then + return t + end + end +end + +-- extract submatrix by using + +local function submatrix(t,i,j) + local rows = #t + local columns = #t[1] + local sign = 1 -- not used + if i <= rows and j <= columns then + local c = copy(t) + remove(c,i) + for k=1,rows-1 do + remove(c[k],j) + end + return c + else + return "error: out of bound" + end +end + +matrix.submatrix = submatrix + +-- calculating determinant using Laplace Expansion + +function matrix.laplace(t) -- not sure if this is the most effient but + local factors = { 1 } -- it's not used for number crunching anyway + local data = copy(t) + local det = 0 + while #data > 0 do + local mat = { } + local siz = #data[1] + if siz == 0 then + return "error: no determinant" + elseif siz == 1 then + det = data[1][1] + return det + end + for i=1,siz do + mat[i] = data[1] + remove(data,1) + end + local factor = remove(factors,1) + local m1 = mat[1] + if siz == 2 then + local m2 = mat[2] + det = det + factor * (m1[1]*m2[2] - m1[2]*m2[1]) + else + for j=1,#m1 do + local m1j = m1[j] + if m1j ~= 0 then + insert(factors, (-1)^(j+1) * factor * m1j) + local m = submatrix(mat,1,j) + for k, v in next, m do + insert(data,v) + end + end + end + end + end + return det +end + -- solve the linear equation m X = c local function solve(m,c) diff --git a/tex/context/modules/mkiv/s-inf-03.mkiv b/tex/context/modules/mkiv/s-inf-03.mkiv index 31333b8e5..d2acb7341 100644 --- a/tex/context/modules/mkiv/s-inf-03.mkiv +++ b/tex/context/modules/mkiv/s-inf-03.mkiv @@ -158,13 +158,11 @@ local upper = string.upper local skipglobal = table.tohash { "_G", "_M", "_ENV", "", "context", "modules", "global", "arg", "utf", 1, - "_ptbs_", "_pcol_", "_plib_", "_clib_", "_tlib_", "kpse", "commands", "ffi", } local skipkeys = table.tohash { - "_pcol_", "_plib_", "_clib_", "_tlib_", "_bpnf_", "_ptbs_", - "_cldf_", "_cldn_", "_cldo_", + -- "_cldf_", "_cldn_", "_cldo_", "_clmb_", "_clme_", "_clmm_", "_clmn_", "_clma_", "_clmh_", "_G", "_M", "_ENV", "", -- "global", "shortcuts", @@ -215,11 +213,10 @@ local function childtables(key,tab,handler,depth) if marked(v) then t = "data" handler(s,t,depth) + elseif done[v] then + -- logs.report("inf-03","key %a in %a already done",k,v) else -if done[v] then - -- logs.report("inf-03","key %a in %a already done",k,v) -else - done[v] = true + done[v] = true handler(s,t,depth) if variant == 3 then childtables(false,v,handler,depth+1) @@ -229,7 +226,6 @@ else childtables(s,v,handler,depth+1) end end -end else handler(s,t,depth) end @@ -252,7 +248,7 @@ end local function show(title,subtitle,alias,builtin,t,lib,libcolor,glo,glocolor,mark,obsolete) -- todo: table as argument --- print(title,subtitle,alias,builtin,t,lib,libcolor,glo,glocolor,mark,obsolete) + -- print(title,subtitle,alias,builtin,t,lib,libcolor,glo,glocolor,mark,obsolete) local keys = sortedkeys(t) -- no sorted_pairs if #keys > 0 then local fulltitle = title @@ -269,7 +265,7 @@ local function show(title,subtitle,alias,builtin,t,lib,libcolor,glo,glocolor,mar end context.startcolumns { n = 2 } context.starttabulate { "|||" } - local t_obsolete = t.obsolete + local t_obsolete = rawget(t,"obsolete") -- tricky a t.obsolete fails if type(t_obsolete) ~= "table" then t_obsolete = nil end diff --git a/tex/generic/context/luatex/luatex-fonts-lig.lua b/tex/generic/context/luatex/luatex-fonts-lig.lua new file mode 100644 index 000000000..c5347aa19 --- /dev/null +++ b/tex/generic/context/luatex/luatex-fonts-lig.lua @@ -0,0 +1,2067 @@ +-- this file is generated by context + +fonts.handlers.otf.addfeature { + ["dataset"]={ + { + ["data"]={ + ["À"]={ "A", "̀" }, + ["Á"]={ "A", "́" }, + ["Â"]={ "A", "̂" }, + ["Ã"]={ "A", "̃" }, + ["Ä"]={ "A", "̈" }, + ["Å"]={ "A", "̊" }, + ["Ç"]={ "C", "̧" }, + ["È"]={ "E", "̀" }, + ["É"]={ "E", "́" }, + ["Ê"]={ "E", "̂" }, + ["Ë"]={ "E", "̈" }, + ["Ì"]={ "I", "̀" }, + ["Í"]={ "I", "́" }, + ["Î"]={ "I", "̂" }, + ["Ï"]={ "I", "̈" }, + ["Ñ"]={ "N", "̃" }, + ["Ò"]={ "O", "̀" }, + ["Ó"]={ "O", "́" }, + ["Ô"]={ "O", "̂" }, + ["Õ"]={ "O", "̃" }, + ["Ö"]={ "O", "̈" }, + ["Ù"]={ "U", "̀" }, + ["Ú"]={ "U", "́" }, + ["Û"]={ "U", "̂" }, + ["Ü"]={ "U", "̈" }, + ["Ý"]={ "Y", "́" }, + ["à"]={ "a", "̀" }, + ["á"]={ "a", "́" }, + ["â"]={ "a", "̂" }, + ["ã"]={ "a", "̃" }, + ["ä"]={ "a", "̈" }, + ["å"]={ "a", "̊" }, + ["ç"]={ "c", "̧" }, + ["è"]={ "e", "̀" }, + ["é"]={ "e", "́" }, + ["ê"]={ "e", "̂" }, + ["ë"]={ "e", "̈" }, + ["ì"]={ "i", "̀" }, + ["í"]={ "i", "́" }, + ["î"]={ "i", "̂" }, + ["ï"]={ "i", "̈" }, + ["ñ"]={ "n", "̃" }, + ["ò"]={ "o", "̀" }, + ["ó"]={ "o", "́" }, + ["ô"]={ "o", "̂" }, + ["õ"]={ "o", "̃" }, + ["ö"]={ "o", "̈" }, + ["ù"]={ "u", "̀" }, + ["ú"]={ "u", "́" }, + ["û"]={ "u", "̂" }, + ["ü"]={ "u", "̈" }, + ["ý"]={ "y", "́" }, + ["ÿ"]={ "y", "̈" }, + ["Ā"]={ "A", "̄" }, + ["ā"]={ "a", "̄" }, + ["Ă"]={ "A", "̆" }, + ["ă"]={ "a", "̆" }, + ["Ą"]={ "A", "̨" }, + ["ą"]={ "a", "̨" }, + ["Ć"]={ "C", "́" }, + ["ć"]={ "c", "́" }, + ["Ĉ"]={ "C", "̂" }, + ["ĉ"]={ "c", "̂" }, + ["Ċ"]={ "C", "̇" }, + ["ċ"]={ "c", "̇" }, + ["Č"]={ "C", "̌" }, + ["č"]={ "c", "̌" }, + ["Ď"]={ "D", "̌" }, + ["ď"]={ "d", "̌" }, + ["Ē"]={ "E", "̄" }, + ["ē"]={ "e", "̄" }, + ["Ĕ"]={ "E", "̆" }, + ["ĕ"]={ "e", "̆" }, + ["Ė"]={ "E", "̇" }, + ["ė"]={ "e", "̇" }, + ["Ę"]={ "E", "̨" }, + ["ę"]={ "e", "̨" }, + ["Ě"]={ "E", "̌" }, + ["ě"]={ "e", "̌" }, + ["Ĝ"]={ "G", "̂" }, + ["ĝ"]={ "g", "̂" }, + ["Ğ"]={ "G", "̆" }, + ["ğ"]={ "g", "̆" }, + ["Ġ"]={ "G", "̇" }, + ["ġ"]={ "g", "̇" }, + ["Ģ"]={ "G", "̧" }, + ["ģ"]={ "g", "̧" }, + ["Ĥ"]={ "H", "̂" }, + ["ĥ"]={ "h", "̂" }, + ["Ĩ"]={ "I", "̃" }, + ["ĩ"]={ "i", "̃" }, + ["Ī"]={ "I", "̄" }, + ["ī"]={ "i", "̄" }, + ["Ĭ"]={ "I", "̆" }, + ["ĭ"]={ "i", "̆" }, + ["Į"]={ "I", "̨" }, + ["į"]={ "i", "̨" }, + ["İ"]={ "I", "̇" }, + ["Ĵ"]={ "J", "̂" }, + ["ĵ"]={ "j", "̂" }, + ["Ķ"]={ "K", "̧" }, + ["ķ"]={ "k", "̧" }, + ["Ĺ"]={ "L", "́" }, + ["ĺ"]={ "l", "́" }, + ["Ļ"]={ "L", "̧" }, + ["ļ"]={ "l", "̧" }, + ["Ľ"]={ "L", "̌" }, + ["ľ"]={ "l", "̌" }, + ["Ń"]={ "N", "́" }, + ["ń"]={ "n", "́" }, + ["Ņ"]={ "N", "̧" }, + ["ņ"]={ "n", "̧" }, + ["Ň"]={ "N", "̌" }, + ["ň"]={ "n", "̌" }, + ["Ō"]={ "O", "̄" }, + ["ō"]={ "o", "̄" }, + ["Ŏ"]={ "O", "̆" }, + ["ŏ"]={ "o", "̆" }, + ["Ő"]={ "O", "̋" }, + ["ő"]={ "o", "̋" }, + ["Ŕ"]={ "R", "́" }, + ["ŕ"]={ "r", "́" }, + ["Ŗ"]={ "R", "̧" }, + ["ŗ"]={ "r", "̧" }, + ["Ř"]={ "R", "̌" }, + ["ř"]={ "r", "̌" }, + ["Ś"]={ "S", "́" }, + ["ś"]={ "s", "́" }, + ["Ŝ"]={ "S", "̂" }, + ["ŝ"]={ "s", "̂" }, + ["Ş"]={ "S", "̧" }, + ["ş"]={ "s", "̧" }, + ["Š"]={ "S", "̌" }, + ["š"]={ "s", "̌" }, + ["Ţ"]={ "T", "̧" }, + ["ţ"]={ "t", "̧" }, + ["Ť"]={ "T", "̌" }, + ["ť"]={ "t", "̌" }, + ["Ũ"]={ "U", "̃" }, + ["ũ"]={ "u", "̃" }, + ["Ū"]={ "U", "̄" }, + ["ū"]={ "u", "̄" }, + ["Ŭ"]={ "U", "̆" }, + ["ŭ"]={ "u", "̆" }, + ["Ů"]={ "U", "̊" }, + ["ů"]={ "u", "̊" }, + ["Ű"]={ "U", "̋" }, + ["ű"]={ "u", "̋" }, + ["Ų"]={ "U", "̨" }, + ["ų"]={ "u", "̨" }, + ["Ŵ"]={ "W", "̂" }, + ["ŵ"]={ "w", "̂" }, + ["Ŷ"]={ "Y", "̂" }, + ["ŷ"]={ "y", "̂" }, + ["Ÿ"]={ "Y", "̈" }, + ["Ź"]={ "Z", "́" }, + ["ź"]={ "z", "́" }, + ["Ż"]={ "Z", "̇" }, + ["ż"]={ "z", "̇" }, + ["Ž"]={ "Z", "̌" }, + ["ž"]={ "z", "̌" }, + ["Ơ"]={ "O", "̛" }, + ["ơ"]={ "o", "̛" }, + ["Ư"]={ "U", "̛" }, + ["ư"]={ "u", "̛" }, + ["Ǎ"]={ "A", "̌" }, + ["ǎ"]={ "a", "̌" }, + ["Ǐ"]={ "I", "̌" }, + ["ǐ"]={ "i", "̌" }, + ["Ǒ"]={ "O", "̌" }, + ["ǒ"]={ "o", "̌" }, + ["Ǔ"]={ "U", "̌" }, + ["ǔ"]={ "u", "̌" }, + ["Ǖ"]={ "Ü", "̄" }, + ["ǖ"]={ "ü", "̄" }, + ["Ǘ"]={ "Ü", "́" }, + ["ǘ"]={ "ü", "́" }, + ["Ǚ"]={ "Ü", "̌" }, + ["ǚ"]={ "ü", "̌" }, + ["Ǜ"]={ "Ü", "̀" }, + ["ǜ"]={ "ü", "̀" }, + ["Ǟ"]={ "Ä", "̄" }, + ["ǟ"]={ "ä", "̄" }, + ["Ǡ"]={ "Ȧ", "̄" }, + ["ǡ"]={ "ȧ", "̄" }, + ["Ǣ"]={ "Æ", "̄" }, + ["ǣ"]={ "æ", "̄" }, + ["Ǧ"]={ "G", "̌" }, + ["ǧ"]={ "g", "̌" }, + ["Ǩ"]={ "K", "̌" }, + ["ǩ"]={ "k", "̌" }, + ["Ǫ"]={ "O", "̨" }, + ["ǫ"]={ "o", "̨" }, + ["Ǭ"]={ "Ǫ", "̄" }, + ["ǭ"]={ "ǫ", "̄" }, + ["Ǯ"]={ "Ʒ", "̌" }, + ["ǯ"]={ "ʒ", "̌" }, + ["ǰ"]={ "j", "̌" }, + ["Ǵ"]={ "G", "́" }, + ["ǵ"]={ "g", "́" }, + ["Ǹ"]={ "N", "̀" }, + ["ǹ"]={ "n", "̀" }, + ["Ǻ"]={ "Å", "́" }, + ["ǻ"]={ "å", "́" }, + ["Ǽ"]={ "Æ", "́" }, + ["ǽ"]={ "æ", "́" }, + ["Ǿ"]={ "Ø", "́" }, + ["ǿ"]={ "ø", "́" }, + ["Ȁ"]={ "A", "̏" }, + ["ȁ"]={ "a", "̏" }, + ["Ȃ"]={ "A", "̑" }, + ["ȃ"]={ "a", "̑" }, + ["Ȅ"]={ "E", "̏" }, + ["ȅ"]={ "e", "̏" }, + ["Ȇ"]={ "E", "̑" }, + ["ȇ"]={ "e", "̑" }, + ["Ȉ"]={ "I", "̏" }, + ["ȉ"]={ "i", "̏" }, + ["Ȋ"]={ "I", "̑" }, + ["ȋ"]={ "i", "̑" }, + ["Ȍ"]={ "O", "̏" }, + ["ȍ"]={ "o", "̏" }, + ["Ȏ"]={ "O", "̑" }, + ["ȏ"]={ "o", "̑" }, + ["Ȑ"]={ "R", "̏" }, + ["ȑ"]={ "r", "̏" }, + ["Ȓ"]={ "R", "̑" }, + ["ȓ"]={ "r", "̑" }, + ["Ȕ"]={ "U", "̏" }, + ["ȕ"]={ "u", "̏" }, + ["Ȗ"]={ "U", "̑" }, + ["ȗ"]={ "u", "̑" }, + ["Ș"]={ "S", "̦" }, + ["ș"]={ "s", "̦" }, + ["Ț"]={ "T", "̦" }, + ["ț"]={ "t", "̦" }, + ["Ȟ"]={ "H", "̌" }, + ["ȟ"]={ "h", "̌" }, + ["Ȧ"]={ "A", "̇" }, + ["ȧ"]={ "a", "̇" }, + ["Ȩ"]={ "E", "̧" }, + ["ȩ"]={ "e", "̧" }, + ["Ȫ"]={ "Ö", "̄" }, + ["ȫ"]={ "ö", "̄" }, + ["Ȭ"]={ "Õ", "̄" }, + ["ȭ"]={ "õ", "̄" }, + ["Ȯ"]={ "O", "̇" }, + ["ȯ"]={ "o", "̇" }, + ["Ȱ"]={ "Ȯ", "̄" }, + ["ȱ"]={ "ȯ", "̄" }, + ["Ȳ"]={ "Y", "̄" }, + ["ȳ"]={ "y", "̄" }, + ["̈́"]={ "̈", "́" }, + ["΅"]={ "¨", "́" }, + ["Ά"]={ "Α", "́" }, + ["Έ"]={ "Ε", "́" }, + ["Ή"]={ "Η", "́" }, + ["Ί"]={ "Ι", "́" }, + ["Ό"]={ "Ο", "́" }, + ["Ύ"]={ "Υ", "́" }, + ["Ώ"]={ "Ω", "́" }, + ["ΐ"]={ "ϊ", "́" }, + ["Ϊ"]={ "Ι", "̈" }, + ["Ϋ"]={ "Υ", "̈" }, + ["ά"]={ "α", "́" }, + ["έ"]={ "ε", "́" }, + ["ή"]={ "η", "́" }, + ["ί"]={ "ι", "́" }, + ["ΰ"]={ "ϋ", "́" }, + ["ϊ"]={ "ι", "̈" }, + ["ϋ"]={ "υ", "̈" }, + ["ό"]={ "ο", "́" }, + ["ύ"]={ "υ", "́" }, + ["ώ"]={ "ω", "́" }, + ["ϓ"]={ "ϒ", "́" }, + ["ϔ"]={ "ϒ", "̈" }, + ["Ѐ"]={ "Е", "̀" }, + ["Ё"]={ "Е", "̈" }, + ["Ѓ"]={ "Г", "́" }, + ["Ї"]={ "І", "̈" }, + ["Ќ"]={ "К", "́" }, + ["Ѝ"]={ "И", "̀" }, + ["Ў"]={ "У", "̆" }, + ["Й"]={ "И", "̆" }, + ["й"]={ "и", "̆" }, + ["ѐ"]={ "е", "̀" }, + ["ё"]={ "е", "̈" }, + ["ѓ"]={ "г", "́" }, + ["ї"]={ "і", "̈" }, + ["ќ"]={ "к", "́" }, + ["ѝ"]={ "и", "̀" }, + ["ў"]={ "у", "̆" }, + ["Ѷ"]={ "Ѵ", "̏" }, + ["ѷ"]={ "ѵ", "̏" }, + ["Ӂ"]={ "Ж", "̆" }, + ["ӂ"]={ "ж", "̆" }, + ["Ӑ"]={ "А", "̆" }, + ["ӑ"]={ "а", "̆" }, + ["Ӓ"]={ "А", "̈" }, + ["ӓ"]={ "а", "̈" }, + ["Ӗ"]={ "Е", "̆" }, + ["ӗ"]={ "е", "̆" }, + ["Ӛ"]={ "Ә", "̈" }, + ["ӛ"]={ "ә", "̈" }, + ["Ӝ"]={ "Ж", "̈" }, + ["ӝ"]={ "ж", "̈" }, + ["Ӟ"]={ "З", "̈" }, + ["ӟ"]={ "з", "̈" }, + ["Ӣ"]={ "И", "̄" }, + ["ӣ"]={ "и", "̄" }, + ["Ӥ"]={ "И", "̈" }, + ["ӥ"]={ "и", "̈" }, + ["Ӧ"]={ "О", "̈" }, + ["ӧ"]={ "о", "̈" }, + ["Ӫ"]={ "Ө", "̈" }, + ["ӫ"]={ "ө", "̈" }, + ["Ӭ"]={ "Э", "̈" }, + ["ӭ"]={ "э", "̈" }, + ["Ӯ"]={ "У", "̄" }, + ["ӯ"]={ "у", "̄" }, + ["Ӱ"]={ "У", "̈" }, + ["ӱ"]={ "у", "̈" }, + ["Ӳ"]={ "У", "̋" }, + ["ӳ"]={ "у", "̋" }, + ["Ӵ"]={ "Ч", "̈" }, + ["ӵ"]={ "ч", "̈" }, + ["Ӹ"]={ "Ы", "̈" }, + ["ӹ"]={ "ы", "̈" }, + ["آ"]={ "ا", "ٓ" }, + ["أ"]={ "ا", "ٔ" }, + ["ؤ"]={ "و", "ٔ" }, + ["إ"]={ "ا", "ٕ" }, + ["ئ"]={ "ي", "ٔ" }, + ["ۀ"]={ "ە", "ٔ" }, + ["ۂ"]={ "ہ", "ٔ" }, + ["ۓ"]={ "ے", "ٔ" }, + ["ऩ"]={ "न", "़" }, + ["ऱ"]={ "र", "़" }, + ["ऴ"]={ "ळ", "़" }, + ["क़"]={ "क", "़" }, + ["ख़"]={ "ख", "़" }, + ["ग़"]={ "ग", "़" }, + ["ज़"]={ "ज", "़" }, + ["ड़"]={ "ड", "़" }, + ["ढ़"]={ "ढ", "़" }, + ["फ़"]={ "फ", "़" }, + ["य़"]={ "य", "़" }, + ["ো"]={ "ে", "া" }, + ["ৌ"]={ "ে", "ৗ" }, + ["ড়"]={ "ড", "়" }, + ["ঢ়"]={ "ঢ", "়" }, + ["য়"]={ "য", "়" }, + ["ਲ਼"]={ "ਲ", "਼" }, + ["ਸ਼"]={ "ਸ", "਼" }, + ["ਖ਼"]={ "ਖ", "਼" }, + ["ਗ਼"]={ "ਗ", "਼" }, + ["ਜ਼"]={ "ਜ", "਼" }, + ["ਫ਼"]={ "ਫ", "਼" }, + ["ୈ"]={ "େ", "ୖ" }, + ["ୋ"]={ "େ", "ା" }, + ["ୌ"]={ "େ", "ୗ" }, + ["ଡ଼"]={ "ଡ", "଼" }, + ["ଢ଼"]={ "ଢ", "଼" }, + ["ஔ"]={ "ஒ", "ௗ" }, + ["ொ"]={ "ெ", "ா" }, + ["ோ"]={ "ே", "ா" }, + ["ௌ"]={ "ெ", "ௗ" }, + ["ై"]={ "ె", "ౖ" }, + ["ೀ"]={ "ಿ", "ೕ" }, + ["ೇ"]={ "ೆ", "ೕ" }, + ["ೈ"]={ "ೆ", "ೖ" }, + ["ೊ"]={ "ೆ", "ೂ" }, + ["ೋ"]={ "ೊ", "ೕ" }, + ["ൊ"]={ "െ", "ാ" }, + ["ോ"]={ "േ", "ാ" }, + ["ൌ"]={ "െ", "ൗ" }, + ["ේ"]={ "ෙ", "්" }, + ["ො"]={ "ෙ", "ා" }, + ["ෝ"]={ "ො", "්" }, + ["ෞ"]={ "ෙ", "ෟ" }, + ["གྷ"]={ "ག", "ྷ" }, + ["ཌྷ"]={ "ཌ", "ྷ" }, + ["དྷ"]={ "ད", "ྷ" }, + ["བྷ"]={ "བ", "ྷ" }, + ["ཛྷ"]={ "ཛ", "ྷ" }, + ["ཀྵ"]={ "ཀ", "ྵ" }, + ["ཱི"]={ "ཱ", "ི" }, + ["ཱུ"]={ "ཱ", "ུ" }, + ["ྲྀ"]={ "ྲ", "ྀ" }, + ["ླྀ"]={ "ླ", "ྀ" }, + ["ཱྀ"]={ "ཱ", "ྀ" }, + ["ྒྷ"]={ "ྒ", "ྷ" }, + ["ྜྷ"]={ "ྜ", "ྷ" }, + ["ྡྷ"]={ "ྡ", "ྷ" }, + ["ྦྷ"]={ "ྦ", "ྷ" }, + ["ྫྷ"]={ "ྫ", "ྷ" }, + ["ྐྵ"]={ "ྐ", "ྵ" }, + ["ဦ"]={ "ဥ", "ီ" }, + ["ᬆ"]={ "ᬅ", "ᬵ" }, + ["ᬈ"]={ "ᬇ", "ᬵ" }, + ["ᬊ"]={ "ᬉ", "ᬵ" }, + ["ᬌ"]={ "ᬋ", "ᬵ" }, + ["ᬎ"]={ "ᬍ", "ᬵ" }, + ["ᬒ"]={ "ᬑ", "ᬵ" }, + ["ᬻ"]={ "ᬺ", "ᬵ" }, + ["ᬽ"]={ "ᬼ", "ᬵ" }, + ["ᭀ"]={ "ᬾ", "ᬵ" }, + ["ᭁ"]={ "ᬿ", "ᬵ" }, + ["ᭃ"]={ "ᭂ", "ᬵ" }, + ["Ḁ"]={ "A", "̥" }, + ["ḁ"]={ "a", "̥" }, + ["Ḃ"]={ "B", "̇" }, + ["ḃ"]={ "b", "̇" }, + ["Ḅ"]={ "B", "̣" }, + ["ḅ"]={ "b", "̣" }, + ["Ḇ"]={ "B", "̱" }, + ["ḇ"]={ "b", "̱" }, + ["Ḉ"]={ "Ç", "́" }, + ["ḉ"]={ "ç", "́" }, + ["Ḋ"]={ "D", "̇" }, + ["ḋ"]={ "d", "̇" }, + ["Ḍ"]={ "D", "̣" }, + ["ḍ"]={ "d", "̣" }, + ["Ḏ"]={ "D", "̱" }, + ["ḏ"]={ "d", "̱" }, + ["Ḑ"]={ "D", "̧" }, + ["ḑ"]={ "d", "̧" }, + ["Ḓ"]={ "D", "̭" }, + ["ḓ"]={ "d", "̭" }, + ["Ḕ"]={ "Ē", "̀" }, + ["ḕ"]={ "ē", "̀" }, + ["Ḗ"]={ "Ē", "́" }, + ["ḗ"]={ "ē", "́" }, + ["Ḙ"]={ "E", "̭" }, + ["ḙ"]={ "e", "̭" }, + ["Ḛ"]={ "E", "̰" }, + ["ḛ"]={ "e", "̰" }, + ["Ḝ"]={ "Ȩ", "̆" }, + ["ḝ"]={ "ȩ", "̆" }, + ["Ḟ"]={ "F", "̇" }, + ["ḟ"]={ "f", "̇" }, + ["Ḡ"]={ "G", "̄" }, + ["ḡ"]={ "g", "̄" }, + ["Ḣ"]={ "H", "̇" }, + ["ḣ"]={ "h", "̇" }, + ["Ḥ"]={ "H", "̣" }, + ["ḥ"]={ "h", "̣" }, + ["Ḧ"]={ "H", "̈" }, + ["ḧ"]={ "h", "̈" }, + ["Ḩ"]={ "H", "̧" }, + ["ḩ"]={ "h", "̧" }, + ["Ḫ"]={ "H", "̮" }, + ["ḫ"]={ "h", "̮" }, + ["Ḭ"]={ "I", "̰" }, + ["ḭ"]={ "i", "̰" }, + ["Ḯ"]={ "Ï", "́" }, + ["ḯ"]={ "ï", "́" }, + ["Ḱ"]={ "K", "́" }, + ["ḱ"]={ "k", "́" }, + ["Ḳ"]={ "K", "̣" }, + ["ḳ"]={ "k", "̣" }, + ["Ḵ"]={ "K", "̱" }, + ["ḵ"]={ "k", "̱" }, + ["Ḷ"]={ "L", "̣" }, + ["ḷ"]={ "l", "̣" }, + ["Ḹ"]={ "Ḷ", "̄" }, + ["ḹ"]={ "ḷ", "̄" }, + ["Ḻ"]={ "L", "̱" }, + ["ḻ"]={ "l", "̱" }, + ["Ḽ"]={ "L", "̭" }, + ["ḽ"]={ "l", "̭" }, + ["Ḿ"]={ "M", "́" }, + ["ḿ"]={ "m", "́" }, + ["Ṁ"]={ "M", "̇" }, + ["ṁ"]={ "m", "̇" }, + ["Ṃ"]={ "M", "̣" }, + ["ṃ"]={ "m", "̣" }, + ["Ṅ"]={ "N", "̇" }, + ["ṅ"]={ "n", "̇" }, + ["Ṇ"]={ "N", "̣" }, + ["ṇ"]={ "n", "̣" }, + ["Ṉ"]={ "N", "̱" }, + ["ṉ"]={ "n", "̱" }, + ["Ṋ"]={ "N", "̭" }, + ["ṋ"]={ "n", "̭" }, + ["Ṍ"]={ "Õ", "́" }, + ["ṍ"]={ "õ", "́" }, + ["Ṏ"]={ "Õ", "̈" }, + ["ṏ"]={ "õ", "̈" }, + ["Ṑ"]={ "Ō", "̀" }, + ["ṑ"]={ "ō", "̀" }, + ["Ṓ"]={ "Ō", "́" }, + ["ṓ"]={ "ō", "́" }, + ["Ṕ"]={ "P", "́" }, + ["ṕ"]={ "p", "́" }, + ["Ṗ"]={ "P", "̇" }, + ["ṗ"]={ "p", "̇" }, + ["Ṙ"]={ "R", "̇" }, + ["ṙ"]={ "r", "̇" }, + ["Ṛ"]={ "R", "̣" }, + ["ṛ"]={ "r", "̣" }, + ["Ṝ"]={ "Ṛ", "̄" }, + ["ṝ"]={ "ṛ", "̄" }, + ["Ṟ"]={ "R", "̱" }, + ["ṟ"]={ "r", "̱" }, + ["Ṡ"]={ "S", "̇" }, + ["ṡ"]={ "s", "̇" }, + ["Ṣ"]={ "S", "̣" }, + ["ṣ"]={ "s", "̣" }, + ["Ṥ"]={ "Ś", "̇" }, + ["ṥ"]={ "ś", "̇" }, + ["Ṧ"]={ "Š", "̇" }, + ["ṧ"]={ "š", "̇" }, + ["Ṩ"]={ "Ṣ", "̇" }, + ["ṩ"]={ "ṣ", "̇" }, + ["Ṫ"]={ "T", "̇" }, + ["ṫ"]={ "t", "̇" }, + ["Ṭ"]={ "T", "̣" }, + ["ṭ"]={ "t", "̣" }, + ["Ṯ"]={ "T", "̱" }, + ["ṯ"]={ "t", "̱" }, + ["Ṱ"]={ "T", "̭" }, + ["ṱ"]={ "t", "̭" }, + ["Ṳ"]={ "U", "̤" }, + ["ṳ"]={ "u", "̤" }, + ["Ṵ"]={ "U", "̰" }, + ["ṵ"]={ "u", "̰" }, + ["Ṷ"]={ "U", "̭" }, + ["ṷ"]={ "u", "̭" }, + ["Ṹ"]={ "Ũ", "́" }, + ["ṹ"]={ "ũ", "́" }, + ["Ṻ"]={ "Ū", "̈" }, + ["ṻ"]={ "ū", "̈" }, + ["Ṽ"]={ "V", "̃" }, + ["ṽ"]={ "v", "̃" }, + ["Ṿ"]={ "V", "̣" }, + ["ṿ"]={ "v", "̣" }, + ["Ẁ"]={ "W", "̀" }, + ["ẁ"]={ "w", "̀" }, + ["Ẃ"]={ "W", "́" }, + ["ẃ"]={ "w", "́" }, + ["Ẅ"]={ "W", "̈" }, + ["ẅ"]={ "w", "̈" }, + ["Ẇ"]={ "W", "̇" }, + ["ẇ"]={ "w", "̇" }, + ["Ẉ"]={ "W", "̣" }, + ["ẉ"]={ "w", "̣" }, + ["Ẋ"]={ "X", "̇" }, + ["ẋ"]={ "x", "̇" }, + ["Ẍ"]={ "X", "̈" }, + ["ẍ"]={ "x", "̈" }, + ["Ẏ"]={ "Y", "̇" }, + ["ẏ"]={ "y", "̇" }, + ["Ẑ"]={ "Z", "̂" }, + ["ẑ"]={ "z", "̂" }, + ["Ẓ"]={ "Z", "̣" }, + ["ẓ"]={ "z", "̣" }, + ["Ẕ"]={ "Z", "̱" }, + ["ẕ"]={ "z", "̱" }, + ["ẖ"]={ "h", "̱" }, + ["ẗ"]={ "t", "̈" }, + ["ẘ"]={ "w", "̊" }, + ["ẙ"]={ "y", "̊" }, + ["ẛ"]={ "ſ", "̇" }, + ["Ạ"]={ "A", "̣" }, + ["ạ"]={ "a", "̣" }, + ["Ả"]={ "A", "̉" }, + ["ả"]={ "a", "̉" }, + ["Ấ"]={ "Â", "́" }, + ["ấ"]={ "â", "́" }, + ["Ầ"]={ "Â", "̀" }, + ["ầ"]={ "â", "̀" }, + ["Ẩ"]={ "Â", "̉" }, + ["ẩ"]={ "â", "̉" }, + ["Ẫ"]={ "Â", "̃" }, + ["ẫ"]={ "â", "̃" }, + ["Ậ"]={ "Ạ", "̂" }, + ["ậ"]={ "ạ", "̂" }, + ["Ắ"]={ "Ă", "́" }, + ["ắ"]={ "ă", "́" }, + ["Ằ"]={ "Ă", "̀" }, + ["ằ"]={ "ă", "̀" }, + ["Ẳ"]={ "Ă", "̉" }, + ["ẳ"]={ "ă", "̉" }, + ["Ẵ"]={ "Ă", "̃" }, + ["ẵ"]={ "ă", "̃" }, + ["Ặ"]={ "Ạ", "̆" }, + ["ặ"]={ "ạ", "̆" }, + ["Ẹ"]={ "E", "̣" }, + ["ẹ"]={ "e", "̣" }, + ["Ẻ"]={ "E", "̉" }, + ["ẻ"]={ "e", "̉" }, + ["Ẽ"]={ "E", "̃" }, + ["ẽ"]={ "e", "̃" }, + ["Ế"]={ "Ê", "́" }, + ["ế"]={ "ê", "́" }, + ["Ề"]={ "Ê", "̀" }, + ["ề"]={ "ê", "̀" }, + ["Ể"]={ "Ê", "̉" }, + ["ể"]={ "ê", "̉" }, + ["Ễ"]={ "Ê", "̃" }, + ["ễ"]={ "ê", "̃" }, + ["Ệ"]={ "Ẹ", "̂" }, + ["ệ"]={ "ẹ", "̂" }, + ["Ỉ"]={ "I", "̉" }, + ["ỉ"]={ "i", "̉" }, + ["Ị"]={ "I", "̣" }, + ["ị"]={ "i", "̣" }, + ["Ọ"]={ "O", "̣" }, + ["ọ"]={ "o", "̣" }, + ["Ỏ"]={ "O", "̉" }, + ["ỏ"]={ "o", "̉" }, + ["Ố"]={ "Ô", "́" }, + ["ố"]={ "ô", "́" }, + ["Ồ"]={ "Ô", "̀" }, + ["ồ"]={ "ô", "̀" }, + ["Ổ"]={ "Ô", "̉" }, + ["ổ"]={ "ô", "̉" }, + ["Ỗ"]={ "Ô", "̃" }, + ["ỗ"]={ "ô", "̃" }, + ["Ộ"]={ "Ọ", "̂" }, + ["ộ"]={ "ọ", "̂" }, + ["Ớ"]={ "Ơ", "́" }, + ["ớ"]={ "ơ", "́" }, + ["Ờ"]={ "Ơ", "̀" }, + ["ờ"]={ "ơ", "̀" }, + ["Ở"]={ "Ơ", "̉" }, + ["ở"]={ "ơ", "̉" }, + ["Ỡ"]={ "Ơ", "̃" }, + ["ỡ"]={ "ơ", "̃" }, + ["Ợ"]={ "Ơ", "̣" }, + ["ợ"]={ "ơ", "̣" }, + ["Ụ"]={ "U", "̣" }, + ["ụ"]={ "u", "̣" }, + ["Ủ"]={ "U", "̉" }, + ["ủ"]={ "u", "̉" }, + ["Ứ"]={ "Ư", "́" }, + ["ứ"]={ "ư", "́" }, + ["Ừ"]={ "Ư", "̀" }, + ["ừ"]={ "ư", "̀" }, + ["Ử"]={ "Ư", "̉" }, + ["ử"]={ "ư", "̉" }, + ["Ữ"]={ "Ư", "̃" }, + ["ữ"]={ "ư", "̃" }, + ["Ự"]={ "Ư", "̣" }, + ["ự"]={ "ư", "̣" }, + ["Ỳ"]={ "Y", "̀" }, + ["ỳ"]={ "y", "̀" }, + ["Ỵ"]={ "Y", "̣" }, + ["ỵ"]={ "y", "̣" }, + ["Ỷ"]={ "Y", "̉" }, + ["ỷ"]={ "y", "̉" }, + ["Ỹ"]={ "Y", "̃" }, + ["ỹ"]={ "y", "̃" }, + ["ἀ"]={ "α", "̓" }, + ["ἁ"]={ "α", "̔" }, + ["ἂ"]={ "ἀ", "̀" }, + ["ἃ"]={ "ἁ", "̀" }, + ["ἄ"]={ "ἀ", "́" }, + ["ἅ"]={ "ἁ", "́" }, + ["ἆ"]={ "ἀ", "͂" }, + ["ἇ"]={ "ἁ", "͂" }, + ["Ἀ"]={ "Α", "̓" }, + ["Ἁ"]={ "Α", "̔" }, + ["Ἂ"]={ "Ἀ", "̀" }, + ["Ἃ"]={ "Ἁ", "̀" }, + ["Ἄ"]={ "Ἀ", "́" }, + ["Ἅ"]={ "Ἁ", "́" }, + ["Ἆ"]={ "Ἀ", "͂" }, + ["Ἇ"]={ "Ἁ", "͂" }, + ["ἐ"]={ "ε", "̓" }, + ["ἑ"]={ "ε", "̔" }, + ["ἒ"]={ "ἐ", "̀" }, + ["ἓ"]={ "ἑ", "̀" }, + ["ἔ"]={ "ἐ", "́" }, + ["ἕ"]={ "ἑ", "́" }, + ["Ἐ"]={ "Ε", "̓" }, + ["Ἑ"]={ "Ε", "̔" }, + ["Ἒ"]={ "Ἐ", "̀" }, + ["Ἓ"]={ "Ἑ", "̀" }, + ["Ἔ"]={ "Ἐ", "́" }, + ["Ἕ"]={ "Ἑ", "́" }, + ["ἠ"]={ "η", "̓" }, + ["ἡ"]={ "η", "̔" }, + ["ἢ"]={ "ἠ", "̀" }, + ["ἣ"]={ "ἡ", "̀" }, + ["ἤ"]={ "ἠ", "́" }, + ["ἥ"]={ "ἡ", "́" }, + ["ἦ"]={ "ἠ", "͂" }, + ["ἧ"]={ "ἡ", "͂" }, + ["Ἠ"]={ "Η", "̓" }, + ["Ἡ"]={ "Η", "̔" }, + ["Ἢ"]={ "Ἠ", "̀" }, + ["Ἣ"]={ "Ἡ", "̀" }, + ["Ἤ"]={ "Ἠ", "́" }, + ["Ἥ"]={ "Ἡ", "́" }, + ["Ἦ"]={ "Ἠ", "͂" }, + ["Ἧ"]={ "Ἡ", "͂" }, + ["ἰ"]={ "ι", "̓" }, + ["ἱ"]={ "ι", "̔" }, + ["ἲ"]={ "ἰ", "̀" }, + ["ἳ"]={ "ἱ", "̀" }, + ["ἴ"]={ "ἰ", "́" }, + ["ἵ"]={ "ἱ", "́" }, + ["ἶ"]={ "ἰ", "͂" }, + ["ἷ"]={ "ἱ", "͂" }, + ["Ἰ"]={ "Ι", "̓" }, + ["Ἱ"]={ "Ι", "̔" }, + ["Ἲ"]={ "Ἰ", "̀" }, + ["Ἳ"]={ "Ἱ", "̀" }, + ["Ἴ"]={ "Ἰ", "́" }, + ["Ἵ"]={ "Ἱ", "́" }, + ["Ἶ"]={ "Ἰ", "͂" }, + ["Ἷ"]={ "Ἱ", "͂" }, + ["ὀ"]={ "ο", "̓" }, + ["ὁ"]={ "ο", "̔" }, + ["ὂ"]={ "ὀ", "̀" }, + ["ὃ"]={ "ὁ", "̀" }, + ["ὄ"]={ "ὀ", "́" }, + ["ὅ"]={ "ὁ", "́" }, + ["Ὀ"]={ "Ο", "̓" }, + ["Ὁ"]={ "Ο", "̔" }, + ["Ὂ"]={ "Ὀ", "̀" }, + ["Ὃ"]={ "Ὁ", "̀" }, + ["Ὄ"]={ "Ὀ", "́" }, + ["Ὅ"]={ "Ὁ", "́" }, + ["ὐ"]={ "υ", "̓" }, + ["ὑ"]={ "υ", "̔" }, + ["ὒ"]={ "ὐ", "̀" }, + ["ὓ"]={ "ὑ", "̀" }, + ["ὔ"]={ "ὐ", "́" }, + ["ὕ"]={ "ὑ", "́" }, + ["ὖ"]={ "ὐ", "͂" }, + ["ὗ"]={ "ὑ", "͂" }, + ["Ὑ"]={ "Υ", "̔" }, + ["Ὓ"]={ "Ὑ", "̀" }, + ["Ὕ"]={ "Ὑ", "́" }, + ["Ὗ"]={ "Ὑ", "͂" }, + ["ὠ"]={ "ω", "̓" }, + ["ὡ"]={ "ω", "̔" }, + ["ὢ"]={ "ὠ", "̀" }, + ["ὣ"]={ "ὡ", "̀" }, + ["ὤ"]={ "ὠ", "́" }, + ["ὥ"]={ "ὡ", "́" }, + ["ὦ"]={ "ὠ", "͂" }, + ["ὧ"]={ "ὡ", "͂" }, + ["Ὠ"]={ "Ω", "̓" }, + ["Ὡ"]={ "Ω", "̔" }, + ["Ὢ"]={ "Ὠ", "̀" }, + ["Ὣ"]={ "Ὡ", "̀" }, + ["Ὤ"]={ "Ὠ", "́" }, + ["Ὥ"]={ "Ὡ", "́" }, + ["Ὦ"]={ "Ὠ", "͂" }, + ["Ὧ"]={ "Ὡ", "͂" }, + ["ὰ"]={ "α", "̀" }, + ["ὲ"]={ "ε", "̀" }, + ["ὴ"]={ "η", "̀" }, + ["ὶ"]={ "ι", "̀" }, + ["ὸ"]={ "ο", "̀" }, + ["ὺ"]={ "υ", "̀" }, + ["ὼ"]={ "ω", "̀" }, + ["ᾀ"]={ "ἀ", "ͅ" }, + ["ᾁ"]={ "ἁ", "ͅ" }, + ["ᾂ"]={ "ἂ", "ͅ" }, + ["ᾃ"]={ "ἃ", "ͅ" }, + ["ᾄ"]={ "ἄ", "ͅ" }, + ["ᾅ"]={ "ἅ", "ͅ" }, + ["ᾆ"]={ "ἆ", "ͅ" }, + ["ᾇ"]={ "ἇ", "ͅ" }, + ["ᾈ"]={ "Ἀ", "ͅ" }, + ["ᾉ"]={ "Ἁ", "ͅ" }, + ["ᾊ"]={ "Ἂ", "ͅ" }, + ["ᾋ"]={ "Ἃ", "ͅ" }, + ["ᾌ"]={ "Ἄ", "ͅ" }, + ["ᾍ"]={ "Ἅ", "ͅ" }, + ["ᾎ"]={ "Ἆ", "ͅ" }, + ["ᾏ"]={ "Ἇ", "ͅ" }, + ["ᾐ"]={ "ἠ", "ͅ" }, + ["ᾑ"]={ "ἡ", "ͅ" }, + ["ᾒ"]={ "ἢ", "ͅ" }, + ["ᾓ"]={ "ἣ", "ͅ" }, + ["ᾔ"]={ "ἤ", "ͅ" }, + ["ᾕ"]={ "ἥ", "ͅ" }, + ["ᾖ"]={ "ἦ", "ͅ" }, + ["ᾗ"]={ "ἧ", "ͅ" }, + ["ᾘ"]={ "Ἠ", "ͅ" }, + ["ᾙ"]={ "Ἡ", "ͅ" }, + ["ᾚ"]={ "Ἢ", "ͅ" }, + ["ᾛ"]={ "Ἣ", "ͅ" }, + ["ᾜ"]={ "Ἤ", "ͅ" }, + ["ᾝ"]={ "Ἥ", "ͅ" }, + ["ᾞ"]={ "Ἦ", "ͅ" }, + ["ᾟ"]={ "Ἧ", "ͅ" }, + ["ᾠ"]={ "ὠ", "ͅ" }, + ["ᾡ"]={ "ὡ", "ͅ" }, + ["ᾢ"]={ "ὢ", "ͅ" }, + ["ᾣ"]={ "ὣ", "ͅ" }, + ["ᾤ"]={ "ὤ", "ͅ" }, + ["ᾥ"]={ "ὥ", "ͅ" }, + ["ᾦ"]={ "ὦ", "ͅ" }, + ["ᾧ"]={ "ὧ", "ͅ" }, + ["ᾨ"]={ "Ὠ", "ͅ" }, + ["ᾩ"]={ "Ὡ", "ͅ" }, + ["ᾪ"]={ "Ὢ", "ͅ" }, + ["ᾫ"]={ "Ὣ", "ͅ" }, + ["ᾬ"]={ "Ὤ", "ͅ" }, + ["ᾭ"]={ "Ὥ", "ͅ" }, + ["ᾮ"]={ "Ὦ", "ͅ" }, + ["ᾯ"]={ "Ὧ", "ͅ" }, + ["ᾰ"]={ "α", "̆" }, + ["ᾱ"]={ "α", "̄" }, + ["ᾲ"]={ "ὰ", "ͅ" }, + ["ᾳ"]={ "α", "ͅ" }, + ["ᾴ"]={ "ά", "ͅ" }, + ["ᾶ"]={ "α", "͂" }, + ["ᾷ"]={ "ᾶ", "ͅ" }, + ["Ᾰ"]={ "Α", "̆" }, + ["Ᾱ"]={ "Α", "̄" }, + ["Ὰ"]={ "Α", "̀" }, + ["ᾼ"]={ "Α", "ͅ" }, + ["῁"]={ "¨", "͂" }, + ["ῂ"]={ "ὴ", "ͅ" }, + ["ῃ"]={ "η", "ͅ" }, + ["ῄ"]={ "ή", "ͅ" }, + ["ῆ"]={ "η", "͂" }, + ["ῇ"]={ "ῆ", "ͅ" }, + ["Ὲ"]={ "Ε", "̀" }, + ["Ὴ"]={ "Η", "̀" }, + ["ῌ"]={ "Η", "ͅ" }, + ["῍"]={ "᾿", "̀" }, + ["῎"]={ "᾿", "́" }, + ["῏"]={ "᾿", "͂" }, + ["ῐ"]={ "ι", "̆" }, + ["ῑ"]={ "ι", "̄" }, + ["ῒ"]={ "ϊ", "̀" }, + ["ῖ"]={ "ι", "͂" }, + ["ῗ"]={ "ϊ", "͂" }, + ["Ῐ"]={ "Ι", "̆" }, + ["Ῑ"]={ "Ι", "̄" }, + ["Ὶ"]={ "Ι", "̀" }, + ["῝"]={ "῾", "̀" }, + ["῞"]={ "῾", "́" }, + ["῟"]={ "῾", "͂" }, + ["ῠ"]={ "υ", "̆" }, + ["ῡ"]={ "υ", "̄" }, + ["ῢ"]={ "ϋ", "̀" }, + ["ῤ"]={ "ρ", "̓" }, + ["ῥ"]={ "ρ", "̔" }, + ["ῦ"]={ "υ", "͂" }, + ["ῧ"]={ "ϋ", "͂" }, + ["Ῠ"]={ "Υ", "̆" }, + ["Ῡ"]={ "Υ", "̄" }, + ["Ὺ"]={ "Υ", "̀" }, + ["Ῥ"]={ "Ρ", "̔" }, + ["῭"]={ "¨", "̀" }, + ["ῲ"]={ "ὼ", "ͅ" }, + ["ῳ"]={ "ω", "ͅ" }, + ["ῴ"]={ "ώ", "ͅ" }, + ["ῶ"]={ "ω", "͂" }, + ["ῷ"]={ "ῶ", "ͅ" }, + ["Ὸ"]={ "Ο", "̀" }, + ["Ὼ"]={ "Ω", "̀" }, + ["ῼ"]={ "Ω", "ͅ" }, + ["↚"]={ "←", "̸" }, + ["↛"]={ "→", "̸" }, + ["↮"]={ "↔", "̸" }, + ["⇍"]={ "⇐", "̸" }, + ["⇎"]={ "⇔", "̸" }, + ["⇏"]={ "⇒", "̸" }, + ["∄"]={ "∃", "̸" }, + ["∉"]={ "∈", "̸" }, + ["∌"]={ "∋", "̸" }, + ["∤"]={ "∣", "̸" }, + ["∦"]={ "∥", "̸" }, + ["≁"]={ "∼", "̸" }, + ["≄"]={ "≃", "̸" }, + ["≇"]={ "≅", "̸" }, + ["≉"]={ "≈", "̸" }, + ["≠"]={ "=", "̸" }, + ["≢"]={ "≡", "̸" }, + ["≭"]={ "≍", "̸" }, + ["≮"]={ "<", "̸" }, + ["≯"]={ ">", "̸" }, + ["≰"]={ "≤", "̸" }, + ["≱"]={ "≥", "̸" }, + ["≴"]={ "≲", "̸" }, + ["≵"]={ "≳", "̸" }, + ["≸"]={ "≶", "̸" }, + ["≹"]={ "≷", "̸" }, + ["⊀"]={ "≺", "̸" }, + ["⊁"]={ "≻", "̸" }, + ["⊄"]={ "⊂", "̸" }, + ["⊅"]={ "⊃", "̸" }, + ["⊈"]={ "⊆", "̸" }, + ["⊉"]={ "⊇", "̸" }, + ["⊬"]={ "⊢", "̸" }, + ["⊭"]={ "⊨", "̸" }, + ["⊮"]={ "⊩", "̸" }, + ["⊯"]={ "⊫", "̸" }, + ["⋠"]={ "≼", "̸" }, + ["⋡"]={ "≽", "̸" }, + ["⋢"]={ "⊑", "̸" }, + ["⋣"]={ "⊒", "̸" }, + ["⋪"]={ "⊲", "̸" }, + ["⋫"]={ "⊳", "̸" }, + ["⋬"]={ "⊴", "̸" }, + ["⋭"]={ "⊵", "̸" }, + ["⫝̸"]={ "⫝", "̸" }, + ["が"]={ "か", "゙" }, + ["ぎ"]={ "き", "゙" }, + ["ぐ"]={ "く", "゙" }, + ["げ"]={ "け", "゙" }, + ["ご"]={ "こ", "゙" }, + ["ざ"]={ "さ", "゙" }, + ["じ"]={ "し", "゙" }, + ["ず"]={ "す", "゙" }, + ["ぜ"]={ "せ", "゙" }, + ["ぞ"]={ "そ", "゙" }, + ["だ"]={ "た", "゙" }, + ["ぢ"]={ "ち", "゙" }, + ["づ"]={ "つ", "゙" }, + ["で"]={ "て", "゙" }, + ["ど"]={ "と", "゙" }, + ["ば"]={ "は", "゙" }, + ["ぱ"]={ "は", "゚" }, + ["び"]={ "ひ", "゙" }, + ["ぴ"]={ "ひ", "゚" }, + ["ぶ"]={ "ふ", "゙" }, + ["ぷ"]={ "ふ", "゚" }, + ["べ"]={ "へ", "゙" }, + ["ぺ"]={ "へ", "゚" }, + ["ぼ"]={ "ほ", "゙" }, + ["ぽ"]={ "ほ", "゚" }, + ["ゔ"]={ "う", "゙" }, + ["ゞ"]={ "ゝ", "゙" }, + ["ガ"]={ "カ", "゙" }, + ["ギ"]={ "キ", "゙" }, + ["グ"]={ "ク", "゙" }, + ["ゲ"]={ "ケ", "゙" }, + ["ゴ"]={ "コ", "゙" }, + ["ザ"]={ "サ", "゙" }, + ["ジ"]={ "シ", "゙" }, + ["ズ"]={ "ス", "゙" }, + ["ゼ"]={ "セ", "゙" }, + ["ゾ"]={ "ソ", "゙" }, + ["ダ"]={ "タ", "゙" }, + ["ヂ"]={ "チ", "゙" }, + ["ヅ"]={ "ツ", "゙" }, + ["デ"]={ "テ", "゙" }, + ["ド"]={ "ト", "゙" }, + ["バ"]={ "ハ", "゙" }, + ["パ"]={ "ハ", "゚" }, + ["ビ"]={ "ヒ", "゙" }, + ["ピ"]={ "ヒ", "゚" }, + ["ブ"]={ "フ", "゙" }, + ["プ"]={ "フ", "゚" }, + ["ベ"]={ "ヘ", "゙" }, + ["ペ"]={ "ヘ", "゚" }, + ["ボ"]={ "ホ", "゙" }, + ["ポ"]={ "ホ", "゚" }, + ["ヴ"]={ "ウ", "゙" }, + ["ヷ"]={ "ワ", "゙" }, + ["ヸ"]={ "ヰ", "゙" }, + ["ヹ"]={ "ヱ", "゙" }, + ["ヺ"]={ "ヲ", "゙" }, + ["ヾ"]={ "ヽ", "゙" }, + ["יִ"]={ "י", "ִ" }, + ["ײַ"]={ "ײ", "ַ" }, + ["שׁ"]={ "ש", "ׁ" }, + ["שׂ"]={ "ש", "ׂ" }, + ["שּׁ"]={ "שּ", "ׁ" }, + ["שּׂ"]={ "שּ", "ׂ" }, + ["אַ"]={ "א", "ַ" }, + ["אָ"]={ "א", "ָ" }, + ["אּ"]={ "א", "ּ" }, + ["בּ"]={ "ב", "ּ" }, + ["גּ"]={ "ג", "ּ" }, + ["דּ"]={ "ד", "ּ" }, + ["הּ"]={ "ה", "ּ" }, + ["וּ"]={ "ו", "ּ" }, + ["זּ"]={ "ז", "ּ" }, + ["טּ"]={ "ט", "ּ" }, + ["יּ"]={ "י", "ּ" }, + ["ךּ"]={ "ך", "ּ" }, + ["כּ"]={ "כ", "ּ" }, + ["לּ"]={ "ל", "ּ" }, + ["מּ"]={ "מ", "ּ" }, + ["נּ"]={ "נ", "ּ" }, + ["סּ"]={ "ס", "ּ" }, + ["ףּ"]={ "ף", "ּ" }, + ["פּ"]={ "פ", "ּ" }, + ["צּ"]={ "צ", "ּ" }, + ["קּ"]={ "ק", "ּ" }, + ["רּ"]={ "ר", "ּ" }, + ["שּ"]={ "ש", "ּ" }, + ["תּ"]={ "ת", "ּ" }, + ["וֹ"]={ "ו", "ֹ" }, + ["בֿ"]={ "ב", "ֿ" }, + ["כֿ"]={ "כ", "ֿ" }, + ["פֿ"]={ "פ", "ֿ" }, + ["𑂚"]={ "𑂙", "𑂺" }, + ["𑂜"]={ "𑂛", "𑂺" }, + ["𑂫"]={ "𑂥", "𑂺" }, + ["𑄮"]={ "𑄱", "𑄧" }, + ["𑄯"]={ "𑄲", "𑄧" }, + ["𑍋"]={ "𑍇", "𑌾" }, + ["𑍌"]={ "𑍇", "𑍗" }, + ["𑒻"]={ "𑒹", "𑒺" }, + ["𑒼"]={ "𑒹", "𑒰" }, + ["𑒾"]={ "𑒹", "𑒽" }, + ["𑖺"]={ "𑖸", "𑖯" }, + ["𑖻"]={ "𑖹", "𑖯" }, + ["𝅗𝅥"]={ "𝅗", "𝅥" }, + ["𝅘𝅥"]={ "𝅘", "𝅥" }, + ["𝅘𝅥𝅮"]={ "𝅘𝅥", "𝅮" }, + ["𝅘𝅥𝅯"]={ "𝅘𝅥", "𝅯" }, + ["𝅘𝅥𝅰"]={ "𝅘𝅥", "𝅰" }, + ["𝅘𝅥𝅱"]={ "𝅘𝅥", "𝅱" }, + ["𝅘𝅥𝅲"]={ "𝅘𝅥", "𝅲" }, + ["𝆹𝅥"]={ "𝆹", "𝅥" }, + ["𝆺𝅥"]={ "𝆺", "𝅥" }, + ["𝆹𝅥𝅮"]={ "𝆹𝅥", "𝅮" }, + ["𝆺𝅥𝅮"]={ "𝆺𝅥", "𝅮" }, + ["𝆹𝅥𝅯"]={ "𝆹𝅥", "𝅯" }, + ["𝆺𝅥𝅯"]={ "𝆺𝅥", "𝅯" }, + }, + }, + { + ["data"]={ + ["À"]={ "A", "̀" }, + ["Á"]={ "A", "́" }, + ["Â"]={ "A", "̂" }, + ["Ã"]={ "A", "̃" }, + ["Ä"]={ "A", "̈" }, + ["Å"]={ "A", "̊" }, + ["Ç"]={ "C", "̧" }, + ["È"]={ "E", "̀" }, + ["É"]={ "E", "́" }, + ["Ê"]={ "E", "̂" }, + ["Ë"]={ "E", "̈" }, + ["Ì"]={ "I", "̀" }, + ["Í"]={ "I", "́" }, + ["Î"]={ "I", "̂" }, + ["Ï"]={ "I", "̈" }, + ["Ñ"]={ "N", "̃" }, + ["Ò"]={ "O", "̀" }, + ["Ó"]={ "O", "́" }, + ["Ô"]={ "O", "̂" }, + ["Õ"]={ "O", "̃" }, + ["Ö"]={ "O", "̈" }, + ["Ù"]={ "U", "̀" }, + ["Ú"]={ "U", "́" }, + ["Û"]={ "U", "̂" }, + ["Ü"]={ "U", "̈" }, + ["Ý"]={ "Y", "́" }, + ["à"]={ "a", "̀" }, + ["á"]={ "a", "́" }, + ["â"]={ "a", "̂" }, + ["ã"]={ "a", "̃" }, + ["ä"]={ "a", "̈" }, + ["å"]={ "a", "̊" }, + ["ç"]={ "c", "̧" }, + ["è"]={ "e", "̀" }, + ["é"]={ "e", "́" }, + ["ê"]={ "e", "̂" }, + ["ë"]={ "e", "̈" }, + ["ì"]={ "i", "̀" }, + ["í"]={ "i", "́" }, + ["î"]={ "i", "̂" }, + ["ï"]={ "i", "̈" }, + ["ñ"]={ "n", "̃" }, + ["ò"]={ "o", "̀" }, + ["ó"]={ "o", "́" }, + ["ô"]={ "o", "̂" }, + ["õ"]={ "o", "̃" }, + ["ö"]={ "o", "̈" }, + ["ù"]={ "u", "̀" }, + ["ú"]={ "u", "́" }, + ["û"]={ "u", "̂" }, + ["ü"]={ "u", "̈" }, + ["ý"]={ "y", "́" }, + ["ÿ"]={ "y", "̈" }, + ["Ā"]={ "A", "̄" }, + ["ā"]={ "a", "̄" }, + ["Ă"]={ "A", "̆" }, + ["ă"]={ "a", "̆" }, + ["Ą"]={ "A", "̨" }, + ["ą"]={ "a", "̨" }, + ["Ć"]={ "C", "́" }, + ["ć"]={ "c", "́" }, + ["Ĉ"]={ "C", "̂" }, + ["ĉ"]={ "c", "̂" }, + ["Ċ"]={ "C", "̇" }, + ["ċ"]={ "c", "̇" }, + ["Č"]={ "C", "̌" }, + ["č"]={ "c", "̌" }, + ["Ď"]={ "D", "̌" }, + ["ď"]={ "d", "̌" }, + ["Ē"]={ "E", "̄" }, + ["ē"]={ "e", "̄" }, + ["Ĕ"]={ "E", "̆" }, + ["ĕ"]={ "e", "̆" }, + ["Ė"]={ "E", "̇" }, + ["ė"]={ "e", "̇" }, + ["Ę"]={ "E", "̨" }, + ["ę"]={ "e", "̨" }, + ["Ě"]={ "E", "̌" }, + ["ě"]={ "e", "̌" }, + ["Ĝ"]={ "G", "̂" }, + ["ĝ"]={ "g", "̂" }, + ["Ğ"]={ "G", "̆" }, + ["ğ"]={ "g", "̆" }, + ["Ġ"]={ "G", "̇" }, + ["ġ"]={ "g", "̇" }, + ["Ģ"]={ "G", "̧" }, + ["ģ"]={ "g", "̧" }, + ["Ĥ"]={ "H", "̂" }, + ["ĥ"]={ "h", "̂" }, + ["Ĩ"]={ "I", "̃" }, + ["ĩ"]={ "i", "̃" }, + ["Ī"]={ "I", "̄" }, + ["ī"]={ "i", "̄" }, + ["Ĭ"]={ "I", "̆" }, + ["ĭ"]={ "i", "̆" }, + ["Į"]={ "I", "̨" }, + ["į"]={ "i", "̨" }, + ["İ"]={ "I", "̇" }, + ["Ĵ"]={ "J", "̂" }, + ["ĵ"]={ "j", "̂" }, + ["Ķ"]={ "K", "̧" }, + ["ķ"]={ "k", "̧" }, + ["Ĺ"]={ "L", "́" }, + ["ĺ"]={ "l", "́" }, + ["Ļ"]={ "L", "̧" }, + ["ļ"]={ "l", "̧" }, + ["Ľ"]={ "L", "̌" }, + ["ľ"]={ "l", "̌" }, + ["Ń"]={ "N", "́" }, + ["ń"]={ "n", "́" }, + ["Ņ"]={ "N", "̧" }, + ["ņ"]={ "n", "̧" }, + ["Ň"]={ "N", "̌" }, + ["ň"]={ "n", "̌" }, + ["Ō"]={ "O", "̄" }, + ["ō"]={ "o", "̄" }, + ["Ŏ"]={ "O", "̆" }, + ["ŏ"]={ "o", "̆" }, + ["Ő"]={ "O", "̋" }, + ["ő"]={ "o", "̋" }, + ["Ŕ"]={ "R", "́" }, + ["ŕ"]={ "r", "́" }, + ["Ŗ"]={ "R", "̧" }, + ["ŗ"]={ "r", "̧" }, + ["Ř"]={ "R", "̌" }, + ["ř"]={ "r", "̌" }, + ["Ś"]={ "S", "́" }, + ["ś"]={ "s", "́" }, + ["Ŝ"]={ "S", "̂" }, + ["ŝ"]={ "s", "̂" }, + ["Ş"]={ "S", "̧" }, + ["ş"]={ "s", "̧" }, + ["Š"]={ "S", "̌" }, + ["š"]={ "s", "̌" }, + ["Ţ"]={ "T", "̧" }, + ["ţ"]={ "t", "̧" }, + ["Ť"]={ "T", "̌" }, + ["ť"]={ "t", "̌" }, + ["Ũ"]={ "U", "̃" }, + ["ũ"]={ "u", "̃" }, + ["Ū"]={ "U", "̄" }, + ["ū"]={ "u", "̄" }, + ["Ŭ"]={ "U", "̆" }, + ["ŭ"]={ "u", "̆" }, + ["Ů"]={ "U", "̊" }, + ["ů"]={ "u", "̊" }, + ["Ű"]={ "U", "̋" }, + ["ű"]={ "u", "̋" }, + ["Ų"]={ "U", "̨" }, + ["ų"]={ "u", "̨" }, + ["Ŵ"]={ "W", "̂" }, + ["ŵ"]={ "w", "̂" }, + ["Ŷ"]={ "Y", "̂" }, + ["ŷ"]={ "y", "̂" }, + ["Ÿ"]={ "Y", "̈" }, + ["Ź"]={ "Z", "́" }, + ["ź"]={ "z", "́" }, + ["Ż"]={ "Z", "̇" }, + ["ż"]={ "z", "̇" }, + ["Ž"]={ "Z", "̌" }, + ["ž"]={ "z", "̌" }, + ["Ơ"]={ "O", "̛" }, + ["ơ"]={ "o", "̛" }, + ["Ư"]={ "U", "̛" }, + ["ư"]={ "u", "̛" }, + ["Ǎ"]={ "A", "̌" }, + ["ǎ"]={ "a", "̌" }, + ["Ǐ"]={ "I", "̌" }, + ["ǐ"]={ "i", "̌" }, + ["Ǒ"]={ "O", "̌" }, + ["ǒ"]={ "o", "̌" }, + ["Ǔ"]={ "U", "̌" }, + ["ǔ"]={ "u", "̌" }, + ["Ǖ"]={ "Ü", "̄" }, + ["ǖ"]={ "ü", "̄" }, + ["Ǘ"]={ "Ü", "́" }, + ["ǘ"]={ "ü", "́" }, + ["Ǚ"]={ "Ü", "̌" }, + ["ǚ"]={ "ü", "̌" }, + ["Ǜ"]={ "Ü", "̀" }, + ["ǜ"]={ "ü", "̀" }, + ["Ǟ"]={ "Ä", "̄" }, + ["ǟ"]={ "ä", "̄" }, + ["Ǡ"]={ "Ȧ", "̄" }, + ["ǡ"]={ "ȧ", "̄" }, + ["Ǣ"]={ "Æ", "̄" }, + ["ǣ"]={ "æ", "̄" }, + ["Ǧ"]={ "G", "̌" }, + ["ǧ"]={ "g", "̌" }, + ["Ǩ"]={ "K", "̌" }, + ["ǩ"]={ "k", "̌" }, + ["Ǫ"]={ "O", "̨" }, + ["ǫ"]={ "o", "̨" }, + ["Ǭ"]={ "Ǫ", "̄" }, + ["ǭ"]={ "ǫ", "̄" }, + ["Ǯ"]={ "Ʒ", "̌" }, + ["ǯ"]={ "ʒ", "̌" }, + ["ǰ"]={ "j", "̌" }, + ["Ǵ"]={ "G", "́" }, + ["ǵ"]={ "g", "́" }, + ["Ǹ"]={ "N", "̀" }, + ["ǹ"]={ "n", "̀" }, + ["Ǻ"]={ "Å", "́" }, + ["ǻ"]={ "å", "́" }, + ["Ǽ"]={ "Æ", "́" }, + ["ǽ"]={ "æ", "́" }, + ["Ǿ"]={ "Ø", "́" }, + ["ǿ"]={ "ø", "́" }, + ["Ȁ"]={ "A", "̏" }, + ["ȁ"]={ "a", "̏" }, + ["Ȃ"]={ "A", "̑" }, + ["ȃ"]={ "a", "̑" }, + ["Ȅ"]={ "E", "̏" }, + ["ȅ"]={ "e", "̏" }, + ["Ȇ"]={ "E", "̑" }, + ["ȇ"]={ "e", "̑" }, + ["Ȉ"]={ "I", "̏" }, + ["ȉ"]={ "i", "̏" }, + ["Ȋ"]={ "I", "̑" }, + ["ȋ"]={ "i", "̑" }, + ["Ȍ"]={ "O", "̏" }, + ["ȍ"]={ "o", "̏" }, + ["Ȏ"]={ "O", "̑" }, + ["ȏ"]={ "o", "̑" }, + ["Ȑ"]={ "R", "̏" }, + ["ȑ"]={ "r", "̏" }, + ["Ȓ"]={ "R", "̑" }, + ["ȓ"]={ "r", "̑" }, + ["Ȕ"]={ "U", "̏" }, + ["ȕ"]={ "u", "̏" }, + ["Ȗ"]={ "U", "̑" }, + ["ȗ"]={ "u", "̑" }, + ["Ș"]={ "S", "̦" }, + ["ș"]={ "s", "̦" }, + ["Ț"]={ "T", "̦" }, + ["ț"]={ "t", "̦" }, + ["Ȟ"]={ "H", "̌" }, + ["ȟ"]={ "h", "̌" }, + ["Ȧ"]={ "A", "̇" }, + ["ȧ"]={ "a", "̇" }, + ["Ȩ"]={ "E", "̧" }, + ["ȩ"]={ "e", "̧" }, + ["Ȫ"]={ "Ö", "̄" }, + ["ȫ"]={ "ö", "̄" }, + ["Ȭ"]={ "Õ", "̄" }, + ["ȭ"]={ "õ", "̄" }, + ["Ȯ"]={ "O", "̇" }, + ["ȯ"]={ "o", "̇" }, + ["Ȱ"]={ "Ȯ", "̄" }, + ["ȱ"]={ "ȯ", "̄" }, + ["Ȳ"]={ "Y", "̄" }, + ["ȳ"]={ "y", "̄" }, + ["̈́"]={ "̈", "́" }, + ["΅"]={ "¨", "́" }, + ["Ά"]={ "Α", "́" }, + ["Έ"]={ "Ε", "́" }, + ["Ή"]={ "Η", "́" }, + ["Ί"]={ "Ι", "́" }, + ["Ό"]={ "Ο", "́" }, + ["Ύ"]={ "Υ", "́" }, + ["Ώ"]={ "Ω", "́" }, + ["ΐ"]={ "ϊ", "́" }, + ["Ϊ"]={ "Ι", "̈" }, + ["Ϋ"]={ "Υ", "̈" }, + ["ά"]={ "α", "́" }, + ["έ"]={ "ε", "́" }, + ["ή"]={ "η", "́" }, + ["ί"]={ "ι", "́" }, + ["ΰ"]={ "ϋ", "́" }, + ["ϊ"]={ "ι", "̈" }, + ["ϋ"]={ "υ", "̈" }, + ["ό"]={ "ο", "́" }, + ["ύ"]={ "υ", "́" }, + ["ώ"]={ "ω", "́" }, + ["ϓ"]={ "ϒ", "́" }, + ["ϔ"]={ "ϒ", "̈" }, + ["Ѐ"]={ "Е", "̀" }, + ["Ё"]={ "Е", "̈" }, + ["Ѓ"]={ "Г", "́" }, + ["Ї"]={ "І", "̈" }, + ["Ќ"]={ "К", "́" }, + ["Ѝ"]={ "И", "̀" }, + ["Ў"]={ "У", "̆" }, + ["Й"]={ "И", "̆" }, + ["й"]={ "и", "̆" }, + ["ѐ"]={ "е", "̀" }, + ["ё"]={ "е", "̈" }, + ["ѓ"]={ "г", "́" }, + ["ї"]={ "і", "̈" }, + ["ќ"]={ "к", "́" }, + ["ѝ"]={ "и", "̀" }, + ["ў"]={ "у", "̆" }, + ["Ѷ"]={ "Ѵ", "̏" }, + ["ѷ"]={ "ѵ", "̏" }, + ["Ӂ"]={ "Ж", "̆" }, + ["ӂ"]={ "ж", "̆" }, + ["Ӑ"]={ "А", "̆" }, + ["ӑ"]={ "а", "̆" }, + ["Ӓ"]={ "А", "̈" }, + ["ӓ"]={ "а", "̈" }, + ["Ӗ"]={ "Е", "̆" }, + ["ӗ"]={ "е", "̆" }, + ["Ӛ"]={ "Ә", "̈" }, + ["ӛ"]={ "ә", "̈" }, + ["Ӝ"]={ "Ж", "̈" }, + ["ӝ"]={ "ж", "̈" }, + ["Ӟ"]={ "З", "̈" }, + ["ӟ"]={ "з", "̈" }, + ["Ӣ"]={ "И", "̄" }, + ["ӣ"]={ "и", "̄" }, + ["Ӥ"]={ "И", "̈" }, + ["ӥ"]={ "и", "̈" }, + ["Ӧ"]={ "О", "̈" }, + ["ӧ"]={ "о", "̈" }, + ["Ӫ"]={ "Ө", "̈" }, + ["ӫ"]={ "ө", "̈" }, + ["Ӭ"]={ "Э", "̈" }, + ["ӭ"]={ "э", "̈" }, + ["Ӯ"]={ "У", "̄" }, + ["ӯ"]={ "у", "̄" }, + ["Ӱ"]={ "У", "̈" }, + ["ӱ"]={ "у", "̈" }, + ["Ӳ"]={ "У", "̋" }, + ["ӳ"]={ "у", "̋" }, + ["Ӵ"]={ "Ч", "̈" }, + ["ӵ"]={ "ч", "̈" }, + ["Ӹ"]={ "Ы", "̈" }, + ["ӹ"]={ "ы", "̈" }, + ["آ"]={ "ا", "ٓ" }, + ["أ"]={ "ا", "ٔ" }, + ["ؤ"]={ "و", "ٔ" }, + ["إ"]={ "ا", "ٕ" }, + ["ئ"]={ "ي", "ٔ" }, + ["ۀ"]={ "ە", "ٔ" }, + ["ۂ"]={ "ہ", "ٔ" }, + ["ۓ"]={ "ے", "ٔ" }, + ["ऩ"]={ "न", "़" }, + ["ऱ"]={ "र", "़" }, + ["ऴ"]={ "ळ", "़" }, + ["क़"]={ "क", "़" }, + ["ख़"]={ "ख", "़" }, + ["ग़"]={ "ग", "़" }, + ["ज़"]={ "ज", "़" }, + ["ड़"]={ "ड", "़" }, + ["ढ़"]={ "ढ", "़" }, + ["फ़"]={ "फ", "़" }, + ["य़"]={ "य", "़" }, + ["ো"]={ "ে", "া" }, + ["ৌ"]={ "ে", "ৗ" }, + ["ড়"]={ "ড", "়" }, + ["ঢ়"]={ "ঢ", "়" }, + ["য়"]={ "য", "়" }, + ["ਲ਼"]={ "ਲ", "਼" }, + ["ਸ਼"]={ "ਸ", "਼" }, + ["ਖ਼"]={ "ਖ", "਼" }, + ["ਗ਼"]={ "ਗ", "਼" }, + ["ਜ਼"]={ "ਜ", "਼" }, + ["ਫ਼"]={ "ਫ", "਼" }, + ["ୈ"]={ "େ", "ୖ" }, + ["ୋ"]={ "େ", "ା" }, + ["ୌ"]={ "େ", "ୗ" }, + ["ଡ଼"]={ "ଡ", "଼" }, + ["ଢ଼"]={ "ଢ", "଼" }, + ["ஔ"]={ "ஒ", "ௗ" }, + ["ொ"]={ "ெ", "ா" }, + ["ோ"]={ "ே", "ா" }, + ["ௌ"]={ "ெ", "ௗ" }, + ["ై"]={ "ె", "ౖ" }, + ["ೀ"]={ "ಿ", "ೕ" }, + ["ೇ"]={ "ೆ", "ೕ" }, + ["ೈ"]={ "ೆ", "ೖ" }, + ["ೊ"]={ "ೆ", "ೂ" }, + ["ೋ"]={ "ೊ", "ೕ" }, + ["ൊ"]={ "െ", "ാ" }, + ["ോ"]={ "േ", "ാ" }, + ["ൌ"]={ "െ", "ൗ" }, + ["ේ"]={ "ෙ", "්" }, + ["ො"]={ "ෙ", "ා" }, + ["ෝ"]={ "ො", "්" }, + ["ෞ"]={ "ෙ", "ෟ" }, + ["གྷ"]={ "ག", "ྷ" }, + ["ཌྷ"]={ "ཌ", "ྷ" }, + ["དྷ"]={ "ད", "ྷ" }, + ["བྷ"]={ "བ", "ྷ" }, + ["ཛྷ"]={ "ཛ", "ྷ" }, + ["ཀྵ"]={ "ཀ", "ྵ" }, + ["ཱི"]={ "ཱ", "ི" }, + ["ཱུ"]={ "ཱ", "ུ" }, + ["ྲྀ"]={ "ྲ", "ྀ" }, + ["ླྀ"]={ "ླ", "ྀ" }, + ["ཱྀ"]={ "ཱ", "ྀ" }, + ["ྒྷ"]={ "ྒ", "ྷ" }, + ["ྜྷ"]={ "ྜ", "ྷ" }, + ["ྡྷ"]={ "ྡ", "ྷ" }, + ["ྦྷ"]={ "ྦ", "ྷ" }, + ["ྫྷ"]={ "ྫ", "ྷ" }, + ["ྐྵ"]={ "ྐ", "ྵ" }, + ["ဦ"]={ "ဥ", "ီ" }, + ["ᬆ"]={ "ᬅ", "ᬵ" }, + ["ᬈ"]={ "ᬇ", "ᬵ" }, + ["ᬊ"]={ "ᬉ", "ᬵ" }, + ["ᬌ"]={ "ᬋ", "ᬵ" }, + ["ᬎ"]={ "ᬍ", "ᬵ" }, + ["ᬒ"]={ "ᬑ", "ᬵ" }, + ["ᬻ"]={ "ᬺ", "ᬵ" }, + ["ᬽ"]={ "ᬼ", "ᬵ" }, + ["ᭀ"]={ "ᬾ", "ᬵ" }, + ["ᭁ"]={ "ᬿ", "ᬵ" }, + ["ᭃ"]={ "ᭂ", "ᬵ" }, + ["Ḁ"]={ "A", "̥" }, + ["ḁ"]={ "a", "̥" }, + ["Ḃ"]={ "B", "̇" }, + ["ḃ"]={ "b", "̇" }, + ["Ḅ"]={ "B", "̣" }, + ["ḅ"]={ "b", "̣" }, + ["Ḇ"]={ "B", "̱" }, + ["ḇ"]={ "b", "̱" }, + ["Ḉ"]={ "Ç", "́" }, + ["ḉ"]={ "ç", "́" }, + ["Ḋ"]={ "D", "̇" }, + ["ḋ"]={ "d", "̇" }, + ["Ḍ"]={ "D", "̣" }, + ["ḍ"]={ "d", "̣" }, + ["Ḏ"]={ "D", "̱" }, + ["ḏ"]={ "d", "̱" }, + ["Ḑ"]={ "D", "̧" }, + ["ḑ"]={ "d", "̧" }, + ["Ḓ"]={ "D", "̭" }, + ["ḓ"]={ "d", "̭" }, + ["Ḕ"]={ "Ē", "̀" }, + ["ḕ"]={ "ē", "̀" }, + ["Ḗ"]={ "Ē", "́" }, + ["ḗ"]={ "ē", "́" }, + ["Ḙ"]={ "E", "̭" }, + ["ḙ"]={ "e", "̭" }, + ["Ḛ"]={ "E", "̰" }, + ["ḛ"]={ "e", "̰" }, + ["Ḝ"]={ "Ȩ", "̆" }, + ["ḝ"]={ "ȩ", "̆" }, + ["Ḟ"]={ "F", "̇" }, + ["ḟ"]={ "f", "̇" }, + ["Ḡ"]={ "G", "̄" }, + ["ḡ"]={ "g", "̄" }, + ["Ḣ"]={ "H", "̇" }, + ["ḣ"]={ "h", "̇" }, + ["Ḥ"]={ "H", "̣" }, + ["ḥ"]={ "h", "̣" }, + ["Ḧ"]={ "H", "̈" }, + ["ḧ"]={ "h", "̈" }, + ["Ḩ"]={ "H", "̧" }, + ["ḩ"]={ "h", "̧" }, + ["Ḫ"]={ "H", "̮" }, + ["ḫ"]={ "h", "̮" }, + ["Ḭ"]={ "I", "̰" }, + ["ḭ"]={ "i", "̰" }, + ["Ḯ"]={ "Ï", "́" }, + ["ḯ"]={ "ï", "́" }, + ["Ḱ"]={ "K", "́" }, + ["ḱ"]={ "k", "́" }, + ["Ḳ"]={ "K", "̣" }, + ["ḳ"]={ "k", "̣" }, + ["Ḵ"]={ "K", "̱" }, + ["ḵ"]={ "k", "̱" }, + ["Ḷ"]={ "L", "̣" }, + ["ḷ"]={ "l", "̣" }, + ["Ḹ"]={ "Ḷ", "̄" }, + ["ḹ"]={ "ḷ", "̄" }, + ["Ḻ"]={ "L", "̱" }, + ["ḻ"]={ "l", "̱" }, + ["Ḽ"]={ "L", "̭" }, + ["ḽ"]={ "l", "̭" }, + ["Ḿ"]={ "M", "́" }, + ["ḿ"]={ "m", "́" }, + ["Ṁ"]={ "M", "̇" }, + ["ṁ"]={ "m", "̇" }, + ["Ṃ"]={ "M", "̣" }, + ["ṃ"]={ "m", "̣" }, + ["Ṅ"]={ "N", "̇" }, + ["ṅ"]={ "n", "̇" }, + ["Ṇ"]={ "N", "̣" }, + ["ṇ"]={ "n", "̣" }, + ["Ṉ"]={ "N", "̱" }, + ["ṉ"]={ "n", "̱" }, + ["Ṋ"]={ "N", "̭" }, + ["ṋ"]={ "n", "̭" }, + ["Ṍ"]={ "Õ", "́" }, + ["ṍ"]={ "õ", "́" }, + ["Ṏ"]={ "Õ", "̈" }, + ["ṏ"]={ "õ", "̈" }, + ["Ṑ"]={ "Ō", "̀" }, + ["ṑ"]={ "ō", "̀" }, + ["Ṓ"]={ "Ō", "́" }, + ["ṓ"]={ "ō", "́" }, + ["Ṕ"]={ "P", "́" }, + ["ṕ"]={ "p", "́" }, + ["Ṗ"]={ "P", "̇" }, + ["ṗ"]={ "p", "̇" }, + ["Ṙ"]={ "R", "̇" }, + ["ṙ"]={ "r", "̇" }, + ["Ṛ"]={ "R", "̣" }, + ["ṛ"]={ "r", "̣" }, + ["Ṝ"]={ "Ṛ", "̄" }, + ["ṝ"]={ "ṛ", "̄" }, + ["Ṟ"]={ "R", "̱" }, + ["ṟ"]={ "r", "̱" }, + ["Ṡ"]={ "S", "̇" }, + ["ṡ"]={ "s", "̇" }, + ["Ṣ"]={ "S", "̣" }, + ["ṣ"]={ "s", "̣" }, + ["Ṥ"]={ "Ś", "̇" }, + ["ṥ"]={ "ś", "̇" }, + ["Ṧ"]={ "Š", "̇" }, + ["ṧ"]={ "š", "̇" }, + ["Ṩ"]={ "Ṣ", "̇" }, + ["ṩ"]={ "ṣ", "̇" }, + ["Ṫ"]={ "T", "̇" }, + ["ṫ"]={ "t", "̇" }, + ["Ṭ"]={ "T", "̣" }, + ["ṭ"]={ "t", "̣" }, + ["Ṯ"]={ "T", "̱" }, + ["ṯ"]={ "t", "̱" }, + ["Ṱ"]={ "T", "̭" }, + ["ṱ"]={ "t", "̭" }, + ["Ṳ"]={ "U", "̤" }, + ["ṳ"]={ "u", "̤" }, + ["Ṵ"]={ "U", "̰" }, + ["ṵ"]={ "u", "̰" }, + ["Ṷ"]={ "U", "̭" }, + ["ṷ"]={ "u", "̭" }, + ["Ṹ"]={ "Ũ", "́" }, + ["ṹ"]={ "ũ", "́" }, + ["Ṻ"]={ "Ū", "̈" }, + ["ṻ"]={ "ū", "̈" }, + ["Ṽ"]={ "V", "̃" }, + ["ṽ"]={ "v", "̃" }, + ["Ṿ"]={ "V", "̣" }, + ["ṿ"]={ "v", "̣" }, + ["Ẁ"]={ "W", "̀" }, + ["ẁ"]={ "w", "̀" }, + ["Ẃ"]={ "W", "́" }, + ["ẃ"]={ "w", "́" }, + ["Ẅ"]={ "W", "̈" }, + ["ẅ"]={ "w", "̈" }, + ["Ẇ"]={ "W", "̇" }, + ["ẇ"]={ "w", "̇" }, + ["Ẉ"]={ "W", "̣" }, + ["ẉ"]={ "w", "̣" }, + ["Ẋ"]={ "X", "̇" }, + ["ẋ"]={ "x", "̇" }, + ["Ẍ"]={ "X", "̈" }, + ["ẍ"]={ "x", "̈" }, + ["Ẏ"]={ "Y", "̇" }, + ["ẏ"]={ "y", "̇" }, + ["Ẑ"]={ "Z", "̂" }, + ["ẑ"]={ "z", "̂" }, + ["Ẓ"]={ "Z", "̣" }, + ["ẓ"]={ "z", "̣" }, + ["Ẕ"]={ "Z", "̱" }, + ["ẕ"]={ "z", "̱" }, + ["ẖ"]={ "h", "̱" }, + ["ẗ"]={ "t", "̈" }, + ["ẘ"]={ "w", "̊" }, + ["ẙ"]={ "y", "̊" }, + ["ẛ"]={ "ſ", "̇" }, + ["Ạ"]={ "A", "̣" }, + ["ạ"]={ "a", "̣" }, + ["Ả"]={ "A", "̉" }, + ["ả"]={ "a", "̉" }, + ["Ấ"]={ "Â", "́" }, + ["ấ"]={ "â", "́" }, + ["Ầ"]={ "Â", "̀" }, + ["ầ"]={ "â", "̀" }, + ["Ẩ"]={ "Â", "̉" }, + ["ẩ"]={ "â", "̉" }, + ["Ẫ"]={ "Â", "̃" }, + ["ẫ"]={ "â", "̃" }, + ["Ậ"]={ "Ạ", "̂" }, + ["ậ"]={ "ạ", "̂" }, + ["Ắ"]={ "Ă", "́" }, + ["ắ"]={ "ă", "́" }, + ["Ằ"]={ "Ă", "̀" }, + ["ằ"]={ "ă", "̀" }, + ["Ẳ"]={ "Ă", "̉" }, + ["ẳ"]={ "ă", "̉" }, + ["Ẵ"]={ "Ă", "̃" }, + ["ẵ"]={ "ă", "̃" }, + ["Ặ"]={ "Ạ", "̆" }, + ["ặ"]={ "ạ", "̆" }, + ["Ẹ"]={ "E", "̣" }, + ["ẹ"]={ "e", "̣" }, + ["Ẻ"]={ "E", "̉" }, + ["ẻ"]={ "e", "̉" }, + ["Ẽ"]={ "E", "̃" }, + ["ẽ"]={ "e", "̃" }, + ["Ế"]={ "Ê", "́" }, + ["ế"]={ "ê", "́" }, + ["Ề"]={ "Ê", "̀" }, + ["ề"]={ "ê", "̀" }, + ["Ể"]={ "Ê", "̉" }, + ["ể"]={ "ê", "̉" }, + ["Ễ"]={ "Ê", "̃" }, + ["ễ"]={ "ê", "̃" }, + ["Ệ"]={ "Ẹ", "̂" }, + ["ệ"]={ "ẹ", "̂" }, + ["Ỉ"]={ "I", "̉" }, + ["ỉ"]={ "i", "̉" }, + ["Ị"]={ "I", "̣" }, + ["ị"]={ "i", "̣" }, + ["Ọ"]={ "O", "̣" }, + ["ọ"]={ "o", "̣" }, + ["Ỏ"]={ "O", "̉" }, + ["ỏ"]={ "o", "̉" }, + ["Ố"]={ "Ô", "́" }, + ["ố"]={ "ô", "́" }, + ["Ồ"]={ "Ô", "̀" }, + ["ồ"]={ "ô", "̀" }, + ["Ổ"]={ "Ô", "̉" }, + ["ổ"]={ "ô", "̉" }, + ["Ỗ"]={ "Ô", "̃" }, + ["ỗ"]={ "ô", "̃" }, + ["Ộ"]={ "Ọ", "̂" }, + ["ộ"]={ "ọ", "̂" }, + ["Ớ"]={ "Ơ", "́" }, + ["ớ"]={ "ơ", "́" }, + ["Ờ"]={ "Ơ", "̀" }, + ["ờ"]={ "ơ", "̀" }, + ["Ở"]={ "Ơ", "̉" }, + ["ở"]={ "ơ", "̉" }, + ["Ỡ"]={ "Ơ", "̃" }, + ["ỡ"]={ "ơ", "̃" }, + ["Ợ"]={ "Ơ", "̣" }, + ["ợ"]={ "ơ", "̣" }, + ["Ụ"]={ "U", "̣" }, + ["ụ"]={ "u", "̣" }, + ["Ủ"]={ "U", "̉" }, + ["ủ"]={ "u", "̉" }, + ["Ứ"]={ "Ư", "́" }, + ["ứ"]={ "ư", "́" }, + ["Ừ"]={ "Ư", "̀" }, + ["ừ"]={ "ư", "̀" }, + ["Ử"]={ "Ư", "̉" }, + ["ử"]={ "ư", "̉" }, + ["Ữ"]={ "Ư", "̃" }, + ["ữ"]={ "ư", "̃" }, + ["Ự"]={ "Ư", "̣" }, + ["ự"]={ "ư", "̣" }, + ["Ỳ"]={ "Y", "̀" }, + ["ỳ"]={ "y", "̀" }, + ["Ỵ"]={ "Y", "̣" }, + ["ỵ"]={ "y", "̣" }, + ["Ỷ"]={ "Y", "̉" }, + ["ỷ"]={ "y", "̉" }, + ["Ỹ"]={ "Y", "̃" }, + ["ỹ"]={ "y", "̃" }, + ["ἀ"]={ "α", "̓" }, + ["ἁ"]={ "α", "̔" }, + ["ἂ"]={ "ἀ", "̀" }, + ["ἃ"]={ "ἁ", "̀" }, + ["ἄ"]={ "ἀ", "́" }, + ["ἅ"]={ "ἁ", "́" }, + ["ἆ"]={ "ἀ", "͂" }, + ["ἇ"]={ "ἁ", "͂" }, + ["Ἀ"]={ "Α", "̓" }, + ["Ἁ"]={ "Α", "̔" }, + ["Ἂ"]={ "Ἀ", "̀" }, + ["Ἃ"]={ "Ἁ", "̀" }, + ["Ἄ"]={ "Ἀ", "́" }, + ["Ἅ"]={ "Ἁ", "́" }, + ["Ἆ"]={ "Ἀ", "͂" }, + ["Ἇ"]={ "Ἁ", "͂" }, + ["ἐ"]={ "ε", "̓" }, + ["ἑ"]={ "ε", "̔" }, + ["ἒ"]={ "ἐ", "̀" }, + ["ἓ"]={ "ἑ", "̀" }, + ["ἔ"]={ "ἐ", "́" }, + ["ἕ"]={ "ἑ", "́" }, + ["Ἐ"]={ "Ε", "̓" }, + ["Ἑ"]={ "Ε", "̔" }, + ["Ἒ"]={ "Ἐ", "̀" }, + ["Ἓ"]={ "Ἑ", "̀" }, + ["Ἔ"]={ "Ἐ", "́" }, + ["Ἕ"]={ "Ἑ", "́" }, + ["ἠ"]={ "η", "̓" }, + ["ἡ"]={ "η", "̔" }, + ["ἢ"]={ "ἠ", "̀" }, + ["ἣ"]={ "ἡ", "̀" }, + ["ἤ"]={ "ἠ", "́" }, + ["ἥ"]={ "ἡ", "́" }, + ["ἦ"]={ "ἠ", "͂" }, + ["ἧ"]={ "ἡ", "͂" }, + ["Ἠ"]={ "Η", "̓" }, + ["Ἡ"]={ "Η", "̔" }, + ["Ἢ"]={ "Ἠ", "̀" }, + ["Ἣ"]={ "Ἡ", "̀" }, + ["Ἤ"]={ "Ἠ", "́" }, + ["Ἥ"]={ "Ἡ", "́" }, + ["Ἦ"]={ "Ἠ", "͂" }, + ["Ἧ"]={ "Ἡ", "͂" }, + ["ἰ"]={ "ι", "̓" }, + ["ἱ"]={ "ι", "̔" }, + ["ἲ"]={ "ἰ", "̀" }, + ["ἳ"]={ "ἱ", "̀" }, + ["ἴ"]={ "ἰ", "́" }, + ["ἵ"]={ "ἱ", "́" }, + ["ἶ"]={ "ἰ", "͂" }, + ["ἷ"]={ "ἱ", "͂" }, + ["Ἰ"]={ "Ι", "̓" }, + ["Ἱ"]={ "Ι", "̔" }, + ["Ἲ"]={ "Ἰ", "̀" }, + ["Ἳ"]={ "Ἱ", "̀" }, + ["Ἴ"]={ "Ἰ", "́" }, + ["Ἵ"]={ "Ἱ", "́" }, + ["Ἶ"]={ "Ἰ", "͂" }, + ["Ἷ"]={ "Ἱ", "͂" }, + ["ὀ"]={ "ο", "̓" }, + ["ὁ"]={ "ο", "̔" }, + ["ὂ"]={ "ὀ", "̀" }, + ["ὃ"]={ "ὁ", "̀" }, + ["ὄ"]={ "ὀ", "́" }, + ["ὅ"]={ "ὁ", "́" }, + ["Ὀ"]={ "Ο", "̓" }, + ["Ὁ"]={ "Ο", "̔" }, + ["Ὂ"]={ "Ὀ", "̀" }, + ["Ὃ"]={ "Ὁ", "̀" }, + ["Ὄ"]={ "Ὀ", "́" }, + ["Ὅ"]={ "Ὁ", "́" }, + ["ὐ"]={ "υ", "̓" }, + ["ὑ"]={ "υ", "̔" }, + ["ὒ"]={ "ὐ", "̀" }, + ["ὓ"]={ "ὑ", "̀" }, + ["ὔ"]={ "ὐ", "́" }, + ["ὕ"]={ "ὑ", "́" }, + ["ὖ"]={ "ὐ", "͂" }, + ["ὗ"]={ "ὑ", "͂" }, + ["Ὑ"]={ "Υ", "̔" }, + ["Ὓ"]={ "Ὑ", "̀" }, + ["Ὕ"]={ "Ὑ", "́" }, + ["Ὗ"]={ "Ὑ", "͂" }, + ["ὠ"]={ "ω", "̓" }, + ["ὡ"]={ "ω", "̔" }, + ["ὢ"]={ "ὠ", "̀" }, + ["ὣ"]={ "ὡ", "̀" }, + ["ὤ"]={ "ὠ", "́" }, + ["ὥ"]={ "ὡ", "́" }, + ["ὦ"]={ "ὠ", "͂" }, + ["ὧ"]={ "ὡ", "͂" }, + ["Ὠ"]={ "Ω", "̓" }, + ["Ὡ"]={ "Ω", "̔" }, + ["Ὢ"]={ "Ὠ", "̀" }, + ["Ὣ"]={ "Ὡ", "̀" }, + ["Ὤ"]={ "Ὠ", "́" }, + ["Ὥ"]={ "Ὡ", "́" }, + ["Ὦ"]={ "Ὠ", "͂" }, + ["Ὧ"]={ "Ὡ", "͂" }, + ["ὰ"]={ "α", "̀" }, + ["ὲ"]={ "ε", "̀" }, + ["ὴ"]={ "η", "̀" }, + ["ὶ"]={ "ι", "̀" }, + ["ὸ"]={ "ο", "̀" }, + ["ὺ"]={ "υ", "̀" }, + ["ὼ"]={ "ω", "̀" }, + ["ᾀ"]={ "ἀ", "ͅ" }, + ["ᾁ"]={ "ἁ", "ͅ" }, + ["ᾂ"]={ "ἂ", "ͅ" }, + ["ᾃ"]={ "ἃ", "ͅ" }, + ["ᾄ"]={ "ἄ", "ͅ" }, + ["ᾅ"]={ "ἅ", "ͅ" }, + ["ᾆ"]={ "ἆ", "ͅ" }, + ["ᾇ"]={ "ἇ", "ͅ" }, + ["ᾈ"]={ "Ἀ", "ͅ" }, + ["ᾉ"]={ "Ἁ", "ͅ" }, + ["ᾊ"]={ "Ἂ", "ͅ" }, + ["ᾋ"]={ "Ἃ", "ͅ" }, + ["ᾌ"]={ "Ἄ", "ͅ" }, + ["ᾍ"]={ "Ἅ", "ͅ" }, + ["ᾎ"]={ "Ἆ", "ͅ" }, + ["ᾏ"]={ "Ἇ", "ͅ" }, + ["ᾐ"]={ "ἠ", "ͅ" }, + ["ᾑ"]={ "ἡ", "ͅ" }, + ["ᾒ"]={ "ἢ", "ͅ" }, + ["ᾓ"]={ "ἣ", "ͅ" }, + ["ᾔ"]={ "ἤ", "ͅ" }, + ["ᾕ"]={ "ἥ", "ͅ" }, + ["ᾖ"]={ "ἦ", "ͅ" }, + ["ᾗ"]={ "ἧ", "ͅ" }, + ["ᾘ"]={ "Ἠ", "ͅ" }, + ["ᾙ"]={ "Ἡ", "ͅ" }, + ["ᾚ"]={ "Ἢ", "ͅ" }, + ["ᾛ"]={ "Ἣ", "ͅ" }, + ["ᾜ"]={ "Ἤ", "ͅ" }, + ["ᾝ"]={ "Ἥ", "ͅ" }, + ["ᾞ"]={ "Ἦ", "ͅ" }, + ["ᾟ"]={ "Ἧ", "ͅ" }, + ["ᾠ"]={ "ὠ", "ͅ" }, + ["ᾡ"]={ "ὡ", "ͅ" }, + ["ᾢ"]={ "ὢ", "ͅ" }, + ["ᾣ"]={ "ὣ", "ͅ" }, + ["ᾤ"]={ "ὤ", "ͅ" }, + ["ᾥ"]={ "ὥ", "ͅ" }, + ["ᾦ"]={ "ὦ", "ͅ" }, + ["ᾧ"]={ "ὧ", "ͅ" }, + ["ᾨ"]={ "Ὠ", "ͅ" }, + ["ᾩ"]={ "Ὡ", "ͅ" }, + ["ᾪ"]={ "Ὢ", "ͅ" }, + ["ᾫ"]={ "Ὣ", "ͅ" }, + ["ᾬ"]={ "Ὤ", "ͅ" }, + ["ᾭ"]={ "Ὥ", "ͅ" }, + ["ᾮ"]={ "Ὦ", "ͅ" }, + ["ᾯ"]={ "Ὧ", "ͅ" }, + ["ᾰ"]={ "α", "̆" }, + ["ᾱ"]={ "α", "̄" }, + ["ᾲ"]={ "ὰ", "ͅ" }, + ["ᾳ"]={ "α", "ͅ" }, + ["ᾴ"]={ "ά", "ͅ" }, + ["ᾶ"]={ "α", "͂" }, + ["ᾷ"]={ "ᾶ", "ͅ" }, + ["Ᾰ"]={ "Α", "̆" }, + ["Ᾱ"]={ "Α", "̄" }, + ["Ὰ"]={ "Α", "̀" }, + ["ᾼ"]={ "Α", "ͅ" }, + ["῁"]={ "¨", "͂" }, + ["ῂ"]={ "ὴ", "ͅ" }, + ["ῃ"]={ "η", "ͅ" }, + ["ῄ"]={ "ή", "ͅ" }, + ["ῆ"]={ "η", "͂" }, + ["ῇ"]={ "ῆ", "ͅ" }, + ["Ὲ"]={ "Ε", "̀" }, + ["Ὴ"]={ "Η", "̀" }, + ["ῌ"]={ "Η", "ͅ" }, + ["῍"]={ "᾿", "̀" }, + ["῎"]={ "᾿", "́" }, + ["῏"]={ "᾿", "͂" }, + ["ῐ"]={ "ι", "̆" }, + ["ῑ"]={ "ι", "̄" }, + ["ῒ"]={ "ϊ", "̀" }, + ["ῖ"]={ "ι", "͂" }, + ["ῗ"]={ "ϊ", "͂" }, + ["Ῐ"]={ "Ι", "̆" }, + ["Ῑ"]={ "Ι", "̄" }, + ["Ὶ"]={ "Ι", "̀" }, + ["῝"]={ "῾", "̀" }, + ["῞"]={ "῾", "́" }, + ["῟"]={ "῾", "͂" }, + ["ῠ"]={ "υ", "̆" }, + ["ῡ"]={ "υ", "̄" }, + ["ῢ"]={ "ϋ", "̀" }, + ["ῤ"]={ "ρ", "̓" }, + ["ῥ"]={ "ρ", "̔" }, + ["ῦ"]={ "υ", "͂" }, + ["ῧ"]={ "ϋ", "͂" }, + ["Ῠ"]={ "Υ", "̆" }, + ["Ῡ"]={ "Υ", "̄" }, + ["Ὺ"]={ "Υ", "̀" }, + ["Ῥ"]={ "Ρ", "̔" }, + ["῭"]={ "¨", "̀" }, + ["ῲ"]={ "ὼ", "ͅ" }, + ["ῳ"]={ "ω", "ͅ" }, + ["ῴ"]={ "ώ", "ͅ" }, + ["ῶ"]={ "ω", "͂" }, + ["ῷ"]={ "ῶ", "ͅ" }, + ["Ὸ"]={ "Ο", "̀" }, + ["Ὼ"]={ "Ω", "̀" }, + ["ῼ"]={ "Ω", "ͅ" }, + ["↚"]={ "←", "̸" }, + ["↛"]={ "→", "̸" }, + ["↮"]={ "↔", "̸" }, + ["⇍"]={ "⇐", "̸" }, + ["⇎"]={ "⇔", "̸" }, + ["⇏"]={ "⇒", "̸" }, + ["∄"]={ "∃", "̸" }, + ["∉"]={ "∈", "̸" }, + ["∌"]={ "∋", "̸" }, + ["∤"]={ "∣", "̸" }, + ["∦"]={ "∥", "̸" }, + ["≁"]={ "∼", "̸" }, + ["≄"]={ "≃", "̸" }, + ["≇"]={ "≅", "̸" }, + ["≉"]={ "≈", "̸" }, + ["≠"]={ "=", "̸" }, + ["≢"]={ "≡", "̸" }, + ["≭"]={ "≍", "̸" }, + ["≮"]={ "<", "̸" }, + ["≯"]={ ">", "̸" }, + ["≰"]={ "≤", "̸" }, + ["≱"]={ "≥", "̸" }, + ["≴"]={ "≲", "̸" }, + ["≵"]={ "≳", "̸" }, + ["≸"]={ "≶", "̸" }, + ["≹"]={ "≷", "̸" }, + ["⊀"]={ "≺", "̸" }, + ["⊁"]={ "≻", "̸" }, + ["⊄"]={ "⊂", "̸" }, + ["⊅"]={ "⊃", "̸" }, + ["⊈"]={ "⊆", "̸" }, + ["⊉"]={ "⊇", "̸" }, + ["⊬"]={ "⊢", "̸" }, + ["⊭"]={ "⊨", "̸" }, + ["⊮"]={ "⊩", "̸" }, + ["⊯"]={ "⊫", "̸" }, + ["⋠"]={ "≼", "̸" }, + ["⋡"]={ "≽", "̸" }, + ["⋢"]={ "⊑", "̸" }, + ["⋣"]={ "⊒", "̸" }, + ["⋪"]={ "⊲", "̸" }, + ["⋫"]={ "⊳", "̸" }, + ["⋬"]={ "⊴", "̸" }, + ["⋭"]={ "⊵", "̸" }, + ["⫝̸"]={ "⫝", "̸" }, + ["が"]={ "か", "゙" }, + ["ぎ"]={ "き", "゙" }, + ["ぐ"]={ "く", "゙" }, + ["げ"]={ "け", "゙" }, + ["ご"]={ "こ", "゙" }, + ["ざ"]={ "さ", "゙" }, + ["じ"]={ "し", "゙" }, + ["ず"]={ "す", "゙" }, + ["ぜ"]={ "せ", "゙" }, + ["ぞ"]={ "そ", "゙" }, + ["だ"]={ "た", "゙" }, + ["ぢ"]={ "ち", "゙" }, + ["づ"]={ "つ", "゙" }, + ["で"]={ "て", "゙" }, + ["ど"]={ "と", "゙" }, + ["ば"]={ "は", "゙" }, + ["ぱ"]={ "は", "゚" }, + ["び"]={ "ひ", "゙" }, + ["ぴ"]={ "ひ", "゚" }, + ["ぶ"]={ "ふ", "゙" }, + ["ぷ"]={ "ふ", "゚" }, + ["べ"]={ "へ", "゙" }, + ["ぺ"]={ "へ", "゚" }, + ["ぼ"]={ "ほ", "゙" }, + ["ぽ"]={ "ほ", "゚" }, + ["ゔ"]={ "う", "゙" }, + ["ゞ"]={ "ゝ", "゙" }, + ["ガ"]={ "カ", "゙" }, + ["ギ"]={ "キ", "゙" }, + ["グ"]={ "ク", "゙" }, + ["ゲ"]={ "ケ", "゙" }, + ["ゴ"]={ "コ", "゙" }, + ["ザ"]={ "サ", "゙" }, + ["ジ"]={ "シ", "゙" }, + ["ズ"]={ "ス", "゙" }, + ["ゼ"]={ "セ", "゙" }, + ["ゾ"]={ "ソ", "゙" }, + ["ダ"]={ "タ", "゙" }, + ["ヂ"]={ "チ", "゙" }, + ["ヅ"]={ "ツ", "゙" }, + ["デ"]={ "テ", "゙" }, + ["ド"]={ "ト", "゙" }, + ["バ"]={ "ハ", "゙" }, + ["パ"]={ "ハ", "゚" }, + ["ビ"]={ "ヒ", "゙" }, + ["ピ"]={ "ヒ", "゚" }, + ["ブ"]={ "フ", "゙" }, + ["プ"]={ "フ", "゚" }, + ["ベ"]={ "ヘ", "゙" }, + ["ペ"]={ "ヘ", "゚" }, + ["ボ"]={ "ホ", "゙" }, + ["ポ"]={ "ホ", "゚" }, + ["ヴ"]={ "ウ", "゙" }, + ["ヷ"]={ "ワ", "゙" }, + ["ヸ"]={ "ヰ", "゙" }, + ["ヹ"]={ "ヱ", "゙" }, + ["ヺ"]={ "ヲ", "゙" }, + ["ヾ"]={ "ヽ", "゙" }, + ["יִ"]={ "י", "ִ" }, + ["ײַ"]={ "ײ", "ַ" }, + ["שׁ"]={ "ש", "ׁ" }, + ["שׂ"]={ "ש", "ׂ" }, + ["שּׁ"]={ "שּ", "ׁ" }, + ["שּׂ"]={ "שּ", "ׂ" }, + ["אַ"]={ "א", "ַ" }, + ["אָ"]={ "א", "ָ" }, + ["אּ"]={ "א", "ּ" }, + ["בּ"]={ "ב", "ּ" }, + ["גּ"]={ "ג", "ּ" }, + ["דּ"]={ "ד", "ּ" }, + ["הּ"]={ "ה", "ּ" }, + ["וּ"]={ "ו", "ּ" }, + ["זּ"]={ "ז", "ּ" }, + ["טּ"]={ "ט", "ּ" }, + ["יּ"]={ "י", "ּ" }, + ["ךּ"]={ "ך", "ּ" }, + ["כּ"]={ "כ", "ּ" }, + ["לּ"]={ "ל", "ּ" }, + ["מּ"]={ "מ", "ּ" }, + ["נּ"]={ "נ", "ּ" }, + ["סּ"]={ "ס", "ּ" }, + ["ףּ"]={ "ף", "ּ" }, + ["פּ"]={ "פ", "ּ" }, + ["צּ"]={ "צ", "ּ" }, + ["קּ"]={ "ק", "ּ" }, + ["רּ"]={ "ר", "ּ" }, + ["שּ"]={ "ש", "ּ" }, + ["תּ"]={ "ת", "ּ" }, + ["וֹ"]={ "ו", "ֹ" }, + ["בֿ"]={ "ב", "ֿ" }, + ["כֿ"]={ "כ", "ֿ" }, + ["פֿ"]={ "פ", "ֿ" }, + ["𑂚"]={ "𑂙", "𑂺" }, + ["𑂜"]={ "𑂛", "𑂺" }, + ["𑂫"]={ "𑂥", "𑂺" }, + ["𑄮"]={ "𑄱", "𑄧" }, + ["𑄯"]={ "𑄲", "𑄧" }, + ["𑍋"]={ "𑍇", "𑌾" }, + ["𑍌"]={ "𑍇", "𑍗" }, + ["𑒻"]={ "𑒹", "𑒺" }, + ["𑒼"]={ "𑒹", "𑒰" }, + ["𑒾"]={ "𑒹", "𑒽" }, + ["𑖺"]={ "𑖸", "𑖯" }, + ["𑖻"]={ "𑖹", "𑖯" }, + ["𝅗𝅥"]={ "𝅗", "𝅥" }, + ["𝅘𝅥"]={ "𝅘", "𝅥" }, + ["𝅘𝅥𝅮"]={ "𝅘𝅥", "𝅮" }, + ["𝅘𝅥𝅯"]={ "𝅘𝅥", "𝅯" }, + ["𝅘𝅥𝅰"]={ "𝅘𝅥", "𝅰" }, + ["𝅘𝅥𝅱"]={ "𝅘𝅥", "𝅱" }, + ["𝅘𝅥𝅲"]={ "𝅘𝅥", "𝅲" }, + ["𝆹𝅥"]={ "𝆹", "𝅥" }, + ["𝆺𝅥"]={ "𝆺", "𝅥" }, + ["𝆹𝅥𝅮"]={ "𝆹𝅥", "𝅮" }, + ["𝆺𝅥𝅮"]={ "𝆺𝅥", "𝅮" }, + ["𝆹𝅥𝅯"]={ "𝆹𝅥", "𝅯" }, + ["𝆺𝅥𝅯"]={ "𝆺𝅥", "𝅯" }, + }, + }, + }, + ["name"]="collapse", + ["prepend"]=true, + ["type"]="ligature", +}
\ No newline at end of file diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua index e59c57a1c..07c490253 100644 --- a/tex/generic/context/luatex/luatex-fonts-merged.lua +++ b/tex/generic/context/luatex/luatex-fonts-merged.lua @@ -1,6 +1,6 @@ -- merged file : c:/data/develop/context/sources/luatex-fonts-merged.lua -- parent file : c:/data/develop/context/sources/luatex-fonts.lua --- merge date : 02/20/17 17:55:09 +-- merge date : 02/23/17 17:07:53 do -- begin closure to overcome local limits and interference @@ -3743,6 +3743,27 @@ function number.sparseexponent(f,n) end return tostring(n) end +local hf={} +local hs={} +setmetatable(hf,{ __index=function(t,k) + local v="%."..k.."f" + t[k]=v + return v +end } ) +setmetatable(hs,{ __index=function(t,k) + local v="%"..k.."s" + t[k]=v + return v +end } ) +function number.formattedfloat(n,b,a) + local s=format(hf[a],n) + local l=(b or 0)+(a or 0)+1 + if #s<l then + return format(hs[l],s) + else + return s + end +end local template=[[ %s %s @@ -3770,6 +3791,7 @@ local autodouble=string.autodouble local sequenced=table.sequenced local formattednumber=number.formatted local sparseexponent=number.sparseexponent +local formattedfloat=number.formattedfloat ]] else environment={ @@ -3793,6 +3815,7 @@ else sequenced=table.sequenced, formattednumber=number.formatted, sparseexponent=number.sparseexponent, + formattedfloat=number.formattedfloat } end local arguments={ "a1" } @@ -3803,6 +3826,7 @@ setmetatable(arguments,{ __index=function(t,k) end }) local prefix_any=C((S("+- .")+R("09"))^0) +local prefix_sub=(C((S("+-")+R("09"))^0)+Cc(0))*P(".")*(C((S("+-")+R("09"))^0)+Cc(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 @@ -3853,6 +3877,10 @@ local format_F=function(f) return format("format((a%s %% 1 == 0) and '%%i' or '%%%sf',a%s)",n,f,n) end end +local format_k=function(b,a) + n=n+1 + return format("formattedfloat(a%s,%i,%i)",n,b or 0,a or 0) +end local format_g=function(f) n=n+1 return format("format('%%%sg',a%s)",f,n) @@ -4061,7 +4089,8 @@ local builder=Cs { "start", +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("N") ++V("k") +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") @@ -4088,6 +4117,7 @@ local builder=Cs { "start", ["S"]=(prefix_any*P("S"))/format_S, ["Q"]=(prefix_any*P("Q"))/format_S, ["N"]=(prefix_any*P("N"))/format_N, + ["k"]=(prefix_sub*P("k"))/format_k, ["c"]=(prefix_any*P("c"))/format_c, ["C"]=(prefix_any*P("C"))/format_C, ["r"]=(prefix_any*P("r"))/format_r, @@ -4289,6 +4319,7 @@ end files.readcardinal1=files.readbyte files.readcardinal=files.readcardinal1 files.readinteger=files.readinteger1 +files.readsignedbyte=files.readinteger1 function files.readcardinal2(f) local a,b=byte(f:read(2),1,2) return 0x100*a+b @@ -8038,11 +8069,9 @@ if not modules then modules={} end modules ['font-otr']={ 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 next,type=next,type +local byte,lower,char,gsub=string.byte,string.lower,string.char,string.gsub +local floor,round=math.floor,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 @@ -8082,7 +8111,7 @@ local readufword=readushort local readoffset=readushort local read2dot14=streamreader.read2dot14 function streamreader.readtag(f) - return lower(strip(readstring(f,4))) + return lower(stripstring(readstring(f,4))) end local function readlongdatetime(f) local a,b,c,d,e,f,g,h=readbytes(f,8) @@ -8123,6 +8152,7 @@ local reservednames={ [0]="copyright", "wwssubfamily", "lightbackgroundpalette", "darkbackgroundpalette", + "variationspostscriptnameprefix", } local platforms={ [0]="unicode", "macintosh", @@ -8323,7 +8353,8 @@ function readers.name(f,fontdata,specification) local encoding=encodings[encoding] local language=languages[language] if encoding and language then - local name=reservednames[readushort(f)] + local index=readushort(f) + local name=reservednames[index] if name then namelist[#namelist+1]={ platform=platform, @@ -8334,7 +8365,13 @@ function readers.name(f,fontdata,specification) offset=start+readushort(f), } else - skipshort(f,2) +namelist[#namelist+1]={ + platform=platform, + encoding=encoding, + language=language, + length=readushort(f), + offset=start+readushort(f), +} end else skipshort(f,3) @@ -8351,12 +8388,13 @@ function readers.name(f,fontdata,specification) end local names={} local done={} + local extras={} 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 + if not done[nametag or i] then local encoding=name.encoding local language=name.language if (not e or encoding==e) and (not l or language==l) then @@ -8369,13 +8407,16 @@ function readers.name(f,fontdata,specification) if decoder then content=decoder(content) end - names[nametag]={ - content=content, - platform=platform, - encoding=encoding, - language=language, - } - done[nametag]=true + if nametag then + names[nametag]={ + content=content, + platform=platform, + encoding=encoding, + language=language, + } + end + extras[i-1]=content + done[nametag or i]=true end end end @@ -8386,6 +8427,7 @@ function readers.name(f,fontdata,specification) filter("macintosh") filter("unicode") fontdata.names=names + fontdata.extras=extras if specification.platformnames then local collected={} for platform,namelist in next,namelists do @@ -8760,7 +8802,8 @@ local sequence={ } local supported={} for i=1,#sequence do - local sp,se,sf=unpack(sequence[i]) + local si=sequence[i] + local sp,se,sf=si[1],si[2],si[3] local p=supported[sp] if not p then p={} @@ -9136,7 +9179,8 @@ function readers.cmap(f,fontdata,specification) end local ok=false for i=1,#sequence do - local sp,se,sf=unpack(sequence[i]) + local si=sequence[i] + local sp,se,sf=si[1],si[2],si[3] if checkcmap(f,fontdata,records,sp,se,sf)>0 then ok=true end @@ -11595,6 +11639,7 @@ local streamreader=readers.streamreader local setposition=streamreader.setposition local getposition=streamreader.getposition local skipshort=streamreader.skipshort +local skipbytes=streamreader.skip local readushort=streamreader.readcardinal2 local readulong=streamreader.readcardinal4 local readshort=streamreader.readinteger2 @@ -11602,6 +11647,9 @@ local readfword=readshort local readstring=streamreader.readstring local readtag=streamreader.readtag local readbytes=streamreader.readbytes +local readfixed=streamreader.readfixed4 +local read2dot14=streamreader.read2dot14 +local readinteger=streamreader.readinteger1 local gsubhandlers={} local gposhandlers={} local lookupidoffset=-1 @@ -13701,6 +13749,166 @@ function readers.svg(f,fontdata,specification) fontdata.hascolor=true end end +function readers.fvar(f,fontdata,specification) + local datatable=fontdata.tables.fvar + if datatable then + local tableoffset=datatable.offset + setposition(f,tableoffset) + local majorversion=readushort(f) + local minorversion=readushort(f) + if majorversion~=1 and minorversion~=0 then + report("table version %a.%a of %a is not supported (yet), maybe font %s is bad", + majorversion,minorversion,"fvar",fontdata.filename) + return + end + local offsettoaxis=tableoffset+readushort(f) + local nofsizepairs=readushort(f) + local nofaxis=readushort(f) + local sizeofaxis=readushort(f) + local nofinstances=readushort(f) + local sizeofinstances=readushort(f) + local extras=fontdata.extras + local axis={} + local instances={} + setposition(f,offsettoaxis) + local function readtuple(f) + local t={} + for i=1,nofaxis do + t[i]=readfixed(f) + end + return t + end + for i=1,nofaxis do + axis[i]={ + tag=readtag(f), + minimum=readfixed(f), + default=readfixed(f), + maximum=readfixed(f), + flags=readushort(f), + nameid=extras[readushort(f)], + } + local n=sizeofaxis-20 + if n>0 then + skipbytes(f,n) + elseif n<0 then + end + end + for i=1,nofinstances do + local subfamid=readushort(f) + local flags=readushort(f) + local tuple=readtuple(f) + local psnameid=false + local nofbytes=2+2+#tuple*2 + if nofbytes<sizeofinstances then + psnameid=readushort(f) + nofbytes=nofbytes+2 + end + instances[i]={ + subfamily=extras[subfamid], + flags=flags, + tuple=tuple, + psname=extras[psnameid] or nil, + } + if nofbytes>0 then + skipbytes(f,nofbytes) + end + end + fontdata.variable={ + axis=axis, + instances=instances, + } + end +end +local tags={ + hasc="", + hdsc="", + vasc="", + vdsc="", + vlgp="", + xhgt="", + cpht="", +} +function readers.mvar(f,fontdata,specification) + local datatable=fontdata.tables.mvar + if datatable then + local tableoffset=datatable.offset + setposition(f,tableoffset) + local majorversion=readushort(f) + local minorversion=readushort(f) + if majorversion~=1 and minorversion~=0 then + report("table version %a.%a of %a is not supported (yet), maybe font %s is bad", + majorversion,minorversion,"fvar",fontdata.filename) + return + end + local nofaxis=readushort(f) + local recordsize=readushort(f) + local nofrecords=readushort(f) + local offsettostore=tableoffset+readushort(f) + local records={} + local dimensions={} + local store={} + local regions={} + for i=1,nofrecords do + local tag=readtag(f) + if tags[tag] then + dimensions[tag]={ + outer=readushort(f), + inner=readushort(f), + } + else + skipshort(f,2) + end + end + setposition(f,offsettostore) + local nofaxis=readushort(f) + local nofregions=readushort(f) + for i=1,nofregions do + local t={} + for i=1,nofaxis do + t[i]={ + start=read2dot14(f), + peak=read2dot14(f), + stop=read2dot14(f), + } + end + regions[i]=t + end + local format=readushort(f) + local offset=offsettostore+readulong(f) + local nofdata=readushort(f) + local data={} + for i=1,nofdata do + data[i]=readulong(f)+offset + end + for i=1,nofdata do + local offset=data[i] + setposition(f,offset) + local nofdeltas=readushort(f) + local nofshort=readushort(f) + local nofregions=readushort(f) + local deltas={} + local regions={} + local length=nofshort+nofregions + for i=1,nofregions do + regions[i]=readushort(f) + end + for i=1,nofdeltas do + local t={} + for i=1,nofshort do + t[i]=readushort(f) + end + for i=1,nofregions do + t[nofshort+i]=readinteger(f) + end + deltas[i]=t + end + data[i]={ + regions=regions, + deltas=deltas, + } + end + end +end end -- closure @@ -16773,7 +16981,7 @@ if not modules then modules={} end modules ['font-otj']={ license="see context related readme files", } if not nodes.properties then return end -local next,rawget=next,rawget +local next,rawget,tonumber=next,rawget,tonumber local fastcopy=table.fastcopy local registertracker=trackers.register local trace_injections=false registertracker("fonts.injections",function(v) trace_injections=v end) @@ -18490,7 +18698,6 @@ local attributes=attributes local fonts=fonts local otf=fonts.handlers.otf local tracers=nodes.tracers -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) @@ -18905,7 +19112,9 @@ local function multiple_glyphs(head,start,multiple,ignoremarks,what) end local function get_alternative_glyph(start,alternatives,value) local n=#alternatives - if value=="random" then + if n==1 then + return alternatives[1],trace_alternatives and "1 (only one present)" + elseif 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 @@ -20311,7 +20520,7 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode) local l=ck[5] size=l-f+1 if size>1 then - local discfound=nil + local discfound local n=f+1 last=startnext while n<=l do @@ -20432,7 +20641,7 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode) prev=getprev(sweepnode) end if prev then - local discfound=nil + local discfound local n=f-1 while n>=1 do if prev then @@ -20541,7 +20750,7 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode) end end prev=getprev(prev) - elseif seq[n][32] and id==glue_code and isspace(prev,threshold,id) then + elseif id==glue_code and seq[n][32] and isspace(prev,threshold,id) then n=n-1 prev=getprev(prev) else @@ -20562,13 +20771,11 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode) 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 + if not current and (sweeptype=="post" or sweeptype=="replace") then + current=getnext(sweepnode) end if current then - local discfound=nil + local discfound local n=l+1 while n<=s do if current then @@ -20668,7 +20875,7 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode) else end current=getnext(current) - elseif seq[n][32] and id==glue_code and isspace(current,threshold,id) then + elseif id==glue_code and seq[n][32] and isspace(current,threshold,id) then n=n+1 current=getnext(current) else @@ -21511,6 +21718,8 @@ local function featuresprocessor(head,font,attr) end elseif char==false then start=getnext(start) + elseif id==glue_code then + start=getnext(start) elseif id==disc_code then local ok if gpossing then @@ -21574,6 +21783,8 @@ local function featuresprocessor(head,font,attr) end elseif char==false then start=getnext(start) + elseif id==glue_code then + start=getnext(start) elseif id==disc_code then local ok if gpossing then @@ -24278,13 +24489,15 @@ local function addfeature(data,feature,specifications) local coveractions=coverup.actions local stepkey=coverup.stepkey local register=coverup.register - local function prepare_substitution(list,featuretype) + local function prepare_substitution(list,featuretype,nocheck) 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 not nocheck and not description then + skip=skip+1 + else if type(replacement)=="table" then replacement=replacement[1] end @@ -24295,19 +24508,17 @@ local function addfeature(data,feature,specifications) else skip=skip+1 end - else - skip=skip+1 end end return coverage end - local function prepare_alternate(list,featuretype) + local function prepare_alternate(list,featuretype,nocheck) 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 + if not nocheck and not description then skip=skip+1 elseif type(replacement)=="table" then local r={} @@ -24329,13 +24540,13 @@ local function addfeature(data,feature,specifications) end return coverage end - local function prepare_multiple(list,featuretype) + local function prepare_multiple(list,featuretype,nocheck) 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 + if not nocheck and not description then skip=skip+1 elseif type(replacement)=="table" then local r,n={},0 @@ -24362,15 +24573,18 @@ local function addfeature(data,feature,specifications) end end end + inspect(coverage) return coverage end - local function prepare_ligature(list,featuretype) + local function prepare_ligature(list,featuretype,nocheck) 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 not nocheck and not description then + skip=skip+1 + else if type(ligature)=="string" then ligature={ lpegmatch(splitter,ligature) } end @@ -24391,8 +24605,6 @@ local function addfeature(data,feature,specifications) else skip=skip+1 end - else - skip=skip+1 end end return coverage @@ -24620,6 +24832,7 @@ local function addfeature(data,feature,specifications) 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 nocheck=specification.nocheck local featureorder=specification.order or { feature } local featurechain=(featuretype=="chainsubstitution" or featuretype=="chainposition") and 1 or 0 local nofsteps=0 @@ -24640,13 +24853,13 @@ local function addfeature(data,feature,specifications) local coverage=nil local format=nil if featuretype=="substitution" then - coverage=prepare_substitution(list,featuretype) + coverage=prepare_substitution(list,featuretype,nocheck) elseif featuretype=="ligature" then - coverage=prepare_ligature(list,featuretype) + coverage=prepare_ligature(list,featuretype,nocheck) elseif featuretype=="alternate" then - coverage=prepare_alternate(list,featuretype) + coverage=prepare_alternate(list,featuretype,nocheck) elseif featuretype=="multiple" then - coverage=prepare_multiple(list,featuretype) + coverage=prepare_multiple(list,featuretype,nocheck) elseif featuretype=="kern" then format="kern" coverage=prepare_kern(list,featuretype) @@ -24673,16 +24886,16 @@ local function addfeature(data,feature,specifications) local format=nil if featuretype=="substitution" then category="gsub" - coverage=prepare_substitution(list,featuretype) + coverage=prepare_substitution(list,featuretype,nocheck) elseif featuretype=="ligature" then category="gsub" - coverage=prepare_ligature(list,featuretype) + coverage=prepare_ligature(list,featuretype,nocheck) elseif featuretype=="alternate" then category="gsub" - coverage=prepare_alternate(list,featuretype) + coverage=prepare_alternate(list,featuretype,nocheck) elseif featuretype=="multiple" then category="gsub" - coverage=prepare_multiple(list,featuretype) + coverage=prepare_multiple(list,featuretype,nocheck) elseif featuretype=="kern" then category="gpos" format="kern" @@ -27332,6 +27545,2076 @@ end -- closure do -- begin closure to overcome local limits and interference + +fonts.handlers.otf.addfeature { + ["dataset"]={ + { + ["data"]={ + ["À"]={ "A","̀" }, + ["Á"]={ "A","́" }, + ["Â"]={ "A","̂" }, + ["Ã"]={ "A","̃" }, + ["Ä"]={ "A","̈" }, + ["Å"]={ "A","̊" }, + ["Ç"]={ "C","̧" }, + ["È"]={ "E","̀" }, + ["É"]={ "E","́" }, + ["Ê"]={ "E","̂" }, + ["Ë"]={ "E","̈" }, + ["Ì"]={ "I","̀" }, + ["Í"]={ "I","́" }, + ["Î"]={ "I","̂" }, + ["Ï"]={ "I","̈" }, + ["Ñ"]={ "N","̃" }, + ["Ò"]={ "O","̀" }, + ["Ó"]={ "O","́" }, + ["Ô"]={ "O","̂" }, + ["Õ"]={ "O","̃" }, + ["Ö"]={ "O","̈" }, + ["Ù"]={ "U","̀" }, + ["Ú"]={ "U","́" }, + ["Û"]={ "U","̂" }, + ["Ü"]={ "U","̈" }, + ["Ý"]={ "Y","́" }, + ["à"]={ "a","̀" }, + ["á"]={ "a","́" }, + ["â"]={ "a","̂" }, + ["ã"]={ "a","̃" }, + ["ä"]={ "a","̈" }, + ["å"]={ "a","̊" }, + ["ç"]={ "c","̧" }, + ["è"]={ "e","̀" }, + ["é"]={ "e","́" }, + ["ê"]={ "e","̂" }, + ["ë"]={ "e","̈" }, + ["ì"]={ "i","̀" }, + ["í"]={ "i","́" }, + ["î"]={ "i","̂" }, + ["ï"]={ "i","̈" }, + ["ñ"]={ "n","̃" }, + ["ò"]={ "o","̀" }, + ["ó"]={ "o","́" }, + ["ô"]={ "o","̂" }, + ["õ"]={ "o","̃" }, + ["ö"]={ "o","̈" }, + ["ù"]={ "u","̀" }, + ["ú"]={ "u","́" }, + ["û"]={ "u","̂" }, + ["ü"]={ "u","̈" }, + ["ý"]={ "y","́" }, + ["ÿ"]={ "y","̈" }, + ["Ā"]={ "A","̄" }, + ["ā"]={ "a","̄" }, + ["Ă"]={ "A","̆" }, + ["ă"]={ "a","̆" }, + ["Ą"]={ "A","̨" }, + ["ą"]={ "a","̨" }, + ["Ć"]={ "C","́" }, + ["ć"]={ "c","́" }, + ["Ĉ"]={ "C","̂" }, + ["ĉ"]={ "c","̂" }, + ["Ċ"]={ "C","̇" }, + ["ċ"]={ "c","̇" }, + ["Č"]={ "C","̌" }, + ["č"]={ "c","̌" }, + ["Ď"]={ "D","̌" }, + ["ď"]={ "d","̌" }, + ["Ē"]={ "E","̄" }, + ["ē"]={ "e","̄" }, + ["Ĕ"]={ "E","̆" }, + ["ĕ"]={ "e","̆" }, + ["Ė"]={ "E","̇" }, + ["ė"]={ "e","̇" }, + ["Ę"]={ "E","̨" }, + ["ę"]={ "e","̨" }, + ["Ě"]={ "E","̌" }, + ["ě"]={ "e","̌" }, + ["Ĝ"]={ "G","̂" }, + ["ĝ"]={ "g","̂" }, + ["Ğ"]={ "G","̆" }, + ["ğ"]={ "g","̆" }, + ["Ġ"]={ "G","̇" }, + ["ġ"]={ "g","̇" }, + ["Ģ"]={ "G","̧" }, + ["ģ"]={ "g","̧" }, + ["Ĥ"]={ "H","̂" }, + ["ĥ"]={ "h","̂" }, + ["Ĩ"]={ "I","̃" }, + ["ĩ"]={ "i","̃" }, + ["Ī"]={ "I","̄" }, + ["ī"]={ "i","̄" }, + ["Ĭ"]={ "I","̆" }, + ["ĭ"]={ "i","̆" }, + ["Į"]={ "I","̨" }, + ["į"]={ "i","̨" }, + ["İ"]={ "I","̇" }, + ["Ĵ"]={ "J","̂" }, + ["ĵ"]={ "j","̂" }, + ["Ķ"]={ "K","̧" }, + ["ķ"]={ "k","̧" }, + ["Ĺ"]={ "L","́" }, + ["ĺ"]={ "l","́" }, + ["Ļ"]={ "L","̧" }, + ["ļ"]={ "l","̧" }, + ["Ľ"]={ "L","̌" }, + ["ľ"]={ "l","̌" }, + ["Ń"]={ "N","́" }, + ["ń"]={ "n","́" }, + ["Ņ"]={ "N","̧" }, + ["ņ"]={ "n","̧" }, + ["Ň"]={ "N","̌" }, + ["ň"]={ "n","̌" }, + ["Ō"]={ "O","̄" }, + ["ō"]={ "o","̄" }, + ["Ŏ"]={ "O","̆" }, + ["ŏ"]={ "o","̆" }, + ["Ő"]={ "O","̋" }, + ["ő"]={ "o","̋" }, + ["Ŕ"]={ "R","́" }, + ["ŕ"]={ "r","́" }, + ["Ŗ"]={ "R","̧" }, + ["ŗ"]={ "r","̧" }, + ["Ř"]={ "R","̌" }, + ["ř"]={ "r","̌" }, + ["Ś"]={ "S","́" }, + ["ś"]={ "s","́" }, + ["Ŝ"]={ "S","̂" }, + ["ŝ"]={ "s","̂" }, + ["Ş"]={ "S","̧" }, + ["ş"]={ "s","̧" }, + ["Š"]={ "S","̌" }, + ["š"]={ "s","̌" }, + ["Ţ"]={ "T","̧" }, + ["ţ"]={ "t","̧" }, + ["Ť"]={ "T","̌" }, + ["ť"]={ "t","̌" }, + ["Ũ"]={ "U","̃" }, + ["ũ"]={ "u","̃" }, + ["Ū"]={ "U","̄" }, + ["ū"]={ "u","̄" }, + ["Ŭ"]={ "U","̆" }, + ["ŭ"]={ "u","̆" }, + ["Ů"]={ "U","̊" }, + ["ů"]={ "u","̊" }, + ["Ű"]={ "U","̋" }, + ["ű"]={ "u","̋" }, + ["Ų"]={ "U","̨" }, + ["ų"]={ "u","̨" }, + ["Ŵ"]={ "W","̂" }, + ["ŵ"]={ "w","̂" }, + ["Ŷ"]={ "Y","̂" }, + ["ŷ"]={ "y","̂" }, + ["Ÿ"]={ "Y","̈" }, + ["Ź"]={ "Z","́" }, + ["ź"]={ "z","́" }, + ["Ż"]={ "Z","̇" }, + ["ż"]={ "z","̇" }, + ["Ž"]={ "Z","̌" }, + ["ž"]={ "z","̌" }, + ["Ơ"]={ "O","̛" }, + ["ơ"]={ "o","̛" }, + ["Ư"]={ "U","̛" }, + ["ư"]={ "u","̛" }, + ["Ǎ"]={ "A","̌" }, + ["ǎ"]={ "a","̌" }, + ["Ǐ"]={ "I","̌" }, + ["ǐ"]={ "i","̌" }, + ["Ǒ"]={ "O","̌" }, + ["ǒ"]={ "o","̌" }, + ["Ǔ"]={ "U","̌" }, + ["ǔ"]={ "u","̌" }, + ["Ǖ"]={ "Ü","̄" }, + ["ǖ"]={ "ü","̄" }, + ["Ǘ"]={ "Ü","́" }, + ["ǘ"]={ "ü","́" }, + ["Ǚ"]={ "Ü","̌" }, + ["ǚ"]={ "ü","̌" }, + ["Ǜ"]={ "Ü","̀" }, + ["ǜ"]={ "ü","̀" }, + ["Ǟ"]={ "Ä","̄" }, + ["ǟ"]={ "ä","̄" }, + ["Ǡ"]={ "Ȧ","̄" }, + ["ǡ"]={ "ȧ","̄" }, + ["Ǣ"]={ "Æ","̄" }, + ["ǣ"]={ "æ","̄" }, + ["Ǧ"]={ "G","̌" }, + ["ǧ"]={ "g","̌" }, + ["Ǩ"]={ "K","̌" }, + ["ǩ"]={ "k","̌" }, + ["Ǫ"]={ "O","̨" }, + ["ǫ"]={ "o","̨" }, + ["Ǭ"]={ "Ǫ","̄" }, + ["ǭ"]={ "ǫ","̄" }, + ["Ǯ"]={ "Ʒ","̌" }, + ["ǯ"]={ "ʒ","̌" }, + ["ǰ"]={ "j","̌" }, + ["Ǵ"]={ "G","́" }, + ["ǵ"]={ "g","́" }, + ["Ǹ"]={ "N","̀" }, + ["ǹ"]={ "n","̀" }, + ["Ǻ"]={ "Å","́" }, + ["ǻ"]={ "å","́" }, + ["Ǽ"]={ "Æ","́" }, + ["ǽ"]={ "æ","́" }, + ["Ǿ"]={ "Ø","́" }, + ["ǿ"]={ "ø","́" }, + ["Ȁ"]={ "A","̏" }, + ["ȁ"]={ "a","̏" }, + ["Ȃ"]={ "A","̑" }, + ["ȃ"]={ "a","̑" }, + ["Ȅ"]={ "E","̏" }, + ["ȅ"]={ "e","̏" }, + ["Ȇ"]={ "E","̑" }, + ["ȇ"]={ "e","̑" }, + ["Ȉ"]={ "I","̏" }, + ["ȉ"]={ "i","̏" }, + ["Ȋ"]={ "I","̑" }, + ["ȋ"]={ "i","̑" }, + ["Ȍ"]={ "O","̏" }, + ["ȍ"]={ "o","̏" }, + ["Ȏ"]={ "O","̑" }, + ["ȏ"]={ "o","̑" }, + ["Ȑ"]={ "R","̏" }, + ["ȑ"]={ "r","̏" }, + ["Ȓ"]={ "R","̑" }, + ["ȓ"]={ "r","̑" }, + ["Ȕ"]={ "U","̏" }, + ["ȕ"]={ "u","̏" }, + ["Ȗ"]={ "U","̑" }, + ["ȗ"]={ "u","̑" }, + ["Ș"]={ "S","̦" }, + ["ș"]={ "s","̦" }, + ["Ț"]={ "T","̦" }, + ["ț"]={ "t","̦" }, + ["Ȟ"]={ "H","̌" }, + ["ȟ"]={ "h","̌" }, + ["Ȧ"]={ "A","̇" }, + ["ȧ"]={ "a","̇" }, + ["Ȩ"]={ "E","̧" }, + ["ȩ"]={ "e","̧" }, + ["Ȫ"]={ "Ö","̄" }, + ["ȫ"]={ "ö","̄" }, + ["Ȭ"]={ "Õ","̄" }, + ["ȭ"]={ "õ","̄" }, + ["Ȯ"]={ "O","̇" }, + ["ȯ"]={ "o","̇" }, + ["Ȱ"]={ "Ȯ","̄" }, + ["ȱ"]={ "ȯ","̄" }, + ["Ȳ"]={ "Y","̄" }, + ["ȳ"]={ "y","̄" }, + ["̈́"]={ "̈","́" }, + ["΅"]={ "¨","́" }, + ["Ά"]={ "Α","́" }, + ["Έ"]={ "Ε","́" }, + ["Ή"]={ "Η","́" }, + ["Ί"]={ "Ι","́" }, + ["Ό"]={ "Ο","́" }, + ["Ύ"]={ "Υ","́" }, + ["Ώ"]={ "Ω","́" }, + ["ΐ"]={ "ϊ","́" }, + ["Ϊ"]={ "Ι","̈" }, + ["Ϋ"]={ "Υ","̈" }, + ["ά"]={ "α","́" }, + ["έ"]={ "ε","́" }, + ["ή"]={ "η","́" }, + ["ί"]={ "ι","́" }, + ["ΰ"]={ "ϋ","́" }, + ["ϊ"]={ "ι","̈" }, + ["ϋ"]={ "υ","̈" }, + ["ό"]={ "ο","́" }, + ["ύ"]={ "υ","́" }, + ["ώ"]={ "ω","́" }, + ["ϓ"]={ "ϒ","́" }, + ["ϔ"]={ "ϒ","̈" }, + ["Ѐ"]={ "Е","̀" }, + ["Ё"]={ "Е","̈" }, + ["Ѓ"]={ "Г","́" }, + ["Ї"]={ "І","̈" }, + ["Ќ"]={ "К","́" }, + ["Ѝ"]={ "И","̀" }, + ["Ў"]={ "У","̆" }, + ["Й"]={ "И","̆" }, + ["й"]={ "и","̆" }, + ["ѐ"]={ "е","̀" }, + ["ё"]={ "е","̈" }, + ["ѓ"]={ "г","́" }, + ["ї"]={ "і","̈" }, + ["ќ"]={ "к","́" }, + ["ѝ"]={ "и","̀" }, + ["ў"]={ "у","̆" }, + ["Ѷ"]={ "Ѵ","̏" }, + ["ѷ"]={ "ѵ","̏" }, + ["Ӂ"]={ "Ж","̆" }, + ["ӂ"]={ "ж","̆" }, + ["Ӑ"]={ "А","̆" }, + ["ӑ"]={ "а","̆" }, + ["Ӓ"]={ "А","̈" }, + ["ӓ"]={ "а","̈" }, + ["Ӗ"]={ "Е","̆" }, + ["ӗ"]={ "е","̆" }, + ["Ӛ"]={ "Ә","̈" }, + ["ӛ"]={ "ә","̈" }, + ["Ӝ"]={ "Ж","̈" }, + ["ӝ"]={ "ж","̈" }, + ["Ӟ"]={ "З","̈" }, + ["ӟ"]={ "з","̈" }, + ["Ӣ"]={ "И","̄" }, + ["ӣ"]={ "и","̄" }, + ["Ӥ"]={ "И","̈" }, + ["ӥ"]={ "и","̈" }, + ["Ӧ"]={ "О","̈" }, + ["ӧ"]={ "о","̈" }, + ["Ӫ"]={ "Ө","̈" }, + ["ӫ"]={ "ө","̈" }, + ["Ӭ"]={ "Э","̈" }, + ["ӭ"]={ "э","̈" }, + ["Ӯ"]={ "У","̄" }, + ["ӯ"]={ "у","̄" }, + ["Ӱ"]={ "У","̈" }, + ["ӱ"]={ "у","̈" }, + ["Ӳ"]={ "У","̋" }, + ["ӳ"]={ "у","̋" }, + ["Ӵ"]={ "Ч","̈" }, + ["ӵ"]={ "ч","̈" }, + ["Ӹ"]={ "Ы","̈" }, + ["ӹ"]={ "ы","̈" }, + ["آ"]={ "ا","ٓ" }, + ["أ"]={ "ا","ٔ" }, + ["ؤ"]={ "و","ٔ" }, + ["إ"]={ "ا","ٕ" }, + ["ئ"]={ "ي","ٔ" }, + ["ۀ"]={ "ە","ٔ" }, + ["ۂ"]={ "ہ","ٔ" }, + ["ۓ"]={ "ے","ٔ" }, + ["ऩ"]={ "न","़" }, + ["ऱ"]={ "र","़" }, + ["ऴ"]={ "ळ","़" }, + ["क़"]={ "क","़" }, + ["ख़"]={ "ख","़" }, + ["ग़"]={ "ग","़" }, + ["ज़"]={ "ज","़" }, + ["ड़"]={ "ड","़" }, + ["ढ़"]={ "ढ","़" }, + ["फ़"]={ "फ","़" }, + ["य़"]={ "य","़" }, + ["ো"]={ "ে","া" }, + ["ৌ"]={ "ে","ৗ" }, + ["ড়"]={ "ড","়" }, + ["ঢ়"]={ "ঢ","়" }, + ["য়"]={ "য","়" }, + ["ਲ਼"]={ "ਲ","਼" }, + ["ਸ਼"]={ "ਸ","਼" }, + ["ਖ਼"]={ "ਖ","਼" }, + ["ਗ਼"]={ "ਗ","਼" }, + ["ਜ਼"]={ "ਜ","਼" }, + ["ਫ਼"]={ "ਫ","਼" }, + ["ୈ"]={ "େ","ୖ" }, + ["ୋ"]={ "େ","ା" }, + ["ୌ"]={ "େ","ୗ" }, + ["ଡ଼"]={ "ଡ","଼" }, + ["ଢ଼"]={ "ଢ","଼" }, + ["ஔ"]={ "ஒ","ௗ" }, + ["ொ"]={ "ெ","ா" }, + ["ோ"]={ "ே","ா" }, + ["ௌ"]={ "ெ","ௗ" }, + ["ై"]={ "ె","ౖ" }, + ["ೀ"]={ "ಿ","ೕ" }, + ["ೇ"]={ "ೆ","ೕ" }, + ["ೈ"]={ "ೆ","ೖ" }, + ["ೊ"]={ "ೆ","ೂ" }, + ["ೋ"]={ "ೊ","ೕ" }, + ["ൊ"]={ "െ","ാ" }, + ["ോ"]={ "േ","ാ" }, + ["ൌ"]={ "െ","ൗ" }, + ["ේ"]={ "ෙ","්" }, + ["ො"]={ "ෙ","ා" }, + ["ෝ"]={ "ො","්" }, + ["ෞ"]={ "ෙ","ෟ" }, + ["གྷ"]={ "ག","ྷ" }, + ["ཌྷ"]={ "ཌ","ྷ" }, + ["དྷ"]={ "ད","ྷ" }, + ["བྷ"]={ "བ","ྷ" }, + ["ཛྷ"]={ "ཛ","ྷ" }, + ["ཀྵ"]={ "ཀ","ྵ" }, + ["ཱི"]={ "ཱ","ི" }, + ["ཱུ"]={ "ཱ","ུ" }, + ["ྲྀ"]={ "ྲ","ྀ" }, + ["ླྀ"]={ "ླ","ྀ" }, + ["ཱྀ"]={ "ཱ","ྀ" }, + ["ྒྷ"]={ "ྒ","ྷ" }, + ["ྜྷ"]={ "ྜ","ྷ" }, + ["ྡྷ"]={ "ྡ","ྷ" }, + ["ྦྷ"]={ "ྦ","ྷ" }, + ["ྫྷ"]={ "ྫ","ྷ" }, + ["ྐྵ"]={ "ྐ","ྵ" }, + ["ဦ"]={ "ဥ","ီ" }, + ["ᬆ"]={ "ᬅ","ᬵ" }, + ["ᬈ"]={ "ᬇ","ᬵ" }, + ["ᬊ"]={ "ᬉ","ᬵ" }, + ["ᬌ"]={ "ᬋ","ᬵ" }, + ["ᬎ"]={ "ᬍ","ᬵ" }, + ["ᬒ"]={ "ᬑ","ᬵ" }, + ["ᬻ"]={ "ᬺ","ᬵ" }, + ["ᬽ"]={ "ᬼ","ᬵ" }, + ["ᭀ"]={ "ᬾ","ᬵ" }, + ["ᭁ"]={ "ᬿ","ᬵ" }, + ["ᭃ"]={ "ᭂ","ᬵ" }, + ["Ḁ"]={ "A","̥" }, + ["ḁ"]={ "a","̥" }, + ["Ḃ"]={ "B","̇" }, + ["ḃ"]={ "b","̇" }, + ["Ḅ"]={ "B","̣" }, + ["ḅ"]={ "b","̣" }, + ["Ḇ"]={ "B","̱" }, + ["ḇ"]={ "b","̱" }, + ["Ḉ"]={ "Ç","́" }, + ["ḉ"]={ "ç","́" }, + ["Ḋ"]={ "D","̇" }, + ["ḋ"]={ "d","̇" }, + ["Ḍ"]={ "D","̣" }, + ["ḍ"]={ "d","̣" }, + ["Ḏ"]={ "D","̱" }, + ["ḏ"]={ "d","̱" }, + ["Ḑ"]={ "D","̧" }, + ["ḑ"]={ "d","̧" }, + ["Ḓ"]={ "D","̭" }, + ["ḓ"]={ "d","̭" }, + ["Ḕ"]={ "Ē","̀" }, + ["ḕ"]={ "ē","̀" }, + ["Ḗ"]={ "Ē","́" }, + ["ḗ"]={ "ē","́" }, + ["Ḙ"]={ "E","̭" }, + ["ḙ"]={ "e","̭" }, + ["Ḛ"]={ "E","̰" }, + ["ḛ"]={ "e","̰" }, + ["Ḝ"]={ "Ȩ","̆" }, + ["ḝ"]={ "ȩ","̆" }, + ["Ḟ"]={ "F","̇" }, + ["ḟ"]={ "f","̇" }, + ["Ḡ"]={ "G","̄" }, + ["ḡ"]={ "g","̄" }, + ["Ḣ"]={ "H","̇" }, + ["ḣ"]={ "h","̇" }, + ["Ḥ"]={ "H","̣" }, + ["ḥ"]={ "h","̣" }, + ["Ḧ"]={ "H","̈" }, + ["ḧ"]={ "h","̈" }, + ["Ḩ"]={ "H","̧" }, + ["ḩ"]={ "h","̧" }, + ["Ḫ"]={ "H","̮" }, + ["ḫ"]={ "h","̮" }, + ["Ḭ"]={ "I","̰" }, + ["ḭ"]={ "i","̰" }, + ["Ḯ"]={ "Ï","́" }, + ["ḯ"]={ "ï","́" }, + ["Ḱ"]={ "K","́" }, + ["ḱ"]={ "k","́" }, + ["Ḳ"]={ "K","̣" }, + ["ḳ"]={ "k","̣" }, + ["Ḵ"]={ "K","̱" }, + ["ḵ"]={ "k","̱" }, + ["Ḷ"]={ "L","̣" }, + ["ḷ"]={ "l","̣" }, + ["Ḹ"]={ "Ḷ","̄" }, + ["ḹ"]={ "ḷ","̄" }, + ["Ḻ"]={ "L","̱" }, + ["ḻ"]={ "l","̱" }, + ["Ḽ"]={ "L","̭" }, + ["ḽ"]={ "l","̭" }, + ["Ḿ"]={ "M","́" }, + ["ḿ"]={ "m","́" }, + ["Ṁ"]={ "M","̇" }, + ["ṁ"]={ "m","̇" }, + ["Ṃ"]={ "M","̣" }, + ["ṃ"]={ "m","̣" }, + ["Ṅ"]={ "N","̇" }, + ["ṅ"]={ "n","̇" }, + ["Ṇ"]={ "N","̣" }, + ["ṇ"]={ "n","̣" }, + ["Ṉ"]={ "N","̱" }, + ["ṉ"]={ "n","̱" }, + ["Ṋ"]={ "N","̭" }, + ["ṋ"]={ "n","̭" }, + ["Ṍ"]={ "Õ","́" }, + ["ṍ"]={ "õ","́" }, + ["Ṏ"]={ "Õ","̈" }, + ["ṏ"]={ "õ","̈" }, + ["Ṑ"]={ "Ō","̀" }, + ["ṑ"]={ "ō","̀" }, + ["Ṓ"]={ "Ō","́" }, + ["ṓ"]={ "ō","́" }, + ["Ṕ"]={ "P","́" }, + ["ṕ"]={ "p","́" }, + ["Ṗ"]={ "P","̇" }, + ["ṗ"]={ "p","̇" }, + ["Ṙ"]={ "R","̇" }, + ["ṙ"]={ "r","̇" }, + ["Ṛ"]={ "R","̣" }, + ["ṛ"]={ "r","̣" }, + ["Ṝ"]={ "Ṛ","̄" }, + ["ṝ"]={ "ṛ","̄" }, + ["Ṟ"]={ "R","̱" }, + ["ṟ"]={ "r","̱" }, + ["Ṡ"]={ "S","̇" }, + ["ṡ"]={ "s","̇" }, + ["Ṣ"]={ "S","̣" }, + ["ṣ"]={ "s","̣" }, + ["Ṥ"]={ "Ś","̇" }, + ["ṥ"]={ "ś","̇" }, + ["Ṧ"]={ "Š","̇" }, + ["ṧ"]={ "š","̇" }, + ["Ṩ"]={ "Ṣ","̇" }, + ["ṩ"]={ "ṣ","̇" }, + ["Ṫ"]={ "T","̇" }, + ["ṫ"]={ "t","̇" }, + ["Ṭ"]={ "T","̣" }, + ["ṭ"]={ "t","̣" }, + ["Ṯ"]={ "T","̱" }, + ["ṯ"]={ "t","̱" }, + ["Ṱ"]={ "T","̭" }, + ["ṱ"]={ "t","̭" }, + ["Ṳ"]={ "U","̤" }, + ["ṳ"]={ "u","̤" }, + ["Ṵ"]={ "U","̰" }, + ["ṵ"]={ "u","̰" }, + ["Ṷ"]={ "U","̭" }, + ["ṷ"]={ "u","̭" }, + ["Ṹ"]={ "Ũ","́" }, + ["ṹ"]={ "ũ","́" }, + ["Ṻ"]={ "Ū","̈" }, + ["ṻ"]={ "ū","̈" }, + ["Ṽ"]={ "V","̃" }, + ["ṽ"]={ "v","̃" }, + ["Ṿ"]={ "V","̣" }, + ["ṿ"]={ "v","̣" }, + ["Ẁ"]={ "W","̀" }, + ["ẁ"]={ "w","̀" }, + ["Ẃ"]={ "W","́" }, + ["ẃ"]={ "w","́" }, + ["Ẅ"]={ "W","̈" }, + ["ẅ"]={ "w","̈" }, + ["Ẇ"]={ "W","̇" }, + ["ẇ"]={ "w","̇" }, + ["Ẉ"]={ "W","̣" }, + ["ẉ"]={ "w","̣" }, + ["Ẋ"]={ "X","̇" }, + ["ẋ"]={ "x","̇" }, + ["Ẍ"]={ "X","̈" }, + ["ẍ"]={ "x","̈" }, + ["Ẏ"]={ "Y","̇" }, + ["ẏ"]={ "y","̇" }, + ["Ẑ"]={ "Z","̂" }, + ["ẑ"]={ "z","̂" }, + ["Ẓ"]={ "Z","̣" }, + ["ẓ"]={ "z","̣" }, + ["Ẕ"]={ "Z","̱" }, + ["ẕ"]={ "z","̱" }, + ["ẖ"]={ "h","̱" }, + ["ẗ"]={ "t","̈" }, + ["ẘ"]={ "w","̊" }, + ["ẙ"]={ "y","̊" }, + ["ẛ"]={ "ſ","̇" }, + ["Ạ"]={ "A","̣" }, + ["ạ"]={ "a","̣" }, + ["Ả"]={ "A","̉" }, + ["ả"]={ "a","̉" }, + ["Ấ"]={ "Â","́" }, + ["ấ"]={ "â","́" }, + ["Ầ"]={ "Â","̀" }, + ["ầ"]={ "â","̀" }, + ["Ẩ"]={ "Â","̉" }, + ["ẩ"]={ "â","̉" }, + ["Ẫ"]={ "Â","̃" }, + ["ẫ"]={ "â","̃" }, + ["Ậ"]={ "Ạ","̂" }, + ["ậ"]={ "ạ","̂" }, + ["Ắ"]={ "Ă","́" }, + ["ắ"]={ "ă","́" }, + ["Ằ"]={ "Ă","̀" }, + ["ằ"]={ "ă","̀" }, + ["Ẳ"]={ "Ă","̉" }, + ["ẳ"]={ "ă","̉" }, + ["Ẵ"]={ "Ă","̃" }, + ["ẵ"]={ "ă","̃" }, + ["Ặ"]={ "Ạ","̆" }, + ["ặ"]={ "ạ","̆" }, + ["Ẹ"]={ "E","̣" }, + ["ẹ"]={ "e","̣" }, + ["Ẻ"]={ "E","̉" }, + ["ẻ"]={ "e","̉" }, + ["Ẽ"]={ "E","̃" }, + ["ẽ"]={ "e","̃" }, + ["Ế"]={ "Ê","́" }, + ["ế"]={ "ê","́" }, + ["Ề"]={ "Ê","̀" }, + ["ề"]={ "ê","̀" }, + ["Ể"]={ "Ê","̉" }, + ["ể"]={ "ê","̉" }, + ["Ễ"]={ "Ê","̃" }, + ["ễ"]={ "ê","̃" }, + ["Ệ"]={ "Ẹ","̂" }, + ["ệ"]={ "ẹ","̂" }, + ["Ỉ"]={ "I","̉" }, + ["ỉ"]={ "i","̉" }, + ["Ị"]={ "I","̣" }, + ["ị"]={ "i","̣" }, + ["Ọ"]={ "O","̣" }, + ["ọ"]={ "o","̣" }, + ["Ỏ"]={ "O","̉" }, + ["ỏ"]={ "o","̉" }, + ["Ố"]={ "Ô","́" }, + ["ố"]={ "ô","́" }, + ["Ồ"]={ "Ô","̀" }, + ["ồ"]={ "ô","̀" }, + ["Ổ"]={ "Ô","̉" }, + ["ổ"]={ "ô","̉" }, + ["Ỗ"]={ "Ô","̃" }, + ["ỗ"]={ "ô","̃" }, + ["Ộ"]={ "Ọ","̂" }, + ["ộ"]={ "ọ","̂" }, + ["Ớ"]={ "Ơ","́" }, + ["ớ"]={ "ơ","́" }, + ["Ờ"]={ "Ơ","̀" }, + ["ờ"]={ "ơ","̀" }, + ["Ở"]={ "Ơ","̉" }, + ["ở"]={ "ơ","̉" }, + ["Ỡ"]={ "Ơ","̃" }, + ["ỡ"]={ "ơ","̃" }, + ["Ợ"]={ "Ơ","̣" }, + ["ợ"]={ "ơ","̣" }, + ["Ụ"]={ "U","̣" }, + ["ụ"]={ "u","̣" }, + ["Ủ"]={ "U","̉" }, + ["ủ"]={ "u","̉" }, + ["Ứ"]={ "Ư","́" }, + ["ứ"]={ "ư","́" }, + ["Ừ"]={ "Ư","̀" }, + ["ừ"]={ "ư","̀" }, + ["Ử"]={ "Ư","̉" }, + ["ử"]={ "ư","̉" }, + ["Ữ"]={ "Ư","̃" }, + ["ữ"]={ "ư","̃" }, + ["Ự"]={ "Ư","̣" }, + ["ự"]={ "ư","̣" }, + ["Ỳ"]={ "Y","̀" }, + ["ỳ"]={ "y","̀" }, + ["Ỵ"]={ "Y","̣" }, + ["ỵ"]={ "y","̣" }, + ["Ỷ"]={ "Y","̉" }, + ["ỷ"]={ "y","̉" }, + ["Ỹ"]={ "Y","̃" }, + ["ỹ"]={ "y","̃" }, + ["ἀ"]={ "α","̓" }, + ["ἁ"]={ "α","̔" }, + ["ἂ"]={ "ἀ","̀" }, + ["ἃ"]={ "ἁ","̀" }, + ["ἄ"]={ "ἀ","́" }, + ["ἅ"]={ "ἁ","́" }, + ["ἆ"]={ "ἀ","͂" }, + ["ἇ"]={ "ἁ","͂" }, + ["Ἀ"]={ "Α","̓" }, + ["Ἁ"]={ "Α","̔" }, + ["Ἂ"]={ "Ἀ","̀" }, + ["Ἃ"]={ "Ἁ","̀" }, + ["Ἄ"]={ "Ἀ","́" }, + ["Ἅ"]={ "Ἁ","́" }, + ["Ἆ"]={ "Ἀ","͂" }, + ["Ἇ"]={ "Ἁ","͂" }, + ["ἐ"]={ "ε","̓" }, + ["ἑ"]={ "ε","̔" }, + ["ἒ"]={ "ἐ","̀" }, + ["ἓ"]={ "ἑ","̀" }, + ["ἔ"]={ "ἐ","́" }, + ["ἕ"]={ "ἑ","́" }, + ["Ἐ"]={ "Ε","̓" }, + ["Ἑ"]={ "Ε","̔" }, + ["Ἒ"]={ "Ἐ","̀" }, + ["Ἓ"]={ "Ἑ","̀" }, + ["Ἔ"]={ "Ἐ","́" }, + ["Ἕ"]={ "Ἑ","́" }, + ["ἠ"]={ "η","̓" }, + ["ἡ"]={ "η","̔" }, + ["ἢ"]={ "ἠ","̀" }, + ["ἣ"]={ "ἡ","̀" }, + ["ἤ"]={ "ἠ","́" }, + ["ἥ"]={ "ἡ","́" }, + ["ἦ"]={ "ἠ","͂" }, + ["ἧ"]={ "ἡ","͂" }, + ["Ἠ"]={ "Η","̓" }, + ["Ἡ"]={ "Η","̔" }, + ["Ἢ"]={ "Ἠ","̀" }, + ["Ἣ"]={ "Ἡ","̀" }, + ["Ἤ"]={ "Ἠ","́" }, + ["Ἥ"]={ "Ἡ","́" }, + ["Ἦ"]={ "Ἠ","͂" }, + ["Ἧ"]={ "Ἡ","͂" }, + ["ἰ"]={ "ι","̓" }, + ["ἱ"]={ "ι","̔" }, + ["ἲ"]={ "ἰ","̀" }, + ["ἳ"]={ "ἱ","̀" }, + ["ἴ"]={ "ἰ","́" }, + ["ἵ"]={ "ἱ","́" }, + ["ἶ"]={ "ἰ","͂" }, + ["ἷ"]={ "ἱ","͂" }, + ["Ἰ"]={ "Ι","̓" }, + ["Ἱ"]={ "Ι","̔" }, + ["Ἲ"]={ "Ἰ","̀" }, + ["Ἳ"]={ "Ἱ","̀" }, + ["Ἴ"]={ "Ἰ","́" }, + ["Ἵ"]={ "Ἱ","́" }, + ["Ἶ"]={ "Ἰ","͂" }, + ["Ἷ"]={ "Ἱ","͂" }, + ["ὀ"]={ "ο","̓" }, + ["ὁ"]={ "ο","̔" }, + ["ὂ"]={ "ὀ","̀" }, + ["ὃ"]={ "ὁ","̀" }, + ["ὄ"]={ "ὀ","́" }, + ["ὅ"]={ "ὁ","́" }, + ["Ὀ"]={ "Ο","̓" }, + ["Ὁ"]={ "Ο","̔" }, + ["Ὂ"]={ "Ὀ","̀" }, + ["Ὃ"]={ "Ὁ","̀" }, + ["Ὄ"]={ "Ὀ","́" }, + ["Ὅ"]={ "Ὁ","́" }, + ["ὐ"]={ "υ","̓" }, + ["ὑ"]={ "υ","̔" }, + ["ὒ"]={ "ὐ","̀" }, + ["ὓ"]={ "ὑ","̀" }, + ["ὔ"]={ "ὐ","́" }, + ["ὕ"]={ "ὑ","́" }, + ["ὖ"]={ "ὐ","͂" }, + ["ὗ"]={ "ὑ","͂" }, + ["Ὑ"]={ "Υ","̔" }, + ["Ὓ"]={ "Ὑ","̀" }, + ["Ὕ"]={ "Ὑ","́" }, + ["Ὗ"]={ "Ὑ","͂" }, + ["ὠ"]={ "ω","̓" }, + ["ὡ"]={ "ω","̔" }, + ["ὢ"]={ "ὠ","̀" }, + ["ὣ"]={ "ὡ","̀" }, + ["ὤ"]={ "ὠ","́" }, + ["ὥ"]={ "ὡ","́" }, + ["ὦ"]={ "ὠ","͂" }, + ["ὧ"]={ "ὡ","͂" }, + ["Ὠ"]={ "Ω","̓" }, + ["Ὡ"]={ "Ω","̔" }, + ["Ὢ"]={ "Ὠ","̀" }, + ["Ὣ"]={ "Ὡ","̀" }, + ["Ὤ"]={ "Ὠ","́" }, + ["Ὥ"]={ "Ὡ","́" }, + ["Ὦ"]={ "Ὠ","͂" }, + ["Ὧ"]={ "Ὡ","͂" }, + ["ὰ"]={ "α","̀" }, + ["ὲ"]={ "ε","̀" }, + ["ὴ"]={ "η","̀" }, + ["ὶ"]={ "ι","̀" }, + ["ὸ"]={ "ο","̀" }, + ["ὺ"]={ "υ","̀" }, + ["ὼ"]={ "ω","̀" }, + ["ᾀ"]={ "ἀ","ͅ" }, + ["ᾁ"]={ "ἁ","ͅ" }, + ["ᾂ"]={ "ἂ","ͅ" }, + ["ᾃ"]={ "ἃ","ͅ" }, + ["ᾄ"]={ "ἄ","ͅ" }, + ["ᾅ"]={ "ἅ","ͅ" }, + ["ᾆ"]={ "ἆ","ͅ" }, + ["ᾇ"]={ "ἇ","ͅ" }, + ["ᾈ"]={ "Ἀ","ͅ" }, + ["ᾉ"]={ "Ἁ","ͅ" }, + ["ᾊ"]={ "Ἂ","ͅ" }, + ["ᾋ"]={ "Ἃ","ͅ" }, + ["ᾌ"]={ "Ἄ","ͅ" }, + ["ᾍ"]={ "Ἅ","ͅ" }, + ["ᾎ"]={ "Ἆ","ͅ" }, + ["ᾏ"]={ "Ἇ","ͅ" }, + ["ᾐ"]={ "ἠ","ͅ" }, + ["ᾑ"]={ "ἡ","ͅ" }, + ["ᾒ"]={ "ἢ","ͅ" }, + ["ᾓ"]={ "ἣ","ͅ" }, + ["ᾔ"]={ "ἤ","ͅ" }, + ["ᾕ"]={ "ἥ","ͅ" }, + ["ᾖ"]={ "ἦ","ͅ" }, + ["ᾗ"]={ "ἧ","ͅ" }, + ["ᾘ"]={ "Ἠ","ͅ" }, + ["ᾙ"]={ "Ἡ","ͅ" }, + ["ᾚ"]={ "Ἢ","ͅ" }, + ["ᾛ"]={ "Ἣ","ͅ" }, + ["ᾜ"]={ "Ἤ","ͅ" }, + ["ᾝ"]={ "Ἥ","ͅ" }, + ["ᾞ"]={ "Ἦ","ͅ" }, + ["ᾟ"]={ "Ἧ","ͅ" }, + ["ᾠ"]={ "ὠ","ͅ" }, + ["ᾡ"]={ "ὡ","ͅ" }, + ["ᾢ"]={ "ὢ","ͅ" }, + ["ᾣ"]={ "ὣ","ͅ" }, + ["ᾤ"]={ "ὤ","ͅ" }, + ["ᾥ"]={ "ὥ","ͅ" }, + ["ᾦ"]={ "ὦ","ͅ" }, + ["ᾧ"]={ "ὧ","ͅ" }, + ["ᾨ"]={ "Ὠ","ͅ" }, + ["ᾩ"]={ "Ὡ","ͅ" }, + ["ᾪ"]={ "Ὢ","ͅ" }, + ["ᾫ"]={ "Ὣ","ͅ" }, + ["ᾬ"]={ "Ὤ","ͅ" }, + ["ᾭ"]={ "Ὥ","ͅ" }, + ["ᾮ"]={ "Ὦ","ͅ" }, + ["ᾯ"]={ "Ὧ","ͅ" }, + ["ᾰ"]={ "α","̆" }, + ["ᾱ"]={ "α","̄" }, + ["ᾲ"]={ "ὰ","ͅ" }, + ["ᾳ"]={ "α","ͅ" }, + ["ᾴ"]={ "ά","ͅ" }, + ["ᾶ"]={ "α","͂" }, + ["ᾷ"]={ "ᾶ","ͅ" }, + ["Ᾰ"]={ "Α","̆" }, + ["Ᾱ"]={ "Α","̄" }, + ["Ὰ"]={ "Α","̀" }, + ["ᾼ"]={ "Α","ͅ" }, + ["῁"]={ "¨","͂" }, + ["ῂ"]={ "ὴ","ͅ" }, + ["ῃ"]={ "η","ͅ" }, + ["ῄ"]={ "ή","ͅ" }, + ["ῆ"]={ "η","͂" }, + ["ῇ"]={ "ῆ","ͅ" }, + ["Ὲ"]={ "Ε","̀" }, + ["Ὴ"]={ "Η","̀" }, + ["ῌ"]={ "Η","ͅ" }, + ["῍"]={ "᾿","̀" }, + ["῎"]={ "᾿","́" }, + ["῏"]={ "᾿","͂" }, + ["ῐ"]={ "ι","̆" }, + ["ῑ"]={ "ι","̄" }, + ["ῒ"]={ "ϊ","̀" }, + ["ῖ"]={ "ι","͂" }, + ["ῗ"]={ "ϊ","͂" }, + ["Ῐ"]={ "Ι","̆" }, + ["Ῑ"]={ "Ι","̄" }, + ["Ὶ"]={ "Ι","̀" }, + ["῝"]={ "῾","̀" }, + ["῞"]={ "῾","́" }, + ["῟"]={ "῾","͂" }, + ["ῠ"]={ "υ","̆" }, + ["ῡ"]={ "υ","̄" }, + ["ῢ"]={ "ϋ","̀" }, + ["ῤ"]={ "ρ","̓" }, + ["ῥ"]={ "ρ","̔" }, + ["ῦ"]={ "υ","͂" }, + ["ῧ"]={ "ϋ","͂" }, + ["Ῠ"]={ "Υ","̆" }, + ["Ῡ"]={ "Υ","̄" }, + ["Ὺ"]={ "Υ","̀" }, + ["Ῥ"]={ "Ρ","̔" }, + ["῭"]={ "¨","̀" }, + ["ῲ"]={ "ὼ","ͅ" }, + ["ῳ"]={ "ω","ͅ" }, + ["ῴ"]={ "ώ","ͅ" }, + ["ῶ"]={ "ω","͂" }, + ["ῷ"]={ "ῶ","ͅ" }, + ["Ὸ"]={ "Ο","̀" }, + ["Ὼ"]={ "Ω","̀" }, + ["ῼ"]={ "Ω","ͅ" }, + ["↚"]={ "←","̸" }, + ["↛"]={ "→","̸" }, + ["↮"]={ "↔","̸" }, + ["⇍"]={ "⇐","̸" }, + ["⇎"]={ "⇔","̸" }, + ["⇏"]={ "⇒","̸" }, + ["∄"]={ "∃","̸" }, + ["∉"]={ "∈","̸" }, + ["∌"]={ "∋","̸" }, + ["∤"]={ "∣","̸" }, + ["∦"]={ "∥","̸" }, + ["≁"]={ "∼","̸" }, + ["≄"]={ "≃","̸" }, + ["≇"]={ "≅","̸" }, + ["≉"]={ "≈","̸" }, + ["≠"]={ "=","̸" }, + ["≢"]={ "≡","̸" }, + ["≭"]={ "≍","̸" }, + ["≮"]={ "<","̸" }, + ["≯"]={ ">","̸" }, + ["≰"]={ "≤","̸" }, + ["≱"]={ "≥","̸" }, + ["≴"]={ "≲","̸" }, + ["≵"]={ "≳","̸" }, + ["≸"]={ "≶","̸" }, + ["≹"]={ "≷","̸" }, + ["⊀"]={ "≺","̸" }, + ["⊁"]={ "≻","̸" }, + ["⊄"]={ "⊂","̸" }, + ["⊅"]={ "⊃","̸" }, + ["⊈"]={ "⊆","̸" }, + ["⊉"]={ "⊇","̸" }, + ["⊬"]={ "⊢","̸" }, + ["⊭"]={ "⊨","̸" }, + ["⊮"]={ "⊩","̸" }, + ["⊯"]={ "⊫","̸" }, + ["⋠"]={ "≼","̸" }, + ["⋡"]={ "≽","̸" }, + ["⋢"]={ "⊑","̸" }, + ["⋣"]={ "⊒","̸" }, + ["⋪"]={ "⊲","̸" }, + ["⋫"]={ "⊳","̸" }, + ["⋬"]={ "⊴","̸" }, + ["⋭"]={ "⊵","̸" }, + ["⫝̸"]={ "⫝","̸" }, + ["が"]={ "か","゙" }, + ["ぎ"]={ "き","゙" }, + ["ぐ"]={ "く","゙" }, + ["げ"]={ "け","゙" }, + ["ご"]={ "こ","゙" }, + ["ざ"]={ "さ","゙" }, + ["じ"]={ "し","゙" }, + ["ず"]={ "す","゙" }, + ["ぜ"]={ "せ","゙" }, + ["ぞ"]={ "そ","゙" }, + ["だ"]={ "た","゙" }, + ["ぢ"]={ "ち","゙" }, + ["づ"]={ "つ","゙" }, + ["で"]={ "て","゙" }, + ["ど"]={ "と","゙" }, + ["ば"]={ "は","゙" }, + ["ぱ"]={ "は","゚" }, + ["び"]={ "ひ","゙" }, + ["ぴ"]={ "ひ","゚" }, + ["ぶ"]={ "ふ","゙" }, + ["ぷ"]={ "ふ","゚" }, + ["べ"]={ "へ","゙" }, + ["ぺ"]={ "へ","゚" }, + ["ぼ"]={ "ほ","゙" }, + ["ぽ"]={ "ほ","゚" }, + ["ゔ"]={ "う","゙" }, + ["ゞ"]={ "ゝ","゙" }, + ["ガ"]={ "カ","゙" }, + ["ギ"]={ "キ","゙" }, + ["グ"]={ "ク","゙" }, + ["ゲ"]={ "ケ","゙" }, + ["ゴ"]={ "コ","゙" }, + ["ザ"]={ "サ","゙" }, + ["ジ"]={ "シ","゙" }, + ["ズ"]={ "ス","゙" }, + ["ゼ"]={ "セ","゙" }, + ["ゾ"]={ "ソ","゙" }, + ["ダ"]={ "タ","゙" }, + ["ヂ"]={ "チ","゙" }, + ["ヅ"]={ "ツ","゙" }, + ["デ"]={ "テ","゙" }, + ["ド"]={ "ト","゙" }, + ["バ"]={ "ハ","゙" }, + ["パ"]={ "ハ","゚" }, + ["ビ"]={ "ヒ","゙" }, + ["ピ"]={ "ヒ","゚" }, + ["ブ"]={ "フ","゙" }, + ["プ"]={ "フ","゚" }, + ["ベ"]={ "ヘ","゙" }, + ["ペ"]={ "ヘ","゚" }, + ["ボ"]={ "ホ","゙" }, + ["ポ"]={ "ホ","゚" }, + ["ヴ"]={ "ウ","゙" }, + ["ヷ"]={ "ワ","゙" }, + ["ヸ"]={ "ヰ","゙" }, + ["ヹ"]={ "ヱ","゙" }, + ["ヺ"]={ "ヲ","゙" }, + ["ヾ"]={ "ヽ","゙" }, + ["יִ"]={ "י","ִ" }, + ["ײַ"]={ "ײ","ַ" }, + ["שׁ"]={ "ש","ׁ" }, + ["שׂ"]={ "ש","ׂ" }, + ["שּׁ"]={ "שּ","ׁ" }, + ["שּׂ"]={ "שּ","ׂ" }, + ["אַ"]={ "א","ַ" }, + ["אָ"]={ "א","ָ" }, + ["אּ"]={ "א","ּ" }, + ["בּ"]={ "ב","ּ" }, + ["גּ"]={ "ג","ּ" }, + ["דּ"]={ "ד","ּ" }, + ["הּ"]={ "ה","ּ" }, + ["וּ"]={ "ו","ּ" }, + ["זּ"]={ "ז","ּ" }, + ["טּ"]={ "ט","ּ" }, + ["יּ"]={ "י","ּ" }, + ["ךּ"]={ "ך","ּ" }, + ["כּ"]={ "כ","ּ" }, + ["לּ"]={ "ל","ּ" }, + ["מּ"]={ "מ","ּ" }, + ["נּ"]={ "נ","ּ" }, + ["סּ"]={ "ס","ּ" }, + ["ףּ"]={ "ף","ּ" }, + ["פּ"]={ "פ","ּ" }, + ["צּ"]={ "צ","ּ" }, + ["קּ"]={ "ק","ּ" }, + ["רּ"]={ "ר","ּ" }, + ["שּ"]={ "ש","ּ" }, + ["תּ"]={ "ת","ּ" }, + ["וֹ"]={ "ו","ֹ" }, + ["בֿ"]={ "ב","ֿ" }, + ["כֿ"]={ "כ","ֿ" }, + ["פֿ"]={ "פ","ֿ" }, + ["𑂚"]={ "𑂙","𑂺" }, + ["𑂜"]={ "𑂛","𑂺" }, + ["𑂫"]={ "𑂥","𑂺" }, + ["𑄮"]={ "𑄱","𑄧" }, + ["𑄯"]={ "𑄲","𑄧" }, + ["𑍋"]={ "𑍇","𑌾" }, + ["𑍌"]={ "𑍇","𑍗" }, + ["𑒻"]={ "𑒹","𑒺" }, + ["𑒼"]={ "𑒹","𑒰" }, + ["𑒾"]={ "𑒹","𑒽" }, + ["𑖺"]={ "𑖸","𑖯" }, + ["𑖻"]={ "𑖹","𑖯" }, + ["𝅗𝅥"]={ "𝅗","𝅥" }, + ["𝅘𝅥"]={ "𝅘","𝅥" }, + ["𝅘𝅥𝅮"]={ "𝅘𝅥","𝅮" }, + ["𝅘𝅥𝅯"]={ "𝅘𝅥","𝅯" }, + ["𝅘𝅥𝅰"]={ "𝅘𝅥","𝅰" }, + ["𝅘𝅥𝅱"]={ "𝅘𝅥","𝅱" }, + ["𝅘𝅥𝅲"]={ "𝅘𝅥","𝅲" }, + ["𝆹𝅥"]={ "𝆹","𝅥" }, + ["𝆺𝅥"]={ "𝆺","𝅥" }, + ["𝆹𝅥𝅮"]={ "𝆹𝅥","𝅮" }, + ["𝆺𝅥𝅮"]={ "𝆺𝅥","𝅮" }, + ["𝆹𝅥𝅯"]={ "𝆹𝅥","𝅯" }, + ["𝆺𝅥𝅯"]={ "𝆺𝅥","𝅯" }, + }, + }, + { + ["data"]={ + ["À"]={ "A","̀" }, + ["Á"]={ "A","́" }, + ["Â"]={ "A","̂" }, + ["Ã"]={ "A","̃" }, + ["Ä"]={ "A","̈" }, + ["Å"]={ "A","̊" }, + ["Ç"]={ "C","̧" }, + ["È"]={ "E","̀" }, + ["É"]={ "E","́" }, + ["Ê"]={ "E","̂" }, + ["Ë"]={ "E","̈" }, + ["Ì"]={ "I","̀" }, + ["Í"]={ "I","́" }, + ["Î"]={ "I","̂" }, + ["Ï"]={ "I","̈" }, + ["Ñ"]={ "N","̃" }, + ["Ò"]={ "O","̀" }, + ["Ó"]={ "O","́" }, + ["Ô"]={ "O","̂" }, + ["Õ"]={ "O","̃" }, + ["Ö"]={ "O","̈" }, + ["Ù"]={ "U","̀" }, + ["Ú"]={ "U","́" }, + ["Û"]={ "U","̂" }, + ["Ü"]={ "U","̈" }, + ["Ý"]={ "Y","́" }, + ["à"]={ "a","̀" }, + ["á"]={ "a","́" }, + ["â"]={ "a","̂" }, + ["ã"]={ "a","̃" }, + ["ä"]={ "a","̈" }, + ["å"]={ "a","̊" }, + ["ç"]={ "c","̧" }, + ["è"]={ "e","̀" }, + ["é"]={ "e","́" }, + ["ê"]={ "e","̂" }, + ["ë"]={ "e","̈" }, + ["ì"]={ "i","̀" }, + ["í"]={ "i","́" }, + ["î"]={ "i","̂" }, + ["ï"]={ "i","̈" }, + ["ñ"]={ "n","̃" }, + ["ò"]={ "o","̀" }, + ["ó"]={ "o","́" }, + ["ô"]={ "o","̂" }, + ["õ"]={ "o","̃" }, + ["ö"]={ "o","̈" }, + ["ù"]={ "u","̀" }, + ["ú"]={ "u","́" }, + ["û"]={ "u","̂" }, + ["ü"]={ "u","̈" }, + ["ý"]={ "y","́" }, + ["ÿ"]={ "y","̈" }, + ["Ā"]={ "A","̄" }, + ["ā"]={ "a","̄" }, + ["Ă"]={ "A","̆" }, + ["ă"]={ "a","̆" }, + ["Ą"]={ "A","̨" }, + ["ą"]={ "a","̨" }, + ["Ć"]={ "C","́" }, + ["ć"]={ "c","́" }, + ["Ĉ"]={ "C","̂" }, + ["ĉ"]={ "c","̂" }, + ["Ċ"]={ "C","̇" }, + ["ċ"]={ "c","̇" }, + ["Č"]={ "C","̌" }, + ["č"]={ "c","̌" }, + ["Ď"]={ "D","̌" }, + ["ď"]={ "d","̌" }, + ["Ē"]={ "E","̄" }, + ["ē"]={ "e","̄" }, + ["Ĕ"]={ "E","̆" }, + ["ĕ"]={ "e","̆" }, + ["Ė"]={ "E","̇" }, + ["ė"]={ "e","̇" }, + ["Ę"]={ "E","̨" }, + ["ę"]={ "e","̨" }, + ["Ě"]={ "E","̌" }, + ["ě"]={ "e","̌" }, + ["Ĝ"]={ "G","̂" }, + ["ĝ"]={ "g","̂" }, + ["Ğ"]={ "G","̆" }, + ["ğ"]={ "g","̆" }, + ["Ġ"]={ "G","̇" }, + ["ġ"]={ "g","̇" }, + ["Ģ"]={ "G","̧" }, + ["ģ"]={ "g","̧" }, + ["Ĥ"]={ "H","̂" }, + ["ĥ"]={ "h","̂" }, + ["Ĩ"]={ "I","̃" }, + ["ĩ"]={ "i","̃" }, + ["Ī"]={ "I","̄" }, + ["ī"]={ "i","̄" }, + ["Ĭ"]={ "I","̆" }, + ["ĭ"]={ "i","̆" }, + ["Į"]={ "I","̨" }, + ["į"]={ "i","̨" }, + ["İ"]={ "I","̇" }, + ["Ĵ"]={ "J","̂" }, + ["ĵ"]={ "j","̂" }, + ["Ķ"]={ "K","̧" }, + ["ķ"]={ "k","̧" }, + ["Ĺ"]={ "L","́" }, + ["ĺ"]={ "l","́" }, + ["Ļ"]={ "L","̧" }, + ["ļ"]={ "l","̧" }, + ["Ľ"]={ "L","̌" }, + ["ľ"]={ "l","̌" }, + ["Ń"]={ "N","́" }, + ["ń"]={ "n","́" }, + ["Ņ"]={ "N","̧" }, + ["ņ"]={ "n","̧" }, + ["Ň"]={ "N","̌" }, + ["ň"]={ "n","̌" }, + ["Ō"]={ "O","̄" }, + ["ō"]={ "o","̄" }, + ["Ŏ"]={ "O","̆" }, + ["ŏ"]={ "o","̆" }, + ["Ő"]={ "O","̋" }, + ["ő"]={ "o","̋" }, + ["Ŕ"]={ "R","́" }, + ["ŕ"]={ "r","́" }, + ["Ŗ"]={ "R","̧" }, + ["ŗ"]={ "r","̧" }, + ["Ř"]={ "R","̌" }, + ["ř"]={ "r","̌" }, + ["Ś"]={ "S","́" }, + ["ś"]={ "s","́" }, + ["Ŝ"]={ "S","̂" }, + ["ŝ"]={ "s","̂" }, + ["Ş"]={ "S","̧" }, + ["ş"]={ "s","̧" }, + ["Š"]={ "S","̌" }, + ["š"]={ "s","̌" }, + ["Ţ"]={ "T","̧" }, + ["ţ"]={ "t","̧" }, + ["Ť"]={ "T","̌" }, + ["ť"]={ "t","̌" }, + ["Ũ"]={ "U","̃" }, + ["ũ"]={ "u","̃" }, + ["Ū"]={ "U","̄" }, + ["ū"]={ "u","̄" }, + ["Ŭ"]={ "U","̆" }, + ["ŭ"]={ "u","̆" }, + ["Ů"]={ "U","̊" }, + ["ů"]={ "u","̊" }, + ["Ű"]={ "U","̋" }, + ["ű"]={ "u","̋" }, + ["Ų"]={ "U","̨" }, + ["ų"]={ "u","̨" }, + ["Ŵ"]={ "W","̂" }, + ["ŵ"]={ "w","̂" }, + ["Ŷ"]={ "Y","̂" }, + ["ŷ"]={ "y","̂" }, + ["Ÿ"]={ "Y","̈" }, + ["Ź"]={ "Z","́" }, + ["ź"]={ "z","́" }, + ["Ż"]={ "Z","̇" }, + ["ż"]={ "z","̇" }, + ["Ž"]={ "Z","̌" }, + ["ž"]={ "z","̌" }, + ["Ơ"]={ "O","̛" }, + ["ơ"]={ "o","̛" }, + ["Ư"]={ "U","̛" }, + ["ư"]={ "u","̛" }, + ["Ǎ"]={ "A","̌" }, + ["ǎ"]={ "a","̌" }, + ["Ǐ"]={ "I","̌" }, + ["ǐ"]={ "i","̌" }, + ["Ǒ"]={ "O","̌" }, + ["ǒ"]={ "o","̌" }, + ["Ǔ"]={ "U","̌" }, + ["ǔ"]={ "u","̌" }, + ["Ǖ"]={ "Ü","̄" }, + ["ǖ"]={ "ü","̄" }, + ["Ǘ"]={ "Ü","́" }, + ["ǘ"]={ "ü","́" }, + ["Ǚ"]={ "Ü","̌" }, + ["ǚ"]={ "ü","̌" }, + ["Ǜ"]={ "Ü","̀" }, + ["ǜ"]={ "ü","̀" }, + ["Ǟ"]={ "Ä","̄" }, + ["ǟ"]={ "ä","̄" }, + ["Ǡ"]={ "Ȧ","̄" }, + ["ǡ"]={ "ȧ","̄" }, + ["Ǣ"]={ "Æ","̄" }, + ["ǣ"]={ "æ","̄" }, + ["Ǧ"]={ "G","̌" }, + ["ǧ"]={ "g","̌" }, + ["Ǩ"]={ "K","̌" }, + ["ǩ"]={ "k","̌" }, + ["Ǫ"]={ "O","̨" }, + ["ǫ"]={ "o","̨" }, + ["Ǭ"]={ "Ǫ","̄" }, + ["ǭ"]={ "ǫ","̄" }, + ["Ǯ"]={ "Ʒ","̌" }, + ["ǯ"]={ "ʒ","̌" }, + ["ǰ"]={ "j","̌" }, + ["Ǵ"]={ "G","́" }, + ["ǵ"]={ "g","́" }, + ["Ǹ"]={ "N","̀" }, + ["ǹ"]={ "n","̀" }, + ["Ǻ"]={ "Å","́" }, + ["ǻ"]={ "å","́" }, + ["Ǽ"]={ "Æ","́" }, + ["ǽ"]={ "æ","́" }, + ["Ǿ"]={ "Ø","́" }, + ["ǿ"]={ "ø","́" }, + ["Ȁ"]={ "A","̏" }, + ["ȁ"]={ "a","̏" }, + ["Ȃ"]={ "A","̑" }, + ["ȃ"]={ "a","̑" }, + ["Ȅ"]={ "E","̏" }, + ["ȅ"]={ "e","̏" }, + ["Ȇ"]={ "E","̑" }, + ["ȇ"]={ "e","̑" }, + ["Ȉ"]={ "I","̏" }, + ["ȉ"]={ "i","̏" }, + ["Ȋ"]={ "I","̑" }, + ["ȋ"]={ "i","̑" }, + ["Ȍ"]={ "O","̏" }, + ["ȍ"]={ "o","̏" }, + ["Ȏ"]={ "O","̑" }, + ["ȏ"]={ "o","̑" }, + ["Ȑ"]={ "R","̏" }, + ["ȑ"]={ "r","̏" }, + ["Ȓ"]={ "R","̑" }, + ["ȓ"]={ "r","̑" }, + ["Ȕ"]={ "U","̏" }, + ["ȕ"]={ "u","̏" }, + ["Ȗ"]={ "U","̑" }, + ["ȗ"]={ "u","̑" }, + ["Ș"]={ "S","̦" }, + ["ș"]={ "s","̦" }, + ["Ț"]={ "T","̦" }, + ["ț"]={ "t","̦" }, + ["Ȟ"]={ "H","̌" }, + ["ȟ"]={ "h","̌" }, + ["Ȧ"]={ "A","̇" }, + ["ȧ"]={ "a","̇" }, + ["Ȩ"]={ "E","̧" }, + ["ȩ"]={ "e","̧" }, + ["Ȫ"]={ "Ö","̄" }, + ["ȫ"]={ "ö","̄" }, + ["Ȭ"]={ "Õ","̄" }, + ["ȭ"]={ "õ","̄" }, + ["Ȯ"]={ "O","̇" }, + ["ȯ"]={ "o","̇" }, + ["Ȱ"]={ "Ȯ","̄" }, + ["ȱ"]={ "ȯ","̄" }, + ["Ȳ"]={ "Y","̄" }, + ["ȳ"]={ "y","̄" }, + ["̈́"]={ "̈","́" }, + ["΅"]={ "¨","́" }, + ["Ά"]={ "Α","́" }, + ["Έ"]={ "Ε","́" }, + ["Ή"]={ "Η","́" }, + ["Ί"]={ "Ι","́" }, + ["Ό"]={ "Ο","́" }, + ["Ύ"]={ "Υ","́" }, + ["Ώ"]={ "Ω","́" }, + ["ΐ"]={ "ϊ","́" }, + ["Ϊ"]={ "Ι","̈" }, + ["Ϋ"]={ "Υ","̈" }, + ["ά"]={ "α","́" }, + ["έ"]={ "ε","́" }, + ["ή"]={ "η","́" }, + ["ί"]={ "ι","́" }, + ["ΰ"]={ "ϋ","́" }, + ["ϊ"]={ "ι","̈" }, + ["ϋ"]={ "υ","̈" }, + ["ό"]={ "ο","́" }, + ["ύ"]={ "υ","́" }, + ["ώ"]={ "ω","́" }, + ["ϓ"]={ "ϒ","́" }, + ["ϔ"]={ "ϒ","̈" }, + ["Ѐ"]={ "Е","̀" }, + ["Ё"]={ "Е","̈" }, + ["Ѓ"]={ "Г","́" }, + ["Ї"]={ "І","̈" }, + ["Ќ"]={ "К","́" }, + ["Ѝ"]={ "И","̀" }, + ["Ў"]={ "У","̆" }, + ["Й"]={ "И","̆" }, + ["й"]={ "и","̆" }, + ["ѐ"]={ "е","̀" }, + ["ё"]={ "е","̈" }, + ["ѓ"]={ "г","́" }, + ["ї"]={ "і","̈" }, + ["ќ"]={ "к","́" }, + ["ѝ"]={ "и","̀" }, + ["ў"]={ "у","̆" }, + ["Ѷ"]={ "Ѵ","̏" }, + ["ѷ"]={ "ѵ","̏" }, + ["Ӂ"]={ "Ж","̆" }, + ["ӂ"]={ "ж","̆" }, + ["Ӑ"]={ "А","̆" }, + ["ӑ"]={ "а","̆" }, + ["Ӓ"]={ "А","̈" }, + ["ӓ"]={ "а","̈" }, + ["Ӗ"]={ "Е","̆" }, + ["ӗ"]={ "е","̆" }, + ["Ӛ"]={ "Ә","̈" }, + ["ӛ"]={ "ә","̈" }, + ["Ӝ"]={ "Ж","̈" }, + ["ӝ"]={ "ж","̈" }, + ["Ӟ"]={ "З","̈" }, + ["ӟ"]={ "з","̈" }, + ["Ӣ"]={ "И","̄" }, + ["ӣ"]={ "и","̄" }, + ["Ӥ"]={ "И","̈" }, + ["ӥ"]={ "и","̈" }, + ["Ӧ"]={ "О","̈" }, + ["ӧ"]={ "о","̈" }, + ["Ӫ"]={ "Ө","̈" }, + ["ӫ"]={ "ө","̈" }, + ["Ӭ"]={ "Э","̈" }, + ["ӭ"]={ "э","̈" }, + ["Ӯ"]={ "У","̄" }, + ["ӯ"]={ "у","̄" }, + ["Ӱ"]={ "У","̈" }, + ["ӱ"]={ "у","̈" }, + ["Ӳ"]={ "У","̋" }, + ["ӳ"]={ "у","̋" }, + ["Ӵ"]={ "Ч","̈" }, + ["ӵ"]={ "ч","̈" }, + ["Ӹ"]={ "Ы","̈" }, + ["ӹ"]={ "ы","̈" }, + ["آ"]={ "ا","ٓ" }, + ["أ"]={ "ا","ٔ" }, + ["ؤ"]={ "و","ٔ" }, + ["إ"]={ "ا","ٕ" }, + ["ئ"]={ "ي","ٔ" }, + ["ۀ"]={ "ە","ٔ" }, + ["ۂ"]={ "ہ","ٔ" }, + ["ۓ"]={ "ے","ٔ" }, + ["ऩ"]={ "न","़" }, + ["ऱ"]={ "र","़" }, + ["ऴ"]={ "ळ","़" }, + ["क़"]={ "क","़" }, + ["ख़"]={ "ख","़" }, + ["ग़"]={ "ग","़" }, + ["ज़"]={ "ज","़" }, + ["ड़"]={ "ड","़" }, + ["ढ़"]={ "ढ","़" }, + ["फ़"]={ "फ","़" }, + ["य़"]={ "य","़" }, + ["ো"]={ "ে","া" }, + ["ৌ"]={ "ে","ৗ" }, + ["ড়"]={ "ড","়" }, + ["ঢ়"]={ "ঢ","়" }, + ["য়"]={ "য","়" }, + ["ਲ਼"]={ "ਲ","਼" }, + ["ਸ਼"]={ "ਸ","਼" }, + ["ਖ਼"]={ "ਖ","਼" }, + ["ਗ਼"]={ "ਗ","਼" }, + ["ਜ਼"]={ "ਜ","਼" }, + ["ਫ਼"]={ "ਫ","਼" }, + ["ୈ"]={ "େ","ୖ" }, + ["ୋ"]={ "େ","ା" }, + ["ୌ"]={ "େ","ୗ" }, + ["ଡ଼"]={ "ଡ","଼" }, + ["ଢ଼"]={ "ଢ","଼" }, + ["ஔ"]={ "ஒ","ௗ" }, + ["ொ"]={ "ெ","ா" }, + ["ோ"]={ "ே","ா" }, + ["ௌ"]={ "ெ","ௗ" }, + ["ై"]={ "ె","ౖ" }, + ["ೀ"]={ "ಿ","ೕ" }, + ["ೇ"]={ "ೆ","ೕ" }, + ["ೈ"]={ "ೆ","ೖ" }, + ["ೊ"]={ "ೆ","ೂ" }, + ["ೋ"]={ "ೊ","ೕ" }, + ["ൊ"]={ "െ","ാ" }, + ["ോ"]={ "േ","ാ" }, + ["ൌ"]={ "െ","ൗ" }, + ["ේ"]={ "ෙ","්" }, + ["ො"]={ "ෙ","ා" }, + ["ෝ"]={ "ො","්" }, + ["ෞ"]={ "ෙ","ෟ" }, + ["གྷ"]={ "ག","ྷ" }, + ["ཌྷ"]={ "ཌ","ྷ" }, + ["དྷ"]={ "ད","ྷ" }, + ["བྷ"]={ "བ","ྷ" }, + ["ཛྷ"]={ "ཛ","ྷ" }, + ["ཀྵ"]={ "ཀ","ྵ" }, + ["ཱི"]={ "ཱ","ི" }, + ["ཱུ"]={ "ཱ","ུ" }, + ["ྲྀ"]={ "ྲ","ྀ" }, + ["ླྀ"]={ "ླ","ྀ" }, + ["ཱྀ"]={ "ཱ","ྀ" }, + ["ྒྷ"]={ "ྒ","ྷ" }, + ["ྜྷ"]={ "ྜ","ྷ" }, + ["ྡྷ"]={ "ྡ","ྷ" }, + ["ྦྷ"]={ "ྦ","ྷ" }, + ["ྫྷ"]={ "ྫ","ྷ" }, + ["ྐྵ"]={ "ྐ","ྵ" }, + ["ဦ"]={ "ဥ","ီ" }, + ["ᬆ"]={ "ᬅ","ᬵ" }, + ["ᬈ"]={ "ᬇ","ᬵ" }, + ["ᬊ"]={ "ᬉ","ᬵ" }, + ["ᬌ"]={ "ᬋ","ᬵ" }, + ["ᬎ"]={ "ᬍ","ᬵ" }, + ["ᬒ"]={ "ᬑ","ᬵ" }, + ["ᬻ"]={ "ᬺ","ᬵ" }, + ["ᬽ"]={ "ᬼ","ᬵ" }, + ["ᭀ"]={ "ᬾ","ᬵ" }, + ["ᭁ"]={ "ᬿ","ᬵ" }, + ["ᭃ"]={ "ᭂ","ᬵ" }, + ["Ḁ"]={ "A","̥" }, + ["ḁ"]={ "a","̥" }, + ["Ḃ"]={ "B","̇" }, + ["ḃ"]={ "b","̇" }, + ["Ḅ"]={ "B","̣" }, + ["ḅ"]={ "b","̣" }, + ["Ḇ"]={ "B","̱" }, + ["ḇ"]={ "b","̱" }, + ["Ḉ"]={ "Ç","́" }, + ["ḉ"]={ "ç","́" }, + ["Ḋ"]={ "D","̇" }, + ["ḋ"]={ "d","̇" }, + ["Ḍ"]={ "D","̣" }, + ["ḍ"]={ "d","̣" }, + ["Ḏ"]={ "D","̱" }, + ["ḏ"]={ "d","̱" }, + ["Ḑ"]={ "D","̧" }, + ["ḑ"]={ "d","̧" }, + ["Ḓ"]={ "D","̭" }, + ["ḓ"]={ "d","̭" }, + ["Ḕ"]={ "Ē","̀" }, + ["ḕ"]={ "ē","̀" }, + ["Ḗ"]={ "Ē","́" }, + ["ḗ"]={ "ē","́" }, + ["Ḙ"]={ "E","̭" }, + ["ḙ"]={ "e","̭" }, + ["Ḛ"]={ "E","̰" }, + ["ḛ"]={ "e","̰" }, + ["Ḝ"]={ "Ȩ","̆" }, + ["ḝ"]={ "ȩ","̆" }, + ["Ḟ"]={ "F","̇" }, + ["ḟ"]={ "f","̇" }, + ["Ḡ"]={ "G","̄" }, + ["ḡ"]={ "g","̄" }, + ["Ḣ"]={ "H","̇" }, + ["ḣ"]={ "h","̇" }, + ["Ḥ"]={ "H","̣" }, + ["ḥ"]={ "h","̣" }, + ["Ḧ"]={ "H","̈" }, + ["ḧ"]={ "h","̈" }, + ["Ḩ"]={ "H","̧" }, + ["ḩ"]={ "h","̧" }, + ["Ḫ"]={ "H","̮" }, + ["ḫ"]={ "h","̮" }, + ["Ḭ"]={ "I","̰" }, + ["ḭ"]={ "i","̰" }, + ["Ḯ"]={ "Ï","́" }, + ["ḯ"]={ "ï","́" }, + ["Ḱ"]={ "K","́" }, + ["ḱ"]={ "k","́" }, + ["Ḳ"]={ "K","̣" }, + ["ḳ"]={ "k","̣" }, + ["Ḵ"]={ "K","̱" }, + ["ḵ"]={ "k","̱" }, + ["Ḷ"]={ "L","̣" }, + ["ḷ"]={ "l","̣" }, + ["Ḹ"]={ "Ḷ","̄" }, + ["ḹ"]={ "ḷ","̄" }, + ["Ḻ"]={ "L","̱" }, + ["ḻ"]={ "l","̱" }, + ["Ḽ"]={ "L","̭" }, + ["ḽ"]={ "l","̭" }, + ["Ḿ"]={ "M","́" }, + ["ḿ"]={ "m","́" }, + ["Ṁ"]={ "M","̇" }, + ["ṁ"]={ "m","̇" }, + ["Ṃ"]={ "M","̣" }, + ["ṃ"]={ "m","̣" }, + ["Ṅ"]={ "N","̇" }, + ["ṅ"]={ "n","̇" }, + ["Ṇ"]={ "N","̣" }, + ["ṇ"]={ "n","̣" }, + ["Ṉ"]={ "N","̱" }, + ["ṉ"]={ "n","̱" }, + ["Ṋ"]={ "N","̭" }, + ["ṋ"]={ "n","̭" }, + ["Ṍ"]={ "Õ","́" }, + ["ṍ"]={ "õ","́" }, + ["Ṏ"]={ "Õ","̈" }, + ["ṏ"]={ "õ","̈" }, + ["Ṑ"]={ "Ō","̀" }, + ["ṑ"]={ "ō","̀" }, + ["Ṓ"]={ "Ō","́" }, + ["ṓ"]={ "ō","́" }, + ["Ṕ"]={ "P","́" }, + ["ṕ"]={ "p","́" }, + ["Ṗ"]={ "P","̇" }, + ["ṗ"]={ "p","̇" }, + ["Ṙ"]={ "R","̇" }, + ["ṙ"]={ "r","̇" }, + ["Ṛ"]={ "R","̣" }, + ["ṛ"]={ "r","̣" }, + ["Ṝ"]={ "Ṛ","̄" }, + ["ṝ"]={ "ṛ","̄" }, + ["Ṟ"]={ "R","̱" }, + ["ṟ"]={ "r","̱" }, + ["Ṡ"]={ "S","̇" }, + ["ṡ"]={ "s","̇" }, + ["Ṣ"]={ "S","̣" }, + ["ṣ"]={ "s","̣" }, + ["Ṥ"]={ "Ś","̇" }, + ["ṥ"]={ "ś","̇" }, + ["Ṧ"]={ "Š","̇" }, + ["ṧ"]={ "š","̇" }, + ["Ṩ"]={ "Ṣ","̇" }, + ["ṩ"]={ "ṣ","̇" }, + ["Ṫ"]={ "T","̇" }, + ["ṫ"]={ "t","̇" }, + ["Ṭ"]={ "T","̣" }, + ["ṭ"]={ "t","̣" }, + ["Ṯ"]={ "T","̱" }, + ["ṯ"]={ "t","̱" }, + ["Ṱ"]={ "T","̭" }, + ["ṱ"]={ "t","̭" }, + ["Ṳ"]={ "U","̤" }, + ["ṳ"]={ "u","̤" }, + ["Ṵ"]={ "U","̰" }, + ["ṵ"]={ "u","̰" }, + ["Ṷ"]={ "U","̭" }, + ["ṷ"]={ "u","̭" }, + ["Ṹ"]={ "Ũ","́" }, + ["ṹ"]={ "ũ","́" }, + ["Ṻ"]={ "Ū","̈" }, + ["ṻ"]={ "ū","̈" }, + ["Ṽ"]={ "V","̃" }, + ["ṽ"]={ "v","̃" }, + ["Ṿ"]={ "V","̣" }, + ["ṿ"]={ "v","̣" }, + ["Ẁ"]={ "W","̀" }, + ["ẁ"]={ "w","̀" }, + ["Ẃ"]={ "W","́" }, + ["ẃ"]={ "w","́" }, + ["Ẅ"]={ "W","̈" }, + ["ẅ"]={ "w","̈" }, + ["Ẇ"]={ "W","̇" }, + ["ẇ"]={ "w","̇" }, + ["Ẉ"]={ "W","̣" }, + ["ẉ"]={ "w","̣" }, + ["Ẋ"]={ "X","̇" }, + ["ẋ"]={ "x","̇" }, + ["Ẍ"]={ "X","̈" }, + ["ẍ"]={ "x","̈" }, + ["Ẏ"]={ "Y","̇" }, + ["ẏ"]={ "y","̇" }, + ["Ẑ"]={ "Z","̂" }, + ["ẑ"]={ "z","̂" }, + ["Ẓ"]={ "Z","̣" }, + ["ẓ"]={ "z","̣" }, + ["Ẕ"]={ "Z","̱" }, + ["ẕ"]={ "z","̱" }, + ["ẖ"]={ "h","̱" }, + ["ẗ"]={ "t","̈" }, + ["ẘ"]={ "w","̊" }, + ["ẙ"]={ "y","̊" }, + ["ẛ"]={ "ſ","̇" }, + ["Ạ"]={ "A","̣" }, + ["ạ"]={ "a","̣" }, + ["Ả"]={ "A","̉" }, + ["ả"]={ "a","̉" }, + ["Ấ"]={ "Â","́" }, + ["ấ"]={ "â","́" }, + ["Ầ"]={ "Â","̀" }, + ["ầ"]={ "â","̀" }, + ["Ẩ"]={ "Â","̉" }, + ["ẩ"]={ "â","̉" }, + ["Ẫ"]={ "Â","̃" }, + ["ẫ"]={ "â","̃" }, + ["Ậ"]={ "Ạ","̂" }, + ["ậ"]={ "ạ","̂" }, + ["Ắ"]={ "Ă","́" }, + ["ắ"]={ "ă","́" }, + ["Ằ"]={ "Ă","̀" }, + ["ằ"]={ "ă","̀" }, + ["Ẳ"]={ "Ă","̉" }, + ["ẳ"]={ "ă","̉" }, + ["Ẵ"]={ "Ă","̃" }, + ["ẵ"]={ "ă","̃" }, + ["Ặ"]={ "Ạ","̆" }, + ["ặ"]={ "ạ","̆" }, + ["Ẹ"]={ "E","̣" }, + ["ẹ"]={ "e","̣" }, + ["Ẻ"]={ "E","̉" }, + ["ẻ"]={ "e","̉" }, + ["Ẽ"]={ "E","̃" }, + ["ẽ"]={ "e","̃" }, + ["Ế"]={ "Ê","́" }, + ["ế"]={ "ê","́" }, + ["Ề"]={ "Ê","̀" }, + ["ề"]={ "ê","̀" }, + ["Ể"]={ "Ê","̉" }, + ["ể"]={ "ê","̉" }, + ["Ễ"]={ "Ê","̃" }, + ["ễ"]={ "ê","̃" }, + ["Ệ"]={ "Ẹ","̂" }, + ["ệ"]={ "ẹ","̂" }, + ["Ỉ"]={ "I","̉" }, + ["ỉ"]={ "i","̉" }, + ["Ị"]={ "I","̣" }, + ["ị"]={ "i","̣" }, + ["Ọ"]={ "O","̣" }, + ["ọ"]={ "o","̣" }, + ["Ỏ"]={ "O","̉" }, + ["ỏ"]={ "o","̉" }, + ["Ố"]={ "Ô","́" }, + ["ố"]={ "ô","́" }, + ["Ồ"]={ "Ô","̀" }, + ["ồ"]={ "ô","̀" }, + ["Ổ"]={ "Ô","̉" }, + ["ổ"]={ "ô","̉" }, + ["Ỗ"]={ "Ô","̃" }, + ["ỗ"]={ "ô","̃" }, + ["Ộ"]={ "Ọ","̂" }, + ["ộ"]={ "ọ","̂" }, + ["Ớ"]={ "Ơ","́" }, + ["ớ"]={ "ơ","́" }, + ["Ờ"]={ "Ơ","̀" }, + ["ờ"]={ "ơ","̀" }, + ["Ở"]={ "Ơ","̉" }, + ["ở"]={ "ơ","̉" }, + ["Ỡ"]={ "Ơ","̃" }, + ["ỡ"]={ "ơ","̃" }, + ["Ợ"]={ "Ơ","̣" }, + ["ợ"]={ "ơ","̣" }, + ["Ụ"]={ "U","̣" }, + ["ụ"]={ "u","̣" }, + ["Ủ"]={ "U","̉" }, + ["ủ"]={ "u","̉" }, + ["Ứ"]={ "Ư","́" }, + ["ứ"]={ "ư","́" }, + ["Ừ"]={ "Ư","̀" }, + ["ừ"]={ "ư","̀" }, + ["Ử"]={ "Ư","̉" }, + ["ử"]={ "ư","̉" }, + ["Ữ"]={ "Ư","̃" }, + ["ữ"]={ "ư","̃" }, + ["Ự"]={ "Ư","̣" }, + ["ự"]={ "ư","̣" }, + ["Ỳ"]={ "Y","̀" }, + ["ỳ"]={ "y","̀" }, + ["Ỵ"]={ "Y","̣" }, + ["ỵ"]={ "y","̣" }, + ["Ỷ"]={ "Y","̉" }, + ["ỷ"]={ "y","̉" }, + ["Ỹ"]={ "Y","̃" }, + ["ỹ"]={ "y","̃" }, + ["ἀ"]={ "α","̓" }, + ["ἁ"]={ "α","̔" }, + ["ἂ"]={ "ἀ","̀" }, + ["ἃ"]={ "ἁ","̀" }, + ["ἄ"]={ "ἀ","́" }, + ["ἅ"]={ "ἁ","́" }, + ["ἆ"]={ "ἀ","͂" }, + ["ἇ"]={ "ἁ","͂" }, + ["Ἀ"]={ "Α","̓" }, + ["Ἁ"]={ "Α","̔" }, + ["Ἂ"]={ "Ἀ","̀" }, + ["Ἃ"]={ "Ἁ","̀" }, + ["Ἄ"]={ "Ἀ","́" }, + ["Ἅ"]={ "Ἁ","́" }, + ["Ἆ"]={ "Ἀ","͂" }, + ["Ἇ"]={ "Ἁ","͂" }, + ["ἐ"]={ "ε","̓" }, + ["ἑ"]={ "ε","̔" }, + ["ἒ"]={ "ἐ","̀" }, + ["ἓ"]={ "ἑ","̀" }, + ["ἔ"]={ "ἐ","́" }, + ["ἕ"]={ "ἑ","́" }, + ["Ἐ"]={ "Ε","̓" }, + ["Ἑ"]={ "Ε","̔" }, + ["Ἒ"]={ "Ἐ","̀" }, + ["Ἓ"]={ "Ἑ","̀" }, + ["Ἔ"]={ "Ἐ","́" }, + ["Ἕ"]={ "Ἑ","́" }, + ["ἠ"]={ "η","̓" }, + ["ἡ"]={ "η","̔" }, + ["ἢ"]={ "ἠ","̀" }, + ["ἣ"]={ "ἡ","̀" }, + ["ἤ"]={ "ἠ","́" }, + ["ἥ"]={ "ἡ","́" }, + ["ἦ"]={ "ἠ","͂" }, + ["ἧ"]={ "ἡ","͂" }, + ["Ἠ"]={ "Η","̓" }, + ["Ἡ"]={ "Η","̔" }, + ["Ἢ"]={ "Ἠ","̀" }, + ["Ἣ"]={ "Ἡ","̀" }, + ["Ἤ"]={ "Ἠ","́" }, + ["Ἥ"]={ "Ἡ","́" }, + ["Ἦ"]={ "Ἠ","͂" }, + ["Ἧ"]={ "Ἡ","͂" }, + ["ἰ"]={ "ι","̓" }, + ["ἱ"]={ "ι","̔" }, + ["ἲ"]={ "ἰ","̀" }, + ["ἳ"]={ "ἱ","̀" }, + ["ἴ"]={ "ἰ","́" }, + ["ἵ"]={ "ἱ","́" }, + ["ἶ"]={ "ἰ","͂" }, + ["ἷ"]={ "ἱ","͂" }, + ["Ἰ"]={ "Ι","̓" }, + ["Ἱ"]={ "Ι","̔" }, + ["Ἲ"]={ "Ἰ","̀" }, + ["Ἳ"]={ "Ἱ","̀" }, + ["Ἴ"]={ "Ἰ","́" }, + ["Ἵ"]={ "Ἱ","́" }, + ["Ἶ"]={ "Ἰ","͂" }, + ["Ἷ"]={ "Ἱ","͂" }, + ["ὀ"]={ "ο","̓" }, + ["ὁ"]={ "ο","̔" }, + ["ὂ"]={ "ὀ","̀" }, + ["ὃ"]={ "ὁ","̀" }, + ["ὄ"]={ "ὀ","́" }, + ["ὅ"]={ "ὁ","́" }, + ["Ὀ"]={ "Ο","̓" }, + ["Ὁ"]={ "Ο","̔" }, + ["Ὂ"]={ "Ὀ","̀" }, + ["Ὃ"]={ "Ὁ","̀" }, + ["Ὄ"]={ "Ὀ","́" }, + ["Ὅ"]={ "Ὁ","́" }, + ["ὐ"]={ "υ","̓" }, + ["ὑ"]={ "υ","̔" }, + ["ὒ"]={ "ὐ","̀" }, + ["ὓ"]={ "ὑ","̀" }, + ["ὔ"]={ "ὐ","́" }, + ["ὕ"]={ "ὑ","́" }, + ["ὖ"]={ "ὐ","͂" }, + ["ὗ"]={ "ὑ","͂" }, + ["Ὑ"]={ "Υ","̔" }, + ["Ὓ"]={ "Ὑ","̀" }, + ["Ὕ"]={ "Ὑ","́" }, + ["Ὗ"]={ "Ὑ","͂" }, + ["ὠ"]={ "ω","̓" }, + ["ὡ"]={ "ω","̔" }, + ["ὢ"]={ "ὠ","̀" }, + ["ὣ"]={ "ὡ","̀" }, + ["ὤ"]={ "ὠ","́" }, + ["ὥ"]={ "ὡ","́" }, + ["ὦ"]={ "ὠ","͂" }, + ["ὧ"]={ "ὡ","͂" }, + ["Ὠ"]={ "Ω","̓" }, + ["Ὡ"]={ "Ω","̔" }, + ["Ὢ"]={ "Ὠ","̀" }, + ["Ὣ"]={ "Ὡ","̀" }, + ["Ὤ"]={ "Ὠ","́" }, + ["Ὥ"]={ "Ὡ","́" }, + ["Ὦ"]={ "Ὠ","͂" }, + ["Ὧ"]={ "Ὡ","͂" }, + ["ὰ"]={ "α","̀" }, + ["ὲ"]={ "ε","̀" }, + ["ὴ"]={ "η","̀" }, + ["ὶ"]={ "ι","̀" }, + ["ὸ"]={ "ο","̀" }, + ["ὺ"]={ "υ","̀" }, + ["ὼ"]={ "ω","̀" }, + ["ᾀ"]={ "ἀ","ͅ" }, + ["ᾁ"]={ "ἁ","ͅ" }, + ["ᾂ"]={ "ἂ","ͅ" }, + ["ᾃ"]={ "ἃ","ͅ" }, + ["ᾄ"]={ "ἄ","ͅ" }, + ["ᾅ"]={ "ἅ","ͅ" }, + ["ᾆ"]={ "ἆ","ͅ" }, + ["ᾇ"]={ "ἇ","ͅ" }, + ["ᾈ"]={ "Ἀ","ͅ" }, + ["ᾉ"]={ "Ἁ","ͅ" }, + ["ᾊ"]={ "Ἂ","ͅ" }, + ["ᾋ"]={ "Ἃ","ͅ" }, + ["ᾌ"]={ "Ἄ","ͅ" }, + ["ᾍ"]={ "Ἅ","ͅ" }, + ["ᾎ"]={ "Ἆ","ͅ" }, + ["ᾏ"]={ "Ἇ","ͅ" }, + ["ᾐ"]={ "ἠ","ͅ" }, + ["ᾑ"]={ "ἡ","ͅ" }, + ["ᾒ"]={ "ἢ","ͅ" }, + ["ᾓ"]={ "ἣ","ͅ" }, + ["ᾔ"]={ "ἤ","ͅ" }, + ["ᾕ"]={ "ἥ","ͅ" }, + ["ᾖ"]={ "ἦ","ͅ" }, + ["ᾗ"]={ "ἧ","ͅ" }, + ["ᾘ"]={ "Ἠ","ͅ" }, + ["ᾙ"]={ "Ἡ","ͅ" }, + ["ᾚ"]={ "Ἢ","ͅ" }, + ["ᾛ"]={ "Ἣ","ͅ" }, + ["ᾜ"]={ "Ἤ","ͅ" }, + ["ᾝ"]={ "Ἥ","ͅ" }, + ["ᾞ"]={ "Ἦ","ͅ" }, + ["ᾟ"]={ "Ἧ","ͅ" }, + ["ᾠ"]={ "ὠ","ͅ" }, + ["ᾡ"]={ "ὡ","ͅ" }, + ["ᾢ"]={ "ὢ","ͅ" }, + ["ᾣ"]={ "ὣ","ͅ" }, + ["ᾤ"]={ "ὤ","ͅ" }, + ["ᾥ"]={ "ὥ","ͅ" }, + ["ᾦ"]={ "ὦ","ͅ" }, + ["ᾧ"]={ "ὧ","ͅ" }, + ["ᾨ"]={ "Ὠ","ͅ" }, + ["ᾩ"]={ "Ὡ","ͅ" }, + ["ᾪ"]={ "Ὢ","ͅ" }, + ["ᾫ"]={ "Ὣ","ͅ" }, + ["ᾬ"]={ "Ὤ","ͅ" }, + ["ᾭ"]={ "Ὥ","ͅ" }, + ["ᾮ"]={ "Ὦ","ͅ" }, + ["ᾯ"]={ "Ὧ","ͅ" }, + ["ᾰ"]={ "α","̆" }, + ["ᾱ"]={ "α","̄" }, + ["ᾲ"]={ "ὰ","ͅ" }, + ["ᾳ"]={ "α","ͅ" }, + ["ᾴ"]={ "ά","ͅ" }, + ["ᾶ"]={ "α","͂" }, + ["ᾷ"]={ "ᾶ","ͅ" }, + ["Ᾰ"]={ "Α","̆" }, + ["Ᾱ"]={ "Α","̄" }, + ["Ὰ"]={ "Α","̀" }, + ["ᾼ"]={ "Α","ͅ" }, + ["῁"]={ "¨","͂" }, + ["ῂ"]={ "ὴ","ͅ" }, + ["ῃ"]={ "η","ͅ" }, + ["ῄ"]={ "ή","ͅ" }, + ["ῆ"]={ "η","͂" }, + ["ῇ"]={ "ῆ","ͅ" }, + ["Ὲ"]={ "Ε","̀" }, + ["Ὴ"]={ "Η","̀" }, + ["ῌ"]={ "Η","ͅ" }, + ["῍"]={ "᾿","̀" }, + ["῎"]={ "᾿","́" }, + ["῏"]={ "᾿","͂" }, + ["ῐ"]={ "ι","̆" }, + ["ῑ"]={ "ι","̄" }, + ["ῒ"]={ "ϊ","̀" }, + ["ῖ"]={ "ι","͂" }, + ["ῗ"]={ "ϊ","͂" }, + ["Ῐ"]={ "Ι","̆" }, + ["Ῑ"]={ "Ι","̄" }, + ["Ὶ"]={ "Ι","̀" }, + ["῝"]={ "῾","̀" }, + ["῞"]={ "῾","́" }, + ["῟"]={ "῾","͂" }, + ["ῠ"]={ "υ","̆" }, + ["ῡ"]={ "υ","̄" }, + ["ῢ"]={ "ϋ","̀" }, + ["ῤ"]={ "ρ","̓" }, + ["ῥ"]={ "ρ","̔" }, + ["ῦ"]={ "υ","͂" }, + ["ῧ"]={ "ϋ","͂" }, + ["Ῠ"]={ "Υ","̆" }, + ["Ῡ"]={ "Υ","̄" }, + ["Ὺ"]={ "Υ","̀" }, + ["Ῥ"]={ "Ρ","̔" }, + ["῭"]={ "¨","̀" }, + ["ῲ"]={ "ὼ","ͅ" }, + ["ῳ"]={ "ω","ͅ" }, + ["ῴ"]={ "ώ","ͅ" }, + ["ῶ"]={ "ω","͂" }, + ["ῷ"]={ "ῶ","ͅ" }, + ["Ὸ"]={ "Ο","̀" }, + ["Ὼ"]={ "Ω","̀" }, + ["ῼ"]={ "Ω","ͅ" }, + ["↚"]={ "←","̸" }, + ["↛"]={ "→","̸" }, + ["↮"]={ "↔","̸" }, + ["⇍"]={ "⇐","̸" }, + ["⇎"]={ "⇔","̸" }, + ["⇏"]={ "⇒","̸" }, + ["∄"]={ "∃","̸" }, + ["∉"]={ "∈","̸" }, + ["∌"]={ "∋","̸" }, + ["∤"]={ "∣","̸" }, + ["∦"]={ "∥","̸" }, + ["≁"]={ "∼","̸" }, + ["≄"]={ "≃","̸" }, + ["≇"]={ "≅","̸" }, + ["≉"]={ "≈","̸" }, + ["≠"]={ "=","̸" }, + ["≢"]={ "≡","̸" }, + ["≭"]={ "≍","̸" }, + ["≮"]={ "<","̸" }, + ["≯"]={ ">","̸" }, + ["≰"]={ "≤","̸" }, + ["≱"]={ "≥","̸" }, + ["≴"]={ "≲","̸" }, + ["≵"]={ "≳","̸" }, + ["≸"]={ "≶","̸" }, + ["≹"]={ "≷","̸" }, + ["⊀"]={ "≺","̸" }, + ["⊁"]={ "≻","̸" }, + ["⊄"]={ "⊂","̸" }, + ["⊅"]={ "⊃","̸" }, + ["⊈"]={ "⊆","̸" }, + ["⊉"]={ "⊇","̸" }, + ["⊬"]={ "⊢","̸" }, + ["⊭"]={ "⊨","̸" }, + ["⊮"]={ "⊩","̸" }, + ["⊯"]={ "⊫","̸" }, + ["⋠"]={ "≼","̸" }, + ["⋡"]={ "≽","̸" }, + ["⋢"]={ "⊑","̸" }, + ["⋣"]={ "⊒","̸" }, + ["⋪"]={ "⊲","̸" }, + ["⋫"]={ "⊳","̸" }, + ["⋬"]={ "⊴","̸" }, + ["⋭"]={ "⊵","̸" }, + ["⫝̸"]={ "⫝","̸" }, + ["が"]={ "か","゙" }, + ["ぎ"]={ "き","゙" }, + ["ぐ"]={ "く","゙" }, + ["げ"]={ "け","゙" }, + ["ご"]={ "こ","゙" }, + ["ざ"]={ "さ","゙" }, + ["じ"]={ "し","゙" }, + ["ず"]={ "す","゙" }, + ["ぜ"]={ "せ","゙" }, + ["ぞ"]={ "そ","゙" }, + ["だ"]={ "た","゙" }, + ["ぢ"]={ "ち","゙" }, + ["づ"]={ "つ","゙" }, + ["で"]={ "て","゙" }, + ["ど"]={ "と","゙" }, + ["ば"]={ "は","゙" }, + ["ぱ"]={ "は","゚" }, + ["び"]={ "ひ","゙" }, + ["ぴ"]={ "ひ","゚" }, + ["ぶ"]={ "ふ","゙" }, + ["ぷ"]={ "ふ","゚" }, + ["べ"]={ "へ","゙" }, + ["ぺ"]={ "へ","゚" }, + ["ぼ"]={ "ほ","゙" }, + ["ぽ"]={ "ほ","゚" }, + ["ゔ"]={ "う","゙" }, + ["ゞ"]={ "ゝ","゙" }, + ["ガ"]={ "カ","゙" }, + ["ギ"]={ "キ","゙" }, + ["グ"]={ "ク","゙" }, + ["ゲ"]={ "ケ","゙" }, + ["ゴ"]={ "コ","゙" }, + ["ザ"]={ "サ","゙" }, + ["ジ"]={ "シ","゙" }, + ["ズ"]={ "ス","゙" }, + ["ゼ"]={ "セ","゙" }, + ["ゾ"]={ "ソ","゙" }, + ["ダ"]={ "タ","゙" }, + ["ヂ"]={ "チ","゙" }, + ["ヅ"]={ "ツ","゙" }, + ["デ"]={ "テ","゙" }, + ["ド"]={ "ト","゙" }, + ["バ"]={ "ハ","゙" }, + ["パ"]={ "ハ","゚" }, + ["ビ"]={ "ヒ","゙" }, + ["ピ"]={ "ヒ","゚" }, + ["ブ"]={ "フ","゙" }, + ["プ"]={ "フ","゚" }, + ["ベ"]={ "ヘ","゙" }, + ["ペ"]={ "ヘ","゚" }, + ["ボ"]={ "ホ","゙" }, + ["ポ"]={ "ホ","゚" }, + ["ヴ"]={ "ウ","゙" }, + ["ヷ"]={ "ワ","゙" }, + ["ヸ"]={ "ヰ","゙" }, + ["ヹ"]={ "ヱ","゙" }, + ["ヺ"]={ "ヲ","゙" }, + ["ヾ"]={ "ヽ","゙" }, + ["יִ"]={ "י","ִ" }, + ["ײַ"]={ "ײ","ַ" }, + ["שׁ"]={ "ש","ׁ" }, + ["שׂ"]={ "ש","ׂ" }, + ["שּׁ"]={ "שּ","ׁ" }, + ["שּׂ"]={ "שּ","ׂ" }, + ["אַ"]={ "א","ַ" }, + ["אָ"]={ "א","ָ" }, + ["אּ"]={ "א","ּ" }, + ["בּ"]={ "ב","ּ" }, + ["גּ"]={ "ג","ּ" }, + ["דּ"]={ "ד","ּ" }, + ["הּ"]={ "ה","ּ" }, + ["וּ"]={ "ו","ּ" }, + ["זּ"]={ "ז","ּ" }, + ["טּ"]={ "ט","ּ" }, + ["יּ"]={ "י","ּ" }, + ["ךּ"]={ "ך","ּ" }, + ["כּ"]={ "כ","ּ" }, + ["לּ"]={ "ל","ּ" }, + ["מּ"]={ "מ","ּ" }, + ["נּ"]={ "נ","ּ" }, + ["סּ"]={ "ס","ּ" }, + ["ףּ"]={ "ף","ּ" }, + ["פּ"]={ "פ","ּ" }, + ["צּ"]={ "צ","ּ" }, + ["קּ"]={ "ק","ּ" }, + ["רּ"]={ "ר","ּ" }, + ["שּ"]={ "ש","ּ" }, + ["תּ"]={ "ת","ּ" }, + ["וֹ"]={ "ו","ֹ" }, + ["בֿ"]={ "ב","ֿ" }, + ["כֿ"]={ "כ","ֿ" }, + ["פֿ"]={ "פ","ֿ" }, + ["𑂚"]={ "𑂙","𑂺" }, + ["𑂜"]={ "𑂛","𑂺" }, + ["𑂫"]={ "𑂥","𑂺" }, + ["𑄮"]={ "𑄱","𑄧" }, + ["𑄯"]={ "𑄲","𑄧" }, + ["𑍋"]={ "𑍇","𑌾" }, + ["𑍌"]={ "𑍇","𑍗" }, + ["𑒻"]={ "𑒹","𑒺" }, + ["𑒼"]={ "𑒹","𑒰" }, + ["𑒾"]={ "𑒹","𑒽" }, + ["𑖺"]={ "𑖸","𑖯" }, + ["𑖻"]={ "𑖹","𑖯" }, + ["𝅗𝅥"]={ "𝅗","𝅥" }, + ["𝅘𝅥"]={ "𝅘","𝅥" }, + ["𝅘𝅥𝅮"]={ "𝅘𝅥","𝅮" }, + ["𝅘𝅥𝅯"]={ "𝅘𝅥","𝅯" }, + ["𝅘𝅥𝅰"]={ "𝅘𝅥","𝅰" }, + ["𝅘𝅥𝅱"]={ "𝅘𝅥","𝅱" }, + ["𝅘𝅥𝅲"]={ "𝅘𝅥","𝅲" }, + ["𝆹𝅥"]={ "𝆹","𝅥" }, + ["𝆺𝅥"]={ "𝆺","𝅥" }, + ["𝆹𝅥𝅮"]={ "𝆹𝅥","𝅮" }, + ["𝆺𝅥𝅮"]={ "𝆺𝅥","𝅮" }, + ["𝆹𝅥𝅯"]={ "𝆹𝅥","𝅯" }, + ["𝆺𝅥𝅯"]={ "𝆺𝅥","𝅯" }, + }, + }, + }, + ["name"]="collapse", + ["prepend"]=true, + ["type"]="ligature", +} +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", diff --git a/tex/generic/context/luatex/luatex-fonts.lua b/tex/generic/context/luatex/luatex-fonts.lua index c21389c71..20690992c 100644 --- a/tex/generic/context/luatex/luatex-fonts.lua +++ b/tex/generic/context/luatex/luatex-fonts.lua @@ -277,6 +277,7 @@ if non_generic_context.luatex_fonts.skip_loading ~= true then loadmodule('font-def.lua') loadmodule('font-xtx.lua') -- xetex compatible specifiers (plain/latex only) loadmodule('luatex-fonts-ext.lua') -- some extensions + -- loadmodule('luatex-fonts-lig.lua') -- and another one -- We need to plug into a callback and the following module implements the handlers. Actual -- plugging in happens later. |