summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/luatex/luaotfload/fontloader-reference.lua
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/tex/luatex/luaotfload/fontloader-reference.lua')
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/fontloader-reference.lua1836
1 files changed, 1279 insertions, 557 deletions
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-reference.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-reference.lua
index 59cbd9ef8ca..736856d2beb 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-reference.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-reference.lua
@@ -1,6 +1,6 @@
-- merged file : c:/data/develop/context/sources/luatex-fonts-merged.lua
-- parent file : c:/data/develop/context/sources/luatex-fonts.lua
--- merge date : 2021-05-20 15:57
+-- merge date : 2022-01-21 20:10
do -- begin closure to overcome local limits and interference
@@ -2255,9 +2255,12 @@ function io.copydata(source,target,action)
flush()
end
end
-function io.savedata(filename,data,joiner)
- local f=open(filename,"wb")
+function io.savedata(filename,data,joiner,append)
+ local f=open(filename,append and "ab" or "wb")
if f then
+ if append and joiner and f:seek("end")>0 then
+ f:write(joiner)
+ end
if type(data)=="table" then
f:write(concat(data,joiner or ""))
elseif type(data)=="function" then
@@ -2791,7 +2794,7 @@ function file.join(one,two,three,...)
if not two then
return one=="" and one or lpegmatch(reslasher,one)
end
- if one=="" then
+ if not one or one=="" then
return lpegmatch(stripper,three and concat({ two,three,... },"/") or two)
end
if lpegmatch(isnetwork,one) then
@@ -3099,7 +3102,7 @@ if not math.tointeger then
end
if not math.ult then
local floor=math.floor
- function math.tointeger(m,n)
+ function math.ult(m,n)
return floor(m)<floor(n)
end
end
@@ -3118,12 +3121,13 @@ if not modules then modules={} end modules ['util-str']={
utilities=utilities or {}
utilities.strings=utilities.strings or {}
local strings=utilities.strings
-local format,gsub,rep,sub,find=string.format,string.gsub,string.rep,string.sub,string.find
+local format,gsub,rep,sub,find,char=string.format,string.gsub,string.rep,string.sub,string.find,string.char
local load,dump=load,string.dump
local tonumber,type,tostring,next,setmetatable=tonumber,type,tostring,next,setmetatable
local unpack,concat=table.unpack,table.concat
local P,V,C,S,R,Ct,Cs,Cp,Carg,Cc=lpeg.P,lpeg.V,lpeg.C,lpeg.S,lpeg.R,lpeg.Ct,lpeg.Cs,lpeg.Cp,lpeg.Carg,lpeg.Cc
local patterns,lpegmatch=lpeg.patterns,lpeg.match
+local tsplitat=lpeg.tsplitat
local utfchar,utfbyte,utflen=utf.char,utf.byte,utf.len
local loadstripped=function(str,shortcuts)
if shortcuts then
@@ -3477,6 +3481,14 @@ patterns.escapedquotes=pattern
function string.escapedquotes(s)
return lpegmatch(pattern,s)
end
+local pattern=(1-P("\\"))^1;pattern=Cs (
+ pattern*((P("\\")/""*(digit^-3/function(s) return char(tonumber(s)) end))+pattern )^1
+)
+patterns.unescapedquotes=pattern
+function string.unescapedquotes(s)
+ return lpegmatch(pattern,s) or s
+end
+string.texnewlines=lpeg.replacer(patterns.newline,"\r",true)
local preamble=""
local environment={
global=global or _G,
@@ -4012,7 +4024,6 @@ function number.to16dot16(n)
return f_16_16(n/65536.0)
end
if not string.explode then
- local tsplitat=lpeg.tsplitat
local p_utf=patterns.utf8character
local p_check=C(p_utf)*(P("+")*Cc(true))^0
local p_split=Ct(C(p_utf)^0)
@@ -4032,6 +4043,20 @@ if not string.explode then
end
end
end
+do
+ local p_whitespace=patterns.whitespace^1
+ local cache=setmetatable({},{ __index=function(t,k)
+ local p=tsplitat(p_whitespace*P(k)*p_whitespace)
+ local v=function(s)
+ return lpegmatch(p,s)
+ end
+ t[k]=v
+ return v
+ end })
+ function string.wordsplitter(s)
+ return cache[s]
+ end
+end
end -- closure
@@ -4202,20 +4227,20 @@ function files.readinteger4le(f)
end
end
function files.readfixed2(f)
- local a,b=byte(f:read(2),1,2)
- if a>=0x80 then
- tonumber((a-0x100).."."..b)
- else
- tonumber((a ).."."..b)
+ local n1,n2=byte(f:read(2),1,2)
+ if n1>=0x80 then
+ n1=n1-0x100
end
+ return n1+n2/0xFF
end
function files.readfixed4(f)
local a,b,c,d=byte(f:read(4),1,4)
- if a>=0x80 then
- tonumber((0x100*a+b-0x10000).."."..(0x100*c+d))
- else
- tonumber((0x100*a+b ).."."..(0x100*c+d))
+ local n1=0x100*a+b
+ local n2=0x100*c+d
+ if n1>=0x8000 then
+ n1=n1-0x10000
end
+ return n1+n2/0xFFFF
end
if bit32 then
local extract=bit32.extract
@@ -4996,7 +5021,7 @@ nuts.setcomponents=direct.setcomponents
nuts.setdirection=direct.setdirection
nuts.setdisc=direct.setdisc
nuts.setreplace=direct.setreplace
-nuts.setfield=setfield
+nuts.setfield=direct.setfield
nuts.setkern=direct.setkern
nuts.setlink=direct.setlink
nuts.setlist=direct.setlist
@@ -5379,6 +5404,7 @@ characters.classifiers={
[1562]=5,
[1563]=6,
[1564]=6,
+ [1565]=6,
[1566]=6,
[1567]=6,
[1568]=2,
@@ -5845,9 +5871,9 @@ characters.classifiers={
[2131]=2,
[2132]=3,
[2133]=2,
- [2134]=4,
- [2135]=4,
- [2136]=4,
+ [2134]=3,
+ [2135]=3,
+ [2136]=3,
[2137]=5,
[2138]=5,
[2139]=5,
@@ -5862,6 +5888,47 @@ characters.classifiers={
[2152]=2,
[2153]=3,
[2154]=3,
+ [2160]=3,
+ [2161]=3,
+ [2162]=3,
+ [2163]=3,
+ [2164]=3,
+ [2165]=3,
+ [2166]=3,
+ [2167]=3,
+ [2168]=3,
+ [2169]=3,
+ [2170]=3,
+ [2171]=3,
+ [2172]=3,
+ [2173]=3,
+ [2174]=3,
+ [2175]=3,
+ [2176]=3,
+ [2177]=3,
+ [2178]=3,
+ [2179]=2,
+ [2180]=2,
+ [2181]=2,
+ [2182]=2,
+ [2183]=4,
+ [2184]=4,
+ [2185]=2,
+ [2186]=2,
+ [2187]=2,
+ [2188]=2,
+ [2189]=2,
+ [2190]=3,
+ [2192]=4,
+ [2193]=4,
+ [2200]=5,
+ [2201]=5,
+ [2202]=5,
+ [2203]=5,
+ [2204]=5,
+ [2205]=5,
+ [2206]=5,
+ [2207]=5,
[2208]=2,
[2209]=2,
[2210]=2,
@@ -5883,6 +5950,7 @@ characters.classifiers={
[2226]=3,
[2227]=2,
[2228]=2,
+ [2229]=2,
[2230]=2,
[2231]=2,
[2232]=2,
@@ -5891,6 +5959,26 @@ characters.classifiers={
[2235]=2,
[2236]=2,
[2237]=2,
+ [2238]=2,
+ [2239]=2,
+ [2240]=2,
+ [2241]=2,
+ [2242]=2,
+ [2243]=2,
+ [2244]=2,
+ [2245]=2,
+ [2246]=2,
+ [2247]=2,
+ [2248]=2,
+ [2250]=5,
+ [2251]=5,
+ [2252]=5,
+ [2253]=5,
+ [2254]=5,
+ [2255]=5,
+ [2256]=5,
+ [2257]=5,
+ [2258]=5,
[2259]=5,
[2260]=5,
[2261]=5,
@@ -6010,6 +6098,7 @@ characters.classifiers={
[2883]=5,
[2884]=5,
[2893]=5,
+ [2901]=5,
[2902]=5,
[2914]=5,
[2915]=5,
@@ -6018,6 +6107,7 @@ characters.classifiers={
[3021]=5,
[3072]=5,
[3076]=5,
+ [3132]=5,
[3134]=5,
[3135]=5,
[3136]=5,
@@ -6051,6 +6141,7 @@ characters.classifiers={
[3405]=5,
[3426]=5,
[3427]=5,
+ [3457]=5,
[3530]=5,
[3538]=5,
[3539]=5,
@@ -6230,6 +6321,7 @@ characters.classifiers={
[6156]=5,
[6157]=5,
[6158]=4,
+ [6159]=5,
[6176]=2,
[6177]=2,
[6178]=2,
@@ -6414,6 +6506,22 @@ characters.classifiers={
[6843]=5,
[6844]=5,
[6845]=5,
+ [6847]=5,
+ [6848]=5,
+ [6849]=5,
+ [6850]=5,
+ [6851]=5,
+ [6852]=5,
+ [6853]=5,
+ [6854]=5,
+ [6855]=5,
+ [6856]=5,
+ [6857]=5,
+ [6858]=5,
+ [6859]=5,
+ [6860]=5,
+ [6861]=5,
+ [6862]=5,
[6912]=5,
[6913]=5,
[6914]=5,
@@ -6546,6 +6654,7 @@ characters.classifiers={
[7671]=5,
[7672]=5,
[7673]=5,
+ [7674]=5,
[7675]=5,
[7676]=5,
[7677]=5,
@@ -6647,6 +6756,7 @@ characters.classifiers={
[43019]=5,
[43045]=5,
[43046]=5,
+ [43052]=5,
[43072]=2,
[43073]=2,
[43074]=2,
@@ -6923,6 +7033,8 @@ characters.classifiers={
[68901]=5,
[68902]=5,
[68903]=5,
+ [69291]=5,
+ [69292]=5,
[69424]=2,
[69425]=2,
[69426]=2,
@@ -6960,6 +7072,56 @@ characters.classifiers={
[69458]=2,
[69459]=2,
[69460]=3,
+ [69488]=2,
+ [69489]=2,
+ [69490]=2,
+ [69491]=2,
+ [69492]=3,
+ [69493]=3,
+ [69494]=2,
+ [69495]=2,
+ [69496]=2,
+ [69497]=2,
+ [69498]=2,
+ [69499]=2,
+ [69500]=2,
+ [69501]=2,
+ [69502]=2,
+ [69503]=2,
+ [69504]=2,
+ [69505]=2,
+ [69506]=5,
+ [69507]=5,
+ [69508]=5,
+ [69509]=5,
+ [69552]=2,
+ [69553]=4,
+ [69554]=2,
+ [69555]=2,
+ [69556]=3,
+ [69557]=3,
+ [69558]=3,
+ [69559]=4,
+ [69560]=2,
+ [69561]=3,
+ [69562]=3,
+ [69563]=2,
+ [69564]=2,
+ [69565]=3,
+ [69566]=2,
+ [69567]=2,
+ [69568]=4,
+ [69569]=2,
+ [69570]=3,
+ [69571]=3,
+ [69572]=2,
+ [69573]=4,
+ [69574]=4,
+ [69575]=4,
+ [69576]=4,
+ [69577]=3,
+ [69578]=2,
+ [69579]=1,
[69633]=5,
[69688]=5,
[69689]=5,
@@ -6976,6 +7138,9 @@ characters.classifiers={
[69700]=5,
[69701]=5,
[69702]=5,
+ [69744]=5,
+ [69747]=5,
+ [69748]=5,
[69759]=5,
[69760]=5,
[69761]=5,
@@ -6986,6 +7151,7 @@ characters.classifiers={
[69817]=5,
[69818]=5,
[69821]=4,
+ [69826]=5,
[69837]=4,
[69888]=5,
[69889]=5,
@@ -7018,6 +7184,7 @@ characters.classifiers={
[70090]=5,
[70091]=5,
[70092]=5,
+ [70095]=5,
[70191]=5,
[70192]=5,
[70193]=5,
@@ -7128,6 +7295,10 @@ characters.classifiers={
[71735]=5,
[71737]=5,
[71738]=5,
+ [71995]=5,
+ [71996]=5,
+ [71998]=5,
+ [72003]=5,
[72148]=5,
[72149]=5,
[72150]=5,
@@ -7265,8 +7436,78 @@ characters.classifiers={
[94096]=5,
[94097]=5,
[94098]=5,
+ [94180]=5,
[113821]=5,
[113822]=5,
+ [118528]=5,
+ [118529]=5,
+ [118530]=5,
+ [118531]=5,
+ [118532]=5,
+ [118533]=5,
+ [118534]=5,
+ [118535]=5,
+ [118536]=5,
+ [118537]=5,
+ [118538]=5,
+ [118539]=5,
+ [118540]=5,
+ [118541]=5,
+ [118542]=5,
+ [118543]=5,
+ [118544]=5,
+ [118545]=5,
+ [118546]=5,
+ [118547]=5,
+ [118548]=5,
+ [118549]=5,
+ [118550]=5,
+ [118551]=5,
+ [118552]=5,
+ [118553]=5,
+ [118554]=5,
+ [118555]=5,
+ [118556]=5,
+ [118557]=5,
+ [118558]=5,
+ [118559]=5,
+ [118560]=5,
+ [118561]=5,
+ [118562]=5,
+ [118563]=5,
+ [118564]=5,
+ [118565]=5,
+ [118566]=5,
+ [118567]=5,
+ [118568]=5,
+ [118569]=5,
+ [118570]=5,
+ [118571]=5,
+ [118572]=5,
+ [118573]=5,
+ [118576]=5,
+ [118577]=5,
+ [118578]=5,
+ [118579]=5,
+ [118580]=5,
+ [118581]=5,
+ [118582]=5,
+ [118583]=5,
+ [118584]=5,
+ [118585]=5,
+ [118586]=5,
+ [118587]=5,
+ [118588]=5,
+ [118589]=5,
+ [118590]=5,
+ [118591]=5,
+ [118592]=5,
+ [118593]=5,
+ [118594]=5,
+ [118595]=5,
+ [118596]=5,
+ [118597]=5,
+ [118598]=5,
[119143]=5,
[119144]=5,
[119145]=5,
@@ -7464,6 +7705,7 @@ characters.classifiers={
[123188]=5,
[123189]=5,
[123190]=5,
+ [123566]=5,
[123628]=5,
[123629]=5,
[123630]=5,
@@ -7631,6 +7873,7 @@ characters.indicgroups={
[2879]=true,
[2902]=true,
[3376]=true,
+ [5901]=true,
},
["after_postscript"]={
[2433]=true,
@@ -7806,6 +8049,7 @@ characters.indicgroups={
[2915]=true,
[3009]=true,
[3010]=true,
+ [3132]=true,
[3170]=true,
[3171]=true,
[3260]=true,
@@ -8224,6 +8468,7 @@ characters.indicgroups={
[4225]=true,
[4226]=true,
[4238]=true,
+ [5901]=true,
[43488]=true,
[43489]=true,
[43490]=true,
@@ -8548,6 +8793,7 @@ characters.indicgroups={
[3090]=true,
[3091]=true,
[3092]=true,
+ [3165]=true,
[3168]=true,
[3169]=true,
[3205]=true,
@@ -8564,6 +8810,7 @@ characters.indicgroups={
[3218]=true,
[3219]=true,
[3220]=true,
+ [3293]=true,
[3296]=true,
[3297]=true,
[3333]=true,
@@ -8604,6 +8851,7 @@ characters.indicgroups={
[2620]=true,
[2748]=true,
[2876]=true,
+ [3132]=true,
[3260]=true,
},
["post_mark"]={
@@ -8707,6 +8955,7 @@ characters.indicgroups={
[3120]=true,
[3248]=true,
[3376]=true,
+ [5901]=true,
},
["stress_tone_mark"]={
[2385]=true,
@@ -10252,10 +10501,16 @@ local encodings={}
fonts.encodings=encodings
encodings.agl={}
encodings.known={}
+encodings.glyphlistfilename="font-age.lua"
setmetatable(encodings.agl,{ __index=function(t,k)
if k=="unicodes" then
logs.report("fonts","loading (extended) adobe glyph list")
- local unicodes=dofile(resolvers.findfile("font-age.lua"))
+ local foundname=resolvers.findfile(encodings.glyphlistfilename) or ""
+ local unicodes=foundname~="" and dofile(foundname)
+ if type(unicodes)~="table" then
+ logs.report("fonts","missing or invalid (extended) adobe glyph list")
+ unicodes={}
+ end
encodings.agl={ unicodes=unicodes }
return unicodes
else
@@ -11287,15 +11542,15 @@ local weights={
[900]="black",
}
local widths={
- [1]="ultracondensed",
- [2]="extracondensed",
- [3]="condensed",
- [4]="semicondensed",
- [5]="normal",
- [6]="semiexpanded",
- [7]="expanded",
- [8]="extraexpanded",
- [9]="ultraexpanded",
+ "ultracondensed",
+ "extracondensed",
+ "condensed",
+ "semicondensed",
+ "normal",
+ "semiexpanded",
+ "expanded",
+ "extraexpanded",
+ "ultraexpanded",
}
setmetatableindex(weights,function(t,k)
local r=floor((k+50)/100)*100
@@ -11305,30 +11560,28 @@ end)
setmetatableindex(widths,function(t,k)
return "normal"
end)
-local panoseweights={
- [ 0]="normal",
- [ 1]="normal",
- [ 2]="verylight",
- [ 3]="light",
- [ 4]="thin",
- [ 5]="book",
- [ 6]="medium",
- [ 7]="demi",
- [ 8]="bold",
- [ 9]="heavy",
- [10]="black",
+local panoseweights={ [0]="normal",
+ "normal",
+ "verylight",
+ "light",
+ "thin",
+ "book",
+ "medium",
+ "demi",
+ "bold",
+ "heavy",
+ "black",
}
-local panosewidths={
- [ 0]="normal",
- [ 1]="normal",
- [ 2]="normal",
- [ 3]="normal",
- [ 4]="normal",
- [ 5]="expanded",
- [ 6]="condensed",
- [ 7]="veryexpanded",
- [ 8]="verycondensed",
- [ 9]="monospaced",
+local panosewidths={ [0]="normal",
+ "normal",
+ "normal",
+ "normal",
+ "normal",
+ "expanded",
+ "condensed",
+ "veryexpanded",
+ "verycondensed",
+ "monospaced",
}
local helpers={}
readers.helpers=helpers
@@ -11762,7 +12015,7 @@ readers.post=function(f,fontdata,specification)
local version=readulong(f)
fontdata.postscript={
version=version,
- italicangle=round(1000*readfixed(f))/1000,
+ italicangle=readfixed(f),
underlineposition=readfword(f),
underlinethickness=readfword(f),
monospaced=readulong(f),
@@ -12379,6 +12632,7 @@ local function getinfo(maindata,sub,platformnames,rawfamilynames,metricstoo,inst
pfmwidth=metrics.widthclass or 5,
panosewidth=metrics.panosewidth,
panoseweight=metrics.panoseweight,
+ fstype=metrics.fstype or 0,
italicangle=postscript.italicangle or 0,
units=fontheader.units or 0,
designsize=fontdata.designsize,
@@ -12872,6 +13126,9 @@ end
function readers.compact(fontdata)
report("the %a helper is not yet implemented","compact")
end
+function readers.condense(fontdata)
+ report("the %a helper is not yet implemented","condense")
+end
local extenders={}
function readers.registerextender(extender)
extenders[#extenders+1]=extender
@@ -13339,7 +13596,8 @@ do
top=0
end
local p_dictionary=(
- p_byte+p_positive+p_negative+p_short+p_long+p_nibbles+p_single+p_double+p_unsupported
+ p_byte+p_positive+p_negative+p_short+p_long+p_nibbles+p_single+p_double
++p_unsupported
)^1
parsedictionaries=function(data,dictionaries,version)
stack={}
@@ -13411,6 +13669,7 @@ do
local y=0
local width=false
local lsb=0
+local result={}
local r=0
local stems=0
local globalbias=0
@@ -14365,12 +14624,12 @@ do
stack[top]=-t*256+64148-tab[i+1]
i=i+2
else
- local n=0x100*tab[i+1]+tab[i+2]
- if n>=0x8000 then
- stack[top]=n-0x10000+(0x100*tab[i+3]+tab[i+4])/0xFFFF
- else
- stack[top]=n+(0x100*tab[i+3]+tab[i+4])/0xFFFF
+ local n1=0x100*tab[i+1]+tab[i+2]
+ local n2=0x100*tab[i+3]+tab[i+4]
+ if n1>=0x8000 then
+ n1=n1-0x10000
end
+ stack[top]=n1+n2/0xFFFF
i=i+5
end
elseif t==28 then
@@ -14458,7 +14717,7 @@ do
i=i+s+1
elseif t==1 or t==3 or t==18 or operation==23 then
p_getstem()
- if true then
+ if version=="cff" then
if top>0 then
for i=1,top do
r=r+1;result[r]=encode[stack[i]]
@@ -14471,7 +14730,7 @@ do
end
i=i+1
elseif t==19 or t==20 then
- local s=p_getmask() or 0
+ local s=p_getmask() or 0
if true then
if top>0 then
for i=1,top do
@@ -14494,7 +14753,7 @@ do
i=i+1
elseif t==13 then
hsbw()
- if version=="cff" then
+ if true then
r=r+1;result[r]=encode[lsb]
r=r+1;result[r]=chars[22]
else
@@ -14621,6 +14880,7 @@ do
r=r+1
result[r]=c_endchar
local stream=concat(result)
+result=nil
if glyph then
glyph.stream=stream
else
@@ -14642,6 +14902,7 @@ do
width=width,
name=charset and charset[index] or nil,
}
+result=nil
else
glyphs[index]={
boundingbox=boundingbox,
@@ -15128,7 +15389,7 @@ if not modules then modules={} end modules ['font-ttf']={
}
local next,type,unpack=next,type,unpack
local band,rshift=bit32.band,bit32.rshift
-local sqrt,round=math.sqrt,math.round
+local sqrt,round,abs,min,max=math.sqrt,math.round,math.abs,math.min,math.max
local char,rep=string.char,string.rep
local concat=table.concat
local idiv=number.idiv
@@ -15262,69 +15523,164 @@ local function curveto(m_x,m_y,l_x,l_y,r_x,r_y)
r_x+2/3*(m_x-r_x),r_y+2/3*(m_y-r_y),
r_x,r_y,"c"
end
+local xv={}
+local yv={}
local function applyaxis(glyph,shape,deltas,dowidth)
local points=shape.points
if points then
local nofpoints=#points
- local h=nofpoints+2
- local l=nofpoints+1
local dw=0
local dl=0
for i=1,#deltas do
local deltaset=deltas[i]
local xvalues=deltaset.xvalues
local yvalues=deltaset.yvalues
- local dpoints=deltaset.points
- local factor=deltaset.factor
- if dpoints then
- local nofdpoints=#dpoints
- for i=1,nofdpoints do
- local d=dpoints[i]
- local p=points[d]
- if p then
- if xvalues then
- local x=xvalues[i]
- if x and x~=0 then
- p[1]=p[1]+factor*x
+ if xvalues and yvalues then
+ local dpoints=deltaset.points
+ local factor=deltaset.factor
+ if dpoints then
+ local cnt=#dpoints
+ if dowidth then
+ cnt=cnt-4
+ end
+ if cnt==1 then
+ local d=dpoints[1]
+ local x=xvalues[d]*factor
+ local y=yvalues[d]*factor
+ for i=1,nofpoints do
+ local p=points[i]
+ if x~=0 then
+ p[1]=p[1]+x
+ end
+ if y~=0 then
+ p[2]=p[2]+y
end
end
- if yvalues then
- local y=yvalues[i]
- if y and y~=0 then
- p[2]=p[2]+factor*y
+ elseif cnt>0 then
+ local function find(i)
+ local prv=cnt
+ for j=1,cnt do
+ local nxt=dpoints[j]
+ if nxt==i then
+ return false,j,false
+ elseif nxt>i then
+ return prv,false,j
+ end
+ prv=j
+ end
+ return prv,false,1
+ end
+ for i=1,nofpoints do
+ local d1,d2,d3=find(i)
+ local p2=points[i]
+ if d2 then
+ xv[i]=xvalues[d2]
+ yv[i]=yvalues[d2]
+ else
+ local n1=dpoints[d1]
+ local n3=dpoints[d3]
+ if n1>nofpoints then
+ n1=nofpoints
+ end
+ if n3>nofpoints then
+ n3=nofpoints
+ end
+ local p1=points[n1]
+ local p3=points[n3]
+ local p1x=p1[1]
+ local p2x=p2[1]
+ local p3x=p3[1]
+ local p1y=p1[2]
+ local p2y=p2[2]
+ local p3y=p3[2]
+ local x1=xvalues[d1]
+ local y1=yvalues[d1]
+ local x3=xvalues[d3]
+ local y3=yvalues[d3]
+ local fx
+ local fy
+ if p1x==p3x then
+ if x1==x3 then
+ fx=x1
+ else
+ fx=0
+ end
+ elseif p2x<=min(p1x,p3x) then
+ if p1x<p3x then
+ fx=x1
+ else
+ fx=x3
+ end
+ elseif p2x>=max(p1x,p3x) then
+ if p1x>p3x then
+ fx=x1
+ else
+ fx=x3
+ end
+ else
+ fx=(p2x-p1x)/(p3x-p1x)
+ fx=(1-fx)*x1+fx*x3
+ end
+ if p1y==p3y then
+ if y1==y3 then
+ fy=y1
+ else
+ fy=0
+ end
+ elseif p2y<=min(p1y,p3y) then
+ if p1y<p3y then
+ fy=y1
+ else
+ fy=y3
+ end
+ elseif p2y>=max(p1y,p3y) then
+ if p1y>p3y then
+ fy=y1
+ else
+ fy=y3
+ end
+ else
+ fy=(p2y-p1y)/(p3y-p1y)
+ fy=(1-fy)*y1+fy*y3
+ end
+ xv[i]=fx
+ yv[i]=fy
end
end
- elseif dowidth then
- if d==h then
- local x=xvalues[i]
- if x then
- dw=dw+factor*x
+ for i=1,nofpoints do
+ local pi=points[i]
+ local fx=xv[i]
+ local fy=yv[i]
+ if fx~=0 then
+ pi[1]=pi[1]+factor*fx
end
- elseif d==l then
- local x=xvalues[i]
- if x then
- dl=dl+factor*x
+ if fy~=0 then
+ pi[2]=pi[2]+factor*fy
end
end
+ else
+ report("bad deltapoint data, maybe a missing hvar table")
end
- end
- else
- for i=1,nofpoints do
- local p=points[i]
- if xvalues then
+ else
+ for i=1,nofpoints do
+ local p=points[i]
local x=xvalues[i]
- if x and x~=0 then
- p[1]=p[1]+factor*x
- end
- end
- if yvalues then
- local y=yvalues[i]
- if y and y~=0 then
- p[2]=p[2]+factor*y
+ if x then
+ local y=yvalues[i]
+ if x~=0 then
+ p[1]=p[1]+factor*x
+ end
+ if y~=0 then
+ p[2]=p[2]+factor*y
+ end
+ else
+ break
end
end
end
if dowidth then
+ local h=nofpoints+2
+ local l=nofpoints+1
local x=xvalues[h]
if x then
dw=dw+factor*x
@@ -15903,13 +16259,13 @@ local function readcomposite(f)
yoffset=yoffset*yscale
end
elseif band(flags,0x0080)~=0 then
- xscale=read2dot14(f)
- xrotate=read2dot14(f)
- yrotate=read2dot14(f)
- yscale=read2dot14(f)
+ xscale=read2dot14(f)
+ xrotate=read2dot14(f)
+ yrotate=read2dot14(f)
+ yscale=read2dot14(f)
if f_xyarg and f_offset then
- xoffset=xoffset*sqrt(xscale^2+xrotate^2)
- yoffset=yoffset*sqrt(yrotate^2+yscale^2)
+ xoffset=xoffset*sqrt(xscale^2+yrotate^2)
+ yoffset=yoffset*sqrt(xrotate^2+yscale^2)
end
end
nofcomponents=nofcomponents+1
@@ -16067,40 +16423,6 @@ end
local function readdeltas(f,nofpoints)
local deltas={}
local p=0
- local z=0
- while nofpoints>0 do
- local control=readbyte(f)
-if not control then
- break
-end
- local allzero=band(control,0x80)~=0
- local runlength=band(control,0x3F)+1
- if allzero then
- z=z+runlength
- else
- local runreader=band(control,0x40)~=0 and readshort or readinteger
- if z>0 then
- for i=1,z do
- p=p+1
- deltas[p]=0
- end
- z=0
- end
- for i=1,runlength do
- p=p+1
- deltas[p]=runreader(f)
- end
- end
- nofpoints=nofpoints-runlength
- end
- if p>0 then
- return deltas
- else
- end
-end
-local function readdeltas(f,nofpoints)
- local deltas={}
- local p=0
while nofpoints>0 do
local control=readbyte(f)
if control then
@@ -19458,6 +19780,7 @@ function readers.hvar(f,fontdata,specification)
end
local tableoffset=gotodatatable(f,fontdata,"hvar",specification.variable)
if not tableoffset then
+ report("no hvar table, expect problems due to messy widths")
return
end
local version=readulong(f)
@@ -20842,7 +21165,7 @@ if not modules then modules={} end modules ['font-otl']={
local lower=string.lower
local type,next,tonumber,tostring,unpack=type,next,tonumber,tostring,unpack
local abs=math.abs
-local derivetable=table.derive
+local derivetable,sortedhash=table.derive,table.sortedhash
local formatters=string.formatters
local setmetatableindex=table.setmetatableindex
local allocate=utilities.storage.allocate
@@ -20858,7 +21181,7 @@ local trace_defining=false registertracker("fonts.defining",function(v) trace_d
local report_otf=logs.reporter("fonts","otf loading")
local fonts=fonts
local otf=fonts.handlers.otf
-otf.version=3.116
+otf.version=3.119
otf.cache=containers.define("fonts","otl",otf.version,true)
otf.svgcache=containers.define("fonts","svg",otf.version,true)
otf.pngcache=containers.define("fonts","png",otf.version,true)
@@ -20993,6 +21316,9 @@ function otf.load(filename,sub,instance)
if cleanup==0 then
checkmemory(used,threshold,tracememory)
end
+ if context then
+ otfreaders.condense(data)
+ end
otfreaders.pack(data)
report_otf("loading done")
report_otf("saving %a in cache",filename)
@@ -21063,7 +21389,7 @@ local function copytotfm(data,cache_id)
local properties=derivetable(data.properties)
local descriptions=derivetable(data.descriptions)
local goodies=derivetable(data.goodies)
- local characters={}
+ local characters={}
local parameters={}
local mathparameters={}
local resources=data.resources
@@ -21231,7 +21557,25 @@ local function copytotfm(data,cache_id)
properties.name=filename or fullname
properties.subfont=subfont
if not CONTEXTLMTXMODE or CONTEXTLMTXMODE==0 then
- properties.encodingbytes=2
+ properties.encodingbytes=2
+elseif CONTEXTLMTXMODE then
+ local duplicates=resources and resources.duplicates
+ if duplicates then
+ local maxindex=data.nofglyphs or metadata.nofglyphs
+ if maxindex then
+ for u,d in sortedhash(duplicates) do
+ local du=descriptions[u]
+ if du then
+ for uu in sortedhash(d) do
+ maxindex=maxindex+1
+ descriptions[uu].dupindex=du.index
+ descriptions[uu].index=maxindex
+ end
+ else
+ end
+ end
+ end
+ end
end
properties.private=properties.private or data.private or privateoffset
return {
@@ -21599,7 +21943,7 @@ local function gref(descriptions,n)
end
end
local function cref(feature,sequence)
- return formatters["feature %a, type %a, chain lookup %a"](feature,sequence.type,sequence.name)
+ return formatters["feature %a, type %a, (chain) lookup %a"](feature,sequence.type,sequence.name)
end
local function report_substitution(feature,sequence,descriptions,unicode,substitution)
if unicode==substitution then
@@ -21660,49 +22004,60 @@ end
local function makefake(tfmdata,name,present)
local private=getprivate(tfmdata)
local character={ intermediate=true,ligatures={} }
- resources.unicodes[name]=private
+ tfmdata.resources.unicodes[name]=private
tfmdata.characters[private]=character
tfmdata.descriptions[private]={ name=name }
present[name]=private
return character
end
local function make_1(present,tree,name)
- for k,v in next,tree do
- if k=="ligature" then
- present[name]=v
+ if tonumber(tree) then
+ present[name]=v
+ else
+ for k,v in next,tree do
+ if k=="ligature" then
+ present[name]=v
+ else
+ make_1(present,v,name.."_"..k)
+ end
+ end
+ end
+end
+local function make_3(present,tfmdata,characters,tree,name,preceding,unicode,done,v)
+ local character=characters[preceding]
+ if not character then
+ if trace_baseinit then
+ report_prepare("weird ligature in lookup %a, current %C, preceding %C",sequence.name,v,preceding)
+ end
+ character=makefake(tfmdata,name,present)
+ end
+ local ligatures=character.ligatures
+ if ligatures then
+ ligatures[unicode]={ char=v }
+ else
+ character.ligatures={ [unicode]={ char=v } }
+ end
+ if done then
+ local d=done[name]
+ if not d then
+ done[name]={ "dummy",v }
else
- make_1(present,v,name.."_"..k)
+ d[#d+1]=v
end
end
end
local function make_2(present,tfmdata,characters,tree,name,preceding,unicode,done)
- for k,v in next,tree do
- if k=="ligature" then
- local character=characters[preceding]
- if not character then
- if trace_baseinit then
- report_prepare("weird ligature in lookup %a, current %C, preceding %C",sequence.name,v,preceding)
- end
- character=makefake(tfmdata,name,present)
- end
- local ligatures=character.ligatures
- if ligatures then
- ligatures[unicode]={ char=v }
+ if tonumber(tree) then
+ make_3(present,tfmdata,characters,tree,name,preceding,unicode,done,tree)
+ else
+ for k,v in next,tree do
+ if k=="ligature" then
+ make_3(present,tfmdata,characters,tree,name,preceding,unicode,done,v)
else
- character.ligatures={ [unicode]={ char=v } }
- end
- if done then
- local d=done[name]
- if not d then
- done[name]={ "dummy",v }
- else
- d[#d+1]=v
- end
+ local code=present[name] or unicode
+ local name=name.."_"..k
+ make_2(present,tfmdata,characters,v,name,code,k,done)
end
- else
- local code=present[name] or unicode
- local name=name.."_"..k
- make_2(present,tfmdata,characters,v,name,code,k,done)
end
end
end
@@ -23522,9 +23877,9 @@ local f_index=formatters["I%05X"]
local f_character_y=formatters["%C"]
local f_character_n=formatters["[ %C ]"]
local check_duplicates=true
-local check_soft_hyphen=true
+local check_soft_hyphen=context
directives.register("otf.checksofthyphen",function(v)
- check_soft_hyphen=v
+ check_soft_hyphen=v
end)
local function replaced(list,index,replacement)
if type(list)=="number" then
@@ -23913,27 +24268,30 @@ local function copyduplicates(fontdata)
local resources=fontdata.resources
local duplicates=resources.duplicates
if check_soft_hyphen then
- local ds=descriptions[0xAD]
- if not ds or ds.width==0 then
- if ds then
+ local dh=descriptions[0x2D]
+ if dh then
+ local ds=descriptions[0xAD]
+ if not ds or ds.width~=dh.width then
descriptions[0xAD]=nil
- if trace_unicodes then
- report_unicodes("patching soft hyphen")
+ if ds then
+ if trace_unicodes then
+ report_unicodes("patching soft hyphen")
+ end
+ else
+ if trace_unicodes then
+ report_unicodes("adding soft hyphen")
+ end
end
- else
- if trace_unicodes then
- report_unicodes("adding soft hyphen")
+ if not duplicates then
+ duplicates={}
+ resources.duplicates=duplicates
+ end
+ local d=duplicates[0x2D]
+ if d then
+ d[0xAD]=true
+ else
+ duplicates[0x2D]={ [0xAD]=true }
end
- end
- if not duplicates then
- duplicates={}
- resources.duplicates=duplicates
- end
- local dh=duplicates[0x2D]
- if dh then
- dh[#dh+1]={ [0xAD]=true }
- else
- duplicates[0x2D]={ [0xAD]=true }
end
end
end
@@ -24199,6 +24557,7 @@ local function unifyglyphs(fontdata,usenames)
local resources=fontdata.resources
local zero=glyphs[0]
local zerocode=zero.unicode
+ local nofglyphs=#glyphs
if not zerocode then
zerocode=private
zero.unicode=zerocode
@@ -24213,7 +24572,7 @@ local function unifyglyphs(fontdata,usenames)
indices[0]=zerocode
end
if names then
- for index=1,#glyphs do
+ for index=1,nofglyphs do
local glyph=glyphs[index]
local unicode=glyph.unicode
if not unicode then
@@ -24246,7 +24605,7 @@ local function unifyglyphs(fontdata,usenames)
descriptions[unicode]=glyph
end
elseif trace_unicodes then
- for index=1,#glyphs do
+ for index=1,nofglyphs do
local glyph=glyphs[index]
local unicode=glyph.unicode
if not unicode then
@@ -24287,7 +24646,7 @@ local function unifyglyphs(fontdata,usenames)
descriptions[unicode]=glyph
end
else
- for index=1,#glyphs do
+ for index=1,nofglyphs do
local glyph=glyphs[index]
local unicode=glyph.unicode
if not unicode then
@@ -24313,7 +24672,7 @@ local function unifyglyphs(fontdata,usenames)
descriptions[unicode]=glyph
end
end
- for index=1,#glyphs do
+ for index=1,nofglyphs do
local math=glyphs[index].math
if math then
local list=math.vparts
@@ -24336,7 +24695,7 @@ local function unifyglyphs(fontdata,usenames)
end
local colorpalettes=resources.colorpalettes
if colorpalettes then
- for index=1,#glyphs do
+ for index=1,nofglyphs do
local colors=glyphs[index].colors
if colors then
for i=1,#colors do
@@ -24351,6 +24710,7 @@ local function unifyglyphs(fontdata,usenames)
fontdata.names=names
fontdata.descriptions=descriptions
fontdata.hashmethod=hashmethod
+ fontdata.nofglyphs=nofglyphs
return indices,names
end
local p_crappyname do
@@ -24423,6 +24783,10 @@ function readers.getcomponents(fontdata)
local function traverse(p,k,v)
if k=="ligature" then
collected[v]={ unpack(l) }
+ elseif tonumber(v) then
+ insert(l,k)
+ collected[v]={ unpack(l) }
+ remove(l)
else
insert(l,k)
for k,vv in next,v do
@@ -24583,7 +24947,6 @@ local function tabstr_flat(t)
end
end
local function tabstr_mixed(t)
- local s={}
local n=#t
if n==0 then
return ""
@@ -24597,6 +24960,7 @@ local function tabstr_mixed(t)
return tostring(k)
end
else
+ local s={}
for i=1,n do
local k=t[i]
if k==true then
@@ -25920,6 +26284,85 @@ function readers.compact(data)
end
end
end
+if CONTEXTLMTXMODE and CONTEXTLMTXMODE>0 then
+ local done=0
+ local function condense_1(k,v,t)
+ if type(v)=="table" then
+ local u=false
+ local l=false
+ for k,v in next,v do
+ if k=="ligature" then
+ l=v
+ if u then
+ break
+ end
+ elseif u then
+ break
+ else
+ u=true
+ end
+ end
+ if l and not u then
+ t[k]=l
+ done=done+1
+ end
+ if u then
+ for k,vv in next,v do
+ if k~="ligature" then
+ condense_1(k,vv,v)
+ end
+ end
+ end
+ end
+ end
+ local function condensesteps_1(lookup)
+ done=0
+ if lookup.type=="gsub_ligature" then
+ local steps=lookup.steps
+ if steps then
+ for i=1,#steps do
+ local step=steps[i]
+ local coverage=step.coverage
+ if coverage then
+ for k,v in next,coverage do
+ if condense_1(k,v,coverage) then
+ coverage[k]=v.ligature
+ done=done+1
+ end
+ end
+ end
+ end
+ end
+ end
+ return done
+ end
+ function readers.condense(data)
+ if not data or data.condensed then
+ return
+ else
+ data.condensed=true
+ end
+ local resources=data.resources
+ local condensed=0
+ local function condense(what)
+ local lookups=resources[what]
+ if lookups then
+ for i=1,#lookups do
+ condensed=condensed+condensesteps_1(lookups[i])
+ end
+ elseif trace_optimizations then
+ report_optimizations("no lookups in %a",what)
+ end
+ end
+ condense("sequences")
+ condense("sublookups")
+ if trace_optimizations then
+ if condensed>0 then
+ report_optimizations("%i ligatures condensed",condensed)
+ end
+ end
+ end
+end
local function mergesteps(t,k)
if k=="merged" then
local merged={}
@@ -26024,7 +26467,7 @@ function readers.expand(data)
end
end
end
- local function expandlookups(sequences)
+ local function expandlookups(sequences,whatever)
if sequences then
for i=1,#sequences do
local sequence=sequences[i]
@@ -26097,6 +26540,9 @@ function readers.expand(data)
if lookups then
for k,v in next,lookups do
local lookup=sublookups[v]
+if not lookup and whatever then
+ lookup=whatever[v]
+end
if lookup then
lookups[k]=lookup
if not subtype then
@@ -26155,7 +26601,7 @@ function readers.expand(data)
end
end
expandlookups(sequences)
- expandlookups(sublookups)
+ expandlookups(sublookups,sequences)
end
end -- closure
@@ -26698,6 +27144,7 @@ local trace_compruns=false registertracker("otf.compruns",function(v) trace_com
local trace_testruns=false registertracker("otf.testruns",function(v) trace_testruns=v end)
local forcediscretionaries=false
local forcepairadvance=false
+local repeatablemultiples=context or false
directives.register("otf.forcediscretionaries",function(v)
forcediscretionaries=v
end)
@@ -27076,15 +27523,47 @@ local function multiple_glyphs(head,start,multiple,skiphash,what,stop)
insertnodeafter(head,start,n)
start=n
end
- if what==true then
- elseif what>1 then
- local m=multiple[nofmultiples]
- for i=2,what do
- local n=copy_node(start)
- resetinjection(n)
- setchar(n,m)
- insertnodeafter(head,start,n)
- start=n
+ if what~=true and repeatablemultiples then
+ local kind=type(what)
+ local m,f,l
+ if kind=="string" then
+ local what,n=string.match(what,"^repeat(.-)[:=](%d+)$")
+ if what=="middle" then
+ m=tonumber(n)
+ elseif what=="first" then
+ f=tonumber(n)
+ elseif what=="last" then
+ l=tonumber(n)
+ end
+ elseif kind=="table" then
+ m=what.middle
+ f=what.first
+ l=what.last
+ end
+ if f or m or l then
+ if m and m>1 and nofmultiples==3 then
+ local middle=getnext(first)
+ for i=2,m do
+ local n=copynode(middle)
+ resetinjection(n)
+ insertnodeafter(head,first,n)
+ end
+ end
+ if f and f>1 then
+ for i=2,f do
+ local n=copynode(first)
+ resetinjection(n)
+ insertnodeafter(head,first,n)
+ end
+ end
+ if l and l>1 then
+ for i=2,l do
+ local n=copynode(start)
+ resetinjection(n)
+ insertnodeafter(head,start,n)
+ start=n
+ end
+ end
end
end
end
@@ -27172,7 +27651,7 @@ function handlers.gsub_ligature(head,start,dataset,sequence,ligature,rlmode,skip
while current do
local char=ischar(current,currentfont)
if char then
- local lg=ligature[char]
+ local lg=not tonumber(ligature) and ligature[char]
if lg then
stop=current
ligature=lg
@@ -27185,14 +27664,14 @@ function handlers.gsub_ligature(head,start,dataset,sequence,ligature,rlmode,skip
end
end
if stop then
- local lig=ligature.ligature
- if lig then
+ local ligature=tonumber(ligature) or ligature.ligature
+ if ligature then
if trace_ligatures then
local stopchar=getchar(stop)
- head,start=markstoligature(head,start,stop,lig)
+ head,start=markstoligature(head,start,stop,ligature)
logprocess("%s: replacing %s upto %s by ligature %s case 1",pref(dataset,sequence),gref(startchar),gref(stopchar),gref(getchar(start)))
else
- head,start=markstoligature(head,start,stop,lig)
+ head,start=markstoligature(head,start,stop,ligature)
end
return head,start,true,false
else
@@ -27207,7 +27686,7 @@ function handlers.gsub_ligature(head,start,dataset,sequence,ligature,rlmode,skip
if skiphash and skiphash[char] then
current=getnext(current)
else
- local lg=ligature[char]
+ local lg=not tonumber(ligature) and ligature[char]
if lg then
if marks[char] then
hasmarks=true
@@ -27233,20 +27712,20 @@ function handlers.gsub_ligature(head,start,dataset,sequence,ligature,rlmode,skip
local match
if replace then
local char=ischar(replace,currentfont)
- if char and ligature[char] then
+ if char and (not tonumber(ligature) and ligature[char]) then
match=true
end
end
if not match and pre then
local char=ischar(pre,currentfont)
- if char and ligature[char] then
+ if char and (not tonumber(ligature) and ligature[char]) then
match=true
end
end
if not match and not pre or not replace then
local n=getnext(discfound)
local char=ischar(n,currentfont)
- if char and ligature[char] then
+ if char and (not tonumber(ligature) and ligature[char]) then
match=true
end
end
@@ -27289,21 +27768,21 @@ function handlers.gsub_ligature(head,start,dataset,sequence,ligature,rlmode,skip
return head,start,true,true
end
end
- local lig=ligature.ligature
- if lig then
+ local ligature=tonumber(ligature) or ligature.ligature
+ if ligature then
if stop then
if trace_ligatures then
local stopchar=getchar(stop)
- head,start=toligature(head,start,stop,lig,dataset,sequence,skiphash,false,hasmarks)
- logprocess("%s: replacing %s upto %s by ligature %s case 2",pref(dataset,sequence),gref(startchar),gref(stopchar),gref(lig))
+ head,start=toligature(head,start,stop,ligature,dataset,sequence,skiphash,false,hasmarks)
+ logprocess("%s: replacing %s upto %s by ligature %s case 2",pref(dataset,sequence),gref(startchar),gref(stopchar),gref(ligature))
else
- head,start=toligature(head,start,stop,lig,dataset,sequence,skiphash,false,hasmarks)
+ head,start=toligature(head,start,stop,ligature,dataset,sequence,skiphash,false,hasmarks)
end
else
resetinjection(start)
- setchar(start,lig)
+ setchar(start,ligature)
if trace_ligatures then
- logprocess("%s: replacing %s by (no real) ligature %s case 3",pref(dataset,sequence),gref(startchar),gref(lig))
+ logprocess("%s: replacing %s by (no real) ligature %s case 3",pref(dataset,sequence),gref(startchar),gref(ligature))
end
end
return head,start,true,false
@@ -27498,7 +27977,7 @@ function handlers.gpos_mark2ligature(head,start,dataset,sequence,markanchors,rlm
end
end
elseif trace_bugs then
- onetimemessage(currentfont,basechar,"no base anchors",report_fonts)
+ onetimemessage(currentfont,basechar,"no base anchors")
end
elseif trace_bugs then
logwarning("%s: prev node is no char, case %i",pref(dataset,sequence),1)
@@ -27777,7 +28256,7 @@ function chainprocs.gsub_ligature(head,start,stop,dataset,sequence,currentlookup
if skiphash and skiphash[schar] then
current=getnext(current)
else
- local lg=ligatures[schar]
+ local lg=not tonumber(ligatures) and ligatures[schar]
if lg then
ligatures=lg
last=current
@@ -27796,7 +28275,7 @@ function chainprocs.gsub_ligature(head,start,stop,dataset,sequence,currentlookup
end
end
end
- local ligature=ligatures.ligature
+ local ligature=tonumber(ligatures) or ligatures.ligature
if ligature then
if chainindex then
stop=last
@@ -28138,7 +28617,7 @@ function chainprocs.gpos_cursive(head,start,stop,dataset,sequence,currentlookup,
end
end
elseif trace_bugs then
- onetimemessage(currentfont,startchar,"no entry anchors",report_fonts)
+ onetimemessage(currentfont,startchar,"no entry anchors")
end
break
end
@@ -28208,7 +28687,7 @@ local function chainrun(head,start,last,dataset,sequence,rlmode,skiphash,ck)
local chainproc=chainprocs[chainkind]
if chainproc then
local ok
- head,start,ok=chainproc(head,start,last,dataset,sequence,chainstep,rlmode,skiphash)
+ head,start,ok=chainproc(head,start,last,dataset,sequence,chainstep,rlmode,skiphash,1)
if ok then
done=true
end
@@ -28625,6 +29104,7 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode,s
local ck=contexts[k]
local seq=ck[3]
local f=ck[4]
+local last=start
if not startchar or not seq[f][startchar] then
goto next
end
@@ -28633,7 +29113,6 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode,s
else
local l=ck[5]
local current=start
- local last=start
if l>f then
local discfound
local n=f+1
@@ -29417,7 +29896,7 @@ local function t_run_single(start,stop,font,attr,lookupcache)
while s do
local char=ischar(s,font)
if char then
- local lg=lookupmatch[char]
+ local lg=not tonumber(lookupmatch) and lookupmatch[char]
if lg then
if sstop then
d=1
@@ -29447,7 +29926,7 @@ local function t_run_single(start,stop,font,attr,lookupcache)
break
end
end
- if l and l.ligature then
+ if l and (tonumber(l) or l.ligature) then
lastd=d
end
else
@@ -29572,7 +30051,7 @@ local function t_run_multiple(start,stop,font,attr,steps,nofsteps)
while s do
local char=ischar(s)
if char then
- local lg=lookupmatch[char]
+ local lg=not tonumber(lookupmatch) and lookupmatch[char]
if lg then
if sstop then
d=1
@@ -29602,7 +30081,7 @@ local function t_run_multiple(start,stop,font,attr,steps,nofsteps)
break
end
end
- if l and l.ligature then
+ if l and (tonumber(l) or l.ligature) then
lastd=d
end
end
@@ -30378,6 +30857,7 @@ local function validspecification(specification,name)
else
dataset={ { data=specification.data } }
specification.data=nil
+ specification.coverage=dataset
specification.dataset=dataset
end
local first=dataset[1]
@@ -30677,7 +31157,28 @@ local function addfeature(data,feature,specifications)
return coverage
end
local prepare_single=prepare_pair
- local function prepare_chain(list,featuretype,sublookups)
+ local function hassteps(lookups)
+ if lookups then
+ for i=1,#lookups do
+ local l=lookups[i]
+ if l then
+ for j=1,#l do
+ local l=l[j]
+ if l then
+ local n=l.nofsteps
+ if not n then
+ return true
+ elseif n>0 then
+ return true
+ end
+ end
+ end
+ end
+ end
+ end
+ return false
+ end
+ local function prepare_chain(list,featuretype,sublookups,nocheck)
local rules=list.rules
local coverage={}
if rules then
@@ -30713,6 +31214,7 @@ local function addfeature(data,feature,specifications)
local lookups=rule.lookups or false
local subtype=nil
if lookups and sublookups then
+ local l={}
for k,v in sortedhash(lookups) do
local t=type(v)
if t=="table" then
@@ -30722,55 +31224,63 @@ local function addfeature(data,feature,specifications)
v[i]={ vi }
end
end
+ l[k]=v
elseif t=="number" then
local lookup=sublookups[v]
if lookup then
- lookups[k]={ lookup }
+ l[k]={ lookup }
if not subtype then
subtype=lookup.type
end
elseif v==0 then
- lookups[k]={ { type="gsub_remove" } }
+ l[k]={ { type="gsub_remove",nosteps=true } }
else
- lookups[k]=false
+ l[k]=false
end
else
- lookups[k]=false
+ l[k]=false
end
end
+ if nocheck then
+ rule.lookups=l
+ end
+ lookups=l
end
if nofsequences>0 then
- local hashed={}
- for i=1,nofsequences do
- local t={}
- local s=sequence[i]
- for i=1,#s do
- local u=tounicode(s[i])
- if u then
- t[u]=true
+ if hassteps(lookups) then
+ local hashed={}
+ for i=1,nofsequences do
+ local t={}
+ local s=sequence[i]
+ for i=1,#s do
+ local u=tounicode(s[i])
+ if u then
+ t[u]=true
+ end
+ end
+ hashed[i]=t
+ end
+ sequence=hashed
+ rulesize=rulesize+1
+ rulehash[rulesize]={
+ nofrules,
+ lookuptype,
+ sequence,
+ start,
+ stop,
+ lookups,
+ replacements,
+ subtype,
+ }
+ for unic in sortedhash(sequence[start]) do
+ local cu=coverage[unic]
+ if not cu then
+ coverage[unic]=rulehash
end
end
- hashed[i]=t
- end
- sequence=hashed
- rulesize=rulesize+1
- rulehash[rulesize]={
- nofrules,
- lookuptype,
- sequence,
- start,
- stop,
- lookups,
- replacements,
- subtype,
- }
- for unic in sortedhash(sequence[start]) do
- local cu=coverage[unic]
- if not cu then
- coverage[unic]=rulehash
- end
+ sequence.n=nofsequences
+ else
end
- sequence.n=nofsequences
end
end
rulehash.n=rulesize
@@ -30857,126 +31367,148 @@ local function addfeature(data,feature,specifications)
end
local askedfeatures=specification.features or everywhere
local askedsteps=specification.steps or specification.subtables or { specification.data } or {}
- local featuretype=normalized[specification.type or "substitution"] or "substitution"
+ local featuretype=specification.type or "substitution"
+ local featureaction=false
local featureflags=specification.flags or noflags
local nocheck=specification.nocheck
+ local mapping=specification.mapping
local featureorder=specification.order or { feature }
local featurechain=(featuretype=="chainsubstitution" or featuretype=="chainposition") and 1 or 0
local nofsteps=0
local steps={}
local sublookups=specification.lookups
local category=nil
+ local steptype=nil
+ local sequence=nil
+ if fonts.handlers.otf.handlers[featuretype] then
+ featureaction=true
+ else
+ featuretype=normalized[specification.type or "substitution"] or "substitution"
+ end
checkflags(specification,resources)
- if sublookups then
- local s={}
- for i=1,#sublookups do
- local specification=sublookups[i]
- local askedsteps=specification.steps or specification.subtables or { specification.data } or {}
- local featuretype=normalized[specification.type or "substitution"] or "substitution"
- local featureflags=specification.flags or noflags
- local nofsteps=0
- local steps={}
- for i=1,#askedsteps do
- local list=askedsteps[i]
- local coverage=nil
- local format=nil
- if featuretype=="substitution" then
- coverage=prepare_substitution(list,featuretype,nocheck)
- elseif featuretype=="ligature" then
- coverage=prepare_ligature(list,featuretype,nocheck)
- elseif featuretype=="alternate" then
- coverage=prepare_alternate(list,featuretype,nocheck)
- elseif featuretype=="multiple" then
- coverage=prepare_multiple(list,featuretype,nocheck)
- elseif featuretype=="kern" or featuretype=="move" then
- format=featuretype
- coverage=prepare_kern(list,featuretype)
- elseif featuretype=="pair" then
- format="pair"
- coverage=prepare_pair(list,featuretype)
- elseif featuretype=="single" then
- format="single"
- coverage=prepare_single(list,featuretype)
- end
- if coverage and next(coverage) then
- nofsteps=nofsteps+1
- steps[nofsteps]=register(coverage,featuretype,format,feature,nofsteps,descriptions,resources)
+ for k,v in next,askedfeatures do
+ if v[1] then
+ askedfeatures[k]=tohash(v)
+ end
+ end
+ if featureflags[1] then featureflags[1]="mark" end
+ if featureflags[2] then featureflags[2]="ligature" end
+ if featureflags[3] then featureflags[3]="base" end
+ if featureaction then
+ category="gsub"
+ sequence={
+ features={ [feature]=askedfeatures },
+ flags=featureflags,
+ name=feature,
+ order=featureorder,
+ type=featuretype,
+ nofsteps=0,
+ }
+ else
+ if sublookups then
+ local s={}
+ for i=1,#sublookups do
+ local specification=sublookups[i]
+ local askedsteps=specification.steps or specification.subtables or { specification.data } or {}
+ local featuretype=normalized[specification.type or "substitution"] or "substitution"
+ local featureflags=specification.flags or noflags
+ local nofsteps=0
+ local steps={}
+ for i=1,#askedsteps do
+ local list=askedsteps[i]
+ local coverage=nil
+ local format=nil
+ if featuretype=="substitution" then
+ coverage=prepare_substitution(list,featuretype,nocheck)
+ elseif featuretype=="ligature" then
+ coverage=prepare_ligature(list,featuretype,nocheck)
+ elseif featuretype=="alternate" then
+ coverage=prepare_alternate(list,featuretype,nocheck)
+ elseif featuretype=="multiple" then
+ coverage=prepare_multiple(list,featuretype,nocheck)
+ elseif featuretype=="kern" or featuretype=="move" then
+ format=featuretype
+ coverage=prepare_kern(list,featuretype)
+ elseif featuretype=="pair" then
+ format="pair"
+ coverage=prepare_pair(list,featuretype)
+ elseif featuretype=="single" then
+ format="single"
+ coverage=prepare_single(list,featuretype)
+ end
+ if coverage and next(coverage) then
+ nofsteps=nofsteps+1
+ steps[nofsteps]=register(coverage,featuretype,format,feature,nofsteps,descriptions,resources)
+ end
end
+ checkmerge(specification)
+ checksteps(specification)
+ s[i]={
+ [stepkey]=steps,
+ nofsteps=nofsteps,
+ flags=featureflags,
+ type=types[featuretype],
+ }
+ end
+ sublookups=s
+ end
+ for i=1,#askedsteps do
+ local list=askedsteps[i]
+ local coverage=nil
+ local format=nil
+ if featuretype=="substitution" then
+ category="gsub"
+ coverage=(mapping and list) or prepare_substitution(list,featuretype,nocheck)
+ elseif featuretype=="ligature" then
+ category="gsub"
+ coverage=prepare_ligature(list,featuretype,nocheck)
+ elseif featuretype=="alternate" then
+ category="gsub"
+ coverage=prepare_alternate(list,featuretype,nocheck)
+ elseif featuretype=="multiple" then
+ category="gsub"
+ coverage=prepare_multiple(list,featuretype,nocheck)
+ elseif featuretype=="kern" or featuretype=="move" then
+ category="gpos"
+ format=featuretype
+ coverage=prepare_kern(list,featuretype)
+ elseif featuretype=="pair" then
+ category="gpos"
+ format="pair"
+ coverage=prepare_pair(list,featuretype)
+ elseif featuretype=="single" then
+ category="gpos"
+ format="single"
+ coverage=prepare_single(list,featuretype)
+ elseif featuretype=="chainsubstitution" then
+ category="gsub"
+ coverage=prepare_chain(list,featuretype,sublookups,nocheck)
+ elseif featuretype=="chainposition" then
+ category="gpos"
+ coverage=prepare_chain(list,featuretype,sublookups,nocheck)
+ else
+ report_otf("not registering feature %a, unknown category",feature)
+ return
end
- checkmerge(specification)
- checksteps(specification)
- s[i]={
+ if coverage and next(coverage) then
+ nofsteps=nofsteps+1
+ steps[nofsteps]=register(coverage,featuretype,format,feature,nofsteps,descriptions,resources)
+ end
+ end
+ if nofsteps>0 then
+ sequence={
+ chain=featurechain,
+ features={ [feature]=askedfeatures },
+ flags=featureflags,
+ name=feature,
+ order=featureorder,
[stepkey]=steps,
nofsteps=nofsteps,
- flags=featureflags,
type=types[featuretype],
}
end
- sublookups=s
- end
- for i=1,#askedsteps do
- local list=askedsteps[i]
- local coverage=nil
- local format=nil
- if featuretype=="substitution" then
- category="gsub"
- coverage=prepare_substitution(list,featuretype,nocheck)
- elseif featuretype=="ligature" then
- category="gsub"
- coverage=prepare_ligature(list,featuretype,nocheck)
- elseif featuretype=="alternate" then
- category="gsub"
- coverage=prepare_alternate(list,featuretype,nocheck)
- elseif featuretype=="multiple" then
- category="gsub"
- coverage=prepare_multiple(list,featuretype,nocheck)
- elseif featuretype=="kern" or featuretype=="move" then
- category="gpos"
- format=featuretype
- coverage=prepare_kern(list,featuretype)
- elseif featuretype=="pair" then
- category="gpos"
- format="pair"
- coverage=prepare_pair(list,featuretype)
- elseif featuretype=="single" then
- category="gpos"
- format="single"
- coverage=prepare_single(list,featuretype)
- elseif featuretype=="chainsubstitution" then
- category="gsub"
- coverage=prepare_chain(list,featuretype,sublookups)
- elseif featuretype=="chainposition" then
- category="gpos"
- coverage=prepare_chain(list,featuretype,sublookups)
- else
- report_otf("not registering feature %a, unknown category",feature)
- return
- end
- if coverage and next(coverage) then
- nofsteps=nofsteps+1
- steps[nofsteps]=register(coverage,featuretype,format,feature,nofsteps,descriptions,resources)
- end
end
- if nofsteps>0 then
- for k,v in next,askedfeatures do
- if v[1] then
- askedfeatures[k]=tohash(v)
- end
- end
- if featureflags[1] then featureflags[1]="mark" end
- if featureflags[2] then featureflags[2]="ligature" end
- if featureflags[3] then featureflags[3]="base" end
- local steptype=types[featuretype]
- local sequence={
- chain=featurechain,
- features={ [feature]=askedfeatures },
- flags=featureflags,
- name=feature,
- order=featureorder,
- [stepkey]=steps,
- nofsteps=nofsteps,
- type=steptype,
- }
+ if sequence then
checkflags(sequence,resources)
checkmerge(sequence)
checksteps(sequence)
@@ -31055,8 +31587,10 @@ if not modules then modules={} end modules ['font-osd']={
copyright="TAT Zetwerk / PRAGMA ADE / ConTeXt Development Team",
license="see context related readme files"
}
-local insert,imerge,copy,tohash=table.insert,table.imerge,table.copy,table.tohash
-local next,type=next,type
+local insert,remove,imerge,copy,tohash=table.insert,table.remove,table.imerge,table.copy,table.tohash
+local next,type,rawget=next,type,rawget
+local formatters=string.formatters
+local settings_to_hash=utilities.parsers.settings_to_hash
local report=logs.reporter("otf","devanagari")
fonts=fonts or {}
fonts.analyzers=fonts.analyzers or {}
@@ -31066,6 +31600,7 @@ local handlers=otf.handlers
local methods=fonts.analyzers.methods
local otffeatures=fonts.constructors.features.otf
local registerotffeature=otffeatures.register
+local trace_steps=false
local nuts=nodes.nuts
local getnext=nuts.getnext
local getprev=nuts.getprev
@@ -31091,7 +31626,8 @@ local flushnode=nuts.flushnode
local copyinjection=nodes.injections.copy
local unsetvalue=attributes.unsetvalue
local fontdata=fonts.hashes.identifiers
-local a_syllabe=attributes.private('syllabe')
+local a_syllabe="syllable"
+local a_reordered="reordered"
local dotted_circle=0x25CC
local c_nbsp=0x00A0
local c_zwnj=0x200C
@@ -31111,6 +31647,7 @@ replace_all_nbsp=function(head)
return replace_all_nbsp(head)
end
local processcharacters=nil
+local logprocess=nil
if context then
--removed
@@ -31123,6 +31660,8 @@ else
end
return head
end
+ logprocess=function(str)
+ end
end
local indicgroups=characters and characters.indicgroups
if not indicgroups and characters then
@@ -31232,7 +31771,7 @@ local before_subscript=indicgroups.before_subscript
local after_subscript=indicgroups.after_subscript
local before_main=indicgroups.before_main
local after_main=indicgroups.after_main
-local mark_four=table.merged (
+local mark_pre_above_below_post=table.merged (
pre_mark,
above_mark,
below_mark,
@@ -31243,6 +31782,11 @@ local mark_above_below_post=table.merged (
below_mark,
post_mark
)
+local devanagarihash=table.setmetatableindex(function(t,k)
+ local v=fontdata[k].resources.devanagari or false
+ t[k]=v
+ return v
+end)
local zw_char={
[c_zwnj]=true,
[c_zwj ]=true,
@@ -31363,7 +31907,7 @@ local function initializedevanagi(tfmdata)
local resources=tfmdata.resources
local devanagari=resources.devanagari
if not devanagari then
- report("adding devanagari features to font")
+ report("adding features to font")
local gsubfeatures=resources.features.gsub
local sequences=resources.sequences
local sharedfeatures=tfmdata.shared.features
@@ -31390,7 +31934,7 @@ local function initializedevanagi(tfmdata)
for k,v in next,pre_mark do
local locl=coverage[k]
if locl then
- if #locl>0 then
+ if #locl>0 then
for j=1,#locl do
local ck=locl[j]
local f=ck[4]
@@ -31411,6 +31955,7 @@ local function initializedevanagi(tfmdata)
end
end
end
+ else
end
if locl then
reorder_matras.steps[1].coverage[locl]=true
@@ -31423,7 +31968,7 @@ local function initializedevanagi(tfmdata)
if basic_shaping_forms[k] then
lastmatch=lastmatch+1
if s~=lastmatch then
- table.insert(sequences,lastmatch,table.remove(sequences,s))
+ insert(sequences,lastmatch,remove(sequences,s))
end
end
end
@@ -31441,9 +31986,7 @@ local function initializedevanagi(tfmdata)
local vatucache={}
local pstfcache={}
local seqsubset={}
- local rephstep={
- coverage={}
- }
+ local rephstep={ coverage={} }
local devanagari={
reph=false,
vattu=false,
@@ -31468,7 +32011,7 @@ local function initializedevanagi(tfmdata)
local has_pstf=features.pstf
if has_rphf and has_rphf[script] then
devanagari.reph=true
- elseif (has_blwf and has_blwf[script] ) or (has_vatu and has_vatu[script] ) then
+ elseif (has_blwf and has_blwf[script]) or (has_vatu and has_vatu[script]) then
devanagari.vattu=true
for i=1,nofsteps do
local step=steps[i]
@@ -31476,10 +32019,8 @@ local function initializedevanagi(tfmdata)
if coverage then
for k,v in next,coverage do
for h,w in next,halant do
- if v[h] then
- if not blwfcache[k] then
- blwfcache[k]=v
- end
+ if v[h] and not blwfcache[k] then
+ blwfcache[k]=v
end
if has_vatu and has_vatu[script] and not vatucache[k] then
vatucache[k]=v
@@ -31502,33 +32043,37 @@ local function initializedevanagi(tfmdata)
local r=coverage[k]
if r then
local found=false
- if #r>0 then
+ if #r>0 then
for j=1,#r do
local ck=r[j]
local f=ck[4]
local chainlookups=ck[6]
- if chainlookups and chainlookups[f] then
+ if chainlookups then
local chainlookup=chainlookups[f]
- for j=1,#chainlookup do
- local chainstep=chainlookup[j]
- local steps=chainstep.steps
- local nofsteps=chainstep.nofsteps
- for i=1,nofsteps do
- local step=steps[i]
- local coverage=step.coverage
- if coverage then
- local h=coverage[k]
- if h then
- for k,v in next,h do
- found=v and v.ligature
+ if chainlookup then
+ for j=1,#chainlookup do
+ local chainstep=chainlookup[j]
+ local steps=chainstep.steps
+ local nofsteps=chainstep.nofsteps
+ for i=1,nofsteps do
+ local step=steps[i]
+ local coverage=step.coverage
+ if coverage then
+ local h=coverage[k]
+ if h then
+ for k,v in next,h do
+ if v then
+ found=tonumber(v) or v.ligature
+ if found then
+ pre_base_reordering_consonants[found]=true
+ break
+ end
+ end
+ end
if found then
- pre_base_reordering_consonants[found]=true
break
end
end
- if found then
- break
- end
end
end
end
@@ -31537,10 +32082,12 @@ local function initializedevanagi(tfmdata)
end
else
for k,v in next,r do
- found=v and v.ligature
- if found then
- pre_base_reordering_consonants[found]=true
- break
+ if v then
+ found=tonumber(v) or v.ligature
+ if found then
+ pre_base_reordering_consonants[found]=true
+ break
+ end
end
end
end
@@ -31558,14 +32105,15 @@ local function initializedevanagi(tfmdata)
local step=steps[i]
local coverage=step.coverage
if coverage then
- local reph,rephbase=false,false
+ local reph=false
+ local base=false
if kind=="rphf" then
for k,v in next,ra do
local r=coverage[k]
if r then
- rephbase=k
+ base=k
local h=false
- if #r>0 then
+ if #r>0 then
for j=1,#r do
local ck=r[j]
local f=ck[4]
@@ -31585,7 +32133,7 @@ local function initializedevanagi(tfmdata)
for k,v in next,halant do
local h=r[k]
if h then
- reph=h.ligature or false
+ reph=tonumber(h) or h.ligature or false
break
end
end
@@ -31602,7 +32150,7 @@ local function initializedevanagi(tfmdata)
for k,v in next,halant do
local h=r[k]
if h then
- reph=h.ligature or false
+ reph=tonumber(h) or h.ligature or false
break
end
end
@@ -31613,7 +32161,7 @@ local function initializedevanagi(tfmdata)
end
end
end
- seqsubset[#seqsubset+1]={ kind,coverage,reph,rephbase }
+ seqsubset[#seqsubset+1]={ kind,coverage,reph,base }
end
end
end
@@ -31628,7 +32176,7 @@ local function initializedevanagi(tfmdata)
local h=coverage[k]
if h then
local found=false
- if #h>0 then
+ if #h>0 then
for j=1,#h do
local ck=h[j]
local f=ck[4]
@@ -31646,10 +32194,12 @@ local function initializedevanagi(tfmdata)
local h=coverage[k]
if h then
for k,v in next,h do
- found=v and v.ligature
- if found then
- pre_base_reordering_consonants[found]=true
- break
+ if v then
+ found=tonumber(v) or v.ligature
+ if found then
+ pre_base_reordering_consonants[found]=true
+ break
+ end
end
end
if found then
@@ -31663,7 +32213,7 @@ local function initializedevanagi(tfmdata)
end
else
for k,v in next,h do
- found=v and v.ligature
+ found=v and (tonumber(v) or v.ligature)
if found then
pre_base_reordering_consonants[found]=true
break
@@ -31689,9 +32239,6 @@ local function initializedevanagi(tfmdata)
sharedfeatures["dv03"]=true
sharedfeatures["dv04"]=true
end
- if script=="mlym" or script=="taml" then
- devanagari.left_matra_before_base=true
- end
end
end
end
@@ -31703,6 +32250,44 @@ registerotffeature {
node=initializedevanagi,
},
}
+local function initializeconjuncts(tfmdata,value)
+ if value then
+ local resources=tfmdata.resources
+ local devanagari=resources.devanagari
+ if devanagari then
+ local conjuncts="auto"
+ local movematra="auto"
+ if type(value)=="string" and value~="auto" then
+ value=settings_to_hash(value)
+ conjuncts=rawget(value,"conjuncts") or conjuncts
+ movematra=rawget(value,"movematra") or movematra
+ end
+ if conjuncts=="auto" then
+ conjuncts="mixed"
+ end
+ if movematra=="auto" and
+ script=="mlym" or
+ script=="taml" then
+ movematra="leftbeforebase"
+ else
+ movematra="default"
+ end
+ devanagari.conjuncts=conjuncts
+ devanagari.movematra=movematra
+ if trace_steps then
+ report("conjuncts %a, movematra %a",conjuncts,movematra)
+ end
+ end
+ end
+end
+registerotffeature {
+ name="indic",
+ description="control indic",
+ default="auto",
+ initializers={
+ node=initializeconjuncts,
+ },
+}
local show_syntax_errors=false
local function inject_syntax_error(head,current,char)
local signal=copy_node(current)
@@ -31748,36 +32333,40 @@ local function initialize_one(font,attr)
end
local function contextchain(contexts,n)
local char=getchar(n)
- for k=1,#contexts do
- local ck=contexts[k]
- local seq=ck[3]
- local f=ck[4]
- local l=ck[5]
- if (l-f)==1 and seq[f+1][char] then
- local ok=true
- local c=n
- for i=l+1,#seq do
- c=getnext(c)
- if not c or not seq[i][ischar(c)] then
- ok=false
- break
- end
- end
- if ok then
- c=getprev(n)
- for i=1,f-1 do
- c=getprev(c)
- if not c or not seq[f-i][ischar(c)] then
+ if not contexts.n then
+ return contexts[char]
+ else
+ for k=1,#contexts do
+ local ck=contexts[k]
+ local seq=ck[3]
+ local f=ck[4]
+ local l=ck[5]
+ if (l-f)==1 and seq[f+1][char] then
+ local ok=true
+ local c=n
+ for i=l+1,#seq do
+ c=getnext(c)
+ if not c or not seq[i][ischar(c)] then
ok=false
+ break
end
end
- end
- if ok then
- return true
+ if ok then
+ c=getprev(n)
+ for i=1,f-1 do
+ c=getprev(c)
+ if not c or not seq[f-i][ischar(c)] then
+ ok=false
+ end
+ end
+ end
+ if ok then
+ return true
+ end
end
end
+ return false
end
- return false
end
local function order_matras(c)
local cn=getnext(c)
@@ -31806,9 +32395,9 @@ local function order_matras(c)
char=getchar(cn)
end
end
+local swapped=table.swapped(states)
local function reorder_one(head,start,stop,font,attr,nbspaces)
- local reph,vattu,blwfcache,vatucache,pstfcache=initialize_one(font,attr)
- local devanagari=fontdata[font].resources.devanagari
+ local reph,vattu,blwfcache,vatucache,pstfcache=initialize_one(font,attr)
local current=start
local n=getnext(start)
local base=nil
@@ -31831,6 +32420,9 @@ local function reorder_one(head,start,stop,font,attr,nbspaces)
stop=getprev(stop)
head=remove_node(head,current)
flushnode(current)
+ if trace_steps then
+ logprocess("reorder one, remove nbsp")
+ end
return head,stop,nbspaces
else
nbspaces=nbspaces+1
@@ -31874,6 +32466,9 @@ local function reorder_one(head,start,stop,font,attr,nbspaces)
stop=current
end
end
+ if trace_steps then
+ logprocess("reorder one, handle nbsp")
+ end
end
end
end
@@ -31928,6 +32523,9 @@ local function reorder_one(head,start,stop,font,attr,nbspaces)
if lastcons==stop then
stop=n
end
+ if trace_steps then
+ logprocess("reorder one, handle halant")
+ end
end
end
n=getnext(start)
@@ -31952,6 +32550,9 @@ local function reorder_one(head,start,stop,font,attr,nbspaces)
if matra==stop then
stop=n
end
+ if trace_steps then
+ logprocess("reorder one, handle matra")
+ end
end
local current=start
while current~=stop do
@@ -31990,14 +32591,19 @@ local function reorder_one(head,start,stop,font,attr,nbspaces)
ch=getchar(n)
end
local tpm=twopart_mark[ch]
- while tpm do
- local extra=copy_node(n)
- copyinjection(extra,n)
- ch=tpm[1]
- setchar(n,ch)
- setchar(extra,tpm[2])
- head=insertnodeafter(head,current,extra)
- tpm=twopart_mark[ch]
+ if tpm then
+ while tpm do
+ local extra=copy_node(n)
+ copyinjection(extra,n)
+ ch=tpm[1]
+ setchar(n,ch)
+ setchar(extra,tpm[2])
+ head=insertnodeafter(head,current,extra)
+ tpm=twopart_mark[ch]
+ end
+ if trace_steps then
+ logprocess("reorder one, handle mark")
+ end
end
while c~=stop and dependent_vowel[ch] do
c=n
@@ -32020,9 +32626,10 @@ local function reorder_one(head,start,stop,font,attr,nbspaces)
local bp=getprev(firstcons)
local cn=getnext(current)
local last=getnext(c)
+ local done=false
while cn~=last do
if pre_mark[getchar(cn)] then
- if devanagari.left_matra_before_base then
+ if devanagarihash[font].movematra=="leftbeforebase" then
local prev,next=getboth(cn)
setlink(prev,next)
if cn==stop then
@@ -32059,6 +32666,7 @@ local function reorder_one(head,start,stop,font,attr,nbspaces)
end
cn=next
end
+ done=true
elseif current~=base and dependent_vowel[getchar(cn)] then
local prev,next=getboth(cn)
if next then
@@ -32071,6 +32679,7 @@ local function reorder_one(head,start,stop,font,attr,nbspaces)
setlink(b,cn,getnext(b))
order_matras(cn)
cn=next
+ done=true
elseif current==base and dependent_vowel[getchar(cn)] then
local cnn=getnext(cn)
order_matras(cn)
@@ -32084,9 +32693,14 @@ local function reorder_one(head,start,stop,font,attr,nbspaces)
end
allreordered=c==stop
current=getnext(c)
+ if done and trace_steps then
+ logprocess("reorder one, matra")
+ end
end
if reph or vattu then
- local current,cns=start,nil
+ local current=start
+ local cns=nil
+ local done=false
while current~=stop do
local c=current
local n=getnext(current)
@@ -32117,6 +32731,7 @@ local function reorder_one(head,start,stop,font,attr,nbspaces)
local next=getnext(b)
setlink(c,next)
setlink(b,current)
+ done=true
end
elseif cns and getnext(cns)~=current then
local cp=getprev(current)
@@ -32124,6 +32739,7 @@ local function reorder_one(head,start,stop,font,attr,nbspaces)
setlink(cp,n)
setlink(cns,current)
setlink(c,cnsn)
+ done=true
if c==stop then
stop=cp
break
@@ -32163,11 +32779,14 @@ local function reorder_one(head,start,stop,font,attr,nbspaces)
end
current=getnext(current)
end
+ if done and trace_steps then
+ logprocess("reorder one, handle reph and vata")
+ end
end
if getchar(base)==c_nbsp then
nbspaces=nbspaces-1
if base==stop then
- stop=getprev(stop)
+ stop=getprev(stop)
end
head=remove_node(head,base)
flushnode(base)
@@ -32195,6 +32814,9 @@ function handlers.devanagari_reorder_matras(head,start)
setlink(start,next)
setlink(current,start)
start=startnext
+ if trace_steps then
+ logprocess("reorder matra")
+ end
break
end
else
@@ -32223,6 +32845,9 @@ function handlers.devanagari_reorder_reph(head,start)
local char=ischar(current,startfont)
if char and getprop(current,a_syllabe)==startattr then
if halant[char] then
+ if trace_steps then
+ logprocess("reorder reph, handling halant")
+ end
local next=getnext(current)
if next then
local nextchar=ischar(next,startfont)
@@ -32253,6 +32878,9 @@ function handlers.devanagari_reorder_reph(head,start)
local char=ischar(current,startfont)
if char and getprop(current,a_syllabe)==startattr then
if consonant[char] and not getstate(current,s_pref) then
+ if trace_steps then
+ logprocess("reorder reph, handling consonant")
+ end
startnext=getnext(start)
head=remove_node(head,start)
setlink(current,start)
@@ -32277,6 +32905,9 @@ function handlers.devanagari_reorder_reph(head,start)
local char=ischar(current,startfont)
if char and getprop(current,a_syllabe)==startattr then
if getstate(current,s_pstf) then
+ if trace_steps then
+ logprocess("reorder reph, before postscript, post base")
+ end
startnext=getnext(start)
head=remove_node(head,start)
setlink(getprev(current),start)
@@ -32284,12 +32915,15 @@ function handlers.devanagari_reorder_reph(head,start)
start=startnext
startattr=getprop(start,a_syllabe)
break
- elseif not c and (vowel_modifier[char] or stress_tone_mark[char] ) then
+ elseif not c and (vowel_modifier[char] or stress_tone_mark[char]) then
c=current
end
current=getnext(current)
else
if c then
+ if trace_steps then
+ logprocess("reorder reph, before postscript")
+ end
startnext=getnext(start)
head=remove_node(head,start)
setlink(getprev(c),start)
@@ -32312,7 +32946,13 @@ function handlers.devanagari_reorder_reph(head,start)
local state=getstate(current)
if before_subscript[rephbase] and (state==s_blwf or state==s_pstf) then
c=current
+ if trace_steps then
+ logprocess("reorder reph, before subscript")
+ end
elseif after_subscript[rephbase] and (state==s_pstf) then
+ if trace_steps then
+ logprocess("reorder reph, after subscript")
+ end
c=current
end
current=getnext(current)
@@ -32343,6 +32983,9 @@ function handlers.devanagari_reorder_reph(head,start)
end
end
if start~=current then
+ if trace_steps then
+ logprocess("reorder reph, to end")
+ end
startnext=getnext(start)
head=remove_node(head,start)
setlink(start,getnext(current))
@@ -32352,9 +32995,8 @@ function handlers.devanagari_reorder_reph(head,start)
end
return head,start,true
end
-local reordered_pre_base_reordering_consonants={}
function handlers.devanagari_reorder_pre_base_reordering_consonants(head,start)
- if reordered_pre_base_reordering_consonants[start] then
+ if getprop(start,a_reordered) then
return head,start,true
end
local current=start
@@ -32365,6 +33007,9 @@ function handlers.devanagari_reorder_pre_base_reordering_consonants(head,start)
local next=getnext(current)
if char and getprop(current,a_syllabe)==startattr then
if halant[char] then
+ if trace_steps then
+ logprocess("reorder pre base consonants, handle halant")
+ end
if next then
local char=ischar(next,startfont)
if char and zw_char[char] and getprop(next,a_syllabe)==startattr then
@@ -32376,7 +33021,7 @@ function handlers.devanagari_reorder_pre_base_reordering_consonants(head,start)
head=remove_node(head,start)
setlink(start,next)
setlink(current,start)
- reordered_pre_base_reordering_consonants[start]=true
+ setprop(start,"reordered",true)
start=startnext
return head,start,true
end
@@ -32390,6 +33035,9 @@ function handlers.devanagari_reorder_pre_base_reordering_consonants(head,start)
while current and getprop(current,a_syllabe)==startattr do
local char=ischar(current)
if (not dependent_vowel[char] and (not getstate(current) or getstate(current,s_init))) then
+ if trace_steps then
+ logprocess("reorder pre base consonants, handle vowel or initial")
+ end
startnext=getnext(start)
head=remove_node(head,start)
if current==head then
@@ -32399,7 +33047,7 @@ function handlers.devanagari_reorder_pre_base_reordering_consonants(head,start)
setlink(getprev(current),start)
setlink(start,current)
end
- reordered_pre_base_reordering_consonants[start]=true
+ setprop(start,"reordered",true)
start=startnext
break
end
@@ -32431,6 +33079,9 @@ function handlers.devanagari_remove_joiners(head,start,kind,lookupname,replaceme
head=stop
end
flushlist(start)
+ if trace_steps then
+ logprocess("remove joiners")
+ end
return head,stop,true
end
local function initialize_two(font,attr)
@@ -32447,15 +33098,17 @@ local function reorder_two(head,start,stop,font,attr,nbspaces)
local basepos=nil
local subpos=nil
local postpos=nil
- reorderreph.coverage={}
- rephbase[font]={}
+ reorderreph.coverage={}
+ rephbase[font]={}
for i=1,#seqsubset do
local subset=seqsubset[i]
local kind=subset[1]
local lookupcache=subset[2]
if kind=="rphf" then
- reorderreph.coverage[subset[3]]=true
- rephbase[font][subset[3]]=subset[4]
+ local reph=subset[3]
+ local base=subset[4]
+ reorderreph.coverage[reph]=true
+ rephbase[font][reph]=base
local current=start
local last=getnext(stop)
while current~=last do
@@ -32464,15 +33117,15 @@ local function reorder_two(head,start,stop,font,attr,nbspaces)
local found=lookupcache[c]
if found then
local next=getnext(current)
- if found[getchar(next)] or contextchain(found,next) then
+ if contextchain(found,next) then
local afternext=next~=stop and getnext(next)
if afternext and zw_char[getchar(afternext)] then
current=afternext
elseif current==start then
setstate(current,s_rphf)
- current=next
+ current=next
else
- current=next
+ current=next
end
end
end
@@ -32488,8 +33141,8 @@ local function reorder_two(head,start,stop,font,attr,nbspaces)
local found=lookupcache[c]
if found then
local next=getnext(current)
- if found[getchar(next)] or contextchain(found,next) then
- if (not getstate(current) and not getstate(next)) then
+ if contextchain(found,next) then
+ if not getstate(current) and not getstate(next) then
setstate(current,s_pref)
setstate(next,s_pref)
current=next
@@ -32508,10 +33161,10 @@ local function reorder_two(head,start,stop,font,attr,nbspaces)
local found=lookupcache[c]
if found then
local next=getnext(current)
- if found[getchar(next)] or contextchain(found,next) then
+ if contextchain(found,next) then
if next~=stop and getchar(getnext(next))==c_zwnj then
current=next
- elseif (not getstate(current)) then
+ elseif not getstate(current) then
setstate(current,s_half)
if not halfpos then
halfpos=current
@@ -32532,8 +33185,8 @@ local function reorder_two(head,start,stop,font,attr,nbspaces)
local found=lookupcache[c]
if found then
local next=getnext(current)
- if found[getchar(next)] or contextchain(found,next) then
- if (not getstate(current) and not getstate(next)) then
+ if contextchain(found,next) then
+ if not getstate(current) and not getstate(next) then
setstate(current,s_blwf)
setstate(next,s_blwf)
current=next
@@ -32553,8 +33206,8 @@ local function reorder_two(head,start,stop,font,attr,nbspaces)
local found=lookupcache[c]
if found then
local next=getnext(current)
- if found[getchar(next)] or contextchain(found,next) then
- if (not getstate(current) and not getstate(next)) then
+ if contextchain(found,next) then
+ if not getstate(current) and not getstate(next) then
setstate(current,s_pstf)
setstate(next,s_pstf)
current=next
@@ -32576,6 +33229,9 @@ local function reorder_two(head,start,stop,font,attr,nbspaces)
stop=getprev(stop)
head=remove_node(head,current)
flushnode(current)
+ if trace_steps then
+ logprocess("reorder two, remove nbsp")
+ end
return head,stop,nbspaces
else
nbspaces=nbspaces+1
@@ -32616,6 +33272,9 @@ local function reorder_two(head,start,stop,font,attr,nbspaces)
end
end
end
+ if trace_steps then
+ logprocess("reorder two, handle nbsp")
+ end
end
else
local last=getnext(stop)
@@ -32645,7 +33304,7 @@ local function reorder_two(head,start,stop,font,attr,nbspaces)
return head,stop,nbspaces
else
if getstate(base) then
- setstate(base,unsetvalue)
+ setstate(base,unsetvalue)
end
basepos=base
end
@@ -32666,14 +33325,19 @@ local function reorder_two(head,start,stop,font,attr,nbspaces)
local target=nil
local cn=getnext(current)
local tpm=twopart_mark[char]
- while tpm do
- local extra=copy_node(current)
- copyinjection(extra,current)
- char=tpm[1]
- setchar(current,char)
- setchar(extra,tpm[2])
- head=insertnodeafter(head,current,extra)
- tpm=twopart_mark[char]
+ if tpm then
+ while tpm do
+ local extra=copy_node(current)
+ copyinjection(extra,current)
+ char=tpm[1]
+ setchar(current,char)
+ setchar(extra,tpm[2])
+ head=insertnodeafter(head,current,extra)
+ tpm=twopart_mark[char]
+ end
+ if tpm and trace_steps then
+ logprocess("reorder two, handle matra")
+ end
end
if not moved[current] and dependent_vowel[char] then
if pre_mark[char] then
@@ -32714,6 +33378,9 @@ local function reorder_two(head,start,stop,font,attr,nbspaces)
end
setlink(getprev(pos),current)
setlink(current,pos)
+ if trace_steps then
+ logprocess("reorder two, handle pre mark")
+ end
elseif above_mark[char] then
target=basepos
if subpos==basepos then
@@ -32753,6 +33420,9 @@ local function reorder_two(head,start,stop,font,attr,nbspaces)
end
setlink(current,getnext(target))
setlink(target,current)
+ if trace_steps then
+ logprocess("reorder two, handle mark")
+ end
end
end
end
@@ -32780,6 +33450,9 @@ local function reorder_two(head,start,stop,font,attr,nbspaces)
stop=prev
end
cn=next
+ if trace_steps then
+ logprocess("reorder two, handle halant and ra")
+ end
end
end
end
@@ -32812,6 +33485,9 @@ local function reorder_two(head,start,stop,font,attr,nbspaces)
setprev(nextnextnext,current)
end
setlink(nextnext,c)
+ if trace_steps then
+ logprocess("reorder two, handle nukta")
+ end
end
if stop==current then break end
current=getnext(current)
@@ -32823,6 +33499,9 @@ local function reorder_two(head,start,stop,font,attr,nbspaces)
nbspaces=nbspaces-1
head=remove_node(head,base)
flushnode(base)
+ if trace_steps then
+ logprocess("reorder two, handle nbsp")
+ end
end
return head,stop,nbspaces
end
@@ -32910,21 +33589,42 @@ local function analyze_next_chars_one(c,font,variant)
local already_below_mark
local already_post_mark
while dependent_vowel[v] do
- local vowels=twopart_mark[v] or { v }
- for k,v in next,vowels do
- if pre_mark[v] and not already_pre_mark then
- already_pre_mark=true
- elseif above_mark[v] and not already_above_mark then
- already_above_mark=true
- elseif below_mark[v] and not already_below_mark then
- already_below_mark=true
- elseif post_mark[v] and not already_post_mark then
- already_post_mark=true
- else
- return c
- end
- end
- c=getnext(c)
+ local vowels=twopart_mark[v]
+ if vowels then
+ for k=1,#vowels do
+ local v=vowels[k]
+ if pre_mark[v] and not already_pre_mark then
+ already_pre_mark=true
+ elseif above_mark[v] and not already_above_mark then
+ already_above_mark=true
+ elseif below_mark[v] and not already_below_mark then
+ already_below_mark=true
+ elseif post_mark[v] and not already_post_mark then
+ already_post_mark=true
+ elseif devanagarihash[font].conjuncts=="continue" then
+ else
+ return c
+ end
+ end
+ else
+ if pre_mark[v] and not already_pre_mark then
+ already_pre_mark=true
+ elseif post_mark[v] and not already_post_mark then
+ if devanagarihash[font].conjuncts=="mixed" then
+ return c
+ else
+ already_post_mark=true
+ end
+ elseif below_mark[v] and not already_below_mark then
+ already_below_mark=true
+ elseif above_mark[v] and not already_above_mark then
+ already_above_mark=true
+ elseif devanagarihash[font].conjuncts=="continue" then
+ else
+ return c
+ end
+ end
+ c=n
n=getnext(c)
if not n then
return c
@@ -32935,7 +33635,7 @@ local function analyze_next_chars_one(c,font,variant)
end
end
if nukta[v] then
- c=getnext(c)
+ c=n
n=getnext(c)
if not n then
return c
@@ -32946,7 +33646,7 @@ local function analyze_next_chars_one(c,font,variant)
end
end
if halant[v] then
- c=getnext(c)
+ c=n
n=getnext(c)
if not n then
return c
@@ -32957,7 +33657,7 @@ local function analyze_next_chars_one(c,font,variant)
end
end
if vowel_modifier[v] then
- c=getnext(c)
+ c=n
n=getnext(c)
if not n then
return c
@@ -32968,7 +33668,7 @@ local function analyze_next_chars_one(c,font,variant)
end
end
if stress_tone_mark[v] then
- c=getnext(c)
+ c=n
n=getnext(c)
if not n then
return c
@@ -32985,11 +33685,12 @@ local function analyze_next_chars_one(c,font,variant)
end
end
local function analyze_next_chars_two(c,font)
- local n=getnext(c)
+ local n,v
+ n=getnext(c)
if not n then
return c
end
- local v=ischar(n,font)
+ v=ischar(n,font)
if v and nukta[v] then
c=n
end
@@ -33048,11 +33749,11 @@ local function analyze_next_chars_two(c,font)
if not c then
return
end
- local n=getnext(c)
+ n=getnext(c)
if not n then
return c
end
- local v=ischar(n,font)
+ v=ischar(n,font)
if not v then
return c
end
@@ -33092,22 +33793,43 @@ local function analyze_next_chars_two(c,font)
local already_pre_mark
local already_above_mark
local already_below_mark
- local already_post_mark
- while dependent_vowel[v] do
- local vowels=twopart_mark[v] or { v }
- for k,v in next,vowels do
- if pre_mark[v] and not already_pre_mark then
- already_pre_mark=true
- elseif above_mark[v] and not already_above_mark then
- already_above_mark=true
- elseif below_mark[v] and not already_below_mark then
- already_below_mark=true
- elseif post_mark[v] and not already_post_mark then
- already_post_mark=true
- else
- return c
- end
- end
+ local already_post_mark
+ while dependent_vowel[v] do
+ local vowels=twopart_mark[v]
+ if vowels then
+ for k=1,#vowels do
+ local v=vowels[k]
+ if pre_mark[v] and not already_pre_mark then
+ already_pre_mark=true
+ elseif above_mark[v] and not already_above_mark then
+ already_above_mark=true
+ elseif below_mark[v] and not already_below_mark then
+ already_below_mark=true
+ elseif post_mark[v] and not already_post_mark then
+ already_post_mark=true
+ elseif devanagarihash[font].conjuncts=="continue" then
+ else
+ return c
+ end
+ end
+ else
+ if pre_mark[v] and not already_pre_mark then
+ already_pre_mark=true
+ elseif post_mark[v] and not already_post_mark then
+ if devanagarihash[font].conjuncts=="mixed" then
+ return c
+ else
+ already_post_mark=true
+ end
+ elseif below_mark[v] and not already_below_mark then
+ already_below_mark=true
+ elseif above_mark[v] and not already_above_mark then
+ already_above_mark=true
+ elseif devanagarihash[font].conjuncts=="continue" then
+ else
+ return c
+ end
+ end
c=n
n=getnext(c)
if not n then
@@ -33342,7 +34064,7 @@ local function method_one(head,font,attr)
end
else
if show_syntax_errors then
- local mark=mark_four[char]
+ local mark=mark_pre_above_below_post[char]
if mark then
head,current=inject_syntax_error(head,current,char)
end
@@ -33363,15 +34085,15 @@ local function method_one(head,font,attr)
while current do
local char=ischar(current,font)
if char then
- if n==0 and not getstate(current) then
- setstate(current,s_init)
- end
- n=n+1
- else
- n=0
- end
- current=getnext(current)
- end
+ if n==0 and not getstate(current) then
+ setstate(current,s_init)
+ end
+ n=n+1
+ else
+ n=0
+ end
+ current=getnext(current)
+ end
return head,done
end
local function method_two(head,font,attr)
@@ -33441,7 +34163,7 @@ local function method_two(head,font,attr)
if not syllableend and show_syntax_errors then
local char=ischar(current,font)
if char and not getstate(current) then
- local mark=mark_four[char]
+ local mark=mark_pre_above_below_post[char]
if mark then
head,current=inject_syntax_error(head,current,char)
end
@@ -33458,15 +34180,15 @@ local function method_two(head,font,attr)
while current do
local char=ischar(current,font)
if char then
- if n==0 and not getstate(current) then
- setstate(current,s_init)
- end
- n=n+1
- else
- n=0
- end
- current=getnext(current)
- end
+ if n==0 and not getstate(current) then
+ setstate(current,s_init)
+ end
+ n=n+1
+ else
+ n=0
+ end
+ current=getnext(current)
+ end
return head,done
end
for i=1,nofscripts do
@@ -36161,7 +36883,7 @@ local afm=fonts.handlers.afm
local pfb=fonts.handlers.pfb
local hashes=fonts.hashes
local identifiers=hashes.identifiers
-local version=0.010
+local version=otf.version or 0.011
local shapescache=containers.define("fonts","shapes",version,true)
local streamscache=containers.define("fonts","streams",version,true)
local compact_streams=false
@@ -36469,7 +37191,7 @@ local function getstreamhash(fontid)
local fontdata=identifiers[fontid]
if fontdata then
local properties=fontdata.properties
- return makehash(properties.filename,properties.subfont,properties.instance)
+ return makehash(properties.filename,properties.subfont,properties.instance),fontdata
end
end
local function loadstreamdata(fontdata)