summaryrefslogtreecommitdiff
path: root/src/luaotfload-fontloader.lua
diff options
context:
space:
mode:
Diffstat (limited to 'src/luaotfload-fontloader.lua')
-rw-r--r--src/luaotfload-fontloader.lua1968
1 files changed, 1309 insertions, 659 deletions
diff --git a/src/luaotfload-fontloader.lua b/src/luaotfload-fontloader.lua
index 4aa03e6..e9c6638 100644
--- a/src/luaotfload-fontloader.lua
+++ b/src/luaotfload-fontloader.lua
@@ -1,6 +1,6 @@
-- merged file : luatex-fonts-merged.lua
-- parent file : luatex-fonts.lua
--- merge date : 09/26/14 11:42:21
+-- merge date : 12/06/14 14:20:08
do -- begin closure to overcome local limits and interference
@@ -149,6 +149,8 @@ patterns.utfbom_16_le=utfbom_16_le
patterns.utfbom_8=utfbom_8
patterns.utf_16_be_nl=P("\000\r\000\n")+P("\000\r")+P("\000\n")
patterns.utf_16_le_nl=P("\r\000\n\000")+P("\r\000")+P("\n\000")
+patterns.utf_32_be_nl=P("\000\000\000\r\000\000\000\n")+P("\000\000\000\r")+P("\000\000\000\n")
+patterns.utf_32_le_nl=P("\r\000\000\000\n\000\000\000")+P("\r\000\000\000")+P("\n\000\000\000")
patterns.utf8one=R("\000\127")
patterns.utf8two=R("\194\223")*utf8next
patterns.utf8three=R("\224\239")*utf8next*utf8next
@@ -178,9 +180,21 @@ patterns.nonwhitespace=nonwhitespace
local stripper=spacer^0*C((spacer^0*nonspacer^1)^0)
local fullstripper=whitespace^0*C((whitespace^0*nonwhitespace^1)^0)
local collapser=Cs(spacer^0/""*nonspacer^0*((spacer^0/" "*nonspacer^1)^0))
+local b_collapser=Cs(whitespace^0/""*(nonwhitespace^1+whitespace^1/" ")^0)
+local e_collapser=Cs((whitespace^1*P(-1)/""+nonwhitespace^1+whitespace^1/" ")^0)
+local m_collapser=Cs((nonwhitespace^1+whitespace^1/" ")^0)
+local b_stripper=Cs(spacer^0/""*(nonspacer^1+spacer^1/" ")^0)
+local e_stripper=Cs((spacer^1*P(-1)/""+nonspacer^1+spacer^1/" ")^0)
+local m_stripper=Cs((nonspacer^1+spacer^1/" ")^0)
patterns.stripper=stripper
patterns.fullstripper=fullstripper
patterns.collapser=collapser
+patterns.b_collapser=b_collapser
+patterns.m_collapser=m_collapser
+patterns.e_collapser=e_collapser
+patterns.b_stripper=b_stripper
+patterns.m_stripper=m_stripper
+patterns.e_stripper=e_stripper
patterns.lowercase=lowercase
patterns.uppercase=uppercase
patterns.letter=patterns.lowercase+patterns.uppercase
@@ -731,6 +745,65 @@ local case_2=period*(digit-trailingzeros)^1*(trailingzeros/"")
local number=digit^1*(case_1+case_2)
local stripper=Cs((number+1)^0)
lpeg.patterns.stripzeros=stripper
+local byte_to_HEX={}
+local byte_to_hex={}
+local byte_to_dec={}
+local hex_to_byte={}
+for i=0,255 do
+ local H=format("%02X",i)
+ local h=format("%02x",i)
+ local d=format("%03i",i)
+ local c=char(i)
+ byte_to_HEX[c]=H
+ byte_to_hex[c]=h
+ byte_to_dec[c]=d
+ hex_to_byte[h]=c
+ hex_to_byte[H]=c
+end
+local hextobyte=P(2)/hex_to_byte
+local bytetoHEX=P(1)/byte_to_HEX
+local bytetohex=P(1)/byte_to_hex
+local bytetodec=P(1)/byte_to_dec
+local hextobytes=Cs(hextobyte^0)
+local bytestoHEX=Cs(bytetoHEX^0)
+local bytestohex=Cs(bytetohex^0)
+local bytestodec=Cs(bytetodec^0)
+patterns.hextobyte=hextobyte
+patterns.bytetoHEX=bytetoHEX
+patterns.bytetohex=bytetohex
+patterns.bytetodec=bytetodec
+patterns.hextobytes=hextobytes
+patterns.bytestoHEX=bytestoHEX
+patterns.bytestohex=bytestohex
+patterns.bytestodec=bytestodec
+function string.toHEX(s)
+ if not s or s=="" then
+ return s
+ else
+ return lpegmatch(bytestoHEX,s)
+ end
+end
+function string.tohex(s)
+ if not s or s=="" then
+ return s
+ else
+ return lpegmatch(bytestohex,s)
+ end
+end
+function string.todec(s)
+ if not s or s=="" then
+ return s
+ else
+ return lpegmatch(bytestodec,s)
+ end
+end
+function string.tobytes(s)
+ if not s or s=="" then
+ return s
+ else
+ return lpegmatch(hextobytes,s)
+ end
+end
end -- closure
@@ -895,7 +968,7 @@ local function compare(a,b)
if ta==tb then
return a<b
else
- return tostring(a)<tostring(b)
+ return tostring(a)<tostring(b)
end
end
local function sortedkeys(tab)
@@ -3560,7 +3633,12 @@ function caches.compile(data,luaname,lucname)
end
end
function table.setmetatableindex(t,f)
+ if type(t)~="table" then
+ f=f or t
+ t={}
+ end
setmetatable(t,{ __index=f })
+ return t
end
arguments={}
if arg then
@@ -3771,21 +3849,12 @@ function nodes.pool.kern(k)
n.kern=k
return n
end
-local getfield=node.getfield or function(n,tag) return n[tag] end
-local setfield=node.setfield or function(n,tag,value) n[tag]=value end
+local getfield=node.getfield
+local setfield=node.setfield
nodes.getfield=getfield
nodes.setfield=setfield
nodes.getattr=getfield
nodes.setattr=setfield
-if node.getid then nodes.getid=node.getid else function nodes.getid (n) return getfield(n,"id") end end
-if node.getsubtype then nodes.getsubtype=node.getsubtype else function nodes.getsubtype(n) return getfield(n,"subtype") end end
-if node.getnext then nodes.getnext=node.getnext else function nodes.getnext (n) return getfield(n,"next") end end
-if node.getprev then nodes.getprev=node.getprev else function nodes.getprev (n) return getfield(n,"prev") end end
-if node.getchar then nodes.getchar=node.getchar else function nodes.getchar (n) return getfield(n,"char") end end
-if node.getfont then nodes.getfont=node.getfont else function nodes.getfont (n) return getfield(n,"font") end end
-if node.getlist then nodes.getlist=node.getlist else function nodes.getlist (n) return getfield(n,"list") end end
-function nodes.tonut (n) return n end
-function nodes.tonode(n) return n end
nodes.tostring=node.tostring or tostring
nodes.copy=node.copy
nodes.copy_list=node.copy_list
@@ -3822,7 +3891,68 @@ nodes.unprotect_glyphs=node.unprotect_glyphs
nodes.kerning=node.kerning
nodes.ligaturing=node.ligaturing
nodes.mlist_to_hlist=node.mlist_to_hlist
-nodes.nuts=nodes
+local direct=node.direct
+local nuts={}
+nodes.nuts=nuts
+local tonode=direct.tonode
+local tonut=direct.todirect
+nodes.tonode=tonode
+nodes.tonut=tonut
+nuts.tonode=tonode
+nuts.tonut=tonut
+local getfield=direct.getfield
+local setfield=direct.setfield
+nuts.getfield=getfield
+nuts.setfield=setfield
+nuts.getnext=direct.getnext
+nuts.getprev=direct.getprev
+nuts.getid=direct.getid
+nuts.getattr=getfield
+nuts.setattr=setfield
+nuts.getfont=direct.getfont
+nuts.getsubtype=direct.getsubtype
+nuts.getchar=direct.getchar
+nuts.insert_before=direct.insert_before
+nuts.insert_after=direct.insert_after
+nuts.delete=direct.delete
+nuts.copy=direct.copy
+nuts.tail=direct.tail
+nuts.flush_list=direct.flush_list
+nuts.end_of_math=direct.end_of_math
+nuts.traverse=direct.traverse
+nuts.traverse_id=direct.traverse_id
+nuts.getprop=nuts.getattr
+nuts.setprop=nuts.setattr
+local new_nut=direct.new
+nuts.new=new_nut
+nuts.pool={}
+function nuts.pool.kern(k)
+ local n=new_nut("kern",1)
+ setfield(n,"kern",k)
+ return n
+end
+local propertydata=direct.get_properties_table()
+nodes.properties={ data=propertydata }
+direct.set_properties_mode(true,true)
+function direct.set_properties_mode() end
+nuts.getprop=function(n,k)
+ local p=propertydata[n]
+ if p then
+ return p[k]
+ end
+end
+nuts.setprop=function(n,k,v)
+ if v then
+ local p=propertydata[n]
+ if p then
+ p[k]=v
+ else
+ propertydata[n]={ [k]=v }
+ end
+ end
+end
+nodes.setprop=nodes.setproperty
+nodes.getprop=nodes.getproperty
end -- closure
@@ -3881,7 +4011,8 @@ constructors.autocleanup=true
constructors.namemode="fullpath"
constructors.version=1.01
constructors.cache=containers.define("fonts","constructors",constructors.version,false)
-constructors.privateoffset=0xF0000
+constructors.privateoffset=0xF0000
+constructors.cacheintex=true
constructors.keys={
properties={
encodingbytes="number",
@@ -4134,7 +4265,7 @@ function constructors.scale(tfmdata,specification)
targetparameters.textsize=textsize
targetparameters.forcedsize=forcedsize
targetparameters.extrafactor=extrafactor
- local tounicode=resources.tounicode
+ local tounicode=fonts.mappings.tounicode
local defaultwidth=resources.defaultwidth or 0
local defaultheight=resources.defaultheight or 0
local defaultdepth=resources.defaultdepth or 0
@@ -4160,6 +4291,7 @@ function constructors.scale(tfmdata,specification)
target.tounicode=1
target.cidinfo=properties.cidinfo
target.format=properties.format
+ target.cache=constructors.cacheintex and "yes" or "renew"
local fontname=properties.fontname or tfmdata.fontname
local fullname=properties.fullname or tfmdata.fullname
local filename=properties.filename or tfmdata.filename
@@ -4214,7 +4346,8 @@ function constructors.scale(tfmdata,specification)
local autoitalicamount=properties.autoitalicamount
local stackmath=not properties.nostackmath
local nonames=properties.noglyphnames
- local nodemode=properties.mode=="node"
+ local haskerns=properties.haskerns or properties.mode=="base"
+ local hasligatures=properties.hasligatures or properties.mode=="base"
if changed and not next(changed) then
changed=false
end
@@ -4277,38 +4410,20 @@ function constructors.scale(tfmdata,specification)
constructors.beforecopyingcharacters(target,tfmdata)
local sharedkerns={}
for unicode,character in next,characters do
- local chr,description,index,touni
+ local chr,description,index
if changed then
local c=changed[unicode]
if c then
- local ligatures=character.ligatures
description=descriptions[c] or descriptions[unicode] or character
character=characters[c] or character
index=description.index or c
- if tounicode then
- touni=tounicode[index]
- if not touni then
- local d=descriptions[unicode] or characters[unicode]
- local i=d.index or unicode
- touni=tounicode[i]
- end
- end
- if ligatures and not character.ligatures then
- character.ligatures=ligatures
- end
else
description=descriptions[unicode] or character
index=description.index or unicode
- if tounicode then
- touni=tounicode[index]
- end
end
else
description=descriptions[unicode] or character
index=description.index or unicode
- if tounicode then
- touni=tounicode[index]
- end
end
local width=description.width
local height=description.height
@@ -4349,8 +4464,10 @@ function constructors.scale(tfmdata,specification)
}
end
end
- if touni then
- chr.tounicode=touni
+ local isunicode=description.unicode
+ if isunicode then
+ chr.unicode=isunicode
+ chr.tounicode=tounicode(isunicode)
end
if hasquality then
local ve=character.expansion_factor
@@ -4443,7 +4560,7 @@ function constructors.scale(tfmdata,specification)
end
end
end
- if not nodemode then
+ if haskerns then
local vk=character.kerns
if vk then
local s=sharedkerns[vk]
@@ -4454,6 +4571,8 @@ function constructors.scale(tfmdata,specification)
end
chr.kerns=s
end
+ end
+ if hasligatures then
local vl=character.ligatures
if vl then
if true then
@@ -4610,6 +4729,7 @@ function constructors.finalize(tfmdata)
tfmdata.extend=nil
tfmdata.slant=nil
tfmdata.units_per_em=nil
+ tfmdata.cache=nil
properties.finalized=true
return tfmdata
end
@@ -4954,6 +5074,16 @@ function constructors.applymanipulators(what,tfmdata,features,trace,report)
end
end
end
+function constructors.addcoreunicodes(unicodes)
+ if not unicodes then
+ unicodes={}
+ end
+ unicodes.space=0x0020
+ unicodes.hyphen=0x002D
+ unicodes.zwj=0x200D
+ unicodes.zwnj=0x200C
+ return unicodes
+end
end -- closure
@@ -5045,7 +5175,7 @@ local function loadcidfile(filename)
ordering=ordering,
filename=filename,
unicodes=unicodes,
- names=names
+ names=names,
}
end
end
@@ -5082,10 +5212,23 @@ function cid.getmap(specification)
local ordering=specification.ordering
local supplement=specification.supplement
local filename=format(registry,ordering,supplement)
- local found=cidmap[lower(filename)]
+ local lowername=lower(filename)
+ local found=cidmap[lowername]
if found then
return found
end
+ if ordering=="Identity" then
+ local found={
+ supplement=supplement,
+ registry=registry,
+ ordering=ordering,
+ filename=filename,
+ unicodes={},
+ names={},
+ }
+ cidmap[lowername]=found
+ return found
+ end
if trace_loading then
report_otf("cidmap needed, registry %a, ordering %a, supplement %a",registry,ordering,supplement)
end
@@ -5136,11 +5279,12 @@ if not modules then modules={} end modules ['font-map']={
copyright="PRAGMA ADE / ConTeXt Development Team",
license="see context related readme files"
}
-local tonumber=tonumber
+local tonumber,next,type=tonumber,next,type
local match,format,find,concat,gsub,lower=string.match,string.format,string.find,table.concat,string.gsub,string.lower
local P,R,S,C,Ct,Cc,lpegmatch=lpeg.P,lpeg.R,lpeg.S,lpeg.C,lpeg.Ct,lpeg.Cc,lpeg.match
local utfbyte=utf.byte
local floor=math.floor
+local formatters=string.formatters
local trace_loading=false trackers.register("fonts.loading",function(v) trace_loading=v end)
local trace_mapping=false trackers.register("fonts.mapping",function(v) trace_unimapping=v end)
local report_fonts=logs.reporter("fonts","loading")
@@ -5180,11 +5324,13 @@ local function makenameparser(str)
return p
end
end
+local f_single=formatters["%04X"]
+local f_double=formatters["%04X%04X"]
local function tounicode16(unicode,name)
if unicode<0x10000 then
- return format("%04X",unicode)
+ return f_single(unicode)
elseif unicode<0x1FFFFFFFFF then
- return format("%04X%04X",floor(unicode/1024),unicode%1024+0xDC00)
+ return f_double(floor(unicode/1024),unicode%1024+0xDC00)
else
report_fonts("can't convert %a in %a into tounicode",unicode,name)
end
@@ -5192,17 +5338,43 @@ end
local function tounicode16sequence(unicodes,name)
local t={}
for l=1,#unicodes do
- local unicode=unicodes[l]
- if unicode<0x10000 then
- t[l]=format("%04X",unicode)
+ local u=unicodes[l]
+ if u<0x10000 then
+ t[l]=f_single(u)
elseif unicode<0x1FFFFFFFFF then
- t[l]=format("%04X%04X",floor(unicode/1024),unicode%1024+0xDC00)
+ t[l]=f_double(floor(u/1024),u%1024+0xDC00)
else
- report_fonts ("can't convert %a in %a into tounicode",unicode,name)
+ 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]
+ if u<0x10000 then
+ t[l]=f_single(u)
+ elseif u<0x1FFFFFFFFF then
+ t[l]=f_double(floor(u/1024),u%1024+0xDC00)
+ else
+ report_fonts ("can't convert %a in %a into tounicode",u,name)
+ return
+ end
+ end
+ return concat(t)
+ else
+ if unicode<0x10000 then
+ return f_single(unicode)
+ elseif unicode<0x1FFFFFFFFF then
+ return f_double(floor(unicode/1024),unicode%1024+0xDC00)
+ else
+ report_fonts("can't convert %a in %a into tounicode",unicode,name)
+ end
+ end
+end
local function fromunicode16(str)
if #str==4 then
return tonumber(str,16)
@@ -5213,17 +5385,41 @@ local function fromunicode16(str)
end
mappings.loadlumtable=loadlumtable
mappings.makenameparser=makenameparser
+mappings.tounicode=tounicode
mappings.tounicode16=tounicode16
mappings.tounicode16sequence=tounicode16sequence
mappings.fromunicode16=fromunicode16
local ligseparator=P("_")
local varseparator=P(".")
local namesplitter=Ct(C((1-ligseparator-varseparator)^1)*(ligseparator*C((1-ligseparator-varseparator)^1))^0)
+local overloads={
+ IJ={ name="I_J",unicode={ 0x49,0x4A },mess=0x0132 },
+ ij={ name="i_j",unicode={ 0x69,0x6A },mess=0x0133 },
+ ff={ name="f_f",unicode={ 0x66,0x66 },mess=0xFB00 },
+ fi={ name="f_i",unicode={ 0x66,0x69 },mess=0xFB01 },
+ fl={ name="f_l",unicode={ 0x66,0x6C },mess=0xFB02 },
+ ffi={ name="f_f_i",unicode={ 0x66,0x66,0x69 },mess=0xFB03 },
+ ffl={ name="f_f_l",unicode={ 0x66,0x66,0x6C },mess=0xFB04 },
+ fj={ name="f_j",unicode={ 0x66,0x6A } },
+ fk={ name="f_k",unicode={ 0x66,0x6B } },
+}
+for k,v in next,overloads do
+ local name=v.name
+ local mess=v.mess
+ if name then
+ overloads[name]=v
+ end
+ if mess then
+ overloads[mess]=v
+ end
+end
+mappings.overloads=overloads
function mappings.addtounicode(data,filename)
local resources=data.resources
local properties=data.properties
local descriptions=data.descriptions
local unicodes=resources.unicodes
+ local lookuptypes=resources.lookuptypes
if not unicodes then
return
end
@@ -5232,18 +5428,10 @@ function mappings.addtounicode(data,filename)
unicodes['zwj']=unicodes['zwj'] or 0x200D
unicodes['zwnj']=unicodes['zwnj'] or 0x200C
local private=fonts.constructors.privateoffset
- local unknown=format("%04X",utfbyte("?"))
- local unicodevector=fonts.encodings.agl.unicodes
- local tounicode={}
- local originals={}
- resources.tounicode=tounicode
- resources.originals=originals
+ local unicodevector=fonts.encodings.agl.unicodes
+ local missing={}
local lumunic,uparser,oparser
local cidinfo,cidnames,cidcodes,usedmap
- if false then
- lumunic=loadlumtable(filename)
- lumunic=lumunic and lumunic.tounicode
- end
cidinfo=properties.cidinfo
usedmap=cidinfo and fonts.cid.getmap(cidinfo)
if usedmap then
@@ -5256,11 +5444,13 @@ function mappings.addtounicode(data,filename)
for unic,glyph in next,descriptions do
local index=glyph.index
local name=glyph.name
- if unic==-1 or unic>=private or (unic>=0xE000 and unic<=0xF8FF) or unic==0xFFFE or unic==0xFFFF then
+ local r=overloads[name]
+ if r then
+ glyph.unicode=r.unicode
+ elseif unic==-1 or unic>=private or (unic>=0xE000 and unic<=0xF8FF) or unic==0xFFFE or unic==0xFFFF then
local unicode=lumunic and lumunic[name] or unicodevector[name]
if unicode then
- originals[index]=unicode
- tounicode[index]=tounicode16(unicode,name)
+ glyph.unicode=unicode
ns=ns+1
end
if (not unicode) and usedmap then
@@ -5268,8 +5458,7 @@ function mappings.addtounicode(data,filename)
if foundindex then
unicode=cidcodes[foundindex]
if unicode then
- originals[index]=unicode
- tounicode[index]=tounicode16(unicode,name)
+ glyph.unicode=unicode
ns=ns+1
else
local reference=cidnames[foundindex]
@@ -5278,21 +5467,18 @@ function mappings.addtounicode(data,filename)
if foundindex then
unicode=cidcodes[foundindex]
if unicode then
- originals[index]=unicode
- tounicode[index]=tounicode16(unicode,name)
+ glyph.unicode=unicode
ns=ns+1
end
end
if not unicode or unicode=="" then
local foundcodes,multiple=lpegmatch(uparser,reference)
if foundcodes then
- originals[index]=foundcodes
+ glyph.unicode=foundcodes
if multiple then
- tounicode[index]=tounicode16sequence(foundcodes)
nl=nl+1
unicode=true
else
- tounicode[index]=tounicode16(foundcodes,name)
ns=ns+1
unicode=foundcodes
end
@@ -5330,39 +5516,157 @@ function mappings.addtounicode(data,filename)
end
if n==0 then
elseif n==1 then
- originals[index]=t[1]
- tounicode[index]=tounicode16(t[1],name)
+ glyph.unicode=t[1]
else
- originals[index]=t
- tounicode[index]=tounicode16sequence(t)
+ glyph.unicode=t
end
nl=nl+1
end
if not unicode or unicode=="" then
local foundcodes,multiple=lpegmatch(uparser,name)
if foundcodes then
+ glyph.unicode=foundcodes
if multiple then
- originals[index]=foundcodes
- tounicode[index]=tounicode16sequence(foundcodes,name)
nl=nl+1
unicode=true
else
- originals[index]=foundcodes
- tounicode[index]=tounicode16(foundcodes,name)
ns=ns+1
unicode=foundcodes
end
end
end
+ local r=overloads[unicode]
+ if r then
+ unicode=r.unicode
+ glyph.unicode=unicode
+ end
+ if not unicode then
+ missing[name]=true
+ end
+ end
+ end
+ if next(missing) then
+ local guess={}
+ local function check(gname,code,unicode)
+ local description=descriptions[code]
+ local variant=description.name
+ if variant==gname then
+ return
+ end
+ local unic=unicodes[variant]
+ if unic==-1 or unic>=private or (unic>=0xE000 and unic<=0xF8FF) or unic==0xFFFE or unic==0xFFFF then
+ else
+ return
+ end
+ if descriptions[code].unicode then
+ return
+ end
+ local g=guess[variant]
+ if g then
+ g[gname]=unicode
+ else
+ guess[variant]={ [gname]=unicode }
+ end
+ end
+ for unicode,description in next,descriptions do
+ local slookups=description.slookups
+ if slookups then
+ local gname=description.name
+ for tag,data in next,slookups do
+ local lookuptype=lookuptypes[tag]
+ if lookuptype=="alternate" then
+ for i=1,#data do
+ check(gname,data[i],unicode)
+ end
+ elseif lookuptype=="substitution" then
+ check(gname,data,unicode)
+ end
+ end
+ end
+ local mlookups=description.mlookups
+ if mlookups then
+ local gname=description.name
+ for tag,list in next,mlookups do
+ local lookuptype=lookuptypes[tag]
+ if lookuptype=="alternate" then
+ for i=1,#list do
+ local data=list[i]
+ for i=1,#data do
+ check(gname,data[i],unicode)
+ end
+ end
+ elseif lookuptype=="substitution" then
+ for i=1,#list do
+ check(gname,list[i],unicode)
+ end
+ end
+ end
+ end
+ end
+ local done=true
+ while done do
+ done=false
+ for k,v in next,guess do
+ if type(v)~="number" then
+ for kk,vv in next,v do
+ if vv==-1 or vv>=private or (vv>=0xE000 and vv<=0xF8FF) or vv==0xFFFE or vv==0xFFFF then
+ local uu=guess[kk]
+ if type(uu)=="number" then
+ guess[k]=uu
+ done=true
+ end
+ else
+ guess[k]=vv
+ done=true
+ end
+ end
+ end
+ end
+ end
+ local orphans=0
+ local guessed=0
+ for k,v in next,guess do
+ if type(v)=="number" then
+ descriptions[unicodes[k]].unicode=descriptions[v].unicode or v
+ guessed=guessed+1
+ else
+ local t=nil
+ local l=lower(k)
+ local u=unicodes[l]
+ if not u then
+ orphans=orphans+1
+ elseif u==-1 or u>=private or (u>=0xE000 and u<=0xF8FF) or u==0xFFFE or u==0xFFFF then
+ local unicode=descriptions[u].unicode
+ if unicode then
+ descriptions[unicodes[k]].unicode=unicode
+ guessed=guessed+1
+ else
+ orphans=orphans+1
+ end
+ else
+ orphans=orphans+1
+ end
+ end
+ end
+ if trace_loading and orphans>0 or guessed>0 then
+ report_fonts("%s glyphs with no related unicode, %s guessed, %s orphans",guessed+orphans,guessed,orphans)
end
end
if trace_mapping then
for unic,glyph in table.sortedhash(descriptions) do
local name=glyph.name
local index=glyph.index
- local toun=tounicode[index]
- if toun then
- report_fonts("internal slot %U, name %a, unicode %U, tounicode %a",index,name,unic,toun)
+ local unicode=glyph.unicode
+ if unicode then
+ if type(unicode)=="table" then
+ local unicodes={}
+ for i=1,#unicode do
+ unicodes[i]=formatters("%U",unicode[i])
+ end
+ report_fonts("internal slot %U, name %a, unicode %U, tounicode % t",index,name,unic,unicodes)
+ else
+ report_fonts("internal slot %U, name %a, unicode %U, tounicode %U",index,name,unic,unicode)
+ end
else
report_fonts("internal slot %U, name %a, unicode %U",index,name,unic)
end
@@ -5504,6 +5808,7 @@ local function read_from_tfm(specification)
properties.fontname=tfmdata.fontname
properties.psname=tfmdata.psname
properties.filename=specification.filename
+ properties.format=fonts.formats.tfm
parameters.size=size
shared.rawdata={}
shared.features=features
@@ -5543,6 +5848,10 @@ local function read_from_tfm(specification)
features.encoding=encoding
end
end
+ properties.haskerns=true
+ properties.haslogatures=true
+ resources.unicodes={}
+ resources.lookuptags={}
return tfmdata
end
end
@@ -5598,6 +5907,7 @@ local trace_indexing=false trackers.register("afm.indexing",function(v) trace_in
local trace_loading=false trackers.register("afm.loading",function(v) trace_loading=v end)
local trace_defining=false trackers.register("fonts.defining",function(v) trace_defining=v end)
local report_afm=logs.reporter("fonts","afm loading")
+local setmetatableindex=table.setmetatableindex
local findbinfile=resolvers.findbinfile
local definers=fonts.definers
local readers=fonts.readers
@@ -5606,7 +5916,7 @@ local afm=constructors.newhandler("afm")
local pfb=constructors.newhandler("pfb")
local afmfeatures=constructors.newfeatures("afm")
local registerafmfeature=afmfeatures.register
-afm.version=1.410
+afm.version=1.500
afm.cache=containers.define("fonts","afm",afm.version,true)
afm.autoprefixed=true
afm.helpdata={}
@@ -5614,6 +5924,7 @@ afm.syncspace=true
afm.addligatures=true
afm.addtexligatures=true
afm.addkerns=true
+local overloads=fonts.mappings.overloads
local applyruntimefixes=fonts.treatments and fonts.treatments.applyfixes
local function setmode(tfmdata,value)
if value then
@@ -5801,7 +6112,7 @@ local function readafm(filename)
return nil
end
end
-local addkerns,addligatures,addtexligatures,unify,normalize
+local addkerns,addligatures,addtexligatures,unify,normalize,fixnames
function afm.load(filename)
filename=resolvers.findfile(filename,'afm') or ""
if filename~="" and not fonts.names.ignoredfile(filename) then
@@ -5844,6 +6155,7 @@ function afm.load(filename)
addkerns(data)
end
normalize(data)
+ fixnames(data)
report_afm("add tounicode data")
fonts.mappings.addtounicode(data,filename)
data.size=size
@@ -5851,6 +6163,7 @@ function afm.load(filename)
data.pfbsize=pfbsize
data.pfbtime=pfbtime
report_afm("saving %a in cache",name)
+ data.resources.unicodes=nil
data=containers.write(afm.cache,name,data)
data=containers.read(afm.cache,name)
end
@@ -5910,18 +6223,30 @@ unify=function(data,filename)
local filename=resources.filename or file.removesuffix(file.basename(filename))
resources.filename=resolvers.unresolve(filename)
resources.unicodes=unicodes
- resources.marks={}
- resources.names=names
+ resources.marks={}
resources.private=private
end
normalize=function(data)
end
+fixnames=function(data)
+ for k,v in next,data.descriptions do
+ local n=v.name
+ local r=overloads[n]
+ if r then
+ local name=r.name
+ if trace_indexing then
+ report_afm("renaming characters %a to %a",n,name)
+ end
+ v.name=name
+ v.unicode=r.unicode
+ end
+ end
+end
local addthem=function(rawdata,ligatures)
if ligatures then
local descriptions=rawdata.descriptions
local resources=rawdata.resources
local unicodes=resources.unicodes
- local names=resources.names
for ligname,ligdata in next,ligatures do
local one=descriptions[unicodes[ligname]]
if one then
@@ -6054,8 +6379,8 @@ local function copytotfm(data)
local filename=constructors.checkedfilename(resources)
local fontname=metadata.fontname or metadata.fullname
local fullname=metadata.fullname or metadata.fontname
- local endash=unicodes['space']
- local emdash=unicodes['emdash']
+ local endash=0x0020
+ local emdash=0x2014
local spacer="space"
local spaceunits=500
local monospaced=metadata.isfixedpitch
@@ -6109,7 +6434,7 @@ local function copytotfm(data)
if charxheight then
parameters.x_height=charxheight
else
- local x=unicodes['x']
+ local x=0x0078
if x then
local x=descriptions[x]
if x then
@@ -6156,7 +6481,34 @@ function afm.setfeatures(tfmdata,features)
return {}
end
end
-local function checkfeatures(specification)
+local function addtables(data)
+ local resources=data.resources
+ local lookuptags=resources.lookuptags
+ local unicodes=resources.unicodes
+ if not lookuptags then
+ lookuptags={}
+ resources.lookuptags=lookuptags
+ end
+ setmetatableindex(lookuptags,function(t,k)
+ local v=type(k)=="number" and ("lookup "..k) or k
+ t[k]=v
+ return v
+ end)
+ if not unicodes then
+ unicodes={}
+ resources.unicodes=unicodes
+ setmetatableindex(unicodes,function(t,k)
+ setmetatableindex(unicodes,nil)
+ for u,d in next,data.descriptions do
+ local n=d.name
+ if n then
+ t[n]=u
+ end
+ end
+ return rawget(t,k)
+ end)
+ end
+ constructors.addcoreunicodes(unicodes)
end
local function afmtotfm(specification)
local afmname=specification.filename or specification.name
@@ -6183,6 +6535,7 @@ local function afmtotfm(specification)
if not tfmdata then
local rawdata=afm.load(afmname)
if rawdata and next(rawdata) then
+ addtables(rawdata)
adddimensions(rawdata)
tfmdata=copytotfm(rawdata)
if tfmdata and next(tfmdata) then
@@ -6217,6 +6570,7 @@ end
local function prepareligatures(tfmdata,ligatures,value)
if value then
local descriptions=tfmdata.descriptions
+ local hasligatures=false
for unicode,character in next,tfmdata.characters do
local description=descriptions[unicode]
local dligatures=description.ligatures
@@ -6232,8 +6586,10 @@ local function prepareligatures(tfmdata,ligatures,value)
type=0
}
end
+ hasligatures=true
end
end
+ tfmdata.properties.hasligatures=hasligatures
end
end
local function preparekerns(tfmdata,kerns,value)
@@ -6242,6 +6598,7 @@ local function preparekerns(tfmdata,kerns,value)
local resources=rawdata.resources
local unicodes=resources.unicodes
local descriptions=tfmdata.descriptions
+ local haskerns=false
for u,chr in next,tfmdata.characters do
local d=descriptions[u]
local newkerns=d[kerns]
@@ -6257,8 +6614,10 @@ local function preparekerns(tfmdata,kerns,value)
kerns[uk]=v
end
end
+ haskerns=true
end
end
+ tfmdata.properties.haskerns=haskerns
end
end
local list={
@@ -6688,6 +7047,8 @@ local reversed,concat,remove,sortedkeys=table.reversed,table.concat,table.remove
local ioflush=io.flush
local fastcopy,tohash,derivetable=table.fastcopy,table.tohash,table.derive
local formatters=string.formatters
+local P,R,S,C,Ct,lpegmatch=lpeg.P,lpeg.R,lpeg.S,lpeg.C,lpeg.Ct,lpeg.match
+local setmetatableindex=table.setmetatableindex
local allocate=utilities.storage.allocate
local registertracker=trackers.register
local registerdirective=directives.register
@@ -6702,26 +7063,27 @@ local trace_dynamics=false registertracker("otf.dynamics",function(v) trace_dyna
local trace_sequences=false registertracker("otf.sequences",function(v) trace_sequences=v end)
local trace_markwidth=false registertracker("otf.markwidth",function(v) trace_markwidth=v end)
local trace_defining=false registertracker("fonts.defining",function(v) trace_defining=v end)
+local compact_lookups=true registertracker("otf.compactlookups",function(v) compact_lookups=v end)
+local purge_names=true registertracker("otf.purgenames",function(v) purge_names=v end)
local report_otf=logs.reporter("fonts","otf loading")
local fonts=fonts
local otf=fonts.handlers.otf
otf.glists={ "gsub","gpos" }
-otf.version=2.760
+otf.version=2.802
otf.cache=containers.define("fonts","otf",otf.version,true)
local fontdata=fonts.hashes.identifiers
local chardata=characters and characters.data
-local otffeatures=fonts.constructors.newfeatures("otf")
+local definers=fonts.definers
+local readers=fonts.readers
+local constructors=fonts.constructors
+local otffeatures=constructors.newfeatures("otf")
local registerotffeature=otffeatures.register
local enhancers=allocate()
otf.enhancers=enhancers
local patches={}
enhancers.patches=patches
-local definers=fonts.definers
-local readers=fonts.readers
-local constructors=fonts.constructors
local forceload=false
local cleanup=0
-local usemetatables=false
local packdata=true
local syncspace=true
local forcenotdef=false
@@ -6740,7 +7102,6 @@ formats.ttc="truetype"
formats.dfont="truetype"
registerdirective("fonts.otf.loader.cleanup",function(v) cleanup=tonumber(v) or (v and 1) or 0 end)
registerdirective("fonts.otf.loader.force",function(v) forceload=v end)
-registerdirective("fonts.otf.loader.usemetatables",function(v) usemetatables=v end)
registerdirective("fonts.otf.loader.pack",function(v) packdata=v end)
registerdirective("fonts.otf.loader.syncspace",function(v) syncspace=v end)
registerdirective("fonts.otf.loader.forcenotdef",function(v) forcenotdef=v end)
@@ -6869,7 +7230,6 @@ local ordered_enhancers={
"prepare lookups",
"analyze glyphs",
"analyze math",
- "prepare tounicode",
"reorganize lookups",
"reorganize mark classes",
"reorganize anchor classes",
@@ -6882,9 +7242,12 @@ local ordered_enhancers={
"check glyphs",
"check metadata",
"check extra features",
+ "prepare tounicode",
"check encoding",
"add duplicates",
"cleanup tables",
+ "compact lookups",
+ "purge names",
}
local actions=allocate()
local before=allocate()
@@ -7075,7 +7438,7 @@ function otf.load(filename,sub,featurefile)
goodies={},
helpers={
tounicodelist=splitter,
- tounicodetable=lpeg.Ct(splitter),
+ tounicodetable=Ct(splitter),
},
}
starttiming(data)
@@ -7118,6 +7481,34 @@ function otf.load(filename,sub,featurefile)
report_otf("loading from cache using hash %a",hash)
end
enhance("unpack",data,filename,nil,false)
+ local resources=data.resources
+ local lookuptags=resources.lookuptags
+ local unicodes=resources.unicodes
+ if not lookuptags then
+ lookuptags={}
+ resources.lookuptags=lookuptags
+ end
+ setmetatableindex(lookuptags,function(t,k)
+ local v=type(k)=="number" and ("lookup "..k) or k
+ t[k]=v
+ return v
+ end)
+ if not unicodes then
+ unicodes={}
+ resources.unicodes=unicodes
+ setmetatableindex(unicodes,function(t,k)
+ setmetatableindex(unicodes,nil)
+ for u,d in next,data.descriptions do
+ local n=d.name
+ if n then
+ t[n]=u
+ else
+ end
+ end
+ return rawget(t,k)
+ end)
+ end
+ constructors.addcoreunicodes(unicodes)
if applyruntimefixes then
applyruntimefixes(filename,data)
end
@@ -7154,34 +7545,22 @@ actions["add dimensions"]=function(data,filename)
local defaultheight=resources.defaultheight or 0
local defaultdepth=resources.defaultdepth or 0
local basename=trace_markwidth and file.basename(filename)
- if usemetatables then
- for _,d in next,descriptions do
- local wd=d.width
- if not wd then
- d.width=defaultwidth
- elseif trace_markwidth and wd~=0 and d.class=="mark" then
- report_otf("mark %a with width %b found in %a",d.name or "<noname>",wd,basename)
- end
- setmetatable(d,mt)
+ for _,d in next,descriptions do
+ local bb,wd=d.boundingbox,d.width
+ if not wd then
+ d.width=defaultwidth
+ elseif trace_markwidth and wd~=0 and d.class=="mark" then
+ report_otf("mark %a with width %b found in %a",d.name or "<noname>",wd,basename)
end
- else
- for _,d in next,descriptions do
- local bb,wd=d.boundingbox,d.width
- if not wd then
- d.width=defaultwidth
- elseif trace_markwidth and wd~=0 and d.class=="mark" then
- report_otf("mark %a with width %b found in %a",d.name or "<noname>",wd,basename)
- end
- if bb then
- local ht,dp=bb[4],-bb[2]
- if ht==0 or ht<0 then
- else
- d.height=ht
- end
- if dp==0 or dp<0 then
- else
- d.depth=dp
- end
+ if bb then
+ local ht,dp=bb[4],-bb[2]
+ if ht==0 or ht<0 then
+ else
+ d.height=ht
+ end
+ if dp==0 or dp<0 then
+ else
+ d.depth=dp
end
end
end
@@ -7249,13 +7628,13 @@ actions["prepare glyphs"]=function(data,filename,raw)
local glyph=cidglyphs[index]
if glyph then
local unicode=glyph.unicode
-if unicode>=0x00E000 and unicode<=0x00F8FF then
+ if unicode>=0x00E000 and unicode<=0x00F8FF then
unicode=-1
-elseif unicode>=0x0F0000 and unicode<=0x0FFFFD then
+ elseif unicode>=0x0F0000 and unicode<=0x0FFFFD then
unicode=-1
-elseif unicode>=0x100000 and unicode<=0x10FFFD then
+ elseif unicode>=0x100000 and unicode<=0x10FFFD then
unicode=-1
-end
+ end
local name=glyph.name or cidnames[index]
if not unicode or unicode==-1 then
unicode=cidunicodes[index]
@@ -7451,8 +7830,8 @@ actions["add duplicates"]=function(data,filename,raw)
local description=descriptions[unicode]
local n=0
for _,description in next,descriptions do
+ local kerns=description.kerns
if kerns then
- local kerns=description.kerns
for _,k in next,kerns do
local ku=k[unicode]
if ku then
@@ -7746,9 +8125,14 @@ local function t_hashed(t,cache)
local ti=t[i]
local tih=cache[ti]
if not tih then
- tih={}
- for i=1,#ti do
- tih[ti[i]]=true
+ local tn=#ti
+ if tn==1 then
+ tih={ [ti[1]]=true }
+ else
+ tih={}
+ for i=1,tn do
+ tih[ti[i]]=true
+ end
end
cache[ti]=tih
end
@@ -7761,12 +8145,17 @@ local function t_hashed(t,cache)
end
local function s_hashed(t,cache)
if t then
- local ht={}
local tf=t[1]
- for i=1,#tf do
- ht[i]={ [tf[i]]=true }
+ local nf=#tf
+ if nf==1 then
+ return { [tf[1]]=true }
+ else
+ local ht={}
+ for i=1,nf do
+ ht[i]={ [tf[i]]=true }
+ end
+ return ht
end
- return ht
else
return nil
end
@@ -8194,7 +8583,7 @@ actions["check glyphs"]=function(data,filename,raw)
description.glyph=nil
end
end
-local valid=(lpeg.R("\x00\x7E")-lpeg.S("(){}[]<>%/ \n\r\f\v"))^0*lpeg.P(-1)
+local valid=(R("\x00\x7E")-S("(){}[]<>%/ \n\r\f\v"))^0*P(-1)
local function valid_ps_name(str)
return str and str~="" and #str<64 and lpegmatch(valid,str) and true or false
end
@@ -8248,8 +8637,17 @@ actions["check metadata"]=function(data,filename,raw)
end
end
actions["cleanup tables"]=function(data,filename,raw)
+ local duplicates=data.resources.duplicates
+ if duplicates then
+ for k,v in next,duplicates do
+ if #v==1 then
+ duplicates[k]=v[1]
+ end
+ end
+ end
data.resources.indices=nil
- data.helpers=nil
+ data.resources.unicodes=nil
+ data.helpers=nil
end
actions["reorganize glyph lookups"]=function(data,filename,raw)
local resources=data.resources
@@ -8354,6 +8752,142 @@ actions["reorganize glyph anchors"]=function(data,filename,raw)
end
end
end
+local bogusname=(P("uni")+P("u"))*R("AF","09")^4+(P("index")+P("glyph")+S("Ii")*P("dentity")*P(".")^0)*R("09")^1
+local uselessname=(1-bogusname)^0*bogusname
+actions["purge names"]=function(data,filename,raw)
+ if purge_names then
+ local n=0
+ for u,d in next,data.descriptions do
+ if lpegmatch(uselessname,d.name) then
+ n=n+1
+ d.name=nil
+ end
+ end
+ if n>0 then
+ report_otf("%s bogus names removed",n)
+ end
+ end
+end
+actions["compact lookups"]=function(data,filename,raw)
+ if not compact_lookups then
+ report_otf("not compacting")
+ return
+ end
+ local last=0
+ local tags=table.setmetatableindex({},
+ function(t,k)
+ last=last+1
+ t[k]=last
+ return last
+ end
+ )
+ local descriptions=data.descriptions
+ local resources=data.resources
+ for u,d in next,descriptions do
+ local slookups=d.slookups
+ if type(slookups)=="table" then
+ local s={}
+ for k,v in next,slookups do
+ s[tags[k]]=v
+ end
+ d.slookups=s
+ end
+ local mlookups=d.mlookups
+ if type(mlookups)=="table" then
+ local m={}
+ for k,v in next,mlookups do
+ m[tags[k]]=v
+ end
+ d.mlookups=m
+ end
+ local kerns=d.kerns
+ if type(kerns)=="table" then
+ local t={}
+ for k,v in next,kerns do
+ t[tags[k]]=v
+ end
+ d.kerns=t
+ end
+ end
+ local lookups=data.lookups
+ if lookups then
+ local l={}
+ for k,v in next,lookups do
+ local rules=v.rules
+ if rules then
+ for i=1,#rules do
+ local l=rules[i].lookups
+ if type(l)=="table" then
+ for i=1,#l do
+ l[i]=tags[l[i]]
+ end
+ end
+ end
+ end
+ l[tags[k]]=v
+ end
+ data.lookups=l
+ end
+ local lookups=resources.lookups
+ if lookups then
+ local l={}
+ for k,v in next,lookups do
+ local s=v.subtables
+ if type(s)=="table" then
+ for i=1,#s do
+ s[i]=tags[s[i]]
+ end
+ end
+ l[tags[k]]=v
+ end
+ resources.lookups=l
+ end
+ local sequences=resources.sequences
+ if sequences then
+ for i=1,#sequences do
+ local s=sequences[i]
+ local n=s.name
+ if n then
+ s.name=tags[n]
+ end
+ local t=s.subtables
+ if type(t)=="table" then
+ for i=1,#t do
+ t[i]=tags[t[i]]
+ end
+ end
+ end
+ end
+ local lookuptypes=resources.lookuptypes
+ if lookuptypes then
+ local l={}
+ for k,v in next,lookuptypes do
+ l[tags[k]]=v
+ end
+ resources.lookuptypes=l
+ end
+ local anchor_to_lookup=resources.anchor_to_lookup
+ if anchor_to_lookup then
+ for anchor,lookups in next,anchor_to_lookup do
+ local l={}
+ for lookup,value in next,lookups do
+ l[tags[lookup]]=value
+ end
+ anchor_to_lookup[anchor]=l
+ end
+ end
+ local lookup_to_anchor=resources.lookup_to_anchor
+ if lookup_to_anchor then
+ local l={}
+ for lookup,value in next,lookup_to_anchor do
+ l[tags[lookup]]=value
+ end
+ resources.lookup_to_anchor=l
+ end
+ tags=table.swapped(tags)
+ report_otf("%s lookup tags compacted",#tags)
+ resources.lookuptags=tags
+end
function otf.setfeatures(tfmdata,features)
local okay=constructors.initializefeatures("otf",tfmdata,features,trace_features,report_otf)
if okay then
@@ -8455,8 +8989,8 @@ local function copytotfm(data,cache_id)
parameters.italicangle=italicangle
parameters.charwidth=charwidth
parameters.charxheight=charxheight
- local space=0x0020
- local emdash=0x2014
+ local space=0x0020
+ local emdash=0x2014
if monospaced then
if descriptions[space] then
spaceunits,spacer=descriptions[space].width,"space"
@@ -8503,7 +9037,7 @@ local function copytotfm(data,cache_id)
if charxheight then
parameters.x_height=charxheight
else
- local x=0x78
+ local x=0x0078
if x then
local x=descriptions[x]
if x then
@@ -8559,14 +9093,23 @@ local function otftotfm(specification)
if duplicates then
local nofduplicates,nofduplicated=0,0
for parent,list in next,duplicates do
- for i=1,#list do
- local unicode=list[i]
- if not descriptions[unicode] then
- descriptions[unicode]=descriptions[parent]
+ if type(list)=="table" then
+ local n=#list
+ for i=1,n do
+ local unicode=list[i]
+ if not descriptions[unicode] then
+ descriptions[unicode]=descriptions[parent]
+ nofduplicated=nofduplicated+1
+ end
+ end
+ nofduplicates=nofduplicates+n
+ else
+ if not descriptions[list] then
+ descriptions[list]=descriptions[parent]
nofduplicated=nofduplicated+1
end
+ nofduplicates=nofduplicates+1
end
- nofduplicates=nofduplicates+#list
end
if trace_otf and nofduplicated~=nofduplicates then
report_otf("%i extra duplicates copied out of %i",nofduplicated,nofduplicates)
@@ -8697,7 +9240,7 @@ if not modules then modules={} end modules ['font-otb']={
}
local concat=table.concat
local format,gmatch,gsub,find,match,lower,strip=string.format,string.gmatch,string.gsub,string.find,string.match,string.lower,string.strip
-local type,next,tonumber,tostring=type,next,tonumber,tostring
+local type,next,tonumber,tostring,rawget=type,next,tonumber,tostring,rawget
local lpegmatch=lpeg.match
local utfchar=utf.char
local trace_baseinit=false trackers.register("otf.baseinit",function(v) trace_baseinit=v end)
@@ -8744,36 +9287,36 @@ local function gref(descriptions,n)
return "<error in base mode tracing>"
end
end
-local function cref(feature,lookupname)
+local function cref(feature,lookuptags,lookupname)
if lookupname then
- return formatters["feature %a, lookup %a"](feature,lookupname)
+ return formatters["feature %a, lookup %a"](feature,lookuptags[lookupname])
else
return formatters["feature %a"](feature)
end
end
-local function report_alternate(feature,lookupname,descriptions,unicode,replacement,value,comment)
+local function report_alternate(feature,lookuptags,lookupname,descriptions,unicode,replacement,value,comment)
report_prepare("%s: base alternate %s => %s (%S => %S)",
- cref(feature,lookupname),
+ cref(feature,lookuptags,lookupname),
gref(descriptions,unicode),
replacement and gref(descriptions,replacement),
value,
comment)
end
-local function report_substitution(feature,lookupname,descriptions,unicode,substitution)
+local function report_substitution(feature,lookuptags,lookupname,descriptions,unicode,substitution)
report_prepare("%s: base substitution %s => %S",
- cref(feature,lookupname),
+ cref(feature,lookuptags,lookupname),
gref(descriptions,unicode),
gref(descriptions,substitution))
end
-local function report_ligature(feature,lookupname,descriptions,unicode,ligature)
+local function report_ligature(feature,lookuptags,lookupname,descriptions,unicode,ligature)
report_prepare("%s: base ligature %s => %S",
- cref(feature,lookupname),
+ cref(feature,lookuptags,lookupname),
gref(descriptions,ligature),
gref(descriptions,unicode))
end
-local function report_kern(feature,lookupname,descriptions,unicode,otherunicode,value)
+local function report_kern(feature,lookuptags,lookupname,descriptions,unicode,otherunicode,value)
report_prepare("%s: base kern %s + %s => %S",
- cref(feature,lookupname),
+ cref(feature,lookuptags,lookupname),
gref(descriptions,unicode),
gref(descriptions,otherunicode),
value)
@@ -8810,7 +9353,7 @@ local function finalize_ligatures(tfmdata,ligatures)
local characters=tfmdata.characters
local descriptions=tfmdata.descriptions
local resources=tfmdata.resources
- local unicodes=resources.unicodes
+ local unicodes=resources.unicodes
local private=resources.private
local alldone=false
while not alldone do
@@ -8846,12 +9389,12 @@ local function finalize_ligatures(tfmdata,ligatures)
local secondname=firstname.."_"..secondcode
if i==size-1 then
target=unicode
- if not unicodes[secondname] then
+ if not rawget(unicodes,secondname) then
unicodes[secondname]=unicode
end
okay=true
else
- target=unicodes[secondname]
+ target=rawget(unicodes,secondname)
if not target then
break
end
@@ -8887,16 +9430,18 @@ local function finalize_ligatures(tfmdata,ligatures)
end
end
resources.private=private
+ return true
end
end
local function preparesubstitutions(tfmdata,feature,value,validlookups,lookuplist)
local characters=tfmdata.characters
local descriptions=tfmdata.descriptions
local resources=tfmdata.resources
+ local properties=tfmdata.properties
local changed=tfmdata.changed
- local unicodes=resources.unicodes
local lookuphash=resources.lookuphash
local lookuptypes=resources.lookuptypes
+ local lookuptags=resources.lookuptags
local ligatures={}
local alternate=tonumber(value) or true and 1
local defaultalt=otf.defaultbasealternate
@@ -8904,39 +9449,39 @@ local function preparesubstitutions(tfmdata,feature,value,validlookups,lookuplis
local trace_alternatives=trace_baseinit and trace_alternatives
local trace_ligatures=trace_baseinit and trace_ligatures
local actions={
- substitution=function(lookupdata,lookupname,description,unicode)
+ substitution=function(lookupdata,lookuptags,lookupname,description,unicode)
if trace_singles then
- report_substitution(feature,lookupname,descriptions,unicode,lookupdata)
+ report_substitution(feature,lookuptags,lookupname,descriptions,unicode,lookupdata)
end
changed[unicode]=lookupdata
end,
- alternate=function(lookupdata,lookupname,description,unicode)
+ alternate=function(lookupdata,lookuptags,lookupname,description,unicode)
local replacement=lookupdata[alternate]
if replacement then
changed[unicode]=replacement
if trace_alternatives then
- report_alternate(feature,lookupname,descriptions,unicode,replacement,value,"normal")
+ report_alternate(feature,lookuptags,lookupname,descriptions,unicode,replacement,value,"normal")
end
elseif defaultalt=="first" then
replacement=lookupdata[1]
changed[unicode]=replacement
if trace_alternatives then
- report_alternate(feature,lookupname,descriptions,unicode,replacement,value,defaultalt)
+ report_alternate(feature,lookuptags,lookupname,descriptions,unicode,replacement,value,defaultalt)
end
elseif defaultalt=="last" then
replacement=lookupdata[#data]
if trace_alternatives then
- report_alternate(feature,lookupname,descriptions,unicode,replacement,value,defaultalt)
+ report_alternate(feature,lookuptags,lookupname,descriptions,unicode,replacement,value,defaultalt)
end
else
if trace_alternatives then
- report_alternate(feature,lookupname,descriptions,unicode,replacement,value,"unknown")
+ report_alternate(feature,lookuptags,lookupname,descriptions,unicode,replacement,value,"unknown")
end
end
end,
- ligature=function(lookupdata,lookupname,description,unicode)
+ ligature=function(lookupdata,lookuptags,lookupname,description,unicode)
if trace_ligatures then
- report_ligature(feature,lookupname,descriptions,unicode,lookupdata)
+ report_ligature(feature,lookuptags,lookupname,descriptions,unicode,lookupdata)
end
ligatures[#ligatures+1]={ unicode,lookupdata }
end,
@@ -8952,7 +9497,7 @@ local function preparesubstitutions(tfmdata,feature,value,validlookups,lookuplis
local lookuptype=lookuptypes[lookupname]
local action=actions[lookuptype]
if action then
- action(lookupdata,lookupname,description,unicode)
+ action(lookupdata,lookuptags,lookupname,description,unicode)
end
end
end
@@ -8967,22 +9512,24 @@ local function preparesubstitutions(tfmdata,feature,value,validlookups,lookuplis
local action=actions[lookuptype]
if action then
for i=1,#lookuplist do
- action(lookuplist[i],lookupname,description,unicode)
+ action(lookuplist[i],lookuptags,lookupname,description,unicode)
end
end
end
end
end
end
- finalize_ligatures(tfmdata,ligatures)
+ properties.hasligatures=finalize_ligatures(tfmdata,ligatures)
end
local function preparepositionings(tfmdata,feature,value,validlookups,lookuplist)
local characters=tfmdata.characters
local descriptions=tfmdata.descriptions
local resources=tfmdata.resources
- local unicodes=resources.unicodes
+ local properties=tfmdata.properties
+ local lookuptags=resources.lookuptags
local sharedkerns={}
local traceindeed=trace_baseinit and trace_kerns
+ local haskerns=false
for unicode,character in next,characters do
local description=descriptions[unicode]
local rawkerns=description.kerns
@@ -9004,13 +9551,13 @@ local function preparepositionings(tfmdata,feature,value,validlookups,lookuplist
newkerns={ [otherunicode]=value }
done=true
if traceindeed then
- report_kern(feature,lookup,descriptions,unicode,otherunicode,value)
+ report_kern(feature,lookuptags,lookup,descriptions,unicode,otherunicode,value)
end
elseif not newkerns[otherunicode] then
newkerns[otherunicode]=value
done=true
if traceindeed then
- report_kern(feature,lookup,descriptions,unicode,otherunicode,value)
+ report_kern(feature,lookuptags,lookup,descriptions,unicode,otherunicode,value)
end
end
end
@@ -9019,12 +9566,14 @@ local function preparepositionings(tfmdata,feature,value,validlookups,lookuplist
if done then
sharedkerns[rawkerns]=newkerns
character.kerns=newkerns
+ haskerns=true
else
sharedkerns[rawkerns]=false
end
end
end
end
+ properties.haskerns=haskerns
end
basemethods.independent={
preparesubstitutions=preparesubstitutions,
@@ -9050,13 +9599,13 @@ local function make_1(present,tree,name)
end
end
end
-local function make_2(present,tfmdata,characters,tree,name,preceding,unicode,done,lookupname)
+local function make_2(present,tfmdata,characters,tree,name,preceding,unicode,done,lookuptags,lookupname)
for k,v in next,tree do
if k=="ligature" then
local character=characters[preceding]
if not character then
if trace_baseinit then
- report_prepare("weird ligature in lookup %a, current %C, preceding %C",lookupname,v,preceding)
+ report_prepare("weird ligature in lookup %a, current %C, preceding %C",lookuptags[lookupname],v,preceding)
end
character=makefake(tfmdata,name,present)
end
@@ -9077,7 +9626,7 @@ local function make_2(present,tfmdata,characters,tree,name,preceding,unicode,don
else
local code=present[name] or unicode
local name=name.."_"..k
- make_2(present,tfmdata,characters,v,name,code,k,done,lookupname)
+ make_2(present,tfmdata,characters,v,name,code,k,done,lookuptags,lookupname)
end
end
end
@@ -9088,6 +9637,7 @@ local function preparesubstitutions(tfmdata,feature,value,validlookups,lookuplis
local changed=tfmdata.changed
local lookuphash=resources.lookuphash
local lookuptypes=resources.lookuptypes
+ local lookuptags=resources.lookuptags
local ligatures={}
local alternate=tonumber(value) or true and 1
local defaultalt=otf.defaultbasealternate
@@ -9101,7 +9651,7 @@ local function preparesubstitutions(tfmdata,feature,value,validlookups,lookuplis
for unicode,data in next,lookupdata do
if lookuptype=="substitution" then
if trace_singles then
- report_substitution(feature,lookupname,descriptions,unicode,data)
+ report_substitution(feature,lookuptags,lookupname,descriptions,unicode,data)
end
changed[unicode]=data
elseif lookuptype=="alternate" then
@@ -9109,28 +9659,28 @@ local function preparesubstitutions(tfmdata,feature,value,validlookups,lookuplis
if replacement then
changed[unicode]=replacement
if trace_alternatives then
- report_alternate(feature,lookupname,descriptions,unicode,replacement,value,"normal")
+ report_alternate(feature,lookuptags,lookupname,descriptions,unicode,replacement,value,"normal")
end
elseif defaultalt=="first" then
replacement=data[1]
changed[unicode]=replacement
if trace_alternatives then
- report_alternate(feature,lookupname,descriptions,unicode,replacement,value,defaultalt)
+ report_alternate(feature,lookuptags,lookupname,descriptions,unicode,replacement,value,defaultalt)
end
elseif defaultalt=="last" then
replacement=data[#data]
if trace_alternatives then
- report_alternate(feature,lookupname,descriptions,unicode,replacement,value,defaultalt)
+ report_alternate(feature,lookuptags,lookupname,descriptions,unicode,replacement,value,defaultalt)
end
else
if trace_alternatives then
- report_alternate(feature,lookupname,descriptions,unicode,replacement,value,"unknown")
+ report_alternate(feature,lookuptags,lookupname,descriptions,unicode,replacement,value,"unknown")
end
end
elseif lookuptype=="ligature" then
ligatures[#ligatures+1]={ unicode,data,lookupname }
if trace_ligatures then
- report_ligature(feature,lookupname,descriptions,unicode,data)
+ report_ligature(feature,lookuptags,lookupname,descriptions,unicode,data)
end
end
end
@@ -9148,7 +9698,7 @@ local function preparesubstitutions(tfmdata,feature,value,validlookups,lookuplis
for i=1,nofligatures do
local ligature=ligatures[i]
local unicode,tree,lookupname=ligature[1],ligature[2],ligature[3]
- make_2(present,tfmdata,characters,tree,"ctx_"..unicode,unicode,unicode,done,lookupname)
+ make_2(present,tfmdata,characters,tree,"ctx_"..unicode,unicode,unicode,done,lookuptags,lookupname)
end
end
end
@@ -9156,7 +9706,9 @@ local function preparepositionings(tfmdata,feature,value,validlookups,lookuplist
local characters=tfmdata.characters
local descriptions=tfmdata.descriptions
local resources=tfmdata.resources
+ local properties=tfmdata.properties
local lookuphash=resources.lookuphash
+ local lookuptags=resources.lookuptags
local traceindeed=trace_baseinit and trace_kerns
for l=1,#lookuplist do
local lookupname=lookuplist[l]
@@ -9172,7 +9724,7 @@ local function preparepositionings(tfmdata,feature,value,validlookups,lookuplist
for otherunicode,kern in next,data do
if not kerns[otherunicode] and kern~=0 then
kerns[otherunicode]=kern
- report_kern(feature,lookup,descriptions,unicode,otherunicode,kern)
+ report_kern(feature,lookuptags,lookup,descriptions,unicode,otherunicode,kern)
end
end
else
@@ -9285,11 +9837,24 @@ local injections=nodes.injections
local nodecodes=nodes.nodecodes
local glyph_code=nodecodes.glyph
local kern_code=nodecodes.kern
-local nodepool=nodes.pool
+local nuts=nodes.nuts
+local nodepool=nuts.pool
local newkern=nodepool.kern
-local traverse_id=node.traverse_id
-local insert_node_before=node.insert_before
-local insert_node_after=node.insert_after
+local tonode=nuts.tonode
+local tonut=nuts.tonut
+local getfield=nuts.getfield
+local getnext=nuts.getnext
+local getprev=nuts.getprev
+local getid=nuts.getid
+local getattr=nuts.getattr
+local getfont=nuts.getfont
+local getsubtype=nuts.getsubtype
+local getchar=nuts.getchar
+local setfield=nuts.setfield
+local setattr=nuts.setattr
+local traverse_id=nuts.traverse_id
+local insert_node_before=nuts.insert_before
+local insert_node_after=nuts.insert_after
local a_kernpair=attributes.private('kernpair')
local a_ligacomp=attributes.private('ligacomp')
local a_markbase=attributes.private('markbase')
@@ -9298,31 +9863,40 @@ local a_markdone=attributes.private('markdone')
local a_cursbase=attributes.private('cursbase')
local a_curscurs=attributes.private('curscurs')
local a_cursdone=attributes.private('cursdone')
+local unsetvalue=attributes.unsetvalue
function injections.installnewkern(nk)
newkern=nk or newkern
end
local cursives={}
local marks={}
local kerns={}
+function injections.reset(n)
+end
+function injections.setligaindex(n,index)
+ setattr(n,a_ligacomp,index)
+end
+function injections.getligaindex(n,default)
+ return getattr(n,a_ligacomp) or default
+end
function injections.setcursive(start,nxt,factor,rlmode,exit,entry,tfmstart,tfmnext)
local dx,dy=factor*(exit[1]-entry[1]),factor*(exit[2]-entry[2])
local ws,wn=tfmstart.width,tfmnext.width
local bound=#cursives+1
- start[a_cursbase]=bound
- nxt[a_curscurs]=bound
+ setattr(start,a_cursbase,bound)
+ setattr(nxt,a_curscurs,bound)
cursives[bound]={ rlmode,dx,dy,ws,wn }
return dx,dy,bound
end
function injections.setpair(current,factor,rlmode,r2lflag,spec,tfmchr)
local x,y,w,h=factor*spec[1],factor*spec[2],factor*spec[3],factor*spec[4]
if x~=0 or w~=0 or y~=0 or h~=0 then
- local bound=current[a_kernpair]
+ local bound=getattr(current,a_kernpair)
if bound then
local kb=kerns[bound]
kb[2],kb[3],kb[4],kb[5]=(kb[2] or 0)+x,(kb[3] or 0)+y,(kb[4] or 0)+w,(kb[5] or 0)+h
else
bound=#kerns+1
- current[a_kernpair]=bound
+ setattr(current,a_kernpair,bound)
kerns[bound]={ rlmode,x,y,w,h,r2lflag,tfmchr.width }
end
return x,y,w,h,bound
@@ -9333,7 +9907,7 @@ function injections.setkern(current,factor,rlmode,x,tfmchr)
local dx=factor*x
if dx~=0 then
local bound=#kerns+1
- current[a_kernpair]=bound
+ setattr(current,a_kernpair,bound)
kerns[bound]={ rlmode,dx }
return dx,bound
else
@@ -9342,25 +9916,25 @@ function injections.setkern(current,factor,rlmode,x,tfmchr)
end
function injections.setmark(start,base,factor,rlmode,ba,ma)
local dx,dy=factor*(ba[1]-ma[1]),factor*(ba[2]-ma[2])
- local bound=base[a_markbase]
+ local bound=getattr(base,a_markbase)
local index=1
if bound then
local mb=marks[bound]
if mb then
index=#mb+1
mb[index]={ dx,dy,rlmode }
- start[a_markmark]=bound
- start[a_markdone]=index
+ setattr(start,a_markmark,bound)
+ setattr(start,a_markdone,index)
return dx,dy,bound
else
- report_injections("possible problem, %U is base mark without data (id %a)",base.char,bound)
+ report_injections("possible problem, %U is base mark without data (id %a)",getchar(base),bound)
end
end
index=index or 1
bound=#marks+1
- base[a_markbase]=bound
- start[a_markmark]=bound
- start[a_markdone]=index
+ setattr(base,a_markbase,bound)
+ setattr(start,a_markmark,bound)
+ setattr(start,a_markdone,index)
marks[bound]={ [index]={ dx,dy,rlmode } }
return dx,dy,bound
end
@@ -9370,15 +9944,15 @@ end
local function trace(head)
report_injections("begin run")
for n in traverse_id(glyph_code,head) do
- if n.subtype<256 then
- local kp=n[a_kernpair]
- local mb=n[a_markbase]
- local mm=n[a_markmark]
- local md=n[a_markdone]
- local cb=n[a_cursbase]
- local cc=n[a_curscurs]
- local char=n.char
- report_injections("font %s, char %U, glyph %c",n.font,char,char)
+ if getsubtype(n)<256 then
+ local kp=getattr(n,a_kernpair)
+ local mb=getattr(n,a_markbase)
+ local mm=getattr(n,a_markmark)
+ local md=getattr(n,a_markdone)
+ local cb=getattr(n,a_cursbase)
+ local cc=getattr(n,a_curscurs)
+ local char=getchar(n)
+ report_injections("font %s, char %U, glyph %c",getfont(n),char,char)
if kp then
local k=kerns[kp]
if k[3] then
@@ -9419,21 +9993,23 @@ local function show_result(head)
local current=head
local skipping=false
while current do
- local id=current.id
+ local id=getid(current)
if id==glyph_code then
- report_injections("char: %C, width %p, xoffset %p, yoffset %p",current.char,current.width,current.xoffset,current.yoffset)
+ report_injections("char: %C, width %p, xoffset %p, yoffset %p",
+ getchar(current),getfield(current,"width"),getfield(current,"xoffset"),getfield(current,"yoffset"))
skipping=false
elseif id==kern_code then
- report_injections("kern: %p",current.kern)
+ report_injections("kern: %p",getfield(current,"kern"))
skipping=false
elseif not skipping then
report_injections()
skipping=true
end
- current=current.next
+ current=getnext(current)
end
end
function injections.handler(head,where,keep)
+ head=tonut(head)
local has_marks,has_cursives,has_kerns=next(marks),next(cursives),next(kerns)
if has_marks or has_cursives then
if trace_injections then
@@ -9443,17 +10019,18 @@ function injections.handler(head,where,keep)
if has_kerns then
local nf,tm=nil,nil
for n in traverse_id(glyph_code,head) do
- if n.subtype<256 then
+ if getsubtype(n)<256 then
nofvalid=nofvalid+1
valid[nofvalid]=n
- if n.font~=nf then
- nf=n.font
- tm=fontdata[nf].resources.marks
+ local f=getfont(n)
+ if f~=nf then
+ nf=f
+ tm=fontdata[nf].resources.marks
end
if tm then
- mk[n]=tm[n.char]
+ mk[n]=tm[getchar(n)]
end
- local k=n[a_kernpair]
+ local k=getattr(n,a_kernpair)
if k then
local kk=kerns[k]
if kk then
@@ -9473,15 +10050,16 @@ function injections.handler(head,where,keep)
else
local nf,tm=nil,nil
for n in traverse_id(glyph_code,head) do
- if n.subtype<256 then
+ if getsubtype(n)<256 then
nofvalid=nofvalid+1
valid[nofvalid]=n
- if n.font~=nf then
- nf=n.font
- tm=fontdata[nf].resources.marks
+ local f=getfont(n)
+ if f~=nf then
+ nf=f
+ tm=fontdata[nf].resources.marks
end
if tm then
- mk[n]=tm[n.char]
+ mk[n]=tm[getchar(n)]
end
end
end
@@ -9490,7 +10068,7 @@ function injections.handler(head,where,keep)
local cx={}
if has_kerns and next(ky) then
for n,k in next,ky do
- n.yoffset=k
+ setfield(n,"yoffset",k)
end
end
if has_cursives then
@@ -9499,9 +10077,9 @@ function injections.handler(head,where,keep)
for i=1,nofvalid do
local n=valid[i]
if not mk[n] then
- local n_cursbase=n[a_cursbase]
+ local n_cursbase=getattr(n,a_cursbase)
if p_cursbase then
- local n_curscurs=n[a_curscurs]
+ local n_curscurs=getattr(n,a_curscurs)
if p_cursbase==n_curscurs then
local c=cursives[n_curscurs]
if c then
@@ -9524,20 +10102,20 @@ function injections.handler(head,where,keep)
end
end
elseif maxt>0 then
- local ny=n.yoffset
+ local ny=getfield(n,"yoffset")
for i=maxt,1,-1 do
ny=ny+d[i]
local ti=t[i]
- ti.yoffset=ti.yoffset+ny
+ setfield(ti,"yoffset",getfield(ti,"yoffset")+ny)
end
maxt=0
end
if not n_cursbase and maxt>0 then
- local ny=n.yoffset
+ local ny=getfield(n,"yoffset")
for i=maxt,1,-1 do
ny=ny+d[i]
local ti=t[i]
- ti.yoffset=ny
+ setfield(ti,"yoffset",ny)
end
maxt=0
end
@@ -9545,11 +10123,11 @@ function injections.handler(head,where,keep)
end
end
if maxt>0 then
- local ny=n.yoffset
+ local ny=getfield(n,"yoffset")
for i=maxt,1,-1 do
ny=ny+d[i]
local ti=t[i]
- ti.yoffset=ny
+ setfield(ti,"yoffset",ny)
end
maxt=0
end
@@ -9560,57 +10138,66 @@ function injections.handler(head,where,keep)
if has_marks then
for i=1,nofvalid do
local p=valid[i]
- local p_markbase=p[a_markbase]
+ local p_markbase=getattr(p,a_markbase)
if p_markbase then
local mrks=marks[p_markbase]
local nofmarks=#mrks
- for n in traverse_id(glyph_code,p.next) do
- local n_markmark=n[a_markmark]
+ for n in traverse_id(glyph_code,getnext(p)) do
+ local n_markmark=getattr(n,a_markmark)
if p_markbase==n_markmark then
- local index=n[a_markdone] or 1
+ local index=getattr(n,a_markdone) or 1
local d=mrks[index]
if d then
local rlmode=d[3]
local k=wx[p]
+ local px=getfield(p,"xoffset")
+ local ox=0
if k then
local x=k[2]
local w=k[4]
if w then
if rlmode and rlmode>=0 then
- n.xoffset=p.xoffset-p.width+d[1]-(w-x)
+ ox=px-getfield(p,"width")+d[1]-(w-x)
else
- n.xoffset=p.xoffset-d[1]-x
+ ox=px-d[1]-x
end
else
if rlmode and rlmode>=0 then
- n.xoffset=p.xoffset-p.width+d[1]
+ ox=px-getfield(p,"width")+d[1]
else
- n.xoffset=p.xoffset-d[1]-x
+ ox=px-d[1]-x
end
end
else
+ local wp=getfield(p,"width")
+ local wn=getfield(n,"width")
if rlmode and rlmode>=0 then
- n.xoffset=p.xoffset-p.width+d[1]
+ ox=px-wp+d[1]
else
- n.xoffset=p.xoffset-d[1]
+ ox=px-d[1]
end
- local w=n.width
- if w~=0 then
- insert_node_before(head,n,newkern(-w/2))
- insert_node_after(head,n,newkern(-w/2))
+ if wn~=0 then
+ insert_node_before(head,n,newkern(-wn/2))
+ insert_node_after(head,n,newkern(-wn/2))
end
end
+ setfield(n,"xoffset",ox)
+ local py=getfield(p,"yoffset")
+ local oy=0
if mk[p] then
- n.yoffset=p.yoffset+d[2]
+ oy=py+d[2]
else
- n.yoffset=n.yoffset+p.yoffset+d[2]
+ oy=getfield(n,"yoffset")+py+d[2]
end
+ setfield(n,"yoffset",oy)
if nofmarks==1 then
break
else
nofmarks=nofmarks-1
end
end
+ elseif not n_markmark then
+ break
else
end
end
@@ -9662,7 +10249,7 @@ function injections.handler(head,where,keep)
if not keep then
kerns={}
end
- return head,true
+ return tonode(head),true
elseif not keep then
kerns,cursives,marks={},{},{}
end
@@ -9671,14 +10258,14 @@ function injections.handler(head,where,keep)
trace(head)
end
for n in traverse_id(glyph_code,head) do
- if n.subtype<256 then
- local k=n[a_kernpair]
+ if getsubtype(n)<256 then
+ local k=getattr(n,a_kernpair)
if k then
local kk=kerns[k]
if kk then
local rl,x,y,w=kk[1],kk[2] or 0,kk[3],kk[4]
if y and y~=0 then
- n.yoffset=y
+ setfield(n,"yoffset",y)
end
if w then
local wx=w-x
@@ -9709,17 +10296,17 @@ function injections.handler(head,where,keep)
if not keep then
kerns={}
end
- return head,true
+ return tonode(head),true
else
end
- return head,false
+ return tonode(head),false
end
end -- closure
do -- begin closure to overcome local limits and interference
-if not modules then modules={} end modules ['font-ota']={
+if not modules then modules={} end modules ['font-otx']={
version=1.001,
comment="companion to font-otf.lua (analysing)",
author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
@@ -9738,13 +10325,24 @@ analyzers.initializers=initializers
analyzers.methods=methods
analyzers.useunicodemarks=false
local a_state=attributes.private('state')
+local nuts=nodes.nuts
+local tonut=nuts.tonut
+local getfield=nuts.getfield
+local getnext=nuts.getnext
+local getprev=nuts.getprev
+local getid=nuts.getid
+local getprop=nuts.getprop
+local setprop=nuts.setprop
+local getfont=nuts.getfont
+local getsubtype=nuts.getsubtype
+local getchar=nuts.getchar
+local traverse_id=nuts.traverse_id
+local traverse_node_list=nuts.traverse
+local end_of_math=nuts.end_of_math
local nodecodes=nodes.nodecodes
local glyph_code=nodecodes.glyph
local disc_code=nodecodes.disc
local math_code=nodecodes.math
-local traverse_id=node.traverse_id
-local traverse_node_list=node.traverse
-local end_of_math=node.end_of_math
local fontdata=fonts.hashes.identifiers
local categories=characters and characters.categories or {}
local otffeatures=fonts.constructors.newfeatures("otf")
@@ -9786,51 +10384,52 @@ function analyzers.setstate(head,font)
local tfmdata=fontdata[font]
local descriptions=tfmdata.descriptions
local first,last,current,n,done=nil,nil,head,0,false
+ current=tonut(current)
while current do
- local id=current.id
- if id==glyph_code and current.font==font then
+ local id=getid(current)
+ if id==glyph_code and getfont(current)==font then
done=true
- local char=current.char
+ local char=getchar(current)
local d=descriptions[char]
if d then
if d.class=="mark" or (useunicodemarks and categories[char]=="mn") then
done=true
- current[a_state]=s_mark
+ setprop(current,a_state,s_mark)
elseif n==0 then
first,last,n=current,current,1
- current[a_state]=s_init
+ setprop(current,a_state,s_init)
else
last,n=current,n+1
- current[a_state]=s_medi
+ setprop(current,a_state,s_medi)
end
else
if first and first==last then
- last[a_state]=s_isol
+ setprop(last,a_state,s_isol)
elseif last then
- last[a_state]=s_fina
+ setprop(last,a_state,s_fina)
end
first,last,n=nil,nil,0
end
elseif id==disc_code then
- current[a_state]=s_medi
+ setprop(current,a_state,s_medi)
last=current
else
if first and first==last then
- last[a_state]=s_isol
+ setprop(last,a_state,s_isol)
elseif last then
- last[a_state]=s_fina
+ setprop(last,a_state,s_fina)
end
first,last,n=nil,nil,0
if id==math_code then
current=end_of_math(current)
end
end
- current=current.next
+ current=getnext(current)
end
if first and first==last then
- last[a_state]=s_isol
+ setprop(last,a_state,s_isol)
elseif last then
- last[a_state]=s_fina
+ setprop(last,a_state,s_fina)
end
return head,done
end
@@ -9978,7 +10577,7 @@ local medial={
}
local arab_warned={}
local function warning(current,what)
- local char=current.char
+ local char=getchar(current)
if not arab_warned[char] then
log.report("analyze","arab: character %C has no %a class",char,what)
arab_warned[char]=true
@@ -9987,30 +10586,30 @@ end
local function finish(first,last)
if last then
if first==last then
- local fc=first.char
+ local fc=getchar(first)
if medial[fc] or final[fc] then
- first[a_state]=s_isol
+ setprop(first,a_state,s_isol)
else
warning(first,"isol")
- first[a_state]=s_error
+ setprop(first,a_state,s_error)
end
else
- local lc=last.char
+ local lc=getchar(last)
if medial[lc] or final[lc] then
- last[a_state]=s_fina
+ setprop(last,a_state,s_fina)
else
warning(last,"fina")
- last[a_state]=s_error
+ setprop(last,a_state,s_error)
end
end
first,last=nil,nil
elseif first then
- local fc=first.char
+ local fc=getchar(first)
if medial[fc] or final[fc] then
- first[a_state]=s_isol
+ setprop(first,a_state,s_isol)
else
warning(first,"isol")
- first[a_state]=s_error
+ setprop(first,a_state,s_error)
end
first=nil
end
@@ -10021,38 +10620,39 @@ function methods.arab(head,font,attr)
local tfmdata=fontdata[font]
local marks=tfmdata.resources.marks
local first,last,current,done=nil,nil,head,false
+ current=tonut(current)
while current do
- local id=current.id
- if id==glyph_code and current.font==font and current.subtype<256 and not current[a_state] then
+ local id=getid(current)
+ if id==glyph_code and getfont(current)==font and getsubtype(current)<256 and not getprop(current,a_state) then
done=true
- local char=current.char
+ local char=getchar(current)
if marks[char] or (useunicodemarks and categories[char]=="mn") then
- current[a_state]=s_mark
+ setprop(current,a_state,s_mark)
elseif isolated[char] then
first,last=finish(first,last)
- current[a_state]=s_isol
+ setprop(current,a_state,s_isol)
first,last=nil,nil
elseif not first then
if medial[char] then
- current[a_state]=s_init
+ setprop(current,a_state,s_init)
first,last=first or current,current
elseif final[char] then
- current[a_state]=s_isol
+ setprop(current,a_state,s_isol)
first,last=nil,nil
else
first,last=finish(first,last)
end
elseif medial[char] then
first,last=first or current,current
- current[a_state]=s_medi
+ setprop(current,a_state,s_medi)
elseif final[char] then
- if not last[a_state]==s_init then
- last[a_state]=s_medi
+ if getprop(last,a_state)~=s_init then
+ setprop(last,a_state,s_medi)
end
- current[a_state]=s_fina
+ setprop(current,a_state,s_fina)
first,last=nil,nil
elseif char>=0x0600 and char<=0x06FF then
- current[a_state]=s_rest
+ setprop(current,a_state,s_rest)
first,last=finish(first,last)
else
first,last=finish(first,last)
@@ -10065,7 +10665,7 @@ function methods.arab(head,font,attr)
current=end_of_math(current)
end
end
- current=current.next
+ current=getnext(current)
end
if first or last then
finish(first,last)
@@ -10129,12 +10729,27 @@ registertracker("otf.positions","otf.marks,otf.kerns,otf.cursive")
registertracker("otf.actions","otf.replacements,otf.positions")
registertracker("otf.injections","nodes.injections")
registertracker("*otf.sample","otf.steps,otf.actions,otf.analyzing")
-local insert_node_after=node.insert_after
-local delete_node=nodes.delete
-local copy_node=node.copy
-local find_node_tail=node.tail or node.slide
-local flush_node_list=node.flush_list
-local end_of_math=node.end_of_math
+local nuts=nodes.nuts
+local tonode=nuts.tonode
+local tonut=nuts.tonut
+local getfield=nuts.getfield
+local setfield=nuts.setfield
+local getnext=nuts.getnext
+local getprev=nuts.getprev
+local getid=nuts.getid
+local getattr=nuts.getattr
+local setattr=nuts.setattr
+local getprop=nuts.getprop
+local setprop=nuts.setprop
+local getfont=nuts.getfont
+local getsubtype=nuts.getsubtype
+local getchar=nuts.getchar
+local insert_node_after=nuts.insert_after
+local delete_node=nuts.delete
+local copy_node=nuts.copy
+local find_node_tail=nuts.tail
+local flush_node_list=nuts.flush_list
+local end_of_math=nuts.end_of_math
local setmetatableindex=table.setmetatableindex
local zwnj=0x200C
local zwj=0x200D
@@ -10155,22 +10770,16 @@ local discretionary_code=disccodes.discretionary
local ligature_code=glyphcodes.ligature
local privateattribute=attributes.private
local a_state=privateattribute('state')
-local a_markbase=privateattribute('markbase')
-local a_markmark=privateattribute('markmark')
-local a_markdone=privateattribute('markdone')
-local a_cursbase=privateattribute('cursbase')
-local a_curscurs=privateattribute('curscurs')
-local a_cursdone=privateattribute('cursdone')
-local a_kernpair=privateattribute('kernpair')
-local a_ligacomp=privateattribute('ligacomp')
+local a_cursbase=privateattribute('cursbase')
local injections=nodes.injections
local setmark=injections.setmark
local setcursive=injections.setcursive
local setkern=injections.setkern
local setpair=injections.setpair
-local markonce=true
+local resetinjection=injections.reset
+local setligaindex=injections.setligaindex
+local getligaindex=injections.getligaindex
local cursonce=true
-local kernonce=true
local fonthashes=fonts.hashes
local fontdata=fonthashes.identifiers
local otffeatures=fonts.constructors.newfeatures("otf")
@@ -10186,6 +10795,7 @@ local currentfont=false
local lookuptable=false
local anchorlookups=false
local lookuptypes=false
+local lookuptags=false
local handlers={}
local rlmode=0
local featurevalue=false
@@ -10230,98 +10840,101 @@ local function gref(n)
end
local function cref(kind,chainname,chainlookupname,lookupname,index)
if index then
- return formatters["feature %a, chain %a, sub %a, lookup %a, index %a"](kind,chainname,chainlookupname,lookupname,index)
+ return formatters["feature %a, chain %a, sub %a, lookup %a, index %a"](kind,chainname,chainlookupname,lookuptags[lookupname],index)
elseif lookupname then
- return formatters["feature %a, chain %a, sub %a, lookup %a"](kind,chainname,chainlookupname,lookupname)
+ return formatters["feature %a, chain %a, sub %a, lookup %a"](kind,chainname,chainlookupname,lookuptags[lookupname])
elseif chainlookupname then
- return formatters["feature %a, chain %a, sub %a"](kind,chainname,chainlookupname)
+ return formatters["feature %a, chain %a, sub %a"](kind,lookuptags[chainname],lookuptags[chainlookupname])
elseif chainname then
- return formatters["feature %a, chain %a"](kind,chainname)
+ return formatters["feature %a, chain %a"](kind,lookuptags[chainname])
else
return formatters["feature %a"](kind)
end
end
local function pref(kind,lookupname)
- return formatters["feature %a, lookup %a"](kind,lookupname)
+ return formatters["feature %a, lookup %a"](kind,lookuptags[lookupname])
end
local function copy_glyph(g)
- local components=g.components
+ local components=getfield(g,"components")
if components then
- g.components=nil
+ setfield(g,"components",nil)
local n=copy_node(g)
- g.components=components
+ setfield(g,"components",components)
return n
else
return copy_node(g)
end
end
local function markstoligature(kind,lookupname,head,start,stop,char)
- if start==stop and start.char==char then
+ if start==stop and getchar(start)==char then
return head,start
else
- local prev=start.prev
- local next=stop.next
- start.prev=nil
- stop.next=nil
+ local prev=getprev(start)
+ local next=getnext(stop)
+ setfield(start,"prev",nil)
+ setfield(stop,"next",nil)
local base=copy_glyph(start)
if head==start then
head=base
end
- base.char=char
- base.subtype=ligature_code
- base.components=start
+ resetinjection(base)
+ setfield(base,"char",char)
+ setfield(base,"subtype",ligature_code)
+ setfield(base,"components",start)
if prev then
- prev.next=base
+ setfield(prev,"next",base)
end
if next then
- next.prev=base
+ setfield(next,"prev",base)
end
- base.next=next
- base.prev=prev
+ setfield(base,"next",next)
+ setfield(base,"prev",prev)
return head,base
end
end
local function getcomponentindex(start)
- if start.id~=glyph_code then
+ if getid(start)~=glyph_code then
return 0
- elseif start.subtype==ligature_code then
+ elseif getsubtype(start)==ligature_code then
local i=0
- local components=start.components
+ local components=getfield(start,"components")
while components do
i=i+getcomponentindex(components)
- components=components.next
+ components=getnext(components)
end
return i
- elseif not marks[start.char] then
+ elseif not marks[getchar(start)] then
return 1
else
return 0
end
end
local function toligature(kind,lookupname,head,start,stop,char,markflag,discfound)
- if start==stop and start.char==char then
- start.char=char
+ if start==stop and getchar(start)==char then
+ resetinjection(start)
+ setfield(start,"char",char)
return head,start
end
- local prev=start.prev
- local next=stop.next
- start.prev=nil
- stop.next=nil
+ local prev=getprev(start)
+ local next=getnext(stop)
+ setfield(start,"prev",nil)
+ setfield(stop,"next",nil)
local base=copy_glyph(start)
if start==head then
head=base
end
- base.char=char
- base.subtype=ligature_code
- base.components=start
+ resetinjection(base)
+ setfield(base,"char",char)
+ setfield(base,"subtype",ligature_code)
+ setfield(base,"components",start)
if prev then
- prev.next=base
+ setfield(prev,"next",base)
end
if next then
- next.prev=base
+ setfield(next,"prev",base)
end
- base.next=next
- base.prev=prev
+ setfield(base,"next",next)
+ setfield(base,"prev",prev)
if not discfound then
local deletemarks=markflag~="mark"
local components=start
@@ -10330,42 +10943,43 @@ local function toligature(kind,lookupname,head,start,stop,char,markflag,discfoun
local head=base
local current=base
while start do
- local char=start.char
+ local char=getchar(start)
if not marks[char] then
baseindex=baseindex+componentindex
componentindex=getcomponentindex(start)
elseif not deletemarks then
- start[a_ligacomp]=baseindex+(start[a_ligacomp] or componentindex)
+ setligaindex(start,baseindex+getligaindex(start,componentindex))
if trace_marks then
- logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(char),start[a_ligacomp])
+ logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(char),getligaindex(start))
end
head,current=insert_node_after(head,current,copy_node(start))
elseif trace_marks then
logwarning("%s: delete mark %s",pref(kind,lookupname),gref(char))
end
- start=start.next
+ start=getnext(start)
end
- local start=current.next
- while start and start.id==glyph_code do
- local char=start.char
+ local start=getnext(current)
+ while start and getid(start)==glyph_code do
+ local char=getchar(start)
if marks[char] then
- start[a_ligacomp]=baseindex+(start[a_ligacomp] or componentindex)
+ setligaindex(start,baseindex+getligaindex(start,componentindex))
if trace_marks then
- logwarning("%s: set mark %s, gets index %s",pref(kind,lookupname),gref(char),start[a_ligacomp])
+ logwarning("%s: set mark %s, gets index %s",pref(kind,lookupname),gref(char),getligaindex(start))
end
else
break
end
- start=start.next
+ start=getnext(start)
end
end
return head,base
end
function handlers.gsub_single(head,start,kind,lookupname,replacement)
if trace_singles then
- logprocess("%s: replacing %s by single %s",pref(kind,lookupname),gref(start.char),gref(replacement))
+ logprocess("%s: replacing %s by single %s",pref(kind,lookupname),gref(getchar(start)),gref(replacement))
end
- start.char=replacement
+ resetinjection(start)
+ setfield(start,"char",replacement)
return head,start,true
end
local function get_alternative_glyph(start,alternatives,value,trace_alternatives)
@@ -10391,7 +11005,7 @@ local function get_alternative_glyph(start,alternatives,value,trace_alternatives
return false,trace_alternatives and formatters["invalid value %a, %s"](value,"out of range")
end
elseif value==0 then
- return start.char,trace_alternatives and formatters["invalid value %a, %s"](value,"no change")
+ return getchar(start),trace_alternatives and formatters["invalid value %a, %s"](value,"no change")
elseif value<1 then
return alternatives[1],trace_alternatives and formatters["invalid value %a, taking %a"](value,1)
else
@@ -10402,25 +11016,27 @@ end
local function multiple_glyphs(head,start,multiple,ignoremarks)
local nofmultiples=#multiple
if nofmultiples>0 then
- start.char=multiple[1]
+ resetinjection(start)
+ setfield(start,"char",multiple[1])
if nofmultiples>1 then
- local sn=start.next
+ local sn=getnext(start)
for k=2,nofmultiples do
local n=copy_node(start)
- n.char=multiple[k]
- n.next=sn
- n.prev=start
+ resetinjection(n)
+ setfield(n,"char",multiple[k])
+ setfield(n,"next",sn)
+ setfield(n,"prev",start)
if sn then
- sn.prev=n
+ setfield(sn,"prev",n)
end
- start.next=n
+ setfield(start,"next",n)
start=n
end
end
return head,start,true
else
if trace_multiples then
- logprocess("no multiple for %s",gref(start.char))
+ logprocess("no multiple for %s",gref(getchar(start)))
end
return head,start,false
end
@@ -10430,34 +11046,35 @@ function handlers.gsub_alternate(head,start,kind,lookupname,alternative,sequence
local choice,comment=get_alternative_glyph(start,alternative,value,trace_alternatives)
if choice then
if trace_alternatives then
- logprocess("%s: replacing %s by alternative %a to %s, %s",pref(kind,lookupname),gref(start.char),choice,gref(choice),comment)
+ logprocess("%s: replacing %s by alternative %a to %s, %s",pref(kind,lookupname),gref(getchar(start)),choice,gref(choice),comment)
end
- start.char=choice
+ resetinjection(start)
+ setfield(start,"char",choice)
else
if trace_alternatives then
- logwarning("%s: no variant %a for %s, %s",pref(kind,lookupname),value,gref(start.char),comment)
+ logwarning("%s: no variant %a for %s, %s",pref(kind,lookupname),value,gref(getchar(start)),comment)
end
end
return head,start,true
end
function handlers.gsub_multiple(head,start,kind,lookupname,multiple,sequence)
if trace_multiples then
- logprocess("%s: replacing %s by multiple %s",pref(kind,lookupname),gref(start.char),gref(multiple))
+ logprocess("%s: replacing %s by multiple %s",pref(kind,lookupname),gref(getchar(start)),gref(multiple))
end
return multiple_glyphs(head,start,multiple,sequence.flags[1])
end
function handlers.gsub_ligature(head,start,kind,lookupname,ligature,sequence)
- local s,stop,discfound=start.next,nil,false
- local startchar=start.char
+ local s,stop,discfound=getnext(start),nil,false
+ local startchar=getchar(start)
if marks[startchar] then
while s do
- local id=s.id
- if id==glyph_code and s.font==currentfont and s.subtype<256 then
- local lg=ligature[s.char]
+ local id=getid(s)
+ if id==glyph_code and getfont(s)==currentfont and getsubtype(s)<256 then
+ local lg=ligature[getchar(s)]
if lg then
stop=s
ligature=lg
- s=s.next
+ s=getnext(s)
else
break
end
@@ -10469,9 +11086,9 @@ function handlers.gsub_ligature(head,start,kind,lookupname,ligature,sequence)
local lig=ligature.ligature
if lig then
if trace_ligatures then
- local stopchar=stop.char
+ local stopchar=getchar(stop)
head,start=markstoligature(kind,lookupname,head,start,stop,lig)
- logprocess("%s: replacing %s upto %s by ligature %s case 1",pref(kind,lookupname),gref(startchar),gref(stopchar),gref(start.char))
+ logprocess("%s: replacing %s upto %s by ligature %s case 1",pref(kind,lookupname),gref(startchar),gref(stopchar),gref(getchar(start)))
else
head,start=markstoligature(kind,lookupname,head,start,stop,lig)
end
@@ -10482,18 +11099,18 @@ function handlers.gsub_ligature(head,start,kind,lookupname,ligature,sequence)
else
local skipmark=sequence.flags[1]
while s do
- local id=s.id
- if id==glyph_code and s.subtype<256 then
- if s.font==currentfont then
- local char=s.char
+ local id=getid(s)
+ if id==glyph_code and getsubtype(s)<256 then
+ if getfont(s)==currentfont then
+ local char=getchar(s)
if skipmark and marks[char] then
- s=s.next
+ s=getnext(s)
else
local lg=ligature[char]
if lg then
stop=s
ligature=lg
- s=s.next
+ s=getnext(s)
else
break
end
@@ -10503,7 +11120,7 @@ function handlers.gsub_ligature(head,start,kind,lookupname,ligature,sequence)
end
elseif id==disc_code then
discfound=true
- s=s.next
+ s=getnext(s)
else
break
end
@@ -10512,36 +11129,36 @@ function handlers.gsub_ligature(head,start,kind,lookupname,ligature,sequence)
if lig then
if stop then
if trace_ligatures then
- local stopchar=stop.char
+ local stopchar=getchar(stop)
head,start=toligature(kind,lookupname,head,start,stop,lig,skipmark,discfound)
- logprocess("%s: replacing %s upto %s by ligature %s case 2",pref(kind,lookupname),gref(startchar),gref(stopchar),gref(start.char))
+ logprocess("%s: replacing %s upto %s by ligature %s case 2",pref(kind,lookupname),gref(startchar),gref(stopchar),gref(getchar(start)))
else
head,start=toligature(kind,lookupname,head,start,stop,lig,skipmark,discfound)
end
- return head,start,true
else
- start.char=lig
+ resetinjection(start)
+ setfield(start,"char",lig)
if trace_ligatures then
logprocess("%s: replacing %s by (no real) ligature %s case 3",pref(kind,lookupname),gref(startchar),gref(lig))
end
- return head,start,true
end
+ return head,start,true
else
end
end
return head,start,false
end
function handlers.gpos_mark2base(head,start,kind,lookupname,markanchors,sequence)
- local markchar=start.char
+ local markchar=getchar(start)
if marks[markchar] then
- local base=start.prev
- if base and base.id==glyph_code and base.font==currentfont and base.subtype<256 then
- local basechar=base.char
+ local base=getprev(start)
+ if base and getid(base)==glyph_code and getfont(base)==currentfont and getsubtype(base)<256 then
+ local basechar=getchar(base)
if marks[basechar] then
while true do
- base=base.prev
- if base and base.id==glyph_code and base.font==currentfont and base.subtype<256 then
- basechar=base.char
+ base=getprev(base)
+ if base and getid(base)==glyph_code and getfont(base)==currentfont and getsubtype(base)<256 then
+ basechar=getchar(base)
if not marks[basechar] then
break
end
@@ -10565,7 +11182,7 @@ function handlers.gpos_mark2base(head,start,kind,lookupname,markanchors,sequence
if al[anchor] then
local ma=markanchors[anchor]
if ma then
- local dx,dy,bound=setmark(start,base,tfmdata.parameters.factor,rlmode,ba,ma)
+ local dx,dy,bound=setmark(start,base,tfmdata.parameters.factor,rlmode,ba,ma,characters[basechar])
if trace_marks then
logprocess("%s, anchor %s, bound %s: anchoring mark %s to basechar %s => (%p,%p)",
pref(kind,lookupname),anchor,bound,gref(markchar),gref(basechar),dx,dy)
@@ -10590,16 +11207,16 @@ function handlers.gpos_mark2base(head,start,kind,lookupname,markanchors,sequence
return head,start,false
end
function handlers.gpos_mark2ligature(head,start,kind,lookupname,markanchors,sequence)
- local markchar=start.char
+ local markchar=getchar(start)
if marks[markchar] then
- local base=start.prev
- if base and base.id==glyph_code and base.font==currentfont and base.subtype<256 then
- local basechar=base.char
+ local base=getprev(start)
+ if base and getid(base)==glyph_code and getfont(base)==currentfont and getsubtype(base)<256 then
+ local basechar=getchar(base)
if marks[basechar] then
while true do
- base=base.prev
- if base and base.id==glyph_code and base.font==currentfont and base.subtype<256 then
- basechar=base.char
+ base=getprev(base)
+ if base and getid(base)==glyph_code and getfont(base)==currentfont and getsubtype(base)<256 then
+ basechar=getchar(base)
if not marks[basechar] then
break
end
@@ -10611,7 +11228,7 @@ function handlers.gpos_mark2ligature(head,start,kind,lookupname,markanchors,sequ
end
end
end
- local index=start[a_ligacomp]
+ local index=getligaindex(start)
local baseanchors=descriptions[basechar]
if baseanchors then
baseanchors=baseanchors.anchors
@@ -10625,7 +11242,7 @@ function handlers.gpos_mark2ligature(head,start,kind,lookupname,markanchors,sequ
if ma then
ba=ba[index]
if ba then
- local dx,dy,bound=setmark(start,base,tfmdata.parameters.factor,rlmode,ba,ma)
+ local dx,dy,bound=setmark(start,base,tfmdata.parameters.factor,rlmode,ba,ma,characters[basechar])
if trace_marks then
logprocess("%s, anchor %s, index %s, bound %s: anchoring mark %s to baselig %s at index %s => (%p,%p)",
pref(kind,lookupname),anchor,index,bound,gref(markchar),gref(basechar),index,dx,dy)
@@ -10656,22 +11273,22 @@ function handlers.gpos_mark2ligature(head,start,kind,lookupname,markanchors,sequ
return head,start,false
end
function handlers.gpos_mark2mark(head,start,kind,lookupname,markanchors,sequence)
- local markchar=start.char
+ local markchar=getchar(start)
if marks[markchar] then
- local base=start.prev
- local slc=start[a_ligacomp]
+ local base=getprev(start)
+ local slc=getligaindex(start)
if slc then
while base do
- local blc=base[a_ligacomp]
+ local blc=getligaindex(base)
if blc and blc~=slc then
- base=base.prev
+ base=getprev(base)
else
break
end
end
end
- if base and base.id==glyph_code and base.font==currentfont and base.subtype<256 then
- local basechar=base.char
+ if base and getid(base)==glyph_code and getfont(base)==currentfont and getsubtype(base)<256 then
+ local basechar=getchar(base)
local baseanchors=descriptions[basechar]
if baseanchors then
baseanchors=baseanchors.anchors
@@ -10683,7 +11300,7 @@ function handlers.gpos_mark2mark(head,start,kind,lookupname,markanchors,sequence
if al[anchor] then
local ma=markanchors[anchor]
if ma then
- local dx,dy,bound=setmark(start,base,tfmdata.parameters.factor,rlmode,ba,ma,true)
+ local dx,dy,bound=setmark(start,base,tfmdata.parameters.factor,rlmode,ba,ma,characters[basechar])
if trace_marks then
logprocess("%s, anchor %s, bound %s: anchoring mark %s to basemark %s => (%p,%p)",
pref(kind,lookupname),anchor,bound,gref(markchar),gref(basechar),dx,dy)
@@ -10709,20 +11326,20 @@ function handlers.gpos_mark2mark(head,start,kind,lookupname,markanchors,sequence
return head,start,false
end
function handlers.gpos_cursive(head,start,kind,lookupname,exitanchors,sequence)
- local alreadydone=cursonce and start[a_cursbase]
+ local alreadydone=cursonce and getprop(start,a_cursbase)
if not alreadydone then
local done=false
- local startchar=start.char
+ local startchar=getchar(start)
if marks[startchar] then
if trace_cursive then
logprocess("%s: ignoring cursive for mark %s",pref(kind,lookupname),gref(startchar))
end
else
- local nxt=start.next
- while not done and nxt and nxt.id==glyph_code and nxt.font==currentfont and nxt.subtype<256 do
- local nextchar=nxt.char
+ local nxt=getnext(start)
+ while not done and nxt and getid(nxt)==glyph_code and getfont(nxt)==currentfont and getsubtype(nxt)<256 do
+ local nextchar=getchar(nxt)
if marks[nextchar] then
- nxt=nxt.next
+ nxt=getnext(nxt)
else
local entryanchors=descriptions[nextchar]
if entryanchors then
@@ -10756,13 +11373,13 @@ function handlers.gpos_cursive(head,start,kind,lookupname,exitanchors,sequence)
return head,start,done
else
if trace_cursive and trace_details then
- logprocess("%s, cursive %s is already done",pref(kind,lookupname),gref(start.char),alreadydone)
+ logprocess("%s, cursive %s is already done",pref(kind,lookupname),gref(getchar(start)),alreadydone)
end
return head,start,false
end
end
function handlers.gpos_single(head,start,kind,lookupname,kerns,sequence)
- local startchar=start.char
+ local startchar=getchar(start)
local dx,dy,w,h=setpair(start,tfmdata.parameters.factor,rlmode,sequence.flags[4],kerns,characters[startchar])
if trace_kerns then
logprocess("%s: shifting single %s by (%p,%p) and correction (%p,%p)",pref(kind,lookupname),gref(startchar),dx,dy,w,h)
@@ -10770,33 +11387,33 @@ function handlers.gpos_single(head,start,kind,lookupname,kerns,sequence)
return head,start,false
end
function handlers.gpos_pair(head,start,kind,lookupname,kerns,sequence)
- local snext=start.next
+ local snext=getnext(start)
if not snext then
return head,start,false
else
local prev,done=start,false
local factor=tfmdata.parameters.factor
local lookuptype=lookuptypes[lookupname]
- while snext and snext.id==glyph_code and snext.font==currentfont and snext.subtype<256 do
- local nextchar=snext.char
+ while snext and getid(snext)==glyph_code and getfont(snext)==currentfont and getsubtype(snext)<256 do
+ local nextchar=getchar(snext)
local krn=kerns[nextchar]
if not krn and marks[nextchar] then
prev=snext
- snext=snext.next
+ snext=getnext(snext)
else
if not krn then
elseif type(krn)=="table" then
if lookuptype=="pair" then
local a,b=krn[2],krn[3]
if a and #a>0 then
- local startchar=start.char
+ local startchar=getchar(start)
local x,y,w,h=setpair(start,factor,rlmode,sequence.flags[4],a,characters[startchar])
if trace_kerns then
logprocess("%s: shifting first of pair %s and %s by (%p,%p) and correction (%p,%p)",pref(kind,lookupname),gref(startchar),gref(nextchar),x,y,w,h)
end
end
if b and #b>0 then
- local startchar=start.char
+ local startchar=getchar(start)
local x,y,w,h=setpair(snext,factor,rlmode,sequence.flags[4],b,characters[nextchar])
if trace_kerns then
logprocess("%s: shifting second of pair %s and %s by (%p,%p) and correction (%p,%p)",pref(kind,lookupname),gref(startchar),gref(nextchar),x,y,w,h)
@@ -10809,7 +11426,7 @@ function handlers.gpos_pair(head,start,kind,lookupname,kerns,sequence)
elseif krn~=0 then
local k=setkern(snext,factor,rlmode,krn)
if trace_kerns then
- logprocess("%s: inserting kern %s between %s and %s",pref(kind,lookupname),k,gref(prev.char),gref(nextchar))
+ logprocess("%s: inserting kern %s between %s and %s",pref(kind,lookupname),k,gref(getchar(prev)),gref(nextchar))
end
done=true
end
@@ -10844,13 +11461,14 @@ function chainmores.chainsub(head,start,stop,kind,chainname,currentcontext,looku
return head,start,false
end
function chainprocs.reversesub(head,start,stop,kind,chainname,currentcontext,lookuphash,replacements)
- local char=start.char
+ local char=getchar(start)
local replacement=replacements[char]
if replacement then
if trace_singles then
logprocess("%s: single reverse replacement of %s by %s",cref(kind,chainname),gref(char),gref(replacement))
end
- start.char=replacement
+ resetinjection(start)
+ setfield(start,"char",replacement)
return head,start,true
else
return head,start,false
@@ -10863,8 +11481,8 @@ function chainprocs.gsub_single(head,start,stop,kind,chainname,currentcontext,lo
logwarning("todo: check if we need to loop over the replacements: %s",concat(subtables," "))
end
while current do
- if current.id==glyph_code then
- local currentchar=current.char
+ if getid(current)==glyph_code then
+ local currentchar=getchar(current)
local lookupname=subtables[1]
local replacement=lookuphash[lookupname]
if not replacement then
@@ -10881,21 +11499,22 @@ function chainprocs.gsub_single(head,start,stop,kind,chainname,currentcontext,lo
if trace_singles then
logprocess("%s: replacing single %s by %s",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(currentchar),gref(replacement))
end
- current.char=replacement
+ resetinjection(current)
+ setfield(current,"char",replacement)
end
end
return head,start,true
elseif current==stop then
break
else
- current=current.next
+ current=getnext(current)
end
end
return head,start,false
end
chainmores.gsub_single=chainprocs.gsub_single
function chainprocs.gsub_multiple(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname)
- local startchar=start.char
+ local startchar=getchar(start)
local subtables=currentlookup.subtables
local lookupname=subtables[1]
local replacements=lookuphash[lookupname]
@@ -10924,8 +11543,8 @@ function chainprocs.gsub_alternate(head,start,stop,kind,chainname,currentcontext
local subtables=currentlookup.subtables
local value=featurevalue==true and tfmdata.shared.features[kind] or featurevalue
while current do
- if current.id==glyph_code then
- local currentchar=current.char
+ if getid(current)==glyph_code then
+ local currentchar=getchar(current)
local lookupname=subtables[1]
local alternatives=lookuphash[lookupname]
if not alternatives then
@@ -10940,7 +11559,8 @@ function chainprocs.gsub_alternate(head,start,stop,kind,chainname,currentcontext
if trace_alternatives then
logprocess("%s: replacing %s by alternative %a to %s, %s",cref(kind,chainname,chainlookupname,lookupname),gref(char),choice,gref(choice),comment)
end
- start.char=choice
+ resetinjection(start)
+ setfield(start,"char",choice)
else
if trace_alternatives then
logwarning("%s: no variant %a for %s, %s",cref(kind,chainname,chainlookupname,lookupname),value,gref(char),comment)
@@ -10954,14 +11574,14 @@ function chainprocs.gsub_alternate(head,start,stop,kind,chainname,currentcontext
elseif current==stop then
break
else
- current=current.next
+ current=getnext(current)
end
end
return head,start,false
end
chainmores.gsub_alternate=chainprocs.gsub_alternate
function chainprocs.gsub_ligature(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex)
- local startchar=start.char
+ local startchar=getchar(start)
local subtables=currentlookup.subtables
local lookupname=subtables[1]
local ligatures=lookuphash[lookupname]
@@ -10976,20 +11596,20 @@ function chainprocs.gsub_ligature(head,start,stop,kind,chainname,currentcontext,
logwarning("%s: no ligatures starting with %s",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar))
end
else
- local s=start.next
+ local s=getnext(start)
local discfound=false
local last=stop
local nofreplacements=0
local skipmark=currentlookup.flags[1]
while s do
- local id=s.id
+ local id=getid(s)
if id==disc_code then
- s=s.next
+ s=getnext(s)
discfound=true
else
- local schar=s.char
+ local schar=getchar(s)
if skipmark and marks[schar] then
- s=s.next
+ s=getnext(s)
else
local lg=ligatures[schar]
if lg then
@@ -10997,7 +11617,7 @@ function chainprocs.gsub_ligature(head,start,stop,kind,chainname,currentcontext,
if s==stop then
break
else
- s=s.next
+ s=getnext(s)
end
else
break
@@ -11014,7 +11634,7 @@ function chainprocs.gsub_ligature(head,start,stop,kind,chainname,currentcontext,
if start==stop then
logprocess("%s: replacing character %s by ligature %s case 3",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar),gref(l2))
else
- logprocess("%s: replacing character %s upto %s by ligature %s case 4",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar),gref(stop.char),gref(l2))
+ logprocess("%s: replacing character %s upto %s by ligature %s case 4",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar),gref(getchar(stop)),gref(l2))
end
end
head,start=toligature(kind,lookupname,head,start,stop,l2,currentlookup.flags[1],discfound)
@@ -11023,7 +11643,7 @@ function chainprocs.gsub_ligature(head,start,stop,kind,chainname,currentcontext,
if start==stop then
logwarning("%s: replacing character %s by ligature fails",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar))
else
- logwarning("%s: replacing character %s upto %s by ligature fails",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar),gref(stop.char))
+ logwarning("%s: replacing character %s upto %s by ligature fails",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar),gref(getchar(stop)))
end
end
end
@@ -11032,7 +11652,7 @@ function chainprocs.gsub_ligature(head,start,stop,kind,chainname,currentcontext,
end
chainmores.gsub_ligature=chainprocs.gsub_ligature
function chainprocs.gpos_mark2base(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname)
- local markchar=start.char
+ local markchar=getchar(start)
if marks[markchar] then
local subtables=currentlookup.subtables
local lookupname=subtables[1]
@@ -11041,14 +11661,14 @@ function chainprocs.gpos_mark2base(head,start,stop,kind,chainname,currentcontext
markanchors=markanchors[markchar]
end
if markanchors then
- local base=start.prev
- if base and base.id==glyph_code and base.font==currentfont and base.subtype<256 then
- local basechar=base.char
+ local base=getprev(start)
+ if base and getid(base)==glyph_code and getfont(base)==currentfont and getsubtype(base)<256 then
+ local basechar=getchar(base)
if marks[basechar] then
while true do
- base=base.prev
- if base and base.id==glyph_code and base.font==currentfont and base.subtype<256 then
- basechar=base.char
+ base=getprev(base)
+ if base and getid(base)==glyph_code and getfont(base)==currentfont and getsubtype(base)<256 then
+ basechar=getchar(base)
if not marks[basechar] then
break
end
@@ -11069,7 +11689,7 @@ function chainprocs.gpos_mark2base(head,start,stop,kind,chainname,currentcontext
if al[anchor] then
local ma=markanchors[anchor]
if ma then
- local dx,dy,bound=setmark(start,base,tfmdata.parameters.factor,rlmode,ba,ma)
+ local dx,dy,bound=setmark(start,base,tfmdata.parameters.factor,rlmode,ba,ma,characters[basechar])
if trace_marks then
logprocess("%s, anchor %s, bound %s: anchoring mark %s to basechar %s => (%p,%p)",
cref(kind,chainname,chainlookupname,lookupname),anchor,bound,gref(markchar),gref(basechar),dx,dy)
@@ -11095,7 +11715,7 @@ function chainprocs.gpos_mark2base(head,start,stop,kind,chainname,currentcontext
return head,start,false
end
function chainprocs.gpos_mark2ligature(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname)
- local markchar=start.char
+ local markchar=getchar(start)
if marks[markchar] then
local subtables=currentlookup.subtables
local lookupname=subtables[1]
@@ -11104,14 +11724,14 @@ function chainprocs.gpos_mark2ligature(head,start,stop,kind,chainname,currentcon
markanchors=markanchors[markchar]
end
if markanchors then
- local base=start.prev
- if base and base.id==glyph_code and base.font==currentfont and base.subtype<256 then
- local basechar=base.char
+ local base=getprev(start)
+ if base and getid(base)==glyph_code and getfont(base)==currentfont and getsubtype(base)<256 then
+ local basechar=getchar(base)
if marks[basechar] then
while true do
- base=base.prev
- if base and base.id==glyph_code and base.font==currentfont and base.subtype<256 then
- basechar=base.char
+ base=getprev(base)
+ if base and getid(base)==glyph_code and getfont(base)==currentfont and getsubtype(base)<256 then
+ basechar=getchar(base)
if not marks[basechar] then
break
end
@@ -11123,7 +11743,7 @@ function chainprocs.gpos_mark2ligature(head,start,stop,kind,chainname,currentcon
end
end
end
- local index=start[a_ligacomp]
+ local index=getligaindex(start)
local baseanchors=descriptions[basechar].anchors
if baseanchors then
local baseanchors=baseanchors['baselig']
@@ -11135,7 +11755,7 @@ function chainprocs.gpos_mark2ligature(head,start,stop,kind,chainname,currentcon
if ma then
ba=ba[index]
if ba then
- local dx,dy,bound=setmark(start,base,tfmdata.parameters.factor,rlmode,ba,ma)
+ local dx,dy,bound=setmark(start,base,tfmdata.parameters.factor,rlmode,ba,ma,characters[basechar])
if trace_marks then
logprocess("%s, anchor %s, bound %s: anchoring mark %s to baselig %s at index %s => (%p,%p)",
cref(kind,chainname,chainlookupname,lookupname),anchor,a or bound,gref(markchar),gref(basechar),index,dx,dy)
@@ -11162,67 +11782,67 @@ function chainprocs.gpos_mark2ligature(head,start,stop,kind,chainname,currentcon
return head,start,false
end
function chainprocs.gpos_mark2mark(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname)
- local markchar=start.char
+ local markchar=getchar(start)
if marks[markchar] then
- local subtables=currentlookup.subtables
- local lookupname=subtables[1]
- local markanchors=lookuphash[lookupname]
- if markanchors then
- markanchors=markanchors[markchar]
- end
- if markanchors then
- local base=start.prev
- local slc=start[a_ligacomp]
- if slc then
- while base do
- local blc=base[a_ligacomp]
- if blc and blc~=slc then
- base=base.prev
- else
- break
- end
+ local subtables=currentlookup.subtables
+ local lookupname=subtables[1]
+ local markanchors=lookuphash[lookupname]
+ if markanchors then
+ markanchors=markanchors[markchar]
+ end
+ if markanchors then
+ local base=getprev(start)
+ local slc=getligaindex(start)
+ if slc then
+ while base do
+ local blc=getligaindex(base)
+ if blc and blc~=slc then
+ base=getprev(base)
+ else
+ break
end
end
- if base and base.id==glyph_code and base.font==currentfont and base.subtype<256 then
- local basechar=base.char
- local baseanchors=descriptions[basechar].anchors
+ end
+ if base and getid(base)==glyph_code and getfont(base)==currentfont and getsubtype(base)<256 then
+ local basechar=getchar(base)
+ local baseanchors=descriptions[basechar].anchors
+ if baseanchors then
+ baseanchors=baseanchors['basemark']
if baseanchors then
- baseanchors=baseanchors['basemark']
- if baseanchors then
- local al=anchorlookups[lookupname]
- for anchor,ba in next,baseanchors do
- if al[anchor] then
- local ma=markanchors[anchor]
- if ma then
- local dx,dy,bound=setmark(start,base,tfmdata.parameters.factor,rlmode,ba,ma,true)
- if trace_marks then
- logprocess("%s, anchor %s, bound %s: anchoring mark %s to basemark %s => (%p,%p)",
- cref(kind,chainname,chainlookupname,lookupname),anchor,bound,gref(markchar),gref(basechar),dx,dy)
- end
- return head,start,true
+ local al=anchorlookups[lookupname]
+ for anchor,ba in next,baseanchors do
+ if al[anchor] then
+ local ma=markanchors[anchor]
+ if ma then
+ local dx,dy,bound=setmark(start,base,tfmdata.parameters.factor,rlmode,ba,ma,characters[basechar])
+ if trace_marks then
+ logprocess("%s, anchor %s, bound %s: anchoring mark %s to basemark %s => (%p,%p)",
+ cref(kind,chainname,chainlookupname,lookupname),anchor,bound,gref(markchar),gref(basechar),dx,dy)
end
+ return head,start,true
end
end
- if trace_bugs then
- logwarning("%s: no matching anchors for mark %s and basemark %s",gref(kind,chainname,chainlookupname,lookupname),gref(markchar),gref(basechar))
- end
+ end
+ if trace_bugs then
+ logwarning("%s: no matching anchors for mark %s and basemark %s",gref(kind,chainname,chainlookupname,lookupname),gref(markchar),gref(basechar))
end
end
- elseif trace_bugs then
- logwarning("%s: prev node is no mark",cref(kind,chainname,chainlookupname,lookupname))
end
elseif trace_bugs then
- logwarning("%s: mark %s has no anchors",cref(kind,chainname,chainlookupname,lookupname),gref(markchar))
+ logwarning("%s: prev node is no mark",cref(kind,chainname,chainlookupname,lookupname))
end
+ elseif trace_bugs then
+ logwarning("%s: mark %s has no anchors",cref(kind,chainname,chainlookupname,lookupname),gref(markchar))
+ end
elseif trace_bugs then
logwarning("%s: mark %s is no mark",cref(kind,chainname,chainlookupname),gref(markchar))
end
return head,start,false
end
function chainprocs.gpos_cursive(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname)
- local alreadydone=cursonce and start[a_cursbase]
+ local alreadydone=cursonce and getprop(start,a_cursbase)
if not alreadydone then
- local startchar=start.char
+ local startchar=getchar(start)
local subtables=currentlookup.subtables
local lookupname=subtables[1]
local exitanchors=lookuphash[lookupname]
@@ -11236,11 +11856,11 @@ function chainprocs.gpos_cursive(head,start,stop,kind,chainname,currentcontext,l
logprocess("%s: ignoring cursive for mark %s",pref(kind,lookupname),gref(startchar))
end
else
- local nxt=start.next
- while not done and nxt and nxt.id==glyph_code and nxt.font==currentfont and nxt.subtype<256 do
- local nextchar=nxt.char
+ local nxt=getnext(start)
+ while not done and nxt and getid(nxt)==glyph_code and getfont(nxt)==currentfont and getsubtype(nxt)<256 do
+ local nextchar=getchar(nxt)
if marks[nextchar] then
- nxt=nxt.next
+ nxt=getnext(nxt)
else
local entryanchors=descriptions[nextchar]
if entryanchors then
@@ -11274,7 +11894,7 @@ function chainprocs.gpos_cursive(head,start,stop,kind,chainname,currentcontext,l
return head,start,done
else
if trace_cursive and trace_details then
- logprocess("%s, cursive %s is already done",pref(kind,lookupname),gref(start.char),alreadydone)
+ logprocess("%s, cursive %s is already done",pref(kind,lookupname),gref(getchar(start)),alreadydone)
end
return head,start,false
end
@@ -11282,7 +11902,7 @@ function chainprocs.gpos_cursive(head,start,stop,kind,chainname,currentcontext,l
return head,start,false
end
function chainprocs.gpos_single(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex,sequence)
- local startchar=start.char
+ local startchar=getchar(start)
local subtables=currentlookup.subtables
local lookupname=subtables[1]
local kerns=lookuphash[lookupname]
@@ -11299,9 +11919,9 @@ function chainprocs.gpos_single(head,start,stop,kind,chainname,currentcontext,lo
end
chainmores.gpos_single=chainprocs.gpos_single
function chainprocs.gpos_pair(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex,sequence)
- local snext=start.next
+ local snext=getnext(start)
if snext then
- local startchar=start.char
+ local startchar=getchar(start)
local subtables=currentlookup.subtables
local lookupname=subtables[1]
local kerns=lookuphash[lookupname]
@@ -11311,26 +11931,26 @@ function chainprocs.gpos_pair(head,start,stop,kind,chainname,currentcontext,look
local lookuptype=lookuptypes[lookupname]
local prev,done=start,false
local factor=tfmdata.parameters.factor
- while snext and snext.id==glyph_code and snext.font==currentfont and snext.subtype<256 do
- local nextchar=snext.char
+ while snext and getid(snext)==glyph_code and getfont(snext)==currentfont and getsubtype(snext)<256 do
+ local nextchar=getchar(snext)
local krn=kerns[nextchar]
if not krn and marks[nextchar] then
prev=snext
- snext=snext.next
+ snext=getnext(snext)
else
if not krn then
elseif type(krn)=="table" then
if lookuptype=="pair" then
local a,b=krn[2],krn[3]
if a and #a>0 then
- local startchar=start.char
+ local startchar=getchar(start)
local x,y,w,h=setpair(start,factor,rlmode,sequence.flags[4],a,characters[startchar])
if trace_kerns then
logprocess("%s: shifting first of pair %s and %s by (%p,%p) and correction (%p,%p)",cref(kind,chainname,chainlookupname),gref(startchar),gref(nextchar),x,y,w,h)
end
end
if b and #b>0 then
- local startchar=start.char
+ local startchar=getchar(start)
local x,y,w,h=setpair(snext,factor,rlmode,sequence.flags[4],b,characters[nextchar])
if trace_kerns then
logprocess("%s: shifting second of pair %s and %s by (%p,%p) and correction (%p,%p)",cref(kind,chainname,chainlookupname),gref(startchar),gref(nextchar),x,y,w,h)
@@ -11342,7 +11962,7 @@ function chainprocs.gpos_pair(head,start,stop,kind,chainname,currentcontext,look
if a and a~=0 then
local k=setkern(snext,factor,rlmode,a)
if trace_kerns then
- logprocess("%s: inserting first kern %s between %s and %s",cref(kind,chainname,chainlookupname),k,gref(prev.char),gref(nextchar))
+ logprocess("%s: inserting first kern %s between %s and %s",cref(kind,chainname,chainlookupname),k,gref(getchar(prev)),gref(nextchar))
end
end
if b and b~=0 then
@@ -11353,7 +11973,7 @@ function chainprocs.gpos_pair(head,start,stop,kind,chainname,currentcontext,look
elseif krn~=0 then
local k=setkern(snext,factor,rlmode,krn)
if trace_kerns then
- logprocess("%s: inserting kern %s between %s and %s",cref(kind,chainname,chainlookupname),k,gref(prev.char),gref(nextchar))
+ logprocess("%s: inserting kern %s between %s and %s",cref(kind,chainname,chainlookupname),k,gref(getchar(prev)),gref(nextchar))
end
done=true
end
@@ -11374,6 +11994,10 @@ local function show_skip(kind,chainname,char,ck,class)
logwarning("%s: skipping char %s, class %a, rule %a, lookuptype %a",cref(kind,chainname),gref(char),class,ck[1],ck[2])
end
end
+local quit_on_no_replacement=true
+directives.register("otf.chain.quitonnoreplacement",function(value)
+ quit_on_no_replacement=value
+end)
local function normal_handle_contextchain(head,start,kind,chainname,contexts,sequence,lookuphash)
local flags=sequence.flags
local done=false
@@ -11391,7 +12015,7 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
local seq=ck[3]
local s=#seq
if s==1 then
- match=current.id==glyph_code and current.font==currentfont and current.subtype<256 and seq[1][current.char]
+ match=getid(current)==glyph_code and getfont(current)==currentfont and getsubtype(current)<256 and seq[1][getchar(current)]
else
local f,l=ck[4],ck[5]
if f==1 and f==l then
@@ -11399,13 +12023,13 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
if f==l then
else
local n=f+1
- last=last.next
+ last=getnext(last)
while n<=l do
if last then
- local id=last.id
+ local id=getid(last)
if id==glyph_code then
- if last.font==currentfont and last.subtype<256 then
- local char=last.char
+ if getfont(last)==currentfont and getsubtype(last)<256 then
+ local char=getchar(last)
local ccd=descriptions[char]
if ccd then
local class=ccd.class
@@ -11414,10 +12038,10 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
if trace_skips then
show_skip(kind,chainname,char,ck,class)
end
- last=last.next
+ last=getnext(last)
elseif seq[n][char] then
if n<l then
- last=last.next
+ last=getnext(last)
end
n=n+1
else
@@ -11433,7 +12057,7 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
break
end
elseif id==disc_code then
- last=last.next
+ last=getnext(last)
else
match=false
break
@@ -11446,15 +12070,15 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
end
end
if match and f>1 then
- local prev=start.prev
+ local prev=getprev(start)
if prev then
local n=f-1
while n>=1 do
if prev then
- local id=prev.id
+ local id=getid(prev)
if id==glyph_code then
- if prev.font==currentfont and prev.subtype<256 then
- local char=prev.char
+ if getfont(prev)==currentfont and getsubtype(prev)<256 then
+ local char=getchar(prev)
local ccd=descriptions[char]
if ccd then
local class=ccd.class
@@ -11484,7 +12108,7 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
match=false
break
end
- prev=prev.prev
+ prev=getprev(prev)
elseif seq[n][32] then
n=n -1
else
@@ -11504,15 +12128,15 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
end
end
if match and s>l then
- local current=last and last.next
+ local current=last and getnext(last)
if current then
local n=l+1
while n<=s do
if current then
- local id=current.id
+ local id=getid(current)
if id==glyph_code then
- if current.font==currentfont and current.subtype<256 then
- local char=current.char
+ if getfont(current)==currentfont and getsubtype(current)<256 then
+ local char=getchar(current)
local ccd=descriptions[char]
if ccd then
local class=ccd.class
@@ -11542,7 +12166,7 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
match=false
break
end
- current=current.next
+ current=getnext(current)
elseif seq[n][32] then
n=n+1
else
@@ -11565,7 +12189,7 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
if match then
if trace_contexts then
local rule,lookuptype,f,l=ck[1],ck[2],ck[4],ck[5]
- local char=start.char
+ local char=getchar(start)
if ck[9] then
logwarning("%s: rule %s matches at char %s for (%s,%s,%s) chars, lookuptype %a, %a => %a",
cref(kind,chainname),rule,gref(char),f-1,l-f+1,s-l,lookuptype,ck[9],ck[10])
@@ -11596,15 +12220,15 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
end
else
local i=1
- repeat
+ while true do
if skipped then
while true do
- local char=start.char
+ local char=getchar(start)
local ccd=descriptions[char]
if ccd then
local class=ccd.class
if class==skipmark or class==skipligature or class==skipbase or (markclass and class=="mark" and not markclass[char]) then
- start=start.next
+ start=getnext(start)
else
break
end
@@ -11633,18 +12257,20 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
end
end
end
- if start then
- start=start.next
+ if i>nofchainlookups then
+ break
+ elseif start then
+ start=getnext(start)
else
end
- until i>nofchainlookups
+ end
end
else
local replacements=ck[7]
if replacements then
head,start,done=chainprocs.reversesub(head,start,last,kind,chainname,ck,lookuphash,replacements)
else
- done=true
+ done=quit_on_no_replacement
if trace_contexts then
logprocess("%s: skipping match",cref(kind,chainname))
end
@@ -11715,7 +12341,7 @@ local function initialize(sequence,script,language,enabled)
if features then
local order=sequence.order
if order then
- for i=1,#order do
+ for i=1,#order do
local kind=order[i]
local valid=enabled[kind]
if valid then
@@ -11767,6 +12393,7 @@ local function featuresprocessor(head,font,attr)
if not lookuphash then
return head,false
end
+ head=tonut(head)
if trace_steps then
checkstep(head)
end
@@ -11778,6 +12405,7 @@ local function featuresprocessor(head,font,attr)
anchorlookups=resources.lookup_to_anchor
lookuptable=resources.lookups
lookuptypes=resources.lookuptypes
+ lookuptags=resources.lookuptags
currentfont=font
rlmode=0
local sequences=resources.sequences
@@ -11799,10 +12427,10 @@ local function featuresprocessor(head,font,attr)
local handler=handlers[typ]
local start=find_node_tail(head)
while start do
- local id=start.id
+ local id=getid(start)
if id==glyph_code then
- if start.font==font and start.subtype<256 then
- local a=start[0]
+ if getfont(start)==font and getsubtype(start)<256 then
+ local a=getattr(start,0)
if a then
a=a==attr
else
@@ -11813,7 +12441,7 @@ local function featuresprocessor(head,font,attr)
local lookupname=subtables[i]
local lookupcache=lookuphash[lookupname]
if lookupcache then
- local lookupmatch=lookupcache[start.char]
+ local lookupmatch=lookupcache[getchar(start)]
if lookupmatch then
head,start,success=handler(head,start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,i)
if success then
@@ -11824,15 +12452,15 @@ local function featuresprocessor(head,font,attr)
report_missing_cache(typ,lookupname)
end
end
- if start then start=start.prev end
+ if start then start=getprev(start) end
else
- start=start.prev
+ start=getprev(start)
end
else
- start=start.prev
+ start=getprev(start)
end
else
- start=start.prev
+ start=getprev(start)
end
end
else
@@ -11850,16 +12478,16 @@ local function featuresprocessor(head,font,attr)
local head=start
local done=false
while start do
- local id=start.id
- if id==glyph_code and start.font==font and start.subtype<256 then
- local a=start[0]
+ local id=getid(start)
+ if id==glyph_code and getfont(start)==font and getsubtype(start)<256 then
+ local a=getattr(start,0)
if a then
- a=(a==attr) and (not attribute or start[a_state]==attribute)
+ a=(a==attr) and (not attribute or getprop(start,a_state)==attribute)
else
- a=not attribute or start[a_state]==attribute
+ a=not attribute or getprop(start,a_state)==attribute
end
if a then
- local lookupmatch=lookupcache[start.char]
+ local lookupmatch=lookupcache[getchar(start)]
if lookupmatch then
local ok
head,start,ok=handler(head,start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,1)
@@ -11867,12 +12495,12 @@ local function featuresprocessor(head,font,attr)
done=true
end
end
- if start then start=start.next end
+ if start then start=getnext(start) end
else
- start=start.next
+ start=getnext(start)
end
else
- start=start.next
+ start=getnext(start)
end
end
if done then
@@ -11881,18 +12509,18 @@ local function featuresprocessor(head,font,attr)
end
end
local function kerndisc(disc)
- local prev=disc.prev
- local next=disc.next
+ local prev=getprev(disc)
+ local next=getnext(disc)
if prev and next then
- prev.next=next
- local a=prev[0]
+ setfield(prev,"next",next)
+ local a=getattr(prev,0)
if a then
- a=(a==attr) and (not attribute or prev[a_state]==attribute)
+ a=(a==attr) and (not attribute or getprop(prev,a_state)==attribute)
else
- a=not attribute or prev[a_state]==attribute
+ a=not attribute or getprop(prev,a_state)==attribute
end
if a then
- local lookupmatch=lookupcache[prev.char]
+ local lookupmatch=lookupcache[getchar(prev)]
if lookupmatch then
local h,d,ok=handler(head,prev,dataset[4],lookupname,lookupmatch,sequence,lookuphash,1)
if ok then
@@ -11901,22 +12529,22 @@ local function featuresprocessor(head,font,attr)
end
end
end
- prev.next=disc
+ setfield(prev,"next",disc)
end
return next
end
while start do
- local id=start.id
+ local id=getid(start)
if id==glyph_code then
- if start.font==font and start.subtype<256 then
- local a=start[0]
+ if getfont(start)==font and getsubtype(start)<256 then
+ local a=getattr(start,0)
if a then
- a=(a==attr) and (not attribute or start[a_state]==attribute)
+ a=(a==attr) and (not attribute or getprop(start,a_state)==attribute)
else
- a=not attribute or start[a_state]==attribute
+ a=not attribute or getprop(start,a_state)==attribute
end
if a then
- local lookupmatch=lookupcache[start.char]
+ local lookupmatch=lookupcache[getchar(start)]
if lookupmatch then
local ok
head,start,ok=handler(head,start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,1)
@@ -11924,38 +12552,38 @@ local function featuresprocessor(head,font,attr)
success=true
end
end
- if start then start=start.next end
+ if start then start=getnext(start) end
else
- start=start.next
+ start=getnext(start)
end
else
- start=start.next
+ start=getnext(start)
end
elseif id==disc_code then
- if start.subtype==discretionary_code then
- local pre=start.pre
+ if getsubtype(start)==discretionary_code then
+ local pre=getfield(start,"pre")
if pre then
local new=subrun(pre)
- if new then start.pre=new end
+ if new then setfield(start,"pre",new) end
end
- local post=start.post
+ local post=getfield(start,"post")
if post then
local new=subrun(post)
- if new then start.post=new end
+ if new then setfield(start,"post",new) end
end
- local replace=start.replace
+ local replace=getfield(start,"replace")
if replace then
local new=subrun(replace)
- if new then start.replace=new end
+ if new then setfield(start,"replace",new) end
end
elseif typ=="gpos_single" or typ=="gpos_pair" then
kerndisc(start)
end
- start=start.next
+ start=getnext(start)
elseif id==whatsit_code then
- local subtype=start.subtype
+ local subtype=getsubtype(start)
if subtype==dir_code then
- local dir=start.dir
+ local dir=getfield(start,"dir")
if dir=="+TRT" or dir=="+TLT" then
topstack=topstack+1
dirstack[topstack]=dir
@@ -11974,7 +12602,7 @@ elseif typ=="gpos_single" or typ=="gpos_pair" then
report_process("directions after txtdir %a: parmode %a, txtmode %a, # stack %a, new dir %a",dir,rlparmode,rlmode,topstack,newdir)
end
elseif subtype==localpar_code then
- local dir=start.dir
+ local dir=getfield(start,"dir")
if dir=="TRT" then
rlparmode=-1
elseif dir=="TLT" then
@@ -11987,11 +12615,11 @@ elseif typ=="gpos_single" or typ=="gpos_pair" then
report_process("directions after pardir %a: parmode %a, txtmode %a",dir,rlparmode,rlmode)
end
end
- start=start.next
+ start=getnext(start)
elseif id==math_code then
- start=end_of_math(start).next
+ start=getnext(end_of_math(start))
else
- start=start.next
+ start=getnext(start)
end
end
end
@@ -12000,20 +12628,20 @@ elseif typ=="gpos_single" or typ=="gpos_pair" then
local head=start
local done=false
while start do
- local id=start.id
- if id==glyph_code and start.id==font and start.subtype<256 then
- local a=start[0]
+ local id=getid(start)
+ if id==glyph_code and getfont(start)==font and getsubtype(start)<256 then
+ local a=getattr(start,0)
if a then
- a=(a==attr) and (not attribute or start[a_state]==attribute)
+ a=(a==attr) and (not attribute or getprop(start,a_state)==attribute)
else
- a=not attribute or start[a_state]==attribute
+ a=not attribute or getprop(start,a_state)==attribute
end
if a then
for i=1,ns do
local lookupname=subtables[i]
local lookupcache=lookuphash[lookupname]
if lookupcache then
- local lookupmatch=lookupcache[start.char]
+ local lookupmatch=lookupcache[getchar(start)]
if lookupmatch then
local ok
head,start,ok=handler(head,start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,i)
@@ -12028,12 +12656,12 @@ elseif typ=="gpos_single" or typ=="gpos_pair" then
report_missing_cache(typ,lookupname)
end
end
- if start then start=start.next end
+ if start then start=getnext(start) end
else
- start=start.next
+ start=getnext(start)
end
else
- start=start.next
+ start=getnext(start)
end
end
if done then
@@ -12042,22 +12670,22 @@ elseif typ=="gpos_single" or typ=="gpos_pair" then
end
end
local function kerndisc(disc)
- local prev=disc.prev
- local next=disc.next
+ local prev=getprev(disc)
+ local next=getnext(disc)
if prev and next then
- prev.next=next
- local a=prev[0]
+ setfield(prev,"next",next)
+ local a=getattr(prev,0)
if a then
- a=(a==attr) and (not attribute or prev[a_state]==attribute)
+ a=(a==attr) and (not attribute or getprop(prev,a_state)==attribute)
else
- a=not attribute or prev[a_state]==attribute
+ a=not attribute or getprop(prev,a_state)==attribute
end
if a then
for i=1,ns do
local lookupname=subtables[i]
local lookupcache=lookuphash[lookupname]
if lookupcache then
- local lookupmatch=lookupcache[prev.char]
+ local lookupmatch=lookupcache[getchar(prev)]
if lookupmatch then
local h,d,ok=handler(head,prev,dataset[4],lookupname,lookupmatch,sequence,lookuphash,i)
if ok then
@@ -12070,26 +12698,26 @@ elseif typ=="gpos_single" or typ=="gpos_pair" then
end
end
end
- prev.next=disc
+ setfield(prev,"next",disc)
end
return next
end
while start do
- local id=start.id
+ local id=getid(start)
if id==glyph_code then
- if start.font==font and start.subtype<256 then
- local a=start[0]
+ if getfont(start)==font and getsubtype(start)<256 then
+ local a=getattr(start,0)
if a then
- a=(a==attr) and (not attribute or start[a_state]==attribute)
+ a=(a==attr) and (not attribute or getprop(start,a_state)==attribute)
else
- a=not attribute or start[a_state]==attribute
+ a=not attribute or getprop(start,a_state)==attribute
end
if a then
for i=1,ns do
local lookupname=subtables[i]
local lookupcache=lookuphash[lookupname]
if lookupcache then
- local lookupmatch=lookupcache[start.char]
+ local lookupmatch=lookupcache[getchar(start)]
if lookupmatch then
local ok
head,start,ok=handler(head,start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,i)
@@ -12104,38 +12732,38 @@ elseif typ=="gpos_single" or typ=="gpos_pair" then
report_missing_cache(typ,lookupname)
end
end
- if start then start=start.next end
+ if start then start=getnext(start) end
else
- start=start.next
+ start=getnext(start)
end
else
- start=start.next
+ start=getnext(start)
end
elseif id==disc_code then
- if start.subtype==discretionary_code then
- local pre=start.pre
+ if getsubtype(start)==discretionary_code then
+ local pre=getfield(start,"pre")
if pre then
local new=subrun(pre)
- if new then start.pre=new end
+ if new then setfield(start,"pre",new) end
end
- local post=start.post
+ local post=getfield(start,"post")
if post then
local new=subrun(post)
- if new then start.post=new end
+ if new then setfield(start,"post",new) end
end
- local replace=start.replace
+ local replace=getfield(start,"replace")
if replace then
local new=subrun(replace)
- if new then start.replace=new end
+ if new then setfield(start,"replace",new) end
end
elseif typ=="gpos_single" or typ=="gpos_pair" then
kerndisc(start)
end
- start=start.next
+ start=getnext(start)
elseif id==whatsit_code then
- local subtype=start.subtype
+ local subtype=getsubtype(start)
if subtype==dir_code then
- local dir=start.dir
+ local dir=getfield(start,"dir")
if dir=="+TRT" or dir=="+TLT" then
topstack=topstack+1
dirstack[topstack]=dir
@@ -12154,7 +12782,7 @@ elseif typ=="gpos_single" or typ=="gpos_pair" then
report_process("directions after txtdir %a: parmode %a, txtmode %a, # stack %a, new dir %a",dir,rlparmode,rlmode,topstack,newdir)
end
elseif subtype==localpar_code then
- local dir=start.dir
+ local dir=getfield(start,"dir")
if dir=="TRT" then
rlparmode=-1
elseif dir=="TLT" then
@@ -12167,11 +12795,11 @@ elseif typ=="gpos_single" or typ=="gpos_pair" then
report_process("directions after pardir %a: parmode %a, txtmode %a",dir,rlparmode,rlmode)
end
end
- start=start.next
+ start=getnext(start)
elseif id==math_code then
- start=end_of_math(start).next
+ start=getnext(end_of_math(start))
else
- start=start.next
+ start=getnext(start)
end
end
end
@@ -12183,6 +12811,7 @@ elseif typ=="gpos_single" or typ=="gpos_pair" then
registerstep(head)
end
end
+ head=tonode(head)
return head,done
end
local function generic(lookupdata,lookupname,unicode,lookuphash)
@@ -12309,6 +12938,7 @@ local function prepare_contextchains(tfmdata)
local rawdata=tfmdata.shared.rawdata
local resources=rawdata.resources
local lookuphash=resources.lookuphash
+ local lookuptags=resources.lookuptags
local lookups=rawdata.lookups
if lookups then
for lookupname,lookupdata in next,rawdata.lookups do
@@ -12321,7 +12951,7 @@ local function prepare_contextchains(tfmdata)
if not validformat then
report_prepare("unsupported format %a",format)
elseif not validformat[lookuptype] then
- report_prepare("unsupported format %a, lookuptype %a, lookupname %a",format,lookuptype,lookupname)
+ report_prepare("unsupported format %a, lookuptype %a, lookupname %a",format,lookuptype,lookuptags[lookupname])
else
local contexts=lookuphash[lookupname]
if not contexts then
@@ -12370,7 +13000,7 @@ local function prepare_contextchains(tfmdata)
else
end
else
- report_prepare("missing lookuptype for lookupname %a",lookupname)
+ report_prepare("missing lookuptype for lookupname %a",lookuptags[lookupname])
end
end
end
@@ -13242,6 +13872,7 @@ if otf.enhancers.register then
otf.enhancers.register("unpack",unpackdata)
end
otf.enhancers.unpack=unpackdata
+otf.enhancers.pack=packdata
end -- closure
@@ -13597,8 +14228,8 @@ function definers.read(specification,size,id)
elseif trace_defining and type(tfmdata)=="table" then
local properties=tfmdata.properties or {}
local parameters=tfmdata.parameters or {}
- report_defining("using %s font with id %a, name %a, size %a, bytes %a, encoding %a, fullname %a, filename %a",
- properties.format,id,properties.name,parameters.size,properties.encodingbytes,
+ report_defining("using %a font with id %a, name %a, size %a, bytes %a, encoding %a, fullname %a, filename %a",
+ properties.format or "unknown",id,properties.name,parameters.size,properties.encodingbytes,
properties.encodingname,properties.fullname,file.basename(properties.filename))
end
statistics.stoptiming(fonts)
@@ -13929,13 +14560,20 @@ local fonts=fonts
local nodes=nodes
local traverse_id=node.traverse_id
local glyph_code=nodes.nodecodes.glyph
+local ligaturing=node.ligaturing
+local kerning=node.kerning
+function node.ligaturing() texio.write_nl("warning: node.ligaturing is already applied") end
+function node.kerning () texio.write_nl("warning: node.kerning is already applied") end
function nodes.handlers.characters(head)
local fontdata=fonts.hashes.identifiers
if fontdata then
- local usedfonts,done,prevfont={},false,nil
+ local usedfonts,basefonts,prevfont,basefont={},{},nil,nil
for n in traverse_id(glyph_code,head) do
local font=n.font
if font~=prevfont then
+ if basefont then
+ basefont[2]=n.prev
+ end
prevfont=font
local used=usedfonts[font]
if not used then
@@ -13946,18 +14584,32 @@ function nodes.handlers.characters(head)
local processors=shared.processes
if processors and #processors>0 then
usedfonts[font]=processors
- done=true
+ else
+ basefont={ n,nil }
+ basefonts[#basefonts+1]=basefont
end
end
end
end
end
end
- if done then
+ if next(usedfonts) then
for font,processors in next,usedfonts do
for i=1,#processors do
- local h,d=processors[i](head,font,0)
- head,done=h or head,done or d
+ head=processors[i](head,font,0) or head
+ end
+ end
+ end
+ if #basefonts>0 then
+ for i=1,#basefonts do
+ local range=basefonts[i]
+ local start,stop=range[1],range[2]
+ if stop then
+ ligaturing(start,stop)
+ kerning(start,stop)
+ else
+ ligaturing(start)
+ kerning(start)
end
end
end
@@ -13970,8 +14622,6 @@ function nodes.simple_font_handler(head)
head=nodes.handlers.characters(head)
nodes.injections.handler(head)
nodes.handlers.protectglyphs(head)
- head=node.ligaturing(head)
- head=node.kerning(head)
return head
end