summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/luatex/luaotfload
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/tex/luatex/luaotfload')
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/fontloader-2015-12-22.lua (renamed from Master/texmf-dist/tex/luatex/luaotfload/fontloader-2015-12-12.lua)643
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/fontloader-basics-nod.lua45
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/fontloader-char-ini.lua1318
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-cff.lua1697
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-con.lua2
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-inj.lua (renamed from Master/texmf-dist/tex/luatex/luaotfload/fontloader-fonts-inj.lua)60
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-map.lua66
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-otf.lua10
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-oti.lua69
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-otn.lua (renamed from Master/texmf-dist/tex/luatex/luaotfload/fontloader-fonts-otn.lua)419
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/fontloader-fonts-def.lua2
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/fontloader-fonts-ota.lua30
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/fontloader-fonts.lua6
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/fontloader-languages.lua15
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/fontloader-languages.tex2
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/fontloader-reference.lua543
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/luaotfload-auxiliary.lua64
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/luaotfload-features.lua380
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/luaotfload-init.lua47
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/luaotfload-letterspace.lua86
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/luaotfload-status.lua46
21 files changed, 4826 insertions, 724 deletions
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-2015-12-12.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-2015-12-22.lua
index 0eaf442ef32..6e8879eab12 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-2015-12-12.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-2015-12-22.lua
@@ -1,6 +1,6 @@
--[[info-----------------------------------------------------------------------
Luaotfload fontloader package
- build 2015-12-12 20:06:58 by phg@phlegethon
+ build 2015-12-22 23:59:34 by phg@phlegethon
-------------------------------------------------------------------------------
© 2015 PRAGMA ADE / ConTeXt Development Team
@@ -34,9 +34,9 @@
· fontloader-font-oti.lua
· fontloader-font-otf.lua
· fontloader-font-otb.lua
- · fontloader-fonts-inj.lua
+ · fontloader-font-inj.lua
· fontloader-fonts-ota.lua
- · fontloader-fonts-otn.lua
+ · fontloader-font-otn.lua
· fontloader-font-otp.lua
· fontloader-fonts-lua.lua
· fontloader-font-def.lua
@@ -47,7 +47,7 @@
--info]]-----------------------------------------------------------------------
-do --- [luaotfload, fontloader-2015-12-12.lua scope for “data-con” 675f5a0af45ffb3e0d2e2ab5d6c2e47b] ---
+do --- [luaotfload, fontloader-2015-12-22.lua scope for “data-con” 675f5a0af45ffb3e0d2e2ab5d6c2e47b] ---
if not modules then modules={} end modules ['data-con']={
version=1.100,
@@ -159,10 +159,10 @@ function containers.cleanname(name)
return (gsub(lower(name),"[^%w\128-\255]+","-"))
end
-end --- [luaotfload, fontloader-2015-12-12.lua scope for “data-con”] ---
+end --- [luaotfload, fontloader-2015-12-22.lua scope for “data-con”] ---
-do --- [luaotfload, fontloader-2015-12-12.lua scope for “basics-nod” d060e22b2afed6e7624f879b0e1a7d71] ---
+do --- [luaotfload, fontloader-2015-12-22.lua scope for “basics-nod” af682899d202229c0c1b859a07384b8c] ---
if not modules then modules={} end modules ['luatex-fonts-nod']={
version=1.001,
@@ -200,15 +200,21 @@ end
nodes={}
nodes.pool={}
nodes.handlers={}
-local nodecodes={} for k,v in next,node.types () do nodecodes[string.gsub(v,"_","")]=k end
-local whatcodes={} for k,v in next,node.whatsits() do whatcodes[string.gsub(v,"_","")]=k end
-local glyphcodes={ [0]="character","glyph","ligature","ghost","left","right" }
-local disccodes={ [0]="discretionary","explicit","automatic","regular","first","second" }
-for i=0,#glyphcodes do glyphcodes[glyphcodes[i]]=i end
-for i=0,#disccodes do disccodes [disccodes [i]]=i end
+local nodecodes={}
+local glyphcodes=node.subtypes("glyph")
+local disccodes=node.subtypes("disc")
+for k,v in next,node.types() do
+ v=string.gsub(v,"_","")
+ nodecodes[k]=v
+ nodecodes[v]=k
+end
+for i=0,#glyphcodes do
+ glyphcodes[glyphcodes[i]]=i
+end
+for i=0,#disccodes do
+ disccodes[disccodes[i]]=i
+end
nodes.nodecodes=nodecodes
-nodes.whatcodes=whatcodes
-nodes.whatsitcodes=whatcodes
nodes.glyphcodes=glyphcodes
nodes.disccodes=disccodes
local free_node=node.free
@@ -272,7 +278,6 @@ nodes.traverse_id=node.traverse_id
nodes.slide=node.slide
nodes.vpack=node.vpack
nodes.first_glyph=node.first_glyph
-nodes.first_character=node.first_character
nodes.has_glyph=node.has_glyph or node.first_glyph
nodes.current_attr=node.current_attr
nodes.do_ligature_n=node.do_ligature_n
@@ -301,13 +306,27 @@ local setfield=direct.setfield
nuts.getfield=getfield
nuts.setfield=setfield
nuts.getnext=direct.getnext
+nuts.setnext=direct.setnext
nuts.getprev=direct.getprev
+nuts.setprev=direct.setprev
+nuts.getboth=direct.getboth
+nuts.setboth=direct.setboth
nuts.getid=direct.getid
-nuts.getattr=getfield
+nuts.getattr=direct.get_attribute or direct.has_attribute or getfield
nuts.setattr=setfield
nuts.getfont=direct.getfont
+nuts.setfont=direct.setfont
nuts.getsubtype=direct.getsubtype
+nuts.setsubtype=direct.setsubtype or function(n,s) setfield(n,"subtype",s) end
nuts.getchar=direct.getchar
+nuts.setchar=direct.setchar
+nuts.getdisc=direct.getdisc
+nuts.setdisc=direct.setdisc
+nuts.setlink=direct.setlink
+nuts.getlist=direct.getlist
+nuts.setlist=direct.setlist or function(n,l) setfield(n,"list",l) end
+nuts.getleader=direct.getleader
+nuts.setleader=direct.setleader or function(n,l) setfield(n,"leader",l) end
nuts.insert_before=direct.insert_before
nuts.insert_after=direct.insert_after
nuts.delete=direct.delete
@@ -321,6 +340,9 @@ nuts.is_node=direct.is_node
nuts.end_of_math=direct.end_of_math
nuts.traverse=direct.traverse
nuts.traverse_id=direct.traverse_id
+nuts.traverse_char=direct.traverse_char
+nuts.ligaturing=direct.ligaturing
+nuts.kerning=direct.kerning
nuts.getprop=nuts.getattr
nuts.setprop=nuts.setattr
local new_nut=direct.new
@@ -354,10 +376,10 @@ end
nodes.setprop=nodes.setproperty
nodes.getprop=nodes.getproperty
-end --- [luaotfload, fontloader-2015-12-12.lua scope for “basics-nod”] ---
+end --- [luaotfload, fontloader-2015-12-22.lua scope for “basics-nod”] ---
-do --- [luaotfload, fontloader-2015-12-12.lua scope for “font-ini” 179f0a75cda26696c1b1cd6d7fe0d8ae] ---
+do --- [luaotfload, fontloader-2015-12-22.lua scope for “font-ini” 179f0a75cda26696c1b1cd6d7fe0d8ae] ---
if not modules then modules={} end modules ['font-ini']={
version=1.001,
@@ -381,10 +403,10 @@ fonts.definers={ methods={} }
fonts.loggers={ register=function() end }
fontloader.totable=fontloader.to_table
-end --- [luaotfload, fontloader-2015-12-12.lua scope for “font-ini”] ---
+end --- [luaotfload, fontloader-2015-12-22.lua scope for “font-ini”] ---
-do --- [luaotfload, fontloader-2015-12-12.lua scope for “font-con” 5ae91fc3b5bb8d22b2fba27258d49971] ---
+do --- [luaotfload, fontloader-2015-12-22.lua scope for “font-con” 99aacd19adce25fa35a9a30d43e8ac79] ---
if not modules then modules={} end modules ['font-con']={
version=1.001,
@@ -1536,10 +1558,10 @@ function constructors.addcoreunicodes(unicodes)
return unicodes
end
-end --- [luaotfload, fontloader-2015-12-12.lua scope for “font-con”] ---
+end --- [luaotfload, fontloader-2015-12-22.lua scope for “font-con”] ---
-do --- [luaotfload, fontloader-2015-12-12.lua scope for “fonts-enc” b224fe179312d924ffaf8334cf5ef15b] ---
+do --- [luaotfload, fontloader-2015-12-22.lua scope for “fonts-enc” b224fe179312d924ffaf8334cf5ef15b] ---
if not modules then modules={} end modules ['luatex-font-enc']={
version=1.001,
@@ -1567,10 +1589,10 @@ setmetatable(fonts.encodings.agl,{ __index=function(t,k)
end
end })
-end --- [luaotfload, fontloader-2015-12-12.lua scope for “fonts-enc”] ---
+end --- [luaotfload, fontloader-2015-12-22.lua scope for “fonts-enc”] ---
-do --- [luaotfload, fontloader-2015-12-12.lua scope for “font-cid” 52421d1fdaa07ec4b1d936c6ff5079be] ---
+do --- [luaotfload, fontloader-2015-12-22.lua scope for “font-cid” 52421d1fdaa07ec4b1d936c6ff5079be] ---
if not modules then modules={} end modules ['font-cid']={
version=1.001,
@@ -1721,10 +1743,10 @@ function cid.getmap(specification)
return found
end
-end --- [luaotfload, fontloader-2015-12-12.lua scope for “font-cid”] ---
+end --- [luaotfload, fontloader-2015-12-22.lua scope for “font-cid”] ---
-do --- [luaotfload, fontloader-2015-12-12.lua scope for “font-map” 60c9f3d4d80944ce9123c9cddc1e57e5] ---
+do --- [luaotfload, fontloader-2015-12-22.lua scope for “font-map” a20a454f933095d78faf1d5f8200d025] ---
if not modules then modules={} end modules ['font-map']={
version=1.001,
@@ -2038,10 +2060,10 @@ function mappings.addtounicode(data,filename,checklookups)
end
end
-end --- [luaotfload, fontloader-2015-12-12.lua scope for “font-map”] ---
+end --- [luaotfload, fontloader-2015-12-22.lua scope for “font-map”] ---
-do --- [luaotfload, fontloader-2015-12-12.lua scope for “fonts-syn” 9729d0e49b770f78e88dab86739e0297] ---
+do --- [luaotfload, fontloader-2015-12-22.lua scope for “fonts-syn” 9729d0e49b770f78e88dab86739e0297] ---
if not modules then modules={} end modules ['luatex-fonts-syn']={
version=1.001,
@@ -2117,10 +2139,10 @@ function fonts.names.ignoredfile(filename)
return false
end
-end --- [luaotfload, fontloader-2015-12-12.lua scope for “fonts-syn”] ---
+end --- [luaotfload, fontloader-2015-12-22.lua scope for “fonts-syn”] ---
-do --- [luaotfload, fontloader-2015-12-12.lua scope for “font-tfm” bbee5eddb11211fb0a8d993db678bf3c] ---
+do --- [luaotfload, fontloader-2015-12-22.lua scope for “font-tfm” bbee5eddb11211fb0a8d993db678bf3c] ---
if not modules then modules={} end modules ['font-tfm']={
version=1.001,
@@ -2275,10 +2297,10 @@ function readers.tfm(specification)
return check_tfm(specification,fullname)
end
-end --- [luaotfload, fontloader-2015-12-12.lua scope for “font-tfm”] ---
+end --- [luaotfload, fontloader-2015-12-22.lua scope for “font-tfm”] ---
-do --- [luaotfload, fontloader-2015-12-12.lua scope for “font-afm” ece4863414d6b38c2e577110c9b55bd3] ---
+do --- [luaotfload, fontloader-2015-12-22.lua scope for “font-afm” ece4863414d6b38c2e577110c9b55bd3] ---
if not modules then modules={} end modules ['font-afm']={
version=1.001,
@@ -3130,10 +3152,10 @@ function readers.pfb(specification,method)
return readers.afm(specification,method)
end
-end --- [luaotfload, fontloader-2015-12-12.lua scope for “font-afm”] ---
+end --- [luaotfload, fontloader-2015-12-22.lua scope for “font-afm”] ---
-do --- [luaotfload, fontloader-2015-12-12.lua scope for “font-afk” b36a76ceb835f41f8c05b471000ddc14] ---
+do --- [luaotfload, fontloader-2015-12-22.lua scope for “font-afk” b36a76ceb835f41f8c05b471000ddc14] ---
if not modules then modules={} end modules ['font-afk']={
version=1.001,
@@ -3300,10 +3322,10 @@ fonts.handlers.afm.helpdata={
}
}
-end --- [luaotfload, fontloader-2015-12-12.lua scope for “font-afk”] ---
+end --- [luaotfload, fontloader-2015-12-22.lua scope for “font-afk”] ---
-do --- [luaotfload, fontloader-2015-12-12.lua scope for “fonts-tfm” 8fd3865240e4e87e99e0739abeda2322] ---
+do --- [luaotfload, fontloader-2015-12-22.lua scope for “fonts-tfm” 8fd3865240e4e87e99e0739abeda2322] ---
if not modules then modules={} end modules ['luatex-fonts-tfm']={
version=1.001,
@@ -3341,10 +3363,10 @@ function fonts.readers.tfm(specification)
end
end
-end --- [luaotfload, fontloader-2015-12-12.lua scope for “fonts-tfm”] ---
+end --- [luaotfload, fontloader-2015-12-22.lua scope for “fonts-tfm”] ---
-do --- [luaotfload, fontloader-2015-12-12.lua scope for “font-oti” 035a51b49029d7da48453ec5f1d65018] ---
+do --- [luaotfload, fontloader-2015-12-22.lua scope for “font-oti” b6d493035cec2d748f2f9ec510c860ef] ---
if not modules then modules={} end modules ['font-oti']={
version=1.001,
@@ -3358,8 +3380,9 @@ local fonts=fonts
local constructors=fonts.constructors
local otf=constructors.newhandler("otf")
local otffeatures=constructors.newfeatures("otf")
-local otftables=otf.tables
local registerotffeature=otffeatures.register
+local otftables=otf.tables or {}
+otf.tables=otftables
local allocate=utilities.storage.allocate
registerotffeature {
name="features",
@@ -3423,11 +3446,69 @@ registerotffeature {
node=setscript,
}
}
+otftables.featuretypes=allocate {
+ gpos_single="position",
+ gpos_pair="position",
+ gpos_cursive="position",
+ gpos_mark2base="position",
+ gpos_mark2ligature="position",
+ gpos_mark2mark="position",
+ gpos_context="position",
+ gpos_contextchain="position",
+ gsub_single="substitution",
+ gsub_multiple="substitution",
+ gsub_alternate="substitution",
+ gsub_ligature="substitution",
+ gsub_context="substitution",
+ gsub_contextchain="substitution",
+ gsub_reversecontextchain="substitution",
+ gsub_reversesub="substitution",
+}
+function otffeatures.checkeddefaultscript(featuretype,autoscript,scripts)
+ if featuretype=="position" then
+ local default=scripts.dflt
+ if default then
+ if autoscript=="position" or autoscript==true then
+ return default
+ else
+ report_otf("script feature %s not applied, enable default positioning")
+ end
+ else
+ end
+ elseif featuretype=="substitution" then
+ local default=scripts.dflt
+ if default then
+ if autoscript=="substitution" or autoscript==true then
+ return default
+ end
+ end
+ end
+end
+function otffeatures.checkeddefaultlanguage(featuretype,autolanguage,languages)
+ if featuretype=="position" then
+ local default=languages.dflt
+ if default then
+ if autolanguage=="position" or autolanguage==true then
+ return default
+ else
+ report_otf("language feature %s not applied, enable default positioning")
+ end
+ else
+ end
+ elseif featuretype=="substitution" then
+ local default=languages.dflt
+ if default then
+ if autolanguage=="substitution" or autolanguage==true then
+ return default
+ end
+ end
+ end
+end
-end --- [luaotfload, fontloader-2015-12-12.lua scope for “font-oti”] ---
+end --- [luaotfload, fontloader-2015-12-22.lua scope for “font-oti”] ---
-do --- [luaotfload, fontloader-2015-12-12.lua scope for “font-otf” b1a5f4340125198b1b0489ef903dd267] ---
+do --- [luaotfload, fontloader-2015-12-22.lua scope for “font-otf” b14a46a7fec8b5cb4c909f4c4c299453] ---
if not modules then modules={} end modules ['font-otf']={
version=1.001,
@@ -3467,7 +3548,7 @@ local report_otf=logs.reporter("fonts","otf loading")
local fonts=fonts
local otf=fonts.handlers.otf
otf.glists={ "gsub","gpos" }
-otf.version=2.819
+otf.version=2.820
otf.cache=containers.define("fonts","otf",otf.version,true)
local hashes=fonts.hashes
local definers=fonts.definers
@@ -3648,6 +3729,7 @@ local ordered_enhancers={
"check encoding",
"add duplicates",
"expand lookups",
+ "check extra features",
"cleanup tables",
"compact lookups",
"purge names",
@@ -3918,7 +4000,6 @@ function otf.load(filename,sub,featurefile)
applyruntimefixes(filename,data)
end
enhance("add dimensions",data,filename,nil,false)
-enhance("check extra features",data,filename)
if trace_sequences then
showfeatureorder(data,filename)
end
@@ -5803,7 +5884,7 @@ otf.coverup={
kern=justset,
},
register=function(coverage,lookuptype,format,feature,n,descriptions,resources)
- local name=formatters["ctx_%s_%s"](feature,n)
+ local name=formatters["ctx_%s_%s_%s"](feature,lookuptype,n)
if lookuptype=="kern" then
resources.lookuptypes[name]="position"
else
@@ -5884,10 +5965,10 @@ function otf.getkern(tfmdata,left,right,kind)
return 0
end
-end --- [luaotfload, fontloader-2015-12-12.lua scope for “font-otf”] ---
+end --- [luaotfload, fontloader-2015-12-22.lua scope for “font-otf”] ---
-do --- [luaotfload, fontloader-2015-12-12.lua scope for “font-otb” 93461f2f412a9b33b35a273c09b64291] ---
+do --- [luaotfload, fontloader-2015-12-22.lua scope for “font-otb” 93461f2f412a9b33b35a273c09b64291] ---
if not modules then modules={} end modules ['font-otb']={
version=1.001,
@@ -6472,10 +6553,10 @@ directives.register("fonts.otf.loader.basemethod",function(v)
end
end)
-end --- [luaotfload, fontloader-2015-12-12.lua scope for “font-otb”] ---
+end --- [luaotfload, fontloader-2015-12-22.lua scope for “font-otb”] ---
-do --- [luaotfload, fontloader-2015-12-12.lua scope for “fonts-inj” 2e61e59f1931a84336c6aea812e219c2] ---
+do --- [luaotfload, fontloader-2015-12-22.lua scope for “font-inj” 593642f0a6fe4a7fef5ed63034276e6f] ---
if not modules then modules={} end modules ['font-inj']={
version=1.001,
@@ -6537,8 +6618,10 @@ function injections.resetcounts()
end
function injections.reset(n)
local p=rawget(properties,n)
- if p and rawget(p,"injections") then
- p.injections=nil
+ if p then
+ p.injections=false
+ else
+ properties[n]=false
end
end
function injections.copy(target,source)
@@ -6555,10 +6638,17 @@ function injections.copy(target,source)
injections=si,
}
end
+ elseif tp then
+ tp.injections=false
else
- if tp then
- tp.injections=nil
- end
+ properties[target]={ injections={} }
+ end
+ else
+ local tp=rawget(properties,target)
+ if tp then
+ tp.injections=false
+ else
+ properties[target]=false
end
end
end
@@ -6793,10 +6883,11 @@ local function show(n,what,nested,symbol)
local markx=i.markx or 0
local marky=i.marky or 0
local markdir=i.markdir or 0
- local markbase=i.markbase or 0
+ local markbase=i.markbase or 0
local cursivex=i.cursivex or 0
local cursivey=i.cursivey or 0
local ligaindex=i.ligaindex or 0
+ local cursbase=i.cursiveanchor
local margin=nested and 4 or 2
if rightkern~=0 or yoffset~=0 then
report_injections("%w%s pair: lx %p, rx %p, dy %p",margin,symbol,leftkern,rightkern,yoffset)
@@ -6807,7 +6898,13 @@ local function show(n,what,nested,symbol)
report_injections("%w%s mark: dx %p, dy %p, dir %s, base %s",margin,symbol,markx,marky,markdir,markbase~=0 and "yes" or "no")
end
if cursivex~=0 or cursivey~=0 then
- report_injections("%w%s curs: dx %p, dy %p",margin,symbol,cursivex,cursivey)
+ if cursbase then
+ report_injections("%w%s curs: base dx %p, dy %p",margin,symbol,cursivex,cursivey)
+ else
+ report_injections("%w%s curs: dx %p, dy %p",margin,symbol,cursivex,cursivey)
+ end
+ elseif cursbase then
+ report_injections("%w%s curs: base",margin,symbol)
end
if ligaindex~=0 then
report_injections("%w%s liga: index %i",margin,symbol,ligaindex)
@@ -7486,12 +7583,12 @@ function injections.handler(head,where)
end
end
-end --- [luaotfload, fontloader-2015-12-12.lua scope for “fonts-inj”] ---
+end --- [luaotfload, fontloader-2015-12-22.lua scope for “font-inj”] ---
-do --- [luaotfload, fontloader-2015-12-12.lua scope for “fonts-ota” e18236703ac20ece7ff45f9209a9b9d6] ---
+do --- [luaotfload, fontloader-2015-12-22.lua scope for “fonts-ota” 67a1fc4c6508526fa54041d22bcb6eab] ---
-if not modules then modules={} end modules ['font-otx']={
+if not modules then modules={} end modules ['luatex-fonts-ota']={
version=1.001,
comment="companion to font-otf.lua (analysing)",
author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
@@ -7508,7 +7605,6 @@ local initializers=allocate()
local methods=allocate()
analyzers.initializers=initializers
analyzers.methods=methods
-analyzers.useunicodemarks=false
local a_state=attributes.private('state')
local nuts=nodes.nuts
local tonut=nuts.tonut
@@ -7564,6 +7660,7 @@ local features={
}
analyzers.states=states
analyzers.features=features
+analyzers.useunicodemarks=false
function analyzers.setstate(head,font)
local useunicodemarks=analyzers.useunicodemarks
local tfmdata=fontdata[font]
@@ -7577,7 +7674,10 @@ function analyzers.setstate(head,font)
local char=getchar(current)
local d=descriptions[char]
if d then
- if d.class=="mark" or (useunicodemarks and categories[char]=="mn") then
+ if d.class=="mark" then
+ done=true
+ setprop(current,a_state,s_mark)
+ elseif useunicodemarks and categories[char]=="mn" then
done=true
setprop(current,a_state,s_mark)
elseif n==0 then
@@ -7864,10 +7964,10 @@ directives.register("otf.analyze.useunicodemarks",function(v)
analyzers.useunicodemarks=v
end)
-end --- [luaotfload, fontloader-2015-12-12.lua scope for “fonts-ota”] ---
+end --- [luaotfload, fontloader-2015-12-22.lua scope for “fonts-ota”] ---
-do --- [luaotfload, fontloader-2015-12-12.lua scope for “fonts-otn” f01870a8622259f58ffbdc5718a53377] ---
+do --- [luaotfload, fontloader-2015-12-22.lua scope for “font-otn” e8a1f33bbba52eda6aec4e6d6a9662dc] ---
if not modules then modules={} end modules ['font-otn']={
version=1.001,
@@ -7927,7 +8027,9 @@ local tonut=nuts.tonut
local getfield=nuts.getfield
local setfield=nuts.setfield
local getnext=nuts.getnext
+local setnext=nuts.setnext
local getprev=nuts.getprev
+local setprev=nuts.setprev
local getid=nuts.getid
local getattr=nuts.getattr
local setattr=nuts.setattr
@@ -7935,7 +8037,9 @@ local getprop=nuts.getprop
local setprop=nuts.setprop
local getfont=nuts.getfont
local getsubtype=nuts.getsubtype
+local setsubtype=nuts.setsubtype
local getchar=nuts.getchar
+local setchar=nuts.setchar
local insert_node_before=nuts.insert_before
local insert_node_after=nuts.insert_after
local delete_node=nuts.delete
@@ -7954,15 +8058,14 @@ local zwj=0x200D
local wildcard="*"
local default="dflt"
local nodecodes=nodes.nodecodes
-local whatcodes=nodes.whatcodes
local glyphcodes=nodes.glyphcodes
local disccodes=nodes.disccodes
local glyph_code=nodecodes.glyph
local glue_code=nodecodes.glue
local disc_code=nodecodes.disc
local math_code=nodecodes.math
-local dir_code=whatcodes.dir
-local localpar_code=whatcodes.localpar
+local dir_code=nodecodes.dir
+local localpar_code=nodecodes.localpar
local discretionary_code=disccodes.discretionary
local ligature_code=glyphcodes.ligature
local privateattribute=attributes.private
@@ -8082,8 +8185,8 @@ local function flattendisk(head,disc)
if replace then
if next then
local tail=find_node_tail(replace)
- setfield(tail,"next",next)
- setfield(next,"prev",tail)
+ setnext(tail,next)
+ setprev(next,tail)
end
return replace,replace
elseif next then
@@ -8097,17 +8200,17 @@ local function flattendisk(head,disc)
if replace then
local tail=find_node_tail(replace)
if next then
- setfield(tail,"next",next)
- setfield(next,"prev",tail)
+ setnext(tail,next)
+ setprev(next,tail)
end
- setfield(prev,"next",replace)
- setfield(replace,"prev",prev)
+ setnext(prev,replace)
+ setprev(replace,prev)
return head,replace
else
if next then
- setfield(next,"prev",prev)
+ setprev(next,prev)
end
- setfield(prev,"next",next)
+ setnext(prev,next)
return head,next
end
end
@@ -8120,14 +8223,14 @@ local function appenddisc(disc,list)
local ptail=find_node_tail(post)
local rtail=find_node_tail(replace)
if post then
- setfield(ptail,"next",phead)
- setfield(phead,"prev",ptail)
+ setnext(ptail,phead)
+ setprev(phead,ptail)
else
setfield(disc,"post",phead)
end
if replace then
- setfield(rtail,"next",rhead)
- setfield(rhead,"prev",rtail)
+ setnext(rtail,rhead)
+ setprev(rhead,rtail)
else
setfield(disc,"replace",rhead)
end
@@ -8138,24 +8241,24 @@ local function markstoligature(kind,lookupname,head,start,stop,char)
else
local prev=getprev(start)
local next=getnext(stop)
- setfield(start,"prev",nil)
- setfield(stop,"next",nil)
+ setprev(start,nil)
+ setnext(stop,nil)
local base=copy_glyph(start)
if head==start then
head=base
end
resetinjection(base)
- setfield(base,"char",char)
- setfield(base,"subtype",ligature_code)
+ setchar(base,char)
+ setsubtype(base,ligature_code)
setfield(base,"components",start)
if prev then
- setfield(prev,"next",base)
+ setnext(prev,base)
end
if next then
- setfield(next,"prev",base)
+ setprev(next,base)
end
- setfield(base,"next",next)
- setfield(base,"prev",prev)
+ setnext(base,next)
+ setprev(base,prev)
return head,base
end
end
@@ -8183,7 +8286,7 @@ local function toligature(kind,lookupname,head,start,stop,char,markflag,discfoun
end
if start==stop and getchar(start)==char then
resetinjection(start)
- setfield(start,"char",char)
+ setchar(start,char)
return head,start
end
local components=getfield(start,"components")
@@ -8192,24 +8295,24 @@ local function toligature(kind,lookupname,head,start,stop,char,markflag,discfoun
local prev=getprev(start)
local next=getnext(stop)
local comp=start
- setfield(start,"prev",nil)
- setfield(stop,"next",nil)
+ setprev(start,nil)
+ setnext(stop,nil)
local base=copy_glyph(start)
if start==head then
head=base
end
resetinjection(base)
- setfield(base,"char",char)
- setfield(base,"subtype",ligature_code)
+ setchar(base,char)
+ setsubtype(base,ligature_code)
setfield(base,"components",comp)
if prev then
- setfield(prev,"next",base)
+ setnext(prev,base)
end
if next then
- setfield(next,"prev",base)
+ setprev(next,base)
end
- setfield(base,"prev",prev)
- setfield(base,"next",next)
+ setprev(base,prev)
+ setnext(base,next)
if not discfound then
local deletemarks=markflag~="mark"
local components=start
@@ -8249,41 +8352,41 @@ local function toligature(kind,lookupname,head,start,stop,char,markflag,discfoun
start=getnext(start)
end
else
- local discprev=getfield(discfound,"prev")
- local discnext=getfield(discfound,"next")
+ local discprev=getprev(discfound)
+ local discnext=getnext(discfound)
if discprev and discnext then
local pre=getfield(discfound,"pre")
local post=getfield(discfound,"post")
local replace=getfield(discfound,"replace")
if not replace then
- local prev=getfield(base,"prev")
+ local prev=getprev(base)
local copied=copy_node_list(comp)
- setfield(discnext,"prev",nil)
- setfield(discprev,"next",nil)
+ setprev(discnext,nil)
+ setnext(discprev,nil)
if pre then
- setfield(discprev,"next",pre)
- setfield(pre,"prev",discprev)
+ setnext(discprev,pre)
+ setprev(pre,discprev)
end
pre=comp
if post then
local tail=find_node_tail(post)
- setfield(tail,"next",discnext)
- setfield(discnext,"prev",tail)
- setfield(post,"prev",nil)
+ setnext(tail,discnext)
+ setprev(discnext,tail)
+ setprev(post,nil)
else
post=discnext
end
- setfield(prev,"next",discfound)
- setfield(discfound,"prev",prev)
- setfield(discfound,"next",next)
- setfield(next,"prev",discfound)
- setfield(base,"next",nil)
- setfield(base,"prev",nil)
+ setnext(prev,discfound)
+ setprev(discfound,prev)
+ setnext(discfound,next)
+ setprev(next,discfound)
+ setnext(base,nil)
+ setprev(base,nil)
setfield(base,"components",copied)
setfield(discfound,"pre",pre)
setfield(discfound,"post",post)
setfield(discfound,"replace",base)
- setfield(discfound,"subtype",discretionary_code)
+ setsubtype(discfound,discretionary_code)
base=prev
end
end
@@ -8294,19 +8397,19 @@ local function multiple_glyphs(head,start,multiple,ignoremarks)
local nofmultiples=#multiple
if nofmultiples>0 then
resetinjection(start)
- setfield(start,"char",multiple[1])
+ setchar(start,multiple[1])
if nofmultiples>1 then
local sn=getnext(start)
for k=2,nofmultiples do
local n=copy_node(start)
resetinjection(n)
- setfield(n,"char",multiple[k])
- setfield(n,"prev",start)
- setfield(n,"next",sn)
+ setchar(n,multiple[k])
+ setprev(n,start)
+ setnext(n,sn)
if sn then
- setfield(sn,"prev",n)
+ setprev(sn,n)
end
- setfield(start,"next",n)
+ setnext(start,n)
start=n
end
end
@@ -8354,7 +8457,7 @@ function handlers.gsub_single(head,start,kind,lookupname,replacement)
logprocess("%s: replacing %s by single %s",pref(kind,lookupname),gref(getchar(start)),gref(replacement))
end
resetinjection(start)
- setfield(start,"char",replacement)
+ setchar(start,replacement)
return head,start,true
end
function handlers.gsub_alternate(head,start,kind,lookupname,alternative,sequence)
@@ -8365,7 +8468,7 @@ function handlers.gsub_alternate(head,start,kind,lookupname,alternative,sequence
logprocess("%s: replacing %s by alternative %a to %s, %s",pref(kind,lookupname),gref(getchar(start)),choice,gref(choice),comment)
end
resetinjection(start)
- setfield(start,"char",choice)
+ setchar(start,choice)
else
if trace_alternatives then
logwarning("%s: no variant %a for %s, %s",pref(kind,lookupname),value,gref(getchar(start)),comment)
@@ -8459,7 +8562,7 @@ function handlers.gsub_ligature(head,start,kind,lookupname,ligature,sequence)
end
else
resetinjection(start)
- setfield(start,"char",lig)
+ setchar(start,lig)
if trace_ligatures then
logprocess("%s: replacing %s by (no real) ligature %s case 3",pref(kind,lookupname),gref(startchar),gref(lig))
end
@@ -8786,7 +8889,7 @@ function chainprocs.reversesub(head,start,stop,kind,chainname,currentcontext,loo
logprocess("%s: single reverse replacement of %s by %s",cref(kind,chainname),gref(char),gref(replacement))
end
resetinjection(start)
- setfield(start,"char",replacement)
+ setchar(start,replacement)
return head,start,true
else
return head,start,false
@@ -8818,7 +8921,7 @@ function chainprocs.gsub_single(head,start,stop,kind,chainname,currentcontext,lo
logprocess("%s: replacing single %s by %s",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(currentchar),gref(replacement))
end
resetinjection(current)
- setfield(current,"char",replacement)
+ setchar(current,replacement)
end
end
return head,start,true
@@ -8876,7 +8979,7 @@ function chainprocs.gsub_alternate(head,start,stop,kind,chainname,currentcontext
logprocess("%s: replacing %s by alternative %a to %s, %s",cref(kind,chainname,chainlookupname,lookupname),gref(char),choice,gref(choice),comment)
end
resetinjection(start)
- setfield(start,"char",choice)
+ setchar(start,choice)
else
if trace_alternatives then
logwarning("%s: no variant %a for %s, %s",cref(kind,chainname,chainlookupname,lookupname),value,gref(char),comment)
@@ -9371,13 +9474,13 @@ local function chaindisk(head,start,last,kind,chainname,ck,lookuphash,chainlooku
local tail=nil
if prev then
tail=prev
- setfield(current,"prev",sweepnode)
+ setprev(current,sweepnode)
else
tail=find_node_tail(head)
end
- setfield(sweepnode,"next",current)
- setfield(head,"prev",nil)
- setfield(tail,"next",nil)
+ setnext(sweepnode,current)
+ setprev(head,nil)
+ setnext(tail,nil)
appenddisc(sweepnode,head)
end
end
@@ -9465,12 +9568,12 @@ local function chaindisk(head,start,last,kind,chainname,ck,lookuphash,chainlooku
startishead=cf==head
cprev=getprev(cprev)
end
- setfield(lookaheaddisc,"prev",cprev)
+ setprev(lookaheaddisc,cprev)
if cprev then
- setfield(cprev,"next",lookaheaddisc)
+ setnext(cprev,lookaheaddisc)
end
- setfield(cf,"prev",nil)
- setfield(cl,"next",nil)
+ setprev(cf,nil)
+ setnext(cl,nil)
if startishead then
head=lookaheaddisc
end
@@ -9492,13 +9595,13 @@ local function chaindisk(head,start,last,kind,chainname,ck,lookuphash,chainlooku
new,cnew,ok=chainproc(new,cnew,clast,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence)
end
if pre then
- setfield(cl,"next",pre)
- setfield(pre,"prev",cl)
+ setnext(cl,pre)
+ setprev(pre,cl)
end
if replace then
local tail=find_node_tail(new)
- setfield(tail,"next",replace)
- setfield(replace,"prev",tail)
+ setnext(tail,replace)
+ setprev(replace,tail)
end
setfield(lookaheaddisc,"pre",cf)
setfield(lookaheaddisc,"replace",new)
@@ -9516,11 +9619,11 @@ local function chaindisk(head,start,last,kind,chainname,ck,lookuphash,chainlooku
cnext=getnext(cnext)
end
if cnext then
- setfield(cnext,"prev",backtrackdisc)
+ setprev(cnext,backtrackdisc)
end
- setfield(backtrackdisc,"next",cnext)
- setfield(cf,"prev",nil)
- setfield(cl,"next",nil)
+ setnext(backtrackdisc,cnext)
+ setprev(cf,nil)
+ setnext(cl,nil)
local replace=getfield(backtrackdisc,"replace")
local post=getfield(backtrackdisc,"post")
local new=copy_node_list(cf)
@@ -9540,15 +9643,15 @@ local function chaindisk(head,start,last,kind,chainname,ck,lookuphash,chainlooku
end
if post then
local tail=find_node_tail(post)
- setfield(tail,"next",cf)
- setfield(cf,"prev",tail)
+ setnext(tail,cf)
+ setprev(cf,tail)
else
post=cf
end
if replace then
local tail=find_node_tail(replace)
- setfield(tail,"next",new)
- setfield(new,"prev",tail)
+ setnext(tail,new)
+ setprev(new,tail)
else
replace=new
end
@@ -10076,25 +10179,40 @@ otf.chainhandlers={
normal=normal_handle_contextchain,
verbose=verbose_handle_contextchain,
}
+local handle_contextchain=nil
+function chained_contextchain(head,start,stop,...)
+ local steps=currentlookup.steps
+ local nofsteps=currentlookup.nofsteps
+ if nofsteps>1 then
+ reportmoresteps(dataset,sequence)
+ end
+ return handle_contextchain(head,start,...)
+end
function otf.setcontextchain(method)
if not method or method=="normal" or not otf.chainhandlers[method] then
- if handlers.contextchain then
+ if handle_contextchain then
logwarning("installing normal contextchain handler")
end
- handlers.contextchain=normal_handle_contextchain
+ handle_contextchain=normal_handle_contextchain
else
logwarning("installing contextchain handler %a",method)
local handler=otf.chainhandlers[method]
- handlers.contextchain=function(...)
+ handle_contextchain=function(...)
return handler(currentfont,...)
end
end
- handlers.gsub_context=handlers.contextchain
- handlers.gsub_contextchain=handlers.contextchain
- handlers.gsub_reversecontextchain=handlers.contextchain
- handlers.gpos_contextchain=handlers.contextchain
- handlers.gpos_context=handlers.contextchain
+ handlers.gsub_context=handle_contextchain
+ handlers.gsub_contextchain=handle_contextchain
+ handlers.gsub_reversecontextchain=handle_contextchain
+ handlers.gpos_contextchain=handle_contextchain
+ handlers.gpos_context=handle_contextchain
+ handlers.contextchain=handle_contextchain
end
+chainprocs.gsub_context=chained_contextchain
+chainprocs.gsub_contextchain=chained_contextchain
+chainprocs.gsub_reversecontextchain=chained_contextchain
+chainprocs.gpos_contextchain=chained_contextchain
+chainprocs.gpos_context=chained_contextchain
otf.setcontextchain()
local missing={}
local function logprocess(...)
@@ -10122,19 +10240,32 @@ setmetatableindex(lookuphashes,function(t,font)
t[font]=lookuphash
return lookuphash
end)
-local autofeatures=fonts.analyzers.features
-local function initialize(sequence,script,language,enabled)
+local autofeatures=fonts.analyzers.features
+local featuretypes=otf.tables.featuretypes
+local defaultscript=otf.features.checkeddefaultscript
+local defaultlanguage=otf.features.checkeddefaultlanguage
+local function initialize(sequence,script,language,enabled,autoscript,autolanguage)
local features=sequence.features
if features then
local order=sequence.order
if order then
- for i=1,#order do
- local kind=order[i]
+ local featuretype=featuretypes[sequence.type or "unknown"]
+ for i=1,#order do
+ local kind=order[i]
local valid=enabled[kind]
if valid then
- local scripts=features[kind]
- local languages=scripts[script] or scripts[wildcard]
- if languages and (languages[language] or languages[wildcard]) then
+ local scripts=features[kind]
+ local languages=scripts and (
+ scripts[script] or
+ scripts[wildcard] or
+ (autoscript and defaultscript(featuretype,autoscript,scripts))
+ )
+ local enabled=languages and (
+ languages[language] or
+ languages[wildcard] or
+ (autolanguage and defaultlanguage(featuretype,autolanguage,languages))
+ )
+ if enabled then
return { valid,autofeatures[kind] or false,sequence,kind }
end
end
@@ -10150,6 +10281,8 @@ function otf.dataset(tfmdata,font)
local language=properties.language or "dflt"
local script=properties.script or "dflt"
local enabled=shared.features
+ local autoscript=enabled and enabled.autoscript
+ local autolanguage=enabled and enabled.autolanguage
local res=resolved[font]
if not res then
res={}
@@ -10167,7 +10300,7 @@ function otf.dataset(tfmdata,font)
rs[language]=rl
local sequences=tfmdata.resources.sequences
for s=1,#sequences do
- local v=enabled and initialize(sequences[s],script,language,enabled)
+ local v=enabled and initialize(sequences[s],script,language,enabled,autoscript,autolanguage)
if v then
rl[#rl+1]=v
end
@@ -10197,57 +10330,57 @@ local function kernrun(disc,run)
if not pre then
elseif prev then
local nest=getprev(pre)
- setfield(pre,"prev",prev)
- setfield(prev,"next",pre)
+ setprev(pre,prev)
+ setnext(prev,pre)
run(prevmarks,"preinjections")
- setfield(pre,"prev",nest)
- setfield(prev,"next",disc)
+ setprev(pre,nest)
+ setnext(prev,disc)
else
run(pre,"preinjections")
end
if not post then
elseif next then
local tail=find_node_tail(post)
- setfield(tail,"next",next)
- setfield(next,"prev",tail)
+ setnext(tail,next)
+ setprev(next,tail)
run(post,"postinjections",next)
- setfield(tail,"next",nil)
- setfield(next,"prev",disc)
+ setnext(tail,nil)
+ setprev(next,disc)
else
run(post,"postinjections")
end
if not replace and prev and next then
- setfield(prev,"next",next)
- setfield(next,"prev",prev)
+ setnext(prev,next)
+ setprev(next,prev)
run(prevmarks,"injections",next)
- setfield(prev,"next",disc)
- setfield(next,"prev",disc)
+ setnext(prev,disc)
+ setprev(next,disc)
elseif prev and next then
local tail=find_node_tail(replace)
local nest=getprev(replace)
- setfield(replace,"prev",prev)
- setfield(prev,"next",replace)
- setfield(tail,"next",next)
- setfield(next,"prev",tail)
+ setprev(replace,prev)
+ setnext(prev,replace)
+ setnext(tail,next)
+ setprev(next,tail)
run(prevmarks,"replaceinjections",next)
- setfield(replace,"prev",nest)
- setfield(prev,"next",disc)
- setfield(tail,"next",nil)
- setfield(next,"prev",disc)
+ setprev(replace,nest)
+ setnext(prev,disc)
+ setnext(tail,nil)
+ setprev(next,disc)
elseif prev then
local nest=getprev(replace)
- setfield(replace,"prev",prev)
- setfield(prev,"next",replace)
+ setprev(replace,prev)
+ setnext(prev,replace)
run(prevmarks,"replaceinjections")
- setfield(replace,"prev",nest)
- setfield(prev,"next",disc)
+ setprev(replace,nest)
+ setnext(prev,disc)
elseif next then
local tail=find_node_tail(replace)
- setfield(tail,"next",next)
- setfield(next,"prev",tail)
+ setnext(tail,next)
+ setprev(next,tail)
run(replace,"replaceinjections",next)
- setfield(tail,"next",nil)
- setfield(next,"prev",disc)
+ setnext(tail,nil)
+ setprev(next,disc)
else
run(replace,"replaceinjections")
end
@@ -10294,21 +10427,21 @@ local function testrun(disc,trun,crun)
local prev=getprev(disc)
if prev then
local tail=find_node_tail(replace)
- setfield(tail,"next",next)
- setfield(next,"prev",tail)
+ setnext(tail,next)
+ setprev(next,tail)
if trun(replace,next) then
setfield(disc,"replace",nil)
- setfield(prev,"next",replace)
- setfield(replace,"prev",prev)
- setfield(next,"prev",tail)
- setfield(tail,"next",next)
- setfield(disc,"prev",nil)
- setfield(disc,"next",nil)
+ setnext(prev,replace)
+ setprev(replace,prev)
+ setprev(next,tail)
+ setnext(tail,next)
+ setprev(disc,nil)
+ setnext(disc,nil)
flush_node_list(disc)
return replace
else
- setfield(tail,"next",nil)
- setfield(next,"prev",disc)
+ setnext(tail,nil)
+ setprev(next,disc)
end
else
end
@@ -10326,19 +10459,19 @@ local function discrun(disc,drun,krun)
report_run("disc")
end
if next and prev then
- setfield(prev,"next",next)
+ setnext(prev,next)
drun(prev)
- setfield(prev,"next",disc)
+ setnext(prev,disc)
end
local pre=getfield(disc,"pre")
if not pre then
elseif prev then
local nest=getprev(pre)
- setfield(pre,"prev",prev)
- setfield(prev,"next",pre)
+ setprev(pre,prev)
+ setnext(prev,pre)
krun(prev,"preinjections")
- setfield(pre,"prev",nest)
- setfield(prev,"next",disc)
+ setprev(pre,nest)
+ setnext(prev,disc)
else
krun(pre,"preinjections")
end
@@ -10596,6 +10729,40 @@ local function featuresprocessor(head,font,attr)
end
elseif id==math_code then
start=getnext(end_of_math(start))
+ elseif id==dir_code then
+ local dir=getfield(start,"dir")
+ if dir=="+TLT" then
+ topstack=topstack+1
+ dirstack[topstack]=dir
+ rlmode=1
+ elseif dir=="+TRT" then
+ topstack=topstack+1
+ dirstack[topstack]=dir
+ rlmode=-1
+ elseif dir=="-TLT" or dir=="-TRT" then
+ topstack=topstack-1
+ rlmode=dirstack[topstack]=="+TRT" and -1 or 1
+ else
+ rlmode=rlparmode
+ end
+ if trace_directions then
+ report_process("directions after txtdir %a: parmode %a, txtmode %a, # stack %a, new dir %a",dir,rlparmode,rlmode,topstack,newdir)
+ end
+ start=getnext(start)
+ elseif id==localpar_code then
+ local dir=getfield(start,"dir")
+ if dir=="TRT" then
+ rlparmode=-1
+ elseif dir=="TLT" then
+ rlparmode=1
+ else
+ rlparmode=0
+ end
+ rlmode=rlparmode
+ if trace_directions then
+ report_process("directions after pardir %a: parmode %a, txtmode %a",dir,rlparmode,rlmode)
+ end
+ start=getnext(start)
else
start=getnext(start)
end
@@ -10816,6 +10983,40 @@ local function featuresprocessor(head,font,attr)
end
elseif id==math_code then
start=getnext(end_of_math(start))
+ elseif id==dir_code then
+ local dir=getfield(start,"dir")
+ if dir=="+TLT" then
+ topstack=topstack+1
+ dirstack[topstack]=dir
+ rlmode=1
+ elseif dir=="+TRT" then
+ topstack=topstack+1
+ dirstack[topstack]=dir
+ rlmode=-1
+ elseif dir=="-TLT" or dir=="-TRT" then
+ topstack=topstack-1
+ rlmode=dirstack[topstack]=="+TRT" and -1 or 1
+ else
+ rlmode=rlparmode
+ end
+ if trace_directions then
+ report_process("directions after txtdir %a: parmode %a, txtmode %a, # stack %a, new dir %a",dir,rlparmode,rlmode,topstack,newdir)
+ end
+ start=getnext(start)
+ elseif id==localpar_code then
+ local dir=getfield(start,"dir")
+ if dir=="TRT" then
+ rlparmode=-1
+ elseif dir=="TLT" then
+ rlparmode=1
+ else
+ rlparmode=0
+ end
+ rlmode=rlparmode
+ if trace_directions then
+ report_process("directions after pardir %a: parmode %a, txtmode %a",dir,rlparmode,rlmode)
+ end
+ start=getnext(start)
else
start=getnext(start)
end
@@ -10951,10 +11152,10 @@ local function split(replacement,original)
end
return result
end
-local valid={
- coverage={ chainsub=true,chainpos=true,contextsub=true },
+local valid={
+ coverage={ chainsub=true,chainpos=true,contextsub=true,contextpos=true },
reversecoverage={ reversesub=true },
- glyphs={ chainsub=true,chainpos=true },
+ glyphs={ chainsub=true,chainpos=true,contextsub=true,contextpos=true },
}
local function prepare_contextchains(tfmdata)
local rawdata=tfmdata.shared.rawdata
@@ -11007,7 +11208,7 @@ local function prepare_contextchains(tfmdata)
sequence[nofsequences]=after[n]
end
end
- if sequence[1] then
+ if sequence[start] then
nt=nt+1
t[nt]={ nofrules,lookuptype,sequence,start,stop,rule.lookups,replacements }
for unic in next,sequence[start] do
@@ -11058,10 +11259,10 @@ registerotffeature {
}
otf.handlers=handlers
-end --- [luaotfload, fontloader-2015-12-12.lua scope for “fonts-otn”] ---
+end --- [luaotfload, fontloader-2015-12-22.lua scope for “font-otn”] ---
-do --- [luaotfload, fontloader-2015-12-12.lua scope for “font-otp” 18b4375155925ee1809150f4f6c3973b] ---
+do --- [luaotfload, fontloader-2015-12-22.lua scope for “font-otp” 18b4375155925ee1809150f4f6c3973b] ---
if not modules then modules={} end modules ['font-otp']={
version=1.001,
@@ -11896,10 +12097,10 @@ end
otf.enhancers.unpack=unpackdata
otf.enhancers.pack=packdata
-end --- [luaotfload, fontloader-2015-12-12.lua scope for “font-otp”] ---
+end --- [luaotfload, fontloader-2015-12-22.lua scope for “font-otp”] ---
-do --- [luaotfload, fontloader-2015-12-12.lua scope for “fonts-lua” 50b8edb1db7009b6c661ab71ff24a466] ---
+do --- [luaotfload, fontloader-2015-12-22.lua scope for “fonts-lua” 50b8edb1db7009b6c661ab71ff24a466] ---
if not modules then modules={} end modules ['luatex-fonts-lua']={
version=1.001,
@@ -11932,10 +12133,10 @@ function fonts.readers.lua(specification)
end
end
-end --- [luaotfload, fontloader-2015-12-12.lua scope for “fonts-lua”] ---
+end --- [luaotfload, fontloader-2015-12-22.lua scope for “fonts-lua”] ---
-do --- [luaotfload, fontloader-2015-12-12.lua scope for “font-def” 3c71c27300a8cb5c29f5d278d2049fb6] ---
+do --- [luaotfload, fontloader-2015-12-22.lua scope for “font-def” 3c71c27300a8cb5c29f5d278d2049fb6] ---
if not modules then modules={} end modules ['font-def']={
version=1.001,
@@ -12266,12 +12467,12 @@ function font.getfont(id)
end
callbacks.register('define_font',definers.read,"definition of fonts (tfmdata preparation)")
-end --- [luaotfload, fontloader-2015-12-12.lua scope for “font-def”] ---
+end --- [luaotfload, fontloader-2015-12-22.lua scope for “font-def”] ---
-do --- [luaotfload, fontloader-2015-12-12.lua scope for “fonts-def” 8dc05f2aa96d2fd0245242c8fd3320eb] ---
+do --- [luaotfload, fontloader-2015-12-22.lua scope for “fonts-def” e758c9faca4d44382b88bbea892e8bbf] ---
-if not modules then modules={} end modules ['luatex-font-def']={
+if not modules then modules={} end modules ['luatex-fonts-def']={
version=1.001,
comment="companion to luatex-*.tex",
author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
@@ -12349,10 +12550,10 @@ function fonts.definers.applypostprocessors(tfmdata)
return tfmdata
end
-end --- [luaotfload, fontloader-2015-12-12.lua scope for “fonts-def”] ---
+end --- [luaotfload, fontloader-2015-12-22.lua scope for “fonts-def”] ---
-do --- [luaotfload, fontloader-2015-12-12.lua scope for “fonts-ext” 0eee87fb26b7d135da88ac0a43a8037a] ---
+do --- [luaotfload, fontloader-2015-12-22.lua scope for “fonts-ext” 0eee87fb26b7d135da88ac0a43a8037a] ---
if not modules then modules={} end modules ['luatex-fonts-ext']={
version=1.001,
@@ -12569,10 +12770,10 @@ otffeatures.register {
}
}
-end --- [luaotfload, fontloader-2015-12-12.lua scope for “fonts-ext”] ---
+end --- [luaotfload, fontloader-2015-12-22.lua scope for “fonts-ext”] ---
-do --- [luaotfload, fontloader-2015-12-12.lua scope for “fonts-cbk” 3e86c6a492ca8d792f6b06149ba0dd57] ---
+do --- [luaotfload, fontloader-2015-12-22.lua scope for “fonts-cbk” 3e86c6a492ca8d792f6b06149ba0dd57] ---
if not modules then modules={} end modules ['luatex-fonts-cbk']={
version=1.001,
@@ -12774,7 +12975,7 @@ function nodes.simple_font_handler(head)
end
end
-end --- [luaotfload, fontloader-2015-12-12.lua scope for “fonts-cbk”] ---
+end --- [luaotfload, fontloader-2015-12-22.lua scope for “fonts-cbk”] ---
--- vim:ft=lua:sw=2:ts=8:et:tw=79
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-basics-nod.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-basics-nod.lua
index 39400a3d001..78f1b172a43 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-basics-nod.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-basics-nod.lua
@@ -51,17 +51,23 @@ nodes = { }
nodes.pool = { }
nodes.handlers = { }
-local nodecodes = { } for k,v in next, node.types () do nodecodes[string.gsub(v,"_","")] = k end
-local whatcodes = { } for k,v in next, node.whatsits() do whatcodes[string.gsub(v,"_","")] = k end
-local glyphcodes = { [0] = "character", "glyph", "ligature", "ghost", "left", "right" }
-local disccodes = { [0] = "discretionary", "explicit", "automatic", "regular", "first", "second" }
-
-for i=0,#glyphcodes do glyphcodes[glyphcodes[i]] = i end
-for i=0,#disccodes do disccodes [disccodes [i]] = i end
+local nodecodes = { }
+local glyphcodes = node.subtypes("glyph")
+local disccodes = node.subtypes("disc")
+
+for k, v in next, node.types() do
+ v = string.gsub(v,"_","")
+ nodecodes[k] = v
+ nodecodes[v] = k
+end
+for i=0,#glyphcodes do
+ glyphcodes[glyphcodes[i]] = i
+end
+for i=0,#disccodes do
+ disccodes[disccodes[i]] = i
+end
nodes.nodecodes = nodecodes
-nodes.whatcodes = whatcodes
-nodes.whatsitcodes = whatcodes
nodes.glyphcodes = glyphcodes
nodes.disccodes = disccodes
@@ -140,7 +146,6 @@ nodes.slide = node.slide
nodes.vpack = node.vpack
nodes.first_glyph = node.first_glyph
-nodes.first_character = node.first_character
nodes.has_glyph = node.has_glyph or node.first_glyph
nodes.current_attr = node.current_attr
@@ -178,20 +183,33 @@ nodes.tonut = tonut
nuts.tonode = tonode
nuts.tonut = tonut
-
local getfield = direct.getfield
local setfield = direct.setfield
nuts.getfield = getfield
nuts.setfield = setfield
nuts.getnext = direct.getnext
+nuts.setnext = direct.setnext
nuts.getprev = direct.getprev
+nuts.setprev = direct.setprev
+nuts.getboth = direct.getboth
+nuts.setboth = direct.setboth
nuts.getid = direct.getid
-nuts.getattr = getfield
+nuts.getattr = direct.get_attribute or direct.has_attribute or getfield
nuts.setattr = setfield
nuts.getfont = direct.getfont
+nuts.setfont = direct.setfont
nuts.getsubtype = direct.getsubtype
+nuts.setsubtype = direct.setsubtype or function(n,s) setfield(n,"subtype",s) end
nuts.getchar = direct.getchar
+nuts.setchar = direct.setchar
+nuts.getdisc = direct.getdisc
+nuts.setdisc = direct.setdisc
+nuts.setlink = direct.setlink
+nuts.getlist = direct.getlist
+nuts.setlist = direct.setlist or function(n,l) setfield(n,"list",l) end
+nuts.getleader = direct.getleader
+nuts.setleader = direct.setleader or function(n,l) setfield(n,"leader",l) end
nuts.insert_before = direct.insert_before
nuts.insert_after = direct.insert_after
@@ -206,6 +224,9 @@ nuts.is_node = direct.is_node
nuts.end_of_math = direct.end_of_math
nuts.traverse = direct.traverse
nuts.traverse_id = direct.traverse_id
+nuts.traverse_char = direct.traverse_char
+nuts.ligaturing = direct.ligaturing
+nuts.kerning = direct.kerning
nuts.getprop = nuts.getattr
nuts.setprop = nuts.setattr
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-char-ini.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-char-ini.lua
new file mode 100644
index 00000000000..0a79051e8f0
--- /dev/null
+++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-char-ini.lua
@@ -0,0 +1,1318 @@
+if not modules then modules = { } end modules ['char-ini'] = {
+ version = 1.001,
+ comment = "companion to char-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- todo: make two files, one for format generation, one for format use
+-- todo: move some to char-utf
+
+-- we can remove the tag range starting at 0xE0000 (special applications)
+
+local utfchar, utfbyte, utfvalues, ustring, utotable = utf.char, utf.byte, utf.values, utf.ustring, utf.totable
+local concat, unpack, tohash = table.concat, table.unpack, table.tohash
+local next, tonumber, type, rawget, rawset = next, tonumber, type, rawget, rawset
+local format, lower, gsub = string.format, string.lower, string.gsub
+local P, R, S, Cs = lpeg.P, lpeg.R, lpeg.S, lpeg.Cs
+
+if not characters then require("char-def") end
+
+local lpegpatterns = lpeg.patterns
+local lpegmatch = lpeg.match
+local utf8byte = lpegpatterns.utf8byte
+local utf8character = lpegpatterns.utf8character
+
+local utfchartabletopattern = lpeg.utfchartabletopattern
+
+local allocate = utilities.storage.allocate
+local mark = utilities.storage.mark
+
+local setmetatableindex = table.setmetatableindex
+
+local trace_defining = false trackers.register("characters.defining", function(v) characters_defining = v end)
+
+local report_defining = logs.reporter("characters")
+
+--[[ldx--
+<p>This module implements some methods and creates additional datastructured
+from the big character table that we use for all kind of purposes:
+<type>char-def.lua</type>.</p>
+
+<p>We assume that at this point <type>characters.data</type> is already
+loaded!</p>
+--ldx]]--
+
+-- todo: in 'char-def.lua' assume defaults:
+--
+-- directtions = l
+-- cjkwd = a
+-- linebreak = al
+
+characters = characters or { }
+local characters = characters
+local data = characters.data
+
+if data then
+ mark(data) -- why does this fail
+else
+ report_defining("fatal error: 'char-def.lua' is not loaded")
+ os.exit()
+end
+
+--[[ldx--
+<p>This converts a string (if given) into a number.</p>
+--ldx]]--
+
+local pattern = (P("0x") + P("U+")) * ((R("09","AF")^1 * P(-1)) / function(s) return tonumber(s,16) end)
+
+lpegpatterns.chartonumber = pattern
+
+local function chartonumber(k)
+ if type(k) == "string" then
+ local u = lpegmatch(pattern,k)
+ if u then
+ return utfbyte(u)
+ else
+ return utfbyte(k) or 0
+ end
+ else
+ return k or 0
+ end
+end
+
+local function charfromnumber(k)
+ if type(k) == "number" then
+ return utfchar(k) or ""
+ else
+ local u = lpegmatch(pattern,k)
+ if u then
+ return utfchar(u)
+ else
+ return k
+ end
+ end
+end
+
+--~ print(chartonumber(97), chartonumber("a"), chartonumber("0x61"), chartonumber("U+61"))
+
+characters.tonumber = chartonumber
+characters.fromnumber = charfromnumber
+
+local private = {
+ description = "PRIVATE SLOT",
+}
+
+local ranges = allocate()
+characters.ranges = ranges
+
+setmetatableindex(data, function(t,k)
+ local tk = type(k)
+ if tk == "string" then
+ k = lpegmatch(pattern,k) or utfbyte(k)
+ if k then
+ local v = rawget(t,k)
+ if v then
+ return v
+ else
+ tk = "number" -- fall through to range
+ end
+ else
+ return private
+ end
+ end
+ if tk == "number" and k < 0xF0000 then
+ for r=1,#ranges do
+ local rr = ranges[r]
+ if k >= rr.first and k <= rr.last then
+ local extender = rr.extender
+ if extender then
+ local v = extender(k,v)
+ t[k] = v
+ return v
+ end
+ end
+ end
+ end
+ return private -- handy for when we loop over characters in fonts and check for a property
+end)
+
+local blocks = allocate {
+ ["aegeannumbers"] = { first = 0x10100, last = 0x1013F, description = "Aegean Numbers" },
+ ["ahom"] = { first = 0x11700, last = 0x1173F, description = "Ahom" },
+ ["alchemicalsymbols"] = { first = 0x1F700, last = 0x1F77F, description = "Alchemical Symbols" },
+ ["alphabeticpresentationforms"] = { first = 0x0FB00, last = 0x0FB4F, otf="latn", description = "Alphabetic Presentation Forms" },
+ ["anatolianhieroglyphs"] = { first = 0x14400, last = 0x1467F, description = "Anatolian Hieroglyphs" },
+ ["ancientgreekmusicalnotation"] = { first = 0x1D200, last = 0x1D24F, otf="grek", description = "Ancient Greek Musical Notation" },
+ ["ancientgreeknumbers"] = { first = 0x10140, last = 0x1018F, otf="grek", description = "Ancient Greek Numbers" },
+ ["ancientsymbols"] = { first = 0x10190, last = 0x101CF, otf="grek", description = "Ancient Symbols" },
+ ["arabic"] = { first = 0x00600, last = 0x006FF, otf="arab", description = "Arabic" },
+ ["arabicextendeda"] = { first = 0x008A0, last = 0x008FF, description = "Arabic Extended-A" },
+ ["arabicmathematicalalphabeticsymbols"] = { first = 0x1EE00, last = 0x1EEFF, description = "Arabic Mathematical Alphabetic Symbols" },
+ ["arabicpresentationformsa"] = { first = 0x0FB50, last = 0x0FDFF, otf="arab", description = "Arabic Presentation Forms-A" },
+ ["arabicpresentationformsb"] = { first = 0x0FE70, last = 0x0FEFF, otf="arab", description = "Arabic Presentation Forms-B" },
+ ["arabicsupplement"] = { first = 0x00750, last = 0x0077F, otf="arab", description = "Arabic Supplement" },
+ ["armenian"] = { first = 0x00530, last = 0x0058F, otf="armn", description = "Armenian" },
+ ["arrows"] = { first = 0x02190, last = 0x021FF, description = "Arrows" },
+ ["avestan"] = { first = 0x10B00, last = 0x10B3F, description = "Avestan" },
+ ["balinese"] = { first = 0x01B00, last = 0x01B7F, otf="bali", description = "Balinese" },
+ ["bamum"] = { first = 0x0A6A0, last = 0x0A6FF, description = "Bamum" },
+ ["bamumsupplement"] = { first = 0x16800, last = 0x16A3F, description = "Bamum Supplement" },
+ ["basiclatin"] = { first = 0x00000, last = 0x0007F, otf="latn", description = "Basic Latin" },
+ ["bassavah"] = { first = 0x16AD0, last = 0x16AFF, description = "Bassa Vah" },
+ ["batak"] = { first = 0x01BC0, last = 0x01BFF, description = "Batak" },
+ ["bengali"] = { first = 0x00980, last = 0x009FF, otf="beng", description = "Bengali" },
+ ["blockelements"] = { first = 0x02580, last = 0x0259F, otf="bopo", description = "Block Elements" },
+ ["bopomofo"] = { first = 0x03100, last = 0x0312F, otf="bopo", description = "Bopomofo" },
+ ["bopomofoextended"] = { first = 0x031A0, last = 0x031BF, otf="bopo", description = "Bopomofo Extended" },
+ ["boxdrawing"] = { first = 0x02500, last = 0x0257F, description = "Box Drawing" },
+ ["brahmi"] = { first = 0x11000, last = 0x1107F, description = "Brahmi" },
+ ["braillepatterns"] = { first = 0x02800, last = 0x028FF, otf="brai", description = "Braille Patterns" },
+ ["buginese"] = { first = 0x01A00, last = 0x01A1F, otf="bugi", description = "Buginese" },
+ ["buhid"] = { first = 0x01740, last = 0x0175F, otf="buhd", description = "Buhid" },
+ ["byzantinemusicalsymbols"] = { first = 0x1D000, last = 0x1D0FF, otf="byzm", description = "Byzantine Musical Symbols" },
+ ["carian"] = { first = 0x102A0, last = 0x102DF, description = "Carian" },
+ ["caucasianalbanian"] = { first = 0x10530, last = 0x1056F, description = "Caucasian Albanian" },
+ ["chakma"] = { first = 0x11100, last = 0x1114F, description = "Chakma" },
+ ["cham"] = { first = 0x0AA00, last = 0x0AA5F, description = "Cham" },
+ ["cherokee"] = { first = 0x013A0, last = 0x013FF, otf="cher", description = "Cherokee" },
+ ["cherokeesupplement"] = { first = 0x0AB70, last = 0x0ABBF, description = "Cherokee Supplement" },
+ ["cjkcompatibility"] = { first = 0x03300, last = 0x033FF, otf="hang", description = "CJK Compatibility" },
+ ["cjkcompatibilityforms"] = { first = 0x0FE30, last = 0x0FE4F, otf="hang", description = "CJK Compatibility Forms" },
+ ["cjkcompatibilityideographs"] = { first = 0x0F900, last = 0x0FAFF, otf="hang", description = "CJK Compatibility Ideographs" },
+ ["cjkcompatibilityideographssupplement"] = { first = 0x2F800, last = 0x2FA1F, otf="hang", description = "CJK Compatibility Ideographs Supplement" },
+ ["cjkradicalssupplement"] = { first = 0x02E80, last = 0x02EFF, otf="hang", description = "CJK Radicals Supplement" },
+ ["cjkstrokes"] = { first = 0x031C0, last = 0x031EF, otf="hang", description = "CJK Strokes" },
+ ["cjksymbolsandpunctuation"] = { first = 0x03000, last = 0x0303F, otf="hang", description = "CJK Symbols and Punctuation" },
+ ["cjkunifiedideographs"] = { first = 0x04E00, last = 0x09FFF, otf="hang", description = "CJK Unified Ideographs", catcode = "letter" },
+ ["cjkunifiedideographsextensiona"] = { first = 0x03400, last = 0x04DBF, otf="hang", description = "CJK Unified Ideographs Extension A" },
+ ["cjkunifiedideographsextensionb"] = { first = 0x20000, last = 0x2A6DF, otf="hang", description = "CJK Unified Ideographs Extension B" },
+ ["cjkunifiedideographsextensionc"] = { first = 0x2A700, last = 0x2B73F, description = "CJK Unified Ideographs Extension C" },
+ ["cjkunifiedideographsextensiond"] = { first = 0x2B740, last = 0x2B81F, description = "CJK Unified Ideographs Extension D" },
+ ["cjkunifiedideographsextensione"] = { first = 0x2B820, last = 0x2CEAF, description = "CJK Unified Ideographs Extension E" },
+ ["combiningdiacriticalmarks"] = { first = 0x00300, last = 0x0036F, description = "Combining Diacritical Marks" },
+ ["combiningdiacriticalmarksextended"] = { first = 0x01AB0, last = 0x01AFF, description = "Combining Diacritical Marks Extended" },
+ ["combiningdiacriticalmarksforsymbols"] = { first = 0x020D0, last = 0x020FF, description = "Combining Diacritical Marks for Symbols" },
+ ["combiningdiacriticalmarkssupplement"] = { first = 0x01DC0, last = 0x01DFF, description = "Combining Diacritical Marks Supplement" },
+ ["combininghalfmarks"] = { first = 0x0FE20, last = 0x0FE2F, description = "Combining Half Marks" },
+ ["commonindicnumberforms"] = { first = 0x0A830, last = 0x0A83F, description = "Common Indic Number Forms" },
+ ["controlpictures"] = { first = 0x02400, last = 0x0243F, description = "Control Pictures" },
+ ["coptic"] = { first = 0x02C80, last = 0x02CFF, otf="copt", description = "Coptic" },
+ ["copticepactnumbers"] = { first = 0x102E0, last = 0x102FF, description = "Coptic Epact Numbers" },
+ ["countingrodnumerals"] = { first = 0x1D360, last = 0x1D37F, description = "Counting Rod Numerals" },
+ ["cuneiform"] = { first = 0x12000, last = 0x123FF, otf="xsux", description = "Cuneiform" },
+ ["cuneiformnumbersandpunctuation"] = { first = 0x12400, last = 0x1247F, otf="xsux", description = "Cuneiform Numbers and Punctuation" },
+ ["currencysymbols"] = { first = 0x020A0, last = 0x020CF, description = "Currency Symbols" },
+ ["cypriotsyllabary"] = { first = 0x10800, last = 0x1083F, otf="cprt", description = "Cypriot Syllabary" },
+ ["cyrillic"] = { first = 0x00400, last = 0x004FF, otf="cyrl", description = "Cyrillic" },
+ ["cyrillicextendeda"] = { first = 0x02DE0, last = 0x02DFF, otf="cyrl", description = "Cyrillic Extended-A" },
+ ["cyrillicextendedb"] = { first = 0x0A640, last = 0x0A69F, otf="cyrl", description = "Cyrillic Extended-B" },
+ ["cyrillicsupplement"] = { first = 0x00500, last = 0x0052F, otf="cyrl", description = "Cyrillic Supplement" },
+ ["deseret"] = { first = 0x10400, last = 0x1044F, otf="dsrt", description = "Deseret" },
+ ["devanagari"] = { first = 0x00900, last = 0x0097F, otf="deva", description = "Devanagari" },
+ ["devanagariextended"] = { first = 0x0A8E0, last = 0x0A8FF, description = "Devanagari Extended" },
+ ["digitsarabicindic"] = { first = 0x00660, last = 0x00669, math = true },
+ -- ["digitsbengali"] = { first = 0x009E6, last = 0x009EF, math = true },
+ ["digitsbold"] = { first = 0x1D7CE, last = 0x1D7D8, math = true },
+ -- ["digitsdevanagari"] = { first = 0x00966, last = 0x0096F, math = true },
+ ["digitsdoublestruck"] = { first = 0x1D7D8, last = 0x1D7E2, math = true },
+ -- ["digitsethiopic"] = { first = 0x01369, last = 0x01371, math = true },
+ ["digitsextendedarabicindic"] = { first = 0x006F0, last = 0x006F9, math = true },
+ -- ["digitsgujarati"] = { first = 0x00AE6, last = 0x00AEF, math = true },
+ -- ["digitsgurmukhi"] = { first = 0x00A66, last = 0x00A6F, math = true },
+ -- ["digitskannada"] = { first = 0x00CE6, last = 0x00CEF, math = true },
+ -- ["digitskhmer"] = { first = 0x017E0, last = 0x017E9, math = true },
+ -- ["digitslao"] = { first = 0x00ED0, last = 0x00ED9, math = true },
+ ["digitslatin"] = { first = 0x00030, last = 0x00039, math = true },
+ -- ["digitsmalayalam"] = { first = 0x00D66, last = 0x00D6F, math = true },
+ -- ["digitsmongolian"] = { first = 0x01810, last = 0x01809, math = true },
+ ["digitsmonospace"] = { first = 0x1D7F6, last = 0x1D80F, math = true },
+ -- ["digitsmyanmar"] = { first = 0x01040, last = 0x01049, math = true },
+ ["digitsnormal"] = { first = 0x00030, last = 0x00039, math = true },
+ -- ["digitsoriya"] = { first = 0x00B66, last = 0x00B6F, math = true },
+ ["digitssansserifbold"] = { first = 0x1D7EC, last = 0x1D805, math = true },
+ ["digitssansserifnormal"] = { first = 0x1D7E2, last = 0x1D7EC, math = true },
+ -- ["digitstamil"] = { first = 0x00030, last = 0x00039, math = true }, -- no zero
+ -- ["digitstelugu"] = { first = 0x00C66, last = 0x00C6F, math = true },
+ -- ["digitsthai"] = { first = 0x00E50, last = 0x00E59, math = true },
+ -- ["digitstibetan"] = { first = 0x00F20, last = 0x00F29, math = true },
+ ["dingbats"] = { first = 0x02700, last = 0x027BF, description = "Dingbats" },
+ ["dominotiles"] = { first = 0x1F030, last = 0x1F09F, description = "Domino Tiles" },
+ ["duployan"] = { first = 0x1BC00, last = 0x1BC9F, description = "Duployan" },
+ ["earlydynasticcuneiform"] = { first = 0x12480, last = 0x1254F, description = "Early Dynastic Cuneiform" },
+ ["egyptianhieroglyphs"] = { first = 0x13000, last = 0x1342F, description = "Egyptian Hieroglyphs" },
+ ["elbasan"] = { first = 0x10500, last = 0x1052F, description = "Elbasan" },
+ ["emoticons"] = { first = 0x1F600, last = 0x1F64F, description = "Emoticons" },
+ ["enclosedalphanumerics"] = { first = 0x02460, last = 0x024FF, description = "Enclosed Alphanumerics" },
+ ["enclosedalphanumericsupplement"] = { first = 0x1F100, last = 0x1F1FF, description = "Enclosed Alphanumeric Supplement" },
+ ["enclosedcjklettersandmonths"] = { first = 0x03200, last = 0x032FF, description = "Enclosed CJK Letters and Months" },
+ ["enclosedideographicsupplement"] = { first = 0x1F200, last = 0x1F2FF, description = "Enclosed Ideographic Supplement" },
+ ["ethiopic"] = { first = 0x01200, last = 0x0137F, otf="ethi", description = "Ethiopic" },
+ ["ethiopicextended"] = { first = 0x02D80, last = 0x02DDF, otf="ethi", description = "Ethiopic Extended" },
+ ["ethiopicextendeda"] = { first = 0x0AB00, last = 0x0AB2F, description = "Ethiopic Extended-A" },
+ ["ethiopicsupplement"] = { first = 0x01380, last = 0x0139F, otf="ethi", description = "Ethiopic Supplement" },
+ ["generalpunctuation"] = { first = 0x02000, last = 0x0206F, description = "General Punctuation" },
+ ["geometricshapes"] = { first = 0x025A0, last = 0x025FF, math = true, description = "Geometric Shapes" },
+ ["geometricshapesextended"] = { first = 0x1F780, last = 0x1F7FF, description = "Geometric Shapes Extended" },
+ ["georgian"] = { first = 0x010A0, last = 0x010FF, otf="geor", description = "Georgian" },
+ ["georgiansupplement"] = { first = 0x02D00, last = 0x02D2F, otf="geor", description = "Georgian Supplement" },
+ ["glagolitic"] = { first = 0x02C00, last = 0x02C5F, otf="glag", description = "Glagolitic" },
+ ["gothic"] = { first = 0x10330, last = 0x1034F, otf="goth", description = "Gothic" },
+ ["grantha"] = { first = 0x11300, last = 0x1137F, description = "Grantha" },
+ ["greekandcoptic"] = { first = 0x00370, last = 0x003FF, otf="grek", description = "Greek and Coptic" },
+ ["greekextended"] = { first = 0x01F00, last = 0x01FFF, otf="grek", description = "Greek Extended" },
+ ["gujarati"] = { first = 0x00A80, last = 0x00AFF, otf="gujr", description = "Gujarati" },
+ ["gurmukhi"] = { first = 0x00A00, last = 0x00A7F, otf="guru", description = "Gurmukhi" },
+ ["halfwidthandfullwidthforms"] = { first = 0x0FF00, last = 0x0FFEF, description = "Halfwidth and Fullwidth Forms" },
+ ["hangulcompatibilityjamo"] = { first = 0x03130, last = 0x0318F, otf="jamo", description = "Hangul Compatibility Jamo" },
+ ["hanguljamo"] = { first = 0x01100, last = 0x011FF, otf="jamo", description = "Hangul Jamo" },
+ ["hanguljamoextendeda"] = { first = 0x0A960, last = 0x0A97F, description = "Hangul Jamo Extended-A" },
+ ["hanguljamoextendedb"] = { first = 0x0D7B0, last = 0x0D7FF, description = "Hangul Jamo Extended-B" },
+ ["hangulsyllables"] = { first = 0x0AC00, last = 0x0D7AF, otf="hang", description = "Hangul Syllables" },
+ ["hanunoo"] = { first = 0x01720, last = 0x0173F, otf="hano", description = "Hanunoo" },
+ ["hatran"] = { first = 0x108E0, last = 0x108FF, description = "Hatran" },
+ ["hebrew"] = { first = 0x00590, last = 0x005FF, otf="hebr", description = "Hebrew" },
+ ["highprivateusesurrogates"] = { first = 0x0DB80, last = 0x0DBFF, description = "High Private Use Surrogates" },
+ ["highsurrogates"] = { first = 0x0D800, last = 0x0DB7F, description = "High Surrogates" },
+ ["hiragana"] = { first = 0x03040, last = 0x0309F, otf="kana", description = "Hiragana" },
+ ["ideographicdescriptioncharacters"] = { first = 0x02FF0, last = 0x02FFF, description = "Ideographic Description Characters" },
+ ["imperialaramaic"] = { first = 0x10840, last = 0x1085F, description = "Imperial Aramaic" },
+ ["inscriptionalpahlavi"] = { first = 0x10B60, last = 0x10B7F, description = "Inscriptional Pahlavi" },
+ ["inscriptionalparthian"] = { first = 0x10B40, last = 0x10B5F, description = "Inscriptional Parthian" },
+ ["ipaextensions"] = { first = 0x00250, last = 0x002AF, description = "IPA Extensions" },
+ ["javanese"] = { first = 0x0A980, last = 0x0A9DF, description = "Javanese" },
+ ["kaithi"] = { first = 0x11080, last = 0x110CF, description = "Kaithi" },
+ ["kanasupplement"] = { first = 0x1B000, last = 0x1B0FF, description = "Kana Supplement" },
+ ["kanbun"] = { first = 0x03190, last = 0x0319F, description = "Kanbun" },
+ ["kangxiradicals"] = { first = 0x02F00, last = 0x02FDF, description = "Kangxi Radicals" },
+ ["kannada"] = { first = 0x00C80, last = 0x00CFF, otf="knda", description = "Kannada" },
+ ["katakana"] = { first = 0x030A0, last = 0x030FF, otf="kana", description = "Katakana" },
+ ["katakanaphoneticextensions"] = { first = 0x031F0, last = 0x031FF, otf="kana", description = "Katakana Phonetic Extensions" },
+ ["kayahli"] = { first = 0x0A900, last = 0x0A92F, description = "Kayah Li" },
+ ["kharoshthi"] = { first = 0x10A00, last = 0x10A5F, otf="khar", description = "Kharoshthi" },
+ ["khmer"] = { first = 0x01780, last = 0x017FF, otf="khmr", description = "Khmer" },
+ ["khmersymbols"] = { first = 0x019E0, last = 0x019FF, otf="khmr", description = "Khmer Symbols" },
+ ["khojki"] = { first = 0x11200, last = 0x1124F, description = "Khojki" },
+ ["khudawadi"] = { first = 0x112B0, last = 0x112FF, description = "Khudawadi" },
+ ["lao"] = { first = 0x00E80, last = 0x00EFF, otf="lao", description = "Lao" },
+ ["latinextendeda"] = { first = 0x00100, last = 0x0017F, otf="latn", description = "Latin Extended-A" },
+ ["latinextendedadditional"] = { first = 0x01E00, last = 0x01EFF, otf="latn", description = "Latin Extended Additional" },
+ ["latinextendedb"] = { first = 0x00180, last = 0x0024F, otf="latn", description = "Latin Extended-B" },
+ ["latinextendedc"] = { first = 0x02C60, last = 0x02C7F, otf="latn", description = "Latin Extended-C" },
+ ["latinextendedd"] = { first = 0x0A720, last = 0x0A7FF, otf="latn", description = "Latin Extended-D" },
+ ["latinextendede"] = { first = 0x0AB30, last = 0x0AB6F, description = "Latin Extended-E" },
+ ["latinsupplement"] = { first = 0x00080, last = 0x000FF, otf="latn", description = "Latin-1 Supplement" },
+ ["lepcha"] = { first = 0x01C00, last = 0x01C4F, description = "Lepcha" },
+ ["letterlikesymbols"] = { first = 0x02100, last = 0x0214F, math = true, description = "Letterlike Symbols" },
+ ["limbu"] = { first = 0x01900, last = 0x0194F, otf="limb", description = "Limbu" },
+ ["lineara"] = { first = 0x10600, last = 0x1077F, description = "Linear A" },
+ ["linearbideograms"] = { first = 0x10080, last = 0x100FF, otf="linb", description = "Linear B Ideograms" },
+ ["linearbsyllabary"] = { first = 0x10000, last = 0x1007F, otf="linb", description = "Linear B Syllabary" },
+ ["lisu"] = { first = 0x0A4D0, last = 0x0A4FF, description = "Lisu" },
+ ["lowercasebold"] = { first = 0x1D41A, last = 0x1D433, math = true },
+ ["lowercaseboldfraktur"] = { first = 0x1D586, last = 0x1D59F, math = true },
+ ["lowercasebolditalic"] = { first = 0x1D482, last = 0x1D49B, math = true },
+ ["lowercaseboldscript"] = { first = 0x1D4EA, last = 0x1D503, math = true },
+ ["lowercasedoublestruck"] = { first = 0x1D552, last = 0x1D56B, math = true },
+ ["lowercasefraktur"] = { first = 0x1D51E, last = 0x1D537, math = true },
+ ["lowercasegreekbold"] = { first = 0x1D6C2, last = 0x1D6DB, math = true },
+ ["lowercasegreekbolditalic"] = { first = 0x1D736, last = 0x1D74F, math = true },
+ ["lowercasegreekitalic"] = { first = 0x1D6FC, last = 0x1D715, math = true },
+ ["lowercasegreeknormal"] = { first = 0x003B1, last = 0x003CA, math = true },
+ ["lowercasegreeksansserifbold"] = { first = 0x1D770, last = 0x1D789, math = true },
+ ["lowercasegreeksansserifbolditalic"] = { first = 0x1D7AA, last = 0x1D7C3, math = true },
+ ["lowercaseitalic"] = { first = 0x1D44E, last = 0x1D467, math = true },
+ ["lowercasemonospace"] = { first = 0x1D68A, last = 0x1D6A3, math = true },
+ ["lowercasenormal"] = { first = 0x00061, last = 0x0007A, math = true },
+ ["lowercasesansserifbold"] = { first = 0x1D5EE, last = 0x1D607, math = true },
+ ["lowercasesansserifbolditalic"] = { first = 0x1D656, last = 0x1D66F, math = true },
+ ["lowercasesansserifitalic"] = { first = 0x1D622, last = 0x1D63B, math = true },
+ ["lowercasesansserifnormal"] = { first = 0x1D5BA, last = 0x1D5D3, math = true },
+ ["lowercasescript"] = { first = 0x1D4B6, last = 0x1D4CF, math = true },
+ ["lowsurrogates"] = { first = 0x0DC00, last = 0x0DFFF, description = "Low Surrogates" },
+ ["lycian"] = { first = 0x10280, last = 0x1029F, description = "Lycian" },
+ ["lydian"] = { first = 0x10920, last = 0x1093F, description = "Lydian" },
+ ["mahajani"] = { first = 0x11150, last = 0x1117F, description = "Mahajani" },
+ ["mahjongtiles"] = { first = 0x1F000, last = 0x1F02F, description = "Mahjong Tiles" },
+ ["malayalam"] = { first = 0x00D00, last = 0x00D7F, otf="mlym", description = "Malayalam" },
+ ["mandaic"] = { first = 0x00840, last = 0x0085F, otf="mand", description = "Mandaic" },
+ ["manichaean"] = { first = 0x10AC0, last = 0x10AFF, description = "Manichaean" },
+ ["mathematicalalphanumericsymbols"] = { first = 0x1D400, last = 0x1D7FF, math = true, description = "Mathematical Alphanumeric Symbols" },
+ ["mathematicaloperators"] = { first = 0x02200, last = 0x022FF, math = true, description = "Mathematical Operators" },
+ ["meeteimayek"] = { first = 0x0ABC0, last = 0x0ABFF, description = "Meetei Mayek" },
+ ["meeteimayekextensions"] = { first = 0x0AAE0, last = 0x0AAFF, description = "Meetei Mayek Extensions" },
+ ["mendekikakui"] = { first = 0x1E800, last = 0x1E8DF, description = "Mende Kikakui" },
+ ["meroiticcursive"] = { first = 0x109A0, last = 0x109FF, description = "Meroitic Cursive" },
+ ["meroitichieroglyphs"] = { first = 0x10980, last = 0x1099F, description = "Meroitic Hieroglyphs" },
+ ["miao"] = { first = 0x16F00, last = 0x16F9F, description = "Miao" },
+ ["miscellaneousmathematicalsymbolsa"] = { first = 0x027C0, last = 0x027EF, math = true, description = "Miscellaneous Mathematical Symbols-A" },
+ ["miscellaneousmathematicalsymbolsb"] = { first = 0x02980, last = 0x029FF, math = true, description = "Miscellaneous Mathematical Symbols-B" },
+ ["miscellaneoussymbols"] = { first = 0x02600, last = 0x026FF, math = true, description = "Miscellaneous Symbols" },
+ ["miscellaneoussymbolsandarrows"] = { first = 0x02B00, last = 0x02BFF, math = true, description = "Miscellaneous Symbols and Arrows" },
+ ["miscellaneoussymbolsandpictographs"] = { first = 0x1F300, last = 0x1F5FF, description = "Miscellaneous Symbols and Pictographs" },
+ ["miscellaneoustechnical"] = { first = 0x02300, last = 0x023FF, math = true, description = "Miscellaneous Technical" },
+ ["modi"] = { first = 0x11600, last = 0x1165F, description = "Modi" },
+ ["modifiertoneletters"] = { first = 0x0A700, last = 0x0A71F, description = "Modifier Tone Letters" },
+ ["mongolian"] = { first = 0x01800, last = 0x018AF, otf="mong", description = "Mongolian" },
+ ["mro"] = { first = 0x16A40, last = 0x16A6F, description = "Mro" },
+ ["multani"] = { first = 0x11280, last = 0x112AF, description = "Multani" },
+ ["musicalsymbols"] = { first = 0x1D100, last = 0x1D1FF, otf="musc", description = "Musical Symbols" },
+ ["myanmar"] = { first = 0x01000, last = 0x0109F, otf="mymr", description = "Myanmar" },
+ ["myanmarextendeda"] = { first = 0x0AA60, last = 0x0AA7F, description = "Myanmar Extended-A" },
+ ["myanmarextendedb"] = { first = 0x0A9E0, last = 0x0A9FF, description = "Myanmar Extended-B" },
+ ["nabataean"] = { first = 0x10880, last = 0x108AF, description = "Nabataean" },
+ ["newtailue"] = { first = 0x01980, last = 0x019DF, description = "New Tai Lue" },
+ ["nko"] = { first = 0x007C0, last = 0x007FF, otf="nko", description = "NKo" },
+ ["numberforms"] = { first = 0x02150, last = 0x0218F, description = "Number Forms" },
+ ["ogham"] = { first = 0x01680, last = 0x0169F, otf="ogam", description = "Ogham" },
+ ["olchiki"] = { first = 0x01C50, last = 0x01C7F, description = "Ol Chiki" },
+ ["oldhungarian"] = { first = 0x10C80, last = 0x10CFF, description = "Old Hungarian" },
+ ["olditalic"] = { first = 0x10300, last = 0x1032F, otf="ital", description = "Old Italic" },
+ ["oldnortharabian"] = { first = 0x10A80, last = 0x10A9F, description = "Old North Arabian" },
+ ["oldpermic"] = { first = 0x10350, last = 0x1037F, description = "Old Permic" },
+ ["oldpersian"] = { first = 0x103A0, last = 0x103DF, otf="xpeo", description = "Old Persian" },
+ ["oldsoutharabian"] = { first = 0x10A60, last = 0x10A7F, description = "Old South Arabian" },
+ ["oldturkic"] = { first = 0x10C00, last = 0x10C4F, description = "Old Turkic" },
+ ["opticalcharacterrecognition"] = { first = 0x02440, last = 0x0245F, description = "Optical Character Recognition" },
+ ["oriya"] = { first = 0x00B00, last = 0x00B7F, otf="orya", description = "Oriya" },
+ ["ornamentaldingbats"] = { first = 0x1F650, last = 0x1F67F, description = "Ornamental Dingbats" },
+ ["osmanya"] = { first = 0x10480, last = 0x104AF, otf="osma", description = "Osmanya" },
+ ["pahawhhmong"] = { first = 0x16B00, last = 0x16B8F, description = "Pahawh Hmong" },
+ ["palmyrene"] = { first = 0x10860, last = 0x1087F, description = "Palmyrene" },
+ ["paucinhau"] = { first = 0x11AC0, last = 0x11AFF, description = "Pau Cin Hau" },
+ ["phagspa"] = { first = 0x0A840, last = 0x0A87F, otf="phag", description = "Phags-pa" },
+ ["phaistosdisc"] = { first = 0x101D0, last = 0x101FF, description = "Phaistos Disc" },
+ ["phoenician"] = { first = 0x10900, last = 0x1091F, otf="phnx", description = "Phoenician" },
+ ["phoneticextensions"] = { first = 0x01D00, last = 0x01D7F, description = "Phonetic Extensions" },
+ ["phoneticextensionssupplement"] = { first = 0x01D80, last = 0x01DBF, description = "Phonetic Extensions Supplement" },
+ ["playingcards"] = { first = 0x1F0A0, last = 0x1F0FF, description = "Playing Cards" },
+ ["privateusearea"] = { first = 0x0E000, last = 0x0F8FF, description = "Private Use Area" },
+ ["psalterpahlavi"] = { first = 0x10B80, last = 0x10BAF, description = "Psalter Pahlavi" },
+ ["rejang"] = { first = 0x0A930, last = 0x0A95F, description = "Rejang" },
+ ["ruminumeralsymbols"] = { first = 0x10E60, last = 0x10E7F, description = "Rumi Numeral Symbols" },
+ ["runic"] = { first = 0x016A0, last = 0x016FF, otf="runr", description = "Runic" },
+ ["samaritan"] = { first = 0x00800, last = 0x0083F, description = "Samaritan" },
+ ["saurashtra"] = { first = 0x0A880, last = 0x0A8DF, description = "Saurashtra" },
+ ["sharada"] = { first = 0x11180, last = 0x111DF, description = "Sharada" },
+ ["shavian"] = { first = 0x10450, last = 0x1047F, otf="shaw", description = "Shavian" },
+ ["shorthandformatcontrols"] = { first = 0x1BCA0, last = 0x1BCAF, description = "Shorthand Format Controls" },
+ ["siddham"] = { first = 0x11580, last = 0x115FF, description = "Siddham" },
+ ["sinhala"] = { first = 0x00D80, last = 0x00DFF, otf="sinh", description = "Sinhala" },
+ ["sinhalaarchaicnumbers"] = { first = 0x111E0, last = 0x111FF, description = "Sinhala Archaic Numbers" },
+ ["smallformvariants"] = { first = 0x0FE50, last = 0x0FE6F, description = "Small Form Variants" },
+ ["sorasompeng"] = { first = 0x110D0, last = 0x110FF, description = "Sora Sompeng" },
+ ["spacingmodifierletters"] = { first = 0x002B0, last = 0x002FF, description = "Spacing Modifier Letters" },
+ ["specials"] = { first = 0x0FFF0, last = 0x0FFFF, description = "Specials" },
+ ["sundanese"] = { first = 0x01B80, last = 0x01BBF, description = "Sundanese" },
+ ["sundanesesupplement"] = { first = 0x01CC0, last = 0x01CCF, description = "Sundanese Supplement" },
+ ["superscriptsandsubscripts"] = { first = 0x02070, last = 0x0209F, description = "Superscripts and Subscripts" },
+ ["supplementalarrowsa"] = { first = 0x027F0, last = 0x027FF, math = true, description = "Supplemental Arrows-A" },
+ ["supplementalarrowsb"] = { first = 0x02900, last = 0x0297F, math = true, description = "Supplemental Arrows-B" },
+ ["supplementalarrowsc"] = { first = 0x1F800, last = 0x1F8FF, math = true, description = "Supplemental Arrows-C" },
+ ["supplementalmathematicaloperators"] = { first = 0x02A00, last = 0x02AFF, math = true, description = "Supplemental Mathematical Operators" },
+ ["supplementalpunctuation"] = { first = 0x02E00, last = 0x02E7F, description = "Supplemental Punctuation" },
+ ["supplementalsymbolsandpictographs"] = { first = 0x1F900, last = 0x1F9FF, description = "Supplemental Symbols and Pictographs" },
+ ["supplementaryprivateuseareaa"] = { first = 0xF0000, last = 0xFFFFF, description = "Supplementary Private Use Area-A" },
+ ["supplementaryprivateuseareab"] = { first = 0x100000,last = 0x10FFFF, description = "Supplementary Private Use Area-B" },
+ ["suttonsignwriting"] = { first = 0x1D800, last = 0x1DAAF, description = "Sutton SignWriting" },
+ ["sylotinagri"] = { first = 0x0A800, last = 0x0A82F, otf="sylo", description = "Syloti Nagri" },
+ ["syriac"] = { first = 0x00700, last = 0x0074F, otf="syrc", description = "Syriac" },
+ ["tagalog"] = { first = 0x01700, last = 0x0171F, otf="tglg", description = "Tagalog" },
+ ["tagbanwa"] = { first = 0x01760, last = 0x0177F, otf="tagb", description = "Tagbanwa" },
+ ["tags"] = { first = 0xE0000, last = 0xE007F, description = "Tags" },
+ ["taile"] = { first = 0x01950, last = 0x0197F, otf="tale", description = "Tai Le" },
+ ["taitham"] = { first = 0x01A20, last = 0x01AAF, description = "Tai Tham" },
+ ["taiviet"] = { first = 0x0AA80, last = 0x0AADF, description = "Tai Viet" },
+ ["taixuanjingsymbols"] = { first = 0x1D300, last = 0x1D35F, description = "Tai Xuan Jing Symbols" },
+ ["takri"] = { first = 0x11680, last = 0x116CF, description = "Takri" },
+ ["tamil"] = { first = 0x00B80, last = 0x00BFF, otf="taml", description = "Tamil" },
+ ["telugu"] = { first = 0x00C00, last = 0x00C7F, otf="telu", description = "Telugu" },
+ ["thaana"] = { first = 0x00780, last = 0x007BF, otf="thaa", description = "Thaana" },
+ ["thai"] = { first = 0x00E00, last = 0x00E7F, otf="thai", description = "Thai" },
+ ["tibetan"] = { first = 0x00F00, last = 0x00FFF, otf="tibt", description = "Tibetan" },
+ ["tifinagh"] = { first = 0x02D30, last = 0x02D7F, otf="tfng", description = "Tifinagh" },
+ ["tirhuta"] = { first = 0x11480, last = 0x114DF, description = "Tirhuta" },
+ ["transportandmapsymbols"] = { first = 0x1F680, last = 0x1F6FF, description = "Transport and Map Symbols" },
+ ["ugaritic"] = { first = 0x10380, last = 0x1039F, otf="ugar", description = "Ugaritic" },
+ ["unifiedcanadianaboriginalsyllabics"] = { first = 0x01400, last = 0x0167F, otf="cans", description = "Unified Canadian Aboriginal Syllabics" },
+ ["unifiedcanadianaboriginalsyllabicsextended"] = { first = 0x018B0, last = 0x018FF, description = "Unified Canadian Aboriginal Syllabics Extended" },
+ ["uppercasebold"] = { first = 0x1D400, last = 0x1D419, math = true },
+ ["uppercaseboldfraktur"] = { first = 0x1D56C, last = 0x1D585, math = true },
+ ["uppercasebolditalic"] = { first = 0x1D468, last = 0x1D481, math = true },
+ ["uppercaseboldscript"] = { first = 0x1D4D0, last = 0x1D4E9, math = true },
+ ["uppercasedoublestruck"] = { first = 0x1D538, last = 0x1D551, math = true },
+ ["uppercasefraktur"] = { first = 0x1D504, last = 0x1D51D, math = true },
+ ["uppercasegreekbold"] = { first = 0x1D6A8, last = 0x1D6C1, math = true },
+ ["uppercasegreekbolditalic"] = { first = 0x1D71C, last = 0x1D735, math = true },
+ ["uppercasegreekitalic"] = { first = 0x1D6E2, last = 0x1D6FB, math = true },
+ ["uppercasegreeknormal"] = { first = 0x00391, last = 0x003AA, math = true },
+ ["uppercasegreeksansserifbold"] = { first = 0x1D756, last = 0x1D76F, math = true },
+ ["uppercasegreeksansserifbolditalic"] = { first = 0x1D790, last = 0x1D7A9, math = true },
+ ["uppercaseitalic"] = { first = 0x1D434, last = 0x1D44D, math = true },
+ ["uppercasemonospace"] = { first = 0x1D670, last = 0x1D689, math = true },
+ ["uppercasenormal"] = { first = 0x00041, last = 0x0005A, math = true },
+ ["uppercasesansserifbold"] = { first = 0x1D5D4, last = 0x1D5ED, math = true },
+ ["uppercasesansserifbolditalic"] = { first = 0x1D63C, last = 0x1D655, math = true },
+ ["uppercasesansserifitalic"] = { first = 0x1D608, last = 0x1D621, math = true },
+ ["uppercasesansserifnormal"] = { first = 0x1D5A0, last = 0x1D5B9, math = true },
+ ["uppercasescript"] = { first = 0x1D49C, last = 0x1D4B5, math = true },
+ ["vai"] = { first = 0x0A500, last = 0x0A63F, description = "Vai" },
+ ["variationselectors"] = { first = 0x0FE00, last = 0x0FE0F, description = "Variation Selectors" },
+ ["variationselectorssupplement"] = { first = 0xE0100, last = 0xE01EF, description = "Variation Selectors Supplement" },
+ ["vedicextensions"] = { first = 0x01CD0, last = 0x01CFF, description = "Vedic Extensions" },
+ ["verticalforms"] = { first = 0x0FE10, last = 0x0FE1F, description = "Vertical Forms" },
+ ["warangciti"] = { first = 0x118A0, last = 0x118FF, description = "Warang Citi" },
+ ["yijinghexagramsymbols"] = { first = 0x04DC0, last = 0x04DFF, otf="yi", description = "Yijing Hexagram Symbols" },
+ ["yiradicals"] = { first = 0x0A490, last = 0x0A4CF, otf="yi", description = "Yi Radicals" },
+ ["yisyllables"] = { first = 0x0A000, last = 0x0A48F, otf="yi", description = "Yi Syllables" },
+}
+
+characters.blocks = blocks
+
+function characters.blockrange(name)
+ local b = blocks[name]
+ if b then
+ return b.first, b.last
+ else
+ return 0, 0
+ end
+end
+
+setmetatableindex(blocks, function(t,k) -- we could use an intermediate table if called often
+ return k and rawget(t,lower(gsub(k,"[^a-zA-Z]","")))
+end)
+
+local otfscripts = utilities.storage.allocate()
+characters.otfscripts = otfscripts
+
+setmetatableindex(otfscripts,function(t,unicode)
+ for k, v in next, blocks do
+ local first, last = v.first, v.last
+ if unicode >= first and unicode <= last then
+ local script = v.otf or "dflt"
+ for u=first,last do
+ t[u] = script
+ end
+ return script
+ end
+ end
+ -- pretty slow when we're here
+ t[unicode] = "dflt"
+ return "dflt"
+end)
+
+local splitter = lpeg.splitat(S(":-"))
+
+function characters.getrange(name) -- used in font fallback definitions (name or range)
+ local range = blocks[name]
+ if range then
+ return range.first, range.last, range.description, range.gaps
+ end
+ name = gsub(name,'"',"0x") -- goodie: tex hex notation
+ local start, stop = lpegmatch(splitter,name)
+ if start and stop then
+ start, stop = tonumber(start,16) or tonumber(start), tonumber(stop,16) or tonumber(stop)
+ if start and stop then
+ return start, stop, nil
+ end
+ end
+ local slot = tonumber(name,16) or tonumber(name)
+ return slot, slot, nil
+end
+
+local categorytags = allocate {
+ lu = "Letter Uppercase",
+ ll = "Letter Lowercase",
+ lt = "Letter Titlecase",
+ lm = "Letter Modifier",
+ lo = "Letter Other",
+ mn = "Mark Nonspacing",
+ mc = "Mark Spacing Combining",
+ me = "Mark Enclosing",
+ nd = "Number Decimal Digit",
+ nl = "Number Letter",
+ no = "Number Other",
+ pc = "Punctuation Connector",
+ pd = "Punctuation Dash",
+ ps = "Punctuation Open",
+ pe = "Punctuation Close",
+ pi = "Punctuation Initial Quote",
+ pf = "Punctuation Final Quote",
+ po = "Punctuation Other",
+ sm = "Symbol Math",
+ sc = "Symbol Currency",
+ sk = "Symbol Modifier",
+ so = "Symbol Other",
+ zs = "Separator Space",
+ zl = "Separator Line",
+ zp = "Separator Paragraph",
+ cc = "Other Control",
+ cf = "Other Format",
+ cs = "Other Surrogate",
+ co = "Other Private Use",
+ cn = "Other Not Assigned",
+}
+
+local detailtags = allocate {
+ sl = "small letter",
+ bl = "big letter",
+ im = "iteration mark",
+ pm = "prolonged sound mark"
+}
+
+characters.categorytags = categorytags
+characters.detailtags = detailtags
+
+-- sounds : voiced unvoiced semivoiced
+
+--~ special : cf (softhyphen) zs (emspace)
+--~ characters: ll lm lo lt lu mn nl no pc pd pe pf pi po ps sc sk sm so
+
+local is_character = allocate ( tohash {
+ "lu","ll","lt","lm","lo",
+ "nd","nl","no",
+ "mn",
+ "nl","no",
+ "pc","pd","ps","pe","pi","pf","po",
+ "sm","sc","sk","so"
+} )
+
+local is_letter = allocate ( tohash {
+ "ll","lm","lo","lt","lu"
+} )
+
+local is_command = allocate ( tohash {
+ "cf","zs"
+} )
+
+local is_spacing = allocate ( tohash {
+ "zs", "zl","zp",
+} )
+
+local is_mark = allocate ( tohash {
+ "mn", "ms",
+} )
+
+local is_punctuation = allocate ( tohash {
+ "pc","pd","ps","pe","pi","pf","po",
+} )
+
+-- to be redone: store checked characters
+
+characters.is_character = is_character
+characters.is_letter = is_letter
+characters.is_command = is_command
+characters.is_spacing = is_spacing
+characters.is_mark = is_mark
+characters.is_punctuation = is_punctuation
+
+local mti = function(t,k)
+ if type(k) == "number" then
+ local c = data[k].category
+ return c and rawget(t,c)
+ else
+ -- avoid auto conversion in data.characters lookups
+ end
+end
+
+setmetatableindex(characters.is_character, mti)
+setmetatableindex(characters.is_letter, mti)
+setmetatableindex(characters.is_command, mti)
+setmetatableindex(characters.is_spacing, mti)
+setmetatableindex(characters.is_punctuation,mti)
+
+-- todo: also define callers for the above
+
+-- linebreak: todo: hash
+--
+-- normative : BK CR LF CM SG GL CB SP ZW NL WJ JL JV JT H2 H3
+-- informative : XX OP CL CP QU NS EX SY IS PR PO NU AL ID IN HY BB BA SA AI B2 HL CJ RI
+--
+-- comments taken from standard:
+
+characters.linebreaks = {
+
+ -- non-tailorable line breaking classes
+
+ ["bk"] = "mandatory break", -- nl, ps : cause a line break (after)
+ ["cr"] = "carriage return", -- cr : cause a line break (after), except between cr and lf
+ ["lf"] = "line feed", -- lf : cause a line break (after)
+ ["cm"] = "combining mark", -- combining marks, control codes : prohibit a line break between the character and the preceding character
+ ["nl"] = "next line", -- nel : cause a line break (after)
+ ["sg"] = "surrogate", -- surrogates :do not occur in well-formed text
+ ["wj"] = "word joiner", -- wj : prohibit line breaks before and after
+ ["zw"] = "zero width space", -- zwsp : provide a break opportunity
+ ["gl"] = "non-breaking (glue)", -- cgj, nbsp, zwnbsp : prohibit line breaks before and after
+ ["sp"] = "space", -- space : enable indirect line breaks
+
+ -- break opportunities
+
+ ["b2"] = "break opportunity before and after", -- em dash : provide a line break opportunity before and after the character
+ ["ba"] = "break after", -- spaces, hyphens : generally provide a line break opportunity after the character
+ ["bb"] = "break before", -- punctuation used in dictionaries : generally provide a line break opportunity before the character
+ ["hy"] = "hyphen", -- hyphen-minus : provide a line break opportunity after the character, except in numeric context
+ ["cb"] = "contingent break opportunity", -- inline objects : provide a line break opportunity contingent on additional information
+
+ -- characters prohibiting certain breaks
+
+ ["cl"] = "close punctuation", -- “}”, “❳”, “⟫” etc. : prohibit line breaks before
+ ["cp"] = "close parenthesis", -- “)”, “]” : prohibit line breaks before
+ ["ex"] = "exclamation/interrogation", -- “!”, “?”, etc. : prohibit line breaks before
+ ["in"] = "inseparable", -- leaders : allow only indirect line breaks between pairs
+ ["ns"] = "nonstarter", -- “‼”, “‽”, “⁇”, “⁉”, etc. : allow only indirect line breaks before
+ ["op"] = "open punctuation", -- “(“, “[“, “{“, etc. : prohibit line breaks after
+ ["qu"] = "quotation", -- quotation marks : act like they are both opening and closing
+
+ -- numeric context
+
+ ["is"] = "infix numeric separator", -- . , : prevent breaks after any and before numeric
+ ["nu"] = "numeric", -- digits : form numeric expressions for line breaking purposes
+ ["po"] = "postfix numeric", -- %, ¢ : do not break following a numeric expression
+ ["pr"] = "prefix numeric", -- $, £, ¥, etc. : do not break in front of a numeric expression
+ ["sy"] = "symbols allowing break after", -- / : prevent a break before, and allow a break after
+
+ -- other characters
+
+ ["ai"] = "ambiguous (alphabetic or ideographic)", -- characters with ambiguous east asian width : act like al when the resolved eaw is n; otherwise, act as id
+ ["al"] = "alphabetic", -- alphabets and regular symbols : are alphabetic characters or symbols that are used with alphabetic characters
+ ["cj"] = "conditional japanese starter", -- small kana : treat as ns or id for strict or normal breaking.
+ ["h2"] = "hangul lv syllable", -- hangul : form korean syllable blocks
+ ["h3"] = "hangul lvt syllable", -- hangul : form korean syllable blocks
+ ["hl"] = "hebrew letter", -- hebrew : do not break around a following hyphen; otherwise act as alphabetic
+ ["id"] = "ideographic", -- ideographs : break before or after, except in some numeric context
+ ["jl"] = "hangul l jamo", -- conjoining jamo : form korean syllable blocks
+ ["jv"] = "hangul v jamo", -- conjoining jamo : form korean syllable blocks
+ ["jt"] = "hangul t jamo", -- conjoining jamo : form korean syllable blocks
+ ["ri"] = "regional indicator", -- regional indicator symbol letter a .. z : keep together, break before and after from others
+ ["sa"] = "complex context dependent (south east asian)", -- south east asian: thai, lao, khmer : provide a line break opportunity contingent on additional, language-specific context analysis
+ ["xx"] = "unknown", -- most unassigned, private-use : have as yet unknown line breaking behavior or unassigned code positions
+
+}
+
+-- east asian width:
+--
+-- N A H W F Na
+
+characters.bidi = allocate {
+ l = "Left-to-Right",
+ lre = "Left-to-Right Embedding",
+ lro = "Left-to-Right Override",
+ r = "Right-to-Left",
+ al = "Right-to-Left Arabic",
+ rle = "Right-to-Left Embedding",
+ rlo = "Right-to-Left Override",
+ pdf = "Pop Directional Format",
+ en = "European Number",
+ es = "European Number Separator",
+ et = "European Number Terminator",
+ an = "Arabic Number",
+ cs = "Common Number Separator",
+ nsm = "Non-Spacing Mark",
+ bn = "Boundary Neutral",
+ b = "Paragraph Separator",
+ s = "Segment Separator",
+ ws = "Whitespace",
+ on = "Other Neutrals",
+}
+
+--[[ldx--
+<p>At this point we assume that the big data table is loaded. From this
+table we derive a few more.</p>
+--ldx]]--
+
+if not characters.fallbacks then
+
+ characters.fallbacks = {
+ [0x0308] = 0x00A8, [0x00A8] = 0x0308, -- dieresiscmb dieresis
+ [0x0304] = 0x00AF, [0x00AF] = 0x0304, -- macroncmb macron
+ [0x0301] = 0x00B4, [0x00B4] = 0x0301, -- acutecomb acute
+ [0x0327] = 0x00B8, [0x00B8] = 0x0327, -- cedillacmb cedilla
+ [0x0302] = 0x02C6, [0x02C6] = 0x0302, -- circumflexcmb circumflex
+ [0x030C] = 0x02C7, [0x02C7] = 0x030C, -- caroncmb caron
+ [0x0306] = 0x02D8, [0x02D8] = 0x0306, -- brevecmb breve
+ [0x0307] = 0x02D9, [0x02D9] = 0x0307, -- dotaccentcmb dotaccent
+ [0x030A] = 0x02DA, [0x02DA] = 0x030A, -- ringcmb ring
+ [0x0328] = 0x02DB, [0x02DB] = 0x0328, -- ogonekcmb ogonek
+ [0x0303] = 0x02DC, [0x02DC] = 0x0303, -- tildecomb tilde
+ [0x030B] = 0x02DD, [0x02DD] = 0x030B, -- hungarumlautcmb hungarumlaut
+ [0x0305] = 0x203E, [0x203E] = 0x0305, -- overlinecmb overline
+ [0x0300] = 0x0060, [0x0060] = 0x0333, -- gravecomb grave
+ }
+
+ -- not done (would mess up mapping):
+ --
+ -- 0X0301/0X0384 0X0314/0X1FFE 0X0313/0X1FBD 0X0313/0X1FBF 0X0342/0X1FC0
+ -- 0X3099/0X309B 0X309A/0X309C 0X0333/0X2017 0X0345/0X037A
+
+end
+
+if storage then
+ storage.register("characters/fallbacks", characters.fallbacks, "characters.fallbacks") -- accents and such
+end
+
+characters.directions = { }
+
+setmetatableindex(characters.directions,function(t,k)
+ local d = data[k]
+ if d then
+ local v = d.direction
+ if v then
+ t[k] = v
+ return v
+ end
+ end
+ t[k] = false -- maybe 'l'
+ return v
+end)
+
+characters.mirrors = { }
+
+setmetatableindex(characters.mirrors,function(t,k)
+ local d = data[k]
+ if d then
+ local v = d.mirror
+ if v then
+ t[k] = v
+ return v
+ end
+ end
+ t[k] = false
+ return v
+end)
+
+characters.textclasses = { }
+
+setmetatableindex(characters.textclasses,function(t,k)
+ local d = data[k]
+ if d then
+ local v = d.textclass
+ if v then
+ t[k] = v
+ return v
+ end
+ end
+ t[k] = false
+ return v
+end)
+
+--[[ldx--
+<p>Next comes a whole series of helper methods. These are (will be) part
+of the official <l n='api'/>.</p>
+--ldx]]--
+
+-- we could make them virtual: characters.contextnames[n]
+
+function characters.contextname(n) return data[n] and data[n].contextname or "" end
+function characters.adobename (n) return data[n] and data[n].adobename or "" end
+function characters.description(n) return data[n] and data[n].description or "" end
+-------- characters.category (n) return data[n] and data[n].category or "" end
+
+function characters.category(n,verbose)
+ local c = data[n].category
+ if not c then
+ return ""
+ elseif verbose then
+ return categorytags[c]
+ else
+ return c
+ end
+end
+
+-- -- some day we will make a table .. not that many calls to utfchar
+--
+-- local utfchar = utf.char
+-- local utfbyte = utf.byte
+-- local utfbytes = { }
+-- local utfchars = { }
+--
+-- table.setmetatableindex(utfbytes,function(t,k) local v = utfchar(k) t[k] = v return v end)
+-- table.setmetatableindex(utfchars,function(t,k) local v = utfbyte(k) t[k] = v return v end)
+
+local function toutfstring(s)
+ if type(s) == "table" then
+ return utfchar(unpack(s)) -- concat { utfchar( unpack(s) ) }
+ else
+ return utfchar(s)
+ end
+end
+
+utf.tostring = toutfstring
+
+local categories = allocate() characters.categories = categories -- lazy table
+
+setmetatableindex(categories, function(t,u) if u then local c = data[u] c = c and c.category or u t[u] = c return c end end)
+
+-- todo: overloads (these register directly in the tables as number and string) e.g. for greek
+-- todo: for string do a numeric lookup in the table itself
+
+local lccodes = allocate() characters.lccodes = lccodes -- lazy table
+local uccodes = allocate() characters.uccodes = uccodes -- lazy table
+local shcodes = allocate() characters.shcodes = shcodes -- lazy table
+local fscodes = allocate() characters.fscodes = fscodes -- lazy table
+
+setmetatableindex(lccodes, function(t,u) if u then local c = data[u] c = c and c.lccode or (type(u) == "string" and utfbyte(u)) or u t[u] = c return c end end)
+setmetatableindex(uccodes, function(t,u) if u then local c = data[u] c = c and c.uccode or (type(u) == "string" and utfbyte(u)) or u t[u] = c return c end end)
+setmetatableindex(shcodes, function(t,u) if u then local c = data[u] c = c and c.shcode or (type(u) == "string" and utfbyte(u)) or u t[u] = c return c end end)
+setmetatableindex(fscodes, function(t,u) if u then local c = data[u] c = c and c.fscode or (type(u) == "string" and utfbyte(u)) or u t[u] = c return c end end)
+
+local lcchars = allocate() characters.lcchars = lcchars -- lazy table
+local ucchars = allocate() characters.ucchars = ucchars -- lazy table
+local shchars = allocate() characters.shchars = shchars -- lazy table
+local fschars = allocate() characters.fschars = fschars -- lazy table
+
+setmetatableindex(lcchars, function(t,u) if u then local c = data[u] c = c and c.lccode c = c and toutfstring(c) or (type(u) == "number" and utfchar(u)) or u t[u] = c return c end end)
+setmetatableindex(ucchars, function(t,u) if u then local c = data[u] c = c and c.uccode c = c and toutfstring(c) or (type(u) == "number" and utfchar(u)) or u t[u] = c return c end end)
+setmetatableindex(shchars, function(t,u) if u then local c = data[u] c = c and c.shcode c = c and toutfstring(c) or (type(u) == "number" and utfchar(u)) or u t[u] = c return c end end)
+setmetatableindex(fschars, function(t,u) if u then local c = data[u] c = c and c.fscode c = c and toutfstring(c) or (type(u) == "number" and utfchar(u)) or u t[u] = c return c end end)
+
+local decomposed = allocate() characters.decomposed = decomposed -- lazy table
+local specials = allocate() characters.specials = specials -- lazy table
+
+setmetatableindex(decomposed, function(t,u) -- either a table or false
+ if u then
+ local c = data[u]
+ local s = c and c.decomposed or false -- could fall back to specials
+ t[u] = s
+ return s
+ end
+end)
+
+setmetatableindex(specials, function(t,u) -- either a table or false
+ if u then
+ local c = data[u]
+ local s = c and c.specials or false
+ t[u] = s
+ return s
+ end
+end)
+
+local specialchars = allocate() characters.specialchars = specialchars -- lazy table
+local descriptions = allocate() characters.descriptions = descriptions -- lazy table
+
+setmetatableindex(specialchars, function(t,u)
+ if u then
+ local c = data[u]
+ local s = c and c.specials
+ if s then
+ local tt, ttn = { }, 0
+ for i=2,#s do
+ local si = s[i]
+ local c = data[si]
+ if is_letter[c.category] then
+ ttn = ttn + 1
+ tt[ttn] = utfchar(si)
+ end
+ end
+ c = concat(tt)
+ t[u] = c
+ return c
+ else
+ if type(u) == "number" then
+ u = utfchar(u)
+ end
+ t[u] = u
+ return u
+ end
+ end
+end)
+
+setmetatableindex(descriptions, function(t,k)
+ -- 0.05 - 0.10 sec
+ for u, c in next, data do
+ local d = c.description
+ if d then
+ d = gsub(d," ","")
+ d = lower(d)
+ t[d] = u
+ end
+ end
+ local d = rawget(t,k)
+ if not d then
+ t[k] = k
+ end
+ return d
+end)
+
+function characters.unicodechar(asked)
+ local n = tonumber(asked)
+ if n then
+ return n
+ elseif type(asked) == "string" then
+ return descriptions[asked] or descriptions[gsub(asked," ","")]
+ end
+end
+
+-- function characters.lower(str)
+-- local new, n = { }, 0
+-- for u in utfvalues(str) do
+-- n = n + 1
+-- new[n] = lcchars[u]
+-- end
+-- return concat(new)
+-- end
+--
+-- function characters.upper(str)
+-- local new, n = { }, 0
+-- for u in utfvalues(str) do
+-- n = n + 1
+-- new[n] = ucchars[u]
+-- end
+-- return concat(new)
+-- end
+--
+-- function characters.shaped(str)
+-- local new, n = { }, 0
+-- for u in utfvalues(str) do
+-- n = n + 1
+-- new[n] = shchars[u]
+-- end
+-- return concat(new)
+-- end
+
+----- tolower = Cs((utf8byte/lcchars)^0)
+----- toupper = Cs((utf8byte/ucchars)^0)
+----- toshape = Cs((utf8byte/shchars)^0)
+
+local tolower = Cs((utf8character/lcchars)^0) -- no need to check spacing
+local toupper = Cs((utf8character/ucchars)^0) -- no need to check spacing
+local toshape = Cs((utf8character/shchars)^0) -- no need to check spacing
+
+lpegpatterns.tolower = tolower -- old ones ... will be overloaded
+lpegpatterns.toupper = toupper -- old ones ... will be overloaded
+lpegpatterns.toshape = toshape -- old ones ... will be overloaded
+
+-- function characters.lower (str) return lpegmatch(tolower,str) end
+-- function characters.upper (str) return lpegmatch(toupper,str) end
+-- function characters.shaped(str) return lpegmatch(toshape,str) end
+
+-- local superscripts = allocate() characters.superscripts = superscripts
+-- local subscripts = allocate() characters.subscripts = subscripts
+
+-- if storage then
+-- storage.register("characters/superscripts", superscripts, "characters.superscripts")
+-- storage.register("characters/subscripts", subscripts, "characters.subscripts")
+-- end
+
+-- end
+
+if not characters.splits then
+
+ local char = allocate()
+ local compat = allocate()
+
+ local splits = {
+ char = char,
+ compat = compat,
+ }
+
+ characters.splits = splits
+
+ -- [0x013F] = { 0x004C, 0x00B7 }
+ -- [0x0140] = { 0x006C, 0x00B7 }
+
+ for unicode, data in next, characters.data do
+ local specials = data.specials
+ if specials and #specials > 2 then
+ local kind = specials[1]
+ if kind == "compat" then
+ compat[unicode] = { unpack(specials,2) }
+ elseif kind == "char" then
+ char [unicode] = { unpack(specials,2) }
+ end
+ end
+ end
+
+ if storage then
+ storage.register("characters/splits", splits, "characters.splits")
+ end
+
+end
+
+if not characters.lhash then
+
+ local lhash = allocate() characters.lhash = lhash -- nil if no conversion
+ local uhash = allocate() characters.uhash = uhash -- nil if no conversion
+ local shash = allocate() characters.shash = shash -- nil if no conversion
+
+ for k, v in next, characters.data do
+ -- if k < 0x11000 then
+ local l = v.lccode
+ if l then
+ -- we have an uppercase
+ if type(l) == "number" then
+ lhash[utfchar(k)] = utfchar(l)
+ elseif #l == 2 then
+ lhash[utfchar(k)] = utfchar(l[1]) .. utfchar(l[2])
+ else
+ inspect(v)
+ end
+ else
+ local u = v.uccode
+ if u then
+ -- we have an lowercase
+ if type(u) == "number" then
+ uhash[utfchar(k)] = utfchar(u)
+ elseif #u == 2 then
+ uhash[utfchar(k)] = utfchar(u[1]) .. utfchar(u[2])
+ else
+ inspect(v)
+ end
+ end
+ end
+ local s = v.shcode
+ if s then
+ if type(s) == "number" then
+ shash[utfchar(k)] = utfchar(s)
+ elseif #s == 2 then
+ shash[utfchar(k)] = utfchar(s[1]) .. utfchar(s[2])
+ else
+ inspect(v)
+ end
+ end
+ -- end
+ end
+
+ if storage then
+ storage.register("characters/lhash", lhash, "characters.lhash")
+ storage.register("characters/uhash", uhash, "characters.uhash")
+ storage.register("characters/shash", shash, "characters.shash")
+ end
+
+end
+
+local lhash = characters.lhash mark(lhash)
+local uhash = characters.uhash mark(uhash)
+local shash = characters.shash mark(shash)
+
+local utf8lowercharacter = utfchartabletopattern(lhash) / lhash
+local utf8uppercharacter = utfchartabletopattern(uhash) / uhash
+local utf8shapecharacter = utfchartabletopattern(shash) / shash
+
+local utf8lower = Cs((utf8lowercharacter + utf8character)^0)
+local utf8upper = Cs((utf8uppercharacter + utf8character)^0)
+local utf8shape = Cs((utf8shapecharacter + utf8character)^0)
+
+lpegpatterns.utf8lowercharacter = utf8lowercharacter -- one character
+lpegpatterns.utf8uppercharacter = utf8uppercharacter -- one character
+lpegpatterns.utf8shapecharacter = utf8shapecharacter -- one character
+
+lpegpatterns.utf8lower = utf8lower -- string
+lpegpatterns.utf8upper = utf8upper -- string
+lpegpatterns.utf8shape = utf8shape -- string
+
+function characters.lower (str) return lpegmatch(utf8lower,str) end
+function characters.upper (str) return lpegmatch(utf8upper,str) end
+function characters.shaped(str) return lpegmatch(utf8shape,str) end
+
+-- local str = [[
+-- ÀÁÂÃÄÅàáâãäå àáâãäåàáâãäå ÀÁÂÃÄÅÀÁÂÃÄÅ AAAAAAaaaaaa
+-- ÆÇæç æçæç ÆÇÆÇ AECaec
+-- ÈÉÊËèéêë èéêëèéêë ÈÉÊËÈÉÊË EEEEeeee
+-- ÌÍÎÏÞìíîïþ ìíîïþìíîïþ ÌÍÎÏÞÌÍÎÏÞ IIIIÞiiiiþ
+-- Ðð ðð ÐÐ Ðð
+-- Ññ ññ ÑÑ Nn
+-- ÒÓÔÕÖòóôõö òóôõöòóôõö ÒÓÔÕÖÒÓÔÕÖ OOOOOooooo
+-- Øø øø ØØ Oo
+-- ÙÚÛÜùúûü ùúûüùúûü ÙÚÛÜÙÚÛÜ UUUUuuuu
+-- Ýýÿ ýýÿ ÝÝŸ Yyy
+-- ß ß SS ss
+-- Ţţ ţţ ŢŢ Tt
+-- ]]
+--
+-- local lower = characters.lower print(lower(str))
+-- local upper = characters.upper print(upper(str))
+-- local shaped = characters.shaped print(shaped(str))
+--
+-- local c, n = os.clock(), 10000
+-- for i=1,n do lower(str) upper(str) shaped(str) end -- 2.08 => 0.77
+-- print(os.clock()-c,n*#str*3)
+
+-- maybe: (twice as fast when much ascii)
+--
+-- local tolower = lpeg.patterns.tolower
+-- local lower = string.lower
+--
+-- local allascii = R("\000\127")^1 * P(-1)
+--
+-- function characters.checkedlower(str)
+-- return lpegmatch(allascii,str) and lower(str) or lpegmatch(tolower,str) or str
+-- end
+
+function characters.lettered(str,spacing)
+ local new, n = { }, 0
+ if spacing then
+ local done = false
+ for u in utfvalues(str) do
+ local c = data[u].category
+ if is_letter[c] then
+ if done and n > 1 then
+ n = n + 1
+ new[n] = " "
+ done = false
+ end
+ n = n + 1
+ new[n] = utfchar(u)
+ elseif spacing and is_spacing[c] then
+ done = true
+ end
+ end
+ else
+ for u in utfvalues(str) do
+ if is_letter[data[u].category] then
+ n = n + 1
+ new[n] = utfchar(u)
+ end
+ end
+ end
+ return concat(new)
+end
+
+--[[ldx--
+<p>Requesting lower and uppercase codes:</p>
+--ldx]]--
+
+function characters.uccode(n) return uccodes[n] end -- obsolete
+function characters.lccode(n) return lccodes[n] end -- obsolete
+
+function characters.shape(n)
+ local shcode = shcodes[n]
+ if not shcode then
+ return n, nil
+ elseif type(shcode) == "table" then
+ return shcode[1], shcode[#shcode]
+ else
+ return shcode, nil
+ end
+end
+
+-- -- some day we might go this route, but it does not really save that much
+-- -- so not now (we can generate a lot using mtx-unicode that operates on the
+-- -- database)
+--
+-- -- category cjkwd direction linebreak
+--
+-- -- adobename comment contextcommand contextname description fallback lccode
+-- -- mathclass mathfiller mathname mathspec mathstretch mathsymbol mirror
+-- -- range shcode specials uccode uccodes unicodeslot
+--
+-- local data = {
+-- ['one']={
+-- common = {
+-- category="cc",
+-- direction="bn",
+-- linebreak="cm",
+-- },
+-- vector = {
+-- [0x0000] = {
+-- description="NULL",
+-- group='one',
+-- unicodeslot=0x0000,
+-- },
+-- {
+-- description="START OF HEADING",
+-- group='one',
+-- unicodeslot=0x0001,
+-- },
+-- }
+-- }
+-- }
+--
+-- local chardata, groupdata = { }, { }
+--
+-- for group, gdata in next, data do
+-- local common, vector = { __index = gdata.common }, gdata.vector
+-- for character, cdata in next, vector do
+-- chardata[character] = cdata
+-- setmetatable(cdata,common)
+-- end
+-- groupdata[group] = gdata
+-- end
+
+-- characters.data, characters.groups = chardata, groupdata
+
+-- [0xF0000]={
+-- category="co",
+-- cjkwd="a",
+-- description="<Plane 0x000F Private Use, First>",
+-- direction="l",
+-- unicodeslot=0xF0000,
+-- },
+-- [0xFFFFD]={
+-- category="co",
+-- cjkwd="a",
+-- description="<Plane 0x000F Private Use, Last>",
+-- direction="l",
+-- unicodeslot=0xFFFFD,
+-- },
+-- [0x100000]={
+-- category="co",
+-- cjkwd="a",
+-- description="<Plane 0x0010 Private Use, First>",
+-- direction="l",
+-- unicodeslot=0x100000,
+-- },
+-- [0x10FFFD]={
+-- category="co",
+-- cjkwd="a",
+-- description="<Plane 0x0010 Private Use, Last>",
+-- direction="l",
+-- unicodeslot=0x10FFFD,
+-- },
+
+if not characters.superscripts then
+
+ local superscripts = allocate() characters.superscripts = superscripts
+ local subscripts = allocate() characters.subscripts = subscripts
+ local fractions = allocate() characters.fractions = fractions
+
+ -- skipping U+02120 (service mark) U+02122 (trademark)
+
+ for k, v in next, data do
+ local specials = v.specials
+ if specials then
+ local what = specials[1]
+ if what == "super" then
+ if #specials == 2 then
+ superscripts[k] = specials[2]
+ elseif trace_defining then
+ report_defining("ignoring %s %a, char %c, description %a","superscript",ustring(k),k,v.description)
+ end
+ elseif what == "sub" then
+ if #specials == 2 then
+ subscripts[k] = specials[2]
+ elseif trace_defining then
+ report_defining("ignoring %s %a, char %c, description %a","subscript",ustring(k),k,v.description)
+ end
+ elseif what == "fraction" then
+ if #specials > 1 then
+ fractions[k] = { unpack(specials,2) }
+ elseif trace_defining then
+ report_defining("ignoring %s %a, char %c, description %a","fraction",ustring(k),k,v.description)
+ end
+ end
+ end
+ end
+
+ -- print(table.serialize(superscripts, "superscripts", { hexify = true }))
+ -- print(table.serialize(subscripts, "subscripts", { hexify = true }))
+ -- print(table.serialize(fractions, "fractions", { hexify = true }))
+
+ if storage then
+ storage.register("characters/superscripts", superscripts, "characters.superscripts")
+ storage.register("characters/subscripts", subscripts, "characters.subscripts")
+ storage.register("characters/fractions", fractions, "characters.fractions")
+ end
+
+end
+
+function characters.showstring(str)
+ local list = utotable(str)
+ for i=1,#list do
+ report_defining("split % 3i : %C",i,list[i])
+ end
+end
+
+-- code moved to char-tex.lua
+
+return characters
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-cff.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-cff.lua
new file mode 100644
index 00000000000..0314e4ac4a1
--- /dev/null
+++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-cff.lua
@@ -0,0 +1,1697 @@
+if not modules then modules = { } end modules ['font-cff'] = {
+ version = 1.001,
+ comment = "companion to font-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- todo: option.outlines
+-- todo: option.boundingbox
+-- per charstring (less memory)
+
+-- This is a heavy one as it is a rather packed format. We don't need al the information
+-- now but we might need it later (who know what magic we can do with metapost). So at
+-- some point this might become a module. We just follow Adobe Technical Notes #5176 and
+-- #5177. In case of doubt I looked in the fontforge code that comes with LuaTeX.
+
+-- For now we save the segments in a list of segments with the operator last in an entry
+-- because that reflects the original. But it might make more sense to use a single array
+-- per segment. For pdf a simple concat works ok, but for other purposes a operator first
+-- flush is nicer.
+
+local next, type, tonumber = next, type, tonumber
+local byte = string.byte
+local concat, remove = table.concat, table.remove
+local floor, abs, round, ceil = math.floor, math.abs, math.round, math.ceil
+local P, C, R, S, C, Cs, Ct = lpeg.P, lpeg.C, lpeg.R, lpeg.S, lpeg.C, lpeg.Cs, lpeg.Ct
+local lpegmatch = lpeg.match
+
+local readers = fonts.handlers.otf.readers
+local streamreader = readers.streamreader
+
+local readbytes = streamreader.readbytes
+local readstring = streamreader.readstring
+local readbyte = streamreader.readcardinal1 -- 8-bit unsigned integer
+local readushort = streamreader.readcardinal2 -- 16-bit unsigned integer
+local readuint = streamreader.readcardinal3 -- 24-bit unsigned integer
+local readulong = streamreader.readcardinal4 -- 24-bit unsigned integer
+local setposition = streamreader.setposition
+local getposition = streamreader.getposition
+
+local setmetatableindex = table.setmetatableindex
+
+local trace_charstrings = false trackers.register("fonts.cff.charstrings",function(v) trace_charstrings = v end)
+local report = logs.reporter("otf reader","cff")
+
+local parsedictionaries
+local parsecharstring
+local parsecharstrings
+local resetcharstrings
+local parseprivates
+
+local defaultstrings = { [0] = -- taken from ff
+ ".notdef", "space", "exclam", "quotedbl", "numbersign", "dollar", "percent",
+ "ampersand", "quoteright", "parenleft", "parenright", "asterisk", "plus",
+ "comma", "hyphen", "period", "slash", "zero", "one", "two", "three", "four",
+ "five", "six", "seven", "eight", "nine", "colon", "semicolon", "less",
+ "equal", "greater", "question", "at", "A", "B", "C", "D", "E", "F", "G", "H",
+ "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W",
+ "X", "Y", "Z", "bracketleft", "backslash", "bracketright", "asciicircum",
+ "underscore", "quoteleft", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j",
+ "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y",
+ "z", "braceleft", "bar", "braceright", "asciitilde", "exclamdown", "cent",
+ "sterling", "fraction", "yen", "florin", "section", "currency",
+ "quotesingle", "quotedblleft", "guillemotleft", "guilsinglleft",
+ "guilsinglright", "fi", "fl", "endash", "dagger", "daggerdbl",
+ "periodcentered", "paragraph", "bullet", "quotesinglbase", "quotedblbase",
+ "quotedblright", "guillemotright", "ellipsis", "perthousand", "questiondown",
+ "grave", "acute", "circumflex", "tilde", "macron", "breve", "dotaccent",
+ "dieresis", "ring", "cedilla", "hungarumlaut", "ogonek", "caron", "emdash",
+ "AE", "ordfeminine", "Lslash", "Oslash", "OE", "ordmasculine", "ae",
+ "dotlessi", "lslash", "oslash", "oe", "germandbls", "onesuperior",
+ "logicalnot", "mu", "trademark", "Eth", "onehalf", "plusminus", "Thorn",
+ "onequarter", "divide", "brokenbar", "degree", "thorn", "threequarters",
+ "twosuperior", "registered", "minus", "eth", "multiply", "threesuperior",
+ "copyright", "Aacute", "Acircumflex", "Adieresis", "Agrave", "Aring",
+ "Atilde", "Ccedilla", "Eacute", "Ecircumflex", "Edieresis", "Egrave",
+ "Iacute", "Icircumflex", "Idieresis", "Igrave", "Ntilde", "Oacute",
+ "Ocircumflex", "Odieresis", "Ograve", "Otilde", "Scaron", "Uacute",
+ "Ucircumflex", "Udieresis", "Ugrave", "Yacute", "Ydieresis", "Zcaron",
+ "aacute", "acircumflex", "adieresis", "agrave", "aring", "atilde",
+ "ccedilla", "eacute", "ecircumflex", "edieresis", "egrave", "iacute",
+ "icircumflex", "idieresis", "igrave", "ntilde", "oacute", "ocircumflex",
+ "odieresis", "ograve", "otilde", "scaron", "uacute", "ucircumflex",
+ "udieresis", "ugrave", "yacute", "ydieresis", "zcaron", "exclamsmall",
+ "Hungarumlautsmall", "dollaroldstyle", "dollarsuperior", "ampersandsmall",
+ "Acutesmall", "parenleftsuperior", "parenrightsuperior", "twodotenleader",
+ "onedotenleader", "zerooldstyle", "oneoldstyle", "twooldstyle",
+ "threeoldstyle", "fouroldstyle", "fiveoldstyle", "sixoldstyle",
+ "sevenoldstyle", "eightoldstyle", "nineoldstyle", "commasuperior",
+ "threequartersemdash", "periodsuperior", "questionsmall", "asuperior",
+ "bsuperior", "centsuperior", "dsuperior", "esuperior", "isuperior",
+ "lsuperior", "msuperior", "nsuperior", "osuperior", "rsuperior", "ssuperior",
+ "tsuperior", "ff", "ffi", "ffl", "parenleftinferior", "parenrightinferior",
+ "Circumflexsmall", "hyphensuperior", "Gravesmall", "Asmall", "Bsmall",
+ "Csmall", "Dsmall", "Esmall", "Fsmall", "Gsmall", "Hsmall", "Ismall",
+ "Jsmall", "Ksmall", "Lsmall", "Msmall", "Nsmall", "Osmall", "Psmall",
+ "Qsmall", "Rsmall", "Ssmall", "Tsmall", "Usmall", "Vsmall", "Wsmall",
+ "Xsmall", "Ysmall", "Zsmall", "colonmonetary", "onefitted", "rupiah",
+ "Tildesmall", "exclamdownsmall", "centoldstyle", "Lslashsmall",
+ "Scaronsmall", "Zcaronsmall", "Dieresissmall", "Brevesmall", "Caronsmall",
+ "Dotaccentsmall", "Macronsmall", "figuredash", "hypheninferior",
+ "Ogoneksmall", "Ringsmall", "Cedillasmall", "questiondownsmall", "oneeighth",
+ "threeeighths", "fiveeighths", "seveneighths", "onethird", "twothirds",
+ "zerosuperior", "foursuperior", "fivesuperior", "sixsuperior",
+ "sevensuperior", "eightsuperior", "ninesuperior", "zeroinferior",
+ "oneinferior", "twoinferior", "threeinferior", "fourinferior",
+ "fiveinferior", "sixinferior", "seveninferior", "eightinferior",
+ "nineinferior", "centinferior", "dollarinferior", "periodinferior",
+ "commainferior", "Agravesmall", "Aacutesmall", "Acircumflexsmall",
+ "Atildesmall", "Adieresissmall", "Aringsmall", "AEsmall", "Ccedillasmall",
+ "Egravesmall", "Eacutesmall", "Ecircumflexsmall", "Edieresissmall",
+ "Igravesmall", "Iacutesmall", "Icircumflexsmall", "Idieresissmall",
+ "Ethsmall", "Ntildesmall", "Ogravesmall", "Oacutesmall", "Ocircumflexsmall",
+ "Otildesmall", "Odieresissmall", "OEsmall", "Oslashsmall", "Ugravesmall",
+ "Uacutesmall", "Ucircumflexsmall", "Udieresissmall", "Yacutesmall",
+ "Thornsmall", "Ydieresissmall", "001.000", "001.001", "001.002", "001.003",
+ "Black", "Bold", "Book", "Light", "Medium", "Regular", "Roman", "Semibold",
+}
+
+local cffreaders = {
+ readbyte,
+ readushort,
+ readuint,
+ readulong,
+}
+
+-- The header contains information about its own size.
+
+local function readheader(f)
+ local offset = getposition(f)
+ local header = {
+ offset = offset,
+ major = readbyte(f),
+ minor = readbyte(f),
+ size = readbyte(f), -- headersize
+ osize = readbyte(f), -- for offsets to start
+ }
+ setposition(f,offset+header.size)
+ return header
+end
+
+-- The indexes all look the same, so we share a loader. We could pass a handler
+-- and run over the array but why bother, we only have a few uses.
+
+local function readlengths(f)
+ local count = readushort(f)
+ if count == 0 then
+ return { }
+ end
+ local osize = readbyte(f)
+ local read = cffreaders[osize]
+ if not read then
+ report("bad offset size: %i",osize)
+ return { }
+ end
+ local lengths = { }
+ local previous = read(f)
+ for i=1,count do
+ local offset = read(f)
+ lengths[i] = offset - previous
+ previous = offset
+ end
+ return lengths
+end
+
+-- There can be subfonts so names is an array. However, in our case it's always
+-- one font. The same is true for the top dictionaries. Watch how we only load
+-- the dictionary string as for interpretation we need to have the strings loaded
+-- as well.
+
+local function readfontnames(f)
+ local names = readlengths(f)
+ for i=1,#names do
+ names[i] = readstring(f,names[i])
+ end
+ return names
+end
+
+local function readtopdictionaries(f)
+ local dictionaries = readlengths(f)
+ for i=1,#dictionaries do
+ dictionaries[i] = readstring(f,dictionaries[i])
+ end
+ return dictionaries
+end
+
+-- Strings are added to a list of standard strings so we start the font specific
+-- one with an offset. Strings are shared so we have one table.
+
+local function readstrings(f)
+ local lengths = readlengths(f)
+ local strings = setmetatableindex({ }, defaultstrings)
+ local index = #defaultstrings
+ for i=1,#lengths do
+ index = index + 1
+ strings[index] = readstring(f,lengths[i])
+ end
+ return strings
+end
+
+-- Parsing the dictionaries is delayed till we have the strings loaded. The parser
+-- is stack based so the operands come before the operator (like in postscript).
+
+-- local function delta(t)
+-- local n = #t
+-- if n > 1 then
+-- local p = t[1]
+-- for i=2,n do
+-- local c = t[i]
+-- t[i] = c + p
+-- p = c
+-- end
+-- end
+-- end
+
+do
+
+ -- We use a closure so that we don't need to pass too much around.
+
+ local stack = { }
+ local top = 0
+ local result = { }
+ local strings = { }
+
+ local p_single =
+ P("\00") / function()
+ result.version = strings[stack[top]] or "unset"
+ top = 0
+ end
+ + P("\01") / function()
+ result.notice = strings[stack[top]] or "unset"
+ top = 0
+ end
+ + P("\02") / function()
+ result.fullname = strings[stack[top]] or "unset"
+ top = 0
+ end
+ + P("\03") / function()
+ result.familyname = strings[stack[top]] or "unset"
+ top = 0
+ end
+ + P("\04") / function()
+ result.weight = strings[stack[top]] or "unset"
+ top = 0
+ end
+ + P("\05") / function()
+ result.fontbbox = { unpack(stack,1,4) }
+ top = 0
+ end
+ -- + P("\06") / function() end -- bluevalues
+ -- + P("\07") / function() end -- otherblues
+ -- + P("\08") / function() end -- familyblues
+ -- + P("\09") / function() end -- familyotherblues
+ -- + P("\10") / function() end -- strhw
+ -- + P("\11") / function() end -- stdvw
+ + P("\13") / function()
+ result.uniqueid = stack[top]
+ top = 0
+ end
+ + P("\14") / function()
+ result.xuid = concat(stack,"",1,top)
+ top = 0
+ end
+ + P("\15") / function()
+ result.charset = stack[top]
+ top = 0
+ end
+ + P("\16") / function()
+ result.encoding = stack[top]
+ top = 0
+ end
+ + P("\17") / function()
+ result.charstrings = stack[top]
+ top = 0
+ end
+ + P("\18") / function()
+ result.private = {
+ size = stack[top-1],
+ offset = stack[top],
+ }
+ top = 0
+ end
+ + P("\19") / function()
+ result.subroutines = stack[top]
+ end
+ + P("\20") / function()
+ result.defaultwidthx = stack[top]
+ end
+ + P("\21") / function()
+ result.nominalwidthx = stack[top]
+ end
+ -- + P("\22") / function() end -- reserved
+ -- + P("\23") / function() end -- reserved
+ -- + P("\24") / function() end -- reserved
+ -- + P("\25") / function() end -- reserved
+ -- + P("\26") / function() end -- reserved
+ -- + P("\27") / function() end -- reserved
+
+ local p_double = P("\12") * (
+ P("\00") / function()
+ result.copyright = stack[top]
+ top = 0
+ end
+ + P("\01") / function()
+ result.monospaced = stack[top] == 1 and true or false -- isfixedpitch
+ top = 0
+ end
+ + P("\02") / function()
+ result.italicangle = stack[top]
+ top = 0
+ end
+ + P("\03") / function()
+ result.underlineposition = stack[top]
+ top = 0
+ end
+ + P("\04") / function()
+ result.underlinethickness = stack[top]
+ top = 0
+ end
+ + P("\05") / function()
+ result.painttype = stack[top]
+ top = 0
+ end
+ + P("\06") / function()
+ result.charstringtype = stack[top]
+ top = 0
+ end
+ + P("\07") / function()
+ result.fontmatrix = { unpack(stack,1,6) }
+ top = 0
+ end
+ + P("\08") / function()
+ result.strokewidth = stack[top]
+ top = 0
+ end
+ + P("\20") / function()
+ result.syntheticbase = stack[top]
+ top = 0
+ end
+ + P("\21") / function()
+ result.postscript = strings[stack[top]] or "unset"
+ top = 0
+ end
+ + P("\22") / function()
+ result.basefontname = strings[stack[top]] or "unset"
+ top = 0
+ end
+ + P("\21") / function()
+ result.basefontblend = stack[top]
+ top = 0
+ end
+ + P("\30") / function()
+ result.cid.registry = strings[stack[top-2]] or "unset"
+ result.cid.ordering = strings[stack[top-1]] or "unset"
+ result.cid.supplement = stack[top]
+ top = 0
+ end
+ + P("\31") / function()
+ result.cid.fontversion = stack[top]
+ top = 0
+ end
+ + P("\32") / function()
+ result.cid.fontrevision= stack[top]
+ top = 0
+ end
+ + P("\33") / function()
+ result.cid.fonttype = stack[top]
+ top = 0
+ end
+ + P("\34") / function()
+ result.cid.count = stack[top]
+ top = 0
+ end
+ + P("\35") / function()
+ result.cid.uidbase = stack[top]
+ top = 0
+ end
+ + P("\36") / function()
+ result.cid.fdarray = stack[top]
+ top = 0
+ end
+ + P("\37") / function()
+ result.cid.fdselect = stack[top]
+ top = 0
+ end
+ + P("\38") / function()
+ result.cid.fontname = strings[stack[top]] or "unset"
+ top = 0
+ end
+ )
+
+ -- Some lpeg fun ... a first variant split the byte and made a new string but
+ -- the second variant is much faster. Not that it matters much as we don't see
+ -- such numbers often.
+
+ local p_last = P("\x0F") / "0" + P("\x1F") / "1" + P("\x2F") / "2" + P("\x3F") / "3"
+ + P("\x4F") / "4" + P("\x5F") / "5" + P("\x6F") / "6" + P("\x7F") / "7"
+ + P("\x8F") / "8" + P("\x9F") / "9" + P("\xAF") / "" + P("\xBF") / ""
+ + P("\xCF") / "" + P("\xDF") / "" + P("\xEF") / "" + R("\xF0\xFF") / ""
+
+ -- local remap = { [0] =
+ -- "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0.", "0E", "0E-", "0", "0-", "0",
+ -- "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "0.", "0E", "0E-", "0", "0-", "0",
+ -- "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "0.", "0E", "0E-", "0", "0-", "0",
+ -- "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "0.", "0E", "0E-", "0", "0-", "0",
+ -- "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "0.", "0E", "0E-", "0", "0-", "0",
+ -- "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "0.", "0E", "0E-", "0", "0-", "0",
+ -- "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "0.", "0E", "0E-", "0", "0-", "0",
+ -- "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "0.", "0E", "0E-", "0", "0-", "0",
+ -- "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "0.", "0E", "0E-", "0", "0-", "0",
+ -- "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "0.", "0E", "0E-", "0", "0-", "0",
+ -- ".0", ".1", ".2", ".3", ".4", ".5", ".6", ".7", ".8", ".9", "..", ".E", ".E-", ".", ".-", ".",
+ -- "E0", "E1", "E2", "E3", "E4", "E5", "E6", "E7", "E8", "E9", "E.", "EE", "EE-", "E", "E-", "E",
+ -- "E-0", "E-1", "E-2", "E-3", "E-4", "E-5", "E-6", "E-7", "E-8", "E-9", "E-.", "E-E", "E-E-", "E-", "E--", "E-",
+ -- "-0", "-1", "-2", "-3", "-4", "-5", "-6", "-7", "-8", "-9", "-.", "-E", "-E-", "-", "--", "-",
+ -- }
+
+ -- local p_nibbles = Cs(((1-p_last)/byte/remap)^0+p_last)
+
+ -- local p = P("\30") * p_nibbles / function(t)
+ -- print(tonumber(t))
+ -- end
+
+ local remap = {
+ ["\x00"] = "00", ["\x01"] = "01", ["\x02"] = "02", ["\x03"] = "03", ["\x04"] = "04", ["\x05"] = "05", ["\x06"] = "06", ["\x07"] = "07", ["\x08"] = "08", ["\x09"] = "09", ["\x0A"] = "0.", ["\x0B"] = "0E", ["\x0C"] = "0E-", ["\x0D"] = "0", ["\x0E"] = "0-", ["\x0F"] = "0",
+ ["\x10"] = "10", ["\x11"] = "11", ["\x12"] = "12", ["\x13"] = "13", ["\x14"] = "14", ["\x15"] = "15", ["\x16"] = "16", ["\x17"] = "17", ["\x18"] = "18", ["\x19"] = "19", ["\x1A"] = "0.", ["\x1B"] = "0E", ["\x1C"] = "0E-", ["\x1D"] = "0", ["\x1E"] = "0-", ["\x1F"] = "0",
+ ["\x20"] = "20", ["\x21"] = "21", ["\x22"] = "22", ["\x23"] = "23", ["\x24"] = "24", ["\x25"] = "25", ["\x26"] = "26", ["\x27"] = "27", ["\x28"] = "28", ["\x29"] = "29", ["\x2A"] = "0.", ["\x2B"] = "0E", ["\x2C"] = "0E-", ["\x2D"] = "0", ["\x2E"] = "0-", ["\x2F"] = "0",
+ ["\x30"] = "30", ["\x31"] = "31", ["\x32"] = "32", ["\x33"] = "33", ["\x34"] = "34", ["\x35"] = "35", ["\x36"] = "36", ["\x37"] = "37", ["\x38"] = "38", ["\x39"] = "39", ["\x3A"] = "0.", ["\x3B"] = "0E", ["\x3C"] = "0E-", ["\x3D"] = "0", ["\x3E"] = "0-", ["\x3F"] = "0",
+ ["\x40"] = "40", ["\x41"] = "41", ["\x42"] = "42", ["\x43"] = "43", ["\x44"] = "44", ["\x45"] = "45", ["\x46"] = "46", ["\x47"] = "47", ["\x48"] = "48", ["\x49"] = "49", ["\x4A"] = "0.", ["\x4B"] = "0E", ["\x4C"] = "0E-", ["\x4D"] = "0", ["\x4E"] = "0-", ["\x4F"] = "0",
+ ["\x50"] = "50", ["\x51"] = "51", ["\x52"] = "52", ["\x53"] = "53", ["\x54"] = "54", ["\x55"] = "55", ["\x56"] = "56", ["\x57"] = "57", ["\x58"] = "58", ["\x59"] = "59", ["\x5A"] = "0.", ["\x5B"] = "0E", ["\x5C"] = "0E-", ["\x5D"] = "0", ["\x5E"] = "0-", ["\x5F"] = "0",
+ ["\x60"] = "60", ["\x61"] = "61", ["\x62"] = "62", ["\x63"] = "63", ["\x64"] = "64", ["\x65"] = "65", ["\x66"] = "66", ["\x67"] = "67", ["\x68"] = "68", ["\x69"] = "69", ["\x6A"] = "0.", ["\x6B"] = "0E", ["\x6C"] = "0E-", ["\x6D"] = "0", ["\x6E"] = "0-", ["\x6F"] = "0",
+ ["\x70"] = "70", ["\x71"] = "71", ["\x72"] = "72", ["\x73"] = "73", ["\x74"] = "74", ["\x75"] = "75", ["\x76"] = "76", ["\x77"] = "77", ["\x78"] = "78", ["\x79"] = "79", ["\x7A"] = "0.", ["\x7B"] = "0E", ["\x7C"] = "0E-", ["\x7D"] = "0", ["\x7E"] = "0-", ["\x7F"] = "0",
+ ["\x80"] = "80", ["\x81"] = "81", ["\x82"] = "82", ["\x83"] = "83", ["\x84"] = "84", ["\x85"] = "85", ["\x86"] = "86", ["\x87"] = "87", ["\x88"] = "88", ["\x89"] = "89", ["\x8A"] = "0.", ["\x8B"] = "0E", ["\x8C"] = "0E-", ["\x8D"] = "0", ["\x8E"] = "0-", ["\x8F"] = "0",
+ ["\x90"] = "90", ["\x91"] = "91", ["\x92"] = "92", ["\x93"] = "93", ["\x94"] = "94", ["\x95"] = "95", ["\x96"] = "96", ["\x97"] = "97", ["\x98"] = "98", ["\x99"] = "99", ["\x9A"] = "0.", ["\x9B"] = "0E", ["\x9C"] = "0E-", ["\x9D"] = "0", ["\x9E"] = "0-", ["\x9F"] = "0",
+ ["\xA0"] = ".0", ["\xA1"] = ".1", ["\xA2"] = ".2", ["\xA3"] = ".3", ["\xA4"] = ".4", ["\xA5"] = ".5", ["\xA6"] = ".6", ["\xA7"] = ".7", ["\xA8"] = ".8", ["\xA9"] = ".9", ["\xAA"] = "..", ["\xAB"] = ".E", ["\xAC"] = ".E-", ["\xAD"] = ".", ["\xAE"] = ".-", ["\xAF"] = ".",
+ ["\xB0"] = "E0", ["\xB1"] = "E1", ["\xB2"] = "E2", ["\xB3"] = "E3", ["\xB4"] = "E4", ["\xB5"] = "E5", ["\xB6"] = "E6", ["\xB7"] = "E7", ["\xB8"] = "E8", ["\xB9"] = "E9", ["\xBA"] = "E.", ["\xBB"] = "EE", ["\xBC"] = "EE-", ["\xBD"] = "E", ["\xBE"] = "E-", ["\xBF"] = "E",
+ ["\xC0"] = "E-0", ["\xC1"] = "E-1", ["\xC2"] = "E-2", ["\xC3"] = "E-3", ["\xC4"] = "E-4", ["\xC5"] = "E-5", ["\xC6"] = "E-6", ["\xC7"] = "E-7", ["\xC8"] = "E-8", ["\xC9"] = "E-9", ["\xCA"] = "E-.", ["\xCB"] = "E-E", ["\xCC"] = "E-E-", ["\xCD"] = "E-", ["\xCE"] = "E--", ["\xCF"] = "E-",
+ ["\xD0"] = "-0", ["\xD1"] = "-1", ["\xD2"] = "-2", ["\xD3"] = "-3", ["\xD4"] = "-4", ["\xD5"] = "-5", ["\xD6"] = "-6", ["\xD7"] = "-7", ["\xD8"] = "-8", ["\xD9"] = "-9", ["\xDA"] = "-.", ["\xDB"] = "-E", ["\xDC"] = "-E-", ["\xDD"] = "-", ["\xDE"] = "--", ["\xDF"] = "-",
+ }
+
+ local p_nibbles = P("\30") * Cs(((1-p_last)/remap)^0+p_last) / function(n)
+ -- 0-9=digit a=. b=E c=E- d=reserved e=- f=finish
+ top = top + 1
+ stack[top] = tonumber(n) or 0
+ end
+
+ local p_byte = C(R("\32\246")) / function(b0)
+ -- -107 .. +107
+ top = top + 1
+ stack[top] = byte(b0) - 139
+ end
+
+ local p_positive = C(R("\247\250")) * C(1) / function(b0,b1)
+ -- +108 .. +1131
+ top = top + 1
+ stack[top] = (byte(b0)-247)*256 + byte(b1) + 108
+ end
+
+ local p_negative = C(R("\251\254")) * C(1) / function(b0,b1)
+ -- -1131 .. -108
+ top = top + 1
+ stack[top] = -(byte(b0)-251)*256 - byte(b1) - 108
+ end
+
+ local p_short = P("\28") * C(1) * C(1) / function(b1,b2)
+ -- -32768 .. +32767 : b1<<8 | b2
+ top = top + 1
+ local n = 0x100 * byte(b1) + byte(b2)
+ if n >= 0x8000 then
+ stack[top] = n - 0xFFFF - 1
+ else
+ stack[top] = n
+ end
+ end
+
+ local p_long = P("\29") * C(1) * C(1) * C(1) * C(1) / function(b1,b2,b3,b4)
+ -- -2^31 .. +2^31-1 : b1<<24 | b2<<16 | b3<<8 | b4
+ top = top + 1
+ local n = 0x1000000 * byte(b1) + 0x10000 * byte(b2) + 0x100 * byte(b3) + byte(b4)
+ if n >= 0x8000000 then
+ stack[top] = n - 0xFFFFFFFF - 1
+ else
+ stack[top] = n
+ end
+ end
+
+ local p_unsupported = P(1) / function(detail)
+ top = 0
+ end
+
+ local p_dictionary = (
+ p_byte
+ + p_positive
+ + p_negative
+ + p_short
+ + p_long
+ + p_nibbles
+ + p_single
+ + p_double
+ + p_unsupported
+ )^1
+
+ parsedictionaries = function(data,dictionaries)
+ stack = { }
+ strings = data.strings
+ for i=1,#dictionaries do
+ top = 0
+ result = {
+ monospaced = false,
+ italicangle = 0,
+ underlineposition = -100,
+ underlinethickness = 50,
+ painttype = 0,
+ charstringtype = 2,
+ fontmatrix = { 0.001, 0, 0, 0.001, 0, 0 },
+ fontbbox = { 0, 0, 0, 0 },
+ strokewidth = 0,
+ charset = 0,
+ encoding = 0,
+ cid = {
+ fontversion = 0,
+ fontrevision = 0,
+ fonttype = 0,
+ count = 8720,
+ }
+ }
+ lpegmatch(p_dictionary,dictionaries[i])
+ dictionaries[i] = result
+ end
+ --
+ result = { }
+ top = 0
+ stack = { }
+ end
+
+ parseprivates = function(data,dictionaries)
+ stack = { }
+ strings = data.strings
+ for i=1,#dictionaries do
+ local private = dictionaries[i].private
+ if private and private.data then
+ top = 0
+ result = {
+ forcebold = false,
+ languagegroup = 0,
+ expansionfactor = 0.06,
+ initialrandomseed = 0,
+ subroutines = 0,
+ defaultwidthx = 0,
+ nominalwidthx = 0,
+ cid = {
+ -- actually an error
+ },
+ }
+ lpegmatch(p_dictionary,private.data)
+ private.data = result
+ end
+ end
+ result = { }
+ top = 0
+ stack = { }
+ end
+
+ -- All bezier curves have 6 points with successive pairs relative to
+ -- the previous pair. Some can be left out and are then copied or zero
+ -- (optimization).
+ --
+ -- We are not really interested in all the details of a glyph because we
+ -- only need to calculate the boundingbox. So, todo: a quick no result but
+ -- calculate only variant.
+ --
+ -- The conversion is straightforward and the specification os clear once
+ -- you understand that the x and y needs to be updates each step. It's also
+ -- quite easy to test because in mp a shape will look bad when a few variables
+ -- are swapped. But still there might be bugs down here because not all
+ -- variants are seen in a font so far. We are less compact that the ff code
+ -- because there quite some variants are done in one helper with a lot of
+ -- testing for states.
+
+ local x = 0
+ local y = 0
+ local width = false
+ local r = 0
+ local stems = 0
+ local globalbias = 0
+ local localbias = 0
+ local globals = false
+ local locals = false
+ local depth = 1
+ local xmin = 0
+ local xmax = 0
+ local ymin = 0
+ local ymax = 0
+ local checked = false
+ local keepcurve = false
+
+ local function showstate(where)
+ report("%w%-10s : [%s] n=%i",depth*2,where,concat(stack," ",1,top),top)
+ end
+
+ local function showvalue(where,value,showstack)
+ if showstack then
+ report("%w%-10s : %s : [%s] n=%i",depth*2,where,tostring(value),concat(stack," ",1,top),top)
+ else
+ report("%w%-10s : %s",depth*2,where,tostring(value))
+ end
+ end
+
+ -- All these indirect calls make this run slower but it's cleaner this way
+ -- and we cache the result. As we moved the boundingbox code inline we gain
+ -- some back.
+
+ local function moveto(x,y)
+ if keepcurve then
+ r = r + 1
+ result[r] = { x, y, "m" }
+ end
+ if checked then
+ if x < xmin then xmin = x elseif x > xmax then xmax = x end
+ if y < ymin then ymin = y elseif y > ymax then ymax = y end
+ else
+ xmin = x
+ ymin = y
+ xmax = x
+ ymax = y
+ checked = true
+ end
+ end
+
+ local function lineto(x,y)
+ if keepcurve then
+ r = r + 1
+ result[r] = { x, y, "l" }
+ end
+ if checked then
+ if x < xmin then xmin = x elseif x > xmax then xmax = x end
+ if y < ymin then ymin = y elseif y > ymax then ymax = y end
+ else
+ xmin = x
+ ymin = y
+ xmax = x
+ ymax = y
+ checked = true
+ end
+ end
+
+ local function curveto(x1,y1,x2,y2,x3,y3)
+ if keepcurve then
+ r = r + 1
+ result[r] = { x1, y1, x2, y2, x3, y3, "c" }
+ end
+ if checked then
+ if x1 < xmin then xmin = x1 elseif x1 > xmax then xmax = x1 end
+ if y1 < ymin then ymin = y1 elseif y1 > ymax then ymax = y1 end
+ else
+ xmin = x1
+ ymin = y1
+ xmax = x1
+ ymax = y1
+ checked = true
+ end
+ if x2 < xmin then xmin = x2 elseif x2 > xmax then xmax = x2 end
+ if y2 < ymin then ymin = y2 elseif y2 > ymax then ymax = y2 end
+ if x3 < xmin then xmin = x3 elseif x3 > xmax then xmax = x3 end
+ if y3 < ymin then ymin = y3 elseif y3 > ymax then ymax = y3 end
+ end
+
+ local function rmoveto()
+ if top > 2 then
+ if not width then
+ width = stack[1]
+ if trace_charstrings then
+ showvalue("width",width)
+ end
+ end
+ elseif not width then
+ width = true
+ end
+ if trace_charstrings then
+ showstate("rmoveto")
+ end
+ x = x + stack[top-1] -- dx1
+ y = y + stack[top] -- dy1
+ top = 0
+ moveto(x,y)
+ end
+
+ local function hmoveto()
+ if top > 1 then
+ if not width then
+ width = stack[1]
+ if trace_charstrings then
+ showvalue("width",width)
+ end
+ end
+ elseif not width then
+ width = true
+ end
+ if trace_charstrings then
+ showstate("hmoveto")
+ end
+ x = x + stack[top] -- dx1
+ top = 0
+ moveto(x,y)
+ end
+
+ local function vmoveto()
+ if top > 1 then
+ if not width then
+ width = stack[1]
+ if trace_charstrings then
+ showvalue("width",width)
+ end
+ end
+ elseif not width then
+ width = true
+ end
+ if trace_charstrings then
+ showstate("vmoveto")
+ end
+ y = y + stack[top] -- dy1
+ top = 0
+ moveto(x,y)
+ end
+
+ local function rlineto()
+ if trace_charstrings then
+ showstate("rlineto")
+ end
+ for i=1,top,2 do
+ x = x + stack[i] -- dxa
+ y = y + stack[i+1] -- dya
+ lineto(x,y)
+ end
+ top = 0
+ end
+
+ local function xlineto(swap) -- x (y,x)+ | (x,y)+
+ for i=1,top do
+ if swap then
+ x = x + stack[i]
+ swap = false
+ else
+ y = y + stack[i]
+ swap = true
+ end
+ lineto(x,y)
+ end
+ top = 0
+ end
+
+ local function hlineto() -- x (y,x)+ | (x,y)+
+ if trace_charstrings then
+ showstate("hlineto")
+ end
+ xlineto(true)
+ end
+
+ local function vlineto() -- y (x,y)+ | (y,x)+
+ if trace_charstrings then
+ showstate("vlineto")
+ end
+ xlineto(false)
+ end
+
+ local function rrcurveto()
+ if trace_charstrings then
+ showstate("rrcurveto")
+ end
+ for i=1,top,6 do
+ local ax = x + stack[i] -- dxa
+ local ay = y + stack[i+1] -- dya
+ local bx = ax + stack[i+2] -- dxb
+ local by = ay + stack[i+3] -- dyb
+ x = bx + stack[i+4] -- dxc
+ y = by + stack[i+5] -- dyc
+ curveto(ax,ay,bx,by,x,y)
+ end
+ top = 0
+ end
+
+ local function hhcurveto()
+ if trace_charstrings then
+ showstate("hhcurveto")
+ end
+ local s = 1
+ if top % 2 ~= 0 then
+ y = y + stack[1] -- dy1
+ s = 2
+ end
+ for i=s,top,4 do
+ local ax = x + stack[i] -- dxa
+ local ay = y
+ local bx = ax + stack[i+1] -- dxb
+ local by = ay + stack[i+2] -- dyb
+ x = bx + stack[i+3] -- dxc
+ y = by
+ curveto(ax,ay,bx,by,x,y)
+ end
+ top = 0
+ end
+
+ local function vvcurveto()
+ if trace_charstrings then
+ showstate("vvcurveto")
+ end
+ local s = 1
+ local d = 0
+ if top % 2 ~= 0 then
+ d = stack[1] -- dx1
+ s = 2
+ end
+ for i=s,top,4 do
+ local ax = x + d
+ local ay = y + stack[i] -- dya
+ local bx = ax + stack[i+1] -- dxb
+ local by = ay + stack[i+2] -- dyb
+ x = bx
+ y = by + stack[i+3] -- dyc
+ curveto(ax,ay,bx,by,x,y)
+ d = 0
+ end
+ top = 0
+ end
+
+ local function xxcurveto(swap)
+ local last = top % 4 ~= 0 and stack[top]
+ if last then
+ top = top - 1
+ end
+ local sw = swap
+ for i=1,top,4 do
+ local ax, ay, bx, by
+ if swap then
+ ax = x + stack[i]
+ ay = y
+ bx = ax + stack[i+1]
+ by = ay + stack[i+2]
+ y = by + stack[i+3]
+ if last and i+3 == top then
+ x = bx + last
+ else
+ x = bx
+ end
+ swap = false
+ else
+ ax = x
+ ay = y + stack[i]
+ bx = ax + stack[i+1]
+ by = ay + stack[i+2]
+ x = bx + stack[i+3]
+ if last and i+3 == top then
+ y = by + last
+ else
+ y = by
+ end
+ swap = true
+ end
+ curveto(ax,ay,bx,by,x,y)
+ end
+ top = 0
+ end
+
+ local function hvcurveto()
+ if trace_charstrings then
+ showstate("hvcurveto")
+ end
+ xxcurveto(true)
+ end
+
+ local function vhcurveto()
+ if trace_charstrings then
+ showstate("vhcurveto")
+ end
+ xxcurveto(false)
+ end
+
+ local function rcurveline()
+ if trace_charstrings then
+ showstate("rcurveline")
+ end
+ for i=1,top-2,6 do
+ local ax = x + stack[i] -- dxa
+ local ay = y + stack[i+1] -- dya
+ local bx = ax + stack[i+2] -- dxb
+ local by = ay + stack[i+3] -- dyb
+ x = bx + stack[i+4] -- dxc
+ y = by + stack[i+5] -- dyc
+ curveto(ax,ay,bx,by,x,y)
+ end
+ x = x + stack[top-1] -- dxc
+ y = y + stack[top] -- dyc
+ lineto(x,y)
+ top = 0
+ end
+
+ local function rlinecurve()
+ if trace_charstrings then
+ showstate("rlinecurve")
+ end
+ if top > 6 then
+ for i=1,top-6,2 do
+ x = x + stack[i]
+ y = y + stack[i+1]
+ lineto(x,y)
+ end
+ end
+ local ax = x + stack[top-5]
+ local ay = y + stack[top-4]
+ local bx = ax + stack[top-3]
+ local by = ay + stack[top-2]
+ x = bx + stack[top-1]
+ y = by + stack[top]
+ curveto(ax,ay,bx,by,x,y)
+ top = 0
+ end
+
+ -- flex is not yet tested! no loop
+
+ local function flex() -- fd not used
+ if trace_charstrings then
+ showstate("flex")
+ end
+ local ax = x + stack[1] -- dx1
+ local ay = y + stack[2] -- dy1
+ local bx = ax + stack[3] -- dx2
+ local by = ay + stack[4] -- dy2
+ local cx = bx + stack[5] -- dx3
+ local cy = by + stack[6] -- dy3
+ curveto(ax,ay,bx,by,cx,cy)
+ local dx = cx + stack[7] -- dx4
+ local dy = cy + stack[8] -- dy4
+ local ex = dx + stack[9] -- dx5
+ local ey = dy + stack[10] -- dy5
+ x = ex + stack[11] -- dx6
+ y = ey + stack[12] -- dy6
+ curveto(dx,dy,ex,ey,x,y)
+ top = 0
+ end
+
+ local function hflex()
+ if trace_charstrings then
+ showstate("hflex")
+ end
+ local ax = x + stack[1] -- dx1
+ local ay = y
+ local bx = ax + stack[2] -- dx2
+ local by = ay + stack[3] -- dy2
+ local cx = bx + stack[4] -- dx3
+ local cy = by
+ curveto(ax,ay,bx,by,cx,cy)
+ local dx = cx + stack[5] -- dx4
+ local dy = by
+ local ex = dx + stack[6] -- dx5
+ local ey = y
+ x = ex + stack[7] -- dx6
+ curveto(dx,dy,ex,ey,x,y)
+ top = 0
+ end
+
+ local function hflex1()
+ if trace_charstrings then
+ showstate("hflex1")
+ end
+ local ax = x + stack[1] -- dx1
+ local ay = y + stack[2] -- dy1
+ local bx = ax + stack[3] -- dx2
+ local by = ay + stack[4] -- dy2
+ local cx = bx + stack[5] -- dx3
+ local cy = by
+ curveto(ax,ay,bx,by,cx,cy)
+ local dx = cx + stack[6] -- dx4
+ local dy = by
+ local ex = dx + stack[7] -- dx5
+ local ey = dy + stack[8] -- dy5
+ x = ex + stack[9] -- dx6
+ curveto(dx,dy,ex,ey,x,y)
+ top = 0
+ end
+
+ local function flex1()
+ if trace_charstrings then
+ showstate("flex1")
+ end
+ local ax = x + stack[1] --dx1
+ local ay = y + stack[2] --dy1
+ local bx = ax + stack[3] --dx2
+ local by = ay + stack[4] --dy2
+ local cx = bx + stack[5] --dx3
+ local cy = by + stack[6] --dy3
+ curveto(ax,ay,bx,by,cx,cy)
+ local dx = cx + stack[7] --dx4
+ local dy = cy + stack[8] --dy4
+ local ex = dx + stack[9] --dx5
+ local ey = dy + stack[10] --dy5
+ if abs(ex - x) > abs(ey - y) then -- spec: abs(dx) > abs(dy)
+ x = ex + stack[11]
+ else
+ y = ey + stack[11]
+ end
+ curveto(dx,dy,ex,ey,x,y)
+ top = 0
+ end
+
+ local function getstem()
+ if top == 0 then
+ -- bad
+ elseif top % 2 ~= 0 then
+ if width then
+ remove(stack,1)
+ else
+ width = remove(stack,1)
+ if trace_charstrings then
+ showvalue("width",width)
+ end
+ end
+ top = top - 1
+ end
+ if trace_charstrings then
+ showstate("stem")
+ end
+ stems = stems + top/2
+ top = 0
+ end
+
+ local function getmask()
+ if top == 0 then
+ -- bad
+ elseif top % 2 ~= 0 then
+ if width then
+ remove(stack,1)
+ else
+ width = remove(stack,1)
+ if trace_charstrings then
+ showvalue("width",width)
+ end
+ end
+ top = top - 1
+ end
+ if trace_charstrings then
+ showstate(operator == 19 and "hintmark" or "cntrmask")
+ end
+ stems = stems + top/2
+ top = 0
+ if stems == 0 then
+ -- forget about it
+ elseif stems <= 8 then
+ return 1
+ else
+ return floor((stems+7)/8)
+ end
+ end
+
+ local function unsupported()
+ if trace_charstrings then
+ showstate("unsupported")
+ end
+ top = 0
+ end
+
+ -- Bah, we cannot use a fast lpeg because a hint has an unknown size and a
+ -- runtime capture cannot handle that well.
+
+ local actions = { [0] =
+ unsupported, -- 0
+ getstem, -- 1 -- hstem
+ unsupported, -- 2
+ getstem, -- 3 -- vstem
+ vmoveto, -- 4
+ rlineto, -- 5
+ hlineto, -- 6
+ vlineto, -- 7
+ rrcurveto, -- 8
+ unsupported, -- 9 -- closepath
+ unsupported, -- 10 -- calllocal,
+ unsupported, -- 11 -- callreturn,
+ unsupported, -- 12 -- elsewhere
+ unsupported, -- 13 -- hsbw
+ unsupported, -- 14 -- endchar,
+ unsupported, -- 15
+ unsupported, -- 16
+ unsupported, -- 17
+ getstem, -- 18 -- hstemhm
+ getmask, -- 19 -- hintmask
+ getmask, -- 20 -- cntrmask
+ rmoveto, -- 21
+ hmoveto, -- 22
+ getstem, -- 23 -- vstemhm
+ rcurveline, -- 24
+ rlinecurve, -- 25
+ vvcurveto, -- 26
+ hhcurveto, -- 27
+ unsupported, -- 28 -- elsewhere
+ unsupported, -- 29 -- elsewhere
+ vhcurveto, -- 30
+ hvcurveto, -- 31
+ }
+
+ local subactions = {
+ [034] = hflex,
+ [035] = flex,
+ [036] = hflex1,
+ [037] = flex1,
+ }
+
+ local p_bytes = Ct((P(1)/byte)^0)
+
+ local function call(scope,list,bias,process)
+ local index = stack[top] + bias
+ top = top - 1
+ if trace_charstrings then
+ showvalue(scope,index,true)
+ end
+ local str = list[index]
+ if str then
+ if type(str) == "string" then
+ str = lpegmatch(p_bytes,str)
+ list[index] = str
+ end
+ depth = depth + 1
+ process(str)
+ depth = depth - 1
+ else
+ report("unknown %s %i",scope,index)
+ end
+ end
+
+ local function process(tab)
+ local i = 1
+ local n = #tab
+ while i <= n do
+ local t = tab[i]
+ if t >= 32 and t<=246 then
+ -- -107 .. +107
+ top = top + 1
+ stack[top] = t - 139
+ i = i + 1
+ elseif t >= 247 and t <= 250 then
+ -- +108 .. +1131
+ top = top + 1
+ stack[top] = (t-247)*256 + tab[i+1] + 108
+ i = i + 2
+ elseif t >= 251 and t <= 254 then
+ -- -1131 .. -108
+ top = top + 1
+ stack[top] = -(t-251)*256 - tab[i+1] - 108
+ i = i + 2
+ elseif t == 28 then
+ -- -32768 .. +32767 : b1<<8 | b2
+ top = top + 1
+ local n = 0x100 * tab[i+1] + tab[i+2]
+ if n >= 0x8000 then
+ stack[top] = n - 0xFFFF - 1
+ else
+ stack[top] = n
+ end
+ i = i + 3
+ elseif t == 255 then
+ local n = 0x100 * tab[i+1] + tab[i+2]
+ top = top + 1
+ if n >= 0x8000 then
+ stack[top] = n - 0xFFFF - 1 + (0x100 * tab[i+3] + tab[i+4])/0xFFFF
+ else
+ stack[top] = n + (0x100 * tab[i+3] + tab[i+4])/0xFFFF
+ end
+ i = i + 5
+ elseif t == 11 then
+ if trace_charstrings then
+ showstate("return")
+ end
+ return
+ elseif t == 10 then
+ call("local",locals,localbias,process)
+ i = i + 1
+ elseif t == 14 then -- endchar
+ if width then
+ -- okay
+ elseif top > 0 then
+ width = stack[1]
+ if trace_charstrings then
+ showvalue("width",width)
+ end
+ else
+ width = true
+ end
+ if trace_charstrings then
+ showstate("endchar")
+ end
+ return
+ elseif t == 29 then
+ call("global",globals,globalbias,process)
+ i = i + 1
+ elseif t == 12 then
+ i = i + 1
+ local t = tab[i]
+ local a = subactions[t]
+ if a then
+ a()
+ else
+ if trace_charstrings then
+ showvalue("<subaction>",t)
+ end
+ top = 0
+ end
+ i = i + 1
+ else
+ local a = actions[t]
+ if a then
+ local s = a()
+ if s then
+ i = i + s
+ end
+ else
+ if trace_charstrings then
+ showvalue("<action>",t)
+ end
+ top = 0
+ end
+ i = i + 1
+ end
+ end
+ end
+
+ -- local function calculatebounds(segments,x,y)
+ -- local nofsegments = #segments
+ -- if nofsegments == 0 then
+ -- return { x, y, x, y }
+ -- else
+ -- local xmin = 10000
+ -- local xmax = -10000
+ -- local ymin = 10000
+ -- local ymax = -10000
+ -- if x < xmin then xmin = x end
+ -- if x > xmax then xmax = x end
+ -- if y < ymin then ymin = y end
+ -- if y > ymax then ymax = y end
+ -- -- we now have a reasonable start so we could
+ -- -- simplyfy the next checks
+ -- for i=1,nofsegments do
+ -- local s = segments[i]
+ -- local x = s[1]
+ -- local y = s[2]
+ -- if x < xmin then xmin = x end
+ -- if x > xmax then xmax = x end
+ -- if y < ymin then ymin = y end
+ -- if y > ymax then ymax = y end
+ -- if s[#s] == "c" then -- "curveto"
+ -- local x = s[3]
+ -- local y = s[4]
+ -- if x < xmin then xmin = x elseif x > xmax then xmax = x end
+ -- if y < ymin then ymin = y elseif y > ymax then ymax = y end
+ -- local x = s[5]
+ -- local y = s[6]
+ -- if x < xmin then xmin = x elseif x > xmax then xmax = x end
+ -- if y < ymin then ymin = y elseif y > ymax then ymax = y end
+ -- end
+ -- end
+ -- return { round(xmin), round(ymin), round(xmax), round(ymax) } -- doesn't make ceil more sense
+ -- end
+ -- end
+
+ parsecharstrings = function(data,glyphs,doshapes)
+ -- for all charstrings
+ local dictionary = data.dictionaries[1]
+ local charstrings = dictionary.charstrings
+ local charset = dictionary.charset
+ keepcurve = doshapes
+ stack = { }
+ glyphs = glyphs or { }
+ strings = data.strings
+ locals = dictionary.subroutines
+ globals = data.routines
+ globalbias = #globals
+ localbias = #locals
+ globalbias = ((globalbias < 1240 and 107) or (globalbias < 33900 and 1131) or 32768) + 1
+ localbias = ((localbias < 1240 and 107) or (localbias < 33900 and 1131) or 32768) + 1
+ local nominalwidth = dictionary.private.data.nominalwidthx or 0
+ local defaultwidth = dictionary.private.data.defaultwidthx or 0
+
+ for i=1,#charstrings do
+ local str = charstrings[i]
+ local tab = lpegmatch(p_bytes,str)
+ local index = i - 1
+ x = 0
+ y = 0
+ width = false
+ r = 0
+ top = 0
+ stems = 0
+ result = { }
+ --
+ xmin = 0
+ xmax = 0
+ ymin = 0
+ ymax = 0
+ checked = false
+ --
+ if trace_charstrings then
+ report("glyph: %i",index)
+ report("data: % t",tab)
+ end
+ --
+ process(tab)
+ --
+ local boundingbox = { round(xmin), round(ymin), round(xmax), round(ymax) }
+ --
+ if width == true or width == false then
+ width = defaultwidth
+ else
+ width = nominalwidth + width
+ end
+ --
+ -- trace_charstrings = index == 3078 -- todo: make tracker
+ local glyph = glyphs[index] -- can be autodefined in otr
+ if not glyph then
+ glyphs[index] = {
+ segments = doshapes ~= false and result or nil, -- optional
+ boundingbox = boundingbox,
+ width = width,
+ name = charset[index],
+ -- sidebearing = 0,
+ }
+ else
+ glyph.segments = doshapes ~= false and result or nil
+ glyph.boundingbox = boundingbox
+ if not glyph.width then
+ glyph.width = width
+ end
+ if charset and not glyph.name then
+ glyph.name = charset[index]
+ end
+ -- glyph.sidebearing = 0 -- todo
+ end
+ if trace_charstrings then
+ report("width: %s",tostring(width))
+ report("boundingbox: % t",boundingbox)
+ end
+ charstrings[i] = nil -- free memory
+ end
+ return glyphs
+ end
+
+ parsecharstring = function(data,dictionary,charstring,glyphs,index,doshapes)
+ local private = dictionary.private
+ keepcurve = doshapes
+ strings = data.strings -- or in dict?
+ locals = dictionary.subroutines or { }
+ globals = data.routines or { }
+ globalbias = #globals
+ localbias = #locals
+ globalbias = ((globalbias < 1240 and 107) or (globalbias < 33900 and 1131) or 32768) + 1
+ localbias = ((localbias < 1240 and 107) or (localbias < 33900 and 1131) or 32768) + 1
+ local nominalwidth = private and private.data.nominalwidthx or 0
+ local defaultwidth = private and private.data.defaultwidthx or 0
+ --
+ local tab = lpegmatch(p_bytes,charstring)
+ x = 0
+ y = 0
+ width = false
+ r = 0
+ top = 0
+ stems = 0
+ result = { }
+ --
+ xmin = 0
+ xmax = 0
+ ymin = 0
+ ymax = 0
+ checked = false
+ --
+ if trace_charstrings then
+ report("glyph: %i",index)
+ report("data: % t",tab)
+ end
+ --
+ process(tab)
+ --
+ local boundingbox = { xmin, ymin, xmax, ymax }
+ --
+ if width == true or width == false then
+ width = defaultwidth
+ else
+ width = nominalwidth + width
+ end
+ --
+ local glyph = glyphs[index] -- can be autodefined in otr
+ if not glyph then
+ glyphs[index] = {
+ segments = doshapes ~= false and result or nil, -- optional
+ boundingbox = boundingbox,
+ width = width,
+ name = charset[index],
+ -- sidebearing = 0,
+ }
+ else
+ glyph.segments = doshapes ~= false and result or nil
+ glyph.boundingbox = boundingbox
+ if not glyph.width then
+ glyph.width = width
+ end
+ if charset and not glyph.name then
+ glyph.name = charset[index]
+ end
+ -- glyph.sidebearing = 0 -- todo
+ end
+ --
+ if trace_charstrings then
+ report("width: %s",tostring(width))
+ report("boundingbox: % t",boundingbox)
+ end
+ --
+ return charstring
+ end
+
+ resetcharstrings = function()
+ result = { }
+ top = 0
+ stack = { }
+ end
+
+end
+
+local function readglobals(f,data)
+ local routines = readlengths(f)
+ for i=1,#routines do
+ routines[i] = readstring(f,routines[i])
+ end
+ data.routines = routines
+end
+
+local function readencodings(f,data)
+ data.encodings = { }
+end
+
+local function readcharsets(f,data,dictionary)
+ local header = data.header
+ local strings = data.strings
+ local nofglyphs = data.nofglyphs
+ local charsetoffset = dictionary.charset
+
+ if charsetoffset ~= 0 then
+ setposition(f,header.offset+charsetoffset)
+ local format = readbyte(f)
+ local charset = { [0] = ".notdef" }
+ dictionary.charset = charset
+ if format == 0 then
+ for i=1,nofglyphs do
+ charset[i] = strings[readushort(f)]
+ end
+ elseif format == 1 or format == 2 then
+ local readcount = format == 1 and readbyte or readushort
+ local i = 1
+ while i <= nofglyphs do
+ local sid = readushort(f)
+ local n = readcount(f)
+ for s=sid,sid+n do
+ charset[i] = strings[s]
+ i = i + 1
+ if i > nofglyphs then
+ break
+ end
+ end
+ end
+ else
+ report("cff parser: unsupported charset format %a",format)
+ end
+ end
+end
+
+local function readprivates(f,data)
+ local header = data.header
+ local dictionaries = data.dictionaries
+ local private = dictionaries[1].private
+ if private then
+ setposition(f,header.offset+private.offset)
+ private.data = readstring(f,private.size)
+ end
+end
+
+local function readlocals(f,data,dictionary)
+ local header = data.header
+ local private = dictionary.private
+ if private then
+ local subroutineoffset = private.data.subroutines
+ if subroutineoffset ~= 0 then
+ setposition(f,header.offset+private.offset+subroutineoffset)
+ local subroutines = readlengths(f)
+ for i=1,#subroutines do
+ subroutines[i] = readstring(f,subroutines[i])
+ end
+ dictionary.subroutines = subroutines
+ private.data.subroutines = nil
+ else
+ dictionary.subroutines = { }
+ end
+ else
+ dictionary.subroutines = { }
+ end
+end
+
+-- These charstrings are little programs and described in: Technical Note #5177. A truetype
+-- font has only one dictionary.
+
+local function readcharstrings(f,data)
+ local header = data.header
+ local dictionaries = data.dictionaries
+ local dictionary = dictionaries[1]
+ local type = dictionary.charstringtype
+ local offset = dictionary.charstrings
+ if type == 2 then
+ setposition(f,header.offset+offset)
+ -- could be a metatable .. delayed loading
+ local charstrings = readlengths(f)
+ local nofglyphs = #charstrings
+ for i=1,nofglyphs do
+ charstrings[i] = readstring(f,charstrings[i])
+ end
+ data.nofglyphs = nofglyphs
+ dictionary.charstrings = charstrings
+ else
+ report("unsupported charstr type %i",type)
+ data.nofglyphs = 0
+ dictionary.charstrings = { }
+ end
+end
+
+-- cid (maybe do this stepwise so less mem) -- share with above
+
+local function readcidprivates(f,data)
+ local header = data.header
+ local dictionaries = data.dictionaries[1].cid.dictionaries
+ for i=1,#dictionaries do
+ local dictionary = dictionaries[i]
+ local private = dictionary.private
+ if private then
+ setposition(f,header.offset+private.offset)
+ private.data = readstring(f,private.size)
+ end
+ end
+ parseprivates(data,dictionaries)
+end
+
+local function readnoselect(f,data,glyphs,doshapes)
+ local dictionaries = data.dictionaries
+ local dictionary = dictionaries[1]
+ readglobals(f,data)
+ readcharstrings(f,data)
+ readencodings(f,data)
+ readcharsets(f,data,dictionary)
+ readprivates(f,data)
+ parseprivates(data,data.dictionaries)
+ readlocals(f,data,dictionary)
+ parsecharstrings(data,glyphs,doshapes)
+ resetcharstrings()
+end
+
+local function readfdselect(f,data,glyphs,doshapes)
+ local header = data.header
+ local dictionaries = data.dictionaries
+ local dictionary = dictionaries[1]
+ local cid = dictionary.cid
+ local cidselect = cid and cid.fdselect
+ readglobals(f,data)
+ readcharstrings(f,data)
+ readencodings(f,data)
+ local charstrings = dictionary.charstrings
+ local fdindex = { }
+ local nofglyphs = data.nofglyphs
+ local maxindex = -1
+ setposition(f,header.offset+cidselect)
+ local format = readbyte(f)
+ if format == 1 then
+ for i=0,nofglyphs do -- notdef included (needs checking)
+ local index = readbyte(i)
+ fdindex[i] = index
+ if index > maxindex then
+ maxindex = index
+ end
+ end
+ elseif format == 3 then
+ local nofranges = readushort(f)
+ local first = readushort(f)
+ local index = readbyte(f)
+ while true do
+ local last = readushort(f)
+ if index > maxindex then
+ maxindex = index
+ end
+ for i=first,last do
+ fdindex[i] = index
+ end
+ if last >= nofglyphs then
+ break
+ else
+ first = last + 1
+ index = readbyte(f)
+ end
+ end
+ else
+ -- unsupported format
+ end
+ if maxindex >= 0 then
+ local cidarray = cid.fdarray
+ setposition(f,header.offset+cidarray)
+ local dictionaries = readlengths(f)
+ for i=1,#dictionaries do
+ dictionaries[i] = readstring(f,dictionaries[i])
+ end
+ parsedictionaries(data,dictionaries)
+ cid.dictionaries = dictionaries
+ readcidprivates(f,data)
+ for i=1,#dictionaries do
+ readlocals(f,data,dictionaries[i])
+ end
+ for i=1,#charstrings do
+ parsecharstring(data,dictionaries[fdindex[i]+1],charstrings[i],glyphs,i,doshapes)
+ end
+ resetcharstrings()
+ end
+end
+
+function readers.cff(f,fontdata,specification)
+-- if specification.glyphs then
+ if specification.details then
+ local datatable = fontdata.tables.cff
+ if datatable then
+ local offset = datatable.offset
+ local glyphs = fontdata.glyphs
+ if not f then
+ report("invalid filehandle")
+ return
+ end
+ if offset then
+ setposition(f,offset)
+ end
+ local header = readheader(f)
+ if header.major > 1 then
+ report("version mismatch")
+ return
+ end
+ local names = readfontnames(f)
+ local dictionaries = readtopdictionaries(f)
+ local strings = readstrings(f)
+ local data = {
+ header = header,
+ names = names,
+ dictionaries = dictionaries,
+ strings = strings,
+ nofglyphs = fontdata.nofglyphs,
+ }
+ --
+ parsedictionaries(data,data.dictionaries)
+ --
+ local d = dictionaries[1]
+ local c = d.cid
+ fontdata.cffinfo = {
+ familynamename = d.familyname,
+ fullname = d.fullname,
+ boundingbox = d.boundingbox,
+ weight = d.weight,
+ italicangle = d.italicangle,
+ underlineposition = d.underlineposition,
+ underlinethickness = d.underlinethickness,
+ monospaced = d.monospaced,
+ }
+ fontdata.cidinfo = c and {
+ registry = c.registry,
+ ordering = c.ordering,
+ supplement = c.supplement,
+ }
+ --
+ if not specification.glyphs then
+ -- we only want some metadata
+ else
+ local cid = d.cid
+ if cid and cid.fdselect then
+ readfdselect(f,data,glyphs,specification.shapes or false)
+ else
+ readnoselect(f,data,glyphs,specification.shapes or false)
+ end
+ end
+ --
+ -- cleanup (probably more can go)
+ --
+ -- for i=1,#dictionaries do
+ -- local d = dictionaries[i]
+ -- d.subroutines = nil
+ -- end
+ -- data.strings = nil
+ -- if data then
+ -- data.charstrings = nil
+ -- data.routines = nil
+ -- end
+ end
+ end
+end
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-con.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-con.lua
index 55d7793cf91..e5bf9e9c1d9 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-con.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-con.lua
@@ -682,6 +682,8 @@ function constructors.scale(tfmdata,specification)
if isunicode then
chr.unicode = isunicode
chr.tounicode = tounicode(isunicode)
+ -- in luatex > 0.85 we can do this:
+ -- chr.tounicode = isunicode
end
if hasquality then
-- we could move these calculations elsewhere (saves calculations)
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-fonts-inj.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-inj.lua
index 36781f72f34..89370210d41 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-fonts-inj.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-inj.lua
@@ -74,7 +74,6 @@ local nofregisteredkerns = 0
local nofregisteredpairs = 0
local nofregisteredmarks = 0
local nofregisteredcursives = 0
------ markanchors = { } -- one base can have more marks
local keepregisteredcounts = false
function injections.keepcounts()
@@ -91,10 +90,41 @@ end
-- We need to make sure that a possible metatable will not kick in unexpectedly.
+-- function injections.reset(n)
+-- local p = rawget(properties,n)
+-- if p and rawget(p,"injections") then
+-- p.injections = nil
+-- end
+-- end
+
+-- function injections.copy(target,source)
+-- local sp = rawget(properties,source)
+-- if sp then
+-- local tp = rawget(properties,target)
+-- local si = rawget(sp,"injections")
+-- if si then
+-- si = fastcopy(si)
+-- if tp then
+-- tp.injections = si
+-- else
+-- propertydata[target] = {
+-- injections = si,
+-- }
+-- end
+-- else
+-- if tp then
+-- tp.injections = nil
+-- end
+-- end
+-- end
+-- end
+
function injections.reset(n)
local p = rawget(properties,n)
- if p and rawget(p,"injections") then
- p.injections = nil
+ if p then
+ p.injections = false -- { }
+ else
+ properties[n] = false -- { injections = { } }
end
end
@@ -112,10 +142,17 @@ function injections.copy(target,source)
injections = si,
}
end
+ elseif tp then
+ tp.injections = false -- { }
else
- if tp then
- tp.injections = nil
- end
+ properties[target] = { injections = { } }
+ end
+ else
+ local tp = rawget(properties,target)
+ if tp then
+ tp.injections = false -- { }
+ else
+ properties[target] = false -- { injections = { } }
end
end
end
@@ -367,10 +404,11 @@ local function show(n,what,nested,symbol)
local markx = i.markx or 0
local marky = i.marky or 0
local markdir = i.markdir or 0
- local markbase = i.markbase or 0 -- will be markbasenode
+ local markbase = i.markbase or 0
local cursivex = i.cursivex or 0
local cursivey = i.cursivey or 0
local ligaindex = i.ligaindex or 0
+ local cursbase = i.cursiveanchor
local margin = nested and 4 or 2
--
if rightkern ~= 0 or yoffset ~= 0 then
@@ -382,7 +420,13 @@ local function show(n,what,nested,symbol)
report_injections("%w%s mark: dx %p, dy %p, dir %s, base %s",margin,symbol,markx,marky,markdir,markbase ~= 0 and "yes" or "no")
end
if cursivex ~= 0 or cursivey ~= 0 then
- report_injections("%w%s curs: dx %p, dy %p",margin,symbol,cursivex,cursivey)
+ if cursbase then
+ report_injections("%w%s curs: base dx %p, dy %p",margin,symbol,cursivex,cursivey)
+ else
+ report_injections("%w%s curs: dx %p, dy %p",margin,symbol,cursivex,cursivey)
+ end
+ elseif cursbase then
+ report_injections("%w%s curs: base",margin,symbol)
end
if ligaindex ~= 0 then
report_injections("%w%s liga: index %i",margin,symbol,ligaindex)
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-map.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-map.lua
index b645d9aef2b..dc3f499abcc 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-map.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-map.lua
@@ -74,6 +74,71 @@ end
local f_single = formatters["%04X"]
local f_double = formatters["%04X%04X"]
+-- 0.684 0.661 0,672 0.650 : cache at lua end (more mem)
+-- 0.682 0,672 0.698 0.657 : no cache (moderate mem i.e. lua strings)
+-- 0.644 0.647 0.655 0.645 : convert in c (less mem in theory)
+
+-- local tounicodes = table.setmetatableindex(function(t,unicode)
+-- local s
+-- if unicode < 0x10000 then
+-- s = f_single(unicode)
+-- elseif unicode < 0x1FFFFFFFFF then
+-- s = f_double(floor(unicode/1024),unicode%1024+0xDC00)
+-- else
+-- s = false
+-- end
+-- t[unicode] = s
+-- return s
+-- end)
+--
+-- local function tounicode16(unicode,name)
+-- local s = tounicodes[unicode]
+-- if s then
+-- return s
+-- else
+-- report_fonts("can't convert %a in %a into tounicode",unicode,name)
+-- end
+-- end
+--
+-- local function tounicode16sequence(unicodes,name)
+-- local t = { }
+-- for l=1,#unicodes do
+-- local u = unicodes[l]
+-- local s = tounicodes[u]
+-- if s then
+-- t[l] = s
+-- else
+-- report_fonts ("can't convert %a in %a into tounicode",u,name)
+-- return
+-- end
+-- end
+-- return concat(t)
+-- end
+--
+-- local function tounicode(unicode,name)
+-- if type(unicode) == "table" then
+-- local t = { }
+-- for l=1,#unicode do
+-- local u = unicode[l]
+-- local s = tounicodes[u]
+-- if s then
+-- t[l] = s
+-- else
+-- report_fonts ("can't convert %a in %a into tounicode",u,name)
+-- return
+-- end
+-- end
+-- return concat(t)
+-- else
+-- local s = tounicodes[unicode]
+-- if s then
+-- return s
+-- else
+-- report_fonts("can't convert %a in %a into tounicode",unicode,name)
+-- end
+-- end
+-- end
+
local function tounicode16(unicode,name)
if unicode < 0x10000 then
return f_single(unicode)
@@ -126,7 +191,6 @@ local function tounicode(unicode,name)
end
end
-
local function fromunicode16(str)
if #str == 4 then
return tonumber(str,16)
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-otf.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-otf.lua
index f709e70006a..0471c172b85 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-otf.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-otf.lua
@@ -58,7 +58,7 @@ local otf = fonts.handlers.otf
otf.glists = { "gsub", "gpos" }
-otf.version = 2.819 -- beware: also sync font-mis.lua and in mtx-fonts
+otf.version = 2.820 -- beware: also sync font-mis.lua and in mtx-fonts
otf.cache = containers.define("fonts", "otf", otf.version, true)
local hashes = fonts.hashes
@@ -296,7 +296,8 @@ local ordered_enhancers = {
"expand lookups", -- a temp hack awaiting the lua loader
--- "check extra features", -- after metadata and duplicates
+--[[phg-- PATCH: Next line restores font features --phg]]--
+ "check extra features", -- after metadata and duplicates
"cleanup tables",
@@ -600,7 +601,9 @@ function otf.load(filename,sub,featurefile) -- second argument (format) is gone
applyruntimefixes(filename,data)
end
enhance("add dimensions",data,filename,nil,false)
+--[[phg-- This was hand-patched to restore the fontloader
enhance("check extra features",data,filename)
+--phg]]--
if trace_sequences then
showfeatureorder(data,filename)
end
@@ -2959,7 +2962,7 @@ otf.coverup = {
kern = justset,
},
register = function(coverage,lookuptype,format,feature,n,descriptions,resources)
- local name = formatters["ctx_%s_%s"](feature,n)
+ local name = formatters["ctx_%s_%s_%s"](feature,lookuptype,n) -- we can have a mix of types
if lookuptype == "kern" then
resources.lookuptypes[name] = "position"
else
@@ -2973,7 +2976,6 @@ otf.coverup = {
else
description.slookups = { [name] = c }
end
--- inspect(feature,description)
end
return name
end
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-oti.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-oti.lua
index 06c2a42fac2..bacd001a5e8 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-oti.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-oti.lua
@@ -13,9 +13,11 @@ local constructors = fonts.constructors
local otf = constructors.newhandler("otf")
local otffeatures = constructors.newfeatures("otf")
-local otftables = otf.tables
local registerotffeature = otffeatures.register
+local otftables = otf.tables or { }
+otf.tables = otftables
+
local allocate = utilities.storage.allocate
registerotffeature {
@@ -89,3 +91,68 @@ registerotffeature {
}
}
+-- here (as also in generic
+
+otftables.featuretypes = allocate {
+ gpos_single = "position",
+ gpos_pair = "position",
+ gpos_cursive = "position",
+ gpos_mark2base = "position",
+ gpos_mark2ligature = "position",
+ gpos_mark2mark = "position",
+ gpos_context = "position",
+ gpos_contextchain = "position",
+ gsub_single = "substitution",
+ gsub_multiple = "substitution",
+ gsub_alternate = "substitution",
+ gsub_ligature = "substitution",
+ gsub_context = "substitution",
+ gsub_contextchain = "substitution",
+ gsub_reversecontextchain = "substitution",
+ gsub_reversesub = "substitution",
+}
+
+function otffeatures.checkeddefaultscript(featuretype,autoscript,scripts)
+ if featuretype == "position" then
+ local default = scripts.dflt
+ if default then
+ if autoscript == "position" or autoscript == true then
+ return default
+ else
+ report_otf("script feature %s not applied, enable default positioning")
+ end
+ else
+ -- no positioning at all
+ end
+ elseif featuretype == "substitution" then
+ local default = scripts.dflt
+ if default then
+ if autoscript == "substitution" or autoscript == true then
+ return default
+ end
+ end
+ end
+end
+
+function otffeatures.checkeddefaultlanguage(featuretype,autolanguage,languages)
+ if featuretype == "position" then
+ local default = languages.dflt
+ if default then
+ if autolanguage == "position" or autolanguage == true then
+ return default
+ else
+ report_otf("language feature %s not applied, enable default positioning")
+ end
+ else
+ -- no positioning at all
+ end
+ elseif featuretype == "substitution" then
+ local default = languages.dflt
+ if default then
+ if autolanguage == "substitution" or autolanguage == true then
+ return default
+ end
+ end
+ end
+end
+
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-fonts-otn.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-otn.lua
index 7fafadbc4fd..b48aea761c8 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-fonts-otn.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-otn.lua
@@ -132,7 +132,7 @@ results in different tables.</p>
-- gpos_context ok --
-- gpos_contextchain ok --
--
--- todo: contextpos and contextsub and class stuff
+-- todo: contextpos
--
-- actions:
--
@@ -212,7 +212,9 @@ local tonut = nuts.tonut
local getfield = nuts.getfield
local setfield = nuts.setfield
local getnext = nuts.getnext
+local setnext = nuts.setnext
local getprev = nuts.getprev
+local setprev = nuts.setprev
local getid = nuts.getid
local getattr = nuts.getattr
local setattr = nuts.setattr
@@ -220,7 +222,9 @@ local getprop = nuts.getprop
local setprop = nuts.setprop
local getfont = nuts.getfont
local getsubtype = nuts.getsubtype
+local setsubtype = nuts.setsubtype
local getchar = nuts.getchar
+local setchar = nuts.setchar
local insert_node_before = nuts.insert_before
local insert_node_after = nuts.insert_after
@@ -243,7 +247,6 @@ local wildcard = "*"
local default = "dflt"
local nodecodes = nodes.nodecodes
-local whatcodes = nodes.whatcodes
local glyphcodes = nodes.glyphcodes
local disccodes = nodes.disccodes
@@ -251,9 +254,9 @@ local glyph_code = nodecodes.glyph
local glue_code = nodecodes.glue
local disc_code = nodecodes.disc
local math_code = nodecodes.math
+local dir_code = nodecodes.dir
+local localpar_code = nodecodes.localpar
-local dir_code = whatcodes.dir
-local localpar_code = whatcodes.localpar
local discretionary_code = disccodes.discretionary
local ligature_code = glyphcodes.ligature
@@ -412,8 +415,8 @@ local function flattendisk(head,disc)
if replace then
if next then
local tail = find_node_tail(replace)
- setfield(tail,"next",next)
- setfield(next,"prev",tail)
+ setnext(tail,next)
+ setprev(next,tail)
end
return replace, replace
elseif next then
@@ -427,17 +430,17 @@ local function flattendisk(head,disc)
if replace then
local tail = find_node_tail(replace)
if next then
- setfield(tail,"next",next)
- setfield(next,"prev",tail)
+ setnext(tail,next)
+ setprev(next,tail)
end
- setfield(prev,"next",replace)
- setfield(replace,"prev",prev)
+ setnext(prev,replace)
+ setprev(replace,prev)
return head, replace
else
if next then
- setfield(next,"prev",prev)
+ setprev(next,prev)
end
- setfield(prev,"next",next)
+ setnext(prev,next)
return head, next
end
end
@@ -451,14 +454,14 @@ local function appenddisc(disc,list)
local ptail = find_node_tail(post)
local rtail = find_node_tail(replace)
if post then
- setfield(ptail,"next",phead)
- setfield(phead,"prev",ptail)
+ setnext(ptail,phead)
+ setprev(phead,ptail)
else
setfield(disc,"post",phead)
end
if replace then
- setfield(rtail,"next",rhead)
- setfield(rhead,"prev",rtail)
+ setnext(rtail,rhead)
+ setprev(rhead,rtail)
else
setfield(disc,"replace",rhead)
end
@@ -472,24 +475,24 @@ local function markstoligature(kind,lookupname,head,start,stop,char)
else
local prev = getprev(start)
local next = getnext(stop)
- setfield(start,"prev",nil)
- setfield(stop,"next",nil)
+ setprev(start,nil)
+ setnext(stop,nil)
local base = copy_glyph(start)
if head == start then
head = base
end
resetinjection(base)
- setfield(base,"char",char)
- setfield(base,"subtype",ligature_code)
+ setchar(base,char)
+ setsubtype(base,ligature_code)
setfield(base,"components",start)
if prev then
- setfield(prev,"next",base)
+ setnext(prev,base)
end
if next then
- setfield(next,"prev",base)
+ setprev(next,base)
end
- setfield(base,"next",next)
- setfield(base,"prev",prev)
+ setnext(base,next)
+ setprev(base,prev)
return head, base
end
end
@@ -528,7 +531,7 @@ local function toligature(kind,lookupname,head,start,stop,char,markflag,discfoun
end
if start == stop and getchar(start) == char then
resetinjection(start)
- setfield(start,"char",char)
+ setchar(start,char)
return head, start
end
-- needs testing (side effects):
@@ -541,24 +544,24 @@ local function toligature(kind,lookupname,head,start,stop,char,markflag,discfoun
local prev = getprev(start)
local next = getnext(stop)
local comp = start
- setfield(start,"prev",nil)
- setfield(stop,"next",nil)
+ setprev(start,nil)
+ setnext(stop,nil)
local base = copy_glyph(start)
if start == head then
head = base
end
resetinjection(base)
- setfield(base,"char",char)
- setfield(base,"subtype",ligature_code)
+ setchar(base,char)
+ setsubtype(base,ligature_code)
setfield(base,"components",comp) -- start can have components ... do we need to flush?
if prev then
- setfield(prev,"next",base)
+ setnext(prev,base)
end
if next then
- setfield(next,"prev",base)
+ setprev(next,base)
end
- setfield(base,"prev",prev)
- setfield(base,"next",next)
+ setprev(base,prev)
+ setnext(base,next)
if not discfound then
local deletemarks = markflag ~= "mark"
local components = start
@@ -602,8 +605,8 @@ local function toligature(kind,lookupname,head,start,stop,char,markflag,discfoun
end
else
-- discfound ... forget about marks .. probably no scripts that hyphenate and have marks
- local discprev = getfield(discfound,"prev")
- local discnext = getfield(discfound,"next")
+ local discprev = getprev(discfound)
+ local discnext = getnext(discfound)
if discprev and discnext then
-- we assume normalization in context, and don't care about generic ... especially
-- \- can give problems as there we can have a negative char but that won't match
@@ -612,34 +615,34 @@ local function toligature(kind,lookupname,head,start,stop,char,markflag,discfoun
local post = getfield(discfound,"post")
local replace = getfield(discfound,"replace")
if not replace then -- todo: signal simple hyphen
- local prev = getfield(base,"prev")
+ local prev = getprev(base)
local copied = copy_node_list(comp)
- setfield(discnext,"prev",nil) -- also blocks funny assignments
- setfield(discprev,"next",nil) -- also blocks funny assignments
+ setprev(discnext,nil) -- also blocks funny assignments
+ setnext(discprev,nil) -- also blocks funny assignments
if pre then
- setfield(discprev,"next",pre)
- setfield(pre,"prev",discprev)
+ setnext(discprev,pre)
+ setprev(pre,discprev)
end
pre = comp
if post then
local tail = find_node_tail(post)
- setfield(tail,"next",discnext)
- setfield(discnext,"prev",tail)
- setfield(post,"prev",nil)
+ setnext(tail,discnext)
+ setprev(discnext,tail)
+ setprev(post,nil)
else
post = discnext
end
- setfield(prev,"next",discfound)
- setfield(discfound,"prev",prev)
- setfield(discfound,"next",next)
- setfield(next,"prev",discfound)
- setfield(base,"next",nil)
- setfield(base,"prev",nil)
+ setnext(prev,discfound)
+ setprev(discfound,prev)
+ setnext(discfound,next)
+ setprev(next,discfound)
+ setnext(base,nil)
+ setprev(base,nil)
setfield(base,"components",copied)
setfield(discfound,"pre",pre)
setfield(discfound,"post",post)
setfield(discfound,"replace",base)
- setfield(discfound,"subtype",discretionary_code)
+ setsubtype(discfound,discretionary_code)
base = prev -- restart
end
end
@@ -651,7 +654,7 @@ local function multiple_glyphs(head,start,multiple,ignoremarks)
local nofmultiples = #multiple
if nofmultiples > 0 then
resetinjection(start)
- setfield(start,"char",multiple[1])
+ setchar(start,multiple[1])
if nofmultiples > 1 then
local sn = getnext(start)
for k=2,nofmultiples do -- todo: use insert_node
@@ -662,13 +665,13 @@ local function multiple_glyphs(head,start,multiple,ignoremarks)
-- end
local n = copy_node(start) -- ignore components
resetinjection(n)
- setfield(n,"char",multiple[k])
- setfield(n,"prev",start)
- setfield(n,"next",sn)
+ setchar(n,multiple[k])
+ setprev(n,start)
+ setnext(n,sn)
if sn then
- setfield(sn,"prev",n)
+ setprev(sn,n)
end
- setfield(start,"next",n)
+ setnext(start,n)
start = n
end
end
@@ -720,7 +723,7 @@ function handlers.gsub_single(head,start,kind,lookupname,replacement)
logprocess("%s: replacing %s by single %s",pref(kind,lookupname),gref(getchar(start)),gref(replacement))
end
resetinjection(start)
- setfield(start,"char",replacement)
+ setchar(start,replacement)
return head, start, true
end
@@ -732,7 +735,7 @@ function handlers.gsub_alternate(head,start,kind,lookupname,alternative,sequence
logprocess("%s: replacing %s by alternative %a to %s, %s",pref(kind,lookupname),gref(getchar(start)),choice,gref(choice),comment)
end
resetinjection(start)
- setfield(start,"char",choice)
+ setchar(start,choice)
else
if trace_alternatives then
logwarning("%s: no variant %a for %s, %s",pref(kind,lookupname),value,gref(getchar(start)),comment)
@@ -830,7 +833,7 @@ function handlers.gsub_ligature(head,start,kind,lookupname,ligature,sequence)
else
-- weird but happens (in some arabic font)
resetinjection(start)
- setfield(start,"char",lig)
+ setchar(start,lig)
if trace_ligatures then
logprocess("%s: replacing %s by (no real) ligature %s case 3",pref(kind,lookupname),gref(startchar),gref(lig))
end
@@ -1207,7 +1210,7 @@ function chainprocs.reversesub(head,start,stop,kind,chainname,currentcontext,loo
logprocess("%s: single reverse replacement of %s by %s",cref(kind,chainname),gref(char),gref(replacement))
end
resetinjection(start)
- setfield(start,"char",replacement)
+ setchar(start,replacement)
return head, start, true
else
return head, start, false
@@ -1238,7 +1241,7 @@ as less as needed but that would also make the code even more messy.</p>
-- repeat -- start x x m x x stop => start m
-- local next = getnext(start)
-- if not marks[getchar(next)] then
--- local components = getfield(next,"components")
+-- local components = getnext(next,"components")
-- if components then -- probably not needed
-- flush_node_list(components)
-- end
@@ -1291,7 +1294,7 @@ function chainprocs.gsub_single(head,start,stop,kind,chainname,currentcontext,lo
logprocess("%s: replacing single %s by %s",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(currentchar),gref(replacement))
end
resetinjection(current)
- setfield(current,"char",replacement)
+ setchar(current,replacement)
end
end
return head, start, true
@@ -1368,7 +1371,7 @@ function chainprocs.gsub_alternate(head,start,stop,kind,chainname,currentcontext
logprocess("%s: replacing %s by alternative %a to %s, %s",cref(kind,chainname,chainlookupname,lookupname),gref(char),choice,gref(choice),comment)
end
resetinjection(start)
- setfield(start,"char",choice)
+ setchar(start,choice)
else
if trace_alternatives then
logwarning("%s: no variant %a for %s, %s",cref(kind,chainname,chainlookupname,lookupname),value,gref(char),comment)
@@ -1936,13 +1939,13 @@ local function chaindisk(head,start,last,kind,chainname,ck,lookuphash,chainlooku
local tail = nil
if prev then
tail = prev
- setfield(current,"prev",sweepnode)
+ setprev(current,sweepnode)
else
tail = find_node_tail(head)
end
- setfield(sweepnode,"next",current)
- setfield(head,"prev",nil)
- setfield(tail,"next",nil)
+ setnext(sweepnode,current)
+ setprev(head,nil)
+ setnext(tail,nil)
appenddisc(sweepnode,head)
end
end
@@ -2036,12 +2039,12 @@ local function chaindisk(head,start,last,kind,chainname,ck,lookuphash,chainlooku
cprev = getprev(cprev)
end
- setfield(lookaheaddisc,"prev",cprev)
+ setprev(lookaheaddisc,cprev)
if cprev then
- setfield(cprev,"next",lookaheaddisc)
+ setnext(cprev,lookaheaddisc)
end
- setfield(cf,"prev",nil)
- setfield(cl,"next",nil)
+ setprev(cf,nil)
+ setnext(cl,nil)
if startishead then
head = lookaheaddisc
end
@@ -2064,13 +2067,13 @@ local function chaindisk(head,start,last,kind,chainname,ck,lookuphash,chainlooku
new, cnew, ok = chainproc(new,cnew,clast,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence)
end
if pre then
- setfield(cl,"next",pre)
- setfield(pre,"prev",cl)
+ setnext(cl,pre)
+ setprev(pre,cl)
end
if replace then
local tail = find_node_tail(new)
- setfield(tail,"next",replace)
- setfield(replace,"prev",tail)
+ setnext(tail,replace)
+ setprev(replace,tail)
end
setfield(lookaheaddisc,"pre",cf) -- also updates tail
setfield(lookaheaddisc,"replace",new) -- also updates tail
@@ -2092,11 +2095,11 @@ local function chaindisk(head,start,last,kind,chainname,ck,lookuphash,chainlooku
cnext = getnext(cnext)
end
if cnext then
- setfield(cnext,"prev",backtrackdisc)
+ setprev(cnext,backtrackdisc)
end
- setfield(backtrackdisc,"next",cnext)
- setfield(cf,"prev",nil)
- setfield(cl,"next",nil)
+ setnext(backtrackdisc,cnext)
+ setprev(cf,nil)
+ setnext(cl,nil)
local replace = getfield(backtrackdisc,"replace")
local post = getfield(backtrackdisc,"post")
local new = copy_node_list(cf)
@@ -2116,15 +2119,15 @@ local function chaindisk(head,start,last,kind,chainname,ck,lookuphash,chainlooku
end
if post then
local tail = find_node_tail(post)
- setfield(tail,"next",cf)
- setfield(cf,"prev",tail)
+ setnext(tail,cf)
+ setprev(cf,tail)
else
post = cf
end
if replace then
local tail = find_node_tail(replace)
- setfield(tail,"next",new)
- setfield(new,"prev",tail)
+ setnext(tail,new)
+ setprev(new,tail)
else
replace = new
end
@@ -2700,26 +2703,49 @@ otf.chainhandlers = {
verbose = verbose_handle_contextchain,
}
+local handle_contextchain = nil
+
+-- normal_handle_contextchain(head,start,kind,chainname,contexts,sequence,lookuphash)
+
+function chained_contextchain(head,start,stop,...)
+ local steps = currentlookup.steps
+ local nofsteps = currentlookup.nofsteps
+ if nofsteps > 1 then
+ reportmoresteps(dataset,sequence)
+ end
+ return handle_contextchain(head,start,...)
+end
+
function otf.setcontextchain(method)
if not method or method == "normal" or not otf.chainhandlers[method] then
- if handlers.contextchain then -- no need for a message while making the format
+ if handle_contextchain then -- no need for a message while making the format
logwarning("installing normal contextchain handler")
end
- handlers.contextchain = normal_handle_contextchain
+ handle_contextchain = normal_handle_contextchain
else
logwarning("installing contextchain handler %a",method)
local handler = otf.chainhandlers[method]
- handlers.contextchain = function(...)
+ handle_contextchain = function(...)
return handler(currentfont,...) -- hm, get rid of ...
end
end
- handlers.gsub_context = handlers.contextchain
- handlers.gsub_contextchain = handlers.contextchain
- handlers.gsub_reversecontextchain = handlers.contextchain
- handlers.gpos_contextchain = handlers.contextchain
- handlers.gpos_context = handlers.contextchain
+
+ handlers.gsub_context = handle_contextchain
+ handlers.gsub_contextchain = handle_contextchain
+ handlers.gsub_reversecontextchain = handle_contextchain
+ handlers.gpos_contextchain = handle_contextchain
+ handlers.gpos_context = handle_contextchain
+
+ handlers.contextchain = handle_contextchain
+
end
+chainprocs.gsub_context = chained_contextchain
+chainprocs.gsub_contextchain = chained_contextchain
+chainprocs.gsub_reversecontextchain = chained_contextchain
+chainprocs.gpos_contextchain = chained_contextchain
+chainprocs.gpos_context = chained_contextchain
+
otf.setcontextchain()
local missing = { } -- we only report once
@@ -2759,20 +2785,33 @@ end)
-- fonts.hashes.lookups = lookuphashes
-local autofeatures = fonts.analyzers.features -- was: constants
+local autofeatures = fonts.analyzers.features
+local featuretypes = otf.tables.featuretypes
+local defaultscript = otf.features.checkeddefaultscript
+local defaultlanguage = otf.features.checkeddefaultlanguage
-local function initialize(sequence,script,language,enabled)
+local function initialize(sequence,script,language,enabled,autoscript,autolanguage)
local features = sequence.features
if features then
local order = sequence.order
if order then
- for i=1,#order do --
- local kind = order[i] --
+ local featuretype = featuretypes[sequence.type or "unknown"]
+ for i=1,#order do
+ local kind = order[i]
local valid = enabled[kind]
if valid then
- local scripts = features[kind] --
- local languages = scripts[script] or scripts[wildcard]
- if languages and (languages[language] or languages[wildcard]) then
+ local scripts = features[kind]
+ local languages = scripts and (
+ scripts[script] or
+ scripts[wildcard] or
+ (autoscript and defaultscript(featuretype,autoscript,scripts))
+ )
+ local enabled = languages and (
+ languages[language] or
+ languages[wildcard] or
+ (autolanguage and defaultlanguage(featuretype,autolanguage,languages))
+ )
+ if enabled then
return { valid, autofeatures[kind] or false, sequence, kind }
end
end
@@ -2785,11 +2824,13 @@ local function initialize(sequence,script,language,enabled)
end
function otf.dataset(tfmdata,font) -- generic variant, overloaded in context
- local shared = tfmdata.shared
- local properties = tfmdata.properties
- local language = properties.language or "dflt"
- local script = properties.script or "dflt"
- local enabled = shared.features
+ local shared = tfmdata.shared
+ local properties = tfmdata.properties
+ local language = properties.language or "dflt"
+ local script = properties.script or "dflt"
+ local enabled = shared.features
+ local autoscript = enabled and enabled.autoscript
+ local autolanguage = enabled and enabled.autolanguage
local res = resolved[font]
if not res then
res = { }
@@ -2808,7 +2849,7 @@ function otf.dataset(tfmdata,font) -- generic variant, overloaded in context
rs[language] = rl
local sequences = tfmdata.resources.sequences
for s=1,#sequences do
- local v = enabled and initialize(sequences[s],script,language,enabled)
+ local v = enabled and initialize(sequences[s],script,language,enabled,autoscript,autolanguage)
if v then
rl[#rl+1] = v
end
@@ -2856,11 +2897,11 @@ local function kernrun(disc,run)
-- go on
elseif prev then
local nest = getprev(pre)
- setfield(pre,"prev",prev)
- setfield(prev,"next",pre)
+ setprev(pre,prev)
+ setnext(prev,pre)
run(prevmarks,"preinjections")
- setfield(pre,"prev",nest)
- setfield(prev,"next",disc)
+ setprev(pre,nest)
+ setnext(prev,disc)
else
run(pre,"preinjections")
end
@@ -2869,48 +2910,48 @@ local function kernrun(disc,run)
-- go on
elseif next then
local tail = find_node_tail(post)
- setfield(tail,"next",next)
- setfield(next,"prev",tail)
+ setnext(tail,next)
+ setprev(next,tail)
run(post,"postinjections",next)
- setfield(tail,"next",nil)
- setfield(next,"prev",disc)
+ setnext(tail,nil)
+ setprev(next,disc)
else
run(post,"postinjections")
end
--
if not replace and prev and next then
-- this should be already done by discfound
- setfield(prev,"next",next)
- setfield(next,"prev",prev)
+ setnext(prev,next)
+ setprev(next,prev)
run(prevmarks,"injections",next)
- setfield(prev,"next",disc)
- setfield(next,"prev",disc)
+ setnext(prev,disc)
+ setprev(next,disc)
elseif prev and next then
local tail = find_node_tail(replace)
local nest = getprev(replace)
- setfield(replace,"prev",prev)
- setfield(prev,"next",replace)
- setfield(tail,"next",next)
- setfield(next,"prev",tail)
+ setprev(replace,prev)
+ setnext(prev,replace)
+ setnext(tail,next)
+ setprev(next,tail)
run(prevmarks,"replaceinjections",next)
- setfield(replace,"prev",nest)
- setfield(prev,"next",disc)
- setfield(tail,"next",nil)
- setfield(next,"prev",disc)
+ setprev(replace,nest)
+ setnext(prev,disc)
+ setnext(tail,nil)
+ setprev(next,disc)
elseif prev then
local nest = getprev(replace)
- setfield(replace,"prev",prev)
- setfield(prev,"next",replace)
+ setprev(replace,prev)
+ setnext(prev,replace)
run(prevmarks,"replaceinjections")
- setfield(replace,"prev",nest)
- setfield(prev,"next",disc)
+ setprev(replace,nest)
+ setnext(prev,disc)
elseif next then
local tail = find_node_tail(replace)
- setfield(tail,"next",next)
- setfield(next,"prev",tail)
+ setnext(tail,next)
+ setprev(next,tail)
run(replace,"replaceinjections",next)
- setfield(tail,"next",nil)
- setfield(next,"prev",disc)
+ setnext(tail,nil)
+ setprev(next,disc)
else
run(replace,"replaceinjections")
end
@@ -2967,21 +3008,21 @@ local function testrun(disc,trun,crun) -- use helper
-- only look ahead
local tail = find_node_tail(replace)
-- local nest = getprev(replace)
- setfield(tail,"next",next)
- setfield(next,"prev",tail)
+ setnext(tail,next)
+ setprev(next,tail)
if trun(replace,next) then
setfield(disc,"replace",nil) -- beware, side effects of nest so first
- setfield(prev,"next",replace)
- setfield(replace,"prev",prev)
- setfield(next,"prev",tail)
- setfield(tail,"next",next)
- setfield(disc,"prev",nil)
- setfield(disc,"next",nil)
+ setnext(prev,replace)
+ setprev(replace,prev)
+ setprev(next,tail)
+ setnext(tail,next)
+ setprev(disc,nil)
+ setnext(disc,nil)
flush_node_list(disc)
return replace -- restart
else
- setfield(tail,"next",nil)
- setfield(next,"prev",disc)
+ setnext(tail,nil)
+ setprev(next,disc)
end
else
-- weird case
@@ -3003,11 +3044,11 @@ local function discrun(disc,drun,krun)
report_run("disc") -- will be more detailed
end
if next and prev then
- setfield(prev,"next",next)
- -- setfield(next,"prev",prev)
+ setnext(prev,next)
+ -- setprev(next,prev)
drun(prev)
- setfield(prev,"next",disc)
- -- setfield(next,"prev",disc)
+ setnext(prev,disc)
+ -- setprev(next,disc)
end
--
local pre = getfield(disc,"pre")
@@ -3015,11 +3056,11 @@ local function discrun(disc,drun,krun)
-- go on
elseif prev then
local nest = getprev(pre)
- setfield(pre,"prev",prev)
- setfield(prev,"next",pre)
+ setprev(pre,prev)
+ setnext(prev,pre)
krun(prev,"preinjections")
- setfield(pre,"prev",nest)
- setfield(prev,"next",disc)
+ setprev(pre,nest)
+ setnext(prev,disc)
else
krun(pre,"preinjections")
end
@@ -3319,6 +3360,41 @@ local function featuresprocessor(head,font,attr)
end
elseif id == math_code then
start = getnext(end_of_math(start))
+ elseif id == dir_code then
+ local dir = getfield(start,"dir")
+ if dir == "+TLT" then
+ topstack = topstack + 1
+ dirstack[topstack] = dir
+ rlmode = 1
+ elseif dir == "+TRT" then
+ topstack = topstack + 1
+ dirstack[topstack] = dir
+ rlmode = -1
+ elseif dir == "-TLT" or dir == "-TRT" then
+ topstack = topstack - 1
+ rlmode = dirstack[topstack] == "+TRT" and -1 or 1
+ else
+ rlmode = rlparmode
+ end
+ if trace_directions then
+ report_process("directions after txtdir %a: parmode %a, txtmode %a, # stack %a, new dir %a",dir,rlparmode,rlmode,topstack,newdir)
+ end
+ start = getnext(start)
+ elseif id == localpar_code then
+ local dir = getfield(start,"dir")
+ if dir == "TRT" then
+ rlparmode = -1
+ elseif dir == "TLT" then
+ rlparmode = 1
+ else
+ rlparmode = 0
+ end
+ -- one might wonder if the par dir should be looked at, so we might as well drop the next line
+ rlmode = rlparmode
+ if trace_directions then
+ report_process("directions after pardir %a: parmode %a, txtmode %a",dir,rlparmode,rlmode)
+ end
+ start = getnext(start)
else
start = getnext(start)
end
@@ -3554,6 +3630,40 @@ local function featuresprocessor(head,font,attr)
end
elseif id == math_code then
start = getnext(end_of_math(start))
+ elseif id == dir_code then
+ local dir = getfield(start,"dir")
+ if dir == "+TLT" then
+ topstack = topstack + 1
+ dirstack[topstack] = dir
+ rlmode = 1
+ elseif dir == "+TRT" then
+ topstack = topstack + 1
+ dirstack[topstack] = dir
+ rlmode = -1
+ elseif dir == "-TLT" or dir == "-TRT" then
+ topstack = topstack - 1
+ rlmode = dirstack[topstack] == "+TRT" and -1 or 1
+ else
+ rlmode = rlparmode
+ end
+ if trace_directions then
+ report_process("directions after txtdir %a: parmode %a, txtmode %a, # stack %a, new dir %a",dir,rlparmode,rlmode,topstack,newdir)
+ end
+ start = getnext(start)
+ elseif id == localpar_code then
+ local dir = getfield(start,"dir")
+ if dir == "TRT" then
+ rlparmode = -1
+ elseif dir == "TLT" then
+ rlparmode = 1
+ else
+ rlparmode = 0
+ end
+ rlmode = rlparmode
+ if trace_directions then
+ report_process("directions after pardir %a: parmode %a, txtmode %a",dir,rlparmode,rlmode)
+ end
+ start = getnext(start)
else
start = getnext(start)
end
@@ -3723,10 +3833,10 @@ local function split(replacement,original)
return result
end
-local valid = {
- coverage = { chainsub = true, chainpos = true, contextsub = true },
+local valid = { -- does contextpos work?
+ coverage = { chainsub = true, chainpos = true, contextsub = true, contextpos = true },
reversecoverage = { reversesub = true },
- glyphs = { chainsub = true, chainpos = true },
+ glyphs = { chainsub = true, chainpos = true, contextsub = true, contextpos = true },
}
local function prepare_contextchains(tfmdata)
@@ -3784,7 +3894,10 @@ local function prepare_contextchains(tfmdata)
sequence[nofsequences] = after[n]
end
end
+--[[phg-- Hard patch: This crashes, see https://github.com/lualatex/luaotfload/issues/303
if sequence[1] then
+--phg]]--
+ if sequence[start] then
-- Replacements only happen with reverse lookups as they are single only. We
-- could pack them into current (replacement value instead of true) and then
-- use sequence[start] instead but it's somewhat ugly.
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-fonts-def.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-fonts-def.lua
index 0c2f0dbd583..f0941ecdce8 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-fonts-def.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-fonts-def.lua
@@ -1,4 +1,4 @@
-if not modules then modules = { } end modules ['luatex-font-def'] = {
+if not modules then modules = { } end modules ['luatex-fonts-def'] = {
version = 1.001,
comment = "companion to luatex-*.tex",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-fonts-ota.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-fonts-ota.lua
index f083fe09e83..256ead5a570 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-fonts-ota.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-fonts-ota.lua
@@ -1,4 +1,4 @@
-if not modules then modules = { } end modules ['font-otx'] = {
+if not modules then modules = { } end modules ['luatex-fonts-ota'] = {
version = 1.001,
comment = "companion to font-otf.lua (analysing)",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
@@ -24,7 +24,6 @@ local methods = allocate()
analyzers.initializers = initializers
analyzers.methods = methods
-analyzers.useunicodemarks = false
local a_state = attributes.private('state')
@@ -98,8 +97,9 @@ local features = {
pstf = s_pstf,
}
-analyzers.states = states
-analyzers.features = features
+analyzers.states = states
+analyzers.features = features
+analyzers.useunicodemarks = false
-- todo: analyzers per script/lang, cross font, so we need an font id hash -> script
-- e.g. latin -> hyphenate, arab -> 1/2/3 analyze -- its own namespace
@@ -117,7 +117,10 @@ function analyzers.setstate(head,font)
local char = getchar(current)
local d = descriptions[char]
if d then
- if d.class == "mark" or (useunicodemarks and categories[char] == "mn") then
+ if d.class == "mark" then
+ done = true
+ setprop(current,a_state,s_mark)
+ elseif useunicodemarks and categories[char] == "mn" then
done = true
setprop(current,a_state,s_mark)
elseif n == 0 then
@@ -136,7 +139,9 @@ function analyzers.setstate(head,font)
first, last, n = nil, nil, 0
end
elseif id == disc_code then
- -- always in the middle
+ -- always in the middle .. it doesn't make much sense to assign a property
+ -- here ... we might at some point decide to flag the components when present
+ -- but even then it's kind of bogus
setprop(current,a_state,s_medi)
last = current
else -- finish
@@ -213,17 +218,6 @@ registerotffeature {
methods.latn = analyzers.setstate
--- This info eventually can go into char-def and we will have a state
--- table for generic then (unicode recognized all states but in practice
--- only has only
---
--- isolated : isol
--- final : isol_fina
--- medial : isol_fina_medi_init
---
--- so in practice, without analyzer it's rather useless info which is
--- why having it in char-def makes only sense for special purposes (like)
--- like tracing cq. visualizing.
local tatweel = 0x0640
local zwnj = 0x200C
@@ -344,8 +338,6 @@ local medial = { -- isol_fina_medi_init
local arab_warned = { }
--- todo: gref
-
local function warning(current,what)
local char = getchar(current)
if not arab_warned[char] then
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-fonts.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-fonts.lua
index f18ba35db16..2e34fb8015a 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-fonts.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-fonts.lua
@@ -215,9 +215,11 @@ if non_generic_context.luatex_fonts.skip_loading ~= true then
loadmodule('font-oti.lua')
loadmodule('font-otf.lua')
loadmodule('font-otb.lua')
- loadmodule('luatex-fonts-inj.lua') -- normally the same as font-inj.lua
+ ----------('luatex-fonts-inj.lua') -- normally the same as font-inj.lua / beware loadmodule is parsed
+ loadmodule('font-inj.lua')
loadmodule('luatex-fonts-ota.lua')
- loadmodule('luatex-fonts-otn.lua') -- normally the same as font-otn.lua
+ ----------('luatex-fonts-otn.lua') -- normally the same as font-otn.lua / beware loadmodule is parsed
+ loadmodule('font-otn.lua')
loadmodule('font-otp.lua')
loadmodule('luatex-fonts-lua.lua')
loadmodule('font-def.lua') -- this code (stripped) might end up in luatex-fonts-def.lua
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-languages.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-languages.lua
index 1ea8c1fd12a..cecd60c1331 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-languages.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-languages.lua
@@ -16,28 +16,33 @@ function languages.loadpatterns(tag)
if not loaded[tag] then
loaded[tag] = 0
local filename = kpse.find_file("lang-" .. tag .. ".lua")
- if filename and filename == "" then
- print("<unknown language file for: " .. tag .. ">")
+ if not filename or filename == "" then
+ texio.write("<unknown language file for: " .. tag .. ">")
else
local whatever = loadfile(filename)
if type(whatever) == "function" then
whatever = whatever()
if type(whatever) == "table" then
+ texio.write("<language file: " .. tag .. ">")
local characters = whatever.patterns.characters or ""
local patterns = whatever.patterns.data or ""
local exceptions = whatever.exceptions.data or ""
- local language = lang.new()
for b in string.utfvalues(characters) do
+ -- what about uppercase
+-- lang.sethjcode(b,b)
tex.setlccode(b,b)
end
+ local language = lang.new()
lang.patterns(language, patterns)
lang.hyphenation(language, exceptions)
loaded[tag] = lang.id(language)
else
- print("<invalid language table: " .. tag .. ">")
+ texio.write("<invalid language table: " .. tag .. ">")
+ os.exit()
end
else
- print("<invalid language file: " .. tag .. ">")
+ texio.write("<invalid language file: " .. tag .. ">")
+ os.exit()
end
end
end
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-languages.tex b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-languages.tex
index 9778da39a44..a087b30939a 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-languages.tex
+++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-languages.tex
@@ -8,6 +8,8 @@
%D Cf. discussion on \CONTEXT\ list:
+% \savinghyphcodes1
+
\directlua {
dofile(kpse.find_file("luatex-languages.lua","tex"))
}
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-reference.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-reference.lua
index ae366179ce1..46de1d0c070 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-reference.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-reference.lua
@@ -1,6 +1,6 @@
--- merged file : luatex-fonts-merged.lua
--- parent file : luatex-fonts.lua
--- merge date : 11/19/15 19:13:15
+-- merged file : c:/data/develop/context/sources/luatex-fonts-merged.lua
+-- parent file : c:/data/develop/context/sources/luatex-fonts.lua
+-- merge date : 12/21/15 16:29:15
do -- begin closure to overcome local limits and interference
@@ -3901,15 +3901,21 @@ end
nodes={}
nodes.pool={}
nodes.handlers={}
-local nodecodes={} for k,v in next,node.types () do nodecodes[string.gsub(v,"_","")]=k end
-local whatcodes={} for k,v in next,node.whatsits() do whatcodes[string.gsub(v,"_","")]=k end
-local glyphcodes={ [0]="character","glyph","ligature","ghost","left","right" }
-local disccodes={ [0]="discretionary","explicit","automatic","regular","first","second" }
-for i=0,#glyphcodes do glyphcodes[glyphcodes[i]]=i end
-for i=0,#disccodes do disccodes [disccodes [i]]=i end
+local nodecodes={}
+local glyphcodes=node.subtypes("glyph")
+local disccodes=node.subtypes("disc")
+for k,v in next,node.types() do
+ v=string.gsub(v,"_","")
+ nodecodes[k]=v
+ nodecodes[v]=k
+end
+for i=0,#glyphcodes do
+ glyphcodes[glyphcodes[i]]=i
+end
+for i=0,#disccodes do
+ disccodes[disccodes[i]]=i
+end
nodes.nodecodes=nodecodes
-nodes.whatcodes=whatcodes
-nodes.whatsitcodes=whatcodes
nodes.glyphcodes=glyphcodes
nodes.disccodes=disccodes
local free_node=node.free
@@ -3973,7 +3979,6 @@ nodes.traverse_id=node.traverse_id
nodes.slide=node.slide
nodes.vpack=node.vpack
nodes.first_glyph=node.first_glyph
-nodes.first_character=node.first_character
nodes.has_glyph=node.has_glyph or node.first_glyph
nodes.current_attr=node.current_attr
nodes.do_ligature_n=node.do_ligature_n
@@ -4002,13 +4007,27 @@ local setfield=direct.setfield
nuts.getfield=getfield
nuts.setfield=setfield
nuts.getnext=direct.getnext
+nuts.setnext=direct.setnext
nuts.getprev=direct.getprev
+nuts.setprev=direct.setprev
+nuts.getboth=direct.getboth
+nuts.setboth=direct.setboth
nuts.getid=direct.getid
-nuts.getattr=getfield
+nuts.getattr=direct.get_attribute or direct.has_attribute or getfield
nuts.setattr=setfield
nuts.getfont=direct.getfont
+nuts.setfont=direct.setfont
nuts.getsubtype=direct.getsubtype
+nuts.setsubtype=direct.setsubtype or function(n,s) setfield(n,"subtype",s) end
nuts.getchar=direct.getchar
+nuts.setchar=direct.setchar
+nuts.getdisc=direct.getdisc
+nuts.setdisc=direct.setdisc
+nuts.setlink=direct.setlink
+nuts.getlist=direct.getlist
+nuts.setlist=direct.setlist or function(n,l) setfield(n,"list",l) end
+nuts.getleader=direct.getleader
+nuts.setleader=direct.setleader or function(n,l) setfield(n,"leader",l) end
nuts.insert_before=direct.insert_before
nuts.insert_after=direct.insert_after
nuts.delete=direct.delete
@@ -4022,6 +4041,9 @@ nuts.is_node=direct.is_node
nuts.end_of_math=direct.end_of_math
nuts.traverse=direct.traverse
nuts.traverse_id=direct.traverse_id
+nuts.traverse_char=direct.traverse_char
+nuts.ligaturing=direct.ligaturing
+nuts.kerning=direct.kerning
nuts.getprop=nuts.getattr
nuts.setprop=nuts.setattr
local new_nut=direct.new
@@ -7048,8 +7070,9 @@ local fonts=fonts
local constructors=fonts.constructors
local otf=constructors.newhandler("otf")
local otffeatures=constructors.newfeatures("otf")
-local otftables=otf.tables
local registerotffeature=otffeatures.register
+local otftables=otf.tables or {}
+otf.tables=otftables
local allocate=utilities.storage.allocate
registerotffeature {
name="features",
@@ -7113,6 +7136,64 @@ registerotffeature {
node=setscript,
}
}
+otftables.featuretypes=allocate {
+ gpos_single="position",
+ gpos_pair="position",
+ gpos_cursive="position",
+ gpos_mark2base="position",
+ gpos_mark2ligature="position",
+ gpos_mark2mark="position",
+ gpos_context="position",
+ gpos_contextchain="position",
+ gsub_single="substitution",
+ gsub_multiple="substitution",
+ gsub_alternate="substitution",
+ gsub_ligature="substitution",
+ gsub_context="substitution",
+ gsub_contextchain="substitution",
+ gsub_reversecontextchain="substitution",
+ gsub_reversesub="substitution",
+}
+function otffeatures.checkeddefaultscript(featuretype,autoscript,scripts)
+ if featuretype=="position" then
+ local default=scripts.dflt
+ if default then
+ if autoscript=="position" or autoscript==true then
+ return default
+ else
+ report_otf("script feature %s not applied, enable default positioning")
+ end
+ else
+ end
+ elseif featuretype=="substitution" then
+ local default=scripts.dflt
+ if default then
+ if autoscript=="substitution" or autoscript==true then
+ return default
+ end
+ end
+ end
+end
+function otffeatures.checkeddefaultlanguage(featuretype,autolanguage,languages)
+ if featuretype=="position" then
+ local default=languages.dflt
+ if default then
+ if autolanguage=="position" or autolanguage==true then
+ return default
+ else
+ report_otf("language feature %s not applied, enable default positioning")
+ end
+ else
+ end
+ elseif featuretype=="substitution" then
+ local default=languages.dflt
+ if default then
+ if autolanguage=="substitution" or autolanguage==true then
+ return default
+ end
+ end
+ end
+end
end -- closure
@@ -7156,7 +7237,7 @@ local report_otf=logs.reporter("fonts","otf loading")
local fonts=fonts
local otf=fonts.handlers.otf
otf.glists={ "gsub","gpos" }
-otf.version=2.819
+otf.version=2.820
otf.cache=containers.define("fonts","otf",otf.version,true)
local hashes=fonts.hashes
local definers=fonts.definers
@@ -9492,7 +9573,7 @@ otf.coverup={
kern=justset,
},
register=function(coverage,lookuptype,format,feature,n,descriptions,resources)
- local name=formatters["ctx_%s_%s"](feature,n)
+ local name=formatters["ctx_%s_%s_%s"](feature,lookuptype,n)
if lookuptype=="kern" then
resources.lookuptypes[name]="position"
else
@@ -10224,8 +10305,10 @@ function injections.resetcounts()
end
function injections.reset(n)
local p=rawget(properties,n)
- if p and rawget(p,"injections") then
- p.injections=nil
+ if p then
+ p.injections=false
+ else
+ properties[n]=false
end
end
function injections.copy(target,source)
@@ -10242,10 +10325,17 @@ function injections.copy(target,source)
injections=si,
}
end
+ elseif tp then
+ tp.injections=false
else
- if tp then
- tp.injections=nil
- end
+ properties[target]={ injections={} }
+ end
+ else
+ local tp=rawget(properties,target)
+ if tp then
+ tp.injections=false
+ else
+ properties[target]=false
end
end
end
@@ -10480,10 +10570,11 @@ local function show(n,what,nested,symbol)
local markx=i.markx or 0
local marky=i.marky or 0
local markdir=i.markdir or 0
- local markbase=i.markbase or 0
+ local markbase=i.markbase or 0
local cursivex=i.cursivex or 0
local cursivey=i.cursivey or 0
local ligaindex=i.ligaindex or 0
+ local cursbase=i.cursiveanchor
local margin=nested and 4 or 2
if rightkern~=0 or yoffset~=0 then
report_injections("%w%s pair: lx %p, rx %p, dy %p",margin,symbol,leftkern,rightkern,yoffset)
@@ -10494,7 +10585,13 @@ local function show(n,what,nested,symbol)
report_injections("%w%s mark: dx %p, dy %p, dir %s, base %s",margin,symbol,markx,marky,markdir,markbase~=0 and "yes" or "no")
end
if cursivex~=0 or cursivey~=0 then
- report_injections("%w%s curs: dx %p, dy %p",margin,symbol,cursivex,cursivey)
+ if cursbase then
+ report_injections("%w%s curs: base dx %p, dy %p",margin,symbol,cursivex,cursivey)
+ else
+ report_injections("%w%s curs: dx %p, dy %p",margin,symbol,cursivex,cursivey)
+ end
+ elseif cursbase then
+ report_injections("%w%s curs: base",margin,symbol)
end
if ligaindex~=0 then
report_injections("%w%s liga: index %i",margin,symbol,ligaindex)
@@ -11177,7 +11274,7 @@ end -- closure
do -- begin closure to overcome local limits and interference
-if not modules then modules={} end modules ['font-otx']={
+if not modules then modules={} end modules ['luatex-fonts-ota']={
version=1.001,
comment="companion to font-otf.lua (analysing)",
author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
@@ -11194,7 +11291,6 @@ local initializers=allocate()
local methods=allocate()
analyzers.initializers=initializers
analyzers.methods=methods
-analyzers.useunicodemarks=false
local a_state=attributes.private('state')
local nuts=nodes.nuts
local tonut=nuts.tonut
@@ -11250,6 +11346,7 @@ local features={
}
analyzers.states=states
analyzers.features=features
+analyzers.useunicodemarks=false
function analyzers.setstate(head,font)
local useunicodemarks=analyzers.useunicodemarks
local tfmdata=fontdata[font]
@@ -11263,7 +11360,10 @@ function analyzers.setstate(head,font)
local char=getchar(current)
local d=descriptions[char]
if d then
- if d.class=="mark" or (useunicodemarks and categories[char]=="mn") then
+ if d.class=="mark" then
+ done=true
+ setprop(current,a_state,s_mark)
+ elseif useunicodemarks and categories[char]=="mn" then
done=true
setprop(current,a_state,s_mark)
elseif n==0 then
@@ -11612,7 +11712,9 @@ local tonut=nuts.tonut
local getfield=nuts.getfield
local setfield=nuts.setfield
local getnext=nuts.getnext
+local setnext=nuts.setnext
local getprev=nuts.getprev
+local setprev=nuts.setprev
local getid=nuts.getid
local getattr=nuts.getattr
local setattr=nuts.setattr
@@ -11620,7 +11722,9 @@ local getprop=nuts.getprop
local setprop=nuts.setprop
local getfont=nuts.getfont
local getsubtype=nuts.getsubtype
+local setsubtype=nuts.setsubtype
local getchar=nuts.getchar
+local setchar=nuts.setchar
local insert_node_before=nuts.insert_before
local insert_node_after=nuts.insert_after
local delete_node=nuts.delete
@@ -11639,15 +11743,14 @@ local zwj=0x200D
local wildcard="*"
local default="dflt"
local nodecodes=nodes.nodecodes
-local whatcodes=nodes.whatcodes
local glyphcodes=nodes.glyphcodes
local disccodes=nodes.disccodes
local glyph_code=nodecodes.glyph
local glue_code=nodecodes.glue
local disc_code=nodecodes.disc
local math_code=nodecodes.math
-local dir_code=whatcodes.dir
-local localpar_code=whatcodes.localpar
+local dir_code=nodecodes.dir
+local localpar_code=nodecodes.localpar
local discretionary_code=disccodes.discretionary
local ligature_code=glyphcodes.ligature
local privateattribute=attributes.private
@@ -11767,8 +11870,8 @@ local function flattendisk(head,disc)
if replace then
if next then
local tail=find_node_tail(replace)
- setfield(tail,"next",next)
- setfield(next,"prev",tail)
+ setnext(tail,next)
+ setprev(next,tail)
end
return replace,replace
elseif next then
@@ -11782,17 +11885,17 @@ local function flattendisk(head,disc)
if replace then
local tail=find_node_tail(replace)
if next then
- setfield(tail,"next",next)
- setfield(next,"prev",tail)
+ setnext(tail,next)
+ setprev(next,tail)
end
- setfield(prev,"next",replace)
- setfield(replace,"prev",prev)
+ setnext(prev,replace)
+ setprev(replace,prev)
return head,replace
else
if next then
- setfield(next,"prev",prev)
+ setprev(next,prev)
end
- setfield(prev,"next",next)
+ setnext(prev,next)
return head,next
end
end
@@ -11805,14 +11908,14 @@ local function appenddisc(disc,list)
local ptail=find_node_tail(post)
local rtail=find_node_tail(replace)
if post then
- setfield(ptail,"next",phead)
- setfield(phead,"prev",ptail)
+ setnext(ptail,phead)
+ setprev(phead,ptail)
else
setfield(disc,"post",phead)
end
if replace then
- setfield(rtail,"next",rhead)
- setfield(rhead,"prev",rtail)
+ setnext(rtail,rhead)
+ setprev(rhead,rtail)
else
setfield(disc,"replace",rhead)
end
@@ -11823,24 +11926,24 @@ local function markstoligature(kind,lookupname,head,start,stop,char)
else
local prev=getprev(start)
local next=getnext(stop)
- setfield(start,"prev",nil)
- setfield(stop,"next",nil)
+ setprev(start,nil)
+ setnext(stop,nil)
local base=copy_glyph(start)
if head==start then
head=base
end
resetinjection(base)
- setfield(base,"char",char)
- setfield(base,"subtype",ligature_code)
+ setchar(base,char)
+ setsubtype(base,ligature_code)
setfield(base,"components",start)
if prev then
- setfield(prev,"next",base)
+ setnext(prev,base)
end
if next then
- setfield(next,"prev",base)
+ setprev(next,base)
end
- setfield(base,"next",next)
- setfield(base,"prev",prev)
+ setnext(base,next)
+ setprev(base,prev)
return head,base
end
end
@@ -11868,7 +11971,7 @@ local function toligature(kind,lookupname,head,start,stop,char,markflag,discfoun
end
if start==stop and getchar(start)==char then
resetinjection(start)
- setfield(start,"char",char)
+ setchar(start,char)
return head,start
end
local components=getfield(start,"components")
@@ -11877,24 +11980,24 @@ local function toligature(kind,lookupname,head,start,stop,char,markflag,discfoun
local prev=getprev(start)
local next=getnext(stop)
local comp=start
- setfield(start,"prev",nil)
- setfield(stop,"next",nil)
+ setprev(start,nil)
+ setnext(stop,nil)
local base=copy_glyph(start)
if start==head then
head=base
end
resetinjection(base)
- setfield(base,"char",char)
- setfield(base,"subtype",ligature_code)
+ setchar(base,char)
+ setsubtype(base,ligature_code)
setfield(base,"components",comp)
if prev then
- setfield(prev,"next",base)
+ setnext(prev,base)
end
if next then
- setfield(next,"prev",base)
+ setprev(next,base)
end
- setfield(base,"prev",prev)
- setfield(base,"next",next)
+ setprev(base,prev)
+ setnext(base,next)
if not discfound then
local deletemarks=markflag~="mark"
local components=start
@@ -11934,41 +12037,41 @@ local function toligature(kind,lookupname,head,start,stop,char,markflag,discfoun
start=getnext(start)
end
else
- local discprev=getfield(discfound,"prev")
- local discnext=getfield(discfound,"next")
+ local discprev=getprev(discfound)
+ local discnext=getnext(discfound)
if discprev and discnext then
local pre=getfield(discfound,"pre")
local post=getfield(discfound,"post")
local replace=getfield(discfound,"replace")
if not replace then
- local prev=getfield(base,"prev")
+ local prev=getprev(base)
local copied=copy_node_list(comp)
- setfield(discnext,"prev",nil)
- setfield(discprev,"next",nil)
+ setprev(discnext,nil)
+ setnext(discprev,nil)
if pre then
- setfield(discprev,"next",pre)
- setfield(pre,"prev",discprev)
+ setnext(discprev,pre)
+ setprev(pre,discprev)
end
pre=comp
if post then
local tail=find_node_tail(post)
- setfield(tail,"next",discnext)
- setfield(discnext,"prev",tail)
- setfield(post,"prev",nil)
+ setnext(tail,discnext)
+ setprev(discnext,tail)
+ setprev(post,nil)
else
post=discnext
end
- setfield(prev,"next",discfound)
- setfield(discfound,"prev",prev)
- setfield(discfound,"next",next)
- setfield(next,"prev",discfound)
- setfield(base,"next",nil)
- setfield(base,"prev",nil)
+ setnext(prev,discfound)
+ setprev(discfound,prev)
+ setnext(discfound,next)
+ setprev(next,discfound)
+ setnext(base,nil)
+ setprev(base,nil)
setfield(base,"components",copied)
setfield(discfound,"pre",pre)
setfield(discfound,"post",post)
setfield(discfound,"replace",base)
- setfield(discfound,"subtype",discretionary_code)
+ setsubtype(discfound,discretionary_code)
base=prev
end
end
@@ -11979,19 +12082,19 @@ local function multiple_glyphs(head,start,multiple,ignoremarks)
local nofmultiples=#multiple
if nofmultiples>0 then
resetinjection(start)
- setfield(start,"char",multiple[1])
+ setchar(start,multiple[1])
if nofmultiples>1 then
local sn=getnext(start)
for k=2,nofmultiples do
local n=copy_node(start)
resetinjection(n)
- setfield(n,"char",multiple[k])
- setfield(n,"prev",start)
- setfield(n,"next",sn)
+ setchar(n,multiple[k])
+ setprev(n,start)
+ setnext(n,sn)
if sn then
- setfield(sn,"prev",n)
+ setprev(sn,n)
end
- setfield(start,"next",n)
+ setnext(start,n)
start=n
end
end
@@ -12039,7 +12142,7 @@ function handlers.gsub_single(head,start,kind,lookupname,replacement)
logprocess("%s: replacing %s by single %s",pref(kind,lookupname),gref(getchar(start)),gref(replacement))
end
resetinjection(start)
- setfield(start,"char",replacement)
+ setchar(start,replacement)
return head,start,true
end
function handlers.gsub_alternate(head,start,kind,lookupname,alternative,sequence)
@@ -12050,7 +12153,7 @@ function handlers.gsub_alternate(head,start,kind,lookupname,alternative,sequence
logprocess("%s: replacing %s by alternative %a to %s, %s",pref(kind,lookupname),gref(getchar(start)),choice,gref(choice),comment)
end
resetinjection(start)
- setfield(start,"char",choice)
+ setchar(start,choice)
else
if trace_alternatives then
logwarning("%s: no variant %a for %s, %s",pref(kind,lookupname),value,gref(getchar(start)),comment)
@@ -12144,7 +12247,7 @@ function handlers.gsub_ligature(head,start,kind,lookupname,ligature,sequence)
end
else
resetinjection(start)
- setfield(start,"char",lig)
+ setchar(start,lig)
if trace_ligatures then
logprocess("%s: replacing %s by (no real) ligature %s case 3",pref(kind,lookupname),gref(startchar),gref(lig))
end
@@ -12471,7 +12574,7 @@ function chainprocs.reversesub(head,start,stop,kind,chainname,currentcontext,loo
logprocess("%s: single reverse replacement of %s by %s",cref(kind,chainname),gref(char),gref(replacement))
end
resetinjection(start)
- setfield(start,"char",replacement)
+ setchar(start,replacement)
return head,start,true
else
return head,start,false
@@ -12503,7 +12606,7 @@ function chainprocs.gsub_single(head,start,stop,kind,chainname,currentcontext,lo
logprocess("%s: replacing single %s by %s",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(currentchar),gref(replacement))
end
resetinjection(current)
- setfield(current,"char",replacement)
+ setchar(current,replacement)
end
end
return head,start,true
@@ -12561,7 +12664,7 @@ function chainprocs.gsub_alternate(head,start,stop,kind,chainname,currentcontext
logprocess("%s: replacing %s by alternative %a to %s, %s",cref(kind,chainname,chainlookupname,lookupname),gref(char),choice,gref(choice),comment)
end
resetinjection(start)
- setfield(start,"char",choice)
+ setchar(start,choice)
else
if trace_alternatives then
logwarning("%s: no variant %a for %s, %s",cref(kind,chainname,chainlookupname,lookupname),value,gref(char),comment)
@@ -13056,13 +13159,13 @@ local function chaindisk(head,start,last,kind,chainname,ck,lookuphash,chainlooku
local tail=nil
if prev then
tail=prev
- setfield(current,"prev",sweepnode)
+ setprev(current,sweepnode)
else
tail=find_node_tail(head)
end
- setfield(sweepnode,"next",current)
- setfield(head,"prev",nil)
- setfield(tail,"next",nil)
+ setnext(sweepnode,current)
+ setprev(head,nil)
+ setnext(tail,nil)
appenddisc(sweepnode,head)
end
end
@@ -13150,12 +13253,12 @@ local function chaindisk(head,start,last,kind,chainname,ck,lookuphash,chainlooku
startishead=cf==head
cprev=getprev(cprev)
end
- setfield(lookaheaddisc,"prev",cprev)
+ setprev(lookaheaddisc,cprev)
if cprev then
- setfield(cprev,"next",lookaheaddisc)
+ setnext(cprev,lookaheaddisc)
end
- setfield(cf,"prev",nil)
- setfield(cl,"next",nil)
+ setprev(cf,nil)
+ setnext(cl,nil)
if startishead then
head=lookaheaddisc
end
@@ -13177,13 +13280,13 @@ local function chaindisk(head,start,last,kind,chainname,ck,lookuphash,chainlooku
new,cnew,ok=chainproc(new,cnew,clast,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence)
end
if pre then
- setfield(cl,"next",pre)
- setfield(pre,"prev",cl)
+ setnext(cl,pre)
+ setprev(pre,cl)
end
if replace then
local tail=find_node_tail(new)
- setfield(tail,"next",replace)
- setfield(replace,"prev",tail)
+ setnext(tail,replace)
+ setprev(replace,tail)
end
setfield(lookaheaddisc,"pre",cf)
setfield(lookaheaddisc,"replace",new)
@@ -13201,11 +13304,11 @@ local function chaindisk(head,start,last,kind,chainname,ck,lookuphash,chainlooku
cnext=getnext(cnext)
end
if cnext then
- setfield(cnext,"prev",backtrackdisc)
+ setprev(cnext,backtrackdisc)
end
- setfield(backtrackdisc,"next",cnext)
- setfield(cf,"prev",nil)
- setfield(cl,"next",nil)
+ setnext(backtrackdisc,cnext)
+ setprev(cf,nil)
+ setnext(cl,nil)
local replace=getfield(backtrackdisc,"replace")
local post=getfield(backtrackdisc,"post")
local new=copy_node_list(cf)
@@ -13225,15 +13328,15 @@ local function chaindisk(head,start,last,kind,chainname,ck,lookuphash,chainlooku
end
if post then
local tail=find_node_tail(post)
- setfield(tail,"next",cf)
- setfield(cf,"prev",tail)
+ setnext(tail,cf)
+ setprev(cf,tail)
else
post=cf
end
if replace then
local tail=find_node_tail(replace)
- setfield(tail,"next",new)
- setfield(new,"prev",tail)
+ setnext(tail,new)
+ setprev(new,tail)
else
replace=new
end
@@ -13761,25 +13864,40 @@ otf.chainhandlers={
normal=normal_handle_contextchain,
verbose=verbose_handle_contextchain,
}
+local handle_contextchain=nil
+function chained_contextchain(head,start,stop,...)
+ local steps=currentlookup.steps
+ local nofsteps=currentlookup.nofsteps
+ if nofsteps>1 then
+ reportmoresteps(dataset,sequence)
+ end
+ return handle_contextchain(head,start,...)
+end
function otf.setcontextchain(method)
if not method or method=="normal" or not otf.chainhandlers[method] then
- if handlers.contextchain then
+ if handle_contextchain then
logwarning("installing normal contextchain handler")
end
- handlers.contextchain=normal_handle_contextchain
+ handle_contextchain=normal_handle_contextchain
else
logwarning("installing contextchain handler %a",method)
local handler=otf.chainhandlers[method]
- handlers.contextchain=function(...)
+ handle_contextchain=function(...)
return handler(currentfont,...)
end
end
- handlers.gsub_context=handlers.contextchain
- handlers.gsub_contextchain=handlers.contextchain
- handlers.gsub_reversecontextchain=handlers.contextchain
- handlers.gpos_contextchain=handlers.contextchain
- handlers.gpos_context=handlers.contextchain
+ handlers.gsub_context=handle_contextchain
+ handlers.gsub_contextchain=handle_contextchain
+ handlers.gsub_reversecontextchain=handle_contextchain
+ handlers.gpos_contextchain=handle_contextchain
+ handlers.gpos_context=handle_contextchain
+ handlers.contextchain=handle_contextchain
end
+chainprocs.gsub_context=chained_contextchain
+chainprocs.gsub_contextchain=chained_contextchain
+chainprocs.gsub_reversecontextchain=chained_contextchain
+chainprocs.gpos_contextchain=chained_contextchain
+chainprocs.gpos_context=chained_contextchain
otf.setcontextchain()
local missing={}
local function logprocess(...)
@@ -13807,19 +13925,32 @@ setmetatableindex(lookuphashes,function(t,font)
t[font]=lookuphash
return lookuphash
end)
-local autofeatures=fonts.analyzers.features
-local function initialize(sequence,script,language,enabled)
+local autofeatures=fonts.analyzers.features
+local featuretypes=otf.tables.featuretypes
+local defaultscript=otf.features.checkeddefaultscript
+local defaultlanguage=otf.features.checkeddefaultlanguage
+local function initialize(sequence,script,language,enabled,autoscript,autolanguage)
local features=sequence.features
if features then
local order=sequence.order
if order then
- for i=1,#order do
- local kind=order[i]
+ local featuretype=featuretypes[sequence.type or "unknown"]
+ for i=1,#order do
+ local kind=order[i]
local valid=enabled[kind]
if valid then
- local scripts=features[kind]
- local languages=scripts[script] or scripts[wildcard]
- if languages and (languages[language] or languages[wildcard]) then
+ local scripts=features[kind]
+ local languages=scripts and (
+ scripts[script] or
+ scripts[wildcard] or
+ (autoscript and defaultscript(featuretype,autoscript,scripts))
+ )
+ local enabled=languages and (
+ languages[language] or
+ languages[wildcard] or
+ (autolanguage and defaultlanguage(featuretype,autolanguage,languages))
+ )
+ if enabled then
return { valid,autofeatures[kind] or false,sequence,kind }
end
end
@@ -13835,6 +13966,8 @@ function otf.dataset(tfmdata,font)
local language=properties.language or "dflt"
local script=properties.script or "dflt"
local enabled=shared.features
+ local autoscript=enabled and enabled.autoscript
+ local autolanguage=enabled and enabled.autolanguage
local res=resolved[font]
if not res then
res={}
@@ -13852,7 +13985,7 @@ function otf.dataset(tfmdata,font)
rs[language]=rl
local sequences=tfmdata.resources.sequences
for s=1,#sequences do
- local v=enabled and initialize(sequences[s],script,language,enabled)
+ local v=enabled and initialize(sequences[s],script,language,enabled,autoscript,autolanguage)
if v then
rl[#rl+1]=v
end
@@ -13882,57 +14015,57 @@ local function kernrun(disc,run)
if not pre then
elseif prev then
local nest=getprev(pre)
- setfield(pre,"prev",prev)
- setfield(prev,"next",pre)
+ setprev(pre,prev)
+ setnext(prev,pre)
run(prevmarks,"preinjections")
- setfield(pre,"prev",nest)
- setfield(prev,"next",disc)
+ setprev(pre,nest)
+ setnext(prev,disc)
else
run(pre,"preinjections")
end
if not post then
elseif next then
local tail=find_node_tail(post)
- setfield(tail,"next",next)
- setfield(next,"prev",tail)
+ setnext(tail,next)
+ setprev(next,tail)
run(post,"postinjections",next)
- setfield(tail,"next",nil)
- setfield(next,"prev",disc)
+ setnext(tail,nil)
+ setprev(next,disc)
else
run(post,"postinjections")
end
if not replace and prev and next then
- setfield(prev,"next",next)
- setfield(next,"prev",prev)
+ setnext(prev,next)
+ setprev(next,prev)
run(prevmarks,"injections",next)
- setfield(prev,"next",disc)
- setfield(next,"prev",disc)
+ setnext(prev,disc)
+ setprev(next,disc)
elseif prev and next then
local tail=find_node_tail(replace)
local nest=getprev(replace)
- setfield(replace,"prev",prev)
- setfield(prev,"next",replace)
- setfield(tail,"next",next)
- setfield(next,"prev",tail)
+ setprev(replace,prev)
+ setnext(prev,replace)
+ setnext(tail,next)
+ setprev(next,tail)
run(prevmarks,"replaceinjections",next)
- setfield(replace,"prev",nest)
- setfield(prev,"next",disc)
- setfield(tail,"next",nil)
- setfield(next,"prev",disc)
+ setprev(replace,nest)
+ setnext(prev,disc)
+ setnext(tail,nil)
+ setprev(next,disc)
elseif prev then
local nest=getprev(replace)
- setfield(replace,"prev",prev)
- setfield(prev,"next",replace)
+ setprev(replace,prev)
+ setnext(prev,replace)
run(prevmarks,"replaceinjections")
- setfield(replace,"prev",nest)
- setfield(prev,"next",disc)
+ setprev(replace,nest)
+ setnext(prev,disc)
elseif next then
local tail=find_node_tail(replace)
- setfield(tail,"next",next)
- setfield(next,"prev",tail)
+ setnext(tail,next)
+ setprev(next,tail)
run(replace,"replaceinjections",next)
- setfield(tail,"next",nil)
- setfield(next,"prev",disc)
+ setnext(tail,nil)
+ setprev(next,disc)
else
run(replace,"replaceinjections")
end
@@ -13979,21 +14112,21 @@ local function testrun(disc,trun,crun)
local prev=getprev(disc)
if prev then
local tail=find_node_tail(replace)
- setfield(tail,"next",next)
- setfield(next,"prev",tail)
+ setnext(tail,next)
+ setprev(next,tail)
if trun(replace,next) then
setfield(disc,"replace",nil)
- setfield(prev,"next",replace)
- setfield(replace,"prev",prev)
- setfield(next,"prev",tail)
- setfield(tail,"next",next)
- setfield(disc,"prev",nil)
- setfield(disc,"next",nil)
+ setnext(prev,replace)
+ setprev(replace,prev)
+ setprev(next,tail)
+ setnext(tail,next)
+ setprev(disc,nil)
+ setnext(disc,nil)
flush_node_list(disc)
return replace
else
- setfield(tail,"next",nil)
- setfield(next,"prev",disc)
+ setnext(tail,nil)
+ setprev(next,disc)
end
else
end
@@ -14011,19 +14144,19 @@ local function discrun(disc,drun,krun)
report_run("disc")
end
if next and prev then
- setfield(prev,"next",next)
+ setnext(prev,next)
drun(prev)
- setfield(prev,"next",disc)
+ setnext(prev,disc)
end
local pre=getfield(disc,"pre")
if not pre then
elseif prev then
local nest=getprev(pre)
- setfield(pre,"prev",prev)
- setfield(prev,"next",pre)
+ setprev(pre,prev)
+ setnext(prev,pre)
krun(prev,"preinjections")
- setfield(pre,"prev",nest)
- setfield(prev,"next",disc)
+ setprev(pre,nest)
+ setnext(prev,disc)
else
krun(pre,"preinjections")
end
@@ -14281,6 +14414,40 @@ local function featuresprocessor(head,font,attr)
end
elseif id==math_code then
start=getnext(end_of_math(start))
+ elseif id==dir_code then
+ local dir=getfield(start,"dir")
+ if dir=="+TLT" then
+ topstack=topstack+1
+ dirstack[topstack]=dir
+ rlmode=1
+ elseif dir=="+TRT" then
+ topstack=topstack+1
+ dirstack[topstack]=dir
+ rlmode=-1
+ elseif dir=="-TLT" or dir=="-TRT" then
+ topstack=topstack-1
+ rlmode=dirstack[topstack]=="+TRT" and -1 or 1
+ else
+ rlmode=rlparmode
+ end
+ if trace_directions then
+ report_process("directions after txtdir %a: parmode %a, txtmode %a, # stack %a, new dir %a",dir,rlparmode,rlmode,topstack,newdir)
+ end
+ start=getnext(start)
+ elseif id==localpar_code then
+ local dir=getfield(start,"dir")
+ if dir=="TRT" then
+ rlparmode=-1
+ elseif dir=="TLT" then
+ rlparmode=1
+ else
+ rlparmode=0
+ end
+ rlmode=rlparmode
+ if trace_directions then
+ report_process("directions after pardir %a: parmode %a, txtmode %a",dir,rlparmode,rlmode)
+ end
+ start=getnext(start)
else
start=getnext(start)
end
@@ -14501,6 +14668,40 @@ local function featuresprocessor(head,font,attr)
end
elseif id==math_code then
start=getnext(end_of_math(start))
+ elseif id==dir_code then
+ local dir=getfield(start,"dir")
+ if dir=="+TLT" then
+ topstack=topstack+1
+ dirstack[topstack]=dir
+ rlmode=1
+ elseif dir=="+TRT" then
+ topstack=topstack+1
+ dirstack[topstack]=dir
+ rlmode=-1
+ elseif dir=="-TLT" or dir=="-TRT" then
+ topstack=topstack-1
+ rlmode=dirstack[topstack]=="+TRT" and -1 or 1
+ else
+ rlmode=rlparmode
+ end
+ if trace_directions then
+ report_process("directions after txtdir %a: parmode %a, txtmode %a, # stack %a, new dir %a",dir,rlparmode,rlmode,topstack,newdir)
+ end
+ start=getnext(start)
+ elseif id==localpar_code then
+ local dir=getfield(start,"dir")
+ if dir=="TRT" then
+ rlparmode=-1
+ elseif dir=="TLT" then
+ rlparmode=1
+ else
+ rlparmode=0
+ end
+ rlmode=rlparmode
+ if trace_directions then
+ report_process("directions after pardir %a: parmode %a, txtmode %a",dir,rlparmode,rlmode)
+ end
+ start=getnext(start)
else
start=getnext(start)
end
@@ -14636,10 +14837,10 @@ local function split(replacement,original)
end
return result
end
-local valid={
- coverage={ chainsub=true,chainpos=true,contextsub=true },
+local valid={
+ coverage={ chainsub=true,chainpos=true,contextsub=true,contextpos=true },
reversecoverage={ reversesub=true },
- glyphs={ chainsub=true,chainpos=true },
+ glyphs={ chainsub=true,chainpos=true,contextsub=true,contextpos=true },
}
local function prepare_contextchains(tfmdata)
local rawdata=tfmdata.shared.rawdata
@@ -15952,7 +16153,7 @@ end -- closure
do -- begin closure to overcome local limits and interference
-if not modules then modules={} end modules ['luatex-font-def']={
+if not modules then modules={} end modules ['luatex-fonts-def']={
version=1.001,
comment="companion to luatex-*.tex",
author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-auxiliary.lua b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-auxiliary.lua
index c50e0cdb647..11d3101b7e4 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-auxiliary.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-auxiliary.lua
@@ -15,7 +15,7 @@ luaotfload.aux = luaotfload.aux or { }
local aux = luaotfload.aux
local log = luaotfload.log
-local report = log.report
+local logreport = log.report
local fonthashes = fonts.hashes
local encodings = fonts.encodings
local identifiers = fonthashes.identifiers
@@ -54,8 +54,8 @@ local start_rewrite_fontname = function ()
rewrite_fontname,
"luaotfload.rewrite_fontname")
rewriting = true
- report ("log", 1, "aux",
- "start rewriting tfmdata.name field")
+ logreport ("log", 1, "aux",
+ "start rewriting tfmdata.name field")
end
end
@@ -66,8 +66,8 @@ local stop_rewrite_fontname = function ()
luatexbase.remove_from_callback
("luaotfload.patch_font", "luaotfload.rewrite_fontname")
rewriting = false
- report ("log", 1, "aux",
- "stop rewriting tfmdata.name field")
+ logreport ("log", 1, "aux",
+ "stop rewriting tfmdata.name field")
end
end
@@ -393,7 +393,7 @@ do
local load_chardef = function ()
- report ("both", 1, "aux", "Loading character metadata from %s.", chardef)
+ logreport ("both", 1, "aux", "Loading character metadata from %s.", chardef)
chardata = dofile (kpse.find_file (chardef, "lua"))
if chardata == nil then
@@ -452,18 +452,18 @@ local provides_script = function (font_id, asked_script)
--- where method: "gpos" | "gsub"
for feature, data in next, featuredata do
if data[asked_script] then
- report ("log", 1, "aux",
- "font no %d (%s) defines feature %s for script %s",
- font_id, fontname, feature, asked_script)
+ logreport ("log", 1, "aux",
+ "font no %d (%s) defines feature %s for script %s",
+ font_id, fontname, feature, asked_script)
return true
end
end
end
- report ("log", 0, "aux",
- "font no %d (%s) defines no feature for script %s",
- font_id, fontname, asked_script)
+ logreport ("log", 0, "aux",
+ "font no %d (%s) defines no feature for script %s",
+ font_id, fontname, asked_script)
end
- report ("log", 0, "aux", "no font with id %d", font_id)
+ logreport ("log", 0, "aux", "no font with id %d", font_id)
return false
end
@@ -491,21 +491,21 @@ local provides_language = function (font_id, asked_script, asked_language)
for feature, data in next, featuredata do
local scriptdata = data[asked_script]
if scriptdata and scriptdata[asked_language] then
- report ("log", 1, "aux",
- "font no %d (%s) defines feature %s "
- .. "for script %s with language %s",
- font_id, fontname, feature,
- asked_script, asked_language)
+ logreport ("log", 1, "aux",
+ "font no %d (%s) defines feature %s "
+ .. "for script %s with language %s",
+ font_id, fontname, feature,
+ asked_script, asked_language)
return true
end
end
end
- report ("log", 0, "aux",
- "font no %d (%s) defines no feature "
- .. "for script %s with language %s",
- font_id, fontname, asked_script, asked_language)
+ logreport ("log", 0, "aux",
+ "font no %d (%s) defines no feature "
+ .. "for script %s with language %s",
+ font_id, fontname, asked_script, asked_language)
end
- report ("log", 0, "aux", "no font with id %d", font_id)
+ logreport ("log", 0, "aux", "no font with id %d", font_id)
return false
end
@@ -564,20 +564,20 @@ local provides_feature = function (font_id, asked_script,
if feature then
local scriptdata = feature[asked_script]
if scriptdata and scriptdata[asked_language] then
- report ("log", 1, "aux",
- "font no %d (%s) defines feature %s "
- .. "for script %s with language %s",
- font_id, fontname, asked_feature,
- asked_script, asked_language)
+ logreport ("log", 1, "aux",
+ "font no %d (%s) defines feature %s "
+ .. "for script %s with language %s",
+ font_id, fontname, asked_feature,
+ asked_script, asked_language)
return true
end
end
end
- report ("log", 0, "aux",
- "font no %d (%s) does not define feature %s for script %s with language %s",
- font_id, fontname, asked_feature, asked_script, asked_language)
+ logreport ("log", 0, "aux",
+ "font no %d (%s) does not define feature %s for script %s with language %s",
+ font_id, fontname, asked_feature, asked_script, asked_language)
end
- report ("log", 0, "aux", "no font with id %d", font_id)
+ logreport ("log", 0, "aux", "no font with id %d", font_id)
return false
end
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-features.lua b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-features.lua
index 962806cc163..8ffc030d15d 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-features.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-features.lua
@@ -938,18 +938,40 @@ local report_otf = logs.reporter("fonts","otf loading")
--HH]]--
+--- start locals for addfeature()
+
+local utfbyte = unicode.utf8.byte
+local utfchar = unicode.utf8.char
+
+local otf = handlers and handlers.otf --- filled in later during initialization
+
+local normalized = {
+ substitution = "substitution",
+ single = "substitution",
+ ligature = "ligature",
+ alternate = "alternate",
+ multiple = "multiple",
+ kern = "kern",
+}
+
local types = {
substitution = "gsub_single",
ligature = "gsub_ligature",
alternate = "gsub_alternate",
+ multiple = "gsub_multiple",
+ kern = "gpos_pair",
}
setmetatableindex(types, function(t,k) t[k] = k return k end) -- "key"
+--- stop locals for addfeature()
+
local everywhere = { ["*"] = { ["*"] = true } } -- or: { ["*"] = { "*" } }
-local noflags = { }
+local noflags = { }
-local function addfeature (data, feature, specifications)
+local tohash = table.tohash
+
+local function ancient_addfeature (data, feature, specifications)
local descriptions = data.descriptions
local resources = data.resources
local lookups = resources.lookups
@@ -1089,6 +1111,250 @@ local function addfeature (data, feature, specifications)
end
end
+local function current_addfeature(data,feature,specifications)
+ local descriptions = data.descriptions
+ local resources = data.resources
+ local features = resources.features
+ local sequences = resources.sequences
+ if not features or not sequences then
+ return
+ end
+ local gsubfeatures = features.gsub
+ if gsubfeatures and gsubfeatures[feature] then
+ return -- already present
+ end
+ local fontfeatures = resources.features or everywhere
+ local unicodes = resources.unicodes
+ local splitter = lpeg.splitter(" ",unicodes)
+ local done = 0
+ local skip = 0
+ if not specifications[1] then
+ -- so we accept a one entry specification
+ specifications = { specifications }
+ end
+
+ local function tounicode(code)
+ if not code then
+ return
+ elseif type(code) == "number" then
+ return code
+ else
+ return unicodes[code] or utfbyte(code)
+ end
+ end
+
+ local coverup = otf.coverup
+ local coveractions = coverup.actions
+ local stepkey = coverup.stepkey
+ local register = coverup.register
+
+ for s=1,#specifications do
+ local specification = specifications[s]
+ local valid = specification.valid
+ if not valid or valid(data,specification,feature) then
+ local initialize = specification.initialize
+ if initialize then
+ -- when false is returned we initialize only once
+ specification.initialize = initialize(specification,data) and initialize or nil
+ end
+ local askedfeatures = specification.features or everywhere
+ local askedsteps = specifications.steps or specification.subtables or { specification.data } or { }
+ local featuretype = normalized[specification.type or "substitution"] or "substitution"
+ local featureflags = specification.flags or noflags
+ local featureorder = specification.order or { feature }
+ local added = false
+ local nofsteps = 0
+ local steps = { }
+ for i=1,#askedsteps do
+ local list = askedsteps[i]
+ local coverage = { }
+ local cover = coveractions[featuretype]
+ local format = nil
+ if not cover then
+ -- unknown
+ elseif featuretype == "substitution" then
+ for code, replacement in next, list do
+ local unicode = tounicode(code)
+ local description = descriptions[unicode]
+ if description then
+ if type(replacement) == "table" then
+ replacement = replacement[1]
+ end
+ replacement = tounicode(replacement)
+ if replacement and descriptions[replacement] then
+ cover(coverage,unicode,replacement)
+ done = done + 1
+ else
+ skip = skip + 1
+ end
+ else
+ skip = skip + 1
+ end
+ end
+ elseif featuretype == "ligature" then
+ for code, ligature in next, list do
+ local unicode = tounicode(code)
+ local description = descriptions[unicode]
+ if description then
+ if type(ligature) == "string" then
+ ligature = { lpegmatch(splitter,ligature) }
+ end
+ local present = true
+ for i=1,#ligature do
+ local l = ligature[i]
+ local u = tounicode(l)
+ if descriptions[u] then
+ ligature[i] = u
+ else
+ present = false
+ break
+ end
+ end
+ if present then
+ cover(coverage,unicode,ligature)
+ done = done + 1
+ else
+ skip = skip + 1
+ end
+ else
+ skip = skip + 1
+ end
+ end
+ elseif featuretype == "alternate" then
+ for code, replacement in next, list do
+ local unicode = tounicode(code)
+ local description = descriptions[unicode]
+ if not description then
+ skip = skip + 1
+ elseif type(replacement) == "table" then
+ local r = { }
+ for i=1,#replacement do
+ local u = tounicode(replacement[i])
+ r[i] = descriptions[u] and u or unicode
+ end
+ cover(coverage,unicode,r)
+ done = done + 1
+ else
+ local u = tounicode(replacement)
+ if u then
+ cover(coverage,unicode,{ u })
+ done = done + 1
+ else
+ skip = skip + 1
+ end
+ end
+ end
+ elseif featuretype == "multiple" then -- todo: unicode can be table
+ for code, replacement in next, list do
+ local unicode = tounicode(code)
+ local description = descriptions[unicode]
+ if not description then
+ skip = skip + 1
+ elseif type(replacement) == "table" then
+ local r, n = { }, 0
+ for i=1,#replacement do
+ local u = tounicode(replacement[i])
+ if descriptions[u] then
+ n = n + 1
+ r[n] = u
+ end
+ end
+ if n > 0 then
+ cover(coverage,unicode,r)
+ done = done + 1
+ else
+ skip = skip + 1
+ end
+ else
+ local u = tounicode(replacement)
+ if u then
+ cover(coverage,unicode,{ u })
+ done = done + 1
+ else
+ skip = skip + 1
+ end
+ end
+ end
+ elseif featuretype == "kern" then
+ for code, replacement in next, list do
+ local unicode = tounicode(code)
+ local description = descriptions[unicode]
+ if description and type(replacement) == "table" then
+ local r = { }
+ for k, v in next, replacement do
+ local u = tounicode(k)
+ if u then
+ r[u] = v
+ end
+ end
+ if next(r) then
+ cover(coverage,unicode,r)
+ done = done + 1
+ else
+ skip = skip + 1
+ end
+ else
+ skip = skip + 1
+ end
+ end
+ format = "kern"
+ end
+ if next(coverage) then
+ added = true
+ nofsteps = nofsteps + 1
+ steps[nofsteps] = register(coverage,featuretype,format,feature,nofsteps,descriptions,resources)
+ end
+ end
+ if added then
+ -- script = { lang1, lang2, lang3 } or script = { lang1 = true, ... }
+ for k, v in next, askedfeatures do
+ if v[1] then
+ askedfeatures[k] = tohash(v)
+ end
+ end
+ local sequence = {
+ chain = 0,
+ features = { [feature] = askedfeatures },
+ flags = featureflags,
+ name = feature, -- not needed
+ order = featureorder,
+ [stepkey] = steps,
+ nofsteps = nofsteps,
+ type = types[featuretype],
+ }
+ if specification.prepend then
+ insert(sequences,1,sequence)
+ else
+ insert(sequences,sequence)
+ end
+ -- register in metadata (merge as there can be a few)
+ if not gsubfeatures then
+ gsubfeatures = { }
+ fontfeatures.gsub = gsubfeatures
+ end
+ local k = gsubfeatures[feature]
+ if not k then
+ k = { }
+ gsubfeatures[feature] = k
+ end
+ for script, languages in next, askedfeatures do
+ local kk = k[script]
+ if not kk then
+ kk = { }
+ k[script] = kk
+ end
+ for language, value in next, languages do
+ kk[language] = value
+ end
+ end
+ end
+ end
+ end
+ if trace_loading then
+ report_otf("registering feature %a, affected glyphs %a, skipped glyphs %a",feature,done,skip)
+ end
+end
+
---[[ end snippet from font-otc.lua ]]
local tlig_specification = {
@@ -1100,7 +1366,7 @@ local tlig_specification = {
[0x0027] = 0x2019, -- quoteleft
[0x0060] = 0x2018, -- quoteright
},
- flags = { },
+ flags = noflags,
order = { "tlig" },
prepend = true,
},
@@ -1120,7 +1386,7 @@ local tlig_specification = {
[0x00AB] = {0x003C, 0x003C}, -- LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
[0x00BB] = {0x003E, 0x003E}, -- RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
},
- flags = { },
+ flags = noflags,
order = { "tlig" },
prepend = true,
},
@@ -1133,12 +1399,25 @@ local tlig_specification = {
[0x00A1] = {0x0021, 0x0060}, -- exclamdown
[0x00BF] = {0x003F, 0x0060}, -- questiondown
},
- flags = { },
+ flags = noflags,
order = { "tlig" },
prepend = true,
},
}
+local tlig_specification = {
+ type = "substitution",
+ features = everywhere,
+ data = {
+ [0x0022] = 0x201D, -- quotedblright
+ [0x0027] = 0x2019, -- quoteleft
+ [0x0060] = 0x2018, -- quoteright
+ },
+ flags = noflags,
+ order = { "tlig" },
+ prepend = true,
+}
+
local anum_arabic = { --- these are the same as in font-otc
[0x0030] = 0x0660,
[0x0031] = 0x0661,
@@ -1183,7 +1462,7 @@ local anum_specification = {
type = "substitution",
features = { arab = { far = true, urd = true, snd = true } },
data = anum_persian,
- flags = { },
+ flags = noflags,
order = { "anum" },
valid = valid,
},
@@ -1191,49 +1470,86 @@ local anum_specification = {
type = "substitution",
features = { arab = { ["*"] = true } },
data = anum_arabic,
- flags = { },
+ flags = noflags,
order = { "anum" },
valid = valid,
},
}
+local rot13_specification = {
+ type = "substitution",
+ features = everywhere,
+ data = {
+ [65] = 78, [ 97] = 110, [78] = 65, [110] = 97,
+ [66] = 79, [ 98] = 111, [79] = 66, [111] = 98,
+ [67] = 80, [ 99] = 112, [80] = 67, [112] = 99,
+ [68] = 81, [100] = 113, [81] = 68, [113] = 100,
+ [69] = 82, [101] = 114, [82] = 69, [114] = 101,
+ [70] = 83, [102] = 115, [83] = 70, [115] = 102,
+ [71] = 84, [103] = 116, [84] = 71, [116] = 103,
+ [72] = 85, [104] = 117, [85] = 72, [117] = 104,
+ [73] = 86, [105] = 118, [86] = 73, [118] = 105,
+ [74] = 87, [106] = 119, [87] = 74, [119] = 106,
+ [75] = 88, [107] = 120, [88] = 75, [120] = 107,
+ [76] = 89, [108] = 121, [89] = 76, [121] = 108,
+ [77] = 90, [109] = 122, [90] = 77, [122] = 109,
+ },
+ flags = noflags,
+ order = { "rot13" },
+ prepend = true,
+}
+
+local extrafeatures = {
+ tlig = { tlig_specification, "tex ligatures and substitutions" },
+ anum = { anum_specification, "arabic numerals" },
+ rot13 = { rot13_specification, "rot13" },
+}
+
+function add_otf_feature (name, specification)
+ if type (name) == "table" then
+ specification = name
+ name = specification.name
+ end
+ if type (name) == "string" then
+ extrafeatures[name] = specification
+ end
+end
+
+otf.addfeature = add_otf_feature
+
+local install_extra_features = function (data, filename, raw)
+ for feature, specification in next, extrafeatures do
+ logreport ("both", 3, "features",
+ "register synthetic feature “%s” for %s font “%s”(%d)",
+ feature,
+ data.format,
+ tostring (data.metadata and data.metadata.fontname or "<unknown>"),
+ data.subfont or -1)
+ otf.features.register { name = feature, description = specification[2] }
+ otf.enhancers.addfeature (data, feature, specification[1])
+ end
+end
+
return {
init = function ()
+ logreport = luaotfload.log.report
+
if not fonts and fonts.handlers then
- logreport ("log", 0, "color",
+ logreport ("log", 0, "features",
"OTF mechanisms missing -- did you forget to \z
load a font loader?")
return false
end
- local otf = fonts.handlers.otf
+ otf = fonts.handlers.otf
- local extrafeatures = {
- tlig = tlig_specification,
- trep = { },
- anum = anum_specification,
- }
+ --- hack for backwards compat with TL2014 loader
+ otf.enhancers.addfeature = otf.version < 2.8 and ancient_addfeature
+ or current_addfeature
otf.enhancers.register ("check extra features",
- function (data,filename, raw)
- for feature, specification in next, extrafeatures do
- addfeature (data, feature, specification)
- end
- end)
-
- logreport = luaotfload.log.report
- if not fonts then
- logreport ("log", 0, "color",
- "OTF mechanisms missing -- did you forget to \z
- load a font loader?")
- return false
- end
-
- otf.features.register {
- name = "anum",
- description = "arabic digits",
- }
+ install_extra_features)
return true
end
}
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-init.lua b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-init.lua
index 895e32ef5dd..d4711527e99 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-init.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-init.lua
@@ -65,6 +65,43 @@ local logreport --- filled in after loading the log module
--doc]]--
+local glyph_codes =
+ { [0] = "character"
+ , [1] = "glyph"
+ , [2] = "ligature"
+ , [3] = "ghost"
+ , [4] = "left"
+ , [5] = "right"
+ }
+
+local disc_codes =
+ { [0] = "discretionary"
+ , [1] = "explicit"
+ , [2] = "automatic"
+ , [3] = "regular"
+ , [4] = "first"
+ , [5] = "second"
+ }
+
+local node_types = { disc = disc_codes, glyph = glyph_codes }
+
+local luatex_stubs = function ()
+ if not node.subtypes then
+ node.subtypes = function (t) return node_types [t] or { } end
+ local direct = node.direct
+
+ local getfield = direct.getfield
+ local setfield = direct.setfield
+
+ direct.setchar = direct.setchar or function (n, ...) setfield (n, "char", ...) end
+ direct.setprev = direct.setprev or function (n, ...) setfield (n, "prev", ...) end
+ direct.setnext = direct.setnext or function (n, ...) setfield (n, "next", ...) end
+
+ direct.getchar = direct.getchar or function (n) getfield (n, "char") end
+ direct.getprev = direct.getprev or function (n) getfield (n, "prev") end
+ direct.getnext = direct.getnext or function (n) getfield (n, "next") end
+ end
+end
local init_early = function ()
@@ -82,6 +119,8 @@ local init_early = function ()
if not lualibs then error "this module requires Luaotfload" end
if not luaotfload then error "this module requires Luaotfload" end
+ luatex_stubs ()
+
--[[doc--
The logger needs to be in place prior to loading the fontloader due
@@ -214,9 +253,9 @@ local context_modules = {
{ ctx, "font-oti" },
{ ctx, "font-otf" },
{ ctx, "font-otb" },
- { ltx, "luatex-fonts-inj" }, --> since 2014-01-07, replaces node-inj.lua
+ { ltx, "font-inj" },
{ ltx, "luatex-fonts-ota" },
- { ltx, "luatex-fonts-otn" }, --> since 2014-01-07, replaces font-otn.lua
+ { ltx, "font-otn" },
{ ctx, "font-otp" }, --> since 2013-04-23
{ ltx, "luatex-fonts-lua" },
{ ctx, "font-def" },
@@ -338,9 +377,9 @@ local init_main = function ()
load_fontloader_module "font-oti"
load_fontloader_module "font-otf"
load_fontloader_module "font-otb"
- load_fontloader_module "fonts-inj" --> since 2014-01-07, replaces node-inj.lua
+ load_fontloader_module "font-inj"
load_fontloader_module "fonts-ota"
- load_fontloader_module "fonts-otn" --> since 2014-01-07, replaces font-otn.lua
+ load_fontloader_module "font-otn"
load_fontloader_module "font-otp" --> since 2013-04-23
load_fontloader_module "fonts-lua"
load_fontloader_module "font-def"
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-letterspace.lua b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-letterspace.lua
index 5fa25f9d343..0d6b8e8264e 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-letterspace.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-letterspace.lua
@@ -20,17 +20,35 @@ local tonumber = tonumber
local next = next
local nodes, node, fonts = nodes, node, fonts
+local nodedirect = nodes.nuts
+
+local getfield = nodedirect.getfield
+local setfield = nodedirect.setfield
+
+local field_setter = function (name) return function (n, ...) setfield (n, name, ...) end end
+local field_getter = function (name) return function (n, ...) getfield (n, name, ...) end end
+
--- As of December 2014 the faster ``node.direct.*`` interface is
--- preferred.
-local nodedirect = nodes.nuts
-local getchar = nodedirect.getchar
+
local getfont = nodedirect.getfont
local getid = nodedirect.getid
-local getnext = nodedirect.getnext
-local getprev = nodedirect.getprev
-local getfield = nodedirect.getfield
-local setfield = nodedirect.setfield
-local getsubtype = nodedirect.getsubtype
+
+local getnext = nodedirect.getnext or field_getter "next"
+local setnext = nodedirect.setnext or field_setter "next"
+
+local getprev = nodedirect.getprev or field_getter "prev"
+local setprev = nodedirect.setprev or field_setter "prev"
+
+local getdisc = nodedirect.getdisc or field_getter "disc"
+local setdisc = nodedirect.setdisc or field_setter "disc"
+
+local getsubtype = nodedirect.getsubtype or field_getter "subtype"
+local setsubtype = nodedirect.setsubtype or field_setter "subtype"
+
+local getchar = nodedirect.getchar or field_getter "subtype"
+local setchar = nodedirect.setchar or field_setter "subtype"
+
local find_node_tail = nodedirect.tail
local todirect = nodedirect.tonut
local tonode = nodedirect.tonode
@@ -310,10 +328,11 @@ kerncharacters = function (head)
else
--- c = kerncharacters (c) --> taken care of after replacing
local s = start
- local p, n = getprev(s), s.next
+ local p = getprev(s)
+ local n = getnext(s)
local tail = find_node_tail(c)
if p then
- setfield(p, "next", c)
+ setnext(p, c)
p = getprev(c)
else
head = c
@@ -321,7 +340,7 @@ kerncharacters = function (head)
if n then
tail = getprev(n)
end
- setnext(tail, "next", n)
+ setnext(tail, n)
start = c
setfield(s, "components", nil)
-- we now leak nodes !
@@ -368,9 +387,10 @@ kerncharacters = function (head)
then
-- keep
else
- prev_subtype = userkern_code
+ setsubtype (prev, userkern_code)
local prev_kern = getfield(prev, "kern")
prev_kern = prev_kern + quaddata[lastfont] * krn
+ setfield (prev, "kern", prev_kern)
done = true
end
end
@@ -395,24 +415,20 @@ kerncharacters = function (head)
end
elseif pid == disc_code then
- -- a bit too complicated, we can best not copy and just calculate
- -- but we could have multiple glyphs involved so ...
local disc = prev -- disc
- local pre = getfield(disc, "pre")
- local post = getfield(disc, "post")
- local replace = getfield(disc, "replace")
- local prv = getprev(disc)
- local nxt = getnext(disc)
+ local pre, post, replace = getdisc (disc)
+ local prv = getprev(disc)
+ local nxt = getnext(disc)
if pre and prv then -- must pair with start.prev
-- this one happens in most cases
local before = copy_node(prv)
- setfield(pre, "prev", before)
- setfield(before, "next", pre)
- setfield(before, "prev", nil)
+ setprev(pre, before)
+ setnext(before, pre)
+ setprev(before, nil)
pre = kerncharacters (before)
pre = getnext(pre)
- setfield(pre, "prev", nil)
+ setprev(pre, nil)
setfield(disc, "pre", pre)
free_node(before)
end
@@ -420,11 +436,11 @@ kerncharacters = function (head)
if post and nxt then -- must pair with start
local after = copy_node(nxt)
local tail = find_node_tail(post)
- setfield(tail, "next", after)
- setfield(after, "prev", tail)
- setfield(after, "next", nil)
+ setnext(tail, after)
+ setprev(after, tail)
+ setnext(after, nil)
post = kerncharacters (post)
- setfield(tail, "next", nil)
+ setnext(tail, nil)
setfield(disc, "post", post)
free_node(after)
end
@@ -433,17 +449,17 @@ kerncharacters = function (head)
local before = copy_node(prv)
local after = copy_node(nxt)
local tail = find_node_tail(replace)
- setfield(replace, "prev", before)
- setfield(before, "next", replace)
- setfield(before, "prev", nil)
- setfield(tail, "next", after)
- setfield(after, "prev", tail)
- setfield(after, "next", nil)
+ setprev(replace, before)
+ setnext(before, replace)
+ setprev(before, nil)
+ setnext(tail, after)
+ setprev(after, tail)
+ setnext(after, nil)
replace = kerncharacters (before)
replace = getnext(replace)
- setfield(replace, "prev", nil)
- setfield(after, "prev.next", nil)
- setfield(disc, "replace", replace)
+ setprev(replace, nil)
+ setnext(getprev(after), nil)
+ setfield(disc, "replace", replace)
free_node(after)
free_node(before)
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-status.lua b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-status.lua
index 34a206312a9..e1cedd13bf1 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-status.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-status.lua
@@ -1,6 +1,6 @@
return {
["hashes"]={
- { "fontloader-2015-12-12.lua", "bcc0cb6536e04a9ee4693848a505d568" },
+ { "fontloader-2015-12-22.lua", "c0cee8ffb486d88193aa78c32416a474" },
{ "fontloader-util-str.lua", "cc6f38cc53aff51d60e2223bf922bb0d" },
{ "fontloader-swiglib-test.lua", "c1cdeff07e5b8896f7aa98ce50c31618" },
{ "fontloader-swiglib.lua", "3a350d89416637073b7f09e281dc7c11" },
@@ -16,39 +16,39 @@ return {
{ "fontloader-l-function.lua", "a7e68a9703c35238729da41a474e951b" },
{ "fontloader-l-file.lua", "bb25347eee3208dbb419e80eb2809e99" },
{ "fontloader-l-boolean.lua", "abe28515dd33e8f6c416c09bca351cf8" },
- { "fontloader-languages.lua", "16446704262489ccbe65a963dcd490f1" },
+ { "fontloader-languages.lua", "4e5bbdad336fa4969ac21a5242643a40" },
{ "fontloader-font-tfm.lua", "bbee5eddb11211fb0a8d993db678bf3c" },
{ "fontloader-fonts-tfm.lua", "8fd3865240e4e87e99e0739abeda2322" },
{ "fontloader-fonts-syn.lua", "9729d0e49b770f78e88dab86739e0297" },
- { "fontloader-fonts-otn.lua", "f01870a8622259f58ffbdc5718a53377" },
- { "fontloader-fonts-ota.lua", "e18236703ac20ece7ff45f9209a9b9d6" },
+ { "fontloader-font-otn.lua", "e8a1f33bbba52eda6aec4e6d6a9662dc" },
+ { "fontloader-fonts-ota.lua", "67a1fc4c6508526fa54041d22bcb6eab" },
{ "fontloader-fonts-lua.lua", "50b8edb1db7009b6c661ab71ff24a466" },
- { "fontloader-fonts.lua", "19a42e8ce2c816e2d3262f3d72b0a5c7" },
- { "fontloader-fonts-inj.lua", "2e61e59f1931a84336c6aea812e219c2" },
+ { "fontloader-fonts.lua", "f3a705aade933e2171c8128cead7f4ad" },
+ { "fontloader-font-inj.lua", "593642f0a6fe4a7fef5ed63034276e6f" },
{ "fontloader-fonts-ext.lua", "0eee87fb26b7d135da88ac0a43a8037a" },
{ "fontloader-fonts-enc.lua", "b224fe179312d924ffaf8334cf5ef15b" },
{ "fontloader-fonts-demo-vf-1.lua", "edf37ece9bd112b1b13d9475528ab210" },
- { "fontloader-fonts-def.lua", "8dc05f2aa96d2fd0245242c8fd3320eb" },
+ { "fontloader-fonts-def.lua", "e758c9faca4d44382b88bbea892e8bbf" },
{ "fontloader-fonts-cbk.lua", "3e86c6a492ca8d792f6b06149ba0dd57" },
{ "fontloader-font-otp.lua", "18b4375155925ee1809150f4f6c3973b" },
- { "fontloader-font-oti.lua", "035a51b49029d7da48453ec5f1d65018" },
- { "fontloader-font-otf.lua", "b1a5f4340125198b1b0489ef903dd267" },
+ { "fontloader-font-oti.lua", "b6d493035cec2d748f2f9ec510c860ef" },
+ { "fontloader-font-otf.lua", "b14a46a7fec8b5cb4c909f4c4c299453" },
{ "fontloader-font-otb.lua", "93461f2f412a9b33b35a273c09b64291" },
- { "fontloader-font-map.lua", "60c9f3d4d80944ce9123c9cddc1e57e5" },
+ { "fontloader-font-map.lua", "a20a454f933095d78faf1d5f8200d025" },
{ "fontloader-font-ini.lua", "179f0a75cda26696c1b1cd6d7fe0d8ae" },
{ "fontloader-font-def.lua", "3c71c27300a8cb5c29f5d278d2049fb6" },
- { "fontloader-font-con.lua", "5ae91fc3b5bb8d22b2fba27258d49971" },
+ { "fontloader-font-con.lua", "99aacd19adce25fa35a9a30d43e8ac79" },
{ "fontloader-font-cid.lua", "52421d1fdaa07ec4b1d936c6ff5079be" },
{ "fontloader-font-afm.lua", "ece4863414d6b38c2e577110c9b55bd3" },
{ "fontloader-font-afk.lua", "b36a76ceb835f41f8c05b471000ddc14" },
{ "fontloader-data-con.lua", "675f5a0af45ffb3e0d2e2ab5d6c2e47b" },
- { "fontloader-basics-nod.lua", "d060e22b2afed6e7624f879b0e1a7d71" },
+ { "fontloader-basics-nod.lua", "af682899d202229c0c1b859a07384b8c" },
{ "fontloader-tl2014.lua", "5bce3c40d6841694d6be5ad3680d5b10" },
- { "fontloader-reference.lua", "f3481efe06dc45db0dc7404aa96754e3" },
+ { "fontloader-reference.lua", "0d04f2ef8be3ad63f760b461fc5c1bb4" },
{ "fontloader-basics-gen.lua", "aa7229a3a0ae35d19bbe46e71d65bd2c" },
{ "mktests", "918cb50be9ee8bd645ac1a27dc501e8c" },
- { "mkstatus", "76308532fa0175ac046e6ed1bf11e4b8" },
- { "mkimport", "988e04fc571b2984eb21894cf0ea76e5" },
+ { "mkstatus", "31abf1d5bf7c35f3856155601dfcea4a" },
+ { "mkimport", "3077a499e7735444d582b741b1960b98" },
{ "mkglyphlist", "0acaf0fbc9dce6fda4e717a7ddcfdef6" },
{ "mkcharacters", "5274a32b25f2dc1f55e75546c551035e" },
{ "luaotfload-glyphlist.lua", "ff440162d1b8a78a586375ee65630c21" },
@@ -59,20 +59,20 @@ return {
{ "luaotfload-main.lua", "98456048a0ebb8040c6b46de529398ec" },
{ "luaotfload-log.lua", "767adc12efe986322d16dd85f05b3e75" },
{ "luaotfload-loaders.lua", "40e9e162b84e22db29cd79afb8a34761" },
- { "luaotfload-letterspace.lua", "3f87639c395f3dd83b6c3ae4f717a02a" },
- { "luaotfload-init.lua", "d850a9a2d87c122de38b9221bf39473c" },
- { "luaotfload-features.lua", "3e98785b46c6779f70ed6e7e4d497e53" },
+ { "luaotfload-letterspace.lua", "b01dd0cd37deb2dbad97adbf738e9dd2" },
+ { "luaotfload-init.lua", "e31c728f5e86c858909c491b39ba0fbd" },
+ { "luaotfload-features.lua", "812cefbc82f612e889842d56e421cca7" },
{ "luaotfload-diagnostics.lua", "7b35c9f91e3e73fc5a61dbfe1f0e7ad9" },
{ "luaotfload-database.lua", "ffb5c6497be2c518eb28fcefaa3175c1" },
{ "luaotfload-configuration.lua", "04eb776c853a22fc49dcf0e52da85dda" },
{ "luaotfload-colors.lua", "b68a52ce0b046343cb689d981d0c5a7a" },
- { "luaotfload-auxiliary.lua", "04d8d1f39e06255a41a9f00febc66e2b" },
+ { "luaotfload-auxiliary.lua", "b0b7624c793d96ae5e6fbb45e67f1310" },
},
["notes"]={
["committer"]="Philipp Gesang <phg@phi-gamma.net>",
- ["description"]="v2.6-fix-2",
- ["loader"]="fontloader-2015-12-12.lua",
- ["revision"]="2fdaee0d9a2687e99b1f44be15b6876be22a495b",
- ["timestamp"]="2015-12-12 20:05:29 +0100",
+ ["description"]="v2.6-fix-3",
+ ["loader"]="fontloader-2015-12-22.lua",
+ ["revision"]="c7e64e04f85ab6386fcbc0bc631db808d0d6109f",
+ ["timestamp"]="2015-12-22 23:32:39 +0100",
},
} \ No newline at end of file